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