]> granicus.if.org Git - clang/blobdiff - include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h
Header guard canonicalization, clang part.
[clang] / include / clang / StaticAnalyzer / Core / BugReporter / BugReporter.h
index d2f92b230cc5abe1551efd5c214557d793d5151a..3e1745e840d1d464e241d46b2e9b642055f3f942 100644 (file)
 //
 //===----------------------------------------------------------------------===//
 
-#ifndef LLVM_CLANG_GR_BUGREPORTER
-#define LLVM_CLANG_GR_BUGREPORTER
+#ifndef LLVM_CLANG_STATICANALYZER_CORE_BUGREPORTER_BUGREPORTER_H
+#define LLVM_CLANG_STATICANALYZER_CORE_BUGREPORTER_BUGREPORTER_H
 
 #include "clang/Basic/SourceLocation.h"
+#include "clang/StaticAnalyzer/Core/AnalyzerOptions.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitor.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h"
+#include "clang/StaticAnalyzer/Core/CheckerManager.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
+#include "llvm/ADT/DenseSet.h"
 #include "llvm/ADT/FoldingSet.h"
-#include "llvm/ADT/ImmutableList.h"
 #include "llvm/ADT/ImmutableSet.h"
 #include "llvm/ADT/SmallSet.h"
-#include <list>
+#include "llvm/ADT/ilist.h"
+#include "llvm/ADT/ilist_node.h"
 
 namespace clang {
 
 class ASTContext;
-class Diagnostic;
+class DiagnosticsEngine;
 class Stmt;
 class ParentMap;
 
 namespace ento {
 
 class PathDiagnostic;
-class PathDiagnosticPiece;
-class PathDiagnosticClient;
 class ExplodedNode;
 class ExplodedGraph;
+class BugReport;
 class BugReporter;
 class BugReporterContext;
 class ExprEngine;
-class ProgramState;
 class BugType;
 
 //===----------------------------------------------------------------------===//
 // Interface for individual bug reports.
 //===----------------------------------------------------------------------===//
 
-class BugReporterVisitor : public llvm::FoldingSetNode {
-public:
-  virtual ~BugReporterVisitor();
-  virtual PathDiagnosticPiece *VisitNode(const ExplodedNode *N,
-                                         const ExplodedNode *PrevN,
-                                         BugReporterContext &BRC) = 0;
-
-  virtual bool isOwnedByReporterContext() { return true; }
-  virtual void Profile(llvm::FoldingSetNodeID &ID) const = 0;
-};
-
-class BugReport : public BugReporterVisitor {
-public:
+/// This class provides an interface through which checkers can create
+/// individual bug reports.
+class BugReport : public llvm::ilist_node<BugReport> {
+public:  
   class NodeResolver {
+    virtual void anchor();
   public:
     virtual ~NodeResolver() {}
     virtual const ExplodedNode*
             getOriginalNode(const ExplodedNode *N) = 0;
   };
 
-  typedef void (*VisitorCreator)(BugReporterContext &BRcC, const void *data,
-                                 const ExplodedNode *N);
   typedef const SourceRange *ranges_iterator;
+  typedef SmallVector<BugReporterVisitor *, 8> VisitorList;
+  typedef VisitorList::iterator visitor_iterator;
+  typedef SmallVector<StringRef, 2> ExtraTextList;
 
 protected:
   friend class BugReporter;
   friend class BugReportEquivClass;
-  typedef SmallVector<std::pair<VisitorCreator, const void*>, 2> Creators;
 
   BugType& BT;
+  const Decl *DeclWithIssue;
   std::string ShortDescription;
   std::string Description;
-  FullSourceLoc Location;
+  PathDiagnosticLocation Location;
+  PathDiagnosticLocation UniqueingLocation;
+  const Decl *UniqueingDecl;
+  
   const ExplodedNode *ErrorNode;
   SmallVector<SourceRange, 4> Ranges;
-  Creators creators;
+  ExtraTextList ExtraText;
+  
+  typedef llvm::DenseSet<SymbolRef> Symbols;
+  typedef llvm::DenseSet<const MemRegion *> Regions;
+
+  /// A (stack of) a set of symbols that are registered with this
+  /// report as being "interesting", and thus used to help decide which
+  /// diagnostics to include when constructing the final path diagnostic.
+  /// The stack is largely used by BugReporter when generating PathDiagnostics
+  /// for multiple PathDiagnosticConsumers.
+  SmallVector<Symbols *, 2> interestingSymbols;
+
+  /// A (stack of) set of regions that are registered with this report as being
+  /// "interesting", and thus used to help decide which diagnostics
+  /// to include when constructing the final path diagnostic.
+  /// The stack is largely used by BugReporter when generating PathDiagnostics
+  /// for multiple PathDiagnosticConsumers.
+  SmallVector<Regions *, 2> interestingRegions;
+
+  /// A set of location contexts that correspoind to call sites which should be
+  /// considered "interesting".
+  llvm::SmallSet<const LocationContext *, 2> InterestingLocationContexts;
+
+  /// A set of custom visitors which generate "event" diagnostics at
+  /// interesting points in the path.
+  VisitorList Callbacks;
+
+  /// Used for ensuring the visitors are only added once.
+  llvm::FoldingSet<BugReporterVisitor> CallbacksSet;
 
-  /// Profile to identify equivalent bug reports for error report coalescing.
-  virtual void Profile(llvm::FoldingSetNodeID& hash) const;
+  /// Used for clients to tell if the report's configuration has changed
+  /// since the last time they checked.
+  unsigned ConfigurationChangeToken;
+  
+  /// When set, this flag disables all callstack pruning from a diagnostic
+  /// path.  This is useful for some reports that want maximum fidelty
+  /// when reporting an issue.
+  bool DoNotPrunePath;
 
-  const Stmt *getStmt() const;
+  /// Used to track unique reasons why a bug report might be invalid.
+  ///
+  /// \sa markInvalid
+  /// \sa removeInvalidation
+  typedef std::pair<const void *, const void *> InvalidationRecord;
+
+  /// If non-empty, this bug report is likely a false positive and should not be
+  /// shown to the user.
+  ///
+  /// \sa markInvalid
+  /// \sa removeInvalidation
+  llvm::SmallSet<InvalidationRecord, 4> Invalidations;
+
+private:
+  // Used internally by BugReporter.
+  Symbols &getInterestingSymbols();
+  Regions &getInterestingRegions();
+
+  void lazyInitializeInterestingSets();
+  void pushInterestingSymbolsAndRegions();
+  void popInterestingSymbolsAndRegions();
 
 public:
   BugReport(BugType& bt, StringRef desc, const ExplodedNode *errornode)
-    : BT(bt), Description(desc), ErrorNode(errornode) {}
+    : BT(bt), DeclWithIssue(nullptr), Description(desc), ErrorNode(errornode),
+      ConfigurationChangeToken(0), DoNotPrunePath(false) {}
 
   BugReport(BugType& bt, StringRef shortDesc, StringRef desc,
             const ExplodedNode *errornode)
-  : BT(bt), ShortDescription(shortDesc), Description(desc),
-    ErrorNode(errornode) {}
+    : BT(bt), DeclWithIssue(nullptr), ShortDescription(shortDesc),
+      Description(desc), ErrorNode(errornode), ConfigurationChangeToken(0),
+      DoNotPrunePath(false) {}
 
-  BugReport(BugType& bt, StringRef desc, FullSourceLoc l)
-    : BT(bt), Description(desc), Location(l), ErrorNode(0) {}
+  BugReport(BugType &bt, StringRef desc, PathDiagnosticLocation l)
+    : BT(bt), DeclWithIssue(nullptr), Description(desc), Location(l),
+      ErrorNode(nullptr), ConfigurationChangeToken(0), DoNotPrunePath(false) {}
 
-  virtual ~BugReport();
+  /// \brief Create a BugReport with a custom uniqueing location.
+  ///
+  /// The reports that have the same report location, description, bug type, and
+  /// ranges are uniqued - only one of the equivalent reports will be presented
+  /// to the user. This method allows to rest the location which should be used
+  /// for uniquing reports. For example, memory leaks checker, could set this to
+  /// the allocation site, rather then the location where the bug is reported.
+  BugReport(BugType& bt, StringRef desc, const ExplodedNode *errornode,
+            PathDiagnosticLocation LocationToUnique, const Decl *DeclToUnique)
+    : BT(bt), DeclWithIssue(nullptr), Description(desc),
+      UniqueingLocation(LocationToUnique),
+      UniqueingDecl(DeclToUnique),
+      ErrorNode(errornode), ConfigurationChangeToken(0),
+      DoNotPrunePath(false) {}
 
-  bool isOwnedByReporterContext() { return false; }
+  virtual ~BugReport();
 
   const BugType& getBugType() const { return BT; }
   BugType& getBugType() { return BT; }
@@ -112,34 +181,111 @@ public:
 
   const StringRef getDescription() const { return Description; }
 
-  const StringRef getShortDescription() const {
-    return ShortDescription.empty() ? Description : ShortDescription;
+  const StringRef getShortDescription(bool UseFallback = true) const {
+    if (ShortDescription.empty() && UseFallback)
+      return Description;
+    return ShortDescription;
   }
 
+  /// Indicates whether or not any path pruning should take place
+  /// when generating a PathDiagnostic from this BugReport.
+  bool shouldPrunePath() const { return !DoNotPrunePath; }
+
+  /// Disable all path pruning when generating a PathDiagnostic.
+  void disablePathPruning() { DoNotPrunePath = true; }
+  
+  void markInteresting(SymbolRef sym);
+  void markInteresting(const MemRegion *R);
+  void markInteresting(SVal V);
+  void markInteresting(const LocationContext *LC);
+  
+  bool isInteresting(SymbolRef sym);
+  bool isInteresting(const MemRegion *R);
+  bool isInteresting(SVal V);
+  bool isInteresting(const LocationContext *LC);
+
+  unsigned getConfigurationChangeToken() const {
+    return ConfigurationChangeToken;
+  }
+
+  /// Returns whether or not this report should be considered valid.
+  ///
+  /// Invalid reports are those that have been classified as likely false
+  /// positives after the fact.
+  bool isValid() const {
+    return Invalidations.empty();
+  }
+
+  /// Marks the current report as invalid, meaning that it is probably a false
+  /// positive and should not be reported to the user.
+  ///
+  /// The \p Tag and \p Data arguments are intended to be opaque identifiers for
+  /// this particular invalidation, where \p Tag represents the visitor
+  /// responsible for invalidation, and \p Data represents the reason this
+  /// visitor decided to invalidate the bug report.
+  ///
+  /// \sa removeInvalidation
+  void markInvalid(const void *Tag, const void *Data) {
+    Invalidations.insert(std::make_pair(Tag, Data));
+  }
+
+  /// Reverses the effects of a previous invalidation.
+  ///
+  /// \sa markInvalid
+  void removeInvalidation(const void *Tag, const void *Data) {
+    Invalidations.erase(std::make_pair(Tag, Data));
+  }
+  
+  /// Return the canonical declaration, be it a method or class, where
+  /// this issue semantically occurred.
+  const Decl *getDeclWithIssue() const;
+  
+  /// Specifically set the Decl where an issue occurred.  This isn't necessary
+  /// for BugReports that cover a path as it will be automatically inferred.
+  void setDeclWithIssue(const Decl *declWithIssue) {
+    DeclWithIssue = declWithIssue;
+  }
+  
   /// \brief This allows for addition of meta data to the diagnostic.
   ///
   /// Currently, only the HTMLDiagnosticClient knows how to display it. 
-  virtual std::pair<const char**,const char**> getExtraDescriptiveText() {
-    return std::make_pair((const char**)0,(const char**)0);
+  void addExtraText(StringRef S) {
+    ExtraText.push_back(S);
   }
 
-  /// Provide custom definition for the last diagnostic piece on the path.
-  virtual PathDiagnosticPiece *getEndPath(BugReporterContext &BRC,
-                                          const ExplodedNode *N);
+  virtual const ExtraTextList &getExtraText() {
+    return ExtraText;
+  }
 
   /// \brief Return the "definitive" location of the reported bug.
   ///
   ///  While a bug can span an entire path, usually there is a specific
   ///  location that can be used to identify where the key issue occurred.
   ///  This location is used by clients rendering diagnostics.
-  virtual SourceLocation getLocation() const;
+  virtual PathDiagnosticLocation getLocation(const SourceManager &SM) const;
+
+  /// \brief Get the location on which the report should be uniqued.
+  PathDiagnosticLocation getUniqueingLocation() const {
+    return UniqueingLocation;
+  }
+  
+  /// \brief Get the declaration containing the uniqueing location.
+  const Decl *getUniqueingDecl() const {
+    return UniqueingDecl;
+  }
+
+  const Stmt *getStmt() const;
 
   /// \brief Add a range to a bug report.
   ///
   /// Ranges are used to highlight regions of interest in the source code.
   /// They should be at the same source code line as the BugReport location.
+  /// By default, the source range of the statement corresponding to the error
+  /// node will be used; add a single invalid range to specify absence of
+  /// ranges.
   void addRange(SourceRange R) {
-    assert(R.isValid());
+    assert((R.isValid() || Ranges.empty()) && "Invalid range can only be used "
+                           "to specify that the report does not have a range.");
     Ranges.push_back(R);
   }
 
@@ -153,25 +299,50 @@ public:
   /// \sa registerConditionVisitor(), registerTrackNullOrUndefValue(),
   /// registerFindLastStore(), registerNilReceiverVisitor(), and
   /// registerVarDeclsLastStore().
-  void addVisitorCreator(VisitorCreator creator, const void *data) {
-    creators.push_back(std::make_pair(creator, data));
-  }
+  void addVisitor(BugReporterVisitor *visitor);
 
-  virtual PathDiagnosticPiece *VisitNode(const ExplodedNode *N,
-                                         const ExplodedNode *PrevN,
-                                         BugReporterContext &BR);
+       /// Iterators through the custom diagnostic visitors.
+  visitor_iterator visitor_begin() { return Callbacks.begin(); }
+  visitor_iterator visitor_end() { return Callbacks.end(); }
 
-  virtual void registerInitialVisitors(BugReporterContext &BRC,
-                                       const ExplodedNode *N) {}
+  /// Profile to identify equivalent bug reports for error report coalescing.
+  /// Reports are uniqued to ensure that we do not emit multiple diagnostics
+  /// for each bug.
+  virtual void Profile(llvm::FoldingSetNodeID& hash) const;
 };
 
+} // end ento namespace
+} // end clang namespace
+
+namespace llvm {
+  template<> struct ilist_traits<clang::ento::BugReport>
+    : public ilist_default_traits<clang::ento::BugReport> {
+    clang::ento::BugReport *createSentinel() const {
+      return static_cast<clang::ento::BugReport *>(&Sentinel);
+    }
+    void destroySentinel(clang::ento::BugReport *) const {}
+
+    clang::ento::BugReport *provideInitialHead() const {
+      return createSentinel();
+    }
+    clang::ento::BugReport *ensureHead(clang::ento::BugReport *) const {
+      return createSentinel();
+    }
+  private:
+    mutable ilist_half_node<clang::ento::BugReport> Sentinel;
+  };
+}
+
+namespace clang {
+namespace ento {
+
 //===----------------------------------------------------------------------===//
 // BugTypes (collections of related reports).
 //===----------------------------------------------------------------------===//
 
 class BugReportEquivClass : public llvm::FoldingSetNode {
   /// List of *owned* BugReport objects.
-  std::list<BugReport*> Reports;
+  llvm::ilist<BugReport> Reports;
 
   friend class BugReporter;
   void AddReport(BugReport* R) { Reports.push_back(R); }
@@ -181,36 +352,17 @@ public:
 
   void Profile(llvm::FoldingSetNodeID& ID) const {
     assert(!Reports.empty());
-    (*Reports.begin())->Profile(ID);
+    Reports.front().Profile(ID);
   }
 
-  class iterator {
-    std::list<BugReport*>::iterator impl;
-  public:
-    iterator(std::list<BugReport*>::iterator i) : impl(i) {}
-    iterator &operator++() { ++impl; return *this; }
-    bool operator==(const iterator &I) const { return I.impl == impl; }
-    bool operator!=(const iterator &I) const { return I.impl != impl; }
-    BugReport* operator*() const { return *impl; }
-    BugReport* operator->() const { return *impl; }
-  };
-
-  class const_iterator {
-    std::list<BugReport*>::const_iterator impl;
-  public:
-    const_iterator(std::list<BugReport*>::const_iterator i) : impl(i) {}
-    const_iterator &operator++() { ++impl; return *this; }
-    bool operator==(const const_iterator &I) const { return I.impl == impl; }
-    bool operator!=(const const_iterator &I) const { return I.impl != impl; }
-    const BugReport* operator*() const { return *impl; }
-    const BugReport* operator->() const { return *impl; }
-  };
+  typedef llvm::ilist<BugReport>::iterator iterator;
+  typedef llvm::ilist<BugReport>::const_iterator const_iterator;
 
-  iterator begin() { return iterator(Reports.begin()); }
-  iterator end() { return iterator(Reports.end()); }
+  iterator begin() { return Reports.begin(); }
+  iterator end() { return Reports.end(); }
 
-  const_iterator begin() const { return const_iterator(Reports.begin()); }
-  const_iterator end() const { return const_iterator(Reports.end()); }
+  const_iterator begin() const { return Reports.begin(); }
+  const_iterator end() const { return Reports.end(); }
 };
 
 //===----------------------------------------------------------------------===//
@@ -220,10 +372,11 @@ public:
 class BugReporterData {
 public:
   virtual ~BugReporterData();
-  virtual Diagnostic& getDiagnostic() = 0;
-  virtual PathDiagnosticClient* getPathDiagnosticClient() = 0;
+  virtual DiagnosticsEngine& getDiagnostic() = 0;
+  virtual ArrayRef<PathDiagnosticConsumer*> getPathDiagnosticConsumers() = 0;
   virtual ASTContext &getASTContext() = 0;
   virtual SourceManager& getSourceManager() = 0;
+  virtual AnalyzerOptions& getAnalyzerOptions() = 0;
 };
 
 /// BugReporter is a utility class for generating PathDiagnostics for analysis.
@@ -244,8 +397,16 @@ private:
   /// Generate and flush the diagnostics for the given bug report.
   void FlushReport(BugReportEquivClass& EQ);
 
+  /// Generate and flush the diagnostics for the given bug report
+  /// and PathDiagnosticConsumer.
+  void FlushReport(BugReport *exampleReport,
+                   PathDiagnosticConsumer &PD,
+                   ArrayRef<BugReport*> BugReports);
+
   /// The set of bug reports tracked by the BugReporter.
   llvm::FoldingSet<BugReportEquivClass> EQClasses;
+  /// A vector of BugReports for tracking the allocated pointers and cleanup.
+  std::vector<BugReportEquivClass *> EQClassesVector;
 
 protected:
   BugReporter(BugReporterData& d, Kind k) : BugTypes(F.getEmptySet()), kind(k),
@@ -261,12 +422,12 @@ public:
 
   Kind getKind() const { return kind; }
 
-  Diagnostic& getDiagnostic() {
+  DiagnosticsEngine& getDiagnostic() {
     return D.getDiagnostic();
   }
 
-  PathDiagnosticClient* getPathDiagnosticClient() {
-    return D.getPathDiagnosticClient();
+  ArrayRef<PathDiagnosticConsumer*> getPathDiagnosticConsumers() {
+    return D.getPathDiagnosticConsumers();
   }
 
   /// \brief Iterator over the set of BugTypes tracked by the BugReporter.
@@ -283,8 +444,15 @@ public:
 
   SourceManager& getSourceManager() { return D.getSourceManager(); }
 
-  virtual void GeneratePathDiagnostic(PathDiagnostic& pathDiagnostic,
-        SmallVectorImpl<BugReport *> &bugReports) {}
+  AnalyzerOptions& getAnalyzerOptions() { return D.getAnalyzerOptions(); }
+
+  virtual bool generatePathDiagnostic(PathDiagnostic& pathDiagnostic,
+                                      PathDiagnosticConsumer &PC,
+                                      ArrayRef<BugReport *> &bugReports) {
+    return true;
+  }
+
+  bool RemoveUnneededCalls(PathPieces &pieces, BugReport *R);
 
   void Register(BugType *BT);
 
@@ -293,52 +461,30 @@ public:
   /// The reports are usually generated by the checkers. Further, they are
   /// folded based on the profile value, which is done to coalesce similar
   /// reports.
-  void EmitReport(BugReport *R);
-
-  void EmitBasicReport(StringRef BugName, StringRef BugStr,
-                       SourceLocation Loc,
-                       SourceRange* RangeBeg, unsigned NumRanges);
-
-  void EmitBasicReport(StringRef BugName, StringRef BugCategory,
-                       StringRef BugStr, SourceLocation Loc,
-                       SourceRange* RangeBeg, unsigned NumRanges);
+  void emitReport(BugReport *R);
 
+  void EmitBasicReport(const Decl *DeclWithIssue, const CheckerBase *Checker,
+                       StringRef BugName, StringRef BugCategory,
+                       StringRef BugStr, PathDiagnosticLocation Loc,
+                       ArrayRef<SourceRange> Ranges = None);
 
-  void EmitBasicReport(StringRef BugName, StringRef BugStr,
-                       SourceLocation Loc) {
-    EmitBasicReport(BugName, BugStr, Loc, 0, 0);
-  }
-
-  void EmitBasicReport(StringRef BugName, StringRef BugCategory,
-                       StringRef BugStr, SourceLocation Loc) {
-    EmitBasicReport(BugName, BugCategory, BugStr, Loc, 0, 0);
-  }
-
-  void EmitBasicReport(StringRef BugName, StringRef BugStr,
-                       SourceLocation Loc, SourceRange R) {
-    EmitBasicReport(BugName, BugStr, Loc, &R, 1);
-  }
-
-  void EmitBasicReport(StringRef BugName, StringRef Category,
-                       StringRef BugStr, SourceLocation Loc,
-                       SourceRange R) {
-    EmitBasicReport(BugName, Category, BugStr, Loc, &R, 1);
-  }
-
-  static bool classof(const BugReporter* R) { return true; }
+  void EmitBasicReport(const Decl *DeclWithIssue, CheckName CheckName,
+                       StringRef BugName, StringRef BugCategory,
+                       StringRef BugStr, PathDiagnosticLocation Loc,
+                       ArrayRef<SourceRange> Ranges = None);
 
 private:
   llvm::StringMap<BugType *> StrBugTypes;
 
   /// \brief Returns a BugType that is associated with the given name and
   /// category.
-  BugType *getBugTypeForName(StringRef name, StringRef category);
+  BugType *getBugTypeForName(CheckName CheckName, StringRef name,
+                             StringRef category);
 };
 
 // FIXME: Get rid of GRBugReporter.  It's the wrong abstraction.
 class GRBugReporter : public BugReporter {
   ExprEngine& Eng;
-  llvm::SmallSet<SymbolRef, 10> NotableSymbols;
 public:
   GRBugReporter(BugReporterData& d, ExprEngine& eng)
     : BugReporter(d, GRBugReporterKind), Eng(eng) {}
@@ -357,16 +503,16 @@ public:
   ///  engine.
   ProgramStateManager &getStateManager();
 
-  virtual void GeneratePathDiagnostic(PathDiagnostic &pathDiagnostic,
-                     SmallVectorImpl<BugReport*> &bugReports);
-
-  void addNotableSymbol(SymbolRef Sym) {
-    NotableSymbols.insert(Sym);
-  }
-
-  bool isNotable(SymbolRef Sym) const {
-    return (bool) NotableSymbols.count(Sym);
-  }
+  /// Generates a path corresponding to one of the given bug reports.
+  ///
+  /// Which report is used for path generation is not specified. The
+  /// bug reporter will try to pick the shortest path, but this is not
+  /// guaranteed.
+  ///
+  /// \return True if the report was valid and a path was generated,
+  ///         false if the reports should be considered invalid.
+  bool generatePathDiagnostic(PathDiagnostic &PD, PathDiagnosticConsumer &PC,
+                              ArrayRef<BugReport*> &bugReports) override;
 
   /// classof - Used by isa<>, cast<>, and dyn_cast<>.
   static bool classof(const BugReporter* R) {
@@ -375,36 +521,17 @@ public:
 };
 
 class BugReporterContext {
+  virtual void anchor();
   GRBugReporter &BR;
-  // Not the most efficient data structure, but we use an ImmutableList for the
-  // Callbacks because it is safe to make additions to list during iteration.
-  llvm::ImmutableList<BugReporterVisitor*>::Factory F;
-  llvm::ImmutableList<BugReporterVisitor*> Callbacks;
-  llvm::FoldingSet<BugReporterVisitor> CallbacksSet;
 public:
-  BugReporterContext(GRBugReporter& br) : BR(br), Callbacks(F.getEmptyList()) {}
-  virtual ~BugReporterContext();
+  BugReporterContext(GRBugReporter& br) : BR(br) {}
 
-  void addVisitor(BugReporterVisitor* visitor);
-
-  typedef llvm::ImmutableList<BugReporterVisitor*>::iterator visitor_iterator;
-  visitor_iterator visitor_begin() { return Callbacks.begin(); }
-  visitor_iterator visitor_end() { return Callbacks.end(); }
+  virtual ~BugReporterContext() {}
 
   GRBugReporter& getBugReporter() { return BR; }
 
   ExplodedGraph &getGraph() { return BR.getGraph(); }
 
-  void addNotableSymbol(SymbolRef Sym) {
-    // FIXME: For now forward to GRBugReporter.
-    BR.addNotableSymbol(Sym);
-  }
-
-  bool isNotable(SymbolRef Sym) const {
-    // FIXME: For now forward to GRBugReporter.
-    return BR.isNotable(Sym);
-  }
-
   ProgramStateManager& getStateManager() {
     return BR.getStateManager();
   }
@@ -424,33 +551,6 @@ public:
   virtual BugReport::NodeResolver& getNodeResolver() = 0;
 };
 
-//===----------------------------------------------------------------------===//
-//===----------------------------------------------------------------------===//
-
-namespace bugreporter {
-
-const Stmt *GetDerefExpr(const ExplodedNode *N);
-const Stmt *GetDenomExpr(const ExplodedNode *N);
-const Stmt *GetCalleeExpr(const ExplodedNode *N);
-const Stmt *GetRetValExpr(const ExplodedNode *N);
-
-void registerConditionVisitor(BugReporterContext &BRC);
-
-void registerTrackNullOrUndefValue(BugReporterContext &BRC, const void *stmt,
-                                   const ExplodedNode *N);
-
-void registerFindLastStore(BugReporterContext &BRC, const void *memregion,
-                           const ExplodedNode *N);
-
-void registerNilReceiverVisitor(BugReporterContext &BRC);  
-
-void registerVarDeclsLastStore(BugReporterContext &BRC, const void *stmt,
-                               const ExplodedNode *N);
-
-} // end namespace clang::bugreporter
-
-//===----------------------------------------------------------------------===//
-
 } // end GR namespace
 
 } // end clang namespace