aboutsummaryrefslogtreecommitdiff
path: root/tools
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2010-01-28 00:27:43 +0000
committerDouglas Gregor <dgregor@apple.com>2010-01-28 00:27:43 +0000
commit5352ac06d8f6194825bb2a99ffa009b61bafb503 (patch)
treee50e65bcdcd96fb196e24794c7086caa9b489bfd /tools
parentf291976ecf537dc4f2d5537b1664d47ff4b94865 (diff)
Implement a diagnostics callback for the C interface to Clang, so that
clients can format diagnostics as they wish rather than having to parse standard error. All of the important parts of the front end's diagnostics are exposed: text, severity, location, source ranges, and fix-its. The diagnostics callback is now available with clang_createTranslationUnitFromSource() and clang_createTranslationUnit(). As part of this change, CXSourceLocation and CXSourceRange got one pointer larger, since we need to hold on to the SourceManager and LangOptions structures in the source location. This is the minimum amount of information needed for the functions that operate on source locations and ranges (as implemented now). Previously we held on to the ASTContext, but the diagnostics callback can end up with source locations when there is no ASTContext (or preprocessor). Still to do: - Code completion needs to support the diagnostics callback, once we have the ability to (de-)serialize diagnostics. - Eliminate the "displayDiagnostics" argument to createIndex; we'll always pass diagnostics to the callback and let it deal with display. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@94709 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'tools')
-rw-r--r--tools/CIndex/CIndex.cpp86
-rw-r--r--tools/CIndex/CIndex.exports11
-rw-r--r--tools/CIndex/CIndexDiagnostic.cpp198
-rw-r--r--tools/CIndex/CIndexDiagnostic.h49
-rw-r--r--tools/CIndex/CIndexer.h24
-rw-r--r--tools/CIndex/CMakeLists.txt1
-rw-r--r--tools/CIndex/CXSourceLocation.h35
-rw-r--r--tools/c-index-test/c-index-test.c52
8 files changed, 391 insertions, 65 deletions
diff --git a/tools/CIndex/CIndex.cpp b/tools/CIndex/CIndex.cpp
index 10099ef0aa..336a638b3a 100644
--- a/tools/CIndex/CIndex.cpp
+++ b/tools/CIndex/CIndex.cpp
@@ -15,6 +15,7 @@
#include "CIndexer.h"
#include "CXCursor.h"
#include "CXSourceLocation.h"
+#include "CIndexDiagnostic.h"
#include "clang/Basic/Version.h"
#include "clang/AST/DeclVisitor.h"
@@ -913,13 +914,21 @@ void clang_setUseExternalASTGeneration(CXIndex CIdx, int value) {
CXXIdx->setUseExternalASTGeneration(value);
}
-// FIXME: need to pass back error info.
CXTranslationUnit clang_createTranslationUnit(CXIndex CIdx,
- const char *ast_filename) {
+ const char *ast_filename,
+ CXDiagnosticCallback diag_callback,
+ CXClientData diag_client_data) {
assert(CIdx && "Passed null CXIndex");
CIndexer *CXXIdx = static_cast<CIndexer *>(CIdx);
- return ASTUnit::LoadFromPCHFile(ast_filename, CXXIdx->getDiags(),
+ // Configure the diagnostics.
+ DiagnosticOptions DiagOpts;
+ llvm::OwningPtr<Diagnostic> Diags;
+ Diags.reset(CompilerInstance::createDiagnostics(DiagOpts, 0, 0));
+ CIndexDiagnosticClient DiagClient(diag_callback, diag_client_data);
+ Diags->setClient(&DiagClient);
+
+ return ASTUnit::LoadFromPCHFile(ast_filename, *Diags,
CXXIdx->getOnlyLocalDecls(),
/* UseBumpAllocator = */ true);
}
@@ -930,10 +939,19 @@ clang_createTranslationUnitFromSourceFile(CXIndex CIdx,
int num_command_line_args,
const char **command_line_args,
unsigned num_unsaved_files,
- struct CXUnsavedFile *unsaved_files) {
+ struct CXUnsavedFile *unsaved_files,
+ CXDiagnosticCallback diag_callback,
+ CXClientData diag_client_data) {
assert(CIdx && "Passed null CXIndex");
CIndexer *CXXIdx = static_cast<CIndexer *>(CIdx);
+ // Configure the diagnostics.
+ DiagnosticOptions DiagOpts;
+ llvm::OwningPtr<Diagnostic> Diags;
+ Diags.reset(CompilerInstance::createDiagnostics(DiagOpts, 0, 0));
+ CIndexDiagnosticClient DiagClient(diag_callback, diag_client_data);
+ Diags->setClient(&DiagClient);
+
llvm::SmallVector<ASTUnit::RemappedFile, 4> RemappedFiles;
for (unsigned I = 0; I != num_unsaved_files; ++I) {
const llvm::MemoryBuffer *Buffer
@@ -955,7 +973,7 @@ clang_createTranslationUnitFromSourceFile(CXIndex CIdx,
Args.insert(Args.end(), command_line_args,
command_line_args + num_command_line_args);
- unsigned NumErrors = CXXIdx->getDiags().getNumErrors();
+ unsigned NumErrors = Diags->getNumErrors();
#ifdef USE_CRASHTRACER
ArgsCrashTracerInfo ACTI(Args);
@@ -963,7 +981,7 @@ clang_createTranslationUnitFromSourceFile(CXIndex CIdx,
llvm::OwningPtr<ASTUnit> Unit(
ASTUnit::LoadFromCommandLine(Args.data(), Args.data() + Args.size(),
- CXXIdx->getDiags(),
+ *Diags,
CXXIdx->getClangResourcesPath(),
CXXIdx->getOnlyLocalDecls(),
/* UseBumpAllocator = */ true,
@@ -972,7 +990,7 @@ clang_createTranslationUnitFromSourceFile(CXIndex CIdx,
// FIXME: Until we have broader testing, just drop the entire AST if we
// encountered an error.
- if (NumErrors != CXXIdx->getDiags().getNumErrors())
+ if (NumErrors != Diags->getNumErrors())
return 0;
return Unit.take();
@@ -1050,7 +1068,7 @@ clang_createTranslationUnitFromSourceFile(CXIndex CIdx,
llvm::errs() << '\n';
}
- ASTUnit *ATU = ASTUnit::LoadFromPCHFile(astTmpFile, CXXIdx->getDiags(),
+ ASTUnit *ATU = ASTUnit::LoadFromPCHFile(astTmpFile, *Diags,
CXXIdx->getOnlyLocalDecls(),
/* UseBumpAllocator = */ true,
RemappedFiles.data(),
@@ -1089,7 +1107,7 @@ CXCursor clang_getTranslationUnitCursor(CXTranslationUnit TU) {
extern "C" {
CXSourceLocation clang_getNullLocation() {
- CXSourceLocation Result = { 0, 0 };
+ CXSourceLocation Result = { { 0, 0 }, 0 };
return Result;
}
@@ -1113,13 +1131,18 @@ CXSourceLocation clang_getLocation(CXTranslationUnit tu,
return cxloc::translateSourceLocation(CXXUnit->getASTContext(), SLoc, false);
}
+CXSourceRange clang_getNullRange() {
+ CXSourceRange Result = { { 0, 0 }, 0, 0 };
+ return Result;
+}
+
CXSourceRange clang_getRange(CXSourceLocation begin, CXSourceLocation end) {
- if (begin.ptr_data != end.ptr_data) {
- CXSourceRange Result = { 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();
- CXSourceRange Result = { begin.ptr_data, begin.int_data, end.int_data };
+ CXSourceRange Result = { { begin.ptr_data[0], begin.ptr_data[1] },
+ begin.int_data, end.int_data };
return Result;
}
@@ -1129,7 +1152,7 @@ void clang_getInstantiationLocation(CXSourceLocation location,
unsigned *column,
unsigned *offset) {
cxloc::CXSourceLocationPtr Ptr
- = cxloc::CXSourceLocationPtr::getFromOpaqueValue(location.ptr_data);
+ = cxloc::CXSourceLocationPtr::getFromOpaqueValue(location.ptr_data[0]);
SourceLocation Loc = SourceLocation::getFromRawEncoding(location.int_data);
if (!Ptr.getPointer() || Loc.isInvalid()) {
@@ -1147,8 +1170,7 @@ void clang_getInstantiationLocation(CXSourceLocation location,
// FIXME: This is largely copy-paste from
///TextDiagnosticPrinter::HighlightRange. When it is clear that this is
// what we want the two routines should be refactored.
- ASTContext &Context = *Ptr.getPointer();
- SourceManager &SM = Context.getSourceManager();
+ const SourceManager &SM = *Ptr.getPointer();
SourceLocation InstLoc = SM.getInstantiationLoc(Loc);
if (Ptr.getInt()) {
@@ -1170,7 +1192,7 @@ void clang_getInstantiationLocation(CXSourceLocation location,
// (CXXUnit), so that the preprocessor will be available here. At
// that point, we can use Preprocessor::getLocForEndOfToken().
unsigned Length = Lexer::MeasureTokenLength(InstLoc, SM,
- Context.getLangOptions());
+ *static_cast<LangOptions *>(location.ptr_data[1]));
if (Length > 0)
InstLoc = InstLoc.getFileLocWithOffset(Length - 1);
}
@@ -1186,15 +1208,17 @@ void clang_getInstantiationLocation(CXSourceLocation location,
}
CXSourceLocation clang_getRangeStart(CXSourceRange range) {
- CXSourceLocation Result = { range.ptr_data, range.begin_int_data };
+ CXSourceLocation Result = { { range.ptr_data[0], range.ptr_data[1] },
+ range.begin_int_data };
return Result;
}
CXSourceLocation clang_getRangeEnd(CXSourceRange range) {
- llvm::PointerIntPair<ASTContext *, 1, bool> Ptr;
- Ptr.setPointer(static_cast<ASTContext *>(range.ptr_data));
+ cxloc::CXSourceLocationPtr Ptr;
+ Ptr.setPointer(static_cast<SourceManager *>(range.ptr_data[0]));
Ptr.setInt(true);
- CXSourceLocation Result = { Ptr.getOpaqueValue(), range.end_int_data };
+ CXSourceLocation Result = { { Ptr.getOpaqueValue(), range.ptr_data[1] },
+ range.end_int_data };
return Result;
}
@@ -1505,10 +1529,8 @@ CXSourceLocation clang_getCursorLocation(CXCursor C) {
return cxloc::translateSourceLocation(getCursorContext(C),
getLocationFromExpr(getCursorExpr(C)));
- if (!getCursorDecl(C)) {
- CXSourceLocation empty = { 0, 0 };
- return empty;
- }
+ if (!getCursorDecl(C))
+ return clang_getNullLocation();
Decl *D = getCursorDecl(C);
SourceLocation Loc = D->getLocation();
@@ -1558,10 +1580,8 @@ CXSourceRange clang_getCursorExtent(CXCursor C) {
return cxloc::translateSourceRange(getCursorContext(C),
getCursorStmt(C)->getSourceRange());
- if (!getCursorDecl(C)) {
- CXSourceRange empty = { 0, 0, 0 };
- return empty;
- }
+ if (!getCursorDecl(C))
+ return clang_getNullRange();
Decl *D = getCursorDecl(C);
return cxloc::translateSourceRange(D->getASTContext(), D->getSourceRange());
@@ -1939,10 +1959,8 @@ CXSourceLocation clang_getTokenLocation(CXTranslationUnit TU, CXToken CXTok) {
CXSourceRange clang_getTokenExtent(CXTranslationUnit TU, CXToken CXTok) {
ASTUnit *CXXUnit = static_cast<ASTUnit *>(TU);
- if (!CXXUnit) {
- CXSourceRange Result = { 0, 0, 0 };
- return Result;
- }
+ if (!CXXUnit)
+ return clang_getNullRange();
return cxloc::translateSourceRange(CXXUnit->getASTContext(),
SourceLocation::getFromRawEncoding(CXTok.int_data[1]));
diff --git a/tools/CIndex/CIndex.exports b/tools/CIndex/CIndex.exports
index 12e2788e4a..8af1897faa 100644
--- a/tools/CIndex/CIndex.exports
+++ b/tools/CIndex/CIndex.exports
@@ -4,6 +4,7 @@ _clang_createIndex
_clang_createTranslationUnit
_clang_createTranslationUnitFromSourceFile
_clang_disposeCodeCompleteResults
+_clang_disposeDiagnosticRanges
_clang_disposeIndex
_clang_disposeString
_clang_disposeTokens
@@ -25,6 +26,15 @@ _clang_getCursorReferenced
_clang_getCursorSpelling
_clang_getCursorUSR
_clang_getDefinitionSpellingAndExtent
+_clang_getDiagnosticFixItInsertion
+_clang_getDiagnosticFixItKind
+_clang_getDiagnosticFixItRemoval
+_clang_getDiagnosticFixItReplacement
+_clang_getDiagnosticLocation
+_clang_getDiagnosticNumFixIts
+_clang_getDiagnosticRanges
+_clang_getDiagnosticSeverity
+_clang_getDiagnosticSpelling
_clang_getFile
_clang_getFileName
_clang_getFileTime
@@ -33,6 +43,7 @@ _clang_getInstantiationLocation
_clang_getLocation
_clang_getNullCursor
_clang_getNullLocation
+_clang_getNullRange
_clang_getNumCompletionChunks
_clang_getRange
_clang_getRangeEnd
diff --git a/tools/CIndex/CIndexDiagnostic.cpp b/tools/CIndex/CIndexDiagnostic.cpp
new file mode 100644
index 0000000000..9a21f383bd
--- /dev/null
+++ b/tools/CIndex/CIndexDiagnostic.cpp
@@ -0,0 +1,198 @@
+/*===-- CIndexDiagnostics.cpp - Diagnostics C Interface -----------*- C -*-===*\
+|* *|
+|* The LLVM Compiler Infrastructure *|
+|* *|
+|* This file is distributed under the University of Illinois Open Source *|
+|* License. See LICENSE.TXT for details. *|
+|* *|
+|*===----------------------------------------------------------------------===*|
+|* *|
+|* Implements the diagnostic functions of the Clang C interface. *|
+|* *|
+\*===----------------------------------------------------------------------===*/
+#include "CIndexDiagnostic.h"
+#include "CIndexer.h"
+#include "CXSourceLocation.h"
+
+using namespace clang;
+using namespace clang::cxloc;
+
+//-----------------------------------------------------------------------------
+// Opaque data structures
+//-----------------------------------------------------------------------------
+namespace {
+ /// \brief The storage behind a CXDiagnostic
+ struct CXStoredDiagnostic {
+ /// \brief The translation unit this diagnostic came from.
+ const LangOptions &LangOpts;
+
+ /// \brief The severity level of this diagnostic.
+ Diagnostic::Level Level;
+
+ /// \brief A reference to the diagnostic information.
+ const DiagnosticInfo &Info;
+ };
+}
+
+//-----------------------------------------------------------------------------
+// CIndex Diagnostic Client
+//-----------------------------------------------------------------------------
+CIndexDiagnosticClient::~CIndexDiagnosticClient() { }
+
+void CIndexDiagnosticClient::BeginSourceFile(const LangOptions &LangOpts,
+ const Preprocessor *PP) {
+ this->LangOpts = LangOpts;
+}
+
+void CIndexDiagnosticClient::HandleDiagnostic(Diagnostic::Level DiagLevel,
+ const DiagnosticInfo &Info) {
+ if (!Callback)
+ return;
+
+ CXStoredDiagnostic Stored = { this->LangOpts, DiagLevel, Info };
+ Callback(&Stored, ClientData);
+}
+
+//-----------------------------------------------------------------------------
+// C Interface Routines
+//-----------------------------------------------------------------------------
+extern "C" {
+
+enum CXDiagnosticSeverity clang_getDiagnosticSeverity(CXDiagnostic Diag) {
+ CXStoredDiagnostic *StoredDiag = static_cast<CXStoredDiagnostic *>(Diag);
+ if (!StoredDiag)
+ return CXDiagnostic_Ignored;
+
+ switch (StoredDiag->Level) {
+ case Diagnostic::Ignored: return CXDiagnostic_Ignored;
+ case Diagnostic::Note: return CXDiagnostic_Note;
+ case Diagnostic::Warning: return CXDiagnostic_Warning;
+ case Diagnostic::Error: return CXDiagnostic_Error;
+ case Diagnostic::Fatal: return CXDiagnostic_Fatal;
+ }
+
+ llvm_unreachable("Invalid diagnostic level");
+ return CXDiagnostic_Ignored;
+}
+
+CXSourceLocation clang_getDiagnosticLocation(CXDiagnostic Diag) {
+ CXStoredDiagnostic *StoredDiag = static_cast<CXStoredDiagnostic *>(Diag);
+ if (!StoredDiag || StoredDiag->Info.getLocation().isInvalid())
+ return clang_getNullLocation();
+
+ return translateSourceLocation(StoredDiag->Info.getLocation().getManager(),
+ StoredDiag->LangOpts,
+ StoredDiag->Info.getLocation());
+}
+
+CXString clang_getDiagnosticSpelling(CXDiagnostic Diag) {
+ CXStoredDiagnostic *StoredDiag = static_cast<CXStoredDiagnostic *>(Diag);
+ if (!StoredDiag)
+ return CIndexer::createCXString("");
+
+ llvm::SmallString<64> Spelling;
+ StoredDiag->Info.FormatDiagnostic(Spelling);
+ return CIndexer::createCXString(Spelling.str(), true);
+}
+
+void clang_getDiagnosticRanges(CXDiagnostic Diag,
+ CXSourceRange **Ranges,
+ unsigned *NumRanges) {
+ if (Ranges)
+ *Ranges = 0;
+ if (NumRanges)
+ *NumRanges = 0;
+
+ CXStoredDiagnostic *StoredDiag = static_cast<CXStoredDiagnostic *>(Diag);
+ if (!StoredDiag || !Ranges || !NumRanges ||
+ !StoredDiag->Info.getNumRanges() ||
+ StoredDiag->Info.getLocation().isInvalid())
+ return;
+
+ unsigned N = StoredDiag->Info.getNumRanges();
+ *Ranges = (CXSourceRange *)malloc(sizeof(CXSourceRange) * N);
+ *NumRanges = N;
+ for (unsigned I = 0; I != N; ++I)
+ (*Ranges)[I] = translateSourceRange(
+ StoredDiag->Info.getLocation().getManager(),
+ StoredDiag->LangOpts,
+ StoredDiag->Info.getRange(I));
+}
+
+void clang_disposeDiagnosticRanges(CXSourceRange *Ranges,
+ unsigned NumRanges) {
+ free(Ranges);
+}
+
+unsigned clang_getDiagnosticNumFixIts(CXDiagnostic Diag) {
+ CXStoredDiagnostic *StoredDiag = static_cast<CXStoredDiagnostic *>(Diag);
+ if (!StoredDiag)
+ return 0;
+
+ return StoredDiag->Info.getNumCodeModificationHints();
+}
+
+enum CXFixItKind clang_getDiagnosticFixItKind(CXDiagnostic Diag,
+ unsigned FixIt) {
+ CXStoredDiagnostic *StoredDiag = static_cast<CXStoredDiagnostic *>(Diag);
+ if (!StoredDiag || FixIt >= StoredDiag->Info.getNumCodeModificationHints())
+ return CXFixIt_Insertion;
+
+ const CodeModificationHint &Hint
+ = StoredDiag->Info.getCodeModificationHint(FixIt);
+ if (Hint.RemoveRange.isInvalid())
+ return CXFixIt_Insertion;
+ if (Hint.InsertionLoc.isInvalid())
+ return CXFixIt_Removal;
+
+ return CXFixIt_Replacement;
+}
+
+CXString clang_getDiagnosticFixItInsertion(CXDiagnostic Diag,
+ unsigned FixIt,
+ CXSourceLocation *Location) {
+ CXStoredDiagnostic *StoredDiag = static_cast<CXStoredDiagnostic *>(Diag);
+ if (!StoredDiag || FixIt >= StoredDiag->Info.getNumCodeModificationHints())
+ return CIndexer::createCXString("");
+
+ const CodeModificationHint &Hint
+ = StoredDiag->Info.getCodeModificationHint(FixIt);
+ return CIndexer::createCXString(Hint.CodeToInsert);
+}
+
+CXSourceRange clang_getDiagnosticFixItRemoval(CXDiagnostic Diag,
+ unsigned FixIt) {
+ CXStoredDiagnostic *StoredDiag = static_cast<CXStoredDiagnostic *>(Diag);
+ if (!StoredDiag || FixIt >= StoredDiag->Info.getNumCodeModificationHints() ||
+ StoredDiag->Info.getLocation().isInvalid())
+ return clang_getNullRange();
+
+ const CodeModificationHint &Hint
+ = StoredDiag->Info.getCodeModificationHint(FixIt);
+ return translateSourceRange(StoredDiag->Info.getLocation().getManager(),
+ StoredDiag->LangOpts,
+ Hint.RemoveRange);
+}
+
+CXString clang_getDiagnosticFixItReplacement(CXDiagnostic Diag,
+ unsigned FixIt,
+ CXSourceRange *Range) {
+ CXStoredDiagnostic *StoredDiag = static_cast<CXStoredDiagnostic *>(Diag);
+ if (!StoredDiag || FixIt >= StoredDiag->Info.getNumCodeModificationHints() ||
+ StoredDiag->Info.getLocation().isInvalid()) {
+ if (Range)
+ *Range = clang_getNullRange();
+
+ return CIndexer::createCXString("");
+ }
+
+ const CodeModificationHint &Hint
+ = StoredDiag->Info.getCodeModificationHint(FixIt);
+ if (Range)
+ *Range = translateSourceRange(StoredDiag->Info.getLocation().getManager(),
+ StoredDiag->LangOpts,
+ Hint.RemoveRange);
+ return CIndexer::createCXString(Hint.CodeToInsert);
+}
+
+} // end extern "C"
diff --git a/tools/CIndex/CIndexDiagnostic.h b/tools/CIndex/CIndexDiagnostic.h
new file mode 100644
index 0000000000..f9620415cb
--- /dev/null
+++ b/tools/CIndex/CIndexDiagnostic.h
@@ -0,0 +1,49 @@
+/*===-- CIndexDiagnostic.h - Diagnostics C Interface --------------*- C -*-===*\
+|* *|
+|* The LLVM Compiler Infrastructure *|
+|* *|
+|* This file is distributed under the University of Illinois Open Source *|
+|* License. See LICENSE.TXT for details. *|
+|* *|
+|*===----------------------------------------------------------------------===*|
+|* *|
+|* Implements the diagnostic functions of the Clang C interface. *|
+|* *|
+\*===----------------------------------------------------------------------===*/
+#ifndef LLVM_CLANG_CINDEX_DIAGNOSTIC_H
+#define LLVM_CLANG_CINDEX_DIAGNOSTIC_H
+
+#include "clang-c/Index.h"
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/LangOptions.h"
+
+namespace clang {
+
+class Preprocessor;
+
+/**
+ * \brief Diagnostic client that translates Clang diagnostics into diagnostics
+ * for the C interface to Clang.
+ */
+class CIndexDiagnosticClient : public DiagnosticClient {
+ CXDiagnosticCallback Callback;
+ CXClientData ClientData;
+ LangOptions LangOpts;
+
+public:
+ CIndexDiagnosticClient(CXDiagnosticCallback Callback,
+ CXClientData ClientData)
+ : Callback(Callback), ClientData(ClientData), LangOpts() { }
+
+ virtual ~CIndexDiagnosticClient();
+
+ virtual void BeginSourceFile(const LangOptions &LangOpts,
+ const Preprocessor *PP);
+
+ virtual void HandleDiagnostic(Diagnostic::Level DiagLevel,
+ const DiagnosticInfo &Info);
+};
+
+} // end namespace clang
+
+#endif // LLVM_CLANG_CINDEX_DIAGNOSTIC_H
diff --git a/tools/CIndex/CIndexer.h b/tools/CIndex/CIndexer.h
index aa63ec0238..44eaaec8b5 100644
--- a/tools/CIndex/CIndexer.h
+++ b/tools/CIndex/CIndexer.h
@@ -24,19 +24,7 @@
using namespace clang;
-/// IgnoreDiagnosticsClient - A DiagnosticsClient that just ignores emitted
-/// warnings and errors.
-class IgnoreDiagnosticsClient : public DiagnosticClient {
-public:
- virtual ~IgnoreDiagnosticsClient() {}
- virtual void HandleDiagnostic(Diagnostic::Level, const DiagnosticInfo &) {}
-};
-
class CIndexer {
- DiagnosticOptions DiagOpts;
- IgnoreDiagnosticsClient IgnoreDiagClient;
- llvm::OwningPtr<Diagnostic> TextDiags;
- Diagnostic IgnoreDiags;
bool UseExternalASTGeneration;
bool OnlyLocalDecls;
bool DisplayDiagnostics;
@@ -44,11 +32,9 @@ class CIndexer {
llvm::sys::Path ClangPath;
public:
- CIndexer() : IgnoreDiags(&IgnoreDiagClient), UseExternalASTGeneration(false),
- OnlyLocalDecls(false), DisplayDiagnostics(false)
- {
- TextDiags.reset(CompilerInstance::createDiagnostics(DiagOpts, 0, 0));
- }
+ CIndexer()
+ : UseExternalASTGeneration(false), OnlyLocalDecls(false),
+ DisplayDiagnostics(false) { }
/// \brief Whether we only want to see "local" declarations (that did not
/// come from a previous precompiled header). If false, we want to see all
@@ -66,10 +52,6 @@ public:
UseExternalASTGeneration = Value;
}
- Diagnostic &getDiags() {
- return DisplayDiagnostics ? *TextDiags : IgnoreDiags;
- }
-
/// \brief Get the path of the clang binary.
const llvm::sys::Path& getClangPath();
diff --git a/tools/CIndex/CMakeLists.txt b/tools/CIndex/CMakeLists.txt
index f4d2225310..26e1b3bb90 100644
--- a/tools/CIndex/CMakeLists.txt
+++ b/tools/CIndex/CMakeLists.txt
@@ -21,6 +21,7 @@ set( LLVM_LINK_COMPONENTS
add_clang_library(CIndex
CIndex.cpp
CIndexCodeCompletion.cpp
+ CIndexDiagnostic.cpp
CIndexInclusionStack.cpp
CIndexUSRs.cpp
CIndexer.cpp
diff --git a/tools/CIndex/CXSourceLocation.h b/tools/CIndex/CXSourceLocation.h
index 1f15f0832c..e1dc7ed966 100644
--- a/tools/CIndex/CXSourceLocation.h
+++ b/tools/CIndex/CXSourceLocation.h
@@ -16,6 +16,9 @@
#include "clang-c/Index.h"
#include "clang/Basic/SourceLocation.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Basic/LangOptions.h"
+#include "clang/AST/ASTContext.h"
namespace clang {
@@ -23,25 +26,45 @@ class ASTContext;
namespace cxloc {
-typedef llvm::PointerIntPair<ASTContext *, 1, bool> CXSourceLocationPtr;
+typedef llvm::PointerIntPair<const SourceManager *, 1, bool>
+ CXSourceLocationPtr;
/// \brief Translate a Clang source location into a CIndex source location.
+static inline CXSourceLocation
+translateSourceLocation(const SourceManager &SM, const LangOptions &LangOpts,
+ SourceLocation Loc, bool AtEnd = false) {
+ CXSourceLocationPtr Ptr(&SM, AtEnd);
+ CXSourceLocation Result = { { Ptr.getOpaqueValue(), (void *)&LangOpts, },
+ Loc.getRawEncoding() };
+ return Result;
+}
+
+/// \brief Translate a Clang source location into a CIndex source location.
static inline CXSourceLocation translateSourceLocation(ASTContext &Context,
SourceLocation Loc,
bool AtEnd = false) {
- CXSourceLocationPtr Ptr(&Context, AtEnd);
- CXSourceLocation Result = { Ptr.getOpaqueValue(), Loc.getRawEncoding() };
- return Result;
+ return translateSourceLocation(Context.getSourceManager(),
+ Context.getLangOptions(),
+ Loc, AtEnd);
}
/// \brief Translate a Clang source range into a CIndex source range.
-static inline CXSourceRange translateSourceRange(ASTContext &Context,
+static inline CXSourceRange translateSourceRange(const SourceManager &SM,
+ const LangOptions &LangOpts,
SourceRange R) {
- CXSourceRange Result = { &Context,
+ CXSourceRange Result = { { (void *)&SM, (void *)&LangOpts },
R.getBegin().getRawEncoding(),
R.getEnd().getRawEncoding() };
return Result;
}
+
+/// \brief Translate a Clang source range into a CIndex source range.
+static inline CXSourceRange translateSourceRange(ASTContext &Context,
+ SourceRange R) {
+ return translateSourceRange(Context.getSourceManager(),
+ Context.getLangOptions(),
+ R);
+}
static inline SourceLocation translateSourceLocation(CXSourceLocation L) {
return SourceLocation::getFromRawEncoding(L.int_data);
diff --git a/tools/c-index-test/c-index-test.c b/tools/c-index-test/c-index-test.c
index 2ad9da12bb..39c3446f04 100644
--- a/tools/c-index-test/c-index-test.c
+++ b/tools/c-index-test/c-index-test.c
@@ -28,10 +28,13 @@ char *basename(const char* path)
extern char *basename(const char *);
#endif
+static void PrintDiagnosticCallback(CXDiagnostic Diagnostic,
+ CXClientData ClientData);
+
static unsigned CreateTranslationUnit(CXIndex Idx, const char *file,
CXTranslationUnit *TU) {
- *TU = clang_createTranslationUnit(Idx, file);
+ *TU = clang_createTranslationUnit(Idx, file, PrintDiagnosticCallback, 0);
if (!TU) {
fprintf(stderr, "Unable to load translation unit from '%s'!\n", file);
return 0;
@@ -177,6 +180,41 @@ static const char* GetCursorSource(CXCursor Cursor) {
typedef void (*PostVisitTU)(CXTranslationUnit);
+static void PrintDiagnosticCallback(CXDiagnostic Diagnostic,
+ CXClientData ClientData) {
+ FILE *out = (FILE *)ClientData;
+ CXFile file;
+ unsigned line, column;
+ CXString text;
+ enum CXDiagnosticSeverity severity = clang_getDiagnosticSeverity(Diagnostic);
+
+ /* Ignore diagnostics that should be ignored. */
+ if (severity == CXDiagnostic_Ignored)
+ return;
+
+ /* Print file:line:column. */
+ clang_getInstantiationLocation(clang_getDiagnosticLocation(Diagnostic),
+ &file, &line, &column, 0);
+ if (file)
+ fprintf(out, "%s:%d:%d: ", clang_getFileName(file), line, column);
+
+ /* Print warning/error/etc. */
+ switch (severity) {
+ case CXDiagnostic_Ignored: assert(0 && "impossible"); break;
+ case CXDiagnostic_Note: fprintf(out, "note: "); break;
+ case CXDiagnostic_Warning: fprintf(out, "warning: "); break;
+ case CXDiagnostic_Error: fprintf(out, "error: "); break;
+ case CXDiagnostic_Fatal: fprintf(out, "fatal error: "); break;
+ }
+
+ text = clang_getDiagnosticSpelling(Diagnostic);
+ if (clang_getCString(text))
+ fprintf(out, "%s\n", clang_getCString(text));
+ else
+ fprintf(out, "<no diagnostic text>\n");
+ clang_disposeString(text);
+}
+
/******************************************************************************/
/* Logic for testing traversal. */
/******************************************************************************/
@@ -407,7 +445,9 @@ int perform_test_load_source(int argc, const char **argv,
argc - num_unsaved_files,
argv + num_unsaved_files,
num_unsaved_files,
- unsaved_files);
+ unsaved_files,
+ PrintDiagnosticCallback,
+ stderr);
if (!TU) {
fprintf(stderr, "Unable to load translation unit!\n");
return 1;
@@ -722,7 +762,9 @@ int inspect_cursor_at(int argc, const char **argv) {
argc - num_unsaved_files - 2 - NumLocations,
argv + num_unsaved_files + 1 + NumLocations,
num_unsaved_files,
- unsaved_files);
+ unsaved_files,
+ PrintDiagnosticCallback,
+ stderr);
if (!TU) {
fprintf(stderr, "unable to parse input\n");
return -1;
@@ -779,7 +821,9 @@ int perform_token_annotation(int argc, const char **argv) {
argc - num_unsaved_files - 3,
argv + num_unsaved_files + 2,
num_unsaved_files,
- unsaved_files);
+ unsaved_files,
+ PrintDiagnosticCallback,
+ stderr);
if (!TU) {
fprintf(stderr, "unable to parse input\n");
clang_disposeIndex(CIdx);