• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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