Introduce serialization and deserialization of diagnostic information
so that CIndex can report diagnostics through the normal mechanisms
even when executing Clang in a separate process. This applies both
when performing code completion and when using ASTs as an intermediary
for clang_createTranslationUnitFromSourceFile().
The serialized format is not perfect at the moment, because it does
not encapsulate macro-instantiation information. Instead, it maps all
source locations back to the instantiation location. However, it does
maintain source-range and fix-it information. To get perfect fidelity
from the serialized format would require serializing a large chunk of
the source manager; at present, it isn't clear if this code will live
long enough for that to matter.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@94740 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/tools/CIndex/CIndex.cpp b/tools/CIndex/CIndex.cpp
index 57b463c..ee73946 100644
--- a/tools/CIndex/CIndex.cpp
+++ b/tools/CIndex/CIndex.cpp
@@ -1044,6 +1044,13 @@
argv.push_back(arg);
}
+ // Generate a temporary name for the diagnostics file.
+ char tmpFileResults[L_tmpnam];
+ char *tmpResultsFileName = tmpnam(tmpFileResults);
+ llvm::sys::Path DiagnosticsFile(tmpResultsFileName);
+ TemporaryFiles.push_back(DiagnosticsFile);
+ argv.push_back("-fdiagnostics-binary");
+
// Add the null terminator.
argv.push_back(NULL);
@@ -1051,7 +1058,8 @@
llvm::sys::Path DevNull; // leave empty, causes redirection to /dev/null
// on Unix or NUL (Windows).
std::string ErrMsg;
- const llvm::sys::Path *Redirects[] = { &DevNull, &DevNull, &DevNull, NULL };
+ const llvm::sys::Path *Redirects[] = { &DevNull, &DevNull, &DiagnosticsFile,
+ NULL };
llvm::sys::Program::ExecuteAndWait(ClangPath, &argv[0], /* env */ NULL,
/* redirects */ &Redirects[0],
/* secondsToWait */ 0, /* memoryLimits */ 0, &ErrMsg);
@@ -1078,6 +1086,9 @@
if (ATU)
ATU->unlinkTemporaryFile();
+ ReportSerializedDiagnostics(DiagnosticsFile, *Diags,
+ num_unsaved_files, unsaved_files);
+
for (unsigned i = 0, e = TemporaryFiles.size(); i != e; ++i)
TemporaryFiles[i].eraseFromDisk();