diff --git a/lib/Sema/CMakeLists.txt b/lib/Sema/CMakeLists.txt index 25007d2fde3cd670d1a1ae158b3820a5cb01bef5..73ecc987fafe1e49a1dfbcf2f9324134d96ad176 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 12ab47c81aa7be0cccdeda3f44fbdb52bd89a8ec..26c8434059085b33e003a74823cb8766fe3e4247 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 45214bfd6c6caec9c1264f9b7b1fa104eccadb81..0f66c45b263ac437dbaff3e42130221f8cee78ee 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 17e0014d981930ac2dcf3d086cf69f0aeb6e4125..0000000000000000000000000000000000000000 --- 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 e734d07e8575ebef25d3649bd2639112014ae237..ae359bb550db3a427cebcbf01948b6a6bc40472c 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()) + return getSema().StmtError(); + + return getSema().Owned(E.takeAs<Stmt>()); + } + } + + return SemaRef.Owned(S->Retain()); +} + template<typename Derived> Sema::OwningExprResult TreeTransform<Derived>::TransformExpr(Expr *E, @@ -1333,7 +1572,7 @@ template<typename Derived> NestedNameSpecifier * TreeTransform<Derived>::TransformNestedNameSpecifier(NestedNameSpecifier *NNS, SourceRange Range) { - // Instantiate the prefix of this nested name specifier. + // Transform the prefix of this nested name specifier. NestedNameSpecifier *Prefix = NNS->getPrefix(); if (Prefix) { Prefix = getDerived().TransformNestedNameSpecifier(Prefix, Range); @@ -2074,6 +2313,458 @@ QualType TreeTransform<Derived>::TransformObjCObjectPointerType( return QualType(T, 0); } +//===----------------------------------------------------------------------===// +// Statement transformation +//===----------------------------------------------------------------------===// +template<typename Derived> +Sema::OwningStmtResult +TreeTransform<Derived>::TransformNullStmt(NullStmt *S) { + return SemaRef.Owned(S->Retain()); +} + +template<typename Derived> +Sema::OwningStmtResult +TreeTransform<Derived>::TransformCompoundStmt(CompoundStmt *S) { + return getDerived().TransformCompoundStmt(S, false); +} + +template<typename Derived> +Sema::OwningStmtResult +TreeTransform<Derived>::TransformCompoundStmt(CompoundStmt *S, + bool IsStmtExpr) { + bool SubStmtChanged = false; + ASTOwningVector<&ActionBase::DeleteStmt> Statements(getSema()); + for (CompoundStmt::body_iterator B = S->body_begin(), BEnd = S->body_end(); + B != BEnd; ++B) { + OwningStmtResult Result = getDerived().TransformStmt(*B); + if (Result.isInvalid()) + return getSema().StmtError(); + + SubStmtChanged = SubStmtChanged || Result.get() != *B; + Statements.push_back(Result.takeAs<Stmt>()); + } + + if (!getDerived().AlwaysRebuild() && + !SubStmtChanged) + return SemaRef.Owned(S->Retain()); + + return getDerived().RebuildCompoundStmt(S->getLBracLoc(), + move_arg(Statements), + S->getRBracLoc(), + IsStmtExpr); +} + +template<typename Derived> +Sema::OwningStmtResult +TreeTransform<Derived>::TransformCaseStmt(CaseStmt *S) { + // The case value expressions are not potentially evaluated. + EnterExpressionEvaluationContext Unevaluated(SemaRef, Action::Unevaluated); + + // Transform the left-hand case value. + OwningExprResult LHS = getDerived().TransformExpr(S->getLHS()); + if (LHS.isInvalid()) + return SemaRef.StmtError(); + + // Transform the right-hand case value (for the GNU case-range extension). + OwningExprResult RHS = getDerived().TransformExpr(S->getRHS()); + if (RHS.isInvalid()) + return SemaRef.StmtError(); + + // Build the case statement. + // Case statements are always rebuilt so that they will attached to their + // transformed switch statement. + OwningStmtResult Case = getDerived().RebuildCaseStmt(S->getCaseLoc(), + move(LHS), + S->getEllipsisLoc(), + move(RHS), + S->getColonLoc()); + if (Case.isInvalid()) + return SemaRef.StmtError(); + + // Transform the statement following the case + OwningStmtResult SubStmt = getDerived().TransformStmt(S->getSubStmt()); + if (SubStmt.isInvalid()) + return SemaRef.StmtError(); + + // Attach the body to the case statement + return getDerived().RebuildCaseStmtBody(move(Case), move(SubStmt)); +} + +template<typename Derived> +Sema::OwningStmtResult +TreeTransform<Derived>::TransformDefaultStmt(DefaultStmt *S) { + // Transform the statement following the default case + OwningStmtResult SubStmt = getDerived().TransformStmt(S->getSubStmt()); + if (SubStmt.isInvalid()) + return SemaRef.StmtError(); + + // Default statements are always rebuilt + return getDerived().RebuildDefaultStmt(S->getDefaultLoc(), S->getColonLoc(), + move(SubStmt)); +} + +template<typename Derived> +Sema::OwningStmtResult +TreeTransform<Derived>::TransformLabelStmt(LabelStmt *S) { + OwningStmtResult SubStmt = getDerived().TransformStmt(S->getSubStmt()); + if (SubStmt.isInvalid()) + return SemaRef.StmtError(); + + // FIXME: Pass the real colon location in. + SourceLocation ColonLoc = SemaRef.PP.getLocForEndOfToken(S->getIdentLoc()); + return getDerived().RebuildLabelStmt(S->getIdentLoc(), S->getID(), ColonLoc, + move(SubStmt)); +} + +template<typename Derived> +Sema::OwningStmtResult +TreeTransform<Derived>::TransformIfStmt(IfStmt *S) { + // Transform the condition + OwningExprResult Cond = getDerived().TransformExpr(S->getCond()); + if (Cond.isInvalid()) + return SemaRef.StmtError(); + + Sema::FullExprArg FullCond(getSema().FullExpr(Cond)); + + // Transform the "then" branch. + OwningStmtResult Then = getDerived().TransformStmt(S->getThen()); + if (Then.isInvalid()) + return SemaRef.StmtError(); + + // Transform the "else" branch. + OwningStmtResult Else = getDerived().TransformStmt(S->getElse()); + if (Else.isInvalid()) + return SemaRef.StmtError(); + + if (!getDerived().AlwaysRebuild() && + FullCond->get() == S->getCond() && + Then.get() == S->getThen() && + Else.get() == S->getElse()) + return SemaRef.Owned(S->Retain()); + + return getDerived().RebuildIfStmt(S->getIfLoc(), FullCond, move(Then), + S->getElseLoc(), move(Else)); +} + +template<typename Derived> +Sema::OwningStmtResult +TreeTransform<Derived>::TransformSwitchStmt(SwitchStmt *S) { + // Transform the condition. + OwningExprResult Cond = getDerived().TransformExpr(S->getCond()); + if (Cond.isInvalid()) + return SemaRef.StmtError(); + + // Rebuild the switch statement. + OwningStmtResult Switch = getDerived().RebuildSwitchStmtStart(move(Cond)); + if (Switch.isInvalid()) + return SemaRef.StmtError(); + + // Transform the body of the switch statement. + OwningStmtResult Body = getDerived().TransformStmt(S->getBody()); + if (Body.isInvalid()) + return SemaRef.StmtError(); + + // Complete the switch statement. + return getDerived().RebuildSwitchStmtBody(S->getSwitchLoc(), move(Switch), + move(Body)); +} + +template<typename Derived> +Sema::OwningStmtResult +TreeTransform<Derived>::TransformWhileStmt(WhileStmt *S) { + // Transform the condition + OwningExprResult Cond = getDerived().TransformExpr(S->getCond()); + if (Cond.isInvalid()) + return SemaRef.StmtError(); + + Sema::FullExprArg FullCond(getSema().FullExpr(Cond)); + + // Transform the body + OwningStmtResult Body = getDerived().TransformStmt(S->getBody()); + if (Body.isInvalid()) + return SemaRef.StmtError(); + + if (!getDerived().AlwaysRebuild() && + FullCond->get() == S->getCond() && + Body.get() == S->getBody()) + return SemaRef.Owned(S->Retain()); + + return getDerived().RebuildWhileStmt(S->getWhileLoc(), FullCond, move(Body)); +} + +template<typename Derived> +Sema::OwningStmtResult +TreeTransform<Derived>::TransformDoStmt(DoStmt *S) { + // Transform the condition + OwningExprResult Cond = getDerived().TransformExpr(S->getCond()); + if (Cond.isInvalid()) + return SemaRef.StmtError(); + + // Transform the body + OwningStmtResult Body = getDerived().TransformStmt(S->getBody()); + if (Body.isInvalid()) + return SemaRef.StmtError(); + + if (!getDerived().AlwaysRebuild() && + Cond.get() == S->getCond() && + Body.get() == S->getBody()) + return SemaRef.Owned(S->Retain()); + + return getDerived().RebuildDoStmt(S->getDoLoc(), move(Body), S->getWhileLoc(), + /*FIXME:*/S->getWhileLoc(), move(Cond), + S->getRParenLoc()); +} + +template<typename Derived> +Sema::OwningStmtResult +TreeTransform<Derived>::TransformForStmt(ForStmt *S) { + // Transform the initialization statement + OwningStmtResult Init = getDerived().TransformStmt(S->getInit()); + if (Init.isInvalid()) + return SemaRef.StmtError(); + + // Transform the condition + OwningExprResult Cond = getDerived().TransformExpr(S->getCond()); + if (Cond.isInvalid()) + return SemaRef.StmtError(); + + // Transform the increment + OwningExprResult Inc = getDerived().TransformExpr(S->getInc()); + if (Inc.isInvalid()) + return SemaRef.StmtError(); + + // Transform the body + OwningStmtResult Body = getDerived().TransformStmt(S->getBody()); + if (Body.isInvalid()) + return SemaRef.StmtError(); + + if (!getDerived().AlwaysRebuild() && + Init.get() == S->getInit() && + Cond.get() == S->getCond() && + Inc.get() == S->getInc() && + Body.get() == S->getBody()) + return SemaRef.Owned(S->Retain()); + + return getDerived().RebuildForStmt(S->getForLoc(), S->getLParenLoc(), + move(Init), move(Cond), move(Inc), + S->getRParenLoc(), move(Body)); +} + +template<typename Derived> +Sema::OwningStmtResult +TreeTransform<Derived>::TransformGotoStmt(GotoStmt *S) { + // Goto statements must always be rebuilt, to resolve the label. + return getDerived().RebuildGotoStmt(S->getGotoLoc(), S->getLabelLoc(), + S->getLabel()); +} + +template<typename Derived> +Sema::OwningStmtResult +TreeTransform<Derived>::TransformIndirectGotoStmt(IndirectGotoStmt *S) { + OwningExprResult Target = getDerived().TransformExpr(S->getTarget()); + if (Target.isInvalid()) + return SemaRef.StmtError(); + + if (!getDerived().AlwaysRebuild() && + Target.get() == S->getTarget()) + return SemaRef.Owned(S->Retain()); + + return getDerived().RebuildIndirectGotoStmt(S->getGotoLoc(), S->getStarLoc(), + move(Target)); +} + +template<typename Derived> +Sema::OwningStmtResult +TreeTransform<Derived>::TransformContinueStmt(ContinueStmt *S) { + return SemaRef.Owned(S->Retain()); +} + +template<typename Derived> +Sema::OwningStmtResult +TreeTransform<Derived>::TransformBreakStmt(BreakStmt *S) { + return SemaRef.Owned(S->Retain()); +} + +template<typename Derived> +Sema::OwningStmtResult +TreeTransform<Derived>::TransformReturnStmt(ReturnStmt *S) { + Sema::OwningExprResult Result = getDerived().TransformExpr(S->getRetValue()); + if (Result.isInvalid()) + return SemaRef.StmtError(); + + // FIXME: We always rebuild the return statement because there is no way + // to tell whether the return type of the function has changed. + return getDerived().RebuildReturnStmt(S->getReturnLoc(), move(Result)); +} + +template<typename Derived> +Sema::OwningStmtResult +TreeTransform<Derived>::TransformDeclStmt(DeclStmt *S) { + bool DeclChanged = false; + llvm::SmallVector<Decl *, 4> Decls; + for (DeclStmt::decl_iterator D = S->decl_begin(), DEnd = S->decl_end(); + D != DEnd; ++D) { + Decl *Transformed = getDerived().TransformDefinition(*D); + if (!Transformed) + return SemaRef.StmtError(); + + if (Transformed != *D) + DeclChanged = true; + + Decls.push_back(Transformed); + } + + if (!getDerived().AlwaysRebuild() && !DeclChanged) + return SemaRef.Owned(S->Retain()); + + return getDerived().RebuildDeclStmt(Decls.data(), Decls.size(), + S->getStartLoc(), S->getEndLoc()); +} + +template<typename Derived> +Sema::OwningStmtResult +TreeTransform<Derived>::TransformSwitchCase(SwitchCase *S) { + assert(false && "SwitchCase is abstract and cannot be transformed"); + return SemaRef.Owned(S->Retain()); +} + +template<typename Derived> +Sema::OwningStmtResult +TreeTransform<Derived>::TransformAsmStmt(AsmStmt *S) { + // FIXME: Implement! + assert(false && "Inline assembly cannot be transformed"); + return SemaRef.Owned(S->Retain()); +} + + +template<typename Derived> +Sema::OwningStmtResult +TreeTransform<Derived>::TransformObjCAtTryStmt(ObjCAtTryStmt *S) { + // FIXME: Implement this + assert(false && "Cannot transform an Objective-C @try statement"); + return SemaRef.Owned(S->Retain()); +} + +template<typename Derived> +Sema::OwningStmtResult +TreeTransform<Derived>::TransformObjCAtCatchStmt(ObjCAtCatchStmt *S) { + // FIXME: Implement this + assert(false && "Cannot transform an Objective-C @catch statement"); + return SemaRef.Owned(S->Retain()); +} + +template<typename Derived> +Sema::OwningStmtResult +TreeTransform<Derived>::TransformObjCAtFinallyStmt(ObjCAtFinallyStmt *S) { + // FIXME: Implement this + assert(false && "Cannot transform an Objective-C @finally statement"); + return SemaRef.Owned(S->Retain()); +} + +template<typename Derived> +Sema::OwningStmtResult +TreeTransform<Derived>::TransformObjCAtThrowStmt(ObjCAtThrowStmt *S) { + // FIXME: Implement this + assert(false && "Cannot transform an Objective-C @throw statement"); + return SemaRef.Owned(S->Retain()); +} + +template<typename Derived> +Sema::OwningStmtResult +TreeTransform<Derived>::TransformObjCAtSynchronizedStmt( + ObjCAtSynchronizedStmt *S) { + // FIXME: Implement this + assert(false && "Cannot transform an Objective-C @synchronized statement"); + return SemaRef.Owned(S->Retain()); +} + +template<typename Derived> +Sema::OwningStmtResult +TreeTransform<Derived>::TransformObjCForCollectionStmt( + ObjCForCollectionStmt *S) { + // FIXME: Implement this + assert(false && "Cannot transform an Objective-C for-each statement"); + return SemaRef.Owned(S->Retain()); +} + + +template<typename Derived> +Sema::OwningStmtResult +TreeTransform<Derived>::TransformCXXCatchStmt(CXXCatchStmt *S) { + // Transform the exception declaration, if any. + VarDecl *Var = 0; + if (S->getExceptionDecl()) { + VarDecl *ExceptionDecl = S->getExceptionDecl(); + TemporaryBase Rebase(*this, ExceptionDecl->getLocation(), + ExceptionDecl->getDeclName()); + + QualType T = getDerived().TransformType(ExceptionDecl->getType()); + if (T.isNull()) + return SemaRef.StmtError(); + + Var = getDerived().RebuildExceptionDecl(ExceptionDecl, + T, + ExceptionDecl->getDeclaratorInfo(), + ExceptionDecl->getIdentifier(), + ExceptionDecl->getLocation(), + /*FIXME: Inaccurate*/ + SourceRange(ExceptionDecl->getLocation())); + if (!Var || Var->isInvalidDecl()) { + if (Var) + Var->Destroy(SemaRef.Context); + return SemaRef.StmtError(); + } + } + + // Transform the actual exception handler. + OwningStmtResult Handler = getDerived().TransformStmt(S->getHandlerBlock()); + if (Handler.isInvalid()) { + if (Var) + Var->Destroy(SemaRef.Context); + return SemaRef.StmtError(); + } + + if (!getDerived().AlwaysRebuild() && + !Var && + Handler.get() == S->getHandlerBlock()) + return SemaRef.Owned(S->Retain()); + + return getDerived().RebuildCXXCatchStmt(S->getCatchLoc(), + Var, + move(Handler)); +} + +template<typename Derived> +Sema::OwningStmtResult +TreeTransform<Derived>::TransformCXXTryStmt(CXXTryStmt *S) { + // Transform the try block itself. + OwningStmtResult TryBlock + = getDerived().TransformCompoundStmt(S->getTryBlock()); + if (TryBlock.isInvalid()) + return SemaRef.StmtError(); + + // Transform the handlers. + bool HandlerChanged = false; + ASTOwningVector<&ActionBase::DeleteStmt> Handlers(SemaRef); + for (unsigned I = 0, N = S->getNumHandlers(); I != N; ++I) { + OwningStmtResult Handler + = getDerived().TransformCXXCatchStmt(S->getHandler(I)); + if (Handler.isInvalid()) + return SemaRef.StmtError(); + + HandlerChanged = HandlerChanged || Handler.get() != S->getHandler(I); + Handlers.push_back(Handler.takeAs<Stmt>()); + } + + if (!getDerived().AlwaysRebuild() && + TryBlock.get() == S->getTryBlock() && + !HandlerChanged) + return SemaRef.Owned(S->Retain()); + + return getDerived().RebuildCXXTryStmt(S->getTryLoc(), move(TryBlock), + move_arg(Handlers)); +} + //===----------------------------------------------------------------------===// // Expression transformation //===----------------------------------------------------------------------===// @@ -2478,12 +3169,12 @@ Sema::OwningExprResult TreeTransform<Derived>::TransformDesignatedInitExpr(DesignatedInitExpr *E) { Designation Desig; - // Instantiate the initializer value + // transform the initializer value OwningExprResult Init = getDerived().TransformExpr(E->getInit()); if (Init.isInvalid()) return SemaRef.ExprError(); - // Instantiate the designators. + // transform the designators. ASTOwningVector<&ActionBase::DeleteExpr, 4> ArrayExprs(SemaRef); bool ExprChanged = false; for (DesignatedInitExpr::designators_iterator D = E->designators_begin(), @@ -2943,7 +3634,7 @@ template<typename Derived> Sema::OwningExprResult TreeTransform<Derived>::TransformCXXConditionDeclExpr(CXXConditionDeclExpr *E) { VarDecl *Var - = cast_or_null<VarDecl>(getDerived().TransformDecl(E->getVarDecl())); + = cast_or_null<VarDecl>(getDerived().TransformDefinition(E->getVarDecl())); if (!Var) return SemaRef.ExprError(); @@ -2982,7 +3673,7 @@ TreeTransform<Derived>::TransformCXXNewExpr(CXXNewExpr *E) { PlacementArgs.push_back(Arg.take()); } - // Instantiate the constructor arguments (if any). + // transform the constructor arguments (if any). ASTOwningVector<&ActionBase::DeleteExpr> ConstructorArgs(SemaRef); for (unsigned I = 0, N = E->getNumConstructorArgs(); I != N; ++I) { OwningExprResult Arg = getDerived().TransformExpr(E->getConstructorArg(I));