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