Commit 68a5d5d7 authored by Stefan Behnel's avatar Stefan Behnel

fix a reference leak for non-simple conditions in boolean and/or expressions

parent 37eea7a5
...@@ -16,6 +16,8 @@ Features added ...@@ -16,6 +16,8 @@ Features added
Bugs fixed Bugs fixed
---------- ----------
* Reference leak for non-simple Python expressions in boolean and/or expressions.
* ``getitimer()``, ``setitimer()``, ``gettimeofday()`` and related type/constant * ``getitimer()``, ``setitimer()``, ``gettimeofday()`` and related type/constant
definitions were moved from ``posix/time.pxd`` to ``posix/sys_time.pxd`` to definitions were moved from ``posix/time.pxd`` to ``posix/sys_time.pxd`` to
fix a naming collision. fix a naming collision.
......
...@@ -10039,20 +10039,30 @@ class BoolBinopResultNode(ExprNode): ...@@ -10039,20 +10039,30 @@ class BoolBinopResultNode(ExprNode):
self.arg.generate_evaluation_code(code) self.arg.generate_evaluation_code(code)
if and_label or or_label: if and_label or or_label:
test_result, uses_temp = self.generate_operand_test(code) test_result, uses_temp = self.generate_operand_test(code)
if uses_temp and (and_label and or_label):
# cannot become final result => free early
# disposal: uses_temp and (and_label and or_label)
self.arg.generate_disposal_code(code)
sense = '!' if or_label else '' sense = '!' if or_label else ''
code.putln("if (%s%s) {" % (sense, test_result)) code.putln("if (%s%s) {" % (sense, test_result))
if uses_temp: if uses_temp:
code.funcstate.release_temp(test_result) code.funcstate.release_temp(test_result)
self.arg.generate_disposal_code(code) if not uses_temp or not (and_label and or_label):
# disposal: (not uses_temp) or {not (and_label and or_label) [if]}
self.arg.generate_disposal_code(code)
if or_label and or_label != fall_through: if or_label and or_label != fall_through:
# value is false => short-circuit to next 'or' # value is false => short-circuit to next 'or'
code.put_goto(or_label) code.put_goto(or_label)
if and_label and and_label != fall_through: if and_label:
# value is true => go to next 'and' # value is true => go to next 'and'
if or_label: if or_label:
code.putln("} else {") code.putln("} else {")
code.put_goto(and_label) if not uses_temp:
# disposal: (not uses_temp) and {(and_label and or_label) [else]}
self.arg.generate_disposal_code(code)
if and_label != fall_through:
code.put_goto(and_label)
if not and_label or not or_label: if not and_label or not or_label:
# if no next 'and' or 'or', we provide the result # if no next 'and' or 'or', we provide the result
...@@ -10062,6 +10072,7 @@ class BoolBinopResultNode(ExprNode): ...@@ -10062,6 +10072,7 @@ class BoolBinopResultNode(ExprNode):
self.value.make_owned_reference(code) self.value.make_owned_reference(code)
code.putln("%s = %s;" % (final_result_temp, self.value.result())) code.putln("%s = %s;" % (final_result_temp, self.value.result()))
self.value.generate_post_assignment_code(code) self.value.generate_post_assignment_code(code)
# disposal: {not (and_label and or_label) [else]}
self.arg.generate_disposal_code(code) self.arg.generate_disposal_code(code)
self.value.free_temps(code) self.value.free_temps(code)
if end_label != fall_through: if end_label != fall_through:
......
def foo(obj1, obj2, obj3, obj4, obj5):
def simple_values(obj1, obj2, obj3, obj4):
""" """
>>> foo(True, False, 23, 'test', 1) >>> simple_values(True, False, 23, 'test')
(0.0, 1.0, False, False) (0.0, 1.0, False, False)
""" """
cdef int bool1, bool2 cdef int bool1, bool2
...@@ -22,3 +23,29 @@ def foo(obj1, obj2, obj3, obj4, obj5): ...@@ -22,3 +23,29 @@ def foo(obj1, obj2, obj3, obj4, obj5):
obj4 = obj1 and obj2 and obj3 obj4 = obj1 and obj2 and obj3
obj5 = (obj1 + obj2 + obj3) and obj4 obj5 = (obj1 + obj2 + obj3) and obj4
return bool3, bool4, obj4, obj5 return bool3, bool4, obj4, obj5
def non_simple_values(obj1, obj2, obj3, obj4):
"""
>>> non_simple_values(1, 2, 3, 4)
(7, 3, 7, 3, 7, 7, 5, 5)
>>> non_simple_values(0, 0, 3, 4)
(0, 7, 4, 4, 4, 4, 4, 4)
>>> non_simple_values(0, 0, 1, -1)
(0, 0, -1, 0, -1, -1, 0, 0)
>>> non_simple_values(1, -1, 1, -1)
(0, 0, 0, 0, 0, 0, 0, 0)
>>> non_simple_values(1, 2, 1, -1)
(0, 3, 0, 3, 0, 0, 1, 1)
>>> non_simple_values(2, 1, 1, -1)
(0, 3, 1, 3, 0, 0, 1, 1)
"""
and1 = obj1 + obj2 and obj3 + obj4
or1 = obj1 + obj2 or obj3 + obj4
and_or = obj1 + obj2 and obj3 + obj4 or obj1 + obj4
or_and = obj1 + obj2 or obj3 + obj4 and obj1 + obj4
and_or_and = obj1 + obj2 and obj3 + obj4 or obj1 + obj4 and obj2 + obj4
and1_or_and = (and1 or (obj1 + obj4 and obj2 + obj4))
or_and_or = (obj1 + obj2 or obj3 + obj4) and (obj1 + obj4 or obj2 + obj4)
or1_and_or = (or1 and (obj1 + obj4 or obj2 + obj4))
return (and1, or1, and_or, or_and, and_or_and, and1_or_and, or_and_or, or1_and_or)
def non_simple_values(obj1, obj2, obj3, obj4):
"""
>>> non_simple_values(1, 2, 3, 4)
(7, 3, 7, 3, 7, 7, 5, 5)
>>> non_simple_values(0, 0, 3, 4)
(0, 7, 4, 4, 4, 4, 4, 4)
>>> non_simple_values(0, 0, 1, -1)
(0, 0, -1, 0, -1, -1, 0, 0)
>>> non_simple_values(1, -1, 1, -1)
(0, 0, 0, 0, 0, 0, 0, 0)
>>> non_simple_values(1, 2, 1, -1)
(0, 3, 0, 3, 0, 0, 1, 1)
>>> non_simple_values(2, 1, 1, -1)
(0, 3, 1, 3, 0, 0, 1, 1)
"""
and1 = obj1 + obj2 and obj3 + obj4
or1 = obj1 + obj2 or obj3 + obj4
and_or = obj1 + obj2 and obj3 + obj4 or obj1 + obj4
or_and = obj1 + obj2 or obj3 + obj4 and obj1 + obj4
and_or_and = obj1 + obj2 and obj3 + obj4 or obj1 + obj4 and obj2 + obj4
and1_or_and = (and1 or (obj1 + obj4 and obj2 + obj4))
or_and_or = (obj1 + obj2 or obj3 + obj4) and (obj1 + obj4 or obj2 + obj4)
or1_and_or = (or1 and (obj1 + obj4 or obj2 + obj4))
return (and1, or1, and_or, or_and, and_or_and, and1_or_and, or_and_or, or1_and_or)
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