Home | History | Annotate | Line # | Download | only in Frontend
      1 //===- DiagnosticRenderer.cpp - Diagnostic Pretty-Printing ----------------===//
      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 #include "clang/Frontend/DiagnosticRenderer.h"
     10 #include "clang/Basic/Diagnostic.h"
     11 #include "clang/Basic/DiagnosticOptions.h"
     12 #include "clang/Basic/LLVM.h"
     13 #include "clang/Basic/SourceLocation.h"
     14 #include "clang/Basic/SourceManager.h"
     15 #include "clang/Edit/Commit.h"
     16 #include "clang/Edit/EditedSource.h"
     17 #include "clang/Edit/EditsReceiver.h"
     18 #include "clang/Lex/Lexer.h"
     19 #include "llvm/ADT/ArrayRef.h"
     20 #include "llvm/ADT/DenseMap.h"
     21 #include "llvm/ADT/None.h"
     22 #include "llvm/ADT/SmallString.h"
     23 #include "llvm/ADT/SmallVector.h"
     24 #include "llvm/ADT/StringRef.h"
     25 #include "llvm/Support/raw_ostream.h"
     26 #include <algorithm>
     27 #include <cassert>
     28 #include <iterator>
     29 #include <utility>
     30 
     31 using namespace clang;
     32 
     33 DiagnosticRenderer::DiagnosticRenderer(const LangOptions &LangOpts,
     34                                        DiagnosticOptions *DiagOpts)
     35     : LangOpts(LangOpts), DiagOpts(DiagOpts), LastLevel() {}
     36 
     37 DiagnosticRenderer::~DiagnosticRenderer() = default;
     38 
     39 namespace {
     40 
     41 class FixitReceiver : public edit::EditsReceiver {
     42   SmallVectorImpl<FixItHint> &MergedFixits;
     43 
     44 public:
     45   FixitReceiver(SmallVectorImpl<FixItHint> &MergedFixits)
     46       : MergedFixits(MergedFixits) {}
     47 
     48   void insert(SourceLocation loc, StringRef text) override {
     49     MergedFixits.push_back(FixItHint::CreateInsertion(loc, text));
     50   }
     51 
     52   void replace(CharSourceRange range, StringRef text) override {
     53     MergedFixits.push_back(FixItHint::CreateReplacement(range, text));
     54   }
     55 };
     56 
     57 } // namespace
     58 
     59 static void mergeFixits(ArrayRef<FixItHint> FixItHints,
     60                         const SourceManager &SM, const LangOptions &LangOpts,
     61                         SmallVectorImpl<FixItHint> &MergedFixits) {
     62   edit::Commit commit(SM, LangOpts);
     63   for (const auto &Hint : FixItHints)
     64     if (Hint.CodeToInsert.empty()) {
     65       if (Hint.InsertFromRange.isValid())
     66         commit.insertFromRange(Hint.RemoveRange.getBegin(),
     67                            Hint.InsertFromRange, /*afterToken=*/false,
     68                            Hint.BeforePreviousInsertions);
     69       else
     70         commit.remove(Hint.RemoveRange);
     71     } else {
     72       if (Hint.RemoveRange.isTokenRange() ||
     73           Hint.RemoveRange.getBegin() != Hint.RemoveRange.getEnd())
     74         commit.replace(Hint.RemoveRange, Hint.CodeToInsert);
     75       else
     76         commit.insert(Hint.RemoveRange.getBegin(), Hint.CodeToInsert,
     77                     /*afterToken=*/false, Hint.BeforePreviousInsertions);
     78     }
     79 
     80   edit::EditedSource Editor(SM, LangOpts);
     81   if (Editor.commit(commit)) {
     82     FixitReceiver Rec(MergedFixits);
     83     Editor.applyRewrites(Rec);
     84   }
     85 }
     86 
     87 void DiagnosticRenderer::emitDiagnostic(FullSourceLoc Loc,
     88                                         DiagnosticsEngine::Level Level,
     89                                         StringRef Message,
     90                                         ArrayRef<CharSourceRange> Ranges,
     91                                         ArrayRef<FixItHint> FixItHints,
     92                                         DiagOrStoredDiag D) {
     93   assert(Loc.hasManager() || Loc.isInvalid());
     94 
     95   beginDiagnostic(D, Level);
     96 
     97   if (!Loc.isValid())
     98     // If we have no source location, just emit the diagnostic message.
     99     emitDiagnosticMessage(Loc, PresumedLoc(), Level, Message, Ranges, D);
    100   else {
    101     // Get the ranges into a local array we can hack on.
    102     SmallVector<CharSourceRange, 20> MutableRanges(Ranges.begin(),
    103                                                    Ranges.end());
    104 
    105     SmallVector<FixItHint, 8> MergedFixits;
    106     if (!FixItHints.empty()) {
    107       mergeFixits(FixItHints, Loc.getManager(), LangOpts, MergedFixits);
    108       FixItHints = MergedFixits;
    109     }
    110 
    111     for (const auto &Hint : FixItHints)
    112       if (Hint.RemoveRange.isValid())
    113         MutableRanges.push_back(Hint.RemoveRange);
    114 
    115     FullSourceLoc UnexpandedLoc = Loc;
    116 
    117     // Find the ultimate expansion location for the diagnostic.
    118     Loc = Loc.getFileLoc();
    119 
    120     PresumedLoc PLoc = Loc.getPresumedLoc(DiagOpts->ShowPresumedLoc);
    121 
    122     // First, if this diagnostic is not in the main file, print out the
    123     // "included from" lines.
    124     emitIncludeStack(Loc, PLoc, Level);
    125 
    126     // Next, emit the actual diagnostic message and caret.
    127     emitDiagnosticMessage(Loc, PLoc, Level, Message, Ranges, D);
    128     emitCaret(Loc, Level, MutableRanges, FixItHints);
    129 
    130     // If this location is within a macro, walk from UnexpandedLoc up to Loc
    131     // and produce a macro backtrace.
    132     if (UnexpandedLoc.isValid() && UnexpandedLoc.isMacroID()) {
    133       emitMacroExpansions(UnexpandedLoc, Level, MutableRanges, FixItHints);
    134     }
    135   }
    136 
    137   LastLoc = Loc;
    138   LastLevel = Level;
    139 
    140   endDiagnostic(D, Level);
    141 }
    142 
    143 void DiagnosticRenderer::emitStoredDiagnostic(StoredDiagnostic &Diag) {
    144   emitDiagnostic(Diag.getLocation(), Diag.getLevel(), Diag.getMessage(),
    145                  Diag.getRanges(), Diag.getFixIts(),
    146                  &Diag);
    147 }
    148 
    149 void DiagnosticRenderer::emitBasicNote(StringRef Message) {
    150   emitDiagnosticMessage(FullSourceLoc(), PresumedLoc(), DiagnosticsEngine::Note,
    151                         Message, None, DiagOrStoredDiag());
    152 }
    153 
    154 /// Prints an include stack when appropriate for a particular
    155 /// diagnostic level and location.
    156 ///
    157 /// This routine handles all the logic of suppressing particular include
    158 /// stacks (such as those for notes) and duplicate include stacks when
    159 /// repeated warnings occur within the same file. It also handles the logic
    160 /// of customizing the formatting and display of the include stack.
    161 ///
    162 /// \param Loc   The diagnostic location.
    163 /// \param PLoc  The presumed location of the diagnostic location.
    164 /// \param Level The diagnostic level of the message this stack pertains to.
    165 void DiagnosticRenderer::emitIncludeStack(FullSourceLoc Loc, PresumedLoc PLoc,
    166                                           DiagnosticsEngine::Level Level) {
    167   FullSourceLoc IncludeLoc =
    168       PLoc.isInvalid() ? FullSourceLoc()
    169                        : FullSourceLoc(PLoc.getIncludeLoc(), Loc.getManager());
    170 
    171   // Skip redundant include stacks altogether.
    172   if (LastIncludeLoc == IncludeLoc)
    173     return;
    174 
    175   LastIncludeLoc = IncludeLoc;
    176 
    177   if (!DiagOpts->ShowNoteIncludeStack && Level == DiagnosticsEngine::Note)
    178     return;
    179 
    180   if (IncludeLoc.isValid())
    181     emitIncludeStackRecursively(IncludeLoc);
    182   else {
    183     emitModuleBuildStack(Loc.getManager());
    184     emitImportStack(Loc);
    185   }
    186 }
    187 
    188 /// Helper to recursively walk up the include stack and print each layer
    189 /// on the way back down.
    190 void DiagnosticRenderer::emitIncludeStackRecursively(FullSourceLoc Loc) {
    191   if (Loc.isInvalid()) {
    192     emitModuleBuildStack(Loc.getManager());
    193     return;
    194   }
    195 
    196   PresumedLoc PLoc = Loc.getPresumedLoc(DiagOpts->ShowPresumedLoc);
    197   if (PLoc.isInvalid())
    198     return;
    199 
    200   // If this source location was imported from a module, print the module
    201   // import stack rather than the
    202   // FIXME: We want submodule granularity here.
    203   std::pair<FullSourceLoc, StringRef> Imported = Loc.getModuleImportLoc();
    204   if (!Imported.second.empty()) {
    205     // This location was imported by a module. Emit the module import stack.
    206     emitImportStackRecursively(Imported.first, Imported.second);
    207     return;
    208   }
    209 
    210   // Emit the other include frames first.
    211   emitIncludeStackRecursively(
    212       FullSourceLoc(PLoc.getIncludeLoc(), Loc.getManager()));
    213 
    214   // Emit the inclusion text/note.
    215   emitIncludeLocation(Loc, PLoc);
    216 }
    217 
    218 /// Emit the module import stack associated with the current location.
    219 void DiagnosticRenderer::emitImportStack(FullSourceLoc Loc) {
    220   if (Loc.isInvalid()) {
    221     emitModuleBuildStack(Loc.getManager());
    222     return;
    223   }
    224 
    225   std::pair<FullSourceLoc, StringRef> NextImportLoc = Loc.getModuleImportLoc();
    226   emitImportStackRecursively(NextImportLoc.first, NextImportLoc.second);
    227 }
    228 
    229 /// Helper to recursively walk up the import stack and print each layer
    230 /// on the way back down.
    231 void DiagnosticRenderer::emitImportStackRecursively(FullSourceLoc Loc,
    232                                                     StringRef ModuleName) {
    233   if (ModuleName.empty()) {
    234     return;
    235   }
    236 
    237   PresumedLoc PLoc = Loc.getPresumedLoc(DiagOpts->ShowPresumedLoc);
    238 
    239   // Emit the other import frames first.
    240   std::pair<FullSourceLoc, StringRef> NextImportLoc = Loc.getModuleImportLoc();
    241   emitImportStackRecursively(NextImportLoc.first, NextImportLoc.second);
    242 
    243   // Emit the inclusion text/note.
    244   emitImportLocation(Loc, PLoc, ModuleName);
    245 }
    246 
    247 /// Emit the module build stack, for cases where a module is (re-)built
    248 /// on demand.
    249 void DiagnosticRenderer::emitModuleBuildStack(const SourceManager &SM) {
    250   ModuleBuildStack Stack = SM.getModuleBuildStack();
    251   for (const auto &I : Stack) {
    252     emitBuildingModuleLocation(I.second, I.second.getPresumedLoc(
    253                                               DiagOpts->ShowPresumedLoc),
    254                                I.first);
    255   }
    256 }
    257 
    258 /// A recursive function to trace all possible backtrace locations
    259 /// to match the \p CaretLocFileID.
    260 static SourceLocation
    261 retrieveMacroLocation(SourceLocation Loc, FileID MacroFileID,
    262                       FileID CaretFileID,
    263                       const SmallVectorImpl<FileID> &CommonArgExpansions,
    264                       bool IsBegin, const SourceManager *SM,
    265                       bool &IsTokenRange) {
    266   assert(SM->getFileID(Loc) == MacroFileID);
    267   if (MacroFileID == CaretFileID)
    268     return Loc;
    269   if (!Loc.isMacroID())
    270     return {};
    271 
    272   CharSourceRange MacroRange, MacroArgRange;
    273 
    274   if (SM->isMacroArgExpansion(Loc)) {
    275     // Only look at the immediate spelling location of this macro argument if
    276     // the other location in the source range is also present in that expansion.
    277     if (std::binary_search(CommonArgExpansions.begin(),
    278                            CommonArgExpansions.end(), MacroFileID))
    279       MacroRange =
    280           CharSourceRange(SM->getImmediateSpellingLoc(Loc), IsTokenRange);
    281     MacroArgRange = SM->getImmediateExpansionRange(Loc);
    282   } else {
    283     MacroRange = SM->getImmediateExpansionRange(Loc);
    284     MacroArgRange =
    285         CharSourceRange(SM->getImmediateSpellingLoc(Loc), IsTokenRange);
    286   }
    287 
    288   SourceLocation MacroLocation =
    289       IsBegin ? MacroRange.getBegin() : MacroRange.getEnd();
    290   if (MacroLocation.isValid()) {
    291     MacroFileID = SM->getFileID(MacroLocation);
    292     bool TokenRange = IsBegin ? IsTokenRange : MacroRange.isTokenRange();
    293     MacroLocation =
    294         retrieveMacroLocation(MacroLocation, MacroFileID, CaretFileID,
    295                               CommonArgExpansions, IsBegin, SM, TokenRange);
    296     if (MacroLocation.isValid()) {
    297       IsTokenRange = TokenRange;
    298       return MacroLocation;
    299     }
    300   }
    301 
    302   // If we moved the end of the range to an expansion location, we now have
    303   // a range of the same kind as the expansion range.
    304   if (!IsBegin)
    305     IsTokenRange = MacroArgRange.isTokenRange();
    306 
    307   SourceLocation MacroArgLocation =
    308       IsBegin ? MacroArgRange.getBegin() : MacroArgRange.getEnd();
    309   MacroFileID = SM->getFileID(MacroArgLocation);
    310   return retrieveMacroLocation(MacroArgLocation, MacroFileID, CaretFileID,
    311                                CommonArgExpansions, IsBegin, SM, IsTokenRange);
    312 }
    313 
    314 /// Walk up the chain of macro expansions and collect the FileIDs identifying the
    315 /// expansions.
    316 static void getMacroArgExpansionFileIDs(SourceLocation Loc,
    317                                         SmallVectorImpl<FileID> &IDs,
    318                                         bool IsBegin, const SourceManager *SM) {
    319   while (Loc.isMacroID()) {
    320     if (SM->isMacroArgExpansion(Loc)) {
    321       IDs.push_back(SM->getFileID(Loc));
    322       Loc = SM->getImmediateSpellingLoc(Loc);
    323     } else {
    324       auto ExpRange = SM->getImmediateExpansionRange(Loc);
    325       Loc = IsBegin ? ExpRange.getBegin() : ExpRange.getEnd();
    326     }
    327   }
    328 }
    329 
    330 /// Collect the expansions of the begin and end locations and compute the set
    331 /// intersection. Produces a sorted vector of FileIDs in CommonArgExpansions.
    332 static void computeCommonMacroArgExpansionFileIDs(
    333     SourceLocation Begin, SourceLocation End, const SourceManager *SM,
    334     SmallVectorImpl<FileID> &CommonArgExpansions) {
    335   SmallVector<FileID, 4> BeginArgExpansions;
    336   SmallVector<FileID, 4> EndArgExpansions;
    337   getMacroArgExpansionFileIDs(Begin, BeginArgExpansions, /*IsBegin=*/true, SM);
    338   getMacroArgExpansionFileIDs(End, EndArgExpansions, /*IsBegin=*/false, SM);
    339   llvm::sort(BeginArgExpansions);
    340   llvm::sort(EndArgExpansions);
    341   std::set_intersection(BeginArgExpansions.begin(), BeginArgExpansions.end(),
    342                         EndArgExpansions.begin(), EndArgExpansions.end(),
    343                         std::back_inserter(CommonArgExpansions));
    344 }
    345 
    346 // Helper function to fix up source ranges.  It takes in an array of ranges,
    347 // and outputs an array of ranges where we want to draw the range highlighting
    348 // around the location specified by CaretLoc.
    349 //
    350 // To find locations which correspond to the caret, we crawl the macro caller
    351 // chain for the beginning and end of each range.  If the caret location
    352 // is in a macro expansion, we search each chain for a location
    353 // in the same expansion as the caret; otherwise, we crawl to the top of
    354 // each chain. Two locations are part of the same macro expansion
    355 // iff the FileID is the same.
    356 static void
    357 mapDiagnosticRanges(FullSourceLoc CaretLoc, ArrayRef<CharSourceRange> Ranges,
    358                     SmallVectorImpl<CharSourceRange> &SpellingRanges) {
    359   FileID CaretLocFileID = CaretLoc.getFileID();
    360 
    361   const SourceManager *SM = &CaretLoc.getManager();
    362 
    363   for (const auto &Range : Ranges) {
    364     if (Range.isInvalid())
    365       continue;
    366 
    367     SourceLocation Begin = Range.getBegin(), End = Range.getEnd();
    368     bool IsTokenRange = Range.isTokenRange();
    369 
    370     FileID BeginFileID = SM->getFileID(Begin);
    371     FileID EndFileID = SM->getFileID(End);
    372 
    373     // Find the common parent for the beginning and end of the range.
    374 
    375     // First, crawl the expansion chain for the beginning of the range.
    376     llvm::SmallDenseMap<FileID, SourceLocation> BeginLocsMap;
    377     while (Begin.isMacroID() && BeginFileID != EndFileID) {
    378       BeginLocsMap[BeginFileID] = Begin;
    379       Begin = SM->getImmediateExpansionRange(Begin).getBegin();
    380       BeginFileID = SM->getFileID(Begin);
    381     }
    382 
    383     // Then, crawl the expansion chain for the end of the range.
    384     if (BeginFileID != EndFileID) {
    385       while (End.isMacroID() && !BeginLocsMap.count(EndFileID)) {
    386         auto Exp = SM->getImmediateExpansionRange(End);
    387         IsTokenRange = Exp.isTokenRange();
    388         End = Exp.getEnd();
    389         EndFileID = SM->getFileID(End);
    390       }
    391       if (End.isMacroID()) {
    392         Begin = BeginLocsMap[EndFileID];
    393         BeginFileID = EndFileID;
    394       }
    395     }
    396 
    397     // There is a chance that begin or end is invalid here, for example if
    398     // specific compile error is reported.
    399     // It is possible that the FileID's do not match, if one comes from an
    400     // included file. In this case we can not produce a meaningful source range.
    401     if (Begin.isInvalid() || End.isInvalid() || BeginFileID != EndFileID)
    402       continue;
    403 
    404     // Do the backtracking.
    405     SmallVector<FileID, 4> CommonArgExpansions;
    406     computeCommonMacroArgExpansionFileIDs(Begin, End, SM, CommonArgExpansions);
    407     Begin = retrieveMacroLocation(Begin, BeginFileID, CaretLocFileID,
    408                                   CommonArgExpansions, /*IsBegin=*/true, SM,
    409                                   IsTokenRange);
    410     End = retrieveMacroLocation(End, BeginFileID, CaretLocFileID,
    411                                 CommonArgExpansions, /*IsBegin=*/false, SM,
    412                                 IsTokenRange);
    413     if (Begin.isInvalid() || End.isInvalid()) continue;
    414 
    415     // Return the spelling location of the beginning and end of the range.
    416     Begin = SM->getSpellingLoc(Begin);
    417     End = SM->getSpellingLoc(End);
    418 
    419     SpellingRanges.push_back(CharSourceRange(SourceRange(Begin, End),
    420                                              IsTokenRange));
    421   }
    422 }
    423 
    424 void DiagnosticRenderer::emitCaret(FullSourceLoc Loc,
    425                                    DiagnosticsEngine::Level Level,
    426                                    ArrayRef<CharSourceRange> Ranges,
    427                                    ArrayRef<FixItHint> Hints) {
    428   SmallVector<CharSourceRange, 4> SpellingRanges;
    429   mapDiagnosticRanges(Loc, Ranges, SpellingRanges);
    430   emitCodeContext(Loc, Level, SpellingRanges, Hints);
    431 }
    432 
    433 /// A helper function for emitMacroExpansion to print the
    434 /// macro expansion message
    435 void DiagnosticRenderer::emitSingleMacroExpansion(
    436     FullSourceLoc Loc, DiagnosticsEngine::Level Level,
    437     ArrayRef<CharSourceRange> Ranges) {
    438   // Find the spelling location for the macro definition. We must use the
    439   // spelling location here to avoid emitting a macro backtrace for the note.
    440   FullSourceLoc SpellingLoc = Loc.getSpellingLoc();
    441 
    442   // Map the ranges into the FileID of the diagnostic location.
    443   SmallVector<CharSourceRange, 4> SpellingRanges;
    444   mapDiagnosticRanges(Loc, Ranges, SpellingRanges);
    445 
    446   SmallString<100> MessageStorage;
    447   llvm::raw_svector_ostream Message(MessageStorage);
    448   StringRef MacroName = Lexer::getImmediateMacroNameForDiagnostics(
    449       Loc, Loc.getManager(), LangOpts);
    450   if (MacroName.empty())
    451     Message << "expanded from here";
    452   else
    453     Message << "expanded from macro '" << MacroName << "'";
    454 
    455   emitDiagnostic(SpellingLoc, DiagnosticsEngine::Note, Message.str(),
    456                  SpellingRanges, None);
    457 }
    458 
    459 /// Check that the macro argument location of Loc starts with ArgumentLoc.
    460 /// The starting location of the macro expansions is used to differeniate
    461 /// different macro expansions.
    462 static bool checkLocForMacroArgExpansion(SourceLocation Loc,
    463                                          const SourceManager &SM,
    464                                          SourceLocation ArgumentLoc) {
    465   SourceLocation MacroLoc;
    466   if (SM.isMacroArgExpansion(Loc, &MacroLoc)) {
    467     if (ArgumentLoc == MacroLoc) return true;
    468   }
    469 
    470   return false;
    471 }
    472 
    473 /// Check if all the locations in the range have the same macro argument
    474 /// expansion, and that the expansion starts with ArgumentLoc.
    475 static bool checkRangeForMacroArgExpansion(CharSourceRange Range,
    476                                            const SourceManager &SM,
    477                                            SourceLocation ArgumentLoc) {
    478   SourceLocation BegLoc = Range.getBegin(), EndLoc = Range.getEnd();
    479   while (BegLoc != EndLoc) {
    480     if (!checkLocForMacroArgExpansion(BegLoc, SM, ArgumentLoc))
    481       return false;
    482     BegLoc.getLocWithOffset(1);
    483   }
    484 
    485   return checkLocForMacroArgExpansion(BegLoc, SM, ArgumentLoc);
    486 }
    487 
    488 /// A helper function to check if the current ranges are all inside the same
    489 /// macro argument expansion as Loc.
    490 static bool checkRangesForMacroArgExpansion(FullSourceLoc Loc,
    491                                             ArrayRef<CharSourceRange> Ranges) {
    492   assert(Loc.isMacroID() && "Must be a macro expansion!");
    493 
    494   SmallVector<CharSourceRange, 4> SpellingRanges;
    495   mapDiagnosticRanges(Loc, Ranges, SpellingRanges);
    496 
    497   /// Count all valid ranges.
    498   unsigned ValidCount = 0;
    499   for (const auto &Range : Ranges)
    500     if (Range.isValid())
    501       ValidCount++;
    502 
    503   if (ValidCount > SpellingRanges.size())
    504     return false;
    505 
    506   /// To store the source location of the argument location.
    507   FullSourceLoc ArgumentLoc;
    508 
    509   /// Set the ArgumentLoc to the beginning location of the expansion of Loc
    510   /// so to check if the ranges expands to the same beginning location.
    511   if (!Loc.isMacroArgExpansion(&ArgumentLoc))
    512     return false;
    513 
    514   for (const auto &Range : SpellingRanges)
    515     if (!checkRangeForMacroArgExpansion(Range, Loc.getManager(), ArgumentLoc))
    516       return false;
    517 
    518   return true;
    519 }
    520 
    521 /// Recursively emit notes for each macro expansion and caret
    522 /// diagnostics where appropriate.
    523 ///
    524 /// Walks up the macro expansion stack printing expansion notes, the code
    525 /// snippet, caret, underlines and FixItHint display as appropriate at each
    526 /// level.
    527 ///
    528 /// \param Loc The location for this caret.
    529 /// \param Level The diagnostic level currently being emitted.
    530 /// \param Ranges The underlined ranges for this code snippet.
    531 /// \param Hints The FixIt hints active for this diagnostic.
    532 void DiagnosticRenderer::emitMacroExpansions(FullSourceLoc Loc,
    533                                              DiagnosticsEngine::Level Level,
    534                                              ArrayRef<CharSourceRange> Ranges,
    535                                              ArrayRef<FixItHint> Hints) {
    536   assert(Loc.isValid() && "must have a valid source location here");
    537   const SourceManager &SM = Loc.getManager();
    538   SourceLocation L = Loc;
    539 
    540   // Produce a stack of macro backtraces.
    541   SmallVector<SourceLocation, 8> LocationStack;
    542   unsigned IgnoredEnd = 0;
    543   while (L.isMacroID()) {
    544     // If this is the expansion of a macro argument, point the caret at the
    545     // use of the argument in the definition of the macro, not the expansion.
    546     if (SM.isMacroArgExpansion(L))
    547       LocationStack.push_back(SM.getImmediateExpansionRange(L).getBegin());
    548     else
    549       LocationStack.push_back(L);
    550 
    551     if (checkRangesForMacroArgExpansion(FullSourceLoc(L, SM), Ranges))
    552       IgnoredEnd = LocationStack.size();
    553 
    554     L = SM.getImmediateMacroCallerLoc(L);
    555 
    556     // Once the location no longer points into a macro, try stepping through
    557     // the last found location.  This sometimes produces additional useful
    558     // backtraces.
    559     if (L.isFileID())
    560       L = SM.getImmediateMacroCallerLoc(LocationStack.back());
    561     assert(L.isValid() && "must have a valid source location here");
    562   }
    563 
    564   LocationStack.erase(LocationStack.begin(),
    565                       LocationStack.begin() + IgnoredEnd);
    566 
    567   unsigned MacroDepth = LocationStack.size();
    568   unsigned MacroLimit = DiagOpts->MacroBacktraceLimit;
    569   if (MacroDepth <= MacroLimit || MacroLimit == 0) {
    570     for (auto I = LocationStack.rbegin(), E = LocationStack.rend();
    571          I != E; ++I)
    572       emitSingleMacroExpansion(FullSourceLoc(*I, SM), Level, Ranges);
    573     return;
    574   }
    575 
    576   unsigned MacroStartMessages = MacroLimit / 2;
    577   unsigned MacroEndMessages = MacroLimit / 2 + MacroLimit % 2;
    578 
    579   for (auto I = LocationStack.rbegin(),
    580             E = LocationStack.rbegin() + MacroStartMessages;
    581        I != E; ++I)
    582     emitSingleMacroExpansion(FullSourceLoc(*I, SM), Level, Ranges);
    583 
    584   SmallString<200> MessageStorage;
    585   llvm::raw_svector_ostream Message(MessageStorage);
    586   Message << "(skipping " << (MacroDepth - MacroLimit)
    587           << " expansions in backtrace; use -fmacro-backtrace-limit=0 to "
    588              "see all)";
    589   emitBasicNote(Message.str());
    590 
    591   for (auto I = LocationStack.rend() - MacroEndMessages,
    592             E = LocationStack.rend();
    593        I != E; ++I)
    594     emitSingleMacroExpansion(FullSourceLoc(*I, SM), Level, Ranges);
    595 }
    596 
    597 DiagnosticNoteRenderer::~DiagnosticNoteRenderer() = default;
    598 
    599 void DiagnosticNoteRenderer::emitIncludeLocation(FullSourceLoc Loc,
    600                                                  PresumedLoc PLoc) {
    601   // Generate a note indicating the include location.
    602   SmallString<200> MessageStorage;
    603   llvm::raw_svector_ostream Message(MessageStorage);
    604   Message << "in file included from " << PLoc.getFilename() << ':'
    605           << PLoc.getLine() << ":";
    606   emitNote(Loc, Message.str());
    607 }
    608 
    609 void DiagnosticNoteRenderer::emitImportLocation(FullSourceLoc Loc,
    610                                                 PresumedLoc PLoc,
    611                                                 StringRef ModuleName) {
    612   // Generate a note indicating the include location.
    613   SmallString<200> MessageStorage;
    614   llvm::raw_svector_ostream Message(MessageStorage);
    615   Message << "in module '" << ModuleName;
    616   if (PLoc.isValid())
    617     Message << "' imported from " << PLoc.getFilename() << ':'
    618             << PLoc.getLine();
    619   Message << ":";
    620   emitNote(Loc, Message.str());
    621 }
    622 
    623 void DiagnosticNoteRenderer::emitBuildingModuleLocation(FullSourceLoc Loc,
    624                                                         PresumedLoc PLoc,
    625                                                         StringRef ModuleName) {
    626   // Generate a note indicating the include location.
    627   SmallString<200> MessageStorage;
    628   llvm::raw_svector_ostream Message(MessageStorage);
    629   if (PLoc.isValid())
    630     Message << "while building module '" << ModuleName << "' imported from "
    631             << PLoc.getFilename() << ':' << PLoc.getLine() << ":";
    632   else
    633     Message << "while building module '" << ModuleName << "':";
    634   emitNote(Loc, Message.str());
    635 }
    636