clang  9.0.0svn
DiagnosticRenderer.cpp
Go to the documentation of this file.
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 
10 #include "clang/Basic/Diagnostic.h"
12 #include "clang/Basic/LLVM.h"
15 #include "clang/Edit/Commit.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 
34  DiagnosticOptions *DiagOpts)
35  : LangOpts(LangOpts), DiagOpts(DiagOpts), LastLevel() {}
36 
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 
89  StringRef Message,
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 
144  emitDiagnostic(Diag.getLocation(), Diag.getLevel(), Diag.getMessage(),
145  Diag.getRanges(), Diag.getFixIts(),
146  &Diag);
147 }
148 
149 void DiagnosticRenderer::emitBasicNote(StringRef Message) {
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,
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) {
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
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.
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.
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
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 
417 void DiagnosticRenderer::emitCaret(FullSourceLoc Loc,
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
428 void DiagnosticRenderer::emitSingleMacroExpansion(
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.
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.
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.
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.
525 void DiagnosticRenderer::emitMacroExpansions(FullSourceLoc Loc,
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 
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 
591 
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 
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 
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 }
bool remove(CharSourceRange range)
Definition: Commit.cpp:91
static DiagnosticBuilder Diag(DiagnosticsEngine *Diags, const LangOptions &Features, FullSourceLoc TokLoc, const char *TokBegin, const char *TokRangeBegin, const char *TokRangeEnd, unsigned DiagID)
Produce a diagnostic highlighting some portion of a literal.
SourceLocation getLocWithOffset(int Offset) const
Return a source location with the specified offset from this SourceLocation.
void emitImportLocation(FullSourceLoc Loc, PresumedLoc PLoc, StringRef ModuleName) override
virtual void emitCodeContext(FullSourceLoc Loc, DiagnosticsEngine::Level Level, SmallVectorImpl< CharSourceRange > &Ranges, ArrayRef< FixItHint > Hints)=0
static void getMacroArgExpansionFileIDs(SourceLocation Loc, SmallVectorImpl< FileID > &IDs, bool IsBegin, const SourceManager *SM)
Walk up the chain of macro expansions and collect the FileIDs identifying the expansions.
Defines the SourceManager interface.
Represents a diagnostic in a form that can be retained until its corresponding source manager is dest...
Definition: Diagnostic.h:1438
void emitStoredDiagnostic(StoredDiagnostic &Diag)
llvm::PointerUnion< const Diagnostic *, const StoredDiagnostic * > DiagOrStoredDiag
bool insertFromRange(SourceLocation loc, CharSourceRange range, bool afterToken=false, bool beforePreviousInsertions=false)
Definition: Commit.cpp:64
const LangOptions & LangOpts
static bool checkRangeForMacroArgExpansion(CharSourceRange Range, const SourceManager &SM, SourceLocation ArgumentLoc)
Check if all the locations in the range have the same macro argument expansion, and that the expansio...
static void computeCommonMacroArgExpansionFileIDs(SourceLocation Begin, SourceLocation End, const SourceManager *SM, SmallVectorImpl< FileID > &CommonArgExpansions)
Collect the expansions of the begin and end locations and compute the set intersection.
virtual void emitBuildingModuleLocation(FullSourceLoc Loc, PresumedLoc PLoc, StringRef ModuleName)=0
void emitIncludeLocation(FullSourceLoc Loc, PresumedLoc PLoc) override
FileID getFileID() const
static bool checkRangesForMacroArgExpansion(FullSourceLoc Loc, ArrayRef< CharSourceRange > Ranges)
A helper function to check if the current ranges are all inside the same macro argument expansion as ...
bool insert(SourceLocation loc, StringRef text, bool afterToken=false, bool beforePreviousInsertions=false)
Definition: Commit.cpp:48
SourceLocation getBegin() const
FullSourceLoc getFileLoc() const
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
Definition: LangOptions.h:49
virtual void emitImportLocation(FullSourceLoc Loc, PresumedLoc PLoc, StringRef ModuleName)=0
bool replace(CharSourceRange range, StringRef text)
Definition: Commit.cpp:116
ModuleBuildStack getModuleBuildStack() const
Retrieve the module build stack.
Forward-declares and imports various common LLVM datatypes that clang wants to use unqualified...
void emitDiagnostic(FullSourceLoc Loc, DiagnosticsEngine::Level Level, StringRef Message, ArrayRef< CharSourceRange > Ranges, ArrayRef< FixItHint > FixItHints, DiagOrStoredDiag D=(Diagnostic *) nullptr)
Emit a diagnostic.
DiagnosticsEngine::Level LastLevel
The level of the last diagnostic emitted.
ArrayRef< CharSourceRange > getRanges() const
Definition: Diagnostic.h:1472
Defines the Diagnostic-related interfaces.
PresumedLoc getPresumedLoc(bool UseLineDirectives=true) const
SourceLocation getSpellingLoc(SourceLocation Loc) const
Given a SourceLocation object, return the spelling location referenced by the ID. ...
StringRef getMessage() const
Definition: Diagnostic.h:1462
bool isValid() const
bool hasManager() const
SourceLocation getImmediateSpellingLoc(SourceLocation Loc) const
Given a SourceLocation object, return the spelling location referenced by the ID. ...
SourceLocation End
bool isMacroArgExpansion(FullSourceLoc *StartLoc=nullptr) const
Represents a character-granular source range.
DiagnosticsEngine::Level getLevel() const
Definition: Diagnostic.h:1460
bool isInvalid() const
Return true if this object is invalid or uninitialized.
ArrayRef< FixItHint > getFixIts() const
Definition: Diagnostic.h:1482
unsigned getLine() const
Return the presumed line number of this location.
static bool checkLocForMacroArgExpansion(SourceLocation Loc, const SourceManager &SM, SourceLocation ArgumentLoc)
Check that the macro argument location of Loc starts with ArgumentLoc.
const SourceManager & getManager() const
SourceLocation Begin
CharSourceRange getImmediateExpansionRange(SourceLocation Loc) const
Return the start/end of the expansion information for an expansion location.
IntrusiveRefCntPtr< DiagnosticOptions > DiagOpts
Represents an unpacked "presumed" location which can be presented to the user.
const SourceManager & SM
Definition: Format.cpp:1568
virtual void emitDiagnosticMessage(FullSourceLoc Loc, PresumedLoc PLoc, DiagnosticsEngine::Level Level, StringRef Message, ArrayRef< CharSourceRange > Ranges, DiagOrStoredDiag Info)=0
const char * getFilename() const
Return the presumed filename of this location.
Encodes a location in the source.
Options for controlling the compiler diagnostics engine.
virtual void beginDiagnostic(DiagOrStoredDiag D, DiagnosticsEngine::Level Level)
static void mapDiagnosticRanges(FullSourceLoc CaretLoc, ArrayRef< CharSourceRange > Ranges, SmallVectorImpl< CharSourceRange > &SpellingRanges)
std::pair< FullSourceLoc, StringRef > getModuleImportLoc() const
DiagnosticRenderer(const LangOptions &LangOpts, DiagnosticOptions *DiagOpts)
static StringRef getImmediateMacroNameForDiagnostics(SourceLocation Loc, const SourceManager &SM, const LangOptions &LangOpts)
Retrieve the name of the immediate macro expansion.
Definition: Lexer.cpp:1014
bool isTokenRange() const
Return true if the end of this range specifies the start of the last token.
An opaque identifier used by SourceManager which refers to a source file (MemoryBuffer) along with it...
SourceLocation LastLoc
The location of the previous diagnostic if known.
Dataflow Directional Tag Classes.
bool isValid() const
Return true if this is a valid SourceLocation object.
SourceLocation LastIncludeLoc
The location of the last include whose stack was printed if known.
const FullSourceLoc & getLocation() const
Definition: Diagnostic.h:1461
virtual void endDiagnostic(DiagOrStoredDiag D, DiagnosticsEngine::Level Level)
virtual void emitIncludeLocation(FullSourceLoc Loc, PresumedLoc PLoc)=0
bool isMacroID() const
static void mergeFixits(ArrayRef< FixItHint > FixItHints, const SourceManager &SM, const LangOptions &LangOpts, SmallVectorImpl< FixItHint > &MergedFixits)
FileID getFileID(SourceLocation SpellingLoc) const
Return the FileID for a SourceLocation.
bool isMacroArgExpansion(SourceLocation Loc, SourceLocation *StartLoc=nullptr) const
Tests whether the given source location represents a macro argument&#39;s expansion into the function-lik...
bool commit(const Commit &commit)
SourceLocation getEnd() const
static FixItHint CreateInsertion(SourceLocation InsertionLoc, StringRef Code, bool BeforePreviousInsertions=false)
Create a code modification hint that inserts the given code string at a specific location.
Definition: Diagnostic.h:91
void applyRewrites(EditsReceiver &receiver, bool adjustRemovals=true)
Defines the clang::SourceLocation class and associated facilities.
Level
The level of the diagnostic, after it has been through mapping.
Definition: Diagnostic.h:151
static FixItHint CreateReplacement(CharSourceRange RemoveRange, StringRef Code)
Create a code modification hint that replaces the given source range with the given code string...
Definition: Diagnostic.h:128
FullSourceLoc getSpellingLoc() const
A SourceLocation and its associated SourceManager.
void emitBuildingModuleLocation(FullSourceLoc Loc, PresumedLoc PLoc, StringRef ModuleName) override
static SourceLocation retrieveMacroLocation(SourceLocation Loc, FileID MacroFileID, FileID CaretFileID, const SmallVectorImpl< FileID > &CommonArgExpansions, bool IsBegin, const SourceManager *SM, bool &IsTokenRange)
A recursive function to trace all possible backtrace locations to match the CaretLocFileID.
A trivial tuple used to represent a source range.
SourceLocation getIncludeLoc() const
Return the presumed include location of this location.
This class handles loading and caching of source files into memory.