diff options
Diffstat (limited to 'tools')
-rw-r--r-- | tools/CIndex/CIndex.cpp | 86 | ||||
-rw-r--r-- | tools/CIndex/CIndex.exports | 11 | ||||
-rw-r--r-- | tools/CIndex/CIndexDiagnostic.cpp | 198 | ||||
-rw-r--r-- | tools/CIndex/CIndexDiagnostic.h | 49 | ||||
-rw-r--r-- | tools/CIndex/CIndexer.h | 24 | ||||
-rw-r--r-- | tools/CIndex/CMakeLists.txt | 1 | ||||
-rw-r--r-- | tools/CIndex/CXSourceLocation.h | 35 | ||||
-rw-r--r-- | tools/c-index-test/c-index-test.c | 52 |
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); |