forked from OSchip/llvm-project
Fix an assertion hit when the serialized diagnostics writer receive a diagnostic
from the frontend when the location is invalid and the SourceManager null. Instead of keeping the SourceManager object in DiagnosticRenderer, propagate it to the calls accordingly (as reference when it is expected to not be null, or pointer when it may be null). This effectively makes DiagnosticRenderer not tied to a specific SourceManager, removing a hack from TextDiagnosticPrinter. rdar://11386874 llvm-svn: 156536
This commit is contained in:
parent
3d081399f0
commit
b16ff5d1ce
|
@ -43,7 +43,6 @@ typedef llvm::PointerUnion<const Diagnostic *,
|
|||
/// class.
|
||||
class DiagnosticRenderer {
|
||||
protected:
|
||||
const SourceManager &SM;
|
||||
const LangOptions &LangOpts;
|
||||
const DiagnosticOptions &DiagOpts;
|
||||
|
||||
|
@ -66,8 +65,7 @@ protected:
|
|||
/// which change the amount of information displayed.
|
||||
DiagnosticsEngine::Level LastLevel;
|
||||
|
||||
DiagnosticRenderer(const SourceManager &SM,
|
||||
const LangOptions &LangOpts,
|
||||
DiagnosticRenderer(const LangOptions &LangOpts,
|
||||
const DiagnosticOptions &DiagOpts);
|
||||
|
||||
virtual ~DiagnosticRenderer();
|
||||
|
@ -76,20 +74,24 @@ protected:
|
|||
DiagnosticsEngine::Level Level,
|
||||
StringRef Message,
|
||||
ArrayRef<CharSourceRange> Ranges,
|
||||
const SourceManager *SM,
|
||||
DiagOrStoredDiag Info) = 0;
|
||||
|
||||
virtual void emitDiagnosticLoc(SourceLocation Loc, PresumedLoc PLoc,
|
||||
DiagnosticsEngine::Level Level,
|
||||
ArrayRef<CharSourceRange> Ranges) = 0;
|
||||
ArrayRef<CharSourceRange> Ranges,
|
||||
const SourceManager &SM) = 0;
|
||||
|
||||
virtual void emitBasicNote(StringRef Message) = 0;
|
||||
|
||||
virtual void emitCodeContext(SourceLocation Loc,
|
||||
DiagnosticsEngine::Level Level,
|
||||
SmallVectorImpl<CharSourceRange>& Ranges,
|
||||
ArrayRef<FixItHint> Hints) = 0;
|
||||
ArrayRef<FixItHint> Hints,
|
||||
const SourceManager &SM) = 0;
|
||||
|
||||
virtual void emitIncludeLocation(SourceLocation Loc, PresumedLoc PLoc) = 0;
|
||||
virtual void emitIncludeLocation(SourceLocation Loc, PresumedLoc PLoc,
|
||||
const SourceManager &SM) = 0;
|
||||
|
||||
virtual void beginDiagnostic(DiagOrStoredDiag D,
|
||||
DiagnosticsEngine::Level Level) {}
|
||||
|
@ -98,12 +100,14 @@ protected:
|
|||
|
||||
|
||||
private:
|
||||
void emitIncludeStack(SourceLocation Loc, DiagnosticsEngine::Level Level);
|
||||
void emitIncludeStackRecursively(SourceLocation Loc);
|
||||
void emitIncludeStack(SourceLocation Loc, DiagnosticsEngine::Level Level,
|
||||
const SourceManager &SM);
|
||||
void emitIncludeStackRecursively(SourceLocation Loc, const SourceManager &SM);
|
||||
void emitMacroExpansionsAndCarets(SourceLocation Loc,
|
||||
DiagnosticsEngine::Level Level,
|
||||
SmallVectorImpl<CharSourceRange>& Ranges,
|
||||
ArrayRef<FixItHint> Hints,
|
||||
const SourceManager &SM,
|
||||
unsigned &MacroDepth,
|
||||
unsigned OnMacroInst = 0);
|
||||
public:
|
||||
|
@ -119,9 +123,12 @@ public:
|
|||
/// \param Message The diagnostic message to emit.
|
||||
/// \param Ranges The underlined ranges for this code snippet.
|
||||
/// \param FixItHints The FixIt hints active for this diagnostic.
|
||||
/// \param SM The SourceManager; will be null if the diagnostic came from the
|
||||
/// frontend, thus \param Loc will be invalid.
|
||||
void emitDiagnostic(SourceLocation Loc, DiagnosticsEngine::Level Level,
|
||||
StringRef Message, ArrayRef<CharSourceRange> Ranges,
|
||||
ArrayRef<FixItHint> FixItHints,
|
||||
const SourceManager *SM,
|
||||
DiagOrStoredDiag D = (Diagnostic *)0);
|
||||
|
||||
void emitStoredDiagnostic(StoredDiagnostic &Diag);
|
||||
|
@ -131,19 +138,20 @@ public:
|
|||
/// notes. It is up to subclasses to further define the behavior.
|
||||
class DiagnosticNoteRenderer : public DiagnosticRenderer {
|
||||
public:
|
||||
DiagnosticNoteRenderer(const SourceManager &SM,
|
||||
const LangOptions &LangOpts,
|
||||
DiagnosticNoteRenderer(const LangOptions &LangOpts,
|
||||
const DiagnosticOptions &DiagOpts)
|
||||
: DiagnosticRenderer(SM, LangOpts, DiagOpts) {}
|
||||
: DiagnosticRenderer(LangOpts, DiagOpts) {}
|
||||
|
||||
virtual ~DiagnosticNoteRenderer();
|
||||
|
||||
virtual void emitBasicNote(StringRef Message);
|
||||
|
||||
virtual void emitIncludeLocation(SourceLocation Loc,
|
||||
PresumedLoc PLoc);
|
||||
PresumedLoc PLoc,
|
||||
const SourceManager &SM);
|
||||
|
||||
virtual void emitNote(SourceLocation Loc, StringRef Message) = 0;
|
||||
virtual void emitNote(SourceLocation Loc, StringRef Message,
|
||||
const SourceManager *SM) = 0;
|
||||
};
|
||||
} // end clang namespace
|
||||
#endif
|
||||
|
|
|
@ -39,7 +39,6 @@ class TextDiagnostic : public DiagnosticRenderer {
|
|||
|
||||
public:
|
||||
TextDiagnostic(raw_ostream &OS,
|
||||
const SourceManager &SM,
|
||||
const LangOptions &LangOpts,
|
||||
const DiagnosticOptions &DiagOpts);
|
||||
|
||||
|
@ -83,39 +82,46 @@ protected:
|
|||
DiagnosticsEngine::Level Level,
|
||||
StringRef Message,
|
||||
ArrayRef<CharSourceRange> Ranges,
|
||||
const SourceManager *SM,
|
||||
DiagOrStoredDiag D);
|
||||
|
||||
virtual void emitDiagnosticLoc(SourceLocation Loc, PresumedLoc PLoc,
|
||||
DiagnosticsEngine::Level Level,
|
||||
ArrayRef<CharSourceRange> Ranges);
|
||||
ArrayRef<CharSourceRange> Ranges,
|
||||
const SourceManager &SM);
|
||||
|
||||
virtual void emitCodeContext(SourceLocation Loc,
|
||||
DiagnosticsEngine::Level Level,
|
||||
SmallVectorImpl<CharSourceRange>& Ranges,
|
||||
ArrayRef<FixItHint> Hints) {
|
||||
emitSnippetAndCaret(Loc, Level, Ranges, Hints);
|
||||
ArrayRef<FixItHint> Hints,
|
||||
const SourceManager &SM) {
|
||||
emitSnippetAndCaret(Loc, Level, Ranges, Hints, SM);
|
||||
}
|
||||
|
||||
virtual void emitBasicNote(StringRef Message);
|
||||
|
||||
virtual void emitIncludeLocation(SourceLocation Loc, PresumedLoc PLoc);
|
||||
virtual void emitIncludeLocation(SourceLocation Loc, PresumedLoc PLoc,
|
||||
const SourceManager &SM);
|
||||
|
||||
private:
|
||||
void emitSnippetAndCaret(SourceLocation Loc, DiagnosticsEngine::Level Level,
|
||||
SmallVectorImpl<CharSourceRange>& Ranges,
|
||||
ArrayRef<FixItHint> Hints);
|
||||
ArrayRef<FixItHint> Hints,
|
||||
const SourceManager &SM);
|
||||
|
||||
void emitSnippet(StringRef SourceLine);
|
||||
|
||||
void highlightRange(const CharSourceRange &R,
|
||||
unsigned LineNo, FileID FID,
|
||||
const SourceColumnMap &map,
|
||||
std::string &CaretLine);
|
||||
std::string &CaretLine,
|
||||
const SourceManager &SM);
|
||||
|
||||
std::string buildFixItInsertionLine(unsigned LineNo,
|
||||
const SourceColumnMap &map,
|
||||
ArrayRef<FixItHint> Hints);
|
||||
void emitParseableFixits(ArrayRef<FixItHint> Hints);
|
||||
ArrayRef<FixItHint> Hints,
|
||||
const SourceManager &SM);
|
||||
void emitParseableFixits(ArrayRef<FixItHint> Hints, const SourceManager &SM);
|
||||
};
|
||||
|
||||
} // end namespace clang
|
||||
|
|
|
@ -26,9 +26,7 @@ class TextDiagnostic;
|
|||
|
||||
class TextDiagnosticPrinter : public DiagnosticConsumer {
|
||||
raw_ostream &OS;
|
||||
const LangOptions *LangOpts;
|
||||
const DiagnosticOptions *DiagOpts;
|
||||
const SourceManager *SM;
|
||||
|
||||
/// \brief Handle to the currently active text diagnostic emitter.
|
||||
OwningPtr<TextDiagnostic> TextDiag;
|
||||
|
|
|
@ -123,10 +123,9 @@ static PresumedLoc getDiagnosticPresumedLoc(const SourceManager &SM,
|
|||
return SM.getPresumedLoc(Loc);
|
||||
}
|
||||
|
||||
DiagnosticRenderer::DiagnosticRenderer(const SourceManager &SM,
|
||||
const LangOptions &LangOpts,
|
||||
DiagnosticRenderer::DiagnosticRenderer(const LangOptions &LangOpts,
|
||||
const DiagnosticOptions &DiagOpts)
|
||||
: SM(SM), LangOpts(LangOpts), DiagOpts(DiagOpts), LastLevel() {}
|
||||
: LangOpts(LangOpts), DiagOpts(DiagOpts), LastLevel() {}
|
||||
|
||||
DiagnosticRenderer::~DiagnosticRenderer() {}
|
||||
|
||||
|
@ -184,18 +183,23 @@ void DiagnosticRenderer::emitDiagnostic(SourceLocation Loc,
|
|||
StringRef Message,
|
||||
ArrayRef<CharSourceRange> Ranges,
|
||||
ArrayRef<FixItHint> FixItHints,
|
||||
const SourceManager *SM,
|
||||
DiagOrStoredDiag D) {
|
||||
assert(SM || Loc.isInvalid());
|
||||
|
||||
beginDiagnostic(D, Level);
|
||||
|
||||
PresumedLoc PLoc = getDiagnosticPresumedLoc(SM, Loc);
|
||||
PresumedLoc PLoc;
|
||||
if (Loc.isValid()) {
|
||||
PLoc = getDiagnosticPresumedLoc(*SM, Loc);
|
||||
|
||||
// First, if this diagnostic is not in the main file, print out the
|
||||
// "included from" lines.
|
||||
emitIncludeStack(PLoc.getIncludeLoc(), Level);
|
||||
// First, if this diagnostic is not in the main file, print out the
|
||||
// "included from" lines.
|
||||
emitIncludeStack(PLoc.getIncludeLoc(), Level, *SM);
|
||||
}
|
||||
|
||||
// Next, emit the actual diagnostic message.
|
||||
emitDiagnosticMessage(Loc, PLoc, Level, Message, Ranges, D);
|
||||
emitDiagnosticMessage(Loc, PLoc, Level, Message, Ranges, SM, D);
|
||||
|
||||
// Only recurse if we have a valid location.
|
||||
if (Loc.isValid()) {
|
||||
|
@ -205,7 +209,7 @@ void DiagnosticRenderer::emitDiagnostic(SourceLocation Loc,
|
|||
|
||||
llvm::SmallVector<FixItHint, 8> MergedFixits;
|
||||
if (!FixItHints.empty()) {
|
||||
mergeFixits(FixItHints, SM, LangOpts, MergedFixits);
|
||||
mergeFixits(FixItHints, *SM, LangOpts, MergedFixits);
|
||||
FixItHints = MergedFixits;
|
||||
}
|
||||
|
||||
|
@ -216,7 +220,7 @@ void DiagnosticRenderer::emitDiagnostic(SourceLocation Loc,
|
|||
MutableRanges.push_back(I->RemoveRange);
|
||||
|
||||
unsigned MacroDepth = 0;
|
||||
emitMacroExpansionsAndCarets(Loc, Level, MutableRanges, FixItHints,
|
||||
emitMacroExpansionsAndCarets(Loc, Level, MutableRanges, FixItHints, *SM,
|
||||
MacroDepth);
|
||||
}
|
||||
|
||||
|
@ -230,6 +234,8 @@ void DiagnosticRenderer::emitDiagnostic(SourceLocation Loc,
|
|||
void DiagnosticRenderer::emitStoredDiagnostic(StoredDiagnostic &Diag) {
|
||||
emitDiagnostic(Diag.getLocation(), Diag.getLevel(), Diag.getMessage(),
|
||||
Diag.getRanges(), Diag.getFixIts(),
|
||||
Diag.getLocation().isValid() ? &Diag.getLocation().getManager()
|
||||
: 0,
|
||||
&Diag);
|
||||
}
|
||||
|
||||
|
@ -245,7 +251,8 @@ void DiagnosticRenderer::emitStoredDiagnostic(StoredDiagnostic &Diag) {
|
|||
/// \param Loc The include location of the current file (not the diagnostic
|
||||
/// location).
|
||||
void DiagnosticRenderer::emitIncludeStack(SourceLocation Loc,
|
||||
DiagnosticsEngine::Level Level) {
|
||||
DiagnosticsEngine::Level Level,
|
||||
const SourceManager &SM) {
|
||||
// Skip redundant include stacks altogether.
|
||||
if (LastIncludeLoc == Loc)
|
||||
return;
|
||||
|
@ -254,12 +261,13 @@ void DiagnosticRenderer::emitIncludeStack(SourceLocation Loc,
|
|||
if (!DiagOpts.ShowNoteIncludeStack && Level == DiagnosticsEngine::Note)
|
||||
return;
|
||||
|
||||
emitIncludeStackRecursively(Loc);
|
||||
emitIncludeStackRecursively(Loc, SM);
|
||||
}
|
||||
|
||||
/// \brief Helper to recursivly walk up the include stack and print each layer
|
||||
/// on the way back down.
|
||||
void DiagnosticRenderer::emitIncludeStackRecursively(SourceLocation Loc) {
|
||||
void DiagnosticRenderer::emitIncludeStackRecursively(SourceLocation Loc,
|
||||
const SourceManager &SM) {
|
||||
if (Loc.isInvalid())
|
||||
return;
|
||||
|
||||
|
@ -268,10 +276,10 @@ void DiagnosticRenderer::emitIncludeStackRecursively(SourceLocation Loc) {
|
|||
return;
|
||||
|
||||
// Emit the other include frames first.
|
||||
emitIncludeStackRecursively(PLoc.getIncludeLoc());
|
||||
emitIncludeStackRecursively(PLoc.getIncludeLoc(), SM);
|
||||
|
||||
// Emit the inclusion text/note.
|
||||
emitIncludeLocation(Loc, PLoc);
|
||||
emitIncludeLocation(Loc, PLoc, SM);
|
||||
}
|
||||
|
||||
/// \brief Recursively emit notes for each macro expansion and caret
|
||||
|
@ -292,6 +300,7 @@ void DiagnosticRenderer::emitMacroExpansionsAndCarets(
|
|||
DiagnosticsEngine::Level Level,
|
||||
SmallVectorImpl<CharSourceRange>& Ranges,
|
||||
ArrayRef<FixItHint> Hints,
|
||||
const SourceManager &SM,
|
||||
unsigned &MacroDepth,
|
||||
unsigned OnMacroInst)
|
||||
{
|
||||
|
@ -302,7 +311,7 @@ void DiagnosticRenderer::emitMacroExpansionsAndCarets(
|
|||
if (Loc.isFileID()) {
|
||||
assert(MacroDepth == 0 && "We shouldn't hit a leaf node twice!");
|
||||
MacroDepth = OnMacroInst;
|
||||
emitCodeContext(Loc, Level, Ranges, Hints);
|
||||
emitCodeContext(Loc, Level, Ranges, Hints, SM);
|
||||
return;
|
||||
}
|
||||
// Otherwise recurse through each macro expansion layer.
|
||||
|
@ -314,7 +323,7 @@ void DiagnosticRenderer::emitMacroExpansionsAndCarets(
|
|||
SourceLocation OneLevelUp = getImmediateMacroCallerLoc(SM, Loc);
|
||||
|
||||
// FIXME: Map ranges?
|
||||
emitMacroExpansionsAndCarets(OneLevelUp, Level, Ranges, Hints, MacroDepth,
|
||||
emitMacroExpansionsAndCarets(OneLevelUp, Level, Ranges, Hints, SM, MacroDepth,
|
||||
OnMacroInst + 1);
|
||||
|
||||
// Save the original location so we can find the spelling of the macro call.
|
||||
|
@ -365,22 +374,23 @@ void DiagnosticRenderer::emitMacroExpansionsAndCarets(
|
|||
<< getImmediateMacroName(MacroLoc, SM, LangOpts) << "'";
|
||||
emitDiagnostic(SM.getSpellingLoc(Loc), DiagnosticsEngine::Note,
|
||||
Message.str(),
|
||||
Ranges, ArrayRef<FixItHint>());
|
||||
Ranges, ArrayRef<FixItHint>(), &SM);
|
||||
}
|
||||
|
||||
DiagnosticNoteRenderer::~DiagnosticNoteRenderer() {}
|
||||
|
||||
void DiagnosticNoteRenderer::emitIncludeLocation(SourceLocation Loc,
|
||||
PresumedLoc PLoc) {
|
||||
PresumedLoc PLoc,
|
||||
const SourceManager &SM) {
|
||||
// Generate a note indicating the include location.
|
||||
SmallString<200> MessageStorage;
|
||||
llvm::raw_svector_ostream Message(MessageStorage);
|
||||
Message << "in file included from " << PLoc.getFilename() << ':'
|
||||
<< PLoc.getLine() << ":";
|
||||
emitNote(Loc, Message.str());
|
||||
emitNote(Loc, Message.str(), &SM);
|
||||
}
|
||||
|
||||
void DiagnosticNoteRenderer::emitBasicNote(StringRef Message) {
|
||||
emitNote(SourceLocation(), Message);
|
||||
emitNote(SourceLocation(), Message, 0);
|
||||
}
|
||||
|
||||
|
|
|
@ -53,10 +53,9 @@ class SDiagsRenderer : public DiagnosticNoteRenderer {
|
|||
RecordData &Record;
|
||||
public:
|
||||
SDiagsRenderer(SDiagsWriter &Writer, RecordData &Record,
|
||||
const SourceManager &SM,
|
||||
const LangOptions &LangOpts,
|
||||
const DiagnosticOptions &DiagOpts)
|
||||
: DiagnosticNoteRenderer(SM, LangOpts, DiagOpts),
|
||||
: DiagnosticNoteRenderer(LangOpts, DiagOpts),
|
||||
Writer(Writer), Record(Record){}
|
||||
|
||||
virtual ~SDiagsRenderer() {}
|
||||
|
@ -67,18 +66,21 @@ protected:
|
|||
DiagnosticsEngine::Level Level,
|
||||
StringRef Message,
|
||||
ArrayRef<CharSourceRange> Ranges,
|
||||
const SourceManager *SM,
|
||||
DiagOrStoredDiag D);
|
||||
|
||||
virtual void emitDiagnosticLoc(SourceLocation Loc, PresumedLoc PLoc,
|
||||
DiagnosticsEngine::Level Level,
|
||||
ArrayRef<CharSourceRange> Ranges) {}
|
||||
ArrayRef<CharSourceRange> Ranges,
|
||||
const SourceManager &SM) {}
|
||||
|
||||
void emitNote(SourceLocation Loc, StringRef Message);
|
||||
void emitNote(SourceLocation Loc, StringRef Message, const SourceManager *SM);
|
||||
|
||||
virtual void emitCodeContext(SourceLocation Loc,
|
||||
DiagnosticsEngine::Level Level,
|
||||
SmallVectorImpl<CharSourceRange>& Ranges,
|
||||
ArrayRef<FixItHint> Hints);
|
||||
ArrayRef<FixItHint> Hints,
|
||||
const SourceManager &SM);
|
||||
|
||||
virtual void beginDiagnostic(DiagOrStoredDiag D,
|
||||
DiagnosticsEngine::Level Level);
|
||||
|
@ -137,15 +139,16 @@ private:
|
|||
unsigned getEmitFile(const char *Filename);
|
||||
|
||||
/// \brief Add SourceLocation information the specified record.
|
||||
void AddLocToRecord(SourceLocation Loc, const SourceManager &SM,
|
||||
void AddLocToRecord(SourceLocation Loc, const SourceManager *SM,
|
||||
PresumedLoc PLoc, RecordDataImpl &Record,
|
||||
unsigned TokSize = 0);
|
||||
|
||||
/// \brief Add SourceLocation information the specified record.
|
||||
void AddLocToRecord(SourceLocation Loc, RecordDataImpl &Record,
|
||||
const SourceManager &SM,
|
||||
const SourceManager *SM,
|
||||
unsigned TokSize = 0) {
|
||||
AddLocToRecord(Loc, SM, SM.getPresumedLoc(Loc), Record, TokSize);
|
||||
AddLocToRecord(Loc, SM, SM ? SM->getPresumedLoc(Loc) : PresumedLoc(),
|
||||
Record, TokSize);
|
||||
}
|
||||
|
||||
/// \brief Add CharSourceRange information the specified record.
|
||||
|
@ -241,7 +244,7 @@ static void EmitRecordID(unsigned ID, const char *Name,
|
|||
}
|
||||
|
||||
void SDiagsWriter::AddLocToRecord(SourceLocation Loc,
|
||||
const SourceManager &SM,
|
||||
const SourceManager *SM,
|
||||
PresumedLoc PLoc,
|
||||
RecordDataImpl &Record,
|
||||
unsigned TokSize) {
|
||||
|
@ -257,19 +260,19 @@ void SDiagsWriter::AddLocToRecord(SourceLocation Loc,
|
|||
Record.push_back(getEmitFile(PLoc.getFilename()));
|
||||
Record.push_back(PLoc.getLine());
|
||||
Record.push_back(PLoc.getColumn()+TokSize);
|
||||
Record.push_back(SM.getFileOffset(Loc));
|
||||
Record.push_back(SM->getFileOffset(Loc));
|
||||
}
|
||||
|
||||
void SDiagsWriter::AddCharSourceRangeToRecord(CharSourceRange Range,
|
||||
RecordDataImpl &Record,
|
||||
const SourceManager &SM) {
|
||||
AddLocToRecord(Range.getBegin(), Record, SM);
|
||||
AddLocToRecord(Range.getBegin(), Record, &SM);
|
||||
unsigned TokSize = 0;
|
||||
if (Range.isTokenRange())
|
||||
TokSize = Lexer::MeasureTokenLength(Range.getEnd(),
|
||||
SM, *LangOpts);
|
||||
|
||||
AddLocToRecord(Range.getEnd(), Record, SM, TokSize);
|
||||
AddLocToRecord(Range.getEnd(), Record, &SM, TokSize);
|
||||
}
|
||||
|
||||
unsigned SDiagsWriter::getEmitFile(const char *FileName){
|
||||
|
@ -484,13 +487,15 @@ void SDiagsWriter::HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
|
|||
diagBuf.clear();
|
||||
Info.FormatDiagnostic(diagBuf);
|
||||
|
||||
SourceManager &SM = Info.getSourceManager();
|
||||
SDiagsRenderer Renderer(*this, Record, SM, *LangOpts, DiagOpts);
|
||||
const SourceManager *
|
||||
SM = Info.hasSourceManager() ? &Info.getSourceManager() : 0;
|
||||
SDiagsRenderer Renderer(*this, Record, *LangOpts, DiagOpts);
|
||||
Renderer.emitDiagnostic(Info.getLocation(), DiagLevel,
|
||||
diagBuf.str(),
|
||||
Info.getRanges(),
|
||||
llvm::makeArrayRef(Info.getFixItHints(),
|
||||
Info.getNumFixItHints()),
|
||||
SM,
|
||||
&Info);
|
||||
}
|
||||
|
||||
|
@ -500,6 +505,7 @@ SDiagsRenderer::emitDiagnosticMessage(SourceLocation Loc,
|
|||
DiagnosticsEngine::Level Level,
|
||||
StringRef Message,
|
||||
ArrayRef<clang::CharSourceRange> Ranges,
|
||||
const SourceManager *SM,
|
||||
DiagOrStoredDiag D) {
|
||||
// Emit the RECORD_DIAG record.
|
||||
Writer.Record.clear();
|
||||
|
@ -539,7 +545,8 @@ void SDiagsRenderer::endDiagnostic(DiagOrStoredDiag D,
|
|||
void SDiagsRenderer::emitCodeContext(SourceLocation Loc,
|
||||
DiagnosticsEngine::Level Level,
|
||||
SmallVectorImpl<CharSourceRange> &Ranges,
|
||||
ArrayRef<FixItHint> Hints) {
|
||||
ArrayRef<FixItHint> Hints,
|
||||
const SourceManager &SM) {
|
||||
// Emit Source Ranges.
|
||||
for (ArrayRef<CharSourceRange>::iterator it=Ranges.begin(), ei=Ranges.end();
|
||||
it != ei; ++it) {
|
||||
|
@ -562,7 +569,8 @@ void SDiagsRenderer::emitCodeContext(SourceLocation Loc,
|
|||
}
|
||||
}
|
||||
|
||||
void SDiagsRenderer::emitNote(SourceLocation Loc, StringRef Message) {
|
||||
void SDiagsRenderer::emitNote(SourceLocation Loc, StringRef Message,
|
||||
const SourceManager *SM) {
|
||||
Writer.Stream.EnterSubblock(BLOCK_DIAG, 4);
|
||||
RecordData Record;
|
||||
Record.push_back(RECORD_DIAG);
|
||||
|
|
|
@ -602,10 +602,9 @@ static bool printWordWrapped(raw_ostream &OS, StringRef Str,
|
|||
}
|
||||
|
||||
TextDiagnostic::TextDiagnostic(raw_ostream &OS,
|
||||
const SourceManager &SM,
|
||||
const LangOptions &LangOpts,
|
||||
const DiagnosticOptions &DiagOpts)
|
||||
: DiagnosticRenderer(SM, LangOpts, DiagOpts), OS(OS) {}
|
||||
: DiagnosticRenderer(LangOpts, DiagOpts), OS(OS) {}
|
||||
|
||||
TextDiagnostic::~TextDiagnostic() {}
|
||||
|
||||
|
@ -615,11 +614,13 @@ TextDiagnostic::emitDiagnosticMessage(SourceLocation Loc,
|
|||
DiagnosticsEngine::Level Level,
|
||||
StringRef Message,
|
||||
ArrayRef<clang::CharSourceRange> Ranges,
|
||||
const SourceManager *SM,
|
||||
DiagOrStoredDiag D) {
|
||||
uint64_t StartOfLocationInfo = OS.tell();
|
||||
|
||||
// Emit the location of this particular diagnostic.
|
||||
emitDiagnosticLoc(Loc, PLoc, Level, Ranges);
|
||||
if (Loc.isValid())
|
||||
emitDiagnosticLoc(Loc, PLoc, Level, Ranges, *SM);
|
||||
|
||||
if (DiagOpts.ShowColors)
|
||||
OS.resetColor();
|
||||
|
@ -693,7 +694,8 @@ TextDiagnostic::printDiagnosticMessage(raw_ostream &OS,
|
|||
/// ranges necessary.
|
||||
void TextDiagnostic::emitDiagnosticLoc(SourceLocation Loc, PresumedLoc PLoc,
|
||||
DiagnosticsEngine::Level Level,
|
||||
ArrayRef<CharSourceRange> Ranges) {
|
||||
ArrayRef<CharSourceRange> Ranges,
|
||||
const SourceManager &SM) {
|
||||
if (PLoc.isInvalid()) {
|
||||
// At least print the file name if available:
|
||||
FileID FID = SM.getFileID(Loc);
|
||||
|
@ -799,7 +801,8 @@ void TextDiagnostic::emitBasicNote(StringRef Message) {
|
|||
}
|
||||
|
||||
void TextDiagnostic::emitIncludeLocation(SourceLocation Loc,
|
||||
PresumedLoc PLoc) {
|
||||
PresumedLoc PLoc,
|
||||
const SourceManager &SM) {
|
||||
if (DiagOpts.ShowLocation)
|
||||
OS << "In file included from " << PLoc.getFilename() << ':'
|
||||
<< PLoc.getLine() << ":\n";
|
||||
|
@ -817,7 +820,8 @@ void TextDiagnostic::emitIncludeLocation(SourceLocation Loc,
|
|||
void TextDiagnostic::emitSnippetAndCaret(
|
||||
SourceLocation Loc, DiagnosticsEngine::Level Level,
|
||||
SmallVectorImpl<CharSourceRange>& Ranges,
|
||||
ArrayRef<FixItHint> Hints) {
|
||||
ArrayRef<FixItHint> Hints,
|
||||
const SourceManager &SM) {
|
||||
assert(!Loc.isInvalid() && "must have a valid source location here");
|
||||
assert(Loc.isFileID() && "must have a file location here");
|
||||
|
||||
|
@ -878,7 +882,7 @@ void TextDiagnostic::emitSnippetAndCaret(
|
|||
for (SmallVectorImpl<CharSourceRange>::iterator I = Ranges.begin(),
|
||||
E = Ranges.end();
|
||||
I != E; ++I)
|
||||
highlightRange(*I, LineNo, FID, sourceColMap, CaretLine);
|
||||
highlightRange(*I, LineNo, FID, sourceColMap, CaretLine, SM);
|
||||
|
||||
// Next, insert the caret itself.
|
||||
ColNo = sourceColMap.byteToColumn(ColNo-1);
|
||||
|
@ -888,7 +892,7 @@ void TextDiagnostic::emitSnippetAndCaret(
|
|||
|
||||
std::string FixItInsertionLine = buildFixItInsertionLine(LineNo,
|
||||
sourceColMap,
|
||||
Hints);
|
||||
Hints, SM);
|
||||
|
||||
// If the source line is too long for our terminal, select only the
|
||||
// "interesting" source region within that line.
|
||||
|
@ -931,7 +935,7 @@ void TextDiagnostic::emitSnippetAndCaret(
|
|||
}
|
||||
|
||||
// Print out any parseable fixit information requested by the options.
|
||||
emitParseableFixits(Hints);
|
||||
emitParseableFixits(Hints, SM);
|
||||
}
|
||||
|
||||
void TextDiagnostic::emitSnippet(StringRef line) {
|
||||
|
@ -974,7 +978,8 @@ void TextDiagnostic::emitSnippet(StringRef line) {
|
|||
void TextDiagnostic::highlightRange(const CharSourceRange &R,
|
||||
unsigned LineNo, FileID FID,
|
||||
const SourceColumnMap &map,
|
||||
std::string &CaretLine) {
|
||||
std::string &CaretLine,
|
||||
const SourceManager &SM) {
|
||||
if (!R.isValid()) return;
|
||||
|
||||
SourceLocation Begin = SM.getExpansionLoc(R.getBegin());
|
||||
|
@ -1059,7 +1064,8 @@ void TextDiagnostic::highlightRange(const CharSourceRange &R,
|
|||
std::string TextDiagnostic::buildFixItInsertionLine(
|
||||
unsigned LineNo,
|
||||
const SourceColumnMap &map,
|
||||
ArrayRef<FixItHint> Hints) {
|
||||
ArrayRef<FixItHint> Hints,
|
||||
const SourceManager &SM) {
|
||||
|
||||
std::string FixItInsertionLine;
|
||||
if (Hints.empty() || !DiagOpts.ShowFixits)
|
||||
|
@ -1114,7 +1120,8 @@ std::string TextDiagnostic::buildFixItInsertionLine(
|
|||
return FixItInsertionLine;
|
||||
}
|
||||
|
||||
void TextDiagnostic::emitParseableFixits(ArrayRef<FixItHint> Hints) {
|
||||
void TextDiagnostic::emitParseableFixits(ArrayRef<FixItHint> Hints,
|
||||
const SourceManager &SM) {
|
||||
if (!DiagOpts.ShowParseableFixits)
|
||||
return;
|
||||
|
||||
|
|
|
@ -27,7 +27,7 @@ using namespace clang;
|
|||
TextDiagnosticPrinter::TextDiagnosticPrinter(raw_ostream &os,
|
||||
const DiagnosticOptions &diags,
|
||||
bool _OwnsOutputStream)
|
||||
: OS(os), LangOpts(0), DiagOpts(&diags), SM(0),
|
||||
: OS(os), DiagOpts(&diags),
|
||||
OwnsOutputStream(_OwnsOutputStream) {
|
||||
}
|
||||
|
||||
|
@ -38,11 +38,11 @@ TextDiagnosticPrinter::~TextDiagnosticPrinter() {
|
|||
|
||||
void TextDiagnosticPrinter::BeginSourceFile(const LangOptions &LO,
|
||||
const Preprocessor *PP) {
|
||||
LangOpts = &LO;
|
||||
// Build the TextDiagnostic utility.
|
||||
TextDiag.reset(new TextDiagnostic(OS, LO, *DiagOpts));
|
||||
}
|
||||
|
||||
void TextDiagnosticPrinter::EndSourceFile() {
|
||||
LangOpts = 0;
|
||||
TextDiag.reset(0);
|
||||
}
|
||||
|
||||
|
@ -152,22 +152,16 @@ void TextDiagnosticPrinter::HandleDiagnostic(DiagnosticsEngine::Level Level,
|
|||
}
|
||||
|
||||
// Assert that the rest of our infrastructure is setup properly.
|
||||
assert(LangOpts && "Unexpected diagnostic outside source file processing");
|
||||
assert(DiagOpts && "Unexpected diagnostic without options set");
|
||||
assert(Info.hasSourceManager() &&
|
||||
"Unexpected diagnostic with no source manager");
|
||||
|
||||
// Rebuild the TextDiagnostic utility if missing or the source manager has
|
||||
// changed.
|
||||
if (!TextDiag || SM != &Info.getSourceManager()) {
|
||||
SM = &Info.getSourceManager();
|
||||
TextDiag.reset(new TextDiagnostic(OS, *SM, *LangOpts, *DiagOpts));
|
||||
}
|
||||
assert(TextDiag && "Unexpected diagnostic outside source file processing");
|
||||
|
||||
TextDiag->emitDiagnostic(Info.getLocation(), Level, DiagMessageStream.str(),
|
||||
Info.getRanges(),
|
||||
llvm::makeArrayRef(Info.getFixItHints(),
|
||||
Info.getNumFixItHints()));
|
||||
Info.getNumFixItHints()),
|
||||
&Info.getSourceManager());
|
||||
|
||||
OS.flush();
|
||||
}
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
// RUN: rm -f %t
|
||||
// RUN: %clang -fsyntax-only %s -Wblahblah --serialize-diagnostics %t > /dev/null 2>&1 || true
|
||||
// RUN: c-index-test -read-diagnostics %t 2>&1 | FileCheck %s
|
||||
|
||||
// This test case tests that we can handle frontend diagnostics.
|
||||
|
||||
// CHECK: warning: unknown warning option '-Wblahblah'
|
||||
// CHECK: Number of diagnostics: 1
|
|
@ -86,11 +86,10 @@ public:
|
|||
|
||||
class CXDiagnosticRenderer : public DiagnosticNoteRenderer {
|
||||
public:
|
||||
CXDiagnosticRenderer(const SourceManager &SM,
|
||||
const LangOptions &LangOpts,
|
||||
CXDiagnosticRenderer(const LangOptions &LangOpts,
|
||||
const DiagnosticOptions &DiagOpts,
|
||||
CXDiagnosticSetImpl *mainSet)
|
||||
: DiagnosticNoteRenderer(SM, LangOpts, DiagOpts),
|
||||
: DiagnosticNoteRenderer(LangOpts, DiagOpts),
|
||||
CurrentSet(mainSet), MainSet(mainSet) {}
|
||||
|
||||
virtual ~CXDiagnosticRenderer() {}
|
||||
|
@ -116,26 +115,38 @@ public:
|
|||
DiagnosticsEngine::Level Level,
|
||||
StringRef Message,
|
||||
ArrayRef<CharSourceRange> Ranges,
|
||||
const SourceManager *SM,
|
||||
DiagOrStoredDiag D) {
|
||||
if (!D.isNull())
|
||||
return;
|
||||
|
||||
CXSourceLocation L = translateSourceLocation(SM, LangOpts, Loc);
|
||||
CXSourceLocation L;
|
||||
if (SM)
|
||||
L = translateSourceLocation(*SM, LangOpts, Loc);
|
||||
else
|
||||
L = clang_getNullLocation();
|
||||
CXDiagnosticImpl *CD = new CXDiagnosticCustomNoteImpl(Message, L);
|
||||
CurrentSet->appendDiagnostic(CD);
|
||||
}
|
||||
|
||||
virtual void emitDiagnosticLoc(SourceLocation Loc, PresumedLoc PLoc,
|
||||
DiagnosticsEngine::Level Level,
|
||||
ArrayRef<CharSourceRange> Ranges) {}
|
||||
ArrayRef<CharSourceRange> Ranges,
|
||||
const SourceManager &SM) {}
|
||||
|
||||
virtual void emitCodeContext(SourceLocation Loc,
|
||||
DiagnosticsEngine::Level Level,
|
||||
SmallVectorImpl<CharSourceRange>& Ranges,
|
||||
ArrayRef<FixItHint> Hints) {}
|
||||
ArrayRef<FixItHint> Hints,
|
||||
const SourceManager &SM) {}
|
||||
|
||||
virtual void emitNote(SourceLocation Loc, StringRef Message) {
|
||||
CXSourceLocation L = translateSourceLocation(SM, LangOpts, Loc);
|
||||
virtual void emitNote(SourceLocation Loc, StringRef Message,
|
||||
const SourceManager *SM) {
|
||||
CXSourceLocation L;
|
||||
if (SM)
|
||||
L = translateSourceLocation(*SM, LangOpts, Loc);
|
||||
else
|
||||
L = clang_getNullLocation();
|
||||
CurrentSet->appendDiagnostic(new CXDiagnosticCustomNoteImpl(Message,
|
||||
L));
|
||||
}
|
||||
|
@ -181,8 +192,7 @@ CXDiagnosticSetImpl *cxdiag::lazyCreateDiags(CXTranslationUnit TU,
|
|||
CXDiagnosticSetImpl *Set = new CXDiagnosticSetImpl();
|
||||
TU->Diagnostics = Set;
|
||||
DiagnosticOptions DOpts;
|
||||
CXDiagnosticRenderer Renderer(AU->getSourceManager(),
|
||||
AU->getASTContext().getLangOpts(),
|
||||
CXDiagnosticRenderer Renderer(AU->getASTContext().getLangOpts(),
|
||||
DOpts, Set);
|
||||
|
||||
for (ASTUnit::stored_diag_iterator it = AU->stored_diag_begin(),
|
||||
|
|
Loading…
Reference in New Issue