r210091 - Implement DR990 and DR1070. Aggregate initialization initializes uninitialized

Richard Smith richard at metafoo.co.uk
Wed Jun 4 09:47:30 PDT 2014


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
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20140604/cbf58388/attachment.html>


More information about the cfe-commits mailing list