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