From c0603457eb734d8a0aeb8a5c3cf131485116e303 Mon Sep 17 00:00:00 2001 From: Corentin Jabot Date: Sat, 24 May 2025 12:37:02 +0200 Subject: [PATCH 1/5] [Clang] Fix a regression introduced by #138518 We did not handle the case where a variable could be initialized by a CXXParenListInitExpr. --- clang/lib/Sema/SemaDecl.cpp | 8 +++++--- clang/test/SemaCXX/paren-list-agg-init.cpp | 22 ++++++++++++++++++++++ 2 files changed, 27 insertions(+), 3 deletions(-) diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 90525f386468a..401d1f34f70c0 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -13783,9 +13783,11 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, bool DirectInit) { VDecl->getLocation(), DirectInit, Init); MultiExprArg Args = Init; - if (CXXDirectInit) - Args = MultiExprArg(CXXDirectInit->getExprs(), - CXXDirectInit->getNumExprs()); + if (auto *CXXDirectInit = dyn_cast(Init)) + Args = + MultiExprArg(CXXDirectInit->getExprs(), CXXDirectInit->getNumExprs()); + else if (auto *CXXDirectInit = dyn_cast(Init)) + Args = CXXDirectInit->getInitExprs(); // Try to correct any TypoExprs in the initialization arguments. for (size_t Idx = 0; Idx < Args.size(); ++Idx) { diff --git a/clang/test/SemaCXX/paren-list-agg-init.cpp b/clang/test/SemaCXX/paren-list-agg-init.cpp index ba7dffdc1af9f..680fdcdbe7b1c 100644 --- a/clang/test/SemaCXX/paren-list-agg-init.cpp +++ b/clang/test/SemaCXX/paren-list-agg-init.cpp @@ -403,3 +403,25 @@ void test() { S{}.f(); // beforecxx20-note {{requested here}} } } + +namespace GH72880_regression { +struct E { + int i = 42; +}; +struct G { + E e; +}; +template +struct Test { + void f() { + constexpr E e; + //FIXME: We should only warn one + constexpr G g(e); // beforecxx20-warning 2{{C++20 extension}} + static_assert(g.e.i == 42); + } +}; +void test() { + Test{}.f(); // beforecxx20-note {{requested here}} +} + +} From 1ac18712bca2076a9073b94a11133a3d88f05a99 Mon Sep 17 00:00:00 2001 From: Corentin Jabot Date: Tue, 27 May 2025 17:48:58 +0200 Subject: [PATCH 2/5] cleanup --- clang/lib/Sema/SemaDecl.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 401d1f34f70c0..cac0eecc5f83a 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -13775,7 +13775,6 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, bool DirectInit) { } // Perform the initialization. - ParenListExpr *CXXDirectInit = dyn_cast(Init); bool IsParenListInit = false; if (!VDecl->isInvalidDecl()) { InitializedEntity Entity = InitializedEntity::InitializeVariable(VDecl); From b2fe02ed27a718ba3d0540d46dbdc3f95b1a786a Mon Sep 17 00:00:00 2001 From: Corentin Jabot Date: Tue, 27 May 2025 19:24:44 +0200 Subject: [PATCH 3/5] Revert "cleanup" This reverts commit 1ac18712bca2076a9073b94a11133a3d88f05a99. --- clang/lib/Sema/SemaDecl.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index cac0eecc5f83a..401d1f34f70c0 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -13775,6 +13775,7 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, bool DirectInit) { } // Perform the initialization. + ParenListExpr *CXXDirectInit = dyn_cast(Init); bool IsParenListInit = false; if (!VDecl->isInvalidDecl()) { InitializedEntity Entity = InitializedEntity::InitializeVariable(VDecl); From acaedbc5e7f57890884cff23ad7478e9f31d5450 Mon Sep 17 00:00:00 2001 From: Corentin Jabot Date: Tue, 27 May 2025 19:32:17 +0200 Subject: [PATCH 4/5] Track that we are initializing from a paren list expr --- clang/lib/Sema/SemaDecl.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 401d1f34f70c0..6b42c9161935f 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -13775,7 +13775,7 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, bool DirectInit) { } // Perform the initialization. - ParenListExpr *CXXDirectInit = dyn_cast(Init); + bool InitializedFromParenListExpr = false; bool IsParenListInit = false; if (!VDecl->isInvalidDecl()) { InitializedEntity Entity = InitializedEntity::InitializeVariable(VDecl); @@ -13783,11 +13783,14 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, bool DirectInit) { VDecl->getLocation(), DirectInit, Init); MultiExprArg Args = Init; - if (auto *CXXDirectInit = dyn_cast(Init)) + if (auto *CXXDirectInit = dyn_cast(Init)) { Args = MultiExprArg(CXXDirectInit->getExprs(), CXXDirectInit->getNumExprs()); - else if (auto *CXXDirectInit = dyn_cast(Init)) + InitializedFromParenListExpr = true; + } else if (auto *CXXDirectInit = dyn_cast(Init)) { Args = CXXDirectInit->getInitExprs(); + InitializedFromParenListExpr = true; + } // Try to correct any TypoExprs in the initialization arguments. for (size_t Idx = 0; Idx < Args.size(); ++Idx) { @@ -14088,7 +14091,7 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, bool DirectInit) { // The form of initialization (using parentheses or '=') is generally // insignificant, but does matter when the entity being initialized has a // class type. - if (CXXDirectInit) { + if (InitializedFromParenListExpr) { assert(DirectInit && "Call-style initializer must be direct init."); VDecl->setInitStyle(IsParenListInit ? VarDecl::ParenListInit : VarDecl::CallInit); From ab9eec7355c753059a379e02c59f714306be3e5b Mon Sep 17 00:00:00 2001 From: cor3ntin Date: Tue, 27 May 2025 23:24:04 +0200 Subject: [PATCH 5/5] Update clang/lib/Sema/SemaDecl.cpp Co-authored-by: Shafik Yaghmour --- clang/lib/Sema/SemaDecl.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 6b42c9161935f..c901c447ad0d7 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -14088,9 +14088,8 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, bool DirectInit) { // special case code. // C++ 8.5p11: - // The form of initialization (using parentheses or '=') is generally - // insignificant, but does matter when the entity being initialized has a - // class type. + // The form of initialization (using parentheses or '=') matters + // when the entity being initialized has class type. if (InitializedFromParenListExpr) { assert(DirectInit && "Call-style initializer must be direct init."); VDecl->setInitStyle(IsParenListInit ? VarDecl::ParenListInit