зеркало из https://github.com/microsoft/clang-1.git
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:
Родитель
5d2ff63254
Коммит
0bb76897be
|
@ -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);
|
||||
|
|
Загрузка…
Ссылка в новой задаче