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

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

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

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

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

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) {
  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->getBeginLoc();
    SourceLocation SecondLoc = end->getBeginLoc();

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

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

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

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

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

    if (!PieceI)
      continue;

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

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

    if (!PieceNextI)
      continue;

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

static bool optimizeEdges(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);
    // 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>>>;

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

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

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

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

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

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

    // 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.
    if (Blk == &Cfg.getExit())
      return false;

    for (const auto &Succ : Blk->succs()) {
      if (const CFGBlock *SuccBlk = Succ.getReachableBlock()) {
        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);

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

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

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

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

/// \return all executed lines including function signatures on the path
/// starting from \p N.
static std::unique_ptr<FilesToLineNumsMap>
findExecutedLines(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;
}
