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): ...@@ -4788,10 +4788,11 @@ class CascadedAssignmentNode(AssignmentNode):
# #
# Used internally: # 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"] child_attrs = ["lhs_list", "rhs", "coerced_values", "cloned_values"]
coerced_rhs_list = None cloned_values = None
coerced_values = None coerced_values = None
def analyse_declarations(self, env): def analyse_declarations(self, env):
...@@ -4801,6 +4802,7 @@ class CascadedAssignmentNode(AssignmentNode): ...@@ -4801,6 +4802,7 @@ class CascadedAssignmentNode(AssignmentNode):
def analyse_types(self, env, use_temp=0): def analyse_types(self, env, use_temp=0):
from .ExprNodes import CloneNode, ProxyNode from .ExprNodes import CloneNode, ProxyNode
# collect distinct types used on the LHS
lhs_types = set() lhs_types = set()
for lhs in self.lhs_list: for lhs in self.lhs_list:
lhs.analyse_target_types(env) lhs.analyse_target_types(env)
...@@ -4819,6 +4821,7 @@ class CascadedAssignmentNode(AssignmentNode): ...@@ -4819,6 +4821,7 @@ class CascadedAssignmentNode(AssignmentNode):
rhs = rhs.coerce_to_simple(env) rhs = rhs.coerce_to_simple(env)
self.rhs = ProxyNode(rhs) if rhs.is_temp else rhs self.rhs = ProxyNode(rhs) if rhs.is_temp else rhs
# clone RHS and coerce it to all distinct LHS types
self.coerced_values = [] self.coerced_values = []
coerced_values = {} coerced_values = {}
for lhs in self.lhs_list: for lhs in self.lhs_list:
...@@ -4827,22 +4830,28 @@ class CascadedAssignmentNode(AssignmentNode): ...@@ -4827,22 +4830,28 @@ class CascadedAssignmentNode(AssignmentNode):
self.coerced_values.append(rhs) self.coerced_values.append(rhs)
coerced_values[lhs.type] = 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: for lhs in self.lhs_list:
rhs = coerced_values.get(lhs.type, self.rhs) rhs = coerced_values.get(lhs.type, self.rhs)
self.coerced_rhs_list.append(CloneNode(rhs)) self.cloned_values.append(CloneNode(rhs))
return self return self
def generate_rhs_evaluation_code(self, code): def generate_rhs_evaluation_code(self, code):
self.rhs.generate_evaluation_code(code) self.rhs.generate_evaluation_code(code)
def generate_assignment_code(self, code): def generate_assignment_code(self, code):
# prepare all coercions
for rhs in self.coerced_values: for rhs in self.coerced_values:
rhs.generate_evaluation_code(code) 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) rhs.generate_evaluation_code(code)
lhs.generate_assignment_code(rhs, 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.generate_disposal_code(code)
self.rhs.free_temps(code) self.rhs.free_temps(code)
...@@ -4852,7 +4861,7 @@ class CascadedAssignmentNode(AssignmentNode): ...@@ -4852,7 +4861,7 @@ class CascadedAssignmentNode(AssignmentNode):
def annotate(self, code): def annotate(self, code):
for rhs in self.coerced_values: for rhs in self.coerced_values:
rhs.annotate(code) 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) lhs.annotate(code)
rhs.annotate(code) rhs.annotate(code)
self.rhs.annotate(code) self.rhs.annotate(code)
......
...@@ -101,3 +101,18 @@ def assign_carray(): ...@@ -101,3 +101,18 @@ def assign_carray():
assert b[0] == 2 assert b[0] == 2
assert c[1] == 3 assert c[1] == 3
return a[0], b[0], c[1] 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