From 0dcc1159b40e8d45d5d02baeb11d19a3e4339c57 Mon Sep 17 00:00:00 2001 From: Zachary Turner Date: Tue, 12 Jun 2018 17:43:52 +0000 Subject: [PATCH] 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 --- include/llvm/ADT/StringExtras.h | 10 +++ include/llvm/Support/Program.h | 15 ++-- lib/Support/GraphWriter.cpp | 64 ++++++-------- lib/Support/Program.cpp | 16 ++-- lib/Support/Signals.cpp | 17 ++-- lib/Support/Unix/Program.inc | 35 ++++++-- lib/Support/Windows/Program.inc | 21 ++--- tools/bugpoint/OptimizerDriver.cpp | 15 ++-- tools/bugpoint/ToolRunner.cpp | 174 +++++++++++++++++-------------------- tools/dsymutil/MachOUtils.cpp | 15 ++-- tools/llvm-cov/CodeCoverage.cpp | 11 ++- unittests/Support/Host.cpp | 4 +- unittests/Support/ProgramTest.cpp | 60 +++++-------- utils/not/not.cpp | 6 +- 14 files changed, 227 insertions(+), 236 deletions(-) diff --git a/include/llvm/ADT/StringExtras.h b/include/llvm/ADT/StringExtras.h index 21a1bbcfad2..12a685cec8a 100644 --- a/include/llvm/ADT/StringExtras.h +++ b/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; } +/// 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 toStringRefArray(const char *const *Strings) { + std::vector Result; + while (*Strings) + Result.push_back(*Strings++); + return Result; +} + /// Construct a string ref from a boolean. inline StringRef toStringRef(bool B) { return StringRef(B ? "true" : "false"); } diff --git a/include/llvm/Support/Program.h b/include/llvm/Support/Program.h index e64bfb2948a..1f4dbdce332 100644 --- a/include/llvm/Support/Program.h +++ b/include/llvm/Support/Program.h @@ -89,12 +89,13 @@ namespace sys { int ExecuteAndWait( StringRef Program, ///< Path of the program to be executed. It is ///< presumed this is the result of the findProgramByName method. - const char **Args, ///< A vector of strings that are passed to the + ArrayRef Args, ///< An array of strings that are passed to the ///< 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> 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> Redirects = {}, ///< ///< An array of optional paths. Should have a size of zero or three. ///< 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 /// \see Wait until the process finished execution or win32 CloseHandle() API /// on ProcessInfo.ProcessHandle to avoid memory leaks. - ProcessInfo ExecuteNoWait(StringRef Program, const char **Args, - const char **Env = nullptr, + ProcessInfo ExecuteNoWait(StringRef Program, ArrayRef Args, + Optional> Env, ArrayRef> Redirects = {}, unsigned MemoryLimit = 0, std::string *ErrMsg = nullptr, diff --git a/lib/Support/GraphWriter.cpp b/lib/Support/GraphWriter.cpp index 794c6ba3a85..9335daffc3e 100644 --- a/lib/Support/GraphWriter.cpp +++ b/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. -static bool ExecGraphViewer(StringRef ExecPath, std::vector &args, +static bool ExecGraphViewer(StringRef ExecPath, std::vector &args, StringRef Filename, bool wait, std::string &ErrMsg) { - assert(args.back() == nullptr); 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"; return true; } sys::fs::remove(Filename); errs() << " done. \n"; } else { - sys::ExecuteNoWait(ExecPath, args.data(), nullptr, {}, 0, &ErrMsg); + sys::ExecuteNoWait(ExecPath, args, None, {}, 0, &ErrMsg); errs() << "Remember to erase graph file: " << Filename << "\n"; } return false; @@ -158,22 +156,20 @@ bool llvm::DisplayGraph(StringRef FilenameRef, bool wait, #ifdef __APPLE__ wait &= !ViewBackground; if (S.TryFindProgram("open", ViewerPath)) { - std::vector args; - args.push_back(ViewerPath.c_str()); + std::vector args; + args.push_back(ViewerPath); if (wait) args.push_back("-W"); - args.push_back(Filename.c_str()); - args.push_back(nullptr); + args.push_back(Filename); errs() << "Trying 'open' program... "; if (!ExecGraphViewer(ViewerPath, args, Filename, wait, ErrMsg)) return false; } #endif if (S.TryFindProgram("xdg-open", ViewerPath)) { - std::vector args; - args.push_back(ViewerPath.c_str()); - args.push_back(Filename.c_str()); - args.push_back(nullptr); + std::vector args; + args.push_back(ViewerPath); + args.push_back(Filename); errs() << "Trying 'xdg-open' program... "; if (!ExecGraphViewer(ViewerPath, args, Filename, wait, ErrMsg)) return false; @@ -181,10 +177,9 @@ bool llvm::DisplayGraph(StringRef FilenameRef, bool wait, // Graphviz if (S.TryFindProgram("Graphviz", ViewerPath)) { - std::vector args; - args.push_back(ViewerPath.c_str()); - args.push_back(Filename.c_str()); - args.push_back(nullptr); + std::vector args; + args.push_back(ViewerPath); + args.push_back(Filename); errs() << "Running 'Graphviz' program... "; return ExecGraphViewer(ViewerPath, args, Filename, wait, ErrMsg); @@ -192,15 +187,13 @@ bool llvm::DisplayGraph(StringRef FilenameRef, bool wait, // xdot if (S.TryFindProgram("xdot|xdot.py", ViewerPath)) { - std::vector args; - args.push_back(ViewerPath.c_str()); - args.push_back(Filename.c_str()); + std::vector args; + args.push_back(ViewerPath); + args.push_back(Filename); args.push_back("-f"); args.push_back(getProgramName(program)); - args.push_back(nullptr); - errs() << "Running 'xdot.py' program... "; return ExecGraphViewer(ViewerPath, args, Filename, wait, ErrMsg); } @@ -235,18 +228,17 @@ bool llvm::DisplayGraph(StringRef FilenameRef, bool wait, std::string OutputFilename = Filename + (Viewer == VK_CmdStart ? ".pdf" : ".ps"); - std::vector args; - args.push_back(GeneratorPath.c_str()); + std::vector args; + args.push_back(GeneratorPath); if (Viewer == VK_CmdStart) args.push_back("-Tpdf"); else args.push_back("-Tps"); args.push_back("-Nfontname=Courier"); args.push_back("-Gsize=7.5,10"); - args.push_back(Filename.c_str()); + args.push_back(Filename); args.push_back("-o"); - args.push_back(OutputFilename.c_str()); - args.push_back(nullptr); + args.push_back(OutputFilename); errs() << "Running '" << GeneratorPath << "' program... "; @@ -258,31 +250,30 @@ bool llvm::DisplayGraph(StringRef FilenameRef, bool wait, std::string StartArg; args.clear(); - args.push_back(ViewerPath.c_str()); + args.push_back(ViewerPath); switch (Viewer) { case VK_OSXOpen: args.push_back("-W"); - args.push_back(OutputFilename.c_str()); + args.push_back(OutputFilename); break; case VK_XDGOpen: wait = false; - args.push_back(OutputFilename.c_str()); + args.push_back(OutputFilename); break; case VK_Ghostview: args.push_back("--spartan"); - args.push_back(OutputFilename.c_str()); + args.push_back(OutputFilename); break; case VK_CmdStart: args.push_back("/S"); args.push_back("/C"); StartArg = (StringRef("start ") + (wait ? "/WAIT " : "") + OutputFilename).str(); - args.push_back(StartArg.c_str()); + args.push_back(StartArg); break; case VK_None: llvm_unreachable("Invalid viewer"); } - args.push_back(nullptr); ErrMsg.clear(); return ExecGraphViewer(ViewerPath, args, OutputFilename, wait, ErrMsg); @@ -290,10 +281,9 @@ bool llvm::DisplayGraph(StringRef FilenameRef, bool wait, // dotty if (S.TryFindProgram("dotty", ViewerPath)) { - std::vector args; - args.push_back(ViewerPath.c_str()); - args.push_back(Filename.c_str()); - args.push_back(nullptr); + std::vector args; + args.push_back(ViewerPath); + args.push_back(Filename); // Dotty spawns another app and doesn't wait until it returns #ifdef _WIN32 diff --git a/lib/Support/Program.cpp b/lib/Support/Program.cpp index 8c56fb6db2d..63cdcdaabee 100644 --- a/lib/Support/Program.cpp +++ b/lib/Support/Program.cpp @@ -23,17 +23,19 @@ using namespace sys; //=== independent code. //===----------------------------------------------------------------------===// -static bool Execute(ProcessInfo &PI, StringRef Program, const char **Args, - const char **Env, ArrayRef> Redirects, +static bool Execute(ProcessInfo &PI, StringRef Program, + ArrayRef Args, Optional> Env, + ArrayRef> Redirects, unsigned MemoryLimit, std::string *ErrMsg); -int sys::ExecuteAndWait(StringRef Program, const char **Args, const char **Envp, +int sys::ExecuteAndWait(StringRef Program, ArrayRef Args, + Optional> Env, ArrayRef> Redirects, unsigned SecondsToWait, unsigned MemoryLimit, std::string *ErrMsg, bool *ExecutionFailed) { assert(Redirects.empty() || Redirects.size() == 3); ProcessInfo PI; - if (Execute(PI, Program, Args, Envp, Redirects, MemoryLimit, ErrMsg)) { + if (Execute(PI, Program, Args, Env, Redirects, MemoryLimit, ErrMsg)) { if (ExecutionFailed) *ExecutionFailed = false; ProcessInfo Result = Wait( @@ -47,8 +49,8 @@ int sys::ExecuteAndWait(StringRef Program, const char **Args, const char **Envp, return -1; } -ProcessInfo sys::ExecuteNoWait(StringRef Program, const char **Args, - const char **Envp, +ProcessInfo sys::ExecuteNoWait(StringRef Program, ArrayRef Args, + Optional> Env, ArrayRef> Redirects, unsigned MemoryLimit, std::string *ErrMsg, bool *ExecutionFailed) { @@ -56,7 +58,7 @@ ProcessInfo sys::ExecuteNoWait(StringRef Program, const char **Args, ProcessInfo PI; if (ExecutionFailed) *ExecutionFailed = false; - if (!Execute(PI, Program, Args, Envp, Redirects, MemoryLimit, ErrMsg)) + if (!Execute(PI, Program, Args, Env, Redirects, MemoryLimit, ErrMsg)) if (ExecutionFailed) *ExecutionFailed = true; diff --git a/lib/Support/Signals.cpp b/lib/Support/Signals.cpp index 76a3c6bed41..6534ff69b84 100644 --- a/lib/Support/Signals.cpp +++ b/lib/Support/Signals.cpp @@ -154,17 +154,18 @@ static bool printSymbolizedStackTrace(StringRef Argv0, void **StackTrace, } } - Optional Redirects[] = {InputFile.str(), OutputFile.str(), llvm::None}; - const char *Args[] = {"llvm-symbolizer", "--functions=linkage", "--inlining", + Optional Redirects[] = {StringRef(InputFile), + StringRef(OutputFile), llvm::None}; + StringRef Args[] = {"llvm-symbolizer", "--functions=linkage", "--inlining", #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 - "--demangle", nullptr}; + "--demangle"}; int RunResult = - sys::ExecuteAndWait(LLVMSymbolizerPath, Args, nullptr, Redirects); + sys::ExecuteAndWait(LLVMSymbolizerPath, Args, None, Redirects); if (RunResult != 0) return false; diff --git a/lib/Support/Unix/Program.inc b/lib/Support/Unix/Program.inc index be971555b82..d0abc3763e8 100644 --- a/lib/Support/Unix/Program.inc +++ b/lib/Support/Unix/Program.inc @@ -23,6 +23,7 @@ #include "llvm/Support/Errc.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/Path.h" +#include "llvm/Support/StringSaver.h" #include "llvm/Support/raw_ostream.h" #if HAVE_SYS_STAT_H #include @@ -164,8 +165,18 @@ static void SetMemoryLimits(unsigned size) { } -static bool Execute(ProcessInfo &PI, StringRef Program, const char **Args, - const char **Envp, ArrayRef> Redirects, +static std::vector +toNullTerminatedCStringArray(ArrayRef Strings, StringSaver &Saver) { + std::vector 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 Args, Optional> Env, + ArrayRef> Redirects, unsigned MemoryLimit, std::string *ErrMsg) { if (!llvm::sys::fs::exists(Program)) { if (ErrMsg) @@ -174,6 +185,18 @@ static bool Execute(ProcessInfo &PI, StringRef Program, const char **Args, return false; } + BumpPtrAllocator Allocator; + StringSaver Saver(Allocator); + std::vector 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 // posix_spawn. It is more efficient than fork/exec. #ifdef HAVE_POSIX_SPAWN @@ -227,7 +250,7 @@ static bool Execute(ProcessInfo &PI, StringRef Program, const char **Args, // positive. pid_t PID = 0; int Err = posix_spawn(&PID, Program.str().c_str(), FileActions, - /*attrp*/nullptr, const_cast(Args), + /*attrp*/ nullptr, const_cast(Argv), const_cast(Envp)); if (FileActions) @@ -280,12 +303,10 @@ static bool Execute(ProcessInfo &PI, StringRef Program, const char **Args, // Execute! std::string PathStr = Program; if (Envp != nullptr) - execve(PathStr.c_str(), - const_cast(Args), + execve(PathStr.c_str(), const_cast(Argv), const_cast(Envp)); else - execv(PathStr.c_str(), - const_cast(Args)); + execv(PathStr.c_str(), const_cast(Argv)); // If the execve() failed, we should exit. Follow Unix protocol and // return 127 if the executable was not found, and 126 otherwise. // Use _exit rather than exit so that atexit functions and static diff --git a/lib/Support/Windows/Program.inc b/lib/Support/Windows/Program.inc index 19a38c78432..cb68c5b10e5 100644 --- a/lib/Support/Windows/Program.inc +++ b/lib/Support/Windows/Program.inc @@ -149,15 +149,9 @@ static HANDLE RedirectIO(Optional Path, int fd, } -static SmallVector buildArgVector(const char **Args) { - SmallVector 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> Redirects, +static bool Execute(ProcessInfo &PI, StringRef Program, + ArrayRef Args, Optional> Env, + ArrayRef> Redirects, unsigned MemoryLimit, std::string *ErrMsg) { if (!sys::fs::can_execute(Program)) { 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 // process. We have to concatenate them all, while quoting the args that // 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. std::vector EnvBlock; - if (Envp) { + if (Env) { // An environment block consists of a null-terminated block of // null-terminated strings. Convert the array of environment variables to // an environment block by concatenating them. - for (unsigned i = 0; Envp[i]; ++i) { + for (const auto E : *Env) { SmallVector EnvString; - if (std::error_code ec = windows::UTF8ToUTF16(Envp[i], EnvString)) { + if (std::error_code ec = windows::UTF8ToUTF16(E, EnvString)) { SetLastError(ec.value()); MakeErrMsg(ErrMsg, "Unable to convert environment variable to UTF-16"); return false; diff --git a/tools/bugpoint/OptimizerDriver.cpp b/tools/bugpoint/OptimizerDriver.cpp index bdb6c5f1941..cbb048db8fe 100644 --- a/tools/bugpoint/OptimizerDriver.cpp +++ b/tools/bugpoint/OptimizerDriver.cpp @@ -194,20 +194,20 @@ bool BugDriver::runPasses(Module &Program, } // setup the child process' arguments - SmallVector Args; + SmallVector Args; if (UseValgrind) { Args.push_back("valgrind"); Args.push_back("--error-exitcode=1"); Args.push_back("-q"); - Args.push_back(tool.c_str()); + Args.push_back(tool); } else - Args.push_back(tool.c_str()); + Args.push_back(tool); 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("-o"); - Args.push_back(OutputFilename.c_str()); + Args.push_back(OutputFilename); std::vector pass_args; for (unsigned i = 0, e = PluginLoader::getNumPlugins(); i != e; ++i) { pass_args.push_back(std::string("-load")); @@ -224,7 +224,6 @@ bool BugDriver::runPasses(Module &Program, Args.push_back(Temp->TmpName.c_str()); for (unsigned i = 0; i < NumExtraArgs; ++i) Args.push_back(*ExtraArgs); - Args.push_back(nullptr); LLVM_DEBUG(errs() << "\nAbout to run:\t"; for (unsigned i = 0, e = Args.size() - 1; i != e; ++i) errs() @@ -239,8 +238,8 @@ bool BugDriver::runPasses(Module &Program, } 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, // remove it now. This may fail if the file was never created, but that's ok. diff --git a/tools/bugpoint/ToolRunner.cpp b/tools/bugpoint/ToolRunner.cpp index 2fb9f93ad7d..812e8e3bbae 100644 --- a/tools/bugpoint/ToolRunner.cpp +++ b/tools/bugpoint/ToolRunner.cpp @@ -53,13 +53,14 @@ cl::opt /// RunProgramWithTimeout - This function provides an alternate interface /// to the sys::Program::ExecuteAndWait interface. /// @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 Args, StringRef StdInFile, + StringRef StdOutFile, StringRef StdErrFile, + unsigned NumSeconds = 0, unsigned MemoryLimit = 0, std::string *ErrMsg = nullptr) { Optional Redirects[3] = {StdInFile, StdOutFile, StdErrFile}; - return sys::ExecuteAndWait(ProgramPath, Args, nullptr, Redirects, NumSeconds, + return sys::ExecuteAndWait(ProgramPath, Args, None, Redirects, NumSeconds, 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 /// code otherwise. /// @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 Args, StringRef StdInFile, + StringRef StdOutFile, StringRef StdErrFile, unsigned NumSeconds = 0, + unsigned MemoryLimit = 0) { Optional Redirects[3] = {StdInFile, StdOutFile, StdErrFile}; // 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? if (255 == ReturnCode) { std::ostringstream OS; OS << "\nError running remote client:\n "; - for (const char **Arg = Args; *Arg; ++Arg) - OS << " " << *Arg; + for (StringRef Arg : Args) + OS << " " << Arg.str(); OS << "\n"; // 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; } -static Error ProcessFailure(StringRef ProgPath, const char **Args, +static Error ProcessFailure(StringRef ProgPath, ArrayRef Args, unsigned Timeout = 0, unsigned MemoryLimit = 0) { std::ostringstream OS; OS << "\nError running tool:\n "; - for (const char **Arg = Args; *Arg; ++Arg) - OS << " " << *Arg; + for (StringRef Arg : Args) + OS << " " << Arg.str(); OS << "\n"; // Rerun the compiler, capturing any error messages to print them. @@ -171,7 +170,7 @@ Expected LLI::ExecuteProgram(const std::string &Bitcode, const std::vector &CCArgs, const std::vector &SharedLibs, unsigned Timeout, unsigned MemoryLimit) { - std::vector LLIArgs; + std::vector LLIArgs; LLIArgs.push_back(LLIPath.c_str()); LLIArgs.push_back("-force-interpreter=true"); @@ -179,18 +178,17 @@ Expected LLI::ExecuteProgram(const std::string &Bitcode, e = SharedLibs.end(); i != e; ++i) { LLIArgs.push_back("-load"); - LLIArgs.push_back((*i).c_str()); + LLIArgs.push_back(*i); } // Add any extra LLI args. 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 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() << ""; outs().flush(); @@ -198,7 +196,7 @@ Expected LLI::ExecuteProgram(const std::string &Bitcode, for (unsigned i = 0, e = LLIArgs.size() - 1; i != e; ++i) errs() << " " << LLIArgs[i]; errs() << "\n";); - return RunProgramWithTimeout(LLIPath, &LLIArgs[0], InputFile, OutputFile, + return RunProgramWithTimeout(LLIPath, LLIArgs, InputFile, OutputFile, OutputFile, Timeout, MemoryLimit); } @@ -285,22 +283,20 @@ public: Error CustomCompiler::compileProgram(const std::string &Bitcode, unsigned Timeout, unsigned MemoryLimit) { - std::vector ProgramArgs; + std::vector ProgramArgs; ProgramArgs.push_back(CompilerCommand.c_str()); for (std::size_t i = 0; i < CompilerArgs.size(); ++i) 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 for (unsigned i = 0, e = CompilerArgs.size(); i != e; ++i) 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(); } @@ -336,19 +332,18 @@ Expected CustomExecutor::ExecuteProgram( const std::vector &SharedLibs, unsigned Timeout, unsigned MemoryLimit) { - std::vector ProgramArgs; - ProgramArgs.push_back(ExecutionCommand.c_str()); + std::vector ProgramArgs; + ProgramArgs.push_back(ExecutionCommand); 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 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); } @@ -463,31 +458,28 @@ Expected LLC::OutputCode(const std::string &Bitcode, exit(1); } OutputAsmFile = UniqueFile.str(); - std::vector LLCArgs; - LLCArgs.push_back(LLCPath.c_str()); + std::vector LLCArgs; + LLCArgs.push_back(LLCPath); // Add any extra LLC args. 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(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) LLCArgs.push_back("-filetype=obj"); - LLCArgs.push_back(nullptr); - outs() << (UseIntegratedAssembler ? "" : ""); outs().flush(); LLVM_DEBUG(errs() << "\nAbout to run:\t"; for (unsigned i = 0, e = LLCArgs.size() - 1; i != e; ++i) errs() << " " << LLCArgs[i]; 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; } @@ -581,23 +573,22 @@ Expected JIT::ExecuteProgram(const std::string &Bitcode, const std::vector &SharedLibs, unsigned Timeout, unsigned MemoryLimit) { // Construct a vector of parameters, incorporating those from the command-line - std::vector JITArgs; + std::vector JITArgs; JITArgs.push_back(LLIPath.c_str()); JITArgs.push_back("-force-interpreter=false"); // Add any extra LLI args. 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) { JITArgs.push_back("-load"); - JITArgs.push_back(SharedLibs[i].c_str()); + JITArgs.push_back(SharedLibs[i]); } JITArgs.push_back(Bitcode.c_str()); // Add optional parameters to the running program from Argv 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() << ""; outs().flush(); @@ -606,7 +597,7 @@ Expected JIT::ExecuteProgram(const std::string &Bitcode, << " " << JITArgs[i]; errs() << "\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); } @@ -630,15 +621,15 @@ AbstractInterpreter::createJIT(const char *Argv0, std::string &Message, // CC abstraction // -static bool IsARMArchitecture(std::vector Args) { - for (std::vector::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 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; @@ -651,9 +642,9 @@ Expected CC::ExecuteProgram(const std::string &ProgramFile, const std::string &OutputFile, const std::vector &ArgsForCC, unsigned Timeout, unsigned MemoryLimit) { - std::vector CCArgs; + std::vector CCArgs; - CCArgs.push_back(CCPath.c_str()); + CCArgs.push_back(CCPath); if (TargetTriple.getArch() == Triple::x86) CCArgs.push_back("-m32"); @@ -661,7 +652,7 @@ Expected CC::ExecuteProgram(const std::string &ProgramFile, for (std::vector::const_iterator I = ccArgs.begin(), E = ccArgs.end(); I != E; ++I) - CCArgs.push_back(I->c_str()); + CCArgs.push_back(*I); // Specify -x explicitly in case the extension is wonky if (fileType != ObjectFile) { @@ -680,7 +671,7 @@ Expected 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("none"); @@ -693,20 +684,19 @@ Expected CC::ExecuteProgram(const std::string &ProgramFile, errs() << "Error making unique filename: " << EC.message() << "\n"; 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 // 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 // command line, so this should be safe. 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("-O2"); // Optimize the program a bit... if (TargetTriple.getArch() == Triple::sparc) CCArgs.push_back("-mcpu=v9"); - CCArgs.push_back(nullptr); // NULL terminator outs() << ""; outs().flush(); @@ -714,30 +704,30 @@ Expected CC::ExecuteProgram(const std::string &ProgramFile, for (unsigned i = 0, e = CCArgs.size() - 1; i != e; ++i) errs() << " " << CCArgs[i]; errs() << "\n";); - if (RunProgramWithTimeout(CCPath, &CCArgs[0], "", "", "")) - return ProcessFailure(CCPath, &CCArgs[0]); + if (RunProgramWithTimeout(CCPath, CCArgs, "", "", "")) + return ProcessFailure(CCPath, CCArgs); - std::vector ProgramArgs; + std::vector ProgramArgs; // Declared here so that the destructor only runs after // ProgramArgs is used. std::string Exec; if (RemoteClientPath.empty()) - ProgramArgs.push_back(OutputBinary.c_str()); + ProgramArgs.push_back(OutputBinary); else { - ProgramArgs.push_back(RemoteClientPath.c_str()); - ProgramArgs.push_back(RemoteHost.c_str()); + ProgramArgs.push_back(RemoteClientPath); + ProgramArgs.push_back(RemoteHost); if (!RemoteUser.empty()) { ProgramArgs.push_back("-l"); - ProgramArgs.push_back(RemoteUser.c_str()); + ProgramArgs.push_back(RemoteUser); } if (!RemotePort.empty()) { ProgramArgs.push_back("-p"); - ProgramArgs.push_back(RemotePort.c_str()); + ProgramArgs.push_back(RemotePort); } 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 @@ -747,13 +737,12 @@ Expected CC::ExecuteProgram(const std::string &ProgramFile, Exec += env_pwd; Exec += "; ./"; Exec += OutputBinary.c_str(); - ProgramArgs.push_back(Exec.c_str()); + ProgramArgs.push_back(Exec); } // Add optional parameters to the running program from Argv 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! outs() << ""; @@ -769,7 +758,7 @@ Expected CC::ExecuteProgram(const std::string &ProgramFile, if (RemoteClientPath.empty()) { LLVM_DEBUG(errs() << ""); std::string Error; - int ExitCode = RunProgramWithTimeout(OutputBinary.str(), &ProgramArgs[0], + int ExitCode = RunProgramWithTimeout(OutputBinary.str(), ProgramArgs, InputFile, OutputFile, OutputFile, Timeout, MemoryLimit, &Error); // Treat a signal (usually SIGSEGV) or timeout as part of the program output @@ -783,7 +772,7 @@ Expected CC::ExecuteProgram(const std::string &ProgramFile, } else { outs() << ""; outs().flush(); - return RunProgramRemotelyWithTimeout(RemoteClientPath, &ProgramArgs[0], + return RunProgramRemotelyWithTimeout(RemoteClientPath, ProgramArgs, InputFile, OutputFile, OutputFile, Timeout, MemoryLimit); } @@ -801,9 +790,9 @@ Error CC::MakeSharedObject(const std::string &InputFile, FileType fileType, } OutputFile = UniqueFilename.str(); - std::vector CCArgs; + std::vector CCArgs; - CCArgs.push_back(CCPath.c_str()); + CCArgs.push_back(CCPath); if (TargetTriple.getArch() == Triple::x86) CCArgs.push_back("-m32"); @@ -811,7 +800,7 @@ Error CC::MakeSharedObject(const std::string &InputFile, FileType fileType, for (std::vector::const_iterator I = ccArgs.begin(), E = ccArgs.end(); I != E; ++I) - CCArgs.push_back(I->c_str()); + CCArgs.push_back(*I); // Compile the C/asm file into a shared object 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("-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("none"); 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("-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. // 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 // command line, so this should be safe. 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() << ""; 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() << " " << CCArgs[i]; errs() << "\n";); - if (RunProgramWithTimeout(CCPath, &CCArgs[0], "", "", "")) - return ProcessFailure(CCPath, &CCArgs[0]); + if (RunProgramWithTimeout(CCPath, CCArgs, "", "", "")) + return ProcessFailure(CCPath, CCArgs); return Error::success(); } diff --git a/tools/dsymutil/MachOUtils.cpp b/tools/dsymutil/MachOUtils.cpp index cd9fbe09cfc..c683b6a786f 100644 --- a/tools/dsymutil/MachOUtils.cpp +++ b/tools/dsymutil/MachOUtils.cpp @@ -33,7 +33,7 @@ std::string getArchName(StringRef Arch) { return Arch; } -static bool runLipo(StringRef SDKPath, SmallVectorImpl &Args) { +static bool runLipo(StringRef SDKPath, SmallVectorImpl &Args) { auto Path = sys::findProgramByName("lipo", makeArrayRef(SDKPath)); if (!Path) Path = sys::findProgramByName("lipo"); @@ -44,8 +44,7 @@ static bool runLipo(StringRef SDKPath, SmallVectorImpl &Args) { } 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) { WithColor::error() << "lipo: " << ErrMsg << "\n"; return false; @@ -73,29 +72,29 @@ bool generateUniversalBinary(SmallVectorImpl &ArchFiles, return true; } - SmallVector Args; + SmallVector Args; Args.push_back("lipo"); Args.push_back("-create"); for (auto &Thin : ArchFiles) - Args.push_back(Thin.Path.c_str()); + Args.push_back(Thin.Path); // Align segments to match dsymutil-classic alignment for (auto &Thin : ArchFiles) { Thin.Arch = getArchName(Thin.Arch); Args.push_back("-segalign"); - Args.push_back(Thin.Arch.c_str()); + Args.push_back(Thin.Arch); Args.push_back("20"); } Args.push_back("-output"); Args.push_back(OutputFileName.data()); - Args.push_back(nullptr); if (Options.Verbose) { outs() << "Running lipo\n"; for (auto Arg : Args) - outs() << ' ' << ((Arg == nullptr) ? "\n" : Arg); + outs() << ' ' << Arg; + outs() << "\n"; } return Options.NoOutput ? true : runLipo(SDKPath, Args); diff --git a/tools/llvm-cov/CodeCoverage.cpp b/tools/llvm-cov/CodeCoverage.cpp index e40cc5c386e..e93b63d388e 100644 --- a/tools/llvm-cov/CodeCoverage.cpp +++ b/tools/llvm-cov/CodeCoverage.cpp @@ -478,14 +478,13 @@ void CodeCoverageTool::demangleSymbols(const CoverageMapping &Coverage) { OutputTOF.os().close(); // Invoke the demangler. - std::vector ArgsV; - for (const std::string &Arg : ViewOpts.DemanglerOpts) - ArgsV.push_back(Arg.c_str()); - ArgsV.push_back(nullptr); + std::vector ArgsV; + for (StringRef Arg : ViewOpts.DemanglerOpts) + ArgsV.push_back(Arg); Optional Redirects[] = {InputPath.str(), OutputPath.str(), {""}}; 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); if (RC) { error(ErrMsg, ViewOpts.DemanglerOpts[0]); diff --git a/unittests/Support/Host.cpp b/unittests/Support/Host.cpp index 736b04c2049..e07d4151bb6 100644 --- a/unittests/Support/Host.cpp +++ b/unittests/Support/Host.cpp @@ -185,12 +185,12 @@ TEST_F(HostTest, getMacOSHostVersion) { path::append(OutputFile, "out"); const char *SwVersPath = "/usr/bin/sw_vers"; - const char *argv[] = {SwVersPath, "-productVersion", nullptr}; + StringRef argv[] = {SwVersPath, "-productVersion"}; StringRef OutputPath = OutputFile.str(); const Optional Redirects[] = {/*STDIN=*/None, /*STDOUT=*/OutputPath, /*STDERR=*/None}; - int RetCode = ExecuteAndWait(SwVersPath, argv, /*env=*/nullptr, Redirects); + int RetCode = ExecuteAndWait(SwVersPath, argv, /*env=*/llvm::None, Redirects); ASSERT_EQ(0, RetCode); int FD = 0; diff --git a/unittests/Support/ProgramTest.cpp b/unittests/Support/ProgramTest.cpp index 7a0676c7a48..ec1c85a9f25 100644 --- a/unittests/Support/ProgramTest.cpp +++ b/unittests/Support/ProgramTest.cpp @@ -60,7 +60,7 @@ static cl::opt ProgramTestStringArg2("program-test-string-arg2"); class ProgramEnvTest : public testing::Test { - std::vector EnvTable; + std::vector EnvTable; std::vector EnvStorage; protected: @@ -77,7 +77,7 @@ protected: }(); ASSERT_TRUE(EnvP); - auto prepareEnvVar = [this](decltype(*EnvP) Var) { + auto prepareEnvVar = [this](decltype(*EnvP) Var) -> StringRef { #if defined(_WIN32) // On Windows convert UTF16 encoded variable to UTF8 auto Len = wcslen(Var); @@ -86,10 +86,10 @@ protected: EnvStorage.emplace_back(); auto convStatus = convertUTF16ToUTF8String(Ref, EnvStorage.back()); EXPECT_TRUE(convStatus); - return EnvStorage.back().c_str(); + return EnvStorage.back(); #else (void)this; - return Var; + return StringRef(Var); #endif }; @@ -104,16 +104,9 @@ protected: 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 getEnviron() const { return EnvTable; } }; #ifdef _WIN32 @@ -129,11 +122,8 @@ TEST_F(ProgramEnvTest, CreateProcessLongPath) { MyExe.append("\\\\?\\"); 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. addEnvVar("LLVM_PROGRAM_TEST_LONG_PATH=1"); @@ -173,13 +163,13 @@ TEST_F(ProgramEnvTest, CreateProcessTrailingSlash) { std::string my_exe = 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. addEnvVar("LLVM_PROGRAM_TEST_CHILD=1"); @@ -210,11 +200,8 @@ TEST_F(ProgramEnvTest, TestExecuteNoWait) { std::string Executable = 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. addEnvVar("LLVM_PROGRAM_TEST_EXECUTE_NO_WAIT=1"); @@ -268,11 +255,8 @@ TEST_F(ProgramEnvTest, TestExecuteAndWaitTimeout) { std::string Executable = 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. addEnvVar("LLVM_PROGRAM_TEST_TIMEOUT=1"); @@ -287,12 +271,12 @@ TEST_F(ProgramEnvTest, TestExecuteAndWaitTimeout) { TEST(ProgramTest, TestExecuteNegative) { std::string Executable = "i_dont_exist"; - const char *argv[] = { Executable.c_str(), nullptr }; + StringRef argv[] = {Executable}; { std::string Error; bool ExecutionFailed; - int RetCode = ExecuteAndWait(Executable, argv, nullptr, {}, 0, 0, &Error, + int RetCode = ExecuteAndWait(Executable, argv, llvm::None, {}, 0, 0, &Error, &ExecutionFailed); ASSERT_TRUE(RetCode < 0) << "On error ExecuteAndWait should return 0 or " "positive value indicating the result code"; @@ -303,7 +287,7 @@ TEST(ProgramTest, TestExecuteNegative) { { std::string Error; bool ExecutionFailed; - ProcessInfo PI = ExecuteNoWait(Executable, argv, nullptr, {}, 0, &Error, + ProcessInfo PI = ExecuteNoWait(Executable, argv, llvm::None, {}, 0, &Error, &ExecutionFailed); ASSERT_EQ(PI.Pid, ProcessInfo::InvalidPid) << "On error ExecuteNoWait should return an invalid ProcessInfo"; diff --git a/utils/not/not.cpp b/utils/not/not.cpp index de71b4c6887..f48079d8875 100644 --- a/utils/not/not.cpp +++ b/utils/not/not.cpp @@ -38,8 +38,12 @@ int main(int argc, const char **argv) { return 1; } + std::vector Argv; + Argv.reserve(argc); + for (int i = 0; i < argc; ++i) + Argv.push_back(argv[i]); 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 // Handle abort() in msvcrt -- It has exit code as 3. abort(), aka // unreachable, should be recognized as a crash. However, some binaries use -- 2.11.0