clang  5.0.0
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 isMacroArgExpansion(SourceLocation Loc, SourceLocation *StartLoc=nullptr) const
Tests whether the given source location represents a macro argument's expansion into the function-lik...
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 getBegin() const
bool isMacroID() const
void emitImportLocation(FullSourceLoc Loc, PresumedLoc PLoc, StringRef ModuleName) override
virtual void emitCodeContext(FullSourceLoc Loc, DiagnosticsEngine::Level Level, SmallVectorImpl< CharSourceRange > &Ranges, ArrayRef< FixItHint > Hints)=0
bool isValid() const
SourceLocation getImmediateSpellingLoc(SourceLocation Loc) const
Given a SourceLocation object, return the spelling location referenced by the ID. ...
SourceLocation getSpellingLoc(SourceLocation Loc) const
Given a SourceLocation object, return the spelling location referenced by the ID. ...
bool isInvalid() const
Return true if this object is invalid or uninitialized.
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.
std::pair< FullSourceLoc, StringRef > getModuleImportLoc() const
Defines the SourceManager interface.
StringRef getMessage() const
Definition: Diagnostic.h:1370
Represents a diagnostic in a form that can be retained until its corresponding source manager is dest...
Definition: Diagnostic.h:1346
void emitStoredDiagnostic(StoredDiagnostic &Diag)
const SourceManager & getManager() const
const FullSourceLoc & getLocation() const
Definition: Diagnostic.h:1369
std::string CodeToInsert
The actual code to insert at the insertion location, as a string.
Definition: Diagnostic.h:76
virtual void emitNote(FullSourceLoc Loc, StringRef Message)=0
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
FileID getFileID() const
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
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
bool isFileID() 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
FullSourceLoc getFileLoc() const
bool replace(CharSourceRange range, StringRef text)
Definition: Commit.cpp:111
SourceLocation getLocWithOffset(int Offset) const
Return a source location with the specified offset from this SourceLocation.
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.
unsigned getLine() const
Return the presumed line number of this location.
detail::InMemoryDirectory::const_iterator I
SourceLocation getIncludeLoc() const
Return the presumed include location of this location.
bool isInvalid() const
FileID getFileID(SourceLocation SpellingLoc) const
Return the FileID for a SourceLocation.
std::vector< bool > & Stack
const SmallVectorImpl< AnnotatedLine * >::const_iterator End
ModuleBuildStack getModuleBuildStack() const
Retrieve the module build stack.
Represents a character-granular source range.
SourceLocation getEnd() const
static bool checkLocForMacroArgExpansion(SourceLocation Loc, const SourceManager &SM, SourceLocation ArgumentLoc)
Check that the macro argument location of Loc starts with ArgumentLoc.
SourceLocation Begin
std::pair< FullSourceLoc, FullSourceLoc > getImmediateExpansionRange() const
bool BeforePreviousInsertions
Definition: Diagnostic.h:78
bool isMacroArgExpansion(FullSourceLoc *StartLoc=nullptr) const
IntrusiveRefCntPtr< DiagnosticOptions > DiagOpts
Represents an unpacked "presumed" location which can be presented to the user.
const SourceManager & SM
Definition: Format.cpp:1293
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
CharSourceRange RemoveRange
Code that should be replaced to correct the error.
Definition: Diagnostic.h:68
ArrayRef< FixItHint > getFixIts() const
Definition: Diagnostic.h:1388
llvm::PointerUnion< const Diagnostic *, const StoredDiagnostic * > DiagOrStoredDiag
bool isTokenRange() const
Return true if the end of this range specifies the start of the last token.
const char * getFilename() const
Return the presumed filename of this location.
Encodes a location in the source.
bool isValid() const
Return true if this is a valid SourceLocation object.
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)
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:1006
bool hasManager() const
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.
SourceLocation LastIncludeLoc
The location of the last include whose stack was printed if known.
std::pair< SourceLocation, SourceLocation > getImmediateExpansionRange(SourceLocation Loc) const
Return the start/end of the expansion information for an expansion location.
virtual void endDiagnostic(DiagOrStoredDiag D, DiagnosticsEngine::Level Level)
virtual void emitIncludeLocation(FullSourceLoc Loc, PresumedLoc PLoc)=0
detail::InMemoryDirectory::const_iterator E
PresumedLoc getPresumedLoc(bool UseLineDirectives=true) const
static void mergeFixits(ArrayRef< FixItHint > FixItHints, const SourceManager &SM, const LangOptions &LangOpts, SmallVectorImpl< FixItHint > &MergedFixits)
bool commit(const Commit &commit)
FullSourceLoc getImmediateMacroCallerLoc() 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
ArrayRef< CharSourceRange > getRanges() const
Definition: Diagnostic.h:1379
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
DiagnosticsEngine::Level getLevel() const
Definition: Diagnostic.h:1368
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.
This class handles loading and caching of source files into memory.
FullSourceLoc getSpellingLoc() const