[cfe-commits] r63242 - in /cfe/trunk: Driver/RewriteObjC.cpp include/clang/AST/Decl.h include/clang/AST/Expr.h include/clang/AST/ExprCXX.h include/clang/Basic/DiagnosticSemaKinds.def lib/AST/Expr.cpp lib/AST/StmtPrinter.cpp lib/CodeGen/CGExprAgg.cpp lib/CodeGen/CGExprConstant.cpp lib/CodeGen/CGExprScalar.cpp lib/Sema/Sema.h lib/Sema/SemaDecl.cpp lib/Sema/SemaExpr.cpp lib/Sema/SemaInit.cpp test/Sema/array-init.c test/Sema/designated-initializers.c test/Sema/vector-init.c

Douglas Gregor dgregor at apple.com
Wed Jan 28 13:54:33 PST 2009


Author: dgregor
Date: Wed Jan 28 15:54:33 2009
New Revision: 63242

URL: http://llvm.org/viewvc/llvm-project?rev=63242&view=rev
Log:
Code generation support for C99 designated initializers.

The approach I've taken in this patch is relatively straightforward,
although the code itself is non-trivial. Essentially, as we process
an initializer list we build up a fully-explicit representation of the
initializer list, where each of the subobject initializations occurs
in order. Designators serve to "fill in" subobject initializations in
a non-linear way. The fully-explicit representation makes initializer
lists (both with and without designators) easy to grok for codegen and
later semantic analyses. We keep the syntactic form of the initializer
list linked into the AST for those clients interested in exactly what
the user wrote.

Known limitations:
  - Designating a member of a union that isn't the first member may
    result in bogus initialization (we warn about this)
  - GNU array-range designators are not supported (we warn about this)


Modified:
    cfe/trunk/Driver/RewriteObjC.cpp
    cfe/trunk/include/clang/AST/Decl.h
    cfe/trunk/include/clang/AST/Expr.h
    cfe/trunk/include/clang/AST/ExprCXX.h
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.def
    cfe/trunk/lib/AST/Expr.cpp
    cfe/trunk/lib/AST/StmtPrinter.cpp
    cfe/trunk/lib/CodeGen/CGExprAgg.cpp
    cfe/trunk/lib/CodeGen/CGExprConstant.cpp
    cfe/trunk/lib/CodeGen/CGExprScalar.cpp
    cfe/trunk/lib/Sema/Sema.h
    cfe/trunk/lib/Sema/SemaDecl.cpp
    cfe/trunk/lib/Sema/SemaExpr.cpp
    cfe/trunk/lib/Sema/SemaInit.cpp
    cfe/trunk/test/Sema/array-init.c
    cfe/trunk/test/Sema/designated-initializers.c
    cfe/trunk/test/Sema/vector-init.c

Modified: cfe/trunk/Driver/RewriteObjC.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Driver/RewriteObjC.cpp?rev=63242&r1=63241&r2=63242&view=diff

==============================================================================
--- cfe/trunk/Driver/RewriteObjC.cpp (original)
+++ cfe/trunk/Driver/RewriteObjC.cpp Wed Jan 28 15:54:33 2009
@@ -2310,7 +2310,7 @@
         // (struct objc_super) { <exprs from above> }
         InitListExpr *ILE = new InitListExpr(SourceLocation(), 
                                              &InitExprs[0], InitExprs.size(), 
-                                             SourceLocation(), false);
+                                             SourceLocation());
         SuperRep = new CompoundLiteralExpr(SourceLocation(), superType, ILE,
                                            false);
         // struct objc_super *
@@ -2391,7 +2391,7 @@
         // (struct objc_super) { <exprs from above> }
         InitListExpr *ILE = new InitListExpr(SourceLocation(), 
                                              &InitExprs[0], InitExprs.size(), 
-                                             SourceLocation(), false);
+                                             SourceLocation());
         SuperRep = new CompoundLiteralExpr(SourceLocation(), superType, ILE, false);
       }
       MsgExprs.push_back(SuperRep);

Modified: cfe/trunk/include/clang/AST/Decl.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Decl.h?rev=63242&r1=63241&r2=63242&view=diff

==============================================================================
--- cfe/trunk/include/clang/AST/Decl.h (original)
+++ cfe/trunk/include/clang/AST/Decl.h Wed Jan 28 15:54:33 2009
@@ -678,6 +678,9 @@
   /// isBitfield - Determines whether this field is a bitfield.
   bool isBitField() const { return BitWidth != NULL; }
 
+  /// @brief Determines whether this is an unnamed bitfield.
+  bool isUnnamedBitfield() const { return BitWidth != NULL && !getDeclName(); }
+
   /// isAnonymousStructOrUnion - Determines whether this field is a
   /// representative for an anonymous struct or union. Such fields are
   /// unnamed and are implicitly generated by the implementation to

Modified: cfe/trunk/include/clang/AST/Expr.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Expr.h?rev=63242&r1=63241&r2=63242&view=diff

==============================================================================
--- cfe/trunk/include/clang/AST/Expr.h (original)
+++ cfe/trunk/include/clang/AST/Expr.h Wed Jan 28 15:54:33 2009
@@ -185,6 +185,10 @@
   /// initializer, which can be emitted at compile-time.
   bool isConstantInitializer(ASTContext &Ctx) const;
   
+  /// @brief Determines whether this expression (or any of its
+  /// subexpressions) has side effects.
+  bool hasSideEffects(ASTContext &Ctx) const;
+
   /// EvalResult is a struct with detailed info about an evaluated expression.
   struct EvalResult {
     /// Val - This is the scalar value the expression can be folded to.
@@ -1619,48 +1623,65 @@
   static VAArgExpr* CreateImpl(llvm::Deserializer& D, ASTContext& C);
 };
   
-/// InitListExpr - used for struct and array initializers, such as:
-///    struct foo x = { 1, { 2, 3 } };
+/// @brief Describes an C or C++ initializer list.
+///
+/// InitListExpr describes an initializer list, which can be used to
+/// initialize objects of different types, including
+/// struct/class/union types, arrays, and vectors. For example:
 ///
-/// Because C is somewhat loose with braces, the AST does not necessarily
-/// directly model the C source.  Instead, the semantic analyzer aims to make
-/// the InitListExprs match up with the type of the decl being initialized.  We
-/// have the following exceptions:
-///
-///  1. Elements at the end of the list may be dropped from the initializer.  
-///     These elements are defined to be initialized to zero.  For example:
-///         int x[20] = { 1 };
-///  2. Initializers may have excess initializers which are to be ignored by the
-///     compiler.  For example:
-///         int x[1] = { 1, 2 };
-///  3. Redundant InitListExprs may be present around scalar elements.  These
-///     always have a single element whose type is the same as the InitListExpr.
-///     this can only happen for Type::isScalarType() types.
-///         int x = { 1 };  int y[2] = { {1}, {2} };
+/// @code
+/// struct foo x = { 1, { 2, 3 } };
+/// @endcode
 ///
+/// Prior to semantic analysis, an initializer list will represent the
+/// initializer list as written by the user, but will have the
+/// placeholder type "void". This initializer list is called the
+/// syntactic form of the initializer, and may contain C99 designated
+/// initializers (represented as DesignatedInitExprs), initializations
+/// of subobject members without explicit braces, and so on. Clients
+/// interested in the original syntax of the initializer list should
+/// use the syntactic form of the initializer list.
+///
+/// After semantic analysis, the initializer list will represent the
+/// semantic form of the initializer, where the initializations of all
+/// subobjects are made explicit with nested InitListExpr nodes and
+/// C99 designators have been eliminated by placing the designated
+/// initializations into the subobject they initialize. Additionally,
+/// any "holes" in the initialization, where no initializer has been
+/// specified for a particular subobject, will be replaced with
+/// implicitly-generated CXXZeroInitValueExpr expressions that
+/// value-initialize the subobjects. Note, however, that the
+/// initializer lists may still have fewer initializers than there are
+/// elements to initialize within the object.
+///
+/// Given the semantic form of the initializer list, one can retrieve
+/// the original syntactic form of that initializer list (if it
+/// exists) using getSyntacticForm(). Since many initializer lists
+/// have the same syntactic and semantic forms, getSyntacticForm() may
+/// return NULL, indicating that the current initializer list also
+/// serves as its syntactic form.
 class InitListExpr : public Expr {
   std::vector<Stmt *> InitExprs;
   SourceLocation LBraceLoc, RBraceLoc;
   
-  /// HadDesignators - Return true if there were any designators in this
-  /// init list expr.  FIXME: this should be replaced by storing the designators
-  /// somehow and updating codegen.
-  bool HadDesignators;
+  /// Contains the initializer list that describes the syntactic form
+  /// written in the source code.
+  InitListExpr *SyntacticForm;
+
 public:
   InitListExpr(SourceLocation lbraceloc, Expr **initexprs, unsigned numinits,
-               SourceLocation rbraceloc, bool HadDesignators);
+               SourceLocation rbraceloc);
   
   unsigned getNumInits() const { return InitExprs.size(); }
-  bool hadDesignators() const { return HadDesignators; }
   
   const Expr* getInit(unsigned Init) const { 
     assert(Init < getNumInits() && "Initializer access out of range!");
-    return cast<Expr>(InitExprs[Init]);
+    return cast_or_null<Expr>(InitExprs[Init]);
   }
   
   Expr* getInit(unsigned Init) { 
     assert(Init < getNumInits() && "Initializer access out of range!");
-    return cast<Expr>(InitExprs[Init]);
+    return cast_or_null<Expr>(InitExprs[Init]);
   }
   
   void setInit(unsigned Init, Expr *expr) { 
@@ -1668,13 +1689,22 @@
     InitExprs[Init] = expr;
   }
 
-  // Dynamic removal/addition (for constructing implicit InitExpr's).
-  void removeInit(unsigned Init) {
-    InitExprs.erase(InitExprs.begin()+Init);
-  }
-  void addInit(unsigned Init, Expr *expr) {
-    InitExprs.insert(InitExprs.begin()+Init, expr);
-  }
+  /// @brief Specify the number of initializers
+  ///
+  /// If there are more than @p NumInits initializers, the remaining
+  /// initializers will be destroyed. If there are fewer than @p
+  /// NumInits initializers, NULL expressions will be added for the
+  /// unknown initializers.
+  void resizeInits(ASTContext &Context, unsigned NumInits);
+
+  /// @brief Updates the initializer at index @p Init with the new
+  /// expression @p expr, and returns the old expression at that
+  /// location.
+  ///
+  /// When @p Init is out of range for this initializer list, the
+  /// initializer list will be extended with NULL expressions to
+  /// accomodate the new entry.
+  Expr *updateInit(unsigned Init, Expr *expr);
 
   // Explicit InitListExpr's originate from source code (and have valid source
   // locations). Implicit InitListExpr's are created by the semantic analyzer.
@@ -1682,6 +1712,13 @@
     return LBraceLoc.isValid() && RBraceLoc.isValid();
   }
   
+  /// @brief Retrieve the initializer list that describes the
+  /// syntactic form of the initializer.
+  ///
+  /// 
+  InitListExpr *getSyntacticForm() const { return SyntacticForm; }
+  void setSyntacticForm(InitListExpr *Init) { SyntacticForm = Init; }
+
   virtual SourceRange getSourceRange() const {
     return SourceRange(LBraceLoc, RBraceLoc);
   } 
@@ -1885,6 +1922,13 @@
              "Only valid on an array-range designator");
       return SourceLocation::getFromRawEncoding(ArrayOrRange.EllipsisLoc);
     }
+
+    SourceLocation getStartLocation() const {
+      if (Kind == FieldDesignator)
+        return getDotLoc().isInvalid()? getFieldLoc() : getDotLoc();
+      else
+        return getLBracketLoc();
+    }
   };
 
   static DesignatedInitExpr *Create(ASTContext &C, Designator *Designators, 

Modified: cfe/trunk/include/clang/AST/ExprCXX.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ExprCXX.h?rev=63242&r1=63241&r2=63242&view=diff

==============================================================================
--- cfe/trunk/include/clang/AST/ExprCXX.h (original)
+++ cfe/trunk/include/clang/AST/ExprCXX.h Wed Jan 28 15:54:33 2009
@@ -477,6 +477,12 @@
   SourceLocation getTypeBeginLoc() const { return TyBeginLoc; }
   SourceLocation getRParenLoc() const { return RParenLoc; }
 
+  /// @brief Whether this initialization expression was
+  /// implicitly-generated.
+  bool isImplicit() const { 
+    return TyBeginLoc.isInvalid() && RParenLoc.isInvalid(); 
+  }
+
   virtual SourceRange getSourceRange() const {
     return SourceRange(TyBeginLoc, RParenLoc);
   }

Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.def
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.def?rev=63242&r1=63241&r2=63242&view=diff

==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.def (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.def Wed Jan 28 15:54:33 2009
@@ -50,8 +50,20 @@
      "field designator %0 does not refer to a non-static data member")
 DIAG(note_field_designator_found, NOTE,
      "field designator refers here")
+DIAG(err_field_designator_anon_class, ERROR,
+     "field designator %0 refers to a member of an anonymous %select{struct|class|union}1")
 DIAG(err_designator_for_scalar_init, ERROR,
      "designator in initializer for scalar type %0")
+DIAG(warn_subobject_initializer_overrides, WARNING,
+     "subobject initialization overrides initialization of other fields within its enclosing subobject")
+DIAG(warn_initializer_overrides, WARNING,
+     "initializer overrides prior initialization of this subobject")
+DIAG(note_previous_initializer, NOTE,
+     "previous initialization %select{|with side effects }0is here%select{| (side effects may not occur at run time)}0")
+DIAG(warn_gnu_array_range_designator_unsupported, WARNING,
+     "GNU array-range designator extension is unsupported")
+DIAG(warn_designator_into_union_broken_init, WARNING,
+     "designated initialization of union member is broken")
 
 // Declarations.
 DIAG(ext_vla, EXTENSION,

Modified: cfe/trunk/lib/AST/Expr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Expr.cpp?rev=63242&r1=63241&r2=63242&view=diff

==============================================================================
--- cfe/trunk/lib/AST/Expr.cpp (original)
+++ cfe/trunk/lib/AST/Expr.cpp Wed Jan 28 15:54:33 2009
@@ -221,13 +221,31 @@
 
 InitListExpr::InitListExpr(SourceLocation lbraceloc, 
                            Expr **initExprs, unsigned numInits,
-                           SourceLocation rbraceloc, bool hadDesignators)
+                           SourceLocation rbraceloc)
   : Expr(InitListExprClass, QualType()),
-    LBraceLoc(lbraceloc), RBraceLoc(rbraceloc), HadDesignators(hadDesignators) {
+    LBraceLoc(lbraceloc), RBraceLoc(rbraceloc), SyntacticForm(0) {
 
   InitExprs.insert(InitExprs.end(), initExprs, initExprs+numInits);
 }
 
+void InitListExpr::resizeInits(ASTContext &Context, unsigned NumInits) {
+  for (unsigned Idx = NumInits, LastIdx = InitExprs.size(); Idx < LastIdx; ++Idx)
+    delete InitExprs[Idx];
+  InitExprs.resize(NumInits, 0);
+}
+
+Expr *InitListExpr::updateInit(unsigned Init, Expr *expr) {
+  if (Init >= InitExprs.size()) {
+    InitExprs.insert(InitExprs.end(), Init - InitExprs.size() + 1, 0);
+    InitExprs.back() = expr;
+    return 0;
+  }
+  
+  Expr *Result = cast_or_null<Expr>(InitExprs[Init]);
+  InitExprs[Init] = expr;
+  return Result;
+}
+
 /// getFunctionType - Return the underlying function type for this block.
 ///
 const FunctionType *BlockExpr::getFunctionType() const {
@@ -740,6 +758,12 @@
   return isEvaluatable(Ctx);
 }
 
+bool Expr::hasSideEffects(ASTContext &Ctx) const {
+  EvalResult Result;
+  Evaluate(Result, Ctx);
+  return Result.HasSideEffects;
+}
+
 /// isIntegerConstantExpr - this recursive routine will test if an expression is
 /// an integer constant expression. Note: With the introduction of VLA's in
 /// C99 the result of the sizeof operator is no longer always a constant

Modified: cfe/trunk/lib/AST/StmtPrinter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/StmtPrinter.cpp?rev=63242&r1=63241&r2=63242&view=diff

==============================================================================
--- cfe/trunk/lib/AST/StmtPrinter.cpp (original)
+++ cfe/trunk/lib/AST/StmtPrinter.cpp Wed Jan 28 15:54:33 2009
@@ -872,13 +872,38 @@
   OS << "{ ";
   for (unsigned i = 0, e = Node->getNumInits(); i != e; ++i) {
     if (i) OS << ", ";
-    PrintExpr(Node->getInit(i));
+    if (Node->getInit(i))
+      PrintExpr(Node->getInit(i));
+    else
+      OS << "0";
   }
   OS << " }";
 }
 
 void StmtPrinter::VisitDesignatedInitExpr(DesignatedInitExpr *Node) {
-  // FIXME!
+  for (DesignatedInitExpr::designators_iterator D = Node->designators_begin(),
+                      DEnd = Node->designators_end();
+       D != DEnd; ++D) {
+    if (D->isFieldDesignator()) {
+      if (D->getDotLoc().isInvalid())
+        OS << D->getFieldName()->getName() << ":";
+      else
+        OS << "." << D->getFieldName()->getName();
+    } else {
+      OS << "[";
+      if (D->isArrayDesignator()) {
+        PrintExpr(Node->getArrayIndex(*D));
+      } else {
+        PrintExpr(Node->getArrayRangeStart(*D));
+        OS << " ... ";
+        PrintExpr(Node->getArrayRangeEnd(*D));        
+      }
+      OS << "]";
+    }
+  }
+
+  OS << " = ";
+  PrintExpr(Node->getInit());
 }
 
 void StmtPrinter::VisitVAArgExpr(VAArgExpr *Node) {
@@ -1187,7 +1212,9 @@
 //===----------------------------------------------------------------------===//
 
 void Stmt::dumpPretty() const {
-  printPretty(llvm::errs());
+  llvm::raw_ostream &OS = llvm::errs();
+  printPretty(OS);
+  OS.flush();
 }
 
 void Stmt::printPretty(llvm::raw_ostream &OS, PrinterHelper* Helper) const {

Modified: cfe/trunk/lib/CodeGen/CGExprAgg.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprAgg.cpp?rev=63242&r1=63241&r2=63242&view=diff

==============================================================================
--- cfe/trunk/lib/CodeGen/CGExprAgg.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExprAgg.cpp Wed Jan 28 15:54:33 2009
@@ -71,7 +71,7 @@
   void VisitArraySubscriptExpr(ArraySubscriptExpr *E) {
     EmitAggLoadOfLValue(E);
   }
-
+  
   // Operators.
   //  case Expr::UnaryOperatorClass:
   //  case Expr::CastExprClass: 
@@ -303,11 +303,6 @@
 }
 
 void AggExprEmitter::EmitNonConstInit(InitListExpr *E) {
-  if (E->hadDesignators()) {
-    CGF.ErrorUnsupported(E, "initializer list with designators");
-    return;
-  }
-  
   const llvm::PointerType *APType =
     cast<llvm::PointerType>(DestPtr->getType());
   const llvm::Type *DestType = APType->getElementType();
@@ -346,6 +341,8 @@
   // FIXME: Are initializers affected by volatile?
   if (E->getType()->isComplexType()) {
     CGF.EmitComplexExprIntoAddr(E, LV.getAddress(), false);
+  } else if (isa<CXXZeroInitValueExpr>(E)) {
+    EmitNullInitializationToLValue(LV, E->getType());
   } else if (CGF.hasAggregateLLVMType(E->getType())) {
     CGF.EmitAnyExpr(E, LV.getAddress(), false);
   } else {
@@ -380,11 +377,6 @@
 }
 
 void AggExprEmitter::VisitInitListExpr(InitListExpr *E) {
-  if (E->hadDesignators()) {
-    CGF.ErrorUnsupported(E, "initializer list with designators");
-    return;
-  }
-
 #if 0
   // FIXME: Disabled while we figure out what to do about 
   // test/CodeGen/bitfield.c
@@ -426,7 +418,7 @@
 
     uint64_t NumArrayElements = AType->getNumElements();
     QualType ElementType = CGF.getContext().getCanonicalType(E->getType());
-    ElementType =CGF.getContext().getAsArrayType(ElementType)->getElementType();
+    ElementType = CGF.getContext().getAsArrayType(ElementType)->getElementType();
     
     unsigned CVRqualifier = ElementType.getCVRQualifiers();
 
@@ -479,7 +471,7 @@
     }
 
     // Unions only initialize one field.
-    // (things can get weird with designators, but they aren't
+    // (FIXME: things can get weird with designators, but they aren't
     // supported yet.)
     if (isUnion)
       break;

Modified: cfe/trunk/lib/CodeGen/CGExprConstant.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprConstant.cpp?rev=63242&r1=63241&r2=63242&view=diff

==============================================================================
--- cfe/trunk/lib/CodeGen/CGExprConstant.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExprConstant.cpp Wed Jan 28 15:54:33 2009
@@ -242,6 +242,8 @@
     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;
     for (RecordDecl::field_iterator Field = RD->field_begin(),
@@ -304,12 +306,6 @@
       return llvm::Constant::getNullValue(RetTy);
     }
     
-    // FIXME: We don't codegen or sema designators yet.
-    if (ILE->hadDesignators()) {
-      CGM.ErrorUnsupported(ILE, "initializer list with designators");
-      return llvm::UndefValue::get(ConvertType(ILE->getType()));
-    }
-
     if (ILE->getType()->isArrayType())
       return EmitArrayInitialization(ILE);
 

Modified: cfe/trunk/lib/CodeGen/CGExprScalar.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprScalar.cpp?rev=63242&r1=63241&r2=63242&view=diff

==============================================================================
--- cfe/trunk/lib/CodeGen/CGExprScalar.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExprScalar.cpp Wed Jan 28 15:54:33 2009
@@ -176,11 +176,6 @@
     if (!VType) 
       return Visit(E->getInit(0));
     
-    if (E->hadDesignators()) {
-      CGF.ErrorUnsupported(E, "initializer list with designators");
-      return llvm::UndefValue::get(CGF.ConvertType(E->getType()));
-    }
-    
     unsigned NumVectorElements = VType->getNumElements();
     const llvm::Type *ElementType = VType->getElementType();
 

Modified: cfe/trunk/lib/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=63242&r1=63241&r2=63242&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Wed Jan 28 15:54:33 2009
@@ -28,6 +28,7 @@
 #include "llvm/ADT/OwningPtr.h"
 #include <string>
 #include <vector>
+#include <map>
 
 namespace llvm {
   class APSInt;
@@ -1835,38 +1836,67 @@
 class InitListChecker {
   Sema *SemaRef;
   bool hadError;
+  std::map<InitListExpr *, InitListExpr *> SyntacticToSemantic;
+  InitListExpr *FullyStructuredList;
   
   void CheckImplicitInitList(InitListExpr *ParentIList, QualType T, 
-                             unsigned &Index);
+                             unsigned &Index, InitListExpr *StructuredInitList,
+                             unsigned &StructuredInitIndex);
   void CheckExplicitInitList(InitListExpr *IList, QualType &T,
-                             unsigned &Index);
-
+                             unsigned &Index, InitListExpr *StructuredInitList,
+                             unsigned &StructuredInitIndex);
   void CheckListElementTypes(InitListExpr *IList, QualType &DeclType, 
                              bool SubobjectIsDesignatorContext, 
-                             unsigned &Index);
+                             unsigned &Index,
+                             InitListExpr *StructuredInitList,
+                             unsigned &StructuredInitIndex);
   void CheckSubElementType(InitListExpr *IList, QualType ElemType, 
-                           Expr *expr, unsigned &Index);
+                           Expr *expr, unsigned &Index,
+                           InitListExpr *StructuredInitList,
+                           unsigned &StructuredInitIndex);
   // FIXME: Does DeclType need to be a reference type?
   void CheckScalarType(InitListExpr *IList, QualType &DeclType, 
-                       Expr *expr, unsigned &Index);
-  void CheckVectorType(InitListExpr *IList, QualType DeclType, unsigned &Index);
+                       Expr *expr, unsigned &Index,
+                       InitListExpr *StructuredInitList,
+                       unsigned &StructuredInitIndex);
+  void CheckVectorType(InitListExpr *IList, QualType DeclType, unsigned &Index,
+                       InitListExpr *StructuredInitList,
+                       unsigned &StructuredInitIndex);
   void CheckStructUnionTypes(InitListExpr *IList, QualType DeclType, 
                              RecordDecl::field_iterator Field, 
-                             bool SubobjectIsDesignatorContext, unsigned &Index);
+                             bool SubobjectIsDesignatorContext, unsigned &Index,
+                             InitListExpr *StructuredInitList,
+                             unsigned &StructuredInitIndex);
   void CheckArrayType(InitListExpr *IList, QualType &DeclType, 
                       llvm::APSInt elementIndex, 
-                      bool SubobjectIsDesignatorContext, unsigned &Index);
+                      bool SubobjectIsDesignatorContext, unsigned &Index,
+                      InitListExpr *StructuredInitList,
+                      unsigned &StructuredInitIndex);
   bool CheckDesignatedInitializer(InitListExpr *IList, DesignatedInitExpr *DIE, 
                                   DesignatedInitExpr::designators_iterator D,
                                   QualType &CurrentObjectType, 
                                   RecordDecl::field_iterator *NextField,
                                   llvm::APSInt *NextElementIndex,
-                                  unsigned &Index);
+                                  unsigned &Index,
+                                  InitListExpr *StructuredList,
+                                  unsigned &StructuredIndex);
+  InitListExpr *getStructuredSubobjectInit(InitListExpr *IList, unsigned Index,
+                                           QualType CurrentObjectType,
+                                           InitListExpr *StructuredList,
+                                           unsigned StructuredIndex,
+                                           SourceRange InitRange);
+  void UpdateStructuredListElement(InitListExpr *StructuredInitList,
+                                   unsigned &StructuredInitIndex,
+                                   Expr *expr);
   int numArrayElements(QualType DeclType);
   int numStructUnionElements(QualType DeclType);
 public:
   InitListChecker(Sema *S, InitListExpr *IL, QualType &T);
   bool HadError() { return hadError; }
+
+  // @brief Retrieves the fully-structured initializer list used for
+  // semantic analysis and code generation.
+  InitListExpr *getFullyStructuredList() const { return FullyStructuredList; }
 };
 
 /// BlockSemaInfo - When a block is being parsed, this contains information

Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=63242&r1=63241&r2=63242&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Wed Jan 28 15:54:33 2009
@@ -1136,6 +1136,9 @@
   }
 
   InitListChecker CheckInitList(this, InitList, DeclType);
+  if (!CheckInitList.HadError())
+    Init = CheckInitList.getFullyStructuredList();
+
   return CheckInitList.HadError();
 }
 
@@ -2209,6 +2212,12 @@
     for (unsigned i = 0; i < numInits; i++) {
       // FIXME: Need to get the type of the declaration for C++,
       // because it could be a reference?
+
+      // Implicitly-generated value initializations are okay.
+      if (isa<CXXZeroInitValueExpr>(Exp->getInit(i)) &&
+          cast<CXXZeroInitValueExpr>(Exp->getInit(i))->isImplicit()) 
+        continue;
+
       if (CheckForConstantInitializer(Exp->getInit(i),
                                       Exp->getInit(i)->getType()))
         return true;

Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=63242&r1=63241&r2=63242&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Wed Jan 28 15:54:33 2009
@@ -1985,7 +1985,7 @@
   // CheckInitializer() - it requires knowledge of the object being intialized. 
 
   InitListExpr *E = new (Context) InitListExpr(LBraceLoc, InitList, NumInit, 
-                                    RBraceLoc, Designators.hasAnyDesignators());
+                                               RBraceLoc);
   E->setType(Context.VoidTy); // FIXME: just a place holder for now.
   return Owned(E);
 }
@@ -3988,8 +3988,7 @@
   // Otherwise, create a compound literal expression as the base, and
   // iteratively process the offsetof designators.
   InitListExpr *IList =
-      new (Context) InitListExpr(SourceLocation(), 0, 0,
-                                 SourceLocation(), false);
+      new (Context) InitListExpr(SourceLocation(), 0, 0, SourceLocation());
   IList->setType(ArgTy);
   Expr *Res =
       new (Context) CompoundLiteralExpr(SourceLocation(), ArgTy, IList, false);

Modified: cfe/trunk/lib/Sema/SemaInit.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaInit.cpp?rev=63242&r1=63241&r2=63242&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaInit.cpp (original)
+++ cfe/trunk/lib/Sema/SemaInit.cpp Wed Jan 28 15:54:33 2009
@@ -15,19 +15,73 @@
 #include "clang/Parse/Designator.h"
 #include "clang/AST/ASTContext.h"
 #include "clang/AST/Expr.h"
+#include "clang/AST/ExprCXX.h"
 #include "clang/Basic/DiagnosticSema.h"
-#include <algorithm> // for std::count_if
-#include <functional> // for std::mem_fun
-
 using namespace clang;
 
+/// Recursively replaces NULL values within the given initializer list
+/// with expressions that perform value-initialization of the
+/// appropriate type.
+static void fillInValueInitializations(ASTContext &Context, InitListExpr *ILE) {
+  assert((ILE->getType() != Context.VoidTy) && "Should not have void type");
+  if (const RecordType *RType = ILE->getType()->getAsRecordType()) {
+    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 (Init >= NumInits)
+        break;
+
+      // FIXME: Check for fields with reference type in C++?
+      if (!ILE->getInit(Init))
+        ILE->setInit(Init, 
+                     new (Context) CXXZeroInitValueExpr(Field->getType(), 
+                                                        SourceLocation(),
+                                                        SourceLocation()));
+      else if (InitListExpr *InnerILE = dyn_cast<InitListExpr>(ILE->getInit(Init)))
+        fillInValueInitializations(Context, InnerILE);
+      ++Init;
+    }
+
+    return;
+  } 
+
+  QualType ElementType;
+  
+  if (const ArrayType *AType = Context.getAsArrayType(ILE->getType()))
+    ElementType = AType->getElementType();
+  else if (const VectorType *VType = ILE->getType()->getAsVectorType())
+    ElementType = VType->getElementType();
+  else 
+    ElementType = ILE->getType();
+  
+  for (unsigned Init = 0, NumInits = ILE->getNumInits(); Init != NumInits; 
+       ++Init) {
+    if (!ILE->getInit(Init))
+      ILE->setInit(Init, new (Context) CXXZeroInitValueExpr(ElementType, 
+                                                            SourceLocation(),
+                                                            SourceLocation()));
+    else if (InitListExpr *InnerILE = dyn_cast<InitListExpr>(ILE->getInit(Init)))
+      fillInValueInitializations(Context, InnerILE);
+  }
+}
+
 InitListChecker::InitListChecker(Sema *S, InitListExpr *IL, QualType &T) {
   hadError = false;
   SemaRef = S;
 
   unsigned newIndex = 0;
+  unsigned newStructuredIndex = 0;
+  FullyStructuredList 
+    = getStructuredSubobjectInit(IL, newIndex, T, 0, 0, SourceRange());
+  CheckExplicitInitList(IL, T, newIndex, FullyStructuredList, newStructuredIndex);
 
-  CheckExplicitInitList(IL, T, newIndex);
+  if (!hadError) {
+    fillInValueInitializations(SemaRef->Context, FullyStructuredList);
+  }
 }
 
 int InitListChecker::numArrayElements(QualType DeclType) {
@@ -42,17 +96,22 @@
 
 int InitListChecker::numStructUnionElements(QualType DeclType) {
   RecordDecl *structDecl = DeclType->getAsRecordType()->getDecl();
-  const int InitializableMembers 
-    = std::count_if(structDecl->field_begin(), structDecl->field_end(),
-                    std::mem_fun(&FieldDecl::getDeclName));
+  int InitializableMembers = 0;
+  for (RecordDecl::field_iterator Field = structDecl->field_begin(),
+                               FieldEnd = structDecl->field_end();
+       Field != FieldEnd; ++Field) {
+    if ((*Field)->getIdentifier() || !(*Field)->isBitField())
+      ++InitializableMembers;
+  }
   if (structDecl->isUnion())
     return std::min(InitializableMembers, 1);
   return InitializableMembers - structDecl->hasFlexibleArrayMember();
 }
 
 void InitListChecker::CheckImplicitInitList(InitListExpr *ParentIList, 
-                                            QualType T, unsigned &Index) {
-  llvm::SmallVector<Expr*, 4> InitExprs;
+                                            QualType T, unsigned &Index,
+                                            InitListExpr *StructuredList,
+                                            unsigned &StructuredIndex) {
   int maxElements = 0;
   
   if (T->isArrayType())
@@ -64,45 +123,39 @@
   else
     assert(0 && "CheckImplicitInitList(): Illegal type");
 
+  // FIXME: Perhaps we should move this warning elsewhere?
   if (maxElements == 0) {
     SemaRef->Diag(ParentIList->getInit(Index)->getLocStart(),
                   diag::err_implicit_empty_initializer);
+    ++Index;
     hadError = true;
     return;
   }
 
-  // Check the element types *before* we create the implicit init list;
-  // otherwise, we might end up taking the wrong number of elements
-  unsigned NewIndex = Index;
-  CheckListElementTypes(ParentIList, T, false, NewIndex);
-
-  for (int i = 0; i < maxElements; ++i) {
-    // Don't attempt to go past the end of the init list
-    if (Index >= ParentIList->getNumInits())
-      break;
-    Expr* expr = ParentIList->getInit(Index);
-    
-    // Add the expr to the new implicit init list and remove if from the old.
-    InitExprs.push_back(expr);
-    ParentIList->removeInit(Index);
-  }
-  // Synthesize an "implicit" InitListExpr (marked by the invalid source locs).
-  InitListExpr *ILE = new InitListExpr(SourceLocation(), 
-                                       &InitExprs[0], InitExprs.size(), 
-                                       SourceLocation(),
-                                       ParentIList->hadDesignators());
-  ILE->setType(T);
-
-  // Modify the parent InitListExpr to point to the implicit InitListExpr.
-  ParentIList->addInit(Index, ILE);
+  // Build a structured initializer list corresponding to this subobject.
+  InitListExpr *StructuredSubobjectInitList
+    = getStructuredSubobjectInit(ParentIList, Index, T, StructuredList, 
+                                 StructuredIndex, 
+                                 ParentIList->getInit(Index)->getSourceRange());
+  unsigned StructuredSubobjectInitIndex = 0;
+
+  // Check the element types and build the structural subobject.
+  CheckListElementTypes(ParentIList, T, false, Index,
+                        StructuredSubobjectInitList, 
+                        StructuredSubobjectInitIndex);
 }
 
 void InitListChecker::CheckExplicitInitList(InitListExpr *IList, QualType &T,
-                                            unsigned &Index) {
+                                            unsigned &Index,
+                                            InitListExpr *StructuredList,
+                                            unsigned &StructuredIndex) {
   assert(IList->isExplicit() && "Illegal Implicit InitListExpr");
-
-  CheckListElementTypes(IList, T, true, Index);
+  SyntacticToSemantic[IList] = StructuredList;
+  StructuredList->setSyntacticForm(IList);
+  CheckListElementTypes(IList, T, true, Index, StructuredList, 
+                        StructuredIndex);
   IList->setType(T);
+  StructuredList->setType(T);
   if (hadError)
     return;
 
@@ -131,27 +184,31 @@
 void InitListChecker::CheckListElementTypes(InitListExpr *IList,
                                             QualType &DeclType, 
                                             bool SubobjectIsDesignatorContext,
-                                            unsigned &Index) {
+                                            unsigned &Index,
+                                            InitListExpr *StructuredList,
+                                            unsigned &StructuredIndex) {
   if (DeclType->isScalarType()) {
-    CheckScalarType(IList, DeclType, 0, Index);
+    CheckScalarType(IList, DeclType, 0, Index, StructuredList, StructuredIndex);
   } else if (DeclType->isVectorType()) {
-    CheckVectorType(IList, DeclType, Index);
+    CheckVectorType(IList, DeclType, Index, StructuredList, StructuredIndex);
   } else if (DeclType->isAggregateType() || DeclType->isUnionType()) {
     if (DeclType->isStructureType() || DeclType->isUnionType()) {
       RecordDecl *RD = DeclType->getAsRecordType()->getDecl();
       CheckStructUnionTypes(IList, DeclType, RD->field_begin(), 
-                            SubobjectIsDesignatorContext, Index);
+                            SubobjectIsDesignatorContext, Index,
+                            StructuredList, StructuredIndex);
     } else if (DeclType->isArrayType()) {
       llvm::APSInt Zero(
                       SemaRef->Context.getTypeSize(SemaRef->Context.getSizeType()),
                       false);
-      CheckArrayType(IList, DeclType, Zero, SubobjectIsDesignatorContext, Index);
+      CheckArrayType(IList, DeclType, Zero, SubobjectIsDesignatorContext, Index,
+                     StructuredList, StructuredIndex);
     }
     else
-      assert(0 && "Aggregate that isn't a function or array?!");
+      assert(0 && "Aggregate that isn't a structure or array?!");
   } else if (DeclType->isVoidType() || DeclType->isFunctionType()) {
     // This type is invalid, issue a diagnostic.
-    Index++;
+    ++Index;
     SemaRef->Diag(IList->getLocStart(), diag::err_illegal_initializer_type)
       << DeclType;
     hadError = true;
@@ -165,31 +222,46 @@
 void InitListChecker::CheckSubElementType(InitListExpr *IList,
                                           QualType ElemType, 
                                           Expr *expr,
-                                          unsigned &Index) {
+                                          unsigned &Index,
+                                          InitListExpr *StructuredList,
+                                          unsigned &StructuredIndex) {
   if (InitListExpr *SubInitList = dyn_cast<InitListExpr>(expr)) {
     unsigned newIndex = 0;
-    CheckExplicitInitList(SubInitList, ElemType, newIndex);
-    Index++;
+    unsigned newStructuredIndex = 0;
+    InitListExpr *newStructuredList 
+      = getStructuredSubobjectInit(IList, Index, ElemType,
+                                   StructuredList, StructuredIndex,
+                                   SubInitList->getSourceRange());
+    CheckExplicitInitList(SubInitList, ElemType, newIndex, 
+                          newStructuredList, newStructuredIndex);
+    ++StructuredIndex;
+    ++Index;
   } else if (StringLiteral *lit =
              SemaRef->IsStringLiteralInit(expr, ElemType)) {
     SemaRef->CheckStringLiteralInit(lit, ElemType);
-    Index++;
+    UpdateStructuredListElement(StructuredList, StructuredIndex, lit);
+    ++Index;
   } else if (ElemType->isScalarType()) {
-    CheckScalarType(IList, ElemType, expr, Index);
+    CheckScalarType(IList, ElemType, expr, Index, StructuredList, 
+                    StructuredIndex);
   } else if (expr->getType()->getAsRecordType() &&
              SemaRef->Context.typesAreCompatible(
                expr->getType().getUnqualifiedType(),
                ElemType.getUnqualifiedType())) {
-    Index++;
+    UpdateStructuredListElement(StructuredList, StructuredIndex, expr);
+    ++Index;
     // FIXME: Add checking
   } else {
-    CheckImplicitInitList(IList, ElemType, Index);
-    Index++;
-  }
+    CheckImplicitInitList(IList, ElemType, Index, StructuredList, 
+                          StructuredIndex);
+    ++StructuredIndex;
+ }
 }
 
 void InitListChecker::CheckScalarType(InitListExpr *IList, QualType &DeclType,
-                                      Expr *expr, unsigned &Index) {
+                                      Expr *expr, unsigned &Index,
+                                      InitListExpr *StructuredList,
+                                      unsigned &StructuredIndex) {
   if (Index < IList->getNumInits()) {
     if (!expr)
       expr = IList->getInit(Index);
@@ -199,6 +271,7 @@
         << IList->getSourceRange();
       hadError = true;
       ++Index;
+      ++StructuredIndex;
       return;
     } else if (isa<DesignatedInitExpr>(expr)) {
       SemaRef->Diag(expr->getSourceRange().getBegin(), 
@@ -206,6 +279,7 @@
         << DeclType << expr->getSourceRange();
       hadError = true;
       ++Index;
+      ++StructuredIndex;
       return;
     }
 
@@ -219,18 +293,27 @@
         DIE->setInit(expr);
       else
         IList->setInit(Index, expr);
+
     }
+    if (hadError)
+      ++StructuredIndex;
+    else
+      UpdateStructuredListElement(StructuredList, StructuredIndex, expr);
     ++Index;
   } else {
     SemaRef->Diag(IList->getLocStart(), diag::err_empty_scalar_initializer)
       << IList->getSourceRange();
     hadError = true;
+    ++Index;
+    ++StructuredIndex;
     return;
   }
 }
 
 void InitListChecker::CheckVectorType(InitListExpr *IList, QualType DeclType, 
-                                      unsigned &Index) {
+                                      unsigned &Index,
+                                      InitListExpr *StructuredList,
+                                      unsigned &StructuredIndex) {
   if (Index < IList->getNumInits()) {
     const VectorType *VT = DeclType->getAsVectorType();
     int maxElements = VT->getNumElements();
@@ -240,7 +323,8 @@
       // Don't attempt to go past the end of the init list
       if (Index >= IList->getNumInits())
         break;
-      CheckSubElementType(IList, elementType, IList->getInit(Index), Index);
+      CheckSubElementType(IList, elementType, IList->getInit(Index), Index,
+                          StructuredList, StructuredIndex);
     }
   }
 }
@@ -248,12 +332,21 @@
 void InitListChecker::CheckArrayType(InitListExpr *IList, QualType &DeclType, 
                                      llvm::APSInt elementIndex,
                                      bool SubobjectIsDesignatorContext, 
-                                     unsigned &Index) {
+                                     unsigned &Index,
+                                     InitListExpr *StructuredList,
+                                     unsigned &StructuredIndex) {
   // Check for the special-case of initializing an array with a string.
   if (Index < IList->getNumInits()) {
     if (StringLiteral *lit = 
         SemaRef->IsStringLiteralInit(IList->getInit(Index), DeclType)) {
       SemaRef->CheckStringLiteralInit(lit, DeclType);
+      // We place the string literal directly into the resulting
+      // initializer list. This is the only place where the structure
+      // of the structured initializer list doesn't match exactly,
+      // because doing so would involve allocating one character
+      // constant for each string.
+      UpdateStructuredListElement(StructuredList, StructuredIndex, lit);
+      StructuredList->resizeInits(SemaRef->Context, StructuredIndex);
       ++Index;
       return;
     }
@@ -267,11 +360,14 @@
                   diag::err_variable_object_no_init)
       << VAT->getSizeExpr()->getSourceRange();
     hadError = true;
+    ++Index;
+    ++StructuredIndex;
     return;
   }
 
   // We might know the maximum number of elements in advance.
-  llvm::APSInt maxElements(elementIndex.getBitWidth(), elementIndex.isUnsigned());
+  llvm::APSInt maxElements(elementIndex.getBitWidth(),
+                           elementIndex.isUnsigned());
   bool maxElementsKnown = false;
   if (const ConstantArrayType *CAT =
         SemaRef->Context.getAsConstantArrayType(DeclType)) {
@@ -295,7 +391,8 @@
       // Handle this designated initializer. elementIndex will be
       // updated to be the next array element we'll initialize.
       if (CheckDesignatedInitializer(IList, DIE, DIE->designators_begin(), 
-                                     DeclType, 0, &elementIndex, Index)) {
+                                     DeclType, 0, &elementIndex, Index,
+                                     StructuredList, StructuredIndex)) {
         hadError = true;
         continue;
       }
@@ -320,7 +417,8 @@
       break;
 
     // Check this element.
-    CheckSubElementType(IList, elementType, IList->getInit(Index), Index);
+    CheckSubElementType(IList, elementType, IList->getInit(Index), Index,
+                        StructuredList, StructuredIndex);
     ++elementIndex;
 
     // If the array is of incomplete type, keep track of the number of
@@ -348,7 +446,9 @@
                                             QualType DeclType, 
                                             RecordDecl::field_iterator Field,
                                             bool SubobjectIsDesignatorContext, 
-                                            unsigned &Index) {
+                                            unsigned &Index,
+                                            InitListExpr *StructuredList,
+                                            unsigned &StructuredIndex) {
   RecordDecl* structDecl = DeclType->getAsRecordType()->getDecl();
     
   // If the record is invalid, some of it's members are invalid. To avoid
@@ -376,7 +476,8 @@
       // Handle this designated initializer. Field will be updated to
       // the next field that we'll be initializing.
       if (CheckDesignatedInitializer(IList, DIE, DIE->designators_begin(), 
-                                     DeclType, &Field, 0, Index))
+                                     DeclType, &Field, 0, Index,
+                                     StructuredList, StructuredIndex))
         hadError = true;
 
       continue;
@@ -391,13 +492,14 @@
     if (Field->getType()->isIncompleteArrayType())
       break;
 
-    if (!Field->getIdentifier()) {
-      // Don't initialize unnamed fields, e.g. "int : 20;"
+    if (!Field->getIdentifier() && Field->isBitField()) {
+      // Don't initialize unnamed bitfields, e.g. "int : 20;"
       ++Field;
       continue;
     }
 
-    CheckSubElementType(IList, Field->getType(), IList->getInit(Index), Index);
+    CheckSubElementType(IList, Field->getType(), IList->getInit(Index), Index,
+                        StructuredList, StructuredIndex);
     if (DeclType->isUnionType()) // FIXME: designated initializers?
       break;
 
@@ -416,8 +518,7 @@
 /// IList, is well-formed for a current object of type @p DeclType
 /// (C99 6.7.8). The actual subobject that this designator refers to
 /// within the current subobject is returned in either 
-/// @p DesignatedField or @p DesignatedIndex (whichever is
-/// appropriate).
+/// @p NextField or @p NextElementIndex (whichever is appropriate).
 ///
 /// @param IList  The initializer list in which this designated
 /// initializer occurs.
@@ -439,6 +540,10 @@
 /// @param Index  Index into @p IList where the designated initializer
 /// @p DIE occurs.
 ///
+/// @param StructuredList  The initializer list expression that
+/// describes all of the subobject initializers in the order they'll
+/// actually be initialized.
+///
 /// @returns true if there was an error, false otherwise.
 bool 
 InitListChecker::CheckDesignatedInitializer(InitListExpr *IList,
@@ -447,16 +552,30 @@
                                       QualType &CurrentObjectType,
                                       RecordDecl::field_iterator *NextField,
                                       llvm::APSInt *NextElementIndex,
-                                      unsigned &Index) {
-  bool IsFirstDesignator = (D == DIE->designators_begin());
-
+                                      unsigned &Index,
+                                      InitListExpr *StructuredList,
+                                      unsigned &StructuredIndex) {
   if (D == DIE->designators_end()) {
     // Check the actual initialization for the designated object type.
     bool prevHadError = hadError;
-    CheckSubElementType(IList, CurrentObjectType, DIE->getInit(), Index);
+    CheckSubElementType(IList, CurrentObjectType, DIE->getInit(), Index,
+                        StructuredList, StructuredIndex);
     return hadError && !prevHadError;
   }
 
+  bool IsFirstDesignator = (D == DIE->designators_begin());
+  assert((IsFirstDesignator || StructuredList) && 
+         "Need a non-designated initializer list to start from");
+
+  // Determine the structural initializer list that corresponds to the
+  // current subobject.
+  StructuredList = IsFirstDesignator? SyntacticToSemantic[IList]
+    : getStructuredSubobjectInit(IList, Index, CurrentObjectType, StructuredList,
+                                 StructuredIndex,
+                                 SourceRange(D->getStartLocation(),
+                                             DIE->getSourceRange().getEnd()));
+  assert(StructuredList && "Expected a structured initializer list");
+
   if (D->isFieldDesignator()) {
     // C99 6.7.8p7:
     //
@@ -478,56 +597,95 @@
       return true;
     }
 
+    // Note: we perform a linear search of the fields here, despite
+    // the fact that we have a faster lookup method, because we always
+    // need to compute the field's index.
     IdentifierInfo *FieldName = D->getFieldName();
-    DeclContext::lookup_result Lookup = RT->getDecl()->lookup(FieldName);
-    FieldDecl *DesignatedField = 0;
-    if (Lookup.first == Lookup.second) {
-      // Lookup did not find anything with this name.
-      SemaRef->Diag(D->getFieldLoc(), diag::err_field_designator_unknown)
-        << FieldName << CurrentObjectType;
-    } else if (isa<FieldDecl>(*Lookup.first)) {
-      // Name lookup found a field.
-      DesignatedField = cast<FieldDecl>(*Lookup.first);
-      // FIXME: Make sure this isn't a field in an anonymous
-      // struct/union.
-    } else {
-      // Name lookup found something, but it wasn't a field.
-      SemaRef->Diag(D->getFieldLoc(), diag::err_field_designator_nonfield)
-        << FieldName;
-      SemaRef->Diag((*Lookup.first)->getLocation(), 
-                    diag::note_field_designator_found);
+    unsigned FieldIndex = 0;
+    RecordDecl::field_iterator Field = RT->getDecl()->field_begin(),
+                            FieldEnd = RT->getDecl()->field_end();
+    for (; Field != FieldEnd; ++Field) {
+      if (Field->isUnnamedBitfield())
+        continue;
+
+      if (Field->getIdentifier() == FieldName)
+        break;
+
+      ++FieldIndex;
     }
 
-    if (!DesignatedField) {
+    if (Field == FieldEnd) {
+      // We did not find the field we're looking for. Produce a
+      // suitable diagnostic and return a failure.
+      DeclContext::lookup_result Lookup = RT->getDecl()->lookup(FieldName);
+      if (Lookup.first == Lookup.second) {
+        // Name lookup didn't find anything.
+        SemaRef->Diag(D->getFieldLoc(), diag::err_field_designator_unknown)
+          << FieldName << CurrentObjectType;
+      } else {
+        // Name lookup found something, but it wasn't a field.
+        SemaRef->Diag(D->getFieldLoc(), diag::err_field_designator_nonfield)
+          << FieldName;
+        SemaRef->Diag((*Lookup.first)->getLocation(), 
+                      diag::note_field_designator_found);
+      }
+
+      ++Index;
+      return true;
+    } else if (cast<RecordDecl>((*Field)->getDeclContext())
+                 ->isAnonymousStructOrUnion()) {
+      SemaRef->Diag(D->getFieldLoc(), diag::err_field_designator_anon_class)
+        << FieldName
+        << (cast<RecordDecl>((*Field)->getDeclContext())->isUnion()? 2 : 
+            (int)SemaRef->getLangOptions().CPlusPlus);
+      SemaRef->Diag((*Field)->getLocation(), diag::note_field_designator_found);
       ++Index;
       return true;
     }
-        
+
+    // All of the fields of a union are located at the same place in
+    // the initializer list.
+    // FIXME: Need to tell CodeGen which type to initialize to. ImplicitCastExpr?
+    if (RT->getDecl()->isUnion() && FieldIndex != 0) {
+      SemaRef->Diag(D->getStartLocation(), 
+                    diag::warn_designator_into_union_broken_init)
+        << SourceRange(D->getStartLocation(), DIE->getSourceRange().getEnd());
+      FieldIndex = 0;
+    }
+
     // Update the designator with the field declaration.
-    D->setField(DesignatedField);
+    D->setField(*Field);
       
+    // Make sure that our non-designated initializer list has space
+    // for a subobject corresponding to this field.
+    if (FieldIndex >= StructuredList->getNumInits())
+      StructuredList->resizeInits(SemaRef->Context, FieldIndex + 1);
+
     // Recurse to check later designated subobjects.
-    QualType FieldType = DesignatedField->getType();
-    if (CheckDesignatedInitializer(IList, DIE, ++D, FieldType, 0, 0, Index))
+    QualType FieldType = (*Field)->getType();
+    unsigned newStructuredIndex = FieldIndex;
+    if (CheckDesignatedInitializer(IList, DIE, ++D, FieldType, 0, 0, Index,
+                                   StructuredList, newStructuredIndex))
       return true;
 
     // Find the position of the next field to be initialized in this
     // subobject.
-    RecordDecl::field_iterator Field(DeclContext::decl_iterator(DesignatedField),
-                                     RT->getDecl()->decls_end());
     ++Field;
+    ++FieldIndex;
 
     // If this the first designator, our caller will continue checking
     // the rest of this struct/class/union subobject.
     if (IsFirstDesignator) {
       if (NextField)
         *NextField = Field;
+      StructuredIndex = FieldIndex;
       return false;
     }
 
     // Check the remaining fields within this class/struct/union subobject.
     bool prevHadError = hadError;
-    CheckStructUnionTypes(IList, CurrentObjectType, Field, false, Index);
+    CheckStructUnionTypes(IList, CurrentObjectType, Field, false, Index,
+                          StructuredList, FieldIndex);
     return hadError && !prevHadError;
   }
 
@@ -561,6 +719,9 @@
   else {
     assert(D->isArrayRangeDesignator() && "Need array-range designator");
     IndexExpr = DIE->getArrayRangeEnd(*D);
+    SemaRef->Diag(D->getEllipsisLoc(), 
+                  diag::warn_gnu_array_range_designator_unsupported)
+      << SourceRange(D->getLBracketLoc(), D->getRBracketLoc());
   }
 
   bool ConstExpr 
@@ -581,28 +742,115 @@
     }
   }
   
+  // Make sure that our non-designated initializer list has space
+  // for a subobject corresponding to this array element.
+  unsigned ElementIndex = DesignatedIndex.getZExtValue();
+  if (ElementIndex >= StructuredList->getNumInits())
+    StructuredList->resizeInits(SemaRef->Context, ElementIndex + 1);
+
   // Recurse to check later designated subobjects.
   QualType ElementType = AT->getElementType();
-  if (CheckDesignatedInitializer(IList, DIE, ++D, ElementType, 0, 0, Index))
+  if (CheckDesignatedInitializer(IList, DIE, ++D, ElementType, 0, 0, Index,
+                                 StructuredList, ElementIndex))
     return true;
 
   // Move to the next index in the array that we'll be initializing.
   ++DesignatedIndex;
+  ElementIndex = DesignatedIndex.getZExtValue();
 
   // If this the first designator, our caller will continue checking
   // the rest of this array subobject.
   if (IsFirstDesignator) {
     if (NextElementIndex)
       *NextElementIndex = DesignatedIndex;
+    StructuredIndex = ElementIndex;
     return false;
   }
     
   // Check the remaining elements within this array subobject.
   bool prevHadError = hadError;
-  CheckArrayType(IList, CurrentObjectType, DesignatedIndex, true, Index);
+  CheckArrayType(IList, CurrentObjectType, DesignatedIndex, true, Index,
+                 StructuredList, ElementIndex);
   return hadError && !prevHadError;  
 }
 
+// Get the structured initializer list for a subobject of type
+// @p CurrentObjectType.
+InitListExpr *
+InitListChecker::getStructuredSubobjectInit(InitListExpr *IList, unsigned Index,
+                                            QualType CurrentObjectType,
+                                            InitListExpr *StructuredList,
+                                            unsigned StructuredIndex,
+                                            SourceRange InitRange) {
+  Expr *ExistingInit = 0;
+  if (!StructuredList)
+    ExistingInit = SyntacticToSemantic[IList];
+  else if (StructuredIndex < StructuredList->getNumInits())
+    ExistingInit = StructuredList->getInit(StructuredIndex);
+  
+  if (InitListExpr *Result = dyn_cast_or_null<InitListExpr>(ExistingInit))
+    return Result;
+
+  if (ExistingInit) {
+    // We are creating an initializer list that initializes the
+    // subobjects of the current object, but there was already an
+    // initialization that completely initialized the current
+    // subobject, e.g., by a compound literal:
+    // 
+    // struct X { int a, b; };
+    // struct X xs[] = { [0] = (struct X) { 1, 2 }, [0].b = 3 };
+    // 
+    // Here, xs[0].a == 0 and xs[0].b == 3, since the second,
+    // designated initializer re-initializes the whole
+    // subobject [0], overwriting previous initializers.
+    SemaRef->Diag(InitRange.getBegin(), diag::warn_subobject_initializer_overrides)
+      << InitRange;
+    SemaRef->Diag(ExistingInit->getSourceRange().getBegin(), 
+                  diag::note_previous_initializer)
+      << ExistingInit->hasSideEffects(SemaRef->Context)
+      << ExistingInit->getSourceRange();
+  }
+
+  InitListExpr *Result 
+    = new (SemaRef->Context) InitListExpr(SourceLocation(), 0, 0, 
+                                          SourceLocation());
+  Result->setType(CurrentObjectType);
+
+  // Link this new initializer list into the structured initializer
+  // lists.
+  if (StructuredList)
+    StructuredList->updateInit(StructuredIndex, Result);
+  else {
+    Result->setSyntacticForm(IList);
+    SyntacticToSemantic[IList] = Result;
+  }
+
+  return Result;
+}
+
+/// Update the initializer at index @p StructuredIndex within the
+/// structured initializer list to the value @p expr.
+void InitListChecker::UpdateStructuredListElement(InitListExpr *StructuredList,
+                                                  unsigned &StructuredIndex,
+                                                  Expr *expr) {
+  // No structured initializer list to update
+  if (!StructuredList)
+    return;
+
+  if (Expr *PrevInit = StructuredList->updateInit(StructuredIndex, expr)) {
+    // This initializer overwrites a previous initializer. Warn.
+    SemaRef->Diag(expr->getSourceRange().getBegin(), 
+                  diag::warn_initializer_overrides)
+      << expr->getSourceRange();
+    SemaRef->Diag(PrevInit->getSourceRange().getBegin(), 
+                  diag::note_previous_initializer)
+      << (int)PrevInit->hasSideEffects(SemaRef->Context)
+      << PrevInit->getSourceRange();
+  }
+  
+  ++StructuredIndex;
+}
+
 /// Check that the given Index expression is a valid array designator
 /// value. This is essentailly just a wrapper around
 /// Expr::isIntegerConstantExpr that also checks for negative values

Modified: cfe/trunk/test/Sema/array-init.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/array-init.c?rev=63242&r1=63241&r2=63242&view=diff

==============================================================================
--- cfe/trunk/test/Sema/array-init.c (original)
+++ cfe/trunk/test/Sema/array-init.c Wed Jan 28 15:54:33 2009
@@ -1,4 +1,4 @@
-// RUN: clang -fsyntax-only -verify -pedantic %s
+// RUN: clang -fsyntax-only -pedantic -verify %s
 
 extern int foof() = 1; // expected-error{{illegal initializer (only variables can be initialized)}}
 
@@ -101,6 +101,7 @@
     { 2, 3 },
     { 4, 5, 6 }
   };
+  int q_sizecheck[(sizeof(q) / sizeof(short [3][2])) == 3? 1 : -1];
 }
 
 unsigned char asso_values[] = { 34 };
@@ -134,15 +135,19 @@
 void testTypedef()
 {
   AryT a = { 1, 2 }, b = { 3, 4, 5 };
+  int a_sizecheck[(sizeof(a) / sizeof(int)) == 2? 1 : -1];
+  int b_sizecheck[(sizeof(b) / sizeof(int)) == 3? 1 : -1];
 }
 
 static char const xx[] = "test";
+int xx_sizecheck[(sizeof(xx) / sizeof(char)) == 5? 1 : -1];
 static char const yy[5] = "test";
 static char const zz[3] = "test"; // expected-warning{{initializer-string for char array is too long}}
 
 void charArrays()
 {
 	static char const test[] = "test";
+        int test_sizecheck[(sizeof(test) / sizeof(char)) == 5? 1 : -1];
 	static char const test2[] = { "weird stuff" };
 	static char const test3[] = { "test", "excess stuff" }; // expected-error{{excess elements in char array initializer}}
 
@@ -171,6 +176,7 @@
 float r1[10] = {{7}}; //expected-warning{{braces around scalar initializer}}
 float r2[] = {{8}}; //expected-warning{{braces around scalar initializer}}
 char r3[][5] = {1,2,3,4,5,6};
+int r3_sizecheck[(sizeof(r3) / sizeof(char[5])) == 2? 1 : -1];
 char r3_2[sizeof r3 == 10 ? 1 : -1];
 float r4[1][2] = {1,{2},3,4}; //expected-warning{{braces around scalar initializer}} expected-warning{{excess elements in array initializer}}
 char r5[][5] = {"aa", "bbb", "ccccc"};
@@ -195,7 +201,7 @@
   return z.z; 
 } 
 struct s3 {void (*a)(void);} t5 = {autoStructTest};
-// GCC extension; flexible array init. Once this is implemented, the warning should be removed.
+// FIXME: GCC extension; flexible array init. Once this is implemented, the warning should be removed.
 // Note that clang objc implementation depends on this extension.
 struct {int a; int b[];} t6 = {1, {1, 2, 3}}; //expected-warning{{excess elements in array initializer}}
 union {char a; int b;} t7[] = {1, 2, 3};
@@ -238,3 +244,21 @@
 
 static void sppp_ipv6cp_up();
 const struct {} ipcp = { sppp_ipv6cp_up }; //expected-warning{{empty struct extension}} expected-warning{{excess elements in array initializer}}
+
+struct _Matrix { union { float m[4][4]; }; }; //expected-warning{{anonymous unions are a GNU extension in C}}
+typedef struct _Matrix Matrix;
+void test_matrix() {
+  const Matrix mat1 = {
+    { { 1.0f, 2.0f, 3.0f, 4.0f,
+        5.0f, 6.0f, 7.0f, 8.0f,
+        9.0f, 10.0f, 11.0f, 12.0f,
+        13.0f, 14.0f, 15.0f, 16.0f } }
+  };
+
+  const Matrix mat2 = {
+    1.0f, 2.0f, 3.0f, 4.0f,
+    5.0f, 6.0f, 7.0f, 8.0f,
+    9.0f, 10.0f, 11.0f, 12.0f,
+    13.0f, 14.0f, 15.0f, 16.0f 
+  };
+}

Modified: cfe/trunk/test/Sema/designated-initializers.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/designated-initializers.c?rev=63242&r1=63241&r2=63242&view=diff

==============================================================================
--- cfe/trunk/test/Sema/designated-initializers.c (original)
+++ cfe/trunk/test/Sema/designated-initializers.c Wed Jan 28 15:54:33 2009
@@ -18,7 +18,8 @@
 };
 
 int iarray3[10] = {
-  [5 ... 12] = 2 // expected-error{{array designator index (12) exceeds array bounds (10)}}
+  [5 ... 12] = 2 // expected-error{{array designator index (12) exceeds array bounds (10)}}\
+                // expected-warning{{GNU array-range designator extension is unsupported}}
 };
 
 struct point {
@@ -44,8 +45,8 @@
 
 struct point array2[10] = {
   [10].x = 2.0, // expected-error{{array designator index (10) exceeds array bounds (10)}}
-  [4 ... 5].y = 2.0,
-  [4 ... 6] = { .x = 3, .y = 4.0 }
+  [4 ... 5].y = 2.0, // expected-warning{{GNU array-range designator extension is unsupported}}
+  [4 ... 6] = { .x = 3, .y = 4.0 } // expected-warning{{GNU array-range designator extension is unsupported}}
 };
 
 struct point array3[10] = {
@@ -116,4 +117,25 @@
 // PR clang/3378
 int bitwidth[] = { [(long long int)1] = 5, [(short int)2] = 2 };
 int a[]= { [sizeof(int)] = 0 };
-int a2[]= { [0 ... sizeof(int)] = 0 };
+int a2[]= { [0 ... sizeof(int)] = 0 }; // expected-warning{{GNU array-range designator extension is unsupported}}
+
+// Test warnings about initializers overriding previous initializers
+struct X {
+  int a, b, c;
+};
+
+int counter = 0;
+int get8() { ++counter; return 8; }
+
+void test() {
+  struct X xs[] = { 
+    [0] = (struct X){1, 2}, // expected-note{{previous initialization is here}}
+    [0].c = 3,  // expected-warning{{subobject initialization overrides initialization of other fields within its enclosing subobject}}
+    (struct X) {4, 5, 6}, // expected-note{{previous initialization is here}}
+    [1].b = get8(), // expected-warning{{subobject initialization overrides initialization of other fields within its enclosing subobject}}
+    [0].b = 8
+  };
+}
+
+// FIXME: we need to 
+union { char c; long l; } u1 = { .l = 0xFFFF }; // expected-warning{{designated initialization of union member is broken}}

Modified: cfe/trunk/test/Sema/vector-init.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/vector-init.c?rev=63242&r1=63241&r2=63242&view=diff

==============================================================================
--- cfe/trunk/test/Sema/vector-init.c (original)
+++ cfe/trunk/test/Sema/vector-init.c Wed Jan 28 15:54:33 2009
@@ -1,5 +1,15 @@
-// RUN: clang %s -verify -fsyntax-only
+// RUN: clang %s -fsyntax-only -verify
 
 typedef __attribute__(( ext_vector_type(4) ))  float float4;
+//typedef float float4 __attribute__((vector_size(16)));
 
 float4 foo = (float4){ 1.0, 2.0, 3.0, 4.0 };
+
+float4 array[] = { 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0};
+int array_sizecheck[(sizeof(array) / sizeof(float4)) == 3? 1 : -1];
+
+float4 array2[2] = { 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 
+                     9.0 }; // expected-warning {{excess elements in array initializer}}
+
+float4 array3[2] = { {1.0, 2.0, 3.0}, 5.0, 6.0, 7.0, 8.0,
+                     9.0 }; // expected-warning {{excess elements in array initializer}}





More information about the cfe-commits mailing list