[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