Index: clang-tools-extra/modularize/Modularize.cpp =================================================================== --- clang-tools-extra/modularize/Modularize.cpp +++ clang-tools-extra/modularize/Modularize.cpp @@ -340,11 +340,9 @@ std::unique_ptr Opts(createDriverOptTable()); const unsigned IncludedFlagsBitmask = options::CC1Option; unsigned MissingArgIndex, MissingArgCount; - SmallVector Argv; - for (CommandLineArguments::const_iterator I = CLArgs.begin(), - E = CLArgs.end(); - I != E; ++I) - Argv.push_back(I->c_str()); + SmallVector Argv; + for (const auto &Str : CLArgs) + Argv.push_back(Str); InputArgList Args = Opts->ParseArgs(Argv, MissingArgIndex, MissingArgCount, IncludedFlagsBitmask); std::vector Inputs = Args.getAllArgValues(OPT_INPUT); Index: clang/include/clang/Basic/Builtins.h =================================================================== --- clang/include/clang/Basic/Builtins.h +++ clang/include/clang/Basic/Builtins.h @@ -207,7 +207,7 @@ /// Returns true if this is a libc/libm function without the '__builtin_' /// prefix. - static bool isBuiltinFunc(const char *Name); + static bool isBuiltinFunc(llvm::StringRef Name); private: const Info &getRecord(unsigned ID) const; Index: clang/include/clang/Driver/Compilation.h =================================================================== --- clang/include/clang/Driver/Compilation.h +++ clang/include/clang/Driver/Compilation.h @@ -189,21 +189,21 @@ /// addTempFile - Add a file to remove on exit, and returns its /// argument. - const char *addTempFile(const char *Name) { + StringRef addTempFile(StringRef Name) { TempFiles.push_back(Name); return Name; } /// addResultFile - Add a file to remove on failure, and returns its /// argument. - const char *addResultFile(const char *Name, const JobAction *JA) { + StringRef addResultFile(StringRef Name, const JobAction *JA) { ResultFiles[JA] = Name; return Name; } /// addFailureResultFile - Add a file to remove if we crash, and returns its /// argument. - const char *addFailureResultFile(const char *Name, const JobAction *JA) { + StringRef addFailureResultFile(StringRef Name, const JobAction *JA) { FailureResultFiles[JA] = Name; return Name; } @@ -212,7 +212,7 @@ /// /// \param IssueErrors - Report failures as errors. /// \return Whether the file was removed successfully. - bool CleanupFile(const char *File, bool IssueErrors = false) const; + bool CleanupFile(StringRef File, bool IssueErrors = false) const; /// CleanupFileList - Remove the files in the given list. /// Index: clang/include/clang/Driver/Driver.h =================================================================== --- clang/include/clang/Driver/Driver.h +++ clang/include/clang/Driver/Driver.h @@ -288,17 +288,17 @@ /// argument vector. A null return value does not necessarily /// indicate an error condition, the diagnostics should be queried /// to determine if an error occurred. - Compilation *BuildCompilation(ArrayRef Args); + Compilation *BuildCompilation(ArrayRef Args); /// @name Driver Steps /// @{ /// ParseDriverMode - Look for and handle the driver mode option in Args. - void ParseDriverMode(StringRef ProgramName, ArrayRef Args); + void ParseDriverMode(StringRef ProgramName, ArrayRef Args); /// ParseArgStrings - Parse the given list of strings into an /// ArgList. - llvm::opt::InputArgList ParseArgStrings(ArrayRef Args); + llvm::opt::InputArgList ParseArgStrings(ArrayRef Args); /// BuildInputs - Construct the list of inputs and their types from /// the given arguments. @@ -418,10 +418,10 @@ /// \param AtTopLevel - Whether this is a "top-level" action. /// \param MultipleArchs - Whether multiple -arch options were supplied. /// \param NormalizedTriple - The normalized triple of the relevant target. - const char *GetNamedOutputPath(Compilation &C, const JobAction &JA, - const char *BaseInput, StringRef BoundArch, - bool AtTopLevel, bool MultipleArchs, - StringRef NormalizedTriple) const; + StringRef GetNamedOutputPath(Compilation &C, const JobAction &JA, + StringRef BaseInput, StringRef BoundArch, + bool AtTopLevel, bool MultipleArchs, + StringRef NormalizedTriple) const; /// GetTemporaryPath - Return the pathname of a temporary file to use /// as part of compilation; the file will have the given prefix and suffix. Index: clang/include/clang/Driver/Job.h =================================================================== --- clang/include/clang/Driver/Job.h +++ clang/include/clang/Driver/Job.h @@ -48,7 +48,7 @@ const Tool &Creator; /// The executable to run. - const char *Executable; + StringRef Executable; /// The list of program arguments (not including the implicit first /// argument, which will be the executable). @@ -73,7 +73,7 @@ /// exclusive file, while others remains as regular command line arguments. /// This functions fills a vector with the regular command line arguments, /// argv, excluding the ones passed in a response file. - void buildArgvForResponseFile(llvm::SmallVectorImpl &Out) const; + void buildArgvForResponseFile(llvm::SmallVectorImpl &Out) const; /// Encodes an array of C strings into a single string separated by whitespace. /// This function will also put in quotes arguments that have whitespaces and @@ -82,7 +82,7 @@ void writeResponseFile(raw_ostream &OS) const; public: - Command(const Action &Source, const Tool &Creator, const char *Executable, + Command(const Action &Source, const Tool &Creator, StringRef Executable, const llvm::opt::ArgStringList &Arguments, ArrayRef Inputs); // FIXME: This really shouldn't be copyable, but is currently copied in some @@ -111,7 +111,7 @@ InputFileList = std::move(List); } - const char *getExecutable() const { return Executable; } + StringRef getExecutable() const { return Executable; } const llvm::opt::ArgStringList &getArguments() const { return Arguments; } @@ -124,7 +124,7 @@ class FallbackCommand : public Command { public: FallbackCommand(const Action &Source_, const Tool &Creator_, - const char *Executable_, const ArgStringList &Arguments_, + StringRef Executable_, const ArgStringList &Arguments_, ArrayRef Inputs, std::unique_ptr Fallback_); Index: clang/include/clang/Driver/ToolChain.h =================================================================== --- clang/include/clang/Driver/ToolChain.h +++ clang/include/clang/Driver/ToolChain.h @@ -208,7 +208,7 @@ // Helper methods std::string GetFilePath(const char *Name) const; - std::string GetProgramPath(const char *Name) const; + std::string GetProgramPath(StringRef Name) const; /// Returns the linker path, respecting the -fuse-ld= argument to determine /// the linker suffix or name. @@ -279,9 +279,9 @@ StringRef Component, bool Shared = false) const; - const char *getCompilerRTArgString(const llvm::opt::ArgList &Args, - StringRef Component, - bool Shared = false) const; + StringRef getCompilerRTArgString(const llvm::opt::ArgList &Args, + StringRef Component, + bool Shared = false) const; /// needsProfileRT - returns true if instrumentation profile is on. static bool needsProfileRT(const llvm::opt::ArgList &Args); Index: clang/include/clang/Driver/Types.h =================================================================== --- clang/include/clang/Driver/Types.h +++ clang/include/clang/Driver/Types.h @@ -86,7 +86,7 @@ /// lookupTypeForTypSpecifier - Lookup the type to use for a user /// specified type name. - ID lookupTypeForTypeSpecifier(const char *Name); + ID lookupTypeForTypeSpecifier(llvm::StringRef Name); /// getCompilationPhases - Get the list of compilation phases ('Phases') to be /// done for type 'Id'. Index: clang/include/clang/Driver/Util.h =================================================================== --- clang/include/clang/Driver/Util.h +++ clang/include/clang/Driver/Util.h @@ -21,7 +21,7 @@ class JobAction; /// ArgStringMap - Type used to map a JobAction to its result file. - typedef llvm::DenseMap ArgStringMap; + typedef llvm::DenseMap ArgStringMap; /// ActionList - Type used for lists of actions. typedef SmallVector ActionList; Index: clang/include/clang/Frontend/CompilerInvocation.h =================================================================== --- clang/include/clang/Frontend/CompilerInvocation.h +++ clang/include/clang/Frontend/CompilerInvocation.h @@ -139,6 +139,16 @@ const char* const *ArgEnd, DiagnosticsEngine &Diags); + /// \brief Create a compiler invocation from a list of input options. + /// \returns true on success. + /// + /// \param [out] Res - The resulting invocation. + /// \param ArgBegin - The first element in the argument vector. + /// \param ArgEnd - The last element in the argument vector. + /// \param Diags - The diagnostic engine to use for errors. + static bool CreateFromArgs(CompilerInvocation &Res, const StringRef *ArgBegin, + const StringRef *ArgEnd, DiagnosticsEngine &Diags); + /// \brief Get the directory where the compiler headers /// reside, relative to the compiler binary (found by the passed in /// arguments). @@ -147,7 +157,7 @@ /// compiler path. /// \param MainAddr - The address of main (or some other function in the main /// executable), for finding the builtin compiler path. - static std::string GetResourcesPath(const char *Argv0, void *MainAddr); + static std::string GetResourcesPath(StringRef Argv0, void *MainAddr); /// \brief Set language defaults for the given input language and /// language standard in the given LangOptions object. Index: clang/include/clang/Tooling/Tooling.h =================================================================== --- clang/include/clang/Tooling/Tooling.h +++ clang/include/clang/Tooling/Tooling.h @@ -259,7 +259,7 @@ private: void addFileMappingsTo(SourceManager &SourceManager); - bool runInvocation(const char *BinaryName, + bool runInvocation(StringRef BinaryName, clang::driver::Compilation *Compilation, clang::CompilerInvocation *Invocation, std::shared_ptr PCHContainerOps); Index: clang/lib/Basic/Builtins.cpp =================================================================== --- clang/lib/Basic/Builtins.cpp +++ clang/lib/Basic/Builtins.cpp @@ -48,8 +48,7 @@ AuxTSRecords = AuxTarget->getTargetBuiltins(); } -bool Builtin::Context::isBuiltinFunc(const char *Name) { - StringRef FuncName(Name); +bool Builtin::Context::isBuiltinFunc(llvm::StringRef FuncName) { for (unsigned i = Builtin::NotBuiltin + 1; i != Builtin::FirstTSBuiltin; ++i) if (FuncName.equals(BuiltinInfo[i].Name)) return strchr(BuiltinInfo[i].Attributes, 'f') != nullptr; Index: clang/lib/Driver/Compilation.cpp =================================================================== --- clang/lib/Driver/Compilation.cpp +++ clang/lib/Driver/Compilation.cpp @@ -65,7 +65,7 @@ return *Entry; } -bool Compilation::CleanupFile(const char *File, bool IssueErrors) const { +bool Compilation::CleanupFile(StringRef File, bool IssueErrors) const { // FIXME: Why are we trying to remove files that we have not created? For // example we should only try to remove a temporary assembly file if // "clang -cc1" succeed in writing it. Was this a workaround for when @@ -98,9 +98,8 @@ bool Compilation::CleanupFileList(const ArgStringList &Files, bool IssueErrors) const { bool Success = true; - for (ArgStringList::const_iterator - it = Files.begin(), ie = Files.end(); it != ie; ++it) - Success &= CleanupFile(*it, IssueErrors); + for (auto File : Files) + Success &= CleanupFile(File, IssueErrors); return Success; } @@ -108,14 +107,12 @@ const JobAction *JA, bool IssueErrors) const { bool Success = true; - for (ArgStringMap::const_iterator - it = Files.begin(), ie = Files.end(); it != ie; ++it) { - + for (auto &Arg : Files) { // If specified, only delete the files associated with the JobAction. // Otherwise, delete all files in the map. - if (JA && it->first != JA) + if (JA && Arg.first != JA) continue; - Success &= CleanupFile(it->second, IssueErrors); + Success &= CleanupFile(Arg.second, IssueErrors); } return Success; } Index: clang/lib/Driver/Driver.cpp =================================================================== --- clang/lib/Driver/Driver.cpp +++ clang/lib/Driver/Driver.cpp @@ -88,17 +88,15 @@ llvm::DeleteContainerSeconds(ToolChains); } -void Driver::ParseDriverMode(StringRef ProgramName, - ArrayRef Args) { +void Driver::ParseDriverMode(StringRef ProgramName, ArrayRef Args) { auto Default = ToolChain::getTargetAndModeFromProgramName(ProgramName); StringRef DefaultMode(Default.second); setDriverModeFromOption(DefaultMode); - for (const char *ArgPtr : Args) { + for (StringRef Arg : Args) { // Ingore nullptrs, they are response file's EOL markers - if (ArgPtr == nullptr) + if (Arg.empty()) continue; - const StringRef Arg = ArgPtr; setDriverModeFromOption(Arg); } } @@ -123,7 +121,7 @@ Diag(diag::err_drv_unsupported_option_argument) << OptName << Value; } -InputArgList Driver::ParseArgStrings(ArrayRef ArgStrings) { +InputArgList Driver::ParseArgStrings(ArrayRef ArgStrings) { llvm::PrettyStackTraceString CrashInfo("Command line argument parsing"); unsigned IncludedFlagsBitmask; @@ -214,7 +212,7 @@ static Arg *MakeInputArg(DerivedArgList &Args, OptTable *Opts, StringRef Value) { Arg *A = new Arg(Opts->getOption(options::OPT_INPUT), Value, - Args.getBaseArgs().MakeIndex(Value), Value.data()); + Args.getBaseArgs().MakeIndex(Value), Value); Args.AddSynthesizedArg(A); A->claim(); return A; @@ -461,7 +459,7 @@ return; } -Compilation *Driver::BuildCompilation(ArrayRef ArgList) { +Compilation *Driver::BuildCompilation(ArrayRef ArgList) { llvm::PrettyStackTraceString CrashInfo("Compilation construction"); // FIXME: Handle environment options which affect driver behavior, somewhere @@ -667,7 +665,7 @@ // Check type first as not all linker inputs have a value. if (types::getPreprocessedType(it->first) == types::TY_INVALID) { IgnoreInput = true; - } else if (!strcmp(it->second->getValue(), "-")) { + } else if (it->second->getValue() == "-") { Diag(clang::diag::note_drv_command_failed_diag_msg) << "Error generating preprocessed source(s) - " "ignoring input from stdin."; @@ -749,9 +747,9 @@ "Preprocessed source(s) and associated run script(s) are located at:"; SmallString<128> VFS; - for (const char *TempFile : TempFiles) { + for (StringRef TempFile : TempFiles) { Diag(clang::diag::note_drv_command_failed_diag_msg) << TempFile; - if (StringRef(TempFile).endswith(".cache")) { + if (TempFile.endswith(".cache")) { // In some cases (modules) we'll dump extra data to help with reproducing // the crash into a directory next to the output. VFS = llvm::sys::path::filename(TempFile); @@ -795,8 +793,7 @@ return; std::string TmpName = GetTemporaryPath("response", "txt"); - Cmd.setResponseFile( - C.addTempFile(C.getArgs().MakeArgString(TmpName.c_str()))); + Cmd.setResponseFile(C.addTempFile(C.getArgs().MakeArgString(TmpName))); } int Driver::ExecuteCompilation( @@ -1127,7 +1124,7 @@ // Collect the list of architectures. Duplicates are allowed, but should only // be handled once (in the order seen). llvm::StringSet<> ArchNames; - SmallVector Archs; + SmallVector Archs; for (Arg *A : Args) { if (A->getOption().matches(options::OPT_arch)) { // Validate the option here; we don't save the type here because its @@ -1283,7 +1280,7 @@ for (Arg *A : Args) { if (A->getOption().getKind() == Option::InputClass) { - const char *Value = A->getValue(); + StringRef Value = A->getValue(); types::ID Ty = types::TY_INVALID; // Infer the input type if necessary. @@ -1293,7 +1290,7 @@ InputTypeArg->claim(); // stdin must be handled specially. - if (memcmp(Value, "-", 2) == 0) { + if (Value == "-") { // If running with -E, treat as a C input (this changes the builtin // macros, for example). This may be overridden by -ObjC below. // @@ -1308,8 +1305,9 @@ // Fallback is C if invoked as C preprocessor or Object otherwise. // We use a host hook here because Darwin at least has its own // idea of what .s is. - if (const char *Ext = strrchr(Value, '.')) - Ty = TC.LookupTypeForExtension(Ext + 1); + auto ExtIdx = Value.rfind('.'); + if (ExtIdx != StringRef::npos) + Ty = TC.LookupTypeForExtension(Value.drop_front(ExtIdx + 1)); if (Ty == types::TY_INVALID) { if (CCCIsCPP()) @@ -1346,9 +1344,12 @@ if (!InputTypeArg->getOption().matches(options::OPT_x)) { // If emulating cl.exe, make sure that /TC and /TP don't affect input // object files. - const char *Ext = strrchr(Value, '.'); - if (Ext && TC.LookupTypeForExtension(Ext + 1) == types::TY_Object) - Ty = types::TY_Object; + auto ExtIdx = Value.find('.'); + if (ExtIdx != StringRef::npos) { + StringRef Ext = Value.drop_front(ExtIdx + 1); + if (TC.LookupTypeForExtension(Ext) == types::TY_Object) + Ty = types::TY_Object; + } } if (Ty == types::TY_INVALID) { Ty = InputType; @@ -2001,7 +2002,7 @@ Args.eraseArg(options::OPT__SLASH_Yu); YuArg = nullptr; } - if (YcArg && YuArg && strcmp(YcArg->getValue(), YuArg->getValue()) != 0) { + if (YcArg && YuArg && YcArg->getValue() != YuArg->getValue()) { Diag(clang::diag::warn_drv_ycyu_different_arg_clang_cl); Args.eraseArg(options::OPT__SLASH_Yc); Args.eraseArg(options::OPT__SLASH_Yu); @@ -2298,7 +2299,7 @@ // // FIXME: This is a hack; find a cleaner way to integrate this into the // process. - const char *LinkingOutput = nullptr; + StringRef LinkingOutput; if (isa(A)) { if (FinalOutput) LinkingOutput = FinalOutput->getValue(); @@ -2593,7 +2594,7 @@ const Arg &Input = IA->getInputArg(); Input.claim(); if (Input.getOption().matches(options::OPT_INPUT)) { - const char *Name = Input.getValue(); + StringRef Name = Input.getValue(); return InputInfo(A, Name, /* BaseInput = */ Name); } return InputInfo(A, &Input, /* BaseInput = */ ""); @@ -2654,7 +2655,7 @@ } // Always use the first input as the base input. - const char *BaseInput = InputInfos[0].getBaseInput(); + StringRef BaseInput = InputInfos[0].getBaseInput(); // ... except dsymutil actions, which use their actual input as the base // input. @@ -2714,9 +2715,8 @@ /// full filename, filename without extension, or a directory. If ArgValue /// does not provide a filename, then use BaseName, and use the extension /// suitable for FileType. -static const char *MakeCLOutputFilename(const ArgList &Args, StringRef ArgValue, - StringRef BaseName, - types::ID FileType) { +static StringRef MakeCLOutputFilename(const ArgList &Args, StringRef ArgValue, + StringRef BaseName, types::ID FileType) { SmallString<128> Filename = ArgValue; if (ArgValue.empty()) { @@ -2743,11 +2743,10 @@ return Args.MakeArgString(Filename.c_str()); } -const char *Driver::GetNamedOutputPath(Compilation &C, const JobAction &JA, - const char *BaseInput, - StringRef BoundArch, bool AtTopLevel, - bool MultipleArchs, - StringRef NormalizedTriple) const { +StringRef Driver::GetNamedOutputPath(Compilation &C, const JobAction &JA, + StringRef BaseInput, StringRef BoundArch, + bool AtTopLevel, bool MultipleArchs, + StringRef NormalizedTriple) const { llvm::PrettyStackTraceString CrashInfo("Computing output path"); // Output to a user requested destination? if (AtTopLevel && !isa(JA) && !isa(JA)) { @@ -2805,7 +2804,7 @@ BaseName = llvm::sys::path::filename(BasePath); // Determine what the derived output name should be. - const char *NamedOutput; + StringRef NamedOutput; if ((JA.getType() == types::TY_Object || JA.getType() == types::TY_LTO_BC) && C.getArgs().hasArg(options::OPT__SLASH_Fo, options::OPT__SLASH_o)) { Index: clang/lib/Driver/InputInfo.h =================================================================== --- clang/lib/Driver/InputInfo.h +++ clang/lib/Driver/InputInfo.h @@ -35,39 +35,39 @@ }; union { - const char *Filename; + StringRef Filename = StringRef(); const llvm::opt::Arg *InputArg; } Data; Class Kind; const Action* Act; types::ID Type; - const char *BaseInput; + StringRef BaseInput; static types::ID GetActionType(const Action *A) { return A != nullptr ? A->getType() : types::TY_Nothing; } public: - InputInfo() : InputInfo(nullptr, nullptr) {} - InputInfo(const Action *A, const char *_BaseInput) + InputInfo() : InputInfo(nullptr, StringRef()) {} + InputInfo(const Action *A, StringRef _BaseInput) : Kind(Nothing), Act(A), Type(GetActionType(A)), BaseInput(_BaseInput) {} - InputInfo(types::ID _Type, const char *_Filename, const char *_BaseInput) + InputInfo(types::ID _Type, StringRef FName, StringRef _BaseInput) : Kind(Filename), Act(nullptr), Type(_Type), BaseInput(_BaseInput) { - Data.Filename = _Filename; + Data.Filename = FName; } - InputInfo(const Action *A, const char *_Filename, const char *_BaseInput) + InputInfo(const Action *A, StringRef FName, StringRef _BaseInput) : Kind(Filename), Act(A), Type(GetActionType(A)), BaseInput(_BaseInput) { - Data.Filename = _Filename; + Data.Filename = FName; } InputInfo(types::ID _Type, const llvm::opt::Arg *_InputArg, - const char *_BaseInput) + StringRef _BaseInput) : Kind(InputArg), Act(nullptr), Type(_Type), BaseInput(_BaseInput) { Data.InputArg = _InputArg; } InputInfo(const Action *A, const llvm::opt::Arg *_InputArg, - const char *_BaseInput) + StringRef _BaseInput) : Kind(InputArg), Act(A), Type(GetActionType(A)), BaseInput(_BaseInput) { Data.InputArg = _InputArg; } @@ -76,12 +76,12 @@ bool isFilename() const { return Kind == Filename; } bool isInputArg() const { return Kind == InputArg; } types::ID getType() const { return Type; } - const char *getBaseInput() const { return BaseInput; } + StringRef getBaseInput() const { return BaseInput; } /// The action for which this InputInfo was created. May be null. const Action *getAction() const { return Act; } void setAction(const Action *A) { Act = A; } - const char *getFilename() const { + StringRef getFilename() const { assert(isFilename() && "Invalid accessor."); return Data.Filename; } @@ -94,7 +94,7 @@ /// debugging. std::string getAsString() const { if (isFilename()) - return std::string("\"") + getFilename() + '"'; + return std::string("\"") + getFilename().str() + '"'; else if (isInputArg()) return "(input arg)"; else Index: clang/lib/Driver/Job.cpp =================================================================== --- clang/lib/Driver/Job.cpp +++ clang/lib/Driver/Job.cpp @@ -29,7 +29,7 @@ using llvm::ArrayRef; Command::Command(const Action &Source, const Tool &Creator, - const char *Executable, const ArgStringList &Arguments, + StringRef Executable, const ArgStringList &Arguments, ArrayRef Inputs) : Source(Source), Creator(Creator), Executable(Executable), Arguments(Arguments) { @@ -38,7 +38,7 @@ InputFilenames.push_back(II.getFilename()); } -static int skipArgs(const char *Flag, bool HaveCrashVFS) { +static int skipArgs(StringRef Flag, bool HaveCrashVFS) { // These flags are all of the form -Flag and are treated as two // arguments. Therefore, we need to skip the flag and the next argument. bool Res = llvm::StringSwitch(Flag) @@ -71,10 +71,9 @@ return 1; // These flags are treated as a single argument (e.g., -F). - StringRef FlagRef(Flag); if ((!HaveCrashVFS && - (FlagRef.startswith("-F") || FlagRef.startswith("-I"))) || - FlagRef.startswith("-fmodules-cache-path=")) + (Flag.startswith("-F") || Flag.startswith("-I"))) || + Flag.startswith("-fmodules-cache-path=")) return 1; return 0; @@ -101,7 +100,7 @@ void Command::writeResponseFile(raw_ostream &OS) const { // In a file list, we only write the set of inputs to the response file if (Creator.getResponseFilesSupport() == Tool::RF_FileList) { - for (const char *Arg : InputFileList) { + for (auto Arg : InputFileList) { OS << Arg << '\n'; } return; @@ -110,14 +109,13 @@ // In regular response files, we send all arguments to the response file. // Wrapping all arguments in double quotes ensures that both Unix tools and // Windows tools understand the response file. - for (const char *Arg : Arguments) { + for (auto ArgStr : Arguments) { OS << '"'; - - for (; *Arg != '\0'; Arg++) { - if (*Arg == '\"' || *Arg == '\\') { + for (auto C : ArgStr) { + if (C == '\"' || C == '\\') { OS << '\\'; } - OS << *Arg; + OS << C; } OS << "\" "; @@ -125,30 +123,30 @@ } void Command::buildArgvForResponseFile( - llvm::SmallVectorImpl &Out) const { + llvm::SmallVectorImpl &Out) const { // When not a file list, all arguments are sent to the response file. // This leaves us to set the argv to a single parameter, requesting the tool // to read the response file. if (Creator.getResponseFilesSupport() != Tool::RF_FileList) { Out.push_back(Executable); - Out.push_back(ResponseFileFlag.c_str()); + Out.push_back(ResponseFileFlag); return; } llvm::StringSet<> Inputs; - for (const char *InputName : InputFileList) + for (auto InputName : InputFileList) Inputs.insert(InputName); Out.push_back(Executable); // In a file list, build args vector ignoring parameters that will go in the // response file (elements of the InputFileList vector) bool FirstInput = true; - for (const char *Arg : Arguments) { + for (auto Arg : Arguments) { if (Inputs.count(Arg) == 0) { Out.push_back(Arg); } else if (FirstInput) { FirstInput = false; Out.push_back(Creator.getResponseFileFlag()); - Out.push_back(ResponseFile.data()); + Out.push_back(ResponseFile); } } } @@ -159,16 +157,16 @@ OS << ' '; printArg(OS, Executable, /*Quote=*/true); - llvm::ArrayRef Args = Arguments; - llvm::SmallVector ArgsRespFile; + llvm::ArrayRef Args = Arguments; + llvm::SmallVector ArgsRespFile; if (!ResponseFile.empty()) { buildArgvForResponseFile(ArgsRespFile); - Args = ArrayRef(ArgsRespFile).slice(1); // no executable name + Args = ArrayRef(ArgsRespFile).slice(1); // no executable name } bool HaveCrashVFS = CrashInfo && !CrashInfo->VFSPath.empty(); for (size_t i = 0, e = Args.size(); i < e; ++i) { - const char *const Arg = Args[i]; + StringRef Arg = Args[i]; if (CrashInfo) { if (int Skip = skipArgs(Arg, HaveCrashVFS)) { @@ -231,11 +229,19 @@ int Command::Execute(const StringRef **Redirects, std::string *ErrMsg, bool *ExecutionFailed) const { + SmallVector Argv; if (ResponseFile.empty()) { - Argv.push_back(Executable); - Argv.append(Arguments.begin(), Arguments.end()); + // Go through std::string to ensure null termination + SmallVector ArgvStr; + ArgvStr.push_back(Executable); + for (auto &Arg : Arguments) + ArgvStr.push_back(Arg); + + Argv.reserve(ArgvStr.size()); + for (auto &Str : ArgvStr) + Argv.push_back(Str.c_str()); Argv.push_back(nullptr); return llvm::sys::ExecuteAndWait(Executable, Argv.data(), /*env*/ nullptr, @@ -251,10 +257,19 @@ // Write file contents and build the Argv vector writeResponseFile(SS); - buildArgvForResponseFile(Argv); - Argv.push_back(nullptr); + SmallVector ArgvStrRef; + buildArgvForResponseFile(ArgvStrRef); SS.flush(); + // Go through std::string to ensure null termination + SmallVector ArgvStr; + for (auto &Arg : ArgvStrRef) + ArgvStr.push_back(Arg); + Argv.reserve(ArgvStr.size()); + for (auto &Str : ArgvStr) + Argv.push_back(Str.c_str()); + Argv.push_back(nullptr); + // Save the response file in the appropriate encoding if (std::error_code EC = writeFileWithEncoding( ResponseFile, RespContents, Creator.getResponseFileEncoding())) { @@ -271,7 +286,7 @@ } FallbackCommand::FallbackCommand(const Action &Source_, const Tool &Creator_, - const char *Executable_, + StringRef Executable_, const ArgStringList &Arguments_, ArrayRef Inputs, std::unique_ptr Fallback_) Index: clang/lib/Driver/SanitizerArgs.cpp =================================================================== --- clang/lib/Driver/SanitizerArgs.cpp +++ clang/lib/Driver/SanitizerArgs.cpp @@ -729,15 +729,14 @@ "Invalid argument in parseArgValues!"); SanitizerMask Kinds = 0; for (int i = 0, n = A->getNumValues(); i != n; ++i) { - const char *Value = A->getValue(i); + StringRef Value = A->getValue(i); SanitizerMask Kind; // Special case: don't accept -fsanitize=all. - if (A->getOption().matches(options::OPT_fsanitize_EQ) && - 0 == strcmp("all", Value)) + if (A->getOption().matches(options::OPT_fsanitize_EQ) && Value == "all") Kind = 0; // Similarly, don't accept -fsanitize=efficiency-all. else if (A->getOption().matches(options::OPT_fsanitize_EQ) && - 0 == strcmp("efficiency-all", Value)) + Value == "efficiency-all") Kind = 0; else Kind = parseSanitizerValue(Value, /*AllowGroups=*/true); @@ -756,7 +755,7 @@ A->getOption().matches(options::OPT_fno_sanitize_coverage)); int Features = 0; for (int i = 0, n = A->getNumValues(); i != n; ++i) { - const char *Value = A->getValue(i); + StringRef Value = A->getValue(i); int F = llvm::StringSwitch(Value) .Case("func", CoverageFunc) .Case("bb", CoverageBB) Index: clang/lib/Driver/ToolChain.cpp =================================================================== --- clang/lib/Driver/ToolChain.cpp +++ clang/lib/Driver/ToolChain.cpp @@ -304,9 +304,9 @@ return Path.str(); } -const char *ToolChain::getCompilerRTArgString(const llvm::opt::ArgList &Args, - StringRef Component, - bool Shared) const { +StringRef ToolChain::getCompilerRTArgString(const llvm::opt::ArgList &Args, + StringRef Component, + bool Shared) const { return Args.MakeArgString(getCompilerRT(Args, Component, Shared)); } @@ -336,7 +336,7 @@ return D.GetFilePath(Name, *this); } -std::string ToolChain::GetProgramPath(const char *Name) const { +std::string ToolChain::GetProgramPath(StringRef Name) const { return D.GetProgramPath(Name, *this); } Index: clang/lib/Driver/ToolChains.cpp =================================================================== --- clang/lib/Driver/ToolChains.cpp +++ clang/lib/Driver/ToolChains.cpp @@ -677,28 +677,28 @@ if (Platform == MacOS) { assert((!iOSVersion && !TvOSVersion && !WatchOSVersion) && "Unknown target platform!"); - if (!Driver::GetReleaseVersion(OSXVersion->getValue(), Major, Minor, Micro, - HadExtra) || + if (!Driver::GetReleaseVersion(OSXVersion->getValue(), Major, Minor, + Micro, HadExtra) || HadExtra || Major != 10 || Minor >= 100 || Micro >= 100) getDriver().Diag(diag::err_drv_invalid_version_number) << OSXVersion->getAsString(Args); } else if (Platform == IPhoneOS) { assert(iOSVersion && "Unknown target platform!"); - if (!Driver::GetReleaseVersion(iOSVersion->getValue(), Major, Minor, Micro, - HadExtra) || + if (!Driver::GetReleaseVersion(iOSVersion->getValue(), Major, Minor, + Micro, HadExtra) || HadExtra || Major >= 100 || Minor >= 100 || Micro >= 100) getDriver().Diag(diag::err_drv_invalid_version_number) << iOSVersion->getAsString(Args); } else if (Platform == TvOS) { if (!Driver::GetReleaseVersion(TvOSVersion->getValue(), Major, Minor, - Micro, HadExtra) || HadExtra || - Major >= 100 || Minor >= 100 || Micro >= 100) + Micro, HadExtra) || + HadExtra || Major >= 100 || Minor >= 100 || Micro >= 100) getDriver().Diag(diag::err_drv_invalid_version_number) << TvOSVersion->getAsString(Args); } else if (Platform == WatchOS) { - if (!Driver::GetReleaseVersion(WatchOSVersion->getValue(), Major, Minor, - Micro, HadExtra) || HadExtra || - Major >= 10 || Minor >= 100 || Micro >= 100) + if (!Driver::GetReleaseVersion(WatchOSVersion->getValue(), Major, + Minor, Micro, HadExtra) || + HadExtra || Major >= 10 || Minor >= 100 || Micro >= 100) getDriver().Diag(diag::err_drv_invalid_version_number) << WatchOSVersion->getAsString(Args); } else @@ -857,7 +857,7 @@ // "input arguments". if (A->getOption().hasFlag(options::LinkerInput)) { // Convert the argument into individual Zlinker_input_args. - for (const char *Value : A->getValues()) { + for (StringRef Value : A->getValues()) { DAL->AddSeparateArg( OriginalArg, Opts.getOption(options::OPT_Zlinker_input), Value); } @@ -1254,7 +1254,7 @@ if (!isTargetIPhoneOS() && Args.hasArg(options::OPT_shared_libgcc) && !isTargetWatchOS() && isMacosxVersionLT(10, 5)) { - const char *Str = Args.MakeArgString(GetFilePath("crt3.o")); + StringRef Str = Args.MakeArgString(GetFilePath("crt3.o")); CmdArgs.push_back(Str); } } @@ -2999,7 +2999,7 @@ // -L Args //---------------------------------------------------------------------------- for (Arg *A : Args.filtered(options::OPT_L)) - for (const char *Value : A->getValues()) + for (StringRef Value : A->getValues()) LibPaths.push_back(Value); //---------------------------------------------------------------------------- Index: clang/lib/Driver/Tools.h =================================================================== --- clang/lib/Driver/Tools.h +++ clang/lib/Driver/Tools.h @@ -45,12 +45,12 @@ /// \brief Clang compiler tool. class LLVM_LIBRARY_VISIBILITY Clang : public Tool { public: - static const char *getBaseInputName(const llvm::opt::ArgList &Args, - const InputInfo &Input); - static const char *getBaseInputStem(const llvm::opt::ArgList &Args, - const InputInfoList &Inputs); - static const char *getDependencyFileName(const llvm::opt::ArgList &Args, - const InputInfoList &Inputs); + static StringRef getBaseInputName(const llvm::opt::ArgList &Args, + const InputInfo &Input); + static StringRef getBaseInputStem(const llvm::opt::ArgList &Args, + const InputInfoList &Inputs); + static StringRef getDependencyFileName(const llvm::opt::ArgList &Args, + const InputInfoList &Inputs); private: void AddPreprocessingOptions(Compilation &C, const JobAction &JA, Index: clang/lib/Driver/Tools.cpp =================================================================== --- clang/lib/Driver/Tools.cpp +++ clang/lib/Driver/Tools.cpp @@ -132,10 +132,10 @@ // Add backslashes to escape spaces and other backslashes. // This is used for the space-separated argument list specified with // the -dwarf-debug-flags option. -static void EscapeSpacesAndBackslashes(const char *Arg, +static void EscapeSpacesAndBackslashes(StringRef ArgStr, SmallVectorImpl &Res) { - for (; *Arg; ++Arg) { - switch (*Arg) { + for (auto Arg : ArgStr) { + switch (Arg) { default: break; case ' ': @@ -143,7 +143,7 @@ Res.push_back('\\'); break; } - Res.push_back(*Arg); + Res.push_back(Arg); } } @@ -332,7 +332,7 @@ (A = Args.getLastArg(options::OPT_MD)) || (A = Args.getLastArg(options::OPT_MMD))) { // Determine the output location. - const char *DepFile; + StringRef DepFile; if (Arg *MF = Args.getLastArg(options::OPT_MF)) { DepFile = MF->getValue(); C.addFailureResultFile(DepFile, &JA); @@ -350,7 +350,7 @@ // Add a default target if one wasn't specified. if (!Args.hasArg(options::OPT_MT) && !Args.hasArg(options::OPT_MQ)) { - const char *DepTarget; + StringRef DepTarget; // If user provided -o, that is the dependency target, except // when we are only generating a dependency file. @@ -430,9 +430,9 @@ ++AI; if (!A->getOption().matches(options::OPT_include)) continue; - if (YcArg && strcmp(A->getValue(), YcArg->getValue()) == 0) + if (YcArg && A->getValue() == YcArg->getValue()) YcIndex = AI; - if (YuArg && strcmp(A->getValue(), YuArg->getValue()) == 0) + if (YuArg && A->getValue() == YuArg->getValue()) YuIndex = AI; } } @@ -568,7 +568,7 @@ // If we have a --sysroot, and don't have an explicit -isysroot flag, add an // -isysroot to the CC1 invocation. StringRef sysroot = C.getSysRoot(); - if (sysroot != "") { + if (!sysroot.empty()) { if (!Args.hasArg(options::OPT_isysroot)) { CmdArgs.push_back("-isysroot"); CmdArgs.push_back(C.getArgs().MakeArgString(sysroot)); @@ -1062,7 +1062,7 @@ // Select the ABI to use. // FIXME: Support -meabi. // FIXME: Parts of this are duplicated in the backend, unify this somehow. - const char *ABIName = nullptr; + StringRef ABIName; if (Arg *A = Args.getLastArg(options::OPT_mabi_EQ)) { ABIName = A->getValue(); } else if (Triple.isOSBinFormatMachO()) { @@ -1176,7 +1176,7 @@ options::OPT_mno_implicit_float, true)) CmdArgs.push_back("-no-implicit-float"); - const char *ABIName = nullptr; + StringRef ABIName; if (Arg *A = Args.getLastArg(options::OPT_mabi_EQ)) ABIName = A->getValue(); else if (Triple.isOSDarwin()) @@ -1631,7 +1631,7 @@ void Clang::AddPPCTargetArgs(const ArgList &Args, ArgStringList &CmdArgs) const { // Select the ABI to use. - const char *ABIName = nullptr; + StringRef ABIName; if (getToolChain().getTriple().isOSLinux()) switch (getToolChain().getArch()) { case llvm::Triple::ppc64: { @@ -1661,7 +1661,7 @@ // The ppc64 linux abis are all "altivec" abis by default. Accept and ignore // the option if given as we don't have backend support for any targets // that don't use the altivec abi. - if (StringRef(A->getValue()) != "altivec") + if (A->getValue() != "altivec") ABIName = A->getValue(); ppc::FloatABI FloatABI = @@ -1679,7 +1679,7 @@ CmdArgs.push_back("hard"); } - if (ABIName) { + if (!ABIName.empty()) { CmdArgs.push_back("-target-abi"); CmdArgs.push_back(ABIName); } @@ -1693,8 +1693,8 @@ /// Get the (LLVM) name of the R600 gpu we are targeting. static std::string getR600TargetGPU(const ArgList &Args) { if (Arg *A = Args.getLastArg(options::OPT_mcpu_EQ)) { - const char *GPUName = A->getValue(); - return llvm::StringSwitch(GPUName) + StringRef GPUName = A->getValue(); + return llvm::StringSwitch(GPUName) .Cases("rv630", "rv635", "r600") .Cases("rv610", "rv620", "rs780", "rs880") .Case("rv740", "rv770") @@ -1780,7 +1780,7 @@ CmdArgs.push_back("-mbackchain"); } -static const char *getSystemZTargetCPU(const ArgList &Args) { +static StringRef getSystemZTargetCPU(const ArgList &Args) { if (const Arg *A = Args.getLastArg(options::OPT_march_EQ)) return A->getValue(); return "z10"; @@ -1804,8 +1804,8 @@ } } -static const char *getX86TargetCPU(const ArgList &Args, - const llvm::Triple &Triple) { +static StringRef getX86TargetCPU(const ArgList &Args, + const llvm::Triple &Triple) { if (const Arg *A = Args.getLastArg(options::OPT_march_EQ)) { if (StringRef(A->getValue()) != "native") { if (Triple.isOSDarwin() && Triple.getArchName() == "x86_64h") @@ -1850,7 +1850,7 @@ if (Triple.getArch() != llvm::Triple::x86_64 && Triple.getArch() != llvm::Triple::x86) - return nullptr; // This routine is only handling x86 targets. + return StringRef(); // This routine is only handling x86 targets. bool Is64Bit = Triple.getArch() == llvm::Triple::x86_64; @@ -2860,7 +2860,7 @@ bool CompressDebugSections = false; bool UseRelaxRelocations = ENABLE_X86_RELAX_RELOCATIONS; - const char *MipsTargetFeature = nullptr; + StringRef MipsTargetFeature; for (const Arg *A : Args.filtered(options::OPT_Wa_COMMA, options::OPT_Xassembler)) { A->claim(); @@ -2917,7 +2917,7 @@ .Case("-mips64r5", "+mips64r5") .Case("-mips64r6", "+mips64r6") .Default(nullptr); - if (MipsTargetFeature) + if (!MipsTargetFeature.empty()) continue; } @@ -2974,7 +2974,7 @@ } if (UseRelaxRelocations) CmdArgs.push_back("--mrelax-relocations"); - if (MipsTargetFeature != nullptr) { + if (!MipsTargetFeature.empty()) { CmdArgs.push_back("-target-feature"); CmdArgs.push_back(MipsTargetFeature); } @@ -3337,7 +3337,7 @@ } } -static const char *SplitDebugName(const ArgList &Args, const InputInfo &Input) { +static StringRef SplitDebugName(const ArgList &Args, const InputInfo &Input) { Arg *FinalOutput = Args.getLastArg(options::OPT_o); if (FinalOutput && Args.hasArg(options::OPT_c)) { SmallString<128> T(FinalOutput->getValue()); @@ -3356,7 +3356,7 @@ static void SplitDebugInfo(const ToolChain &TC, Compilation &C, const Tool &T, const JobAction &JA, const ArgList &Args, - const InputInfo &Output, const char *OutFile) { + const InputInfo &Output, StringRef OutFile) { ArgStringList ExtractArgs; ExtractArgs.push_back("--extract-dwo"); @@ -3368,7 +3368,7 @@ ExtractArgs.push_back(Output.getFilename()); ExtractArgs.push_back(OutFile); - const char *Exec = Args.MakeArgString(TC.GetProgramPath("objcopy")); + StringRef Exec = Args.MakeArgString(TC.GetProgramPath("objcopy")); InputInfo II(types::TY_Object, Output.getFilename(), Output.getFilename()); // First extract the dwo sections. @@ -6207,7 +6207,7 @@ SmallString<256> Flags; Flags += Exec; - for (const char *OriginalArg : OriginalArgs) { + for (StringRef OriginalArg : OriginalArgs) { SmallString<128> EscapedArg; EscapeSpacesAndBackslashes(OriginalArg, EscapedArg); Flags += " "; @@ -6222,7 +6222,7 @@ bool SplitDwarf = SplitDwarfArg && getToolChain().getTriple().isOSLinux() && (isa(JA) || isa(JA) || isa(JA)); - const char *SplitDwarfOut; + StringRef SplitDwarfOut; if (SplitDwarf) { CmdArgs.push_back("-split-dwarf-file"); SplitDwarfOut = SplitDebugName(Args, Input); @@ -6798,7 +6798,7 @@ SmallString<256> Flags; const char *Exec = getToolChain().getDriver().getClangProgramPath(); Flags += Exec; - for (const char *OriginalArg : OriginalArgs) { + for (StringRef OriginalArg : OriginalArgs) { SmallString<128> EscapedArg; EscapeSpacesAndBackslashes(OriginalArg, EscapedArg); Flags += " "; @@ -6980,7 +6980,7 @@ } else GCCName = "gcc"; - const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath(GCCName)); + StringRef Exec = Args.MakeArgString(getToolChain().GetProgramPath(GCCName)); C.addCommand(llvm::make_unique(JA, *this, Exec, CmdArgs, Inputs)); } @@ -7092,7 +7092,7 @@ II.getInputArg().render(Args, CmdArgs); } - auto *Exec = Args.MakeArgString(HTC.GetProgramPath(AsName.c_str())); + auto Exec = Args.MakeArgString(HTC.GetProgramPath(AsName.c_str())); C.addCommand(llvm::make_unique(JA, *this, Exec, CmdArgs, Inputs)); } @@ -7323,7 +7323,7 @@ const ToolChain &ToolChain = getToolChain(); const Driver &D = ToolChain.getDriver(); - const char *Linker = Args.MakeArgString(ToolChain.GetLinkerPath()); + auto Linker = Args.MakeArgString(ToolChain.GetLinkerPath()); ArgStringList CmdArgs; CmdArgs.push_back("-flavor"); CmdArgs.push_back("ld"); @@ -7624,23 +7624,22 @@ } } -const char *Clang::getBaseInputName(const ArgList &Args, - const InputInfo &Input) { +StringRef Clang::getBaseInputName(const ArgList &Args, const InputInfo &Input) { return Args.MakeArgString(llvm::sys::path::filename(Input.getBaseInput())); } -const char *Clang::getBaseInputStem(const ArgList &Args, - const InputInfoList &Inputs) { - const char *Str = getBaseInputName(Args, Inputs[0]); - - if (const char *End = strrchr(Str, '.')) - return Args.MakeArgString(std::string(Str, End)); +StringRef Clang::getBaseInputStem(const ArgList &Args, + const InputInfoList &Inputs) { + StringRef Str = getBaseInputName(Args, Inputs[0]); + auto DotPos = Str.find('.'); + if (DotPos != StringRef::npos) + return Args.MakeArgString(Str.take_front(DotPos)); return Str; } -const char *Clang::getDependencyFileName(const ArgList &Args, - const InputInfoList &Inputs) { +StringRef Clang::getDependencyFileName(const ArgList &Args, + const InputInfoList &Inputs) { // FIXME: Think about this more. std::string Res; @@ -7719,7 +7718,7 @@ if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtend.o"))); - const char *Exec = Args.MakeArgString(ToolChain.GetLinkerPath()); + StringRef Exec = Args.MakeArgString(ToolChain.GetLinkerPath()); C.addCommand(llvm::make_unique(JA, *this, Exec, CmdArgs, Inputs)); } @@ -7787,7 +7786,7 @@ // asm_final spec is empty. - const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("as")); + StringRef Exec = Args.MakeArgString(getToolChain().GetProgramPath("as")); C.addCommand(llvm::make_unique(JA, *this, Exec, CmdArgs, Inputs)); } @@ -7848,7 +7847,7 @@ // the linker to use, so that it's lifetime will extend past a possible // dsymutil step. if (Version[0] >= 116 && NeedsTempPath(Inputs)) { - const char *TmpPath = C.getArgs().MakeArgString( + StringRef TmpPath = C.getArgs().MakeArgString( D.GetTemporaryPath("cc", types::getTypeTempSuffix(types::TY_Object))); C.addTempFile(TmpPath); CmdArgs.push_back("-object_path_lto"); @@ -7989,7 +7988,7 @@ // Give --sysroot= preference, over the Apple specific behavior to also use // --isysroot as the syslibroot. StringRef sysroot = C.getSysRoot(); - if (sysroot != "") { + if (!sysroot.empty()) { CmdArgs.push_back("-syslibroot"); CmdArgs.push_back(C.getArgs().MakeArgString(sysroot)); } else if (const Arg *A = Args.getLastArg(options::OPT_isysroot)) { @@ -8043,8 +8042,7 @@ options::OPT_ccc_arcmt_migrate)) { for (const auto &Arg : Args) Arg->claim(); - const char *Exec = - Args.MakeArgString(getToolChain().GetProgramPath("touch")); + StringRef Exec = Args.MakeArgString(getToolChain().GetProgramPath("touch")); CmdArgs.push_back(Output.getFilename()); C.addCommand(llvm::make_unique(JA, *this, Exec, CmdArgs, None)); return; @@ -8118,7 +8116,7 @@ if (!LinkingOutput.empty()) { CmdArgs.push_back("-arch_multiple"); CmdArgs.push_back("-final_output"); - CmdArgs.push_back(LinkingOutput.data()); + CmdArgs.push_back(LinkingOutput); } if (Args.hasArg(options::OPT_fnested_functions)) @@ -8163,7 +8161,7 @@ } } - const char *Exec = Args.MakeArgString(getToolChain().GetLinkerPath()); + StringRef Exec = Args.MakeArgString(getToolChain().GetLinkerPath()); std::unique_ptr Cmd = llvm::make_unique(JA, *this, Exec, CmdArgs, Inputs); Cmd->setInputFileList(std::move(InputFileList)); @@ -8188,7 +8186,7 @@ CmdArgs.push_back(II.getFilename()); } - const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("lipo")); + StringRef Exec = Args.MakeArgString(getToolChain().GetProgramPath("lipo")); C.addCommand(llvm::make_unique(JA, *this, Exec, CmdArgs, Inputs)); } @@ -8207,7 +8205,7 @@ assert(Input.isFilename() && "Unexpected dsymutil input."); CmdArgs.push_back(Input.getFilename()); - const char *Exec = + StringRef Exec = Args.MakeArgString(getToolChain().GetProgramPath("dsymutil")); C.addCommand(llvm::make_unique(JA, *this, Exec, CmdArgs, Inputs)); } @@ -8230,7 +8228,7 @@ // Grabbing the output of the earlier dsymutil run. CmdArgs.push_back(Input.getFilename()); - const char *Exec = + StringRef Exec = Args.MakeArgString(getToolChain().GetProgramPath("dwarfdump")); C.addCommand(llvm::make_unique(JA, *this, Exec, CmdArgs, Inputs)); } @@ -8251,7 +8249,7 @@ for (const auto &II : Inputs) CmdArgs.push_back(II.getFilename()); - const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("as")); + StringRef Exec = Args.MakeArgString(getToolChain().GetProgramPath("as")); C.addCommand(llvm::make_unique(JA, *this, Exec, CmdArgs, Inputs)); } @@ -8329,7 +8327,7 @@ getToolChain().addProfileRTLibs(Args, CmdArgs); - const char *Exec = Args.MakeArgString(getToolChain().GetLinkerPath()); + StringRef Exec = Args.MakeArgString(getToolChain().GetLinkerPath()); C.addCommand(llvm::make_unique(JA, *this, Exec, CmdArgs, Inputs)); } @@ -8400,7 +8398,7 @@ for (const auto &II : Inputs) CmdArgs.push_back(II.getFilename()); - const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("as")); + StringRef Exec = Args.MakeArgString(getToolChain().GetProgramPath("as")); C.addCommand(llvm::make_unique(JA, *this, Exec, CmdArgs, Inputs)); } @@ -8522,7 +8520,7 @@ Args.MakeArgString(getToolChain().GetFilePath("crtendS.o"))); } - const char *Exec = Args.MakeArgString(getToolChain().GetLinkerPath()); + StringRef Exec = Args.MakeArgString(getToolChain().GetLinkerPath()); C.addCommand(llvm::make_unique(JA, *this, Exec, CmdArgs, Inputs)); } @@ -8542,7 +8540,7 @@ for (const auto &II : Inputs) CmdArgs.push_back(II.getFilename()); - const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("as")); + StringRef Exec = Args.MakeArgString(getToolChain().GetProgramPath("as")); C.addCommand(llvm::make_unique(JA, *this, Exec, CmdArgs, Inputs)); } @@ -8651,7 +8649,7 @@ Args.MakeArgString(getToolChain().GetFilePath("crtendS.o"))); } - const char *Exec = Args.MakeArgString(getToolChain().GetLinkerPath()); + StringRef Exec = Args.MakeArgString(getToolChain().GetLinkerPath()); C.addCommand(llvm::make_unique(JA, *this, Exec, CmdArgs, Inputs)); } @@ -8744,7 +8742,7 @@ for (const auto &II : Inputs) CmdArgs.push_back(II.getFilename()); - const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("as")); + StringRef Exec = Args.MakeArgString(getToolChain().GetProgramPath("as")); C.addCommand(llvm::make_unique(JA, *this, Exec, CmdArgs, Inputs)); } @@ -8934,7 +8932,7 @@ ToolChain.addProfileRTLibs(Args, CmdArgs); - const char *Exec = Args.MakeArgString(getToolChain().GetLinkerPath()); + StringRef Exec = Args.MakeArgString(getToolChain().GetLinkerPath()); C.addCommand(llvm::make_unique(JA, *this, Exec, CmdArgs, Inputs)); } @@ -9017,7 +9015,7 @@ for (const auto &II : Inputs) CmdArgs.push_back(II.getFilename()); - const char *Exec = Args.MakeArgString((getToolChain().GetProgramPath("as"))); + StringRef Exec = Args.MakeArgString((getToolChain().GetProgramPath("as"))); C.addCommand(llvm::make_unique(JA, *this, Exec, CmdArgs, Inputs)); } @@ -9226,7 +9224,7 @@ getToolChain().addProfileRTLibs(Args, CmdArgs); - const char *Exec = Args.MakeArgString(getToolChain().GetLinkerPath()); + StringRef Exec = Args.MakeArgString(getToolChain().GetLinkerPath()); C.addCommand(llvm::make_unique(JA, *this, Exec, CmdArgs, Inputs)); } @@ -9435,7 +9433,7 @@ for (const auto &II : Inputs) CmdArgs.push_back(II.getFilename()); - const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("as")); + StringRef Exec = Args.MakeArgString(getToolChain().GetProgramPath("as")); C.addCommand(llvm::make_unique(JA, *this, Exec, CmdArgs, Inputs)); // Handle the debug info splitting at object creation time if we're @@ -9595,7 +9593,7 @@ // handled somewhere else. Args.ClaimAllArgs(options::OPT_w); - const char *Exec = Args.MakeArgString(ToolChain.GetLinkerPath()); + StringRef Exec = Args.MakeArgString(ToolChain.GetLinkerPath()); if (llvm::sys::path::filename(Exec) == "lld") { CmdArgs.push_back("-flavor"); CmdArgs.push_back("old-gnu"); @@ -9977,7 +9975,7 @@ } } - const char *Exec = Args.MakeArgString(ToolChain.GetLinkerPath()); + StringRef Exec = Args.MakeArgString(ToolChain.GetLinkerPath()); C.addCommand(llvm::make_unique(JA, *this, Exec, CmdArgs, Inputs)); } @@ -10000,7 +9998,7 @@ // handled somewhere else. Args.ClaimAllArgs(options::OPT_w); - const char *Exec = Args.MakeArgString(ToolChain.GetLinkerPath()); + StringRef Exec = Args.MakeArgString(ToolChain.GetLinkerPath()); if (llvm::sys::path::filename(Exec).equals_lower("lld")) { CmdArgs.push_back("-flavor"); CmdArgs.push_back("gnu"); @@ -10103,7 +10101,7 @@ for (const auto &II : Inputs) CmdArgs.push_back(II.getFilename()); - const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("as")); + StringRef Exec = Args.MakeArgString(getToolChain().GetProgramPath("as")); C.addCommand(llvm::make_unique(JA, *this, Exec, CmdArgs, Inputs)); } @@ -10154,7 +10152,7 @@ Args.MakeArgString(getToolChain().GetFilePath("crtend.o"))); } - const char *Exec = Args.MakeArgString(getToolChain().GetLinkerPath()); + StringRef Exec = Args.MakeArgString(getToolChain().GetLinkerPath()); C.addCommand(llvm::make_unique(JA, *this, Exec, CmdArgs, Inputs)); } @@ -10183,7 +10181,7 @@ for (const auto &II : Inputs) CmdArgs.push_back(II.getFilename()); - const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("as")); + StringRef Exec = Args.MakeArgString(getToolChain().GetProgramPath("as")); C.addCommand(llvm::make_unique(JA, *this, Exec, CmdArgs, Inputs)); } @@ -10306,7 +10304,7 @@ getToolChain().addProfileRTLibs(Args, CmdArgs); - const char *Exec = Args.MakeArgString(getToolChain().GetLinkerPath()); + StringRef Exec = Args.MakeArgString(getToolChain().GetLinkerPath()); C.addCommand(llvm::make_unique(JA, *this, Exec, CmdArgs, Inputs)); } @@ -10468,7 +10466,7 @@ // Render -l options differently for the MSVC linker. if (A.getOption().matches(options::OPT_l)) { StringRef Lib = A.getValue(); - const char *LinkLibArg; + StringRef LinkLibArg; if (Lib.endswith(".lib")) LinkLibArg = Args.MakeArgString(Lib); else @@ -10504,7 +10502,7 @@ linkPath = TC.GetProgramPath(linkPath.c_str()); } - const char *Exec = Args.MakeArgString(linkPath); + StringRef Exec = Args.MakeArgString(linkPath); C.addCommand(llvm::make_unique(JA, *this, Exec, CmdArgs, Inputs)); } @@ -10618,8 +10616,7 @@ // Output filename. assert(Output.getType() == types::TY_Object); - const char *Fo = - Args.MakeArgString(std::string("/Fo") + Output.getFilename()); + StringRef Fo = Args.MakeArgString(std::string("/Fo") + Output.getFilename()); CmdArgs.push_back(Fo); const Driver &D = getToolChain().getDriver(); @@ -10652,7 +10649,7 @@ for (const auto &II : Inputs) CmdArgs.push_back(II.getFilename()); - const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("as")); + StringRef Exec = Args.MakeArgString(getToolChain().GetProgramPath("as")); C.addCommand(llvm::make_unique(JA, *this, Exec, CmdArgs, Inputs)); if (Args.hasArg(options::OPT_gsplit_dwarf)) @@ -10846,7 +10843,7 @@ CmdArgs.push_back(Args.MakeArgString(TC.GetFilePath("crtend.o"))); } } - const char *Exec = Args.MakeArgString(TC.GetProgramPath(LinkerName.data())); + StringRef Exec = Args.MakeArgString(TC.GetProgramPath(LinkerName)); C.addCommand(llvm::make_unique(JA, *this, Exec, CmdArgs, Inputs)); } @@ -10882,7 +10879,7 @@ for (const auto &II : Inputs) CmdArgs.push_back(II.getFilename()); - const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("xcc")); + StringRef Exec = Args.MakeArgString(getToolChain().GetProgramPath("xcc")); C.addCommand(llvm::make_unique(JA, *this, Exec, CmdArgs, Inputs)); } @@ -10910,7 +10907,7 @@ AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs); - const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("xcc")); + StringRef Exec = Args.MakeArgString(getToolChain().GetProgramPath("xcc")); C.addCommand(llvm::make_unique(JA, *this, Exec, CmdArgs, Inputs)); } @@ -10923,7 +10920,7 @@ const auto &TC = static_cast(getToolChain()); ArgStringList CmdArgs; - const char *Exec; + StringRef Exec; switch (TC.getArch()) { default: @@ -10964,7 +10961,7 @@ const Driver &D = TC.getDriver(); SmallString<128> EntryPoint; ArgStringList CmdArgs; - const char *Exec; + StringRef Exec; // Silence warning for "clang -g foo.o -o foo" Args.ClaimAllArgs(options::OPT_g_Group); @@ -11294,7 +11291,7 @@ assert(Input.isFilename() && "Invalid input."); CmdArgs.push_back(Input.getFilename()); - const char *Exec = + StringRef Exec = Args.MakeArgString(getToolChain().GetProgramPath("orbis-as")); C.addCommand(llvm::make_unique(JA, *this, Exec, CmdArgs, Inputs)); } @@ -11363,7 +11360,7 @@ CmdArgs.push_back("-lpthread"); } - const char *Exec = Args.MakeArgString(ToolChain.GetProgramPath("orbis-ld")); + StringRef Exec = Args.MakeArgString(ToolChain.GetProgramPath("orbis-ld")); C.addCommand(llvm::make_unique(JA, T, Exec, CmdArgs, Inputs)); } @@ -11534,7 +11531,7 @@ CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtn.o"))); } - const char *Exec = + StringRef Exec = #ifdef LLVM_ON_WIN32 Args.MakeArgString(ToolChain.GetProgramPath("orbis-ld.gold")); #else @@ -11642,7 +11639,7 @@ for (const auto& A : Args.getAllArgValues(options::OPT_Xcuda_ptxas)) CmdArgs.push_back(Args.MakeArgString(A)); - const char *Exec = Args.MakeArgString(TC.GetProgramPath("ptxas")); + StringRef Exec = Args.MakeArgString(TC.GetProgramPath("ptxas")); C.addCommand(llvm::make_unique(JA, *this, Exec, CmdArgs, Inputs)); } @@ -11686,6 +11683,6 @@ for (const auto& A : Args.getAllArgValues(options::OPT_Xcuda_fatbinary)) CmdArgs.push_back(Args.MakeArgString(A)); - const char *Exec = Args.MakeArgString(TC.GetProgramPath("fatbinary")); + StringRef Exec = Args.MakeArgString(TC.GetProgramPath("fatbinary")); C.addCommand(llvm::make_unique(JA, *this, Exec, CmdArgs, Inputs)); } Index: clang/lib/Driver/Types.cpp =================================================================== --- clang/lib/Driver/Types.cpp +++ clang/lib/Driver/Types.cpp @@ -230,11 +230,10 @@ .Default(TY_INVALID); } -types::ID types::lookupTypeForTypeSpecifier(const char *Name) { +types::ID types::lookupTypeForTypeSpecifier(llvm::StringRef Name) { for (unsigned i=0; igetOption().getName().drop_front(1).rtrim("=-")); } else { // Otherwise, add its value (for OPT_W_Joined and similar). - for (const char *Arg : A->getValues()) + for (StringRef Arg : A->getValues()) Diagnostics.emplace_back(Arg); } } @@ -141,16 +141,14 @@ static void getAllNoBuiltinFuncValues(ArgList &Args, std::vector &Funcs) { - SmallVector Values; for (const auto &Arg : Args) { const Option &O = Arg->getOption(); if (O.matches(options::OPT_fno_builtin_)) { - const char *FuncName = Arg->getValue(); + StringRef FuncName = Arg->getValue(); if (Builtin::Context::isBuiltinFunc(FuncName)) - Values.push_back(FuncName); + Funcs.push_back(FuncName); } } - Funcs.insert(Funcs.end(), Values.begin(), Values.end()); } static bool ParseAnalyzerArgs(AnalyzerOptions &Opts, ArgList &Args, @@ -1369,10 +1367,10 @@ return DashX; } -std::string CompilerInvocation::GetResourcesPath(const char *Argv0, +std::string CompilerInvocation::GetResourcesPath(StringRef Argv0, void *MainAddr) { std::string ClangExecutable = - llvm::sys::fs::getMainExecutable(Argv0, MainAddr); + llvm::sys::fs::getMainExecutable(Argv0.str().c_str(), MainAddr); StringRef Dir = llvm::sys::path::parent_path(ClangExecutable); // Compute the path to the resource directory. @@ -1395,7 +1393,7 @@ Opts.UseStandardSystemIncludes = !Args.hasArg(OPT_nostdsysteminc); Opts.UseStandardCXXIncludes = !Args.hasArg(OPT_nostdincxx); if (const Arg *A = Args.getLastArg(OPT_stdlib_EQ)) - Opts.UseLibcxx = (strcmp(A->getValue(), "libc++") == 0); + Opts.UseLibcxx = A->getValue() == "libc++"; Opts.ResourceDir = Args.getLastArgValue(OPT_resource_dir); Opts.ModuleCachePath = Args.getLastArgValue(OPT_fmodules_cache_path); Opts.ModuleUserBuildPath = Args.getLastArgValue(OPT_fmodules_user_build_path); @@ -1460,9 +1458,11 @@ if (A->getOption().matches(OPT_iprefix)) Prefix = A->getValue(); else if (A->getOption().matches(OPT_iwithprefix)) - Opts.AddPath(Prefix.str() + A->getValue(), frontend::After, false, true); + Opts.AddPath((Prefix + A->getValue()).str(), frontend::After, false, + true); else - Opts.AddPath(Prefix.str() + A->getValue(), frontend::Angled, false, true); + Opts.AddPath((Prefix + A->getValue()).str(), frontend::Angled, false, + true); } for (const Arg *A : Args.filtered(OPT_idirafter)) @@ -2369,6 +2369,16 @@ const char *const *ArgBegin, const char *const *ArgEnd, DiagnosticsEngine &Diags) { + SmallVector ArgsStr; + for (const char *const *Arg = ArgBegin; Arg != ArgEnd; ++Arg) + ArgsStr.push_back(StringRef(*Arg)); + return CreateFromArgs(Res, ArgsStr.begin(), ArgsStr.end(), Diags); +} + +bool CompilerInvocation::CreateFromArgs(CompilerInvocation &Res, + const StringRef *ArgBegin, + const StringRef *ArgEnd, + DiagnosticsEngine &Diags) { bool Success = true; // Parse the arguments. Index: clang/lib/Frontend/CreateInvocationFromCommandLine.cpp =================================================================== --- clang/lib/Frontend/CreateInvocationFromCommandLine.cpp +++ clang/lib/Frontend/CreateInvocationFromCommandLine.cpp @@ -39,7 +39,7 @@ Diags = CompilerInstance::createDiagnostics(new DiagnosticOptions); } - SmallVector Args(ArgList.begin(), ArgList.end()); + SmallVector Args(ArgList.begin(), ArgList.end()); // FIXME: Find a cleaner way to force the driver into restricted modes. Args.push_back("-fsyntax-only"); @@ -92,12 +92,10 @@ return nullptr; } - const ArgStringList &CCArgs = Cmd.getArguments(); + auto &CCArgs = Cmd.getArguments(); std::unique_ptr CI(new CompilerInvocation()); if (!CompilerInvocation::CreateFromArgs(*CI, - const_cast(CCArgs.data()), - const_cast(CCArgs.data()) + - CCArgs.size(), + CCArgs.begin(), CCArgs.end(), *Diags)) return nullptr; return CI.release(); Index: clang/lib/Tooling/CompilationDatabase.cpp =================================================================== --- clang/lib/Tooling/CompilationDatabase.cpp +++ clang/lib/Tooling/CompilationDatabase.cpp @@ -204,7 +204,7 @@ /// \li true if successful. /// \li false if \c Args cannot be used for compilation jobs (e.g. /// contains an option like -E or -version). -static bool stripPositionalArgs(std::vector Args, +static bool stripPositionalArgs(std::vector Args, std::vector &Result) { IntrusiveRefCntPtr DiagOpts = new DiagnosticOptions(); UnusedInputDiagConsumer DiagClient; @@ -266,15 +266,15 @@ // Remove all compilation input files from the command line. This is // necessary so that getCompileCommands() can construct a command line for // each file. - std::vector::iterator End = std::remove_if( + std::vector::iterator End = std::remove_if( Args.begin(), Args.end(), MatchesAny(CompileAnalyzer.Inputs)); // Remove all inputs deemed unused for compilation. End = std::remove_if(Args.begin(), End, MatchesAny(DiagClient.UnusedInputs)); // Remove the -c add above as well. It will be at the end right now. - assert(strcmp(*(End - 1), "-c") == 0); - --End; + --End; + assert(*End == "-c"); Result = std::vector(Args.begin() + 1, End); return true; @@ -285,7 +285,11 @@ const char *const *DoubleDash = std::find(Argv, Argv + Argc, StringRef("--")); if (DoubleDash == Argv + Argc) return nullptr; - std::vector CommandLine(DoubleDash + 1, Argv + Argc); + std::vector CommandLine; + CommandLine.reserve(Argv + Argc - DoubleDash - 1); + for (auto Arg : ArrayRef(DoubleDash + 1, Argv + Argc)) + CommandLine.push_back(Arg); + Argc = DoubleDash - Argv; std::vector StrippedArgs; Index: clang/lib/Tooling/JSONCompilationDatabase.cpp =================================================================== --- clang/lib/Tooling/JSONCompilationDatabase.cpp +++ clang/lib/Tooling/JSONCompilationDatabase.cpp @@ -131,9 +131,11 @@ if (Syntax == JSONCommandLineSyntax::Windows) { llvm::BumpPtrAllocator Alloc; llvm::StringSaver Saver(Alloc); - llvm::SmallVector T; + llvm::SmallVector T; llvm::cl::TokenizeWindowsCommandLine(EscapedCommandLine, Saver, T); - std::vector Result(T.begin(), T.end()); + std::vector Result; + for (StringRef Token : T) + Result.push_back(Token); return Result; } assert(Syntax == JSONCommandLineSyntax::Gnu); Index: clang/lib/Tooling/Tooling.cpp =================================================================== --- clang/lib/Tooling/Tooling.cpp +++ clang/lib/Tooling/Tooling.cpp @@ -50,9 +50,9 @@ // it to be based on the same framework. /// \brief Builds a clang driver initialized for running clang tools. -static clang::driver::Driver *newDriver( - clang::DiagnosticsEngine *Diagnostics, const char *BinaryName, - IntrusiveRefCntPtr VFS) { +static clang::driver::Driver * +newDriver(clang::DiagnosticsEngine *Diagnostics, StringRef BinaryName, + IntrusiveRefCntPtr VFS) { clang::driver::Driver *CompilerDriver = new clang::driver::Driver(BinaryName, llvm::sys::getDefaultTargetTriple(), *Diagnostics, std::move(VFS)); @@ -238,15 +238,15 @@ } bool ToolInvocation::run() { - std::vector Argv; + std::vector Argv; for (const std::string &Str : CommandLine) - Argv.push_back(Str.c_str()); - const char *const BinaryName = Argv[0]; + Argv.push_back(Str); + StringRef BinaryName(Argv[0]); IntrusiveRefCntPtr DiagOpts = new DiagnosticOptions(); unsigned MissingArgIndex, MissingArgCount; std::unique_ptr Opts(driver::createDriverOptTable()); llvm::opt::InputArgList ParsedArgs = Opts->ParseArgs( - ArrayRef(Argv).slice(1), MissingArgIndex, MissingArgCount); + ArrayRef(Argv).slice(1), MissingArgIndex, MissingArgCount); ParseDiagnosticArgs(*DiagOpts, ParsedArgs); TextDiagnosticPrinter DiagnosticPrinter( llvm::errs(), &*DiagOpts); @@ -280,7 +280,7 @@ } bool ToolInvocation::runInvocation( - const char *BinaryName, clang::driver::Compilation *Compilation, + StringRef BinaryName, clang::driver::Compilation *Compilation, clang::CompilerInvocation *Invocation, std::shared_ptr PCHContainerOps) { // Show the invocation, with -v. Index: clang/tools/driver/cc1_main.cpp =================================================================== --- clang/tools/driver/cc1_main.cpp +++ clang/tools/driver/cc1_main.cpp @@ -129,7 +129,7 @@ static void ensureSufficientStack() {} #endif -int cc1_main(ArrayRef Argv, const char *Argv0, void *MainAddr) { +int cc1_main(ArrayRef Argv, StringRef Argv0, void *MainAddr) { ensureSufficientStack(); std::unique_ptr Clang(new CompilerInstance()); Index: clang/tools/driver/cc1as_main.cpp =================================================================== --- clang/tools/driver/cc1as_main.cpp +++ clang/tools/driver/cc1as_main.cpp @@ -148,15 +148,14 @@ DwarfVersion = 0; } - static bool CreateFromArgs(AssemblerInvocation &Res, - ArrayRef Argv, + static bool CreateFromArgs(AssemblerInvocation &Res, ArrayRef Argv, DiagnosticsEngine &Diags); }; } bool AssemblerInvocation::CreateFromArgs(AssemblerInvocation &Opts, - ArrayRef Argv, + ArrayRef Argv, DiagnosticsEngine &Diags) { bool Success = true; @@ -449,7 +448,7 @@ exit(1); } -int cc1as_main(ArrayRef Argv, const char *Argv0, void *MainAddr) { +int cc1as_main(ArrayRef Argv, StringRef Argv0, void *MainAddr) { // Initialize targets and assembly printers/parsers. InitializeAllTargetInfos(); InitializeAllTargetMCs(); Index: clang/tools/driver/driver.cpp =================================================================== --- clang/tools/driver/driver.cpp +++ clang/tools/driver/driver.cpp @@ -52,14 +52,14 @@ using namespace clang::driver; using namespace llvm::opt; -std::string GetExecutablePath(const char *Argv0, bool CanonicalPrefixes) { +std::string GetExecutablePath(StringRef Argv0, bool CanonicalPrefixes) { if (!CanonicalPrefixes) return Argv0; // This just needs to be some symbol in the binary; C++ doesn't // allow taking the address of ::main however. void *P = (void*) (intptr_t) GetExecutablePath; - return llvm::sys::fs::getMainExecutable(Argv0, P); + return llvm::sys::fs::getMainExecutable(Argv0.str().c_str(), P); } static const char *GetStableCStr(std::set &SavedStrings, @@ -95,8 +95,7 @@ /// \param Edit - The override command to perform. /// \param SavedStrings - Set to use for storing string representations. static void ApplyOneQAOverride(raw_ostream &OS, - SmallVectorImpl &Args, - StringRef Edit, + SmallVectorImpl &Args, StringRef Edit, std::set &SavedStrings) { // This does not need to be efficient. @@ -118,7 +117,7 @@ for (unsigned i = 1, e = Args.size(); i != e; ++i) { // Ignore end-of-line response file markers - if (Args[i] == nullptr) + if (Args[i].empty()) continue; std::string Repl = llvm::Regex(MatchPattern).sub(ReplPattern, Args[i]); @@ -145,14 +144,14 @@ } } else if (Edit[0] == 'O') { for (unsigned i = 1; i < Args.size();) { - const char *A = Args[i]; + StringRef A = Args[i]; // Ignore end-of-line response file markers - if (A == nullptr) + if (A.empty()) continue; if (A[0] == '-' && A[1] == 'O' && - (A[2] == '\0' || - (A[3] == '\0' && (A[2] == 's' || A[2] == 'z' || - ('0' <= A[2] && A[2] <= '9'))))) { + (A.size() == 2 || + (A.size() == 3 && + (A[2] == 's' || A[2] == 'z' || ('0' <= A[2] && A[2] <= '9'))))) { OS << "### Deleting argument " << Args[i] << '\n'; Args.erase(Args.begin() + i); } else @@ -167,7 +166,7 @@ /// ApplyQAOverride - Apply a comma separate list of edits to the /// input argument lists. See ApplyOneQAOverride. -static void ApplyQAOverride(SmallVectorImpl &Args, +static void ApplyQAOverride(SmallVectorImpl &Args, const char *OverrideStr, std::set &SavedStrings) { raw_ostream *OS = &llvm::errs(); @@ -194,13 +193,12 @@ } } -extern int cc1_main(ArrayRef Argv, const char *Argv0, - void *MainAddr); -extern int cc1as_main(ArrayRef Argv, const char *Argv0, +extern int cc1_main(ArrayRef Argv, StringRef Argv0, void *MainAddr); +extern int cc1as_main(ArrayRef Argv, StringRef Argv0, void *MainAddr); static void insertTargetAndModeArgs(StringRef Target, StringRef Mode, - SmallVectorImpl &ArgVector, + SmallVectorImpl &ArgVector, std::set &SavedStrings) { if (!Mode.empty()) { // Add the mode flag to the arguments. @@ -220,12 +218,14 @@ } static void getCLEnvVarOptions(std::string &EnvValue, llvm::StringSaver &Saver, - SmallVectorImpl &Opts) { + SmallVectorImpl &Opts) { llvm::cl::TokenizeWindowsCommandLine(EnvValue, Saver, Opts); // The first instance of '#' should be replaced with '=' in each option. - for (const char *Opt : Opts) - if (char *NumberSignPtr = const_cast(::strchr(Opt, '#'))) - *NumberSignPtr = '='; + for (StringRef Opt : Opts) { + auto Pos = Opt.find('#'); + if (Pos != StringRef::npos) + const_cast(Opt.data())[Pos] = '='; + } } static void SetBackdoorDriverOutputsFromEnvVars(Driver &TheDriver) { @@ -257,8 +257,7 @@ // This lets us create the DiagnosticsEngine with a properly-filled-out // DiagnosticOptions instance. -static DiagnosticOptions * -CreateAndPopulateDiagOpts(ArrayRef argv) { +static DiagnosticOptions *CreateAndPopulateDiagOpts(ArrayRef argv) { auto *DiagOpts = new DiagnosticOptions; std::unique_ptr Opts(createDriverOptTable()); unsigned MissingArgIndex, MissingArgCount; @@ -271,8 +270,8 @@ return DiagOpts; } -static void SetInstallDir(SmallVectorImpl &argv, - Driver &TheDriver, bool CanonicalPrefixes) { +static void SetInstallDir(SmallVectorImpl &argv, Driver &TheDriver, + bool CanonicalPrefixes) { // Attempt to find the original path used to invoke the driver, to determine // the installed path. We do this manually, because we want to support that // path being a symlink. @@ -293,7 +292,7 @@ TheDriver.setInstalledDir(InstalledPathParent); } -static int ExecuteCC1Tool(ArrayRef argv, StringRef Tool) { +static int ExecuteCC1Tool(ArrayRef argv, StringRef Tool) { void *GetExecutablePathVP = (void *)(intptr_t) GetExecutablePath; if (Tool == "") return cc1_main(argv.slice(2), argv[0], GetExecutablePathVP); @@ -313,7 +312,7 @@ if (llvm::sys::Process::FixupStandardFileDescriptors()) return 1; - SmallVector argv; + SmallVector argv; llvm::SpecificBumpPtrAllocator ArgAllocator; std::error_code EC = llvm::sys::Process::GetArgumentVector( argv, llvm::makeArrayRef(argv_, argc_), ArgAllocator); @@ -339,16 +338,16 @@ // response files written by clang will tokenize the same way in either mode. bool ClangCLMode = false; if (TargetAndMode.second == "--driver-mode=cl" || - std::find_if(argv.begin(), argv.end(), [](const char *F) { - return F && strcmp(F, "--driver-mode=cl") == 0; + std::find_if(argv.begin(), argv.end(), [](StringRef F) { + return F == "--driver-mode=cl"; }) != argv.end()) { ClangCLMode = true; } enum { Default, POSIX, Windows } RSPQuoting = Default; - for (const char *F : argv) { - if (strcmp(F, "--rsp-quoting=posix") == 0) + for (StringRef F : argv) { + if (F == "--rsp-quoting=posix") RSPQuoting = POSIX; - else if (strcmp(F, "--rsp-quoting=windows") == 0) + else if (F == "--rsp-quoting=windows") RSPQuoting = Windows; } @@ -370,22 +369,22 @@ // Handle -cc1 integrated tools, even if -cc1 was expanded from a response // file. auto FirstArg = std::find_if(argv.begin() + 1, argv.end(), - [](const char *A) { return A != nullptr; }); + [](StringRef A) { return !A.empty(); }); if (FirstArg != argv.end() && StringRef(*FirstArg).startswith("-cc1")) { // If -cc1 came from a response file, remove the EOL sentinels. if (MarkEOLs) { - auto newEnd = std::remove(argv.begin(), argv.end(), nullptr); + auto newEnd = std::remove(argv.begin(), argv.end(), StringRef()); argv.resize(newEnd - argv.begin()); } - return ExecuteCC1Tool(argv, argv[1] + 4); + return ExecuteCC1Tool(argv, argv[1].drop_front(4)); } bool CanonicalPrefixes = true; for (int i = 1, size = argv.size(); i < size; ++i) { // Skip end-of-line response file markers - if (argv[i] == nullptr) + if (argv[i].empty()) continue; - if (StringRef(argv[i]) == "-no-canonical-prefixes") { + if (argv[i] == "-no-canonical-prefixes") { CanonicalPrefixes = false; break; } @@ -397,7 +396,7 @@ // Arguments in "CL" are prepended. llvm::Optional OptCL = llvm::sys::Process::GetEnv("CL"); if (OptCL.hasValue()) { - SmallVector PrependedOpts; + SmallVector PrependedOpts; getCLEnvVarOptions(OptCL.getValue(), Saver, PrependedOpts); // Insert right after the program name to prepend to the argument list. @@ -406,7 +405,7 @@ // Arguments in "_CL_" are appended. llvm::Optional Opt_CL_ = llvm::sys::Process::GetEnv("_CL_"); if (Opt_CL_.hasValue()) { - SmallVector AppendedOpts; + SmallVector AppendedOpts; getCLEnvVarOptions(Opt_CL_.getValue(), Saver, AppendedOpts); // Insert at the end of the argument list to append. Index: lld/COFF/Driver.h =================================================================== --- lld/COFF/Driver.h +++ lld/COFF/Driver.h @@ -45,18 +45,18 @@ public: ArgParser() : Alloc(AllocAux) {} // Parses command line options. - llvm::opt::InputArgList parse(llvm::ArrayRef Args); + llvm::opt::InputArgList parse(llvm::ArrayRef Args); // Concatenate LINK environment varirable and given arguments and parse them. - llvm::opt::InputArgList parseLINK(llvm::ArrayRef Args); + llvm::opt::InputArgList parseLINK(llvm::ArrayRef Args); // Tokenizes a given string and then parses as command line options. llvm::opt::InputArgList parse(StringRef S) { return parse(tokenize(S)); } private: - std::vector tokenize(StringRef S); + std::vector tokenize(StringRef S); - std::vector replaceResponseFiles(std::vector); + std::vector replaceResponseFiles(std::vector); llvm::BumpPtrAllocator AllocAux; llvm::StringSaver Alloc; @@ -65,7 +65,7 @@ class LinkerDriver { public: LinkerDriver() : Alloc(AllocAux) {} - void link(llvm::ArrayRef Args); + void link(llvm::ArrayRef Args); // Used by the resolver to parse .drectve section contents. void parseDirectives(StringRef S); @@ -117,7 +117,7 @@ // Functions below this line are defined in DriverUtils.cpp. -void printHelp(const char *Argv0); +void printHelp(StringRef Argv0); // For /machine option. MachineTypes getMachineType(StringRef Arg); Index: lld/COFF/Driver.cpp =================================================================== --- lld/COFF/Driver.cpp +++ lld/COFF/Driver.cpp @@ -43,7 +43,7 @@ Configuration *Config; LinkerDriver *Driver; -bool link(llvm::ArrayRef Args) { +bool link(llvm::ArrayRef Args) { Configuration C; LinkerDriver D; Config = &C; @@ -306,7 +306,7 @@ return DebugTypes; } -void LinkerDriver::link(llvm::ArrayRef ArgsArr) { +void LinkerDriver::link(llvm::ArrayRef ArgsArr) { // If the first command line argument is "/lib", link.exe acts like lib.exe. // We call our own implementation of lib.exe that understands bitcode files. if (ArgsArr.size() > 1 && StringRef(ArgsArr[1]).equals_lower("/lib")) { Index: lld/COFF/DriverUtils.cpp =================================================================== --- lld/COFF/DriverUtils.cpp +++ lld/COFF/DriverUtils.cpp @@ -617,9 +617,9 @@ }; // Parses a given list of options. -llvm::opt::InputArgList ArgParser::parse(ArrayRef ArgsArr) { +llvm::opt::InputArgList ArgParser::parse(ArrayRef ArgsArr) { // First, replace respnose files (@-style options). - std::vector Argv = replaceResponseFiles(ArgsArr); + std::vector Argv = replaceResponseFiles(ArgsArr); // Make InputArgList from string vectors. COFFOptTable Table; @@ -631,7 +631,7 @@ // Print the real command line if response files are expanded. if (Args.hasArg(OPT_verbose) && ArgsArr.size() != Argv.size()) { llvm::outs() << "Command line:"; - for (const char *S : Argv) + for (StringRef S : Argv) llvm::outs() << " " << S; llvm::outs() << "\n"; } @@ -645,34 +645,34 @@ return Args; } -llvm::opt::InputArgList ArgParser::parseLINK(ArrayRef Args) { +llvm::opt::InputArgList ArgParser::parseLINK(ArrayRef Args) { // Concatenate LINK env and given arguments and parse them. Optional Env = Process::GetEnv("LINK"); if (!Env) return parse(Args); - std::vector V = tokenize(*Env); + std::vector V = tokenize(*Env); V.insert(V.end(), Args.begin(), Args.end()); return parse(V); } -std::vector ArgParser::tokenize(StringRef S) { - SmallVector Tokens; +std::vector ArgParser::tokenize(StringRef S) { + SmallVector Tokens; StringSaver Saver(AllocAux); llvm::cl::TokenizeWindowsCommandLine(S, Saver, Tokens); - return std::vector(Tokens.begin(), Tokens.end()); + return std::vector(Tokens.begin(), Tokens.end()); } // Creates a new command line by replacing options starting with '@' // character. '@' is replaced by the file's contents. -std::vector -ArgParser::replaceResponseFiles(std::vector Argv) { - SmallVector Tokens(Argv.data(), Argv.data() + Argv.size()); +std::vector +ArgParser::replaceResponseFiles(std::vector Argv) { + SmallVector Tokens(Argv.data(), Argv.data() + Argv.size()); StringSaver Saver(AllocAux); ExpandResponseFiles(Saver, TokenizeWindowsCommandLine, Tokens); - return std::vector(Tokens.begin(), Tokens.end()); + return std::vector(Tokens.begin(), Tokens.end()); } -void printHelp(const char *Argv0) { +void printHelp(StringRef Argv0) { COFFOptTable Table; Table.PrintHelp(llvm::outs(), Argv0, "LLVM Linker", false); } Index: lld/ELF/Driver.h =================================================================== --- lld/ELF/Driver.h +++ lld/ELF/Driver.h @@ -27,7 +27,7 @@ class LinkerDriver { public: - void main(ArrayRef Args); + void main(ArrayRef Args); void addFile(StringRef Path, bool KnownScript = false); void addLibrary(StringRef Name); llvm::LLVMContext Context; // to parse bitcode files @@ -55,7 +55,7 @@ class ELFOptTable : public llvm::opt::OptTable { public: ELFOptTable(); - llvm::opt::InputArgList parse(ArrayRef Argv); + llvm::opt::InputArgList parse(ArrayRef Argv); private: llvm::BumpPtrAllocator Alloc; @@ -69,7 +69,7 @@ #undef OPTION }; -void printHelp(const char *Argv0); +void printHelp(StringRef Argv0); std::string getVersionString(); std::vector parseHexstring(StringRef S); Index: lld/ELF/Driver.cpp =================================================================== --- lld/ELF/Driver.cpp +++ lld/ELF/Driver.cpp @@ -38,7 +38,7 @@ Configuration *elf::Config; LinkerDriver *elf::Driver; -bool elf::link(ArrayRef Args, raw_ostream &Error) { +bool elf::link(ArrayRef Args, raw_ostream &Error) { HasError = false; ErrorOS = &Error; @@ -199,11 +199,11 @@ Driver->Context.enableDebugTypeODRUniquing(); // Parse and evaluate -mllvm options. - std::vector V; + std::vector V; V.push_back("lld (LLVM option parsing)"); for (auto *Arg : Args.filtered(OPT_mllvm)) V.push_back(Arg->getValue()); - cl::ParseCommandLineOptions(V.size(), V.data()); + cl::ParseCommandLineOptions(V.size(), V); } // Some command line options or some combinations of them are not allowed. @@ -249,10 +249,10 @@ return V; } -static const char *getReproduceOption(opt::InputArgList &Args) { +static StringRef getReproduceOption(opt::InputArgList &Args) { if (auto *Arg = Args.getLastArg(OPT_reproduce)) return Arg->getValue(); - return getenv("LLD_REPRODUCE"); + return StringRef(getenv("LLD_REPRODUCE")); } static bool hasZOption(opt::InputArgList &Args, StringRef Key) { @@ -278,7 +278,7 @@ return Default; } -void LinkerDriver::main(ArrayRef ArgsArr) { +void LinkerDriver::main(ArrayRef ArgsArr) { ELFOptTable Parser; opt::InputArgList Args = Parser.parse(ArgsArr.slice(1)); if (Args.hasArg(OPT_help)) { @@ -288,7 +288,8 @@ if (Args.hasArg(OPT_version)) outs() << getVersionString(); - if (const char *Path = getReproduceOption(Args)) { + StringRef Path = getReproduceOption(Args); + if (!Path.empty()) { // Note that --reproduce is a debug option so you can ignore it // if you are trying to understand the whole picture of the code. ErrorOr F = CpioFile::create(Path); Index: lld/ELF/DriverUtils.cpp =================================================================== --- lld/ELF/DriverUtils.cpp +++ lld/ELF/DriverUtils.cpp @@ -66,11 +66,11 @@ } // Parses a given list of options. -opt::InputArgList ELFOptTable::parse(ArrayRef Argv) { +opt::InputArgList ELFOptTable::parse(ArrayRef Argv) { // Make InputArgList from string vectors. unsigned MissingIndex; unsigned MissingCount; - SmallVector Vec(Argv.data(), Argv.data() + Argv.size()); + SmallVector Vec(Argv.data(), Argv.data() + Argv.size()); // We need to get the quoting style for response files before parsing all // options so we parse here before and ignore all the options but @@ -93,7 +93,7 @@ return Args; } -void elf::printHelp(const char *Argv0) { +void elf::printHelp(StringRef Argv0) { ELFOptTable Table; Table.PrintHelp(outs(), Argv0, "lld", false); } Index: lld/include/lld/Core/LinkingContext.h =================================================================== --- lld/include/lld/Core/LinkingContext.h +++ lld/include/lld/Core/LinkingContext.h @@ -102,7 +102,7 @@ /// options which are used to configure LLVM's command line settings. /// For instance the -debug-only XXX option can be used to dynamically /// trace different parts of LLVM and lld. - const std::vector &llvmOptions() const { return _llvmOptions; } + const std::vector &llvmOptions() const { return _llvmOptions; } /// \name Methods used by Drivers to configure TargetInfo /// @{ @@ -126,7 +126,7 @@ void setAllowShlibUndefines(bool allow) { _allowShlibUndefines = allow; } void setLogInputFiles(bool log) { _logInputFiles = log; } - void appendLLVMOption(const char *opt) { _llvmOptions.push_back(opt); } + void appendLLVMOption(StringRef opt) { _llvmOptions.push_back(opt); } std::vector> &getNodes() { return _nodes; } const std::vector> &getNodes() const { return _nodes; } @@ -234,7 +234,7 @@ bool _logInputFiles = false; bool _allowShlibUndefines = false; std::vector _deadStripRoots; - std::vector _llvmOptions; + std::vector _llvmOptions; StringRefVector _initialUndefinedSymbols; std::vector> _nodes; mutable llvm::BumpPtrAllocator _allocator; Index: lld/include/lld/Driver/Driver.h =================================================================== --- lld/include/lld/Driver/Driver.h +++ lld/include/lld/Driver/Driver.h @@ -13,18 +13,22 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/Support/raw_ostream.h" +namespace llvm { +class StringRef; +} + namespace lld { namespace coff { -bool link(llvm::ArrayRef Args); +bool link(llvm::ArrayRef Args); } namespace elf { -bool link(llvm::ArrayRef Args, +bool link(llvm::ArrayRef Args, llvm::raw_ostream &Diag = llvm::errs()); } namespace mach_o { -bool link(llvm::ArrayRef Args, +bool link(llvm::ArrayRef Args, llvm::raw_ostream &Diag = llvm::errs()); } } Index: lld/lib/Driver/DarwinLdDriver.cpp =================================================================== --- lld/lib/Driver/DarwinLdDriver.cpp +++ lld/lib/Driver/DarwinLdDriver.cpp @@ -284,26 +284,31 @@ // Honor -mllvm if (!ctx.llvmOptions().empty()) { unsigned numArgs = ctx.llvmOptions().size(); - auto **args = new const char *[numArgs + 2]; - args[0] = "lld (LLVM option parsing)"; - for (unsigned i = 0; i != numArgs; ++i) - args[i + 1] = ctx.llvmOptions()[i]; - args[numArgs + 1] = nullptr; - llvm::cl::ParseCommandLineOptions(numArgs + 1, args); + SmallVector LLVMArgs; + LLVMArgs.reserve(numArgs + 1); + LLVMArgs.push_back("lld (LLVM option parsing)"); + LLVMArgs.append(ctx.llvmOptions().begin(), ctx.llvmOptions().end()); + llvm::cl::ParseCommandLineOptions(numArgs + 1, LLVMArgs); } } namespace lld { namespace mach_o { -bool parse(llvm::ArrayRef args, MachOLinkingContext &ctx, +bool parse(llvm::ArrayRef args, MachOLinkingContext &ctx, raw_ostream &diagnostics) { // Parse command line options using DarwinLdOptions.td DarwinLdOptTable table; unsigned missingIndex; unsigned missingCount; + + SmallVector Args; + Args.reserve(args.size()); + for (auto Arg : args.slice(1)) + Args.push_back(StringRef(Arg)); + llvm::opt::InputArgList parsedArgs = - table.ParseArgs(args.slice(1), missingIndex, missingCount); + table.ParseArgs(Args, missingIndex, missingCount); if (missingCount) { diagnostics << "error: missing arg value for '" << parsedArgs.getArgString(missingIndex) << "' expected " @@ -498,11 +503,11 @@ // Handle -sectalign segname sectname align for (auto &alignArg : parsedArgs.filtered(OPT_sectalign)) { - const char* segName = alignArg->getValue(0); - const char* sectName = alignArg->getValue(1); - const char* alignStr = alignArg->getValue(2); + StringRef segName = alignArg->getValue(0); + StringRef sectName = alignArg->getValue(1); + StringRef alignStr = alignArg->getValue(2); if ((alignStr[0] == '0') && (alignStr[1] == 'x')) - alignStr += 2; + alignStr = alignStr.drop_front(2); unsigned long long alignValue; if (llvm::getAsUnsignedInteger(alignStr, 16, alignValue)) { diagnostics << "error: -sectalign alignment value '" @@ -1109,16 +1114,17 @@ } break; case OPT_sectcreate: { - const char* seg = arg->getValue(0); - const char* sect = arg->getValue(1); - const char* fileName = arg->getValue(2); + StringRef seg = arg->getValue(0); + StringRef sect = arg->getValue(1); + StringRef fileName = arg->getValue(2); - ErrorOr> contentOrErr = + ErrorOr> contentOrErr = MemoryBuffer::getFile(fileName); - if (!contentOrErr) { - diagnostics << "error: can't open -sectcreate file " << fileName << "\n"; - return false; + if (!contentOrErr) { + diagnostics << "error: can't open -sectcreate file " << fileName + << "\n"; + return false; } ctx.addSectCreateSection(seg, sect, std::move(*contentOrErr)); @@ -1149,7 +1155,7 @@ } /// This is where the link is actually performed. -bool link(llvm::ArrayRef args, raw_ostream &diagnostics) { +bool link(llvm::ArrayRef args, raw_ostream &diagnostics) { MachOLinkingContext ctx; if (!parse(args, ctx, diagnostics)) return false; Index: lld/tools/lld/lld.cpp =================================================================== --- lld/tools/lld/lld.cpp +++ lld/tools/lld/lld.cpp @@ -71,14 +71,14 @@ return Invalid; } -static Flavor parseFlavor(std::vector &V) { +static Flavor parseFlavor(std::vector &V) { // Parse -flavor option. - if (V.size() > 1 && V[1] == StringRef("-flavor")) { + if (V.size() > 1 && V[1] == "-flavor") { if (V.size() <= 2) die("missing arg value for '-flavor'"); Flavor F = getFlavor(V[2]); if (F == Invalid) - die("Unknown flavor: " + StringRef(V[2])); + die("Unknown flavor: " + V[2]); V.erase(V.begin() + 1, V.begin() + 3); return F; } @@ -98,7 +98,10 @@ PrettyStackTraceProgram StackPrinter(Argc, Argv); llvm_shutdown_obj Shutdown; - std::vector Args(Argv, Argv + Argc); + std::vector Args; + Args.reserve(Argc); + for (int ArgId = 0; ArgId < Argc; ++ArgId) + Args.push_back(StringRef(Argv[ArgId])); switch (parseFlavor(Args)) { case Gnu: return !elf::link(Args); Index: lld/unittests/DriverTests/DarwinLdDriverTest.cpp =================================================================== --- lld/unittests/DriverTests/DarwinLdDriverTest.cpp +++ lld/unittests/DriverTests/DarwinLdDriverTest.cpp @@ -23,7 +23,7 @@ namespace lld { namespace mach_o { -bool parse(llvm::ArrayRef args, MachOLinkingContext &ctx, +bool parse(llvm::ArrayRef args, MachOLinkingContext &ctx, raw_ostream &diagnostics); } } @@ -40,7 +40,7 @@ llvm_unreachable("not handling other types of input files"); } - bool parse(std::vector args) { + bool parse(std::vector args) { args.insert(args.begin(), "ld"); std::string errorMessage; raw_string_ostream os(errorMessage); Index: llvm/include/llvm/LibDriver/LibDriver.h =================================================================== --- llvm/include/llvm/LibDriver/LibDriver.h +++ llvm/include/llvm/LibDriver/LibDriver.h @@ -16,9 +16,10 @@ #define LLVM_LIBDRIVER_LIBDRIVER_H namespace llvm { +class StringRef; template class ArrayRef; -int libDriverMain(ArrayRef ARgs); +int libDriverMain(ArrayRef ARgs); } #endif Index: llvm/include/llvm/Option/Arg.h =================================================================== --- llvm/include/llvm/Option/Arg.h +++ llvm/include/llvm/Option/Arg.h @@ -56,15 +56,15 @@ mutable unsigned OwnsValues : 1; /// \brief The argument values, as C strings. - SmallVector Values; + SmallVector Values; public: Arg(const Option Opt, StringRef Spelling, unsigned Index, const Arg *BaseArg = nullptr); - Arg(const Option Opt, StringRef Spelling, unsigned Index, - const char *Value0, const Arg *BaseArg = nullptr); - Arg(const Option Opt, StringRef Spelling, unsigned Index, - const char *Value0, const char *Value1, const Arg *BaseArg = nullptr); + Arg(const Option Opt, StringRef Spelling, unsigned Index, StringRef Value0, + const Arg *BaseArg = nullptr); + Arg(const Option Opt, StringRef Spelling, unsigned Index, StringRef Value0, + StringRef Value1, const Arg *BaseArg = nullptr); ~Arg(); const Option &getOption() const { return Opt; } @@ -89,12 +89,10 @@ void claim() const { getBaseArg().Claimed = true; } unsigned getNumValues() const { return Values.size(); } - const char *getValue(unsigned N = 0) const { - return Values[N]; - } + StringRef getValue(unsigned N = 0) const { return Values[N]; } - SmallVectorImpl &getValues() { return Values; } - const SmallVectorImpl &getValues() const { return Values; } + SmallVectorImpl &getValues() { return Values; } + const SmallVectorImpl &getValues() const { return Values; } bool containsValue(StringRef Value) const { for (unsigned i = 0, e = getNumValues(); i != e; ++i) Index: llvm/include/llvm/Option/ArgList.h =================================================================== --- llvm/include/llvm/Option/ArgList.h +++ llvm/include/llvm/Option/ArgList.h @@ -218,7 +218,7 @@ OptSpecifier Id6, OptSpecifier Id7) const; /// getArgString - Return the input argument string at \p Index. - virtual const char *getArgString(unsigned Index) const = 0; + virtual StringRef getArgString(unsigned Index) const = 0; /// getNumInputArgStrings - Return the number of original argument strings, /// which are guaranteed to be the first strings in the argument string @@ -299,16 +299,16 @@ /// Construct a constant string pointer whose /// lifetime will match that of the ArgList. - virtual const char *MakeArgStringRef(StringRef Str) const = 0; - const char *MakeArgString(const Twine &Str) const { + virtual StringRef MakeArgStringRef(StringRef Str) const = 0; + StringRef MakeArgString(const Twine &Str) const { SmallString<256> Buf; - return MakeArgStringRef(Str.toStringRef(Buf)); + return StringRef(MakeArgStringRef(Str.toStringRef(Buf))); } /// \brief Create an arg string for (\p LHS + \p RHS), reusing the /// string at \p Index if possible. - const char *GetOrMakeJoinedArgString(unsigned Index, StringRef LHS, - StringRef RHS) const; + StringRef GetOrMakeJoinedArgString(unsigned Index, StringRef LHS, + StringRef RHS) const; void print(raw_ostream &O) const; void dump() const; @@ -339,6 +339,7 @@ void releaseMemory(); public: + InputArgList(ArrayRef Args); InputArgList(const char* const *ArgBegin, const char* const *ArgEnd); InputArgList(InputArgList &&RHS) : ArgList(std::move(RHS)), ArgStrings(std::move(RHS.ArgStrings)), @@ -354,8 +355,8 @@ } ~InputArgList() { releaseMemory(); } - const char *getArgString(unsigned Index) const override { - return ArgStrings[Index]; + StringRef getArgString(unsigned Index) const override { + return StringRef(ArgStrings[Index]); } unsigned getNumInputArgStrings() const override { @@ -371,7 +372,7 @@ unsigned MakeIndex(StringRef String0, StringRef String1) const; using ArgList::MakeArgString; - const char *MakeArgStringRef(StringRef Str) const override; + StringRef MakeArgStringRef(StringRef Str) const override; /// @} }; @@ -388,7 +389,7 @@ /// Construct a new derived arg list from \p BaseArgs. DerivedArgList(const InputArgList &BaseArgs); - const char *getArgString(unsigned Index) const override { + StringRef getArgString(unsigned Index) const override { return BaseArgs.getArgString(Index); } @@ -408,7 +409,7 @@ void AddSynthesizedArg(Arg *A); using ArgList::MakeArgString; - const char *MakeArgStringRef(StringRef Str) const override; + StringRef MakeArgStringRef(StringRef Str) const override; /// AddFlagArg - Construct a new FlagArg for the given option \p Id and /// append it to the argument list. Index: llvm/include/llvm/Option/OptTable.h =================================================================== --- llvm/include/llvm/Option/OptTable.h +++ llvm/include/llvm/Option/OptTable.h @@ -88,9 +88,7 @@ const Option getOption(OptSpecifier Opt) const; /// \brief Lookup the name of the given option. - const char *getOptionName(OptSpecifier id) const { - return getInfo(id).Name; - } + StringRef getOptionName(OptSpecifier id) const { return getInfo(id).Name; } /// \brief Get the kind of the given option. unsigned getOptionKind(OptSpecifier id) const { @@ -149,7 +147,7 @@ /// is the default and means exclude nothing. /// \return An InputArgList; on error this will contain all the options /// which could be parsed. - InputArgList ParseArgs(ArrayRef Args, unsigned &MissingArgIndex, + InputArgList ParseArgs(ArrayRef Args, unsigned &MissingArgIndex, unsigned &MissingArgCount, unsigned FlagsToInclude = 0, unsigned FlagsToExclude = 0) const; @@ -161,12 +159,12 @@ /// \param FlagsToInclude - If non-zero, only include options with any /// of these flags set. /// \param FlagsToExclude - Exclude options with any of these flags set. - void PrintHelp(raw_ostream &OS, const char *Name, - const char *Title, unsigned FlagsToInclude, + void PrintHelp(raw_ostream &OS, StringRef Name, + StringRef Title, unsigned FlagsToInclude, unsigned FlagsToExclude) const; - void PrintHelp(raw_ostream &OS, const char *Name, - const char *Title, bool ShowHidden = false) const; + void PrintHelp(raw_ostream &OS, StringRef Name, + StringRef Title, bool ShowHidden = false) const; }; } // end namespace opt } // end namespace llvm Index: llvm/include/llvm/Option/Option.h =================================================================== --- llvm/include/llvm/Option/Option.h +++ llvm/include/llvm/Option/Option.h @@ -20,7 +20,7 @@ class Arg; class ArgList; /// ArgStringList - Type used for constructing argv lists for subprocesses. -typedef SmallVector ArgStringList; +typedef SmallVector ArgStringList; /// Base flags for all options. Custom flags may be added after. enum DriverFlag { @@ -117,7 +117,7 @@ /// \brief Get the default prefix for this option. StringRef getPrefix() const { const char *Prefix = *Info->Prefixes; - return Prefix ? Prefix : StringRef(); + return Prefix ? StringRef(Prefix) : StringRef(); } /// \brief Get the name of this option with the default prefix. Index: llvm/include/llvm/Support/CommandLine.h =================================================================== --- llvm/include/llvm/Support/CommandLine.h +++ llvm/include/llvm/Support/CommandLine.h @@ -49,6 +49,9 @@ bool ParseCommandLineOptions(int argc, const char *const *argv, StringRef Overview = "", bool IgnoreErrors = false); +bool ParseCommandLineOptions(int argc, ArrayRef argv, + StringRef Overview = "", + bool IgnoreErrors = false); //===----------------------------------------------------------------------===// // ParseEnvironmentOptions - Environment variable option processing alternate @@ -1766,7 +1769,7 @@ /// lines and end of the response file to be marked with a nullptr string. /// \param [out] NewArgv All parsed strings are appended to NewArgv. void TokenizeGNUCommandLine(StringRef Source, StringSaver &Saver, - SmallVectorImpl &NewArgv, + SmallVectorImpl &NewArgv, bool MarkEOLs = false); /// \brief Tokenizes a Windows command line which may contain quotes and escaped @@ -1781,13 +1784,13 @@ /// lines and end of the response file to be marked with a nullptr string. /// \param [out] NewArgv All parsed strings are appended to NewArgv. void TokenizeWindowsCommandLine(StringRef Source, StringSaver &Saver, - SmallVectorImpl &NewArgv, + SmallVectorImpl &NewArgv, bool MarkEOLs = false); /// \brief String tokenization function type. Should be compatible with either /// Windows or Unix command line tokenizers. typedef void (*TokenizerCallback)(StringRef Source, StringSaver &Saver, - SmallVectorImpl &NewArgv, + SmallVectorImpl &NewArgv, bool MarkEOLs); /// \brief Expand response files on a command line recursively using the given @@ -1805,7 +1808,7 @@ /// with nullptrs in the Argv vector. /// \return true if all @files were expanded successfully or there were none. bool ExpandResponseFiles(StringSaver &Saver, TokenizerCallback Tokenizer, - SmallVectorImpl &Argv, + SmallVectorImpl &Argv, bool MarkEOLs = false); /// \brief Mark all options not part of this category as cl::ReallyHidden. Index: llvm/include/llvm/Support/Process.h =================================================================== --- llvm/include/llvm/Support/Process.h +++ llvm/include/llvm/Support/Process.h @@ -87,7 +87,7 @@ /// the operating system to the program. This function expects to be handed /// the vector passed in from main. static std::error_code - GetArgumentVector(SmallVectorImpl &Args, + GetArgumentVector(SmallVectorImpl &Args, ArrayRef ArgsFromMain, SpecificBumpPtrAllocator &ArgAllocator); Index: llvm/include/llvm/Support/Program.h =================================================================== --- llvm/include/llvm/Support/Program.h +++ llvm/include/llvm/Support/Program.h @@ -132,7 +132,8 @@ /// Return true if the given arguments fit within system-specific /// argument length limits. - bool commandLineFitsWithinSystemLimits(StringRef Program, ArrayRef Args); + bool commandLineFitsWithinSystemLimits(StringRef Program, + ArrayRef Args); /// File encoding options when writing contents that a non-UTF8 tool will /// read (on Windows systems). For UNIX, we always use UTF-8. Index: llvm/lib/LibDriver/LibDriver.cpp =================================================================== --- llvm/lib/LibDriver/LibDriver.cpp +++ llvm/lib/LibDriver/LibDriver.cpp @@ -99,8 +99,8 @@ return Optional(); } -int llvm::libDriverMain(llvm::ArrayRef ArgsArr) { - SmallVector NewArgs(ArgsArr.begin(), ArgsArr.end()); +int llvm::libDriverMain(llvm::ArrayRef ArgsArr) { + SmallVector NewArgs(ArgsArr.begin(), ArgsArr.end()); BumpPtrAllocator Alloc; StringSaver Saver(Alloc); cl::ExpandResponseFiles(Saver, cl::TokenizeWindowsCommandLine, NewArgs); @@ -109,8 +109,12 @@ LibOptTable Table; unsigned MissingIndex; unsigned MissingCount; + SmallVector ArgsStr; + for (auto Arg : ArgsArr.slice(1)) + ArgsStr.push_back(Arg); + llvm::opt::InputArgList Args = - Table.ParseArgs(ArgsArr.slice(1), MissingIndex, MissingCount); + Table.ParseArgs(ArgsStr, MissingIndex, MissingCount); if (MissingCount) { llvm::errs() << "missing arg value for \"" << Args.getArgString(MissingIndex) << "\", expected " Index: llvm/lib/Option/Arg.cpp =================================================================== --- llvm/lib/Option/Arg.cpp +++ llvm/lib/Option/Arg.cpp @@ -22,15 +22,15 @@ : Opt(Opt), BaseArg(BaseArg), Spelling(S), Index(Index), Claimed(false), OwnsValues(false) {} -Arg::Arg(const Option Opt, StringRef S, unsigned Index, const char *Value0, +Arg::Arg(const Option Opt, StringRef S, unsigned Index, StringRef Value0, const Arg *BaseArg) : Opt(Opt), BaseArg(BaseArg), Spelling(S), Index(Index), Claimed(false), OwnsValues(false) { Values.push_back(Value0); } -Arg::Arg(const Option Opt, StringRef S, unsigned Index, const char *Value0, - const char *Value1, const Arg *BaseArg) +Arg::Arg(const Option Opt, StringRef S, unsigned Index, StringRef Value0, + StringRef Value1, const Arg *BaseArg) : Opt(Opt), BaseArg(BaseArg), Spelling(S), Index(Index), Claimed(false), OwnsValues(false) { Values.push_back(Value0); @@ -40,7 +40,7 @@ Arg::~Arg() { if (OwnsValues) { for (unsigned i = 0, e = Values.size(); i != e; ++i) - delete[] Values[i]; + delete[] Values[i].data(); } } @@ -84,14 +84,15 @@ render(Args, Output); return; } - - Output.append(Values.begin(), Values.end()); + for (auto Val : Values) + Output.push_back(Val); } void Arg::render(const ArgList &Args, ArgStringList &Output) const { switch (getOption().getRenderStyle()) { case Option::RenderValuesStyle: - Output.append(Values.begin(), Values.end()); + for (auto Val : Values) + Output.push_back(Val); break; case Option::RenderCommaJoinedStyle: { Index: llvm/lib/Option/ArgList.cpp =================================================================== --- llvm/lib/Option/ArgList.cpp +++ llvm/lib/Option/ArgList.cpp @@ -239,7 +239,7 @@ } std::vector ArgList::getAllArgValues(OptSpecifier Id) const { - SmallVector Values; + SmallVector Values; AddAllArgValues(Values, Id); return std::vector(Values.begin(), Values.end()); } @@ -303,8 +303,8 @@ OptSpecifier Id1, OptSpecifier Id2) const { for (auto Arg : filtered(Id0, Id1, Id2)) { Arg->claim(); - const auto &Values = Arg->getValues(); - Output.append(Values.begin(), Values.end()); + for (auto &Value : Arg->getValues()) + Output.push_back(Value); } } @@ -315,8 +315,8 @@ Arg->claim(); if (Joined) { - Output.push_back(MakeArgString(StringRef(Translation) + - Arg->getValue(0))); + Output.push_back( + MakeArgString(StringRef(Translation) + Arg->getValue(0))); } else { Output.push_back(Translation); Output.push_back(Arg->getValue(0)); @@ -335,10 +335,9 @@ (*it)->claim(); } -const char *ArgList::GetOrMakeJoinedArgString(unsigned Index, - StringRef LHS, - StringRef RHS) const { - StringRef Cur = getArgString(Index); +StringRef ArgList::GetOrMakeJoinedArgString(unsigned Index, StringRef LHS, + StringRef RHS) const { + StringRef Cur(getArgString(Index)); if (Cur.size() == LHS.size() + RHS.size() && Cur.startswith(LHS) && Cur.endswith(RHS)) return Cur.data(); @@ -363,6 +362,11 @@ delete A; } +InputArgList::InputArgList(ArrayRef Args) + : NumInputArgStrings(Args.size()) { + ArgStrings.append(Args.begin(), Args.end()); +} + InputArgList::InputArgList(const char* const *ArgBegin, const char* const *ArgEnd) : NumInputArgStrings(ArgEnd - ArgBegin) { @@ -388,7 +392,7 @@ return Index0; } -const char *InputArgList::MakeArgStringRef(StringRef Str) const { +StringRef InputArgList::MakeArgStringRef(StringRef Str) const { return getArgString(MakeIndex(Str)); } @@ -397,7 +401,7 @@ DerivedArgList::DerivedArgList(const InputArgList &BaseArgs) : BaseArgs(BaseArgs) {} -const char *DerivedArgList::MakeArgStringRef(StringRef Str) const { +StringRef DerivedArgList::MakeArgStringRef(StringRef Str) const { return BaseArgs.MakeArgString(Str); } @@ -435,6 +439,6 @@ unsigned Index = BaseArgs.MakeIndex((Opt.getName() + Value).str()); SynthesizedArgs.push_back(make_unique( Opt, MakeArgString(Opt.getPrefix() + Opt.getName()), Index, - BaseArgs.getArgString(Index) + Opt.getName().size(), BaseArg)); + BaseArgs.getArgString(Index).drop_front(Opt.getName().size()), BaseArg)); return SynthesizedArgs.back().get(); } Index: llvm/lib/Option/OptTable.cpp =================================================================== --- llvm/lib/Option/OptTable.cpp +++ llvm/lib/Option/OptTable.cpp @@ -27,9 +27,9 @@ // Ordering on Info. The ordering is *almost* case-insensitive lexicographic, // with an exceptions. '\0' comes at the end of the alphabet instead of the // beginning (thus options precede any other options which prefix them). -static int StrCmpOptionNameIgnoreCase(const char *A, const char *B) { - const char *X = A, *Y = B; - char a = tolower(*A), b = tolower(*B); +static int StrCmpOptionNameIgnoreCase(StringRef A, StringRef B) { + const char *X = A.data(), *Y = B.data(); + char a = tolower(*X), b = tolower(*Y); while (a == b) { if (a == '\0') return 0; @@ -48,10 +48,10 @@ } #ifndef NDEBUG -static int StrCmpOptionName(const char *A, const char *B) { +static int StrCmpOptionName(StringRef A, StringRef B) { if (int N = StrCmpOptionNameIgnoreCase(A, B)) return N; - return strcmp(A, B); + return A.compare(B); } static inline bool operator<(const OptTable::Info &A, const OptTable::Info &B) { @@ -132,7 +132,7 @@ i != e; ++i) { if (const char *const *P = getInfo(i).Prefixes) { for (; *P != nullptr; ++P) { - PrefixesUnion.insert(*P); + PrefixesUnion.insert(StringRef(*P)); } } } @@ -190,7 +190,7 @@ unsigned FlagsToInclude, unsigned FlagsToExclude) const { unsigned Prev = Index; - const char *Str = Args.getArgString(Index); + auto Str = Args.getArgString(Index); // Anything that doesn't start with PrefixesUnion is an input, as is '-' // itself. @@ -229,8 +229,9 @@ continue; // See if this option matches. - if (Arg *A = Opt.accept(Args, Index, ArgSize)) + if (Arg *A = Opt.accept(Args, Index, ArgSize)) { return A; + } // Otherwise, see if this argument was missing values. if (Prev != Index) @@ -245,12 +246,12 @@ return new Arg(getOption(TheUnknownOptionID), Str, Index++, Str); } -InputArgList OptTable::ParseArgs(ArrayRef ArgArr, +InputArgList OptTable::ParseArgs(ArrayRef ArgArr, unsigned &MissingArgIndex, unsigned &MissingArgCount, unsigned FlagsToInclude, unsigned FlagsToExclude) const { - InputArgList Args(ArgArr.begin(), ArgArr.end()); + InputArgList Args(ArgArr); // FIXME: Handle '@' args (or at least error on them). @@ -258,7 +259,7 @@ unsigned Index = 0, End = ArgArr.size(); while (Index < End) { // Ingore nullptrs, they are response file's EOL markers - if (Args.getArgString(Index) == nullptr) { + if (Args.getArgString(Index).empty()) { ++Index; continue; } @@ -381,14 +382,14 @@ return getOptionHelpGroup(Opts, GroupID); } -void OptTable::PrintHelp(raw_ostream &OS, const char *Name, const char *Title, +void OptTable::PrintHelp(raw_ostream &OS, StringRef Name, StringRef Title, bool ShowHidden) const { PrintHelp(OS, Name, Title, /*Include*/ 0, /*Exclude*/ (ShowHidden ? 0 : HelpHidden)); } -void OptTable::PrintHelp(raw_ostream &OS, const char *Name, const char *Title, +void OptTable::PrintHelp(raw_ostream &OS, StringRef Name, StringRef Title, unsigned FlagsToInclude, unsigned FlagsToExclude) const { OS << "OVERVIEW: " << Title << "\n"; Index: llvm/lib/Option/Option.cpp =================================================================== --- llvm/lib/Option/Option.cpp +++ llvm/lib/Option/Option.cpp @@ -108,7 +108,8 @@ StringRef Spelling; // If the option was an alias, get the spelling from the unaliased one. if (getID() == UnaliasedOption.getID()) { - Spelling = StringRef(Args.getArgString(Index), ArgSize); + assert(ArgSize <= Args.getArgString(Index).size() && "Overflow!"); + Spelling = StringRef(Args.getArgString(Index).data(), ArgSize); } else { Spelling = Args.MakeArgString(Twine(UnaliasedOption.getPrefix()) + Twine(UnaliasedOption.getName())); @@ -116,17 +117,18 @@ switch (getKind()) { case FlagClass: { - if (ArgSize != strlen(Args.getArgString(Index))) + if (ArgSize != Args.getArgString(Index).size()) return nullptr; Arg *A = new Arg(UnaliasedOption, Spelling, Index++); if (getAliasArgs()) { const char *Val = getAliasArgs(); while (*Val != '\0') { - A->getValues().push_back(Val); + StringRef ValStr(Val); + A->getValues().push_back(ValStr); // Move past the '\0' to the next argument. - Val += strlen(Val) + 1; + Val += ValStr.size() + 1; } } @@ -137,12 +139,12 @@ return A; } case JoinedClass: { - const char *Value = Args.getArgString(Index) + ArgSize; + StringRef Value = Args.getArgString(Index).drop_front(ArgSize); return new Arg(UnaliasedOption, Spelling, Index++, Value); } case CommaJoinedClass: { // Always matches. - const char *Str = Args.getArgString(Index) + ArgSize; + const char *Str = Args.getArgString(Index).drop_front(ArgSize).data(); Arg *A = new Arg(UnaliasedOption, Spelling, Index++); // Parse out the comma separated values. @@ -155,7 +157,7 @@ char *Value = new char[Str - Prev + 1]; memcpy(Value, Prev, Str - Prev); Value[Str - Prev] = '\0'; - A->getValues().push_back(Value); + A->getValues().push_back(StringRef(Value, Str - Prev)); } if (!c) @@ -170,21 +172,19 @@ } case SeparateClass: // Matches iff this is an exact match. - // FIXME: Avoid strlen. - if (ArgSize != strlen(Args.getArgString(Index))) + if (ArgSize != Args.getArgString(Index).size()) return nullptr; Index += 2; if (Index > Args.getNumInputArgStrings() || - Args.getArgString(Index - 1) == nullptr) + Args.getArgString(Index - 1).empty()) return nullptr; return new Arg(UnaliasedOption, Spelling, Index - 2, Args.getArgString(Index - 1)); case MultiArgClass: { // Matches iff this is an exact match. - // FIXME: Avoid strlen. - if (ArgSize != strlen(Args.getArgString(Index))) + if (ArgSize != Args.getArgString(Index).size()) return nullptr; Index += 1 + getNumArgs(); @@ -199,16 +199,15 @@ } case JoinedOrSeparateClass: { // If this is not an exact match, it is a joined arg. - // FIXME: Avoid strlen. - if (ArgSize != strlen(Args.getArgString(Index))) { - const char *Value = Args.getArgString(Index) + ArgSize; + if (ArgSize != Args.getArgString(Index).size()) { + auto Value = Args.getArgString(Index).drop_front(ArgSize); return new Arg(*this, Spelling, Index++, Value); } // Otherwise it must be separate. Index += 2; if (Index > Args.getNumInputArgStrings() || - Args.getArgString(Index - 1) == nullptr) + Args.getArgString(Index - 1).empty()) return nullptr; return new Arg(UnaliasedOption, Spelling, @@ -218,32 +217,31 @@ // Always matches. Index += 2; if (Index > Args.getNumInputArgStrings() || - Args.getArgString(Index - 1) == nullptr) + Args.getArgString(Index - 1).empty()) return nullptr; return new Arg(UnaliasedOption, Spelling, Index - 2, - Args.getArgString(Index - 2) + ArgSize, + Args.getArgString(Index - 2).drop_front(ArgSize), Args.getArgString(Index - 1)); case RemainingArgsClass: { // Matches iff this is an exact match. - // FIXME: Avoid strlen. - if (ArgSize != strlen(Args.getArgString(Index))) + if (ArgSize != Args.getArgString(Index).size()) return nullptr; Arg *A = new Arg(UnaliasedOption, Spelling, Index++); while (Index < Args.getNumInputArgStrings() && - Args.getArgString(Index) != nullptr) + !Args.getArgString(Index).empty()) A->getValues().push_back(Args.getArgString(Index++)); return A; } case RemainingArgsJoinedClass: { Arg *A = new Arg(UnaliasedOption, Spelling, Index); - if (ArgSize != strlen(Args.getArgString(Index))) { + if (ArgSize != Args.getArgString(Index).size()) { // An inexact match means there is a joined arg. - A->getValues().push_back(Args.getArgString(Index) + ArgSize); + A->getValues().push_back(Args.getArgString(Index).drop_front(ArgSize)); } Index++; while (Index < Args.getNumInputArgStrings() && - Args.getArgString(Index) != nullptr) + !Args.getArgString(Index).empty()) A->getValues().push_back(Args.getArgString(Index++)); return A; } Index: llvm/lib/Support/CommandLine.cpp =================================================================== --- llvm/lib/Support/CommandLine.cpp +++ llvm/lib/Support/CommandLine.cpp @@ -112,6 +112,9 @@ bool ParseCommandLineOptions(int argc, const char *const *argv, StringRef Overview, bool IgnoreErrors); + bool ParseCommandLineOptions(int argc, ArrayRef argv, + StringRef Overview = "", + bool IgnoreErrors = false); void addLiteralOption(Option &Opt, SubCommand *SC, StringRef Name) { if (Opt.hasArgStr()) @@ -528,7 +531,7 @@ /// don't allow a value (-foo) the former is rejected (-foo=). static inline bool ProvideOption(Option *Handler, StringRef ArgName, StringRef Value, int argc, - const char *const *argv, int &i) { + ArrayRef argv, int &i) { // Is this a multi-argument option? unsigned NumAdditionalVals = Handler->getNumAdditionalVals(); @@ -539,7 +542,7 @@ if (i + 1 >= argc) return Handler->error("requires a value!"); // Steal the next argument, like for '-o filename' - assert(argv && "null check"); + assert((unsigned)i < argv.size() && "bound check"); Value = StringRef(argv[++i]); } break; @@ -573,7 +576,7 @@ while (NumAdditionalVals > 0) { if (i + 1 >= argc) return Handler->error("not enough values!"); - assert(argv && "null check"); + assert((unsigned)i < argv.size() && "bound check"); Value = StringRef(argv[++i]); if (CommaSeparateAndAddOccurrence(Handler, i, ArgName, Value, MultiArg)) @@ -586,7 +589,7 @@ static bool ProvidePositionalOption(Option *Handler, StringRef Arg, int i) { int Dummy = i; - return ProvideOption(Handler, Handler->ArgStr, Arg, 0, nullptr, Dummy); + return ProvideOption(Handler, Handler->ArgStr, Arg, 0, StringRef(), Dummy); } // Option predicates... @@ -666,7 +669,7 @@ "Option can not be cl::Grouping AND cl::ValueRequired!"); int Dummy = 0; ErrorParsing |= - ProvideOption(PGOpt, OneArgName, StringRef(), 0, nullptr, Dummy); + ProvideOption(PGOpt, OneArgName, StringRef(), 0, StringRef(), Dummy); // Get the next grouping option. PGOpt = getOptionPred(Arg, Length, isGrouping, OptionsMap); @@ -691,7 +694,7 @@ static bool isQuote(char C) { return C == '\"' || C == '\''; } void cl::TokenizeGNUCommandLine(StringRef Src, StringSaver &Saver, - SmallVectorImpl &NewArgv, + SmallVectorImpl &NewArgv, bool MarkEOLs) { SmallString<128> Token; for (size_t I = 0, E = Src.size(); I != E; ++I) { @@ -700,7 +703,7 @@ while (I != E && isWhitespace(Src[I])) { // Mark the end of lines in response files if (MarkEOLs && Src[I] == '\n') - NewArgv.push_back(nullptr); + NewArgv.push_back(StringRef()); ++I; } if (I == E) @@ -746,7 +749,7 @@ NewArgv.push_back(Saver.save(StringRef(Token)).data()); // Mark the end of response files if (MarkEOLs) - NewArgv.push_back(nullptr); + NewArgv.push_back(StringRef()); } /// Backslashes are interpreted in a rather complicated way in the Windows-style @@ -788,7 +791,7 @@ } void cl::TokenizeWindowsCommandLine(StringRef Src, StringSaver &Saver, - SmallVectorImpl &NewArgv, + SmallVectorImpl &NewArgv, bool MarkEOLs) { SmallString<128> Token; @@ -802,7 +805,7 @@ if (isWhitespace(Src[I])) { // Mark the end of lines in response files if (MarkEOLs && Src[I] == '\n') - NewArgv.push_back(nullptr); + NewArgv.push_back(StringRef()); continue; } if (Src[I] == '"') { @@ -829,7 +832,7 @@ State = INIT; // Mark the end of lines in response files if (MarkEOLs && Src[I] == '\n') - NewArgv.push_back(nullptr); + NewArgv.push_back(StringRef()); continue; } if (Src[I] == '"') { @@ -862,7 +865,7 @@ NewArgv.push_back(Saver.save(StringRef(Token)).data()); // Mark the end of response files if (MarkEOLs) - NewArgv.push_back(nullptr); + NewArgv.push_back(StringRef()); } // It is called byte order marker but the UTF-8 BOM is actually not affected @@ -871,9 +874,9 @@ return (S.size() >= 3 && S[0] == '\xef' && S[1] == '\xbb' && S[2] == '\xbf'); } -static bool ExpandResponseFile(const char *FName, StringSaver &Saver, +static bool ExpandResponseFile(StringRef FName, StringSaver &Saver, TokenizerCallback Tokenizer, - SmallVectorImpl &NewArgv, + SmallVectorImpl &NewArgv, bool MarkEOLs = false) { ErrorOr> MemBufOrErr = MemoryBuffer::getFile(FName); @@ -905,16 +908,15 @@ /// \brief Expand response files on a command line recursively using the given /// StringSaver and tokenization strategy. bool cl::ExpandResponseFiles(StringSaver &Saver, TokenizerCallback Tokenizer, - SmallVectorImpl &Argv, - bool MarkEOLs) { + SmallVectorImpl &Argv, bool MarkEOLs) { unsigned RspFiles = 0; bool AllExpanded = true; // Don't cache Argv.size() because it can change. for (unsigned I = 0; I != Argv.size();) { - const char *Arg = Argv[I]; + StringRef Arg = Argv[I]; // Check if it is an EOL marker - if (Arg == nullptr) { + if (Arg.empty()) { ++I; continue; } @@ -932,8 +934,8 @@ // contents. Nested response files are expanded in subsequent iterations. // FIXME: If a nested response file uses a relative path, is it relative to // the cwd of the process or the response file? - SmallVector ExpandedArgv; - if (!ExpandResponseFile(Arg + 1, Saver, Tokenizer, ExpandedArgv, + SmallVector ExpandedArgv; + if (!ExpandResponseFile(Arg.drop_front(1), Saver, Tokenizer, ExpandedArgv, MarkEOLs)) { // We couldn't read this file, so we leave it in the argument stream and // move on. @@ -965,7 +967,7 @@ // Get program's "name", which we wouldn't know without the caller // telling us. - SmallVector newArgv; + SmallVector newArgv; BumpPtrAllocator A; StringSaver Saver(A); newArgv.push_back(Saver.save(progName).data()); @@ -974,7 +976,8 @@ // and hand it off to ParseCommandLineOptions(). TokenizeGNUCommandLine(*envValue, Saver, newArgv); int newArgc = static_cast(newArgv.size()); - ParseCommandLineOptions(newArgc, &newArgv[0], StringRef(Overview)); + + ParseCommandLineOptions(newArgc, newArgv, StringRef(Overview)); } bool cl::ParseCommandLineOptions(int argc, const char *const *argv, @@ -983,6 +986,12 @@ IgnoreErrors); } +bool cl::ParseCommandLineOptions(int argc, ArrayRef argv, + StringRef Overview, bool IgnoreErrors) { + return GlobalParser->ParseCommandLineOptions(argc, argv, Overview, + IgnoreErrors); +} + void CommandLineParser::ResetAllOptionOccurrences() { // So that we can parse different command lines multiple times in succession // we reset all option values to look like they have never been seen before. @@ -996,14 +1005,26 @@ const char *const *argv, StringRef Overview, bool IgnoreErrors) { + SmallVector Args; + Args.reserve(argc); + for (int ArgId = 0; ArgId < argc; ArgId++) + Args.push_back(StringRef(argv[ArgId])); + return ParseCommandLineOptions(argc, Args, Overview, IgnoreErrors); +} + +bool CommandLineParser::ParseCommandLineOptions(int argc, + ArrayRef argv, + StringRef Overview, + bool IgnoreErrors) { assert(hasOptions() && "No options specified!"); // Expand response files. - SmallVector newArgv(argv, argv + argc); + SmallVector newArgv; + newArgv.append(argv.begin(), argv.end()); BumpPtrAllocator A; StringSaver Saver(A); ExpandResponseFiles(Saver, TokenizeGNUCommandLine, newArgv); - argv = &newArgv[0]; + argv = newArgv; argc = static_cast(newArgv.size()); // Copy the program name into ProgName, making sure not to overflow it. @@ -1020,7 +1041,7 @@ int FirstArg = 1; SubCommand *ChosenSubCommand = &*TopLevelSubCommand; - if (argc >= 2 && argv[FirstArg][0] != '-') { + if (argc >= 2 && !argv[FirstArg].startswith("-")) { // If the first argument specifies a valid subcommand, start processing // options from the second argument. ChosenSubCommand = LookupSubCommand(StringRef(argv[FirstArg])); @@ -1101,7 +1122,7 @@ // considered to be positional if it doesn't start with '-', if it is "-" // itself, or if we have seen "--" already. // - if (argv[i][0] != '-' || argv[i][1] == 0 || DashDashFound) { + if (!argv[i].startswith("-") || argv[i].size() == 1 || DashDashFound) { // Positional argument! if (ActivePositionalArg) { ProvidePositionalOption(ActivePositionalArg, StringRef(argv[i]), i); @@ -1123,8 +1144,7 @@ // Delay processing positional arguments until the end... continue; } - } else if (argv[i][0] == '-' && argv[i][1] == '-' && argv[i][2] == 0 && - !DashDashFound) { + } else if (argv[i] == "--" && !DashDashFound) { DashDashFound = true; // This is the mythical "--"? continue; // Don't try to process it as an argument itself. } else if (ActivePositionalArg && @@ -1132,7 +1152,7 @@ // If there is a positional argument eating options, check to see if this // option is another positional argument. If so, treat it as an argument, // otherwise feed it to the eating positional. - ArgName = StringRef(argv[i] + 1); + ArgName = argv[i].drop_front(1); // Eat leading dashes. while (!ArgName.empty() && ArgName[0] == '-') ArgName = ArgName.substr(1); @@ -1144,7 +1164,7 @@ } } else { // We start with a '-', must be an argument. - ArgName = StringRef(argv[i] + 1); + ArgName = argv[i].drop_front(1); // Eat leading dashes. while (!ArgName.empty() && ArgName[0] == '-') ArgName = ArgName.substr(1); Index: llvm/lib/Support/Unix/Process.inc =================================================================== --- llvm/lib/Support/Unix/Process.inc +++ llvm/lib/Support/Unix/Process.inc @@ -182,10 +182,12 @@ } std::error_code -Process::GetArgumentVector(SmallVectorImpl &ArgsOut, +Process::GetArgumentVector(SmallVectorImpl &ArgsOut, ArrayRef ArgsIn, SpecificBumpPtrAllocator &) { - ArgsOut.append(ArgsIn.begin(), ArgsIn.end()); + ArgsOut.reserve(ArgsIn.size()); + for (auto Arg : ArgsIn) + ArgsOut.push_back(Arg); return std::error_code(); } Index: llvm/lib/Support/Unix/Program.inc =================================================================== --- llvm/lib/Support/Unix/Program.inc +++ llvm/lib/Support/Unix/Program.inc @@ -446,7 +446,7 @@ return EC; } -bool llvm::sys::commandLineFitsWithinSystemLimits(StringRef Program, ArrayRef Args) { +bool llvm::sys::commandLineFitsWithinSystemLimits(StringRef Program, ArrayRef Args) { static long ArgMax = sysconf(_SC_ARG_MAX); // System says no practical limit. @@ -457,9 +457,9 @@ long HalfArgMax = ArgMax / 2; size_t ArgLength = Program.size() + 1; - for (ArrayRef::iterator I = Args.begin(), E = Args.end(); + for (auto I = Args.begin(), E = Args.end(); I != E; ++I) { - ArgLength += strlen(*I) + 1; + ArgLength += I->size() + 1; if (ArgLength > size_t(HalfArgMax)) { return false; } Index: llvm/lib/Support/Windows/Process.inc =================================================================== --- llvm/lib/Support/Windows/Process.inc +++ llvm/lib/Support/Windows/Process.inc @@ -159,17 +159,17 @@ } static void AllocateAndPush(const SmallVectorImpl &S, - SmallVectorImpl &Vector, + SmallVectorImpl &Vector, SpecificBumpPtrAllocator &Allocator) { char *Buffer = Allocator.Allocate(S.size() + 1); ::memcpy(Buffer, S.data(), S.size()); Buffer[S.size()] = '\0'; - Vector.push_back(Buffer); + Vector.push_back(StringRef(Buffer, S.size())); } /// Convert Arg from UTF-16 to UTF-8 and push it onto Args. static std::error_code -ConvertAndPushArg(const wchar_t *Arg, SmallVectorImpl &Args, +ConvertAndPushArg(const wchar_t *Arg, SmallVectorImpl &Args, SpecificBumpPtrAllocator &Allocator) { SmallVector ArgString; if (std::error_code ec = windows::UTF16ToUTF8(Arg, wcslen(Arg), ArgString)) @@ -181,7 +181,7 @@ /// \brief Perform wildcard expansion of Arg, or just push it into Args if it /// doesn't have wildcards or doesn't match any files. static std::error_code -WildcardExpand(const wchar_t *Arg, SmallVectorImpl &Args, +WildcardExpand(const wchar_t *Arg, SmallVectorImpl &Args, SpecificBumpPtrAllocator &Allocator) { if (!wcspbrk(Arg, L"*?")) { // Arg does not contain any wildcard characters. This is the common case. @@ -229,7 +229,7 @@ } static std::error_code -ExpandShortFileName(const wchar_t *Arg, SmallVectorImpl &Args, +ExpandShortFileName(const wchar_t *Arg, SmallVectorImpl &Args, SpecificBumpPtrAllocator &Allocator) { SmallVector LongPath; DWORD Length = GetLongPathNameW(Arg, LongPath.data(), LongPath.capacity()); @@ -246,7 +246,7 @@ } std::error_code -Process::GetArgumentVector(SmallVectorImpl &Args, +Process::GetArgumentVector(SmallVectorImpl &Args, ArrayRef, SpecificBumpPtrAllocator &ArgAllocator) { int ArgCount; Index: llvm/lib/Support/Windows/Program.inc =================================================================== --- llvm/lib/Support/Windows/Program.inc +++ llvm/lib/Support/Windows/Program.inc @@ -535,16 +535,16 @@ return EC; } -bool llvm::sys::commandLineFitsWithinSystemLimits(StringRef Program, ArrayRef Args) { +bool llvm::sys::commandLineFitsWithinSystemLimits(StringRef Program, ArrayRef Args) { // The documented max length of the command line passed to CreateProcess. static const size_t MaxCommandStringLength = 32768; // Account for the trailing space for the program path and the // trailing NULL of the last argument. size_t ArgLength = ArgLenWithQuotes(Program.str().c_str()) + 2; - for (ArrayRef::iterator I = Args.begin(), E = Args.end(); + for (auto I = Args.begin(), E = Args.end(); I != E; ++I) { // Account for the trailing space for every arg - ArgLength += ArgLenWithQuotes(*I) + 1; + ArgLength += ArgLenWithQuotes(I->str().c_str()) + 1; if (ArgLength > MaxCommandStringLength) { return false; } Index: llvm/tools/llvm-ar/llvm-ar.cpp =================================================================== --- llvm/tools/llvm-ar/llvm-ar.cpp +++ llvm/tools/llvm-ar/llvm-ar.cpp @@ -845,8 +845,13 @@ StringRef Stem = sys::path::stem(ToolName); if (Stem.find("ranlib") == StringRef::npos && - Stem.find("lib") != StringRef::npos) - return libDriverMain(makeArrayRef(argv, argc)); + Stem.find("lib") != StringRef::npos) { + SmallVector Args; + for (int ArgId = 0; ArgId < argc; ArgId++) { + Args.push_back(StringRef(argv[ArgId])); + } + return libDriverMain(Args); + } // Have the command line options parsed and handle things // like --help and --version. Index: llvm/tools/llvm-pdbdump/llvm-pdbdump.cpp =================================================================== --- llvm/tools/llvm-pdbdump/llvm-pdbdump.cpp +++ llvm/tools/llvm-pdbdump/llvm-pdbdump.cpp @@ -529,14 +529,14 @@ ExitOnErr.setBanner("llvm-pdbdump: "); - SmallVector argv; + SmallVector argv; SpecificBumpPtrAllocator ArgAllocator; ExitOnErr(errorCodeToError(sys::Process::GetArgumentVector( argv, makeArrayRef(argv_, argc_), ArgAllocator))); llvm_shutdown_obj Y; // Call llvm_shutdown() on exit. - cl::ParseCommandLineOptions(argv.size(), argv.data(), "LLVM PDB Dumper\n"); + cl::ParseCommandLineOptions(argv.size(), argv, "LLVM PDB Dumper\n"); if (!opts::raw::DumpBlockRangeOpt.empty()) { llvm::Regex R("^([0-9]+)(-([0-9]+))?$"); llvm::SmallVector Matches; Index: llvm/unittests/Option/OptionParsingTest.cpp =================================================================== --- llvm/unittests/Option/OptionParsingTest.cpp +++ llvm/unittests/Option/OptionParsingTest.cpp @@ -52,17 +52,8 @@ }; } -const char *Args[] = { - "-A", - "-Bhi", - "--C=desu", - "-C", "bye", - "-D,adena", - "-E", "apple", "bloom", - "-Fblarg", - "-F", "42", - "-Gchuu", "2" - }; +StringRef Args[] = {"-A", "-Bhi", "--C=desu", "-C", "bye", "-D,adena", "-E", + "apple", "bloom", "-Fblarg", "-F", "42", "-Gchuu", "2"}; TEST(Option, OptionParsing) { TestOptTable T; @@ -127,7 +118,7 @@ EXPECT_FALSE(AL.hasArg(OPT_C)); EXPECT_TRUE(AL.hasArg(OPT_SLASH_C)); - const char *NewArgs[] = { "/C", "foo", "--C=bar" }; + StringRef NewArgs[] = {"/C", "foo", "--C=bar"}; AL = T.ParseArgs(NewArgs, MAI, MAC); EXPECT_TRUE(AL.hasArg(OPT_SLASH_C)); EXPECT_TRUE(AL.hasArg(OPT_C)); @@ -139,7 +130,7 @@ TestOptTable T; unsigned MAI, MAC; - const char *MyArgs[] = { "-I" }; + StringRef MyArgs[] = {"-I"}; InputArgList AL = T.ParseArgs(MyArgs, MAI, MAC); EXPECT_TRUE(AL.hasArg(OPT_H)); } @@ -148,7 +139,7 @@ TestOptTable T; unsigned MAI, MAC; - const char *MyArgs[] = { "-J", "-Joo" }; + StringRef MyArgs[] = {"-J", "-Joo"}; InputArgList AL = T.ParseArgs(MyArgs, MAI, MAC); EXPECT_TRUE(AL.hasArg(OPT_B)); EXPECT_EQ("foo", AL.getAllArgValues(OPT_B)[0]); @@ -159,7 +150,7 @@ TestOptTable T(true); unsigned MAI, MAC; - const char *MyArgs[] = { "-a", "-joo" }; + StringRef MyArgs[] = {"-a", "-joo"}; InputArgList AL = T.ParseArgs(MyArgs, MAI, MAC); EXPECT_TRUE(AL.hasArg(OPT_A)); EXPECT_TRUE(AL.hasArg(OPT_B)); @@ -169,7 +160,7 @@ TestOptTable T; unsigned MAI, MAC; - const char *MyArgs[] = { "-a", "-joo" }; + StringRef MyArgs[] = {"-a", "-joo"}; InputArgList AL = T.ParseArgs(MyArgs, MAI, MAC); EXPECT_FALSE(AL.hasArg(OPT_A)); EXPECT_FALSE(AL.hasArg(OPT_B)); @@ -179,7 +170,7 @@ TestOptTable T; unsigned MAI, MAC; - const char *MyArgs[] = { "-A", "-slurp" }; + StringRef MyArgs[] = {"-A", "-slurp"}; InputArgList AL = T.ParseArgs(MyArgs, MAI, MAC); EXPECT_TRUE(AL.hasArg(OPT_A)); EXPECT_TRUE(AL.hasArg(OPT_Slurp)); @@ -190,7 +181,7 @@ TestOptTable T; unsigned MAI, MAC; - const char *MyArgs[] = { "-A", "-slurp", "-B", "--", "foo" }; + StringRef MyArgs[] = {"-A", "-slurp", "-B", "--", "foo"}; InputArgList AL = T.ParseArgs(MyArgs, MAI, MAC); EXPECT_EQ(AL.size(), 2U); EXPECT_TRUE(AL.hasArg(OPT_A)); @@ -206,7 +197,7 @@ TestOptTable T; unsigned MAI, MAC; - const char *MyArgs[] = { "-A", "-slurpjoined" }; + StringRef MyArgs[] = {"-A", "-slurpjoined"}; InputArgList AL = T.ParseArgs(MyArgs, MAI, MAC); EXPECT_TRUE(AL.hasArg(OPT_A)); EXPECT_TRUE(AL.hasArg(OPT_SlurpJoined)); @@ -217,7 +208,7 @@ TestOptTable T; unsigned MAI, MAC; - const char *MyArgs[] = { "-A", "-slurpjoinedfoo" }; + StringRef MyArgs[] = {"-A", "-slurpjoinedfoo"}; InputArgList AL = T.ParseArgs(MyArgs, MAI, MAC); EXPECT_TRUE(AL.hasArg(OPT_A)); EXPECT_TRUE(AL.hasArg(OPT_SlurpJoined)); @@ -229,7 +220,7 @@ TestOptTable T; unsigned MAI, MAC; - const char *MyArgs[] = { "-A", "-slurpjoinedfoo", "bar", "baz" }; + StringRef MyArgs[] = {"-A", "-slurpjoinedfoo", "bar", "baz"}; InputArgList AL = T.ParseArgs(MyArgs, MAI, MAC); EXPECT_TRUE(AL.hasArg(OPT_A)); EXPECT_TRUE(AL.hasArg(OPT_SlurpJoined)); @@ -243,7 +234,7 @@ TestOptTable T; unsigned MAI, MAC; - const char *MyArgs[] = { "-A", "-slurpjoined", "foo", "bar", "baz" }; + StringRef MyArgs[] = {"-A", "-slurpjoined", "foo", "bar", "baz"}; InputArgList AL = T.ParseArgs(MyArgs, MAI, MAC); EXPECT_TRUE(AL.hasArg(OPT_A)); EXPECT_TRUE(AL.hasArg(OPT_SlurpJoined)); @@ -258,7 +249,7 @@ unsigned MAI, MAC; // Check that a flag alias provides an empty argument to a joined option. - const char *MyArgs[] = { "-K" }; + const StringRef MyArgs[] = {"-K"}; InputArgList AL = T.ParseArgs(MyArgs, MAI, MAC); EXPECT_EQ(AL.size(), 1U); EXPECT_TRUE(AL.hasArg(OPT_B)); Index: llvm/unittests/Support/CommandLineTest.cpp =================================================================== --- llvm/unittests/Support/CommandLineTest.cpp +++ llvm/unittests/Support/CommandLineTest.cpp @@ -165,19 +165,18 @@ } typedef void ParserFunction(StringRef Source, StringSaver &Saver, - SmallVectorImpl &NewArgv, - bool MarkEOLs); + SmallVectorImpl &NewArgv, bool MarkEOLs); void testCommandLineTokenizer(ParserFunction *parse, StringRef Input, - const char *const Output[], size_t OutputSize) { - SmallVector Actual; + const StringRef Output[], size_t OutputSize) { + SmallVector Actual; BumpPtrAllocator A; StringSaver Saver(A); parse(Input, Saver, Actual, /*MarkEOLs=*/false); EXPECT_EQ(OutputSize, Actual.size()); for (unsigned I = 0, E = Actual.size(); I != E; ++I) { if (I < OutputSize) - EXPECT_STREQ(Output[I], Actual[I]); + EXPECT_EQ(Output[I], Actual[I]); } } @@ -185,9 +184,9 @@ const char Input[] = "foo\\ bar \"foo bar\" \'foo bar\' 'foo\\\\bar' -DFOO=bar\\(\\) " "foo\"bar\"baz C:\\\\src\\\\foo.cpp \"C:\\src\\foo.cpp\""; - const char *const Output[] = { - "foo bar", "foo bar", "foo bar", "foo\\bar", - "-DFOO=bar()", "foobarbaz", "C:\\src\\foo.cpp", "C:srcfoo.cpp"}; + const StringRef Output[] = {"foo bar", "foo bar", "foo bar", + "foo\\bar", "-DFOO=bar()", "foobarbaz", + "C:\\src\\foo.cpp", "C:srcfoo.cpp"}; testCommandLineTokenizer(cl::TokenizeGNUCommandLine, Input, Output, array_lengthof(Output)); } @@ -195,8 +194,8 @@ TEST(CommandLineTest, TokenizeWindowsCommandLine) { const char Input[] = "a\\b c\\\\d e\\\\\"f g\" h\\\"i j\\\\\\\"k \"lmn\" o pqr " "\"st \\\"u\" \\v"; - const char *const Output[] = { "a\\b", "c\\\\d", "e\\f g", "h\"i", "j\\\"k", - "lmn", "o", "pqr", "st \"u", "\\v" }; + const StringRef Output[] = {"a\\b", "c\\\\d", "e\\f g", "h\"i", "j\\\"k", + "lmn", "o", "pqr", "st \"u", "\\v"}; testCommandLineTokenizer(cl::TokenizeWindowsCommandLine, Input, Output, array_lengthof(Output)); }