CheckerContext.h revision 461af1e502c9bd88330bbf17d449a7593fc0d624
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 LangOptions &getLangOptions() const {
71    return Eng.getContext().getLangOptions();
72  }
73
74  const LocationContext *getLocationContext() const {
75    return Pred->getLocationContext();
76  }
77
78  BugReporter &getBugReporter() {
79    return Eng.getBugReporter();
80  }
81
82  SourceManager &getSourceManager() {
83    return getBugReporter().getSourceManager();
84  }
85
86  SValBuilder &getSValBuilder() {
87    return Eng.getSValBuilder();
88  }
89
90  SymbolManager &getSymbolManager() {
91    return getSValBuilder().getSymbolManager();
92  }
93
94  bool isObjCGCEnabled() const {
95    return Eng.isObjCGCEnabled();
96  }
97
98  ProgramStateManager &getStateManager() {
99    return Eng.getStateManager();
100  }
101
102  AnalysisDeclContext *getCurrentAnalysisDeclContext() const {
103    return Pred->getLocationContext()->getAnalysisDeclContext();
104  }
105
106  /// \brief Generates a new transition in the program state graph
107  /// (ExplodedGraph). Uses the default CheckerContext predecessor node.
108  ///
109  /// @param State The state of the generated node.
110  /// @param Tag The tag is used to uniquely identify the creation site. If no
111  ///        tag is specified, a default tag, unique to the given checker,
112  ///        will be used. Tags are used to prevent states generated at
113  ///        different sites from caching out.
114  ExplodedNode *addTransition(const ProgramState *State,
115                              const ProgramPointTag *Tag = 0) {
116    return addTransitionImpl(State, false, 0, Tag);
117  }
118
119  /// \brief Generates a default transition (containing checker tag but no
120  /// checker state changes).
121  ExplodedNode *addTransition() {
122    return addTransition(getState());
123  }
124
125  /// \brief Generates a new transition with the given predecessor.
126  /// Allows checkers to generate a chain of nodes.
127  ///
128  /// @param State The state of the generated node.
129  /// @param Pred The transition will be generated from the specified Pred node
130  ///             to the newly generated node.
131  /// @param Tag The tag to uniquely identify the creation site.
132  /// @param IsSink Mark the new node as sink, which will stop exploration of
133  ///               the given path.
134  ExplodedNode *addTransition(const ProgramState *State,
135                             ExplodedNode *Pred,
136                             const ProgramPointTag *Tag = 0,
137                             bool IsSink = false) {
138    return addTransitionImpl(State, IsSink, Pred, Tag);
139  }
140
141  /// \brief Generate a sink node. Generating sink stops exploration of the
142  /// given path.
143  ExplodedNode *generateSink(const ProgramState *state = 0) {
144    return addTransitionImpl(state ? state : getState(), true);
145  }
146
147  /// \brief Emit the diagnostics report.
148  void EmitReport(BugReport *R) {
149    Eng.getBugReporter().EmitReport(R);
150  }
151
152  /// \brief Get the declaration of the called function (path-sensitive).
153  const FunctionDecl *getCalleeDecl(const CallExpr *CE) const;
154
155  /// \brief Get the name of the called function (path-sensitive).
156  StringRef getCalleeName(const FunctionDecl *FunDecl) const;
157
158  /// \brief Get the name of the called function (path-sensitive).
159  StringRef getCalleeName(const CallExpr *CE) const {
160    const FunctionDecl *FunDecl = getCalleeDecl(CE);
161    return getCalleeName(FunDecl);
162  }
163
164  /// Given a function declaration and a name checks if this is a C lib
165  /// function with the given name.
166  bool isCLibraryFunction(const FunctionDecl *FD, StringRef Name);
167
168  /// \brief Depending on wither the location corresponds to a macro, return
169  /// either the macro name or the token spelling.
170  ///
171  /// This could be useful when checkers' logic depends on whether a function
172  /// is called with a given macro argument. For example:
173  ///   s = socket(AF_INET,..)
174  /// If AF_INET is a macro, the result should be treated as a source of taint.
175  ///
176  /// \sa clang::Lexer::getSpelling(), clang::Lexer::getImmediateMacroName().
177  StringRef getMacroNameOrSpelling(SourceLocation &Loc);
178
179private:
180  ExplodedNode *addTransitionImpl(const ProgramState *State,
181                                 bool MarkAsSink,
182                                 ExplodedNode *P = 0,
183                                 const ProgramPointTag *Tag = 0) {
184    assert(State);
185    if (State == Pred->getState() && !Tag && !MarkAsSink)
186      return Pred;
187
188    ExplodedNode *node = NB.generateNode(Tag ? Location.withTag(Tag) : Location,
189                                        State,
190                                        P ? P : Pred, MarkAsSink);
191    return node;
192  }
193};
194
195} // end GR namespace
196
197} // end clang namespace
198
199#endif
200