Rework how CIndex handles diagnostics. Rather than using a callback,
we attach diagnostics to translation units and code-completion
results, so they can be queried at any time.

To facilitate this, the new StoredDiagnostic class stores a diagnostic
in a serializable/deserializable form, and ASTUnit knows how to
capture diagnostics in this stored form. CIndex's CXDiagnostic is a
thin wrapper around StoredDiagnostic, providing a C interface to
stored or de-serialized diagnostics.

I've XFAIL'd one test case temporarily, because currently we end up
storing diagnostics in an ASTUnit that's never returned to the user
(because it contains errors). I'll introduce a temporary fix for this
soon; the real fix will be to allow us to return and query invalid ASTs.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@96592 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/tools/c-index-test/c-index-test.c b/tools/c-index-test/c-index-test.c
index 640375a..b983d3a 100644
--- a/tools/c-index-test/c-index-test.c
+++ b/tools/c-index-test/c-index-test.c
@@ -28,10 +28,6 @@
 extern char *basename(const char *);
 #endif
 
-static void PrintDiagnosticCallback(CXDiagnostic Diagnostic,
-                                    CXClientData ClientData);
-
-
 static void PrintExtent(FILE *out, unsigned begin_line, unsigned begin_column,
                         unsigned end_line, unsigned end_column) {
   fprintf(out, "[%d:%d - %d:%d]", begin_line, begin_column,
@@ -41,7 +37,7 @@
 static unsigned CreateTranslationUnit(CXIndex Idx, const char *file,
                                       CXTranslationUnit *TU) {
 
-  *TU = clang_createTranslationUnit(Idx, file, PrintDiagnosticCallback, stderr);
+  *TU = clang_createTranslationUnit(Idx, file);
   if (!TU) {
     fprintf(stderr, "Unable to load translation unit from '%s'!\n", file);
     return 0;
@@ -199,9 +195,8 @@
 
 typedef void (*PostVisitTU)(CXTranslationUnit);
 
-static void PrintDiagnosticCallback(CXDiagnostic Diagnostic,
-                                    CXClientData ClientData) {
-  FILE *out = (FILE *)ClientData;
+void PrintDiagnostic(CXDiagnostic Diagnostic) {
+  FILE *out = stderr;
   CXFile file;
   unsigned line, column;
   CXString text;
@@ -321,6 +316,15 @@
   }
 }
 
+void PrintDiagnostics(CXTranslationUnit TU) {
+  int i, n = clang_getNumDiagnostics(TU);
+  for (i = 0; i != n; ++i) {
+    CXDiagnostic Diag = clang_getDiagnostic(TU, i);
+    PrintDiagnostic(Diag);
+    clang_disposeDiagnostic(Diag);
+  }
+}
+
 /******************************************************************************/
 /* Logic for testing traversal.                                               */
 /******************************************************************************/
@@ -518,6 +522,7 @@
   if (PV)
     PV(TU);
 
+  PrintDiagnostics(TU);
   clang_disposeTranslationUnit(TU);
   return 0;
 }
@@ -567,9 +572,7 @@
                                                  argc - num_unsaved_files,
                                                  argv + num_unsaved_files,
                                                  num_unsaved_files,
-                                                 unsaved_files,
-                                                 PrintDiagnosticCallback,
-                                                 stderr);
+                                                 unsaved_files);
   if (!TU) {
     fprintf(stderr, "Unable to load translation unit!\n");
     clang_disposeIndex(Idx);
@@ -815,13 +818,18 @@
                                argv[argc - 1], argc - num_unsaved_files - 3,
                                argv + num_unsaved_files + 2,
                                num_unsaved_files, unsaved_files,
-                               filename, line, column,
-                               PrintDiagnosticCallback, stderr);
+                               filename, line, column);
 
   if (results) {
     unsigned i, n = results->NumResults;
     for (i = 0; i != n; ++i)
       print_completion_result(results->Results + i, stdout);
+    n = clang_codeCompleteGetNumDiagnostics(results);
+    for (i = 0; i != n; ++i) {
+      CXDiagnostic diag = clang_codeCompleteGetDiagnostic(results, i);
+      PrintDiagnostic(diag);
+      clang_disposeDiagnostic(diag);
+    }
     clang_disposeCodeCompleteResults(results);
   }
 
@@ -874,9 +882,7 @@
                                   argc - num_unsaved_files - 2 - NumLocations,
                                    argv + num_unsaved_files + 1 + NumLocations,
                                                  num_unsaved_files,
-                                                 unsaved_files,
-                                                 PrintDiagnosticCallback,
-                                                 stderr);
+                                                 unsaved_files);
   if (!TU) {
     fprintf(stderr, "unable to parse input\n");
     return -1;
@@ -895,6 +901,7 @@
     free(Locations[Loc].filename);
   }
 
+  PrintDiagnostics(TU);
   clang_disposeTranslationUnit(TU);
   clang_disposeIndex(CIdx);
   free(Locations);
@@ -933,9 +940,7 @@
                                                  argc - num_unsaved_files - 3,
                                                  argv + num_unsaved_files + 2,
                                                  num_unsaved_files,
-                                                 unsaved_files,
-                                                 PrintDiagnosticCallback,
-                                                 stderr);
+                                                 unsaved_files);
   if (!TU) {
     fprintf(stderr, "unable to parse input\n");
     clang_disposeIndex(CIdx);
@@ -1000,6 +1005,7 @@
   free(cursors);
 
  teardown:
+  PrintDiagnostics(TU);
   clang_disposeTranslationUnit(TU);
   clang_disposeIndex(CIdx);
   free(filename);