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