瀏覽代碼

Refactor ExecuteAndWait to take StringRefs.

This simplifies some code which had StringRefs to begin with, and
makes other code more complicated which had const char* to begin
with.

In the end, I think this makes for a more idiomatic and platform
agnostic API.  Not all platforms launch process with null terminated
c-string arrays for the environment pointer and argv, but the api
was designed that way because it allowed easy pass-through for
posix-based platforms.  There's a little additional overhead now
since on posix based platforms we'll be takign StringRefs which
were constructed from null terminated strings and then copying
them to null terminate them again, but from a readability and
usability standpoint of the API user, I think this API signature
is strictly better.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@334518 91177308-0d34-0410-b5e6-96231b3b80d8
Zachary Turner 7 年之前
父節點
當前提交
0dcc1159b4

+ 10 - 0
include/llvm/ADT/StringExtras.h

@@ -39,6 +39,16 @@ inline char hexdigit(unsigned X, bool LowerCase = false) {
   return X < 10 ? '0' + X : HexChar + X - 10;
   return X < 10 ? '0' + X : HexChar + X - 10;
 }
 }
 
 
+/// Given an array of c-style strings terminated by a null pointer, construct
+/// a vector of StringRefs representing the same strings without the terminating
+/// null string.
+inline std::vector<StringRef> toStringRefArray(const char *const *Strings) {
+  std::vector<StringRef> Result;
+  while (*Strings)
+    Result.push_back(*Strings++);
+  return Result;
+}
+
 /// Construct a string ref from a boolean.
 /// Construct a string ref from a boolean.
 inline StringRef toStringRef(bool B) { return StringRef(B ? "true" : "false"); }
 inline StringRef toStringRef(bool B) { return StringRef(B ? "true" : "false"); }
 
 

+ 8 - 7
include/llvm/Support/Program.h

@@ -89,12 +89,13 @@ namespace sys {
   int ExecuteAndWait(
   int ExecuteAndWait(
       StringRef Program, ///< Path of the program to be executed. It is
       StringRef Program, ///< Path of the program to be executed. It is
       ///< presumed this is the result of the findProgramByName method.
       ///< presumed this is the result of the findProgramByName method.
-      const char **Args, ///< A vector of strings that are passed to the
+      ArrayRef<StringRef> Args, ///< An array of strings that are passed to the
       ///< program.  The first element should be the name of the program.
       ///< program.  The first element should be the name of the program.
-      ///< The list *must* be terminated by a null char* entry.
-      const char **Env = nullptr, ///< An optional vector of strings to use for
-      ///< the program's environment. If not provided, the current program's
-      ///< environment will be used.
+      ///< The array should **not** be terminated by an empty StringRef.
+      Optional<ArrayRef<StringRef>> Env = None, ///< An optional vector of
+      ///< strings to use for the program's environment. If not provided, the
+      ///< current program's environment will be used.  If specified, the
+      ///< vector should **not** be terminated by an empty StringRef.
       ArrayRef<Optional<StringRef>> Redirects = {}, ///<
       ArrayRef<Optional<StringRef>> Redirects = {}, ///<
       ///< An array of optional paths. Should have a size of zero or three.
       ///< An array of optional paths. Should have a size of zero or three.
       ///< If the array is empty, no redirections are performed.
       ///< If the array is empty, no redirections are performed.
@@ -123,8 +124,8 @@ namespace sys {
   /// \note On Microsoft Windows systems, users will need to either call
   /// \note On Microsoft Windows systems, users will need to either call
   /// \see Wait until the process finished execution or win32 CloseHandle() API
   /// \see Wait until the process finished execution or win32 CloseHandle() API
   /// on ProcessInfo.ProcessHandle to avoid memory leaks.
   /// on ProcessInfo.ProcessHandle to avoid memory leaks.
-  ProcessInfo ExecuteNoWait(StringRef Program, const char **Args,
-                            const char **Env = nullptr,
+  ProcessInfo ExecuteNoWait(StringRef Program, ArrayRef<StringRef> Args,
+                            Optional<ArrayRef<StringRef>> Env,
                             ArrayRef<Optional<StringRef>> Redirects = {},
                             ArrayRef<Optional<StringRef>> Redirects = {},
                             unsigned MemoryLimit = 0,
                             unsigned MemoryLimit = 0,
                             std::string *ErrMsg = nullptr,
                             std::string *ErrMsg = nullptr,

+ 27 - 37
lib/Support/GraphWriter.cpp

@@ -91,20 +91,18 @@ std::string llvm::createGraphFilename(const Twine &Name, int &FD) {
 }
 }
 
 
 // Execute the graph viewer. Return true if there were errors.
 // Execute the graph viewer. Return true if there were errors.
-static bool ExecGraphViewer(StringRef ExecPath, std::vector<const char *> &args,
+static bool ExecGraphViewer(StringRef ExecPath, std::vector<StringRef> &args,
                             StringRef Filename, bool wait,
                             StringRef Filename, bool wait,
                             std::string &ErrMsg) {
                             std::string &ErrMsg) {
-  assert(args.back() == nullptr);
   if (wait) {
   if (wait) {
-    if (sys::ExecuteAndWait(ExecPath, args.data(), nullptr, {}, 0, 0,
-                            &ErrMsg)) {
+    if (sys::ExecuteAndWait(ExecPath, args, None, {}, 0, 0, &ErrMsg)) {
       errs() << "Error: " << ErrMsg << "\n";
       errs() << "Error: " << ErrMsg << "\n";
       return true;
       return true;
     }
     }
     sys::fs::remove(Filename);
     sys::fs::remove(Filename);
     errs() << " done. \n";
     errs() << " done. \n";
   } else {
   } else {
-    sys::ExecuteNoWait(ExecPath, args.data(), nullptr, {}, 0, &ErrMsg);
+    sys::ExecuteNoWait(ExecPath, args, None, {}, 0, &ErrMsg);
     errs() << "Remember to erase graph file: " << Filename << "\n";
     errs() << "Remember to erase graph file: " << Filename << "\n";
   }
   }
   return false;
   return false;
@@ -158,22 +156,20 @@ bool llvm::DisplayGraph(StringRef FilenameRef, bool wait,
 #ifdef __APPLE__
 #ifdef __APPLE__
   wait &= !ViewBackground;
   wait &= !ViewBackground;
   if (S.TryFindProgram("open", ViewerPath)) {
   if (S.TryFindProgram("open", ViewerPath)) {
-    std::vector<const char *> args;
-    args.push_back(ViewerPath.c_str());
+    std::vector<StringRef> args;
+    args.push_back(ViewerPath);
     if (wait)
     if (wait)
       args.push_back("-W");
       args.push_back("-W");
-    args.push_back(Filename.c_str());
-    args.push_back(nullptr);
+    args.push_back(Filename);
     errs() << "Trying 'open' program... ";
     errs() << "Trying 'open' program... ";
     if (!ExecGraphViewer(ViewerPath, args, Filename, wait, ErrMsg))
     if (!ExecGraphViewer(ViewerPath, args, Filename, wait, ErrMsg))
       return false;
       return false;
   }
   }
 #endif
 #endif
   if (S.TryFindProgram("xdg-open", ViewerPath)) {
   if (S.TryFindProgram("xdg-open", ViewerPath)) {
-    std::vector<const char *> args;
-    args.push_back(ViewerPath.c_str());
-    args.push_back(Filename.c_str());
-    args.push_back(nullptr);
+    std::vector<StringRef> args;
+    args.push_back(ViewerPath);
+    args.push_back(Filename);
     errs() << "Trying 'xdg-open' program... ";
     errs() << "Trying 'xdg-open' program... ";
     if (!ExecGraphViewer(ViewerPath, args, Filename, wait, ErrMsg))
     if (!ExecGraphViewer(ViewerPath, args, Filename, wait, ErrMsg))
       return false;
       return false;
@@ -181,10 +177,9 @@ bool llvm::DisplayGraph(StringRef FilenameRef, bool wait,
 
 
   // Graphviz
   // Graphviz
   if (S.TryFindProgram("Graphviz", ViewerPath)) {
   if (S.TryFindProgram("Graphviz", ViewerPath)) {
-    std::vector<const char *> args;
-    args.push_back(ViewerPath.c_str());
-    args.push_back(Filename.c_str());
-    args.push_back(nullptr);
+    std::vector<StringRef> args;
+    args.push_back(ViewerPath);
+    args.push_back(Filename);
 
 
     errs() << "Running 'Graphviz' program... ";
     errs() << "Running 'Graphviz' program... ";
     return ExecGraphViewer(ViewerPath, args, Filename, wait, ErrMsg);
     return ExecGraphViewer(ViewerPath, args, Filename, wait, ErrMsg);
@@ -192,15 +187,13 @@ bool llvm::DisplayGraph(StringRef FilenameRef, bool wait,
 
 
   // xdot
   // xdot
   if (S.TryFindProgram("xdot|xdot.py", ViewerPath)) {
   if (S.TryFindProgram("xdot|xdot.py", ViewerPath)) {
-    std::vector<const char *> args;
-    args.push_back(ViewerPath.c_str());
-    args.push_back(Filename.c_str());
+    std::vector<StringRef> args;
+    args.push_back(ViewerPath);
+    args.push_back(Filename);
 
 
     args.push_back("-f");
     args.push_back("-f");
     args.push_back(getProgramName(program));
     args.push_back(getProgramName(program));
 
 
-    args.push_back(nullptr);
-
     errs() << "Running 'xdot.py' program... ";
     errs() << "Running 'xdot.py' program... ";
     return ExecGraphViewer(ViewerPath, args, Filename, wait, ErrMsg);
     return ExecGraphViewer(ViewerPath, args, Filename, wait, ErrMsg);
   }
   }
@@ -235,18 +228,17 @@ bool llvm::DisplayGraph(StringRef FilenameRef, bool wait,
     std::string OutputFilename =
     std::string OutputFilename =
         Filename + (Viewer == VK_CmdStart ? ".pdf" : ".ps");
         Filename + (Viewer == VK_CmdStart ? ".pdf" : ".ps");
 
 
-    std::vector<const char *> args;
-    args.push_back(GeneratorPath.c_str());
+    std::vector<StringRef> args;
+    args.push_back(GeneratorPath);
     if (Viewer == VK_CmdStart)
     if (Viewer == VK_CmdStart)
       args.push_back("-Tpdf");
       args.push_back("-Tpdf");
     else
     else
       args.push_back("-Tps");
       args.push_back("-Tps");
     args.push_back("-Nfontname=Courier");
     args.push_back("-Nfontname=Courier");
     args.push_back("-Gsize=7.5,10");
     args.push_back("-Gsize=7.5,10");
-    args.push_back(Filename.c_str());
+    args.push_back(Filename);
     args.push_back("-o");
     args.push_back("-o");
-    args.push_back(OutputFilename.c_str());
-    args.push_back(nullptr);
+    args.push_back(OutputFilename);
 
 
     errs() << "Running '" << GeneratorPath << "' program... ";
     errs() << "Running '" << GeneratorPath << "' program... ";
 
 
@@ -258,31 +250,30 @@ bool llvm::DisplayGraph(StringRef FilenameRef, bool wait,
     std::string StartArg;
     std::string StartArg;
 
 
     args.clear();
     args.clear();
-    args.push_back(ViewerPath.c_str());
+    args.push_back(ViewerPath);
     switch (Viewer) {
     switch (Viewer) {
     case VK_OSXOpen:
     case VK_OSXOpen:
       args.push_back("-W");
       args.push_back("-W");
-      args.push_back(OutputFilename.c_str());
+      args.push_back(OutputFilename);
       break;
       break;
     case VK_XDGOpen:
     case VK_XDGOpen:
       wait = false;
       wait = false;
-      args.push_back(OutputFilename.c_str());
+      args.push_back(OutputFilename);
       break;
       break;
     case VK_Ghostview:
     case VK_Ghostview:
       args.push_back("--spartan");
       args.push_back("--spartan");
-      args.push_back(OutputFilename.c_str());
+      args.push_back(OutputFilename);
       break;
       break;
     case VK_CmdStart:
     case VK_CmdStart:
       args.push_back("/S");
       args.push_back("/S");
       args.push_back("/C");
       args.push_back("/C");
       StartArg =
       StartArg =
           (StringRef("start ") + (wait ? "/WAIT " : "") + OutputFilename).str();
           (StringRef("start ") + (wait ? "/WAIT " : "") + OutputFilename).str();
-      args.push_back(StartArg.c_str());
+      args.push_back(StartArg);
       break;
       break;
     case VK_None:
     case VK_None:
       llvm_unreachable("Invalid viewer");
       llvm_unreachable("Invalid viewer");
     }
     }
-    args.push_back(nullptr);
 
 
     ErrMsg.clear();
     ErrMsg.clear();
     return ExecGraphViewer(ViewerPath, args, OutputFilename, wait, ErrMsg);
     return ExecGraphViewer(ViewerPath, args, OutputFilename, wait, ErrMsg);
@@ -290,10 +281,9 @@ bool llvm::DisplayGraph(StringRef FilenameRef, bool wait,
 
 
   // dotty
   // dotty
   if (S.TryFindProgram("dotty", ViewerPath)) {
   if (S.TryFindProgram("dotty", ViewerPath)) {
-    std::vector<const char *> args;
-    args.push_back(ViewerPath.c_str());
-    args.push_back(Filename.c_str());
-    args.push_back(nullptr);
+    std::vector<StringRef> args;
+    args.push_back(ViewerPath);
+    args.push_back(Filename);
 
 
 // Dotty spawns another app and doesn't wait until it returns
 // Dotty spawns another app and doesn't wait until it returns
 #ifdef _WIN32
 #ifdef _WIN32

+ 9 - 7
lib/Support/Program.cpp

@@ -23,17 +23,19 @@ using namespace sys;
 //===          independent code.
 //===          independent code.
 //===----------------------------------------------------------------------===//
 //===----------------------------------------------------------------------===//
 
 
-static bool Execute(ProcessInfo &PI, StringRef Program, const char **Args,
-                    const char **Env, ArrayRef<Optional<StringRef>> Redirects,
+static bool Execute(ProcessInfo &PI, StringRef Program,
+                    ArrayRef<StringRef> Args, Optional<ArrayRef<StringRef>> Env,
+                    ArrayRef<Optional<StringRef>> Redirects,
                     unsigned MemoryLimit, std::string *ErrMsg);
                     unsigned MemoryLimit, std::string *ErrMsg);
 
 
-int sys::ExecuteAndWait(StringRef Program, const char **Args, const char **Envp,
+int sys::ExecuteAndWait(StringRef Program, ArrayRef<StringRef> Args,
+                        Optional<ArrayRef<StringRef>> Env,
                         ArrayRef<Optional<StringRef>> Redirects,
                         ArrayRef<Optional<StringRef>> Redirects,
                         unsigned SecondsToWait, unsigned MemoryLimit,
                         unsigned SecondsToWait, unsigned MemoryLimit,
                         std::string *ErrMsg, bool *ExecutionFailed) {
                         std::string *ErrMsg, bool *ExecutionFailed) {
   assert(Redirects.empty() || Redirects.size() == 3);
   assert(Redirects.empty() || Redirects.size() == 3);
   ProcessInfo PI;
   ProcessInfo PI;
-  if (Execute(PI, Program, Args, Envp, Redirects, MemoryLimit, ErrMsg)) {
+  if (Execute(PI, Program, Args, Env, Redirects, MemoryLimit, ErrMsg)) {
     if (ExecutionFailed)
     if (ExecutionFailed)
       *ExecutionFailed = false;
       *ExecutionFailed = false;
     ProcessInfo Result = Wait(
     ProcessInfo Result = Wait(
@@ -47,8 +49,8 @@ int sys::ExecuteAndWait(StringRef Program, const char **Args, const char **Envp,
   return -1;
   return -1;
 }
 }
 
 
-ProcessInfo sys::ExecuteNoWait(StringRef Program, const char **Args,
-                               const char **Envp,
+ProcessInfo sys::ExecuteNoWait(StringRef Program, ArrayRef<StringRef> Args,
+                               Optional<ArrayRef<StringRef>> Env,
                                ArrayRef<Optional<StringRef>> Redirects,
                                ArrayRef<Optional<StringRef>> Redirects,
                                unsigned MemoryLimit, std::string *ErrMsg,
                                unsigned MemoryLimit, std::string *ErrMsg,
                                bool *ExecutionFailed) {
                                bool *ExecutionFailed) {
@@ -56,7 +58,7 @@ ProcessInfo sys::ExecuteNoWait(StringRef Program, const char **Args,
   ProcessInfo PI;
   ProcessInfo PI;
   if (ExecutionFailed)
   if (ExecutionFailed)
     *ExecutionFailed = false;
     *ExecutionFailed = false;
-  if (!Execute(PI, Program, Args, Envp, Redirects, MemoryLimit, ErrMsg))
+  if (!Execute(PI, Program, Args, Env, Redirects, MemoryLimit, ErrMsg))
     if (ExecutionFailed)
     if (ExecutionFailed)
       *ExecutionFailed = true;
       *ExecutionFailed = true;
 
 

+ 9 - 8
lib/Support/Signals.cpp

@@ -154,17 +154,18 @@ static bool printSymbolizedStackTrace(StringRef Argv0, void **StackTrace,
     }
     }
   }
   }
 
 
-  Optional<StringRef> Redirects[] = {InputFile.str(), OutputFile.str(), llvm::None};
-  const char *Args[] = {"llvm-symbolizer", "--functions=linkage", "--inlining",
+  Optional<StringRef> Redirects[] = {StringRef(InputFile),
+                                     StringRef(OutputFile), llvm::None};
+  StringRef Args[] = {"llvm-symbolizer", "--functions=linkage", "--inlining",
 #ifdef _WIN32
 #ifdef _WIN32
-                        // Pass --relative-address on Windows so that we don't
-                        // have to add ImageBase from PE file.
-                        // FIXME: Make this the default for llvm-symbolizer.
-                        "--relative-address",
+                      // Pass --relative-address on Windows so that we don't
+                      // have to add ImageBase from PE file.
+                      // FIXME: Make this the default for llvm-symbolizer.
+                      "--relative-address",
 #endif
 #endif
-                        "--demangle", nullptr};
+                      "--demangle"};
   int RunResult =
   int RunResult =
-      sys::ExecuteAndWait(LLVMSymbolizerPath, Args, nullptr, Redirects);
+      sys::ExecuteAndWait(LLVMSymbolizerPath, Args, None, Redirects);
   if (RunResult != 0)
   if (RunResult != 0)
     return false;
     return false;
 
 

+ 28 - 7
lib/Support/Unix/Program.inc

@@ -23,6 +23,7 @@
 #include "llvm/Support/Errc.h"
 #include "llvm/Support/Errc.h"
 #include "llvm/Support/FileSystem.h"
 #include "llvm/Support/FileSystem.h"
 #include "llvm/Support/Path.h"
 #include "llvm/Support/Path.h"
+#include "llvm/Support/StringSaver.h"
 #include "llvm/Support/raw_ostream.h"
 #include "llvm/Support/raw_ostream.h"
 #if HAVE_SYS_STAT_H
 #if HAVE_SYS_STAT_H
 #include <sys/stat.h>
 #include <sys/stat.h>
@@ -164,8 +165,18 @@ static void SetMemoryLimits(unsigned size) {
 
 
 }
 }
 
 
-static bool Execute(ProcessInfo &PI, StringRef Program, const char **Args,
-                    const char **Envp, ArrayRef<Optional<StringRef>> Redirects,
+static std::vector<const char *>
+toNullTerminatedCStringArray(ArrayRef<StringRef> Strings, StringSaver &Saver) {
+  std::vector<const char *> Result;
+  for (StringRef S : Strings)
+    Result.push_back(Saver.save(S).data());
+  Result.push_back(nullptr);
+  return Result;
+}
+
+static bool Execute(ProcessInfo &PI, StringRef Program,
+                    ArrayRef<StringRef> Args, Optional<ArrayRef<StringRef>> Env,
+                    ArrayRef<Optional<StringRef>> Redirects,
                     unsigned MemoryLimit, std::string *ErrMsg) {
                     unsigned MemoryLimit, std::string *ErrMsg) {
   if (!llvm::sys::fs::exists(Program)) {
   if (!llvm::sys::fs::exists(Program)) {
     if (ErrMsg)
     if (ErrMsg)
@@ -174,6 +185,18 @@ static bool Execute(ProcessInfo &PI, StringRef Program, const char **Args,
     return false;
     return false;
   }
   }
 
 
+  BumpPtrAllocator Allocator;
+  StringSaver Saver(Allocator);
+  std::vector<const char *> ArgVector, EnvVector;
+  const char **Argv = nullptr;
+  const char **Envp = nullptr;
+  ArgVector = toNullTerminatedCStringArray(Args, Saver);
+  Argv = ArgVector.data();
+  if (Env) {
+    EnvVector = toNullTerminatedCStringArray(*Env, Saver);
+    Envp = EnvVector.data();
+  }
+
   // If this OS has posix_spawn and there is no memory limit being implied, use
   // If this OS has posix_spawn and there is no memory limit being implied, use
   // posix_spawn.  It is more efficient than fork/exec.
   // posix_spawn.  It is more efficient than fork/exec.
 #ifdef HAVE_POSIX_SPAWN
 #ifdef HAVE_POSIX_SPAWN
@@ -227,7 +250,7 @@ static bool Execute(ProcessInfo &PI, StringRef Program, const char **Args,
     // positive.
     // positive.
     pid_t PID = 0;
     pid_t PID = 0;
     int Err = posix_spawn(&PID, Program.str().c_str(), FileActions,
     int Err = posix_spawn(&PID, Program.str().c_str(), FileActions,
-                          /*attrp*/nullptr, const_cast<char **>(Args),
+                          /*attrp*/ nullptr, const_cast<char **>(Argv),
                           const_cast<char **>(Envp));
                           const_cast<char **>(Envp));
 
 
     if (FileActions)
     if (FileActions)
@@ -280,12 +303,10 @@ static bool Execute(ProcessInfo &PI, StringRef Program, const char **Args,
       // Execute!
       // Execute!
       std::string PathStr = Program;
       std::string PathStr = Program;
       if (Envp != nullptr)
       if (Envp != nullptr)
-        execve(PathStr.c_str(),
-               const_cast<char **>(Args),
+        execve(PathStr.c_str(), const_cast<char **>(Argv),
                const_cast<char **>(Envp));
                const_cast<char **>(Envp));
       else
       else
-        execv(PathStr.c_str(),
-              const_cast<char **>(Args));
+        execv(PathStr.c_str(), const_cast<char **>(Argv));
       // If the execve() failed, we should exit. Follow Unix protocol and
       // If the execve() failed, we should exit. Follow Unix protocol and
       // return 127 if the executable was not found, and 126 otherwise.
       // return 127 if the executable was not found, and 126 otherwise.
       // Use _exit rather than exit so that atexit functions and static
       // Use _exit rather than exit so that atexit functions and static

+ 7 - 14
lib/Support/Windows/Program.inc

@@ -149,15 +149,9 @@ static HANDLE RedirectIO(Optional<StringRef> Path, int fd,
 
 
 }
 }
 
 
-static SmallVector<StringRef, 8> buildArgVector(const char **Args) {
-  SmallVector<StringRef, 8> Result;
-  for (unsigned I = 0; Args[I]; ++I)
-    Result.push_back(StringRef(Args[I]));
-  return Result;
-}
-
-static bool Execute(ProcessInfo &PI, StringRef Program, const char **Args,
-                    const char **Envp, ArrayRef<Optional<StringRef>> Redirects,
+static bool Execute(ProcessInfo &PI, StringRef Program,
+                    ArrayRef<StringRef> Args, Optional<ArrayRef<StringRef>> Env,
+                    ArrayRef<Optional<StringRef>> Redirects,
                     unsigned MemoryLimit, std::string *ErrMsg) {
                     unsigned MemoryLimit, std::string *ErrMsg) {
   if (!sys::fs::can_execute(Program)) {
   if (!sys::fs::can_execute(Program)) {
     if (ErrMsg)
     if (ErrMsg)
@@ -176,19 +170,18 @@ static bool Execute(ProcessInfo &PI, StringRef Program, const char **Args,
   // Windows wants a command line, not an array of args, to pass to the new
   // Windows wants a command line, not an array of args, to pass to the new
   // process.  We have to concatenate them all, while quoting the args that
   // process.  We have to concatenate them all, while quoting the args that
   // have embedded spaces (or are empty).
   // have embedded spaces (or are empty).
-  auto ArgVector = buildArgVector(Args);
-  std::string Command = flattenWindowsCommandLine(ArgVector);
+  std::string Command = flattenWindowsCommandLine(Args);
 
 
   // The pointer to the environment block for the new process.
   // The pointer to the environment block for the new process.
   std::vector<wchar_t> EnvBlock;
   std::vector<wchar_t> EnvBlock;
 
 
-  if (Envp) {
+  if (Env) {
     // An environment block consists of a null-terminated block of
     // An environment block consists of a null-terminated block of
     // null-terminated strings. Convert the array of environment variables to
     // null-terminated strings. Convert the array of environment variables to
     // an environment block by concatenating them.
     // an environment block by concatenating them.
-    for (unsigned i = 0; Envp[i]; ++i) {
+    for (const auto E : *Env) {
       SmallVector<wchar_t, MAX_PATH> EnvString;
       SmallVector<wchar_t, MAX_PATH> EnvString;
-      if (std::error_code ec = windows::UTF8ToUTF16(Envp[i], EnvString)) {
+      if (std::error_code ec = windows::UTF8ToUTF16(E, EnvString)) {
         SetLastError(ec.value());
         SetLastError(ec.value());
         MakeErrMsg(ErrMsg, "Unable to convert environment variable to UTF-16");
         MakeErrMsg(ErrMsg, "Unable to convert environment variable to UTF-16");
         return false;
         return false;

+ 7 - 8
tools/bugpoint/OptimizerDriver.cpp

@@ -194,20 +194,20 @@ bool BugDriver::runPasses(Module &Program,
   }
   }
 
 
   // setup the child process' arguments
   // setup the child process' arguments
-  SmallVector<const char *, 8> Args;
+  SmallVector<StringRef, 8> Args;
   if (UseValgrind) {
   if (UseValgrind) {
     Args.push_back("valgrind");
     Args.push_back("valgrind");
     Args.push_back("--error-exitcode=1");
     Args.push_back("--error-exitcode=1");
     Args.push_back("-q");
     Args.push_back("-q");
-    Args.push_back(tool.c_str());
+    Args.push_back(tool);
   } else
   } else
-    Args.push_back(tool.c_str());
+    Args.push_back(tool);
 
 
   for (unsigned i = 0, e = OptArgs.size(); i != e; ++i)
   for (unsigned i = 0, e = OptArgs.size(); i != e; ++i)
-    Args.push_back(OptArgs[i].c_str());
+    Args.push_back(OptArgs[i]);
   Args.push_back("-disable-symbolication");
   Args.push_back("-disable-symbolication");
   Args.push_back("-o");
   Args.push_back("-o");
-  Args.push_back(OutputFilename.c_str());
+  Args.push_back(OutputFilename);
   std::vector<std::string> pass_args;
   std::vector<std::string> pass_args;
   for (unsigned i = 0, e = PluginLoader::getNumPlugins(); i != e; ++i) {
   for (unsigned i = 0, e = PluginLoader::getNumPlugins(); i != e; ++i) {
     pass_args.push_back(std::string("-load"));
     pass_args.push_back(std::string("-load"));
@@ -224,7 +224,6 @@ bool BugDriver::runPasses(Module &Program,
   Args.push_back(Temp->TmpName.c_str());
   Args.push_back(Temp->TmpName.c_str());
   for (unsigned i = 0; i < NumExtraArgs; ++i)
   for (unsigned i = 0; i < NumExtraArgs; ++i)
     Args.push_back(*ExtraArgs);
     Args.push_back(*ExtraArgs);
-  Args.push_back(nullptr);
 
 
   LLVM_DEBUG(errs() << "\nAbout to run:\t";
   LLVM_DEBUG(errs() << "\nAbout to run:\t";
              for (unsigned i = 0, e = Args.size() - 1; i != e; ++i) errs()
              for (unsigned i = 0, e = Args.size() - 1; i != e; ++i) errs()
@@ -239,8 +238,8 @@ bool BugDriver::runPasses(Module &Program,
   }
   }
 
 
   std::string ErrMsg;
   std::string ErrMsg;
-  int result = sys::ExecuteAndWait(Prog, Args.data(), nullptr, Redirects,
-                                   Timeout, MemoryLimit, &ErrMsg);
+  int result = sys::ExecuteAndWait(Prog, Args, None, Redirects, Timeout,
+                                   MemoryLimit, &ErrMsg);
 
 
   // If we are supposed to delete the bitcode file or if the passes crashed,
   // If we are supposed to delete the bitcode file or if the passes crashed,
   // remove it now.  This may fail if the file was never created, but that's ok.
   // remove it now.  This may fail if the file was never created, but that's ok.

+ 81 - 93
tools/bugpoint/ToolRunner.cpp

@@ -53,13 +53,14 @@ cl::opt<std::string>
 /// RunProgramWithTimeout - This function provides an alternate interface
 /// RunProgramWithTimeout - This function provides an alternate interface
 /// to the sys::Program::ExecuteAndWait interface.
 /// to the sys::Program::ExecuteAndWait interface.
 /// @see sys::Program::ExecuteAndWait
 /// @see sys::Program::ExecuteAndWait
-static int RunProgramWithTimeout(StringRef ProgramPath, const char **Args,
-                                 StringRef StdInFile, StringRef StdOutFile,
-                                 StringRef StdErrFile, unsigned NumSeconds = 0,
+static int RunProgramWithTimeout(StringRef ProgramPath,
+                                 ArrayRef<StringRef> Args, StringRef StdInFile,
+                                 StringRef StdOutFile, StringRef StdErrFile,
+                                 unsigned NumSeconds = 0,
                                  unsigned MemoryLimit = 0,
                                  unsigned MemoryLimit = 0,
                                  std::string *ErrMsg = nullptr) {
                                  std::string *ErrMsg = nullptr) {
   Optional<StringRef> Redirects[3] = {StdInFile, StdOutFile, StdErrFile};
   Optional<StringRef> Redirects[3] = {StdInFile, StdOutFile, StdErrFile};
-  return sys::ExecuteAndWait(ProgramPath, Args, nullptr, Redirects, NumSeconds,
+  return sys::ExecuteAndWait(ProgramPath, Args, None, Redirects, NumSeconds,
                              MemoryLimit, ErrMsg);
                              MemoryLimit, ErrMsg);
 }
 }
 
 
@@ -69,24 +70,22 @@ static int RunProgramWithTimeout(StringRef ProgramPath, const char **Args,
 /// fails. Remote client is required to return 255 if it failed or program exit
 /// fails. Remote client is required to return 255 if it failed or program exit
 /// code otherwise.
 /// code otherwise.
 /// @see sys::Program::ExecuteAndWait
 /// @see sys::Program::ExecuteAndWait
-static int RunProgramRemotelyWithTimeout(StringRef RemoteClientPath,
-                                         const char **Args, StringRef StdInFile,
-                                         StringRef StdOutFile,
-                                         StringRef StdErrFile,
-                                         unsigned NumSeconds = 0,
-                                         unsigned MemoryLimit = 0) {
+static int RunProgramRemotelyWithTimeout(
+    StringRef RemoteClientPath, ArrayRef<StringRef> Args, StringRef StdInFile,
+    StringRef StdOutFile, StringRef StdErrFile, unsigned NumSeconds = 0,
+    unsigned MemoryLimit = 0) {
   Optional<StringRef> Redirects[3] = {StdInFile, StdOutFile, StdErrFile};
   Optional<StringRef> Redirects[3] = {StdInFile, StdOutFile, StdErrFile};
 
 
   // Run the program remotely with the remote client
   // Run the program remotely with the remote client
-  int ReturnCode = sys::ExecuteAndWait(RemoteClientPath, Args, nullptr,
-                                       Redirects, NumSeconds, MemoryLimit);
+  int ReturnCode = sys::ExecuteAndWait(RemoteClientPath, Args, None, Redirects,
+                                       NumSeconds, MemoryLimit);
 
 
   // Has the remote client fail?
   // Has the remote client fail?
   if (255 == ReturnCode) {
   if (255 == ReturnCode) {
     std::ostringstream OS;
     std::ostringstream OS;
     OS << "\nError running remote client:\n ";
     OS << "\nError running remote client:\n ";
-    for (const char **Arg = Args; *Arg; ++Arg)
-      OS << " " << *Arg;
+    for (StringRef Arg : Args)
+      OS << " " << Arg.str();
     OS << "\n";
     OS << "\n";
 
 
     // The error message is in the output file, let's print it out from there.
     // The error message is in the output file, let's print it out from there.
@@ -105,12 +104,12 @@ static int RunProgramRemotelyWithTimeout(StringRef RemoteClientPath,
   return ReturnCode;
   return ReturnCode;
 }
 }
 
 
-static Error ProcessFailure(StringRef ProgPath, const char **Args,
+static Error ProcessFailure(StringRef ProgPath, ArrayRef<StringRef> Args,
                             unsigned Timeout = 0, unsigned MemoryLimit = 0) {
                             unsigned Timeout = 0, unsigned MemoryLimit = 0) {
   std::ostringstream OS;
   std::ostringstream OS;
   OS << "\nError running tool:\n ";
   OS << "\nError running tool:\n ";
-  for (const char **Arg = Args; *Arg; ++Arg)
-    OS << " " << *Arg;
+  for (StringRef Arg : Args)
+    OS << " " << Arg.str();
   OS << "\n";
   OS << "\n";
 
 
   // Rerun the compiler, capturing any error messages to print them.
   // Rerun the compiler, capturing any error messages to print them.
@@ -171,7 +170,7 @@ Expected<int> LLI::ExecuteProgram(const std::string &Bitcode,
                                   const std::vector<std::string> &CCArgs,
                                   const std::vector<std::string> &CCArgs,
                                   const std::vector<std::string> &SharedLibs,
                                   const std::vector<std::string> &SharedLibs,
                                   unsigned Timeout, unsigned MemoryLimit) {
                                   unsigned Timeout, unsigned MemoryLimit) {
-  std::vector<const char *> LLIArgs;
+  std::vector<StringRef> LLIArgs;
   LLIArgs.push_back(LLIPath.c_str());
   LLIArgs.push_back(LLIPath.c_str());
   LLIArgs.push_back("-force-interpreter=true");
   LLIArgs.push_back("-force-interpreter=true");
 
 
@@ -179,18 +178,17 @@ Expected<int> LLI::ExecuteProgram(const std::string &Bitcode,
                                                 e = SharedLibs.end();
                                                 e = SharedLibs.end();
        i != e; ++i) {
        i != e; ++i) {
     LLIArgs.push_back("-load");
     LLIArgs.push_back("-load");
-    LLIArgs.push_back((*i).c_str());
+    LLIArgs.push_back(*i);
   }
   }
 
 
   // Add any extra LLI args.
   // Add any extra LLI args.
   for (unsigned i = 0, e = ToolArgs.size(); i != e; ++i)
   for (unsigned i = 0, e = ToolArgs.size(); i != e; ++i)
-    LLIArgs.push_back(ToolArgs[i].c_str());
+    LLIArgs.push_back(ToolArgs[i]);
 
 
-  LLIArgs.push_back(Bitcode.c_str());
+  LLIArgs.push_back(Bitcode);
   // Add optional parameters to the running program from Argv
   // Add optional parameters to the running program from Argv
   for (unsigned i = 0, e = Args.size(); i != e; ++i)
   for (unsigned i = 0, e = Args.size(); i != e; ++i)
-    LLIArgs.push_back(Args[i].c_str());
-  LLIArgs.push_back(nullptr);
+    LLIArgs.push_back(Args[i]);
 
 
   outs() << "<lli>";
   outs() << "<lli>";
   outs().flush();
   outs().flush();
@@ -198,7 +196,7 @@ Expected<int> LLI::ExecuteProgram(const std::string &Bitcode,
              for (unsigned i = 0, e = LLIArgs.size() - 1; i != e; ++i) errs()
              for (unsigned i = 0, e = LLIArgs.size() - 1; i != e; ++i) errs()
              << " " << LLIArgs[i];
              << " " << LLIArgs[i];
              errs() << "\n";);
              errs() << "\n";);
-  return RunProgramWithTimeout(LLIPath, &LLIArgs[0], InputFile, OutputFile,
+  return RunProgramWithTimeout(LLIPath, LLIArgs, InputFile, OutputFile,
                                OutputFile, Timeout, MemoryLimit);
                                OutputFile, Timeout, MemoryLimit);
 }
 }
 
 
@@ -285,22 +283,20 @@ public:
 Error CustomCompiler::compileProgram(const std::string &Bitcode,
 Error CustomCompiler::compileProgram(const std::string &Bitcode,
                                      unsigned Timeout, unsigned MemoryLimit) {
                                      unsigned Timeout, unsigned MemoryLimit) {
 
 
-  std::vector<const char *> ProgramArgs;
+  std::vector<StringRef> ProgramArgs;
   ProgramArgs.push_back(CompilerCommand.c_str());
   ProgramArgs.push_back(CompilerCommand.c_str());
 
 
   for (std::size_t i = 0; i < CompilerArgs.size(); ++i)
   for (std::size_t i = 0; i < CompilerArgs.size(); ++i)
     ProgramArgs.push_back(CompilerArgs.at(i).c_str());
     ProgramArgs.push_back(CompilerArgs.at(i).c_str());
-  ProgramArgs.push_back(Bitcode.c_str());
-  ProgramArgs.push_back(nullptr);
+  ProgramArgs.push_back(Bitcode);
 
 
   // Add optional parameters to the running program from Argv
   // Add optional parameters to the running program from Argv
   for (unsigned i = 0, e = CompilerArgs.size(); i != e; ++i)
   for (unsigned i = 0, e = CompilerArgs.size(); i != e; ++i)
     ProgramArgs.push_back(CompilerArgs[i].c_str());
     ProgramArgs.push_back(CompilerArgs[i].c_str());
 
 
-  if (RunProgramWithTimeout(CompilerCommand, &ProgramArgs[0], "", "", "",
-                            Timeout, MemoryLimit))
-    return ProcessFailure(CompilerCommand, &ProgramArgs[0], Timeout,
-                          MemoryLimit);
+  if (RunProgramWithTimeout(CompilerCommand, ProgramArgs, "", "", "", Timeout,
+                            MemoryLimit))
+    return ProcessFailure(CompilerCommand, ProgramArgs, Timeout, MemoryLimit);
   return Error::success();
   return Error::success();
 }
 }
 
 
@@ -336,19 +332,18 @@ Expected<int> CustomExecutor::ExecuteProgram(
     const std::vector<std::string> &SharedLibs, unsigned Timeout,
     const std::vector<std::string> &SharedLibs, unsigned Timeout,
     unsigned MemoryLimit) {
     unsigned MemoryLimit) {
 
 
-  std::vector<const char *> ProgramArgs;
-  ProgramArgs.push_back(ExecutionCommand.c_str());
+  std::vector<StringRef> ProgramArgs;
+  ProgramArgs.push_back(ExecutionCommand);
 
 
   for (std::size_t i = 0; i < ExecutorArgs.size(); ++i)
   for (std::size_t i = 0; i < ExecutorArgs.size(); ++i)
-    ProgramArgs.push_back(ExecutorArgs.at(i).c_str());
-  ProgramArgs.push_back(Bitcode.c_str());
-  ProgramArgs.push_back(nullptr);
+    ProgramArgs.push_back(ExecutorArgs[i]);
+  ProgramArgs.push_back(Bitcode);
 
 
   // Add optional parameters to the running program from Argv
   // Add optional parameters to the running program from Argv
   for (unsigned i = 0, e = Args.size(); i != e; ++i)
   for (unsigned i = 0, e = Args.size(); i != e; ++i)
-    ProgramArgs.push_back(Args[i].c_str());
+    ProgramArgs.push_back(Args[i]);
 
 
-  return RunProgramWithTimeout(ExecutionCommand, &ProgramArgs[0], InputFile,
+  return RunProgramWithTimeout(ExecutionCommand, ProgramArgs, InputFile,
                                OutputFile, OutputFile, Timeout, MemoryLimit);
                                OutputFile, OutputFile, Timeout, MemoryLimit);
 }
 }
 
 
@@ -463,31 +458,28 @@ Expected<CC::FileType> LLC::OutputCode(const std::string &Bitcode,
     exit(1);
     exit(1);
   }
   }
   OutputAsmFile = UniqueFile.str();
   OutputAsmFile = UniqueFile.str();
-  std::vector<const char *> LLCArgs;
-  LLCArgs.push_back(LLCPath.c_str());
+  std::vector<StringRef> LLCArgs;
+  LLCArgs.push_back(LLCPath);
 
 
   // Add any extra LLC args.
   // Add any extra LLC args.
   for (unsigned i = 0, e = ToolArgs.size(); i != e; ++i)
   for (unsigned i = 0, e = ToolArgs.size(); i != e; ++i)
-    LLCArgs.push_back(ToolArgs[i].c_str());
+    LLCArgs.push_back(ToolArgs[i]);
 
 
   LLCArgs.push_back("-o");
   LLCArgs.push_back("-o");
-  LLCArgs.push_back(OutputAsmFile.c_str()); // Output to the Asm file
-  LLCArgs.push_back(Bitcode.c_str());       // This is the input bitcode
+  LLCArgs.push_back(OutputAsmFile); // Output to the Asm file
+  LLCArgs.push_back(Bitcode);       // This is the input bitcode
 
 
   if (UseIntegratedAssembler)
   if (UseIntegratedAssembler)
     LLCArgs.push_back("-filetype=obj");
     LLCArgs.push_back("-filetype=obj");
 
 
-  LLCArgs.push_back(nullptr);
-
   outs() << (UseIntegratedAssembler ? "<llc-ia>" : "<llc>");
   outs() << (UseIntegratedAssembler ? "<llc-ia>" : "<llc>");
   outs().flush();
   outs().flush();
   LLVM_DEBUG(errs() << "\nAbout to run:\t";
   LLVM_DEBUG(errs() << "\nAbout to run:\t";
              for (unsigned i = 0, e = LLCArgs.size() - 1; i != e; ++i) errs()
              for (unsigned i = 0, e = LLCArgs.size() - 1; i != e; ++i) errs()
              << " " << LLCArgs[i];
              << " " << LLCArgs[i];
              errs() << "\n";);
              errs() << "\n";);
-  if (RunProgramWithTimeout(LLCPath, &LLCArgs[0], "", "", "", Timeout,
-                            MemoryLimit))
-    return ProcessFailure(LLCPath, &LLCArgs[0], Timeout, MemoryLimit);
+  if (RunProgramWithTimeout(LLCPath, LLCArgs, "", "", "", Timeout, MemoryLimit))
+    return ProcessFailure(LLCPath, LLCArgs, Timeout, MemoryLimit);
   return UseIntegratedAssembler ? CC::ObjectFile : CC::AsmFile;
   return UseIntegratedAssembler ? CC::ObjectFile : CC::AsmFile;
 }
 }
 
 
@@ -581,23 +573,22 @@ Expected<int> JIT::ExecuteProgram(const std::string &Bitcode,
                                   const std::vector<std::string> &SharedLibs,
                                   const std::vector<std::string> &SharedLibs,
                                   unsigned Timeout, unsigned MemoryLimit) {
                                   unsigned Timeout, unsigned MemoryLimit) {
   // Construct a vector of parameters, incorporating those from the command-line
   // Construct a vector of parameters, incorporating those from the command-line
-  std::vector<const char *> JITArgs;
+  std::vector<StringRef> JITArgs;
   JITArgs.push_back(LLIPath.c_str());
   JITArgs.push_back(LLIPath.c_str());
   JITArgs.push_back("-force-interpreter=false");
   JITArgs.push_back("-force-interpreter=false");
 
 
   // Add any extra LLI args.
   // Add any extra LLI args.
   for (unsigned i = 0, e = ToolArgs.size(); i != e; ++i)
   for (unsigned i = 0, e = ToolArgs.size(); i != e; ++i)
-    JITArgs.push_back(ToolArgs[i].c_str());
+    JITArgs.push_back(ToolArgs[i]);
 
 
   for (unsigned i = 0, e = SharedLibs.size(); i != e; ++i) {
   for (unsigned i = 0, e = SharedLibs.size(); i != e; ++i) {
     JITArgs.push_back("-load");
     JITArgs.push_back("-load");
-    JITArgs.push_back(SharedLibs[i].c_str());
+    JITArgs.push_back(SharedLibs[i]);
   }
   }
   JITArgs.push_back(Bitcode.c_str());
   JITArgs.push_back(Bitcode.c_str());
   // Add optional parameters to the running program from Argv
   // Add optional parameters to the running program from Argv
   for (unsigned i = 0, e = Args.size(); i != e; ++i)
   for (unsigned i = 0, e = Args.size(); i != e; ++i)
-    JITArgs.push_back(Args[i].c_str());
-  JITArgs.push_back(nullptr);
+    JITArgs.push_back(Args[i]);
 
 
   outs() << "<jit>";
   outs() << "<jit>";
   outs().flush();
   outs().flush();
@@ -606,7 +597,7 @@ Expected<int> JIT::ExecuteProgram(const std::string &Bitcode,
              << " " << JITArgs[i];
              << " " << JITArgs[i];
              errs() << "\n";);
              errs() << "\n";);
   LLVM_DEBUG(errs() << "\nSending output to " << OutputFile << "\n");
   LLVM_DEBUG(errs() << "\nSending output to " << OutputFile << "\n");
-  return RunProgramWithTimeout(LLIPath, &JITArgs[0], InputFile, OutputFile,
+  return RunProgramWithTimeout(LLIPath, JITArgs, InputFile, OutputFile,
                                OutputFile, Timeout, MemoryLimit);
                                OutputFile, Timeout, MemoryLimit);
 }
 }
 
 
@@ -630,15 +621,15 @@ AbstractInterpreter::createJIT(const char *Argv0, std::string &Message,
 // CC abstraction
 // CC abstraction
 //
 //
 
 
-static bool IsARMArchitecture(std::vector<const char *> Args) {
-  for (std::vector<const char *>::const_iterator I = Args.begin(),
-                                                 E = Args.end();
-       I != E; ++I) {
-    if (StringRef(*I).equals_lower("-arch")) {
-      ++I;
-      if (I != E && StringRef(*I).startswith_lower("arm"))
-        return true;
-    }
+static bool IsARMArchitecture(std::vector<StringRef> Args) {
+  for (size_t I = 0; I < Args.size(); ++I) {
+    if (!Args[I].equals_lower("-arch"))
+      continue;
+    ++I;
+    if (I == Args.size())
+      break;
+    if (Args[I].startswith_lower("arm"))
+      return true;
   }
   }
 
 
   return false;
   return false;
@@ -651,9 +642,9 @@ Expected<int> CC::ExecuteProgram(const std::string &ProgramFile,
                                  const std::string &OutputFile,
                                  const std::string &OutputFile,
                                  const std::vector<std::string> &ArgsForCC,
                                  const std::vector<std::string> &ArgsForCC,
                                  unsigned Timeout, unsigned MemoryLimit) {
                                  unsigned Timeout, unsigned MemoryLimit) {
-  std::vector<const char *> CCArgs;
+  std::vector<StringRef> CCArgs;
 
 
-  CCArgs.push_back(CCPath.c_str());
+  CCArgs.push_back(CCPath);
 
 
   if (TargetTriple.getArch() == Triple::x86)
   if (TargetTriple.getArch() == Triple::x86)
     CCArgs.push_back("-m32");
     CCArgs.push_back("-m32");
@@ -661,7 +652,7 @@ Expected<int> CC::ExecuteProgram(const std::string &ProgramFile,
   for (std::vector<std::string>::const_iterator I = ccArgs.begin(),
   for (std::vector<std::string>::const_iterator I = ccArgs.begin(),
                                                 E = ccArgs.end();
                                                 E = ccArgs.end();
        I != E; ++I)
        I != E; ++I)
-    CCArgs.push_back(I->c_str());
+    CCArgs.push_back(*I);
 
 
   // Specify -x explicitly in case the extension is wonky
   // Specify -x explicitly in case the extension is wonky
   if (fileType != ObjectFile) {
   if (fileType != ObjectFile) {
@@ -680,7 +671,7 @@ Expected<int> CC::ExecuteProgram(const std::string &ProgramFile,
     }
     }
   }
   }
 
 
-  CCArgs.push_back(ProgramFile.c_str()); // Specify the input filename.
+  CCArgs.push_back(ProgramFile); // Specify the input filename.
 
 
   CCArgs.push_back("-x");
   CCArgs.push_back("-x");
   CCArgs.push_back("none");
   CCArgs.push_back("none");
@@ -693,20 +684,19 @@ Expected<int> CC::ExecuteProgram(const std::string &ProgramFile,
     errs() << "Error making unique filename: " << EC.message() << "\n";
     errs() << "Error making unique filename: " << EC.message() << "\n";
     exit(1);
     exit(1);
   }
   }
-  CCArgs.push_back(OutputBinary.c_str()); // Output to the right file...
+  CCArgs.push_back(OutputBinary); // Output to the right file...
 
 
   // Add any arguments intended for CC. We locate them here because this is
   // Add any arguments intended for CC. We locate them here because this is
   // most likely -L and -l options that need to come before other libraries but
   // most likely -L and -l options that need to come before other libraries but
   // after the source. Other options won't be sensitive to placement on the
   // after the source. Other options won't be sensitive to placement on the
   // command line, so this should be safe.
   // command line, so this should be safe.
   for (unsigned i = 0, e = ArgsForCC.size(); i != e; ++i)
   for (unsigned i = 0, e = ArgsForCC.size(); i != e; ++i)
-    CCArgs.push_back(ArgsForCC[i].c_str());
+    CCArgs.push_back(ArgsForCC[i]);
 
 
   CCArgs.push_back("-lm"); // Hard-code the math library...
   CCArgs.push_back("-lm"); // Hard-code the math library...
   CCArgs.push_back("-O2"); // Optimize the program a bit...
   CCArgs.push_back("-O2"); // Optimize the program a bit...
   if (TargetTriple.getArch() == Triple::sparc)
   if (TargetTriple.getArch() == Triple::sparc)
     CCArgs.push_back("-mcpu=v9");
     CCArgs.push_back("-mcpu=v9");
-  CCArgs.push_back(nullptr); // NULL terminator
 
 
   outs() << "<CC>";
   outs() << "<CC>";
   outs().flush();
   outs().flush();
@@ -714,30 +704,30 @@ Expected<int> CC::ExecuteProgram(const std::string &ProgramFile,
              for (unsigned i = 0, e = CCArgs.size() - 1; i != e; ++i) errs()
              for (unsigned i = 0, e = CCArgs.size() - 1; i != e; ++i) errs()
              << " " << CCArgs[i];
              << " " << CCArgs[i];
              errs() << "\n";);
              errs() << "\n";);
-  if (RunProgramWithTimeout(CCPath, &CCArgs[0], "", "", ""))
-    return ProcessFailure(CCPath, &CCArgs[0]);
+  if (RunProgramWithTimeout(CCPath, CCArgs, "", "", ""))
+    return ProcessFailure(CCPath, CCArgs);
 
 
-  std::vector<const char *> ProgramArgs;
+  std::vector<StringRef> ProgramArgs;
 
 
   // Declared here so that the destructor only runs after
   // Declared here so that the destructor only runs after
   // ProgramArgs is used.
   // ProgramArgs is used.
   std::string Exec;
   std::string Exec;
 
 
   if (RemoteClientPath.empty())
   if (RemoteClientPath.empty())
-    ProgramArgs.push_back(OutputBinary.c_str());
+    ProgramArgs.push_back(OutputBinary);
   else {
   else {
-    ProgramArgs.push_back(RemoteClientPath.c_str());
-    ProgramArgs.push_back(RemoteHost.c_str());
+    ProgramArgs.push_back(RemoteClientPath);
+    ProgramArgs.push_back(RemoteHost);
     if (!RemoteUser.empty()) {
     if (!RemoteUser.empty()) {
       ProgramArgs.push_back("-l");
       ProgramArgs.push_back("-l");
-      ProgramArgs.push_back(RemoteUser.c_str());
+      ProgramArgs.push_back(RemoteUser);
     }
     }
     if (!RemotePort.empty()) {
     if (!RemotePort.empty()) {
       ProgramArgs.push_back("-p");
       ProgramArgs.push_back("-p");
-      ProgramArgs.push_back(RemotePort.c_str());
+      ProgramArgs.push_back(RemotePort);
     }
     }
     if (!RemoteExtra.empty()) {
     if (!RemoteExtra.empty()) {
-      ProgramArgs.push_back(RemoteExtra.c_str());
+      ProgramArgs.push_back(RemoteExtra);
     }
     }
 
 
     // Full path to the binary. We need to cd to the exec directory because
     // Full path to the binary. We need to cd to the exec directory because
@@ -747,13 +737,12 @@ Expected<int> CC::ExecuteProgram(const std::string &ProgramFile,
     Exec += env_pwd;
     Exec += env_pwd;
     Exec += "; ./";
     Exec += "; ./";
     Exec += OutputBinary.c_str();
     Exec += OutputBinary.c_str();
-    ProgramArgs.push_back(Exec.c_str());
+    ProgramArgs.push_back(Exec);
   }
   }
 
 
   // Add optional parameters to the running program from Argv
   // Add optional parameters to the running program from Argv
   for (unsigned i = 0, e = Args.size(); i != e; ++i)
   for (unsigned i = 0, e = Args.size(); i != e; ++i)
-    ProgramArgs.push_back(Args[i].c_str());
-  ProgramArgs.push_back(nullptr); // NULL terminator
+    ProgramArgs.push_back(Args[i]);
 
 
   // Now that we have a binary, run it!
   // Now that we have a binary, run it!
   outs() << "<program>";
   outs() << "<program>";
@@ -769,7 +758,7 @@ Expected<int> CC::ExecuteProgram(const std::string &ProgramFile,
   if (RemoteClientPath.empty()) {
   if (RemoteClientPath.empty()) {
     LLVM_DEBUG(errs() << "<run locally>");
     LLVM_DEBUG(errs() << "<run locally>");
     std::string Error;
     std::string Error;
-    int ExitCode = RunProgramWithTimeout(OutputBinary.str(), &ProgramArgs[0],
+    int ExitCode = RunProgramWithTimeout(OutputBinary.str(), ProgramArgs,
                                          InputFile, OutputFile, OutputFile,
                                          InputFile, OutputFile, OutputFile,
                                          Timeout, MemoryLimit, &Error);
                                          Timeout, MemoryLimit, &Error);
     // Treat a signal (usually SIGSEGV) or timeout as part of the program output
     // Treat a signal (usually SIGSEGV) or timeout as part of the program output
@@ -783,7 +772,7 @@ Expected<int> CC::ExecuteProgram(const std::string &ProgramFile,
   } else {
   } else {
     outs() << "<run remotely>";
     outs() << "<run remotely>";
     outs().flush();
     outs().flush();
-    return RunProgramRemotelyWithTimeout(RemoteClientPath, &ProgramArgs[0],
+    return RunProgramRemotelyWithTimeout(RemoteClientPath, ProgramArgs,
                                          InputFile, OutputFile, OutputFile,
                                          InputFile, OutputFile, OutputFile,
                                          Timeout, MemoryLimit);
                                          Timeout, MemoryLimit);
   }
   }
@@ -801,9 +790,9 @@ Error CC::MakeSharedObject(const std::string &InputFile, FileType fileType,
   }
   }
   OutputFile = UniqueFilename.str();
   OutputFile = UniqueFilename.str();
 
 
-  std::vector<const char *> CCArgs;
+  std::vector<StringRef> CCArgs;
 
 
-  CCArgs.push_back(CCPath.c_str());
+  CCArgs.push_back(CCPath);
 
 
   if (TargetTriple.getArch() == Triple::x86)
   if (TargetTriple.getArch() == Triple::x86)
     CCArgs.push_back("-m32");
     CCArgs.push_back("-m32");
@@ -811,7 +800,7 @@ Error CC::MakeSharedObject(const std::string &InputFile, FileType fileType,
   for (std::vector<std::string>::const_iterator I = ccArgs.begin(),
   for (std::vector<std::string>::const_iterator I = ccArgs.begin(),
                                                 E = ccArgs.end();
                                                 E = ccArgs.end();
        I != E; ++I)
        I != E; ++I)
-    CCArgs.push_back(I->c_str());
+    CCArgs.push_back(*I);
 
 
   // Compile the C/asm file into a shared object
   // Compile the C/asm file into a shared object
   if (fileType != ObjectFile) {
   if (fileType != ObjectFile) {
@@ -819,7 +808,7 @@ Error CC::MakeSharedObject(const std::string &InputFile, FileType fileType,
     CCArgs.push_back(fileType == AsmFile ? "assembler" : "c");
     CCArgs.push_back(fileType == AsmFile ? "assembler" : "c");
   }
   }
   CCArgs.push_back("-fno-strict-aliasing");
   CCArgs.push_back("-fno-strict-aliasing");
-  CCArgs.push_back(InputFile.c_str()); // Specify the input filename.
+  CCArgs.push_back(InputFile); // Specify the input filename.
   CCArgs.push_back("-x");
   CCArgs.push_back("-x");
   CCArgs.push_back("none");
   CCArgs.push_back("none");
   if (TargetTriple.getArch() == Triple::sparc)
   if (TargetTriple.getArch() == Triple::sparc)
@@ -843,7 +832,7 @@ Error CC::MakeSharedObject(const std::string &InputFile, FileType fileType,
     CCArgs.push_back("-mcpu=v9");
     CCArgs.push_back("-mcpu=v9");
 
 
   CCArgs.push_back("-o");
   CCArgs.push_back("-o");
-  CCArgs.push_back(OutputFile.c_str()); // Output to the right filename.
+  CCArgs.push_back(OutputFile);         // Output to the right filename.
   CCArgs.push_back("-O2");              // Optimize the program a bit.
   CCArgs.push_back("-O2");              // Optimize the program a bit.
 
 
   // Add any arguments intended for CC. We locate them here because this is
   // Add any arguments intended for CC. We locate them here because this is
@@ -851,8 +840,7 @@ Error CC::MakeSharedObject(const std::string &InputFile, FileType fileType,
   // after the source. Other options won't be sensitive to placement on the
   // after the source. Other options won't be sensitive to placement on the
   // command line, so this should be safe.
   // command line, so this should be safe.
   for (unsigned i = 0, e = ArgsForCC.size(); i != e; ++i)
   for (unsigned i = 0, e = ArgsForCC.size(); i != e; ++i)
-    CCArgs.push_back(ArgsForCC[i].c_str());
-  CCArgs.push_back(nullptr); // NULL terminator
+    CCArgs.push_back(ArgsForCC[i]);
 
 
   outs() << "<CC>";
   outs() << "<CC>";
   outs().flush();
   outs().flush();
@@ -860,8 +848,8 @@ Error CC::MakeSharedObject(const std::string &InputFile, FileType fileType,
              for (unsigned i = 0, e = CCArgs.size() - 1; i != e; ++i) errs()
              for (unsigned i = 0, e = CCArgs.size() - 1; i != e; ++i) errs()
              << " " << CCArgs[i];
              << " " << CCArgs[i];
              errs() << "\n";);
              errs() << "\n";);
-  if (RunProgramWithTimeout(CCPath, &CCArgs[0], "", "", ""))
-    return ProcessFailure(CCPath, &CCArgs[0]);
+  if (RunProgramWithTimeout(CCPath, CCArgs, "", "", ""))
+    return ProcessFailure(CCPath, CCArgs);
   return Error::success();
   return Error::success();
 }
 }
 
 

+ 7 - 8
tools/dsymutil/MachOUtils.cpp

@@ -33,7 +33,7 @@ std::string getArchName(StringRef Arch) {
   return Arch;
   return Arch;
 }
 }
 
 
-static bool runLipo(StringRef SDKPath, SmallVectorImpl<const char *> &Args) {
+static bool runLipo(StringRef SDKPath, SmallVectorImpl<StringRef> &Args) {
   auto Path = sys::findProgramByName("lipo", makeArrayRef(SDKPath));
   auto Path = sys::findProgramByName("lipo", makeArrayRef(SDKPath));
   if (!Path)
   if (!Path)
     Path = sys::findProgramByName("lipo");
     Path = sys::findProgramByName("lipo");
@@ -44,8 +44,7 @@ static bool runLipo(StringRef SDKPath, SmallVectorImpl<const char *> &Args) {
   }
   }
 
 
   std::string ErrMsg;
   std::string ErrMsg;
-  int result =
-      sys::ExecuteAndWait(*Path, Args.data(), nullptr, {}, 0, 0, &ErrMsg);
+  int result = sys::ExecuteAndWait(*Path, Args, None, {}, 0, 0, &ErrMsg);
   if (result) {
   if (result) {
     WithColor::error() << "lipo: " << ErrMsg << "\n";
     WithColor::error() << "lipo: " << ErrMsg << "\n";
     return false;
     return false;
@@ -73,29 +72,29 @@ bool generateUniversalBinary(SmallVectorImpl<ArchAndFilename> &ArchFiles,
     return true;
     return true;
   }
   }
 
 
-  SmallVector<const char *, 8> Args;
+  SmallVector<StringRef, 8> Args;
   Args.push_back("lipo");
   Args.push_back("lipo");
   Args.push_back("-create");
   Args.push_back("-create");
 
 
   for (auto &Thin : ArchFiles)
   for (auto &Thin : ArchFiles)
-    Args.push_back(Thin.Path.c_str());
+    Args.push_back(Thin.Path);
 
 
   // Align segments to match dsymutil-classic alignment
   // Align segments to match dsymutil-classic alignment
   for (auto &Thin : ArchFiles) {
   for (auto &Thin : ArchFiles) {
     Thin.Arch = getArchName(Thin.Arch);
     Thin.Arch = getArchName(Thin.Arch);
     Args.push_back("-segalign");
     Args.push_back("-segalign");
-    Args.push_back(Thin.Arch.c_str());
+    Args.push_back(Thin.Arch);
     Args.push_back("20");
     Args.push_back("20");
   }
   }
 
 
   Args.push_back("-output");
   Args.push_back("-output");
   Args.push_back(OutputFileName.data());
   Args.push_back(OutputFileName.data());
-  Args.push_back(nullptr);
 
 
   if (Options.Verbose) {
   if (Options.Verbose) {
     outs() << "Running lipo\n";
     outs() << "Running lipo\n";
     for (auto Arg : Args)
     for (auto Arg : Args)
-      outs() << ' ' << ((Arg == nullptr) ? "\n" : Arg);
+      outs() << ' ' << Arg;
+    outs() << "\n";
   }
   }
 
 
   return Options.NoOutput ? true : runLipo(SDKPath, Args);
   return Options.NoOutput ? true : runLipo(SDKPath, Args);

+ 5 - 6
tools/llvm-cov/CodeCoverage.cpp

@@ -478,14 +478,13 @@ void CodeCoverageTool::demangleSymbols(const CoverageMapping &Coverage) {
   OutputTOF.os().close();
   OutputTOF.os().close();
 
 
   // Invoke the demangler.
   // Invoke the demangler.
-  std::vector<const char *> ArgsV;
-  for (const std::string &Arg : ViewOpts.DemanglerOpts)
-    ArgsV.push_back(Arg.c_str());
-  ArgsV.push_back(nullptr);
+  std::vector<StringRef> ArgsV;
+  for (StringRef Arg : ViewOpts.DemanglerOpts)
+    ArgsV.push_back(Arg);
   Optional<StringRef> Redirects[] = {InputPath.str(), OutputPath.str(), {""}};
   Optional<StringRef> Redirects[] = {InputPath.str(), OutputPath.str(), {""}};
   std::string ErrMsg;
   std::string ErrMsg;
-  int RC = sys::ExecuteAndWait(ViewOpts.DemanglerOpts[0], ArgsV.data(),
-                               /*env=*/nullptr, Redirects, /*secondsToWait=*/0,
+  int RC = sys::ExecuteAndWait(ViewOpts.DemanglerOpts[0], ArgsV,
+                               /*env=*/None, Redirects, /*secondsToWait=*/0,
                                /*memoryLimit=*/0, &ErrMsg);
                                /*memoryLimit=*/0, &ErrMsg);
   if (RC) {
   if (RC) {
     error(ErrMsg, ViewOpts.DemanglerOpts[0]);
     error(ErrMsg, ViewOpts.DemanglerOpts[0]);

+ 2 - 2
unittests/Support/Host.cpp

@@ -185,12 +185,12 @@ TEST_F(HostTest, getMacOSHostVersion) {
   path::append(OutputFile, "out");
   path::append(OutputFile, "out");
 
 
   const char *SwVersPath = "/usr/bin/sw_vers";
   const char *SwVersPath = "/usr/bin/sw_vers";
-  const char *argv[] = {SwVersPath, "-productVersion", nullptr};
+  StringRef argv[] = {SwVersPath, "-productVersion"};
   StringRef OutputPath = OutputFile.str();
   StringRef OutputPath = OutputFile.str();
   const Optional<StringRef> Redirects[] = {/*STDIN=*/None,
   const Optional<StringRef> Redirects[] = {/*STDIN=*/None,
                                            /*STDOUT=*/OutputPath,
                                            /*STDOUT=*/OutputPath,
                                            /*STDERR=*/None};
                                            /*STDERR=*/None};
-  int RetCode = ExecuteAndWait(SwVersPath, argv, /*env=*/nullptr, Redirects);
+  int RetCode = ExecuteAndWait(SwVersPath, argv, /*env=*/llvm::None, Redirects);
   ASSERT_EQ(0, RetCode);
   ASSERT_EQ(0, RetCode);
 
 
   int FD = 0;
   int FD = 0;

+ 22 - 38
unittests/Support/ProgramTest.cpp

@@ -60,7 +60,7 @@ static cl::opt<std::string>
 ProgramTestStringArg2("program-test-string-arg2");
 ProgramTestStringArg2("program-test-string-arg2");
 
 
 class ProgramEnvTest : public testing::Test {
 class ProgramEnvTest : public testing::Test {
-  std::vector<const char *> EnvTable;
+  std::vector<StringRef> EnvTable;
   std::vector<std::string> EnvStorage;
   std::vector<std::string> EnvStorage;
 
 
 protected:
 protected:
@@ -77,7 +77,7 @@ protected:
     }();
     }();
     ASSERT_TRUE(EnvP);
     ASSERT_TRUE(EnvP);
 
 
-    auto prepareEnvVar = [this](decltype(*EnvP) Var) {
+    auto prepareEnvVar = [this](decltype(*EnvP) Var) -> StringRef {
 #if defined(_WIN32)
 #if defined(_WIN32)
       // On Windows convert UTF16 encoded variable to UTF8
       // On Windows convert UTF16 encoded variable to UTF8
       auto Len = wcslen(Var);
       auto Len = wcslen(Var);
@@ -86,10 +86,10 @@ protected:
       EnvStorage.emplace_back();
       EnvStorage.emplace_back();
       auto convStatus = convertUTF16ToUTF8String(Ref, EnvStorage.back());
       auto convStatus = convertUTF16ToUTF8String(Ref, EnvStorage.back());
       EXPECT_TRUE(convStatus);
       EXPECT_TRUE(convStatus);
-      return EnvStorage.back().c_str();
+      return EnvStorage.back();
 #else
 #else
       (void)this;
       (void)this;
-      return Var;
+      return StringRef(Var);
 #endif
 #endif
     };
     };
 
 
@@ -104,16 +104,9 @@ protected:
     EnvStorage.clear();
     EnvStorage.clear();
   }
   }
 
 
-  void addEnvVar(const char *Var) {
-    ASSERT_TRUE(EnvTable.empty() || EnvTable.back()) << "Env table sealed";
-    EnvTable.emplace_back(Var);
-  }
+  void addEnvVar(StringRef Var) { EnvTable.emplace_back(Var); }
 
 
-  const char **getEnviron() {
-    if (EnvTable.back() != nullptr)
-      EnvTable.emplace_back(nullptr); // Seal table.
-    return &EnvTable[0];
-  }
+  ArrayRef<StringRef> getEnviron() const { return EnvTable; }
 };
 };
 
 
 #ifdef _WIN32
 #ifdef _WIN32
@@ -129,11 +122,8 @@ TEST_F(ProgramEnvTest, CreateProcessLongPath) {
     MyExe.append("\\\\?\\");
     MyExe.append("\\\\?\\");
   MyExe.append(MyAbsExe);
   MyExe.append(MyAbsExe);
 
 
-  const char *ArgV[] = {
-    MyExe.c_str(),
-    "--gtest_filter=ProgramEnvTest.CreateProcessLongPath",
-    nullptr
-  };
+  StringRef ArgV[] = {MyExe,
+                      "--gtest_filter=ProgramEnvTest.CreateProcessLongPath"};
 
 
   // Add LLVM_PROGRAM_TEST_LONG_PATH to the environment of the child.
   // Add LLVM_PROGRAM_TEST_LONG_PATH to the environment of the child.
   addEnvVar("LLVM_PROGRAM_TEST_LONG_PATH=1");
   addEnvVar("LLVM_PROGRAM_TEST_LONG_PATH=1");
@@ -173,13 +163,13 @@ TEST_F(ProgramEnvTest, CreateProcessTrailingSlash) {
 
 
   std::string my_exe =
   std::string my_exe =
       sys::fs::getMainExecutable(TestMainArgv0, &ProgramTestStringArg1);
       sys::fs::getMainExecutable(TestMainArgv0, &ProgramTestStringArg1);
-  const char *argv[] = {
-    my_exe.c_str(),
-    "--gtest_filter=ProgramEnvTest.CreateProcessTrailingSlash",
-    "-program-test-string-arg1", "has\\\\ trailing\\",
-    "-program-test-string-arg2", "has\\\\ trailing\\",
-    nullptr
-  };
+  StringRef argv[] = {
+      my_exe,
+      "--gtest_filter=ProgramEnvTest.CreateProcessTrailingSlash",
+      "-program-test-string-arg1",
+      "has\\\\ trailing\\",
+      "-program-test-string-arg2",
+      "has\\\\ trailing\\"};
 
 
   // Add LLVM_PROGRAM_TEST_CHILD to the environment of the child.
   // Add LLVM_PROGRAM_TEST_CHILD to the environment of the child.
   addEnvVar("LLVM_PROGRAM_TEST_CHILD=1");
   addEnvVar("LLVM_PROGRAM_TEST_CHILD=1");
@@ -210,11 +200,8 @@ TEST_F(ProgramEnvTest, TestExecuteNoWait) {
 
 
   std::string Executable =
   std::string Executable =
       sys::fs::getMainExecutable(TestMainArgv0, &ProgramTestStringArg1);
       sys::fs::getMainExecutable(TestMainArgv0, &ProgramTestStringArg1);
-  const char *argv[] = {
-    Executable.c_str(),
-    "--gtest_filter=ProgramEnvTest.TestExecuteNoWait",
-    nullptr
-  };
+  StringRef argv[] = {Executable,
+                      "--gtest_filter=ProgramEnvTest.TestExecuteNoWait"};
 
 
   // Add LLVM_PROGRAM_TEST_EXECUTE_NO_WAIT to the environment of the child.
   // Add LLVM_PROGRAM_TEST_EXECUTE_NO_WAIT to the environment of the child.
   addEnvVar("LLVM_PROGRAM_TEST_EXECUTE_NO_WAIT=1");
   addEnvVar("LLVM_PROGRAM_TEST_EXECUTE_NO_WAIT=1");
@@ -268,11 +255,8 @@ TEST_F(ProgramEnvTest, TestExecuteAndWaitTimeout) {
 
 
   std::string Executable =
   std::string Executable =
       sys::fs::getMainExecutable(TestMainArgv0, &ProgramTestStringArg1);
       sys::fs::getMainExecutable(TestMainArgv0, &ProgramTestStringArg1);
-  const char *argv[] = {
-    Executable.c_str(),
-    "--gtest_filter=ProgramEnvTest.TestExecuteAndWaitTimeout",
-    nullptr
-  };
+  StringRef argv[] = {
+      Executable, "--gtest_filter=ProgramEnvTest.TestExecuteAndWaitTimeout"};
 
 
   // Add LLVM_PROGRAM_TEST_TIMEOUT to the environment of the child.
   // Add LLVM_PROGRAM_TEST_TIMEOUT to the environment of the child.
  addEnvVar("LLVM_PROGRAM_TEST_TIMEOUT=1");
  addEnvVar("LLVM_PROGRAM_TEST_TIMEOUT=1");
@@ -287,12 +271,12 @@ TEST_F(ProgramEnvTest, TestExecuteAndWaitTimeout) {
 
 
 TEST(ProgramTest, TestExecuteNegative) {
 TEST(ProgramTest, TestExecuteNegative) {
   std::string Executable = "i_dont_exist";
   std::string Executable = "i_dont_exist";
-  const char *argv[] = { Executable.c_str(), nullptr };
+  StringRef argv[] = {Executable};
 
 
   {
   {
     std::string Error;
     std::string Error;
     bool ExecutionFailed;
     bool ExecutionFailed;
-    int RetCode = ExecuteAndWait(Executable, argv, nullptr, {}, 0, 0, &Error,
+    int RetCode = ExecuteAndWait(Executable, argv, llvm::None, {}, 0, 0, &Error,
                                  &ExecutionFailed);
                                  &ExecutionFailed);
     ASSERT_TRUE(RetCode < 0) << "On error ExecuteAndWait should return 0 or "
     ASSERT_TRUE(RetCode < 0) << "On error ExecuteAndWait should return 0 or "
                                 "positive value indicating the result code";
                                 "positive value indicating the result code";
@@ -303,7 +287,7 @@ TEST(ProgramTest, TestExecuteNegative) {
   {
   {
     std::string Error;
     std::string Error;
     bool ExecutionFailed;
     bool ExecutionFailed;
-    ProcessInfo PI = ExecuteNoWait(Executable, argv, nullptr, {}, 0, &Error,
+    ProcessInfo PI = ExecuteNoWait(Executable, argv, llvm::None, {}, 0, &Error,
                                    &ExecutionFailed);
                                    &ExecutionFailed);
     ASSERT_EQ(PI.Pid, ProcessInfo::InvalidPid)
     ASSERT_EQ(PI.Pid, ProcessInfo::InvalidPid)
         << "On error ExecuteNoWait should return an invalid ProcessInfo";
         << "On error ExecuteNoWait should return an invalid ProcessInfo";

+ 5 - 1
utils/not/not.cpp

@@ -38,8 +38,12 @@ int main(int argc, const char **argv) {
     return 1;
     return 1;
   }
   }
 
 
+  std::vector<StringRef> Argv;
+  Argv.reserve(argc);
+  for (int i = 0; i < argc; ++i)
+    Argv.push_back(argv[i]);
   std::string ErrMsg;
   std::string ErrMsg;
-  int Result = sys::ExecuteAndWait(*Program, argv, nullptr, {}, 0, 0, &ErrMsg);
+  int Result = sys::ExecuteAndWait(*Program, Argv, None, {}, 0, 0, &ErrMsg);
 #ifdef _WIN32
 #ifdef _WIN32
   // Handle abort() in msvcrt -- It has exit code as 3.  abort(), aka
   // Handle abort() in msvcrt -- It has exit code as 3.  abort(), aka
   // unreachable, should be recognized as a crash.  However, some binaries use
   // unreachable, should be recognized as a crash.  However, some binaries use