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/Analysis/Support/SaveAndRestore.h" 19 #include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h" 20 21 namespace clang { 22 23 namespace ento { 24 25 class CheckerContext { 26 ExplodedNodeSet &Dst; 27 StmtNodeBuilder &B; 28 ExprEngine &Eng; 29 ExplodedNode *Pred; 30 SaveAndRestore<bool> OldSink; 31 const void *checkerTag; 32 SaveAndRestore<ProgramPoint::Kind> OldPointKind; 33 SaveOr OldHasGen; 34 const GRState *ST; 35 const Stmt *statement; 36 const unsigned size; 37 public: 38 bool *respondsToCallback; 39 public: 40 CheckerContext(ExplodedNodeSet &dst, StmtNodeBuilder &builder, 41 ExprEngine &eng, ExplodedNode *pred, 42 const void *tag, ProgramPoint::Kind K, 43 bool *respondsToCB = 0, 44 const Stmt *stmt = 0, const GRState *st = 0) Dst(dst)45 : Dst(dst), B(builder), Eng(eng), Pred(pred), 46 OldSink(B.BuildSinks), 47 checkerTag(tag), 48 OldPointKind(B.PointKind, K), 49 OldHasGen(B.hasGeneratedNode), 50 ST(st), statement(stmt), size(Dst.size()), 51 respondsToCallback(respondsToCB) {} 52 53 ~CheckerContext(); 54 getEngine()55 ExprEngine &getEngine() { 56 return Eng; 57 } 58 getAnalysisManager()59 AnalysisManager &getAnalysisManager() { 60 return Eng.getAnalysisManager(); 61 } 62 getConstraintManager()63 ConstraintManager &getConstraintManager() { 64 return Eng.getConstraintManager(); 65 } 66 getStoreManager()67 StoreManager &getStoreManager() { 68 return Eng.getStoreManager(); 69 } 70 getNodeSet()71 ExplodedNodeSet &getNodeSet() { return Dst; } getNodeBuilder()72 StmtNodeBuilder &getNodeBuilder() { return B; } getPredecessor()73 ExplodedNode *&getPredecessor() { return Pred; } getState()74 const GRState *getState() { return ST ? ST : B.GetState(Pred); } getStmt()75 const Stmt *getStmt() const { return statement; } 76 getASTContext()77 ASTContext &getASTContext() { 78 return Eng.getContext(); 79 } 80 getBugReporter()81 BugReporter &getBugReporter() { 82 return Eng.getBugReporter(); 83 } 84 getSourceManager()85 SourceManager &getSourceManager() { 86 return getBugReporter().getSourceManager(); 87 } 88 getSValBuilder()89 SValBuilder &getSValBuilder() { 90 return Eng.getSValBuilder(); 91 } 92 93 ExplodedNode *generateNode(bool autoTransition = true) { 94 assert(statement && "Only transitions with statements currently supported"); 95 ExplodedNode *N = generateNodeImpl(statement, getState(), false, 96 checkerTag); 97 if (N && autoTransition) 98 Dst.Add(N); 99 return N; 100 } 101 102 ExplodedNode *generateNode(const Stmt *stmt, const GRState *state, 103 bool autoTransition = true, const void *tag = 0) { 104 assert(state); 105 ExplodedNode *N = generateNodeImpl(stmt, state, false, 106 tag ? tag : checkerTag); 107 if (N && autoTransition) 108 addTransition(N); 109 return N; 110 } 111 112 ExplodedNode *generateNode(const GRState *state, ExplodedNode *pred, 113 bool autoTransition = true) { 114 assert(statement && "Only transitions with statements currently supported"); 115 ExplodedNode *N = generateNodeImpl(statement, state, pred, false); 116 if (N && autoTransition) 117 addTransition(N); 118 return N; 119 } 120 121 ExplodedNode *generateNode(const GRState *state, bool autoTransition = true, 122 const void *tag = 0) { 123 assert(statement && "Only transitions with statements currently supported"); 124 ExplodedNode *N = generateNodeImpl(statement, state, false, 125 tag ? tag : checkerTag); 126 if (N && autoTransition) 127 addTransition(N); 128 return N; 129 } 130 131 ExplodedNode *generateSink(const Stmt *stmt, const GRState *state = 0) { 132 return generateNodeImpl(stmt, state ? state : getState(), true, 133 checkerTag); 134 } 135 136 ExplodedNode *generateSink(const GRState *state = 0) { 137 assert(statement && "Only transitions with statements currently supported"); 138 return generateNodeImpl(statement, state ? state : getState(), true, 139 checkerTag); 140 } 141 addTransition(ExplodedNode * node)142 void addTransition(ExplodedNode *node) { 143 Dst.Add(node); 144 } 145 146 void addTransition(const GRState *state, const void *tag = 0) { 147 assert(state); 148 // If the 'state' is not new, we need to check if the cached state 'ST' 149 // is new. 150 if (state != getState() || (ST && ST != B.GetState(Pred))) 151 // state is new or equals to ST. 152 generateNode(state, true, tag); 153 else 154 Dst.Add(Pred); 155 } 156 EmitReport(BugReport * R)157 void EmitReport(BugReport *R) { 158 Eng.getBugReporter().EmitReport(R); 159 } 160 getCurrentAnalysisContext()161 AnalysisContext *getCurrentAnalysisContext() const { 162 return Pred->getLocationContext()->getAnalysisContext(); 163 } 164 165 private: generateNodeImpl(const Stmt * stmt,const GRState * state,bool markAsSink,const void * tag)166 ExplodedNode *generateNodeImpl(const Stmt* stmt, const GRState *state, 167 bool markAsSink, const void *tag) { 168 ExplodedNode *node = B.generateNode(stmt, state, Pred, tag); 169 if (markAsSink && node) 170 node->markAsSink(); 171 return node; 172 } 173 generateNodeImpl(const Stmt * stmt,const GRState * state,ExplodedNode * pred,bool markAsSink)174 ExplodedNode *generateNodeImpl(const Stmt* stmt, const GRState *state, 175 ExplodedNode *pred, bool markAsSink) { 176 ExplodedNode *node = B.generateNode(stmt, state, pred, checkerTag); 177 if (markAsSink && node) 178 node->markAsSink(); 179 return node; 180 } 181 }; 182 183 } // end GR namespace 184 185 } // end clang namespace 186 187 #endif 188