From f7e77cdc290825c173e4eac5c95e17ed19a0fc06 Mon Sep 17 00:00:00 2001 From: gsamain <gwenael.samain@nexedi.com> Date: Mon, 8 Jul 2019 11:24:34 +0000 Subject: [PATCH] Make declaration of cypclass methods work when declaring without defining a pointer type as return type --- Cython/Compiler/Nodes.py | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/Cython/Compiler/Nodes.py b/Cython/Compiler/Nodes.py index d6a1ba5ef..9df1fb331 100644 --- a/Cython/Compiler/Nodes.py +++ b/Cython/Compiler/Nodes.py @@ -1391,28 +1391,35 @@ class CVarDefNode(StatNode): return if type.is_reference and self.visibility != 'extern': error(declarator.pos, "C++ references cannot be declared; use a pointer instead") + cfunc_declarator = declarator if type.is_cfunction: + while not isinstance(cfunc_declarator, (CFuncDeclaratorNode, CNameDeclaratorNode)): + cfunc_declarator = cfunc_declarator.base + if isinstance(cfunc_declarator, CNameDeclaratorNode): + # It's probably a typedef'ed attribute, in which case the self + # handling has already been done, so skip all self hacks. + cfunc_declarator = None if 'staticmethod' in env.directives: type.is_static_method = True - elif name in ("__new__", "__alloc__") and\ + elif cfunc_declarator and name in ("__new__", "__alloc__") and\ env.is_cpp_class_scope and env.parent_type.is_cyp_class: type.is_static_method = True - if declarator.skipped_self: - _name, _type, _pos, _arg = declarator.skipped_self + if cfunc_declarator.skipped_self: + _name, _type, _pos, _arg = cfunc_declarator.skipped_self if name == "__new__": _type = PyrexTypes.CPtrType(PyrexTypes.CFuncType(_type, [], nogil=1)) # aka _type = {class_type} (*f)() nogil reinjected_arg = PyrexTypes.CFuncTypeArg(_name, _type, _pos) type.args = [reinjected_arg] + type.args - declarator.args = [_arg] + declarator.args + cfunc_declarator.args = [_arg] + cfunc_declarator.args elif name == "__alloc__": # Force __alloc__ to have the signature: # {class_type} f() nogil type.return_type = _type type.args = [] - declarator.args = [] - declarator.skipped_self = None + cfunc_declarator.args = [] + cfunc_declarator.skipped_self = None self.entry = dest_scope.declare_cfunction( name, type, declarator.pos, @@ -1423,8 +1430,8 @@ class CVarDefNode(StatNode): if create_extern_wrapper: self.entry.type.create_to_py_utility_code(env) self.entry.create_wrapper = True - if env.is_cpp_class_scope and env.parent_type.is_cyp_class\ - and not declarator.skipped_self and not type.is_static_method: + if cfunc_declarator and type.is_cfunction and env.is_cpp_class_scope and env.parent_type.is_cyp_class\ + and not cfunc_declarator.skipped_self and not type.is_static_method: # It means we have a cypclass method without the self argument # => shout error(self.pos, "Cypclass methods must have a self argument") -- 2.30.9