Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions clang/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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
^^^^^^^^^^^^^^^^^^^^^^^^^
Expand Down
4 changes: 2 additions & 2 deletions clang/include/clang/AST/ExprCXX.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
5 changes: 5 additions & 0 deletions clang/include/clang/Sema/Sema.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
9 changes: 9 additions & 0 deletions clang/lib/Sema/SemaExpr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
32 changes: 28 additions & 4 deletions clang/lib/Sema/TreeTransform.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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;
;
Copy link
Collaborator

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?


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;
Copy link
Contributor

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?


return getDerived().RebuildCXXParenListInitExpr(
TransformedInits, T, E->getUserSpecifiedInitExprs().size(),
E->getInitLoc(), E->getBeginLoc(), E->getEndLoc());
}

template<typename Derived>
Expand Down
37 changes: 32 additions & 5 deletions clang/test/SemaCXX/paren-list-agg-init.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down Expand Up @@ -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}}

Expand Down Expand Up @@ -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}}

}

Expand All @@ -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}}
}
}