From: Douglas Gregor Date: Fri, 29 Jan 2010 00:41:11 +0000 (+0000) Subject: When printing diagnostics in c-index-test, also print source ranges X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=51c6d384551674facc19f745ecf6e289d28dc55f;p=clang When printing diagnostics in c-index-test, also print source ranges and fix-it information, so we can see everything in one place. Along the way, fix a few bugs with deserialization and query of diagnostics in CIndex. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@94768 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Basic/Diagnostic.h b/include/clang/Basic/Diagnostic.h index 1f7cd07c60..d2516f8695 100644 --- a/include/clang/Basic/Diagnostic.h +++ b/include/clang/Basic/Diagnostic.h @@ -482,7 +482,7 @@ private: /// DiagRanges - The list of ranges added to this diagnostic. It currently /// only support 10 ranges, could easily be extended if needed. - const SourceRange *DiagRanges[10]; + SourceRange DiagRanges[10]; enum { MaxCodeModificationHints = 3 }; @@ -609,7 +609,7 @@ public: sizeof(DiagObj->DiagRanges)/sizeof(DiagObj->DiagRanges[0]) && "Too many arguments to diagnostic!"); if (DiagObj) - DiagObj->DiagRanges[NumRanges++] = &R; + DiagObj->DiagRanges[NumRanges++] = R; } void AddCodeModificationHint(const CodeModificationHint &Hint) const { @@ -772,9 +772,9 @@ public: return DiagObj->NumDiagRanges; } - const SourceRange &getRange(unsigned Idx) const { + SourceRange getRange(unsigned Idx) const { assert(Idx < DiagObj->NumDiagRanges && "Invalid diagnostic range index!"); - return *DiagObj->DiagRanges[Idx]; + return DiagObj->DiagRanges[Idx]; } unsigned getNumCodeModificationHints() const { diff --git a/test/Index/code-complete-errors.c b/test/Index/code-complete-errors.c index 43bc5d8a1a..ecd56aa40f 100644 --- a/test/Index/code-complete-errors.c +++ b/test/Index/code-complete-errors.c @@ -1,16 +1,16 @@ _Complex cd; // CHECK: code-complete-errors.c:1:1: warning: plain '_Complex' requires a type specifier; assuming '_Complex double' - +// CHECK: FIX-IT: Insert " double" at 1:9 struct s { - int x, y;; -}; + int x, y;; // CHECK: code-complete-errors.c:4:12: warning: extra ';' inside a struct or union +}; // CHECK: FIX-IT: Remove 4:12-4:13 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: 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() { } -// RUN: c-index-test -code-completion-at=%s:13:12 %s 2> %t +// RUN: c-index-test -code-completion-at=%s:13:12 -pedantic %s 2> %t // RUN: FileCheck -check-prefix=CHECK %s < %t diff --git a/tools/CIndex/CIndexDiagnostic.cpp b/tools/CIndex/CIndexDiagnostic.cpp index eb039dff6e..52de8bbc91 100644 --- a/tools/CIndex/CIndexDiagnostic.cpp +++ b/tools/CIndex/CIndexDiagnostic.cpp @@ -154,12 +154,21 @@ enum CXFixItKind clang_getDiagnosticFixItKind(CXDiagnostic Diag, CXString clang_getDiagnosticFixItInsertion(CXDiagnostic Diag, unsigned FixIt, CXSourceLocation *Location) { + if (Location) + *Location = clang_getNullLocation(); + CXStoredDiagnostic *StoredDiag = static_cast(Diag); if (!StoredDiag || FixIt >= StoredDiag->Info.getNumCodeModificationHints()) return CIndexer::createCXString(""); const CodeModificationHint &Hint = StoredDiag->Info.getCodeModificationHint(FixIt); + + if (Location && StoredDiag->Info.getLocation().isValid()) + *Location = translateSourceLocation( + StoredDiag->Info.getLocation().getManager(), + StoredDiag->LangOpts, + Hint.InsertionLoc); return CIndexer::createCXString(Hint.CodeToInsert); } @@ -180,6 +189,9 @@ CXSourceRange clang_getDiagnosticFixItRemoval(CXDiagnostic Diag, CXString clang_getDiagnosticFixItReplacement(CXDiagnostic Diag, unsigned FixIt, CXSourceRange *Range) { + if (Range) + *Range = clang_getNullRange(); + CXStoredDiagnostic *StoredDiag = static_cast(Diag); if (!StoredDiag || FixIt >= StoredDiag->Info.getNumCodeModificationHints() || StoredDiag->Info.getLocation().isInvalid()) { diff --git a/tools/c-index-test/c-index-test.c b/tools/c-index-test/c-index-test.c index d4bc008369..658412c75a 100644 --- a/tools/c-index-test/c-index-test.c +++ b/tools/c-index-test/c-index-test.c @@ -195,8 +195,36 @@ static void PrintDiagnosticCallback(CXDiagnostic Diagnostic, /* 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); + if (file) { + CXSourceRange *ranges = 0; + unsigned num_ranges; + unsigned i; + unsigned printed_any_ranges = 0; + + fprintf(out, "%s:%d:%d:", clang_getFileName(file), line, column); + + clang_getDiagnosticRanges(Diagnostic, &ranges, &num_ranges); + for (i = 0; i != num_ranges; ++i) { + CXFile start_file, end_file; + unsigned start_line, start_column, end_line, end_column; + clang_getInstantiationLocation(clang_getRangeStart(ranges[i]), + &start_file, &start_line, &start_column,0); + clang_getInstantiationLocation(clang_getRangeEnd(ranges[i]), + &end_file, &end_line, &end_column, 0); + + if (start_file != end_file || start_file != file) + continue; + + fprintf(out, "{%d:%d-%d:%d}", start_line, start_column, end_line, + end_column+1); + printed_any_ranges = 1; + } + clang_disposeDiagnosticRanges(ranges, num_ranges); + if (printed_any_ranges) + fprintf(out, ":"); + + fprintf(out, " "); + } /* Print warning/error/etc. */ switch (severity) { @@ -213,6 +241,61 @@ static void PrintDiagnosticCallback(CXDiagnostic Diagnostic, 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 %d:%d-%d:%d\n", + start_line, start_column, end_line, end_column+1); + 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 %d:%d-%d:%d with \"%s\"\n", + start_line, start_column, end_line, end_column+1, + clang_getCString(text)); + clang_disposeString(text); + break; + } + } + } + } } /******************************************************************************/