Fix a bug with designated initializers where we were stepping out of a

union subobject initialization before checking whether the next
initiailizer was actually a designated initializer. This led to
spurious "excess elements in union initializer" errors. Thanks to
rdivacky for reporting the bug!

llvm-svn: 64392
This commit is contained in:
Douglas Gregor 2009-02-12 19:00:39 +00:00
parent c335c40a4b
commit a9add4ea76
2 changed files with 21 additions and 8 deletions

View File

@ -742,14 +742,13 @@ void InitListChecker::CheckStructUnionTypes(InitListExpr *IList,
return; return;
} }
// If structDecl is a forward declaration, this loop won't do // If structDecl is a forward declaration, this loop won't do
// anything except look at designated initializers; That's okay, // anything except look at designated initializers; That's okay,
// because an error should get printed out elsewhere. It might be // because an error should get printed out elsewhere. It might be
// worthwhile to skip over the rest of the initializer, though. // worthwhile to skip over the rest of the initializer, though.
RecordDecl *RD = DeclType->getAsRecordType()->getDecl(); RecordDecl *RD = DeclType->getAsRecordType()->getDecl();
RecordDecl::field_iterator FieldEnd = RD->field_end(); RecordDecl::field_iterator FieldEnd = RD->field_end();
bool InitializedSomething = false;
while (Index < IList->getNumInits()) { while (Index < IList->getNumInits()) {
Expr *Init = IList->getInit(Index); Expr *Init = IList->getInit(Index);
@ -768,11 +767,7 @@ void InitListChecker::CheckStructUnionTypes(InitListExpr *IList,
true, TopLevelObject)) true, TopLevelObject))
hadError = true; hadError = true;
// Abort early for unions: the designator handled the InitializedSomething = true;
// initialization of the appropriate field.
if (DeclType->isUnionType())
break;
continue; continue;
} }
@ -781,6 +776,10 @@ void InitListChecker::CheckStructUnionTypes(InitListExpr *IList,
break; break;
} }
// We've already initialized a member of a union. We're done.
if (InitializedSomething && DeclType->isUnionType())
break;
// If we've hit the flexible array member at the end, we're done. // If we've hit the flexible array member at the end, we're done.
if (Field->getType()->isIncompleteArrayType()) if (Field->getType()->isIncompleteArrayType())
break; break;
@ -793,11 +792,11 @@ void InitListChecker::CheckStructUnionTypes(InitListExpr *IList,
CheckSubElementType(IList, Field->getType(), Index, CheckSubElementType(IList, Field->getType(), Index,
StructuredList, StructuredIndex); StructuredList, StructuredIndex);
InitializedSomething = true;
if (DeclType->isUnionType()) { if (DeclType->isUnionType()) {
// Initialize the first field within the union. // Initialize the first field within the union.
StructuredList->setInitializedFieldInUnion(*Field); StructuredList->setInitializedFieldInUnion(*Field);
break;
} }
++Field; ++Field;

View File

@ -172,3 +172,17 @@ struct bar saloon = {
.f.arr[3] = 1, .f.arr[3] = 1,
.arr = { &f } .arr = { &f }
}; };
typedef unsigned char u_char;
typedef unsigned short u_short;
union wibble {
u_char arr1[6];
u_short arr2[3];
};
const union wibble wobble = { .arr2[0] = 0xffff,
.arr2[1] = 0xffff,
.arr2[2] = 0xffff };
const union wibble wobble2 = { .arr2 = {4, 5, 6}, 7 }; // expected-error{{excess elements in union initializer}}