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

View File

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

View File

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

View File

@ -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);
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);
}

View File

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

View File

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

View File

@ -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();
}

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 {
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(),