Index: ELF/Driver.h =================================================================== --- ELF/Driver.h +++ ELF/Driver.h @@ -28,6 +28,10 @@ public: // Parses command line options. llvm::opt::InputArgList parse(ArrayRef Args); + +private: + std::vector replaceResponseFiles(ArrayRef Args); + llvm::BumpPtrAllocator Alloc; }; class LinkerDriver { Index: ELF/DriverUtils.cpp =================================================================== --- ELF/DriverUtils.cpp +++ ELF/DriverUtils.cpp @@ -16,6 +16,8 @@ #include "Driver.h" #include "Error.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/StringSaver.h" using namespace llvm; @@ -53,7 +55,8 @@ unsigned MissingIndex; unsigned MissingCount; - opt::InputArgList Args = Table.ParseArgs(Argv, MissingIndex, MissingCount); + std::vector ArgvVec = replaceResponseFiles(Argv); + opt::InputArgList Args = Table.ParseArgs(ArgvVec, MissingIndex, MissingCount); if (MissingCount) error(Twine("missing arg value for \"") + Args.getArgString(MissingIndex) + "\", expected " + Twine(MissingCount) + @@ -67,3 +70,13 @@ return Args; } + +// Creates a new command line by replacing options starting with '@' +// character. '@' is replaced by the file's contents. +std::vector +ArgParser::replaceResponseFiles(ArrayRef Argv) { + SmallVector Tokens(Argv.data(), Argv.data() + Argv.size()); + StringSaver S(Alloc); + llvm::cl::ExpandResponseFiles(S, llvm::cl::TokenizeGNUCommandLine, Tokens); + return std::vector(Tokens.begin(), Tokens.end()); +} Index: test/elf2/basic.s =================================================================== --- test/elf2/basic.s +++ test/elf2/basic.s @@ -176,6 +176,11 @@ # CHECK-NEXT: } # CHECK-NEXT: ] +# RUN: echo " -o %t2" > %t.responsefile +# RUN: lld -flavor gnu2 %t @%t.responsefile +# RUN: llvm-readobj -file-headers -sections -program-headers -symbols %t2 \ +# RUN: | FileCheck %s + # RUN: not lld -flavor gnu2 %t 2>&1 | FileCheck --check-prefix=NO_O %s # NO_O: -o must be specified.