Implement new DiagnosticsRenderer that packages notes retrieved by clang_getDiagnosticSetFromTU() as

child diagnostics of primary diagnostics.  By using the DiagnosticRenderer, these Diagnostics now
match with those generated for serialized diagnostics.

llvm-svn: 150456
This commit is contained in:
Ted Kremenek 2012-02-14 02:46:03 +00:00
parent 0964cca5d5
commit 914c7e62e8
3 changed files with 126 additions and 10 deletions

View File

@ -418,13 +418,21 @@ void PrintDiagnostic(CXDiagnostic Diagnostic) {
}
}
void PrintDiagnostics(CXTranslationUnit TU) {
int i, n = clang_getNumDiagnostics(TU);
for (i = 0; i != n; ++i) {
CXDiagnostic Diag = clang_getDiagnostic(TU, i);
void PrintDiagnosticSet(CXDiagnosticSet Set) {
int i = 0, n = clang_getNumDiagnosticsInSet(Set);
for ( ; i != n ; ++i) {
CXDiagnostic Diag = clang_getDiagnosticInSet(Set, i);
CXDiagnosticSet ChildDiags = clang_getChildDiagnostics(Diag);
PrintDiagnostic(Diag);
clang_disposeDiagnostic(Diag);
}
if (ChildDiags)
PrintDiagnosticSet(ChildDiags);
}
}
void PrintDiagnostics(CXTranslationUnit TU) {
CXDiagnosticSet TUSet = clang_getDiagnosticSetFromTU(TU);
PrintDiagnosticSet(TUSet);
clang_disposeDiagnosticSet(TUSet);
}
void PrintMemoryUsage(CXTranslationUnit TU) {

View File

@ -18,6 +18,8 @@
#include "clang/Frontend/ASTUnit.h"
#include "clang/Frontend/FrontendDiagnostic.h"
#include "clang/Frontend/DiagnosticRenderer.h"
#include "clang/Frontend/DiagnosticOptions.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/Twine.h"
#include "llvm/Support/MemoryBuffer.h"
@ -40,6 +42,109 @@ CXDiagnosticSetImpl::~CXDiagnosticSetImpl() {
CXDiagnosticImpl::~CXDiagnosticImpl() {}
namespace {
class CXDiagnosticCustomNoteImpl : public CXDiagnosticImpl {
CXString Message;
CXSourceLocation Loc;
public:
CXDiagnosticCustomNoteImpl(StringRef Msg, CXSourceLocation L)
: CXDiagnosticImpl(CustomNoteDiagnosticKind),
Message(createCXString(Msg)), Loc(L) {}
virtual ~CXDiagnosticCustomNoteImpl() {
clang_disposeString(Message);
}
CXDiagnosticSeverity getSeverity() const {
return CXDiagnostic_Note;
}
CXSourceLocation getLocation() const {
return Loc;
}
CXString getSpelling() const {
return Message;
}
CXString getDiagnosticOption(CXString *Disable) const {
if (Disable)
*Disable = createCXString("", false);
return createCXString("", false);
}
unsigned getCategory() const { return 0; }
unsigned getNumRanges() const { return 0; }
CXSourceRange getRange(unsigned Range) const { return clang_getNullRange(); }
unsigned getNumFixIts() const { return 0; }
CXString getFixIt(unsigned FixIt, CXSourceRange *ReplacementRange) const {
if (ReplacementRange)
*ReplacementRange = clang_getNullRange();
return createCXString("", false);
}
};
class CXDiagnosticRenderer : public DiagnosticNoteRenderer {
public:
CXDiagnosticRenderer(const SourceManager &SM,
const LangOptions &LangOpts,
const DiagnosticOptions &DiagOpts,
CXDiagnosticSetImpl *mainSet)
: DiagnosticNoteRenderer(SM, LangOpts, DiagOpts),
CurrentSet(mainSet), MainSet(mainSet) {}
virtual ~CXDiagnosticRenderer() {}
virtual void beginDiagnostic(DiagOrStoredDiag D,
DiagnosticsEngine::Level Level) {
const StoredDiagnostic *SD = D.dyn_cast<const StoredDiagnostic*>();
if (!SD)
return;
if (Level != DiagnosticsEngine::Note)
CurrentSet = MainSet;
CXStoredDiagnostic *CD = new CXStoredDiagnostic(*SD, LangOpts);
CurrentSet->appendDiagnostic(CD);
if (Level != DiagnosticsEngine::Note)
CurrentSet = &CD->getChildDiagnostics();
}
virtual void emitDiagnosticMessage(SourceLocation Loc, PresumedLoc PLoc,
DiagnosticsEngine::Level Level,
StringRef Message,
ArrayRef<CharSourceRange> Ranges,
DiagOrStoredDiag D) {
if (!D.isNull())
return;
CXSourceLocation L = translateSourceLocation(SM, LangOpts, Loc);
CXDiagnosticImpl *CD = new CXDiagnosticCustomNoteImpl(Message, L);
CurrentSet->appendDiagnostic(CD);
}
virtual void emitDiagnosticLoc(SourceLocation Loc, PresumedLoc PLoc,
DiagnosticsEngine::Level Level,
ArrayRef<CharSourceRange> Ranges) {}
virtual void emitCodeContext(SourceLocation Loc,
DiagnosticsEngine::Level Level,
SmallVectorImpl<CharSourceRange>& Ranges,
ArrayRef<FixItHint> Hints) {};
virtual void emitNote(SourceLocation Loc, StringRef Message) {
CXSourceLocation L = translateSourceLocation(SM, LangOpts, Loc);
CurrentSet->appendDiagnostic(new CXDiagnosticCustomNoteImpl(Message,
L));
}
CXDiagnosticSetImpl *CurrentSet;
CXDiagnosticSetImpl *MainSet;
};
}
CXDiagnosticSetImpl *cxdiag::lazyCreateDiags(CXTranslationUnit TU,
bool checkIfChanged) {
ASTUnit *AU = static_cast<ASTUnit *>(TU->TUData);
@ -75,12 +180,14 @@ CXDiagnosticSetImpl *cxdiag::lazyCreateDiags(CXTranslationUnit TU,
if (!TU->Diagnostics) {
CXDiagnosticSetImpl *Set = new CXDiagnosticSetImpl();
TU->Diagnostics = Set;
DiagnosticOptions DOpts;
CXDiagnosticRenderer Renderer(AU->getSourceManager(),
AU->getASTContext().getLangOptions(),
DOpts, Set);
for (ASTUnit::stored_diag_iterator it = AU->stored_diag_begin(),
ei = AU->stored_diag_end(); it != ei; ++it) {
CXStoredDiagnostic *D =
new CXStoredDiagnostic(*it, AU->getASTContext().getLangOptions());
Set->appendDiagnostic(D);
Renderer.emitStoredDiagnostic(*it);
}
}
return static_cast<CXDiagnosticSetImpl*>(TU->Diagnostics);

View File

@ -54,7 +54,8 @@ public:
class CXDiagnosticImpl {
public:
enum Kind { StoredDiagnosticKind, LoadedDiagnosticKind };
enum Kind { StoredDiagnosticKind, LoadedDiagnosticKind,
CustomNoteDiagnosticKind };
virtual ~CXDiagnosticImpl();