Commit 31d5d476 authored by Stefan Behnel's avatar Stefan Behnel

fix temp leak and crash when assigning a C value to both a Python and C target...

fix temp leak and crash when assigning a C value to both a Python and C target in a cascaded assignment
parent ea071f25
......@@ -4788,10 +4788,11 @@ class CascadedAssignmentNode(AssignmentNode):
#
# Used internally:
#
# coerced_rhs_list [ExprNode] RHS coerced to type of each LHS
# coerced_values [ExprNode] RHS coerced to all distinct LHS types
# cloned_values [ExprNode] cloned RHS value for each LHS
child_attrs = ["lhs_list", "rhs", "coerced_values", "coerced_rhs_list"]
coerced_rhs_list = None
child_attrs = ["lhs_list", "rhs", "coerced_values", "cloned_values"]
cloned_values = None
coerced_values = None
def analyse_declarations(self, env):
......@@ -4801,6 +4802,7 @@ class CascadedAssignmentNode(AssignmentNode):
def analyse_types(self, env, use_temp=0):
from .ExprNodes import CloneNode, ProxyNode
# collect distinct types used on the LHS
lhs_types = set()
for lhs in self.lhs_list:
lhs.analyse_target_types(env)
......@@ -4819,6 +4821,7 @@ class CascadedAssignmentNode(AssignmentNode):
rhs = rhs.coerce_to_simple(env)
self.rhs = ProxyNode(rhs) if rhs.is_temp else rhs
# clone RHS and coerce it to all distinct LHS types
self.coerced_values = []
coerced_values = {}
for lhs in self.lhs_list:
......@@ -4827,22 +4830,28 @@ class CascadedAssignmentNode(AssignmentNode):
self.coerced_values.append(rhs)
coerced_values[lhs.type] = rhs
self.coerced_rhs_list = []
# clone coerced values for all LHS assignments
self.cloned_values = []
for lhs in self.lhs_list:
rhs = coerced_values.get(lhs.type, self.rhs)
self.coerced_rhs_list.append(CloneNode(rhs))
self.cloned_values.append(CloneNode(rhs))
return self
def generate_rhs_evaluation_code(self, code):
self.rhs.generate_evaluation_code(code)
def generate_assignment_code(self, code):
# prepare all coercions
for rhs in self.coerced_values:
rhs.generate_evaluation_code(code)
for lhs, rhs in zip(self.lhs_list, self.coerced_rhs_list):
# assign clones to LHS
for lhs, rhs in zip(self.lhs_list, self.cloned_values):
rhs.generate_evaluation_code(code)
lhs.generate_assignment_code(rhs, code)
# Assignment has disposed of the cloned RHS
# dispose of coerced values and original RHS
for rhs_value in self.coerced_values:
rhs_value.generate_disposal_code(code)
rhs_value.free_temps(code)
self.rhs.generate_disposal_code(code)
self.rhs.free_temps(code)
......@@ -4852,7 +4861,7 @@ class CascadedAssignmentNode(AssignmentNode):
def annotate(self, code):
for rhs in self.coerced_values:
rhs.annotate(code)
for lhs, rhs in zip(self.lhs_list, self.coerced_rhs_list):
for lhs, rhs in zip(self.lhs_list, self.cloned_values):
lhs.annotate(code)
rhs.annotate(code)
self.rhs.annotate(code)
......
......@@ -101,3 +101,18 @@ def assign_carray():
assert b[0] == 2
assert c[1] == 3
return a[0], b[0], c[1]
def pyobject_from_cvalue(table, key):
"""
>>> table = {'X':0, 'Y':1}
>>> pyobject_from_cvalue(table, 'Z')
2
>>> pyobject_from_cvalue(table, 'X')
0
"""
cdef int num
num = table.get(key, -1)
if num < 0:
num = table[key] = len(table)
return num
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