From: Douglas Gregor Date: Thu, 18 Feb 2010 23:07:20 +0000 (+0000) Subject: Re-apply my diagnostics-capture patch for CIndex, with some tweaks to X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=0a812cf707da15dadd19fdeb0178b9707f4e01a6;p=clang Re-apply my diagnostics-capture patch for CIndex, with some tweaks to try to address the msvc failures. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@96624 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang-c/Index.h b/include/clang-c/Index.h index 99c129b220..0130b72b6f 100644 --- a/include/clang-c/Index.h +++ b/include/clang-c/Index.h @@ -18,6 +18,7 @@ #include #include +#include #ifdef __cplusplus extern "C" { @@ -145,8 +146,8 @@ CINDEX_LINKAGE void clang_disposeString(CXString string); * * Here is an example: * - * // excludeDeclsFromPCH = 1 - * Idx = clang_createIndex(1); + * // excludeDeclsFromPCH = 1, displayDiagnostics=1 + * Idx = clang_createIndex(1, 1); * * // IndexTest.pch was produced with the following command: * // "clang -x c IndexTest.h -emit-ast -o IndexTest.pch" @@ -170,7 +171,8 @@ CINDEX_LINKAGE void clang_disposeString(CXString string); * -include-pch) allows 'excludeDeclsFromPCH' to remove redundant callbacks * (which gives the indexer the same performance benefit as the compiler). */ -CINDEX_LINKAGE CXIndex clang_createIndex(int excludeDeclarationsFromPCH); +CINDEX_LINKAGE CXIndex clang_createIndex(int excludeDeclarationsFromPCH, + int displayDiagnostics); /** * \brief Destroy the given index. @@ -438,6 +440,79 @@ CINDEX_LINKAGE CXDiagnostic clang_getDiagnostic(CXTranslationUnit Unit, */ CINDEX_LINKAGE void clang_disposeDiagnostic(CXDiagnostic Diagnostic); +/** + * \brief Options to control the display of diagnostics. + * + * The values in this enum are meant to be combined to customize the + * behavior of \c clang_displayDiagnostic(). + */ +enum CXDiagnosticDisplayOptions { + /** + * \brief Display the source-location information where the + * diagnostic was located. + * + * When set, diagnostics will be prefixed by the file, line, and + * (optionally) column to which the diagnostic refers. For example, + * + * \code + * test.c:28: warning: extra tokens at end of #endif directive + * \endcode + * + * This option corresponds to the clang flag \c -fshow-source-location. + */ + CXDiagnostic_DisplaySourceLocation = 0x01, + + /** + * \brief If displaying the source-location information of the + * diagnostic, also include the column number. + * + * This option corresponds to the clang flag \c -fshow-column. + */ + CXDiagnostic_DisplayColumn = 0x02, + + /** + * \brief If displaying the source-location information of the + * diagnostic, also include information about source ranges in a + * machine-parsable format. + * + * This option corresponds to the clang flag + * \c -fdiagnostics-print-source-range-info. + */ + CXDiagnostic_DisplaySourceRanges = 0x04 +}; + +/** + * \brief Display the given diagnostic by printing it to the given file. + * + * This routine will display the given diagnostic to a file, rendering + * the diagnostic according to the various options given. The + * \c clang_defaultDiagnosticDisplayOptions() function returns the set of + * options that most closely mimics the behavior of the clang compiler. + * + * \param Diagnostic The diagnostic to print. + * + * \param File The file to print to (e.g., \c stderr). + * + * \param Options A set of options that control the diagnostic display, + * created by combining \c CXDiagnosticDisplayOptions values. + */ +CINDEX_LINKAGE void clang_displayDiagnostic(CXDiagnostic Diagnostic, + FILE *File, + unsigned Options); + +/** + * \brief Retrieve the set of display options most similar to the + * default behavior of the clang compiler. + * + * \returns A set of display options suitable for use with \c + * clang_displayDiagnostic(). + */ +CINDEX_LINKAGE unsigned clang_defaultDiagnosticDisplayOptions(void); + +/** + * \brief Print a diagnostic to the given file. + */ + /** * \brief Determine the severity of the given diagnostic. */ @@ -1247,7 +1322,7 @@ CINDEX_LINKAGE void clang_getDefinitionSpellingAndExtent(CXCursor, unsigned *startColumn, unsigned *endLine, unsigned *endColumn); - +CINDEX_LINKAGE void clang_enableStackTraces(void); /** * @} */ diff --git a/lib/Basic/Diagnostic.cpp b/lib/Basic/Diagnostic.cpp index e92d1e56ca..c5c9ca7484 100644 --- a/lib/Basic/Diagnostic.cpp +++ b/lib/Basic/Diagnostic.cpp @@ -923,7 +923,7 @@ StoredDiagnostic::StoredDiagnostic() { } StoredDiagnostic::StoredDiagnostic(Diagnostic::Level Level, llvm::StringRef Message) - : Level(Level), Message(Message) { } + : Level(Level), Loc(), Message(Message) { } StoredDiagnostic::StoredDiagnostic(Diagnostic::Level Level, const DiagnosticInfo &Info) diff --git a/test/Index/cindex-on-invalid.m b/test/Index/cindex-on-invalid.m index 0f6bdffe91..651c40a335 100644 --- a/test/Index/cindex-on-invalid.m +++ b/test/Index/cindex-on-invalid.m @@ -1,6 +1,5 @@ // RUN: not c-index-test -test-load-source local %s > %t 2> %t.err // RUN: FileCheck %s < %t.err -// XFAIL: * // CHECK: error: expected identifier or '(' // CHECK: Unable to load translation unit! diff --git a/test/Index/code-complete-errors.c b/test/Index/code-complete-errors.c index 520a8c87df..29c2a86198 100644 --- a/test/Index/code-complete-errors.c +++ b/test/Index/code-complete-errors.c @@ -7,7 +7,7 @@ struct s { struct s s0 = { y: 5 }; // CHECK: code-complete-errors.c:7:20: warning: use of GNU old-style field designator extension // CHECK: FIX-IT: Replace [7:17 - 7:19] with ".y = " int f(int *ptr1, float *ptr2) { - return ptr1 != ptr2; // CHECK: code-complete-errors.c:10:15:[10:10 - 10:14][10:18 - 10:22]: warning: comparison of distinct pointer types ('int *' and 'float *') + return ptr1 != ptr2; // CHECK: code-complete-errors.c:10:15:{10:10-10:14}{10:18-10:22}: warning: comparison of distinct pointer types ('int *' and 'float *') } void g() { } diff --git a/tools/CIndex/CIndex.cpp b/tools/CIndex/CIndex.cpp index 61e9210aa5..5eddee45b2 100644 --- a/tools/CIndex/CIndex.cpp +++ b/tools/CIndex/CIndex.cpp @@ -27,6 +27,7 @@ #include "clang/Lex/Preprocessor.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/System/Program.h" +#include "llvm/System/Signals.h" // Needed to define L_TMPNAM on some systems. #include @@ -907,10 +908,13 @@ bool CursorVisitor::VisitAttributes(Decl *D) { } extern "C" { -CXIndex clang_createIndex(int excludeDeclarationsFromPCH) { +CXIndex clang_createIndex(int excludeDeclarationsFromPCH, + int displayDiagnostics) { CIndexer *CIdxr = new CIndexer(); if (excludeDeclarationsFromPCH) CIdxr->setOnlyLocalDecls(); + if (displayDiagnostics) + CIdxr->setDisplayDiagnostics(); return CIdxr; } @@ -997,8 +1001,18 @@ clang_createTranslationUnitFromSourceFile(CXIndex CIdx, // FIXME: Until we have broader testing, just drop the entire AST if we // encountered an error. - if (NumErrors != Diags->getNumErrors()) + if (NumErrors != Diags->getNumErrors()) { + if (CXXIdx->getDisplayDiagnostics()) { + for (ASTUnit::diag_iterator D = Unit->diag_begin(), + DEnd = Unit->diag_end(); + D != DEnd; ++D) { + CXStoredDiagnostic Diag(*D, Unit->getASTContext().getLangOptions()); + clang_displayDiagnostic(&Diag, stderr, + clang_defaultDiagnosticDisplayOptions()); + } + } return 0; + } return Unit.take(); } @@ -1089,18 +1103,35 @@ clang_createTranslationUnitFromSourceFile(CXIndex CIdx, RemappedFiles.data(), RemappedFiles.size(), /*CaptureDiagnostics=*/true); - if (ATU) - ATU->unlinkTemporaryFile(); - - // FIXME: Currently we don't report diagnostics on invalid ASTs. if (ATU) { LoadSerializedDiagnostics(DiagnosticsFile, num_unsaved_files, unsaved_files, ATU->getFileManager(), ATU->getSourceManager(), ATU->getDiagnostics()); + } else if (CXXIdx->getDisplayDiagnostics()) { + // We failed to load the ASTUnit, but we can still deserialize the + // diagnostics and emit them. + FileManager FileMgr; + SourceManager SourceMgr; + // FIXME: Faked LangOpts! + LangOptions LangOpts; + llvm::SmallVector Diags; + LoadSerializedDiagnostics(DiagnosticsFile, + num_unsaved_files, unsaved_files, + FileMgr, SourceMgr, Diags); + for (llvm::SmallVector::iterator D = Diags.begin(), + DEnd = Diags.end(); + D != DEnd; ++D) { + CXStoredDiagnostic Diag(*D, LangOpts); + clang_displayDiagnostic(&Diag, stderr, + clang_defaultDiagnosticDisplayOptions()); + } } + if (ATU) + ATU->unlinkTemporaryFile(); + for (unsigned i = 0, e = TemporaryFiles.size(); i != e; ++i) TemporaryFiles[i].eraseFromDisk(); @@ -1909,6 +1940,10 @@ void clang_getDefinitionSpellingAndExtent(CXCursor C, *endColumn = SM.getSpellingColumnNumber(Body->getRBracLoc()); } +void clang_enableStackTraces(void) { + llvm::sys::PrintStackTraceOnErrorSignal(); +} + } // end: extern "C" //===----------------------------------------------------------------------===// diff --git a/tools/CIndex/CIndex.exports b/tools/CIndex/CIndex.exports index 1c445b74aa..449bb95a94 100644 --- a/tools/CIndex/CIndex.exports +++ b/tools/CIndex/CIndex.exports @@ -5,12 +5,15 @@ _clang_codeCompleteGetNumDiagnostics _clang_createIndex _clang_createTranslationUnit _clang_createTranslationUnitFromSourceFile +_clang_defaultDiagnosticDisplayOptions +_clang_displayDiagnostic _clang_disposeCodeCompleteResults _clang_disposeDiagnostic _clang_disposeIndex _clang_disposeString _clang_disposeTokens _clang_disposeTranslationUnit +_clang_enableStackTraces _clang_equalCursors _clang_equalLocations _clang_getClangVersion diff --git a/tools/CIndex/CIndexCodeCompletion.cpp b/tools/CIndex/CIndexCodeCompletion.cpp index 9e8946381a..08510f2e55 100644 --- a/tools/CIndex/CIndexCodeCompletion.cpp +++ b/tools/CIndex/CIndexCodeCompletion.cpp @@ -177,6 +177,9 @@ static bool ReadUnsigned(const char *&Memory, const char *MemoryEnd, /// \brief The CXCodeCompleteResults structure we allocate internally; /// the client only sees the initial CXCodeCompleteResults structure. struct AllocatedCXCodeCompleteResults : public CXCodeCompleteResults { + AllocatedCXCodeCompleteResults(); + ~AllocatedCXCodeCompleteResults(); + /// \brief The memory buffer from which we parsed the results. We /// retain this buffer because the completion strings point into it. llvm::MemoryBuffer *Buffer; @@ -194,6 +197,16 @@ struct AllocatedCXCodeCompleteResults : public CXCodeCompleteResults { FileManager FileMgr; }; +AllocatedCXCodeCompleteResults::AllocatedCXCodeCompleteResults() + : CXCodeCompleteResults(), Buffer(0) { } + +AllocatedCXCodeCompleteResults::~AllocatedCXCodeCompleteResults() { + for (unsigned I = 0, N = NumResults; I != N; ++I) + delete (CodeCompletionString *)Results[I].CompletionString; + delete [] Results; + delete Buffer; +} + CXCodeCompleteResults *clang_codeComplete(CXIndex CIdx, const char *source_filename, int num_command_line_args, @@ -368,15 +381,6 @@ void clang_disposeCodeCompleteResults(CXCodeCompleteResults *ResultsIn) { AllocatedCXCodeCompleteResults *Results = static_cast(ResultsIn); - - for (unsigned I = 0, N = Results->NumResults; I != N; ++I) - delete (CXCompletionString *)Results->Results[I].CompletionString; - delete [] Results->Results; - - Results->Results = 0; - Results->NumResults = 0; - delete Results->Buffer; - Results->Buffer = 0; delete Results; } diff --git a/tools/CIndex/CIndexDiagnostic.cpp b/tools/CIndex/CIndexDiagnostic.cpp index 70676f0e14..07c1983672 100644 --- a/tools/CIndex/CIndexDiagnostic.cpp +++ b/tools/CIndex/CIndexDiagnostic.cpp @@ -47,6 +47,81 @@ void clang_disposeDiagnostic(CXDiagnostic Diagnostic) { delete Stored; } +void clang_displayDiagnostic(CXDiagnostic Diagnostic, FILE *Out, + unsigned Options) { + if (!Diagnostic || !Out) + return; + + CXDiagnosticSeverity Severity = clang_getDiagnosticSeverity(Diagnostic); + + // Ignore diagnostics that should be ignored. + if (Severity == CXDiagnostic_Ignored) + return; + + if (Options & CXDiagnostic_DisplaySourceLocation) { + // Print source location (file:line), along with optional column + // and source ranges. + CXFile File; + unsigned Line, Column; + clang_getInstantiationLocation(clang_getDiagnosticLocation(Diagnostic), + &File, &Line, &Column, 0); + if (File) { + CXString FName = clang_getFileName(File); + fprintf(Out, "%s:%d:", clang_getCString(FName), Line); + clang_disposeString(FName); + if (Options & CXDiagnostic_DisplayColumn) + fprintf(Out, "%d:", Column); + + if (Options & CXDiagnostic_DisplaySourceRanges) { + unsigned N = clang_getDiagnosticNumRanges(Diagnostic); + bool PrintedRange = false; + for (unsigned I = 0; I != N; ++I) { + CXFile StartFile, EndFile; + CXSourceRange Range = clang_getDiagnosticRange(Diagnostic, I); + + unsigned StartLine, StartColumn, EndLine, EndColumn; + clang_getInstantiationLocation(clang_getRangeStart(Range), + &StartFile, &StartLine, &StartColumn, + 0); + clang_getInstantiationLocation(clang_getRangeEnd(Range), + &EndFile, &EndLine, &EndColumn, 0); + + if (StartFile != EndFile || StartFile != File) + continue; + + fprintf(Out, "{%d:%d-%d:%d}", StartLine, StartColumn, + EndLine, EndColumn); + PrintedRange = true; + } + if (PrintedRange) + fprintf(Out, ":"); + } + } + + fprintf(Out, " "); + } + + /* 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; + } + + CXString Text = clang_getDiagnosticSpelling(Diagnostic); + if (clang_getCString(Text)) + fprintf(Out, "%s\n", clang_getCString(Text)); + else + fprintf(Out, "\n"); + clang_disposeString(Text); +} + +unsigned clang_defaultDiagnosticDisplayOptions() { + return CXDiagnostic_DisplaySourceLocation | CXDiagnostic_DisplayColumn; +} + enum CXDiagnosticSeverity clang_getDiagnosticSeverity(CXDiagnostic Diag) { CXStoredDiagnostic *StoredDiag = static_cast(Diag); if (!StoredDiag) @@ -204,15 +279,18 @@ void clang::LoadSerializedDiagnostics(const llvm::sys::Path &DiagnosticsPath, Diags.push_back(StoredDiagnostic(Diagnostic::Fatal, (Twine("could not remap from missing file ") + unsaved_files[I].Filename).str())); + delete F; return; } MemoryBuffer *Buffer = MemoryBuffer::getMemBuffer(unsaved_files[I].Contents, unsaved_files[I].Contents + unsaved_files[I].Length); - if (!Buffer) + if (!Buffer) { + delete F; return; - + } + SourceMgr.overrideFileContents(File, Buffer); } @@ -224,8 +302,9 @@ void clang::LoadSerializedDiagnostics(const llvm::sys::Path &DiagnosticsPath, StoredDiagnostic Stored = StoredDiagnostic::Deserialize(FileMgr, SourceMgr, Memory, MemoryEnd); if (!Stored) - return; + break; Diags.push_back(Stored); } + delete F; } diff --git a/tools/CIndex/CIndexer.h b/tools/CIndex/CIndexer.h index d559f13864..1fa3ca9387 100644 --- a/tools/CIndex/CIndexer.h +++ b/tools/CIndex/CIndexer.h @@ -34,11 +34,14 @@ namespace cxstring { class CIndexer { bool UseExternalASTGeneration; bool OnlyLocalDecls; - + bool DisplayDiagnostics; + llvm::sys::Path ClangPath; public: - CIndexer() : UseExternalASTGeneration(false), OnlyLocalDecls(false) { } + 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 @@ -46,6 +49,11 @@ public: bool getOnlyLocalDecls() const { return OnlyLocalDecls; } void setOnlyLocalDecls(bool Local = true) { OnlyLocalDecls = Local; } + bool getDisplayDiagnostics() const { return DisplayDiagnostics; } + void setDisplayDiagnostics(bool Display = true) { + DisplayDiagnostics = Display; + } + bool getUseExternalASTGeneration() const { return UseExternalASTGeneration; } void setUseExternalASTGeneration(bool Value) { UseExternalASTGeneration = Value; diff --git a/tools/c-index-test/c-index-test.c b/tools/c-index-test/c-index-test.c index b983d3a4de..c5f8431c34 100644 --- a/tools/c-index-test/c-index-test.c +++ b/tools/c-index-test/c-index-test.c @@ -198,120 +198,73 @@ typedef void (*PostVisitTU)(CXTranslationUnit); void PrintDiagnostic(CXDiagnostic Diagnostic) { FILE *out = stderr; CXFile file; - unsigned line, column; CXString text; - enum CXDiagnosticSeverity severity = clang_getDiagnosticSeverity(Diagnostic); + unsigned display_opts = CXDiagnostic_DisplaySourceLocation + | CXDiagnostic_DisplayColumn | CXDiagnostic_DisplaySourceRanges; + unsigned i, num_fixits; - /* Ignore diagnostics that should be ignored. */ - if (severity == CXDiagnostic_Ignored) + clang_displayDiagnostic(Diagnostic, out, display_opts); + if (clang_getDiagnosticSeverity(Diagnostic) == CXDiagnostic_Ignored) return; - /* Print file:line:column. */ clang_getInstantiationLocation(clang_getDiagnosticLocation(Diagnostic), - &file, &line, &column, 0); - if (file) { - unsigned i, n; - unsigned printed_any_ranges = 0; - CXString fname; - - fname = clang_getFileName(file); - fprintf(out, "%s:%d:%d:", clang_getCString(fname), line, column); - clang_disposeString(fname); + &file, 0, 0, 0); + if (!file) + return; - n = clang_getDiagnosticNumRanges(Diagnostic); - for (i = 0; i != n; ++i) { + num_fixits = clang_getDiagnosticNumFixIts(Diagnostic); + for (i = 0; i != num_fixits; ++i) { + switch (clang_getDiagnosticFixItKind(Diagnostic, i)) { + case CXFixIt_Insertion: { + CXSourceLocation insertion_loc; + CXFile insertion_file; + unsigned insertion_line, insertion_column; + text = clang_getDiagnosticFixItInsertion(Diagnostic, i, &insertion_loc); + clang_getInstantiationLocation(insertion_loc, &insertion_file, + &insertion_line, &insertion_column, 0); + if (insertion_file == file) + fprintf(out, "FIX-IT: Insert \"%s\" at %d:%d\n", + clang_getCString(text), insertion_line, insertion_column); + clang_disposeString(text); + break; + } + + case CXFixIt_Removal: { CXFile start_file, end_file; - CXSourceRange range = clang_getDiagnosticRange(Diagnostic, i); - unsigned start_line, start_column, end_line, end_column; - clang_getInstantiationLocation(clang_getRangeStart(range), - &start_file, &start_line, &start_column,0); - clang_getInstantiationLocation(clang_getRangeEnd(range), + CXSourceRange remove_range + = clang_getDiagnosticFixItRemoval(Diagnostic, i); + clang_getInstantiationLocation(clang_getRangeStart(remove_range), + &start_file, &start_line, &start_column, + 0); + clang_getInstantiationLocation(clang_getRangeEnd(remove_range), &end_file, &end_line, &end_column, 0); - - if (start_file != end_file || start_file != file) - continue; - - PrintExtent(out, start_line, start_column, end_line, end_column); - printed_any_ranges = 1; - } - if (printed_any_ranges) - fprintf(out, ":"); - - fprintf(out, " "); - } - - /* 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, "\n"); - clang_disposeString(text); - - if (file) { - unsigned i, num_fixits = clang_getDiagnosticNumFixIts(Diagnostic); - for (i = 0; i != num_fixits; ++i) { - switch (clang_getDiagnosticFixItKind(Diagnostic, i)) { - case CXFixIt_Insertion: { - CXSourceLocation insertion_loc; - CXFile insertion_file; - unsigned insertion_line, insertion_column; - text = clang_getDiagnosticFixItInsertion(Diagnostic, i, &insertion_loc); - clang_getInstantiationLocation(insertion_loc, &insertion_file, - &insertion_line, &insertion_column, 0); - if (insertion_file == file) - fprintf(out, "FIX-IT: Insert \"%s\" at %d:%d\n", - clang_getCString(text), insertion_line, insertion_column); - clang_disposeString(text); - break; - } - - case CXFixIt_Removal: { - CXFile start_file, end_file; - unsigned start_line, start_column, end_line, end_column; - CXSourceRange remove_range - = clang_getDiagnosticFixItRemoval(Diagnostic, i); - clang_getInstantiationLocation(clang_getRangeStart(remove_range), - &start_file, &start_line, &start_column, - 0); - clang_getInstantiationLocation(clang_getRangeEnd(remove_range), - &end_file, &end_line, &end_column, 0); - if (start_file == file && end_file == file) { - fprintf(out, "FIX-IT: Remove "); - PrintExtent(out, start_line, start_column, end_line, end_column); - fprintf(out, "\n"); - } - break; - } - - case CXFixIt_Replacement: { - CXFile start_file, end_file; - unsigned start_line, start_column, end_line, end_column; - CXSourceRange remove_range; - text = clang_getDiagnosticFixItReplacement(Diagnostic, i,&remove_range); - clang_getInstantiationLocation(clang_getRangeStart(remove_range), - &start_file, &start_line, &start_column, - 0); - clang_getInstantiationLocation(clang_getRangeEnd(remove_range), - &end_file, &end_line, &end_column, 0); - if (start_file == end_file) { - fprintf(out, "FIX-IT: Replace "); - PrintExtent(out, start_line, start_column, end_line, end_column); - fprintf(out, " with \"%s\"\n", clang_getCString(text)); - } - clang_disposeString(text); - break; + if (start_file == file && end_file == file) { + fprintf(out, "FIX-IT: Remove "); + PrintExtent(out, start_line, start_column, end_line, end_column); + fprintf(out, "\n"); } + break; + } + + case CXFixIt_Replacement: { + CXFile start_file, end_file; + unsigned start_line, start_column, end_line, end_column; + CXSourceRange remove_range; + text = clang_getDiagnosticFixItReplacement(Diagnostic, i,&remove_range); + clang_getInstantiationLocation(clang_getRangeStart(remove_range), + &start_file, &start_line, &start_column, + 0); + clang_getInstantiationLocation(clang_getRangeEnd(remove_range), + &end_file, &end_line, &end_column, 0); + if (start_file == end_file) { + fprintf(out, "FIX-IT: Replace "); + PrintExtent(out, start_line, start_column, end_line, end_column); + fprintf(out, " with \"%s\"\n", clang_getCString(text)); } + clang_disposeString(text); + break; + } } } } @@ -534,7 +487,8 @@ int perform_test_load_tu(const char *file, const char *filter, CXTranslationUnit TU; int result; Idx = clang_createIndex(/* excludeDeclsFromPCH */ - !strcmp(filter, "local") ? 1 : 0); + !strcmp(filter, "local") ? 1 : 0, + /* displayDiagnosics=*/1); if (!CreateTranslationUnit(Idx, file, &TU)) { clang_disposeIndex(Idx); @@ -558,7 +512,8 @@ int perform_test_load_source(int argc, const char **argv, int result; Idx = clang_createIndex(/* excludeDeclsFromPCH */ - !strcmp(filter, "local") ? 1 : 0); + !strcmp(filter, "local") ? 1 : 0, + /* displayDiagnosics=*/1); if (UseExternalASTs && strlen(UseExternalASTs)) clang_setUseExternalASTGeneration(Idx, 1); @@ -612,7 +567,8 @@ static int perform_file_scan(const char *ast_file, const char *source_file, unsigned line = 1, col = 1; unsigned start_line = 1, start_col = 1; - if (!(Idx = clang_createIndex(/* excludeDeclsFromPCH */ 1))) { + if (!(Idx = clang_createIndex(/* excludeDeclsFromPCH */ 1, + /* displayDiagnosics=*/1))) { fprintf(stderr, "Could not create Index\n"); return 1; } @@ -813,7 +769,7 @@ int perform_code_completion(int argc, const char **argv) { if (parse_remapped_files(argc, argv, 2, &unsaved_files, &num_unsaved_files)) return -1; - CIdx = clang_createIndex(0); + CIdx = clang_createIndex(0, 1); results = clang_codeComplete(CIdx, argv[argc - 1], argc - num_unsaved_files - 3, argv + num_unsaved_files + 2, @@ -877,7 +833,7 @@ int inspect_cursor_at(int argc, const char **argv) { &num_unsaved_files)) return -1; - CIdx = clang_createIndex(0); + CIdx = clang_createIndex(0, 1); TU = clang_createTranslationUnitFromSourceFile(CIdx, argv[argc - 1], argc - num_unsaved_files - 2 - NumLocations, argv + num_unsaved_files + 1 + NumLocations, @@ -935,7 +891,7 @@ int perform_token_annotation(int argc, const char **argv) { if (parse_remapped_files(argc, argv, 2, &unsaved_files, &num_unsaved_files)) return -1; - CIdx = clang_createIndex(0); + CIdx = clang_createIndex(0, 1); TU = clang_createTranslationUnitFromSourceFile(CIdx, argv[argc - 1], argc - num_unsaved_files - 3, argv + num_unsaved_files + 2, @@ -1053,6 +1009,7 @@ static void print_usage(void) { } int main(int argc, const char **argv) { + clang_enableStackTraces(); if (argc > 2 && strstr(argv[1], "-code-completion-at=") == argv[1]) return perform_code_completion(argc, argv); if (argc > 2 && strstr(argv[1], "-cursor-at=") == argv[1])