[cfe-commits] r63315 - in /cfe/trunk: include/clang/AST/Expr.h lib/AST/Expr.cpp lib/CodeGen/CGExprAgg.cpp lib/CodeGen/CGExprConstant.cpp lib/Sema/SemaInit.cpp
Douglas Gregor
dgregor at apple.com
Thu Jan 29 08:53:56 PST 2009
Author: dgregor
Date: Thu Jan 29 10:53:55 2009
New Revision: 63315
URL: http://llvm.org/viewvc/llvm-project?rev=63315&view=rev
Log:
Clean up designated initialization of unions, so that CodeGen doesn't
have to try to guess which member is being initialized.
Modified:
cfe/trunk/include/clang/AST/Expr.h
cfe/trunk/lib/AST/Expr.cpp
cfe/trunk/lib/CodeGen/CGExprAgg.cpp
cfe/trunk/lib/CodeGen/CGExprConstant.cpp
cfe/trunk/lib/Sema/SemaInit.cpp
Modified: cfe/trunk/include/clang/AST/Expr.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Expr.h?rev=63315&r1=63314&r2=63315&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/Expr.h (original)
+++ cfe/trunk/include/clang/AST/Expr.h Thu Jan 29 10:53:55 2009
@@ -1664,6 +1664,10 @@
/// 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 @@
/// 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() {
Modified: cfe/trunk/lib/AST/Expr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Expr.cpp?rev=63315&r1=63314&r2=63315&view=diff
==============================================================================
--- cfe/trunk/lib/AST/Expr.cpp (original)
+++ cfe/trunk/lib/AST/Expr.cpp Thu Jan 29 10:53:55 2009
@@ -223,7 +223,8 @@
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);
}
Modified: cfe/trunk/lib/CodeGen/CGExprAgg.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprAgg.cpp?rev=63315&r1=63314&r2=63315&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGExprAgg.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExprAgg.cpp Thu Jan 29 10:53:55 2009
@@ -443,7 +443,38 @@
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 @@
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;
}
}
Modified: cfe/trunk/lib/CodeGen/CGExprConstant.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprConstant.cpp?rev=63315&r1=63314&r2=63315&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGExprConstant.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExprConstant.cpp Thu Jan 29 10:53:55 2009
@@ -241,32 +241,29 @@
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 (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;
- }
+ // If this is an empty initializer list, we value-initialize the
+ // union.
+ if (ILE->getNumInits() == 0)
+ return llvm::Constant::getNullValue(Ty);
- if (!curField || !curField->getIdentifier() || ILE->getNumInits() == 0)
+ FieldDecl* curField = ILE->getInitializedFieldInUnion();
+ if (!curField) {
+#ifndef NDEBUG
+#endif
+ }
+
+ 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
Modified: cfe/trunk/lib/Sema/SemaInit.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaInit.cpp?rev=63315&r1=63314&r2=63315&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaInit.cpp (original)
+++ cfe/trunk/lib/Sema/SemaInit.cpp Thu Jan 29 10:53:55 2009
@@ -573,6 +573,11 @@
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 @@
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 @@
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 @@
// 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);
More information about the cfe-commits
mailing list