diff options
-rw-r--r-- | lib/Sema/CMakeLists.txt | 1 | ||||
-rw-r--r-- | lib/Sema/Sema.h | 3 | ||||
-rw-r--r-- | lib/Sema/SemaTemplateInstantiate.cpp | 77 | ||||
-rw-r--r-- | lib/Sema/SemaTemplateInstantiateStmt.cpp | 451 | ||||
-rw-r--r-- | lib/Sema/TreeTransform.h | 721 |
5 files changed, 754 insertions, 499 deletions
diff --git a/lib/Sema/CMakeLists.txt b/lib/Sema/CMakeLists.txt index 25007d2fde..73ecc987fa 100644 --- a/lib/Sema/CMakeLists.txt +++ b/lib/Sema/CMakeLists.txt @@ -26,7 +26,6 @@ add_clang_library(clangSema SemaTemplateDeduction.cpp SemaTemplateInstantiate.cpp SemaTemplateInstantiateDecl.cpp - SemaTemplateInstantiateStmt.cpp SemaType.cpp ) diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h index 12ab47c81a..26c8434059 100644 --- a/lib/Sema/Sema.h +++ b/lib/Sema/Sema.h @@ -2834,9 +2834,6 @@ public: OwningStmtResult InstantiateStmt(Stmt *S, const TemplateArgumentList &TemplateArgs); - OwningStmtResult InstantiateCompoundStmt(CompoundStmt *S, - const TemplateArgumentList &TemplateArgs, - bool isStmtExpr); Decl *InstantiateDecl(Decl *D, DeclContext *Owner, const TemplateArgumentList &TemplateArgs); diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp index 45214bfd6c..0f66c45b26 100644 --- a/lib/Sema/SemaTemplateInstantiate.cpp +++ b/lib/Sema/SemaTemplateInstantiate.cpp @@ -294,12 +294,14 @@ namespace { DeclarationName Entity; public: + typedef TreeTransform<TemplateInstantiator> inherited; + TemplateInstantiator(Sema &SemaRef, const TemplateArgumentList &TemplateArgs, SourceLocation Loc, DeclarationName Entity) - : TreeTransform<TemplateInstantiator>(SemaRef), TemplateArgs(TemplateArgs), - Loc(Loc), Entity(Entity) { } + : inherited(SemaRef), TemplateArgs(TemplateArgs), Loc(Loc), + Entity(Entity) { } /// \brief Determine whether the given type \p T has already been /// transformed. @@ -319,21 +321,20 @@ namespace { /// \brief Transform the given declaration by instantiating a reference to /// this declaration. Decl *TransformDecl(Decl *D); - - Sema::OwningStmtResult TransformStmt(Stmt *S) { - return SemaRef.InstantiateStmt(S, TemplateArgs); - } - Sema::OwningStmtResult TransformCompoundStmt(CompoundStmt *S, - bool IsStmtExpr) { - return SemaRef.InstantiateCompoundStmt(S, TemplateArgs, IsStmtExpr); - } + /// \brief Transform the definition of the given declaration by + /// instantiating it. + Decl *TransformDefinition(Decl *D); + + /// \brief Rebuild the exception declaration and register the declaration + /// as an instantiated local. + VarDecl *RebuildExceptionDecl(VarDecl *ExceptionDecl, QualType T, + DeclaratorInfo *Declarator, + IdentifierInfo *Name, + SourceLocation Loc, SourceRange TypeRange); Sema::OwningExprResult TransformDeclRefExpr(DeclRefExpr *E); - Sema::OwningExprResult - TransformCXXConditionDeclExpr(CXXConditionDeclExpr *E); - /// \brief Transforms a template type parameter type by performing /// substitution of the corresponding template type argument. QualType TransformTemplateTypeParmType(const TemplateTypeParmType *T); @@ -357,6 +358,29 @@ Decl *TemplateInstantiator::TransformDecl(Decl *D) { return SemaRef.InstantiateCurrentDeclRef(cast_or_null<NamedDecl>(D)); } +Decl *TemplateInstantiator::TransformDefinition(Decl *D) { + Decl *Inst = getSema().InstantiateDecl(D, getSema().CurContext, TemplateArgs); + if (!Inst) + return 0; + + getSema().CurrentInstantiationScope->InstantiatedLocal(D, Inst); + return Inst; +} + +VarDecl * +TemplateInstantiator::RebuildExceptionDecl(VarDecl *ExceptionDecl, + QualType T, + DeclaratorInfo *Declarator, + IdentifierInfo *Name, + SourceLocation Loc, + SourceRange TypeRange) { + VarDecl *Var = inherited::RebuildExceptionDecl(ExceptionDecl, T, Declarator, + Name, Loc, TypeRange); + if (Var && !Var->isInvalidDecl()) + getSema().CurrentInstantiationScope->InstantiatedLocal(ExceptionDecl, Var); + return Var; +} + Sema::OwningExprResult TemplateInstantiator::TransformDeclRefExpr(DeclRefExpr *E) { // FIXME: Clean this up a bit @@ -428,22 +452,6 @@ TemplateInstantiator::TransformDeclRefExpr(DeclRefExpr *E) { /*FIXME:*/false); } -Sema::OwningExprResult -TemplateInstantiator::TransformCXXConditionDeclExpr(CXXConditionDeclExpr *E) { - VarDecl *Var - = cast_or_null<VarDecl>(SemaRef.InstantiateDecl(E->getVarDecl(), - SemaRef.CurContext, - TemplateArgs)); - if (!Var) - return SemaRef.ExprError(); - - SemaRef.CurrentInstantiationScope->InstantiatedLocal(E->getVarDecl(), Var); - return SemaRef.Owned(new (SemaRef.Context) CXXConditionDeclExpr( - E->getStartLoc(), - SourceLocation(), - Var)); -} - QualType TemplateInstantiator::TransformTemplateTypeParmType( const TemplateTypeParmType *T) { @@ -840,6 +848,17 @@ void Sema::InstantiateClassTemplateSpecializationMembers( ClassTemplateSpec->getTemplateArgs()); } +Sema::OwningStmtResult +Sema::InstantiateStmt(Stmt *S, const TemplateArgumentList &TemplateArgs) { + if (!S) + return Owned(S); + + TemplateInstantiator Instantiator(*this, TemplateArgs, + SourceLocation(), + DeclarationName()); + return Instantiator.TransformStmt(S); +} + Sema::OwningExprResult Sema::InstantiateExpr(Expr *E, const TemplateArgumentList &TemplateArgs) { if (!E) diff --git a/lib/Sema/SemaTemplateInstantiateStmt.cpp b/lib/Sema/SemaTemplateInstantiateStmt.cpp deleted file mode 100644 index 17e0014d98..0000000000 --- a/lib/Sema/SemaTemplateInstantiateStmt.cpp +++ /dev/null @@ -1,451 +0,0 @@ -//===--- SemaTemplateInstantiateStmt.cpp - C++ Template Stmt Instantiation ===/ -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -//===----------------------------------------------------------------------===/ -// -// This file implements C++ template instantiation for statements. -// -//===----------------------------------------------------------------------===/ -#include "Sema.h" -#include "clang/AST/ASTContext.h" -#include "clang/AST/DeclTemplate.h" -#include "clang/AST/StmtVisitor.h" -#include "clang/AST/Expr.h" -#include "clang/AST/ExprCXX.h" -#include "clang/Parse/DeclSpec.h" -#include "llvm/Support/Compiler.h" -using namespace clang; - -namespace { - class VISIBILITY_HIDDEN TemplateStmtInstantiator - : public StmtVisitor<TemplateStmtInstantiator, Sema::OwningStmtResult> { - Sema &SemaRef; - const TemplateArgumentList &TemplateArgs; - - template<typename T> - Sema::FullExprArg FullExpr(T &expr) { - return SemaRef.FullExpr(expr); - } - - public: - typedef Sema::OwningExprResult OwningExprResult; - typedef Sema::OwningStmtResult OwningStmtResult; - - TemplateStmtInstantiator(Sema &SemaRef, - const TemplateArgumentList &TemplateArgs) - : SemaRef(SemaRef), TemplateArgs(TemplateArgs) { } - - // Declare VisitXXXStmt nodes for all of the statement kinds. -#define STMT(Type, Base) OwningStmtResult Visit##Type(Type *S); -#define EXPR(Type, Base) -#include "clang/AST/StmtNodes.def" - - // Visit an expression (which will use the expression - // instantiator). - OwningStmtResult VisitExpr(Expr *E); - - // Base case. I'm supposed to ignore this. - OwningStmtResult VisitStmt(Stmt *S) { - S->dump(); - assert(false && "Cannot instantiate this kind of statement"); - return SemaRef.StmtError(); - } - }; -} - -//===----------------------------------------------------------------------===/ -// Common/C statements -//===----------------------------------------------------------------------===/ -Sema::OwningStmtResult TemplateStmtInstantiator::VisitDeclStmt(DeclStmt *S) { - llvm::SmallVector<Decl *, 4> Decls; - for (DeclStmt::decl_iterator D = S->decl_begin(), DEnd = S->decl_end(); - D != DEnd; ++D) { - Decl *Instantiated = SemaRef.InstantiateDecl(*D, SemaRef.CurContext, - TemplateArgs); - if (!Instantiated) - return SemaRef.StmtError(); - - Decls.push_back(Instantiated); - SemaRef.CurrentInstantiationScope->InstantiatedLocal(*D, Instantiated); - } - - return SemaRef.Owned(new (SemaRef.Context) DeclStmt( - DeclGroupRef::Create(SemaRef.Context, - &Decls[0], - Decls.size()), - S->getStartLoc(), - S->getEndLoc())); -} - -Sema::OwningStmtResult TemplateStmtInstantiator::VisitNullStmt(NullStmt *S) { - return SemaRef.Owned(S->Retain()); -} - -Sema::OwningStmtResult TemplateStmtInstantiator::VisitLabelStmt(LabelStmt *S) { - OwningStmtResult SubStmt = Visit(S->getSubStmt()); - - if (SubStmt.isInvalid()) - return SemaRef.StmtError(); - - // FIXME: Pass the real colon loc in. - return SemaRef.ActOnLabelStmt(S->getIdentLoc(), S->getID(), SourceLocation(), - move(SubStmt)); -} - -Sema::OwningStmtResult TemplateStmtInstantiator::VisitGotoStmt(GotoStmt *S) { - return SemaRef.ActOnGotoStmt(S->getGotoLoc(), S->getLabelLoc(), - S->getLabel()->getID()); -} - -Sema::OwningStmtResult -TemplateStmtInstantiator::VisitIndirectGotoStmt(IndirectGotoStmt *S) { - OwningExprResult Target = SemaRef.InstantiateExpr(S->getTarget(), - TemplateArgs); - if (Target.isInvalid()) - return SemaRef.StmtError(); - - return SemaRef.ActOnIndirectGotoStmt(S->getGotoLoc(), S->getStarLoc(), - move(Target)); -} - -Sema::OwningStmtResult TemplateStmtInstantiator::VisitBreakStmt(BreakStmt *S) { - return SemaRef.Owned(S->Retain()); -} - -Sema::OwningStmtResult -TemplateStmtInstantiator::VisitContinueStmt(ContinueStmt *S) { - return SemaRef.Owned(S->Retain()); -} - -Sema::OwningStmtResult -TemplateStmtInstantiator::VisitReturnStmt(ReturnStmt *S) { - Sema::OwningExprResult Result = SemaRef.ExprEmpty(); - if (Expr *E = S->getRetValue()) { - Result = SemaRef.InstantiateExpr(E, TemplateArgs); - - if (Result.isInvalid()) - return SemaRef.StmtError(); - } - - return SemaRef.ActOnReturnStmt(S->getReturnLoc(), move(Result)); -} - -Sema::OwningStmtResult -TemplateStmtInstantiator::VisitCompoundStmt(CompoundStmt *S) { - return SemaRef.InstantiateCompoundStmt(S, TemplateArgs, false); -} - -Sema::OwningStmtResult -TemplateStmtInstantiator::VisitSwitchCase(SwitchCase *S) { - assert(false && "SwitchCase statements are never directly instantiated"); - return SemaRef.StmtError(); -} - -Sema::OwningStmtResult TemplateStmtInstantiator::VisitCaseStmt(CaseStmt *S) { - // The case value expressions are not potentially evaluated. - EnterExpressionEvaluationContext Unevaluated(SemaRef, Action::Unevaluated); - - // Instantiate left-hand case value. - OwningExprResult LHS = SemaRef.InstantiateExpr(S->getLHS(), TemplateArgs); - if (LHS.isInvalid()) - return SemaRef.StmtError(); - - // Instantiate right-hand case value (for the GNU case-range extension). - OwningExprResult RHS = SemaRef.InstantiateExpr(S->getRHS(), TemplateArgs); - if (RHS.isInvalid()) - return SemaRef.StmtError(); - - // Build the case statement. - OwningStmtResult Case = SemaRef.ActOnCaseStmt(S->getCaseLoc(), - move(LHS), - S->getEllipsisLoc(), - move(RHS), - S->getColonLoc()); - if (Case.isInvalid()) - return SemaRef.StmtError(); - - // Instantiate the statement following the case - OwningStmtResult SubStmt = SemaRef.InstantiateStmt(S->getSubStmt(), - TemplateArgs); - if (SubStmt.isInvalid()) - return SemaRef.StmtError(); - - SemaRef.ActOnCaseStmtBody(Case.get(), move(SubStmt)); - return move(Case); -} - -Sema::OwningStmtResult -TemplateStmtInstantiator::VisitDefaultStmt(DefaultStmt *S) { - // Instantiate the statement following the default case - OwningStmtResult SubStmt = SemaRef.InstantiateStmt(S->getSubStmt(), - TemplateArgs); - if (SubStmt.isInvalid()) - return SemaRef.StmtError(); - - return SemaRef.ActOnDefaultStmt(S->getDefaultLoc(), - S->getColonLoc(), - move(SubStmt), - /*CurScope=*/0); -} - -Sema::OwningStmtResult TemplateStmtInstantiator::VisitIfStmt(IfStmt *S) { - // Instantiate the condition - OwningExprResult Cond = SemaRef.InstantiateExpr(S->getCond(), TemplateArgs); - if (Cond.isInvalid()) - return SemaRef.StmtError(); - - Sema::FullExprArg FullCond(FullExpr(Cond)); - - // Instantiate the "then" branch. - OwningStmtResult Then = SemaRef.InstantiateStmt(S->getThen(), TemplateArgs); - if (Then.isInvalid()) - return SemaRef.StmtError(); - - // Instantiate the "else" branch. - OwningStmtResult Else = SemaRef.InstantiateStmt(S->getElse(), TemplateArgs); - if (Else.isInvalid()) - return SemaRef.StmtError(); - - return SemaRef.ActOnIfStmt(S->getIfLoc(), FullCond, move(Then), - S->getElseLoc(), move(Else)); -} - -Sema::OwningStmtResult -TemplateStmtInstantiator::VisitSwitchStmt(SwitchStmt *S) { - // Instantiate the condition. - OwningExprResult Cond = SemaRef.InstantiateExpr(S->getCond(), TemplateArgs); - if (Cond.isInvalid()) - return SemaRef.StmtError(); - - // Start the switch statement itself. - OwningStmtResult Switch = SemaRef.ActOnStartOfSwitchStmt(move(Cond)); - if (Switch.isInvalid()) - return SemaRef.StmtError(); - - // Instantiate the body of the switch statement. - OwningStmtResult Body = SemaRef.InstantiateStmt(S->getBody(), TemplateArgs); - if (Body.isInvalid()) - return SemaRef.StmtError(); - - // Complete the switch statement. - return SemaRef.ActOnFinishSwitchStmt(S->getSwitchLoc(), move(Switch), - move(Body)); -} - -Sema::OwningStmtResult TemplateStmtInstantiator::VisitWhileStmt(WhileStmt *S) { - // Instantiate the condition - OwningExprResult Cond = SemaRef.InstantiateExpr(S->getCond(), TemplateArgs); - if (Cond.isInvalid()) - return SemaRef.StmtError(); - - Sema::FullExprArg FullCond(FullExpr(Cond)); - - // Instantiate the body - OwningStmtResult Body = SemaRef.InstantiateStmt(S->getBody(), TemplateArgs); - if (Body.isInvalid()) - return SemaRef.StmtError(); - - return SemaRef.ActOnWhileStmt(S->getWhileLoc(), FullCond, move(Body)); -} - -Sema::OwningStmtResult TemplateStmtInstantiator::VisitDoStmt(DoStmt *S) { - // Instantiate the condition - OwningExprResult Cond = SemaRef.InstantiateExpr(S->getCond(), TemplateArgs); - if (Cond.isInvalid()) - return SemaRef.StmtError(); - - // Instantiate the body - OwningStmtResult Body = SemaRef.InstantiateStmt(S->getBody(), TemplateArgs); - if (Body.isInvalid()) - return SemaRef.StmtError(); - - return SemaRef.ActOnDoStmt(S->getDoLoc(), move(Body), S->getWhileLoc(), - SourceLocation(), move(Cond), S->getRParenLoc()); -} - -Sema::OwningStmtResult TemplateStmtInstantiator::VisitForStmt(ForStmt *S) { - // Instantiate the initialization statement - OwningStmtResult Init = SemaRef.InstantiateStmt(S->getInit(), TemplateArgs); - if (Init.isInvalid()) - return SemaRef.StmtError(); - - // Instantiate the condition - OwningExprResult Cond = SemaRef.InstantiateExpr(S->getCond(), TemplateArgs); - if (Cond.isInvalid()) - return SemaRef.StmtError(); - - // Instantiate the increment - OwningExprResult Inc = SemaRef.InstantiateExpr(S->getInc(), TemplateArgs); - if (Inc.isInvalid()) - return SemaRef.StmtError(); - - // Instantiate the body - OwningStmtResult Body = SemaRef.InstantiateStmt(S->getBody(), TemplateArgs); - if (Body.isInvalid()) - return SemaRef.StmtError(); - - return SemaRef.ActOnForStmt(S->getForLoc(), S->getLParenLoc(), - move(Init), move(Cond), move(Inc), - S->getRParenLoc(), move(Body)); -} - -Sema::OwningStmtResult -TemplateStmtInstantiator::VisitAsmStmt(AsmStmt *S) { - // FIXME: Implement this - assert(false && "Cannot instantiate an 'asm' statement"); - return SemaRef.StmtError(); -} - -//===----------------------------------------------------------------------===/ -// C++ statements -//===----------------------------------------------------------------------===/ -Sema::OwningStmtResult -TemplateStmtInstantiator::VisitCXXTryStmt(CXXTryStmt *S) { - // Instantiate the try block itself. - OwningStmtResult TryBlock = VisitCompoundStmt(S->getTryBlock()); - if (TryBlock.isInvalid()) - return SemaRef.StmtError(); - - // Instantiate the handlers. - ASTOwningVector<&ActionBase::DeleteStmt> Handlers(SemaRef); - for (unsigned I = 0, N = S->getNumHandlers(); I != N; ++I) { - OwningStmtResult Handler = VisitCXXCatchStmt(S->getHandler(I)); - if (Handler.isInvalid()) - return SemaRef.StmtError(); - - Handlers.push_back(Handler.takeAs<Stmt>()); - } - - return SemaRef.ActOnCXXTryBlock(S->getTryLoc(), move(TryBlock), - move_arg(Handlers)); -} - -Sema::OwningStmtResult -TemplateStmtInstantiator::VisitCXXCatchStmt(CXXCatchStmt *S) { - // Instantiate the exception declaration, if any. - VarDecl *Var = 0; - if (S->getExceptionDecl()) { - VarDecl *ExceptionDecl = S->getExceptionDecl(); - QualType T = SemaRef.InstantiateType(ExceptionDecl->getType(), - TemplateArgs, - ExceptionDecl->getLocation(), - ExceptionDecl->getDeclName()); - if (T.isNull()) - return SemaRef.StmtError(); - - Var = SemaRef.BuildExceptionDeclaration(0, T, - ExceptionDecl->getDeclaratorInfo(), - ExceptionDecl->getIdentifier(), - ExceptionDecl->getLocation(), - /*FIXME: Inaccurate*/ - SourceRange(ExceptionDecl->getLocation())); - if (Var->isInvalidDecl()) { - Var->Destroy(SemaRef.Context); - return SemaRef.StmtError(); - } - - // Introduce the exception declaration into scope. - SemaRef.CurrentInstantiationScope->InstantiatedLocal(ExceptionDecl, Var); - } - - // Instantiate the actual exception handler. - OwningStmtResult Handler = Visit(S->getHandlerBlock()); - if (Handler.isInvalid()) { - if (Var) - Var->Destroy(SemaRef.Context); - return SemaRef.StmtError(); - } - - return SemaRef.Owned(new (SemaRef.Context) CXXCatchStmt(S->getCatchLoc(), - Var, - Handler.takeAs<Stmt>())); -} - -//===----------------------------------------------------------------------===/ -// Objective-C statements -//===----------------------------------------------------------------------===/ -Sema::OwningStmtResult -TemplateStmtInstantiator::VisitObjCAtFinallyStmt(ObjCAtFinallyStmt *S) { - // FIXME: Implement this - assert(false && "Cannot instantiate an Objective-C @finally statement"); - return SemaRef.StmtError(); -} - -Sema::OwningStmtResult -TemplateStmtInstantiator::VisitObjCAtSynchronizedStmt( - ObjCAtSynchronizedStmt *S) { - // FIXME: Implement this - assert(false && "Cannot instantiate an Objective-C @synchronized statement"); - return SemaRef.StmtError(); -} - -Sema::OwningStmtResult -TemplateStmtInstantiator::VisitObjCAtTryStmt(ObjCAtTryStmt *S) { - // FIXME: Implement this - assert(false && "Cannot instantiate an Objective-C @try statement"); - return SemaRef.StmtError(); -} - -Sema::OwningStmtResult -TemplateStmtInstantiator::VisitObjCForCollectionStmt( - ObjCForCollectionStmt *S) { - // FIXME: Implement this - assert(false && "Cannot instantiate an Objective-C \"for\" statement"); - return SemaRef.StmtError(); -} - -Sema::OwningStmtResult -TemplateStmtInstantiator::VisitObjCAtThrowStmt(ObjCAtThrowStmt *S) { - // FIXME: Implement this - assert(false && "Cannot instantiate an Objective-C @throw statement"); - return SemaRef.StmtError(); -} - -Sema::OwningStmtResult -TemplateStmtInstantiator::VisitObjCAtCatchStmt(ObjCAtCatchStmt *S) { - // FIXME: Implement this - assert(false && "Cannot instantiate an Objective-C @catch statement"); - return SemaRef.StmtError(); -} - -Sema::OwningStmtResult TemplateStmtInstantiator::VisitExpr(Expr *E) { - Sema::OwningExprResult Result = SemaRef.InstantiateExpr(E, TemplateArgs); - if (Result.isInvalid()) - return SemaRef.StmtError(); - - return SemaRef.Owned(Result.takeAs<Stmt>()); -} - -Sema::OwningStmtResult -Sema::InstantiateStmt(Stmt *S, const TemplateArgumentList &TemplateArgs) { - if (!S) - return Owned((Stmt *)0); - - TemplateStmtInstantiator Instantiator(*this, TemplateArgs); - return Instantiator.Visit(S); -} - -Sema::OwningStmtResult -Sema::InstantiateCompoundStmt(CompoundStmt *S, - const TemplateArgumentList &TemplateArgs, - bool isStmtExpr) { - if (!S) - return Owned((Stmt *)0); - - TemplateStmtInstantiator Instantiator(*this, TemplateArgs); - ASTOwningVector<&ActionBase::DeleteStmt> Statements(*this); - for (CompoundStmt::body_iterator B = S->body_begin(), BEnd = S->body_end(); - B != BEnd; ++B) { - OwningStmtResult Result = Instantiator.Visit(*B); - if (Result.isInvalid()) - return StmtError(); - - Statements.push_back(Result.takeAs<Stmt>()); - } - - return ActOnCompoundStmt(S->getLBracLoc(), S->getRBracLoc(), - move_arg(Statements), isStmtExpr); -} diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h index e734d07e85..ae359bb550 100644 --- a/lib/Sema/TreeTransform.h +++ b/lib/Sema/TreeTransform.h @@ -18,6 +18,9 @@ #include "clang/AST/Expr.h" #include "clang/AST/ExprCXX.h" #include "clang/AST/ExprObjC.h" +#include "clang/AST/Stmt.h" +#include "clang/AST/StmtCXX.h" +#include "clang/AST/StmtObjC.h" #include "clang/Parse/Ownership.h" #include "clang/Parse/Designator.h" #include "clang/Lex/Preprocessor.h" @@ -61,7 +64,7 @@ namespace clang { /// /// For more fine-grained transformations, subclasses can replace any of the /// \c TransformXXX functions (where XXX is the name of an AST node, e.g., -/// PointerType) to alter the transformation. As mentioned previously, +/// PointerType, StmtExpr) to alter the transformation. As mentioned previously, /// replacing TransformTemplateTypeParmType() allows template instantiation /// to substitute template arguments for their corresponding template /// parameters. Additionally, subclasses can override the \c RebuildXXX @@ -76,9 +79,6 @@ namespace clang { /// operands have not changed (\c AlwaysRebuild()), and customize the /// default locations and entity names used for type-checking /// (\c getBaseLocation(), \c getBaseEntity()). -/// -/// FIXME: In the future, TreeTransform will support transformation of -/// statements and expressions as well as types. template<typename Derived> class TreeTransform { protected: @@ -90,6 +90,7 @@ public: typedef Sema::StmtArg StmtArg; typedef Sema::ExprArg ExprArg; typedef Sema::MultiExprArg MultiExprArg; + typedef Sema::MultiStmtArg MultiStmtArg; /// \brief Initializes a new tree transformer. TreeTransform(Sema &SemaRef) : SemaRef(SemaRef) { } @@ -191,7 +192,13 @@ public: /// \brief Transform the given statement. /// - /// FIXME: At the moment, subclasses must override this. + /// By default, this routine transforms a statement by delegating to the + /// appropriate TransformXXXStmt function to transform a specific kind of + /// statement or the TransformExpr() function to transform an expression. + /// Subclasses may override this function to transform statements using some + /// other mechanism. + /// + /// \returns the transformed statement. OwningStmtResult TransformStmt(Stmt *S); /// \brief Transform the given expression. @@ -222,6 +229,12 @@ public: /// By default, acts as the identity function on declarations. Subclasses /// may override this function to provide alternate behavior. Decl *TransformDecl(Decl *D) { return D; } + + /// \brief Transform the definition of the given declaration. + /// + /// By default, invokes TransformDecl() to transform the declaration. + /// Subclasses may override this function to provide alternate behavior. + Decl *TransformDefinition(Decl *D) { return getDerived().TransformDecl(D); } /// \brief Transform the given nested-name-specifier. /// @@ -251,12 +264,10 @@ public: QualType Transform##CLASS##Type(const CLASS##Type *T); #include "clang/AST/TypeNodes.def" - OwningStmtResult TransformCompoundStmt(Stmt *S, bool IsStmtExpr) { - // FIXME: Actually handle this transformation properly. - return getDerived().TransformStmt(S); - } + OwningStmtResult TransformCompoundStmt(CompoundStmt *S, bool IsStmtExpr); -#define STMT(Node, Parent) +#define STMT(Node, Parent) \ + OwningStmtResult Transform##Node(Node *S); #define EXPR(Node, Parent) \ OwningExprResult Transform##Node(Node *E); #define ABSTRACT_EXPR(Node, Parent) @@ -540,6 +551,204 @@ public: const IdentifierInfo &II); + /// \brief Build a new compound statement. + /// + /// By default, performs semantic analysis to build the new statement. + /// Subclasses may override this routine to provide different behavior. + OwningStmtResult RebuildCompoundStmt(SourceLocation LBraceLoc, + MultiStmtArg Statements, + SourceLocation RBraceLoc, + bool IsStmtExpr) { + return getSema().ActOnCompoundStmt(LBraceLoc, RBraceLoc, move(Statements), + IsStmtExpr); + } + + /// \brief Build a new case statement. + /// + /// By default, performs semantic analysis to build the new statement. + /// Subclasses may override this routine to provide different behavior. + OwningStmtResult RebuildCaseStmt(SourceLocation CaseLoc, + ExprArg LHS, + SourceLocation EllipsisLoc, + ExprArg RHS, + SourceLocation ColonLoc) { + return getSema().ActOnCaseStmt(CaseLoc, move(LHS), EllipsisLoc, move(RHS), + ColonLoc); + } + + /// \brief Attach the body to a new case statement. + /// + /// By default, performs semantic analysis to build the new statement. + /// Subclasses may override this routine to provide different behavior. + OwningStmtResult RebuildCaseStmtBody(StmtArg S, StmtArg Body) { + getSema().ActOnCaseStmtBody(S.get(), move(Body)); + return move(S); + } + + /// \brief Build a new default statement. + /// + /// By default, performs semantic analysis to build the new statement. + /// Subclasses may override this routine to provide different behavior. + OwningStmtResult RebuildDefaultStmt(SourceLocation DefaultLoc, + SourceLocation ColonLoc, + StmtArg SubStmt) { + return getSema().ActOnDefaultStmt(DefaultLoc, ColonLoc, move(SubStmt), + /*CurScope=*/0); + } + + /// \brief Build a new label statement. + /// + /// By default, performs semantic analysis to build the new statement. + /// Subclasses may override this routine to provide different behavior. + OwningStmtResult RebuildLabelStmt(SourceLocation IdentLoc, + IdentifierInfo *Id, + SourceLocation ColonLoc, + StmtArg SubStmt) { + return SemaRef.ActOnLabelStmt(IdentLoc, Id, ColonLoc, move(SubStmt)); + } + + /// \brief Build a new "if" statement. + /// + /// By default, performs semantic analysis to build the new statement. + /// Subclasses may override this routine to provide different behavior. + OwningStmtResult RebuildIfStmt(SourceLocation IfLoc, Sema::FullExprArg Cond, + StmtArg Then, SourceLocation ElseLoc, + StmtArg Else) { + return getSema().ActOnIfStmt(IfLoc, Cond, move(Then), ElseLoc, move(Else)); + } + + /// \brief Start building a new switch statement. + /// + /// By default, performs semantic analysis to build the new statement. + /// Subclasses may override this routine to provide different behavior. + OwningStmtResult RebuildSwitchStmtStart(ExprArg Cond) { + return getSema().ActOnStartOfSwitchStmt(move(Cond)); + } + + /// \brief Attach the body to the switch statement. + /// + /// By default, performs semantic analysis to build the new statement. + /// Subclasses may override this routine to provide different behavior. + OwningStmtResult RebuildSwitchStmtBody(SourceLocation SwitchLoc, + StmtArg Switch, StmtArg Body) { + return getSema().ActOnFinishSwitchStmt(SwitchLoc, move(Switch), + move(Body)); + } + + /// \brief Build a new while statement. + /// + /// By default, performs semantic analysis to build the new statement. + /// Subclasses may override this routine to provide different behavior. + OwningStmtResult RebuildWhileStmt(SourceLocation WhileLoc, + Sema::FullExprArg Cond, + StmtArg Body) { + return getSema().ActOnWhileStmt(WhileLoc, Cond, move(Body)); + } + + /// \brief Build a new do-while statement. + /// + /// By default, performs semantic analysis to build the new statement. + /// Subclasses may override this routine to provide different behavior. + OwningStmtResult RebuildDoStmt(SourceLocation DoLoc, StmtArg Body, + SourceLocation WhileLoc, + SourceLocation LParenLoc, + ExprArg Cond, + SourceLocation RParenLoc) { + return getSema().ActOnDoStmt(DoLoc, move(Body), WhileLoc, LParenLoc, + move(Cond), RParenLoc); + } + + /// \brief Build a new for statement. + /// + /// By default, performs semantic analysis to build the new statement. + /// Subclasses may override this routine to provide different behavior. + OwningStmtResult RebuildForStmt(SourceLocation ForLoc, + SourceLocation LParenLoc, + StmtArg Init, ExprArg Cond, ExprArg Inc, + SourceLocation RParenLoc, StmtArg Body) { + return getSema().ActOnForStmt(ForLoc, LParenLoc, move(Init), move(Cond), + move(Inc), RParenLoc, move(Body)); + } + + /// \brief Build a new goto statement. + /// + /// By default, performs semantic analysis to build the new statement. + /// Subclasses may override this routine to provide different behavior. + OwningStmtResult RebuildGotoStmt(SourceLocation GotoLoc, + SourceLocation LabelLoc, + LabelStmt *Label) { + return getSema().ActOnGotoStmt(GotoLoc, LabelLoc, Label->getID()); + } + + /// \brief Build a new indirect goto statement. + /// + /// By default, performs semantic analysis to build the new statement. + /// Subclasses may override this routine to provide different behavior. + OwningStmtResult RebuildIndirectGotoStmt(SourceLocation GotoLoc, + SourceLocation StarLoc, + ExprArg Target) { + return getSema().ActOnIndirectGotoStmt(GotoLoc, StarLoc, move(Target)); + } + + /// \brief Build a new return statement. + /// + /// By default, performs semantic analysis to build the new statement. + /// Subclasses may override this routine to provide different behavior. + OwningStmtResult RebuildReturnStmt(SourceLocation ReturnLoc, + ExprArg Result) { + + return getSema().ActOnReturnStmt(ReturnLoc, move(Result)); + } + + /// \brief Build a new declaration statement. + /// + /// By default, performs semantic analysis to build the new statement. + /// Subclasses may override this routine to provide different behavior. + OwningStmtResult RebuildDeclStmt(Decl **Decls, unsigned NumDecls, + SourceLocation StartLoc, + SourceLocation EndLoc) { + return getSema().Owned( + new (getSema().Context) DeclStmt( + DeclGroupRef::Create(getSema().Context, + Decls, NumDecls), + StartLoc, EndLoc)); + } + + /// \brief Build a new C++ exception declaration. + /// + /// By default, performs semantic analysis to build the new decaration. + /// Subclasses may override this routine to provide different behavior. + VarDecl *RebuildExceptionDecl(VarDecl *ExceptionDecl, QualType T, + DeclaratorInfo *Declarator, + IdentifierInfo *Name, + SourceLocation Loc, + SourceRange TypeRange) { + return getSema().BuildExceptionDeclaration(0, T, Declarator, Name, Loc, + TypeRange); + } + + /// \brief Build a new C++ catch statement. + /// + /// By default, performs semantic analysis to build the new statement. + /// Subclasses may override this routine to provide different behavior. + OwningStmtResult RebuildCXXCatchStmt(SourceLocation CatchLoc, + VarDecl *ExceptionDecl, + StmtArg Handler) { + return getSema().Owned( + new (getSema().Context) CXXCatchStmt(CatchLoc, ExceptionDecl, + Handler.takeAs<Stmt>())); + } + + /// \brief Build a new C++ try statement. + /// + /// By default, performs semantic analysis to build the new statement. + /// Subclasses may override this routine to provide different behavior. + OwningStmtResult RebuildCXXTryStmt(SourceLocation TryLoc, + StmtArg TryBlock, + MultiStmtArg Handlers) { + return getSema().ActOnCXXTryBlock(TryLoc, move(TryBlock), move(Handlers)); + } + /// \brief Build a new expression that references a declaration. /// /// By default, performs semantic analysis to build the new expression. @@ -1311,6 +1520,36 @@ public: } }; +template<typename Derived> +Sema::OwningStmtResult TreeTransform<Derived>::TransformStmt(Stmt *S) { + if (!S) + return SemaRef.Owned(S); + + switch (S->getStmtClass()) { + case Stmt::NoStmtClass: break; + + // Transform individual statement nodes +#define STMT(Node, Parent) \ + case Stmt::Node##Class: return getDerived().Transform##Node(cast<Node>(S)); +#define EXPR(Node, Parent) +#include "clang/AST/StmtNodes.def" + + // Transform expressions by calling TransformExpr. +#define STMT(Node, Parent) +#define EXPR(Node, Parent) case Stmt::Node##Class: +#include "clang/AST/StmtNodes.def" + { + Sema::OwningExprResult E = getDerived().TransformExpr(cast<Expr>(S)); + if (E.isInvalid())< |