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