mirror of
https://github.com/python/cpython.git
synced 2025-07-27 21:24:32 +00:00
Patch #1346214: correctly optimize away "if 0"-style stmts
(thanks to Neal for review)
This commit is contained in:
parent
9f16760666
commit
ddbaa660d3
5 changed files with 57 additions and 18 deletions
|
@ -2148,7 +2148,7 @@ static int
|
|||
compiler_if(struct compiler *c, stmt_ty s)
|
||||
{
|
||||
basicblock *end, *next;
|
||||
|
||||
int constant;
|
||||
assert(s->kind == If_kind);
|
||||
end = compiler_new_block(c);
|
||||
if (end == NULL)
|
||||
|
@ -2156,15 +2156,27 @@ compiler_if(struct compiler *c, stmt_ty s)
|
|||
next = compiler_new_block(c);
|
||||
if (next == NULL)
|
||||
return 0;
|
||||
VISIT(c, expr, s->v.If.test);
|
||||
ADDOP_JREL(c, JUMP_IF_FALSE, next);
|
||||
ADDOP(c, POP_TOP);
|
||||
VISIT_SEQ(c, stmt, s->v.If.body);
|
||||
ADDOP_JREL(c, JUMP_FORWARD, end);
|
||||
compiler_use_next_block(c, next);
|
||||
ADDOP(c, POP_TOP);
|
||||
if (s->v.If.orelse)
|
||||
VISIT_SEQ(c, stmt, s->v.If.orelse);
|
||||
|
||||
constant = expr_constant(s->v.If.test);
|
||||
/* constant = 0: "if 0"
|
||||
* 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) {
|
||||
VISIT_SEQ(c, stmt, s->v.If.body);
|
||||
} else {
|
||||
VISIT(c, expr, s->v.If.test);
|
||||
ADDOP_JREL(c, JUMP_IF_FALSE, next);
|
||||
ADDOP(c, POP_TOP);
|
||||
VISIT_SEQ(c, stmt, s->v.If.body);
|
||||
ADDOP_JREL(c, JUMP_FORWARD, end);
|
||||
compiler_use_next_block(c, next);
|
||||
ADDOP(c, POP_TOP);
|
||||
if (s->v.If.orelse)
|
||||
VISIT_SEQ(c, stmt, s->v.If.orelse);
|
||||
}
|
||||
compiler_use_next_block(c, end);
|
||||
return 1;
|
||||
}
|
||||
|
@ -2639,10 +2651,6 @@ compiler_visit_stmt(struct compiler *c, stmt_ty s)
|
|||
if (c->u->u_ste->ste_type != FunctionBlock)
|
||||
return compiler_error(c, "'return' outside function");
|
||||
if (s->v.Return.value) {
|
||||
if (c->u->u_ste->ste_generator) {
|
||||
return compiler_error(c,
|
||||
"'return' with argument inside generator");
|
||||
}
|
||||
VISIT(c, expr, s->v.Return.value);
|
||||
}
|
||||
else
|
||||
|
@ -3356,6 +3364,13 @@ expr_constant(expr_ty e)
|
|||
return PyObject_IsTrue(e->v.Num.n);
|
||||
case Str_kind:
|
||||
return PyObject_IsTrue(e->v.Str.s);
|
||||
case Name_kind:
|
||||
/* __debug__ is not assignable, so we can optimize
|
||||
* it away in if and while statements */
|
||||
if (strcmp(PyString_AS_STRING(e->v.Name.id),
|
||||
"__debug__") == 0)
|
||||
return ! Py_OptimizeFlag;
|
||||
/* fall through */
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
|
|
|
@ -13,6 +13,8 @@
|
|||
|
||||
#define IMPORT_STAR_WARNING "import * only allowed at module level"
|
||||
|
||||
#define RETURN_VAL_IN_GENERATOR \
|
||||
"'return' with argument inside generator"
|
||||
|
||||
/* XXX(nnorwitz): change name since static? */
|
||||
static PySTEntryObject *
|
||||
|
@ -66,6 +68,7 @@ PySTEntry_New(struct symtable *st, identifier name, _Py_block_ty block,
|
|||
ste->ste_nested = 1;
|
||||
ste->ste_child_free = 0;
|
||||
ste->ste_generator = 0;
|
||||
ste->ste_returns_value = 0;
|
||||
|
||||
if (PyDict_SetItem(st->st_symbols, ste->ste_id, (PyObject *)ste) < 0)
|
||||
goto fail;
|
||||
|
@ -944,8 +947,17 @@ symtable_visit_stmt(struct symtable *st, stmt_ty s)
|
|||
break;
|
||||
}
|
||||
case Return_kind:
|
||||
if (s->v.Return.value)
|
||||
if (s->v.Return.value) {
|
||||
VISIT(st, expr, s->v.Return.value);
|
||||
st->st_cur->ste_returns_value = 1;
|
||||
if (st->st_cur->ste_generator) {
|
||||
PyErr_SetString(PyExc_SyntaxError,
|
||||
RETURN_VAL_IN_GENERATOR);
|
||||
PyErr_SyntaxLocation(st->st_filename,
|
||||
s->lineno);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case Delete_kind:
|
||||
VISIT_SEQ(st, expr, s->v.Delete.targets);
|
||||
|
@ -1136,6 +1148,13 @@ symtable_visit_expr(struct symtable *st, expr_ty e)
|
|||
if (e->v.Yield.value)
|
||||
VISIT(st, expr, e->v.Yield.value);
|
||||
st->st_cur->ste_generator = 1;
|
||||
if (st->st_cur->ste_returns_value) {
|
||||
PyErr_SetString(PyExc_SyntaxError,
|
||||
RETURN_VAL_IN_GENERATOR);
|
||||
PyErr_SyntaxLocation(st->st_filename,
|
||||
e->lineno);
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
case Compare_kind:
|
||||
VISIT(st, expr, e->v.Compare.left);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue