[cfe-commits] r94952 - in /cfe/trunk: include/clang/AST/ include/clang/Basic/ include/clang/Parse/ lib/AST/ lib/CodeGen/ lib/Parse/ lib/Sema/ test/CXX/dcl.decl/dcl.init/ test/SemaCXX/ test/SemaTemplate/

Douglas Gregor dgregor at apple.com
Sun Jan 31 01:12:52 PST 2010


Author: dgregor
Date: Sun Jan 31 03:12:51 2010
New Revision: 94952

URL: http://llvm.org/viewvc/llvm-project?rev=94952&view=rev
Log:
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.


Added:
    cfe/trunk/test/CXX/dcl.decl/dcl.init/p6.cpp   (with props)
Modified:
    cfe/trunk/include/clang/AST/DeclCXX.h
    cfe/trunk/include/clang/AST/ExprCXX.h
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
    cfe/trunk/include/clang/Parse/Action.h
    cfe/trunk/lib/AST/DeclCXX.cpp
    cfe/trunk/lib/AST/DeclPrinter.cpp
    cfe/trunk/lib/AST/ExprCXX.cpp
    cfe/trunk/lib/CodeGen/CGClass.cpp
    cfe/trunk/lib/CodeGen/CGExprCXX.cpp
    cfe/trunk/lib/Parse/ParseDeclCXX.cpp
    cfe/trunk/lib/Sema/Sema.h
    cfe/trunk/lib/Sema/SemaDeclCXX.cpp
    cfe/trunk/lib/Sema/SemaInit.cpp
    cfe/trunk/lib/Sema/SemaInit.h
    cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
    cfe/trunk/test/SemaCXX/constructor-initializer.cpp
    cfe/trunk/test/SemaCXX/copy-assignment.cpp
    cfe/trunk/test/SemaCXX/illegal-member-initialization.cpp
    cfe/trunk/test/SemaCXX/overload-member-call.cpp
    cfe/trunk/test/SemaCXX/overloaded-operator.cpp
    cfe/trunk/test/SemaTemplate/instantiate-member-initializers.cpp

Modified: cfe/trunk/include/clang/AST/DeclCXX.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclCXX.h?rev=94952&r1=94951&r2=94952&view=diff

==============================================================================
--- cfe/trunk/include/clang/AST/DeclCXX.h (original)
+++ cfe/trunk/include/clang/AST/DeclCXX.h Sun Jan 31 03:12:51 2010
@@ -941,9 +941,9 @@
   /// \brief The source location for the field name.
   SourceLocation MemberLocation;
   
-  /// Args - The arguments used to initialize the base or member.
-  Stmt **Args;
-  unsigned NumArgs;
+  /// \brief The argument used to initialize the base or member, which may
+  /// end up constructing an object (when multiple arguments are involved).
+  Stmt *Init;
 
   /// \brief Stores either the constructor to call to initialize this base or
   /// member (a CXXConstructorDecl pointer), or stores the anonymous union of
@@ -963,7 +963,7 @@
   /// @endcode
   /// In above example, BaseOrMember holds the field decl. for anonymous union
   /// and AnonUnionMember holds field decl for au_i1.
-  llvm::PointerUnion<CXXConstructorDecl *, FieldDecl *> CtorOrAnonUnion;
+  FieldDecl *AnonUnionMember;
 
   /// LParenLoc - Location of the left paren of the ctor-initializer.
   SourceLocation LParenLoc;
@@ -975,30 +975,22 @@
   /// CXXBaseOrMemberInitializer - Creates a new base-class initializer.
   explicit
   CXXBaseOrMemberInitializer(ASTContext &Context,
-                             TypeSourceInfo *TInfo, CXXConstructorDecl *C,
+                             TypeSourceInfo *TInfo,
                              SourceLocation L, 
-                             Expr **Args, unsigned NumArgs,
+                             Expr *Init,
                              SourceLocation R);
 
   /// CXXBaseOrMemberInitializer - Creates a new member initializer.
   explicit
   CXXBaseOrMemberInitializer(ASTContext &Context,
                              FieldDecl *Member, SourceLocation MemberLoc,
-                             CXXConstructorDecl *C, SourceLocation L,
-                             Expr **Args, unsigned NumArgs,
+                             SourceLocation L,
+                             Expr *Init,
                              SourceLocation R);
 
   /// \brief Destroy the base or member initializer.
   void Destroy(ASTContext &Context);
 
-  /// arg_iterator - Iterates through the member initialization
-  /// arguments.
-  typedef ExprIterator arg_iterator;
-
-  /// arg_const_iterator - Iterates through the member initialization
-  /// arguments.
-  typedef ConstExprIterator const_arg_iterator;
-
   /// isBaseInitializer - Returns true when this initializer is
   /// initializing a base class.
   bool isBaseInitializer() const { return BaseOrMember.is<TypeSourceInfo*>(); }
@@ -1048,32 +1040,16 @@
   SourceRange getSourceRange() const;
   
   FieldDecl *getAnonUnionMember() const {
-    return CtorOrAnonUnion.dyn_cast<FieldDecl *>();
+    return AnonUnionMember;
   }
   void setAnonUnionMember(FieldDecl *anonMember) {
-    CtorOrAnonUnion = anonMember;
-  }
-
-  const CXXConstructorDecl *getConstructor() const {
-    return CtorOrAnonUnion.dyn_cast<CXXConstructorDecl *>();
+    AnonUnionMember = anonMember;
   }
 
   SourceLocation getLParenLoc() const { return LParenLoc; }
   SourceLocation getRParenLoc() const { return RParenLoc; }
 
-  /// arg_begin() - Retrieve an iterator to the first initializer argument.
-  arg_iterator       arg_begin()       { return Args; }
-  /// arg_begin() - Retrieve an iterator to the first initializer argument.
-  const_arg_iterator const_arg_begin() const { return Args; }
-
-  /// arg_end() - Retrieve an iterator past the last initializer argument.
-  arg_iterator       arg_end()       { return Args + NumArgs; }
-  /// arg_end() - Retrieve an iterator past the last initializer argument.
-  const_arg_iterator const_arg_end() const { return Args + NumArgs; }
-
-  /// getNumArgs - Determine the number of arguments used to
-  /// initialize the member or base.
-  unsigned getNumArgs() const { return NumArgs; }
+  Expr *getInit() { return static_cast<Expr *>(Init); }
 };
 
 /// CXXConstructorDecl - Represents a C++ constructor within a

Modified: cfe/trunk/include/clang/AST/ExprCXX.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ExprCXX.h?rev=94952&r1=94951&r2=94952&view=diff

==============================================================================
--- cfe/trunk/include/clang/AST/ExprCXX.h (original)
+++ cfe/trunk/include/clang/AST/ExprCXX.h Sun Jan 31 03:12:51 2010
@@ -613,6 +613,7 @@
   SourceLocation Loc;
   bool Elidable : 1;
   bool ZeroInitialization : 1;
+  bool BaseInitialization : 1;
   Stmt **Args;
   unsigned NumArgs;
 
@@ -621,7 +622,8 @@
                    SourceLocation Loc,
                    CXXConstructorDecl *d, bool elidable,
                    Expr **args, unsigned numargs,
-                   bool ZeroInitialization = false);
+                   bool ZeroInitialization = false,
+                   bool BaseInitialization = false);
   ~CXXConstructExpr() { }
 
   virtual void DoDestroy(ASTContext &C);
@@ -635,7 +637,8 @@
                                   SourceLocation Loc,
                                   CXXConstructorDecl *D, bool Elidable,
                                   Expr **Args, unsigned NumArgs,
-                                  bool ZeroInitialization = false);
+                                  bool ZeroInitialization = false,
+                                  bool BaseInitialization = false);
 
 
   CXXConstructorDecl* getConstructor() const { return Constructor; }
@@ -655,6 +658,11 @@
     ZeroInitialization = ZeroInit;
   }
   
+  /// \brief Determines whether this constructor is actually constructing
+  /// a base class (rather than a complete object).
+  bool isBaseInitialization() const { return BaseInitialization; }
+  void setBaseInitialization(bool BI) { BaseInitialization = BI; }
+  
   typedef ExprIterator arg_iterator;
   typedef ConstExprIterator const_arg_iterator;
 

Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=94952&r1=94951&r2=94952&view=diff

==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Sun Jan 31 03:12:51 2010
@@ -588,6 +588,8 @@
   "declaration of reference variable %0 requires an initializer">;
 def err_const_var_requires_init : Error<
   "declaration of const variable '%0' requires an initializer">;
+def err_reference_without_init : Error<
+  "reference to type %0 requires an initializer">;
 def err_reference_has_multiple_inits : Error<
   "reference cannot be initialized with multiple values">;
 def err_init_non_aggr_init_list : Error<
@@ -880,10 +882,7 @@
   "assignment operator">;
 def note_first_required_here : Note<
   "synthesized method is first required here">;
-def err_null_intialized_reference_member : Error<
-  "cannot initialize the member to null in default constructor because "
-  "reference member %0 cannot be null-initialized">;
-def err_unintialized_member_in_ctor : Error<
+def err_uninitialized_member_in_ctor : Error<
   "%select{|implicit default }0constructor for %1 must explicitly initialize "
   "the %select{reference|const}2 member %3">;
 
@@ -1949,7 +1948,8 @@
 def err_array_size_not_integral : Error<
   "array size expression must have integral or enumerated type, not %0">;
 def err_default_init_const : Error<
-  "default initialization of an object of const type %0">;  
+  "default initialization of an object of const type %0"
+  "%select{| requires a user-provided default constructor}1">;
 def err_delete_operand : Error<"cannot delete expression of type %0">;
 def err_ambiguous_delete_operand : Error<"ambiguous conversion of delete "
                                          "expression of type %0 to a pointer">;
@@ -2252,8 +2252,6 @@
 def err_mem_init_not_member_or_class : Error<
   "member initializer %0 does not name a non-static data member or base "
   "class">;
-def err_mem_initializer_mismatch : Error<
-  "Too many arguments for member initializer %0">;
 
 def warn_field_initialized : Warning<
   "member '%0' will be initialized after">,

Modified: cfe/trunk/include/clang/Parse/Action.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Action.h?rev=94952&r1=94951&r2=94952&view=diff

==============================================================================
--- cfe/trunk/include/clang/Parse/Action.h (original)
+++ cfe/trunk/include/clang/Parse/Action.h Sun Jan 31 03:12:51 2010
@@ -1654,9 +1654,12 @@
   /// a well-formed program), ColonLoc is the location of the ':' that
   /// starts the constructor initializer, and MemInit/NumMemInits
   /// contains the individual member (and base) initializers.
+  /// AnyErrors will be true if there were any invalid member initializers
+  /// that are not represented in the list.
   virtual void ActOnMemInitializers(DeclPtrTy ConstructorDecl,
                                     SourceLocation ColonLoc,
-                                    MemInitTy **MemInits, unsigned NumMemInits){
+                                    MemInitTy **MemInits, unsigned NumMemInits,
+                                    bool AnyErrors){
   }
 
  virtual void ActOnDefaultCtorInitializers(DeclPtrTy CDtorDecl) {}

Modified: cfe/trunk/lib/AST/DeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclCXX.cpp?rev=94952&r1=94951&r2=94952&view=diff

==============================================================================
--- cfe/trunk/lib/AST/DeclCXX.cpp (original)
+++ cfe/trunk/lib/AST/DeclCXX.cpp Sun Jan 31 03:12:51 2010
@@ -673,42 +673,25 @@
 
 CXXBaseOrMemberInitializer::
 CXXBaseOrMemberInitializer(ASTContext &Context,
-                           TypeSourceInfo *TInfo, CXXConstructorDecl *C,
-                           SourceLocation L, 
-                           Expr **Args, unsigned NumArgs,
-                           SourceLocation R)
-  : BaseOrMember(TInfo), Args(0), NumArgs(0), CtorOrAnonUnion(C), 
+                           TypeSourceInfo *TInfo, 
+                           SourceLocation L, Expr *Init, SourceLocation R)
+  : BaseOrMember(TInfo), Init(Init), AnonUnionMember(0),
     LParenLoc(L), RParenLoc(R) 
 {
-  if (NumArgs > 0) {
-    this->NumArgs = NumArgs;
-    this->Args = new (Context) Stmt*[NumArgs];
-    for (unsigned Idx = 0; Idx < NumArgs; ++Idx)
-      this->Args[Idx] = Args[Idx];
-  }
 }
 
 CXXBaseOrMemberInitializer::
 CXXBaseOrMemberInitializer(ASTContext &Context,
                            FieldDecl *Member, SourceLocation MemberLoc,
-                           CXXConstructorDecl *C, SourceLocation L,
-                           Expr **Args, unsigned NumArgs,
-                           SourceLocation R)
-  : BaseOrMember(Member), MemberLocation(MemberLoc), Args(0), NumArgs(0), 
-    CtorOrAnonUnion(C), LParenLoc(L), RParenLoc(R) 
+                           SourceLocation L, Expr *Init, SourceLocation R)
+  : BaseOrMember(Member), MemberLocation(MemberLoc), Init(Init), 
+    AnonUnionMember(0), LParenLoc(L), RParenLoc(R) 
 {
-  if (NumArgs > 0) {
-    this->NumArgs = NumArgs;
-    this->Args = new (Context) Stmt*[NumArgs];
-    for (unsigned Idx = 0; Idx < NumArgs; ++Idx)
-      this->Args[Idx] = Args[Idx];
-  }
 }
 
 void CXXBaseOrMemberInitializer::Destroy(ASTContext &Context) {
-  for (unsigned I = 0; I != NumArgs; ++I)
-    Args[I]->Destroy(Context);
-  Context.Deallocate(Args);
+  if (Init)
+    Init->Destroy(Context);
   this->~CXXBaseOrMemberInitializer();
 }
 

Modified: cfe/trunk/lib/AST/DeclPrinter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclPrinter.cpp?rev=94952&r1=94951&r2=94952&view=diff

==============================================================================
--- cfe/trunk/lib/AST/DeclPrinter.cpp (original)
+++ cfe/trunk/lib/AST/DeclPrinter.cpp Sun Jan 31 03:12:51 2010
@@ -17,6 +17,7 @@
 #include "clang/AST/DeclCXX.h"
 #include "clang/AST/DeclObjC.h"
 #include "clang/AST/Expr.h"
+#include "clang/AST/ExprCXX.h"
 #include "clang/AST/PrettyPrinter.h"
 #include "llvm/Support/raw_ostream.h"
 using namespace clang;
@@ -403,32 +404,51 @@
           CXXBaseOrMemberInitializer * BMInitializer = (*B);
           if (B != CDecl->init_begin())
             Out << ", ";
-          bool hasArguments = (BMInitializer->arg_begin() !=
-                               BMInitializer->arg_end());
           if (BMInitializer->isMemberInitializer()) {
             FieldDecl *FD = BMInitializer->getMember();
             Out <<  FD->getNameAsString();
+          } else {
+            Out << QualType(BMInitializer->getBaseClass(), 0).getAsString();
           }
-          else // FIXME. skip dependent types for now.
-            if (const RecordType *RT =
-                BMInitializer->getBaseClass()->getAs<RecordType>()) {
-              const CXXRecordDecl *BaseDecl =
-                cast<CXXRecordDecl>(RT->getDecl());
-              Out << BaseDecl->getNameAsString();
-          }
-          if (hasArguments) {
-            Out << "(";
-            for (CXXBaseOrMemberInitializer::const_arg_iterator BE =
-                 BMInitializer->const_arg_begin(),
-                 EE =  BMInitializer->const_arg_end(); BE != EE; ++BE) {
-              if (BE != BMInitializer->const_arg_begin())
-                Out<< ", ";
-              const Expr *Exp = (*BE);
-              Exp->printPretty(Out, Context, 0, Policy, Indentation);
+          
+          Out << "(";
+          if (!BMInitializer->getInit()) {
+            // Nothing to print
+          } else {
+            Expr *Init = BMInitializer->getInit();
+            if (CXXExprWithTemporaries *Tmp
+                  = dyn_cast<CXXExprWithTemporaries>(Init))
+              Init = Tmp->getSubExpr();
+            
+            Init = Init->IgnoreParens();
+            
+            Expr *SimpleInit = 0;
+            Expr **Args = 0;
+            unsigned NumArgs = 0;
+            if (ParenListExpr *ParenList = dyn_cast<ParenListExpr>(Init)) {
+              Args = ParenList->getExprs();
+              NumArgs = ParenList->getNumExprs();
+            } else if (CXXConstructExpr *Construct
+                                          = dyn_cast<CXXConstructExpr>(Init)) {
+              Args = Construct->getArgs();
+              NumArgs = Construct->getNumArgs();
+            } else
+              SimpleInit = Init;
+            
+            if (SimpleInit)
+              SimpleInit->printPretty(Out, Context, 0, Policy, Indentation);
+            else {
+              for (unsigned I = 0; I != NumArgs; ++I) {
+                if (isa<CXXDefaultArgExpr>(Args[I]))
+                  break;
+                
+                if (I)
+                  Out << ", ";
+                Args[I]->printPretty(Out, Context, 0, Policy, Indentation);
+              }
             }
-            Out << ")";
-          } else
-            Out << "()";
+          }
+          Out << ")";
         }
       }
     }

Modified: cfe/trunk/lib/AST/ExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprCXX.cpp?rev=94952&r1=94951&r2=94952&view=diff

==============================================================================
--- cfe/trunk/lib/AST/ExprCXX.cpp (original)
+++ cfe/trunk/lib/AST/ExprCXX.cpp Sun Jan 31 03:12:51 2010
@@ -424,22 +424,26 @@
                                            SourceLocation Loc,
                                            CXXConstructorDecl *D, bool Elidable,
                                            Expr **Args, unsigned NumArgs,
-                                           bool ZeroInitialization) {
+                                           bool ZeroInitialization,
+                                           bool BaseInitialization) {
   return new (C) CXXConstructExpr(C, CXXConstructExprClass, T, Loc, D, 
-                                  Elidable, Args, NumArgs, ZeroInitialization);
+                                  Elidable, Args, NumArgs, ZeroInitialization,
+                                  BaseInitialization);
 }
 
 CXXConstructExpr::CXXConstructExpr(ASTContext &C, StmtClass SC, QualType T,
                                    SourceLocation Loc,
                                    CXXConstructorDecl *D, bool elidable,
                                    Expr **args, unsigned numargs,
-                                   bool ZeroInitialization)
+                                   bool ZeroInitialization,
+                                   bool BaseInitialization)
 : Expr(SC, T,
        T->isDependentType(),
        (T->isDependentType() ||
         CallExpr::hasAnyValueDependentArguments(args, numargs))),
   Constructor(D), Loc(Loc), Elidable(elidable), 
-  ZeroInitialization(ZeroInitialization), Args(0), NumArgs(numargs) 
+  ZeroInitialization(ZeroInitialization), 
+  BaseInitialization(BaseInitialization), Args(0), NumArgs(numargs) 
 {
   if (NumArgs) {
     Args = new (C) Stmt*[NumArgs];

Modified: cfe/trunk/lib/CodeGen/CGClass.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGClass.cpp?rev=94952&r1=94951&r2=94952&view=diff

==============================================================================
--- cfe/trunk/lib/CodeGen/CGClass.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGClass.cpp Sun Jan 31 03:12:51 2010
@@ -811,11 +811,7 @@
   llvm::Value *V = CGF.Builder.CreateBitCast(ThisPtr, Int8PtrTy);
   V = CGF.Builder.CreateConstInBoundsGEP1_64(V, Offset/8);
   V = CGF.Builder.CreateBitCast(V, BaseClassType->getPointerTo());
-
-  CGF.EmitCXXConstructorCall(BaseInit->getConstructor(),
-                             Ctor_Base, V,
-                             BaseInit->const_arg_begin(),
-                             BaseInit->const_arg_end());
+  CGF.EmitAggExpr(BaseInit->getInit(), V, false, false, true);
 }
 
 static void EmitMemberInitializer(CodeGenFunction &CGF,
@@ -846,55 +842,34 @@
 
   // We lose the constructor for anonymous union members, so handle them
   // explicitly.
-  // FIXME: This is somwhat ugly.
+  // FIXME: This is somwhat ugly, and doesn't seem necessary at all.
   if (MemberInit->getAnonUnionMember() && FieldType->getAs<RecordType>()) {
-    if (MemberInit->getNumArgs())
-      CGF.EmitAggExpr(*MemberInit->arg_begin(), LHS.getAddress(),
+    if (MemberInit->getInit())
+      CGF.EmitAggExpr(MemberInit->getInit(), LHS.getAddress(), 
                       LHS.isVolatileQualified());
     else
       CGF.EmitAggregateClear(LHS.getAddress(), Field->getType());
     return;
   }
 
-  if (FieldType->getAs<RecordType>()) {
-    assert(MemberInit->getConstructor() &&
-           "EmitCtorPrologue - no constructor to initialize member");
-    if (Array) {
-      const llvm::Type *BasePtr = CGF.ConvertType(FieldType);
-      BasePtr = llvm::PointerType::getUnqual(BasePtr);
-      llvm::Value *BaseAddrPtr =
-        CGF.Builder.CreateBitCast(LHS.getAddress(), BasePtr);
-      CGF.EmitCXXAggrConstructorCall(MemberInit->getConstructor(),
-                                     Array, BaseAddrPtr,
-                                     MemberInit->const_arg_begin(),
-                                     MemberInit->const_arg_end());
-    }
-    else
-      CGF.EmitCXXConstructorCall(MemberInit->getConstructor(),
-                                 Ctor_Complete, LHS.getAddress(),
-                                 MemberInit->const_arg_begin(),
-                                 MemberInit->const_arg_end());
-    return;
-  }
-
-  assert(MemberInit->getNumArgs() == 1 && "Initializer count must be 1 only");
-  Expr *RhsExpr = *MemberInit->arg_begin();
+  // FIXME: If there's no initializer and the CXXBaseOrMemberInitializer
+  // was implicitly generated, we shouldn't be zeroing memory.
   RValue RHS;
   if (FieldType->isReferenceType()) {
-    RHS = CGF.EmitReferenceBindingToExpr(RhsExpr, FieldType,
-                                    /*IsInitializer=*/true);
+    RHS = CGF.EmitReferenceBindingToExpr(MemberInit->getInit(), FieldType,
+                                         /*IsInitializer=*/true);
     CGF.EmitStoreThroughLValue(RHS, LHS, FieldType);
-  } else if (Array) {
+  } else if (Array && !MemberInit->getInit()) {
     CGF.EmitMemSetToZero(LHS.getAddress(), Field->getType());
-  } else if (!CGF.hasAggregateLLVMType(RhsExpr->getType())) {
-    RHS = RValue::get(CGF.EmitScalarExpr(RhsExpr, true));
+  } else if (!CGF.hasAggregateLLVMType(Field->getType())) {
+    RHS = RValue::get(CGF.EmitScalarExpr(MemberInit->getInit(), true));
     CGF.EmitStoreThroughLValue(RHS, LHS, FieldType);
-  } else if (RhsExpr->getType()->isAnyComplexType()) {
-    CGF.EmitComplexExprIntoAddr(RhsExpr, LHS.getAddress(),
+  } else if (MemberInit->getInit()->getType()->isAnyComplexType()) {
+    CGF.EmitComplexExprIntoAddr(MemberInit->getInit(), LHS.getAddress(),
                                 LHS.isVolatileQualified());
   } else {
-    // Handle member function pointers; other aggregates shouldn't get this far.
-    CGF.EmitAggExpr(RhsExpr, LHS.getAddress(), LHS.isVolatileQualified());
+    CGF.EmitAggExpr(MemberInit->getInit(), LHS.getAddress(), 
+                    LHS.isVolatileQualified(), false, true);
   }
 }
 

Modified: cfe/trunk/lib/CodeGen/CGExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprCXX.cpp?rev=94952&r1=94951&r2=94952&view=diff

==============================================================================
--- cfe/trunk/lib/CodeGen/CGExprCXX.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExprCXX.cpp Sun Jan 31 03:12:51 2010
@@ -339,7 +339,9 @@
   }
   else
     // Call the constructor.
-    EmitCXXConstructorCall(CD, Ctor_Complete, Dest,
+    EmitCXXConstructorCall(CD, 
+                           E->isBaseInitialization()? Ctor_Base : Ctor_Complete, 
+                           Dest,
                            E->arg_begin(), E->arg_end());
 }
 

Modified: cfe/trunk/lib/Parse/ParseDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDeclCXX.cpp?rev=94952&r1=94951&r2=94952&view=diff

==============================================================================
--- cfe/trunk/lib/Parse/ParseDeclCXX.cpp (original)
+++ cfe/trunk/lib/Parse/ParseDeclCXX.cpp Sun Jan 31 03:12:51 2010
@@ -1550,12 +1550,15 @@
   SourceLocation ColonLoc = ConsumeToken();
 
   llvm::SmallVector<MemInitTy*, 4> MemInitializers;
-
+  bool AnyErrors = false;
+  
   do {
     MemInitResult MemInit = ParseMemInitializer(ConstructorDecl);
     if (!MemInit.isInvalid())
       MemInitializers.push_back(MemInit.get());
-
+    else
+      AnyErrors = true;
+    
     if (Tok.is(tok::comma))
       ConsumeToken();
     else if (Tok.is(tok::l_brace))
@@ -1569,7 +1572,8 @@
   } while (true);
 
   Actions.ActOnMemInitializers(ConstructorDecl, ColonLoc,
-                               MemInitializers.data(), MemInitializers.size());
+                               MemInitializers.data(), MemInitializers.size(),
+                               AnyErrors);
 }
 
 /// ParseMemInitializer - Parse a C++ member initializer, which is

Modified: cfe/trunk/lib/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=94952&r1=94951&r2=94952&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Sun Jan 31 03:12:51 2010
@@ -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,

Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=94952&r1=94951&r2=94952&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Sun Jan 31 03:12:51 2010
@@ -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();
-
-    // 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();
-  }
-
-  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();
-    }
+  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));
+
+    // 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, BaseTInfo, 
+                                                    LParenLoc, 
+                                                    BaseInit.takeAs<Expr>(),
+                                                    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;
 
-  // 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 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

Modified: cfe/trunk/lib/Sema/SemaInit.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaInit.cpp?rev=94952&r1=94951&r2=94952&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaInit.cpp (original)
+++ cfe/trunk/lib/Sema/SemaInit.cpp Sun Jan 31 03:12:51 2010
@@ -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;
   }
   

Modified: cfe/trunk/lib/Sema/SemaInit.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaInit.h?rev=94952&r1=94951&r2=94952&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaInit.h (original)
+++ cfe/trunk/lib/Sema/SemaInit.h Sun Jan 31 03:12:51 2010
@@ -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 {

Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp?rev=94952&r1=94951&r2=94952&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp Sun Jan 31 03:12:51 2010
@@ -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

Added: cfe/trunk/test/CXX/dcl.decl/dcl.init/p6.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/dcl.decl/dcl.init/p6.cpp?rev=94952&view=auto

==============================================================================
--- cfe/trunk/test/CXX/dcl.decl/dcl.init/p6.cpp (added)
+++ cfe/trunk/test/CXX/dcl.decl/dcl.init/p6.cpp Sun Jan 31 03:12:51 2010
@@ -0,0 +1,15 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+// FIXME: Very incomplete!
+
+// 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.
+struct NoUserDefault { };
+struct HasUserDefault { HasUserDefault(); };
+
+void test_const_default_init() {
+  const NoUserDefault x1; // expected-error{{default initialization of an object of const type 'struct NoUserDefault const' requires a user-provided default constructor}}
+  const HasUserDefault x2;
+  const int x3; // FIXME: xpected-error{{default initialization of an object of const type 'struct NoUserDefault const' requires a user-provided default constructor}}
+}

Propchange: cfe/trunk/test/CXX/dcl.decl/dcl.init/p6.cpp

------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cfe/trunk/test/CXX/dcl.decl/dcl.init/p6.cpp

------------------------------------------------------------------------------
    svn:keywords = Id

Propchange: cfe/trunk/test/CXX/dcl.decl/dcl.init/p6.cpp

------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: cfe/trunk/test/SemaCXX/constructor-initializer.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/constructor-initializer.cpp?rev=94952&r1=94951&r2=94952&view=diff

==============================================================================
--- cfe/trunk/test/SemaCXX/constructor-initializer.cpp (original)
+++ cfe/trunk/test/SemaCXX/constructor-initializer.cpp Sun Jan 31 03:12:51 2010
@@ -104,8 +104,8 @@
 };
 
 struct N : M  {
-  N() : M(1),        // expected-error {{no matching constructor for initialization of 'M'}}
-        m1(100) {  } // expected-error {{no matching constructor for initialization of 'm1'}}
+  N() : M(1),        // expected-error {{no matching constructor for initialization of 'struct M'}}
+        m1(100) {  } // expected-error {{no matching constructor for initialization of 'struct M'}}
   M m1;
 };
 
@@ -116,8 +116,8 @@
 };
 
 struct Q {
-  Q() : f1(1,2),       // expected-error {{Too many arguments for member initializer 'f1'}}
-        pf(0.0)  { }   // expected-error {{incompatible type passing 'double', expected 'float *'}}
+  Q() : f1(1,2),       // expected-error {{excess elements in scalar initializer}}
+        pf(0.0)  { }   // expected-error {{cannot initialize a member subobject of type 'float *' with an rvalue of type 'double'}}
   float f1;
 
   float *pf;

Modified: cfe/trunk/test/SemaCXX/copy-assignment.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/copy-assignment.cpp?rev=94952&r1=94951&r2=94952&view=diff

==============================================================================
--- cfe/trunk/test/SemaCXX/copy-assignment.cpp (original)
+++ cfe/trunk/test/SemaCXX/copy-assignment.cpp Sun Jan 31 03:12:51 2010
@@ -47,22 +47,22 @@
 
 void test() {
   A a, na;
-  const A constA;
+  const A constA = A();
   ConvertibleToA convertibleToA;
   ConvertibleToConstA convertibleToConstA;
 
   B b, nb;
-  const B constB;
+  const B constB = B();
   ConvertibleToB convertibleToB;
   ConvertibleToBref convertibleToBref;
   ConvertibleToConstB convertibleToConstB;
   ConvertibleToConstBref convertibleToConstBref;
 
   C c, nc;
-  const C constC;
+  const C constC = C();
 
   D d, nd;
-  const D constD;
+  const D constD = D();
 
   ConvertibleToInt convertibleToInt;
 

Modified: cfe/trunk/test/SemaCXX/illegal-member-initialization.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/illegal-member-initialization.cpp?rev=94952&r1=94951&r2=94952&view=diff

==============================================================================
--- cfe/trunk/test/SemaCXX/illegal-member-initialization.cpp (original)
+++ cfe/trunk/test/SemaCXX/illegal-member-initialization.cpp Sun Jan 31 03:12:51 2010
@@ -1,9 +1,8 @@
 // RUN: %clang_cc1 -fsyntax-only -verify %s 
 
 struct A {
-   A() : value(), cvalue() { } // expected-error {{cannot initialize the member to null in default constructor because reference member 'value' cannot be null-initialized}} \
-                               // expected-error {{constructor for 'struct A' must explicitly initialize the reference member 'value'}}
-   int &value; // expected-note{{declared at}} {{expected-note{{declared at}}
+   A() : value(), cvalue() { } // expected-error {{reference to type 'int' requires an initializer}}
+   int &value;
    const int cvalue;
 };
 
@@ -18,7 +17,7 @@
    int &value; // expected-note{{declared at}}
    const int cvalue; // expected-note{{declared at}}
    B& b; // expected-note{{declared at}}
-   const B cb; // expected-note{{declared at}}
+   const B cb; // expected-note{{declared here}}
 };
 
 

Modified: cfe/trunk/test/SemaCXX/overload-member-call.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/overload-member-call.cpp?rev=94952&r1=94951&r2=94952&view=diff

==============================================================================
--- cfe/trunk/test/SemaCXX/overload-member-call.cpp (original)
+++ cfe/trunk/test/SemaCXX/overload-member-call.cpp Sun Jan 31 03:12:51 2010
@@ -89,7 +89,7 @@
     A a;
     a.foo(4, "hello"); //expected-error {{no matching member function for call to 'foo'}}
 
-    const A b;
+    const A b = A();
     b.bar(0); //expected-error {{no matching member function for call to 'bar'}}
 
     a.baz(b); //expected-error {{no matching member function for call to 'baz'}}

Modified: cfe/trunk/test/SemaCXX/overloaded-operator.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/overloaded-operator.cpp?rev=94952&r1=94951&r2=94952&view=diff

==============================================================================
--- cfe/trunk/test/SemaCXX/overloaded-operator.cpp (original)
+++ cfe/trunk/test/SemaCXX/overloaded-operator.cpp Sun Jan 31 03:12:51 2010
@@ -344,7 +344,7 @@
     int operator[](unsigned); // expected-note {{candidate}}
   };
   int test1() {
-    const NonConstArray x;
+    const NonConstArray x = NonConstArray();
     return x[0]; // expected-error {{no viable overloaded operator[] for type}}
   }
 

Modified: cfe/trunk/test/SemaTemplate/instantiate-member-initializers.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/instantiate-member-initializers.cpp?rev=94952&r1=94951&r2=94952&view=diff

==============================================================================
--- cfe/trunk/test/SemaTemplate/instantiate-member-initializers.cpp (original)
+++ cfe/trunk/test/SemaTemplate/instantiate-member-initializers.cpp Sun Jan 31 03:12:51 2010
@@ -1,7 +1,7 @@
 // RUN: %clang_cc1 -fsyntax-only -Wall -verify %s
 
 template<typename T> struct A {
-  A() : a(1) { } // expected-error{{incompatible type passing 'int', expected 'void *'}}
+  A() : a(1) { } // expected-error{{cannot initialize a member subobject of type 'void *' with an rvalue of type 'int'}}
 
   T a;
 };





More information about the cfe-commits mailing list