Index: Python/symtable.c
===================================================================
--- Python/symtable.c (revision 68142)
+++ Python/symtable.c (working copy)
@@ -22,7 +22,12 @@
#define RETURN_VAL_IN_GENERATOR \
"'return' with argument inside generator"
+#define RETURN_OUTSIDE_FUNCTION \
+ "'return' outside function"
+#define YIELD_OUTSIDE_FUNCTION \
+ "'yield' outside function"
+
static PySTEntryObject *
ste_new(struct symtable *st, identifier name, _Py_block_ty block,
void *key, int lineno)
@@ -1063,6 +1068,12 @@
break;
}
case Return_kind:
+ if (st->st_cur->ste_type != FunctionBlock) {
+ PyErr_SetString(PyExc_SyntaxError,
+ RETURN_OUTSIDE_FUNCTION);
+ PyErr_SyntaxLocation(st->st_filename,
+ s->lineno);
+ }
if (s->v.Return.value) {
VISIT(st, expr, s->v.Return.value);
st->st_cur->ste_returns_value = 1;
@@ -1278,6 +1289,12 @@
return 0;
break;
case Yield_kind:
+ if (st->st_cur->ste_type != FunctionBlock) {
+ PyErr_SetString(PyExc_SyntaxError,
+ YIELD_OUTSIDE_FUNCTION);
+ PyErr_SyntaxLocation(st->st_filename,
+ e->lineno);
+ }
if (e->v.Yield.value)
VISIT(st, expr, e->v.Yield.value);
st->st_cur->ste_generator = 1;
Index: Lib/test/test_syntax.py
===================================================================
--- Lib/test/test_syntax.py (revision 68142)
+++ Lib/test/test_syntax.py (working copy)
@@ -528,6 +528,16 @@
def test_break_outside_loop(self):
self._check_error("break", "outside loop")
+ def test_yield_outside_function(self):
+ # Issue XXXX: raise a SyntaxError even if the compiler
+ # trims the code because of a "if 0"
+ 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_delete_deref(self):
source = re.sub('(?m)^ *:', '', """\
:def foo(x):