Index: Python/symtable.c =================================================================== --- Python/symtable.c (Revision 46273) +++ Python/symtable.c (Arbeitskopie) @@ -66,6 +66,7 @@ ste->ste_nested = 1; ste->ste_child_free = 0; ste->ste_generator = 0; + ste->ste_returnsval = 0; if (PyDict_SetItem(st->st_symbols, ste->ste_id, (PyObject *)ste) < 0) goto fail; @@ -944,8 +945,17 @@ 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_returnsval = 1; + if (st->st_cur->ste_generator) { + PyErr_SetString(PyExc_SyntaxError, + "'return' with argument inside generator"); + PyErr_SyntaxLocation(st->st_filename, + s->lineno); + return 0; + } + } break; case Delete_kind: VISIT_SEQ(st, expr, s->v.Delete.targets); @@ -1136,6 +1146,13 @@ if (e->v.Yield.value) VISIT(st, expr, e->v.Yield.value); st->st_cur->ste_generator = 1; + if (st->st_cur->ste_returnsval) { + PyErr_SetString(PyExc_SyntaxError, + "'return' with argument inside generator"); + PyErr_SyntaxLocation(st->st_filename, + e->lineno); + return 0; + } break; case Compare_kind: VISIT(st, expr, e->v.Compare.left); Index: Python/compile.c =================================================================== --- Python/compile.c (Revision 46273) +++ Python/compile.c (Arbeitskopie) @@ -2148,7 +2148,7 @@ 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 @@ 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 @@ 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 @@ 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; } Index: Include/symtable.h =================================================================== --- Include/symtable.h (Revision 46273) +++ Include/symtable.h (Arbeitskopie) @@ -39,6 +39,8 @@ unsigned ste_generator : 1; /* true if namespace is a generator */ unsigned ste_varargs : 1; /* true if block has varargs */ unsigned ste_varkeywords : 1; /* true if block has varkeywords */ + unsigned ste_returnsval : 1; /* true if namespace uses return with + an argument */ int ste_lineno; /* first line of block */ int ste_opt_lineno; /* lineno of last exec or import * */ int ste_tmpname; /* counter for listcomp temp vars */ Index: Lib/test/test_generators.py =================================================================== --- Lib/test/test_generators.py (Revision 46273) +++ Lib/test/test_generators.py (Arbeitskopie) @@ -733,7 +733,7 @@ ... yield 1 Traceback (most recent call last): .. -SyntaxError: 'return' with argument inside generator (, line 2) +SyntaxError: 'return' with argument inside generator (, line 3) >>> def f(): ... yield 1 @@ -876,9 +876,9 @@ ... if 0: ... return 3 # but *this* sucks (line 8) ... if 0: -... yield 2 # because it's a generator +... yield 2 # because it's a generator (line 10) Traceback (most recent call last): -SyntaxError: 'return' with argument inside generator (, line 8) +SyntaxError: 'return' with argument inside generator (, line 10) This one caused a crash (see SF bug 567538):