From 0abcac3a30e0f63580317491a603680ed738430a Mon Sep 17 00:00:00 2001 From: Claudio Bisegni Date: Wed, 2 May 2018 18:26:35 +0200 Subject: [PATCH] Interpreter and other class have been modified for support null args --- include/cling/Interpreter/InvocationOptions.h | 5 +- lib/Interpreter/CIFactory.cpp | 13 +- lib/Interpreter/InvocationOptions.cpp | 196 +++++++++++------- 3 files changed, 129 insertions(+), 85 deletions(-) diff --git a/include/cling/Interpreter/InvocationOptions.h b/include/cling/Interpreter/InvocationOptions.h index 833d139284..97aacebe40 100644 --- a/include/cling/Interpreter/InvocationOptions.h +++ b/include/cling/Interpreter/InvocationOptions.h @@ -37,7 +37,8 @@ namespace cling { ///\param [in] argv - arguments ///\param [out] Inputs - save all arguments that are inputs/files here /// - void Parse(int argc, const char* const argv[], + void Parse(int argc, + const char* const * argv, std::vector* Inputs = nullptr); ///\brief By default clang will try to set up an Interpreter with features @@ -72,7 +73,7 @@ namespace cling { class InvocationOptions { public: - InvocationOptions(int argc, const char* const argv[]); + InvocationOptions(int argc = 0, const char* const * argv = nullptr); /// \brief A line starting with this string is assumed to contain a /// directive for the MetaProcessor. Defaults to "." diff --git a/lib/Interpreter/CIFactory.cpp b/lib/Interpreter/CIFactory.cpp index e85f05f294..62790a8527 100644 --- a/lib/Interpreter/CIFactory.cpp +++ b/lib/Interpreter/CIFactory.cpp @@ -828,7 +828,11 @@ static void stringifyPreprocSetting(PreprocessorOptions& PPOpts, const size_t argc = COpts.Remaining.size(); const char* const* argv = &COpts.Remaining[0]; - std::vector argvCompile(argv, argv+1); + std::vector argvCompile; + if(argc && argv) { + argvCompile = std::vector(argv, argv+1); + } + argvCompile.reserve(argc+5); // Variables for storing the memory of the C-string arguments. @@ -910,7 +914,10 @@ static void stringifyPreprocSetting(PreprocessorOptions& PPOpts, argvCompile.insert(argvCompile.end(), argv+1, argv + argc); // Add host specific includes, -resource-dir if necessary, and -isysroot - std::string ClingBin = GetExecutablePath(argv[0]); + std::string ClingBin; + if(argv) { + ClingBin = GetExecutablePath(argv[0]); + } AddHostArguments(ClingBin, argvCompile, LLVMDir, COpts); // Be explicit about the stdlib on OS X @@ -948,7 +955,7 @@ static void stringifyPreprocSetting(PreprocessorOptions& PPOpts, // COFF format currently needs a few changes in LLVM to function properly. TheTriple.setObjectFormat(llvm::Triple::COFF); #endif - clang::driver::Driver Drvr(argv[0], TheTriple.getTriple(), *Diags); + clang::driver::Driver Drvr(ClingBin, TheTriple.getTriple(), *Diags); //Drvr.setWarnMissingInput(false); Drvr.setCheckInputsExist(false); // think foo.C(12) llvm::ArrayRefRF(&(argvCompile[0]), argvCompile.size()); diff --git a/lib/Interpreter/InvocationOptions.cpp b/lib/Interpreter/InvocationOptions.cpp index 77dd965a42..48b2d21c44 100644 --- a/lib/Interpreter/InvocationOptions.cpp +++ b/lib/Interpreter/InvocationOptions.cpp @@ -16,8 +16,8 @@ #include "llvm/Option/Arg.h" #include "llvm/Option/ArgList.h" -#include "llvm/Option/Option.h" #include "llvm/Option/OptTable.h" +#include "llvm/Option/Option.h" #include @@ -40,108 +40,141 @@ namespace { static const char kNoStdInc[] = "-nostdinc"; #endif -#define PREFIX(NAME, VALUE) const char *const NAME[] = VALUE; +#define PREFIX(NAME, VALUE) const char* const NAME[] = VALUE; #define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \ HELPTEXT, METAVAR, VALUES) #include "cling/Interpreter/ClingOptions.inc" #undef OPTION #undef PREFIX - static const OptTable::Info ClingInfoTable[] = { +static const OptTable::Info ClingInfoTable[] = { #define PREFIX(NAME, VALUE) #define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \ - HELPTEXT, METAVAR, VALUES) \ - { PREFIX, NAME, HELPTEXT, METAVAR, OPT_##ID, Option::KIND##Class, PARAM, \ - FLAGS, OPT_##GROUP, OPT_##ALIAS, ALIASARGS, VALUES }, + HELPTEXT, METAVAR, VALUES) \ + {PREFIX, NAME, HELPTEXT, METAVAR, OPT_##ID, Option::KIND##Class, \ + PARAM, FLAGS, OPT_##GROUP, OPT_##ALIAS, ALIASARGS, VALUES}, #include "cling/Interpreter/ClingOptions.inc" #undef OPTION #undef PREFIX - }; - - class ClingOptTable : public OptTable { - public: - ClingOptTable() - : OptTable(ClingInfoTable) {} - }; - - static OptTable* CreateClingOptTable() { - return new ClingOptTable(); - } - - static void ParseStartupOpts(cling::InvocationOptions& Opts, - InputArgList& Args) { - Opts.ErrorOut = Args.hasArg(OPT__errorout); - Opts.NoLogo = Args.hasArg(OPT__nologo); - Opts.ShowVersion = Args.hasArg(OPT_version); - Opts.Help = Args.hasArg(OPT_help); - Opts.NoRuntime = Args.hasArg(OPT_noruntime); - if (Arg* MetaStringArg = Args.getLastArg(OPT__metastr, OPT__metastr_EQ)) { - Opts.MetaString = MetaStringArg->getValue(); - if (Opts.MetaString.empty()) { - cling::errs() << "ERROR: meta string must be non-empty! Defaulting to '.'.\n"; - Opts.MetaString = "."; - } +}; + +class ClingOptTable : public OptTable { + public: + ClingOptTable() : OptTable(ClingInfoTable) {} +}; + +static OptTable* CreateClingOptTable() { return new ClingOptTable(); } + +static void ParseStartupOpts(cling::InvocationOptions& Opts, + InputArgList& Args) { + Opts.ErrorOut = Args.hasArg(OPT__errorout); + Opts.NoLogo = Args.hasArg(OPT__nologo); + Opts.ShowVersion = Args.hasArg(OPT_version); + Opts.Help = Args.hasArg(OPT_help); + Opts.NoRuntime = Args.hasArg(OPT_noruntime); + if (Arg* MetaStringArg = Args.getLastArg(OPT__metastr, OPT__metastr_EQ)) { + Opts.MetaString = MetaStringArg->getValue(); + if (Opts.MetaString.empty()) { + cling::errs() + << "ERROR: meta string must be non-empty! Defaulting to '.'.\n"; + Opts.MetaString = "."; } } +} - static void Extend(std::vector& A, std::vector B) { - A.reserve(A.size()+B.size()); - for (std::string& Val: B) - A.push_back(std::move(Val)); - } +static void Extend(std::vector& A, std::vector B) { + A.reserve(A.size() + B.size()); + for (std::string& Val : B) A.push_back(std::move(Val)); +} - static void ParseLinkerOpts(cling::InvocationOptions& Opts, - InputArgList& Args /* , Diags */) { - Extend(Opts.LibsToLoad, Args.getAllArgValues(OPT_l)); - Extend(Opts.LibSearchPath, Args.getAllArgValues(OPT_L)); - } +static void ParseLinkerOpts(cling::InvocationOptions& Opts, + InputArgList& Args /* , Diags */) { + Extend(Opts.LibsToLoad, Args.getAllArgValues(OPT_l)); + Extend(Opts.LibSearchPath, Args.getAllArgValues(OPT_L)); } +} // namespace CompilerOptions::CompilerOptions(int argc, const char* const* argv) - : Language(false), ResourceDir(false), SysRoot(false), NoBuiltinInc(false), - NoCXXInc(false), StdVersion(false), StdLib(false), HasOutput(false), - Verbose(false), CxxModules(false), CUDA(false) { + : Language(false), + ResourceDir(false), + SysRoot(false), + NoBuiltinInc(false), + NoCXXInc(false), + StdVersion(false), + StdLib(false), + HasOutput(false), + Verbose(false), + CxxModules(false), + CUDA(false) { if (argc && argv) { // Preserve what's already in Remaining, the user might want to push args // to clang while still using main's argc, argv // insert should/usually does call reserve, but its not part of the standard Remaining.reserve(Remaining.size() + argc); - Remaining.insert(Remaining.end(), argv, argv+argc); + Remaining.insert(Remaining.end(), argv, argv + argc); Parse(argc, argv); } } -void CompilerOptions::Parse(int argc, const char* const argv[], +void CompilerOptions::Parse(int argc, const char* const* argv, std::vector* Inputs) { unsigned MissingArgIndex, MissingArgCount; std::unique_ptr OptsC1(createDriverOptTable()); - ArrayRef ArgStrings(argv+1, argv + argc); - InputArgList Args(OptsC1->ParseArgs(ArgStrings, MissingArgIndex, - MissingArgCount, 0, - options::NoDriverOption | options::CLOption)); + ArrayRef ArgStrings; + if (argc && argv) { + ArgStrings = ArrayRef(argv + 1, argv + argc); + } + + InputArgList Args( + OptsC1->ParseArgs(ArgStrings, MissingArgIndex, MissingArgCount, 0, + options::NoDriverOption | options::CLOption)); for (const Arg* arg : Args) { switch (arg->getOption().getID()) { // case options::OPT_d_Flag: case options::OPT_E: - case options::OPT_o: HasOutput = true; break; - case options::OPT_x: Language = true; - CUDA = llvm::StringRef(arg->getValue()) == "cuda"; - break; - case options::OPT_resource_dir: ResourceDir = true; break; - case options::OPT_isysroot: SysRoot = true; break; - case options::OPT_std_EQ: StdVersion = true; break; - case options::OPT_stdlib_EQ: StdLib = true; break; + case options::OPT_o: + HasOutput = true; + break; + case options::OPT_x: + Language = true; + CUDA = llvm::StringRef(arg->getValue()) == "cuda"; + break; + case options::OPT_resource_dir: + ResourceDir = true; + break; + case options::OPT_isysroot: + SysRoot = true; + break; + case options::OPT_std_EQ: + StdVersion = true; + break; + case options::OPT_stdlib_EQ: + StdLib = true; + break; // case options::OPT_nostdlib: - case options::OPT_nobuiltininc: NoBuiltinInc = true; break; + case options::OPT_nobuiltininc: + NoBuiltinInc = true; + break; // case options::OPT_nostdinc: - case options::OPT_nostdincxx: NoCXXInc = true; break; - case options::OPT_v: Verbose = true; break; - case options::OPT_fmodules: CxxModules = true; break; - case options::OPT_fmodule_name_EQ: LLVM_FALLTHROUGH; - case options::OPT_fmodule_name: ModuleName = arg->getValue(); break; - case options::OPT_fmodules_cache_path: CachePath = arg->getValue(); break; + case options::OPT_nostdincxx: + NoCXXInc = true; + break; + case options::OPT_v: + Verbose = true; + break; + case options::OPT_fmodules: + CxxModules = true; + break; + case options::OPT_fmodule_name_EQ: + LLVM_FALLTHROUGH; + case options::OPT_fmodule_name: + ModuleName = arg->getValue(); + break; + case options::OPT_fmodules_cache_path: + CachePath = arg->getValue(); + break; default: if (Inputs && arg->getOption().getKind() == Option::InputClass) @@ -154,8 +187,7 @@ void CompilerOptions::Parse(int argc, const char* const argv[], bool CompilerOptions::DefaultLanguage(const LangOptions* LangOpts) const { // When StdVersion is set (-std=c++11, -std=gnu++11, etc.) then definitely // don't setup the defaults, as they may interfere with what the user is doing - if (StdVersion) - return false; + if (StdVersion) return false; // Also don't set up the defaults when language is explicitly set; unless // the language was set to generate a PCH, in which case definitely do. @@ -165,33 +197,38 @@ bool CompilerOptions::DefaultLanguage(const LangOptions* LangOpts) const { return true; } -InvocationOptions::InvocationOptions(int argc, const char* const* argv) : - MetaString("."), ErrorOut(false), NoLogo(false), ShowVersion(false), - Help(false), NoRuntime(false) { - - ArrayRef ArgStrings(argv, argv + argc); +InvocationOptions::InvocationOptions(int argc, const char* const* argv) + : MetaString("."), + ErrorOut(false), + NoLogo(false), + ShowVersion(false), + Help(false), + NoRuntime(false) { + ArrayRef ArgStrings; + if (argc && argv) { + // fill with arguments + ArgStrings = ArrayRef(argv, argv + argc); + } unsigned MissingArgIndex, MissingArgCount; std::unique_ptr Opts(CreateClingOptTable()); - InputArgList Args(Opts->ParseArgs(ArgStrings, MissingArgIndex, - MissingArgCount, 0, - options::NoDriverOption | options::CLOption)); + InputArgList Args( + Opts->ParseArgs(ArgStrings, MissingArgIndex, MissingArgCount, 0, + options::NoDriverOption | options::CLOption)); // Forward unknown arguments. for (const Arg* arg : Args) { switch (arg->getOption().getKind()) { case Option::FlagClass: // pass -v to clang as well - if (arg->getOption().getID() != OPT_v) - break; + if (arg->getOption().getID() != OPT_v) break; case Option::UnknownClass: case Option::InputClass: // prune "-" we need to control where it appears when invoking clang if (!arg->getSpelling().equals("-")) { if (const char* Arg = argv[arg->getIndex()]) { #ifdef CLING_TRANSLATE_NOSTDINCxx - if (!::strcmp(Arg, "-nostdinc++")) - Arg = kNoStdInc; + if (!::strcmp(Arg, "-nostdinc++")) Arg = kNoStdInc; #endif CompilerOpts.Remaining.push_back(Arg); } @@ -203,7 +240,6 @@ InvocationOptions::InvocationOptions(int argc, const char* const* argv) : // Get Input list and any compiler specific flags we're interested in CompilerOpts.Parse(argc, argv, &Inputs); - ParseStartupOpts(*this, Args); ParseLinkerOpts(*this, Args); }