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