summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2009-08-20 07:17:43 +0000
committerDouglas Gregor <dgregor@apple.com>2009-08-20 07:17:43 +0000
commit43959a93c6aba8b03b09116fe077f4ce8e80005e (patch)
tree4b456c1cc2755e9741e84b310e13b76de03f2a18
parent357f7ce199fdeb20634595dbfba5484d1f908ed2 (diff)
Refactor the instantiation of statements into a generic tree
transformation. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@79519 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/Sema/CMakeLists.txt1
-rw-r--r--lib/Sema/Sema.h3
-rw-r--r--lib/Sema/SemaTemplateInstantiate.cpp77
-rw-r--r--lib/Sema/SemaTemplateInstantiateStmt.cpp451
-rw-r--r--lib/Sema/TreeTransform.h721
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())
+ 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);
@@ -2075,6 +2314,458 @@ QualType TreeTransform<Derived>::TransformObjCObjectPointerType(
}
//===----------------------------------------------------------------------===//
+// 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
//===----------------------------------------------------------------------===//
template<typename Derived>
@@ -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));