Rework the CIndex API for displaying diagnostics. Instead of printing
the diagnostics to a FILE*, return a CXString containing the formatted
diagnostic.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@96823 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/tools/CIndex/CIndex.cpp b/tools/CIndex/CIndex.cpp
index f74daf8..d95aaee 100644
--- a/tools/CIndex/CIndex.cpp
+++ b/tools/CIndex/CIndex.cpp
@@ -1007,9 +1007,17 @@
                                  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 @@
                                                        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/tools/CIndex/CIndex.exports b/tools/CIndex/CIndex.exports
index e32e9d5..743317d 100644
--- a/tools/CIndex/CIndex.exports
+++ b/tools/CIndex/CIndex.exports
@@ -6,7 +6,6 @@
 _clang_createTranslationUnit
 _clang_createTranslationUnitFromSourceFile
 _clang_defaultDiagnosticDisplayOptions
-_clang_displayDiagnostic
 _clang_disposeCodeCompleteResults
 _clang_disposeDiagnostic
 _clang_disposeIndex
@@ -16,6 +15,7 @@
 _clang_enableStackTraces
 _clang_equalCursors
 _clang_equalLocations
+_clang_formatDiagnostic
 _clang_getClangVersion
 _clang_getCString
 _clang_getCompletionChunkCompletionString
diff --git a/tools/CIndex/CIndexDiagnostic.cpp b/tools/CIndex/CIndexDiagnostic.cpp
index 75da335..6aed49e 100644
--- a/tools/CIndex/CIndexDiagnostic.cpp
+++ b/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 @@
   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 @@
                                    &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 @@
           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, "<no diagnostic text>\n");
+    Out << "<no diagnostic text>";
   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() {