Clean up designated initialization of unions, so that CodeGen doesn't

have to try to guess which member is being initialized.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@63315 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Douglas Gregor 2009-01-29 16:53:55 +00:00
Родитель 5d2ff63254
Коммит 0bb76897be
5 изменённых файлов: 81 добавлений и 42 удалений

Просмотреть файл

@ -1664,6 +1664,10 @@ class InitListExpr : public Expr {
/// written in the source code.
InitListExpr *SyntacticForm;
/// If this initializer list initializes a union, specifies which
/// field within the union will be initialized.
FieldDecl *UnionFieldInit;
public:
InitListExpr(SourceLocation lbraceloc, Expr **initexprs, unsigned numinits,
SourceLocation rbraceloc);
@ -1702,6 +1706,15 @@ public:
/// accomodate the new entry.
Expr *updateInit(unsigned Init, Expr *expr);
/// \brief If this initializes a union, specifies which field in the
/// union to initialize.
///
/// Typically, this field is the first named field within the
/// union. However, a designated initializer can specify the
/// initialization of a different field within the union.
FieldDecl *getInitializedFieldInUnion() { return UnionFieldInit; }
void setInitializedFieldInUnion(FieldDecl *FD) { UnionFieldInit = FD; }
// Explicit InitListExpr's originate from source code (and have valid source
// locations). Implicit InitListExpr's are created by the semantic analyzer.
bool isExplicit() {

Просмотреть файл

@ -223,7 +223,8 @@ InitListExpr::InitListExpr(SourceLocation lbraceloc,
Expr **initExprs, unsigned numInits,
SourceLocation rbraceloc)
: Expr(InitListExprClass, QualType()),
LBraceLoc(lbraceloc), RBraceLoc(rbraceloc), SyntacticForm(0) {
LBraceLoc(lbraceloc), RBraceLoc(rbraceloc), SyntacticForm(0),
UnionFieldInit(0) {
InitExprs.insert(InitExprs.end(), initExprs, initExprs+numInits);
}

Просмотреть файл

@ -443,7 +443,38 @@ void AggExprEmitter::VisitInitListExpr(InitListExpr *E) {
unsigned NumInitElements = E->getNumInits();
RecordDecl *SD = E->getType()->getAsRecordType()->getDecl();
unsigned CurInitVal = 0;
bool isUnion = E->getType()->isUnionType();
if (E->getType()->isUnionType()) {
// Only initialize one field of a union. The field itself is
// specified by the initializer list.
if (!E->getInitializedFieldInUnion()) {
// Empty union; we have nothing to do.
#ifndef NDEBUG
// Make sure that it's really an empty and not a failure of
// semantic analysis.
for (RecordDecl::field_iterator Field = SD->field_begin(),
FieldEnd = SD->field_end();
Field != FieldEnd; ++Field)
assert(Field->isUnnamedBitfield() && "Only unnamed bitfields allowed");
#endif
return;
}
// FIXME: volatility
FieldDecl *Field = E->getInitializedFieldInUnion();
LValue FieldLoc = CGF.EmitLValueForField(DestPtr, Field, true, 0);
if (NumInitElements) {
// Store the initializer into the field
EmitInitializationToLValue(E->getInit(0), FieldLoc);
} else {
// Default-initialize to null
EmitNullInitializationToLValue(FieldLoc, Field->getType());
}
return;
}
// Here we iterate over the fields; this makes it simpler to both
// default-initialize fields and skip over unnamed fields.
@ -457,29 +488,15 @@ void AggExprEmitter::VisitInitListExpr(InitListExpr *E) {
if (Field->isUnnamedBitfield())
continue;
// When we're coping with C99 designated initializers into a
// union, find the field that has the same type as the expression
// we're initializing the union with.
if (isUnion && CurInitVal < NumInitElements &&
(CGF.getContext().getCanonicalType(Field->getType()) !=
CGF.getContext().getCanonicalType(E->getInit(CurInitVal)->getType())))
continue;
// FIXME: volatility
LValue FieldLoc = CGF.EmitLValueForField(DestPtr, *Field, isUnion,0);
LValue FieldLoc = CGF.EmitLValueForField(DestPtr, *Field, false, 0);
if (CurInitVal < NumInitElements) {
// Store the initializer into the field
// This will probably have to get a bit smarter when we support
// designators in initializers
EmitInitializationToLValue(E->getInit(CurInitVal++), FieldLoc);
} else {
// We're out of initalizers; default-initialize to null
EmitNullInitializationToLValue(FieldLoc, Field->getType());
}
// Unions only initialize one field.
if (isUnion)
break;
}
}

Просмотреть файл

@ -241,32 +241,29 @@ public:
RecordDecl *RD = ILE->getType()->getAsRecordType()->getDecl();
const llvm::Type *Ty = ConvertType(ILE->getType());
// Find the field decl we're initializing, if any
// FIXME: C99 designated initializers won't always initialize the
// first field
int FieldNo = 0; // Field no in RecordDecl
FieldDecl* curField = 0;
bool sawAnyFields = false;
for (RecordDecl::field_iterator Field = RD->field_begin(),
FieldEnd = RD->field_end();
Field != FieldEnd; ++Field) {
curField = *Field;
FieldNo++;
// If this is an empty initializer list, we value-initialize the
// union.
if (ILE->getNumInits() == 0)
return llvm::Constant::getNullValue(Ty);
if (curField->isUnnamedBitfield())
continue;
// If we have an initializer, find the field whose type is the
// same as that initializer. This
sawAnyFields = true;
if (ILE->getNumInits() > 0 &&
CGM.getContext().getCanonicalType(curField->getType()) ==
CGM.getContext().getCanonicalType(ILE->getInit(0)->getType()))
break;
FieldDecl* curField = ILE->getInitializedFieldInUnion();
if (!curField) {
#ifndef NDEBUG
#endif
}
if (!curField || !curField->getIdentifier() || ILE->getNumInits() == 0)
if (!curField) {
// There's no field to initialize, so value-initialize the union.
#ifndef NDEBUG
// Make sure that it's really an empty and not a failure of
// semantic analysis.
for (RecordDecl::field_iterator Field = RD->field_begin(),
FieldEnd = RD->field_end();
Field != FieldEnd; ++Field)
assert(Field->isUnnamedBitfield() && "Only unnamed bitfields allowed");
#endif
return llvm::Constant::getNullValue(Ty);
}
if (curField->isBitField()) {
// Create a dummy struct for bit-field insertion

Просмотреть файл

@ -573,6 +573,11 @@ void InitListChecker::CheckStructUnionTypes(InitListExpr *IList,
StructuredList, StructuredIndex))
hadError = true;
// Abort early for unions: the designator handled the
// initialization of the appropriate field.
if (DeclType->isUnionType())
break;
continue;
}
@ -585,7 +590,7 @@ void InitListChecker::CheckStructUnionTypes(InitListExpr *IList,
if (Field->getType()->isIncompleteArrayType())
break;
if (!Field->getIdentifier() && Field->isBitField()) {
if (Field->isUnnamedBitfield()) {
// Don't initialize unnamed bitfields, e.g. "int : 20;"
++Field;
continue;
@ -593,8 +598,12 @@ void InitListChecker::CheckStructUnionTypes(InitListExpr *IList,
CheckSubElementType(IList, Field->getType(), Index,
StructuredList, StructuredIndex);
if (DeclType->isUnionType())
if (DeclType->isUnionType()) {
// Initialize the first field within the union.
StructuredList->setInitializedFieldInUnion(*Field);
break;
}
++Field;
}
@ -753,8 +762,10 @@ InitListChecker::CheckDesignatedInitializer(InitListExpr *IList,
// All of the fields of a union are located at the same place in
// the initializer list.
if (RT->getDecl()->isUnion())
if (RT->getDecl()->isUnion()) {
FieldIndex = 0;
StructuredList->setInitializedFieldInUnion(*Field);
}
// Update the designator with the field declaration.
D->setField(*Field);