[cfe-commits] r91492 - in /cfe/trunk: 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

Douglas Gregor dgregor at apple.com
Tue Dec 15 17:38:02 PST 2009


Author: dgregor
Date: Tue Dec 15 19:38:02 2009
New Revision: 91492

URL: http://llvm.org/viewvc/llvm-project?rev=91492&view=rev
Log:
Switch the C++ new expression over to InitializationSequence, rather
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.


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

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

==============================================================================
--- cfe/trunk/include/clang/AST/ExprCXX.h (original)
+++ cfe/trunk/include/clang/AST/ExprCXX.h Tue Dec 15 19:38:02 2009
@@ -489,6 +489,7 @@
 class CXXConstructExpr : public Expr {
   CXXConstructorDecl *Constructor;
 
+  SourceLocation Loc;
   bool Elidable;
 
   Stmt **Args;
@@ -496,6 +497,7 @@
 
 protected:
   CXXConstructExpr(ASTContext &C, StmtClass SC, QualType T,
+                   SourceLocation Loc,
                    CXXConstructorDecl *d, bool elidable,
                    Expr **args, unsigned numargs);
   ~CXXConstructExpr() { }
@@ -508,6 +510,7 @@
   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 @@
   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 @@
   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) {

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

==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Tue Dec 15 19:38:02 2009
@@ -1818,8 +1818,8 @@
   "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">;

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

==============================================================================
--- cfe/trunk/lib/AST/ExprCXX.cpp (original)
+++ cfe/trunk/lib/AST/ExprCXX.cpp Tue Dec 15 19:38:02 2009
@@ -372,26 +372,28 @@
                                                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];
 

Modified: cfe/trunk/lib/Frontend/PCHReaderStmt.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/PCHReaderStmt.cpp?rev=91492&r1=91491&r2=91492&view=diff

==============================================================================
--- cfe/trunk/lib/Frontend/PCHReaderStmt.cpp (original)
+++ cfe/trunk/lib/Frontend/PCHReaderStmt.cpp Tue Dec 15 19:38:02 2009
@@ -858,6 +858,7 @@
 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]));

Modified: cfe/trunk/lib/Frontend/PCHWriterStmt.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/PCHWriterStmt.cpp?rev=91492&r1=91491&r2=91492&view=diff

==============================================================================
--- cfe/trunk/lib/Frontend/PCHWriterStmt.cpp (original)
+++ cfe/trunk/lib/Frontend/PCHWriterStmt.cpp Tue Dec 15 19:38:02 2009
@@ -785,6 +785,7 @@
 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)

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

==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Tue Dec 15 19:38:02 2009
@@ -3676,8 +3676,8 @@
   /// 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);
 

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Tue Dec 15 19:38:02 2009
@@ -3504,6 +3504,18 @@
   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 @@
     } 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 @@
           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 @@
     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.

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Tue Dec 15 19:38:02 2009
@@ -125,8 +125,10 @@
   //   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 @@
   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));
 }
 

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Tue Dec 15 19:38:02 2009
@@ -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 @@
 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 @@
                                        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 @@
       return ExprError();
   }
   InitExpr.release();
+  
+  // FIXME: Store the TInfo to preserve type information better.
   return Owned(new (Context) CompoundLiteralExpr(LParenLoc, literalType,
                                                  literalExpr, isFileScope));
 }

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaExprCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExprCXX.cpp Tue Dec 15 19:38:02 2009
@@ -425,74 +425,70 @@
   
   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();

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaInit.cpp (original)
+++ cfe/trunk/lib/Sema/SemaInit.cpp Tue Dec 15 19:38:02 2009
@@ -135,8 +135,12 @@
 }
 
 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 @@
   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 @@
       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 @@
   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 @@
 
   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 @@
   }
   
   //     - 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 @@
     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 @@
   //      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 @@
                                                  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 @@
       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 @@
       if (CurInit.isInvalid())
         return S.ExprError();
           
-      CurInit = S.MaybeBindToTemporary(CurInit.takeAs<Expr>());
       break;
     }
         
@@ -3228,12 +3316,16 @@
     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 @@
     }
     break;
   }
+      
+  case FK_DefaultInitOfConst:
+    S.Diag(Kind.getLocation(), diag::err_default_init_const)
+      << DestType;
+    break;
   }
   
   return true;

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaInit.h (original)
+++ cfe/trunk/lib/Sema/SemaInit.h Tue Dec 15 19:38:02 2009
@@ -137,8 +137,8 @@
   }
   
   /// \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 @@
   /// \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 @@
     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 @@
     /// \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:

Modified: cfe/trunk/test/SemaCXX/new-delete.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/new-delete.cpp?rev=91492&r1=91491&r2=91492&view=diff

==============================================================================
--- cfe/trunk/test/SemaCXX/new-delete.cpp (original)
+++ cfe/trunk/test/SemaCXX/new-delete.cpp Tue Dec 15 19:38:02 2009
@@ -59,12 +59,12 @@
   (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'}}

Modified: cfe/trunk/test/SemaTemplate/instantiate-expr-4.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/instantiate-expr-4.cpp?rev=91492&r1=91491&r2=91492&view=diff

==============================================================================
--- cfe/trunk/test/SemaTemplate/instantiate-expr-4.cpp (original)
+++ cfe/trunk/test/SemaTemplate/instantiate-expr-4.cpp Tue Dec 15 19:38:02 2009
@@ -21,8 +21,8 @@
 
 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>





More information about the cfe-commits mailing list