https://github.com/arrowten created 
https://github.com/llvm/llvm-project/pull/203715

When rebuilding a CXXFunctionalCastExpr during template instantiation, where 
the sub-expression is a CXXParenListInitExpr, we were passing all stored 
initializers to BuildCXXTypeConstructExpr — including the ones the compiler 
synthesized for uninitialized aggregate fields. Only the user-written 
initializers should be passed, otherwise we hit an assertion.

The test cases might be incomplete. I would like suggestions on what more type 
of testcases to be added.

Fixes #194986 

>From 7bb116a9b11ea3775d67defb41e27674122e94b1 Mon Sep 17 00:00:00 2001
From: Ajay Wakodikar <[email protected]>
Date: Sat, 13 Jun 2026 12:49:23 -0400
Subject: [PATCH] [Sema] Fix assertion in TreeTransform when rebuilding
 CXXParenListInitExpr

---
 clang/lib/Sema/TreeTransform.h                       |  6 +++++-
 .../test/SemaCXX/paren-agg-init-template-rebuild.cpp | 12 ++++++++++++
 2 files changed, 17 insertions(+), 1 deletion(-)
 create mode 100644 clang/test/SemaCXX/paren-agg-init-template-rebuild.cpp

diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h
index 53107c827006d..e475041026dc8 100644
--- a/clang/lib/Sema/TreeTransform.h
+++ b/clang/lib/Sema/TreeTransform.h
@@ -3410,9 +3410,13 @@ class TreeTransform {
           TInfo, LParenLoc, MultiExprArg(PLE->getExprs(), PLE->getNumExprs()),
           RParenLoc, ListInitialization);
 
+    // Skip compiler-added exprs — only pass what the user actually wrote,
+    // or we get false "too many initializers" errors.
     if (auto *PLE = dyn_cast<CXXParenListInitExpr>(Sub))
       return getSema().BuildCXXTypeConstructExpr(
-          TInfo, LParenLoc, PLE->getInitExprs(), RParenLoc, 
ListInitialization);
+          TInfo, LParenLoc,
+          PLE->getInitExprs().slice(0, 
PLE->getUserSpecifiedInitExprs().size()),
+          RParenLoc, ListInitialization);
 
     return getSema().BuildCXXTypeConstructExpr(TInfo, LParenLoc,
                                                MultiExprArg(&Sub, 1), 
RParenLoc,
diff --git a/clang/test/SemaCXX/paren-agg-init-template-rebuild.cpp 
b/clang/test/SemaCXX/paren-agg-init-template-rebuild.cpp
new file mode 100644
index 0000000000000..9ac9d9fe797bb
--- /dev/null
+++ b/clang/test/SemaCXX/paren-agg-init-template-rebuild.cpp
@@ -0,0 +1,12 @@
+// RUN: %clang_cc1 -verify -std=c++23 %s -fsyntax-only
+
+struct S {}; // expected-note 2{{candidate constructor}}
+template <typename T> struct SS { T t1; T t2; };
+template <class T, class... Args> T C(Args... args) { return SS("foo"); } // 
expected-error {{no viable conversion}}
+S s = C<S>(); // expected-note {{in instantiation of function template 
specialization 'C<S>'}}
+
+template <class T> struct SS2 { T t1, t2; };
+template <class> void C2() {
+  SS2("foo"); // expected-warning 2{{expression result unused}}
+}
+template void C2<int>(); // expected-note {{in instantiation of function 
template specialization 'C2<int>'}}

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to