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/STLExtras.h"
36#include "llvm/ADT/SmallString.h"
37#include "llvm/ADT/SmallVector.h"
38#include "llvm/ADT/StringExtras.h"
39#include "llvm/ADT/StringRef.h"
40#include "llvm/Support/Casting.h"
41#include "llvm/Support/ErrorHandling.h"
42#include "llvm/Support/raw_ostream.h"
43#include <cassert>
44#include <cstring>
45#include <memory>
46#include <optional>
47#include <utility>
48#include <vector>
49
50using namespace clang;
51using namespace ento;
52
53static StringRef StripTrailingDots(StringRef s) {
54  for (StringRef::size_type i = s.size(); i != 0; --i)
55    if (s[i - 1] != '.')
56      return s.substr(0, i);
57  return {};
58}
59
60PathDiagnosticPiece::PathDiagnosticPiece(StringRef s,
61                                         Kind k, DisplayHint hint)
62    : str(StripTrailingDots(s)), kind(k), Hint(hint) {}
63
64PathDiagnosticPiece::PathDiagnosticPiece(Kind k, DisplayHint hint)
65    : kind(k), Hint(hint) {}
66
67PathDiagnosticPiece::~PathDiagnosticPiece() = default;
68
69PathDiagnosticEventPiece::~PathDiagnosticEventPiece() = default;
70
71PathDiagnosticCallPiece::~PathDiagnosticCallPiece() = default;
72
73PathDiagnosticControlFlowPiece::~PathDiagnosticControlFlowPiece() = default;
74
75PathDiagnosticMacroPiece::~PathDiagnosticMacroPiece() = default;
76
77PathDiagnosticNotePiece::~PathDiagnosticNotePiece() = default;
78
79PathDiagnosticPopUpPiece::~PathDiagnosticPopUpPiece() = default;
80
81void PathPieces::flattenTo(PathPieces &Primary, PathPieces &Current,
82                           bool ShouldFlattenMacros) const {
83  for (auto &Piece : *this) {
84    switch (Piece->getKind()) {
85    case PathDiagnosticPiece::Call: {
86      auto &Call = cast<PathDiagnosticCallPiece>(*Piece);
87      if (auto CallEnter = Call.getCallEnterEvent())
88        Current.push_back(std::move(CallEnter));
89      Call.path.flattenTo(Primary, Primary, ShouldFlattenMacros);
90      if (auto callExit = Call.getCallExitEvent())
91        Current.push_back(std::move(callExit));
92      break;
93    }
94    case PathDiagnosticPiece::Macro: {
95      auto &Macro = cast<PathDiagnosticMacroPiece>(*Piece);
96      if (ShouldFlattenMacros) {
97        Macro.subPieces.flattenTo(Primary, Primary, ShouldFlattenMacros);
98      } else {
99        Current.push_back(Piece);
100        PathPieces NewPath;
101        Macro.subPieces.flattenTo(Primary, NewPath, ShouldFlattenMacros);
102        // FIXME: This probably shouldn't mutate the original path piece.
103        Macro.subPieces = NewPath;
104      }
105      break;
106    }
107    case PathDiagnosticPiece::Event:
108    case PathDiagnosticPiece::ControlFlow:
109    case PathDiagnosticPiece::Note:
110    case PathDiagnosticPiece::PopUp:
111      Current.push_back(Piece);
112      break;
113    }
114  }
115}
116
117PathDiagnostic::~PathDiagnostic() = default;
118
119PathDiagnostic::PathDiagnostic(
120    StringRef CheckerName, const Decl *declWithIssue, StringRef bugtype,
121    StringRef verboseDesc, StringRef shortDesc, StringRef category,
122    PathDiagnosticLocation LocationToUnique, const Decl *DeclToUnique,
123    std::unique_ptr<FilesToLineNumsMap> ExecutedLines)
124    : CheckerName(CheckerName), DeclWithIssue(declWithIssue),
125      BugType(StripTrailingDots(bugtype)),
126      VerboseDesc(StripTrailingDots(verboseDesc)),
127      ShortDesc(StripTrailingDots(shortDesc)),
128      Category(StripTrailingDots(category)), UniqueingLoc(LocationToUnique),
129      UniqueingDecl(DeclToUnique), ExecutedLines(std::move(ExecutedLines)),
130      path(pathImpl) {}
131
132void PathDiagnosticConsumer::anchor() {}
133
134PathDiagnosticConsumer::~PathDiagnosticConsumer() {
135  // Delete the contents of the FoldingSet if it isn't empty already.
136  for (auto &Diag : Diags)
137    delete &Diag;
138}
139
140void PathDiagnosticConsumer::HandlePathDiagnostic(
141    std::unique_ptr<PathDiagnostic> D) {
142  if (!D || D->path.empty())
143    return;
144
145  // We need to flatten the locations (convert Stmt* to locations) because
146  // the referenced statements may be freed by the time the diagnostics
147  // are emitted.
148  D->flattenLocations();
149
150  // If the PathDiagnosticConsumer does not support diagnostics that
151  // cross file boundaries, prune out such diagnostics now.
152  if (!supportsCrossFileDiagnostics()) {
153    // Verify that the entire path is from the same FileID.
154    FileID FID;
155    const SourceManager &SMgr = D->path.front()->getLocation().getManager();
156    SmallVector<const PathPieces *, 5> WorkList;
157    WorkList.push_back(&D->path);
158    SmallString<128> buf;
159    llvm::raw_svector_ostream warning(buf);
160    warning << "warning: Path diagnostic report is not generated. Current "
161            << "output format does not support diagnostics that cross file "
162            << "boundaries. Refer to --analyzer-output for valid output "
163            << "formats\n";
164
165    while (!WorkList.empty()) {
166      const PathPieces &path = *WorkList.pop_back_val();
167
168      for (const auto &I : path) {
169        const PathDiagnosticPiece *piece = I.get();
170        FullSourceLoc L = piece->getLocation().asLocation().getExpansionLoc();
171
172        if (FID.isInvalid()) {
173          FID = SMgr.getFileID(L);
174        } else if (SMgr.getFileID(L) != FID) {
175          llvm::errs() << warning.str();
176          return;
177        }
178
179        // Check the source ranges.
180        ArrayRef<SourceRange> Ranges = piece->getRanges();
181        for (const auto &I : Ranges) {
182          SourceLocation L = SMgr.getExpansionLoc(I.getBegin());
183          if (!L.isFileID() || SMgr.getFileID(L) != FID) {
184            llvm::errs() << warning.str();
185            return;
186          }
187          L = SMgr.getExpansionLoc(I.getEnd());
188          if (!L.isFileID() || SMgr.getFileID(L) != FID) {
189            llvm::errs() << warning.str();
190            return;
191          }
192        }
193
194        if (const auto *call = dyn_cast<PathDiagnosticCallPiece>(piece))
195          WorkList.push_back(&call->path);
196        else if (const auto *macro = dyn_cast<PathDiagnosticMacroPiece>(piece))
197          WorkList.push_back(&macro->subPieces);
198      }
199    }
200
201    if (FID.isInvalid())
202      return; // FIXME: Emit a warning?
203  }
204
205  // Profile the node to see if we already have something matching it
206  llvm::FoldingSetNodeID profile;
207  D->Profile(profile);
208  void *InsertPos = nullptr;
209
210  if (PathDiagnostic *orig = Diags.FindNodeOrInsertPos(profile, InsertPos)) {
211    // Keep the PathDiagnostic with the shorter path.
212    // Note, the enclosing routine is called in deterministic order, so the
213    // results will be consistent between runs (no reason to break ties if the
214    // size is the same).
215    const unsigned orig_size = orig->full_size();
216    const unsigned new_size = D->full_size();
217    if (orig_size <= new_size)
218      return;
219
220    assert(orig != D.get());
221    Diags.RemoveNode(orig);
222    delete orig;
223  }
224
225  Diags.InsertNode(D.release());
226}
227
228static std::optional<bool> comparePath(const PathPieces &X,
229                                       const PathPieces &Y);
230
231static std::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 std::nullopt;
243}
244
245static std::optional<bool> compareMacro(const PathDiagnosticMacroPiece &X,
246                                        const PathDiagnosticMacroPiece &Y) {
247  return comparePath(X.subPieces, Y.subPieces);
248}
249
250static std::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 std::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 std::nullopt;
309  }
310  llvm_unreachable("all cases handled");
311}
312
313static std::optional<bool> comparePath(const PathPieces &X,
314                                       const PathPieces &Y) {
315  if (X.size() != Y.size())
316    return X.size() < Y.size();
317
318  PathPieces::const_iterator X_I = X.begin(), X_end = X.end();
319  PathPieces::const_iterator Y_I = Y.begin(), Y_end = Y.end();
320
321  for (; X_I != X_end && Y_I != Y_end; ++X_I, ++Y_I)
322    if (std::optional<bool> b = comparePiece(**X_I, **Y_I))
323      return *b;
324
325  return std::nullopt;
326}
327
328static bool compareCrossTUSourceLocs(FullSourceLoc XL, FullSourceLoc YL) {
329  if (XL.isInvalid() && YL.isValid())
330    return true;
331  if (XL.isValid() && YL.isInvalid())
332    return false;
333  std::pair<FileID, unsigned> XOffs = XL.getDecomposedLoc();
334  std::pair<FileID, unsigned> YOffs = YL.getDecomposedLoc();
335  const SourceManager &SM = XL.getManager();
336  std::pair<bool, bool> InSameTU = SM.isInTheSameTranslationUnit(XOffs, YOffs);
337  if (InSameTU.first)
338    return XL.isBeforeInTranslationUnitThan(YL);
339  const FileEntry *XFE = SM.getFileEntryForID(XL.getSpellingLoc().getFileID());
340  const FileEntry *YFE = SM.getFileEntryForID(YL.getSpellingLoc().getFileID());
341  if (!XFE || !YFE)
342    return XFE && !YFE;
343  int NameCmp = XFE->getName().compare(YFE->getName());
344  if (NameCmp != 0)
345    return NameCmp < 0;
346  // Last resort: Compare raw file IDs that are possibly expansions.
347  return XL.getFileID() < YL.getFileID();
348}
349
350static bool compare(const PathDiagnostic &X, const PathDiagnostic &Y) {
351  FullSourceLoc XL = X.getLocation().asLocation();
352  FullSourceLoc YL = Y.getLocation().asLocation();
353  if (XL != YL)
354    return compareCrossTUSourceLocs(XL, YL);
355  FullSourceLoc XUL = X.getUniqueingLoc().asLocation();
356  FullSourceLoc YUL = Y.getUniqueingLoc().asLocation();
357  if (XUL != YUL)
358    return compareCrossTUSourceLocs(XUL, YUL);
359  if (X.getBugType() != Y.getBugType())
360    return X.getBugType() < Y.getBugType();
361  if (X.getCategory() != Y.getCategory())
362    return X.getCategory() < Y.getCategory();
363  if (X.getVerboseDescription() != Y.getVerboseDescription())
364    return X.getVerboseDescription() < Y.getVerboseDescription();
365  if (X.getShortDescription() != Y.getShortDescription())
366    return X.getShortDescription() < Y.getShortDescription();
367  auto CompareDecls = [&XL](const Decl *D1,
368                            const Decl *D2) -> std::optional<bool> {
369    if (D1 == D2)
370      return std::nullopt;
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 std::nullopt;
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  return *comparePath(X.path, Y.path);
399}
400
401void PathDiagnosticConsumer::FlushDiagnostics(
402                                     PathDiagnosticConsumer::FilesMade *Files) {
403  if (flushed)
404    return;
405
406  flushed = true;
407
408  std::vector<const PathDiagnostic *> BatchDiags;
409  for (const auto &D : Diags)
410    BatchDiags.push_back(&D);
411
412  // Sort the diagnostics so that they are always emitted in a deterministic
413  // order.
414  int (*Comp)(const PathDiagnostic *const *, const PathDiagnostic *const *) =
415      [](const PathDiagnostic *const *X, const PathDiagnostic *const *Y) {
416        assert(*X != *Y && "PathDiagnostics not uniqued!");
417        if (compare(**X, **Y))
418          return -1;
419        assert(compare(**Y, **X) && "Not a total order!");
420        return 1;
421      };
422  array_pod_sort(BatchDiags.begin(), BatchDiags.end(), Comp);
423
424  FlushDiagnosticsImpl(BatchDiags, Files);
425
426  // Delete the flushed diagnostics.
427  for (const auto D : BatchDiags)
428    delete D;
429
430  // Clear out the FoldingSet.
431  Diags.clear();
432}
433
434PathDiagnosticConsumer::FilesMade::~FilesMade() {
435  for (auto It = Set.begin(); It != Set.end();)
436    (It++)->~PDFileEntry();
437}
438
439void PathDiagnosticConsumer::FilesMade::addDiagnostic(const PathDiagnostic &PD,
440                                                      StringRef ConsumerName,
441                                                      StringRef FileName) {
442  llvm::FoldingSetNodeID NodeID;
443  NodeID.Add(PD);
444  void *InsertPos;
445  PDFileEntry *Entry = Set.FindNodeOrInsertPos(NodeID, InsertPos);
446  if (!Entry) {
447    Entry = Alloc.Allocate<PDFileEntry>();
448    Entry = new (Entry) PDFileEntry(NodeID);
449    Set.InsertNode(Entry, InsertPos);
450  }
451
452  // Allocate persistent storage for the file name.
453  char *FileName_cstr = (char*) Alloc.Allocate(FileName.size(), 1);
454  memcpy(FileName_cstr, FileName.data(), FileName.size());
455
456  Entry->files.push_back(std::make_pair(ConsumerName,
457                                        StringRef(FileName_cstr,
458                                                  FileName.size())));
459}
460
461PathDiagnosticConsumer::PDFileEntry::ConsumerFiles *
462PathDiagnosticConsumer::FilesMade::getFiles(const PathDiagnostic &PD) {
463  llvm::FoldingSetNodeID NodeID;
464  NodeID.Add(PD);
465  void *InsertPos;
466  PDFileEntry *Entry = Set.FindNodeOrInsertPos(NodeID, InsertPos);
467  if (!Entry)
468    return nullptr;
469  return &Entry->files;
470}
471
472//===----------------------------------------------------------------------===//
473// PathDiagnosticLocation methods.
474//===----------------------------------------------------------------------===//
475
476SourceLocation PathDiagnosticLocation::getValidSourceLocation(
477    const Stmt *S, LocationOrAnalysisDeclContext LAC, bool UseEndOfStatement) {
478  SourceLocation L = UseEndOfStatement ? S->getEndLoc() : S->getBeginLoc();
479  assert(!LAC.isNull() &&
480         "A valid LocationContext or AnalysisDeclContext should be passed to "
481         "PathDiagnosticLocation upon creation.");
482
483  // S might be a temporary statement that does not have a location in the
484  // source code, so find an enclosing statement and use its location.
485  if (!L.isValid()) {
486    AnalysisDeclContext *ADC;
487    if (LAC.is<const LocationContext*>())
488      ADC = LAC.get<const LocationContext*>()->getAnalysisDeclContext();
489    else
490      ADC = LAC.get<AnalysisDeclContext*>();
491
492    ParentMap &PM = ADC->getParentMap();
493
494    const Stmt *Parent = S;
495    do {
496      Parent = PM.getParent(Parent);
497
498      // In rare cases, we have implicit top-level expressions,
499      // such as arguments for implicit member initializers.
500      // In this case, fall back to the start of the body (even if we were
501      // asked for the statement end location).
502      if (!Parent) {
503        const Stmt *Body = ADC->getBody();
504        if (Body)
505          L = Body->getBeginLoc();
506        else
507          L = ADC->getDecl()->getEndLoc();
508        break;
509      }
510
511      L = UseEndOfStatement ? Parent->getEndLoc() : Parent->getBeginLoc();
512    } while (!L.isValid());
513  }
514
515  // FIXME: Ironically, this assert actually fails in some cases.
516  //assert(L.isValid());
517  return L;
518}
519
520static PathDiagnosticLocation
521getLocationForCaller(const StackFrameContext *SFC,
522                     const LocationContext *CallerCtx,
523                     const SourceManager &SM) {
524  const CFGBlock &Block = *SFC->getCallSiteBlock();
525  CFGElement Source = Block[SFC->getIndex()];
526
527  switch (Source.getKind()) {
528  case CFGElement::Statement:
529  case CFGElement::Constructor:
530  case CFGElement::CXXRecordTypedCall:
531    return PathDiagnosticLocation(Source.castAs<CFGStmt>().getStmt(),
532                                  SM, CallerCtx);
533  case CFGElement::Initializer: {
534    const CFGInitializer &Init = Source.castAs<CFGInitializer>();
535    return PathDiagnosticLocation(Init.getInitializer()->getInit(),
536                                  SM, CallerCtx);
537  }
538  case CFGElement::AutomaticObjectDtor: {
539    const CFGAutomaticObjDtor &Dtor = Source.castAs<CFGAutomaticObjDtor>();
540    return PathDiagnosticLocation::createEnd(Dtor.getTriggerStmt(),
541                                             SM, CallerCtx);
542  }
543  case CFGElement::DeleteDtor: {
544    const CFGDeleteDtor &Dtor = Source.castAs<CFGDeleteDtor>();
545    return PathDiagnosticLocation(Dtor.getDeleteExpr(), SM, CallerCtx);
546  }
547  case CFGElement::BaseDtor:
548  case CFGElement::MemberDtor: {
549    const AnalysisDeclContext *CallerInfo = CallerCtx->getAnalysisDeclContext();
550    if (const Stmt *CallerBody = CallerInfo->getBody())
551      return PathDiagnosticLocation::createEnd(CallerBody, SM, CallerCtx);
552    return PathDiagnosticLocation::create(CallerInfo->getDecl(), SM);
553  }
554  case CFGElement::NewAllocator: {
555    const CFGNewAllocator &Alloc = Source.castAs<CFGNewAllocator>();
556    return PathDiagnosticLocation(Alloc.getAllocatorExpr(), SM, CallerCtx);
557  }
558  case CFGElement::TemporaryDtor: {
559    // Temporary destructors are for temporaries. They die immediately at around
560    // the location of CXXBindTemporaryExpr. If they are lifetime-extended,
561    // they'd be dealt with via an AutomaticObjectDtor instead.
562    const auto &Dtor = Source.castAs<CFGTemporaryDtor>();
563    return PathDiagnosticLocation::createEnd(Dtor.getBindTemporaryExpr(), SM,
564                                             CallerCtx);
565  }
566  case CFGElement::ScopeBegin:
567  case CFGElement::ScopeEnd:
568    llvm_unreachable("not yet implemented!");
569  case CFGElement::LifetimeEnds:
570  case CFGElement::LoopExit:
571    llvm_unreachable("CFGElement kind should not be on callsite!");
572  }
573
574  llvm_unreachable("Unknown CFGElement kind");
575}
576
577PathDiagnosticLocation
578PathDiagnosticLocation::createBegin(const Decl *D,
579                                    const SourceManager &SM) {
580  return PathDiagnosticLocation(D->getBeginLoc(), SM, SingleLocK);
581}
582
583PathDiagnosticLocation
584PathDiagnosticLocation::createBegin(const Stmt *S,
585                                    const SourceManager &SM,
586                                    LocationOrAnalysisDeclContext LAC) {
587  return PathDiagnosticLocation(getValidSourceLocation(S, LAC),
588                                SM, SingleLocK);
589}
590
591PathDiagnosticLocation
592PathDiagnosticLocation::createEnd(const Stmt *S,
593                                  const SourceManager &SM,
594                                  LocationOrAnalysisDeclContext LAC) {
595  if (const auto *CS = dyn_cast<CompoundStmt>(S))
596    return createEndBrace(CS, SM);
597  return PathDiagnosticLocation(getValidSourceLocation(S, LAC, /*End=*/true),
598                                SM, SingleLocK);
599}
600
601PathDiagnosticLocation
602PathDiagnosticLocation::createOperatorLoc(const BinaryOperator *BO,
603                                          const SourceManager &SM) {
604  return PathDiagnosticLocation(BO->getOperatorLoc(), SM, SingleLocK);
605}
606
607PathDiagnosticLocation
608PathDiagnosticLocation::createConditionalColonLoc(
609                                            const ConditionalOperator *CO,
610                                            const SourceManager &SM) {
611  return PathDiagnosticLocation(CO->getColonLoc(), SM, SingleLocK);
612}
613
614PathDiagnosticLocation
615PathDiagnosticLocation::createMemberLoc(const MemberExpr *ME,
616                                        const SourceManager &SM) {
617
618  assert(ME->getMemberLoc().isValid() || ME->getBeginLoc().isValid());
619
620  // In some cases, getMemberLoc isn't valid -- in this case we'll return with
621  // some other related valid SourceLocation.
622  if (ME->getMemberLoc().isValid())
623    return PathDiagnosticLocation(ME->getMemberLoc(), SM, SingleLocK);
624
625  return PathDiagnosticLocation(ME->getBeginLoc(), SM, SingleLocK);
626}
627
628PathDiagnosticLocation
629PathDiagnosticLocation::createBeginBrace(const CompoundStmt *CS,
630                                         const SourceManager &SM) {
631  SourceLocation L = CS->getLBracLoc();
632  return PathDiagnosticLocation(L, SM, SingleLocK);
633}
634
635PathDiagnosticLocation
636PathDiagnosticLocation::createEndBrace(const CompoundStmt *CS,
637                                       const SourceManager &SM) {
638  SourceLocation L = CS->getRBracLoc();
639  return PathDiagnosticLocation(L, SM, SingleLocK);
640}
641
642PathDiagnosticLocation
643PathDiagnosticLocation::createDeclBegin(const LocationContext *LC,
644                                        const SourceManager &SM) {
645  // FIXME: Should handle CXXTryStmt if analyser starts supporting C++.
646  if (const auto *CS = dyn_cast_or_null<CompoundStmt>(LC->getDecl()->getBody()))
647    if (!CS->body_empty()) {
648      SourceLocation Loc = (*CS->body_begin())->getBeginLoc();
649      return PathDiagnosticLocation(Loc, SM, SingleLocK);
650    }
651
652  return PathDiagnosticLocation();
653}
654
655PathDiagnosticLocation
656PathDiagnosticLocation::createDeclEnd(const LocationContext *LC,
657                                      const SourceManager &SM) {
658  SourceLocation L = LC->getDecl()->getBodyRBrace();
659  return PathDiagnosticLocation(L, SM, SingleLocK);
660}
661
662PathDiagnosticLocation
663PathDiagnosticLocation::create(const ProgramPoint& P,
664                               const SourceManager &SMng) {
665  const Stmt* S = nullptr;
666  if (std::optional<BlockEdge> BE = P.getAs<BlockEdge>()) {
667    const CFGBlock *BSrc = BE->getSrc();
668    if (BSrc->getTerminator().isVirtualBaseBranch()) {
669      // TODO: VirtualBaseBranches should also appear for destructors.
670      // In this case we should put the diagnostic at the end of decl.
671      return PathDiagnosticLocation::createBegin(
672          P.getLocationContext()->getDecl(), SMng);
673
674    } else {
675      S = BSrc->getTerminatorCondition();
676      if (!S) {
677        // If the BlockEdge has no terminator condition statement but its
678        // source is the entry of the CFG (e.g. a checker crated the branch at
679        // the beginning of a function), use the function's declaration instead.
680        assert(BSrc == &BSrc->getParent()->getEntry() && "CFGBlock has no "
681               "TerminatorCondition and is not the enrty block of the CFG");
682        return PathDiagnosticLocation::createBegin(
683            P.getLocationContext()->getDecl(), SMng);
684      }
685    }
686  } else if (std::optional<StmtPoint> SP = P.getAs<StmtPoint>()) {
687    S = SP->getStmt();
688    if (P.getAs<PostStmtPurgeDeadSymbols>())
689      return PathDiagnosticLocation::createEnd(S, SMng, P.getLocationContext());
690  } else if (std::optional<PostInitializer> PIP = P.getAs<PostInitializer>()) {
691    return PathDiagnosticLocation(PIP->getInitializer()->getSourceLocation(),
692                                  SMng);
693  } else if (std::optional<PreImplicitCall> PIC = P.getAs<PreImplicitCall>()) {
694    return PathDiagnosticLocation(PIC->getLocation(), SMng);
695  } else if (std::optional<PostImplicitCall> PIE =
696                 P.getAs<PostImplicitCall>()) {
697    return PathDiagnosticLocation(PIE->getLocation(), SMng);
698  } else if (std::optional<CallEnter> CE = P.getAs<CallEnter>()) {
699    return getLocationForCaller(CE->getCalleeContext(),
700                                CE->getLocationContext(),
701                                SMng);
702  } else if (std::optional<CallExitEnd> CEE = P.getAs<CallExitEnd>()) {
703    return getLocationForCaller(CEE->getCalleeContext(),
704                                CEE->getLocationContext(),
705                                SMng);
706  } else if (auto CEB = P.getAs<CallExitBegin>()) {
707    if (const ReturnStmt *RS = CEB->getReturnStmt())
708      return PathDiagnosticLocation::createBegin(RS, SMng,
709                                                 CEB->getLocationContext());
710    return PathDiagnosticLocation(
711        CEB->getLocationContext()->getDecl()->getSourceRange().getEnd(), SMng);
712  } else if (std::optional<BlockEntrance> BE = P.getAs<BlockEntrance>()) {
713    if (std::optional<CFGElement> BlockFront = BE->getFirstElement()) {
714      if (auto StmtElt = BlockFront->getAs<CFGStmt>()) {
715        return PathDiagnosticLocation(StmtElt->getStmt()->getBeginLoc(), SMng);
716      } else if (auto NewAllocElt = BlockFront->getAs<CFGNewAllocator>()) {
717        return PathDiagnosticLocation(
718            NewAllocElt->getAllocatorExpr()->getBeginLoc(), SMng);
719      }
720      llvm_unreachable("Unexpected CFG element at front of block");
721    }
722
723    return PathDiagnosticLocation(
724        BE->getBlock()->getTerminatorStmt()->getBeginLoc(), SMng);
725  } else if (std::optional<FunctionExitPoint> FE =
726                 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