[clang] [llvm] [clang][LLVM Demangler] Add an assertion that validates that all mang… (PR #111391)

Viktoriia Bakalova via cfe-commits cfe-commits at lists.llvm.org
Mon Oct 7 08:17:12 PDT 2024


https://github.com/VitaNuo updated https://github.com/llvm/llvm-project/pull/111391

>From 542558c9dc6e8b8d7e5f68b6f0fa74098b56fd3a Mon Sep 17 00:00:00 2001
From: Viktoriia Bakalova <bakalova at google.com>
Date: Mon, 7 Oct 2024 15:10:28 +0000
Subject: [PATCH] [clang][LLVM Demangler] Add an assertion that validates that
 all mangled names produced by `clang` can be demangled by LLVM demangler.

Introduce the above assertion behind the `-fno-demangling-failures` flag to prevent unintended breakages.
---
 clang/include/clang/Basic/CodeGenOptions.def |  3 +++
 clang/include/clang/Driver/Options.td        |  4 ++++
 clang/lib/CodeGen/CodeGenModule.cpp          |  8 ++++++++
 clang/test/CodeGenCXX/assert-demangle.cpp    | 14 ++++++++++++++
 llvm/include/llvm/Demangle/Demangle.h        |  7 +++++++
 llvm/lib/Demangle/Demangle.cpp               | 10 ++++++++++
 6 files changed, 46 insertions(+)
 create mode 100644 clang/test/CodeGenCXX/assert-demangle.cpp

diff --git a/clang/include/clang/Basic/CodeGenOptions.def b/clang/include/clang/Basic/CodeGenOptions.def
index eac831278ee20d..d3e150fe53f804 100644
--- a/clang/include/clang/Basic/CodeGenOptions.def
+++ b/clang/include/clang/Basic/CodeGenOptions.def
@@ -462,6 +462,9 @@ ENUM_CODEGENOPT(ZeroCallUsedRegs, llvm::ZeroCallUsedRegs::ZeroCallUsedRegsKind,
 /// non-deleting destructors. (No effect on Microsoft ABI.)
 CODEGENOPT(CtorDtorReturnThis, 1, 0)
 
+/// Whether to validate if a produced mangled name can be demangled with LLVM demangler.
+CODEGENOPT(NoDemanglingFailures, 1, 0)
+
 /// FIXME: Make DebugOptions its own top-level .def file.
 #include "DebugOptions.def"
 
diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td
index 607ff47a857b8f..a6a8cfe21676c0 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -1967,6 +1967,10 @@ def fclang_abi_compat_EQ : Joined<["-"], "fclang-abi-compat=">, Group<f_clang_Gr
   Visibility<[ClangOption, CC1Option]>,
   MetaVarName<"<version>">, Values<"<major>.<minor>,latest">,
   HelpText<"Attempt to match the ABI of Clang <version>">;
+def fno_demangling_failures: Flag<["-"], "fno-demangling-failures">, Group<f_clang_Group>,
+  Visibility<[ClangOption, CC1Option]>,
+  HelpText<"Assert that clang can demangle all the mangled names it generates">,
+  MarshallingInfoFlag<CodeGenOpts<"NoDemanglingFailures">>;
 def fclasspath_EQ : Joined<["-"], "fclasspath=">, Group<f_Group>;
 def fcolor_diagnostics : Flag<["-"], "fcolor-diagnostics">, Group<f_Group>,
 
diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp
index 25c1c496a4f27f..94b04df652d4b9 100644
--- a/clang/lib/CodeGen/CodeGenModule.cpp
+++ b/clang/lib/CodeGen/CodeGenModule.cpp
@@ -48,12 +48,14 @@
 #include "clang/Basic/Version.h"
 #include "clang/CodeGen/BackendUtil.h"
 #include "clang/CodeGen/ConstantInitBuilder.h"
+#include "clang/Driver/Driver.h"
 #include "clang/Frontend/FrontendDiagnostic.h"
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/ADT/StringSwitch.h"
 #include "llvm/Analysis/TargetLibraryInfo.h"
 #include "llvm/BinaryFormat/ELF.h"
+#include "llvm/Demangle/Demangle.h"
 #include "llvm/Frontend/OpenMP/OMPIRBuilder.h"
 #include "llvm/IR/AttributeMask.h"
 #include "llvm/IR/CallingConv.h"
@@ -75,6 +77,7 @@
 #include "llvm/TargetParser/Triple.h"
 #include "llvm/TargetParser/X86TargetParser.h"
 #include "llvm/Transforms/Utils/BuildLibCalls.h"
+#include <cassert>
 #include <optional>
 
 using namespace clang;
@@ -2044,6 +2047,11 @@ StringRef CodeGenModule::getMangledName(GlobalDecl GD) {
                  GD.getWithKernelReferenceKind(KernelReferenceKind::Kernel),
                  ND));
 
+  if (getCodeGenOpts().NoDemanglingFailures)
+    assert((!llvm::isMangledName(MangledName) ||
+            llvm::demangle(MangledName) != MangledName) &&
+           "clang must demangle a mangled name it generates!");
+
   auto Result = Manglings.insert(std::make_pair(MangledName, GD));
   return MangledDeclNames[CanonicalGD] = Result.first->first();
 }
diff --git a/clang/test/CodeGenCXX/assert-demangle.cpp b/clang/test/CodeGenCXX/assert-demangle.cpp
new file mode 100644
index 00000000000000..86a7686f72d929
--- /dev/null
+++ b/clang/test/CodeGenCXX/assert-demangle.cpp
@@ -0,0 +1,14 @@
+// RUN: %clang_cc1 -emit-llvm -fno-demangling-failures -triple %itanium_abi_triple -o - %s | FileCheck %s
+
+// CHECK: @_ZN6foobar3barEv
+// CHECK: @_ZN6foobar1A3fooEi
+namespace foobar {
+struct A {
+  void foo (int) {
+  }
+};
+
+void bar() {
+  A().foo(0);
+}
+} // namespace foobar
diff --git a/llvm/include/llvm/Demangle/Demangle.h b/llvm/include/llvm/Demangle/Demangle.h
index fe129603c0785d..910f0410d62db3 100644
--- a/llvm/include/llvm/Demangle/Demangle.h
+++ b/llvm/include/llvm/Demangle/Demangle.h
@@ -67,6 +67,13 @@ char *dlangDemangle(std::string_view MangledName);
 /// demangling occurred.
 std::string demangle(std::string_view MangledName);
 
+/// Determines if the argument string is a valid mangled name known to the
+/// demangler.
+/// \param Name - reference to a string that is potentially a mangled name.
+/// \returns - true if the argument represents a valid mangled name, false
+/// otherwise.
+bool isMangledName(std::string_view Name);
+
 bool nonMicrosoftDemangle(std::string_view MangledName, std::string &Result,
                           bool CanHaveLeadingDot = true,
                           bool ParseParams = true);
diff --git a/llvm/lib/Demangle/Demangle.cpp b/llvm/lib/Demangle/Demangle.cpp
index f0f7eacac98e64..6b40cbb56cf28d 100644
--- a/llvm/lib/Demangle/Demangle.cpp
+++ b/llvm/lib/Demangle/Demangle.cpp
@@ -47,6 +47,16 @@ static bool isRustEncoding(std::string_view S) { return starts_with(S, "_R"); }
 
 static bool isDLangEncoding(std::string_view S) { return starts_with(S, "_D"); }
 
+static bool isMicrosoftEncoding(std::string_view S) {
+  return starts_with(S, '?');
+}
+
+bool llvm::isMangledName(std::string_view Name) {
+  return starts_with(Name, '.') || isItaniumEncoding(Name) ||
+         isRustEncoding(Name) || isDLangEncoding(Name) ||
+         isMicrosoftEncoding(Name);
+}
+
 bool llvm::nonMicrosoftDemangle(std::string_view MangledName,
                                 std::string &Result, bool CanHaveLeadingDot,
                                 bool ParseParams) {



More information about the cfe-commits mailing list