diff options
author | Pablo Galindo <Pablogsal@gmail.com> | 2019-05-17 10:37:08 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-05-17 10:37:08 (GMT) |
commit | af8646c8054d0f4180a2013383039b6a472f9698 (patch) | |
tree | ceafae5989deb1ab62b8237593bd8752ab600e39 | |
parent | a8b46944d72bba6dc76260ed61da5c78d3f9d9c0 (diff) | |
download | cpython-af8646c8054d0f4180a2013383039b6a472f9698.zip cpython-af8646c8054d0f4180a2013383039b6a472f9698.tar.gz cpython-af8646c8054d0f4180a2013383039b6a472f9698.tar.bz2 |
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.
-rw-r--r-- | Lib/test/test_syntax.py | 14 | ||||
-rw-r--r-- | Misc/NEWS.d/next/Core and Builtins/2019-05-15-01-29-29.bpo-1875.9oxXFX.rst | 3 | ||||
-rw-r--r-- | Python/compile.c | 9 | ||||
-rw-r--r-- | Python/peephole.c | 16 |
4 files changed, 33 insertions, 9 deletions
diff --git a/Lib/test/test_syntax.py b/Lib/test/test_syntax.py index 4a2899e..8451c07 100644 --- a/Lib/test/test_syntax.py +++ b/Lib/test/test_syntax.py @@ -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) diff --git a/Misc/NEWS.d/next/Core and Builtins/2019-05-15-01-29-29.bpo-1875.9oxXFX.rst b/Misc/NEWS.d/next/Core and Builtins/2019-05-15-01-29-29.bpo-1875.9oxXFX.rst new file mode 100644 index 0000000..8f095ed --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2019-05-15-01-29-29.bpo-1875.9oxXFX.rst @@ -0,0 +1,3 @@ +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. diff --git a/Python/compile.c b/Python/compile.c index 91ce04b..2a086a5 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -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)) { diff --git a/Python/peephole.c b/Python/peephole.c index cc244aa..1ce3535 100644 --- a/Python/peephole.c +++ b/Python/peephole.c @@ -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. |