[clang] 64cc3fa - [Clang] Fix the mangling of lambdas (#89204)

via cfe-commits cfe-commits at lists.llvm.org
Fri Apr 19 08:44:16 PDT 2024


Author: cor3ntin
Date: 2024-04-19T17:44:12+02:00
New Revision: 64cc3fad53c8313ad2fb3f2ba2fd44f280e5babf

URL: https://github.com/llvm/llvm-project/commit/64cc3fad53c8313ad2fb3f2ba2fd44f280e5babf
DIFF: https://github.com/llvm/llvm-project/commit/64cc3fad53c8313ad2fb3f2ba2fd44f280e5babf.diff

LOG: [Clang] Fix the mangling of lambdas (#89204)

Lambdas used in the initializer of a local class were not mangling the
name of the member.

Fixes #88906

Added: 
    clang/test/CodeGenCXX/mangle-lambdas-gh88906.cpp

Modified: 
    clang/docs/ReleaseNotes.rst
    clang/include/clang/Basic/LangOptions.h
    clang/lib/AST/ItaniumMangle.cpp
    clang/lib/Frontend/CompilerInvocation.cpp

Removed: 
    


################################################################################
diff  --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index e0a6d2f0fc7cf2..aea8fda35bb29c 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -549,6 +549,7 @@ Bug Fixes to C++ Support
 - Fix a crash in requires expression with templated base class member function. Fixes (#GH84020).
 - Fix a crash caused by defined struct in a type alias template when the structure
   has fields with dependent type. Fixes (#GH75221).
+- Fix the Itanium mangling of lambdas defined in a member of a local class (#GH88906)
 
 Bug Fixes to AST Handling
 ^^^^^^^^^^^^^^^^^^^^^^^^^

diff  --git a/clang/include/clang/Basic/LangOptions.h b/clang/include/clang/Basic/LangOptions.h
index 24b109e32cdd3e..75562284ec7de0 100644
--- a/clang/include/clang/Basic/LangOptions.h
+++ b/clang/include/clang/Basic/LangOptions.h
@@ -224,6 +224,11 @@ class LangOptionsBase {
     ///   - the parameter list of a template template parameter
     Ver17,
 
+    /// Attempt to be ABI-compatible with code generated by Clang 18.0.x.
+    /// This causes clang to revert some fixes to the mangling of lambdas
+    /// in the initializers of members of local classes.
+    Ver18,
+
     /// Conform to the underlying platform's C and C++ ABIs as closely
     /// as we can.
     Latest

diff  --git a/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp
index c3b98d2d2149cb..106c69dd5beed7 100644
--- a/clang/lib/AST/ItaniumMangle.cpp
+++ b/clang/lib/AST/ItaniumMangle.cpp
@@ -1062,26 +1062,23 @@ void CXXNameMangler::mangleNameWithAbiTags(GlobalDecl GD,
   //         ::= <local-name>
   //
   const DeclContext *DC = Context.getEffectiveDeclContext(ND);
+  bool IsLambda = isLambda(ND);
 
   // If this is an extern variable declared locally, the relevant DeclContext
   // is that of the containing namespace, or the translation unit.
   // FIXME: This is a hack; extern variables declared locally should have
   // a proper semantic declaration context!
-  if (isLocalContainerContext(DC) && ND->hasLinkage() && !isLambda(ND))
+  if (isLocalContainerContext(DC) && ND->hasLinkage() && !IsLambda)
     while (!DC->isNamespace() && !DC->isTranslationUnit())
       DC = Context.getEffectiveParentContext(DC);
-  else if (GetLocalClassDecl(ND)) {
+  else if (GetLocalClassDecl(ND) &&
+           (!IsLambda || isCompatibleWith(LangOptions::ClangABI::Ver18))) {
     mangleLocalName(GD, AdditionalAbiTags);
     return;
   }
 
   assert(!isa<LinkageSpecDecl>(DC) && "context cannot be LinkageSpecDecl");
 
-  if (isLocalContainerContext(DC)) {
-    mangleLocalName(GD, AdditionalAbiTags);
-    return;
-  }
-
   // Closures can require a nested-name mangling even if they're semantically
   // in the global namespace.
   if (const NamedDecl *PrefixND = getClosurePrefix(ND)) {
@@ -1089,6 +1086,11 @@ void CXXNameMangler::mangleNameWithAbiTags(GlobalDecl GD,
     return;
   }
 
+  if (isLocalContainerContext(DC)) {
+    mangleLocalName(GD, AdditionalAbiTags);
+    return;
+  }
+
   if (DC->isTranslationUnit() || isStdNamespace(DC)) {
     // Check if we have a template.
     const TemplateArgumentList *TemplateArgs = nullptr;
@@ -2201,8 +2203,6 @@ void CXXNameMangler::manglePrefix(const DeclContext *DC, bool NoFunction) {
   if (NoFunction && isLocalContainerContext(DC))
     return;
 
-  assert(!isLocalContainerContext(DC));
-
   const NamedDecl *ND = cast<NamedDecl>(DC);
   if (mangleSubstitution(ND))
     return;

diff  --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp
index 5531e938e0f4f4..8236051e30c4a5 100644
--- a/clang/lib/Frontend/CompilerInvocation.cpp
+++ b/clang/lib/Frontend/CompilerInvocation.cpp
@@ -3660,6 +3660,9 @@ void CompilerInvocationBase::GenerateLangArgs(const LangOptions &Opts,
   case LangOptions::ClangABI::Ver17:
     GenerateArg(Consumer, OPT_fclang_abi_compat_EQ, "17.0");
     break;
+  case LangOptions::ClangABI::Ver18:
+    GenerateArg(Consumer, OPT_fclang_abi_compat_EQ, "18.0");
+    break;
   case LangOptions::ClangABI::Latest:
     break;
   }
@@ -4167,6 +4170,8 @@ bool CompilerInvocation::ParseLangArgs(LangOptions &Opts, ArgList &Args,
         Opts.setClangABICompat(LangOptions::ClangABI::Ver15);
       else if (Major <= 17)
         Opts.setClangABICompat(LangOptions::ClangABI::Ver17);
+      else if (Major <= 18)
+        Opts.setClangABICompat(LangOptions::ClangABI::Ver18);
     } else if (Ver != "latest") {
       Diags.Report(diag::err_drv_invalid_value)
           << A->getAsString(Args) << A->getValue();

diff  --git a/clang/test/CodeGenCXX/mangle-lambdas-gh88906.cpp b/clang/test/CodeGenCXX/mangle-lambdas-gh88906.cpp
new file mode 100644
index 00000000000000..e7592cec5da776
--- /dev/null
+++ b/clang/test/CodeGenCXX/mangle-lambdas-gh88906.cpp
@@ -0,0 +1,46 @@
+// RUN: %clang_cc1 -triple x86_64-linux-gnu %s -emit-llvm -mconstructor-aliases -o - | FileCheck %s
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -fclang-abi-compat=18 %s -emit-llvm -mconstructor-aliases  -o - | FileCheck --check-prefix=CLANG18 %s
+// RUN: %clang_cc1 -triple i386-pc-win32 %s -emit-llvm -mconstructor-aliases -o - | FileCheck --check-prefix=MSABI %s
+
+
+class func {
+public:
+    template <typename T>
+    func(T){};
+    template <typename T, typename U>
+    func(T, U){};
+};
+
+void GH88906(){
+  class Test{
+    public:
+    func a{[]{ }, []{ }};
+    func b{[]{ }};
+    func c{[]{ }};
+  } test;
+}
+
+// CHECK-LABEL: define internal void @_ZZ7GH88906vEN4TestC2Ev
+// CHECK: call void @_ZN4funcC2IN7GH889064Test1aMUlvE_ENS3_UlvE0_EEET_T0_
+// CHECK: call void @_ZN4funcC2IN7GH889064Test1bMUlvE_EEET_
+// CHECK: call void @_ZN4funcC2IN7GH889064Test1cMUlvE_EEET_
+
+// CHECK-LABEL: define internal void @_ZN4funcC2IN7GH889064Test1aMUlvE_ENS3_UlvE0_EEET_T0_
+// CHECK-LABEL: define internal void @_ZN4funcC2IN7GH889064Test1bMUlvE_EEET_
+// CHECK-LABEL: define internal void @_ZN4funcC2IN7GH889064Test1cMUlvE_EEET_
+
+// CLANG18-LABEL: define internal void @_ZZ7GH88906vEN4TestC2Ev
+// CLANG18: call void @_ZN4funcC2IZ7GH88906vEN4TestUlvE_EZ7GH88906vENS1_UlvE0_EEET_T0_
+// CLANG18: call void @_ZN4funcC2IZ7GH88906vEN4TestUlvE_EEET_
+// CLANG18: call void @_ZN4funcC2IZ7GH88906vEN4TestUlvE_EEET_
+
+
+
+// MSABI-LABEL: define internal x86_thiscallcc noundef ptr @"??0Test@?1??GH88906@@YAXXZ at QAE@XZ"
+// MSABI: call x86_thiscallcc noundef ptr @"??$?0V<lambda_1>@a at Test@?1??GH88906@@YAXXZ at V<lambda_2>@12?1??3 at YAXXZ@@func@@QAE at V<lambda_1>@a at Test@?1??GH88906@@YAXXZ at V<lambda_2>@23?1??4 at YAXXZ@@Z"
+// MSABI: call x86_thiscallcc noundef ptr @"??$?0V<lambda_1>@b at Test@?1??GH88906@@YAXXZ@@func@@QAE at V<lambda_1>@b at Test@?1??GH88906@@YAXXZ@@Z"
+// MSABI: call x86_thiscallcc noundef ptr @"??$?0V<lambda_1>@c at Test@?1??GH88906@@YAXXZ@@func@@QAE at V<lambda_1>@c at Test@?1??GH88906@@YAXXZ@@Z"
+
+// MSABI-LABEL: define internal x86_thiscallcc noundef ptr @"??$?0V<lambda_1>@a at Test@?1??GH88906@@YAXXZ at V<lambda_2>@12?1??3 at YAXXZ@@func@@QAE at V<lambda_1>@a at Test@?1??GH88906@@YAXXZ at V<lambda_2>@23?1??4 at YAXXZ@@Z"
+// MSABI-LABEL: define internal x86_thiscallcc noundef ptr @"??$?0V<lambda_1>@b at Test@?1??GH88906@@YAXXZ@@func@@QAE at V<lambda_1>@b at Test@?1??GH88906@@YAXXZ@@Z"
+// MSABI-LABEL: define internal x86_thiscallcc noundef ptr @"??$?0V<lambda_1>@c at Test@?1??GH88906@@YAXXZ@@func@@QAE at V<lambda_1>@c at Test@?1??GH88906@@YAXXZ@@Z"


        


More information about the cfe-commits mailing list