[cfe-commits] r87103 - in /cfe/trunk: include/clang/Frontend/CompilerInstance.h lib/Frontend/CompilerInstance.cpp tools/clang-cc/clang-cc.cpp
Daniel Dunbar
daniel at zuster.org
Fri Nov 13 02:37:48 PST 2009
Author: ddunbar
Date: Fri Nov 13 04:37:48 2009
New Revision: 87103
URL: http://llvm.org/viewvc/llvm-project?rev=87103&view=rev
Log:
Add output file list to CompilerInstance, so that it can track them instead of
forcing all clients to do it.
Modified:
cfe/trunk/include/clang/Frontend/CompilerInstance.h
cfe/trunk/lib/Frontend/CompilerInstance.cpp
cfe/trunk/tools/clang-cc/clang-cc.cpp
Modified: cfe/trunk/include/clang/Frontend/CompilerInstance.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Frontend/CompilerInstance.h?rev=87103&r1=87102&r2=87103&view=diff
==============================================================================
--- cfe/trunk/include/clang/Frontend/CompilerInstance.h (original)
+++ cfe/trunk/include/clang/Frontend/CompilerInstance.h Fri Nov 13 04:37:48 2009
@@ -14,6 +14,8 @@
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/OwningPtr.h"
#include <cassert>
+#include <list>
+#include <string>
namespace llvm {
class LLVMContext;
@@ -82,6 +84,9 @@
/// The code completion consumer.
llvm::OwningPtr<CodeCompleteConsumer> CompletionConsumer;
+ /// The list of active output files.
+ std::list< std::pair<std::string, llvm::raw_ostream*> > OutputFiles;
+
public:
/// Create a new compiler instance with the given LLVM context, optionally
/// taking ownership of it.
@@ -332,6 +337,27 @@
}
/// }
+ /// @name Output Files
+ /// {
+
+ /// getOutputFileList - Get the list of (path, output stream) pairs of output
+ /// files; the path may be empty but the stream will always be non-null.
+ const std::list< std::pair<std::string,
+ llvm::raw_ostream*> > &getOutputFileList() const;
+
+ /// addOutputFile - Add an output file onto the list of tracked output files.
+ ///
+ /// \param Path - The path to the output file, or empty.
+ /// \param OS - The output stream, which should be non-null.
+ void addOutputFile(llvm::StringRef Path, llvm::raw_ostream *OS);
+
+ /// ClearOutputFiles - Clear the output file list, destroying the contained
+ /// output streams.
+ ///
+ /// \param EraseFiles - If true, attempt to erase the files from disk.
+ void ClearOutputFiles(bool EraseFiles);
+
+ /// }
/// @name Construction Utility Methods
/// {
Modified: cfe/trunk/lib/Frontend/CompilerInstance.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/CompilerInstance.cpp?rev=87103&r1=87102&r2=87103&view=diff
==============================================================================
--- cfe/trunk/lib/Frontend/CompilerInstance.cpp (original)
+++ cfe/trunk/lib/Frontend/CompilerInstance.cpp Fri Nov 13 04:37:48 2009
@@ -25,6 +25,7 @@
#include "clang/Sema/CodeCompleteConsumer.h"
#include "llvm/LLVMContext.h"
#include "llvm/Support/raw_ostream.h"
+#include "llvm/System/Path.h"
using namespace clang;
CompilerInstance::CompilerInstance(llvm::LLVMContext *_LLVMContext,
@@ -243,3 +244,22 @@
else
return new CIndexCodeCompleteConsumer(ShowMacros, OS);
}
+
+// Output Files
+
+void CompilerInstance::addOutputFile(llvm::StringRef Path,
+ llvm::raw_ostream *OS) {
+ assert(OS && "Attempt to add empty stream to output list!");
+ OutputFiles.push_back(std::make_pair(Path, OS));
+}
+
+void CompilerInstance::ClearOutputFiles(bool EraseFiles) {
+ for (std::list< std::pair<std::string, llvm::raw_ostream*> >::iterator
+ it = OutputFiles.begin(), ie = OutputFiles.end(); it != ie; ++it) {
+ delete it->second;
+ if (EraseFiles && !it->first.empty())
+ llvm::sys::Path(it->first).eraseFromDisk();
+ }
+ OutputFiles.clear();
+}
+
Modified: cfe/trunk/tools/clang-cc/clang-cc.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/clang-cc/clang-cc.cpp?rev=87103&r1=87102&r2=87103&view=diff
==============================================================================
--- cfe/trunk/tools/clang-cc/clang-cc.cpp (original)
+++ cfe/trunk/tools/clang-cc/clang-cc.cpp Fri Nov 13 04:37:48 2009
@@ -232,15 +232,13 @@
/// anything.
llvm::Timer *ClangFrontendTimer = 0;
-static llvm::raw_ostream *ComputeOutFile(const FrontendOptions &Opts,
- const std::string &InFile,
- const char *Extension,
- bool Binary,
- llvm::sys::Path& OutPath) {
- llvm::raw_ostream *Ret;
+static llvm::raw_fd_ostream *ComputeOutFile(CompilerInstance &CI,
+ const std::string &InFile,
+ const char *Extension,
+ bool Binary) {
std::string OutFile;
- if (!Opts.OutputFile.empty())
- OutFile = Opts.OutputFile;
+ if (!CI.getFrontendOpts().OutputFile.empty())
+ OutFile = CI.getFrontendOpts().OutputFile;
else if (InFile == "-") {
OutFile = "-";
} else if (Extension) {
@@ -253,18 +251,20 @@
}
std::string Error;
- Ret = new llvm::raw_fd_ostream(OutFile.c_str(), Error,
- (Binary ? llvm::raw_fd_ostream::F_Binary : 0));
+ llvm::raw_fd_ostream *OS =
+ new llvm::raw_fd_ostream(OutFile.c_str(), Error,
+ (Binary ? llvm::raw_fd_ostream::F_Binary : 0));
if (!Error.empty()) {
// FIXME: Don't fail this way.
llvm::errs() << "ERROR: " << Error << "\n";
::exit(1);
}
- if (OutFile != "-")
- OutPath = OutFile;
+ // Track that this is an output file, so that we remember to close it and so
+ // we can remove it on errors.
+ CI.addOutputFile((InFile == "-") ? "" : OutFile, OS);
- return Ret;
+ return OS;
}
/// AddFixItLocations - Add any individual user specified "fix-it" locations,
@@ -294,9 +294,7 @@
static ASTConsumer *CreateConsumerAction(CompilerInstance &CI,
Preprocessor &PP,
const std::string &InFile,
- ProgActions PA,
- llvm::OwningPtr<llvm::raw_ostream> &OS,
- llvm::sys::Path &OutPath) {
+ ProgActions PA) {
const FrontendOptions &FEOpts = CI.getFrontendOpts();
switch (PA) {
@@ -304,13 +302,10 @@
return 0;
case ASTPrint:
- OS.reset(ComputeOutFile(CI.getFrontendOpts(), InFile, 0, false, OutPath));
- return CreateASTPrinter(OS.get());
+ return CreateASTPrinter(ComputeOutFile(CI, InFile, 0, false));
case ASTPrintXML:
- OS.reset(ComputeOutFile(CI.getFrontendOpts(), InFile, "xml", false,
- OutPath));
- return CreateASTPrinterXML(OS.get());
+ return CreateASTPrinterXML(ComputeOutFile(CI, InFile, "xml", false));
case ASTDump:
return CreateASTDumper();
@@ -329,20 +324,18 @@
case EmitBC:
case EmitLLVMOnly: {
BackendAction Act;
+ llvm::OwningPtr<llvm::raw_ostream> OS;
if (ProgAction == EmitAssembly) {
Act = Backend_EmitAssembly;
- OS.reset(ComputeOutFile(CI.getFrontendOpts(), InFile, "s", true,
- OutPath));
+ OS.reset(ComputeOutFile(CI, InFile, "s", true));
} else if (ProgAction == EmitLLVM) {
Act = Backend_EmitLL;
- OS.reset(ComputeOutFile(CI.getFrontendOpts(), InFile, "ll", true,
- OutPath));
+ OS.reset(ComputeOutFile(CI, InFile, "ll", true));
} else if (ProgAction == EmitLLVMOnly) {
Act = Backend_EmitNothing;
} else {
Act = Backend_EmitBC;
- OS.reset(ComputeOutFile(CI.getFrontendOpts(), InFile, "bc", true,
- OutPath));
+ OS.reset(ComputeOutFile(CI, InFile, "bc", true));
}
// Fix-its can change semantics, disallow with any IRgen action.
@@ -352,14 +345,13 @@
}
return CreateBackendConsumer(Act, PP.getDiagnostics(), PP.getLangOptions(),
- CI.getCodeGenOpts(), InFile, OS.get(),
+ CI.getCodeGenOpts(), InFile, OS.take(),
CI.getLLVMContext());
}
case RewriteObjC:
- OS.reset(ComputeOutFile(CI.getFrontendOpts(), InFile, "cpp", true, OutPath));
- return CreateObjCRewriter(InFile, OS.get(), PP.getDiagnostics(),
- PP.getLangOptions(),
+ return CreateObjCRewriter(InFile, ComputeOutFile(CI, InFile, "cpp", true),
+ PP.getDiagnostics(), PP.getLangOptions(),
CI.getDiagnosticOpts().NoRewriteMacros);
case RewriteBlocks:
@@ -379,15 +371,13 @@
ProgActions PA) {
Preprocessor &PP = CI.getPreprocessor();
const FrontendOptions &FEOpts = CI.getFrontendOpts();
- llvm::OwningPtr<llvm::raw_ostream> OS;
llvm::OwningPtr<ASTConsumer> Consumer;
FixItRewriter *FixItRewrite = 0;
bool CompleteTranslationUnit = true;
- llvm::sys::Path OutPath;
switch (PA) {
default:
- Consumer.reset(CreateConsumerAction(CI, PP, InFile, PA, OS, OutPath));
+ Consumer.reset(CreateConsumerAction(CI, PP, InFile, PA));
if (!Consumer.get()) {
PP.getDiagnostics().Report(diag::err_fe_invalid_ast_action);
return;
@@ -395,8 +385,7 @@
break;
case EmitHTML:
- OS.reset(ComputeOutFile(CI.getFrontendOpts(), InFile, 0, true, OutPath));
- Consumer.reset(CreateHTMLPrinter(OS.get(), PP));
+ Consumer.reset(CreateHTMLPrinter(ComputeOutFile(CI, InFile, 0, true), PP));
break;
case RunAnalysis:
@@ -412,11 +401,11 @@
Relocatable = false;
}
- OS.reset(ComputeOutFile(CI.getFrontendOpts(), InFile, 0, true, OutPath));
+ llvm::raw_ostream *OS = ComputeOutFile(CI, InFile, 0, true);
if (Relocatable)
- Consumer.reset(CreatePCHGenerator(PP, OS.get(), Sysroot.c_str()));
+ Consumer.reset(CreatePCHGenerator(PP, OS, Sysroot.c_str()));
else
- Consumer.reset(CreatePCHGenerator(PP, OS.get()));
+ Consumer.reset(CreatePCHGenerator(PP, OS));
CompleteTranslationUnit = false;
break;
}
@@ -525,32 +514,29 @@
llvm::errs() << "ERROR: PTH requires an seekable file for output!\n";
::exit(1);
}
- OS.reset(ComputeOutFile(CI.getFrontendOpts(), InFile, 0, true, OutPath));
- CacheTokens(PP, static_cast<llvm::raw_fd_ostream*>(OS.get()));
+ CacheTokens(PP, ComputeOutFile(CI, InFile, 0, true));
break;
case ParseNoop:
ParseFile(PP, new MinimalAction(PP));
break;
- case ParsePrintCallbacks:
- OS.reset(ComputeOutFile(CI.getFrontendOpts(), InFile, 0, true, OutPath));
- ParseFile(PP, CreatePrintParserActionsAction(PP, OS.get()));
+ case ParsePrintCallbacks: {
+ llvm::raw_ostream *OS = ComputeOutFile(CI, InFile, 0, true);
+ ParseFile(PP, CreatePrintParserActionsAction(PP, OS));
break;
-
+ }
case PrintPreprocessedInput:
- OS.reset(ComputeOutFile(CI.getFrontendOpts(), InFile, 0, true, OutPath));
- DoPrintPreprocessedInput(PP, OS.get(), CI.getPreprocessorOutputOpts());
+ DoPrintPreprocessedInput(PP, ComputeOutFile(CI, InFile, 0, true),
+ CI.getPreprocessorOutputOpts());
break;
case RewriteMacros:
- OS.reset(ComputeOutFile(CI.getFrontendOpts(), InFile, 0, true, OutPath));
- RewriteMacrosInInput(PP, OS.get());
+ RewriteMacrosInInput(PP, ComputeOutFile(CI, InFile, 0, true));
break;
case RewriteTest:
- OS.reset(ComputeOutFile(CI.getFrontendOpts(), InFile, 0, true, OutPath));
- DoRewriteTest(PP, OS.get());
+ DoRewriteTest(PP, ComputeOutFile(CI, InFile, 0, true));
break;
case RunPreprocessorOnly: { // Just lex as fast as we can, no output.
@@ -591,13 +577,9 @@
fprintf(stderr, "\n");
}
- // 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 we had errors, try to erase the output file.
- if (PP.getDiagnostics().getNumErrors() && !OutPath.isEmpty())
- OutPath.eraseFromDisk();
+ // Cleanup the output streams, and erase the output files if we encountered an
+ // error.
+ CI.ClearOutputFiles(/*EraseFiles=*/PP.getDiagnostics().getNumErrors());
}
/// ProcessASTInputFile - Process a single AST input file with the specified
@@ -612,11 +594,8 @@
}
Preprocessor &PP = AST->getPreprocessor();
-
- llvm::OwningPtr<llvm::raw_ostream> OS;
- llvm::sys::Path OutPath;
- llvm::OwningPtr<ASTConsumer> Consumer(CreateConsumerAction(CI, PP, InFile, PA,
- OS, OutPath));
+ llvm::OwningPtr<ASTConsumer> Consumer(CreateConsumerAction(CI, PP,
+ InFile, PA));
if (!Consumer.get()) {
CI.getDiagnostics().Report(diag::err_fe_invalid_ast_action);
return;
@@ -647,13 +626,9 @@
AST.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 we had errors, try to erase the output file.
- if (PP.getDiagnostics().getNumErrors() && !OutPath.isEmpty())
- OutPath.eraseFromDisk();
+ // Cleanup the output streams, and erase the output files if we encountered an
+ // error.
+ CI.ClearOutputFiles(/*EraseFiles=*/PP.getDiagnostics().getNumErrors());
}
static void LLVMErrorHandler(void *UserData, const std::string &Message) {
More information about the cfe-commits
mailing list