CheckerContext.h revision 4eff823b8e015e003d05953c386d685ee6bb6235
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 ExplodedNode *&getPredecessor() { return Pred; } 82 const ProgramState *getState() { return ST ? ST : Pred->getState(); } 83 const Stmt *getStmt() const { return statement; } 84 85 /// \brief Returns the number of times the current block has been visited 86 /// along the analyzed path. 87 unsigned getCurrentBlockCount() {return B.getCurrentBlockCount();} 88 89 ASTContext &getASTContext() { 90 return Eng.getContext(); 91 } 92 93 BugReporter &getBugReporter() { 94 return Eng.getBugReporter(); 95 } 96 97 SourceManager &getSourceManager() { 98 return getBugReporter().getSourceManager(); 99 } 100 101 SValBuilder &getSValBuilder() { 102 return Eng.getSValBuilder(); 103 } 104 105 SymbolManager &getSymbolManager() { 106 return getSValBuilder().getSymbolManager(); 107 } 108 109 bool isObjCGCEnabled() { 110 return Eng.isObjCGCEnabled(); 111 } 112 113 /// \brief Generate a default checker node (containing checker tag but no 114 /// checker state changes). 115 ExplodedNode *generateNode(bool autoTransition = true) { 116 return generateNode(getState(), autoTransition); 117 } 118 119 /// \brief Generate a new checker node with the given predecessor. 120 /// Allows checkers to generate a chain of nodes. 121 ExplodedNode *generateNode(const ProgramState *state, 122 ExplodedNode *pred, 123 const ProgramPointTag *tag = 0, 124 bool autoTransition = true) { 125 ExplodedNode *N = generateNodeImpl(state, false, pred, tag); 126 if (N && autoTransition) 127 addTransition(N); 128 return N; 129 } 130 131 /// \brief Generate a new checker node. 132 ExplodedNode *generateNode(const ProgramState *state, 133 bool autoTransition = true, 134 const ProgramPointTag *tag = 0) { 135 ExplodedNode *N = generateNodeImpl(state, false, 0, tag); 136 if (N && autoTransition) 137 addTransition(N); 138 return N; 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 generateNodeImpl(state ? state : getState(), true); 145 } 146 147 void addTransition(ExplodedNode *node) { 148 Dst.Add(node); 149 } 150 151 void addTransition(const ProgramState *state, 152 const ProgramPointTag *tag = 0) { 153 assert(state); 154 // If the 'state' is not new, we need to check if the cached state 'ST' 155 // is new. 156 if (state != getState() || (ST && ST != Pred->getState())) 157 // state is new or equals to ST. 158 generateNode(state, true, tag); 159 else 160 Dst.Add(Pred); 161 } 162 163 void EmitReport(BugReport *R) { 164 Eng.getBugReporter().EmitReport(R); 165 } 166 167 AnalysisContext *getCurrentAnalysisContext() const { 168 return Pred->getLocationContext()->getAnalysisContext(); 169 } 170 171private: 172 ExplodedNode *generateNodeImpl(const ProgramState *state, 173 bool markAsSink, 174 ExplodedNode *pred = 0, 175 const ProgramPointTag *tag = 0) { 176 assert(statement && "Only transitions with statements currently supported"); 177 ExplodedNode *node = B.generateNode(statement, state, 178 pred ? pred : Pred, 179 tag ? tag : checkerTag); 180 if (markAsSink && node) 181 node->markAsSink(); 182 return node; 183 } 184}; 185 186} // end GR namespace 187 188} // end clang namespace 189 190#endif 191