Skip to content

Commit 7b9f01c

Browse files
committed
Add new overload for CreateInterpreter and deprecate old interface
1 parent e1ace51 commit 7b9f01c

File tree

3 files changed

+187
-64
lines changed

3 files changed

+187
-64
lines changed

include/clang/Interpreter/CppInterOp.h

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -591,9 +591,24 @@ namespace Cpp {
591591
///\param[in] Args - the list of arguments for interpreter constructor.
592592
///\param[in] CPPINTEROP_EXTRA_INTERPRETER_ARGS - an env variable, if defined,
593593
/// adds additional arguments to the interpreter.
594+
595+
//New Overload for CreateInterpreter, takes std::vector<std::string>
596+
CPPINTEROP_API TInterp_t CreateInterpreter(
597+
const std::vector<std::string>& Args = {},
598+
const std::vector<std::string>& GpuArgs = {});
599+
600+
/// New Overload for CreateInterpreter, takes std::initializer_list<std::string>
601+
/// later converted to std::vector<std::string> in the implementation
602+
/// This is a temporary solution until we can remove the old overload.
603+
CPPINTEROP_API TInterp_t CreateInterpreter(
604+
std::initializer_list<std::string> Args,
605+
std::initializer_list<std::string> GpuArgs);
606+
607+
/// @deprecated Use the overload that takes std::vector<std::string> instead.
608+
[[deprecated("Use the overload that takes std::vector<std::string> instead.")]]
594609
CPPINTEROP_API TInterp_t
595-
CreateInterpreter(const std::vector<const char*>& Args = {},
596-
const std::vector<const char*>& GpuArgs = {});
610+
CreateInterpreter(const std::vector<const char*>& Args,
611+
const std::vector<const char*>& GpuArgs);
597612

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

lib/Interpreter/CppInterOp.cpp

Lines changed: 156 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -2914,71 +2914,165 @@ namespace Cpp {
29142914
}
29152915
} // namespace
29162916

2917-
TInterp_t CreateInterpreter(const std::vector<const char*>& Args /*={}*/,
2918-
const std::vector<const char*>& GpuArgs /*={}*/) {
2919-
std::string MainExecutableName =
2920-
sys::fs::getMainExecutable(nullptr, nullptr);
2921-
std::string ResourceDir = MakeResourcesPath();
2922-
std::vector<const char *> ClingArgv = {"-resource-dir", ResourceDir.c_str(),
2923-
"-std=c++14"};
2924-
ClingArgv.insert(ClingArgv.begin(), MainExecutableName.c_str());
2917+
// This Methond is Deprecated and should not be used
2918+
// It is kept for backward compatibility
2919+
// Updated overload of CreateInterpreter using std::vector<std::string>
2920+
// is preferred and defined below
2921+
[[deprecated("Use the overload that takes std::vector<std::string> instead.")]]
2922+
TInterp_t CreateInterpreter(const std::vector<const char*>& Args,
2923+
const std::vector<const char*>& GpuArgs) {
2924+
2925+
//Convert const char* vectors to std::string vectors
2926+
std::vector<std::string> ArgsStr(Args.begin(), Args.end());
2927+
std::vector<std::string> GpuArgsStr(GpuArgs.begin(), GpuArgs.end());
2928+
//forwarding to the overloaded implementation
2929+
return CreateInterpreter(ArgsStr, GpuArgsStr);
2930+
2931+
// std::string MainExecutableName =
2932+
// sys::fs::getMainExecutable(nullptr, nullptr);
2933+
// std::string ResourceDir = MakeResourcesPath();
2934+
// std::vector<const char *> ClingArgv = {"-resource-dir", ResourceDir.c_str(),
2935+
// "-std=c++14"};
2936+
// ClingArgv.insert(ClingArgv.begin(), MainExecutableName.c_str());
2937+
// #ifdef _WIN32
2938+
// // FIXME : Workaround Sema::PushDeclContext assert on windows
2939+
// ClingArgv.push_back("-fno-delayed-template-parsing");
2940+
// #endif
2941+
// ClingArgv.insert(ClingArgv.end(), Args.begin(), Args.end());
2942+
// // To keep the Interpreter creation interface between cling and clang-repl
2943+
// // to some extent compatible we should put Args and GpuArgs together. On the
2944+
// // receiving end we should check for -xcuda to know.
2945+
// if (!GpuArgs.empty()) {
2946+
// llvm::StringRef Arg0 = GpuArgs[0];
2947+
// Arg0 = Arg0.trim().ltrim('-');
2948+
// if (Arg0 != "cuda") {
2949+
// llvm::errs() << "[CreateInterpreter]: Make sure --cuda is passed as the"
2950+
// << " first argument of the GpuArgs\n";
2951+
// return nullptr;
2952+
// }
2953+
// }
2954+
// ClingArgv.insert(ClingArgv.end(), GpuArgs.begin(), GpuArgs.end());
2955+
2956+
// // Process externally passed arguments if present.
2957+
// std::vector<std::string> ExtraArgs;
2958+
// auto EnvOpt =
2959+
// llvm::sys::Process::GetEnv("CPPINTEROP_EXTRA_INTERPRETER_ARGS");
2960+
// if (EnvOpt) {
2961+
// StringRef Env(*EnvOpt);
2962+
// while (!Env.empty()) {
2963+
// StringRef Arg;
2964+
// std::tie(Arg, Env) = Env.split(' ');
2965+
// ExtraArgs.push_back(Arg.str());
2966+
// }
2967+
// }
2968+
// std::transform(ExtraArgs.begin(), ExtraArgs.end(),
2969+
// std::back_inserter(ClingArgv),
2970+
// [&](const std::string& str) { return str.c_str(); });
2971+
2972+
// auto I = new compat::Interpreter(ClingArgv.size(), &ClingArgv[0]);
2973+
2974+
// // Honor -mllvm.
2975+
// //
2976+
// // FIXME: Remove this, one day.
2977+
// // This should happen AFTER plugins have been loaded!
2978+
// const CompilerInstance* Clang = I->getCI();
2979+
// if (!Clang->getFrontendOpts().LLVMArgs.empty()) {
2980+
// unsigned NumArgs = Clang->getFrontendOpts().LLVMArgs.size();
2981+
// auto Args = std::make_unique<const char*[]>(NumArgs + 2);
2982+
// Args[0] = "clang (LLVM option parsing)";
2983+
// for (unsigned i = 0; i != NumArgs; ++i)
2984+
// Args[i + 1] = Clang->getFrontendOpts().LLVMArgs[i].c_str();
2985+
// Args[NumArgs + 1] = nullptr;
2986+
// llvm::cl::ParseCommandLineOptions(NumArgs + 1, Args.get());
2987+
// }
2988+
// // FIXME: Enable this assert once we figure out how to fix the multiple
2989+
// // calls to CreateInterpreter.
2990+
// //assert(!sInterpreter && "Interpreter already set.");
2991+
// sInterpreter = I;
2992+
// return I;
2993+
}
2994+
2995+
//Overloaded defination of CreateInterpreter using std::initializer_list
2996+
// for Args and GpuArgs
2997+
// This is a convenience function that allows the user to pass
2998+
// arguments as initializer lists, which are then converted to
2999+
// std::vector<std::string> internally.
3000+
TInterp_t CreateInterpreter(std::initializer_list<std::string> Args,
3001+
std::initializer_list<std::string> GpuArgs) {
3002+
return CreateInterpreter(std::vector<std::string>(Args),
3003+
std::vector<std::string>(GpuArgs));
3004+
}
3005+
3006+
//overloaded defination of CreateInterpreter using std::vector<std::string>
3007+
// for Args and GpuArgs
3008+
TInterp_t CreateInterpreter(const std::vector<std::string>& Args,
3009+
const std::vector<std::string>& GpuArgs) {
3010+
// Retrieve the path to the main executable
3011+
std::string MainExecutableName = sys::fs::getMainExecutable(nullptr, nullptr);
3012+
3013+
// Construct the resource directory path
3014+
std::string ResourceDir = MakeResourcesPath();
3015+
3016+
// Initialize the argument list for the interpreter
3017+
std::vector<std::string> ClingArgv = {MainExecutableName, "-resource-dir", ResourceDir, "-std=c++14"};
3018+
29253019
#ifdef _WIN32
2926-
// FIXME : Workaround Sema::PushDeclContext assert on windows
2927-
ClingArgv.push_back("-fno-delayed-template-parsing");
3020+
// Add Windows-specific workaround for delayed template parsing
3021+
ClingArgv.push_back("-fno-delayed-template-parsing");
29283022
#endif
2929-
ClingArgv.insert(ClingArgv.end(), Args.begin(), Args.end());
2930-
// To keep the Interpreter creation interface between cling and clang-repl
2931-
// to some extent compatible we should put Args and GpuArgs together. On the
2932-
// receiving end we should check for -xcuda to know.
2933-
if (!GpuArgs.empty()) {
2934-
llvm::StringRef Arg0 = GpuArgs[0];
2935-
Arg0 = Arg0.trim().ltrim('-');
2936-
if (Arg0 != "cuda") {
2937-
llvm::errs() << "[CreateInterpreter]: Make sure --cuda is passed as the"
2938-
<< " first argument of the GpuArgs\n";
2939-
return nullptr;
2940-
}
2941-
}
2942-
ClingArgv.insert(ClingArgv.end(), GpuArgs.begin(), GpuArgs.end());
2943-
2944-
// Process externally passed arguments if present.
2945-
std::vector<std::string> ExtraArgs;
2946-
auto EnvOpt =
2947-
llvm::sys::Process::GetEnv("CPPINTEROP_EXTRA_INTERPRETER_ARGS");
2948-
if (EnvOpt) {
2949-
StringRef Env(*EnvOpt);
2950-
while (!Env.empty()) {
2951-
StringRef Arg;
2952-
std::tie(Arg, Env) = Env.split(' ');
2953-
ExtraArgs.push_back(Arg.str());
2954-
}
2955-
}
2956-
std::transform(ExtraArgs.begin(), ExtraArgs.end(),
2957-
std::back_inserter(ClingArgv),
2958-
[&](const std::string& str) { return str.c_str(); });
2959-
2960-
auto I = new compat::Interpreter(ClingArgv.size(), &ClingArgv[0]);
29613023

2962-
// Honor -mllvm.
2963-
//
2964-
// FIXME: Remove this, one day.
2965-
// This should happen AFTER plugins have been loaded!
2966-
const CompilerInstance* Clang = I->getCI();
2967-
if (!Clang->getFrontendOpts().LLVMArgs.empty()) {
2968-
unsigned NumArgs = Clang->getFrontendOpts().LLVMArgs.size();
2969-
auto Args = std::make_unique<const char*[]>(NumArgs + 2);
2970-
Args[0] = "clang (LLVM option parsing)";
2971-
for (unsigned i = 0; i != NumArgs; ++i)
2972-
Args[i + 1] = Clang->getFrontendOpts().LLVMArgs[i].c_str();
2973-
Args[NumArgs + 1] = nullptr;
2974-
llvm::cl::ParseCommandLineOptions(NumArgs + 1, Args.get());
2975-
}
2976-
// FIXME: Enable this assert once we figure out how to fix the multiple
2977-
// calls to CreateInterpreter.
2978-
//assert(!sInterpreter && "Interpreter already set.");
2979-
sInterpreter = I;
2980-
return I;
2981-
}
3024+
// Append user-provided arguments
3025+
ClingArgv.insert(ClingArgv.end(), Args.begin(), Args.end());
3026+
3027+
// Validate and append GPU-specific arguments
3028+
if (!GpuArgs.empty()) {
3029+
llvm::StringRef Arg0 = GpuArgs[0];
3030+
Arg0 = Arg0.trim().ltrim('-');
3031+
if (Arg0 != "cuda") {
3032+
llvm::errs() << "[CreateInterpreter]: Make sure --cuda is passed as the"
3033+
<< " first argument of the GpuArgs\n";
3034+
return nullptr;
3035+
}
3036+
}
3037+
ClingArgv.insert(ClingArgv.end(), GpuArgs.begin(), GpuArgs.end());
3038+
3039+
// Process additional arguments from the environment variable
3040+
auto EnvOpt = llvm::sys::Process::GetEnv("CPPINTEROP_EXTRA_INTERPRETER_ARGS");
3041+
if (EnvOpt) {
3042+
llvm::StringRef Env(*EnvOpt);
3043+
while (!Env.empty()) {
3044+
llvm::StringRef Arg;
3045+
std::tie(Arg, Env) = Env.split(' ');
3046+
ClingArgv.push_back(Arg.str());
3047+
}
3048+
}
3049+
3050+
// Convert std::vector<std::string> to std::vector<const char*> for compatibility
3051+
std::vector<const char*> ClingArgvCStr;
3052+
for (const auto& arg : ClingArgv) {
3053+
ClingArgvCStr.push_back(arg.c_str());
3054+
}
3055+
3056+
// Create the interpreter instance
3057+
auto I = new compat::Interpreter(ClingArgvCStr.size(), ClingArgvCStr.data());
3058+
3059+
// Process LLVM-specific arguments
3060+
const CompilerInstance* Clang = I->getCI();
3061+
if (!Clang->getFrontendOpts().LLVMArgs.empty()) {
3062+
unsigned NumArgs = Clang->getFrontendOpts().LLVMArgs.size();
3063+
auto Args = std::make_unique<const char*[]>(NumArgs + 2);
3064+
Args[0] = "clang (LLVM option parsing)";
3065+
for (unsigned i = 0; i != NumArgs; ++i) {
3066+
Args[i + 1] = Clang->getFrontendOpts().LLVMArgs[i].c_str();
3067+
}
3068+
Args[NumArgs + 1] = nullptr;
3069+
llvm::cl::ParseCommandLineOptions(NumArgs + 1, Args.get());
3070+
}
3071+
3072+
// Set the global interpreter instance
3073+
sInterpreter = I;
3074+
return I;
3075+
}
29823076

29833077
TInterp_t GetInterpreter() { return sInterpreter; }
29843078

unittests/CppInterOp/InterpreterTest.cpp

Lines changed: 14 additions & 0 deletions
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)