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)



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@63242 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp
index 8e43f99..ed73bfa 100644
--- a/lib/AST/Expr.cpp
+++ b/lib/AST/Expr.cpp
@@ -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
diff --git a/lib/AST/StmtPrinter.cpp b/lib/AST/StmtPrinter.cpp
index 80de5b8..7a558ab 100644
--- a/lib/AST/StmtPrinter.cpp
+++ b/lib/AST/StmtPrinter.cpp
@@ -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 {