r210091 - Implement DR990 and DR1070. Aggregate initialization initializes uninitialized

Richard Smith richard-llvm at metafoo.co.uk
Tue Jun 3 01:26:01 PDT 2014


Author: rsmith
Date: Tue Jun  3 03:26:00 2014
New Revision: 210091

URL: http://llvm.org/viewvc/llvm-project?rev=210091&view=rev
Log:
Implement DR990 and DR1070. Aggregate initialization initializes uninitialized
elements from {}, rather than value-initializing them. This permits calling an
initializer-list constructor or constructing a std::initializer_list object.
(It would also permit initializing a const reference or rvalue reference if
that weren't explicitly prohibited by other rules.)

Added:
    cfe/trunk/test/CXX/drs/dr10xx.cpp
    cfe/trunk/test/CXX/drs/dr9xx.cpp
Modified:
    cfe/trunk/include/clang/AST/Expr.h
    cfe/trunk/include/clang/Sema/Initialization.h
    cfe/trunk/lib/CodeGen/CGExprCXX.cpp
    cfe/trunk/lib/Sema/SemaInit.cpp
    cfe/trunk/test/CodeGenCXX/cxx0x-initializer-stdinitializerlist.cpp
    cfe/trunk/test/CodeGenCXX/cxx1y-initializer-aggregate.cpp
    cfe/trunk/test/SemaCXX/cxx0x-initializer-constructor.cpp
    cfe/trunk/test/SemaCXX/cxx0x-initializer-stdinitializerlist.cpp
    cfe/trunk/www/cxx_dr_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=210091&r1=210090&r2=210091&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/Expr.h (original)
+++ cfe/trunk/include/clang/AST/Expr.h Tue Jun  3 03:26:00 2014
@@ -3909,6 +3909,7 @@ public:
 
   // Iterators
   child_range children() {
+    // FIXME: This does not include the array filler expression.
     if (InitExprs.empty()) return child_range();
     return child_range(&InitExprs[0], &InitExprs[0] + InitExprs.size());
   }

Modified: cfe/trunk/include/clang/Sema/Initialization.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Initialization.h?rev=210091&r1=210090&r2=210091&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Initialization.h (original)
+++ cfe/trunk/include/clang/Sema/Initialization.h Tue Jun  3 03:26:00 2014
@@ -401,6 +401,13 @@ public:
     return SourceLocation::getFromRawEncoding(LocAndNRVO.Location);
   }
 
+  /// \brief If this is an array, vector, or complex number element, get the
+  /// element's index.
+  unsigned getElementIndex() const {
+    assert(getKind() == EK_ArrayElement || getKind() == EK_VectorElement ||
+           getKind() == EK_ComplexElement);
+    return Index;
+  }
   /// \brief If this is already the initializer for an array or vector
   /// element, sets the element index.
   void setElementIndex(unsigned Index) {
@@ -851,17 +858,17 @@ public:
   ///
   /// \param Args the argument(s) provided for initialization.
   ///
-  /// \param InInitList true if we are initializing from an expression within
-  ///        an initializer list. This disallows narrowing conversions in C++11
-  ///        onwards.
+  /// \param TopLevelOfInitList true if we are initializing from an expression
+  ///        at the top level inside an initializer list. This disallows
+  ///        narrowing conversions in C++11 onwards.
   InitializationSequence(Sema &S, 
                          const InitializedEntity &Entity,
                          const InitializationKind &Kind,
                          MultiExprArg Args,
-                         bool InInitList = false);
+                         bool TopLevelOfInitList = false);
   void InitializeFrom(Sema &S, const InitializedEntity &Entity,
                       const InitializationKind &Kind, MultiExprArg Args,
-                      bool InInitList);
+                      bool TopLevelOfInitList);
 
   ~InitializationSequence();
   

Modified: cfe/trunk/lib/CodeGen/CGExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprCXX.cpp?rev=210091&r1=210090&r2=210091&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGExprCXX.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExprCXX.cpp Tue Jun  3 03:26:00 2014
@@ -858,9 +858,21 @@ CodeGenFunction::EmitNewArrayInitializer
     return true;
   };
 
+  // If all elements have already been initialized, skip any further
+  // initialization.
+  llvm::ConstantInt *ConstNum = dyn_cast<llvm::ConstantInt>(NumElements);
+  if (ConstNum && ConstNum->getZExtValue() <= InitListElements) {
+    // If there was a Cleanup, deactivate it.
+    if (CleanupDominator)
+      DeactivateCleanupBlock(Cleanup, CleanupDominator);
+    return;
+  }
+
+  assert(Init && "have trailing elements to initialize but no initializer");
+
   // If this is a constructor call, try to optimize it out, and failing that
   // emit a single loop to initialize all remaining elements.
-  if (const CXXConstructExpr *CCE = dyn_cast_or_null<CXXConstructExpr>(Init)){
+  if (const CXXConstructExpr *CCE = dyn_cast<CXXConstructExpr>(Init)) {
     CXXConstructorDecl *Ctor = CCE->getConstructor();
     if (Ctor->isTrivial()) {
       // If new expression did not specify value-initialization, then there
@@ -891,7 +903,7 @@ CodeGenFunction::EmitNewArrayInitializer
 
   // If this is value-initialization, we can usually use memset.
   ImplicitValueInitExpr IVIE(ElementType);
-  if (Init && isa<ImplicitValueInitExpr>(Init)) {
+  if (isa<ImplicitValueInitExpr>(Init)) {
     if (TryMemsetInitialization())
       return;
 
@@ -906,15 +918,10 @@ CodeGenFunction::EmitNewArrayInitializer
   assert(getContext().hasSameUnqualifiedType(ElementType, Init->getType()) &&
          "got wrong type of element to initialize");
 
-  llvm::ConstantInt *ConstNum = dyn_cast<llvm::ConstantInt>(NumElements);
-
-  // If all elements have already been initialized, skip the whole loop.
-  if (ConstNum && ConstNum->getZExtValue() <= InitListElements) {
-    // If there was a Cleanup, deactivate it.
-    if (CleanupDominator)
-      DeactivateCleanupBlock(Cleanup, CleanupDominator);
-    return;
-  }
+  // If we have an empty initializer list, we can usually use memset.
+  if (auto *ILE = dyn_cast<InitListExpr>(Init))
+    if (ILE->getNumInits() == 0 && TryMemsetInitialization())
+      return;
 
   // Create the loop blocks.
   llvm::BasicBlock *EntryBB = Builder.GetInsertBlock();

Modified: cfe/trunk/lib/Sema/SemaInit.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaInit.cpp?rev=210091&r1=210090&r2=210091&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaInit.cpp (original)
+++ cfe/trunk/lib/Sema/SemaInit.cpp Tue Jun  3 03:26:00 2014
@@ -312,15 +312,20 @@ class InitListChecker {
   int numArrayElements(QualType DeclType);
   int numStructUnionElements(QualType DeclType);
 
-  void FillInValueInitForField(unsigned Init, FieldDecl *Field,
+  static ExprResult PerformEmptyInit(Sema &SemaRef,
+                                     SourceLocation Loc,
+                                     const InitializedEntity &Entity,
+                                     bool VerifyOnly);
+  void FillInEmptyInitForField(unsigned Init, FieldDecl *Field,
                                const InitializedEntity &ParentEntity,
                                InitListExpr *ILE, bool &RequiresSecondPass);
-  void FillInValueInitializations(const InitializedEntity &Entity,
+  void FillInEmptyInitializations(const InitializedEntity &Entity,
                                   InitListExpr *ILE, bool &RequiresSecondPass);
   bool CheckFlexibleArrayInit(const InitializedEntity &Entity,
                               Expr *InitExpr, FieldDecl *Field,
                               bool TopLevelObject);
-  void CheckValueInitializable(const InitializedEntity &Entity);
+  void CheckEmptyInitializable(const InitializedEntity &Entity,
+                               SourceLocation Loc);
 
 public:
   InitListChecker(Sema &S, const InitializedEntity &Entity,
@@ -333,33 +338,84 @@ public:
 };
 } // end anonymous namespace
 
-void InitListChecker::CheckValueInitializable(const InitializedEntity &Entity) {
-  assert(VerifyOnly &&
-         "CheckValueInitializable is only inteded for verification mode.");
-
-  SourceLocation Loc;
+ExprResult InitListChecker::PerformEmptyInit(Sema &SemaRef,
+                                             SourceLocation Loc,
+                                             const InitializedEntity &Entity,
+                                             bool VerifyOnly) {
   InitializationKind Kind = InitializationKind::CreateValue(Loc, Loc, Loc,
                                                             true);
-  InitializationSequence InitSeq(SemaRef, Entity, Kind, None);
-  if (InitSeq.Failed())
+  MultiExprArg SubInit;
+  Expr *InitExpr;
+  InitListExpr DummyInitList(SemaRef.Context, Loc, None, Loc);
+
+  // C++ [dcl.init.aggr]p7:
+  //   If there are fewer initializer-clauses in the list than there are
+  //   members in the aggregate, then each member not explicitly initialized
+  //   ...
+  if (SemaRef.getLangOpts().CPlusPlus11 &&
+      Entity.getType()->getBaseElementTypeUnsafe()->isRecordType()) {
+    // C++1y / DR1070:
+    //   shall be initialized [...] from an empty initializer list.
+    //
+    // We apply the resolution of this DR to C++11 but not C++98, since C++98
+    // does not have useful semantics for initialization from an init list.
+    // We treat this as copy-initialization, because aggregate initialization
+    // always performs copy-initialization on its elements.
+    //
+    // Only do this if we're initializing a class type, to avoid filling in
+    // the initializer list where possible.
+    InitExpr = VerifyOnly ? &DummyInitList : new (SemaRef.Context)
+                   InitListExpr(SemaRef.Context, Loc, None, Loc);
+    InitExpr->setType(SemaRef.Context.VoidTy);
+    SubInit = InitExpr;
+    Kind = InitializationKind::CreateCopy(Loc, Loc);
+  } else {
+    // C++03:
+    //   shall be value-initialized.
+  }
+
+  InitializationSequence InitSeq(SemaRef, Entity, Kind, SubInit);
+  if (!InitSeq) {
+    if (!VerifyOnly) {
+      InitSeq.Diagnose(SemaRef, Entity, Kind, SubInit);
+      if (Entity.getKind() == InitializedEntity::EK_Member)
+        SemaRef.Diag(Entity.getDecl()->getLocation(),
+                     diag::note_in_omitted_aggregate_initializer)
+          << /*field*/1 << Entity.getDecl();
+      else if (Entity.getKind() == InitializedEntity::EK_ArrayElement)
+        SemaRef.Diag(Loc, diag::note_in_omitted_aggregate_initializer)
+          << /*array element*/0 << Entity.getElementIndex();
+    }
+    return ExprError();
+  }
+
+  return VerifyOnly ? ExprResult(static_cast<Expr *>(nullptr))
+                    : InitSeq.Perform(SemaRef, Entity, Kind, SubInit);
+}
+
+void InitListChecker::CheckEmptyInitializable(const InitializedEntity &Entity,
+                                              SourceLocation Loc) {
+  assert(VerifyOnly &&
+         "CheckEmptyInitializable is only inteded for verification mode.");
+  if (PerformEmptyInit(SemaRef, Loc, Entity, /*VerifyOnly*/true).isInvalid())
     hadError = true;
 }
 
-void InitListChecker::FillInValueInitForField(unsigned Init, FieldDecl *Field,
+void InitListChecker::FillInEmptyInitForField(unsigned Init, FieldDecl *Field,
                                         const InitializedEntity &ParentEntity,
                                               InitListExpr *ILE,
                                               bool &RequiresSecondPass) {
-  SourceLocation Loc = ILE->getLocStart();
+  SourceLocation Loc = ILE->getLocEnd();
   unsigned NumInits = ILE->getNumInits();
   InitializedEntity MemberEntity
     = InitializedEntity::InitializeMember(Field, &ParentEntity);
   if (Init >= NumInits || !ILE->getInit(Init)) {
-    // If there's no explicit initializer but we have a default initializer, use
-    // that. This only happens in C++1y, since classes with default
-    // initializers are not aggregates in C++11.
+    // C++1y [dcl.init.aggr]p7:
+    //   If there are fewer initializer-clauses in the list than there are
+    //   members in the aggregate, then each member not explicitly initialized
+    //   shall be initialized from its brace-or-equal-initializer [...]
     if (Field->hasInClassInitializer()) {
-      Expr *DIE = CXXDefaultInitExpr::Create(SemaRef.Context,
-                                             ILE->getRBraceLoc(), Field);
+      Expr *DIE = CXXDefaultInitExpr::Create(SemaRef.Context, Loc, Field);
       if (Init < NumInits)
         ILE->setInit(Init, DIE);
       else {
@@ -369,9 +425,6 @@ void InitListChecker::FillInValueInitFor
       return;
     }
 
-    // FIXME: We probably don't need to handle references
-    // specially here, since value-initialization of references is
-    // handled in InitializationSequence.
     if (Field->getType()->isReferenceType()) {
       // C++ [dcl.init.aggr]p9:
       //   If an incomplete or empty initializer-list leaves a
@@ -386,20 +439,8 @@ void InitListChecker::FillInValueInitFor
       return;
     }
 
-    InitializationKind Kind = InitializationKind::CreateValue(Loc, Loc, Loc,
-                                                              true);
-    InitializationSequence InitSeq(SemaRef, MemberEntity, Kind, None);
-    if (!InitSeq) {
-      InitSeq.Diagnose(SemaRef, MemberEntity, Kind, None);
-      SemaRef.Diag(Field->getLocation(),
-                   diag::note_in_omitted_aggregate_initializer)
-        << /*field*/1 << Field;
-      hadError = true;
-      return;
-    }
-
-    ExprResult MemberInit
-      = InitSeq.Perform(SemaRef, MemberEntity, Kind, None);
+    ExprResult MemberInit = PerformEmptyInit(SemaRef, Loc, MemberEntity,
+                                             /*VerifyOnly*/false);
     if (MemberInit.isInvalid()) {
       hadError = true;
       return;
@@ -409,8 +450,8 @@ void InitListChecker::FillInValueInitFor
       // Do nothing
     } else if (Init < NumInits) {
       ILE->setInit(Init, MemberInit.getAs<Expr>());
-    } else if (InitSeq.isConstructorInitialization()) {
-      // Value-initialization requires a constructor call, so
+    } else if (!isa<ImplicitValueInitExpr>(MemberInit.get())) {
+      // Empty initialization requires a constructor call, so
       // extend the initializer list to include the constructor
       // call and make a note that we'll need to take another pass
       // through the initializer list.
@@ -419,7 +460,7 @@ void InitListChecker::FillInValueInitFor
     }
   } else if (InitListExpr *InnerILE
                = dyn_cast<InitListExpr>(ILE->getInit(Init)))
-    FillInValueInitializations(MemberEntity, InnerILE,
+    FillInEmptyInitializations(MemberEntity, InnerILE,
                                RequiresSecondPass);
 }
 
@@ -427,7 +468,7 @@ void InitListChecker::FillInValueInitFor
 /// with expressions that perform value-initialization of the
 /// appropriate type.
 void
-InitListChecker::FillInValueInitializations(const InitializedEntity &Entity,
+InitListChecker::FillInEmptyInitializations(const InitializedEntity &Entity,
                                             InitListExpr *ILE,
                                             bool &RequiresSecondPass) {
   assert((ILE->getType() != SemaRef.Context.VoidTy) &&
@@ -436,13 +477,13 @@ InitListChecker::FillInValueInitializati
   if (const RecordType *RType = ILE->getType()->getAs<RecordType>()) {
     const RecordDecl *RDecl = RType->getDecl();
     if (RDecl->isUnion() && ILE->getInitializedFieldInUnion())
-      FillInValueInitForField(0, ILE->getInitializedFieldInUnion(),
+      FillInEmptyInitForField(0, ILE->getInitializedFieldInUnion(),
                               Entity, ILE, RequiresSecondPass);
     else if (RDecl->isUnion() && isa<CXXRecordDecl>(RDecl) &&
              cast<CXXRecordDecl>(RDecl)->hasInClassInitializer()) {
       for (auto *Field : RDecl->fields()) {
         if (Field->hasInClassInitializer()) {
-          FillInValueInitForField(0, Field, Entity, ILE, RequiresSecondPass);
+          FillInEmptyInitForField(0, Field, Entity, ILE, RequiresSecondPass);
           break;
         }
       }
@@ -455,7 +496,7 @@ InitListChecker::FillInValueInitializati
         if (hadError)
           return;
 
-        FillInValueInitForField(Init, Field, Entity, ILE, RequiresSecondPass);
+        FillInEmptyInitForField(Init, Field, Entity, ILE, RequiresSecondPass);
         if (hadError)
           return;
 
@@ -489,10 +530,6 @@ InitListChecker::FillInValueInitializati
   } else
     ElementType = ILE->getType();
 
-  SourceLocation Loc = ILE->getLocEnd();
-  if (ILE->getSyntacticForm())
-    Loc = ILE->getSyntacticForm()->getLocEnd();
-
   for (unsigned Init = 0; Init != NumElements; ++Init) {
     if (hadError)
       return;
@@ -503,19 +540,9 @@ InitListChecker::FillInValueInitializati
 
     Expr *InitExpr = (Init < NumInits ? ILE->getInit(Init) : nullptr);
     if (!InitExpr && !ILE->hasArrayFiller()) {
-      InitializationKind Kind = InitializationKind::CreateValue(Loc, Loc, Loc,
-                                                                true);
-      InitializationSequence InitSeq(SemaRef, ElementEntity, Kind, None);
-      if (!InitSeq) {
-        InitSeq.Diagnose(SemaRef, ElementEntity, Kind, None);
-        SemaRef.Diag(Loc, diag::note_in_omitted_aggregate_initializer)
-          << /*array element*/0 << Init;
-        hadError = true;
-        return;
-      }
-
-      ExprResult ElementInit
-        = InitSeq.Perform(SemaRef, ElementEntity, Kind, None);
+      ExprResult ElementInit = PerformEmptyInit(SemaRef, ILE->getLocEnd(),
+                                                ElementEntity,
+                                                /*VerifyOnly*/false);
       if (ElementInit.isInvalid()) {
         hadError = true;
         return;
@@ -538,8 +565,8 @@ InitListChecker::FillInValueInitializati
           return;
         }
 
-        if (InitSeq.isConstructorInitialization()) {
-          // Value-initialization requires a constructor call, so
+        if (!isa<ImplicitValueInitExpr>(ElementInit.get())) {
+          // Empty initialization requires a constructor call, so
           // extend the initializer list to include the constructor
           // call and make a note that we'll need to take another pass
           // through the initializer list.
@@ -549,7 +576,7 @@ InitListChecker::FillInValueInitializati
       }
     } else if (InitListExpr *InnerILE
                  = dyn_cast_or_null<InitListExpr>(InitExpr))
-      FillInValueInitializations(ElementEntity, InnerILE, RequiresSecondPass);
+      FillInEmptyInitializations(ElementEntity, InnerILE, RequiresSecondPass);
   }
 }
 
@@ -567,9 +594,9 @@ InitListChecker::InitListChecker(Sema &S
 
   if (!hadError && !VerifyOnly) {
     bool RequiresSecondPass = false;
-    FillInValueInitializations(Entity, FullyStructuredList, RequiresSecondPass);
+    FillInEmptyInitializations(Entity, FullyStructuredList, RequiresSecondPass);
     if (RequiresSecondPass && !hadError)
-      FillInValueInitializations(Entity, FullyStructuredList,
+      FillInEmptyInitializations(Entity, FullyStructuredList,
                                  RequiresSecondPass);
   }
 }
@@ -678,7 +705,6 @@ void InitListChecker::CheckExplicitInitL
                                             InitListExpr *IList, QualType &T,
                                             InitListExpr *StructuredList,
                                             bool TopLevelObject) {
-  assert(IList->isExplicit() && "Illegal Implicit InitListExpr");
   if (!VerifyOnly) {
     SyntacticToSemantic[IList] = StructuredList;
     StructuredList->setSyntacticForm(IList);
@@ -1121,8 +1147,9 @@ void InitListChecker::CheckVectorType(co
   if (Index >= IList->getNumInits()) {
     // Make sure the element type can be value-initialized.
     if (VerifyOnly)
-      CheckValueInitializable(
-          InitializedEntity::InitializeElement(SemaRef.Context, 0, Entity));
+      CheckEmptyInitializable(
+          InitializedEntity::InitializeElement(SemaRef.Context, 0, Entity),
+          IList->getLocEnd());
     return;
   }
 
@@ -1169,7 +1196,7 @@ void InitListChecker::CheckVectorType(co
       // Don't attempt to go past the end of the init list
       if (Index >= IList->getNumInits()) {
         if (VerifyOnly)
-          CheckValueInitializable(ElementEntity);
+          CheckEmptyInitializable(ElementEntity, IList->getLocEnd());
         break;
       }
 
@@ -1346,8 +1373,9 @@ void InitListChecker::CheckArrayType(con
     // If so, check if doing that is possible.
     // FIXME: This needs to detect holes left by designated initializers too.
     if (maxElementsKnown && elementIndex < maxElements)
-      CheckValueInitializable(InitializedEntity::InitializeElement(
-                                                  SemaRef.Context, 0, Entity));
+      CheckEmptyInitializable(InitializedEntity::InitializeElement(
+                                                  SemaRef.Context, 0, Entity),
+                              IList->getLocEnd());
   }
 }
 
@@ -1432,8 +1460,9 @@ void InitListChecker::CheckStructUnionTy
          Field != FieldEnd; ++Field) {
       if (Field->getDeclName()) {
         if (VerifyOnly)
-          CheckValueInitializable(
-              InitializedEntity::InitializeMember(*Field, &Entity));
+          CheckEmptyInitializable(
+              InitializedEntity::InitializeMember(*Field, &Entity),
+              IList->getLocEnd());
         else
           StructuredList->setInitializedFieldInUnion(*Field);
         break;
@@ -1545,8 +1574,9 @@ void InitListChecker::CheckStructUnionTy
     // FIXME: Should check for holes left by designated initializers too.
     for (; Field != FieldEnd && !hadError; ++Field) {
       if (!Field->isUnnamedBitfield() && !Field->hasInClassInitializer())
-        CheckValueInitializable(
-            InitializedEntity::InitializeMember(*Field, &Entity));
+        CheckEmptyInitializable(
+            InitializedEntity::InitializeMember(*Field, &Entity),
+            IList->getLocEnd());
     }
   }
 

Added: cfe/trunk/test/CXX/drs/dr10xx.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/drs/dr10xx.cpp?rev=210091&view=auto
==============================================================================
--- cfe/trunk/test/CXX/drs/dr10xx.cpp (added)
+++ cfe/trunk/test/CXX/drs/dr10xx.cpp Tue Jun  3 03:26:00 2014
@@ -0,0 +1,33 @@
+// RUN: %clang_cc1 -std=c++98 %s -verify -fexceptions -fcxx-exceptions -pedantic-errors
+// RUN: %clang_cc1 -std=c++11 %s -verify -fexceptions -fcxx-exceptions -pedantic-errors
+// RUN: %clang_cc1 -std=c++1y %s -verify -fexceptions -fcxx-exceptions -pedantic-errors
+
+// expected-no-diagnostics
+
+namespace std {
+  __extension__ typedef __SIZE_TYPE__ size_t;
+
+  template<typename T> struct initializer_list {
+    const T *p; size_t n;
+    initializer_list(const T *p, size_t n);
+  };
+}
+
+namespace dr1070 { // dr1070: 3.5
+#if __cplusplus >= 201103L
+  struct A {
+    A(std::initializer_list<int>);
+  };
+  struct B {
+    int i;
+    A a;
+  };
+  B b = {1};
+  struct C {
+    std::initializer_list<int> a;
+    B b;
+    std::initializer_list<double> c;
+  };
+  C c = {};
+#endif
+}

Added: cfe/trunk/test/CXX/drs/dr9xx.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/drs/dr9xx.cpp?rev=210091&view=auto
==============================================================================
--- cfe/trunk/test/CXX/drs/dr9xx.cpp (added)
+++ cfe/trunk/test/CXX/drs/dr9xx.cpp Tue Jun  3 03:26:00 2014
@@ -0,0 +1,45 @@
+// RUN: %clang_cc1 -std=c++98 %s -verify -fexceptions -fcxx-exceptions -pedantic-errors
+// RUN: %clang_cc1 -std=c++11 %s -verify -fexceptions -fcxx-exceptions -pedantic-errors
+// RUN: %clang_cc1 -std=c++1y %s -verify -fexceptions -fcxx-exceptions -pedantic-errors
+
+#if __cplusplus < 201103L
+// expected-no-diagnostics
+#endif
+
+namespace std {
+  __extension__ typedef __SIZE_TYPE__ size_t;
+
+  template<typename T> struct initializer_list {
+    const T *p; size_t n;
+    initializer_list(const T *p, size_t n);
+  };
+}
+
+namespace dr990 { // dr990: 3.5
+#if __cplusplus >= 201103L
+  struct A { // expected-note 2{{candidate}}
+    A(std::initializer_list<int>); // expected-note {{candidate}}
+  };
+  struct B {
+    A a;
+  };
+  B b1 { };
+  B b2 { 1 }; // expected-error {{no viable conversion from 'int' to 'dr990::A'}}
+  B b3 { { 1 } };
+
+  struct C {
+    C();
+    C(int);
+    C(std::initializer_list<int>) = delete; // expected-note {{here}}
+  };
+  C c1[3] { 1 }; // ok
+  C c2[3] { 1, {2} }; // expected-error {{call to deleted}}
+
+  struct D {
+    D();
+    D(std::initializer_list<int>);
+    D(std::initializer_list<double>);
+  };
+  D d{};
+#endif
+}

Modified: cfe/trunk/test/CodeGenCXX/cxx0x-initializer-stdinitializerlist.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/cxx0x-initializer-stdinitializerlist.cpp?rev=210091&r1=210090&r2=210091&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/cxx0x-initializer-stdinitializerlist.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/cxx0x-initializer-stdinitializerlist.cpp Tue Jun  3 03:26:00 2014
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -std=c++11 -S -triple x86_64-none-linux-gnu -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -std=c++11 -triple x86_64-none-linux-gnu -emit-llvm -o - %s | FileCheck %s
 
 namespace std {
   typedef decltype(sizeof(int)) size_t;
@@ -431,3 +431,20 @@ namespace nested {
     // CHECK: }
   }
 }
+
+namespace DR1070 {
+  struct A {
+    A(std::initializer_list<int>);
+  };
+  struct B {
+    int i;
+    A a;
+  };
+  B b = {1};
+  struct C {
+    std::initializer_list<int> a;
+    B b;
+    std::initializer_list<double> c;
+  };
+  C c = {};
+}

Modified: cfe/trunk/test/CodeGenCXX/cxx1y-initializer-aggregate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/cxx1y-initializer-aggregate.cpp?rev=210091&r1=210090&r2=210091&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/cxx1y-initializer-aggregate.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/cxx1y-initializer-aggregate.cpp Tue Jun  3 03:26:00 2014
@@ -46,7 +46,7 @@ B z { 1 };
 // CHECK: store i8 %{{.*}}, i8* getelementptr inbounds ({{.*}} @a, i32 0, i32 2)
 // CHECK: call i32 @_ZN1A1fEv({{.*}} @a)
 // CHECK: store i32 %{{.*}}, i32* getelementptr inbounds ({{.*}}* @a, i32 0, i32 3)
-// CHECK: call void @{{.*}}C1Ev({{.*}} getelementptr inbounds (%struct.A* @a, i32 0, i32 4))
+// CHECK: store double 1.000000e+00, double* getelementptr inbounds ({{.*}} @a, i32 0, i32 4, i32 0)
 
 // No dynamic initialization of 'b':
 

Modified: cfe/trunk/test/SemaCXX/cxx0x-initializer-constructor.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/cxx0x-initializer-constructor.cpp?rev=210091&r1=210090&r2=210091&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/cxx0x-initializer-constructor.cpp (original)
+++ cfe/trunk/test/SemaCXX/cxx0x-initializer-constructor.cpp Tue Jun  3 03:26:00 2014
@@ -389,8 +389,8 @@ namespace PR11410 {
 
   struct B {
     A a; // expected-note {{in implicit initialization of field 'a'}}
-  } b = { // expected-error {{call to deleted constructor}}
-  };
+  } b = {
+  }; // expected-error {{call to deleted constructor}}
 
   struct C {
     C(int = 0); // expected-note 2{{candidate}}

Modified: cfe/trunk/test/SemaCXX/cxx0x-initializer-stdinitializerlist.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/cxx0x-initializer-stdinitializerlist.cpp?rev=210091&r1=210090&r2=210091&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/cxx0x-initializer-stdinitializerlist.cpp (original)
+++ cfe/trunk/test/SemaCXX/cxx0x-initializer-stdinitializerlist.cpp Tue Jun  3 03:26:00 2014
@@ -230,3 +230,11 @@ namespace PR18013 {
   int f();
   std::initializer_list<long (*)()> x = {f}; // expected-error {{cannot initialize an array element of type 'long (*const)()' with an lvalue of type 'int ()': different return type ('long' vs 'int')}}
 }
+
+namespace DR1070 {
+  struct S {
+    S(std::initializer_list<int>);
+  };
+  S s[3] = { {1, 2, 3}, {4, 5} }; // ok
+  S *p = new S[3] { {1, 2, 3}, {4, 5} }; // ok
+}

Modified: cfe/trunk/www/cxx_dr_status.html
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/www/cxx_dr_status.html?rev=210091&r1=210090&r2=210091&view=diff
==============================================================================
--- cfe/trunk/www/cxx_dr_status.html (original)
+++ cfe/trunk/www/cxx_dr_status.html Tue Jun  3 03:26:00 2014
@@ -3233,7 +3233,7 @@ of class templates</td>
     <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#532">532</a></td>
     <td>C++11</td>
     <td>Member/nonmember operator template partial ordering</td>
-    <td class="none" align="center">Unknown</td>
+    <td class="svn" align="center">SVN</td>
   </tr>
   <tr id="533">
     <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_closed.html#533">533</a></td>
@@ -5755,7 +5755,7 @@ and <I>POD class</I></td>
     <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#990">990</a></td>
     <td>CD2</td>
     <td>Value initialization with multiple initializer-list constructors</td>
-    <td class="none" align="center">Unknown</td>
+    <td class="svn" align="center">SVN</td>
   </tr>
   <tr id="991">
     <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#991">991</a></td>
@@ -6235,7 +6235,7 @@ and <I>POD class</I></td>
     <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1070">1070</a></td>
     <td>C++11</td>
     <td>Missing initializer clauses in aggregate initialization</td>
-    <td class="none" align="center">Unknown</td>
+    <td class="svn" align="center">SVN</td>
   </tr>
   <tr id="1071">
     <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1071">1071</a></td>





More information about the cfe-commits mailing list