[clang] [Clang] Avoid numbering lambdas with invalid types (PR #232606)

via cfe-commits cfe-commits at lists.llvm.org
Thu Oct 15 23:09:11 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-clang

Author: Kunal Dubey  (xakep8)

<details>
<summary>Changes</summary>

This is stacked on #<!-- -->232357. The first commit belongs to that PR; the lambda error-recovery change is the second commit.

During error recovery, a lambda parameter can contain an invalid type. Clang still tries to assign the lambda a stable number, which requires mangling its parameter types and can reach an internal compiler error.

Skip lambda numbering when the lambda's call-operator type already contains errors. This lets Clang report the original source error instead of crashing.

Fixes #<!-- -->170185


---
Full diff: https://github.com/llvm/llvm-project/pull/232606.diff


5 Files Affected:

- (modified) clang/docs/ReleaseNotes.md (+8) 
- (modified) clang/lib/AST/ItaniumMangle.cpp (+21-2) 
- (modified) clang/lib/Sema/SemaLambda.cpp (+3) 
- (modified) clang/test/CodeGenCXX/mangle-cxx2a.cpp (+46) 
- (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..ddde9d48606df 100644
--- a/clang/lib/AST/ItaniumMangle.cpp
+++ b/clang/lib/AST/ItaniumMangle.cpp
@@ -4945,7 +4945,13 @@ void CXXNameMangler::mangleCastExpression(const Expr *E, StringRef CastEncoding)
   const ExplicitCastExpr *ECE = cast<ExplicitCastExpr>(E);
   Out << CastEncoding;
   mangleType(ECE->getType());
-  mangleExpression(ECE->getSubExpr());
+  if (const auto *PLIE = dyn_cast<CXXParenListInitExpr>(ECE->getSubExpr())) {
+    ArrayRef<Expr *> Inits = PLIE->getUserSpecifiedInitExprs();
+    assert(Inits.size() == 1 && "cast must have exactly one operand");
+    mangleExpression(Inits.front());
+  } else {
+    mangleExpression(ECE->getSubExpr());
+  }
 }
 
 void CXXNameMangler::mangleInitListElements(const InitListExpr *InitList) {
@@ -5344,6 +5350,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 +5779,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..82dad5cdeb83b 100644
--- a/clang/test/CodeGenCXX/mangle-cxx2a.cpp
+++ b/clang/test/CodeGenCXX/mangle-cxx2a.cpp
@@ -9,3 +9,49 @@ 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>);
+
+  template <int N> void c_style(X<N + ((A)1).a>) {}
+  template <int N> void static_style(X<N + static_cast<A>(1).a>) {}
+
+  // CHECK-LABEL: define {{.*}} @_ZN10paren_init7c_styleILi0EEEvNS_1XIXplT_dtcvNS_1AELi1E1aEEE
+  template void c_style<0>(X<1>);
+  // CHECK-LABEL: define {{.*}} @_ZN10paren_init12static_styleILi0EEEvNS_1XIXplT_dtscNS_1AELi1E1aEEE
+  template void static_style<0>(X<1>);
+
+  // 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/232606


More information about the cfe-commits mailing list