aboutsummaryrefslogtreecommitdiff
path: root/tools
diff options
context:
space:
mode:
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);