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,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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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