r228897 - More for DR1467: In C++, when initializing an element of an aggregate,
Richard Smith
richard-llvm at metafoo.co.uk
Wed Feb 11 17:55:09 PST 2015
Author: rsmith
Date: Wed Feb 11 19:55:09 2015
New Revision: 228897
URL: http://llvm.org/viewvc/llvm-project?rev=228897&view=rev
Log:
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.
Modified:
cfe/trunk/lib/Sema/SemaInit.cpp
cfe/trunk/test/CXX/drs/dr14xx.cpp
cfe/trunk/test/SemaCXX/atomic-type.cpp
Modified: cfe/trunk/lib/Sema/SemaInit.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaInit.cpp?rev=228897&r1=228896&r2=228897&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaInit.cpp (original)
+++ cfe/trunk/lib/Sema/SemaInit.cpp Wed Feb 11 19:55:09 2015
@@ -966,7 +966,7 @@ void InitListChecker::CheckSubElementTyp
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::CheckSubElementTyp
++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::CheckSubElementTyp
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::CheckSubElementTyp
}
// 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::CheckSubElementTyp
// 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 {
Modified: cfe/trunk/test/CXX/drs/dr14xx.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/drs/dr14xx.cpp?rev=228897&r1=228896&r2=228897&view=diff
==============================================================================
--- cfe/trunk/test/CXX/drs/dr14xx.cpp (original)
+++ cfe/trunk/test/CXX/drs/dr14xx.cpp Wed Feb 11 19:55:09 2015
@@ -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
Modified: cfe/trunk/test/SemaCXX/atomic-type.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/atomic-type.cpp?rev=228897&r1=228896&r2=228897&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/atomic-type.cpp (original)
+++ cfe/trunk/test/SemaCXX/atomic-type.cpp Wed Feb 11 19:55:09 2015
@@ -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) {
More information about the cfe-commits
mailing list