diff --git a/include/clang/Interpreter/CppInterOp.h b/include/clang/Interpreter/CppInterOp.h index c2f7115cf..fd79b1e2e 100644 --- a/include/clang/Interpreter/CppInterOp.h +++ b/include/clang/Interpreter/CppInterOp.h @@ -591,9 +591,24 @@ namespace Cpp { ///\param[in] Args - the list of arguments for interpreter constructor. ///\param[in] CPPINTEROP_EXTRA_INTERPRETER_ARGS - an env variable, if defined, /// adds additional arguments to the interpreter. + + //New Overload for CreateInterpreter, takes std::vector + CPPINTEROP_API TInterp_t CreateInterpreter( + const std::vector& Args = {}, + const std::vector& GpuArgs = {}); + + /// New Overload for CreateInterpreter, takes std::initializer_list + /// later converted to std::vector in the implementation + /// This is a temporary solution until we can remove the old overload. + CPPINTEROP_API TInterp_t CreateInterpreter( + std::initializer_list Args, + std::initializer_list GpuArgs); + + /// @deprecated Use the overload that takes std::vector instead. + [[deprecated("Use the overload that takes std::vector instead.")]] CPPINTEROP_API TInterp_t - CreateInterpreter(const std::vector& Args = {}, - const std::vector& GpuArgs = {}); + CreateInterpreter(const std::vector& Args, + const std::vector& GpuArgs); /// Checks which Interpreter backend was CppInterOp library built with (Cling, /// Clang-REPL, etcetera). In practice, the selected interpreter should not diff --git a/lib/Interpreter/CppInterOp.cpp b/lib/Interpreter/CppInterOp.cpp index 3575bb2fa..a916d4312 100755 --- a/lib/Interpreter/CppInterOp.cpp +++ b/lib/Interpreter/CppInterOp.cpp @@ -48,6 +48,7 @@ #include "llvm/Support/Casting.h" #include "llvm/Support/Debug.h" #include "llvm/Support/raw_os_ostream.h" +#include "llvm/Support/FileSystem.h" #include #include @@ -55,6 +56,8 @@ #include #include #include +#include + // Stream redirect. #ifdef _WIN32 @@ -2914,14 +2917,47 @@ namespace Cpp { } } // namespace - TInterp_t CreateInterpreter(const std::vector& Args /*={}*/, - const std::vector& GpuArgs /*={}*/) { - std::string MainExecutableName = + // This Methond is Deprecated and should not be used + // It is kept for backward compatibility + // Updated overload of CreateInterpreter using std::vector + // is preferred and defined below + [[deprecated("Use the overload that takes std::vector instead.")]] + TInterp_t CreateInterpreter(const std::vector& Args, + const std::vector& GpuArgs) { + + //Convert const char* vectors to std::string vectors + std::vector ArgsStr(Args.begin(), Args.end()); + std::vector GpuArgsStr(GpuArgs.begin(), GpuArgs.end()); + //forwarding to the overloaded implementation + return CreateInterpreter(ArgsStr, GpuArgsStr); + } + + //Overloaded defination of CreateInterpreter using std::initializer_list + // for Args and GpuArgs + // This is a convenience function that allows the user to pass + // arguments as initializer lists, which are then converted to + // std::vector internally. + TInterp_t CreateInterpreter(std::initializer_list Args, + std::initializer_list GpuArgs) { + return CreateInterpreter(std::vector(Args), + std::vector(GpuArgs)); + } + + //overloaded defination of CreateInterpreter using std::vector + // for Args and GpuArgs + TInterp_t CreateInterpreter(const std::vector& Args, + const std::vector& GpuArgs) { + // Retrieve the path to the main executable + std::string MainExecutableName = sys::fs::getMainExecutable(nullptr, nullptr); + + // Construct the resource directory path std::string ResourceDir = MakeResourcesPath(); - std::vector ClingArgv = {"-resource-dir", ResourceDir.c_str(), - "-std=c++14"}; - ClingArgv.insert(ClingArgv.begin(), MainExecutableName.c_str()); + + // Initialize the argument list for the interpreter + std::vector ClingArgv = {"-resource-dir", ResourceDir, "-std=c++14"}; + ClingArgv.insert(ClingArgv.begin(), MainExecutableName); + #ifdef _WIN32 // FIXME : Workaround Sema::PushDeclContext assert on windows ClingArgv.push_back("-fno-delayed-template-parsing"); @@ -2942,22 +2978,23 @@ namespace Cpp { ClingArgv.insert(ClingArgv.end(), GpuArgs.begin(), GpuArgs.end()); // Process externally passed arguments if present. - std::vector ExtraArgs; - auto EnvOpt = + auto EnvOpt = llvm::sys::Process::GetEnv("CPPINTEROP_EXTRA_INTERPRETER_ARGS"); if (EnvOpt) { StringRef Env(*EnvOpt); while (!Env.empty()) { StringRef Arg; std::tie(Arg, Env) = Env.split(' '); - ExtraArgs.push_back(Arg.str()); + ClingArgv.push_back(Arg.str()); } } - std::transform(ExtraArgs.begin(), ExtraArgs.end(), - std::back_inserter(ClingArgv), - [&](const std::string& str) { return str.c_str(); }); + // Convert std::vector to std::vector + std::vector ClingArgvCStr; + std::transform(ClingArgv.begin(), ClingArgv.end(), + std::back_inserter(ClingArgvCStr), + [](const std::string& str) { return str.c_str(); }); - auto I = new compat::Interpreter(ClingArgv.size(), &ClingArgv[0]); + auto I = new compat::Interpreter(ClingArgvCStr.size(), ClingArgvCStr.data()); // Honor -mllvm. // @@ -2973,6 +3010,7 @@ namespace Cpp { Args[NumArgs + 1] = nullptr; llvm::cl::ParseCommandLineOptions(NumArgs + 1, Args.get()); } + // FIXME: Enable this assert once we figure out how to fix the multiple // calls to CreateInterpreter. //assert(!sInterpreter && "Interpreter already set."); diff --git a/unittests/CppInterOp/InterpreterTest.cpp b/unittests/CppInterOp/InterpreterTest.cpp index 55cd3f742..403423afb 100644 --- a/unittests/CppInterOp/InterpreterTest.cpp +++ b/unittests/CppInterOp/InterpreterTest.cpp @@ -285,3 +285,17 @@ if (llvm::sys::RunningOnValgrind()) delete ExtInterp; #endif } + +TEST(InterpreterTest, NewOverloadCreateInterpreter) { + // This uses the new overload taking std::vector + auto* I = Cpp::CreateInterpreter({ "-std=c++17" }, {}); + EXPECT_TRUE(I); +} + +TEST(InterpreterTest, DeprecatedCreateInterpreter) { + // This uses the deprecated interface taking std::vector + std::vector args = { "-std=c++14" }; + std::vector gpuArgs; + auto* I = Cpp::CreateInterpreter(args, gpuArgs); + EXPECT_TRUE(I); +}