Skip to content

Commit 64cc3fa

Browse files
authored
[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
1 parent 5e5b8c4 commit 64cc3fa

File tree

5 files changed

+66
-9
lines changed

5 files changed

+66
-9
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -549,6 +549,7 @@ Bug Fixes to C++ Support
549549
- Fix a crash in requires expression with templated base class member function. Fixes (#GH84020).
550550
- Fix a crash caused by defined struct in a type alias template when the structure
551551
has fields with dependent type. Fixes (#GH75221).
552+
- Fix the Itanium mangling of lambdas defined in a member of a local class (#GH88906)
552553

553554
Bug Fixes to AST Handling
554555
^^^^^^^^^^^^^^^^^^^^^^^^^

clang/include/clang/Basic/LangOptions.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,11 @@ class LangOptionsBase {
224224
/// - the parameter list of a template template parameter
225225
Ver17,
226226

227+
/// Attempt to be ABI-compatible with code generated by Clang 18.0.x.
228+
/// This causes clang to revert some fixes to the mangling of lambdas
229+
/// in the initializers of members of local classes.
230+
Ver18,
231+
227232
/// Conform to the underlying platform's C and C++ ABIs as closely
228233
/// as we can.
229234
Latest

clang/lib/AST/ItaniumMangle.cpp

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1062,33 +1062,35 @@ void CXXNameMangler::mangleNameWithAbiTags(GlobalDecl GD,
10621062
// ::= <local-name>
10631063
//
10641064
const DeclContext *DC = Context.getEffectiveDeclContext(ND);
1065+
bool IsLambda = isLambda(ND);
10651066

10661067
// If this is an extern variable declared locally, the relevant DeclContext
10671068
// is that of the containing namespace, or the translation unit.
10681069
// FIXME: This is a hack; extern variables declared locally should have
10691070
// a proper semantic declaration context!
1070-
if (isLocalContainerContext(DC) && ND->hasLinkage() && !isLambda(ND))
1071+
if (isLocalContainerContext(DC) && ND->hasLinkage() && !IsLambda)
10711072
while (!DC->isNamespace() && !DC->isTranslationUnit())
10721073
DC = Context.getEffectiveParentContext(DC);
1073-
else if (GetLocalClassDecl(ND)) {
1074+
else if (GetLocalClassDecl(ND) &&
1075+
(!IsLambda || isCompatibleWith(LangOptions::ClangABI::Ver18))) {
10741076
mangleLocalName(GD, AdditionalAbiTags);
10751077
return;
10761078
}
10771079

10781080
assert(!isa<LinkageSpecDecl>(DC) && "context cannot be LinkageSpecDecl");
10791081

1080-
if (isLocalContainerContext(DC)) {
1081-
mangleLocalName(GD, AdditionalAbiTags);
1082-
return;
1083-
}
1084-
10851082
// Closures can require a nested-name mangling even if they're semantically
10861083
// in the global namespace.
10871084
if (const NamedDecl *PrefixND = getClosurePrefix(ND)) {
10881085
mangleNestedNameWithClosurePrefix(GD, PrefixND, AdditionalAbiTags);
10891086
return;
10901087
}
10911088

1089+
if (isLocalContainerContext(DC)) {
1090+
mangleLocalName(GD, AdditionalAbiTags);
1091+
return;
1092+
}
1093+
10921094
if (DC->isTranslationUnit() || isStdNamespace(DC)) {
10931095
// Check if we have a template.
10941096
const TemplateArgumentList *TemplateArgs = nullptr;
@@ -2201,8 +2203,6 @@ void CXXNameMangler::manglePrefix(const DeclContext *DC, bool NoFunction) {
22012203
if (NoFunction && isLocalContainerContext(DC))
22022204
return;
22032205

2204-
assert(!isLocalContainerContext(DC));
2205-
22062206
const NamedDecl *ND = cast<NamedDecl>(DC);
22072207
if (mangleSubstitution(ND))
22082208
return;

clang/lib/Frontend/CompilerInvocation.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3660,6 +3660,9 @@ void CompilerInvocationBase::GenerateLangArgs(const LangOptions &Opts,
36603660
case LangOptions::ClangABI::Ver17:
36613661
GenerateArg(Consumer, OPT_fclang_abi_compat_EQ, "17.0");
36623662
break;
3663+
case LangOptions::ClangABI::Ver18:
3664+
GenerateArg(Consumer, OPT_fclang_abi_compat_EQ, "18.0");
3665+
break;
36633666
case LangOptions::ClangABI::Latest:
36643667
break;
36653668
}
@@ -4167,6 +4170,8 @@ bool CompilerInvocation::ParseLangArgs(LangOptions &Opts, ArgList &Args,
41674170
Opts.setClangABICompat(LangOptions::ClangABI::Ver15);
41684171
else if (Major <= 17)
41694172
Opts.setClangABICompat(LangOptions::ClangABI::Ver17);
4173+
else if (Major <= 18)
4174+
Opts.setClangABICompat(LangOptions::ClangABI::Ver18);
41704175
} else if (Ver != "latest") {
41714176
Diags.Report(diag::err_drv_invalid_value)
41724177
<< A->getAsString(Args) << A->getValue();
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
// RUN: %clang_cc1 -triple x86_64-linux-gnu %s -emit-llvm -mconstructor-aliases -o - | FileCheck %s
2+
// RUN: %clang_cc1 -triple x86_64-linux-gnu -fclang-abi-compat=18 %s -emit-llvm -mconstructor-aliases -o - | FileCheck --check-prefix=CLANG18 %s
3+
// RUN: %clang_cc1 -triple i386-pc-win32 %s -emit-llvm -mconstructor-aliases -o - | FileCheck --check-prefix=MSABI %s
4+
5+
6+
class func {
7+
public:
8+
template <typename T>
9+
func(T){};
10+
template <typename T, typename U>
11+
func(T, U){};
12+
};
13+
14+
void GH88906(){
15+
class Test{
16+
public:
17+
func a{[]{ }, []{ }};
18+
func b{[]{ }};
19+
func c{[]{ }};
20+
} test;
21+
}
22+
23+
// CHECK-LABEL: define internal void @_ZZ7GH88906vEN4TestC2Ev
24+
// CHECK: call void @_ZN4funcC2IN7GH889064Test1aMUlvE_ENS3_UlvE0_EEET_T0_
25+
// CHECK: call void @_ZN4funcC2IN7GH889064Test1bMUlvE_EEET_
26+
// CHECK: call void @_ZN4funcC2IN7GH889064Test1cMUlvE_EEET_
27+
28+
// CHECK-LABEL: define internal void @_ZN4funcC2IN7GH889064Test1aMUlvE_ENS3_UlvE0_EEET_T0_
29+
// CHECK-LABEL: define internal void @_ZN4funcC2IN7GH889064Test1bMUlvE_EEET_
30+
// CHECK-LABEL: define internal void @_ZN4funcC2IN7GH889064Test1cMUlvE_EEET_
31+
32+
// CLANG18-LABEL: define internal void @_ZZ7GH88906vEN4TestC2Ev
33+
// CLANG18: call void @_ZN4funcC2IZ7GH88906vEN4TestUlvE_EZ7GH88906vENS1_UlvE0_EEET_T0_
34+
// CLANG18: call void @_ZN4funcC2IZ7GH88906vEN4TestUlvE_EEET_
35+
// CLANG18: call void @_ZN4funcC2IZ7GH88906vEN4TestUlvE_EEET_
36+
37+
38+
39+
// MSABI-LABEL: define internal x86_thiscallcc noundef ptr @"??0Test@?1??GH88906@@YAXXZ@QAE@XZ"
40+
// MSABI: call x86_thiscallcc noundef ptr @"??$?0V<lambda_1>@a@Test@?1??GH88906@@YAXXZ@V<lambda_2>@12?1??3@YAXXZ@@func@@QAE@V<lambda_1>@a@Test@?1??GH88906@@YAXXZ@V<lambda_2>@23?1??4@YAXXZ@@Z"
41+
// MSABI: call x86_thiscallcc noundef ptr @"??$?0V<lambda_1>@b@Test@?1??GH88906@@YAXXZ@@func@@QAE@V<lambda_1>@b@Test@?1??GH88906@@YAXXZ@@Z"
42+
// MSABI: call x86_thiscallcc noundef ptr @"??$?0V<lambda_1>@c@Test@?1??GH88906@@YAXXZ@@func@@QAE@V<lambda_1>@c@Test@?1??GH88906@@YAXXZ@@Z"
43+
44+
// MSABI-LABEL: define internal x86_thiscallcc noundef ptr @"??$?0V<lambda_1>@a@Test@?1??GH88906@@YAXXZ@V<lambda_2>@12?1??3@YAXXZ@@func@@QAE@V<lambda_1>@a@Test@?1??GH88906@@YAXXZ@V<lambda_2>@23?1??4@YAXXZ@@Z"
45+
// MSABI-LABEL: define internal x86_thiscallcc noundef ptr @"??$?0V<lambda_1>@b@Test@?1??GH88906@@YAXXZ@@func@@QAE@V<lambda_1>@b@Test@?1??GH88906@@YAXXZ@@Z"
46+
// MSABI-LABEL: define internal x86_thiscallcc noundef ptr @"??$?0V<lambda_1>@c@Test@?1??GH88906@@YAXXZ@@func@@QAE@V<lambda_1>@c@Test@?1??GH88906@@YAXXZ@@Z"

0 commit comments

Comments
 (0)