clang  3.8.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 
14 #include "clang/Edit/Commit.h"
17 #include "clang/Lex/Lexer.h"
18 #include "llvm/ADT/SmallSet.h"
19 #include "llvm/ADT/SmallString.h"
20 #include "llvm/Support/ErrorHandling.h"
21 #include "llvm/Support/MemoryBuffer.h"
22 #include "llvm/Support/raw_ostream.h"
23 #include <algorithm>
24 using namespace clang;
25 
26 /// \brief Retrieve the name of the immediate macro expansion.
27 ///
28 /// This routine starts from a source location, and finds the name of the macro
29 /// responsible for its immediate expansion. It looks through any intervening
30 /// macro argument expansions to compute this. It returns a StringRef which
31 /// refers to the SourceManager-owned buffer of the source where that macro
32 /// name is spelled. Thus, the result shouldn't out-live that SourceManager.
33 ///
34 /// This differs from Lexer::getImmediateMacroName in that any macro argument
35 /// location will result in the topmost function macro that accepted it.
36 /// e.g.
37 /// \code
38 /// MAC1( MAC2(foo) )
39 /// \endcode
40 /// for location of 'foo' token, this function will return "MAC1" while
41 /// Lexer::getImmediateMacroName will return "MAC2".
43  const SourceManager &SM,
44  const LangOptions &LangOpts) {
45  assert(Loc.isMacroID() && "Only reasonble to call this on macros");
46  // Walk past macro argument expanions.
47  while (SM.isMacroArgExpansion(Loc))
48  Loc = SM.getImmediateExpansionRange(Loc).first;
49 
50  // If the macro's spelling has no FileID, then it's actually a token paste
51  // or stringization (or similar) and not a macro at all.
52  if (!SM.getFileEntryForID(SM.getFileID(SM.getSpellingLoc(Loc))))
53  return StringRef();
54 
55  // Find the spelling location of the start of the non-argument expansion
56  // range. This is where the macro name was spelled in order to begin
57  // expanding this macro.
58  Loc = SM.getSpellingLoc(SM.getImmediateExpansionRange(Loc).first);
59 
60  // Dig out the buffer where the macro name was spelled and the extents of the
61  // name so that we can render it into the expansion note.
62  std::pair<FileID, unsigned> ExpansionInfo = SM.getDecomposedLoc(Loc);
63  unsigned MacroTokenLength = Lexer::MeasureTokenLength(Loc, SM, LangOpts);
64  StringRef ExpansionBuffer = SM.getBufferData(ExpansionInfo.first);
65  return ExpansionBuffer.substr(ExpansionInfo.second, MacroTokenLength);
66 }
67 
69  DiagnosticOptions *DiagOpts)
70  : LangOpts(LangOpts), DiagOpts(DiagOpts), LastLevel() {}
71 
73 
74 namespace {
75 
76 class FixitReceiver : public edit::EditsReceiver {
77  SmallVectorImpl<FixItHint> &MergedFixits;
78 
79 public:
80  FixitReceiver(SmallVectorImpl<FixItHint> &MergedFixits)
81  : MergedFixits(MergedFixits) { }
82  void insert(SourceLocation loc, StringRef text) override {
83  MergedFixits.push_back(FixItHint::CreateInsertion(loc, text));
84  }
85  void replace(CharSourceRange range, StringRef text) override {
86  MergedFixits.push_back(FixItHint::CreateReplacement(range, text));
87  }
88 };
89 
90 }
91 
92 static void mergeFixits(ArrayRef<FixItHint> FixItHints,
93  const SourceManager &SM, const LangOptions &LangOpts,
94  SmallVectorImpl<FixItHint> &MergedFixits) {
95  edit::Commit commit(SM, LangOpts);
97  I = FixItHints.begin(), E = FixItHints.end(); I != E; ++I) {
98  const FixItHint &Hint = *I;
99  if (Hint.CodeToInsert.empty()) {
100  if (Hint.InsertFromRange.isValid())
101  commit.insertFromRange(Hint.RemoveRange.getBegin(),
102  Hint.InsertFromRange, /*afterToken=*/false,
104  else
105  commit.remove(Hint.RemoveRange);
106  } else {
107  if (Hint.RemoveRange.isTokenRange() ||
108  Hint.RemoveRange.getBegin() != Hint.RemoveRange.getEnd())
109  commit.replace(Hint.RemoveRange, Hint.CodeToInsert);
110  else
111  commit.insert(Hint.RemoveRange.getBegin(), Hint.CodeToInsert,
112  /*afterToken=*/false, Hint.BeforePreviousInsertions);
113  }
114  }
115 
116  edit::EditedSource Editor(SM, LangOpts);
117  if (Editor.commit(commit)) {
118  FixitReceiver Rec(MergedFixits);
119  Editor.applyRewrites(Rec);
120  }
121 }
122 
125  StringRef Message,
127  ArrayRef<FixItHint> FixItHints,
128  const SourceManager *SM,
129  DiagOrStoredDiag D) {
130  assert(SM || Loc.isInvalid());
131 
132  beginDiagnostic(D, Level);
133 
134  if (!Loc.isValid())
135  // If we have no source location, just emit the diagnostic message.
136  emitDiagnosticMessage(Loc, PresumedLoc(), Level, Message, Ranges, SM, D);
137  else {
138  // Get the ranges into a local array we can hack on.
139  SmallVector<CharSourceRange, 20> MutableRanges(Ranges.begin(),
140  Ranges.end());
141 
142  SmallVector<FixItHint, 8> MergedFixits;
143  if (!FixItHints.empty()) {
144  mergeFixits(FixItHints, *SM, LangOpts, MergedFixits);
145  FixItHints = MergedFixits;
146  }
147 
148  for (ArrayRef<FixItHint>::const_iterator I = FixItHints.begin(),
149  E = FixItHints.end();
150  I != E; ++I)
151  if (I->RemoveRange.isValid())
152  MutableRanges.push_back(I->RemoveRange);
153 
154  SourceLocation UnexpandedLoc = Loc;
155 
156  // Find the ultimate expansion location for the diagnostic.
157  Loc = SM->getFileLoc(Loc);
158 
159  PresumedLoc PLoc = SM->getPresumedLoc(Loc, DiagOpts->ShowPresumedLoc);
160 
161  // First, if this diagnostic is not in the main file, print out the
162  // "included from" lines.
163  emitIncludeStack(Loc, PLoc, Level, *SM);
164 
165  // Next, emit the actual diagnostic message and caret.
166  emitDiagnosticMessage(Loc, PLoc, Level, Message, Ranges, SM, D);
167  emitCaret(Loc, Level, MutableRanges, FixItHints, *SM);
168 
169  // If this location is within a macro, walk from UnexpandedLoc up to Loc
170  // and produce a macro backtrace.
171  if (UnexpandedLoc.isValid() && UnexpandedLoc.isMacroID()) {
172  emitMacroExpansions(UnexpandedLoc, Level, MutableRanges, FixItHints, *SM);
173  }
174  }
175 
176  LastLoc = Loc;
177  LastLevel = Level;
178 
179  endDiagnostic(D, Level);
180 }
181 
182 
184  emitDiagnostic(Diag.getLocation(), Diag.getLevel(), Diag.getMessage(),
185  Diag.getRanges(), Diag.getFixIts(),
186  Diag.getLocation().isValid() ? &Diag.getLocation().getManager()
187  : nullptr,
188  &Diag);
189 }
190 
191 void DiagnosticRenderer::emitBasicNote(StringRef Message) {
194  None, nullptr, DiagOrStoredDiag());
195 }
196 
197 /// \brief Prints an include stack when appropriate for a particular
198 /// diagnostic level and location.
199 ///
200 /// This routine handles all the logic of suppressing particular include
201 /// stacks (such as those for notes) and duplicate include stacks when
202 /// repeated warnings occur within the same file. It also handles the logic
203 /// of customizing the formatting and display of the include stack.
204 ///
205 /// \param Loc The diagnostic location.
206 /// \param PLoc The presumed location of the diagnostic location.
207 /// \param Level The diagnostic level of the message this stack pertains to.
208 void DiagnosticRenderer::emitIncludeStack(SourceLocation Loc,
209  PresumedLoc PLoc,
211  const SourceManager &SM) {
212  SourceLocation IncludeLoc = PLoc.getIncludeLoc();
213 
214  // Skip redundant include stacks altogether.
215  if (LastIncludeLoc == IncludeLoc)
216  return;
217 
218  LastIncludeLoc = IncludeLoc;
219 
220  if (!DiagOpts->ShowNoteIncludeStack && Level == DiagnosticsEngine::Note)
221  return;
222 
223  if (IncludeLoc.isValid())
224  emitIncludeStackRecursively(IncludeLoc, SM);
225  else {
226  emitModuleBuildStack(SM);
227  emitImportStack(Loc, SM);
228  }
229 }
230 
231 /// \brief Helper to recursivly walk up the include stack and print each layer
232 /// on the way back down.
233 void DiagnosticRenderer::emitIncludeStackRecursively(SourceLocation Loc,
234  const SourceManager &SM) {
235  if (Loc.isInvalid()) {
236  emitModuleBuildStack(SM);
237  return;
238  }
239 
240  PresumedLoc PLoc = SM.getPresumedLoc(Loc, DiagOpts->ShowPresumedLoc);
241  if (PLoc.isInvalid())
242  return;
243 
244  // If this source location was imported from a module, print the module
245  // import stack rather than the
246  // FIXME: We want submodule granularity here.
247  std::pair<SourceLocation, StringRef> Imported = SM.getModuleImportLoc(Loc);
248  if (!Imported.second.empty()) {
249  // This location was imported by a module. Emit the module import stack.
250  emitImportStackRecursively(Imported.first, Imported.second, SM);
251  return;
252  }
253 
254  // Emit the other include frames first.
255  emitIncludeStackRecursively(PLoc.getIncludeLoc(), SM);
256 
257  // Emit the inclusion text/note.
258  emitIncludeLocation(Loc, PLoc, SM);
259 }
260 
261 /// \brief Emit the module import stack associated with the current location.
262 void DiagnosticRenderer::emitImportStack(SourceLocation Loc,
263  const SourceManager &SM) {
264  if (Loc.isInvalid()) {
265  emitModuleBuildStack(SM);
266  return;
267  }
268 
269  std::pair<SourceLocation, StringRef> NextImportLoc
270  = SM.getModuleImportLoc(Loc);
271  emitImportStackRecursively(NextImportLoc.first, NextImportLoc.second, SM);
272 }
273 
274 /// \brief Helper to recursivly walk up the import stack and print each layer
275 /// on the way back down.
276 void DiagnosticRenderer::emitImportStackRecursively(SourceLocation Loc,
277  StringRef ModuleName,
278  const SourceManager &SM) {
279  if (ModuleName.empty()) {
280  return;
281  }
282 
283  PresumedLoc PLoc = SM.getPresumedLoc(Loc, DiagOpts->ShowPresumedLoc);
284 
285  // Emit the other import frames first.
286  std::pair<SourceLocation, StringRef> NextImportLoc
287  = SM.getModuleImportLoc(Loc);
288  emitImportStackRecursively(NextImportLoc.first, NextImportLoc.second, SM);
289 
290  // Emit the inclusion text/note.
291  emitImportLocation(Loc, PLoc, ModuleName, SM);
292 }
293 
294 /// \brief Emit the module build stack, for cases where a module is (re-)built
295 /// on demand.
296 void DiagnosticRenderer::emitModuleBuildStack(const SourceManager &SM) {
298  for (unsigned I = 0, N = Stack.size(); I != N; ++I) {
299  const SourceManager &CurSM = Stack[I].second.getManager();
300  SourceLocation CurLoc = Stack[I].second;
302  CurSM.getPresumedLoc(CurLoc,
303  DiagOpts->ShowPresumedLoc),
304  Stack[I].first,
305  CurSM);
306  }
307 }
308 
309 /// A recursive function to trace all possible backtrace locations
310 /// to match the \p CaretLocFileID.
311 static SourceLocation
313  FileID CaretFileID,
314  const SmallVectorImpl<FileID> &CommonArgExpansions,
315  bool IsBegin, const SourceManager *SM) {
316  assert(SM->getFileID(Loc) == MacroFileID);
317  if (MacroFileID == CaretFileID)
318  return Loc;
319  if (!Loc.isMacroID())
320  return SourceLocation();
321 
322  SourceLocation MacroLocation, MacroArgLocation;
323 
324  if (SM->isMacroArgExpansion(Loc)) {
325  // Only look at the immediate spelling location of this macro argument if
326  // the other location in the source range is also present in that expansion.
327  if (std::binary_search(CommonArgExpansions.begin(),
328  CommonArgExpansions.end(), MacroFileID))
329  MacroLocation = SM->getImmediateSpellingLoc(Loc);
330  MacroArgLocation = IsBegin ? SM->getImmediateExpansionRange(Loc).first
331  : SM->getImmediateExpansionRange(Loc).second;
332  } else {
333  MacroLocation = IsBegin ? SM->getImmediateExpansionRange(Loc).first
334  : SM->getImmediateExpansionRange(Loc).second;
335  MacroArgLocation = SM->getImmediateSpellingLoc(Loc);
336  }
337 
338  if (MacroLocation.isValid()) {
339  MacroFileID = SM->getFileID(MacroLocation);
340  MacroLocation =
341  retrieveMacroLocation(MacroLocation, MacroFileID, CaretFileID,
342  CommonArgExpansions, IsBegin, SM);
343  if (MacroLocation.isValid())
344  return MacroLocation;
345  }
346 
347  MacroFileID = SM->getFileID(MacroArgLocation);
348  return retrieveMacroLocation(MacroArgLocation, MacroFileID, CaretFileID,
349  CommonArgExpansions, IsBegin, SM);
350 }
351 
352 /// Walk up the chain of macro expansions and collect the FileIDs identifying the
353 /// expansions.
356  bool IsBegin, const SourceManager *SM) {
357  while (Loc.isMacroID()) {
358  if (SM->isMacroArgExpansion(Loc)) {
359  IDs.push_back(SM->getFileID(Loc));
360  Loc = SM->getImmediateSpellingLoc(Loc);
361  } else {
362  auto ExpRange = SM->getImmediateExpansionRange(Loc);
363  Loc = IsBegin ? ExpRange.first : ExpRange.second;
364  }
365  }
366 }
367 
368 /// Collect the expansions of the begin and end locations and compute the set
369 /// intersection. Produces a sorted vector of FileIDs in CommonArgExpansions.
372  SmallVectorImpl<FileID> &CommonArgExpansions) {
373  SmallVector<FileID, 4> BeginArgExpansions;
374  SmallVector<FileID, 4> EndArgExpansions;
375  getMacroArgExpansionFileIDs(Begin, BeginArgExpansions, /*IsBegin=*/true, SM);
376  getMacroArgExpansionFileIDs(End, EndArgExpansions, /*IsBegin=*/false, SM);
377  std::sort(BeginArgExpansions.begin(), BeginArgExpansions.end());
378  std::sort(EndArgExpansions.begin(), EndArgExpansions.end());
379  std::set_intersection(BeginArgExpansions.begin(), BeginArgExpansions.end(),
380  EndArgExpansions.begin(), EndArgExpansions.end(),
381  std::back_inserter(CommonArgExpansions));
382 }
383 
384 // Helper function to fix up source ranges. It takes in an array of ranges,
385 // and outputs an array of ranges where we want to draw the range highlighting
386 // around the location specified by CaretLoc.
387 //
388 // To find locations which correspond to the caret, we crawl the macro caller
389 // chain for the beginning and end of each range. If the caret location
390 // is in a macro expansion, we search each chain for a location
391 // in the same expansion as the caret; otherwise, we crawl to the top of
392 // each chain. Two locations are part of the same macro expansion
393 // iff the FileID is the same.
395  SourceLocation CaretLoc,
397  SmallVectorImpl<CharSourceRange> &SpellingRanges,
398  const SourceManager *SM) {
399  FileID CaretLocFileID = SM->getFileID(CaretLoc);
400 
401  for (auto I = Ranges.begin(), E = Ranges.end(); I != E; ++I) {
402  if (I->isInvalid()) continue;
403 
404  SourceLocation Begin = I->getBegin(), End = I->getEnd();
405  bool IsTokenRange = I->isTokenRange();
406 
407  FileID BeginFileID = SM->getFileID(Begin);
408  FileID EndFileID = SM->getFileID(End);
409 
410  // Find the common parent for the beginning and end of the range.
411 
412  // First, crawl the expansion chain for the beginning of the range.
413  llvm::SmallDenseMap<FileID, SourceLocation> BeginLocsMap;
414  while (Begin.isMacroID() && BeginFileID != EndFileID) {
415  BeginLocsMap[BeginFileID] = Begin;
416  Begin = SM->getImmediateExpansionRange(Begin).first;
417  BeginFileID = SM->getFileID(Begin);
418  }
419 
420  // Then, crawl the expansion chain for the end of the range.
421  if (BeginFileID != EndFileID) {
422  while (End.isMacroID() && !BeginLocsMap.count(EndFileID)) {
423  End = SM->getImmediateExpansionRange(End).second;
424  EndFileID = SM->getFileID(End);
425  }
426  if (End.isMacroID()) {
427  Begin = BeginLocsMap[EndFileID];
428  BeginFileID = EndFileID;
429  }
430  }
431 
432  // Do the backtracking.
433  SmallVector<FileID, 4> CommonArgExpansions;
434  computeCommonMacroArgExpansionFileIDs(Begin, End, SM, CommonArgExpansions);
435  Begin = retrieveMacroLocation(Begin, BeginFileID, CaretLocFileID,
436  CommonArgExpansions, /*IsBegin=*/true, SM);
437  End = retrieveMacroLocation(End, BeginFileID, CaretLocFileID,
438  CommonArgExpansions, /*IsBegin=*/false, SM);
439  if (Begin.isInvalid() || End.isInvalid()) continue;
440 
441  // Return the spelling location of the beginning and end of the range.
442  Begin = SM->getSpellingLoc(Begin);
443  End = SM->getSpellingLoc(End);
444 
445  SpellingRanges.push_back(CharSourceRange(SourceRange(Begin, End),
446  IsTokenRange));
447  }
448 }
449 
450 void DiagnosticRenderer::emitCaret(SourceLocation Loc,
453  ArrayRef<FixItHint> Hints,
454  const SourceManager &SM) {
455  SmallVector<CharSourceRange, 4> SpellingRanges;
456  mapDiagnosticRanges(Loc, Ranges, SpellingRanges, &SM);
457  emitCodeContext(Loc, Level, SpellingRanges, Hints, SM);
458 }
459 
460 /// \brief A helper function for emitMacroExpansion to print the
461 /// macro expansion message
462 void DiagnosticRenderer::emitSingleMacroExpansion(
463  SourceLocation Loc,
466  const SourceManager &SM) {
467  // Find the spelling location for the macro definition. We must use the
468  // spelling location here to avoid emitting a macro backtrace for the note.
469  SourceLocation SpellingLoc = SM.getSpellingLoc(Loc);
470 
471  // Map the ranges into the FileID of the diagnostic location.
472  SmallVector<CharSourceRange, 4> SpellingRanges;
473  mapDiagnosticRanges(Loc, Ranges, SpellingRanges, &SM);
474 
475  SmallString<100> MessageStorage;
476  llvm::raw_svector_ostream Message(MessageStorage);
477  StringRef MacroName = getImmediateMacroName(Loc, SM, LangOpts);
478  if (MacroName.empty())
479  Message << "expanded from here";
480  else
481  Message << "expanded from macro '" << MacroName << "'";
482 
483  emitDiagnostic(SpellingLoc, DiagnosticsEngine::Note, Message.str(),
484  SpellingRanges, None, &SM);
485 }
486 
487 /// Check that the macro argument location of Loc starts with ArgumentLoc.
488 /// The starting location of the macro expansions is used to differeniate
489 /// different macro expansions.
491  const SourceManager &SM,
492  SourceLocation ArgumentLoc) {
493  SourceLocation MacroLoc;
494  if (SM.isMacroArgExpansion(Loc, &MacroLoc)) {
495  if (ArgumentLoc == MacroLoc) return true;
496  }
497 
498  return false;
499 }
500 
501 /// Check if all the locations in the range have the same macro argument
502 /// expansion, and that that expansion starts with ArgumentLoc.
504  const SourceManager &SM,
505  SourceLocation ArgumentLoc) {
506  SourceLocation BegLoc = Range.getBegin(), EndLoc = Range.getEnd();
507  while (BegLoc != EndLoc) {
508  if (!checkLocForMacroArgExpansion(BegLoc, SM, ArgumentLoc))
509  return false;
510  BegLoc.getLocWithOffset(1);
511  }
512 
513  return checkLocForMacroArgExpansion(BegLoc, SM, ArgumentLoc);
514 }
515 
516 /// A helper function to check if the current ranges are all inside the same
517 /// macro argument expansion as Loc.
520  const SourceManager &SM) {
521  assert(Loc.isMacroID() && "Must be a macro expansion!");
522 
523  SmallVector<CharSourceRange, 4> SpellingRanges;
524  mapDiagnosticRanges(Loc, Ranges, SpellingRanges, &SM);
525 
526  /// Count all valid ranges.
527  unsigned ValidCount = 0;
528  for (auto I : Ranges)
529  if (I.isValid()) ValidCount++;
530 
531  if (ValidCount > SpellingRanges.size())
532  return false;
533 
534  /// To store the source location of the argument location.
535  SourceLocation ArgumentLoc;
536 
537  /// Set the ArgumentLoc to the beginning location of the expansion of Loc
538  /// so to check if the ranges expands to the same beginning location.
539  if (!SM.isMacroArgExpansion(Loc,&ArgumentLoc))
540  return false;
541 
542  for (auto I = SpellingRanges.begin(), E = SpellingRanges.end(); I != E; ++I) {
543  if (!checkRangeForMacroArgExpansion(*I, SM, ArgumentLoc))
544  return false;
545  }
546 
547  return true;
548 }
549 
550 /// \brief Recursively emit notes for each macro expansion and caret
551 /// diagnostics where appropriate.
552 ///
553 /// Walks up the macro expansion stack printing expansion notes, the code
554 /// snippet, caret, underlines and FixItHint display as appropriate at each
555 /// level.
556 ///
557 /// \param Loc The location for this caret.
558 /// \param Level The diagnostic level currently being emitted.
559 /// \param Ranges The underlined ranges for this code snippet.
560 /// \param Hints The FixIt hints active for this diagnostic.
561 void DiagnosticRenderer::emitMacroExpansions(SourceLocation Loc,
564  ArrayRef<FixItHint> Hints,
565  const SourceManager &SM) {
566  assert(Loc.isValid() && "must have a valid source location here");
567 
568  // Produce a stack of macro backtraces.
569  SmallVector<SourceLocation, 8> LocationStack;
570  unsigned IgnoredEnd = 0;
571  while (Loc.isMacroID()) {
572  // If this is the expansion of a macro argument, point the caret at the
573  // use of the argument in the definition of the macro, not the expansion.
574  if (SM.isMacroArgExpansion(Loc))
575  LocationStack.push_back(SM.getImmediateExpansionRange(Loc).first);
576  else
577  LocationStack.push_back(Loc);
578 
579  if (checkRangesForMacroArgExpansion(Loc, Ranges, SM))
580  IgnoredEnd = LocationStack.size();
581 
582  Loc = SM.getImmediateMacroCallerLoc(Loc);
583 
584  // Once the location no longer points into a macro, try stepping through
585  // the last found location. This sometimes produces additional useful
586  // backtraces.
587  if (Loc.isFileID())
588  Loc = SM.getImmediateMacroCallerLoc(LocationStack.back());
589  assert(Loc.isValid() && "must have a valid source location here");
590  }
591 
592  LocationStack.erase(LocationStack.begin(),
593  LocationStack.begin() + IgnoredEnd);
594 
595  unsigned MacroDepth = LocationStack.size();
596  unsigned MacroLimit = DiagOpts->MacroBacktraceLimit;
597  if (MacroDepth <= MacroLimit || MacroLimit == 0) {
598  for (auto I = LocationStack.rbegin(), E = LocationStack.rend();
599  I != E; ++I)
600  emitSingleMacroExpansion(*I, Level, Ranges, SM);
601  return;
602  }
603 
604  unsigned MacroStartMessages = MacroLimit / 2;
605  unsigned MacroEndMessages = MacroLimit / 2 + MacroLimit % 2;
606 
607  for (auto I = LocationStack.rbegin(),
608  E = LocationStack.rbegin() + MacroStartMessages;
609  I != E; ++I)
610  emitSingleMacroExpansion(*I, Level, Ranges, SM);
611 
612  SmallString<200> MessageStorage;
613  llvm::raw_svector_ostream Message(MessageStorage);
614  Message << "(skipping " << (MacroDepth - MacroLimit)
615  << " expansions in backtrace; use -fmacro-backtrace-limit=0 to "
616  "see all)";
617  emitBasicNote(Message.str());
618 
619  for (auto I = LocationStack.rend() - MacroEndMessages,
620  E = LocationStack.rend();
621  I != E; ++I)
622  emitSingleMacroExpansion(*I, Level, Ranges, SM);
623 }
624 
626 
628  PresumedLoc PLoc,
629  const SourceManager &SM) {
630  // Generate a note indicating the include location.
631  SmallString<200> MessageStorage;
632  llvm::raw_svector_ostream Message(MessageStorage);
633  Message << "in file included from " << PLoc.getFilename() << ':'
634  << PLoc.getLine() << ":";
635  emitNote(Loc, Message.str(), &SM);
636 }
637 
639  PresumedLoc PLoc,
640  StringRef ModuleName,
641  const SourceManager &SM) {
642  // Generate a note indicating the include location.
643  SmallString<200> MessageStorage;
644  llvm::raw_svector_ostream Message(MessageStorage);
645  Message << "in module '" << ModuleName;
646  if (PLoc.isValid())
647  Message << "' imported from " << PLoc.getFilename() << ':'
648  << PLoc.getLine();
649  Message << ":";
650  emitNote(Loc, Message.str(), &SM);
651 }
652 
653 void
655  PresumedLoc PLoc,
656  StringRef ModuleName,
657  const SourceManager &SM) {
658  // Generate a note indicating the include location.
659  SmallString<200> MessageStorage;
660  llvm::raw_svector_ostream Message(MessageStorage);
661  if (PLoc.getFilename())
662  Message << "while building module '" << ModuleName << "' imported from "
663  << PLoc.getFilename() << ':' << PLoc.getLine() << ":";
664  else
665  Message << "while building module '" << ModuleName << "':";
666  emitNote(Loc, Message.str(), &SM);
667 }
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.
void emitDiagnostic(SourceLocation Loc, DiagnosticsEngine::Level Level, StringRef Message, ArrayRef< CharSourceRange > Ranges, ArrayRef< FixItHint > FixItHints, const SourceManager *SM, DiagOrStoredDiag D=(Diagnostic *) nullptr)
Emit a diagnostic.
SourceLocation getBegin() const
bool isMacroID() const
bool isValid() const
Defines the clang::FileManager interface and associated types.
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.
Defines the SourceManager interface.
virtual void emitBuildingModuleLocation(SourceLocation Loc, PresumedLoc PLoc, StringRef ModuleName, const SourceManager &SM)=0
StringRef getMessage() const
Definition: Diagnostic.h:1281
Represents a diagnostic in a form that can be retained until its corresponding source manager is dest...
Definition: Diagnostic.h:1257
void emitStoredDiagnostic(StoredDiagnostic &Diag)
const SourceManager & getManager() const
const FullSourceLoc & getLocation() const
Definition: Diagnostic.h:1280
std::string CodeToInsert
The actual code to insert at the insertion location, as a string.
Definition: Diagnostic.h:64
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.
void applyRewrites(EditsReceiver &receiver)
bool insert(SourceLocation loc, StringRef text, bool afterToken=false, bool beforePreviousInsertions=false)
Definition: Commit.cpp:43
StringRef getBufferData(FileID FID, bool *Invalid=nullptr) const
Return a StringRef to the source buffer data for the specified FileID.
bool isFileID() const
virtual void emitDiagnosticMessage(SourceLocation Loc, PresumedLoc PLoc, DiagnosticsEngine::Level Level, StringRef Message, ArrayRef< CharSourceRange > Ranges, const SourceManager *SM, DiagOrStoredDiag Info)=0
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
Definition: LangOptions.h:48
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.
SmallVector< CharSourceRange, 8 > Ranges
Definition: Format.cpp:1715
SourceLocation getImmediateMacroCallerLoc(SourceLocation Loc) const
Gets the location of the immediate macro caller, one level up the stack toward the initial macro type...
void emitImportLocation(SourceLocation Loc, PresumedLoc PLoc, StringRef ModuleName, const SourceManager &SM) override
DiagnosticsEngine::Level LastLevel
The level of the last diagnostic emitted.
unsigned getLine() const
Return the presumed line number of this location.
void emitIncludeLocation(SourceLocation Loc, PresumedLoc PLoc, const SourceManager &SM) override
detail::InMemoryDirectory::const_iterator I
SourceLocation getIncludeLoc() const
Return the presumed include location of this location.
bool isInvalid() const
const FileEntry * getFileEntryForID(FileID FID) const
Returns the FileEntry record for the provided FileID.
FileID getFileID(SourceLocation SpellingLoc) const
Return the FileID for a SourceLocation.
static void mapDiagnosticRanges(SourceLocation CaretLoc, ArrayRef< CharSourceRange > Ranges, SmallVectorImpl< CharSourceRange > &SpellingRanges, const SourceManager *SM)
std::vector< bool > & Stack
const SmallVectorImpl< AnnotatedLine * >::const_iterator End
SourceManager & SM
ModuleBuildStack getModuleBuildStack() const
Retrieve the module build stack.
Represents a character-granular source range.
SourceLocation getEnd() const
static unsigned MeasureTokenLength(SourceLocation Loc, const SourceManager &SM, const LangOptions &LangOpts)
MeasureTokenLength - Relex the token at the specified location and return its length in bytes in the ...
Definition: Lexer.cpp:406
static bool checkLocForMacroArgExpansion(SourceLocation Loc, const SourceManager &SM, SourceLocation ArgumentLoc)
Check that the macro argument location of Loc starts with ArgumentLoc.
std::pair< SourceLocation, StringRef > getModuleImportLoc(SourceLocation Loc) const
static bool checkRangesForMacroArgExpansion(SourceLocation Loc, ArrayRef< CharSourceRange > Ranges, const SourceManager &SM)
A helper function to check if the current ranges are all inside the same macro argument expansion as ...
bool BeforePreviousInsertions
Definition: Diagnostic.h:66
IntrusiveRefCntPtr< DiagnosticOptions > DiagOpts
Represents an unpacked "presumed" location which can be presented to the user.
static StringRef getImmediateMacroName(SourceLocation Loc, const SourceManager &SM, const LangOptions &LangOpts)
Retrieve the name of the immediate macro expansion.
CharSourceRange InsertFromRange
Code in the specific range that should be inserted in the insertion location.
Definition: Diagnostic.h:60
CharSourceRange RemoveRange
Code that should be replaced to correct the error.
Definition: Diagnostic.h:56
ArrayRef< FixItHint > getFixIts() const
Definition: Diagnostic.h:1300
virtual void emitCodeContext(SourceLocation Loc, DiagnosticsEngine::Level Level, SmallVectorImpl< CharSourceRange > &Ranges, ArrayRef< FixItHint > Hints, const SourceManager &SM)=0
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)
virtual void emitIncludeLocation(SourceLocation Loc, PresumedLoc PLoc, const SourceManager &SM)=0
DiagnosticRenderer(const LangOptions &LangOpts, DiagnosticOptions *DiagOpts)
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)
detail::InMemoryDirectory::const_iterator E
virtual void emitNote(SourceLocation Loc, StringRef Message, const SourceManager *SM)=0
static void mergeFixits(ArrayRef< FixItHint > FixItHints, const SourceManager &SM, const LangOptions &LangOpts, SmallVectorImpl< FixItHint > &MergedFixits)
bool commit(const Commit &commit)
void emitBuildingModuleLocation(SourceLocation Loc, PresumedLoc PLoc, StringRef ModuleName, const SourceManager &SM) override
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:78
ArrayRef< CharSourceRange > getRanges() const
Definition: Diagnostic.h:1290
Level
The level of the diagnostic, after it has been through mapping.
Definition: Diagnostic.h:141
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:115
DiagnosticsEngine::Level getLevel() const
Definition: Diagnostic.h:1279
Annotates a diagnostic with some code that should be inserted, removed, or replaced to fix the proble...
Definition: Diagnostic.h:52
virtual void emitImportLocation(SourceLocation Loc, PresumedLoc PLoc, StringRef ModuleName, const SourceManager &SM)=0
A trivial tuple used to represent a source range.
std::pair< FileID, unsigned > getDecomposedLoc(SourceLocation Loc) const
Decompose the specified location into a raw FileID + Offset pair.
This class handles loading and caching of source files into memory.
PresumedLoc getPresumedLoc(SourceLocation Loc, bool UseLineDirectives=true) const
Returns the "presumed" location of a SourceLocation specifies.