Rework base and member initialization in constructors, with several
(necessarily simultaneous) changes:

  - CXXBaseOrMemberInitializer now contains only a single initializer
    rather than a set of initialiation arguments + a constructor. The
    single initializer covers all aspects of initialization, including
    constructor calls as necessary but also cleanup of temporaries
    created by the initializer (which we never handled
    before!).

  - Rework + simplify code generation for CXXBaseOrMemberInitializers,
    since we can now just emit the initializer as an initializer.

  - Switched base and member initialization over to the new
    initialization code (InitializationSequence), so that it

  - Improved diagnostics for the new initialization code when
    initializing bases and members, to match the diagnostics produced
    by the previous (special-purpose) code.

  - Simplify the representation of type-checked constructor initializers in
    templates; instead of keeping the fully-type-checked AST, which is
    rather hard to undo at template instantiation time, throw away the
    type-checked AST and store the raw expressions in the AST. This
    simplifies instantiation, but loses a little but of information in
    the AST.

  - When type-checking implicit base or member initializers within a
    dependent context, don't add the generated initializers into the
    AST, because they'll look like they were explicit.

  - Record in CXXConstructExpr when the constructor call is to
  initialize a base class, so that CodeGen does not have to infer it
  from context. This ensures that we call the right kind of
  constructor.

There are also a few "opportunity" fixes here that were needed to not
regress, for example:

  - Diagnose default-initialization of a const-qualified class that
    does not have a user-declared default constructor. We had this
    diagnostic specifically for bases and members, but missed it for
    variables. That's fixed now.

  - When defining the implicit constructors, destructor, and
    copy-assignment operator, set the CurContext to that constructor
    when we're defining the body.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@94952 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h
index 86dbff3..6f1ab14 100644
--- a/lib/Sema/Sema.h
+++ b/lib/Sema/Sema.h
@@ -1911,7 +1911,8 @@
                                          QualType DeclInitType,
                                          CXXConstructorDecl *Constructor,
                                          MultiExprArg Exprs,
-                                         bool RequiresZeroInit = false);
+                                         bool RequiresZeroInit = false,
+                                         bool BaseInitialization = false);
 
   // FIXME: Can re remove this and have the above BuildCXXConstructExpr check if
   // the constructor can be elidable?
@@ -1920,7 +1921,8 @@
                                          CXXConstructorDecl *Constructor,
                                          bool Elidable,
                                          MultiExprArg Exprs,
-                                         bool RequiresZeroInit = false);
+                                         bool RequiresZeroInit = false,
+                                         bool BaseInitialization = false);
 
   OwningExprResult BuildCXXTemporaryObjectExpr(CXXConstructorDecl *Cons,
                                                QualType writtenTy,
@@ -2282,9 +2284,10 @@
                                      CXXRecordDecl *ClassDecl);
 
   bool SetBaseOrMemberInitializers(CXXConstructorDecl *Constructor,
-                              CXXBaseOrMemberInitializer **Initializers,
-                              unsigned NumInitializers,
-                              bool IsImplicitConstructor);
+                                   CXXBaseOrMemberInitializer **Initializers,
+                                   unsigned NumInitializers,
+                                   bool IsImplicitConstructor,
+                                   bool AnyErrors);
 
   /// MarkBaseAndMemberDestructorsReferenced - Given a destructor decl,
   /// mark all its non-trivial member and base destructor declarations
@@ -2316,7 +2319,8 @@
 
   virtual void ActOnMemInitializers(DeclPtrTy ConstructorDecl,
                                     SourceLocation ColonLoc,
-                                    MemInitTy **MemInits, unsigned NumMemInits);
+                                    MemInitTy **MemInits, unsigned NumMemInits,
+                                    bool AnyErrors);
 
   void CheckCompletedCXXClass(CXXRecordDecl *Record);
   virtual void ActOnFinishCXXMemberSpecification(Scope* S, SourceLocation RLoc,
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index 130bf4d..f23f702 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -1195,10 +1195,6 @@
                              unsigned NumArgs, SourceLocation IdLoc,
                              SourceLocation LParenLoc,
                              SourceLocation RParenLoc) {
-  // FIXME: CXXBaseOrMemberInitializer should only contain a single 
-  // subexpression so we can wrap it in a CXXExprWithTemporaries if necessary.
-  ExprTemporaries.clear();
-
   // Diagnose value-uses of fields to initialize themselves, e.g.
   //   foo(foo)
   // where foo is not also a parameter to the constructor.
@@ -1220,65 +1216,80 @@
   for (unsigned i = 0; i < NumArgs; i++)
     HasDependentArg |= Args[i]->isTypeDependent();
 
-  CXXConstructorDecl *C = 0;
   QualType FieldType = Member->getType();
   if (const ArrayType *Array = Context.getAsArrayType(FieldType))
     FieldType = Array->getElementType();
   ASTOwningVector<&ActionBase::DeleteExpr> ConstructorArgs(*this);
-  if (FieldType->isDependentType()) {
-    // Can't check init for dependent type.
-  } else if (FieldType->isRecordType()) {
-    // Member is a record (struct/union/class), so pass the initializer
-    // arguments down to the record's constructor.
-    if (!HasDependentArg) {
-      C = PerformInitializationByConstructor(FieldType, 
-                                             MultiExprArg(*this, 
-                                                          (void**)Args, 
-                                                          NumArgs), 
-                                             IdLoc,
-                                             SourceRange(IdLoc, RParenLoc), 
-                                             Member->getDeclName(), 
-                  InitializationKind::CreateDirect(IdLoc, LParenLoc, RParenLoc),
-                                             ConstructorArgs);
-      
-      if (C) {
-        // Take over the constructor arguments as our own.
-        NumArgs = ConstructorArgs.size();
-        Args = (Expr **)ConstructorArgs.take();
-      }
-    }
-  } else if (NumArgs != 1 && NumArgs != 0) {
-    // The member type is not a record type (or an array of record
-    // types), so it can be only be default- or copy-initialized.
-    return Diag(IdLoc, diag::err_mem_initializer_mismatch)
-                << Member->getDeclName() << SourceRange(IdLoc, RParenLoc);
-  } else if (!HasDependentArg) {
-    Expr *NewExp;
-    if (NumArgs == 0) {
-      if (FieldType->isReferenceType()) {
-        Diag(IdLoc, diag::err_null_intialized_reference_member)
-              << Member->getDeclName();
-        return Diag(Member->getLocation(), diag::note_declared_at);
-      }
-      NewExp = new (Context) CXXZeroInitValueExpr(FieldType, IdLoc, RParenLoc);
-      NumArgs = 1;
-    }
-    else
-      NewExp = (Expr*)Args[0];
-    if (!Member->isInvalidDecl() &&
-        PerformCopyInitialization(NewExp, FieldType, AA_Passing))
-      return true;
-    Args[0] = NewExp;
+  if (FieldType->isDependentType() || HasDependentArg) {
+    // Can't check initialization for a member of dependent type or when
+    // any of the arguments are type-dependent expressions.
+    OwningExprResult Init
+      = Owned(new (Context) ParenListExpr(Context, LParenLoc, Args, NumArgs,
+                                          RParenLoc));
+
+    // Erase any temporaries within this evaluation context; we're not
+    // going to track them in the AST, since we'll be rebuilding the
+    // ASTs during template instantiation.
+    ExprTemporaries.erase(
+              ExprTemporaries.begin() + ExprEvalContexts.back().NumTemporaries,
+                          ExprTemporaries.end());
+    
+    return new (Context) CXXBaseOrMemberInitializer(Context, Member, IdLoc,
+                                                    LParenLoc, 
+                                                    Init.takeAs<Expr>(),
+                                                    RParenLoc);
+    
   }
   
-  // FIXME: CXXBaseOrMemberInitializer should only contain a single 
-  // subexpression so we can wrap it in a CXXExprWithTemporaries if necessary.
-  ExprTemporaries.clear();
+  if (Member->isInvalidDecl())
+    return true;
   
-  // FIXME: Perform direct initialization of the member.
+  // Initialize the member.
+  InitializedEntity MemberEntity =
+    InitializedEntity::InitializeMember(Member, 0);
+  InitializationKind Kind = 
+    InitializationKind::CreateDirect(IdLoc, LParenLoc, RParenLoc);
+  
+  InitializationSequence InitSeq(*this, MemberEntity, Kind, Args, NumArgs);
+  
+  OwningExprResult MemberInit =
+    InitSeq.Perform(*this, MemberEntity, Kind, 
+                    MultiExprArg(*this, (void**)Args, NumArgs), 0);
+  if (MemberInit.isInvalid())
+    return true;
+  
+  // C++0x [class.base.init]p7:
+  //   The initialization of each base and member constitutes a 
+  //   full-expression.
+  MemberInit = MaybeCreateCXXExprWithTemporaries(move(MemberInit));
+  if (MemberInit.isInvalid())
+    return true;
+  
+  // If we are in a dependent context, template instantiation will
+  // perform this type-checking again. Just save the arguments that we
+  // received in a ParenListExpr.
+  // FIXME: This isn't quite ideal, since our ASTs don't capture all
+  // of the information that we have about the member
+  // initializer. However, deconstructing the ASTs is a dicey process,
+  // and this approach is far more likely to get the corner cases right.
+  if (CurContext->isDependentContext()) {
+    // Bump the reference count of all of the arguments.
+    for (unsigned I = 0; I != NumArgs; ++I)
+      Args[I]->Retain();
+
+    OwningExprResult Init
+      = Owned(new (Context) ParenListExpr(Context, LParenLoc, Args, NumArgs,
+                                          RParenLoc));
+    return new (Context) CXXBaseOrMemberInitializer(Context, Member, IdLoc,
+                                                    LParenLoc, 
+                                                    Init.takeAs<Expr>(),
+                                                    RParenLoc);
+  }
+
   return new (Context) CXXBaseOrMemberInitializer(Context, Member, IdLoc,
-                                                  C, LParenLoc, (Expr **)Args,
-                                                  NumArgs, RParenLoc);
+                                                  LParenLoc, 
+                                                  MemberInit.takeAs<Expr>(),
+                                                  RParenLoc);
 }
 
 Sema::MemInitResult
@@ -1291,76 +1302,118 @@
     HasDependentArg |= Args[i]->isTypeDependent();
 
   SourceLocation BaseLoc = BaseTInfo->getTypeLoc().getSourceRange().getBegin();
-  if (!BaseType->isDependentType()) {
-    if (!BaseType->isRecordType())
-      return Diag(BaseLoc, diag::err_base_init_does_not_name_class)
-        << BaseType << BaseTInfo->getTypeLoc().getSourceRange();
+  if (BaseType->isDependentType() || HasDependentArg) {
+    // Can't check initialization for a base of dependent type or when
+    // any of the arguments are type-dependent expressions.
+    OwningExprResult BaseInit
+      = Owned(new (Context) ParenListExpr(Context, LParenLoc, Args, NumArgs,
+                                          RParenLoc));
 
-    // C++ [class.base.init]p2:
-    //   [...] Unless the mem-initializer-id names a nonstatic data
-    //   member of the constructor’s class or a direct or virtual base
-    //   of that class, the mem-initializer is ill-formed. A
-    //   mem-initializer-list can initialize a base class using any
-    //   name that denotes that base class type.
+    // Erase any temporaries within this evaluation context; we're not
+    // going to track them in the AST, since we'll be rebuilding the
+    // ASTs during template instantiation.
+    ExprTemporaries.erase(
+              ExprTemporaries.begin() + ExprEvalContexts.back().NumTemporaries,
+                          ExprTemporaries.end());
 
-    // Check for direct and virtual base classes.
-    const CXXBaseSpecifier *DirectBaseSpec = 0;
-    const CXXBaseSpecifier *VirtualBaseSpec = 0;
-    FindBaseInitializer(*this, ClassDecl, BaseType, DirectBaseSpec, 
-                        VirtualBaseSpec);
-
-    // C++ [base.class.init]p2:
-    //   If a mem-initializer-id is ambiguous because it designates both
-    //   a direct non-virtual base class and an inherited virtual base
-    //   class, the mem-initializer is ill-formed.
-    if (DirectBaseSpec && VirtualBaseSpec)
-      return Diag(BaseLoc, diag::err_base_init_direct_and_virtual)
-        << BaseType << BaseTInfo->getTypeLoc().getSourceRange();
-    // C++ [base.class.init]p2:
-    // Unless the mem-initializer-id names a nonstatic data membeer of the
-    // constructor's class ot a direst or virtual base of that class, the
-    // mem-initializer is ill-formed.
-    if (!DirectBaseSpec && !VirtualBaseSpec)
-      return Diag(BaseLoc, diag::err_not_direct_base_or_virtual)
-        << BaseType << ClassDecl->getNameAsCString()
-        << BaseTInfo->getTypeLoc().getSourceRange();
+    return new (Context) CXXBaseOrMemberInitializer(Context, BaseTInfo, 
+                                                    LParenLoc, 
+                                                    BaseInit.takeAs<Expr>(),
+                                                    RParenLoc);
   }
-
-  CXXConstructorDecl *C = 0;
-  ASTOwningVector<&ActionBase::DeleteExpr> ConstructorArgs(*this);
-  if (!BaseType->isDependentType() && !HasDependentArg) {
-    DeclarationName Name = Context.DeclarationNames.getCXXConstructorName(
-                      Context.getCanonicalType(BaseType).getUnqualifiedType());
-
-    C = PerformInitializationByConstructor(BaseType, 
-                                           MultiExprArg(*this, 
-                                                        (void**)Args, NumArgs),
-                                           BaseLoc, 
-                                           SourceRange(BaseLoc, RParenLoc),
-                                           Name, 
-                InitializationKind::CreateDirect(BaseLoc, LParenLoc, RParenLoc),
-                                           ConstructorArgs);
-    if (C) {
-      // Take over the constructor arguments as our own.
-      NumArgs = ConstructorArgs.size();
-      Args = (Expr **)ConstructorArgs.take();
-    }
-  }
-
-  // FIXME: CXXBaseOrMemberInitializer should only contain a single 
-  // subexpression so we can wrap it in a CXXExprWithTemporaries if necessary.
-  ExprTemporaries.clear();
   
-  return new (Context) CXXBaseOrMemberInitializer(Context, BaseTInfo, C, 
-                                                  LParenLoc, (Expr **)Args, 
-                                                  NumArgs, RParenLoc);
+  if (!BaseType->isRecordType())
+    return Diag(BaseLoc, diag::err_base_init_does_not_name_class)
+             << BaseType << BaseTInfo->getTypeLoc().getSourceRange();
+
+  // C++ [class.base.init]p2:
+  //   [...] Unless the mem-initializer-id names a nonstatic data
+  //   member of the constructor’s class or a direct or virtual base
+  //   of that class, the mem-initializer is ill-formed. A
+  //   mem-initializer-list can initialize a base class using any
+  //   name that denotes that base class type.
+
+  // Check for direct and virtual base classes.
+  const CXXBaseSpecifier *DirectBaseSpec = 0;
+  const CXXBaseSpecifier *VirtualBaseSpec = 0;
+  FindBaseInitializer(*this, ClassDecl, BaseType, DirectBaseSpec, 
+                      VirtualBaseSpec);
+
+  // C++ [base.class.init]p2:
+  //   If a mem-initializer-id is ambiguous because it designates both
+  //   a direct non-virtual base class and an inherited virtual base
+  //   class, the mem-initializer is ill-formed.
+  if (DirectBaseSpec && VirtualBaseSpec)
+    return Diag(BaseLoc, diag::err_base_init_direct_and_virtual)
+      << BaseType << BaseTInfo->getTypeLoc().getSourceRange();
+  // C++ [base.class.init]p2:
+  // Unless the mem-initializer-id names a nonstatic data membeer of the
+  // constructor's class ot a direst or virtual base of that class, the
+  // mem-initializer is ill-formed.
+  if (!DirectBaseSpec && !VirtualBaseSpec)
+    return Diag(BaseLoc, diag::err_not_direct_base_or_virtual)
+      << BaseType << ClassDecl->getNameAsCString()
+      << BaseTInfo->getTypeLoc().getSourceRange();
+
+  CXXBaseSpecifier *BaseSpec
+    = const_cast<CXXBaseSpecifier *>(DirectBaseSpec);
+  if (!BaseSpec)
+    BaseSpec = const_cast<CXXBaseSpecifier *>(VirtualBaseSpec);
+
+  // Initialize the base.
+  InitializedEntity BaseEntity =
+    InitializedEntity::InitializeBase(Context, BaseSpec);
+  InitializationKind Kind = 
+    InitializationKind::CreateDirect(BaseLoc, LParenLoc, RParenLoc);
+  
+  InitializationSequence InitSeq(*this, BaseEntity, Kind, Args, NumArgs);
+  
+  OwningExprResult BaseInit =
+    InitSeq.Perform(*this, BaseEntity, Kind, 
+                    MultiExprArg(*this, (void**)Args, NumArgs), 0);
+  if (BaseInit.isInvalid())
+    return true;
+  
+  // C++0x [class.base.init]p7:
+  //   The initialization of each base and member constitutes a 
+  //   full-expression.
+  BaseInit = MaybeCreateCXXExprWithTemporaries(move(BaseInit));
+  if (BaseInit.isInvalid())
+    return true;
+
+  // If we are in a dependent context, template instantiation will
+  // perform this type-checking again. Just save the arguments that we
+  // received in a ParenListExpr.
+  // FIXME: This isn't quite ideal, since our ASTs don't capture all
+  // of the information that we have about the base
+  // initializer. However, deconstructing the ASTs is a dicey process,
+  // and this approach is far more likely to get the corner cases right.
+  if (CurContext->isDependentContext()) {
+    // Bump the reference count of all of the arguments.
+    for (unsigned I = 0; I != NumArgs; ++I)
+      Args[I]->Retain();
+
+    OwningExprResult Init
+      = Owned(new (Context) ParenListExpr(Context, LParenLoc, Args, NumArgs,
+                                          RParenLoc));
+    return new (Context) CXXBaseOrMemberInitializer(Context, BaseTInfo,
+                                                    LParenLoc, 
+                                                    Init.takeAs<Expr>(),
+                                                    RParenLoc);
+  }
+
+  return new (Context) CXXBaseOrMemberInitializer(Context, BaseTInfo,
+                                                  LParenLoc, 
+                                                  BaseInit.takeAs<Expr>(),
+                                                  RParenLoc);
 }
 
 bool
 Sema::SetBaseOrMemberInitializers(CXXConstructorDecl *Constructor,
-                              CXXBaseOrMemberInitializer **Initializers,
-                              unsigned NumInitializers,
-                              bool IsImplicitConstructor) {
+                                  CXXBaseOrMemberInitializer **Initializers,
+                                  unsigned NumInitializers,
+                                  bool IsImplicitConstructor,
+                                  bool AnyErrors) {
   // 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());
@@ -1403,6 +1456,8 @@
         AllToInit.push_back(Member);
     }
   } else {
+    llvm::SmallVector<CXXBaseSpecifier *, 4> BasesToDefaultInit;
+    
     // Push virtual bases before others.
     for (CXXRecordDecl::base_class_iterator VBase =
          ClassDecl->vbases_begin(),
@@ -1412,44 +1467,34 @@
       if (CXXBaseOrMemberInitializer *Value
             = AllBaseFields.lookup(VBase->getType()->getAs<RecordType>())) {
         AllToInit.push_back(Value);
-      }
-      else {
-        CXXRecordDecl *VBaseDecl =
-          cast<CXXRecordDecl>(VBase->getType()->getAs<RecordType>()->getDecl());
-        assert(VBaseDecl && "SetBaseOrMemberInitializers - VBaseDecl null");
-        CXXConstructorDecl *Ctor = VBaseDecl->getDefaultConstructor(Context);
-        if (!Ctor) {
-          Diag(Constructor->getLocation(), diag::err_missing_default_ctor)
-            << (int)IsImplicitConstructor << Context.getTagDeclType(ClassDecl)
-            << 0 << VBase->getType();
-          Diag(VBaseDecl->getLocation(), diag::note_previous_decl)
-            << Context.getTagDeclType(VBaseDecl);
+      } else if (!AnyErrors) {
+        InitializedEntity InitEntity
+          = InitializedEntity::InitializeBase(Context, VBase);
+        InitializationKind InitKind
+          = InitializationKind::CreateDefault(Constructor->getLocation());
+        InitializationSequence InitSeq(*this, InitEntity, InitKind, 0, 0);        
+        OwningExprResult BaseInit = InitSeq.Perform(*this, InitEntity, InitKind,
+                                                    MultiExprArg(*this, 0, 0));
+        BaseInit = MaybeCreateCXXExprWithTemporaries(move(BaseInit));
+        if (BaseInit.isInvalid()) {
           HadError = true;
           continue;
         }
 
-        ASTOwningVector<&ActionBase::DeleteExpr> CtorArgs(*this);
-        if (CompleteConstructorCall(Ctor, MultiExprArg(*this, 0, 0), 
-                                    Constructor->getLocation(), CtorArgs))
+        // Don't attach synthesized base initializers in a dependent
+        // context; they'll be checked again at template instantiation
+        // time.
+        if (CurContext->isDependentContext())
           continue;
         
-        MarkDeclarationReferenced(Constructor->getLocation(), Ctor);
-        
-        // FIXME: CXXBaseOrMemberInitializer should only contain a single 
-        // subexpression so we can wrap it in a CXXExprWithTemporaries if 
-        // necessary.
-        // FIXME: Is there any better source-location information we can give?
-        ExprTemporaries.clear();
-        CXXBaseOrMemberInitializer *Member =
+        CXXBaseOrMemberInitializer *CXXBaseInit =
           new (Context) CXXBaseOrMemberInitializer(Context,
                              Context.getTrivialTypeSourceInfo(VBase->getType(), 
                                                               SourceLocation()),
-                                                   Ctor,
                                                    SourceLocation(),
-                                                   CtorArgs.takeAs<Expr>(),
-                                                   CtorArgs.size(), 
+                                                   BaseInit.takeAs<Expr>(),
                                                    SourceLocation());
-        AllToInit.push_back(Member);
+        AllToInit.push_back(CXXBaseInit);
       }
     }
 
@@ -1466,43 +1511,34 @@
             = AllBaseFields.lookup(Base->getType()->getAs<RecordType>())) {
         AllToInit.push_back(Value);
       }
-      else {
-        CXXRecordDecl *BaseDecl =
-          cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());
-        assert(BaseDecl && "SetBaseOrMemberInitializers - BaseDecl null");
-         CXXConstructorDecl *Ctor = BaseDecl->getDefaultConstructor(Context);
-        if (!Ctor) {
-          Diag(Constructor->getLocation(), diag::err_missing_default_ctor)
-            << (int)IsImplicitConstructor << Context.getTagDeclType(ClassDecl)
-            << 0 << Base->getType();
-          Diag(BaseDecl->getLocation(), diag::note_previous_decl)
-            << Context.getTagDeclType(BaseDecl);
+      else if (!AnyErrors) {
+        InitializedEntity InitEntity
+          = InitializedEntity::InitializeBase(Context, Base);
+        InitializationKind InitKind
+          = InitializationKind::CreateDefault(Constructor->getLocation());
+        InitializationSequence InitSeq(*this, InitEntity, InitKind, 0, 0);        
+        OwningExprResult BaseInit = InitSeq.Perform(*this, InitEntity, InitKind,
+                                                    MultiExprArg(*this, 0, 0));
+        BaseInit = MaybeCreateCXXExprWithTemporaries(move(BaseInit));
+        if (BaseInit.isInvalid()) {
           HadError = true;
           continue;
         }
-
-        ASTOwningVector<&ActionBase::DeleteExpr> CtorArgs(*this);
-        if (CompleteConstructorCall(Ctor, MultiExprArg(*this, 0, 0), 
-                                     Constructor->getLocation(), CtorArgs))
+        
+        // Don't attach synthesized base initializers in a dependent
+        // context; they'll be regenerated at template instantiation
+        // time.
+        if (CurContext->isDependentContext())
           continue;
         
-        MarkDeclarationReferenced(Constructor->getLocation(), Ctor);
-
-        // FIXME: CXXBaseOrMemberInitializer should only contain a single 
-        // subexpression so we can wrap it in a CXXExprWithTemporaries if 
-        // necessary.
-        // FIXME: Is there any better source-location information we can give?
-        ExprTemporaries.clear();
-        CXXBaseOrMemberInitializer *Member =
+        CXXBaseOrMemberInitializer *CXXBaseInit =
           new (Context) CXXBaseOrMemberInitializer(Context,
                              Context.getTrivialTypeSourceInfo(Base->getType(), 
                                                               SourceLocation()),
-                                                   Ctor,
                                                    SourceLocation(),
-                                                   CtorArgs.takeAs<Expr>(),
-                                                   CtorArgs.size(), 
+                                                   BaseInit.takeAs<Expr>(),
                                                    SourceLocation());
-        AllToInit.push_back(Member);
+        AllToInit.push_back(CXXBaseInit);
       }
     }
   }
@@ -1535,66 +1571,49 @@
       continue;
     }
 
-    if ((*Field)->getType()->isDependentType())
+    if ((*Field)->getType()->isDependentType() || AnyErrors)
       continue;
     
     QualType FT = Context.getBaseElementType((*Field)->getType());
-    if (const RecordType* RT = FT->getAs<RecordType>()) {
-      CXXConstructorDecl *Ctor =
-        cast<CXXRecordDecl>(RT->getDecl())->getDefaultConstructor(Context);
-      if (!Ctor) {
-        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_decl)
-          << Context.getTagDeclType(RT->getDecl());
+    if (FT->getAs<RecordType>()) {
+      InitializedEntity InitEntity
+        = InitializedEntity::InitializeMember(*Field);
+      InitializationKind InitKind
+        = InitializationKind::CreateDefault(Constructor->getLocation());
+
+      InitializationSequence InitSeq(*this, InitEntity, InitKind, 0, 0);
+      OwningExprResult MemberInit = InitSeq.Perform(*this, InitEntity, InitKind,
+                                                    MultiExprArg(*this, 0, 0));
+      MemberInit = MaybeCreateCXXExprWithTemporaries(move(MemberInit));
+      if (MemberInit.isInvalid()) {
         HadError = true;
         continue;
       }
-
-      if (FT.isConstQualified() && Ctor->isTrivial()) {
-        Diag(Constructor->getLocation(), diag::err_unintialized_member_in_ctor)
-          << (int)IsImplicitConstructor << Context.getTagDeclType(ClassDecl)
-          << 1 << (*Field)->getDeclName();
-        Diag((*Field)->getLocation(), diag::note_declared_at);
-        HadError = true;
-      }
-
-      // Don't create initializers for trivial constructors, since they don't
-      // actually need to be run.
-      if (Ctor->isTrivial())
-        continue;
-
-      ASTOwningVector<&ActionBase::DeleteExpr> CtorArgs(*this);
-      if (CompleteConstructorCall(Ctor, MultiExprArg(*this, 0, 0), 
-                                  Constructor->getLocation(), CtorArgs))
+      
+      // Don't attach synthesized member initializers in a dependent
+      // context; they'll be regenerated a template instantiation
+      // time.
+      if (CurContext->isDependentContext())
         continue;
       
-      // FIXME: CXXBaseOrMemberInitializer should only contain a single 
-      // subexpression so we can wrap it in a CXXExprWithTemporaries if necessary.
-      ExprTemporaries.clear();
       CXXBaseOrMemberInitializer *Member =
         new (Context) CXXBaseOrMemberInitializer(Context,
                                                  *Field, SourceLocation(),
-                                                 Ctor,
                                                  SourceLocation(),
-                                                 CtorArgs.takeAs<Expr>(),
-                                                 CtorArgs.size(),
+                                                 MemberInit.takeAs<Expr>(),
                                                  SourceLocation());
 
       AllToInit.push_back(Member);
-      MarkDeclarationReferenced(Constructor->getLocation(), Ctor);
     }
     else if (FT->isReferenceType()) {
-      Diag(Constructor->getLocation(), diag::err_unintialized_member_in_ctor)
+      Diag(Constructor->getLocation(), diag::err_uninitialized_member_in_ctor)
         << (int)IsImplicitConstructor << Context.getTagDeclType(ClassDecl)
         << 0 << (*Field)->getDeclName();
       Diag((*Field)->getLocation(), diag::note_declared_at);
       HadError = true;
     }
     else if (FT.isConstQualified()) {
-      Diag(Constructor->getLocation(), diag::err_unintialized_member_in_ctor)
+      Diag(Constructor->getLocation(), diag::err_uninitialized_member_in_ctor)
         << (int)IsImplicitConstructor << Context.getTagDeclType(ClassDecl)
         << 1 << (*Field)->getDeclName();
       Diag((*Field)->getLocation(), diag::note_declared_at);
@@ -1659,7 +1678,8 @@
 /// ActOnMemInitializers - Handle the member initializers for a constructor.
 void Sema::ActOnMemInitializers(DeclPtrTy ConstructorDecl,
                                 SourceLocation ColonLoc,
-                                MemInitTy **MemInits, unsigned NumMemInits) {
+                                MemInitTy **MemInits, unsigned NumMemInits,
+                                bool AnyErrors) {
   if (!ConstructorDecl)
     return;
 
@@ -1709,7 +1729,7 @@
 
   SetBaseOrMemberInitializers(Constructor,
                       reinterpret_cast<CXXBaseOrMemberInitializer **>(MemInits),
-                      NumMemInits, false);
+                      NumMemInits, false, AnyErrors);
 
   if (Constructor->isDependentContext())
     return;
@@ -1860,7 +1880,7 @@
 
   if (CXXConstructorDecl *Constructor
       = dyn_cast<CXXConstructorDecl>(CDtorDecl.getAs<Decl>()))
-    SetBaseOrMemberInitializers(Constructor, 0, 0, false);
+    SetBaseOrMemberInitializers(Constructor, 0, 0, false, false);
 }
 
 namespace {
@@ -3673,13 +3693,16 @@
     = cast<CXXRecordDecl>(Constructor->getDeclContext());
   assert(ClassDecl && "DefineImplicitDefaultConstructor - invalid constructor");
 
-  if (SetBaseOrMemberInitializers(Constructor, 0, 0, true)) {
+  DeclContext *PreviousContext = CurContext;
+  CurContext = Constructor;
+  if (SetBaseOrMemberInitializers(Constructor, 0, 0, true, false)) {
     Diag(CurrentLocation, diag::note_member_synthesized_at) 
       << CXXDefaultConstructor << Context.getTagDeclType(ClassDecl);
     Constructor->setInvalidDecl();
   } else {
     Constructor->setUsed();
   }
+  CurContext = PreviousContext;
 }
 
 void Sema::DefineImplicitDestructor(SourceLocation CurrentLocation,
@@ -3688,6 +3711,10 @@
          "DefineImplicitDestructor - call it for implicit default dtor");
   CXXRecordDecl *ClassDecl = Destructor->getParent();
   assert(ClassDecl && "DefineImplicitDestructor - invalid destructor");
+
+  DeclContext *PreviousContext = CurContext;
+  CurContext = Destructor;
+
   // C++ [class.dtor] p5
   // Before the implicitly-declared default destructor for a class is
   // implicitly defined, all the implicitly-declared default destructors
@@ -3734,8 +3761,11 @@
       << CXXDestructor << Context.getTagDeclType(ClassDecl);
 
     Destructor->setInvalidDecl();
+    CurContext = PreviousContext;
+
     return;
   }
+  CurContext = PreviousContext;
 
   Destructor->setUsed();
 }
@@ -3750,6 +3780,9 @@
   CXXRecordDecl *ClassDecl
     = cast<CXXRecordDecl>(MethodDecl->getDeclContext());
 
+  DeclContext *PreviousContext = CurContext;
+  CurContext = MethodDecl;
+
   // C++[class.copy] p12
   // Before the implicitly-declared copy assignment operator for a class is
   // implicitly defined, all implicitly-declared copy assignment operators
@@ -3793,6 +3826,8 @@
   }
   if (!err)
     MethodDecl->setUsed();
+
+  CurContext = PreviousContext;
 }
 
 CXXMethodDecl *
@@ -3835,6 +3870,10 @@
   CXXRecordDecl *ClassDecl
     = cast<CXXRecordDecl>(CopyConstructor->getDeclContext());
   assert(ClassDecl && "DefineImplicitCopyConstructor - invalid constructor");
+
+  DeclContext *PreviousContext = CurContext;
+  CurContext = CopyConstructor;
+
   // C++ [class.copy] p209
   // Before the implicitly-declared copy constructor for a class is
   // implicitly defined, all the implicitly-declared copy constructors
@@ -3863,13 +3902,16 @@
     }
   }
   CopyConstructor->setUsed();
+
+  CurContext = PreviousContext;
 }
 
 Sema::OwningExprResult
 Sema::BuildCXXConstructExpr(SourceLocation ConstructLoc, QualType DeclInitType,
                             CXXConstructorDecl *Constructor,
                             MultiExprArg ExprArgs,
-                            bool RequiresZeroInit) {
+                            bool RequiresZeroInit,
+                            bool BaseInitialization) {
   bool Elidable = false;
 
   // C++ [class.copy]p15:
@@ -3902,7 +3944,8 @@
   }
 
   return BuildCXXConstructExpr(ConstructLoc, DeclInitType, Constructor,
-                               Elidable, move(ExprArgs), RequiresZeroInit);
+                               Elidable, move(ExprArgs), RequiresZeroInit,
+                               BaseInitialization);
 }
 
 /// BuildCXXConstructExpr - Creates a complete call to a constructor,
@@ -3911,14 +3954,15 @@
 Sema::BuildCXXConstructExpr(SourceLocation ConstructLoc, QualType DeclInitType,
                             CXXConstructorDecl *Constructor, bool Elidable,
                             MultiExprArg ExprArgs,
-                            bool RequiresZeroInit) {
+                            bool RequiresZeroInit,
+                            bool BaseInitialization) {
   unsigned NumExprs = ExprArgs.size();
   Expr **Exprs = (Expr **)ExprArgs.release();
 
   MarkDeclarationReferenced(ConstructLoc, Constructor);
   return Owned(CXXConstructExpr::Create(Context, DeclInitType, ConstructLoc,
                                         Constructor, Elidable, Exprs, NumExprs, 
-                                        RequiresZeroInit));
+                                        RequiresZeroInit, BaseInitialization));
 }
 
 Sema::OwningExprResult
diff --git a/lib/Sema/SemaInit.cpp b/lib/Sema/SemaInit.cpp
index b0dee9c..5269167 100644
--- a/lib/Sema/SemaInit.cpp
+++ b/lib/Sema/SemaInit.cpp
@@ -2562,7 +2562,18 @@
                                 Result);
     return;
   }
-  
+
+  // C++0x [dcl.init]p6:
+  //   If a program calls for the default initialization of an object
+  //   of a const-qualified type T, T shall be a class type with a
+  //   user-provided default constructor.
+  if (Kind.getKind() == InitializationKind::IK_Default &&
+      Entity.getType().isConstQualified() &&
+      cast<CXXConstructorDecl>(Best->Function)->isImplicit()) {
+    Sequence.SetFailed(InitializationSequence::FK_DefaultInitOfConst);
+    return;
+  }
+
   // Add the constructor initialization step. Any cv-qualification conversion is
   // subsumed by the initialization.
   if (Kind.getKind() == InitializationKind::IK_Copy) {
@@ -2635,9 +2646,6 @@
   //       constructor for T is called (and the initialization is ill-formed if
   //       T has no accessible default constructor);
   if (DestType->isRecordType()) {
-    // FIXME: If a program calls for the default initialization of an object of
-    // a const-qualified type T, T shall be a class type with a user-provided 
-    // default constructor.
     return TryConstructorInitialization(S, Entity, Kind, 0, 0, DestType,
                                         Sequence);
   }
@@ -3408,7 +3416,8 @@
       CurInit = S.BuildCXXConstructExpr(Loc, Entity.getType(),
                                         Constructor, 
                                         move_arg(ConstructorArgs),
-                                        ConstructorInitRequiresZeroInit);
+                                        ConstructorInitRequiresZeroInit,
+                               Entity.getKind() == InitializedEntity::EK_Base);
       if (CurInit.isInvalid())
         return S.ExprError();
       
@@ -3488,8 +3497,13 @@
   QualType DestType = Entity.getType();
   switch (Failure) {
   case FK_TooManyInitsForReference:
-    S.Diag(Kind.getLocation(), diag::err_reference_has_multiple_inits)
-      << SourceRange(Args[0]->getLocStart(), Args[NumArgs - 1]->getLocEnd());
+    // FIXME: Customize for the initialized entity?
+    if (NumArgs == 0)
+      S.Diag(Kind.getLocation(), diag::err_reference_without_init)
+        << DestType.getNonReferenceType();
+    else  // FIXME: diagnostic below could be better!
+      S.Diag(Kind.getLocation(), diag::err_reference_has_multiple_inits)
+        << SourceRange(Args[0]->getLocStart(), Args[NumArgs - 1]->getLocEnd());
     break;
     
   case FK_ArrayNeedsInitList:
@@ -3634,6 +3648,45 @@
         break;
         
       case OR_No_Viable_Function:
+        if (Kind.getKind() == InitializationKind::IK_Default &&
+            (Entity.getKind() == InitializedEntity::EK_Base ||
+             Entity.getKind() == InitializedEntity::EK_Member) &&
+            isa<CXXConstructorDecl>(S.CurContext)) {
+          // This is implicit default initialization of a member or
+          // base within a constructor. If no viable function was
+          // found, notify the user that she needs to explicitly
+          // initialize this base/member.
+          CXXConstructorDecl *Constructor
+            = cast<CXXConstructorDecl>(S.CurContext);
+          if (Entity.getKind() == InitializedEntity::EK_Base) {
+            S.Diag(Kind.getLocation(), diag::err_missing_default_ctor)
+              << Constructor->isImplicit()
+              << S.Context.getTypeDeclType(Constructor->getParent())
+              << /*base=*/0
+              << Entity.getType();
+
+            RecordDecl *BaseDecl
+              = Entity.getBaseSpecifier()->getType()->getAs<RecordType>()
+                                                                  ->getDecl();
+            S.Diag(BaseDecl->getLocation(), diag::note_previous_decl)
+              << S.Context.getTagDeclType(BaseDecl);
+          } else {
+            S.Diag(Kind.getLocation(), diag::err_missing_default_ctor)
+              << Constructor->isImplicit()
+              << S.Context.getTypeDeclType(Constructor->getParent())
+              << /*member=*/1
+              << Entity.getName();
+            S.Diag(Entity.getDecl()->getLocation(), diag::note_field_decl);
+
+            if (const RecordType *Record
+                                 = Entity.getType()->getAs<RecordType>())
+              S.Diag(Record->getDecl()->getLocation(), 
+                     diag::note_previous_decl)
+                << S.Context.getTagDeclType(Record->getDecl());
+          }
+          break;
+        }
+
         S.Diag(Kind.getLocation(), diag::err_ovl_no_viable_function_in_init)
           << DestType << ArgsRange;
         S.PrintOverloadCandidates(FailedCandidateSet, Sema::OCD_AllCandidates,
@@ -3664,8 +3717,23 @@
   }
       
   case FK_DefaultInitOfConst:
-    S.Diag(Kind.getLocation(), diag::err_default_init_const)
-      << DestType;
+    if (Entity.getKind() == InitializedEntity::EK_Member &&
+        isa<CXXConstructorDecl>(S.CurContext)) {
+      // This is implicit default-initialization of a const member in
+      // a constructor. Complain that it needs to be explicitly
+      // initialized.
+      CXXConstructorDecl *Constructor = cast<CXXConstructorDecl>(S.CurContext);
+      S.Diag(Kind.getLocation(), diag::err_uninitialized_member_in_ctor)
+        << Constructor->isImplicit()
+        << S.Context.getTypeDeclType(Constructor->getParent())
+        << /*const=*/1
+        << Entity.getName();
+      S.Diag(Entity.getDecl()->getLocation(), diag::note_previous_decl)
+        << Entity.getName();
+    } else {
+      S.Diag(Kind.getLocation(), diag::err_default_init_const)
+        << DestType << (bool)DestType->getAs<RecordType>();
+    }
     break;
   }
   
diff --git a/lib/Sema/SemaInit.h b/lib/Sema/SemaInit.h
index 0b72fd4..001ba91 100644
--- a/lib/Sema/SemaInit.h
+++ b/lib/Sema/SemaInit.h
@@ -66,7 +66,6 @@
     /// \brief The entity being initialized is an element of a vector.
     /// or vector.
     EK_VectorElement
-
   };
   
 private:
@@ -95,8 +94,8 @@
     /// base class.
     CXXBaseSpecifier *Base;
 
-    /// \brief When Kind = EK_ArrayOrVectorElement, the index of the
-    /// array or vector element being initialized.
+    /// \brief When Kind = EK_ArrayElement or EK_VectorElement, the
+    /// index of the array or vector element being initialized.
     unsigned Index;
   };
 
@@ -201,6 +200,12 @@
   /// initialized.
   DeclaratorDecl *getDecl() const;
 
+  /// \brief Retrieve the base specifier.
+  CXXBaseSpecifier *getBaseSpecifier() const {
+    assert(getKind() == EK_Base && "Not a base specifier");
+    return Base;
+  }
+
   /// \brief Determine the location of the 'return' keyword when initializing
   /// the result of a function call.
   SourceLocation getReturnLoc() const {
diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp
index a2f1f63..d526962 100644
--- a/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -1830,7 +1830,8 @@
                            const MultiLevelTemplateArgumentList &TemplateArgs) {
 
   llvm::SmallVector<MemInitTy*, 4> NewInits;
-
+  bool AnyErrors = false;
+  
   // Instantiate all the initializers.
   for (CXXConstructorDecl::init_const_iterator Inits = Tmpl->init_begin(),
                                             InitsEnd = Tmpl->init_end();
@@ -1838,26 +1839,38 @@
     CXXBaseOrMemberInitializer *Init = *Inits;
 
     ASTOwningVector<&ActionBase::DeleteExpr> NewArgs(*this);
+    llvm::SmallVector<SourceLocation, 4> CommaLocs;
 
     // Instantiate all the arguments.
-    for (ExprIterator Args = Init->arg_begin(), ArgsEnd = Init->arg_end();
-         Args != ArgsEnd; ++Args) {
-      OwningExprResult NewArg = SubstExpr(*Args, TemplateArgs);
-
-      if (NewArg.isInvalid())
-        New->setInvalidDecl();
-      else
-        NewArgs.push_back(NewArg.takeAs<Expr>());
+    Expr *InitE = Init->getInit();
+    if (!InitE) {
+      // Nothing to instantiate;
+    } else if (ParenListExpr *ParenList = dyn_cast<ParenListExpr>(InitE)) {
+      if (InstantiateInitializationArguments(*this, ParenList->getExprs(),
+                                             ParenList->getNumExprs(),
+                                             TemplateArgs, CommaLocs, 
+                                             NewArgs)) {
+        AnyErrors = true;
+        continue;
+      }
+    } else {
+      OwningExprResult InitArg = SubstExpr(InitE, TemplateArgs);
+      if (InitArg.isInvalid()) {
+        AnyErrors = true;
+        continue;
+      }
+      
+      NewArgs.push_back(InitArg.release());
     }
-
+    
     MemInitResult NewInit;
-
     if (Init->isBaseInitializer()) {
       TypeSourceInfo *BaseTInfo = SubstType(Init->getBaseClassInfo(), 
                                             TemplateArgs, 
                                             Init->getSourceLocation(), 
                                             New->getDeclName());
       if (!BaseTInfo) {
+        AnyErrors = true;
         New->setInvalidDecl();
         continue;
       }
@@ -1885,9 +1898,10 @@
                                        Init->getRParenLoc());
     }
 
-    if (NewInit.isInvalid())
+    if (NewInit.isInvalid()) {
+      AnyErrors = true;
       New->setInvalidDecl();
-    else {
+    } else {
       // FIXME: It would be nice if ASTOwningVector had a release function.
       NewArgs.take();
 
@@ -1899,7 +1913,8 @@
   ActOnMemInitializers(DeclPtrTy::make(New),
                        /*FIXME: ColonLoc */
                        SourceLocation(),
-                       NewInits.data(), NewInits.size());
+                       NewInits.data(), NewInits.size(),
+                       AnyErrors);
 }
 
 // TODO: this could be templated if the various decl types used the