Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
C
cython
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Labels
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Commits
Open sidebar
nexedi
cython
Commits
0790e362
Commit
0790e362
authored
Dec 17, 2020
by
Xavier Thompson
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Fix reference counting of cypclass operations
parent
db5127ae
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
175 additions
and
4 deletions
+175
-4
Cython/Compiler/ExprNodes.py
Cython/Compiler/ExprNodes.py
+14
-4
tests/run/cypclass_operator_refcount.pyx
tests/run/cypclass_operator_refcount.pyx
+161
-0
No files found.
Cython/Compiler/ExprNodes.py
View file @
0790e362
...
@@ -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,8 +13195,12 @@ class CmpNode(object):
...
@@ -13191,8 +13195,12 @@ 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
code1
=
operand1
.
result_as
(
common_type
)
if
type1
.
is_cyp_class
and
op
not
in
(
"is"
,
"is_not"
):
code2
=
operand2
.
result_as
(
common_type
)
code1
=
"(*%s)"
%
operand1
.
result
()
code2
=
operand2
.
result
()
else
:
code1
=
operand1
.
result_as
(
common_type
)
code2
=
operand2
.
result_as
(
common_type
)
statement
=
"%s = %s(%s %s %s);"
%
(
statement
=
"%s = %s(%s %s %s);"
%
(
result_code
,
result_code
,
coerce_result
,
coerce_result
,
...
@@ -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
...
...
tests/run/cypclass_operator_refcount.pyx
0 → 100644
View file @
0790e362
# 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
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment