clang  10.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
RangeSelector range(RangeSelector Begin, RangeSelector End)
Selects from the start of Begin and to the end of End.
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:1609
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:1022
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:92
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:152
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:129
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.