[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