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,6 +361,68 @@ public:
}; };
} // end anonymous namespace } // end anonymous namespace
void InitListChecker::FillInValueInitForField(unsigned Init, FieldDecl *Field,
const InitializedEntity &ParentEntity,
InitListExpr *ILE,
bool &RequiresSecondPass) {
SourceLocation Loc = ILE->getSourceRange().getBegin();
unsigned NumInits = ILE->getNumInits();
InitializedEntity MemberEntity
= InitializedEntity::InitializeMember(Field, &ParentEntity);
if (Init >= NumInits || !ILE->getInit(Init)) {
// FIXME: We probably don't need to handle references
// specially here, since value-initialization of references is
// handled in InitializationSequence.
if (Field->getType()->isReferenceType()) {
// C++ [dcl.init.aggr]p9:
// If an incomplete or empty initializer-list leaves a
// member of reference type uninitialized, the program is
// ill-formed.
SemaRef.Diag(Loc, diag::err_init_reference_member_uninitialized)
<< Field->getType()
<< ILE->getSyntacticForm()->getSourceRange();
SemaRef.Diag(Field->getLocation(),
diag::note_uninit_reference_member);
hadError = true;
return;
}
InitializationKind Kind = InitializationKind::CreateValue(Loc, Loc, Loc,
true);
InitializationSequence InitSeq(SemaRef, MemberEntity, Kind, 0, 0);
if (!InitSeq) {
InitSeq.Diagnose(SemaRef, MemberEntity, Kind, 0, 0);
hadError = true;
return;
}
Sema::OwningExprResult MemberInit
= InitSeq.Perform(SemaRef, MemberEntity, Kind,
Sema::MultiExprArg(SemaRef, 0, 0));
if (MemberInit.isInvalid()) {
hadError = true;
return;
}
if (hadError) {
// Do nothing
} else if (Init < NumInits) {
ILE->setInit(Init, MemberInit.takeAs<Expr>());
} else if (InitSeq.getKind()
== InitializationSequence::ConstructorInitialization) {
// Value-initialization requires a constructor call, so
// extend the initializer list to include the constructor
// call and make a note that we'll need to take another pass
// through the initializer list.
ILE->updateInit(Init, MemberInit.takeAs<Expr>());
RequiresSecondPass = true;
}
} else if (InitListExpr *InnerILE
= dyn_cast<InitListExpr>(ILE->getInit(Init)))
FillInValueInitializations(MemberEntity, InnerILE,
RequiresSecondPass);
}
/// Recursively replaces NULL values within the given initializer list /// Recursively replaces NULL values within the given initializer list
/// with expressions that perform value-initialization of the /// with expressions that perform value-initialization of the
/// appropriate type. /// appropriate type.
@ -372,76 +437,32 @@ InitListChecker::FillInValueInitializations(const InitializedEntity &Entity,
Loc = ILE->getSyntacticForm()->getSourceRange().getBegin(); Loc = ILE->getSyntacticForm()->getSourceRange().getBegin();
if (const RecordType *RType = ILE->getType()->getAs<RecordType>()) { if (const RecordType *RType = ILE->getType()->getAs<RecordType>()) {
unsigned Init = 0, NumInits = ILE->getNumInits(); if (RType->getDecl()->isUnion() &&
for (RecordDecl::field_iterator ILE->getInitializedFieldInUnion())
Field = RType->getDecl()->field_begin(), FillInValueInitForField(0, ILE->getInitializedFieldInUnion(),
FieldEnd = RType->getDecl()->field_end(); Entity, ILE, RequiresSecondPass);
Field != FieldEnd; ++Field) { else {
if (Field->isUnnamedBitfield()) unsigned Init = 0;
continue; for (RecordDecl::field_iterator
Field = RType->getDecl()->field_begin(),
FieldEnd = RType->getDecl()->field_end();
Field != FieldEnd; ++Field) {
if (Field->isUnnamedBitfield())
continue;
if (hadError) if (hadError)
return;
InitializedEntity MemberEntity
= InitializedEntity::InitializeMember(*Field, &Entity);
if (Init >= NumInits || !ILE->getInit(Init)) {
// FIXME: We probably don't need to handle references
// specially here, since value-initialization of references is
// handled in InitializationSequence.
if (Field->getType()->isReferenceType()) {
// C++ [dcl.init.aggr]p9:
// If an incomplete or empty initializer-list leaves a
// member of reference type uninitialized, the program is
// ill-formed.
SemaRef.Diag(Loc, diag::err_init_reference_member_uninitialized)
<< Field->getType()
<< ILE->getSyntacticForm()->getSourceRange();
SemaRef.Diag(Field->getLocation(),
diag::note_uninit_reference_member);
hadError = true;
return; return;
}
FillInValueInitForField(Init, *Field, Entity, ILE, RequiresSecondPass);
InitializationKind Kind = InitializationKind::CreateValue(Loc, Loc, Loc, if (hadError)
true);
InitializationSequence InitSeq(SemaRef, MemberEntity, Kind, 0, 0);
if (!InitSeq) {
InitSeq.Diagnose(SemaRef, MemberEntity, Kind, 0, 0);
hadError = true;
return; return;
}
Sema::OwningExprResult MemberInit ++Init;
= InitSeq.Perform(SemaRef, MemberEntity, Kind,
Sema::MultiExprArg(SemaRef, 0, 0));
if (MemberInit.isInvalid()) {
hadError = true;
return;
}
if (hadError) { // Only look at the first initialization of a union.
// Do nothing if (RType->getDecl()->isUnion())
} else if (Init < NumInits) { break;
ILE->setInit(Init, MemberInit.takeAs<Expr>()); }
} else if (InitSeq.getKind()
== InitializationSequence::ConstructorInitialization) {
// Value-initialization requires a constructor call, so
// extend the initializer list to include the constructor
// call and make a note that we'll need to take another pass
// through the initializer list.
ILE->updateInit(Init, MemberInit.takeAs<Expr>());
RequiresSecondPass = true;
}
} else if (InitListExpr *InnerILE
= dyn_cast<InitListExpr>(ILE->getInit(Init)))
FillInValueInitializations(MemberEntity, InnerILE,
RequiresSecondPass);
++Init;
// Only look at the first initialization of a union.
if (RType->getDecl()->isUnion())
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
}
}
};