When filling in value initializations within an initializer list, be

sure to fill in the initialized member of a union when a member was
explicitly designated. Fixes PR5843.

llvm-svn: 91858
This commit is contained in:
Douglas Gregor 2009-12-22 00:05:34 +00:00
parent c6b473433b
commit 2bb0765bb4
2 changed files with 103 additions and 65 deletions

View File

@ -345,6 +345,9 @@ class InitListChecker {
int numArrayElements(QualType DeclType); int numArrayElements(QualType DeclType);
int numStructUnionElements(QualType DeclType); int numStructUnionElements(QualType DeclType);
void FillInValueInitForField(unsigned Init, FieldDecl *Field,
const InitializedEntity &ParentEntity,
InitListExpr *ILE, bool &RequiresSecondPass);
void FillInValueInitializations(const InitializedEntity &Entity, void FillInValueInitializations(const InitializedEntity &Entity,
InitListExpr *ILE, bool &RequiresSecondPass); InitListExpr *ILE, bool &RequiresSecondPass);
public: public:
@ -358,33 +361,14 @@ public:
}; };
} // end anonymous namespace } // end anonymous namespace
/// Recursively replaces NULL values within the given initializer list void InitListChecker::FillInValueInitForField(unsigned Init, FieldDecl *Field,
/// with expressions that perform value-initialization of the const InitializedEntity &ParentEntity,
/// appropriate type.
void
InitListChecker::FillInValueInitializations(const InitializedEntity &Entity,
InitListExpr *ILE, InitListExpr *ILE,
bool &RequiresSecondPass) { bool &RequiresSecondPass) {
assert((ILE->getType() != SemaRef.Context.VoidTy) &&
"Should not have void type");
SourceLocation Loc = ILE->getSourceRange().getBegin(); SourceLocation Loc = ILE->getSourceRange().getBegin();
if (ILE->getSyntacticForm()) unsigned NumInits = ILE->getNumInits();
Loc = ILE->getSyntacticForm()->getSourceRange().getBegin();
if (const RecordType *RType = ILE->getType()->getAs<RecordType>()) {
unsigned Init = 0, NumInits = ILE->getNumInits();
for (RecordDecl::field_iterator
Field = RType->getDecl()->field_begin(),
FieldEnd = RType->getDecl()->field_end();
Field != FieldEnd; ++Field) {
if (Field->isUnnamedBitfield())
continue;
if (hadError)
return;
InitializedEntity MemberEntity InitializedEntity MemberEntity
= InitializedEntity::InitializeMember(*Field, &Entity); = InitializedEntity::InitializeMember(Field, &ParentEntity);
if (Init >= NumInits || !ILE->getInit(Init)) { if (Init >= NumInits || !ILE->getInit(Init)) {
// FIXME: We probably don't need to handle references // FIXME: We probably don't need to handle references
// specially here, since value-initialization of references is // specially here, since value-initialization of references is
@ -437,12 +421,49 @@ InitListChecker::FillInValueInitializations(const InitializedEntity &Entity,
= dyn_cast<InitListExpr>(ILE->getInit(Init))) = dyn_cast<InitListExpr>(ILE->getInit(Init)))
FillInValueInitializations(MemberEntity, InnerILE, FillInValueInitializations(MemberEntity, InnerILE,
RequiresSecondPass); RequiresSecondPass);
}
/// Recursively replaces NULL values within the given initializer list
/// with expressions that perform value-initialization of the
/// appropriate type.
void
InitListChecker::FillInValueInitializations(const InitializedEntity &Entity,
InitListExpr *ILE,
bool &RequiresSecondPass) {
assert((ILE->getType() != SemaRef.Context.VoidTy) &&
"Should not have void type");
SourceLocation Loc = ILE->getSourceRange().getBegin();
if (ILE->getSyntacticForm())
Loc = ILE->getSyntacticForm()->getSourceRange().getBegin();
if (const RecordType *RType = ILE->getType()->getAs<RecordType>()) {
if (RType->getDecl()->isUnion() &&
ILE->getInitializedFieldInUnion())
FillInValueInitForField(0, ILE->getInitializedFieldInUnion(),
Entity, ILE, RequiresSecondPass);
else {
unsigned Init = 0;
for (RecordDecl::field_iterator
Field = RType->getDecl()->field_begin(),
FieldEnd = RType->getDecl()->field_end();
Field != FieldEnd; ++Field) {
if (Field->isUnnamedBitfield())
continue;
if (hadError)
return;
FillInValueInitForField(Init, *Field, Entity, ILE, RequiresSecondPass);
if (hadError)
return;
++Init; ++Init;
// Only look at the first initialization of a union. // Only look at the first initialization of a union.
if (RType->getDecl()->isUnion()) if (RType->getDecl()->isUnion())
break; break;
} }
}
return; return;
} }

View File

@ -231,4 +231,21 @@ int crazy_Y[] = {
[ 0 ? crazy_x : 4] = 1 [ 0 ? crazy_x : 4] = 1
}; };
// PR5843
struct expr {
int nargs;
union {
unsigned long int num;
struct expr *args[3];
} val;
};
struct expr expr0 = {
.nargs = 2,
.val = {
.args = {
[0] = (struct expr *)0,
[1] = (struct expr *)0
}
}
};