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 `bb` because the first `T::a` definition
is overridden by the second one due to the missing `<local-name>`
encoding and discriminator required to distinguish the two local `T`
definitions.
34 lines
720 B
C++
34 lines
720 B
C++
// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++20 -O2 -emit-llvm -o /dev/null %s
|
|
// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++20 -O2 -disable-llvm-passes -emit-llvm -o - %s | FileCheck %s
|
|
|
|
struct E {
|
|
E();
|
|
template<typename T>
|
|
E(T t);
|
|
~E();
|
|
};
|
|
|
|
E::E() {
|
|
struct {
|
|
// CHECK-DAG: _ZTSZN1EC1EvEN3$_012anotherValueMUlvE_E
|
|
int anotherValue = [x = 1] { return x; }();
|
|
} obj;
|
|
}
|
|
|
|
template<typename T>
|
|
E::E(T t) {
|
|
struct {
|
|
// CHECK-DAG: _ZTSZN1EC1IiEET_ENUt_12anotherValueMUlvE_E
|
|
int anotherValue = [x = 1] { return x; }();
|
|
} obj;
|
|
}
|
|
|
|
E::~E() {
|
|
struct {
|
|
// CHECK-DAG: _ZTSZN1ED1EvEN3$_012anotherValueMUlvE_E
|
|
int anotherValue = [x = 2] { return x; }();
|
|
} obj;
|
|
}
|
|
|
|
E e(1);
|