From d94546a0a1deef7286c13e49b9584621ae81cc9a Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Wed, 20 May 2009 21:38:11 +0000 Subject: [PATCH] Template instantiation for the various kinds of AST nodes that occur due to C++ type construction of the form T(a1, a2, ..., aN). git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@72183 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/AST/ExprCXX.h | 11 ++- lib/AST/ExprCXX.cpp | 4 ++ lib/Sema/SemaTemplateInstantiateExpr.cpp | 87 +++++++++++++++++++++++- test/SemaTemplate/instantiate-expr-4.cpp | 35 ++++++++++ 4 files changed, 131 insertions(+), 6 deletions(-) create mode 100644 test/SemaTemplate/instantiate-expr-4.cpp diff --git a/include/clang/AST/ExprCXX.h b/include/clang/AST/ExprCXX.h index f3c8244160..df01e9bef4 100644 --- a/include/clang/AST/ExprCXX.h +++ b/include/clang/AST/ExprCXX.h @@ -431,8 +431,11 @@ public: void Destroy(ASTContext &C); - const VarDecl* getVarDecl() const { return VD; } - const CXXConstructorDecl* getConstructor() const { return Constructor; } + VarDecl* getVarDecl() const { return VD; } + CXXConstructorDecl* getConstructor() const { return Constructor; } + + /// \brief Whether this construction is elidable. + bool isElidable() const { return Elidable; } typedef ExprIterator arg_iterator; typedef ConstExprIterator const_arg_iterator; @@ -537,7 +540,7 @@ class CXXZeroInitValueExpr : public Expr { public: CXXZeroInitValueExpr(QualType ty, SourceLocation tyBeginLoc, SourceLocation rParenLoc ) : - Expr(CXXZeroInitValueExprClass, ty), + Expr(CXXZeroInitValueExprClass, ty, false, false), TyBeginLoc(tyBeginLoc), RParenLoc(rParenLoc) {} SourceLocation getTypeBeginLoc() const { return TyBeginLoc; } @@ -553,6 +556,8 @@ public: return SourceRange(TyBeginLoc, RParenLoc); } + CXXZeroInitValueExpr* Clone(ASTContext &C) const; + static bool classof(const Stmt *T) { return T->getStmtClass() == CXXZeroInitValueExprClass; } diff --git a/lib/AST/ExprCXX.cpp b/lib/AST/ExprCXX.cpp index a73843ca36..cca391e193 100644 --- a/lib/AST/ExprCXX.cpp +++ b/lib/AST/ExprCXX.cpp @@ -365,3 +365,7 @@ CXXBoolLiteralExpr* CXXBoolLiteralExpr::Clone(ASTContext &C) const { CXXNullPtrLiteralExpr* CXXNullPtrLiteralExpr::Clone(ASTContext &C) const { return new (C) CXXNullPtrLiteralExpr(getType(), Loc); } + +CXXZeroInitValueExpr* CXXZeroInitValueExpr::Clone(ASTContext &C) const { + return new (C) CXXZeroInitValueExpr(getType(), TyBeginLoc, RParenLoc); +} diff --git a/lib/Sema/SemaTemplateInstantiateExpr.cpp b/lib/Sema/SemaTemplateInstantiateExpr.cpp index 1dad862063..1b2fa46957 100644 --- a/lib/Sema/SemaTemplateInstantiateExpr.cpp +++ b/lib/Sema/SemaTemplateInstantiateExpr.cpp @@ -85,9 +85,9 @@ namespace { // FIXME: CXXTypeIdExpr // FIXME: CXXThrowExpr // FIXME: CXXDefaultArgExpr - // FIXME: CXXConstructExpr - // FIXME: CXXFunctionalCastExpr - // FIXME: CXXZeroInitValueExpr + OwningExprResult VisitCXXConstructExpr(CXXConstructExpr *E); + OwningExprResult VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr *E); + OwningExprResult VisitCXXZeroInitValueExpr(CXXZeroInitValueExpr *E); // FIXME: CXXNewExpr // FIXME: CXXDeleteExpr // FIXME: UnaryTypeTraitExpr @@ -835,6 +835,87 @@ TemplateExprInstantiator::VisitCXXThisExpr(CXXThisExpr *E) { return SemaRef.Owned(TE); } +Sema::OwningExprResult +TemplateExprInstantiator::VisitCXXConstructExpr(CXXConstructExpr *E) { + assert(!cast(E->getConstructor()->getDeclContext()) + ->isDependentType() && "Dependent constructor shouldn't be here"); + + QualType T = SemaRef.InstantiateType(E->getType(), TemplateArgs, + /*FIXME*/E->getSourceRange().getBegin(), + DeclarationName()); + if (T.isNull()) + return SemaRef.ExprError(); + + bool Invalid = false; + llvm::SmallVector Args; + for (CXXConstructExpr::arg_iterator Arg = E->arg_begin(), + ArgEnd = E->arg_end(); + Arg != ArgEnd; ++Arg) { + OwningExprResult ArgInst = Visit(*Arg); + if (ArgInst.isInvalid()) { + Invalid = true; + break; + } + + Args.push_back(ArgInst.takeAs()); + } + + + VarDecl *Var = 0; + if (!Invalid) { + Var = cast_or_null(SemaRef.InstantiateDecl(E->getVarDecl(), + SemaRef.CurContext, + TemplateArgs)); + if (!Var) + Invalid = true; + } + + if (Invalid) { + for (unsigned I = 0, N = Args.size(); I != N; ++I) + Args[I]->Destroy(SemaRef.Context); + + return SemaRef.ExprError(); + } + + return SemaRef.Owned(CXXConstructExpr::Create(SemaRef.Context, Var, T, + E->getConstructor(), + E->isElidable(), + &Args.front(), Args.size())); +} + +Sema::OwningExprResult +TemplateExprInstantiator::VisitCXXFunctionalCastExpr( + CXXFunctionalCastExpr *E) { + // Instantiate the type that we're casting to. + QualType ExplicitTy = SemaRef.InstantiateType(E->getTypeAsWritten(), + TemplateArgs, + E->getTypeBeginLoc(), + DeclarationName()); + if (ExplicitTy.isNull()) + return SemaRef.ExprError(); + + // Instantiate the subexpression. + OwningExprResult SubExpr = Visit(E->getSubExpr()); + if (SubExpr.isInvalid()) + return SemaRef.ExprError(); + + // FIXME: The end of the type's source range is wrong + Expr *Sub = SubExpr.takeAs(); + return SemaRef.ActOnCXXTypeConstructExpr(SourceRange(E->getTypeBeginLoc()), + ExplicitTy.getAsOpaquePtr(), + /*FIXME:*/E->getTypeBeginLoc(), + Sema::MultiExprArg(SemaRef, + (void **)&Sub, + 1), + 0, + E->getRParenLoc()); +} + +Sema::OwningExprResult +TemplateExprInstantiator::VisitCXXZeroInitValueExpr(CXXZeroInitValueExpr *E) { + return SemaRef.Clone(E); +} + Sema::OwningExprResult TemplateExprInstantiator::VisitCXXUnresolvedConstructExpr( CXXUnresolvedConstructExpr *E) { diff --git a/test/SemaTemplate/instantiate-expr-4.cpp b/test/SemaTemplate/instantiate-expr-4.cpp new file mode 100644 index 0000000000..a5b55b35d7 --- /dev/null +++ b/test/SemaTemplate/instantiate-expr-4.cpp @@ -0,0 +1,35 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +// --------------------------------------------------------------------- +// C++ Functional Casts +// --------------------------------------------------------------------- +template +struct ValueInit0 { + int f() { + return int(); + } +}; + +template struct ValueInit0<5>; + +template +struct FunctionalCast0 { + int f() { + return int(N); + } +}; + +template struct FunctionalCast0<5>; + +struct X { + X(int, int); +}; + +template +struct BuildTemporary0 { + X f() { + return X(N, M); + } +}; + +template struct BuildTemporary0<5, 7>; -- 2.40.0