Commit efbff337 authored by Torsten Landschoff's avatar Torsten Landschoff

Change tp_clear generation to clear to NULL.

Better to crash early than to never know that the reference changed to
None. See discussion here:

http://article.gmane.org/gmane.comp.python.cython.devel/14833
parent 1af954ae
...@@ -1367,7 +1367,6 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode): ...@@ -1367,7 +1367,6 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
if py_attrs or py_buffers: if py_attrs or py_buffers:
self.generate_self_cast(scope, code) self.generate_self_cast(scope, code)
code.putln("PyObject* tmp;")
if base_type: if base_type:
# want to call it explicitly if possible so inlining can be performed # want to call it explicitly if possible so inlining can be performed
...@@ -1390,13 +1389,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode): ...@@ -1390,13 +1389,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
UtilityCode.load_cached("CallNextTpClear", "ExtensionTypes.c")) UtilityCode.load_cached("CallNextTpClear", "ExtensionTypes.c"))
for entry in py_attrs: for entry in py_attrs:
name = "p->%s" % entry.cname code.putln("Py_CLEAR(p->%s);" % entry.cname)
code.putln("tmp = ((PyObject*)%s);" % name)
if entry.is_declared_generic:
code.put_init_to_py_none(name, py_object_type, nanny=False)
else:
code.put_init_to_py_none(name, entry.type, nanny=False)
code.putln("Py_XDECREF(tmp);")
for entry in py_buffers: for entry in py_buffers:
# Note: shouldn't this call __Pyx_ReleaseBuffer ?? # Note: shouldn't this call __Pyx_ReleaseBuffer ??
......
"""
Check that Cython generates a tp_clear function that actually clears object
references to NULL instead of None.
Discussed here: http://article.gmane.org/gmane.comp.python.cython.devel/14833
"""
from cpython.ref cimport PyObject, Py_TYPE
cdef class ExtensionType:
"""
Just a type which is handled by a specific C type (instead of PyObject)
to check that tp_clear works when the C pointer is of a type different
from PyObject *.
"""
# Pull tp_clear for PyTypeObject as I did not find another way to access it
# from Cython code.
cdef extern from "Python.h":
ctypedef struct PyTypeObject:
void (*tp_clear)(object)
cdef class TpClearFixture:
"""
An extension type that has a tp_clear method generated to test that it
actually clears the references to NULL.
>>> fixture = TpClearFixture()
>>> isinstance(fixture.extension_type, ExtensionType)
True
>>> isinstance(fixture.any_object, str)
True
>>> fixture.call_tp_clear()
>>> fixture.check_any_object_status()
'NULL'
>>> fixture.check_extension_type_status()
'NULL'
"""
cdef public object any_object
cdef public ExtensionType extension_type
def __cinit__(self):
self.any_object = "Hello World"
self.extension_type = ExtensionType()
cpdef public call_tp_clear(self):
cdef PyTypeObject *pto = Py_TYPE(self)
pto.tp_clear(self)
cpdef public str check_any_object_status(self):
if <void*>(self.any_object) == NULL:
return 'NULL'
elif self.any_object is None:
return 'None'
else:
return 'not cleared'
cpdef public str check_extension_type_status(self):
if <void*>(self.any_object) == NULL:
return 'NULL'
elif self.any_object is None:
return 'None'
else:
return 'not cleared'
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