llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang
Author: Kristina Bessonova (chbessonova)
<details>
<summary>Changes</summary>
Lambdas appearing in default member initializers of members of local classes
were previously mangled as if they belonged only to the class scope, ignoring
the enclosing function-local context.
This caused different (but same-named) local classes to produce identical
closure type mangling and corresponding RTTI/IR collisions.
Consider the following example:
```
void foo() {
{
struct T {
std::function<void()> a = [](){ std::cout << "a"; };
} t;
t.a();
}
{
struct T {
std::function<void()> a = [](){ std::cout << "b"; };
} t;
t.a();
}
}
```
The expected output is `ab` (and GCC-compiled code behaves accordingly), while
clang previously printed `aa` because the second `T::a` definition never
reached IR generation due to the missing `<local-name>` encoding and
discriminator required to distinguish the two local `T` definitions.
---
Full diff: https://github.com/llvm/llvm-project/pull/206740.diff
4 Files Affected:
- (modified) clang/lib/AST/ItaniumMangle.cpp (+12-8)
- (modified) clang/test/CodeGenCXX/dtor-local-lambda-mangle.cpp (+3-3)
- (modified) clang/test/CodeGenCXX/mangle-lambdas-gh88906.cpp (+6-6)
- (added) clang/test/CodeGenCXX/mangle-lambdas-in-dmi-local-class.cpp (+65)
``````````diff
diff --git a/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp
index e5cdd6f31c507..e014b45a5da93 100644
--- a/clang/lib/AST/ItaniumMangle.cpp
+++ b/clang/lib/AST/ItaniumMangle.cpp
@@ -530,7 +530,8 @@ class CXXNameMangler {
ArrayRef<TemplateArgument> Args);
void mangleNestedNameWithClosurePrefix(GlobalDecl GD,
const NamedDecl *PrefixND,
- ArrayRef<StringRef>
AdditionalAbiTags);
+ ArrayRef<StringRef> AdditionalAbiTags,
+ bool NoFunction = false);
void manglePrefix(NestedNameSpecifier Qualifier);
void manglePrefix(const DeclContext *DC, bool NoFunction=false);
void manglePrefix(QualType type);
@@ -1067,10 +1068,8 @@ void CXXNameMangler::mangleNameWithAbiTags(
// ::= <local-name>
//
const DeclContext *DC = Context.getEffectiveDeclContext(ND);
- bool IsLambda = isLambda(ND);
- if (GetLocalClassDecl(ND) &&
- (!IsLambda || isCompatibleWith(LangOptions::ClangABI::Ver18))) {
+ if (GetLocalClassDecl(ND)) {
mangleLocalName(GD, AdditionalAbiTags);
return;
}
@@ -1845,7 +1844,7 @@ void CXXNameMangler::mangleNestedName(const TemplateDecl
*TD,
void CXXNameMangler::mangleNestedNameWithClosurePrefix(
GlobalDecl GD, const NamedDecl *PrefixND,
- ArrayRef<StringRef> AdditionalAbiTags) {
+ ArrayRef<StringRef> AdditionalAbiTags, bool NoFunction) {
// A <closure-prefix> represents a variable or field, not a regular
// DeclContext, so needs special handling. In this case we're mangling a
// limited form of <nested-name>:
@@ -1854,7 +1853,7 @@ void CXXNameMangler::mangleNestedNameWithClosurePrefix(
Out << 'N';
- mangleClosurePrefix(PrefixND);
+ mangleClosurePrefix(PrefixND, NoFunction);
mangleUnqualifiedName(GD, nullptr, AdditionalAbiTags);
Out << 'E';
@@ -1945,8 +1944,13 @@ void CXXNameMangler::mangleLocalName(GlobalDecl GD,
mangleUnqualifiedBlock(BD);
} else {
const NamedDecl *ND = cast<NamedDecl>(D);
- mangleNestedName(GD, Context.getEffectiveDeclContext(ND),
- AdditionalAbiTags, true /*NoFunction*/);
+ const NamedDecl *PrefixND = getClosurePrefix(ND);
+ if (PrefixND && !isCompatibleWith(LangOptions::ClangABI::Ver18))
+ mangleNestedNameWithClosurePrefix(GD, PrefixND, AdditionalAbiTags,
+ true /*NoFunction*/);
+ else
+ mangleNestedName(GD, Context.getEffectiveDeclContext(ND),
+ AdditionalAbiTags, true /*NoFunction*/);
}
} else if (const BlockDecl *BD = dyn_cast<BlockDecl>(D)) {
// Mangle a block in a default parameter; see above explanation for
diff --git a/clang/test/CodeGenCXX/dtor-local-lambda-mangle.cpp
b/clang/test/CodeGenCXX/dtor-local-lambda-mangle.cpp
index 95283dad4a933..bd7b60b816fa7 100644
--- a/clang/test/CodeGenCXX/dtor-local-lambda-mangle.cpp
+++ b/clang/test/CodeGenCXX/dtor-local-lambda-mangle.cpp
@@ -10,7 +10,7 @@ struct E {
E::E() {
struct {
- // CHECK-DAG: _ZTSN1EC13$_012anotherValueMUlvE_E
+ // CHECK-DAG: _ZTSZN1EC1EvEN3$_012anotherValueMUlvE_E
int anotherValue = [x = 1] { return x; }();
} obj;
}
@@ -18,14 +18,14 @@ E::E() {
template<typename T>
E::E(T t) {
struct {
- // CHECK-DAG: _ZTSN1EC1IiEUt_12anotherValueMUlvE_E
+ // CHECK-DAG: _ZTSZN1ED1EvEN3$_012anotherValueMUlvE_E
int anotherValue = [x = 1] { return x; }();
} obj;
}
E::~E() {
struct {
- // CHECK-DAG: _ZTSN1ED13$_012anotherValueMUlvE_E
+ // CHECK-DAG: _ZTSZN1EC1IiEET_ENUt_12anotherValueMUlvE_E
int anotherValue = [x = 2] { return x; }();
} obj;
}
diff --git a/clang/test/CodeGenCXX/mangle-lambdas-gh88906.cpp
b/clang/test/CodeGenCXX/mangle-lambdas-gh88906.cpp
index e7592cec5da77..ba99906d358be 100644
--- a/clang/test/CodeGenCXX/mangle-lambdas-gh88906.cpp
+++ b/clang/test/CodeGenCXX/mangle-lambdas-gh88906.cpp
@@ -21,13 +21,13 @@ void GH88906(){
}
// 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: call void
@_ZN4funcC2IZ7GH88906vEN4Test1aMUlvE_EZ7GH88906vENS2_UlvE0_EEET_T0_
+// CHECK: call void @_ZN4funcC2IZ7GH88906vEN4Test1bMUlvE_EEET_
+// CHECK: call void @_ZN4funcC2IZ7GH88906vEN4Test1cMUlvE_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_
+// CHECK-LABEL: define internal void
@_ZN4funcC2IZ7GH88906vEN4Test1aMUlvE_EZ7GH88906vENS2_UlvE0_EEET_T0_
+// CHECK-LABEL: define internal void @_ZN4funcC2IZ7GH88906vEN4Test1bMUlvE_EEET_
+// CHECK-LABEL: define internal void @_ZN4funcC2IZ7GH88906vEN4Test1cMUlvE_EEET_
// CLANG18-LABEL: define internal void @_ZZ7GH88906vEN4TestC2Ev
// CLANG18: call void
@_ZN4funcC2IZ7GH88906vEN4TestUlvE_EZ7GH88906vENS1_UlvE0_EEET_T0_
diff --git a/clang/test/CodeGenCXX/mangle-lambdas-in-dmi-local-class.cpp
b/clang/test/CodeGenCXX/mangle-lambdas-in-dmi-local-class.cpp
new file mode 100644
index 0000000000000..479ce23dc53ab
--- /dev/null
+++ b/clang/test/CodeGenCXX/mangle-lambdas-in-dmi-local-class.cpp
@@ -0,0 +1,65 @@
+// RUN: %clang_cc1 -triple x86_64-linux-gnu %s -emit-llvm -I%S -std=c++20 -o -
| FileCheck %s
+
+// Ensure that local classes mangled with <local-name> while mangling a lamda
+// in default member initializer.
+
+// Itanium ABI 5.1.2
+// Names
+// <...> Entities declared within a function, including members of local
classes, are mangled with <local-name>. Entities declared in a namespace or
class scope are mangled with <nested-name>. <...>
+
+#include <typeinfo>
+
+void foo() {
+ {
+ struct Test {
+ const std::type_info& a = typeid([] {});
+ const std::type_info& b = typeid([] {});
+ } T;
+ }
+
+ {
+ struct Test {
+ const std::type_info& a = typeid([] {});
+ const std::type_info& b = typeid([] {});
+ } T;
+ }
+}
+
+// _Z
+// TI
+// Z3foovE ; local-name scope
+// N
+// 4Test
+// 1a ; member a
+// M ; member-initializer context
+// UlvE_ ; lambda closure type
+// E
+
+// CHECK: @_ZTIZ3foovEN4Test1aMUlvE_E
+// CHECK: @_ZTSZ3foovEN4Test1aMUlvE_E
+// CHECK: @_ZTIZ3foovEN4Test1bMUlvE_E
+// CHECK: @_ZTSZ3foovEN4Test1bMUlvE_E
+
+// _Z
+// TI
+// Z3foovE ; local-name scope
+// N
+// 4Test
+// 1a ; member a
+// M ; member-initializer context
+// UlvE_ ; lambda closure type
+// E
+// _0 ; second local 'Test' definition
+
+// CHECK: @_ZTIZ3foovEN4Test1aMUlvE_E_0
+// CHECK: @_ZTSZ3foovEN4Test1aMUlvE_E_0
+// CHECK: @_ZTIZ3foovEN4Test1bMUlvE_E_0
+// CHECK: @_ZTSZ3foovEN4Test1bMUlvE_E_0
+
+// CHECK-LABEL: @_ZZ3foovEN4TestC2Ev
+// CHECK: store ptr @_ZTIZ3foovEN4Test1aMUlvE_E
+// CHECK: store ptr @_ZTIZ3foovEN4Test1bMUlvE_E
+
+// CHECK-LABEL: @_ZZ3foovEN4TestC2E_0v
+// CHECK: store ptr @_ZTIZ3foovEN4Test1aMUlvE_E_0
+// CHECK: store ptr @_ZTIZ3foovEN4Test1bMUlvE_E_0
``````````
</details>
https://github.com/llvm/llvm-project/pull/206740
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits