BugReporter.h revision ef3643fbbbf66247c5e205497fae0f46e240c143
1aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root//===--- BugReporter.h - Generate PathDiagnostics --------------*- C++ -*-===// 2aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root// 3aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root// The LLVM Compiler Infrastructure 4aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root// 5aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root// This file is distributed under the University of Illinois Open Source 6aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root// License. See LICENSE.TXT for details. 7aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root// 8aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root//===----------------------------------------------------------------------===// 9aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root// 10aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root// This file defines BugReporter, a utility class for generating 11aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root// PathDiagnostics for analyses based on ProgramState. 12aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root// 13aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root//===----------------------------------------------------------------------===// 14aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root 15aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root#ifndef LLVM_CLANG_GR_BUGREPORTER 16aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root#define LLVM_CLANG_GR_BUGREPORTER 17860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root 18aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root#include "clang/Basic/SourceLocation.h" 19aceaabe71de0da877be36f5bfb88c7111f81fc3eKenny Root#include "clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitor.h" 20aceaabe71de0da877be36f5bfb88c7111f81fc3eKenny Root#include "clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h" 21aceaabe71de0da877be36f5bfb88c7111f81fc3eKenny Root#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h" 22aceaabe71de0da877be36f5bfb88c7111f81fc3eKenny Root#include "llvm/ADT/FoldingSet.h" 23aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root#include "llvm/ADT/ImmutableList.h" 24aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root#include "llvm/ADT/ImmutableSet.h" 25aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root#include "llvm/ADT/SmallSet.h" 26aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root#include <list> 27aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root 28aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Rootnamespace clang { 29aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root 3047cc520bd63c1eabfdef23cbab10457701f2a395Kenny Rootclass ASTContext; 31c43ab99bd48be940dde4c8ee74155e0482cd1599Kenny Rootclass DiagnosticsEngine; 32c43ab99bd48be940dde4c8ee74155e0482cd1599Kenny Rootclass Stmt; 33aceaabe71de0da877be36f5bfb88c7111f81fc3eKenny Rootclass ParentMap; 34aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root 35aceaabe71de0da877be36f5bfb88c7111f81fc3eKenny Rootnamespace ento { 36aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root 37aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Rootclass PathDiagnostic; 38aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Rootclass ExplodedNode; 39aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Rootclass ExplodedGraph; 40aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Rootclass BugReport; 4147cc520bd63c1eabfdef23cbab10457701f2a395Kenny Rootclass BugReporter; 4247cc520bd63c1eabfdef23cbab10457701f2a395Kenny Rootclass BugReporterContext; 439df6cea08a4eb527ba5b6fc9275e8b0571c12892Kenny Rootclass ExprEngine; 449df6cea08a4eb527ba5b6fc9275e8b0571c12892Kenny Rootclass BugType; 459df6cea08a4eb527ba5b6fc9275e8b0571c12892Kenny Root 46aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root//===----------------------------------------------------------------------===// 47aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root// Interface for individual bug reports. 48aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root//===----------------------------------------------------------------------===// 49aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root 50aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root/// This class provides an interface through which checkers can create 51aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root/// individual bug reports. 52aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Rootclass BugReport { 53aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Rootpublic: 54aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root class NodeResolver { 55aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root public: 56aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root virtual ~NodeResolver() {} 57aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root virtual const ExplodedNode* 58aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root getOriginalNode(const ExplodedNode *N) = 0; 59aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root }; 60aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root 61aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root typedef const SourceRange *ranges_iterator; 62aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root typedef llvm::ImmutableList<BugReporterVisitor*>::iterator visitor_iterator; 63aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root typedef SmallVector<StringRef, 2> ExtraTextList; 64aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root 65aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Rootprotected: 66aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root friend class BugReporter; 67aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root friend class BugReportEquivClass; 68aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root 69aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root BugType& BT; 70aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root std::string ShortDescription; 71aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root std::string Description; 72aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root PathDiagnosticLocation Location; 73aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root const ExplodedNode *ErrorNode; 74aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root SmallVector<SourceRange, 4> Ranges; 75aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root ExtraTextList ExtraText; 76aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root 77aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root // Not the most efficient data structure, but we use an ImmutableList for the 78aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root // Callbacks because it is safe to make additions to list during iteration. 79aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root llvm::ImmutableList<BugReporterVisitor*>::Factory F; 80aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root llvm::ImmutableList<BugReporterVisitor*> Callbacks; 81aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root llvm::FoldingSet<BugReporterVisitor> CallbacksSet; 8280f0c28bcba376c34616ed27c7af3e02d4677d37Kenny Root 8380f0c28bcba376c34616ed27c7af3e02d4677d37Kenny Rootpublic: 8480f0c28bcba376c34616ed27c7af3e02d4677d37Kenny Root BugReport(BugType& bt, StringRef desc, const ExplodedNode *errornode) 8580f0c28bcba376c34616ed27c7af3e02d4677d37Kenny Root : BT(bt), Description(desc), ErrorNode(errornode), 8680f0c28bcba376c34616ed27c7af3e02d4677d37Kenny Root Callbacks(F.getEmptyList()) {} 8780f0c28bcba376c34616ed27c7af3e02d4677d37Kenny Root 8880f0c28bcba376c34616ed27c7af3e02d4677d37Kenny Root BugReport(BugType& bt, StringRef shortDesc, StringRef desc, 8980f0c28bcba376c34616ed27c7af3e02d4677d37Kenny Root const ExplodedNode *errornode) 9080f0c28bcba376c34616ed27c7af3e02d4677d37Kenny Root : BT(bt), ShortDescription(shortDesc), Description(desc), 91aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root ErrorNode(errornode), Callbacks(F.getEmptyList()) {} 92aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root 93aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root BugReport(BugType& bt, StringRef desc, PathDiagnosticLocation l) 94aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root : BT(bt), Description(desc), Location(l), ErrorNode(0), 95aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root Callbacks(F.getEmptyList()) {} 96aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root 97aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root virtual ~BugReport(); 98aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root 99aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root const BugType& getBugType() const { return BT; } 100aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root BugType& getBugType() { return BT; } 101aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root 102aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root const ExplodedNode *getErrorNode() const { return ErrorNode; } 103aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root 104aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root const StringRef getDescription() const { return Description; } 105aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root 106aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root const StringRef getShortDescription() const { 107aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root return ShortDescription.empty() ? Description : ShortDescription; 108aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root } 109aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root 110aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root /// \brief This allows for addition of meta data to the diagnostic. 111aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root /// 112aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root /// Currently, only the HTMLDiagnosticClient knows how to display it. 113aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root void addExtraText(StringRef S) { 114c43ab99bd48be940dde4c8ee74155e0482cd1599Kenny Root ExtraText.push_back(S); 115c43ab99bd48be940dde4c8ee74155e0482cd1599Kenny Root } 116c43ab99bd48be940dde4c8ee74155e0482cd1599Kenny Root 117c43ab99bd48be940dde4c8ee74155e0482cd1599Kenny Root virtual const ExtraTextList &getExtraText() { 118c43ab99bd48be940dde4c8ee74155e0482cd1599Kenny Root return ExtraText; 119c43ab99bd48be940dde4c8ee74155e0482cd1599Kenny Root } 120c43ab99bd48be940dde4c8ee74155e0482cd1599Kenny Root 121c43ab99bd48be940dde4c8ee74155e0482cd1599Kenny Root /// \brief Return the "definitive" location of the reported bug. 122c43ab99bd48be940dde4c8ee74155e0482cd1599Kenny Root /// 123c43ab99bd48be940dde4c8ee74155e0482cd1599Kenny Root /// While a bug can span an entire path, usually there is a specific 124c43ab99bd48be940dde4c8ee74155e0482cd1599Kenny Root /// location that can be used to identify where the key issue occurred. 125c43ab99bd48be940dde4c8ee74155e0482cd1599Kenny Root /// This location is used by clients rendering diagnostics. 126c43ab99bd48be940dde4c8ee74155e0482cd1599Kenny Root virtual PathDiagnosticLocation getLocation(const SourceManager &SM) const; 127c43ab99bd48be940dde4c8ee74155e0482cd1599Kenny Root 128c43ab99bd48be940dde4c8ee74155e0482cd1599Kenny Root const Stmt *getStmt() const; 129c43ab99bd48be940dde4c8ee74155e0482cd1599Kenny Root 130c43ab99bd48be940dde4c8ee74155e0482cd1599Kenny Root /// \brief Add a range to a bug report. 131c43ab99bd48be940dde4c8ee74155e0482cd1599Kenny Root /// 132c43ab99bd48be940dde4c8ee74155e0482cd1599Kenny Root /// Ranges are used to highlight regions of interest in the source code. 133c43ab99bd48be940dde4c8ee74155e0482cd1599Kenny Root /// They should be at the same source code line as the BugReport location. 134c43ab99bd48be940dde4c8ee74155e0482cd1599Kenny Root /// By default, the source range of the statement corresponding to the error 135c43ab99bd48be940dde4c8ee74155e0482cd1599Kenny Root /// node will be used; add a single invalid range to specify absence of 136c43ab99bd48be940dde4c8ee74155e0482cd1599Kenny Root /// ranges. 137c43ab99bd48be940dde4c8ee74155e0482cd1599Kenny Root void addRange(SourceRange R) { 138c43ab99bd48be940dde4c8ee74155e0482cd1599Kenny Root assert((R.isValid() || Ranges.empty()) && "Invalid range can only be used " 139c43ab99bd48be940dde4c8ee74155e0482cd1599Kenny Root "to specify that the report does not have a range."); 140c43ab99bd48be940dde4c8ee74155e0482cd1599Kenny Root Ranges.push_back(R); 141c43ab99bd48be940dde4c8ee74155e0482cd1599Kenny Root } 142c43ab99bd48be940dde4c8ee74155e0482cd1599Kenny Root 143c43ab99bd48be940dde4c8ee74155e0482cd1599Kenny Root /// \brief Get the SourceRanges associated with the report. 144c43ab99bd48be940dde4c8ee74155e0482cd1599Kenny Root virtual std::pair<ranges_iterator, ranges_iterator> getRanges(); 145c43ab99bd48be940dde4c8ee74155e0482cd1599Kenny Root 146c43ab99bd48be940dde4c8ee74155e0482cd1599Kenny Root /// \brief Add custom or predefined bug report visitors to this report. 147c43ab99bd48be940dde4c8ee74155e0482cd1599Kenny Root /// 148c43ab99bd48be940dde4c8ee74155e0482cd1599Kenny Root /// The visitors should be used when the default trace is not sufficient. 149c43ab99bd48be940dde4c8ee74155e0482cd1599Kenny Root /// For example, they allow constructing a more elaborate trace. 150c43ab99bd48be940dde4c8ee74155e0482cd1599Kenny Root /// \sa registerConditionVisitor(), registerTrackNullOrUndefValue(), 151c43ab99bd48be940dde4c8ee74155e0482cd1599Kenny Root /// registerFindLastStore(), registerNilReceiverVisitor(), and 152c43ab99bd48be940dde4c8ee74155e0482cd1599Kenny Root /// registerVarDeclsLastStore(). 153c43ab99bd48be940dde4c8ee74155e0482cd1599Kenny Root void addVisitor(BugReporterVisitor *visitor); 154c43ab99bd48be940dde4c8ee74155e0482cd1599Kenny Root 155c43ab99bd48be940dde4c8ee74155e0482cd1599Kenny Root /// Iterators through the custom diagnostic visitors. 156c43ab99bd48be940dde4c8ee74155e0482cd1599Kenny Root visitor_iterator visitor_begin() { return Callbacks.begin(); } 157c43ab99bd48be940dde4c8ee74155e0482cd1599Kenny Root visitor_iterator visitor_end() { return Callbacks.end(); } 158c43ab99bd48be940dde4c8ee74155e0482cd1599Kenny Root 159c43ab99bd48be940dde4c8ee74155e0482cd1599Kenny Root /// Profile to identify equivalent bug reports for error report coalescing. 160c43ab99bd48be940dde4c8ee74155e0482cd1599Kenny Root /// Reports are uniqued to ensure that we do not emit multiple diagnostics 161c43ab99bd48be940dde4c8ee74155e0482cd1599Kenny Root /// for each bug. 162c43ab99bd48be940dde4c8ee74155e0482cd1599Kenny Root virtual void Profile(llvm::FoldingSetNodeID& hash) const; 163c43ab99bd48be940dde4c8ee74155e0482cd1599Kenny Root}; 164aceaabe71de0da877be36f5bfb88c7111f81fc3eKenny Root 165aceaabe71de0da877be36f5bfb88c7111f81fc3eKenny Root//===----------------------------------------------------------------------===// 166aceaabe71de0da877be36f5bfb88c7111f81fc3eKenny Root// BugTypes (collections of related reports). 167aceaabe71de0da877be36f5bfb88c7111f81fc3eKenny Root//===----------------------------------------------------------------------===// 168aceaabe71de0da877be36f5bfb88c7111f81fc3eKenny Root 169aceaabe71de0da877be36f5bfb88c7111f81fc3eKenny Rootclass BugReportEquivClass : public llvm::FoldingSetNode { 170aceaabe71de0da877be36f5bfb88c7111f81fc3eKenny Root /// List of *owned* BugReport objects. 171aceaabe71de0da877be36f5bfb88c7111f81fc3eKenny Root std::list<BugReport*> Reports; 172aceaabe71de0da877be36f5bfb88c7111f81fc3eKenny Root 173aceaabe71de0da877be36f5bfb88c7111f81fc3eKenny Root friend class BugReporter; 174aceaabe71de0da877be36f5bfb88c7111f81fc3eKenny Root void AddReport(BugReport* R) { Reports.push_back(R); } 175aceaabe71de0da877be36f5bfb88c7111f81fc3eKenny Rootpublic: 176aceaabe71de0da877be36f5bfb88c7111f81fc3eKenny Root BugReportEquivClass(BugReport* R) { Reports.push_back(R); } 177aceaabe71de0da877be36f5bfb88c7111f81fc3eKenny Root ~BugReportEquivClass(); 178aceaabe71de0da877be36f5bfb88c7111f81fc3eKenny Root 179aceaabe71de0da877be36f5bfb88c7111f81fc3eKenny Root void Profile(llvm::FoldingSetNodeID& ID) const { 180aceaabe71de0da877be36f5bfb88c7111f81fc3eKenny Root assert(!Reports.empty()); 181aceaabe71de0da877be36f5bfb88c7111f81fc3eKenny Root (*Reports.begin())->Profile(ID); 182aceaabe71de0da877be36f5bfb88c7111f81fc3eKenny Root } 183aceaabe71de0da877be36f5bfb88c7111f81fc3eKenny Root 184aceaabe71de0da877be36f5bfb88c7111f81fc3eKenny Root class iterator { 185aceaabe71de0da877be36f5bfb88c7111f81fc3eKenny Root std::list<BugReport*>::iterator impl; 186aceaabe71de0da877be36f5bfb88c7111f81fc3eKenny Root public: 187aceaabe71de0da877be36f5bfb88c7111f81fc3eKenny Root iterator(std::list<BugReport*>::iterator i) : impl(i) {} 188aceaabe71de0da877be36f5bfb88c7111f81fc3eKenny Root iterator &operator++() { ++impl; return *this; } 189aceaabe71de0da877be36f5bfb88c7111f81fc3eKenny Root bool operator==(const iterator &I) const { return I.impl == impl; } 190aceaabe71de0da877be36f5bfb88c7111f81fc3eKenny Root bool operator!=(const iterator &I) const { return I.impl != impl; } 191aceaabe71de0da877be36f5bfb88c7111f81fc3eKenny Root BugReport* operator*() const { return *impl; } 192aceaabe71de0da877be36f5bfb88c7111f81fc3eKenny Root BugReport* operator->() const { return *impl; } 193aa48fdb4d42bc5de668f11055f88fb430fdf4d61Kenny Root }; 194 195 class const_iterator { 196 std::list<BugReport*>::const_iterator impl; 197 public: 198 const_iterator(std::list<BugReport*>::const_iterator i) : impl(i) {} 199 const_iterator &operator++() { ++impl; return *this; } 200 bool operator==(const const_iterator &I) const { return I.impl == impl; } 201 bool operator!=(const const_iterator &I) const { return I.impl != impl; } 202 const BugReport* operator*() const { return *impl; } 203 const BugReport* operator->() const { return *impl; } 204 }; 205 206 iterator begin() { return iterator(Reports.begin()); } 207 iterator end() { return iterator(Reports.end()); } 208 209 const_iterator begin() const { return const_iterator(Reports.begin()); } 210 const_iterator end() const { return const_iterator(Reports.end()); } 211}; 212 213//===----------------------------------------------------------------------===// 214// BugReporter and friends. 215//===----------------------------------------------------------------------===// 216 217class BugReporterData { 218public: 219 virtual ~BugReporterData(); 220 virtual DiagnosticsEngine& getDiagnostic() = 0; 221 virtual PathDiagnosticConsumer* getPathDiagnosticConsumer() = 0; 222 virtual ASTContext &getASTContext() = 0; 223 virtual SourceManager& getSourceManager() = 0; 224}; 225 226/// BugReporter is a utility class for generating PathDiagnostics for analysis. 227/// It collects the BugReports and BugTypes and knows how to generate 228/// and flush the corresponding diagnostics. 229class BugReporter { 230public: 231 enum Kind { BaseBRKind, GRBugReporterKind }; 232 233private: 234 typedef llvm::ImmutableSet<BugType*> BugTypesTy; 235 BugTypesTy::Factory F; 236 BugTypesTy BugTypes; 237 238 const Kind kind; 239 BugReporterData& D; 240 241 /// Generate and flush the diagnostics for the given bug report. 242 void FlushReport(BugReportEquivClass& EQ); 243 244 /// The set of bug reports tracked by the BugReporter. 245 llvm::FoldingSet<BugReportEquivClass> EQClasses; 246 /// A vector of BugReports for tracking the allocated pointers and cleanup. 247 std::vector<BugReportEquivClass *> EQClassesVector; 248 249protected: 250 BugReporter(BugReporterData& d, Kind k) : BugTypes(F.getEmptySet()), kind(k), 251 D(d) {} 252 253public: 254 BugReporter(BugReporterData& d) : BugTypes(F.getEmptySet()), kind(BaseBRKind), 255 D(d) {} 256 virtual ~BugReporter(); 257 258 /// \brief Generate and flush diagnostics for all bug reports. 259 void FlushReports(); 260 261 Kind getKind() const { return kind; } 262 263 DiagnosticsEngine& getDiagnostic() { 264 return D.getDiagnostic(); 265 } 266 267 PathDiagnosticConsumer* getPathDiagnosticConsumer() { 268 return D.getPathDiagnosticConsumer(); 269 } 270 271 /// \brief Iterator over the set of BugTypes tracked by the BugReporter. 272 typedef BugTypesTy::iterator iterator; 273 iterator begin() { return BugTypes.begin(); } 274 iterator end() { return BugTypes.end(); } 275 276 /// \brief Iterator over the set of BugReports tracked by the BugReporter. 277 typedef llvm::FoldingSet<BugReportEquivClass>::iterator EQClasses_iterator; 278 EQClasses_iterator EQClasses_begin() { return EQClasses.begin(); } 279 EQClasses_iterator EQClasses_end() { return EQClasses.end(); } 280 281 ASTContext &getContext() { return D.getASTContext(); } 282 283 SourceManager& getSourceManager() { return D.getSourceManager(); } 284 285 virtual void GeneratePathDiagnostic(PathDiagnostic& pathDiagnostic, 286 SmallVectorImpl<BugReport *> &bugReports) {} 287 288 void Register(BugType *BT); 289 290 /// \brief Add the given report to the set of reports tracked by BugReporter. 291 /// 292 /// The reports are usually generated by the checkers. Further, they are 293 /// folded based on the profile value, which is done to coalesce similar 294 /// reports. 295 void EmitReport(BugReport *R); 296 297 void EmitBasicReport(StringRef BugName, StringRef BugStr, 298 PathDiagnosticLocation Loc, 299 SourceRange* RangeBeg, unsigned NumRanges); 300 301 void EmitBasicReport(StringRef BugName, StringRef BugCategory, 302 StringRef BugStr, PathDiagnosticLocation Loc, 303 SourceRange* RangeBeg, unsigned NumRanges); 304 305 306 void EmitBasicReport(StringRef BugName, StringRef BugStr, 307 PathDiagnosticLocation Loc) { 308 EmitBasicReport(BugName, BugStr, Loc, 0, 0); 309 } 310 311 void EmitBasicReport(StringRef BugName, StringRef BugCategory, 312 StringRef BugStr, PathDiagnosticLocation Loc) { 313 EmitBasicReport(BugName, BugCategory, BugStr, Loc, 0, 0); 314 } 315 316 void EmitBasicReport(StringRef BugName, StringRef BugStr, 317 PathDiagnosticLocation Loc, SourceRange R) { 318 EmitBasicReport(BugName, BugStr, Loc, &R, 1); 319 } 320 321 void EmitBasicReport(StringRef BugName, StringRef Category, 322 StringRef BugStr, PathDiagnosticLocation Loc, 323 SourceRange R) { 324 EmitBasicReport(BugName, Category, BugStr, Loc, &R, 1); 325 } 326 327 static bool classof(const BugReporter* R) { return true; } 328 329private: 330 llvm::StringMap<BugType *> StrBugTypes; 331 332 /// \brief Returns a BugType that is associated with the given name and 333 /// category. 334 BugType *getBugTypeForName(StringRef name, StringRef category); 335}; 336 337// FIXME: Get rid of GRBugReporter. It's the wrong abstraction. 338class GRBugReporter : public BugReporter { 339 ExprEngine& Eng; 340 llvm::SmallSet<SymbolRef, 10> NotableSymbols; 341public: 342 GRBugReporter(BugReporterData& d, ExprEngine& eng) 343 : BugReporter(d, GRBugReporterKind), Eng(eng) {} 344 345 virtual ~GRBugReporter(); 346 347 /// getEngine - Return the analysis engine used to analyze a given 348 /// function or method. 349 ExprEngine &getEngine() { return Eng; } 350 351 /// getGraph - Get the exploded graph created by the analysis engine 352 /// for the analyzed method or function. 353 ExplodedGraph &getGraph(); 354 355 /// getStateManager - Return the state manager used by the analysis 356 /// engine. 357 ProgramStateManager &getStateManager(); 358 359 virtual void GeneratePathDiagnostic(PathDiagnostic &pathDiagnostic, 360 SmallVectorImpl<BugReport*> &bugReports); 361 362 void addNotableSymbol(SymbolRef Sym) { 363 NotableSymbols.insert(Sym); 364 } 365 366 bool isNotable(SymbolRef Sym) const { 367 return (bool) NotableSymbols.count(Sym); 368 } 369 370 /// classof - Used by isa<>, cast<>, and dyn_cast<>. 371 static bool classof(const BugReporter* R) { 372 return R->getKind() == GRBugReporterKind; 373 } 374}; 375 376class BugReporterContext { 377 GRBugReporter &BR; 378public: 379 BugReporterContext(GRBugReporter& br) : BR(br) {} 380 381 virtual ~BugReporterContext() {} 382 383 GRBugReporter& getBugReporter() { return BR; } 384 385 ExplodedGraph &getGraph() { return BR.getGraph(); } 386 387 void addNotableSymbol(SymbolRef Sym) { 388 // FIXME: For now forward to GRBugReporter. 389 BR.addNotableSymbol(Sym); 390 } 391 392 bool isNotable(SymbolRef Sym) const { 393 // FIXME: For now forward to GRBugReporter. 394 return BR.isNotable(Sym); 395 } 396 397 ProgramStateManager& getStateManager() { 398 return BR.getStateManager(); 399 } 400 401 SValBuilder& getSValBuilder() { 402 return getStateManager().getSValBuilder(); 403 } 404 405 ASTContext &getASTContext() { 406 return BR.getContext(); 407 } 408 409 SourceManager& getSourceManager() { 410 return BR.getSourceManager(); 411 } 412 413 virtual BugReport::NodeResolver& getNodeResolver() = 0; 414}; 415 416} // end GR namespace 417 418} // end clang namespace 419 420#endif 421