diff --git a/Include/pyerrors.h b/Include/pyerrors.h
index 1eee16d..a6d637c 100644
--- a/Include/pyerrors.h
+++ b/Include/pyerrors.h
@@ -111,6 +111,7 @@ PyAPI_DATA(PyObject *) PyExc_BaseException;
 PyAPI_DATA(PyObject *) PyExc_Exception;
 PyAPI_DATA(PyObject *) PyExc_StopIteration;
 PyAPI_DATA(PyObject *) PyExc_GeneratorExit;
+PyAPI_DATA(PyObject *) PyExc_GeneratorReturn;
 PyAPI_DATA(PyObject *) PyExc_ArithmeticError;
 PyAPI_DATA(PyObject *) PyExc_LookupError;
 
diff --git a/Lib/test/exception_hierarchy.txt b/Lib/test/exception_hierarchy.txt
index 73ccb66..355b44b 100644
--- a/Lib/test/exception_hierarchy.txt
+++ b/Lib/test/exception_hierarchy.txt
@@ -2,6 +2,7 @@ BaseException
  +-- SystemExit
  +-- KeyboardInterrupt
  +-- GeneratorExit
+ +-- GeneratorReturn
  +-- Exception
       +-- StopIteration
       +-- ArithmeticError
diff --git a/Lib/test/test_generators.py b/Lib/test/test_generators.py
index 90af15b..eae1910 100644
--- a/Lib/test/test_generators.py
+++ b/Lib/test/test_generators.py
@@ -723,35 +723,19 @@ Ye olde Fibonacci generator, tee style.
 
 """
 
-# syntax_tests mostly provokes SyntaxErrors.  Also fiddling with #if 0
-# hackery.
-
 syntax_tests = """
 
 >>> def f():
 ...     return 22
 ...     yield 1
-Traceback (most recent call last):
-  ..
-SyntaxError: 'return' with argument inside generator
 
 >>> def f():
 ...     yield 1
 ...     return 22
-Traceback (most recent call last):
-  ..
-SyntaxError: 'return' with argument inside generator
-
-"return None" is not the same as "return" in a generator:
 
 >>> def f():
 ...     yield 1
 ...     return None
-Traceback (most recent call last):
-  ..
-SyntaxError: 'return' with argument inside generator
-
-These are fine:
 
 >>> def f():
 ...     yield 1
@@ -866,20 +850,6 @@ These are fine:
 >>> type(f())
 <class 'generator'>
 
-
->>> def f():
-...     if 0:
-...         lambda x:  x        # shouldn't trigger here
-...         return              # or here
-...         def f(i):
-...             return 2*i      # or here
-...         if 0:
-...             return 3        # but *this* sucks (line 8)
-...     if 0:
-...         yield 2             # because it's a generator (line 10)
-Traceback (most recent call last):
-SyntaxError: 'return' with argument inside generator
-
 This one caused a crash (see SF bug 567538):
 
 >>> def f():
@@ -1566,11 +1536,6 @@ Traceback (most recent call last):
   ...
 SyntaxError: 'yield' outside function
 
->>> def f(): return lambda x=(yield): 1
-Traceback (most recent call last):
-  ...
-SyntaxError: 'return' with argument inside generator
-
 >>> def f(): x = yield = y
 Traceback (most recent call last):
   ...
@@ -1802,6 +1767,60 @@ enclosing function a generator:
 >>> data
 [27, 27]
 
+
+Test GeneratorReturn exception.
+
+General test on correct exception generated by a return statement:
+
+>>> def test():
+...     yield 10
+...     return 11
+...     yield 12
+>>> list(test())
+Traceback (most recent call last):
+  ...
+GeneratorReturn: 11
+
+
+Try..finally block test:
+
+>>> def test():
+...    try:
+...        yield 1/0
+...    except:
+...        pass
+...    finally:
+...        return 42
+>>> list(test())
+Traceback (most recent call last):
+  ...
+GeneratorReturn: 42
+
+
+Complex return/yield test:
+
+>>> def test():
+...    return (yield)
+>>> gen = test()
+>>> next(gen)
+>>> gen.send(42)
+Traceback (most recent call last):
+  ...
+GeneratorReturn: 42
+
+
+Test GeneratorReturn non-catchability in generator that returned value:
+
+>>> def test():
+...    try:
+...        yield
+...        return 100
+...    except GeneratorReturn:
+...        pass
+>>> list(test())
+Traceback (most recent call last):
+  ...
+GeneratorReturn: 100
 """
 
 refleaks_tests = """
diff --git a/Objects/exceptions.c b/Objects/exceptions.c
index b82b6ba..83ea6a4 100644
--- a/Objects/exceptions.c
+++ b/Objects/exceptions.c
@@ -481,6 +481,11 @@ SimpleExtendsException(PyExc_Exception, StopIteration,
 SimpleExtendsException(PyExc_BaseException, GeneratorExit,
                        "Request that a generator exit.");
 
+/*
+ *    GeneratorReturn extends BaseException
+ */
+SimpleExtendsException(PyExc_BaseException, GeneratorReturn,
+                       "A value returned from a generator.");
 
 /*
  *    SystemExit extends BaseException
@@ -1890,6 +1895,7 @@ _PyExc_Init(void)
     PRE_INIT(TypeError)
     PRE_INIT(StopIteration)
     PRE_INIT(GeneratorExit)
+    PRE_INIT(GeneratorReturn)
     PRE_INIT(SystemExit)
     PRE_INIT(KeyboardInterrupt)
     PRE_INIT(ImportError)
@@ -1952,6 +1958,7 @@ _PyExc_Init(void)
     POST_INIT(TypeError)
     POST_INIT(StopIteration)
     POST_INIT(GeneratorExit)
+    POST_INIT(GeneratorReturn)
     POST_INIT(SystemExit)
     POST_INIT(KeyboardInterrupt)
     POST_INIT(ImportError)
diff --git a/Objects/genobject.c b/Objects/genobject.c
index 34ee7dc..c5e8793 100644
--- a/Objects/genobject.c
+++ b/Objects/genobject.c
@@ -92,12 +92,15 @@ gen_send_ex(PyGenObject *gen, PyObject *arg, int exc)
 
     /* If the generator just returned (as opposed to yielding), signal
      * that the generator is exhausted. */
-    if (result == Py_None && f->f_stacktop == NULL) {
+    if (result && f->f_stacktop == NULL) {
+        if (result == Py_None) {
+            PyErr_SetNone(PyExc_StopIteration);
+        } else {
+            PyObject *e = PyObject_CallFunctionObjArgs(PyExc_GeneratorReturn, result, NULL);
+            PyErr_SetObject(PyExc_GeneratorReturn, e);
+        }
         Py_DECREF(result);
         result = NULL;
-        /* Set exception if not called by gen_iternext() */
-        if (arg)
-            PyErr_SetNone(PyExc_StopIteration);
     }
 
     if (!result || f->f_stacktop == NULL) {
diff --git a/Python/symtable.c b/Python/symtable.c
index 55c9f47..5116040 100644
--- a/Python/symtable.c
+++ b/Python/symtable.c
@@ -19,9 +19,6 @@
 
 #define IMPORT_STAR_WARNING "import * only allowed at module level"
 
-#define RETURN_VAL_IN_GENERATOR \
-    "'return' with argument inside generator"
-
 
 static PySTEntryObject *
 ste_new(struct symtable *st, identifier name, _Py_block_ty block,
@@ -1155,13 +1152,6 @@ symtable_visit_stmt(struct symtable *st, stmt_ty s)
         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:
@@ -1364,13 +1354,6 @@ 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);
