[clang] 13926e1 - [Clang] Preserve CXXParenListInitExpr in TreeTransform. (#138518)
via cfe-commits
cfe-commits at lists.llvm.org
Mon May 5 09:46:44 PDT 2025
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 at -1 2{{aggregate initialization of type 'A' from a parenthesized list of values is a C++20 extension}}
+ // beforecxx20-warning at -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 at -1 {{aggregate initialization of type 'const F' from a parenthesized list of values is a C++20 extension}}
- bar<int, 'a'>();
- // beforecxx20-note at -1 {{in instantiation of function template specialization 'bar<int, 'a'>' requested here}}
-
G<char> g('b', 'b');
// beforecxx20-warning at -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 at -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 at -1 {{aggregate initialization of type 'ThroughAlias<int, 1>' (aka 'int[1]') from a parenthesized list of values is a C++20 extension}}
+// beforecxx20-warning at -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 at -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 at -1 {{C++20 extension}}
+ DerivedTpl b = static_cast<DerivedTpl<T>>(BaseTpl<T>());
+ // beforecxx20-warning at -1 {{C++20 extension}}
+ static_assert(static_cast<Derived>(Base()).count == 42);
+ // beforecxx20-warning at -1 {{C++20 extension}}
+ static_assert(static_cast<DerivedTpl<T>>(BaseTpl<T>()).count == 43);
+ // beforecxx20-warning at -1 {{C++20 extension}}
+ }
+};
+
+void test() {
+ S<int>{}.f(); // beforecxx20-note {{requested here}}
+}
+}
More information about the cfe-commits
mailing list