diff options
-rw-r--r-- | clang/lib/Driver/Job.cpp | 14 | ||||
-rw-r--r-- | clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp | 4 | ||||
-rw-r--r-- | clang/tools/clang-offload-bundler/ClangOffloadBundler.cpp | 23 | ||||
-rw-r--r-- | lld/COFF/DriverUtils.cpp | 7 | ||||
-rw-r--r-- | lldb/unittests/ObjectFile/ELF/TestObjectFileELF.cpp | 5 | ||||
-rw-r--r-- | lldb/unittests/Symbol/TestDWARFCallFrameInfo.cpp | 5 | ||||
-rw-r--r-- | llvm/include/llvm/ADT/StringExtras.h | 10 | ||||
-rw-r--r-- | llvm/include/llvm/Support/Program.h | 15 | ||||
-rw-r--r-- | llvm/lib/Support/GraphWriter.cpp | 64 | ||||
-rw-r--r-- | llvm/lib/Support/Program.cpp | 16 | ||||
-rw-r--r-- | llvm/lib/Support/Signals.cpp | 17 | ||||
-rw-r--r-- | llvm/lib/Support/Unix/Program.inc | 35 | ||||
-rw-r--r-- | llvm/lib/Support/Windows/Program.inc | 21 | ||||
-rw-r--r-- | llvm/tools/bugpoint/OptimizerDriver.cpp | 15 | ||||
-rw-r--r-- | llvm/tools/bugpoint/ToolRunner.cpp | 174 | ||||
-rw-r--r-- | llvm/tools/dsymutil/MachOUtils.cpp | 15 | ||||
-rw-r--r-- | llvm/tools/llvm-cov/CodeCoverage.cpp | 11 | ||||
-rw-r--r-- | llvm/unittests/Support/Host.cpp | 4 | ||||
-rw-r--r-- | llvm/unittests/Support/ProgramTest.cpp | 60 | ||||
-rw-r--r-- | llvm/utils/not/not.cpp | 6 |
20 files changed, 254 insertions, 267 deletions
diff --git a/clang/lib/Driver/Job.cpp b/clang/lib/Driver/Job.cpp index 71cda621043..74af597ad36 100644 --- a/clang/lib/Driver/Job.cpp +++ b/clang/lib/Driver/Job.cpp @@ -317,13 +317,11 @@ int Command::Execute(ArrayRef<llvm::Optional<StringRef>> Redirects, std::string *ErrMsg, bool *ExecutionFailed) const { SmallVector<const char*, 128> Argv; - const char **Envp; - if (Environment.empty()) { - Envp = nullptr; - } else { + Optional<ArrayRef<StringRef>> Env; + if (!Environment.empty()) { assert(Environment.back() == nullptr && "Environment vector should be null-terminated by now"); - Envp = const_cast<const char **>(Environment.data()); + Env = llvm::toStringRefArray(Environment.data()); } if (ResponseFile == nullptr) { @@ -331,8 +329,9 @@ int Command::Execute(ArrayRef<llvm::Optional<StringRef>> Redirects, Argv.append(Arguments.begin(), Arguments.end()); Argv.push_back(nullptr); + auto Args = llvm::toStringRefArray(Argv.data()); return llvm::sys::ExecuteAndWait( - Executable, Argv.data(), Envp, Redirects, /*secondsToWait*/ 0, + Executable, Args, Env, Redirects, /*secondsToWait*/ 0, /*memoryLimit*/ 0, ErrMsg, ExecutionFailed); } @@ -357,7 +356,8 @@ int Command::Execute(ArrayRef<llvm::Optional<StringRef>> Redirects, return -1; } - return llvm::sys::ExecuteAndWait(Executable, Argv.data(), Envp, Redirects, + auto Args = llvm::toStringRefArray(Argv.data()); + return llvm::sys::ExecuteAndWait(Executable, Args, Env, Redirects, /*secondsToWait*/ 0, /*memoryLimit*/ 0, ErrMsg, ExecutionFailed); } diff --git a/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp b/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp index 9c5e04cc3c5..3d86945a55c 100644 --- a/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp +++ b/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp @@ -883,9 +883,9 @@ UbigraphViz::~UbigraphViz() { std::string Ubiviz; if (auto Path = llvm::sys::findProgramByName("ubiviz")) Ubiviz = *Path; - const char *args[] = {Ubiviz.c_str(), Filename.c_str(), nullptr}; + std::array<StringRef, 2> Args = {Ubiviz, Filename}; - if (llvm::sys::ExecuteAndWait(Ubiviz, &args[0], nullptr, {}, 0, 0, &ErrMsg)) { + if (llvm::sys::ExecuteAndWait(Ubiviz, Args, llvm::None, {}, 0, 0, &ErrMsg)) { llvm::errs() << "Error viewing graph: " << ErrMsg << "\n"; } diff --git a/clang/tools/clang-offload-bundler/ClangOffloadBundler.cpp b/clang/tools/clang-offload-bundler/ClangOffloadBundler.cpp index d9fb3898b51..29cd9848d11 100644 --- a/clang/tools/clang-offload-bundler/ClangOffloadBundler.cpp +++ b/clang/tools/clang-offload-bundler/ClangOffloadBundler.cpp @@ -536,23 +536,22 @@ public: // close it and use the name to pass down to clang. OS.close(); SmallString<128> TargetName = getTriple(TargetNames[HostInputIndex]); - const char *ClangArgs[] = {"clang", - "-r", - "-target", - TargetName.c_str(), - "-o", - OutputFileNames.front().c_str(), - InputFileNames[HostInputIndex].c_str(), - BitcodeFileName.c_str(), - "-nostdlib", - nullptr}; + std::vector<StringRef> ClangArgs = {"clang", + "-r", + "-target", + TargetName.c_str(), + "-o", + OutputFileNames.front().c_str(), + InputFileNames[HostInputIndex].c_str(), + BitcodeFileName.c_str(), + "-nostdlib"}; // If the user asked for the commands to be printed out, we do that instead // of executing it. if (PrintExternalCommands) { errs() << "\"" << ClangBinary.get() << "\""; - for (unsigned I = 1; ClangArgs[I]; ++I) - errs() << " \"" << ClangArgs[I] << "\""; + for (StringRef Arg : ClangArgs) + errs() << " \"" << Arg << "\""; errs() << "\n"; } else { // Write the bitcode contents to the temporary file. diff --git a/lld/COFF/DriverUtils.cpp b/lld/COFF/DriverUtils.cpp index 98751193f26..d534d858efe 100644 --- a/lld/COFF/DriverUtils.cpp +++ b/lld/COFF/DriverUtils.cpp @@ -61,12 +61,7 @@ public: StringRef Exe = Saver.save(*ExeOrErr); Args.insert(Args.begin(), Exe); - std::vector<const char *> Vec; - for (StringRef S : Args) - Vec.push_back(S.data()); - Vec.push_back(nullptr); - - if (sys::ExecuteAndWait(Args[0], Vec.data()) != 0) + if (sys::ExecuteAndWait(Args[0], Args) != 0) fatal("ExecuteAndWait failed: " + llvm::join(Args.begin(), Args.end(), " ")); } diff --git a/lldb/unittests/ObjectFile/ELF/TestObjectFileELF.cpp b/lldb/unittests/ObjectFile/ELF/TestObjectFileELF.cpp index bec46bb037e..9051ddfd01a 100644 --- a/lldb/unittests/ObjectFile/ELF/TestObjectFileELF.cpp +++ b/lldb/unittests/ObjectFile/ELF/TestObjectFileELF.cpp @@ -61,11 +61,12 @@ TEST_F(ObjectFileELFTest, SectionsResolveConsistently) { "sections-resolve-consistently-%%%%%%", "obj", obj)); llvm::FileRemover remover(obj); - const char *args[] = {YAML2OBJ, yaml.c_str(), nullptr}; + llvm::StringRef args[] = {YAML2OBJ, yaml}; llvm::StringRef obj_ref = obj; const llvm::Optional<llvm::StringRef> redirects[] = {llvm::None, obj_ref, llvm::None}; - ASSERT_EQ(0, llvm::sys::ExecuteAndWait(YAML2OBJ, args, nullptr, redirects)); + ASSERT_EQ(0, + llvm::sys::ExecuteAndWait(YAML2OBJ, args, llvm::None, redirects)); uint64_t size; ASSERT_NO_ERROR(llvm::sys::fs::file_size(obj, size)); ASSERT_GT(size, 0u); diff --git a/lldb/unittests/Symbol/TestDWARFCallFrameInfo.cpp b/lldb/unittests/Symbol/TestDWARFCallFrameInfo.cpp index 85cb4a72b95..c8d560f03de 100644 --- a/lldb/unittests/Symbol/TestDWARFCallFrameInfo.cpp +++ b/lldb/unittests/Symbol/TestDWARFCallFrameInfo.cpp @@ -96,11 +96,12 @@ void DWARFCallFrameInfoTest::TestBasic(DWARFCallFrameInfo::Type type, "basic-call-frame-info-%%%%%%", "obj", obj)); llvm::FileRemover obj_remover(obj); - const char *args[] = {YAML2OBJ, yaml.c_str(), nullptr}; + llvm::StringRef args[] = {YAML2OBJ, yaml}; llvm::StringRef obj_ref = obj; const llvm::Optional<llvm::StringRef> redirects[] = {llvm::None, obj_ref, llvm::None}; - ASSERT_EQ(0, llvm::sys::ExecuteAndWait(YAML2OBJ, args, nullptr, redirects)); + ASSERT_EQ(0, + llvm::sys::ExecuteAndWait(YAML2OBJ, args, llvm::None, redirects)); uint64_t size; ASSERT_NO_ERROR(llvm::sys::fs::file_size(obj, size)); diff --git a/llvm/include/llvm/ADT/StringExtras.h b/llvm/include/llvm/ADT/StringExtras.h index 21a1bbcfad2..12a685cec8a 100644 --- a/llvm/include/llvm/ADT/StringExtras.h +++ b/llvm/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<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. inline StringRef toStringRef(bool B) { return StringRef(B ? "true" : "false"); } diff --git a/llvm/include/llvm/Support/Program.h b/llvm/include/llvm/Support/Program.h index e64bfb2948a..1f4dbdce332 100644 --- a/llvm/include/llvm/Support/Program.h +++ b/llvm/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<StringRef> 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<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 = {}, ///< ///< 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<StringRef> Args, + Optional<ArrayRef<StringRef>> Env, ArrayRef<Optional<StringRef>> Redirects = {}, unsigned MemoryLimit = 0, std::string *ErrMsg = nullptr, diff --git a/llvm/lib/Support/GraphWriter.cpp b/llvm/lib/Support/GraphWriter.cpp index 794c6ba3a85..9335daffc3e 100644 --- a/llvm/lib/Support/GraphWriter.cpp +++ b/llvm/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<const char *> &args, +static bool ExecGraphViewer(StringRef ExecPath, std::vector<StringRef> &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<const char *> args; - args.push_back(ViewerPath.c_str()); + std::vector<StringRef> 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<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... "; 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<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... "; 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<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(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<const char *> args; - args.push_back(GeneratorPath.c_str()); + std::vector<StringRef> 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<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 #ifdef _WIN32 diff --git a/llvm/lib/Support/Program.cpp b/llvm/lib/Support/Program.cpp index 8c56fb6db2d..63cdcdaabee 100644 --- a/llvm/lib/Support/Program.cpp +++ b/llvm/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<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); -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, 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<StringRef> Args, + Optional<ArrayRef<StringRef>> Env, ArrayRef<Optional<StringRef>> 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/llvm/lib/Support/Signals.cpp b/llvm/lib/Support/Signals.cpp index 76a3c6bed41..6534ff69b84 100644 --- a/llvm/lib/Support/Signals.cpp +++ b/llvm/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 - // 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/llvm/lib/Support/Unix/Program.inc b/llvm/lib/Support/Unix/Program.inc index be971555b82..d0abc3763e8 100644 --- a/llvm/lib/Support/Unix/Program.inc +++ b/llvm/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 <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) { 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<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 // 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<char **>(Args), + /*attrp*/ nullptr, const_cast<char **>(Argv), const_cast<char **>(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<char **>(Args), + execve(PathStr.c_str(), const_cast<char **>(Argv), const_cast<char **>(Envp)); 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 // 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/llvm/lib/Support/Windows/Program.inc b/llvm/lib/Support/Windows/Program.inc index 19a38c78432..cb68c5b10e5 100644 --- a/llvm/lib/Support/Windows/Program.inc +++ b/llvm/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) { 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<wchar_t> 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<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()); MakeErrMsg(ErrMsg, "Unable to convert environment variable to UTF-16"); return false; diff --git a/llvm/tools/bugpoint/OptimizerDriver.cpp b/llvm/tools/bugpoint/OptimizerDriver.cpp index bdb6c5f1941..cbb048db8fe 100644 --- a/llvm/tools/bugpoint/OptimizerDriver.cpp +++ b/llvm/tools/bugpoint/OptimizerDriver.cpp @@ -194,20 +194,20 @@ bool BugDriver::runPasses(Module &Program, } // setup the child process' arguments - SmallVector<const char *, 8> Args; + SmallVector<StringRef, 8> 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<std::string> 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/llvm/tools/bugpoint/ToolRunner.cpp b/llvm/tools/bugpoint/ToolRunner.cpp index 2fb9f93ad7d..812e8e3bbae 100644 --- a/llvm/tools/bugpoint/ToolRunner.cpp +++ b/llvm/tools/bugpoint/ToolRunner.cpp @@ -53,13 +53,14 @@ cl::opt<std::string> /// 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<StringRef> Args, StringRef StdInFile, + StringRef StdOutFile, StringRef StdErrFile, + unsigned NumSeconds = 0, unsigned MemoryLimit = 0, std::string *ErrMsg = nullptr) { 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); } @@ -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<StringRef> Args, StringRef StdInFile, + StringRef StdOutFile, StringRef StdErrFile, unsigned NumSeconds = 0, + unsigned MemoryLimit = 0) { Optional<StringRef> 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<StringRef> 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<int> LLI::ExecuteProgram(const std::string &Bitcode, const std::vector<std::string> &CCArgs, const std::vector<std::string> &SharedLibs, unsigned Timeout, unsigned MemoryLimit) { - std::vector<const char *> LLIArgs; + std::vector<StringRef> LLIArgs; LLIArgs.push_back(LLIPath.c_str()); LLIArgs.push_back("-force-interpreter=true"); @@ -179,18 +178,17 @@ Expected<int> 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() << "<lli>"; 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() << " " << 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<const char *> ProgramArgs; + std::vector<StringRef> 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<int> CustomExecutor::ExecuteProgram( const std::vector<std::string> &SharedLibs, unsigned Timeout, 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) - 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<CC::FileType> LLC::OutputCode(const std::string &Bitcode, exit(1); } 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. 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 ? "<llc-ia>" : "<llc>"); 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<int> JIT::ExecuteProgram(const std::string &Bitcode, const std::vector<std::string> &SharedLibs, unsigned Timeout, unsigned MemoryLimit) { // 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("-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() << "<jit>"; outs().flush(); @@ -606,7 +597,7 @@ Expected<int> 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<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; @@ -651,9 +642,9 @@ Expected<int> CC::ExecuteProgram(const std::string &ProgramFile, const std::string &OutputFile, const std::vector<std::string> &ArgsForCC, 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) 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(), 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<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("none"); @@ -693,20 +684,19 @@ Expected<int> 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() << "<CC>"; 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() << " " << CCArgs[i]; 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 // 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<int> 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() << "<program>"; @@ -769,7 +758,7 @@ Expected<int> CC::ExecuteProgram(const std::string &ProgramFile, if (RemoteClientPath.empty()) { LLVM_DEBUG(errs() << "<run locally>"); 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<int> CC::ExecuteProgram(const std::string &ProgramFile, } else { outs() << "<run remotely>"; 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<const char *> CCArgs; + std::vector<StringRef> 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<std::string>::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() << "<CC>"; 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/llvm/tools/dsymutil/MachOUtils.cpp b/llvm/tools/dsymutil/MachOUtils.cpp index cd9fbe09cfc..c683b6a786f 100644 --- a/llvm/tools/dsymutil/MachOUtils.cpp +++ b/llvm/tools/dsymutil/MachOUtils.cpp @@ -33,7 +33,7 @@ std::string getArchName(StringRef 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)); if (!Path) Path = sys::findProgramByName("lipo"); @@ -44,8 +44,7 @@ static bool runLipo(StringRef SDKPath, SmallVectorImpl<const char *> &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<ArchAndFilename> &ArchFiles, return true; } - SmallVector<const char *, 8> Args; + SmallVector<StringRef, 8> 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/llvm/tools/llvm-cov/CodeCoverage.cpp b/llvm/tools/llvm-cov/CodeCoverage.cpp index e40cc5c386e..e93b63d388e 100644 --- a/llvm/tools/llvm-cov/CodeCoverage.cpp +++ b/llvm/tools/llvm-cov/CodeCoverage.cpp @@ -478,14 +478,13 @@ void CodeCoverageTool::demangleSymbols(const CoverageMapping &Coverage) { OutputTOF.os().close(); // 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(), {""}}; 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/llvm/unittests/Support/Host.cpp b/llvm/unittests/Support/Host.cpp index 736b04c2049..e07d4151bb6 100644 --- a/llvm/unittests/Support/Host.cpp +++ b/llvm/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<StringRef> 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/llvm/unittests/Support/ProgramTest.cpp b/llvm/unittests/Support/ProgramTest.cpp index 7a0676c7a48..ec1c85a9f25 100644 --- a/llvm/unittests/Support/ProgramTest.cpp +++ b/llvm/unittests/Support/ProgramTest.cpp @@ -60,7 +60,7 @@ static cl::opt<std::string> ProgramTestStringArg2("program-test-string-arg2"); class ProgramEnvTest : public testing::Test { - std::vector<const char *> EnvTable; + std::vector<StringRef> EnvTable; std::vector<std::string> 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<StringRef> 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/llvm/utils/not/not.cpp b/llvm/utils/not/not.cpp index de71b4c6887..f48079d8875 100644 --- a/llvm/utils/not/not.cpp +++ b/llvm/utils/not/not.cpp @@ -38,8 +38,12 @@ int main(int argc, const char **argv) { return 1; } + std::vector<StringRef> 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 |