[cfe-commits] r79519 - in /cfe/trunk/lib/Sema: CMakeLists.txt Sema.h SemaTemplateInstantiate.cpp SemaTemplateInstantiateStmt.cpp TreeTransform.h

Douglas Gregor dgregor at apple.com
Thu Aug 20 00:17:43 PDT 2009


Author: dgregor
Date: Thu Aug 20 02:17:43 2009
New Revision: 79519

URL: http://llvm.org/viewvc/llvm-project?rev=79519&view=rev
Log:
Refactor the instantiation of statements into a generic tree
transformation.

Removed:
    cfe/trunk/lib/Sema/SemaTemplateInstantiateStmt.cpp
Modified:
    cfe/trunk/lib/Sema/CMakeLists.txt
    cfe/trunk/lib/Sema/Sema.h
    cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp
    cfe/trunk/lib/Sema/TreeTransform.h

Modified: cfe/trunk/lib/Sema/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/CMakeLists.txt?rev=79519&r1=79518&r2=79519&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/CMakeLists.txt (original)
+++ cfe/trunk/lib/Sema/CMakeLists.txt Thu Aug 20 02:17:43 2009
@@ -26,7 +26,6 @@
   SemaTemplateDeduction.cpp
   SemaTemplateInstantiate.cpp
   SemaTemplateInstantiateDecl.cpp
-  SemaTemplateInstantiateStmt.cpp
   SemaType.cpp
   )
 

Modified: cfe/trunk/lib/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=79519&r1=79518&r2=79519&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Thu Aug 20 02:17:43 2009
@@ -2834,9 +2834,6 @@
 
   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);

Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp?rev=79519&r1=79518&r2=79519&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp Thu Aug 20 02:17:43 2009
@@ -294,12 +294,14 @@
     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 @@
     /// \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 @@
   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 @@
                                           /*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 @@
                           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)

Removed: cfe/trunk/lib/Sema/SemaTemplateInstantiateStmt.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiateStmt.cpp?rev=79518&view=auto

==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiateStmt.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiateStmt.cpp (removed)
@@ -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);
-}

Modified: cfe/trunk/lib/Sema/TreeTransform.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/TreeTransform.h?rev=79519&r1=79518&r2=79519&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/TreeTransform.h (original)
+++ cfe/trunk/lib/Sema/TreeTransform.h Thu Aug 20 02:17:43 2009
@@ -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 @@
 ///
 /// 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 @@
 /// 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 @@
   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 @@
        
   /// \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 @@
   /// 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 @@
   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 @@
                                    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 @@
   }
 };
 
+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 @@
 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 @@
 }
 
 //===----------------------------------------------------------------------===//
+// 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 @@
 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 @@
 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 @@
     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));





More information about the cfe-commits mailing list