Start work on SerializedDiagnosticPrinter, a new DiagnosticConsumer that serializes out the diagnostics for a given translation unit to a bit code file.  This is a WIP.

The motivation for this new DiagnosticConsumer is to provide a way for tools invoking the compiler
to get its diagnostics via a libclang interface, rather than textually parsing the compiler output.
This gives us flexibility to change the compiler's textual output, but have a structured data format
for clients to use to get the diagnostics via a stable API.

I have no tests for this, but llvm-bcanalyzer so far shows that the emitted file is well-formed.

More work to follow.

llvm-svn: 143259
diff --git a/clang/lib/Frontend/CompilerInstance.cpp b/clang/lib/Frontend/CompilerInstance.cpp
index 5526487..9b96141 100644
--- a/clang/lib/Frontend/CompilerInstance.cpp
+++ b/clang/lib/Frontend/CompilerInstance.cpp
@@ -24,6 +24,7 @@
 #include "clang/Frontend/FrontendActions.h"
 #include "clang/Frontend/FrontendDiagnostic.h"
 #include "clang/Frontend/LogDiagnosticPrinter.h"
+#include "clang/Frontend/SerializedDiagnosticPrinter.h"
 #include "clang/Frontend/TextDiagnosticPrinter.h"
 #include "clang/Frontend/VerifyDiagnosticConsumer.h"
 #include "clang/Frontend/Utils.h"
@@ -153,6 +154,28 @@
   Diags.setClient(new ChainedDiagnosticConsumer(Diags.takeClient(), Logger));
 }
 
+static void SetupSerializedDiagnostics(const DiagnosticOptions &DiagOpts,
+                                       DiagnosticsEngine &Diags,
+                                       StringRef OutputFile) {
+  std::string ErrorInfo;
+  llvm::OwningPtr<llvm::raw_fd_ostream> OS;
+  OS.reset(new llvm::raw_fd_ostream(OutputFile.str().c_str(), ErrorInfo,
+                                    llvm::raw_fd_ostream::F_Binary));
+  
+  if (!ErrorInfo.empty()) {
+    Diags.Report(diag::warn_fe_serialized_diag_failure)
+      << OutputFile << ErrorInfo;
+    return;
+  }
+  
+  DiagnosticConsumer *SerializedConsumer =
+    clang::serialized_diags::create(OS.take(), Diags);
+
+  
+  Diags.setClient(new ChainedDiagnosticConsumer(Diags.takeClient(),
+                                                SerializedConsumer));
+}
+
 void CompilerInstance::createDiagnostics(int Argc, const char* const *Argv,
                                          DiagnosticConsumer *Client,
                                          bool ShouldOwnClient,
@@ -194,6 +217,10 @@
   if (!Opts.DumpBuildInformation.empty())
     SetUpBuildDumpLog(Opts, Argc, Argv, *Diags);
 
+  if (!Opts.DiagnosticSerializationFile.empty())
+    SetupSerializedDiagnostics(Opts, *Diags,
+                               Opts.DiagnosticSerializationFile);
+  
   // Configure our handling of diagnostics.
   ProcessWarningOptions(*Diags, Opts);