diff options
-rw-r--r-- | include/clang-c/Index.h | 342 | ||||
-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 |
9 files changed, 677 insertions, 121 deletions
diff --git a/include/clang-c/Index.h b/include/clang-c/Index.h index 0470592a0f..e26dff1eb1 100644 --- a/include/clang-c/Index.h +++ b/include/clang-c/Index.h @@ -178,12 +178,6 @@ CINDEX_LINKAGE CXIndex clang_createIndex(int excludeDeclarationsFromPCH, CINDEX_LINKAGE void clang_disposeIndex(CXIndex index); /** - * \brief Get the original translation unit source file name. - */ -CINDEX_LINKAGE CXString -clang_getTranslationUnitSpelling(CXTranslationUnit CTUnit); - -/** * \brief Request that AST's be generated externally for API calls which parse * source code on the fly, e.g. \see createTranslationUnitFromSourceFile. * @@ -195,54 +189,6 @@ clang_getTranslationUnitSpelling(CXTranslationUnit CTUnit); */ CINDEX_LINKAGE void clang_setUseExternalASTGeneration(CXIndex index, int value); - -/** - * \brief Create a translation unit from an AST file (-emit-ast). - */ -CINDEX_LINKAGE CXTranslationUnit clang_createTranslationUnit( - CXIndex, const char *ast_filename -); - -/** - * \brief Destroy the specified CXTranslationUnit object. - */ -CINDEX_LINKAGE void clang_disposeTranslationUnit(CXTranslationUnit); - -/** - * \brief Return the CXTranslationUnit for a given source file and the provided - * command line arguments one would pass to the compiler. - * - * Note: The 'source_filename' argument is optional. If the caller provides a - * NULL pointer, the name of the source file is expected to reside in the - * specified command line arguments. - * - * Note: When encountered in 'clang_command_line_args', the following options - * are ignored: - * - * '-c' - * '-emit-ast' - * '-fsyntax-only' - * '-o <output file>' (both '-o' and '<output file>' are ignored) - * - * - * \param source_filename - The name of the source file to load, or NULL if the - * source file is included in clang_command_line_args. - * - * \param num_unsaved_files the number of unsaved file entries in \p - * unsaved_files. - * - * \param unsaved_files the files that have not yet been saved to disk - * but may be required for code completion, including the contents of - * those files. - */ -CINDEX_LINKAGE CXTranslationUnit clang_createTranslationUnitFromSourceFile( - CXIndex CIdx, - const char *source_filename, - int num_clang_command_line_args, - const char **clang_command_line_args, - unsigned num_unsaved_files, - struct CXUnsavedFile *unsaved_files); - /** * \defgroup CINDEX_FILES File manipulation routines * @@ -303,7 +249,7 @@ CINDEX_LINKAGE CXFile clang_getFile(CXTranslationUnit tu, * particular file, line, and column. */ typedef struct { - void *ptr_data; + void *ptr_data[2]; unsigned int_data; } CXSourceLocation; @@ -314,7 +260,7 @@ typedef struct { * starting and end locations from a source range, respectively. */ typedef struct { - void *ptr_data; + void *ptr_data[2]; unsigned begin_int_data; unsigned end_int_data; } CXSourceRange; @@ -345,6 +291,11 @@ CINDEX_LINKAGE CXSourceLocation clang_getLocation(CXTranslationUnit tu, unsigned column); /** + * \brief Retrieve a NULL (invalid) source range. + */ +CINDEX_LINKAGE CXSourceRange clang_getNullRange(); + +/** * \brief Retrieve a source range given the beginning and ending source * locations. */ @@ -393,6 +344,285 @@ CINDEX_LINKAGE CXSourceLocation clang_getRangeEnd(CXSourceRange range); */ /** + * \defgroup CINDEX_DIAG Diagnostic reporting + * + * @{ + */ + +/** + * \brief Describes the severity of a particular diagnostic. + */ +enum CXDiagnosticSeverity { + /** + * \brief A diagnostic that has been suppressed, e.g., by a command-line + * option. + */ + CXDiagnostic_Ignored = 0, + + /** + * \brief This diagnostic is a note that should be attached to the + * previous (non-note) diagnostic. + */ + CXDiagnostic_Note = 1, + + /** + * \brief This diagnostic indicates suspicious code that may not be + * wrong. + */ + CXDiagnostic_Warning = 2, + + /** + * \brief This diagnostic indicates that the code is ill-formed. + */ + CXDiagnostic_Error = 3, + + /** + * \brief This diagnostic indicates that the code is ill-formed such + * that future parser recovery is unlikely to produce useful + * results. + */ + CXDiagnostic_Fatal = 4 +}; + +/** + * \brief Describes the kind of fix-it hint expressed within a + * diagnostic. + */ +enum CXFixItKind { + /** + * \brief A fix-it hint that inserts code at a particular position. + */ + CXFixIt_Insertion = 0, + + /** + * \brief A fix-it hint that removes code within a range. + */ + CXFixIt_Removal = 1, + + /** + * \brief A fix-it hint that replaces the code within a range with another + * string. + */ + CXFixIt_Replacement = 2 +}; + +/** + * \brief A single diagnostic, containing the diagnostic's severity, + * location, text, source ranges, and fix-it hints. + */ +typedef void *CXDiagnostic; + +/** + * \brief Callback function invoked for each diagnostic emitted during + * translation. + * + * \param Diagnostic the diagnostic emitted during translation. This + * diagnostic pointer is only valid during the execution of the + * callback. + * + * \param ClientData the callback client data. + */ +typedef void (*CXDiagnosticCallback)(CXDiagnostic Diagnostic, + CXClientData ClientData); + +/** + * \brief Determine the severity of the given diagnostic. + */ +CINDEX_LINKAGE enum CXDiagnosticSeverity +clang_getDiagnosticSeverity(CXDiagnostic); + +/** + * \brief Retrieve the source location of the given diagnostic. + * + * This location is where Clang would print the caret ('^') when + * displaying the diagnostic on the command line. + */ +CINDEX_LINKAGE CXSourceLocation clang_getDiagnosticLocation(CXDiagnostic); + +/** + * \brief Retrieve the text of the given diagnostic. + */ +CINDEX_LINKAGE CXString clang_getDiagnosticSpelling(CXDiagnostic); + +/** + * \brief Retrieve the source ranges associated with the diagnostic. + * + * These source ranges highlight important elements in the source + * code. On the command line, Clang displays source ranges by + * underlining them with '~' characters. + * + * \param Diagnostic the diagnostic whose ranges are being extracted. + * + * \param Ranges [out] will be set to a newly-allocated array + * containing the source ranges of this diagnostic. These ranges must + * be freed with \c clang_disposeDiagnosticRanges(). + * + * \param NumRanges [out] will be set to the number of source ranges + * in the \p Ranges array. + */ +CINDEX_LINKAGE void clang_getDiagnosticRanges(CXDiagnostic Diagnostic, + CXSourceRange **Ranges, + unsigned *NumRanges); + +/** + * \brief Free the source ranges returned by \c clang_getDiagnosticRanges(). + */ +CINDEX_LINKAGE void clang_disposeDiagnosticRanges(CXSourceRange *Ranges, + unsigned NumRanges); + +/** + * \brief Determine the number of fix-it hints associated with the + * given diagnostic. + */ +CINDEX_LINKAGE unsigned clang_getDiagnosticNumFixIts(CXDiagnostic Diagnostic); + +/** + * \brief Retrieve the kind of the given fix-it. + * + * \param Diagnostic the diagnostic whose fix-its are being queried. + * + * \param FixIt the zero-based index of the fix-it to query. + */ +CINDEX_LINKAGE enum CXFixItKind +clang_getDiagnosticFixItKind(CXDiagnostic Diagnostic, unsigned FixIt); + +/** + * \brief Retrieve the insertion information for an insertion fix-it. + * + * For a fix-it that describes an insertion into a text buffer, + * retrieve the source location where the text should be inserted and + * the text to be inserted. + * + * \param Diagnostic the diagnostic whose fix-its are being queried. + * + * \param FixIt the zero-based index of the insertion fix-it. + * + * \param Location will be set to the location where text should be + * inserted. + * + * \returns the text string to insert at the given location. + */ +CINDEX_LINKAGE CXString +clang_getDiagnosticFixItInsertion(CXDiagnostic Diagnostic, unsigned FixIt, + CXSourceLocation *Location); + +/** + * \brief Retrieve the removal information for a removal fix-it. + * + * For a fix-it that describes a removal from a text buffer, retrieve + * the source range that should be removed. + * + * \param Diagnostic the diagnostic whose fix-its are being queried. + * + * \param FixIt the zero-based index of the removal fix-it. + * + * \returns a source range describing the text that should be removed + * from the buffer. + */ +CINDEX_LINKAGE CXSourceRange +clang_getDiagnosticFixItRemoval(CXDiagnostic Diagnostic, unsigned FixIt); + +/** + * \brief Retrieve the replacement information for an replacement fix-it. + * + * For a fix-it that describes replacement of text in the text buffer + * with alternative text. + * + * \param Diagnostic the diagnostic whose fix-its are being queried. + * + * \param FixIt the zero-based index of the replacement fix-it. + * + * \param Range will be set to the source range whose text should be + * replaced with the returned text. + * + * \returns the text string to use as replacement text. + */ +CINDEX_LINKAGE CXString +clang_getDiagnosticFixItReplacement(CXDiagnostic Diagnostic, unsigned FixIt, + CXSourceRange *Range); + +/** + * @} + */ + +/** + * \defgroup CINDEX_TRANSLATION_UNIT Translation unit manipulation + * + * The routines in this group provide the ability to create and destroy + * translation units from files, either by parsing the contents of the files or + * by reading in a serialized representation of a translation unit. + * + * @{ + */ + +/** + * \brief Get the original translation unit source file name. + */ +CINDEX_LINKAGE CXString +clang_getTranslationUnitSpelling(CXTranslationUnit CTUnit); + +/** + * \brief Return the CXTranslationUnit for a given source file and the provided + * command line arguments one would pass to the compiler. + * + * Note: The 'source_filename' argument is optional. If the caller provides a + * NULL pointer, the name of the source file is expected to reside in the + * specified command line arguments. + * + * Note: When encountered in 'clang_command_line_args', the following options + * are ignored: + * + * '-c' + * '-emit-ast' + * '-fsyntax-only' + * '-o <output file>' (both '-o' and '<output file>' are ignored) + * + * + * \param source_filename - The name of the source file to load, or NULL if the + * source file is included in clang_command_line_args. + * + * \param num_unsaved_files the number of unsaved file entries in \p + * unsaved_files. + * + * \param unsaved_files the files that have not yet been saved to disk + * but may be required for code completion, including the contents of + * those files. + * + * \param diag_callback callback function that will receive any diagnostics + * emitted while processing this source file. If NULL, diagnostics will be + * suppressed. + * + * \param diag_client_data client data that will be passed to the diagnostic + * callback function. + */ +CINDEX_LINKAGE CXTranslationUnit clang_createTranslationUnitFromSourceFile( + CXIndex CIdx, + const char *source_filename, + int num_clang_command_line_args, + const char **clang_command_line_args, + unsigned num_unsaved_files, + struct CXUnsavedFile *unsaved_files, + CXDiagnosticCallback diag_callback, + CXClientData diag_client_data); + +/** + * \brief Create a translation unit from an AST file (-emit-ast). + */ +CINDEX_LINKAGE CXTranslationUnit clang_createTranslationUnit(CXIndex, + const char *ast_filename, + CXDiagnosticCallback diag_callback, + CXClientData diag_client_data); + +/** + * \brief Destroy the specified CXTranslationUnit object. + */ +CINDEX_LINKAGE void clang_disposeTranslationUnit(CXTranslationUnit); + +/** + * @} + */ + +/** * \brief Describes the kind of entity that a cursor refers to. */ enum CXCursorKind { 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; |