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