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