Commit 0e80efb8 authored by Ashwin Srinath's avatar Ashwin Srinath Committed by GitHub

Correctly process the entries of overloaded extern static C++ methods (GH-4129)

Closes https://github.com/cython/cython/issues/1851
parent 535cba08
......@@ -7012,29 +7012,11 @@ class AttributeNode(ExprNode):
return None
ubcm_entry = entry
else:
# Create a temporary entry describing the C method
# as an ordinary function.
if entry.func_cname and not hasattr(entry.type, 'op_arg_struct'):
cname = entry.func_cname
if entry.type.is_static_method or (
env.parent_scope and env.parent_scope.is_cpp_class_scope):
ctype = entry.type
elif type.is_cpp_class:
error(self.pos, "%s not a static member of %s" % (entry.name, type))
ctype = PyrexTypes.error_type
else:
# Fix self type.
ctype = copy.copy(entry.type)
ctype.args = ctype.args[:]
ctype.args[0] = PyrexTypes.CFuncTypeArg('self', type, 'self', None)
else:
cname = "%s->%s" % (type.vtabptr_cname, entry.cname)
ctype = entry.type
ubcm_entry = Symtab.Entry(entry.name, cname, ctype)
ubcm_entry.is_cfunction = 1
ubcm_entry.func_cname = entry.func_cname
ubcm_entry.is_unbound_cmethod = 1
ubcm_entry.scope = entry.scope
ubcm_entry = self._create_unbound_cmethod_entry(type, entry, env)
ubcm_entry.overloaded_alternatives = [
self._create_unbound_cmethod_entry(type, overloaded_alternative, env)
for overloaded_alternative in entry.overloaded_alternatives
]
return self.as_name_node(env, ubcm_entry, target=False)
elif type.is_enum or type.is_cpp_enum:
if self.attribute in type.values:
......@@ -7047,6 +7029,32 @@ class AttributeNode(ExprNode):
error(self.pos, "%s not a known value of %s" % (self.attribute, type))
return None
def _create_unbound_cmethod_entry(self, type, entry, env):
# Create a temporary entry describing the unbound C method in `entry`
# as an ordinary function.
if entry.func_cname and entry.type.op_arg_struct is None:
cname = entry.func_cname
if entry.type.is_static_method or (
env.parent_scope and env.parent_scope.is_cpp_class_scope):
ctype = entry.type
elif type.is_cpp_class:
error(self.pos, "%s not a static member of %s" % (entry.name, type))
ctype = PyrexTypes.error_type
else:
# Fix self type.
ctype = copy.copy(entry.type)
ctype.args = ctype.args[:]
ctype.args[0] = PyrexTypes.CFuncTypeArg('self', type, 'self', None)
else:
cname = "%s->%s" % (type.vtabptr_cname, entry.cname)
ctype = entry.type
ubcm_entry = Symtab.Entry(entry.name, cname, ctype)
ubcm_entry.is_cfunction = 1
ubcm_entry.func_cname = entry.func_cname
ubcm_entry.is_unbound_cmethod = 1
ubcm_entry.scope = entry.scope
return ubcm_entry
def analyse_as_type(self, env):
module_scope = self.obj.analyse_as_module(env)
if module_scope:
......
......@@ -2841,12 +2841,14 @@ class CFuncType(CType):
# (used for optimisation overrides)
# is_const_method boolean
# is_static_method boolean
# op_arg_struct CPtrType Pointer to optional argument struct
is_cfunction = 1
original_sig = None
cached_specialized_types = None
from_fused = False
is_const_method = False
op_arg_struct = None
subtypes = ['return_type', 'args']
......
# mode: run
# tag: cpp
cdef extern from *:
"""
struct Foo
{
static const char* bar(int x, int y) {
return "second";
}
static const char* bar(int x) {
return "first";
}
const char* baz(int x, int y) {
return "second";
}
const char* baz(int x) {
return "first";
}
};
"""
cppclass Foo:
@staticmethod
const char* bar(int x)
@staticmethod
const char* bar(int x, int y)
const char* baz(int x)
const char* baz(int x, int y)
def test_normal_method_overload():
"""
>>> test_normal_method_overload()
"""
cdef Foo f
assert f.baz(1) == b"first"
assert f.baz(1, 2) == b"second"
def test_static_method_overload():
"""
>>> test_static_method_overload()
"""
assert Foo.bar(1) == b"first"
assert Foo.bar(1, 2) == b"second"
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment