//===- BugReporter.cpp - Generate PathDiagnostics for bugs ----------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
//  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/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/BugReporter/PathDiagnostic.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;

#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() {}

//===----------------------------------------------------------------------===//
// Helper routines for walking the ExplodedGraph and fetching statements.
//===----------------------------------------------------------------------===//

static const Stmt *GetPreviousStmt(const ExplodedNode *N) {
  for (N = N->getFirstPred(); N; N = N->getFirstPred())
    if (const Stmt *S = PathDiagnosticLocation::getStmt(N))
      return S;

  return nullptr;
}

static inline const Stmt*
GetCurrentOrPreviousStmt(const ExplodedNode *N) {
  if (const Stmt *S = PathDiagnosticLocation::getStmt(N))
    return S;

  return GetPreviousStmt(N);
}

//===----------------------------------------------------------------------===//
// 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::ControlFlow:
        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::Note:
        break;
    }
    path.push_back(std::move(piece));
  }
}

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

/// 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(PathPieces &pieces, BugReport *R,
                                LocationContextMap &LCM,
                                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.
        assert(LCM.count(&call.path));
        if (!removeUnneededCalls(call.path, R, LCM,
                                 R->isInteresting(LCM[&call.path])))
          continue;

        containsSomethingInteresting = true;
        break;
      }
      case PathDiagnosticPiece::Macro: {
        auto &macro = cast<PathDiagnosticMacroPiece>(*piece);
        if (!removeUnneededCalls(macro.subPieces, R, LCM, 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:
        break;

      case PathDiagnosticPiece::Note:
        break;
    }

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

  return containsSomethingInteresting;
}

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

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

namespace {

class PathDiagnosticBuilder : public BugReporterContext {
  BugReport *R;
  PathDiagnosticConsumer *PDC;

public:
  const LocationContext *LC;

  PathDiagnosticBuilder(GRBugReporter &br,
                        BugReport *r, InterExplodedGraphMap &Backmap,
                        PathDiagnosticConsumer *pdc)
      : BugReporterContext(br, Backmap), R(r), PDC(pdc),
        LC(r->getErrorNode()->getLocationContext()) {}

  PathDiagnosticLocation ExecutionContinues(const ExplodedNode *N);

  PathDiagnosticLocation ExecutionContinues(llvm::raw_string_ostream &os,
                                            const ExplodedNode *N);

  BugReport *getBugReport() { return R; }

  Decl const &getCodeDecl() { return R->getErrorNode()->getCodeDecl(); }

  ParentMap& getParentMap() { return LC->getParentMap(); }

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

  PathDiagnosticLocation getEnclosingStmtLocation(const Stmt *S);

  PathDiagnosticConsumer::PathGenerationScheme getGenerationScheme() const {
    return PDC ? PDC->getGenerationScheme() : PathDiagnosticConsumer::Minimal;
  }

  bool supportsLogicalOpControlFlow() const {
    return PDC ? PDC->supportsLogicalOpControlFlow() : true;
  }
};

} // namespace

PathDiagnosticLocation
PathDiagnosticBuilder::ExecutionContinues(const ExplodedNode *N) {
  if (const Stmt *S = PathDiagnosticLocation::getNextStmt(N))
    return PathDiagnosticLocation(S, getSourceManager(), LC);

  return PathDiagnosticLocation::createDeclEnd(N->getLocationContext(),
                                               getSourceManager());
}

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

  const PathDiagnosticLocation &Loc = ExecutionContinues(N);

  if (Loc.asStmt())
    os << "Execution continues on line "
       << getSourceManager().getExpansionLineNumber(Loc.asLocation())
       << '.';
  else {
    os << "Execution jumps to the end of the ";
    const Decl *D = N->getLocationContext()->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, SourceManager &SMgr, const ParentMap &P,
                         const LocationContext *LC, bool allowNestedContexts) {
  if (!S)
    return {};

  while (const Stmt *Parent = getEnclosingParent(S, P)) {
    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);
}

PathDiagnosticLocation
PathDiagnosticBuilder::getEnclosingStmtLocation(const Stmt *S) {
  assert(S && "Null Stmt passed to getEnclosingStmtLocation");
  return ::getEnclosingStmtLocation(S, getSourceManager(), getParentMap(), LC,
                                    /*allowNestedContexts=*/false);
}

//===----------------------------------------------------------------------===//
// "Minimal" path diagnostic generation algorithm.
//===----------------------------------------------------------------------===//
using StackDiagPair =
    std::pair<PathDiagnosticCallPiece *, const ExplodedNode *>;
using StackDiagVector = SmallVector<StackDiagPair, 6>;

static void updateStackPiecesWithMessage(PathDiagnosticPiece &P,
                                         StackDiagVector &CallStack) {
  // If the piece contains a special message, add it to all the call
  // pieces on the active stack.
  if (auto *ep = dyn_cast<PathDiagnosticEventPiece>(&P)) {
    if (ep->hasCallStackHint())
      for (const auto &I : CallStack) {
        PathDiagnosticCallPiece *CP = I.first;
        const ExplodedNode *N = I.second;
        std::string stackMsg = ep->getCallStackMessage(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 CompactPathDiagnostic(PathPieces &path, const SourceManager& SM);


std::shared_ptr<PathDiagnosticControlFlowPiece> generateDiagForSwitchOP(
  const ExplodedNode *N,
  const CFGBlock *Dst,
  const SourceManager &SM,
  const LocationContext *LC,
  PathDiagnosticBuilder &PDB,
  PathDiagnosticLocation &Start
  ) {
  // 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, LC);

    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(PDB.getASTContext());

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


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

}

std::shared_ptr<PathDiagnosticControlFlowPiece> generateDiagForBinaryOP(
                                                 const ExplodedNode *N,
                                                 const Stmt *T,
                                                 const CFGBlock *Src,
                                                 const CFGBlock *Dst,
                                                 const SourceManager &SM,
                                                 PathDiagnosticBuilder &PDB,
                                                 const LocationContext *LC) {
  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, LC);
      Start =
        PathDiagnosticLocation::createOperatorLoc(B, SM);
    } else {
      os << "true";
      Start = PathDiagnosticLocation(B->getLHS(), SM, LC);
      End = PDB.ExecutionContinues(N);
    }
  } else {
    assert(B->getOpcode() == BO_LOr);
    os << "||"
      << "' is ";

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

void generateMinimalDiagForBlockEdge(const ExplodedNode *N, BlockEdge BE,
                                     const SourceManager &SM,
                                     PathDiagnosticBuilder &PDB,
                                     PathDiagnostic &PD) {
  const LocationContext *LC = N->getLocationContext();
  const CFGBlock *Src = BE.getSrc();
  const CFGBlock *Dst = BE.getDst();
  const Stmt *T = Src->getTerminator();
  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 = PathDiagnosticLocation::getNextStmt(N))
      PD.getActivePath().push_front(generateDiagForGotoOP(S, PDB, Start));
    break;
  }

  case Stmt::SwitchStmtClass: {
    PD.getActivePath().push_front(
        generateDiagForSwitchOP(N, Dst, SM, LC, PDB, Start));
    break;
  }

  case Stmt::BreakStmtClass:
  case Stmt::ContinueStmtClass: {
    std::string sbuf;
    llvm::raw_string_ostream os(sbuf);
    PathDiagnosticLocation End = PDB.ExecutionContinues(os, N);
    PD.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 = PDB.ExecutionContinues(N);

    if (const Stmt *S = End.asStmt())
      End = PDB.getEnclosingStmtLocation(S);

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

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

    std::shared_ptr<PathDiagnosticControlFlowPiece> Diag =
        generateDiagForBinaryOP(N, T, Src, Dst, SM, PDB, LC);
    PD.getActivePath().push_front(Diag);
    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 = PDB.ExecutionContinues(os, N);

      if (const Stmt *S = End.asStmt())
        End = PDB.getEnclosingStmtLocation(S);

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

      if (const Stmt *S = End.asStmt())
        End = PDB.getEnclosingStmtLocation(S);

      PD.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 = PDB.ExecutionContinues(os, N);
      if (const Stmt *S = End.asStmt())
        End = PDB.getEnclosingStmtLocation(S);

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

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

    break;

  case Stmt::IfStmtClass: {
    PathDiagnosticLocation End = PDB.ExecutionContinues(N);

    if (const Stmt *S = End.asStmt())
      End = PDB.getEnclosingStmtLocation(S);

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

    break;
  }
  }
}

// Cone-of-influence: support the reverse propagation of "interesting" symbols
// and values by tracing interesting calculations backwards through evaluated
// expressions along a path.  This is probably overly complicated, but the idea
// is that if an expression computed an "interesting" value, the child
// expressions are are also likely to be "interesting" as well (which then
// propagates to the values they in turn compute).  This reverse propagation
// is needed to track interesting correlations across function call boundaries,
// where formal arguments bind to actual arguments, etc.  This is also needed
// because the constraint solver sometimes simplifies certain symbolic values
// into constants when appropriate, and this complicates reasoning about
// interesting values.
using InterestingExprs = llvm::DenseSet<const Expr *>;

static void reversePropagateIntererstingSymbols(BugReport &R,
                                                InterestingExprs &IE,
                                                const ProgramState *State,
                                                const Expr *Ex,
                                                const LocationContext *LCtx) {
  SVal V = State->getSVal(Ex, LCtx);
  if (!(R.isInteresting(V) || IE.count(Ex)))
    return;

  switch (Ex->getStmtClass()) {
    default:
      if (!isa<CastExpr>(Ex))
        break;
      // Fall through.
    case Stmt::BinaryOperatorClass:
    case Stmt::UnaryOperatorClass: {
      for (const Stmt *SubStmt : Ex->children()) {
        if (const auto *child = dyn_cast_or_null<Expr>(SubStmt)) {
          IE.insert(child);
          SVal ChildV = State->getSVal(child, LCtx);
          R.markInteresting(ChildV);
        }
      }
      break;
    }
  }

  R.markInteresting(V);
}

static void reversePropagateInterestingSymbols(BugReport &R,
                                               InterestingExprs &IE,
                                               const ProgramState *State,
                                               const LocationContext *CalleeCtx,
                                               const LocationContext *CallerCtx)
{
  // FIXME: Handle non-CallExpr-based CallEvents.
  const StackFrameContext *Callee = CalleeCtx->getStackFrame();
  const Stmt *CallSite = Callee->getCallSite();
  if (const auto *CE = dyn_cast_or_null<CallExpr>(CallSite)) {
    if (const auto *FD = dyn_cast<FunctionDecl>(CalleeCtx->getDecl())) {
      FunctionDecl::param_const_iterator PI = FD->param_begin(),
                                         PE = FD->param_end();
      CallExpr::const_arg_iterator AI = CE->arg_begin(), AE = CE->arg_end();
      for (; AI != AE && PI != PE; ++AI, ++PI) {
        if (const Expr *ArgE = *AI) {
          if (const ParmVarDecl *PD = *PI) {
            Loc LV = State->getLValue(PD, CalleeCtx);
            if (R.isInteresting(LV) || R.isInteresting(State->getRawSVal(LV)))
              IE.insert(ArgE);
          }
        }
      }
    }
  }
}

//===----------------------------------------------------------------------===//
// 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(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(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(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,
                          const LocationContext *LC) {
  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;
}

static const char StrEnteringLoop[] = "Entering loop body";
static const char StrLoopBodyZero[] = "Loop body executed 0 times";
static const char StrLoopRangeEmpty[] =
  "Loop body skipped when range is empty";
static const char StrLoopCollectionEmpty[] =
  "Loop body skipped when collection is empty";

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

/// Generate diagnostics for the node \p N,
/// and write it into \p PD.
/// \p AddPathEdges Whether diagnostic consumer can generate path arrows
/// showing both row and column.
static void generatePathDiagnosticsForNode(const ExplodedNode *N,
      PathDiagnostic &PD,
      PathDiagnosticLocation &PrevLoc,
      PathDiagnosticBuilder &PDB,
      LocationContextMap &LCM,
      StackDiagVector &CallStack,
      InterestingExprs &IE,
      bool AddPathEdges) {
  ProgramPoint P = N->getLocation();
  const SourceManager& SM = PDB.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 (AddPathEdges) {
      // 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(PD.getActivePath(), PrevLoc,
            PathDiagnosticLocation::createBegin(D, SM), CalleeLC);
    }

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

    PathDiagnosticCallPiece *C;
    if (VisitedEntireCall) {
      C = cast<PathDiagnosticCallPiece>(PD.getActivePath().front().get());
    } else {
      const Decl *Caller = CE->getLocationContext()->getDecl();
      C = PathDiagnosticCallPiece::construct(PD.getActivePath(), Caller);

      if (AddPathEdges) {
        // Since we just transferred the path over to the call piece,
        // reset the mapping from active to location context.
        assert(PD.getActivePath().size() == 1 &&
            PD.getActivePath().front().get() == C);
        LCM[&PD.getActivePath()] = nullptr;
      }

      // Record the location context mapping for the path within
      // the call.
      assert(LCM[&C->path] == nullptr ||
          LCM[&C->path] == CE->getCalleeContext());
      LCM[&C->path] = CE->getCalleeContext();

      // If this is the first item in the active path, record
      // the new mapping from active path to location context.
      const LocationContext *&NewLC = LCM[&PD.getActivePath()];
      if (!NewLC)
        NewLC = N->getLocationContext();

      PDB.LC = NewLC;
    }
    C->setCallee(*CE, SM);

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

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


  if (AddPathEdges) {
    // Query the location context here and the previous location
    // as processing CallEnter may change the active path.
    PDB.LC = N->getLocationContext();

    // Record the mapping from the active path to the location
    // context.
    assert(!LCM[&PD.getActivePath()] || LCM[&PD.getActivePath()] == PDB.LC);
    LCM[&PD.getActivePath()] = PDB.LC;
  }

  // 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 C = PathDiagnosticCallPiece::construct(N, *CE, SM);
    // Record the mapping from call piece to LocationContext.
    LCM[&C->path] = CE->getCalleeContext();

    if (AddPathEdges) {
      const Stmt *S = CE->getCalleeContext()->getCallSite();
      // Propagate the interesting symbols accordingly.
      if (const auto *Ex = dyn_cast_or_null<Expr>(S)) {
        reversePropagateIntererstingSymbols(*PDB.getBugReport(), IE,
            N->getState().get(), Ex,
            N->getLocationContext());
      }
      // Add the edge to the return site.
      addEdgeToPath(PD.getActivePath(), PrevLoc, C->callReturn, PDB.LC);
      PrevLoc.invalidate();
    }

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

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

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

    // For expressions, make sure we propagate the
    // interesting symbols correctly.
    if (const Expr *Ex = PS->getStmtAs<Expr>())
      reversePropagateIntererstingSymbols(*PDB.getBugReport(), IE,
          N->getState().get(), Ex,
          N->getLocationContext());

    // 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, PDB.LC);
      addEdgeToPath(PD.getActivePath(), PrevLoc, L, PDB.LC);
    }

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

    if (!AddPathEdges) {
      generateMinimalDiagForBlockEdge(N, *BE, SM, PDB, PD);
      return;
    }

    // Does this represent entering a call?  If so, look at propagating
    // interesting symbols across call boundaries.
    if (const ExplodedNode *NextNode = N->getFirstPred()) {
      const LocationContext *CallerCtx = NextNode->getLocationContext();
      const LocationContext *CalleeCtx = PDB.LC;
      if (CallerCtx != CalleeCtx && AddPathEdges) {
        reversePropagateInterestingSymbols(*PDB.getBugReport(), IE,
            N->getState().get(),
            CalleeCtx, CallerCtx);
      }
    }

    // Are we jumping to the head of a loop?  Add a special diagnostic.
    if (const Stmt *Loop = BE->getSrc()->getLoopTarget()) {
      PathDiagnosticLocation L(Loop, SM, PDB.LC);
      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(PD.getActivePath(), PrevLoc, p->getLocation(), PDB.LC);
      PD.getActivePath().push_front(std::move(p));

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

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

    if (const Stmt *Term = BSrc->getTerminator()) {
      // 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, N), Term);

        const char *str = nullptr;

        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) {
          PathDiagnosticLocation L(TermCond ? TermCond : Term, SM, PDB.LC);
          auto PE = std::make_shared<PathDiagnosticEventPiece>(L, str);
          PE->setPrunable(true);
          addEdgeToPath(PD.getActivePath(), PrevLoc,
              PE->getLocation(), PDB.LC);
          PD.getActivePath().push_front(std::move(PE));
        }
      } else if (isa<BreakStmt>(Term) || isa<ContinueStmt>(Term) ||
          isa<GotoStmt>(Term)) {
        PathDiagnosticLocation L(Term, SM, PDB.LC);
        addEdgeToPath(PD.getActivePath(), PrevLoc, L, PDB.LC);
      }
    }
  }
}

static std::unique_ptr<PathDiagnostic>
generateEmptyDiagnosticForReport(BugReport *R, SourceManager &SM) {
  BugType &BT = R->getBugType();
  return llvm::make_unique<PathDiagnostic>(
      R->getBugType().getCheckName(), R->getDeclWithIssue(),
      R->getBugType().getName(), R->getDescription(),
      R->getShortDescription(/*Fallback=*/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<ExprWithCleanups>(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, SourceManager &SM,
                            const ParentMap &PM, const LocationContext *LCtx) {
  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, SM, PM, LCtx,
                                                /*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, SM, PM, LCtx, /*allowNested=*/true);
      if (!DstContext.isValid() || DstContext.asStmt() == Dst)
        break;

      // If the source is in the same context, we're already good.
      if (std::find(SrcContexts.begin(), SrcContexts.end(), 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(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(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, SourceManager &SM,
                                ParentMap &PM) {
  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(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, SourceManager &SM,
                            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->getLocStart();
    SourceLocation SecondLoc = end->getLocStart();

    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(PathPieces &path, SourceManager &SM,
                          OptimizedCallsSet &OCS,
                          LocationContextMap &LCM) {
  bool hasChanges = false;
  const LocationContext *LC = LCM[&path];
  assert(LC);
  ParentMap &PM = LC->getParentMap();

  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(CallI->path, SM, OCS, LCM)) {}
        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, SM, PM, LC);
    // Remove "cyclical" edges that include one or more context edges.
    removeContextCycles(path, SM, PM);
    // 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(PathPieces &Path, LocationContextMap &LCM,
                                  SourceManager &SM) {
  const auto *FirstEdge =
      dyn_cast<PathDiagnosticControlFlowPiece>(Path.front().get());
  if (!FirstEdge)
    return;

  const Decl *D = LCM[&Path]->getDecl();
  PathDiagnosticLocation EntryLoc = PathDiagnosticLocation::createBegin(D, SM);
  if (FirstEdge->getStartLocation() != EntryLoc)
    return;

  Path.pop_front();
}

using VisitorsDiagnosticsTy = llvm::DenseMap<const ExplodedNode *,
                   std::vector<std::shared_ptr<PathDiagnosticPiece>>>;

/// 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 (\p ActiveScheme is Extensive),
/// the path is modified to insert artificially generated
/// edges.
/// Otherwise, more detailed diagnostics is emitted for block edges, explaining
/// the transitions in words.
static std::unique_ptr<PathDiagnostic> generatePathDiagnosticForConsumer(
    PathDiagnosticConsumer::PathGenerationScheme ActiveScheme,
    PathDiagnosticBuilder &PDB,
    const ExplodedNode *ErrorNode,
    const VisitorsDiagnosticsTy &VisitorsDiagnostics) {

  bool GenerateDiagnostics = (ActiveScheme != PathDiagnosticConsumer::None);
  bool AddPathEdges = (ActiveScheme == PathDiagnosticConsumer::Extensive);
  SourceManager &SM = PDB.getSourceManager();
  BugReport *R = PDB.getBugReport();
  AnalyzerOptions &Opts = PDB.getBugReporter().getAnalyzerOptions();
  StackDiagVector CallStack;
  InterestingExprs IE;
  LocationContextMap LCM;
  std::unique_ptr<PathDiagnostic> PD = generateEmptyDiagnosticForReport(R, SM);

  if (GenerateDiagnostics) {
    auto EndNotes = VisitorsDiagnostics.find(ErrorNode);
    std::shared_ptr<PathDiagnosticPiece> LastPiece;
    if (EndNotes != VisitorsDiagnostics.end()) {
      assert(!EndNotes->second.empty());
      LastPiece = EndNotes->second[0];
    } else {
      LastPiece = BugReporterVisitor::getDefaultEndPath(PDB, ErrorNode, *R);
    }
    PD->setEndOfPath(LastPiece);
  }

  PathDiagnosticLocation PrevLoc = PD->getLocation();
  const ExplodedNode *NextNode = ErrorNode->getFirstPred();
  while (NextNode) {
    if (GenerateDiagnostics)
      generatePathDiagnosticsForNode(
          NextNode, *PD, PrevLoc, PDB, LCM, CallStack, IE, AddPathEdges);

    auto VisitorNotes = VisitorsDiagnostics.find(NextNode);
    NextNode = NextNode->getFirstPred();
    if (!GenerateDiagnostics || 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 auto &Note : VisitorNotes->second) {
      llvm::FoldingSetNodeID ID;
      Note->Profile(ID);
      auto P = DeduplicationSet.insert(ID);
      if (!P.second)
        continue;

      if (AddPathEdges)
        addEdgeToPath(PD->getActivePath(), PrevLoc, Note->getLocation(),
                      PDB.LC);
      updateStackPiecesWithMessage(*Note, CallStack);
      PD->getActivePath().push_front(Note);
    }
  }

  if (AddPathEdges) {
    // 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 = PDB.LC->getStackFrame();
    const Decl *D = CalleeLC->getDecl();
    addEdgeToPath(PD->getActivePath(), PrevLoc,
                  PathDiagnosticLocation::createBegin(D, SM), CalleeLC);
  }

  if (!AddPathEdges && GenerateDiagnostics)
    CompactPathDiagnostic(PD->getMutablePieces(), SM);

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

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

    if (AddPathEdges) {

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

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

    // 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(PD->getMutablePieces());
    removeEdgesToDefaultInitializers(PD->getMutablePieces());
  }
  return PD;
}


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

void BugType::anchor() {}

void BugType::FlushReports(BugReporter &BR) {}

void BuiltinBug::anchor() {}

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

void BugReport::NodeResolver::anchor() {}

void BugReport::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 BugReport::clearVisitors() {
  Callbacks.clear();
}

BugReport::~BugReport() {
  while (!interestingSymbols.empty()) {
    popInterestingSymbolsAndRegions();
  }
}

const Decl *BugReport::getDeclWithIssue() const {
  if (DeclWithIssue)
    return DeclWithIssue;

  const ExplodedNode *N = getErrorNode();
  if (!N)
    return nullptr;

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

void BugReport::Profile(llvm::FoldingSetNodeID& hash) const {
  hash.AddPointer(&BT);
  hash.AddString(Description);
  PathDiagnosticLocation UL = getUniqueingLocation();
  if (UL.isValid()) {
    UL.Profile(hash);
  } else if (Location.isValid()) {
    Location.Profile(hash);
  } else {
    assert(ErrorNode);
    hash.AddPointer(GetCurrentOrPreviousStmt(ErrorNode));
  }

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

void BugReport::markInteresting(SymbolRef sym) {
  if (!sym)
    return;

  getInterestingSymbols().insert(sym);

  if (const auto *meta = dyn_cast<SymbolMetadata>(sym))
    getInterestingRegions().insert(meta->getRegion());
}

void BugReport::markInteresting(const MemRegion *R) {
  if (!R)
    return;

  R = R->getBaseRegion();
  getInterestingRegions().insert(R);

  if (const auto *SR = dyn_cast<SymbolicRegion>(R))
    getInterestingSymbols().insert(SR->getSymbol());
}

void BugReport::markInteresting(SVal V) {
  markInteresting(V.getAsRegion());
  markInteresting(V.getAsSymbol());
}

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

bool BugReport::isInteresting(SVal V) {
  return isInteresting(V.getAsRegion()) || isInteresting(V.getAsSymbol());
}

bool BugReport::isInteresting(SymbolRef sym) {
  if (!sym)
    return false;
  // We don't currently consider metadata symbols to be interesting
  // even if we know their region is interesting. Is that correct behavior?
  return getInterestingSymbols().count(sym);
}

bool BugReport::isInteresting(const MemRegion *R) {
  if (!R)
    return false;
  R = R->getBaseRegion();
  bool b = getInterestingRegions().count(R);
  if (b)
    return true;
  if (const auto *SR = dyn_cast<SymbolicRegion>(R))
    return getInterestingSymbols().count(SR->getSymbol());
  return false;
}

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

void BugReport::lazyInitializeInterestingSets() {
  if (interestingSymbols.empty()) {
    interestingSymbols.push_back(new Symbols());
    interestingRegions.push_back(new Regions());
  }
}

BugReport::Symbols &BugReport::getInterestingSymbols() {
  lazyInitializeInterestingSets();
  return *interestingSymbols.back();
}

BugReport::Regions &BugReport::getInterestingRegions() {
  lazyInitializeInterestingSets();
  return *interestingRegions.back();
}

void BugReport::pushInterestingSymbolsAndRegions() {
  interestingSymbols.push_back(new Symbols(getInterestingSymbols()));
  interestingRegions.push_back(new Regions(getInterestingRegions()));
}

void BugReport::popInterestingSymbolsAndRegions() {
  delete interestingSymbols.pop_back_val();
  delete interestingRegions.pop_back_val();
}

const Stmt *BugReport::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 = GetPreviousStmt(ErrorNode);
  }
  if (!S)
    S = PathDiagnosticLocation::getStmt(ErrorNode);

  return S;
}

llvm::iterator_range<BugReport::ranges_iterator> BugReport::getRanges() {
  // If no custom ranges, add the range of the statement corresponding to
  // the error node.
  if (Ranges.empty()) {
    if (const auto *E = dyn_cast_or_null<Expr>(getStmt()))
      addRange(E->getSourceRange());
    else
      return llvm::make_range(ranges_iterator(), ranges_iterator());
  }

  // User-specified absence of range info.
  if (Ranges.size() == 1 && !Ranges.begin()->isValid())
    return llvm::make_range(ranges_iterator(), ranges_iterator());

  return llvm::make_range(Ranges.begin(), Ranges.end());
}

PathDiagnosticLocation BugReport::getLocation(const SourceManager &SM) const {
  if (ErrorNode) {
    assert(!Location.isValid() &&
     "Either Location or ErrorNode should be specified but not both.");
    return PathDiagnosticLocation::createEndOfPath(ErrorNode, SM);
  }

  assert(Location.isValid());
  return Location;
}

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

BugReportEquivClass::~BugReportEquivClass() = default;

GRBugReporter::~GRBugReporter() = default;

BugReporterData::~BugReporterData() = default;

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

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

BugReporter::~BugReporter() {
  FlushReports();

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

void BugReporter::FlushReports() {
  if (BugTypes.isEmpty())
    return;

  // First flush the warnings for each BugType.  This may end up creating new
  // warnings and new BugTypes.
  // FIXME: Only NSErrorChecker needs BugType's FlushReports.
  // Turn NSErrorChecker into a proper checker and remove this.
  SmallVector<const BugType *, 16> bugTypes(BugTypes.begin(), BugTypes.end());
  for (const auto I : bugTypes)
    const_cast<BugType*>(I)->FlushReports(*this);

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

  // Remove all references to the BugType objects.
  BugTypes = F.getEmptySet();
}

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

namespace {

/// A wrapper around a report graph, which contains only a single path, and its
/// node maps.
class ReportGraph {
public:
  InterExplodedGraphMap BackMap;
  std::unique_ptr<ExplodedGraph> Graph;
  const ExplodedNode *ErrorNode;
  size_t Index;
};

/// A wrapper around a trimmed graph and its node maps.
class TrimmedGraph {
  InterExplodedGraphMap InverseMap;

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

  PriorityMapTy PriorityMap;

  using NodeIndexPair = std::pair<const ExplodedNode *, size_t>;

  SmallVector<NodeIndexPair, 32> ReportNodes;

  std::unique_ptr<ExplodedGraph> G;

  /// 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 NodeIndexPair &LHS, const NodeIndexPair &RHS) const {
      return (*this)(LHS.first, RHS.first);
    }
  };

public:
  TrimmedGraph(const ExplodedGraph *OriginalGraph,
               ArrayRef<const ExplodedNode *> Nodes);

  bool popNextReportGraph(ReportGraph &GraphWrapper);
};

} // namespace

TrimmedGraph::TrimmedGraph(const ExplodedGraph *OriginalGraph,
                           ArrayRef<const ExplodedNode *> Nodes) {
  // The trimmed graph is created in the body of the constructor to ensure
  // that the DenseMaps have been initialized already.
  InterExplodedGraphMap ForwardMap;
  G = OriginalGraph->trim(Nodes, &ForwardMap, &InverseMap);

  // 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 (unsigned i = 0, count = Nodes.size(); i < count; ++i) {
    if (const ExplodedNode *NewNode = ForwardMap.lookup(Nodes[i])) {
      ReportNodes.push_back(std::make_pair(NewNode, i));
      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(G->num_roots() == 1);
  WS.push(*G->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(std::make_pair(Node, Priority));
    ++Priority;

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

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

    for (ExplodedNode::const_pred_iterator I = Node->succ_begin(),
                                           E = Node->succ_end();
         I != E; ++I)
      WS.push(*I);
  }

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

bool TrimmedGraph::popNextReportGraph(ReportGraph &GraphWrapper) {
  if (ReportNodes.empty())
    return false;

  const ExplodedNode *OrigN;
  std::tie(OrigN, GraphWrapper.Index) = 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 = llvm::make_unique<ExplodedGraph>();
  GraphWrapper.BackMap.clear();

  // 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->isSink());

    // Store the mapping to the original node.
    InterExplodedGraphMap::const_iterator IMitr = InverseMap.find(OrigN);
    assert(IMitr != InverseMap.end() && "No mapping to original node.");
    GraphWrapper.BackMap[NewN] = IMitr->second;

    // Link up the new node with the previous node.
    if (Succ)
      Succ->addPredecessor(NewN, *GNew);
    else
      GraphWrapper.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));
  }

  GraphWrapper.Graph = std::move(GNew);

  return true;
}

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

  using PiecesTy = std::vector<std::shared_ptr<PathDiagnosticPiece>>;

  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)) {
      CompactPathDiagnostic(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(BugReport *R, const ExplodedNode *ErrorNode,
                            BugReporterContext &BRC) {
  auto Notes = llvm::make_unique<VisitorsDiagnosticsTy>();
  BugReport::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.
    for (BugReport::visitor_iterator I = R->visitor_begin(),
                                     E = R->visitor_end();
         I != E; ++I) {
      visitors.push_back(std::move(*I));
    }
    R->clearVisitors();

    const ExplodedNode *Pred = NextNode->getFirstPred();
    if (!Pred) {
      std::shared_ptr<PathDiagnosticPiece> 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.");
          LastPiece = std::move(Piece);
          (*Notes)[ErrorNode].push_back(LastPiece);
        }
      }
      break;
    }

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

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

    NextNode = Pred;
  }

  return Notes;
}

/// Find a non-invalidated report for a given equivalence class,
/// and return together with a cache of visitors notes.
/// If none found, return a nullptr paired with an empty cache.
static
std::pair<BugReport*, std::unique_ptr<VisitorsDiagnosticsTy>> findValidReport(
  TrimmedGraph &TrimG,
  ReportGraph &ErrorGraph,
  ArrayRef<BugReport *> &bugReports,
  AnalyzerOptions &Opts,
  GRBugReporter &Reporter) {

  while (TrimG.popNextReportGraph(ErrorGraph)) {
    // Find the BugReport with the original location.
    assert(ErrorGraph.Index < bugReports.size());
    BugReport *R = bugReports[ErrorGraph.Index];
    assert(R && "No original report found for sliced graph.");
    assert(R->isValid() && "Report selected by trimmed graph marked invalid.");
    const ExplodedNode *ErrorNode = ErrorGraph.ErrorNode;

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

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

    BugReporterContext BRC(Reporter, ErrorGraph.BackMap);

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

    if (R->isValid()) {
      if (Opts.shouldCrosscheckWithZ3()) {
        // If crosscheck is enabled, remove all visitors, add the refutation
        // visitor and check again
        R->clearVisitors();
        R->addVisitor(llvm::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, ErrorGraph.ErrorNode, BRC);
      }

      // Check if the bug is still valid
      if (R->isValid())
        return std::make_pair(R, std::move(visitorNotes));
    }
  }

  return std::make_pair(nullptr, llvm::make_unique<VisitorsDiagnosticsTy>());
}

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

  auto Out = llvm::make_unique<DiagnosticForConsumerMapTy>();
  bool HasValid = false;
  SmallVector<const ExplodedNode *, 32> errorNodes;
  for (const auto I : bugReports) {
    if (I->isValid()) {
      HasValid = true;
      errorNodes.push_back(I->getErrorNode());
    } else {
      // Keep the errorNodes list in sync with the bugReports list.
      errorNodes.push_back(nullptr);
    }
  }

  // If all the reports have been marked invalid by a previous path generation,
  // we're done.
  if (!HasValid)
    return Out;

  TrimmedGraph TrimG(&getGraph(), errorNodes);
  ReportGraph ErrorGraph;
  auto ReportInfo = findValidReport(TrimG, ErrorGraph, bugReports,
                  getAnalyzerOptions(), *this);
  BugReport *R = ReportInfo.first;

  if (R && R->isValid()) {
    const ExplodedNode *ErrorNode = ErrorGraph.ErrorNode;
    for (PathDiagnosticConsumer *PC : consumers) {
      PathDiagnosticBuilder PDB(*this, R, ErrorGraph.BackMap, PC);
      std::unique_ptr<PathDiagnostic> PD = generatePathDiagnosticForConsumer(
          PC->getGenerationScheme(), PDB, ErrorNode, *ReportInfo.second);
      (*Out)[PC] = std::move(PD);
    }
  }

  return Out;
}

void BugReporter::Register(BugType *BT) {
  BugTypes = F.add(BugTypes, BT);
}

void BugReporter::emitReport(std::unique_ptr<BugReport> R) {
  if (const ExplodedNode *E = R->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;
  }

  bool ValidSourceLoc = R->getLocation(getSourceManager()).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.
  BugType& BT = R->getBugType();
  Register(&BT);
  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));
}

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

static const CFGBlock *findBlockForNode(const ExplodedNode *N) {
  ProgramPoint P = N->getLocation();
  if (auto BEP = P.getAs<BlockEntrance>())
    return BEP->getBlock();

  // Find the node's current statement in the CFG.
  if (const Stmt *S = PathDiagnosticLocation::getStmt(N))
    return N->getLocationContext()->getAnalysisDeclContext()
                                  ->getCFGStmtMap()->getBlock(S);

  return nullptr;
}

// Returns true if by simply looking at the block, we can be sure that it
// results in a sink during analysis. This is useful to know when the analysis
// was interrupted, and we try to figure out if it would sink eventually.
// There may be many more reasons why a sink would appear during analysis
// (eg. checkers may generate sinks arbitrarily), but here we only consider
// sinks that would be obvious by looking at the CFG.
static bool isImmediateSinkBlock(const CFGBlock *Blk) {
  if (Blk->hasNoReturnElement())
    return true;

  // FIXME: Throw-expressions are currently generating sinks during analysis:
  // they're not supported yet, and also often used for actually terminating
  // the program. So we should treat them as sinks in this analysis as well,
  // at least for now, but once we have better support for exceptions,
  // we'd need to carefully handle the case when the throw is being
  // immediately caught.
  if (std::any_of(Blk->begin(), Blk->end(), [](const CFGElement &Elm) {
        if (Optional<CFGStmt> StmtElm = Elm.getAs<CFGStmt>())
          if (isa<CXXThrowExpr>(StmtElm->getStmt()))
            return true;
        return false;
      }))
    return true;

  return false;
}

// Returns true if by looking at the CFG surrounding the node's program
// point, we can be sure that any analysis starting from this point would
// eventually end with a sink. We scan the child CFG blocks in a depth-first
// manner and see if all paths eventually end up in an immediate sink block.
static bool isInevitablySinking(const ExplodedNode *N) {
  const CFG &Cfg = N->getCFG();

  const CFGBlock *StartBlk = findBlockForNode(N);
  if (!StartBlk)
    return false;
  if (isImmediateSinkBlock(StartBlk))
    return true;

  llvm::SmallVector<const CFGBlock *, 32> DFSWorkList;
  llvm::SmallPtrSet<const CFGBlock *, 32> Visited;

  DFSWorkList.push_back(StartBlk);
  while (!DFSWorkList.empty()) {
    const CFGBlock *Blk = DFSWorkList.back();
    DFSWorkList.pop_back();
    Visited.insert(Blk);

    for (const auto &Succ : Blk->succs()) {
      if (const CFGBlock *SuccBlk = Succ.getReachableBlock()) {
        if (SuccBlk == &Cfg.getExit()) {
          // If at least one path reaches the CFG exit, it means that control is
          // returned to the caller. For now, say that we are not sure what
          // happens next. If necessary, this can be improved to analyze
          // the parent StackFrameContext's call site in a similar manner.
          return false;
        }

        if (!isImmediateSinkBlock(SuccBlk) && !Visited.count(SuccBlk)) {
          // If the block has reachable child blocks that aren't no-return,
          // add them to the worklist.
          DFSWorkList.push_back(SuccBlk);
        }
      }
    }
  }

  // Nothing reached the exit. It can only mean one thing: there's no return.
  return true;
}

static BugReport *
FindReportInEquivalenceClass(BugReportEquivClass& EQ,
                             SmallVectorImpl<BugReport*> &bugReports) {
  BugReportEquivClass::iterator I = EQ.begin(), E = EQ.end();
  assert(I != E);
  BugType& BT = I->getBugType();

  // 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.
  if (!BT.isSuppressOnSink()) {
    BugReport *R = &*I;
    for (auto &I : EQ) {
      const ExplodedNode *N = I.getErrorNode();
      if (N) {
        R = &I;
        bugReports.push_back(R);
      }
    }
    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 (; I != E; ++I) {
    const ExplodedNode *errorNode = I->getErrorNode();

    if (!errorNode)
      continue;
    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(&*I);
      if (!exampleReport)
        exampleReport = &*I;
      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 (isInevitablySinking(errorNode))
      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(&*I);
            if (!exampleReport)
              exampleReport = &*I;
            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(getSourceManager());
      auto piece = llvm::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);
    }

    // Get the meta data.
    const BugReport::ExtraTextList &Meta = report->getExtraText();
    for (const auto &i : Meta)
      PD->addMeta(i);

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

/// Insert all lines participating in the function signature \p Signature
/// into \p ExecutedLines.
static void populateExecutedLinesWithFunctionSignature(
    const Decl *Signature, SourceManager &SM,
    std::unique_ptr<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();
  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->operator[](FID.getHashValue()).insert(Line);
}

static void populateExecutedLinesWithStmt(
    const Stmt *S, SourceManager &SM,
    std::unique_ptr<FilesToLineNumsMap> &ExecutedLines) {
  SourceLocation Loc = S->getSourceRange().getBegin();
  SourceLocation ExpansionLoc = SM.getExpansionLoc(Loc);
  FileID FID = SM.getFileID(ExpansionLoc);
  unsigned LineNo = SM.getExpansionLineNumber(ExpansionLoc);
  ExecutedLines->operator[](FID.getHashValue()).insert(LineNo);
}

/// \return all executed lines including function signatures on the path
/// starting from \p N.
static std::unique_ptr<FilesToLineNumsMap>
findExecutedLines(SourceManager &SM, const ExplodedNode *N) {
  auto ExecutedLines = llvm::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 = PathDiagnosticLocation::getStmt(N)) {
      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 *report, ArrayRef<PathDiagnosticConsumer *> consumers,
    ArrayRef<BugReport *> bugReports) {

  if (!report->isPathSensitive()) {
    auto Out = llvm::make_unique<DiagnosticForConsumerMapTy>();
    for (auto *Consumer : consumers)
      (*Out)[Consumer] = generateEmptyDiagnosticForReport(report,
                                                          getSourceManager());
    return Out;
  }

  // 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());
  std::unique_ptr<DiagnosticForConsumerMapTy> Out =
    generatePathDiagnostics(consumers, bugReports);

  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.
  AnalyzerOptions &Opts = getAnalyzerOptions();
  for (auto const &P : *Out)
    if (Opts.shouldReportIssuesInMainSourceFile() && !Opts.AnalyzeAll)
      P.second->resetDiagnosticLocationToMainFile();

  return Out;
}

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

void BugReporter::EmitBasicReport(const Decl *DeclWithIssue,
                                  CheckName CheckName,
                                  StringRef name, StringRef category,
                                  StringRef str, PathDiagnosticLocation Loc,
                                  ArrayRef<SourceRange> Ranges) {
  // 'BT' is owned by BugReporter.
  BugType *BT = getBugTypeForName(CheckName, name, category);
  auto R = llvm::make_unique<BugReport>(*BT, str, Loc);
  R->setDeclWithIssue(DeclWithIssue);
  for (ArrayRef<SourceRange>::iterator I = Ranges.begin(), E = Ranges.end();
       I != E; ++I)
    R->addRange(*I);
  emitReport(std::move(R));
}

BugType *BugReporter::getBugTypeForName(CheckName 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;
}
