CheckerContext.h revision 5d0ea6d62e076c776ddad028c4eb615783be1323
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 ProgramPointTag *checkerTag; 32 SaveAndRestore<ProgramPoint::Kind> OldPointKind; 33 SaveOr OldHasGen; 34 const ProgramState *ST; 35 const Stmt *statement; 36 const unsigned size; 37public: 38 bool *respondsToCallback; 39public: 40 CheckerContext(ExplodedNodeSet &dst, 41 StmtNodeBuilder &builder, 42 ExprEngine &eng, 43 ExplodedNode *pred, 44 const ProgramPointTag *tag, 45 ProgramPoint::Kind K, 46 bool *respondsToCB = 0, 47 const Stmt *stmt = 0, 48 const ProgramState *st = 0) 49 : Dst(dst), 50 B(builder), 51 Eng(eng), 52 Pred(pred), 53 OldSink(B.BuildSinks), 54 checkerTag(tag), 55 OldPointKind(B.PointKind, K), 56 OldHasGen(B.hasGeneratedNode), 57 ST(st), 58 statement(stmt), 59 size(Dst.size()), 60 respondsToCallback(respondsToCB) {} 61 62 ~CheckerContext(); 63 64 ExprEngine &getEngine() { 65 return Eng; 66 } 67 68 AnalysisManager &getAnalysisManager() { 69 return Eng.getAnalysisManager(); 70 } 71 72 ConstraintManager &getConstraintManager() { 73 return Eng.getConstraintManager(); 74 } 75 76 StoreManager &getStoreManager() { 77 return Eng.getStoreManager(); 78 } 79 80 ExplodedNodeSet &getNodeSet() { return Dst; } 81 StmtNodeBuilder &getNodeBuilder() { return B; } 82 ExplodedNode *&getPredecessor() { return Pred; } 83 const ProgramState *getState() { return ST ? ST : Pred->getState(); } 84 const Stmt *getStmt() const { return statement; } 85 86 /// \brief Returns the number of times the current block has been visited 87 /// along the analyzed path. 88 unsigned getCurrentBlockCount() {return B.getCurrentBlockCount();} 89 90 ASTContext &getASTContext() { 91 return Eng.getContext(); 92 } 93 94 BugReporter &getBugReporter() { 95 return Eng.getBugReporter(); 96 } 97 98 SourceManager &getSourceManager() { 99 return getBugReporter().getSourceManager(); 100 } 101 102 SValBuilder &getSValBuilder() { 103 return Eng.getSValBuilder(); 104 } 105 106 SymbolManager &getSymbolManager() { 107 return getSValBuilder().getSymbolManager(); 108 } 109 110 bool isObjCGCEnabled() { 111 return Eng.isObjCGCEnabled(); 112 } 113 114 /// \brief Generate a default checker node (containing checker tag but no 115 /// checker state changes). 116 ExplodedNode *generateNode(bool autoTransition = true) { 117 assert(statement && "Only transitions with statements currently supported"); 118 ExplodedNode *N = generateNodeImpl(statement, getState(), false, 119 checkerTag); 120 if (N && autoTransition) 121 Dst.Add(N); 122 return N; 123 } 124 125 /// \brief Generate a new checker node with the given predecessor. 126 /// Allows checkers to generate a chain of nodes. 127 ExplodedNode *generateNode(const ProgramState *state, 128 ExplodedNode *pred, 129 bool autoTransition = true) { 130 assert(statement && "Only transitions with statements currently supported"); 131 ExplodedNode *N = generateNodeImpl(statement, state, pred, false); 132 if (N && autoTransition) 133 addTransition(N); 134 return N; 135 } 136 137 /// \brief Generate a new checker node. 138 ExplodedNode *generateNode(const ProgramState *state, 139 bool autoTransition = true, 140 const ProgramPointTag *tag = 0) { 141 assert(statement && "Only transitions with statements currently supported"); 142 ExplodedNode *N = generateNodeImpl(statement, state, false, 143 tag ? tag : checkerTag); 144 if (N && autoTransition) 145 addTransition(N); 146 return N; 147 } 148 149 /// \brief Generate a sink node. Generating sink stops exploration of the 150 /// given path. 151 ExplodedNode *generateSink(const ProgramState *state = 0) { 152 assert(statement && "Only transitions with statements currently supported"); 153 return generateNodeImpl(statement, state ? state : getState(), true, 154 checkerTag); 155 } 156 157 void addTransition(ExplodedNode *node) { 158 Dst.Add(node); 159 } 160 161 void addTransition(const ProgramState *state, 162 const ProgramPointTag *tag = 0) { 163 assert(state); 164 // If the 'state' is not new, we need to check if the cached state 'ST' 165 // is new. 166 if (state != getState() || (ST && ST != Pred->getState())) 167 // state is new or equals to ST. 168 generateNode(state, true, tag); 169 else 170 Dst.Add(Pred); 171 } 172 173 void EmitReport(BugReport *R) { 174 Eng.getBugReporter().EmitReport(R); 175 } 176 177 AnalysisContext *getCurrentAnalysisContext() const { 178 return Pred->getLocationContext()->getAnalysisContext(); 179 } 180 181private: 182 ExplodedNode *generateNodeImpl(const Stmt *stmt, 183 const ProgramState *state, 184 bool markAsSink, 185 const ProgramPointTag *tag) { 186 ExplodedNode *node = B.generateNode(stmt, state, Pred, tag); 187 if (markAsSink && node) 188 node->markAsSink(); 189 return node; 190 } 191 192 ExplodedNode *generateNodeImpl(const Stmt *stmt, 193 const ProgramState *state, 194 ExplodedNode *pred, 195 bool markAsSink) { 196 ExplodedNode *node = B.generateNode(stmt, state, pred, checkerTag); 197 if (markAsSink && node) 198 node->markAsSink(); 199 return node; 200 } 201}; 202 203} // end GR namespace 204 205} // end clang namespace 206 207#endif 208