1//===- PathDiagnostic.cpp - Path-Specific Diagnostic Handling -------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9//  This file defines the PathDiagnostic-related interfaces.
10//
11//===----------------------------------------------------------------------===//
12
13#include "clang/Analysis/PathDiagnostic.h"
14#include "clang/AST/Decl.h"
15#include "clang/AST/DeclBase.h"
16#include "clang/AST/DeclCXX.h"
17#include "clang/AST/DeclObjC.h"
18#include "clang/AST/DeclTemplate.h"
19#include "clang/AST/Expr.h"
20#include "clang/AST/ExprCXX.h"
21#include "clang/AST/OperationKinds.h"
22#include "clang/AST/ParentMap.h"
23#include "clang/AST/PrettyPrinter.h"
24#include "clang/AST/Stmt.h"
25#include "clang/AST/Type.h"
26#include "clang/Analysis/AnalysisDeclContext.h"
27#include "clang/Analysis/CFG.h"
28#include "clang/Analysis/ProgramPoint.h"
29#include "clang/Basic/FileManager.h"
30#include "clang/Basic/LLVM.h"
31#include "clang/Basic/SourceLocation.h"
32#include "clang/Basic/SourceManager.h"
33#include "llvm/ADT/ArrayRef.h"
34#include "llvm/ADT/FoldingSet.h"
35#include "llvm/ADT/None.h"
36#include "llvm/ADT/Optional.h"
37#include "llvm/ADT/STLExtras.h"
38#include "llvm/ADT/SmallString.h"
39#include "llvm/ADT/SmallVector.h"
40#include "llvm/ADT/StringExtras.h"
41#include "llvm/ADT/StringRef.h"
42#include "llvm/Support/Casting.h"
43#include "llvm/Support/ErrorHandling.h"
44#include "llvm/Support/raw_ostream.h"
45#include <cassert>
46#include <cstring>
47#include <memory>
48#include <utility>
49#include <vector>
50
51using namespace clang;
52using namespace ento;
53
54static StringRef StripTrailingDots(StringRef s) {
55  for (StringRef::size_type i = s.size(); i != 0; --i)
56    if (s[i - 1] != '.')
57      return s.substr(0, i);
58  return {};
59}
60
61PathDiagnosticPiece::PathDiagnosticPiece(StringRef s,
62                                         Kind k, DisplayHint hint)
63    : str(StripTrailingDots(s)), kind(k), Hint(hint) {}
64
65PathDiagnosticPiece::PathDiagnosticPiece(Kind k, DisplayHint hint)
66    : kind(k), Hint(hint) {}
67
68PathDiagnosticPiece::~PathDiagnosticPiece() = default;
69
70PathDiagnosticEventPiece::~PathDiagnosticEventPiece() = default;
71
72PathDiagnosticCallPiece::~PathDiagnosticCallPiece() = default;
73
74PathDiagnosticControlFlowPiece::~PathDiagnosticControlFlowPiece() = default;
75
76PathDiagnosticMacroPiece::~PathDiagnosticMacroPiece() = default;
77
78PathDiagnosticNotePiece::~PathDiagnosticNotePiece() = default;
79
80PathDiagnosticPopUpPiece::~PathDiagnosticPopUpPiece() = default;
81
82void PathPieces::flattenTo(PathPieces &Primary, PathPieces &Current,
83                           bool ShouldFlattenMacros) const {
84  for (auto &Piece : *this) {
85    switch (Piece->getKind()) {
86    case PathDiagnosticPiece::Call: {
87      auto &Call = cast<PathDiagnosticCallPiece>(*Piece);
88      if (auto CallEnter = Call.getCallEnterEvent())
89        Current.push_back(std::move(CallEnter));
90      Call.path.flattenTo(Primary, Primary, ShouldFlattenMacros);
91      if (auto callExit = Call.getCallExitEvent())
92        Current.push_back(std::move(callExit));
93      break;
94    }
95    case PathDiagnosticPiece::Macro: {
96      auto &Macro = cast<PathDiagnosticMacroPiece>(*Piece);
97      if (ShouldFlattenMacros) {
98        Macro.subPieces.flattenTo(Primary, Primary, ShouldFlattenMacros);
99      } else {
100        Current.push_back(Piece);
101        PathPieces NewPath;
102        Macro.subPieces.flattenTo(Primary, NewPath, ShouldFlattenMacros);
103        // FIXME: This probably shouldn't mutate the original path piece.
104        Macro.subPieces = NewPath;
105      }
106      break;
107    }
108    case PathDiagnosticPiece::Event:
109    case PathDiagnosticPiece::ControlFlow:
110    case PathDiagnosticPiece::Note:
111    case PathDiagnosticPiece::PopUp:
112      Current.push_back(Piece);
113      break;
114    }
115  }
116}
117
118PathDiagnostic::~PathDiagnostic() = default;
119
120PathDiagnostic::PathDiagnostic(
121    StringRef CheckerName, const Decl *declWithIssue, StringRef bugtype,
122    StringRef verboseDesc, StringRef shortDesc, StringRef category,
123    PathDiagnosticLocation LocationToUnique, const Decl *DeclToUnique,
124    std::unique_ptr<FilesToLineNumsMap> ExecutedLines)
125    : CheckerName(CheckerName), DeclWithIssue(declWithIssue),
126      BugType(StripTrailingDots(bugtype)),
127      VerboseDesc(StripTrailingDots(verboseDesc)),
128      ShortDesc(StripTrailingDots(shortDesc)),
129      Category(StripTrailingDots(category)), UniqueingLoc(LocationToUnique),
130      UniqueingDecl(DeclToUnique), ExecutedLines(std::move(ExecutedLines)),
131      path(pathImpl) {}
132
133void PathDiagnosticConsumer::anchor() {}
134
135PathDiagnosticConsumer::~PathDiagnosticConsumer() {
136  // Delete the contents of the FoldingSet if it isn't empty already.
137  for (auto &Diag : Diags)
138    delete &Diag;
139}
140
141void PathDiagnosticConsumer::HandlePathDiagnostic(
142    std::unique_ptr<PathDiagnostic> D) {
143  if (!D || D->path.empty())
144    return;
145
146  // We need to flatten the locations (convert Stmt* to locations) because
147  // the referenced statements may be freed by the time the diagnostics
148  // are emitted.
149  D->flattenLocations();
150
151  // If the PathDiagnosticConsumer does not support diagnostics that
152  // cross file boundaries, prune out such diagnostics now.
153  if (!supportsCrossFileDiagnostics()) {
154    // Verify that the entire path is from the same FileID.
155    FileID FID;
156    const SourceManager &SMgr = D->path.front()->getLocation().getManager();
157    SmallVector<const PathPieces *, 5> WorkList;
158    WorkList.push_back(&D->path);
159    SmallString<128> buf;
160    llvm::raw_svector_ostream warning(buf);
161    warning << "warning: Path diagnostic report is not generated. Current "
162            << "output format does not support diagnostics that cross file "
163            << "boundaries. Refer to --analyzer-output for valid output "
164            << "formats\n";
165
166    while (!WorkList.empty()) {
167      const PathPieces &path = *WorkList.pop_back_val();
168
169      for (const auto &I : path) {
170        const PathDiagnosticPiece *piece = I.get();
171        FullSourceLoc L = piece->getLocation().asLocation().getExpansionLoc();
172
173        if (FID.isInvalid()) {
174          FID = SMgr.getFileID(L);
175        } else if (SMgr.getFileID(L) != FID) {
176          llvm::errs() << warning.str();
177          return;
178        }
179
180        // Check the source ranges.
181        ArrayRef<SourceRange> Ranges = piece->getRanges();
182        for (const auto &I : Ranges) {
183          SourceLocation L = SMgr.getExpansionLoc(I.getBegin());
184          if (!L.isFileID() || SMgr.getFileID(L) != FID) {
185            llvm::errs() << warning.str();
186            return;
187          }
188          L = SMgr.getExpansionLoc(I.getEnd());
189          if (!L.isFileID() || SMgr.getFileID(L) != FID) {
190            llvm::errs() << warning.str();
191            return;
192          }
193        }
194
195        if (const auto *call = dyn_cast<PathDiagnosticCallPiece>(piece))
196          WorkList.push_back(&call->path);
197        else if (const auto *macro = dyn_cast<PathDiagnosticMacroPiece>(piece))
198          WorkList.push_back(&macro->subPieces);
199      }
200    }
201
202    if (FID.isInvalid())
203      return; // FIXME: Emit a warning?
204  }
205
206  // Profile the node to see if we already have something matching it
207  llvm::FoldingSetNodeID profile;
208  D->Profile(profile);
209  void *InsertPos = nullptr;
210
211  if (PathDiagnostic *orig = Diags.FindNodeOrInsertPos(profile, InsertPos)) {
212    // Keep the PathDiagnostic with the shorter path.
213    // Note, the enclosing routine is called in deterministic order, so the
214    // results will be consistent between runs (no reason to break ties if the
215    // size is the same).
216    const unsigned orig_size = orig->full_size();
217    const unsigned new_size = D->full_size();
218    if (orig_size <= new_size)
219      return;
220
221    assert(orig != D.get());
222    Diags.RemoveNode(orig);
223    delete orig;
224  }
225
226  Diags.InsertNode(D.release());
227}
228
229static Optional<bool> comparePath(const PathPieces &X, const PathPieces &Y);
230
231static Optional<bool>
232compareControlFlow(const PathDiagnosticControlFlowPiece &X,
233                   const PathDiagnosticControlFlowPiece &Y) {
234  FullSourceLoc XSL = X.getStartLocation().asLocation();
235  FullSourceLoc YSL = Y.getStartLocation().asLocation();
236  if (XSL != YSL)
237    return XSL.isBeforeInTranslationUnitThan(YSL);
238  FullSourceLoc XEL = X.getEndLocation().asLocation();
239  FullSourceLoc YEL = Y.getEndLocation().asLocation();
240  if (XEL != YEL)
241    return XEL.isBeforeInTranslationUnitThan(YEL);
242  return None;
243}
244
245static Optional<bool> compareMacro(const PathDiagnosticMacroPiece &X,
246                                   const PathDiagnosticMacroPiece &Y) {
247  return comparePath(X.subPieces, Y.subPieces);
248}
249
250static Optional<bool> compareCall(const PathDiagnosticCallPiece &X,
251                                  const PathDiagnosticCallPiece &Y) {
252  FullSourceLoc X_CEL = X.callEnter.asLocation();
253  FullSourceLoc Y_CEL = Y.callEnter.asLocation();
254  if (X_CEL != Y_CEL)
255    return X_CEL.isBeforeInTranslationUnitThan(Y_CEL);
256  FullSourceLoc X_CEWL = X.callEnterWithin.asLocation();
257  FullSourceLoc Y_CEWL = Y.callEnterWithin.asLocation();
258  if (X_CEWL != Y_CEWL)
259    return X_CEWL.isBeforeInTranslationUnitThan(Y_CEWL);
260  FullSourceLoc X_CRL = X.callReturn.asLocation();
261  FullSourceLoc Y_CRL = Y.callReturn.asLocation();
262  if (X_CRL != Y_CRL)
263    return X_CRL.isBeforeInTranslationUnitThan(Y_CRL);
264  return comparePath(X.path, Y.path);
265}
266
267static Optional<bool> comparePiece(const PathDiagnosticPiece &X,
268                                   const PathDiagnosticPiece &Y) {
269  if (X.getKind() != Y.getKind())
270    return X.getKind() < Y.getKind();
271
272  FullSourceLoc XL = X.getLocation().asLocation();
273  FullSourceLoc YL = Y.getLocation().asLocation();
274  if (XL != YL)
275    return XL.isBeforeInTranslationUnitThan(YL);
276
277  if (X.getString() != Y.getString())
278    return X.getString() < Y.getString();
279
280  if (X.getRanges().size() != Y.getRanges().size())
281    return X.getRanges().size() < Y.getRanges().size();
282
283  const SourceManager &SM = XL.getManager();
284
285  for (unsigned i = 0, n = X.getRanges().size(); i < n; ++i) {
286    SourceRange XR = X.getRanges()[i];
287    SourceRange YR = Y.getRanges()[i];
288    if (XR != YR) {
289      if (XR.getBegin() != YR.getBegin())
290        return SM.isBeforeInTranslationUnit(XR.getBegin(), YR.getBegin());
291      return SM.isBeforeInTranslationUnit(XR.getEnd(), YR.getEnd());
292    }
293  }
294
295  switch (X.getKind()) {
296    case PathDiagnosticPiece::ControlFlow:
297      return compareControlFlow(cast<PathDiagnosticControlFlowPiece>(X),
298                                cast<PathDiagnosticControlFlowPiece>(Y));
299    case PathDiagnosticPiece::Macro:
300      return compareMacro(cast<PathDiagnosticMacroPiece>(X),
301                          cast<PathDiagnosticMacroPiece>(Y));
302    case PathDiagnosticPiece::Call:
303      return compareCall(cast<PathDiagnosticCallPiece>(X),
304                         cast<PathDiagnosticCallPiece>(Y));
305    case PathDiagnosticPiece::Event:
306    case PathDiagnosticPiece::Note:
307    case PathDiagnosticPiece::PopUp:
308      return None;
309  }
310  llvm_unreachable("all cases handled");
311}
312
313static Optional<bool> comparePath(const PathPieces &X, const PathPieces &Y) {
314  if (X.size() != Y.size())
315    return X.size() < Y.size();
316
317  PathPieces::const_iterator X_I = X.begin(), X_end = X.end();
318  PathPieces::const_iterator Y_I = Y.begin(), Y_end = Y.end();
319
320  for ( ; X_I != X_end && Y_I != Y_end; ++X_I, ++Y_I) {
321    Optional<bool> b = comparePiece(**X_I, **Y_I);
322    if (b.hasValue())
323      return b.getValue();
324  }
325
326  return None;
327}
328
329static bool compareCrossTUSourceLocs(FullSourceLoc XL, FullSourceLoc YL) {
330  if (XL.isInvalid() && YL.isValid())
331    return true;
332  if (XL.isValid() && YL.isInvalid())
333    return false;
334  std::pair<FileID, unsigned> XOffs = XL.getDecomposedLoc();
335  std::pair<FileID, unsigned> YOffs = YL.getDecomposedLoc();
336  const SourceManager &SM = XL.getManager();
337  std::pair<bool, bool> InSameTU = SM.isInTheSameTranslationUnit(XOffs, YOffs);
338  if (InSameTU.first)
339    return XL.isBeforeInTranslationUnitThan(YL);
340  const FileEntry *XFE = SM.getFileEntryForID(XL.getSpellingLoc().getFileID());
341  const FileEntry *YFE = SM.getFileEntryForID(YL.getSpellingLoc().getFileID());
342  if (!XFE || !YFE)
343    return XFE && !YFE;
344  int NameCmp = XFE->getName().compare(YFE->getName());
345  if (NameCmp != 0)
346    return NameCmp == -1;
347  // Last resort: Compare raw file IDs that are possibly expansions.
348  return XL.getFileID() < YL.getFileID();
349}
350
351static bool compare(const PathDiagnostic &X, const PathDiagnostic &Y) {
352  FullSourceLoc XL = X.getLocation().asLocation();
353  FullSourceLoc YL = Y.getLocation().asLocation();
354  if (XL != YL)
355    return compareCrossTUSourceLocs(XL, YL);
356  FullSourceLoc XUL = X.getUniqueingLoc().asLocation();
357  FullSourceLoc YUL = Y.getUniqueingLoc().asLocation();
358  if (XUL != YUL)
359    return compareCrossTUSourceLocs(XUL, YUL);
360  if (X.getBugType() != Y.getBugType())
361    return X.getBugType() < Y.getBugType();
362  if (X.getCategory() != Y.getCategory())
363    return X.getCategory() < Y.getCategory();
364  if (X.getVerboseDescription() != Y.getVerboseDescription())
365    return X.getVerboseDescription() < Y.getVerboseDescription();
366  if (X.getShortDescription() != Y.getShortDescription())
367    return X.getShortDescription() < Y.getShortDescription();
368  auto CompareDecls = [&XL](const Decl *D1, const Decl *D2) -> Optional<bool> {
369    if (D1 == D2)
370      return None;
371    if (!D1)
372      return true;
373    if (!D2)
374      return false;
375    SourceLocation D1L = D1->getLocation();
376    SourceLocation D2L = D2->getLocation();
377    if (D1L != D2L) {
378      const SourceManager &SM = XL.getManager();
379      return compareCrossTUSourceLocs(FullSourceLoc(D1L, SM),
380                                      FullSourceLoc(D2L, SM));
381    }
382    return None;
383  };
384  if (auto Result = CompareDecls(X.getDeclWithIssue(), Y.getDeclWithIssue()))
385    return *Result;
386  if (XUL.isValid()) {
387    if (auto Result = CompareDecls(X.getUniqueingDecl(), Y.getUniqueingDecl()))
388      return *Result;
389  }
390  PathDiagnostic::meta_iterator XI = X.meta_begin(), XE = X.meta_end();
391  PathDiagnostic::meta_iterator YI = Y.meta_begin(), YE = Y.meta_end();
392  if (XE - XI != YE - YI)
393    return (XE - XI) < (YE - YI);
394  for ( ; XI != XE ; ++XI, ++YI) {
395    if (*XI != *YI)
396      return (*XI) < (*YI);
397  }
398  Optional<bool> b = comparePath(X.path, Y.path);
399  assert(b.hasValue());
400  return b.getValue();
401}
402
403void PathDiagnosticConsumer::FlushDiagnostics(
404                                     PathDiagnosticConsumer::FilesMade *Files) {
405  if (flushed)
406    return;
407
408  flushed = true;
409
410  std::vector<const PathDiagnostic *> BatchDiags;
411  for (const auto &D : Diags)
412    BatchDiags.push_back(&D);
413
414  // Sort the diagnostics so that they are always emitted in a deterministic
415  // order.
416  int (*Comp)(const PathDiagnostic *const *, const PathDiagnostic *const *) =
417      [](const PathDiagnostic *const *X, const PathDiagnostic *const *Y) {
418        assert(*X != *Y && "PathDiagnostics not uniqued!");
419        if (compare(**X, **Y))
420          return -1;
421        assert(compare(**Y, **X) && "Not a total order!");
422        return 1;
423      };
424  array_pod_sort(BatchDiags.begin(), BatchDiags.end(), Comp);
425
426  FlushDiagnosticsImpl(BatchDiags, Files);
427
428  // Delete the flushed diagnostics.
429  for (const auto D : BatchDiags)
430    delete D;
431
432  // Clear out the FoldingSet.
433  Diags.clear();
434}
435
436PathDiagnosticConsumer::FilesMade::~FilesMade() {
437  for (PDFileEntry &Entry : Set)
438    Entry.~PDFileEntry();
439}
440
441void PathDiagnosticConsumer::FilesMade::addDiagnostic(const PathDiagnostic &PD,
442                                                      StringRef ConsumerName,
443                                                      StringRef FileName) {
444  llvm::FoldingSetNodeID NodeID;
445  NodeID.Add(PD);
446  void *InsertPos;
447  PDFileEntry *Entry = Set.FindNodeOrInsertPos(NodeID, InsertPos);
448  if (!Entry) {
449    Entry = Alloc.Allocate<PDFileEntry>();
450    Entry = new (Entry) PDFileEntry(NodeID);
451    Set.InsertNode(Entry, InsertPos);
452  }
453
454  // Allocate persistent storage for the file name.
455  char *FileName_cstr = (char*) Alloc.Allocate(FileName.size(), 1);
456  memcpy(FileName_cstr, FileName.data(), FileName.size());
457
458  Entry->files.push_back(std::make_pair(ConsumerName,
459                                        StringRef(FileName_cstr,
460                                                  FileName.size())));
461}
462
463PathDiagnosticConsumer::PDFileEntry::ConsumerFiles *
464PathDiagnosticConsumer::FilesMade::getFiles(const PathDiagnostic &PD) {
465  llvm::FoldingSetNodeID NodeID;
466  NodeID.Add(PD);
467  void *InsertPos;
468  PDFileEntry *Entry = Set.FindNodeOrInsertPos(NodeID, InsertPos);
469  if (!Entry)
470    return nullptr;
471  return &Entry->files;
472}
473
474//===----------------------------------------------------------------------===//
475// PathDiagnosticLocation methods.
476//===----------------------------------------------------------------------===//
477
478SourceLocation PathDiagnosticLocation::getValidSourceLocation(
479    const Stmt *S, LocationOrAnalysisDeclContext LAC, bool UseEndOfStatement) {
480  SourceLocation L = UseEndOfStatement ? S->getEndLoc() : S->getBeginLoc();
481  assert(!LAC.isNull() &&
482         "A valid LocationContext or AnalysisDeclContext should be passed to "
483         "PathDiagnosticLocation upon creation.");
484
485  // S might be a temporary statement that does not have a location in the
486  // source code, so find an enclosing statement and use its location.
487  if (!L.isValid()) {
488    AnalysisDeclContext *ADC;
489    if (LAC.is<const LocationContext*>())
490      ADC = LAC.get<const LocationContext*>()->getAnalysisDeclContext();
491    else
492      ADC = LAC.get<AnalysisDeclContext*>();
493
494    ParentMap &PM = ADC->getParentMap();
495
496    const Stmt *Parent = S;
497    do {
498      Parent = PM.getParent(Parent);
499
500      // In rare cases, we have implicit top-level expressions,
501      // such as arguments for implicit member initializers.
502      // In this case, fall back to the start of the body (even if we were
503      // asked for the statement end location).
504      if (!Parent) {
505        const Stmt *Body = ADC->getBody();
506        if (Body)
507          L = Body->getBeginLoc();
508        else
509          L = ADC->getDecl()->getEndLoc();
510        break;
511      }
512
513      L = UseEndOfStatement ? Parent->getEndLoc() : Parent->getBeginLoc();
514    } while (!L.isValid());
515  }
516
517  // FIXME: Ironically, this assert actually fails in some cases.
518  //assert(L.isValid());
519  return L;
520}
521
522static PathDiagnosticLocation
523getLocationForCaller(const StackFrameContext *SFC,
524                     const LocationContext *CallerCtx,
525                     const SourceManager &SM) {
526  const CFGBlock &Block = *SFC->getCallSiteBlock();
527  CFGElement Source = Block[SFC->getIndex()];
528
529  switch (Source.getKind()) {
530  case CFGElement::Statement:
531  case CFGElement::Constructor:
532  case CFGElement::CXXRecordTypedCall:
533    return PathDiagnosticLocation(Source.castAs<CFGStmt>().getStmt(),
534                                  SM, CallerCtx);
535  case CFGElement::Initializer: {
536    const CFGInitializer &Init = Source.castAs<CFGInitializer>();
537    return PathDiagnosticLocation(Init.getInitializer()->getInit(),
538                                  SM, CallerCtx);
539  }
540  case CFGElement::AutomaticObjectDtor: {
541    const CFGAutomaticObjDtor &Dtor = Source.castAs<CFGAutomaticObjDtor>();
542    return PathDiagnosticLocation::createEnd(Dtor.getTriggerStmt(),
543                                             SM, CallerCtx);
544  }
545  case CFGElement::DeleteDtor: {
546    const CFGDeleteDtor &Dtor = Source.castAs<CFGDeleteDtor>();
547    return PathDiagnosticLocation(Dtor.getDeleteExpr(), SM, CallerCtx);
548  }
549  case CFGElement::BaseDtor:
550  case CFGElement::MemberDtor: {
551    const AnalysisDeclContext *CallerInfo = CallerCtx->getAnalysisDeclContext();
552    if (const Stmt *CallerBody = CallerInfo->getBody())
553      return PathDiagnosticLocation::createEnd(CallerBody, SM, CallerCtx);
554    return PathDiagnosticLocation::create(CallerInfo->getDecl(), SM);
555  }
556  case CFGElement::NewAllocator: {
557    const CFGNewAllocator &Alloc = Source.castAs<CFGNewAllocator>();
558    return PathDiagnosticLocation(Alloc.getAllocatorExpr(), SM, CallerCtx);
559  }
560  case CFGElement::TemporaryDtor: {
561    // Temporary destructors are for temporaries. They die immediately at around
562    // the location of CXXBindTemporaryExpr. If they are lifetime-extended,
563    // they'd be dealt with via an AutomaticObjectDtor instead.
564    const auto &Dtor = Source.castAs<CFGTemporaryDtor>();
565    return PathDiagnosticLocation::createEnd(Dtor.getBindTemporaryExpr(), SM,
566                                             CallerCtx);
567  }
568  case CFGElement::ScopeBegin:
569  case CFGElement::ScopeEnd:
570    llvm_unreachable("not yet implemented!");
571  case CFGElement::LifetimeEnds:
572  case CFGElement::LoopExit:
573    llvm_unreachable("CFGElement kind should not be on callsite!");
574  }
575
576  llvm_unreachable("Unknown CFGElement kind");
577}
578
579PathDiagnosticLocation
580PathDiagnosticLocation::createBegin(const Decl *D,
581                                    const SourceManager &SM) {
582  return PathDiagnosticLocation(D->getBeginLoc(), SM, SingleLocK);
583}
584
585PathDiagnosticLocation
586PathDiagnosticLocation::createBegin(const Stmt *S,
587                                    const SourceManager &SM,
588                                    LocationOrAnalysisDeclContext LAC) {
589  return PathDiagnosticLocation(getValidSourceLocation(S, LAC),
590                                SM, SingleLocK);
591}
592
593PathDiagnosticLocation
594PathDiagnosticLocation::createEnd(const Stmt *S,
595                                  const SourceManager &SM,
596                                  LocationOrAnalysisDeclContext LAC) {
597  if (const auto *CS = dyn_cast<CompoundStmt>(S))
598    return createEndBrace(CS, SM);
599  return PathDiagnosticLocation(getValidSourceLocation(S, LAC, /*End=*/true),
600                                SM, SingleLocK);
601}
602
603PathDiagnosticLocation
604PathDiagnosticLocation::createOperatorLoc(const BinaryOperator *BO,
605                                          const SourceManager &SM) {
606  return PathDiagnosticLocation(BO->getOperatorLoc(), SM, SingleLocK);
607}
608
609PathDiagnosticLocation
610PathDiagnosticLocation::createConditionalColonLoc(
611                                            const ConditionalOperator *CO,
612                                            const SourceManager &SM) {
613  return PathDiagnosticLocation(CO->getColonLoc(), SM, SingleLocK);
614}
615
616PathDiagnosticLocation
617PathDiagnosticLocation::createMemberLoc(const MemberExpr *ME,
618                                        const SourceManager &SM) {
619
620  assert(ME->getMemberLoc().isValid() || ME->getBeginLoc().isValid());
621
622  // In some cases, getMemberLoc isn't valid -- in this case we'll return with
623  // some other related valid SourceLocation.
624  if (ME->getMemberLoc().isValid())
625    return PathDiagnosticLocation(ME->getMemberLoc(), SM, SingleLocK);
626
627  return PathDiagnosticLocation(ME->getBeginLoc(), SM, SingleLocK);
628}
629
630PathDiagnosticLocation
631PathDiagnosticLocation::createBeginBrace(const CompoundStmt *CS,
632                                         const SourceManager &SM) {
633  SourceLocation L = CS->getLBracLoc();
634  return PathDiagnosticLocation(L, SM, SingleLocK);
635}
636
637PathDiagnosticLocation
638PathDiagnosticLocation::createEndBrace(const CompoundStmt *CS,
639                                       const SourceManager &SM) {
640  SourceLocation L = CS->getRBracLoc();
641  return PathDiagnosticLocation(L, SM, SingleLocK);
642}
643
644PathDiagnosticLocation
645PathDiagnosticLocation::createDeclBegin(const LocationContext *LC,
646                                        const SourceManager &SM) {
647  // FIXME: Should handle CXXTryStmt if analyser starts supporting C++.
648  if (const auto *CS = dyn_cast_or_null<CompoundStmt>(LC->getDecl()->getBody()))
649    if (!CS->body_empty()) {
650      SourceLocation Loc = (*CS->body_begin())->getBeginLoc();
651      return PathDiagnosticLocation(Loc, SM, SingleLocK);
652    }
653
654  return PathDiagnosticLocation();
655}
656
657PathDiagnosticLocation
658PathDiagnosticLocation::createDeclEnd(const LocationContext *LC,
659                                      const SourceManager &SM) {
660  SourceLocation L = LC->getDecl()->getBodyRBrace();
661  return PathDiagnosticLocation(L, SM, SingleLocK);
662}
663
664PathDiagnosticLocation
665PathDiagnosticLocation::create(const ProgramPoint& P,
666                               const SourceManager &SMng) {
667  const Stmt* S = nullptr;
668  if (Optional<BlockEdge> BE = P.getAs<BlockEdge>()) {
669    const CFGBlock *BSrc = BE->getSrc();
670    if (BSrc->getTerminator().isVirtualBaseBranch()) {
671      // TODO: VirtualBaseBranches should also appear for destructors.
672      // In this case we should put the diagnostic at the end of decl.
673      return PathDiagnosticLocation::createBegin(
674          P.getLocationContext()->getDecl(), SMng);
675
676    } else {
677      S = BSrc->getTerminatorCondition();
678      if (!S) {
679        // If the BlockEdge has no terminator condition statement but its
680        // source is the entry of the CFG (e.g. a checker crated the branch at
681        // the beginning of a function), use the function's declaration instead.
682        assert(BSrc == &BSrc->getParent()->getEntry() && "CFGBlock has no "
683               "TerminatorCondition and is not the enrty block of the CFG");
684        return PathDiagnosticLocation::createBegin(
685            P.getLocationContext()->getDecl(), SMng);
686      }
687    }
688  } else if (Optional<StmtPoint> SP = P.getAs<StmtPoint>()) {
689    S = SP->getStmt();
690    if (P.getAs<PostStmtPurgeDeadSymbols>())
691      return PathDiagnosticLocation::createEnd(S, SMng, P.getLocationContext());
692  } else if (Optional<PostInitializer> PIP = P.getAs<PostInitializer>()) {
693    return PathDiagnosticLocation(PIP->getInitializer()->getSourceLocation(),
694                                  SMng);
695  } else if (Optional<PreImplicitCall> PIC = P.getAs<PreImplicitCall>()) {
696    return PathDiagnosticLocation(PIC->getLocation(), SMng);
697  } else if (Optional<PostImplicitCall> PIE = P.getAs<PostImplicitCall>()) {
698    return PathDiagnosticLocation(PIE->getLocation(), SMng);
699  } else if (Optional<CallEnter> CE = P.getAs<CallEnter>()) {
700    return getLocationForCaller(CE->getCalleeContext(),
701                                CE->getLocationContext(),
702                                SMng);
703  } else if (Optional<CallExitEnd> CEE = P.getAs<CallExitEnd>()) {
704    return getLocationForCaller(CEE->getCalleeContext(),
705                                CEE->getLocationContext(),
706                                SMng);
707  } else if (auto CEB = P.getAs<CallExitBegin>()) {
708    if (const ReturnStmt *RS = CEB->getReturnStmt())
709      return PathDiagnosticLocation::createBegin(RS, SMng,
710                                                 CEB->getLocationContext());
711    return PathDiagnosticLocation(
712        CEB->getLocationContext()->getDecl()->getSourceRange().getEnd(), SMng);
713  } else if (Optional<BlockEntrance> BE = P.getAs<BlockEntrance>()) {
714    if (Optional<CFGElement> BlockFront = BE->getFirstElement()) {
715      if (auto StmtElt = BlockFront->getAs<CFGStmt>()) {
716        return PathDiagnosticLocation(StmtElt->getStmt()->getBeginLoc(), SMng);
717      } else if (auto NewAllocElt = BlockFront->getAs<CFGNewAllocator>()) {
718        return PathDiagnosticLocation(
719            NewAllocElt->getAllocatorExpr()->getBeginLoc(), SMng);
720      }
721      llvm_unreachable("Unexpected CFG element at front of block");
722    }
723
724    return PathDiagnosticLocation(
725        BE->getBlock()->getTerminatorStmt()->getBeginLoc(), SMng);
726  } else if (Optional<FunctionExitPoint> FE = P.getAs<FunctionExitPoint>()) {
727    return PathDiagnosticLocation(FE->getStmt(), SMng,
728                                  FE->getLocationContext());
729  } else {
730    llvm_unreachable("Unexpected ProgramPoint");
731  }
732
733  return PathDiagnosticLocation(S, SMng, P.getLocationContext());
734}
735
736PathDiagnosticLocation PathDiagnosticLocation::createSingleLocation(
737                                           const PathDiagnosticLocation &PDL) {
738  FullSourceLoc L = PDL.asLocation();
739  return PathDiagnosticLocation(L, L.getManager(), SingleLocK);
740}
741
742FullSourceLoc
743  PathDiagnosticLocation::genLocation(SourceLocation L,
744                                      LocationOrAnalysisDeclContext LAC) const {
745  assert(isValid());
746  // Note that we want a 'switch' here so that the compiler can warn us in
747  // case we add more cases.
748  switch (K) {
749    case SingleLocK:
750    case RangeK:
751      break;
752    case StmtK:
753      // Defensive checking.
754      if (!S)
755        break;
756      return FullSourceLoc(getValidSourceLocation(S, LAC),
757                           const_cast<SourceManager&>(*SM));
758    case DeclK:
759      // Defensive checking.
760      if (!D)
761        break;
762      return FullSourceLoc(D->getLocation(), const_cast<SourceManager&>(*SM));
763  }
764
765  return FullSourceLoc(L, const_cast<SourceManager&>(*SM));
766}
767
768PathDiagnosticRange
769  PathDiagnosticLocation::genRange(LocationOrAnalysisDeclContext LAC) const {
770  assert(isValid());
771  // Note that we want a 'switch' here so that the compiler can warn us in
772  // case we add more cases.
773  switch (K) {
774    case SingleLocK:
775      return PathDiagnosticRange(SourceRange(Loc,Loc), true);
776    case RangeK:
777      break;
778    case StmtK: {
779      const Stmt *S = asStmt();
780      switch (S->getStmtClass()) {
781        default:
782          break;
783        case Stmt::DeclStmtClass: {
784          const auto *DS = cast<DeclStmt>(S);
785          if (DS->isSingleDecl()) {
786            // Should always be the case, but we'll be defensive.
787            return SourceRange(DS->getBeginLoc(),
788                               DS->getSingleDecl()->getLocation());
789          }
790          break;
791        }
792          // FIXME: Provide better range information for different
793          //  terminators.
794        case Stmt::IfStmtClass:
795        case Stmt::WhileStmtClass:
796        case Stmt::DoStmtClass:
797        case Stmt::ForStmtClass:
798        case Stmt::ChooseExprClass:
799        case Stmt::IndirectGotoStmtClass:
800        case Stmt::SwitchStmtClass:
801        case Stmt::BinaryConditionalOperatorClass:
802        case Stmt::ConditionalOperatorClass:
803        case Stmt::ObjCForCollectionStmtClass: {
804          SourceLocation L = getValidSourceLocation(S, LAC);
805          return SourceRange(L, L);
806        }
807      }
808      SourceRange R = S->getSourceRange();
809      if (R.isValid())
810        return R;
811      break;
812    }
813    case DeclK:
814      if (const auto *MD = dyn_cast<ObjCMethodDecl>(D))
815        return MD->getSourceRange();
816      if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
817        if (Stmt *Body = FD->getBody())
818          return Body->getSourceRange();
819      }
820      else {
821        SourceLocation L = D->getLocation();
822        return PathDiagnosticRange(SourceRange(L, L), true);
823      }
824  }
825
826  return SourceRange(Loc, Loc);
827}
828
829void PathDiagnosticLocation::flatten() {
830  if (K == StmtK) {
831    K = RangeK;
832    S = nullptr;
833    D = nullptr;
834  }
835  else if (K == DeclK) {
836    K = SingleLocK;
837    S = nullptr;
838    D = nullptr;
839  }
840}
841
842//===----------------------------------------------------------------------===//
843// Manipulation of PathDiagnosticCallPieces.
844//===----------------------------------------------------------------------===//
845
846std::shared_ptr<PathDiagnosticCallPiece>
847PathDiagnosticCallPiece::construct(const CallExitEnd &CE,
848                                   const SourceManager &SM) {
849  const Decl *caller = CE.getLocationContext()->getDecl();
850  PathDiagnosticLocation pos = getLocationForCaller(CE.getCalleeContext(),
851                                                    CE.getLocationContext(),
852                                                    SM);
853  return std::shared_ptr<PathDiagnosticCallPiece>(
854      new PathDiagnosticCallPiece(caller, pos));
855}
856
857PathDiagnosticCallPiece *
858PathDiagnosticCallPiece::construct(PathPieces &path,
859                                   const Decl *caller) {
860  std::shared_ptr<PathDiagnosticCallPiece> C(
861      new PathDiagnosticCallPiece(path, caller));
862  path.clear();
863  auto *R = C.get();
864  path.push_front(std::move(C));
865  return R;
866}
867
868void PathDiagnosticCallPiece::setCallee(const CallEnter &CE,
869                                        const SourceManager &SM) {
870  const StackFrameContext *CalleeCtx = CE.getCalleeContext();
871  Callee = CalleeCtx->getDecl();
872
873  callEnterWithin = PathDiagnosticLocation::createBegin(Callee, SM);
874  callEnter = getLocationForCaller(CalleeCtx, CE.getLocationContext(), SM);
875
876  // Autosynthesized property accessors are special because we'd never
877  // pop back up to non-autosynthesized code until we leave them.
878  // This is not generally true for autosynthesized callees, which may call
879  // non-autosynthesized callbacks.
880  // Unless set here, the IsCalleeAnAutosynthesizedPropertyAccessor flag
881  // defaults to false.
882  if (const auto *MD = dyn_cast<ObjCMethodDecl>(Callee))
883    IsCalleeAnAutosynthesizedPropertyAccessor = (
884        MD->isPropertyAccessor() &&
885        CalleeCtx->getAnalysisDeclContext()->isBodyAutosynthesized());
886}
887
888static void describeTemplateParameters(raw_ostream &Out,
889                                       const ArrayRef<TemplateArgument> TAList,
890                                       const LangOptions &LO,
891                                       StringRef Prefix = StringRef(),
892                                       StringRef Postfix = StringRef());
893
894static void describeTemplateParameter(raw_ostream &Out,
895                                      const TemplateArgument &TArg,
896                                      const LangOptions &LO) {
897
898  if (TArg.getKind() == TemplateArgument::ArgKind::Pack) {
899    describeTemplateParameters(Out, TArg.getPackAsArray(), LO);
900  } else {
901    TArg.print(PrintingPolicy(LO), Out, /*IncludeType*/ true);
902  }
903}
904
905static void describeTemplateParameters(raw_ostream &Out,
906                                       const ArrayRef<TemplateArgument> TAList,
907                                       const LangOptions &LO,
908                                       StringRef Prefix, StringRef Postfix) {
909  if (TAList.empty())
910    return;
911
912  Out << Prefix;
913  for (int I = 0, Last = TAList.size() - 1; I != Last; ++I) {
914    describeTemplateParameter(Out, TAList[I], LO);
915    Out << ", ";
916  }
917  describeTemplateParameter(Out, TAList[TAList.size() - 1], LO);
918  Out << Postfix;
919}
920
921static void describeClass(raw_ostream &Out, const CXXRecordDecl *D,
922                          StringRef Prefix = StringRef()) {
923  if (!D->getIdentifier())
924    return;
925  Out << Prefix << '\'' << *D;
926  if (const auto T = dyn_cast<ClassTemplateSpecializationDecl>(D))
927    describeTemplateParameters(Out, T->getTemplateArgs().asArray(),
928                               D->getLangOpts(), "<", ">");
929
930  Out << '\'';
931}
932
933static bool describeCodeDecl(raw_ostream &Out, const Decl *D,
934                             bool ExtendedDescription,
935                             StringRef Prefix = StringRef()) {
936  if (!D)
937    return false;
938
939  if (isa<BlockDecl>(D)) {
940    if (ExtendedDescription)
941      Out << Prefix << "anonymous block";
942    return ExtendedDescription;
943  }
944
945  if (const auto *MD = dyn_cast<CXXMethodDecl>(D)) {
946    Out << Prefix;
947    if (ExtendedDescription && !MD->isUserProvided()) {
948      if (MD->isExplicitlyDefaulted())
949        Out << "defaulted ";
950      else
951        Out << "implicit ";
952    }
953
954    if (const auto *CD = dyn_cast<CXXConstructorDecl>(MD)) {
955      if (CD->isDefaultConstructor())
956        Out << "default ";
957      else if (CD->isCopyConstructor())
958        Out << "copy ";
959      else if (CD->isMoveConstructor())
960        Out << "move ";
961
962      Out << "constructor";
963      describeClass(Out, MD->getParent(), " for ");
964    } else if (isa<CXXDestructorDecl>(MD)) {
965      if (!MD->isUserProvided()) {
966        Out << "destructor";
967        describeClass(Out, MD->getParent(), " for ");
968      } else {
969        // Use ~Foo for explicitly-written destructors.
970        Out << "'" << *MD << "'";
971      }
972    } else if (MD->isCopyAssignmentOperator()) {
973        Out << "copy assignment operator";
974        describeClass(Out, MD->getParent(), " for ");
975    } else if (MD->isMoveAssignmentOperator()) {
976        Out << "move assignment operator";
977        describeClass(Out, MD->getParent(), " for ");
978    } else {
979      if (MD->getParent()->getIdentifier())
980        Out << "'" << *MD->getParent() << "::" << *MD << "'";
981      else
982        Out << "'" << *MD << "'";
983    }
984
985    return true;
986  }
987
988  Out << Prefix << '\'' << cast<NamedDecl>(*D);
989
990  // Adding template parameters.
991  if (const auto FD = dyn_cast<FunctionDecl>(D))
992    if (const TemplateArgumentList *TAList =
993                                    FD->getTemplateSpecializationArgs())
994      describeTemplateParameters(Out, TAList->asArray(), FD->getLangOpts(), "<",
995                                 ">");
996
997  Out << '\'';
998  return true;
999}
1000
1001std::shared_ptr<PathDiagnosticEventPiece>
1002PathDiagnosticCallPiece::getCallEnterEvent() const {
1003  // We do not produce call enters and call exits for autosynthesized property
1004  // accessors. We do generally produce them for other functions coming from
1005  // the body farm because they may call callbacks that bring us back into
1006  // visible code.
1007  if (!Callee || IsCalleeAnAutosynthesizedPropertyAccessor)
1008    return nullptr;
1009
1010  SmallString<256> buf;
1011  llvm::raw_svector_ostream Out(buf);
1012
1013  Out << "Calling ";
1014  describeCodeDecl(Out, Callee, /*ExtendedDescription=*/true);
1015
1016  assert(callEnter.asLocation().isValid());
1017  return std::make_shared<PathDiagnosticEventPiece>(callEnter, Out.str());
1018}
1019
1020std::shared_ptr<PathDiagnosticEventPiece>
1021PathDiagnosticCallPiece::getCallEnterWithinCallerEvent() const {
1022  if (!callEnterWithin.asLocation().isValid())
1023    return nullptr;
1024  if (Callee->isImplicit() || !Callee->hasBody())
1025    return nullptr;
1026  if (const auto *MD = dyn_cast<CXXMethodDecl>(Callee))
1027    if (MD->isDefaulted())
1028      return nullptr;
1029
1030  SmallString<256> buf;
1031  llvm::raw_svector_ostream Out(buf);
1032
1033  Out << "Entered call";
1034  describeCodeDecl(Out, Caller, /*ExtendedDescription=*/false, " from ");
1035
1036  return std::make_shared<PathDiagnosticEventPiece>(callEnterWithin, Out.str());
1037}
1038
1039std::shared_ptr<PathDiagnosticEventPiece>
1040PathDiagnosticCallPiece::getCallExitEvent() const {
1041  // We do not produce call enters and call exits for autosynthesized property
1042  // accessors. We do generally produce them for other functions coming from
1043  // the body farm because they may call callbacks that bring us back into
1044  // visible code.
1045  if (NoExit || IsCalleeAnAutosynthesizedPropertyAccessor)
1046    return nullptr;
1047
1048  SmallString<256> buf;
1049  llvm::raw_svector_ostream Out(buf);
1050
1051  if (!CallStackMessage.empty()) {
1052    Out << CallStackMessage;
1053  } else {
1054    bool DidDescribe = describeCodeDecl(Out, Callee,
1055                                        /*ExtendedDescription=*/false,
1056                                        "Returning from ");
1057    if (!DidDescribe)
1058      Out << "Returning to caller";
1059  }
1060
1061  assert(callReturn.asLocation().isValid());
1062  return std::make_shared<PathDiagnosticEventPiece>(callReturn, Out.str());
1063}
1064
1065static void compute_path_size(const PathPieces &pieces, unsigned &size) {
1066  for (const auto &I : pieces) {
1067    const PathDiagnosticPiece *piece = I.get();
1068    if (const auto *cp = dyn_cast<PathDiagnosticCallPiece>(piece))
1069      compute_path_size(cp->path, size);
1070    else
1071      ++size;
1072  }
1073}
1074
1075unsigned PathDiagnostic::full_size() {
1076  unsigned size = 0;
1077  compute_path_size(path, size);
1078  return size;
1079}
1080
1081//===----------------------------------------------------------------------===//
1082// FoldingSet profiling methods.
1083//===----------------------------------------------------------------------===//
1084
1085void PathDiagnosticLocation::Profile(llvm::FoldingSetNodeID &ID) const {
1086  ID.Add(Range.getBegin());
1087  ID.Add(Range.getEnd());
1088  ID.Add(static_cast<const SourceLocation &>(Loc));
1089}
1090
1091void PathDiagnosticPiece::Profile(llvm::FoldingSetNodeID &ID) const {
1092  ID.AddInteger((unsigned) getKind());
1093  ID.AddString(str);
1094  // FIXME: Add profiling support for code hints.
1095  ID.AddInteger((unsigned) getDisplayHint());
1096  ArrayRef<SourceRange> Ranges = getRanges();
1097  for (const auto &I : Ranges) {
1098    ID.Add(I.getBegin());
1099    ID.Add(I.getEnd());
1100  }
1101}
1102
1103void PathDiagnosticCallPiece::Profile(llvm::FoldingSetNodeID &ID) const {
1104  PathDiagnosticPiece::Profile(ID);
1105  for (const auto &I : path)
1106    ID.Add(*I);
1107}
1108
1109void PathDiagnosticSpotPiece::Profile(llvm::FoldingSetNodeID &ID) const {
1110  PathDiagnosticPiece::Profile(ID);
1111  ID.Add(Pos);
1112}
1113
1114void PathDiagnosticControlFlowPiece::Profile(llvm::FoldingSetNodeID &ID) const {
1115  PathDiagnosticPiece::Profile(ID);
1116  for (const auto &I : *this)
1117    ID.Add(I);
1118}
1119
1120void PathDiagnosticMacroPiece::Profile(llvm::FoldingSetNodeID &ID) const {
1121  PathDiagnosticSpotPiece::Profile(ID);
1122  for (const auto &I : subPieces)
1123    ID.Add(*I);
1124}
1125
1126void PathDiagnosticNotePiece::Profile(llvm::FoldingSetNodeID &ID) const {
1127  PathDiagnosticSpotPiece::Profile(ID);
1128}
1129
1130void PathDiagnosticPopUpPiece::Profile(llvm::FoldingSetNodeID &ID) const {
1131  PathDiagnosticSpotPiece::Profile(ID);
1132}
1133
1134void PathDiagnostic::Profile(llvm::FoldingSetNodeID &ID) const {
1135  ID.Add(getLocation());
1136  ID.Add(getUniqueingLoc());
1137  ID.AddString(BugType);
1138  ID.AddString(VerboseDesc);
1139  ID.AddString(Category);
1140}
1141
1142void PathDiagnostic::FullProfile(llvm::FoldingSetNodeID &ID) const {
1143  Profile(ID);
1144  for (const auto &I : path)
1145    ID.Add(*I);
1146  for (meta_iterator I = meta_begin(), E = meta_end(); I != E; ++I)
1147    ID.AddString(*I);
1148}
1149
1150LLVM_DUMP_METHOD void PathPieces::dump() const {
1151  unsigned index = 0;
1152  for (PathPieces::const_iterator I = begin(), E = end(); I != E; ++I) {
1153    llvm::errs() << "[" << index++ << "]  ";
1154    (*I)->dump();
1155    llvm::errs() << "\n";
1156  }
1157}
1158
1159LLVM_DUMP_METHOD void PathDiagnosticCallPiece::dump() const {
1160  llvm::errs() << "CALL\n--------------\n";
1161
1162  if (const Stmt *SLoc = getLocation().getStmtOrNull())
1163    SLoc->dump();
1164  else if (const auto *ND = dyn_cast_or_null<NamedDecl>(getCallee()))
1165    llvm::errs() << *ND << "\n";
1166  else
1167    getLocation().dump();
1168}
1169
1170LLVM_DUMP_METHOD void PathDiagnosticEventPiece::dump() const {
1171  llvm::errs() << "EVENT\n--------------\n";
1172  llvm::errs() << getString() << "\n";
1173  llvm::errs() << " ---- at ----\n";
1174  getLocation().dump();
1175}
1176
1177LLVM_DUMP_METHOD void PathDiagnosticControlFlowPiece::dump() const {
1178  llvm::errs() << "CONTROL\n--------------\n";
1179  getStartLocation().dump();
1180  llvm::errs() << " ---- to ----\n";
1181  getEndLocation().dump();
1182}
1183
1184LLVM_DUMP_METHOD void PathDiagnosticMacroPiece::dump() const {
1185  llvm::errs() << "MACRO\n--------------\n";
1186  // FIXME: Print which macro is being invoked.
1187}
1188
1189LLVM_DUMP_METHOD void PathDiagnosticNotePiece::dump() const {
1190  llvm::errs() << "NOTE\n--------------\n";
1191  llvm::errs() << getString() << "\n";
1192  llvm::errs() << " ---- at ----\n";
1193  getLocation().dump();
1194}
1195
1196LLVM_DUMP_METHOD void PathDiagnosticPopUpPiece::dump() const {
1197  llvm::errs() << "POP-UP\n--------------\n";
1198  llvm::errs() << getString() << "\n";
1199  llvm::errs() << " ---- at ----\n";
1200  getLocation().dump();
1201}
1202
1203LLVM_DUMP_METHOD void PathDiagnosticLocation::dump() const {
1204  if (!isValid()) {
1205    llvm::errs() << "<INVALID>\n";
1206    return;
1207  }
1208
1209  switch (K) {
1210  case RangeK:
1211    // FIXME: actually print the range.
1212    llvm::errs() << "<range>\n";
1213    break;
1214  case SingleLocK:
1215    asLocation().dump();
1216    llvm::errs() << "\n";
1217    break;
1218  case StmtK:
1219    if (S)
1220      S->dump();
1221    else
1222      llvm::errs() << "<NULL STMT>\n";
1223    break;
1224  case DeclK:
1225    if (const auto *ND = dyn_cast_or_null<NamedDecl>(D))
1226      llvm::errs() << *ND << "\n";
1227    else if (isa<BlockDecl>(D))
1228      // FIXME: Make this nicer.
1229      llvm::errs() << "<block>\n";
1230    else if (D)
1231      llvm::errs() << "<unknown decl>\n";
1232    else
1233      llvm::errs() << "<NULL DECL>\n";
1234    break;
1235  }
1236}
1237