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