Fix for SF bug 1569998: break permitted inside try.
The compiler was checking that there was something on the fblock stack, but not that there was a loop on the stack. Fixed that and added a test for the specific syntax error. Bug fix candidate.
This commit is contained in:
parent
1e3c3b15df
commit
82271f13e7
|
@ -322,6 +322,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
|
||||||
|
|
|
@ -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);
|
||||||
|
@ -2157,7 +2159,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;
|
||||||
|
@ -3147,6 +3149,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.
|
||||||
*/
|
*/
|
||||||
|
|
Loading…
Reference in New Issue