[pkg-d-commits] [ldc] 24/149: Improve support for response files in command line (#1942)

Matthias Klumpp mak at moszumanska.debian.org
Sun Apr 23 22:36:54 UTC 2017


This is an automated email from the git hooks/post-receive script.

mak pushed a commit to annotated tag v1.2.0
in repository ldc.

commit b7e576d5796d749c2c32b7b9996726a730a55479
Author: kinke <kinke at users.noreply.github.com>
Date:   Wed Jan 4 23:58:15 2017 +0100

    Improve support for response files in command line (#1942)
    
    Fix issue #1941 by expanding response files *before* temptatively parsing
    an explicit `-conf` and/or target triple for the config file lookup.
    After injecting the switches from the config file right after argv[0],
    expand again to catch any response files specified in the config file
    switches.
---
 driver/main.cpp         | 107 +++++++++++++++++++++++++++---------------------
 tests/driver/gh1941.d   |   4 ++
 tests/driver/gh1941.rsp |   1 +
 3 files changed, 65 insertions(+), 47 deletions(-)

diff --git a/driver/main.cpp b/driver/main.cpp
index 485f11b..79b882c 100644
--- a/driver/main.cpp
+++ b/driver/main.cpp
@@ -231,48 +231,50 @@ void initFromPathString(const char *&dest, const cl::opt<std::string> &src) {
   }
 }
 
-const char *tryGetExplicitConfFile(int argc, char **argv) {
-  // begin at the back => use latest -conf= specification
-  for (int i = argc - 1; i >= 1; --i) {
-    if (strncmp(argv[i], "-conf=", 6) == 0) {
-      return argv[i] + 6;
-    }
-  }
-  return nullptr;
-}
-
 template <int N> // option length incl. terminating null
-void tryParse(int argc, char **argv, int i, const char *&output,
-              const char (&option)[N]) {
-  if (strncmp(argv[i], option, N - 1) != 0)
+void tryParse(const llvm::SmallVectorImpl<const char *> &args, size_t i,
+              const char *&output, const char (&option)[N]) {
+  if (strncmp(args[i], option, N - 1) != 0)
     return;
 
-  char nextChar = argv[i][N - 1];
+  char nextChar = args[i][N - 1];
   if (nextChar == '=')
-    output = argv[i] + N;
-  else if (nextChar == 0 && i < argc - 1)
-    output = argv[i + 1];
+    output = args[i] + N;
+  else if (nextChar == 0 && i < args.size() - 1)
+    output = args[i + 1];
 }
 
-llvm::Triple tryGetExplicitTriple(int argc, char **argv) {
+const char *
+tryGetExplicitConfFile(const llvm::SmallVectorImpl<const char *> &args) {
+  const char *conf = nullptr;
+  // begin at the back => use latest -conf specification
+  assert(args.size() >= 1);
+  for (size_t i = args.size() - 1; !conf && i >= 1; --i) {
+    tryParse(args, i, conf, "-conf");
+  }
+  return conf;
+}
+
+llvm::Triple
+tryGetExplicitTriple(const llvm::SmallVectorImpl<const char *> &args) {
   // most combinations of flags are illegal, this mimicks command line
   //  behaviour for legal ones only
   llvm::Triple triple(llvm::sys::getDefaultTargetTriple());
   const char *mtriple = nullptr;
   const char *march = nullptr;
-  for (int i = 1; i < argc; ++i) {
-    if (sizeof(void *) != 4 && strcmp(argv[i], "-m32") == 0) {
+  for (size_t i = 1; i < args.size(); ++i) {
+    if (sizeof(void *) != 4 && strcmp(args[i], "-m32") == 0) {
       triple = triple.get32BitArchVariant();
       if (triple.getArch() == llvm::Triple::ArchType::x86)
         triple.setArchName("i686"); // instead of i386
       return triple;
     }
 
-    if (sizeof(void *) != 8 && strcmp(argv[i], "-m64") == 0)
+    if (sizeof(void *) != 8 && strcmp(args[i], "-m64") == 0)
       return triple.get64BitArchVariant();
 
-    tryParse(argc, argv, i, mtriple, "-mtriple");
-    tryParse(argc, argv, i, march, "-march");
+    tryParse(args, i, mtriple, "-mtriple");
+    tryParse(args, i, march, "-march");
   }
   if (mtriple)
     triple = llvm::Triple(llvm::Triple::normalize(mtriple));
@@ -283,6 +285,21 @@ llvm::Triple tryGetExplicitTriple(int argc, char **argv) {
   return triple;
 }
 
+void expandResponseFiles(llvm::BumpPtrAllocator &A,
+                         llvm::SmallVectorImpl<const char *> &args) {
+#if LDC_LLVM_VER >= 308
+  llvm::StringSaver Saver(A);
+  cl::ExpandResponseFiles(Saver,
+#ifdef _WIN32
+                          cl::TokenizeWindowsCommandLine
+#else
+                          cl::TokenizeGNUCommandLine
+#endif
+                          ,
+                          args);
+#endif
+}
+
 /// Parses switches from the command line, any response files and the global
 /// config file and sets up global.params accordingly.
 ///
@@ -304,41 +321,37 @@ void parseCommandLine(int argc, char **argv, Strings &sourceFiles,
   global.params.moduleDeps = nullptr;
   global.params.moduleDepsFile = nullptr;
 
-  // Build combined list of command line arguments.
-  opts::allArguments.push_back(argv[0]);
+  // Set up `opts::allArguments`, the combined list of command line arguments.
+  using opts::allArguments;
+
+  // initialize with the actual command line
+  allArguments.insert(allArguments.end(), argv, argv + argc);
+
+  // expand response files (`@<file>`) in-place
+  llvm::BumpPtrAllocator allocator;
+  expandResponseFiles(allocator, allArguments);
 
+  // read config file
   ConfigFile cfg_file;
-  const char *explicitConfFile = tryGetExplicitConfFile(argc, argv);
-  const std::string cfg_triple = tryGetExplicitTriple(argc, argv).getTriple();
+  const char *explicitConfFile = tryGetExplicitConfFile(allArguments);
+  const std::string cfg_triple = tryGetExplicitTriple(allArguments).getTriple();
   // just ignore errors for now, they are still printed
   cfg_file.read(explicitConfFile, cfg_triple.c_str());
-  opts::allArguments.insert(opts::allArguments.end(), cfg_file.switches_begin(),
-                            cfg_file.switches_end());
 
-  opts::allArguments.insert(opts::allArguments.end(), &argv[1], &argv[argc]);
+  // insert switches from config file before all explicit ones
+  allArguments.insert(allArguments.begin() + 1, cfg_file.switches_begin(),
+                      cfg_file.switches_end());
+
+  // finalize by expanding response files specified in config file
+  expandResponseFiles(allocator, allArguments);
 
   cl::SetVersionPrinter(&printVersion);
 
   opts::hideLLVMOptions();
   opts::createClashingOptions();
 
-// pre-expand response files (LLVM's ParseCommandLineOptions() always uses
-// TokenizeGNUCommandLine which eats backslashes)
-#if LDC_LLVM_VER >= 308
-  llvm::BumpPtrAllocator A;
-  llvm::StringSaver Saver(A);
-  cl::ExpandResponseFiles(Saver,
-#ifdef _WIN32
-                          cl::TokenizeWindowsCommandLine
-#else
-                          cl::TokenizeGNUCommandLine
-#endif
-                          ,
-                          opts::allArguments);
-#endif
-
-  cl::ParseCommandLineOptions(opts::allArguments.size(),
-                              const_cast<char **>(opts::allArguments.data()),
+  cl::ParseCommandLineOptions(allArguments.size(),
+                              const_cast<char **>(allArguments.data()),
                               "LDC - the LLVM D compiler\n");
 
   helpOnly = mCPU == "help" ||
diff --git a/tests/driver/gh1941.d b/tests/driver/gh1941.d
new file mode 100644
index 0000000..2bfb930
--- /dev/null
+++ b/tests/driver/gh1941.d
@@ -0,0 +1,4 @@
+// REQUIRES: atleast_llvm308
+// RUN: %ldc -c %s @%S/gh1941.rsp 2>&1 | FileCheck %s
+
+// CHECK: 'foo.conf' not found
diff --git a/tests/driver/gh1941.rsp b/tests/driver/gh1941.rsp
new file mode 100644
index 0000000..f577217
--- /dev/null
+++ b/tests/driver/gh1941.rsp
@@ -0,0 +1 @@
+-conf=foo.conf

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-d/ldc.git



More information about the pkg-d-commits mailing list