]> granicus.if.org Git - clang/commitdiff
Switch the C++ new expression over to InitializationSequence, rather
authorDouglas Gregor <dgregor@apple.com>
Wed, 16 Dec 2009 01:38:02 +0000 (01:38 +0000)
committerDouglas Gregor <dgregor@apple.com>
Wed, 16 Dec 2009 01:38:02 +0000 (01:38 +0000)
than using its own partial implementation of initialization.

Switched CheckInitializerTypes over to
InitializedEntity/InitializationKind, to help move us closer to
InitializationSequence.

Added InitializedEntity::getName() to retrieve the name of the entity,
for diagnostics that care about such things.

Implemented support for default initialization in
InitializationSequence.

Clean up the determination of the "source expressions" for an
initialization sequence in InitializationSequence::Perform.

Taught CXXConstructExpr to store more location information.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@91492 91177308-0d34-0410-b5e6-96231b3b80d8

14 files changed:
include/clang/AST/ExprCXX.h
include/clang/Basic/DiagnosticSemaKinds.td
lib/AST/ExprCXX.cpp
lib/Frontend/PCHReaderStmt.cpp
lib/Frontend/PCHWriterStmt.cpp
lib/Sema/Sema.h
lib/Sema/SemaDecl.cpp
lib/Sema/SemaDeclCXX.cpp
lib/Sema/SemaExpr.cpp
lib/Sema/SemaExprCXX.cpp
lib/Sema/SemaInit.cpp
lib/Sema/SemaInit.h
test/SemaCXX/new-delete.cpp
test/SemaTemplate/instantiate-expr-4.cpp

index 8f424474a4c7663f6901317a422d317c214595aa..02c7a017c00d11dd54315520a224275089517302 100644 (file)
@@ -489,6 +489,7 @@ public:
 class CXXConstructExpr : public Expr {
   CXXConstructorDecl *Constructor;
 
+  SourceLocation Loc;
   bool Elidable;
 
   Stmt **Args;
@@ -496,6 +497,7 @@ class CXXConstructExpr : public Expr {
 
 protected:
   CXXConstructExpr(ASTContext &C, StmtClass SC, QualType T,
+                   SourceLocation Loc,
                    CXXConstructorDecl *d, bool elidable,
                    Expr **args, unsigned numargs);
   ~CXXConstructExpr() { }
@@ -508,6 +510,7 @@ public:
   CXXConstructExpr(EmptyShell Empty, ASTContext &C, unsigned numargs);
   
   static CXXConstructExpr *Create(ASTContext &C, QualType T,
+                                  SourceLocation Loc,
                                   CXXConstructorDecl *D, bool Elidable,
                                   Expr **Args, unsigned NumArgs);
 
@@ -515,6 +518,9 @@ public:
   CXXConstructorDecl* getConstructor() const { return Constructor; }
   void setConstructor(CXXConstructorDecl *C) { Constructor = C; }
   
+  SourceLocation getLocation() const { return Loc; }
+  void setLocation(SourceLocation Loc) { this->Loc = Loc; }
+  
   /// \brief Whether this construction is elidable.
   bool isElidable() const { return Elidable; }
   void setElidable(bool E) { Elidable = E; }
@@ -549,9 +555,9 @@ public:
   virtual SourceRange getSourceRange() const { 
     // FIXME: Should we know where the parentheses are, if there are any?
     if (NumArgs == 0)
-      return SourceRange(); 
+      return SourceRange(Loc); 
     
-    return SourceRange(Args[0]->getLocStart(), Args[NumArgs - 1]->getLocEnd());
+    return SourceRange(Loc, Args[NumArgs - 1]->getLocEnd());
   }
 
   static bool classof(const Stmt *T) {
index f80cb6a1e465b0df94ab12f3718a0359cd63e381..ff23ec9b0e9cc3dffee57fa4947b7d4f7fa95925 100644 (file)
@@ -1818,8 +1818,8 @@ def err_new_paren_array_nonconst : Error<
   "when type is in parentheses, array cannot have dynamic size">;
 def err_array_size_not_integral : Error<
   "array size expression must have integral or enumerated type, not %0">;
-def err_new_uninitialized_const : Error<
-  "must provide an initializer if the allocated object is 'const'">;
+def err_default_init_const : Error<
+  "default initialization of an object of const type %0">;  
 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">;
index eecdba1ecaa4d7e729909545460b021fe7caf275..f173d795ce9a94ba06ce530a62a8e7609d914920 100644 (file)
@@ -372,26 +372,28 @@ CXXTemporaryObjectExpr::CXXTemporaryObjectExpr(ASTContext &C,
                                                Expr **Args,
                                                unsigned NumArgs,
                                                SourceLocation rParenLoc)
-  : CXXConstructExpr(C, CXXTemporaryObjectExprClass, writtenTy, Cons,
-                     false, Args, NumArgs),
+  : CXXConstructExpr(C, CXXTemporaryObjectExprClass, writtenTy, tyBeginLoc,
+                     Cons, false, Args, NumArgs),
   TyBeginLoc(tyBeginLoc), RParenLoc(rParenLoc) {
 }
 
 CXXConstructExpr *CXXConstructExpr::Create(ASTContext &C, QualType T,
+                                           SourceLocation Loc,
                                            CXXConstructorDecl *D, bool Elidable,
                                            Expr **Args, unsigned NumArgs) {
-  return new (C) CXXConstructExpr(C, CXXConstructExprClass, T, D, Elidable,
-                                  Args, NumArgs);
+  return new (C) CXXConstructExpr(C, CXXConstructExprClass, T, Loc, D, 
+                                  Elidable, Args, NumArgs);
 }
 
 CXXConstructExpr::CXXConstructExpr(ASTContext &C, StmtClass SC, QualType T,
+                                   SourceLocation Loc,
                                    CXXConstructorDecl *D, bool elidable,
                                    Expr **args, unsigned numargs)
 : Expr(SC, T,
        T->isDependentType(),
        (T->isDependentType() ||
         CallExpr::hasAnyValueDependentArguments(args, numargs))),
-  Constructor(D), Elidable(elidable), Args(0), NumArgs(numargs) {
+  Constructor(D), Loc(Loc), Elidable(elidable), Args(0), NumArgs(numargs) {
     if (NumArgs) {
       Args = new (C) Stmt*[NumArgs];
 
index f28e61e1ecdc80aaf017035af02925156b67399f..6c3cbca2159b3262850b82790cc755c1c14aa842 100644 (file)
@@ -858,6 +858,7 @@ unsigned PCHStmtReader::VisitCXXOperatorCallExpr(CXXOperatorCallExpr *E) {
 unsigned PCHStmtReader::VisitCXXConstructExpr(CXXConstructExpr *E) {
   VisitExpr(E);
   E->setConstructor(cast<CXXConstructorDecl>(Reader.GetDecl(Record[Idx++])));
+  E->setLocation(SourceLocation::getFromRawEncoding(Record[Idx++]));
   E->setElidable(Record[Idx++]);  
   for (unsigned I = 0, N = E->getNumArgs(); I != N; ++I)
     E->setArg(I, cast<Expr>(StmtStack[StmtStack.size() - N + I]));
index 22f7ad66d9d154b5dad423969223614fc41fdcdc..bf1d06f9ced8541b165bc6c466fa379a019f2080 100644 (file)
@@ -785,6 +785,7 @@ void PCHStmtWriter::VisitCXXOperatorCallExpr(CXXOperatorCallExpr *E) {
 void PCHStmtWriter::VisitCXXConstructExpr(CXXConstructExpr *E) {
   VisitExpr(E);
   Writer.AddDeclRef(E->getConstructor(), Record);
+  Writer.AddSourceLocation(E->getLocation(), Record);
   Record.push_back(E->isElidable());
   Record.push_back(E->getNumArgs());
   for (unsigned I = 0, N = E->getNumArgs(); I != N; ++I)
index 32a57269d6b596e3e3b5771d3da0e670c22d0a5a..0472d50ea5785d61816e5270e29ef0db22a49580 100644 (file)
@@ -3676,8 +3676,8 @@ public:
   /// type checking declaration initializers (C99 6.7.8)
 
   bool CheckInitializerTypes(Expr *&simpleInit_or_initList, QualType &declType,
-                             SourceLocation InitLoc,DeclarationName InitEntity,
-                             bool DirectInit);
+                             const InitializedEntity &Entity,
+                             const InitializationKind &Kind);
   bool CheckInitList(InitListExpr *&InitList, QualType &DeclType);
   bool CheckForConstantInitializer(Expr *e, QualType t);
 
index 6c5c2595aef5680645344687701f781daac56f18..7a27e1185e316357635f660a1587abd3ea2095b7 100644 (file)
@@ -3504,6 +3504,18 @@ void Sema::AddInitializerToDecl(DeclPtrTy dcl, ExprArg init, bool DirectInit) {
   Expr *Init = init.takeAs<Expr>();
   assert(Init && "missing initializer");
 
+  // Capture the variable that is being initialized and the style of
+  // initialization.
+  InitializedEntity Entity = InitializedEntity::InitializeVariable(VDecl);
+  
+  // FIXME: Poor source location information.
+  InitializationKind Kind
+    = DirectInit? InitializationKind::CreateDirect(VDecl->getLocation(),
+                                                   Init->getLocStart(),
+                                                   Init->getLocEnd())
+                : InitializationKind::CreateCopy(VDecl->getLocation(),
+                                                 Init->getLocStart());
+  
   // Get the decls type and save a reference for later, since
   // CheckInitializerTypes may change it.
   QualType DclT = VDecl->getType(), SavT = DclT;
@@ -3514,16 +3526,6 @@ void Sema::AddInitializerToDecl(DeclPtrTy dcl, ExprArg init, bool DirectInit) {
     } else if (!VDecl->isInvalidDecl()) {
       if (VDecl->getType()->isReferenceType()
           || isa<InitListExpr>(Init)) {
-        InitializedEntity Entity
-          = InitializedEntity::InitializeVariable(VDecl);
-
-        // FIXME: Poor source location information.
-        InitializationKind Kind
-          = DirectInit? InitializationKind::CreateDirect(VDecl->getLocation(),
-                                                         SourceLocation(),
-                                                         SourceLocation())
-                      : InitializationKind::CreateCopy(VDecl->getLocation(),
-                                                       SourceLocation());
         InitializationSequence InitSeq(*this, Entity, Kind, &Init, 1);
         if (InitSeq) {
           OwningExprResult Result = InitSeq.Perform(*this, Entity, Kind,
@@ -3540,8 +3542,7 @@ void Sema::AddInitializerToDecl(DeclPtrTy dcl, ExprArg init, bool DirectInit) {
           VDecl->setInvalidDecl();
           return;
         }    
-      } else if (CheckInitializerTypes(Init, DclT, VDecl->getLocation(),
-                                       VDecl->getDeclName(), DirectInit))
+      } else if (CheckInitializerTypes(Init, DclT, Entity, Kind))
         VDecl->setInvalidDecl();
 
       // C++ 3.6.2p2, allow dynamic initialization of static initializers.
@@ -3602,8 +3603,7 @@ void Sema::AddInitializerToDecl(DeclPtrTy dcl, ExprArg init, bool DirectInit) {
     if (VDecl->getStorageClass() == VarDecl::Extern)
       Diag(VDecl->getLocation(), diag::warn_extern_init);
     if (!VDecl->isInvalidDecl())
-      if (CheckInitializerTypes(Init, DclT, VDecl->getLocation(),
-                                VDecl->getDeclName(), DirectInit))
+      if (CheckInitializerTypes(Init, DclT, Entity, Kind))
         VDecl->setInvalidDecl();
 
     // C++ 3.6.2p2, allow dynamic initialization of static initializers.
index 80d67efae9b1b3e066a6a6f781673f451380a642..a70841f536dcb33ffdebc1667299792c8eb65f05 100644 (file)
@@ -125,8 +125,10 @@ Sema::SetParamDefaultArgument(ParmVarDecl *Param, ExprArg DefaultArg,
   //   the same semantic constraints as the initializer expression in
   //   a declaration of a variable of the parameter type, using the
   //   copy-initialization semantics (8.5).
-  if (CheckInitializerTypes(Arg, ParamType, EqualLoc,
-                            Param->getDeclName(), /*DirectInit=*/false))
+  InitializedEntity Entity = InitializedEntity::InitializeParameter(Param);
+  InitializationKind Kind = InitializationKind::CreateCopy(Param->getLocation(),
+                                                           EqualLoc);
+  if (CheckInitializerTypes(Arg, ParamType, Entity, Kind))
     return true;
 
   Arg = MaybeCreateCXXExprWithTemporaries(Arg);
@@ -3775,7 +3777,8 @@ Sema::BuildCXXConstructExpr(SourceLocation ConstructLoc, QualType DeclInitType,
   Expr **Exprs = (Expr **)ExprArgs.release();
 
   MarkDeclarationReferenced(ConstructLoc, Constructor);
-  return Owned(CXXConstructExpr::Create(Context, DeclInitType, Constructor,
+  return Owned(CXXConstructExpr::Create(Context, DeclInitType, ConstructLoc,
+                                        Constructor,
                                         Elidable, Exprs, NumExprs));
 }
 
index 12c3a3a2b00744f8c064c6c773cd445979c50a31..70646dd9ed4b03b7e2ef294a7ecae805fe39b3b8 100644 (file)
@@ -12,6 +12,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "Sema.h"
+#include "SemaInit.h"
 #include "Lookup.h"
 #include "clang/AST/ASTContext.h"
 #include "clang/AST/DeclObjC.h"
@@ -3531,8 +3532,12 @@ Action::OwningExprResult
 Sema::ActOnCompoundLiteral(SourceLocation LParenLoc, TypeTy *Ty,
                            SourceLocation RParenLoc, ExprArg InitExpr) {
   assert((Ty != 0) && "ActOnCompoundLiteral(): missing type");
-  //FIXME: Preserve type source info.
-  QualType literalType = GetTypeFromParser(Ty);
+  
+  TypeSourceInfo *TInfo = 0;
+  QualType literalType = GetTypeFromParser(Ty, &TInfo);  
+  if (!TInfo)
+    TInfo = Context.getTrivialTypeSourceInfo(literalType, LParenLoc);
+  
   // FIXME: put back this assert when initializers are worked out.
   //assert((InitExpr != 0) && "ActOnCompoundLiteral(): missing expression");
   Expr *literalExpr = static_cast<Expr*>(InitExpr.get());
@@ -3548,8 +3553,12 @@ Sema::ActOnCompoundLiteral(SourceLocation LParenLoc, TypeTy *Ty,
                                        literalExpr->getSourceRange().getEnd())))
     return ExprError();
 
-  if (CheckInitializerTypes(literalExpr, literalType, LParenLoc,
-                            DeclarationName(), /*FIXME:DirectInit=*/false))
+  InitializedEntity Entity
+    = InitializedEntity::InitializeTemporary(TInfo->getTypeLoc());
+  InitializationKind Kind
+    = InitializationKind::CreateCast(SourceRange(LParenLoc, RParenLoc), 
+                                     /*IsCStyleCast=*/true);
+  if (CheckInitializerTypes(literalExpr, literalType, Entity, Kind))
     return ExprError();
 
   bool isFileScope = getCurFunctionOrMethodDecl() == 0;
@@ -3558,6 +3567,8 @@ Sema::ActOnCompoundLiteral(SourceLocation LParenLoc, TypeTy *Ty,
       return ExprError();
   }
   InitExpr.release();
+  
+  // FIXME: Store the TInfo to preserve type information better.
   return Owned(new (Context) CompoundLiteralExpr(LParenLoc, literalType,
                                                  literalExpr, isFileScope));
 }
index d119350a6f5389b1089fd9a7f42fc506168c8b1c..80b64306540fc2412d42b3cddac3275072aee468 100644 (file)
@@ -425,74 +425,70 @@ Sema::BuildCXXNew(SourceLocation StartLoc, bool UseGlobal,
   
   bool Init = ConstructorLParen.isValid();
   // --- Choosing a constructor ---
-  // C++ 5.3.4p15
-  // 1) If T is a POD and there's no initializer (ConstructorLParen is invalid)
-  //   the object is not initialized. If the object, or any part of it, is
-  //   const-qualified, it's an error.
-  // 2) If T is a POD and there's an empty initializer, the object is value-
-  //   initialized.
-  // 3) If T is a POD and there's one initializer argument, the object is copy-
-  //   constructed.
-  // 4) If T is a POD and there's more initializer arguments, it's an error.
-  // 5) If T is not a POD, the initializer arguments are used as constructor
-  //   arguments.
-  //
-  // Or by the C++0x formulation:
-  // 1) If there's no initializer, the object is default-initialized according
-  //    to C++0x rules.
-  // 2) Otherwise, the object is direct-initialized.
   CXXConstructorDecl *Constructor = 0;
   Expr **ConsArgs = (Expr**)ConstructorArgs.get();
-  const RecordType *RT;
   unsigned NumConsArgs = ConstructorArgs.size();
   ASTOwningVector<&ActionBase::DeleteExpr> ConvertedConstructorArgs(*this);
 
-  if (AllocType->isDependentType() || 
-      Expr::hasAnyTypeDependentArguments(ConsArgs, NumConsArgs)) {
-    // Skip all the checks.
-  } else if ((RT = AllocType->getAs<RecordType>()) &&
-             !AllocType->isAggregateType()) {
-    InitializationKind InitKind = InitializationKind::CreateDefault(TypeLoc);
-    if (NumConsArgs > 0)
-      InitKind = InitializationKind::CreateDirect(TypeLoc,
-                                                  PlacementLParen, 
-                                                  PlacementRParen);
-    Constructor = PerformInitializationByConstructor(
-                      AllocType, move(ConstructorArgs),
-                      TypeLoc,
-                      SourceRange(TypeLoc, ConstructorRParen),
-                      RT->getDecl()->getDeclName(),
-                      InitKind,
-                      ConvertedConstructorArgs);
-    if (!Constructor)
+  if (!AllocType->isDependentType() &&
+      !Expr::hasAnyTypeDependentArguments(ConsArgs, NumConsArgs)) {
+    // C++0x [expr.new]p15:
+    //   A new-expression that creates an object of type T initializes that
+    //   object as follows:
+    InitializationKind Kind
+    //     - If the new-initializer is omitted, the object is default-
+    //       initialized (8.5); if no initialization is performed,
+    //       the object has indeterminate value
+      = !Init? InitializationKind::CreateDefault(TypeLoc)
+    //     - Otherwise, the new-initializer is interpreted according to the 
+    //       initialization rules of 8.5 for direct-initialization.
+             : InitializationKind::CreateDirect(TypeLoc,
+                                                ConstructorLParen, 
+                                                ConstructorRParen);
+    
+    // FIXME: We shouldn't have to fake this.
+    TypeSourceInfo *TInfo
+      = Context.getTrivialTypeSourceInfo(AllocType, TypeLoc);
+    InitializedEntity Entity
+      = InitializedEntity::InitializeTemporary(TInfo->getTypeLoc());
+    InitializationSequence InitSeq(*this, Entity, Kind, ConsArgs, NumConsArgs);
+    
+    if (!InitSeq) {
+      InitSeq.Diagnose(*this, Entity, Kind, ConsArgs, NumConsArgs);
       return ExprError();
+    }
 
-    // Take the converted constructor arguments and use them for the new 
-    // expression.
-    NumConsArgs = ConvertedConstructorArgs.size();
-    ConsArgs = (Expr **)ConvertedConstructorArgs.take();
-  } else {
-    if (!Init) {
-      // FIXME: Check that no subpart is const.
-      if (AllocType.isConstQualified())
-        return ExprError(Diag(StartLoc, diag::err_new_uninitialized_const)
-                           << TypeRange);
-    } else if (NumConsArgs == 0) {
-      // Object is value-initialized. Do nothing.
-    } else if (NumConsArgs == 1) {
-      // Object is direct-initialized.
-      // FIXME: What DeclarationName do we pass in here?
-      if (CheckInitializerTypes(ConsArgs[0], AllocType, StartLoc,
-                                DeclarationName() /*AllocType.getAsString()*/,
-                                /*DirectInit=*/true))
-        return ExprError();
+    OwningExprResult FullInit = InitSeq.Perform(*this, Entity, Kind, 
+                                                move(ConstructorArgs));
+    if (FullInit.isInvalid())
+      return ExprError();
+    
+    // FullInit is our initializer; walk through it to determine if it's a 
+    // constructor call, which CXXNewExpr handles directly.
+    if (Expr *FullInitExpr = (Expr *)FullInit.get()) {
+      if (CXXBindTemporaryExpr *Binder
+            = dyn_cast<CXXBindTemporaryExpr>(FullInitExpr))
+        FullInitExpr = Binder->getSubExpr();
+      if (CXXConstructExpr *Construct
+                    = dyn_cast<CXXConstructExpr>(FullInitExpr)) {
+        Constructor = Construct->getConstructor();
+        for (CXXConstructExpr::arg_iterator A = Construct->arg_begin(),
+                                         AEnd = Construct->arg_end();
+             A != AEnd; ++A)
+          ConvertedConstructorArgs.push_back(A->Retain());
+      } else {
+        // Take the converted initializer.
+        ConvertedConstructorArgs.push_back(FullInit.release());
+      }
     } else {
-      return ExprError(Diag(StartLoc,
-                            diag::err_builtin_direct_init_more_than_one_arg)
-        << SourceRange(ConstructorLParen, ConstructorRParen));
+      // No initialization required.
     }
+    
+    // Take the converted arguments and use them for the new expression.
+    NumConsArgs = ConvertedConstructorArgs.size();
+    ConsArgs = (Expr **)ConvertedConstructorArgs.take();
   }
-
+  
   // FIXME: Also check that the destructor is accessible. (C++ 5.3.4p16)
   
   PlacementArgs.release();
index 45184650eb7efc8a1cc0d1241deb51a6d65d91e2..a732b07b9dde023fa387f2b493b9a32c99e0ea34 100644 (file)
@@ -135,8 +135,12 @@ static void CheckStringInit(Expr *Str, QualType &DeclT, Sema &S) {
 }
 
 bool Sema::CheckInitializerTypes(Expr *&Init, QualType &DeclType,
-                                 SourceLocation InitLoc,
-                                 DeclarationName InitEntity, bool DirectInit) {
+                                 const InitializedEntity &Entity,
+                                 const InitializationKind &Kind) {
+  SourceLocation InitLoc = Kind.getLocation();
+  DeclarationName InitEntity = Entity.getName();
+  bool DirectInit = (Kind.getKind() == InitializationKind::IK_Direct);
+  
   if (DeclType->isDependentType() ||
       Init->isTypeDependent() || Init->isValueDependent()) {
     // We have either a dependent type or a type- or value-dependent
@@ -1954,6 +1958,24 @@ InitializedEntity InitializedEntity::InitializeBase(ASTContext &Context,
   return Result;
 }
 
+DeclarationName InitializedEntity::getName() const {
+  switch (getKind()) {
+  case EK_Variable:
+  case EK_Parameter:
+  case EK_Member:
+    return VariableOrMember->getDeclName();
+
+  case EK_Result:
+  case EK_Exception:
+  case EK_Temporary:
+  case EK_Base:
+    return DeclarationName();
+  }
+  
+  // Silence GCC warning
+  return DeclarationName();
+}
+
 //===----------------------------------------------------------------------===//
 // Initialization sequence
 //===----------------------------------------------------------------------===//
@@ -2512,7 +2534,7 @@ static void TryConstructorInitialization(Sema &S,
       Constructor = cast<CXXConstructorDecl>(*Con);
     
     if (!Constructor->isInvalidDecl() &&
-        Constructor->isConvertingConstructor(AllowExplicit)) {
+        (AllowExplicit || !Constructor->isExplicit())) {
       if (ConstructorTmpl)
         S.AddTemplateOverloadCandidate(ConstructorTmpl, /*ExplicitArgs*/ 0,
                                        Args, NumArgs, CandidateSet);
@@ -2575,6 +2597,41 @@ static void TryValueInitialization(Sema &S,
   Sequence.setSequenceKind(InitializationSequence::ZeroInitialization);
 }
 
+/// \brief Attempt default initialization (C++ [dcl.init]p6).
+static void TryDefaultInitialization(Sema &S,
+                                     const InitializedEntity &Entity,
+                                     const InitializationKind &Kind,
+                                     InitializationSequence &Sequence) {
+  assert(Kind.getKind() == InitializationKind::IK_Default);
+  
+  // C++ [dcl.init]p6:
+  //   To default-initialize an object of type T means:
+  //     - if T is an array type, each element is default-initialized;
+  QualType DestType = Entity.getType().getType();
+  while (const ArrayType *Array = S.Context.getAsArrayType(DestType))
+    DestType = Array->getElementType();
+         
+  //     - if T is a (possibly cv-qualified) class type (Clause 9), the default
+  //       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);
+  }
+  
+  //     - otherwise, no initialization is performed.
+  Sequence.setSequenceKind(InitializationSequence::NoInitialization);
+  
+  //   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 (DestType.isConstQualified())
+    Sequence.SetFailed(InitializationSequence::FK_DefaultInitOfConst);
+}
+
 /// \brief Attempt a user-defined conversion between two types (C++ [dcl.init]),
 /// which enumerates all conversion functions and performs overload resolution
 /// to select the best.
@@ -2749,7 +2806,7 @@ InitializationSequence::InitializationSequence(Sema &S,
 
   QualType SourceType;
   Expr *Initializer = 0;
-  if (Kind.getKind() == InitializationKind::IK_Copy) {
+  if (NumArgs == 1) {
     Initializer = Args[0];
     if (!isa<InitListExpr>(Initializer))
       SourceType = Initializer->getType();
@@ -2785,11 +2842,18 @@ InitializationSequence::InitializationSequence(Sema &S,
   }
   
   //     - If the initializer is (), the object is value-initialized.
-  if (Kind.getKind() == InitializationKind::IK_Value) {
+  if (Kind.getKind() == InitializationKind::IK_Value ||
+      (Kind.getKind() == InitializationKind::IK_Direct && NumArgs == 0)) {
     TryValueInitialization(S, Entity, Kind, *this);
     return;
   }
   
+  // Handle default initialization.
+  if (Kind.getKind() == InitializationKind::IK_Default){
+    TryDefaultInitialization(S, Entity, Kind, *this);
+    return;
+  }
+  
   //     - Otherwise, if the destination type is an array, the program is 
   //       ill-formed.
   if (const ArrayType *AT = Context.getAsArrayType(DestType)) {
@@ -2824,9 +2888,15 @@ InitializationSequence::InitializationSequence(Sema &S,
     return;
   }
   
+  if (NumArgs > 1) {
+    SetFailed(FK_TooManyInitsForScalar);
+    return;
+  }
+  assert(NumArgs == 1 && "Zero-argument case handled above");
+  
   //    - Otherwise, if the source type is a (possibly cv-qualified) class 
   //      type, conversion functions are considered.
-  if (SourceType->isRecordType()) {
+  if (!SourceType.isNull() && SourceType->isRecordType()) {
     TryUserDefinedConversion(S, Entity, Kind, Initializer, *this);
     return;
   }
@@ -2836,6 +2906,7 @@ InitializationSequence::InitializationSequence(Sema &S,
   //      conversions (Clause 4) will be used, if necessary, to convert the
   //      initializer expression to the cv-unqualified version of the 
   //      destination type; no user-defined conversions are considered.
+  setSequenceKind(StandardConversion);
   TryImplicitConversion(S, Entity, Kind, Initializer, *this);
 }
 
@@ -2909,23 +2980,41 @@ InitializationSequence::Perform(Sema &S,
                                                  SourceLocation()));
   }
 
+  if (SequenceKind == NoInitialization)
+    return S.Owned((Expr *)0);
+  
   QualType DestType = Entity.getType().getType().getNonReferenceType();
   if (ResultType)
     *ResultType = Entity.getType().getType();
 
-  Sema::OwningExprResult CurInit(S);
-  // For copy initialization and any other initialization forms that
-  // only have a single initializer, we start with the (only)
-  // initializer we have.
-  // FIXME: DPG is not happy about this. There's confusion regarding whether
-  // we're supposed to start the conversion from the solitary initializer or
-  // from the set of arguments.
-  if (Kind.getKind() == InitializationKind::IK_Copy ||
-      SequenceKind != ConstructorInitialization) {
-    assert(Args.size() == 1);
-    CurInit = Sema::OwningExprResult(S, Args.release()[0]);
-    if (CurInit.isInvalid())
-      return S.ExprError();
+  Sema::OwningExprResult CurInit = S.Owned((Expr *)0);
+  
+  assert(!Steps.empty() && "Cannot have an empty initialization sequence");
+  
+  // For initialization steps that start with a single initializer, 
+  // grab the only argument out the Args and place it into the "current"
+  // initializer.
+  switch (Steps.front().Kind) {
+    case SK_ResolveAddressOfOverloadedFunction:
+    case SK_CastDerivedToBaseRValue:
+    case SK_CastDerivedToBaseLValue:
+    case SK_BindReference:
+    case SK_BindReferenceToTemporary:
+    case SK_UserConversion:
+    case SK_QualificationConversionLValue:
+    case SK_QualificationConversionRValue:
+    case SK_ConversionSequence:
+    case SK_ListInitialization:
+      assert(Args.size() == 1);
+      CurInit = Sema::OwningExprResult(S, 
+                                       ((Expr **)(Args.get()))[0]->Retain());
+      if (CurInit.isInvalid())
+        return S.ExprError();
+      break;
+      
+    case SK_ConstructorInitialization:
+    case SK_ZeroInitialization:
+      break;
   }
     
   // Walk through the computed steps for the initialization sequence, 
@@ -2936,7 +3025,7 @@ InitializationSequence::Perform(Sema &S,
       return S.ExprError();
     
     Expr *CurInitExpr = (Expr *)CurInit.get();
-    QualType SourceType = CurInitExpr->getType();
+    QualType SourceType = CurInitExpr? CurInitExpr->getType() : QualType();
     
     switch (Step->Kind) {
     case SK_ResolveAddressOfOverloadedFunction:
@@ -3100,7 +3189,6 @@ InitializationSequence::Perform(Sema &S,
       if (CurInit.isInvalid())
         return S.ExprError();
           
-      CurInit = S.MaybeBindToTemporary(CurInit.takeAs<Expr>());
       break;
     }
         
@@ -3228,12 +3316,16 @@ bool InitializationSequence::Diagnose(Sema &S,
     break;
 
   case FK_TooManyInitsForScalar: {
-    InitListExpr *InitList = cast<InitListExpr>(Args[0]);
+    SourceRange R;
+
+    if (InitListExpr *InitList = dyn_cast<InitListExpr>(Args[0]))
+      R = SourceRange(InitList->getInit(1)->getLocStart(),
+                      InitList->getLocEnd());
+    else
+      R = SourceRange(Args[0]->getLocStart(), Args[NumArgs - 1]->getLocEnd());
 
     S.Diag(Kind.getLocation(), diag::err_excess_initializers)
-      << /*scalar=*/2 
-      << SourceRange(InitList->getInit(1)->getLocStart(),
-                     InitList->getLocEnd());
+      << /*scalar=*/2 << R;
     break;
   }
 
@@ -3290,6 +3382,11 @@ bool InitializationSequence::Diagnose(Sema &S,
     }
     break;
   }
+      
+  case FK_DefaultInitOfConst:
+    S.Diag(Kind.getLocation(), diag::err_default_init_const)
+      << DestType;
+    break;
   }
   
   return true;
index 2d4b01f26b0de8e6adcdbd5f422e8586b6d6c5c4..c084025b817b6ef5616e36ba8d9bf40172434e61 100644 (file)
@@ -137,8 +137,8 @@ public:
   }
   
   /// \brief Create the initialization entity for a temporary.
-  static InitializedEntity InitializeTemporary(EntityKind Kind, TypeLoc TL) {
-    return InitializedEntity(Kind, SourceLocation(), TL);
+  static InitializedEntity InitializeTemporary(TypeLoc TL) {
+    return InitializedEntity(EK_Temporary, SourceLocation(), TL);
   }
   
   /// \brief Create the initialization entity for a base class subobject.
@@ -156,6 +156,9 @@ public:
   /// \brief Retrieve type being initialized.
   TypeLoc getType() const { return TL; }
   
+  /// \brief Retrieve the name of the entity being initialized.
+  DeclarationName getName() const;
+  
   /// \brief Determine the location of the 'return' keyword when initializing
   /// the result of a function call.
   SourceLocation getReturnLoc() const {
@@ -319,7 +322,13 @@ public:
     ListInitialization,
     
     /// \brief Zero-initialization.
-    ZeroInitialization
+    ZeroInitialization,
+    
+    /// \brief No initialization required.
+    NoInitialization,
+    
+    /// \brief Standard conversion sequence.
+    StandardConversion
   };
   
   /// \brief Describes the kind of a particular step in an initialization
@@ -420,7 +429,9 @@ public:
     /// \brief Overloading for a user-defined conversion failed.
     FK_UserConversionOverloadFailed,
     /// \brief Overloaded for initialization by constructor failed.
-    FK_ConstructorOverloadFailed
+    FK_ConstructorOverloadFailed,
+    /// \brief Default-initialization of a 'const' object.
+    FK_DefaultInitOfConst
   };
   
 private:
index fcc939d4e843fa114d30269a1f1592321aaa1b35..91f800daea5274ee2982c3011783c656109a4c98 100644 (file)
@@ -59,12 +59,12 @@ void bad_news(int *ip)
   (void)new int[1][i]; // expected-error {{only the first dimension}}
   (void)new (int[1][i]); // expected-error {{only the first dimension}}
   (void)new (int[i]); // expected-error {{when type is in parentheses}}
-  (void)new int(*(S*)0); // expected-error {{incompatible type initializing}}
-  (void)new int(1, 2); // expected-error {{initializer of a builtin type can only take one argument}}
+  (void)new int(*(S*)0); // expected-error {{no viable conversion from 'struct S' to 'int'}}
+  (void)new int(1, 2); // expected-error {{excess elements in scalar initializer}}
   (void)new S(1); // expected-error {{no matching constructor}}
-  (void)new S(1, 1); // expected-error {{call to constructor of 'S' is ambiguous}}
-  (void)new const int; // expected-error {{must provide an initializer}}
-  (void)new float*(ip); // expected-error {{incompatible type initializing 'int *', expected 'float *'}}
+  (void)new S(1, 1); // expected-error {{call to constructor of 'struct S' is ambiguous}}
+  (void)new const int; // expected-error {{default initialization of an object of const type 'int const'}}
+  (void)new float*(ip); // expected-error {{cannot initialize a value of type 'float *' with an lvalue of type 'int *'}}
   // Undefined, but clang should reject it directly.
   (void)new int[-1]; // expected-error {{array size is negative}}
   (void)new int[*(S*)0]; // expected-error {{array size expression must have integral or enumerated type, not 'struct S'}}
index e3da45e65841034242d8984a482895835361a23f..ffe1d58f28cb0d0d991f71d472d37d5b7f9714a0 100644 (file)
@@ -21,8 +21,8 @@ struct FunctionalCast0 {
 
 template struct FunctionalCast0<5>;
 
-struct X { // expected-note 2 {{candidate function}}
-  X(int, int); // expected-note 2 {{candidate function}}
+struct X { // expected-note 3 {{candidate function}}
+  X(int, int); // expected-note 3 {{candidate function}}
 };
 
 template<int N, int M>