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:
Argyrios Kyrtzidis 2012-05-10 05:03:45 +00:00
parent 3d081399f0
commit b16ff5d1ce
9 changed files with 144 additions and 95 deletions

View File

@ -43,7 +43,6 @@ typedef llvm::PointerUnion<const Diagnostic *,
/// class. /// class.
class DiagnosticRenderer { class DiagnosticRenderer {
protected: protected:
const SourceManager &SM;
const LangOptions &LangOpts; const LangOptions &LangOpts;
const DiagnosticOptions &DiagOpts; const DiagnosticOptions &DiagOpts;
@ -66,8 +65,7 @@ protected:
/// which change the amount of information displayed. /// which change the amount of information displayed.
DiagnosticsEngine::Level LastLevel; DiagnosticsEngine::Level LastLevel;
DiagnosticRenderer(const SourceManager &SM, DiagnosticRenderer(const LangOptions &LangOpts,
const LangOptions &LangOpts,
const DiagnosticOptions &DiagOpts); const DiagnosticOptions &DiagOpts);
virtual ~DiagnosticRenderer(); virtual ~DiagnosticRenderer();
@ -76,20 +74,24 @@ protected:
DiagnosticsEngine::Level Level, DiagnosticsEngine::Level Level,
StringRef Message, StringRef Message,
ArrayRef<CharSourceRange> Ranges, ArrayRef<CharSourceRange> Ranges,
const SourceManager *SM,
DiagOrStoredDiag Info) = 0; DiagOrStoredDiag Info) = 0;
virtual void emitDiagnosticLoc(SourceLocation Loc, PresumedLoc PLoc, virtual void emitDiagnosticLoc(SourceLocation Loc, PresumedLoc PLoc,
DiagnosticsEngine::Level Level, DiagnosticsEngine::Level Level,
ArrayRef<CharSourceRange> Ranges) = 0; ArrayRef<CharSourceRange> Ranges,
const SourceManager &SM) = 0;
virtual void emitBasicNote(StringRef Message) = 0; virtual void emitBasicNote(StringRef Message) = 0;
virtual void emitCodeContext(SourceLocation Loc, virtual void emitCodeContext(SourceLocation Loc,
DiagnosticsEngine::Level Level, DiagnosticsEngine::Level Level,
SmallVectorImpl<CharSourceRange>& Ranges, 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, virtual void beginDiagnostic(DiagOrStoredDiag D,
DiagnosticsEngine::Level Level) {} DiagnosticsEngine::Level Level) {}
@ -98,12 +100,14 @@ protected:
private: private:
void emitIncludeStack(SourceLocation Loc, DiagnosticsEngine::Level Level); void emitIncludeStack(SourceLocation Loc, DiagnosticsEngine::Level Level,
void emitIncludeStackRecursively(SourceLocation Loc); const SourceManager &SM);
void emitIncludeStackRecursively(SourceLocation Loc, const SourceManager &SM);
void emitMacroExpansionsAndCarets(SourceLocation Loc, void emitMacroExpansionsAndCarets(SourceLocation Loc,
DiagnosticsEngine::Level Level, DiagnosticsEngine::Level Level,
SmallVectorImpl<CharSourceRange>& Ranges, SmallVectorImpl<CharSourceRange>& Ranges,
ArrayRef<FixItHint> Hints, ArrayRef<FixItHint> Hints,
const SourceManager &SM,
unsigned &MacroDepth, unsigned &MacroDepth,
unsigned OnMacroInst = 0); unsigned OnMacroInst = 0);
public: public:
@ -119,9 +123,12 @@ public:
/// \param Message The diagnostic message to emit. /// \param Message The diagnostic message to emit.
/// \param Ranges The underlined ranges for this code snippet. /// \param Ranges The underlined ranges for this code snippet.
/// \param FixItHints The FixIt hints active for this diagnostic. /// \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, void emitDiagnostic(SourceLocation Loc, DiagnosticsEngine::Level Level,
StringRef Message, ArrayRef<CharSourceRange> Ranges, StringRef Message, ArrayRef<CharSourceRange> Ranges,
ArrayRef<FixItHint> FixItHints, ArrayRef<FixItHint> FixItHints,
const SourceManager *SM,
DiagOrStoredDiag D = (Diagnostic *)0); DiagOrStoredDiag D = (Diagnostic *)0);
void emitStoredDiagnostic(StoredDiagnostic &Diag); void emitStoredDiagnostic(StoredDiagnostic &Diag);
@ -131,19 +138,20 @@ public:
/// notes. It is up to subclasses to further define the behavior. /// notes. It is up to subclasses to further define the behavior.
class DiagnosticNoteRenderer : public DiagnosticRenderer { class DiagnosticNoteRenderer : public DiagnosticRenderer {
public: public:
DiagnosticNoteRenderer(const SourceManager &SM, DiagnosticNoteRenderer(const LangOptions &LangOpts,
const LangOptions &LangOpts,
const DiagnosticOptions &DiagOpts) const DiagnosticOptions &DiagOpts)
: DiagnosticRenderer(SM, LangOpts, DiagOpts) {} : DiagnosticRenderer(LangOpts, DiagOpts) {}
virtual ~DiagnosticNoteRenderer(); virtual ~DiagnosticNoteRenderer();
virtual void emitBasicNote(StringRef Message); virtual void emitBasicNote(StringRef Message);
virtual void emitIncludeLocation(SourceLocation Loc, 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 } // end clang namespace
#endif #endif

View File

@ -39,7 +39,6 @@ class TextDiagnostic : public DiagnosticRenderer {
public: public:
TextDiagnostic(raw_ostream &OS, TextDiagnostic(raw_ostream &OS,
const SourceManager &SM,
const LangOptions &LangOpts, const LangOptions &LangOpts,
const DiagnosticOptions &DiagOpts); const DiagnosticOptions &DiagOpts);
@ -83,39 +82,46 @@ protected:
DiagnosticsEngine::Level Level, DiagnosticsEngine::Level Level,
StringRef Message, StringRef Message,
ArrayRef<CharSourceRange> Ranges, ArrayRef<CharSourceRange> Ranges,
const SourceManager *SM,
DiagOrStoredDiag D); DiagOrStoredDiag D);
virtual void emitDiagnosticLoc(SourceLocation Loc, PresumedLoc PLoc, virtual void emitDiagnosticLoc(SourceLocation Loc, PresumedLoc PLoc,
DiagnosticsEngine::Level Level, DiagnosticsEngine::Level Level,
ArrayRef<CharSourceRange> Ranges); ArrayRef<CharSourceRange> Ranges,
const SourceManager &SM);
virtual void emitCodeContext(SourceLocation Loc, virtual void emitCodeContext(SourceLocation Loc,
DiagnosticsEngine::Level Level, DiagnosticsEngine::Level Level,
SmallVectorImpl<CharSourceRange>& Ranges, SmallVectorImpl<CharSourceRange>& Ranges,
ArrayRef<FixItHint> Hints) { ArrayRef<FixItHint> Hints,
emitSnippetAndCaret(Loc, Level, Ranges, Hints); const SourceManager &SM) {
emitSnippetAndCaret(Loc, Level, Ranges, Hints, SM);
} }
virtual void emitBasicNote(StringRef Message); virtual void emitBasicNote(StringRef Message);
virtual void emitIncludeLocation(SourceLocation Loc, PresumedLoc PLoc); virtual void emitIncludeLocation(SourceLocation Loc, PresumedLoc PLoc,
const SourceManager &SM);
private: private:
void emitSnippetAndCaret(SourceLocation Loc, DiagnosticsEngine::Level Level, void emitSnippetAndCaret(SourceLocation Loc, DiagnosticsEngine::Level Level,
SmallVectorImpl<CharSourceRange>& Ranges, SmallVectorImpl<CharSourceRange>& Ranges,
ArrayRef<FixItHint> Hints); ArrayRef<FixItHint> Hints,
const SourceManager &SM);
void emitSnippet(StringRef SourceLine); void emitSnippet(StringRef SourceLine);
void highlightRange(const CharSourceRange &R, void highlightRange(const CharSourceRange &R,
unsigned LineNo, FileID FID, unsigned LineNo, FileID FID,
const SourceColumnMap &map, const SourceColumnMap &map,
std::string &CaretLine); std::string &CaretLine,
const SourceManager &SM);
std::string buildFixItInsertionLine(unsigned LineNo, std::string buildFixItInsertionLine(unsigned LineNo,
const SourceColumnMap &map, const SourceColumnMap &map,
ArrayRef<FixItHint> Hints); ArrayRef<FixItHint> Hints,
void emitParseableFixits(ArrayRef<FixItHint> Hints); const SourceManager &SM);
void emitParseableFixits(ArrayRef<FixItHint> Hints, const SourceManager &SM);
}; };
} // end namespace clang } // end namespace clang

View File

@ -26,9 +26,7 @@ class TextDiagnostic;
class TextDiagnosticPrinter : public DiagnosticConsumer { class TextDiagnosticPrinter : public DiagnosticConsumer {
raw_ostream &OS; raw_ostream &OS;
const LangOptions *LangOpts;
const DiagnosticOptions *DiagOpts; const DiagnosticOptions *DiagOpts;
const SourceManager *SM;
/// \brief Handle to the currently active text diagnostic emitter. /// \brief Handle to the currently active text diagnostic emitter.
OwningPtr<TextDiagnostic> TextDiag; OwningPtr<TextDiagnostic> TextDiag;

View File

@ -123,10 +123,9 @@ static PresumedLoc getDiagnosticPresumedLoc(const SourceManager &SM,
return SM.getPresumedLoc(Loc); return SM.getPresumedLoc(Loc);
} }
DiagnosticRenderer::DiagnosticRenderer(const SourceManager &SM, DiagnosticRenderer::DiagnosticRenderer(const LangOptions &LangOpts,
const LangOptions &LangOpts,
const DiagnosticOptions &DiagOpts) const DiagnosticOptions &DiagOpts)
: SM(SM), LangOpts(LangOpts), DiagOpts(DiagOpts), LastLevel() {} : LangOpts(LangOpts), DiagOpts(DiagOpts), LastLevel() {}
DiagnosticRenderer::~DiagnosticRenderer() {} DiagnosticRenderer::~DiagnosticRenderer() {}
@ -184,18 +183,23 @@ void DiagnosticRenderer::emitDiagnostic(SourceLocation Loc,
StringRef Message, StringRef Message,
ArrayRef<CharSourceRange> Ranges, ArrayRef<CharSourceRange> Ranges,
ArrayRef<FixItHint> FixItHints, ArrayRef<FixItHint> FixItHints,
const SourceManager *SM,
DiagOrStoredDiag D) { DiagOrStoredDiag D) {
assert(SM || Loc.isInvalid());
beginDiagnostic(D, Level); 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 // First, if this diagnostic is not in the main file, print out the
// "included from" lines. // "included from" lines.
emitIncludeStack(PLoc.getIncludeLoc(), Level); emitIncludeStack(PLoc.getIncludeLoc(), Level, *SM);
}
// Next, emit the actual diagnostic message. // 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. // Only recurse if we have a valid location.
if (Loc.isValid()) { if (Loc.isValid()) {
@ -205,7 +209,7 @@ void DiagnosticRenderer::emitDiagnostic(SourceLocation Loc,
llvm::SmallVector<FixItHint, 8> MergedFixits; llvm::SmallVector<FixItHint, 8> MergedFixits;
if (!FixItHints.empty()) { if (!FixItHints.empty()) {
mergeFixits(FixItHints, SM, LangOpts, MergedFixits); mergeFixits(FixItHints, *SM, LangOpts, MergedFixits);
FixItHints = MergedFixits; FixItHints = MergedFixits;
} }
@ -216,7 +220,7 @@ void DiagnosticRenderer::emitDiagnostic(SourceLocation Loc,
MutableRanges.push_back(I->RemoveRange); MutableRanges.push_back(I->RemoveRange);
unsigned MacroDepth = 0; unsigned MacroDepth = 0;
emitMacroExpansionsAndCarets(Loc, Level, MutableRanges, FixItHints, emitMacroExpansionsAndCarets(Loc, Level, MutableRanges, FixItHints, *SM,
MacroDepth); MacroDepth);
} }
@ -230,6 +234,8 @@ void DiagnosticRenderer::emitDiagnostic(SourceLocation Loc,
void DiagnosticRenderer::emitStoredDiagnostic(StoredDiagnostic &Diag) { void DiagnosticRenderer::emitStoredDiagnostic(StoredDiagnostic &Diag) {
emitDiagnostic(Diag.getLocation(), Diag.getLevel(), Diag.getMessage(), emitDiagnostic(Diag.getLocation(), Diag.getLevel(), Diag.getMessage(),
Diag.getRanges(), Diag.getFixIts(), Diag.getRanges(), Diag.getFixIts(),
Diag.getLocation().isValid() ? &Diag.getLocation().getManager()
: 0,
&Diag); &Diag);
} }
@ -245,7 +251,8 @@ void DiagnosticRenderer::emitStoredDiagnostic(StoredDiagnostic &Diag) {
/// \param Loc The include location of the current file (not the diagnostic /// \param Loc The include location of the current file (not the diagnostic
/// location). /// location).
void DiagnosticRenderer::emitIncludeStack(SourceLocation Loc, void DiagnosticRenderer::emitIncludeStack(SourceLocation Loc,
DiagnosticsEngine::Level Level) { DiagnosticsEngine::Level Level,
const SourceManager &SM) {
// Skip redundant include stacks altogether. // Skip redundant include stacks altogether.
if (LastIncludeLoc == Loc) if (LastIncludeLoc == Loc)
return; return;
@ -254,12 +261,13 @@ void DiagnosticRenderer::emitIncludeStack(SourceLocation Loc,
if (!DiagOpts.ShowNoteIncludeStack && Level == DiagnosticsEngine::Note) if (!DiagOpts.ShowNoteIncludeStack && Level == DiagnosticsEngine::Note)
return; return;
emitIncludeStackRecursively(Loc); emitIncludeStackRecursively(Loc, SM);
} }
/// \brief Helper to recursivly walk up the include stack and print each layer /// \brief Helper to recursivly walk up the include stack and print each layer
/// on the way back down. /// on the way back down.
void DiagnosticRenderer::emitIncludeStackRecursively(SourceLocation Loc) { void DiagnosticRenderer::emitIncludeStackRecursively(SourceLocation Loc,
const SourceManager &SM) {
if (Loc.isInvalid()) if (Loc.isInvalid())
return; return;
@ -268,10 +276,10 @@ void DiagnosticRenderer::emitIncludeStackRecursively(SourceLocation Loc) {
return; return;
// Emit the other include frames first. // Emit the other include frames first.
emitIncludeStackRecursively(PLoc.getIncludeLoc()); emitIncludeStackRecursively(PLoc.getIncludeLoc(), SM);
// Emit the inclusion text/note. // Emit the inclusion text/note.
emitIncludeLocation(Loc, PLoc); emitIncludeLocation(Loc, PLoc, SM);
} }
/// \brief Recursively emit notes for each macro expansion and caret /// \brief Recursively emit notes for each macro expansion and caret
@ -292,6 +300,7 @@ void DiagnosticRenderer::emitMacroExpansionsAndCarets(
DiagnosticsEngine::Level Level, DiagnosticsEngine::Level Level,
SmallVectorImpl<CharSourceRange>& Ranges, SmallVectorImpl<CharSourceRange>& Ranges,
ArrayRef<FixItHint> Hints, ArrayRef<FixItHint> Hints,
const SourceManager &SM,
unsigned &MacroDepth, unsigned &MacroDepth,
unsigned OnMacroInst) unsigned OnMacroInst)
{ {
@ -302,7 +311,7 @@ void DiagnosticRenderer::emitMacroExpansionsAndCarets(
if (Loc.isFileID()) { if (Loc.isFileID()) {
assert(MacroDepth == 0 && "We shouldn't hit a leaf node twice!"); assert(MacroDepth == 0 && "We shouldn't hit a leaf node twice!");
MacroDepth = OnMacroInst; MacroDepth = OnMacroInst;
emitCodeContext(Loc, Level, Ranges, Hints); emitCodeContext(Loc, Level, Ranges, Hints, SM);
return; return;
} }
// Otherwise recurse through each macro expansion layer. // Otherwise recurse through each macro expansion layer.
@ -314,7 +323,7 @@ void DiagnosticRenderer::emitMacroExpansionsAndCarets(
SourceLocation OneLevelUp = getImmediateMacroCallerLoc(SM, Loc); SourceLocation OneLevelUp = getImmediateMacroCallerLoc(SM, Loc);
// FIXME: Map ranges? // FIXME: Map ranges?
emitMacroExpansionsAndCarets(OneLevelUp, Level, Ranges, Hints, MacroDepth, emitMacroExpansionsAndCarets(OneLevelUp, Level, Ranges, Hints, SM, MacroDepth,
OnMacroInst + 1); OnMacroInst + 1);
// Save the original location so we can find the spelling of the macro call. // 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) << "'"; << getImmediateMacroName(MacroLoc, SM, LangOpts) << "'";
emitDiagnostic(SM.getSpellingLoc(Loc), DiagnosticsEngine::Note, emitDiagnostic(SM.getSpellingLoc(Loc), DiagnosticsEngine::Note,
Message.str(), Message.str(),
Ranges, ArrayRef<FixItHint>()); Ranges, ArrayRef<FixItHint>(), &SM);
} }
DiagnosticNoteRenderer::~DiagnosticNoteRenderer() {} DiagnosticNoteRenderer::~DiagnosticNoteRenderer() {}
void DiagnosticNoteRenderer::emitIncludeLocation(SourceLocation Loc, void DiagnosticNoteRenderer::emitIncludeLocation(SourceLocation Loc,
PresumedLoc PLoc) { PresumedLoc PLoc,
const SourceManager &SM) {
// Generate a note indicating the include location. // Generate a note indicating the include location.
SmallString<200> MessageStorage; SmallString<200> MessageStorage;
llvm::raw_svector_ostream Message(MessageStorage); llvm::raw_svector_ostream Message(MessageStorage);
Message << "in file included from " << PLoc.getFilename() << ':' Message << "in file included from " << PLoc.getFilename() << ':'
<< PLoc.getLine() << ":"; << PLoc.getLine() << ":";
emitNote(Loc, Message.str()); emitNote(Loc, Message.str(), &SM);
} }
void DiagnosticNoteRenderer::emitBasicNote(StringRef Message) { void DiagnosticNoteRenderer::emitBasicNote(StringRef Message) {
emitNote(SourceLocation(), Message); emitNote(SourceLocation(), Message, 0);
} }

View File

@ -53,10 +53,9 @@ class SDiagsRenderer : public DiagnosticNoteRenderer {
RecordData &Record; RecordData &Record;
public: public:
SDiagsRenderer(SDiagsWriter &Writer, RecordData &Record, SDiagsRenderer(SDiagsWriter &Writer, RecordData &Record,
const SourceManager &SM,
const LangOptions &LangOpts, const LangOptions &LangOpts,
const DiagnosticOptions &DiagOpts) const DiagnosticOptions &DiagOpts)
: DiagnosticNoteRenderer(SM, LangOpts, DiagOpts), : DiagnosticNoteRenderer(LangOpts, DiagOpts),
Writer(Writer), Record(Record){} Writer(Writer), Record(Record){}
virtual ~SDiagsRenderer() {} virtual ~SDiagsRenderer() {}
@ -67,18 +66,21 @@ protected:
DiagnosticsEngine::Level Level, DiagnosticsEngine::Level Level,
StringRef Message, StringRef Message,
ArrayRef<CharSourceRange> Ranges, ArrayRef<CharSourceRange> Ranges,
const SourceManager *SM,
DiagOrStoredDiag D); DiagOrStoredDiag D);
virtual void emitDiagnosticLoc(SourceLocation Loc, PresumedLoc PLoc, virtual void emitDiagnosticLoc(SourceLocation Loc, PresumedLoc PLoc,
DiagnosticsEngine::Level Level, 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, virtual void emitCodeContext(SourceLocation Loc,
DiagnosticsEngine::Level Level, DiagnosticsEngine::Level Level,
SmallVectorImpl<CharSourceRange>& Ranges, SmallVectorImpl<CharSourceRange>& Ranges,
ArrayRef<FixItHint> Hints); ArrayRef<FixItHint> Hints,
const SourceManager &SM);
virtual void beginDiagnostic(DiagOrStoredDiag D, virtual void beginDiagnostic(DiagOrStoredDiag D,
DiagnosticsEngine::Level Level); DiagnosticsEngine::Level Level);
@ -137,15 +139,16 @@ private:
unsigned getEmitFile(const char *Filename); unsigned getEmitFile(const char *Filename);
/// \brief Add SourceLocation information the specified record. /// \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, PresumedLoc PLoc, RecordDataImpl &Record,
unsigned TokSize = 0); unsigned TokSize = 0);
/// \brief Add SourceLocation information the specified record. /// \brief Add SourceLocation information the specified record.
void AddLocToRecord(SourceLocation Loc, RecordDataImpl &Record, void AddLocToRecord(SourceLocation Loc, RecordDataImpl &Record,
const SourceManager &SM, const SourceManager *SM,
unsigned TokSize = 0) { 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. /// \brief Add CharSourceRange information the specified record.
@ -241,7 +244,7 @@ static void EmitRecordID(unsigned ID, const char *Name,
} }
void SDiagsWriter::AddLocToRecord(SourceLocation Loc, void SDiagsWriter::AddLocToRecord(SourceLocation Loc,
const SourceManager &SM, const SourceManager *SM,
PresumedLoc PLoc, PresumedLoc PLoc,
RecordDataImpl &Record, RecordDataImpl &Record,
unsigned TokSize) { unsigned TokSize) {
@ -257,19 +260,19 @@ void SDiagsWriter::AddLocToRecord(SourceLocation Loc,
Record.push_back(getEmitFile(PLoc.getFilename())); Record.push_back(getEmitFile(PLoc.getFilename()));
Record.push_back(PLoc.getLine()); Record.push_back(PLoc.getLine());
Record.push_back(PLoc.getColumn()+TokSize); Record.push_back(PLoc.getColumn()+TokSize);
Record.push_back(SM.getFileOffset(Loc)); Record.push_back(SM->getFileOffset(Loc));
} }
void SDiagsWriter::AddCharSourceRangeToRecord(CharSourceRange Range, void SDiagsWriter::AddCharSourceRangeToRecord(CharSourceRange Range,
RecordDataImpl &Record, RecordDataImpl &Record,
const SourceManager &SM) { const SourceManager &SM) {
AddLocToRecord(Range.getBegin(), Record, SM); AddLocToRecord(Range.getBegin(), Record, &SM);
unsigned TokSize = 0; unsigned TokSize = 0;
if (Range.isTokenRange()) if (Range.isTokenRange())
TokSize = Lexer::MeasureTokenLength(Range.getEnd(), TokSize = Lexer::MeasureTokenLength(Range.getEnd(),
SM, *LangOpts); SM, *LangOpts);
AddLocToRecord(Range.getEnd(), Record, SM, TokSize); AddLocToRecord(Range.getEnd(), Record, &SM, TokSize);
} }
unsigned SDiagsWriter::getEmitFile(const char *FileName){ unsigned SDiagsWriter::getEmitFile(const char *FileName){
@ -484,13 +487,15 @@ void SDiagsWriter::HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
diagBuf.clear(); diagBuf.clear();
Info.FormatDiagnostic(diagBuf); Info.FormatDiagnostic(diagBuf);
SourceManager &SM = Info.getSourceManager(); const SourceManager *
SDiagsRenderer Renderer(*this, Record, SM, *LangOpts, DiagOpts); SM = Info.hasSourceManager() ? &Info.getSourceManager() : 0;
SDiagsRenderer Renderer(*this, Record, *LangOpts, DiagOpts);
Renderer.emitDiagnostic(Info.getLocation(), DiagLevel, Renderer.emitDiagnostic(Info.getLocation(), DiagLevel,
diagBuf.str(), diagBuf.str(),
Info.getRanges(), Info.getRanges(),
llvm::makeArrayRef(Info.getFixItHints(), llvm::makeArrayRef(Info.getFixItHints(),
Info.getNumFixItHints()), Info.getNumFixItHints()),
SM,
&Info); &Info);
} }
@ -500,6 +505,7 @@ SDiagsRenderer::emitDiagnosticMessage(SourceLocation Loc,
DiagnosticsEngine::Level Level, DiagnosticsEngine::Level Level,
StringRef Message, StringRef Message,
ArrayRef<clang::CharSourceRange> Ranges, ArrayRef<clang::CharSourceRange> Ranges,
const SourceManager *SM,
DiagOrStoredDiag D) { DiagOrStoredDiag D) {
// Emit the RECORD_DIAG record. // Emit the RECORD_DIAG record.
Writer.Record.clear(); Writer.Record.clear();
@ -539,7 +545,8 @@ void SDiagsRenderer::endDiagnostic(DiagOrStoredDiag D,
void SDiagsRenderer::emitCodeContext(SourceLocation Loc, void SDiagsRenderer::emitCodeContext(SourceLocation Loc,
DiagnosticsEngine::Level Level, DiagnosticsEngine::Level Level,
SmallVectorImpl<CharSourceRange> &Ranges, SmallVectorImpl<CharSourceRange> &Ranges,
ArrayRef<FixItHint> Hints) { ArrayRef<FixItHint> Hints,
const SourceManager &SM) {
// Emit Source Ranges. // Emit Source Ranges.
for (ArrayRef<CharSourceRange>::iterator it=Ranges.begin(), ei=Ranges.end(); for (ArrayRef<CharSourceRange>::iterator it=Ranges.begin(), ei=Ranges.end();
it != ei; ++it) { 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); Writer.Stream.EnterSubblock(BLOCK_DIAG, 4);
RecordData Record; RecordData Record;
Record.push_back(RECORD_DIAG); Record.push_back(RECORD_DIAG);

View File

@ -602,10 +602,9 @@ static bool printWordWrapped(raw_ostream &OS, StringRef Str,
} }
TextDiagnostic::TextDiagnostic(raw_ostream &OS, TextDiagnostic::TextDiagnostic(raw_ostream &OS,
const SourceManager &SM,
const LangOptions &LangOpts, const LangOptions &LangOpts,
const DiagnosticOptions &DiagOpts) const DiagnosticOptions &DiagOpts)
: DiagnosticRenderer(SM, LangOpts, DiagOpts), OS(OS) {} : DiagnosticRenderer(LangOpts, DiagOpts), OS(OS) {}
TextDiagnostic::~TextDiagnostic() {} TextDiagnostic::~TextDiagnostic() {}
@ -615,11 +614,13 @@ TextDiagnostic::emitDiagnosticMessage(SourceLocation Loc,
DiagnosticsEngine::Level Level, DiagnosticsEngine::Level Level,
StringRef Message, StringRef Message,
ArrayRef<clang::CharSourceRange> Ranges, ArrayRef<clang::CharSourceRange> Ranges,
const SourceManager *SM,
DiagOrStoredDiag D) { DiagOrStoredDiag D) {
uint64_t StartOfLocationInfo = OS.tell(); uint64_t StartOfLocationInfo = OS.tell();
// Emit the location of this particular diagnostic. // Emit the location of this particular diagnostic.
emitDiagnosticLoc(Loc, PLoc, Level, Ranges); if (Loc.isValid())
emitDiagnosticLoc(Loc, PLoc, Level, Ranges, *SM);
if (DiagOpts.ShowColors) if (DiagOpts.ShowColors)
OS.resetColor(); OS.resetColor();
@ -693,7 +694,8 @@ TextDiagnostic::printDiagnosticMessage(raw_ostream &OS,
/// ranges necessary. /// ranges necessary.
void TextDiagnostic::emitDiagnosticLoc(SourceLocation Loc, PresumedLoc PLoc, void TextDiagnostic::emitDiagnosticLoc(SourceLocation Loc, PresumedLoc PLoc,
DiagnosticsEngine::Level Level, DiagnosticsEngine::Level Level,
ArrayRef<CharSourceRange> Ranges) { ArrayRef<CharSourceRange> Ranges,
const SourceManager &SM) {
if (PLoc.isInvalid()) { if (PLoc.isInvalid()) {
// At least print the file name if available: // At least print the file name if available:
FileID FID = SM.getFileID(Loc); FileID FID = SM.getFileID(Loc);
@ -799,7 +801,8 @@ void TextDiagnostic::emitBasicNote(StringRef Message) {
} }
void TextDiagnostic::emitIncludeLocation(SourceLocation Loc, void TextDiagnostic::emitIncludeLocation(SourceLocation Loc,
PresumedLoc PLoc) { PresumedLoc PLoc,
const SourceManager &SM) {
if (DiagOpts.ShowLocation) if (DiagOpts.ShowLocation)
OS << "In file included from " << PLoc.getFilename() << ':' OS << "In file included from " << PLoc.getFilename() << ':'
<< PLoc.getLine() << ":\n"; << PLoc.getLine() << ":\n";
@ -817,7 +820,8 @@ void TextDiagnostic::emitIncludeLocation(SourceLocation Loc,
void TextDiagnostic::emitSnippetAndCaret( void TextDiagnostic::emitSnippetAndCaret(
SourceLocation Loc, DiagnosticsEngine::Level Level, SourceLocation Loc, DiagnosticsEngine::Level Level,
SmallVectorImpl<CharSourceRange>& Ranges, SmallVectorImpl<CharSourceRange>& Ranges,
ArrayRef<FixItHint> Hints) { ArrayRef<FixItHint> Hints,
const SourceManager &SM) {
assert(!Loc.isInvalid() && "must have a valid source location here"); assert(!Loc.isInvalid() && "must have a valid source location here");
assert(Loc.isFileID() && "must have a file 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(), for (SmallVectorImpl<CharSourceRange>::iterator I = Ranges.begin(),
E = Ranges.end(); E = Ranges.end();
I != E; ++I) I != E; ++I)
highlightRange(*I, LineNo, FID, sourceColMap, CaretLine); highlightRange(*I, LineNo, FID, sourceColMap, CaretLine, SM);
// Next, insert the caret itself. // Next, insert the caret itself.
ColNo = sourceColMap.byteToColumn(ColNo-1); ColNo = sourceColMap.byteToColumn(ColNo-1);
@ -888,7 +892,7 @@ void TextDiagnostic::emitSnippetAndCaret(
std::string FixItInsertionLine = buildFixItInsertionLine(LineNo, std::string FixItInsertionLine = buildFixItInsertionLine(LineNo,
sourceColMap, sourceColMap,
Hints); Hints, SM);
// If the source line is too long for our terminal, select only the // If the source line is too long for our terminal, select only the
// "interesting" source region within that line. // "interesting" source region within that line.
@ -931,7 +935,7 @@ void TextDiagnostic::emitSnippetAndCaret(
} }
// Print out any parseable fixit information requested by the options. // Print out any parseable fixit information requested by the options.
emitParseableFixits(Hints); emitParseableFixits(Hints, SM);
} }
void TextDiagnostic::emitSnippet(StringRef line) { void TextDiagnostic::emitSnippet(StringRef line) {
@ -974,7 +978,8 @@ void TextDiagnostic::emitSnippet(StringRef line) {
void TextDiagnostic::highlightRange(const CharSourceRange &R, void TextDiagnostic::highlightRange(const CharSourceRange &R,
unsigned LineNo, FileID FID, unsigned LineNo, FileID FID,
const SourceColumnMap &map, const SourceColumnMap &map,
std::string &CaretLine) { std::string &CaretLine,
const SourceManager &SM) {
if (!R.isValid()) return; if (!R.isValid()) return;
SourceLocation Begin = SM.getExpansionLoc(R.getBegin()); SourceLocation Begin = SM.getExpansionLoc(R.getBegin());
@ -1059,7 +1064,8 @@ void TextDiagnostic::highlightRange(const CharSourceRange &R,
std::string TextDiagnostic::buildFixItInsertionLine( std::string TextDiagnostic::buildFixItInsertionLine(
unsigned LineNo, unsigned LineNo,
const SourceColumnMap &map, const SourceColumnMap &map,
ArrayRef<FixItHint> Hints) { ArrayRef<FixItHint> Hints,
const SourceManager &SM) {
std::string FixItInsertionLine; std::string FixItInsertionLine;
if (Hints.empty() || !DiagOpts.ShowFixits) if (Hints.empty() || !DiagOpts.ShowFixits)
@ -1114,7 +1120,8 @@ std::string TextDiagnostic::buildFixItInsertionLine(
return FixItInsertionLine; return FixItInsertionLine;
} }
void TextDiagnostic::emitParseableFixits(ArrayRef<FixItHint> Hints) { void TextDiagnostic::emitParseableFixits(ArrayRef<FixItHint> Hints,
const SourceManager &SM) {
if (!DiagOpts.ShowParseableFixits) if (!DiagOpts.ShowParseableFixits)
return; return;

View File

@ -27,7 +27,7 @@ using namespace clang;
TextDiagnosticPrinter::TextDiagnosticPrinter(raw_ostream &os, TextDiagnosticPrinter::TextDiagnosticPrinter(raw_ostream &os,
const DiagnosticOptions &diags, const DiagnosticOptions &diags,
bool _OwnsOutputStream) bool _OwnsOutputStream)
: OS(os), LangOpts(0), DiagOpts(&diags), SM(0), : OS(os), DiagOpts(&diags),
OwnsOutputStream(_OwnsOutputStream) { OwnsOutputStream(_OwnsOutputStream) {
} }
@ -38,11 +38,11 @@ TextDiagnosticPrinter::~TextDiagnosticPrinter() {
void TextDiagnosticPrinter::BeginSourceFile(const LangOptions &LO, void TextDiagnosticPrinter::BeginSourceFile(const LangOptions &LO,
const Preprocessor *PP) { const Preprocessor *PP) {
LangOpts = &LO; // Build the TextDiagnostic utility.
TextDiag.reset(new TextDiagnostic(OS, LO, *DiagOpts));
} }
void TextDiagnosticPrinter::EndSourceFile() { void TextDiagnosticPrinter::EndSourceFile() {
LangOpts = 0;
TextDiag.reset(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 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(DiagOpts && "Unexpected diagnostic without options set");
assert(Info.hasSourceManager() && assert(Info.hasSourceManager() &&
"Unexpected diagnostic with no source manager"); "Unexpected diagnostic with no source manager");
assert(TextDiag && "Unexpected diagnostic outside source file processing");
// 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));
}
TextDiag->emitDiagnostic(Info.getLocation(), Level, DiagMessageStream.str(), TextDiag->emitDiagnostic(Info.getLocation(), Level, DiagMessageStream.str(),
Info.getRanges(), Info.getRanges(),
llvm::makeArrayRef(Info.getFixItHints(), llvm::makeArrayRef(Info.getFixItHints(),
Info.getNumFixItHints())); Info.getNumFixItHints()),
&Info.getSourceManager());
OS.flush(); OS.flush();
} }

View File

@ -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

View File

@ -86,11 +86,10 @@ public:
class CXDiagnosticRenderer : public DiagnosticNoteRenderer { class CXDiagnosticRenderer : public DiagnosticNoteRenderer {
public: public:
CXDiagnosticRenderer(const SourceManager &SM, CXDiagnosticRenderer(const LangOptions &LangOpts,
const LangOptions &LangOpts,
const DiagnosticOptions &DiagOpts, const DiagnosticOptions &DiagOpts,
CXDiagnosticSetImpl *mainSet) CXDiagnosticSetImpl *mainSet)
: DiagnosticNoteRenderer(SM, LangOpts, DiagOpts), : DiagnosticNoteRenderer(LangOpts, DiagOpts),
CurrentSet(mainSet), MainSet(mainSet) {} CurrentSet(mainSet), MainSet(mainSet) {}
virtual ~CXDiagnosticRenderer() {} virtual ~CXDiagnosticRenderer() {}
@ -116,26 +115,38 @@ public:
DiagnosticsEngine::Level Level, DiagnosticsEngine::Level Level,
StringRef Message, StringRef Message,
ArrayRef<CharSourceRange> Ranges, ArrayRef<CharSourceRange> Ranges,
const SourceManager *SM,
DiagOrStoredDiag D) { DiagOrStoredDiag D) {
if (!D.isNull()) if (!D.isNull())
return; 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); CXDiagnosticImpl *CD = new CXDiagnosticCustomNoteImpl(Message, L);
CurrentSet->appendDiagnostic(CD); CurrentSet->appendDiagnostic(CD);
} }
virtual void emitDiagnosticLoc(SourceLocation Loc, PresumedLoc PLoc, virtual void emitDiagnosticLoc(SourceLocation Loc, PresumedLoc PLoc,
DiagnosticsEngine::Level Level, DiagnosticsEngine::Level Level,
ArrayRef<CharSourceRange> Ranges) {} ArrayRef<CharSourceRange> Ranges,
const SourceManager &SM) {}
virtual void emitCodeContext(SourceLocation Loc, virtual void emitCodeContext(SourceLocation Loc,
DiagnosticsEngine::Level Level, DiagnosticsEngine::Level Level,
SmallVectorImpl<CharSourceRange>& Ranges, SmallVectorImpl<CharSourceRange>& Ranges,
ArrayRef<FixItHint> Hints) {} ArrayRef<FixItHint> Hints,
const SourceManager &SM) {}
virtual void emitNote(SourceLocation Loc, StringRef Message) { virtual void emitNote(SourceLocation Loc, StringRef Message,
CXSourceLocation L = translateSourceLocation(SM, LangOpts, Loc); const SourceManager *SM) {
CXSourceLocation L;
if (SM)
L = translateSourceLocation(*SM, LangOpts, Loc);
else
L = clang_getNullLocation();
CurrentSet->appendDiagnostic(new CXDiagnosticCustomNoteImpl(Message, CurrentSet->appendDiagnostic(new CXDiagnosticCustomNoteImpl(Message,
L)); L));
} }
@ -181,8 +192,7 @@ CXDiagnosticSetImpl *cxdiag::lazyCreateDiags(CXTranslationUnit TU,
CXDiagnosticSetImpl *Set = new CXDiagnosticSetImpl(); CXDiagnosticSetImpl *Set = new CXDiagnosticSetImpl();
TU->Diagnostics = Set; TU->Diagnostics = Set;
DiagnosticOptions DOpts; DiagnosticOptions DOpts;
CXDiagnosticRenderer Renderer(AU->getSourceManager(), CXDiagnosticRenderer Renderer(AU->getASTContext().getLangOpts(),
AU->getASTContext().getLangOpts(),
DOpts, Set); DOpts, Set);
for (ASTUnit::stored_diag_iterator it = AU->stored_diag_begin(), for (ASTUnit::stored_diag_iterator it = AU->stored_diag_begin(),