CheckerContext.h revision 5ac1df3e15f91ed663826faec7efe2462c18d98c
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#include "llvm/ADT/ImmutableMap.h"
20
21// Declare an immutable map suitable for placement into program states's GDM.
22#define REGISTER_MAP_WITH_GDM(Map, Key, Value) \
23  typedef llvm::ImmutableMap<Key, Value> Map; \
24  namespace clang { \
25  namespace ento { \
26    template <> \
27    struct ProgramStateTrait<Map> \
28      : public ProgramStatePartialTrait<Map> { \
29      static void *GDMIndex() { static int Index; return &Index; } \
30    }; \
31  } \
32  }
33
34
35namespace clang {
36namespace ento {
37
38class CheckerContext {
39  ExprEngine &Eng;
40  /// The current exploded(symbolic execution) graph node.
41  ExplodedNode *Pred;
42  /// The flag is true if the (state of the execution) has been modified
43  /// by the checker using this context. For example, a new transition has been
44  /// added or a bug report issued.
45  bool Changed;
46  /// The tagged location, which is used to generate all new nodes.
47  const ProgramPoint Location;
48  NodeBuilder &NB;
49
50public:
51  /// If we are post visiting a call, this flag will be set if the
52  /// call was inlined.  In all other cases it will be false.
53  const bool wasInlined;
54
55  CheckerContext(NodeBuilder &builder,
56                 ExprEngine &eng,
57                 ExplodedNode *pred,
58                 const ProgramPoint &loc,
59                 bool wasInlined = false)
60    : Eng(eng),
61      Pred(pred),
62      Changed(false),
63      Location(loc),
64      NB(builder),
65      wasInlined(wasInlined) {
66    assert(Pred->getState() &&
67           "We should not call the checkers on an empty state.");
68  }
69
70  AnalysisManager &getAnalysisManager() {
71    return Eng.getAnalysisManager();
72  }
73
74  ConstraintManager &getConstraintManager() {
75    return Eng.getConstraintManager();
76  }
77
78  StoreManager &getStoreManager() {
79    return Eng.getStoreManager();
80  }
81
82  const AnalyzerOptions::ConfigTable &getConfig() const {
83    return Eng.getAnalysisManager().options.Config;
84  }
85
86  /// \brief Returns the previous node in the exploded graph, which includes
87  /// the state of the program before the checker ran. Note, checkers should
88  /// not retain the node in their state since the nodes might get invalidated.
89  ExplodedNode *getPredecessor() { return Pred; }
90  ProgramStateRef getState() const { return Pred->getState(); }
91
92  /// \brief Check if the checker changed the state of the execution; ex: added
93  /// a new transition or a bug report.
94  bool isDifferent() { return Changed; }
95
96  /// \brief Returns the number of times the current block has been visited
97  /// along the analyzed path.
98  unsigned blockCount() const {
99    return NB.getContext().blockCount();
100  }
101
102  ASTContext &getASTContext() {
103    return Eng.getContext();
104  }
105
106  const LangOptions &getLangOpts() const {
107    return Eng.getContext().getLangOpts();
108  }
109
110  const LocationContext *getLocationContext() const {
111    return Pred->getLocationContext();
112  }
113
114  const StackFrameContext *getStackFrame() const {
115    return Pred->getStackFrame();
116  }
117
118  /// Returns true if the predecessor is within an inlined function/method.
119  bool isWithinInlined() {
120    return (getStackFrame()->getParent() != 0);
121  }
122
123  BugReporter &getBugReporter() {
124    return Eng.getBugReporter();
125  }
126
127  SourceManager &getSourceManager() {
128    return getBugReporter().getSourceManager();
129  }
130
131  SValBuilder &getSValBuilder() {
132    return Eng.getSValBuilder();
133  }
134
135  SymbolManager &getSymbolManager() {
136    return getSValBuilder().getSymbolManager();
137  }
138
139  bool isObjCGCEnabled() const {
140    return Eng.isObjCGCEnabled();
141  }
142
143  ProgramStateManager &getStateManager() {
144    return Eng.getStateManager();
145  }
146
147  AnalysisDeclContext *getCurrentAnalysisDeclContext() const {
148    return Pred->getLocationContext()->getAnalysisDeclContext();
149  }
150
151  /// \brief If the given node corresponds to a PostStore program point, retrieve
152  /// the location region as it was uttered in the code.
153  ///
154  /// This utility can be useful for generating extensive diagnostics, for
155  /// example, for finding variables that the given symbol was assigned to.
156  static const MemRegion *getLocationRegionIfPostStore(const ExplodedNode *N) {
157    ProgramPoint L = N->getLocation();
158    if (const PostStore *PSL = dyn_cast<PostStore>(&L))
159      return reinterpret_cast<const MemRegion*>(PSL->getLocationValue());
160    return 0;
161  }
162
163  /// \brief Get the value of arbitrary expressions at this point in the path.
164  SVal getSVal(const Stmt *S) const {
165    return getState()->getSVal(S, getLocationContext());
166  }
167
168  /// \brief Generates a new transition in the program state graph
169  /// (ExplodedGraph). Uses the default CheckerContext predecessor node.
170  ///
171  /// @param State The state of the generated node. If not specified, the state
172  ///        will not be changed, but the new node will have the checker's tag.
173  /// @param Tag The tag is used to uniquely identify the creation site. If no
174  ///        tag is specified, a default tag, unique to the given checker,
175  ///        will be used. Tags are used to prevent states generated at
176  ///        different sites from caching out.
177  ExplodedNode *addTransition(ProgramStateRef State = 0,
178                              const ProgramPointTag *Tag = 0) {
179    return addTransitionImpl(State ? State : getState(), false, 0, Tag);
180  }
181
182  /// \brief Generates a new transition with the given predecessor.
183  /// Allows checkers to generate a chain of nodes.
184  ///
185  /// @param State The state of the generated node.
186  /// @param Pred The transition will be generated from the specified Pred node
187  ///             to the newly generated node.
188  /// @param Tag The tag to uniquely identify the creation site.
189  ExplodedNode *addTransition(ProgramStateRef State,
190                              ExplodedNode *Pred,
191                              const ProgramPointTag *Tag = 0) {
192    return addTransitionImpl(State, false, Pred, Tag);
193  }
194
195  /// \brief Generate a sink node. Generating a sink stops exploration of the
196  /// given path.
197  ExplodedNode *generateSink(ProgramStateRef State = 0,
198                             ExplodedNode *Pred = 0,
199                             const ProgramPointTag *Tag = 0) {
200    return addTransitionImpl(State ? State : getState(), true, Pred, Tag);
201  }
202
203  /// \brief Emit the diagnostics report.
204  void EmitReport(BugReport *R) {
205    Changed = true;
206    Eng.getBugReporter().EmitReport(R);
207  }
208
209  /// \brief Get the declaration of the called function (path-sensitive).
210  const FunctionDecl *getCalleeDecl(const CallExpr *CE) const;
211
212  /// \brief Get the name of the called function (path-sensitive).
213  StringRef getCalleeName(const FunctionDecl *FunDecl) const;
214
215  /// \brief Get the identifier of the called function (path-sensitive).
216  const IdentifierInfo *getCalleeIdentifier(const CallExpr *CE) const {
217    const FunctionDecl *FunDecl = getCalleeDecl(CE);
218    if (FunDecl)
219      return FunDecl->getIdentifier();
220    else
221      return 0;
222  }
223
224  /// \brief Get the name of the called function (path-sensitive).
225  StringRef getCalleeName(const CallExpr *CE) const {
226    const FunctionDecl *FunDecl = getCalleeDecl(CE);
227    return getCalleeName(FunDecl);
228  }
229
230  /// Given a function declaration and a name checks if this is a C lib
231  /// function with the given name.
232  bool isCLibraryFunction(const FunctionDecl *FD, StringRef Name);
233  static bool isCLibraryFunction(const FunctionDecl *FD, StringRef Name,
234                                 ASTContext &Context);
235
236  /// \brief Depending on wither the location corresponds to a macro, return
237  /// either the macro name or the token spelling.
238  ///
239  /// This could be useful when checkers' logic depends on whether a function
240  /// is called with a given macro argument. For example:
241  ///   s = socket(AF_INET,..)
242  /// If AF_INET is a macro, the result should be treated as a source of taint.
243  ///
244  /// \sa clang::Lexer::getSpelling(), clang::Lexer::getImmediateMacroName().
245  StringRef getMacroNameOrSpelling(SourceLocation &Loc);
246
247private:
248  ExplodedNode *addTransitionImpl(ProgramStateRef State,
249                                 bool MarkAsSink,
250                                 ExplodedNode *P = 0,
251                                 const ProgramPointTag *Tag = 0) {
252    if (!State || (State == Pred->getState() && !Tag && !MarkAsSink))
253      return Pred;
254
255    Changed = true;
256    const ProgramPoint &LocalLoc = (Tag ? Location.withTag(Tag) : Location);
257    if (!P)
258      P = Pred;
259
260    ExplodedNode *node;
261    if (MarkAsSink)
262      node = NB.generateSink(LocalLoc, State, P);
263    else
264      node = NB.generateNode(LocalLoc, State, P);
265    return node;
266  }
267};
268
269/// \brief A helper class which wraps a boolean value set to false by default.
270struct DefaultBool {
271  bool Val;
272  DefaultBool() : Val(false) {}
273  operator bool() const { return Val; }
274  DefaultBool &operator=(bool b) { Val = b; return *this; }
275};
276
277} // end GR namespace
278
279} // end clang namespace
280
281#endif
282