//===- BugReporter.cpp - Generate PathDiagnostics for bugs ----------------===//
//
// 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.
//
//===----------------------------------------------------------------------===//

#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclBase.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/Expr.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/ParentMap.h"
#include "clang/AST/Stmt.h"
#include "clang/AST/StmtCXX.h"
#include "clang/AST/StmtObjC.h"
#include "clang/Analysis/AnalysisDeclContext.h"
#include "clang/Analysis/CFG.h"
#include "clang/Analysis/CFGStmtMap.h"
#include "clang/Analysis/PathDiagnostic.h"
#include "clang/Analysis/ProgramPoint.h"
#include "clang/Basic/LLVM.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/SourceManager.h"
#include "clang/StaticAnalyzer/Core/AnalyzerOptions.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitors.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
#include "clang/StaticAnalyzer/Core/Checker.h"
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/FoldingSet.h"
#include "llvm/ADT/None.h"
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/iterator_range.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
#include <cassert>
#include <cstddef>
#include <iterator>
#include <memory>
#include <queue>
#include <string>
#include <tuple>
#include <utility>
#include <vector>

using namespace clang;
using namespace ento;
using namespace llvm;

#define DEBUG_TYPE "BugReporter"

STATISTIC(MaxBugClassSize,
          "The maximum number of bug reports in the same equivalence class");
STATISTIC(MaxValidBugClassSize,
          "The maximum number of bug reports in the same equivalence class "
          "where at least one report is valid (not suppressed)");

BugReporterVisitor::~BugReporterVisitor() = default;

void BugReporterContext::anchor() {}

//===----------------------------------------------------------------------===//
// PathDiagnosticBuilder and its associated routines and helper objects.
//===----------------------------------------------------------------------===//

namespace {

/// A (CallPiece, node assiciated with its CallEnter) pair.
using CallWithEntry =
    std::pair<PathDiagnosticCallPiece *, const ExplodedNode *>;
using CallWithEntryStack = SmallVector<CallWithEntry, 6>;

/// Map from each node to the diagnostic pieces visitors emit for them.
using VisitorsDiagnosticsTy =
    llvm::DenseMap<const ExplodedNode *, std::vector<PathDiagnosticPieceRef>>;

/// A map from PathDiagnosticPiece to the LocationContext of the inlined
/// function call it represents.
using LocationContextMap =
    llvm::DenseMap<const PathPieces *, const LocationContext *>;

/// A helper class that contains everything needed to construct a
/// PathDiagnostic object. It does no much more then providing convenient
/// getters and some well placed asserts for extra security.
class PathDiagnosticConstruct {
  /// The consumer we're constructing the bug report for.
  const PathDiagnosticConsumer *Consumer;
  /// Our current position in the bug path, which is owned by
  /// PathDiagnosticBuilder.
  const ExplodedNode *CurrentNode;
  /// A mapping from parts of the bug path (for example, a function call, which
  /// would span backwards from a CallExit to a CallEnter with the nodes in
  /// between them) with the location contexts it is associated with.
  LocationContextMap LCM;
  const SourceManager &SM;

public:
  /// We keep stack of calls to functions as we're ascending the bug path.
  /// TODO: PathDiagnostic has a stack doing the same thing, shouldn't we use
  /// that instead?
  CallWithEntryStack CallStack;
  /// The bug report we're constructing. For ease of use, this field is kept
  /// public, though some "shortcut" getters are provided for commonly used
  /// methods of PathDiagnostic.
  std::unique_ptr<PathDiagnostic> PD;

public:
  PathDiagnosticConstruct(const PathDiagnosticConsumer *PDC,
                          const ExplodedNode *ErrorNode,
                          const PathSensitiveBugReport *R);

  /// \returns the location context associated with the current position in the
  /// bug path.
  const LocationContext *getCurrLocationContext() const {
    assert(CurrentNode && "Already reached the root!");
    return CurrentNode->getLocationContext();
  }

  /// Same as getCurrLocationContext (they should always return the same
  /// location context), but works after reaching the root of the bug path as
  /// well.
  const LocationContext *getLocationContextForActivePath() const {
    return LCM.find(&PD->getActivePath())->getSecond();
  }

  const ExplodedNode *getCurrentNode() const { return CurrentNode; }

  /// Steps the current node to its predecessor.
  /// \returns whether we reached the root of the bug path.
  bool ascendToPrevNode() {
    CurrentNode = CurrentNode->getFirstPred();
    return static_cast<bool>(CurrentNode);
  }

  const ParentMap &getParentMap() const {
    return getCurrLocationContext()->getParentMap();
  }

  const SourceManager &getSourceManager() const { return SM; }

  const Stmt *getParent(const Stmt *S) const {
    return getParentMap().getParent(S);
  }

  void updateLocCtxMap(const PathPieces *Path, const LocationContext *LC) {
    assert(Path && LC);
    LCM[Path] = LC;
  }

  const LocationContext *getLocationContextFor(const PathPieces *Path) const {
    assert(LCM.count(Path) &&
           "Failed to find the context associated with these pieces!");
    return LCM.find(Path)->getSecond();
  }

  bool isInLocCtxMap(const PathPieces *Path) const { return LCM.count(Path); }

  PathPieces &getActivePath() { return PD->getActivePath(); }
  PathPieces &getMutablePieces() { return PD->getMutablePieces(); }

  bool shouldAddPathEdges() const { return Consumer->shouldAddPathEdges(); }
  bool shouldGenerateDiagnostics() const {
    return Consumer->shouldGenerateDiagnostics();
  }
  bool supportsLogicalOpControlFlow() const {
    return Consumer->supportsLogicalOpControlFlow();
  }
};

/// Contains every contextual information needed for constructing a
/// PathDiagnostic object for a given bug report. This class and its fields are
/// immutable, and passes a BugReportConstruct object around during the
/// construction.
class PathDiagnosticBuilder : public BugReporterContext {
  /// A linear path from the error node to the root.
  std::unique_ptr<const ExplodedGraph> BugPath;
  /// The bug report we're describing. Visitors create their diagnostics with
  /// them being the last entities being able to modify it (for example,
  /// changing interestingness here would cause inconsistencies as to how this
  /// file and visitors construct diagnostics), hence its const.
  const PathSensitiveBugReport *R;
  /// The leaf of the bug path. This isn't the same as the bug reports error
  /// node, which refers to the *original* graph, not the bug path.
  const ExplodedNode *const ErrorNode;
  /// The diagnostic pieces visitors emitted, which is expected to be collected
  /// by the time this builder is constructed.
  std::unique_ptr<const VisitorsDiagnosticsTy> VisitorsDiagnostics;

public:
  /// Find a non-invalidated report for a given equivalence class,  and returns
  /// a PathDiagnosticBuilder able to construct bug reports for different
  /// consumers. Returns None if no valid report is found.
  static Optional<PathDiagnosticBuilder>
  findValidReport(ArrayRef<PathSensitiveBugReport *> &bugReports,
                  PathSensitiveBugReporter &Reporter);

  PathDiagnosticBuilder(
      BugReporterContext BRC, std::unique_ptr<ExplodedGraph> BugPath,
      PathSensitiveBugReport *r, const ExplodedNode *ErrorNode,
      std::unique_ptr<VisitorsDiagnosticsTy> VisitorsDiagnostics);

  /// This function is responsible for generating diagnostic pieces that are
  /// *not* provided by bug report visitors.
  /// These diagnostics may differ depending on the consumer's settings,
  /// and are therefore constructed separately for each consumer.
  ///
  /// There are two path diagnostics generation modes: with adding edges (used
  /// for plists) and without  (used for HTML and text). When edges are added,
  /// the path is modified to insert artificially generated edges.
  /// Otherwise, more detailed diagnostics is emitted for block edges,
  /// explaining the transitions in words.
  std::unique_ptr<PathDiagnostic>
  generate(const PathDiagnosticConsumer *PDC) const;

private:
  void updateStackPiecesWithMessage(PathDiagnosticPieceRef P,
                                    const CallWithEntryStack &CallStack) const;
  void generatePathDiagnosticsForNode(PathDiagnosticConstruct &C,
                                      PathDiagnosticLocation &PrevLoc) const;

  void generateMinimalDiagForBlockEdge(PathDiagnosticConstruct &C,
                                       BlockEdge BE) const;

  PathDiagnosticPieceRef
  generateDiagForGotoOP(const PathDiagnosticConstruct &C, const Stmt *S,
                        PathDiagnosticLocation &Start) const;

  PathDiagnosticPieceRef
  generateDiagForSwitchOP(const PathDiagnosticConstruct &C, const CFGBlock *Dst,
                          PathDiagnosticLocation &Start) const;

  PathDiagnosticPieceRef
  generateDiagForBinaryOP(const PathDiagnosticConstruct &C, const Stmt *T,
                          const CFGBlock *Src, const CFGBlock *DstC) const;

  PathDiagnosticLocation
  ExecutionContinues(const PathDiagnosticConstruct &C) const;

  PathDiagnosticLocation
  ExecutionContinues(llvm::raw_string_ostream &os,
                     const PathDiagnosticConstruct &C) const;

  const PathSensitiveBugReport *getBugReport() const { return R; }
};

} // namespace

//===----------------------------------------------------------------------===//
// Base implementation of stack hint generators.
//===----------------------------------------------------------------------===//

StackHintGenerator::~StackHintGenerator() = default;

std::string StackHintGeneratorForSymbol::getMessage(const ExplodedNode *N){
  if (!N)
    return getMessageForSymbolNotFound();

  ProgramPoint P = N->getLocation();
  CallExitEnd CExit = P.castAs<CallExitEnd>();

  // FIXME: Use CallEvent to abstract this over all calls.
  const Stmt *CallSite = CExit.getCalleeContext()->getCallSite();
  const auto *CE = dyn_cast_or_null<CallExpr>(CallSite);
  if (!CE)
    return {};

  // Check if one of the parameters are set to the interesting symbol.
  unsigned ArgIndex = 0;
  for (CallExpr::const_arg_iterator I = CE->arg_begin(),
                                    E = CE->arg_end(); I != E; ++I, ++ArgIndex){
    SVal SV = N->getSVal(*I);

    // Check if the variable corresponding to the symbol is passed by value.
    SymbolRef AS = SV.getAsLocSymbol();
    if (AS == Sym) {
      return getMessageForArg(*I, ArgIndex);
    }

    // Check if the parameter is a pointer to the symbol.
    if (Optional<loc::MemRegionVal> Reg = SV.getAs<loc::MemRegionVal>()) {
      // Do not attempt to dereference void*.
      if ((*I)->getType()->isVoidPointerType())
        continue;
      SVal PSV = N->getState()->getSVal(Reg->getRegion());
      SymbolRef AS = PSV.getAsLocSymbol();
      if (AS == Sym) {
        return getMessageForArg(*I, ArgIndex);
      }
    }
  }

  // Check if we are returning the interesting symbol.
  SVal SV = N->getSVal(CE);
  SymbolRef RetSym = SV.getAsLocSymbol();
  if (RetSym == Sym) {
    return getMessageForReturn(CE);
  }

  return getMessageForSymbolNotFound();
}

std::string StackHintGeneratorForSymbol::getMessageForArg(const Expr *ArgE,
                                                          unsigned ArgIndex) {
  // Printed parameters start at 1, not 0.
  ++ArgIndex;

  return (llvm::Twine(Msg) + " via " + std::to_string(ArgIndex) +
          llvm::getOrdinalSuffix(ArgIndex) + " parameter").str();
}

//===----------------------------------------------------------------------===//
// Diagnostic cleanup.
//===----------------------------------------------------------------------===//

static PathDiagnosticEventPiece *
eventsDescribeSameCondition(PathDiagnosticEventPiece *X,
                            PathDiagnosticEventPiece *Y) {
  // Prefer diagnostics that come from ConditionBRVisitor over
  // those that came from TrackConstraintBRVisitor,
  // unless the one from ConditionBRVisitor is
  // its generic fallback diagnostic.
  const void *tagPreferred = ConditionBRVisitor::getTag();
  const void *tagLesser = TrackConstraintBRVisitor::getTag();

  if (X->getLocation() != Y->getLocation())
    return nullptr;

  if (X->getTag() == tagPreferred && Y->getTag() == tagLesser)
    return ConditionBRVisitor::isPieceMessageGeneric(X) ? Y : X;

  if (Y->getTag() == tagPreferred && X->getTag() == tagLesser)
    return ConditionBRVisitor::isPieceMessageGeneric(Y) ? X : Y;

  return nullptr;
}

/// An optimization pass over PathPieces that removes redundant diagnostics
/// generated by both ConditionBRVisitor and TrackConstraintBRVisitor.  Both
/// BugReporterVisitors use different methods to generate diagnostics, with
/// one capable of emitting diagnostics in some cases but not in others.  This
/// can lead to redundant diagnostic pieces at the same point in a path.
static void removeRedundantMsgs(PathPieces &path) {
  unsigned N = path.size();
  if (N < 2)
    return;
  // NOTE: this loop intentionally is not using an iterator.  Instead, we
  // are streaming the path and modifying it in place.  This is done by
  // grabbing the front, processing it, and if we decide to keep it append
  // it to the end of the path.  The entire path is processed in this way.
  for (unsigned i = 0; i < N; ++i) {
    auto piece = std::move(path.front());
    path.pop_front();

    switch (piece->getKind()) {
      case PathDiagnosticPiece::Call:
        removeRedundantMsgs(cast<PathDiagnosticCallPiece>(*piece).path);
        break;
      case PathDiagnosticPiece::Macro:
        removeRedundantMsgs(cast<PathDiagnosticMacroPiece>(*piece).subPieces);
        break;
      case PathDiagnosticPiece::Event: {
        if (i == N-1)
          break;

        if (auto *nextEvent =
            dyn_cast<PathDiagnosticEventPiece>(path.front().get())) {
          auto *event = cast<PathDiagnosticEventPiece>(piece.get());
          // Check to see if we should keep one of the two pieces.  If we
          // come up with a preference, record which piece to keep, and consume
          // another piece from the path.
          if (auto *pieceToKeep =
                  eventsDescribeSameCondition(event, nextEvent)) {
            piece = std::move(pieceToKeep == event ? piece : path.front());
            path.pop_front();
            ++i;
          }
        }
        break;
      }
      case PathDiagnosticPiece::ControlFlow:
      case PathDiagnosticPiece::Note:
      case PathDiagnosticPiece::PopUp:
        break;
    }
    path.push_back(std::move(piece));
  }
}

/// Recursively scan through a path and prune out calls and macros pieces
/// that aren't needed.  Return true if afterwards the path contains
/// "interesting stuff" which means it shouldn't be pruned from the parent path.
static bool removeUnneededCalls(const PathDiagnosticConstruct &C,
                                PathPieces &pieces,
                                const PathSensitiveBugReport *R,
                                bool IsInteresting = false) {
  bool containsSomethingInteresting = IsInteresting;
  const unsigned N = pieces.size();

  for (unsigned i = 0 ; i < N ; ++i) {
    // Remove the front piece from the path.  If it is still something we
    // want to keep once we are done, we will push it back on the end.
    auto piece = std::move(pieces.front());
    pieces.pop_front();

    switch (piece->getKind()) {
      case PathDiagnosticPiece::Call: {
        auto &call = cast<PathDiagnosticCallPiece>(*piece);
        // Check if the location context is interesting.
        if (!removeUnneededCalls(
                C, call.path, R,
                R->isInteresting(C.getLocationContextFor(&call.path))))
          continue;

        containsSomethingInteresting = true;
        break;
      }
      case PathDiagnosticPiece::Macro: {
        auto &macro = cast<PathDiagnosticMacroPiece>(*piece);
        if (!removeUnneededCalls(C, macro.subPieces, R, IsInteresting))
          continue;
        containsSomethingInteresting = true;
        break;
      }
      case PathDiagnosticPiece::Event: {
        auto &event = cast<PathDiagnosticEventPiece>(*piece);

        // We never throw away an event, but we do throw it away wholesale
        // as part of a path if we throw the entire path away.
        containsSomethingInteresting |= !event.isPrunable();
        break;
      }
      case PathDiagnosticPiece::ControlFlow:
      case PathDiagnosticPiece::Note:
      case PathDiagnosticPiece::PopUp:
        break;
    }

    pieces.push_back(std::move(piece));
  }

  return containsSomethingInteresting;
}

/// Same logic as above to remove extra pieces.
static void removePopUpNotes(PathPieces &Path) {
  for (unsigned int i = 0; i < Path.size(); ++i) {
    auto Piece = std::move(Path.front());
    Path.pop_front();
    if (!isa<PathDiagnosticPopUpPiece>(*Piece))
      Path.push_back(std::move(Piece));
  }
}

/// Returns true if the given decl has been implicitly given a body, either by
/// the analyzer or by the compiler proper.
static bool hasImplicitBody(const Decl *D) {
  assert(D);
  return D->isImplicit() || !D->hasBody();
}

/// Recursively scan through a path and make sure that all call pieces have
/// valid locations.
static void
adjustCallLocations(PathPieces &Pieces,
                    PathDiagnosticLocation *LastCallLocation = nullptr) {
  for (const auto &I : Pieces) {
    auto *Call = dyn_cast<PathDiagnosticCallPiece>(I.get());

    if (!Call)
      continue;

    if (LastCallLocation) {
      bool CallerIsImplicit = hasImplicitBody(Call->getCaller());
      if (CallerIsImplicit || !Call->callEnter.asLocation().isValid())
        Call->callEnter = *LastCallLocation;
      if (CallerIsImplicit || !Call->callReturn.asLocation().isValid())
        Call->callReturn = *LastCallLocation;
    }

    // Recursively clean out the subclass.  Keep this call around if
    // it contains any informative diagnostics.
    PathDiagnosticLocation *ThisCallLocation;
    if (Call->callEnterWithin.asLocation().isValid() &&
        !hasImplicitBody(Call->getCallee()))
      ThisCallLocation = &Call->callEnterWithin;
    else
      ThisCallLocation = &Call->callEnter;

    assert(ThisCallLocation && "Outermost call has an invalid location");
    adjustCallLocations(Call->path, ThisCallLocation);
  }
}

/// Remove edges in and out of C++ default initializer expressions. These are
/// for fields that have in-class initializers, as opposed to being initialized
/// explicitly in a constructor or braced list.
static void removeEdgesToDefaultInitializers(PathPieces &Pieces) {
  for (PathPieces::iterator I = Pieces.begin(), E = Pieces.end(); I != E;) {
    if (auto *C = dyn_cast<PathDiagnosticCallPiece>(I->get()))
      removeEdgesToDefaultInitializers(C->path);

    if (auto *M = dyn_cast<PathDiagnosticMacroPiece>(I->get()))
      removeEdgesToDefaultInitializers(M->subPieces);

    if (auto *CF = dyn_cast<PathDiagnosticControlFlowPiece>(I->get())) {
      const Stmt *Start = CF->getStartLocation().asStmt();
      const Stmt *End = CF->getEndLocation().asStmt();
      if (Start && isa<CXXDefaultInitExpr>(Start)) {
        I = Pieces.erase(I);
        continue;
      } else if (End && isa<CXXDefaultInitExpr>(End)) {
        PathPieces::iterator Next = std::next(I);
        if (Next != E) {
          if (auto *NextCF =
                  dyn_cast<PathDiagnosticControlFlowPiece>(Next->get())) {
            NextCF->setStartLocation(CF->getStartLocation());
          }
        }
        I = Pieces.erase(I);
        continue;
      }
    }

    I++;
  }
}

/// Remove all pieces with invalid locations as these cannot be serialized.
/// We might have pieces with invalid locations as a result of inlining Body
/// Farm generated functions.
static void removePiecesWithInvalidLocations(PathPieces &Pieces) {
  for (PathPieces::iterator I = Pieces.begin(), E = Pieces.end(); I != E;) {
    if (auto *C = dyn_cast<PathDiagnosticCallPiece>(I->get()))
      removePiecesWithInvalidLocations(C->path);

    if (auto *M = dyn_cast<PathDiagnosticMacroPiece>(I->get()))
      removePiecesWithInvalidLocations(M->subPieces);

    if (!(*I)->getLocation().isValid() ||
        !(*I)->getLocation().asLocation().isValid()) {
      I = Pieces.erase(I);
      continue;
    }
    I++;
  }
}

PathDiagnosticLocation PathDiagnosticBuilder::ExecutionContinues(
    const PathDiagnosticConstruct &C) const {
  if (const Stmt *S = C.getCurrentNode()->getNextStmtForDiagnostics())
    return PathDiagnosticLocation(S, getSourceManager(),
                                  C.getCurrLocationContext());

  return PathDiagnosticLocation::createDeclEnd(C.getCurrLocationContext(),
                                               getSourceManager());
}

PathDiagnosticLocation PathDiagnosticBuilder::ExecutionContinues(
    llvm::raw_string_ostream &os, const PathDiagnosticConstruct &C) const {
  // Slow, but probably doesn't matter.
  if (os.str().empty())
    os << ' ';

  const PathDiagnosticLocation &Loc = ExecutionContinues(C);

  if (Loc.asStmt())
    os << "Execution continues on line "
       << getSourceManager().getExpansionLineNumber(Loc.asLocation())
       << '.';
  else {
    os << "Execution jumps to the end of the ";
    const Decl *D = C.getCurrLocationContext()->getDecl();
    if (isa<ObjCMethodDecl>(D))
      os << "method";
    else if (isa<FunctionDecl>(D))
      os << "function";
    else {
      assert(isa<BlockDecl>(D));
      os << "anonymous block";
    }
    os << '.';
  }

  return Loc;
}

static const Stmt *getEnclosingParent(const Stmt *S, const ParentMap &PM) {
  if (isa<Expr>(S) && PM.isConsumedExpr(cast<Expr>(S)))
    return PM.getParentIgnoreParens(S);

  const Stmt *Parent = PM.getParentIgnoreParens(S);
  if (!Parent)
    return nullptr;

  switch (Parent->getStmtClass()) {
  case Stmt::ForStmtClass:
  case Stmt::DoStmtClass:
  case Stmt::WhileStmtClass:
  case Stmt::ObjCForCollectionStmtClass:
  case Stmt::CXXForRangeStmtClass:
    return Parent;
  default:
    break;
  }

  return nullptr;
}

static PathDiagnosticLocation
getEnclosingStmtLocation(const Stmt *S, const LocationContext *LC,
                         bool allowNestedContexts = false) {
  if (!S)
    return {};

  const SourceManager &SMgr = LC->getDecl()->getASTContext().getSourceManager();

  while (const Stmt *Parent = getEnclosingParent(S, LC->getParentMap())) {
    switch (Parent->getStmtClass()) {
      case Stmt::BinaryOperatorClass: {
        const auto *B = cast<BinaryOperator>(Parent);
        if (B->isLogicalOp())
          return PathDiagnosticLocation(allowNestedContexts ? B : S, SMgr, LC);
        break;
      }
      case Stmt::CompoundStmtClass:
      case Stmt::StmtExprClass:
        return PathDiagnosticLocation(S, SMgr, LC);
      case Stmt::ChooseExprClass:
        // Similar to '?' if we are referring to condition, just have the edge
        // point to the entire choose expression.
        if (allowNestedContexts || cast<ChooseExpr>(Parent)->getCond() == S)
          return PathDiagnosticLocation(Parent, SMgr, LC);
        else
          return PathDiagnosticLocation(S, SMgr, LC);
      case Stmt::BinaryConditionalOperatorClass:
      case Stmt::ConditionalOperatorClass:
        // For '?', if we are referring to condition, just have the edge point
        // to the entire '?' expression.
        if (allowNestedContexts ||
            cast<AbstractConditionalOperator>(Parent)->getCond() == S)
          return PathDiagnosticLocation(Parent, SMgr, LC);
        else
          return PathDiagnosticLocation(S, SMgr, LC);
      case Stmt::CXXForRangeStmtClass:
        if (cast<CXXForRangeStmt>(Parent)->getBody() == S)
          return PathDiagnosticLocation(S, SMgr, LC);
        break;
      case Stmt::DoStmtClass:
          return PathDiagnosticLocation(S, SMgr, LC);
      case Stmt::ForStmtClass:
        if (cast<ForStmt>(Parent)->getBody() == S)
          return PathDiagnosticLocation(S, SMgr, LC);
        break;
      case Stmt::IfStmtClass:
        if (cast<IfStmt>(Parent)->getCond() != S)
          return PathDiagnosticLocation(S, SMgr, LC);
        break;
      case Stmt::ObjCForCollectionStmtClass:
        if (cast<ObjCForCollectionStmt>(Parent)->getBody() == S)
          return PathDiagnosticLocation(S, SMgr, LC);
        break;
      case Stmt::WhileStmtClass:
        if (cast<WhileStmt>(Parent)->getCond() != S)
          return PathDiagnosticLocation(S, SMgr, LC);
        break;
      default:
        break;
    }

    S = Parent;
  }

  assert(S && "Cannot have null Stmt for PathDiagnosticLocation");

  return PathDiagnosticLocation(S, SMgr, LC);
}

//===----------------------------------------------------------------------===//
// "Minimal" path diagnostic generation algorithm.
//===----------------------------------------------------------------------===//

/// If the piece contains a special message, add it to all the call pieces on
/// the active stack. For example, my_malloc allocated memory, so MallocChecker
/// will construct an event at the call to malloc(), and add a stack hint that
/// an allocated memory was returned. We'll use this hint to construct a message
/// when returning from the call to my_malloc
///
///   void *my_malloc() { return malloc(sizeof(int)); }
///   void fishy() {
///     void *ptr = my_malloc(); // returned allocated memory
///   } // leak
void PathDiagnosticBuilder::updateStackPiecesWithMessage(
    PathDiagnosticPieceRef P, const CallWithEntryStack &CallStack) const {
  if (R->hasCallStackHint(P))
    for (const auto &I : CallStack) {
      PathDiagnosticCallPiece *CP = I.first;
      const ExplodedNode *N = I.second;
      std::string stackMsg = R->getCallStackMessage(P, N);

      // The last message on the path to final bug is the most important
      // one. Since we traverse the path backwards, do not add the message
      // if one has been previously added.
      if (!CP->hasCallStackMessage())
        CP->setCallStackMessage(stackMsg);
    }
}

static void CompactMacroExpandedPieces(PathPieces &path,
                                       const SourceManager& SM);

PathDiagnosticPieceRef PathDiagnosticBuilder::generateDiagForSwitchOP(
    const PathDiagnosticConstruct &C, const CFGBlock *Dst,
    PathDiagnosticLocation &Start) const {

  const SourceManager &SM = getSourceManager();
  // Figure out what case arm we took.
  std::string sbuf;
  llvm::raw_string_ostream os(sbuf);
  PathDiagnosticLocation End;

  if (const Stmt *S = Dst->getLabel()) {
    End = PathDiagnosticLocation(S, SM, C.getCurrLocationContext());

    switch (S->getStmtClass()) {
    default:
      os << "No cases match in the switch statement. "
        "Control jumps to line "
        << End.asLocation().getExpansionLineNumber();
      break;
    case Stmt::DefaultStmtClass:
      os << "Control jumps to the 'default' case at line "
        << End.asLocation().getExpansionLineNumber();
      break;

    case Stmt::CaseStmtClass: {
      os << "Control jumps to 'case ";
      const auto *Case = cast<CaseStmt>(S);
      const Expr *LHS = Case->getLHS()->IgnoreParenCasts();

      // Determine if it is an enum.
      bool GetRawInt = true;

      if (const auto *DR = dyn_cast<DeclRefExpr>(LHS)) {
        // FIXME: Maybe this should be an assertion.  Are there cases
        // were it is not an EnumConstantDecl?
        const auto *D = dyn_cast<EnumConstantDecl>(DR->getDecl());

        if (D) {
          GetRawInt = false;
          os << *D;
        }
      }

      if (GetRawInt)
        os << LHS->EvaluateKnownConstInt(getASTContext());

      os << ":'  at line " << End.asLocation().getExpansionLineNumber();
      break;
    }
    }
  } else {
    os << "'Default' branch taken. ";
    End = ExecutionContinues(os, C);
  }
  return std::make_shared<PathDiagnosticControlFlowPiece>(Start, End,
                                                       os.str());
}

PathDiagnosticPieceRef PathDiagnosticBuilder::generateDiagForGotoOP(
    const PathDiagnosticConstruct &C, const Stmt *S,
    PathDiagnosticLocation &Start) const {
  std::string sbuf;
  llvm::raw_string_ostream os(sbuf);
  const PathDiagnosticLocation &End =
      getEnclosingStmtLocation(S, C.getCurrLocationContext());
  os << "Control jumps to line " << End.asLocation().getExpansionLineNumber();
  return std::make_shared<PathDiagnosticControlFlowPiece>(Start, End, os.str());
}

PathDiagnosticPieceRef PathDiagnosticBuilder::generateDiagForBinaryOP(
    const PathDiagnosticConstruct &C, const Stmt *T, const CFGBlock *Src,
    const CFGBlock *Dst) const {

  const SourceManager &SM = getSourceManager();

  const auto *B = cast<BinaryOperator>(T);
  std::string sbuf;
  llvm::raw_string_ostream os(sbuf);
  os << "Left side of '";
  PathDiagnosticLocation Start, End;

  if (B->getOpcode() == BO_LAnd) {
    os << "&&"
      << "' is ";

    if (*(Src->succ_begin() + 1) == Dst) {
      os << "false";
      End = PathDiagnosticLocation(B->getLHS(), SM, C.getCurrLocationContext());
      Start =
        PathDiagnosticLocation::createOperatorLoc(B, SM);
    } else {
      os << "true";
      Start =
          PathDiagnosticLocation(B->getLHS(), SM, C.getCurrLocationContext());
      End = ExecutionContinues(C);
    }
  } else {
    assert(B->getOpcode() == BO_LOr);
    os << "||"
      << "' is ";

    if (*(Src->succ_begin() + 1) == Dst) {
      os << "false";
      Start =
          PathDiagnosticLocation(B->getLHS(), SM, C.getCurrLocationContext());
      End = ExecutionContinues(C);
    } else {
      os << "true";
      End = PathDiagnosticLocation(B->getLHS(), SM, C.getCurrLocationContext());
      Start =
        PathDiagnosticLocation::createOperatorLoc(B, SM);
    }
  }
  return std::make_shared<PathDiagnosticControlFlowPiece>(Start, End,
                                                         os.str());
}

void PathDiagnosticBuilder::generateMinimalDiagForBlockEdge(
    PathDiagnosticConstruct &C, BlockEdge BE) const {
  const SourceManager &SM = getSourceManager();
  const LocationContext *LC = C.getCurrLocationContext();
  const CFGBlock *Src = BE.getSrc();
  const CFGBlock *Dst = BE.getDst();
  const Stmt *T = Src->getTerminatorStmt();
  if (!T)
    return;

  auto Start = PathDiagnosticLocation::createBegin(T, SM, LC);
  switch (T->getStmtClass()) {
  default:
    break;

  case Stmt::GotoStmtClass:
  case Stmt::IndirectGotoStmtClass: {
    if (const Stmt *S = C.getCurrentNode()->getNextStmtForDiagnostics())
      C.getActivePath().push_front(generateDiagForGotoOP(C, S, Start));
    break;
  }

  case Stmt::SwitchStmtClass: {
    C.getActivePath().push_front(generateDiagForSwitchOP(C, Dst, Start));
    break;
  }

  case Stmt::BreakStmtClass:
  case Stmt::ContinueStmtClass: {
    std::string sbuf;
    llvm::raw_string_ostream os(sbuf);
    PathDiagnosticLocation End = ExecutionContinues(os, C);
    C.getActivePath().push_front(
        std::make_shared<PathDiagnosticControlFlowPiece>(Start, End, os.str()));
    break;
  }

  // Determine control-flow for ternary '?'.
  case Stmt::BinaryConditionalOperatorClass:
  case Stmt::ConditionalOperatorClass: {
    std::string sbuf;
    llvm::raw_string_ostream os(sbuf);
    os << "'?' condition is ";

    if (*(Src->succ_begin() + 1) == Dst)
      os << "false";
    else
      os << "true";

    PathDiagnosticLocation End = ExecutionContinues(C);

    if (const Stmt *S = End.asStmt())
      End = getEnclosingStmtLocation(S, C.getCurrLocationContext());

    C.getActivePath().push_front(
        std::make_shared<PathDiagnosticControlFlowPiece>(Start, End, os.str()));
    break;
  }

  // Determine control-flow for short-circuited '&&' and '||'.
  case Stmt::BinaryOperatorClass: {
    if (!C.supportsLogicalOpControlFlow())
      break;

    C.getActivePath().push_front(generateDiagForBinaryOP(C, T, Src, Dst));
    break;
  }

  case Stmt::DoStmtClass:
    if (*(Src->succ_begin()) == Dst) {
      std::string sbuf;
      llvm::raw_string_ostream os(sbuf);

      os << "Loop condition is true. ";
      PathDiagnosticLocation End = ExecutionContinues(os, C);

      if (const Stmt *S = End.asStmt())
        End = getEnclosingStmtLocation(S, C.getCurrLocationContext());

      C.getActivePath().push_front(
          std::make_shared<PathDiagnosticControlFlowPiece>(Start, End,
                                                           os.str()));
    } else {
      PathDiagnosticLocation End = ExecutionContinues(C);

      if (const Stmt *S = End.asStmt())
        End = getEnclosingStmtLocation(S, C.getCurrLocationContext());

      C.getActivePath().push_front(
          std::make_shared<PathDiagnosticControlFlowPiece>(
              Start, End, "Loop condition is false.  Exiting loop"));
    }
    break;

  case Stmt::WhileStmtClass:
  case Stmt::ForStmtClass:
    if (*(Src->succ_begin() + 1) == Dst) {
      std::string sbuf;
      llvm::raw_string_ostream os(sbuf);

      os << "Loop condition is false. ";
      PathDiagnosticLocation End = ExecutionContinues(os, C);
      if (const Stmt *S = End.asStmt())
        End = getEnclosingStmtLocation(S, C.getCurrLocationContext());

      C.getActivePath().push_front(
          std::make_shared<PathDiagnosticControlFlowPiece>(Start, End,
                                                           os.str()));
    } else {
      PathDiagnosticLocation End = ExecutionContinues(C);
      if (const Stmt *S = End.asStmt())
        End = getEnclosingStmtLocation(S, C.getCurrLocationContext());

      C.getActivePath().push_front(
          std::make_shared<PathDiagnosticControlFlowPiece>(
              Start, End, "Loop condition is true.  Entering loop body"));
    }

    break;

  case Stmt::IfStmtClass: {
    PathDiagnosticLocation End = ExecutionContinues(C);

    if (const Stmt *S = End.asStmt())
      End = getEnclosingStmtLocation(S, C.getCurrLocationContext());

    if (*(Src->succ_begin() + 1) == Dst)
      C.getActivePath().push_front(
          std::make_shared<PathDiagnosticControlFlowPiece>(
              Start, End, "Taking false branch"));
    else
      C.getActivePath().push_front(
          std::make_shared<PathDiagnosticControlFlowPiece>(
              Start, End, "Taking true branch"));

    break;
  }
  }
}

//===----------------------------------------------------------------------===//
// Functions for determining if a loop was executed 0 times.
//===----------------------------------------------------------------------===//

static bool isLoop(const Stmt *Term) {
  switch (Term->getStmtClass()) {
    case Stmt::ForStmtClass:
    case Stmt::WhileStmtClass:
    case Stmt::ObjCForCollectionStmtClass:
    case Stmt::CXXForRangeStmtClass:
      return true;
    default:
      // Note that we intentionally do not include do..while here.
      return false;
  }
}

static bool isJumpToFalseBranch(const BlockEdge *BE) {
  const CFGBlock *Src = BE->getSrc();
  assert(Src->succ_size() == 2);
  return (*(Src->succ_begin()+1) == BE->getDst());
}

static bool isContainedByStmt(const ParentMap &PM, const Stmt *S,
                              const Stmt *SubS) {
  while (SubS) {
    if (SubS == S)
      return true;
    SubS = PM.getParent(SubS);
  }
  return false;
}

static const Stmt *getStmtBeforeCond(const ParentMap &PM, const Stmt *Term,
                                     const ExplodedNode *N) {
  while (N) {
    Optional<StmtPoint> SP = N->getLocation().getAs<StmtPoint>();
    if (SP) {
      const Stmt *S = SP->getStmt();
      if (!isContainedByStmt(PM, Term, S))
        return S;
    }
    N = N->getFirstPred();
  }
  return nullptr;
}

static bool isInLoopBody(const ParentMap &PM, const Stmt *S, const Stmt *Term) {
  const Stmt *LoopBody = nullptr;
  switch (Term->getStmtClass()) {
    case Stmt::CXXForRangeStmtClass: {
      const auto *FR = cast<CXXForRangeStmt>(Term);
      if (isContainedByStmt(PM, FR->getInc(), S))
        return true;
      if (isContainedByStmt(PM, FR->getLoopVarStmt(), S))
        return true;
      LoopBody = FR->getBody();
      break;
    }
    case Stmt::ForStmtClass: {
      const auto *FS = cast<ForStmt>(Term);
      if (isContainedByStmt(PM, FS->getInc(), S))
        return true;
      LoopBody = FS->getBody();
      break;
    }
    case Stmt::ObjCForCollectionStmtClass: {
      const auto *FC = cast<ObjCForCollectionStmt>(Term);
      LoopBody = FC->getBody();
      break;
    }
    case Stmt::WhileStmtClass:
      LoopBody = cast<WhileStmt>(Term)->getBody();
      break;
    default:
      return false;
  }
  return isContainedByStmt(PM, LoopBody, S);
}

/// Adds a sanitized control-flow diagnostic edge to a path.
static void addEdgeToPath(PathPieces &path,
                          PathDiagnosticLocation &PrevLoc,
                          PathDiagnosticLocation NewLoc) {
  if (!NewLoc.isValid())
    return;

  SourceLocation NewLocL = NewLoc.asLocation();
  if (NewLocL.isInvalid())
    return;

  if (!PrevLoc.isValid() || !PrevLoc.asLocation().isValid()) {
    PrevLoc = NewLoc;
    return;
  }

  // Ignore self-edges, which occur when there are multiple nodes at the same
  // statement.
  if (NewLoc.asStmt() && NewLoc.asStmt() == PrevLoc.asStmt())
    return;

  path.push_front(
      std::make_shared<PathDiagnosticControlFlowPiece>(NewLoc, PrevLoc));
  PrevLoc = NewLoc;
}

/// A customized wrapper for CFGBlock::getTerminatorCondition()
/// which returns the element for ObjCForCollectionStmts.
static const Stmt *getTerminatorCondition(const CFGBlock *B) {
  const Stmt *S = B->getTerminatorCondition();
  if (const auto *FS = dyn_cast_or_null<ObjCForCollectionStmt>(S))
    return FS->getElement();
  return S;
}

constexpr llvm::StringLiteral StrEnteringLoop = "Entering loop body";
constexpr llvm::StringLiteral StrLoopBodyZero = "Loop body executed 0 times";
constexpr llvm::StringLiteral StrLoopRangeEmpty =
    "Loop body skipped when range is empty";
constexpr llvm::StringLiteral StrLoopCollectionEmpty =
    "Loop body skipped when collection is empty";

static std::unique_ptr<FilesToLineNumsMap>
findExecutedLines(const SourceManager &SM, const ExplodedNode *N);

void PathDiagnosticBuilder::generatePathDiagnosticsForNode(
    PathDiagnosticConstruct &C, PathDiagnosticLocation &PrevLoc) const {
  ProgramPoint P = C.getCurrentNode()->getLocation();
  const SourceManager &SM = getSourceManager();

  // Have we encountered an entrance to a call?  It may be
  // the case that we have not encountered a matching
  // call exit before this point.  This means that the path
  // terminated within the call itself.
  if (auto CE = P.getAs<CallEnter>()) {

    if (C.shouldAddPathEdges()) {
      // Add an edge to the start of the function.
      const StackFrameContext *CalleeLC = CE->getCalleeContext();
      const Decl *D = CalleeLC->getDecl();
      // Add the edge only when the callee has body. We jump to the beginning
      // of the *declaration*, however we expect it to be followed by the
      // body. This isn't the case for autosynthesized property accessors in
      // Objective-C. No need for a similar extra check for CallExit points
      // because the exit edge comes from a statement (i.e. return),
      // not from declaration.
      if (D->hasBody())
        addEdgeToPath(C.getActivePath(), PrevLoc,
                      PathDiagnosticLocation::createBegin(D, SM));
    }

    // Did we visit an entire call?
    bool VisitedEntireCall = C.PD->isWithinCall();
    C.PD->popActivePath();

    PathDiagnosticCallPiece *Call;
    if (VisitedEntireCall) {
      Call = cast<PathDiagnosticCallPiece>(C.getActivePath().front().get());
    } else {
      // The path terminated within a nested location context, create a new
      // call piece to encapsulate the rest of the path pieces.
      const Decl *Caller = CE->getLocationContext()->getDecl();
      Call = PathDiagnosticCallPiece::construct(C.getActivePath(), Caller);
      assert(C.getActivePath().size() == 1 &&
             C.getActivePath().front().get() == Call);

      // Since we just transferred the path over to the call piece, reset the
      // mapping of the active path to the current location context.
      assert(C.isInLocCtxMap(&C.getActivePath()) &&
             "When we ascend to a previously unvisited call, the active path's "
             "address shouldn't change, but rather should be compacted into "
             "a single CallEvent!");
      C.updateLocCtxMap(&C.getActivePath(), C.getCurrLocationContext());

      // Record the location context mapping for the path within the call.
      assert(!C.isInLocCtxMap(&Call->path) &&
             "When we ascend to a previously unvisited call, this must be the "
             "first time we encounter the caller context!");
      C.updateLocCtxMap(&Call->path, CE->getCalleeContext());
    }
    Call->setCallee(*CE, SM);

    // Update the previous location in the active path.
    PrevLoc = Call->getLocation();

    if (!C.CallStack.empty()) {
      assert(C.CallStack.back().first == Call);
      C.CallStack.pop_back();
    }
    return;
  }

  assert(C.getCurrLocationContext() == C.getLocationContextForActivePath() &&
         "The current position in the bug path is out of sync with the "
         "location context associated with the active path!");

  // Have we encountered an exit from a function call?
  if (Optional<CallExitEnd> CE = P.getAs<CallExitEnd>()) {

    // We are descending into a call (backwards).  Construct
    // a new call piece to contain the path pieces for that call.
    auto Call = PathDiagnosticCallPiece::construct(*CE, SM);
    // Record the mapping from call piece to LocationContext.
    assert(!C.isInLocCtxMap(&Call->path) &&
           "We just entered a call, this must've been the first time we "
           "encounter its context!");
    C.updateLocCtxMap(&Call->path, CE->getCalleeContext());

    if (C.shouldAddPathEdges()) {
      // Add the edge to the return site.
      addEdgeToPath(C.getActivePath(), PrevLoc, Call->callReturn);
      PrevLoc.invalidate();
    }

    auto *P = Call.get();
    C.getActivePath().push_front(std::move(Call));

    // Make the contents of the call the active path for now.
    C.PD->pushActivePath(&P->path);
    C.CallStack.push_back(CallWithEntry(P, C.getCurrentNode()));
    return;
  }

  if (auto PS = P.getAs<PostStmt>()) {
    if (!C.shouldAddPathEdges())
      return;

    // Add an edge.  If this is an ObjCForCollectionStmt do
    // not add an edge here as it appears in the CFG both
    // as a terminator and as a terminator condition.
    if (!isa<ObjCForCollectionStmt>(PS->getStmt())) {
      PathDiagnosticLocation L =
          PathDiagnosticLocation(PS->getStmt(), SM, C.getCurrLocationContext());
      addEdgeToPath(C.getActivePath(), PrevLoc, L);
    }

  } else if (auto BE = P.getAs<BlockEdge>()) {

    if (!C.shouldAddPathEdges()) {
      generateMinimalDiagForBlockEdge(C, *BE);
      return;
    }

    // Are we jumping to the head of a loop?  Add a special diagnostic.
    if (const Stmt *Loop = BE->getSrc()->getLoopTarget()) {
      PathDiagnosticLocation L(Loop, SM, C.getCurrLocationContext());
      const Stmt *Body = nullptr;

      if (const auto *FS = dyn_cast<ForStmt>(Loop))
        Body = FS->getBody();
      else if (const auto *WS = dyn_cast<WhileStmt>(Loop))
        Body = WS->getBody();
      else if (const auto *OFS = dyn_cast<ObjCForCollectionStmt>(Loop)) {
        Body = OFS->getBody();
      } else if (const auto *FRS = dyn_cast<CXXForRangeStmt>(Loop)) {
        Body = FRS->getBody();
      }
      // do-while statements are explicitly excluded here

      auto p = std::make_shared<PathDiagnosticEventPiece>(
          L, "Looping back to the head "
          "of the loop");
      p->setPrunable(true);

      addEdgeToPath(C.getActivePath(), PrevLoc, p->getLocation());
      C.getActivePath().push_front(std::move(p));

      if (const auto *CS = dyn_cast_or_null<CompoundStmt>(Body)) {
        addEdgeToPath(C.getActivePath(), PrevLoc,
                      PathDiagnosticLocation::createEndBrace(CS, SM));
      }
    }

    const CFGBlock *BSrc = BE->getSrc();
    const ParentMap &PM = C.getParentMap();

    if (const Stmt *Term = BSrc->getTerminatorStmt()) {
      // Are we jumping past the loop body without ever executing the
      // loop (because the condition was false)?
      if (isLoop(Term)) {
        const Stmt *TermCond = getTerminatorCondition(BSrc);
        bool IsInLoopBody = isInLoopBody(
            PM, getStmtBeforeCond(PM, TermCond, C.getCurrentNode()), Term);

        StringRef str;

        if (isJumpToFalseBranch(&*BE)) {
          if (!IsInLoopBody) {
            if (isa<ObjCForCollectionStmt>(Term)) {
              str = StrLoopCollectionEmpty;
            } else if (isa<CXXForRangeStmt>(Term)) {
              str = StrLoopRangeEmpty;
            } else {
              str = StrLoopBodyZero;
            }
          }
        } else {
          str = StrEnteringLoop;
        }

        if (!str.empty()) {
          PathDiagnosticLocation L(TermCond ? TermCond : Term, SM,
                                   C.getCurrLocationContext());
          auto PE = std::make_shared<PathDiagnosticEventPiece>(L, str);
          PE->setPrunable(true);
          addEdgeToPath(C.getActivePath(), PrevLoc, PE->getLocation());
          C.getActivePath().push_front(std::move(PE));
        }
      } else if (isa<BreakStmt>(Term) || isa<ContinueStmt>(Term) ||
          isa<GotoStmt>(Term)) {
        PathDiagnosticLocation L(Term, SM, C.getCurrLocationContext());
        addEdgeToPath(C.getActivePath(), PrevLoc, L);
      }
    }
  }
}

static std::unique_ptr<PathDiagnostic>
generateDiagnosticForBasicReport(const BasicBugReport *R) {
  const BugType &BT = R->getBugType();
  return std::make_unique<PathDiagnostic>(
      BT.getCheckerName(), R->getDeclWithIssue(), BT.getDescription(),
      R->getDescription(), R->getShortDescription(/*UseFallback=*/false),
      BT.getCategory(), R->getUniqueingLocation(), R->getUniqueingDecl(),
      std::make_unique<FilesToLineNumsMap>());
}

static std::unique_ptr<PathDiagnostic>
generateEmptyDiagnosticForReport(const PathSensitiveBugReport *R,
                                 const SourceManager &SM) {
  const BugType &BT = R->getBugType();
  return std::make_unique<PathDiagnostic>(
      BT.getCheckerName(), R->getDeclWithIssue(), BT.getDescription(),
      R->getDescription(), R->getShortDescription(/*UseFallback=*/false),
      BT.getCategory(), R->getUniqueingLocation(), R->getUniqueingDecl(),
      findExecutedLines(SM, R->getErrorNode()));
}

static const Stmt *getStmtParent(const Stmt *S, const ParentMap &PM) {
  if (!S)
    return nullptr;

  while (true) {
    S = PM.getParentIgnoreParens(S);

    if (!S)
      break;

    if (isa<FullExpr>(S) ||
        isa<CXXBindTemporaryExpr>(S) ||
        isa<SubstNonTypeTemplateParmExpr>(S))
      continue;

    break;
  }

  return S;
}

static bool isConditionForTerminator(const Stmt *S, const Stmt *Cond) {
  switch (S->getStmtClass()) {
    case Stmt::BinaryOperatorClass: {
      const auto *BO = cast<BinaryOperator>(S);
      if (!BO->isLogicalOp())
        return false;
      return BO->getLHS() == Cond || BO->getRHS() == Cond;
    }
    case Stmt::IfStmtClass:
      return cast<IfStmt>(S)->getCond() == Cond;
    case Stmt::ForStmtClass:
      return cast<ForStmt>(S)->getCond() == Cond;
    case Stmt::WhileStmtClass:
      return cast<WhileStmt>(S)->getCond() == Cond;
    case Stmt::DoStmtClass:
      return cast<DoStmt>(S)->getCond() == Cond;
    case Stmt::ChooseExprClass:
      return cast<ChooseExpr>(S)->getCond() == Cond;
    case Stmt::IndirectGotoStmtClass:
      return cast<IndirectGotoStmt>(S)->getTarget() == Cond;
    case Stmt::SwitchStmtClass:
      return cast<SwitchStmt>(S)->getCond() == Cond;
    case Stmt::BinaryConditionalOperatorClass:
      return cast<BinaryConditionalOperator>(S)->getCond() == Cond;
    case Stmt::ConditionalOperatorClass: {
      const auto *CO = cast<ConditionalOperator>(S);
      return CO->getCond() == Cond ||
             CO->getLHS() == Cond ||
             CO->getRHS() == Cond;
    }
    case Stmt::ObjCForCollectionStmtClass:
      return cast<ObjCForCollectionStmt>(S)->getElement() == Cond;
    case Stmt::CXXForRangeStmtClass: {
      const auto *FRS = cast<CXXForRangeStmt>(S);
      return FRS->getCond() == Cond || FRS->getRangeInit() == Cond;
    }
    default:
      return false;
  }
}

static bool isIncrementOrInitInForLoop(const Stmt *S, const Stmt *FL) {
  if (const auto *FS = dyn_cast<ForStmt>(FL))
    return FS->getInc() == S || FS->getInit() == S;
  if (const auto *FRS = dyn_cast<CXXForRangeStmt>(FL))
    return FRS->getInc() == S || FRS->getRangeStmt() == S ||
           FRS->getLoopVarStmt() || FRS->getRangeInit() == S;
  return false;
}

using OptimizedCallsSet = llvm::DenseSet<const PathDiagnosticCallPiece *>;

/// Adds synthetic edges from top-level statements to their subexpressions.
///
/// This avoids a "swoosh" effect, where an edge from a top-level statement A
/// points to a sub-expression B.1 that's not at the start of B. In these cases,
/// we'd like to see an edge from A to B, then another one from B to B.1.
static void addContextEdges(PathPieces &pieces, const LocationContext *LC) {
  const ParentMap &PM = LC->getParentMap();
  PathPieces::iterator Prev = pieces.end();
  for (PathPieces::iterator I = pieces.begin(), E = Prev; I != E;
       Prev = I, ++I) {
    auto *Piece = dyn_cast<PathDiagnosticControlFlowPiece>(I->get());

    if (!Piece)
      continue;

    PathDiagnosticLocation SrcLoc = Piece->getStartLocation();
    SmallVector<PathDiagnosticLocation, 4> SrcContexts;

    PathDiagnosticLocation NextSrcContext = SrcLoc;
    const Stmt *InnerStmt = nullptr;
    while (NextSrcContext.isValid() && NextSrcContext.asStmt() != InnerStmt) {
      SrcContexts.push_back(NextSrcContext);
      InnerStmt = NextSrcContext.asStmt();
      NextSrcContext = getEnclosingStmtLocation(InnerStmt, LC,
                                                /*allowNested=*/true);
    }

    // Repeatedly split the edge as necessary.
    // This is important for nested logical expressions (||, &&, ?:) where we
    // want to show all the levels of context.
    while (true) {
      const Stmt *Dst = Piece->getEndLocation().getStmtOrNull();

      // We are looking at an edge. Is the destination within a larger
      // expression?
      PathDiagnosticLocation DstContext =
          getEnclosingStmtLocation(Dst, LC, /*allowNested=*/true);
      if (!DstContext.isValid() || DstContext.asStmt() == Dst)
        break;

      // If the source is in the same context, we're already good.
      if (llvm::find(SrcContexts, DstContext) != SrcContexts.end())
        break;

      // Update the subexpression node to point to the context edge.
      Piece->setStartLocation(DstContext);

      // Try to extend the previous edge if it's at the same level as the source
      // context.
      if (Prev != E) {
        auto *PrevPiece = dyn_cast<PathDiagnosticControlFlowPiece>(Prev->get());

        if (PrevPiece) {
          if (const Stmt *PrevSrc =
                  PrevPiece->getStartLocation().getStmtOrNull()) {
            const Stmt *PrevSrcParent = getStmtParent(PrevSrc, PM);
            if (PrevSrcParent ==
                getStmtParent(DstContext.getStmtOrNull(), PM)) {
              PrevPiece->setEndLocation(DstContext);
              break;
            }
          }
        }
      }

      // Otherwise, split the current edge into a context edge and a
      // subexpression edge. Note that the context statement may itself have
      // context.
      auto P =
          std::make_shared<PathDiagnosticControlFlowPiece>(SrcLoc, DstContext);
      Piece = P.get();
      I = pieces.insert(I, std::move(P));
    }
  }
}

/// Move edges from a branch condition to a branch target
///        when the condition is simple.
///
/// This restructures some of the work of addContextEdges.  That function
/// creates edges this may destroy, but they work together to create a more
/// aesthetically set of edges around branches.  After the call to
/// addContextEdges, we may have (1) an edge to the branch, (2) an edge from
/// the branch to the branch condition, and (3) an edge from the branch
/// condition to the branch target.  We keep (1), but may wish to remove (2)
/// and move the source of (3) to the branch if the branch condition is simple.
static void simplifySimpleBranches(PathPieces &pieces) {
  for (PathPieces::iterator I = pieces.begin(), E = pieces.end(); I != E; ++I) {
    const auto *PieceI = dyn_cast<PathDiagnosticControlFlowPiece>(I->get());

    if (!PieceI)
      continue;

    const Stmt *s1Start = PieceI->getStartLocation().getStmtOrNull();
    const Stmt *s1End   = PieceI->getEndLocation().getStmtOrNull();

    if (!s1Start || !s1End)
      continue;

    PathPieces::iterator NextI = I; ++NextI;
    if (NextI == E)
      break;

    PathDiagnosticControlFlowPiece *PieceNextI = nullptr;

    while (true) {
      if (NextI == E)
        break;

      const auto *EV = dyn_cast<PathDiagnosticEventPiece>(NextI->get());
      if (EV) {
        StringRef S = EV->getString();
        if (S == StrEnteringLoop || S == StrLoopBodyZero ||
            S == StrLoopCollectionEmpty || S == StrLoopRangeEmpty) {
          ++NextI;
          continue;
        }
        break;
      }

      PieceNextI = dyn_cast<PathDiagnosticControlFlowPiece>(NextI->get());
      break;
    }

    if (!PieceNextI)
      continue;

    const Stmt *s2Start = PieceNextI->getStartLocation().getStmtOrNull();
    const Stmt *s2End   = PieceNextI->getEndLocation().getStmtOrNull();

    if (!s2Start || !s2End || s1End != s2Start)
      continue;

    // We only perform this transformation for specific branch kinds.
    // We don't want to do this for do..while, for example.
    if (!(isa<ForStmt>(s1Start) || isa<WhileStmt>(s1Start) ||
          isa<IfStmt>(s1Start) || isa<ObjCForCollectionStmt>(s1Start) ||
          isa<CXXForRangeStmt>(s1Start)))
      continue;

    // Is s1End the branch condition?
    if (!isConditionForTerminator(s1Start, s1End))
      continue;

    // Perform the hoisting by eliminating (2) and changing the start
    // location of (3).
    PieceNextI->setStartLocation(PieceI->getStartLocation());
    I = pieces.erase(I);
  }
}

/// Returns the number of bytes in the given (character-based) SourceRange.
///
/// If the locations in the range are not on the same line, returns None.
///
/// Note that this does not do a precise user-visible character or column count.
static Optional<size_t> getLengthOnSingleLine(const SourceManager &SM,
                                              SourceRange Range) {
  SourceRange ExpansionRange(SM.getExpansionLoc(Range.getBegin()),
                             SM.getExpansionRange(Range.getEnd()).getEnd());

  FileID FID = SM.getFileID(ExpansionRange.getBegin());
  if (FID != SM.getFileID(ExpansionRange.getEnd()))
    return None;

  bool Invalid;
  const llvm::MemoryBuffer *Buffer = SM.getBuffer(FID, &Invalid);
  if (Invalid)
    return None;

  unsigned BeginOffset = SM.getFileOffset(ExpansionRange.getBegin());
  unsigned EndOffset = SM.getFileOffset(ExpansionRange.getEnd());
  StringRef Snippet = Buffer->getBuffer().slice(BeginOffset, EndOffset);

  // We're searching the raw bytes of the buffer here, which might include
  // escaped newlines and such. That's okay; we're trying to decide whether the
  // SourceRange is covering a large or small amount of space in the user's
  // editor.
  if (Snippet.find_first_of("\r\n") != StringRef::npos)
    return None;

  // This isn't Unicode-aware, but it doesn't need to be.
  return Snippet.size();
}

/// \sa getLengthOnSingleLine(SourceManager, SourceRange)
static Optional<size_t> getLengthOnSingleLine(const SourceManager &SM,
                                              const Stmt *S) {
  return getLengthOnSingleLine(SM, S->getSourceRange());
}

/// Eliminate two-edge cycles created by addContextEdges().
///
/// Once all the context edges are in place, there are plenty of cases where
/// there's a single edge from a top-level statement to a subexpression,
/// followed by a single path note, and then a reverse edge to get back out to
/// the top level. If the statement is simple enough, the subexpression edges
/// just add noise and make it harder to understand what's going on.
///
/// This function only removes edges in pairs, because removing only one edge
/// might leave other edges dangling.
///
/// This will not remove edges in more complicated situations:
/// - if there is more than one "hop" leading to or from a subexpression.
/// - if there is an inlined call between the edges instead of a single event.
/// - if the whole statement is large enough that having subexpression arrows
///   might be helpful.
static void removeContextCycles(PathPieces &Path, const SourceManager &SM) {
  for (PathPieces::iterator I = Path.begin(), E = Path.end(); I != E; ) {
    // Pattern match the current piece and its successor.
    const auto *PieceI = dyn_cast<PathDiagnosticControlFlowPiece>(I->get());

    if (!PieceI) {
      ++I;
      continue;
    }

    const Stmt *s1Start = PieceI->getStartLocation().getStmtOrNull();
    const Stmt *s1End   = PieceI->getEndLocation().getStmtOrNull();

    PathPieces::iterator NextI = I; ++NextI;
    if (NextI == E)
      break;

    const auto *PieceNextI =
        dyn_cast<PathDiagnosticControlFlowPiece>(NextI->get());

    if (!PieceNextI) {
      if (isa<PathDiagnosticEventPiece>(NextI->get())) {
        ++NextI;
        if (NextI == E)
          break;
        PieceNextI = dyn_cast<PathDiagnosticControlFlowPiece>(NextI->get());
      }

      if (!PieceNextI) {
        ++I;
        continue;
      }
    }

    const Stmt *s2Start = PieceNextI->getStartLocation().getStmtOrNull();
    const Stmt *s2End   = PieceNextI->getEndLocation().getStmtOrNull();

    if (s1Start && s2Start && s1Start == s2End && s2Start == s1End) {
      const size_t MAX_SHORT_LINE_LENGTH = 80;
      Optional<size_t> s1Length = getLengthOnSingleLine(SM, s1Start);
      if (s1Length && *s1Length <= MAX_SHORT_LINE_LENGTH) {
        Optional<size_t> s2Length = getLengthOnSingleLine(SM, s2Start);
        if (s2Length && *s2Length <= MAX_SHORT_LINE_LENGTH) {
          Path.erase(I);
          I = Path.erase(NextI);
          continue;
        }
      }
    }

    ++I;
  }
}

/// Return true if X is contained by Y.
static bool lexicalContains(const ParentMap &PM, const Stmt *X, const Stmt *Y) {
  while (X) {
    if (X == Y)
      return true;
    X = PM.getParent(X);
  }
  return false;
}

// Remove short edges on the same line less than 3 columns in difference.
static void removePunyEdges(PathPieces &path, const SourceManager &SM,
                            const ParentMap &PM) {
  bool erased = false;

  for (PathPieces::iterator I = path.begin(), E = path.end(); I != E;
       erased ? I : ++I) {
    erased = false;

    const auto *PieceI = dyn_cast<PathDiagnosticControlFlowPiece>(I->get());

    if (!PieceI)
      continue;

    const Stmt *start = PieceI->getStartLocation().getStmtOrNull();
    const Stmt *end   = PieceI->getEndLocation().getStmtOrNull();

    if (!start || !end)
      continue;

    const Stmt *endParent = PM.getParent(end);
    if (!endParent)
      continue;

    if (isConditionForTerminator(end, endParent))
      continue;

    SourceLocation FirstLoc = start->getBeginLoc();
    SourceLocation SecondLoc = end->getBeginLoc();

    if (!SM.isWrittenInSameFile(FirstLoc, SecondLoc))
      continue;
    if (SM.isBeforeInTranslationUnit(SecondLoc, FirstLoc))
      std::swap(SecondLoc, FirstLoc);

    SourceRange EdgeRange(FirstLoc, SecondLoc);
    Optional<size_t> ByteWidth = getLengthOnSingleLine(SM, EdgeRange);

    // If the statements are on different lines, continue.
    if (!ByteWidth)
      continue;

    const size_t MAX_PUNY_EDGE_LENGTH = 2;
    if (*ByteWidth <= MAX_PUNY_EDGE_LENGTH) {
      // FIXME: There are enough /bytes/ between the endpoints of the edge, but
      // there might not be enough /columns/. A proper user-visible column count
      // is probably too expensive, though.
      I = path.erase(I);
      erased = true;
      continue;
    }
  }
}

static void removeIdenticalEvents(PathPieces &path) {
  for (PathPieces::iterator I = path.begin(), E = path.end(); I != E; ++I) {
    const auto *PieceI = dyn_cast<PathDiagnosticEventPiece>(I->get());

    if (!PieceI)
      continue;

    PathPieces::iterator NextI = I; ++NextI;
    if (NextI == E)
      return;

    const auto *PieceNextI = dyn_cast<PathDiagnosticEventPiece>(NextI->get());

    if (!PieceNextI)
      continue;

    // Erase the second piece if it has the same exact message text.
    if (PieceI->getString() == PieceNextI->getString()) {
      path.erase(NextI);
    }
  }
}

static bool optimizeEdges(const PathDiagnosticConstruct &C, PathPieces &path,
                          OptimizedCallsSet &OCS) {
  bool hasChanges = false;
  const LocationContext *LC = C.getLocationContextFor(&path);
  assert(LC);
  const ParentMap &PM = LC->getParentMap();
  const SourceManager &SM = C.getSourceManager();

  for (PathPieces::iterator I = path.begin(), E = path.end(); I != E; ) {
    // Optimize subpaths.
    if (auto *CallI = dyn_cast<PathDiagnosticCallPiece>(I->get())) {
      // Record the fact that a call has been optimized so we only do the
      // effort once.
      if (!OCS.count(CallI)) {
        while (optimizeEdges(C, CallI->path, OCS)) {
        }
        OCS.insert(CallI);
      }
      ++I;
      continue;
    }

    // Pattern match the current piece and its successor.
    auto *PieceI = dyn_cast<PathDiagnosticControlFlowPiece>(I->get());

    if (!PieceI) {
      ++I;
      continue;
    }

    const Stmt *s1Start = PieceI->getStartLocation().getStmtOrNull();
    const Stmt *s1End   = PieceI->getEndLocation().getStmtOrNull();
    const Stmt *level1 = getStmtParent(s1Start, PM);
    const Stmt *level2 = getStmtParent(s1End, PM);

    PathPieces::iterator NextI = I; ++NextI;
    if (NextI == E)
      break;

    const auto *PieceNextI = dyn_cast<PathDiagnosticControlFlowPiece>(NextI->get());

    if (!PieceNextI) {
      ++I;
      continue;
    }

    const Stmt *s2Start = PieceNextI->getStartLocation().getStmtOrNull();
    const Stmt *s2End   = PieceNextI->getEndLocation().getStmtOrNull();
    const Stmt *level3 = getStmtParent(s2Start, PM);
    const Stmt *level4 = getStmtParent(s2End, PM);

    // Rule I.
    //
    // If we have two consecutive control edges whose end/begin locations
    // are at the same level (e.g. statements or top-level expressions within
    // a compound statement, or siblings share a single ancestor expression),
    // then merge them if they have no interesting intermediate event.
    //
    // For example:
    //
    // (1.1 -> 1.2) -> (1.2 -> 1.3) becomes (1.1 -> 1.3) because the common
    // parent is '1'.  Here 'x.y.z' represents the hierarchy of statements.
    //
    // NOTE: this will be limited later in cases where we add barriers
    // to prevent this optimization.
    if (level1 && level1 == level2 && level1 == level3 && level1 == level4) {
      PieceI->setEndLocation(PieceNextI->getEndLocation());
      path.erase(NextI);
      hasChanges = true;
      continue;
    }

    // Rule II.
    //
    // Eliminate edges between subexpressions and parent expressions
    // when the subexpression is consumed.
    //
    // NOTE: this will be limited later in cases where we add barriers
    // to prevent this optimization.
    if (s1End && s1End == s2Start && level2) {
      bool removeEdge = false;
      // Remove edges into the increment or initialization of a
      // loop that have no interleaving event.  This means that
      // they aren't interesting.
      if (isIncrementOrInitInForLoop(s1End, level2))
        removeEdge = true;
      // Next only consider edges that are not anchored on
      // the condition of a terminator.  This are intermediate edges
      // that we might want to trim.
      else if (!isConditionForTerminator(level2, s1End)) {
        // Trim edges on expressions that are consumed by
        // the parent expression.
        if (isa<Expr>(s1End) && PM.isConsumedExpr(cast<Expr>(s1End))) {
          removeEdge = true;
        }
        // Trim edges where a lexical containment doesn't exist.
        // For example:
        //
        //  X -> Y -> Z
        //
        // If 'Z' lexically contains Y (it is an ancestor) and
        // 'X' does not lexically contain Y (it is a descendant OR
        // it has no lexical relationship at all) then trim.
        //
        // This can eliminate edges where we dive into a subexpression
        // and then pop back out, etc.
        else if (s1Start && s2End &&
                 lexicalContains(PM, s2Start, s2End) &&
                 !lexicalContains(PM, s1End, s1Start)) {
          removeEdge = true;
        }
        // Trim edges from a subexpression back to the top level if the
        // subexpression is on a different line.
        //
        // A.1 -> A -> B
        // becomes
        // A.1 -> B
        //
        // These edges just look ugly and don't usually add anything.
        else if (s1Start && s2End &&
                 lexicalContains(PM, s1Start, s1End)) {
          SourceRange EdgeRange(PieceI->getEndLocation().asLocation(),
                                PieceI->getStartLocation().asLocation());
          if (!getLengthOnSingleLine(SM, EdgeRange).hasValue())
            removeEdge = true;
        }
      }

      if (removeEdge) {
        PieceI->setEndLocation(PieceNextI->getEndLocation());
        path.erase(NextI);
        hasChanges = true;
        continue;
      }
    }

    // Optimize edges for ObjC fast-enumeration loops.
    //
    // (X -> collection) -> (collection -> element)
    //
    // becomes:
    //
    // (X -> element)
    if (s1End == s2Start) {
      const auto *FS = dyn_cast_or_null<ObjCForCollectionStmt>(level3);
      if (FS && FS->getCollection()->IgnoreParens() == s2Start &&
          s2End == FS->getElement()) {
        PieceI->setEndLocation(PieceNextI->getEndLocation());
        path.erase(NextI);
        hasChanges = true;
        continue;
      }
    }

    // No changes at this index?  Move to the next one.
    ++I;
  }

  if (!hasChanges) {
    // Adjust edges into subexpressions to make them more uniform
    // and aesthetically pleasing.
    addContextEdges(path, LC);
    // Remove "cyclical" edges that include one or more context edges.
    removeContextCycles(path, SM);
    // Hoist edges originating from branch conditions to branches
    // for simple branches.
    simplifySimpleBranches(path);
    // Remove any puny edges left over after primary optimization pass.
    removePunyEdges(path, SM, PM);
    // Remove identical events.
    removeIdenticalEvents(path);
  }

  return hasChanges;
}

/// Drop the very first edge in a path, which should be a function entry edge.
///
/// If the first edge is not a function entry edge (say, because the first
/// statement had an invalid source location), this function does nothing.
// FIXME: We should just generate invalid edges anyway and have the optimizer
// deal with them.
static void dropFunctionEntryEdge(const PathDiagnosticConstruct &C,
                                  PathPieces &Path) {
  const auto *FirstEdge =
      dyn_cast<PathDiagnosticControlFlowPiece>(Path.front().get());
  if (!FirstEdge)
    return;

  const Decl *D = C.getLocationContextFor(&Path)->getDecl();
  PathDiagnosticLocation EntryLoc =
      PathDiagnosticLocation::createBegin(D, C.getSourceManager());
  if (FirstEdge->getStartLocation() != EntryLoc)
    return;

  Path.pop_front();
}

/// Populate executes lines with lines containing at least one diagnostics.
static void updateExecutedLinesWithDiagnosticPieces(PathDiagnostic &PD) {

  PathPieces path = PD.path.flatten(/*ShouldFlattenMacros=*/true);
  FilesToLineNumsMap &ExecutedLines = PD.getExecutedLines();

  for (const auto &P : path) {
    FullSourceLoc Loc = P->getLocation().asLocation().getExpansionLoc();
    FileID FID = Loc.getFileID();
    unsigned LineNo = Loc.getLineNumber();
    assert(FID.isValid());
    ExecutedLines[FID].insert(LineNo);
  }
}

PathDiagnosticConstruct::PathDiagnosticConstruct(
    const PathDiagnosticConsumer *PDC, const ExplodedNode *ErrorNode,
    const PathSensitiveBugReport *R)
    : Consumer(PDC), CurrentNode(ErrorNode),
      SM(CurrentNode->getCodeDecl().getASTContext().getSourceManager()),
      PD(generateEmptyDiagnosticForReport(R, getSourceManager())) {
  LCM[&PD->getActivePath()] = ErrorNode->getLocationContext();
}

PathDiagnosticBuilder::PathDiagnosticBuilder(
    BugReporterContext BRC, std::unique_ptr<ExplodedGraph> BugPath,
    PathSensitiveBugReport *r, const ExplodedNode *ErrorNode,
    std::unique_ptr<VisitorsDiagnosticsTy> VisitorsDiagnostics)
    : BugReporterContext(BRC), BugPath(std::move(BugPath)), R(r),
      ErrorNode(ErrorNode),
      VisitorsDiagnostics(std::move(VisitorsDiagnostics)) {}

std::unique_ptr<PathDiagnostic>
PathDiagnosticBuilder::generate(const PathDiagnosticConsumer *PDC) const {
  PathDiagnosticConstruct Construct(PDC, ErrorNode, R);

  const SourceManager &SM = getSourceManager();
  const AnalyzerOptions &Opts = getAnalyzerOptions();
  StringRef ErrorTag = ErrorNode->getLocation().getTag()->getTagDescription();

  // See whether we need to silence the checker/package.
  // FIXME: This will not work if the report was emitted with an incorrect tag.
  for (const std::string &CheckerOrPackage : Opts.SilencedCheckersAndPackages) {
    if (ErrorTag.startswith(CheckerOrPackage))
      return nullptr;
  }

  if (!PDC->shouldGenerateDiagnostics())
    return generateEmptyDiagnosticForReport(R, getSourceManager());

  // Construct the final (warning) event for the bug report.
  auto EndNotes = VisitorsDiagnostics->find(ErrorNode);
  PathDiagnosticPieceRef LastPiece;
  if (EndNotes != VisitorsDiagnostics->end()) {
    assert(!EndNotes->second.empty());
    LastPiece = EndNotes->second[0];
  } else {
    LastPiece = BugReporterVisitor::getDefaultEndPath(*this, ErrorNode,
                                                      *getBugReport());
  }
  Construct.PD->setEndOfPath(LastPiece);

  PathDiagnosticLocation PrevLoc = Construct.PD->getLocation();
  // From the error node to the root, ascend the bug path and construct the bug
  // report.
  while (Construct.ascendToPrevNode()) {
    generatePathDiagnosticsForNode(Construct, PrevLoc);

    auto VisitorNotes = VisitorsDiagnostics->find(Construct.getCurrentNode());
    if (VisitorNotes == VisitorsDiagnostics->end())
      continue;

    // This is a workaround due to inability to put shared PathDiagnosticPiece
    // into a FoldingSet.
    std::set<llvm::FoldingSetNodeID> DeduplicationSet;

    // Add pieces from custom visitors.
    for (const PathDiagnosticPieceRef &Note : VisitorNotes->second) {
      llvm::FoldingSetNodeID ID;
      Note->Profile(ID);
      if (!DeduplicationSet.insert(ID).second)
        continue;

      if (PDC->shouldAddPathEdges())
        addEdgeToPath(Construct.getActivePath(), PrevLoc, Note->getLocation());
      updateStackPiecesWithMessage(Note, Construct.CallStack);
      Construct.getActivePath().push_front(Note);
    }
  }

  if (PDC->shouldAddPathEdges()) {
    // Add an edge to the start of the function.
    // We'll prune it out later, but it helps make diagnostics more uniform.
    const StackFrameContext *CalleeLC =
        Construct.getLocationContextForActivePath()->getStackFrame();
    const Decl *D = CalleeLC->getDecl();
    addEdgeToPath(Construct.getActivePath(), PrevLoc,
                  PathDiagnosticLocation::createBegin(D, SM));
  }


  // Finally, prune the diagnostic path of uninteresting stuff.
  if (!Construct.PD->path.empty()) {
    if (R->shouldPrunePath() && Opts.ShouldPrunePaths) {
      bool stillHasNotes =
          removeUnneededCalls(Construct, Construct.getMutablePieces(), R);
      assert(stillHasNotes);
      (void)stillHasNotes;
    }

    // Remove pop-up notes if needed.
    if (!Opts.ShouldAddPopUpNotes)
      removePopUpNotes(Construct.getMutablePieces());

    // Redirect all call pieces to have valid locations.
    adjustCallLocations(Construct.getMutablePieces());
    removePiecesWithInvalidLocations(Construct.getMutablePieces());

    if (PDC->shouldAddPathEdges()) {

      // Reduce the number of edges from a very conservative set
      // to an aesthetically pleasing subset that conveys the
      // necessary information.
      OptimizedCallsSet OCS;
      while (optimizeEdges(Construct, Construct.getMutablePieces(), OCS)) {
      }

      // Drop the very first function-entry edge. It's not really necessary
      // for top-level functions.
      dropFunctionEntryEdge(Construct, Construct.getMutablePieces());
    }

    // Remove messages that are basically the same, and edges that may not
    // make sense.
    // We have to do this after edge optimization in the Extensive mode.
    removeRedundantMsgs(Construct.getMutablePieces());
    removeEdgesToDefaultInitializers(Construct.getMutablePieces());
  }

  if (Opts.ShouldDisplayMacroExpansions)
    CompactMacroExpandedPieces(Construct.getMutablePieces(), SM);

  return std::move(Construct.PD);
}

//===----------------------------------------------------------------------===//
// Methods for BugType and subclasses.
//===----------------------------------------------------------------------===//

void BugType::anchor() {}

void BuiltinBug::anchor() {}

//===----------------------------------------------------------------------===//
// Methods for BugReport and subclasses.
//===----------------------------------------------------------------------===//

void PathSensitiveBugReport::addVisitor(
    std::unique_ptr<BugReporterVisitor> visitor) {
  if (!visitor)
    return;

  llvm::FoldingSetNodeID ID;
  visitor->Profile(ID);

  void *InsertPos = nullptr;
  if (CallbacksSet.FindNodeOrInsertPos(ID, InsertPos)) {
    return;
  }

  Callbacks.push_back(std::move(visitor));
}

void PathSensitiveBugReport::clearVisitors() {
  Callbacks.clear();
}

const Decl *PathSensitiveBugReport::getDeclWithIssue() const {
  const ExplodedNode *N = getErrorNode();
  if (!N)
    return nullptr;

  const LocationContext *LC = N->getLocationContext();
  return LC->getStackFrame()->getDecl();
}

void BasicBugReport::Profile(llvm::FoldingSetNodeID& hash) const {
  hash.AddInteger(static_cast<int>(getKind()));
  hash.AddPointer(&BT);
  hash.AddString(Description);
  assert(Location.isValid());
  Location.Profile(hash);

  for (SourceRange range : Ranges) {
    if (!range.isValid())
      continue;
    hash.AddInteger(range.getBegin().getRawEncoding());
    hash.AddInteger(range.getEnd().getRawEncoding());
  }
}

void PathSensitiveBugReport::Profile(llvm::FoldingSetNodeID &hash) const {
  hash.AddInteger(static_cast<int>(getKind()));
  hash.AddPointer(&BT);
  hash.AddString(Description);
  PathDiagnosticLocation UL = getUniqueingLocation();
  if (UL.isValid()) {
    UL.Profile(hash);
  } else {
    // TODO: The statement may be null if the report was emitted before any
    // statements were executed. In particular, some checkers by design
    // occasionally emit their reports in empty functions (that have no
    // statements in their body). Do we profile correctly in this case?
    hash.AddPointer(ErrorNode->getCurrentOrPreviousStmtForDiagnostics());
  }

  for (SourceRange range : Ranges) {
    if (!range.isValid())
      continue;
    hash.AddInteger(range.getBegin().getRawEncoding());
    hash.AddInteger(range.getEnd().getRawEncoding());
  }
}

template <class T>
static void insertToInterestingnessMap(
    llvm::DenseMap<T, bugreporter::TrackingKind> &InterestingnessMap, T Val,
    bugreporter::TrackingKind TKind) {
  auto Result = InterestingnessMap.insert({Val, TKind});

  if (Result.second)
    return;

  // Even if this symbol/region was already marked as interesting as a
  // condition, if we later mark it as interesting again but with
  // thorough tracking, overwrite it. Entities marked with thorough
  // interestiness are the most important (or most interesting, if you will),
  // and we wouldn't like to downplay their importance.

  switch (TKind) {
    case bugreporter::TrackingKind::Thorough:
      Result.first->getSecond() = bugreporter::TrackingKind::Thorough;
      return;
    case bugreporter::TrackingKind::Condition:
      return;
  }

  llvm_unreachable(
      "BugReport::markInteresting currently can only handle 2 different "
      "tracking kinds! Please define what tracking kind should this entitiy"
      "have, if it was already marked as interesting with a different kind!");
}

void PathSensitiveBugReport::markInteresting(SymbolRef sym,
                                             bugreporter::TrackingKind TKind) {
  if (!sym)
    return;

  insertToInterestingnessMap(InterestingSymbols, sym, TKind);

  if (const auto *meta = dyn_cast<SymbolMetadata>(sym))
    markInteresting(meta->getRegion(), TKind);
}

void PathSensitiveBugReport::markInteresting(const MemRegion *R,
                                             bugreporter::TrackingKind TKind) {
  if (!R)
    return;

  R = R->getBaseRegion();
  insertToInterestingnessMap(InterestingRegions, R, TKind);

  if (const auto *SR = dyn_cast<SymbolicRegion>(R))
    markInteresting(SR->getSymbol(), TKind);
}

void PathSensitiveBugReport::markInteresting(SVal V,
                                             bugreporter::TrackingKind TKind) {
  markInteresting(V.getAsRegion(), TKind);
  markInteresting(V.getAsSymbol(), TKind);
}

void PathSensitiveBugReport::markInteresting(const LocationContext *LC) {
  if (!LC)
    return;
  InterestingLocationContexts.insert(LC);
}

Optional<bugreporter::TrackingKind>
PathSensitiveBugReport::getInterestingnessKind(SVal V) const {
  auto RKind = getInterestingnessKind(V.getAsRegion());
  auto SKind = getInterestingnessKind(V.getAsSymbol());
  if (!RKind)
    return SKind;
  if (!SKind)
    return RKind;

  // If either is marked with throrough tracking, return that, we wouldn't like
  // to downplay a note's importance by 'only' mentioning it as a condition.
  switch(*RKind) {
    case bugreporter::TrackingKind::Thorough:
      return RKind;
    case bugreporter::TrackingKind::Condition:
      return SKind;
  }

  llvm_unreachable(
      "BugReport::getInterestingnessKind currently can only handle 2 different "
      "tracking kinds! Please define what tracking kind should we return here "
      "when the kind of getAsRegion() and getAsSymbol() is different!");
  return None;
}

Optional<bugreporter::TrackingKind>
PathSensitiveBugReport::getInterestingnessKind(SymbolRef sym) const {
  if (!sym)
    return None;
  // We don't currently consider metadata symbols to be interesting
  // even if we know their region is interesting. Is that correct behavior?
  auto It = InterestingSymbols.find(sym);
  if (It == InterestingSymbols.end())
    return None;
  return It->getSecond();
}

Optional<bugreporter::TrackingKind>
PathSensitiveBugReport::getInterestingnessKind(const MemRegion *R) const {
  if (!R)
    return None;

  R = R->getBaseRegion();
  auto It = InterestingRegions.find(R);
  if (It != InterestingRegions.end())
    return It->getSecond();

  if (const auto *SR = dyn_cast<SymbolicRegion>(R))
    return getInterestingnessKind(SR->getSymbol());
  return None;
}

bool PathSensitiveBugReport::isInteresting(SVal V) const {
  return getInterestingnessKind(V).hasValue();
}

bool PathSensitiveBugReport::isInteresting(SymbolRef sym) const {
  return getInterestingnessKind(sym).hasValue();
}

bool PathSensitiveBugReport::isInteresting(const MemRegion *R) const {
  return getInterestingnessKind(R).hasValue();
}

bool PathSensitiveBugReport::isInteresting(const LocationContext *LC)  const {
  if (!LC)
    return false;
  return InterestingLocationContexts.count(LC);
}

const Stmt *PathSensitiveBugReport::getStmt() const {
  if (!ErrorNode)
    return nullptr;

  ProgramPoint ProgP = ErrorNode->getLocation();
  const Stmt *S = nullptr;

  if (Optional<BlockEntrance> BE = ProgP.getAs<BlockEntrance>()) {
    CFGBlock &Exit = ProgP.getLocationContext()->getCFG()->getExit();
    if (BE->getBlock() == &Exit)
      S = ErrorNode->getPreviousStmtForDiagnostics();
  }
  if (!S)
    S = ErrorNode->getStmtForDiagnostics();

  return S;
}

ArrayRef<SourceRange>
PathSensitiveBugReport::getRanges() const {
  // If no custom ranges, add the range of the statement corresponding to
  // the error node.
  if (Ranges.empty() && isa_and_nonnull<Expr>(getStmt()))
      return ErrorNodeRange;

  return Ranges;
}

PathDiagnosticLocation
PathSensitiveBugReport::getLocation() const {
  assert(ErrorNode && "Cannot create a location with a null node.");
  const Stmt *S = ErrorNode->getStmtForDiagnostics();
    ProgramPoint P = ErrorNode->getLocation();
  const LocationContext *LC = P.getLocationContext();
  SourceManager &SM =
      ErrorNode->getState()->getStateManager().getContext().getSourceManager();

  if (!S) {
    // If this is an implicit call, return the implicit call point location.
    if (Optional<PreImplicitCall> PIE = P.getAs<PreImplicitCall>())
      return PathDiagnosticLocation(PIE->getLocation(), SM);
    if (auto FE = P.getAs<FunctionExitPoint>()) {
      if (const ReturnStmt *RS = FE->getStmt())
        return PathDiagnosticLocation::createBegin(RS, SM, LC);
    }
    S = ErrorNode->getNextStmtForDiagnostics();
  }

  if (S) {
    // For member expressions, return the location of the '.' or '->'.
    if (const auto *ME = dyn_cast<MemberExpr>(S))
      return PathDiagnosticLocation::createMemberLoc(ME, SM);

    // For binary operators, return the location of the operator.
    if (const auto *B = dyn_cast<BinaryOperator>(S))
      return PathDiagnosticLocation::createOperatorLoc(B, SM);

    if (P.getAs<PostStmtPurgeDeadSymbols>())
      return PathDiagnosticLocation::createEnd(S, SM, LC);

    if (S->getBeginLoc().isValid())
      return PathDiagnosticLocation(S, SM, LC);

    return PathDiagnosticLocation(
        PathDiagnosticLocation::getValidSourceLocation(S, LC), SM);
  }

  return PathDiagnosticLocation::createDeclEnd(ErrorNode->getLocationContext(),
                                               SM);
}

//===----------------------------------------------------------------------===//
// Methods for BugReporter and subclasses.
//===----------------------------------------------------------------------===//

const ExplodedGraph &PathSensitiveBugReporter::getGraph() const {
  return Eng.getGraph();
}

ProgramStateManager &PathSensitiveBugReporter::getStateManager() const {
  return Eng.getStateManager();
}

BugReporter::~BugReporter() {
  // Make sure reports are flushed.
  assert(StrBugTypes.empty() &&
         "Destroying BugReporter before diagnostics are emitted!");

  // Free the bug reports we are tracking.
  for (const auto I : EQClassesVector)
    delete I;
}

void BugReporter::FlushReports() {
  // We need to flush reports in deterministic order to ensure the order
  // of the reports is consistent between runs.
  for (const auto EQ : EQClassesVector)
    FlushReport(*EQ);

  // BugReporter owns and deletes only BugTypes created implicitly through
  // EmitBasicReport.
  // FIXME: There are leaks from checkers that assume that the BugTypes they
  // create will be destroyed by the BugReporter.
  llvm::DeleteContainerSeconds(StrBugTypes);
}

//===----------------------------------------------------------------------===//
// PathDiagnostics generation.
//===----------------------------------------------------------------------===//

namespace {

/// A wrapper around an ExplodedGraph that contains a single path from the root
/// to the error node.
class BugPathInfo {
public:
  std::unique_ptr<ExplodedGraph> BugPath;
  PathSensitiveBugReport *Report;
  const ExplodedNode *ErrorNode;
};

/// A wrapper around an ExplodedGraph whose leafs are all error nodes. Can
/// conveniently retrieve bug paths from a single error node to the root.
class BugPathGetter {
  std::unique_ptr<ExplodedGraph> TrimmedGraph;

  using PriorityMapTy = llvm::DenseMap<const ExplodedNode *, unsigned>;

  /// Assign each node with its distance from the root.
  PriorityMapTy PriorityMap;

  /// Since the getErrorNode() or BugReport refers to the original ExplodedGraph,
  /// we need to pair it to the error node of the constructed trimmed graph.
  using ReportNewNodePair =
      std::pair<PathSensitiveBugReport *, const ExplodedNode *>;
  SmallVector<ReportNewNodePair, 32> ReportNodes;

  BugPathInfo CurrentBugPath;

  /// A helper class for sorting ExplodedNodes by priority.
  template <bool Descending>
  class PriorityCompare {
    const PriorityMapTy &PriorityMap;

  public:
    PriorityCompare(const PriorityMapTy &M) : PriorityMap(M) {}

    bool operator()(const ExplodedNode *LHS, const ExplodedNode *RHS) const {
      PriorityMapTy::const_iterator LI = PriorityMap.find(LHS);
      PriorityMapTy::const_iterator RI = PriorityMap.find(RHS);
      PriorityMapTy::const_iterator E = PriorityMap.end();

      if (LI == E)
        return Descending;
      if (RI == E)
        return !Descending;

      return Descending ? LI->second > RI->second
                        : LI->second < RI->second;
    }

    bool operator()(const ReportNewNodePair &LHS,
                    const ReportNewNodePair &RHS) const {
      return (*this)(LHS.second, RHS.second);
    }
  };

public:
  BugPathGetter(const ExplodedGraph *OriginalGraph,
                ArrayRef<PathSensitiveBugReport *> &bugReports);

  BugPathInfo *getNextBugPath();
};

} // namespace

BugPathGetter::BugPathGetter(const ExplodedGraph *OriginalGraph,
                             ArrayRef<PathSensitiveBugReport *> &bugReports) {
  SmallVector<const ExplodedNode *, 32> Nodes;
  for (const auto I : bugReports) {
    assert(I->isValid() &&
           "We only allow BugReporterVisitors and BugReporter itself to "
           "invalidate reports!");
    Nodes.emplace_back(I->getErrorNode());
  }

  // The trimmed graph is created in the body of the constructor to ensure
  // that the DenseMaps have been initialized already.
  InterExplodedGraphMap ForwardMap;
  TrimmedGraph = OriginalGraph->trim(Nodes, &ForwardMap);

  // Find the (first) error node in the trimmed graph.  We just need to consult
  // the node map which maps from nodes in the original graph to nodes
  // in the new graph.
  llvm::SmallPtrSet<const ExplodedNode *, 32> RemainingNodes;

  for (PathSensitiveBugReport *Report : bugReports) {
    const ExplodedNode *NewNode = ForwardMap.lookup(Report->getErrorNode());
    assert(NewNode &&
           "Failed to construct a trimmed graph that contains this error "
           "node!");
    ReportNodes.emplace_back(Report, NewNode);
    RemainingNodes.insert(NewNode);
  }

  assert(!RemainingNodes.empty() && "No error node found in the trimmed graph");

  // Perform a forward BFS to find all the shortest paths.
  std::queue<const ExplodedNode *> WS;

  assert(TrimmedGraph->num_roots() == 1);
  WS.push(*TrimmedGraph->roots_begin());
  unsigned Priority = 0;

  while (!WS.empty()) {
    const ExplodedNode *Node = WS.front();
    WS.pop();

    PriorityMapTy::iterator PriorityEntry;
    bool IsNew;
    std::tie(PriorityEntry, IsNew) = PriorityMap.insert({Node, Priority});
    ++Priority;

    if (!IsNew) {
      assert(PriorityEntry->second <= Priority);
      continue;
    }

    if (RemainingNodes.erase(Node))
      if (RemainingNodes.empty())
        break;

    for (const ExplodedNode *Succ : Node->succs())
      WS.push(Succ);
  }

  // Sort the error paths from longest to shortest.
  llvm::sort(ReportNodes, PriorityCompare<true>(PriorityMap));
}

BugPathInfo *BugPathGetter::getNextBugPath() {
  if (ReportNodes.empty())
    return nullptr;

  const ExplodedNode *OrigN;
  std::tie(CurrentBugPath.Report, OrigN) = ReportNodes.pop_back_val();
  assert(PriorityMap.find(OrigN) != PriorityMap.end() &&
         "error node not accessible from root");

  // Create a new graph with a single path. This is the graph that will be
  // returned to the caller.
  auto GNew = std::make_unique<ExplodedGraph>();

  // Now walk from the error node up the BFS path, always taking the
  // predeccessor with the lowest number.
  ExplodedNode *Succ = nullptr;
  while (true) {
    // Create the equivalent node in the new graph with the same state
    // and location.
    ExplodedNode *NewN = GNew->createUncachedNode(
        OrigN->getLocation(), OrigN->getState(),
        OrigN->getID(), OrigN->isSink());

    // Link up the new node with the previous node.
    if (Succ)
      Succ->addPredecessor(NewN, *GNew);
    else
      CurrentBugPath.ErrorNode = NewN;

    Succ = NewN;

    // Are we at the final node?
    if (OrigN->pred_empty()) {
      GNew->addRoot(NewN);
      break;
    }

    // Find the next predeccessor node.  We choose the node that is marked
    // with the lowest BFS number.
    OrigN = *std::min_element(OrigN->pred_begin(), OrigN->pred_end(),
                              PriorityCompare<false>(PriorityMap));
  }

  CurrentBugPath.BugPath = std::move(GNew);

  return &CurrentBugPath;
}

/// CompactMacroExpandedPieces - This function postprocesses a PathDiagnostic
/// object and collapses PathDiagosticPieces that are expanded by macros.
static void CompactMacroExpandedPieces(PathPieces &path,
                                       const SourceManager& SM) {
  using MacroStackTy = std::vector<
      std::pair<std::shared_ptr<PathDiagnosticMacroPiece>, SourceLocation>>;

  using PiecesTy = std::vector<PathDiagnosticPieceRef>;

  MacroStackTy MacroStack;
  PiecesTy Pieces;

  for (PathPieces::const_iterator I = path.begin(), E = path.end();
       I != E; ++I) {
    const auto &piece = *I;

    // Recursively compact calls.
    if (auto *call = dyn_cast<PathDiagnosticCallPiece>(&*piece)) {
      CompactMacroExpandedPieces(call->path, SM);
    }

    // Get the location of the PathDiagnosticPiece.
    const FullSourceLoc Loc = piece->getLocation().asLocation();

    // Determine the instantiation location, which is the location we group
    // related PathDiagnosticPieces.
    SourceLocation InstantiationLoc = Loc.isMacroID() ?
                                      SM.getExpansionLoc(Loc) :
                                      SourceLocation();

    if (Loc.isFileID()) {
      MacroStack.clear();
      Pieces.push_back(piece);
      continue;
    }

    assert(Loc.isMacroID());

    // Is the PathDiagnosticPiece within the same macro group?
    if (!MacroStack.empty() && InstantiationLoc == MacroStack.back().second) {
      MacroStack.back().first->subPieces.push_back(piece);
      continue;
    }

    // We aren't in the same group.  Are we descending into a new macro
    // or are part of an old one?
    std::shared_ptr<PathDiagnosticMacroPiece> MacroGroup;

    SourceLocation ParentInstantiationLoc = InstantiationLoc.isMacroID() ?
                                          SM.getExpansionLoc(Loc) :
                                          SourceLocation();

    // Walk the entire macro stack.
    while (!MacroStack.empty()) {
      if (InstantiationLoc == MacroStack.back().second) {
        MacroGroup = MacroStack.back().first;
        break;
      }

      if (ParentInstantiationLoc == MacroStack.back().second) {
        MacroGroup = MacroStack.back().first;
        break;
      }

      MacroStack.pop_back();
    }

    if (!MacroGroup || ParentInstantiationLoc == MacroStack.back().second) {
      // Create a new macro group and add it to the stack.
      auto NewGroup = std::make_shared<PathDiagnosticMacroPiece>(
          PathDiagnosticLocation::createSingleLocation(piece->getLocation()));

      if (MacroGroup)
        MacroGroup->subPieces.push_back(NewGroup);
      else {
        assert(InstantiationLoc.isFileID());
        Pieces.push_back(NewGroup);
      }

      MacroGroup = NewGroup;
      MacroStack.push_back(std::make_pair(MacroGroup, InstantiationLoc));
    }

    // Finally, add the PathDiagnosticPiece to the group.
    MacroGroup->subPieces.push_back(piece);
  }

  // Now take the pieces and construct a new PathDiagnostic.
  path.clear();

  path.insert(path.end(), Pieces.begin(), Pieces.end());
}

/// Generate notes from all visitors.
/// Notes associated with {@code ErrorNode} are generated using
/// {@code getEndPath}, and the rest are generated with {@code VisitNode}.
static std::unique_ptr<VisitorsDiagnosticsTy>
generateVisitorsDiagnostics(PathSensitiveBugReport *R,
                            const ExplodedNode *ErrorNode,
                            BugReporterContext &BRC) {
  std::unique_ptr<VisitorsDiagnosticsTy> Notes =
      std::make_unique<VisitorsDiagnosticsTy>();
  PathSensitiveBugReport::VisitorList visitors;

  // Run visitors on all nodes starting from the node *before* the last one.
  // The last node is reserved for notes generated with {@code getEndPath}.
  const ExplodedNode *NextNode = ErrorNode->getFirstPred();
  while (NextNode) {

    // At each iteration, move all visitors from report to visitor list. This is
    // important, because the Profile() functions of the visitors make sure that
    // a visitor isn't added multiple times for the same node, but it's fine
    // to add the a visitor with Profile() for different nodes (e.g. tracking
    // a region at different points of the symbolic execution).
    for (std::unique_ptr<BugReporterVisitor> &Visitor : R->visitors())
      visitors.push_back(std::move(Visitor));

    R->clearVisitors();

    const ExplodedNode *Pred = NextNode->getFirstPred();
    if (!Pred) {
      PathDiagnosticPieceRef LastPiece;
      for (auto &V : visitors) {
        V->finalizeVisitor(BRC, ErrorNode, *R);

        if (auto Piece = V->getEndPath(BRC, ErrorNode, *R)) {
          assert(!LastPiece &&
                 "There can only be one final piece in a diagnostic.");
          assert(Piece->getKind() == PathDiagnosticPiece::Kind::Event &&
                 "The final piece must contain a message!");
          LastPiece = std::move(Piece);
          (*Notes)[ErrorNode].push_back(LastPiece);
        }
      }
      break;
    }

    for (auto &V : visitors) {
      auto P = V->VisitNode(NextNode, BRC, *R);
      if (P)
        (*Notes)[NextNode].push_back(std::move(P));
    }

    if (!R->isValid())
      break;

    NextNode = Pred;
  }

  return Notes;
}

Optional<PathDiagnosticBuilder> PathDiagnosticBuilder::findValidReport(
    ArrayRef<PathSensitiveBugReport *> &bugReports,
    PathSensitiveBugReporter &Reporter) {

  BugPathGetter BugGraph(&Reporter.getGraph(), bugReports);

  while (BugPathInfo *BugPath = BugGraph.getNextBugPath()) {
    // Find the BugReport with the original location.
    PathSensitiveBugReport *R = BugPath->Report;
    assert(R && "No original report found for sliced graph.");
    assert(R->isValid() && "Report selected by trimmed graph marked invalid.");
    const ExplodedNode *ErrorNode = BugPath->ErrorNode;

    // Register refutation visitors first, if they mark the bug invalid no
    // further analysis is required
    R->addVisitor(std::make_unique<LikelyFalsePositiveSuppressionBRVisitor>());

    // Register additional node visitors.
    R->addVisitor(std::make_unique<NilReceiverBRVisitor>());
    R->addVisitor(std::make_unique<ConditionBRVisitor>());
    R->addVisitor(std::make_unique<TagVisitor>());

    BugReporterContext BRC(Reporter);

    // Run all visitors on a given graph, once.
    std::unique_ptr<VisitorsDiagnosticsTy> visitorNotes =
        generateVisitorsDiagnostics(R, ErrorNode, BRC);

    if (R->isValid()) {
      if (Reporter.getAnalyzerOptions().ShouldCrosscheckWithZ3) {
        // If crosscheck is enabled, remove all visitors, add the refutation
        // visitor and check again
        R->clearVisitors();
        R->addVisitor(std::make_unique<FalsePositiveRefutationBRVisitor>());

        // We don't overrite the notes inserted by other visitors because the
        // refutation manager does not add any new note to the path
        generateVisitorsDiagnostics(R, BugPath->ErrorNode, BRC);
      }

      // Check if the bug is still valid
      if (R->isValid())
        return PathDiagnosticBuilder(
            std::move(BRC), std::move(BugPath->BugPath), BugPath->Report,
            BugPath->ErrorNode, std::move(visitorNotes));
    }
  }

  return {};
}

std::unique_ptr<DiagnosticForConsumerMapTy>
PathSensitiveBugReporter::generatePathDiagnostics(
    ArrayRef<PathDiagnosticConsumer *> consumers,
    ArrayRef<PathSensitiveBugReport *> &bugReports) {
  assert(!bugReports.empty());

  auto Out = std::make_unique<DiagnosticForConsumerMapTy>();

  Optional<PathDiagnosticBuilder> PDB =
      PathDiagnosticBuilder::findValidReport(bugReports, *this);

  if (PDB) {
    for (PathDiagnosticConsumer *PC : consumers) {
      if (std::unique_ptr<PathDiagnostic> PD = PDB->generate(PC)) {
        (*Out)[PC] = std::move(PD);
      }
    }
  }

  return Out;
}

void BugReporter::emitReport(std::unique_ptr<BugReport> R) {
  bool ValidSourceLoc = R->getLocation().isValid();
  assert(ValidSourceLoc);
  // If we mess up in a release build, we'd still prefer to just drop the bug
  // instead of trying to go on.
  if (!ValidSourceLoc)
    return;

  // Compute the bug report's hash to determine its equivalence class.
  llvm::FoldingSetNodeID ID;
  R->Profile(ID);

  // Lookup the equivance class.  If there isn't one, create it.
  void *InsertPos;
  BugReportEquivClass* EQ = EQClasses.FindNodeOrInsertPos(ID, InsertPos);

  if (!EQ) {
    EQ = new BugReportEquivClass(std::move(R));
    EQClasses.InsertNode(EQ, InsertPos);
    EQClassesVector.push_back(EQ);
  } else
    EQ->AddReport(std::move(R));
}

void PathSensitiveBugReporter::emitReport(std::unique_ptr<BugReport> R) {
  if (auto PR = dyn_cast<PathSensitiveBugReport>(R.get()))
    if (const ExplodedNode *E = PR->getErrorNode()) {
      // An error node must either be a sink or have a tag, otherwise
      // it could get reclaimed before the path diagnostic is created.
      assert((E->isSink() || E->getLocation().getTag()) &&
             "Error node must either be a sink or have a tag");

      const AnalysisDeclContext *DeclCtx =
          E->getLocationContext()->getAnalysisDeclContext();
      // The source of autosynthesized body can be handcrafted AST or a model
      // file. The locations from handcrafted ASTs have no valid source
      // locations and have to be discarded. Locations from model files should
      // be preserved for processing and reporting.
      if (DeclCtx->isBodyAutosynthesized() &&
          !DeclCtx->isBodyAutosynthesizedFromModelFile())
        return;
    }

  BugReporter::emitReport(std::move(R));
}

//===----------------------------------------------------------------------===//
// Emitting reports in equivalence classes.
//===----------------------------------------------------------------------===//

namespace {

struct FRIEC_WLItem {
  const ExplodedNode *N;
  ExplodedNode::const_succ_iterator I, E;

  FRIEC_WLItem(const ExplodedNode *n)
      : N(n), I(N->succ_begin()), E(N->succ_end()) {}
};

} // namespace

BugReport *PathSensitiveBugReporter::findReportInEquivalenceClass(
    BugReportEquivClass &EQ, SmallVectorImpl<BugReport *> &bugReports) {
  // If we don't need to suppress any of the nodes because they are
  // post-dominated by a sink, simply add all the nodes in the equivalence class
  // to 'Nodes'.  Any of the reports will serve as a "representative" report.
  assert(EQ.getReports().size() > 0);
  const BugType& BT = EQ.getReports()[0]->getBugType();
  if (!BT.isSuppressOnSink()) {
    BugReport *R = EQ.getReports()[0].get();
    for (auto &J : EQ.getReports()) {
      if (auto *PR = dyn_cast<PathSensitiveBugReport>(J.get())) {
        R = PR;
        bugReports.push_back(PR);
      }
    }
    return R;
  }

  // For bug reports that should be suppressed when all paths are post-dominated
  // by a sink node, iterate through the reports in the equivalence class
  // until we find one that isn't post-dominated (if one exists).  We use a
  // DFS traversal of the ExplodedGraph to find a non-sink node.  We could write
  // this as a recursive function, but we don't want to risk blowing out the
  // stack for very long paths.
  BugReport *exampleReport = nullptr;

  for (const auto &I: EQ.getReports()) {
    auto *R = dyn_cast<PathSensitiveBugReport>(I.get());
    if (!R)
      continue;

    const ExplodedNode *errorNode = R->getErrorNode();
    if (errorNode->isSink()) {
      llvm_unreachable(
           "BugType::isSuppressSink() should not be 'true' for sink end nodes");
    }
    // No successors?  By definition this nodes isn't post-dominated by a sink.
    if (errorNode->succ_empty()) {
      bugReports.push_back(R);
      if (!exampleReport)
        exampleReport = R;
      continue;
    }

    // See if we are in a no-return CFG block. If so, treat this similarly
    // to being post-dominated by a sink. This works better when the analysis
    // is incomplete and we have never reached the no-return function call(s)
    // that we'd inevitably bump into on this path.
    if (const CFGBlock *ErrorB = errorNode->getCFGBlock())
      if (ErrorB->isInevitablySinking())
        continue;

    // At this point we know that 'N' is not a sink and it has at least one
    // successor.  Use a DFS worklist to find a non-sink end-of-path node.
    using WLItem = FRIEC_WLItem;
    using DFSWorkList = SmallVector<WLItem, 10>;

    llvm::DenseMap<const ExplodedNode *, unsigned> Visited;

    DFSWorkList WL;
    WL.push_back(errorNode);
    Visited[errorNode] = 1;

    while (!WL.empty()) {
      WLItem &WI = WL.back();
      assert(!WI.N->succ_empty());

      for (; WI.I != WI.E; ++WI.I) {
        const ExplodedNode *Succ = *WI.I;
        // End-of-path node?
        if (Succ->succ_empty()) {
          // If we found an end-of-path node that is not a sink.
          if (!Succ->isSink()) {
            bugReports.push_back(R);
            if (!exampleReport)
              exampleReport = R;
            WL.clear();
            break;
          }
          // Found a sink?  Continue on to the next successor.
          continue;
        }
        // Mark the successor as visited.  If it hasn't been explored,
        // enqueue it to the DFS worklist.
        unsigned &mark = Visited[Succ];
        if (!mark) {
          mark = 1;
          WL.push_back(Succ);
          break;
        }
      }

      // The worklist may have been cleared at this point.  First
      // check if it is empty before checking the last item.
      if (!WL.empty() && &WL.back() == &WI)
        WL.pop_back();
    }
  }

  // ExampleReport will be NULL if all the nodes in the equivalence class
  // were post-dominated by sinks.
  return exampleReport;
}

void BugReporter::FlushReport(BugReportEquivClass& EQ) {
  SmallVector<BugReport*, 10> bugReports;
  BugReport *report = findReportInEquivalenceClass(EQ, bugReports);
  if (!report)
    return;

  ArrayRef<PathDiagnosticConsumer*> Consumers = getPathDiagnosticConsumers();
  std::unique_ptr<DiagnosticForConsumerMapTy> Diagnostics =
      generateDiagnosticForConsumerMap(report, Consumers, bugReports);

  for (auto &P : *Diagnostics) {
    PathDiagnosticConsumer *Consumer = P.first;
    std::unique_ptr<PathDiagnostic> &PD = P.second;

    // If the path is empty, generate a single step path with the location
    // of the issue.
    if (PD->path.empty()) {
      PathDiagnosticLocation L = report->getLocation();
      auto piece = std::make_unique<PathDiagnosticEventPiece>(
        L, report->getDescription());
      for (SourceRange Range : report->getRanges())
        piece->addRange(Range);
      PD->setEndOfPath(std::move(piece));
    }

    PathPieces &Pieces = PD->getMutablePieces();
    if (getAnalyzerOptions().ShouldDisplayNotesAsEvents) {
      // For path diagnostic consumers that don't support extra notes,
      // we may optionally convert those to path notes.
      for (auto I = report->getNotes().rbegin(),
           E = report->getNotes().rend(); I != E; ++I) {
        PathDiagnosticNotePiece *Piece = I->get();
        auto ConvertedPiece = std::make_shared<PathDiagnosticEventPiece>(
          Piece->getLocation(), Piece->getString());
        for (const auto &R: Piece->getRanges())
          ConvertedPiece->addRange(R);

        Pieces.push_front(std::move(ConvertedPiece));
      }
    } else {
      for (auto I = report->getNotes().rbegin(),
           E = report->getNotes().rend(); I != E; ++I)
        Pieces.push_front(*I);
    }

    for (const auto &I : report->getFixits())
      Pieces.back()->addFixit(I);

    updateExecutedLinesWithDiagnosticPieces(*PD);
    Consumer->HandlePathDiagnostic(std::move(PD));
  }
}

/// Insert all lines participating in the function signature \p Signature
/// into \p ExecutedLines.
static void populateExecutedLinesWithFunctionSignature(
    const Decl *Signature, const SourceManager &SM,
    FilesToLineNumsMap &ExecutedLines) {
  SourceRange SignatureSourceRange;
  const Stmt* Body = Signature->getBody();
  if (const auto FD = dyn_cast<FunctionDecl>(Signature)) {
    SignatureSourceRange = FD->getSourceRange();
  } else if (const auto OD = dyn_cast<ObjCMethodDecl>(Signature)) {
    SignatureSourceRange = OD->getSourceRange();
  } else {
    return;
  }
  SourceLocation Start = SignatureSourceRange.getBegin();
  SourceLocation End = Body ? Body->getSourceRange().getBegin()
    : SignatureSourceRange.getEnd();
  if (!Start.isValid() || !End.isValid())
    return;
  unsigned StartLine = SM.getExpansionLineNumber(Start);
  unsigned EndLine = SM.getExpansionLineNumber(End);

  FileID FID = SM.getFileID(SM.getExpansionLoc(Start));
  for (unsigned Line = StartLine; Line <= EndLine; Line++)
    ExecutedLines[FID].insert(Line);
}

static void populateExecutedLinesWithStmt(
    const Stmt *S, const SourceManager &SM,
    FilesToLineNumsMap &ExecutedLines) {
  SourceLocation Loc = S->getSourceRange().getBegin();
  if (!Loc.isValid())
    return;
  SourceLocation ExpansionLoc = SM.getExpansionLoc(Loc);
  FileID FID = SM.getFileID(ExpansionLoc);
  unsigned LineNo = SM.getExpansionLineNumber(ExpansionLoc);
  ExecutedLines[FID].insert(LineNo);
}

/// \return all executed lines including function signatures on the path
/// starting from \p N.
static std::unique_ptr<FilesToLineNumsMap>
findExecutedLines(const SourceManager &SM, const ExplodedNode *N) {
  auto ExecutedLines = std::make_unique<FilesToLineNumsMap>();

  while (N) {
    if (N->getFirstPred() == nullptr) {
      // First node: show signature of the entrance point.
      const Decl *D = N->getLocationContext()->getDecl();
      populateExecutedLinesWithFunctionSignature(D, SM, *ExecutedLines);
    } else if (auto CE = N->getLocationAs<CallEnter>()) {
      // Inlined function: show signature.
      const Decl* D = CE->getCalleeContext()->getDecl();
      populateExecutedLinesWithFunctionSignature(D, SM, *ExecutedLines);
    } else if (const Stmt *S = N->getStmtForDiagnostics()) {
      populateExecutedLinesWithStmt(S, SM, *ExecutedLines);

      // Show extra context for some parent kinds.
      const Stmt *P = N->getParentMap().getParent(S);

      // The path exploration can die before the node with the associated
      // return statement is generated, but we do want to show the whole
      // return.
      if (const auto *RS = dyn_cast_or_null<ReturnStmt>(P)) {
        populateExecutedLinesWithStmt(RS, SM, *ExecutedLines);
        P = N->getParentMap().getParent(RS);
      }

      if (P && (isa<SwitchCase>(P) || isa<LabelStmt>(P)))
        populateExecutedLinesWithStmt(P, SM, *ExecutedLines);
    }

    N = N->getFirstPred();
  }
  return ExecutedLines;
}

std::unique_ptr<DiagnosticForConsumerMapTy>
BugReporter::generateDiagnosticForConsumerMap(
    BugReport *exampleReport, ArrayRef<PathDiagnosticConsumer *> consumers,
    ArrayRef<BugReport *> bugReports) {
  auto *basicReport = cast<BasicBugReport>(exampleReport);
  auto Out = std::make_unique<DiagnosticForConsumerMapTy>();
  for (auto *Consumer : consumers)
    (*Out)[Consumer] = generateDiagnosticForBasicReport(basicReport);
  return Out;
}

static PathDiagnosticCallPiece *
getFirstStackedCallToHeaderFile(PathDiagnosticCallPiece *CP,
                                const SourceManager &SMgr) {
  SourceLocation CallLoc = CP->callEnter.asLocation();

  // If the call is within a macro, don't do anything (for now).
  if (CallLoc.isMacroID())
    return nullptr;

  assert(AnalysisManager::isInCodeFile(CallLoc, SMgr) &&
         "The call piece should not be in a header file.");

  // Check if CP represents a path through a function outside of the main file.
  if (!AnalysisManager::isInCodeFile(CP->callEnterWithin.asLocation(), SMgr))
    return CP;

  const PathPieces &Path = CP->path;
  if (Path.empty())
    return nullptr;

  // Check if the last piece in the callee path is a call to a function outside
  // of the main file.
  if (auto *CPInner = dyn_cast<PathDiagnosticCallPiece>(Path.back().get()))
    return getFirstStackedCallToHeaderFile(CPInner, SMgr);

  // Otherwise, the last piece is in the main file.
  return nullptr;
}

static void resetDiagnosticLocationToMainFile(PathDiagnostic &PD) {
  if (PD.path.empty())
    return;

  PathDiagnosticPiece *LastP = PD.path.back().get();
  assert(LastP);
  const SourceManager &SMgr = LastP->getLocation().getManager();

  // We only need to check if the report ends inside headers, if the last piece
  // is a call piece.
  if (auto *CP = dyn_cast<PathDiagnosticCallPiece>(LastP)) {
    CP = getFirstStackedCallToHeaderFile(CP, SMgr);
    if (CP) {
      // Mark the piece.
       CP->setAsLastInMainSourceFile();

      // Update the path diagnostic message.
      const auto *ND = dyn_cast<NamedDecl>(CP->getCallee());
      if (ND) {
        SmallString<200> buf;
        llvm::raw_svector_ostream os(buf);
        os << " (within a call to '" << ND->getDeclName() << "')";
        PD.appendToDesc(os.str());
      }

      // Reset the report containing declaration and location.
      PD.setDeclWithIssue(CP->getCaller());
      PD.setLocation(CP->getLocation());

      return;
    }
  }
}



std::unique_ptr<DiagnosticForConsumerMapTy>
PathSensitiveBugReporter::generateDiagnosticForConsumerMap(
    BugReport *exampleReport, ArrayRef<PathDiagnosticConsumer *> consumers,
    ArrayRef<BugReport *> bugReports) {
  std::vector<BasicBugReport *> BasicBugReports;
  std::vector<PathSensitiveBugReport *> PathSensitiveBugReports;
  if (isa<BasicBugReport>(exampleReport))
    return BugReporter::generateDiagnosticForConsumerMap(exampleReport,
                                                         consumers, bugReports);

  // Generate the full path sensitive diagnostic, using the generation scheme
  // specified by the PathDiagnosticConsumer. Note that we have to generate
  // path diagnostics even for consumers which do not support paths, because
  // the BugReporterVisitors may mark this bug as a false positive.
  assert(!bugReports.empty());
  MaxBugClassSize.updateMax(bugReports.size());

  // Avoid copying the whole array because there may be a lot of reports.
  ArrayRef<PathSensitiveBugReport *> convertedArrayOfReports(
      reinterpret_cast<PathSensitiveBugReport *const *>(&*bugReports.begin()),
      reinterpret_cast<PathSensitiveBugReport *const *>(&*bugReports.end()));
  std::unique_ptr<DiagnosticForConsumerMapTy> Out = generatePathDiagnostics(
      consumers, convertedArrayOfReports);

  if (Out->empty())
    return Out;

  MaxValidBugClassSize.updateMax(bugReports.size());

  // Examine the report and see if the last piece is in a header. Reset the
  // report location to the last piece in the main source file.
  const AnalyzerOptions &Opts = getAnalyzerOptions();
  for (auto const &P : *Out)
    if (Opts.ShouldReportIssuesInMainSourceFile && !Opts.AnalyzeAll)
      resetDiagnosticLocationToMainFile(*P.second);

  return Out;
}

void BugReporter::EmitBasicReport(const Decl *DeclWithIssue,
                                  const CheckerBase *Checker, StringRef Name,
                                  StringRef Category, StringRef Str,
                                  PathDiagnosticLocation Loc,
                                  ArrayRef<SourceRange> Ranges,
                                  ArrayRef<FixItHint> Fixits) {
  EmitBasicReport(DeclWithIssue, Checker->getCheckerName(), Name, Category, Str,
                  Loc, Ranges, Fixits);
}

void BugReporter::EmitBasicReport(const Decl *DeclWithIssue,
                                  CheckerNameRef CheckName,
                                  StringRef name, StringRef category,
                                  StringRef str, PathDiagnosticLocation Loc,
                                  ArrayRef<SourceRange> Ranges,
                                  ArrayRef<FixItHint> Fixits) {
  // 'BT' is owned by BugReporter.
  BugType *BT = getBugTypeForName(CheckName, name, category);
  auto R = std::make_unique<BasicBugReport>(*BT, str, Loc);
  R->setDeclWithIssue(DeclWithIssue);
  for (const auto &SR : Ranges)
    R->addRange(SR);
  for (const auto &FH : Fixits)
    R->addFixItHint(FH);
  emitReport(std::move(R));
}

BugType *BugReporter::getBugTypeForName(CheckerNameRef CheckName,
                                        StringRef name, StringRef category) {
  SmallString<136> fullDesc;
  llvm::raw_svector_ostream(fullDesc) << CheckName.getName() << ":" << name
                                      << ":" << category;
  BugType *&BT = StrBugTypes[fullDesc];
  if (!BT)
    BT = new BugType(CheckName, name, category);
  return BT;
}
