Skip to content

Commit 5228f93

Browse files
Merge branch 'main' into dev/templ-func-move
2 parents 7c5c911 + 7bb23b9 commit 5228f93

File tree

3 files changed

+64
-16
lines changed

3 files changed

+64
-16
lines changed

include/clang/Interpreter/CppInterOp.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,10 @@
44
#include "CppInterOp/CppInterOp.h"
55
#if defined(_MSC_VER)
66
#pragma message( \
7-
"#include <clang/Interpreter/CppInterOp.h> is deprecated; use #include <CppInterOp/CppInterOp.h")
7+
"#include <clang/Interpreter/CppInterOp.h> is deprecated; use #include <CppInterOp/CppInterOp.h>")
88
#else
99
#warning \
10-
"#include <clang/Interpreter/CppInterOp.h> is deprecated; use #include <CppInterOp/CppInterOp.h"
10+
"#include <clang/Interpreter/CppInterOp.h> is deprecated; use #include <CppInterOp/CppInterOp.h>"
1111
#endif
1212

1313
#endif // CLANG_CPPINTEROP_H

lib/CppInterOp/CppInterOp.cpp

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

1263-
TCppFuncAddr_t GetFunctionAddress(TCppFunction_t method) {
1264-
auto* D = (Decl*)method;
1265-
1266-
const auto get_mangled_name = [](FunctionDecl* FD) {
1263+
static TCppFuncAddr_t GetFunctionAddress(const FunctionDecl* FD) {
1264+
const auto get_mangled_name = [](const FunctionDecl* FD) {
12671265
auto MangleCtxt = getASTContext().createMangleContext();
12681266

12691267
if (!MangleCtxt->shouldMangleDeclName(FD)) {
@@ -1281,12 +1279,20 @@ TCppFuncAddr_t GetFunctionAddress(TCppFunction_t method) {
12811279
return mangled_name;
12821280
};
12831281

1284-
if (auto* FD = llvm::dyn_cast_or_null<FunctionDecl>(D))
1282+
// Constructor and Destructors needs to be handled differently
1283+
if (!llvm::isa<CXXConstructorDecl>(FD) && !llvm::isa<CXXDestructorDecl>(FD))
12851284
return GetFunctionAddress(get_mangled_name(FD).c_str());
12861285

12871286
return 0;
12881287
}
12891288

1289+
TCppFuncAddr_t GetFunctionAddress(TCppFunction_t method) {
1290+
auto* D = static_cast<Decl*>(method);
1291+
if (auto* FD = llvm::dyn_cast_or_null<FunctionDecl>(D))
1292+
return GetFunctionAddress(FD);
1293+
return nullptr;
1294+
}
1295+
12901296
bool IsVirtualMethod(TCppFunction_t method) {
12911297
auto* D = (Decl*)method;
12921298
if (auto* CXXMD = llvm::dyn_cast_or_null<CXXMethodDecl>(D)) {
@@ -2387,15 +2393,17 @@ int get_wrapper_code(compat::Interpreter& I, const FunctionDecl* FD,
23872393
// header file.
23882394
break;
23892395
}
2390-
if (!Pattern->hasBody()) {
2391-
llvm::errs() << "TClingCallFunc::make_wrapper"
2392-
<< ":"
2393-
<< "Cannot make wrapper for a function template"
2394-
"instantiation with no body!";
2395-
return 0;
2396-
}
2397-
if (FD->isImplicitlyInstantiable()) {
2398-
needInstantiation = true;
2396+
if (!GetFunctionAddress(FD)) {
2397+
if (!Pattern->hasBody()) {
2398+
llvm::errs() << "TClingCallFunc::make_wrapper"
2399+
<< ":"
2400+
<< "Cannot make wrapper for a function template "
2401+
<< "instantiation with no body!";
2402+
return 0;
2403+
}
2404+
if (FD->isImplicitlyInstantiable()) {
2405+
needInstantiation = true;
2406+
}
23992407
}
24002408
} break;
24012409
case FunctionDecl::TK_DependentFunctionTemplateSpecialization: {

unittests/CppInterOp/FunctionReflectionTest.cpp

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1421,6 +1421,8 @@ TEST(FunctionReflectionTest, GetFunctionAddress) {
14211421
std::stringstream address;
14221422
address << Cpp::GetFunctionAddress(Decls[0]);
14231423
EXPECT_EQ(address.str(), output);
1424+
1425+
EXPECT_FALSE(Cpp::GetFunctionAddress(Cpp::GetGlobalScope()));
14241426
}
14251427

14261428
TEST(FunctionReflectionTest, IsVirtualMethod) {
@@ -1489,6 +1491,15 @@ TEST(FunctionReflectionTest, JitCallAdvanced) {
14891491
clang_Interpreter_dispose(I);
14901492
}
14911493

1494+
template <typename T> T instantiation_in_host() { return T(0); }
1495+
#if defined(_WIN32)
1496+
template __declspec(dllexport) int instantiation_in_host<int>();
1497+
#elif defined(__GNUC__)
1498+
template __attribute__((__visibility__("default"))) int
1499+
instantiation_in_host<int>();
1500+
#else
1501+
template int instantiation_in_host<int>();
1502+
#endif
14921503

14931504
TEST(FunctionReflectionTest, GetFunctionCallWrapper) {
14941505
#ifdef EMSCRIPTEN
@@ -1844,6 +1855,35 @@ TEST(FunctionReflectionTest, GetFunctionCallWrapper) {
18441855

18451856
auto call_move_callable = Cpp::MakeFunctionCallable(call_move);
18461857
EXPECT_EQ(call_move_callable.getKind(), Cpp::JitCall::kGenericCall);
1858+
1859+
// instantiation in host, no template function body
1860+
Interp->process("template<typename T> T instantiation_in_host();");
1861+
1862+
unresolved_candidate_methods.clear();
1863+
Cpp::GetClassTemplatedMethods("instantiation_in_host", Cpp::GetGlobalScope(),
1864+
unresolved_candidate_methods);
1865+
EXPECT_EQ(unresolved_candidate_methods.size(), 1);
1866+
1867+
Cpp::TCppScope_t instantiation_in_host = Cpp::BestOverloadFunctionMatch(
1868+
unresolved_candidate_methods, {Cpp::GetType("int")}, {});
1869+
EXPECT_TRUE(instantiation_in_host);
1870+
1871+
Cpp::JitCall instantiation_in_host_callable =
1872+
Cpp::MakeFunctionCallable(instantiation_in_host);
1873+
EXPECT_EQ(instantiation_in_host_callable.getKind(),
1874+
Cpp::JitCall::kGenericCall);
1875+
1876+
instantiation_in_host = Cpp::BestOverloadFunctionMatch(
1877+
unresolved_candidate_methods, {Cpp::GetType("double")}, {});
1878+
EXPECT_TRUE(instantiation_in_host);
1879+
1880+
Cpp::BeginStdStreamCapture(Cpp::CaptureStreamKind::kStdErr);
1881+
instantiation_in_host_callable =
1882+
Cpp::MakeFunctionCallable(instantiation_in_host);
1883+
std::string err_msg = Cpp::EndStdStreamCapture();
1884+
EXPECT_TRUE(err_msg.find("instantiation with no body") != std::string::npos);
1885+
EXPECT_EQ(instantiation_in_host_callable.getKind(),
1886+
Cpp::JitCall::kUnknown); // expect to fail
18471887
}
18481888

18491889
TEST(FunctionReflectionTest, IsConstMethod) {

0 commit comments

Comments
 (0)