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