Implement support for designated initializers that refer to members of
anonymous structs or unions. Fixes PR3778.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@69153 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp
index dd34617..e2dd64a 100644
--- a/lib/AST/Expr.cpp
+++ b/lib/AST/Expr.cpp
@@ -20,6 +20,7 @@
 #include "clang/AST/RecordLayout.h"
 #include "clang/AST/StmtVisitor.h"
 #include "clang/Basic/TargetInfo.h"
+#include <algorithm>
 using namespace clang;
 
 //===----------------------------------------------------------------------===//
@@ -1499,6 +1500,19 @@
     return getField()->getIdentifier();
 }
 
+DesignatedInitExpr::DesignatedInitExpr(QualType Ty, unsigned NumDesignators, 
+                                       const Designator *Designators,
+                                       SourceLocation EqualOrColonLoc, 
+                                       bool GNUSyntax,
+                                       unsigned NumSubExprs)
+  : Expr(DesignatedInitExprClass, Ty), 
+    EqualOrColonLoc(EqualOrColonLoc), GNUSyntax(GNUSyntax), 
+    NumDesignators(NumDesignators), NumSubExprs(NumSubExprs) { 
+  this->Designators = new Designator[NumDesignators];
+  for (unsigned I = 0; I != NumDesignators; ++I)
+    this->Designators[I] = Designators[I];
+}
+
 DesignatedInitExpr *
 DesignatedInitExpr::Create(ASTContext &C, Designator *Designators, 
                            unsigned NumDesignators,
@@ -1506,10 +1520,9 @@
                            SourceLocation ColonOrEqualLoc,
                            bool UsesColonSyntax, Expr *Init) {
   void *Mem = C.Allocate(sizeof(DesignatedInitExpr) +
-                         sizeof(Designator) * NumDesignators +
                          sizeof(Stmt *) * (NumIndexExprs + 1), 8);
   DesignatedInitExpr *DIE 
-    = new (Mem) DesignatedInitExpr(C.VoidTy, NumDesignators,
+    = new (Mem) DesignatedInitExpr(C.VoidTy, NumDesignators, Designators,
                                    ColonOrEqualLoc, UsesColonSyntax,
                                    NumIndexExprs + 1);
 
@@ -1517,7 +1530,6 @@
   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())
@@ -1549,22 +1561,10 @@
   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));
 }
@@ -1574,7 +1574,6 @@
          "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));
 }
@@ -1584,11 +1583,43 @@
          "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));
 }
 
+/// \brief Replaces the designator at index @p Idx with the series
+/// of designators in [First, Last).
+void DesignatedInitExpr::ExpandDesignator(unsigned Idx, 
+                                          const Designator *First, 
+                                          const Designator *Last) {
+  unsigned NumNewDesignators = Last - First;
+  if (NumNewDesignators == 0) {
+    std::copy_backward(Designators + Idx + 1,
+                       Designators + NumDesignators,
+                       Designators + Idx);
+    --NumNewDesignators;
+    return;
+  } else if (NumNewDesignators == 1) {
+    Designators[Idx] = *First;
+    return;
+  }
+
+  Designator *NewDesignators 
+    = new Designator[NumDesignators - 1 + NumNewDesignators];
+  std::copy(Designators, Designators + Idx, NewDesignators);
+  std::copy(First, Last, NewDesignators + Idx);
+  std::copy(Designators + Idx + 1, Designators + NumDesignators,
+            NewDesignators + Idx + NumNewDesignators);
+  delete [] Designators;
+  Designators = NewDesignators;
+  NumDesignators = NumDesignators - 1 + NumNewDesignators;
+}
+
+void DesignatedInitExpr::Destroy(ASTContext &C) {
+  delete [] Designators;
+  Expr::Destroy(C);
+}
+
 //===----------------------------------------------------------------------===//
 //  ExprIterator.
 //===----------------------------------------------------------------------===//
@@ -1774,7 +1805,6 @@
 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() {