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