Removed the ifdefs from several instances of getResponseFileEncoding() by using
a new datatype called EncodingStrategy, introduced in the llvm side of the
patch at D4896. This datatype stores the desired encoding on both UNIX and
Windows systems, letting the writeFileWithEncoding() function in Support to
select the appropriate encoding to use.
http://reviews.llvm.org/D4897
Files:
include/clang/Driver/Compilation.h
include/clang/Driver/Job.h
include/clang/Driver/Tool.h
lib/Driver/Compilation.cpp
lib/Driver/Job.cpp
lib/Driver/Tools.cpp
lib/Driver/Tools.h
test/Driver/response-file.c
Index: include/clang/Driver/Compilation.h
===================================================================
--- include/clang/Driver/Compilation.h
+++ include/clang/Driver/Compilation.h
@@ -94,7 +94,7 @@
JobList &getJobs() { return Jobs; }
const JobList &getJobs() const { return Jobs; }
- void addCommand(Command *C) { Jobs.addJob(C); }
+ void addCommand(Command *C);
const llvm::opt::ArgStringList &getTempFiles() const { return TempFiles; }
Index: include/clang/Driver/Job.h
===================================================================
--- include/clang/Driver/Job.h
+++ include/clang/Driver/Job.h
@@ -72,13 +72,33 @@
/// argument, which will be the executable).
llvm::opt::ArgStringList Arguments;
+ /// Whether this job will need to write its arguments to a disk file
+ const bool needsResponseFile;
+
+ /// Response file name
+ const char *ResponseFile;
+
+ /// The input file list in case we need to emit a file list instead of a
+ /// proper response file
+ llvm::opt::ArgStringList InputFileList;
+
+ /// Helps Command::Print to precisely describe the contents of a reponse
+ /// file, when it is used.
+ void PrintArgsWithRespFile(llvm::raw_ostream &OS,
+ const char *Terminator, bool Quote,
+ bool CrashReport) const;
+
public:
Command(const Action &_Source, const Tool &_Creator, const char *_Executable,
const llvm::opt::ArgStringList &_Arguments);
void Print(llvm::raw_ostream &OS, const char *Terminator, bool Quote,
bool CrashReport = false) const override;
+ /// Checks whether the given command line arguments fit within system
+ /// limits (the maximum command line length).
+ bool NeedsResponseFile() const { return needsResponseFile; }
+
virtual int Execute(const StringRef **Redirects, std::string *ErrMsg,
bool *ExecutionFailed) const;
@@ -88,6 +108,9 @@
/// getCreator - Return the Tool which caused the creation of this job.
const Tool &getCreator() const { return Creator; }
+ void setResponseFile(const char *FileName) { ResponseFile = FileName; }
+ void setInputFileList(llvm::opt::ArgStringList List) { InputFileList = List; }
+
const char *getExecutable() const { return Executable; }
const llvm::opt::ArgStringList &getArguments() const { return Arguments; }
Index: include/clang/Driver/Tool.h
===================================================================
--- include/clang/Driver/Tool.h
+++ include/clang/Driver/Tool.h
@@ -11,6 +11,7 @@
#define LLVM_CLANG_DRIVER_TOOL_H
#include "clang/Basic/LLVM.h"
+#include "llvm/Support/Program.h"
namespace llvm {
namespace opt {
@@ -31,6 +32,24 @@
/// Tool - Information on a specific compilation tool.
class Tool {
+public:
+ // Documents the level of support for response files in this tool.
+ // Response files are necessary if the command line gets too large,
+ // requiring the arguments to be transfered to a file.
+ enum ResponseFileSupport {
+ // Provides full support for response files, which means we can transfer
+ // all tool input arguments to a file. E.g.: clang, gcc, binutils and MSVC
+ // tools.
+ RF_Full,
+ // Input file names can live in a file, but flags can't. E.g.: ld64 (Mac
+ // OS X linker).
+ RF_FileList,
+ // Does not support response files: all arguments must be passed via
+ // command line.
+ RF_None
+ };
+
+private:
/// The tool name (for debugging).
const char *Name;
@@ -57,6 +76,30 @@
virtual bool hasIntegratedCPP() const = 0;
virtual bool isLinkJob() const { return false; }
virtual bool isDsymutilJob() const { return false; }
+ /// \brief Returns the level of support for response files of this tool,
+ /// whether it accepts arguments to be passed via a file on disk.
+ virtual ResponseFileSupport getResponseFilesSupport() const {
+ return RF_None;
+ }
+ /// \brief Returns which encoding the response file should use. This is only
+ /// relevant on Windows platforms where there are different encodings being
+ /// accepted for different tools. On UNIX, UTF8 is universal.
+ ///
+ /// Windows use cases: - GCC and Binutils on mingw only accept ANSI response
+ /// files encoded with the system current code page.
+ /// - MSVC's CL.exe and LINK.exe accept UTF16 on Windows.
+ /// - Clang accepts both UTF8 and UTF16.
+ ///
+ /// FIXME: When GNU tools learn how to parse UTF16 on Windows, we should
+ /// always use UTF16 for Windows, which is the Windows official encoding for
+ /// international characters.
+ virtual llvm::sys::EncodingStrategy getResponseFileEncoding() const {
+ return {/*UnixEncoding*/ llvm::sys::EM_UTF8,
+ /*WindowsEncoding*/llvm::sys::EM_UTF8};
+ }
+ /// \brief Returns which prefix to use when passing the name of a response
+ /// file as a parameter to this tool.
+ virtual const char *getResponseFileFlag() const { return "@"; }
/// \brief Does this tool have "good" standardized diagnostics, or should the
/// driver add an additional "command failed" diagnostic on failures.
Index: lib/Driver/Compilation.cpp
===================================================================
--- lib/Driver/Compilation.cpp
+++ lib/Driver/Compilation.cpp
@@ -52,6 +52,15 @@
}
}
+void Compilation::addCommand(Command *C) {
+ Jobs.addJob(C);
+ // Verify if we need a response file
+ if (C->NeedsResponseFile()) {
+ std::string TmpName = TheDriver.GetTemporaryPath("response", "txt");
+ C->setResponseFile(addTempFile(getArgs().MakeArgString(TmpName.c_str())));
+ }
+}
+
const DerivedArgList &Compilation::getArgsForToolChain(const ToolChain *TC,
const char *BoundArch) {
if (!TC)
@@ -88,7 +97,7 @@
// Failure is only failure if the file exists and is "regular". We checked
// for it being regular before, and llvm::sys::fs::remove ignores ENOENT,
// so we don't need to check again.
-
+
if (IssueErrors)
getDriver().Diag(clang::diag::err_drv_unable_to_remove_file)
<< EC.message();
Index: lib/Driver/Job.cpp
===================================================================
--- lib/Driver/Job.cpp
+++ lib/Driver/Job.cpp
@@ -28,7 +28,11 @@
const char *_Executable,
const ArgStringList &_Arguments)
: Job(CommandClass), Source(_Source), Creator(_Creator),
- Executable(_Executable), Arguments(_Arguments) {}
+ Executable(_Executable), Arguments(_Arguments),
+ needsResponseFile(
+ !llvm::sys::argumentsFitWithinSystemLimits(_Arguments) &&
+ Creator.getResponseFilesSupport() != Tool::RF_None),
+ ResponseFile(nullptr) {}
static int skipArgs(const char *Flag) {
// These flags are all of the form -Flag <Arg> and are treated as two
@@ -93,12 +97,189 @@
OS << '"';
}
+/// ArgNeedsQuotes - Check whether argument needs to be quoted when serializing
+/// it to a response file.
+static bool ArgNeedsQuotes(const char *Str) {
+ return Str[0] == '\0' || strpbrk(Str, "\t \"&\'()*<>\\`^|") != 0;
+}
+
+/// Returns the number of backslashes and quotes in this string. These
+/// characters need to be escaped in the response files of some tools, but
+/// others do not care. Thus, we escape for all response files.
+static unsigned int CountBackslashesAndQuotes(const char *Start) {
+ unsigned int Count = 0;
+ while (*Start != '\0') {
+ if (*Start == '\\' || *Start == '\"')
+ ++Count;
+ ++Start;
+ }
+ return Count;
+}
+
+/// Encodes the array of C strings into a single string separated by whitespace.
+/// This function will also put in quotes arguments that have whitespaces and
+/// will escape the regular backslashes (used in Windows paths) and quotes.
+static std::unique_ptr<char[]> FlattenArgs(const char * const *Args) {
+ // First, determine the length of the command line.
+ unsigned Len = 0;
+ for (unsigned Cur = 0; Args[Cur]; ++Cur) {
+ bool Quoted = ArgNeedsQuotes(Args[Cur]);
+ Len += Quoted ? 2 : 0;
+ Len += CountBackslashesAndQuotes(Args[Cur]) + strlen(Args[Cur]) + 1;
+ }
+
+ // Now build the command line.
+ std::unique_ptr<char[]> Command(new char[Len + 1]);
+ char *Cur = Command.get();
+
+ for (unsigned I = 0; Args[I]; ++I) {
+ const char *Arg = Args[I];
+
+ bool NeedsQuoting = ArgNeedsQuotes(Arg);
+ if (NeedsQuoting)
+ *Cur++ = '"';
+
+ while (*Arg != '\0') {
+ if (*Arg == '\"' || *Arg == '\\') {
+ *Cur++ = '\\';
+ }
+ *Cur++ = *Arg++;
+ }
+
+ if (NeedsQuoting) {
+ *Cur++ = '"';
+ }
+ *Cur++ = ' ';
+ }
+
+ *Cur = 0;
+ return Command;
+}
+
+/// Check if string \p Arg is present in the list of inputs.
+static bool IsInInputList(const llvm::SmallVectorImpl<const char *> &Inputs,
+ const char *Arg) {
+ for (auto InputName : Inputs) {
+ if (strcmp(Arg, InputName) == 0)
+ return true;
+ }
+ return false;
+}
+
+/// Read the list of input files in Inputs and adjusts Argv accordingly,
+/// removing the elements of Inputs from Argv (since they will be passed via a
+/// response file). This function will also Insert the response file name in
+/// argv. Finally, it returns a C string with the contents of the response
+/// file (the input file list separated by newlines).
+static std::unique_ptr<char[]>
+FlattenFileList(const llvm::SmallVectorImpl<const char *> &Inputs,
+ llvm::SmallVectorImpl<const char *> &Argv,
+ const char *ResponseFlag, const char *ResponseFile) {
+ llvm::SmallVector<const char *, 128> NewArgv;
+ unsigned Len = 0;
+ for (auto Input : Inputs) {
+ Len += strlen(Input) + 1;
+ }
+ bool FirstInput = true;
+ for (auto Arg : Argv) {
+ // End of list?
+ if (Arg == nullptr) {
+ NewArgv.push_back(Arg);
+ break;
+ }
+ if (!IsInInputList(Inputs, Arg)) {
+ NewArgv.push_back(Arg);
+ } else if (FirstInput) {
+ FirstInput = false;
+ NewArgv.push_back(ResponseFlag);
+ NewArgv.push_back(ResponseFile);
+ }
+ }
+ Argv = NewArgv;
+ // Now build the file list.
+ std::unique_ptr<char[]> Command(new char[Len + 1]);
+ char *Cur = Command.get();
+ for (auto Arg : Inputs) {
+ const char *Src = Arg;
+ while (*Src != '\0')
+ *Cur++ = *Src++;
+ *Cur++ = '\n';
+ }
+ *Cur = 0;
+ return Command;
+}
+
+void Command::PrintArgsWithRespFile(raw_ostream &OS,
+ const char *Terminator, bool Quote,
+ bool CrashReport) const {
+ std::string ResponseFlag = Creator.getResponseFileFlag();
+ ResponseFlag += ResponseFile;
+ OS << ' ';
+
+ llvm::opt::ArgStringList Argv = Arguments;
+ Argv.push_back(nullptr);
+ std::unique_ptr<char[]> FlattenedArgs;
+ Tool::ResponseFileSupport RespFileSup = Creator.getResponseFilesSupport();
+ if (RespFileSup == Tool::RF_FileList) {
+ FlattenedArgs = FlattenFileList(InputFileList, Argv,
+ Creator.getResponseFileFlag(),
+ ResponseFile);
+ } else {
+ FlattenedArgs = FlattenArgs(Argv.data());
+ Argv.clear();
+ }
+
+ // Print args that are not in the FileList (if it is a proper response file
+ // rather than a file list, all arguments go into the response file and Argv
+ // is empty).
+ for (size_t Cur = 0, End = Argv.size(); Cur < End; ++Cur) {
+ const char *const Arg = Argv[Cur];
+ if (Arg == nullptr)
+ break;
+
+ if (CrashReport) {
+ if (int Skip = skipArgs(Arg)) {
+ Cur += Skip - 1;
+ continue;
+ }
+ }
+
+ OS << ' ';
+ PrintArg(OS, Arg, Quote);
+
+ if (CrashReport && quoteNextArg(Arg) && Cur + 1 < End) {
+ OS << ' ';
+ PrintArg(OS, Arguments[++Cur], true);
+ }
+ }
+ // Now print our response file flag and print the contents that we will put in
+ // a response file. If it is a FileList, FlattenFileList() already put the
+ // flag in Argv and there is no need to print it again.
+ if (RespFileSup != Tool::RF_FileList) {
+ PrintArg(OS, ResponseFlag.c_str(), Quote);
+ }
+ OS << "\n Arguments passed via response file:\n";
+ OS << FlattenedArgs.get();
+ // Avoiding duplicated newline terminator, since FileLists are
+ // newline-separated.
+ if (RespFileSup != Tool::RF_FileList) {
+ OS << "\n";
+ }
+ OS << " (end of response file)";
+ OS << Terminator;
+}
+
void Command::Print(raw_ostream &OS, const char *Terminator, bool Quote,
bool CrashReport) const {
// Always quote the exe.
OS << ' ';
PrintArg(OS, Executable, /*Quote=*/true);
+ if (needsResponseFile && ResponseFile != nullptr) {
+ PrintArgsWithRespFile(OS, Terminator, Quote, CrashReport);
+ return;
+ }
+
for (size_t i = 0, e = Arguments.size(); i < e; ++i) {
const char *const Arg = Arguments[i];
@@ -128,6 +309,46 @@
Argv.push_back(Arguments[i]);
Argv.push_back(nullptr);
+ if (ResponseFile == nullptr || !needsResponseFile) {
+ return llvm::sys::ExecuteAndWait(Executable, Argv.data(), /*env*/ nullptr,
+ Redirects, /*secondsToWait*/ 0,
+ /*memoryLimit*/ 0, ErrMsg,
+ ExecutionFailed);
+ }
+
+ // We need to put arguments in a response file (command is too large)
+ std::string ResponseFlag;
+ std::unique_ptr<char[]> FlattenedArgs;
+ Tool::ResponseFileSupport RespFileSup = Creator.getResponseFilesSupport();
+ ResponseFlag = Creator.getResponseFileFlag();
+ ResponseFlag += ResponseFile;
+ if (RespFileSup == Tool::RF_FileList)
+ FlattenedArgs = FlattenFileList(InputFileList, Argv,
+ Creator.getResponseFileFlag(),
+ ResponseFile);
+ else
+ FlattenedArgs = FlattenArgs(Argv.data() + 1 /* Skip exec name */);
+
+ if (std::error_code ec =
+ llvm::sys::writeFileWithEncoding(ResponseFile, FlattenedArgs.get(),
+ Creator.getResponseFileEncoding())) {
+ if (ErrMsg)
+ *ErrMsg = ec.message();
+ if (ExecutionFailed)
+ *ExecutionFailed = true;
+ return -1;
+ }
+
+ // Substitute the argument vector with a single argument to supply the
+ // response file. In case of a FileList, FlattenFileList() already prepared
+ // Argv with the correct arguments.
+ if (RespFileSup != Tool::RF_FileList) {
+ Argv.clear();
+ Argv.push_back(Executable);
+ Argv.push_back(ResponseFlag.c_str());
+ Argv.push_back(nullptr);
+ }
+
return llvm::sys::ExecuteAndWait(Executable, Argv.data(), /*env*/ nullptr,
Redirects, /*secondsToWait*/ 0,
/*memoryLimit*/ 0, ErrMsg, ExecutionFailed);
Index: lib/Driver/Tools.cpp
===================================================================
--- lib/Driver/Tools.cpp
+++ lib/Driver/Tools.cpp
@@ -506,7 +506,7 @@
} else
D.Diag(diag::err_drv_clang_unsupported) << A->getAsString(Args);
}
-
+
// Handle -mfpu=.
//
// FIXME: Centralize feature selection, defaulting shouldn't be also in the
@@ -815,7 +815,7 @@
}
}
- // Setting -mno-global-merge disables the codegen global merge pass. Setting
+ // Setting -mno-global-merge disables the codegen global merge pass. Setting
// -mglobal-merge has no effect as the pass is enabled by default.
if (Arg *A = Args.getLastArg(options::OPT_mglobal_merge,
options::OPT_mno_global_merge)) {
@@ -2507,7 +2507,7 @@
// Select the appropriate action.
RewriteKind rewriteKind = RK_None;
-
+
if (isa<AnalyzeJobAction>(JA)) {
assert(JA.getType() == types::TY_Plist && "Invalid output type.");
CmdArgs.push_back("-analyze");
@@ -2609,18 +2609,18 @@
if (getToolChain().getTriple().getVendor() == llvm::Triple::Apple)
CmdArgs.push_back("-analyzer-checker=osx");
-
+
CmdArgs.push_back("-analyzer-checker=deadcode");
-
+
if (types::isCXX(Inputs[0].getType()))
CmdArgs.push_back("-analyzer-checker=cplusplus");
// Enable the following experimental checkers for testing.
CmdArgs.push_back(
"-analyzer-checker=security.insecureAPI.UncheckedReturn");
CmdArgs.push_back("-analyzer-checker=security.insecureAPI.getpw");
CmdArgs.push_back("-analyzer-checker=security.insecureAPI.gets");
- CmdArgs.push_back("-analyzer-checker=security.insecureAPI.mktemp");
+ CmdArgs.push_back("-analyzer-checker=security.insecureAPI.mktemp");
CmdArgs.push_back("-analyzer-checker=security.insecureAPI.mkstemp");
CmdArgs.push_back("-analyzer-checker=security.insecureAPI.vfork");
}
@@ -2845,7 +2845,7 @@
// This alias option is being used to simplify the getLastArg logic.
OptSpecifier FastMathAliasOption = OFastEnabled ? options::OPT_Ofast :
options::OPT_ffast_math;
-
+
// Handle various floating point optimization flags, mapping them to the
// appropriate LLVM code generation flags. The pattern for all of these is to
// default off the codegen optimizations, and if any flag enables them and no
@@ -2944,7 +2944,7 @@
CmdArgs.push_back("-menable-unsafe-fp-math");
- // Validate and pass through -fp-contract option.
+ // Validate and pass through -fp-contract option.
if (Arg *A = Args.getLastArg(options::OPT_ffast_math, FastMathAliasOption,
options::OPT_fno_fast_math,
options::OPT_ffp_contract)) {
@@ -3590,7 +3590,7 @@
Args.AddLastArg(CmdArgs, options::OPT_fno_standalone_debug);
Args.AddLastArg(CmdArgs, options::OPT_fno_operator_names);
// AltiVec language extensions aren't relevant for assembling.
- if (!isa<PreprocessJobAction>(JA) ||
+ if (!isa<PreprocessJobAction>(JA) ||
Output.getType() != types::TY_PP_Asm)
Args.AddLastArg(CmdArgs, options::OPT_faltivec);
Args.AddLastArg(CmdArgs, options::OPT_fdiagnostics_show_template_tree);
@@ -3776,7 +3776,7 @@
!Args.hasArg(options::OPT_fno_blocks))) {
CmdArgs.push_back("-fblocks");
- if (!Args.hasArg(options::OPT_fgnu_runtime) &&
+ if (!Args.hasArg(options::OPT_fgnu_runtime) &&
!getToolChain().hasBlocksRuntime())
CmdArgs.push_back("-fblocks-runtime-optional");
}
@@ -3786,8 +3786,8 @@
// modules implementation is solid for C++/Objective-C++ programs as well.
bool HaveModules = false;
if (Args.hasFlag(options::OPT_fmodules, options::OPT_fno_modules, false)) {
- bool AllowedInCXX = Args.hasFlag(options::OPT_fcxx_modules,
- options::OPT_fno_cxx_modules,
+ bool AllowedInCXX = Args.hasFlag(options::OPT_fcxx_modules,
+ options::OPT_fno_cxx_modules,
false);
if (AllowedInCXX || !types::isCXX(InputType)) {
CmdArgs.push_back("-fmodules");
@@ -3957,7 +3957,7 @@
CmdArgs.push_back("-fms-extensions");
// -fms-compatibility=0 is default.
- if (Args.hasFlag(options::OPT_fms_compatibility,
+ if (Args.hasFlag(options::OPT_fms_compatibility,
options::OPT_fno_ms_compatibility,
(IsWindowsMSVC && Args.hasFlag(options::OPT_fms_extensions,
options::OPT_fno_ms_extensions,
@@ -4044,12 +4044,12 @@
objcRuntime.getKind() == ObjCRuntime::FragileMacOSX &&
objcRuntime.isNeXTFamily())
CmdArgs.push_back("-fobjc-subscripting-legacy-runtime");
-
+
// -fencode-extended-block-signature=1 is default.
if (getToolChain().IsEncodeExtendedBlockSignatureDefault()) {
CmdArgs.push_back("-fencode-extended-block-signature");
}
-
+
// Allow -fno-objc-arr to trump -fobjc-arr/-fobjc-arc.
// NOTE: This logic is duplicated in ToolChains.cpp.
bool ARC = isObjCAutoRefCount(Args);
@@ -4343,7 +4343,7 @@
options::OPT_fno_apple_pragma_pack, false))
CmdArgs.push_back("-fapple-pragma-pack");
- // le32-specific flags:
+ // le32-specific flags:
// -fno-math-builtin: clang should not convert math builtins to intrinsics
// by default.
if (getToolChain().getArch() == llvm::Triple::le32) {
@@ -4384,7 +4384,7 @@
Args.AddLastArg(CmdArgs, options::OPT_dM);
Args.AddLastArg(CmdArgs, options::OPT_dD);
-
+
// Handle serialized diagnostics.
if (Arg *A = Args.getLastArg(options::OPT__serialize_diags)) {
CmdArgs.push_back("-serialize-diagnostic-file");
@@ -4550,8 +4550,8 @@
<< value;
} else {
// Otherwise, determine if we are using the non-fragile ABI.
- bool nonFragileABIIsDefault =
- (rewriteKind == RK_NonFragile ||
+ bool nonFragileABIIsDefault =
+ (rewriteKind == RK_NonFragile ||
(rewriteKind == RK_None &&
getToolChain().IsObjCNonFragileABIDefault()));
if (args.hasFlag(options::OPT_fobjc_nonfragile_abi,
@@ -4804,7 +4804,7 @@
// Add the "effective" target triple.
CmdArgs.push_back("-triple");
- std::string TripleStr =
+ std::string TripleStr =
getToolChain().ComputeEffectiveClangTriple(Args, Input.getType());
CmdArgs.push_back(Args.MakeArgString(TripleStr));
@@ -5780,6 +5780,12 @@
const char *LinkingOutput) const {
assert(Output.getType() == types::TY_Image && "Invalid linker output type.");
+ // If the number of arguments surpasses the system limits, we will encode the
+ // input files in a separate file, shortening the command line. To this end,
+ // build a list of input file names that can be passed via a file with the
+ // -filelist linker option.
+ llvm::opt::ArgStringList InputFileList;
+
// The logic here is derived from gcc's behavior; most of which
// comes from specs (starting with link_command). Consult gcc for
// more information.
@@ -5848,7 +5854,21 @@
}
AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs);
-
+ // Build the input file for -filelist (list of linker input files) in case we
+ // need it later
+ for (const auto &II : Inputs) {
+ if (II.isFilename()) {
+ InputFileList.push_back(II.getFilename());
+ continue;
+ }
+
+ // This is a linker input argument.
+ // We cannot mix input arguments and file names in a -filelist input, thus
+ // we prematurely stop our list (remaining files shall be passed as
+ // arguments).
+ break;
+ }
+
if (isObjCRuntimeLinked(Args) &&
!Args.hasArg(options::OPT_nostdlib) &&
!Args.hasArg(options::OPT_nodefaultlibs)) {
@@ -5891,7 +5911,10 @@
const char *Exec =
Args.MakeArgString(getToolChain().GetLinkerPath());
- C.addCommand(new Command(JA, *this, Exec, CmdArgs));
+ Command *Cmd = new Command(JA, *this, Exec, CmdArgs);
+ if (Cmd->NeedsResponseFile())
+ Cmd->setInputFileList(InputFileList);
+ C.addCommand(Cmd);
}
void darwin::Lipo::ConstructJob(Compilation &C, const JobAction &JA,
@@ -6209,7 +6232,7 @@
if (!Args.hasArg(options::OPT_nostdlib) &&
!Args.hasArg(options::OPT_nostartfiles)) {
if (!Args.hasArg(options::OPT_shared)) {
- if (Args.hasArg(options::OPT_pg))
+ if (Args.hasArg(options::OPT_pg))
CmdArgs.push_back(Args.MakeArgString(
getToolChain().GetFilePath("gcrt0.o")));
else
@@ -6243,7 +6266,7 @@
!Args.hasArg(options::OPT_nodefaultlibs)) {
if (D.CCCIsCXX()) {
getToolChain().AddCXXStdlibLibArgs(Args, CmdArgs);
- if (Args.hasArg(options::OPT_pg))
+ if (Args.hasArg(options::OPT_pg))
CmdArgs.push_back("-lm_p");
else
CmdArgs.push_back("-lm");
@@ -6508,7 +6531,7 @@
const InputInfoList &Inputs,
const ArgList &Args,
const char *LinkingOutput) const {
- const toolchains::FreeBSD& ToolChain =
+ const toolchains::FreeBSD& ToolChain =
static_cast<const toolchains::FreeBSD&>(getToolChain());
const Driver &D = ToolChain.getDriver();
const bool IsPIE =
@@ -6744,7 +6767,7 @@
break;
default:
- break;
+ break;
}
Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA,
Index: lib/Driver/Tools.h
===================================================================
--- lib/Driver/Tools.h
+++ lib/Driver/Tools.h
@@ -95,6 +95,9 @@
bool hasGoodDiagnostics() const override { return true; }
bool hasIntegratedAssembler() const override { return true; }
bool hasIntegratedCPP() const override { return true; }
+ ResponseFileSupport getResponseFilesSupport() const override {
+ return RF_Full;
+ }
void ConstructJob(Compilation &C, const JobAction &JA,
const InputInfo &Output, const InputInfoList &Inputs,
@@ -111,6 +114,9 @@
bool hasGoodDiagnostics() const override { return true; }
bool hasIntegratedAssembler() const override { return false; }
bool hasIntegratedCPP() const override { return false; }
+ ResponseFileSupport getResponseFilesSupport() const override {
+ return RF_Full;
+ }
void ConstructJob(Compilation &C, const JobAction &JA,
const InputInfo &Output, const InputInfoList &Inputs,
@@ -130,6 +136,13 @@
const InputInfoList &Inputs,
const llvm::opt::ArgList &TCArgs,
const char *LinkingOutput) const override;
+ ResponseFileSupport getResponseFilesSupport() const override {
+ return RF_Full;
+ }
+ llvm::sys::EncodingStrategy getResponseFileEncoding() const override {
+ return {/*UnixEncoding*/ llvm::sys::EM_UTF8,
+ /*WindowsEncoding*/llvm::sys::EM_CurrentCodePage};
+ }
/// RenderExtraToolArgs - Render any arguments necessary to force
/// the particular tool mode.
@@ -191,6 +204,13 @@
const InputInfo &Output, const InputInfoList &Inputs,
const llvm::opt::ArgList &TCArgs,
const char *LinkingOutput) const override;
+ ResponseFileSupport getResponseFilesSupport() const override {
+ return RF_Full;
+ }
+ llvm::sys::EncodingStrategy getResponseFileEncoding() const override {
+ return {/*UnixEncoding*/ llvm::sys::EM_UTF8,
+ /*WindowsEncoding*/llvm::sys::EM_CurrentCodePage};
+ }
};
class LLVM_LIBRARY_VISIBILITY Link : public Tool {
@@ -207,6 +227,13 @@
const InputInfo &Output, const InputInfoList &Inputs,
const llvm::opt::ArgList &TCArgs,
const char *LinkingOutput) const override;
+ ResponseFileSupport getResponseFilesSupport() const override {
+ return RF_Full;
+ }
+ llvm::sys::EncodingStrategy getResponseFileEncoding() const override {
+ return {/*UnixEncoding*/ llvm::sys::EM_UTF8,
+ /*WindowsEncoding*/llvm::sys::EM_CurrentCodePage};
+ }
};
} // end namespace hexagon.
@@ -276,6 +303,12 @@
bool hasIntegratedCPP() const override { return false; }
bool isLinkJob() const override { return true; }
+ ResponseFileSupport getResponseFilesSupport() const override {
+ return RF_FileList;
+ }
+ virtual const char *getResponseFileFlag() const override {
+ return "-filelist";
+ }
void ConstructJob(Compilation &C, const JobAction &JA,
const InputInfo &Output, const InputInfoList &Inputs,
@@ -339,6 +372,14 @@
const InputInfoList &Inputs,
const llvm::opt::ArgList &TCArgs,
const char *LinkingOutput) const override;
+
+ ResponseFileSupport getResponseFilesSupport() const override {
+ return RF_Full;
+ }
+ llvm::sys::EncodingStrategy getResponseFileEncoding() const override {
+ return {/*UnixEncoding*/ llvm::sys::EM_UTF8,
+ /*WindowsEncoding*/llvm::sys::EM_CurrentCodePage};
+ }
};
class LLVM_LIBRARY_VISIBILITY Link : public Tool {
public:
@@ -351,6 +392,14 @@
const InputInfo &Output, const InputInfoList &Inputs,
const llvm::opt::ArgList &TCArgs,
const char *LinkingOutput) const override;
+
+ ResponseFileSupport getResponseFilesSupport() const override {
+ return RF_Full;
+ }
+ llvm::sys::EncodingStrategy getResponseFileEncoding() const override {
+ return {/*UnixEncoding*/ llvm::sys::EM_UTF8,
+ /*WindowsEncoding*/llvm::sys::EM_CurrentCodePage};
+ }
};
} // end namespace openbsd
@@ -367,6 +416,14 @@
const InputInfo &Output, const InputInfoList &Inputs,
const llvm::opt::ArgList &TCArgs,
const char *LinkingOutput) const override;
+
+ ResponseFileSupport getResponseFilesSupport() const override {
+ return RF_Full;
+ }
+ llvm::sys::EncodingStrategy getResponseFileEncoding() const override {
+ return {/*UnixEncoding*/ llvm::sys::EM_UTF8,
+ /*WindowsEncoding*/llvm::sys::EM_CurrentCodePage};
+ }
};
class LLVM_LIBRARY_VISIBILITY Link : public Tool {
public:
@@ -379,6 +436,14 @@
const InputInfo &Output, const InputInfoList &Inputs,
const llvm::opt::ArgList &TCArgs,
const char *LinkingOutput) const override;
+
+ ResponseFileSupport getResponseFilesSupport() const override {
+ return RF_Full;
+ }
+ llvm::sys::EncodingStrategy getResponseFileEncoding() const override {
+ return {/*UnixEncoding*/ llvm::sys::EM_UTF8,
+ /*WindowsEncoding*/llvm::sys::EM_CurrentCodePage};
+ }
};
} // end namespace bitrig
@@ -395,6 +460,14 @@
const InputInfo &Output, const InputInfoList &Inputs,
const llvm::opt::ArgList &TCArgs,
const char *LinkingOutput) const override;
+
+ ResponseFileSupport getResponseFilesSupport() const override {
+ return RF_Full;
+ }
+ llvm::sys::EncodingStrategy getResponseFileEncoding() const override {
+ return {/*UnixEncoding*/ llvm::sys::EM_UTF8,
+ /*WindowsEncoding*/llvm::sys::EM_CurrentCodePage};
+ }
};
class LLVM_LIBRARY_VISIBILITY Link : public Tool {
public:
@@ -407,6 +480,14 @@
const InputInfo &Output, const InputInfoList &Inputs,
const llvm::opt::ArgList &TCArgs,
const char *LinkingOutput) const override;
+
+ ResponseFileSupport getResponseFilesSupport() const override {
+ return RF_Full;
+ }
+ llvm::sys::EncodingStrategy getResponseFileEncoding() const override {
+ return {/*UnixEncoding*/ llvm::sys::EM_UTF8,
+ /*WindowsEncoding*/llvm::sys::EM_CurrentCodePage};
+ }
};
} // end namespace freebsd
@@ -424,6 +505,14 @@
const InputInfo &Output, const InputInfoList &Inputs,
const llvm::opt::ArgList &TCArgs,
const char *LinkingOutput) const override;
+
+ ResponseFileSupport getResponseFilesSupport() const override {
+ return RF_Full;
+ }
+ llvm::sys::EncodingStrategy getResponseFileEncoding() const override {
+ return {/*UnixEncoding*/ llvm::sys::EM_UTF8,
+ /*WindowsEncoding*/llvm::sys::EM_CurrentCodePage};
+ }
};
class LLVM_LIBRARY_VISIBILITY Link : public Tool {
@@ -438,6 +527,14 @@
const InputInfo &Output, const InputInfoList &Inputs,
const llvm::opt::ArgList &TCArgs,
const char *LinkingOutput) const override;
+
+ ResponseFileSupport getResponseFilesSupport() const override {
+ return RF_Full;
+ }
+ llvm::sys::EncodingStrategy getResponseFileEncoding() const override {
+ return {/*UnixEncoding*/ llvm::sys::EM_UTF8,
+ /*WindowsEncoding*/llvm::sys::EM_CurrentCodePage};
+ }
};
} // end namespace netbsd
@@ -454,13 +551,28 @@
const InputInfoList &Inputs,
const llvm::opt::ArgList &TCArgs,
const char *LinkingOutput) const override;
+
+ ResponseFileSupport getResponseFilesSupport() const override {
+ return RF_Full;
+ }
+ llvm::sys::EncodingStrategy getResponseFileEncoding() const override {
+ return {/*UnixEncoding*/ llvm::sys::EM_UTF8,
+ /*WindowsEncoding*/llvm::sys::EM_CurrentCodePage};
+ }
};
class LLVM_LIBRARY_VISIBILITY Link : public Tool {
public:
Link(const ToolChain &TC) : Tool("GNU::Link", "linker", TC) {}
bool hasIntegratedCPP() const override { return false; }
bool isLinkJob() const override { return true; }
+ ResponseFileSupport getResponseFilesSupport() const override {
+ return RF_Full;
+ }
+ llvm::sys::EncodingStrategy getResponseFileEncoding() const override {
+ return {/*UnixEncoding*/ llvm::sys::EM_UTF8,
+ /*WindowsEncoding*/llvm::sys::EM_CurrentCodePage};
+ }
void ConstructJob(Compilation &C, const JobAction &JA,
const InputInfo &Output,
@@ -483,6 +595,14 @@
const InputInfoList &Inputs,
const llvm::opt::ArgList &TCArgs,
const char *LinkingOutput) const override;
+
+ ResponseFileSupport getResponseFilesSupport() const override {
+ return RF_Full;
+ }
+ llvm::sys::EncodingStrategy getResponseFileEncoding() const override {
+ return {/*UnixEncoding*/ llvm::sys::EM_UTF8,
+ /*WindowsEncoding*/llvm::sys::EM_CurrentCodePage};
+ }
};
class LLVM_LIBRARY_VISIBILITY Link : public Tool {
public:
@@ -496,6 +616,14 @@
const InputInfoList &Inputs,
const llvm::opt::ArgList &TCArgs,
const char *LinkingOutput) const override;
+
+ ResponseFileSupport getResponseFilesSupport() const override {
+ return RF_Full;
+ }
+ llvm::sys::EncodingStrategy getResponseFileEncoding() const override {
+ return {/*UnixEncoding*/ llvm::sys::EM_UTF8,
+ /*WindowsEncoding*/llvm::sys::EM_CurrentCodePage};
+ }
};
} // end namespace minix
@@ -540,6 +668,14 @@
const InputInfo &Output, const InputInfoList &Inputs,
const llvm::opt::ArgList &TCArgs,
const char *LinkingOutput) const override;
+
+ ResponseFileSupport getResponseFilesSupport() const override {
+ return RF_Full;
+ }
+ llvm::sys::EncodingStrategy getResponseFileEncoding() const override {
+ return {/*UnixEncoding*/ llvm::sys::EM_UTF8,
+ /*WindowsEncoding*/llvm::sys::EM_CurrentCodePage};
+ }
};
class LLVM_LIBRARY_VISIBILITY Link : public Tool {
public:
@@ -553,6 +689,14 @@
const InputInfoList &Inputs,
const llvm::opt::ArgList &TCArgs,
const char *LinkingOutput) const override;
+
+ ResponseFileSupport getResponseFilesSupport() const override {
+ return RF_Full;
+ }
+ llvm::sys::EncodingStrategy getResponseFileEncoding() const override {
+ return {/*UnixEncoding*/ llvm::sys::EM_UTF8,
+ /*WindowsEncoding*/llvm::sys::EM_CurrentCodePage};
+ }
};
} // end namespace dragonfly
@@ -564,6 +708,13 @@
bool hasIntegratedCPP() const override { return false; }
bool isLinkJob() const override { return true; }
+ ResponseFileSupport getResponseFilesSupport() const override {
+ return RF_Full;
+ }
+ llvm::sys::EncodingStrategy getResponseFileEncoding() const override {
+ return {/*UnixEncoding*/ llvm::sys::EM_UTF16,
+ /*WindowsEncoding*/llvm::sys::EM_UTF16};
+ }
void ConstructJob(Compilation &C, const JobAction &JA,
const InputInfo &Output, const InputInfoList &Inputs,
@@ -578,6 +729,13 @@
bool hasIntegratedAssembler() const override { return true; }
bool hasIntegratedCPP() const override { return true; }
bool isLinkJob() const override { return false; }
+ ResponseFileSupport getResponseFilesSupport() const override {
+ return RF_Full;
+ }
+ llvm::sys::EncodingStrategy getResponseFileEncoding() const override {
+ return {/*UnixEncoding*/ llvm::sys::EM_UTF16,
+ /*WindowsEncoding*/llvm::sys::EM_UTF16};
+ }
void ConstructJob(Compilation &C, const JobAction &JA,
const InputInfo &Output, const InputInfoList &Inputs,
Index: test/Driver/response-file.c
===================================================================
--- /dev/null
+++ test/Driver/response-file.c
@@ -0,0 +1,26 @@
+// REQUIRES: long_tests
+
+// Check that clang is able to process short response files
+// Since this is a short response file, clang must not use a response file
+// to pass its parameters to other tools. This is only necessary for a large
+// number of parameters.
+// RUN: echo "-DTEST" >> %t.0.txt
+// RUN: %clang -E @%t.0.txt %s -v 2>&1 | FileCheck %s -check-prefix=SHORT
+// SHORT-NOT: Arguments passed via response file
+// SHORT: -D TEST
+// SHORT: extern int it_works;
+
+// Check that clang is able to process long response files, routing a long
+// sequence of arguments to other tools by using response files as well.
+// We generate a 2MB response file to be big enough to surpass any system
+// limit.
+// RUN: awk "BEGIN { while (count++<300000) string=string \"-DTEST \";\
+// RUN: print string }" > %t.1.txt
+// RUN: %clang -E @%t.1.txt %s -v 2>&1 | FileCheck %s -check-prefix=LONG
+// LONG: Arguments passed via response file
+// LONG: -D TEST
+// LONG: extern int it_works;
+
+#ifdef TEST
+extern int it_works;
+#endif
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits