[PATCH] clang-cl: Implement support for the /Fo option

Hans Wennborg hans at chromium.org
Tue Aug 6 14:39:14 PDT 2013


  New patch to address Reid's comments.

Hi rnk,

http://llvm-reviews.chandlerc.com/D1302

CHANGE SINCE LAST DIFF
  http://llvm-reviews.chandlerc.com/D1302?vs=3229&id=3232#toc

Files:
  include/clang/Basic/DiagnosticDriverKinds.td
  include/clang/Driver/CLCompatOptions.td
  lib/Driver/Driver.cpp
  test/Driver/cl-Fo.c
  test/Driver/cl-options.c

Index: include/clang/Basic/DiagnosticDriverKinds.td
===================================================================
--- include/clang/Basic/DiagnosticDriverKinds.td
+++ include/clang/Basic/DiagnosticDriverKinds.td
@@ -33,6 +33,8 @@
   "unsupported use of internal gcc -Z option '%0'">;
 def err_drv_output_argument_with_multiple_files : Error<
   "cannot specify -o when generating multiple output files">;
+def err_drv_obj_file_argument_with_multiple_sources : Error<
+  "cannot specify '%0%1' when compiling multiple source files">;
 def err_no_external_windows_assembler : Error<
   "there is no external assembler we can use on windows">;
 def err_drv_unable_to_remove_file : Error<
@@ -133,6 +135,9 @@
   "unknown platform, assuming -mfloat-abi=%0">;
 def warn_ignoring_ftabstop_value : Warning<
   "ignoring invalid -ftabstop value '%0', using default value %1">;
+def warn_drv_overriding_fo_option : Warning<
+  "overriding '%0%1' option with '%2%3'">,
+  InGroup<DiagGroup<"overriding-fo-option">>;
 def warn_drv_overriding_t_option : Warning<
   "overriding '%0' option with '%1'">,
   InGroup<DiagGroup<"overriding-t-option">>;
Index: include/clang/Driver/CLCompatOptions.td
===================================================================
--- include/clang/Driver/CLCompatOptions.td
+++ include/clang/Driver/CLCompatOptions.td
@@ -83,6 +83,9 @@
 
 // Non-aliases:
 
+def _SLASH_Fo : CLJoined<"Fo">,
+  HelpText<"Set output object file, or directory (ends in / or \\)">,
+  MetaVarName<"<file or directory>">;
 def _SLASH_Tc : CLJoinedOrSeparate<"Tc">, HelpText<"Specify a C source file">,
   MetaVarName<"<filename>">;
 def _SLASH_TC : CLFlag<"TC">, HelpText<"Treat all source files as C">;
@@ -106,7 +109,6 @@
 
 def _SLASH_EH : CLJoined<"EH">;
 def _SLASH_Fd : CLJoined<"Fd">;
-def _SLASH_Fo : CLJoined<"Fo">;
 def _SLASH_fp : CLJoined<"fp">;
 def _SLASH_Gd : CLFlag<"Gd">;
 def _SLASH_GL : CLFlag<"GL">;
Index: lib/Driver/Driver.cpp
===================================================================
--- lib/Driver/Driver.cpp
+++ 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 += "-";
Index: test/Driver/cl-Fo.c
===================================================================
--- /dev/null
+++ test/Driver/cl-Fo.c
@@ -0,0 +1,34 @@
+// Don't attempt slash switches on msys bash.
+// REQUIRES: shell-preserves-root
+
+// Note: %s must be preceded by --, otherwise it may be interpreted as a
+// command-line option, e.g. on Mac where %s is commonly under /Users.
+
+// RUN: %clang_cl /Foa -### -- %s 2>&1 | FileCheck -check-prefix=CHECK-NAME %s
+// CHECK-NAME:  "-o" "a.o"
+
+// RUN: %clang_cl /Foa.ext /Fob.ext -### -- %s 2>&1 | FileCheck -check-prefix=CHECK-NAMEEXT %s
+// CHECK-NAMEEXT:  warning: overriding '/Foa.ext' option with '/Fob.ext'
+// CHECK-NAMEEXT:  "-o" "b.ext"
+
+// RUN: %clang_cl /Fofoo.dir/ -### -- %s 2>&1 | FileCheck -check-prefix=CHECK-DIR %s
+// CHECK-DIR:  "-o" "foo.dir{{[/\\]+}}cl-Fo.o"
+
+// RUN: %clang_cl /Fofoo.dir/a -### -- %s 2>&1 | FileCheck -check-prefix=CHECK-DIRNAME %s
+// CHECK-DIRNAME:  "-o" "foo.dir{{[/\\]+}}a.o"
+
+// RUN: %clang_cl /Fofoo.dir/a.ext -### -- %s 2>&1 | FileCheck -check-prefix=CHECK-DIRNAMEEXT %s
+// CHECK-DIRNAMEEXT:  "-o" "foo.dir{{[/\\]+}}a.ext"
+
+// RUN: %clang_cl /Fo.. -### -- %s 2>&1 | FileCheck -check-prefix=CHECK-CRAZY %s
+// CHECK-CRAZY:  "-o" "...o"
+
+
+// RUN: %clang_cl /Fo -### 2>&1 | FileCheck -check-prefix=CHECK-MISSINGARG %s
+// CHECK-MISSINGARG: error: argument to '/Fo' is missing (expected 1 value)
+
+// RUN: %clang_cl /Foa.obj -### -- %s %s 2>&1 | FileCheck -check-prefix=CHECK-MULTIPLESOURCEERROR %s
+// CHECK-MULTIPLESOURCEERROR: error: cannot specify '/Foa.obj' when compiling multiple source files
+
+// RUN: %clang_cl /Fomydir/ -### -- %s %s 2>&1 | FileCheck -check-prefix=CHECK-MULTIPLESOURCEOK %s
+// CHECK-MULTIPLESOURCEOK: "-o" "mydir{{[/\\]+}}cl-Fo.o"
Index: test/Driver/cl-options.c
===================================================================
--- test/Driver/cl-options.c
+++ test/Driver/cl-options.c
@@ -88,7 +88,7 @@
 
 // Unsupported but parsed options. Check that we don't error on them.
 // (/Zs is for syntax-only)
-// RUN: %clang_cl /Zs /EHsc /Fdfoo /Fobar /fp:precise /Gd /GL /GL- -- %s 2>&1
+// RUN: %clang_cl /Zs /EHsc /Fdfoo /fp:precise /Gd /GL /GL- -- %s 2>&1
 // RUN: %clang_cl /Zs /Gm /Gm- /GS /Gy /Gy- /GZ /MD /MT /MDd /MTd /Oi -- %s 2>&1
 // RUN: %clang_cl /Zs /RTC1 /wfoo /Zc:wchar_t- -- %s 2>&1
 // RUN: %clang_cl /Zs /ZI /Zi /showIncludes -- %s 2>&1
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D1302.2.patch
Type: text/x-patch
Size: 7460 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20130806/23006b87/attachment.bin>


More information about the cfe-commits mailing list