forked from OSchip/llvm-project
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:
parent
c6b473433b
commit
2bb0765bb4
|
@ -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;
|
||||||
|
|
|
@ -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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
Loading…
Reference in New Issue