Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ include(GNUInstallDirs)
# This option won't make a lot of sense since we only ship the shared library in site-packages
# Perhaps this should permanently be OFF and users can build their own CppInterOp if they want to run the tests?
option(CPPJIT_ENABLE_CPPINTEROP_TESTS "enable CppInterOp tests" OFF)
set(CPPINTEROP_GIT_REPOSITORY "https://github.com/compiler-research/CppInterOp.git" CACHE STRING "")
set(CPPINTEROP_GIT_TAG "f4adaa6b50542dd564089fe584d407bf15351c97" CACHE STRING "")
set(CPPINTEROP_GIT_REPOSITORY "https://github.com/Vipul-Cariappa/CppInterOp.git" CACHE STRING "")
set(CPPINTEROP_GIT_TAG "dev/best-overload-function-match" CACHE STRING "")
set(CPPINTEROP_SOURCE_DIR "" CACHE PATH
"Override default CppInterOp built by ExternalProject_Add, with a path to local CppInterOp source")

Expand Down
20 changes: 16 additions & 4 deletions src/cpyrt/TemplateProxy.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ using namespace cppjit;
#include "CPPClassMethod.h"
#include "CPPConstructor.h"
#include "CPPFunction.h"
#include "CPPInstance.h"
#include "CPPMethod.h"
#include "CPPOverload.h"
#include "PyCallable.h"
Expand Down Expand Up @@ -81,14 +82,17 @@ PyObject* TemplateProxy::Instantiate(const std::string& fname,
std::string proto = "";

// adjust arguments for self if this is a rebound global function
PyObject* self = nullptr;
bool isNS = (((CPPScope*)fTI->fPyClass)->fFlags & CPPScope::kIsNamespace);
bool isStaticMethod =
interop::IsStaticTemplate(((CPPScope*)fTI->fPyClass)->fCppType, fname);
if (!isNS && cpyrt_PyArgs_GET_SIZE(args, nargsf) &&
(!fSelf || (fSelf == Py_None &&
!interop::IsStaticTemplate(
((CPPScope*)fTI->fPyClass)->fCppType, fname)))) {
(!fSelf || (fSelf == Py_None && !isStaticMethod))) {
self = args[0];
args += 1;
nargsf -= 1;
}
} else if (fSelf && fSelf != Py_None && !isStaticMethod)
self = fSelf;

Py_ssize_t argc = cpyrt_PyArgs_GET_SIZE(args, nargsf);
if (argc != 0) {
Expand Down Expand Up @@ -190,6 +194,14 @@ PyObject* TemplateProxy::Instantiate(const std::string& fname,

// the following causes instantiation as necessary
interop::TCppScope_t scope = ((CPPClass*)fTI->fPyClass)->fCppType;
if (self && CPPInstance_Check(self) && interop::GetName(scope) != fname) {
std::string self_name =
interop::GetScopedFinalName(((CPPInstance*)self)->ObjectIsA(true));
if (proto.empty())
proto = self_name + '&';
else
proto = self_name + "&, " + proto;
}
interop::TCppMethod_t cppmeth =
interop::GetMethodTemplate(scope, fname, proto);
if (cppmeth) { // overload stops here
Expand Down
48 changes: 31 additions & 17 deletions src/interop/interop_wrapper.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -1483,9 +1483,29 @@ bool interop::IsTemplatedMethod(TCppMethod_t method) {
return Cpp::IsTemplatedFunction(method);
}

static void ResolveMethodsFromName(
interop::TCppScope_t scope, const std::string& name, std::string& pureName,
std::string& explicitParams,
std::vector<interop::TCppMethod_t>& unresolved_candidate_methods) {
if ((name.find("operator<") != 0) && (name.find('<') != std::string::npos)) {
pureName = name.substr(0, name.find('<'));
size_t start = name.find('<');
size_t end = name.rfind('>');
explicitParams = name.substr(start + 1, end - start - 1);
} else {
pureName = name;
}

std::lock_guard<std::recursive_mutex> Lock(InterOpMutex);
Cpp::GetClassTemplatedMethods(pureName, scope, unresolved_candidate_methods);
}

bool interop::IsStaticTemplate(TCppScope_t scope, const std::string& name) {
std::vector<TCppMethod_t> candidate_methods;
Cpp::GetClassTemplatedMethods(name, scope, candidate_methods);
std::string pureName;
std::string explicit_params;
ResolveMethodsFromName(scope, name, pureName, explicit_params,
candidate_methods);
bool is_static = true;
for (auto i : candidate_methods) {
if (!Cpp::IsStaticMethod(i)) {
Expand All @@ -1501,20 +1521,11 @@ interop::TCppMethod_t interop::GetMethodTemplate(TCppScope_t scope,
const std::string& proto) {
std::string pureName;
std::string explicit_params;

if ((name.find("operator<") != 0) && (name.find('<') != std::string::npos)) {
pureName = name.substr(0, name.find('<'));
size_t start = name.find('<');
size_t end = name.rfind('>');
explicit_params = name.substr(start + 1, end - start - 1);
} else {
pureName = name;
}
std::vector<interop::TCppMethod_t> unresolved_candidate_methods;
ResolveMethodsFromName(scope, name, pureName, explicit_params,
unresolved_candidate_methods);

std::lock_guard<std::recursive_mutex> Lock(InterOpMutex);

std::vector<interop::TCppMethod_t> unresolved_candidate_methods;
Cpp::GetClassTemplatedMethods(pureName, scope, unresolved_candidate_methods);
if (unresolved_candidate_methods.empty() && name.find("operator") == 0) {
// try operators
interop::GetClassOperators(scope, pureName, unresolved_candidate_methods);
Expand All @@ -1526,8 +1537,10 @@ interop::TCppMethod_t interop::GetMethodTemplate(TCppScope_t scope,
interop::AppendTypesSlow(proto, arg_types, scope);
interop::AppendTypesSlow(explicit_params, templ_params, scope);
interop::TCppMethod_t cppmeth = nullptr;
cppmeth = Cpp::BestOverloadFunctionMatch(unresolved_candidate_methods,
templ_params, arg_types);
std::vector<Cpp::FuncRef> ambiguous_candidates;
cppmeth =
Cpp::BestOverloadFunctionMatch(unresolved_candidate_methods, templ_params,
arg_types, ambiguous_candidates);

// If overload resolution failed but explicit template arguments were
// supplied, fall back to direct template-argument substitution: ask Sema
Expand Down Expand Up @@ -1612,8 +1625,9 @@ interop::TCppMethod_t interop::GetGlobalOperator(TCppScope_t scope,
else
return nullptr;
}
interop::TCppMethod_t cppmeth =
Cpp::BestOverloadFunctionMatch(overloads, {}, arg_types);
std::vector<Cpp::FuncRef> ambiguous_candidates;
interop::TCppMethod_t cppmeth = Cpp::BestOverloadFunctionMatch(
overloads, {}, arg_types, ambiguous_candidates);
if (cppmeth)
return cppmeth;
return nullptr;
Expand Down
5 changes: 2 additions & 3 deletions test/test_templates.py
Original file line number Diff line number Diff line change
Expand Up @@ -439,11 +439,12 @@ def get_tn(ns):
return tn

# templated class
A = ns.A["int", "double"]
a = ns.A["int", "double"]()
assert get_tn(ns) == "some_variadic::A<int,double>"

# static functions
a.sa(1, 1.0, "a")
A.sa(1, 1.0, "a")
assert (
get_tn(ns).find("some_variadic::A<int,double>::void(int&&,double&&,std::")
== 0
Expand Down Expand Up @@ -480,8 +481,6 @@ def get_tn(ns):
assert get_tn(ns) == "some_variadic::B"

# static functions
b.sb(1, 1.0, "a")
assert get_tn(ns).find("some_variadic::B::void(int&&,double&&,std::") == 0
ns.B.sb(1, 1.0, "a")
assert get_tn(ns).find("some_variadic::B::void(int&&,double&&,std::") == 0
ns.B.sb_T["int"](1, 1.0, "a")
Expand Down
Loading