• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //== CheckerContext.h - Context info for path-sensitive checkers--*- 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 CheckerContext that provides contextual info for
11 // path-sensitive checkers.
12 //
13 //===----------------------------------------------------------------------===//
14 
15 #ifndef LLVM_CLANG_SA_CORE_PATHSENSITIVE_CHECKERCONTEXT
16 #define LLVM_CLANG_SA_CORE_PATHSENSITIVE_CHECKERCONTEXT
17 
18 #include "clang/Analysis/Support/SaveAndRestore.h"
19 #include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
20 
21 namespace clang {
22 
23 namespace ento {
24 
25 class CheckerContext {
26   ExplodedNodeSet &Dst;
27   StmtNodeBuilder &B;
28   ExprEngine &Eng;
29   ExplodedNode *Pred;
30   SaveAndRestore<bool> OldSink;
31   const void *checkerTag;
32   SaveAndRestore<ProgramPoint::Kind> OldPointKind;
33   SaveOr OldHasGen;
34   const GRState *ST;
35   const Stmt *statement;
36   const unsigned size;
37 public:
38   bool *respondsToCallback;
39 public:
40   CheckerContext(ExplodedNodeSet &dst, StmtNodeBuilder &builder,
41                  ExprEngine &eng, ExplodedNode *pred,
42                  const void *tag, ProgramPoint::Kind K,
43                  bool *respondsToCB = 0,
44                  const Stmt *stmt = 0, const GRState *st = 0)
Dst(dst)45     : Dst(dst), B(builder), Eng(eng), Pred(pred),
46       OldSink(B.BuildSinks),
47       checkerTag(tag),
48       OldPointKind(B.PointKind, K),
49       OldHasGen(B.hasGeneratedNode),
50       ST(st), statement(stmt), size(Dst.size()),
51       respondsToCallback(respondsToCB) {}
52 
53   ~CheckerContext();
54 
getEngine()55   ExprEngine &getEngine() {
56     return Eng;
57   }
58 
getAnalysisManager()59   AnalysisManager &getAnalysisManager() {
60     return Eng.getAnalysisManager();
61   }
62 
getConstraintManager()63   ConstraintManager &getConstraintManager() {
64     return Eng.getConstraintManager();
65   }
66 
getStoreManager()67   StoreManager &getStoreManager() {
68     return Eng.getStoreManager();
69   }
70 
getNodeSet()71   ExplodedNodeSet &getNodeSet() { return Dst; }
getNodeBuilder()72   StmtNodeBuilder &getNodeBuilder() { return B; }
getPredecessor()73   ExplodedNode *&getPredecessor() { return Pred; }
getState()74   const GRState *getState() { return ST ? ST : B.GetState(Pred); }
getStmt()75   const Stmt *getStmt() const { return statement; }
76 
getASTContext()77   ASTContext &getASTContext() {
78     return Eng.getContext();
79   }
80 
getBugReporter()81   BugReporter &getBugReporter() {
82     return Eng.getBugReporter();
83   }
84 
getSourceManager()85   SourceManager &getSourceManager() {
86     return getBugReporter().getSourceManager();
87   }
88 
getSValBuilder()89   SValBuilder &getSValBuilder() {
90     return Eng.getSValBuilder();
91   }
92 
93   ExplodedNode *generateNode(bool autoTransition = true) {
94     assert(statement && "Only transitions with statements currently supported");
95     ExplodedNode *N = generateNodeImpl(statement, getState(), false,
96                                        checkerTag);
97     if (N && autoTransition)
98       Dst.Add(N);
99     return N;
100   }
101 
102   ExplodedNode *generateNode(const Stmt *stmt, const GRState *state,
103                              bool autoTransition = true, const void *tag = 0) {
104     assert(state);
105     ExplodedNode *N = generateNodeImpl(stmt, state, false,
106                                        tag ? tag : checkerTag);
107     if (N && autoTransition)
108       addTransition(N);
109     return N;
110   }
111 
112   ExplodedNode *generateNode(const GRState *state, ExplodedNode *pred,
113                              bool autoTransition = true) {
114    assert(statement && "Only transitions with statements currently supported");
115     ExplodedNode *N = generateNodeImpl(statement, state, pred, false);
116     if (N && autoTransition)
117       addTransition(N);
118     return N;
119   }
120 
121   ExplodedNode *generateNode(const GRState *state, bool autoTransition = true,
122                              const void *tag = 0) {
123     assert(statement && "Only transitions with statements currently supported");
124     ExplodedNode *N = generateNodeImpl(statement, state, false,
125                                        tag ? tag : checkerTag);
126     if (N && autoTransition)
127       addTransition(N);
128     return N;
129   }
130 
131   ExplodedNode *generateSink(const Stmt *stmt, const GRState *state = 0) {
132     return generateNodeImpl(stmt, state ? state : getState(), true,
133                             checkerTag);
134   }
135 
136   ExplodedNode *generateSink(const GRState *state = 0) {
137     assert(statement && "Only transitions with statements currently supported");
138     return generateNodeImpl(statement, state ? state : getState(), true,
139                             checkerTag);
140   }
141 
addTransition(ExplodedNode * node)142   void addTransition(ExplodedNode *node) {
143     Dst.Add(node);
144   }
145 
146   void addTransition(const GRState *state, const void *tag = 0) {
147     assert(state);
148     // If the 'state' is not new, we need to check if the cached state 'ST'
149     // is new.
150     if (state != getState() || (ST && ST != B.GetState(Pred)))
151       // state is new or equals to ST.
152       generateNode(state, true, tag);
153     else
154       Dst.Add(Pred);
155   }
156 
EmitReport(BugReport * R)157   void EmitReport(BugReport *R) {
158     Eng.getBugReporter().EmitReport(R);
159   }
160 
getCurrentAnalysisContext()161   AnalysisContext *getCurrentAnalysisContext() const {
162     return Pred->getLocationContext()->getAnalysisContext();
163   }
164 
165 private:
generateNodeImpl(const Stmt * stmt,const GRState * state,bool markAsSink,const void * tag)166   ExplodedNode *generateNodeImpl(const Stmt* stmt, const GRState *state,
167                              bool markAsSink, const void *tag) {
168     ExplodedNode *node = B.generateNode(stmt, state, Pred, tag);
169     if (markAsSink && node)
170       node->markAsSink();
171     return node;
172   }
173 
generateNodeImpl(const Stmt * stmt,const GRState * state,ExplodedNode * pred,bool markAsSink)174   ExplodedNode *generateNodeImpl(const Stmt* stmt, const GRState *state,
175                                  ExplodedNode *pred, bool markAsSink) {
176    ExplodedNode *node = B.generateNode(stmt, state, pred, checkerTag);
177     if (markAsSink && node)
178       node->markAsSink();
179     return node;
180   }
181 };
182 
183 } // end GR namespace
184 
185 } // end clang namespace
186 
187 #endif
188