r188210 - clang-cl: Support the /Fe option

Hans Wennborg hans at hanshq.net
Mon Aug 12 14:56:42 PDT 2013


Author: hans
Date: Mon Aug 12 16:56:42 2013
New Revision: 188210

URL: http://llvm.org/viewvc/llvm-project?rev=188210&view=rev
Log:
clang-cl: Support the /Fe option

This is used to name the linked output file.

Differential Revision: http://llvm-reviews.chandlerc.com/D1344

Added:
    cfe/trunk/test/Driver/cl-Fe.c
Modified:
    cfe/trunk/include/clang/Basic/DiagnosticDriverKinds.td
    cfe/trunk/include/clang/Driver/CLCompatOptions.td
    cfe/trunk/lib/Driver/Driver.cpp
    cfe/trunk/lib/Driver/Types.cpp
    cfe/trunk/test/Driver/cl-Fo.c

Modified: cfe/trunk/include/clang/Basic/DiagnosticDriverKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticDriverKinds.td?rev=188210&r1=188209&r2=188210&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticDriverKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticDriverKinds.td Mon Aug 12 16:56:42 2013
@@ -135,7 +135,7 @@ def warn_drv_assuming_mfloat_abi_is : Wa
   "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<
+def warn_drv_overriding_joined_option : Warning<
   "overriding '%0%1' option with '%2%3'">,
   InGroup<DiagGroup<"overriding-fo-option">>;
 def warn_drv_overriding_t_option : Warning<

Modified: cfe/trunk/include/clang/Driver/CLCompatOptions.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Driver/CLCompatOptions.td?rev=188210&r1=188209&r2=188210&view=diff
==============================================================================
--- cfe/trunk/include/clang/Driver/CLCompatOptions.td (original)
+++ cfe/trunk/include/clang/Driver/CLCompatOptions.td Mon Aug 12 16:56:42 2013
@@ -90,6 +90,9 @@ def _SLASH_Zs : CLFlag<"Zs">, HelpText<"
 
 // Non-aliases:
 
+def _SLASH_Fe : CLJoined<"Fe">,
+  HelpText<"Set output executable file or directory (ends in / or \\)">,
+  MetaVarName<"<file or directory>">;
 def _SLASH_Fo : CLJoined<"Fo">,
   HelpText<"Set output object file, or directory (ends in / or \\)">,
   MetaVarName<"<file or directory>">;

Modified: cfe/trunk/lib/Driver/Driver.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Driver/Driver.cpp?rev=188210&r1=188209&r2=188210&view=diff
==============================================================================
--- cfe/trunk/lib/Driver/Driver.cpp (original)
+++ cfe/trunk/lib/Driver/Driver.cpp Mon Aug 12 16:56:42 2013
@@ -267,6 +267,26 @@ DerivedArgList *Driver::TranslateInputAr
   return DAL;
 }
 
+/// \brief Check whether there are multiple instances of OptionID in Args, and
+/// if so, issue a diagnostics about it.
+static void DiagnoseOptionOverride(const Driver &D, const DerivedArgList &Args,
+                                   unsigned OptionID) {
+  assert(Args.hasArg(OptionID));
+
+  arg_iterator it = Args.filtered_begin(OptionID);
+  arg_iterator ie = Args.filtered_end();
+  Arg *Previous = *it;
+  ++it;
+
+  while (it != ie) {
+    D.Diag(clang::diag::warn_drv_overriding_joined_option)
+        << Previous->getSpelling() << Previous->getValue()
+        << (*it)->getSpelling() << (*it)->getValue();
+    Previous = *it;
+    ++it;
+  }
+}
+
 Compilation *Driver::BuildCompilation(ArrayRef<const char *> ArgList) {
   llvm::PrettyStackTraceString CrashInfo("Compilation construction");
 
@@ -358,18 +378,9 @@ Compilation *Driver::BuildCompilation(Ar
   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();
-      }
-    }
-
+    DiagnoseOptionOverride(*this, C->getArgs(), options::OPT__SLASH_Fo);
     StringRef V = A->getValue();
-    if (V == "") {
+    if (V.empty()) {
       // It has to have a value.
       Diag(clang::diag::err_drv_missing_argument) << A->getSpelling() << 1;
       C->getArgs().eraseArg(options::OPT__SLASH_Fo);
@@ -381,6 +392,16 @@ Compilation *Driver::BuildCompilation(Ar
     }
   }
 
+  if (Arg *A = C->getArgs().getLastArg(options::OPT__SLASH_Fe)) {
+    DiagnoseOptionOverride(*this, C->getArgs(), options::OPT__SLASH_Fe);
+
+    if (A->getValue()[0] == '\0') {
+      // It has to have a value.
+      Diag(clang::diag::err_drv_missing_argument) << A->getSpelling() << 1;
+      C->getArgs().eraseArg(options::OPT__SLASH_Fe);
+    }
+  }
+
   // 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())
@@ -1565,6 +1586,27 @@ void Driver::BuildJobsForAction(Compilat
   }
 }
 
+/// \brief Create output filename based on ArgValue, which could either be a 
+/// full filename, filename without extension, or a directory.
+static const char *MakeCLOutputFilename(const ArgList &Args, StringRef ArgValue,
+                                        StringRef BaseName, types::ID FileType) {
+  SmallString<128> Filename = ArgValue;
+  assert(!ArgValue.empty() && "Output filename argument must not be empty.");
+  
+  if (llvm::sys::path::is_separator(Filename.back())) {
+    // If the argument is a directory, output to BaseName in that dir.
+    llvm::sys::path::append(Filename, BaseName);
+  }
+
+  if (!llvm::sys::path::has_extension(ArgValue)) {
+    // If the argument didn't provide an extension, then set it.
+    const char *Extension = types::getTypeTempSuffix(FileType, true);
+    llvm::sys::path::replace_extension(Filename, Extension);
+  }
+
+  return Args.MakeArgString(Filename.c_str());
+}
+
 const char *Driver::GetNamedOutputPath(Compilation &C,
                                        const JobAction &JA,
                                        const char *BaseInput,
@@ -1612,23 +1654,21 @@ const char *Driver::GetNamedOutputPath(C
       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(".");
-      Filename.append(types::getTypeTempSuffix(types::TY_Object, IsCLMode()));
-    }
-
-    NamedOutput = C.getArgs().MakeArgString(Filename.c_str());
+    NamedOutput = MakeCLOutputFilename(C.getArgs(), Val, BaseName,
+                                       types::TY_Object);
+  } else if (JA.getType() == types::TY_Image &&
+             C.getArgs().hasArg(options::OPT__SLASH_Fe)) {
+    // The /Fe flag names the linked file.
+    StringRef Val = C.getArgs().getLastArg(options::OPT__SLASH_Fe)->getValue();
+    NamedOutput = MakeCLOutputFilename(C.getArgs(), Val, BaseName,
+                                       types::TY_Image);
   } else if (JA.getType() == types::TY_Image) {    
-    if (MultipleArchs && BoundArch) {
+    if (IsCLMode()) {
+      // clang-cl uses BaseName for the executable name.
+      SmallString<128> Filename = BaseName;
+      llvm::sys::path::replace_extension(Filename, "exe");
+      NamedOutput = C.getArgs().MakeArgString(Filename.c_str());
+    } else if (MultipleArchs && BoundArch) {
       SmallString<128> Output(DefaultImageName.c_str());
       Output += "-";
       Output.append(BoundArch);

Modified: cfe/trunk/lib/Driver/Types.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Driver/Types.cpp?rev=188210&r1=188209&r2=188210&view=diff
==============================================================================
--- cfe/trunk/lib/Driver/Types.cpp (original)
+++ cfe/trunk/lib/Driver/Types.cpp Mon Aug 12 16:56:42 2013
@@ -47,6 +47,8 @@ types::ID types::getPreprocessedType(ID
 const char *types::getTypeTempSuffix(ID Id, bool CLMode) {
   if (Id == TY_Object && CLMode)
     return "obj";
+  if (Id == TY_Image && CLMode)
+    return "exe";
   return getInfo(Id).TempSuffix;
 }
 

Added: cfe/trunk/test/Driver/cl-Fe.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Driver/cl-Fe.c?rev=188210&view=auto
==============================================================================
--- cfe/trunk/test/Driver/cl-Fe.c (added)
+++ cfe/trunk/test/Driver/cl-Fe.c Mon Aug 12 16:56:42 2013
@@ -0,0 +1,31 @@
+// 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 -### -- %s 2>&1 | FileCheck -check-prefix=DEFAULTEXE %s
+// DEFAULTEXE: cl-Fe.exe
+
+// RUN: %clang_cl /Fefoo -### -- %s 2>&1 | FileCheck -check-prefix=FeNOEXT %s
+// FeNOEXT: foo.exe
+
+// RUN: %clang_cl /Fefoo.ext -### -- %s 2>&1 | FileCheck -check-prefix=FeEXT %s
+// FeEXT: foo.ext
+
+// RUN: %clang_cl /Fefoo.dir/ -### -- %s 2>&1 | FileCheck -check-prefix=FeDIR %s
+// FeDIR: foo.dir{{[/\\]+}}cl-Fe.exe
+
+// RUN: %clang_cl /Fefoo.dir/a -### -- %s 2>&1 | FileCheck -check-prefix=FeDIRNAME %s
+// FeDIRNAME: foo.dir{{[/\\]+}}a.exe
+
+// RUN: %clang_cl /Fefoo.dir/a.ext -### -- %s 2>&1 | FileCheck -check-prefix=FeDIRNAMEEXT %s
+// FeDIRNAMEEXT: foo.dir{{[/\\]+}}a.ext
+
+// RUN: %clang_cl /Fe -### 2>&1 | FileCheck -check-prefix=MISSINGARG %s
+// MISSINGARG: error: argument to '/Fe' is missing (expected 1 value)
+
+// RUN: %clang_cl /Fefoo /Febar -### -- %s 2>&1 | FileCheck -check-prefix=FEOVERRIDE %s
+// FEOVERRIDE: warning: overriding '/Fefoo' option with '/Febar'
+// FEOVERRIDE: bar.exe

Modified: cfe/trunk/test/Driver/cl-Fo.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Driver/cl-Fo.c?rev=188210&r1=188209&r2=188210&view=diff
==============================================================================
--- cfe/trunk/test/Driver/cl-Fo.c (original)
+++ cfe/trunk/test/Driver/cl-Fo.c Mon Aug 12 16:56:42 2013
@@ -21,7 +21,7 @@
 // CHECK-DIRNAMEEXT:  "-o" "foo.dir{{[/\\]+}}a.ext"
 
 // RUN: %clang_cl /Fo.. -### -- %s 2>&1 | FileCheck -check-prefix=CHECK-CRAZY %s
-// CHECK-CRAZY:  "-o" "...obj"
+// CHECK-CRAZY:  "-o" "..obj"
 
 
 // RUN: %clang_cl /Fo -### 2>&1 | FileCheck -check-prefix=CHECK-MISSINGARG %s





More information about the cfe-commits mailing list