]> granicus.if.org Git - clang/commitdiff
Refactor ASTConsumers to take a raw_ostream instead of a filename where
authorEli Friedman <eli.friedman@gmail.com>
Mon, 18 May 2009 22:20:00 +0000 (22:20 +0000)
committerEli Friedman <eli.friedman@gmail.com>
Mon, 18 May 2009 22:20:00 +0000 (22:20 +0000)
appropriate.  There shouldn't be any significant functionality change.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@72052 91177308-0d34-0410-b5e6-96231b3b80d8

tools/clang-cc/ASTConsumers.h
tools/clang-cc/Backend.cpp
tools/clang-cc/GeneratePCH.cpp
tools/clang-cc/HTMLPrint.cpp
tools/clang-cc/RewriteBlocks.cpp
tools/clang-cc/RewriteObjC.cpp
tools/clang-cc/clang-cc.cpp

index f270f363421a399bb33e5b39fa3cde0c0590a20c..bb31e5c1588c308d9048796399a531a61d42d345 100644 (file)
@@ -36,7 +36,7 @@ class LangOptions;
 // original C code.  The output is intended to be in a format such that
 // clang could re-parse the output back into the same AST, but the
 // implementation is still incomplete.
-ASTConsumer *CreateASTPrinter(llvm::raw_ostream* OS = NULL);
+ASTConsumer *CreateASTPrinter(llvm::raw_ostream* OS);
 
 // AST dumper: dumps the raw AST in human-readable form to stderr; this is
 // intended for debugging. A normal dump is done with FullDump = false;
@@ -56,7 +56,7 @@ ASTConsumer *CreateDeclContextPrinter();
 // ObjC rewriter: attempts tp rewrite ObjC constructs into pure C code.
 // This is considered experimental, and only works with Apple's ObjC runtime.
 ASTConsumer *CreateCodeRewriterTest(const std::string& InFile,
-                                    const std::string& OutFile,
+                                    llvm::raw_ostream* OS,
                                     Diagnostic &Diags,
                                     const LangOptions &LOpts);
 
@@ -73,24 +73,23 @@ ASTConsumer *CreateBackendConsumer(BackendAction Action,
                                    Diagnostic &Diags,
                                    const LangOptions &Features,
                                    const CompileOptions &CompileOpts,
-                                   const std::string &InFile,
-                                   const std::string &OutFile);
+                                   const std::string &ModuleID,
+                                   llvm::raw_ostream *OS);
 
 // HTML printer: uses the rewriter to convert source code to HTML with
 // syntax highlighting suitable for viewing in a web-browser.
-ASTConsumer* CreateHTMLPrinter(const std::string &OutFile, Diagnostic &D,
+ASTConsumer* CreateHTMLPrinter(llvm::raw_ostream *OS, Diagnostic &D,
                                Preprocessor *PP, PreprocessorFactory *PPF);
 
 // PCH generator: generates a precompiled header file; this file can be
 // used later with the PCHReader (clang-cc option -include-pch)
 // to speed up compile times.
 ASTConsumer *CreatePCHGenerator(const Preprocessor &PP,
-                                const std::string &OutFile);
+                                llvm::raw_ostream *OS);
 
 // Block rewriter: rewrites code using the Apple blocks extension to pure
-// C code.
+// C code.  Output is always sent to stdout.
 ASTConsumer *CreateBlockRewriter(const std::string &InFile,
-                                 const std::string &OutFile,
                                  Diagnostic &Diags,
                                  const LangOptions &LangOpts);
 
index ebee66167d07c3f0aeda04967d007ddd35d9d867..2988ae697a6f063a7f43107a3fddcf9ec81fa738 100644 (file)
@@ -42,8 +42,7 @@ namespace {
   class VISIBILITY_HIDDEN BackendConsumer : public ASTConsumer {
     BackendAction Action;
     CompileOptions CompileOpts;
-    const std::string &InputFile;
-    std::string OutputFile;
+    llvm::raw_ostream *AsmOutStream;
     ASTContext *Context;
 
     Timer LLVMIRGeneration;
@@ -53,7 +52,6 @@ namespace {
     
     llvm::Module *TheModule;
     llvm::TargetData *TheTargetData;
-    llvm::raw_ostream *AsmOutStream;
 
     mutable llvm::ModuleProvider *ModuleProvider;
     mutable FunctionPassManager *CodeGenPasses;
@@ -78,15 +76,14 @@ namespace {
   public:  
     BackendConsumer(BackendAction action, Diagnostic &Diags, 
                     const LangOptions &langopts, const CompileOptions &compopts,
-                    const std::string &infile, const std::string &outfile) :
+                    const std::string &infile, llvm::raw_ostream* OS) :
       Action(action), 
       CompileOpts(compopts),
-      InputFile(infile), 
-      OutputFile(outfile), 
+      AsmOutStream(OS), 
       LLVMIRGeneration("LLVM IR Generation Time"),
       CodeGenerationTime("Code Generation Time"),
-      Gen(CreateLLVMCodeGen(Diags, InputFile, compopts)),
-      TheModule(0), TheTargetData(0), AsmOutStream(0), ModuleProvider(0),
+      Gen(CreateLLVMCodeGen(Diags, infile, compopts)),
+      TheModule(0), TheTargetData(0), ModuleProvider(0),
       CodeGenPasses(0), PerModulePasses(0), PerFunctionPasses(0) {
       
       // Enable -time-passes if -ftime-report is enabled.
@@ -94,7 +91,6 @@ namespace {
     }
 
     ~BackendConsumer() {
-      delete AsmOutStream;
       delete TheTargetData;
       delete ModuleProvider;
       delete CodeGenPasses;
@@ -196,28 +192,6 @@ bool BackendConsumer::AddEmitPasses(std::string &Error) {
   if (Action == Backend_EmitNothing)
     return true;
 
-  if (OutputFile == "-" || (InputFile == "-" && OutputFile.empty())) {
-    AsmOutStream = new raw_stdout_ostream();
-    sys::Program::ChangeStdoutToBinary();
-  } else {
-    if (OutputFile.empty()) {
-      llvm::sys::Path Path(InputFile);
-      Path.eraseSuffix();
-      if (Action == Backend_EmitBC) {
-        Path.appendSuffix("bc");
-      } else if (Action == Backend_EmitLL) {
-        Path.appendSuffix("ll");
-      } else {
-        Path.appendSuffix("s");
-      }
-      OutputFile = Path.toString();
-    }
-
-    AsmOutStream = new raw_fd_ostream(OutputFile.c_str(), true, Error);
-    if (!Error.empty())
-      return false;
-  }
-
   if (Action == Backend_EmitBC) {
     getPerModulePasses()->add(createBitcodeWriterPass(*AsmOutStream));
   } else if (Action == Backend_EmitLL) {
@@ -435,7 +409,6 @@ ASTConsumer *clang::CreateBackendConsumer(BackendAction Action,
                                           const LangOptions &LangOpts,
                                           const CompileOptions &CompileOpts,
                                           const std::string& InFile,
-                                          const std::string& OutFile) {
-  return new BackendConsumer(Action, Diags, LangOpts, CompileOpts,
-                             InFile, OutFile);  
+                                          llvm::raw_ostream* OS) {
+  return new BackendConsumer(Action, Diags, LangOpts, CompileOpts, InFile, OS);
 }
index 9bc5ded71571563aa092052ea8dce0a09b7dc29b..62ab0ec010b9113614093d375b96b573cff7aeab 100644 (file)
@@ -32,19 +32,19 @@ using namespace llvm;
 namespace {
   class VISIBILITY_HIDDEN PCHGenerator : public SemaConsumer {
     const Preprocessor &PP;
-    std::string OutFile;
+    llvm::raw_ostream *Out;
     Sema *SemaPtr;
     MemorizeStatCalls *StatCalls; // owned by the FileManager
 
   public:
-    explicit PCHGenerator(const Preprocessor &PP, const std::string &OutFile);
+    explicit PCHGenerator(const Preprocessor &PP, llvm::raw_ostream *Out);
     virtual void InitializeSema(Sema &S) { SemaPtr = &S; }
     virtual void HandleTranslationUnit(ASTContext &Ctx);
   };
 }
 
-PCHGenerator::PCHGenerator(const Preprocessor &PP, const std::string &OutFile)
-  : PP(PP), OutFile(OutFile), SemaPtr(0), StatCalls(0) { 
+PCHGenerator::PCHGenerator(const Preprocessor &PP, llvm::raw_ostream *OS)
+  : PP(PP), Out(OS), SemaPtr(0), StatCalls(0) { 
 
   // Install a stat() listener to keep track of all of the stat()
   // calls.
@@ -65,23 +65,14 @@ void PCHGenerator::HandleTranslationUnit(ASTContext &Ctx) {
   assert(SemaPtr && "No Sema?");
   Writer.WritePCH(*SemaPtr, StatCalls);
 
-  // Open up the PCH file.
-  std::string ErrMsg;
-  llvm::raw_fd_ostream Out(OutFile.c_str(), true, ErrMsg);
-  
-  if (!ErrMsg.empty()) {
-    llvm::errs() << "PCH error: " << ErrMsg << "\n";
-    return;
-  }
-
   // Write the generated bitstream to "Out".
-  Out.write((char *)&Buffer.front(), Buffer.size());
+  Out->write((char *)&Buffer.front(), Buffer.size());
 
   // Make sure it hits disk now.
-  Out.flush();
+  Out->flush();
 }
 
 ASTConsumer *clang::CreatePCHGenerator(const Preprocessor &PP,
-                                       const std::string &OutFile) {
-  return new PCHGenerator(PP, OutFile);
+                                       llvm::raw_ostream *OS) {
+  return new PCHGenerator(PP, OS);
 }
index 0e15973939e9da1258641fcb8eb4c3e98f45b142..71121095aed47e41e748fc8a47f43e86c5a9a124 100644 (file)
@@ -30,25 +30,25 @@ using namespace clang;
 namespace {
   class HTMLPrinter : public ASTConsumer {
     Rewriter R;
-    std::string OutFilename;
+    llvm::raw_ostream *Out;
     Diagnostic &Diags;
     Preprocessor *PP;
     PreprocessorFactory *PPF;
   public:
-    HTMLPrinter(const std::string &OutFile, Diagnostic &D, Preprocessor *pp,
+    HTMLPrinter(llvm::raw_ostream *OS, Diagnostic &D, Preprocessor *pp,
                 PreprocessorFactory* ppf)
-      : OutFilename(OutFile), Diags(D), PP(pp), PPF(ppf) {}
+      : Out(OS), Diags(D), PP(pp), PPF(ppf) {}
     virtual ~HTMLPrinter();
     
     void Initialize(ASTContext &context);
   };
 }
 
-ASTConsumer* clang::CreateHTMLPrinter(const std::string &OutFile, 
+ASTConsumer* clang::CreateHTMLPrinter(llvm::raw_ostream *OS,
                                       Diagnostic &D, Preprocessor *PP,
                                       PreprocessorFactory* PPF) {
   
-  return new HTMLPrinter(OutFile, D, PP, PPF);
+  return new HTMLPrinter(OS, D, PP, PPF);
 }
 
 void HTMLPrinter::Initialize(ASTContext &context) {
@@ -73,25 +73,11 @@ HTMLPrinter::~HTMLPrinter() {
   if (PP) html::SyntaxHighlight(R, FID, *PP);
   if (PPF) html::HighlightMacros(R, FID, *PP);
   html::EscapeText(R, FID, false, true);
-  
-  // Open the output.
-  FILE *OutputFILE;
-  if (OutFilename.empty() || OutFilename == "-")
-    OutputFILE = stdout;
-  else {
-    OutputFILE = fopen(OutFilename.c_str(), "w+");
-    if (OutputFILE == 0) {
-      fprintf(stderr, "Error opening output file '%s'.\n", OutFilename.c_str());
-      exit(1);
-    }
-  }
-  
+
   // Emit the HTML.
   const RewriteBuffer &RewriteBuf = R.getEditBuffer(FID);
   char *Buffer = (char*)malloc(RewriteBuf.size());
   std::copy(RewriteBuf.begin(), RewriteBuf.end(), Buffer);
-  fwrite(Buffer, 1, RewriteBuf.size(), OutputFILE);
+  Out->write(Buffer, RewriteBuf.size());
   free(Buffer);
-  
-  if (OutputFILE != stdout) fclose(OutputFILE);
 }
index f9ed0ecc095fcb3d812afde1d2de2382a119f8af..135f4a70bfae3c18a596256becd5d7195a2b61b0 100644 (file)
@@ -57,12 +57,10 @@ class RewriteBlocks : public ASTConsumer {
   ObjCMethodDecl *CurMethodDef;
   
   bool IsHeader;
-  std::string InFileName;
-  std::string OutFileName;
   
   std::string Preamble;
 public:
-  RewriteBlocks(std::string inFile, std::string outFile, Diagnostic &D, 
+  RewriteBlocks(std::string inFile, Diagnostic &D, 
                 const LangOptions &LOpts);
   ~RewriteBlocks() {
     // Get the buffer corresponding to MainFileID.  
@@ -169,12 +167,10 @@ static bool IsHeaderFile(const std::string &Filename) {
   return Ext == "h" || Ext == "hh" || Ext == "H";
 }    
 
-RewriteBlocks::RewriteBlocks(std::string inFile, std::string outFile, 
+RewriteBlocks::RewriteBlocks(std::string inFile,
                              Diagnostic &D, const LangOptions &LOpts) : 
   Diags(D), LangOpts(LOpts) {
   IsHeader = IsHeaderFile(inFile);
-  InFileName = inFile;
-  OutFileName = outFile;
   CurFunctionDef = 0;
   CurMethodDef = 0;
   RewriteFailedDiag = Diags.getCustomDiagID(Diagnostic::Warning, 
@@ -182,10 +178,9 @@ RewriteBlocks::RewriteBlocks(std::string inFile, std::string outFile,
 }
 
 ASTConsumer *clang::CreateBlockRewriter(const std::string& InFile,
-                                        const std::string& OutFile,
                                         Diagnostic &Diags,
                                         const LangOptions &LangOpts) {
-  return new RewriteBlocks(InFile, OutFile, Diags, LangOpts);
+  return new RewriteBlocks(InFile, Diags, LangOpts);
 }
 
 void RewriteBlocks::Initialize(ASTContext &context) {
index 37dd52485d66b606d75f7f63c0578d7e536513e0..b104747c00c4c8b859a5036fffb2047ee04f364d 100644 (file)
@@ -93,7 +93,7 @@ namespace {
     bool IsHeader;
     
     std::string InFileName;
-    std::string OutFileName;
+    llvm::raw_ostream* OutFile;
      
     std::string Preamble;
 
@@ -136,7 +136,7 @@ namespace {
     }
     void HandleTopLevelSingleDecl(Decl *D);
     void HandleDeclInMainFile(Decl *D);
-    RewriteObjC(std::string inFile, std::string outFile,
+    RewriteObjC(std::string inFile, llvm::raw_ostream *OS,
                 Diagnostic &D, const LangOptions &LOpts);
 
     ~RewriteObjC() {}
@@ -416,12 +416,10 @@ static bool IsHeaderFile(const std::string &Filename) {
   return Ext == "h" || Ext == "hh" || Ext == "H";
 }    
 
-RewriteObjC::RewriteObjC(std::string inFile, std::string outFile,
+RewriteObjC::RewriteObjC(std::string inFile, llvm::raw_ostream* OS,
                          Diagnostic &D, const LangOptions &LOpts)
-      : Diags(D), LangOpts(LOpts) {
+      : Diags(D), LangOpts(LOpts), InFileName(inFile), OutFile(OS) {
   IsHeader = IsHeaderFile(inFile);
-  InFileName = inFile;
-  OutFileName = outFile;
   RewriteFailedDiag = Diags.getCustomDiagID(Diagnostic::Warning, 
                "rewriting sub-expression within a macro (may not be correct)");
   TryFinallyContainsReturnDiag = Diags.getCustomDiagID(Diagnostic::Warning, 
@@ -430,10 +428,10 @@ RewriteObjC::RewriteObjC(std::string inFile, std::string outFile,
 }
 
 ASTConsumer *clang::CreateCodeRewriterTest(const std::string& InFile,
-                                           const std::string& OutFile,
+                                           llvm::raw_ostream* OS,
                                            Diagnostic &Diags, 
                                            const LangOptions &LOpts) {
-  return new RewriteObjC(InFile, OutFile, Diags, LOpts);
+  return new RewriteObjC(InFile, OS, Diags, LOpts);
 }
 
 void RewriteObjC::Initialize(ASTContext &context) {
@@ -4654,33 +4652,6 @@ void RewriteObjC::HandleTranslationUnit(ASTContext &C) {
   
   if (Diags.hasErrorOccurred())
     return;
-
-  // Create the output file.
-  
-  llvm::OwningPtr<llvm::raw_ostream> OwnedStream;
-  llvm::raw_ostream *OutFile;
-  if (OutFileName == "-") {
-    OutFile = &llvm::outs();
-  } else if (!OutFileName.empty()) {
-    std::string Err;
-    OutFile = new llvm::raw_fd_ostream(OutFileName.c_str(), 
-                                       // set binary mode (critical for Windoze)
-                                       true, 
-                                       Err);
-    OwnedStream.reset(OutFile);
-  } else if (InFileName == "-") {
-    OutFile = &llvm::outs();
-  } else {
-    llvm::sys::Path Path(InFileName);
-    Path.eraseSuffix();
-    Path.appendSuffix("cpp");
-    std::string Err;
-    OutFile = new llvm::raw_fd_ostream(Path.toString().c_str(), 
-                                       // set binary mode (critical for Windoze)
-                                       true, 
-                                       Err);
-    OwnedStream.reset(OutFile);
-  }
   
   RewriteInclude();
   
index 588ed2f76a107db4d7eba6406ca5fbd719ad7e0e..6aaa471efeaa4abeb612a2a42dd0179a211d0d9a 100644 (file)
 #include "llvm/Support/MemoryBuffer.h"
 #include "llvm/Support/PluginLoader.h"
 #include "llvm/Support/PrettyStackTrace.h"
+#include "llvm/Support/Streams.h"
 #include "llvm/Support/Timer.h"
 #include "llvm/System/Host.h"
 #include "llvm/System/Path.h"
 #include "llvm/System/Process.h"
+#include "llvm/System/Program.h"
 #include "llvm/System/Signals.h"
 #include <cstdlib>
 #if HAVE_SYS_TYPES_H
@@ -1569,101 +1571,141 @@ static void SetUpBuildDumpLog(unsigned argc, char **argv,
 // Main driver
 //===----------------------------------------------------------------------===//
 
-/// CreateASTConsumer - Create the ASTConsumer for the corresponding program
-/// action.  These consumers can operate on both ASTs that are freshly
-/// parsed from source files as well as those deserialized from Bitcode.
-/// Note that PP and PPF may be null here.
-static ASTConsumer *CreateASTConsumer(const std::string& InFile,
-                                      Diagnostic& Diag, FileManager& FileMgr, 
-                                      const LangOptions& LangOpts,
-                                      const llvm::StringMap<bool>& Features,
-                                      Preprocessor *PP,
-                                      PreprocessorFactory *PPF) {
-  switch (ProgAction) {
+static llvm::raw_ostream* ComputeOutFile(const std::string& InFile,
+                                         const char* Extension,
+                                         bool Binary,
+                                         llvm::sys::Path& OutPath) {
+  llvm::raw_ostream* Ret;
+  bool UseStdout = false;
+  std::string OutFile;
+  if (OutputFile == "-" || (OutputFile.empty() && InFile == "-")) {
+    UseStdout = true;
+  } else if (!OutputFile.empty()) {
+    OutFile = OutputFile;
+  } else if (Extension) {
+    llvm::sys::Path Path(InFile);
+    Path.eraseSuffix();
+    Path.appendSuffix(Extension);
+    OutFile = Path.toString();
+  } else {
+    UseStdout = true;
+  }
+
+  if (UseStdout) {
+    Ret = new llvm::raw_stdout_ostream();
+    if (Binary)
+      llvm::sys::Program::ChangeStdoutToBinary();
+  } else {
+    std::string Error;
+    Ret = new llvm::raw_fd_ostream(OutFile.c_str(), Binary, Error);
+    if (!Error.empty()) {
+      // FIXME: Don't fail this way.
+      llvm::cerr << "ERROR: " << Error << "\n";
+      ::exit(1);
+    }
+    OutPath = OutFile;
+  }
+
+  return Ret;
+}
+
+/// ProcessInputFile - Process a single input file with the specified state.
+///
+static void ProcessInputFile(Preprocessor &PP, PreprocessorFactory &PPF,
+                             const std::string &InFile, ProgActions PA,
+                             const llvm::StringMap<bool> &Features) {
+  llvm::OwningPtr<llvm::raw_ostream> OS;
+  llvm::OwningPtr<ASTConsumer> Consumer;
+  bool ClearSourceMgr = false;
+  FixItRewriter *FixItRewrite = 0;
+  bool CompleteTranslationUnit = true;
+  llvm::sys::Path OutPath;
+
+  switch (PA) {
   default:
-    return NULL;
-    
+    fprintf(stderr, "Unexpected program action!\n");
+    HadErrors = true;
+    return;
+
   case ASTPrint:
-    return CreateASTPrinter();
+    OS.reset(ComputeOutFile(InFile, 0, false, OutPath));
+    Consumer.reset(CreateASTPrinter(OS.get()));
+    break;
     
   case ASTDump:
-    return CreateASTDumper(false);
+    Consumer.reset(CreateASTDumper(false));
+    break;
 
   case ASTDumpFull:
-    return CreateASTDumper(true);
+    Consumer.reset(CreateASTDumper(true));
+    break;
     
   case ASTView:
-    return CreateASTViewer();   
+    Consumer.reset(CreateASTViewer());   
+    break;
 
   case PrintDeclContext:
-    return CreateDeclContextPrinter();
-    
+    Consumer.reset(CreateDeclContextPrinter());
+    break;
+
   case EmitHTML:
-    return CreateHTMLPrinter(OutputFile, Diag, PP, PPF);
+    OS.reset(ComputeOutFile(InFile, 0, true, OutPath));
+    Consumer.reset(CreateHTMLPrinter(OS.get(), PP.getDiagnostics(), &PP, &PPF));
+    break;
 
   case InheritanceView:
-    return CreateInheritanceViewer(InheritanceViewCls);
-    
+    Consumer.reset(CreateInheritanceViewer(InheritanceViewCls));
+    break;
+
   case EmitAssembly:
   case EmitLLVM:
   case EmitBC: 
   case EmitLLVMOnly: {
     BackendAction Act;
-    if (ProgAction == EmitAssembly)
+    if (ProgAction == EmitAssembly) {
       Act = Backend_EmitAssembly;
-    else if (ProgAction == EmitLLVM)
+      OS.reset(ComputeOutFile(InFile, "s", true, OutPath));
+    } else if (ProgAction == EmitLLVM) {
       Act = Backend_EmitLL;
-    else if (ProgAction == EmitLLVMOnly)
+      OS.reset(ComputeOutFile(InFile, "ll", true, OutPath));
+    } else if (ProgAction == EmitLLVMOnly) {
       Act = Backend_EmitNothing;
-    else
+    } else {
       Act = Backend_EmitBC;
-    
+      OS.reset(ComputeOutFile(InFile, "bc", true, OutPath));
+    }
+
     CompileOptions Opts;
-    InitializeCompileOptions(Opts, LangOpts, Features);
-    return CreateBackendConsumer(Act, Diag, LangOpts, Opts, 
-                                 InFile, OutputFile);
+    InitializeCompileOptions(Opts, PP.getLangOptions(), Features);
+    Consumer.reset(CreateBackendConsumer(Act, PP.getDiagnostics(),
+                                         PP.getLangOptions(), Opts, InFile,
+                                         OS.get()));
+    break;
   }
 
   case GeneratePCH:
-    return CreatePCHGenerator(*PP, OutputFile);    
+    OS.reset(ComputeOutFile(InFile, 0, true, OutPath));
+    Consumer.reset(CreatePCHGenerator(PP, OS.get()));
+    CompleteTranslationUnit = false;
+    break;
 
   case RewriteObjC:
-    return CreateCodeRewriterTest(InFile, OutputFile, Diag, LangOpts);
+    OS.reset(ComputeOutFile(InFile, "cpp", true, OutPath));
+    Consumer.reset(CreateCodeRewriterTest(InFile, OS.get(),
+                                          PP.getDiagnostics(),
+                                          PP.getLangOptions()));
+    break;
 
   case RewriteBlocks:
-    return CreateBlockRewriter(InFile, OutputFile, Diag, LangOpts);
-    
-  case RunAnalysis:
-    return CreateAnalysisConsumer(Diag, PP, PPF, LangOpts, OutputFile);
-  }
-}
-
-/// ProcessInputFile - Process a single input file with the specified state.
-///
-static void ProcessInputFile(Preprocessor &PP, PreprocessorFactory &PPF,
-                             const std::string &InFile, ProgActions PA,
-                             const llvm::StringMap<bool> &Features) {
-  llvm::OwningPtr<ASTConsumer> Consumer;
-  bool ClearSourceMgr = false;
-  FixItRewriter *FixItRewrite = 0;
-  bool CompleteTranslationUnit = true;
-
-  switch (PA) {
-  default:
-    Consumer.reset(CreateASTConsumer(InFile, PP.getDiagnostics(),
-                                     PP.getFileManager(), PP.getLangOptions(),
-                                     Features, &PP, &PPF));
-    
-    if (!Consumer) {      
-      fprintf(stderr, "Unexpected program action!\n");
-      HadErrors = true;
-      return;
-    }
+    Consumer.reset(CreateBlockRewriter(InFile, PP.getDiagnostics(),
+                                       PP.getLangOptions()));
+    break;
 
-    if (ProgAction == GeneratePCH)
-      CompleteTranslationUnit = false;
+  case RunAnalysis:
+    Consumer.reset(CreateAnalysisConsumer(PP.getDiagnostics(), &PP, &PPF,
+                                          PP.getLangOptions(), OutputFile));
     break;
-      
+
   case DumpRawTokens: {
     llvm::TimeRegion Timer(ClangFrontendTimer);
     SourceManager &SM = PP.getSourceManager();
@@ -1869,7 +1911,7 @@ static void ProcessInputFile(Preprocessor &PP, PreprocessorFactory &PPF,
     ContextOwner.take();
   else
     ContextOwner.reset(); // Delete ASTContext
-  
+
   if (VerifyDiagnostics)
     if (CheckDiagnostics(PP))
       exit(1);
@@ -1891,6 +1933,18 @@ static void ProcessInputFile(Preprocessor &PP, PreprocessorFactory &PPF,
 
   if (DisableFree)
     Consumer.take();
+  else
+    Consumer.reset();
+
+  // Always delete the output stream because we don't want to leak file
+  // handles.  Also, we don't want to try to erase an open file.
+  OS.reset();
+
+  if ((HadErrors || (PP.getDiagnostics().getNumErrors() != 0)) &&
+      !OutPath.isEmpty()) {
+    // If we had errors, try to erase the output file.
+    OutPath.eraseFromDisk();
+  }
 }
 
 static llvm::cl::list<std::string>