Commit 78a87802 authored by Stefan Behnel's avatar Stefan Behnel

second try to fix ticket #583: method signatures of overridden C methods in pure mode

parent 7e54d9a4
...@@ -534,8 +534,9 @@ class CFuncDeclaratorNode(CDeclaratorNode): ...@@ -534,8 +534,9 @@ class CFuncDeclaratorNode(CDeclaratorNode):
if nonempty: if nonempty:
nonempty -= 1 nonempty -= 1
func_type_args = [] func_type_args = []
for arg_node in self.args: for i, arg_node in enumerate(self.args):
name_declarator, type = arg_node.analyse(env, nonempty = nonempty) name_declarator, type = arg_node.analyse(env, nonempty = nonempty,
is_self_arg = (i == 0 and env.is_c_class_scope))
name = name_declarator.name name = name_declarator.name
if name_declarator.cname: if name_declarator.cname:
error(self.pos, error(self.pos,
...@@ -649,8 +650,9 @@ class CArgDeclNode(Node): ...@@ -649,8 +650,9 @@ class CArgDeclNode(Node):
default_value = None default_value = None
annotation = None annotation = None
def analyse(self, env, nonempty = 0): def analyse(self, env, nonempty = 0, is_self_arg = False):
#print "CArgDeclNode.analyse: is_self_arg =", self.is_self_arg ### if is_self_arg:
self.base_type.is_self_arg = self.is_self_arg = True
if self.type is None: if self.type is None:
# The parser may missinterpret names as types... # The parser may missinterpret names as types...
# We fix that here. # We fix that here.
...@@ -1600,7 +1602,7 @@ class CFuncDefNode(FuncDefNode): ...@@ -1600,7 +1602,7 @@ class CFuncDefNode(FuncDefNode):
def analyse_declarations(self, env): def analyse_declarations(self, env):
self.directive_locals.update(env.directives['locals']) self.directive_locals.update(env.directives['locals'])
base_type = self.base_type.analyse(env) base_type = self.base_type.analyse(env)
# The 2 here is because we need both function and argument names. # The 2 here is because we need both function and argument names.
name_declarator, type = self.declarator.analyse(base_type, env, nonempty = 2 * (self.body is not None)) name_declarator, type = self.declarator.analyse(base_type, env, nonempty = 2 * (self.body is not None))
if not type.is_cfunction: if not type.is_cfunction:
error(self.pos, error(self.pos,
...@@ -1907,12 +1909,15 @@ class DefNode(FuncDefNode): ...@@ -1907,12 +1909,15 @@ class DefNode(FuncDefNode):
is_overridable = True) is_overridable = True)
cfunc = CVarDefNode(self.pos, type=cfunc_type) cfunc = CVarDefNode(self.pos, type=cfunc_type)
else: else:
if scope is None:
scope = cfunc.scope
cfunc_type = cfunc.type cfunc_type = cfunc.type
if len(self.args) != len(cfunc_type.args) or cfunc_type.has_varargs: if len(self.args) != len(cfunc_type.args) or cfunc_type.has_varargs:
error(self.pos, "wrong number of arguments") error(self.pos, "wrong number of arguments")
error(cfunc.pos, "previous declaration here") error(cfunc.pos, "previous declaration here")
for formal_arg, type_arg in zip(self.args, cfunc_type.args): for i, (formal_arg, type_arg) in enumerate(zip(self.args, cfunc_type.args)):
name_declarator, type = formal_arg.analyse(cfunc.scope, nonempty=1) name_declarator, type = formal_arg.analyse(scope, nonempty=1,
is_self_arg = (i == 0 and scope.is_c_class_scope))
if type is None or type is PyrexTypes.py_object_type: if type is None or type is PyrexTypes.py_object_type:
formal_arg.type = type_arg.type formal_arg.type = type_arg.type
formal_arg.name_declarator = name_declarator formal_arg.name_declarator = name_declarator
......
...@@ -1233,15 +1233,11 @@ class AlignFunctionDefinitions(CythonTransform): ...@@ -1233,15 +1233,11 @@ class AlignFunctionDefinitions(CythonTransform):
def visit_DefNode(self, node): def visit_DefNode(self, node):
pxd_def = self.scope.lookup(node.name) pxd_def = self.scope.lookup(node.name)
if pxd_def: if pxd_def:
if self.scope.is_c_class_scope and len(pxd_def.type.args) > 0: if not pxd_def.is_cfunction:
# The self parameter type needs adjusting.
pxd_def.type.args[0].type = self.scope.parent_type
if pxd_def.is_cfunction:
node = node.as_cfunction(pxd_def)
else:
error(node.pos, "'%s' redeclared" % node.name) error(node.pos, "'%s' redeclared" % node.name)
error(pxd_def.pos, "previous declaration here") error(pxd_def.pos, "previous declaration here")
return None return None
node = node.as_cfunction(pxd_def)
elif self.scope.is_module_scope and self.directives['auto_cpdef']: elif self.scope.is_module_scope and self.directives['auto_cpdef']:
node = node.as_cfunction(scope=self.scope) node = node.as_cfunction(scope=self.scope)
# Enable this when internal def functions are allowed. # Enable this when internal def functions are allowed.
......
cdef class Base: cdef class Base:
cpdef str method(self) cpdef str noargs(self)
cpdef str int_arg(self, int i)
cpdef str _class(tp)
cdef class Derived(Base): cdef class Derived(Base):
cpdef str method(self) cpdef str noargs(self)
cpdef str int_arg(self, int i)
cpdef str _class(tp)
cdef class DerivedDerived(Derived):
cpdef str noargs(self)
cpdef str int_arg(self, int i)
cpdef str _class(tp)
cdef class Derived2(Base):
cpdef str noargs(self)
cpdef str int_arg(self, int i)
cpdef str _class(tp)
class Base(object): class Base(object):
''' '''
>>> base = Base() >>> base = Base()
>>> print(base.method()) >>> print(base.noargs())
Base
>>> print(base.int_arg(1))
Base
>>> print(base._class())
Base Base
''' '''
def method(self): def noargs(self):
return "Base"
def int_arg(self, i):
return "Base"
@classmethod
def _class(tp):
return "Base" return "Base"
class Derived(Base): class Derived(Base):
''' '''
>>> derived = Derived() >>> derived = Derived()
>>> print(derived.method()) >>> print(derived.noargs())
Derived
>>> print(derived.int_arg(1))
Derived
>>> print(derived._class())
Derived Derived
''' '''
def method(self): def noargs(self):
return "Derived"
def int_arg(self, i):
return "Derived"
@classmethod
def _class(tp):
return "Derived" return "Derived"
class DerivedDerived(Derived):
'''
>>> derived = DerivedDerived()
>>> print(derived.noargs())
DerivedDerived
>>> print(derived.int_arg(1))
DerivedDerived
>>> print(derived._class())
DerivedDerived
'''
def noargs(self):
return "DerivedDerived"
def int_arg(self, i):
return "DerivedDerived"
@classmethod
def _class(tp):
return "DerivedDerived"
class Derived2(Base):
'''
>>> derived = Derived2()
>>> print(derived.noargs())
Derived2
>>> print(derived.int_arg(1))
Derived2
>>> print(derived._class())
Derived2
'''
def noargs(self):
return "Derived2"
def int_arg(self, i):
return "Derived2"
@classmethod
def _class(tp):
return "Derived2"
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