summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--clang/lib/Sema/SemaInit.cpp79
-rw-r--r--clang/test/CXX/drs/dr14xx.cpp3
-rw-r--r--clang/test/SemaCXX/atomic-type.cpp11
3 files changed, 52 insertions, 41 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 {
diff --git a/clang/test/CXX/drs/dr14xx.cpp b/clang/test/CXX/drs/dr14xx.cpp
index 94e733fb9ce..0ffc0edcece 100644
--- a/clang/test/CXX/drs/dr14xx.cpp
+++ b/clang/test/CXX/drs/dr14xx.cpp
@@ -324,6 +324,9 @@ namespace dr1467 { // dr1467: 3.7 c++11
S s1;
S s2 = {s1}; // ok, not list-initialization so we pick the non-explicit constructor
}
+
+ struct NestedInit { int a, b, c; };
+ NestedInit ni[1] = {{NestedInit{1, 2, 3}}};
} // dr1467
namespace dr1490 { // dr1490: 3.7 c++11
diff --git a/clang/test/SemaCXX/atomic-type.cpp b/clang/test/SemaCXX/atomic-type.cpp
index 779b0671cad..a2b314aacdd 100644
--- a/clang/test/SemaCXX/atomic-type.cpp
+++ b/clang/test/SemaCXX/atomic-type.cpp
@@ -71,6 +71,8 @@ namespace copy_init {
#if __cplusplus >= 201103L
_Atomic(X) e2{0}; // expected-error {{illegal initializer}}
_Atomic(X) a{X(0)};
+ // FIXME: This does not seem like the right answer.
+ _Atomic(int) e3{0}; // expected-error {{illegal initializer}}
#endif
struct Y {
@@ -79,9 +81,14 @@ namespace copy_init {
};
Y y1 = { X(0), 4 };
Y y2 = { 0, 4 }; // expected-error {{cannot initialize}}
+
// FIXME: It's not really clear if we should allow these. Generally, C++11
- // allows extraneous braces around initializers.
- Y y3 = { { X(0) }, { 4 } }; // expected-error 2{{illegal initializer type}}
+ // allows extraneous braces around initializers. We should at least give the
+ // same answer in all these cases:
+ Y y3 = { X(0), { 4 } }; // expected-error {{illegal initializer type}}
+ Y y4 = { { X(0) }, 4 };
+ _Atomic(int) ai = { 4 }; // expected-error {{illegal initializer type}}
+ _Atomic(X) ax = { X(0) };
}
bool PR21836(_Atomic(int) *x) {
OpenPOWER on IntegriCloud