cython-devel
changeset 3338:879bb33c11c9
fix ticket #533: 'continue' in the 'else' block of a for-in-loop leaks a reference
| author | Stefan Behnel <scoder@users.berlios.de> |
|---|---|
| date | Sun May 09 13:14:09 2010 +0200 (3 years ago) |
| parents | e14fe9894ca9 |
| children | 57f8fb925531 |
| files | Cython/Compiler/Nodes.py tests/run/for_in_break_continue_T533.pyx |
line diff
1.1 --- a/Cython/Compiler/Nodes.py Sat May 08 19:24:53 2010 -0300
1.2 +++ b/Cython/Compiler/Nodes.py Sun May 09 13:14:09 2010 +0200
1.3 @@ -4095,11 +4095,28 @@
1.4 "}")
1.5 break_label = code.break_label
1.6 code.set_loop_labels(old_loop_labels)
1.7 - if self.else_clause:
1.8 +
1.9 + if self.else_clause:
1.10 + # in nested loops, the 'else' block can contain a
1.11 + # 'continue' statement for the outer loop, but we may need
1.12 + # to generate cleanup code before taking that path, so we
1.13 + # intercept it here
1.14 + orig_continue_label = code.continue_label
1.15 + code.continue_label = code.new_label('outer_continue')
1.16 +
1.17 code.putln("/*else*/ {")
1.18 self.else_clause.generate_execution_code(code)
1.19 code.putln("}")
1.20 - code.put_label(break_label)
1.21 +
1.22 + if code.label_used(code.continue_label):
1.23 + code.put_goto(break_label)
1.24 + code.put_label(code.continue_label)
1.25 + self.iterator.generate_disposal_code(code)
1.26 + code.put_goto(orig_continue_label)
1.27 + code.set_loop_labels(old_loop_labels)
1.28 +
1.29 + if code.label_used(break_label):
1.30 + code.put_label(break_label)
1.31 self.iterator.release_counter_temp(code)
1.32 self.iterator.generate_disposal_code(code)
1.33 self.iterator.free_temps(code)
2.1 --- a/tests/run/for_in_break_continue_T533.pyx Sat May 08 19:24:53 2010 -0300
2.2 +++ b/tests/run/for_in_break_continue_T533.pyx Sun May 09 13:14:09 2010 +0200
2.3 @@ -2,6 +2,9 @@
2.4 def for_in():
2.5 """
2.6 >>> for_in()
2.7 + CONTINUE -1
2.8 + CONTINUE 4
2.9 + BREAK 6
2.10 6
2.11 """
2.12 i = -1
2.13 @@ -10,6 +13,28 @@
2.14 if i > 5:
2.15 break
2.16 else:
2.17 + print "CONTINUE", i
2.18 continue
2.19 + print "BREAK", i
2.20 break
2.21 return i
2.22 +
2.23 +def for_from():
2.24 + """
2.25 + >>> for_from()
2.26 + CONTINUE 0
2.27 + CONTINUE 5
2.28 + BREAK 6
2.29 + 6
2.30 + """
2.31 + i = -1
2.32 + for L in [[], range(5), range(10)]:
2.33 + for i from 0 <= i < len(L):
2.34 + if i > 5:
2.35 + break
2.36 + else:
2.37 + print "CONTINUE", i
2.38 + continue
2.39 + print "BREAK", i
2.40 + break
2.41 + return i
