CheckerContext.h revision 3f5e8d87dbf449d8b39fe96068415428594d370e
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
21namespace clang {
22
23namespace ento {
24
25class CheckerContext {
26  ExplodedNodeSet &Dst;
27  StmtNodeBuilder &B;
28  ExprEngine &Eng;
29  ExplodedNode *Pred;
30  SaveAndRestore<bool> OldSink;
31  SaveOr OldHasGen;
32  const ProgramPoint Location;
33  const ProgramState *ST;
34  const unsigned size;
35public:
36  bool *respondsToCallback;
37public:
38  CheckerContext(ExplodedNodeSet &dst,
39                 StmtNodeBuilder &builder,
40                 ExprEngine &eng,
41                 ExplodedNode *pred,
42                 const ProgramPoint &loc,
43                 bool *respondsToCB = 0,
44                 const ProgramState *st = 0)
45    : Dst(dst),
46      B(builder),
47      Eng(eng),
48      Pred(pred),
49      OldSink(B.BuildSinks),
50      OldHasGen(B.hasGeneratedNode),
51      Location(loc),
52      ST(st),
53      size(Dst.size()),
54      respondsToCallback(respondsToCB) {}
55
56  ~CheckerContext();
57
58  ExprEngine &getEngine() {
59    return Eng;
60  }
61
62  AnalysisManager &getAnalysisManager() {
63    return Eng.getAnalysisManager();
64  }
65
66  ConstraintManager &getConstraintManager() {
67    return Eng.getConstraintManager();
68  }
69
70  StoreManager &getStoreManager() {
71    return Eng.getStoreManager();
72  }
73
74  ExplodedNodeSet &getNodeSet() { return Dst; }
75  ExplodedNode *&getPredecessor() { return Pred; }
76  const ProgramState *getState() { return ST ? ST : Pred->getState(); }
77
78  /// \brief Returns the number of times the current block has been visited
79  /// along the analyzed path.
80  unsigned getCurrentBlockCount() {return B.getCurrentBlockCount();}
81
82  ASTContext &getASTContext() {
83    return Eng.getContext();
84  }
85
86  BugReporter &getBugReporter() {
87    return Eng.getBugReporter();
88  }
89
90  SourceManager &getSourceManager() {
91    return getBugReporter().getSourceManager();
92  }
93
94  SValBuilder &getSValBuilder() {
95    return Eng.getSValBuilder();
96  }
97
98  SymbolManager &getSymbolManager() {
99    return getSValBuilder().getSymbolManager();
100  }
101
102  bool isObjCGCEnabled() {
103    return Eng.isObjCGCEnabled();
104  }
105
106  /// \brief Generate a default checker node (containing checker tag but no
107  /// checker state changes).
108  ExplodedNode *generateNode(bool autoTransition = true) {
109    return generateNode(getState(), autoTransition);
110  }
111
112  /// \brief Generate a new checker node with the given predecessor.
113  /// Allows checkers to generate a chain of nodes.
114  ExplodedNode *generateNode(const ProgramState *state,
115                             ExplodedNode *pred,
116                             const ProgramPointTag *tag = 0,
117                             bool autoTransition = true) {
118    ExplodedNode *N = generateNodeImpl(state, false, pred, tag);
119    if (N && autoTransition)
120      addTransition(N);
121    return N;
122  }
123
124  /// \brief Generate a new checker node.
125  ExplodedNode *generateNode(const ProgramState *state,
126                             bool autoTransition = true,
127                             const ProgramPointTag *tag = 0) {
128    ExplodedNode *N = generateNodeImpl(state, false, 0, tag);
129    if (N && autoTransition)
130      addTransition(N);
131    return N;
132  }
133
134  /// \brief Generate a sink node. Generating sink stops exploration of the
135  /// given path.
136  ExplodedNode *generateSink(const ProgramState *state = 0) {
137    return generateNodeImpl(state ? state : getState(), true);
138  }
139
140  void addTransition(ExplodedNode *node) {
141    Dst.Add(node);
142  }
143
144  void addTransition(const ProgramState *state,
145                     const ProgramPointTag *tag = 0) {
146    assert(state);
147    // If the 'state' is not new, we need to check if the cached state 'ST'
148    // is new.
149    if (state != getState() || (ST && ST != Pred->getState()))
150      // state is new or equals to ST.
151      generateNode(state, true, tag);
152    else
153      Dst.Add(Pred);
154  }
155
156  void EmitReport(BugReport *R) {
157    Eng.getBugReporter().EmitReport(R);
158  }
159
160  AnalysisContext *getCurrentAnalysisContext() const {
161    return Pred->getLocationContext()->getAnalysisContext();
162  }
163
164private:
165  ExplodedNode *generateNodeImpl(const ProgramState *state,
166                                 bool markAsSink,
167                                 ExplodedNode *pred = 0,
168                                 const ProgramPointTag *tag = 0) {
169
170    ExplodedNode *node = B.generateNode(tag ? Location.withTag(tag) : Location,
171                                        state,
172                                        pred ? pred : Pred);
173    if (markAsSink && node)
174      node->markAsSink();
175    return node;
176  }
177};
178
179} // end GR namespace
180
181} // end clang namespace
182
183#endif
184