Remove custom handling of array copies in lambda by-value array capture and
copy constructors of classes with array members, instead using
ArrayInitLoopExpr to represent the initialization loop.

This exposed a bug in the static analyzer where it was unable to differentiate
between zero-initialized and unknown array values, which has also been fixed
here.

llvm-svn: 289618
diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp
index 1a7522d..67e96ea 100644
--- a/clang/lib/AST/ASTImporter.cpp
+++ b/clang/lib/AST/ASTImporter.cpp
@@ -274,6 +274,8 @@
     Expr *VisitMemberExpr(MemberExpr *E);
     Expr *VisitCallExpr(CallExpr *E);
     Expr *VisitInitListExpr(InitListExpr *E);
+    Expr *VisitArrayInitLoopExpr(ArrayInitLoopExpr *E);
+    Expr *VisitArrayInitIndexExpr(ArrayInitIndexExpr *E);
     Expr *VisitCXXDefaultInitExpr(CXXDefaultInitExpr *E);
     Expr *VisitCXXNamedCastExpr(CXXNamedCastExpr *E);
 
@@ -6564,6 +6566,30 @@
   return To;
 }
 
+Expr *ASTNodeImporter::VisitArrayInitLoopExpr(ArrayInitLoopExpr *E) {
+  QualType ToType = Importer.Import(E->getType());
+  if (ToType.isNull())
+    return nullptr;
+
+  Expr *ToCommon = Importer.Import(E->getCommonExpr());
+  if (!ToCommon && E->getCommonExpr())
+    return nullptr;
+
+  Expr *ToSubExpr = Importer.Import(E->getSubExpr());
+  if (!ToSubExpr && E->getSubExpr())
+    return nullptr;
+
+  return new (Importer.getToContext())
+      ArrayInitLoopExpr(ToType, ToCommon, ToSubExpr);
+}
+
+Expr *ASTNodeImporter::VisitArrayInitIndexExpr(ArrayInitIndexExpr *E) {
+  QualType ToType = Importer.Import(E->getType());
+  if (ToType.isNull())
+    return nullptr;
+  return new (Importer.getToContext()) ArrayInitIndexExpr(ToType);
+}
+
 Expr *ASTNodeImporter::VisitCXXDefaultInitExpr(CXXDefaultInitExpr *DIE) {
   FieldDecl *ToField = llvm::dyn_cast_or_null<FieldDecl>(
       Importer.Import(DIE->getField()));
@@ -7054,25 +7080,6 @@
     return new (ToContext)
         CXXCtorInitializer(ToContext, ToTInfo, Import(From->getLParenLoc()),
                            ToExpr, Import(From->getRParenLoc()));
-  } else if (unsigned NumArrayIndices = From->getNumArrayIndices()) {
-    FieldDecl *ToField =
-        llvm::cast_or_null<FieldDecl>(Import(From->getMember()));
-    if (!ToField && From->getMember())
-      return nullptr;
-
-    SmallVector<VarDecl *, 4> ToAIs(NumArrayIndices);
-
-    for (unsigned AII = 0; AII < NumArrayIndices; ++AII) {
-      VarDecl *ToArrayIndex =
-          dyn_cast_or_null<VarDecl>(Import(From->getArrayIndex(AII)));
-      if (!ToArrayIndex && From->getArrayIndex(AII))
-        return nullptr;
-    }
-
-    return CXXCtorInitializer::Create(
-        ToContext, ToField, Import(From->getMemberLocation()),
-        Import(From->getLParenLoc()), ToExpr, Import(From->getRParenLoc()),
-        ToAIs.data(), NumArrayIndices);
   } else {
     return nullptr;
   }
diff --git a/clang/lib/AST/DeclCXX.cpp b/clang/lib/AST/DeclCXX.cpp
index f1848e8..8563416 100644
--- a/clang/lib/AST/DeclCXX.cpp
+++ b/clang/lib/AST/DeclCXX.cpp
@@ -1739,7 +1739,7 @@
                                        SourceLocation EllipsisLoc)
   : Initializee(TInfo), MemberOrEllipsisLocation(EllipsisLoc), Init(Init), 
     LParenLoc(L), RParenLoc(R), IsDelegating(false), IsVirtual(IsVirtual), 
-    IsWritten(false), SourceOrderOrNumArrayIndices(0)
+    IsWritten(false), SourceOrder(0)
 {
 }
 
@@ -1750,7 +1750,7 @@
                                        SourceLocation R)
   : Initializee(Member), MemberOrEllipsisLocation(MemberLoc), Init(Init),
     LParenLoc(L), RParenLoc(R), IsDelegating(false), IsVirtual(false),
-    IsWritten(false), SourceOrderOrNumArrayIndices(0)
+    IsWritten(false), SourceOrder(0)
 {
 }
 
@@ -1761,7 +1761,7 @@
                                        SourceLocation R)
   : Initializee(Member), MemberOrEllipsisLocation(MemberLoc), Init(Init),
     LParenLoc(L), RParenLoc(R), IsDelegating(false), IsVirtual(false),
-    IsWritten(false), SourceOrderOrNumArrayIndices(0)
+    IsWritten(false), SourceOrder(0)
 {
 }
 
@@ -1771,38 +1771,10 @@
                                        SourceLocation R)
   : Initializee(TInfo), MemberOrEllipsisLocation(), Init(Init),
     LParenLoc(L), RParenLoc(R), IsDelegating(true), IsVirtual(false),
-    IsWritten(false), SourceOrderOrNumArrayIndices(0)
+    IsWritten(false), SourceOrder(0)
 {
 }
 
-CXXCtorInitializer::CXXCtorInitializer(ASTContext &Context,
-                                       FieldDecl *Member,
-                                       SourceLocation MemberLoc,
-                                       SourceLocation L, Expr *Init,
-                                       SourceLocation R,
-                                       VarDecl **Indices,
-                                       unsigned NumIndices)
-  : Initializee(Member), MemberOrEllipsisLocation(MemberLoc), Init(Init), 
-    LParenLoc(L), RParenLoc(R), IsDelegating(false), IsVirtual(false),
-    IsWritten(false), SourceOrderOrNumArrayIndices(NumIndices)
-{
-  std::uninitialized_copy(Indices, Indices + NumIndices,
-                          getTrailingObjects<VarDecl *>());
-}
-
-CXXCtorInitializer *CXXCtorInitializer::Create(ASTContext &Context,
-                                               FieldDecl *Member, 
-                                               SourceLocation MemberLoc,
-                                               SourceLocation L, Expr *Init,
-                                               SourceLocation R,
-                                               VarDecl **Indices,
-                                               unsigned NumIndices) {
-  void *Mem = Context.Allocate(totalSizeToAlloc<VarDecl *>(NumIndices),
-                               alignof(CXXCtorInitializer));
-  return new (Mem) CXXCtorInitializer(Context, Member, MemberLoc, L, Init, R,
-                                      Indices, NumIndices);
-}
-
 TypeLoc CXXCtorInitializer::getBaseClassLoc() const {
   if (isBaseInitializer())
     return Initializee.get<TypeSourceInfo*>()->getTypeLoc();
diff --git a/clang/lib/AST/ExprCXX.cpp b/clang/lib/AST/ExprCXX.cpp
index 5ad014f..ad510e0 100644
--- a/clang/lib/AST/ExprCXX.cpp
+++ b/clang/lib/AST/ExprCXX.cpp
@@ -869,8 +869,6 @@
                        SourceLocation CaptureDefaultLoc,
                        ArrayRef<LambdaCapture> Captures, bool ExplicitParams,
                        bool ExplicitResultType, ArrayRef<Expr *> CaptureInits,
-                       ArrayRef<VarDecl *> ArrayIndexVars,
-                       ArrayRef<unsigned> ArrayIndexStarts,
                        SourceLocation ClosingBrace,
                        bool ContainsUnexpandedParameterPack)
     : Expr(LambdaExprClass, T, VK_RValue, OK_Ordinary, T->isDependentType(),
@@ -907,17 +905,6 @@
   
   // Copy the body of the lambda.
   *Stored++ = getCallOperator()->getBody();
-
-  // Copy the array index variables, if any.
-  HasArrayIndexVars = !ArrayIndexVars.empty();
-  if (HasArrayIndexVars) {
-    assert(ArrayIndexStarts.size() == NumCaptures);
-    memcpy(getArrayIndexVars(), ArrayIndexVars.data(),
-           sizeof(VarDecl *) * ArrayIndexVars.size());
-    memcpy(getArrayIndexStarts(), ArrayIndexStarts.data(), 
-           sizeof(unsigned) * Captures.size());
-    getArrayIndexStarts()[Captures.size()] = ArrayIndexVars.size();
-  }
 }
 
 LambdaExpr *LambdaExpr::Create(
@@ -925,31 +912,24 @@
     SourceRange IntroducerRange, LambdaCaptureDefault CaptureDefault,
     SourceLocation CaptureDefaultLoc, ArrayRef<LambdaCapture> Captures,
     bool ExplicitParams, bool ExplicitResultType, ArrayRef<Expr *> CaptureInits,
-    ArrayRef<VarDecl *> ArrayIndexVars, ArrayRef<unsigned> ArrayIndexStarts,
     SourceLocation ClosingBrace, bool ContainsUnexpandedParameterPack) {
   // Determine the type of the expression (i.e., the type of the
   // function object we're creating).
   QualType T = Context.getTypeDeclType(Class);
 
-  unsigned Size = totalSizeToAlloc<Stmt *, unsigned, VarDecl *>(
-      Captures.size() + 1, ArrayIndexVars.empty() ? 0 : Captures.size() + 1,
-      ArrayIndexVars.size());
+  unsigned Size = totalSizeToAlloc<Stmt *>(Captures.size() + 1);
   void *Mem = Context.Allocate(Size);
-  return new (Mem) LambdaExpr(T, IntroducerRange,
-                              CaptureDefault, CaptureDefaultLoc, Captures,
-                              ExplicitParams, ExplicitResultType,
-                              CaptureInits, ArrayIndexVars, ArrayIndexStarts,
-                              ClosingBrace, ContainsUnexpandedParameterPack);
+  return new (Mem)
+      LambdaExpr(T, IntroducerRange, CaptureDefault, CaptureDefaultLoc,
+                 Captures, ExplicitParams, ExplicitResultType, CaptureInits,
+                 ClosingBrace, ContainsUnexpandedParameterPack);
 }
 
 LambdaExpr *LambdaExpr::CreateDeserialized(const ASTContext &C,
-                                           unsigned NumCaptures,
-                                           unsigned NumArrayIndexVars) {
-  unsigned Size = totalSizeToAlloc<Stmt *, unsigned, VarDecl *>(
-      NumCaptures + 1, NumArrayIndexVars ? NumCaptures + 1 : 0,
-      NumArrayIndexVars);
+                                           unsigned NumCaptures) {
+  unsigned Size = totalSizeToAlloc<Stmt *>(NumCaptures + 1);
   void *Mem = C.Allocate(Size);
-  return new (Mem) LambdaExpr(EmptyShell(), NumCaptures, NumArrayIndexVars > 0);
+  return new (Mem) LambdaExpr(EmptyShell(), NumCaptures);
 }
 
 bool LambdaExpr::isInitCapture(const LambdaCapture *C) const {
@@ -995,19 +975,6 @@
   return capture_range(implicit_capture_begin(), implicit_capture_end());
 }
 
-ArrayRef<VarDecl *>
-LambdaExpr::getCaptureInitIndexVars(const_capture_init_iterator Iter) const {
-  assert(HasArrayIndexVars && "No array index-var data?");
-  
-  unsigned Index = Iter - capture_init_begin();
-  assert(Index < getLambdaClass()->getLambdaData().NumCaptures &&
-         "Capture index out-of-range");
-  VarDecl *const *IndexVars = getArrayIndexVars();
-  const unsigned *IndexStarts = getArrayIndexStarts();
-  return llvm::makeArrayRef(IndexVars + IndexStarts[Index],
-                            IndexVars + IndexStarts[Index + 1]);
-}
-
 CXXRecordDecl *LambdaExpr::getLambdaClass() const {
   return getType()->getAsCXXRecordDecl();
 }