]> CyberLeo.Net >> Repos - FreeBSD/stable/9.git/blob - contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h
Copy head to stable/9 as part of 9.0-RELEASE release cycle.
[FreeBSD/stable/9.git] / contrib / llvm / tools / clang / include / clang / StaticAnalyzer / Core / PathSensitive / CheckerContext.h
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)
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
55   ExprEngine &getEngine() {
56     return Eng;
57   }
58
59   AnalysisManager &getAnalysisManager() {
60     return Eng.getAnalysisManager();
61   }
62
63   ConstraintManager &getConstraintManager() {
64     return Eng.getConstraintManager();
65   }
66
67   StoreManager &getStoreManager() {
68     return Eng.getStoreManager();
69   }
70
71   ExplodedNodeSet &getNodeSet() { return Dst; }
72   StmtNodeBuilder &getNodeBuilder() { return B; }
73   ExplodedNode *&getPredecessor() { return Pred; }
74   const GRState *getState() { return ST ? ST : B.GetState(Pred); }
75   const Stmt *getStmt() const { return statement; }
76
77   ASTContext &getASTContext() {
78     return Eng.getContext();
79   }
80   
81   BugReporter &getBugReporter() {
82     return Eng.getBugReporter();
83   }
84   
85   SourceManager &getSourceManager() {
86     return getBugReporter().getSourceManager();
87   }
88
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
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
157   void EmitReport(BugReport *R) {
158     Eng.getBugReporter().EmitReport(R);
159   }
160
161   AnalysisContext *getCurrentAnalysisContext() const {
162     return Pred->getLocationContext()->getAnalysisContext();
163   }
164
165 private:
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
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