CheckerContext.h revision 955cd444f445bcdbade1cdd3926254c8ee7890d8
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 20namespace clang { 21namespace ento { 22 23class 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 35public: 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 const StackFrameContext *getStackFrame() const { 96 return Pred->getStackFrame(); 97 } 98 99 BugReporter &getBugReporter() { 100 return Eng.getBugReporter(); 101 } 102 103 SourceManager &getSourceManager() { 104 return getBugReporter().getSourceManager(); 105 } 106 107 SValBuilder &getSValBuilder() { 108 return Eng.getSValBuilder(); 109 } 110 111 SymbolManager &getSymbolManager() { 112 return getSValBuilder().getSymbolManager(); 113 } 114 115 bool isObjCGCEnabled() const { 116 return Eng.isObjCGCEnabled(); 117 } 118 119 ProgramStateManager &getStateManager() { 120 return Eng.getStateManager(); 121 } 122 123 AnalysisDeclContext *getCurrentAnalysisDeclContext() const { 124 return Pred->getLocationContext()->getAnalysisDeclContext(); 125 } 126 127 /// \brief If the given node corresponds to a PostStore program point, retrieve 128 /// the location region as it was uttered in the code. 129 /// 130 /// This utility can be useful for generating extensive diagnostics, for 131 /// example, for finding variables that the given symbol was assigned to. 132 static const MemRegion *getLocationRegionIfPostStore(const ExplodedNode *N) { 133 ProgramPoint L = N->getLocation(); 134 if (const PostStore *PSL = dyn_cast<PostStore>(&L)) 135 return reinterpret_cast<const MemRegion*>(PSL->getLocationValue()); 136 return 0; 137 } 138 139 /// \brief Get the value of arbitrary expressions at this point in the path. 140 SVal getSVal(const Stmt *S) const { 141 return getState()->getSVal(S, getLocationContext()); 142 } 143 144 /// \brief Generates a new transition in the program state graph 145 /// (ExplodedGraph). Uses the default CheckerContext predecessor node. 146 /// 147 /// @param State The state of the generated node. 148 /// @param Tag The tag is used to uniquely identify the creation site. If no 149 /// tag is specified, a default tag, unique to the given checker, 150 /// will be used. Tags are used to prevent states generated at 151 /// different sites from caching out. 152 ExplodedNode *addTransition(ProgramStateRef State, 153 const ProgramPointTag *Tag = 0) { 154 return addTransitionImpl(State, false, 0, Tag); 155 } 156 157 /// \brief Generates a default transition (containing checker tag but no 158 /// checker state changes). 159 ExplodedNode *addTransition() { 160 return addTransition(getState()); 161 } 162 163 /// \brief Generates a new transition with the given predecessor. 164 /// Allows checkers to generate a chain of nodes. 165 /// 166 /// @param State The state of the generated node. 167 /// @param Pred The transition will be generated from the specified Pred node 168 /// to the newly generated node. 169 /// @param Tag The tag to uniquely identify the creation site. 170 /// @param IsSink Mark the new node as sink, which will stop exploration of 171 /// the given path. 172 ExplodedNode *addTransition(ProgramStateRef State, 173 ExplodedNode *Pred, 174 const ProgramPointTag *Tag = 0, 175 bool IsSink = false) { 176 return addTransitionImpl(State, IsSink, Pred, Tag); 177 } 178 179 /// \brief Generate a sink node. Generating sink stops exploration of the 180 /// given path. 181 ExplodedNode *generateSink(ProgramStateRef state = 0) { 182 return addTransitionImpl(state ? state : getState(), true); 183 } 184 185 /// \brief Emit the diagnostics report. 186 void EmitReport(BugReport *R) { 187 Changed = true; 188 Eng.getBugReporter().EmitReport(R); 189 } 190 191 /// \brief Get the declaration of the called function (path-sensitive). 192 const FunctionDecl *getCalleeDecl(const CallExpr *CE) const; 193 194 /// \brief Get the name of the called function (path-sensitive). 195 StringRef getCalleeName(const FunctionDecl *FunDecl) const; 196 197 /// \brief Get the name of the called function (path-sensitive). 198 StringRef getCalleeName(const CallExpr *CE) const { 199 const FunctionDecl *FunDecl = getCalleeDecl(CE); 200 return getCalleeName(FunDecl); 201 } 202 203 /// Given a function declaration and a name checks if this is a C lib 204 /// function with the given name. 205 bool isCLibraryFunction(const FunctionDecl *FD, StringRef Name); 206 static bool isCLibraryFunction(const FunctionDecl *FD, StringRef Name, 207 ASTContext &Context); 208 209 /// \brief Depending on wither the location corresponds to a macro, return 210 /// either the macro name or the token spelling. 211 /// 212 /// This could be useful when checkers' logic depends on whether a function 213 /// is called with a given macro argument. For example: 214 /// s = socket(AF_INET,..) 215 /// If AF_INET is a macro, the result should be treated as a source of taint. 216 /// 217 /// \sa clang::Lexer::getSpelling(), clang::Lexer::getImmediateMacroName(). 218 StringRef getMacroNameOrSpelling(SourceLocation &Loc); 219 220private: 221 ExplodedNode *addTransitionImpl(ProgramStateRef State, 222 bool MarkAsSink, 223 ExplodedNode *P = 0, 224 const ProgramPointTag *Tag = 0) { 225 if (!State || (State == Pred->getState() && !Tag && !MarkAsSink)) 226 return Pred; 227 228 Changed = true; 229 ExplodedNode *node = NB.generateNode(Tag ? Location.withTag(Tag) : Location, 230 State, 231 P ? P : Pred, MarkAsSink); 232 return node; 233 } 234}; 235 236/// \brief A helper class which wraps a boolean value set to false by default. 237struct DefaultBool { 238 bool Val; 239 DefaultBool() : Val(false) {} 240 operator bool() const { return Val; } 241 DefaultBool &operator=(bool b) { Val = b; return *this; } 242}; 243 244} // end GR namespace 245 246} // end clang namespace 247 248#endif 249