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