summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Cython/Compiler/Nodes.py23
-rw-r--r--tests/run/for_in_break_continue_T533.pyx29
2 files changed, 42 insertions, 10 deletions
diff --git a/Cython/Compiler/Nodes.py b/Cython/Compiler/Nodes.py
index c5ddad0a6..457ae94ad 100644
--- a/Cython/Compiler/Nodes.py
+++ b/Cython/Compiler/Nodes.py
@@ -6723,23 +6723,28 @@ class _ForInStatNode(LoopNode, StatNode):
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
+ # In nested loops, the 'else' block can contain 'continue' or 'break'
+ # statements for the outer loop, but we may need to generate cleanup code
+ # before taking those paths, so we intercept them here.
+ orig_exit_labels = (code.continue_label, code.break_label)
code.continue_label = code.new_label('outer_continue')
+ code.break_label = code.new_label('outer_break')
code.putln("/*else*/ {")
self.else_clause.generate_execution_code(code)
code.putln("}")
- if code.label_used(code.continue_label):
- code.put_goto(break_label)
+ needs_goto_end = not self.else_clause.is_terminator
+ for exit_label, orig_exit_label in zip([code.continue_label, code.break_label], orig_exit_labels):
+ if not code.label_used(exit_label):
+ continue
+ if needs_goto_end:
+ code.put_goto(break_label)
+ needs_goto_end = False
code.mark_pos(self.pos)
- code.put_label(code.continue_label)
+ code.put_label(exit_label)
self.iterator.generate_disposal_code(code)
- code.put_goto(orig_continue_label)
+ code.put_goto(orig_exit_label)
code.set_loop_labels(old_loop_labels)
code.mark_pos(self.pos)
diff --git a/tests/run/for_in_break_continue_T533.pyx b/tests/run/for_in_break_continue_T533.pyx
index 0baa9fa49..20dfa4caa 100644
--- a/tests/run/for_in_break_continue_T533.pyx
+++ b/tests/run/for_in_break_continue_T533.pyx
@@ -1,4 +1,6 @@
-# ticket: 533
+# mode: run
+# ticket: t533
+# ticket: gh1093
def for_in():
"""
@@ -20,6 +22,7 @@ def for_in():
break
return i
+
def for_from():
"""
>>> for_from()
@@ -39,3 +42,27 @@ def for_from():
print "BREAK", i
break
return i
+
+
+def for_in_break2(data, avoid):
+ """
+ >>> for_in_break2([1,2,3,None], avoid=[1,2,3])
+ 3
+ >>> for_in_break2([1,2,3,None], avoid=[1])
+ 1
+ >>> for_in_break2([1,2,3,None], avoid=[1])
+ 1
+ """
+ data_iter = iter(data)
+ value = None
+ while 1:
+ match = next(data_iter)
+ if match is None:
+ break
+ for value in avoid:
+ if match == value:
+ break
+ else:
+ break
+
+ return value