1218887Sdim//===--- BugReporter.h - Generate PathDiagnostics --------------*- C++ -*-===// 2218887Sdim// 3218887Sdim// The LLVM Compiler Infrastructure 4218887Sdim// 5218887Sdim// This file is distributed under the University of Illinois Open Source 6218887Sdim// License. See LICENSE.TXT for details. 7218887Sdim// 8218887Sdim//===----------------------------------------------------------------------===// 9218887Sdim// 10218887Sdim// This file defines BugReporter, a utility class for generating 11226633Sdim// PathDiagnostics for analyses based on ProgramState. 12218887Sdim// 13218887Sdim//===----------------------------------------------------------------------===// 14218887Sdim 15218887Sdim#ifndef LLVM_CLANG_GR_BUGREPORTER 16218887Sdim#define LLVM_CLANG_GR_BUGREPORTER 17218887Sdim 18218887Sdim#include "clang/Basic/SourceLocation.h" 19226633Sdim#include "clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitor.h" 20226633Sdim#include "clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h" 21226633Sdim#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h" 22249423Sdim#include "llvm/ADT/DenseSet.h" 23218887Sdim#include "llvm/ADT/FoldingSet.h" 24249423Sdim#include "llvm/ADT/ImmutableSet.h" 25249423Sdim#include "llvm/ADT/SmallSet.h" 26234353Sdim#include "llvm/ADT/ilist.h" 27234353Sdim#include "llvm/ADT/ilist_node.h" 28218887Sdim 29218887Sdimnamespace clang { 30218887Sdim 31218887Sdimclass ASTContext; 32226633Sdimclass DiagnosticsEngine; 33218887Sdimclass Stmt; 34218887Sdimclass ParentMap; 35218887Sdim 36218887Sdimnamespace ento { 37218887Sdim 38218887Sdimclass PathDiagnostic; 39218887Sdimclass ExplodedNode; 40218887Sdimclass ExplodedGraph; 41226633Sdimclass BugReport; 42218887Sdimclass BugReporter; 43218887Sdimclass BugReporterContext; 44218887Sdimclass ExprEngine; 45218887Sdimclass BugType; 46218887Sdim 47218887Sdim//===----------------------------------------------------------------------===// 48218887Sdim// Interface for individual bug reports. 49218887Sdim//===----------------------------------------------------------------------===// 50218887Sdim 51226633Sdim/// This class provides an interface through which checkers can create 52226633Sdim/// individual bug reports. 53234353Sdimclass BugReport : public llvm::ilist_node<BugReport> { 54234353Sdimpublic: 55226633Sdim class NodeResolver { 56234353Sdim virtual void anchor(); 57226633Sdim public: 58226633Sdim virtual ~NodeResolver() {} 59226633Sdim virtual const ExplodedNode* 60226633Sdim getOriginalNode(const ExplodedNode *N) = 0; 61226633Sdim }; 62218887Sdim 63226633Sdim typedef const SourceRange *ranges_iterator; 64234353Sdim typedef SmallVector<BugReporterVisitor *, 8> VisitorList; 65234353Sdim typedef VisitorList::iterator visitor_iterator; 66226633Sdim typedef SmallVector<StringRef, 2> ExtraTextList; 67218887Sdim 68218887Sdimprotected: 69226633Sdim friend class BugReporter; 70226633Sdim friend class BugReportEquivClass; 71226633Sdim 72218887Sdim BugType& BT; 73234353Sdim const Decl *DeclWithIssue; 74218887Sdim std::string ShortDescription; 75218887Sdim std::string Description; 76226633Sdim PathDiagnosticLocation Location; 77234353Sdim PathDiagnosticLocation UniqueingLocation; 78249423Sdim const Decl *UniqueingDecl; 79249423Sdim 80218887Sdim const ExplodedNode *ErrorNode; 81226633Sdim SmallVector<SourceRange, 4> Ranges; 82226633Sdim ExtraTextList ExtraText; 83234353Sdim 84234353Sdim typedef llvm::DenseSet<SymbolRef> Symbols; 85234353Sdim typedef llvm::DenseSet<const MemRegion *> Regions; 86218887Sdim 87239462Sdim /// A (stack of) a set of symbols that are registered with this 88239462Sdim /// report as being "interesting", and thus used to help decide which 89239462Sdim /// diagnostics to include when constructing the final path diagnostic. 90239462Sdim /// The stack is largely used by BugReporter when generating PathDiagnostics 91239462Sdim /// for multiple PathDiagnosticConsumers. 92249423Sdim SmallVector<Symbols *, 2> interestingSymbols; 93234353Sdim 94239462Sdim /// A (stack of) set of regions that are registered with this report as being 95234353Sdim /// "interesting", and thus used to help decide which diagnostics 96234353Sdim /// to include when constructing the final path diagnostic. 97239462Sdim /// The stack is largely used by BugReporter when generating PathDiagnostics 98239462Sdim /// for multiple PathDiagnosticConsumers. 99249423Sdim SmallVector<Regions *, 2> interestingRegions; 100234353Sdim 101243830Sdim /// A set of location contexts that correspoind to call sites which should be 102243830Sdim /// considered "interesting". 103243830Sdim llvm::SmallSet<const LocationContext *, 2> InterestingLocationContexts; 104243830Sdim 105234353Sdim /// A set of custom visitors which generate "event" diagnostics at 106234353Sdim /// interesting points in the path. 107234353Sdim VisitorList Callbacks; 108234353Sdim 109234353Sdim /// Used for ensuring the visitors are only added once. 110226633Sdim llvm::FoldingSet<BugReporterVisitor> CallbacksSet; 111218887Sdim 112234353Sdim /// Used for clients to tell if the report's configuration has changed 113234353Sdim /// since the last time they checked. 114234353Sdim unsigned ConfigurationChangeToken; 115239462Sdim 116239462Sdim /// When set, this flag disables all callstack pruning from a diagnostic 117239462Sdim /// path. This is useful for some reports that want maximum fidelty 118239462Sdim /// when reporting an issue. 119239462Sdim bool DoNotPrunePath; 120234353Sdim 121243830Sdim /// Used to track unique reasons why a bug report might be invalid. 122243830Sdim /// 123243830Sdim /// \sa markInvalid 124243830Sdim /// \sa removeInvalidation 125243830Sdim typedef std::pair<const void *, const void *> InvalidationRecord; 126243830Sdim 127243830Sdim /// If non-empty, this bug report is likely a false positive and should not be 128243830Sdim /// shown to the user. 129243830Sdim /// 130243830Sdim /// \sa markInvalid 131243830Sdim /// \sa removeInvalidation 132243830Sdim llvm::SmallSet<InvalidationRecord, 4> Invalidations; 133243830Sdim 134239462Sdimprivate: 135239462Sdim // Used internally by BugReporter. 136239462Sdim Symbols &getInterestingSymbols(); 137239462Sdim Regions &getInterestingRegions(); 138239462Sdim 139239462Sdim void lazyInitializeInterestingSets(); 140239462Sdim void pushInterestingSymbolsAndRegions(); 141239462Sdim void popInterestingSymbolsAndRegions(); 142239462Sdim 143218887Sdimpublic: 144226633Sdim BugReport(BugType& bt, StringRef desc, const ExplodedNode *errornode) 145234353Sdim : BT(bt), DeclWithIssue(0), Description(desc), ErrorNode(errornode), 146239462Sdim ConfigurationChangeToken(0), DoNotPrunePath(false) {} 147218887Sdim 148226633Sdim BugReport(BugType& bt, StringRef shortDesc, StringRef desc, 149218887Sdim const ExplodedNode *errornode) 150234353Sdim : BT(bt), DeclWithIssue(0), ShortDescription(shortDesc), Description(desc), 151239462Sdim ErrorNode(errornode), ConfigurationChangeToken(0), 152239462Sdim DoNotPrunePath(false) {} 153218887Sdim 154226633Sdim BugReport(BugType& bt, StringRef desc, PathDiagnosticLocation l) 155234353Sdim : BT(bt), DeclWithIssue(0), Description(desc), Location(l), ErrorNode(0), 156239462Sdim ConfigurationChangeToken(0), 157239462Sdim DoNotPrunePath(false) {} 158226633Sdim 159234353Sdim /// \brief Create a BugReport with a custom uniqueing location. 160234353Sdim /// 161234353Sdim /// The reports that have the same report location, description, bug type, and 162234353Sdim /// ranges are uniqued - only one of the equivalent reports will be presented 163234353Sdim /// to the user. This method allows to rest the location which should be used 164234353Sdim /// for uniquing reports. For example, memory leaks checker, could set this to 165234353Sdim /// the allocation site, rather then the location where the bug is reported. 166234353Sdim BugReport(BugType& bt, StringRef desc, const ExplodedNode *errornode, 167249423Sdim PathDiagnosticLocation LocationToUnique, const Decl *DeclToUnique) 168234353Sdim : BT(bt), DeclWithIssue(0), Description(desc), 169234353Sdim UniqueingLocation(LocationToUnique), 170249423Sdim UniqueingDecl(DeclToUnique), 171243830Sdim ErrorNode(errornode), ConfigurationChangeToken(0), 172243830Sdim DoNotPrunePath(false) {} 173234353Sdim 174218887Sdim virtual ~BugReport(); 175218887Sdim 176218887Sdim const BugType& getBugType() const { return BT; } 177218887Sdim BugType& getBugType() { return BT; } 178218887Sdim 179226633Sdim const ExplodedNode *getErrorNode() const { return ErrorNode; } 180218887Sdim 181226633Sdim const StringRef getDescription() const { return Description; } 182218887Sdim 183243830Sdim const StringRef getShortDescription(bool UseFallback = true) const { 184243830Sdim if (ShortDescription.empty() && UseFallback) 185243830Sdim return Description; 186243830Sdim return ShortDescription; 187218887Sdim } 188218887Sdim 189239462Sdim /// Indicates whether or not any path pruning should take place 190239462Sdim /// when generating a PathDiagnostic from this BugReport. 191239462Sdim bool shouldPrunePath() const { return !DoNotPrunePath; } 192239462Sdim 193239462Sdim /// Disable all path pruning when generating a PathDiagnostic. 194239462Sdim void disablePathPruning() { DoNotPrunePath = true; } 195239462Sdim 196234353Sdim void markInteresting(SymbolRef sym); 197234353Sdim void markInteresting(const MemRegion *R); 198234353Sdim void markInteresting(SVal V); 199243830Sdim void markInteresting(const LocationContext *LC); 200234353Sdim 201239462Sdim bool isInteresting(SymbolRef sym); 202239462Sdim bool isInteresting(const MemRegion *R); 203239462Sdim bool isInteresting(SVal V); 204243830Sdim bool isInteresting(const LocationContext *LC); 205234353Sdim 206234353Sdim unsigned getConfigurationChangeToken() const { 207234353Sdim return ConfigurationChangeToken; 208234353Sdim } 209243830Sdim 210243830Sdim /// Returns whether or not this report should be considered valid. 211243830Sdim /// 212243830Sdim /// Invalid reports are those that have been classified as likely false 213243830Sdim /// positives after the fact. 214243830Sdim bool isValid() const { 215243830Sdim return Invalidations.empty(); 216243830Sdim } 217243830Sdim 218243830Sdim /// Marks the current report as invalid, meaning that it is probably a false 219243830Sdim /// positive and should not be reported to the user. 220243830Sdim /// 221243830Sdim /// The \p Tag and \p Data arguments are intended to be opaque identifiers for 222243830Sdim /// this particular invalidation, where \p Tag represents the visitor 223243830Sdim /// responsible for invalidation, and \p Data represents the reason this 224243830Sdim /// visitor decided to invalidate the bug report. 225243830Sdim /// 226243830Sdim /// \sa removeInvalidation 227243830Sdim void markInvalid(const void *Tag, const void *Data) { 228243830Sdim Invalidations.insert(std::make_pair(Tag, Data)); 229243830Sdim } 230243830Sdim 231243830Sdim /// Reverses the effects of a previous invalidation. 232243830Sdim /// 233243830Sdim /// \sa markInvalid 234243830Sdim void removeInvalidation(const void *Tag, const void *Data) { 235243830Sdim Invalidations.erase(std::make_pair(Tag, Data)); 236243830Sdim } 237234353Sdim 238234353Sdim /// Return the canonical declaration, be it a method or class, where 239234353Sdim /// this issue semantically occurred. 240234353Sdim const Decl *getDeclWithIssue() const; 241234353Sdim 242234353Sdim /// Specifically set the Decl where an issue occurred. This isn't necessary 243234353Sdim /// for BugReports that cover a path as it will be automatically inferred. 244234353Sdim void setDeclWithIssue(const Decl *declWithIssue) { 245234353Sdim DeclWithIssue = declWithIssue; 246234353Sdim } 247234353Sdim 248226633Sdim /// \brief This allows for addition of meta data to the diagnostic. 249226633Sdim /// 250226633Sdim /// Currently, only the HTMLDiagnosticClient knows how to display it. 251226633Sdim void addExtraText(StringRef S) { 252226633Sdim ExtraText.push_back(S); 253218887Sdim } 254218887Sdim 255226633Sdim virtual const ExtraTextList &getExtraText() { 256226633Sdim return ExtraText; 257226633Sdim } 258218887Sdim 259226633Sdim /// \brief Return the "definitive" location of the reported bug. 260226633Sdim /// 261218887Sdim /// While a bug can span an entire path, usually there is a specific 262221345Sdim /// location that can be used to identify where the key issue occurred. 263218887Sdim /// This location is used by clients rendering diagnostics. 264226633Sdim virtual PathDiagnosticLocation getLocation(const SourceManager &SM) const; 265218887Sdim 266249423Sdim /// \brief Get the location on which the report should be uniqued. 267249423Sdim PathDiagnosticLocation getUniqueingLocation() const { 268249423Sdim return UniqueingLocation; 269249423Sdim } 270249423Sdim 271249423Sdim /// \brief Get the declaration containing the uniqueing location. 272249423Sdim const Decl *getUniqueingDecl() const { 273249423Sdim return UniqueingDecl; 274249423Sdim } 275249423Sdim 276226633Sdim const Stmt *getStmt() const; 277218887Sdim 278226633Sdim /// \brief Add a range to a bug report. 279226633Sdim /// 280226633Sdim /// Ranges are used to highlight regions of interest in the source code. 281226633Sdim /// They should be at the same source code line as the BugReport location. 282226633Sdim /// By default, the source range of the statement corresponding to the error 283226633Sdim /// node will be used; add a single invalid range to specify absence of 284226633Sdim /// ranges. 285226633Sdim void addRange(SourceRange R) { 286226633Sdim assert((R.isValid() || Ranges.empty()) && "Invalid range can only be used " 287226633Sdim "to specify that the report does not have a range."); 288226633Sdim Ranges.push_back(R); 289226633Sdim } 290218887Sdim 291226633Sdim /// \brief Get the SourceRanges associated with the report. 292226633Sdim virtual std::pair<ranges_iterator, ranges_iterator> getRanges(); 293218887Sdim 294226633Sdim /// \brief Add custom or predefined bug report visitors to this report. 295226633Sdim /// 296226633Sdim /// The visitors should be used when the default trace is not sufficient. 297226633Sdim /// For example, they allow constructing a more elaborate trace. 298226633Sdim /// \sa registerConditionVisitor(), registerTrackNullOrUndefValue(), 299226633Sdim /// registerFindLastStore(), registerNilReceiverVisitor(), and 300226633Sdim /// registerVarDeclsLastStore(). 301226633Sdim void addVisitor(BugReporterVisitor *visitor); 302226633Sdim 303226633Sdim /// Iterators through the custom diagnostic visitors. 304226633Sdim visitor_iterator visitor_begin() { return Callbacks.begin(); } 305226633Sdim visitor_iterator visitor_end() { return Callbacks.end(); } 306226633Sdim 307226633Sdim /// Profile to identify equivalent bug reports for error report coalescing. 308226633Sdim /// Reports are uniqued to ensure that we do not emit multiple diagnostics 309226633Sdim /// for each bug. 310226633Sdim virtual void Profile(llvm::FoldingSetNodeID& hash) const; 311218887Sdim}; 312218887Sdim 313234353Sdim} // end ento namespace 314234353Sdim} // end clang namespace 315234353Sdim 316234353Sdimnamespace llvm { 317234353Sdim template<> struct ilist_traits<clang::ento::BugReport> 318234353Sdim : public ilist_default_traits<clang::ento::BugReport> { 319234353Sdim clang::ento::BugReport *createSentinel() const { 320234353Sdim return static_cast<clang::ento::BugReport *>(&Sentinel); 321234353Sdim } 322234353Sdim void destroySentinel(clang::ento::BugReport *) const {} 323234353Sdim 324234353Sdim clang::ento::BugReport *provideInitialHead() const { 325234353Sdim return createSentinel(); 326234353Sdim } 327234353Sdim clang::ento::BugReport *ensureHead(clang::ento::BugReport *) const { 328234353Sdim return createSentinel(); 329234353Sdim } 330234353Sdim private: 331234353Sdim mutable ilist_half_node<clang::ento::BugReport> Sentinel; 332234353Sdim }; 333234353Sdim} 334234353Sdim 335234353Sdimnamespace clang { 336234353Sdimnamespace ento { 337234353Sdim 338218887Sdim//===----------------------------------------------------------------------===// 339218887Sdim// BugTypes (collections of related reports). 340218887Sdim//===----------------------------------------------------------------------===// 341218887Sdim 342218887Sdimclass BugReportEquivClass : public llvm::FoldingSetNode { 343226633Sdim /// List of *owned* BugReport objects. 344234353Sdim llvm::ilist<BugReport> Reports; 345218887Sdim 346218887Sdim friend class BugReporter; 347218887Sdim void AddReport(BugReport* R) { Reports.push_back(R); } 348218887Sdimpublic: 349218887Sdim BugReportEquivClass(BugReport* R) { Reports.push_back(R); } 350218887Sdim ~BugReportEquivClass(); 351218887Sdim 352218887Sdim void Profile(llvm::FoldingSetNodeID& ID) const { 353218887Sdim assert(!Reports.empty()); 354234353Sdim Reports.front().Profile(ID); 355218887Sdim } 356218887Sdim 357234353Sdim typedef llvm::ilist<BugReport>::iterator iterator; 358234353Sdim typedef llvm::ilist<BugReport>::const_iterator const_iterator; 359218887Sdim 360234353Sdim iterator begin() { return Reports.begin(); } 361234353Sdim iterator end() { return Reports.end(); } 362218887Sdim 363234353Sdim const_iterator begin() const { return Reports.begin(); } 364234353Sdim const_iterator end() const { return Reports.end(); } 365218887Sdim}; 366218887Sdim 367218887Sdim//===----------------------------------------------------------------------===// 368218887Sdim// BugReporter and friends. 369218887Sdim//===----------------------------------------------------------------------===// 370218887Sdim 371218887Sdimclass BugReporterData { 372218887Sdimpublic: 373218887Sdim virtual ~BugReporterData(); 374226633Sdim virtual DiagnosticsEngine& getDiagnostic() = 0; 375239462Sdim virtual ArrayRef<PathDiagnosticConsumer*> getPathDiagnosticConsumers() = 0; 376226633Sdim virtual ASTContext &getASTContext() = 0; 377218887Sdim virtual SourceManager& getSourceManager() = 0; 378218887Sdim}; 379218887Sdim 380226633Sdim/// BugReporter is a utility class for generating PathDiagnostics for analysis. 381226633Sdim/// It collects the BugReports and BugTypes and knows how to generate 382226633Sdim/// and flush the corresponding diagnostics. 383218887Sdimclass BugReporter { 384218887Sdimpublic: 385218887Sdim enum Kind { BaseBRKind, GRBugReporterKind }; 386218887Sdim 387218887Sdimprivate: 388218887Sdim typedef llvm::ImmutableSet<BugType*> BugTypesTy; 389218887Sdim BugTypesTy::Factory F; 390218887Sdim BugTypesTy BugTypes; 391218887Sdim 392218887Sdim const Kind kind; 393218887Sdim BugReporterData& D; 394218887Sdim 395226633Sdim /// Generate and flush the diagnostics for the given bug report. 396218887Sdim void FlushReport(BugReportEquivClass& EQ); 397218887Sdim 398239462Sdim /// Generate and flush the diagnostics for the given bug report 399239462Sdim /// and PathDiagnosticConsumer. 400239462Sdim void FlushReport(BugReport *exampleReport, 401239462Sdim PathDiagnosticConsumer &PD, 402239462Sdim ArrayRef<BugReport*> BugReports); 403239462Sdim 404226633Sdim /// The set of bug reports tracked by the BugReporter. 405219077Sdim llvm::FoldingSet<BugReportEquivClass> EQClasses; 406226633Sdim /// A vector of BugReports for tracking the allocated pointers and cleanup. 407226633Sdim std::vector<BugReportEquivClass *> EQClassesVector; 408219077Sdim 409218887Sdimprotected: 410218887Sdim BugReporter(BugReporterData& d, Kind k) : BugTypes(F.getEmptySet()), kind(k), 411218887Sdim D(d) {} 412218887Sdim 413218887Sdimpublic: 414218887Sdim BugReporter(BugReporterData& d) : BugTypes(F.getEmptySet()), kind(BaseBRKind), 415218887Sdim D(d) {} 416218887Sdim virtual ~BugReporter(); 417218887Sdim 418226633Sdim /// \brief Generate and flush diagnostics for all bug reports. 419218887Sdim void FlushReports(); 420218887Sdim 421218887Sdim Kind getKind() const { return kind; } 422218887Sdim 423226633Sdim DiagnosticsEngine& getDiagnostic() { 424218887Sdim return D.getDiagnostic(); 425218887Sdim } 426218887Sdim 427239462Sdim ArrayRef<PathDiagnosticConsumer*> getPathDiagnosticConsumers() { 428239462Sdim return D.getPathDiagnosticConsumers(); 429218887Sdim } 430218887Sdim 431226633Sdim /// \brief Iterator over the set of BugTypes tracked by the BugReporter. 432218887Sdim typedef BugTypesTy::iterator iterator; 433218887Sdim iterator begin() { return BugTypes.begin(); } 434218887Sdim iterator end() { return BugTypes.end(); } 435218887Sdim 436226633Sdim /// \brief Iterator over the set of BugReports tracked by the BugReporter. 437219077Sdim typedef llvm::FoldingSet<BugReportEquivClass>::iterator EQClasses_iterator; 438219077Sdim EQClasses_iterator EQClasses_begin() { return EQClasses.begin(); } 439219077Sdim EQClasses_iterator EQClasses_end() { return EQClasses.end(); } 440219077Sdim 441226633Sdim ASTContext &getContext() { return D.getASTContext(); } 442218887Sdim 443218887Sdim SourceManager& getSourceManager() { return D.getSourceManager(); } 444218887Sdim 445243830Sdim virtual bool generatePathDiagnostic(PathDiagnostic& pathDiagnostic, 446239462Sdim PathDiagnosticConsumer &PC, 447243830Sdim ArrayRef<BugReport *> &bugReports) { 448243830Sdim return true; 449243830Sdim } 450218887Sdim 451249423Sdim bool RemoveUnneededCalls(PathPieces &pieces, BugReport *R); 452243830Sdim 453218887Sdim void Register(BugType *BT); 454218887Sdim 455226633Sdim /// \brief Add the given report to the set of reports tracked by BugReporter. 456226633Sdim /// 457226633Sdim /// The reports are usually generated by the checkers. Further, they are 458226633Sdim /// folded based on the profile value, which is done to coalesce similar 459226633Sdim /// reports. 460243830Sdim void emitReport(BugReport *R); 461218887Sdim 462234353Sdim void EmitBasicReport(const Decl *DeclWithIssue, 463234353Sdim StringRef BugName, StringRef BugCategory, 464226633Sdim StringRef BugStr, PathDiagnosticLocation Loc, 465218887Sdim SourceRange* RangeBeg, unsigned NumRanges); 466218887Sdim 467234353Sdim void EmitBasicReport(const Decl *DeclWithIssue, 468234353Sdim StringRef BugName, StringRef BugCategory, 469226633Sdim StringRef BugStr, PathDiagnosticLocation Loc) { 470234353Sdim EmitBasicReport(DeclWithIssue, BugName, BugCategory, BugStr, Loc, 0, 0); 471218887Sdim } 472218887Sdim 473234353Sdim void EmitBasicReport(const Decl *DeclWithIssue, 474234353Sdim StringRef BugName, StringRef Category, 475226633Sdim StringRef BugStr, PathDiagnosticLocation Loc, 476218887Sdim SourceRange R) { 477234353Sdim EmitBasicReport(DeclWithIssue, BugName, Category, BugStr, Loc, &R, 1); 478218887Sdim } 479218887Sdim 480219077Sdimprivate: 481219077Sdim llvm::StringMap<BugType *> StrBugTypes; 482219077Sdim 483219077Sdim /// \brief Returns a BugType that is associated with the given name and 484219077Sdim /// category. 485226633Sdim BugType *getBugTypeForName(StringRef name, StringRef category); 486218887Sdim}; 487218887Sdim 488218887Sdim// FIXME: Get rid of GRBugReporter. It's the wrong abstraction. 489218887Sdimclass GRBugReporter : public BugReporter { 490218887Sdim ExprEngine& Eng; 491218887Sdimpublic: 492218887Sdim GRBugReporter(BugReporterData& d, ExprEngine& eng) 493218887Sdim : BugReporter(d, GRBugReporterKind), Eng(eng) {} 494218887Sdim 495218887Sdim virtual ~GRBugReporter(); 496218887Sdim 497218887Sdim /// getEngine - Return the analysis engine used to analyze a given 498218887Sdim /// function or method. 499218887Sdim ExprEngine &getEngine() { return Eng; } 500218887Sdim 501218887Sdim /// getGraph - Get the exploded graph created by the analysis engine 502218887Sdim /// for the analyzed method or function. 503218887Sdim ExplodedGraph &getGraph(); 504218887Sdim 505218887Sdim /// getStateManager - Return the state manager used by the analysis 506218887Sdim /// engine. 507226633Sdim ProgramStateManager &getStateManager(); 508218887Sdim 509243830Sdim /// Generates a path corresponding to one of the given bug reports. 510243830Sdim /// 511243830Sdim /// Which report is used for path generation is not specified. The 512243830Sdim /// bug reporter will try to pick the shortest path, but this is not 513243830Sdim /// guaranteed. 514243830Sdim /// 515243830Sdim /// \return True if the report was valid and a path was generated, 516243830Sdim /// false if the reports should be considered invalid. 517243830Sdim virtual bool generatePathDiagnostic(PathDiagnostic &PD, 518239462Sdim PathDiagnosticConsumer &PC, 519239462Sdim ArrayRef<BugReport*> &bugReports); 520218887Sdim 521218887Sdim /// classof - Used by isa<>, cast<>, and dyn_cast<>. 522218887Sdim static bool classof(const BugReporter* R) { 523218887Sdim return R->getKind() == GRBugReporterKind; 524218887Sdim } 525218887Sdim}; 526218887Sdim 527218887Sdimclass BugReporterContext { 528234353Sdim virtual void anchor(); 529218887Sdim GRBugReporter &BR; 530218887Sdimpublic: 531226633Sdim BugReporterContext(GRBugReporter& br) : BR(br) {} 532218887Sdim 533226633Sdim virtual ~BugReporterContext() {} 534218887Sdim 535218887Sdim GRBugReporter& getBugReporter() { return BR; } 536218887Sdim 537218887Sdim ExplodedGraph &getGraph() { return BR.getGraph(); } 538218887Sdim 539226633Sdim ProgramStateManager& getStateManager() { 540218887Sdim return BR.getStateManager(); 541218887Sdim } 542218887Sdim 543218887Sdim SValBuilder& getSValBuilder() { 544218887Sdim return getStateManager().getSValBuilder(); 545218887Sdim } 546218887Sdim 547226633Sdim ASTContext &getASTContext() { 548218887Sdim return BR.getContext(); 549218887Sdim } 550218887Sdim 551218887Sdim SourceManager& getSourceManager() { 552218887Sdim return BR.getSourceManager(); 553218887Sdim } 554218887Sdim 555218887Sdim virtual BugReport::NodeResolver& getNodeResolver() = 0; 556218887Sdim}; 557218887Sdim 558218887Sdim} // end GR namespace 559218887Sdim 560218887Sdim} // end clang namespace 561218887Sdim 562218887Sdim#endif 563