- try to clean this up

http://reviews.llvm.org/D3771

Files:
  include/clang/Driver/Options.td
  lib/Driver/Driver.cpp
  test/Driver/cl-outputs.c
Index: include/clang/Driver/Options.td
===================================================================
--- include/clang/Driver/Options.td
+++ include/clang/Driver/Options.td
@@ -1237,7 +1237,8 @@
   HelpText<"Disable standard #include directories for the C++ standard library">;
 def nostdlib : Flag<["-"], "nostdlib">;
 def object : Flag<["-"], "object">;
-def o : JoinedOrSeparate<["-"], "o">, Flags<[DriverOption, RenderAsInput, CC1Option]>,
+def o : JoinedOrSeparate<["-"], "o">,
+  Flags<[DriverOption, RenderAsInput, CC1Option, CoreOption]>,
   HelpText<"Write output to <file>">, MetaVarName<"<file>">;
 def pagezero__size : JoinedOrSeparate<["-"], "pagezero_size">;
 def pass_exit_codes : Flag<["-", "--"], "pass-exit-codes">, Flags<[Unsupported]>;
Index: lib/Driver/Driver.cpp
===================================================================
--- lib/Driver/Driver.cpp
+++ lib/Driver/Driver.cpp
@@ -1606,17 +1606,41 @@
                                        bool AtTopLevel,
                                        bool MultipleArchs) const {
   llvm::PrettyStackTraceString CrashInfo("Computing output path");
-  // Output to a user requested destination?
-  if (AtTopLevel && !isa<DsymutilJobAction>(JA) &&
-      !isa<VerifyJobAction>(JA)) {
-    if (Arg *FinalOutput = C.getArgs().getLastArg(options::OPT_o))
-      return C.addResultFile(FinalOutput->getValue(), &JA);
+  StringRef BaseName = llvm::sys::path::filename(BaseInput);
+
+  if (!isa<DsymutilJobAction>(JA) && !isa<VerifyJobAction>(JA)) {
+    // Only apply -o to the output of the top level action.
+    options::ID MaybeDashO = AtTopLevel ? options::OPT_o : options::OPT_INVALID;
+    // Find the last clang-cl output argument that is relevant to the current job.
+    options::ID MaybeCLOpt;
+    switch (JA.getType()) {
+    case types::TY_PP_Asm: MaybeCLOpt = options::OPT__SLASH_Fa; break;
+    case types::TY_Object: MaybeCLOpt = options::OPT__SLASH_Fo; break;
+    case types::TY_Image:  MaybeCLOpt = options::OPT__SLASH_Fe; break;
+    default: MaybeCLOpt = options::OPT_INVALID; break;
+    }
+    Arg *OutputArg = C.getArgs().getLastArg(MaybeDashO, MaybeCLOpt);
+
+    // If we had an explicit output argument, honor it.
+    if (OutputArg) {
+      Option Op = OutputArg->getOption();
+      const char *NamedOutput;
+      if (Op.matches(options::OPT__SLASH_Fa) ||
+          Op.matches(options::OPT__SLASH_Fo) ||
+          Op.matches(options::OPT__SLASH_Fe)) {
+        NamedOutput = MakeCLOutputFilename(C.getArgs(), OutputArg->getValue(),
+                                           BaseName, JA.getType());
+      } else {
+        assert(Op.matches(options::OPT_o));
+        NamedOutput = OutputArg->getValue();
+      }
+      return C.addResultFile(NamedOutput, &JA);
+    }
   }
 
   // For /P, preprocess to file named after BaseInput.
   if (C.getArgs().hasArg(options::OPT__SLASH_P)) {
     assert(AtTopLevel && isa<PreprocessJobAction>(JA));
-    StringRef BaseName = llvm::sys::path::filename(BaseInput);
     return C.addResultFile(MakeCLOutputFilename(C.getArgs(), "", BaseName,
                                                 types::TY_PP_C), &JA);
   }
@@ -1627,19 +1651,13 @@
     return "-";
 
   // Is this the assembly listing for /FA?
-  if (JA.getType() == types::TY_PP_Asm &&
-      (C.getArgs().hasArg(options::OPT__SLASH_FA) ||
-       C.getArgs().hasArg(options::OPT__SLASH_Fa))) {
-    // Use /Fa and the input filename to determine the asm file name.
-    StringRef BaseName = llvm::sys::path::filename(BaseInput);
-    StringRef FaValue = C.getArgs().getLastArgValue(options::OPT__SLASH_Fa);
-    return C.addResultFile(MakeCLOutputFilename(C.getArgs(), FaValue, BaseName,
-                                                JA.getType()), &JA);
+  if (C.getArgs().hasArg(options::OPT__SLASH_FA)) {
+    return C.addResultFile(
+        MakeCLOutputFilename(C.getArgs(), "", BaseName, JA.getType()), &JA);
   }
 
   // Output to a temporary file?
-  if ((!AtTopLevel && !C.getArgs().hasArg(options::OPT_save_temps) &&
-        !C.getArgs().hasArg(options::OPT__SLASH_Fo)) ||
+  if ((!AtTopLevel && !C.getArgs().hasArg(options::OPT_save_temps)) ||
       CCGenDiagnostics) {
     StringRef Name = llvm::sys::path::filename(BaseInput);
     std::pair<StringRef, StringRef> Split = Name.split('.');
@@ -1649,31 +1667,14 @@
     return C.addTempFile(C.getArgs().MakeArgString(TmpName.c_str()));
   }
 
-  SmallString<128> BasePath(BaseInput);
-  StringRef BaseName;
-
   // Dsymutil actions should use the full path.
   if (isa<DsymutilJobAction>(JA) || isa<VerifyJobAction>(JA))
-    BaseName = BasePath;
-  else
-    BaseName = llvm::sys::path::filename(BasePath);
+    BaseName = BaseInput;
 
   // Determine what the derived output name should be.
   const char *NamedOutput;
 
-  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();
-    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 (JA.getType() == types::TY_Image) {
     if (IsCLMode()) {
       // clang-cl uses BaseName for the executable name.
       NamedOutput = MakeCLOutputFilename(C.getArgs(), "", BaseName,
@@ -1725,6 +1726,7 @@
 
   // As an annoying special case, PCH generation doesn't strip the pathname.
   if (JA.getType() == types::TY_PCH) {
+    SmallString<128> BasePath(BaseInput);
     llvm::sys::path::remove_filename(BasePath);
     if (BasePath.empty())
       BasePath = NamedOutput;
Index: test/Driver/cl-outputs.c
===================================================================
--- test/Driver/cl-outputs.c
+++ test/Driver/cl-outputs.c
@@ -109,3 +109,31 @@
 // RUN: %clang_cl /P -### -- %s 2>&1 | FileCheck -check-prefix=P %s
 // P: "-E"
 // P: "-o" "cl-outputs.i"
+
+// Last arg wins between -o and -Fo for simple compilation.
+// RUN: %clang_cl -c -o t1.obj -Fot2.obj -### -- %s 2>&1 | FileCheck %s -check-prefix o_Fo
+// o_Fo: "-cc1"
+// o_Fo: "-o" "t2.obj"
+// RUN: %clang_cl -c -Fot1.obj -o t2.obj -### -- %s 2>&1 | FileCheck %s -check-prefix Fo_o
+// Fo_o: "-cc1"
+// Fo_o: "-o" "t2.obj"
+
+// Last arg wins between -o and -Fe for linked images.
+// RUN: %clang_cl -o t1.exe -Fet2.exe -### -- %s 2>&1 | FileCheck %s -check-prefix o_Fe
+// o_Fe: "-cc1"
+// o_Fe: link.exe
+// o_Fe: "-out:t2.exe"
+// RUN: %clang_cl -Fet1.exe -o t2.exe -### -- %s 2>&1 | FileCheck %s -check-prefix Fe_o
+// Fe_o: "-cc1"
+// Fe_o: link.exe
+// Fe_o: "-out:t2.exe"
+
+// -Fo and -Fa work for intermediate outputs.
+// RUN: %clang_cl -Fat.s -Fot.obj -o t.exe -### -- %s 2>&1 | FileCheck %s -check-prefix Fa_Fo_o
+// Fa_Fo_o: "-cc1"
+// Fa_Fo_o: "-S"
+// Fa_Fo_o: "-o" "t.s"
+// Fa_Fo_o: "-cc1as"
+// Fa_Fo_o: "-o" "t.obj"
+// Fa_Fo_o: link.exe
+// Fa_Fo_o: "-out:t.exe"
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits

Reply via email to