r210091 - Implement DR990 and DR1070. Aggregate initialization initializes uninitialized

Evgeniy Stepanov eugeni.stepanov at gmail.com
Wed Jun 4 09:54:10 PDT 2014


In fact, it may be some other commit that caused this.

The actual problem is with stlport, which defines constructors for all
containers this way. (i.e. no real default constructor).
This, in turn, breaks declarations like
class A { int x; int y; string z; } a = {{1, 1}, {2, 2}};

Regression window is 209387 - 201180.

On Wed, Jun 4, 2014 at 8:47 PM, Richard Smith <richard at metafoo.co.uk> wrote:
> On 4 Jun 2014 05:07, "Evgeniy Stepanov" <eugeni.stepanov at gmail.com> wrote:
>>
>> Hi,
>>
>> This change is causing this to fail with -std=c++11:
>> struct A { explicit A(int x = 0) {(void)x;}; };
>> A a = {};
>> with error: chosen constructor is explicit in copy-initialization
>>
>> but this passes:
>> struct A { explicit A(int x = 0) {(void)x;}; };
>> A a{};
>>
>> Is it correct?
>
> It looks correct (but I need to double check, because the empty list / class
> with default constructor case is a special case in the standard). I'm
> surprised that code was affected by this change, though, since it contains
> no aggregate initialization.
>
>> On Tue, Jun 3, 2014 at 12:26 PM, Richard Smith
>> <richard-llvm at metafoo.co.uk> wrote:
>> > 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>
>> >
>> >
>> > _______________________________________________
>> > cfe-commits mailing list
>> > cfe-commits at cs.uiuc.edu
>> > http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits



More information about the cfe-commits mailing list