From e434d6ac0397bc299a1a3b4fcb8049a70dc38f46 Mon Sep 17 00:00:00 2001 From: solo-source Date: Wed, 2 Apr 2025 00:04:40 +0530 Subject: [PATCH 1/4] Add new overload for CreateInterpreter and deprecate old interface --- include/clang/Interpreter/CppInterOp.h | 19 +- lib/Interpreter/CppInterOp.cpp | 218 ++++++++++++++++------- unittests/CppInterOp/InterpreterTest.cpp | 14 ++ 3 files changed, 187 insertions(+), 64 deletions(-) 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..7990de395 100755 --- a/lib/Interpreter/CppInterOp.cpp +++ b/lib/Interpreter/CppInterOp.cpp @@ -2914,71 +2914,165 @@ namespace Cpp { } } // namespace - TInterp_t CreateInterpreter(const std::vector& Args /*={}*/, - const std::vector& GpuArgs /*={}*/) { - std::string MainExecutableName = - sys::fs::getMainExecutable(nullptr, nullptr); - std::string ResourceDir = MakeResourcesPath(); - std::vector ClingArgv = {"-resource-dir", ResourceDir.c_str(), - "-std=c++14"}; - ClingArgv.insert(ClingArgv.begin(), MainExecutableName.c_str()); + // 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); + +// std::string MainExecutableName = +// sys::fs::getMainExecutable(nullptr, nullptr); +// std::string ResourceDir = MakeResourcesPath(); +// std::vector ClingArgv = {"-resource-dir", ResourceDir.c_str(), +// "-std=c++14"}; +// ClingArgv.insert(ClingArgv.begin(), MainExecutableName.c_str()); +// #ifdef _WIN32 +// // FIXME : Workaround Sema::PushDeclContext assert on windows +// ClingArgv.push_back("-fno-delayed-template-parsing"); +// #endif +// ClingArgv.insert(ClingArgv.end(), Args.begin(), Args.end()); +// // To keep the Interpreter creation interface between cling and clang-repl +// // to some extent compatible we should put Args and GpuArgs together. On the +// // receiving end we should check for -xcuda to know. +// if (!GpuArgs.empty()) { +// llvm::StringRef Arg0 = GpuArgs[0]; +// Arg0 = Arg0.trim().ltrim('-'); +// if (Arg0 != "cuda") { +// llvm::errs() << "[CreateInterpreter]: Make sure --cuda is passed as the" +// << " first argument of the GpuArgs\n"; +// return nullptr; +// } +// } +// ClingArgv.insert(ClingArgv.end(), GpuArgs.begin(), GpuArgs.end()); + +// // Process externally passed arguments if present. +// std::vector ExtraArgs; +// 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()); +// } +// } +// std::transform(ExtraArgs.begin(), ExtraArgs.end(), +// std::back_inserter(ClingArgv), +// [&](const std::string& str) { return str.c_str(); }); + +// auto I = new compat::Interpreter(ClingArgv.size(), &ClingArgv[0]); + +// // Honor -mllvm. +// // +// // FIXME: Remove this, one day. +// // This should happen AFTER plugins have been loaded! +// const CompilerInstance* Clang = I->getCI(); +// if (!Clang->getFrontendOpts().LLVMArgs.empty()) { +// unsigned NumArgs = Clang->getFrontendOpts().LLVMArgs.size(); +// auto Args = std::make_unique(NumArgs + 2); +// Args[0] = "clang (LLVM option parsing)"; +// for (unsigned i = 0; i != NumArgs; ++i) +// Args[i + 1] = Clang->getFrontendOpts().LLVMArgs[i].c_str(); +// 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."); +// sInterpreter = I; +// return I; + } + + //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(); + +// Initialize the argument list for the interpreter +std::vector ClingArgv = {MainExecutableName, "-resource-dir", ResourceDir, "-std=c++14"}; + #ifdef _WIN32 - // FIXME : Workaround Sema::PushDeclContext assert on windows - ClingArgv.push_back("-fno-delayed-template-parsing"); +// Add Windows-specific workaround for delayed template parsing +ClingArgv.push_back("-fno-delayed-template-parsing"); #endif - ClingArgv.insert(ClingArgv.end(), Args.begin(), Args.end()); - // To keep the Interpreter creation interface between cling and clang-repl - // to some extent compatible we should put Args and GpuArgs together. On the - // receiving end we should check for -xcuda to know. - if (!GpuArgs.empty()) { - llvm::StringRef Arg0 = GpuArgs[0]; - Arg0 = Arg0.trim().ltrim('-'); - if (Arg0 != "cuda") { - llvm::errs() << "[CreateInterpreter]: Make sure --cuda is passed as the" - << " first argument of the GpuArgs\n"; - return nullptr; - } - } - ClingArgv.insert(ClingArgv.end(), GpuArgs.begin(), GpuArgs.end()); - - // Process externally passed arguments if present. - std::vector ExtraArgs; - 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()); - } - } - std::transform(ExtraArgs.begin(), ExtraArgs.end(), - std::back_inserter(ClingArgv), - [&](const std::string& str) { return str.c_str(); }); - - auto I = new compat::Interpreter(ClingArgv.size(), &ClingArgv[0]); - // Honor -mllvm. - // - // FIXME: Remove this, one day. - // This should happen AFTER plugins have been loaded! - const CompilerInstance* Clang = I->getCI(); - if (!Clang->getFrontendOpts().LLVMArgs.empty()) { - unsigned NumArgs = Clang->getFrontendOpts().LLVMArgs.size(); - auto Args = std::make_unique(NumArgs + 2); - Args[0] = "clang (LLVM option parsing)"; - for (unsigned i = 0; i != NumArgs; ++i) - Args[i + 1] = Clang->getFrontendOpts().LLVMArgs[i].c_str(); - 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."); - sInterpreter = I; - return I; - } +// Append user-provided arguments +ClingArgv.insert(ClingArgv.end(), Args.begin(), Args.end()); + +// Validate and append GPU-specific arguments +if (!GpuArgs.empty()) { +llvm::StringRef Arg0 = GpuArgs[0]; +Arg0 = Arg0.trim().ltrim('-'); +if (Arg0 != "cuda") { +llvm::errs() << "[CreateInterpreter]: Make sure --cuda is passed as the" + << " first argument of the GpuArgs\n"; +return nullptr; +} +} +ClingArgv.insert(ClingArgv.end(), GpuArgs.begin(), GpuArgs.end()); + +// Process additional arguments from the environment variable +auto EnvOpt = llvm::sys::Process::GetEnv("CPPINTEROP_EXTRA_INTERPRETER_ARGS"); +if (EnvOpt) { +llvm::StringRef Env(*EnvOpt); +while (!Env.empty()) { +llvm::StringRef Arg; +std::tie(Arg, Env) = Env.split(' '); +ClingArgv.push_back(Arg.str()); +} +} + +// Convert std::vector to std::vector for compatibility +std::vector ClingArgvCStr; +for (const auto& arg : ClingArgv) { +ClingArgvCStr.push_back(arg.c_str()); +} + +// Create the interpreter instance +auto I = new compat::Interpreter(ClingArgvCStr.size(), ClingArgvCStr.data()); + +// Process LLVM-specific arguments +const CompilerInstance* Clang = I->getCI(); +if (!Clang->getFrontendOpts().LLVMArgs.empty()) { +unsigned NumArgs = Clang->getFrontendOpts().LLVMArgs.size(); +auto Args = std::make_unique(NumArgs + 2); +Args[0] = "clang (LLVM option parsing)"; +for (unsigned i = 0; i != NumArgs; ++i) { +Args[i + 1] = Clang->getFrontendOpts().LLVMArgs[i].c_str(); +} +Args[NumArgs + 1] = nullptr; +llvm::cl::ParseCommandLineOptions(NumArgs + 1, Args.get()); +} + +// Set the global interpreter instance +sInterpreter = I; +return I; +} TInterp_t GetInterpreter() { return sInterpreter; } 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); +} From 1499cce5ab396d4538d91b3aa03241ff63106ac1 Mon Sep 17 00:00:00 2001 From: solo-source Date: Wed, 2 Apr 2025 11:09:15 +0530 Subject: [PATCH 2/4] Added Missed Header Files. --- lib/Interpreter/CppInterOp.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/Interpreter/CppInterOp.cpp b/lib/Interpreter/CppInterOp.cpp index 7990de395..39f2bc12c 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 From b52b308c32d6d822c5be399312ccc3f866e1c2d2 Mon Sep 17 00:00:00 2001 From: solo-source Date: Wed, 2 Apr 2025 12:06:01 +0530 Subject: [PATCH 3/4] Improved formatting of the code for better readability. --- lib/Interpreter/CppInterOp.cpp | 189 +++++++++++---------------------- 1 file changed, 63 insertions(+), 126 deletions(-) diff --git a/lib/Interpreter/CppInterOp.cpp b/lib/Interpreter/CppInterOp.cpp index 39f2bc12c..eb70af646 100755 --- a/lib/Interpreter/CppInterOp.cpp +++ b/lib/Interpreter/CppInterOp.cpp @@ -2930,69 +2930,6 @@ namespace Cpp { std::vector GpuArgsStr(GpuArgs.begin(), GpuArgs.end()); //forwarding to the overloaded implementation return CreateInterpreter(ArgsStr, GpuArgsStr); - -// std::string MainExecutableName = -// sys::fs::getMainExecutable(nullptr, nullptr); -// std::string ResourceDir = MakeResourcesPath(); -// std::vector ClingArgv = {"-resource-dir", ResourceDir.c_str(), -// "-std=c++14"}; -// ClingArgv.insert(ClingArgv.begin(), MainExecutableName.c_str()); -// #ifdef _WIN32 -// // FIXME : Workaround Sema::PushDeclContext assert on windows -// ClingArgv.push_back("-fno-delayed-template-parsing"); -// #endif -// ClingArgv.insert(ClingArgv.end(), Args.begin(), Args.end()); -// // To keep the Interpreter creation interface between cling and clang-repl -// // to some extent compatible we should put Args and GpuArgs together. On the -// // receiving end we should check for -xcuda to know. -// if (!GpuArgs.empty()) { -// llvm::StringRef Arg0 = GpuArgs[0]; -// Arg0 = Arg0.trim().ltrim('-'); -// if (Arg0 != "cuda") { -// llvm::errs() << "[CreateInterpreter]: Make sure --cuda is passed as the" -// << " first argument of the GpuArgs\n"; -// return nullptr; -// } -// } -// ClingArgv.insert(ClingArgv.end(), GpuArgs.begin(), GpuArgs.end()); - -// // Process externally passed arguments if present. -// std::vector ExtraArgs; -// 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()); -// } -// } -// std::transform(ExtraArgs.begin(), ExtraArgs.end(), -// std::back_inserter(ClingArgv), -// [&](const std::string& str) { return str.c_str(); }); - -// auto I = new compat::Interpreter(ClingArgv.size(), &ClingArgv[0]); - -// // Honor -mllvm. -// // -// // FIXME: Remove this, one day. -// // This should happen AFTER plugins have been loaded! -// const CompilerInstance* Clang = I->getCI(); -// if (!Clang->getFrontendOpts().LLVMArgs.empty()) { -// unsigned NumArgs = Clang->getFrontendOpts().LLVMArgs.size(); -// auto Args = std::make_unique(NumArgs + 2); -// Args[0] = "clang (LLVM option parsing)"; -// for (unsigned i = 0; i != NumArgs; ++i) -// Args[i + 1] = Clang->getFrontendOpts().LLVMArgs[i].c_str(); -// 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."); -// sInterpreter = I; -// return I; } //Overloaded defination of CreateInterpreter using std::initializer_list @@ -3004,78 +2941,78 @@ namespace Cpp { 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); + // Retrieve the path to the main executable + std::string MainExecutableName = sys::fs::getMainExecutable(nullptr, nullptr); + + // Construct the resource directory path + std::string ResourceDir = MakeResourcesPath(); + + // Initialize the argument list for the interpreter + std::vector ClingArgv = {MainExecutableName, "-resource-dir", ResourceDir, "-std=c++14"}; + + #ifdef _WIN32 + // Add Windows-specific workaround for delayed template parsing + ClingArgv.push_back("-fno-delayed-template-parsing"); + #endif + + // Append user-provided arguments + ClingArgv.insert(ClingArgv.end(), Args.begin(), Args.end()); + + // Validate and append GPU-specific arguments + if (!GpuArgs.empty()) { + llvm::StringRef Arg0 = GpuArgs[0]; + Arg0 = Arg0.trim().ltrim('-'); + if (Arg0 != "cuda") { + llvm::errs() << "[CreateInterpreter]: Make sure --cuda is passed as the" + << " first argument of the GpuArgs\n"; + return nullptr; + } + } + ClingArgv.insert(ClingArgv.end(), GpuArgs.begin(), GpuArgs.end()); -// Construct the resource directory path -std::string ResourceDir = MakeResourcesPath(); + // Process additional arguments from the environment variable + auto EnvOpt = llvm::sys::Process::GetEnv("CPPINTEROP_EXTRA_INTERPRETER_ARGS"); + if (EnvOpt) { + llvm::StringRef Env(*EnvOpt); + while (!Env.empty()) { + llvm::StringRef Arg; + std::tie(Arg, Env) = Env.split(' '); + ClingArgv.push_back(Arg.str()); + } + } -// Initialize the argument list for the interpreter -std::vector ClingArgv = {MainExecutableName, "-resource-dir", ResourceDir, "-std=c++14"}; + // Convert std::vector to std::vector for compatibility + std::vector ClingArgvCStr; + for (const auto& arg : ClingArgv) { + ClingArgvCStr.push_back(arg.c_str()); + } -#ifdef _WIN32 -// Add Windows-specific workaround for delayed template parsing -ClingArgv.push_back("-fno-delayed-template-parsing"); -#endif + // Create the interpreter instance + auto I = new compat::Interpreter(ClingArgvCStr.size(), ClingArgvCStr.data()); + + // Process LLVM-specific arguments + const CompilerInstance* Clang = I->getCI(); + if (!Clang->getFrontendOpts().LLVMArgs.empty()) { + unsigned NumArgs = Clang->getFrontendOpts().LLVMArgs.size(); + auto Args = std::make_unique(NumArgs + 2); + Args[0] = "clang (LLVM option parsing)"; + for (unsigned i = 0; i != NumArgs; ++i) { + Args[i + 1] = Clang->getFrontendOpts().LLVMArgs[i].c_str(); + } + Args[NumArgs + 1] = nullptr; + llvm::cl::ParseCommandLineOptions(NumArgs + 1, Args.get()); + } -// Append user-provided arguments -ClingArgv.insert(ClingArgv.end(), Args.begin(), Args.end()); - -// Validate and append GPU-specific arguments -if (!GpuArgs.empty()) { -llvm::StringRef Arg0 = GpuArgs[0]; -Arg0 = Arg0.trim().ltrim('-'); -if (Arg0 != "cuda") { -llvm::errs() << "[CreateInterpreter]: Make sure --cuda is passed as the" - << " first argument of the GpuArgs\n"; -return nullptr; -} -} -ClingArgv.insert(ClingArgv.end(), GpuArgs.begin(), GpuArgs.end()); - -// Process additional arguments from the environment variable -auto EnvOpt = llvm::sys::Process::GetEnv("CPPINTEROP_EXTRA_INTERPRETER_ARGS"); -if (EnvOpt) { -llvm::StringRef Env(*EnvOpt); -while (!Env.empty()) { -llvm::StringRef Arg; -std::tie(Arg, Env) = Env.split(' '); -ClingArgv.push_back(Arg.str()); -} -} - -// Convert std::vector to std::vector for compatibility -std::vector ClingArgvCStr; -for (const auto& arg : ClingArgv) { -ClingArgvCStr.push_back(arg.c_str()); -} - -// Create the interpreter instance -auto I = new compat::Interpreter(ClingArgvCStr.size(), ClingArgvCStr.data()); - -// Process LLVM-specific arguments -const CompilerInstance* Clang = I->getCI(); -if (!Clang->getFrontendOpts().LLVMArgs.empty()) { -unsigned NumArgs = Clang->getFrontendOpts().LLVMArgs.size(); -auto Args = std::make_unique(NumArgs + 2); -Args[0] = "clang (LLVM option parsing)"; -for (unsigned i = 0; i != NumArgs; ++i) { -Args[i + 1] = Clang->getFrontendOpts().LLVMArgs[i].c_str(); -} -Args[NumArgs + 1] = nullptr; -llvm::cl::ParseCommandLineOptions(NumArgs + 1, Args.get()); -} - -// Set the global interpreter instance -sInterpreter = I; -return I; -} + // Set the global interpreter instance + sInterpreter = I; + return I; + } TInterp_t GetInterpreter() { return sInterpreter; } From 7d3585f654ed37387cd1abaf97f295d64000373d Mon Sep 17 00:00:00 2001 From: solo-source Date: Wed, 2 Apr 2025 12:44:37 +0530 Subject: [PATCH 4/4] undid weird formatting and brought back old comments. --- lib/Interpreter/CppInterOp.cpp | 52 ++++++++++++++++++---------------- 1 file changed, 28 insertions(+), 24 deletions(-) diff --git a/lib/Interpreter/CppInterOp.cpp b/lib/Interpreter/CppInterOp.cpp index eb70af646..a916d4312 100755 --- a/lib/Interpreter/CppInterOp.cpp +++ b/lib/Interpreter/CppInterOp.cpp @@ -2948,68 +2948,72 @@ namespace Cpp { 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); + std::string MainExecutableName = + sys::fs::getMainExecutable(nullptr, nullptr); // Construct the resource directory path std::string ResourceDir = MakeResourcesPath(); // Initialize the argument list for the interpreter - std::vector ClingArgv = {MainExecutableName, "-resource-dir", ResourceDir, "-std=c++14"}; + std::vector ClingArgv = {"-resource-dir", ResourceDir, "-std=c++14"}; + ClingArgv.insert(ClingArgv.begin(), MainExecutableName); - #ifdef _WIN32 - // Add Windows-specific workaround for delayed template parsing +#ifdef _WIN32 + // FIXME : Workaround Sema::PushDeclContext assert on windows ClingArgv.push_back("-fno-delayed-template-parsing"); - #endif - - // Append user-provided arguments +#endif ClingArgv.insert(ClingArgv.end(), Args.begin(), Args.end()); - - // Validate and append GPU-specific arguments + // To keep the Interpreter creation interface between cling and clang-repl + // to some extent compatible we should put Args and GpuArgs together. On the + // receiving end we should check for -xcuda to know. if (!GpuArgs.empty()) { llvm::StringRef Arg0 = GpuArgs[0]; Arg0 = Arg0.trim().ltrim('-'); if (Arg0 != "cuda") { llvm::errs() << "[CreateInterpreter]: Make sure --cuda is passed as the" - << " first argument of the GpuArgs\n"; + << " first argument of the GpuArgs\n"; return nullptr; } } ClingArgv.insert(ClingArgv.end(), GpuArgs.begin(), GpuArgs.end()); - // Process additional arguments from the environment variable - auto EnvOpt = llvm::sys::Process::GetEnv("CPPINTEROP_EXTRA_INTERPRETER_ARGS"); + // Process externally passed arguments if present. + auto EnvOpt = + llvm::sys::Process::GetEnv("CPPINTEROP_EXTRA_INTERPRETER_ARGS"); if (EnvOpt) { - llvm::StringRef Env(*EnvOpt); + StringRef Env(*EnvOpt); while (!Env.empty()) { - llvm::StringRef Arg; + StringRef Arg; std::tie(Arg, Env) = Env.split(' '); ClingArgv.push_back(Arg.str()); } } - - // Convert std::vector to std::vector for compatibility + // Convert std::vector to std::vector std::vector ClingArgvCStr; - for (const auto& arg : ClingArgv) { - ClingArgvCStr.push_back(arg.c_str()); - } + std::transform(ClingArgv.begin(), ClingArgv.end(), + std::back_inserter(ClingArgvCStr), + [](const std::string& str) { return str.c_str(); }); - // Create the interpreter instance auto I = new compat::Interpreter(ClingArgvCStr.size(), ClingArgvCStr.data()); - // Process LLVM-specific arguments + // Honor -mllvm. + // + // FIXME: Remove this, one day. + // This should happen AFTER plugins have been loaded! const CompilerInstance* Clang = I->getCI(); if (!Clang->getFrontendOpts().LLVMArgs.empty()) { unsigned NumArgs = Clang->getFrontendOpts().LLVMArgs.size(); auto Args = std::make_unique(NumArgs + 2); Args[0] = "clang (LLVM option parsing)"; - for (unsigned i = 0; i != NumArgs; ++i) { + for (unsigned i = 0; i != NumArgs; ++i) Args[i + 1] = Clang->getFrontendOpts().LLVMArgs[i].c_str(); - } Args[NumArgs + 1] = nullptr; llvm::cl::ParseCommandLineOptions(NumArgs + 1, Args.get()); } - // Set the global interpreter instance + // FIXME: Enable this assert once we figure out how to fix the multiple + // calls to CreateInterpreter. + //assert(!sInterpreter && "Interpreter already set."); sInterpreter = I; return I; }