BugReporter.h revision c095997b853270d8adb6fe55209a4dbc42803d16
1// BugReporter.h - Generate PathDiagnostics ----------*- 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 BugReporter, a utility class for generating 11// PathDiagnostics for analyses based on ValueState. 12// 13//===----------------------------------------------------------------------===// 14 15#ifndef LLVM_CLANG_ANALYSIS_BUGREPORTER 16#define LLVM_CLANG_ANALYSIS_BUGREPORTER 17 18#include "clang/Basic/SourceLocation.h" 19#include "clang/Analysis/PathSensitive/ValueState.h" 20#include "clang/Analysis/PathSensitive/ExplodedGraph.h" 21#include "llvm/ADT/SmallPtrSet.h" 22#include "llvm/ADT/SmallSet.h" 23#include <vector> 24 25namespace clang { 26 27class PathDiagnostic; 28class PathDiagnosticPiece; 29class PathDiagnosticClient; 30class ASTContext; 31class Diagnostic; 32class BugReporter; 33class GRExprEngine; 34class ValueState; 35class Stmt; 36class BugReport; 37class ParentMap; 38 39class BugType { 40public: 41 BugType() {} 42 virtual ~BugType(); 43 44 virtual const char* getName() const = 0; 45 virtual const char* getDescription() const { return getName(); } 46 47 virtual std::pair<const char**,const char**> getExtraDescriptiveText() { 48 return std::pair<const char**, const char**>(0, 0); 49 } 50 51 virtual void EmitWarnings(BugReporter& BR) {} 52 virtual void GetErrorNodes(std::vector<ExplodedNode<ValueState>*>& Nodes) {} 53 54 virtual bool isCached(BugReport& R) = 0; 55}; 56 57class BugTypeCacheLocation : public BugType { 58 llvm::SmallPtrSet<void*,10> CachedErrors; 59public: 60 BugTypeCacheLocation() {} 61 virtual ~BugTypeCacheLocation() {} 62 virtual bool isCached(BugReport& R); 63 bool isCached(ProgramPoint P); 64}; 65 66 67class BugReport { 68 BugType& Desc; 69 ExplodedNode<ValueState> *EndNode; 70 SourceRange R; 71public: 72 BugReport(BugType& D, ExplodedNode<ValueState> *n) : Desc(D), EndNode(n) {} 73 virtual ~BugReport(); 74 75 const BugType& getBugType() const { return Desc; } 76 BugType& getBugType() { return Desc; } 77 78 ExplodedNode<ValueState>* getEndNode() const { return EndNode; } 79 80 Stmt* getStmt(BugReporter& BR) const; 81 82 const char* getName() const { return getBugType().getName(); } 83 84 virtual const char* getDescription() const { 85 return getBugType().getDescription(); 86 } 87 88 virtual std::pair<const char**,const char**> getExtraDescriptiveText() { 89 return getBugType().getExtraDescriptiveText(); 90 } 91 92 virtual PathDiagnosticPiece* getEndPath(BugReporter& BR, 93 ExplodedNode<ValueState>* N); 94 95 virtual FullSourceLoc getLocation(SourceManager& Mgr); 96 97 virtual void getRanges(BugReporter& BR,const SourceRange*& beg, 98 const SourceRange*& end); 99 100 virtual PathDiagnosticPiece* VisitNode(ExplodedNode<ValueState>* N, 101 ExplodedNode<ValueState>* PrevN, 102 ExplodedGraph<ValueState>& G, 103 BugReporter& BR); 104}; 105 106class RangedBugReport : public BugReport { 107 std::vector<SourceRange> Ranges; 108public: 109 RangedBugReport(BugType& D, ExplodedNode<ValueState> *n) 110 : BugReport(D, n) {} 111 112 virtual ~RangedBugReport(); 113 114 void addRange(SourceRange R) { Ranges.push_back(R); } 115 116 virtual void getRanges(BugReporter& BR,const SourceRange*& beg, 117 const SourceRange*& end) { 118 119 if (Ranges.empty()) { 120 beg = NULL; 121 end = NULL; 122 } 123 else { 124 beg = &Ranges[0]; 125 end = beg + Ranges.size(); 126 } 127 } 128}; 129 130class BugReporterData { 131public: 132 virtual ~BugReporterData(); 133 virtual Diagnostic& getDiagnostic() = 0; 134 virtual PathDiagnosticClient* getPathDiagnosticClient() = 0; 135 virtual ASTContext& getContext() = 0; 136 virtual SourceManager& getSourceManager() = 0; 137 virtual CFG& getCFG() = 0; 138 virtual ParentMap& getParentMap() = 0; 139 virtual LiveVariables& getLiveVariables() = 0; 140}; 141 142class BugReporter { 143public: 144 enum Kind { BaseBRKind, GRBugReporterKind }; 145 146protected: 147 Kind kind; 148 BugReporterData& D; 149 150 BugReporter(BugReporterData& d, Kind k) : kind(k), D(d) {} 151 152public: 153 BugReporter(BugReporterData& d) : kind(BaseBRKind), D(d) {} 154 virtual ~BugReporter(); 155 156 Kind getKind() const { return kind; } 157 158 Diagnostic& getDiagnostic() { 159 return D.getDiagnostic(); 160 } 161 162 PathDiagnosticClient* getPathDiagnosticClient() { 163 return D.getPathDiagnosticClient(); 164 } 165 166 ASTContext& getContext() { 167 return D.getContext(); 168 } 169 170 SourceManager& getSourceManager() { 171 return getContext().getSourceManager(); 172 } 173 174 CFG& getCFG() { 175 return D.getCFG(); 176 } 177 178 ParentMap& getParentMap() { 179 return D.getParentMap(); 180 } 181 182 LiveVariables& getLiveVariables() { 183 return D.getLiveVariables(); 184 } 185 186 virtual void GeneratePathDiagnostic(PathDiagnostic& PD, BugReport& R) {} 187 188 void EmitWarning(BugReport& R); 189 190 static bool classof(const BugReporter* R) { return true; } 191}; 192 193class GRBugReporter : public BugReporter { 194 GRExprEngine& Eng; 195 llvm::SmallSet<SymbolID, 10> NotableSymbols; 196public: 197 198 GRBugReporter(BugReporterData& d, GRExprEngine& eng) 199 : BugReporter(d, GRBugReporterKind), Eng(eng) {} 200 201 virtual ~GRBugReporter(); 202 203 GRExprEngine& getEngine() { 204 return Eng; 205 } 206 207 ExplodedGraph<ValueState>& getGraph(); 208 209 ValueStateManager& getStateManager(); 210 211 virtual void GeneratePathDiagnostic(PathDiagnostic& PD, BugReport& R); 212 213 void addNotableSymbol(SymbolID Sym) { 214 NotableSymbols.insert(Sym); 215 } 216 217 bool isNotable(SymbolID Sym) const { 218 return (bool) NotableSymbols.count(Sym); 219 } 220 221 static bool classof(const BugReporter* R) { 222 return R->getKind() == GRBugReporterKind; 223 } 224}; 225 226} // end clang namespace 227 228#endif 229