Skip to content

Commit e19a731

Browse files
fix: codegen need not instantiate func body if it can be resolved
This is the case where the the instantiated function is present in one of the libraries loaded or the host application.
1 parent ad1dab7 commit e19a731

File tree

2 files changed

+45
-14
lines changed

2 files changed

+45
-14
lines changed

lib/CppInterOp/CppInterOp.cpp

Lines changed: 22 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1250,10 +1250,8 @@ TCppFuncAddr_t GetFunctionAddress(const char* mangled_name) {
12501250
return nullptr;
12511251
}
12521252

1253-
TCppFuncAddr_t GetFunctionAddress(TCppFunction_t method) {
1254-
auto* D = (Decl*)method;
1255-
1256-
const auto get_mangled_name = [](FunctionDecl* FD) {
1253+
static TCppFuncAddr_t GetFunctionAddress(const FunctionDecl* FD) {
1254+
const auto get_mangled_name = [](const FunctionDecl* FD) {
12571255
auto MangleCtxt = getASTContext().createMangleContext();
12581256

12591257
if (!MangleCtxt->shouldMangleDeclName(FD)) {
@@ -1271,12 +1269,20 @@ TCppFuncAddr_t GetFunctionAddress(TCppFunction_t method) {
12711269
return mangled_name;
12721270
};
12731271

1274-
if (auto* FD = llvm::dyn_cast_or_null<FunctionDecl>(D))
1272+
// Constructor and Destructors needs to be handled differently
1273+
if (!llvm::isa<CXXConstructorDecl>(FD) && !llvm::isa<CXXDestructorDecl>(FD))
12751274
return GetFunctionAddress(get_mangled_name(FD).c_str());
12761275

12771276
return 0;
12781277
}
12791278

1279+
TCppFuncAddr_t GetFunctionAddress(TCppFunction_t method) {
1280+
auto* D = static_cast<Decl*>(method);
1281+
if (auto* FD = llvm::dyn_cast_or_null<FunctionDecl>(D))
1282+
return GetFunctionAddress(FD);
1283+
return nullptr;
1284+
}
1285+
12801286
bool IsVirtualMethod(TCppFunction_t method) {
12811287
auto* D = (Decl*)method;
12821288
if (auto* CXXMD = llvm::dyn_cast_or_null<CXXMethodDecl>(D)) {
@@ -2363,15 +2369,17 @@ int get_wrapper_code(compat::Interpreter& I, const FunctionDecl* FD,
23632369
// header file.
23642370
break;
23652371
}
2366-
if (!Pattern->hasBody()) {
2367-
llvm::errs() << "TClingCallFunc::make_wrapper"
2368-
<< ":"
2369-
<< "Cannot make wrapper for a function template"
2370-
"instantiation with no body!";
2371-
return 0;
2372-
}
2373-
if (FD->isImplicitlyInstantiable()) {
2374-
needInstantiation = true;
2372+
if (!GetFunctionAddress(FD)) {
2373+
if (!Pattern->hasBody()) {
2374+
llvm::errs() << "TClingCallFunc::make_wrapper"
2375+
<< ":"
2376+
<< "Cannot make wrapper for a function template "
2377+
<< "instantiation with no body!";
2378+
return 0;
2379+
}
2380+
if (FD->isImplicitlyInstantiable()) {
2381+
needInstantiation = true;
2382+
}
23752383
}
23762384
} break;
23772385
case FunctionDecl::TK_DependentFunctionTemplateSpecialization: {

unittests/CppInterOp/FunctionReflectionTest.cpp

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1479,6 +1479,12 @@ TEST(FunctionReflectionTest, JitCallAdvanced) {
14791479
clang_Interpreter_dispose(I);
14801480
}
14811481

1482+
template <typename T> T instantiation_in_host() { return T(0); }
1483+
#if defined(_WIN32)
1484+
template __declspec(dllexport) int instantiation_in_host<int>();
1485+
#else
1486+
template int instantiation_in_host<int>();
1487+
#endif
14821488

14831489
TEST(FunctionReflectionTest, GetFunctionCallWrapper) {
14841490
#ifdef EMSCRIPTEN
@@ -1814,6 +1820,23 @@ TEST(FunctionReflectionTest, GetFunctionCallWrapper) {
18141820

18151821
auto fn_callable = Cpp::MakeFunctionCallable(fn);
18161822
EXPECT_EQ(fn_callable.getKind(), Cpp::JitCall::kGenericCall);
1823+
1824+
// instantiation in host, no template function body
1825+
Interp->process("template<typename T> T instantiation_in_host();");
1826+
1827+
unresolved_candidate_methods.clear();
1828+
Cpp::GetClassTemplatedMethods("instantiation_in_host", Cpp::GetGlobalScope(),
1829+
unresolved_candidate_methods);
1830+
EXPECT_EQ(unresolved_candidate_methods.size(), 1);
1831+
1832+
Cpp::TCppScope_t instantiation_in_host = Cpp::BestOverloadFunctionMatch(
1833+
unresolved_candidate_methods, {Cpp::GetType("int")}, {});
1834+
EXPECT_TRUE(instantiation_in_host);
1835+
1836+
auto instantiation_in_host_callable =
1837+
Cpp::MakeFunctionCallable(instantiation_in_host);
1838+
EXPECT_EQ(instantiation_in_host_callable.getKind(),
1839+
Cpp::JitCall::kGenericCall);
18171840
}
18181841

18191842
TEST(FunctionReflectionTest, IsConstMethod) {

0 commit comments

Comments
 (0)