Initial implementation of semantic analysis and ASTs for C99
designated initializers. This implementation should cover all of the
constraints in C99 6.7.8, including long, complex designations and
computing the size of incomplete array types initialized with a
designated initializer. Please see the new test-case and holler if you
find cases where this doesn't work.

There are still some wrinkles with GNU's anonymous structs and
anonymous unions (it isn't clear how these should work; we'll just
follow GCC's lead) and with designated initializers for the members of a
union. I'll tackle those very soon.

CodeGen is still nonexistent, and there's some leftover code in the
parser's representation of designators that I'll also need to clean up.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@62737 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp
index 03b4949..70b63fe 100644
--- a/lib/AST/Expr.cpp
+++ b/lib/AST/Expr.cpp
@@ -1349,6 +1349,106 @@
 }
 
 //===----------------------------------------------------------------------===//
+//  DesignatedInitExpr
+//===----------------------------------------------------------------------===//
+
+IdentifierInfo *DesignatedInitExpr::Designator::getFieldName() {
+  assert(Kind == FieldDesignator && "Only valid on a field designator");
+  if (Field.NameOrField & 0x01)
+    return reinterpret_cast<IdentifierInfo *>(Field.NameOrField&~0x01);
+  else
+    return getField()->getIdentifier();
+}
+
+DesignatedInitExpr *
+DesignatedInitExpr::Create(ASTContext &C, Designator *Designators, 
+                           unsigned NumDesignators,
+                           Expr **IndexExprs, unsigned NumIndexExprs,
+                           SourceLocation ColonOrEqualLoc,
+                           bool UsesColonSyntax, Expr *Init) {
+  void *Mem = C.getAllocator().Allocate(sizeof(DesignatedInitExpr) +
+                                        sizeof(Designator) * NumDesignators +
+                                        sizeof(Stmt *) * (NumIndexExprs + 1),
+                                        8);
+  DesignatedInitExpr *DIE 
+    = new (Mem) DesignatedInitExpr(C.VoidTy, NumDesignators,
+                                   ColonOrEqualLoc, UsesColonSyntax,
+                                   NumIndexExprs + 1);
+
+  // Fill in the designators
+  unsigned ExpectedNumSubExprs = 0;
+  designators_iterator Desig = DIE->designators_begin();
+  for (unsigned Idx = 0; Idx < NumDesignators; ++Idx, ++Desig) {
+    new (static_cast<void*>(Desig)) Designator(Designators[Idx]);
+    if (Designators[Idx].isArrayDesignator())
+      ++ExpectedNumSubExprs;
+    else if (Designators[Idx].isArrayRangeDesignator())
+      ExpectedNumSubExprs += 2;
+  }
+  assert(ExpectedNumSubExprs == NumIndexExprs && "Wrong number of indices!");
+
+  // Fill in the subexpressions, including the initializer expression.
+  child_iterator Child = DIE->child_begin();
+  *Child++ = Init;
+  for (unsigned Idx = 0; Idx < NumIndexExprs; ++Idx, ++Child)
+    *Child = IndexExprs[Idx];
+
+  return DIE;
+}
+
+SourceRange DesignatedInitExpr::getSourceRange() const {
+  SourceLocation StartLoc;
+  Designator &First = *const_cast<DesignatedInitExpr*>(this)->designators_begin();
+  if (First.isFieldDesignator()) {
+    if (UsesColonSyntax)
+      StartLoc = SourceLocation::getFromRawEncoding(First.Field.FieldLoc);
+    else
+      StartLoc = SourceLocation::getFromRawEncoding(First.Field.DotLoc);
+  } else
+    StartLoc = SourceLocation::getFromRawEncoding(First.ArrayOrRange.LBracketLoc);
+  return SourceRange(StartLoc, getInit()->getSourceRange().getEnd());
+}
+
+DesignatedInitExpr::designators_iterator DesignatedInitExpr::designators_begin() {
+  char* Ptr = static_cast<char*>(static_cast<void *>(this));
+  Ptr += sizeof(DesignatedInitExpr);
+  return static_cast<Designator*>(static_cast<void*>(Ptr));
+}
+
+DesignatedInitExpr::designators_iterator DesignatedInitExpr::designators_end() {
+  return designators_begin() + NumDesignators;
+}
+
+Expr *DesignatedInitExpr::getArrayIndex(const Designator& D) {
+  assert(D.Kind == Designator::ArrayDesignator && "Requires array designator");
+  char* Ptr = static_cast<char*>(static_cast<void *>(this));
+  Ptr += sizeof(DesignatedInitExpr);
+  Ptr += sizeof(Designator) * NumDesignators;
+  Stmt **SubExprs = reinterpret_cast<Stmt**>(reinterpret_cast<void**>(Ptr));
+  return cast<Expr>(*(SubExprs + D.ArrayOrRange.Index + 1));
+}
+
+Expr *DesignatedInitExpr::getArrayRangeStart(const Designator& D) {
+  assert(D.Kind == Designator::ArrayRangeDesignator && 
+         "Requires array range designator");
+  char* Ptr = static_cast<char*>(static_cast<void *>(this));
+  Ptr += sizeof(DesignatedInitExpr);
+  Ptr += sizeof(Designator) * NumDesignators;
+  Stmt **SubExprs = reinterpret_cast<Stmt**>(reinterpret_cast<void**>(Ptr));
+  return cast<Expr>(*(SubExprs + D.ArrayOrRange.Index + 1));
+}
+
+Expr *DesignatedInitExpr::getArrayRangeEnd(const Designator& D) {
+  assert(D.Kind == Designator::ArrayRangeDesignator && 
+         "Requires array range designator");
+  char* Ptr = static_cast<char*>(static_cast<void *>(this));
+  Ptr += sizeof(DesignatedInitExpr);
+  Ptr += sizeof(Designator) * NumDesignators;
+  Stmt **SubExprs = reinterpret_cast<Stmt**>(reinterpret_cast<void**>(Ptr));
+  return cast<Expr>(*(SubExprs + D.ArrayOrRange.Index + 2));
+}
+
+//===----------------------------------------------------------------------===//
 //  ExprIterator.
 //===----------------------------------------------------------------------===//
 
@@ -1533,6 +1633,17 @@
   return InitExprs.size() ? &InitExprs[0] + InitExprs.size() : 0;
 }
 
+/// DesignatedInitExpr
+Stmt::child_iterator DesignatedInitExpr::child_begin() {
+  char* Ptr = static_cast<char*>(static_cast<void *>(this));
+  Ptr += sizeof(DesignatedInitExpr);
+  Ptr += sizeof(Designator) * NumDesignators;
+  return reinterpret_cast<Stmt**>(reinterpret_cast<void**>(Ptr));
+}
+Stmt::child_iterator DesignatedInitExpr::child_end() {
+  return child_iterator(&*child_begin() + NumSubExprs);
+}
+
 // ObjCStringLiteral
 Stmt::child_iterator ObjCStringLiteral::child_begin() { 
   return child_iterator();