Author: rsmith Date: Fri Aug 30 18:00:37 2019 New Revision: 370558 URL: http://llvm.org/viewvc/llvm-project?rev=370558&view=rev Log: [c++20] Add support for designated direct-list-initialization syntax.
This completes the implementation of P0329R4. Added: cfe/trunk/test/Parser/cxx2a-designated-init.cpp Modified: cfe/trunk/include/clang/AST/Expr.h cfe/trunk/include/clang/Sema/Sema.h cfe/trunk/lib/Parse/ParseInit.cpp cfe/trunk/lib/Sema/SemaInit.cpp cfe/trunk/www/cxx_status.html Modified: cfe/trunk/include/clang/AST/Expr.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Expr.h?rev=370558&r1=370557&r2=370558&view=diff ============================================================================== --- cfe/trunk/include/clang/AST/Expr.h (original) +++ cfe/trunk/include/clang/AST/Expr.h Fri Aug 30 18:00:37 2019 @@ -4831,6 +4831,10 @@ public: SourceLocation getEqualOrColonLoc() const { return EqualOrColonLoc; } void setEqualOrColonLoc(SourceLocation L) { EqualOrColonLoc = L; } + /// Whether this designated initializer should result in direct-initialization + /// of the designated subobject (eg, '{.foo{1, 2, 3}}'). + bool isDirectInit() const { return EqualOrColonLoc.isInvalid(); } + /// Determines whether this designated initializer used the /// deprecated GNU syntax for designated initializers. bool usesGNUSyntax() const { return GNUSyntax; } Modified: cfe/trunk/include/clang/Sema/Sema.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=370558&r1=370557&r2=370558&view=diff ============================================================================== --- cfe/trunk/include/clang/Sema/Sema.h (original) +++ cfe/trunk/include/clang/Sema/Sema.h Fri Aug 30 18:00:37 2019 @@ -4644,7 +4644,7 @@ public: SourceLocation RBraceLoc); ExprResult ActOnDesignatedInitializer(Designation &Desig, - SourceLocation Loc, + SourceLocation EqualOrColonLoc, bool GNUSyntax, ExprResult Init); Modified: cfe/trunk/lib/Parse/ParseInit.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseInit.cpp?rev=370558&r1=370557&r2=370558&view=diff ============================================================================== --- cfe/trunk/lib/Parse/ParseInit.cpp (original) +++ cfe/trunk/lib/Parse/ParseInit.cpp Fri Aug 30 18:00:37 2019 @@ -116,6 +116,8 @@ static void CheckArrayDesignatorSyntax(P /// ParseInitializerWithPotentialDesignator - Parse the 'initializer' production /// checking to see if the token stream starts with a designator. /// +/// C99: +/// /// designation: /// designator-list '=' /// [GNU] array-designator @@ -133,6 +135,21 @@ static void CheckArrayDesignatorSyntax(P /// '[' constant-expression ']' /// [GNU] '[' constant-expression '...' constant-expression ']' /// +/// C++20: +/// +/// designated-initializer-list: +/// designated-initializer-clause +/// designated-initializer-list ',' designated-initializer-clause +/// +/// designated-initializer-clause: +/// designator brace-or-equal-initializer +/// +/// designator: +/// '.' identifier +/// +/// We allow the C99 syntax extensions in C++20, but do not allow the C++20 +/// extension (a braced-init-list after the designator with no '=') in C99. +/// /// NOTE: [OBC] allows '[ objc-receiver objc-message-args ]' as an /// initializer (because it is an expression). We need to consider this case /// when parsing array designators. @@ -365,6 +382,14 @@ ExprResult Parser::ParseInitializerWithP ParseInitializer()); } + // Handle a C++20 braced designated initialization, which results in + // direct-list-initialization of the aggregate element. We allow this as an + // extension from C++11 onwards (when direct-list-initialization was added). + if (Tok.is(tok::l_brace) && getLangOpts().CPlusPlus11) { + return Actions.ActOnDesignatedInitializer(Desig, SourceLocation(), false, + ParseBraceInitializer()); + } + // We read some number of designators and found something that isn't an = or // an initializer. If we have exactly one array designator, this // is the GNU 'designation: array-designator' extension. Otherwise, it is a Modified: cfe/trunk/lib/Sema/SemaInit.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaInit.cpp?rev=370558&r1=370557&r2=370558&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaInit.cpp (original) +++ cfe/trunk/lib/Sema/SemaInit.cpp Fri Aug 30 18:00:37 2019 @@ -2367,6 +2367,29 @@ InitListChecker::CheckDesignatedInitiali bool FinishSubobjectInit, bool TopLevelObject) { if (DesigIdx == DIE->size()) { + // C++20 designated initialization can result in direct-list-initialization + // of the designated subobject. This is the only way that we can end up + // performing direct initialization as part of aggregate initialization, so + // it needs special handling. + if (DIE->isDirectInit()) { + Expr *Init = DIE->getInit(); + assert(isa<InitListExpr>(Init) && + "designator result in direct non-list initialization?"); + InitializationKind Kind = InitializationKind::CreateDirectList( + DIE->getBeginLoc(), Init->getBeginLoc(), Init->getEndLoc()); + InitializationSequence Seq(SemaRef, Entity, Kind, Init, + /*TopLevelOfInitList*/ true); + if (StructuredList) { + ExprResult Result = VerifyOnly + ? getDummyInit() + : Seq.Perform(SemaRef, Entity, Kind, Init); + UpdateStructuredListElement(StructuredList, StructuredIndex, + Result.get()); + } + ++Index; + return !Seq; + } + // Check the actual initialization for the designated object type. bool prevHadError = hadError; @@ -3101,7 +3124,7 @@ CheckArrayDesignatorExpr(Sema &S, Expr * } ExprResult Sema::ActOnDesignatedInitializer(Designation &Desig, - SourceLocation Loc, + SourceLocation EqualOrColonLoc, bool GNUSyntax, ExprResult Init) { typedef DesignatedInitExpr::Designator ASTDesignator; @@ -3189,8 +3212,9 @@ ExprResult Sema::ActOnDesignatedInitiali // Clear out the expressions within the designation. Desig.ClearExprs(*this); - return DesignatedInitExpr::Create(Context, Designators, InitExpressions, Loc, - GNUSyntax, Init.getAs<Expr>()); + return DesignatedInitExpr::Create(Context, Designators, InitExpressions, + EqualOrColonLoc, GNUSyntax, + Init.getAs<Expr>()); } //===----------------------------------------------------------------------===// Added: cfe/trunk/test/Parser/cxx2a-designated-init.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Parser/cxx2a-designated-init.cpp?rev=370558&view=auto ============================================================================== --- cfe/trunk/test/Parser/cxx2a-designated-init.cpp (added) +++ cfe/trunk/test/Parser/cxx2a-designated-init.cpp Fri Aug 30 18:00:37 2019 @@ -0,0 +1,25 @@ +// RUN: %clang_cc1 -std=c++98 -verify=cxx98 %s +// RUN: %clang_cc1 -std=c++11 -verify %s -Wno-c++2a-extensions +// RUN: %clang_cc1 -std=c++2a -verify %s + +struct A { + explicit A(int, int); // expected-note {{here}} +}; + +struct B { + A a; +}; + +B b1 = {.a = {1, 2}}; // cxx98-error {{non-aggregate type 'A' cannot be initialized with an initializer list}} +// expected-error@-1 {{chosen constructor is explicit in copy-initialization}} +B b2 = {.a{1, 2}}; // cxx98-error {{expected '='}} + +struct C { + char x, y; +}; +struct D { + C c; +}; + +D d1 = {.c = {1, 2000}}; // cxx98-warning {{changes value}} expected-error {{narrow}} expected-warning {{changes value}} expected-note {{}} +D d2 = {.c{1, 2000}}; // cxx98-error {{expected '='}} expected-error {{narrow}} expected-warning {{changes value}} expected-note {{}} Modified: cfe/trunk/www/cxx_status.html URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/www/cxx_status.html?rev=370558&r1=370557&r2=370558&view=diff ============================================================================== --- cfe/trunk/www/cxx_status.html (original) +++ cfe/trunk/www/cxx_status.html Fri Aug 30 18:00:37 2019 @@ -871,7 +871,7 @@ as the draft C++2a standard evolves. <tr> <td>Designated initializers</td> <td><a href="http://wg21.link/p0329r4";>P0329R4</a></td> - <td class="partial" align="center">Partial (extension)</td> + <td class="svn" align="center">SVN (Clang 10)</td> </tr> <tr> <td><i>template-parameter-list</i> for generic lambdas</td> _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits