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