Author: cor3ntin Date: 2025-05-05T18:46:40+02:00 New Revision: 13926e149081ca2771bdea7c08c07d92d87f7818
URL: https://github.com/llvm/llvm-project/commit/13926e149081ca2771bdea7c08c07d92d87f7818 DIFF: https://github.com/llvm/llvm-project/commit/13926e149081ca2771bdea7c08c07d92d87f7818.diff LOG: [Clang] Preserve CXXParenListInitExpr in TreeTransform. (#138518) We were converting a CXXParenListInitExpr to a ParenListExpr in TreeTransform. However, ParenListExpr is typeless, so Clang could not rebuild the correct initialization sequence in some contexts. Fixes #72880 Added: Modified: clang/docs/ReleaseNotes.rst clang/include/clang/AST/ExprCXX.h clang/include/clang/Sema/Sema.h clang/lib/Sema/SemaExpr.cpp clang/lib/Sema/TreeTransform.h clang/test/SemaCXX/paren-list-agg-init.cpp Removed: ################################################################################ diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index d5571b958ebed..b097e920e09ef 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -649,6 +649,7 @@ Bug Fixes to C++ Support (#GH136432), (#GH137014), (#GH138018) - Fixed an assertion when trying to constant-fold various builtins when the argument referred to a reference to an incomplete type. (#GH129397) +- Fixed a crash when a cast involved a parenthesized aggregate initialization in dependent context. (#GH72880) Bug Fixes to AST Handling ^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/clang/include/clang/AST/ExprCXX.h b/clang/include/clang/AST/ExprCXX.h index 844f6dd90ae1d..04d08b022c562 100644 --- a/clang/include/clang/AST/ExprCXX.h +++ b/clang/include/clang/AST/ExprCXX.h @@ -5124,8 +5124,8 @@ class CXXParenListInitExpr final void updateDependence() { setDependence(computeDependence(this)); } - ArrayRef<Expr *> getInitExprs() { - return ArrayRef(getTrailingObjects<Expr *>(), NumExprs); + MutableArrayRef<Expr *> getInitExprs() { + return MutableArrayRef(getTrailingObjects<Expr *>(), NumExprs); } const ArrayRef<Expr *> getInitExprs() const { diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 19343eb0af092..741951cb9ea0e 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -7167,6 +7167,11 @@ class Sema final : public SemaBase { ExprResult ActOnParenExpr(SourceLocation L, SourceLocation R, Expr *E); ExprResult ActOnParenListExpr(SourceLocation L, SourceLocation R, MultiExprArg Val); + ExprResult ActOnCXXParenListInitExpr(ArrayRef<Expr *> Args, QualType T, + unsigned NumUserSpecifiedExprs, + SourceLocation InitLoc, + SourceLocation LParenLoc, + SourceLocation RParenLoc); /// ActOnStringLiteral - The specified tokens were lexed as pasted string /// fragments (e.g. "foo" "bar" L"baz"). The result string has to handle diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 1963e048d6e78..b1ef316ef0b2f 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -7985,6 +7985,15 @@ ExprResult Sema::ActOnParenListExpr(SourceLocation L, return ParenListExpr::Create(Context, L, Val, R); } +ExprResult Sema::ActOnCXXParenListInitExpr(ArrayRef<Expr *> Args, QualType T, + unsigned NumUserSpecifiedExprs, + SourceLocation InitLoc, + SourceLocation LParenLoc, + SourceLocation RParenLoc) { + return CXXParenListInitExpr::Create(Context, Args, T, NumUserSpecifiedExprs, + InitLoc, LParenLoc, RParenLoc); +} + bool Sema::DiagnoseConditionalForNull(const Expr *LHSExpr, const Expr *RHSExpr, SourceLocation QuestionLoc) { const Expr *NullExpr = LHSExpr; diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index aed00e0ff06cd..8b4b79c6ec039 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -3099,6 +3099,15 @@ class TreeTransform { return getSema().ActOnParenListExpr(LParenLoc, RParenLoc, SubExprs); } + ExprResult RebuildCXXParenListInitExpr(ArrayRef<Expr *> Args, QualType T, + unsigned NumUserSpecifiedExprs, + SourceLocation InitLoc, + SourceLocation LParenLoc, + SourceLocation RParenLoc) { + return getSema().ActOnCXXParenListInitExpr(Args, T, NumUserSpecifiedExprs, + InitLoc, LParenLoc, RParenLoc); + } + /// Build a new address-of-label expression. /// /// By default, performs semantic analysis, using the name of the label @@ -3315,6 +3324,11 @@ class TreeTransform { return getSema().BuildCXXTypeConstructExpr( TInfo, LParenLoc, MultiExprArg(PLE->getExprs(), PLE->getNumExprs()), RParenLoc, ListInitialization); + + if (auto *PLE = dyn_cast<CXXParenListInitExpr>(Sub)) + return getSema().BuildCXXTypeConstructExpr( + TInfo, LParenLoc, PLE->getInitExprs(), RParenLoc, ListInitialization); + return getSema().BuildCXXTypeConstructExpr(TInfo, LParenLoc, MultiExprArg(&Sub, 1), RParenLoc, ListInitialization); @@ -16487,12 +16501,21 @@ ExprResult TreeTransform<Derived>::TransformCXXParenListInitExpr(CXXParenListInitExpr *E) { SmallVector<Expr *, 4> TransformedInits; ArrayRef<Expr *> InitExprs = E->getInitExprs(); - if (TransformExprs(InitExprs.data(), InitExprs.size(), true, - TransformedInits)) + + QualType T = getDerived().TransformType(E->getType()); + + bool ArgChanged = false; + + if (getDerived().TransformExprs(InitExprs.data(), InitExprs.size(), true, + TransformedInits, &ArgChanged)) return ExprError(); - return getDerived().RebuildParenListExpr(E->getBeginLoc(), TransformedInits, - E->getEndLoc()); + if (!getDerived().AlwaysRebuild() && !ArgChanged && T == E->getType()) + return E; + + return getDerived().RebuildCXXParenListInitExpr( + TransformedInits, T, E->getUserSpecifiedInitExprs().size(), + E->getInitLoc(), E->getBeginLoc(), E->getEndLoc()); } template<typename Derived> diff --git a/clang/test/SemaCXX/paren-list-agg-init.cpp b/clang/test/SemaCXX/paren-list-agg-init.cpp index b2d0f2564bb59..ba7dffdc1af9f 100644 --- a/clang/test/SemaCXX/paren-list-agg-init.cpp +++ b/clang/test/SemaCXX/paren-list-agg-init.cpp @@ -83,7 +83,7 @@ template <typename T, char CH> void bar() { T t = 0; A a(CH, 1.1); // OK; C++ paren list constructors are supported in semantic tree transformations. - // beforecxx20-warning@-1 2{{aggregate initialization of type 'A' from a parenthesized list of values is a C++20 extension}} + // beforecxx20-warning@-1 {{aggregate initialization of type 'A' from a parenthesized list of values is a C++20 extension}} } template <class T, class... Args> @@ -157,9 +157,6 @@ void foo(int n) { // expected-note {{declared here}} constexpr F f2(1, 1); // OK: f2.b is initialized by a constant expression. // beforecxx20-warning@-1 {{aggregate initialization of type 'const F' from a parenthesized list of values is a C++20 extension}} - bar<int, 'a'>(); - // beforecxx20-note@-1 {{in instantiation of function template specialization 'bar<int, 'a'>' requested here}} - G<char> g('b', 'b'); // beforecxx20-warning@-1 {{aggregate initialization of type 'G<char>' from a parenthesized list of values is a C++20 extension}} @@ -354,7 +351,7 @@ using Td = int[]; Td d(42,43); // beforecxx20-warning@-1 {{aggregate initialization of type 'int[2]' from a parenthesized list of values is a C++20 extension}} template<typename T, int Sz> using ThroughAlias = T[Sz]; ThroughAlias<int, 1> e(42); -// beforecxx20-warning@-1 {{aggregate initialization of type 'ThroughAlias<int, 1>' (aka 'int[1]') from a parenthesized list of values is a C++20 extension}} +// beforecxx20-warning@-1 {{aggregate initialization of type 'ThroughAlias<int, 1>' (aka 'int[1]') from a parenthesized list of values is a C++20 extension}} } @@ -376,3 +373,33 @@ static_assert(S(1, 2) == S(3, 4)); // beforecxx20-warning@-1 2{{C++20 extension}} } + +namespace GH72880 { +struct Base {}; +struct Derived : Base { + int count = 42; +}; + +template <typename T> +struct BaseTpl {}; +template <typename T> +struct DerivedTpl : BaseTpl<T> { + int count = 43; +}; +template <typename T> struct S { + void f() { + Derived a = static_cast<Derived>(Base()); + // beforecxx20-warning@-1 {{C++20 extension}} + DerivedTpl b = static_cast<DerivedTpl<T>>(BaseTpl<T>()); + // beforecxx20-warning@-1 {{C++20 extension}} + static_assert(static_cast<Derived>(Base()).count == 42); + // beforecxx20-warning@-1 {{C++20 extension}} + static_assert(static_cast<DerivedTpl<T>>(BaseTpl<T>()).count == 43); + // beforecxx20-warning@-1 {{C++20 extension}} + } +}; + +void test() { + S<int>{}.f(); // beforecxx20-note {{requested here}} +} +} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits