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 11226890Sdim// 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" 19263509Sdim#include "clang/StaticAnalyzer/Core/AnalyzerOptions.h" 20226890Sdim#include "clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitor.h" 21226890Sdim#include "clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h" 22226890Sdim#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h" 23252723Sdim#include "llvm/ADT/DenseSet.h" 24218887Sdim#include "llvm/ADT/FoldingSet.h" 25252723Sdim#include "llvm/ADT/ImmutableSet.h" 26252723Sdim#include "llvm/ADT/SmallSet.h" 27235633Sdim#include "llvm/ADT/ilist.h" 28235633Sdim#include "llvm/ADT/ilist_node.h" 29218887Sdim 30218887Sdimnamespace clang { 31218887Sdim 32218887Sdimclass ASTContext; 33226890Sdimclass DiagnosticsEngine; 34218887Sdimclass Stmt; 35218887Sdimclass ParentMap; 36218887Sdim 37218887Sdimnamespace ento { 38218887Sdim 39218887Sdimclass PathDiagnostic; 40218887Sdimclass ExplodedNode; 41218887Sdimclass ExplodedGraph; 42226890Sdimclass BugReport; 43218887Sdimclass BugReporter; 44218887Sdimclass BugReporterContext; 45218887Sdimclass ExprEngine; 46218887Sdimclass BugType; 47218887Sdim 48218887Sdim//===----------------------------------------------------------------------===// 49218887Sdim// Interface for individual bug reports. 50218887Sdim//===----------------------------------------------------------------------===// 51218887Sdim 52226890Sdim/// This class provides an interface through which checkers can create 53226890Sdim/// individual bug reports. 54235633Sdimclass BugReport : public llvm::ilist_node<BugReport> { 55235633Sdimpublic: 56226890Sdim class NodeResolver { 57235633Sdim virtual void anchor(); 58226890Sdim public: 59226890Sdim virtual ~NodeResolver() {} 60226890Sdim virtual const ExplodedNode* 61226890Sdim getOriginalNode(const ExplodedNode *N) = 0; 62226890Sdim }; 63218887Sdim 64226890Sdim typedef const SourceRange *ranges_iterator; 65235633Sdim typedef SmallVector<BugReporterVisitor *, 8> VisitorList; 66235633Sdim typedef VisitorList::iterator visitor_iterator; 67226890Sdim typedef SmallVector<StringRef, 2> ExtraTextList; 68218887Sdim 69218887Sdimprotected: 70226890Sdim friend class BugReporter; 71226890Sdim friend class BugReportEquivClass; 72226890Sdim 73218887Sdim BugType& BT; 74235633Sdim const Decl *DeclWithIssue; 75218887Sdim std::string ShortDescription; 76218887Sdim std::string Description; 77226890Sdim PathDiagnosticLocation Location; 78235633Sdim PathDiagnosticLocation UniqueingLocation; 79252723Sdim const Decl *UniqueingDecl; 80252723Sdim 81218887Sdim const ExplodedNode *ErrorNode; 82226890Sdim SmallVector<SourceRange, 4> Ranges; 83226890Sdim ExtraTextList ExtraText; 84235633Sdim 85235633Sdim typedef llvm::DenseSet<SymbolRef> Symbols; 86235633Sdim typedef llvm::DenseSet<const MemRegion *> Regions; 87218887Sdim 88245431Sdim /// A (stack of) a set of symbols that are registered with this 89245431Sdim /// report as being "interesting", and thus used to help decide which 90245431Sdim /// diagnostics to include when constructing the final path diagnostic. 91245431Sdim /// The stack is largely used by BugReporter when generating PathDiagnostics 92245431Sdim /// for multiple PathDiagnosticConsumers. 93252723Sdim SmallVector<Symbols *, 2> interestingSymbols; 94235633Sdim 95245431Sdim /// A (stack of) set of regions that are registered with this report as being 96235633Sdim /// "interesting", and thus used to help decide which diagnostics 97235633Sdim /// to include when constructing the final path diagnostic. 98245431Sdim /// The stack is largely used by BugReporter when generating PathDiagnostics 99245431Sdim /// for multiple PathDiagnosticConsumers. 100252723Sdim SmallVector<Regions *, 2> interestingRegions; 101235633Sdim 102245431Sdim /// A set of location contexts that correspoind to call sites which should be 103245431Sdim /// considered "interesting". 104245431Sdim llvm::SmallSet<const LocationContext *, 2> InterestingLocationContexts; 105245431Sdim 106235633Sdim /// A set of custom visitors which generate "event" diagnostics at 107235633Sdim /// interesting points in the path. 108235633Sdim VisitorList Callbacks; 109235633Sdim 110235633Sdim /// Used for ensuring the visitors are only added once. 111226890Sdim llvm::FoldingSet<BugReporterVisitor> CallbacksSet; 112218887Sdim 113235633Sdim /// Used for clients to tell if the report's configuration has changed 114235633Sdim /// since the last time they checked. 115235633Sdim unsigned ConfigurationChangeToken; 116245431Sdim 117245431Sdim /// When set, this flag disables all callstack pruning from a diagnostic 118245431Sdim /// path. This is useful for some reports that want maximum fidelty 119245431Sdim /// when reporting an issue. 120245431Sdim bool DoNotPrunePath; 121235633Sdim 122245431Sdim /// Used to track unique reasons why a bug report might be invalid. 123245431Sdim /// 124245431Sdim /// \sa markInvalid 125245431Sdim /// \sa removeInvalidation 126245431Sdim typedef std::pair<const void *, const void *> InvalidationRecord; 127245431Sdim 128245431Sdim /// If non-empty, this bug report is likely a false positive and should not be 129245431Sdim /// shown to the user. 130245431Sdim /// 131245431Sdim /// \sa markInvalid 132245431Sdim /// \sa removeInvalidation 133245431Sdim llvm::SmallSet<InvalidationRecord, 4> Invalidations; 134245431Sdim 135245431Sdimprivate: 136245431Sdim // Used internally by BugReporter. 137245431Sdim Symbols &getInterestingSymbols(); 138245431Sdim Regions &getInterestingRegions(); 139245431Sdim 140245431Sdim void lazyInitializeInterestingSets(); 141245431Sdim void pushInterestingSymbolsAndRegions(); 142245431Sdim void popInterestingSymbolsAndRegions(); 143245431Sdim 144218887Sdimpublic: 145226890Sdim BugReport(BugType& bt, StringRef desc, const ExplodedNode *errornode) 146235633Sdim : BT(bt), DeclWithIssue(0), Description(desc), ErrorNode(errornode), 147245431Sdim ConfigurationChangeToken(0), DoNotPrunePath(false) {} 148218887Sdim 149226890Sdim BugReport(BugType& bt, StringRef shortDesc, StringRef desc, 150218887Sdim const ExplodedNode *errornode) 151235633Sdim : BT(bt), DeclWithIssue(0), ShortDescription(shortDesc), Description(desc), 152245431Sdim ErrorNode(errornode), ConfigurationChangeToken(0), 153245431Sdim DoNotPrunePath(false) {} 154218887Sdim 155226890Sdim BugReport(BugType& bt, StringRef desc, PathDiagnosticLocation l) 156235633Sdim : BT(bt), DeclWithIssue(0), Description(desc), Location(l), ErrorNode(0), 157245431Sdim ConfigurationChangeToken(0), 158245431Sdim DoNotPrunePath(false) {} 159226890Sdim 160235633Sdim /// \brief Create a BugReport with a custom uniqueing location. 161235633Sdim /// 162235633Sdim /// The reports that have the same report location, description, bug type, and 163235633Sdim /// ranges are uniqued - only one of the equivalent reports will be presented 164235633Sdim /// to the user. This method allows to rest the location which should be used 165235633Sdim /// for uniquing reports. For example, memory leaks checker, could set this to 166235633Sdim /// the allocation site, rather then the location where the bug is reported. 167235633Sdim BugReport(BugType& bt, StringRef desc, const ExplodedNode *errornode, 168252723Sdim PathDiagnosticLocation LocationToUnique, const Decl *DeclToUnique) 169235633Sdim : BT(bt), DeclWithIssue(0), Description(desc), 170235633Sdim UniqueingLocation(LocationToUnique), 171252723Sdim UniqueingDecl(DeclToUnique), 172245431Sdim ErrorNode(errornode), ConfigurationChangeToken(0), 173245431Sdim DoNotPrunePath(false) {} 174235633Sdim 175218887Sdim virtual ~BugReport(); 176218887Sdim 177218887Sdim const BugType& getBugType() const { return BT; } 178218887Sdim BugType& getBugType() { return BT; } 179218887Sdim 180226890Sdim const ExplodedNode *getErrorNode() const { return ErrorNode; } 181218887Sdim 182226890Sdim const StringRef getDescription() const { return Description; } 183218887Sdim 184245431Sdim const StringRef getShortDescription(bool UseFallback = true) const { 185245431Sdim if (ShortDescription.empty() && UseFallback) 186245431Sdim return Description; 187245431Sdim return ShortDescription; 188218887Sdim } 189218887Sdim 190245431Sdim /// Indicates whether or not any path pruning should take place 191245431Sdim /// when generating a PathDiagnostic from this BugReport. 192245431Sdim bool shouldPrunePath() const { return !DoNotPrunePath; } 193245431Sdim 194245431Sdim /// Disable all path pruning when generating a PathDiagnostic. 195245431Sdim void disablePathPruning() { DoNotPrunePath = true; } 196245431Sdim 197235633Sdim void markInteresting(SymbolRef sym); 198235633Sdim void markInteresting(const MemRegion *R); 199235633Sdim void markInteresting(SVal V); 200245431Sdim void markInteresting(const LocationContext *LC); 201235633Sdim 202245431Sdim bool isInteresting(SymbolRef sym); 203245431Sdim bool isInteresting(const MemRegion *R); 204245431Sdim bool isInteresting(SVal V); 205245431Sdim bool isInteresting(const LocationContext *LC); 206235633Sdim 207235633Sdim unsigned getConfigurationChangeToken() const { 208235633Sdim return ConfigurationChangeToken; 209235633Sdim } 210245431Sdim 211245431Sdim /// Returns whether or not this report should be considered valid. 212245431Sdim /// 213245431Sdim /// Invalid reports are those that have been classified as likely false 214245431Sdim /// positives after the fact. 215245431Sdim bool isValid() const { 216245431Sdim return Invalidations.empty(); 217245431Sdim } 218245431Sdim 219245431Sdim /// Marks the current report as invalid, meaning that it is probably a false 220245431Sdim /// positive and should not be reported to the user. 221245431Sdim /// 222245431Sdim /// The \p Tag and \p Data arguments are intended to be opaque identifiers for 223245431Sdim /// this particular invalidation, where \p Tag represents the visitor 224245431Sdim /// responsible for invalidation, and \p Data represents the reason this 225245431Sdim /// visitor decided to invalidate the bug report. 226245431Sdim /// 227245431Sdim /// \sa removeInvalidation 228245431Sdim void markInvalid(const void *Tag, const void *Data) { 229245431Sdim Invalidations.insert(std::make_pair(Tag, Data)); 230245431Sdim } 231245431Sdim 232245431Sdim /// Reverses the effects of a previous invalidation. 233245431Sdim /// 234245431Sdim /// \sa markInvalid 235245431Sdim void removeInvalidation(const void *Tag, const void *Data) { 236245431Sdim Invalidations.erase(std::make_pair(Tag, Data)); 237245431Sdim } 238235633Sdim 239235633Sdim /// Return the canonical declaration, be it a method or class, where 240235633Sdim /// this issue semantically occurred. 241235633Sdim const Decl *getDeclWithIssue() const; 242235633Sdim 243235633Sdim /// Specifically set the Decl where an issue occurred. This isn't necessary 244235633Sdim /// for BugReports that cover a path as it will be automatically inferred. 245235633Sdim void setDeclWithIssue(const Decl *declWithIssue) { 246235633Sdim DeclWithIssue = declWithIssue; 247235633Sdim } 248235633Sdim 249226890Sdim /// \brief This allows for addition of meta data to the diagnostic. 250226890Sdim /// 251226890Sdim /// Currently, only the HTMLDiagnosticClient knows how to display it. 252226890Sdim void addExtraText(StringRef S) { 253226890Sdim ExtraText.push_back(S); 254218887Sdim } 255218887Sdim 256226890Sdim virtual const ExtraTextList &getExtraText() { 257226890Sdim return ExtraText; 258226890Sdim } 259218887Sdim 260226890Sdim /// \brief Return the "definitive" location of the reported bug. 261226890Sdim /// 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. 265226890Sdim virtual PathDiagnosticLocation getLocation(const SourceManager &SM) const; 266218887Sdim 267252723Sdim /// \brief Get the location on which the report should be uniqued. 268252723Sdim PathDiagnosticLocation getUniqueingLocation() const { 269252723Sdim return UniqueingLocation; 270252723Sdim } 271252723Sdim 272252723Sdim /// \brief Get the declaration containing the uniqueing location. 273252723Sdim const Decl *getUniqueingDecl() const { 274252723Sdim return UniqueingDecl; 275252723Sdim } 276252723Sdim 277226890Sdim const Stmt *getStmt() const; 278218887Sdim 279226890Sdim /// \brief Add a range to a bug report. 280226890Sdim /// 281226890Sdim /// Ranges are used to highlight regions of interest in the source code. 282226890Sdim /// They should be at the same source code line as the BugReport location. 283226890Sdim /// By default, the source range of the statement corresponding to the error 284226890Sdim /// node will be used; add a single invalid range to specify absence of 285226890Sdim /// ranges. 286226890Sdim void addRange(SourceRange R) { 287226890Sdim assert((R.isValid() || Ranges.empty()) && "Invalid range can only be used " 288226890Sdim "to specify that the report does not have a range."); 289226890Sdim Ranges.push_back(R); 290226890Sdim } 291218887Sdim 292226890Sdim /// \brief Get the SourceRanges associated with the report. 293226890Sdim virtual std::pair<ranges_iterator, ranges_iterator> getRanges(); 294218887Sdim 295226890Sdim /// \brief Add custom or predefined bug report visitors to this report. 296226890Sdim /// 297226890Sdim /// The visitors should be used when the default trace is not sufficient. 298226890Sdim /// For example, they allow constructing a more elaborate trace. 299226890Sdim /// \sa registerConditionVisitor(), registerTrackNullOrUndefValue(), 300226890Sdim /// registerFindLastStore(), registerNilReceiverVisitor(), and 301226890Sdim /// registerVarDeclsLastStore(). 302226890Sdim void addVisitor(BugReporterVisitor *visitor); 303226890Sdim 304226890Sdim /// Iterators through the custom diagnostic visitors. 305226890Sdim visitor_iterator visitor_begin() { return Callbacks.begin(); } 306226890Sdim visitor_iterator visitor_end() { return Callbacks.end(); } 307226890Sdim 308226890Sdim /// Profile to identify equivalent bug reports for error report coalescing. 309226890Sdim /// Reports are uniqued to ensure that we do not emit multiple diagnostics 310226890Sdim /// for each bug. 311226890Sdim virtual void Profile(llvm::FoldingSetNodeID& hash) const; 312218887Sdim}; 313218887Sdim 314235633Sdim} // end ento namespace 315235633Sdim} // end clang namespace 316235633Sdim 317235633Sdimnamespace llvm { 318235633Sdim template<> struct ilist_traits<clang::ento::BugReport> 319235633Sdim : public ilist_default_traits<clang::ento::BugReport> { 320235633Sdim clang::ento::BugReport *createSentinel() const { 321235633Sdim return static_cast<clang::ento::BugReport *>(&Sentinel); 322235633Sdim } 323235633Sdim void destroySentinel(clang::ento::BugReport *) const {} 324235633Sdim 325235633Sdim clang::ento::BugReport *provideInitialHead() const { 326235633Sdim return createSentinel(); 327235633Sdim } 328235633Sdim clang::ento::BugReport *ensureHead(clang::ento::BugReport *) const { 329235633Sdim return createSentinel(); 330235633Sdim } 331235633Sdim private: 332235633Sdim mutable ilist_half_node<clang::ento::BugReport> Sentinel; 333235633Sdim }; 334235633Sdim} 335235633Sdim 336235633Sdimnamespace clang { 337235633Sdimnamespace ento { 338235633Sdim 339218887Sdim//===----------------------------------------------------------------------===// 340218887Sdim// BugTypes (collections of related reports). 341218887Sdim//===----------------------------------------------------------------------===// 342218887Sdim 343218887Sdimclass BugReportEquivClass : public llvm::FoldingSetNode { 344226890Sdim /// List of *owned* BugReport objects. 345235633Sdim 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()); 355235633Sdim Reports.front().Profile(ID); 356218887Sdim } 357218887Sdim 358235633Sdim typedef llvm::ilist<BugReport>::iterator iterator; 359235633Sdim typedef llvm::ilist<BugReport>::const_iterator const_iterator; 360218887Sdim 361235633Sdim iterator begin() { return Reports.begin(); } 362235633Sdim iterator end() { return Reports.end(); } 363218887Sdim 364235633Sdim const_iterator begin() const { return Reports.begin(); } 365235633Sdim const_iterator end() const { return Reports.end(); } 366218887Sdim}; 367218887Sdim 368218887Sdim//===----------------------------------------------------------------------===// 369218887Sdim// BugReporter and friends. 370218887Sdim//===----------------------------------------------------------------------===// 371218887Sdim 372218887Sdimclass BugReporterData { 373218887Sdimpublic: 374218887Sdim virtual ~BugReporterData(); 375226890Sdim virtual DiagnosticsEngine& getDiagnostic() = 0; 376245431Sdim virtual ArrayRef<PathDiagnosticConsumer*> getPathDiagnosticConsumers() = 0; 377226890Sdim virtual ASTContext &getASTContext() = 0; 378218887Sdim virtual SourceManager& getSourceManager() = 0; 379263509Sdim virtual AnalyzerOptions& getAnalyzerOptions() = 0; 380218887Sdim}; 381218887Sdim 382226890Sdim/// BugReporter is a utility class for generating PathDiagnostics for analysis. 383226890Sdim/// It collects the BugReports and BugTypes and knows how to generate 384226890Sdim/// 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 397226890Sdim /// Generate and flush the diagnostics for the given bug report. 398218887Sdim void FlushReport(BugReportEquivClass& EQ); 399218887Sdim 400245431Sdim /// Generate and flush the diagnostics for the given bug report 401245431Sdim /// and PathDiagnosticConsumer. 402245431Sdim void FlushReport(BugReport *exampleReport, 403245431Sdim PathDiagnosticConsumer &PD, 404245431Sdim ArrayRef<BugReport*> BugReports); 405245431Sdim 406226890Sdim /// The set of bug reports tracked by the BugReporter. 407219077Sdim llvm::FoldingSet<BugReportEquivClass> EQClasses; 408226890Sdim /// A vector of BugReports for tracking the allocated pointers and cleanup. 409226890Sdim 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 420226890Sdim /// \brief Generate and flush diagnostics for all bug reports. 421218887Sdim void FlushReports(); 422218887Sdim 423218887Sdim Kind getKind() const { return kind; } 424218887Sdim 425226890Sdim DiagnosticsEngine& getDiagnostic() { 426218887Sdim return D.getDiagnostic(); 427218887Sdim } 428218887Sdim 429245431Sdim ArrayRef<PathDiagnosticConsumer*> getPathDiagnosticConsumers() { 430245431Sdim return D.getPathDiagnosticConsumers(); 431218887Sdim } 432218887Sdim 433226890Sdim /// \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 438226890Sdim /// \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 443226890Sdim ASTContext &getContext() { return D.getASTContext(); } 444218887Sdim 445218887Sdim SourceManager& getSourceManager() { return D.getSourceManager(); } 446218887Sdim 447263509Sdim AnalyzerOptions& getAnalyzerOptions() { return D.getAnalyzerOptions(); } 448263509Sdim 449245431Sdim virtual bool generatePathDiagnostic(PathDiagnostic& pathDiagnostic, 450245431Sdim PathDiagnosticConsumer &PC, 451245431Sdim ArrayRef<BugReport *> &bugReports) { 452245431Sdim return true; 453245431Sdim } 454218887Sdim 455252723Sdim bool RemoveUnneededCalls(PathPieces &pieces, BugReport *R); 456245431Sdim 457218887Sdim void Register(BugType *BT); 458218887Sdim 459226890Sdim /// \brief Add the given report to the set of reports tracked by BugReporter. 460226890Sdim /// 461226890Sdim /// The reports are usually generated by the checkers. Further, they are 462226890Sdim /// folded based on the profile value, which is done to coalesce similar 463226890Sdim /// reports. 464245431Sdim void emitReport(BugReport *R); 465218887Sdim 466235633Sdim void EmitBasicReport(const Decl *DeclWithIssue, 467235633Sdim StringRef BugName, StringRef BugCategory, 468226890Sdim StringRef BugStr, PathDiagnosticLocation Loc, 469263509Sdim 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. 476226890Sdim 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. 498226890Sdim ProgramStateManager &getStateManager(); 499218887Sdim 500245431Sdim /// Generates a path corresponding to one of the given bug reports. 501245431Sdim /// 502245431Sdim /// Which report is used for path generation is not specified. The 503245431Sdim /// bug reporter will try to pick the shortest path, but this is not 504245431Sdim /// guaranteed. 505245431Sdim /// 506245431Sdim /// \return True if the report was valid and a path was generated, 507245431Sdim /// false if the reports should be considered invalid. 508245431Sdim virtual bool generatePathDiagnostic(PathDiagnostic &PD, 509245431Sdim PathDiagnosticConsumer &PC, 510245431Sdim 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 { 519235633Sdim virtual void anchor(); 520218887Sdim GRBugReporter &BR; 521218887Sdimpublic: 522226890Sdim BugReporterContext(GRBugReporter& br) : BR(br) {} 523218887Sdim 524226890Sdim virtual ~BugReporterContext() {} 525218887Sdim 526218887Sdim GRBugReporter& getBugReporter() { return BR; } 527218887Sdim 528218887Sdim ExplodedGraph &getGraph() { return BR.getGraph(); } 529218887Sdim 530226890Sdim ProgramStateManager& getStateManager() { 531218887Sdim return BR.getStateManager(); 532218887Sdim } 533218887Sdim 534218887Sdim SValBuilder& getSValBuilder() { 535218887Sdim return getStateManager().getSValBuilder(); 536218887Sdim } 537218887Sdim 538226890Sdim 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