From 940fed5e255ceddab0881992fd4e8ab1e7b6a4db Mon Sep 17 00:00:00 2001 From: Stefan Behnel Date: Sun, 9 May 2010 13:14:09 +0200 Subject: [PATCH] fix ticket #533: 'continue' in the 'else' block of a for-in-loop leaks a reference --- Cython/Compiler/Nodes.py | 19 +++++++++++++++++- tests/run/for_in_break_continue_T533.pyx | 25 ++++++++++++++++++++++++ 2 files changed, 43 insertions(+), 1 deletion(-) diff --git a/Cython/Compiler/Nodes.py b/Cython/Compiler/Nodes.py index d4d3a556..f1ee64a5 100644 --- a/Cython/Compiler/Nodes.py +++ b/Cython/Compiler/Nodes.py @@ -4095,11 +4095,28 @@ class ForInStatNode(LoopNode, StatNode): "}") break_label = code.break_label code.set_loop_labels(old_loop_labels) + if self.else_clause: + # in nested loops, the 'else' block can contain a + # 'continue' statement for the outer loop, but we may need + # to generate cleanup code before taking that path, so we + # intercept it here + orig_continue_label = code.continue_label + code.continue_label = code.new_label('outer_continue') + code.putln("/*else*/ {") self.else_clause.generate_execution_code(code) code.putln("}") - code.put_label(break_label) + + if code.label_used(code.continue_label): + code.put_goto(break_label) + code.put_label(code.continue_label) + self.iterator.generate_disposal_code(code) + code.put_goto(orig_continue_label) + code.set_loop_labels(old_loop_labels) + + if code.label_used(break_label): + code.put_label(break_label) self.iterator.release_counter_temp(code) self.iterator.generate_disposal_code(code) self.iterator.free_temps(code) diff --git a/tests/run/for_in_break_continue_T533.pyx b/tests/run/for_in_break_continue_T533.pyx index 0608258a..23c27246 100644 --- a/tests/run/for_in_break_continue_T533.pyx +++ b/tests/run/for_in_break_continue_T533.pyx @@ -2,6 +2,9 @@ def for_in(): """ >>> for_in() + CONTINUE -1 + CONTINUE 4 + BREAK 6 6 """ i = -1 @@ -10,6 +13,28 @@ def for_in(): if i > 5: break else: + print "CONTINUE", i continue + print "BREAK", i + break + return i + +def for_from(): + """ + >>> for_from() + CONTINUE 0 + CONTINUE 5 + BREAK 6 + 6 + """ + i = -1 + for L in [[], range(5), range(10)]: + for i from 0 <= i < len(L): + if i > 5: + break + else: + print "CONTINUE", i + continue + print "BREAK", i break return i -- 2.26.2