1 //===--- CFGStmtVisitor.h - Visitor for Stmts in a CFG ----------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // This file defines the CFGStmtVisitor interface, which extends 11 // StmtVisitor. This interface is useful for visiting statements in a CFG 12 // where some statements have implicit control-flow and thus should 13 // be treated specially. 14 // 15 //===----------------------------------------------------------------------===// 16 17 #ifndef LLVM_CLANG_ANALYSIS_CFGSTMTVISITOR_H 18 #define LLVM_CLANG_ANALYSIS_CFGSTMTVISITOR_H 19 20 #include "clang/AST/StmtVisitor.h" 21 #include "clang/Analysis/CFG.h" 22 23 namespace clang { 24 25 #define DISPATCH_CASE(CLASS) \ 26 case Stmt::CLASS ## Class: return \ 27 static_cast<ImplClass*>(this)->BlockStmt_Visit ## CLASS(static_cast<CLASS*>(S)); 28 29 #define DEFAULT_BLOCKSTMT_VISIT(CLASS) RetTy BlockStmt_Visit ## CLASS(CLASS *S)\ 30 { return\ 31 static_cast<ImplClass*>(this)->BlockStmt_VisitImplicitControlFlowExpr(\ 32 cast<Expr>(S)); } 33 34 template <typename ImplClass, typename RetTy=void> 35 class CFGStmtVisitor : public StmtVisitor<ImplClass,RetTy> { 36 Stmt* CurrentBlkStmt; 37 38 struct NullifyStmt { 39 Stmt*& S; 40 NullifyStmtNullifyStmt41 NullifyStmt(Stmt*& s) : S(s) {} ~NullifyStmtNullifyStmt42 ~NullifyStmt() { S = NULL; } 43 }; 44 45 public: CFGStmtVisitor()46 CFGStmtVisitor() : CurrentBlkStmt(NULL) {} 47 getCurrentBlkStmt()48 Stmt* getCurrentBlkStmt() const { return CurrentBlkStmt; } 49 Visit(Stmt * S)50 RetTy Visit(Stmt* S) { 51 if (S == CurrentBlkStmt || 52 !static_cast<ImplClass*>(this)->getCFG().isBlkExpr(S)) 53 return StmtVisitor<ImplClass,RetTy>::Visit(S); 54 else 55 return RetTy(); 56 } 57 58 /// VisitConditionVariableInit - Handle the initialization of condition 59 /// variables at branches. Valid statements include IfStmt, ForStmt, 60 /// WhileStmt, and SwitchStmt. VisitConditionVariableInit(Stmt * S)61 RetTy VisitConditionVariableInit(Stmt *S) { 62 return RetTy(); 63 } 64 65 /// BlockVisit_XXX - Visitor methods for visiting the "root" statements in 66 /// CFGBlocks. Root statements are the statements that appear explicitly in 67 /// the list of statements in a CFGBlock. For substatements, or when there 68 /// is no implementation provided for a BlockStmt_XXX method, we default 69 /// to using StmtVisitor's Visit method. BlockStmt_Visit(Stmt * S)70 RetTy BlockStmt_Visit(Stmt* S) { 71 CurrentBlkStmt = S; 72 NullifyStmt cleanup(CurrentBlkStmt); 73 74 switch (S->getStmtClass()) { 75 case Stmt::IfStmtClass: 76 case Stmt::ForStmtClass: 77 case Stmt::WhileStmtClass: 78 case Stmt::SwitchStmtClass: 79 return static_cast<ImplClass*>(this)->VisitConditionVariableInit(S); 80 81 DISPATCH_CASE(StmtExpr) 82 DISPATCH_CASE(ConditionalOperator) 83 DISPATCH_CASE(BinaryConditionalOperator) 84 DISPATCH_CASE(ObjCForCollectionStmt) 85 DISPATCH_CASE(CXXForRangeStmt) 86 87 case Stmt::BinaryOperatorClass: { 88 BinaryOperator* B = cast<BinaryOperator>(S); 89 if (B->isLogicalOp()) 90 return static_cast<ImplClass*>(this)->BlockStmt_VisitLogicalOp(B); 91 else if (B->getOpcode() == BO_Comma) 92 return static_cast<ImplClass*>(this)->BlockStmt_VisitComma(B); 93 // Fall through. 94 } 95 96 default: 97 if (isa<Expr>(S)) 98 return 99 static_cast<ImplClass*>(this)->BlockStmt_VisitExpr(cast<Expr>(S)); 100 else 101 return static_cast<ImplClass*>(this)->BlockStmt_VisitStmt(S); 102 } 103 } 104 105 DEFAULT_BLOCKSTMT_VISIT(StmtExpr) DEFAULT_BLOCKSTMT_VISIT(ConditionalOperator)106 DEFAULT_BLOCKSTMT_VISIT(ConditionalOperator) 107 DEFAULT_BLOCKSTMT_VISIT(BinaryConditionalOperator) 108 109 RetTy BlockStmt_VisitObjCForCollectionStmt(ObjCForCollectionStmt* S) { 110 return static_cast<ImplClass*>(this)->BlockStmt_VisitStmt(S); 111 } 112 BlockStmt_VisitCXXForRangeStmt(CXXForRangeStmt * S)113 RetTy BlockStmt_VisitCXXForRangeStmt(CXXForRangeStmt* S) { 114 return static_cast<ImplClass*>(this)->BlockStmt_VisitStmt(S); 115 } 116 BlockStmt_VisitImplicitControlFlowExpr(Expr * E)117 RetTy BlockStmt_VisitImplicitControlFlowExpr(Expr* E) { 118 return static_cast<ImplClass*>(this)->BlockStmt_VisitExpr(E); 119 } 120 BlockStmt_VisitExpr(Expr * E)121 RetTy BlockStmt_VisitExpr(Expr* E) { 122 return static_cast<ImplClass*>(this)->BlockStmt_VisitStmt(E); 123 } 124 BlockStmt_VisitStmt(Stmt * S)125 RetTy BlockStmt_VisitStmt(Stmt* S) { 126 return static_cast<ImplClass*>(this)->Visit(S); 127 } 128 BlockStmt_VisitLogicalOp(BinaryOperator * B)129 RetTy BlockStmt_VisitLogicalOp(BinaryOperator* B) { 130 return 131 static_cast<ImplClass*>(this)->BlockStmt_VisitImplicitControlFlowExpr(B); 132 } 133 BlockStmt_VisitComma(BinaryOperator * B)134 RetTy BlockStmt_VisitComma(BinaryOperator* B) { 135 return 136 static_cast<ImplClass*>(this)->BlockStmt_VisitImplicitControlFlowExpr(B); 137 } 138 139 //===--------------------------------------------------------------------===// 140 // Utility methods. Not called by default (but subclasses may use them). 141 //===--------------------------------------------------------------------===// 142 143 /// VisitChildren: Call "Visit" on each child of S. VisitChildren(Stmt * S)144 void VisitChildren(Stmt* S) { 145 146 switch (S->getStmtClass()) { 147 default: 148 break; 149 150 case Stmt::StmtExprClass: { 151 CompoundStmt* CS = cast<StmtExpr>(S)->getSubStmt(); 152 if (CS->body_empty()) return; 153 static_cast<ImplClass*>(this)->Visit(CS->body_back()); 154 return; 155 } 156 157 case Stmt::BinaryOperatorClass: { 158 BinaryOperator* B = cast<BinaryOperator>(S); 159 if (B->getOpcode() != BO_Comma) break; 160 static_cast<ImplClass*>(this)->Visit(B->getRHS()); 161 return; 162 } 163 } 164 165 for (Stmt::child_range I = S->children(); I; ++I) 166 if (*I) static_cast<ImplClass*>(this)->Visit(*I); 167 } 168 }; 169 170 #undef DEFAULT_BLOCKSTMT_VISIT 171 #undef DISPATCH_CASE 172 173 } // end namespace clang 174 175 #endif 176