CheckerContext.h revision f05aac8472d8ed081a361a218fd14d59ddc91b85
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  const ProgramPoint Location;
31  const ProgramState *ST;
32  const unsigned size;
33  NodeBuilder NB;
34public:
35  bool *respondsToCallback;
36public:
37  CheckerContext(ExplodedNodeSet &dst,
38                 StmtNodeBuilder &builder,
39                 ExprEngine &eng,
40                 ExplodedNode *pred,
41                 const ProgramPoint &loc,
42                 bool *respondsToCB = 0,
43                 const ProgramState *st = 0)
44    : Dst(dst),
45      B(builder),
46      Eng(eng),
47      Pred(pred),
48      Location(loc),
49      ST(st),
50      size(Dst.size()),
51      NB(builder.Eng, pred),
52      respondsToCallback(respondsToCB) {
53    assert(!(ST && ST != Pred->getState()));
54  }
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  ExplodedNode *&getPredecessor() { return Pred; }
75  const ProgramState *getState() { return ST ? ST : Pred->getState(); }
76
77  /// \brief Returns the number of times the current block has been visited
78  /// along the analyzed path.
79  unsigned getCurrentBlockCount() {return B.getCurrentBlockCount();}
80
81  ASTContext &getASTContext() {
82    return Eng.getContext();
83  }
84
85  BugReporter &getBugReporter() {
86    return Eng.getBugReporter();
87  }
88
89  SourceManager &getSourceManager() {
90    return getBugReporter().getSourceManager();
91  }
92
93  SValBuilder &getSValBuilder() {
94    return Eng.getSValBuilder();
95  }
96
97  SymbolManager &getSymbolManager() {
98    return getSValBuilder().getSymbolManager();
99  }
100
101  bool isObjCGCEnabled() {
102    return Eng.isObjCGCEnabled();
103  }
104
105  /// \brief Generate a default checker node (containing checker tag but no
106  /// checker state changes).
107  ExplodedNode *generateNode(bool autoTransition = true) {
108    return generateNode(getState(), autoTransition);
109  }
110
111  /// \brief Generate a new checker node with the given predecessor.
112  /// Allows checkers to generate a chain of nodes.
113  ExplodedNode *generateNode(const ProgramState *state,
114                             ExplodedNode *pred,
115                             const ProgramPointTag *tag = 0,
116                             bool autoTransition = true,
117                             bool isSink = false) {
118    ExplodedNode *N = generateNodeImpl(state, isSink, pred, tag);
119    return N;
120  }
121
122  /// \brief Generate a new checker node.
123  ExplodedNode *generateNode(const ProgramState *state,
124                             bool autoTransition = true,
125                             const ProgramPointTag *tag = 0) {
126    ExplodedNode *N = generateNodeImpl(state, false, 0, tag);
127    return N;
128  }
129
130  /// \brief Generate a sink node. Generating sink stops exploration of the
131  /// given path.
132  ExplodedNode *generateSink(const ProgramState *state = 0) {
133    return generateNodeImpl(state ? state : getState(), true);
134  }
135
136  void addTransition(const ProgramState *state,
137                     const ProgramPointTag *tag = 0) {
138    assert(state);
139    // If the 'state' is not new, we need to check if the cached state 'ST'
140    // is new.
141    if (state != getState())
142      generateNode(state, true, tag);
143  }
144
145  void EmitReport(BugReport *R) {
146    Eng.getBugReporter().EmitReport(R);
147  }
148
149  AnalysisContext *getCurrentAnalysisContext() const {
150    return Pred->getLocationContext()->getAnalysisContext();
151  }
152
153private:
154  ExplodedNode *generateNodeImpl(const ProgramState *state,
155                                 bool markAsSink,
156                                 ExplodedNode *pred = 0,
157                                 const ProgramPointTag *tag = 0) {
158
159    ExplodedNode *node = NB.generateNode(tag ? Location.withTag(tag) : Location,
160                                        state,
161                                        pred ? pred : Pred, markAsSink);
162    return node;
163  }
164};
165
166} // end GR namespace
167
168} // end clang namespace
169
170#endif
171