Commit af8646c8 authored by Pablo Galindo's avatar Pablo Galindo Committed by GitHub

bpo-1875: Raise SyntaxError in invalid blocks that will be optimised away (GH-13332)

Move the check for dead conditionals (if 0) to the peephole optimizer
and make sure that the code block is still compiled to report any
existing syntax errors within.
parent a8b46944
......@@ -696,6 +696,20 @@ class SyntaxTestCase(unittest.TestCase):
def test_break_outside_loop(self):
self._check_error("break", "outside loop")
def test_yield_outside_function(self):
self._check_error("if 0: yield", "outside function")
self._check_error("class C:\n if 0: yield", "outside function")
def test_return_outside_function(self):
self._check_error("if 0: return", "outside function")
self._check_error("class C:\n if 0: return", "outside function")
def test_break_outside_loop(self):
self._check_error("if 0: break", "outside loop")
def test_continue_outside_loop(self):
self._check_error("if 0: continue", "not properly in loop")
def test_unexpected_indent(self):
self._check_error("foo()\n bar()\n", "unexpected indent",
subclass=IndentationError)
......
A :exc:`SyntaxError` is now raised if a code blocks that will be optimized
away (e.g. if conditions that are always false) contains syntax errors.
Patch by Pablo Galindo.
......@@ -2546,13 +2546,12 @@ compiler_if(struct compiler *c, stmt_ty s)
return 0;
constant = expr_constant(s->v.If.test);
/* constant = 0: "if 0"
/* constant = 0: "if 0" Leave the optimizations to
* the pephole optimizer to check for syntax errors
* in the block.
* constant = 1: "if 1", "if 2", ...
* constant = -1: rest */
if (constant == 0) {
if (s->v.If.orelse)
VISIT_SEQ(c, stmt, s->v.If.orelse);
} else if (constant == 1) {
if (constant == 1) {
VISIT_SEQ(c, stmt, s->v.If.body);
} else {
if (asdl_seq_LEN(s->v.If.orelse)) {
......
......@@ -302,11 +302,19 @@ PyCode_Optimize(PyObject *code, PyObject* consts, PyObject *names,
case LOAD_CONST:
cumlc = lastlc + 1;
if (nextop != POP_JUMP_IF_FALSE ||
!ISBASICBLOCK(blocks, op_start, i + 1) ||
!PyObject_IsTrue(PyList_GET_ITEM(consts, get_arg(codestr, i))))
!ISBASICBLOCK(blocks, op_start, i + 1)) {
break;
fill_nops(codestr, op_start, nexti + 1);
cumlc = 0;
}
PyObject* cnt = PyList_GET_ITEM(consts, get_arg(codestr, i));
int is_true = PyObject_IsTrue(cnt);
if (is_true == 1) {
fill_nops(codestr, op_start, nexti + 1);
cumlc = 0;
} else if (is_true == 0) {
h = get_arg(codestr, nexti) / sizeof(_Py_CODEUNIT);
tgt = find_op(codestr, codelen, h);
fill_nops(codestr, op_start, tgt);
}
break;
/* Try to fold tuples of constants.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment