From 191b92312782dfa8fe6f5e45bba5eb59663e8f25 Mon Sep 17 00:00:00 2001
From: Robert Bradshaw <robertwb@gmail.com>
Date: Sun, 13 Jul 2014 02:25:11 -0700
Subject: [PATCH] Fix infinite recurison when using super with cpdef methods.

This should also be a (small) performance improvement.
---
 CHANGES.rst              |  2 ++
 Cython/Compiler/Nodes.py | 13 +++++++++++++
 tests/run/py3k_super.pyx | 24 ++++++++++++++++++++----
 3 files changed, 35 insertions(+), 4 deletions(-)

diff --git a/CHANGES.rst b/CHANGES.rst
index 06949f5f2..ef9f3c969 100644
--- a/CHANGES.rst
+++ b/CHANGES.rst
@@ -84,6 +84,8 @@ Bugs fixed
 
 * Correctly handle ``from cython.submodule cimport name``.
 
+* Fix infinite recursion when using super with cpdef methods.
+
 Other changes
 -------------
 
diff --git a/Cython/Compiler/Nodes.py b/Cython/Compiler/Nodes.py
index 0e8851417..33f7df772 100644
--- a/Cython/Compiler/Nodes.py
+++ b/Cython/Compiler/Nodes.py
@@ -2286,6 +2286,7 @@ class CFuncDefNode(FuncDefNode):
                            "private types")
 
     def call_self_node(self, omit_optional_args=0, is_module_scope=0):
+        # OLD - DELETE
         from . import ExprNodes
         args = self.type.args
         if omit_optional_args:
@@ -2300,6 +2301,18 @@ class CFuncDefNode(FuncDefNode):
         c_call = ExprNodes.SimpleCallNode(self.pos, function=cfunc, args=[ExprNodes.NameNode(self.pos, name=n) for n in arg_names[1-is_module_scope:]], wrapper_call=skip_dispatch)
         return ReturnStatNode(pos=self.pos, return_type=PyrexTypes.py_object_type, value=c_call)
 
+    def call_self_node(self, omit_optional_args=0, is_module_scope=0):
+        from . import ExprNodes
+        args = self.type.args
+        if omit_optional_args:
+            args = args[:len(args) - self.type.optional_arg_count]
+        arg_names = [arg.name for arg in args]
+        cfunc = ExprNodes.PythonCapiFunctionNode(self.pos, self.entry.name, self.entry.func_cname, self.type)
+        cfunc.entry = self.entry
+        skip_dispatch = not is_module_scope or Options.lookup_module_cpdef
+        c_call = ExprNodes.SimpleCallNode(self.pos, function=cfunc, args=[ExprNodes.NameNode(self.pos, name=n) for n in arg_names], wrapper_call=skip_dispatch)
+        return ReturnStatNode(pos=self.pos, return_type=PyrexTypes.py_object_type, value=c_call)
+
     def declare_arguments(self, env):
         for arg in self.type.args:
             if not arg.name:
diff --git a/tests/run/py3k_super.pyx b/tests/run/py3k_super.pyx
index 0fd20f130..97ff3de14 100644
--- a/tests/run/py3k_super.pyx
+++ b/tests/run/py3k_super.pyx
@@ -63,13 +63,29 @@ def test_class_cell_empty():
 
 cdef class CClassBase(object):
     def method(self):
-        return 1
+        return 'def'
+
+#     cpdef method_cp(self):
+#         return 'cpdef'
+#     cdef method_c(self):
+#         return 'cdef'
+#     def call_method_c(self):
+#         return self.method_c()
 
-cdef class CClassSuper(CClassBase):
+cdef class CClassSub(CClassBase):
     """
-    >>> CClassSuper().method()
-    1
+    >>> CClassSub().method()
+    'def'
     """
+#     >>> CClassSub().method_cp()
+#     'cpdef'
+#     >>> CClassSub().call_method_c()
+#     'cdef'
 
     def method(self):
         return super().method()
+
+#     cpdef method_cp(self):
+#         return super().method_cp()
+#     cdef method_c(self):
+#         return super().method_c()
-- 
2.30.9