Skip to content

Commit dfd90ce

Browse files
committed
Add new overload for CreateInterpreter and deprecate old interface
1 parent a9a865e commit dfd90ce

File tree

3 files changed

+187
-64
lines changed

3 files changed

+187
-64
lines changed

include/clang/Interpreter/CppInterOp.h

+17-2
Original file line numberDiff line numberDiff line change
@@ -577,9 +577,24 @@ namespace Cpp {
577577
///\param[in] Args - the list of arguments for interpreter constructor.
578578
///\param[in] CPPINTEROP_EXTRA_INTERPRETER_ARGS - an env variable, if defined,
579579
/// adds additional arguments to the interpreter.
580+
581+
//New Overload for CreateInterpreter, takes std::vector<std::string>
582+
CPPINTEROP_API TInterp_t CreateInterpreter(
583+
const std::vector<std::string>& Args = {},
584+
const std::vector<std::string>& GpuArgs = {});
585+
586+
/// New Overload for CreateInterpreter, takes std::initializer_list<std::string>
587+
/// later converted to std::vector<std::string> in the implementation
588+
/// This is a temporary solution until we can remove the old overload.
589+
CPPINTEROP_API TInterp_t CreateInterpreter(
590+
std::initializer_list<std::string> Args,
591+
std::initializer_list<std::string> GpuArgs);
592+
593+
/// @deprecated Use the overload that takes std::vector<std::string> instead.
594+
[[deprecated("Use the overload that takes std::vector<std::string> instead.")]]
580595
CPPINTEROP_API TInterp_t
581-
CreateInterpreter(const std::vector<const char*>& Args = {},
582-
const std::vector<const char*>& GpuArgs = {});
596+
CreateInterpreter(const std::vector<const char*>& Args,
597+
const std::vector<const char*>& GpuArgs);
583598

584599
/// Checks which Interpreter backend was CppInterOp library built with (Cling,
585600
/// Clang-REPL, etcetera). In practice, the selected interpreter should not

lib/Interpreter/CppInterOp.cpp

+156-62
Original file line numberDiff line numberDiff line change
@@ -2876,71 +2876,165 @@ namespace Cpp {
28762876
}
28772877
} // namespace
28782878

2879-
TInterp_t CreateInterpreter(const std::vector<const char*>& Args /*={}*/,
2880-
const std::vector<const char*>& GpuArgs /*={}*/) {
2881-
std::string MainExecutableName =
2882-
sys::fs::getMainExecutable(nullptr, nullptr);
2883-
std::string ResourceDir = MakeResourcesPath();
2884-
std::vector<const char *> ClingArgv = {"-resource-dir", ResourceDir.c_str(),
2885-
"-std=c++14"};
2886-
ClingArgv.insert(ClingArgv.begin(), MainExecutableName.c_str());
2879+
// This Methond is Deprecated and should not be used
2880+
// It is kept for backward compatibility
2881+
// Updated overload of CreateInterpreter using std::vector<std::string>
2882+
// is preferred and defined below
2883+
[[deprecated("Use the overload that takes std::vector<std::string> instead.")]]
2884+
TInterp_t CreateInterpreter(const std::vector<const char*>& Args,
2885+
const std::vector<const char*>& GpuArgs) {
2886+
2887+
//Convert const char* vectors to std::string vectors
2888+
std::vector<std::string> ArgsStr(Args.begin(), Args.end());
2889+
std::vector<std::string> GpuArgsStr(GpuArgs.begin(), GpuArgs.end());
2890+
//forwarding to the overloaded implementation
2891+
return CreateInterpreter(ArgsStr, GpuArgsStr);
2892+
2893+
// std::string MainExecutableName =
2894+
// sys::fs::getMainExecutable(nullptr, nullptr);
2895+
// std::string ResourceDir = MakeResourcesPath();
2896+
// std::vector<const char *> ClingArgv = {"-resource-dir", ResourceDir.c_str(),
2897+
// "-std=c++14"};
2898+
// ClingArgv.insert(ClingArgv.begin(), MainExecutableName.c_str());
2899+
// #ifdef _WIN32
2900+
// // FIXME : Workaround Sema::PushDeclContext assert on windows
2901+
// ClingArgv.push_back("-fno-delayed-template-parsing");
2902+
// #endif
2903+
// ClingArgv.insert(ClingArgv.end(), Args.begin(), Args.end());
2904+
// // To keep the Interpreter creation interface between cling and clang-repl
2905+
// // to some extent compatible we should put Args and GpuArgs together. On the
2906+
// // receiving end we should check for -xcuda to know.
2907+
// if (!GpuArgs.empty()) {
2908+
// llvm::StringRef Arg0 = GpuArgs[0];
2909+
// Arg0 = Arg0.trim().ltrim('-');
2910+
// if (Arg0 != "cuda") {
2911+
// llvm::errs() << "[CreateInterpreter]: Make sure --cuda is passed as the"
2912+
// << " first argument of the GpuArgs\n";
2913+
// return nullptr;
2914+
// }
2915+
// }
2916+
// ClingArgv.insert(ClingArgv.end(), GpuArgs.begin(), GpuArgs.end());
2917+
2918+
// // Process externally passed arguments if present.
2919+
// std::vector<std::string> ExtraArgs;
2920+
// auto EnvOpt =
2921+
// llvm::sys::Process::GetEnv("CPPINTEROP_EXTRA_INTERPRETER_ARGS");
2922+
// if (EnvOpt) {
2923+
// StringRef Env(*EnvOpt);
2924+
// while (!Env.empty()) {
2925+
// StringRef Arg;
2926+
// std::tie(Arg, Env) = Env.split(' ');
2927+
// ExtraArgs.push_back(Arg.str());
2928+
// }
2929+
// }
2930+
// std::transform(ExtraArgs.begin(), ExtraArgs.end(),
2931+
// std::back_inserter(ClingArgv),
2932+
// [&](const std::string& str) { return str.c_str(); });
2933+
2934+
// auto I = new compat::Interpreter(ClingArgv.size(), &ClingArgv[0]);
2935+
2936+
// // Honor -mllvm.
2937+
// //
2938+
// // FIXME: Remove this, one day.
2939+
// // This should happen AFTER plugins have been loaded!
2940+
// const CompilerInstance* Clang = I->getCI();
2941+
// if (!Clang->getFrontendOpts().LLVMArgs.empty()) {
2942+
// unsigned NumArgs = Clang->getFrontendOpts().LLVMArgs.size();
2943+
// auto Args = std::make_unique<const char*[]>(NumArgs + 2);
2944+
// Args[0] = "clang (LLVM option parsing)";
2945+
// for (unsigned i = 0; i != NumArgs; ++i)
2946+
// Args[i + 1] = Clang->getFrontendOpts().LLVMArgs[i].c_str();
2947+
// Args[NumArgs + 1] = nullptr;
2948+
// llvm::cl::ParseCommandLineOptions(NumArgs + 1, Args.get());
2949+
// }
2950+
// // FIXME: Enable this assert once we figure out how to fix the multiple
2951+
// // calls to CreateInterpreter.
2952+
// //assert(!sInterpreter && "Interpreter already set.");
2953+
// sInterpreter = I;
2954+
// return I;
2955+
}
2956+
2957+
//Overloaded defination of CreateInterpreter using std::initializer_list
2958+
// for Args and GpuArgs
2959+
// This is a convenience function that allows the user to pass
2960+
// arguments as initializer lists, which are then converted to
2961+
// std::vector<std::string> internally.
2962+
TInterp_t CreateInterpreter(std::initializer_list<std::string> Args,
2963+
std::initializer_list<std::string> GpuArgs) {
2964+
return CreateInterpreter(std::vector<std::string>(Args),
2965+
std::vector<std::string>(GpuArgs));
2966+
}
2967+
2968+
//overloaded defination of CreateInterpreter using std::vector<std::string>
2969+
// for Args and GpuArgs
2970+
TInterp_t CreateInterpreter(const std::vector<std::string>& Args,
2971+
const std::vector<std::string>& GpuArgs) {
2972+
// Retrieve the path to the main executable
2973+
std::string MainExecutableName = sys::fs::getMainExecutable(nullptr, nullptr);
2974+
2975+
// Construct the resource directory path
2976+
std::string ResourceDir = MakeResourcesPath();
2977+
2978+
// Initialize the argument list for the interpreter
2979+
std::vector<std::string> ClingArgv = {MainExecutableName, "-resource-dir", ResourceDir, "-std=c++14"};
2980+
28872981
#ifdef _WIN32
2888-
// FIXME : Workaround Sema::PushDeclContext assert on windows
2889-
ClingArgv.push_back("-fno-delayed-template-parsing");
2982+
// Add Windows-specific workaround for delayed template parsing
2983+
ClingArgv.push_back("-fno-delayed-template-parsing");
28902984
#endif
2891-
ClingArgv.insert(ClingArgv.end(), Args.begin(), Args.end());
2892-
// To keep the Interpreter creation interface between cling and clang-repl
2893-
// to some extent compatible we should put Args and GpuArgs together. On the
2894-
// receiving end we should check for -xcuda to know.
2895-
if (!GpuArgs.empty()) {
2896-
llvm::StringRef Arg0 = GpuArgs[0];
2897-
Arg0 = Arg0.trim().ltrim('-');
2898-
if (Arg0 != "cuda") {
2899-
llvm::errs() << "[CreateInterpreter]: Make sure --cuda is passed as the"
2900-
<< " first argument of the GpuArgs\n";
2901-
return nullptr;
2902-
}
2903-
}
2904-
ClingArgv.insert(ClingArgv.end(), GpuArgs.begin(), GpuArgs.end());
2905-
2906-
// Process externally passed arguments if present.
2907-
std::vector<std::string> ExtraArgs;
2908-
auto EnvOpt =
2909-
llvm::sys::Process::GetEnv("CPPINTEROP_EXTRA_INTERPRETER_ARGS");
2910-
if (EnvOpt) {
2911-
StringRef Env(*EnvOpt);
2912-
while (!Env.empty()) {
2913-
StringRef Arg;
2914-
std::tie(Arg, Env) = Env.split(' ');
2915-
ExtraArgs.push_back(Arg.str());
2916-
}
2917-
}
2918-
std::transform(ExtraArgs.begin(), ExtraArgs.end(),
2919-
std::back_inserter(ClingArgv),
2920-
[&](const std::string& str) { return str.c_str(); });
2921-
2922-
auto I = new compat::Interpreter(ClingArgv.size(), &ClingArgv[0]);
29232985

2924-
// Honor -mllvm.
2925-
//
2926-
// FIXME: Remove this, one day.
2927-
// This should happen AFTER plugins have been loaded!
2928-
const CompilerInstance* Clang = I->getCI();
2929-
if (!Clang->getFrontendOpts().LLVMArgs.empty()) {
2930-
unsigned NumArgs = Clang->getFrontendOpts().LLVMArgs.size();
2931-
auto Args = std::make_unique<const char*[]>(NumArgs + 2);
2932-
Args[0] = "clang (LLVM option parsing)";
2933-
for (unsigned i = 0; i != NumArgs; ++i)
2934-
Args[i + 1] = Clang->getFrontendOpts().LLVMArgs[i].c_str();
2935-
Args[NumArgs + 1] = nullptr;
2936-
llvm::cl::ParseCommandLineOptions(NumArgs + 1, Args.get());
2937-
}
2938-
// FIXME: Enable this assert once we figure out how to fix the multiple
2939-
// calls to CreateInterpreter.
2940-
//assert(!sInterpreter && "Interpreter already set.");
2941-
sInterpreter = I;
2942-
return I;
2943-
}
2986+
// Append user-provided arguments
2987+
ClingArgv.insert(ClingArgv.end(), Args.begin(), Args.end());
2988+
2989+
// Validate and append GPU-specific arguments
2990+
if (!GpuArgs.empty()) {
2991+
llvm::StringRef Arg0 = GpuArgs[0];
2992+
Arg0 = Arg0.trim().ltrim('-');
2993+
if (Arg0 != "cuda") {
2994+
llvm::errs() << "[CreateInterpreter]: Make sure --cuda is passed as the"
2995+
<< " first argument of the GpuArgs\n";
2996+
return nullptr;
2997+
}
2998+
}
2999+
ClingArgv.insert(ClingArgv.end(), GpuArgs.begin(), GpuArgs.end());
3000+
3001+
// Process additional arguments from the environment variable
3002+
auto EnvOpt = llvm::sys::Process::GetEnv("CPPINTEROP_EXTRA_INTERPRETER_ARGS");
3003+
if (EnvOpt) {
3004+
llvm::StringRef Env(*EnvOpt);
3005+
while (!Env.empty()) {
3006+
llvm::StringRef Arg;
3007+
std::tie(Arg, Env) = Env.split(' ');
3008+
ClingArgv.push_back(Arg.str());
3009+
}
3010+
}
3011+
3012+
// Convert std::vector<std::string> to std::vector<const char*> for compatibility
3013+
std::vector<const char*> ClingArgvCStr;
3014+
for (const auto& arg : ClingArgv) {
3015+
ClingArgvCStr.push_back(arg.c_str());
3016+
}
3017+
3018+
// Create the interpreter instance
3019+
auto I = new compat::Interpreter(ClingArgvCStr.size(), ClingArgvCStr.data());
3020+
3021+
// Process LLVM-specific arguments
3022+
const CompilerInstance* Clang = I->getCI();
3023+
if (!Clang->getFrontendOpts().LLVMArgs.empty()) {
3024+
unsigned NumArgs = Clang->getFrontendOpts().LLVMArgs.size();
3025+
auto Args = std::make_unique<const char*[]>(NumArgs + 2);
3026+
Args[0] = "clang (LLVM option parsing)";
3027+
for (unsigned i = 0; i != NumArgs; ++i) {
3028+
Args[i + 1] = Clang->getFrontendOpts().LLVMArgs[i].c_str();
3029+
}
3030+
Args[NumArgs + 1] = nullptr;
3031+
llvm::cl::ParseCommandLineOptions(NumArgs + 1, Args.get());
3032+
}
3033+
3034+
// Set the global interpreter instance
3035+
sInterpreter = I;
3036+
return I;
3037+
}
29443038

29453039
TInterp_t GetInterpreter() { return sInterpreter; }
29463040

unittests/CppInterOp/InterpreterTest.cpp

+14
Original file line numberDiff line numberDiff line change
@@ -258,3 +258,17 @@ if (llvm::sys::RunningOnValgrind())
258258
delete ExtInterp;
259259
#endif
260260
}
261+
262+
TEST(InterpreterTest, NewOverloadCreateInterpreter) {
263+
// This uses the new overload taking std::vector<std::string>
264+
auto* I = Cpp::CreateInterpreter({ "-std=c++17" }, {});
265+
EXPECT_TRUE(I);
266+
}
267+
268+
TEST(InterpreterTest, DeprecatedCreateInterpreter) {
269+
// This uses the deprecated interface taking std::vector<const char*>
270+
std::vector<const char*> args = { "-std=c++14" };
271+
std::vector<const char*> gpuArgs;
272+
auto* I = Cpp::CreateInterpreter(args, gpuArgs);
273+
EXPECT_TRUE(I);
274+
}

0 commit comments

Comments
 (0)