]> granicus.if.org Git - python/commitdiff
Fix #1569998: no break inside try statement (outside loop) allowed.
authorGeorg Brandl <georg@python.org>
Sun, 8 Oct 2006 07:12:23 +0000 (07:12 +0000)
committerGeorg Brandl <georg@python.org>
Sun, 8 Oct 2006 07:12:23 +0000 (07:12 +0000)
  (backport from rev. 52129)

Lib/test/test_syntax.py
Misc/NEWS
Python/compile.c

index bc9cb127ea7a53a9cb68dcda1a238c7c0ced5be7..521789f34641b045ad22f642f9d4152d5ac7b591 100644 (file)
@@ -319,6 +319,20 @@ This is essentially a continue in a finally which should not be allowed.
       ...
     SyntaxError: 'continue' not supported inside 'finally' clause (<doctest test.test_syntax[41]>, line 8)
 
+There is one test for a break that is not in a loop.  The compiler
+uses a single data structure to keep track of try-finally and loops,
+so we need to be sure that a break is actually inside a loop.  If it
+isn't, there should be a syntax error.
+
+   >>> try:
+   ...     print 1
+   ...     break
+   ...     print 2
+   ... finally:
+   ...     print 3
+   Traceback (most recent call last):
+     ...
+   SyntaxError: 'break' outside loop (<doctest test.test_syntax[42]>, line 3)
 """
 
 import re
index 9bccc28b69548dd3b012972e2c9c6ea39f73c19d..a390730c1a719f56ceafc5afe50a21b0e6500999 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -12,6 +12,9 @@ What's New in Python 2.5.1c1?
 Core and builtins
 -----------------
 
+- Bug #1569998: break inside a try statement (outside a loop) is now
+  recognized and rejected.
+
 - Patch #1542451: disallow continue anywhere under a finally.
 
 - list.pop(x) accepts any object x following the __index__ protocol.
index 76c462829dc21458668b01adf6e336bcce15cf3f..038bc2f4fede9dc79c6c9395f77a42bc09ea2161 100644 (file)
@@ -187,6 +187,8 @@ static int compiler_push_fblock(struct compiler *, enum fblocktype,
                                basicblock *);
 static void compiler_pop_fblock(struct compiler *, enum fblocktype,
                                basicblock *);
+/* Returns true if there is a loop on the fblock stack. */
+static int compiler_in_loop(struct compiler *);
 
 static int inplace_binop(struct compiler *, operator_ty);
 static int expr_constant(expr_ty e);
@@ -2764,7 +2766,7 @@ compiler_visit_stmt(struct compiler *c, stmt_ty s)
        case Pass_kind:
                break;
        case Break_kind:
-               if (!c->u->u_nfblocks)
+                if (!compiler_in_loop(c))
                        return compiler_error(c, "'break' outside loop");
                ADDOP(c, BREAK_LOOP);
                break;
@@ -3754,6 +3756,16 @@ compiler_pop_fblock(struct compiler *c, enum fblocktype t, basicblock *b)
        assert(u->u_fblock[u->u_nfblocks].fb_block == b);
 }
 
+static int
+compiler_in_loop(struct compiler *c) {
+        int i;
+        struct compiler_unit *u = c->u;
+        for (i = 0; i < u->u_nfblocks; ++i) {
+                if (u->u_fblock[i].fb_type == LOOP)
+                        return 1;
+        }
+        return 0;
+}
 /* Raises a SyntaxError and returns 0.
    If something goes wrong, a different exception may be raised.
 */