[clang] [Clang] Fix mangling for struct initializers and invalid lambdas (PR #232357)
via cfe-commits
cfe-commits at lists.llvm.org
Thu Oct 15 08:01:21 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang
Author: Kunal Dubey (xakep8)
<details>
<summary>Changes</summary>
Clang omitted the arguments used to initialize a struct with parentheses, which could give different declarations the same internal name.
It could also crash when error recovery tried to process a lambda with and invalid type, because clang correctly finds the error that the type is invalid but keeps processing to read more errors but for this it has to assign a name to the lambda and number similar lambdas, which partly depends on it parameters but since the parameters are incomplete it crashes.
Included the written initializer arguments in the generated name and skipped lambda numbering when the lambda type contains errors.
Fixes #<!-- -->231953 #<!-- -->170185
---
Full diff: https://github.com/llvm/llvm-project/pull/232357.diff
5 Files Affected:
- (modified) clang/docs/ReleaseNotes.md (+8)
- (modified) clang/lib/AST/ItaniumMangle.cpp (+14-1)
- (modified) clang/lib/Sema/SemaLambda.cpp (+3)
- (modified) clang/test/CodeGenCXX/mangle-cxx2a.cpp (+38)
- (added) clang/test/SemaCXX/crash-GH170185.cpp (+14)
``````````diff
diff --git a/clang/docs/ReleaseNotes.md b/clang/docs/ReleaseNotes.md
index aba1dba5854fe..3710ab8e36abb 100644
--- a/clang/docs/ReleaseNotes.md
+++ b/clang/docs/ReleaseNotes.md
@@ -64,6 +64,11 @@ in a future version of Clang.
### ABI Changes in This Version
+- Clang now correctly mangles C++20 parenthesized aggregate initialization
+ expressions. Previously, initializer arguments could be omitted from the
+ mangled name, causing distinct entities to receive the same name.
+ (#GH231953)
+
- Except on PlayStation, Clang now derives the x86-64 System V AVX ABI level
for 256- and 512-bit vector arguments and returns from effective per-function
target features. Features and `arch=` CPUs that imply AVX or AVX512F are
@@ -799,6 +804,9 @@ features cannot lower the translation-unit ABI level;
#### Bug Fixes to C++ Support
+- Fixed a crash when a lambda parameter type contains an invalid non-type
+ template argument. (#GH170185)
+
- Fixed lambdas with specifiers or attributes after the capture list being
misparsed as function declarations in direct-initialization contexts under
`-fms-extensions` or in HLSL mode.
diff --git a/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp
index 0e32839a77be5..3692bcba9b1dd 100644
--- a/clang/lib/AST/ItaniumMangle.cpp
+++ b/clang/lib/AST/ItaniumMangle.cpp
@@ -5344,6 +5344,9 @@ void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity,
E = CCE->arg_end();
I != E; ++I)
mangleExpression(*I);
+ } else if (const auto *PLE = dyn_cast<CXXParenListInitExpr>(Init)) {
+ for (const Expr *Arg : PLE->getUserSpecifiedInitExprs())
+ mangleExpression(Arg);
} else if (const ParenListExpr *PLE = dyn_cast<ParenListExpr>(Init)) {
for (unsigned i = 0, e = PLE->getNumExprs(); i != e; ++i)
mangleExpression(PLE->getExpr(i));
@@ -5770,7 +5773,17 @@ void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity,
Sub = CCE->getArg(0)->IgnoreImplicit();
if (auto *StdInitList = dyn_cast<CXXStdInitializerListExpr>(Sub))
Sub = StdInitList->getSubExpr()->IgnoreImplicit();
- if (auto *IL = dyn_cast<InitListExpr>(Sub)) {
+ if (auto *PLIE = dyn_cast<CXXParenListInitExpr>(Sub)) {
+ ArrayRef<Expr *> Inits = PLIE->getUserSpecifiedInitExprs();
+ Out << "cv";
+ mangleType(E->getType());
+ if (Inits.size() != 1)
+ Out << '_';
+ for (const Expr *Init : Inits)
+ mangleExpression(Init);
+ if (Inits.size() != 1)
+ Out << 'E';
+ } else if (auto *IL = dyn_cast<InitListExpr>(Sub)) {
Out << "tl";
mangleType(E->getType());
mangleInitListElements(IL);
diff --git a/clang/lib/Sema/SemaLambda.cpp b/clang/lib/Sema/SemaLambda.cpp
index 0c9a92cdd0c32..ec74102c0ecaf 100644
--- a/clang/lib/Sema/SemaLambda.cpp
+++ b/clang/lib/Sema/SemaLambda.cpp
@@ -489,6 +489,9 @@ bool Sema::DiagnoseInvalidExplicitObjectParameterInLambda(
void Sema::handleLambdaNumbering(
CXXRecordDecl *Class, CXXMethodDecl *Method,
std::optional<CXXRecordDecl::LambdaNumbering> NumberingOverride) {
+ if (Method->getType()->containsErrors())
+ return;
+
ContextRAII ManglingContext(*this, Class->getDeclContext());
auto getMangleNumberingContext =
diff --git a/clang/test/CodeGenCXX/mangle-cxx2a.cpp b/clang/test/CodeGenCXX/mangle-cxx2a.cpp
index 3e4689948a7a7..0bfa2e21032cc 100644
--- a/clang/test/CodeGenCXX/mangle-cxx2a.cpp
+++ b/clang/test/CodeGenCXX/mangle-cxx2a.cpp
@@ -9,3 +9,41 @@ namespace spaceship {
template<typename T> void f(decltype(Y() < X(), T()) x) {}
template void f<int>(int);
}
+
+namespace paren_init {
+ struct A { int a; };
+ struct B { int a, b; };
+ struct D { int a, b = 7; };
+ template <int> struct X {};
+
+ template <int N> void f(X<N + A(1).a>) {}
+ template <int N> void f(X<N + A(2).a>) {}
+
+ // CHECK-LABEL: define {{.*}} @_ZN10paren_init1fILi0EEEvNS_1XIXplT_dtcvNS_1AELi1E1aEEE
+ template void f<0>(X<1>);
+ // CHECK-LABEL: define {{.*}} @_ZN10paren_init1fILi0EEEvNS_1XIXplT_dtcvNS_1AELi2E1aEEE
+ template void f<0>(X<2>);
+
+ // Check zero and multiple arguments, and a default member initializer.
+ template <int N> void zero(X<N + A().a>) {}
+ template <int N> void two(X<N + B(1, 2).b>) {}
+ template <int N> void defaulted(X<N + D(1).b>) {}
+
+ // CHECK-LABEL: define {{.*}} @_ZN10paren_init4zeroILi0EEEvNS_1XIXplT_dtcvNS_1AE_E1aEEE
+ template void zero<0>(X<0>);
+ // CHECK-LABEL: define {{.*}} @_ZN10paren_init3twoILi0EEEvNS_1XIXplT_dtcvNS_1BE_Li1ELi2EE1bEEE
+ template void two<0>(X<2>);
+ // CHECK-LABEL: define {{.*}} @_ZN10paren_init9defaultedILi0EEEvNS_1XIXplT_dtcvNS_1DELi1E1bEEE
+ template void defaulted<0>(X<7>);
+
+ template <int N> void new_zero(decltype((N, new A()))) {}
+ template <int N> void new_one(decltype((N, new A(1)))) {}
+ template <int N> void new_two(decltype((N, new B(1, 2)))) {}
+
+ // CHECK-LABEL: define {{.*}} @_ZN10paren_init8new_zeroILi0EEEvDTcmT_nw_NS_1AEpiEE
+ template void new_zero<0>(A *);
+ // CHECK-LABEL: define {{.*}} @_ZN10paren_init7new_oneILi0EEEvDTcmT_nw_NS_1AEpiLi1EEE
+ template void new_one<0>(A *);
+ // CHECK-LABEL: define {{.*}} @_ZN10paren_init7new_twoILi0EEEvDTcmT_nw_NS_1BEpiLi1ELi2EEE
+ template void new_two<0>(B *);
+}
diff --git a/clang/test/SemaCXX/crash-GH170185.cpp b/clang/test/SemaCXX/crash-GH170185.cpp
new file mode 100644
index 0000000000000..21fb071a1e80f
--- /dev/null
+++ b/clang/test/SemaCXX/crash-GH170185.cpp
@@ -0,0 +1,14 @@
+// RUN: %clang_cc1 -std=c++20 -fsyntax-only -verify %s
+
+struct Foo; // expected-note 2 {{forward declaration of 'Foo'}}
+
+template <Foo X> // expected-error {{non-type template parameter has incomplete type 'Foo'}}
+struct Arr;
+
+Foo f; // expected-error {{variable has incomplete type 'Foo'}}
+
+void foo() {
+ []() {
+ (void)[&](Arr<f>) {};
+ }();
+}
``````````
</details>
https://github.com/llvm/llvm-project/pull/232357
More information about the cfe-commits
mailing list