[cfe-commits] r72199 - in /cfe/trunk: lib/Sema/Sema.h lib/Sema/SemaExprCXX.cpp lib/Sema/SemaTemplateInstantiateExpr.cpp test/SemaTemplate/instantiate-expr-4.cpp

Douglas Gregor dgregor at apple.com
Wed May 20 17:00:41 PDT 2009


Author: dgregor
Date: Wed May 20 19:00:09 2009
New Revision: 72199

URL: http://llvm.org/viewvc/llvm-project?rev=72199&view=rev
Log:
Template instantiation for C++ "new" expressions.

Modified:
    cfe/trunk/lib/Sema/Sema.h
    cfe/trunk/lib/Sema/SemaExprCXX.cpp
    cfe/trunk/lib/Sema/SemaTemplateInstantiateExpr.cpp
    cfe/trunk/test/SemaTemplate/instantiate-expr-4.cpp

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

==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Wed May 20 19:00:09 2009
@@ -1556,7 +1556,21 @@
                                        SourceLocation ConstructorLParen,
                                        MultiExprArg ConstructorArgs,
                                        SourceLocation ConstructorRParen);
-  bool CheckAllocatedType(QualType AllocType, const Declarator &D);
+  OwningExprResult BuildCXXNew(SourceLocation StartLoc, bool UseGlobal,
+                               SourceLocation PlacementLParen,
+                               MultiExprArg PlacementArgs,
+                               SourceLocation PlacementRParen,
+                               bool ParenTypeId, 
+                               QualType AllocType,
+                               SourceLocation TypeLoc,
+                               SourceRange TypeRange,
+                               ExprArg ArraySize,
+                               SourceLocation ConstructorLParen,
+                               MultiExprArg ConstructorArgs,
+                               SourceLocation ConstructorRParen);
+  
+  bool CheckAllocatedType(QualType AllocType, SourceLocation Loc,
+                          SourceRange R);
   bool FindAllocationFunctions(SourceLocation StartLoc, SourceRange Range,
                                bool UseGlobal, QualType AllocType, bool IsArray,
                                Expr **PlaceArgs, unsigned NumPlaceArgs,

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaExprCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExprCXX.cpp Wed May 20 19:00:09 2009
@@ -283,18 +283,57 @@
   if (D.isInvalidType())
     return ExprError();
 
-  if (CheckAllocatedType(AllocType, D))
+  // Every dimension shall be of constant size.
+  unsigned i = 1;
+  QualType ElementType = AllocType;
+  while (const ArrayType *Array = Context.getAsArrayType(ElementType)) {
+    if (!Array->isConstantArrayType()) {
+      Diag(D.getTypeObject(i).Loc, diag::err_new_array_nonconst)
+        << static_cast<Expr*>(D.getTypeObject(i).Arr.NumElts)->getSourceRange();
+      return ExprError();
+    }
+    ElementType = Array->getElementType();
+    ++i;
+  }
+
+  return BuildCXXNew(StartLoc, UseGlobal, 
+                     PlacementLParen,
+                     move(PlacementArgs), 
+                     PlacementRParen,
+                     ParenTypeId,
+                     AllocType, 
+                     D.getSourceRange().getBegin(),
+                     D.getSourceRange(),
+                     Owned(ArraySize),
+                     ConstructorLParen,
+                     move(ConstructorArgs),
+                     ConstructorRParen);
+}
+
+Sema::OwningExprResult 
+Sema::BuildCXXNew(SourceLocation StartLoc, bool UseGlobal,
+                  SourceLocation PlacementLParen,
+                  MultiExprArg PlacementArgs,
+                  SourceLocation PlacementRParen,
+                  bool ParenTypeId, 
+                  QualType AllocType,
+                  SourceLocation TypeLoc,
+                  SourceRange TypeRange,
+                  ExprArg ArraySizeE,
+                  SourceLocation ConstructorLParen,
+                  MultiExprArg ConstructorArgs,
+                  SourceLocation ConstructorRParen) {
+  if (CheckAllocatedType(AllocType, TypeLoc, TypeRange))
     return ExprError();
 
-  QualType ResultType = AllocType->isDependentType()
-                          ? Context.DependentTy
-                          : Context.getPointerType(AllocType);
+  QualType ResultType = Context.getPointerType(AllocType);
 
   // That every array dimension except the first is constant was already
   // checked by the type check above.
 
   // C++ 5.3.4p6: "The expression in a direct-new-declarator shall have integral
   //   or enumeration type with a non-negative value."
+  Expr *ArraySize = (Expr *)ArraySizeE.get();
   if (ArraySize && !ArraySize->isTypeDependent()) {
     QualType SizeType = ArraySize->getType();
     if (!SizeType->isIntegralType() && !SizeType->isEnumeralType())
@@ -357,9 +396,8 @@
             !AllocType->isAggregateType()) {
     Constructor = PerformInitializationByConstructor(
                       AllocType, ConsArgs, NumConsArgs,
-                      D.getSourceRange().getBegin(),
-                      SourceRange(D.getSourceRange().getBegin(),
-                                  ConstructorRParen),
+                      TypeLoc,
+                      SourceRange(TypeLoc, ConstructorRParen),
                       RT->getDecl()->getDeclName(),
                       NumConsArgs != 0 ? IK_Direct : IK_Default);
     if (!Constructor)
@@ -369,7 +407,7 @@
       // FIXME: Check that no subpart is const.
       if (AllocType.isConstQualified())
         return ExprError(Diag(StartLoc, diag::err_new_uninitialized_const)
-          << D.getSourceRange());
+                           << TypeRange);
     } else if (NumConsArgs == 0) {
       // Object is value-initialized. Do nothing.
     } else if (NumConsArgs == 1) {
@@ -390,46 +428,36 @@
 
   PlacementArgs.release();
   ConstructorArgs.release();
+  ArraySizeE.release();
   return Owned(new (Context) CXXNewExpr(UseGlobal, OperatorNew, PlaceArgs,
                         NumPlaceArgs, ParenTypeId, ArraySize, Constructor, Init,
                         ConsArgs, NumConsArgs, OperatorDelete, ResultType,
-                        StartLoc, Init ? ConstructorRParen : SourceLocation()));
+                        StartLoc, Init ? ConstructorRParen : SourceLocation()));  
 }
 
 /// CheckAllocatedType - Checks that a type is suitable as the allocated type
 /// in a new-expression.
 /// dimension off and stores the size expression in ArraySize.
-bool Sema::CheckAllocatedType(QualType AllocType, const Declarator &D)
+bool Sema::CheckAllocatedType(QualType AllocType, SourceLocation Loc,
+                              SourceRange R)
 {
   // C++ 5.3.4p1: "[The] type shall be a complete object type, but not an
   //   abstract class type or array thereof.
   if (AllocType->isFunctionType())
-    return Diag(D.getSourceRange().getBegin(), diag::err_bad_new_type)
-      << AllocType << 0 << D.getSourceRange();
+    return Diag(Loc, diag::err_bad_new_type)
+      << AllocType << 0 << R;
   else if (AllocType->isReferenceType())
-    return Diag(D.getSourceRange().getBegin(), diag::err_bad_new_type)
-      << AllocType << 1 << D.getSourceRange();
+    return Diag(Loc, diag::err_bad_new_type)
+      << AllocType << 1 << R;
   else if (!AllocType->isDependentType() &&
-           RequireCompleteType(D.getSourceRange().getBegin(), AllocType,
+           RequireCompleteType(Loc, AllocType,
                                diag::err_new_incomplete_type,
-                               D.getSourceRange()))
+                               R))
     return true;
-  else if (RequireNonAbstractType(D.getSourceRange().getBegin(), AllocType,
+  else if (RequireNonAbstractType(Loc, AllocType,
                                   diag::err_allocation_of_abstract_type))
     return true;
 
-  // Every dimension shall be of constant size.
-  unsigned i = 1;
-  while (const ArrayType *Array = Context.getAsArrayType(AllocType)) {
-    if (!Array->isConstantArrayType()) {
-      Diag(D.getTypeObject(i).Loc, diag::err_new_array_nonconst)
-        << static_cast<Expr*>(D.getTypeObject(i).Arr.NumElts)->getSourceRange();
-      return true;
-    }
-    AllocType = Array->getElementType();
-    ++i;
-  }
-
   return false;
 }
 

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiateExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiateExpr.cpp Wed May 20 19:00:09 2009
@@ -88,7 +88,7 @@
     OwningExprResult VisitCXXConstructExpr(CXXConstructExpr *E);
     OwningExprResult VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr *E);
     OwningExprResult VisitCXXZeroInitValueExpr(CXXZeroInitValueExpr *E);
-    // FIXME: CXXNewExpr
+    OwningExprResult VisitCXXNewExpr(CXXNewExpr *E);
     // FIXME: CXXDeleteExpr
     // FIXME: UnaryTypeTraitExpr
     // FIXME: QualifiedDeclRefExpr
@@ -886,6 +886,61 @@
 }
 
 Sema::OwningExprResult 
+TemplateExprInstantiator::VisitCXXNewExpr(CXXNewExpr *E) {
+  // Instantiate the type that we're allocating
+  QualType AllocType = SemaRef.InstantiateType(E->getAllocatedType(),
+                                               TemplateArgs,
+                                   /*FIXME:*/E->getSourceRange().getBegin(),
+                                               DeclarationName());
+  if (AllocType.isNull())
+    return SemaRef.ExprError();
+
+  // Instantiate the size of the array we're allocating (if any).
+  OwningExprResult ArraySize = SemaRef.InstantiateExpr(E->getArraySize(),
+                                                       TemplateArgs);
+  if (ArraySize.isInvalid())
+    return SemaRef.ExprError();
+
+  // Instantiate the placement arguments (if any).
+  ASTOwningVector<&ActionBase::DeleteExpr> PlacementArgs(SemaRef);
+  for (unsigned I = 0, N = E->getNumPlacementArgs(); I != N; ++I) {
+    OwningExprResult Arg = Visit(E->getPlacementArg(I));
+    if (Arg.isInvalid())
+      return SemaRef.ExprError();
+
+    PlacementArgs.push_back(Arg.take());
+  }
+
+  // Instantiate the constructor arguments (if any).
+  ASTOwningVector<&ActionBase::DeleteExpr> ConstructorArgs(SemaRef);
+  for (unsigned I = 0, N = E->getNumConstructorArgs(); I != N; ++I) {
+    OwningExprResult Arg = Visit(E->getConstructorArg(I));
+    if (Arg.isInvalid())
+      return SemaRef.ExprError();
+
+    ConstructorArgs.push_back(Arg.take());
+  }
+
+  return SemaRef.BuildCXXNew(E->getSourceRange().getBegin(), 
+                             E->isGlobalNew(),
+                             /*FIXME*/SourceLocation(),
+                             Sema::MultiExprArg(SemaRef,
+                                                PlacementArgs.take(),
+                                                PlacementArgs.size()),
+                             /*FIXME*/SourceLocation(),
+                             E->isParenTypeId(),
+                             AllocType,
+                             /*FIXME*/E->getSourceRange().getBegin(),
+                             SourceRange(),
+                             move(ArraySize),
+                             /*FIXME*/SourceLocation(),
+                             Sema::MultiExprArg(SemaRef,
+                                                ConstructorArgs.take(),
+                                                ConstructorArgs.size()),
+                             E->getSourceRange().getEnd());
+}
+
+Sema::OwningExprResult 
 TemplateExprInstantiator::VisitCXXExprWithTemporaries(
                                                   CXXExprWithTemporaries *E) {
   OwningExprResult SubExpr = Visit(E->getSubExpr());

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=72199&r1=72198&r2=72199&view=diff

==============================================================================
--- cfe/trunk/test/SemaTemplate/instantiate-expr-4.cpp (original)
+++ cfe/trunk/test/SemaTemplate/instantiate-expr-4.cpp Wed May 20 19:00:09 2009
@@ -21,8 +21,8 @@
 
 template struct FunctionalCast0<5>;
 
-struct X {
-  X(int, int);
+struct X { // expected-note 2 {{candidate function}}
+  X(int, int); // expected-note 2 {{candidate function}}
 };
 
 template<int N, int M>
@@ -42,3 +42,44 @@
 };
 
 template struct Temporaries0<5, 7>;
+
+// ---------------------------------------------------------------------
+// new expressions
+// ---------------------------------------------------------------------
+struct Y { };
+
+template<typename T>
+struct New0 {
+  T* f(bool x) {
+    if (x)
+      return new T; // expected-error{{no matching}}
+    else
+      return new T();
+  }
+};
+
+template struct New0<int>;
+template struct New0<Y>;
+template struct New0<X>; // expected-note{{instantiation}}
+
+template<typename T, typename Arg1>
+struct New1 {
+  T* f(bool x, Arg1 a1) {
+    return new T(a1); // expected-error{{no matching}}
+  }
+};
+
+template struct New1<int, float>;
+template struct New1<Y, Y>;
+template struct New1<X, Y>; // expected-note{{instantiation}}
+
+template<typename T, typename Arg1, typename Arg2>
+struct New2 {
+  T* f(bool x, Arg1 a1, Arg2 a2) {
+    return new T(a1, a2); // expected-error{{no matching}}
+  }
+};
+
+template struct New2<X, int, float>;
+template struct New2<X, int, int*>; // expected-note{{instantiation}}
+// FIXME: template struct New2<int, int, float>;





More information about the cfe-commits mailing list