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:
parent
c335c40a4b
commit
a9add4ea76
|
@ -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;
|
||||||
|
|
|
@ -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}}
|
||||||
|
|
Loading…
Reference in New Issue