BugReporter.h revision e207558e9dbed963eebf5cf31fdb02616f1545a3
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/Diagnostic.h" 19#include "clang/Basic/SourceLocation.h" 20#include "clang/Analysis/PathSensitive/ValueState.h" 21#include "clang/Analysis/PathSensitive/ExplodedGraph.h" 22#include "llvm/ADT/SmallPtrSet.h" 23#include "llvm/ADT/SmallSet.h" 24#include <vector> 25#include <list> 26 27 28namespace clang { 29 30class PathDiagnostic; 31class PathDiagnosticPiece; 32class PathDiagnosticClient; 33class ASTContext; 34class Diagnostic; 35class BugReporter; 36class GRExprEngine; 37class ValueState; 38class Stmt; 39class BugReport; 40class ParentMap; 41 42class BugType { 43public: 44 BugType() {} 45 virtual ~BugType(); 46 47 virtual const char* getName() const = 0; 48 virtual const char* getDescription() const { return getName(); } 49 50 virtual std::pair<const char**,const char**> getExtraDescriptiveText() { 51 return std::pair<const char**, const char**>(0, 0); 52 } 53 54 virtual void EmitWarnings(BugReporter& BR) {} 55 virtual void GetErrorNodes(std::vector<ExplodedNode<ValueState>*>& Nodes) {} 56 57 virtual bool isCached(BugReport& R) = 0; 58}; 59 60class BugTypeCacheLocation : public BugType { 61 llvm::SmallPtrSet<void*,10> CachedErrors; 62public: 63 BugTypeCacheLocation() {} 64 virtual ~BugTypeCacheLocation() {} 65 virtual bool isCached(BugReport& R); 66 bool isCached(ProgramPoint P); 67}; 68 69 70class BugReport { 71 BugType& Desc; 72 ExplodedNode<ValueState> *EndNode; 73 SourceRange R; 74public: 75 BugReport(BugType& D, ExplodedNode<ValueState> *n) : Desc(D), EndNode(n) {} 76 virtual ~BugReport(); 77 78 const BugType& getBugType() const { return Desc; } 79 BugType& getBugType() { return Desc; } 80 81 ExplodedNode<ValueState>* getEndNode() const { return EndNode; } 82 83 Stmt* getStmt(BugReporter& BR) const; 84 85 const char* getName() const { return getBugType().getName(); } 86 87 virtual const char* getDescription() const { 88 return getBugType().getDescription(); 89 } 90 91 virtual std::pair<const char**,const char**> getExtraDescriptiveText() { 92 return getBugType().getExtraDescriptiveText(); 93 } 94 95 virtual PathDiagnosticPiece* getEndPath(BugReporter& BR, 96 ExplodedNode<ValueState>* N); 97 98 virtual FullSourceLoc getLocation(SourceManager& Mgr); 99 100 virtual void getRanges(BugReporter& BR,const SourceRange*& beg, 101 const SourceRange*& end); 102 103 virtual PathDiagnosticPiece* VisitNode(ExplodedNode<ValueState>* N, 104 ExplodedNode<ValueState>* PrevN, 105 ExplodedGraph<ValueState>& G, 106 BugReporter& BR); 107}; 108 109class RangedBugReport : public BugReport { 110 std::vector<SourceRange> Ranges; 111public: 112 RangedBugReport(BugType& D, ExplodedNode<ValueState> *n) 113 : BugReport(D, n) {} 114 115 virtual ~RangedBugReport(); 116 117 void addRange(SourceRange R) { Ranges.push_back(R); } 118 119 virtual void getRanges(BugReporter& BR,const SourceRange*& beg, 120 const SourceRange*& end) { 121 122 if (Ranges.empty()) { 123 beg = NULL; 124 end = NULL; 125 } 126 else { 127 beg = &Ranges[0]; 128 end = beg + Ranges.size(); 129 } 130 } 131}; 132 133class BugReporterData { 134public: 135 virtual ~BugReporterData(); 136 virtual Diagnostic& getDiagnostic() = 0; 137 virtual PathDiagnosticClient* getPathDiagnosticClient() = 0; 138 virtual ASTContext& getContext() = 0; 139 virtual SourceManager& getSourceManager() = 0; 140 virtual CFG& getCFG() = 0; 141 virtual ParentMap& getParentMap() = 0; 142 virtual LiveVariables& getLiveVariables() = 0; 143}; 144 145class BugReporter { 146public: 147 enum Kind { BaseBRKind, GRBugReporterKind }; 148 149protected: 150 Kind kind; 151 BugReporterData& D; 152 153 BugReporter(BugReporterData& d, Kind k) : kind(k), D(d) {} 154 155public: 156 BugReporter(BugReporterData& d) : kind(BaseBRKind), D(d) {} 157 virtual ~BugReporter(); 158 159 Kind getKind() const { return kind; } 160 161 Diagnostic& getDiagnostic() { 162 return D.getDiagnostic(); 163 } 164 165 PathDiagnosticClient* getPathDiagnosticClient() { 166 return D.getPathDiagnosticClient(); 167 } 168 169 ASTContext& getContext() { 170 return D.getContext(); 171 } 172 173 SourceManager& getSourceManager() { 174 return D.getSourceManager(); 175 } 176 177 CFG& getCFG() { 178 return D.getCFG(); 179 } 180 181 ParentMap& getParentMap() { 182 return D.getParentMap(); 183 } 184 185 LiveVariables& getLiveVariables() { 186 return D.getLiveVariables(); 187 } 188 189 virtual void GeneratePathDiagnostic(PathDiagnostic& PD, BugReport& R) {} 190 191 void EmitWarning(BugReport& R); 192 193 static bool classof(const BugReporter* R) { return true; } 194}; 195 196class GRBugReporter : public BugReporter { 197 GRExprEngine& Eng; 198 llvm::SmallSet<SymbolID, 10> NotableSymbols; 199public: 200 201 GRBugReporter(BugReporterData& d, GRExprEngine& eng) 202 : BugReporter(d, GRBugReporterKind), Eng(eng) {} 203 204 virtual ~GRBugReporter(); 205 206 GRExprEngine& getEngine() { 207 return Eng; 208 } 209 210 ExplodedGraph<ValueState>& getGraph(); 211 212 ValueStateManager& getStateManager(); 213 214 virtual void GeneratePathDiagnostic(PathDiagnostic& PD, BugReport& R); 215 216 void addNotableSymbol(SymbolID Sym) { 217 NotableSymbols.insert(Sym); 218 } 219 220 bool isNotable(SymbolID Sym) const { 221 return (bool) NotableSymbols.count(Sym); 222 } 223 224 static bool classof(const BugReporter* R) { 225 return R->getKind() == GRBugReporterKind; 226 } 227}; 228 229 230class DiagBugReport : public RangedBugReport { 231 std::list<std::string> Strs; 232 FullSourceLoc L; 233 const char* description; 234public: 235 DiagBugReport(const char* desc, BugType& D, FullSourceLoc l) : 236 RangedBugReport(D, NULL), L(l), description(desc) {} 237 238 virtual ~DiagBugReport() {} 239 virtual FullSourceLoc getLocation(SourceManager&) { return L; } 240 241 virtual const char* getDescription() const { 242 return description; 243 } 244 245 void addString(const std::string& s) { Strs.push_back(s); } 246 247 typedef std::list<std::string>::const_iterator str_iterator; 248 str_iterator str_begin() const { return Strs.begin(); } 249 str_iterator str_end() const { return Strs.end(); } 250}; 251 252class DiagCollector : public DiagnosticClient { 253 std::list<DiagBugReport> Reports; 254 BugType& D; 255public: 256 DiagCollector(BugType& d) : D(d) {} 257 258 virtual ~DiagCollector() {} 259 260 virtual void HandleDiagnostic(Diagnostic &Diags, 261 Diagnostic::Level DiagLevel, 262 FullSourceLoc Pos, 263 diag::kind ID, 264 const std::string *Strs, 265 unsigned NumStrs, 266 const SourceRange *Ranges, 267 unsigned NumRanges) { 268 269 // FIXME: Use a map from diag::kind to BugType, instead of having just 270 // one BugType. 271 272 Reports.push_back(DiagBugReport(Diags.getDescription(ID), D, Pos)); 273 DiagBugReport& R = Reports.back(); 274 275 for ( ; NumRanges ; --NumRanges, ++Ranges) 276 R.addRange(*Ranges); 277 278 for ( ; NumStrs ; --NumStrs, ++Strs) 279 R.addString(*Strs); 280 } 281 282 // Iterators. 283 284 typedef std::list<DiagBugReport>::iterator iterator; 285 iterator begin() { return Reports.begin(); } 286 iterator end() { return Reports.end(); } 287}; 288 289} // end clang namespace 290 291#endif 292