Fix #1569998: no break inside try statement (outside loop) allowed.

(backport from rev. 52129)
This commit is contained in:
Georg Brandl 2006-10-08 07:12:23 +00:00
parent 74284b9606
commit a5fe3ef8d8
3 changed files with 30 additions and 1 deletions

View 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) 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 import re

View file

@ -12,6 +12,9 @@ What's New in Python 2.5.1c1?
Core and builtins 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. - Patch #1542451: disallow continue anywhere under a finally.
- list.pop(x) accepts any object x following the __index__ protocol. - list.pop(x) accepts any object x following the __index__ protocol.

View file

@ -187,6 +187,8 @@ static int compiler_push_fblock(struct compiler *, enum fblocktype,
basicblock *); basicblock *);
static void compiler_pop_fblock(struct compiler *, enum fblocktype, static void compiler_pop_fblock(struct compiler *, enum fblocktype,
basicblock *); 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 inplace_binop(struct compiler *, operator_ty);
static int expr_constant(expr_ty e); static int expr_constant(expr_ty e);
@ -2764,7 +2766,7 @@ compiler_visit_stmt(struct compiler *c, stmt_ty s)
case Pass_kind: case Pass_kind:
break; break;
case Break_kind: case Break_kind:
if (!c->u->u_nfblocks) if (!compiler_in_loop(c))
return compiler_error(c, "'break' outside loop"); return compiler_error(c, "'break' outside loop");
ADDOP(c, BREAK_LOOP); ADDOP(c, BREAK_LOOP);
break; 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); 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. /* Raises a SyntaxError and returns 0.
If something goes wrong, a different exception may be raised. If something goes wrong, a different exception may be raised.
*/ */