CheckerContext.h revision 9b0c749a20d0f7d0e63441d76baa15def3f37fdb
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/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
19
20namespace clang {
21namespace ento {
22
23class CheckerContext {
24  ExprEngine &Eng;
25  ExplodedNode *Pred;
26  const ProgramPoint Location;
27  NodeBuilder &NB;
28
29public:
30  CheckerContext(NodeBuilder &builder,
31                 ExprEngine &eng,
32                 ExplodedNode *pred,
33                 const ProgramPoint &loc)
34    : Eng(eng),
35      Pred(pred),
36      Location(loc),
37      NB(builder) {
38    assert(Pred->getState() &&
39           "We should not call the checkers on an empty state.");
40  }
41
42  AnalysisManager &getAnalysisManager() {
43    return Eng.getAnalysisManager();
44  }
45
46  ConstraintManager &getConstraintManager() {
47    return Eng.getConstraintManager();
48  }
49
50  StoreManager &getStoreManager() {
51    return Eng.getStoreManager();
52  }
53
54  /// \brief Returns the previous node in the exploded graph, which includes
55  /// the state of the program before the checker ran. Note, checkers should
56  /// not retain the node in their state since the nodes might get invalidated.
57  ExplodedNode *getPredecessor() { return Pred; }
58  const ProgramState *getState() const { return Pred->getState(); }
59
60  /// \brief Returns the number of times the current block has been visited
61  /// along the analyzed path.
62  unsigned getCurrentBlockCount() const {
63    return NB.getContext().getCurrentBlockCount();
64  }
65
66  ASTContext &getASTContext() {
67    return Eng.getContext();
68  }
69
70  const LocationContext *getLocationContext() const {
71    return Pred->getLocationContext();
72  }
73
74  BugReporter &getBugReporter() {
75    return Eng.getBugReporter();
76  }
77
78  SourceManager &getSourceManager() {
79    return getBugReporter().getSourceManager();
80  }
81
82  SValBuilder &getSValBuilder() {
83    return Eng.getSValBuilder();
84  }
85
86  SymbolManager &getSymbolManager() {
87    return getSValBuilder().getSymbolManager();
88  }
89
90  bool isObjCGCEnabled() const {
91    return Eng.isObjCGCEnabled();
92  }
93
94  ProgramStateManager &getStateManager() {
95    return Eng.getStateManager();
96  }
97
98  AnalysisDeclContext *getCurrentAnalysisDeclContext() const {
99    return Pred->getLocationContext()->getAnalysisDeclContext();
100  }
101
102  /// \brief Generates a new transition in the program state graph
103  /// (ExplodedGraph). Uses the default CheckerContext predecessor node.
104  ///
105  /// @param State The state of the generated node.
106  /// @param Tag The tag is used to uniquely identify the creation site. If no
107  ///        tag is specified, a default tag, unique to the given checker,
108  ///        will be used. Tags are used to prevent states generated at
109  ///        different sites from caching out.
110  ExplodedNode *addTransition(const ProgramState *State,
111                              const ProgramPointTag *Tag = 0) {
112    return addTransitionImpl(State, false, 0, Tag);
113  }
114
115  /// \brief Generates a default transition (containing checker tag but no
116  /// checker state changes).
117  ExplodedNode *addTransition() {
118    return addTransition(getState());
119  }
120
121  /// \brief Generates a new transition with the given predecessor.
122  /// Allows checkers to generate a chain of nodes.
123  ///
124  /// @param State The state of the generated node.
125  /// @param Pred The transition will be generated from the specified Pred node
126  ///             to the newly generated node.
127  /// @param Tag The tag to uniquely identify the creation site.
128  /// @param IsSink Mark the new node as sink, which will stop exploration of
129  ///               the given path.
130  ExplodedNode *addTransition(const ProgramState *State,
131                             ExplodedNode *Pred,
132                             const ProgramPointTag *Tag = 0,
133                             bool IsSink = false) {
134    return addTransitionImpl(State, IsSink, Pred, Tag);
135  }
136
137  /// \brief Generate a sink node. Generating sink stops exploration of the
138  /// given path.
139  ExplodedNode *generateSink(const ProgramState *state = 0) {
140    return addTransitionImpl(state ? state : getState(), true);
141  }
142
143  /// \brief Emit the diagnostics report.
144  void EmitReport(BugReport *R) {
145    Eng.getBugReporter().EmitReport(R);
146  }
147
148  /// \brief Get the declaration of the called function (path-sensitive).
149  const FunctionDecl *getCalleeDecl(const CallExpr *CE) const;
150
151  /// \brief Get the name of the called function (path-sensitive).
152  StringRef getCalleeName(const FunctionDecl *FunDecl) const;
153
154  /// \brief Get the name of the called function (path-sensitive).
155  StringRef getCalleeName(const CallExpr *CE) const {
156    const FunctionDecl *FunDecl = getCalleeDecl(CE);
157    return getCalleeName(FunDecl);
158  }
159
160  /// Given a function declaration and a name checks if this is a C lib
161  /// function with the given name.
162  bool isCLibraryFunction(const FunctionDecl *FD, StringRef Name);
163
164private:
165  ExplodedNode *addTransitionImpl(const ProgramState *State,
166                                 bool MarkAsSink,
167                                 ExplodedNode *P = 0,
168                                 const ProgramPointTag *Tag = 0) {
169    assert(State);
170    if (State == Pred->getState() && !Tag && !MarkAsSink)
171      return Pred;
172
173    ExplodedNode *node = NB.generateNode(Tag ? Location.withTag(Tag) : Location,
174                                        State,
175                                        P ? P : Pred, MarkAsSink);
176    return node;
177  }
178};
179
180} // end GR namespace
181
182} // end clang namespace
183
184#endif
185