r210091 - Implement DR990 and DR1070. Aggregate initialization initializes uninitialized
Evgeniy Stepanov
eugeni.stepanov at gmail.com
Wed Jun 4 05:06:38 PDT 2014
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?
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