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
31using namespace clang;
32
33DiagnosticRenderer::DiagnosticRenderer(const LangOptions &LangOpts,
34                                       DiagnosticOptions *DiagOpts)
35    : LangOpts(LangOpts), DiagOpts(DiagOpts), LastLevel() {}
36
37DiagnosticRenderer::~DiagnosticRenderer() = default;
38
39namespace {
40
41class FixitReceiver : public edit::EditsReceiver {
42  SmallVectorImpl<FixItHint> &MergedFixits;
43
44public:
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
59static 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
87void 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
143void DiagnosticRenderer::emitStoredDiagnostic(StoredDiagnostic &Diag) {
144  emitDiagnostic(Diag.getLocation(), Diag.getLevel(), Diag.getMessage(),
145                 Diag.getRanges(), Diag.getFixIts(),
146                 &Diag);
147}
148
149void 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.
165void 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.
190void 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.
219void 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.
231void 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.
249void 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.
260static SourceLocation
261retrieveMacroLocation(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.
316static 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.
332static 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.
356static void
357mapDiagnosticRanges(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    // Do the backtracking.
398    SmallVector<FileID, 4> CommonArgExpansions;
399    computeCommonMacroArgExpansionFileIDs(Begin, End, SM, CommonArgExpansions);
400    Begin = retrieveMacroLocation(Begin, BeginFileID, CaretLocFileID,
401                                  CommonArgExpansions, /*IsBegin=*/true, SM,
402                                  IsTokenRange);
403    End = retrieveMacroLocation(End, BeginFileID, CaretLocFileID,
404                                CommonArgExpansions, /*IsBegin=*/false, SM,
405                                IsTokenRange);
406    if (Begin.isInvalid() || End.isInvalid()) continue;
407
408    // Return the spelling location of the beginning and end of the range.
409    Begin = SM->getSpellingLoc(Begin);
410    End = SM->getSpellingLoc(End);
411
412    SpellingRanges.push_back(CharSourceRange(SourceRange(Begin, End),
413                                             IsTokenRange));
414  }
415}
416
417void DiagnosticRenderer::emitCaret(FullSourceLoc Loc,
418                                   DiagnosticsEngine::Level Level,
419                                   ArrayRef<CharSourceRange> Ranges,
420                                   ArrayRef<FixItHint> Hints) {
421  SmallVector<CharSourceRange, 4> SpellingRanges;
422  mapDiagnosticRanges(Loc, Ranges, SpellingRanges);
423  emitCodeContext(Loc, Level, SpellingRanges, Hints);
424}
425
426/// A helper function for emitMacroExpansion to print the
427/// macro expansion message
428void DiagnosticRenderer::emitSingleMacroExpansion(
429    FullSourceLoc Loc, DiagnosticsEngine::Level Level,
430    ArrayRef<CharSourceRange> Ranges) {
431  // Find the spelling location for the macro definition. We must use the
432  // spelling location here to avoid emitting a macro backtrace for the note.
433  FullSourceLoc SpellingLoc = Loc.getSpellingLoc();
434
435  // Map the ranges into the FileID of the diagnostic location.
436  SmallVector<CharSourceRange, 4> SpellingRanges;
437  mapDiagnosticRanges(Loc, Ranges, SpellingRanges);
438
439  SmallString<100> MessageStorage;
440  llvm::raw_svector_ostream Message(MessageStorage);
441  StringRef MacroName = Lexer::getImmediateMacroNameForDiagnostics(
442      Loc, Loc.getManager(), LangOpts);
443  if (MacroName.empty())
444    Message << "expanded from here";
445  else
446    Message << "expanded from macro '" << MacroName << "'";
447
448  emitDiagnostic(SpellingLoc, DiagnosticsEngine::Note, Message.str(),
449                 SpellingRanges, None);
450}
451
452/// Check that the macro argument location of Loc starts with ArgumentLoc.
453/// The starting location of the macro expansions is used to differeniate
454/// different macro expansions.
455static bool checkLocForMacroArgExpansion(SourceLocation Loc,
456                                         const SourceManager &SM,
457                                         SourceLocation ArgumentLoc) {
458  SourceLocation MacroLoc;
459  if (SM.isMacroArgExpansion(Loc, &MacroLoc)) {
460    if (ArgumentLoc == MacroLoc) return true;
461  }
462
463  return false;
464}
465
466/// Check if all the locations in the range have the same macro argument
467/// expansion, and that the expansion starts with ArgumentLoc.
468static bool checkRangeForMacroArgExpansion(CharSourceRange Range,
469                                           const SourceManager &SM,
470                                           SourceLocation ArgumentLoc) {
471  SourceLocation BegLoc = Range.getBegin(), EndLoc = Range.getEnd();
472  while (BegLoc != EndLoc) {
473    if (!checkLocForMacroArgExpansion(BegLoc, SM, ArgumentLoc))
474      return false;
475    BegLoc.getLocWithOffset(1);
476  }
477
478  return checkLocForMacroArgExpansion(BegLoc, SM, ArgumentLoc);
479}
480
481/// A helper function to check if the current ranges are all inside the same
482/// macro argument expansion as Loc.
483static bool checkRangesForMacroArgExpansion(FullSourceLoc Loc,
484                                            ArrayRef<CharSourceRange> Ranges) {
485  assert(Loc.isMacroID() && "Must be a macro expansion!");
486
487  SmallVector<CharSourceRange, 4> SpellingRanges;
488  mapDiagnosticRanges(Loc, Ranges, SpellingRanges);
489
490  /// Count all valid ranges.
491  unsigned ValidCount = 0;
492  for (const auto &Range : Ranges)
493    if (Range.isValid())
494      ValidCount++;
495
496  if (ValidCount > SpellingRanges.size())
497    return false;
498
499  /// To store the source location of the argument location.
500  FullSourceLoc ArgumentLoc;
501
502  /// Set the ArgumentLoc to the beginning location of the expansion of Loc
503  /// so to check if the ranges expands to the same beginning location.
504  if (!Loc.isMacroArgExpansion(&ArgumentLoc))
505    return false;
506
507  for (const auto &Range : SpellingRanges)
508    if (!checkRangeForMacroArgExpansion(Range, Loc.getManager(), ArgumentLoc))
509      return false;
510
511  return true;
512}
513
514/// Recursively emit notes for each macro expansion and caret
515/// diagnostics where appropriate.
516///
517/// Walks up the macro expansion stack printing expansion notes, the code
518/// snippet, caret, underlines and FixItHint display as appropriate at each
519/// level.
520///
521/// \param Loc The location for this caret.
522/// \param Level The diagnostic level currently being emitted.
523/// \param Ranges The underlined ranges for this code snippet.
524/// \param Hints The FixIt hints active for this diagnostic.
525void DiagnosticRenderer::emitMacroExpansions(FullSourceLoc Loc,
526                                             DiagnosticsEngine::Level Level,
527                                             ArrayRef<CharSourceRange> Ranges,
528                                             ArrayRef<FixItHint> Hints) {
529  assert(Loc.isValid() && "must have a valid source location here");
530  const SourceManager &SM = Loc.getManager();
531  SourceLocation L = Loc;
532
533  // Produce a stack of macro backtraces.
534  SmallVector<SourceLocation, 8> LocationStack;
535  unsigned IgnoredEnd = 0;
536  while (L.isMacroID()) {
537    // If this is the expansion of a macro argument, point the caret at the
538    // use of the argument in the definition of the macro, not the expansion.
539    if (SM.isMacroArgExpansion(L))
540      LocationStack.push_back(SM.getImmediateExpansionRange(L).getBegin());
541    else
542      LocationStack.push_back(L);
543
544    if (checkRangesForMacroArgExpansion(FullSourceLoc(L, SM), Ranges))
545      IgnoredEnd = LocationStack.size();
546
547    L = SM.getImmediateMacroCallerLoc(L);
548
549    // Once the location no longer points into a macro, try stepping through
550    // the last found location.  This sometimes produces additional useful
551    // backtraces.
552    if (L.isFileID())
553      L = SM.getImmediateMacroCallerLoc(LocationStack.back());
554    assert(L.isValid() && "must have a valid source location here");
555  }
556
557  LocationStack.erase(LocationStack.begin(),
558                      LocationStack.begin() + IgnoredEnd);
559
560  unsigned MacroDepth = LocationStack.size();
561  unsigned MacroLimit = DiagOpts->MacroBacktraceLimit;
562  if (MacroDepth <= MacroLimit || MacroLimit == 0) {
563    for (auto I = LocationStack.rbegin(), E = LocationStack.rend();
564         I != E; ++I)
565      emitSingleMacroExpansion(FullSourceLoc(*I, SM), Level, Ranges);
566    return;
567  }
568
569  unsigned MacroStartMessages = MacroLimit / 2;
570  unsigned MacroEndMessages = MacroLimit / 2 + MacroLimit % 2;
571
572  for (auto I = LocationStack.rbegin(),
573            E = LocationStack.rbegin() + MacroStartMessages;
574       I != E; ++I)
575    emitSingleMacroExpansion(FullSourceLoc(*I, SM), Level, Ranges);
576
577  SmallString<200> MessageStorage;
578  llvm::raw_svector_ostream Message(MessageStorage);
579  Message << "(skipping " << (MacroDepth - MacroLimit)
580          << " expansions in backtrace; use -fmacro-backtrace-limit=0 to "
581             "see all)";
582  emitBasicNote(Message.str());
583
584  for (auto I = LocationStack.rend() - MacroEndMessages,
585            E = LocationStack.rend();
586       I != E; ++I)
587    emitSingleMacroExpansion(FullSourceLoc(*I, SM), Level, Ranges);
588}
589
590DiagnosticNoteRenderer::~DiagnosticNoteRenderer() = default;
591
592void DiagnosticNoteRenderer::emitIncludeLocation(FullSourceLoc Loc,
593                                                 PresumedLoc PLoc) {
594  // Generate a note indicating the include location.
595  SmallString<200> MessageStorage;
596  llvm::raw_svector_ostream Message(MessageStorage);
597  Message << "in file included from " << PLoc.getFilename() << ':'
598          << PLoc.getLine() << ":";
599  emitNote(Loc, Message.str());
600}
601
602void DiagnosticNoteRenderer::emitImportLocation(FullSourceLoc Loc,
603                                                PresumedLoc PLoc,
604                                                StringRef ModuleName) {
605  // Generate a note indicating the include location.
606  SmallString<200> MessageStorage;
607  llvm::raw_svector_ostream Message(MessageStorage);
608  Message << "in module '" << ModuleName;
609  if (PLoc.isValid())
610    Message << "' imported from " << PLoc.getFilename() << ':'
611            << PLoc.getLine();
612  Message << ":";
613  emitNote(Loc, Message.str());
614}
615
616void DiagnosticNoteRenderer::emitBuildingModuleLocation(FullSourceLoc Loc,
617                                                        PresumedLoc PLoc,
618                                                        StringRef ModuleName) {
619  // Generate a note indicating the include location.
620  SmallString<200> MessageStorage;
621  llvm::raw_svector_ostream Message(MessageStorage);
622  if (PLoc.isValid())
623    Message << "while building module '" << ModuleName << "' imported from "
624            << PLoc.getFilename() << ':' << PLoc.getLine() << ":";
625  else
626    Message << "while building module '" << ModuleName << "':";
627  emitNote(Loc, Message.str());
628}
629