diff --git a/clang/include/clang/Basic/CodeGenOptions.def b/clang/include/clang/Basic/CodeGenOptions.def index eac831278ee20..ad5e125c5b8bb 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 issue a diagnostic if a produced mangled name can not be demangled with the LLVM demangler. +CODEGENOPT(DiagnosticsDemanglerFailures, 1, 0) + /// FIXME: Make DebugOptions its own top-level .def file. #include "DebugOptions.def" diff --git a/clang/include/clang/Basic/DiagnosticFrontendKinds.td b/clang/include/clang/Basic/DiagnosticFrontendKinds.td index a6b17ccb6799d..b785aa0ee0b5a 100644 --- a/clang/include/clang/Basic/DiagnosticFrontendKinds.td +++ b/clang/include/clang/Basic/DiagnosticFrontendKinds.td @@ -384,4 +384,8 @@ def warn_hlsl_langstd_minimal : Warning<"support for HLSL language version %0 is incomplete, " "recommend using %1 instead">, InGroup; + +def warn_name_cannot_be_demangled : Warning< + "cannot demangle the name '%0'">, + InGroup; } diff --git a/clang/include/clang/Basic/DiagnosticGroups.td b/clang/include/clang/Basic/DiagnosticGroups.td index 7d81bdf827ea0..993ec11160544 100644 --- a/clang/include/clang/Basic/DiagnosticGroups.td +++ b/clang/include/clang/Basic/DiagnosticGroups.td @@ -1582,3 +1582,6 @@ def ExtractAPIMisuse : DiagGroup<"extractapi-misuse">; // Warnings about using the non-standard extension having an explicit specialization // with a storage class specifier. def ExplicitSpecializationStorageClass : DiagGroup<"explicit-specialization-storage-class">; + +// Diagnostics related to the LLVM demangler. +def Demangler: DiagGroup<"demangler">; diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index 607ff47a857b8..d6320d82d94cd 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, MetaVarName<"">, Values<".,latest">, HelpText<"Attempt to match the ABI of Clang ">; +def fdiagnostics_demangler_failures: Flag<["-"], "fdiagnostics-demangler-failures">, Group, + Visibility<[ClangOption, CC1Option]>, + HelpText<"Produce a diagnostic if clang cannot demangle a mangled name it generates">, + MarshallingInfoFlag>; def fclasspath_EQ : Joined<["-"], "fclasspath=">, Group; def fcolor_diagnostics : Flag<["-"], "fcolor-diagnostics">, Group, diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index 25c1c496a4f27..3d63564c7e8cc 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -54,6 +54,7 @@ #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" @@ -2044,6 +2045,14 @@ StringRef CodeGenModule::getMangledName(GlobalDecl GD) { GD.getWithKernelReferenceKind(KernelReferenceKind::Kernel), ND)); + if (getContext().getLangOpts().getClangABICompat() > + LangOptions::ClangABI::Ver19) { + if (llvm::isMangledName(MangledName) && + llvm::demangle(MangledName) == MangledName) + Diags.Report(ND->getLocation(), diag::warn_name_cannot_be_demangled) + << MangledName; + } + auto Result = Manglings.insert(std::make_pair(MangledName, GD)); return MangledDeclNames[CanonicalGD] = Result.first->first(); } diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index b9987288d82d1..cb648a2baa29f 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -4444,6 +4444,9 @@ static void RenderDiagnosticsOptions(const Driver &D, const ArgList &Args, Args.addOptOutFlag(CmdArgs, options::OPT_fspell_checking, options::OPT_fno_spell_checking); + + if (Args.hasArg(options::OPT_fdiagnostics_demangler_failures)) + CmdArgs.push_back("-fdiagnostics-demangler-failures"); } DwarfFissionKind tools::getDebugFissionKind(const Driver &D, diff --git a/clang/test/CodeGenCXX/warn-demangling-failure.cpp b/clang/test/CodeGenCXX/warn-demangling-failure.cpp new file mode 100644 index 0000000000000..8f75d93a0a440 --- /dev/null +++ b/clang/test/CodeGenCXX/warn-demangling-failure.cpp @@ -0,0 +1,13 @@ +// RUN: %clang_cc1 -emit-llvm -fdemangling-failures -triple %itanium_abi_triple -o - %s | FileCheck %s +template void parallel_loop(F &&f) { f(0); } + +//CHECK-LABEL: @main +int main() { + int x; + parallel_loop([&](auto y) { // expected-warning {{cannot demangle the name '_ZZ4mainENK3$_0clIiEEDaT_'}} +#pragma clang __debug captured + { + x = y; + }; + }); +} diff --git a/llvm/include/llvm/Demangle/Demangle.h b/llvm/include/llvm/Demangle/Demangle.h index fe129603c0785..910f0410d62db 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 f0f7eacac98e6..a2b97b72b3fc1 100644 --- a/llvm/lib/Demangle/Demangle.cpp +++ b/llvm/lib/Demangle/Demangle.cpp @@ -47,6 +47,15 @@ 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 isItaniumEncoding(Name) || isRustEncoding(Name) || + isDLangEncoding(Name) || isMicrosoftEncoding(Name); +} + bool llvm::nonMicrosoftDemangle(std::string_view MangledName, std::string &Result, bool CanHaveLeadingDot, bool ParseParams) {