CheckerContext.h revision 3152b3cb5b6a2f797d0972c81a5eb3fd69c0d620
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  ExprEngine &Eng;
28  ExplodedNode *Pred;
29  const ProgramPoint Location;
30  const ProgramState *ST;
31  const unsigned size;
32  // TODO: Use global context.
33  NodeBuilderContext Ctx;
34  NodeBuilder &NB;
35public:
36  bool *respondsToCallback;
37public:
38  CheckerContext(ExplodedNodeSet &dst,
39                 NodeBuilder &builder,
40                 ExprEngine &eng,
41                 ExplodedNode *pred,
42                 const ProgramPoint &loc,
43                 bool *respondsToCB = 0,
44                 const ProgramState *st = 0)
45    : Dst(dst),
46      Eng(eng),
47      Pred(pred),
48      Location(loc),
49      ST(st),
50      size(Dst.size()),
51      Ctx(builder.C.Eng, builder.getBlock()),
52      NB(builder),
53      respondsToCallback(respondsToCB) {
54    assert(!(ST && ST != Pred->getState()));
55  }
56
57  ~CheckerContext();
58
59  ExprEngine &getEngine() {
60    return Eng;
61  }
62
63  AnalysisManager &getAnalysisManager() {
64    return Eng.getAnalysisManager();
65  }
66
67  ConstraintManager &getConstraintManager() {
68    return Eng.getConstraintManager();
69  }
70
71  StoreManager &getStoreManager() {
72    return Eng.getStoreManager();
73  }
74
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 NB.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                             bool isSink = false) {
119    ExplodedNode *N = generateNodeImpl(state, isSink, pred, tag);
120    return N;
121  }
122
123  /// \brief Generate a new checker node.
124  ExplodedNode *generateNode(const ProgramState *state,
125                             bool autoTransition = true,
126                             const ProgramPointTag *tag = 0) {
127    ExplodedNode *N = generateNodeImpl(state, false, 0, tag);
128    return N;
129  }
130
131  /// \brief Generate a sink node. Generating sink stops exploration of the
132  /// given path.
133  ExplodedNode *generateSink(const ProgramState *state = 0) {
134    return generateNodeImpl(state ? state : getState(), true);
135  }
136
137  void addTransition(const ProgramState *state,
138                     const ProgramPointTag *tag = 0) {
139    assert(state);
140    // If the 'state' is not new, we need to check if the cached state 'ST'
141    // is new.
142    if (state != getState())
143      generateNode(state, true, tag);
144  }
145
146  void EmitReport(BugReport *R) {
147    Eng.getBugReporter().EmitReport(R);
148  }
149
150  AnalysisContext *getCurrentAnalysisContext() const {
151    return Pred->getLocationContext()->getAnalysisContext();
152  }
153
154private:
155  ExplodedNode *generateNodeImpl(const ProgramState *state,
156                                 bool markAsSink,
157                                 ExplodedNode *pred = 0,
158                                 const ProgramPointTag *tag = 0) {
159
160    ExplodedNode *node = NB.generateNode(tag ? Location.withTag(tag) : Location,
161                                        state,
162                                        pred ? pred : Pred, markAsSink);
163    return node;
164  }
165};
166
167} // end GR namespace
168
169} // end clang namespace
170
171#endif
172