Hi Richard,
Here is an updated patch based on your suggestion earlier. We discussed this
briefly during the social, but for the record, I tried several different 
representations
for the vector of "updater" expressions and settled on using an InitListExpr 
for now.
Using an InitListExpr avoids having to decode a DesignatedInitExpr in
the CodeGen phase, and also allows merging multiple DesignatedInitExpr into
a common data structure, which then allows better diagnostics. The problem of
having to leave "holes" in an InitListExpr (to account for fields that are 
initialized by
the "base" expression and not to be overwritten by zeros) is solved by 
inserting a
new type of NoInitExpr as placeholders into these "holes."

There are two new functions in lib/AST/StmtProfile.cpp which I had to add in
order to build clang, but for which I am having trouble writing coverage tests. 
I
left a FIXME note there for now.

Feedback and advice are greatly appreciated,

- Gao


http://reviews.llvm.org/D5789

Files:
  include/clang/AST/DataRecursiveASTVisitor.h
  include/clang/AST/Expr.h
  include/clang/AST/RecursiveASTVisitor.h
  include/clang/Basic/StmtNodes.td
  include/clang/Serialization/ASTBitCodes.h
  lib/AST/Expr.cpp
  lib/AST/ExprClassification.cpp
  lib/AST/ExprConstant.cpp
  lib/AST/ItaniumMangle.cpp
  lib/AST/StmtPrinter.cpp
  lib/AST/StmtProfile.cpp
  lib/CodeGen/CGExprAgg.cpp
  lib/CodeGen/CGExprCXX.cpp
  lib/Sema/SemaExceptionSpec.cpp
  lib/Sema/SemaInit.cpp
  lib/Sema/TreeTransform.h
  lib/Serialization/ASTReaderStmt.cpp
  lib/Serialization/ASTWriter.cpp
  lib/Serialization/ASTWriterStmt.cpp
  lib/StaticAnalyzer/Core/ExprEngine.cpp
  test/Analysis/designated-initializer.c
  test/CodeGen/Inputs/stdio.h
  test/CodeGen/partial-reinitialization1.c
  test/CodeGen/partial-reinitialization2.c
  test/PCH/designated-init.c.h
  test/Sema/designated-initializers.c
  tools/libclang/CXCursor.cpp

EMAIL PREFERENCES
  http://reviews.llvm.org/settings/panel/emailpreferences/
Index: include/clang/AST/DataRecursiveASTVisitor.h
===================================================================
--- include/clang/AST/DataRecursiveASTVisitor.h
+++ include/clang/AST/DataRecursiveASTVisitor.h
@@ -2204,9 +2204,11 @@
 DEF_TRAVERSE_STMT(CXXThrowExpr, {})
 DEF_TRAVERSE_STMT(UserDefinedLiteral, {})
 DEF_TRAVERSE_STMT(DesignatedInitExpr, {})
+DEF_TRAVERSE_STMT(DesignatedInitUpdateExpr, {})
 DEF_TRAVERSE_STMT(ExtVectorElementExpr, {})
 DEF_TRAVERSE_STMT(GNUNullExpr, {})
 DEF_TRAVERSE_STMT(ImplicitValueInitExpr, {})
+DEF_TRAVERSE_STMT(NoInitExpr, {})
 DEF_TRAVERSE_STMT(ObjCBoolLiteralExpr, {})
 DEF_TRAVERSE_STMT(ObjCEncodeExpr, {
   if (TypeSourceInfo *TInfo = S->getEncodedTypeSourceInfo())
Index: include/clang/AST/Expr.h
===================================================================
--- include/clang/AST/Expr.h
+++ include/clang/AST/Expr.h
@@ -4262,6 +4262,86 @@
   }
 };
 
+/// \brief Represents a place-holder for an object not to be initialized by
+/// anything.
+///
+/// This only makes sense when it appears as part of an updater of a
+/// DesignatedInitUpdateExpr (see below). The base expression of a DIUE
+/// initializes a big object, and the NoInitExpr's mark the spots within the
+/// big object not to be overwritten by the updater.
+///
+/// \see DesignatedInitUpdateExpr
+class NoInitExpr : public Expr {
+public:
+  explicit NoInitExpr(QualType ty)
+    : Expr(NoInitExprClass, ty, VK_RValue, OK_Ordinary,
+           false, false, ty->isInstantiationDependentType(), false) { }
+
+  explicit NoInitExpr(EmptyShell Empty)
+    : Expr(NoInitExprClass, Empty) { }
+
+  static bool classof(const Stmt *T) {
+    return T->getStmtClass() == NoInitExprClass;
+  }
+
+  SourceLocation getLocStart() const LLVM_READONLY { return SourceLocation(); }
+  SourceLocation getLocEnd() const LLVM_READONLY { return SourceLocation(); }
+
+  // Iterators
+  child_range children() { return child_range(); }
+};
+
+// In cases like:
+//   struct Q { int a, b, c; };
+//   Q *getQ();
+//   void foo() {
+//     struct A { Q q; } a = { *getQ(), .q.b = 3 };
+//   }
+//
+// We will have an InitListExpr for a, with type A, and then a
+// DesignatedInitUpdateExpr for "a.q" with type Q. The "base" for this DIUE
+// is the call expression *getQ(); the "updater" for the DIUE is ".q.b = 3"
+//
+class DesignatedInitUpdateExpr : public Expr {
+  // BaseAndUpdaterExprs[0] is the base expression;
+  // BaseAndUpdaterExprs[1] is an InitListExpr overwriting part of the base.
+  Stmt *BaseAndUpdaterExprs[2];
+  SourceLocation LBraceLoc, RBraceLoc;
+
+public:
+  DesignatedInitUpdateExpr(const ASTContext &C, SourceLocation lbraceloc,
+                           Expr* baseExprs, SourceLocation rbraceloc);
+
+  explicit DesignatedInitUpdateExpr(EmptyShell Empty)
+    : Expr(DesignatedInitUpdateExprClass, Empty) { }
+
+  SourceLocation getLocStart() const LLVM_READONLY;
+  SourceLocation getLocEnd() const LLVM_READONLY;
+
+  static bool classof(const Stmt *T) {
+    return T->getStmtClass() == DesignatedInitUpdateExprClass;
+  }
+
+  SourceLocation getLBraceLoc() const { return LBraceLoc; }
+  void setLBraceLoc(SourceLocation Loc) { LBraceLoc = Loc; }
+  SourceLocation getRBraceLoc() const { return RBraceLoc; }
+  void setRBraceLoc(SourceLocation Loc) { RBraceLoc = Loc; }
+
+  Expr *getBase() const { return cast<Expr>(BaseAndUpdaterExprs[0]); }
+  void setBase(Expr *Base) { BaseAndUpdaterExprs[0] = Base; }
+
+  InitListExpr *getUpdater() const {
+    return cast<InitListExpr>(BaseAndUpdaterExprs[1]);
+  }
+  void setUpdater(Expr *Updater) { BaseAndUpdaterExprs[1] = Updater; }
+
+  // Iterators
+  // children = the base and the updater
+  child_range children() {
+    return child_range(&BaseAndUpdaterExprs[0], &BaseAndUpdaterExprs[0] + 2);
+  }
+};
+
 /// \brief Represents an implicitly-generated value initialization of
 /// an object of a given type.
 ///
Index: include/clang/AST/RecursiveASTVisitor.h
===================================================================
--- include/clang/AST/RecursiveASTVisitor.h
+++ include/clang/AST/RecursiveASTVisitor.h
@@ -2234,9 +2234,11 @@
 DEF_TRAVERSE_STMT(CXXThrowExpr, {})
 DEF_TRAVERSE_STMT(UserDefinedLiteral, {})
 DEF_TRAVERSE_STMT(DesignatedInitExpr, {})
+DEF_TRAVERSE_STMT(DesignatedInitUpdateExpr, {})
 DEF_TRAVERSE_STMT(ExtVectorElementExpr, {})
 DEF_TRAVERSE_STMT(GNUNullExpr, {})
 DEF_TRAVERSE_STMT(ImplicitValueInitExpr, {})
+DEF_TRAVERSE_STMT(NoInitExpr, {})
 DEF_TRAVERSE_STMT(ObjCBoolLiteralExpr, {})
 DEF_TRAVERSE_STMT(ObjCEncodeExpr, {
   if (TypeSourceInfo *TInfo = S->getEncodedTypeSourceInfo())
Index: include/clang/Basic/StmtNodes.td
===================================================================
--- include/clang/Basic/StmtNodes.td
+++ include/clang/Basic/StmtNodes.td
@@ -77,7 +77,9 @@
 def ExtVectorElementExpr : DStmt<Expr>;
 def InitListExpr : DStmt<Expr>;
 def DesignatedInitExpr : DStmt<Expr>;
+def DesignatedInitUpdateExpr : DStmt<Expr>;
 def ImplicitValueInitExpr : DStmt<Expr>;
+def NoInitExpr : DStmt<Expr>;
 def ParenListExpr : DStmt<Expr>;
 def VAArgExpr : DStmt<Expr>;
 def GenericSelectionExpr : DStmt<Expr>;
Index: include/clang/Serialization/ASTBitCodes.h
===================================================================
--- include/clang/Serialization/ASTBitCodes.h
+++ include/clang/Serialization/ASTBitCodes.h
@@ -1192,8 +1192,12 @@
       EXPR_INIT_LIST,
       /// \brief A DesignatedInitExpr record.
       EXPR_DESIGNATED_INIT,
+      /// \brief A DesignatedInitUpdateExpr record.
+      EXPR_DESIGNATED_INIT_UPDATE,
       /// \brief An ImplicitValueInitExpr record.
       EXPR_IMPLICIT_VALUE_INIT,
+      /// \brief An NoInitExpr record.
+      EXPR_NO_INIT,
       /// \brief A VAArgExpr record.
       EXPR_VA_ARG,
       /// \brief An AddrLabelExpr record.
Index: lib/AST/Expr.cpp
===================================================================
--- lib/AST/Expr.cpp
+++ lib/AST/Expr.cpp
@@ -2772,6 +2772,13 @@
     const Expr *Exp = cast<CompoundLiteralExpr>(this)->getInitializer();
     return Exp->isConstantInitializer(Ctx, false, Culprit);
   }
+  case DesignatedInitUpdateExprClass: {
+    const DesignatedInitUpdateExpr *DIUE = cast<DesignatedInitUpdateExpr>(this);
+    if (!DIUE->getBase()->isConstantInitializer(Ctx, false, Culprit))
+      return false;
+    assert(false && "DIUE->getBase() should not be a constant expression");
+    break;
+  }
   case InitListExprClass: {
     const InitListExpr *ILE = cast<InitListExpr>(this);
     if (ILE->getType()->isArrayType()) {
@@ -2818,6 +2825,7 @@
     break;
   }
   case ImplicitValueInitExprClass:
+  case NoInitExprClass:
     return true;
   case ParenExprClass:
     return cast<ParenExpr>(this)->getSubExpr()
@@ -2925,6 +2933,7 @@
   case UnaryExprOrTypeTraitExprClass:
   case AddrLabelExprClass:
   case GNUNullExprClass:
+  case NoInitExprClass:
   case CXXBoolLiteralExprClass:
   case CXXNullPtrLiteralExprClass:
   case CXXThisExprClass:
@@ -2975,6 +2984,7 @@
   case CompoundLiteralExprClass:
   case ExtVectorElementExprClass:
   case DesignatedInitExprClass:
+  case DesignatedInitUpdateExprClass:
   case ParenListExprClass:
   case CXXPseudoDestructorExprClass:
   case CXXStdInitializerListExprClass:
@@ -3981,6 +3991,30 @@
   NumDesignators = NumDesignators - 1 + NumNewDesignators;
 }
 
+DesignatedInitUpdateExpr::DesignatedInitUpdateExpr(const ASTContext &C,
+    SourceLocation lbraceloc, Expr *baseExpr, SourceLocation rbraceloc)
+  : Expr(DesignatedInitUpdateExprClass, baseExpr->getType(), VK_RValue,
+         OK_Ordinary, false, false, false, false),
+    LBraceLoc(lbraceloc), RBraceLoc(rbraceloc) {
+  BaseAndUpdaterExprs[0] = baseExpr;
+
+  InitListExpr *ILE = new (C) InitListExpr(C, lbraceloc, None, rbraceloc);
+  ILE->setType(baseExpr->getType());
+  BaseAndUpdaterExprs[1] = ILE;
+}
+
+SourceLocation DesignatedInitUpdateExpr::getLocStart() const {
+  if (LBraceLoc.isValid())
+    return LBraceLoc;
+  return getBase()->getLocStart();
+}
+
+SourceLocation DesignatedInitUpdateExpr::getLocEnd() const {
+  if (RBraceLoc.isValid())
+    return RBraceLoc;
+  return getUpdater()->getLocEnd();
+}
+
 ParenListExpr::ParenListExpr(const ASTContext& C, SourceLocation lparenloc,
                              ArrayRef<Expr*> exprs,
                              SourceLocation rparenloc)
Index: lib/AST/ExprClassification.cpp
===================================================================
--- lib/AST/ExprClassification.cpp
+++ lib/AST/ExprClassification.cpp
@@ -183,6 +183,8 @@
   case Expr::ObjCIndirectCopyRestoreExprClass:
   case Expr::AtomicExprClass:
   case Expr::CXXFoldExprClass:
+  case Expr::NoInitExprClass:
+  case Expr::DesignatedInitUpdateExprClass:
     return Cl::CL_PRValue;
 
     // Next come the complicated cases.
Index: lib/AST/ExprConstant.cpp
===================================================================
--- lib/AST/ExprConstant.cpp
+++ lib/AST/ExprConstant.cpp
@@ -8671,6 +8671,8 @@
   case Expr::CompoundLiteralExprClass:
   case Expr::ExtVectorElementExprClass:
   case Expr::DesignatedInitExprClass:
+  case Expr::NoInitExprClass:
+  case Expr::DesignatedInitUpdateExprClass:
   case Expr::ImplicitValueInitExprClass:
   case Expr::ParenListExprClass:
   case Expr::VAArgExprClass:
Index: lib/AST/ItaniumMangle.cpp
===================================================================
--- lib/AST/ItaniumMangle.cpp
+++ lib/AST/ItaniumMangle.cpp
@@ -2674,7 +2674,9 @@
   // contexts and so should never appear in a mangling.
   case Expr::AddrLabelExprClass:
   case Expr::DesignatedInitExprClass:
+  case Expr::DesignatedInitUpdateExprClass:
   case Expr::ImplicitValueInitExprClass:
+  case Expr::NoInitExprClass:
   case Expr::ParenListExprClass:
   case Expr::LambdaExprClass:
   case Expr::MSPropertyRefExprClass:
Index: lib/AST/StmtPrinter.cpp
===================================================================
--- lib/AST/StmtPrinter.cpp
+++ lib/AST/StmtPrinter.cpp
@@ -1422,6 +1422,22 @@
   PrintExpr(Node->getInit());
 }
 
+void StmtPrinter::VisitDesignatedInitUpdateExpr(
+    DesignatedInitUpdateExpr *Node) {
+  OS << "{";
+  OS << "/*base*/";
+  PrintExpr(Node->getBase());
+  OS << ", ";
+
+  OS << "/*updater*/";
+  PrintExpr(Node->getUpdater());
+  OS << "}";
+}
+
+void StmtPrinter::VisitNoInitExpr(NoInitExpr *Node) {
+  OS << "/*no init*/";
+}
+
 void StmtPrinter::VisitImplicitValueInitExpr(ImplicitValueInitExpr *Node) {
   if (Policy.LangOpts.CPlusPlus) {
     OS << "/*implicit*/";
Index: lib/AST/StmtProfile.cpp
===================================================================
--- lib/AST/StmtProfile.cpp
+++ lib/AST/StmtProfile.cpp
@@ -694,6 +694,16 @@
   }
 }
 
+// FIXME: how to test these functions?
+void StmtProfiler::VisitDesignatedInitUpdateExpr(
+    const DesignatedInitUpdateExpr *S) {
+  llvm_unreachable("Not implemented");
+}
+
+void StmtProfiler::VisitNoInitExpr(const NoInitExpr *S) {
+  llvm_unreachable("Not implemented");
+}
+
 void StmtProfiler::VisitImplicitValueInitExpr(const ImplicitValueInitExpr *S) {
   VisitExpr(S);
 }
Index: lib/CodeGen/CGExprAgg.cpp
===================================================================
--- lib/CodeGen/CGExprAgg.cpp
+++ lib/CodeGen/CGExprAgg.cpp
@@ -159,10 +159,12 @@
     EmitAggLoadOfLValue(E);
   }
 
+  void VisitDesignatedInitUpdateExpr(DesignatedInitUpdateExpr *E);
   void VisitAbstractConditionalOperator(const AbstractConditionalOperator *CO);
   void VisitChooseExpr(const ChooseExpr *CE);
   void VisitInitListExpr(InitListExpr *E);
   void VisitImplicitValueInitExpr(ImplicitValueInitExpr *E);
+  void VisitNoInitExpr(NoInitExpr *E) { } // Do nothing.
   void VisitCXXDefaultArgExpr(CXXDefaultArgExpr *DAE) {
     Visit(DAE->getExpr());
   }
@@ -1050,6 +1052,9 @@
     return;
   } else if (isa<ImplicitValueInitExpr>(E) || isa<CXXScalarValueInitExpr>(E)) {
     return EmitNullInitializationToLValue(LV);
+  } else if (isa<NoInitExpr>(E)) {
+    // Do nothing.
+    return;
   } else if (type->isReferenceType()) {
     RValue RV = CGF.EmitReferenceBindingToExpr(E);
     return CGF.EmitStoreThroughLValue(RV, LV);
@@ -1270,6 +1275,15 @@
     cleanupDominator->eraseFromParent();
 }
 
+void AggExprEmitter::VisitDesignatedInitUpdateExpr(DesignatedInitUpdateExpr *E) {
+  AggValueSlot Dest = EnsureSlot(E->getType());
+
+  LValue DestLV = CGF.MakeAddrLValue(Dest.getAddr(), E->getType(),
+                                     Dest.getAlignment());
+  EmitInitializationToLValue(E->getBase(), DestLV);
+  VisitInitListExpr(E->getUpdater());
+}
+
 //===----------------------------------------------------------------------===//
 //                        Entry Points into this File
 //===----------------------------------------------------------------------===//
Index: lib/CodeGen/CGExprCXX.cpp
===================================================================
--- lib/CodeGen/CGExprCXX.cpp
+++ lib/CodeGen/CGExprCXX.cpp
@@ -952,6 +952,25 @@
     if (ILE->getNumInits() == 0 && TryMemsetInitialization())
       return;
 
+  // If we have a struct whose every field is value-initialized, we can
+  // usually use memset.
+  if (auto *ILE = dyn_cast<InitListExpr>(Init)) {
+    if (const RecordType *RType = ILE->getType()->getAs<RecordType>()) {
+      if (RType->getDecl()->isStruct()) {
+        unsigned NumFields = 0;
+        for (auto *Field : RType->getDecl()->fields())
+          if (!Field->isUnnamedBitfield())
+            ++NumFields;
+        if (ILE->getNumInits() == NumFields)
+          for (unsigned i = 0, e = ILE->getNumInits(); i != e; ++i)
+            if (!isa<ImplicitValueInitExpr>(ILE->getInit(i)))
+              --NumFields;
+        if (ILE->getNumInits() == NumFields && TryMemsetInitialization())
+          return;
+      }
+    }
+  }
+
   // Create the loop blocks.
   llvm::BasicBlock *EntryBB = Builder.GetInsertBlock();
   llvm::BasicBlock *LoopBB = createBasicBlock("new.loop");
Index: lib/Sema/SemaExceptionSpec.cpp
===================================================================
--- lib/Sema/SemaExceptionSpec.cpp
+++ lib/Sema/SemaExceptionSpec.cpp
@@ -1041,6 +1041,7 @@
   case Expr::CXXReinterpretCastExprClass:
   case Expr::CXXStdInitializerListExprClass:
   case Expr::DesignatedInitExprClass:
+  case Expr::DesignatedInitUpdateExprClass:
   case Expr::ExprWithCleanupsClass:
   case Expr::ExtVectorElementExprClass:
   case Expr::InitListExprClass:
@@ -1135,6 +1136,7 @@
   case Expr::ImaginaryLiteralClass:
   case Expr::ImplicitValueInitExprClass:
   case Expr::IntegerLiteralClass:
+  case Expr::NoInitExprClass:
   case Expr::ObjCEncodeExprClass:
   case Expr::ObjCStringLiteralClass:
   case Expr::ObjCBoolLiteralExprClass:
Index: lib/Sema/SemaInit.cpp
===================================================================
--- lib/Sema/SemaInit.cpp
+++ lib/Sema/SemaInit.cpp
@@ -306,7 +306,8 @@
                                            QualType CurrentObjectType,
                                            InitListExpr *StructuredList,
                                            unsigned StructuredIndex,
-                                           SourceRange InitRange);
+                                           SourceRange InitRange,
+                                           bool IsFullyOverwritten = false);
   void UpdateStructuredListElement(InitListExpr *StructuredList,
                                    unsigned &StructuredIndex,
                                    Expr *expr);
@@ -317,11 +318,33 @@
                                      SourceLocation Loc,
                                      const InitializedEntity &Entity,
                                      bool VerifyOnly);
+
+  // Explanation on the "FillWithNoInit" mode:
+  //
+  // Assume we have the following definitions (Case#1):
+  // struct P { char x[6][6]; } xp = { .x[1] = "bar" };
+  // struct PP { struct P lp; } l = { .lp = xp, .lp.x[1][2] = 'f' };
+  //
+  // l.lp.x[1][0..1] should not be filled with implicit initializers because the
+  // "base" initializer "xp" will provide values for them; l.lp.x[1] will be "baf".
+  //
+  // But if we have (Case#2):
+  // struct PP l = { .lp = xp, .lp.x[1] = { [2] = 'f' } };
+  //
+  // l.lp.x[1][0..1] are implicitly initialized and do not use values from the
+  // "base" initializer; l.lp.x[1] will be "\0\0f\0\0\0".
+  //
+  // To distinguish Case#1 from Case#2, and also to avoid leaving many "holes"
+  // in the InitListExpr, the "holes" in Case#1 are filled not with empty
+  // initializers but with a special "NoInitExpr" place holders, which tells the
+  // CodeGen not to generate any initializers for these parts.
   void FillInEmptyInitForField(unsigned Init, FieldDecl *Field,
                                const InitializedEntity &ParentEntity,
-                               InitListExpr *ILE, bool &RequiresSecondPass);
+                               InitListExpr *ILE, bool &RequiresSecondPass,
+                               bool FillWithNoInit = false);
   void FillInEmptyInitializations(const InitializedEntity &Entity,
-                                  InitListExpr *ILE, bool &RequiresSecondPass);
+                                  InitListExpr *ILE, bool &RequiresSecondPass,
+                                  bool FillWithNoInit = false);
   bool CheckFlexibleArrayInit(const InitializedEntity &Entity,
                               Expr *InitExpr, FieldDecl *Field,
                               bool TopLevelObject);
@@ -455,12 +478,26 @@
 void InitListChecker::FillInEmptyInitForField(unsigned Init, FieldDecl *Field,
                                         const InitializedEntity &ParentEntity,
                                               InitListExpr *ILE,
-                                              bool &RequiresSecondPass) {
+                                              bool &RequiresSecondPass,
+                                              bool FillWithNoInit) {
   SourceLocation Loc = ILE->getLocEnd();
   unsigned NumInits = ILE->getNumInits();
   InitializedEntity MemberEntity
     = InitializedEntity::InitializeMember(Field, &ParentEntity);
+
+  if (const RecordType *RType = ILE->getType()->getAs<RecordType>())
+    if (!RType->getDecl()->isUnion())
+      assert(Init < NumInits && "This ILE should have been expanded");
+
   if (Init >= NumInits || !ILE->getInit(Init)) {
+    if (FillWithNoInit) {
+      Expr *Filler = new (SemaRef.Context) NoInitExpr(Field->getType());
+      if (Init < NumInits)
+        ILE->setInit(Init, Filler);
+      else
+        ILE->updateInit(SemaRef.Context, Init, Filler);
+      return;
+    }
     // C++1y [dcl.init.aggr]p7:
     //   If there are fewer initializer-clauses in the list than there are
     //   members in the aggregate, then each member not explicitly initialized
@@ -516,7 +553,11 @@
   } else if (InitListExpr *InnerILE
                = dyn_cast<InitListExpr>(ILE->getInit(Init)))
     FillInEmptyInitializations(MemberEntity, InnerILE,
-                               RequiresSecondPass);
+                               RequiresSecondPass, FillWithNoInit);
+  else if (DesignatedInitUpdateExpr *InnerDIUE
+               = dyn_cast<DesignatedInitUpdateExpr>(ILE->getInit(Init)))
+    FillInEmptyInitializations(MemberEntity, InnerDIUE->getUpdater(),
+                               RequiresSecondPass, /*FillWithNoInit =*/ true);
 }
 
 /// Recursively replaces NULL values within the given initializer list
@@ -525,7 +566,8 @@
 void
 InitListChecker::FillInEmptyInitializations(const InitializedEntity &Entity,
                                             InitListExpr *ILE,
-                                            bool &RequiresSecondPass) {
+                                            bool &RequiresSecondPass,
+                                            bool FillWithNoInit) {
   assert((ILE->getType() != SemaRef.Context.VoidTy) &&
          "Should not have void type");
 
@@ -533,16 +575,27 @@
     const RecordDecl *RDecl = RType->getDecl();
     if (RDecl->isUnion() && ILE->getInitializedFieldInUnion())
       FillInEmptyInitForField(0, ILE->getInitializedFieldInUnion(),
-                              Entity, ILE, RequiresSecondPass);
+                              Entity, ILE, RequiresSecondPass, FillWithNoInit);
     else if (RDecl->isUnion() && isa<CXXRecordDecl>(RDecl) &&
              cast<CXXRecordDecl>(RDecl)->hasInClassInitializer()) {
       for (auto *Field : RDecl->fields()) {
         if (Field->hasInClassInitializer()) {
-          FillInEmptyInitForField(0, Field, Entity, ILE, RequiresSecondPass);
+          FillInEmptyInitForField(0, Field, Entity, ILE, RequiresSecondPass,
+                                  FillWithNoInit);
           break;
         }
       }
     } else {
+      // The fields beyond ILE->getNumInits() are default initialized, so in
+      // order to leave them uninitialized, the ILE is expanded and the extra
+      // fields are then filled with NoInitExpr.
+      unsigned NumFields = 0;
+      for (auto *Field : RDecl->fields())
+        if (!Field->isUnnamedBitfield())
+          ++NumFields;
+      if (ILE->getNumInits() < NumFields)
+        ILE->resizeInits(SemaRef.Context, NumFields);
+
       unsigned Init = 0;
       for (auto *Field : RDecl->fields()) {
         if (Field->isUnnamedBitfield())
@@ -551,7 +604,8 @@
         if (hadError)
           return;
 
-        FillInEmptyInitForField(Init, Field, Entity, ILE, RequiresSecondPass);
+        FillInEmptyInitForField(Init, Field, Entity, ILE, RequiresSecondPass,
+                                FillWithNoInit);
         if (hadError)
           return;
 
@@ -594,7 +648,9 @@
       ElementEntity.setElementIndex(Init);
 
     Expr *InitExpr = (Init < NumInits ? ILE->getInit(Init) : nullptr);
-    if (!InitExpr && !ILE->hasArrayFiller()) {
+    if (!InitExpr && Init < NumInits && ILE->hasArrayFiller())
+      ILE->setInit(Init, ILE->getArrayFiller());
+    else if (!InitExpr && !ILE->hasArrayFiller()) {
       ExprResult ElementInit = PerformEmptyInit(SemaRef, ILE->getLocEnd(),
                                                 ElementEntity,
                                                 /*VerifyOnly*/false);
@@ -603,6 +659,10 @@
         return;
       }
 
+      Expr *Filler = FillWithNoInit ?
+          new (SemaRef.Context) NoInitExpr(ElementType) :
+          ElementInit.getAs<Expr>();
+
       if (hadError) {
         // Do nothing
       } else if (Init < NumInits) {
@@ -609,29 +669,34 @@
         // For arrays, just set the expression used for value-initialization
         // of the "holes" in the array.
         if (ElementEntity.getKind() == InitializedEntity::EK_ArrayElement)
-          ILE->setArrayFiller(ElementInit.getAs<Expr>());
+          ILE->setArrayFiller(Filler);
         else
-          ILE->setInit(Init, ElementInit.getAs<Expr>());
+          ILE->setInit(Init, Filler);
       } else {
         // For arrays, just set the expression used for value-initialization
         // of the rest of elements and exit.
         if (ElementEntity.getKind() == InitializedEntity::EK_ArrayElement) {
-          ILE->setArrayFiller(ElementInit.getAs<Expr>());
+          ILE->setArrayFiller(Filler);
           return;
         }
 
-        if (!isa<ImplicitValueInitExpr>(ElementInit.get())) {
+        if (!isa<ImplicitValueInitExpr>(Filler) && !isa<NoInitExpr>(Filler)) {
           // Empty initialization requires a constructor call, so
           // extend the initializer list to include the constructor
           // call and make a note that we'll need to take another pass
           // through the initializer list.
-          ILE->updateInit(SemaRef.Context, Init, ElementInit.getAs<Expr>());
+          ILE->updateInit(SemaRef.Context, Init, Filler);
           RequiresSecondPass = true;
         }
       }
     } else if (InitListExpr *InnerILE
                  = dyn_cast_or_null<InitListExpr>(InitExpr))
-      FillInEmptyInitializations(ElementEntity, InnerILE, RequiresSecondPass);
+      FillInEmptyInitializations(ElementEntity, InnerILE, RequiresSecondPass,
+                                 FillWithNoInit);
+    else if (DesignatedInitUpdateExpr *InnerDIUE
+                 = dyn_cast_or_null<DesignatedInitUpdateExpr>(InitExpr))
+      FillInEmptyInitializations(ElementEntity, InnerDIUE->getUpdater(),
+                                 RequiresSecondPass, /*FillWithNoInit =*/ true);
   }
 }
 
@@ -966,13 +1031,26 @@
                               StructuredList, StructuredIndex);
 
   if (InitListExpr *SubInitList = dyn_cast<InitListExpr>(expr)) {
-    if (!SemaRef.getLangOpts().CPlusPlus) {
+    if (SubInitList->getNumInits() == 1 &&
+        IsStringInit(SubInitList->getInit(0), ElemType, SemaRef.Context) ==
+        SIF_None) {
+      expr = SubInitList->getInit(0);
+    } else if (!SemaRef.getLangOpts().CPlusPlus) {
       InitListExpr *InnerStructuredList
         = getStructuredSubobjectInit(IList, Index, ElemType,
                                      StructuredList, StructuredIndex,
-                                     SubInitList->getSourceRange());
+                                     SubInitList->getSourceRange(), true);
       CheckExplicitInitList(Entity, SubInitList, ElemType,
                             InnerStructuredList);
+
+      if (!hadError && !VerifyOnly) {
+        bool RequiresSecondPass = false;
+        FillInEmptyInitializations(Entity, InnerStructuredList,
+                                   RequiresSecondPass);
+        if (RequiresSecondPass && !hadError)
+          FillInEmptyInitializations(Entity, InnerStructuredList,
+                                     RequiresSecondPass);
+      }
       ++StructuredIndex;
       ++Index;
       return;
@@ -1835,6 +1913,183 @@
 
 }
 
+static void partialMergeFrom(const ASTContext &C, InitListExpr *TargetExpr,
+                             Expr *BackgroundExpr) {
+  assert(!TargetExpr->hasArrayFiller() && "Filler already exists!");
+
+  BackgroundExpr = BackgroundExpr->IgnoreParenImpCasts();
+  if (CompoundLiteralExpr *CLE =
+        dyn_cast<CompoundLiteralExpr>(BackgroundExpr))
+    BackgroundExpr = CLE->getInitializer()->IgnoreParenImpCasts();
+
+  // A string literal or an obj-c encode expression gets decomposed into
+  // individual characters.
+  if (isa<StringLiteral>(BackgroundExpr) ||
+      isa<ObjCEncodeExpr>(BackgroundExpr)) {
+    const ArrayType *AT = C.getAsArrayType(TargetExpr->getType());
+    assert(AT && "expecting array type");
+
+    QualType CharTy = AT->getElementType();
+    QualType PromotedCharTy = (CharTy->isPromotableIntegerType() ?
+      C.getPromotedIntegerType(CharTy) : CharTy);
+    unsigned CharWidth = C.getTypeSize(PromotedCharTy);
+
+    const StringLiteral *SL = dyn_cast<StringLiteral>(BackgroundExpr);
+    const ObjCEncodeExpr *OEE = dyn_cast<ObjCEncodeExpr>(BackgroundExpr);
+    std::string OEE_Str;
+    if (OEE)
+      C.getObjCEncodingForType(OEE->getEncodedType(), OEE_Str);
+
+    uint64_t StrLen = SL ? SL->getLength() : OEE_Str.size();
+    const llvm::APInt &ArraySize = cast<ConstantArrayType>(AT)->getSize();
+    if (ArraySize.ult(StrLen))
+      StrLen = ArraySize.getZExtValue();
+
+    if (StrLen > TargetExpr->getNumInits())
+      TargetExpr->resizeInits(C, StrLen);
+
+    for (unsigned i = 0; i != StrLen; ++i) {
+      if (TargetExpr->getInit(i))
+        continue;
+
+      llvm::APInt Element(CharWidth, SL ? SL->getCodeUnit(i) : OEE_Str[i]);
+      Expr *ElementExpr = IntegerLiteral::Create(C, Element, PromotedCharTy,
+                                                 BackgroundExpr->getExprLoc());
+      if (CharTy != PromotedCharTy)
+        ElementExpr = ImplicitCastExpr::Create(C, CharTy, CK_IntegralCast,
+                                               ElementExpr, nullptr, VK_RValue);
+      TargetExpr->setInit(i, ElementExpr);
+    }
+
+    if (ArraySize.ugt(StrLen))
+      TargetExpr->setArrayFiller(new (C) ImplicitValueInitExpr(CharTy));
+
+    return;
+  }
+
+  if (isa<ImplicitValueInitExpr>(BackgroundExpr)) {
+    unsigned NumInits = TargetExpr->getNumInits();
+
+    if (const RecordType *RType = TargetExpr->getType()->getAs<RecordType>()) {
+      const RecordDecl *RD = RType->getDecl();
+      unsigned i = 0;
+
+      unsigned NumFields = 0;
+      for (FieldDecl *FD : RD->fields()) {
+        if (FD->isUnnamedBitfield())
+          continue;
+        ++NumFields;
+      }
+      if (NumInits < NumFields)
+        TargetExpr->resizeInits(C, NumFields);
+
+      for (RecordDecl::field_iterator I = RD->field_begin(),E = RD->field_end();
+           I != E; ++I, ++i) {
+        FieldDecl *FD = *I;
+        if (FD->isUnnamedBitfield()) {
+          --i;
+          continue;
+        }
+
+        ImplicitValueInitExpr *EmptyInit =
+          new (C) ImplicitValueInitExpr(FD->getType());
+
+        if (!TargetExpr->getInit(i)) {
+          TargetExpr->setInit(i, EmptyInit);
+          continue;
+        }
+
+        // If this is not an aggregate type, we are done. The current
+        // initializer takes effect; the background initializer is overwritten.
+        Expr *ChildExpr = TargetExpr->getInit(i);
+        if (!ChildExpr->getType()->isAggregateType())
+          continue;
+
+        assert(isa<InitListExpr>(ChildExpr) && "expecting an init list expr");
+
+        InitListExpr *ChildILE = cast<InitListExpr>(ChildExpr);
+        partialMergeFrom(C, ChildILE, EmptyInit);
+
+        // Only look at the first initialization of a union
+        if (TargetExpr->getType()->isUnionType())
+          break;
+      }
+
+      return;
+    }
+
+    QualType ElementType;
+    bool IsArray = false;
+
+    if (const VectorType *VT = TargetExpr->getType()->getAs<VectorType>())
+      ElementType = VT->getElementType();
+    else if (const ArrayType *AT = C.getAsArrayType(TargetExpr->getType())) {
+      ElementType = AT->getElementType();
+      IsArray = true;
+    } else 
+      ElementType = TargetExpr->getType();
+
+    ImplicitValueInitExpr *EmptyInit =
+      new (C) ImplicitValueInitExpr(ElementType);
+
+    if (IsArray)
+      TargetExpr->setArrayFiller(EmptyInit);
+
+    for (unsigned i = 0; i != NumInits; ++i) {
+      if (!TargetExpr->getInit(i) && !IsArray)
+        TargetExpr->setInit(i, EmptyInit);
+
+      // If this is not an aggregate type, we are done. The current
+      // initializer takes effect; the background initializer is overwritten.
+      Expr *ChildExpr = TargetExpr->getInit(i);
+      if (!ChildExpr->getType()->isAggregateType())
+        continue;
+
+      assert(isa<InitListExpr>(ChildExpr) && "expecting an init list expr");
+
+      InitListExpr *ChildILE = cast<InitListExpr>(ChildExpr);
+      partialMergeFrom(C, ChildILE, EmptyInit);
+    }
+
+    return;
+  }
+
+  assert(isa<InitListExpr>(BackgroundExpr) &&
+         "cannot break down background initializer!");
+  InitListExpr *BackgroundILE = cast<InitListExpr>(BackgroundExpr);
+  if (BackgroundILE->getNumInits() > TargetExpr->getNumInits())
+    TargetExpr->resizeInits(C, BackgroundILE->getNumInits());
+
+  for (unsigned i = 0; i != TargetExpr->getNumInits(); ++i) {
+    if (i >= BackgroundILE->getNumInits() || !BackgroundILE->getInit(i))
+      // Nothing to merge from.
+      continue;
+
+    if (!TargetExpr->getInit(i)) {
+      TargetExpr->setInit(i, BackgroundILE->getInit(i));
+      continue;
+    }
+
+    // If this is not an aggregate type, we are done. The current initializer
+    // takes effect; the background initializer is overwritten.
+    Expr *ChildExpr = TargetExpr->getInit(i);
+    if (!ChildExpr->getType()->isAggregateType())
+      continue;
+
+    assert(isa<InitListExpr>(ChildExpr) && "expecting an init list expr");
+
+    InitListExpr *ChildILE = cast<InitListExpr>(ChildExpr);
+    partialMergeFrom(C, ChildILE, BackgroundILE->getInit(i));
+
+    // Only look at the first initialization of a union
+    if (TargetExpr->getType()->isUnionType())
+      break;
+  }
+
+  if (BackgroundILE->hasArrayFiller())
+    TargetExpr->setArrayFiller(BackgroundILE->getArrayFiller());
+}
+
 /// @brief Check the well-formedness of a C99 designated initializer.
 ///
 /// Determines whether the designated initializer @p DIE, which
@@ -1913,11 +2168,82 @@
 
     // Determine the structural initializer list that corresponds to the
     // current subobject.
-    StructuredList = IsFirstDesignator? SyntacticToSemantic.lookup(IList)
-      : getStructuredSubobjectInit(IList, Index, CurrentObjectType,
-                                   StructuredList, StructuredIndex,
-                                   SourceRange(D->getLocStart(),
-                                               DIE->getLocEnd()));
+    if (IsFirstDesignator)
+      StructuredList = SyntacticToSemantic.lookup(IList);
+    else {
+      Expr *ExistingInit = StructuredIndex < StructuredList->getNumInits() ?
+          StructuredList->getInit(StructuredIndex) : nullptr;
+      if (!ExistingInit && StructuredList->hasArrayFiller())
+        ExistingInit = StructuredList->getArrayFiller();
+
+      if (!ExistingInit)
+        StructuredList =
+          getStructuredSubobjectInit(IList, Index, CurrentObjectType,
+                                     StructuredList, StructuredIndex,
+                                     SourceRange(D->getLocStart(),
+                                                 DIE->getLocEnd()));
+      else if (InitListExpr *Result = dyn_cast<InitListExpr>(ExistingInit))
+        StructuredList = Result;
+      else if (ExistingInit->isConstantInitializer(SemaRef.Context, false)) {
+        InitListExpr *Result = new (SemaRef.Context) InitListExpr(
+            SemaRef.Context, D->getLocStart(), None, DIE->getLocEnd());
+
+        QualType ResultType = CurrentObjectType;
+        if (!ResultType->isArrayType())
+          ResultType = ResultType.getNonLValueExprType(SemaRef.Context);
+        Result->setType(ResultType);
+
+        // If we decomposed an aggregate initializer into individual components,
+        // we do not issue diagnostics here; instead we wait till later and
+        // issue diagnostics on each individual component.
+        partialMergeFrom(SemaRef.Context, Result, ExistingInit);
+        ExistingInit = nullptr;
+        StructuredList->updateInit(SemaRef.Context, StructuredIndex, Result);
+        StructuredList = Result;
+      }
+      else {
+        if (DesignatedInitUpdateExpr *E =
+                dyn_cast<DesignatedInitUpdateExpr>(ExistingInit))
+          StructuredList = E->getUpdater();
+        else {
+          DesignatedInitUpdateExpr *DIUE =
+              new (SemaRef.Context) DesignatedInitUpdateExpr(SemaRef.Context,
+                                        D->getLocStart(), ExistingInit,
+                                        DIE->getLocEnd());
+          StructuredList->updateInit(SemaRef.Context, StructuredIndex, DIUE);
+          StructuredList = DIUE->getUpdater();
+        }
+
+        // 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(D->getLocStart(),
+                     diag::warn_subobject_initializer_overrides)
+          << SourceRange(D->getLocStart(), DIE->getLocEnd());
+  
+        // We need to check on source range validity because the previous
+        // initializer does not have to be an explicit initializer. e.g.,
+        //
+        // struct P { int a, b; };
+        // struct PP { struct P p } l = { { .a = 2 }, .p.b = 3 };
+        //
+        // There is an overwrite taking place because the first braced initializer
+        // list "{ .a = 2 }" already provides value for .p.b (which is zero).
+        if (ExistingInit->getSourceRange().isValid())
+          SemaRef.Diag(ExistingInit->getLocStart(),
+                       diag::note_previous_initializer)
+            << /*FIXME:has side effects=*/0
+            << ExistingInit->getSourceRange();
+      }
+    }
     assert(StructuredList && "Expected a structured initializer list");
   }
 
@@ -2367,7 +2693,8 @@
                                             QualType CurrentObjectType,
                                             InitListExpr *StructuredList,
                                             unsigned StructuredIndex,
-                                            SourceRange InitRange) {
+                                            SourceRange InitRange,
+                                            bool IsFullyOverwritten) {
   if (VerifyOnly)
     return nullptr; // No structured list in verification-only mode.
   Expr *ExistingInit = nullptr;
@@ -2377,7 +2704,16 @@
     ExistingInit = StructuredList->getInit(StructuredIndex);
 
   if (InitListExpr *Result = dyn_cast_or_null<InitListExpr>(ExistingInit))
-    return Result;
+    // There might have already been initializers for subobjects of the current
+    // object, but a subsequent initializer list will overwrite the entirety
+    // of the current object. (See DR 253 and C99 6.7.8p21). e.g.,
+    //
+    // struct P { char x[6]; };
+    // struct P l = { .x[2] = 'x', .x = { [0] = 'f' } };
+    //
+    // The first designated initializer is ignored, and l.x is just "f".
+    if (!IsFullyOverwritten)
+      return Result;
 
   if (ExistingInit) {
     // We are creating an initializer list that initializes the
@@ -2472,11 +2808,28 @@
     SemaRef.Diag(expr->getLocStart(),
                   diag::warn_initializer_overrides)
       << expr->getSourceRange();
-    SemaRef.Diag(PrevInit->getLocStart(),
-                  diag::note_previous_initializer)
-      << /*FIXME:has side effects=*/0
-      << PrevInit->getSourceRange();
+
+    // We need to check on source range validity because the previous
+    // initializer does not have to be an explicit initializer.
+    // struct P { int a, b; };
+    // struct PP { struct P p } l = { { .a = 2 }, .p.b = 3 };
+    // There is an overwrite taking place because the first braced initializer
+    // list "{ .a = 2 }' already provides value for .p.b (which is zero).
+    if (PrevInit->getSourceRange().isValid())
+      SemaRef.Diag(PrevInit->getLocStart(),
+                   diag::note_previous_initializer)
+        << /*FIXME:has side effects=*/0
+        << PrevInit->getSourceRange();
   }
+  // It is also possible to overwrite an implicitly initialized array element:
+  // struct S { char L[6]; } var[] = {
+  //   { { 'f', 'o', 'o' } }, // var[0].L[3..6] zero-initialized, and then
+  //   [0].L[4] = 'x' };      // var[0].L[4] was overriden
+  else if (StructuredList->hasArrayFiller()) {
+    SemaRef.Diag(expr->getLocStart(),
+                 diag::warn_initializer_overrides)
+      << expr->getSourceRange();
+  }
 
   ++StructuredIndex;
 }
Index: lib/Sema/TreeTransform.h
===================================================================
--- lib/Sema/TreeTransform.h
+++ lib/Sema/TreeTransform.h
@@ -7923,8 +7923,26 @@
                                                 E->usesGNUSyntax(), Init.get());
 }
 
+// Seems that if TransformInitListExpr() only works on the syntactic form of an
+// InitListExpr, then a DesignatedInitUpdateExpr is not encountered.
 template<typename Derived>
 ExprResult
+TreeTransform<Derived>::TransformDesignatedInitUpdateExpr(
+    DesignatedInitUpdateExpr *E) {
+  llvm_unreachable("not implemented");
+  return ExprError();
+}
+
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformNoInitExpr(
+    NoInitExpr *E) {
+  llvm_unreachable("not implemented");
+  return ExprError();
+}
+
+template<typename Derived>
+ExprResult
 TreeTransform<Derived>::TransformImplicitValueInitExpr(
                                                      ImplicitValueInitExpr *E) {
   TemporaryBase Rebase(*this, E->getLocStart(), DeclarationName());
Index: lib/Serialization/ASTReaderStmt.cpp
===================================================================
--- lib/Serialization/ASTReaderStmt.cpp
+++ lib/Serialization/ASTReaderStmt.cpp
@@ -801,6 +801,18 @@
                     Designators.data(), Designators.size());
 }
 
+void ASTStmtReader::VisitDesignatedInitUpdateExpr(DesignatedInitUpdateExpr *E) {
+  VisitExpr(E);
+  E->setLBraceLoc(ReadSourceLocation(Record, Idx));
+  E->setRBraceLoc(ReadSourceLocation(Record, Idx));
+  E->setBase(Reader.ReadSubExpr());
+  E->setUpdater(Reader.ReadSubExpr());
+}
+
+void ASTStmtReader::VisitNoInitExpr(NoInitExpr *E) {
+  VisitExpr(E);
+}
+
 void ASTStmtReader::VisitImplicitValueInitExpr(ImplicitValueInitExpr *E) {
   VisitExpr(E);
 }
@@ -2479,10 +2491,18 @@
 
       break;
 
+    case EXPR_DESIGNATED_INIT_UPDATE:
+      S = new (Context) DesignatedInitUpdateExpr(Empty);
+      break;
+
     case EXPR_IMPLICIT_VALUE_INIT:
       S = new (Context) ImplicitValueInitExpr(Empty);
       break;
 
+    case EXPR_NO_INIT:
+      S = new (Context) NoInitExpr(Empty);
+      break;
+
     case EXPR_VA_ARG:
       S = new (Context) VAArgExpr(Empty);
       break;
Index: lib/Serialization/ASTWriter.cpp
===================================================================
--- lib/Serialization/ASTWriter.cpp
+++ lib/Serialization/ASTWriter.cpp
@@ -774,7 +774,9 @@
   RECORD(EXPR_EXT_VECTOR_ELEMENT);
   RECORD(EXPR_INIT_LIST);
   RECORD(EXPR_DESIGNATED_INIT);
+  RECORD(EXPR_DESIGNATED_INIT_UPDATE);
   RECORD(EXPR_IMPLICIT_VALUE_INIT);
+  RECORD(EXPR_NO_INIT);
   RECORD(EXPR_VA_ARG);
   RECORD(EXPR_ADDR_LABEL);
   RECORD(EXPR_STMT);
Index: lib/Serialization/ASTWriterStmt.cpp
===================================================================
--- lib/Serialization/ASTWriterStmt.cpp
+++ lib/Serialization/ASTWriterStmt.cpp
@@ -737,6 +737,20 @@
   Code = serialization::EXPR_DESIGNATED_INIT;
 }
 
+void ASTStmtWriter::VisitDesignatedInitUpdateExpr(DesignatedInitUpdateExpr *E) {
+  VisitExpr(E);
+  Writer.AddSourceLocation(E->getLBraceLoc(), Record);
+  Writer.AddSourceLocation(E->getRBraceLoc(), Record);
+  Writer.AddStmt(E->getBase());
+  Writer.AddStmt(E->getUpdater());
+  Code = serialization::EXPR_DESIGNATED_INIT_UPDATE;
+}
+
+void ASTStmtWriter::VisitNoInitExpr(NoInitExpr *E) {
+  VisitExpr(E);
+  Code = serialization::EXPR_NO_INIT;
+}
+
 void ASTStmtWriter::VisitImplicitValueInitExpr(ImplicitValueInitExpr *E) {
   VisitExpr(E);
   Code = serialization::EXPR_IMPLICIT_VALUE_INIT;
Index: lib/StaticAnalyzer/Core/ExprEngine.cpp
===================================================================
--- lib/StaticAnalyzer/Core/ExprEngine.cpp
+++ lib/StaticAnalyzer/Core/ExprEngine.cpp
@@ -859,6 +859,7 @@
 
     // Cases not handled yet; but will handle some day.
     case Stmt::DesignatedInitExprClass:
+    case Stmt::DesignatedInitUpdateExprClass:
     case Stmt::ExtVectorElementExprClass:
     case Stmt::ImaginaryLiteralClass:
     case Stmt::ObjCAtCatchStmtClass:
@@ -891,6 +892,7 @@
     case Stmt::CXXBoolLiteralExprClass:
     case Stmt::ObjCBoolLiteralExprClass:
     case Stmt::FloatingLiteralClass:
+    case Stmt::NoInitExprClass:
     case Stmt::SizeOfPackExprClass:
     case Stmt::StringLiteralClass:
     case Stmt::ObjCStringLiteralClass:
Index: test/Analysis/designated-initializer.c
===================================================================
--- test/Analysis/designated-initializer.c
+++ test/Analysis/designated-initializer.c
@@ -0,0 +1,37 @@
+// RUN: %clang_cc1 -analyze -analyzer-checker=debug.DumpCFG %s 2>&1 \
+// RUN:   | FileCheck %s
+
+struct Q { int a, b, c; };
+union UQ { struct Q q; };
+union UQ getUQ() {
+  union UQ u = { { 1, 2, 3 } };
+  return u;
+}
+
+void test() {
+  struct LUQ { union UQ uq; } var = { getUQ(), .uq.q.a = 100 };
+  struct Q s[] = {
+    [0] = (struct Q){1, 2},
+    [0].c = 3
+  }; 
+}
+
+// CHECK: void test()
+// CHECK: [B1]
+// CHECK:   1: getUQ
+// CHECK:   2: [B1.1] (ImplicitCastExpr, FunctionToPointerDecay, union UQ (*)())
+// CHECK:   3: [B1.2]()
+// CHECK:   4: 100
+// CHECK:   5: /*no init*/
+// CHECK:   6: /*no init*/
+// CHECK:   7: {[B1.4], [B1.5], [B1.6]}
+// CHECK:   8: {[B1.7]}
+// CHECK:   9: {/*base*/[B1.3], /*updater*/[B1.8]}
+// CHECK:  10: {[B1.3], .uq.q.a = [B1.4]}
+// CHECK:  11: struct LUQ var = {getUQ(), .uq.q.a = 100};
+// CHECK:  12: 1
+// CHECK:  13: 2
+// CHECK:  14: 3
+// CHECK:  15: {[B1.12], [B1.13], [B1.14]}
+// CHECK:  16: {[0] = (struct Q){[B1.12], [B1.13]}, [0].c = [B1.14]}
+// CHECK:  17: struct Q s[] = {[0] = (struct Q){1, 2}, [0].c = 3};
Index: test/CodeGen/Inputs/stdio.h
===================================================================
--- test/CodeGen/Inputs/stdio.h
+++ test/CodeGen/Inputs/stdio.h
@@ -1,4 +1,5 @@
 struct FILE;
+extern int printf(const char *format, ...);
 extern int vfprintf(struct FILE *s, const char *format, __builtin_va_list arg);
 extern int vprintf(const char *format, __builtin_va_list arg);
 
Index: test/CodeGen/partial-reinitialization1.c
===================================================================
--- test/CodeGen/partial-reinitialization1.c
+++ test/CodeGen/partial-reinitialization1.c
@@ -0,0 +1,74 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-unknown -isystem %S/Inputs %s -emit-llvm -o - | FileCheck %s
+
+struct P1 {
+    struct Q1 {
+      char a[6];
+      char b[6];
+    } q;
+};
+
+// CHECK: { [6 x i8] c"foo\00\00\00", [6 x i8] c"\00x\00\00\00\00" }
+struct P1 l1 = {
+    (struct Q1){ "foo", "bar" },
+               .q.b = { "boo" },
+               .q.b = { [1] = 'x' }
+};
+
+// CHECK: { [6 x i8] c"foo\00\00\00", [6 x i8] c"bxo\00\00\00" }
+struct P1 l1a = {
+    (struct Q1){ "foo", "bar" },
+               .q.b = { "boo" },
+               .q.b[1] = 'x'
+};
+
+
+struct P2 { char x[6]; };
+
+// CHECK: { [6 x i8] c"n\00\00\00\00\00" }
+struct P2 l2 = {
+  .x = { [1] = 'o' },
+  .x = { [0] = 'n' }
+}; 
+
+struct P3 {
+    struct Q3 {
+      struct R1 {
+         int a, b, c;
+      } r1;
+
+      struct R2 {
+         int d, e, f;
+      } r2;
+    } q;
+};
+
+// CHECK: @l3 = global %struct.P3 { %struct.Q3 { %struct.R1 { i32 1, i32 2, i32 3 }, %struct.R2 { i32 0, i32 10, i32 0 } } }
+struct P3 l3 = {
+  (struct Q3){ { 1, 2, 3 }, { 4, 5, 6 } },
+                    .q.r2 = { 7, 8, 9 },
+                    .q.r2 = { .e = 10 }
+};
+
+// This bit is taken from Sema/wchar.c so we can avoid the wchar.h include.      
+typedef __WCHAR_TYPE__ wchar_t;                                                  
+
+struct P4 {
+    wchar_t x[6];
+};
+
+// CHECK: { [6 x i32] [i32 102, i32 111, i32 120, i32 0, i32 0, i32 0] }
+struct P4 l4 = { { L"foo" }, .x[2] = L'x' };
+
+struct P5 {
+  int x;
+  struct Q5 {
+    int a, b, c;
+  } q;
+  int y;
+};
+
+// A three-pass test
+// CHECK: @l5 = global %struct.P5 { i32 1, %struct.Q5 { i32 6, i32 9, i32 8 }, i32 5 }
+struct P5 l5 = { 1, { 2, 3, 4 }, 5,
+                 .q = { 6, 7, 8 },
+                 .q.b = 9 };
Index: test/CodeGen/partial-reinitialization2.c
===================================================================
--- test/CodeGen/partial-reinitialization2.c
+++ test/CodeGen/partial-reinitialization2.c
@@ -0,0 +1,90 @@
+// RUN: %clang_cc1 -isystem %S/Inputs %s -emit-llvm -o - | lli | FileCheck %s
+
+#include <stdio.h>
+
+struct P1 { char x[6]; } g1 = { "foo" };
+struct LP1 { struct P1 p1; };
+
+struct P2    { int a, b, c; } g2 = { 1, 2, 3 };
+struct LP2   { struct P2 p2; };
+struct LP2P2 { struct P2 p1, p2; };
+union  UP2   { struct P2 p2; };
+
+struct LP3 { struct P1 p1[2]; } g3 = { { "dog" }, { "cat" } };
+struct LLP3 { struct LP3 l3 };
+union ULP3 { struct LP3 l3 };
+
+void test1(void)
+{ // CHECK: fox
+  struct LP1 l = { .p1 = g1, .p1.x[2] = 'x' };
+  int i;
+  for (i = 0; i < 6; i ++)
+    printf("%c", l.p1.x[i]);
+  printf("\n");
+}
+
+void test2(void)
+{ // CHECK: fro
+  struct LP1 l = { .p1 = g1, .p1.x[1] = 'r' };
+  int i;
+  for (i = 0; i < 6; i ++)
+    printf("%c", l.p1.x[i]);
+  printf("\n");
+}
+
+void test3(void)
+{ // CHECK: 1 10 3
+  struct LP2 l = { .p2 = g2, .p2.b = 10 };
+  printf("%d %d %d\n", l.p2.a, l.p2.b, l.p2.c);
+}
+
+struct P2 get235() {
+  struct P2 p = { 2, 3, 5 };
+  return p;
+}
+
+struct LP2P2 get456789() {
+  struct LP2P2 l = { { 4, 5, 6 }, { 7, 8, 9 } };
+  return l;
+}
+
+union UP2 get123() {
+  union UP2 u = { { 1, 2, 3 } };
+  return u;
+}
+
+void test4(void)
+{ // CHECK: 100 2 3
+  struct LUP2 { union UP2 up; } var = { get123(), .up.p2.a = 100 };
+  printf("%d %d %d\n", var.up.p2.a, var.up.p2.b, var.up.p2.c);
+}
+
+void test5(void)
+{ // CHECK: 0 78 0 0 0 0
+  struct LLP3 var = { .l3 = g3, .l3.p1 = { [0] = g1 }, .l3.p1[1].x[1] = 'x' };
+  int i;
+  for (i = 0; i < 6; i ++)
+    printf("%x ", var.l3.p1[1].x[i]);
+  printf("\n");
+}
+
+void test6(void)
+{ // CHECK: 2 10 5 : 7 8 9
+  struct LLP2P2 { struct LP2P2 lp; } var =  { get456789(),
+                                              .lp.p1 = get235(),
+                                              .lp.p1.b = 10 };
+  printf("%d %d %d : %d %d %d\n",
+          var.lp.p1.a, var.lp.p1.b, var.lp.p1.c,
+          var.lp.p2.a, var.lp.p2.b, var.lp.p2.c);
+}
+
+int main()
+{
+  test1();
+  test2();
+  test3();
+  test4();
+  test5();
+  test6();
+  return 0;
+}
Index: test/PCH/designated-init.c.h
===================================================================
--- test/PCH/designated-init.c.h
+++ test/PCH/designated-init.c.h
@@ -40,3 +40,25 @@
         },
     }
 };
+
+struct P1 {
+    struct Q1 {
+      char a[6];
+      char b[6];
+    } q;
+};
+
+struct P1 l1 = {
+    (struct Q1){ "foo", "bar" },
+               .q.b = { "boo" },
+               .q.b = { [1] = 'x' }
+};
+
+extern struct Q1 *foo();
+static struct P1 test_foo() {
+  struct P1 l = { *foo(),
+                  .q.b = { "boo" },
+                  .q.b = { [1] = 'x' }
+                };
+  return l;
+}
Index: test/Sema/designated-initializers.c
===================================================================
--- test/Sema/designated-initializers.c
+++ test/Sema/designated-initializers.c
@@ -45,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-note 2 {{previous initialization is here}}
+  [4 ... 6] = { .x = 3, .y = 4.0 }  // expected-warning 2 {{subobject initialization overrides initialization of other fields within its enclosing subobject}}
 };
 
 struct point array3[10] = {
@@ -130,10 +130,10 @@
 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}}
+    [0].c = 3,  // expected-warning{{initializer overrides prior initialization of this 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
+    [1].b = get8(), // expected-warning{{initializer overrides prior initialization of this subobject}}
+    [0].b = 8   // expected-warning{{initializer overrides prior initialization of this subobject}}
   };
 }
 
@@ -318,7 +318,7 @@
       .a = 1 // expected-note{{previous initialization is here}}
     } },
   .a = 2, // expected-warning{{initializer overrides prior initialization of this subobject}}
-  .b = 3
+  .b = 3  // expected-warning{{initializer overrides prior initialization of this subobject}}
 };
 struct ds ds1 = { .c = 0 };
 struct ds ds2 = { { {
@@ -339,5 +339,15 @@
   int M;
 } overwrite_string2[] = {
     { { "foo" }, 1 },
-    [0].L[4] = 'x' // no-warning
+    [0].L[4] = 'x' // expected-warning{{initializer overrides prior initialization of this subobject}}
   };
+struct overwrite_string_struct
+overwrite_string3[] = {
+  "foo", 1,
+  [0].L[4] = 'x'  // expected-warning{{initializer overrides prior initialization of this subobject}}
+};
+struct overwrite_string_struct
+overwrite_string4[] = {
+  { { 'f', 'o', 'o' }, 1 },
+  [0].L[4] = 'x' // expected-warning{{initializer overrides prior initialization of this subobject}}
+};
Index: tools/libclang/CXCursor.cpp
===================================================================
--- tools/libclang/CXCursor.cpp
+++ tools/libclang/CXCursor.cpp
@@ -235,11 +235,13 @@
   case Stmt::CXXUuidofExprClass:
   case Stmt::ChooseExprClass:
   case Stmt::DesignatedInitExprClass:
+  case Stmt::DesignatedInitUpdateExprClass:
   case Stmt::ExprWithCleanupsClass:
   case Stmt::ExpressionTraitExprClass:
   case Stmt::ExtVectorElementExprClass:
   case Stmt::ImplicitCastExprClass:
   case Stmt::ImplicitValueInitExprClass:
+  case Stmt::NoInitExprClass:
   case Stmt::MaterializeTemporaryExprClass:
   case Stmt::ObjCIndirectCopyRestoreExprClass:
   case Stmt::OffsetOfExprClass:
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits

Reply via email to