https://github.com/akash-manna-sky updated https://github.com/llvm/llvm-project/pull/224918
>From f2bdc5dd3748b3daa0ae401c5276de5b4c0c1455 Mon Sep 17 00:00:00 2001 From: Akash Manna <[email protected]> Date: Sun, 20 Sep 2026 17:19:35 +0530 Subject: [PATCH 1/2] [Clang] Re-analyze parenthesized aggregate mem-initializers on instantiation Since #138518, template instantiation preserves a parenthesized aggregate initialization as a CXXParenListInitExpr whose elements have been reverted to their written form, and the consumer is expected to redo the initialization from them. BuildMemberInitializer still treated the node as a single argument, so the malformed node was reused as the member's initializer. This crashed CodeGen for braced-list elements, rejected valid array members and left union members uninitialized. Treat a CXXParenListInitExpr like a ParenListExpr in BuildMemberInitializer and perform the initialization from its user-specified elements. Fixes #176161 --- clang/docs/ReleaseNotes.md | 4 +++ clang/lib/Sema/SemaDeclCXX.cpp | 4 +++ clang/test/CodeGenCXX/GH176161.cpp | 41 ++++++++++++++++++++++ clang/test/SemaCXX/paren-list-agg-init.cpp | 41 ++++++++++++++++++++++ 4 files changed, 90 insertions(+) create mode 100644 clang/test/CodeGenCXX/GH176161.cpp diff --git a/clang/docs/ReleaseNotes.md b/clang/docs/ReleaseNotes.md index f4a34a37aff52e..5f6e65fdb10a70 100644 --- a/clang/docs/ReleaseNotes.md +++ b/clang/docs/ReleaseNotes.md @@ -707,6 +707,10 @@ features cannot lower the translation-unit ABI level; inside a union caused the union to be treated as a polymorphic class. (#GH213854) +- Fixed a crash, a rejected-valid case and a miscompile when instantiating a + constructor whose mem-initializer used parenthesized aggregate initialization, + e.g. ``: agg({1, 2})`` or ``: arr(1, 2)``. (#GH176161) + - Fixed an assertion when a type-trait keyword that had already been made available as an identifier (e.g. `struct __make_unsigned`) was seen again in a token that was lexed and cached before the first occurrence was parsed. diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index 02b4c347dee094..ffd6d6cbf8596c 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -4685,6 +4685,10 @@ Sema::BuildMemberInitializer(ValueDecl *Member, Expr *Init, Args = MultiExprArg(ParenList->getExprs(), ParenList->getNumExprs()); } else if (InitListExpr *InitList = dyn_cast<InitListExpr>(Init)) { Args = MultiExprArg(InitList->getInits(), InitList->getNumInits()); + } else if (auto *ParenListInit = dyn_cast<CXXParenListInitExpr>(Init)) { + // Template instantiation reverts the elements to their syntactic form; + // redo the initialization from the written arguments. + Args = ParenListInit->getUserSpecifiedInitExprs(); } else { // Template instantiation doesn't reconstruct ParenListExprs for us. Args = Init; diff --git a/clang/test/CodeGenCXX/GH176161.cpp b/clang/test/CodeGenCXX/GH176161.cpp new file mode 100644 index 00000000000000..98b1fe4d97340b --- /dev/null +++ b/clang/test/CodeGenCXX/GH176161.cpp @@ -0,0 +1,41 @@ +// RUN: %clang_cc1 -triple x86_64-linux-gnu -std=c++23 -emit-llvm -o - %s | FileCheck %s + +template <typename T> struct ConfigFlag { T value; }; + +struct Tuple { + Tuple(ConfigFlag<bool> &&a, ConfigFlag<bool> &&b) : first(a), second(b) {} + ConfigFlag<bool> first, second; +}; + +struct ConfigSystem { + Tuple flags; +}; + +template <unsigned R> class M { +public: + M(const int *arr) { + auto flagProcessing = [] { + struct Configurator { + ConfigSystem config; + Configurator() + : config({ConfigFlag<bool>(true), ConfigFlag<bool>(false)}) {} + }; + Configurator configurator; + }; + flagProcessing(); + for (unsigned long r = 0; r < R; ++r) + m[r] = arr[r]; + } + int m[R]; +}; + +int main() { + int arr[2] = {1, 2}; + M<2> m(arr); +} + +// CHECK-LABEL: define {{.*}}12ConfiguratorC2Ev( +// CHECK: store i8 1, ptr +// CHECK: store i8 0, ptr +// CHECK: call void @_ZN5TupleC{{[12]}}E +// CHECK: ret void diff --git a/clang/test/SemaCXX/paren-list-agg-init.cpp b/clang/test/SemaCXX/paren-list-agg-init.cpp index 680fdcdbe7b1ce..90414dbd5a78fd 100644 --- a/clang/test/SemaCXX/paren-list-agg-init.cpp +++ b/clang/test/SemaCXX/paren-list-agg-init.cpp @@ -425,3 +425,44 @@ void test() { } } + +namespace GH176161 { +struct Inner { + constexpr Inner(int a, int b) : x(a), y(b) {} + int x, y; +}; +struct Agg { + Inner i; + int k = 7; +}; + +template <class T> struct S { + Agg a; + constexpr S() : a({1, 2}) {} // beforecxx20-warning 2{{C++20 extension}} +}; + +constexpr S<int> s; // beforecxx20-note {{requested here}} +static_assert(s.a.i.x == 1); +static_assert(s.a.i.y == 2); +static_assert(s.a.k == 7); + +struct X { + constexpr X() : v(5) {} + constexpr X(int v) : v(v) {} + int v; +}; +template <class T> struct Arr { + X arr[3]; + constexpr Arr() : arr(1, 2) {} // beforecxx20-warning 2{{C++20 extension}} +}; +constexpr Arr<int> arr; // beforecxx20-note {{requested here}} +static_assert(arr.arr[0].v == 1 && arr.arr[1].v == 2 && arr.arr[2].v == 5); + +union U { int a; float b; }; +template <class T> struct Un { + U u; + constexpr Un() : u('a') {} // beforecxx20-warning 2{{C++20 extension}} +}; +constexpr Un<int> un; // beforecxx20-note {{requested here}} +static_assert(un.u.a == 'a'); +} >From 5392ae9c73f49d9047950966f501f97d7284d7c9 Mon Sep 17 00:00:00 2001 From: Akash Manna <[email protected]> Date: Wed, 23 Sep 2026 00:17:40 +0530 Subject: [PATCH 2/2] [Clang] Re-analyze parenthesized aggregate mem-initializers on instantiation Since #138518, template instantiation preserves a parenthesized aggregate initialization as a CXXParenListInitExpr whose elements have been reverted to their written form, and the consumer is expected to redo the initialization from them. BuildMemberInitializer still treated the node as a single argument, so the malformed node was reused as the member's initializer. This crashed CodeGen for braced-list elements, dropped the conversions of scalar elements, rejected valid array members and left union members uninitialized. Treat a CXXParenListInitExpr like a ParenListExpr in BuildMemberInitializer and perform the initialization from its user-specified elements. Fixes #176161 Fixes #189005 Fixes #213284 --- clang/docs/ReleaseNotes.md | 4 ++-- clang/test/CodeGenCXX/GH176161.cpp | 12 ++++++++++++ clang/test/SemaCXX/paren-list-agg-init.cpp | 11 +++++++++++ 3 files changed, 25 insertions(+), 2 deletions(-) diff --git a/clang/docs/ReleaseNotes.md b/clang/docs/ReleaseNotes.md index 5f6e65fdb10a70..65c51853009deb 100644 --- a/clang/docs/ReleaseNotes.md +++ b/clang/docs/ReleaseNotes.md @@ -707,9 +707,9 @@ features cannot lower the translation-unit ABI level; inside a union caused the union to be treated as a polymorphic class. (#GH213854) -- Fixed a crash, a rejected-valid case and a miscompile when instantiating a +- Fixed a crash, a miscompile and a rejected-valid case when instantiating a constructor whose mem-initializer used parenthesized aggregate initialization, - e.g. ``: agg({1, 2})`` or ``: arr(1, 2)``. (#GH176161) + e.g. ``: agg({1, 2})`` or ``: arr(1, 2)``. (#GH176161, #GH189005, #GH213284) - Fixed an assertion when a type-trait keyword that had already been made available as an identifier (e.g. `struct __make_unsigned`) was seen again diff --git a/clang/test/CodeGenCXX/GH176161.cpp b/clang/test/CodeGenCXX/GH176161.cpp index 98b1fe4d97340b..d175b4d58dc249 100644 --- a/clang/test/CodeGenCXX/GH176161.cpp +++ b/clang/test/CodeGenCXX/GH176161.cpp @@ -39,3 +39,15 @@ int main() { // CHECK: store i8 0, ptr // CHECK: call void @_ZN5TupleC{{[12]}}E // CHECK: ret void + +namespace GH213284 { +struct Ref { unsigned long long bits; }; +template <typename> struct Result { + Result() : thing(0) {} + Ref thing; +}; +Result<void> construct() { return Result<void>(); } +} + +// CHECK-LABEL: define {{.*}}@_ZN8GH2132846ResultIvEC2Ev( +// CHECK: store i64 0, ptr diff --git a/clang/test/SemaCXX/paren-list-agg-init.cpp b/clang/test/SemaCXX/paren-list-agg-init.cpp index 90414dbd5a78fd..01e8e7638141f6 100644 --- a/clang/test/SemaCXX/paren-list-agg-init.cpp +++ b/clang/test/SemaCXX/paren-list-agg-init.cpp @@ -466,3 +466,14 @@ template <class T> struct Un { constexpr Un<int> un; // beforecxx20-note {{requested here}} static_assert(un.u.a == 'a'); } + +namespace GH189005 { +struct Elem { int x; }; +struct Outer { Elem arr[2]; }; +template <class T> struct Nested { + Outer m; + constexpr Nested() : m({{1}, {2}}) {} // beforecxx20-warning 2{{C++20 extension}} +}; +constexpr Nested<int> n; // beforecxx20-note {{requested here}} +static_assert(n.m.arr[0].x == 1 && n.m.arr[1].x == 2); +} _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
