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

#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclBase.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/Expr.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/ParentMap.h"
#include "clang/AST/Stmt.h"
#include "clang/AST/StmtCXX.h"
#include "clang/AST/StmtObjC.h"
#include "clang/Analysis/AnalysisDeclContext.h"
#include "clang/Analysis/CFG.h"
#include "clang/Analysis/CFGStmtMap.h"
#include "clang/Analysis/PathDiagnostic.h"
#include "clang/Analysis/ProgramPoint.h"
#include "clang/Basic/LLVM.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/SourceManager.h"
#include "clang/StaticAnalyzer/Core/AnalyzerOptions.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitors.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
#include "clang/StaticAnalyzer/Core/Checker.h"
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
#include "clang/StaticAnalyzer/Core/CheckerRegistryData.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/SMTConv.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/StringExtras.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/iterator_range.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
#include <cassert>
#include <cstddef>
#include <iterator>
#include <memory>
#include <queue>
#include <string>
#include <tuple>
#include <utility>
#include <vector>

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

#define DEBUG_TYPE "BugReporter"

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

BugReporterVisitor::~BugReporterVisitor() = default;

void BugReporterContext::anchor() {}

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

namespace {

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  PathDiagnosticLocation
  ExecutionContinues(const PathDiagnosticConstruct &C) const;

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

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

} // namespace

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

StackHintGenerator::~StackHintGenerator() = default;

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

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

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

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

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

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

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

  return getMessageForSymbolNotFound();
}

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

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

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

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

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

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

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

  return nullptr;
}

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

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

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

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

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

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

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

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

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

  return containsSomethingInteresting;
}

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

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

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

    if (!Call)
      continue;

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

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

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

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

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

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

    I++;
  }
}

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

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

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

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

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

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

  const PathDiagnosticLocation &Loc = ExecutionContinues(C);

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

  return Loc;
}

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

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

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

  return nullptr;
}

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

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

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

    S = Parent;
  }

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

  return PathDiagnosticLocation(S, SMgr, LC);
}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  const SourceManager &SM = getSourceManager();

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

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

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

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

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

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

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

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

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

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

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

    PathDiagnosticLocation End = ExecutionContinues(C);

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    break;

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

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

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

    break;
  }
  }
}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    if (C.shouldAddControlNotes()) {
      generateMinimalDiagForBlockEdge(C, *BE);
    }

    if (!C.shouldAddPathEdges()) {
      return;
    }

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

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

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

      addEdgeToPath(C.getActivePath(), PrevLoc, p->getLocation());
      // We might've added a very similar control node already
      if (!C.shouldAddControlNotes()) {
        C.getActivePath().push_front(std::move(p));
      }

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

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

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

        StringRef str;

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

        if (!str.empty()) {
          PathDiagnosticLocation L(TermCond ? TermCond : Term, SM,
                                   C.getCurrLocationContext());
          auto PE = std::make_shared<PathDiagnosticEventPiece>(L, str);
          PE->setPrunable(true);
          addEdgeToPath(C.getActivePath(), PrevLoc, PE->getLocation());

          // We might've added a very similar control node already
          if (!C.shouldAddControlNotes()) {
            C.getActivePath().push_front(std::move(PE));
          }
        }
      } else if (isa<BreakStmt, ContinueStmt, GotoStmt>(Term)) {
        PathDiagnosticLocation L(Term, SM, C.getCurrLocationContext());
        addEdgeToPath(C.getActivePath(), PrevLoc, L);
      }
    }
  }
}

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

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

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

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

    if (!S)
      break;

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

    break;
  }

  return S;
}

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

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

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

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

    if (!Piece)
      continue;

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

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

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

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

      // If the source is in the same context, we're already good.
      if (llvm::is_contained(SrcContexts, DstContext))
        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, WhileStmt, IfStmt, ObjCForCollectionStmt,
             CXXForRangeStmt>(s1Start))
      continue;

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

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

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

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

  Optional<MemoryBufferRef> Buffer = SM.getBufferOrNone(FID);
  if (!Buffer)
    return None;

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

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

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

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

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

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

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

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

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

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

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

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

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

    ++I;
  }
}

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

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

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

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

    if (!PieceI)
      continue;

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

    if (!start || !end)
      continue;

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

    if (isConditionForTerminator(end, endParent))
      continue;

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

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

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

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

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

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

    if (!PieceI)
      continue;

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

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

    if (!PieceNextI)
      continue;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  return hasChanges;
}

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

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

  Path.pop_front();
}

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

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

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

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

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

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

  const SourceManager &SM = getSourceManager();
  const AnalyzerOptions &Opts = getAnalyzerOptions();

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

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

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

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

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

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

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

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


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

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

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

    if (PDC->shouldAddPathEdges()) {

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

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

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

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

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

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

void BugType::anchor() {}

void BuiltinBug::anchor() {}

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

LLVM_ATTRIBUTE_USED static bool
isDependency(const CheckerRegistryData &Registry, StringRef CheckerName) {
  for (const std::pair<StringRef, StringRef> &Pair : Registry.Dependencies) {
    if (Pair.second == CheckerName)
      return true;
  }
  return false;
}

LLVM_ATTRIBUTE_USED static bool isHidden(const CheckerRegistryData &Registry,
                                         StringRef CheckerName) {
  for (const CheckerInfo &Checker : Registry.Checkers) {
    if (Checker.FullName == CheckerName)
      return Checker.IsHidden;
  }
  llvm_unreachable(
      "Checker name not found in CheckerRegistry -- did you retrieve it "
      "correctly from CheckerManager::getCurrentCheckerName?");
}

PathSensitiveBugReport::PathSensitiveBugReport(
    const BugType &bt, StringRef shortDesc, StringRef desc,
    const ExplodedNode *errorNode, PathDiagnosticLocation LocationToUnique,
    const Decl *DeclToUnique)
    : BugReport(Kind::PathSensitive, bt, shortDesc, desc), ErrorNode(errorNode),
      ErrorNodeRange(getStmt() ? getStmt()->getSourceRange() : SourceRange()),
      UniqueingLocation(LocationToUnique), UniqueingDecl(DeclToUnique) {
  assert(!isDependency(ErrorNode->getState()
                           ->getAnalysisManager()
                           .getCheckerManager()
                           ->getCheckerRegistryData(),
                       bt.getCheckerName()) &&
         "Some checkers depend on this one! We don't allow dependency "
         "checkers to emit warnings, because checkers should depend on "
         "*modeling*, not *diagnostics*.");

  assert(
      (bt.getCheckerName().startswith("debug") ||
       !isHidden(ErrorNode->getState()
                     ->getAnalysisManager()
                     .getCheckerManager()
                     ->getCheckerRegistryData(),
                 bt.getCheckerName())) &&
          "Hidden checkers musn't emit diagnostics as they are by definition "
          "non-user facing!");
}

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

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

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

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

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

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

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

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

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

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

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

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

  if (Result.second)
    return;

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

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

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

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

  insertToInterestingnessMap(InterestingSymbols, sym, TKind);

  // FIXME: No tests exist for this code and it is questionable:
  // How to handle multiple metadata for the same region?
  if (const auto *meta = dyn_cast<SymbolMetadata>(sym))
    markInteresting(meta->getRegion(), TKind);
}

void PathSensitiveBugReport::markNotInteresting(SymbolRef sym) {
  if (!sym)
    return;
  InterestingSymbols.erase(sym);

  // The metadata part of markInteresting is not reversed here.
  // Just making the same region not interesting is incorrect
  // in specific cases.
  if (const auto *meta = dyn_cast<SymbolMetadata>(sym))
    markNotInteresting(meta->getRegion());
}

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

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

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

void PathSensitiveBugReport::markNotInteresting(const MemRegion *R) {
  if (!R)
    return;

  R = R->getBaseRegion();
  InterestingRegions.erase(R);

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  return S;
}

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

  return Ranges;
}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

namespace {

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

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

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

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

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

  BugPathInfo CurrentBugPath;

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

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

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

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

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

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

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

  BugPathInfo *getNextBugPath();
};

} // namespace

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    Succ = NewN;

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

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

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

  return &CurrentBugPath;
}

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

  using PiecesTy = std::vector<PathDiagnosticPieceRef>;

  MacroStackTy MacroStack;
  PiecesTy Pieces;

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

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

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

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

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

    assert(Loc.isMacroID());

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

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

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

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

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

      MacroStack.pop_back();
    }

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

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

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

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

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

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

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

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

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

    R->clearVisitors();

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

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

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

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

    NextNode = Pred;
  }

  return Notes;
}

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

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

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

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

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

    BugReporterContext BRC(Reporter);

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

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

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

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

  return {};
}

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

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

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

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

  return Out;
}

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

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

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

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

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

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

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

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

namespace {

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

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

} // namespace

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

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

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

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

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

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

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

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

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

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

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

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

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

  // See whether we need to silence the checker/package.
  for (const std::string &CheckerOrPackage :
       getAnalyzerOptions().SilencedCheckersAndPackages) {
    if (report->getBugType().getCheckerName().startswith(
            CheckerOrPackage))
      return;
  }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

      if (isa_and_nonnull<SwitchCase, LabelStmt>(P))
        populateExecutedLinesWithStmt(P, SM, *ExecutedLines);
    }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

      return;
    }
  }
}



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

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

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

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

  MaxValidBugClassSize.updateMax(bugReports.size());

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

  return Out;
}

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

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

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