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