cc1: Factor out CompilerInstance::ExecuteAction which has the majority of the
clang -cc1 logic for running an action against a set of options.
 - This should make it easier to build tools that have a clang -cc1 like
   interface, but aren't actually part of clang -cc1.

llvm-svn: 93282
diff --git a/clang/tools/driver/cc1_main.cpp b/clang/tools/driver/cc1_main.cpp
index d901c6f8..d2f1017 100644
--- a/clang/tools/driver/cc1_main.cpp
+++ b/clang/tools/driver/cc1_main.cpp
@@ -14,10 +14,6 @@
 //===----------------------------------------------------------------------===//
 
 #include "clang/Basic/Diagnostic.h"
-#include "clang/Basic/FileManager.h"
-#include "clang/Basic/SourceManager.h"
-#include "clang/Basic/TargetInfo.h"
-#include "clang/Basic/Version.h"
 #include "clang/Driver/Arg.h"
 #include "clang/Driver/ArgList.h"
 #include "clang/Driver/CC1Options.h"
@@ -30,7 +26,6 @@
 #include "clang/Frontend/FrontendPluginRegistry.h"
 #include "clang/Frontend/TextDiagnosticBuffer.h"
 #include "clang/Frontend/TextDiagnosticPrinter.h"
-#include "clang/Frontend/VerifyDiagnosticsClient.h"
 #include "llvm/LLVMContext.h"
 #include "llvm/ADT/OwningPtr.h"
 #include "llvm/Support/ErrorHandling.h"
@@ -38,8 +33,6 @@
 #include "llvm/Support/PrettyStackTrace.h"
 #include "llvm/Support/raw_ostream.h"
 #include "llvm/System/DynamicLibrary.h"
-#include "llvm/System/Host.h"
-#include "llvm/System/Path.h"
 #include "llvm/System/Signals.h"
 #include "llvm/Target/TargetSelect.h"
 #include <cstdio>
@@ -207,13 +200,13 @@
                                      Diags);
 
   // Infer the builtin include path if unspecified.
-  if (Clang.getInvocation().getHeaderSearchOpts().UseBuiltinIncludes &&
-      Clang.getInvocation().getHeaderSearchOpts().ResourceDir.empty())
-    Clang.getInvocation().getHeaderSearchOpts().ResourceDir =
+  if (Clang.getHeaderSearchOpts().UseBuiltinIncludes &&
+      Clang.getHeaderSearchOpts().ResourceDir.empty())
+    Clang.getHeaderSearchOpts().ResourceDir =
       CompilerInvocation::GetResourcesPath(Argv0, MainAddr);
 
   // Honor -help.
-  if (Clang.getInvocation().getFrontendOpts().ShowHelp) {
+  if (Clang.getFrontendOpts().ShowHelp) {
     llvm::OwningPtr<driver::OptTable> Opts(driver::createCC1OptTable());
     Opts->PrintHelp(llvm::outs(), "clang -cc1",
                     "LLVM 'Clang' Compiler: http://clang.llvm.org");
@@ -223,7 +216,7 @@
   // Honor -version.
   //
   // FIXME: Use a better -version message?
-  if (Clang.getInvocation().getFrontendOpts().ShowVersion) {
+  if (Clang.getFrontendOpts().ShowVersion) {
     llvm::cl::PrintVersionMessage();
     return 0;
   }
@@ -249,85 +242,18 @@
       Diags.Report(diag::err_fe_unable_to_load_plugin) << Path << Error;
   }
 
-  // Create the frontend action.
-  llvm::OwningPtr<FrontendAction> Act(CreateFrontendAction(Clang));
-
-  // If there were any errors in processing arguments, exit now.
-  if (!Act || Clang.getDiagnostics().getNumErrors())
-    return 1;
-
-  // Create the target instance.
-  Clang.setTarget(TargetInfo::CreateTargetInfo(Clang.getDiagnostics(),
-                                               Clang.getTargetOpts()));
-  if (!Clang.hasTarget())
-    return 1;
-
-  // Inform the target of the language options.
-  //
-  // FIXME: We shouldn't need to do this, the target should be immutable once
-  // created. This complexity should be lifted elsewhere.
-  Clang.getTarget().setForcedLangOptions(Clang.getLangOpts());
-
-  // Validate/process some options.
-  if (Clang.getHeaderSearchOpts().Verbose)
-    llvm::errs() << "clang -cc1 version " CLANG_VERSION_STRING
-                 << " based upon " << PACKAGE_STRING
-                 << " hosted on " << llvm::sys::getHostTriple() << "\n";
-
-  if (Clang.getFrontendOpts().ShowTimers)
-    Clang.createFrontendTimer();
-
-  for (unsigned i = 0, e = Clang.getFrontendOpts().Inputs.size(); i != e; ++i) {
-    const std::string &InFile = Clang.getFrontendOpts().Inputs[i].second;
-
-    // If we aren't using an AST file, setup the file and source managers and
-    // the preprocessor.
-    bool IsAST =
-      Clang.getFrontendOpts().Inputs[i].first == FrontendOptions::IK_AST;
-    if (!IsAST) {
-      if (!i) {
-        // Create a file manager object to provide access to and cache the
-        // filesystem.
-        Clang.createFileManager();
-
-        // Create the source manager.
-        Clang.createSourceManager();
-      } else {
-        // Reset the ID tables if we are reusing the SourceManager.
-        Clang.getSourceManager().clearIDTables();
-      }
-
-      // Create the preprocessor.
-      Clang.createPreprocessor();
-    }
-
-    if (Act->BeginSourceFile(Clang, InFile, IsAST)) {
-      Act->Execute();
-      Act->EndSourceFile();
-    }
+  // If there were errors in processing arguments, don't do anything else.
+  bool Success = false;
+  if (!Clang.getDiagnostics().getNumErrors()) {
+    // Create and execute the frontend action.
+    llvm::OwningPtr<FrontendAction> Act(CreateFrontendAction(Clang));
+    if (Act)
+      Success = Clang.ExecuteAction(*Act);
   }
 
-  if (Clang.getDiagnosticOpts().ShowCarets)
-    if (unsigned NumDiagnostics = Clang.getDiagnostics().getNumDiagnostics())
-      fprintf(stderr, "%d diagnostic%s generated.\n", NumDiagnostics,
-              (NumDiagnostics == 1 ? "" : "s"));
-
-  if (Clang.getFrontendOpts().ShowStats) {
-    Clang.getFileManager().PrintStats();
-    fprintf(stderr, "\n");
-  }
-
-  // Return the appropriate status when verifying diagnostics.
-  //
-  // FIXME: If we could make getNumErrors() do the right thing, we wouldn't need
-  // this.
-  if (Clang.getDiagnosticOpts().VerifyDiagnostics)
-    return static_cast<VerifyDiagnosticsClient&>(
-      Clang.getDiagnosticClient()).HadErrors();
-
   // Managed static deconstruction. Useful for making things like
   // -time-passes usable.
   llvm::llvm_shutdown();
 
-  return (Clang.getDiagnostics().getNumErrors() != 0);
+  return !Success;
 }