-
Notifications
You must be signed in to change notification settings - Fork 13.4k
[Clang] Preserve CXXParenListInitExpr in TreeTransform. #138518
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
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
@llvm/pr-subscribers-clang Author: cor3ntin (cor3ntin) ChangesWe 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 Full diff: https://github.com/llvm/llvm-project/pull/138518.diff 6 Files Affected:
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 4bd9d904e1ea9..55a46fb6f947e 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -642,6 +642,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 d72d97addfac2..787b07c4080ea 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..a3120f61f0d9c 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,22 @@ 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 (!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}}
+}
+}
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please change the commit message to do Fixes # instead of the reverse, so this actually closes the bug :)
clang/lib/Sema/TreeTransform.h
Outdated
QualType T = getDerived().TransformType(E->getType()); | ||
|
||
bool ArgChanged = false; | ||
; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
extra semicolon for no reason?
clang/lib/Sema/TreeTransform.h
Outdated
if (!ArgChanged && T == E->getType()) | ||
return E; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we want to handle AlwaysRebuild?
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 llvm#72880
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 llvm#72880
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 llvm#72880
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 llvm#72880
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