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