r370558 - [c++20] Add support for designated direct-list-initialization syntax.

Richard Smith via cfe-commits cfe-commits at lists.llvm.org
Fri Aug 30 18:00:38 PDT 2019


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 at -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>




More information about the cfe-commits mailing list