Skip to content

Commit 67087bd

Browse files
[python] Improve CPyCppyy heuristic for Clone methods
The heuristic checks if the token "Clone" is present in the method name being called and gives Python the ownership of the returned object. This is valid behaviour for methods such as `TObject::Clone` where the ownership of the returned value is given to the caller. But the `CPPOverload::Set` method gets as the method name being called the actual function name concatenated with the full template argument list. For example, given the function ``` template <typename T> void foo(); ``` When it passes through this method its name will be `foo<T>`. This behaviour has an undesired side-effect. When `T` is a type with the token `Clone` in its name, then the heuristic will trigger and Python will take ownership of the return value. This is the root cause of the problem seen at #16725, where `T` is `TClonesArray`. This commit improves on the heuristic by stripping the template argument list from the method name before checking for the presence of the token. Co-authored-by: Jonas Rembser <[email protected]>
1 parent f792d83 commit 67087bd

File tree

1 file changed

+13
-4
lines changed

1 file changed

+13
-4
lines changed

Diff for: bindings/pyroot/cppyy/CPyCppyy/src/CPPOverload.cxx

+13-4
Original file line numberDiff line numberDiff line change
@@ -1072,10 +1072,19 @@ void CPyCppyy::CPPOverload::Set(const std::string& name, std::vector<PyCallable*
10721072
if (name == "__init__")
10731073
fMethodInfo->fFlags |= (CallContext::kIsCreator | CallContext::kIsConstructor);
10741074

1075-
// special case, in heuristics mode also tag *Clone* methods as creators
1076-
if (CallContext::sMemoryPolicy == CallContext::kUseHeuristics && \
1077-
name.find("Clone") != std::string::npos)
1078-
fMethodInfo->fFlags |= CallContext::kIsCreator;
1075+
// special case, in heuristics mode also tag *Clone* methods as creators. Only
1076+
// check that Clone is present in the method name, not in the template argument
1077+
// list.
1078+
if (CallContext::sMemoryPolicy == CallContext::kUseHeuristics) {
1079+
std::string_view name_maybe_template = name;
1080+
auto begin_template = name_maybe_template.find_first_of('<');
1081+
if (begin_template <= name_maybe_template.size()) {
1082+
name_maybe_template = name_maybe_template.substr(0, begin_template);
1083+
}
1084+
if (name_maybe_template.find("Clone") != std::string_view::npos) {
1085+
fMethodInfo->fFlags |= CallContext::kIsCreator;
1086+
}
1087+
}
10791088

10801089
#if PY_VERSION_HEX >= 0x03080000
10811090
fVectorCall = (vectorcallfunc)mp_vectorcall;

0 commit comments

Comments
 (0)