clang-cl: Implement support for the /Fo option
This implements support for the /Fo option, which is used
to set the filename or output dir for object files.
Differential Revision: http://llvm-reviews.chandlerc.com/D1302
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@187820 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Driver/Driver.cpp b/lib/Driver/Driver.cpp
index 84e5fe2..729b9af 100644
--- a/lib/Driver/Driver.cpp
+++ b/lib/Driver/Driver.cpp
@@ -357,6 +357,30 @@
InputList Inputs;
BuildInputs(C->getDefaultToolChain(), C->getArgs(), Inputs);
+ if (Arg *A = C->getArgs().getLastArg(options::OPT__SLASH_Fo)) {
+ // Check for multiple /Fo arguments.
+ for (arg_iterator it = C->getArgs().filtered_begin(options::OPT__SLASH_Fo),
+ ie = C->getArgs().filtered_end(); it != ie; ++it) {
+ if (*it != A) {
+ Diag(clang::diag::warn_drv_overriding_fo_option)
+ << (*it)->getSpelling() << (*it)->getValue()
+ << A->getSpelling() << A->getValue();
+ }
+ }
+
+ StringRef V = A->getValue();
+ if (V == "") {
+ // It has to have a value.
+ Diag(clang::diag::err_drv_missing_argument) << A->getSpelling() << 1;
+ C->getArgs().eraseArg(options::OPT__SLASH_Fo);
+ } else if (Inputs.size() > 1 && !llvm::sys::path::is_separator(V.back())) {
+ // Check whether /Fo tries to name an output file for multiple inputs.
+ Diag(clang::diag::err_drv_obj_file_argument_with_multiple_sources)
+ << A->getSpelling() << V;
+ C->getArgs().eraseArg(options::OPT__SLASH_Fo);
+ }
+ }
+
// Construct the list of abstract actions to perform for this compilation. On
// Darwin target OSes this uses the driver-driver and universal actions.
if (TC.getTriple().isOSDarwin())
@@ -1559,7 +1583,8 @@
return "-";
// Output to a temporary file?
- if ((!AtTopLevel && !C.getArgs().hasArg(options::OPT_save_temps)) ||
+ if ((!AtTopLevel && !C.getArgs().hasArg(options::OPT_save_temps) &&
+ !C.getArgs().hasArg(options::OPT__SLASH_Fo)) ||
CCGenDiagnostics) {
StringRef Name = llvm::sys::path::filename(BaseInput);
std::pair<StringRef, StringRef> Split = Name.split('.');
@@ -1579,7 +1604,28 @@
// Determine what the derived output name should be.
const char *NamedOutput;
- if (JA.getType() == types::TY_Image) {
+
+ if (JA.getType() == types::TY_Object &&
+ C.getArgs().hasArg(options::OPT__SLASH_Fo)) {
+ // The /Fo flag decides the object filename.
+ StringRef Val = C.getArgs().getLastArg(options::OPT__SLASH_Fo)->getValue();
+ SmallString<128> Filename = Val;
+
+ if (llvm::sys::path::is_separator(Val.back())) {
+ // If /Fo names a dir, output to BaseName in that dir.
+ llvm::sys::path::append(Filename, BaseName);
+ }
+ if (!llvm::sys::path::has_extension(Val)) {
+ // If /Fo doesn't provide a filename with an extension, we set it.
+ if (llvm::sys::path::has_extension(Filename.str()))
+ Filename = Filename.substr(0, Filename.rfind("."));
+ Filename.append(".");
+ // FIXME: For clang-cl, we want .obj rather than .o for object files.
+ Filename.append(types::getTypeTempSuffix(types::TY_Object));
+ }
+
+ NamedOutput = C.getArgs().MakeArgString(Filename.c_str());
+ } else if (JA.getType() == types::TY_Image) {
if (MultipleArchs && BoundArch) {
SmallString<128> Output(DefaultImageName.c_str());
Output += "-";