diff options
author | Richard Smith <richard-llvm@metafoo.co.uk> | 2015-02-12 01:55:09 +0000 |
---|---|---|
committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2015-02-12 01:55:09 +0000 |
commit | 3c567fce463690d717ca4448c5769524b5a904d8 (patch) | |
tree | 8e2cfc4f80a45f20194fa849cabfa9c72e0c0037 /clang/lib/Sema/SemaInit.cpp | |
parent | 420fa12dfddc33b0d0b54666340bfa630b61b5bc (diff) | |
download | bcm5719-llvm-3c567fce463690d717ca4448c5769524b5a904d8.tar.gz bcm5719-llvm-3c567fce463690d717ca4448c5769524b5a904d8.zip |
More for DR1467: In C++, when initializing an element of an aggregate,
always use the normal copy-initialization rules. Remove a special case that
tries to stay within the list initialization checker here; that makes us do the
wrong thing when list-initialization of an aggregate would not perform
aggregate initialization.
llvm-svn: 228897
Diffstat (limited to 'clang/lib/Sema/SemaInit.cpp')
-rw-r--r-- | clang/lib/Sema/SemaInit.cpp | 79 |
1 files changed, 40 insertions, 39 deletions
diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp index dab06195878..5692d6e8f21 100644 --- a/clang/lib/Sema/SemaInit.cpp +++ b/clang/lib/Sema/SemaInit.cpp @@ -966,7 +966,7 @@ void InitListChecker::CheckSubElementType(const InitializedEntity &Entity, StructuredList, StructuredIndex); if (InitListExpr *SubInitList = dyn_cast<InitListExpr>(expr)) { - if (!ElemType->isRecordType() || ElemType->isAggregateType()) { + if (!SemaRef.getLangOpts().CPlusPlus) { InitListExpr *InnerStructuredList = getStructuredSubobjectInit(IList, Index, ElemType, StructuredList, StructuredIndex, @@ -977,8 +977,6 @@ void InitListChecker::CheckSubElementType(const InitializedEntity &Entity, ++Index; return; } - assert(SemaRef.getLangOpts().CPlusPlus && - "non-aggregate records are only possible in C++"); // C++ initialization is handled later. } else if (isa<ImplicitValueInitExpr>(expr)) { // This happens during template instantiation when we see an InitListExpr @@ -991,43 +989,24 @@ void InitListChecker::CheckSubElementType(const InitializedEntity &Entity, return; } - // FIXME: Need to handle atomic aggregate types with implicit init lists. - if (ElemType->isScalarType() || ElemType->isAtomicType()) - return CheckScalarType(Entity, IList, ElemType, Index, - StructuredList, StructuredIndex); - - assert((ElemType->isRecordType() || ElemType->isVectorType() || - ElemType->isArrayType()) && "Unexpected type"); - - if (const ArrayType *arrayType = SemaRef.Context.getAsArrayType(ElemType)) { - // arrayType can be incomplete if we're initializing a flexible - // array member. There's nothing we can do with the completed - // type here, though. - - if (IsStringInit(expr, arrayType, SemaRef.Context) == SIF_None) { - if (!VerifyOnly) { - CheckStringInit(expr, ElemType, arrayType, SemaRef); - UpdateStructuredListElement(StructuredList, StructuredIndex, expr); - } - ++Index; - return; - } - - // Fall through for subaggregate initialization. - - } else if (SemaRef.getLangOpts().CPlusPlus) { - // C++ [dcl.init.aggr]p12: - // All implicit type conversions (clause 4) are considered when - // initializing the aggregate member with an initializer from - // an initializer-list. If the initializer can initialize a - // member, the member is initialized. [...] + if (SemaRef.getLangOpts().CPlusPlus) { + // C++ [dcl.init.aggr]p2: + // Each member is copy-initialized from the corresponding + // initializer-clause. // FIXME: Better EqualLoc? InitializationKind Kind = InitializationKind::CreateCopy(expr->getLocStart(), SourceLocation()); - InitializationSequence Seq(SemaRef, Entity, Kind, expr); + InitializationSequence Seq(SemaRef, Entity, Kind, expr, + /*TopLevelOfInitList*/ true); - if (Seq) { + // C++14 [dcl.init.aggr]p13: + // If the assignment-expression can initialize a member, the member is + // initialized. Otherwise [...] brace elision is assumed + // + // Brace elision is never performed if the element is not an + // assignment-expression. + if (Seq || isa<InitListExpr>(expr)) { if (!VerifyOnly) { ExprResult Result = Seq.Perform(SemaRef, Entity, Kind, expr); @@ -1042,7 +1021,31 @@ void InitListChecker::CheckSubElementType(const InitializedEntity &Entity, } // Fall through for subaggregate initialization + } else if (ElemType->isScalarType() || ElemType->isAtomicType()) { + // FIXME: Need to handle atomic aggregate types with implicit init lists. + return CheckScalarType(Entity, IList, ElemType, Index, + StructuredList, StructuredIndex); + } else if (const ArrayType *arrayType = + SemaRef.Context.getAsArrayType(ElemType)) { + // arrayType can be incomplete if we're initializing a flexible + // array member. There's nothing we can do with the completed + // type here, though. + + if (IsStringInit(expr, arrayType, SemaRef.Context) == SIF_None) { + if (!VerifyOnly) { + CheckStringInit(expr, ElemType, arrayType, SemaRef); + UpdateStructuredListElement(StructuredList, StructuredIndex, expr); + } + ++Index; + return; + } + + // Fall through for subaggregate initialization. + } else { + assert((ElemType->isRecordType() || ElemType->isVectorType()) && + "Unexpected type"); + // C99 6.7.8p13: // // The initializer for a structure or union object that has @@ -1052,10 +1055,8 @@ void InitListChecker::CheckSubElementType(const InitializedEntity &Entity, // initial value of the object, including unnamed members, is // that of the expression. ExprResult ExprRes = expr; - if ((ElemType->isRecordType() || ElemType->isVectorType()) && - SemaRef.CheckSingleAssignmentConstraints(ElemType, ExprRes, - !VerifyOnly) - != Sema::Incompatible) { + if (SemaRef.CheckSingleAssignmentConstraints( + ElemType, ExprRes, !VerifyOnly) != Sema::Incompatible) { if (ExprRes.isInvalid()) hadError = true; else { |