CheckerContext.h revision 6bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89
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  /// \brief Returns the previous node in the exploded graph, which includes
115  /// the state of the program before the checker ran. Note, checkers should
116  /// not retain the node in their state since the nodes might get invalidated.
117  ExplodedNode *getPredecessor() { return Pred; }
118  const ProgramStateRef &getState() const { return Pred->getState(); }
119
120  /// \brief Check if the checker changed the state of the execution; ex: added
121  /// a new transition or a bug report.
122  bool isDifferent() { return Changed; }
123
124  /// \brief Returns the number of times the current block has been visited
125  /// along the analyzed path.
126  unsigned blockCount() const {
127    return NB.getContext().blockCount();
128  }
129
130  ASTContext &getASTContext() {
131    return Eng.getContext();
132  }
133
134  const LangOptions &getLangOpts() const {
135    return Eng.getContext().getLangOpts();
136  }
137
138  const LocationContext *getLocationContext() const {
139    return Pred->getLocationContext();
140  }
141
142  const StackFrameContext *getStackFrame() const {
143    return Pred->getStackFrame();
144  }
145
146  /// Return true if the current LocationContext has no caller context.
147  bool inTopFrame() const { return getLocationContext()->inTopFrame();  }
148
149  BugReporter &getBugReporter() {
150    return Eng.getBugReporter();
151  }
152
153  SourceManager &getSourceManager() {
154    return getBugReporter().getSourceManager();
155  }
156
157  SValBuilder &getSValBuilder() {
158    return Eng.getSValBuilder();
159  }
160
161  SymbolManager &getSymbolManager() {
162    return getSValBuilder().getSymbolManager();
163  }
164
165  bool isObjCGCEnabled() const {
166    return Eng.isObjCGCEnabled();
167  }
168
169  ProgramStateManager &getStateManager() {
170    return Eng.getStateManager();
171  }
172
173  AnalysisDeclContext *getCurrentAnalysisDeclContext() const {
174    return Pred->getLocationContext()->getAnalysisDeclContext();
175  }
176
177  /// \brief If the given node corresponds to a PostStore program point, retrieve
178  /// the location region as it was uttered in the code.
179  ///
180  /// This utility can be useful for generating extensive diagnostics, for
181  /// example, for finding variables that the given symbol was assigned to.
182  static const MemRegion *getLocationRegionIfPostStore(const ExplodedNode *N) {
183    ProgramPoint L = N->getLocation();
184    if (Optional<PostStore> PSL = L.getAs<PostStore>())
185      return reinterpret_cast<const MemRegion*>(PSL->getLocationValue());
186    return nullptr;
187  }
188
189  /// \brief Get the value of arbitrary expressions at this point in the path.
190  SVal getSVal(const Stmt *S) const {
191    return getState()->getSVal(S, getLocationContext());
192  }
193
194  /// \brief Generates a new transition in the program state graph
195  /// (ExplodedGraph). Uses the default CheckerContext predecessor node.
196  ///
197  /// @param State The state of the generated node. If not specified, the state
198  ///        will not be changed, but the new node will have the checker's tag.
199  /// @param Tag The tag is used to uniquely identify the creation site. If no
200  ///        tag is specified, a default tag, unique to the given checker,
201  ///        will be used. Tags are used to prevent states generated at
202  ///        different sites from caching out.
203  ExplodedNode *addTransition(ProgramStateRef State = nullptr,
204                              const ProgramPointTag *Tag = nullptr) {
205    return addTransitionImpl(State ? State : getState(), false, nullptr, Tag);
206  }
207
208  /// \brief Generates a new transition with the given predecessor.
209  /// Allows checkers to generate a chain of nodes.
210  ///
211  /// @param State The state of the generated node.
212  /// @param Pred The transition will be generated from the specified Pred node
213  ///             to the newly generated node.
214  /// @param Tag The tag to uniquely identify the creation site.
215  ExplodedNode *addTransition(ProgramStateRef State,
216                              ExplodedNode *Pred,
217                              const ProgramPointTag *Tag = nullptr) {
218    return addTransitionImpl(State, false, Pred, Tag);
219  }
220
221  /// \brief Generate a sink node. Generating a sink stops exploration of the
222  /// given path.
223  ExplodedNode *generateSink(ProgramStateRef State = nullptr,
224                             ExplodedNode *Pred = nullptr,
225                             const ProgramPointTag *Tag = nullptr) {
226    return addTransitionImpl(State ? State : getState(), true, Pred, Tag);
227  }
228
229  /// \brief Emit the diagnostics report.
230  void emitReport(BugReport *R) {
231    Changed = true;
232    Eng.getBugReporter().emitReport(R);
233  }
234
235  /// \brief Get the declaration of the called function (path-sensitive).
236  const FunctionDecl *getCalleeDecl(const CallExpr *CE) const;
237
238  /// \brief Get the name of the called function (path-sensitive).
239  StringRef getCalleeName(const FunctionDecl *FunDecl) const;
240
241  /// \brief Get the identifier of the called function (path-sensitive).
242  const IdentifierInfo *getCalleeIdentifier(const CallExpr *CE) const {
243    const FunctionDecl *FunDecl = getCalleeDecl(CE);
244    if (FunDecl)
245      return FunDecl->getIdentifier();
246    else
247      return nullptr;
248  }
249
250  /// \brief Get the name of the called function (path-sensitive).
251  StringRef getCalleeName(const CallExpr *CE) const {
252    const FunctionDecl *FunDecl = getCalleeDecl(CE);
253    return getCalleeName(FunDecl);
254  }
255
256  /// \brief Returns true if the callee is an externally-visible function in the
257  /// top-level namespace, such as \c malloc.
258  ///
259  /// If a name is provided, the function must additionally match the given
260  /// name.
261  ///
262  /// Note that this deliberately excludes C++ library functions in the \c std
263  /// namespace, but will include C library functions accessed through the
264  /// \c std namespace. This also does not check if the function is declared
265  /// as 'extern "C"', or if it uses C++ name mangling.
266  static bool isCLibraryFunction(const FunctionDecl *FD,
267                                 StringRef Name = StringRef());
268
269  /// \brief Depending on wither the location corresponds to a macro, return
270  /// either the macro name or the token spelling.
271  ///
272  /// This could be useful when checkers' logic depends on whether a function
273  /// is called with a given macro argument. For example:
274  ///   s = socket(AF_INET,..)
275  /// If AF_INET is a macro, the result should be treated as a source of taint.
276  ///
277  /// \sa clang::Lexer::getSpelling(), clang::Lexer::getImmediateMacroName().
278  StringRef getMacroNameOrSpelling(SourceLocation &Loc);
279
280private:
281  ExplodedNode *addTransitionImpl(ProgramStateRef State,
282                                 bool MarkAsSink,
283                                 ExplodedNode *P = nullptr,
284                                 const ProgramPointTag *Tag = nullptr) {
285    if (!State || (State == Pred->getState() && !Tag && !MarkAsSink))
286      return Pred;
287
288    Changed = true;
289    const ProgramPoint &LocalLoc = (Tag ? Location.withTag(Tag) : Location);
290    if (!P)
291      P = Pred;
292
293    ExplodedNode *node;
294    if (MarkAsSink)
295      node = NB.generateSink(LocalLoc, State, P);
296    else
297      node = NB.generateNode(LocalLoc, State, P);
298    return node;
299  }
300};
301
302} // end GR namespace
303
304} // end clang namespace
305
306#endif
307