[cfe-commits] r144269 - in /cfe/trunk: include/clang-c/ include/clang/Frontend/ lib/Frontend/ tools/c-index-test/ tools/libclang/
Ted Kremenek
kremenek at apple.com
Thu Nov 10 00:43:13 PST 2011
Author: kremenek
Date: Thu Nov 10 02:43:12 2011
New Revision: 144269
URL: http://llvm.org/viewvc/llvm-project?rev=144269&view=rev
Log:
serialized diagnostics: implement full deserialization of clang diagnostics via the libclang API.
I've tested it on simple cases and it works. Test cases to follow as well as a few tweaks.
Added:
cfe/trunk/tools/libclang/CXLoadedDiagnostic.cpp
cfe/trunk/tools/libclang/CXLoadedDiagnostic.h
Modified:
cfe/trunk/include/clang-c/Index.h
cfe/trunk/include/clang/Frontend/SerializedDiagnosticPrinter.h
cfe/trunk/lib/Frontend/SerializedDiagnosticPrinter.cpp
cfe/trunk/tools/c-index-test/c-index-test.c
cfe/trunk/tools/libclang/CIndex.cpp
cfe/trunk/tools/libclang/CIndexDiagnostic.cpp
cfe/trunk/tools/libclang/CIndexDiagnostic.h
cfe/trunk/tools/libclang/CMakeLists.txt
cfe/trunk/tools/libclang/CXSourceLocation.cpp
cfe/trunk/tools/libclang/CXStoredDiagnostic.cpp
cfe/trunk/tools/libclang/CXTranslationUnit.h
cfe/trunk/tools/libclang/libclang.exports
Modified: cfe/trunk/include/clang-c/Index.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang-c/Index.h?rev=144269&r1=144268&r2=144269&view=diff
==============================================================================
--- cfe/trunk/include/clang-c/Index.h (original)
+++ cfe/trunk/include/clang-c/Index.h Thu Nov 10 02:43:12 2011
@@ -522,6 +522,86 @@
typedef void *CXDiagnostic;
/**
+ * \brief A group of CXDiagnostics.
+ */
+typedef void *CXDiagnosticSet;
+
+/**
+ * \brief Determine the number of diagnostics in a CXDiagnosticSet.
+ */
+CINDEX_LINKAGE unsigned clang_getNumDiagnosticsInSet(CXDiagnosticSet Diags);
+
+/**
+ * \brief Retrieve a diagnostic associated with the given CXDiagnosticSet.
+ *
+ * \param Unit the CXDiagnosticSet to query.
+ * \param Index the zero-based diagnostic number to retrieve.
+ *
+ * \returns the requested diagnostic. This diagnostic must be freed
+ * via a call to \c clang_disposeDiagnostic().
+ */
+CINDEX_LINKAGE CXDiagnostic clang_getDiagnosticInSet(CXDiagnosticSet Diags,
+ unsigned Index);
+
+
+/**
+ * \brief Describes the kind of error that occurred (if any) in a call to
+ * \c clang_loadDiagnostics.
+ */
+enum CXLoadDiag_Error {
+ /**
+ * \brief Indicates that no error occurred.
+ */
+ CXLoadDiag_None = 0,
+
+ /**
+ * \brief Indicates that an unknown error occurred while attempting to
+ * deserialize diagnostics.
+ */
+ CXLoadDiag_Unknown = 1,
+
+ /**
+ * \brief Indicates that the file containing the serialized diagnostics
+ * could not be opened.
+ */
+ CXLoadDiag_CannotLoad = 2,
+
+ /**
+ * \brief Indicates that the serialized diagnostics file is invalid or
+ * corrupt.
+ */
+ CXLoadDiag_InvalidFile = 3
+};
+
+/**
+ * \brief Deserialize a set of diagnostics from a Clang diagnostics bitcode
+ * file.
+ *
+ * \param The name of the file to deserialize.
+ * \param A pointer to a enum value recording if there was a problem
+ * deserializing the diagnostics.
+ * \param A pointer to a CXString for recording the error string
+ * if the file was not successfully loaded.
+ *
+ * \returns A loaded CXDiagnosticSet if successful, and NULL otherwise. These
+ * diagnostics should be released using clang_disposeDiagnosticSet().
+ */
+CINDEX_LINKAGE CXDiagnosticSet clang_loadDiagnostics(const char *file,
+ enum CXLoadDiag_Error *error,
+ CXString *errorString);
+
+/**
+ * \brief Release a CXDiagnosticSet and all of its contained diagnostics.
+ */
+CINDEX_LINKAGE void clang_disposeDiagnosticSet(CXDiagnosticSet Diags);
+
+/**
+ * \brief Retrieve the child diagnostics of a CXDiagnostic. This
+ * CXDiagnosticSet does not need to be released by clang_diposeDiagnosticSet.
+ */
+CINDEX_LINKAGE CXDiagnosticSet clang_getChildDiagnostics(CXDiagnostic D);
+
+/**
* \brief Determine the number of diagnostics produced for the given
* translation unit.
*/
Modified: cfe/trunk/include/clang/Frontend/SerializedDiagnosticPrinter.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Frontend/SerializedDiagnosticPrinter.h?rev=144269&r1=144268&r2=144269&view=diff
==============================================================================
--- cfe/trunk/include/clang/Frontend/SerializedDiagnosticPrinter.h (original)
+++ cfe/trunk/include/clang/Frontend/SerializedDiagnosticPrinter.h Thu Nov 10 02:43:12 2011
@@ -39,7 +39,9 @@
RECORD_DIAG_FLAG,
RECORD_CATEGORY,
RECORD_FILENAME,
- RECORD_FIXIT
+ RECORD_FIXIT,
+ RECORD_FIRST = RECORD_VERSION,
+ RECORD_LAST = RECORD_FIXIT
};
/// \brief Returns a DiagnosticConsumer that serializes diagnostics to
Modified: cfe/trunk/lib/Frontend/SerializedDiagnosticPrinter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/SerializedDiagnosticPrinter.cpp?rev=144269&r1=144268&r2=144269&view=diff
==============================================================================
--- cfe/trunk/lib/Frontend/SerializedDiagnosticPrinter.cpp (original)
+++ cfe/trunk/lib/Frontend/SerializedDiagnosticPrinter.cpp Thu Nov 10 02:43:12 2011
@@ -16,6 +16,7 @@
#include "clang/Basic/FileManager.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/Version.h"
+#include "clang/Lex/Lexer.h"
#include "clang/Frontend/SerializedDiagnosticPrinter.h"
using namespace clang;
@@ -47,7 +48,8 @@
class SDiagsWriter : public DiagnosticConsumer {
public:
SDiagsWriter(DiagnosticsEngine &diags, llvm::raw_ostream *os)
- : Stream(Buffer), OS(os), Diags(diags), inNonNoteDiagnostic(false)
+ : LangOpts(0), Stream(Buffer), OS(os), Diags(diags),
+ inNonNoteDiagnostic(false)
{
EmitPreamble();
};
@@ -59,6 +61,11 @@
void EndSourceFile();
+ void BeginSourceFile(const LangOptions &LO,
+ const Preprocessor *PP) {
+ LangOpts = &LO;
+ }
+
DiagnosticConsumer *clone(DiagnosticsEngine &Diags) const {
// It makes no sense to clone this.
return 0;
@@ -88,7 +95,8 @@
unsigned getEmitFile(SourceLocation Loc);
/// \brief Add SourceLocation information the specified record.
- void AddLocToRecord(SourceLocation Loc, RecordDataImpl &Record);
+ void AddLocToRecord(SourceLocation Loc, RecordDataImpl &Record,
+ unsigned TokSize = 0);
/// \brief Add CharSourceRange information the specified record.
void AddCharSourceRangeToRecord(CharSourceRange R, RecordDataImpl &Record);
@@ -96,6 +104,8 @@
/// \brief The version of the diagnostics file.
enum { Version = 1 };
+ const LangOptions *LangOpts;
+
/// \brief The byte buffer for the serialized content.
std::vector<unsigned char> Buffer;
@@ -181,13 +191,14 @@
}
void SDiagsWriter::AddLocToRecord(SourceLocation Loc,
- RecordDataImpl &Record) {
+ RecordDataImpl &Record,
+ unsigned TokSize) {
if (Loc.isInvalid()) {
// Emit a "sentinel" location.
- Record.push_back((unsigned) 0); // File.
- Record.push_back(~(unsigned)0); // Line.
- Record.push_back(~(unsigned)0); // Column.
- Record.push_back(~(unsigned)0); // Offset.
+ Record.push_back((unsigned)0); // File.
+ Record.push_back((unsigned)0); // Line.
+ Record.push_back((unsigned)0); // Column.
+ Record.push_back((unsigned)0); // Offset.
return;
}
@@ -195,7 +206,7 @@
Loc = SM.getSpellingLoc(Loc);
Record.push_back(getEmitFile(Loc));
Record.push_back(SM.getSpellingLineNumber(Loc));
- Record.push_back(SM.getSpellingColumnNumber(Loc));
+ Record.push_back(SM.getSpellingColumnNumber(Loc)+TokSize);
std::pair<FileID, unsigned> LocInfo = SM.getDecomposedLoc(Loc);
FileID FID = LocInfo.first;
@@ -206,7 +217,13 @@
void SDiagsWriter::AddCharSourceRangeToRecord(CharSourceRange Range,
RecordDataImpl &Record) {
AddLocToRecord(Range.getBegin(), Record);
- AddLocToRecord(Range.getEnd(), Record);
+ unsigned TokSize = 0;
+ if (Range.isTokenRange())
+ TokSize = Lexer::MeasureTokenLength(Range.getEnd(),
+ Diags.getSourceManager(),
+ *LangOpts);
+
+ AddLocToRecord(Range.getEnd(), Record, TokSize);
}
unsigned SDiagsWriter::getEmitFile(SourceLocation Loc) {
Modified: cfe/trunk/tools/c-index-test/c-index-test.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/c-index-test/c-index-test.c?rev=144269&r1=144268&r2=144269&view=diff
==============================================================================
--- cfe/trunk/tools/c-index-test/c-index-test.c (original)
+++ cfe/trunk/tools/c-index-test/c-index-test.c Thu Nov 10 02:43:12 2011
@@ -2431,6 +2431,155 @@
}
/******************************************************************************/
+/* Serialized diagnostics. */
+/******************************************************************************/
+
+static const char *getDiagnosticCodeStr(enum CXLoadDiag_Error error) {
+ switch (error) {
+ case CXLoadDiag_CannotLoad: return "Cannot Load File";
+ case CXLoadDiag_None: break;
+ case CXLoadDiag_Unknown: return "Unknown";
+ case CXLoadDiag_InvalidFile: return "Invalid File";
+ }
+ return "None";
+}
+
+static const char *getSeverityString(enum CXDiagnosticSeverity severity) {
+ switch (severity) {
+ case CXDiagnostic_Note: return "note";
+ case CXDiagnostic_Error: return "error";
+ case CXDiagnostic_Fatal: return "fatal";
+ case CXDiagnostic_Ignored: return "ignored";
+ case CXDiagnostic_Warning: return "warning";
+ }
+ return "unknown";
+}
+
+static void printIndent(unsigned indent) {
+ while (indent > 0) {
+ fprintf(stderr, " ");
+ --indent;
+ }
+}
+
+static void printLocation(CXSourceLocation L) {
+ CXFile File;
+ CXString FileName;
+ unsigned line, column, offset;
+
+ clang_getExpansionLocation(L, &File, &line, &column, &offset);
+ FileName = clang_getFileName(File);
+
+ fprintf(stderr, "%s:%d:%d", clang_getCString(FileName), line, column);
+ clang_disposeString(FileName);
+}
+
+static void printRanges(CXDiagnostic D, unsigned indent) {
+ unsigned i, n = clang_getDiagnosticNumRanges(D);
+
+ for (i = 0; i < n; ++i) {
+ CXSourceLocation Start, End;
+ CXSourceRange SR = clang_getDiagnosticRange(D, i);
+ Start = clang_getRangeStart(SR);
+ End = clang_getRangeEnd(SR);
+
+ printIndent(indent);
+ fprintf(stderr, "Range: ");
+ printLocation(Start);
+ fprintf(stderr, " ");
+ printLocation(End);
+ fprintf(stderr, "\n");
+ }
+}
+
+static void printFixIts(CXDiagnostic D, unsigned indent) {
+ unsigned i, n = clang_getDiagnosticNumFixIts(D);
+ for (i = 0 ; i < n; ++i) {
+ CXSourceRange ReplacementRange;
+ CXString text;
+ text = clang_getDiagnosticFixIt(D, i, &ReplacementRange);
+
+ printIndent(indent);
+ fprintf(stderr, "FIXIT: (");
+ printLocation(clang_getRangeStart(ReplacementRange));
+ fprintf(stderr, " - ");
+ printLocation(clang_getRangeEnd(ReplacementRange));
+ fprintf(stderr, "): \"%s\"\n", clang_getCString(text));
+ clang_disposeString(text);
+ }
+}
+
+static void printDiagnosticSet(CXDiagnosticSet Diags, unsigned indent) {
+ if (!Diags)
+ return;
+
+ fprintf(stderr, "\n");
+
+ unsigned i = 0;
+ unsigned n = clang_getNumDiagnosticsInSet(Diags);
+ for (i = 0; i < n; ++i) {
+ CXSourceLocation DiagLoc;
+ CXDiagnostic D;
+ CXFile File;
+ CXString FileName, DiagSpelling, DiagOption;
+ unsigned line, column, offset;
+ const char *DiagOptionStr = 0;
+
+ D = clang_getDiagnosticInSet(Diags, i);
+ DiagLoc = clang_getDiagnosticLocation(D);
+ clang_getExpansionLocation(DiagLoc, &File, &line, &column, &offset);
+ FileName = clang_getFileName(File);
+ DiagSpelling = clang_getDiagnosticSpelling(D);
+
+ printIndent(indent);
+
+ fprintf(stderr, "%s:%d:%d: %s: %s",
+ clang_getCString(FileName),
+ line,
+ column,
+ getSeverityString(clang_getDiagnosticSeverity(D)),
+ clang_getCString(DiagSpelling));
+
+ DiagOption = clang_getDiagnosticOption(D, 0);
+ DiagOptionStr = clang_getCString(DiagOption);
+ if (DiagOptionStr) {
+ fprintf(stderr, " [%s]", DiagOptionStr);
+ }
+
+ fprintf(stderr, "\n");
+
+ printRanges(D, indent);
+ printFixIts(D, indent);
+
+ // Print subdiagnostics.
+ printDiagnosticSet(clang_getChildDiagnostics(D), indent+2);
+
+ clang_disposeString(FileName);
+ clang_disposeString(DiagSpelling);
+ clang_disposeString(DiagOption);
+ }
+}
+
+static int read_diagnostics(const char *filename) {
+ enum CXLoadDiag_Error error;
+ CXString errorString;
+ CXDiagnosticSet Diags = 0;
+
+ Diags = clang_loadDiagnostics(filename, &error, &errorString);
+ if (!Diags) {
+ fprintf(stderr, "Trouble deserializing file (%s): %s\n",
+ getDiagnosticCodeStr(error),
+ clang_getCString(errorString));
+ clang_disposeString(errorString);
+ return 1;
+ }
+
+ printDiagnosticSet(Diags, 0);
+ clang_disposeDiagnosticSet(Diags);
+ return 0;
+}
+
+/******************************************************************************/
/* Command line processing. */
/******************************************************************************/
@@ -2475,7 +2624,9 @@
" c-index-test -test-print-typekind {<args>}*\n"
" c-index-test -print-usr [<CursorKind> {<args>}]*\n"
" c-index-test -print-usr-file <file>\n"
- " c-index-test -write-pch <file> <compiler arguments>\n\n");
+ " c-index-test -write-pch <file> <compiler arguments>\n");
+ fprintf(stderr,
+ " c-index-test -read-diagnostics <file>\n\n");
fprintf(stderr,
" <symbol filter> values:\n%s",
" all - load all symbols, including those from PCH\n"
@@ -2492,6 +2643,8 @@
int cindextest_main(int argc, const char **argv) {
clang_enableStackTraces();
+ if (argc > 2 && strcmp(argv[1], "-read-diagnostics") == 0)
+ return read_diagnostics(argv[2]);
if (argc > 2 && strstr(argv[1], "-code-completion-at=") == argv[1])
return perform_code_completion(argc, argv, 0);
if (argc > 2 && strstr(argv[1], "-code-completion-timing=") == argv[1])
Modified: cfe/trunk/tools/libclang/CIndex.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/CIndex.cpp?rev=144269&r1=144268&r2=144269&view=diff
==============================================================================
--- cfe/trunk/tools/libclang/CIndex.cpp (original)
+++ cfe/trunk/tools/libclang/CIndex.cpp Thu Nov 10 02:43:12 2011
@@ -58,6 +58,7 @@
CXTranslationUnit D = new CXTranslationUnitImpl();
D->TUData = TU;
D->StringPool = createCXStringPool();
+ D->Diagnostics = 0;
return D;
}
@@ -2562,6 +2563,7 @@
delete static_cast<ASTUnit *>(CTUnit->TUData);
disposeCXStringPool(CTUnit->StringPool);
+ delete static_cast<CXDiagnosticSetImpl *>(CTUnit->Diagnostics);
delete CTUnit;
}
}
@@ -2582,6 +2584,11 @@
ReparseTranslationUnitInfo *RTUI =
static_cast<ReparseTranslationUnitInfo*>(UserData);
CXTranslationUnit TU = RTUI->TU;
+
+ // Reset the associated diagnostics.
+ delete static_cast<CXDiagnosticSetImpl*>(TU->Diagnostics);
+ TU->Diagnostics = 0;
+
unsigned num_unsaved_files = RTUI->num_unsaved_files;
struct CXUnsavedFile *unsaved_files = RTUI->unsaved_files;
unsigned options = RTUI->options;
Modified: cfe/trunk/tools/libclang/CIndexDiagnostic.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/CIndexDiagnostic.cpp?rev=144269&r1=144268&r2=144269&view=diff
==============================================================================
--- cfe/trunk/tools/libclang/CIndexDiagnostic.cpp (original)
+++ cfe/trunk/tools/libclang/CIndexDiagnostic.cpp Thu Nov 10 02:43:12 2011
@@ -28,27 +28,58 @@
using namespace clang::cxstring;
using namespace llvm;
+
+CXDiagnosticSetImpl::~CXDiagnosticSetImpl() {
+ for (std::vector<CXDiagnosticImpl *>::iterator it = Diagnostics.begin(),
+ et = Diagnostics.end();
+ it != et; ++it) {
+ delete *it;
+ }
+}
+
+CXDiagnosticImpl::~CXDiagnosticImpl() {}
+
+static CXDiagnosticSetImpl *lazyCreateDiags(CXTranslationUnit TU) {
+ if (!TU->Diagnostics) {
+ ASTUnit *AU = static_cast<ASTUnit *>(TU->TUData);
+ CXDiagnosticSetImpl *Set = new CXDiagnosticSetImpl();
+ TU->Diagnostics = 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);
+ }
+ }
+ return static_cast<CXDiagnosticSetImpl*>(TU->Diagnostics);
+}
+
//-----------------------------------------------------------------------------
// C Interface Routines
//-----------------------------------------------------------------------------
extern "C" {
unsigned clang_getNumDiagnostics(CXTranslationUnit Unit) {
- ASTUnit *CXXUnit = static_cast<ASTUnit *>(Unit->TUData);
- return CXXUnit? CXXUnit->stored_diag_size() : 0;
+ if (!Unit->TUData)
+ return 0;
+ return lazyCreateDiags(Unit)->getNumDiagnostics();
}
CXDiagnostic clang_getDiagnostic(CXTranslationUnit Unit, unsigned Index) {
- ASTUnit *CXXUnit = static_cast<ASTUnit *>(Unit->TUData);
- if (!CXXUnit || Index >= CXXUnit->stored_diag_size())
+ if (!Unit->TUData)
+ return 0;
+
+ CXDiagnosticSetImpl *Diags = lazyCreateDiags(Unit);
+ if (Index >= Diags->getNumDiagnostics())
return 0;
- return new CXStoredDiagnostic(CXXUnit->stored_diag_begin()[Index],
- CXXUnit->getASTContext().getLangOptions());
+ return Diags->getDiagnostic(Index);
}
void clang_disposeDiagnostic(CXDiagnostic Diagnostic) {
- delete static_cast<CXDiagnosticImpl *>(Diagnostic);
+ // No-op. Kept as a legacy API. CXDiagnostics are now managed
+ // by the enclosing CXDiagnosticSet.
}
CXString clang_formatDiagnostic(CXDiagnostic Diagnostic, unsigned Options) {
@@ -243,4 +274,32 @@
return D->getFixIt(FixIt, ReplacementRange);
}
+void clang_disposeDiagnosticSet(CXDiagnosticSet Diags) {
+ CXDiagnosticSetImpl *D = static_cast<CXDiagnosticSetImpl*>(Diags);
+ if (D->isExternallyManaged())
+ delete D;
+}
+
+CXDiagnostic clang_getDiagnosticInSet(CXDiagnosticSet Diags,
+ unsigned Index) {
+ if (CXDiagnosticSetImpl *D = static_cast<CXDiagnosticSetImpl*>(Diags))
+ if (Index < D->getNumDiagnostics())
+ return D->getDiagnostic(Index);
+ return 0;
+}
+
+CXDiagnosticSet clang_getChildDiagnostics(CXDiagnostic Diag) {
+ if (CXDiagnosticImpl *D = static_cast<CXDiagnosticImpl *>(Diag)) {
+ CXDiagnosticSetImpl &ChildDiags = D->getChildDiagnostics();
+ return ChildDiags.empty() ? 0 : (CXDiagnosticSet) &ChildDiags;
+ }
+ return 0;
+}
+
+unsigned clang_getNumDiagnosticsInSet(CXDiagnosticSet Diags) {
+ if (CXDiagnosticSetImpl *D = static_cast<CXDiagnosticSetImpl*>(Diags))
+ return D->getNumDiagnostics();
+ return 0;
+}
+
} // end extern "C"
Modified: cfe/trunk/tools/libclang/CIndexDiagnostic.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/CIndexDiagnostic.h?rev=144269&r1=144268&r2=144269&view=diff
==============================================================================
--- cfe/trunk/tools/libclang/CIndexDiagnostic.h (original)
+++ cfe/trunk/tools/libclang/CIndexDiagnostic.h Thu Nov 10 02:43:12 2011
@@ -14,15 +14,47 @@
#define LLVM_CLANG_CINDEX_DIAGNOSTIC_H
#include "clang-c/Index.h"
+#include <vector>
+#include <assert.h>
namespace clang {
class LangOptions;
class StoredDiagnostic;
+class CXDiagnosticImpl;
+
+class CXDiagnosticSetImpl {
+ std::vector<CXDiagnosticImpl *> Diagnostics;
+ const bool IsExternallyManaged;
+public:
+ CXDiagnosticSetImpl(bool isManaged = false)
+ : IsExternallyManaged(isManaged) {}
+
+ virtual ~CXDiagnosticSetImpl();
+
+ size_t getNumDiagnostics() const {
+ return Diagnostics.size();
+ }
+
+ CXDiagnosticImpl *getDiagnostic(unsigned i) const {
+ assert(i < getNumDiagnostics());
+ return Diagnostics[i];
+ }
+
+ void appendDiagnostic(CXDiagnosticImpl *D) {
+ Diagnostics.push_back(D);
+ }
+
+ bool empty() const {
+ return Diagnostics.empty();
+ }
+
+ bool isExternallyManaged() const { return IsExternallyManaged; }
+};
class CXDiagnosticImpl {
public:
- enum Kind { StoredDiagnosticKind, SerializedDiagnosticKind };
+ enum Kind { StoredDiagnosticKind, LoadedDiagnosticKind };
virtual ~CXDiagnosticImpl();
@@ -55,9 +87,18 @@
CXSourceRange *ReplacementRange) const = 0;
Kind getKind() const { return K; }
-
+
+ CXDiagnosticSetImpl &getChildDiagnostics() {
+ return ChildDiags;
+ }
+
protected:
CXDiagnosticImpl(Kind k) : K(k) {}
+ CXDiagnosticSetImpl ChildDiags;
+
+ void append(CXDiagnosticImpl *D) {
+ ChildDiags.appendDiagnostic(D);
+ }
private:
Kind K;
Modified: cfe/trunk/tools/libclang/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/CMakeLists.txt?rev=144269&r1=144268&r2=144269&view=diff
==============================================================================
--- cfe/trunk/tools/libclang/CMakeLists.txt (original)
+++ cfe/trunk/tools/libclang/CMakeLists.txt Thu Nov 10 02:43:12 2011
@@ -29,6 +29,8 @@
CIndexer.h
CXCursor.cpp
CXCursor.h
+ CXLoadedDiagnostic.cpp
+ CXLoadedDiagnostic.h
CXSourceLocation.cpp
CXSourceLocation.h
CXStoredDiagnostic.cpp
Added: cfe/trunk/tools/libclang/CXLoadedDiagnostic.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/CXLoadedDiagnostic.cpp?rev=144269&view=auto
==============================================================================
--- cfe/trunk/tools/libclang/CXLoadedDiagnostic.cpp (added)
+++ cfe/trunk/tools/libclang/CXLoadedDiagnostic.cpp Thu Nov 10 02:43:12 2011
@@ -0,0 +1,655 @@
+/*===-- CXLoadedDiagnostic.cpp - Handling of persisent diags -*- C++ -*-===*\
+|* *|
+|* The LLVM Compiler Infrastructure *|
+|* *|
+|* This file is distributed under the University of Illinois Open Source *|
+|* License. See LICENSE.TXT for details. *|
+|* *|
+|*===----------------------------------------------------------------------===*|
+|* *|
+|* Implements handling of persisent diagnostics. *|
+|* *|
+\*===----------------------------------------------------------------------===*/
+
+#include "CXLoadedDiagnostic.h"
+#include "CXString.h"
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/FileManager.h"
+#include "clang/Frontend/SerializedDiagnosticPrinter.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/Twine.h"
+#include "llvm/ADT/Optional.h"
+#include "clang/Basic/LLVM.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Bitcode/BitstreamReader.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include <assert.h>
+
+using namespace clang;
+using namespace clang::cxstring;
+
+//===----------------------------------------------------------------------===//
+// Extend CXDiagnosticSetImpl which contains strings for diagnostics.
+//===----------------------------------------------------------------------===//
+
+typedef llvm::DenseMap<unsigned, llvm::StringRef> Strings;
+
+namespace {
+class CXLoadedDiagnosticSetImpl : public CXDiagnosticSetImpl {
+public:
+ CXLoadedDiagnosticSetImpl() : CXDiagnosticSetImpl(true), FakeFiles(FO) {}
+ virtual ~CXLoadedDiagnosticSetImpl() {}
+
+ llvm::StringRef makeString(const char *blob, unsigned blobLen);
+
+ llvm::BumpPtrAllocator Alloc;
+ Strings Categories;
+ Strings WarningFlags;
+ Strings FileNames;
+
+ FileSystemOptions FO;
+ FileManager FakeFiles;
+ llvm::DenseMap<unsigned, const FileEntry *> Files;
+};
+}
+
+llvm::StringRef CXLoadedDiagnosticSetImpl::makeString(const char *blob,
+ unsigned bloblen) {
+ char *mem = Alloc.Allocate<char>(bloblen);
+ memcpy(mem, blob, bloblen);
+ return llvm::StringRef(mem, bloblen);
+}
+
+//===----------------------------------------------------------------------===//
+// Cleanup.
+//===----------------------------------------------------------------------===//
+
+CXLoadedDiagnostic::~CXLoadedDiagnostic() {}
+
+//===----------------------------------------------------------------------===//
+// Public CXLoadedDiagnostic methods.
+//===----------------------------------------------------------------------===//
+
+CXDiagnosticSeverity CXLoadedDiagnostic::getSeverity() const {
+ // FIXME: possibly refactor with logic in CXStoredDiagnostic.
+ switch (severity) {
+ case DiagnosticsEngine::Ignored: return CXDiagnostic_Ignored;
+ case DiagnosticsEngine::Note: return CXDiagnostic_Note;
+ case DiagnosticsEngine::Warning: return CXDiagnostic_Warning;
+ case DiagnosticsEngine::Error: return CXDiagnostic_Error;
+ case DiagnosticsEngine::Fatal: return CXDiagnostic_Fatal;
+ }
+
+ llvm_unreachable("Invalid diagnostic level");
+ return CXDiagnostic_Ignored;
+}
+
+static CXSourceLocation makeLocation(const CXLoadedDiagnostic::Location *DLoc) {
+ // The lowest bit of ptr_data[0] is always set to 1 to indicate this
+ // is a persistent diagnostic.
+ uintptr_t V = (uintptr_t) DLoc;
+ V |= 0x1;
+ CXSourceLocation Loc = { { (void*) V, 0 }, 0 };
+ return Loc;
+}
+
+CXSourceLocation CXLoadedDiagnostic::getLocation() const {
+ // The lowest bit of ptr_data[0] is always set to 1 to indicate this
+ // is a persistent diagnostic.
+ return makeLocation(&DiagLoc);
+}
+
+CXString CXLoadedDiagnostic::getSpelling() const {
+ return cxstring::createCXString(Spelling, false);
+}
+
+CXString CXLoadedDiagnostic::getDiagnosticOption(CXString *Disable) const {
+ if (DiagOption.empty())
+ return createCXString("");
+
+ // FIXME: possibly refactor with logic in CXStoredDiagnostic.
+ if (Disable)
+ *Disable = createCXString((Twine("-Wno-") + DiagOption).str());
+ return createCXString((Twine("-W") + DiagOption).str());
+}
+
+unsigned CXLoadedDiagnostic::getCategory() const {
+ return category;
+}
+
+unsigned CXLoadedDiagnostic::getNumRanges() const {
+ return Ranges.size();
+}
+
+CXSourceRange CXLoadedDiagnostic::getRange(unsigned Range) const {
+ assert(Range < Ranges.size());
+ return Ranges[Range];
+}
+
+unsigned CXLoadedDiagnostic::getNumFixIts() const {
+ return FixIts.size();
+}
+
+CXString CXLoadedDiagnostic::getFixIt(unsigned FixIt,
+ CXSourceRange *ReplacementRange) const {
+ assert(FixIt < FixIts.size());
+ if (ReplacementRange)
+ *ReplacementRange = FixIts[FixIt].first;
+ return FixIts[FixIt].second;
+}
+
+void CXLoadedDiagnostic::decodeLocation(CXSourceLocation location,
+ CXFile *file,
+ unsigned int *line,
+ unsigned int *column,
+ unsigned int *offset) {
+
+
+ // CXSourceLocation consists of the following fields:
+ //
+ // void *ptr_data[2];
+ // unsigned int_data;
+ //
+ // The lowest bit of ptr_data[0] is always set to 1 to indicate this
+ // is a persistent diagnostic.
+ //
+ // For now, do the unoptimized approach and store the data in a side
+ // data structure. We can optimize this case later.
+
+ uintptr_t V = (uintptr_t) location.ptr_data[0];
+ assert((V & 0x1) == 1);
+ V &= ~(uintptr_t)1;
+
+ const Location &Loc = *((Location*)V);
+
+ if (file)
+ *file = Loc.file;
+ if (line)
+ *line = Loc.line;
+ if (column)
+ *column = Loc.column;
+ if (offset)
+ *offset = Loc.offset;
+}
+
+//===----------------------------------------------------------------------===//
+// Deserialize diagnostics.
+//===----------------------------------------------------------------------===//
+
+enum { MaxSupportedVersion = 1 };
+typedef SmallVector<uint64_t, 64> RecordData;
+enum LoadResult { Failure = 1, Success = 0 };
+enum StreamResult { Read_EndOfStream,
+ Read_BlockBegin,
+ Read_Failure,
+ Read_Record,
+ Read_BlockEnd };
+
+namespace {
+class DiagLoader {
+ enum CXLoadDiag_Error *error;
+ CXString *errorString;
+
+ void reportBad(enum CXLoadDiag_Error code, llvm::StringRef err) {
+ if (error)
+ *error = code;
+ if (errorString)
+ *errorString = createCXString(err);
+ }
+
+ void reportInvalidFile(llvm::StringRef err) {
+ return reportBad(CXLoadDiag_InvalidFile, err);
+ }
+
+ LoadResult readMetaBlock(llvm::BitstreamCursor &Stream);
+
+ LoadResult readDiagnosticBlock(llvm::BitstreamCursor &Stream,
+ CXDiagnosticSetImpl &Diags,
+ CXLoadedDiagnosticSetImpl &TopDiags);
+
+ StreamResult readToNextRecordOrBlock(llvm::BitstreamCursor &Stream,
+ llvm::StringRef errorContext,
+ unsigned &BlockOrRecordID,
+ const bool atTopLevel = false);
+
+
+ LoadResult readString(CXLoadedDiagnosticSetImpl &TopDiags,
+ Strings &strings, llvm::StringRef errorContext,
+ RecordData &Record,
+ const char *BlobStart,
+ unsigned BlobLen);
+
+ LoadResult readString(CXLoadedDiagnosticSetImpl &TopDiags,
+ llvm::StringRef &RetStr,
+ llvm::StringRef errorContext,
+ RecordData &Record,
+ const char *BlobStart,
+ unsigned BlobLen);
+
+ LoadResult readRange(CXLoadedDiagnosticSetImpl &TopDiags,
+ RecordData &Record, unsigned RecStartIdx,
+ CXSourceRange &SR);
+
+ LoadResult readLocation(CXLoadedDiagnosticSetImpl &TopDiags,
+ RecordData &Record, unsigned &offset,
+ CXLoadedDiagnostic::Location &Loc);
+
+public:
+ DiagLoader(enum CXLoadDiag_Error *e, CXString *es)
+ : error(e), errorString(es) {
+ if (error)
+ *error = CXLoadDiag_None;
+ if (errorString)
+ *errorString = createCXString("");
+ }
+
+ CXDiagnosticSet load(const char *file);
+};
+}
+
+CXDiagnosticSet DiagLoader::load(const char *file) {
+ // Open the diagnostics file.
+ std::string ErrStr;
+ FileSystemOptions FO;
+ FileManager FileMgr(FO);
+
+ llvm::OwningPtr<llvm::MemoryBuffer> Buffer;
+ Buffer.reset(FileMgr.getBufferForFile(file));
+
+ if (!Buffer) {
+ reportBad(CXLoadDiag_CannotLoad, ErrStr);
+ return 0;
+ }
+
+ llvm::BitstreamReader StreamFile;
+ StreamFile.init((const unsigned char *)Buffer->getBufferStart(),
+ (const unsigned char *)Buffer->getBufferEnd());
+
+ llvm::BitstreamCursor Stream;
+ Stream.init(StreamFile);
+
+ // Sniff for the signature.
+ if (Stream.Read(8) != 'D' ||
+ Stream.Read(8) != 'I' ||
+ Stream.Read(8) != 'A' ||
+ Stream.Read(8) != 'G') {
+ reportBad(CXLoadDiag_InvalidFile,
+ "Bad header in diagnostics file");
+ return 0;
+ }
+
+ llvm::OwningPtr<CXLoadedDiagnosticSetImpl>
+ Diags(new CXLoadedDiagnosticSetImpl());
+
+ while (true) {
+ unsigned BlockID = 0;
+ StreamResult Res = readToNextRecordOrBlock(Stream, "Top-level",
+ BlockID, true);
+ switch (Res) {
+ case Read_EndOfStream:
+ return (CXDiagnosticSet) Diags.take();
+ case Read_Failure:
+ return 0;
+ case Read_Record:
+ llvm_unreachable("Top-level does not have records");
+ return 0;
+ case Read_BlockEnd:
+ continue;
+ case Read_BlockBegin:
+ break;
+ }
+
+ switch (BlockID) {
+ case serialized_diags::BLOCK_META:
+ if (readMetaBlock(Stream))
+ return 0;
+ break;
+ case serialized_diags::BLOCK_DIAG:
+ if (readDiagnosticBlock(Stream, *Diags.get(), *Diags.get()))
+ return 0;
+ break;
+ default:
+ if (!Stream.SkipBlock()) {
+ reportInvalidFile("Malformed block at top-level of diagnostics file");
+ return 0;
+ }
+ break;
+ }
+ }
+}
+
+StreamResult DiagLoader::readToNextRecordOrBlock(llvm::BitstreamCursor &Stream,
+ llvm::StringRef errorContext,
+ unsigned &blockOrRecordID,
+ const bool atTopLevel) {
+
+ blockOrRecordID = 0;
+
+ while (!Stream.AtEndOfStream()) {
+ unsigned Code = Stream.ReadCode();
+
+ // Handle the top-level specially.
+ if (atTopLevel) {
+ if (Code == llvm::bitc::ENTER_SUBBLOCK) {
+ unsigned BlockID = Stream.ReadSubBlockID();
+ if (BlockID == llvm::bitc::BLOCKINFO_BLOCK_ID) {
+ if (Stream.ReadBlockInfoBlock()) {
+ reportInvalidFile("Malformed BlockInfoBlock in diagnostics file");
+ return Read_Failure;
+ }
+ continue;
+ }
+ blockOrRecordID = BlockID;
+ return Read_BlockBegin;
+ }
+ reportInvalidFile("Only blocks can appear at the top of a "
+ "diagnostic file");
+ return Read_Failure;
+ }
+
+ switch ((llvm::bitc::FixedAbbrevIDs)Code) {
+ case llvm::bitc::ENTER_SUBBLOCK:
+ blockOrRecordID = Stream.ReadSubBlockID();
+ return Read_BlockBegin;
+
+ case llvm::bitc::END_BLOCK:
+ if (Stream.ReadBlockEnd()) {
+ reportInvalidFile("Cannot read end of block");
+ return Read_Failure;
+ }
+ return Read_BlockEnd;
+
+ case llvm::bitc::DEFINE_ABBREV:
+ Stream.ReadAbbrevRecord();
+ continue;
+
+ case llvm::bitc::UNABBREV_RECORD:
+ reportInvalidFile("Diagnostics file should have no unabbreviated "
+ "records");
+ return Read_Failure;
+
+ default:
+ // We found a record.
+ blockOrRecordID = Code;
+ return Read_Record;
+ }
+ }
+
+ if (atTopLevel)
+ return Read_EndOfStream;
+
+ reportInvalidFile(Twine("Premature end of diagnostics file within ").str() +
+ errorContext.str());
+ return Read_Failure;
+}
+
+LoadResult DiagLoader::readMetaBlock(llvm::BitstreamCursor &Stream) {
+ if (Stream.EnterSubBlock(clang::serialized_diags::BLOCK_META)) {
+ reportInvalidFile("Malformed metadata block");
+ return Failure;
+ }
+
+ bool versionChecked = false;
+
+ while (true) {
+ unsigned blockOrCode = 0;
+ StreamResult Res = readToNextRecordOrBlock(Stream, "Metadata Block",
+ blockOrCode);
+
+ switch(Res) {
+ case Read_EndOfStream:
+ llvm_unreachable("EndOfStream handled by readToNextRecordOrBlock");
+ case Read_Failure:
+ return Failure;
+ case Read_Record:
+ break;
+ case Read_BlockBegin:
+ if (Stream.SkipBlock()) {
+ reportInvalidFile("Malformed metadata block");
+ return Failure;
+ }
+ case Read_BlockEnd:
+ if (!versionChecked) {
+ reportInvalidFile("Diagnostics file does not contain version"
+ " information");
+ return Failure;
+ }
+ return Success;
+ }
+
+ RecordData Record;
+ const char *Blob;
+ unsigned BlobLen;
+ unsigned recordID = Stream.ReadRecord(blockOrCode, Record, &Blob, &BlobLen);
+
+ if (recordID == serialized_diags::RECORD_VERSION) {
+ if (Record.size() < 1) {
+ reportInvalidFile("malformed VERSION identifier in diagnostics file");
+ return Failure;
+ }
+ if (Record[0] > MaxSupportedVersion) {
+ reportInvalidFile("diagnosics file is a newer version than the one "
+ "supported");
+ return Failure;
+ }
+ versionChecked = true;
+ }
+ }
+}
+
+LoadResult DiagLoader::readString(CXLoadedDiagnosticSetImpl &TopDiags,
+ llvm::StringRef &RetStr,
+ llvm::StringRef errorContext,
+ RecordData &Record,
+ const char *BlobStart,
+ unsigned BlobLen) {
+
+ // Basic buffer overflow check.
+ if (BlobLen > 65536) {
+ reportInvalidFile(std::string("Out-of-bounds string in ") +
+ std::string(errorContext));
+ return Failure;
+ }
+
+ if (Record.size() < 1 || BlobLen == 0) {
+ reportInvalidFile(std::string("Corrupted ") + std::string(errorContext)
+ + std::string(" entry"));
+ return Failure;
+ }
+
+ RetStr = TopDiags.makeString(BlobStart, BlobLen);
+ return Success;
+}
+
+LoadResult DiagLoader::readString(CXLoadedDiagnosticSetImpl &TopDiags,
+ Strings &strings,
+ llvm::StringRef errorContext,
+ RecordData &Record,
+ const char *BlobStart,
+ unsigned BlobLen) {
+ llvm::StringRef RetStr;
+ if (readString(TopDiags, RetStr, errorContext, Record, BlobStart, BlobLen))
+ return Failure;
+ strings[Record[0]] = RetStr;
+ return Success;
+}
+
+LoadResult DiagLoader::readLocation(CXLoadedDiagnosticSetImpl &TopDiags,
+ RecordData &Record, unsigned &offset,
+ CXLoadedDiagnostic::Location &Loc) {
+ if (Record.size() < offset + 3) {
+ reportInvalidFile("Corrupted source location");
+ return Failure;
+ }
+
+ unsigned fileID = Record[offset++];
+ if (fileID == 0) {
+ // Sentinel value.
+ Loc.file = 0;
+ Loc.line = 0;
+ Loc.column = 0;
+ Loc.offset = 0;
+ return Success;
+ }
+
+ const FileEntry *FE = TopDiags.Files[fileID];
+ if (!FE) {
+ reportInvalidFile("Corrupted file entry in source location");
+ return Failure;
+ }
+ Loc.file = (void*) FE;
+ Loc.line = Record[offset++];
+ Loc.column = Record[offset++];
+ Loc.offset = Record[offset++];
+ return Success;
+}
+
+LoadResult DiagLoader::readRange(CXLoadedDiagnosticSetImpl &TopDiags,
+ RecordData &Record,
+ unsigned int RecStartIdx,
+ CXSourceRange &SR) {
+ CXLoadedDiagnostic::Location *Start, *End;
+ Start = TopDiags.Alloc.Allocate<CXLoadedDiagnostic::Location>();
+ End = TopDiags.Alloc.Allocate<CXLoadedDiagnostic::Location>();
+
+ if (readLocation(TopDiags, Record, RecStartIdx, *Start))
+ return Failure;
+ if (readLocation(TopDiags, Record, RecStartIdx, *End))
+ return Failure;
+
+ CXSourceLocation startLoc = makeLocation(Start);
+ CXSourceLocation endLoc = makeLocation(End);
+ SR = clang_getRange(startLoc, endLoc);
+ return Success;
+}
+
+LoadResult DiagLoader::readDiagnosticBlock(llvm::BitstreamCursor &Stream,
+ CXDiagnosticSetImpl &Diags,
+ CXLoadedDiagnosticSetImpl &TopDiags){
+
+ if (Stream.EnterSubBlock(clang::serialized_diags::BLOCK_DIAG)) {
+ reportInvalidFile("malformed diagnostic block");
+ return Failure;
+ }
+
+ llvm::OwningPtr<CXLoadedDiagnostic> D(new CXLoadedDiagnostic());
+ RecordData Record;
+
+ while (true) {
+ unsigned blockOrCode = 0;
+ StreamResult Res = readToNextRecordOrBlock(Stream, "Diagnostic Block",
+ blockOrCode);
+ switch (Res) {
+ case Read_EndOfStream:
+ llvm_unreachable("EndOfStream handled in readToNextRecordOrBlock");
+ return Failure;
+ case Read_Failure:
+ return Failure;
+ case Read_BlockBegin: {
+ // The only blocks we care about are subdiagnostics.
+ if (blockOrCode != serialized_diags::BLOCK_DIAG) {
+ if (!Stream.SkipBlock()) {
+ reportInvalidFile("Invalid subblock in Diagnostics block");
+ return Failure;
+ }
+ } else if (readDiagnosticBlock(Stream, D->getChildDiagnostics(),
+ TopDiags)) {
+ return Failure;
+ }
+
+ continue;
+ }
+ case Read_BlockEnd:
+ Diags.appendDiagnostic(D.take());
+ return Success;
+ case Read_Record:
+ break;
+ }
+
+ // Read the record.
+ Record.clear();
+ const char *BlobStart = 0;
+ unsigned BlobLen = 0;
+ unsigned recID = Stream.ReadRecord(blockOrCode, Record,
+ BlobStart, BlobLen);
+
+ if (recID < serialized_diags::RECORD_FIRST ||
+ recID > serialized_diags::RECORD_LAST)
+ continue;
+
+ switch ((serialized_diags::RecordIDs)recID) {
+ case serialized_diags::RECORD_VERSION:
+ continue;
+ case serialized_diags::RECORD_CATEGORY:
+ if (readString(TopDiags, TopDiags.Categories, "category", Record,
+ BlobStart, BlobLen))
+ return Failure;
+ continue;
+
+ case serialized_diags::RECORD_DIAG_FLAG:
+ if (readString(TopDiags, TopDiags.WarningFlags, "warning flag", Record,
+ BlobStart, BlobLen))
+ return Failure;
+ continue;
+
+ case serialized_diags::RECORD_FILENAME: {
+ if (readString(TopDiags, TopDiags.FileNames, "filename", Record,
+ BlobStart, BlobLen))
+ return Failure;
+
+ if (Record.size() < 3) {
+ reportInvalidFile("Invalid file entry");
+ return Failure;
+ }
+
+ const FileEntry *FE =
+ TopDiags.FakeFiles.getVirtualFile(TopDiags.FileNames[Record[0]],
+ /* size */ Record[1],
+ /* time */ Record[2]);
+
+ TopDiags.Files[Record[0]] = FE;
+ continue;
+ }
+
+ case serialized_diags::RECORD_SOURCE_RANGE: {
+ CXSourceRange SR;
+ if (readRange(TopDiags, Record, 0, SR))
+ return Failure;
+ D->Ranges.push_back(SR);
+ continue;
+ }
+
+ case serialized_diags::RECORD_FIXIT: {
+ CXSourceRange SR;
+ if (readRange(TopDiags, Record, 0, SR))
+ return Failure;
+ llvm::StringRef RetStr;
+ if (readString(TopDiags, RetStr, "FIXIT", Record, BlobStart, BlobLen))
+ return Failure;
+ D->FixIts.push_back(std::make_pair(SR, createCXString(RetStr, false)));
+ continue;
+ }
+
+ case serialized_diags::RECORD_DIAG: {
+ D->severity = Record[0];
+ unsigned offset = 1;
+ if (readLocation(TopDiags, Record, offset, D->DiagLoc))
+ return Failure;
+ D->category = Record[offset++];
+ unsigned diagFlag = Record[offset++];
+ D->DiagOption = diagFlag ? TopDiags.WarningFlags[diagFlag] : "";
+ D->Spelling = TopDiags.makeString(BlobStart, BlobLen);
+ continue;
+ }
+ }
+ }
+}
+
+extern "C" {
+CXDiagnosticSet clang_loadDiagnostics(const char *file,
+ enum CXLoadDiag_Error *error,
+ CXString *errorString) {
+ DiagLoader L(error, errorString);
+ return L.load(file);
+}
+} // end extern 'C'.
Added: cfe/trunk/tools/libclang/CXLoadedDiagnostic.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/CXLoadedDiagnostic.h?rev=144269&view=auto
==============================================================================
--- cfe/trunk/tools/libclang/CXLoadedDiagnostic.h (added)
+++ cfe/trunk/tools/libclang/CXLoadedDiagnostic.h Thu Nov 10 02:43:12 2011
@@ -0,0 +1,90 @@
+/*===-- CXLoadedDiagnostic.h - Handling of persisent diags ------*- C++ -*-===*\
+|* *|
+|* The LLVM Compiler Infrastructure *|
+|* *|
+|* This file is distributed under the University of Illinois Open Source *|
+|* License. See LICENSE.TXT for details. *|
+|* *|
+|*===----------------------------------------------------------------------===*|
+|* *|
+|* Implements handling of persisent diagnostics. *|
+|* *|
+\*===----------------------------------------------------------------------===*/
+
+#ifndef LLVM_CLANG_CINDEX_LOADED_DIAGNOSTIC_H
+#define LLVM_CLANG_CINDEX_LOADED_DIAGNOSTIC_H
+
+#include "CIndexDiagnostic.h"
+#include "llvm/ADT/StringRef.h"
+#include "clang/Basic/LLVM.h"
+#include <string>
+#include <vector>
+
+namespace clang {
+class CXLoadedDiagnostic : public CXDiagnosticImpl {
+public:
+ CXLoadedDiagnostic() : CXDiagnosticImpl(LoadedDiagnosticKind),
+ severity(0), category(0) {}
+
+ virtual ~CXLoadedDiagnostic();
+
+ /// \brief Return the severity of the diagnostic.
+ virtual CXDiagnosticSeverity getSeverity() const;
+
+ /// \brief Return the location of the diagnostic.
+ virtual CXSourceLocation getLocation() const;
+
+ /// \brief Return the spelling of the diagnostic.
+ virtual CXString getSpelling() const;
+
+ /// \brief Return the text for the diagnostic option.
+ virtual CXString getDiagnosticOption(CXString *Disable) const;
+
+ /// \brief Return the category of the diagnostic.
+ virtual unsigned getCategory() const;
+
+ /// \brief Return the number of source ranges for the diagnostic.
+ virtual unsigned getNumRanges() const;
+
+ /// \brief Return the source ranges for the diagnostic.
+ virtual CXSourceRange getRange(unsigned Range) const;
+
+ /// \brief Return the number of FixIts.
+ virtual unsigned getNumFixIts() const;
+
+ /// \brief Return the FixIt information (source range and inserted text).
+ virtual CXString getFixIt(unsigned FixIt,
+ CXSourceRange *ReplacementRange) const;
+
+ static bool classof(const CXDiagnosticImpl *D) {
+ return D->getKind() == LoadedDiagnosticKind;
+ }
+
+ /// \brief Decode the CXSourceLocation into file, line, column, and offset.
+ static void decodeLocation(CXSourceLocation location,
+ CXFile *file,
+ unsigned *line,
+ unsigned *column,
+ unsigned *offset);
+
+ struct Location {
+ CXFile file;
+ unsigned line;
+ unsigned column;
+ unsigned offset;
+
+ Location() : line(0), column(0), offset(0) {}
+ };
+
+ Location DiagLoc;
+
+ std::vector<CXSourceRange> Ranges;
+ std::vector<std::pair<CXSourceRange, CXString> > FixIts;
+ llvm::StringRef Spelling;
+ llvm::StringRef DiagOption;
+ unsigned severity;
+ unsigned category;
+};
+}
+
+#endif
Modified: cfe/trunk/tools/libclang/CXSourceLocation.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/CXSourceLocation.cpp?rev=144269&r1=144268&r2=144269&view=diff
==============================================================================
--- cfe/trunk/tools/libclang/CXSourceLocation.cpp (original)
+++ cfe/trunk/tools/libclang/CXSourceLocation.cpp Thu Nov 10 02:43:12 2011
@@ -17,6 +17,7 @@
#include "CXString.h"
#include "CXSourceLocation.h"
#include "CXTranslationUnit.h"
+#include "CXLoadedDiagnostic.h"
using namespace clang;
using namespace clang::cxstring;
@@ -54,6 +55,13 @@
}
CXSourceRange clang_getRange(CXSourceLocation begin, CXSourceLocation end) {
+ if (!isASTUnitSourceLocation(begin)) {
+ if (isASTUnitSourceLocation(end))
+ return clang_getNullRange();
+ CXSourceRange Result = { { begin.ptr_data[0], end.ptr_data[0] }, 0, 0 };
+ return Result;
+ }
+
if (begin.ptr_data[0] != end.ptr_data[0] ||
begin.ptr_data[1] != end.ptr_data[1])
return clang_getNullRange();
@@ -64,7 +72,6 @@
return Result;
}
-
unsigned clang_equalRanges(CXSourceRange range1, CXSourceRange range2) {
return range1.ptr_data[0] == range2.ptr_data[0]
&& range1.ptr_data[1] == range2.ptr_data[1]
@@ -78,12 +85,24 @@
CXSourceLocation clang_getRangeStart(CXSourceRange range) {
+ // Special decoding for CXSourceLocations for CXLoadedDiagnostics.
+ if ((uintptr_t)range.ptr_data[0] & 0x1) {
+ CXSourceLocation Result = { { range.ptr_data[0], 0 }, 0 };
+ return Result;
+ }
+
CXSourceLocation Result = { { range.ptr_data[0], range.ptr_data[1] },
range.begin_int_data };
return Result;
}
CXSourceLocation clang_getRangeEnd(CXSourceRange range) {
+ // Special decoding for CXSourceLocations for CXLoadedDiagnostics.
+ if ((uintptr_t)range.ptr_data[0] & 0x1) {
+ CXSourceLocation Result = { { range.ptr_data[1], 0 }, 0 };
+ return Result;
+ }
+
CXSourceLocation Result = { { range.ptr_data[0], range.ptr_data[1] },
range.end_int_data };
return Result;
@@ -182,41 +201,40 @@
unsigned *column,
unsigned *offset) {
- if (isASTUnitSourceLocation(location)) {
- SourceLocation Loc = SourceLocation::getFromRawEncoding(location.int_data);
-
- if (!location.ptr_data[0] || Loc.isInvalid()) {
- createNullLocation(file, line, column, offset);
- return;
- }
-
- const SourceManager &SM =
- *static_cast<const SourceManager*>(location.ptr_data[0]);
- SourceLocation ExpansionLoc = SM.getExpansionLoc(Loc);
-
- // Check that the FileID is invalid on the expansion location.
- // This can manifest in invalid code.
- FileID fileID = SM.getFileID(ExpansionLoc);
- bool Invalid = false;
- const SrcMgr::SLocEntry &sloc = SM.getSLocEntry(fileID, &Invalid);
- if (Invalid || !sloc.isFile()) {
- createNullLocation(file, line, column, offset);
- return;
- }
-
- if (file)
- *file = (void *)SM.getFileEntryForSLocEntry(sloc);
- if (line)
- *line = SM.getExpansionLineNumber(ExpansionLoc);
- if (column)
- *column = SM.getExpansionColumnNumber(ExpansionLoc);
- if (offset)
- *offset = SM.getDecomposedLoc(ExpansionLoc).second;
+ if (!isASTUnitSourceLocation(location)) {
+ CXLoadedDiagnostic::decodeLocation(location, file, line, column, offset);
+ return;
+ }
+
+ SourceLocation Loc = SourceLocation::getFromRawEncoding(location.int_data);
+
+ if (!location.ptr_data[0] || Loc.isInvalid()) {
+ createNullLocation(file, line, column, offset);
+ return;
+ }
+
+ const SourceManager &SM =
+ *static_cast<const SourceManager*>(location.ptr_data[0]);
+ SourceLocation ExpansionLoc = SM.getExpansionLoc(Loc);
+
+ // Check that the FileID is invalid on the expansion location.
+ // This can manifest in invalid code.
+ FileID fileID = SM.getFileID(ExpansionLoc);
+ bool Invalid = false;
+ const SrcMgr::SLocEntry &sloc = SM.getSLocEntry(fileID, &Invalid);
+ if (Invalid || !sloc.isFile()) {
+ createNullLocation(file, line, column, offset);
return;
}
- // FIXME:
- createNullLocation(file, line, column, offset);
+ if (file)
+ *file = (void *)SM.getFileEntryForSLocEntry(sloc);
+ if (line)
+ *line = SM.getExpansionLineNumber(ExpansionLoc);
+ if (column)
+ *column = SM.getExpansionColumnNumber(ExpansionLoc);
+ if (offset)
+ *offset = SM.getDecomposedLoc(ExpansionLoc).second;
}
void clang_getPresumedLocation(CXSourceLocation location,
@@ -224,28 +242,29 @@
unsigned *line,
unsigned *column) {
- if (isASTUnitSourceLocation(location)) {
- SourceLocation Loc = SourceLocation::getFromRawEncoding(location.int_data);
-
- if (!location.ptr_data[0] || Loc.isInvalid())
- createNullLocation(filename, line, column);
- else {
- const SourceManager &SM =
- *static_cast<const SourceManager*>(location.ptr_data[0]);
- PresumedLoc PreLoc = SM.getPresumedLoc(Loc);
-
- if (filename)
- *filename = createCXString(PreLoc.getFilename());
- if (line)
- *line = PreLoc.getLine();
- if (column)
- *column = PreLoc.getColumn();
- }
+ if (!isASTUnitSourceLocation(location)) {
+ // Other SourceLocation implementations do not support presumed locations
+ // at this time.
+ createNullLocation(filename, line, column);
return;
}
-
- // FIXME:
- createNullLocation(filename, line, column);
+
+ SourceLocation Loc = SourceLocation::getFromRawEncoding(location.int_data);
+
+ if (!location.ptr_data[0] || Loc.isInvalid())
+ createNullLocation(filename, line, column);
+ else {
+ const SourceManager &SM =
+ *static_cast<const SourceManager*>(location.ptr_data[0]);
+ PresumedLoc PreLoc = SM.getPresumedLoc(Loc);
+
+ if (filename)
+ *filename = createCXString(PreLoc.getFilename());
+ if (line)
+ *line = PreLoc.getLine();
+ if (column)
+ *column = PreLoc.getColumn();
+ }
}
void clang_getInstantiationLocation(CXSourceLocation location,
@@ -263,44 +282,44 @@
unsigned *column,
unsigned *offset) {
- if (isASTUnitSourceLocation(location)) {
- SourceLocation Loc = SourceLocation::getFromRawEncoding(location.int_data);
-
- if (!location.ptr_data[0] || Loc.isInvalid())
- return createNullLocation(file, line, column, offset);
-
- const SourceManager &SM =
- *static_cast<const SourceManager*>(location.ptr_data[0]);
- SourceLocation SpellLoc = Loc;
- if (SpellLoc.isMacroID()) {
- SourceLocation SimpleSpellingLoc = SM.getImmediateSpellingLoc(SpellLoc);
- if (SimpleSpellingLoc.isFileID() &&
- SM.getFileEntryForID(SM.getDecomposedLoc(SimpleSpellingLoc).first))
- SpellLoc = SimpleSpellingLoc;
- else
- SpellLoc = SM.getExpansionLoc(SpellLoc);
- }
-
- std::pair<FileID, unsigned> LocInfo = SM.getDecomposedLoc(SpellLoc);
- FileID FID = LocInfo.first;
- unsigned FileOffset = LocInfo.second;
-
- if (FID.isInvalid())
- return createNullLocation(file, line, column, offset);
-
- if (file)
- *file = (void *)SM.getFileEntryForID(FID);
- if (line)
- *line = SM.getLineNumber(FID, FileOffset);
- if (column)
- *column = SM.getColumnNumber(FID, FileOffset);
- if (offset)
- *offset = FileOffset;
+ if (!isASTUnitSourceLocation(location)) {
+ CXLoadedDiagnostic::decodeLocation(location, file, line,
+ column, offset);
return;
}
-
- // FIXME:
- createNullLocation(file, line, column, offset);
+
+ SourceLocation Loc = SourceLocation::getFromRawEncoding(location.int_data);
+
+ if (!location.ptr_data[0] || Loc.isInvalid())
+ return createNullLocation(file, line, column, offset);
+
+ const SourceManager &SM =
+ *static_cast<const SourceManager*>(location.ptr_data[0]);
+ SourceLocation SpellLoc = Loc;
+ if (SpellLoc.isMacroID()) {
+ SourceLocation SimpleSpellingLoc = SM.getImmediateSpellingLoc(SpellLoc);
+ if (SimpleSpellingLoc.isFileID() &&
+ SM.getFileEntryForID(SM.getDecomposedLoc(SimpleSpellingLoc).first))
+ SpellLoc = SimpleSpellingLoc;
+ else
+ SpellLoc = SM.getExpansionLoc(SpellLoc);
+ }
+
+ std::pair<FileID, unsigned> LocInfo = SM.getDecomposedLoc(SpellLoc);
+ FileID FID = LocInfo.first;
+ unsigned FileOffset = LocInfo.second;
+
+ if (FID.isInvalid())
+ return createNullLocation(file, line, column, offset);
+
+ if (file)
+ *file = (void *)SM.getFileEntryForID(FID);
+ if (line)
+ *line = SM.getLineNumber(FID, FileOffset);
+ if (column)
+ *column = SM.getColumnNumber(FID, FileOffset);
+ if (offset)
+ *offset = FileOffset;
}
} // end extern "C"
Modified: cfe/trunk/tools/libclang/CXStoredDiagnostic.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/CXStoredDiagnostic.cpp?rev=144269&r1=144268&r2=144269&view=diff
==============================================================================
--- cfe/trunk/tools/libclang/CXStoredDiagnostic.cpp (original)
+++ cfe/trunk/tools/libclang/CXStoredDiagnostic.cpp Thu Nov 10 02:43:12 2011
@@ -28,9 +28,6 @@
using namespace clang::cxloc;
using namespace clang::cxstring;
-// Needed for vtable of CXPersisetntDiagnostic.
-CXDiagnosticImpl::~CXDiagnosticImpl() {}
-
CXDiagnosticSeverity CXStoredDiagnostic::getSeverity() const {
switch (Diag.getLevel()) {
case DiagnosticsEngine::Ignored: return CXDiagnostic_Ignored;
Modified: cfe/trunk/tools/libclang/CXTranslationUnit.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/CXTranslationUnit.h?rev=144269&r1=144268&r2=144269&view=diff
==============================================================================
--- cfe/trunk/tools/libclang/CXTranslationUnit.h (original)
+++ cfe/trunk/tools/libclang/CXTranslationUnit.h Thu Nov 10 02:43:12 2011
@@ -18,6 +18,7 @@
struct CXTranslationUnitImpl {
void *TUData;
void *StringPool;
+ void *Diagnostics;
};
}
@@ -27,7 +28,7 @@
namespace cxtu {
CXTranslationUnitImpl *MakeCXTranslationUnit(ASTUnit *TU);
-
+
class CXTUOwner {
CXTranslationUnitImpl *TU;
Modified: cfe/trunk/tools/libclang/libclang.exports
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/libclang.exports?rev=144269&r1=144268&r2=144269&view=diff
==============================================================================
--- cfe/trunk/tools/libclang/libclang.exports (original)
+++ cfe/trunk/tools/libclang/libclang.exports Thu Nov 10 02:43:12 2011
@@ -32,6 +32,7 @@
clang_disposeCXTUResourceUsage
clang_disposeCodeCompleteResults
clang_disposeDiagnostic
+clang_disposeDiagnosticSet
clang_disposeIndex
clang_disposeOverriddenCursors
clang_disposeString
@@ -53,6 +54,7 @@
clang_getCXXAccessSpecifier
clang_getCanonicalCursor
clang_getCanonicalType
+clang_getChildDiagnostics
clang_getClangVersion
clang_getCompletionAnnotation
clang_getCompletionAvailability
@@ -86,6 +88,7 @@
clang_getDiagnosticCategory
clang_getDiagnosticCategoryName
clang_getDiagnosticFixIt
+clang_getDiagnosticInSet
clang_getDiagnosticLocation
clang_getDiagnosticNumFixIts
clang_getDiagnosticNumRanges
@@ -108,6 +111,7 @@
clang_getNullRange
clang_getNumCompletionChunks
clang_getNumDiagnostics
+clang_getNumDiagnosticsInSet
clang_getNumOverloadedDecls
clang_getOverloadedDecl
clang_getOverriddenCursors
@@ -150,6 +154,7 @@
clang_isUnexposed
clang_isVirtualBase
clang_isVolatileQualifiedType
+clang_loadDiagnostics
clang_parseTranslationUnit
clang_remap_dispose
clang_remap_getFilenames
More information about the cfe-commits
mailing list