r228897 - More for DR1467: In C++, when initializing an element of an aggregate,

Richard Smith richard-llvm at metafoo.co.uk
Wed Feb 11 17:55:09 PST 2015


Author: rsmith
Date: Wed Feb 11 19:55:09 2015
New Revision: 228897

URL: http://llvm.org/viewvc/llvm-project?rev=228897&view=rev
Log:
More for DR1467: In C++, when initializing an element of an aggregate,
always use the normal copy-initialization rules. Remove a special case that
tries to stay within the list initialization checker here; that makes us do the
wrong thing when list-initialization of an aggregate would not perform
aggregate initialization.

Modified:
    cfe/trunk/lib/Sema/SemaInit.cpp
    cfe/trunk/test/CXX/drs/dr14xx.cpp
    cfe/trunk/test/SemaCXX/atomic-type.cpp

Modified: cfe/trunk/lib/Sema/SemaInit.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaInit.cpp?rev=228897&r1=228896&r2=228897&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaInit.cpp (original)
+++ cfe/trunk/lib/Sema/SemaInit.cpp Wed Feb 11 19:55:09 2015
@@ -966,7 +966,7 @@ void InitListChecker::CheckSubElementTyp
                               StructuredList, StructuredIndex);
 
   if (InitListExpr *SubInitList = dyn_cast<InitListExpr>(expr)) {
-    if (!ElemType->isRecordType() || ElemType->isAggregateType()) {
+    if (!SemaRef.getLangOpts().CPlusPlus) {
       InitListExpr *InnerStructuredList
         = getStructuredSubobjectInit(IList, Index, ElemType,
                                      StructuredList, StructuredIndex,
@@ -977,8 +977,6 @@ void InitListChecker::CheckSubElementTyp
       ++Index;
       return;
     }
-    assert(SemaRef.getLangOpts().CPlusPlus &&
-           "non-aggregate records are only possible in C++");
     // C++ initialization is handled later.
   } else if (isa<ImplicitValueInitExpr>(expr)) {
     // This happens during template instantiation when we see an InitListExpr
@@ -991,43 +989,24 @@ void InitListChecker::CheckSubElementTyp
     return;
   }
 
-  // FIXME: Need to handle atomic aggregate types with implicit init lists.
-  if (ElemType->isScalarType() || ElemType->isAtomicType())
-    return CheckScalarType(Entity, IList, ElemType, Index,
-                           StructuredList, StructuredIndex);
-
-  assert((ElemType->isRecordType() || ElemType->isVectorType() ||
-          ElemType->isArrayType()) && "Unexpected type");
-
-  if (const ArrayType *arrayType = SemaRef.Context.getAsArrayType(ElemType)) {
-    // arrayType can be incomplete if we're initializing a flexible
-    // array member.  There's nothing we can do with the completed
-    // type here, though.
-
-    if (IsStringInit(expr, arrayType, SemaRef.Context) == SIF_None) {
-      if (!VerifyOnly) {
-        CheckStringInit(expr, ElemType, arrayType, SemaRef);
-        UpdateStructuredListElement(StructuredList, StructuredIndex, expr);
-      }
-      ++Index;
-      return;
-    }
-
-    // Fall through for subaggregate initialization.
-
-  } else if (SemaRef.getLangOpts().CPlusPlus) {
-    // C++ [dcl.init.aggr]p12:
-    //   All implicit type conversions (clause 4) are considered when
-    //   initializing the aggregate member with an initializer from
-    //   an initializer-list. If the initializer can initialize a
-    //   member, the member is initialized. [...]
+  if (SemaRef.getLangOpts().CPlusPlus) {
+    // C++ [dcl.init.aggr]p2:
+    //   Each member is copy-initialized from the corresponding
+    //   initializer-clause.
 
     // FIXME: Better EqualLoc?
     InitializationKind Kind =
       InitializationKind::CreateCopy(expr->getLocStart(), SourceLocation());
-    InitializationSequence Seq(SemaRef, Entity, Kind, expr);
+    InitializationSequence Seq(SemaRef, Entity, Kind, expr,
+                               /*TopLevelOfInitList*/ true);
 
-    if (Seq) {
+    // C++14 [dcl.init.aggr]p13:
+    //   If the assignment-expression can initialize a member, the member is
+    //   initialized. Otherwise [...] brace elision is assumed
+    //
+    // Brace elision is never performed if the element is not an
+    // assignment-expression.
+    if (Seq || isa<InitListExpr>(expr)) {
       if (!VerifyOnly) {
         ExprResult Result =
           Seq.Perform(SemaRef, Entity, Kind, expr);
@@ -1042,7 +1021,31 @@ void InitListChecker::CheckSubElementTyp
     }
 
     // Fall through for subaggregate initialization
+  } else if (ElemType->isScalarType() || ElemType->isAtomicType()) {
+    // FIXME: Need to handle atomic aggregate types with implicit init lists.
+    return CheckScalarType(Entity, IList, ElemType, Index,
+                           StructuredList, StructuredIndex);
+  } else if (const ArrayType *arrayType =
+                 SemaRef.Context.getAsArrayType(ElemType)) {
+    // arrayType can be incomplete if we're initializing a flexible
+    // array member.  There's nothing we can do with the completed
+    // type here, though.
+
+    if (IsStringInit(expr, arrayType, SemaRef.Context) == SIF_None) {
+      if (!VerifyOnly) {
+        CheckStringInit(expr, ElemType, arrayType, SemaRef);
+        UpdateStructuredListElement(StructuredList, StructuredIndex, expr);
+      }
+      ++Index;
+      return;
+    }
+
+    // Fall through for subaggregate initialization.
+
   } else {
+    assert((ElemType->isRecordType() || ElemType->isVectorType()) &&
+           "Unexpected type");
+
     // C99 6.7.8p13:
     //
     //   The initializer for a structure or union object that has
@@ -1052,10 +1055,8 @@ void InitListChecker::CheckSubElementTyp
     //   initial value of the object, including unnamed members, is
     //   that of the expression.
     ExprResult ExprRes = expr;
-    if ((ElemType->isRecordType() || ElemType->isVectorType()) &&
-        SemaRef.CheckSingleAssignmentConstraints(ElemType, ExprRes,
-                                                 !VerifyOnly)
-          != Sema::Incompatible) {
+    if (SemaRef.CheckSingleAssignmentConstraints(
+            ElemType, ExprRes, !VerifyOnly) != Sema::Incompatible) {
       if (ExprRes.isInvalid())
         hadError = true;
       else {

Modified: cfe/trunk/test/CXX/drs/dr14xx.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/drs/dr14xx.cpp?rev=228897&r1=228896&r2=228897&view=diff
==============================================================================
--- cfe/trunk/test/CXX/drs/dr14xx.cpp (original)
+++ cfe/trunk/test/CXX/drs/dr14xx.cpp Wed Feb 11 19:55:09 2015
@@ -324,6 +324,9 @@ namespace dr1467 {  // dr1467: 3.7 c++11
     S s1;
     S s2 = {s1}; // ok, not list-initialization so we pick the non-explicit constructor
   }
+
+  struct NestedInit { int a, b, c; };
+  NestedInit ni[1] = {{NestedInit{1, 2, 3}}};
 } // dr1467
 
 namespace dr1490 {  // dr1490: 3.7 c++11

Modified: cfe/trunk/test/SemaCXX/atomic-type.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/atomic-type.cpp?rev=228897&r1=228896&r2=228897&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/atomic-type.cpp (original)
+++ cfe/trunk/test/SemaCXX/atomic-type.cpp Wed Feb 11 19:55:09 2015
@@ -71,6 +71,8 @@ namespace copy_init {
 #if __cplusplus >= 201103L
   _Atomic(X) e2{0}; // expected-error {{illegal initializer}}
   _Atomic(X) a{X(0)};
+  // FIXME: This does not seem like the right answer.
+  _Atomic(int) e3{0}; // expected-error {{illegal initializer}}
 #endif
 
   struct Y {
@@ -79,9 +81,14 @@ namespace copy_init {
   };
   Y y1 = { X(0), 4 };
   Y y2 = { 0, 4 }; // expected-error {{cannot initialize}}
+
   // FIXME: It's not really clear if we should allow these. Generally, C++11
-  // allows extraneous braces around initializers.
-  Y y3 = { { X(0) }, { 4 } }; // expected-error 2{{illegal initializer type}}
+  // allows extraneous braces around initializers. We should at least give the
+  // same answer in all these cases:
+  Y y3 = { X(0), { 4 } }; // expected-error {{illegal initializer type}}
+  Y y4 = { { X(0) }, 4 };
+  _Atomic(int) ai = { 4 }; // expected-error {{illegal initializer type}}
+  _Atomic(X) ax = { X(0) };
 }
 
 bool PR21836(_Atomic(int) *x) {





More information about the cfe-commits mailing list