//===- BugReporter.h - Generate PathDiagnostics -----------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
//  This file defines BugReporter, a utility class for generating
//  PathDiagnostics for analyses based on ProgramState.
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_CLANG_STATICANALYZER_CORE_BUGREPORTER_BUGREPORTER_H
#define LLVM_CLANG_STATICANALYZER_CORE_BUGREPORTER_BUGREPORTER_H

#include "clang/Analysis/PathDiagnostic.h"
#include "clang/Basic/LLVM.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitors.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/SymExpr.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/FoldingSet.h"
#include "llvm/ADT/ImmutableSet.h"
#include "llvm/ADT/None.h"
#include "llvm/ADT/SmallSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/ilist.h"
#include "llvm/ADT/ilist_node.h"
#include "llvm/ADT/iterator_range.h"
#include <cassert>
#include <memory>
#include <string>
#include <utility>
#include <vector>

namespace clang {

class AnalyzerOptions;
class ASTContext;
class Decl;
class DiagnosticsEngine;
class LocationContext;
class SourceManager;
class Stmt;

namespace ento {

class BugType;
class CheckerBase;
class ExplodedGraph;
class ExplodedNode;
class ExprEngine;
class MemRegion;
class SValBuilder;

//===----------------------------------------------------------------------===//
// Interface for individual bug reports.
//===----------------------------------------------------------------------===//

/// A mapping from diagnostic consumers to the diagnostics they should
/// consume.
using DiagnosticForConsumerMapTy =
    llvm::DenseMap<PathDiagnosticConsumer *, std::unique_ptr<PathDiagnostic>>;

/// Interface for classes constructing Stack hints.
///
/// If a PathDiagnosticEvent occurs in a different frame than the final
/// diagnostic the hints can be used to summarize the effect of the call.
class StackHintGenerator {
public:
  virtual ~StackHintGenerator() = 0;

  /// Construct the Diagnostic message for the given ExplodedNode.
  virtual std::string getMessage(const ExplodedNode *N) = 0;
};

/// Constructs a Stack hint for the given symbol.
///
/// The class knows how to construct the stack hint message based on
/// traversing the CallExpr associated with the call and checking if the given
/// symbol is returned or is one of the arguments.
/// The hint can be customized by redefining 'getMessageForX()' methods.
class StackHintGeneratorForSymbol : public StackHintGenerator {
private:
  SymbolRef Sym;
  std::string Msg;

public:
  StackHintGeneratorForSymbol(SymbolRef S, StringRef M) : Sym(S), Msg(M) {}
  ~StackHintGeneratorForSymbol() override = default;

  /// Search the call expression for the symbol Sym and dispatch the
  /// 'getMessageForX()' methods to construct a specific message.
  std::string getMessage(const ExplodedNode *N) override;

  /// Produces the message of the following form:
  ///   'Msg via Nth parameter'
  virtual std::string getMessageForArg(const Expr *ArgE, unsigned ArgIndex);

  virtual std::string getMessageForReturn(const CallExpr *CallExpr) {
    return Msg;
  }

  virtual std::string getMessageForSymbolNotFound() {
    return Msg;
  }
};

/// This class provides an interface through which checkers can create
/// individual bug reports.
class BugReport {
public:
  enum class Kind { Basic, PathSensitive };

protected:
  friend class BugReportEquivClass;
  friend class BugReporter;

  Kind K;
  const BugType& BT;
  std::string ShortDescription;
  std::string Description;

  SmallVector<SourceRange, 4> Ranges;
  SmallVector<std::shared_ptr<PathDiagnosticNotePiece>, 4> Notes;
  SmallVector<FixItHint, 4> Fixits;

  BugReport(Kind kind, const BugType &bt, StringRef desc)
      : BugReport(kind, bt, "", desc) {}

  BugReport(Kind K, const BugType &BT, StringRef ShortDescription,
            StringRef Description)
      : K(K), BT(BT), ShortDescription(ShortDescription),
        Description(Description) {}

public:
  virtual ~BugReport() = default;

  Kind getKind() const { return K; }

  const BugType& getBugType() const { return BT; }

  /// A verbose warning message that is appropriate for displaying next to
  /// the source code that introduces the problem. The description should be
  /// at least a full sentence starting with a capital letter. The period at
  /// the end of the warning is traditionally omitted. If the description
  /// consists of multiple sentences, periods between the sentences are
  /// encouraged, but the period at the end of the description is still omitted.
  StringRef getDescription() const { return Description; }

  /// A short general warning message that is appropriate for displaying in
  /// the list of all reported bugs. It should describe what kind of bug is found
  /// but does not need to try to go into details of that specific bug.
  /// Grammatical conventions of getDescription() apply here as well.
  StringRef getShortDescription(bool UseFallback = true) const {
    if (ShortDescription.empty() && UseFallback)
      return Description;
    return ShortDescription;
  }

  /// The primary location of the bug report that points at the undesirable
  /// behavior in the code. UIs should attach the warning description to this
  /// location. The warning description should describe the bad behavior
  /// at this location.
  virtual PathDiagnosticLocation getLocation() const = 0;

  /// The smallest declaration that contains the bug location.
  /// This is purely cosmetic; the declaration can be displayed to the user
  /// but it does not affect whether the report is emitted.
  virtual const Decl *getDeclWithIssue() const = 0;

  /// Get the location on which the report should be uniqued. Two warnings are
  /// considered to be equivalent whenever they have the same bug types,
  /// descriptions, and uniqueing locations. Out of a class of equivalent
  /// warnings only one gets displayed to the user. For most warnings the
  /// uniqueing location coincides with their location, but sometimes
  /// it makes sense to use different locations. For example, a leak
  /// checker can place the warning at the location where the last reference
  /// to the leaking resource is dropped but at the same time unique the warning
  /// by where that resource is acquired (allocated).
  virtual PathDiagnosticLocation getUniqueingLocation() const = 0;

  /// Get the declaration that corresponds to (usually contains) the uniqueing
  /// location. This is not actively used for uniqueing, i.e. otherwise
  /// identical reports that have different uniqueing decls will be considered
  /// equivalent.
  virtual const Decl *getUniqueingDecl() const = 0;

  /// Add new item to the list of additional notes that need to be attached to
  /// this report. If the report is path-sensitive, these notes will not be
  /// displayed as part of the execution path explanation, but will be displayed
  /// separately. Use bug visitors if you need to add an extra path note.
  void addNote(StringRef Msg, const PathDiagnosticLocation &Pos,
               ArrayRef<SourceRange> Ranges = {}) {
    auto P = std::make_shared<PathDiagnosticNotePiece>(Pos, Msg);

    for (const auto &R : Ranges)
      P->addRange(R);

    Notes.push_back(std::move(P));
  }

  ArrayRef<std::shared_ptr<PathDiagnosticNotePiece>> getNotes() {
    return Notes;
  }

  /// 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() || Ranges.empty()) && "Invalid range can only be used "
                           "to specify that the report does not have a range.");
    Ranges.push_back(R);
  }

  /// Get the SourceRanges associated with the report.
  virtual ArrayRef<SourceRange> getRanges() const {
    return Ranges;
  }

  /// Add a fix-it hint to the bug report.
  ///
  /// Fix-it hints are the suggested edits to the code that would resolve
  /// the problem explained by the bug report. Fix-it hints should be
  /// as conservative as possible because it is not uncommon for the user
  /// to blindly apply all fixits to their project. Note that it is very hard
  /// to produce a good fix-it hint for most path-sensitive warnings.
  void addFixItHint(const FixItHint &F) {
    Fixits.push_back(F);
  }

  llvm::ArrayRef<FixItHint> getFixits() const { return Fixits; }

  /// Reports are uniqued to ensure that we do not emit multiple diagnostics
  /// for each bug.
  virtual void Profile(llvm::FoldingSetNodeID& hash) const = 0;
};

class BasicBugReport : public BugReport {
  PathDiagnosticLocation Location;
  const Decl *DeclWithIssue = nullptr;

public:
  BasicBugReport(const BugType &bt, StringRef desc, PathDiagnosticLocation l)
      : BugReport(Kind::Basic, bt, desc), Location(l) {}

  static bool classof(const BugReport *R) {
    return R->getKind() == Kind::Basic;
  }

  PathDiagnosticLocation getLocation() const override {
    assert(Location.isValid());
    return Location;
  }

  const Decl *getDeclWithIssue() const override {
    return DeclWithIssue;
  }

  PathDiagnosticLocation getUniqueingLocation() const override {
    return getLocation();
  }

  const Decl *getUniqueingDecl() const override {
    return getDeclWithIssue();
  }

  /// 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;
  }

  void Profile(llvm::FoldingSetNodeID& hash) const override;
};

class PathSensitiveBugReport : public BugReport {
public:
  using VisitorList = SmallVector<std::unique_ptr<BugReporterVisitor>, 8>;
  using visitor_iterator = VisitorList::iterator;
  using visitor_range = llvm::iterator_range<visitor_iterator>;

protected:
  /// The ExplodedGraph node against which the report was thrown. It corresponds
  /// to the end of the execution path that demonstrates the bug.
  const ExplodedNode *ErrorNode = nullptr;

  /// The range that corresponds to ErrorNode's program point. It is usually
  /// highlighted in the report.
  const SourceRange ErrorNodeRange;

  /// Profile to identify equivalent bug reports for error report coalescing.

  /// 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.
  llvm::DenseMap<SymbolRef, bugreporter::TrackingKind> 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.
  llvm::DenseMap<const MemRegion *, bugreporter::TrackingKind>
      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;

  /// 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 = false;

  /// Used to track unique reasons why a bug report might be invalid.
  ///
  /// \sa markInvalid
  /// \sa removeInvalidation
  using InvalidationRecord = std::pair<const void *, const void *>;

  /// 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;

  /// Conditions we're already tracking.
  llvm::SmallSet<const ExplodedNode *, 4> TrackedConditions;

  /// Reports with different uniqueing locations are considered to be different
  /// for the purposes of deduplication.
  PathDiagnosticLocation UniqueingLocation;
  const Decl *UniqueingDecl;

  const Stmt *getStmt() const;

  /// If an event occurs in a different frame than the final diagnostic,
  /// supply a message that will be used to construct an extra hint on the
  /// returns from all the calls on the stack from this event to the final
  /// diagnostic.
  // FIXME: Allow shared_ptr keys in DenseMap?
  std::map<PathDiagnosticPieceRef, std::unique_ptr<StackHintGenerator>>
      StackHints;

public:
  PathSensitiveBugReport(const BugType &bt, StringRef desc,
                         const ExplodedNode *errorNode)
      : PathSensitiveBugReport(bt, desc, desc, errorNode) {}

  PathSensitiveBugReport(const BugType &bt, StringRef shortDesc, StringRef desc,
                         const ExplodedNode *errorNode)
      : PathSensitiveBugReport(bt, shortDesc, desc, errorNode,
                               /*LocationToUnique*/ {},
                               /*DeclToUnique*/ nullptr) {}

  /// Create a PathSensitiveBugReport 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.
  PathSensitiveBugReport(const BugType &bt, StringRef desc,
                         const ExplodedNode *errorNode,
                         PathDiagnosticLocation LocationToUnique,
                         const Decl *DeclToUnique)
      : PathSensitiveBugReport(bt, desc, desc, errorNode, LocationToUnique,
                               DeclToUnique) {}

  PathSensitiveBugReport(const BugType &bt, StringRef shortDesc, StringRef desc,
                         const ExplodedNode *errorNode,
                         PathDiagnosticLocation LocationToUnique,
                         const Decl *DeclToUnique);

  static bool classof(const BugReport *R) {
    return R->getKind() == Kind::PathSensitive;
  }

  const ExplodedNode *getErrorNode() const { return ErrorNode; }

  /// 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; }

  /// Get the location on which the report should be uniqued.
  PathDiagnosticLocation getUniqueingLocation() const override {
    return UniqueingLocation;
  }

  /// Get the declaration containing the uniqueing location.
  const Decl *getUniqueingDecl() const override {
    return UniqueingDecl;
  }

  const Decl *getDeclWithIssue() const override;

  ArrayRef<SourceRange> getRanges() const override;

  PathDiagnosticLocation getLocation() const override;

  /// Marks a symbol as interesting. Different kinds of interestingness will
  /// be processed differently by visitors (e.g. if the tracking kind is
  /// condition, will append "will be used as a condition" to the message).
  void markInteresting(SymbolRef sym, bugreporter::TrackingKind TKind =
                                          bugreporter::TrackingKind::Thorough);

  void markNotInteresting(SymbolRef sym);

  /// Marks a region as interesting. Different kinds of interestingness will
  /// be processed differently by visitors (e.g. if the tracking kind is
  /// condition, will append "will be used as a condition" to the message).
  void markInteresting(
      const MemRegion *R,
      bugreporter::TrackingKind TKind = bugreporter::TrackingKind::Thorough);

  void markNotInteresting(const MemRegion *R);

  /// Marks a symbolic value as interesting. Different kinds of interestingness
  /// will be processed differently by visitors (e.g. if the tracking kind is
  /// condition, will append "will be used as a condition" to the message).
  void markInteresting(SVal V, bugreporter::TrackingKind TKind =
                                   bugreporter::TrackingKind::Thorough);
  void markInteresting(const LocationContext *LC);

  bool isInteresting(SymbolRef sym) const;
  bool isInteresting(const MemRegion *R) const;
  bool isInteresting(SVal V) const;
  bool isInteresting(const LocationContext *LC) const;

  Optional<bugreporter::TrackingKind>
  getInterestingnessKind(SymbolRef sym) const;

  Optional<bugreporter::TrackingKind>
  getInterestingnessKind(const MemRegion *R) const;

  Optional<bugreporter::TrackingKind> getInterestingnessKind(SVal V) const;

  /// 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));
  }

  /// 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.
  void Profile(llvm::FoldingSetNodeID &hash) const override;

  /// Add custom or predefined bug report visitors to this report.
  ///
  /// The visitors should be used when the default trace is not sufficient.
  /// For example, they allow constructing a more elaborate trace.
  /// @{
  void addVisitor(std::unique_ptr<BugReporterVisitor> visitor);

  template <class VisitorType, class... Args>
  void addVisitor(Args &&... ConstructorArgs) {
    addVisitor(
        std::make_unique<VisitorType>(std::forward<Args>(ConstructorArgs)...));
  }
  /// @}

  /// Remove all visitors attached to this bug report.
  void clearVisitors();

  /// Iterators through the custom diagnostic visitors.
  visitor_iterator visitor_begin() { return Callbacks.begin(); }
  visitor_iterator visitor_end() { return Callbacks.end(); }
  visitor_range visitors() { return {visitor_begin(), visitor_end()}; }

  /// Notes that the condition of the CFGBlock associated with \p Cond is
  /// being tracked.
  /// \returns false if the condition is already being tracked.
  bool addTrackedCondition(const ExplodedNode *Cond) {
    return TrackedConditions.insert(Cond).second;
  }

  void addCallStackHint(PathDiagnosticPieceRef Piece,
                        std::unique_ptr<StackHintGenerator> StackHint) {
    StackHints[Piece] = std::move(StackHint);
  }

  bool hasCallStackHint(PathDiagnosticPieceRef Piece) const {
    return StackHints.count(Piece) > 0;
  }

  /// Produce the hint for the given node. The node contains
  /// information about the call for which the diagnostic can be generated.
  std::string
  getCallStackMessage(PathDiagnosticPieceRef Piece,
                      const ExplodedNode *N) const {
    auto I = StackHints.find(Piece);
    if (I != StackHints.end())
      return I->second->getMessage(N);
    return "";
  }
};

//===----------------------------------------------------------------------===//
// BugTypes (collections of related reports).
//===----------------------------------------------------------------------===//

class BugReportEquivClass : public llvm::FoldingSetNode {
  friend class BugReporter;

  /// List of *owned* BugReport objects.
  llvm::SmallVector<std::unique_ptr<BugReport>, 4> Reports;

  void AddReport(std::unique_ptr<BugReport> &&R) {
    Reports.push_back(std::move(R));
  }

public:
  BugReportEquivClass(std::unique_ptr<BugReport> R) { AddReport(std::move(R)); }

  ArrayRef<std::unique_ptr<BugReport>> getReports() const { return Reports; }

  void Profile(llvm::FoldingSetNodeID& ID) const {
    assert(!Reports.empty());
    Reports.front()->Profile(ID);
  }
};

//===----------------------------------------------------------------------===//
// BugReporter and friends.
//===----------------------------------------------------------------------===//

class BugReporterData {
public:
  virtual ~BugReporterData() = default;

  virtual ArrayRef<PathDiagnosticConsumer*> getPathDiagnosticConsumers() = 0;
  virtual ASTContext &getASTContext() = 0;
  virtual SourceManager &getSourceManager() = 0;
  virtual AnalyzerOptions &getAnalyzerOptions() = 0;
  virtual Preprocessor &getPreprocessor() = 0;
};

/// BugReporter is a utility class for generating PathDiagnostics for analysis.
/// It collects the BugReports and BugTypes and knows how to generate
/// and flush the corresponding diagnostics.
///
/// The base class is used for generating path-insensitive
class BugReporter {
private:
  BugReporterData& D;

  /// Generate and flush the diagnostics for the given bug report.
  void FlushReport(BugReportEquivClass& EQ);

  /// 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;

public:
  BugReporter(BugReporterData &d);
  virtual ~BugReporter();

  /// Generate and flush diagnostics for all bug reports.
  void FlushReports();

  ArrayRef<PathDiagnosticConsumer*> getPathDiagnosticConsumers() {
    return D.getPathDiagnosticConsumers();
  }

  /// Iterator over the set of BugReports tracked by the BugReporter.
  using EQClasses_iterator = llvm::FoldingSet<BugReportEquivClass>::iterator;
  EQClasses_iterator EQClasses_begin() { return EQClasses.begin(); }
  EQClasses_iterator EQClasses_end() { return EQClasses.end(); }

  ASTContext &getContext() { return D.getASTContext(); }

  const SourceManager &getSourceManager() { return D.getSourceManager(); }

  const AnalyzerOptions &getAnalyzerOptions() { return D.getAnalyzerOptions(); }

  Preprocessor &getPreprocessor() { return D.getPreprocessor(); }

  /// Add the given report to the set of reports tracked by BugReporter.
  ///
  /// The reports are usually generated by the checkers. Further, they are
  /// folded based on the profile value, which is done to coalesce similar
  /// reports.
  virtual void emitReport(std::unique_ptr<BugReport> R);

  void EmitBasicReport(const Decl *DeclWithIssue, const CheckerBase *Checker,
                       StringRef BugName, StringRef BugCategory,
                       StringRef BugStr, PathDiagnosticLocation Loc,
                       ArrayRef<SourceRange> Ranges = None,
                       ArrayRef<FixItHint> Fixits = None);

  void EmitBasicReport(const Decl *DeclWithIssue, CheckerNameRef CheckerName,
                       StringRef BugName, StringRef BugCategory,
                       StringRef BugStr, PathDiagnosticLocation Loc,
                       ArrayRef<SourceRange> Ranges = None,
                       ArrayRef<FixItHint> Fixits = None);

private:
  llvm::StringMap<std::unique_ptr<BugType>> StrBugTypes;

  /// Returns a BugType that is associated with the given name and
  /// category.
  BugType *getBugTypeForName(CheckerNameRef CheckerName, StringRef name,
                             StringRef category);

  virtual BugReport *
  findReportInEquivalenceClass(BugReportEquivClass &eqClass,
                               SmallVectorImpl<BugReport *> &bugReports) {
    return eqClass.getReports()[0].get();
  }

protected:
  /// Generate the diagnostics for the given bug report.
  virtual std::unique_ptr<DiagnosticForConsumerMapTy>
  generateDiagnosticForConsumerMap(BugReport *exampleReport,
                                   ArrayRef<PathDiagnosticConsumer *> consumers,
                                   ArrayRef<BugReport *> bugReports);
};

/// GRBugReporter is used for generating path-sensitive reports.
class PathSensitiveBugReporter final : public BugReporter {
  ExprEngine& Eng;

  BugReport *findReportInEquivalenceClass(
      BugReportEquivClass &eqClass,
      SmallVectorImpl<BugReport *> &bugReports) override;

  /// Generate the diagnostics for the given bug report.
  std::unique_ptr<DiagnosticForConsumerMapTy>
  generateDiagnosticForConsumerMap(BugReport *exampleReport,
                                   ArrayRef<PathDiagnosticConsumer *> consumers,
                                   ArrayRef<BugReport *> bugReports) override;
public:
  PathSensitiveBugReporter(BugReporterData& d, ExprEngine& eng)
      : BugReporter(d), Eng(eng) {}

  /// getGraph - Get the exploded graph created by the analysis engine
  ///  for the analyzed method or function.
  const ExplodedGraph &getGraph() const;

  /// getStateManager - Return the state manager used by the analysis
  ///  engine.
  ProgramStateManager &getStateManager() const;

  /// \p bugReports A set of bug reports within a *single* equivalence class
  ///
  /// \return A mapping from consumers to the corresponding diagnostics.
  /// Iterates through the bug reports within a single equivalence class,
  /// stops at a first non-invalidated report.
  std::unique_ptr<DiagnosticForConsumerMapTy> generatePathDiagnostics(
      ArrayRef<PathDiagnosticConsumer *> consumers,
      ArrayRef<PathSensitiveBugReport *> &bugReports);

  void emitReport(std::unique_ptr<BugReport> R) override;
};


class BugReporterContext {
  PathSensitiveBugReporter &BR;

  virtual void anchor();

public:
  BugReporterContext(PathSensitiveBugReporter &br) : BR(br) {}

  virtual ~BugReporterContext() = default;

  PathSensitiveBugReporter& getBugReporter() { return BR; }

  ProgramStateManager& getStateManager() const {
    return BR.getStateManager();
  }

  ASTContext &getASTContext() const {
    return BR.getContext();
  }

  const SourceManager& getSourceManager() const {
    return BR.getSourceManager();
  }

  const AnalyzerOptions &getAnalyzerOptions() const {
    return BR.getAnalyzerOptions();
  }
};

/// The tag that carries some information with it.
///
/// It can be valuable to produce tags with some bits of information and later
/// reuse them for a better diagnostic.
///
/// Please make sure that derived class' constuctor is private and that the user
/// can only create objects using DataTag::Factory.  This also means that
/// DataTag::Factory should be friend for every derived class.
class DataTag : public ProgramPointTag {
public:
  StringRef getTagDescription() const override { return "Data Tag"; }

  // Manage memory for DataTag objects.
  class Factory {
    std::vector<std::unique_ptr<DataTag>> Tags;

  public:
    template <class DataTagType, class... Args>
    const DataTagType *make(Args &&... ConstructorArgs) {
      // We cannot use std::make_unique because we cannot access the private
      // constructor from inside it.
      Tags.emplace_back(
          new DataTagType(std::forward<Args>(ConstructorArgs)...));
      return static_cast<DataTagType *>(Tags.back().get());
    }
  };

protected:
  DataTag(void *TagKind) : ProgramPointTag(TagKind) {}
};

/// The tag upon which the TagVisitor reacts. Add these in order to display
/// additional PathDiagnosticEventPieces along the path.
class NoteTag : public DataTag {
public:
  using Callback = std::function<std::string(BugReporterContext &,
                                             PathSensitiveBugReport &)>;

private:
  static int Kind;

  const Callback Cb;
  const bool IsPrunable;

  NoteTag(Callback &&Cb, bool IsPrunable)
      : DataTag(&Kind), Cb(std::move(Cb)), IsPrunable(IsPrunable) {}

public:
  static bool classof(const ProgramPointTag *T) {
    return T->getTagKind() == &Kind;
  }

  Optional<std::string> generateMessage(BugReporterContext &BRC,
                                        PathSensitiveBugReport &R) const {
    std::string Msg = Cb(BRC, R);
    if (Msg.empty())
      return None;

    return std::move(Msg);
  }

  StringRef getTagDescription() const override {
    // TODO: Remember a few examples of generated messages
    // and display them in the ExplodedGraph dump by
    // returning them from this function.
    return "Note Tag";
  }

  bool isPrunable() const { return IsPrunable; }

  friend class Factory;
  friend class TagVisitor;
};

} // namespace ento

} // namespace clang

#endif // LLVM_CLANG_STATICANALYZER_CORE_BUGREPORTER_BUGREPORTER_H
