Make getLinkerFileListName more similar to getDependencyFileName.  Add an 
assertion.  Tweak some variable names as per review comments.

http://reviews.llvm.org/D4104

Files:
  include/clang/Basic/DiagnosticDriverKinds.td
  include/clang/Driver/Options.td
  lib/Driver/Tools.cpp
  lib/Driver/Tools.h
  test/Driver/Inputs/filelist/a.o
  test/Driver/Inputs/filelist/a.obj
  test/Driver/Inputs/filelist/b.o
  test/Driver/Inputs/filelist/c.a
  test/Driver/filelist.c
Index: include/clang/Basic/DiagnosticDriverKinds.td
===================================================================
--- include/clang/Basic/DiagnosticDriverKinds.td
+++ include/clang/Basic/DiagnosticDriverKinds.td
@@ -39,6 +39,7 @@
   "cannot specify '%0%1' when compiling multiple source files">;
 def err_no_external_assembler : Error<
   "there is no external assembler that can be used on this platform">;
+def err_drv_unable_to_open_file : Error< "unable to open file: %0">;
 def err_drv_unable_to_remove_file : Error<
   "unable to remove file: %0">;
 def err_drv_command_failure : Error<
Index: include/clang/Driver/Options.td
===================================================================
--- include/clang/Driver/Options.td
+++ include/clang/Driver/Options.td
@@ -1384,6 +1384,8 @@
 def : Flag<["-"], "no-integrated-as">, Alias<fno_integrated_as>,
       Flags<[CC1Option, DriverOption]>;
 
+def fuse_linker_response_files : Joined<["-"], "fuse-linker-response-files">;
+
 def working_directory : JoinedOrSeparate<["-"], "working-directory">, Flags<[CC1Option]>,
   HelpText<"Resolve file paths relative to the specified directory">;
 def working_directory_EQ : Joined<["-"], "working-directory=">, Flags<[CC1Option]>,
Index: lib/Driver/Tools.cpp
===================================================================
--- lib/Driver/Tools.cpp
+++ lib/Driver/Tools.cpp
@@ -39,6 +39,7 @@
 #include "llvm/Support/Program.h"
 #include "llvm/Support/raw_ostream.h"
 #include <sys/stat.h>
+#include <fstream>
 
 using namespace clang::driver;
 using namespace clang::driver::tools;
@@ -168,11 +169,17 @@
   }
 }
 
-static void AddLinkerInputs(const ToolChain &TC,
+static void AddLinkerInputs(Compilation &C, const ToolChain &TC,
                             const InputInfoList &Inputs, const ArgList &Args,
                             ArgStringList &CmdArgs) {
+  const bool UseLinkerResponseFiles =
+    Args.hasArg(options::OPT_fuse_linker_response_files);
   const Driver &D = TC.getDriver();
 
+  const char *CurrentFileListName;
+  std::ofstream CurrentFileList;
+  unsigned FileListSequence = 0;
+
   // Add extra linker input arguments which are not treated as inputs
   // (constructed via -Xarch_).
   Args.AddAllArgValues(CmdArgs, options::OPT_Zlinker_input);
@@ -190,10 +197,35 @@
 
     // Add filenames immediately.
     if (II.isFilename()) {
-      CmdArgs.push_back(II.getFilename());
+      if (UseLinkerResponseFiles && II.getType() == types::TY_Object) {
+        if (!CurrentFileList.is_open()) {
+          CurrentFileListName =
+            Clang::getLinkerFileListName(Args, Inputs, FileListSequence++);
+
+          // Skip the leading '@'
+          assert(CurrentFileListName[0] == '@' && "expected '@' prefixed name");
+          CurrentFileList.open(&CurrentFileListName[1],
+                               std::ios_base::trunc | std::ios_base::out);
+          if (!CurrentFileList.is_open())
+            D.Diag(diag::err_drv_unable_to_open_file) << CurrentFileListName;
+          C.addTempFile(CurrentFileListName);
+        }
+        CurrentFileList << II.getFilename() << std::endl;
+      } else {
+        if (CurrentFileList.is_open()) {
+          CurrentFileList.close();
+          CmdArgs.push_back(CurrentFileListName);
+        }
+        CmdArgs.push_back(II.getFilename());
+      }
       continue;
     }
 
+    if (CurrentFileList.is_open()) {
+      CurrentFileList.close();
+      CmdArgs.push_back(CurrentFileListName);
+    }
+
     // Otherwise, this is a linker input argument.
     const Arg &A = II.getInputArg();
 
@@ -206,6 +238,13 @@
       A.renderAsInput(Args, CmdArgs);
   }
 
+  // NOTE this is needed here to handle the case where an object file is the
+  // last argument; otherwise, we don't properly close the file list.
+  if (CurrentFileList.is_open()) {
+    CurrentFileList.close();
+    CmdArgs.push_back(CurrentFileListName);
+  }
+
   // LIBRARY_PATH - included following the user specified library paths.
   //                and only supported on native toolchains.
   if (!TC.isCrossCompiling())
@@ -4886,7 +4925,7 @@
   Args.AddAllArgs(CmdArgs, options::OPT_t);
   Args.AddAllArgs(CmdArgs, options::OPT_u_Group);
 
-  AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs);
+  AddLinkerInputs(C, ToolChain, Inputs, Args, CmdArgs);
 
   //----------------------------------------------------------------------------
   // Libraries
@@ -5153,6 +5192,26 @@
   return Args.MakeArgString(Res + ".d");
 }
 
+const char *Clang::getLinkerFileListName(const llvm::opt::ArgList &Args,
+                                         const InputInfoList &Inputs,
+                                         unsigned SequenceNumber) {
+  std::string Buffer;
+  llvm::raw_string_ostream Name(Buffer);
+
+  // Add the prefix so as to ensure that it is made part of the argument string
+  Name << "@";
+
+  if (Arg *Output = Args.getLastArg(options::OPT_o)) {
+    StringRef Value = Output->getValue();
+    Name << Value.substr(0, Value.rfind('.'));
+  } else {
+    Name << getBaseInputStem(Args, Inputs);
+  }
+
+  Name << SequenceNumber << ".rsp";
+  return Args.MakeArgString(Name.str());
+}
+
 void darwin::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
                                     const InputInfo &Output,
                                     const InputInfoList &Inputs,
@@ -5503,7 +5562,7 @@
     break;
   }
 
-  AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs);
+  AddLinkerInputs(C, getToolChain(), Inputs, Args, CmdArgs);
   
   if (isObjCRuntimeLinked(Args) &&
       !Args.hasArg(options::OPT_nostdlib) &&
@@ -5545,8 +5604,7 @@
   Args.AddAllArgs(CmdArgs, options::OPT_T_Group);
   Args.AddAllArgs(CmdArgs, options::OPT_F);
 
-  const char *Exec =
-    Args.MakeArgString(getToolChain().GetProgramPath("ld"));
+  const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("ld"));
   C.addCommand(new Command(JA, *this, Exec, CmdArgs));
 }
 
@@ -5713,7 +5771,7 @@
   Args.AddAllArgs(CmdArgs, options::OPT_e);
   Args.AddAllArgs(CmdArgs, options::OPT_r);
 
-  AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs);
+  AddLinkerInputs(C, getToolChain(), Inputs, Args, CmdArgs);
 
   if (!Args.hasArg(options::OPT_nostdlib) &&
       !Args.hasArg(options::OPT_nodefaultlibs)) {
@@ -5735,8 +5793,7 @@
 
   addProfileRT(getToolChain(), Args, CmdArgs);
 
-  const char *Exec =
-    Args.MakeArgString(getToolChain().GetProgramPath("ld"));
+  const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("ld"));
   C.addCommand(new Command(JA, *this, Exec, CmdArgs));
 }
 
@@ -5819,7 +5876,7 @@
   Args.AddAllArgs(CmdArgs, options::OPT_T_Group);
   Args.AddAllArgs(CmdArgs, options::OPT_e);
 
-  AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs);
+  AddLinkerInputs(C, getToolChain(), Inputs, Args, CmdArgs);
 
   if (!Args.hasArg(options::OPT_nostdlib) &&
       !Args.hasArg(options::OPT_nodefaultlibs)) {
@@ -6001,7 +6058,7 @@
   Args.AddAllArgs(CmdArgs, options::OPT_Z_Flag);
   Args.AddAllArgs(CmdArgs, options::OPT_r);
 
-  AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs);
+  AddLinkerInputs(C, getToolChain(), Inputs, Args, CmdArgs);
 
   if (!Args.hasArg(options::OPT_nostdlib) &&
       !Args.hasArg(options::OPT_nodefaultlibs)) {
@@ -6127,7 +6184,7 @@
   Args.AddAllArgs(CmdArgs, options::OPT_T_Group);
   Args.AddAllArgs(CmdArgs, options::OPT_e);
 
-  AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs);
+  AddLinkerInputs(C, getToolChain(), Inputs, Args, CmdArgs);
 
   if (!Args.hasArg(options::OPT_nostdlib) &&
       !Args.hasArg(options::OPT_nodefaultlibs)) {
@@ -6376,7 +6433,7 @@
   if (D.IsUsingLTO(Args))
     AddGoldPlugin(ToolChain, Args, CmdArgs);
 
-  AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs);
+  AddLinkerInputs(C, ToolChain, Inputs, Args, CmdArgs);
 
   if (!Args.hasArg(options::OPT_nostdlib) &&
       !Args.hasArg(options::OPT_nodefaultlibs)) {
@@ -6638,7 +6695,7 @@
   Args.AddAllArgs(CmdArgs, options::OPT_Z_Flag);
   Args.AddAllArgs(CmdArgs, options::OPT_r);
 
-  AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs);
+  AddLinkerInputs(C, getToolChain(), Inputs, Args, CmdArgs);
 
   unsigned Major, Minor, Micro;
   getToolChain().getTriple().getOSVersion(Major, Minor, Micro);
@@ -7100,7 +7157,7 @@
   if (Args.hasArg(options::OPT_Z_Xlinker__no_demangle))
     CmdArgs.push_back("--no-demangle");
 
-  AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs);
+  AddLinkerInputs(C, ToolChain, Inputs, Args, CmdArgs);
 
   addSanitizerRuntimes(getToolChain(), Args, CmdArgs);
   // The profile runtime also needs access to system libraries.
@@ -7229,7 +7286,7 @@
   Args.AddAllArgs(CmdArgs, options::OPT_T_Group);
   Args.AddAllArgs(CmdArgs, options::OPT_e);
 
-  AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs);
+  AddLinkerInputs(C, getToolChain(), Inputs, Args, CmdArgs);
 
   addProfileRT(getToolChain(), Args, CmdArgs);
 
@@ -7357,7 +7414,7 @@
   Args.AddAllArgs(CmdArgs, options::OPT_T_Group);
   Args.AddAllArgs(CmdArgs, options::OPT_e);
 
-  AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs);
+  AddLinkerInputs(C, getToolChain(), Inputs, Args, CmdArgs);
 
   if (!Args.hasArg(options::OPT_nostdlib) &&
       !Args.hasArg(options::OPT_nodefaultlibs)) {
@@ -7693,7 +7750,7 @@
   if (EH.ShouldUseExceptionTables)
     CmdArgs.push_back("-fexceptions");
 
-  AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs);
+  AddLinkerInputs(C, getToolChain(), Inputs, Args, CmdArgs);
 
   const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("xcc"));
   C.addCommand(new Command(JA, *this, Exec, CmdArgs));
Index: lib/Driver/Tools.h
===================================================================
--- lib/Driver/Tools.h
+++ lib/Driver/Tools.h
@@ -40,6 +40,9 @@
                                         const InputInfoList &Inputs);
     static const char *getDependencyFileName(const llvm::opt::ArgList &Args,
                                              const InputInfoList &Inputs);
+    static const char *getLinkerFileListName(const llvm::opt::ArgList &Args,
+                                             const InputInfoList &Inputs,
+                                             unsigned SequenceNumber);
 
   private:
     void AddPreprocessingOptions(Compilation &C, const JobAction &JA,
Index: test/Driver/filelist.c
===================================================================
--- /dev/null
+++ test/Driver/filelist.c
@@ -0,0 +1,54 @@
+// Test handling of -fuse-linker-response-files
+
+// RUN: %clang -### %S/Inputs/filelist/a.o -o test 2>&1 \
+// RUN:   | FileCheck %s -check-prefix CHECK-NO-FILELIST
+
+// CHECK-NO-FILELIST-NOT: "@test0.rsp"
+// CHECK-NO-FILELIST: "{{.*}}/test/Driver/Inputs/filelist/a.o"
+
+// RUN: %clang -### -fuse-linker-response-files -save-temps %S/Inputs/filelist/a.o -o test 2>&1 \
+// RUN:   | FileCheck %s -check-prefix CHECK-FILELIST
+// RUN: FileCheck -check-prefix CHECK-FILELIST-0 %s < test0.rsp
+
+// CHECK-FILELIST-NOT: "{{.*}}/test/Driver/Inputs/filelist/a.o"
+// CHECK-FILELIST: "@test0.rsp"
+
+// CHECK-FILELIST-0: {{.*}}/test/Driver/Inputs/filelist/a.o
+
+// RUN: %clang -### -fuse-linker-response-files -save-temps %S/Inputs/filelist/a.o -library %S/Inputs/filelist/b.o -o test 2>&1 \
+// RUN:   | FileCheck %s -check-prefix CHECK-FILELIST-SPLIT
+// RUN: FileCheck -check-prefix CHECK-FILELIST-SPLIT-0 %s < test0.rsp
+// RUN: FileCheck -check-prefix CHECK-FILELIST-SPLIT-1 %s < test1.rsp
+
+// CHECK-FILELIST-SPLIT-NOT: "{{.*}}/test/Driver/Inputs/filelist/a.o"
+// CHECK-FILELIST-SPLIT: @test0.rsp
+// CHECK-FILELIST-SPLIT: -library
+// CHECK-FILELIST-SPLIT-NOT: "{{.*}}/test/Driver/Inputs/filelist/b.o"
+// CHECK-FILELIST-SPLIT: @test1.rsp
+
+// CHECK-FILELIST-SPLIT-0: a.o
+
+// CHECK-FILELIST-SPLIT-1: b.o
+
+// RUN: %clang '-###' -fuse-linker-response-files -save-temps %S/Inputs/filelist/a.o %S/Inputs/filelist/c.a %S/Inputs/filelist/b.o -o test 2>&1 \
+// RUN:   | FileCheck %s -check-prefix CHECK-FILELIST-ARCHIVES
+// RUN: FileCheck -check-prefix CHECK-FILELIST-ARCHIVES-0 %s < test0.rsp
+
+// CHECK-FILELIST-ARCHIVES-NOT: "{{.*}}/test/Driver/Inputs/filelist/a.o"
+// CHECK-FILELIST-ARCHIVES-NOT: "{{.*}}/test/Driver/Inputs/filelist/c.a"
+// CHECK-FILELIST-ARCHIVES-NOT: "{{.*}}/test/Driver/Inputs/filelist/b.o"
+// CHECK-FILELIST-ARCHIVES: @test0.rsp
+
+// CHECK-FILELIST-ARCHIVES-0: {{.*}}/test/Driver/Inputs/filelist/a.o
+// CHECK-FILELIST-ARCHIVES-0: {{.*}}/test/Driver/Inputs/filelist/c.a
+// CHECK-FILELIST-ARCHIVES-0: {{.*}}/test/Driver/Inputs/filelist/b.o
+
+// RUN: %clang -### -fuse-linker-response-files -save-temps %S/Inputs/filelist/a.obj -o test 2>&1 \
+// RUN:   | FileCheck %s -check-prefix CHECK-ALT-SUFFIX
+// RUN: FileCheck -check-prefix CHECK-ALT-SUFFIX-0 %s < test0.rsp
+
+// CHECK-ALT-SUFFIX-NOT: "{{.*}}/test/Driver/Inputs/filelist/a.obj"
+// CHECK-ALT-SUFFIX: "@test0.rsp"
+
+// CHECK-ALT-SUFFIX-0: {{.*}}/test/Driver/Inputs/filelist/a.obj
+
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits

Reply via email to