summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPablo Galindo <Pablogsal@gmail.com>2019-05-17 10:37:08 (GMT)
committerGitHub <noreply@github.com>2019-05-17 10:37:08 (GMT)
commitaf8646c8054d0f4180a2013383039b6a472f9698 (patch)
treeceafae5989deb1ab62b8237593bd8752ab600e39
parenta8b46944d72bba6dc76260ed61da5c78d3f9d9c0 (diff)
downloadcpython-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.py14
-rw-r--r--Misc/NEWS.d/next/Core and Builtins/2019-05-15-01-29-29.bpo-1875.9oxXFX.rst3
-rw-r--r--Python/compile.c9
-rw-r--r--Python/peephole.c16
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.