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" 19263508Sdim#include "clang/StaticAnalyzer/Core/AnalyzerOptions.h" 20226633Sdim#include "clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitor.h" 21226633Sdim#include "clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h" 22226633Sdim#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h" 23249423Sdim#include "llvm/ADT/DenseSet.h" 24218887Sdim#include "llvm/ADT/FoldingSet.h" 25249423Sdim#include "llvm/ADT/ImmutableSet.h" 26249423Sdim#include "llvm/ADT/SmallSet.h" 27234353Sdim#include "llvm/ADT/ilist.h" 28234353Sdim#include "llvm/ADT/ilist_node.h" 29218887Sdim 30218887Sdimnamespace clang { 31218887Sdim 32218887Sdimclass ASTContext; 33226633Sdimclass DiagnosticsEngine; 34218887Sdimclass Stmt; 35218887Sdimclass ParentMap; 36218887Sdim 37218887Sdimnamespace ento { 38218887Sdim 39218887Sdimclass PathDiagnostic; 40218887Sdimclass ExplodedNode; 41218887Sdimclass ExplodedGraph; 42226633Sdimclass BugReport; 43218887Sdimclass BugReporter; 44218887Sdimclass BugReporterContext; 45218887Sdimclass ExprEngine; 46218887Sdimclass BugType; 47218887Sdim 48218887Sdim//===----------------------------------------------------------------------===// 49218887Sdim// Interface for individual bug reports. 50218887Sdim//===----------------------------------------------------------------------===// 51218887Sdim 52226633Sdim/// This class provides an interface through which checkers can create 53226633Sdim/// individual bug reports. 54234353Sdimclass BugReport : public llvm::ilist_node<BugReport> { 55234353Sdimpublic: 56226633Sdim class NodeResolver { 57234353Sdim virtual void anchor(); 58226633Sdim public: 59226633Sdim virtual ~NodeResolver() {} 60226633Sdim virtual const ExplodedNode* 61226633Sdim getOriginalNode(const ExplodedNode *N) = 0; 62226633Sdim }; 63218887Sdim 64226633Sdim typedef const SourceRange *ranges_iterator; 65234353Sdim typedef SmallVector<BugReporterVisitor *, 8> VisitorList; 66234353Sdim typedef VisitorList::iterator visitor_iterator; 67226633Sdim typedef SmallVector<StringRef, 2> ExtraTextList; 68218887Sdim 69218887Sdimprotected: 70226633Sdim friend class BugReporter; 71226633Sdim friend class BugReportEquivClass; 72226633Sdim 73218887Sdim BugType& BT; 74234353Sdim const Decl *DeclWithIssue; 75218887Sdim std::string ShortDescription; 76218887Sdim std::string Description; 77226633Sdim PathDiagnosticLocation Location; 78234353Sdim PathDiagnosticLocation UniqueingLocation; 79249423Sdim const Decl *UniqueingDecl; 80249423Sdim 81218887Sdim const ExplodedNode *ErrorNode; 82226633Sdim SmallVector<SourceRange, 4> Ranges; 83226633Sdim ExtraTextList ExtraText; 84234353Sdim 85234353Sdim typedef llvm::DenseSet<SymbolRef> Symbols; 86234353Sdim typedef llvm::DenseSet<const MemRegion *> Regions; 87218887Sdim 88239462Sdim /// A (stack of) a set of symbols that are registered with this 89239462Sdim /// report as being "interesting", and thus used to help decide which 90239462Sdim /// diagnostics to include when constructing the final path diagnostic. 91239462Sdim /// The stack is largely used by BugReporter when generating PathDiagnostics 92239462Sdim /// for multiple PathDiagnosticConsumers. 93249423Sdim SmallVector<Symbols *, 2> interestingSymbols; 94234353Sdim 95239462Sdim /// A (stack of) set of regions that are registered with this report as being 96234353Sdim /// "interesting", and thus used to help decide which diagnostics 97234353Sdim /// to include when constructing the final path diagnostic. 98239462Sdim /// The stack is largely used by BugReporter when generating PathDiagnostics 99239462Sdim /// for multiple PathDiagnosticConsumers. 100249423Sdim SmallVector<Regions *, 2> interestingRegions; 101234353Sdim 102243830Sdim /// A set of location contexts that correspoind to call sites which should be 103243830Sdim /// considered "interesting". 104243830Sdim llvm::SmallSet<const LocationContext *, 2> InterestingLocationContexts; 105243830Sdim 106234353Sdim /// A set of custom visitors which generate "event" diagnostics at 107234353Sdim /// interesting points in the path. 108234353Sdim VisitorList Callbacks; 109234353Sdim 110234353Sdim /// Used for ensuring the visitors are only added once. 111226633Sdim llvm::FoldingSet<BugReporterVisitor> CallbacksSet; 112218887Sdim 113234353Sdim /// Used for clients to tell if the report's configuration has changed 114234353Sdim /// since the last time they checked. 115234353Sdim unsigned ConfigurationChangeToken; 116239462Sdim 117239462Sdim /// When set, this flag disables all callstack pruning from a diagnostic 118239462Sdim /// path. This is useful for some reports that want maximum fidelty 119239462Sdim /// when reporting an issue. 120239462Sdim bool DoNotPrunePath; 121234353Sdim 122243830Sdim /// Used to track unique reasons why a bug report might be invalid. 123243830Sdim /// 124243830Sdim /// \sa markInvalid 125243830Sdim /// \sa removeInvalidation 126243830Sdim typedef std::pair<const void *, const void *> InvalidationRecord; 127243830Sdim 128243830Sdim /// If non-empty, this bug report is likely a false positive and should not be 129243830Sdim /// shown to the user. 130243830Sdim /// 131243830Sdim /// \sa markInvalid 132243830Sdim /// \sa removeInvalidation 133243830Sdim llvm::SmallSet<InvalidationRecord, 4> Invalidations; 134243830Sdim 135239462Sdimprivate: 136239462Sdim // Used internally by BugReporter. 137239462Sdim Symbols &getInterestingSymbols(); 138239462Sdim Regions &getInterestingRegions(); 139239462Sdim 140239462Sdim void lazyInitializeInterestingSets(); 141239462Sdim void pushInterestingSymbolsAndRegions(); 142239462Sdim void popInterestingSymbolsAndRegions(); 143239462Sdim 144218887Sdimpublic: 145226633Sdim BugReport(BugType& bt, StringRef desc, const ExplodedNode *errornode) 146234353Sdim : BT(bt), DeclWithIssue(0), Description(desc), ErrorNode(errornode), 147239462Sdim ConfigurationChangeToken(0), DoNotPrunePath(false) {} 148218887Sdim 149226633Sdim BugReport(BugType& bt, StringRef shortDesc, StringRef desc, 150218887Sdim const ExplodedNode *errornode) 151234353Sdim : BT(bt), DeclWithIssue(0), ShortDescription(shortDesc), Description(desc), 152239462Sdim ErrorNode(errornode), ConfigurationChangeToken(0), 153239462Sdim DoNotPrunePath(false) {} 154218887Sdim 155226633Sdim BugReport(BugType& bt, StringRef desc, PathDiagnosticLocation l) 156234353Sdim : BT(bt), DeclWithIssue(0), Description(desc), Location(l), ErrorNode(0), 157239462Sdim ConfigurationChangeToken(0), 158239462Sdim DoNotPrunePath(false) {} 159226633Sdim 160234353Sdim /// \brief Create a BugReport with a custom uniqueing location. 161234353Sdim /// 162234353Sdim /// The reports that have the same report location, description, bug type, and 163234353Sdim /// ranges are uniqued - only one of the equivalent reports will be presented 164234353Sdim /// to the user. This method allows to rest the location which should be used 165234353Sdim /// for uniquing reports. For example, memory leaks checker, could set this to 166234353Sdim /// the allocation site, rather then the location where the bug is reported. 167234353Sdim BugReport(BugType& bt, StringRef desc, const ExplodedNode *errornode, 168249423Sdim PathDiagnosticLocation LocationToUnique, const Decl *DeclToUnique) 169234353Sdim : BT(bt), DeclWithIssue(0), Description(desc), 170234353Sdim UniqueingLocation(LocationToUnique), 171249423Sdim UniqueingDecl(DeclToUnique), 172243830Sdim ErrorNode(errornode), ConfigurationChangeToken(0), 173243830Sdim DoNotPrunePath(false) {} 174234353Sdim 175218887Sdim virtual ~BugReport(); 176218887Sdim 177218887Sdim const BugType& getBugType() const { return BT; } 178218887Sdim BugType& getBugType() { return BT; } 179218887Sdim 180226633Sdim const ExplodedNode *getErrorNode() const { return ErrorNode; } 181218887Sdim 182226633Sdim const StringRef getDescription() const { return Description; } 183218887Sdim 184243830Sdim const StringRef getShortDescription(bool UseFallback = true) const { 185243830Sdim if (ShortDescription.empty() && UseFallback) 186243830Sdim return Description; 187243830Sdim return ShortDescription; 188218887Sdim } 189218887Sdim 190239462Sdim /// Indicates whether or not any path pruning should take place 191239462Sdim /// when generating a PathDiagnostic from this BugReport. 192239462Sdim bool shouldPrunePath() const { return !DoNotPrunePath; } 193239462Sdim 194239462Sdim /// Disable all path pruning when generating a PathDiagnostic. 195239462Sdim void disablePathPruning() { DoNotPrunePath = true; } 196239462Sdim 197234353Sdim void markInteresting(SymbolRef sym); 198234353Sdim void markInteresting(const MemRegion *R); 199234353Sdim void markInteresting(SVal V); 200243830Sdim void markInteresting(const LocationContext *LC); 201234353Sdim 202239462Sdim bool isInteresting(SymbolRef sym); 203239462Sdim bool isInteresting(const MemRegion *R); 204239462Sdim bool isInteresting(SVal V); 205243830Sdim bool isInteresting(const LocationContext *LC); 206234353Sdim 207234353Sdim unsigned getConfigurationChangeToken() const { 208234353Sdim return ConfigurationChangeToken; 209234353Sdim } 210243830Sdim 211243830Sdim /// Returns whether or not this report should be considered valid. 212243830Sdim /// 213243830Sdim /// Invalid reports are those that have been classified as likely false 214243830Sdim /// positives after the fact. 215243830Sdim bool isValid() const { 216243830Sdim return Invalidations.empty(); 217243830Sdim } 218243830Sdim 219243830Sdim /// Marks the current report as invalid, meaning that it is probably a false 220243830Sdim /// positive and should not be reported to the user. 221243830Sdim /// 222243830Sdim /// The \p Tag and \p Data arguments are intended to be opaque identifiers for 223243830Sdim /// this particular invalidation, where \p Tag represents the visitor 224243830Sdim /// responsible for invalidation, and \p Data represents the reason this 225243830Sdim /// visitor decided to invalidate the bug report. 226243830Sdim /// 227243830Sdim /// \sa removeInvalidation 228243830Sdim void markInvalid(const void *Tag, const void *Data) { 229243830Sdim Invalidations.insert(std::make_pair(Tag, Data)); 230243830Sdim } 231243830Sdim 232243830Sdim /// Reverses the effects of a previous invalidation. 233243830Sdim /// 234243830Sdim /// \sa markInvalid 235243830Sdim void removeInvalidation(const void *Tag, const void *Data) { 236243830Sdim Invalidations.erase(std::make_pair(Tag, Data)); 237243830Sdim } 238234353Sdim 239234353Sdim /// Return the canonical declaration, be it a method or class, where 240234353Sdim /// this issue semantically occurred. 241234353Sdim const Decl *getDeclWithIssue() const; 242234353Sdim 243234353Sdim /// Specifically set the Decl where an issue occurred. This isn't necessary 244234353Sdim /// for BugReports that cover a path as it will be automatically inferred. 245234353Sdim void setDeclWithIssue(const Decl *declWithIssue) { 246234353Sdim DeclWithIssue = declWithIssue; 247234353Sdim } 248234353Sdim 249226633Sdim /// \brief This allows for addition of meta data to the diagnostic. 250226633Sdim /// 251226633Sdim /// Currently, only the HTMLDiagnosticClient knows how to display it. 252226633Sdim void addExtraText(StringRef S) { 253226633Sdim ExtraText.push_back(S); 254218887Sdim } 255218887Sdim 256226633Sdim virtual const ExtraTextList &getExtraText() { 257226633Sdim return ExtraText; 258226633Sdim } 259218887Sdim 260226633Sdim /// \brief Return the "definitive" location of the reported bug. 261226633Sdim /// 262218887Sdim /// While a bug can span an entire path, usually there is a specific 263221345Sdim /// location that can be used to identify where the key issue occurred. 264218887Sdim /// This location is used by clients rendering diagnostics. 265226633Sdim virtual PathDiagnosticLocation getLocation(const SourceManager &SM) const; 266218887Sdim 267249423Sdim /// \brief Get the location on which the report should be uniqued. 268249423Sdim PathDiagnosticLocation getUniqueingLocation() const { 269249423Sdim return UniqueingLocation; 270249423Sdim } 271249423Sdim 272249423Sdim /// \brief Get the declaration containing the uniqueing location. 273249423Sdim const Decl *getUniqueingDecl() const { 274249423Sdim return UniqueingDecl; 275249423Sdim } 276249423Sdim 277226633Sdim const Stmt *getStmt() const; 278218887Sdim 279226633Sdim /// \brief Add a range to a bug report. 280226633Sdim /// 281226633Sdim /// Ranges are used to highlight regions of interest in the source code. 282226633Sdim /// They should be at the same source code line as the BugReport location. 283226633Sdim /// By default, the source range of the statement corresponding to the error 284226633Sdim /// node will be used; add a single invalid range to specify absence of 285226633Sdim /// ranges. 286226633Sdim void addRange(SourceRange R) { 287226633Sdim assert((R.isValid() || Ranges.empty()) && "Invalid range can only be used " 288226633Sdim "to specify that the report does not have a range."); 289226633Sdim Ranges.push_back(R); 290226633Sdim } 291218887Sdim 292226633Sdim /// \brief Get the SourceRanges associated with the report. 293226633Sdim virtual std::pair<ranges_iterator, ranges_iterator> getRanges(); 294218887Sdim 295226633Sdim /// \brief Add custom or predefined bug report visitors to this report. 296226633Sdim /// 297226633Sdim /// The visitors should be used when the default trace is not sufficient. 298226633Sdim /// For example, they allow constructing a more elaborate trace. 299226633Sdim /// \sa registerConditionVisitor(), registerTrackNullOrUndefValue(), 300226633Sdim /// registerFindLastStore(), registerNilReceiverVisitor(), and 301226633Sdim /// registerVarDeclsLastStore(). 302226633Sdim void addVisitor(BugReporterVisitor *visitor); 303226633Sdim 304226633Sdim /// Iterators through the custom diagnostic visitors. 305226633Sdim visitor_iterator visitor_begin() { return Callbacks.begin(); } 306226633Sdim visitor_iterator visitor_end() { return Callbacks.end(); } 307226633Sdim 308226633Sdim /// Profile to identify equivalent bug reports for error report coalescing. 309226633Sdim /// Reports are uniqued to ensure that we do not emit multiple diagnostics 310226633Sdim /// for each bug. 311226633Sdim virtual void Profile(llvm::FoldingSetNodeID& hash) const; 312218887Sdim}; 313218887Sdim 314234353Sdim} // end ento namespace 315234353Sdim} // end clang namespace 316234353Sdim 317234353Sdimnamespace llvm { 318234353Sdim template<> struct ilist_traits<clang::ento::BugReport> 319234353Sdim : public ilist_default_traits<clang::ento::BugReport> { 320234353Sdim clang::ento::BugReport *createSentinel() const { 321234353Sdim return static_cast<clang::ento::BugReport *>(&Sentinel); 322234353Sdim } 323234353Sdim void destroySentinel(clang::ento::BugReport *) const {} 324234353Sdim 325234353Sdim clang::ento::BugReport *provideInitialHead() const { 326234353Sdim return createSentinel(); 327234353Sdim } 328234353Sdim clang::ento::BugReport *ensureHead(clang::ento::BugReport *) const { 329234353Sdim return createSentinel(); 330234353Sdim } 331234353Sdim private: 332234353Sdim mutable ilist_half_node<clang::ento::BugReport> Sentinel; 333234353Sdim }; 334234353Sdim} 335234353Sdim 336234353Sdimnamespace clang { 337234353Sdimnamespace ento { 338234353Sdim 339218887Sdim//===----------------------------------------------------------------------===// 340218887Sdim// BugTypes (collections of related reports). 341218887Sdim//===----------------------------------------------------------------------===// 342218887Sdim 343218887Sdimclass BugReportEquivClass : public llvm::FoldingSetNode { 344226633Sdim /// List of *owned* BugReport objects. 345234353Sdim llvm::ilist<BugReport> Reports; 346218887Sdim 347218887Sdim friend class BugReporter; 348218887Sdim void AddReport(BugReport* R) { Reports.push_back(R); } 349218887Sdimpublic: 350218887Sdim BugReportEquivClass(BugReport* R) { Reports.push_back(R); } 351218887Sdim ~BugReportEquivClass(); 352218887Sdim 353218887Sdim void Profile(llvm::FoldingSetNodeID& ID) const { 354218887Sdim assert(!Reports.empty()); 355234353Sdim Reports.front().Profile(ID); 356218887Sdim } 357218887Sdim 358234353Sdim typedef llvm::ilist<BugReport>::iterator iterator; 359234353Sdim typedef llvm::ilist<BugReport>::const_iterator const_iterator; 360218887Sdim 361234353Sdim iterator begin() { return Reports.begin(); } 362234353Sdim iterator end() { return Reports.end(); } 363218887Sdim 364234353Sdim const_iterator begin() const { return Reports.begin(); } 365234353Sdim const_iterator end() const { return Reports.end(); } 366218887Sdim}; 367218887Sdim 368218887Sdim//===----------------------------------------------------------------------===// 369218887Sdim// BugReporter and friends. 370218887Sdim//===----------------------------------------------------------------------===// 371218887Sdim 372218887Sdimclass BugReporterData { 373218887Sdimpublic: 374218887Sdim virtual ~BugReporterData(); 375226633Sdim virtual DiagnosticsEngine& getDiagnostic() = 0; 376239462Sdim virtual ArrayRef<PathDiagnosticConsumer*> getPathDiagnosticConsumers() = 0; 377226633Sdim virtual ASTContext &getASTContext() = 0; 378218887Sdim virtual SourceManager& getSourceManager() = 0; 379263508Sdim virtual AnalyzerOptions& getAnalyzerOptions() = 0; 380218887Sdim}; 381218887Sdim 382226633Sdim/// BugReporter is a utility class for generating PathDiagnostics for analysis. 383226633Sdim/// It collects the BugReports and BugTypes and knows how to generate 384226633Sdim/// and flush the corresponding diagnostics. 385218887Sdimclass BugReporter { 386218887Sdimpublic: 387218887Sdim enum Kind { BaseBRKind, GRBugReporterKind }; 388218887Sdim 389218887Sdimprivate: 390218887Sdim typedef llvm::ImmutableSet<BugType*> BugTypesTy; 391218887Sdim BugTypesTy::Factory F; 392218887Sdim BugTypesTy BugTypes; 393218887Sdim 394218887Sdim const Kind kind; 395218887Sdim BugReporterData& D; 396218887Sdim 397226633Sdim /// Generate and flush the diagnostics for the given bug report. 398218887Sdim void FlushReport(BugReportEquivClass& EQ); 399218887Sdim 400239462Sdim /// Generate and flush the diagnostics for the given bug report 401239462Sdim /// and PathDiagnosticConsumer. 402239462Sdim void FlushReport(BugReport *exampleReport, 403239462Sdim PathDiagnosticConsumer &PD, 404239462Sdim ArrayRef<BugReport*> BugReports); 405239462Sdim 406226633Sdim /// The set of bug reports tracked by the BugReporter. 407219077Sdim llvm::FoldingSet<BugReportEquivClass> EQClasses; 408226633Sdim /// A vector of BugReports for tracking the allocated pointers and cleanup. 409226633Sdim std::vector<BugReportEquivClass *> EQClassesVector; 410219077Sdim 411218887Sdimprotected: 412218887Sdim BugReporter(BugReporterData& d, Kind k) : BugTypes(F.getEmptySet()), kind(k), 413218887Sdim D(d) {} 414218887Sdim 415218887Sdimpublic: 416218887Sdim BugReporter(BugReporterData& d) : BugTypes(F.getEmptySet()), kind(BaseBRKind), 417218887Sdim D(d) {} 418218887Sdim virtual ~BugReporter(); 419218887Sdim 420226633Sdim /// \brief Generate and flush diagnostics for all bug reports. 421218887Sdim void FlushReports(); 422218887Sdim 423218887Sdim Kind getKind() const { return kind; } 424218887Sdim 425226633Sdim DiagnosticsEngine& getDiagnostic() { 426218887Sdim return D.getDiagnostic(); 427218887Sdim } 428218887Sdim 429239462Sdim ArrayRef<PathDiagnosticConsumer*> getPathDiagnosticConsumers() { 430239462Sdim return D.getPathDiagnosticConsumers(); 431218887Sdim } 432218887Sdim 433226633Sdim /// \brief Iterator over the set of BugTypes tracked by the BugReporter. 434218887Sdim typedef BugTypesTy::iterator iterator; 435218887Sdim iterator begin() { return BugTypes.begin(); } 436218887Sdim iterator end() { return BugTypes.end(); } 437218887Sdim 438226633Sdim /// \brief Iterator over the set of BugReports tracked by the BugReporter. 439219077Sdim typedef llvm::FoldingSet<BugReportEquivClass>::iterator EQClasses_iterator; 440219077Sdim EQClasses_iterator EQClasses_begin() { return EQClasses.begin(); } 441219077Sdim EQClasses_iterator EQClasses_end() { return EQClasses.end(); } 442219077Sdim 443226633Sdim ASTContext &getContext() { return D.getASTContext(); } 444218887Sdim 445218887Sdim SourceManager& getSourceManager() { return D.getSourceManager(); } 446218887Sdim 447263508Sdim AnalyzerOptions& getAnalyzerOptions() { return D.getAnalyzerOptions(); } 448263508Sdim 449243830Sdim virtual bool generatePathDiagnostic(PathDiagnostic& pathDiagnostic, 450239462Sdim PathDiagnosticConsumer &PC, 451243830Sdim ArrayRef<BugReport *> &bugReports) { 452243830Sdim return true; 453243830Sdim } 454218887Sdim 455249423Sdim bool RemoveUnneededCalls(PathPieces &pieces, BugReport *R); 456243830Sdim 457218887Sdim void Register(BugType *BT); 458218887Sdim 459226633Sdim /// \brief Add the given report to the set of reports tracked by BugReporter. 460226633Sdim /// 461226633Sdim /// The reports are usually generated by the checkers. Further, they are 462226633Sdim /// folded based on the profile value, which is done to coalesce similar 463226633Sdim /// reports. 464243830Sdim void emitReport(BugReport *R); 465218887Sdim 466234353Sdim void EmitBasicReport(const Decl *DeclWithIssue, 467234353Sdim StringRef BugName, StringRef BugCategory, 468226633Sdim StringRef BugStr, PathDiagnosticLocation Loc, 469263508Sdim ArrayRef<SourceRange> Ranges = None); 470218887Sdim 471219077Sdimprivate: 472219077Sdim llvm::StringMap<BugType *> StrBugTypes; 473219077Sdim 474219077Sdim /// \brief Returns a BugType that is associated with the given name and 475219077Sdim /// category. 476226633Sdim BugType *getBugTypeForName(StringRef name, StringRef category); 477218887Sdim}; 478218887Sdim 479218887Sdim// FIXME: Get rid of GRBugReporter. It's the wrong abstraction. 480218887Sdimclass GRBugReporter : public BugReporter { 481218887Sdim ExprEngine& Eng; 482218887Sdimpublic: 483218887Sdim GRBugReporter(BugReporterData& d, ExprEngine& eng) 484218887Sdim : BugReporter(d, GRBugReporterKind), Eng(eng) {} 485218887Sdim 486218887Sdim virtual ~GRBugReporter(); 487218887Sdim 488218887Sdim /// getEngine - Return the analysis engine used to analyze a given 489218887Sdim /// function or method. 490218887Sdim ExprEngine &getEngine() { return Eng; } 491218887Sdim 492218887Sdim /// getGraph - Get the exploded graph created by the analysis engine 493218887Sdim /// for the analyzed method or function. 494218887Sdim ExplodedGraph &getGraph(); 495218887Sdim 496218887Sdim /// getStateManager - Return the state manager used by the analysis 497218887Sdim /// engine. 498226633Sdim ProgramStateManager &getStateManager(); 499218887Sdim 500243830Sdim /// Generates a path corresponding to one of the given bug reports. 501243830Sdim /// 502243830Sdim /// Which report is used for path generation is not specified. The 503243830Sdim /// bug reporter will try to pick the shortest path, but this is not 504243830Sdim /// guaranteed. 505243830Sdim /// 506243830Sdim /// \return True if the report was valid and a path was generated, 507243830Sdim /// false if the reports should be considered invalid. 508243830Sdim virtual bool generatePathDiagnostic(PathDiagnostic &PD, 509239462Sdim PathDiagnosticConsumer &PC, 510239462Sdim ArrayRef<BugReport*> &bugReports); 511218887Sdim 512218887Sdim /// classof - Used by isa<>, cast<>, and dyn_cast<>. 513218887Sdim static bool classof(const BugReporter* R) { 514218887Sdim return R->getKind() == GRBugReporterKind; 515218887Sdim } 516218887Sdim}; 517218887Sdim 518218887Sdimclass BugReporterContext { 519234353Sdim virtual void anchor(); 520218887Sdim GRBugReporter &BR; 521218887Sdimpublic: 522226633Sdim BugReporterContext(GRBugReporter& br) : BR(br) {} 523218887Sdim 524226633Sdim virtual ~BugReporterContext() {} 525218887Sdim 526218887Sdim GRBugReporter& getBugReporter() { return BR; } 527218887Sdim 528218887Sdim ExplodedGraph &getGraph() { return BR.getGraph(); } 529218887Sdim 530226633Sdim ProgramStateManager& getStateManager() { 531218887Sdim return BR.getStateManager(); 532218887Sdim } 533218887Sdim 534218887Sdim SValBuilder& getSValBuilder() { 535218887Sdim return getStateManager().getSValBuilder(); 536218887Sdim } 537218887Sdim 538226633Sdim ASTContext &getASTContext() { 539218887Sdim return BR.getContext(); 540218887Sdim } 541218887Sdim 542218887Sdim SourceManager& getSourceManager() { 543218887Sdim return BR.getSourceManager(); 544218887Sdim } 545218887Sdim 546218887Sdim virtual BugReport::NodeResolver& getNodeResolver() = 0; 547218887Sdim}; 548218887Sdim 549218887Sdim} // end GR namespace 550218887Sdim 551218887Sdim} // end clang namespace 552218887Sdim 553218887Sdim#endif 554