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