Commit 5c79474f authored by Xavier Thompson's avatar Xavier Thompson

Fix template cypclass field reference counting

parent 7f1cf72d
......@@ -7759,8 +7759,9 @@ class AttributeNode(ExprNode):
elif self.type.is_cyp_class:
rhs.make_owned_reference(code)
rhs.generate_giveref(code)
code.put_gotref(select_code, self.type)
code.put_xdecref(select_code, self.type)
if not self.entry.is_specialised:
code.put_gotref(select_code, self.type)
code.put_xdecref(select_code, self.type)
if not self.type.is_memoryviewslice:
code.putln(
......
......@@ -6022,7 +6022,12 @@ class SingleAssignmentNode(AssignmentNode):
not rhs.is_name and not rhs.is_literal and
(rhs.type.is_pyobject or rhs.type.is_cyp_class)):
# things like (cdef) attribute access are not safe (traverses pointers)
rhs = rhs.coerce_to_temp(env)
if rhs.is_attribute and rhs.type.is_cyp_class and rhs.entry.is_specialised:
rhs = rhs.coerce_to_temp(env)
# cypclass fields specialised from a template do their own reference counting.
rhs.use_managed_ref = False
else:
rhs = rhs.coerce_to_temp(env)
elif rhs.type.is_pyobject:
rhs = rhs.coerce_to_simple(env)
self.rhs = rhs
......@@ -6576,7 +6581,10 @@ class DelStatNode(StatNode):
arg.free_temps(code)
elif arg.type.is_cyp_class:
arg.generate_evaluation_code(code)
code.put_xdecref_clear(arg.result(), arg.type)
if arg.is_attribute and arg.entry.is_specialised:
code.putln("%s = nullptr;" % arg.result())
else:
code.put_xdecref_clear(arg.result(), arg.type)
arg.generate_disposal_code(code)
arg.free_temps(code)
# else error reported earlier
......
......@@ -182,6 +182,8 @@ class Entry(object):
# active_entry Entry Entry for the active version of an asyncable cypclass method
#
# is_consumed boolean The entry is the operand of a 'consume' expression.
#
# is_specialised boolean The entry is a template specialisation.
# TODO: utility_code and utility_code_definition serves the same purpose...
......@@ -261,6 +263,7 @@ class Entry(object):
original_name = None
active_entry = None
is_consumed = False
is_specialised = False
def __init__(self, name, cname, type, pos = None, init = None):
self.name = name
......@@ -3136,11 +3139,12 @@ class CppClassScope(Scope):
e.cname,
utility_code=e.utility_code)
else:
scope.declare_var(entry.name,
e = scope.declare_var(entry.name,
entry.type.specialize(values),
entry.pos,
entry.cname,
entry.visibility)
e.is_specialised = True
return scope
......
......@@ -129,3 +129,57 @@ def test_getting_and_setting():
if Cy_GETREF(v) != 3:
return -(i+2)
return 0
def test_field_getting():
"""
>>> test_field_getting()
Template destroyed
Value destroyed
0
"""
v = Value()
h = Template[Value](v)
if Cy_GETREF(v) != 3:
return -1
for i in range(10):
v = h.value
if Cy_GETREF(v) != 3:
return -(i+2)
return 0
def test_field_setting():
"""
>>> test_field_setting()
Template destroyed
Value destroyed
0
"""
h = Template[Value](NULL)
v = Value()
for i in range(10):
h.value = v
if Cy_GETREF(v) != 3:
return -(i+1)
return 0
def test_field_deleting():
"""
>>> test_field_deleting()
Template destroyed
Value destroyed
0
"""
v = Value()
h = Template[Value](v)
if Cy_GETREF(v) != 3:
return -1
del h.value
if Cy_GETREF(v) != 2:
return -1
del h
return 0
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