clang  3.7.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  unsigned MacroDepth = 0;
173  emitMacroExpansions(UnexpandedLoc, Level, MutableRanges, FixItHints, *SM,
174  MacroDepth);
175  }
176  }
177 
178  LastLoc = Loc;
179  LastLevel = Level;
180 
181  endDiagnostic(D, Level);
182 }
183 
184 
186  emitDiagnostic(Diag.getLocation(), Diag.getLevel(), Diag.getMessage(),
187  Diag.getRanges(), Diag.getFixIts(),
188  Diag.getLocation().isValid() ? &Diag.getLocation().getManager()
189  : nullptr,
190  &Diag);
191 }
192 
193 void DiagnosticRenderer::emitBasicNote(StringRef Message) {
196  None, nullptr, DiagOrStoredDiag());
197 }
198 
199 /// \brief Prints an include stack when appropriate for a particular
200 /// diagnostic level and location.
201 ///
202 /// This routine handles all the logic of suppressing particular include
203 /// stacks (such as those for notes) and duplicate include stacks when
204 /// repeated warnings occur within the same file. It also handles the logic
205 /// of customizing the formatting and display of the include stack.
206 ///
207 /// \param Loc The diagnostic location.
208 /// \param PLoc The presumed location of the diagnostic location.
209 /// \param Level The diagnostic level of the message this stack pertains to.
210 void DiagnosticRenderer::emitIncludeStack(SourceLocation Loc,
211  PresumedLoc PLoc,
213  const SourceManager &SM) {
214  SourceLocation IncludeLoc = PLoc.getIncludeLoc();
215 
216  // Skip redundant include stacks altogether.
217  if (LastIncludeLoc == IncludeLoc)
218  return;
219 
220  LastIncludeLoc = IncludeLoc;
221 
222  if (!DiagOpts->ShowNoteIncludeStack && Level == DiagnosticsEngine::Note)
223  return;
224 
225  if (IncludeLoc.isValid())
226  emitIncludeStackRecursively(IncludeLoc, SM);
227  else {
228  emitModuleBuildStack(SM);
229  emitImportStack(Loc, SM);
230  }
231 }
232 
233 /// \brief Helper to recursivly walk up the include stack and print each layer
234 /// on the way back down.
235 void DiagnosticRenderer::emitIncludeStackRecursively(SourceLocation Loc,
236  const SourceManager &SM) {
237  if (Loc.isInvalid()) {
238  emitModuleBuildStack(SM);
239  return;
240  }
241 
242  PresumedLoc PLoc = SM.getPresumedLoc(Loc, DiagOpts->ShowPresumedLoc);
243  if (PLoc.isInvalid())
244  return;
245 
246  // If this source location was imported from a module, print the module
247  // import stack rather than the
248  // FIXME: We want submodule granularity here.
249  std::pair<SourceLocation, StringRef> Imported = SM.getModuleImportLoc(Loc);
250  if (Imported.first.isValid()) {
251  // This location was imported by a module. Emit the module import stack.
252  emitImportStackRecursively(Imported.first, Imported.second, SM);
253  return;
254  }
255 
256  // Emit the other include frames first.
257  emitIncludeStackRecursively(PLoc.getIncludeLoc(), SM);
258 
259  // Emit the inclusion text/note.
260  emitIncludeLocation(Loc, PLoc, SM);
261 }
262 
263 /// \brief Emit the module import stack associated with the current location.
264 void DiagnosticRenderer::emitImportStack(SourceLocation Loc,
265  const SourceManager &SM) {
266  if (Loc.isInvalid()) {
267  emitModuleBuildStack(SM);
268  return;
269  }
270 
271  std::pair<SourceLocation, StringRef> NextImportLoc
272  = SM.getModuleImportLoc(Loc);
273  emitImportStackRecursively(NextImportLoc.first, NextImportLoc.second, SM);
274 }
275 
276 /// \brief Helper to recursivly walk up the import stack and print each layer
277 /// on the way back down.
278 void DiagnosticRenderer::emitImportStackRecursively(SourceLocation Loc,
279  StringRef ModuleName,
280  const SourceManager &SM) {
281  if (Loc.isInvalid()) {
282  return;
283  }
284 
285  PresumedLoc PLoc = SM.getPresumedLoc(Loc, DiagOpts->ShowPresumedLoc);
286  if (PLoc.isInvalid())
287  return;
288 
289  // Emit the other import frames first.
290  std::pair<SourceLocation, StringRef> NextImportLoc
291  = SM.getModuleImportLoc(Loc);
292  emitImportStackRecursively(NextImportLoc.first, NextImportLoc.second, SM);
293 
294  // Emit the inclusion text/note.
295  emitImportLocation(Loc, PLoc, ModuleName, SM);
296 }
297 
298 /// \brief Emit the module build stack, for cases where a module is (re-)built
299 /// on demand.
300 void DiagnosticRenderer::emitModuleBuildStack(const SourceManager &SM) {
302  for (unsigned I = 0, N = Stack.size(); I != N; ++I) {
303  const SourceManager &CurSM = Stack[I].second.getManager();
304  SourceLocation CurLoc = Stack[I].second;
306  CurSM.getPresumedLoc(CurLoc,
307  DiagOpts->ShowPresumedLoc),
308  Stack[I].first,
309  CurSM);
310  }
311 }
312 
313 // Helper function to fix up source ranges. It takes in an array of ranges,
314 // and outputs an array of ranges where we want to draw the range highlighting
315 // around the location specified by CaretLoc.
316 //
317 // To find locations which correspond to the caret, we crawl the macro caller
318 // chain for the beginning and end of each range. If the caret location
319 // is in a macro expansion, we search each chain for a location
320 // in the same expansion as the caret; otherwise, we crawl to the top of
321 // each chain. Two locations are part of the same macro expansion
322 // iff the FileID is the same.
324  SourceLocation CaretLoc,
326  SmallVectorImpl<CharSourceRange> &SpellingRanges,
327  const SourceManager *SM) {
328  FileID CaretLocFileID = SM->getFileID(CaretLoc);
329 
330  for (ArrayRef<CharSourceRange>::const_iterator I = Ranges.begin(),
331  E = Ranges.end();
332  I != E; ++I) {
333  SourceLocation Begin = I->getBegin(), End = I->getEnd();
334  bool IsTokenRange = I->isTokenRange();
335 
336  FileID BeginFileID = SM->getFileID(Begin);
337  FileID EndFileID = SM->getFileID(End);
338 
339  // Find the common parent for the beginning and end of the range.
340 
341  // First, crawl the expansion chain for the beginning of the range.
342  llvm::SmallDenseMap<FileID, SourceLocation> BeginLocsMap;
343  while (Begin.isMacroID() && BeginFileID != EndFileID) {
344  BeginLocsMap[BeginFileID] = Begin;
345  Begin = SM->getImmediateExpansionRange(Begin).first;
346  BeginFileID = SM->getFileID(Begin);
347  }
348 
349  // Then, crawl the expansion chain for the end of the range.
350  if (BeginFileID != EndFileID) {
351  while (End.isMacroID() && !BeginLocsMap.count(EndFileID)) {
352  End = SM->getImmediateExpansionRange(End).second;
353  EndFileID = SM->getFileID(End);
354  }
355  if (End.isMacroID()) {
356  Begin = BeginLocsMap[EndFileID];
357  BeginFileID = EndFileID;
358  }
359  }
360 
361  while (Begin.isMacroID() && BeginFileID != CaretLocFileID) {
362  if (SM->isMacroArgExpansion(Begin)) {
363  Begin = SM->getImmediateSpellingLoc(Begin);
365  } else {
366  Begin = SM->getImmediateExpansionRange(Begin).first;
367  End = SM->getImmediateExpansionRange(End).second;
368  }
369  BeginFileID = SM->getFileID(Begin);
370  if (BeginFileID != SM->getFileID(End)) {
371  // FIXME: Ugly hack to stop a crash; this code is making bad
372  // assumptions and it's too complicated for me to reason
373  // about.
374  Begin = End = SourceLocation();
375  break;
376  }
377  }
378 
379  // Return the spelling location of the beginning and end of the range.
380  Begin = SM->getSpellingLoc(Begin);
381  End = SM->getSpellingLoc(End);
382  SpellingRanges.push_back(CharSourceRange(SourceRange(Begin, End),
383  IsTokenRange));
384  }
385 }
386 
387 void DiagnosticRenderer::emitCaret(SourceLocation Loc,
390  ArrayRef<FixItHint> Hints,
391  const SourceManager &SM) {
392  SmallVector<CharSourceRange, 4> SpellingRanges;
393  mapDiagnosticRanges(Loc, Ranges, SpellingRanges, &SM);
394  emitCodeContext(Loc, Level, SpellingRanges, Hints, SM);
395 }
396 
397 /// \brief Recursively emit notes for each macro expansion and caret
398 /// diagnostics where appropriate.
399 ///
400 /// Walks up the macro expansion stack printing expansion notes, the code
401 /// snippet, caret, underlines and FixItHint display as appropriate at each
402 /// level.
403 ///
404 /// \param Loc The location for this caret.
405 /// \param Level The diagnostic level currently being emitted.
406 /// \param Ranges The underlined ranges for this code snippet.
407 /// \param Hints The FixIt hints active for this diagnostic.
408 /// \param OnMacroInst The current depth of the macro expansion stack.
409 void DiagnosticRenderer::emitMacroExpansions(SourceLocation Loc,
412  ArrayRef<FixItHint> Hints,
413  const SourceManager &SM,
414  unsigned &MacroDepth,
415  unsigned OnMacroInst) {
416  assert(!Loc.isInvalid() && "must have a valid source location here");
417 
418  // Walk up to the caller of this macro, and produce a backtrace down to there.
419  SourceLocation OneLevelUp = SM.getImmediateMacroCallerLoc(Loc);
420  if (OneLevelUp.isMacroID())
421  emitMacroExpansions(OneLevelUp, Level, Ranges, Hints, SM,
422  MacroDepth, OnMacroInst + 1);
423  else
424  MacroDepth = OnMacroInst + 1;
425 
426  unsigned MacroSkipStart = 0, MacroSkipEnd = 0;
427  if (MacroDepth > DiagOpts->MacroBacktraceLimit &&
428  DiagOpts->MacroBacktraceLimit != 0) {
429  MacroSkipStart = DiagOpts->MacroBacktraceLimit / 2 +
430  DiagOpts->MacroBacktraceLimit % 2;
431  MacroSkipEnd = MacroDepth - DiagOpts->MacroBacktraceLimit / 2;
432  }
433 
434  // Whether to suppress printing this macro expansion.
435  bool Suppressed = (OnMacroInst >= MacroSkipStart &&
436  OnMacroInst < MacroSkipEnd);
437 
438  if (Suppressed) {
439  // Tell the user that we've skipped contexts.
440  if (OnMacroInst == MacroSkipStart) {
441  SmallString<200> MessageStorage;
442  llvm::raw_svector_ostream Message(MessageStorage);
443  Message << "(skipping " << (MacroSkipEnd - MacroSkipStart)
444  << " expansions in backtrace; use -fmacro-backtrace-limit=0 to "
445  "see all)";
446  emitBasicNote(Message.str());
447  }
448  return;
449  }
450 
451  // Find the spelling location for the macro definition. We must use the
452  // spelling location here to avoid emitting a macro bactrace for the note.
453  SourceLocation SpellingLoc = Loc;
454  // If this is the expansion of a macro argument, point the caret at the
455  // use of the argument in the definition of the macro, not the expansion.
456  if (SM.isMacroArgExpansion(Loc))
457  SpellingLoc = SM.getImmediateExpansionRange(Loc).first;
458  SpellingLoc = SM.getSpellingLoc(SpellingLoc);
459 
460  // Map the ranges into the FileID of the diagnostic location.
461  SmallVector<CharSourceRange, 4> SpellingRanges;
462  mapDiagnosticRanges(Loc, Ranges, SpellingRanges, &SM);
463 
464  SmallString<100> MessageStorage;
465  llvm::raw_svector_ostream Message(MessageStorage);
466  StringRef MacroName = getImmediateMacroName(Loc, SM, LangOpts);
467  if (MacroName.empty())
468  Message << "expanded from here";
469  else
470  Message << "expanded from macro '" << MacroName << "'";
471  emitDiagnostic(SpellingLoc, DiagnosticsEngine::Note, Message.str(),
472  SpellingRanges, None, &SM);
473 }
474 
476 
478  PresumedLoc PLoc,
479  const SourceManager &SM) {
480  // Generate a note indicating the include location.
481  SmallString<200> MessageStorage;
482  llvm::raw_svector_ostream Message(MessageStorage);
483  Message << "in file included from " << PLoc.getFilename() << ':'
484  << PLoc.getLine() << ":";
485  emitNote(Loc, Message.str(), &SM);
486 }
487 
489  PresumedLoc PLoc,
490  StringRef ModuleName,
491  const SourceManager &SM) {
492  // Generate a note indicating the include location.
493  SmallString<200> MessageStorage;
494  llvm::raw_svector_ostream Message(MessageStorage);
495  Message << "in module '" << ModuleName << "' imported from "
496  << PLoc.getFilename() << ':' << PLoc.getLine() << ":";
497  emitNote(Loc, Message.str(), &SM);
498 }
499 
500 void
502  PresumedLoc PLoc,
503  StringRef ModuleName,
504  const SourceManager &SM) {
505  // Generate a note indicating the include location.
506  SmallString<200> MessageStorage;
507  llvm::raw_svector_ostream Message(MessageStorage);
508  if (PLoc.getFilename())
509  Message << "while building module '" << ModuleName << "' imported from "
510  << PLoc.getFilename() << ':' << PLoc.getLine() << ":";
511  else
512  Message << "while building module '" << ModuleName << "':";
513  emitNote(Loc, Message.str(), &SM);
514 }
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
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.
Defines the SourceManager interface.
virtual void emitBuildingModuleLocation(SourceLocation Loc, PresumedLoc PLoc, StringRef ModuleName, const SourceManager &SM)=0
StringRef getMessage() const
Definition: Diagnostic.h:1283
Represents a diagnostic in a form that can be retained until its corresponding source manager is dest...
Definition: Diagnostic.h:1258
void emitStoredDiagnostic(StoredDiagnostic &Diag)
const SourceManager & getManager() const
const FullSourceLoc & getLocation() const
Definition: Diagnostic.h:1282
std::string CodeToInsert
The actual code to insert at the insertion location, as a string.
Definition: Diagnostic.h:64
bool insertFromRange(SourceLocation loc, CharSourceRange range, bool afterToken=false, bool beforePreviousInsertions=false)
Definition: Commit.cpp:59
const LangOptions & LangOpts
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.
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
SmallVector< CharSourceRange, 8 > Ranges
Definition: Format.cpp:1554
SourceLocation getImmediateMacroCallerLoc(SourceLocation Loc) const
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
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)
Definition: Lexer.cpp:406
std::pair< SourceLocation, StringRef > getModuleImportLoc(SourceLocation Loc) const
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. Empty for an insertion hint.
Definition: Diagnostic.h:56
ArrayRef< FixItHint > getFixIts() const
Definition: Diagnostic.h:1302
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. Return false if the end o...
const char * getFilename() const
Return the presumed filename of this location.
Encodes a location in the source. The SourceManager can decode this to get at the full include stack...
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)
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:1292
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:1281
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.
bool isMacroArgExpansion(SourceLocation Loc) const
Tests whether the given source location represents a macro argument's expansion into the function-lik...
PresumedLoc getPresumedLoc(SourceLocation Loc, bool UseLineDirectives=true) const
Returns the "presumed" location of a SourceLocation specifies.