Commit 0790e362 authored by Xavier Thompson's avatar Xavier Thompson

Fix reference counting of cypclass operations

parent db5127ae
...@@ -10585,11 +10585,11 @@ class UnopNode(ExprNode): ...@@ -10585,11 +10585,11 @@ class UnopNode(ExprNode):
elif self.is_temp: elif self.is_temp:
if self.is_cpp_operation() and self.exception_check == '+': if self.is_cpp_operation() and self.exception_check == '+':
translate_cpp_exception(code, self.pos, translate_cpp_exception(code, self.pos,
"%s = %s %s;" % (self.result(), self.operator, self.operand.result()), "%s = %s;" % (self.result(), self.calculate_operation_result_code(self.operator)),
self.result() if self.type.is_pyobject else None, self.result() if self.type.is_pyobject else None,
self.exception_value, self.in_nogil_context) self.exception_value, self.in_nogil_context)
else: else:
code.putln("%s = %s %s;" % (self.result(), self.operator, self.operand.result())) code.putln("%s = %s;" % (self.result(), self.calculate_operation_result_code(self.operator)))
def generate_py_operation_code(self, code): def generate_py_operation_code(self, code):
function = self.py_operation_function(code) function = self.py_operation_function(code)
...@@ -10620,6 +10620,8 @@ class UnopNode(ExprNode): ...@@ -10620,6 +10620,8 @@ class UnopNode(ExprNode):
self.is_temp = True self.is_temp = True
if self.exception_value is None: if self.exception_value is None:
env.use_utility_code(UtilityCode.load_cached("CppExceptionConversion", "CppSupport.cpp")) env.use_utility_code(UtilityCode.load_cached("CppExceptionConversion", "CppSupport.cpp"))
if self.op_func_type.return_type.is_cyp_class:
self.is_temp = True
else: else:
self.exception_check = '' self.exception_check = ''
self.exception_value = '' self.exception_value = ''
...@@ -11745,6 +11747,8 @@ class BinopNode(ExprNode): ...@@ -11745,6 +11747,8 @@ class BinopNode(ExprNode):
self.operand1 = self.operand1.coerce_to(func_type.args[0].type, env) self.operand1 = self.operand1.coerce_to(func_type.args[0].type, env)
self.operand2 = self.operand2.coerce_to(func_type.args[1].type, env) self.operand2 = self.operand2.coerce_to(func_type.args[1].type, env)
self.type = func_type.return_type.as_returned_type() self.type = func_type.return_type.as_returned_type()
if self.type.is_cyp_class:
self.is_temp = 1
def result_type(self, type1, type2, env): def result_type(self, type1, type2, env):
if self.is_pythran_operation_types(type1, type2, env): if self.is_pythran_operation_types(type1, type2, env):
...@@ -13191,6 +13195,10 @@ class CmpNode(object): ...@@ -13191,6 +13195,10 @@ class CmpNode(object):
common_type = PyrexTypes.widest_numeric_type(type1, type2) common_type = PyrexTypes.widest_numeric_type(type1, type2)
else: else:
common_type = type1 common_type = type1
if type1.is_cyp_class and op not in ("is", "is_not"):
code1 = "(*%s)" % operand1.result()
code2 = operand2.result()
else:
code1 = operand1.result_as(common_type) code1 = operand1.result_as(common_type)
code2 = operand2.result_as(common_type) code2 = operand2.result_as(common_type)
statement = "%s = %s(%s %s %s);" % ( statement = "%s = %s(%s %s %s);" % (
...@@ -13441,6 +13449,8 @@ class PrimaryCmpNode(ExprNode, CmpNode): ...@@ -13441,6 +13449,8 @@ class PrimaryCmpNode(ExprNode, CmpNode):
self.operand1 = self.operand1.coerce_to(func_type.args[0].type, env) self.operand1 = self.operand1.coerce_to(func_type.args[0].type, env)
self.operand2 = self.operand2.coerce_to(func_type.args[1].type, env) self.operand2 = self.operand2.coerce_to(func_type.args[1].type, env)
self.type = func_type.return_type.as_returned_type() self.type = func_type.return_type.as_returned_type()
if self.type.is_cyp_class:
self.is_temp = True
def analyse_memoryviewslice_comparison(self, env): def analyse_memoryviewslice_comparison(self, env):
have_none = self.operand1.is_none or self.operand2.is_none have_none = self.operand1.is_none or self.operand2.is_none
......
# mode: run
# tag: cpp, cpp11
# cython: experimental_cpp_class_def=True, language_level=2
from libc.stdio cimport printf
cdef cypclass Value:
__dealloc__(self) with gil:
print("Value destroyed")
cdef cypclass Arg:
__dealloc__(self) with gil:
print("Arg destroyed")
cdef cypclass Binop:
Value __add__(self, Arg a):
return Value()
def test_binop():
"""
>>> test_binop()
Arg destroyed
Value destroyed
"""
cdef Value r0
with nogil:
bin = Binop()
r0 = bin + Arg()
cdef cypclass Cmp:
Value __eq__(self, Arg a):
return Value()
def test_cmp():
"""
>>> test_cmp()
Arg destroyed
Value destroyed
"""
cdef Value r0
with nogil:
cmp = Cmp()
r0 = cmp == Arg()
return
cdef cypclass InplaceOps:
Value val
InplaceOps __iadd__(self, Arg a):
self.val = Value()
def test_inplace_ops():
"""
>>> test_inplace_ops()
Arg destroyed
Value destroyed
"""
cdef Value r0
with nogil:
iop = InplaceOps()
iop += Arg()
r0 = iop.val
return
cdef cypclass Call:
Value __call__(self):
return Value()
Value __call__(self, Arg a):
return Value()
def test_call():
"""
>>> test_call()
Arg destroyed
Value destroyed
Value destroyed
"""
cdef Value r0, r1
with nogil:
call = Call()
r0 = call()
r1 = call(Arg())
return
cdef cypclass Index:
__dealloc__(self) with gil:
print("Index destroyed")
cdef cypclass Subscript:
Value value
Index index
__init__(self):
self.value = NULL
self.index = NULL
Value __getitem__(const self, Index index):
if self.index is index:
return value
return NULL
void __setitem__(self, Index index, Value value):
self.index = index
self.value = value
def test_subscript():
"""
>>> test_subscript()
Index destroyed
Value destroyed
"""
cdef Value r0
with nogil:
s = Subscript()
index = Index()
value = Value()
s[index] = value
return
cdef cypclass Unop:
Value __pos__(self):
return Value()
def test_unop():
"""
>>> test_unop()
Value destroyed
"""
cdef Value r0
with nogil:
un = Unop()
r0 = +un
return
def test_typecast():
"""
>>> test_typecast()
Value destroyed
"""
with nogil:
r1 = <cyobject> Value()
return
\ No newline at end of file
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