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

#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclBase.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/Expr.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/ParentMap.h"
#include "clang/AST/Stmt.h"
#include "clang/AST/StmtCXX.h"
#include "clang/AST/StmtObjC.h"
#include "clang/Analysis/AnalysisDeclContext.h"
#include "clang/Analysis/CFG.h"
#include "clang/Analysis/CFGStmtMap.h"
#include "clang/Analysis/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 CompactMacroExpandedPieces(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 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;
      LLVM_FALLTHROUGH;
    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) {
  const 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<FullExpr>(S) ||
        isa<CXXBindTemporaryExpr>(S) ||
        isa<SubstNonTypeTemplateParmExpr>(S))
      continue;

    break;
  }

  return S;
}

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

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

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

/// Adds synthetic edges from top-level statements to their subexpressions.
///
/// This avoids a "swoosh" effect, where an edge from a top-level statement A
/// points to a sub-expression B.1 that's not at the start of B. In these cases,
/// we'd like to see an edge from A to B, then another one from B to B.1.
static void addContextEdges(PathPieces &pieces, 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 (llvm::find(SrcContexts, DstContext) != SrcContexts.end())
        break;

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

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

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

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

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

    if (!PieceI)
      continue;

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

    if (!s1Start || !s1End)
      continue;

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

    PathDiagnosticControlFlowPiece *PieceNextI = nullptr;

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

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

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

    if (!PieceNextI)
      continue;

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

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

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

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

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

/// Returns the number of bytes in the given (character-based) SourceRange.
///
/// If the locations in the range are not on the same line, returns None.
///
/// Note that this does not do a precise user-visible character or column count.
static Optional<size_t> getLengthOnSingleLine(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));
  }


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

  if (GenerateDiagnostics && Opts.ShouldDisplayMacroExpansions)
    CompactMacroExpandedPieces(PD->getMutablePieces(), SM);

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

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

  using PiecesTy = std::vector<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)) {
      CompactMacroExpandedPieces(call->path, SM);
    }

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

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

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

    assert(Loc.isMacroID());

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

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

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

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

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

      MacroStack.pop_back();
    }

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

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

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

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

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

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

/// Generate notes from all visitors.
/// Notes associated with {@code ErrorNode} are generated using
/// {@code getEndPath}, and the rest are generated with {@code VisitNode}.
static std::unique_ptr<VisitorsDiagnosticsTy>
generateVisitorsDiagnostics(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>());
    R->addVisitor(llvm::make_unique<TagVisitor>());

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