namespace llvm {
class LLVMContext;
class raw_ostream;
+class raw_fd_ostream;
}
namespace clang {
bool UseDebugPrinter, bool ShowMacros,
llvm::raw_ostream &OS);
+ /// Create the default output file (from the invocation's options) and add it
+ /// to the list of tracked output files.
+ llvm::raw_fd_ostream *
+ createDefaultOutputFile(bool Binary = true, llvm::StringRef BaseInput = "",
+ llvm::StringRef Extension = "");
+
+ /// Create a new output file and add it to the list of tracked output files,
+ /// optionally deriving the output path name.
+ llvm::raw_fd_ostream *
+ createOutputFile(llvm::StringRef OutputPath, bool Binary = true,
+ llvm::StringRef BaseInput = "",
+ llvm::StringRef Extension = "");
+
+ /// Create a new output file, optionally deriving the output path name.
+ ///
+ /// If \arg OutputPath is empty, then createOutputFile will derive an output
+ /// path location as \arg BaseInput, with any suffix removed, and \arg
+ /// Extension appended.
+ ///
+ /// \param OutputPath - If given, the path to the output file.
+ /// \param Error [out] - On failure, the error message.
+ /// \param BaseInput - If \arg OutputPath is empty, the input path name to use
+ /// for deriving the output path.
+ /// \param Extension - The extension to use for derived output names.
+ /// \param Binary - The mode to open the file in.
+ /// \param ResultPathName [out] - If given, the result path name will be
+ /// stored here on success.
+ static llvm::raw_fd_ostream *
+ createOutputFile(llvm::StringRef OutputPath, std::string &Error,
+ bool Binary = true, llvm::StringRef BaseInput = "",
+ llvm::StringRef Extension = "",
+ std::string *ResultPathName = 0);
+
/// }
};
OutputFiles.clear();
}
+llvm::raw_fd_ostream *
+CompilerInstance::createDefaultOutputFile(bool Binary,
+ llvm::StringRef InFile,
+ llvm::StringRef Extension) {
+ return createOutputFile(getFrontendOpts().OutputFile, Binary,
+ InFile, Extension);
+}
+
+llvm::raw_fd_ostream *
+CompilerInstance::createOutputFile(llvm::StringRef OutputPath,
+ bool Binary,
+ llvm::StringRef InFile,
+ llvm::StringRef Extension) {
+ std::string Error, OutputPathName;
+ llvm::raw_fd_ostream *OS = createOutputFile(OutputPath, Error, Binary,
+ InFile, Extension,
+ &OutputPathName);
+ if (!OS) {
+ // FIXME: Don't fail this way.
+ llvm::errs() << "ERROR: " << Error << "\n";
+ ::exit(1);
+ }
+
+ // Add the output file -- but don't try to remove "-", since this means we are
+ // using stdin.
+ addOutputFile((OutputPathName != "-") ? OutputPathName : "", OS);
+
+ return OS;
+}
+
+llvm::raw_fd_ostream *
+CompilerInstance::createOutputFile(llvm::StringRef OutputPath,
+ std::string &Error,
+ bool Binary,
+ llvm::StringRef InFile,
+ llvm::StringRef Extension,
+ std::string *ResultPathName) {
+ std::string OutFile;
+ if (!OutputPath.empty()) {
+ OutFile = OutputPath;
+ } else if (InFile == "-") {
+ OutFile = "-";
+ } else if (!Extension.empty()) {
+ llvm::sys::Path Path(InFile);
+ Path.eraseSuffix();
+ Path.appendSuffix(Extension);
+ OutFile = Path.str();
+ } else {
+ OutFile = "-";
+ }
+
+ llvm::raw_fd_ostream *OS =
+ new llvm::raw_fd_ostream(OutFile.c_str(), Error,
+ (Binary ? llvm::raw_fd_ostream::F_Binary : 0));
+ if (!OS)
+ return 0;
+
+ if (ResultPathName)
+ *ResultPathName = OutFile;
+
+ return OS;
+}
/// anything.
llvm::Timer *ClangFrontendTimer = 0;
-static llvm::raw_fd_ostream *ComputeOutFile(CompilerInstance &CI,
- const std::string &InFile,
- const char *Extension,
- bool Binary) {
- std::string OutFile;
- if (!CI.getFrontendOpts().OutputFile.empty())
- OutFile = CI.getFrontendOpts().OutputFile;
- else if (InFile == "-") {
- OutFile = "-";
- } else if (Extension) {
- llvm::sys::Path Path(InFile);
- Path.eraseSuffix();
- Path.appendSuffix(Extension);
- OutFile = Path.str();
- } else {
- OutFile = "-";
- }
-
- std::string Error;
- 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);
- }
-
- // 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 OS;
-}
-
/// AddFixItLocations - Add any individual user specified "fix-it" locations,
/// and return true on success (if any were added).
static bool AddFixItLocations(FixItRewriter *FixItRewrite,
return 0;
case ASTPrint:
- return CreateASTPrinter(ComputeOutFile(CI, InFile, 0, false));
+ return CreateASTPrinter(CI.createDefaultOutputFile(false, InFile));
case ASTPrintXML:
- return CreateASTPrinterXML(ComputeOutFile(CI, InFile, "xml", false));
+ return CreateASTPrinterXML(CI.createDefaultOutputFile(false, InFile,
+ "xml"));
case ASTDump:
return CreateASTDumper();
llvm::OwningPtr<llvm::raw_ostream> OS;
if (ProgAction == EmitAssembly) {
Act = Backend_EmitAssembly;
- OS.reset(ComputeOutFile(CI, InFile, "s", true));
+ OS.reset(CI.createDefaultOutputFile(false, InFile, "s"));
} else if (ProgAction == EmitLLVM) {
Act = Backend_EmitLL;
- OS.reset(ComputeOutFile(CI, InFile, "ll", true));
+ OS.reset(CI.createDefaultOutputFile(false, InFile, "ll"));
} else if (ProgAction == EmitLLVMOnly) {
Act = Backend_EmitNothing;
} else {
Act = Backend_EmitBC;
- OS.reset(ComputeOutFile(CI, InFile, "bc", true));
+ OS.reset(CI.createDefaultOutputFile(true, InFile, "bc"));
}
// Fix-its can change semantics, disallow with any IRgen action.
}
case RewriteObjC:
- return CreateObjCRewriter(InFile, ComputeOutFile(CI, InFile, "cpp", true),
+ return CreateObjCRewriter(InFile,
+ CI.createDefaultOutputFile(true, InFile, "cpp"),
PP.getDiagnostics(), PP.getLangOptions(),
CI.getDiagnosticOpts().NoRewriteMacros);
break;
case EmitHTML:
- Consumer.reset(CreateHTMLPrinter(ComputeOutFile(CI, InFile, 0, true), PP));
+ Consumer.reset(CreateHTMLPrinter(CI.createDefaultOutputFile(false, InFile),
+ PP));
break;
case RunAnalysis:
Relocatable = false;
}
- llvm::raw_ostream *OS = ComputeOutFile(CI, InFile, 0, true);
+ llvm::raw_ostream *OS = CI.createDefaultOutputFile(true, InFile);
if (Relocatable)
Consumer.reset(CreatePCHGenerator(PP, OS, Sysroot.c_str()));
else
llvm::errs() << "ERROR: PTH requires an seekable file for output!\n";
::exit(1);
}
- CacheTokens(PP, ComputeOutFile(CI, InFile, 0, true));
+ CacheTokens(PP, CI.createDefaultOutputFile(true, InFile));
break;
case ParseNoop:
break;
case ParsePrintCallbacks: {
- llvm::raw_ostream *OS = ComputeOutFile(CI, InFile, 0, true);
+ llvm::raw_ostream *OS = CI.createDefaultOutputFile(false, InFile);
ParseFile(PP, CreatePrintParserActionsAction(PP, OS));
break;
}
case PrintPreprocessedInput:
- DoPrintPreprocessedInput(PP, ComputeOutFile(CI, InFile, 0, true),
+ DoPrintPreprocessedInput(PP, CI.createDefaultOutputFile(false, InFile),
CI.getPreprocessorOutputOpts());
break;
case RewriteMacros:
- RewriteMacrosInInput(PP, ComputeOutFile(CI, InFile, 0, true));
+ RewriteMacrosInInput(PP, CI.createDefaultOutputFile(true, InFile));
break;
case RewriteTest:
- DoRewriteTest(PP, ComputeOutFile(CI, InFile, 0, true));
+ DoRewriteTest(PP, CI.createDefaultOutputFile(false, InFile));
break;
case RunPreprocessorOnly: { // Just lex as fast as we can, no output.