From d770f73facd5cca11567b651c0dda86dc2bc96ea Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Mon, 22 Feb 2010 23:17:23 +0000 Subject: [PATCH] Rework the CIndex API for displaying diagnostics. Instead of printing the diagnostics to a FILE*, return a CXString containing the formatted diagnostic. llvm-svn: 96823 --- clang/include/clang-c/Index.h | 13 ++++--- clang/tools/CIndex/CIndex.cpp | 25 +++++++++++--- clang/tools/CIndex/CIndex.exports | 2 +- clang/tools/CIndex/CIndexDiagnostic.cpp | 46 ++++++++++++------------- clang/tools/c-index-test/c-index-test.c | 8 +++-- 5 files changed, 56 insertions(+), 38 deletions(-) diff --git a/clang/include/clang-c/Index.h b/clang/include/clang-c/Index.h index 5426256d43ac..6d1a02fb4f73 100644 --- a/clang/include/clang-c/Index.h +++ b/clang/include/clang-c/Index.h @@ -460,23 +460,22 @@ enum CXDiagnosticDisplayOptions { }; /** - * \brief Display the given diagnostic by printing it to the given file. + * \brief Format the given diagnostic in a manner that is suitable for display. * - * This routine will display the given diagnostic to a file, rendering + * This routine will format the given diagnostic to a string, 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. + * + * \returns A new string containing for formatted diagnostic. */ -CINDEX_LINKAGE void clang_displayDiagnostic(CXDiagnostic Diagnostic, - FILE *File, - unsigned Options); +CINDEX_LINKAGE CXString clang_formatDiagnostic(CXDiagnostic Diagnostic, + unsigned Options); /** * \brief Retrieve the set of display options most similar to the diff --git a/clang/tools/CIndex/CIndex.cpp b/clang/tools/CIndex/CIndex.cpp index f74daf8e8892..d95aaee770c0 100644 --- a/clang/tools/CIndex/CIndex.cpp +++ b/clang/tools/CIndex/CIndex.cpp @@ -1007,9 +1007,17 @@ clang_createTranslationUnitFromSourceFile(CXIndex CIdx, DEnd = Unit->diag_end(); D != DEnd; ++D) { CXStoredDiagnostic Diag(*D, Unit->getASTContext().getLangOptions()); - clang_displayDiagnostic(&Diag, stderr, - clang_defaultDiagnosticDisplayOptions()); + CXString Msg = clang_formatDiagnostic(&Diag, + clang_defaultDiagnosticDisplayOptions()); + fprintf(stderr, "%s\n", clang_getCString(Msg)); + clang_disposeString(Msg); } +#ifdef LLVM_ON_WIN32 + // On Windows, force a flush, since there may be multiple copies of + // stderr and stdout in the file system, all with different buffers + // but writing to the same device. + fflush(stderr); +#endif } return 0; } @@ -1124,9 +1132,18 @@ clang_createTranslationUnitFromSourceFile(CXIndex CIdx, DEnd = Diags.end(); D != DEnd; ++D) { CXStoredDiagnostic Diag(*D, LangOpts); - clang_displayDiagnostic(&Diag, stderr, - clang_defaultDiagnosticDisplayOptions()); + CXString Msg = clang_formatDiagnostic(&Diag, + clang_defaultDiagnosticDisplayOptions()); + fprintf(stderr, "%s\n", clang_getCString(Msg)); + clang_disposeString(Msg); } + +#ifdef LLVM_ON_WIN32 + // On Windows, force a flush, since there may be multiple copies of + // stderr and stdout in the file system, all with different buffers + // but writing to the same device. + fflush(stderr); +#endif } if (ATU) { diff --git a/clang/tools/CIndex/CIndex.exports b/clang/tools/CIndex/CIndex.exports index e32e9d598cdf..743317dc1214 100644 --- a/clang/tools/CIndex/CIndex.exports +++ b/clang/tools/CIndex/CIndex.exports @@ -6,7 +6,6 @@ _clang_createIndex _clang_createTranslationUnit _clang_createTranslationUnitFromSourceFile _clang_defaultDiagnosticDisplayOptions -_clang_displayDiagnostic _clang_disposeCodeCompleteResults _clang_disposeDiagnostic _clang_disposeIndex @@ -16,6 +15,7 @@ _clang_disposeTranslationUnit _clang_enableStackTraces _clang_equalCursors _clang_equalLocations +_clang_formatDiagnostic _clang_getClangVersion _clang_getCString _clang_getCompletionChunkCompletionString diff --git a/clang/tools/CIndex/CIndexDiagnostic.cpp b/clang/tools/CIndex/CIndexDiagnostic.cpp index 75da335afc29..6aed49eaaee4 100644 --- a/clang/tools/CIndex/CIndexDiagnostic.cpp +++ b/clang/tools/CIndex/CIndexDiagnostic.cpp @@ -15,8 +15,10 @@ #include "CXSourceLocation.h" #include "clang/Frontend/FrontendDiagnostic.h" +#include "llvm/ADT/SmallString.h" #include "llvm/ADT/Twine.h" #include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/raw_ostream.h" using namespace clang; using namespace clang::cxloc; @@ -47,17 +49,19 @@ void clang_disposeDiagnostic(CXDiagnostic Diagnostic) { delete Stored; } -void clang_displayDiagnostic(CXDiagnostic Diagnostic, FILE *Out, - unsigned Options) { - if (!Diagnostic || !Out) - return; +CXString clang_formatDiagnostic(CXDiagnostic Diagnostic, unsigned Options) { + if (!Diagnostic) + return createCXString(""); CXDiagnosticSeverity Severity = clang_getDiagnosticSeverity(Diagnostic); // Ignore diagnostics that should be ignored. if (Severity == CXDiagnostic_Ignored) - return; + return createCXString(""); + llvm::SmallString<256> Str; + llvm::raw_svector_ostream Out(Str); + if (Options & CXDiagnostic_DisplaySourceLocation) { // Print source location (file:line), along with optional column // and source ranges. @@ -67,10 +71,10 @@ void clang_displayDiagnostic(CXDiagnostic Diagnostic, FILE *Out, &File, &Line, &Column, 0); if (File) { CXString FName = clang_getFileName(File); - fprintf(Out, "%s:%d:", clang_getCString(FName), Line); + Out << clang_getCString(FName) << ":" << Line << ":"; clang_disposeString(FName); if (Options & CXDiagnostic_DisplayColumn) - fprintf(Out, "%d:", Column); + Out << Column << ":"; if (Options & CXDiagnostic_DisplaySourceRanges) { unsigned N = clang_getDiagnosticNumRanges(Diagnostic); @@ -89,40 +93,34 @@ void clang_displayDiagnostic(CXDiagnostic Diagnostic, FILE *Out, if (StartFile != EndFile || StartFile != File) continue; - fprintf(Out, "{%d:%d-%d:%d}", StartLine, StartColumn, - EndLine, EndColumn); + Out << "{" << StartLine << ":" << StartColumn << "-" + << EndLine << ":" << EndColumn << "}"; PrintedRange = true; } if (PrintedRange) - fprintf(Out, ":"); + Out << ":"; } } - fprintf(Out, " "); + 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; + case CXDiagnostic_Note: Out << "note: "; break; + case CXDiagnostic_Warning: Out << "warning: "; break; + case CXDiagnostic_Error: Out << "error: "; break; + case CXDiagnostic_Fatal: Out << "fatal error: "; break; } CXString Text = clang_getDiagnosticSpelling(Diagnostic); if (clang_getCString(Text)) - fprintf(Out, "%s\n", clang_getCString(Text)); + Out << clang_getCString(Text); else - fprintf(Out, "\n"); + Out << ""; clang_disposeString(Text); - -#ifdef LLVM_ON_WIN32 - // On Windows, force a flush, since there may be multiple copies of - // stderr and stdout in the file system, all with different buffers - // but writing to the same device. - fflush(Out); -#endif + return createCXString(Out.str(), true); } unsigned clang_defaultDiagnosticDisplayOptions() { diff --git a/clang/tools/c-index-test/c-index-test.c b/clang/tools/c-index-test/c-index-test.c index 2207364266f4..34bb99024654 100644 --- a/clang/tools/c-index-test/c-index-test.c +++ b/clang/tools/c-index-test/c-index-test.c @@ -198,14 +198,18 @@ typedef void (*PostVisitTU)(CXTranslationUnit); void PrintDiagnostic(CXDiagnostic Diagnostic) { FILE *out = stderr; CXFile file; + CXString Msg; unsigned display_opts = CXDiagnostic_DisplaySourceLocation | CXDiagnostic_DisplayColumn | CXDiagnostic_DisplaySourceRanges; unsigned i, num_fixits; - - clang_displayDiagnostic(Diagnostic, out, display_opts); + if (clang_getDiagnosticSeverity(Diagnostic) == CXDiagnostic_Ignored) return; + Msg = clang_formatDiagnostic(Diagnostic, display_opts); + fprintf(stderr, "%s\n", clang_getCString(Msg)); + clang_disposeString(Msg); + clang_getInstantiationLocation(clang_getDiagnosticLocation(Diagnostic), &file, 0, 0, 0); if (!file)