Unify the codepaths used to verify base and member initializers for explicitly
and implicitly defined constructors.  This has a number of benefits:

1. Less code.

2. Explicit and implicit constructors get the same diagnostics.

3. The AST explicitly contains constructor calls from implicit default
constructors.  This allows handing some cases that previously weren't handled
correctly in IRGen without any additional code. Specifically, implicit default
constructors containing calls to constructors with default arguments are now
handled correctly.

llvm-svn: 86500
diff --git a/clang/lib/CodeGen/CGCXX.cpp b/clang/lib/CodeGen/CGCXX.cpp
index cc6f13b..0e394b5 100644
--- a/clang/lib/CodeGen/CGCXX.cpp
+++ b/clang/lib/CodeGen/CGCXX.cpp
@@ -1483,64 +1483,6 @@
       PopCXXTemporary();
   }
 
-  if (!CD->getNumBaseOrMemberInitializers() && !CD->isTrivial()) {
-    // Nontrivial default constructor with no initializer list. It may still
-    // have bases classes and/or contain non-static data members which require
-    // construction.
-    for (CXXRecordDecl::base_class_const_iterator Base =
-          ClassDecl->bases_begin();
-          Base != ClassDecl->bases_end(); ++Base) {
-      // FIXME. copy assignment of virtual base NYI
-      if (Base->isVirtual())
-        continue;
-
-      CXXRecordDecl *BaseClassDecl
-        = cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());
-      if (BaseClassDecl->hasTrivialConstructor())
-        continue;
-      if (CXXConstructorDecl *BaseCX =
-            BaseClassDecl->getDefaultConstructor(getContext())) {
-        LoadOfThis = LoadCXXThis();
-        llvm::Value *V = GetAddressCXXOfBaseClass(LoadOfThis, ClassDecl,
-                                                  BaseClassDecl,
-                                                  /*NullCheckValue=*/false);
-        EmitCXXConstructorCall(BaseCX, Ctor_Complete, V, 0, 0);
-      }
-    }
-
-    for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(),
-         FieldEnd = ClassDecl->field_end();
-         Field != FieldEnd; ++Field) {
-      QualType FieldType = getContext().getCanonicalType((*Field)->getType());
-      const ConstantArrayType *Array =
-        getContext().getAsConstantArrayType(FieldType);
-      if (Array)
-        FieldType = getContext().getBaseElementType(FieldType);
-      if (!FieldType->getAs<RecordType>() || Field->isAnonymousStructOrUnion())
-        continue;
-      const RecordType *ClassRec = FieldType->getAs<RecordType>();
-      CXXRecordDecl *MemberClassDecl =
-        dyn_cast<CXXRecordDecl>(ClassRec->getDecl());
-      if (!MemberClassDecl || MemberClassDecl->hasTrivialConstructor())
-        continue;
-      if (CXXConstructorDecl *MamberCX =
-            MemberClassDecl->getDefaultConstructor(getContext())) {
-        LoadOfThis = LoadCXXThis();
-        LValue LHS = EmitLValueForField(LoadOfThis, *Field, false, 0);
-        if (Array) {
-          const llvm::Type *BasePtr = ConvertType(FieldType);
-          BasePtr = llvm::PointerType::getUnqual(BasePtr);
-          llvm::Value *BaseAddrPtr =
-            Builder.CreateBitCast(LHS.getAddress(), BasePtr);
-          EmitCXXAggrConstructorCall(MamberCX, Array, BaseAddrPtr);
-        }
-        else
-          EmitCXXConstructorCall(MamberCX, Ctor_Complete, LHS.getAddress(),
-                                 0, 0);
-      }
-    }
-  }
-
   // Initialize the vtable pointer
   if (ClassDecl->isDynamicClass()) {
     if (!LoadOfThis)
diff --git a/clang/lib/Sema/Sema.h b/clang/lib/Sema/Sema.h
index bfef9a3..b21315b 100644
--- a/clang/lib/Sema/Sema.h
+++ b/clang/lib/Sema/Sema.h
@@ -1747,11 +1747,6 @@
                                const FunctionProtoType *Proto,
                                Expr **Args, unsigned NumArgs,
                                SourceLocation RParenLoc);
-  void BuildBaseOrMemberInitializers(ASTContext &C,
-                                 CXXConstructorDecl *Constructor,
-                                 CXXBaseOrMemberInitializer **Initializers,
-                                 unsigned NumInitializers
-                                 );
 
   void DeconstructCallFunction(Expr *FnExpr,
                                NamedDecl *&Function,
@@ -2280,8 +2275,7 @@
   void SetBaseOrMemberInitializers(CXXConstructorDecl *Constructor,
                               CXXBaseOrMemberInitializer **Initializers,
                               unsigned NumInitializers,
-                              llvm::SmallVectorImpl<CXXBaseSpecifier *>& Bases,
-                              llvm::SmallVectorImpl<FieldDecl *>&Members);
+                              bool IsImplicitConstructor);
 
   /// computeBaseOrMembersToDestroy - Compute information in current
   /// destructor decl's AST of bases and non-static data members which will be
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index f7c4428..5dd62f5 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -1190,8 +1190,7 @@
 Sema::SetBaseOrMemberInitializers(CXXConstructorDecl *Constructor,
                               CXXBaseOrMemberInitializer **Initializers,
                               unsigned NumInitializers,
-                              llvm::SmallVectorImpl<CXXBaseSpecifier *>& Bases,
-                              llvm::SmallVectorImpl<FieldDecl *>&Fields) {
+                              bool IsImplicitConstructor) {
   // We need to build the initializer AST according to order of construction
   // and not what user specified in the Initializers list.
   CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(Constructor->getDeclContext());
@@ -1254,7 +1253,11 @@
         assert(VBaseDecl && "SetBaseOrMemberInitializers - VBaseDecl null");
         CXXConstructorDecl *Ctor = VBaseDecl->getDefaultConstructor(Context);
         if (!Ctor) {
-          Bases.push_back(VBase);
+          Diag(Constructor->getLocation(), diag::err_missing_default_ctor)
+            << (int)IsImplicitConstructor << Context.getTagDeclType(ClassDecl)
+            << 0 << VBase->getType();
+          Diag(VBaseDecl->getLocation(), diag::note_previous_class_decl)
+            << Context.getTagDeclType(VBaseDecl);
           continue;
         }
 
@@ -1299,7 +1302,11 @@
         assert(BaseDecl && "SetBaseOrMemberInitializers - BaseDecl null");
          CXXConstructorDecl *Ctor = BaseDecl->getDefaultConstructor(Context);
         if (!Ctor) {
-          Bases.push_back(Base);
+          Diag(Constructor->getLocation(), diag::err_missing_default_ctor)
+            << (int)IsImplicitConstructor << Context.getTagDeclType(ClassDecl)
+            << 0 << Base->getType();
+          Diag(BaseDecl->getLocation(), diag::note_previous_class_decl)
+            << Context.getTagDeclType(BaseDecl);
           continue;
         }
 
@@ -1357,17 +1364,20 @@
       continue;
     }
 
-    if ((*Field)->getType()->isDependentType()) {
-      Fields.push_back(*Field);
+    if ((*Field)->getType()->isDependentType())
       continue;
-    }
     
     QualType FT = Context.getBaseElementType((*Field)->getType());
     if (const RecordType* RT = FT->getAs<RecordType>()) {
       CXXConstructorDecl *Ctor =
         cast<CXXRecordDecl>(RT->getDecl())->getDefaultConstructor(Context);
       if (!Ctor) {
-        Fields.push_back(*Field);
+        Diag(Constructor->getLocation(), diag::err_missing_default_ctor)
+          << (int)IsImplicitConstructor << Context.getTagDeclType(ClassDecl)
+          << 1 << (*Field)->getDeclName();
+        Diag(Field->getLocation(), diag::note_field_decl);
+        Diag(RT->getDecl()->getLocation(), diag::note_previous_class_decl)
+          << Context.getTagDeclType(RT->getDecl());
         continue;
       }
       
@@ -1383,22 +1393,24 @@
                                                  SourceLocation());
 
       AllToInit.push_back(Member);
-      if (Ctor)
-        MarkDeclarationReferenced(Constructor->getLocation(), Ctor);
-      if (FT.isConstQualified() && (!Ctor || Ctor->isTrivial())) {
+      MarkDeclarationReferenced(Constructor->getLocation(), Ctor);
+      if (FT.isConstQualified() && Ctor->isTrivial()) {
         Diag(Constructor->getLocation(), diag::err_unintialized_member_in_ctor)
-          << Context.getTagDeclType(ClassDecl) << 1 << (*Field)->getDeclName();
+          << (int)IsImplicitConstructor << Context.getTagDeclType(ClassDecl)
+          << 1 << (*Field)->getDeclName();
         Diag((*Field)->getLocation(), diag::note_declared_at);
       }
     }
     else if (FT->isReferenceType()) {
       Diag(Constructor->getLocation(), diag::err_unintialized_member_in_ctor)
-        << Context.getTagDeclType(ClassDecl) << 0 << (*Field)->getDeclName();
+        << (int)IsImplicitConstructor << Context.getTagDeclType(ClassDecl)
+        << 0 << (*Field)->getDeclName();
       Diag((*Field)->getLocation(), diag::note_declared_at);
     }
     else if (FT.isConstQualified()) {
       Diag(Constructor->getLocation(), diag::err_unintialized_member_in_ctor)
-        << Context.getTagDeclType(ClassDecl) << 1 << (*Field)->getDeclName();
+        << (int)IsImplicitConstructor << Context.getTagDeclType(ClassDecl)
+        << 1 << (*Field)->getDeclName();
       Diag((*Field)->getLocation(), diag::note_declared_at);
     }
   }
@@ -1415,29 +1427,6 @@
   }
 }
 
-void
-Sema::BuildBaseOrMemberInitializers(ASTContext &C,
-                                 CXXConstructorDecl *Constructor,
-                                 CXXBaseOrMemberInitializer **Initializers,
-                                 unsigned NumInitializers
-                                 ) {
-  llvm::SmallVector<CXXBaseSpecifier *, 4> Bases;
-  llvm::SmallVector<FieldDecl *, 4> Members;
-
-  SetBaseOrMemberInitializers(Constructor,
-                              Initializers, NumInitializers, Bases, Members);
-  for (unsigned int i = 0; i < Bases.size(); i++) {
-    if (!Bases[i]->getType()->isDependentType())
-      Diag(Bases[i]->getSourceRange().getBegin(),
-           diag::err_missing_default_constructor) << 0 << Bases[i]->getType();
-  }
-  for (unsigned int i = 0; i < Members.size(); i++) {
-    if (!Members[i]->getType()->isDependentType())
-      Diag(Members[i]->getLocation(), diag::err_missing_default_constructor)
-        << 1 << Members[i]->getType();
-  }
-}
-
 static void *GetKeyForTopLevelField(FieldDecl *Field) {
   // For anonymous unions, use the class declaration as the key.
   if (const RecordType *RT = Field->getType()->getAs<RecordType>()) {
@@ -1462,7 +1451,7 @@
   if (Member->isMemberInitializer()) {
     FieldDecl *Field = Member->getMember();
 
-    // After BuildBaseOrMemberInitializers call, Field is the anonymous union
+    // After SetBaseOrMemberInitializers call, Field is the anonymous union
     // data member of the class. Data member used in the initializer list is
     // in AnonUnionMember field.
     if (MemberMaybeAnon && Field->isAnonymousStructOrUnion())
@@ -1527,9 +1516,9 @@
       return;
   }
 
-  BuildBaseOrMemberInitializers(Context, Constructor,
+  SetBaseOrMemberInitializers(Constructor,
                       reinterpret_cast<CXXBaseOrMemberInitializer **>(MemInits),
-                      NumMemInits);
+                      NumMemInits, false);
 
   if (Constructor->isDependentContext())
     return;
@@ -1694,9 +1683,7 @@
 
   if (CXXConstructorDecl *Constructor
       = dyn_cast<CXXConstructorDecl>(CDtorDecl.getAs<Decl>()))
-    BuildBaseOrMemberInitializers(Context,
-                                     Constructor,
-                                     (CXXBaseOrMemberInitializer **)0, 0);
+    SetBaseOrMemberInitializers(Constructor, 0, 0, false);
 }
 
 namespace {
@@ -2973,67 +2960,11 @@
   CXXRecordDecl *ClassDecl
     = cast<CXXRecordDecl>(Constructor->getDeclContext());
   assert(ClassDecl && "DefineImplicitDefaultConstructor - invalid constructor");
-  // Before the implicitly-declared default constructor for a class is
-  // implicitly defined, all the implicitly-declared default constructors
-  // for its base class and its non-static data members shall have been
-  // implicitly defined.
-  bool err = false;
-  for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin(),
-       E = ClassDecl->bases_end(); Base != E; ++Base) {
-    CXXRecordDecl *BaseClassDecl
-      = cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());
-    if (!BaseClassDecl->hasTrivialConstructor()) {
-      if (CXXConstructorDecl *BaseCtor =
-            BaseClassDecl->getDefaultConstructor(Context))
-        MarkDeclarationReferenced(CurrentLocation, BaseCtor);
-      else {
-        Diag(CurrentLocation, diag::err_defining_default_ctor)
-          << Context.getTagDeclType(ClassDecl) << 0
-          << Context.getTagDeclType(BaseClassDecl);
-        Diag(BaseClassDecl->getLocation(), diag::note_previous_class_decl)
-              << Context.getTagDeclType(BaseClassDecl);
-        err = true;
-      }
-    }
-  }
-  for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(),
-       E = ClassDecl->field_end(); Field != E; ++Field) {
-    QualType FieldType = Context.getCanonicalType((*Field)->getType());
-    if (const ArrayType *Array = Context.getAsArrayType(FieldType))
-      FieldType = Array->getElementType();
-    if (const RecordType *FieldClassType = FieldType->getAs<RecordType>()) {
-      CXXRecordDecl *FieldClassDecl
-        = cast<CXXRecordDecl>(FieldClassType->getDecl());
-      if (!FieldClassDecl->hasTrivialConstructor()) {
-        if (CXXConstructorDecl *FieldCtor =
-            FieldClassDecl->getDefaultConstructor(Context))
-          MarkDeclarationReferenced(CurrentLocation, FieldCtor);
-        else {
-          Diag(CurrentLocation, diag::err_defining_default_ctor)
-          << Context.getTagDeclType(ClassDecl) << 1 <<
-              Context.getTagDeclType(FieldClassDecl);
-          Diag((*Field)->getLocation(), diag::note_field_decl);
-          Diag(FieldClassDecl->getLocation(), diag::note_previous_class_decl)
-          << Context.getTagDeclType(FieldClassDecl);
-          err = true;
-        }
-      }
-    } else if (FieldType->isReferenceType()) {
-      Diag(CurrentLocation, diag::err_unintialized_member)
-        << Context.getTagDeclType(ClassDecl) << 0 << Field->getDeclName();
-      Diag((*Field)->getLocation(), diag::note_declared_at);
-      err = true;
-    } else if (FieldType.isConstQualified()) {
-      Diag(CurrentLocation, diag::err_unintialized_member)
-        << Context.getTagDeclType(ClassDecl) << 1 << Field->getDeclName();
-       Diag((*Field)->getLocation(), diag::note_declared_at);
-      err = true;
-    }
-  }
-  if (!err)
-    Constructor->setUsed();
-  else
-    Constructor->setInvalidDecl();
+
+  SetBaseOrMemberInitializers(Constructor, 0, 0, true);
+
+  Constructor->setUsed();
+  return;
 }
 
 void Sema::DefineImplicitDestructor(SourceLocation CurrentLocation,