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"
24 using namespace clang;
45 assert(Loc.
isMacroID() &&
"Only reasonble to call this on macros");
64 StringRef ExpansionBuffer = SM.
getBufferData(ExpansionInfo.first);
65 return ExpansionBuffer.substr(ExpansionInfo.second, MacroTokenLength);
70 : LangOpts(LangOpts), DiagOpts(DiagOpts), LastLevel() {}
81 : MergedFixits(MergedFixits) { }
97 I = FixItHints.begin(), E = FixItHints.end(); I != E; ++I) {
117 if (Editor.
commit(commit)) {
118 FixitReceiver Rec(MergedFixits);
143 if (!FixItHints.empty()) {
145 FixItHints = MergedFixits;
149 E = FixItHints.end();
151 if (I->RemoveRange.isValid())
152 MutableRanges.push_back(I->RemoveRange);
157 Loc = SM->getFileLoc(Loc);
163 emitIncludeStack(Loc, PLoc, Level, *SM);
167 emitCaret(Loc, Level, MutableRanges, FixItHints, *SM);
172 unsigned MacroDepth = 0;
173 emitMacroExpansions(UnexpandedLoc, Level, MutableRanges, FixItHints, *SM,
193 void DiagnosticRenderer::emitBasicNote(StringRef Message) {
226 emitIncludeStackRecursively(IncludeLoc, SM);
228 emitModuleBuildStack(SM);
229 emitImportStack(Loc, SM);
235 void DiagnosticRenderer::emitIncludeStackRecursively(
SourceLocation Loc,
238 emitModuleBuildStack(SM);
250 if (Imported.first.isValid()) {
252 emitImportStackRecursively(Imported.first, Imported.second, SM);
267 emitModuleBuildStack(SM);
271 std::pair<SourceLocation, StringRef> NextImportLoc
273 emitImportStackRecursively(NextImportLoc.first, NextImportLoc.second, SM);
278 void DiagnosticRenderer::emitImportStackRecursively(
SourceLocation Loc,
279 StringRef ModuleName,
290 std::pair<SourceLocation, StringRef> NextImportLoc
292 emitImportStackRecursively(NextImportLoc.first, NextImportLoc.second, SM);
300 void DiagnosticRenderer::emitModuleBuildStack(
const SourceManager &SM) {
302 for (
unsigned I = 0, N = Stack.size(); I != N; ++I) {
334 bool IsTokenRange = I->isTokenRange();
342 llvm::SmallDenseMap<FileID, SourceLocation> BeginLocsMap;
343 while (Begin.
isMacroID() && BeginFileID != EndFileID) {
344 BeginLocsMap[BeginFileID] = Begin;
350 if (BeginFileID != EndFileID) {
351 while (
End.isMacroID() && !BeginLocsMap.count(EndFileID)) {
355 if (
End.isMacroID()) {
356 Begin = BeginLocsMap[EndFileID];
357 BeginFileID = EndFileID;
361 while (Begin.
isMacroID() && BeginFileID != CaretLocFileID) {
414 unsigned &MacroDepth,
415 unsigned OnMacroInst) {
416 assert(!Loc.
isInvalid() &&
"must have a valid source location here");
420 if (OneLevelUp.isMacroID())
421 emitMacroExpansions(OneLevelUp, Level, Ranges, Hints, SM,
422 MacroDepth, OnMacroInst + 1);
424 MacroDepth = OnMacroInst + 1;
426 unsigned MacroSkipStart = 0, MacroSkipEnd = 0;
427 if (MacroDepth >
DiagOpts->MacroBacktraceLimit &&
428 DiagOpts->MacroBacktraceLimit != 0) {
429 MacroSkipStart =
DiagOpts->MacroBacktraceLimit / 2 +
431 MacroSkipEnd = MacroDepth -
DiagOpts->MacroBacktraceLimit / 2;
435 bool Suppressed = (OnMacroInst >= MacroSkipStart &&
436 OnMacroInst < MacroSkipEnd);
440 if (OnMacroInst == MacroSkipStart) {
442 llvm::raw_svector_ostream Message(MessageStorage);
443 Message <<
"(skipping " << (MacroSkipEnd - MacroSkipStart)
444 <<
" expansions in backtrace; use -fmacro-backtrace-limit=0 to "
446 emitBasicNote(Message.str());
465 llvm::raw_svector_ostream Message(MessageStorage);
467 if (MacroName.empty())
468 Message <<
"expanded from here";
470 Message <<
"expanded from macro '" << MacroName <<
"'";
472 SpellingRanges,
None, &
SM);
482 llvm::raw_svector_ostream Message(MessageStorage);
483 Message <<
"in file included from " << PLoc.
getFilename() <<
':'
490 StringRef ModuleName,
494 llvm::raw_svector_ostream Message(MessageStorage);
495 Message <<
"in module '" << ModuleName <<
"' imported from "
503 StringRef ModuleName,
507 llvm::raw_svector_ostream Message(MessageStorage);
509 Message <<
"while building module '" << ModuleName <<
"' imported from "
512 Message <<
"while building module '" << ModuleName <<
"':";
bool remove(CharSourceRange range)
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
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
Represents a diagnostic in a form that can be retained until its corresponding source manager is dest...
void emitStoredDiagnostic(StoredDiagnostic &Diag)
const SourceManager & getManager() const
const FullSourceLoc & getLocation() const
std::string CodeToInsert
The actual code to insert at the insertion location, as a string.
bool insertFromRange(SourceLocation loc, CharSourceRange range, bool afterToken=false, bool beforePreviousInsertions=false)
const LangOptions & LangOpts
void applyRewrites(EditsReceiver &receiver)
bool insert(SourceLocation loc, StringRef text, bool afterToken=false, bool beforePreviousInsertions=false)
virtual ~DiagnosticRenderer()
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...
bool replace(CharSourceRange range, StringRef text)
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.
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
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)
std::pair< SourceLocation, StringRef > getModuleImportLoc(SourceLocation Loc) const
bool BeforePreviousInsertions
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.
CharSourceRange RemoveRange
Code that should be replaced to correct the error. Empty for an insertion hint.
ArrayRef< FixItHint > getFixIts() const
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)
~DiagnosticNoteRenderer() override
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.
ArrayRef< CharSourceRange > getRanges() const
Level
The level of the diagnostic, after it has been through mapping.
static FixItHint CreateReplacement(CharSourceRange RemoveRange, StringRef Code)
Create a code modification hint that replaces the given source range with the given code string...
DiagnosticsEngine::Level getLevel() const
Annotates a diagnostic with some code that should be inserted, removed, or replaced to fix the proble...
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.