diff --git a/CHANGES.rst b/CHANGES.rst
index f61d9cbe6198af192ae07de06f65350cb8524916..6615c43026145ffd70ce870310855f285afa3e9e 100644
--- a/CHANGES.rst
+++ b/CHANGES.rst
@@ -15,27 +15,105 @@ Features added
 
 * Tracing is supported in ``nogil`` functions/sections and module init code.
 
-* Adding/subtracting constant Python floats and small integers is faster.
+* PEP 448 (Additional Unpacking Generalizations) was implemented.
+
+* When generators are used in a Cython module and the module imports the
+  modules "inspect" and/or "asyncio", Cython enables interoperability by
+  patching these modules to recognise Cython's internal generator type.
+  This can be disabled by C compiling the module with
+  "-D CYTHON_PATCH_ASYNCIO=0" or "-D CYTHON_PATCH_INSPECT=0"
+
+* When generators are used in a Cython module, the new ``Generator`` ABC
+  will be patched into the ``collections`` or ``collections.abc``
+  stdlib module if it is not there yet.  It allows type checks for
+  ``isinstance(obj, Generator)`` which includes both Python generators
+  and Cython generators.  This can be disabled by C compiling the module
+  with "-D CYTHON_PATCH_ABC=0".  See https://bugs.python.org/issue24018
+
+* Adding/subtracting/dividing/modulus and equality comparisons with
+  constant Python floats and small integers are faster.
+
+* Binary and/or/xor/rshift operations with small constant Python integers
+  are faster.
+
+* Keyword argument dicts are no longer copied on function entry when they
+  are not being used or only passed through to other function calls (e.g.
+  in wrapper functions).
+
+* The ``PyTypeObject`` declaration in ``cpython.object`` was extended.
+
+* ``wraparound()`` and ``boundscheck()`` are available as no-ops in pure
+  Python mode.
+
+* Const iterators were added to the provided C++ STL declarations.
+
+* ``NULL`` is allowed as default argument when embedding signatures.
+  This fixes ticket 843.
+
+* When compiling with ``--embed``, the internal module name is changed to
+  ``__main__`` to allow arbitrary program names, including those that would
+  be invalid for modules.  Note that this prevents reuse of the generated
+  C code as an importable module.
 
 Bugs fixed
 ----------
 
+* Calling "yield from" from Python on a Cython generator that returned a value
+  triggered a crash in CPython.  This is now being worked around.
+  See https://bugs.python.org/issue23996
+
 * Language level 3 did not enable true division (a.k.a. float division) for
   integer operands.
 
+* Relative cimports could accidentally fall back to trying an absolute cimport
+  on failure.
+
+* The result of calling a C struct constructor no longer requires an intermediate
+  assignment when coercing to a Python dict.
+
+* C++ exception declarations with mapping functions could fail to compile when
+  pre-declared in .pxd files.
+
+
+0.22.1 (2015-05-??)
+===================
+
+Bugs fixed
+----------
+
+* Crash when returning values on generator termination.
+
+* In some cases, exceptions raised during internal isinstance() checks were
+  not propagated.
+
 * Runtime reported file paths of source files (e.g for profiling and tracing)
   are now relative to the build root directory instead of the main source file.
 
 * Tracing exception handling code could enter the trace function with an active
   exception set.
 
+* The internal generator function type was not shared across modules.
+
 * Comparisons of (inferred) ctuples failed to compile.
 
+* Closures inside of cdef functions returning ``void`` failed to compile.
+
+* Using ``const`` C++ references in intermediate parts of longer expressions
+  could fail to compile.
+
 * C++ exception declarations with mapping functions could fail to compile when
   pre-declared in .pxd files.
 
+* C++ compilation could fail with an ambiguity error in recent MacOS-X Xcode
+  versions.
+
 * C compilation could fail in pypy3.
 
+* Fixed a memory leak in the compiler when compiling multiple modules.
+
+* When compiling multiple modules, external library dependencies could leak
+  into later compiler runs.  Fix by Jeroen Demeyer.  This fixes ticket 845.
+
 
 0.22 (2015-02-11)
 =================
diff --git a/Cython/Build/Dependencies.py b/Cython/Build/Dependencies.py
index baf009ff481e973bd96110ccc5342cacfb84f6fa..70004d2dd41923af2a4ba114afd1da432bc921dd 100644
--- a/Cython/Build/Dependencies.py
+++ b/Cython/Build/Dependencies.py
@@ -45,7 +45,7 @@ except ImportError:
 from distutils.extension import Extension
 
 from .. import Utils
-from ..Utils import cached_function, cached_method, path_exists, find_root_package_dir
+from ..Utils import cached_function, cached_method, path_exists, find_root_package_dir, is_package_dir
 from ..Compiler.Main import Context, CompilationOptions, default_options
 
 join_path = cached_function(os.path.join)
@@ -216,12 +216,13 @@ class DistutilsInfo(object):
                 self.values[key] = value
             elif type is transitive_list:
                 if key in self.values:
-                    all = self.values[key]
+                    # Change a *copy* of the list (Trac #845)
+                    all = self.values[key][:]
                     for v in value:
                         if v not in all:
                             all.append(v)
-                else:
-                    self.values[key] = value
+                    value = all
+                self.values[key] = value
         return self
 
     def subs(self, aliases):
@@ -250,9 +251,8 @@ class DistutilsInfo(object):
         for key, value in self.values.items():
             type = distutils_settings[key]
             if type in [list, transitive_list]:
-                getattr(extension, key).extend(value)
-            else:
-                setattr(extension, key, value)
+                value = getattr(extension, key) + list(value)
+            setattr(extension, key, value)
 
 @cython.locals(start=long, q=long, single_q=long, double_q=long, hash_mark=long,
                end=long, k=long, counter=long, quote_len=long)
@@ -383,7 +383,7 @@ def resolve_depend(depend, include_dirs):
 @cached_function
 def package(filename):
     dir = os.path.dirname(os.path.abspath(str(filename)))
-    if dir != filename and path_exists(join_path(dir, '__init__.py')):
+    if dir != filename and is_package_dir(dir):
         return package(dir) + (os.path.basename(dir),)
     else:
         return ()
@@ -832,7 +832,15 @@ def cythonize(module_list, exclude=[], nthreads=0, aliases=None, quiet=False, fo
         if not os.path.exists(options.cache):
             os.makedirs(options.cache)
     to_compile.sort()
-    if len(to_compile) <= 1:
+    # Drop "priority" component of "to_compile" entries and add a
+    # simple progress indicator.
+    N = len(to_compile)
+    progress_fmt = "[{0:%d}/{1}] " % len(str(N))
+    for i in range(N):
+        progress = progress_fmt.format(i+1, N)
+        to_compile[i] = to_compile[i][1:] + (progress,)
+
+    if N <= 1:
         nthreads = 0
     if nthreads:
         # Requires multiprocessing (or Python >= 2.6)
@@ -862,7 +870,7 @@ def cythonize(module_list, exclude=[], nthreads=0, aliases=None, quiet=False, fo
             pool.join()
     if not nthreads:
         for args in to_compile:
-            cythonize_one(*args[1:])
+            cythonize_one(*args)
 
     if exclude_failures:
         failed_modules = set()
@@ -927,7 +935,7 @@ else:
 
 # TODO: Share context? Issue: pyx processing leaks into pxd module
 @record_results
-def cythonize_one(pyx_file, c_file, fingerprint, quiet, options=None, raise_on_failure=True, embedded_metadata=None):
+def cythonize_one(pyx_file, c_file, fingerprint, quiet, options=None, raise_on_failure=True, embedded_metadata=None, progress=""):
     from ..Compiler.Main import compile, default_options
     from ..Compiler.Errors import CompileError, PyrexError
 
@@ -944,7 +952,7 @@ def cythonize_one(pyx_file, c_file, fingerprint, quiet, options=None, raise_on_f
             options.cache, "%s-%s%s" % (os.path.basename(c_file), fingerprint, gzip_ext))
         if os.path.exists(fingerprint_file):
             if not quiet:
-                print("Found compiled %s in cache" % pyx_file)
+                print("%sFound compiled %s in cache" % (progress, pyx_file))
             os.utime(fingerprint_file, None)
             g = gzip_open(fingerprint_file, 'rb')
             try:
@@ -957,7 +965,7 @@ def cythonize_one(pyx_file, c_file, fingerprint, quiet, options=None, raise_on_f
                 g.close()
             return
     if not quiet:
-        print("Cythonizing %s" % pyx_file)
+        print("%sCythonizing %s" % (progress, pyx_file))
     if options is None:
         options = CompilationOptions(default_options)
     options.output_file = c_file
@@ -1000,7 +1008,7 @@ def cythonize_one(pyx_file, c_file, fingerprint, quiet, options=None, raise_on_f
 def cythonize_one_helper(m):
     import traceback
     try:
-        return cythonize_one(*m[1:])
+        return cythonize_one(*m)
     except Exception:
         traceback.print_exc()
         raise
diff --git a/Cython/Compiler/Annotate.py b/Cython/Compiler/Annotate.py
index 28a0d4cc4fc53c53fc8fc7930460c3c1d1fdcd55..de5dc6e19ed7163fa6b07dec6eef3d486c42bf3d 100644
--- a/Cython/Compiler/Annotate.py
+++ b/Cython/Compiler/Annotate.py
@@ -277,9 +277,9 @@ _parse_code = re.compile(
     ur'(?P<trace>__Pyx_Trace[A-Za-z]+)|'
     ur'(?:'
     ur'(?P<pyx_macro_api>__Pyx_[A-Z][A-Z_]+)|'
-    ur'(?P<pyx_c_api>__Pyx_[A-Z][a-z_][A-Za-z_]+)|'
+    ur'(?P<pyx_c_api>__Pyx_[A-Z][a-z_][A-Za-z_]*)|'
     ur'(?P<py_macro_api>Py[A-Z][a-z]+_[A-Z][A-Z_]+)|'
-    ur'(?P<py_c_api>Py[A-Z][a-z]+_[A-Z][a-z][A-Za-z_]+)'
+    ur'(?P<py_c_api>Py[A-Z][a-z]+_[A-Z][a-z][A-Za-z_]*)'
     ur')(?=\()|'       # look-ahead to exclude subsequent '(' from replacement
     ur'(?P<error_goto>(?:(?<=;) *if .* +)?\{__pyx_filename = .*goto __pyx_L\w+;\})'
 ).sub
diff --git a/Cython/Compiler/AutoDocTransforms.py b/Cython/Compiler/AutoDocTransforms.py
index 775f6358f964ac22e764c25057eba883348338b0..88b0cd88a821de2c350cbeee886aaa18780615cf 100644
--- a/Cython/Compiler/AutoDocTransforms.py
+++ b/Cython/Compiler/AutoDocTransforms.py
@@ -51,6 +51,8 @@ class EmbedSignature(CythonTransform):
         default_val = arg.default
         if not default_val:
             return None
+        if isinstance(default_val, ExprNodes.NullNode):
+            return 'NULL'
         try:
             denv = self.denv  # XXX
             ctval = default_val.compile_time_value(self.denv)
diff --git a/Cython/Compiler/Builtin.py b/Cython/Compiler/Builtin.py
index 18de98fea8be79833d751ecc5350eafd1a037bbd..b518abbd7db4fd8537f3e0115702a4cdde9bf363 100644
--- a/Cython/Compiler/Builtin.py
+++ b/Cython/Compiler/Builtin.py
@@ -165,7 +165,26 @@ builtin_function_table = [
                     utility_code = iter_next_utility_code),  # not available in Py2 => implemented here
     #('oct',       "",     "",      ""),
     #('open',       "ss",   "O",     "PyFile_FromString"),   # not in Py3
-    #('ord',       "",     "",      ""),
+] + [
+    BuiltinFunction('ord',        None,    None,   "__Pyx_long_cast",
+                    func_type=PyrexTypes.CFuncType(
+                        PyrexTypes.c_long_type, [PyrexTypes.CFuncTypeArg("c", c_type, None)],
+                        is_strict_signature=True))
+    for c_type in [PyrexTypes.c_py_ucs4_type, PyrexTypes.c_py_unicode_type]
+] + [
+    BuiltinFunction('ord',        None,    None,   "__Pyx_uchar_cast",
+                    func_type=PyrexTypes.CFuncType(
+                        PyrexTypes.c_uchar_type, [PyrexTypes.CFuncTypeArg("c", c_type, None)],
+                        is_strict_signature=True))
+    for c_type in [PyrexTypes.c_char_type, PyrexTypes.c_schar_type, PyrexTypes.c_uchar_type]
+] + [
+    BuiltinFunction('ord',        None,    None,   "__Pyx_PyObject_Ord",
+                    utility_code=UtilityCode.load_cached("object_ord", "Builtins.c"),
+                    func_type=PyrexTypes.CFuncType(
+                        PyrexTypes.c_long_type, [
+                            PyrexTypes.CFuncTypeArg("c", PyrexTypes.py_object_type, None)
+                        ],
+                        exception_value="(long)(Py_UCS4)-1")),
     BuiltinFunction('pow',        "OOO",  "O",     "PyNumber_Power"),
     BuiltinFunction('pow',        "OO",   "O",     "__Pyx_PyNumber_Power2",
                     utility_code = UtilityCode.load("pow2", "Builtins.c")),
@@ -300,6 +319,8 @@ builtin_types_table = [
                                     BuiltinMethod("clear",   "T",  "r", "PySet_Clear"),
                                     # discard() and remove() have a special treatment for unhashable values
 #                                    BuiltinMethod("discard", "TO", "r", "PySet_Discard"),
+                                    BuiltinMethod("update",     "TO", "r", "__Pyx_PySet_Update",
+                                                  utility_code=UtilityCode.load_cached("PySet_Update", "Builtins.c")),
                                     BuiltinMethod("add",     "TO", "r", "PySet_Add"),
                                     BuiltinMethod("pop",     "T",  "O", "PySet_Pop")]),
     ("frozenset", "PyFrozenSet_Type", []),
diff --git a/Cython/Compiler/Code.py b/Cython/Compiler/Code.py
index f497bc56dc5d6f95e33dec43f7f0fcf3f6874ed3..0f4fd0ecaffed23aa4a6a56a9e2d94776272092d 100644
--- a/Cython/Compiler/Code.py
+++ b/Cython/Compiler/Code.py
@@ -231,12 +231,11 @@ class UtilityCodeBase(object):
                 loader = __loader__
                 archive = loader.archive
                 with closing(zipfile.ZipFile(archive)) as fileobj:
-                    listing = [ os.path.basename(name)
-                                for name in fileobj.namelist()
-                                if os.path.join(archive, name).startswith(utility_dir)]
-            files = [ os.path.join(utility_dir, filename)
-                      for filename in listing
-                      if filename.startswith(prefix) ]
+                    listing = [os.path.basename(name)
+                               for name in fileobj.namelist()
+                               if os.path.join(archive, name).startswith(utility_dir)]
+            files = [filename for filename in listing
+                     if filename.startswith(prefix)]
             if not files:
                 raise ValueError("No match found for utility code " + util_code_name)
             if len(files) > 1:
@@ -397,6 +396,9 @@ class UtilityCode(UtilityCodeBase):
     def inject_string_constants(self, impl, output):
         """Replace 'PYIDENT("xyz")' by a constant Python identifier cname.
         """
+        if 'PYIDENT(' not in impl:
+            return False, impl
+
         replacements = {}
         def externalise(matchobj):
             name = matchobj.group(1)
@@ -407,9 +409,55 @@ class UtilityCode(UtilityCodeBase):
                     StringEncoding.EncodedString(name)).cname
             return cname
 
-        impl = re.sub('PYIDENT\("([^"]+)"\)', externalise, impl)
+        impl = re.sub(r'PYIDENT\("([^"]+)"\)', externalise, impl)
+        assert 'PYIDENT(' not in impl
         return bool(replacements), impl
 
+    def inject_unbound_methods(self, impl, output):
+        """Replace 'UNBOUND_METHOD(type, "name")' by a constant Python identifier cname.
+        """
+        if 'CALL_UNBOUND_METHOD(' not in impl:
+            return False, impl
+
+        utility_code = set()
+        def externalise(matchobj):
+            type_cname, method_name, args = matchobj.groups()
+            args = [arg.strip() for arg in args[1:].split(',')]
+            if len(args) == 1:
+                call = '__Pyx_CallUnboundCMethod0'
+                utility_code.add("CallUnboundCMethod0")
+            elif len(args) == 2:
+                call = '__Pyx_CallUnboundCMethod1'
+                utility_code.add("CallUnboundCMethod1")
+            else:
+                assert False, "CALL_UNBOUND_METHOD() requires 1 or 2 call arguments"
+
+            cname = output.get_cached_unbound_method(type_cname, method_name, len(args))
+            return '%s(&%s, %s)' % (call, cname, ', '.join(args))
+
+        impl = re.sub(r'CALL_UNBOUND_METHOD\(([a-zA-Z_]+),\s*"([^"]+)"((?:,\s*[^),]+)+)\)', externalise, impl)
+        assert 'CALL_UNBOUND_METHOD(' not in impl
+
+        for helper in sorted(utility_code):
+            output.use_utility_code(UtilityCode.load_cached(helper, "ObjectHandling.c"))
+        return bool(utility_code), impl
+
+    def wrap_c_strings(self, impl):
+        """Replace CSTRING('''xyz''') by a C compatible string
+        """
+        if 'CSTRING(' not in impl:
+            return impl
+
+        def split_string(matchobj):
+            content = matchobj.group(1).replace('"', '\042')
+            return ''.join(
+                '"%s\\n"\n' % line if not line.endswith('\\') or line.endswith('\\\\') else '"%s"\n' % line[:-1]
+                for line in content.splitlines())
+
+        impl = re.sub(r'CSTRING\(\s*"""([^"]+|"[^"])"""\s*\)', split_string, impl)
+        assert 'CSTRING(' not in impl
+        return impl
+
     def put_code(self, output):
         if self.requires:
             for dependency in self.requires:
@@ -419,9 +467,10 @@ class UtilityCode(UtilityCodeBase):
                 self.format_code(self.proto),
                 '%s_proto' % self.name)
         if self.impl:
-            impl = self.format_code(self.impl)
-            is_specialised, impl = self.inject_string_constants(impl, output)
-            if not is_specialised:
+            impl = self.format_code(self.wrap_c_strings(self.impl))
+            is_specialised1, impl = self.inject_string_constants(impl, output)
+            is_specialised2, impl = self.inject_unbound_methods(impl, output)
+            if not (is_specialised1 or is_specialised2):
                 # no module specific adaptations => can be reused
                 output['utility_code_def'].put_or_include(
                     impl, '%s_impl' % self.name)
@@ -642,7 +691,7 @@ class FunctionState(object):
 
         A C string referring to the variable is returned.
         """
-        if type.is_const:
+        if type.is_const and not type.is_reference:
             type = type.const_base_type
         if not type.is_pyobject and not type.is_memoryviewslice:
             # Make manage_ref canonical, so that manage_ref will always mean
@@ -913,6 +962,7 @@ class GlobalState(object):
         'typeinfo',
         'before_global_var',
         'global_var',
+        'string_decls',
         'decls',
         'all_the_rest',
         'pystring_table',
@@ -946,6 +996,7 @@ class GlobalState(object):
         self.pyunicode_ptr_const_index = {}
         self.num_const_index = {}
         self.py_constants = []
+        self.cached_cmethods = {}
 
         assert writer.globalstate is None
         writer.globalstate = self
@@ -1000,7 +1051,8 @@ class GlobalState(object):
         # utility_code_def
         #
         code = self.parts['utility_code_def']
-        code.put(UtilityCode.load_as_string("TypeConversions", "TypeConversion.c")[1])
+        util = TempitaUtilityCode.load_cached("TypeConversions", "TypeConversion.c")
+        code.put(util.format_code(util.impl))
         code.putln("")
 
     def __getitem__(self, key):
@@ -1167,6 +1219,15 @@ class GlobalState(object):
             prefix = Naming.const_prefix
         return "%s%s" % (prefix, name_suffix)
 
+    def get_cached_unbound_method(self, type_cname, method_name, args_count):
+        key = (type_cname, method_name, args_count)
+        try:
+            cname = self.cached_cmethods[key]
+        except KeyError:
+            cname = self.cached_cmethods[key] = self.new_const_cname(
+                'umethod', '%s_%s' % (type_cname, method_name))
+        return cname
+
     def add_cached_builtin_decl(self, entry):
         if entry.is_builtin and entry.is_const:
             if self.should_declare(entry.cname, entry):
@@ -1198,6 +1259,7 @@ class GlobalState(object):
             w.error_goto(pos)))
 
     def generate_const_declarations(self):
+        self.generate_cached_methods_decls()
         self.generate_string_constants()
         self.generate_num_constants()
         self.generate_object_constant_decls()
@@ -1211,13 +1273,34 @@ class GlobalState(object):
             decls_writer.putln(
                 "static %s;" % c.type.declaration_code(cname))
 
+    def generate_cached_methods_decls(self):
+        if not self.cached_cmethods:
+            return
+
+        decl = self.parts['decls']
+        init = self.parts['init_globals']
+        cnames = []
+        for (type_cname, method_name, _), cname in sorted(self.cached_cmethods.items()):
+            cnames.append(cname)
+            method_name_cname = self.get_interned_identifier(StringEncoding.EncodedString(method_name)).cname
+            decl.putln('static __Pyx_CachedCFunction %s = {0, &%s, 0, 0, 0};' % (
+                cname, method_name_cname))
+            # split type reference storage as it might not be static
+            init.putln('%s.type = (PyObject*)&%s;' % (
+                cname, type_cname))
+
+        if Options.generate_cleanup_code:
+            cleanup = self.parts['cleanup_globals']
+            for cname in cnames:
+                cleanup.putln("Py_CLEAR(%s.method);" % cname)
+
     def generate_string_constants(self):
         c_consts = [ (len(c.cname), c.cname, c)
                      for c in self.string_const_index.values() ]
         c_consts.sort()
         py_strings = []
 
-        decls_writer = self.parts['decls']
+        decls_writer = self.parts['string_decls']
         for _, cname, c in c_consts:
             conditional = False
             if c.py_versions and (2 not in c.py_versions or 3 not in c.py_versions):
@@ -1798,6 +1881,10 @@ class CCodeWriter(object):
         if entry.type.is_pyobject:
             self.putln("__Pyx_INCREF(%s);" % self.entry_as_pyobject(entry))
 
+    def put_var_xincref(self, entry):
+        if entry.type.is_pyobject:
+            self.putln("__Pyx_XINCREF(%s);" % self.entry_as_pyobject(entry))
+
     def put_decref_clear(self, cname, type, nanny=True, clear_before_decref=False):
         self._put_decref(cname, type, nanny, null_check=False,
                          clear=True, clear_before_decref=clear_before_decref)
diff --git a/Cython/Compiler/ExprNodes.py b/Cython/Compiler/ExprNodes.py
index cd8d5e3a161f4788e57b68e063845dcd2d7ec688..dc4fb5ca704d69dac021e1efe5c2a932ea740a5e 100644
--- a/Cython/Compiler/ExprNodes.py
+++ b/Cython/Compiler/ExprNodes.py
@@ -25,7 +25,7 @@ from .Code import UtilityCode, TempitaUtilityCode
 from . import StringEncoding
 from . import Naming
 from . import Nodes
-from .Nodes import Node
+from .Nodes import Node, utility_code_for_imports
 from . import PyrexTypes
 from .PyrexTypes import py_object_type, c_long_type, typecast, error_type, \
     unspecified_type
@@ -70,24 +70,28 @@ constant_value_not_set = object()
 # error messages when coercing from key[0] to key[1]
 coercion_error_dict = {
     # string related errors
-    (Builtin.unicode_type, Builtin.bytes_type) : "Cannot convert Unicode string to 'bytes' implicitly, encoding required.",
-    (Builtin.unicode_type, Builtin.str_type)   : "Cannot convert Unicode string to 'str' implicitly. This is not portable and requires explicit encoding.",
-    (Builtin.unicode_type, PyrexTypes.c_char_ptr_type) : "Unicode objects only support coercion to Py_UNICODE*.",
-    (Builtin.unicode_type, PyrexTypes.c_uchar_ptr_type) : "Unicode objects only support coercion to Py_UNICODE*.",
-    (Builtin.bytes_type, Builtin.unicode_type) : "Cannot convert 'bytes' object to unicode implicitly, decoding required",
-    (Builtin.bytes_type, Builtin.str_type) : "Cannot convert 'bytes' object to str implicitly. This is not portable to Py3.",
-    (Builtin.bytes_type, Builtin.basestring_type) : "Cannot convert 'bytes' object to basestring implicitly. This is not portable to Py3.",
-    (Builtin.bytes_type, PyrexTypes.c_py_unicode_ptr_type) : "Cannot convert 'bytes' object to Py_UNICODE*, use 'unicode'.",
-    (Builtin.basestring_type, Builtin.bytes_type) : "Cannot convert 'basestring' object to bytes implicitly. This is not portable.",
-    (Builtin.str_type, Builtin.unicode_type) : "str objects do not support coercion to unicode, use a unicode string literal instead (u'')",
-    (Builtin.str_type, Builtin.bytes_type) : "Cannot convert 'str' to 'bytes' implicitly. This is not portable.",
-    (Builtin.str_type, PyrexTypes.c_char_ptr_type) : "'str' objects do not support coercion to C types (use 'bytes'?).",
-    (Builtin.str_type, PyrexTypes.c_uchar_ptr_type) : "'str' objects do not support coercion to C types (use 'bytes'?).",
-    (Builtin.str_type, PyrexTypes.c_py_unicode_ptr_type) : "'str' objects do not support coercion to C types (use 'unicode'?).",
-    (PyrexTypes.c_char_ptr_type, Builtin.unicode_type) : "Cannot convert 'char*' to unicode implicitly, decoding required",
-    (PyrexTypes.c_uchar_ptr_type, Builtin.unicode_type) : "Cannot convert 'char*' to unicode implicitly, decoding required",
+    (unicode_type, str_type): ("Cannot convert Unicode string to 'str' implicitly."
+                               " This is not portable and requires explicit encoding."),
+    (unicode_type, bytes_type): "Cannot convert Unicode string to 'bytes' implicitly, encoding required.",
+    (unicode_type, PyrexTypes.c_char_ptr_type): "Unicode objects only support coercion to Py_UNICODE*.",
+    (unicode_type, PyrexTypes.c_uchar_ptr_type): "Unicode objects only support coercion to Py_UNICODE*.",
+    (bytes_type, unicode_type): "Cannot convert 'bytes' object to unicode implicitly, decoding required",
+    (bytes_type, str_type): "Cannot convert 'bytes' object to str implicitly. This is not portable to Py3.",
+    (bytes_type, basestring_type): ("Cannot convert 'bytes' object to basestring implicitly."
+                                    " This is not portable to Py3."),
+    (bytes_type, PyrexTypes.c_py_unicode_ptr_type): "Cannot convert 'bytes' object to Py_UNICODE*, use 'unicode'.",
+    (basestring_type, bytes_type): "Cannot convert 'basestring' object to bytes implicitly. This is not portable.",
+    (str_type, unicode_type): ("str objects do not support coercion to unicode,"
+                               " use a unicode string literal instead (u'')"),
+    (str_type, bytes_type): "Cannot convert 'str' to 'bytes' implicitly. This is not portable.",
+    (str_type, PyrexTypes.c_char_ptr_type): "'str' objects do not support coercion to C types (use 'bytes'?).",
+    (str_type, PyrexTypes.c_uchar_ptr_type): "'str' objects do not support coercion to C types (use 'bytes'?).",
+    (str_type, PyrexTypes.c_py_unicode_ptr_type): "'str' objects do not support coercion to C types (use 'unicode'?).",
+    (PyrexTypes.c_char_ptr_type, unicode_type): "Cannot convert 'char*' to unicode implicitly, decoding required",
+    (PyrexTypes.c_uchar_ptr_type, unicode_type): "Cannot convert 'char*' to unicode implicitly, decoding required",
 }
 
+
 def find_coercion_error(type_tuple, default, env):
     err = coercion_error_dict.get(type_tuple)
     if err is None:
@@ -293,6 +297,7 @@ class ExprNode(Node):
 
     is_sequence_constructor = False
     is_dict_literal = False
+    is_set_literal = False
     is_string_literal = False
     is_attribute = False
     is_subscript = False
@@ -2251,7 +2256,6 @@ class ImportNode(ExprNode):
             name_list = self.name_list.analyse_types(env)
             self.name_list = name_list.coerce_to_pyobject(env)
         self.is_temp = 1
-        env.use_utility_code(UtilityCode.load_cached("Import", "ImportExport.c"))
         return self
 
     gil_message = "Python import"
@@ -2261,13 +2265,24 @@ class ImportNode(ExprNode):
             name_list_code = self.name_list.py_result()
         else:
             name_list_code = "0"
-        code.putln(
-            "%s = __Pyx_Import(%s, %s, %d); %s" % (
-                self.result(),
-                self.module_name.py_result(),
-                name_list_code,
-                self.level,
-                code.error_goto_if_null(self.result(), self.pos)))
+
+        code.globalstate.use_utility_code(UtilityCode.load_cached("Import", "ImportExport.c"))
+        import_code = "__Pyx_Import(%s, %s, %d)" % (
+            self.module_name.py_result(),
+            name_list_code,
+            self.level)
+
+        if (self.level <= 0 and
+                self.module_name.is_string_literal and
+                self.module_name.value in utility_code_for_imports):
+            helper_func, code_name, code_file = utility_code_for_imports[self.module_name.value]
+            code.globalstate.use_utility_code(UtilityCode.load_cached(code_name, code_file))
+            import_code = '%s(%s)' % (helper_func, import_code)
+
+        code.putln("%s = %s; %s" % (
+            self.result(),
+            import_code,
+            code.error_goto_if_null(self.result(), self.pos)))
         code.put_gotref(self.py_result())
 
 
@@ -2470,6 +2485,7 @@ class IteratorNode(ExprNode):
                 self.counter_cname,
                 inc_dec,
                 code.error_goto_if_null(result_name, self.pos)))
+        code.put_gotref(result_name)
         code.putln("#endif")
 
     def generate_iter_next_result_code(self, result_name, code):
@@ -5012,17 +5028,17 @@ class PyMethodCallNode(SimpleCallNode):
 
             if len(args) > 1:
                 code.putln("if (%s) {" % self_arg)
-            code.putln("PyTuple_SET_ITEM(%s, 0, %s); __Pyx_GIVEREF(%s); %s = NULL;" % (
-                args_tuple, self_arg, self_arg, self_arg))  # stealing owned ref in this case
+            code.putln("__Pyx_GIVEREF(%s); PyTuple_SET_ITEM(%s, 0, %s); %s = NULL;" % (
+                self_arg, args_tuple, self_arg, self_arg))  # stealing owned ref in this case
             code.funcstate.release_temp(self_arg)
             if len(args) > 1:
                 code.putln("}")
 
             for i, arg in enumerate(args):
                 arg.make_owned_reference(code)
+                code.put_giveref(arg.py_result())
                 code.putln("PyTuple_SET_ITEM(%s, %d+%s, %s);" % (
                     args_tuple, i, arg_offset, arg.py_result()))
-                code.put_giveref(arg.py_result())
             if len(args) > 1:
                 code.funcstate.release_temp(arg_offset_cname)
 
@@ -5214,8 +5230,8 @@ class GeneralCallNode(CallNode):
             self.compile_time_value_error(e)
 
     def explicit_args_kwds(self):
-        if (self.keyword_args and not isinstance(self.keyword_args, DictNode) or
-            not isinstance(self.positional_args, TupleNode)):
+        if (self.keyword_args and not self.keyword_args.is_dict_literal or
+                not self.positional_args.is_sequence_constructor):
             raise CompileError(self.pos,
                 'Compile-time keyword arguments must be explicit.')
         return self.positional_args.args, self.keyword_args
@@ -5269,7 +5285,7 @@ class GeneralCallNode(CallNode):
         if not isinstance(self.positional_args, TupleNode):
             # has starred argument
             return self
-        if not isinstance(self.keyword_args, DictNode):
+        if not self.keyword_args.is_dict_literal:
             # keywords come from arbitrary expression => nothing to do here
             return self
         function = self.function
@@ -5435,8 +5451,9 @@ class AsTupleNode(ExprNode):
             self.compile_time_value_error(e)
 
     def analyse_types(self, env):
-        self.arg = self.arg.analyse_types(env)
-        self.arg = self.arg.coerce_to_pyobject(env)
+        self.arg = self.arg.analyse_types(env).coerce_to_pyobject(env)
+        if self.arg.type is tuple_type:
+            return self.arg.as_none_safe_node("'NoneType' object is not iterable")
         self.type = tuple_type
         self.is_temp = 1
         return self
@@ -5456,6 +5473,168 @@ class AsTupleNode(ExprNode):
         code.put_gotref(self.py_result())
 
 
+class MergedDictNode(ExprNode):
+    #  Helper class for keyword arguments and other merged dicts.
+    #
+    #  keyword_args      [DictNode or other ExprNode]
+
+    subexprs = ['keyword_args']
+    is_temp = 1
+    type = dict_type
+    reject_duplicates = True
+
+    def calculate_constant_result(self):
+        result = {}
+        reject_duplicates = self.reject_duplicates
+        for item in self.keyword_args:
+            if item.is_dict_literal:
+                # process items in order
+                items = ((key.constant_result, value.constant_result)
+                         for key, value in item.key_value_pairs)
+            else:
+                items = item.constant_result.iteritems()
+
+            for key, value in items:
+                if reject_duplicates and key in result:
+                    raise ValueError("duplicate keyword argument found: %s" % key)
+                result[key] = value
+
+        self.constant_result = result
+
+    def compile_time_value(self, denv):
+        result = {}
+        reject_duplicates = self.reject_duplicates
+        for item in self.keyword_args:
+            if item.is_dict_literal:
+                # process items in order
+                items = [(key.compile_time_value(denv), value.compile_time_value(denv))
+                         for key, value in item.key_value_pairs]
+            else:
+                items = item.compile_time_value(denv).iteritems()
+
+            try:
+                for key, value in items:
+                    if reject_duplicates and key in result:
+                        raise ValueError("duplicate keyword argument found: %s" % key)
+                    result[key] = value
+            except Exception, e:
+                self.compile_time_value_error(e)
+        return result
+
+    def type_dependencies(self, env):
+        return ()
+
+    def infer_type(self, env):
+        return dict_type
+
+    def analyse_types(self, env):
+        args = [
+            arg.analyse_types(env).coerce_to_pyobject(env).as_none_safe_node(
+                # FIXME: CPython's error message starts with the runtime function name
+                'argument after ** must be a mapping, not NoneType')
+            for arg in self.keyword_args
+        ]
+
+        if len(args) == 1 and args[0].type is dict_type:
+            # strip this intermediate node and use the bare dict
+            arg = args[0]
+            if arg.is_name and arg.entry.is_arg and len(arg.entry.cf_assignments) == 1:
+                # passing **kwargs through to function call => allow NULL
+                arg.allow_null = True
+            return arg
+
+        self.keyword_args = args
+        return self
+
+    def may_be_none(self):
+        return False
+
+    gil_message = "Constructing Python dict"
+
+    def generate_evaluation_code(self, code):
+        code.mark_pos(self.pos)
+        self.allocate_temp_result(code)
+
+        args = iter(self.keyword_args)
+        item = next(args)
+        item.generate_evaluation_code(code)
+        if item.type is not dict_type:
+            # CPython supports calling functions with non-dicts, so do we
+            code.putln('if (likely(PyDict_CheckExact(%s))) {' %
+                       item.py_result())
+
+        if item.is_dict_literal:
+            item.make_owned_reference(code)
+            code.putln("%s = %s;" % (self.result(), item.py_result()))
+            item.generate_post_assignment_code(code)
+        else:
+            code.putln("%s = PyDict_Copy(%s); %s" % (
+                self.result(),
+                item.py_result(),
+                code.error_goto_if_null(self.result(), item.pos)))
+            code.put_gotref(self.result())
+            item.generate_disposal_code(code)
+
+        if item.type is not dict_type:
+            code.putln('} else {')
+            code.putln("%s = PyObject_CallFunctionObjArgs((PyObject*)&PyDict_Type, %s, NULL); %s" % (
+                self.result(),
+                item.py_result(),
+                code.error_goto_if_null(self.result(), self.pos)))
+            code.put_gotref(self.py_result())
+            item.generate_disposal_code(code)
+            code.putln('}')
+        item.free_temps(code)
+
+        helpers = set()
+        for item in args:
+            if item.is_dict_literal:
+                # inline update instead of creating an intermediate dict
+                for arg in item.key_value_pairs:
+                    arg.generate_evaluation_code(code)
+                    if self.reject_duplicates:
+                        code.putln("if (unlikely(PyDict_Contains(%s, %s))) {" % (
+                            self.result(),
+                            arg.key.py_result()))
+                        helpers.add("RaiseDoubleKeywords")
+                        # FIXME: find out function name at runtime!
+                        code.putln('__Pyx_RaiseDoubleKeywordsError("function", %s); %s' % (
+                            arg.key.py_result(),
+                            code.error_goto(self.pos)))
+                        code.putln("}")
+                    code.put_error_if_neg(arg.key.pos, "PyDict_SetItem(%s, %s, %s)" % (
+                        self.result(),
+                        arg.key.py_result(),
+                        arg.value.py_result()))
+                    arg.generate_disposal_code(code)
+                    arg.free_temps(code)
+            else:
+                item.generate_evaluation_code(code)
+                if self.reject_duplicates:
+                    # merge mapping into kwdict one by one as we need to check for duplicates
+                    helpers.add("MergeKeywords")
+                    code.put_error_if_neg(item.pos, "__Pyx_MergeKeywords(%s, %s)" % (
+                        self.result(), item.py_result()))
+                else:
+                    # simple case, just add all entries
+                    helpers.add("RaiseMappingExpected")
+                    code.putln("if (unlikely(PyDict_Update(%s, %s) < 0)) {" % (
+                        self.result(), item.py_result()))
+                    code.putln("if (PyErr_ExceptionMatches(PyExc_AttributeError)) "
+                               "__Pyx_RaiseMappingExpectedError(%s);" % item.py_result())
+                    code.putln(code.error_goto(item.pos))
+                    code.putln("}")
+                item.generate_disposal_code(code)
+                item.free_temps(code)
+
+        for helper in sorted(helpers):
+            code.globalstate.use_utility_code(UtilityCode.load_cached(helper, "FunctionArguments.c"))
+
+    def annotate(self, code):
+        for item in self.keyword_args:
+            item.annotate(code)
+
+
 class AttributeNode(ExprNode):
     #  obj.attribute
     #
@@ -5992,14 +6171,14 @@ class AttributeNode(ExprNode):
 #
 #-------------------------------------------------------------------
 
-class StarredTargetNode(ExprNode):
+class StarredUnpackingNode(ExprNode):
     #  A starred expression like "*a"
     #
-    #  This is only allowed in sequence assignment targets such as
+    #  This is only allowed in sequence assignment or construction such as
     #
     #      a, *b = (1,2,3,4)    =>     a = 1 ; b = [2,3,4]
     #
-    #  and will be removed during type analysis (or generate an error
+    #  and will be special cased during type analysis (or generate an error
     #  if it's found at unexpected places).
     #
     #  target          ExprNode
@@ -6008,17 +6187,22 @@ class StarredTargetNode(ExprNode):
     is_starred = 1
     type = py_object_type
     is_temp = 1
+    starred_expr_allowed_here = False
 
     def __init__(self, pos, target):
-        ExprNode.__init__(self, pos)
-        self.target = target
+        ExprNode.__init__(self, pos, target=target)
 
     def analyse_declarations(self, env):
-        error(self.pos, "can use starred expression only as assignment target")
+        if not self.starred_expr_allowed_here:
+            error(self.pos, "starred expression is not allowed here")
         self.target.analyse_declarations(env)
 
+    def infer_type(self, env):
+        return self.target.infer_type(env)
+
     def analyse_types(self, env):
-        error(self.pos, "can use starred expression only as assignment target")
+        if not self.starred_expr_allowed_here:
+            error(self.pos, "starred expression is not allowed here")
         self.target = self.target.analyse_types(env)
         self.type = self.target.type
         return self
@@ -6077,9 +6261,9 @@ class SequenceNode(ExprNode):
             arg.analyse_target_declaration(env)
 
     def analyse_types(self, env, skip_children=False):
-        for i in range(len(self.args)):
-            arg = self.args[i]
-            if not skip_children: arg = arg.analyse_types(env)
+        for i, arg in enumerate(self.args):
+            if not skip_children:
+                arg = arg.analyse_types(env)
             self.args[i] = arg.coerce_to_pyobject(env)
         if self.mult_factor:
             self.mult_factor = self.mult_factor.analyse_types(env)
@@ -6089,6 +6273,39 @@ class SequenceNode(ExprNode):
         # not setting self.type here, subtypes do this
         return self
 
+    def _create_merge_node_if_necessary(self, env):
+        self._flatten_starred_args()
+        if not any(arg.is_starred for arg in self.args):
+            return self
+        # convert into MergedSequenceNode by building partial sequences
+        args = []
+        values = []
+        for arg in self.args:
+            if arg.is_starred:
+                if values:
+                    args.append(TupleNode(values[0].pos, args=values).analyse_types(env, skip_children=True))
+                    values = []
+                args.append(arg.target)
+            else:
+                values.append(arg)
+        if values:
+            args.append(TupleNode(values[0].pos, args=values).analyse_types(env, skip_children=True))
+        node = MergedSequenceNode(self.pos, args, self.type)
+        if self.mult_factor:
+            node = binop_node(
+                self.pos, '*', node, self.mult_factor.coerce_to_pyobject(env),
+                inplace=True, type=self.type, is_temp=True)
+        return node
+
+    def _flatten_starred_args(self):
+        args = []
+        for arg in self.args:
+            if arg.is_starred and arg.target.is_sequence_constructor and not arg.target.mult_factor:
+                args.extend(arg.target.args)
+            else:
+                args.append(arg)
+        self.args[:] = args
+
     def may_be_none(self):
         return False
 
@@ -6101,11 +6318,11 @@ class SequenceNode(ExprNode):
         for i, arg in enumerate(self.args):
             arg = self.args[i] = arg.analyse_target_types(env)
             if arg.is_starred:
-                if not arg.type.assignable_from(Builtin.list_type):
+                if not arg.type.assignable_from(list_type):
                     error(arg.pos,
                           "starred target must have Python object (list) type")
                 if arg.type is py_object_type:
-                    arg.type = Builtin.list_type
+                    arg.type = list_type
             unpacked_item = PyTempNode(self.pos, env)
             coerced_unpacked_item = unpacked_item.coerce_to(arg.type, env)
             if unpacked_item is not coerced_unpacked_item:
@@ -6136,12 +6353,12 @@ class SequenceNode(ExprNode):
                 else:
                     size_factor = ' * (%s)' % (c_mult,)
 
-        if self.type is Builtin.tuple_type and (self.is_literal or self.slow) and not c_mult:
+        if self.type is tuple_type and (self.is_literal or self.slow) and not c_mult:
             # use PyTuple_Pack() to avoid generating huge amounts of one-time code
             code.putln('%s = PyTuple_Pack(%d, %s); %s' % (
                 target,
                 len(self.args),
-                ', '.join([ arg.py_result() for arg in self.args ]),
+                ', '.join(arg.py_result() for arg in self.args),
                 code.error_goto_if_null(target, self.pos)))
             code.put_gotref(target)
         elif self.type.is_ctuple:
@@ -6150,9 +6367,9 @@ class SequenceNode(ExprNode):
                     target, i, arg.result()))
         else:
             # build the tuple/list step by step, potentially multiplying it as we go
-            if self.type is Builtin.list_type:
+            if self.type is list_type:
                 create_func, set_item_func = 'PyList_New', 'PyList_SET_ITEM'
-            elif self.type is Builtin.tuple_type:
+            elif self.type is tuple_type:
                 create_func, set_item_func = 'PyTuple_New', 'PyTuple_SET_ITEM'
             else:
                 raise InternalError("sequence packing for unexpected type %s" % self.type)
@@ -6184,12 +6401,12 @@ class SequenceNode(ExprNode):
                 arg = self.args[i]
                 if c_mult or not arg.result_in_temp():
                     code.put_incref(arg.result(), arg.ctype())
+                code.put_giveref(arg.py_result())
                 code.putln("%s(%s, %s, %s);" % (
                     set_item_func,
                     target,
                     (offset and i) and ('%s + %s' % (offset, i)) or (offset or i),
                     arg.py_result()))
-                code.put_giveref(arg.py_result())
 
             if c_mult:
                 code.putln('}')
@@ -6209,7 +6426,7 @@ class SequenceNode(ExprNode):
     def generate_subexpr_disposal_code(self, code):
         if self.mult_factor and self.mult_factor.type.is_int:
             super(SequenceNode, self).generate_subexpr_disposal_code(code)
-        elif self.type is Builtin.tuple_type and (self.is_literal or self.slow):
+        elif self.type is tuple_type and (self.is_literal or self.slow):
             super(SequenceNode, self).generate_subexpr_disposal_code(code)
         else:
             # We call generate_post_assignment_code here instead
@@ -6528,39 +6745,42 @@ class TupleNode(SequenceNode):
         if any(type.is_pyobject or type.is_unspecified or type.is_fused for type in arg_types):
             return tuple_type
         else:
-            type = PyrexTypes.c_tuple_type(arg_types)
-            env.declare_tuple_type(self.pos, type)
-            return type
+            return env.declare_tuple_type(self.pos, arg_types).type
 
     def analyse_types(self, env, skip_children=False):
         if len(self.args) == 0:
             self.is_temp = False
             self.is_literal = True
             return self
-        else:
-            if not skip_children:
-                self.args = [arg.analyse_types(env) for arg in self.args]
-            if not self.mult_factor and not any(arg.type.is_pyobject or arg.type.is_fused for arg in self.args):
-                self.type = PyrexTypes.c_tuple_type(arg.type for arg in self.args)
-                env.declare_tuple_type(self.pos, self.type)
-                self.is_temp = 1
-                return self
-            else:
-                node = SequenceNode.analyse_types(self, env, skip_children=True)
-                for child in node.args:
-                    if not child.is_literal:
-                        break
-                else:
-                    if not node.mult_factor or node.mult_factor.is_literal and \
-                           isinstance(node.mult_factor.constant_result, (int, long)):
-                        node.is_temp = False
-                        node.is_literal = True
-                    else:
-                        if not node.mult_factor.type.is_pyobject:
-                            node.mult_factor = node.mult_factor.coerce_to_pyobject(env)
-                        node.is_temp = True
-                        node.is_partly_literal = True
-                return node
+
+        if not skip_children:
+            for i, arg in enumerate(self.args):
+                if arg.is_starred:
+                    arg.starred_expr_allowed_here = True
+                self.args[i] = arg.analyse_types(env)
+        if (not self.mult_factor and
+                not any((arg.is_starred or arg.type.is_pyobject or arg.type.is_fused) for arg in self.args)):
+            self.type = env.declare_tuple_type(self.pos, (arg.type for arg in self.args)).type
+            self.is_temp = 1
+            return self
+
+        node = SequenceNode.analyse_types(self, env, skip_children=True)
+        node = node._create_merge_node_if_necessary(env)
+        if not node.is_sequence_constructor:
+            return node
+
+        if not all(child.is_literal for child in node.args):
+            return node
+        if not node.mult_factor or (
+                node.mult_factor.is_literal and isinstance(node.mult_factor.constant_result, (int, long))):
+            node.is_temp = False
+            node.is_literal = True
+        else:
+            if not node.mult_factor.type.is_pyobject:
+                node.mult_factor = node.mult_factor.coerce_to_pyobject(env)
+            node.is_temp = True
+            node.is_partly_literal = True
+        return node
 
     def coerce_to(self, dst_type, env):
         if self.type.is_ctuple:
@@ -6657,6 +6877,9 @@ class ListNode(SequenceNode):
         return list_type
 
     def analyse_expressions(self, env):
+        for arg in self.args:
+            if arg.is_starred:
+                arg.starred_expr_allowed_here = True
         node = SequenceNode.analyse_expressions(self, env)
         return node.coerce_to_pyobject(env)
 
@@ -6668,6 +6891,7 @@ class ListNode(SequenceNode):
         release_errors(ignore=True)
         if env.is_module_scope:
             self.in_module_scope = True
+        node = node._create_merge_node_if_necessary(env)
         return node
 
     def coerce_to(self, dst_type, env):
@@ -7062,13 +7286,182 @@ class InlinedGeneratorExpressionNode(ScopedExprNode):
         self.loop.generate_execution_code(code)
 
 
-class SetNode(ExprNode):
-    #  Set constructor.
+class MergedSequenceNode(ExprNode):
+    """
+    Merge a sequence of iterables into a set/list/tuple.
 
-    type = set_type
+    The target collection is determined by self.type, which must be set externally.
 
+    args    [ExprNode]
+    """
     subexprs = ['args']
+    is_temp = True
+    gil_message = "Constructing Python collection"
+
+    def __init__(self, pos, args, type):
+        if type in (list_type, tuple_type) and args and args[0].is_sequence_constructor:
+            # construct a list directly from the first argument that we can then extend
+            if args[0].type is not list_type:
+                args[0] = ListNode(args[0].pos, args=args[0].args, is_temp=True)
+        ExprNode.__init__(self, pos, args=args, type=type)
+
+    def calculate_constant_result(self):
+        result = []
+        for item in self.args:
+            if item.is_sequence_constructor and item.mult_factor:
+                if item.mult_factor.constant_result <= 0:
+                    continue
+                # otherwise, adding each item once should be enough
+            if item.is_set_literal or item.is_sequence_constructor:
+                # process items in order
+                items = (arg.constant_result for arg in item.args)
+            else:
+                items = item.constant_result
+            result.extend(items)
+        if self.type is set_type:
+            result = set(result)
+        elif self.type is tuple_type:
+            result = tuple(result)
+        else:
+            assert self.type is list_type
+        self.constant_result = result
+
+    def compile_time_value(self, denv):
+        result = []
+        for item in self.args:
+            if item.is_sequence_constructor and item.mult_factor:
+                if item.mult_factor.compile_time_value(denv) <= 0:
+                    continue
+            if item.is_set_literal or item.is_sequence_constructor:
+                # process items in order
+                items = (arg.compile_time_value(denv) for arg in item.args)
+            else:
+                items = item.compile_time_value(denv)
+            result.extend(items)
+        if self.type is set_type:
+            try:
+                result = set(result)
+            except Exception as e:
+                self.compile_time_value_error(e)
+        elif self.type is tuple_type:
+            result = tuple(result)
+        else:
+            assert self.type is list_type
+        return result
+
+    def type_dependencies(self, env):
+        return ()
+
+    def infer_type(self, env):
+        return self.type
+
+    def analyse_types(self, env):
+        args = [
+            arg.analyse_types(env).coerce_to_pyobject(env).as_none_safe_node(
+                # FIXME: CPython's error message starts with the runtime function name
+                'argument after * must be an iterable, not NoneType')
+            for arg in self.args
+        ]
+
+        if len(args) == 1 and args[0].type is self.type:
+            # strip this intermediate node and use the bare collection
+            return args[0]
+
+        assert self.type in (set_type, list_type, tuple_type)
+
+        self.args = args
+        return self
+
+    def may_be_none(self):
+        return False
+
+    def generate_evaluation_code(self, code):
+        code.mark_pos(self.pos)
+        self.allocate_temp_result(code)
+
+        is_set = self.type is set_type
+
+        args = iter(self.args)
+        item = next(args)
+        item.generate_evaluation_code(code)
+        if (is_set and item.is_set_literal or
+                not is_set and item.is_sequence_constructor and item.type is list_type):
+            code.putln("%s = %s;" % (self.result(), item.py_result()))
+            item.generate_post_assignment_code(code)
+        else:
+            code.putln("%s = %s(%s); %s" % (
+                self.result(),
+                'PySet_New' if is_set else 'PySequence_List',
+                item.py_result(),
+                code.error_goto_if_null(self.result(), self.pos)))
+            code.put_gotref(self.py_result())
+            item.generate_disposal_code(code)
+        item.free_temps(code)
+
+        helpers = set()
+        if is_set:
+            add_func = "PySet_Add"
+            extend_func = "__Pyx_PySet_Update"
+        else:
+            add_func = "__Pyx_ListComp_Append"
+            extend_func = "__Pyx_PyList_Extend"
+
+        for item in args:
+            if (is_set and (item.is_set_literal or item.is_sequence_constructor) or
+                    (item.is_sequence_constructor and not item.mult_factor)):
+                if not is_set and item.args:
+                    helpers.add(("ListCompAppend", "Optimize.c"))
+                for arg in item.args:
+                    arg.generate_evaluation_code(code)
+                    code.put_error_if_neg(arg.pos, "%s(%s, %s)" % (
+                        add_func,
+                        self.result(),
+                        arg.py_result()))
+                    arg.generate_disposal_code(code)
+                    arg.free_temps(code)
+                continue
+
+            if is_set:
+                helpers.add(("PySet_Update", "Builtins.c"))
+            else:
+                helpers.add(("ListExtend", "Optimize.c"))
+
+            item.generate_evaluation_code(code)
+            code.put_error_if_neg(item.pos, "%s(%s, %s)" % (
+                extend_func,
+                self.result(),
+                item.py_result()))
+            item.generate_disposal_code(code)
+            item.free_temps(code)
+
+        if self.type is tuple_type:
+            code.putln("{")
+            code.putln("PyObject *%s = PyList_AsTuple(%s);" % (
+                Naming.quick_temp_cname,
+                self.result()))
+            code.put_decref(self.result(), py_object_type)
+            code.putln("%s = %s; %s" % (
+                self.result(),
+                Naming.quick_temp_cname,
+                code.error_goto_if_null(self.result(), self.pos)))
+            code.put_gotref(self.result())
+            code.putln("}")
+
+        for helper in sorted(helpers):
+            code.globalstate.use_utility_code(UtilityCode.load_cached(*helper))
 
+    def annotate(self, code):
+        for item in self.args:
+            item.annotate(code)
+
+
+class SetNode(ExprNode):
+    """
+    Set constructor.
+    """
+    subexprs = ['args']
+    type = set_type
+    is_set_literal = True
     gil_message = "Constructing Python set"
 
     def analyse_types(self, env):
@@ -7123,6 +7516,7 @@ class DictNode(ExprNode):
     exclude_null_values = False
     type = dict_type
     is_dict_literal = True
+    reject_duplicates = False
 
     obj_conversion_errors = []
 
@@ -7164,6 +7558,13 @@ class DictNode(ExprNode):
     def coerce_to(self, dst_type, env):
         if dst_type.is_pyobject:
             self.release_errors()
+            if self.type.is_struct_or_union:
+                if not dict_type.subtype_of(dst_type):
+                    error(self.pos, "Cannot interpret struct as non-dict type '%s'" % dst_type)
+                return DictNode(self.pos, key_value_pairs=[
+                    DictItemNode(item.pos, key=item.key.coerce_to_pyobject(env),
+                                 value=item.value.coerce_to_pyobject(env))
+                    for item in self.key_value_pairs])
             if not self.type.subtype_of(dst_type):
                 error(self.pos, "Cannot interpret dict as type '%s'" % dst_type)
         elif dst_type.is_struct_or_union:
@@ -7205,23 +7606,60 @@ class DictNode(ExprNode):
         #  pairs are evaluated and used one at a time.
         code.mark_pos(self.pos)
         self.allocate_temp_result(code)
-        if self.type.is_pyobject:
+
+        is_dict = self.type.is_pyobject
+        if is_dict:
             self.release_errors()
             code.putln(
                 "%s = PyDict_New(); %s" % (
                     self.result(),
                     code.error_goto_if_null(self.result(), self.pos)))
             code.put_gotref(self.py_result())
+
+        keys_seen = set()
+        key_type = None
+        needs_error_helper = False
+
         for item in self.key_value_pairs:
             item.generate_evaluation_code(code)
-            if self.type.is_pyobject:
+            if is_dict:
                 if self.exclude_null_values:
                     code.putln('if (%s) {' % item.value.py_result())
-                code.put_error_if_neg(self.pos,
-                    "PyDict_SetItem(%s, %s, %s)" % (
-                        self.result(),
-                        item.key.py_result(),
-                        item.value.py_result()))
+                key = item.key
+                if self.reject_duplicates:
+                    if keys_seen is not None:
+                        # avoid runtime 'in' checks for literals that we can do at compile time
+                        if not key.is_string_literal:
+                            keys_seen = None
+                        elif key.value in keys_seen:
+                            # FIXME: this could be a compile time error, at least in Cython code
+                            keys_seen = None
+                        elif key_type is not type(key.value):
+                            if key_type is None:
+                                key_type = type(key.value)
+                                keys_seen.add(key.value)
+                            else:
+                                # different types => may not be able to compare at compile time
+                                keys_seen = None
+                        else:
+                            keys_seen.add(key.value)
+
+                    if keys_seen is None:
+                        code.putln('if (unlikely(PyDict_Contains(%s, %s))) {' % (
+                            self.result(), key.py_result()))
+                        # currently only used in function calls
+                        needs_error_helper = True
+                        code.putln('__Pyx_RaiseDoubleKeywordsError("function", %s); %s' % (
+                            key.py_result(),
+                            code.error_goto(item.pos)))
+                        code.putln("} else {")
+
+                code.put_error_if_neg(self.pos, "PyDict_SetItem(%s, %s, %s)" % (
+                    self.result(),
+                    item.key.py_result(),
+                    item.value.py_result()))
+                if self.reject_duplicates and keys_seen is None:
+                    code.putln('}')
                 if self.exclude_null_values:
                     code.putln('}')
             else:
@@ -7232,10 +7670,15 @@ class DictNode(ExprNode):
             item.generate_disposal_code(code)
             item.free_temps(code)
 
+        if needs_error_helper:
+            code.globalstate.use_utility_code(
+                UtilityCode.load_cached("RaiseDoubleKeywords", "FunctionArguments.c"))
+
     def annotate(self, code):
         for item in self.key_value_pairs:
             item.annotate(code)
 
+
 class DictItemNode(ExprNode):
     # Represents a single item in a DictNode
     #
@@ -7435,120 +7878,6 @@ class Py3ClassNode(ExprNode):
                 code.error_goto_if_null(self.result(), self.pos)))
         code.put_gotref(self.py_result())
 
-class KeywordArgsNode(ExprNode):
-    #  Helper class for keyword arguments.
-    #
-    #  starstar_arg      DictNode
-    #  keyword_args      [DictItemNode]
-
-    subexprs = ['starstar_arg', 'keyword_args']
-    is_temp = 1
-    type = dict_type
-
-    def calculate_constant_result(self):
-        result = dict(self.starstar_arg.constant_result)
-        for item in self.keyword_args:
-            key, value = item.constant_result
-            if key in result:
-                raise ValueError("duplicate keyword argument found: %s" % key)
-            result[key] = value
-        self.constant_result = result
-
-    def compile_time_value(self, denv):
-        result = self.starstar_arg.compile_time_value(denv)
-        pairs = [ (item.key.compile_time_value(denv), item.value.compile_time_value(denv))
-                  for item in self.keyword_args ]
-        try:
-            result = dict(result)
-            for key, value in pairs:
-                if key in result:
-                    raise ValueError("duplicate keyword argument found: %s" % key)
-                result[key] = value
-        except Exception, e:
-            self.compile_time_value_error(e)
-        return result
-
-    def type_dependencies(self, env):
-        return ()
-
-    def infer_type(self, env):
-        return dict_type
-
-    def analyse_types(self, env):
-        arg = self.starstar_arg.analyse_types(env)
-        arg = arg.coerce_to_pyobject(env)
-        self.starstar_arg = arg.as_none_safe_node(
-            # FIXME: CPython's error message starts with the runtime function name
-            'argument after ** must be a mapping, not NoneType')
-        self.keyword_args = [ item.analyse_types(env)
-                              for item in self.keyword_args ]
-        return self
-
-    def may_be_none(self):
-        return False
-
-    gil_message = "Constructing Python dict"
-
-    def generate_evaluation_code(self, code):
-        code.mark_pos(self.pos)
-        self.allocate_temp_result(code)
-        self.starstar_arg.generate_evaluation_code(code)
-        if self.starstar_arg.type is not Builtin.dict_type:
-            # CPython supports calling functions with non-dicts, so do we
-            code.putln('if (likely(PyDict_Check(%s))) {' %
-                       self.starstar_arg.py_result())
-        if self.keyword_args:
-            code.putln(
-                "%s = PyDict_Copy(%s); %s" % (
-                    self.result(),
-                    self.starstar_arg.py_result(),
-                    code.error_goto_if_null(self.result(), self.pos)))
-            code.put_gotref(self.py_result())
-        else:
-            code.putln("%s = %s;" % (
-                self.result(),
-                self.starstar_arg.py_result()))
-            code.put_incref(self.result(), py_object_type)
-        if self.starstar_arg.type is not Builtin.dict_type:
-            code.putln('} else {')
-            code.putln(
-                "%s = PyObject_CallFunctionObjArgs("
-                "(PyObject*)&PyDict_Type, %s, NULL); %s" % (
-                    self.result(),
-                    self.starstar_arg.py_result(),
-                    code.error_goto_if_null(self.result(), self.pos)))
-            code.put_gotref(self.py_result())
-            code.putln('}')
-        self.starstar_arg.generate_disposal_code(code)
-        self.starstar_arg.free_temps(code)
-
-        if not self.keyword_args:
-            return
-
-        code.globalstate.use_utility_code(
-            UtilityCode.load_cached("RaiseDoubleKeywords", "FunctionArguments.c"))
-        for item in self.keyword_args:
-            item.generate_evaluation_code(code)
-            code.putln("if (unlikely(PyDict_GetItem(%s, %s))) {" % (
-                    self.result(),
-                    item.key.py_result()))
-            # FIXME: find out function name at runtime!
-            code.putln('__Pyx_RaiseDoubleKeywordsError("function", %s); %s' % (
-                item.key.py_result(),
-                code.error_goto(self.pos)))
-            code.putln("}")
-            code.put_error_if_neg(self.pos,
-                "PyDict_SetItem(%s, %s, %s)" % (
-                    self.result(),
-                    item.key.py_result(),
-                    item.value.py_result()))
-            item.generate_disposal_code(code)
-            item.free_temps(code)
-
-    def annotate(self, code):
-        self.starstar_arg.annotate(code)
-        for item in self.keyword_args:
-            item.annotate(code)
 
 class PyClassMetaclassNode(ExprNode):
     # Helper class holds Python3 metaclass object
@@ -7660,7 +7989,7 @@ class ClassCellInjectorNode(ExprNode):
 
     def generate_injection_code(self, code, classobj_cname):
         if self.is_active:
-            code.putln('__Pyx_CyFunction_InitClassCell(%s, %s);' % (
+            code.put_error_if_neg(self.pos, '__Pyx_CyFunction_InitClassCell(%s, %s)' % (
                 self.result(), classobj_cname))
 
 
@@ -9821,11 +10150,13 @@ class DivNode(NumBinopNode):
                                     or not self.type.signed
                                     or self.type.is_float)
             if not self.cdivision:
-                code.globalstate.use_utility_code(div_int_utility_code.specialize(self.type))
+                code.globalstate.use_utility_code(
+                    UtilityCode.load_cached("DivInt", "CMath.c").specialize(self.type))
         NumBinopNode.generate_evaluation_code(self, code)
         self.generate_div_warning_code(code)
 
     def generate_div_warning_code(self, code):
+        in_nogil = self.in_nogil_context
         if not self.type.is_pyobject:
             if self.zerodivision_check:
                 if not self.infix:
@@ -9833,13 +10164,15 @@ class DivNode(NumBinopNode):
                 else:
                     zero_test = "%s == 0" % self.operand2.result()
                 code.putln("if (unlikely(%s)) {" % zero_test)
-                code.put_ensure_gil()
+                if in_nogil:
+                    code.put_ensure_gil()
                 code.putln('PyErr_SetString(PyExc_ZeroDivisionError, "%s");' % self.zero_division_message())
-                code.put_release_ensured_gil()
+                if in_nogil:
+                    code.put_release_ensured_gil()
                 code.putln(code.error_goto(self.pos))
                 code.putln("}")
                 if self.type.is_int and self.type.signed and self.operator != '%':
-                    code.globalstate.use_utility_code(division_overflow_test_code)
+                    code.globalstate.use_utility_code(UtilityCode.load_cached("UnaryNegOverflows", "Overflow.c"))
                     if self.operand2.type.signed == 2:
                         # explicitly signed, no runtime check needed
                         minus1_check = 'unlikely(%s == -1)' % self.operand2.result()
@@ -9852,28 +10185,38 @@ class DivNode(NumBinopNode):
                                self.type.empty_declaration_code(),
                                minus1_check,
                                self.operand1.result()))
-                    code.put_ensure_gil()
+                    if in_nogil:
+                        code.put_ensure_gil()
                     code.putln('PyErr_SetString(PyExc_OverflowError, "value too large to perform division");')
-                    code.put_release_ensured_gil()
+                    if in_nogil:
+                        code.put_release_ensured_gil()
                     code.putln(code.error_goto(self.pos))
                     code.putln("}")
             if code.globalstate.directives['cdivision_warnings'] and self.operator != '/':
-                code.globalstate.use_utility_code(cdivision_warning_utility_code)
+                code.globalstate.use_utility_code(
+                    UtilityCode.load_cached("CDivisionWarning", "CMath.c"))
                 code.putln("if (unlikely((%s < 0) ^ (%s < 0))) {" % (
                                 self.operand1.result(),
                                 self.operand2.result()))
-                code.put_ensure_gil()
-                code.putln(code.set_error_info(self.pos, used=True))
-                code.putln("if (__Pyx_cdivision_warning(%(FILENAME)s, "
-                                                       "%(LINENO)s)) {" % {
+                warning_code = "__Pyx_cdivision_warning(%(FILENAME)s, %(LINENO)s)" % {
                     'FILENAME': Naming.filename_cname,
                     'LINENO':  Naming.lineno_cname,
-                    })
-                code.put_release_ensured_gil()
+                }
+
+                if in_nogil:
+                    result_code = 'result'
+                    code.putln("int %s;" % result_code)
+                    code.put_ensure_gil()
+                    code.putln(code.set_error_info(self.pos, used=True))
+                    code.putln("%s = %s;" % (result_code, warning_code))
+                    code.put_release_ensured_gil()
+                else:
+                    result_code = warning_code
+                    code.putln(code.set_error_info(self.pos, used=True))
+
+                code.put("if (unlikely(%s)) " % result_code)
                 code.put_goto(code.error_label)
                 code.putln("}")
-                code.put_release_ensured_gil()
-                code.putln("}")
 
     def calculate_result_code(self):
         if self.type.is_complex:
@@ -9941,12 +10284,12 @@ class ModNode(DivNode):
         if not self.type.is_pyobject and not self.cdivision:
             if self.type.is_int:
                 code.globalstate.use_utility_code(
-                    mod_int_utility_code.specialize(self.type))
+                    UtilityCode.load_cached("ModInt", "CMath.c").specialize(self.type))
             else:  # float
                 code.globalstate.use_utility_code(
-                    mod_float_utility_code.specialize(
+                    UtilityCode.load_cached("ModFloat", "CMath.c").specialize(
                         self.type, math_h_modifier=self.type.math_h_modifier))
-        # note: skipping over DivNode here
+        # NOTE: skipping over DivNode here
         NumBinopNode.generate_evaluation_code(self, code)
         self.generate_div_warning_code(code)
 
@@ -9999,7 +10342,7 @@ class PowNode(NumBinopNode):
         elif self.type.is_int:
             self.pow_func = "__Pyx_pow_%s" % self.type.empty_declaration_code().replace(' ', '_')
             env.use_utility_code(
-                int_pow_utility_code.specialize(
+                UtilityCode.load_cached("IntPow", "CMath.c").specialize(
                     func_name=self.pow_func,
                     type=self.type.empty_declaration_code(),
                     signed=self.type.signed and 1 or 0))
@@ -10615,18 +10958,18 @@ class CmpNode(object):
             if self.operand2.type is Builtin.dict_type:
                 self.operand2 = self.operand2.as_none_safe_node("'NoneType' object is not iterable")
                 self.special_bool_cmp_utility_code = UtilityCode.load_cached("PyDictContains", "ObjectHandling.c")
-                self.special_bool_cmp_function = "__Pyx_PyDict_Contains"
+                self.special_bool_cmp_function = "__Pyx_PyDict_ContainsTF"
                 return True
             elif self.operand2.type is Builtin.unicode_type:
                 self.operand2 = self.operand2.as_none_safe_node("'NoneType' object is not iterable")
                 self.special_bool_cmp_utility_code = UtilityCode.load_cached("PyUnicodeContains", "StringTools.c")
-                self.special_bool_cmp_function = "__Pyx_PyUnicode_Contains"
+                self.special_bool_cmp_function = "__Pyx_PyUnicode_ContainsTF"
                 return True
             else:
                 if not self.operand2.type.is_pyobject:
                     self.operand2 = self.operand2.coerce_to_pyobject(env)
                 self.special_bool_cmp_utility_code = UtilityCode.load_cached("PySequenceContains", "ObjectHandling.c")
-                self.special_bool_cmp_function = "__Pyx_PySequence_Contains"
+                self.special_bool_cmp_function = "__Pyx_PySequence_ContainsTF"
                 return True
         return False
 
@@ -11466,11 +11809,13 @@ class CoerceToBooleanNode(CoercionNode):
     type = PyrexTypes.c_bint_type
 
     _special_builtins = {
-        Builtin.list_type    : 'PyList_GET_SIZE',
-        Builtin.tuple_type   : 'PyTuple_GET_SIZE',
-        Builtin.bytes_type   : 'PyBytes_GET_SIZE',
-        Builtin.unicode_type : 'PyUnicode_GET_SIZE',
-        }
+        Builtin.list_type:       'PyList_GET_SIZE',
+        Builtin.tuple_type:      'PyTuple_GET_SIZE',
+        Builtin.set_type:        'PySet_GET_SIZE',
+        Builtin.frozenset_type:  'PySet_GET_SIZE',
+        Builtin.bytes_type:      'PyBytes_GET_SIZE',
+        Builtin.unicode_type:    'PyUnicode_GET_SIZE',
+    }
 
     def __init__(self, arg, env):
         CoercionNode.__init__(self, arg)
@@ -11509,6 +11854,7 @@ class CoerceToBooleanNode(CoercionNode):
                     self.arg.py_result(),
                     code.error_goto_if_neg(self.result(), self.pos)))
 
+
 class CoerceToComplexNode(CoercionNode):
 
     def __init__(self, arg, dst_type, env):
@@ -11810,103 +12156,3 @@ requires = [raise_unbound_local_error_utility_code])
 raise_too_many_values_to_unpack = UtilityCode.load_cached("RaiseTooManyValuesToUnpack", "ObjectHandling.c")
 raise_need_more_values_to_unpack = UtilityCode.load_cached("RaiseNeedMoreValuesToUnpack", "ObjectHandling.c")
 tuple_unpacking_error_code = UtilityCode.load_cached("UnpackTupleError", "ObjectHandling.c")
-
-#------------------------------------------------------------------------------------
-
-int_pow_utility_code = UtilityCode(
-proto="""
-static CYTHON_INLINE %(type)s %(func_name)s(%(type)s, %(type)s); /* proto */
-""",
-impl="""
-static CYTHON_INLINE %(type)s %(func_name)s(%(type)s b, %(type)s e) {
-    %(type)s t = b;
-    switch (e) {
-        case 3:
-            t *= b;
-        case 2:
-            t *= b;
-        case 1:
-            return t;
-        case 0:
-            return 1;
-    }
-    #if %(signed)s
-    if (unlikely(e<0)) return 0;
-    #endif
-    t = 1;
-    while (likely(e)) {
-        t *= (b * (e&1)) | ((~e)&1);    /* 1 or b */
-        b *= b;
-        e >>= 1;
-    }
-    return t;
-}
-""")
-
-# ------------------------------ Division ------------------------------------
-
-div_int_utility_code = UtilityCode(
-proto="""
-static CYTHON_INLINE %(type)s __Pyx_div_%(type_name)s(%(type)s, %(type)s); /* proto */
-""",
-impl="""
-static CYTHON_INLINE %(type)s __Pyx_div_%(type_name)s(%(type)s a, %(type)s b) {
-    %(type)s q = a / b;
-    %(type)s r = a - q*b;
-    q -= ((r != 0) & ((r ^ b) < 0));
-    return q;
-}
-""")
-
-mod_int_utility_code = UtilityCode(
-proto="""
-static CYTHON_INLINE %(type)s __Pyx_mod_%(type_name)s(%(type)s, %(type)s); /* proto */
-""",
-impl="""
-static CYTHON_INLINE %(type)s __Pyx_mod_%(type_name)s(%(type)s a, %(type)s b) {
-    %(type)s r = a %% b;
-    r += ((r != 0) & ((r ^ b) < 0)) * b;
-    return r;
-}
-""")
-
-mod_float_utility_code = UtilityCode(
-proto="""
-static CYTHON_INLINE %(type)s __Pyx_mod_%(type_name)s(%(type)s, %(type)s); /* proto */
-""",
-impl="""
-static CYTHON_INLINE %(type)s __Pyx_mod_%(type_name)s(%(type)s a, %(type)s b) {
-    %(type)s r = fmod%(math_h_modifier)s(a, b);
-    r += ((r != 0) & ((r < 0) ^ (b < 0))) * b;
-    return r;
-}
-""")
-
-cdivision_warning_utility_code = UtilityCode(
-proto="""
-static int __Pyx_cdivision_warning(const char *, int); /* proto */
-""",
-impl="""
-static int __Pyx_cdivision_warning(const char *filename, int lineno) {
-#if CYTHON_COMPILING_IN_PYPY
-    filename++; // avoid compiler warnings
-    lineno++;
-    return PyErr_Warn(PyExc_RuntimeWarning,
-                     "division with oppositely signed operands, C and Python semantics differ");
-#else
-    return PyErr_WarnExplicit(PyExc_RuntimeWarning,
-                              "division with oppositely signed operands, C and Python semantics differ",
-                              filename,
-                              lineno,
-                              __Pyx_MODULE_NAME,
-                              NULL);
-#endif
-}
-""")
-
-# from intobject.c
-division_overflow_test_code = UtilityCode(
-proto="""
-#define UNARY_NEG_WOULD_OVERFLOW(x)    \
-        (((x) < 0) & ((unsigned long)(x) == 0-(unsigned long)(x)))
-""")
diff --git a/Cython/Compiler/Main.py b/Cython/Compiler/Main.py
index c9c30c5094814044e1b7be61ced11e78fd57263b..20526a84bb5eee7e7382497e5fc59f8976961d56 100644
--- a/Cython/Compiler/Main.py
+++ b/Cython/Compiler/Main.py
@@ -19,6 +19,7 @@ from . import Errors
 # conditional metaclass. These options are processed by CmdLine called from
 # main() in this file.
 # import Parsing
+from .StringEncoding import EncodedString
 from .Scanning import PyrexScanner, FileSourceDescriptor
 from .Errors import PyrexError, CompileError, error, warning
 from .Symtab import ModuleScope
@@ -76,7 +77,8 @@ class Context(object):
         self.cpp = cpp
         self.options = options
 
-        self.pxds = {} # full name -> node tree
+        self.pxds = {}  # full name -> node tree
+        self._interned = {}  # (type(value), value, *key_args) -> interned_value
 
         standard_include_path = os.path.abspath(os.path.normpath(
             os.path.join(os.path.dirname(__file__), os.path.pardir, 'Includes')))
@@ -93,6 +95,27 @@ class Context(object):
             self.future_directives.update([print_function, unicode_literals, absolute_import, division])
             self.modules['builtins'] = self.modules['__builtin__']
 
+    def intern_ustring(self, value, encoding=None):
+        key = (EncodedString, value, encoding)
+        try:
+            return self._interned[key]
+        except KeyError:
+            pass
+        value = EncodedString(value)
+        if encoding:
+            value.encoding = encoding
+        self._interned[key] = value
+        return value
+
+    def intern_value(self, value, *key):
+        key = (type(value), value) + key
+        try:
+            return self._interned[key]
+        except KeyError:
+            pass
+        self._interned[key] = value
+        return value
+
     # pipeline creation functions can now be found in Pipeline.py
 
     def process_pxd(self, source_desc, scope, module_name):
@@ -110,7 +133,8 @@ class Context(object):
     def nonfatal_error(self, exc):
         return Errors.report_error(exc)
 
-    def find_module(self, module_name, relative_to=None, pos=None, need_pxd=1, check_module_name=True):
+    def find_module(self, module_name, relative_to=None, pos=None, need_pxd=1,
+                    absolute_fallback=True):
         # Finds and returns the module scope corresponding to
         # the given relative or absolute module name. If this
         # is the first time the module has been requested, finds
@@ -125,25 +149,39 @@ class Context(object):
 
         scope = None
         pxd_pathname = None
-        if check_module_name and not module_name_pattern.match(module_name):
-            if pos is None:
-                pos = (module_name, 0, 0)
-            raise CompileError(pos, "'%s' is not a valid module name" % module_name)
+        if relative_to:
+            if module_name:
+                # from .module import ...
+                qualified_name = relative_to.qualify_name(module_name)
+            else:
+                # from . import ...
+                qualified_name = relative_to.qualified_name
+                scope = relative_to
+                relative_to = None
+        else:
+            qualified_name = module_name
+
+        if not module_name_pattern.match(qualified_name):
+            raise CompileError(pos or (module_name, 0, 0),
+                               "'%s' is not a valid module name" % module_name)
+
         if relative_to:
             if debug_find_module:
                 print("...trying relative import")
             scope = relative_to.lookup_submodule(module_name)
             if not scope:
-                qualified_name = relative_to.qualify_name(module_name)
                 pxd_pathname = self.find_pxd_file(qualified_name, pos)
                 if pxd_pathname:
                     scope = relative_to.find_submodule(module_name)
         if not scope:
             if debug_find_module:
                 print("...trying absolute import")
+            if absolute_fallback:
+                qualified_name = module_name
             scope = self
-            for name in module_name.split("."):
+            for name in qualified_name.split("."):
                 scope = scope.find_submodule(name)
+
         if debug_find_module:
             print("...scope = %s" % scope)
         if not scope.pxd_file_loaded:
@@ -153,15 +191,15 @@ class Context(object):
             if not pxd_pathname:
                 if debug_find_module:
                     print("...looking for pxd file")
-                pxd_pathname = self.find_pxd_file(module_name, pos)
+                pxd_pathname = self.find_pxd_file(qualified_name, pos)
                 if debug_find_module:
                     print("......found %s" % pxd_pathname)
                 if not pxd_pathname and need_pxd:
-                    package_pathname = self.search_include_directories(module_name, ".py", pos)
+                    package_pathname = self.search_include_directories(qualified_name, ".py", pos)
                     if package_pathname and package_pathname.endswith('__init__.py'):
                         pass
                     else:
-                        error(pos, "'%s.pxd' not found" % module_name.replace('.', os.sep))
+                        error(pos, "'%s.pxd' not found" % qualified_name.replace('.', os.sep))
             if pxd_pathname:
                 try:
                     if debug_find_module:
@@ -170,7 +208,7 @@ class Context(object):
                     if not pxd_pathname.endswith(rel_path):
                         rel_path = pxd_pathname  # safety measure to prevent printing incorrect paths
                     source_desc = FileSourceDescriptor(pxd_pathname, rel_path)
-                    err, result = self.process_pxd(source_desc, scope, module_name)
+                    err, result = self.process_pxd(source_desc, scope, qualified_name)
                     if err:
                         raise err
                     (pxd_codenodes, pxd_scope) = result
diff --git a/Cython/Compiler/ModuleNode.py b/Cython/Compiler/ModuleNode.py
index 7a06009da6767ee4ad9d378910d7b12f67df3198..28ec86e7885ac1c2a3b83c035670a69cb459a6b0 100644
--- a/Cython/Compiler/ModuleNode.py
+++ b/Cython/Compiler/ModuleNode.py
@@ -571,26 +571,6 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
             code.putln("")
         code.putln("#define PY_SSIZE_T_CLEAN")
 
-        # sizeof(PyLongObject.ob_digit[0]) may have been determined dynamically
-        # at compile time in CPython, in which case we can't know the correct
-        # storage size for an installed system.  We can rely on it only if
-        # pyconfig.h defines it statically, i.e. if it was set by "configure".
-        # Once we include "Python.h", it will come up with its own idea about
-        # a suitable value, which may or may not match the real one.
-        code.putln("#ifndef CYTHON_USE_PYLONG_INTERNALS")
-        code.putln("#ifdef PYLONG_BITS_IN_DIGIT")
-        # assume it's an incorrect left-over
-        code.putln("#define CYTHON_USE_PYLONG_INTERNALS 0")
-        code.putln("#else")
-        code.putln('#include "pyconfig.h"')
-        code.putln("#ifdef PYLONG_BITS_IN_DIGIT")
-        code.putln("#define CYTHON_USE_PYLONG_INTERNALS 1")
-        code.putln("#else")
-        code.putln("#define CYTHON_USE_PYLONG_INTERNALS 0")
-        code.putln("#endif")
-        code.putln("#endif")
-        code.putln("#endif")
-
         for filename in env.python_include_files:
             code.putln('#include "%s"' % filename)
         code.putln("#ifndef Py_PYTHON_H")
@@ -1982,7 +1962,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
                 "};")
 
     def generate_import_star(self, env, code):
-        env.use_utility_code(streq_utility_code)
+        env.use_utility_code(UtilityCode.load_cached("CStringEquals", "StringTools.c"))
         code.putln()
         code.enter_cfunc_scope()  # as we need labels
         code.putln("static int %s(PyObject *o, PyObject* py_name, char *name) {" % Naming.import_star_set)
@@ -2044,8 +2024,9 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
         code.putln("bad:")
         code.putln("return -1;")
         code.putln("}")
-        code.putln(import_star_utility_code)
-        code.exit_cfunc_scope() # done with labels
+        code.putln("")
+        code.putln(UtilityCode.load_cached("ImportStar", "ImportExport.c").impl)
+        code.exit_cfunc_scope()  # done with labels
 
     def generate_module_init_func(self, imported_modules, env, code):
         code.enter_cfunc_scope()
@@ -2170,6 +2151,10 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
         code.putln("/*--- Execution code ---*/")
         code.mark_pos(None)
 
+        code.putln("#ifdef __Pyx_Generator_USED")
+        code.put_error_if_neg(self.pos, "__Pyx_patch_abc()")
+        code.putln("#endif")
+
         if profile or linetrace:
             code.put_trace_call(header3, self.pos, nogil=not code.funcstate.gil_owned)
             code.funcstate.can_trace = True
@@ -2358,12 +2343,13 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
             wmain = "wmain"
         else:
             wmain = Options.embed
+        main_method = UtilityCode.load_cached("MainFunction", "Embed.c")
         code.globalstate.use_utility_code(
             main_method.specialize(
-                module_name = env.module_name,
-                module_is_main = module_is_main,
-                main_method = Options.embed,
-                wmain_method = wmain))
+                module_name=env.module_name,
+                module_is_main=module_is_main,
+                main_method=Options.embed,
+                wmain_method=wmain))
 
     def generate_pymoduledef_struct(self, env, code):
         if env.doc:
@@ -2829,140 +2815,7 @@ def generate_cfunction_declaration(entry, env, code, definition):
 #
 #------------------------------------------------------------------------------------
 
-streq_utility_code = UtilityCode(
-proto = """
-static CYTHON_INLINE int __Pyx_StrEq(const char *, const char *); /*proto*/
-""",
-impl = """
-static CYTHON_INLINE int __Pyx_StrEq(const char *s1, const char *s2) {
-     while (*s1 != '\\0' && *s1 == *s2) { s1++; s2++; }
-     return *s1 == *s2;
-}
-""")
-
-#------------------------------------------------------------------------------------
-
-import_star_utility_code = """
-
-/* import_all_from is an unexposed function from ceval.c */
-
-static int
-__Pyx_import_all_from(PyObject *locals, PyObject *v)
-{
-    PyObject *all = PyObject_GetAttrString(v, "__all__");
-    PyObject *dict, *name, *value;
-    int skip_leading_underscores = 0;
-    int pos, err;
-
-    if (all == NULL) {
-        if (!PyErr_ExceptionMatches(PyExc_AttributeError))
-            return -1; /* Unexpected error */
-        PyErr_Clear();
-        dict = PyObject_GetAttrString(v, "__dict__");
-        if (dict == NULL) {
-            if (!PyErr_ExceptionMatches(PyExc_AttributeError))
-                return -1;
-            PyErr_SetString(PyExc_ImportError,
-            "from-import-* object has no __dict__ and no __all__");
-            return -1;
-        }
-#if PY_MAJOR_VERSION < 3
-        all = PyObject_CallMethod(dict, (char *)"keys", NULL);
-#else
-        all = PyMapping_Keys(dict);
-#endif
-        Py_DECREF(dict);
-        if (all == NULL)
-            return -1;
-        skip_leading_underscores = 1;
-    }
-
-    for (pos = 0, err = 0; ; pos++) {
-        name = PySequence_GetItem(all, pos);
-        if (name == NULL) {
-            if (!PyErr_ExceptionMatches(PyExc_IndexError))
-                err = -1;
-            else
-                PyErr_Clear();
-            break;
-        }
-        if (skip_leading_underscores &&
-#if PY_MAJOR_VERSION < 3
-            PyString_Check(name) &&
-            PyString_AS_STRING(name)[0] == '_')
-#else
-            PyUnicode_Check(name) &&
-            PyUnicode_AS_UNICODE(name)[0] == '_')
-#endif
-        {
-            Py_DECREF(name);
-            continue;
-        }
-        value = PyObject_GetAttr(v, name);
-        if (value == NULL)
-            err = -1;
-        else if (PyDict_CheckExact(locals))
-            err = PyDict_SetItem(locals, name, value);
-        else
-            err = PyObject_SetItem(locals, name, value);
-        Py_DECREF(name);
-        Py_XDECREF(value);
-        if (err != 0)
-            break;
-    }
-    Py_DECREF(all);
-    return err;
-}
-
-
-static int %(IMPORT_STAR)s(PyObject* m) {
-
-    int i;
-    int ret = -1;
-    char* s;
-    PyObject *locals = 0;
-    PyObject *list = 0;
-#if PY_MAJOR_VERSION >= 3
-    PyObject *utf8_name = 0;
-#endif
-    PyObject *name;
-    PyObject *item;
-
-    locals = PyDict_New();              if (!locals) goto bad;
-    if (__Pyx_import_all_from(locals, m) < 0) goto bad;
-    list = PyDict_Items(locals);        if (!list) goto bad;
-
-    for(i=0; i<PyList_GET_SIZE(list); i++) {
-        name = PyTuple_GET_ITEM(PyList_GET_ITEM(list, i), 0);
-        item = PyTuple_GET_ITEM(PyList_GET_ITEM(list, i), 1);
-#if PY_MAJOR_VERSION >= 3
-        utf8_name = PyUnicode_AsUTF8String(name);
-        if (!utf8_name) goto bad;
-        s = PyBytes_AS_STRING(utf8_name);
-        if (%(IMPORT_STAR_SET)s(item, name, s) < 0) goto bad;
-        Py_DECREF(utf8_name); utf8_name = 0;
-#else
-        s = PyString_AsString(name);
-        if (!s) goto bad;
-        if (%(IMPORT_STAR_SET)s(item, name, s) < 0) goto bad;
-#endif
-    }
-    ret = 0;
-
-bad:
-    Py_XDECREF(locals);
-    Py_XDECREF(list);
-#if PY_MAJOR_VERSION >= 3
-    Py_XDECREF(utf8_name);
-#endif
-    return ret;
-}
-""" % {'IMPORT_STAR'     : Naming.import_star,
-       'IMPORT_STAR_SET' : Naming.import_star_set }
-
-refnanny_utility_code = UtilityCode.load_cached("Refnanny", "ModuleSetupCode.c")
-
-main_method = UtilityCode.load("MainFunction", "Embed.c")
+refnanny_utility_code = UtilityCode.load("Refnanny", "ModuleSetupCode.c")
 
 packed_struct_utility_code = UtilityCode(proto="""
 #if defined(__GNUC__)
diff --git a/Cython/Compiler/Naming.py b/Cython/Compiler/Naming.py
index 6539b3471ab69230e72746c01f8d42e2b3990beb..6a40ae123455accdd6a1afffb65bdbcb76f04e9d 100644
--- a/Cython/Compiler/Naming.py
+++ b/Cython/Compiler/Naming.py
@@ -61,6 +61,7 @@ interned_prefixes = {
     'codeobj': pyrex_prefix + "codeobj_",
     'slice': pyrex_prefix + "slice_",
     'ustring': pyrex_prefix + "ustring_",
+    'umethod': pyrex_prefix + "umethod_",
 }
 
 ctuple_type_prefix = pyrex_prefix + "ctuple_"
diff --git a/Cython/Compiler/Nodes.py b/Cython/Compiler/Nodes.py
index af985683d3f2bb0ddc5cf97f715d170bd4cbefd3..13134036979739ae80b843a0c5f981016d8d44a1 100644
--- a/Cython/Compiler/Nodes.py
+++ b/Cython/Compiler/Nodes.py
@@ -1180,10 +1180,9 @@ class CTupleBaseTypeNode(CBaseTypeNode):
                 error(c.pos, "Tuple types can't (yet) contain Python objects.")
                 return error_type
             component_types.append(type)
-        type = PyrexTypes.c_tuple_type(component_types)
-        entry = env.declare_tuple_type(self.pos, type)
+        entry = env.declare_tuple_type(self.pos, component_types)
         entry.used = True
-        return type
+        return entry.type
 
 
 class FusedTypeNode(CBaseTypeNode):
@@ -1829,7 +1828,17 @@ class FuncDefNode(StatNode, BlockNode):
                     code.put_release_ensured_gil()
 
             # FIXME: what if the error return value is a Python value?
-            code.putln("return %s;" % self.error_value())
+            err_val = self.error_value()
+            if err_val is None:
+                if not self.caller_will_check_exceptions():
+                    warning(self.entry.pos,
+                            "Unraisable exception in function '%s'." %
+                            self.entry.qualified_name, 0)
+                    code.put_unraisable(self.entry.qualified_name, lenv.nogil)
+                #if self.return_type.is_void:
+                code.putln("return;")
+            else:
+                code.putln("return %s;" % err_val)
             code.putln("}")
             code.put_gotref(Naming.cur_scope_cname)
             # Note that it is unsafe to decref the scope at this point.
@@ -1863,20 +1872,21 @@ class FuncDefNode(StatNode, BlockNode):
         is_cdef = isinstance(self, CFuncDefNode)
         for entry in lenv.arg_entries:
             if entry.type.is_pyobject:
-                if ((acquire_gil or len(entry.cf_assignments) > 1) and
-                    not entry.in_closure):
+                if (acquire_gil or len(entry.cf_assignments) > 1) and not entry.in_closure:
                     code.put_var_incref(entry)
 
             # Note: defaults are always incref-ed. For def functions, we
             #       we aquire arguments from object converstion, so we have
             #       new references. If we are a cdef function, we need to
             #       incref our arguments
-            elif (is_cdef and entry.type.is_memoryviewslice and
-                  len(entry.cf_assignments) > 1):
+            elif is_cdef and entry.type.is_memoryviewslice and len(entry.cf_assignments) > 1:
                 code.put_incref_memoryviewslice(entry.cname, have_gil=code.funcstate.gil_owned)
         for entry in lenv.var_entries:
             if entry.is_arg and len(entry.cf_assignments) > 1:
-                code.put_var_incref(entry)
+                if entry.xdecref_cleanup:
+                    code.put_var_xincref(entry)
+                else:
+                    code.put_var_incref(entry)
 
         # ----- Initialise local buffer auxiliary variables
         for entry in lenv.var_entries + lenv.arg_entries:
@@ -2017,7 +2027,10 @@ class FuncDefNode(StatNode, BlockNode):
                                                  have_gil=not lenv.nogil)
             elif entry.type.is_pyobject:
                 if not entry.is_arg or len(entry.cf_assignments) > 1:
-                    code.put_var_decref(entry)
+                    if entry.xdecref_cleanup:
+                        code.put_var_xdecref(entry)
+                    else:
+                        code.put_var_decref(entry)
 
         # Decref any increfed args
         for entry in lenv.arg_entries:
@@ -3131,6 +3144,15 @@ class DefNodeWrapper(FuncDefNode):
                 if not arg.hdr_type.create_to_py_utility_code(env):
                     pass # will fail later
 
+        if self.starstar_arg and not self.starstar_arg.entry.cf_used:
+            # we will set the kwargs argument to NULL instead of a new dict
+            # and must therefore correct the control flow state
+            entry = self.starstar_arg.entry
+            entry.xdecref_cleanup = 1
+            for ass in entry.cf_assignments:
+                if not ass.is_arg and ass.lhs.is_name:
+                    ass.lhs.cf_maybe_null = True
+
     def signature_has_nongeneric_args(self):
         argcount = len(self.args)
         if argcount == 0 or (
@@ -3380,7 +3402,7 @@ class DefNodeWrapper(FuncDefNode):
             code.putln("}")
 
         if self.starstar_arg:
-            if self.star_arg:
+            if self.star_arg or not self.starstar_arg.entry.cf_used:
                 kwarg_check = "unlikely(%s)" % Naming.kwds_cname
             else:
                 kwarg_check = "%s" % Naming.kwds_cname
@@ -3394,15 +3416,28 @@ class DefNodeWrapper(FuncDefNode):
                 kwarg_check, Naming.kwds_cname, self.name,
                 bool(self.starstar_arg), self.error_value()))
 
-        if self.starstar_arg:
-            code.putln("%s = (%s) ? PyDict_Copy(%s) : PyDict_New();" % (
-                    self.starstar_arg.entry.cname,
-                    Naming.kwds_cname,
-                    Naming.kwds_cname))
-            code.putln("if (unlikely(!%s)) return %s;" % (
-                    self.starstar_arg.entry.cname, self.error_value()))
-            self.starstar_arg.entry.xdecref_cleanup = 0
-            code.put_gotref(self.starstar_arg.entry.cname)
+        if self.starstar_arg and self.starstar_arg.entry.cf_used:
+            if all(ref.node.allow_null for ref in self.starstar_arg.entry.cf_references):
+                code.putln("if (%s) {" % kwarg_check)
+                code.putln("%s = PyDict_Copy(%s); if (unlikely(!%s)) return %s;" % (
+                        self.starstar_arg.entry.cname,
+                        Naming.kwds_cname,
+                        self.starstar_arg.entry.cname,
+                        self.error_value()))
+                code.put_gotref(self.starstar_arg.entry.cname)
+                code.putln("} else {")
+                code.putln("%s = NULL;" % (self.starstar_arg.entry.cname,))
+                code.putln("}")
+                self.starstar_arg.entry.xdecref_cleanup = 1
+            else:
+                code.put("%s = (%s) ? PyDict_Copy(%s) : PyDict_New(); " % (
+                        self.starstar_arg.entry.cname,
+                        Naming.kwds_cname,
+                        Naming.kwds_cname))
+                code.putln("if (unlikely(!%s)) return %s;" % (
+                        self.starstar_arg.entry.cname, self.error_value()))
+                self.starstar_arg.entry.xdecref_cleanup = 0
+                code.put_gotref(self.starstar_arg.entry.cname)
 
         if self.self_in_stararg and not self.target.is_staticmethod:
             # need to create a new tuple with 'self' inserted as first item
@@ -3410,9 +3445,9 @@ class DefNodeWrapper(FuncDefNode):
                     self.star_arg.entry.cname,
                     Naming.args_cname,
                     self.star_arg.entry.cname))
-            if self.starstar_arg:
+            if self.starstar_arg and self.starstar_arg.entry.cf_used:
                 code.putln("{")
-                code.put_decref_clear(self.starstar_arg.entry.cname, py_object_type)
+                code.put_xdecref_clear(self.starstar_arg.entry.cname, py_object_type)
                 code.putln("return %s;" % self.error_value())
                 code.putln("}")
             else:
@@ -4132,9 +4167,11 @@ class OverrideCheckNode(StatNode):
         code.funcstate.release_temp(func_node_temp)
         code.putln("}")
 
+
 class ClassDefNode(StatNode, BlockNode):
     pass
 
+
 class PyClassDefNode(ClassDefNode):
     #  A Python class definition.
     #
@@ -4160,7 +4197,7 @@ class PyClassDefNode(ClassDefNode):
     mkw = None
 
     def __init__(self, pos, name, bases, doc, body, decorators=None,
-                 keyword_args=None, starstar_arg=None, force_py3_semantics=False):
+                 keyword_args=None, force_py3_semantics=False):
         StatNode.__init__(self, pos)
         self.name = name
         self.doc = doc
@@ -4175,31 +4212,30 @@ class PyClassDefNode(ClassDefNode):
             doc_node = None
 
         allow_py2_metaclass = not force_py3_semantics
-        if keyword_args or starstar_arg:
+        if keyword_args:
             allow_py2_metaclass = False
             self.is_py3_style_class = True
-            if keyword_args and not starstar_arg:
-                for i, item in list(enumerate(keyword_args.key_value_pairs))[::-1]:
-                    if item.key.value == 'metaclass':
-                        if self.metaclass is not None:
-                            error(item.pos, "keyword argument 'metaclass' passed multiple times")
-                        # special case: we already know the metaclass,
-                        # so we don't need to do the "build kwargs,
-                        # find metaclass" dance at runtime
-                        self.metaclass = item.value
-                        del keyword_args.key_value_pairs[i]
-            if starstar_arg:
-                self.mkw = ExprNodes.KeywordArgsNode(
-                    pos, keyword_args=keyword_args and keyword_args.key_value_pairs or [],
-                    starstar_arg=starstar_arg)
-            elif keyword_args.key_value_pairs:
-                self.mkw = keyword_args
+            if keyword_args.is_dict_literal:
+                if keyword_args.key_value_pairs:
+                    for i, item in list(enumerate(keyword_args.key_value_pairs))[::-1]:
+                        if item.key.value == 'metaclass':
+                            if self.metaclass is not None:
+                                error(item.pos, "keyword argument 'metaclass' passed multiple times")
+                            # special case: we already know the metaclass,
+                            # so we don't need to do the "build kwargs,
+                            # find metaclass" dance at runtime
+                            self.metaclass = item.value
+                            del keyword_args.key_value_pairs[i]
+                    self.mkw = keyword_args
+                else:
+                    assert self.metaclass is not None
             else:
-                assert self.metaclass is not None
+                # MergedDictNode
+                self.mkw = ExprNodes.ProxyNode(keyword_args)
 
         if force_py3_semantics or self.bases or self.mkw or self.metaclass:
             if self.metaclass is None:
-                if starstar_arg:
+                if keyword_args and not keyword_args.is_dict_literal:
                     # **kwargs may contain 'metaclass' arg
                     mkdict = self.mkw
                 else:
@@ -5475,10 +5511,11 @@ class ReturnStatNode(StatNode):
                         have_gil=self.in_nogil_context)
             elif self.in_generator:
                 # return value == raise StopIteration(value), but uncatchable
-                code.putln(
-                    "%s = NULL; PyErr_SetObject(PyExc_StopIteration, %s);" % (
-                        Naming.retval_cname,
-                        self.value.result_as(self.return_type)))
+                code.globalstate.use_utility_code(
+                    UtilityCode.load_cached("ReturnWithStopIteration", "Generator.c"))
+                code.putln("%s = NULL; __Pyx_ReturnWithStopIteration(%s);" % (
+                    Naming.retval_cname,
+                    self.value.py_result()))
                 self.value.generate_disposal_code(code)
             else:
                 self.value.make_owned_reference(code)
@@ -5490,7 +5527,10 @@ class ReturnStatNode(StatNode):
             self.value.free_temps(code)
         else:
             if self.return_type.is_pyobject:
-                code.put_init_to_py_none(Naming.retval_cname, self.return_type)
+                if self.in_generator:
+                    code.putln("%s = NULL;" % Naming.retval_cname)
+                else:
+                    code.put_init_to_py_none(Naming.retval_cname, self.return_type)
             elif self.return_type.is_returncode:
                 self.put_return(code, self.return_type.default_value)
 
@@ -6556,7 +6596,7 @@ class TryExceptStatNode(StatNode):
         else:
             # try block cannot raise exceptions, but we had to allocate the temps above,
             # so just keep the C compiler from complaining about them being unused
-            save_exc.putln("if (%s); else {/*mark used*/};" % '||'.join(exc_save_vars))
+            save_exc.putln("if (%s); else {/*mark used*/}" % '||'.join(exc_save_vars))
 
             def restore_saved_exception():
                 pass
@@ -7162,6 +7202,14 @@ utility_code_for_cimports = {
 }
 
 
+utility_code_for_imports = {
+    # utility code used when special modules are imported.
+    # TODO: Consider a generic user-level mechanism for importing
+    'asyncio': ("__Pyx_patch_asyncio", "PatchAsyncIO", "Generator.c"),
+    'inspect': ("__Pyx_patch_inspect", "PatchInspect", "Generator.c"),
+}
+
+
 class CImportStatNode(StatNode):
     #  cimport statement
     #
@@ -7224,6 +7272,7 @@ class FromCImportStatNode(StatNode):
             return
         if self.relative_level and self.relative_level > env.qualified_name.count('.'):
             error(self.pos, "relative cimport beyond main package is not allowed")
+            return
         module_scope = env.find_module(self.module_name, self.pos, relative_level=self.relative_level)
         module_name = module_scope.qualified_name
         env.add_imported_module(module_scope)
@@ -7244,7 +7293,8 @@ class FromCImportStatNode(StatNode):
                     elif kind == 'class':
                         entry = module_scope.declare_c_class(name, pos=pos, module_name=module_name)
                     else:
-                        submodule_scope = env.context.find_module(name, relative_to=module_scope, pos=self.pos)
+                        submodule_scope = env.context.find_module(
+                            name, relative_to=module_scope, pos=self.pos, absolute_fallback=False)
                         if submodule_scope.parent_module is module_scope:
                             env.declare_module(as_name or name, submodule_scope, self.pos)
                         else:
diff --git a/Cython/Compiler/Optimize.py b/Cython/Compiler/Optimize.py
index 260e435d245e9391a0726bad0e6936312fc1f146..297fc510841256325c7319471d23999d63fb0c0a 100644
--- a/Cython/Compiler/Optimize.py
+++ b/Cython/Compiler/Optimize.py
@@ -1422,6 +1422,31 @@ class EarlyReplaceBuiltinCalls(Visitor.EnvTransform):
             stop=stop,
             step=step or ExprNodes.NoneNode(node.pos))
 
+    def _handle_simple_function_ord(self, node, pos_args):
+        """Unpack ord('X').
+        """
+        if len(pos_args) != 1:
+            return node
+        arg = pos_args[0]
+        if isinstance(arg, (ExprNodes.UnicodeNode, ExprNodes.BytesNode)):
+            if len(arg.value) == 1:
+                return ExprNodes.IntNode(
+                    arg.pos, type=PyrexTypes.c_long_type,
+                    value=str(ord(arg.value)),
+                    constant_result=ord(arg.value)
+                )
+        elif isinstance(arg, ExprNodes.StringNode):
+            if arg.unicode_value and len(arg.unicode_value) == 1 \
+                    and ord(arg.unicode_value) <= 255:  # Py2/3 portability
+                return ExprNodes.IntNode(
+                    arg.pos, type=PyrexTypes.c_int_type,
+                    value=str(ord(arg.unicode_value)),
+                    constant_result=ord(arg.unicode_value)
+                )
+        return node
+
+    # sequence processing
+
     class YieldNodeCollector(Visitor.TreeVisitor):
         def __init__(self):
             Visitor.TreeVisitor.__init__(self)
@@ -1632,7 +1657,7 @@ class EarlyReplaceBuiltinCalls(Visitor.EnvTransform):
             yield_expression, yield_stat_node = self._find_single_yield_expression(loop_node)
             if yield_expression is None:
                 return node
-        else: # ComprehensionNode
+        else:  # ComprehensionNode
             yield_stat_node = gen_expr_node.append
             yield_expression = yield_stat_node.expr
             try:
@@ -1712,6 +1737,8 @@ class EarlyReplaceBuiltinCalls(Visitor.EnvTransform):
 
         return last_result
 
+    # builtin type creation
+
     def _DISABLED_handle_simple_function_tuple(self, node, pos_args):
         if not pos_args:
             return ExprNodes.TupleNode(node.pos, args=[], constant_result=())
@@ -2297,14 +2324,14 @@ class OptimizeBuiltinCalls(Visitor.NodeRefCleanupMixin,
         exception_value="-1")
 
     _map_to_capi_len_function = {
-        Builtin.unicode_type   : "__Pyx_PyUnicode_GET_LENGTH",
-        Builtin.bytes_type     : "PyBytes_GET_SIZE",
-        Builtin.list_type      : "PyList_GET_SIZE",
-        Builtin.tuple_type     : "PyTuple_GET_SIZE",
-        Builtin.dict_type      : "PyDict_Size",
-        Builtin.set_type       : "PySet_Size",
-        Builtin.frozenset_type : "__Pyx_PyFrozenSet_Size",
-        }.get
+        Builtin.unicode_type:    "__Pyx_PyUnicode_GET_LENGTH",
+        Builtin.bytes_type:      "PyBytes_GET_SIZE",
+        Builtin.list_type:       "PyList_GET_SIZE",
+        Builtin.tuple_type:      "PyTuple_GET_SIZE",
+        Builtin.set_type:        "PySet_GET_SIZE",
+        Builtin.frozenset_type:  "PySet_GET_SIZE",
+        Builtin.dict_type:       "PyDict_Size",
+    }.get
 
     _ext_types_with_pysize = set(["cpython.array.array"])
 
@@ -2452,7 +2479,7 @@ class OptimizeBuiltinCalls(Visitor.NodeRefCleanupMixin,
         if isinstance(arg, ExprNodes.CoerceToPyTypeNode):
             if arg.arg.type.is_unicode_char:
                 return ExprNodes.TypecastNode(
-                    arg.pos, operand=arg.arg, type=PyrexTypes.c_int_type
+                    arg.pos, operand=arg.arg, type=PyrexTypes.c_long_type
                     ).coerce_to(node.type, self.current_env())
         elif isinstance(arg, ExprNodes.UnicodeNode):
             if len(arg.value) == 1:
@@ -2640,7 +2667,8 @@ class OptimizeBuiltinCalls(Visitor.NodeRefCleanupMixin,
     PyObject_PopIndex_func_type = PyrexTypes.CFuncType(
         PyrexTypes.py_object_type, [
             PyrexTypes.CFuncTypeArg("list", PyrexTypes.py_object_type, None),
-            PyrexTypes.CFuncTypeArg("index", PyrexTypes.c_py_ssize_t_type, None),
+            PyrexTypes.CFuncTypeArg("py_index", PyrexTypes.py_object_type, None),
+            PyrexTypes.CFuncTypeArg("c_index", PyrexTypes.c_py_ssize_t_type, None),
             PyrexTypes.CFuncTypeArg("is_signed", PyrexTypes.c_int_type, None),
         ],
         has_varargs=True)  # to fake the additional macro args that lack a proper C type
@@ -2675,14 +2703,23 @@ class OptimizeBuiltinCalls(Visitor.NodeRefCleanupMixin,
             )
         elif len(args) == 2:
             index = unwrap_coerced_node(args[1])
+            py_index = ExprNodes.NoneNode(index.pos)
             orig_index_type = index.type
             if not index.type.is_int:
-                if is_list or isinstance(index, ExprNodes.IntNode):
+                if isinstance(index, ExprNodes.IntNode):
+                    py_index = index.coerce_to_pyobject(self.current_env())
+                    index = index.coerce_to(PyrexTypes.c_py_ssize_t_type, self.current_env())
+                elif is_list:
+                    if index.type.is_pyobject:
+                        py_index = index.coerce_to_simple(self.current_env())
+                        index = ExprNodes.CloneNode(py_index)
                     index = index.coerce_to(PyrexTypes.c_py_ssize_t_type, self.current_env())
                 else:
                     return node
             elif not PyrexTypes.numeric_type_fits(index.type, PyrexTypes.c_py_ssize_t_type):
                 return node
+            elif isinstance(index, ExprNodes.IntNode):
+                py_index = index.coerce_to_pyobject(self.current_env())
             # real type might still be larger at runtime
             if not orig_index_type.is_int:
                 orig_index_type = index.type
@@ -2694,7 +2731,7 @@ class OptimizeBuiltinCalls(Visitor.NodeRefCleanupMixin,
             return ExprNodes.PythonCapiCallNode(
                 node.pos, "__Pyx_Py%s_PopIndex" % type_name,
                 self.PyObject_PopIndex_func_type,
-                args=[obj, index,
+                args=[obj, py_index, index,
                       ExprNodes.IntNode(index.pos, value=str(orig_index_type.signed and 1 or 0),
                                         constant_result=orig_index_type.signed and 1 or 0,
                                         type=PyrexTypes.c_int_type),
@@ -2802,38 +2839,110 @@ class OptimizeBuiltinCalls(Visitor.NodeRefCleanupMixin,
     def _handle_simple_method_object___sub__(self, node, function, args, is_unbound_method):
         return self._optimise_num_binop('Subtract', node, function, args, is_unbound_method)
 
+    def _handle_simple_method_object___eq__(self, node, function, args, is_unbound_method):
+        return self._optimise_num_binop('Eq', node, function, args, is_unbound_method)
+
+    def _handle_simple_method_object___neq__(self, node, function, args, is_unbound_method):
+        return self._optimise_num_binop('Ne', node, function, args, is_unbound_method)
+
+    def _handle_simple_method_object___and__(self, node, function, args, is_unbound_method):
+        return self._optimise_num_binop('And', node, function, args, is_unbound_method)
+
+    def _handle_simple_method_object___or__(self, node, function, args, is_unbound_method):
+        return self._optimise_num_binop('Or', node, function, args, is_unbound_method)
+
+    def _handle_simple_method_object___xor__(self, node, function, args, is_unbound_method):
+        return self._optimise_num_binop('Xor', node, function, args, is_unbound_method)
+
+    def _handle_simple_method_object___rshift__(self, node, function, args, is_unbound_method):
+        if len(args) != 2 or not isinstance(args[1], ExprNodes.IntNode):
+            return node
+        if not args[1].has_constant_result() or not (1 <= args[1].constant_result <= 63):
+            return node
+        return self._optimise_num_binop('Rshift', node, function, args, is_unbound_method)
+
+    def _handle_simple_method_object___mod__(self, node, function, args, is_unbound_method):
+        return self._optimise_num_div('Remainder', node, function, args, is_unbound_method)
+
+    def _handle_simple_method_object___floordiv__(self, node, function, args, is_unbound_method):
+        return self._optimise_num_div('FloorDivide', node, function, args, is_unbound_method)
+
+    def _handle_simple_method_object___truediv__(self, node, function, args, is_unbound_method):
+        return self._optimise_num_div('TrueDivide', node, function, args, is_unbound_method)
+
+    def _handle_simple_method_object___div__(self, node, function, args, is_unbound_method):
+        return self._optimise_num_div('Divide', node, function, args, is_unbound_method)
+
+    def _optimise_num_div(self, operator, node, function, args, is_unbound_method):
+        if len(args) != 2 or not args[1].has_constant_result() or args[1].constant_result == 0:
+            return node
+        if isinstance(args[1], ExprNodes.IntNode):
+            if not (-2**30 <= args[1].constant_result <= 2**30):
+                return node
+        elif isinstance(args[1], ExprNodes.FloatNode):
+            if not (-2**53 <= args[1].constant_result <= 2**53):
+                return node
+        else:
+            return node
+        return self._optimise_num_binop(operator, node, function, args, is_unbound_method)
+
     def _handle_simple_method_float___add__(self, node, function, args, is_unbound_method):
         return self._optimise_num_binop('Add', node, function, args, is_unbound_method)
 
     def _handle_simple_method_float___sub__(self, node, function, args, is_unbound_method):
         return self._optimise_num_binop('Subtract', node, function, args, is_unbound_method)
 
+    def _handle_simple_method_float___truediv__(self, node, function, args, is_unbound_method):
+        return self._optimise_num_binop('TrueDivide', node, function, args, is_unbound_method)
+
+    def _handle_simple_method_float___div__(self, node, function, args, is_unbound_method):
+        return self._optimise_num_binop('Divide', node, function, args, is_unbound_method)
+
+    def _handle_simple_method_float___mod__(self, node, function, args, is_unbound_method):
+        return self._optimise_num_binop('Remainder', node, function, args, is_unbound_method)
+
+    def _handle_simple_method_float___eq__(self, node, function, args, is_unbound_method):
+        return self._optimise_num_binop('Eq', node, function, args, is_unbound_method)
+
+    def _handle_simple_method_float___neq__(self, node, function, args, is_unbound_method):
+        return self._optimise_num_binop('Ne', node, function, args, is_unbound_method)
+
     def _optimise_num_binop(self, operator, node, function, args, is_unbound_method):
         """
-        Optimise '+' / '-' operator for (likely) float or small integer operations.
+        Optimise math operators for (likely) float or small integer operations.
         """
         if len(args) != 2:
             return node
         if not node.type.is_pyobject:
             return node
 
-        # when adding IntNode/FloatNode to something else, assume other operand is also numeric
+        # When adding IntNode/FloatNode to something else, assume other operand is also numeric.
+        # Prefer constants on RHS as they allows better size control for some operators.
         num_nodes = (ExprNodes.IntNode, ExprNodes.FloatNode)
-        if isinstance(args[0], num_nodes):
-            if args[1].type is not PyrexTypes.py_object_type:
-                return node
-            numval = args[0]
-            arg_order = 'CObj'
-        elif isinstance(args[1], num_nodes):
+        if isinstance(args[1], num_nodes):
             if args[0].type is not PyrexTypes.py_object_type:
                 return node
             numval = args[1]
             arg_order = 'ObjC'
+        elif isinstance(args[0], num_nodes):
+            if args[1].type is not PyrexTypes.py_object_type:
+                return node
+            numval = args[0]
+            arg_order = 'CObj'
         else:
             return node
 
+        if not numval.has_constant_result():
+            return node
+
         is_float = isinstance(numval, ExprNodes.FloatNode)
-        if not numval.has_constant_result() or (not is_float and abs(numval.constant_result) > 2**30):
+        if is_float:
+            if operator not in ('Add', 'Subtract', 'Remainder', 'TrueDivide', 'Divide', 'Eq', 'Ne'):
+                return node
+        elif operator == 'Divide':
+            # mixed old-/new-style division is not currently optimised for integers
+            return node
+        elif abs(numval.constant_result) > 2**30:
             return node
 
         args = list(args)
@@ -3724,6 +3833,93 @@ class ConstantFolding(Visitor.VisitorTransform, SkipDeclarations):
                 sequence_node.mult_factor = factor
         return sequence_node
 
+    def visit_MergedDictNode(self, node):
+        """Unpack **args in place if we can."""
+        self.visitchildren(node)
+        args = []
+        items = []
+
+        def add(arg):
+            if arg.is_dict_literal:
+                if items:
+                    items[0].key_value_pairs.extend(arg.key_value_pairs)
+                else:
+                    items.append(arg)
+            elif isinstance(arg, ExprNodes.MergedDictNode):
+                for child_arg in arg.keyword_args:
+                    add(child_arg)
+            else:
+                if items:
+                    args.append(items[0])
+                    del items[:]
+                args.append(arg)
+
+        for arg in node.keyword_args:
+            add(arg)
+        if items:
+            args.append(items[0])
+
+        if len(args) == 1:
+            arg = args[0]
+            if arg.is_dict_literal or isinstance(arg, ExprNodes.MergedDictNode):
+                return arg
+        node.keyword_args[:] = args
+        self._calculate_const(node)
+        return node
+
+    def visit_MergedSequenceNode(self, node):
+        """Unpack *args in place if we can."""
+        self.visitchildren(node)
+
+        is_set = node.type is Builtin.set_type
+        args = []
+        values = []
+
+        def add(arg):
+            if (is_set and arg.is_set_literal) or (arg.is_sequence_constructor and not arg.mult_factor):
+                if values:
+                    values[0].args.extend(arg.args)
+                else:
+                    values.append(arg)
+            elif isinstance(arg, ExprNodes.MergedSequenceNode):
+                for child_arg in arg.args:
+                    add(child_arg)
+            else:
+                if values:
+                    args.append(values[0])
+                    del values[:]
+                args.append(arg)
+
+        for arg in node.args:
+            add(arg)
+        if values:
+            args.append(values[0])
+
+        if len(args) == 1:
+            arg = args[0]
+            if ((is_set and arg.is_set_literal) or
+                    (arg.is_sequence_constructor and arg.type is node.type) or
+                    isinstance(arg, ExprNodes.MergedSequenceNode)):
+                return arg
+        node.args[:] = args
+        self._calculate_const(node)
+        return node
+
+    def visit_SequenceNode(self, node):
+        """Unpack *args in place if we can."""
+        self.visitchildren(node)
+        args = []
+        for arg in node.args:
+            if not arg.is_starred:
+                args.append(arg)
+            elif arg.target.is_sequence_constructor and not arg.target.mult_factor:
+                args.extend(arg.target.args)
+            else:
+                args.append(arg)
+        node.args[:] = args
+        self._calculate_const(node)
+        return node
+
     def visit_PrimaryCmpNode(self, node):
         # calculate constant partial results in the comparison cascade
         self.visitchildren(node, ['operand1'])
diff --git a/Cython/Compiler/Parsing.pxd b/Cython/Compiler/Parsing.pxd
index 8f87f290716409dc5cb8f09c293bb734660a1779..9a96d1acc659198ad1b8006c5950aa4a147ab30d 100644
--- a/Cython/Compiler/Parsing.pxd
+++ b/Cython/Compiler/Parsing.pxd
@@ -48,7 +48,7 @@ cdef p_power(PyrexScanner s)
 cdef p_new_expr(PyrexScanner s)
 cdef p_trailer(PyrexScanner s, node1)
 cdef p_call_parse_args(PyrexScanner s, bint allow_genexp = *)
-cdef p_call_build_packed_args(pos, positional_args, keyword_args, star_arg, starstar_arg)
+cdef p_call_build_packed_args(pos, positional_args, keyword_args)
 cdef p_call(PyrexScanner s, function)
 cdef p_index(PyrexScanner s, base)
 cdef tuple p_subscript_list(PyrexScanner s)
diff --git a/Cython/Compiler/Parsing.py b/Cython/Compiler/Parsing.py
index 962adcbcfe4c3c0206db86e590cb7c61b6177385..06259cd4d53116dd1ce59c6d138f920e0fa529fd 100644
--- a/Cython/Compiler/Parsing.py
+++ b/Cython/Compiler/Parsing.py
@@ -12,10 +12,12 @@ cython.declare(Nodes=object, ExprNodes=object, EncodedString=object,
                FileSourceDescriptor=object, lookup_unicodechar=object,
                Future=object, Options=object, error=object, warning=object,
                Builtin=object, ModuleNode=object, Utils=object,
-               re=object, _unicode=object, _bytes=object)
+               re=object, _unicode=object, _bytes=object,
+               partial=object, reduce=object)
 
 import re
 from unicodedata import lookup as lookup_unicodechar
+from functools import partial, reduce
 
 from .Scanning import PyrexScanner, FileSourceDescriptor
 from . import Nodes
@@ -53,7 +55,7 @@ class Ctx(object):
         d.update(kwds)
         return ctx
 
-def p_ident(s, message = "Expected an identifier"):
+def p_ident(s, message="Expected an identifier"):
     if s.sy == 'IDENT':
         name = s.systring
         s.next()
@@ -208,7 +210,7 @@ def p_starred_expr(s):
         starred = False
     expr = p_bit_expr(s)
     if starred:
-        expr = ExprNodes.StarredTargetNode(pos, expr)
+        expr = ExprNodes.StarredUnpackingNode(pos, expr)
     return expr
 
 def p_cascaded_cmp(s):
@@ -405,28 +407,39 @@ def p_trailer(s, node1):
         return p_index(s, node1)
     else: # s.sy == '.'
         s.next()
-        name = EncodedString( p_ident(s) )
+        name = p_ident(s)
         return ExprNodes.AttributeNode(pos,
-            obj = node1, attribute = name)
+            obj=node1, attribute=name)
+
 
 # arglist:  argument (',' argument)* [',']
 # argument: [test '='] test       # Really [keyword '='] test
 
-def p_call_parse_args(s, allow_genexp = True):
+# since PEP 448:
+# argument: ( test [comp_for] |
+#             test '=' test |
+#             '**' expr |
+#             star_expr )
+
+def p_call_parse_args(s, allow_genexp=True):
     # s.sy == '('
     pos = s.position()
     s.next()
     positional_args = []
     keyword_args = []
-    star_arg = None
-    starstar_arg = None
-    while s.sy not in ('**', ')'):
+    starstar_seen = False
+    last_was_tuple_unpack = False
+    while s.sy != ')':
         if s.sy == '*':
-            if star_arg:
-                s.error("only one star-arg parameter allowed",
-                        pos=s.position())
+            if starstar_seen:
+                s.error("Non-keyword arg following keyword arg", pos=s.position())
+            s.next()
+            positional_args.append(p_test(s))
+            last_was_tuple_unpack = True
+        elif s.sy == '**':
             s.next()
-            star_arg = p_test(s)
+            keyword_args.append(p_test(s))
+            starstar_seen = True
         else:
             arg = p_test(s)
             if s.sy == '=':
@@ -434,80 +447,85 @@ def p_call_parse_args(s, allow_genexp = True):
                 if not arg.is_name:
                     s.error("Expected an identifier before '='",
                             pos=arg.pos)
-                encoded_name = EncodedString(arg.name)
+                encoded_name = s.context.intern_ustring(arg.name)
                 keyword = ExprNodes.IdentifierStringNode(
                     arg.pos, value=encoded_name)
                 arg = p_test(s)
                 keyword_args.append((keyword, arg))
             else:
                 if keyword_args:
-                    s.error("Non-keyword arg following keyword arg",
-                            pos=arg.pos)
-                if star_arg:
-                    s.error("Non-keyword arg following star-arg",
-                            pos=arg.pos)
-                positional_args.append(arg)
+                    s.error("Non-keyword arg following keyword arg", pos=arg.pos)
+                if positional_args and not last_was_tuple_unpack:
+                    positional_args[-1].append(arg)
+                else:
+                    positional_args.append([arg])
+                last_was_tuple_unpack = False
         if s.sy != ',':
             break
         s.next()
 
     if s.sy == 'for':
-        if len(positional_args) == 1 and not star_arg:
-            positional_args = [ p_genexp(s, positional_args[0]) ]
-    elif s.sy == '**':
-        s.next()
-        starstar_arg = p_test(s)
-        if s.sy == ',':
-            s.next()  # FIXME: this is actually not valid Python syntax
+        if not keyword_args and not last_was_tuple_unpack:
+            if len(positional_args) == 1 and len(positional_args[0]) == 1:
+                positional_args = [[p_genexp(s, positional_args[0][0])]]
     s.expect(')')
-    return positional_args, keyword_args, star_arg, starstar_arg
+    return positional_args or [[]], keyword_args
 
-def p_call_build_packed_args(pos, positional_args, keyword_args,
-                             star_arg, starstar_arg):
-    arg_tuple = None
+
+def p_call_build_packed_args(pos, positional_args, keyword_args):
     keyword_dict = None
-    if positional_args or not star_arg:
-        arg_tuple = ExprNodes.TupleNode(pos,
-            args = positional_args)
-    if star_arg:
-        star_arg_tuple = ExprNodes.AsTupleNode(pos, arg = star_arg)
-        if arg_tuple:
-            arg_tuple = ExprNodes.binop_node(pos,
-                operator = '+', operand1 = arg_tuple,
-                operand2 = star_arg_tuple)
-        else:
-            arg_tuple = star_arg_tuple
-    if keyword_args or starstar_arg:
-        keyword_args = [ExprNodes.DictItemNode(pos=key.pos, key=key, value=value)
-                          for key, value in keyword_args]
-        if starstar_arg:
-            keyword_dict = ExprNodes.KeywordArgsNode(
-                pos,
-                starstar_arg = starstar_arg,
-                keyword_args = keyword_args)
-        else:
-            keyword_dict = ExprNodes.DictNode(
-                pos, key_value_pairs = keyword_args)
+
+    subtuples = [
+        ExprNodes.TupleNode(pos, args=arg) if isinstance(arg, list) else ExprNodes.AsTupleNode(pos, arg=arg)
+        for arg in positional_args
+    ]
+    # TODO: implement a faster way to join tuples than creating each one and adding them
+    arg_tuple = reduce(partial(ExprNodes.binop_node, pos, '+'), subtuples)
+
+    if keyword_args:
+        kwargs = []
+        dict_items = []
+        for item in keyword_args:
+            if isinstance(item, tuple):
+                key, value = item
+                dict_items.append(ExprNodes.DictItemNode(pos=key.pos, key=key, value=value))
+            elif item.is_dict_literal:
+                # unpack "**{a:b}" directly
+                dict_items.extend(item.key_value_pairs)
+            else:
+                if dict_items:
+                    kwargs.append(ExprNodes.DictNode(
+                        dict_items[0].pos, key_value_pairs=dict_items, reject_duplicates=True))
+                    dict_items = []
+                kwargs.append(item)
+
+        if dict_items:
+            kwargs.append(ExprNodes.DictNode(
+                dict_items[0].pos, key_value_pairs=dict_items, reject_duplicates=True))
+
+        if kwargs:
+            if len(kwargs) == 1 and kwargs[0].is_dict_literal:
+                # only simple keyword arguments found -> one dict
+                keyword_dict = kwargs[0]
+            else:
+                # at least one **kwargs
+                keyword_dict = ExprNodes.MergedDictNode(pos, keyword_args=kwargs)
+
     return arg_tuple, keyword_dict
 
+
 def p_call(s, function):
     # s.sy == '('
     pos = s.position()
+    positional_args, keyword_args = p_call_parse_args(s)
 
-    positional_args, keyword_args, star_arg, starstar_arg = \
-                     p_call_parse_args(s)
-
-    if not (keyword_args or star_arg or starstar_arg):
-        return ExprNodes.SimpleCallNode(pos,
-            function = function,
-            args = positional_args)
+    if not keyword_args and len(positional_args) == 1 and isinstance(positional_args[0], list):
+        return ExprNodes.SimpleCallNode(pos, function=function, args=positional_args[0])
     else:
-        arg_tuple, keyword_dict = p_call_build_packed_args(
-            pos, positional_args, keyword_args, star_arg, starstar_arg)
-        return ExprNodes.GeneralCallNode(pos,
-            function = function,
-            positional_args = arg_tuple,
-            keyword_args = keyword_dict)
+        arg_tuple, keyword_dict = p_call_build_packed_args(pos, positional_args, keyword_args)
+        return ExprNodes.GeneralCallNode(
+            pos, function=function, positional_args=arg_tuple, keyword_args=keyword_dict)
+
 
 #lambdef: 'lambda' [varargslist] ':' test
 
@@ -643,7 +661,7 @@ def p_atom(s):
         else:
             return ExprNodes.StringNode(pos, value = bytes_value, unicode_value = unicode_value)
     elif sy == 'IDENT':
-        name = EncodedString( s.systring )
+        name = s.systring
         s.next()
         if name == "None":
             return ExprNodes.NoneNode(pos)
@@ -897,11 +915,13 @@ def p_string_literal(s, kind_override=None):
     s.next()
     return (kind, bytes_value, unicode_value)
 
-# list_display      ::=      "[" [listmaker] "]"
-# listmaker     ::=     expression ( comp_for | ( "," expression )* [","] )
+
+# since PEP 448:
+# list_display  ::=     "[" [listmaker] "]"
+# listmaker     ::=     (test|star_expr) ( comp_for | (',' (test|star_expr))* [','] )
 # comp_iter     ::=     comp_for | comp_if
-# comp_for     ::=     "for" expression_list "in" testlist [comp_iter]
-# comp_if     ::=     "if" test [comp_iter]
+# comp_for      ::=     "for" expression_list "in" testlist [comp_iter]
+# comp_if       ::=     "if" test [comp_iter]
 
 def p_list_maker(s):
     # s.sy == '['
@@ -909,24 +929,29 @@ def p_list_maker(s):
     s.next()
     if s.sy == ']':
         s.expect(']')
-        return ExprNodes.ListNode(pos, args = [])
-    expr = p_test(s)
+        return ExprNodes.ListNode(pos, args=[])
+
+    expr = p_test_or_starred_expr(s)
     if s.sy == 'for':
+        if expr.is_starred:
+            s.error("iterable unpacking cannot be used in comprehension")
         append = ExprNodes.ComprehensionAppendNode(pos, expr=expr)
         loop = p_comp_for(s, append)
         s.expect(']')
         return ExprNodes.ComprehensionNode(
-            pos, loop=loop, append=append, type = Builtin.list_type,
+            pos, loop=loop, append=append, type=Builtin.list_type,
             # list comprehensions leak their loop variable in Py2
-            has_local_scope = s.context.language_level >= 3)
+            has_local_scope=s.context.language_level >= 3)
+
+    # (merged) list literal
+    if s.sy == ',':
+        s.next()
+        exprs = p_test_or_starred_expr_list(s, expr)
     else:
-        if s.sy == ',':
-            s.next()
-            exprs = p_simple_expr_list(s, expr)
-        else:
-            exprs = [expr]
-        s.expect(']')
-        return ExprNodes.ListNode(pos, args = exprs)
+        exprs = [expr]
+    s.expect(']')
+    return ExprNodes.ListNode(pos, args=exprs)
+
 
 def p_comp_iter(s, body):
     if s.sy == 'for':
@@ -955,7 +980,12 @@ def p_comp_if(s, body):
                                          body = p_comp_iter(s, body))],
         else_clause = None )
 
-#dictmaker: test ':' test (',' test ':' test)* [',']
+
+# since PEP 448:
+#dictorsetmaker: ( ((test ':' test | '**' expr)
+#                   (comp_for | (',' (test ':' test | '**' expr))* [','])) |
+#                  ((test | star_expr)
+#                   (comp_for | (',' (test | star_expr))* [','])) )
 
 def p_dict_or_set_maker(s):
     # s.sy == '{'
@@ -963,57 +993,108 @@ def p_dict_or_set_maker(s):
     s.next()
     if s.sy == '}':
         s.next()
-        return ExprNodes.DictNode(pos, key_value_pairs = [])
-    item = p_test(s)
-    if s.sy == ',' or s.sy == '}':
-        # set literal
-        values = [item]
-        while s.sy == ',':
+        return ExprNodes.DictNode(pos, key_value_pairs=[])
+
+    parts = []
+    target_type = 0
+    last_was_simple_item = False
+    while True:
+        if s.sy in ('*', '**'):
+            # merged set/dict literal
+            if target_type == 0:
+                target_type = 1 if s.sy == '*' else 2  # 'stars'
+            elif target_type != len(s.sy):
+                s.error("unexpected %sitem found in %s literal" % (
+                    s.sy, 'set' if target_type == 1 else 'dict'))
+            s.next()
+            if s.sy == '*':
+                s.error("expected expression, found '*'")
+            item = p_starred_expr(s)
+            parts.append(item)
+            last_was_simple_item = False
+        else:
+            item = p_test(s)
+            if target_type == 0:
+                target_type = 2 if s.sy == ':' else 1  # dict vs. set
+            if target_type == 2:
+                # dict literal
+                s.expect(':')
+                key = item
+                value = p_test(s)
+                item = ExprNodes.DictItemNode(key.pos, key=key, value=value)
+            if last_was_simple_item:
+                parts[-1].append(item)
+            else:
+                parts.append([item])
+                last_was_simple_item = True
+
+        if s.sy == ',':
             s.next()
             if s.sy == '}':
                 break
-            values.append( p_test(s) )
-        s.expect('}')
-        return ExprNodes.SetNode(pos, args=values)
-    elif s.sy == 'for':
-        # set comprehension
-        append = ExprNodes.ComprehensionAppendNode(
-            item.pos, expr=item)
-        loop = p_comp_for(s, append)
-        s.expect('}')
-        return ExprNodes.ComprehensionNode(
-            pos, loop=loop, append=append, type=Builtin.set_type)
-    elif s.sy == ':':
-        # dict literal or comprehension
-        key = item
-        s.next()
-        value = p_test(s)
-        if s.sy == 'for':
-            # dict comprehension
-            append = ExprNodes.DictComprehensionAppendNode(
-                item.pos, key_expr=key, value_expr=value)
+        else:
+            break
+
+    if s.sy == 'for':
+        # dict/set comprehension
+        if len(parts) == 1 and isinstance(parts[0], list) and len(parts[0]) == 1:
+            item = parts[0][0]
+            if target_type == 2:
+                assert isinstance(item, ExprNodes.DictItemNode), type(item)
+                comprehension_type = Builtin.dict_type
+                append = ExprNodes.DictComprehensionAppendNode(
+                    item.pos, key_expr=item.key, value_expr=item.value)
+            else:
+                comprehension_type = Builtin.set_type
+                append = ExprNodes.ComprehensionAppendNode(item.pos, expr=item)
             loop = p_comp_for(s, append)
             s.expect('}')
-            return ExprNodes.ComprehensionNode(
-                pos, loop=loop, append=append, type=Builtin.dict_type)
+            return ExprNodes.ComprehensionNode(pos, loop=loop, append=append, type=comprehension_type)
         else:
-            # dict literal
-            items = [ExprNodes.DictItemNode(key.pos, key=key, value=value)]
-            while s.sy == ',':
-                s.next()
-                if s.sy == '}':
-                    break
-                key = p_test(s)
-                s.expect(':')
-                value = p_test(s)
-                items.append(
-                    ExprNodes.DictItemNode(key.pos, key=key, value=value))
-            s.expect('}')
-            return ExprNodes.DictNode(pos, key_value_pairs=items)
-    else:
-        # raise an error
-        s.expect('}')
-    return ExprNodes.DictNode(pos, key_value_pairs = [])
+            # syntax error, try to find a good error message
+            if len(parts) == 1 and not isinstance(parts[0], list):
+                s.error("iterable unpacking cannot be used in comprehension")
+            else:
+                # e.g. "{1,2,3 for ..."
+                s.expect('}')
+            return ExprNodes.DictNode(pos, key_value_pairs=[])
+
+    s.expect('}')
+    if target_type == 1:
+        # (merged) set literal
+        items = []
+        set_items = []
+        for part in parts:
+            if isinstance(part, list):
+                set_items.extend(part)
+            else:
+                if set_items:
+                    items.append(ExprNodes.SetNode(set_items[0].pos, args=set_items))
+                    set_items = []
+                items.append(part)
+        if set_items:
+            items.append(ExprNodes.SetNode(set_items[0].pos, args=set_items))
+        if len(items) == 1 and items[0].is_set_literal:
+            return items[0]
+        return ExprNodes.MergedSequenceNode(pos, args=items, type=Builtin.set_type)
+    else:
+        # (merged) dict literal
+        items = []
+        dict_items = []
+        for part in parts:
+            if isinstance(part, list):
+                dict_items.extend(part)
+            else:
+                if dict_items:
+                    items.append(ExprNodes.DictNode(dict_items[0].pos, key_value_pairs=dict_items))
+                    dict_items = []
+                items.append(part)
+        if dict_items:
+            items.append(ExprNodes.DictNode(dict_items[0].pos, key_value_pairs=dict_items))
+        if len(items) == 1 and items[0].is_dict_literal:
+            return items[0]
+        return ExprNodes.MergedDictNode(pos, keyword_args=items, reject_duplicates=False)
+
 
 # NOTE: no longer in Py3 :)
 def p_backquote_expr(s):
@@ -1040,10 +1121,11 @@ def p_simple_expr_list(s, expr=None):
         s.next()
     return exprs
 
+
 def p_test_or_starred_expr_list(s, expr=None):
     exprs = expr is not None and [expr] or []
     while s.sy not in expr_terminators:
-        exprs.append( p_test_or_starred_expr(s) )
+        exprs.append(p_test_or_starred_expr(s))
         if s.sy != ',':
             break
         s.next()
@@ -1295,7 +1377,6 @@ def p_import_statement(s):
     stats = []
     is_absolute = Future.absolute_import in s.context.future_directives
     for pos, target_name, dotted_name, as_name in items:
-        dotted_name = EncodedString(dotted_name)
         if kind == 'cimport':
             stat = Nodes.CImportStatNode(
                 pos,
@@ -1305,7 +1386,7 @@ def p_import_statement(s):
         else:
             if as_name and "." in dotted_name:
                 name_list = ExprNodes.ListNode(pos, args=[
-                    ExprNodes.IdentifierStringNode(pos, value=EncodedString("*"))])
+                    ExprNodes.IdentifierStringNode(pos, value=s.context.intern_ustring("*"))])
             else:
                 name_list = None
             stat = Nodes.SingleAssignmentNode(
@@ -1334,7 +1415,7 @@ def p_from_import_statement(s, first_statement = 0):
         level = None
     if level is not None and s.sy in ('import', 'cimport'):
         # we are dealing with "from .. import foo, bar"
-        dotted_name_pos, dotted_name = s.position(), ''
+        dotted_name_pos, dotted_name = s.position(), s.context.intern_ustring('')
     else:
         if level is None and Future.absolute_import in s.context.future_directives:
             level = 0
@@ -1347,7 +1428,7 @@ def p_from_import_statement(s, first_statement = 0):
     is_cimport = kind == 'cimport'
     is_parenthesized = False
     if s.sy == '*':
-        imported_names = [(s.position(), "*", None, None)]
+        imported_names = [(s.position(), s.context.intern_ustring("*"), None, None)]
         s.next()
     else:
         if s.sy == '(':
@@ -1361,7 +1442,6 @@ def p_from_import_statement(s, first_statement = 0):
         imported_names.append(p_imported_name(s, is_cimport))
     if is_parenthesized:
         s.expect(')')
-    dotted_name = EncodedString(dotted_name)
     if dotted_name == '__future__':
         if not first_statement:
             s.error("from __future__ imports must occur at the beginning of the file")
@@ -1388,16 +1468,12 @@ def p_from_import_statement(s, first_statement = 0):
         imported_name_strings = []
         items = []
         for (name_pos, name, as_name, kind) in imported_names:
-            encoded_name = EncodedString(name)
             imported_name_strings.append(
-                ExprNodes.IdentifierStringNode(name_pos, value = encoded_name))
+                ExprNodes.IdentifierStringNode(name_pos, value=name))
             items.append(
-                (name,
-                 ExprNodes.NameNode(name_pos,
-                                    name = as_name or name)))
+                (name, ExprNodes.NameNode(name_pos, name=as_name or name)))
         import_list = ExprNodes.ListNode(
-            imported_names[0][0], args = imported_name_strings)
-        dotted_name = EncodedString(dotted_name)
+            imported_names[0][0], args=imported_name_strings)
         return Nodes.FromImportStatNode(pos,
             module = ExprNodes.ImportNode(dotted_name_pos,
                 module_name = ExprNodes.IdentifierStringNode(pos, value = dotted_name),
@@ -1405,8 +1481,8 @@ def p_from_import_statement(s, first_statement = 0):
                 name_list = import_list),
             items = items)
 
-imported_name_kinds = cython.declare(
-    set, set(['class', 'struct', 'union']))
+
+imported_name_kinds = cython.declare(set, set(['class', 'struct', 'union']))
 
 def p_imported_name(s, is_cimport):
     pos = s.position()
@@ -1418,6 +1494,7 @@ def p_imported_name(s, is_cimport):
     as_name = p_as_name(s)
     return (pos, name, as_name, kind)
 
+
 def p_dotted_name(s, as_allowed):
     pos = s.position()
     target_name = p_ident(s)
@@ -1428,7 +1505,8 @@ def p_dotted_name(s, as_allowed):
         names.append(p_ident(s))
     if as_allowed:
         as_name = p_as_name(s)
-    return (pos, target_name, u'.'.join(names), as_name)
+    return (pos, target_name, s.context.intern_ustring(u'.'.join(names)), as_name)
+
 
 def p_as_name(s):
     if s.sy == 'IDENT' and s.systring == 'as':
@@ -1437,6 +1515,7 @@ def p_as_name(s):
     else:
         return None
 
+
 def p_assert_statement(s):
     # s.sy == 'assert'
     pos = s.position()
@@ -1449,6 +1528,7 @@ def p_assert_statement(s):
         value = None
     return Nodes.AssertStatNode(pos, cond = cond, value = value)
 
+
 statement_terminators = cython.declare(set, set([';', 'NEWLINE', 'EOF']))
 
 def p_if_statement(s):
@@ -1993,8 +2073,7 @@ def p_positional_and_keyword_args(s, end_sy_set, templates = None):
                 arg = Nodes.CComplexBaseTypeNode(base_type.pos,
                     base_type = base_type, declarator = declarator)
                 parsed_type = True
-            keyword_node = ExprNodes.IdentifierStringNode(
-                arg.pos, value = EncodedString(ident))
+            keyword_node = ExprNodes.IdentifierStringNode(arg.pos, value=ident)
             keyword_args.append((keyword_node, arg))
             was_keyword = True
 
@@ -2361,7 +2440,7 @@ def p_c_declarator(s, ctx = Ctx(), empty = 0, is_type = 0, cmethod_flag = 0,
     if s.sy == '(':
         s.next()
         if s.sy == ')' or looking_at_name(s):
-            base = Nodes.CNameDeclaratorNode(pos, name = EncodedString(u""), cname = None)
+            base = Nodes.CNameDeclaratorNode(pos, name=s.context.intern_ustring(u""), cname=None)
             result = p_c_func_declarator(s, pos, ctx, base, cmethod_flag)
         else:
             result = p_c_declarator(s, ctx, empty = empty, is_type = is_type,
@@ -2454,7 +2533,7 @@ def p_c_simple_declarator(s, ctx, empty, is_type, cmethod_flag,
     else:
         rhs = None
         if s.sy == 'IDENT':
-            name = EncodedString(s.systring)
+            name = s.systring
             if empty:
                 error(s.position(), "Declarator should be empty")
             s.next()
@@ -2913,11 +2992,10 @@ def p_decorators(s):
         s.next()
         decstring = p_dotted_name(s, as_allowed=0)[2]
         names = decstring.split('.')
-        decorator = ExprNodes.NameNode(pos, name=EncodedString(names[0]))
+        decorator = ExprNodes.NameNode(pos, name=s.context.intern_ustring(names[0]))
         for name in names[1:]:
-            decorator = ExprNodes.AttributeNode(pos,
-                                           attribute=EncodedString(name),
-                                           obj=decorator)
+            decorator = ExprNodes.AttributeNode(
+                pos, attribute=s.context.intern_ustring(name), obj=decorator)
         if s.sy == '(':
             decorator = p_call(s, decorator)
         decorators.append(Nodes.DecoratorNode(pos, decorator=decorator))
@@ -2928,7 +3006,7 @@ def p_def_statement(s, decorators=None):
     # s.sy == 'def'
     pos = s.position()
     s.next()
-    name = EncodedString( p_ident(s) )
+    name = p_ident(s)
     s.expect('(')
     args, star_arg, starstar_arg = p_varargslist(s, terminator=')')
     s.expect(')')
@@ -2973,20 +3051,18 @@ def p_py_arg_decl(s, annotated = 1):
         annotation = p_test(s)
     return Nodes.PyArgDeclNode(pos, name = name, annotation = annotation)
 
+
 def p_class_statement(s, decorators):
     # s.sy == 'class'
     pos = s.position()
     s.next()
-    class_name = EncodedString( p_ident(s) )
-    class_name.encoding = s.source_encoding
+    class_name = EncodedString(p_ident(s))
+    class_name.encoding = s.source_encoding  # FIXME: why is this needed?
     arg_tuple = None
     keyword_dict = None
-    starstar_arg = None
     if s.sy == '(':
-        positional_args, keyword_args, star_arg, starstar_arg = \
-                            p_call_parse_args(s, allow_genexp = False)
-        arg_tuple, keyword_dict = p_call_build_packed_args(
-            pos, positional_args, keyword_args, star_arg, None)
+        positional_args, keyword_args = p_call_parse_args(s, allow_genexp=False)
+        arg_tuple, keyword_dict = p_call_build_packed_args(pos, positional_args, keyword_args)
     if arg_tuple is None:
         # XXX: empty arg_tuple
         arg_tuple = ExprNodes.TupleNode(pos, args=[])
@@ -2995,10 +3071,10 @@ def p_class_statement(s, decorators):
         pos, name=class_name,
         bases=arg_tuple,
         keyword_args=keyword_dict,
-        starstar_arg=starstar_arg,
         doc=doc, body=body, decorators=decorators,
         force_py3_semantics=s.context.language_level >= 3)
 
+
 def p_c_class_definition(s, pos,  ctx):
     # s.sy == 'class'
     s.next()
diff --git a/Cython/Compiler/Pipeline.py b/Cython/Compiler/Pipeline.py
index 7e2a44ddc7dfd2506385290040f8844dbcfb8d88..305d70595fd8304c873ec25e90cf90ef49534855 100644
--- a/Cython/Compiler/Pipeline.py
+++ b/Cython/Compiler/Pipeline.py
@@ -30,8 +30,7 @@ def parse_stage_factory(context):
         full_module_name = compsrc.full_module_name
         initial_pos = (source_desc, 1, 0)
         saved_cimport_from_pyx, Options.cimport_from_pyx = Options.cimport_from_pyx, False
-        scope = context.find_module(full_module_name, pos = initial_pos, need_pxd = 0,
-                                    check_module_name = not Options.embed)
+        scope = context.find_module(full_module_name, pos = initial_pos, need_pxd = 0)
         Options.cimport_from_pyx = saved_cimport_from_pyx
         tree = context.parse(source_desc, scope, pxd = 0, full_module_name = full_module_name)
         tree.compilation_source = compsrc
diff --git a/Cython/Compiler/PyrexTypes.py b/Cython/Compiler/PyrexTypes.py
index 2543f73d76e85ae91a614a1eaefbf830f091533c..a81b0395d7167a3a372088e6484ffd0a51a60e9b 100644
--- a/Cython/Compiler/PyrexTypes.py
+++ b/Cython/Compiler/PyrexTypes.py
@@ -393,7 +393,7 @@ class CTypedefType(BaseType):
                 base_type = self.typedef_base_type
                 if type(base_type) is CIntType:
                     self.to_py_function = "__Pyx_PyInt_From_" + self.specialization_name()
-                    env.use_utility_code(TempitaUtilityCode.load(
+                    env.use_utility_code(TempitaUtilityCode.load_cached(
                         "CIntToPy", "TypeConversion.c",
                         context={"TYPE": self.empty_declaration_code(),
                                  "TO_PY_FUNCTION": self.to_py_function}))
@@ -415,7 +415,7 @@ class CTypedefType(BaseType):
                 base_type = self.typedef_base_type
                 if type(base_type) is CIntType:
                     self.from_py_function = "__Pyx_PyInt_As_" + self.specialization_name()
-                    env.use_utility_code(TempitaUtilityCode.load(
+                    env.use_utility_code(TempitaUtilityCode.load_cached(
                         "CIntFromPy", "TypeConversion.c",
                         context={"TYPE": self.empty_declaration_code(),
                                  "FROM_PY_FUNCTION": self.from_py_function}))
@@ -450,17 +450,17 @@ class CTypedefType(BaseType):
         type = self.empty_declaration_code()
         name = self.specialization_name()
         if binop == "lshift":
-            env.use_utility_code(TempitaUtilityCode.load(
+            env.use_utility_code(TempitaUtilityCode.load_cached(
                 "LeftShift", "Overflow.c",
                 context={'TYPE': type, 'NAME': name, 'SIGNED': self.signed}))
         else:
             if const_rhs:
                 binop += "_const"
             _load_overflow_base(env)
-            env.use_utility_code(TempitaUtilityCode.load(
+            env.use_utility_code(TempitaUtilityCode.load_cached(
                 "SizeCheck", "Overflow.c",
                 context={'TYPE': type, 'NAME': name}))
-            env.use_utility_code(TempitaUtilityCode.load(
+            env.use_utility_code(TempitaUtilityCode.load_cached(
                 "Binop", "Overflow.c",
                 context={'TYPE': type, 'NAME': name, 'BINOP': binop}))
         return "__Pyx_%s_%s_checking_overflow" % (binop, name)
@@ -697,10 +697,9 @@ class MemoryViewSliceType(PyrexType):
 
         # We don't have 'code', so use a LazyUtilityCode with a callback.
         def lazy_utility_callback(code):
-            context['dtype_typeinfo'] = Buffer.get_type_information_cname(
-                                                          code, self.dtype)
+            context['dtype_typeinfo'] = Buffer.get_type_information_cname(code, self.dtype)
             return TempitaUtilityCode.load(
-                        "ObjectToMemviewSlice", "MemoryView_C.c", context=context)
+                "ObjectToMemviewSlice", "MemoryView_C.c", context=context)
 
         env.use_utility_code(Buffer.acquire_utility_code)
         env.use_utility_code(MemoryView.memviewslice_init_code)
@@ -777,8 +776,8 @@ class MemoryViewSliceType(PyrexType):
                 error_condition = error_condition,
             )
 
-        utility = TempitaUtilityCode.load(
-                        utility_name, "MemoryView_C.c", context=context)
+        utility = TempitaUtilityCode.load_cached(
+            utility_name, "MemoryView_C.c", context=context)
         env.use_utility_code(utility)
         return get_function, set_function
 
@@ -1490,7 +1489,7 @@ class CIntType(CNumericType):
     def create_to_py_utility_code(self, env):
         if type(self).to_py_function is None:
             self.to_py_function = "__Pyx_PyInt_From_" + self.specialization_name()
-            env.use_utility_code(TempitaUtilityCode.load(
+            env.use_utility_code(TempitaUtilityCode.load_cached(
                 "CIntToPy", "TypeConversion.c",
                 context={"TYPE": self.empty_declaration_code(),
                          "TO_PY_FUNCTION": self.to_py_function}))
@@ -1499,7 +1498,7 @@ class CIntType(CNumericType):
     def create_from_py_utility_code(self, env):
         if type(self).from_py_function is None:
             self.from_py_function = "__Pyx_PyInt_As_" + self.specialization_name()
-            env.use_utility_code(TempitaUtilityCode.load(
+            env.use_utility_code(TempitaUtilityCode.load_cached(
                 "CIntFromPy", "TypeConversion.c",
                 context={"TYPE": self.empty_declaration_code(),
                          "FROM_PY_FUNCTION": self.from_py_function}))
@@ -1539,18 +1538,18 @@ class CIntType(CNumericType):
         type = self.empty_declaration_code()
         name = self.specialization_name()
         if binop == "lshift":
-            env.use_utility_code(TempitaUtilityCode.load(
+            env.use_utility_code(TempitaUtilityCode.load_cached(
                 "LeftShift", "Overflow.c",
                 context={'TYPE': type, 'NAME': name, 'SIGNED': self.signed}))
         else:
             if const_rhs:
                 binop += "_const"
             if type in ('int', 'long', 'long long'):
-                env.use_utility_code(TempitaUtilityCode.load(
+                env.use_utility_code(TempitaUtilityCode.load_cached(
                     "BaseCaseSigned", "Overflow.c",
                     context={'INT': type, 'NAME': name}))
             elif type in ('unsigned int', 'unsigned long', 'unsigned long long'):
-                env.use_utility_code(TempitaUtilityCode.load(
+                env.use_utility_code(TempitaUtilityCode.load_cached(
                     "BaseCaseUnsigned", "Overflow.c",
                     context={'UINT': type, 'NAME': name}))
             elif self.rank <= 1:
@@ -1558,22 +1557,23 @@ class CIntType(CNumericType):
                 return "__Pyx_%s_%s_no_overflow" % (binop, name)
             else:
                 _load_overflow_base(env)
-                env.use_utility_code(TempitaUtilityCode.load(
+                env.use_utility_code(TempitaUtilityCode.load_cached(
                     "SizeCheck", "Overflow.c",
                     context={'TYPE': type, 'NAME': name}))
-                env.use_utility_code(TempitaUtilityCode.load(
+                env.use_utility_code(TempitaUtilityCode.load_cached(
                     "Binop", "Overflow.c",
                     context={'TYPE': type, 'NAME': name, 'BINOP': binop}))
         return "__Pyx_%s_%s_checking_overflow" % (binop, name)
 
+
 def _load_overflow_base(env):
     env.use_utility_code(UtilityCode.load("Common", "Overflow.c"))
     for type in ('int', 'long', 'long long'):
-        env.use_utility_code(TempitaUtilityCode.load(
+        env.use_utility_code(TempitaUtilityCode.load_cached(
             "BaseCaseSigned", "Overflow.c",
             context={'INT': type, 'NAME': type.replace(' ', '_')}))
     for type in ('unsigned int', 'unsigned long', 'unsigned long long'):
-        env.use_utility_code(TempitaUtilityCode.load(
+        env.use_utility_code(TempitaUtilityCode.load_cached(
             "BaseCaseUnsigned", "Overflow.c",
             context={'UINT': type, 'NAME': type.replace(' ', '_')}))
 
@@ -2710,8 +2710,9 @@ class CFuncType(CType):
                 trailer = " except %s" % self.exception_value
             elif self.exception_check == '+':
                 trailer = " except +"
-            else:
-                " except *" # ignored
+            elif self.exception_check and for_display:
+                # not spelled out by default, unless for human eyes
+                trailer = " except *"
             if self.nogil:
                 trailer += " nogil"
         if not with_calling_convention:
@@ -3684,13 +3685,11 @@ class CTupleType(CType):
         env.use_utility_code(self._convert_from_py_code)
         return True
 
-c_tuple_types = {}
+
 def c_tuple_type(components):
     components = tuple(components)
-    tuple_type = c_tuple_types.get(components)
-    if tuple_type is None:
-        cname = Naming.ctuple_type_prefix + type_list_identifier(components)
-        tuple_type = c_tuple_types[components] = CTupleType(cname, components)
+    cname = Naming.ctuple_type_prefix + type_list_identifier(components)
+    tuple_type = CTupleType(cname, components)
     return tuple_type
 
 
diff --git a/Cython/Compiler/Scanning.py b/Cython/Compiler/Scanning.py
index d01bc19ea4f2b03201cf424ef09053842e300f06..6170cea0126b12de51071369cc0d963e8cd739c2 100644
--- a/Cython/Compiler/Scanning.py
+++ b/Cython/Compiler/Scanning.py
@@ -6,7 +6,7 @@
 from __future__ import absolute_import
 
 import cython
-cython.declare(EncodedString=object, make_lexicon=object, lexicon=object,
+cython.declare(make_lexicon=object, lexicon=object,
                any_string_prefix=unicode, IDENT=unicode,
                print_function=object, error=object, warning=object,
                os=object, platform=object)
@@ -21,8 +21,6 @@ from .Errors import error, warning
 from .Lexicon import any_string_prefix, make_lexicon, IDENT
 from .Future import print_function
 
-from .StringEncoding import EncodedString
-
 debug_scanner = 0
 trace_scanner = 0
 scanner_debug_flags = 0
@@ -421,14 +419,11 @@ class PyrexScanner(Scanner):
             if systring in self.keywords:
                 if systring == u'print' and print_function in self.context.future_directives:
                     self.keywords.discard('print')
-                    systring = EncodedString(systring)
                 elif systring == u'exec' and self.context.language_level >= 3:
                     self.keywords.discard('exec')
-                    systring = EncodedString(systring)
                 else:
                     sy = systring
-            else:
-                systring = EncodedString(systring)
+            systring = self.context.intern_ustring(systring)
         self.sy = sy
         self.systring = systring
         if False: # debug_scanner:
diff --git a/Cython/Compiler/Symtab.py b/Cython/Compiler/Symtab.py
index 1437f832358288e83b33a977701a4e6207196bf8..c2f3ac847923382eb3e72c49c6b73edd61a40531 100644
--- a/Cython/Compiler/Symtab.py
+++ b/Cython/Compiler/Symtab.py
@@ -610,8 +610,8 @@ class Scope(object):
         self.sue_entries.append(entry)
         return entry
 
-    def declare_tuple_type(self, pos, type):
-        return self.outer_scope.declare_tuple_type(pos, type)
+    def declare_tuple_type(self, pos, components):
+        return self.outer_scope.declare_tuple_type(pos, components)
 
     def declare_var(self, name, type, pos,
                     cname = None, visibility = 'private',
@@ -1056,6 +1056,7 @@ class ModuleScope(Scope):
         self.cached_builtins = []
         self.undeclared_cached_builtins = []
         self.namespace_cname = self.module_cname
+        self._cached_tuple_types = {}
         for var_name in ['__builtins__', '__name__', '__file__', '__doc__', '__path__']:
             self.declare_var(EncodedString(var_name), py_object_type, None)
 
@@ -1075,18 +1076,24 @@ class ModuleScope(Scope):
 
         return self.outer_scope.lookup(name, language_level=language_level)
 
-    def declare_tuple_type(self, pos, type):
-        cname = type.cname
+    def declare_tuple_type(self, pos, components):
+        components = tuple(components)
+        try:
+            ttype = self._cached_tuple_types[components]
+        except KeyError:
+            ttype = self._cached_tuple_types[components] = PyrexTypes.c_tuple_type(components)
+        cname = ttype.cname
         entry = self.lookup_here(cname)
         if not entry:
             scope = StructOrUnionScope(cname)
-            for ix, component in enumerate(type.components):
+            for ix, component in enumerate(components):
                 scope.declare_var(name="f%s" % ix, type=component, pos=pos)
-            struct_entry = self.declare_struct_or_union(cname + '_struct', 'struct', scope, typedef_flag=True, pos=pos, cname=cname)
+            struct_entry = self.declare_struct_or_union(
+                cname + '_struct', 'struct', scope, typedef_flag=True, pos=pos, cname=cname)
             self.type_entries.remove(struct_entry)
-            type.struct_entry = struct_entry
-            entry = self.declare_type(cname, type, pos, cname)
-        type.entry = entry
+            ttype.struct_entry = struct_entry
+            entry = self.declare_type(cname, ttype, pos, cname)
+        ttype.entry = entry
         return entry
 
     def declare_builtin(self, name, pos):
@@ -1127,14 +1134,23 @@ class ModuleScope(Scope):
         # relative imports relative to this module's parent.
         # Finds and parses the module's .pxd file if the module
         # has not been referenced before.
-        module_scope = self.global_scope()
+        relative_to = None
+        absolute_fallback = False
         if relative_level is not None and relative_level > 0:
-            # merge current absolute module name and relative import name into qualified name
-            current_module = module_scope.qualified_name.split('.')
-            base_package = current_module[:-relative_level]
-            module_name = '.'.join(base_package + (module_name.split('.') if module_name else []))
+            # explicit relative cimport
+            # error of going beyond top-level is handled in cimport node
+            relative_to = self
+            while relative_level > 0 and relative_to:
+                relative_to = relative_to.parent_module
+                relative_level -= 1
+        elif relative_level != 0:
+            # -1 or None: try relative cimport first, then absolute
+            relative_to = self.parent_module
+            absolute_fallback = True
+
+        module_scope = self.global_scope()
         return module_scope.context.find_module(
-            module_name, relative_to=None if relative_level == 0 else self.parent_module, pos=pos)
+            module_name, relative_to=relative_to, pos=pos, absolute_fallback=absolute_fallback)
 
     def find_submodule(self, name):
         # Find and return scope for a submodule of this module,
@@ -1258,6 +1274,8 @@ class ModuleScope(Scope):
                 cname = name
             else:
                 cname = self.mangle(Naming.func_prefix, name)
+        if visibility == 'extern' and type.optional_arg_count:
+            error(pos, "Extern functions cannot have default arguments values.")
         entry = self.lookup_here(name)
         if entry and entry.defined_in_pxd:
             if entry.visibility != "private":
diff --git a/Cython/Compiler/TreeFragment.py b/Cython/Compiler/TreeFragment.py
index 352699533b7577a0b197eb5b337e38b4117ed24f..e08acb2895b836b40401cc69b0882d215204db39 100644
--- a/Cython/Compiler/TreeFragment.py
+++ b/Cython/Compiler/TreeFragment.py
@@ -32,7 +32,7 @@ class StringParseContext(Main.Context):
                               create_testscope=False)
         self.module_name = name
 
-    def find_module(self, module_name, relative_to=None, pos=None, need_pxd=1):
+    def find_module(self, module_name, relative_to=None, pos=None, need_pxd=1, absolute_fallback=True):
         if module_name not in (self.module_name, 'cython'):
             raise AssertionError("Not yet supporting any cimports/includes from string code snippets")
         return ModuleScope(module_name, parent_module=None, context=self)
diff --git a/Cython/Compiler/TypeInference.py b/Cython/Compiler/TypeInference.py
index 66b504c3c0470cbe2a4bfbdd27fc132cacd63553..94d00915811fd3d0bcc6b96bc6fdbb554c3c4bbb 100644
--- a/Cython/Compiler/TypeInference.py
+++ b/Cython/Compiler/TypeInference.py
@@ -12,8 +12,10 @@ from .Visitor import CythonTransform, EnvTransform
 
 class TypedExprNode(ExprNodes.ExprNode):
     # Used for declaring assignments of a specified type without a known entry.
-    def __init__(self, type):
-        self.type = type
+    subexprs = []
+
+    def __init__(self, type, pos=None):
+        super(TypedExprNode, self).__init__(pos, type=type)
 
 object_expr = TypedExprNode(py_object_type)
 
@@ -184,10 +186,10 @@ class MarkParallelAssignments(EnvTransform):
         # use fake expressions with the right result type
         if node.star_arg:
             self.mark_assignment(
-                node.star_arg, TypedExprNode(Builtin.tuple_type))
+                node.star_arg, TypedExprNode(Builtin.tuple_type, node.pos))
         if node.starstar_arg:
             self.mark_assignment(
-                node.starstar_arg, TypedExprNode(Builtin.dict_type))
+                node.starstar_arg, TypedExprNode(Builtin.dict_type, node.pos))
         EnvTransform.visit_FuncDefNode(self, node)
         return node
 
diff --git a/Cython/Compiler/UtilityCode.py b/Cython/Compiler/UtilityCode.py
index 01c2c9e81de9e019af71aaf34aaaa1ca2705d442..9f7bebb814d07324fa15a9d16af26808e8053061 100644
--- a/Cython/Compiler/UtilityCode.py
+++ b/Cython/Compiler/UtilityCode.py
@@ -34,7 +34,9 @@ class NonManglingModuleScope(Symtab.ModuleScope):
 class CythonUtilityCodeContext(StringParseContext):
     scope = None
 
-    def find_module(self, module_name, relative_to=None, pos=None, need_pxd=True):
+    def find_module(self, module_name, relative_to=None, pos=None, need_pxd=True, absolute_fallback=True):
+        if relative_to:
+            raise AssertionError("Relative imports not supported in utility code.")
         if module_name != self.module_name:
             if module_name not in self.modules:
                 raise AssertionError("Only the cython cimport is supported.")
diff --git a/Cython/Compiler/Visitor.py b/Cython/Compiler/Visitor.py
index 7222edef34d2f7fdbff3fe2dfbefcc93c5d6d381..6c7b7b2f21c3f1bcbba09e41ce11e3689f6e5102 100644
--- a/Cython/Compiler/Visitor.py
+++ b/Cython/Compiler/Visitor.py
@@ -14,6 +14,7 @@ from . import Nodes
 from . import ExprNodes
 from . import Errors
 from . import DebugFlags
+from . import Future
 
 import cython
 
@@ -434,7 +435,7 @@ find_special_method_for_binary_operator = {
     '>':  '__gt__',
     '+':  '__add__',
     '&':  '__and__',
-    '/':  '__truediv__',
+    '/':  '__div__',
     '//': '__floordiv__',
     '<<': '__lshift__',
     '%':  '__mod__',
@@ -515,6 +516,9 @@ class MethodDispatcherTransform(EnvTransform):
             operand1, operand2 = node.operand1, node.operand2
             if special_method_name == '__contains__':
                 operand1, operand2 = operand2, operand1
+            elif special_method_name == '__div__':
+                if Future.division in self.current_env().global_scope().context.future_directives:
+                    special_method_name = '__truediv__'
             obj_type = operand1.type
             if obj_type.is_builtin_type:
                 type_name = obj_type.name
@@ -705,12 +709,17 @@ class PrintTree(TreeVisitor):
     """Prints a representation of the tree to standard output.
     Subclass and override repr_of to provide more information
     about nodes. """
-    def __init__(self):
+    def __init__(self, start=None, end=None):
         TreeVisitor.__init__(self)
         self._indent = ""
+        if start is not None or end is not None:
+            self._line_range = (start or 0, end or 2**30)
+        else:
+            self._line_range = None
 
     def indent(self):
         self._indent += "  "
+
     def unindent(self):
         self._indent = self._indent[:-2]
 
@@ -724,15 +733,17 @@ class PrintTree(TreeVisitor):
     # under the parent-node, not displaying the list itself in
     # the hierarchy.
     def visit_Node(self, node):
-        if len(self.access_path) == 0:
-            name = "(root)"
-        else:
-            parent, attr, idx = self.access_path[-1]
-            if idx is not None:
-                name = "%s[%d]" % (attr, idx)
+        line = node.pos[1]
+        if self._line_range is None or self._line_range[0] <= line <= self._line_range[1]:
+            if len(self.access_path) == 0:
+                name = "(root)"
             else:
-                name = attr
-        print("%s- %s: %s" % (self._indent, name, self.repr_of(node)))
+                parent, attr, idx = self.access_path[-1]
+                if idx is not None:
+                    name = "%s[%d]" % (attr, idx)
+                else:
+                    name = attr
+            print("%s- %s: %s" % (self._indent, name, self.repr_of(node)))
         self.indent()
         self.visitchildren(node)
         self.unindent()
diff --git a/Cython/Includes/cpython/bytes.pxd b/Cython/Includes/cpython/bytes.pxd
index 2fb350201539f5761b4276003c443daa741a7f28..ea72c6aae7757c521cc5fcda5d55df9c89229ac3 100644
--- a/Cython/Includes/cpython/bytes.pxd
+++ b/Cython/Includes/cpython/bytes.pxd
@@ -1,4 +1,4 @@
-from cpython.ref cimport PyObject
+from .object cimport PyObject
 
 cdef extern from "Python.h":
     ctypedef struct va_list
diff --git a/Cython/Includes/cpython/cobject.pxd b/Cython/Includes/cpython/cobject.pxd
index 62c47064f5493ac60e2cbeb6a5a12a777e777b19..497d8a92e803599715bd4f59b95aaafb2e9c0671 100644
--- a/Cython/Includes/cpython/cobject.pxd
+++ b/Cython/Includes/cpython/cobject.pxd
@@ -1,4 +1,3 @@
-from cpython.ref cimport PyObject
 
 cdef extern from "Python.h":
 
diff --git a/Cython/Includes/cpython/datetime.pxd b/Cython/Includes/cpython/datetime.pxd
index 3c6f8a7f3969251e83ba3f303b84e4c124eae008..2e0c4bd88b9aaf3ed98049d6340acddb2652eb02 100644
--- a/Cython/Includes/cpython/datetime.pxd
+++ b/Cython/Includes/cpython/datetime.pxd
@@ -1,4 +1,4 @@
-from cpython.ref cimport PyObject
+from cpython.object cimport PyObject
 
 cdef extern from "Python.h":
     ctypedef struct PyTypeObject:
diff --git a/Cython/Includes/cpython/dict.pxd b/Cython/Includes/cpython/dict.pxd
index 69a416aeefd4f9dac5ee188364ecf1ebad3504a3..d58faea9a802a90e97c16a74d4d9858a3f6e7260 100644
--- a/Cython/Includes/cpython/dict.pxd
+++ b/Cython/Includes/cpython/dict.pxd
@@ -1,4 +1,4 @@
-from cpython.ref cimport PyObject
+from .object cimport PyObject
 
 cdef extern from "Python.h":
 
diff --git a/Cython/Includes/cpython/exc.pxd b/Cython/Includes/cpython/exc.pxd
index 89beb214a4127b08cf3e457db4914d431a3f7eb0..2e4eda5a03c16b1a07d730b0015f0bed6537c789 100644
--- a/Cython/Includes/cpython/exc.pxd
+++ b/Cython/Includes/cpython/exc.pxd
@@ -1,4 +1,4 @@
-from cpython.ref cimport PyObject
+from .object cimport PyObject
 
 cdef extern from "Python.h":
 
diff --git a/Cython/Includes/cpython/function.pxd b/Cython/Includes/cpython/function.pxd
index e8e4f068cfa68b485dbe4f38adcef5cc84579aa0..0002a3f6cbc426dc05dbdfce454da44483fbfa3e 100644
--- a/Cython/Includes/cpython/function.pxd
+++ b/Cython/Includes/cpython/function.pxd
@@ -1,4 +1,4 @@
-from cpython.ref cimport PyObject
+from .object cimport PyObject
 
 cdef extern from "Python.h":
 
diff --git a/Cython/Includes/cpython/getargs.pxd b/Cython/Includes/cpython/getargs.pxd
index 591aefbfdeda65dc902c679d6d3a19a1c0c1f0ed..be6df3285a720af1cdd21e5f40267686f9042526 100644
--- a/Cython/Includes/cpython/getargs.pxd
+++ b/Cython/Includes/cpython/getargs.pxd
@@ -1,4 +1,3 @@
-from cpython.ref cimport PyObject
 
 cdef extern from "Python.h":
     #####################################################################
diff --git a/Cython/Includes/cpython/list.pxd b/Cython/Includes/cpython/list.pxd
index 5cfd5735f6a71b2ee54e2e2f8394251ddfd93823..c6a29535c9aafb890c437477a224acc9b167cd99 100644
--- a/Cython/Includes/cpython/list.pxd
+++ b/Cython/Includes/cpython/list.pxd
@@ -1,4 +1,4 @@
-from cpython.ref cimport PyObject
+from .object cimport PyObject
 
 cdef extern from "Python.h":
 
diff --git a/Cython/Includes/cpython/method.pxd b/Cython/Includes/cpython/method.pxd
index bc09416422b6a0194828390de339e8c1d311229b..f51ebcc7c75b41477211925f13e87a1bea7dacb3 100644
--- a/Cython/Includes/cpython/method.pxd
+++ b/Cython/Includes/cpython/method.pxd
@@ -1,5 +1,6 @@
+from .object cimport PyObject
+
 cdef extern from "Python.h":
-    ctypedef void PyObject
     ############################################################################
     # 7.5.4 Method Objects
     ############################################################################
diff --git a/Cython/Includes/cpython/module.pxd b/Cython/Includes/cpython/module.pxd
index c821896058943c6478d8bcfd2ccefda79fef34f4..f36b9892ba3816700a9ba814d1f6703f74c46dca 100644
--- a/Cython/Includes/cpython/module.pxd
+++ b/Cython/Includes/cpython/module.pxd
@@ -1,4 +1,4 @@
-from cpython.ref cimport PyObject
+from .object cimport PyObject
 
 cdef extern from "Python.h":
     ctypedef struct _inittab
diff --git a/Cython/Includes/cpython/number.pxd b/Cython/Includes/cpython/number.pxd
index 346546e3299d7871c820bfddd4044dd9ebe188aa..3ad8de59c07cee4c7aa04310694306771e2f56e2 100644
--- a/Cython/Includes/cpython/number.pxd
+++ b/Cython/Includes/cpython/number.pxd
@@ -1,4 +1,4 @@
-from cpython.ref cimport PyObject
+from .object cimport PyObject
 
 cdef extern from "Python.h":
 
diff --git a/Cython/Includes/cpython/object.pxd b/Cython/Includes/cpython/object.pxd
index d861965788e8a45bb911ac0fcc67d2762b9d7035..ebd1acd2c97b7b99b4fdf9f7268094283396781a 100644
--- a/Cython/Includes/cpython/object.pxd
+++ b/Cython/Includes/cpython/object.pxd
@@ -1,8 +1,69 @@
-from cpython.ref cimport PyObject, PyTypeObject
 from libc.stdio cimport FILE
+cimport cpython.type
 
 cdef extern from "Python.h":
 
+    ctypedef struct PyObject  # forward declaration
+
+    ctypedef object (*newfunc)(cpython.type.type, object, object)  # (type, args, kwargs)
+
+    ctypedef object (*unaryfunc)(object)
+    ctypedef object (*binaryfunc)(object, object)
+    ctypedef object (*ternaryfunc)(object, object, object)
+    ctypedef int (*inquiry)(object)
+    ctypedef Py_ssize_t (*lenfunc)(object)
+    ctypedef object (*ssizeargfunc)(object, Py_ssize_t)
+    ctypedef object (*ssizessizeargfunc)(object, Py_ssize_t, Py_ssize_t)
+    ctypedef int (*ssizeobjargproc)(object, Py_ssize_t, object)
+    ctypedef int (*ssizessizeobjargproc)(object, Py_ssize_t, Py_ssize_t, object)
+    ctypedef int (*objobjargproc)(object, object, object)
+    ctypedef int (*objobjproc)(object, object)
+
+    ctypedef Py_hash_t (*hashfunc)(object)
+    ctypedef object (*reprfunc)(object)
+
+    ctypedef int (*cmpfunc)(object, object)
+    ctypedef object (*richcmpfunc)(object, object, int)
+
+    # The following functions use 'PyObject*' as first argument instead of 'object' to prevent
+    # accidental reference counting when calling them during a garbage collection run.
+    ctypedef void (*destructor)(PyObject*)
+    ctypedef int (*visitproc)(PyObject*, void *)
+    ctypedef int (*traverseproc)(PyObject*, visitproc, void*)
+
+    ctypedef struct PyTypeObject:
+        const char* tp_name
+        const char* tp_doc
+        Py_ssize_t tp_basicsize
+        Py_ssize_t tp_itemsize
+        Py_ssize_t tp_dictoffset
+        unsigned long tp_flags
+
+        newfunc tp_new
+        destructor tp_dealloc
+        traverseproc tp_traverse
+        inquiry tp_clear
+
+        ternaryfunc tp_call
+        hashfunc tp_hash
+        reprfunc tp_str
+        reprfunc tp_repr
+
+        cmpfunc tp_compare
+        richcmpfunc tp_richcompare
+
+        PyTypeObject* tp_base
+
+    ctypedef struct PyObject:
+        Py_ssize_t ob_refcnt
+        PyTypeObject *ob_type
+
+    cdef PyTypeObject *Py_TYPE(object)
+
+    void* PyObject_Malloc(size_t)
+    void* PyObject_Realloc(void *, size_t)
+    void PyObject_Free(void *)
+
     #####################################################################
     # 6.1 Object Protocol
     #####################################################################
diff --git a/Cython/Includes/cpython/pycapsule.pxd b/Cython/Includes/cpython/pycapsule.pxd
index f0b326bc2cba32402c63a17f5a926a3de70f893d..449f369a2cd0b712ffb58ed6554faf5d4acf8537 100644
--- a/Cython/Includes/cpython/pycapsule.pxd
+++ b/Cython/Includes/cpython/pycapsule.pxd
@@ -1,4 +1,3 @@
-from cpython.ref cimport PyObject
 
 # available since Python 3.1!
 
diff --git a/Cython/Includes/cpython/pystate.pxd b/Cython/Includes/cpython/pystate.pxd
index d53259f3779fb98905b5c25af5c35bfd83c0b8ab..f58503f9e6237e8b5b0df3a364326664330704f2 100644
--- a/Cython/Includes/cpython/pystate.pxd
+++ b/Cython/Includes/cpython/pystate.pxd
@@ -1,6 +1,6 @@
 # Thread and interpreter state structures and their interfaces
 
-from cpython.ref cimport PyObject
+from .object cimport PyObject
 
 cdef extern from "Python.h":
 
diff --git a/Cython/Includes/cpython/ref.pxd b/Cython/Includes/cpython/ref.pxd
index 63ee54b8415e8b6aa16918261c3d2763fa5c8758..4bc9a7d7c887986d1ce4851f3ac0ad73ccbe7e2b 100644
--- a/Cython/Includes/cpython/ref.pxd
+++ b/Cython/Includes/cpython/ref.pxd
@@ -1,15 +1,6 @@
-cdef extern from "Python.h":
-    ctypedef struct PyTypeObject:
-        Py_ssize_t tp_basicsize
-        Py_ssize_t tp_itemsize
-        long tp_flags
-
-    ctypedef struct PyObject:
-        Py_ssize_t ob_refcnt
-        PyTypeObject *ob_type
-    cdef PyTypeObject *Py_TYPE(object)
-
+from .object cimport PyObject, PyTypeObject, Py_TYPE  # legacy imports for re-export
 
+cdef extern from "Python.h":
     #####################################################################
     # 3. Reference Counts
     #####################################################################
diff --git a/Cython/Includes/cpython/sequence.pxd b/Cython/Includes/cpython/sequence.pxd
index 61ddca2f7b4b97c58ac95fe96b871014393a31c8..eb279968d20a3654cffdac8e570ec56df3a354ed 100644
--- a/Cython/Includes/cpython/sequence.pxd
+++ b/Cython/Includes/cpython/sequence.pxd
@@ -1,4 +1,4 @@
-from cpython.ref cimport PyObject
+from .object cimport PyObject
 
 cdef extern from "Python.h":
 
diff --git a/Cython/Includes/cpython/string.pxd b/Cython/Includes/cpython/string.pxd
index 65c6d371c73edba59f676ff2c0764ecda0b352c6..8af78f3dde615e2b2892a1e36b9f94754a9f2fa7 100644
--- a/Cython/Includes/cpython/string.pxd
+++ b/Cython/Includes/cpython/string.pxd
@@ -1,4 +1,4 @@
-from cpython.ref cimport PyObject
+from .object cimport PyObject
 
 cdef extern from "Python.h":
     ctypedef struct va_list
diff --git a/Cython/Includes/cpython/tuple.pxd b/Cython/Includes/cpython/tuple.pxd
index 6da28902cd68f0ebd64804e69c5c97c191ea7894..6564b5013926a0f38cf15216acb63b5fa6d0cbfe 100644
--- a/Cython/Includes/cpython/tuple.pxd
+++ b/Cython/Includes/cpython/tuple.pxd
@@ -1,4 +1,4 @@
-from cpython.ref cimport PyObject
+from .object cimport PyObject
 
 cdef extern from "Python.h":
 
diff --git a/Cython/Includes/cpython/weakref.pxd b/Cython/Includes/cpython/weakref.pxd
index 8f510526afde9e288913eca0d5c296024181dc54..ae710be6975252441425e0c49be4445fc1bbe907 100644
--- a/Cython/Includes/cpython/weakref.pxd
+++ b/Cython/Includes/cpython/weakref.pxd
@@ -1,4 +1,4 @@
-from cpython.ref cimport PyObject
+from .object cimport PyObject
 
 cdef extern from "Python.h":
 
diff --git a/Cython/Includes/libcpp/complex.pxd b/Cython/Includes/libcpp/complex.pxd
index 4645c9e2b22c33e39783252c8248984a33c5305e..c875d5e5bd9628e5cb6519811fc34dae30de788a 100644
--- a/Cython/Includes/libcpp/complex.pxd
+++ b/Cython/Includes/libcpp/complex.pxd
@@ -39,63 +39,63 @@ cdef extern from "<complex>" namespace "std" nogil:
         void imag(T)
 
     # Return real part
-    T real(complex[T]&)
+    T real[T](complex[T]&)
     long double real(long double)
     double real(double)
     float real(float)
 
     # Return imaginary part
-    T imag(complex[T]&)
+    T imag[T](complex[T]&)
     long double imag(long double)
     double imag(double)
     float imag(float)
 
-    T abs(complex[T]&)
-    T arg(complex[T]&)
+    T abs[T](complex[T]&)
+    T arg[T](complex[T]&)
     long double arg(long double)
     double arg(double)
     float arg(float)
 
-    T norm(complex[T])
+    T norm[T](complex[T])
     long double norm(long double)
     double norm(double)
     float norm(float)
 
-    complex[T] conj(complex[T]&)
+    complex[T] conj[T](complex[T]&)
     complex[long double] conj(long double)
     complex[double] conj(double)
     complex[float] conj(float)
 
-    complex[T] proj(complex[T])
+    complex[T] proj[T](complex[T])
     complex[long double] proj(long double)
     complex[double] proj(double)
     complex[float] proj(float)
 
-    complex[T] polar(T&, T&)
-    complex[T] ploar(T&)
+    complex[T] polar[T](T&, T&)
+    complex[T] ploar[T](T&)
 
-    complex[T] exp(complex[T]&)
-    complex[T] log(complex[T]&)
-    complex[T] log10(complex[T]&)
+    complex[T] exp[T](complex[T]&)
+    complex[T] log[T](complex[T]&)
+    complex[T] log10[T](complex[T]&)
 
-    complex[T] pow(complex[T]&, complex[T]&)
-    complex[T] pow(complex[T]&, T&)
-    complex[T] pow(T&, complex[T]&)
+    complex[T] pow[T](complex[T]&, complex[T]&)
+    complex[T] pow[T](complex[T]&, T&)
+    complex[T] pow[T](T&, complex[T]&)
     # There are some promotion versions too
 
-    complex[T] sqrt(complex[T]&)
+    complex[T] sqrt[T](complex[T]&)
 
-    complex[T] sin(complex[T]&)
-    complex[T] cos(complex[T]&)
-    complex[T] tan(complex[T]&)
-    complex[T] asin(complex[T]&)
-    complex[T] acos(complex[T]&)
-    complex[T] atan(complex[T]&)
+    complex[T] sin[T](complex[T]&)
+    complex[T] cos[T](complex[T]&)
+    complex[T] tan[T](complex[T]&)
+    complex[T] asin[T](complex[T]&)
+    complex[T] acos[T](complex[T]&)
+    complex[T] atan[T](complex[T]&)
 
-    complex[T] sinh(complex[T]&)
-    complex[T] cosh(complex[T]&)
-    complex[T] tanh(complex[T]&)
+    complex[T] sinh[T](complex[T]&)
+    complex[T] cosh[T](complex[T]&)
+    complex[T] tanh[T](complex[T]&)
 
-    complex[T] asinh(complex[T]&)
-    complex[T] acosh(complex[T]&)
-    complex[T] atanh(complex[T]&)
+    complex[T] asinh[T](complex[T]&)
+    complex[T] acosh[T](complex[T]&)
+    complex[T] atanh[T](complex[T]&)
diff --git a/Cython/Includes/libcpp/deque.pxd b/Cython/Includes/libcpp/deque.pxd
index 2c34807a82e70a705956e9b4c939e031c3179f4a..d7e7747454db2155520910998bbf5a0ad900fa09 100644
--- a/Cython/Includes/libcpp/deque.pxd
+++ b/Cython/Includes/libcpp/deque.pxd
@@ -12,8 +12,8 @@ cdef extern from "<deque>" namespace "std" nogil:
             iterator operator--()
             bint operator==(reverse_iterator)
             bint operator!=(reverse_iterator)
-        #cppclass const_iterator(iterator):
-        #    pass
+        cppclass const_iterator(iterator):
+            pass
         #cppclass const_reverse_iterator(reverse_iterator):
         #    pass
         deque() except +
@@ -34,11 +34,11 @@ cdef extern from "<deque>" namespace "std" nogil:
         T& at(size_t)
         T& back()
         iterator begin()
-        #const_iterator begin()
+        const_iterator const_begin "begin"()
         void clear()
         bint empty()
         iterator end()
-        #const_iterator end()
+        const_iterator const_end "end"()
         iterator erase(iterator)
         iterator erase(iterator, iterator)
         T& front()
diff --git a/Cython/Includes/libcpp/list.pxd b/Cython/Includes/libcpp/list.pxd
index 3e7259c0b9844d4a99219973582705d0f8bd946f..bad97f2bce2527c04afeff0ca59c4d40703a3ed4 100644
--- a/Cython/Includes/libcpp/list.pxd
+++ b/Cython/Includes/libcpp/list.pxd
@@ -16,10 +16,10 @@ cdef extern from "<list>" namespace "std" nogil:
             reverse_iterator operator--()
             bint operator==(reverse_iterator)
             bint operator!=(reverse_iterator)
-        #cppclass const_iterator(iterator):
-        #    pass
-        #cppclass const_reverse_iterator(reverse_iterator):
-        #    pass
+        cppclass const_iterator(iterator):
+            pass
+        cppclass const_reverse_iterator(reverse_iterator):
+            pass
         list() except +
         list(list&) except +
         list(size_t, T&) except +
@@ -33,11 +33,11 @@ cdef extern from "<list>" namespace "std" nogil:
         void assign(size_t, T&)
         T& back()
         iterator begin()
-        #const_iterator begin()
+        const_iterator const_begin "begin"()
         void clear()
         bint empty()
         iterator end()
-        #const_iterator end()
+        const_iterator const_end "end"()
         iterator erase(iterator)
         iterator erase(iterator, iterator)
         T& front()
@@ -51,11 +51,11 @@ cdef extern from "<list>" namespace "std" nogil:
         void push_back(T&)
         void push_front(T&)
         reverse_iterator rbegin()
-        #const_reverse_iterator rbegin()
+        const_reverse_iterator const_rbegin "rbegin"()
         void remove(T&)
         #void remove_if(UnPred)
         reverse_iterator rend()
-        #const_reverse_iterator rend()
+        const_reverse_iterator const_rend "rend"()
         void resize(size_t, T&)
         void reverse()
         size_t size()
diff --git a/Cython/Includes/libcpp/map.pxd b/Cython/Includes/libcpp/map.pxd
index a3768d8a2832aa2fdaf017595f3257d5904b8ce9..a1c84f1f6196bba830a492ed080039f8c37536d5 100644
--- a/Cython/Includes/libcpp/map.pxd
+++ b/Cython/Includes/libcpp/map.pxd
@@ -20,8 +20,8 @@ cdef extern from "<map>" namespace "std" nogil:
             iterator operator--()
             bint operator==(reverse_iterator)
             bint operator!=(reverse_iterator)
-        #cppclass const_reverse_iterator(reverse_iterator):
-        #    pass
+        cppclass const_reverse_iterator(reverse_iterator):
+            pass
         map() except +
         map(map&) except +
         #map(key_compare&)
@@ -53,14 +53,14 @@ cdef extern from "<map>" namespace "std" nogil:
         #void insert(input_iterator, input_iterator)
         #key_compare key_comp()
         iterator lower_bound(const T&)
-        #const_iterator lower_bound(const key_type&)
+        const_iterator const_lower_bound "lower_bound"(const T&)
         size_t max_size()
         reverse_iterator rbegin()
-        #const_reverse_iterator rbegin()
+        const_reverse_iterator const_rbegin "rbegin"()
         reverse_iterator rend()
-        #const_reverse_iterator rend()
+        const_reverse_iterator const_rend "rend"()
         size_t size()
         void swap(map&)
         iterator upper_bound(const T&)
-        #const_iterator upper_bound(const key_type&)
+        const_iterator const_upper_bound "upper_bound"(const T&)
         #value_compare value_comp()
diff --git a/Cython/Includes/libcpp/set.pxd b/Cython/Includes/libcpp/set.pxd
index dd74377134d650f13ffd68121a2f3d358e7866f0..1d9719b841c95201f702b769d3e7c20556db9083 100644
--- a/Cython/Includes/libcpp/set.pxd
+++ b/Cython/Includes/libcpp/set.pxd
@@ -14,10 +14,10 @@ cdef extern from "<set>" namespace "std" nogil:
             iterator operator--()
             bint operator==(reverse_iterator)
             bint operator!=(reverse_iterator)
-        #cppclass const_iterator(iterator):
-        #    pass
-        #cppclass const_reverse_iterator(reverse_iterator):
-        #    pass
+        cppclass const_iterator(iterator):
+            pass
+        cppclass const_reverse_iterator(reverse_iterator):
+            pass
         set() except +
         set(set&) except +
         #set(key_compare&)
@@ -29,32 +29,32 @@ cdef extern from "<set>" namespace "std" nogil:
         bint operator<=(set&, set&)
         bint operator>=(set&, set&)
         iterator begin()
-        #const_iterator begin()
+        const_iterator const_begin "begin"()
         void clear()
         size_t count(const T&)
         bint empty()
         iterator end()
-        #const_iterator end()
+        const_iterator const_end "end"()
         pair[iterator, iterator] equal_range(const T&)
         #pair[const_iterator, const_iterator] equal_range(T&)
         void erase(iterator)
         void erase(iterator, iterator)
         size_t erase(T&)
         iterator find(T&)
-        #const_iterator find(T&)
+        const_iterator const_find "find"(T&)
         pair[iterator, bint] insert(const T&) except +
         iterator insert(iterator, const T&) except +
         #void insert(input_iterator, input_iterator)
         #key_compare key_comp()
         iterator lower_bound(T&)
-        #const_iterator lower_bound(T&)
+        const_iterator const_lower_bound "lower_bound"(T&)
         size_t max_size()
         reverse_iterator rbegin()
-        #const_reverse_iterator rbegin()
+        const_reverse_iterator const_rbegin "rbegin"()
         reverse_iterator rend()
-        #const_reverse_iterator rend()
+        const_reverse_iterator const_rend "rend"()
         size_t size()
         void swap(set&)
         iterator upper_bound(const T&)
-        #const_iterator upper_bound(const T&)
+        const_iterator const_upper_bound "upper_bound"(const T&)
         #value_compare value_comp()
diff --git a/Cython/Includes/libcpp/unordered_map.pxd b/Cython/Includes/libcpp/unordered_map.pxd
index 3bf4f5deecfc4a96e6ca533a3cf95a06a0d15b14..114b28e25d08f464412c1f9bf61f7f230f17034a 100644
--- a/Cython/Includes/libcpp/unordered_map.pxd
+++ b/Cython/Includes/libcpp/unordered_map.pxd
@@ -14,10 +14,10 @@ cdef extern from "<unordered_map>" namespace "std" nogil:
             iterator operator--()
             bint operator==(reverse_iterator)
             bint operator!=(reverse_iterator)
-        #cppclass const_iterator(iterator):
-        #    pass
-        #cppclass const_reverse_iterator(reverse_iterator):
-        #    pass
+        cppclass const_iterator(iterator):
+            pass
+        cppclass const_reverse_iterator(reverse_iterator):
+            pass
         unordered_map() except +
         unordered_map(unordered_map&) except +
         #unordered_map(key_compare&)
@@ -31,34 +31,34 @@ cdef extern from "<unordered_map>" namespace "std" nogil:
         bint operator>=(unordered_map&, unordered_map&)
         U& at(T&)
         iterator begin()
-        #const_iterator begin()
+        const_iterator const_begin "begin"()
         void clear()
         size_t count(T&)
         bint empty()
         iterator end()
-        #const_iterator end()
+        const_iterator const_end "end"()
         pair[iterator, iterator] equal_range(T&)
         #pair[const_iterator, const_iterator] equal_range(key_type&)
         void erase(iterator)
         void erase(iterator, iterator)
         size_t erase(T&)
         iterator find(T&)
-        #const_iterator find(key_type&)
+        const_iterator const_find "find"(T&)
         pair[iterator, bint] insert(pair[T, U]) # XXX pair[T,U]&
         iterator insert(iterator, pair[T, U]) # XXX pair[T,U]&
         #void insert(input_iterator, input_iterator)
         #key_compare key_comp()
         iterator lower_bound(T&)
-        #const_iterator lower_bound(key_type&)
+        const_iterator const_lower_bound "lower_bound"(T&)
         size_t max_size()
         reverse_iterator rbegin()
-        #const_reverse_iterator rbegin()
+        const_reverse_iterator const_rbegin "rbegin"()
         reverse_iterator rend()
-        #const_reverse_iterator rend()
+        const_reverse_iterator const_rend "rend"()
         size_t size()
         void swap(unordered_map&)
         iterator upper_bound(T&)
-        #const_iterator upper_bound(key_type&)
+        const_iterator const_upper_bound "upper_bound"(T&)
         #value_compare value_comp()
         void max_load_factor(float)
         float max_load_factor()
diff --git a/Cython/Includes/libcpp/unordered_set.pxd b/Cython/Includes/libcpp/unordered_set.pxd
index 55107dbefccae392392befa8f75939c837ceec5a..866902c2e93c0ad08b19e0288c2563e27426e75d 100644
--- a/Cython/Includes/libcpp/unordered_set.pxd
+++ b/Cython/Includes/libcpp/unordered_set.pxd
@@ -14,10 +14,10 @@ cdef extern from "<unordered_set>" namespace "std" nogil:
             iterator operator--()
             bint operator==(reverse_iterator)
             bint operator!=(reverse_iterator)
-        #cppclass const_iterator(iterator):
-        #    pass
-        #cppclass const_reverse_iterator(reverse_iterator):
-        #    pass
+        cppclass const_iterator(iterator):
+            pass
+        cppclass const_reverse_iterator(reverse_iterator):
+            pass
         unordered_set() except +
         unordered_set(unordered_set&) except +
         #unordered_set(key_compare&)
@@ -29,32 +29,32 @@ cdef extern from "<unordered_set>" namespace "std" nogil:
         bint operator<=(unordered_set&, unordered_set&)
         bint operator>=(unordered_set&, unordered_set&)
         iterator begin()
-        #const_iterator begin()
+        const_iterator const_begin "begin"()
         void clear()
         size_t count(T&)
         bint empty()
         iterator end()
-        #const_iterator end()
+        const_iterator const_end "end"()
         pair[iterator, iterator] equal_range(T&)
         #pair[const_iterator, const_iterator] equal_range(T&)
         void erase(iterator)
         void erase(iterator, iterator)
         size_t erase(T&)
         iterator find(T&)
-        #const_iterator find(T&)
+        const_iterator const_find "find"(T&)
         pair[iterator, bint] insert(T&)
         iterator insert(iterator, T&)
         #void insert(input_iterator, input_iterator)
         #key_compare key_comp()
         iterator lower_bound(T&)
-        #const_iterator lower_bound(T&)
+        const_iterator const_lower_bound "lower_bound"(T&)
         size_t max_size()
         reverse_iterator rbegin()
-        #const_reverse_iterator rbegin()
+        const_reverse_iterator const_rbegin "rbegin"()
         reverse_iterator rend()
-        #const_reverse_iterator rend()
+        const_reverse_iterator const_rend "rend"()
         size_t size()
         void swap(unordered_set&)
         iterator upper_bound(T&)
-        #const_iterator upper_bound(T&)
+        const_iterator const_upper_bound "upper_bound"(T&)
         #value_compare value_comp()
diff --git a/Cython/Includes/libcpp/vector.pxd b/Cython/Includes/libcpp/vector.pxd
index 22db3a3370b57d806a14aa52152434de9a4ae266..e8afcd9677678bdece13c775bad79cdedf4854c4 100644
--- a/Cython/Includes/libcpp/vector.pxd
+++ b/Cython/Includes/libcpp/vector.pxd
@@ -24,10 +24,10 @@ cdef extern from "<vector>" namespace "std" nogil:
             bint operator>(reverse_iterator)
             bint operator<=(reverse_iterator)
             bint operator>=(reverse_iterator)
-        #cppclass const_iterator(iterator):
-        #    pass
-        #cppclass const_reverse_iterator(reverse_iterator):
-        #    pass
+        cppclass const_iterator(iterator):
+            pass
+        cppclass const_reverse_iterator(reverse_iterator):
+            pass
         vector() except +
         vector(vector&) except +
         vector(size_t) except +
@@ -46,12 +46,12 @@ cdef extern from "<vector>" namespace "std" nogil:
         T& at(size_t) except +
         T& back()
         iterator begin()
-        #const_iterator begin()
+        const_iterator const_begin "begin"()
         size_t capacity()
         void clear()
         bint empty()
         iterator end()
-        #const_iterator end()
+        const_iterator const_end "end"()
         iterator erase(iterator)
         iterator erase(iterator, iterator)
         T& front()
@@ -62,15 +62,15 @@ cdef extern from "<vector>" namespace "std" nogil:
         void pop_back()
         void push_back(T&) except +
         reverse_iterator rbegin()
-        #const_reverse_iterator rbegin()
+        const_reverse_iterator const_rbegin "rbegin"()
         reverse_iterator rend()
-        #const_reverse_iterator rend()
+        const_reverse_iterator const_rend "rend"()
         void reserve(size_t)
         void resize(size_t) except +
         void resize(size_t, T&) except +
         size_t size()
         void swap(vector&)
-        
+
         # C++11 methods
         T* data()
         void shrink_to_fit()
diff --git a/Cython/Includes/numpy/__init__.pxd b/Cython/Includes/numpy/__init__.pxd
index edb1dbfa518e3c44dd4c61c61b64ae7ea43c214e..0ad89f7bca7768ddd153a4cbb574c7db58ac9fe2 100644
--- a/Cython/Includes/numpy/__init__.pxd
+++ b/Cython/Includes/numpy/__init__.pxd
@@ -241,7 +241,6 @@ cdef extern from "numpy/arrayobject.h":
             cdef int t
             cdef char* f = NULL
             cdef dtype descr = self.descr
-            cdef list stack
             cdef int offset
 
             cdef bint hasfields = PyDataType_HASFIELDS(descr)
@@ -788,8 +787,6 @@ cdef inline char* _util_dtypestring(dtype descr, char* f, char* end, int* offset
     # string. The new location in the format string is returned.
 
     cdef dtype child
-    cdef int delta_offset
-    cdef tuple i
     cdef int endian_detector = 1
     cdef bint little_endian = ((<char*>&endian_detector)[0] != 0)
     cdef tuple fields
diff --git a/Cython/Parser/Grammar b/Cython/Parser/Grammar
index bea5cfe9127be8b1abe7fc0a421dbf4591c77c76..cb66a36b3c9b626dc0b7978ce6c9e5903a0ab561 100644
--- a/Cython/Parser/Grammar
+++ b/Cython/Parser/Grammar
@@ -109,17 +109,29 @@ subscript: test | [test] ':' [test] [sliceop]
 sliceop: ':' [test]
 exprlist: (expr|star_expr) (',' (expr|star_expr))* [',']
 testlist: test (',' test)* [',']
-dictorsetmaker: ( (test ':' test (comp_for | (',' test ':' test)* [','])) |
-                  (test (comp_for | (',' test)* [','])) )
+dictorsetmaker: ( ((test ':' test | '**' expr)
+                   (comp_for | (',' (test ':' test | '**' expr))* [','])) |
+                  ((test | star_expr)
+                   (comp_for | (',' (test | star_expr))* [','])) )
 
 classdef: 'class' PY_NAME ['(' [arglist] ')'] ':' suite
 
-arglist: (argument ',')* (argument [',']
-                         |'*' test (',' argument)* [',' '**' test]
-                         |'**' test)
+arglist: argument (',' argument)*  [',']
+
 # The reason that keywords are test nodes instead of NAME is that using NAME
 # results in an ambiguity. ast.c makes sure it's a NAME.
-argument: test [comp_for] | test '=' test  # Really [keyword '='] test
+# "test '=' test" is really "keyword '=' test", but we have no such token.
+# These need to be in a single rule to avoid grammar that is ambiguous
+# to our LL(1) parser. Even though 'test' includes '*expr' in star_expr,
+# we explicitly match '*' here, too, to give it proper precedence.
+# Illegal combinations and orderings are blocked in ast.c:
+# multiple (test comp_for) arguements are blocked; keyword unpackings
+# that precede iterable unpackings are blocked; etc.
+argument: ( test [comp_for] |
+            test '=' test |
+            '**' expr |
+            star_expr )
+
 comp_iter: comp_for | comp_if
 comp_for: 'for' exprlist ('in' or_test | for_from_clause) [comp_iter]
 comp_if: 'if' test_nocond [comp_iter]
diff --git a/Cython/Shadow.py b/Cython/Shadow.py
index 72b4c0343429296ed2af44e9ce4f0e87b5a974f9..d058a3aa3c15ef90351ad025455a74da8f247b9f 100644
--- a/Cython/Shadow.py
+++ b/Cython/Shadow.py
@@ -1,5 +1,5 @@
 # cython.* namespace for pure mode.
-__version__ = "0.22"
+__version__ = "0.23dev"
 
 
 # BEGIN shameless copy from Cython/minivect/minitypes.py
@@ -97,7 +97,7 @@ class _EmptyDecoratorAndManager(object):
 
 cclass = ccall = cfunc = _EmptyDecoratorAndManager()
 
-returns = lambda type_arg: _EmptyDecoratorAndManager()
+returns = wraparound = boundscheck = lambda arg: _EmptyDecoratorAndManager()
 
 final = internal = type_version_tag = no_gc_clear = _empty_decorator
 
diff --git a/Cython/Utility/Buffer.c b/Cython/Utility/Buffer.c
index ad8ce0daac977497dc667fa19d6f69ac24288d11..c5865b15e429fe41daaf0b82035e157c344093e1 100644
--- a/Cython/Utility/Buffer.c
+++ b/Cython/Utility/Buffer.c
@@ -858,16 +858,13 @@ static struct __pyx_typeinfo_string __Pyx_TypeInfoToFormat(__Pyx_TypeInfo *type)
         case 'I':
         case 'U':
             if (size == 1)
-                *buf = 'b';
+                *buf = (type->is_unsigned) ? 'B' : 'b';
             else if (size == 2)
-                *buf = 'h';
+                *buf = (type->is_unsigned) ? 'H' : 'h';
             else if (size == 4)
-                *buf = 'i';
+                *buf = (type->is_unsigned) ? 'I' : 'i';
             else if (size == 8)
-                *buf = 'q';
-
-            if (type->is_unsigned)
-                *buf = toupper(*buf);
+                *buf = (type->is_unsigned) ? 'Q' : 'q';
             break;
         case 'P':
             *buf = 'P';
diff --git a/Cython/Utility/Builtins.c b/Cython/Utility/Builtins.c
index 4482a7aab9a9c093160a04f0159d310204063e0a..c9d2a65f620d3149143e7a5f86abbe63faf409fd 100644
--- a/Cython/Utility/Builtins.c
+++ b/Cython/Utility/Builtins.c
@@ -29,7 +29,7 @@ static PyObject* __Pyx_Globals(void) {
         goto bad;
     for (i = PyList_GET_SIZE(names)-1; i >= 0; i--) {
 #if CYTHON_COMPILING_IN_PYPY
-        PyObject* name = PySequence_GetItem(names, i);
+        PyObject* name = PySequence_ITEM(names, i);
         if (!name)
             goto bad;
 #else
@@ -239,20 +239,64 @@ static CYTHON_INLINE unsigned PY_LONG_LONG __Pyx_abs_longlong(PY_LONG_LONG x) {
 #endif
 }
 
+
 //////////////////// pow2.proto ////////////////////
 
 #define __Pyx_PyNumber_Power2(a, b) PyNumber_Power(a, b, Py_None)
 
+
+//////////////////// object_ord.proto ////////////////////
+//@requires: TypeConversion.c::UnicodeAsUCS4
+
+#if PY_MAJOR_VERSION >= 3
+#define __Pyx_PyObject_Ord(c) \
+    (likely(PyUnicode_Check(c)) ? (long)__Pyx_PyUnicode_AsPy_UCS4(c) : __Pyx__PyObject_Ord(c))
+#else
+#define __Pyx_PyObject_Ord(c) __Pyx__PyObject_Ord(c)
+#endif
+static long __Pyx__PyObject_Ord(PyObject* c); /*proto*/
+
+//////////////////// object_ord ////////////////////
+
+static long __Pyx__PyObject_Ord(PyObject* c) {
+    Py_ssize_t size;
+    if (PyBytes_Check(c)) {
+        size = PyBytes_GET_SIZE(c);
+        if (likely(size == 1)) {
+            return (unsigned char) PyBytes_AS_STRING(c)[0];
+        }
+#if PY_MAJOR_VERSION < 3
+    } else if (PyUnicode_Check(c)) {
+        return (long)__Pyx_PyUnicode_AsPy_UCS4(c);
+#endif
+#if (!CYTHON_COMPILING_IN_PYPY) || (defined(PyByteArray_AS_STRING) && defined(PyByteArray_GET_SIZE))
+    } else if (PyByteArray_Check(c)) {
+        size = PyByteArray_GET_SIZE(c);
+        if (likely(size == 1)) {
+            return (unsigned char) PyByteArray_AS_STRING(c)[0];
+        }
+#endif
+    } else {
+        // FIXME: support character buffers - but CPython doesn't support them either
+        PyErr_Format(PyExc_TypeError,
+            "ord() expected string of length 1, but %.200s found", c->ob_type->tp_name);
+        return (long)(Py_UCS4)-1;
+    }
+    PyErr_Format(PyExc_TypeError,
+        "ord() expected a character, but string of length %zd found", size);
+    return (long)(Py_UCS4)-1;
+}
+
+
 //////////////////// py_dict_keys.proto ////////////////////
 
 static CYTHON_INLINE PyObject* __Pyx_PyDict_Keys(PyObject* d); /*proto*/
 
 //////////////////// py_dict_keys ////////////////////
-//@requires: ObjectHandling.c::PyObjectCallMethod1
 
 static CYTHON_INLINE PyObject* __Pyx_PyDict_Keys(PyObject* d) {
     if (PY_MAJOR_VERSION >= 3)
-        return __Pyx_PyObject_CallMethod1((PyObject*)&PyDict_Type, PYIDENT("keys"), d);
+        return CALL_UNBOUND_METHOD(PyDict_Type, "keys", d);
     else
         return PyDict_Keys(d);
 }
@@ -262,11 +306,10 @@ static CYTHON_INLINE PyObject* __Pyx_PyDict_Keys(PyObject* d) {
 static CYTHON_INLINE PyObject* __Pyx_PyDict_Values(PyObject* d); /*proto*/
 
 //////////////////// py_dict_values ////////////////////
-//@requires: ObjectHandling.c::PyObjectCallMethod1
 
 static CYTHON_INLINE PyObject* __Pyx_PyDict_Values(PyObject* d) {
     if (PY_MAJOR_VERSION >= 3)
-        return __Pyx_PyObject_CallMethod1((PyObject*)&PyDict_Type, PYIDENT("values"), d);
+        return CALL_UNBOUND_METHOD(PyDict_Type, "values", d);
     else
         return PyDict_Values(d);
 }
@@ -276,11 +319,10 @@ static CYTHON_INLINE PyObject* __Pyx_PyDict_Values(PyObject* d) {
 static CYTHON_INLINE PyObject* __Pyx_PyDict_Items(PyObject* d); /*proto*/
 
 //////////////////// py_dict_items ////////////////////
-//@requires: ObjectHandling.c::PyObjectCallMethod1
 
 static CYTHON_INLINE PyObject* __Pyx_PyDict_Items(PyObject* d) {
     if (PY_MAJOR_VERSION >= 3)
-        return __Pyx_PyObject_CallMethod1((PyObject*)&PyDict_Type, PYIDENT("items"), d);
+        return CALL_UNBOUND_METHOD(PyDict_Type, "items", d);
     else
         return PyDict_Items(d);
 }
@@ -290,10 +332,12 @@ static CYTHON_INLINE PyObject* __Pyx_PyDict_Items(PyObject* d) {
 static CYTHON_INLINE PyObject* __Pyx_PyDict_IterKeys(PyObject* d); /*proto*/
 
 //////////////////// py_dict_iterkeys ////////////////////
-//@requires: ObjectHandling.c::PyObjectCallMethod0
 
 static CYTHON_INLINE PyObject* __Pyx_PyDict_IterKeys(PyObject* d) {
-    return __Pyx_PyObject_CallMethod0(d, (PY_MAJOR_VERSION >= 3) ? PYIDENT("keys") : PYIDENT("iterkeys"));
+    if (PY_MAJOR_VERSION >= 3)
+        return CALL_UNBOUND_METHOD(PyDict_Type, "keys", d);
+    else
+        return CALL_UNBOUND_METHOD(PyDict_Type, "iterkeys", d);
 }
 
 //////////////////// py_dict_itervalues.proto ////////////////////
@@ -301,10 +345,12 @@ static CYTHON_INLINE PyObject* __Pyx_PyDict_IterKeys(PyObject* d) {
 static CYTHON_INLINE PyObject* __Pyx_PyDict_IterValues(PyObject* d); /*proto*/
 
 //////////////////// py_dict_itervalues ////////////////////
-//@requires: ObjectHandling.c::PyObjectCallMethod0
 
 static CYTHON_INLINE PyObject* __Pyx_PyDict_IterValues(PyObject* d) {
-    return __Pyx_PyObject_CallMethod0(d, (PY_MAJOR_VERSION >= 3) ? PYIDENT("values") : PYIDENT("itervalues"));
+    if (PY_MAJOR_VERSION >= 3)
+        return CALL_UNBOUND_METHOD(PyDict_Type, "values", d);
+    else
+        return CALL_UNBOUND_METHOD(PyDict_Type, "itervalues", d);
 }
 
 //////////////////// py_dict_iteritems.proto ////////////////////
@@ -312,10 +358,12 @@ static CYTHON_INLINE PyObject* __Pyx_PyDict_IterValues(PyObject* d) {
 static CYTHON_INLINE PyObject* __Pyx_PyDict_IterItems(PyObject* d); /*proto*/
 
 //////////////////// py_dict_iteritems ////////////////////
-//@requires: ObjectHandling.c::PyObjectCallMethod0
 
 static CYTHON_INLINE PyObject* __Pyx_PyDict_IterItems(PyObject* d) {
-    return __Pyx_PyObject_CallMethod0(d, (PY_MAJOR_VERSION >= 3) ? PYIDENT("items") : PYIDENT("iteritems"));
+    if (PY_MAJOR_VERSION >= 3)
+        return CALL_UNBOUND_METHOD(PyDict_Type, "items", d);
+    else
+        return CALL_UNBOUND_METHOD(PyDict_Type, "iteritems", d);
 }
 
 //////////////////// py_dict_viewkeys.proto ////////////////////
@@ -326,10 +374,12 @@ static CYTHON_INLINE PyObject* __Pyx_PyDict_IterItems(PyObject* d) {
 static CYTHON_INLINE PyObject* __Pyx_PyDict_ViewKeys(PyObject* d); /*proto*/
 
 //////////////////// py_dict_viewkeys ////////////////////
-//@requires: ObjectHandling.c::PyObjectCallMethod0
 
 static CYTHON_INLINE PyObject* __Pyx_PyDict_ViewKeys(PyObject* d) {
-    return __Pyx_PyObject_CallMethod0(d, (PY_MAJOR_VERSION >= 3) ? PYIDENT("keys") : PYIDENT("viewkeys"));
+    if (PY_MAJOR_VERSION >= 3)
+        return CALL_UNBOUND_METHOD(PyDict_Type, "keys", d);
+    else
+        return CALL_UNBOUND_METHOD(PyDict_Type, "viewkeys", d);
 }
 
 //////////////////// py_dict_viewvalues.proto ////////////////////
@@ -340,10 +390,12 @@ static CYTHON_INLINE PyObject* __Pyx_PyDict_ViewKeys(PyObject* d) {
 static CYTHON_INLINE PyObject* __Pyx_PyDict_ViewValues(PyObject* d); /*proto*/
 
 //////////////////// py_dict_viewvalues ////////////////////
-//@requires: ObjectHandling.c::PyObjectCallMethod0
 
 static CYTHON_INLINE PyObject* __Pyx_PyDict_ViewValues(PyObject* d) {
-    return __Pyx_PyObject_CallMethod0(d, (PY_MAJOR_VERSION >= 3) ? PYIDENT("values") : PYIDENT("viewvalues"));
+    if (PY_MAJOR_VERSION >= 3)
+        return CALL_UNBOUND_METHOD(PyDict_Type, "values", d);
+    else
+        return CALL_UNBOUND_METHOD(PyDict_Type, "viewvalues", d);
 }
 
 //////////////////// py_dict_viewitems.proto ////////////////////
@@ -354,10 +406,12 @@ static CYTHON_INLINE PyObject* __Pyx_PyDict_ViewValues(PyObject* d) {
 static CYTHON_INLINE PyObject* __Pyx_PyDict_ViewItems(PyObject* d); /*proto*/
 
 //////////////////// py_dict_viewitems ////////////////////
-//@requires: ObjectHandling.c::PyObjectCallMethod0
 
 static CYTHON_INLINE PyObject* __Pyx_PyDict_ViewItems(PyObject* d) {
-    return __Pyx_PyObject_CallMethod0(d, (PY_MAJOR_VERSION >= 3) ? PYIDENT("items") : PYIDENT("viewitems"));
+    if (PY_MAJOR_VERSION >= 3)
+        return CALL_UNBOUND_METHOD(PyDict_Type, "items", d);
+    else
+        return CALL_UNBOUND_METHOD(PyDict_Type, "viewitems", d);
 }
 
 //////////////////// pyfrozenset_new.proto ////////////////////
@@ -396,3 +450,34 @@ static CYTHON_INLINE PyObject* __Pyx_PyFrozenSet_New(PyObject* it) {
     return PyObject_Call((PyObject*)&PyFrozenSet_Type, $empty_tuple, NULL);
 #endif
 }
+
+
+//////////////////// PySet_Update.proto ////////////////////
+
+static CYTHON_INLINE int __Pyx_PySet_Update(PyObject* set, PyObject* it); /*proto*/
+
+//////////////////// PySet_Update ////////////////////
+
+static CYTHON_INLINE int __Pyx_PySet_Update(PyObject* set, PyObject* it) {
+    PyObject *retval;
+    #if CYTHON_COMPILING_IN_CPYTHON
+    if (PyAnySet_Check(it)) {
+        if (PySet_GET_SIZE(it) == 0)
+            return 0;
+        // fast and safe case: CPython will update our result set and return it
+        retval = PySet_Type.tp_as_number->nb_inplace_or(set, it);
+        if (likely(retval == set)) {
+            Py_DECREF(retval);
+            return 0;
+        }
+        if (unlikely(!retval))
+            return -1;
+        // unusual result, fall through to set.update() call below
+        Py_DECREF(retval);
+    }
+    #endif
+    retval = CALL_UNBOUND_METHOD(PySet_Type, "update", set, it);
+    if (unlikely(!retval)) return -1;
+    Py_DECREF(retval);
+    return 0;
+}
diff --git a/Cython/Utility/CMath.c b/Cython/Utility/CMath.c
new file mode 100644
index 0000000000000000000000000000000000000000..3e2e486dca44b84527c895157bd87f9bfc697d0f
--- /dev/null
+++ b/Cython/Utility/CMath.c
@@ -0,0 +1,93 @@
+
+/////////////// CDivisionWarning.proto ///////////////
+
+static int __Pyx_cdivision_warning(const char *, int); /* proto */
+
+/////////////// CDivisionWarning ///////////////
+
+static int __Pyx_cdivision_warning(const char *filename, int lineno) {
+#if CYTHON_COMPILING_IN_PYPY
+    // avoid compiler warnings
+    filename++; lineno++;
+    return PyErr_Warn(PyExc_RuntimeWarning,
+                     "division with oppositely signed operands, C and Python semantics differ");
+#else
+    return PyErr_WarnExplicit(PyExc_RuntimeWarning,
+                              "division with oppositely signed operands, C and Python semantics differ",
+                              filename,
+                              lineno,
+                              __Pyx_MODULE_NAME,
+                              NULL);
+#endif
+}
+
+
+/////////////// DivInt.proto ///////////////
+
+static CYTHON_INLINE %(type)s __Pyx_div_%(type_name)s(%(type)s, %(type)s); /* proto */
+
+/////////////// DivInt ///////////////
+
+static CYTHON_INLINE %(type)s __Pyx_div_%(type_name)s(%(type)s a, %(type)s b) {
+    %(type)s q = a / b;
+    %(type)s r = a - q*b;
+    q -= ((r != 0) & ((r ^ b) < 0));
+    return q;
+}
+
+
+/////////////// ModInt.proto ///////////////
+
+static CYTHON_INLINE %(type)s __Pyx_mod_%(type_name)s(%(type)s, %(type)s); /* proto */
+
+/////////////// ModInt ///////////////
+
+static CYTHON_INLINE %(type)s __Pyx_mod_%(type_name)s(%(type)s a, %(type)s b) {
+    %(type)s r = a %% b;
+    r += ((r != 0) & ((r ^ b) < 0)) * b;
+    return r;
+}
+
+
+/////////////// ModFloat.proto ///////////////
+
+static CYTHON_INLINE %(type)s __Pyx_mod_%(type_name)s(%(type)s, %(type)s); /* proto */
+
+/////////////// ModFloat ///////////////
+
+static CYTHON_INLINE %(type)s __Pyx_mod_%(type_name)s(%(type)s a, %(type)s b) {
+    %(type)s r = fmod%(math_h_modifier)s(a, b);
+    r += ((r != 0) & ((r < 0) ^ (b < 0))) * b;
+    return r;
+}
+
+
+/////////////// IntPow.proto ///////////////
+
+static CYTHON_INLINE %(type)s %(func_name)s(%(type)s, %(type)s); /* proto */
+
+/////////////// IntPow ///////////////
+
+static CYTHON_INLINE %(type)s %(func_name)s(%(type)s b, %(type)s e) {
+    %(type)s t = b;
+    switch (e) {
+        case 3:
+            t *= b;
+        case 2:
+            t *= b;
+        case 1:
+            return t;
+        case 0:
+            return 1;
+    }
+    #if %(signed)s
+    if (unlikely(e<0)) return 0;
+    #endif
+    t = 1;
+    while (likely(e)) {
+        t *= (b * (e&1)) | ((~e)&1);    /* 1 or b */
+        b *= b;
+        e >>= 1;
+    }
+    return t;
+}
diff --git a/Cython/Utility/CythonFunction.c b/Cython/Utility/CythonFunction.c
index 9cc38f03c6580b5058217a45a0df91909b547ff7..05547987446bf6261fb84df60537d1114842c36d 100644
--- a/Cython/Utility/CythonFunction.c
+++ b/Cython/Utility/CythonFunction.c
@@ -245,17 +245,27 @@ __Pyx_CyFunction_get_code(__pyx_CyFunctionObject *op)
 
 static int
 __Pyx_CyFunction_init_defaults(__pyx_CyFunctionObject *op) {
+    int result = 0;
     PyObject *res = op->defaults_getter((PyObject *) op);
     if (unlikely(!res))
         return -1;
 
     // Cache result
+    #if CYTHON_COMPILING_IN_CPYTHON
     op->defaults_tuple = PyTuple_GET_ITEM(res, 0);
     Py_INCREF(op->defaults_tuple);
     op->defaults_kwdict = PyTuple_GET_ITEM(res, 1);
     Py_INCREF(op->defaults_kwdict);
+    #else
+    op->defaults_tuple = PySequence_ITEM(res, 0);
+    if (unlikely(!op->defaults_tuple)) result = -1;
+    else {
+        op->defaults_kwdict = PySequence_ITEM(res, 1);
+        if (unlikely(!op->defaults_kwdict)) result = -1;
+    }
+    #endif
     Py_DECREF(res);
-    return 0;
+    return result;
 }
 
 static int
@@ -566,21 +576,21 @@ __Pyx_CyFunction_repr(__pyx_CyFunctionObject *op)
 // PyPy does not have this function
 static PyObject * __Pyx_CyFunction_Call(PyObject *func, PyObject *arg, PyObject *kw) {
     PyCFunctionObject* f = (PyCFunctionObject*)func;
-    PyCFunction meth = PyCFunction_GET_FUNCTION(func);
-    PyObject *self = PyCFunction_GET_SELF(func);
+    PyCFunction meth = f->m_ml->ml_meth;
+    PyObject *self = f->m_self;
     Py_ssize_t size;
 
-    switch (PyCFunction_GET_FLAGS(func) & ~(METH_CLASS | METH_STATIC | METH_COEXIST)) {
+    switch (f->m_ml->ml_flags & (METH_VARARGS | METH_KEYWORDS | METH_NOARGS | METH_O)) {
     case METH_VARARGS:
-        if (likely(kw == NULL) || PyDict_Size(kw) == 0)
+        if (likely(kw == NULL || PyDict_Size(kw) == 0))
             return (*meth)(self, arg);
         break;
     case METH_VARARGS | METH_KEYWORDS:
         return (*(PyCFunctionWithKeywords)meth)(self, arg, kw);
     case METH_NOARGS:
-        if (likely(kw == NULL) || PyDict_Size(kw) == 0) {
+        if (likely(kw == NULL || PyDict_Size(kw) == 0)) {
             size = PyTuple_GET_SIZE(arg);
-            if (size == 0)
+            if (likely(size == 0))
                 return (*meth)(self, NULL);
             PyErr_Format(PyExc_TypeError,
                 "%.200s() takes no arguments (%" CYTHON_FORMAT_SSIZE_T "d given)",
@@ -589,10 +599,15 @@ static PyObject * __Pyx_CyFunction_Call(PyObject *func, PyObject *arg, PyObject
         }
         break;
     case METH_O:
-        if (likely(kw == NULL) || PyDict_Size(kw) == 0) {
+        if (likely(kw == NULL || PyDict_Size(kw) == 0)) {
             size = PyTuple_GET_SIZE(arg);
-            if (size == 1)
-                return (*meth)(self, PyTuple_GET_ITEM(arg, 0));
+            if (likely(size == 1)) {
+                PyObject *result, *arg0 = PySequence_ITEM(arg, 0);
+                if (unlikely(!arg0)) return NULL;
+                result = (*meth)(self, arg0);
+                Py_DECREF(arg0);
+                return result;
+            }
             PyErr_Format(PyExc_TypeError,
                 "%.200s() takes exactly one argument (%" CYTHON_FORMAT_SSIZE_T "d given)",
                 f->m_ml->ml_name, size);
@@ -720,21 +735,30 @@ static CYTHON_INLINE void __Pyx_CyFunction_SetAnnotationsDict(PyObject *func, Py
 }
 
 //////////////////// CyFunctionClassCell.proto ////////////////////
-static CYTHON_INLINE void __Pyx_CyFunction_InitClassCell(PyObject *cyfunctions,
-                                                         PyObject *classobj);
+static CYTHON_INLINE int __Pyx_CyFunction_InitClassCell(PyObject *cyfunctions, PyObject *classobj);
 
 //////////////////// CyFunctionClassCell ////////////////////
 //@requires: CythonFunction
 
-static CYTHON_INLINE void __Pyx_CyFunction_InitClassCell(PyObject *cyfunctions, PyObject *classobj) {
-    int i;
+static CYTHON_INLINE int __Pyx_CyFunction_InitClassCell(PyObject *cyfunctions, PyObject *classobj) {
+    Py_ssize_t i, count = PyList_GET_SIZE(cyfunctions);
 
-    for (i = 0; i < PyList_GET_SIZE(cyfunctions); i++) {
-        __pyx_CyFunctionObject *m =
-            (__pyx_CyFunctionObject *) PyList_GET_ITEM(cyfunctions, i);
-        m->func_classobj = classobj;
+    for (i = 0; i < count; i++) {
+        __pyx_CyFunctionObject *m = (__pyx_CyFunctionObject *)
+#if CYTHON_COMPILING_IN_CPYTHON
+            PyList_GET_ITEM(cyfunctions, i);
+#else
+            PySequence_ITEM(cyfunctions, i);
+        if (unlikely(!m))
+            return -1;
+#endif
         Py_INCREF(classobj);
+        m->func_classobj = classobj;
+#if !CYTHON_COMPILING_IN_CPYTHON
+        Py_DECREF((PyObject*)m);
+#endif
     }
+    return 0;
 }
 
 //////////////////// FusedFunction.proto ////////////////////
@@ -886,9 +910,15 @@ __pyx_FusedFunction_getitem(__pyx_FusedFunctionObject *self, PyObject *idx)
             return NULL;
 
         for (i = 0; i < n; i++) {
+#if CYTHON_COMPILING_IN_CPYTHON
             PyObject *item = PyTuple_GET_ITEM(idx, i);
-
+#else
+            PyObject *item = PySequence_ITEM(idx, i);
+#endif
             string = _obj_to_str(item);
+#if !CYTHON_COMPILING_IN_CPYTHON
+            Py_DECREF(item);
+#endif
             if (!string || PyList_Append(list, string) < 0)
                 goto __pyx_err;
 
@@ -998,12 +1028,19 @@ __pyx_FusedFunction_call(PyObject *func, PyObject *args, PyObject *kw)
             return NULL;
 
         self = binding_func->self;
+#if !CYTHON_COMPILING_IN_CPYTHON
+        Py_INCREF(self);
+#endif
         Py_INCREF(self);
         PyTuple_SET_ITEM(new_args, 0, self);
 
         for (i = 0; i < argc; i++) {
+#if CYTHON_COMPILING_IN_CPYTHON
             PyObject *item = PyTuple_GET_ITEM(args, i);
             Py_INCREF(item);
+#else
+            PyObject *item = PySequence_ITEM(args, i);  if (unlikely(!item)) goto bad;
+#endif
             PyTuple_SET_ITEM(new_args, i + 1, item);
         }
 
@@ -1014,30 +1051,42 @@ __pyx_FusedFunction_call(PyObject *func, PyObject *args, PyObject *kw)
             PyErr_SetString(PyExc_TypeError, "Need at least one argument, 0 given.");
             return NULL;
         }
+#if CYTHON_COMPILING_IN_CPYTHON
         self = PyTuple_GET_ITEM(args, 0);
+#else
+        self = PySequence_ITEM(args, 0);  if (unlikely(!self)) return NULL;
+#endif
     }
 
-    if (self && !is_classmethod && !is_staticmethod &&
-            !PyObject_IsInstance(self, binding_func->type)) {
-        PyErr_Format(PyExc_TypeError,
-                     "First argument should be of type %.200s, got %.200s.",
-                     ((PyTypeObject *) binding_func->type)->tp_name,
-                     self->ob_type->tp_name);
-        goto __pyx_err;
+    if (self && !is_classmethod && !is_staticmethod) {
+        int is_instance = PyObject_IsInstance(self, binding_func->type);
+        if (unlikely(!is_instance)) {
+            PyErr_Format(PyExc_TypeError,
+                         "First argument should be of type %.200s, got %.200s.",
+                         ((PyTypeObject *) binding_func->type)->tp_name,
+                         self->ob_type->tp_name);
+            goto bad;
+        } else if (unlikely(is_instance == -1)) {
+            goto bad;
+        }
     }
+#if !CYTHON_COMPILING_IN_CPYTHON
+    Py_XDECREF(self);
+    self = NULL;
+#endif
 
     if (binding_func->__signatures__) {
         PyObject *tup = PyTuple_Pack(4, binding_func->__signatures__, args,
                                         kw == NULL ? Py_None : kw,
                                         binding_func->func.defaults_tuple);
         if (!tup)
-            goto __pyx_err;
+            goto bad;
 
         new_func = (__pyx_FusedFunctionObject *) __pyx_FusedFunction_callfunction(func, tup, NULL);
         Py_DECREF(tup);
 
         if (!new_func)
-            goto __pyx_err;
+            goto bad;
 
         Py_XINCREF(binding_func->func.func_classobj);
         Py_CLEAR(new_func->func.func_classobj);
@@ -1047,7 +1096,10 @@ __pyx_FusedFunction_call(PyObject *func, PyObject *args, PyObject *kw)
     }
 
     result = __pyx_FusedFunction_callfunction(func, args, kw);
-__pyx_err:
+bad:
+#if !CYTHON_COMPILING_IN_CPYTHON
+    Py_XDECREF(self);
+#endif
     Py_XDECREF(new_args);
     Py_XDECREF((PyObject *) new_func);
     return result;
diff --git a/Cython/Utility/Exceptions.c b/Cython/Utility/Exceptions.c
index 61929406aa39418c27d6aacabbc73db49e82b90b..b28a5d1943cc19b302de9f09b8bf7037fca78a0a 100644
--- a/Cython/Utility/Exceptions.c
+++ b/Cython/Utility/Exceptions.c
@@ -144,11 +144,15 @@ static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb, PyObject
         if (value && PyExceptionInstance_Check(value)) {
             instance_class = (PyObject*) Py_TYPE(value);
             if (instance_class != type) {
-                if (PyObject_IsSubclass(instance_class, type)) {
+                int is_subclass = PyObject_IsSubclass(instance_class, type);
+                if (!is_subclass) {
+                    instance_class = NULL;
+                } else if (unlikely(is_subclass == -1)) {
+                    // error on subclass test
+                    goto bad;
+                } else {
                     // believe the instance
                     type = instance_class;
-                } else {
-                    instance_class = NULL;
                 }
             }
         }
diff --git a/Cython/Utility/FunctionArguments.c b/Cython/Utility/FunctionArguments.c
index d0ea7b86f95fb2974d5115354013162e2d121930..e2055815d2d8e0b28ab52af79673693808f0f854 100644
--- a/Cython/Utility/FunctionArguments.c
+++ b/Cython/Utility/FunctionArguments.c
@@ -110,6 +110,17 @@ static void __Pyx_RaiseDoubleKeywordsError(
 }
 
 
+//////////////////// RaiseMappingExpected.proto ////////////////////
+
+static void __Pyx_RaiseMappingExpectedError(PyObject* arg); /*proto*/
+
+//////////////////// RaiseMappingExpected ////////////////////
+
+static void __Pyx_RaiseMappingExpectedError(PyObject* arg) {
+    PyErr_Format(PyExc_TypeError, "'%.200s' object is not a mapping", Py_TYPE(arg)->tp_name);
+}
+
+
 //////////////////// KeywordStringCheck.proto ////////////////////
 
 static CYTHON_INLINE int __Pyx_CheckKeywordStrings(PyObject *kwdict, const char* function_name, int kw_allowed); /*proto*/
@@ -290,3 +301,58 @@ invalid_keyword:
 bad:
     return -1;
 }
+
+
+//////////////////// MergeKeywords.proto ////////////////////
+
+static int __Pyx_MergeKeywords(PyObject *kwdict, PyObject *source_mapping); /*proto*/
+
+//////////////////// MergeKeywords ////////////////////
+//@requires: RaiseDoubleKeywords
+//@requires: Optimize.c::dict_iter
+
+static int __Pyx_MergeKeywords(PyObject *kwdict, PyObject *source_mapping) {
+    PyObject *iter, *key = NULL, *value = NULL;
+    int source_is_dict, result;
+    Py_ssize_t orig_length, ppos = 0;
+
+    iter = __Pyx_dict_iterator(source_mapping, 0, PYIDENT("items"), &orig_length, &source_is_dict);
+    if (unlikely(!iter)) {
+        // slow fallback: try converting to dict, then iterate
+        PyObject *args;
+        if (!PyErr_ExceptionMatches(PyExc_AttributeError)) goto bad;
+        PyErr_Clear();
+        args = PyTuple_Pack(1, source_mapping);
+        if (likely(args)) {
+            PyObject *fallback = PyObject_Call((PyObject*)&PyDict_Type, args, NULL);
+            Py_DECREF(args);
+            if (likely(fallback)) {
+                iter = __Pyx_dict_iterator(fallback, 1, PYIDENT("items"), &orig_length, &source_is_dict);
+                Py_DECREF(fallback);
+            }
+        }
+        if (unlikely(!iter)) goto bad;
+    }
+
+    while (1) {
+        result = __Pyx_dict_iter_next(iter, orig_length, &ppos, &key, &value, NULL, source_is_dict);
+        if (unlikely(result < 0)) goto bad;
+        if (!result) break;
+
+        if (unlikely(PyDict_Contains(kwdict, key))) {
+            __Pyx_RaiseDoubleKeywordsError("function", key);
+            result = -1;
+        } else {
+            result = PyDict_SetItem(kwdict, key, value);
+        }
+        Py_DECREF(key);
+        Py_DECREF(value);
+        if (unlikely(result < 0)) goto bad;
+    }
+    Py_XDECREF(iter);
+    return 0;
+
+bad:
+    Py_XDECREF(iter);
+    return -1;
+}
diff --git a/Cython/Utility/Generator.c b/Cython/Utility/Generator.c
index 03105705790567569d672c4467c1d8aa66d01d9f..589a143bf2bea30e7fb7d8e3598890947678898c 100644
--- a/Cython/Utility/Generator.c
+++ b/Cython/Utility/Generator.c
@@ -64,6 +64,8 @@ typedef struct {
     char is_running;
 } __pyx_GeneratorObject;
 
+static PyTypeObject *__pyx_GeneratorType = 0;
+
 static __pyx_GeneratorObject *__Pyx_Generator_New(__pyx_generator_body_t body,
                                                   PyObject *closure, PyObject *name, PyObject *qualname);
 static int __pyx_Generator_init(void);
@@ -80,15 +82,15 @@ static int __Pyx_PyGen_FetchStopIterationValue(PyObject **pvalue);
 //@requires: Exceptions.c::SwapException
 //@requires: Exceptions.c::RaiseException
 //@requires: ObjectHandling.c::PyObjectCallMethod1
+//@requires: ObjectHandling.c::PyObjectGetAttrStr
 //@requires: CommonTypes.c::FetchCommonType
+//@requires: PatchGeneratorABC
 
 static PyObject *__Pyx_Generator_Next(PyObject *self);
 static PyObject *__Pyx_Generator_Send(PyObject *self, PyObject *value);
 static PyObject *__Pyx_Generator_Close(PyObject *self);
 static PyObject *__Pyx_Generator_Throw(PyObject *gen, PyObject *args);
 
-static PyTypeObject *__pyx_GeneratorType = 0;
-
 #define __Pyx_Generator_CheckExact(obj) (Py_TYPE(obj) == __pyx_GeneratorType)
 #define __Pyx_Generator_Undelegate(gen) Py_CLEAR((gen)->yieldfrom)
 
@@ -102,6 +104,7 @@ static PyTypeObject *__pyx_GeneratorType = 0;
 static int __Pyx_PyGen_FetchStopIterationValue(PyObject **pvalue) {
     PyObject *et, *ev, *tb;
     PyObject *value = NULL;
+    int result;
 
     __Pyx_ErrFetch(&et, &ev, &tb);
 
@@ -113,15 +116,21 @@ static int __Pyx_PyGen_FetchStopIterationValue(PyObject **pvalue) {
         return 0;
     }
 
-    if (unlikely(et != PyExc_StopIteration) &&
-            unlikely(!PyErr_GivenExceptionMatches(et, PyExc_StopIteration))) {
-        __Pyx_ErrRestore(et, ev, tb);
-        return -1;
-    }
-
     // most common case: plain StopIteration without or with separate argument
     if (likely(et == PyExc_StopIteration)) {
-        if (likely(!ev) || !PyObject_IsInstance(ev, PyExc_StopIteration)) {
+        int error = 0;
+#if PY_VERSION_HEX >= 0x030300A0
+        if (ev && Py_TYPE(ev) == (PyTypeObject*)PyExc_StopIteration) {
+            value = ((PyStopIterationObject *)ev)->value;
+            Py_INCREF(value);
+            Py_DECREF(ev);
+            Py_XDECREF(tb);
+            Py_DECREF(et);
+            *pvalue = value;
+            return 0;
+        }
+#endif
+        if (!ev || !(error = PyObject_IsInstance(ev, PyExc_StopIteration))) {
             // PyErr_SetObject() and friends put the value directly into ev
             if (!ev) {
                 Py_INCREF(Py_None);
@@ -132,26 +141,40 @@ static int __Pyx_PyGen_FetchStopIterationValue(PyObject **pvalue) {
             *pvalue = ev;
             return 0;
         }
+        if (unlikely(error == -1)) {
+            // error during isinstance() check
+            return -1;
+        }
+    } else if (!PyErr_GivenExceptionMatches(et, PyExc_StopIteration)) {
+        __Pyx_ErrRestore(et, ev, tb);
+        return -1;
     }
+
     // otherwise: normalise and check what that gives us
     PyErr_NormalizeException(&et, &ev, &tb);
-    if (unlikely(!PyObject_IsInstance(ev, PyExc_StopIteration))) {
+    result = PyObject_IsInstance(ev, PyExc_StopIteration);
+    if (unlikely(!result)) {
         // looks like normalisation failed - raise the new exception
         __Pyx_ErrRestore(et, ev, tb);
         return -1;
     }
     Py_XDECREF(tb);
     Py_DECREF(et);
+    if (unlikely(result == -1)) {
+        // error during isinstance() check
+        Py_DECREF(ev);
+        return -1;
+    }
 #if PY_VERSION_HEX >= 0x030300A0
     value = ((PyStopIterationObject *)ev)->value;
     Py_INCREF(value);
     Py_DECREF(ev);
 #else
     {
-        PyObject* args = PyObject_GetAttr(ev, PYIDENT("args"));
+        PyObject* args = __Pyx_PyObject_GetAttrStr(ev, PYIDENT("args"));
         Py_DECREF(ev);
         if (likely(args)) {
-            value = PyObject_GetItem(args, 0);
+            value = PySequence_GetItem(args, 0);
             Py_DECREF(args);
         }
         if (unlikely(!value)) {
@@ -260,6 +283,15 @@ PyObject *__Pyx_Generator_SendEx(__pyx_GeneratorObject *self, PyObject *value) {
     return retval;
 }
 
+static CYTHON_INLINE
+PyObject *__Pyx_Generator_MethodReturn(PyObject *retval) {
+    if (unlikely(!retval && !PyErr_Occurred())) {
+        // method call must not terminate with NULL without setting an exception
+        PyErr_SetNone(PyExc_StopIteration);
+    }
+    return retval;
+}
+
 static CYTHON_INLINE
 PyObject *__Pyx_Generator_FinishDelegation(__pyx_GeneratorObject *gen) {
     PyObject *ret;
@@ -295,6 +327,7 @@ static PyObject *__Pyx_Generator_Next(PyObject *self) {
 }
 
 static PyObject *__Pyx_Generator_Send(PyObject *self, PyObject *value) {
+    PyObject *retval;
     __pyx_GeneratorObject *gen = (__pyx_GeneratorObject*) self;
     PyObject *yf = gen->yieldfrom;
     if (unlikely(__Pyx_Generator_CheckRunning(gen)))
@@ -317,9 +350,11 @@ static PyObject *__Pyx_Generator_Send(PyObject *self, PyObject *value) {
         if (likely(ret)) {
             return ret;
         }
-        return __Pyx_Generator_FinishDelegation(gen);
+        retval = __Pyx_Generator_FinishDelegation(gen);
+    } else {
+        retval = __Pyx_Generator_SendEx(gen, value);
     }
-    return __Pyx_Generator_SendEx(gen, value);
+    return __Pyx_Generator_MethodReturn(retval);
 }
 
 //   This helper function is used by gen_close and gen_throw to
@@ -335,7 +370,7 @@ static int __Pyx_Generator_CloseIter(__pyx_GeneratorObject *gen, PyObject *yf) {
     } else {
         PyObject *meth;
         gen->is_running = 1;
-        meth = PyObject_GetAttr(yf, PYIDENT("close"));
+        meth = __Pyx_PyObject_GetAttrStr(yf, PYIDENT("close"));
         if (unlikely(!meth)) {
             if (!PyErr_ExceptionMatches(PyExc_AttributeError)) {
                 PyErr_WriteUnraisable(yf);
@@ -413,14 +448,14 @@ static PyObject *__Pyx_Generator_Throw(PyObject *self, PyObject *args) {
             Py_DECREF(yf);
             __Pyx_Generator_Undelegate(gen);
             if (err < 0)
-                return __Pyx_Generator_SendEx(gen, NULL);
+                return __Pyx_Generator_MethodReturn(__Pyx_Generator_SendEx(gen, NULL));
             goto throw_here;
         }
         gen->is_running = 1;
         if (__Pyx_Generator_CheckExact(yf)) {
             ret = __Pyx_Generator_Throw(yf, args);
         } else {
-            PyObject *meth = PyObject_GetAttr(yf, PYIDENT("throw"));
+            PyObject *meth = __Pyx_PyObject_GetAttrStr(yf, PYIDENT("throw"));
             if (unlikely(!meth)) {
                 Py_DECREF(yf);
                 if (!PyErr_ExceptionMatches(PyExc_AttributeError)) {
@@ -440,11 +475,11 @@ static PyObject *__Pyx_Generator_Throw(PyObject *self, PyObject *args) {
         if (!ret) {
             ret = __Pyx_Generator_FinishDelegation(gen);
         }
-        return ret;
+        return __Pyx_Generator_MethodReturn(ret);
     }
 throw_here:
     __Pyx_Raise(typ, val, tb, NULL);
-    return __Pyx_Generator_SendEx(gen, NULL);
+    return __Pyx_Generator_MethodReturn(__Pyx_Generator_SendEx(gen, NULL));
 }
 
 static int __Pyx_Generator_traverse(PyObject *self, visitproc visit, void *arg) {
@@ -703,7 +738,7 @@ static PyTypeObject __pyx_GeneratorType_type = {
 static __pyx_GeneratorObject *__Pyx_Generator_New(__pyx_generator_body_t body,
                                                   PyObject *closure, PyObject *name, PyObject *qualname) {
     __pyx_GeneratorObject *gen =
-        PyObject_GC_New(__pyx_GeneratorObject, &__pyx_GeneratorType_type);
+        PyObject_GC_New(__pyx_GeneratorObject, __pyx_GeneratorType);
 
     if (gen == NULL)
         return NULL;
@@ -739,3 +774,289 @@ static int __pyx_Generator_init(void) {
     }
     return 0;
 }
+
+
+/////////////// ReturnWithStopIteration.proto ///////////////
+
+#if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX < 0x030500B1
+// CPython 3.3 <= x < 3.5b1 crash in yield-from when the StopIteration is not instantiated
+#define __Pyx_ReturnWithStopIteration(value)  \
+    if (value == Py_None) PyErr_SetNone(PyExc_StopIteration); else __Pyx__ReturnWithStopIteration(value)
+static void __Pyx__ReturnWithStopIteration(PyObject* value); /*proto*/
+#else
+#define __Pyx_ReturnWithStopIteration(value)  PyErr_SetObject(PyExc_StopIteration, value)
+#endif
+
+/////////////// ReturnWithStopIteration ///////////////
+
+#if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX < 0x030500B1
+static void __Pyx__ReturnWithStopIteration(PyObject* value) {
+    PyObject *exc, *args;
+    args = PyTuple_New(1);
+    if (!args) return;
+    Py_INCREF(value);
+    PyTuple_SET_ITEM(args, 0, value);
+    exc = PyObject_Call(PyExc_StopIteration, args, NULL);
+    Py_DECREF(args);
+    if (!exc) return;
+    Py_INCREF(PyExc_StopIteration);
+    PyErr_Restore(PyExc_StopIteration, exc, NULL);
+}
+#endif
+
+
+//////////////////// PatchModuleWithGenerator.proto ////////////////////
+
+static PyObject* __Pyx_Generator_patch_module(PyObject* module, const char* py_code); /*proto*/
+
+//////////////////// PatchModuleWithGenerator ////////////////////
+//@substitute: naming
+
+static PyObject* __Pyx_Generator_patch_module(PyObject* module, const char* py_code) {
+#ifdef __Pyx_Generator_USED
+    PyObject *globals, *result_obj;
+    globals = PyDict_New();  if (unlikely(!globals)) goto ignore;
+    if (unlikely(PyDict_SetItemString(globals, "_cython_generator_type", (PyObject*)__pyx_GeneratorType) < 0)) goto ignore;
+    if (unlikely(PyDict_SetItemString(globals, "_module", module) < 0)) goto ignore;
+    if (unlikely(PyDict_SetItemString(globals, "__builtins__", $builtins_cname) < 0)) goto ignore;
+    result_obj = PyRun_String(py_code, Py_file_input, globals, globals);
+    if (unlikely(!result_obj)) goto ignore;
+    Py_DECREF(result_obj);
+    Py_DECREF(globals);
+    return module;
+
+ignore:
+    Py_XDECREF(globals);
+    PyErr_WriteUnraisable(module);
+    if (unlikely(PyErr_WarnEx(PyExc_RuntimeWarning, "Cython module failed to patch module with custom type", 1) < 0)) {
+        Py_DECREF(module);
+        module = NULL;
+    }
+#else
+    // avoid "unused" warning
+    py_code++;
+#endif
+    return module;
+}
+
+
+//////////////////// PatchGeneratorABC.proto ////////////////////
+
+// patch 'collections.abc' if it lacks generator support
+// see https://bugs.python.org/issue24018
+static int __Pyx_patch_abc(void); /*proto*/
+
+//////////////////// PatchGeneratorABC ////////////////////
+//@requires: PatchModuleWithGenerator
+
+static int __Pyx_patch_abc(void) {
+#if defined(__Pyx_Generator_USED) && (!defined(CYTHON_PATCH_ABC) || CYTHON_PATCH_ABC)
+    static int abc_patched = 0;
+    if (!abc_patched) {
+        PyObject *module;
+        module = PyImport_ImportModule((PY_VERSION_HEX >= 0x03030000) ? "collections.abc" : "collections");
+        if (!module) {
+            PyErr_WriteUnraisable(NULL);
+            if (unlikely(PyErr_WarnEx(PyExc_RuntimeWarning,
+                    ((PY_VERSION_HEX >= 0x03030000) ?
+                        "Cython module failed to patch collections.abc.Generator" :
+                        "Cython module failed to patch collections.Generator"), 1) < 0)) {
+                return -1;
+            }
+        } else {
+            PyObject *abc = PyObject_GetAttrString(module, "Generator");
+            if (abc) {
+                abc_patched = 1;
+                Py_DECREF(abc);
+            } else {
+                PyErr_Clear();
+                module = __Pyx_Generator_patch_module(
+                    module, CSTRING("""\
+def mk_gen():
+    from abc import abstractmethod
+
+    required_methods = (
+        '__iter__', '__next__' if hasattr(iter(()), '__next__') else 'next',
+         'send', 'throw', 'close')
+
+    class Generator(_module.Iterator):
+        __slots__ = ()
+
+        if '__next__' in required_methods:
+            def __next__(self):
+                return self.send(None)
+        else:
+            def next(self):
+                return self.send(None)
+
+        @abstractmethod
+        def send(self, value):
+            raise StopIteration
+
+        @abstractmethod
+        def throw(self, typ, val=None, tb=None):
+            if val is None:
+                if tb is None:
+                    raise typ
+                val = typ()
+            if tb is not None:
+                val = val.with_traceback(tb)
+            raise val
+
+        def close(self):
+            try:
+                self.throw(GeneratorExit)
+            except (GeneratorExit, StopIteration):
+                pass
+            else:
+                raise RuntimeError('generator ignored GeneratorExit')
+
+        @classmethod
+        def __subclasshook__(cls, C):
+            if cls is Generator:
+                mro = C.__mro__
+                for method in required_methods:
+                    for base in mro:
+                        if method in base.__dict__:
+                            break
+                    else:
+                        return NotImplemented
+                return True
+            return NotImplemented
+
+    generator = type((lambda: (yield))())
+    Generator.register(generator)
+    Generator.register(_cython_generator_type)
+    return Generator
+
+_module.Generator = mk_gen()
+""")
+                );
+                abc_patched = 1;
+                if (unlikely(!module))
+                    return -1;
+            }
+            Py_DECREF(module);
+        }
+    }
+#else
+    // avoid "unused" warning for __Pyx_Generator_patch_module()
+    if (0) __Pyx_Generator_patch_module(NULL, NULL);
+#endif
+    return 0;
+}
+
+
+//////////////////// PatchAsyncIO.proto ////////////////////
+
+// run after importing "asyncio" to patch Cython generator support into it
+static PyObject* __Pyx_patch_asyncio(PyObject* module); /*proto*/
+
+//////////////////// PatchAsyncIO ////////////////////
+//@requires: PatchModuleWithGenerator
+//@requires: PatchInspect
+
+static PyObject* __Pyx_patch_asyncio(PyObject* module) {
+#if defined(__Pyx_Generator_USED) && (!defined(CYTHON_PATCH_ASYNCIO) || CYTHON_PATCH_ASYNCIO)
+    PyObject *patch_module = NULL;
+    static int asyncio_patched = 0;
+    if (unlikely((!asyncio_patched) && module)) {
+        PyObject *package;
+        package = __Pyx_Import(PYIDENT("asyncio.coroutines"), NULL, 0);
+        if (package) {
+            patch_module = __Pyx_Generator_patch_module(
+                PyObject_GetAttrString(package, "coroutines"), CSTRING("""\
+old_types = getattr(_module, '_COROUTINE_TYPES', None)
+if old_types is not None and _cython_generator_type not in old_types:
+    _module._COROUTINE_TYPES = type(old_types) (tuple(old_types) + (_cython_generator_type,))
+""")
+            );
+        #if PY_VERSION_HEX < 0x03050000
+        } else {
+            // Py3.4 used to have asyncio.tasks instead of asyncio.coroutines
+            PyErr_Clear();
+            package = __Pyx_Import(PYIDENT("asyncio.tasks"), NULL, 0);
+            if (unlikely(!package)) goto asyncio_done;
+            patch_module = __Pyx_Generator_patch_module(
+                PyObject_GetAttrString(package, "tasks"), CSTRING("""\
+if (hasattr(_module, 'iscoroutine') and
+        getattr(_module.iscoroutine, '_cython_generator_type', None) is not _cython_generator_type):
+    def cy_wrap(orig_func, cython_generator_type=_cython_generator_type, type=type):
+        def cy_iscoroutine(obj): return type(obj) is cython_generator_type or orig_func(obj)
+        cy_iscoroutine._cython_generator_type = cython_generator_type
+        return cy_iscoroutine
+    _module.iscoroutine = cy_wrap(_module.iscoroutine)
+""")
+            );
+        #endif
+        }
+        Py_DECREF(package);
+        if (unlikely(!patch_module)) goto ignore;
+#if PY_VERSION_HEX < 0x03050000
+asyncio_done:
+        PyErr_Clear();
+#endif
+        asyncio_patched = 1;
+        // now patch inspect.isgenerator() by looking up the imported module in the patched asyncio module
+        {
+            PyObject *inspect_module;
+            if (patch_module) {
+                inspect_module = PyObject_GetAttrString(patch_module, "inspect");
+                Py_DECREF(patch_module);
+            } else {
+                inspect_module = __Pyx_Import(PYIDENT("inspect"), NULL, 0);
+            }
+            if (unlikely(!inspect_module)) goto ignore;
+            inspect_module = __Pyx_patch_inspect(inspect_module);
+            if (unlikely(!inspect_module)) {
+                Py_DECREF(module);
+                module = NULL;
+            }
+            Py_DECREF(inspect_module);
+        }
+    }
+    return module;
+ignore:
+    PyErr_WriteUnraisable(module);
+    if (unlikely(PyErr_WarnEx(PyExc_RuntimeWarning, "Cython module failed to patch asyncio package with custom generator type", 1) < 0)) {
+        Py_DECREF(module);
+        module = NULL;
+    }
+#else
+    // avoid "unused" warning for __Pyx_Generator_patch_module()
+    if (0) return __Pyx_Generator_patch_module(module, NULL);
+#endif
+    return module;
+}
+
+
+//////////////////// PatchInspect.proto ////////////////////
+
+// run after importing "inspect" to patch Cython generator support into it
+static PyObject* __Pyx_patch_inspect(PyObject* module); /*proto*/
+
+//////////////////// PatchInspect ////////////////////
+//@requires: PatchModuleWithGenerator
+
+static PyObject* __Pyx_patch_inspect(PyObject* module) {
+#if defined(__Pyx_Generator_USED) && (!defined(CYTHON_PATCH_INSPECT) || CYTHON_PATCH_INSPECT)
+    static int inspect_patched = 0;
+    if (unlikely((!inspect_patched) && module)) {
+        module = __Pyx_Generator_patch_module(
+            module, CSTRING("""\
+if getattr(_module.isgenerator, '_cython_generator_type', None) is not _cython_generator_type:
+    def cy_wrap(orig_func, cython_generator_type=_cython_generator_type, type=type):
+        def cy_isgenerator(obj): return type(obj) is cython_generator_type or orig_func(obj)
+        cy_isgenerator._cython_generator_type = cython_generator_type
+        return cy_isgenerator
+    _module.isgenerator = cy_wrap(_module.isgenerator)
+""")
+        );
+        inspect_patched = 1;
+    }
+#else
+    // avoid "unused" warning for __Pyx_Generator_patch_module()
+    if (0) return __Pyx_Generator_patch_module(module, NULL);
+#endif
+    return module;
+}
diff --git a/Cython/Utility/ImportExport.c b/Cython/Utility/ImportExport.c
index 7273d8301a0acde540d968d3ab4ed8f2df652f82..d11ca2adc167f1283c0f997d1b4242f2426eaa46 100644
--- a/Cython/Utility/ImportExport.c
+++ b/Cython/Utility/ImportExport.c
@@ -113,6 +113,124 @@ static PyObject* __Pyx_ImportFrom(PyObject* module, PyObject* name) {
 }
 
 
+/////////////// ImportStar ///////////////
+//@substitute: naming
+
+/* import_all_from is an unexposed function from ceval.c */
+
+static int
+__Pyx_import_all_from(PyObject *locals, PyObject *v)
+{
+    PyObject *all = PyObject_GetAttrString(v, "__all__");
+    PyObject *dict, *name, *value;
+    int skip_leading_underscores = 0;
+    int pos, err;
+
+    if (all == NULL) {
+        if (!PyErr_ExceptionMatches(PyExc_AttributeError))
+            return -1; /* Unexpected error */
+        PyErr_Clear();
+        dict = PyObject_GetAttrString(v, "__dict__");
+        if (dict == NULL) {
+            if (!PyErr_ExceptionMatches(PyExc_AttributeError))
+                return -1;
+            PyErr_SetString(PyExc_ImportError,
+            "from-import-* object has no __dict__ and no __all__");
+            return -1;
+        }
+#if PY_MAJOR_VERSION < 3
+        all = PyObject_CallMethod(dict, (char *)"keys", NULL);
+#else
+        all = PyMapping_Keys(dict);
+#endif
+        Py_DECREF(dict);
+        if (all == NULL)
+            return -1;
+        skip_leading_underscores = 1;
+    }
+
+    for (pos = 0, err = 0; ; pos++) {
+        name = PySequence_GetItem(all, pos);
+        if (name == NULL) {
+            if (!PyErr_ExceptionMatches(PyExc_IndexError))
+                err = -1;
+            else
+                PyErr_Clear();
+            break;
+        }
+        if (skip_leading_underscores &&
+#if PY_MAJOR_VERSION < 3
+            PyString_Check(name) &&
+            PyString_AS_STRING(name)[0] == '_')
+#else
+            PyUnicode_Check(name) &&
+            PyUnicode_AS_UNICODE(name)[0] == '_')
+#endif
+        {
+            Py_DECREF(name);
+            continue;
+        }
+        value = PyObject_GetAttr(v, name);
+        if (value == NULL)
+            err = -1;
+        else if (PyDict_CheckExact(locals))
+            err = PyDict_SetItem(locals, name, value);
+        else
+            err = PyObject_SetItem(locals, name, value);
+        Py_DECREF(name);
+        Py_XDECREF(value);
+        if (err != 0)
+            break;
+    }
+    Py_DECREF(all);
+    return err;
+}
+
+
+static int ${import_star}(PyObject* m) {
+
+    int i;
+    int ret = -1;
+    char* s;
+    PyObject *locals = 0;
+    PyObject *list = 0;
+#if PY_MAJOR_VERSION >= 3
+    PyObject *utf8_name = 0;
+#endif
+    PyObject *name;
+    PyObject *item;
+
+    locals = PyDict_New();              if (!locals) goto bad;
+    if (__Pyx_import_all_from(locals, m) < 0) goto bad;
+    list = PyDict_Items(locals);        if (!list) goto bad;
+
+    for(i=0; i<PyList_GET_SIZE(list); i++) {
+        name = PyTuple_GET_ITEM(PyList_GET_ITEM(list, i), 0);
+        item = PyTuple_GET_ITEM(PyList_GET_ITEM(list, i), 1);
+#if PY_MAJOR_VERSION >= 3
+        utf8_name = PyUnicode_AsUTF8String(name);
+        if (!utf8_name) goto bad;
+        s = PyBytes_AS_STRING(utf8_name);
+        if (${import_star_set}(item, name, s) < 0) goto bad;
+        Py_DECREF(utf8_name); utf8_name = 0;
+#else
+        s = PyString_AsString(name);
+        if (!s) goto bad;
+        if (${import_star_set}(item, name, s) < 0) goto bad;
+#endif
+    }
+    ret = 0;
+
+bad:
+    Py_XDECREF(locals);
+    Py_XDECREF(list);
+#if PY_MAJOR_VERSION >= 3
+    Py_XDECREF(utf8_name);
+#endif
+    return ret;
+}
+
+
 /////////////// ModuleImport.proto ///////////////
 
 static PyObject *__Pyx_ImportModule(const char *name); /*proto*/
diff --git a/Cython/Utility/ModuleSetupCode.c b/Cython/Utility/ModuleSetupCode.c
index 3ae8a0c71617da62c39b44efe09a1453b49b7258..61bccda9631bbeeb2aac5a82ae70a2f053bf4f9b 100644
--- a/Cython/Utility/ModuleSetupCode.c
+++ b/Cython/Utility/ModuleSetupCode.c
@@ -40,6 +40,10 @@
 #define CYTHON_COMPILING_IN_CPYTHON 1
 #endif
 
+#if !defined(CYTHON_USE_PYLONG_INTERNALS) && CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x02070000
+#define CYTHON_USE_PYLONG_INTERNALS 1
+#endif
+
 #if CYTHON_COMPILING_IN_PYPY && PY_VERSION_HEX < 0x02070600 && !defined(Py_OptimizeFlag)
 #define Py_OptimizeFlag 0
 #endif
@@ -59,16 +63,16 @@
   #define __Pyx_DefaultClassType PyType_Type
 #endif
 
-#if !defined(Py_TPFLAGS_CHECKTYPES)
+#ifndef Py_TPFLAGS_CHECKTYPES
   #define Py_TPFLAGS_CHECKTYPES 0
 #endif
-#if !defined(Py_TPFLAGS_HAVE_INDEX)
+#ifndef Py_TPFLAGS_HAVE_INDEX
   #define Py_TPFLAGS_HAVE_INDEX 0
 #endif
-#if !defined(Py_TPFLAGS_HAVE_NEWBUFFER)
+#ifndef Py_TPFLAGS_HAVE_NEWBUFFER
   #define Py_TPFLAGS_HAVE_NEWBUFFER 0
 #endif
-#if !defined(Py_TPFLAGS_HAVE_FINALIZE)
+#ifndef Py_TPFLAGS_HAVE_FINALIZE
   #define Py_TPFLAGS_HAVE_FINALIZE 0
 #endif
 
@@ -96,13 +100,14 @@
 #if CYTHON_COMPILING_IN_PYPY
   #define __Pyx_PyUnicode_Concat(a, b)      PyNumber_Add(a, b)
   #define __Pyx_PyUnicode_ConcatSafe(a, b)  PyNumber_Add(a, b)
-  // PyPy doesn't handle frozenset() in PySet_Size()
-  #define __Pyx_PyFrozenSet_Size(s)         PyObject_Size(s)
 #else
   #define __Pyx_PyUnicode_Concat(a, b)      PyUnicode_Concat(a, b)
   #define __Pyx_PyUnicode_ConcatSafe(a, b)  ((unlikely((a) == Py_None) || unlikely((b) == Py_None)) ? \
       PyNumber_Add(a, b) : __Pyx_PyUnicode_Concat(a, b))
-  #define __Pyx_PyFrozenSet_Size(s)         PySet_Size(s)
+#endif
+
+#if CYTHON_COMPILING_IN_PYPY && !defined(PyUnicode_Contains)
+  #define PyUnicode_Contains(u, s)  PySequence_Contains(u, s)
 #endif
 
 #define __Pyx_PyString_FormatSafe(a, b)   ((unlikely((a) == Py_None)) ? PyNumber_Remainder(a, b) : __Pyx_PyString_Format(a, b))
@@ -257,6 +262,14 @@ class __Pyx_FakeReference {
 # endif
 #endif
 
+#ifndef CYTHON_NCP_UNUSED
+# if CYTHON_COMPILING_IN_CPYTHON
+#  define CYTHON_NCP_UNUSED
+# else
+#  define CYTHON_NCP_UNUSED CYTHON_UNUSED
+# endif
+#endif
+
 typedef struct {PyObject **p; char *s; const Py_ssize_t n; const char* encoding;
                 const char is_unicode; const char is_str; const char intern; } __Pyx_StringTabEntry; /*proto*/
 
diff --git a/Cython/Utility/ObjectHandling.c b/Cython/Utility/ObjectHandling.c
index c35166bb38eb93bc6e3895944af50e307c840fe7..c0680ebde341dc57ad03024ce264e830c7274000 100644
--- a/Cython/Utility/ObjectHandling.c
+++ b/Cython/Utility/ObjectHandling.c
@@ -279,7 +279,8 @@ static CYTHON_INLINE PyObject *__Pyx_GetItemInt_Generic(PyObject *o, PyObject* j
 
 {{for type in ['List', 'Tuple']}}
 static CYTHON_INLINE PyObject *__Pyx_GetItemInt_{{type}}_Fast(PyObject *o, Py_ssize_t i,
-                                                              int wraparound, int boundscheck) {
+                                                              CYTHON_NCP_UNUSED int wraparound,
+                                                              CYTHON_NCP_UNUSED int boundscheck) {
 #if CYTHON_COMPILING_IN_CPYTHON
     if (wraparound & unlikely(i < 0)) i += Py{{type}}_GET_SIZE(o);
     if ((!boundscheck) || likely((0 <= i) & (i < Py{{type}}_GET_SIZE(o)))) {
@@ -294,8 +295,9 @@ static CYTHON_INLINE PyObject *__Pyx_GetItemInt_{{type}}_Fast(PyObject *o, Py_ss
 }
 {{endfor}}
 
-static CYTHON_INLINE PyObject *__Pyx_GetItemInt_Fast(PyObject *o, Py_ssize_t i,
-                                                     int is_list, int wraparound, int boundscheck) {
+static CYTHON_INLINE PyObject *__Pyx_GetItemInt_Fast(PyObject *o, Py_ssize_t i, int is_list,
+                                                     CYTHON_NCP_UNUSED int wraparound,
+                                                     CYTHON_NCP_UNUSED int boundscheck) {
 #if CYTHON_COMPILING_IN_CPYTHON
     if (is_list || PyList_CheckExact(o)) {
         Py_ssize_t n = ((!wraparound) | likely(i >= 0)) ? i : i + PyList_GET_SIZE(o);
@@ -361,8 +363,8 @@ static CYTHON_INLINE int __Pyx_SetItemInt_Generic(PyObject *o, PyObject *j, PyOb
     return r;
 }
 
-static CYTHON_INLINE int __Pyx_SetItemInt_Fast(PyObject *o, Py_ssize_t i, PyObject *v,
-                                               int is_list, int wraparound, int boundscheck) {
+static CYTHON_INLINE int __Pyx_SetItemInt_Fast(PyObject *o, Py_ssize_t i, PyObject *v, int is_list,
+                                               CYTHON_NCP_UNUSED int wraparound, CYTHON_NCP_UNUSED int boundscheck) {
 #if CYTHON_COMPILING_IN_CPYTHON
     if (is_list || PyList_CheckExact(o)) {
         Py_ssize_t n = (!wraparound) ? i : ((likely(i >= 0)) ? i : i + PyList_GET_SIZE(o));
@@ -415,7 +417,7 @@ static CYTHON_INLINE int __Pyx_SetItemInt_Fast(PyObject *o, Py_ssize_t i, PyObje
 
 static CYTHON_INLINE int __Pyx_DelItem_Generic(PyObject *o, PyObject *j);
 static CYTHON_INLINE int __Pyx_DelItemInt_Fast(PyObject *o, Py_ssize_t i,
-                                               CYTHON_UNUSED int is_list, int wraparound);
+                                               int is_list, int wraparound);
 
 /////////////// DelItemInt ///////////////
 
@@ -428,7 +430,7 @@ static CYTHON_INLINE int __Pyx_DelItem_Generic(PyObject *o, PyObject *j) {
 }
 
 static CYTHON_INLINE int __Pyx_DelItemInt_Fast(PyObject *o, Py_ssize_t i,
-                                               CYTHON_UNUSED int is_list, int wraparound) {
+                                               CYTHON_UNUSED int is_list, CYTHON_NCP_UNUSED int wraparound) {
 #if CYTHON_COMPILING_IN_PYPY
     if (is_list || PySequence_Check(o)) {
         return PySequence_DelItem(o, i);
@@ -478,12 +480,11 @@ static CYTHON_INLINE int __Pyx_PyObject_SetSlice(
 /////////////// SliceObject ///////////////
 
 {{if access == 'Get'}}
-static CYTHON_INLINE PyObject* __Pyx_PyObject_GetSlice(
-        PyObject* obj, Py_ssize_t cstart, Py_ssize_t cstop,
+static CYTHON_INLINE PyObject* __Pyx_PyObject_GetSlice(PyObject* obj,
 {{else}}
-static CYTHON_INLINE int __Pyx_PyObject_SetSlice(
-        PyObject* obj, PyObject* value, Py_ssize_t cstart, Py_ssize_t cstop,
+static CYTHON_INLINE int __Pyx_PyObject_SetSlice(PyObject* obj, PyObject* value,
 {{endif}}
+        Py_ssize_t cstart, Py_ssize_t cstop,
         PyObject** _py_start, PyObject** _py_stop, PyObject** _py_slice,
         int has_cstart, int has_cstop, CYTHON_UNUSED int wraparound) {
 #if CYTHON_COMPILING_IN_CPYTHON
@@ -723,7 +724,11 @@ static PyObject *__Pyx_FindInheritedMetaclass(PyObject *bases) {
     PyObject *metaclass;
     if (PyTuple_Check(bases) && PyTuple_GET_SIZE(bases) > 0) {
         PyTypeObject *metatype;
+#if CYTHON_COMPILING_IN_CPYTHON
         PyObject *base = PyTuple_GET_ITEM(bases, 0);
+#else
+        PyObject *base = PySequence_ITEM(bases, 0);
+#endif
 #if PY_MAJOR_VERSION < 3
         PyObject* basetype = __Pyx_PyObject_GetAttrStr(base, PYIDENT("__class__"));
         if (basetype) {
@@ -738,6 +743,9 @@ static PyObject *__Pyx_FindInheritedMetaclass(PyObject *bases) {
         metatype = Py_TYPE(base);
 #endif
         metaclass = __Pyx_CalculateMetaclass(metatype, bases);
+#if !CYTHON_COMPILING_IN_CPYTHON
+        Py_DECREF(base);
+#endif
 #if PY_MAJOR_VERSION < 3
         Py_DECREF(basetype);
 #endif
@@ -762,7 +770,7 @@ static PyObject *__Pyx_Py3MetaclassGet(PyObject *bases, PyObject *mkw); /*proto*
 //@requires: CalculateMetaclass
 
 static PyObject *__Pyx_Py3MetaclassGet(PyObject *bases, PyObject *mkw) {
-    PyObject *metaclass = PyDict_GetItem(mkw, PYIDENT("metaclass"));
+    PyObject *metaclass = mkw ? PyDict_GetItem(mkw, PYIDENT("metaclass")) : NULL;
     if (metaclass) {
         Py_INCREF(metaclass);
         if (PyDict_DelItem(mkw, PYIDENT("metaclass")) < 0) {
@@ -927,14 +935,14 @@ static CYTHON_INLINE int __Pyx_TypeTest(PyObject *obj, PyTypeObject *type) {
 
 /////////////// PyDictContains.proto ///////////////
 
-static CYTHON_INLINE int __Pyx_PyDict_Contains(PyObject* item, PyObject* dict, int eq) {
+static CYTHON_INLINE int __Pyx_PyDict_ContainsTF(PyObject* item, PyObject* dict, int eq) {
     int result = PyDict_Contains(dict, item);
     return unlikely(result < 0) ? result : (result == (eq == Py_EQ));
 }
 
 /////////////// PySequenceContains.proto ///////////////
 
-static CYTHON_INLINE int __Pyx_PySequence_Contains(PyObject* item, PyObject* seq, int eq) {
+static CYTHON_INLINE int __Pyx_PySequence_ContainsTF(PyObject* item, PyObject* seq, int eq) {
     int result = PySequence_Contains(seq, item);
     return unlikely(result < 0) ? result : (result == (eq == Py_EQ));
 }
@@ -1093,6 +1101,127 @@ static CYTHON_INLINE int __Pyx_PyObject_SetAttrStr(PyObject* obj, PyObject* attr
 #endif
 
 
+/////////////// UnpackUnboundCMethod.proto ///////////////
+
+typedef struct {
+    PyObject *type;
+    PyObject **method_name;
+    PyCFunction func;   // set on first access (direct C function pointer)
+    PyObject *method;   // set on first access (fallback)
+    int flag;
+} __Pyx_CachedCFunction;
+
+/////////////// UnpackUnboundCMethod ///////////////
+//@requires: PyObjectGetAttrStr
+
+static int __Pyx_TryUnpackUnboundCMethod(__Pyx_CachedCFunction* target) {
+    PyObject *method;
+    method = __Pyx_PyObject_GetAttrStr(target->type, *target->method_name);
+    if (unlikely(!method))
+        return -1;
+    target->method = method;
+#if CYTHON_COMPILING_IN_CPYTHON
+    #if PY_MAJOR_VERSION >= 3
+    // method dscriptor type isn't exported in Py2.x, cannot easily check the type there
+    if (likely(PyObject_TypeCheck(method, &PyMethodDescr_Type)))
+    #endif
+    {
+        PyMethodDescrObject *descr = (PyMethodDescrObject*) method;
+        target->func = descr->d_method->ml_meth;
+        target->flag = descr->d_method->ml_flags & (METH_VARARGS | METH_KEYWORDS | METH_O | METH_NOARGS);
+    }
+#endif
+    return 0;
+}
+
+
+/////////////// CallUnboundCMethod0.proto ///////////////
+//@substitute: naming
+
+static PyObject* __Pyx__CallUnboundCMethod0(__Pyx_CachedCFunction* cfunc, PyObject* self); /*proto*/
+#if CYTHON_COMPILING_IN_CPYTHON
+#define __Pyx_CallUnboundCMethod0(cfunc, self)  \
+    ((likely((cfunc)->func)) ? \
+        (likely((cfunc)->flag == METH_NOARGS) ?  (*((cfunc)->func))(self, NULL) : \
+         (likely((cfunc)->flag == (METH_VARARGS | METH_KEYWORDS)) ?  ((*(PyCFunctionWithKeywords)(cfunc)->func)(self, $empty_tuple, NULL)) : \
+             ((cfunc)->flag == METH_VARARGS ?  (*((cfunc)->func))(self, $empty_tuple) : __Pyx__CallUnboundCMethod0(cfunc, self)))) : \
+        __Pyx__CallUnboundCMethod0(cfunc, self))
+#else
+#define __Pyx_CallUnboundCMethod0(cfunc, self)  __Pyx__CallUnboundCMethod0(cfunc, self)
+#endif
+
+/////////////// CallUnboundCMethod0 ///////////////
+//@requires: UnpackUnboundCMethod
+//@requires: PyObjectCall
+
+static PyObject* __Pyx__CallUnboundCMethod0(__Pyx_CachedCFunction* cfunc, PyObject* self) {
+    PyObject *args, *result = NULL;
+    if (unlikely(!cfunc->method) && unlikely(__Pyx_TryUnpackUnboundCMethod(cfunc) < 0)) return NULL;
+#if CYTHON_COMPILING_IN_CPYTHON
+    args = PyTuple_New(1);
+    if (unlikely(!args)) goto bad;
+    Py_INCREF(self);
+    PyTuple_SET_ITEM(args, 0, self);
+#else
+    args = PyTuple_Pack(1, self);
+    if (unlikely(!args)) goto bad;
+#endif
+    result = __Pyx_PyObject_Call(cfunc->method, args, NULL);
+    Py_DECREF(args);
+bad:
+    return result;
+}
+
+
+/////////////// CallUnboundCMethod1.proto ///////////////
+
+static PyObject* __Pyx__CallUnboundCMethod1(__Pyx_CachedCFunction* cfunc, PyObject* self, PyObject* arg); /*proto*/
+
+#if CYTHON_COMPILING_IN_CPYTHON
+#define __Pyx_CallUnboundCMethod1(cfunc, self, arg)  \
+    ((likely((cfunc)->func && (cfunc)->flag == METH_O)) ? (*((cfunc)->func))(self, arg) : \
+        __Pyx__CallUnboundCMethod1(cfunc, self, arg))
+#else
+#define __Pyx_CallUnboundCMethod1(cfunc, self, arg)  __Pyx__CallUnboundCMethod1(cfunc, self, arg)
+#endif
+
+/////////////// CallUnboundCMethod1 ///////////////
+//@requires: UnpackUnboundCMethod
+//@requires: PyObjectCall
+
+static PyObject* __Pyx__CallUnboundCMethod1(__Pyx_CachedCFunction* cfunc, PyObject* self, PyObject* arg){
+    PyObject *args, *result = NULL;
+    if (unlikely(!cfunc->method) && unlikely(__Pyx_TryUnpackUnboundCMethod(cfunc) < 0)) return NULL;
+#if CYTHON_COMPILING_IN_CPYTHON
+    if (cfunc->func && (cfunc->flag & METH_VARARGS)) {
+        args = PyTuple_New(1);
+        if (unlikely(!args)) goto bad;
+        Py_INCREF(arg);
+        PyTuple_SET_ITEM(args, 0, arg);
+        if (cfunc->flag & METH_KEYWORDS)
+            result = (*(PyCFunctionWithKeywords)cfunc->func)(self, args, NULL);
+        else
+            result = (*cfunc->func)(self, args);
+    } else {
+        args = PyTuple_New(2);
+        if (unlikely(!args)) goto bad;
+        Py_INCREF(self);
+        PyTuple_SET_ITEM(args, 0, self);
+        Py_INCREF(arg);
+        PyTuple_SET_ITEM(args, 1, arg);
+        result = __Pyx_PyObject_Call(cfunc->method, args, NULL);
+    }
+#else
+    args = PyTuple_Pack(2, self, arg);
+    if (unlikely(!args)) goto bad;
+    result = __Pyx_PyObject_Call(cfunc->method, args, NULL);
+#endif
+bad:
+    Py_XDECREF(args);
+    return result;
+}
+
+
 /////////////// PyObjectCallMethod0.proto ///////////////
 
 static PyObject* __Pyx_PyObject_CallMethod0(PyObject* obj, PyObject* method_name); /*proto*/
@@ -1414,6 +1543,8 @@ bad:
 
 static PyObject* __Pyx__PyNumber_MatrixMultiply(PyObject* x, PyObject* y, const char* op_name) {
     int right_is_subtype = PyObject_IsSubclass((PyObject*)Py_TYPE(y), (PyObject*)Py_TYPE(x));
+    if (unlikely(right_is_subtype == -1))
+        return NULL;
     if (right_is_subtype) {
         // to allow subtypes to override parent behaviour, try reversed operation first
         // see note at https://docs.python.org/3/reference/datamodel.html#emulating-numeric-types
diff --git a/Cython/Utility/Optimize.c b/Cython/Utility/Optimize.c
index 57a38e4e0ac7a763d0c968ede1a0ff804b9bef34..9b18bec1a59a2b551038f8b8322941bb2a5a755c 100644
--- a/Cython/Utility/Optimize.c
+++ b/Cython/Utility/Optimize.c
@@ -78,11 +78,17 @@ static CYTHON_INLINE int __Pyx_PyList_Extend(PyObject* L, PyObject* v) {
 
 /////////////// pop.proto ///////////////
 
-#define __Pyx_PyObject_Pop(L) (PyList_CheckExact(L) ? \
-    __Pyx_PyList_Pop(L) : __Pyx__PyObject_Pop(L))
+static CYTHON_INLINE PyObject* __Pyx__PyObject_Pop(PyObject* L); /*proto*/
 
+#if CYTHON_COMPILING_IN_CPYTHON
 static CYTHON_INLINE PyObject* __Pyx_PyList_Pop(PyObject* L); /*proto*/
-static CYTHON_INLINE PyObject* __Pyx__PyObject_Pop(PyObject* L); /*proto*/
+#define __Pyx_PyObject_Pop(L) (likely(PyList_CheckExact(L)) ? \
+    __Pyx_PyList_Pop(L) : __Pyx__PyObject_Pop(L))
+
+#else
+#define __Pyx_PyList_Pop(L)  __Pyx__PyObject_Pop(L)
+#define __Pyx_PyObject_Pop(L)  __Pyx__PyObject_Pop(L)
+#endif
 
 /////////////// pop ///////////////
 //@requires: ObjectHandling.c::PyObjectCallMethod0
@@ -96,44 +102,65 @@ static CYTHON_INLINE PyObject* __Pyx__PyObject_Pop(PyObject* L) {
     return __Pyx_PyObject_CallMethod0(L, PYIDENT("pop"));
 }
 
-static CYTHON_INLINE PyObject* __Pyx_PyList_Pop(PyObject* L) {
 #if CYTHON_COMPILING_IN_CPYTHON
+static CYTHON_INLINE PyObject* __Pyx_PyList_Pop(PyObject* L) {
     /* Check that both the size is positive and no reallocation shrinking needs to be done. */
     if (likely(PyList_GET_SIZE(L) > (((PyListObject*)L)->allocated >> 1))) {
         Py_SIZE(L) -= 1;
         return PyList_GET_ITEM(L, PyList_GET_SIZE(L));
     }
-#endif
-    return __Pyx_PyObject_CallMethod0(L, PYIDENT("pop"));
+    return CALL_UNBOUND_METHOD(PyList_Type, "pop", L);
 }
+#endif
 
 
 /////////////// pop_index.proto ///////////////
 
-#define __Pyx_PyObject_PopIndex(L, ix, is_signed, type, to_py_func) ( \
-    (PyList_CheckExact(L) && __Pyx_fits_Py_ssize_t(ix, type, is_signed)) ? \
-        __Pyx__PyList_PopIndex(L, ix) : __Pyx__PyObject_PopIndex(L, to_py_func(ix)))
+static PyObject* __Pyx__PyObject_PopNewIndex(PyObject* L, PyObject* py_ix); /*proto*/
+static PyObject* __Pyx__PyObject_PopIndex(PyObject* L, PyObject* py_ix); /*proto*/
+
+#if CYTHON_COMPILING_IN_CPYTHON
+static PyObject* __Pyx__PyList_PopIndex(PyObject* L, PyObject* py_ix, Py_ssize_t ix); /*proto*/
+
+#define __Pyx_PyObject_PopIndex(L, py_ix, ix, is_signed, type, to_py_func) ( \
+    (likely(PyList_CheckExact(L) && __Pyx_fits_Py_ssize_t(ix, type, is_signed))) ? \
+        __Pyx__PyList_PopIndex(L, py_ix, ix) : ( \
+        (unlikely(py_ix == Py_None)) ? __Pyx__PyObject_PopNewIndex(L, to_py_func(ix)) : \
+            __Pyx__PyObject_PopIndex(L, py_ix)))
 
-#define __Pyx_PyList_PopIndex(L, ix, is_signed, type, to_py_func) ( \
+#define __Pyx_PyList_PopIndex(L, py_ix, ix, is_signed, type, to_py_func) ( \
     __Pyx_fits_Py_ssize_t(ix, type, is_signed) ? \
-        __Pyx__PyList_PopIndex(L, ix) : __Pyx__PyObject_PopIndex(L, to_py_func(ix)))
+        __Pyx__PyList_PopIndex(L, py_ix, ix) : ( \
+        (unlikely(py_ix == Py_None)) ? __Pyx__PyObject_PopNewIndex(L, to_py_func(ix)) : \
+            __Pyx__PyObject_PopIndex(L, py_ix)))
 
-static PyObject* __Pyx__PyList_PopIndex(PyObject* L, Py_ssize_t ix); /*proto*/
-static PyObject* __Pyx__PyObject_PopIndex(PyObject* L, PyObject* py_ix); /*proto*/
+#else
+
+#define __Pyx_PyList_PopIndex(L, py_ix, ix, is_signed, type, to_py_func) \
+    __Pyx_PyObject_PopIndex(L, py_ix, ix, is_signed, type, to_py_func)
+
+#define __Pyx_PyObject_PopIndex(L, py_ix, ix, is_signed, type, to_py_func) ( \
+    (unlikely(py_ix == Py_None)) ? __Pyx__PyObject_PopNewIndex(L, to_py_func(ix)) : \
+        __Pyx__PyObject_PopIndex(L, py_ix))
+#endif
 
 /////////////// pop_index ///////////////
 //@requires: ObjectHandling.c::PyObjectCallMethod1
 
-static PyObject* __Pyx__PyObject_PopIndex(PyObject* L, PyObject* py_ix) {
+static PyObject* __Pyx__PyObject_PopNewIndex(PyObject* L, PyObject* py_ix) {
     PyObject *r;
     if (unlikely(!py_ix)) return NULL;
-    r = __Pyx_PyObject_CallMethod1(L, PYIDENT("pop"), py_ix);
+    r = __Pyx__PyObject_PopIndex(L, py_ix);
     Py_DECREF(py_ix);
     return r;
 }
 
-static PyObject* __Pyx__PyList_PopIndex(PyObject* L, Py_ssize_t ix) {
+static PyObject* __Pyx__PyObject_PopIndex(PyObject* L, PyObject* py_ix) {
+    return __Pyx_PyObject_CallMethod1(L, PYIDENT("pop"), py_ix);
+}
+
 #if CYTHON_COMPILING_IN_CPYTHON
+static PyObject* __Pyx__PyList_PopIndex(PyObject* L, PyObject* py_ix, Py_ssize_t ix) {
     Py_ssize_t size = PyList_GET_SIZE(L);
     if (likely(size > (((PyListObject*)L)->allocated >> 1))) {
         Py_ssize_t cix = ix;
@@ -148,9 +175,13 @@ static PyObject* __Pyx__PyList_PopIndex(PyObject* L, Py_ssize_t ix) {
             return v;
         }
     }
-#endif
-    return __Pyx__PyObject_PopIndex(L, PyInt_FromSsize_t(ix));
+    if (py_ix == Py_None) {
+        return __Pyx__PyObject_PopNewIndex(L, PyInt_FromSsize_t(ix));
+    } else {
+        return __Pyx__PyObject_PopIndex(L, py_ix);
+    }
 }
+#endif
 
 
 /////////////// dict_getitem_default.proto ///////////////
@@ -280,8 +311,9 @@ static CYTHON_INLINE PyObject* __Pyx_dict_iterator(PyObject* iterable, int is_di
     return PyObject_GetIter(iterable);
 }
 
-static CYTHON_INLINE int __Pyx_dict_iter_next(PyObject* iter_obj, Py_ssize_t orig_length, Py_ssize_t* ppos,
-                                              PyObject** pkey, PyObject** pvalue, PyObject** pitem, int source_is_dict) {
+static CYTHON_INLINE int __Pyx_dict_iter_next(
+        PyObject* iter_obj, CYTHON_NCP_UNUSED Py_ssize_t orig_length, CYTHON_NCP_UNUSED Py_ssize_t* ppos,
+        PyObject** pkey, PyObject** pvalue, PyObject** pitem, int source_is_dict) {
     PyObject* next_item;
 #if !CYTHON_COMPILING_IN_PYPY
     if (source_is_dict) {
@@ -390,7 +422,7 @@ static double __Pyx__PyObject_AsDouble(PyObject* obj); /* proto */
 static double __Pyx__PyObject_AsDouble(PyObject* obj) {
     PyObject* float_value;
 #if CYTHON_COMPILING_IN_PYPY
-    float_value = PyNumber_Float(obj);
+    float_value = PyNumber_Float(obj);  if (0) goto bad;
 #else
     PyNumberMethods *nb = Py_TYPE(obj)->tp_as_number;
     if (likely(nb) && likely(nb->nb_float)) {
@@ -442,22 +474,27 @@ static PyObject* __Pyx__PyNumber_PowerOf2(PyObject *two, PyObject *exp, PyObject
 // see http://bugs.python.org/issue21420
 #if CYTHON_COMPILING_IN_CPYTHON
     Py_ssize_t shiftby;
+#if PY_MAJOR_VERSION < 3
+    if (likely(PyInt_CheckExact(exp))) {
+        shiftby = PyInt_AS_LONG(exp);
+    } else
+#endif
     if (likely(PyLong_CheckExact(exp))) {
-        #if PY_MAJOR_VERSION >= 3 && CYTHON_USE_PYLONG_INTERNALS
-        switch (Py_SIZE(exp)) {
-            case  0: shiftby = 0; break;
-            case  1: shiftby = ((PyLongObject*)exp)->ob_digit[0]; break;
-            default:
-                if (unlikely(Py_SIZE(exp) < 0)) goto fallback;
-                shiftby = PyLong_AsSsize_t(exp); break;
+        #if CYTHON_USE_PYLONG_INTERNALS
+        const Py_ssize_t size = Py_SIZE(exp);
+        // tuned to optimise branch prediction
+        if (likely(size == 1)) {
+            shiftby = ((PyLongObject*)exp)->ob_digit[0];
+        } else if (size == 0) {
+            return PyInt_FromLong(1L);
+        } else if (unlikely(size < 0)) {
+            goto fallback;
+        } else {
+            shiftby = PyLong_AsSsize_t(exp);
         }
         #else
         shiftby = PyLong_AsSsize_t(exp);
         #endif
-#if PY_MAJOR_VERSION < 3
-    } else if (likely(PyInt_CheckExact(exp))) {
-        shiftby = PyInt_AsLong(exp);
-#endif
     } else {
         goto fallback;
     }
@@ -465,6 +502,9 @@ static PyObject* __Pyx__PyNumber_PowerOf2(PyObject *two, PyObject *exp, PyObject
         if ((size_t)shiftby <= sizeof(long) * 8 - 2) {
             long value = 1L << shiftby;
             return PyInt_FromLong(value);
+        } else if ((size_t)shiftby <= sizeof(unsigned PY_LONG_LONG) * 8 - 1) {
+            unsigned PY_LONG_LONG value = ((unsigned PY_LONG_LONG)1) << shiftby;
+            return PyLong_FromUnsignedLongLong(value);
         } else {
             PyObject *one = PyInt_FromLong(1L);
             if (unlikely(!one)) return NULL;
@@ -485,54 +525,210 @@ fallback:
 static PyObject* __Pyx_PyInt_{{op}}{{order}}(PyObject *op1, PyObject *op2, long intval, int inplace); /*proto*/
 #else
 #define __Pyx_PyInt_{{op}}{{order}}(op1, op2, intval, inplace) \
-    ((inplace ? PyNumber_InPlace{{op}} : PyNumber_{{op}})(op1, op2))
+    {{if op in ('Eq', 'Ne')}}PyObject_RichCompare(op1, op2, Py_{{op.upper()}})
+    {{else}}(inplace ? PyNumber_InPlace{{op}}(op1, op2) : PyNumber_{{op}}(op1, op2))
+    {{endif}}
 #endif
 
 /////////////// PyIntBinop ///////////////
 //@requires: TypeConversion.c::PyLongInternals
 
 #if CYTHON_COMPILING_IN_CPYTHON
+{{py: from Cython.Utility import pylong_join }}
 {{py: pyval, ival = ('op2', 'b') if order == 'CObj' else ('op1', 'a') }}
-
-static PyObject* __Pyx_PyInt_{{op}}{{order}}(PyObject *op1, PyObject *op2, long intval, int inplace) {
-    const long {{'a' if order == 'CObj' else 'b'}} = intval;
+{{py: slot_name = {'TrueDivide': 'true_divide', 'FloorDivide': 'floor_divide'}.get(op, op.lower()) }}
+{{py:
+c_op = {
+    'Add': '+', 'Subtract': '-', 'Remainder': '%', 'TrueDivide': '/', 'FloorDivide': '/',
+    'Or': '|', 'Xor': '^', 'And': '&', 'Rshift': '>>',
+    'Eq': '==', 'Ne': '!=',
+    }[op]
+}}
+
+static PyObject* __Pyx_PyInt_{{op}}{{order}}(PyObject *op1, PyObject *op2, CYTHON_UNUSED long intval, CYTHON_UNUSED int inplace) {
+    {{if op in ('Eq', 'Ne')}}
+    if (op1 == op2) {
+        Py_RETURN_{{'TRUE' if op == 'Eq' else 'FALSE'}};
+    }
+    {{endif}}
 
     #if PY_MAJOR_VERSION < 3
     if (likely(PyInt_CheckExact({{pyval}}))) {
-        long x, {{ival}};
-        {{ival}} = PyInt_AS_LONG({{pyval}});
-        // adapted from intobject.c in Py2.7:
-        // casts in the line below avoid undefined behaviour on overflow
-        x = (long)((unsigned long)a {{ '+' if op == 'Add' else '-' }} b);
-        if (likely((x^a) >= 0 || (x^{{ '~' if op == 'Subtract' else '' }}b) >= 0))
+        const long {{'a' if order == 'CObj' else 'b'}} = intval;
+        {{if c_op in '+-%' or op == 'FloorDivide'}}
+        long x;
+        {{endif}}
+        long {{ival}} = PyInt_AS_LONG({{pyval}});
+
+        {{if op in ('Eq', 'Ne')}}
+        if (a {{c_op}} b) {
+            Py_RETURN_TRUE;
+        } else {
+            Py_RETURN_FALSE;
+        }
+        {{elif c_op in '+-'}}
+            // adapted from intobject.c in Py2.7:
+            // casts in the line below avoid undefined behaviour on overflow
+            x = (long)((unsigned long)a {{c_op}} b);
+            if (likely((x^a) >= 0 || (x^{{ '~' if op == 'Subtract' else '' }}b) >= 0))
+                return PyInt_FromLong(x);
+            return PyLong_Type.tp_as_number->nb_{{slot_name}}(op1, op2);
+        {{elif c_op == '%'}}
+            // see ExprNodes.py :: mod_int_utility_code
+            x = a % b;
+            x += ((x != 0) & ((x ^ b) < 0)) * b;
             return PyInt_FromLong(x);
-        return PyLong_Type.tp_as_number->nb_{{op.lower()}}(op1, op2);
+        {{elif op == 'TrueDivide'}}
+            if (8 * sizeof(long) <= 53 || likely(labs({{ival}}) <= (1L << 53))) {
+                return PyFloat_FromDouble((double)a / (double)b);
+            }
+            // let Python do the rounding
+            return PyInt_Type.tp_as_number->nb_{{slot_name}}(op1, op2);
+        {{elif op == 'FloorDivide'}}
+            // INT_MIN / -1  is the only case that overflows
+            if (unlikely(b == -1 && ((unsigned long)a) == 0-(unsigned long)a))
+                return PyInt_Type.tp_as_number->nb_{{slot_name}}(op1, op2);
+            else {
+                long q, r;
+                // see ExprNodes.py :: div_int_utility_code
+                q = a / b;
+                r = a - q*b;
+                q -= ((r != 0) & ((r ^ b) < 0));
+                x = q;
+            }
+            return PyInt_FromLong(x);
+        {{else}}
+            // other operations are safe, no overflow
+            return PyInt_FromLong(a {{c_op}} b);
+        {{endif}}
     }
     #endif
 
-    #if PY_MAJOR_VERSION >= 3 && CYTHON_USE_PYLONG_INTERNALS
+    #if CYTHON_USE_PYLONG_INTERNALS && PY_MAJOR_VERSION >= 3
     if (likely(PyLong_CheckExact({{pyval}}))) {
-        long {{ival}};
-        switch (Py_SIZE({{pyval}})) {
-            case -1: {{ival}} = -(sdigit)((PyLongObject*){{pyval}})->ob_digit[0]; break;
-            case  0: {{ival}} = 0; break;
-            case  1: {{ival}} = ((PyLongObject*){{pyval}})->ob_digit[0]; break;
-            default: return PyLong_Type.tp_as_number->nb_{{op.lower()}}(op1, op2);
+        const long {{'a' if order == 'CObj' else 'b'}} = intval;
+        long {{ival}}{{if op not in ('Eq', 'Ne')}}, x{{endif}};
+        {{if op not in ('Eq', 'Ne', 'TrueDivide')}}
+        const PY_LONG_LONG ll{{'a' if order == 'CObj' else 'b'}} = intval;
+        PY_LONG_LONG ll{{ival}}, llx;
+        {{endif}}
+        const digit* digits = ((PyLongObject*){{pyval}})->ob_digit;
+        const Py_ssize_t size = Py_SIZE({{pyval}});
+        // handle most common case first to avoid indirect branch and optimise branch prediction
+        if (likely(__Pyx_sst_abs(size) <= 1)) {
+            {{ival}} = likely(size) ? digits[0] : 0;
+            if (size == -1) {{ival}} = -{{ival}};
+        } else {
+            switch (size) {
+                {{for _size in range(2, 5)}}
+                {{for _case in (-_size, _size)}}
+                case {{_case}}:
+                    if (8 * sizeof(long) - 1 > {{_size}} * PyLong_SHIFT{{if op == 'TrueDivide'}} && {{_size-1}} * PyLong_SHIFT < 53{{endif}}) {
+                        {{ival}} = {{'-' if _case < 0 else ''}}(long) {{pylong_join(_size, 'digits')}};
+                        break;
+                    {{if op not in ('Eq', 'Ne', 'TrueDivide')}}
+                    } else if (8 * sizeof(PY_LONG_LONG) - 1 > {{_size}} * PyLong_SHIFT) {
+                        ll{{ival}} = {{'-' if _case < 0 else ''}}(PY_LONG_LONG) {{pylong_join(_size, 'digits', 'unsigned PY_LONG_LONG')}};
+                        goto long_long;
+                    {{endif}}
+                    }
+                    // if size doesn't fit into a long or PY_LONG_LONG anymore, fall through to default
+                {{endfor}}
+                {{endfor}}
+
+                {{if op in ('Eq', 'Ne')}}
+                #if PyLong_SHIFT < 30 && PyLong_SHIFT != 15
+                // unusual setup - your fault
+                default: return PyLong_Type.tp_richcompare({{'op1, op2' if order == 'ObjC' else 'op2, op1'}}, Py_{{op.upper()}});
+                #else
+                // too large for the long values we allow => definitely not equal
+                default: Py_RETURN_{{'FALSE' if op == 'Eq' else 'TRUE'}};
+                #endif
+                {{else}}
+                default: return PyLong_Type.tp_as_number->nb_{{slot_name}}(op1, op2);
+                {{endif}}
+            }
         }
-        return PyLong_FromLong(a {{ '+' if op == 'Add' else '-' }} b);
+        {{if op in ('Eq', 'Ne')}}
+            if (a {{c_op}} b) {
+                Py_RETURN_TRUE;
+            } else {
+                Py_RETURN_FALSE;
+            }
+        {{else}}
+            {{if c_op == '%'}}
+                // see ExprNodes.py :: mod_int_utility_code
+                x = a % b;
+                x += ((x != 0) & ((x ^ b) < 0)) * b;
+            {{elif op == 'TrueDivide'}}
+                if (8 * sizeof(long) <= 53 || (abs(size) <= 52 / PyLong_SHIFT) || likely(labs({{ival}}) <= (1L << 53))) {
+                    return PyFloat_FromDouble((double)a / (double)b);
+                }
+                return PyLong_Type.tp_as_number->nb_{{slot_name}}(op1, op2);
+            {{elif op == 'FloorDivide'}}
+                {
+                    long q, r;
+                    // see ExprNodes.py :: div_int_utility_code
+                    q = a / b;
+                    r = a - q*b;
+                    q -= ((r != 0) & ((r ^ b) < 0));
+                    x = q;
+                }
+            {{else}}
+                x = a {{c_op}} b;
+            {{endif}}
+            return PyLong_FromLong(x);
+
+        {{if op != 'TrueDivide'}}
+        long_long:
+            {{if c_op == '%'}}
+                // see ExprNodes.py :: mod_int_utility_code
+                llx = lla % llb;
+                llx += ((llx != 0) & ((llx ^ llb) < 0)) * llb;
+            {{elif op == 'FloorDivide'}}
+                {
+                    PY_LONG_LONG q, r;
+                    // see ExprNodes.py :: div_int_utility_code
+                    q = lla / llb;
+                    r = lla - q*llb;
+                    q -= ((r != 0) & ((r ^ llb) < 0));
+                    llx = q;
+                }
+            {{else}}
+                llx = lla {{c_op}} llb;
+            {{endif}}
+            return PyLong_FromLongLong(llx);
+        {{endif}}
+        {{endif}}
     }
     #endif
 
+    {{if c_op in '+-' or op in ('TrueDivide', 'Eq', 'Ne')}}
     if (PyFloat_CheckExact({{pyval}})) {
-        double result;
+        const long {{'a' if order == 'CObj' else 'b'}} = intval;
         double {{ival}} = PyFloat_AS_DOUBLE({{pyval}});
-        // copied from floatobject.c in Py3.5:
-        PyFPE_START_PROTECT("{{op.lower()}}", return NULL)
-        result = ((double)a) {{ '+' if op == 'Add' else '-' }} (double)b;
-        PyFPE_END_PROTECT(result)
-        return PyFloat_FromDouble(result);
+        {{if op in ('Eq', 'Ne')}}
+            if ((double)a {{c_op}} (double)b) {
+                Py_RETURN_TRUE;
+            } else {
+                Py_RETURN_FALSE;
+            }
+        {{else}}
+            double result;
+            // copied from floatobject.c in Py3.5:
+            PyFPE_START_PROTECT("{{op.lower() if not op.endswith('Divide') else 'divide'}}", return NULL)
+            result = ((double)a) {{c_op}} (double)b;
+            PyFPE_END_PROTECT(result)
+            return PyFloat_FromDouble(result);
+        {{endif}}
     }
+    {{endif}}
+
+    {{if op in ('Eq', 'Ne')}}
+    return PyObject_RichCompare(op1, op2, Py_{{op.upper()}});
+    {{else}}
     return (inplace ? PyNumber_InPlace{{op}} : PyNumber_{{op}})(op1, op2);
+    {{endif}}
 }
 #endif
 
@@ -542,18 +738,34 @@ static PyObject* __Pyx_PyInt_{{op}}{{order}}(PyObject *op1, PyObject *op2, long
 static PyObject* __Pyx_PyFloat_{{op}}{{order}}(PyObject *op1, PyObject *op2, double floatval, int inplace); /*proto*/
 #else
 #define __Pyx_PyFloat_{{op}}{{order}}(op1, op2, floatval, inplace) \
-    ((inplace ? PyNumber_InPlace{{op}} : PyNumber_{{op}})(op1, op2))
+    {{if op in ('Eq', 'Ne')}}PyObject_RichCompare(op1, op2, Py_{{op.upper()}})
+    {{elif op == 'Divide'}}((inplace ? __Pyx_PyNumber_InPlaceDivide(op1, op2) : __Pyx_PyNumber_Divide(op1, op2)))
+    {{else}}(inplace ? PyNumber_InPlace{{op}}(op1, op2) : PyNumber_{{op}}(op1, op2))
+    {{endif}}
 #endif
 
 /////////////// PyFloatBinop ///////////////
 //@requires: TypeConversion.c::PyLongInternals
 
 #if CYTHON_COMPILING_IN_CPYTHON
+{{py: from Cython.Utility import pylong_join }}
 {{py: pyval, fval = ('op2', 'b') if order == 'CObj' else ('op1', 'a') }}
-
-static PyObject* __Pyx_PyFloat_{{op}}{{order}}(PyObject *op1, PyObject *op2, double floatval, int inplace) {
+{{py:
+c_op = {
+    'Add': '+', 'Subtract': '-', 'TrueDivide': '/', 'Divide': '/', 'Remainder': '%',
+    'Eq': '==', 'Ne': '!=',
+    }[op]
+}}
+
+static PyObject* __Pyx_PyFloat_{{op}}{{order}}(PyObject *op1, PyObject *op2, double floatval, CYTHON_UNUSED int inplace) {
     const double {{'a' if order == 'CObj' else 'b'}} = floatval;
-    double result, {{fval}};
+    double {{fval}}{{if op not in ('Eq', 'Ne')}}, result{{endif}};
+
+    {{if op in ('Eq', 'Ne')}}
+    if (op1 == op2) {
+        Py_RETURN_{{'TRUE' if op == 'Eq' else 'FALSE'}};
+    }
+    {{endif}}
 
     if (likely(PyFloat_CheckExact({{pyval}}))) {
         {{fval}} = PyFloat_AS_DOUBLE({{pyval}});
@@ -566,26 +778,72 @@ static PyObject* __Pyx_PyFloat_{{op}}{{order}}(PyObject *op1, PyObject *op2, dou
     #endif
 
     if (likely(PyLong_CheckExact({{pyval}}))) {
-        #if PY_MAJOR_VERSION >= 3 && CYTHON_USE_PYLONG_INTERNALS
-        switch (Py_SIZE({{pyval}})) {
-            case -1: {{fval}} = -(double)((PyLongObject*){{pyval}})->ob_digit[0]; break;
+        #if CYTHON_USE_PYLONG_INTERNALS && PY_MAJOR_VERSION >= 3
+        const digit* digits = ((PyLongObject*){{pyval}})->ob_digit;
+        const Py_ssize_t size = Py_SIZE({{pyval}});
+        switch (size) {
             case  0: {{fval}} = 0.0; break;
-            case  1: {{fval}} = (double)((PyLongObject*){{pyval}})->ob_digit[0]; break;
-            default: {{fval}} = PyLong_AsDouble({{pyval}});
-                if (unlikely({{fval}} == -1 && PyErr_Occurred())) return NULL;
-                break;
-        }
+            case -1: {{fval}} = -(double) digits[0]; break;
+            case  1: {{fval}} = (double) digits[0]; break;
+            {{for _size in (2, 3, 4)}}
+            case -{{_size}}:
+            case {{_size}}:
+                if (8 * sizeof(unsigned long) > {{_size}} * PyLong_SHIFT && ((8 * sizeof(unsigned long) < 53) || ({{_size-1}} * PyLong_SHIFT < 53))) {
+                    {{fval}} = (double) {{pylong_join(_size, 'digits')}};
+                    // let CPython do its own float rounding from 2**53 on (max. consecutive integer in double float)
+                    if ((8 * sizeof(unsigned long) < 53) || ({{_size}} * PyLong_SHIFT < 53) || ({{fval}} < (double) (1L<<53))) {
+                        if (size == {{-_size}})
+                            {{fval}} = -{{fval}};
+                        break;
+                    }
+                }
+                // Fall through if size doesn't fit safely into a double anymore.
+                // It may not be obvious that this is a safe fall-through given the "fval < 2**53"
+                // check above.  However, the number of digits that CPython uses for a given PyLong
+                // value is minimal, and together with the "(size-1) * SHIFT < 53" check above,
+                // this should make it safe.
+            {{endfor}}
+            default:
         #else
-        {{fval}} = PyLong_AsDouble({{pyval}});
-        if (unlikely({{fval}} == -1.0 && PyErr_Occurred())) return NULL;
+        {
         #endif
-    } else
+        {{if op in ('Eq', 'Ne')}}
+            return PyFloat_Type.tp_richcompare({{'op1, op2' if order == 'CObj' else 'op2, op1'}}, Py_{{op.upper()}});
+        {{else}}
+            {{fval}} = PyLong_AsDouble({{pyval}});
+            if (unlikely({{fval}} == -1.0 && PyErr_Occurred())) return NULL;
+        {{endif}}
+        }
+    } else {
+        {{if op in ('Eq', 'Ne')}}
+        return PyObject_RichCompare(op1, op2, Py_{{op.upper()}});
+        {{elif op == 'Divide'}}
+        return (inplace ? __Pyx_PyNumber_InPlaceDivide(op1, op2) : __Pyx_PyNumber_Divide(op1, op2));
+        {{else}}
         return (inplace ? PyNumber_InPlace{{op}} : PyNumber_{{op}})(op1, op2);
+        {{endif}}
+    }
 
-    // copied from floatobject.c in Py3.5:
-    PyFPE_START_PROTECT("{{op.lower()}}", return NULL)
-    result = a {{ '+' if op == 'Add' else '-' }} b;
-    PyFPE_END_PROTECT(result)
-    return PyFloat_FromDouble(result);
+    {{if op in ('Eq', 'Ne')}}
+        if (a {{c_op}} b) {
+            Py_RETURN_TRUE;
+        } else {
+            Py_RETURN_FALSE;
+        }
+    {{else}}
+        // copied from floatobject.c in Py3.5:
+        PyFPE_START_PROTECT("{{op.lower() if not op.endswith('Divide') else 'divide'}}", return NULL)
+        {{if c_op == '%'}}
+        result = fmod(a, b);
+        if (result)
+            result += ((result < 0) ^ (b < 0)) * b;
+        else
+            result = copysign(0.0, b);
+        {{else}}
+        result = a {{c_op}} b;
+        {{endif}}
+        PyFPE_END_PROTECT(result)
+        return PyFloat_FromDouble(result);
+    {{endif}}
 }
 #endif
diff --git a/Cython/Utility/Overflow.c b/Cython/Utility/Overflow.c
index 1ac58df5b25fd34f3b25b68b8bedc78e0e36640b..b357df99fe179e1a55a948537d8b7e8d881f4301 100644
--- a/Cython/Utility/Overflow.c
+++ b/Cython/Utility/Overflow.c
@@ -83,8 +83,8 @@ static CYTHON_INLINE {{UINT}} __Pyx_mul_{{NAME}}_checking_overflow({{UINT}} a, {
         {{UINT}} r = ({{UINT}}) big_r;
         *overflow |= big_r != r;
         return r;
-    } else if (sizeof({{UINT}}) < sizeof(unsigned long long)) {
-        unsigned long long big_r = ((unsigned long long) a) * ((unsigned long long) b);
+    } else if (sizeof({{UINT}}) < sizeof(unsigned PY_LONG_LONG)) {
+        unsigned PY_LONG_LONG big_r = ((unsigned PY_LONG_LONG) a) * ((unsigned PY_LONG_LONG) b);
         {{UINT}} r = ({{UINT}}) big_r;
         *overflow |= big_r != r;
         return r;
@@ -137,8 +137,8 @@ static CYTHON_INLINE {{INT}} __Pyx_add_{{NAME}}_checking_overflow({{INT}} a, {{I
         {{INT}} r = ({{INT}}) big_r;
         *overflow |= big_r != r;
         return r;
-    } else if (sizeof({{INT}}) < sizeof(long long)) {
-        long long big_r = ((long long) a) + ((long long) b);
+    } else if (sizeof({{INT}}) < sizeof(PY_LONG_LONG)) {
+        PY_LONG_LONG big_r = ((PY_LONG_LONG) a) + ((PY_LONG_LONG) b);
         {{INT}} r = ({{INT}}) big_r;
         *overflow |= big_r != r;
         return r;
@@ -181,8 +181,8 @@ static CYTHON_INLINE {{INT}} __Pyx_mul_{{NAME}}_checking_overflow({{INT}} a, {{I
         {{INT}} r = ({{INT}}) big_r;
         *overflow |= big_r != r;
         return ({{INT}}) r;
-    } else if (sizeof({{INT}}) < sizeof(long long)) {
-        long long big_r = ((long long) a) * ((long long) b);
+    } else if (sizeof({{INT}}) < sizeof(PY_LONG_LONG)) {
+        PY_LONG_LONG big_r = ((PY_LONG_LONG) a) * ((PY_LONG_LONG) b);
         {{INT}} r = ({{INT}}) big_r;
         *overflow |= big_r != r;
         return ({{INT}}) r;
@@ -228,7 +228,7 @@ __Pyx_check_sane_{{NAME}}();
 static int __Pyx_check_sane_{{NAME}}(void) {
     if (sizeof({{TYPE}}) <= sizeof(int) ||
         sizeof({{TYPE}}) == sizeof(long) ||
-        sizeof({{TYPE}}) == sizeof(long long)) {
+        sizeof({{TYPE}}) == sizeof(PY_LONG_LONG)) {
         return 0;
     } else {
         PyErr_Format(PyExc_RuntimeError, \
@@ -252,7 +252,7 @@ static CYTHON_INLINE {{TYPE}} __Pyx_{{BINOP}}_{{NAME}}_checking_overflow({{TYPE}
             return __Pyx_{{BINOP}}_unsigned_int_checking_overflow(a, b, overflow);
         } else if (sizeof({{TYPE}}) == sizeof(unsigned long)) {
             return __Pyx_{{BINOP}}_unsigned_long_checking_overflow(a, b, overflow);
-        } else if (sizeof({{TYPE}}) == sizeof(unsigned long long)) {
+        } else if (sizeof({{TYPE}}) == sizeof(unsigned PY_LONG_LONG)) {
             return __Pyx_{{BINOP}}_unsigned_long_long_checking_overflow(a, b, overflow);
         } else {
             abort(); return 0; // handled elsewhere
@@ -262,7 +262,7 @@ static CYTHON_INLINE {{TYPE}} __Pyx_{{BINOP}}_{{NAME}}_checking_overflow({{TYPE}
             return __Pyx_{{BINOP}}_int_checking_overflow(a, b, overflow);
         } else if (sizeof({{TYPE}}) == sizeof(long)) {
             return __Pyx_{{BINOP}}_long_checking_overflow(a, b, overflow);
-        } else if (sizeof({{TYPE}}) == sizeof(long long)) {
+        } else if (sizeof({{TYPE}}) == sizeof(PY_LONG_LONG)) {
             return __Pyx_{{BINOP}}_long_long_checking_overflow(a, b, overflow);
         } else {
             abort(); return 0; // handled elsewhere
@@ -282,3 +282,10 @@ static CYTHON_INLINE {{TYPE}} __Pyx_lshift_{{NAME}}_checking_overflow({{TYPE}} a
 }
 #define __Pyx_lshift_const_{{NAME}}_checking_overflow __Pyx_lshift_{{NAME}}_checking_overflow
 
+
+/////////////// UnaryNegOverflows.proto ///////////////
+
+//FIXME: shouldn't the macro name be prefixed by "__Pyx_" ?  Too late now, I guess...
+// from intobject.c
+#define UNARY_NEG_WOULD_OVERFLOW(x)    \
+        (((x) < 0) & ((unsigned long)(x) == 0-(unsigned long)(x)))
diff --git a/Cython/Utility/StringTools.c b/Cython/Utility/StringTools.c
index ad5c4fcd75388172250bd906c44d9b38ab2e1657..06598745d332d0b2044760360eb3b73aff441731 100644
--- a/Cython/Utility/StringTools.c
+++ b/Cython/Utility/StringTools.c
@@ -111,12 +111,24 @@ static CYTHON_INLINE int __Pyx_PyUnicodeBufferContainsUCS4(Py_UNICODE* buffer, P
 
 //////////////////// PyUnicodeContains.proto ////////////////////
 
-static CYTHON_INLINE int __Pyx_PyUnicode_Contains(PyObject* substring, PyObject* text, int eq) {
+static CYTHON_INLINE int __Pyx_PyUnicode_ContainsTF(PyObject* substring, PyObject* text, int eq) {
     int result = PyUnicode_Contains(text, substring);
     return unlikely(result < 0) ? result : (result == (eq == Py_EQ));
 }
 
 
+//////////////////// CStringEquals.proto ////////////////////
+
+static CYTHON_INLINE int __Pyx_StrEq(const char *, const char *); /*proto*/
+
+//////////////////// CStringEquals ////////////////////
+
+static CYTHON_INLINE int __Pyx_StrEq(const char *s1, const char *s2) {
+    while (*s1 != '\0' && *s1 == *s2) { s1++; s2++; }
+    return *s1 == *s2;
+}
+
+
 //////////////////// StrEquals.proto ////////////////////
 //@requires: BytesEquals
 //@requires: UnicodeEquals
@@ -533,7 +545,7 @@ static int __Pyx_PyUnicode_Tailmatch(PyObject* s, PyObject* substr,
             result = PyUnicode_Tailmatch(s, PyTuple_GET_ITEM(substr, i),
                                          start, end, direction);
 #else
-            PyObject* sub = PySequence_GetItem(substr, i);
+            PyObject* sub = PySequence_ITEM(substr, i);
             if (unlikely(!sub)) return -1;
             result = PyUnicode_Tailmatch(s, sub, start, end, direction);
             Py_DECREF(sub);
@@ -618,7 +630,7 @@ static int __Pyx_PyBytes_Tailmatch(PyObject* self, PyObject* substr, Py_ssize_t
             result = __Pyx_PyBytes_SingleTailmatch(self, PyTuple_GET_ITEM(substr, i),
                                                    start, end, direction);
 #else
-            PyObject* sub = PySequence_GetItem(substr, i);
+            PyObject* sub = PySequence_ITEM(substr, i);
             if (unlikely(!sub)) return -1;
             result = __Pyx_PyBytes_SingleTailmatch(self, sub, start, end, direction);
             Py_DECREF(sub);
@@ -721,7 +733,7 @@ static CYTHON_INLINE int __Pyx_PyByteArray_AppendObject(PyObject* bytearray, PyO
         }
         ival = (unsigned char) (PyString_AS_STRING(value)[0]);
     } else
-#else
+#endif
 #if CYTHON_USE_PYLONG_INTERNALS
     if (likely(PyLong_CheckExact(value)) && likely(Py_SIZE(value) == 1 || Py_SIZE(value) == 0)) {
         if (Py_SIZE(value) == 0) {
@@ -731,7 +743,6 @@ static CYTHON_INLINE int __Pyx_PyByteArray_AppendObject(PyObject* bytearray, PyO
             if (unlikely(ival > 255)) goto bad_range;
         }
     } else
-#endif
 #endif
     {
         // CPython calls PyNumber_Index() internally
diff --git a/Cython/Utility/TypeConversion.c b/Cython/Utility/TypeConversion.c
index 4cd82291c58702ddef9786b4ab009d0900e05d0b..850f1cbea74aa9531ac43ec513e490d0aede8fcb 100644
--- a/Cython/Utility/TypeConversion.c
+++ b/Cython/Utility/TypeConversion.c
@@ -2,6 +2,9 @@
 
 /* Type Conversion Predeclarations */
 
+#define __Pyx_uchar_cast(c) ((unsigned char)c)
+#define __Pyx_long_cast(x) ((long)x)
+
 #define __Pyx_fits_Py_ssize_t(v, type, is_signed)  (    \
     (sizeof(type) < sizeof(Py_ssize_t))  ||             \
     (sizeof(type) > sizeof(Py_ssize_t) &&               \
@@ -13,6 +16,18 @@
           (is_signed || likely(v < (type)PY_SSIZE_T_MAX ||        \
                                v == (type)PY_SSIZE_T_MAX)))  )
 
+// fast and unsafe abs(Py_ssize_t) that ignores the overflow for (-PY_SSIZE_T_MAX-1)
+#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
+    #define __Pyx_sst_abs(value) \
+        (sizeof(int) >= sizeof(Py_ssize_t) ? abs(value) : \
+         (sizeof(long) >= sizeof(Py_ssize_t) ? labs(value) : llabs(value)))
+#else
+    #define __Pyx_sst_abs(value) \
+        (sizeof(int) >= sizeof(Py_ssize_t) ? abs(value) : \
+         (sizeof(long) >= sizeof(Py_ssize_t) ? labs(value) : \
+          ((value<0) ? -value : value)))
+#endif
+
 static CYTHON_INLINE char* __Pyx_PyObject_AsString(PyObject*);
 static CYTHON_INLINE char* __Pyx_PyObject_AsStringAndSize(PyObject*, Py_ssize_t* length);
 
@@ -53,8 +68,9 @@ static CYTHON_INLINE size_t __Pyx_Py_UNICODE_strlen(const Py_UNICODE *u)
 #define __Pyx_PyUnicode_FromUnicodeAndLength PyUnicode_FromUnicode
 #define __Pyx_PyUnicode_AsUnicode            PyUnicode_AsUnicode
 
-#define __Pyx_Owned_Py_None(b) (Py_INCREF(Py_None), Py_None)
-#define __Pyx_PyBool_FromLong(b) ((b) ? (Py_INCREF(Py_True), Py_True) : (Py_INCREF(Py_False), Py_False))
+#define __Pyx_NewRef(obj) (Py_INCREF(obj), obj)
+#define __Pyx_Owned_Py_None(b) __Pyx_NewRef(Py_None)
+#define __Pyx_PyBool_FromLong(b) ((b) ? __Pyx_NewRef(Py_True) : __Pyx_NewRef(Py_False))
 static CYTHON_INLINE int __Pyx_PyObject_IsTrue(PyObject*);
 static CYTHON_INLINE PyObject* __Pyx_PyNumber_Int(PyObject* x);
 
@@ -164,7 +180,7 @@ static CYTHON_INLINE char* __Pyx_PyObject_AsString(PyObject* o) {
 }
 
 static CYTHON_INLINE char* __Pyx_PyObject_AsStringAndSize(PyObject* o, Py_ssize_t *length) {
-#if __PYX_DEFAULT_STRING_ENCODING_IS_ASCII || __PYX_DEFAULT_STRING_ENCODING_IS_DEFAULT
+#if CYTHON_COMPILING_IN_CPYTHON && (__PYX_DEFAULT_STRING_ENCODING_IS_ASCII || __PYX_DEFAULT_STRING_ENCODING_IS_DEFAULT)
     if (
 #if PY_MAJOR_VERSION < 3 && __PYX_DEFAULT_STRING_ENCODING_IS_ASCII
             __Pyx_sys_getdefaultencoding_not_ascii && 
@@ -172,7 +188,7 @@ static CYTHON_INLINE char* __Pyx_PyObject_AsStringAndSize(PyObject* o, Py_ssize_
             PyUnicode_Check(o)) {
 #if PY_VERSION_HEX < 0x03030000
         char* defenc_c;
-        // borrowed, cached reference
+        // borrowed reference, cached internally in 'o' by CPython
         PyObject* defenc = _PyUnicode_AsDefaultEncodedString(o, NULL);
         if (!defenc) return NULL;
         defenc_c = PyBytes_AS_STRING(defenc);
@@ -210,7 +226,7 @@ static CYTHON_INLINE char* __Pyx_PyObject_AsStringAndSize(PyObject* o, Py_ssize_
     } else
 #endif /* __PYX_DEFAULT_STRING_ENCODING_IS_ASCII  || __PYX_DEFAULT_STRING_ENCODING_IS_DEFAULT */
 
-#if !CYTHON_COMPILING_IN_PYPY
+#if (!CYTHON_COMPILING_IN_PYPY) || (defined(PyByteArray_AS_STRING) && defined(PyByteArray_GET_SIZE))
     if (PyByteArray_Check(o)) {
         *length = PyByteArray_GET_SIZE(o);
         return PyByteArray_AS_STRING(o);
@@ -243,7 +259,7 @@ static CYTHON_INLINE PyObject* __Pyx_PyNumber_Int(PyObject* x) {
 #else
   if (PyLong_Check(x))
 #endif
-    return Py_INCREF(x), x;
+    return __Pyx_NewRef(x);
   m = Py_TYPE(x)->tp_as_number;
 #if PY_MAJOR_VERSION < 3
   if (m && m->nb_int) {
@@ -280,22 +296,41 @@ static CYTHON_INLINE PyObject* __Pyx_PyNumber_Int(PyObject* x) {
   return res;
 }
 
+{{py: from Cython.Utility import pylong_join }}
+
 static CYTHON_INLINE Py_ssize_t __Pyx_PyIndex_AsSsize_t(PyObject* b) {
   Py_ssize_t ival;
   PyObject *x;
 #if PY_MAJOR_VERSION < 3
-  if (likely(PyInt_CheckExact(b)))
-      return PyInt_AS_LONG(b);
+  if (likely(PyInt_CheckExact(b))) {
+    if (sizeof(Py_ssize_t) >= sizeof(long))
+        return PyInt_AS_LONG(b);
+    else
+        return PyInt_AsSsize_t(x);
+  }
 #endif
   if (likely(PyLong_CheckExact(b))) {
-    #if CYTHON_COMPILING_IN_CPYTHON && PY_MAJOR_VERSION >= 3
-     #if CYTHON_USE_PYLONG_INTERNALS
-       switch (Py_SIZE(b)) {
-       case -1: return -(sdigit)((PyLongObject*)b)->ob_digit[0];
-       case  0: return 0;
-       case  1: return ((PyLongObject*)b)->ob_digit[0];
-       }
-     #endif
+    #if CYTHON_USE_PYLONG_INTERNALS
+    const digit* digits = ((PyLongObject*)b)->ob_digit;
+    const Py_ssize_t size = Py_SIZE(b);
+    // handle most common case first to avoid indirect branch and optimise branch prediction
+    if (likely(__Pyx_sst_abs(size) <= 1)) {
+        ival = likely(size) ? digits[0] : 0;
+        if (size == -1) ival = -ival;
+        return ival;
+    } else {
+      switch (size) {
+         {{for _size in (2, 3, 4)}}
+         {{for _case in (_size, -_size)}}
+         case {{_case}}:
+           if (8 * sizeof(Py_ssize_t) > {{_size}} * PyLong_SHIFT) {
+             return {{'-' if _case < 0 else ''}}(Py_ssize_t) {{pylong_join(_size, 'digits', 'size_t')}};
+           }
+           break;
+         {{endfor}}
+         {{endfor}}
+      }
+    }
     #endif
     return PyLong_AsSsize_t(b);
   }
@@ -347,56 +382,79 @@ static {{struct_type_decl}} {{funcname}}(PyObject * o) {
         goto bad;
     }
     
+#if CYTHON_COMPILING_IN_CPYTHON
     {{for ix, component in enumerate(components):}}
         {{py:attr = "result.f%s" % ix}}
         {{attr}} = {{component.from_py_function}}(PyTuple_GET_ITEM(o, {{ix}}));
-        if ({{component.error_condition(attr)}})
-            goto bad;
+        if ({{component.error_condition(attr)}}) goto bad;
     {{endfor}}
-    
+#else
+    {
+        PyObject *item;
+    {{for ix, component in enumerate(components):}}
+        {{py:attr = "result.f%s" % ix}}
+        item = PySequence_ITEM(o, {{ix}});  if (unlikely(!item)) goto bad;
+        {{attr}} = {{component.from_py_function}}(item);
+        Py_DECREF(item);
+        if ({{component.error_condition(attr)}}) goto bad;
+    {{endfor}}
+    }
+#endif
+
     return result;
 bad:
     return result;
 }
 
 
-/////////////// ObjectAsUCS4.proto ///////////////
+/////////////// UnicodeAsUCS4.proto ///////////////
 
-static CYTHON_INLINE Py_UCS4 __Pyx_PyObject_AsPy_UCS4(PyObject*);
+static CYTHON_INLINE Py_UCS4 __Pyx_PyUnicode_AsPy_UCS4(PyObject*);
 
-/////////////// ObjectAsUCS4 ///////////////
+/////////////// UnicodeAsUCS4 ///////////////
 
-static CYTHON_INLINE Py_UCS4 __Pyx_PyObject_AsPy_UCS4(PyObject* x) {
-   long ival;
-   if (PyUnicode_Check(x)) {
-       Py_ssize_t length;
-       #if CYTHON_PEP393_ENABLED
-       length = PyUnicode_GET_LENGTH(x);
-       if (likely(length == 1)) {
-           return PyUnicode_READ_CHAR(x, 0);
-       }
-       #else
-       length = PyUnicode_GET_SIZE(x);
-       if (likely(length == 1)) {
-           return PyUnicode_AS_UNICODE(x)[0];
-       }
-       #if Py_UNICODE_SIZE == 2
-       else if (PyUnicode_GET_SIZE(x) == 2) {
-           Py_UCS4 high_val = PyUnicode_AS_UNICODE(x)[0];
-           if (high_val >= 0xD800 && high_val <= 0xDBFF) {
-               Py_UCS4 low_val = PyUnicode_AS_UNICODE(x)[1];
-               if (low_val >= 0xDC00 && low_val <= 0xDFFF) {
-                   return 0x10000 + (((high_val & ((1<<10)-1)) << 10) | (low_val & ((1<<10)-1)));
-               }
+static CYTHON_INLINE Py_UCS4 __Pyx_PyUnicode_AsPy_UCS4(PyObject* x) {
+   Py_ssize_t length;
+   #if CYTHON_PEP393_ENABLED
+   length = PyUnicode_GET_LENGTH(x);
+   if (likely(length == 1)) {
+       return PyUnicode_READ_CHAR(x, 0);
+   }
+   #else
+   length = PyUnicode_GET_SIZE(x);
+   if (likely(length == 1)) {
+       return PyUnicode_AS_UNICODE(x)[0];
+   }
+   #if Py_UNICODE_SIZE == 2
+   else if (PyUnicode_GET_SIZE(x) == 2) {
+       Py_UCS4 high_val = PyUnicode_AS_UNICODE(x)[0];
+       if (high_val >= 0xD800 && high_val <= 0xDBFF) {
+           Py_UCS4 low_val = PyUnicode_AS_UNICODE(x)[1];
+           if (low_val >= 0xDC00 && low_val <= 0xDFFF) {
+               return 0x10000 + (((high_val & ((1<<10)-1)) << 10) | (low_val & ((1<<10)-1)));
            }
        }
-       #endif
-       #endif
-       PyErr_Format(PyExc_ValueError,
-                    "only single character unicode strings can be converted to Py_UCS4, "
-                    "got length %" CYTHON_FORMAT_SSIZE_T "d", length);
-       return (Py_UCS4)-1;
    }
+   #endif
+   #endif
+   PyErr_Format(PyExc_ValueError,
+                "only single character unicode strings can be converted to Py_UCS4, "
+                "got length %" CYTHON_FORMAT_SSIZE_T "d", length);
+   return (Py_UCS4)-1;
+}
+
+
+/////////////// ObjectAsUCS4.proto ///////////////
+//@requires: UnicodeAsUCS4
+
+#define __Pyx_PyObject_AsPy_UCS4(x) \
+    (likely(PyUnicode_Check(x)) ? __Pyx_PyUnicode_AsPy_UCS4(x) : __Pyx__PyObject_AsPy_UCS4(x))
+static Py_UCS4 __Pyx__PyObject_AsPy_UCS4(PyObject*);
+
+/////////////// ObjectAsUCS4 ///////////////
+
+static Py_UCS4 __Pyx__PyObject_AsPy_UCS4(PyObject* x) {
+   long ival;
    ival = __Pyx_PyInt_As_long(x);
    if (unlikely(ival < 0)) {
        if (!PyErr_Occurred())
@@ -411,6 +469,7 @@ static CYTHON_INLINE Py_UCS4 __Pyx_PyObject_AsPy_UCS4(PyObject* x) {
    return (Py_UCS4)ival;
 }
 
+
 /////////////// ObjectAsPyUnicode.proto ///////////////
 
 static CYTHON_INLINE Py_UNICODE __Pyx_PyObject_AsPy_UNICODE(PyObject*);
@@ -475,14 +534,14 @@ static CYTHON_INLINE PyObject* {{TO_PY_FUNCTION}}({{TYPE}} value) {
             return PyInt_FromLong((long) value);
         } else if (sizeof({{TYPE}}) <= sizeof(unsigned long)) {
             return PyLong_FromUnsignedLong((unsigned long) value);
-        } else if (sizeof({{TYPE}}) <= sizeof(unsigned long long)) {
-            return PyLong_FromUnsignedLongLong((unsigned long long) value);
+        } else if (sizeof({{TYPE}}) <= sizeof(unsigned PY_LONG_LONG)) {
+            return PyLong_FromUnsignedLongLong((unsigned PY_LONG_LONG) value);
         }
     } else {
         if (sizeof({{TYPE}}) <= sizeof(long)) {
             return PyInt_FromLong((long) value);
-        } else if (sizeof({{TYPE}}) <= sizeof(long long)) {
-            return PyLong_FromLongLong((long long) value);
+        } else if (sizeof({{TYPE}}) <= sizeof(PY_LONG_LONG)) {
+            return PyLong_FromLongLong((PY_LONG_LONG) value);
         }
     }
     {
@@ -498,11 +557,19 @@ static CYTHON_INLINE PyObject* {{TO_PY_FUNCTION}}({{TYPE}} value) {
 
 // see CIntFromPy
 #define __PYX_VERIFY_RETURN_INT(target_type, func_type, func_value)       \
+    __PYX__VERIFY_RETURN_INT(target_type, func_type, func_value, 0)
+
+#define __PYX_VERIFY_RETURN_INT_EXC(target_type, func_type, func_value)   \
+    __PYX__VERIFY_RETURN_INT(target_type, func_type, func_value, 1)
+
+#define __PYX__VERIFY_RETURN_INT(target_type, func_type, func_value, exc) \
     {                                                                     \
         func_type value = func_value;                                     \
         if (sizeof(target_type) < sizeof(func_type)) {                    \
             if (unlikely(value != (func_type) (target_type) value)) {     \
                 func_type zero = 0;                                       \
+                if (exc && unlikely(value == (func_type)-1 && PyErr_Occurred()))  \
+                    return (target_type) -1;                              \
                 if (is_unsigned && unlikely(value < zero))                \
                     goto raise_neg_overflow;                              \
                 else                                                      \
@@ -515,10 +582,8 @@ static CYTHON_INLINE PyObject* {{TO_PY_FUNCTION}}({{TYPE}} value) {
 
 /////////////// PyLongInternals ///////////////
 
-#if CYTHON_COMPILING_IN_CPYTHON && PY_MAJOR_VERSION >= 3
- #if CYTHON_USE_PYLONG_INTERNALS
+#if CYTHON_USE_PYLONG_INTERNALS
   #include "longintrepr.h"
- #endif
 #endif
 
 
@@ -530,6 +595,8 @@ static CYTHON_INLINE {{TYPE}} {{FROM_PY_FUNCTION}}(PyObject *);
 //@requires: CIntFromPyVerify
 //@requires: PyLongInternals
 
+{{py: from Cython.Utility import pylong_join }}
+
 static CYTHON_INLINE {{TYPE}} {{FROM_PY_FUNCTION}}(PyObject *x) {
     const {{TYPE}} neg_one = ({{TYPE}}) -1, const_zero = 0;
     const int is_unsigned = neg_one > const_zero;
@@ -548,38 +615,70 @@ static CYTHON_INLINE {{TYPE}} {{FROM_PY_FUNCTION}}(PyObject *x) {
 #endif
     if (likely(PyLong_Check(x))) {
         if (is_unsigned) {
-#if CYTHON_COMPILING_IN_CPYTHON && PY_MAJOR_VERSION >= 3
- #if CYTHON_USE_PYLONG_INTERNALS
+#if CYTHON_USE_PYLONG_INTERNALS
+            const digit* digits = ((PyLongObject*)x)->ob_digit;
             switch (Py_SIZE(x)) {
                 case  0: return 0;
-                case  1: __PYX_VERIFY_RETURN_INT({{TYPE}}, digit, ((PyLongObject*)x)->ob_digit[0]);
+                case  1: __PYX_VERIFY_RETURN_INT({{TYPE}}, digit, digits[0])
+                {{for _size in (2, 3, 4)}}
+                case {{_size}}:
+                    if (8 * sizeof({{TYPE}}) > {{_size-1}} * PyLong_SHIFT) {
+                        if (8 * sizeof(unsigned long) > {{_size}} * PyLong_SHIFT) {
+                            __PYX_VERIFY_RETURN_INT({{TYPE}}, unsigned long, {{pylong_join(_size, 'digits')}})
+                        } else if (8 * sizeof({{TYPE}}) >= {{_size}} * PyLong_SHIFT) {
+                            return {{pylong_join(_size, 'digits', TYPE)}};
+                        }
+                    }
+                    break;
+                {{endfor}}
             }
- #endif
 #endif
 #if CYTHON_COMPILING_IN_CPYTHON
             if (unlikely(Py_SIZE(x) < 0)) {
                 goto raise_neg_overflow;
             }
+#else
+            {
+                // misuse Py_False as a quick way to compare to a '0' int object in PyPy
+                int result = PyObject_RichCompareBool(x, Py_False, Py_LT);
+                if (unlikely(result < 0))
+                    return ({{TYPE}}) -1;
+                if (unlikely(result == 1))
+                    goto raise_neg_overflow;
+            }
 #endif
             if (sizeof({{TYPE}}) <= sizeof(unsigned long)) {
-                __PYX_VERIFY_RETURN_INT({{TYPE}}, unsigned long, PyLong_AsUnsignedLong(x))
-            } else if (sizeof({{TYPE}}) <= sizeof(unsigned long long)) {
-                __PYX_VERIFY_RETURN_INT({{TYPE}}, unsigned long long, PyLong_AsUnsignedLongLong(x))
+                __PYX_VERIFY_RETURN_INT_EXC({{TYPE}}, unsigned long, PyLong_AsUnsignedLong(x))
+            } else if (sizeof({{TYPE}}) <= sizeof(unsigned PY_LONG_LONG)) {
+                __PYX_VERIFY_RETURN_INT_EXC({{TYPE}}, unsigned PY_LONG_LONG, PyLong_AsUnsignedLongLong(x))
             }
         } else {
-#if CYTHON_COMPILING_IN_CPYTHON && PY_MAJOR_VERSION >= 3
- #if CYTHON_USE_PYLONG_INTERNALS
+            // signed
+#if CYTHON_USE_PYLONG_INTERNALS
+            const digit* digits = ((PyLongObject*)x)->ob_digit;
             switch (Py_SIZE(x)) {
                 case  0: return 0;
-                case  1: __PYX_VERIFY_RETURN_INT({{TYPE}},  digit, +(((PyLongObject*)x)->ob_digit[0]));
-                case -1: __PYX_VERIFY_RETURN_INT({{TYPE}}, sdigit, -(sdigit) ((PyLongObject*)x)->ob_digit[0]);
+                case -1: __PYX_VERIFY_RETURN_INT({{TYPE}}, sdigit, -(sdigit) digits[0])
+                case  1: __PYX_VERIFY_RETURN_INT({{TYPE}},  digit, +digits[0])
+                {{for _size in (2, 3, 4)}}
+                {{for _case in (-_size, _size)}}
+                case {{_case}}:
+                    if (8 * sizeof({{TYPE}}){{' - 1' if _case < 0 else ''}} > {{_size-1}} * PyLong_SHIFT) {
+                        if (8 * sizeof(unsigned long) > {{_size}} * PyLong_SHIFT) {
+                            __PYX_VERIFY_RETURN_INT({{TYPE}}, {{'long' if _case < 0 else 'unsigned long'}}, {{'-(long) ' if _case < 0 else ''}}{{pylong_join(_size, 'digits')}})
+                        } else if (8 * sizeof({{TYPE}}) - 1 > {{_size}} * PyLong_SHIFT) {
+                            return {{'-' if _case < 0 else ''}}{{pylong_join(_size, 'digits', TYPE)}};
+                        }
+                    }
+                    break;
+                {{endfor}}
+                {{endfor}}
             }
- #endif
 #endif
             if (sizeof({{TYPE}}) <= sizeof(long)) {
-                __PYX_VERIFY_RETURN_INT({{TYPE}}, long, PyLong_AsLong(x))
-            } else if (sizeof({{TYPE}}) <= sizeof(long long)) {
-                __PYX_VERIFY_RETURN_INT({{TYPE}}, long long, PyLong_AsLongLong(x))
+                __PYX_VERIFY_RETURN_INT_EXC({{TYPE}}, long, PyLong_AsLong(x))
+            } else if (sizeof({{TYPE}}) <= sizeof(PY_LONG_LONG)) {
+                __PYX_VERIFY_RETURN_INT_EXC({{TYPE}}, PY_LONG_LONG, PyLong_AsLongLong(x))
             }
         }
         {
diff --git a/Cython/Utility/__init__.py b/Cython/Utility/__init__.py
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..40fe94b335acb64e44151f52f062cec1ea17cd5b 100644
--- a/Cython/Utility/__init__.py
+++ b/Cython/Utility/__init__.py
@@ -0,0 +1,29 @@
+
+def pylong_join(count, digits_ptr='digits', join_type='unsigned long'):
+    """
+    Generate an unrolled shift-then-or loop over the first 'count' digits.
+    Assumes that they fit into 'join_type'.
+
+    (((d[2] << n) | d[1]) << n) | d[0]
+    """
+    return ('(' * (count * 2) + "(%s)" % join_type + ' | '.join(
+        "%s[%d])%s)" % (digits_ptr, _i, " << PyLong_SHIFT" if _i else '')
+        for _i in range(count-1, -1, -1)))
+
+
+# although it could potentially make use of data independence,
+# this implementation is a bit slower than the simpler one above
+def _pylong_join(count, digits_ptr='digits', join_type='unsigned long'):
+    """
+    Generate an or-ed series of shifts for the first 'count' digits.
+    Assumes that they fit into 'join_type'.
+
+    (d[2] << 2*n) | (d[1] << 1*n) | d[0]
+    """
+    def shift(n):
+        # avoid compiler warnings for overly large shifts that will be discarded anyway
+        return " << (%d * PyLong_SHIFT < 8 * sizeof(%s) ? %d * PyLong_SHIFT : 0)" % (n, join_type, n) if n else ''
+
+    return '(%s)' % ' | '.join(
+        "(((%s)%s[%d])%s)" % (join_type, digits_ptr, i, shift(i))
+        for i in range(count-1, -1, -1))
diff --git a/appveyor.yml b/appveyor.yml
new file mode 100644
index 0000000000000000000000000000000000000000..bc37d2d4b3fa4dd226ef5b921e0a5f3043f2fcbf
--- /dev/null
+++ b/appveyor.yml
@@ -0,0 +1,56 @@
+environment:
+
+  global:
+    # SDK v7.0 MSVC Express 2008's SetEnv.cmd script will fail if the
+    # /E:ON and /V:ON options are not enabled in the batch script intepreter
+    # See: http://stackoverflow.com/a/13751649/163740
+    WITH_COMPILER: "cmd /E:ON /V:ON /C .\\appveyor\\run_with_compiler.cmd"
+
+  matrix:
+    - PYTHON: "C:\\Python27"
+      PYTHON_VERSION: "2.7.9"
+      PYTHON_ARCH: "32"
+
+    - PYTHON: "C:\\Python33"
+      PYTHON_VERSION: "3.3.6"
+      PYTHON_ARCH: "32"
+
+    - PYTHON: "C:\\Python34"
+      PYTHON_VERSION: "3.4.3"
+      PYTHON_ARCH: "32"
+
+    - PYTHON: "C:\\Python27-x64"
+      PYTHON_VERSION: "2.7.9"
+      PYTHON_ARCH: "64"
+      WINDOWS_SDK_VERSION: "v7.0"
+
+    - PYTHON: "C:\\Python33-x64"
+      PYTHON_VERSION: "3.3.6"
+      PYTHON_ARCH: "64"
+      WINDOWS_SDK_VERSION: "v7.1"
+
+    - PYTHON: "C:\\Python34-x64"
+      PYTHON_VERSION: "3.4.3"
+      PYTHON_ARCH: "64"
+      WINDOWS_SDK_VERSION: "v7.1"
+
+init:
+  - "ECHO %PYTHON% %PYTHON_VERSION% %PYTHON_ARCH%"
+
+install:
+  - "powershell appveyor\\install.ps1"
+  - "%PYTHON%\\python --version"
+
+build: off
+
+test_script:
+  - "%WITH_COMPILER% %PYTHON%\\python setup.py test"
+
+after_test:
+  - "%WITH_COMPILER% %PYTHON%\\python setup.py bdist_wheel"
+
+artifacts:
+  - path: dist\*
+
+#on_success:
+#  - TODO: upload the content of dist/*.whl to a public wheelhouse
diff --git a/appveyor/install.ps1 b/appveyor/install.ps1
new file mode 100644
index 0000000000000000000000000000000000000000..2f96d26b3384608343b01a6211cdedfb2d20857e
--- /dev/null
+++ b/appveyor/install.ps1
@@ -0,0 +1,85 @@
+# Sample script to install Python and pip under Windows
+# Authors: Olivier Grisel and Kyle Kastner
+# License: CC0 1.0 Universal: http://creativecommons.org/publicdomain/zero/1.0/
+
+$BASE_URL = "https://www.python.org/ftp/python/"
+$GET_PIP_URL = "https://bootstrap.pypa.io/get-pip.py"
+$GET_PIP_PATH = "C:\get-pip.py"
+
+
+function DownloadPython ($python_version, $platform_suffix) {
+    $webclient = New-Object System.Net.WebClient
+    $filename = "python-" + $python_version + $platform_suffix + ".msi"
+    $url = $BASE_URL + $python_version + "/" + $filename
+
+    $basedir = $pwd.Path + "\"
+    $filepath = $basedir + $filename
+    if (Test-Path $filename) {
+        Write-Host "Reusing" $filepath
+        return $filepath
+    }
+
+    # Download and retry up to 5 times in case of network transient errors.
+    Write-Host "Downloading" $filename "from" $url
+    $retry_attempts = 3
+    for($i=0; $i -lt $retry_attempts; $i++){
+        try {
+            $webclient.DownloadFile($url, $filepath)
+            break
+        }
+        Catch [Exception]{
+            Start-Sleep 1
+        }
+   }
+   Write-Host "File saved at" $filepath
+   return $filepath
+}
+
+
+function InstallPython ($python_version, $architecture, $python_home) {
+    Write-Host "Installing Python" $python_version "for" $architecture "bit architecture to" $python_home
+    if (Test-Path $python_home) {
+        Write-Host $python_home "already exists, skipping."
+        return $false
+    }
+    if ($architecture -eq "32") {
+        $platform_suffix = ""
+    } else {
+        $platform_suffix = ".amd64"
+    }
+    $filepath = DownloadPython $python_version $platform_suffix
+    Write-Host "Installing" $filepath "to" $python_home
+    $args = "/qn /i $filepath TARGETDIR=$python_home"
+    Write-Host "msiexec.exe" $args
+    Start-Process -FilePath "msiexec.exe" -ArgumentList $args -Wait -Passthru
+    Write-Host "Python $python_version ($architecture) installation complete"
+    return $true
+}
+
+
+function InstallPip ($python_home) {
+    $pip_path = $python_home + "\Scripts\pip.exe"
+    $python_path = $python_home + "\python.exe"
+    if (-not(Test-Path $pip_path)) {
+        Write-Host "Installing pip..."
+        $webclient = New-Object System.Net.WebClient
+        $webclient.DownloadFile($GET_PIP_URL, $GET_PIP_PATH)
+        Write-Host "Executing:" $python_path $GET_PIP_PATH
+        Start-Process -FilePath "$python_path" -ArgumentList "$GET_PIP_PATH" -Wait -Passthru
+    } else {
+        Write-Host "pip already installed."
+    }
+}
+
+function InstallPackage ($python_home, $pkg) {
+    $pip_path = $python_home + "\Scripts\pip.exe"
+    & $pip_path install $pkg
+}
+
+function main () {
+    InstallPython $env:PYTHON_VERSION $env:PYTHON_ARCH $env:PYTHON
+    InstallPip $env:PYTHON
+    InstallPackage $env:PYTHON wheel
+}
+
+main
diff --git a/appveyor/run_with_compiler.cmd b/appveyor/run_with_compiler.cmd
new file mode 100644
index 0000000000000000000000000000000000000000..3a472bc836c30415445def35bc58338a1cbe38c5
--- /dev/null
+++ b/appveyor/run_with_compiler.cmd
@@ -0,0 +1,47 @@
+:: To build extensions for 64 bit Python 3, we need to configure environment
+:: variables to use the MSVC 2010 C++ compilers from GRMSDKX_EN_DVD.iso of:
+:: MS Windows SDK for Windows 7 and .NET Framework 4 (SDK v7.1)
+::
+:: To build extensions for 64 bit Python 2, we need to configure environment
+:: variables to use the MSVC 2008 C++ compilers from GRMSDKX_EN_DVD.iso of:
+:: MS Windows SDK for Windows 7 and .NET Framework 3.5 (SDK v7.0)
+::
+:: 32 bit builds do not require specific environment configurations.
+::
+:: Note: this script needs to be run with the /E:ON and /V:ON flags for the
+:: cmd interpreter, at least for (SDK v7.0)
+::
+:: More details at:
+:: https://github.com/cython/cython/wiki/64BitCythonExtensionsOnWindows
+:: http://stackoverflow.com/a/13751649/163740
+::
+:: Author: Olivier Grisel
+:: License: CC0 1.0 Universal: http://creativecommons.org/publicdomain/zero/1.0/
+@ECHO OFF
+
+SET COMMAND_TO_RUN=%*
+SET WIN_SDK_ROOT=C:\Program Files\Microsoft SDKs\Windows
+
+SET MAJOR_PYTHON_VERSION="%PYTHON_VERSION:~0,1%"
+IF %MAJOR_PYTHON_VERSION% == "2" (
+    SET WINDOWS_SDK_VERSION="v7.0"
+) ELSE IF %MAJOR_PYTHON_VERSION% == "3" (
+    SET WINDOWS_SDK_VERSION="v7.1"
+) ELSE (
+    ECHO Unsupported Python version: "%MAJOR_PYTHON_VERSION%"
+    EXIT 1
+)
+
+IF "%PYTHON_ARCH%"=="64" (
+    ECHO Configuring Windows SDK %WINDOWS_SDK_VERSION% for Python %MAJOR_PYTHON_VERSION% on a 64 bit architecture
+    SET DISTUTILS_USE_SDK=1
+    SET MSSdk=1
+    "%WIN_SDK_ROOT%\%WINDOWS_SDK_VERSION%\Setup\WindowsSdkVer.exe" -q -version:%WINDOWS_SDK_VERSION%
+    "%WIN_SDK_ROOT%\%WINDOWS_SDK_VERSION%\Bin\SetEnv.cmd" /x64 /release
+    ECHO Executing: %COMMAND_TO_RUN%
+    call %COMMAND_TO_RUN% || EXIT 1
+) ELSE (
+    ECHO Using default MSVC build environment for 32 bit architecture
+    ECHO Executing: %COMMAND_TO_RUN%
+    call %COMMAND_TO_RUN% || EXIT 1
+)
diff --git a/docs/src/quickstart/build.rst b/docs/src/quickstart/build.rst
index 78ee142155a04a356e5f235b1200cbe482daaef8..41abf280009d8bf9c959b6ba2b16a3ab8814400c 100644
--- a/docs/src/quickstart/build.rst
+++ b/docs/src/quickstart/build.rst
@@ -60,9 +60,9 @@ use pip:
     (venv)$ ipython notebook
 
 To enable support for Cython compilation, install Cython and load the
-``cythonmagic`` extension from within IPython::
+``Cython`` extension from within IPython::
 
-    %load_ext cythonmagic
+    %load_ext Cython
 
 Then, prefix a cell with the ``%%cython`` marker to compile it::
 
diff --git a/docs/src/tutorial/memory_allocation.rst b/docs/src/tutorial/memory_allocation.rst
index 8d82e36f53bf49562fc54026f6e84211ab248840..eb0d45fadfbd1d58fe556090650fc4d976a21083 100644
--- a/docs/src/tutorial/memory_allocation.rst
+++ b/docs/src/tutorial/memory_allocation.rst
@@ -22,7 +22,7 @@ management in C.
 Simple C values and structs (such as a local variable ``cdef double x``) are
 usually allocated on the stack and passed by value, but for larger and more
 complicated objects (e.g. a dynamically-sized list of doubles), the memory must
-be manually requested and released.  C provides the functions :c:func`malloc`,
+be manually requested and released.  C provides the functions :c:func:`malloc`,
 :c:func:`realloc`, and :c:func:`free` for this purpose, which can be imported
 in cython from ``clibc.stdlib``. Their signatures are:
 
diff --git a/docs/src/tutorial/numpy.rst b/docs/src/tutorial/numpy.rst
index 54ea330972eac745aecb69c2e05ed84edc14b759..fa0cd2ab8b556a46f2cc1eb5e73862e2aacd9b6f 100644
--- a/docs/src/tutorial/numpy.rst
+++ b/docs/src/tutorial/numpy.rst
@@ -234,7 +234,7 @@ The array lookups are still slowed down by two factors:
 Now bounds checking is not performed (and, as a side-effect, if you ''do''
 happen to access out of bounds you will in the best case crash your program
 and in the worst case corrupt data). It is possible to switch bounds-checking
-mode in many ways, see [:reference/directives:compiler directives] for more
+mode in many ways, see :ref:`compiler-directives` for more
 information.
 
 Negative indices are dealt with by ensuring Cython that the indices will be
diff --git a/docs/src/userguide/pypy.rst b/docs/src/userguide/pypy.rst
index 6d1dd5b1f34cdeb66fd3278b9fdb26fd4bc71996..e0fd09c549e38e8f404ca1b3eff33ff43d9c5b72 100644
--- a/docs/src/userguide/pypy.rst
+++ b/docs/src/userguide/pypy.rst
@@ -1,8 +1,8 @@
 Porting Cython code to PyPy
-============================
+===========================
 
 Since version 0.17, Cython has basic support for cpyext, the layer in
-`PyPy <http://pypy.org>`_ that emulates CPython's C-API.  This is
+`PyPy <http://pypy.org/>`_ that emulates CPython's C-API.  This is
 achieved by making the generated C code adapt at C compile time, so
 the generated code will compile in both CPython and PyPy unchanged.
 
@@ -14,7 +14,7 @@ that works in both CPython and PyPy.
 
 
 Reference counts
------------------
+----------------
 
 A general design difference in PyPy is that the runtime does not use
 reference counting internally but always a garbage collector.  Reference
@@ -25,7 +25,7 @@ any references held in Python space.
 
 
 Object lifetime
-----------------
+---------------
 
 As a direct consequence of the different garbage collection characteristics,
 objects may see the end of their lifetime at other points than in
@@ -45,7 +45,7 @@ e.g. when context managers can be used together with the ``with`` statement.
 
 
 Borrowed references and data pointers
---------------------------------------
+-------------------------------------
 
 The memory management in PyPy is allowed to move objects around in memory.
 The C-API layer is only an indirect view on PyPy objects and often replicates
@@ -88,7 +88,7 @@ when done with it to convert it into an owned reference.
 
 
 Builtin types, slots and fields
---------------------------------
+-------------------------------
 
 The following builtin types are not currently available in cpyext in
 form of their C level representation: :c:type:`PyComplexObject`,
@@ -110,8 +110,19 @@ protocols for object operations.  Cython will map them to an appropriate
 usage of the C-API in both CPython and cpyext.
 
 
+GIL handling
+------------
+
+Currently, the GIL handling function :c:func:`PyGILState_Ensure` is not
+re-entrant in PyPy and deadlocks when called twice.  This means that
+code that tries to acquire the GIL "just in case", because it might be
+called with or without the GIL, will not work as expected in PyPy.
+See `PyGILState_Ensure should not deadlock if GIL already held
+<https://bitbucket.org/pypy/pypy/issue/1778>`_.
+
+
 Efficiency
------------
+----------
 
 Simple functions and especially macros that are used for speed in CPython
 may exhibit substantially different performance characteristics in cpyext.
@@ -137,16 +148,19 @@ than Cython currently does, it's best to fix Cython for everyone's benefit.
 
 
 Known problems
----------------
+--------------
 
 * As of PyPy 1.9, subtyping builtin types can result in infinite recursion
   on method calls in some rare cases.
 
 * Docstrings of special methods are not propagated to Python space.
 
+* The Python 3.x adaptations in pypy3 only slowly start to include the
+  C-API, so more incompatibilities can be expected there.
+
 
 Bugs and crashes
------------------
+----------------
 
 The cpyext implementation in PyPy is much younger and substantially less
 mature than the well tested C-API and its underlying native implementation
diff --git a/docs/src/userguide/source_files_and_compilation.rst b/docs/src/userguide/source_files_and_compilation.rst
index 1ec52e1170f9bad06b9bb4999539705629ca8f5b..6a0486a2be8fc183f0475fca6ec79e9a145c9994 100644
--- a/docs/src/userguide/source_files_and_compilation.rst
+++ b/docs/src/userguide/source_files_and_compilation.rst
@@ -68,7 +68,7 @@ explicitly, you can use glob patterns::
 You can also use glob patterns in :class:`Extension` objects if you pass
 them through :func:`cythonize`::
 
-    extensions = [Extension("*", "*.pyx")]
+    extensions = [Extension("*", ["*.pyx"])]
 
     setup(
         ext_modules = cythonize(extensions)
diff --git a/runtests.py b/runtests.py
index a0f0c92ab6abe92a53bdaeb13e10b520610a4755..e4b7b586f024b0c58206539e69486d8d24f72536 100755
--- a/runtests.py
+++ b/runtests.py
@@ -98,14 +98,15 @@ def get_distutils_distro(_cache=[]):
 
 
 EXT_DEP_MODULES = {
-    'tag:numpy' : 'numpy',
-    'tag:pstats': 'pstats',
-    'tag:posix' : 'posix',
-    'tag:array' : 'array',
+    'tag:numpy':    'numpy',
+    'tag:asyncio':  'asyncio',
+    'tag:pstats':   'pstats',
+    'tag:posix':    'posix',
+    'tag:array':    'array',
     'tag:coverage': 'Cython.Coverage',
-    'Coverage': 'Cython.Coverage',
-    'tag:ipython': 'IPython',
-    'tag:jedi': 'jedi',
+    'Coverage':     'Cython.Coverage',
+    'tag:ipython':  'IPython',
+    'tag:jedi':     'jedi',
 }
 
 def patch_inspect_isfunction():
@@ -271,6 +272,10 @@ def get_openmp_compiler_flags(language):
     if not gcc_version:
         return None # not gcc - FIXME: do something about other compilers
 
+    # gcc defines "__int128_t", assume that at least all 64 bit architectures have it
+    global COMPILER_HAS_INT128
+    COMPILER_HAS_INT128 = getattr(sys, 'maxsize', getattr(sys, 'maxint', 0)) > 2**60
+
     compiler_version = gcc_version.group(1)
     if compiler_version and compiler_version.split('.') >= ['4', '2']:
         return '-fopenmp', '-fopenmp'
@@ -280,6 +285,8 @@ try:
 except locale.Error:
     pass
 
+COMPILER = None
+COMPILER_HAS_INT128 = False
 OPENMP_C_COMPILER_FLAGS = get_openmp_compiler_flags('c')
 OPENMP_CPP_COMPILER_FLAGS = get_openmp_compiler_flags('cpp')
 
@@ -322,12 +329,12 @@ VER_DEP_MODULES = {
     (3,1): (_is_py3_before_32, lambda x: x in ['run.pyclass_special_methods',
                                                ]),
     (3,3) : (operator.lt, lambda x: x in ['build.package_compilation',
+                                          'run.yield_from_py33',
                                           ]),
-    (3,4,0,'beta',3) : (operator.le, lambda x: x in ['run.py34_signature',
-                                          ]),
+    (3,4): (operator.lt, lambda x: x in ['run.py34_signature',
+                                         ]),
 }
 
-COMPILER = None
 INCLUDE_DIRS = [ d for d in os.getenv('INCLUDE', '').split(os.pathsep) if d ]
 CFLAGS = os.getenv('CFLAGS', '').split()
 CCACHE = os.getenv('CYTHON_RUNTESTS_CCACHE', '').split()
@@ -1693,7 +1700,7 @@ def main():
                       action="store_true", default=False,
                       help="only compile pyx to c, do not run C compiler or run the tests")
     parser.add_option("--no-refnanny", dest="with_refnanny",
-                      action="store_false", default=not IS_PYPY,
+                      action="store_false", default=True,
                       help="do not regression test reference counting")
     parser.add_option("--no-fork", dest="fork",
                       action="store_false", default=True,
@@ -1933,7 +1940,7 @@ def runtests(options, cmd_args, coverage=None):
 
     try:
         import jedi
-        if list(map(int, re.findall('[0-9]+', jedi.__version__ or '0'))) < [0, 8, 1]:
+        if not ([0, 8, 1] <= list(map(int, re.findall('[0-9]+', jedi.__version__ or '0'))) < [0, 9]):
             raise ImportError
     except (ImportError, AttributeError, TypeError):
         exclude_selectors.append(RegExSelector('Jedi'))
@@ -1941,11 +1948,17 @@ def runtests(options, cmd_args, coverage=None):
     if options.exclude:
         exclude_selectors += [ string_selector(r) for r in options.exclude ]
 
+    if not COMPILER_HAS_INT128 or not IS_CPYTHON:
+        exclude_selectors += [RegExSelector('int128')]
+
     if options.shard_num > -1:
         exclude_selectors.append(ShardExcludeSelector(options.shard_num, options.shard_count))
 
     if not test_bugs:
-        exclude_selectors += [ FileListExcluder(os.path.join(ROOTDIR, "bugs.txt"), verbose=verbose_excludes) ]
+        exclude_selectors += [
+            FileListExcluder(os.path.join(ROOTDIR, bugs_file_name), verbose=verbose_excludes)
+            for bugs_file_name in ['bugs.txt'] + (['pypy_bugs.txt'] if IS_PYPY else [])
+        ]
 
     if sys.platform in ['win32', 'cygwin'] and sys.version_info < (2,6):
         exclude_selectors += [ lambda x: x == "run.specialfloat" ]
diff --git a/setup.py b/setup.py
index c9e6f1a1c8287f237e5c344885e9c6a331a2a23a..b5698f6a78ddfd6069c61c518c5b19bbb0b4d6d2 100755
--- a/setup.py
+++ b/setup.py
@@ -6,6 +6,7 @@ except ImportError:
 import os
 import stat
 import subprocess
+import textwrap
 import sys
 
 import platform
@@ -313,48 +314,45 @@ if include_debugger:
     setup_args['package_data']['Cython.Debugger.Tests'] = ['codefile', 'cfuncs.c']
 
 setup(
-  name = 'Cython',
-  version = version,
-  url = 'http://www.cython.org',
-  author = 'Robert Bradshaw, Stefan Behnel, Dag Seljebotn, Greg Ewing, et al.',
-  author_email = 'cython-devel@python.org',
-  description = "The Cython compiler for writing C extensions for the Python language.",
-  long_description = """\
-  The Cython language makes writing C extensions for the Python language as
-  easy as Python itself.  Cython is a source code translator based on the
-  well-known Pyrex_, but supports more cutting edge functionality and
-  optimizations.
-
-  The Cython language is very close to the Python language (and most Python
-  code is also valid Cython code), but Cython additionally supports calling C
-  functions and declaring C types on variables and class attributes. This
-  allows the compiler to generate very efficient C code from Cython code.
-
-  This makes Cython the ideal language for writing glue code for external C
-  libraries, and for fast C modules that speed up the execution of Python
-  code.
-
-  .. _Pyrex: http://www.cosc.canterbury.ac.nz/greg.ewing/python/Pyrex/
-  """,
-  classifiers = [
-    "Development Status :: 5 - Production/Stable",
-    "Intended Audience :: Developers",
-    "License :: OSI Approved :: Apache Software License",
-    "Operating System :: OS Independent",
-    "Programming Language :: Python",
-    "Programming Language :: Python :: 2",
-    "Programming Language :: Python :: 3",
-    "Programming Language :: C",
-    "Programming Language :: Cython",
-    "Topic :: Software Development :: Code Generators",
-    "Topic :: Software Development :: Compilers",
-    "Topic :: Software Development :: Libraries :: Python Modules"
-  ],
-
-  scripts = scripts,
-  packages=packages,
-
-  py_modules = ["cython"],
-
-  **setup_args
-  )
+    name='Cython',
+    version=version,
+    url='http://www.cython.org',
+    author='Robert Bradshaw, Stefan Behnel, Dag Seljebotn, Greg Ewing, et al.',
+    author_email='cython-devel@python.org',
+    description="The Cython compiler for writing C extensions for the Python language.",
+    long_description=textwrap.dedent("""\
+    The Cython language makes writing C extensions for the Python language as
+    easy as Python itself.  Cython is a source code translator based on Pyrex_,
+    but supports more cutting edge functionality and optimizations.
+
+    The Cython language is very close to the Python language (and most Python
+    code is also valid Cython code), but Cython additionally supports calling C
+    functions and declaring C types on variables and class attributes. This
+    allows the compiler to generate very efficient C code from Cython code.
+
+    This makes Cython the ideal language for writing glue code for external C
+    libraries, and for fast C modules that speed up the execution of Python
+    code.
+
+    .. _Pyrex: http://www.cosc.canterbury.ac.nz/greg.ewing/python/Pyrex/
+    """),
+    classifiers=[
+        "Development Status :: 5 - Production/Stable",
+        "Intended Audience :: Developers",
+        "License :: OSI Approved :: Apache Software License",
+        "Operating System :: OS Independent",
+        "Programming Language :: Python",
+        "Programming Language :: Python :: 2",
+        "Programming Language :: Python :: 3",
+        "Programming Language :: C",
+        "Programming Language :: Cython",
+        "Topic :: Software Development :: Code Generators",
+        "Topic :: Software Development :: Compilers",
+        "Topic :: Software Development :: Libraries :: Python Modules"
+    ],
+
+    scripts=scripts,
+    packages=packages,
+    py_modules=["cython"],
+    **setup_args
+)
diff --git a/tests/bugs.txt b/tests/bugs.txt
index 5235bc933725db2b6f7b7aeebc5877a52263c83b..62c5e5d89b56c0b9a4376e1762ed8ce9b7f5f392 100644
--- a/tests/bugs.txt
+++ b/tests/bugs.txt
@@ -44,6 +44,8 @@ pyregr.test_exceptions
 pyregr.test_subprocess
 pyregr.test_zipfile64
 pyregr.test_tuple
+pyregr.test_urllib2net
+pyregr.test_urllibnet
 
 # Inlined generators
 all
diff --git a/tests/build/common_include_dir.srctree b/tests/build/common_include_dir.srctree
index a03bac28a9c351329ae5aa8b865537764a838bc6..8867c46210708bb8c521606f6e2f8eecc2c709e8 100644
--- a/tests/build/common_include_dir.srctree
+++ b/tests/build/common_include_dir.srctree
@@ -14,18 +14,21 @@ PYTHON fake_grep.py -c '#include "common/AddTraceback_impl_.*h"' c.c
 
 ######## setup.py ########
 
+import sys
 from Cython.Build.Dependencies import cythonize
 
 from distutils.core import setup
 
 # Test concurrent safety if multiprocessing is available.
 # (In particular, TravisCI does not support spawning processes from tests.)
-try:
-    import multiprocessing
-    multiprocessing.Pool(2).close()
-    nthreads = 2
-except (ImportError, OSError):
-    nthreads = 0
+nthreads = 0
+if not hasattr(sys, 'pypy_version_info'):
+    try:
+        import multiprocessing
+        multiprocessing.Pool(2).close()
+        nthreads = 2
+    except (ImportError, OSError):
+        pass
 
 setup(
   ext_modules = cythonize("*.pyx", common_utility_include_dir='common', nthreads=nthreads),
diff --git a/tests/compile/distutils_libraries_T845.srctree b/tests/compile/distutils_libraries_T845.srctree
new file mode 100644
index 0000000000000000000000000000000000000000..69c85492c705608bfb478ccf1c81889c5e334c5e
--- /dev/null
+++ b/tests/compile/distutils_libraries_T845.srctree
@@ -0,0 +1,33 @@
+PYTHON setup.py build_ext --inplace
+
+######## setup.py ########
+
+from Cython.Build import cythonize
+from Cython.Distutils.extension import Extension
+
+ext_modules = [
+    Extension("a", ["a.pyx"]),
+    Extension("x", ["x.pyx"]),
+    Extension("y", ["y.pyx"]),
+]
+
+ext_modules = cythonize(ext_modules)
+
+assert ext_modules[1].libraries == ["lib_x"]
+assert ext_modules[2].libraries == ["lib_y"]
+
+######## libx.pxd ########
+# distutils: libraries = lib_x
+
+######## liby.pxd ########
+# distutils: libraries = lib_y
+
+######## a.pyx ########
+cimport libx
+cimport liby
+
+######## x.pyx ########
+cimport libx
+
+######## y.pyx ########
+cimport liby
diff --git a/tests/errors/callargs.pyx b/tests/errors/callargs.pyx
index 73db3a9776653566a1cac8512f5bdd28a15cb3b2..edcd702b7b43621831c92757444d0957602adb26 100644
--- a/tests/errors/callargs.pyx
+++ b/tests/errors/callargs.pyx
@@ -7,16 +7,21 @@ args   = (1,2,3)
 kwargs = {u"test" : "toast"}
 
 def test():
+    # ok
+    f(1, 2, c=3, *args, d=5, **kwargs, **kwargs)
+    f(1, 2, c=3, *args, d=5, **kwargs, x=6)
+    f(1, 2, **kwargs, c=3)
+    f(1, 2, c=3, *args, *args, **kwargs)
     f(*args, 1, 2, 3)
+    # errors
     f(**kwargs, 1, 2, c=3)
     f(*args, **kwargs, *args)
     f(1, 2, c=3, *args, **kwargs, *args)
-    f(1, 2, c=3, *args, d=5, **kwargs, **kwargs)
-    f(1, 2, c=3, *args, d=5, **kwargs, x=6)
     f(1=2)
 
+
 # too bad we don't get more errors here ...
 
 _ERRORS = u"""
-10:13: Non-keyword arg following star-arg
+17:16: Non-keyword arg following keyword arg
 """
diff --git a/tests/errors/e_relative_cimport.pyx b/tests/errors/e_relative_cimport.pyx
index b15ab4801a742a17e39a70e64cb7694a12c55926..36a134411e133b3ac35252573b8e9840539c9468 100644
--- a/tests/errors/e_relative_cimport.pyx
+++ b/tests/errors/e_relative_cimport.pyx
@@ -2,16 +2,14 @@
 # tag: cimport
 
 from ..relative_cimport cimport some_name
-
+from .e_relative_cimport cimport some_name
 from ..cython cimport declare
+from . cimport e_relative_cimport
 
 
 _ERRORS="""
-4:0: 'relative_cimport.pxd' not found
-4:0: 'some_name.pxd' not found
 4:0: relative cimport beyond main package is not allowed
-4:32: Name 'some_name' not declared in module 'relative_cimport'
-6:0: 'declare.pxd' not found
+5:0: relative cimport beyond main package is not allowed
 6:0: relative cimport beyond main package is not allowed
-6:22: Name 'declare' not declared in module 'cython'
+7:0: relative cimport beyond main package is not allowed
 """
diff --git a/tests/errors/extended_unpacking.pyx b/tests/errors/extended_unpacking.pyx
index eeae75670786fa7c42d485d62fb3fd2b35b8397e..c5b5f6145b32bbcf6549b2ebf0a7fac858125bf6 100644
--- a/tests/errors/extended_unpacking.pyx
+++ b/tests/errors/extended_unpacking.pyx
@@ -16,6 +16,8 @@ def syntax1():
     [*a, *b]
 
     (a, b, *c, d, e, f, *g, h, i)
+    [a, b, *c, d, e, f, *g, h, i]
+    {a, b, *c, d, e, f, *g, h, i}
 
 
 def syntax2():
@@ -33,19 +35,15 @@ def types(l):
 
 _ERRORS = u"""
 # syntax1()
- 8: 4: can use starred expression only as assignment target
-10: 4: can use starred expression only as assignment target
-12: 4: can use starred expression only as assignment target
-14: 4: can use starred expression only as assignment target
-16: 5: can use starred expression only as assignment target
-16: 9: can use starred expression only as assignment target
-18:11: can use starred expression only as assignment target
-18:24: can use starred expression only as assignment target
+ 8: 4: starred expression is not allowed here
+10: 4: starred expression is not allowed here
+12: 4: starred expression is not allowed here
+14: 4: starred expression is not allowed here
 
 # syntax2()
-24:11: more than 1 starred expression in assignment
+26:11: more than 1 starred expression in assignment
 
 # types()
-30:15: Cannot coerce list to type 'int'
-31:10: starred target must have Python object (list) type
+32:15: Cannot coerce list to type 'int'
+33:10: starred target must have Python object (list) type
 """
diff --git a/tests/errors/nogil.pyx b/tests/errors/nogil.pyx
index 98b694049585f9c6a499aaf4a3c0994de1890429..9ccea843863d87f33d4d88f3be29b9f14bbe23e6 100644
--- a/tests/errors/nogil.pyx
+++ b/tests/errors/nogil.pyx
@@ -42,6 +42,7 @@ cdef object m():
         (x, y)
         [x, y]
         {x: y}
+        {x, y}
         obj and x
         t(obj)
 #        f(42) # Cython handles this internally
@@ -129,35 +130,37 @@ _ERRORS = u"""
 42:9: Discarding owned Python object not allowed without gil
 43:8: Constructing Python list not allowed without gil
 43:8: Discarding owned Python object not allowed without gil
-44:8: Constructing Python dict not allowed without gil
-44:8: Discarding owned Python object not allowed without gil
-45:12: Discarding owned Python object not allowed without gil
-45:12: Truth-testing Python object not allowed without gil
-46:13: Python type test not allowed without gil
-48:10: Discarding owned Python object not allowed without gil
-48:10: Operation not allowed without gil
-49:8: Discarding owned Python object not allowed without gil
-49:8: Operation not allowed without gil
-50:10: Assignment of Python object not allowed without gil
-50:14: Assignment of Python object not allowed without gil
-51:9: Assignment of Python object not allowed without gil
-51:13: Assignment of Python object not allowed without gil
-51:16: Creating temporary Python reference not allowed without gil
-51:19: Creating temporary Python reference not allowed without gil
-52:11: Assignment of Python object not allowed without gil
-52:11: Indexing Python object not allowed without gil
-53:11: Accessing Python attribute not allowed without gil
+44:10: Constructing Python dict not allowed without gil
+44:10: Discarding owned Python object not allowed without gil
+45:10: Constructing Python set not allowed without gil
+45:10: Discarding owned Python object not allowed without gil
+46:12: Discarding owned Python object not allowed without gil
+46:12: Truth-testing Python object not allowed without gil
+47:13: Python type test not allowed without gil
+49:10: Discarding owned Python object not allowed without gil
+49:10: Operation not allowed without gil
+50:8: Discarding owned Python object not allowed without gil
+50:8: Operation not allowed without gil
+51:10: Assignment of Python object not allowed without gil
+51:14: Assignment of Python object not allowed without gil
+52:9: Assignment of Python object not allowed without gil
+52:13: Assignment of Python object not allowed without gil
+52:16: Creating temporary Python reference not allowed without gil
+52:19: Creating temporary Python reference not allowed without gil
 53:11: Assignment of Python object not allowed without gil
-54:8: Constructing Python tuple not allowed without gil
-54:8: Python print statement not allowed without gil
-55:8: Deleting Python object not allowed without gil
-56:8: Returning Python object not allowed without gil
-57:8: Raising exception not allowed without gil
-58:14: Truth-testing Python object not allowed without gil
-60:17: Truth-testing Python object not allowed without gil
-62:8: For-loop using object bounds or target not allowed without gil
-62:14: Coercion from Python not allowed without the GIL
-62:25: Coercion from Python not allowed without the GIL
-64:8: Try-except statement not allowed without gil
-85:8: For-loop using object bounds or target not allowed without gil
+53:11: Indexing Python object not allowed without gil
+54:11: Accessing Python attribute not allowed without gil
+54:11: Assignment of Python object not allowed without gil
+55:8: Constructing Python tuple not allowed without gil
+55:8: Python print statement not allowed without gil
+56:8: Deleting Python object not allowed without gil
+57:8: Returning Python object not allowed without gil
+58:8: Raising exception not allowed without gil
+59:14: Truth-testing Python object not allowed without gil
+61:17: Truth-testing Python object not allowed without gil
+63:8: For-loop using object bounds or target not allowed without gil
+63:14: Coercion from Python not allowed without the GIL
+63:25: Coercion from Python not allowed without the GIL
+65:8: Try-except statement not allowed without gil
+86:8: For-loop using object bounds or target not allowed without gil
 """
diff --git a/tests/errors/pep448_syntax_1.pyx b/tests/errors/pep448_syntax_1.pyx
new file mode 100644
index 0000000000000000000000000000000000000000..ca262971462ca2f08ef5858194f794d31baff84d
--- /dev/null
+++ b/tests/errors/pep448_syntax_1.pyx
@@ -0,0 +1,10 @@
+# mode: error
+# tag: pep448
+
+def unpack_mix():
+    [*1, **1]
+
+
+_ERRORS = """
+5:9: Expected an identifier or literal
+"""
diff --git a/tests/errors/pep448_syntax_2.pyx b/tests/errors/pep448_syntax_2.pyx
new file mode 100644
index 0000000000000000000000000000000000000000..45027af931b3b82ffbc14ae60f64bdd48319010d
--- /dev/null
+++ b/tests/errors/pep448_syntax_2.pyx
@@ -0,0 +1,10 @@
+# mode: error
+# tag: pep448
+
+def unpack_wrong_stars():
+    [**1]
+
+
+_ERRORS = """
+5:5: Expected an identifier or literal
+"""
diff --git a/tests/errors/pep448_syntax_3.pyx b/tests/errors/pep448_syntax_3.pyx
new file mode 100644
index 0000000000000000000000000000000000000000..e81119e32e6a9b9c59956a47df7fbe5553d45421
--- /dev/null
+++ b/tests/errors/pep448_syntax_3.pyx
@@ -0,0 +1,10 @@
+# mode: error
+# tag: pep448
+
+def unpack_mix_in_set():
+    {*1, **2}
+
+
+_ERRORS = """
+5:9: unexpected **item found in set literal
+"""
diff --git a/tests/pypy_bugs.txt b/tests/pypy_bugs.txt
new file mode 100644
index 0000000000000000000000000000000000000000..4651cc0bf0c77ad0237a9cf58feea3c2b15658e2
--- /dev/null
+++ b/tests/pypy_bugs.txt
@@ -0,0 +1,43 @@
+# This file contains tests corresponding to unresolved bugs
+# either in PyPy, PyPy's cpyext, or Cython under PyPy,
+# which will be skipped in the normal testing run.
+
+broken_exception
+bufaccess
+exarkun
+memoryview
+memslice
+sequential_parallel
+setjmp
+yield_from_pep380
+memoryview_inplace_division
+
+# GIL issues
+# https://bitbucket.org/pypy/pypy/issue/2025/cpyext-finish-implementation-of
+run.exceptions_nogil
+run.nogil
+run.with_gil
+run.parallel
+
+# gc issue?
+memoryview_in_subclasses
+external_ref_reassignment
+run.exttype_dealloc
+
+# https://bitbucket.org/pypy/pypy/issue/2023/cpyext-pydict_keys-values-items-does-not
+builtin_subtype_methods_cy3
+
+# bugs in cpyext
+run.special_methods_T561
+run.special_methods_T561_py2
+
+# tests for things that don't exist in cpyext
+compile.pylong
+run.datetime_pxd
+run.datetime_cimport
+run.datetime_members
+run.extern_builtins_T258
+run.unicode_ascii_auto_encoding
+run.unicode_default_auto_encoding
+run.str_ascii_auto_encoding
+run.str_default_auto_encoding
diff --git a/tests/run/addop.pyx b/tests/run/addop.pyx
index e283043470f47c38b653bea8c879efb3b793759a..c8d474be1bdbf98f25015f195611b11314fc1d33 100644
--- a/tests/run/addop.pyx
+++ b/tests/run/addop.pyx
@@ -1,6 +1,10 @@
 cimport cython
 
 
+def bigint(x):
+    print(str(x).rstrip('L'))
+
+
 def mixed_test():
     """
     >>> mixed_test()
@@ -29,6 +33,10 @@ def add_x_1(x):
     2
     >>> add_x_1(-1)
     0
+    >>> bigint(2**50 + 1)
+    1125899906842625
+    >>> bigint(add_x_1(2**50))
+    1125899906842625
     >>> add_x_1(1.5)
     2.5
     >>> add_x_1(-1.5)
@@ -73,13 +81,17 @@ def add_x_large(x):
     -1073741824.0
     >>> add_x_large(2**30 + 1)
     2147483649
+    >>> bigint(2**50 + 1 + 2**30)
+    1125900980584449
+    >>> bigint(add_x_large(2**50 + 1))
+    1125900980584449
     >>> 2**31 + 2**30
     3221225472
     >>> add_x_large(2**31)
     3221225472
-    >>> print(2**66 + 2**30)
+    >>> bigint(2**66 + 2**30)
     73786976295911948288
-    >>> print(add_x_large(2**66))
+    >>> bigint(add_x_large(2**66))
     73786976295911948288
     >>> try: add_x_large("abc")
     ... except TypeError: pass
@@ -96,6 +108,10 @@ def add_1_x(x):
     2
     >>> add_1_x(-1)
     0
+    >>> bigint(2**50 + 1)
+    1125899906842625
+    >>> bigint(add_1_x(2**50))
+    1125899906842625
     >>> add_1_x(1.5)
     2.5
     >>> add_1_x(-1.5)
@@ -115,6 +131,12 @@ def add_1f_x(x):
     2.0
     >>> add_1f_x(-1)
     0.0
+    >>> 1.0 + 2**52
+    4503599627370497.0
+    >>> add_1f_x(2**52)
+    4503599627370497.0
+    >>> add_1f_x(2**60) == 1.0 + 2**60 or add_1f_x(2**60)
+    True
     >>> add_1f_x(1.5)
     2.5
     >>> add_1f_x(-1.5)
diff --git a/tests/run/asyncio_generators.srctree b/tests/run/asyncio_generators.srctree
new file mode 100644
index 0000000000000000000000000000000000000000..d8d7215353ad300a8d09b412471dfcd2593755cb
--- /dev/null
+++ b/tests/run/asyncio_generators.srctree
@@ -0,0 +1,103 @@
+# mode: run
+# tag: asyncio
+
+"""
+PYTHON setup.py build_ext -i
+PYTHON test_from_import.py
+PYTHON test_import.py
+PYTHON test_both.py
+"""
+
+######## setup.py ########
+
+from Cython.Build.Dependencies import cythonize
+from distutils.core import setup
+
+setup(
+  ext_modules = cythonize("*.pyx"),
+)
+
+
+######## test_from_import.py ########
+
+import from_asyncio_import
+import asyncio
+
+def runloop(task):
+    loop = asyncio.get_event_loop()
+    result = loop.run_until_complete(task())
+    assert 3 == result, result
+
+runloop(from_asyncio_import.wait3)
+
+
+######## test_import.py ########
+
+import import_asyncio
+import asyncio
+
+def runloop(task):
+    loop = asyncio.get_event_loop()
+    result = loop.run_until_complete(task())
+    assert 3 == result, result
+
+runloop(import_asyncio.wait3)
+
+
+######## test_both.py ########
+
+import asyncio
+
+def runloop(task):
+    loop = asyncio.get_event_loop()
+    result = loop.run_until_complete(task())
+    assert 3 == result, result
+
+import import_asyncio
+runloop(import_asyncio.wait3)       # 1a)
+import from_asyncio_import
+runloop(from_asyncio_import.wait3)  # 1b)
+
+runloop(from_asyncio_import.wait3)  # 2a)
+runloop(import_asyncio.wait3)       # 2b)
+runloop(from_asyncio_import.wait3)  # 3a)
+runloop(import_asyncio.wait3)       # 3b)
+
+try:
+    from collections.abc import Generator
+except ImportError:
+    from collections import Generator
+
+assert isinstance(from_asyncio_import.wait3(), Generator)
+assert isinstance(import_asyncio.wait3(), Generator)
+assert isinstance((lambda:(yield))(), Generator)
+
+
+######## import_asyncio.pyx ########
+# cython: binding=True
+
+import asyncio
+
+@asyncio.coroutine
+def wait3():
+    counter = 0
+    for i in range(3):
+        print(counter)
+        yield from asyncio.sleep(0.01)
+        counter += 1
+    return counter
+
+
+######## from_asyncio_import.pyx ########
+# cython: binding=True
+
+from asyncio import coroutine, sleep
+
+@coroutine
+def wait3():
+    counter = 0
+    for i in range(3):
+        print(counter)
+        yield from sleep(0.01)
+        counter += 1
+    return counter
diff --git a/tests/run/builtin_ord.pyx b/tests/run/builtin_ord.pyx
index f9bf0bb7697c50d4e97f11ad706e012da384d26c..84eb1021167ab629e7c058af3c7091602f91230e 100644
--- a/tests/run/builtin_ord.pyx
+++ b/tests/run/builtin_ord.pyx
@@ -1,11 +1,18 @@
 
 cimport cython
 
+import sys
+
 uspace = u' '
 ustring_with_a = u'abcdefg'
 ustring_without_a = u'bcdefg'
 
-@cython.test_fail_if_path_exists('//SimpleCallNode')
+
+@cython.test_assert_path_exists(
+    # ord() should receive and return a C value
+    '//ReturnStatNode//CoerceToPyTypeNode//SimpleCallNode')
+@cython.test_fail_if_path_exists(
+    '//ReturnStatNode//SimpleCallNode//CoerceToPyTypeNode')
 def ord_Py_UNICODE(unicode s):
     """
     >>> ord_Py_UNICODE(uspace)
@@ -15,17 +22,23 @@ def ord_Py_UNICODE(unicode s):
     u = s[0]
     return ord(u)
 
-@cython.test_assert_path_exists('//IntNode')
+
+@cython.test_assert_path_exists('//TupleNode//IntNode')
 @cython.test_fail_if_path_exists('//SimpleCallNode')
 def ord_const():
     """
-    >>> ord_const()
+    >>> ord(b' ')
+    32
+    >>> ord(' ')
     32
+    >>> ord_const()
+    (32, 32, 32, 255, 255, 4660, 0)
     """
-    return ord(u' ')
+    return ord(u' '), ord(b' '), ord(' '), ord('\xff'), ord(b'\xff'), ord(u'\u1234'), ord('\0')
+
 
 @cython.test_assert_path_exists('//PrimaryCmpNode//IntNode')
-@cython.test_fail_if_path_exists('//SimpleCallNode')
+#@cython.test_fail_if_path_exists('//SimpleCallNode')
 def unicode_for_loop_ord(unicode s):
     """
     >>> unicode_for_loop_ord(ustring_with_a)
@@ -37,3 +50,43 @@ def unicode_for_loop_ord(unicode s):
         if ord(c) == ord(u'a'):
             return True
     return False
+
+
+def compare_to_char(s):
+    """
+    >>> compare_to_char(uspace)
+    False
+    >>> compare_to_char(b'a')
+    False
+    >>> compare_to_char(b'x')
+    True
+    >>> compare_to_char('x')
+    True
+    """
+    cdef char c = b'x'
+    return ord(s) == c
+
+
+def ord_object(s):
+    """
+    >>> try: ord_object('abc')
+    ... except ValueError: assert sys.version_info[0] >= 3
+    ... except TypeError: assert sys.version_info[0] < 3
+    >>> ord_object('a')
+    97
+    >>> ord_object(b'a')
+    97
+    """
+    return ord(s)
+
+
+def non_builtin_ord(s):
+    """
+    >>> non_builtin_ord('x')
+    (123, 123)
+    """
+    def _ord(s):
+        return 123
+
+    ord = _ord
+    return ord(s), _ord(s)
diff --git a/tests/run/builtins_truth_test.pyx b/tests/run/builtins_truth_test.pyx
index be20d64c9f5fc16791ea9c226978ceb4c5f3e7b8..cad7162f6b72cf82fd61b8a46202f46ee2a16d32 100644
--- a/tests/run/builtins_truth_test.pyx
+++ b/tests/run/builtins_truth_test.pyx
@@ -10,6 +10,7 @@ def bool_list(list obj):
     """
     return bool(obj)
 
+
 def if_list(list obj):
     """
     >>> if_list( [] )
@@ -24,6 +25,7 @@ def if_list(list obj):
     else:
         return False
 
+
 def if_list_nogil(list obj):
     """
     >>> if_list_nogil( [] )
@@ -41,6 +43,7 @@ def if_list_nogil(list obj):
             result = False
     return result
 
+
 def if_list_literal(t):
     """
     >>> if_list_literal(True)
@@ -71,6 +74,7 @@ def bool_tuple(tuple obj):
     """
     return bool(obj)
 
+
 def if_tuple(tuple obj):
     """
     >>> if_tuple( () )
@@ -85,6 +89,7 @@ def if_tuple(tuple obj):
     else:
         return False
 
+
 def if_tuple_literal(t):
     """
     >>> if_tuple_literal(True)
@@ -104,6 +109,97 @@ def if_tuple_literal(t):
             return False
 
 
+def bool_set(set obj):
+    """
+    >>> bool_set( set() )
+    False
+    >>> bool_set( set([1]) )
+    True
+    >>> bool_set(None)
+    False
+    """
+    return bool(obj)
+
+
+def if_set(set obj):
+    """
+    >>> if_set( set() )
+    False
+    >>> if_set( set([1]) )
+    True
+    >>> if_set(None)
+    False
+    """
+    if obj:
+        return True
+    else:
+        return False
+
+
+def if_set_nogil(set obj):
+    """
+    >>> if_set_nogil( set() )
+    False
+    >>> if_set_nogil( set([1]) )
+    True
+    >>> if_set_nogil(None)
+    False
+    """
+    cdef bint result
+    with nogil:
+        if obj:
+            result = True
+        else:
+            result = False
+    return result
+
+
+def if_set_literal(t):
+    """
+    >>> if_set_literal(True)
+    True
+    >>> if_set_literal(False)
+    False
+    """
+    if t:
+        if {1,2,3}:
+            return True
+        else:
+            return False
+    else:
+        if set():
+            return True
+        else:
+            return False
+
+
+def bool_frozenset(frozenset obj):
+    """
+    >>> bool_frozenset( frozenset() )
+    False
+    >>> bool_frozenset( frozenset([1]) )
+    True
+    >>> bool_frozenset(None)
+    False
+    """
+    return bool(obj)
+
+
+def if_frozenset(frozenset obj):
+    """
+    >>> if_frozenset( frozenset() )
+    False
+    >>> if_frozenset( frozenset([1]) )
+    True
+    >>> if_frozenset(None)
+    False
+    """
+    if obj:
+        return True
+    else:
+        return False
+
+
 b0 = b''
 b1 = b'abc'
 
diff --git a/tests/run/c_int_types_T255.pyx b/tests/run/c_int_types_T255.pyx
index 4e94309612524a8305f9eb0c1e57b54fa0dd7fa6..df79ca059784aa5a0ae5fa2201844d127edb3759 100644
--- a/tests/run/c_int_types_T255.pyx
+++ b/tests/run/c_int_types_T255.pyx
@@ -22,7 +22,7 @@ def test_schar(signed char x):
    >>> test_schar(128) #doctest: +ELLIPSIS
    Traceback (most recent call last):
        ...
-   OverflowError: ...
+   OverflowError: value too large to convert to signed char
    """
    return x
 
@@ -43,7 +43,7 @@ def test_add_schar(x, y):
    >>> test_add_schar(SCHAR_MAX, 1) #doctest: +ELLIPSIS
    Traceback (most recent call last):
        ...
-   OverflowError: ...
+   OverflowError: value too large to convert to signed char
    """
    cdef signed char r = x + y
    return r
@@ -55,7 +55,7 @@ def test_uchar(unsigned char x):
    >>> test_uchar(-1) #doctest: +ELLIPSIS
    Traceback (most recent call last):
        ...
-   OverflowError: ...
+   OverflowError: can't convert negative value to unsigned char
    >>> test_uchar(0)
    0
    >>> test_uchar(1)
@@ -65,7 +65,7 @@ def test_uchar(unsigned char x):
    >>> test_uchar(UCHAR_MAX+1) #doctest: +ELLIPSIS
    Traceback (most recent call last):
        ...
-   OverflowError: ...
+   OverflowError: value too large to convert to unsigned char
    """
    return x
 
@@ -76,7 +76,7 @@ def test_add_uchar(x, y):
    >>> test_add_uchar(UCHAR_MAX, 1) #doctest: +ELLIPSIS
    Traceback (most recent call last):
        ...
-   OverflowError: ...
+   OverflowError: value too large to convert to unsigned char
    """
    cdef unsigned char r = x + y
    return r
@@ -95,7 +95,7 @@ def test_char(char x):
    Traceback (most recent call last):
        ...
    OverflowError: ...
-   >>> if CHAR_MIN < 0: 
+   >>> if CHAR_MIN < 0:
    ...     assert test_char(-1) == -1
    >>> test_char(CHAR_MIN) == CHAR_MIN
    True
@@ -108,7 +108,7 @@ def test_char(char x):
    >>> test_char(CHAR_MAX+1) #doctest: +ELLIPSIS
    Traceback (most recent call last):
        ...
-   OverflowError: ...
+   OverflowError: value too large to convert to char
    """
    return x
 
@@ -129,7 +129,7 @@ def test_add_char(x, y):
    >>> test_add_char(CHAR_MAX, 1) #doctest: +ELLIPSIS
    Traceback (most recent call last):
        ...
-   OverflowError: ...
+   OverflowError: value too large to convert to char
    """
    cdef char r = x + y
    return r
@@ -144,7 +144,7 @@ def test_short(short x):
    >>> test_short(SHORT_MIN-1) #doctest: +ELLIPSIS
    Traceback (most recent call last):
        ...
-   OverflowError: ...
+   OverflowError: value too large to convert to short
    >>> test_short(SHORT_MIN) == SHORT_MIN
    True
    >>> test_short(-1)
@@ -158,7 +158,7 @@ def test_short(short x):
    >>> test_short(SHORT_MAX+1) #doctest: +ELLIPSIS
    Traceback (most recent call last):
        ...
-   OverflowError: ...
+   OverflowError: value too large to convert to short
    """
    return x
 
@@ -167,7 +167,7 @@ def test_add_short(x, y):
    >>> test_add_short(SHORT_MIN, -1) #doctest: +ELLIPSIS
    Traceback (most recent call last):
        ...
-   OverflowError: ...
+   OverflowError: value too large to convert to short
    >>> test_add_short(SHORT_MIN, 0) == SHORT_MIN
    True
    >>> test_add_short(SHORT_MIN, 1) == SHORT_MIN+1
@@ -179,7 +179,7 @@ def test_add_short(x, y):
    >>> test_add_short(SHORT_MAX, 1) #doctest: +ELLIPSIS
    Traceback (most recent call last):
        ...
-   OverflowError: ...
+   OverflowError: value too large to convert to short
    """
    cdef short r = x + y
    return r
@@ -192,7 +192,7 @@ def test_sshort(short x):
    >>> test_sshort(SSHORT_MIN-1) #doctest: +ELLIPSIS
    Traceback (most recent call last):
        ...
-   OverflowError: ...
+   OverflowError: value too large to convert to short
    >>> test_sshort(SSHORT_MIN) == SSHORT_MIN
    True
    >>> test_sshort(-1)
@@ -206,7 +206,7 @@ def test_sshort(short x):
    >>> test_short(SSHORT_MAX+1) #doctest: +ELLIPSIS
    Traceback (most recent call last):
        ...
-   OverflowError: ...
+   OverflowError: value too large to convert to short
    """
    return x
 
@@ -215,7 +215,7 @@ def test_add_sshort(x, y):
    >>> test_add_sshort(SSHORT_MIN, -1) #doctest: +ELLIPSIS
    Traceback (most recent call last):
        ...
-   OverflowError: ...
+   OverflowError: value too large to convert to signed short
    >>> test_add_sshort(SSHORT_MIN, 0) == SSHORT_MIN
    True
    >>> test_add_sshort(SSHORT_MIN, 1) == SSHORT_MIN+1
@@ -227,7 +227,7 @@ def test_add_sshort(x, y):
    >>> test_add_sshort(SSHORT_MAX, 1) #doctest: +ELLIPSIS
    Traceback (most recent call last):
        ...
-   OverflowError: ...
+   OverflowError: value too large to convert to signed short
    """
    cdef signed short r = x + y
    return r
@@ -239,7 +239,7 @@ def test_ushort(unsigned short x):
    >>> test_ushort(-1) #doctest: +ELLIPSIS
    Traceback (most recent call last):
        ...
-   OverflowError: ...
+   OverflowError: can't convert negative value to unsigned short
    >>> test_ushort(0)
    0
    >>> test_ushort(1)
@@ -260,7 +260,7 @@ def test_add_ushort(x, y):
    >>> test_add_ushort(USHORT_MAX, 1) #doctest: +ELLIPSIS
    Traceback (most recent call last):
        ...
-   OverflowError: ...
+   OverflowError: value too large to convert to unsigned short
    """
    cdef unsigned short r = x + y
    return r
@@ -318,7 +318,7 @@ def test_add_int(x, y):
 SINT_MAX = <signed int>((<unsigned int>-1)>>1)
 SINT_MIN = (-SINT_MAX-1)
 
-def test_sint(int x):
+def test_sint(signed int x):
    u"""
    >>> test_sint(SINT_MIN-1) #doctest: +ELLIPSIS
    Traceback (most recent call last):
@@ -370,7 +370,7 @@ def test_uint(unsigned int x):
    >>> test_uint(-1) #doctest: +ELLIPSIS
    Traceback (most recent call last):
        ...
-   OverflowError: ...
+   OverflowError: can't convert negative value to unsigned int
    >>> print(test_uint(0))
    0
    >>> print(test_uint(1))
@@ -449,7 +449,7 @@ def test_add_long(x, y):
 SLONG_MAX = <signed long>((<unsigned long>-1)>>1)
 SLONG_MIN = (-SLONG_MAX-1)
 
-def test_slong(long x):
+def test_slong(signed long x):
    u"""
    >>> test_slong(SLONG_MIN-1) #doctest: +ELLIPSIS
    Traceback (most recent call last):
@@ -501,7 +501,7 @@ def test_ulong(unsigned long x):
    >>> test_ulong(-1) #doctest: +ELLIPSIS
    Traceback (most recent call last):
        ...
-   OverflowError: ...
+   OverflowError: can't convert negative value to unsigned long
    >>> print(test_ulong(0))
    0
    >>> print(test_ulong(1))
@@ -632,7 +632,7 @@ def test_ulonglong(unsigned long long x):
    >>> test_ulonglong(-1) #doctest: +ELLIPSIS
    Traceback (most recent call last):
        ...
-   OverflowError: ...
+   OverflowError: can't convert negative value to unsigned PY_LONG_LONG
    >>> print(test_ulonglong(0))
    0
    >>> print(test_ulonglong(1))
diff --git a/tests/run/closure_inside_cdef_T554.pyx b/tests/run/closure_inside_cdef_T554.pyx
index 494f17fac19ff3d4ba15fb73e00de8a617f23c98..5c84a447ffd7c49f4c403a16cc7f74a4989a7e26 100644
--- a/tests/run/closure_inside_cdef_T554.pyx
+++ b/tests/run/closure_inside_cdef_T554.pyx
@@ -9,6 +9,23 @@ def call_f(x):
     """
     return f(x)
 
+
 cdef f(x):                # def  here => works fine
-   def g(y): return y*x  # cdef here => compile error
-   return g(x)           # faults@ INCREF(.*cur_scope->.*v_x
+   def g(y): return y*x   # cdef here => compile error
+   return g(x)            # faults@ INCREF(.*cur_scope->.*v_x
+
+
+def closure_in_void():
+    """
+    >>> genex = closure_in_void()
+    >>> list(genex)
+    ['a', 'b', 'c']
+    """
+    l = []
+    add_gen(l)
+    return l[0]
+
+
+cdef void add_gen(l):
+    x = "abc"
+    l.append((c for c in x))
diff --git a/tests/run/cpdef_extern_func.pyx b/tests/run/cpdef_extern_func.pyx
index 8fcdda26b9f62fd3cc5d3464824bd81a1248d83f..5dffd2992c118d6d30fba906b398e5f52c1537d1 100644
--- a/tests/run/cpdef_extern_func.pyx
+++ b/tests/run/cpdef_extern_func.pyx
@@ -8,10 +8,9 @@ __doc__ = """
 2.0
 >>> pxd_sqrt(9)
 3.0
->>> log(10)
+>>> log(10)  # doctest: +ELLIPSIS
 Traceback (most recent call last):
-...
-NameError: name 'log' is not defined
+NameError: ...name 'log' is not defined
 >>> strchr('abcabc', ord('c'))
 'cabc'
 >>> strchr(needle=ord('c'), haystack='abcabc')
diff --git a/tests/run/cpp_stl_string.pyx b/tests/run/cpp_stl_string.pyx
index bf4b5343754f4c65dc6298c2829ab65a461f2432..4ee1847be78fc7ee25c06edd0869e1ff8d964430 100644
--- a/tests/run/cpp_stl_string.pyx
+++ b/tests/run/cpp_stl_string.pyx
@@ -167,6 +167,29 @@ def test_decode(char* a):
     cdef string b = string(a)
     return b.decode('ascii')
 
+
+@cython.test_assert_path_exists("//ReturnStatNode//PythonCapiCallNode")
+def test_cstr_decode(char* a):
+    """
+    >>> print(test_cstr_decode(b_asdf))
+    asdf
+    """
+    cdef string b = string(a)
+    return b.c_str().decode('utf-8')
+
+
+@cython.test_assert_path_exists("//ReturnStatNode//PythonCapiCallNode")
+@cython.test_fail_if_path_exists("//ReturnStatNode//AttributeNode")
+def test_cstr_ptr_decode(char* a):
+    """
+    >>> print(test_cstr_ptr_decode(b_asdf))
+    asdf
+    """
+    cdef string b = string(a)
+    s = b.c_str()
+    return s.decode('utf-8')
+
+
 @cython.test_assert_path_exists("//PythonCapiCallNode")
 @cython.test_fail_if_path_exists("//AttributeNode")
 def test_decode_sliced(char* a):
diff --git a/tests/run/cpp_template_ref_args.h b/tests/run/cpp_template_ref_args.h
index fa4e770f327094dac167fa0013e7164fb2f849e1..098c6f11ebd6fb2a445e9751bfc412e00e1470a6 100644
--- a/tests/run/cpp_template_ref_args.h
+++ b/tests/run/cpp_template_ref_args.h
@@ -4,6 +4,7 @@
 template <typename T>
 struct Bar {
     Bar & ref() { return *this; }
+    const Bar & const_ref() { return *this; }
     T value;
 };
 
diff --git a/tests/run/cpp_template_ref_args.pyx b/tests/run/cpp_template_ref_args.pyx
index 526cef97af6c27d06254fc4455b202183043e040..2a37a98f18ea7675c0a169b6c4ae6c0ed2206f60 100644
--- a/tests/run/cpp_template_ref_args.pyx
+++ b/tests/run/cpp_template_ref_args.pyx
@@ -8,6 +8,7 @@ cdef extern from "cpp_template_ref_args.h":
         # bug: Bar[T] created before class fully defined
         T value
         Bar[T] & ref() except +
+        const Bar[T] & const_ref() except +
 
     cdef cppclass Foo[T]:
         Foo()
@@ -33,8 +34,8 @@ def test_template_ref_arg(int x):
 def test_template_ref_attr(int x):
     """
     >>> test_template_ref_attr(4)
-    4
+    (4, 4)
     """
     cdef Bar[int] bar
     bar.value = x
-    return bar.ref().value
+    return bar.ref().value, bar.const_ref().value
diff --git a/tests/run/ctypedef_int_types_T333.pyx b/tests/run/ctypedef_int_types_T333.pyx
index 4cfe35b9a8240615c2d30334ba34a7cf09105254..3f1a99f69e4abdcd986c2c8435083d753adf30eb 100644
--- a/tests/run/ctypedef_int_types_T333.pyx
+++ b/tests/run/ctypedef_int_types_T333.pyx
@@ -25,7 +25,7 @@ def test_schar(SChar x):
    >>> test_schar(-129) #doctest: +ELLIPSIS
    Traceback (most recent call last):
        ...
-   OverflowError: ...
+   OverflowError: value too large to convert to SChar
    >>> test_schar(-128)
    -128
    >>> test_schar(0)
@@ -35,7 +35,7 @@ def test_schar(SChar x):
    >>> test_schar(128) #doctest: +ELLIPSIS
    Traceback (most recent call last):
        ...
-   OverflowError: ...
+   OverflowError: value too large to convert to SChar
    """
    return x
 
@@ -44,7 +44,7 @@ def test_add_schar(x, y):
    >>> test_add_schar(SCHAR_MIN, -1) #doctest: +ELLIPSIS
    Traceback (most recent call last):
        ...
-   OverflowError: ...
+   OverflowError: value too large to convert to SChar
    >>> test_add_schar(SCHAR_MIN, 0) == SCHAR_MIN
    True
    >>> test_add_schar(SCHAR_MIN, 1) == SCHAR_MIN+1
@@ -56,7 +56,7 @@ def test_add_schar(x, y):
    >>> test_add_schar(SCHAR_MAX, 1) #doctest: +ELLIPSIS
    Traceback (most recent call last):
        ...
-   OverflowError: ...
+   OverflowError: value too large to convert to SChar
    """
    cdef SChar r = x + y
    return r
@@ -68,7 +68,7 @@ def test_uchar(UChar x):
    >>> test_uchar(-1) #doctest: +ELLIPSIS
    Traceback (most recent call last):
        ...
-   OverflowError: ...
+   OverflowError: can't convert negative value to UChar
    >>> test_uchar(0)
    0
    >>> test_uchar(1)
@@ -78,7 +78,7 @@ def test_uchar(UChar x):
    >>> test_uchar(UCHAR_MAX+1) #doctest: +ELLIPSIS
    Traceback (most recent call last):
        ...
-   OverflowError: ...
+   OverflowError: value too large to convert to UChar
    """
    return x
 
@@ -89,7 +89,7 @@ def test_add_uchar(x, y):
    >>> test_add_uchar(UCHAR_MAX, 1) #doctest: +ELLIPSIS
    Traceback (most recent call last):
        ...
-   OverflowError: ...
+   OverflowError: value too large to convert to UChar
    """
    cdef UChar r = x + y
    return r
@@ -99,12 +99,12 @@ def test_add_uchar(x, y):
 SSHORT_MAX = <SShort>((<UShort>-1)>>1)
 SSHORT_MIN = (-SSHORT_MAX-1)
 
-def test_sshort(short x):
+def test_sshort(SShort x):
    u"""
    >>> test_sshort(SSHORT_MIN-1) #doctest: +ELLIPSIS
    Traceback (most recent call last):
        ...
-   OverflowError: ...
+   OverflowError: value too large to convert to SShort
    >>> test_sshort(SSHORT_MIN) == SSHORT_MIN
    True
    >>> test_sshort(-1)
@@ -127,7 +127,7 @@ def test_add_sshort(x, y):
    >>> test_add_sshort(SSHORT_MIN, -1) #doctest: +ELLIPSIS
    Traceback (most recent call last):
        ...
-   OverflowError: ...
+   OverflowError: value too large to convert to SShort
    >>> test_add_sshort(SSHORT_MIN, 0) == SSHORT_MIN
    True
    >>> test_add_sshort(SSHORT_MIN, 1) == SSHORT_MIN+1
@@ -139,7 +139,7 @@ def test_add_sshort(x, y):
    >>> test_add_sshort(SSHORT_MAX, 1) #doctest: +ELLIPSIS
    Traceback (most recent call last):
        ...
-   OverflowError: ...
+   OverflowError: value too large to convert to SShort
    """
    cdef SShort r = x + y
    return r
@@ -151,7 +151,7 @@ def test_ushort(UShort x):
    >>> test_ushort(-1) #doctest: +ELLIPSIS
    Traceback (most recent call last):
        ...
-   OverflowError: ...
+   OverflowError: can't convert negative value to UShort
    >>> test_ushort(0)
    0
    >>> test_ushort(1)
@@ -161,7 +161,7 @@ def test_ushort(UShort x):
    >>> test_ushort(USHORT_MAX+1) #doctest: +ELLIPSIS
    Traceback (most recent call last):
        ...
-   OverflowError: ...
+   OverflowError: value too large to convert to UShort
    """
    return x
 
@@ -172,7 +172,7 @@ def test_add_ushort(x, y):
    >>> test_add_ushort(USHORT_MAX, 1) #doctest: +ELLIPSIS
    Traceback (most recent call last):
        ...
-   OverflowError: ...
+   OverflowError: value too large to convert to UShort
    """
    cdef UShort r = x + y
    return r
@@ -182,7 +182,7 @@ def test_add_ushort(x, y):
 SINT_MAX = <SInt>((<UInt>-1)>>1)
 SINT_MIN = (-SINT_MAX-1)
 
-def test_sint(int x):
+def test_sint(SInt x):
    u"""
    >>> test_sint(SINT_MIN-1) #doctest: +ELLIPSIS
    Traceback (most recent call last):
@@ -234,7 +234,7 @@ def test_uint(UInt x):
    >>> test_uint(-1) #doctest: +ELLIPSIS
    Traceback (most recent call last):
        ...
-   OverflowError: ...
+   OverflowError: can't convert negative value to UInt
    >>> print(test_uint(0))
    0
    >>> print(test_uint(1))
@@ -317,7 +317,7 @@ def test_ulong(ULong x):
    >>> test_ulong(-1) #doctest: +ELLIPSIS
    Traceback (most recent call last):
        ...
-   OverflowError: ...
+   OverflowError: can't convert negative value to ULong
    >>> print(test_ulong(0))
    0
    >>> print(test_ulong(1))
@@ -400,7 +400,7 @@ def test_ulonglong(ULongLong x):
    >>> test_ulonglong(-1) #doctest: +ELLIPSIS
    Traceback (most recent call last):
        ...
-   OverflowError: ...
+   OverflowError: can't convert negative value to ULongLong
    >>> print(test_ulonglong(0))
    0
    >>> print(test_ulonglong(1))
@@ -554,7 +554,7 @@ def test_MyUInt2(MyUInt2 x):
    >>> test_MyUInt2(-1) #doctest: +ELLIPSIS
    Traceback (most recent call last):
        ...
-   OverflowError: ...
+   OverflowError: can't convert negative value to ...
    >>> test_MyUInt2(0)
    0
    >>> test_MyUInt2(1)
@@ -582,7 +582,7 @@ def test_DefUChar(defs.UChar x):
    >>> test_DefUChar(-1) #doctest: +ELLIPSIS
    Traceback (most recent call last):
        ...
-   OverflowError: ...
+   OverflowError: can't convert negative value to ...
    >>> test_DefUChar(0)
    0
    >>> test_DefUChar(1)
@@ -606,7 +606,7 @@ def test_ExtUInt(defs.ExtUInt x):
    >>> test_ExtUInt(-1) #doctest: +ELLIPSIS
    Traceback (most recent call last):
        ...
-   OverflowError: ...
+   OverflowError: can't convert negative value to ...
    >>> test_ExtUInt(0)
    0
    >>> test_ExtUInt(1)
@@ -634,7 +634,7 @@ def test_LocUInt(LocUInt x):
    >>> test_LocUInt(-1) #doctest: +ELLIPSIS
    Traceback (most recent call last):
        ...
-   OverflowError: ...
+   OverflowError: can't convert negative value to ...
    >>> test_LocUInt(0)
    0
    >>> test_LocUInt(1)
diff --git a/tests/run/dict.pyx b/tests/run/dict.pyx
index 850cd7991de7ccae9eb97fdb42bd0286bb1b5020..ea93e4c557228ba144ae373e6e8af8b2f79647ab 100644
--- a/tests/run/dict.pyx
+++ b/tests/run/dict.pyx
@@ -1,3 +1,8 @@
+import sys
+
+IS_PY35 = sys.version_info >= (3, 5)
+
+
 def empty():
     """
     >>> empty()
@@ -90,15 +95,15 @@ def item_creation_sideeffect(L, sideeffect, unhashable):
     >>> L = []
     >>> item_creation_sideeffect(L, sideeffect, unhashable)  # doctest: +ELLIPSIS
     Traceback (most recent call last):
-    TypeError:... unhashable ...
+    TypeError: ...unhashable...
     >>> L
     [2, 4]
 
     >>> L = []
     >>> {1:2, sideeffect(2): 3, 3: 4, unhashable(4): 5, sideeffect(5): 6}  # doctest: +ELLIPSIS
     Traceback (most recent call last):
-    TypeError:... unhashable ...
-    >>> L
-    [2, 4]
+    TypeError: ...unhashable...
+    >>> L if IS_PY35 else (L + [5])
+    [2, 4, 5]
     """
     return {1:2, sideeffect(2): 3, 3: 4, unhashable(4): 5, sideeffect(5): 6}
diff --git a/tests/run/embedsignatures.pyx b/tests/run/embedsignatures.pyx
index 0bfebfefbaf30068a58202c6a3c36e4cfbe50bcc..781cd21181a76d1d0096446194248329dbfe61bb 100644
--- a/tests/run/embedsignatures.pyx
+++ b/tests/run/embedsignatures.pyx
@@ -199,6 +199,9 @@ __doc__ = ur"""
 
     >>> print(funcdoc(f_defexpr5))
     f_defexpr5(int x=4)
+
+    >>> print(funcdoc(f_charptr_null))
+    f_charptr_null(char *s=NULL) -> char *
 """
 
 cdef class Ext:
@@ -403,6 +406,10 @@ cpdef f_defexpr4(int x = (Ext.CONST1 + FLAG1) * Ext.CONST2):
 cpdef f_defexpr5(int x = 2+2):
     pass
 
+cpdef (char*) f_charptr_null(char* s=NULL):
+    return s or b'abc'
+
+
 # no signatures for lambda functions
 lambda_foo = lambda x: 10
 lambda_bar = lambda x: 20
diff --git a/tests/run/float_division.pyx b/tests/run/float_division.pyx
new file mode 100644
index 0000000000000000000000000000000000000000..36d6009384608eef2a3c510b1fd1c4c18803d073
--- /dev/null
+++ b/tests/run/float_division.pyx
@@ -0,0 +1,200 @@
+# mode: run
+# tag: division
+
+
+def int_by_float():
+    """
+    >>> int_by_float()
+    0.5
+    """
+    return 1 / 2.0
+
+
+def float_by_int():
+    """
+    >>> float_by_int()
+    2.0
+    """
+    return 2.0 / 1
+
+
+def float_by_float():
+    """
+    >>> float_by_float()
+    1.5
+    """
+    return 3.0 / 2.0
+
+
+def div_1_by(x):
+    """
+    >>> div_1_by(1.0)
+    1.0
+    >>> div_1_by(2.0)
+    0.5
+    >>> div_1_by(0.5)
+    2.0
+    >>> 1.0 / float('inf')
+    0.0
+    >>> div_1_by(float('inf'))
+    0.0
+    >>> div_1_by(float('-inf'))
+    -0.0
+    >>> div_1_by(float('nan'))
+    nan
+    """
+    return 1.0 / x
+
+
+def div_by_2(x):
+    """
+    >>> div_by_2(1.0)
+    0.5
+    >>> float('inf') / 2.0
+    inf
+    >>> div_by_2(float('inf'))
+    inf
+    >>> div_by_2(float('-inf'))
+    -inf
+    >>> float('nan') / 2.0
+    nan
+    >>> div_by_2(float('nan'))
+    nan
+    """
+    return x / 2.0
+
+
+def div_by_neg_2(x):
+    """
+    >>> div_by_neg_2(1.0)
+    -0.5
+    >>> div_by_neg_2(-1.0)
+    0.5
+    >>> (-2**14) / (-2.0)
+    8192.0
+    >>> div_by_neg_2(-2**14)
+    8192.0
+    >>> (-2**52) / (-2.0)
+    2251799813685248.0
+    >>> div_by_neg_2(-2**52)
+    2251799813685248.0
+    >>> (-2**53-1) / (-2.0)
+    4503599627370496.0
+    >>> div_by_neg_2(-2**53-1)
+    4503599627370496.0
+    >>> float('inf') / -2.0
+    -inf
+    >>> div_by_neg_2(float('inf'))
+    -inf
+    >>> div_by_neg_2(float('-inf'))
+    inf
+    >>> float('nan') / -2.0
+    nan
+    >>> div_by_neg_2(float('nan'))
+    nan
+    """
+    return x / -2.0
+
+
+def div_neg_2_by(x):
+    """
+    >>> div_neg_2_by(1.0)
+    -2.0
+    >>> div_neg_2_by(-1)
+    2.0
+    >>> div_neg_2_by(-2.0)
+    1.0
+    >>> div_neg_2_by(-2)
+    1.0
+    >>> -2.0 / float('inf')
+    -0.0
+    >>> div_neg_2_by(float('inf'))
+    -0.0
+    >>> div_neg_2_by(float('-inf'))
+    0.0
+    >>> float('nan') / -2.0
+    nan
+    >>> div_neg_2_by(float('nan'))
+    nan
+    """
+    return (-2.0) / x
+
+
+def div_by_nan(x):
+    """
+    >>> 1.0 / float('nan')
+    nan
+    >>> div_by_nan(1.0)
+    nan
+    >>> float('nan') / float('nan')
+    nan
+    >>> div_by_nan(float('nan'))
+    nan
+    >>> float('inf') / float('nan')
+    nan
+    >>> div_by_nan(float('inf'))
+    nan
+    """
+    return x / float("nan")
+
+
+def div_nan_by(x):
+    """
+    >>> float('nan') / 1.0
+    nan
+    >>> div_nan_by(1.0)
+    nan
+    >>> float('nan') / float('nan')
+    nan
+    >>> div_nan_by(float('nan'))
+    nan
+    """
+    return float("nan") / x
+
+
+def div_by_inf(x):
+    """
+    >>> 1 / float('inf')
+    0.0
+    >>> div_by_inf(1)
+    0.0
+    >>> 1.0 / float('inf')
+    0.0
+    >>> div_by_inf(1.0)
+    0.0
+    >>> div_by_inf(float('inf'))
+    nan
+    """
+    return x / float("inf")
+
+
+def div_inf_by(x):
+    """
+    >>> float('inf') / 1.0
+    inf
+    >>> div_inf_by(1.0)
+    inf
+    >>> float('inf') / float('nan')
+    nan
+    >>> div_inf_by(float('nan'))
+    nan
+    >>> float('inf') / float('-inf')
+    nan
+    >>> div_inf_by(float('-inf'))
+    nan
+    """
+    return float("inf") / x
+
+
+def div_neg_inf_by(x):
+    """
+    >>> float('-inf') / 1.0
+    -inf
+    >>> div_neg_inf_by(1.0)
+    -inf
+    >>> float('-inf') / -1.0
+    inf
+    >>> div_neg_inf_by(-1.0)
+    inf
+    """
+    return float("-inf") / x
diff --git a/tests/run/future_division.pyx b/tests/run/future_division.pyx
index e67bc091167643aa51e9a9215d7b18d170edcc84..5820dca5d308667777b98eb70980b93b1e995b31 100644
--- a/tests/run/future_division.pyx
+++ b/tests/run/future_division.pyx
@@ -36,15 +36,49 @@ def constants():
     """
     return 1/2, 1//2, 5/2.0, 5//2.0, 5/2, 5//2
 
+
 def py_mix(a):
     """
     >>> py_mix(1)
     (0.5, 0, 0.5, 0.0, 0.5, 0)
     >>> py_mix(1.0)
     (0.5, 0.0, 0.5, 0.0, 0.5, 0.0)
+    >>> 2**53 / 2.0
+    4503599627370496.0
+    >>> py_mix(2**53)
+    (4503599627370496.0, 4503599627370496, 4503599627370496.0, 4503599627370496.0, 4503599627370496.0, 4503599627370496)
+    >>> py_mix(2**53 + 1)
+    (4503599627370496.0, 4503599627370496, 4503599627370496.0, 4503599627370496.0, 4503599627370496.0, 4503599627370496)
+    >>> py_mix(2**53 + 1.0)
+    (4503599627370496.0, 4503599627370496.0, 4503599627370496.0, 4503599627370496.0, 4503599627370496.0, 4503599627370496.0)
     """
     return a/2, a//2, a/2.0, a//2.0, a/2, a//2
 
+
+def py_mix_by_neg1(a):
+    """
+    >>> py_mix_by_neg1(0)
+    (-0.0, 0, -0.0, -0.0, -0.0, 0)
+    >>> py_mix_by_neg1(-1)
+    (1.0, 1, 1.0, 1.0, 1.0, 1)
+    >>> py_mix_by_neg1(int(2**31-1))
+    (-2147483647.0, -2147483647, -2147483647.0, -2147483647.0, -2147483647.0, -2147483647)
+    >>> py_mix_by_neg1(int(-2**31-1))
+    (2147483649.0, 2147483649, 2147483649.0, 2147483649.0, 2147483649.0, 2147483649)
+    >>> results = py_mix_by_neg1(int(2**63-1))
+    >>> results[0] == results[2] == results[3] == results[4] == float(2**63-1) / -1.0 or results
+    True
+    >>> results[1] == results[5] == (2**63-1) // -1 or results
+    True
+    >>> results = py_mix_by_neg1(int(-2**63-1))
+    >>> results[0] == results[2] == results[3] == results[4] == float(-2**63-1) / -1.0 or results
+    True
+    >>> results[1] == results[5] == (-2**63-1) // -1 or results
+    True
+    """
+    return a/-1, a//-1, a/-1.0, a//-1.0, a/-1, a//-1
+
+
 def py_mix_rev(a):
     """
     >>> py_mix_rev(4)
diff --git a/tests/run/generators.pyx b/tests/run/generators.pyx
index df7c4e20f99e487b92f576b48b87b01c56601095..6736694253798dd754c875a14e84f7a8ef2a6425 100644
--- a/tests/run/generators.pyx
+++ b/tests/run/generators.pyx
@@ -1,6 +1,12 @@
 # mode: run
 # tag: generators
 
+try:
+    from collections.abc import Generator
+except ImportError:
+    from collections import Generator
+
+
 def very_simple():
     """
     >>> x = very_simple()
@@ -293,6 +299,7 @@ def test_decorated(*args):
     for i in args:
         yield i
 
+
 def test_return(a):
     """
     >>> d = dict()
@@ -309,6 +316,76 @@ def test_return(a):
     a['i_was_here'] = True
     return
 
+
+def test_return_in_finally(a):
+    """
+    >>> d = dict()
+    >>> obj = test_return_in_finally(d)
+    >>> next(obj)
+    1
+    >>> next(obj)
+    Traceback (most recent call last):
+    StopIteration
+    >>> d['i_was_here']
+    True
+
+    >>> d = dict()
+    >>> obj = test_return_in_finally(d)
+    >>> next(obj)
+    1
+    >>> obj.send(2)
+    Traceback (most recent call last):
+    StopIteration
+    >>> d['i_was_here']
+    True
+
+    >>> obj = test_return_in_finally(None)
+    >>> next(obj)
+    1
+    >>> next(obj)
+    Traceback (most recent call last):
+    StopIteration
+
+    >>> obj = test_return_in_finally(None)
+    >>> next(obj)
+    1
+    >>> obj.send(2)
+    Traceback (most recent call last):
+    StopIteration
+    """
+    yield 1
+    try:
+        a['i_was_here'] = True
+    finally:
+        return
+
+
+def test_return_none_in_finally(a):
+    """
+    >>> d = dict()
+    >>> obj = test_return_none_in_finally(d)
+    >>> next(obj)
+    1
+    >>> next(obj)
+    Traceback (most recent call last):
+    StopIteration
+    >>> d['i_was_here']
+    True
+
+    >>> obj = test_return_none_in_finally(None)
+    >>> next(obj)
+    1
+    >>> next(obj)
+    Traceback (most recent call last):
+    StopIteration
+    """
+    yield 1
+    try:
+        a['i_was_here'] = True
+    finally:
+        return None
+
+
 def test_copied_yield(foo):
     """
     >>> class Manager(object):
@@ -396,3 +473,21 @@ def test_double_with_gil_section():
                     pass
             with gil:
                 pass
+
+
+def test_generator_abc():
+    """
+    >>> isinstance(test_generator_abc(), Generator)
+    True
+
+    >>> try:
+    ...     from collections.abc import Generator
+    ... except ImportError:
+    ...     from collections import Generator
+
+    >>> isinstance(test_generator_abc(), Generator)
+    True
+    >>> isinstance((lambda:(yield))(), Generator)
+    True
+    """
+    yield 1
diff --git a/tests/run/generators_py.py b/tests/run/generators_py.py
index 286f26b0d8b67cd19d1b67e764c472cb05beb80d..152e06a39c410491ee73e05ab39b77b61c0ddd21 100644
--- a/tests/run/generators_py.py
+++ b/tests/run/generators_py.py
@@ -3,12 +3,6 @@
 
 import cython
 
-try:
-    from builtins import next # Py3k
-except ImportError:
-    def next(it):
-        return it.next()
-
 
 def very_simple():
     """
diff --git a/tests/run/ifelseexpr_T267.pyx b/tests/run/ifelseexpr_T267.pyx
index 270d7f33d0e11b18ef24c73e6d05c32b46398359..24dabc442cefb27ae39eb007f110e79391730490 100644
--- a/tests/run/ifelseexpr_T267.pyx
+++ b/tests/run/ifelseexpr_T267.pyx
@@ -25,6 +25,7 @@ def temps(x):
     """
     return ident(1) if ident(x) < ident(5) else ident(10)
 
+
 def nested(x):
     """
     >>> nested(1)
@@ -34,7 +35,9 @@ def nested(x):
     >>> nested(3)
     3
     """
-    return 1 if x == 1 else (2 if x == 2 else 3)
+    a = 1 if x == 1 else (2 if x == 2 else 3)
+    return a
+
 
 @cython.test_fail_if_path_exists('//CondExprNode')
 def const_true(a,b):
diff --git a/tests/run/index.pyx b/tests/run/index.pyx
index 539d13d062f0b1010bf45379db88733cee60ceda..a0bbbd6248aa80e8e50ef44a3a6d12ad450b7812 100644
--- a/tests/run/index.pyx
+++ b/tests/run/index.pyx
@@ -83,12 +83,12 @@ def del_index_list(list L, Py_ssize_t index):
     [0, 2, 3]
     >>> del_index_list(list(range(4)), -1)
     [0, 1, 2]
-    >>> del_index_list(list(range(4)), py_maxsize)
+    >>> del_index_list(list(range(4)), py_maxsize)  # doctest: +ELLIPSIS
     Traceback (most recent call last):
-    IndexError: list assignment index out of range
-    >>> del_index_list(list(range(4)), -py_maxsize)
+    IndexError: list... index out of range
+    >>> del_index_list(list(range(4)), -py_maxsize)  # doctest: +ELLIPSIS
     Traceback (most recent call last):
-    IndexError: list assignment index out of range
+    IndexError: list... index out of range
     """
     del L[index]
     return L
@@ -102,12 +102,12 @@ def set_index_list(list L, Py_ssize_t index):
     [0, 5, 2, 3]
     >>> set_index_list(list(range(4)), -1)
     [0, 1, 2, 5]
-    >>> set_index_list(list(range(4)), py_maxsize)
+    >>> set_index_list(list(range(4)), py_maxsize)  # doctest: +ELLIPSIS
     Traceback (most recent call last):
-    IndexError: list assignment index out of range
-    >>> set_index_list(list(range(4)), -py_maxsize)
+    IndexError: list... index out of range
+    >>> set_index_list(list(range(4)), -py_maxsize)  # doctest: +ELLIPSIS
     Traceback (most recent call last):
-    IndexError: list assignment index out of range
+    IndexError: list... index out of range
     """
     L[index] = 5
     return L
diff --git a/tests/run/int128.pyx b/tests/run/int128.pyx
new file mode 100644
index 0000000000000000000000000000000000000000..cb18ccbd8774ab3502cb8c68eb90c34818965243
--- /dev/null
+++ b/tests/run/int128.pyx
@@ -0,0 +1,119 @@
+
+cdef extern from *:
+    ctypedef long long int128_t "__int128_t"
+    ctypedef unsigned long long uint128_t "__uint128_t"
+
+
+def bigint(x):
+    print(str(x).rstrip('L'))
+
+
+def unsigned_conversion(x):
+    """
+    >>> bigint(unsigned_conversion(0))
+    0
+    >>> bigint(unsigned_conversion(2))
+    2
+
+    >>> unsigned_conversion(-2)  # doctest: +ELLIPSIS
+    Traceback (most recent call last):
+    OverflowError: can't convert negative value to ...uint128_t
+    >>> unsigned_conversion(-2**120)  # doctest: +ELLIPSIS
+    Traceback (most recent call last):
+    OverflowError: can't convert negative value to ...uint128_t
+    >>> unsigned_conversion(-2**127)  # doctest: +ELLIPSIS
+    Traceback (most recent call last):
+    OverflowError: can't convert negative value to ...uint128_t
+    >>> unsigned_conversion(-2**128)  # doctest: +ELLIPSIS
+    Traceback (most recent call last):
+    OverflowError: can't convert negative value to ...uint128_t
+
+    >>> bigint(unsigned_conversion(2**20))
+    1048576
+    >>> bigint(unsigned_conversion(2**30-1))
+    1073741823
+    >>> bigint(unsigned_conversion(2**30))
+    1073741824
+    >>> bigint(unsigned_conversion(2**30+1))
+    1073741825
+
+    >>> bigint(2**60)
+    1152921504606846976
+    >>> bigint(unsigned_conversion(2**60-1))
+    1152921504606846975
+    >>> bigint(unsigned_conversion(2**60))
+    1152921504606846976
+    >>> bigint(unsigned_conversion(2**60+1))
+    1152921504606846977
+    >>> bigint(2**64)
+    18446744073709551616
+    >>> bigint(unsigned_conversion(2**64))
+    18446744073709551616
+
+    >>> bigint(2**120)
+    1329227995784915872903807060280344576
+    >>> bigint(unsigned_conversion(2**120))
+    1329227995784915872903807060280344576
+    >>> bigint(2**128-1)
+    340282366920938463463374607431768211455
+    >>> bigint(unsigned_conversion(2**128-1))
+    340282366920938463463374607431768211455
+    >>> bigint(unsigned_conversion(2**128))  # doctest: +ELLIPSIS
+    Traceback (most recent call last):
+    OverflowError: ... too big to convert
+    """
+    cdef uint128_t n = x
+    return n
+
+
+def signed_conversion(x):
+    """
+    >>> bigint(signed_conversion(0))
+    0
+    >>> bigint(signed_conversion(2))
+    2
+    >>> bigint(signed_conversion(-2))
+    -2
+
+    >>> bigint(signed_conversion(2**20))
+    1048576
+    >>> bigint(signed_conversion(2**32))
+    4294967296
+    >>> bigint(2**64)
+    18446744073709551616
+    >>> bigint(signed_conversion(2**64))
+    18446744073709551616
+    >>> bigint(signed_conversion(-2**64))
+    -18446744073709551616
+
+    >>> bigint(2**118)
+    332306998946228968225951765070086144
+    >>> bigint(signed_conversion(2**118))
+    332306998946228968225951765070086144
+    >>> bigint(signed_conversion(-2**118))
+    -332306998946228968225951765070086144
+
+    >>> bigint(2**120)
+    1329227995784915872903807060280344576
+    >>> bigint(signed_conversion(2**120))
+    1329227995784915872903807060280344576
+    >>> bigint(signed_conversion(-2**120))
+    -1329227995784915872903807060280344576
+
+    >>> bigint(2**127-1)
+    170141183460469231731687303715884105727
+    >>> bigint(signed_conversion(2**127-2))
+    170141183460469231731687303715884105726
+    >>> bigint(signed_conversion(2**127-1))
+    170141183460469231731687303715884105727
+    >>> bigint(signed_conversion(2**127))  # doctest: +ELLIPSIS
+    Traceback (most recent call last):
+    OverflowError: ... too big to convert
+    >>> bigint(signed_conversion(-2**127))
+    -170141183460469231731687303715884105728
+    >>> bigint(signed_conversion(-2**127-1))  # doctest: +ELLIPSIS
+    Traceback (most recent call last):
+    OverflowError: ... too big to convert
+    """
+    cdef int128_t n = x
+    return n
diff --git a/tests/run/kwargs_passthrough.pyx b/tests/run/kwargs_passthrough.pyx
new file mode 100644
index 0000000000000000000000000000000000000000..704638a55a1a87bb87c84026b0611358a76a1ed1
--- /dev/null
+++ b/tests/run/kwargs_passthrough.pyx
@@ -0,0 +1,238 @@
+cimport cython
+
+
+@cython.test_fail_if_path_exists('//MergedDictNode')
+def wrap_passthrough(f):
+    """
+    >>> def f(a=1): return a
+    >>> wrapped = wrap_passthrough(f)
+    >>> wrapped(1)
+    CALLED
+    1
+    >>> wrapped(a=2)
+    CALLED
+    2
+    """
+    def wrapper(*args, **kwargs):
+        print("CALLED")
+        return f(*args, **kwargs)
+    return wrapper
+
+
+@cython.test_fail_if_path_exists('//MergedDictNode')
+def unused(*args, **kwargs):
+    """
+    >>> unused()
+    ()
+    >>> unused(1, 2)
+    (1, 2)
+    """
+    return args
+
+
+@cython.test_fail_if_path_exists('//MergedDictNode')
+def used_in_closure(**kwargs):
+    """
+    >>> used_in_closure()
+    >>> d = {}
+    >>> used_in_closure(**d)
+    >>> d  # must not be modified
+    {}
+    """
+    def func():
+        kwargs['test'] = 1
+    return func()
+
+
+@cython.test_fail_if_path_exists('//MergedDictNode')
+def modify_in_closure(**kwargs):
+    """
+    >>> func = modify_in_closure()
+    >>> func()
+
+    >>> d = {}
+    >>> func = modify_in_closure(**d)
+    >>> func()
+    >>> d  # must not be modified
+    {}
+    """
+    def func():
+        kwargs['test'] = 1
+    return func
+
+
+@cython.test_assert_path_exists('//MergedDictNode')
+def wrap_passthrough_more(f):
+    """
+    >>> def f(a=1, test=2):
+    ...     return a, test
+    >>> wrapped = wrap_passthrough_more(f)
+    >>> wrapped(1)
+    CALLED
+    (1, 1)
+    >>> wrapped(a=2)
+    CALLED
+    (2, 1)
+    """
+    def wrapper(*args, **kwargs):
+        print("CALLED")
+        return f(*args, test=1, **kwargs)
+    return wrapper
+
+
+@cython.test_fail_if_path_exists('//MergedDictNode')
+def wrap_passthrough2(f):
+    """
+    >>> def f(a=1): return a
+    >>> wrapped = wrap_passthrough2(f)
+    >>> wrapped(1)
+    CALLED
+    1
+    >>> wrapped(a=2)
+    CALLED
+    2
+    """
+    def wrapper(*args, **kwargs):
+        print("CALLED")
+        f(*args, **kwargs)
+        return f(*args, **kwargs)
+    return wrapper
+
+
+@cython.test_fail_if_path_exists('//MergedDictNode')
+def wrap_modify(f):
+    """
+    >>> def f(a=1, test=2):
+    ...     return a, test
+
+    >>> wrapped = wrap_modify(f)
+    >>> wrapped(1)
+    CALLED
+    (1, 1)
+    >>> wrapped(a=2)
+    CALLED
+    (2, 1)
+    >>> wrapped(a=2, test=3)
+    CALLED
+    (2, 1)
+    """
+    def wrapper(*args, **kwargs):
+        print("CALLED")
+        kwargs['test'] = 1
+        return f(*args, **kwargs)
+    return wrapper
+
+
+@cython.test_fail_if_path_exists('//MergedDictNode')
+def wrap_modify_mix(f):
+    """
+    >>> def f(a=1, test=2):
+    ...     return a, test
+
+    >>> wrapped = wrap_modify_mix(f)
+    >>> wrapped(1)
+    CALLED
+    (1, 1)
+    >>> wrapped(a=2)
+    CALLED
+    (2, 1)
+    >>> wrapped(a=2, test=3)
+    CALLED
+    (2, 1)
+    """
+    def wrapper(*args, **kwargs):
+        print("CALLED")
+        f(*args, **kwargs)
+        kwargs['test'] = 1
+        return f(*args, **kwargs)
+    return wrapper
+
+
+@cython.test_assert_path_exists('//MergedDictNode')
+def wrap_modify_func(f):
+    """
+    >>> def f(a=1, test=2):
+    ...     return a, test
+
+    >>> wrapped = wrap_modify_func(f)
+    >>> wrapped(1)
+    CALLED
+    (1, 1)
+    >>> wrapped(a=2)
+    CALLED
+    (2, 1)
+    >>> wrapped(a=2, test=3)
+    CALLED
+    (2, 1)
+    """
+    def modify(kw):
+        kw['test'] = 1
+        return kw
+
+    def wrapper(*args, **kwargs):
+        print("CALLED")
+        return f(*args, **modify(kwargs))
+    return wrapper
+
+
+@cython.test_assert_path_exists('//MergedDictNode')
+def wrap_modify_func_mix(f):
+    """
+    >>> def f(a=1, test=2):
+    ...     return a, test
+
+    >>> wrapped = wrap_modify_func_mix(f)
+    >>> wrapped(1)
+    CALLED
+    (1, 1)
+    >>> wrapped(a=2)
+    CALLED
+    (2, 1)
+    >>> wrapped(a=2, test=3)
+    CALLED
+    (2, 1)
+    """
+    def modify(kw):
+        kw['test'] = 1
+        return kw
+
+    def wrapper(*args, **kwargs):
+        print("CALLED")
+        f(*args, **kwargs)
+        return f(*args, **modify(kwargs))
+    return wrapper
+
+
+@cython.test_fail_if_path_exists('//MergedDictNode')
+def wrap_reassign(f):
+    """
+    >>> def f(a=1, test=2):
+    ...     return a, test
+
+    >>> wrapped = wrap_reassign(f)
+    >>> wrapped(1)
+    CALLED
+    (1, 1)
+    >>> wrapped(a=2)
+    CALLED
+    (1, 1)
+    >>> wrapped(a=2, test=3)
+    CALLED
+    (1, 1)
+    """
+    def wrapper(*args, **kwargs):
+        print("CALLED")
+        kwargs = {'test': 1}
+        return f(*args, **kwargs)
+    return wrapper
+
+
+@cython.test_fail_if_path_exists('//MergedDictNode')
+def kwargs_metaclass(**kwargs):
+    """
+    >>> K = kwargs_metaclass()
+    >>> K = kwargs_metaclass(metaclass=type)
+    """
+    class K(**kwargs):
+        pass
+    return K
diff --git a/tests/run/libcpp_all.pyx b/tests/run/libcpp_all.pyx
index 97cc5ab75fba0346de7b38abfb858a09dec90da2..de75797de3c903c350f557771eb5a5779a67094c 100644
--- a/tests/run/libcpp_all.pyx
+++ b/tests/run/libcpp_all.pyx
@@ -1,5 +1,7 @@
 # tag: cpp
 
+import cython
+
 cimport libcpp
 
 cimport libcpp.deque
@@ -10,6 +12,7 @@ cimport libcpp.queue
 cimport libcpp.set
 cimport libcpp.stack
 cimport libcpp.vector
+cimport libcpp.complex
 
 from libcpp.deque  cimport *
 from libcpp.list   cimport *
@@ -19,6 +22,7 @@ from libcpp.queue  cimport *
 from libcpp.set    cimport *
 from libcpp.stack  cimport *
 from libcpp.vector cimport *
+from libcpp.complex cimport *
 
 cdef libcpp.deque.deque[int]   d1 = deque[int]()
 cdef libcpp.list.list[int]     l1 = list[int]()
@@ -67,3 +71,23 @@ def test_vector_coercion(*args):
     for a in args:
         v.push_back(a)
     return [v[0][i] for i in range(v.size())]
+
+def test_const_vector(*args):
+    """
+    >>> test_const_vector(1.75)
+    [1.75]
+    >>> test_const_vector(1, 10, 100)
+    [1.0, 10.0, 100.0]
+    """
+    cdef vector[double] v
+    for a in args:
+        v.push_back(a)
+    return const_vector_to_list(v)
+
+cdef const_vector_to_list(const vector[double]& cv):
+    cdef vector[double].const_iterator iter = cv.const_begin()
+    cdef lst = []
+    while iter != cv.const_end():
+        lst.append(cython.operator.dereference(iter))
+        cython.operator.preincrement(iter)
+    return lst
diff --git a/tests/run/min_max_optimization.pyx b/tests/run/min_max_optimization.pyx
index e20106318d3cef95b5becfbe180febcec36114a0..9cb25d4e5f3af3dede5ce37ae0d281b73de195db 100644
--- a/tests/run/min_max_optimization.pyx
+++ b/tests/run/min_max_optimization.pyx
@@ -165,3 +165,26 @@ def test_minN():
     print min(my_int, 2, my_int, 0, my_pyint, my_int, len(my_list))
     print min(my_int, my_int, 0, my_pyint, my_int, len(my_list))
     print min(my_int, my_int, 2, my_int, 0, my_pyint, my_int, len(my_list))
+
+
+'''
+# ticket 772
+# FIXME: signed vs. unsigned fails to safely handle intermediate results
+
+@cython.test_assert_path_exists("//CondExprNode")
+@cython.test_fail_if_path_exists("//SimpleCallNode")
+def max3_typed_signed_unsigned(int a, unsigned int b, int c):
+    """
+    >>> max3_typed_signed_unsigned(1,2,-3)
+    2
+    >>> max3_typed_signed_unsigned(-2,3,1)
+    3
+    >>> max3_typed_signed_unsigned(-2,1,-3)
+    1
+    >>> max3_typed_signed_unsigned(3,-1,2)
+    3
+    >>> max3_typed_signed_unsigned(-3,2,1)
+    2
+    """
+    return max(a,b,c)
+'''
diff --git a/tests/run/modop.pyx b/tests/run/modop.pyx
index 915359b7f574a9d992747e2dc112be7c00614ec5..96f4b77f2c958b600b0f8cd7a99cbfb6ec56d650 100644
--- a/tests/run/modop.pyx
+++ b/tests/run/modop.pyx
@@ -1,9 +1,5 @@
 import sys
-if sys.version_info[0] < 3:
-    __doc__ = u"""
-    >>> modptr()
-    'spameggs'
-    """
+
 
 def modobj(obj2, obj3):
     """
@@ -15,6 +11,187 @@ def modobj(obj2, obj3):
     obj1 = obj2 % obj3
     return obj1
 
+
+def mod_obj_10(int2):
+    """
+    >>> 0 % 10
+    0
+    >>> mod_obj_10(0)
+    0
+    >>> 1 % 10
+    1
+    >>> mod_obj_10(1)
+    1
+    >>> (-1) % 10
+    9
+    >>> mod_obj_10(-1)
+    9
+    >>> 9 % 10
+    9
+    >>> mod_obj_10(9)
+    9
+    >>> 10 % 10
+    0
+    >>> mod_obj_10(10)
+    0
+    >>> (-10) % 10
+    0
+    >>> mod_obj_10(-10)
+    0
+    >>> (-12) % 10
+    8
+    >>> mod_obj_10(-12)
+    8
+    >>> 10002 % 10
+    2
+    >>> mod_obj_10(10002)
+    2
+    >>> int((2**25) % 10)
+    2
+    >>> int(mod_obj_10(2**25))
+    2
+    >>> int((-2**25) % 10)
+    8
+    >>> int(mod_obj_10(-2**25))
+    8
+    >>> int((-2**31-1) % 10)
+    1
+    >>> int(mod_obj_10(int(-2**31-1)))
+    1
+    >>> int((2**50) % 10)
+    4
+    >>> int(mod_obj_10(2**50))
+    4
+    >>> int((-2**50) % 10)
+    6
+    >>> int(mod_obj_10(-2**50))
+    6
+    >>> int((-2**63-1) % 10)
+    1
+    >>> int(mod_obj_10(-2**63-1))
+    1
+    >>> int((2**200) % 10)
+    6
+    >>> int(mod_obj_10(2**200))
+    6
+    >>> int((-2**200) % 10)
+    4
+    >>> int(mod_obj_10(-2**200))
+    4
+    """
+    int1 = int2 % 10
+    return int1
+
+
+def mod_obj_17(int2):
+    """
+    >>> 0 % 17
+    0
+    >>> mod_obj_17(0)
+    0
+    >>> 1 % 17
+    1
+    >>> mod_obj_17(1)
+    1
+    >>> (-1) % 17
+    16
+    >>> mod_obj_17(-1)
+    16
+    >>> 9 % 17
+    9
+    >>> mod_obj_17(16)
+    16
+    >>> 17 % 17
+    0
+    >>> mod_obj_17(17)
+    0
+    >>> (-17) % 17
+    0
+    >>> mod_obj_17(-17)
+    0
+    >>> (-18) % 17
+    16
+    >>> mod_obj_17(-18)
+    16
+    >>> 10002 % 17
+    6
+    >>> mod_obj_17(10002)
+    6
+    >>> int((2**25) % 17)
+    2
+    >>> int(mod_obj_17(2**25))
+    2
+    >>> int((-2**25) % 17)
+    15
+    >>> int(mod_obj_17(-2**25))
+    15
+    >>> int((-2**31-1) % 17)
+    7
+    >>> int(mod_obj_17(int(-2**31-1)))
+    7
+    >>> int((2**50) % 17)
+    4
+    >>> int(mod_obj_17(2**50))
+    4
+    >>> int((-2**50) % 17)
+    13
+    >>> int(mod_obj_17(-2**50))
+    13
+    >>> int((-2**63-1) % 17)
+    7
+    >>> int(mod_obj_17(-2**63-1))
+    7
+    >>> int((2**200) % 17)
+    1
+    >>> int(mod_obj_17(2**200))
+    1
+    >>> int((-2**200) % 17)
+    16
+    >>> int(mod_obj_17(-2**200))
+    16
+    """
+    int1 = int2 % 17
+    return int1
+
+
+def mod_obj_m2(int2):
+    """
+    >>> 0 % -2
+    0
+    >>> mod_obj_m2(0)
+    0
+    >>> 1 % -2
+    -1
+    >>> mod_obj_m2(1)
+    -1
+    >>> 9 % -2
+    -1
+    >>> mod_obj_m2(9)
+    -1
+    """
+    int1 = int2 % -2
+    return int1
+
+
+def mod_obj_m2f(obj2):
+    """
+    >>> 0 % -2.0 == 0.0    # -0.0 in Py2.7+
+    True
+    >>> mod_obj_m2f(0)
+    -0.0
+    >>> 1 % -2.0
+    -1.0
+    >>> mod_obj_m2f(1)
+    -1.0
+    >>> 9 % -2.0
+    -1.0
+    >>> mod_obj_m2f(9)
+    -1.0
+    """
+    result = obj2 % -2.0
+    return result
+
+
 def modint(int int2, int int3):
     """
     >>> modint(9,2)
@@ -24,9 +201,14 @@ def modint(int int2, int int3):
     int1 = int2 % int3
     return int1
 
+
 def modptr():
+    """
+    >>> print(modptr() if sys.version_info[0] < 3 else 'spameggs')
+    spameggs
+    """
     cdef char *str2, *str3
     str2 = "spam%s"
     str3 = "eggs"
-    obj1 = str2 % str3 # '%' operator doesn't work on byte strings in Py3
+    obj1 = str2 % str3  # '%' operator doesn't work on byte strings in Py3
     return obj1
diff --git a/tests/run/non_dict_kwargs_T470.pyx b/tests/run/non_dict_kwargs_T470.pyx
index aae6c736b577475e196fb3534c795e22e3f5cbaf..b60d5621008164dd70eb996e9fe2224e7a86bcea 100644
--- a/tests/run/non_dict_kwargs_T470.pyx
+++ b/tests/run/non_dict_kwargs_T470.pyx
@@ -1,31 +1,16 @@
+# mode: run
 # ticket: 470
 
-__doc__ = u"""
->>> func(**{'a' : 7})
-True
->>> func(**SubDict())
-True
-
->>> call_non_dict_test()
-True
->>> call_non_dict_test_kw()
-True
-
->>> call_sub_dict_test()
-True
->>> call_sub_dict_test_kw()
-True
-"""
-
-import sys
-
-if sys.version_info >= (2,6):
-    __doc__ += u"""
->>> func(**NonDict())
-True
-"""
 
 def func(**kwargs):
+    """
+    >>> func(**{'a' : 7})
+    True
+    >>> func(**SubDict())
+    True
+    >>> func(**NonDict())
+    True
+    """
     return type(kwargs) is dict and kwargs['a'] == 7
 
 
@@ -37,9 +22,17 @@ class NonDict(object):
        return ['a']
 
 def call_non_dict_test():
+    """
+    >>> call_non_dict_test()
+    True
+    """
     return func(**NonDict())
 
 def call_non_dict_test_kw():
+    """
+    >>> call_non_dict_test_kw()
+    True
+    """
     return func(b=5, **NonDict())
 
 
@@ -48,7 +41,15 @@ class SubDict(dict):
         self['a'] = 7
 
 def call_sub_dict_test():
+    """
+    >>> call_sub_dict_test()
+    True
+    """
     return func(**SubDict())
 
 def call_sub_dict_test_kw():
+    """
+    >>> call_sub_dict_test_kw()
+    True
+    """
     return func(b=5, **SubDict())
diff --git a/tests/run/non_future_division.pyx b/tests/run/non_future_division.pyx
index 2d93551b247b14335657965d6143f301289d165d..4c91413d3c235edba126909250a7d84bb8cbcdfa 100644
--- a/tests/run/non_future_division.pyx
+++ b/tests/run/non_future_division.pyx
@@ -36,15 +36,49 @@ def constants():
     """
     return 1/2, 1//2, 5/2.0, 5//2.0, 5/2, 5//2
 
+
 def py_mix(a):
     """
     >>> py_mix(1)
     (0, 0, 0.5, 0.0, 0, 0)
     >>> py_mix(1.0)
     (0.5, 0.0, 0.5, 0.0, 0.5, 0.0)
+    >>> 2**53 / 2.0
+    4503599627370496.0
+    >>> py_mix(2**53)
+    (4503599627370496, 4503599627370496, 4503599627370496.0, 4503599627370496.0, 4503599627370496, 4503599627370496)
+    >>> py_mix(2**53 + 1)
+    (4503599627370496, 4503599627370496, 4503599627370496.0, 4503599627370496.0, 4503599627370496, 4503599627370496)
+    >>> py_mix(2**53 + 1.0)
+    (4503599627370496.0, 4503599627370496.0, 4503599627370496.0, 4503599627370496.0, 4503599627370496.0, 4503599627370496.0)
     """
     return a/2, a//2, a/2.0, a//2.0, a/2, a//2
 
+
+def py_mix_by_neg1(a):
+    """
+    >>> py_mix_by_neg1(0)
+    (0, 0, -0.0, -0.0, 0, 0)
+    >>> py_mix_by_neg1(-1)
+    (1, 1, 1.0, 1.0, 1, 1)
+    >>> py_mix_by_neg1(int(2**31-1))
+    (-2147483647, -2147483647, -2147483647.0, -2147483647.0, -2147483647, -2147483647)
+    >>> py_mix_by_neg1(int(-2**31-1))
+    (2147483649, 2147483649, 2147483649.0, 2147483649.0, 2147483649, 2147483649)
+    >>> results = py_mix_by_neg1(int(2**63-1))
+    >>> results[2] == results[3] == float(2**63-1) / -1.0 or results
+    True
+    >>> results[0] == results[1] == results[4] == results[5] == (2**63-1) // -1 or results
+    True
+    >>> results = py_mix_by_neg1(int(-2**63-1))
+    >>> results[2] == results[3] == float(-2**63-1) / -1.0 or results
+    True
+    >>> results[0] == results[1] == results[4] == results[5] == (-2**63-1) // -1 or results
+    True
+    """
+    return a/-1, a//-1, a/-1.0, a//-1.0, a/-1, a//-1
+
+
 def py_mix_rev(a):
     """
     >>> py_mix_rev(4)
diff --git a/tests/run/onelinesuite.py b/tests/run/onelinesuite.py
index bc9b02153fd0f34d09c2e6b40e275a7924dffe52..1e46571610a422f19e20aa0945163f172b9b31d5 100644
--- a/tests/run/onelinesuite.py
+++ b/tests/run/onelinesuite.py
@@ -2,12 +2,12 @@
 # tag: syntax
 
 """
->>> y
+>>> y  # doctest: +ELLIPSIS
 Traceback (most recent call last):
-NameError: name 'y' is not defined
->>> z
+NameError: ...name 'y' is not defined
+>>> z  # doctest: +ELLIPSIS
 Traceback (most recent call last):
-NameError: name 'z' is not defined
+NameError: ...name 'z' is not defined
 >>> f()
 17
 """
diff --git a/tests/run/pep448_extended_unpacking.pyx b/tests/run/pep448_extended_unpacking.pyx
new file mode 100644
index 0000000000000000000000000000000000000000..2f27c62cacacadafca90451fd6bde6b988d49b09
--- /dev/null
+++ b/tests/run/pep448_extended_unpacking.pyx
@@ -0,0 +1,520 @@
+
+cimport cython
+
+
+class Iter(object):
+    def __init__(self, it=()):
+        self.it = iter(it)
+    def __iter__(self):
+        return self
+    def __next__(self):
+        return next(self.it)
+    next = __next__
+
+
+class Map(object):
+    def __init__(self, mapping={}):
+        self.mapping = mapping
+    def __iter__(self):
+        return iter(self.mapping)
+    def keys(self):
+        return self.mapping.keys()
+    def __getitem__(self, key):
+        return self.mapping[key]
+
+
+#### tuples
+
+
+@cython.test_fail_if_path_exists(
+    "//TupleNode//TupleNode",
+    "//MergedSequenceNode",
+)
+def unpack_tuple_literal():
+    """
+    >>> unpack_tuple_literal()
+    (1, 2, 4, 5)
+    """
+    return (*(1, 2, *(4, 5)),)
+
+
+def unpack_tuple_literal_mult():
+    """
+    >>> unpack_tuple_literal_mult()
+    (1, 2, 4, 5, 4, 5, 1, 2, 4, 5, 4, 5, 1, 2, 4, 5, 4, 5)
+    """
+    return (*((1, 2, *((4, 5) * 2)) * 3),)
+
+
+@cython.test_fail_if_path_exists(
+    "//TupleNode//TupleNode",
+    "//MergedSequenceNode",
+)
+def unpack_tuple_literal_empty():
+    """
+    >>> unpack_tuple_literal_empty()
+    ()
+    """
+    return (*(*(), *()), *(), *(*(*(),),))
+
+
+def unpack_tuple_simple(it):
+    """
+    >>> unpack_tuple_simple([])
+    ()
+    >>> unpack_tuple_simple(set())
+    ()
+    >>> unpack_tuple_simple(Iter())
+    ()
+
+    >>> unpack_tuple_simple([1])
+    (1,)
+
+    >>> unpack_tuple_simple([2, 1])
+    (2, 1)
+    >>> unpack_tuple_simple((2, 1))
+    (2, 1)
+    >>> sorted(unpack_tuple_simple(set([2, 1])))
+    [1, 2]
+    >>> unpack_tuple_simple(Iter([2, 1]))
+    (2, 1)
+    """
+    return (*it,)
+
+
+def unpack_tuple_from_iterable(it):
+    """
+    >>> unpack_tuple_from_iterable([1, 2, 3])
+    (1, 2, 1, 2, 3, 1, 1, 2, 3, 1, 2, 3, 1, 2, 3, 2, 1, 1, 2, 3)
+    >>> unpack_tuple_from_iterable((1, 2, 3))
+    (1, 2, 1, 2, 3, 1, 1, 2, 3, 1, 2, 3, 1, 2, 3, 2, 1, 1, 2, 3)
+    >>> sorted(unpack_tuple_from_iterable(set([1, 2, 3])))
+    [1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3]
+
+    >>> unpack_tuple_from_iterable([1, 2])
+    (1, 2, 1, 2, 1, 1, 2, 1, 2, 1, 2, 2, 1, 1, 2)
+    >>> sorted(unpack_tuple_from_iterable(set([1, 2])))
+    [1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2]
+    >>> unpack_tuple_from_iterable(Iter([1, 2]))
+    (1, 2, 1, 2, 1, 2, 1)
+
+    >>> unpack_tuple_from_iterable([3])
+    (1, 2, 3, 1, 3, 3, 3, 2, 1, 3)
+    >>> unpack_tuple_from_iterable(set([3]))
+    (1, 2, 3, 1, 3, 3, 3, 2, 1, 3)
+    >>> unpack_tuple_from_iterable(Iter([3]))
+    (1, 2, 3, 1, 2, 1)
+
+    >>> unpack_tuple_from_iterable([])
+    (1, 2, 1, 2, 1)
+    >>> unpack_tuple_from_iterable(set([]))
+    (1, 2, 1, 2, 1)
+    >>> unpack_tuple_from_iterable([])
+    (1, 2, 1, 2, 1)
+    >>> unpack_tuple_from_iterable(Iter([1, 2, 3]))
+    (1, 2, 1, 2, 3, 1, 2, 1)
+    """
+    return (1, 2, *it, 1, *(*it, *it), *it, 2, 1, *it)
+
+
+def unpack_tuple_keep_originals(a, b, c):
+    """
+    >>> a = b = [1, 2]
+    >>> c = [3, 4]
+    >>> unpack_tuple_keep_originals(a, b, c)
+    (1, 2, 1, 2, 2, 3, 4)
+    >>> a
+    [1, 2]
+    >>> b
+    [1, 2]
+    >>> c
+    [3, 4]
+
+    >>> a = b = (1, 2)
+    >>> c = (3, 4)
+    >>> unpack_tuple_keep_originals(a, b, c)
+    (1, 2, 1, 2, 2, 3, 4)
+    >>> a
+    (1, 2)
+    >>> b
+    (1, 2)
+    >>> c
+    (3, 4)
+    """
+    return (*a, *b, 2, *c)
+
+
+#### lists
+
+
+@cython.test_fail_if_path_exists(
+    "//ListNode//ListNode",
+    "//MergedSequenceNode",
+)
+def unpack_list_literal():
+    """
+    >>> unpack_list_literal()
+    [1, 2, 4, 5]
+    """
+    return [*[1, 2, *[4, 5]]]
+
+
+def unpack_list_literal_mult():
+    """
+    >>> unpack_list_literal_mult()
+    [1, 2, 4, 5, 4, 5, 1, 2, 4, 5, 4, 5, 1, 2, 4, 5, 4, 5]
+    """
+    return [*([1, 2, *([4, 5] * 2)] * 3)]
+
+
+@cython.test_fail_if_path_exists(
+    "//ListNode//ListNode",
+    "//MergedSequenceNode",
+)
+def unpack_list_literal_empty():
+    """
+    >>> unpack_list_literal_empty()
+    []
+    """
+    return [*[*[], *[]], *[], *[*[*[]]]]
+
+
+def unpack_list_simple(it):
+    """
+    >>> unpack_list_simple([])
+    []
+    >>> unpack_list_simple(set())
+    []
+    >>> unpack_list_simple(Iter())
+    []
+
+    >>> unpack_list_simple([1])
+    [1]
+
+    >>> unpack_list_simple([2, 1])
+    [2, 1]
+    >>> unpack_list_simple((2, 1))
+    [2, 1]
+    >>> sorted(unpack_list_simple(set([2, 1])))
+    [1, 2]
+    >>> unpack_list_simple(Iter([2, 1]))
+    [2, 1]
+    """
+    return [*it]
+
+
+def unpack_list_from_iterable(it):
+    """
+    >>> unpack_list_from_iterable([1, 2, 3])
+    [1, 2, 1, 2, 3, 1, 1, 2, 3, 1, 2, 3, 1, 2, 3, 2, 1, 1, 2, 3]
+    >>> unpack_list_from_iterable((1, 2, 3))
+    [1, 2, 1, 2, 3, 1, 1, 2, 3, 1, 2, 3, 1, 2, 3, 2, 1, 1, 2, 3]
+    >>> sorted(unpack_list_from_iterable(set([1, 2, 3])))
+    [1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3]
+
+    >>> unpack_list_from_iterable([1, 2])
+    [1, 2, 1, 2, 1, 1, 2, 1, 2, 1, 2, 2, 1, 1, 2]
+    >>> sorted(unpack_list_from_iterable(set([1, 2])))
+    [1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2]
+    >>> unpack_list_from_iterable(Iter([1, 2]))
+    [1, 2, 1, 2, 1, 2, 1]
+
+    >>> unpack_list_from_iterable([3])
+    [1, 2, 3, 1, 3, 3, 3, 2, 1, 3]
+    >>> unpack_list_from_iterable(set([3]))
+    [1, 2, 3, 1, 3, 3, 3, 2, 1, 3]
+    >>> unpack_list_from_iterable(Iter([3]))
+    [1, 2, 3, 1, 2, 1]
+
+    >>> unpack_list_from_iterable([])
+    [1, 2, 1, 2, 1]
+    >>> unpack_list_from_iterable(set([]))
+    [1, 2, 1, 2, 1]
+    >>> unpack_list_from_iterable([])
+    [1, 2, 1, 2, 1]
+    >>> unpack_list_from_iterable(Iter([1, 2, 3]))
+    [1, 2, 1, 2, 3, 1, 2, 1]
+    """
+    return [1, 2, *it, 1, *[*it, *it], *it, 2, 1, *it]
+
+
+def unpack_list_keep_originals(a, b, c):
+    """
+    >>> a = b = [1, 2]
+    >>> c = [3, 4]
+    >>> unpack_list_keep_originals(a, b, c)
+    [1, 2, 1, 2, 2, 3, 4]
+    >>> a
+    [1, 2]
+    >>> b
+    [1, 2]
+    >>> c
+    [3, 4]
+    """
+    return [*a, *b, 2, *c]
+
+
+###### sets
+
+
+@cython.test_fail_if_path_exists(
+    "//SetNode//SetNode",
+    "//MergedSequenceNode",
+)
+def unpack_set_literal():
+    """
+    >>> s = unpack_set_literal()
+    >>> s == set([1, 2, 4, 5]) or s
+    True
+    """
+    return {*{1, 2, *{4, 5}}}
+
+
+def unpack_set_simple(it):
+    """
+    >>> s = unpack_set_simple([])
+    >>> s == set([]) or s
+    True
+
+    >>> s = unpack_set_simple(set())
+    >>> s == set([]) or s
+    True
+
+    >>> s = unpack_set_simple(Iter())
+    >>> s == set([]) or s
+    True
+
+    >>> s = unpack_set_simple([1])
+    >>> s == set([1]) or s
+    True
+
+    >>> s = unpack_set_simple([2, 1])
+    >>> s == set([1, 2]) or s
+    True
+
+    >>> s = unpack_set_simple((2, 1))
+    >>> s == set([1, 2]) or s
+    True
+
+    >>> s = unpack_set_simple(set([2, 1]))
+    >>> s == set([1, 2]) or s
+    True
+
+    >>> s = unpack_set_simple(Iter([2, 1]))
+    >>> s == set([1, 2]) or s
+    True
+    """
+    return {*it}
+
+
+def unpack_set_from_iterable(it):
+    """
+    >>> s = unpack_set_from_iterable([1, 2, 3])
+    >>> s == set([1, 2, 3]) or s
+    True
+
+    >>> s = unpack_set_from_iterable([1, 2])
+    >>> s == set([1, 2]) or s
+    True
+
+    >>> s = unpack_set_from_iterable(set([1, 2]))
+    >>> s == set([1, 2]) or s
+    True
+
+    >>> s = unpack_set_from_iterable(Iter([1, 2]))
+    >>> s == set([1, 2]) or s
+    True
+
+    >>> s = unpack_set_from_iterable([3])
+    >>> s == set([1, 2, 3]) or s
+    True
+
+    >>> s = unpack_set_from_iterable(set([3]))
+    >>> s == set([1, 2, 3]) or s
+    True
+
+    >>> s = unpack_set_from_iterable(Iter([3]))
+    >>> s == set([1, 2, 3]) or s
+    True
+
+    >>> s = unpack_set_from_iterable([])
+    >>> s == set([1, 2]) or s
+    True
+
+    >>> s = unpack_set_from_iterable(set([]))
+    >>> s == set([1, 2]) or s
+    True
+
+    >>> s = unpack_set_from_iterable([])
+    >>> s == set([1, 2]) or s
+    True
+
+    >>> s = unpack_set_from_iterable((1, 2, 3))
+    >>> s == set([1, 2, 3]) or s
+    True
+
+    >>> s = unpack_set_from_iterable(set([1, 2, 3]))
+    >>> s == set([1, 2, 3]) or s
+    True
+
+    >>> s = unpack_set_from_iterable(Iter([1, 2, 3]))
+    >>> s == set([1, 2, 3]) or s
+    True
+    """
+    return {1, 2, *it, 1, *{*it, *it}, *it, 2, 1, *it, *it}
+
+
+def unpack_set_keep_originals(a, b, c):
+    """
+    >>> a = b = {1, 2}
+    >>> c = {3, 4}
+    >>> s = unpack_set_keep_originals(a, b, c)
+    >>> s == set([1, 2, 3, 4]) or s
+    True
+    >>> a == set([1, 2]) or a
+    True
+    >>> b == set([1, 2]) or b
+    True
+    >>> c == set([3, 4]) or c
+    True
+    """
+    return {*a, *b, 2, *c}
+
+
+#### dicts
+
+
+@cython.test_fail_if_path_exists(
+    "//DictNode//DictNode",
+    "//MergedDictNode",
+)
+def unpack_dict_literal():
+    """
+    >>> d = unpack_dict_literal()
+    >>> d == dict(a=1, b=2, c=4, d=5) or d
+    True
+    """
+    return {**{'a': 1, 'b': 2, **{'c': 4, 'd': 5}}}
+
+
+@cython.test_fail_if_path_exists(
+    "//DictNode//DictNode",
+    "//MergedDictNode",
+)
+def unpack_dict_literal_empty():
+    """
+    >>> unpack_dict_literal_empty()
+    {}
+    """
+    return {**{**{}, **{}}, **{}, **{**{**{}}}}
+
+
+def unpack_dict_simple(it):
+    """
+    >>> d = unpack_dict_simple({})
+    >>> d == {} or d
+    True
+
+    >>> d = unpack_dict_simple([])
+    >>> d == {} or d
+    True
+
+    >>> d = unpack_dict_simple(set())
+    >>> d == {} or d
+    True
+
+    >>> d = unpack_dict_simple(Iter())
+    >>> d == {} or d
+    True
+
+    >>> d = unpack_dict_simple(Map())
+    >>> d == {} or d
+    True
+
+    >>> d = unpack_dict_simple(dict(a=1))
+    >>> d == dict(a=1) or d
+    True
+
+    >>> d = unpack_dict_simple(dict(a=1, b=2))
+    >>> d == dict(a=1, b=2) or d
+    True
+
+    >>> d = unpack_dict_simple(Map(dict(a=1, b=2)))
+    >>> d == dict(a=1, b=2) or d
+    True
+    """
+    return {**it}
+
+
+def unpack_dict_from_iterable(it):
+    """
+    >>> d = unpack_dict_from_iterable(dict(a=1, b=2, c=3))
+    >>> d == dict(a=1, b=2, c=3) or d
+    True
+
+    >>> d = unpack_dict_from_iterable(dict(a=1, b=2))
+    >>> d == dict(a=1, b=2) or d
+    True
+
+    >>> d = unpack_dict_from_iterable(Map(dict(a=1, b=2)))
+    >>> d == dict(a=1, b=2) or d
+    True
+
+    >>> d = unpack_dict_from_iterable(dict(a=3))
+    >>> d == dict(a=3, b=5) or d
+    True
+
+    >>> d = unpack_dict_from_iterable(Map(dict(a=3)))
+    >>> d == dict(a=3, b=5) or d
+    True
+
+    >>> d = unpack_dict_from_iterable({})
+    >>> d == dict(a=4, b=5) or d
+    True
+
+    >>> d = unpack_dict_from_iterable(Map())
+    >>> d == dict(a=4, b=5) or d
+    True
+
+    >>> d = unpack_dict_from_iterable(Iter())
+    Traceback (most recent call last):
+    TypeError: 'Iter' object is not a mapping
+
+    >>> d = unpack_dict_from_iterable([])
+    Traceback (most recent call last):
+    TypeError: 'list' object is not a mapping
+
+    >>> d = unpack_dict_from_iterable(dict(b=2, c=3))
+    >>> d == dict(a=4, b=2, c=3) or d
+    True
+
+    >>> d = unpack_dict_from_iterable(Map(dict(b=2, c=3)))
+    >>> d == dict(a=4, b=2, c=3) or d
+    True
+
+    >>> d = unpack_dict_from_iterable(dict(a=2, c=3))
+    >>> d == dict(a=2, b=5, c=3) or d
+    True
+
+    >>> d = unpack_dict_from_iterable(Map(dict(a=2, c=3)))
+    >>> d == dict(a=2, b=5, c=3) or d
+    True
+    """
+    return {'a': 2, 'b': 3, **it, 'a': 1, **{**it, **it}, **it, 'a': 4, 'b': 5, **it, **it}
+
+
+def unpack_dict_keep_originals(a, b, c):
+    """
+    >>> a = b = {1: 2}
+    >>> c = {2: 3, 4: 5}
+    >>> d = unpack_dict_keep_originals(a, b, c)
+    >>> d == {1: 2, 2: 3, 4: 5} or d
+    True
+    >>> a
+    {1: 2}
+    >>> b
+    {1: 2}
+    >>> c == {2: 3, 4: 5} or c
+    True
+    """
+    return {**a, **b, 2: 4, **c}
diff --git a/tests/run/pep448_test_extcall.pyx b/tests/run/pep448_test_extcall.pyx
new file mode 100644
index 0000000000000000000000000000000000000000..a7bbeb1b0ff43da3288129f6e7da8d59f90772a7
--- /dev/null
+++ b/tests/run/pep448_test_extcall.pyx
@@ -0,0 +1,574 @@
+# mode: run
+# tag: pep448
+
+from __future__ import print_function
+
+import sys
+
+IS_PY3 = sys.version_info[0] >= 3
+
+if IS_PY3:
+    __doc__ = """
+>>> def f(*, w): pass
+>>> try: errors_call_no_args(f)
+... except TypeError: pass
+... else: print("FAILED!")
+
+>>> def f(*, a, b, c, d, e): pass
+>>> try: errors_call_no_args(f)
+... except TypeError: pass
+... else: print("FAILED!")
+
+>>> def f(*, kw, b): pass
+>>> try: errors_call_3args_2kwargs(f)
+... except TypeError: pass
+... else: print("FAILED!")
+
+>>> def f(a, b=2, *, kw): pass
+>>> try: errors_call_3args_1kwarg(f)
+... except TypeError: pass
+... else: print("FAILED!")
+
+>>> def f(*, kw): pass
+>>> try: errors_call_1arg_1kwarg(f)
+... except TypeError: pass
+... else: print("FAILED!")
+"""
+
+# test for method/function calls. adapted from CPython's "test_extcall.py".
+
+def sortdict(d):
+    return '{%s}' % ', '.join(['%r: %r' % item for item in sorted(d.items())])
+
+# We're going the use these types for extra testing
+
+try:
+    from collections import UserList, UserDict
+except ImportError:
+    from UserList import UserList
+    from UserDict import UserDict
+
+
+# We're defining four helper functions
+
+def e(a,b):
+    print(a, b)
+
+def f(*a, **k):
+    print(a, sortdict(k))
+
+def g(x, *y, **z):
+    print(x, y, sortdict(z))
+
+def h(j=1, a=2, h=3):
+    print(j, a, h)
+
+
+# Argument list examples
+
+def call_f_positional():
+    """
+    >>> call_f_positional()
+    () {}
+    (1,) {}
+    (1, 2) {}
+    (1, 2, 3) {}
+    (1, 2, 3, 4, 5) {}
+    (1, 2, 3, 4, 5) {}
+    (1, 2, 3, 4, 5) {}
+    (1, 2, 3, 4, 5) {}
+    (1, 2, 3, 4, 5, 6, 7) {}
+    (1, 2, 3, 4, 5, 6, 7) {}
+    (1, 2, 3, 4, 5, 6, 7) {}
+    """
+    f()
+    f(1)
+    f(1, 2)
+    f(1, 2, 3)
+    f(1, 2, 3, *(4, 5))
+    f(1, 2, 3, *[4, 5])
+    f(*[1, 2, 3], 4, 5)
+    f(1, 2, 3, *UserList([4, 5]))
+    f(1, 2, 3, *[4, 5], *[6, 7])
+    f(1, *[2, 3], 4, *[5, 6], 7)
+    f(*UserList([1, 2]), *UserList([3, 4]), 5, *UserList([6, 7]))
+
+
+# Here we add keyword arguments
+
+def call_f_kwargs():
+    """
+    >>> call_f_kwargs()
+    (1, 2, 3) {'a': 4, 'b': 5}
+    (1, 2, 3, 4, 5) {'a': 6, 'b': 7}
+    (1, 2, 3, 6, 7) {'a': 8, 'b': 9, 'x': 4, 'y': 5}
+    (1, 2, 3, 4, 5) {'a': 6, 'b': 7, 'c': 8}
+    (1, 2, 3, 4, 5) {'a': 8, 'b': 9, 'x': 6, 'y': 7}
+    (1, 2, 3) {'a': 4, 'b': 5}
+    (1, 2, 3, 4, 5) {'a': 6, 'b': 7}
+    (1, 2, 3, 6, 7) {'a': 8, 'b': 9, 'x': 4, 'y': 5}
+    (1, 2, 3, 4, 5) {'a': 8, 'b': 9, 'x': 6, 'y': 7}
+    """
+
+    f(1, 2, 3, **{'a':4, 'b':5})
+    f(1, 2, 3, *[4, 5], **{'a':6, 'b':7})
+    f(1, 2, 3, x=4, y=5, *(6, 7), **{'a':8, 'b': 9})
+    f(1, 2, 3, *[4, 5], **{'c': 8}, **{'a':6, 'b':7})
+    f(1, 2, 3, *(4, 5), x=6, y=7, **{'a':8, 'b': 9})
+
+    f(1, 2, 3, **UserDict(a=4, b=5))
+    f(1, 2, 3, *(4, 5), **UserDict(a=6, b=7))
+    f(1, 2, 3, x=4, y=5, *(6, 7), **UserDict(a=8, b=9))
+    f(1, 2, 3, *(4, 5), x=6, y=7, **UserDict(a=8, b=9))
+
+
+# Examples with invalid arguments (TypeErrors). We're also testing the function
+# names in the exception messages.
+#
+# Verify clearing of SF bug #733667
+
+def errors_f1():
+    """
+    >>> errors_f1()  # doctest: +ELLIPSIS
+    Traceback (most recent call last):
+        ...
+    TypeError: ...got multiple values for keyword argument 'a'
+    """
+    f(1, 2, **{'a': -1, 'b': 5}, **{'a': 4, 'c': 6})
+
+
+def errors_f2():
+    """
+    >>> errors_f2()  # doctest: +ELLIPSIS
+    Traceback (most recent call last):
+        ...
+    TypeError: ...multiple values for keyword argument 'a'
+    """
+    f(1, 2, **{'a': -1, 'b': 5}, a=4, c=6)
+
+
+def errors_e1():
+    """
+    >>> try: errors_e1()
+    ... except TypeError: pass
+    ... else: print("FAILED!")
+    """
+    e(c=4)
+
+
+def errors_e2():
+    """
+    >>> try: errors_e2()
+    ... except TypeError: pass
+    ... else: print("FAILED!")
+    """
+    e(a=1, b=2, c=4)
+
+
+def errors_g1():
+    """
+    >>> errors_g1()
+    Traceback (most recent call last):
+      ...
+    TypeError: g() takes at least 1 positional argument (0 given)
+
+    # TypeError: g() missing 1 required positional argument: 'x'
+    """
+    g()
+
+
+def errors_g2():
+    """
+    >>> errors_g2()
+    Traceback (most recent call last):
+      ...
+    TypeError: g() takes at least 1 positional argument (0 given)
+
+    # TypeError: g() missing 1 required positional argument: 'x'
+    """
+    g(*())
+
+
+def errors_g3():
+    """
+    >>> errors_g3()
+    Traceback (most recent call last):
+      ...
+    TypeError: g() takes at least 1 positional argument (0 given)
+
+    # TypeError: g() missing 1 required positional argument: 'x'
+    """
+    g(*(), **{})
+
+
+def call_g_positional():
+    """
+    >>> call_g_positional()
+    1 () {}
+    1 (2,) {}
+    1 (2, 3) {}
+    1 (2, 3, 4, 5) {}
+    """
+    g(1)
+    g(1, 2)
+    g(1, 2, 3)
+    g(1, 2, 3, *(4, 5))
+
+
+
+def call_nonseq_positional1():
+    """
+    >>> call_nonseq_positional1()
+    Traceback (most recent call last):
+      ...
+    TypeError: 'Nothing' object is not iterable
+
+    # TypeError: g() argument after * must be a sequence, not Nothing
+    """
+    class Nothing(object): pass
+    g(*Nothing())
+
+
+def call_nonseq_positional2():
+    """
+    >>> call_nonseq_positional2()
+    Traceback (most recent call last):
+      ...
+    TypeError: 'Nothing' object is not iterable
+
+    # TypeError: g() argument after * must be a sequence, not Nothing
+    """
+    class Nothing(object):
+        def __len__(self): return 5
+    g(*Nothing())
+
+
+def call_seqlike_positional1():
+    """
+    >>> call_seqlike_positional1()
+    0 (1, 2) {}
+    """
+    class Nothing(object):
+        def __len__(self): return 5
+        def __getitem__(self, i):
+            if i<3: return i
+            else: raise IndexError(i)
+
+    g(*Nothing())
+
+
+def call_seqlike_positional2():
+    """
+    >>> call_seqlike_positional2()
+    0 (1, 2, 3) {}
+    """
+    class Nothing:
+        def __init__(self): self.c = 0
+        def __iter__(self): return self
+        def __next__(self):
+            if self.c == 4:
+                raise StopIteration
+            c = self.c
+            self.c += 1
+            return c
+        next = __next__
+
+    g(*Nothing())
+
+
+# Make sure that the function doesn't stomp the dictionary
+
+def call_kwargs_unmodified1():
+    """
+    >>> call_kwargs_unmodified1()
+    1 () {'a': 1, 'b': 2, 'c': 3, 'd': 4}
+    True
+    """
+    d = {'a': 1, 'b': 2, 'c': 3}
+    d2 = d.copy()
+    g(1, d=4, **d)
+    return d == d2
+
+
+# What about willful misconduct?
+
+def call_kwargs_unmodified2():
+    """
+    >>> call_kwargs_unmodified2()
+    {}
+    """
+    def saboteur(**kw):
+        kw['x'] = 'm'
+        return kw
+
+    d = {}
+    kw = saboteur(a=1, **d)
+    return d
+
+
+def errors_args_kwargs_overlap():
+    """
+    >>> errors_args_kwargs_overlap()  # doctest: +ELLIPSIS
+    Traceback (most recent call last):
+      ...
+    TypeError: ...got multiple values for... argument 'x'
+    """
+    g(1, 2, 3, **{'x': 4, 'y': 5})
+
+
+def errors_non_string_kwarg():
+    """
+    >>> errors_non_string_kwarg()  # doctest: +ELLIPSIS
+    Traceback (most recent call last):
+    TypeError: ...keywords must be strings
+    """
+    f(**{1:2})
+
+
+def errors_unexpected_kwarg():
+    """
+    >>> errors_unexpected_kwarg()
+    Traceback (most recent call last):
+      ...
+    TypeError: h() got an unexpected keyword argument 'e'
+    """
+    h(**{'e': 2})
+
+
+def errors_call_nonseq():
+    """
+    >>> try: errors_call_nonseq()
+    ... except TypeError: pass
+    ... else: print("FAILED!")
+    """
+    h(*h)
+
+
+def errors_call_builtin_nonseq():
+    """
+    >>> try: errors_call_builtin_nonseq()
+    ... except TypeError: pass
+    ... else: print("FAILED!")
+    """
+    dir(*h)
+
+
+def errors_call_none_nonseq():
+    """
+    >>> try: errors_call_none_nonseq()
+    ... except TypeError: pass
+    ... else: print("FAILED!")
+    """
+    None(*h)
+
+
+def errors_call_nonmapping_kwargs():
+    """
+    >>> try: errors_call_nonmapping_kwargs()
+    ... except TypeError: pass
+    ... else: print("FAILED!")
+    """
+    h(**h)
+
+
+def errors_call_builtin_nonmapping_kwargs():
+    """
+    >>> try: errors_call_builtin_nonmapping_kwargs()
+    ... except TypeError: pass
+    ... else: print("FAILED!")
+    """
+    dir(**h)
+
+
+def errors_call_none_nonmapping_kwargs():
+    """
+    >>> try: errors_call_none_nonmapping_kwargs()
+    ... except TypeError: pass
+    ... else: print("FAILED!")
+    """
+    None(**h)
+
+
+'''  # compile time error in Cython
+def errors_call_builtin_duplicate_kwarg():
+    """
+    >>> errors_call_builtin_duplicate_kwarg()  # doctest: +ELLIPSIS
+    Traceback (most recent call last):
+      ...
+    TypeError: ...got multiple values for keyword argument 'b'
+    """
+    dir(b=1, **{'b': 1})
+'''
+
+
+# Another helper function
+
+def f2(*a, **b):
+    return a, b
+
+
+def call_many_kwargs():
+    """
+    call_many_kwargs()
+    (3, 512, True)
+    """
+    d = {}
+    for i in range(512):
+        key = 'k%d' % i
+        d[key] = i
+    a, b = f2(1, *(2,3), **d)
+    return len(a), len(b), b == d
+
+
+def call_method(Foo):
+    """
+    >>> class Foo(object):
+    ...     def method(self, arg1, arg2):
+    ...         print(arg1+arg2)
+
+    >>> call_method(Foo)
+    3
+    3
+    5
+    5
+    """
+    x = Foo()
+    Foo.method(*(x, 1, 2))
+    Foo.method(x, *(1, 2))
+    if sys.version_info[0] >= 3:
+        Foo.method(*(1, 2, 3))
+        Foo.method(1, *[2, 3])
+    else:
+        print(5)
+        print(5)
+
+
+# A PyCFunction that takes only positional parameters should allow an
+# empty keyword dictionary to pass without a complaint, but raise a
+# TypeError if te dictionary is not empty
+
+def call_builtin_empty_dict():
+    """
+    >>> call_builtin_empty_dict()
+    """
+    silence = id(1, *{})
+    silence = id(1, **{})
+
+
+def call_builtin_nonempty_dict():
+    """
+    >>> call_builtin_nonempty_dict()
+    Traceback (most recent call last):
+      ...
+    TypeError: id() takes no keyword arguments
+    """
+    return id(1, **{'foo': 1})
+
+
+''' Cython: currently just passes empty kwargs into f() while CPython keeps the content
+
+# A corner case of keyword dictionary items being deleted during
+# the function call setup. See <http://bugs.python.org/issue2016>.
+
+def call_kwargs_modified_while_building():
+    """
+    >>> call_kwargs_modified_while_building()
+    1 2
+    """
+    class Name(str):
+        def __eq__(self, other):
+            try:
+                 del x[self]
+            except KeyError:
+                 pass
+            return str.__eq__(self, other)
+        def __hash__(self):
+            return str.__hash__(self)
+
+    x = {Name("a"):1, Name("b"):2}
+    def f(a, b):
+        print(a,b)
+    f(**x)
+'''
+
+
+# Too many arguments:
+
+def errors_call_one_arg(f):
+    """
+    >>> def f(): pass
+    >>> try: errors_call_one_arg(f)
+    ... except TypeError: pass
+    ... else: print("FAILED!")
+    """
+    f(1)
+
+def errors_call_2args(f):
+    """
+    >>> def f(a): pass
+    >>> try: errors_call_2args(f)
+    ... except TypeError: pass
+    ... else: print("FAILED!")
+    """
+    f(1, 2)
+
+def errors_call_3args(f):
+    """
+    >>> def f(a, b=1): pass
+    >>> try: errors_call_3args(f)
+    ... except TypeError: pass
+    ... else: print("FAILED!")
+    """
+    f(1, 2, 3)
+
+
+def errors_call_1arg_1kwarg(f):
+    # Py3 only
+    f(1, kw=3)
+
+
+def errors_call_3args_2kwargs(f):
+    # Py3 only
+    f(1, 2, 3, b=3, kw=3)
+
+
+def errors_call_3args_1kwarg(f):
+    # Py3 only
+    f(2, 3, 4, kw=4)
+
+
+# Too few and missing arguments:
+
+def errors_call_no_args(f):
+    """
+    >>> def f(a): pass
+    >>> try: errors_call_no_args(f)
+    ... except TypeError: pass
+    ... else: print("FAILED!")
+
+    >>> def f(a, b): pass
+    >>> try: errors_call_no_args(f)
+    ... except TypeError: pass
+    ... else: print("FAILED!")
+
+    >>> def f(a, b, c): pass
+    >>> try: errors_call_no_args(f)
+    ... except TypeError: pass
+    ... else: print("FAILED!")
+
+    >>> def f(a, b, c, d, e): pass
+    >>> try: errors_call_no_args(f)
+    ... except TypeError: pass
+    ... else: print("FAILED!")
+    """
+    f()
+
+
+def errors_call_one_missing_kwarg(f):
+    """
+    >>> def f(a, b=4, c=5, d=5): pass
+    >>> try: errors_call_one_missing_kwarg(f)
+    ... except TypeError: pass
+    ... else: print("FAILED!")
+    """
+    f(c=12, b=9)
diff --git a/tests/run/powop.pyx b/tests/run/powop.pyx
index 88da79a8b2f46ccf938fc208c3baab679b6486ef..966336c2a29a2e82bf253181c798e5345f69b5f3 100644
--- a/tests/run/powop.pyx
+++ b/tests/run/powop.pyx
@@ -105,8 +105,16 @@ def optimised_pow2(n):
     1024
     >>> optimised_pow2(30)
     1073741824
+    >>> print(repr(optimised_pow2(31)).rstrip('L'))
+    2147483648
     >>> print(repr(optimised_pow2(32)).rstrip('L'))
     4294967296
+    >>> print(repr(optimised_pow2(60)).rstrip('L'))
+    1152921504606846976
+    >>> print(repr(optimised_pow2(63)).rstrip('L'))
+    9223372036854775808
+    >>> print(repr(optimised_pow2(64)).rstrip('L'))
+    18446744073709551616
     >>> print(repr(optimised_pow2(100)).rstrip('L'))
     1267650600228229401496703205376
     >>> optimised_pow2(30000) == 2 ** 30000
diff --git a/tests/run/pure_py.py b/tests/run/pure_py.py
index 5f436f4089a5d82fa6aea390637755312d2f99d4..2fa801744f302d209560c6fc09e3f43eeee1878f 100644
--- a/tests/run/pure_py.py
+++ b/tests/run/pure_py.py
@@ -5,6 +5,7 @@ is_compiled = cython.compiled
 NULL = 5
 _NULL = NULL
 
+
 def test_sizeof():
     """
     >>> test_sizeof()
@@ -24,6 +25,7 @@ def test_sizeof():
     else:
         print(cython.sizeof(cython.char) == 1)
 
+
 def test_declare(n):
     """
     >>> test_declare(100)
@@ -43,6 +45,7 @@ def test_declare(n):
     ptr = cython.declare(cython.p_int, cython.address(y))
     return y, ptr[0]
 
+
 @cython.locals(x=cython.double, n=cython.int)
 def test_cast(x):
     """
@@ -52,6 +55,7 @@ def test_cast(x):
     n = cython.cast(cython.int, x)
     return n
 
+
 @cython.locals(x=cython.int, y=cython.p_int)
 def test_address(x):
     """
@@ -61,6 +65,30 @@ def test_address(x):
     y = cython.address(x)
     return y[0]
 
+
+@cython.wraparound(False)
+def test_wraparound(x):
+    """
+    >>> test_wraparound([1, 2, 3])
+    [1, 2, 1]
+    """
+    with cython.wraparound(True):
+        x[-1] = x[0]
+    return x
+
+
+@cython.boundscheck(False)
+def test_boundscheck(x):
+    """
+    >>> test_boundscheck([1, 2, 3])
+    3
+    >>> try: test_boundscheck([1, 2])
+    ... except IndexError: pass
+    """
+    with cython.boundscheck(True):
+        return x[2]
+
+
 ## CURRENTLY BROKEN - FIXME!!
 ## Is this test make sense? Implicit conversion in pure Python??
 
@@ -74,6 +102,7 @@ def test_address(x):
 ##     y = x
 ##     return y
 
+
 def test_with_nogil(nogil):
     """
     >>> raised = []
diff --git a/tests/run/py_ucs4_type.pyx b/tests/run/py_ucs4_type.pyx
index ce495f455892af3fdb9e6379dca50d09287c4a5c..433e1315d1d16827efa66d270c077ec85147a6db 100644
--- a/tests/run/py_ucs4_type.pyx
+++ b/tests/run/py_ucs4_type.pyx
@@ -5,6 +5,10 @@ cimport cython
 cdef Py_UCS4 char_ASCII = u'A'
 cdef Py_UCS4 char_KLINGON = u'\uF8D2'
 
+u_A = char_ASCII
+u_KLINGON = char_KLINGON
+
+
 def compare_ASCII():
     """
     >>> compare_ASCII()
@@ -86,6 +90,19 @@ def unicode_ordinal(Py_UCS4 i):
     """
     return i
 
+
+def ord_py_ucs4(Py_UCS4 x):
+    """
+    >>> ord_py_ucs4(u0)
+    0
+    >>> ord_py_ucs4(u_A)
+    65
+    >>> ord_py_ucs4(u_KLINGON)
+    63698
+    """
+    return ord(x)
+
+
 @cython.test_assert_path_exists('//PythonCapiCallNode')
 @cython.test_fail_if_path_exists('//SimpleCallNode')
 def unicode_type_methods(Py_UCS4 uchar):
diff --git a/tests/run/py_unicode_type.pyx b/tests/run/py_unicode_type.pyx
index 4bbf6bc09ff014830df2e7a6713c921fce573464..78a5e4a51adbad8ecdd8af2240254632f5f5024c 100644
--- a/tests/run/py_unicode_type.pyx
+++ b/tests/run/py_unicode_type.pyx
@@ -5,6 +5,10 @@ cimport cython
 cdef Py_UNICODE char_ASCII = u'A'
 cdef Py_UNICODE char_KLINGON = u'\uF8D2'
 
+u_A = char_ASCII
+u_KLINGON = char_KLINGON
+
+
 def compare_ASCII():
     """
     >>> compare_ASCII()
@@ -78,6 +82,19 @@ def unicode_ordinal(Py_UNICODE i):
     """
     return i
 
+
+def ord_pyunicode(Py_UNICODE x):
+    """
+    >>> ord_pyunicode(u0)
+    0
+    >>> ord_pyunicode(u_A)
+    65
+    >>> ord_pyunicode(u_KLINGON)
+    63698
+    """
+    return ord(x)
+
+
 @cython.test_assert_path_exists('//PythonCapiCallNode')
 @cython.test_fail_if_path_exists('//SimpleCallNode')
 def unicode_type_methods(Py_UNICODE uchar):
diff --git a/tests/run/pyintop.pyx b/tests/run/pyintop.pyx
index f222d1c8a65318640773e21f4db52015c34abeb0..5c44683b83e1a09f8917e75c6a40ba4299bfb505 100644
--- a/tests/run/pyintop.pyx
+++ b/tests/run/pyintop.pyx
@@ -1,47 +1,152 @@
-def f(obj1, obj2, obj3):
+# mode: run
+
+
+def bigint(x):
+    # avoid 'L' postfix in Py2.x
+    print(str(x).rstrip('L'))
+
+
+def or_obj(obj2, obj3):
     """
-    >>> f(1,2,3)
+    >>> or_obj(2, 3)
     3
     """
     obj1 = obj2 | obj3
     return obj1
 
-def g(obj1, obj2, obj3):
+
+def or_int(obj2):
+    """
+    >>> or_int(1)
+    17
+    >>> or_int(16)
+    16
+    """
+    obj1 = obj2 | 0x10
+    return obj1
+
+
+def xor_obj(obj2, obj3):
     """
-    >>> g(1,2,3)
+    >>> xor_obj(2, 3)
     1
     """
     obj1 = obj2 ^ obj3
     return obj1
 
-def h(obj1, obj2, obj3):
+
+def xor_int(obj2):
+    """
+    >>> xor_int(2)
+    18
+    >>> xor_int(16)
+    0
+    """
+    obj1 = obj2 ^ 0x10
+    return obj1
+
+
+def and_obj(obj2, obj3):
     """
-    >>> h(1,2,3)
+    >>> and_obj(2, 3)
     2
     """
     obj1 = obj2 & obj3
     return obj1
 
-def j(obj1, obj2, obj3):
+
+def and_int(obj2):
     """
-    >>> j(1,2,3)
+    >>> and_int(1)
+    0
+    >>> and_int(18)
+    16
+    """
+    obj1 = obj2 & 0x10
+    return obj1
+
+
+def lshift_obj(obj2, obj3):
+    """
+    >>> lshift_obj(2, 3)
     16
     """
     obj1 = obj2 << obj3
     return obj1
 
-def k(obj1, obj2, obj3):
+
+def rshift_obj(obj2, obj3):
     """
-    >>> k(1,2,3)
+    >>> rshift_obj(2, 3)
     0
     """
     obj1 = obj2 >> obj3
     return obj1
 
-def l(obj1, obj2, obj3):
+
+def rshift_int(obj2):
+    """
+    >>> rshift_int(2)
+    0
+
+    >>> rshift_int(27)
+    3
+    >>> (-27) >> 3
+    -4
+    >>> rshift_int(-27)
+    -4
+
+    >>> rshift_int(32)
+    4
+    >>> (-32) >> 3
+    -4
+    >>> rshift_int(-32)
+    -4
+
+    >>> (2**28) >> 3
+    33554432
+    >>> rshift_int(2**28)
+    33554432
+    >>> (-2**28) >> 3
+    -33554432
+    >>> rshift_int(-2**28)
+    -33554432
+
+    >>> (2**30) >> 3
+    134217728
+    >>> rshift_int(2**30)
+    134217728
+    >>> rshift_int(-2**30)
+    -134217728
+
+    >>> bigint((2**60) >> 3)
+    144115188075855872
+    >>> bigint(rshift_int(2**60))
+    144115188075855872
+    >>> bigint(rshift_int(-2**60))
+    -144115188075855872
     """
-    >>> l(1,2,3)
+    obj1 = obj2 >> 3
+    return obj1
+
+
+def mixed_obj(obj2, obj3):
+    """
+    >>> mixed_obj(2, 3)
     16
     """
     obj1 = obj2 << obj3 | obj2 >> obj3
     return obj1
+
+
+def mixed_int(obj2):
+    """
+    >>> mixed_int(2)
+    18
+    >>> mixed_int(16)
+    0
+    >>> mixed_int(17)
+    1
+    """
+    obj1 = (obj2 ^ 0x10) | (obj2 & 0x01)
+    return obj1
diff --git a/tests/run/relative_cimport.srctree b/tests/run/relative_cimport.srctree
index 09bbc897b88a69b0dc718b9a0c01280ed7a51c58..c547a86bee90073f20e1ac0bcd4b36ef44486931 100644
--- a/tests/run/relative_cimport.srctree
+++ b/tests/run/relative_cimport.srctree
@@ -37,8 +37,10 @@ cdef class test_pxd:
 
 from . cimport a
 from .a cimport test_pxd
+cimport a as implicitly_relative_a
 
 assert a.test_pxd is test_pxd
+assert implicitly_relative_a.test_pxd is test_pxd
 
 def test():
     cdef test_pxd obj = test_pxd()
diff --git a/tests/run/set.pyx b/tests/run/set.pyx
index abd313790f5ca3f5bcfb73c66eba5c73cf71830e..5aa87a09aafc9b6398a2917b59e08e7efe470bde 100644
--- a/tests/run/set.pyx
+++ b/tests/run/set.pyx
@@ -1,16 +1,10 @@
 
-# Py2.3 doesn't have the 'set' builtin type, but Cython does :)
-_set = set
-_frozenset = frozenset
-
 cimport cython
 
-import sys
-
 
 def cython_set():
     """
-    >>> cython_set() is _set
+    >>> cython_set() is set
     True
     """
     assert set is cython.set
@@ -19,7 +13,7 @@ def cython_set():
 
 def cython_frozenset():
     """
-    >>> cython_frozenset() is _frozenset
+    >>> cython_frozenset() is frozenset
     True
     """
     assert frozenset is cython.frozenset
@@ -28,7 +22,7 @@ def cython_frozenset():
 
 def cython_set_override():
     """
-    >>> cython_set_override() is _set
+    >>> cython_set_override() is set
     True
     """
     set = 1
@@ -37,7 +31,7 @@ def cython_set_override():
 
 def cython_frozenset_override():
     """
-    >>> cython_frozenset_override() is _frozenset
+    >>> cython_frozenset_override() is frozenset
     True
     """
     frozenset = 1
@@ -46,7 +40,7 @@ def cython_frozenset_override():
 
 def test_set_literal():
     """
-    >>> type(test_set_literal()) is _set
+    >>> type(test_set_literal()) is set
     True
     >>> sorted(test_set_literal())
     ['a', 'b', 1]
@@ -57,7 +51,7 @@ def test_set_literal():
 
 def test_set_add():
     """
-    >>> type(test_set_add()) is _set
+    >>> type(test_set_add()) is set
     True
     >>> sorted(test_set_add())
     ['a', 1, (1, 2)]
@@ -71,9 +65,55 @@ def test_set_add():
     return s1
 
 
+def test_set_update(v=None):
+    """
+    >>> type(test_set_update()) is set
+    True
+    >>> sorted(test_set_update())
+    ['a', 'b', 'c', 1, 2, (1, 2)]
+    >>> sorted(test_set_update([]))
+    ['a', 'b', 'c', 1, 2, (1, 2)]
+    >>> try: test_set_update(object())
+    ... except TypeError: pass
+    ... else: print("NOT RAISED!")
+    """
+    cdef set s1
+    s1 = set([1, (1, 2)])
+    s1.update((1,))
+    s1.update('abc')
+    s1.update(set([1]))
+    s1.update(frozenset((1,2)))
+    if v is not None:
+        s1.update(v)
+    return s1
+
+
+def test_object_update(v=None):
+    """
+    >>> type(test_object_update()) is set
+    True
+    >>> sorted(test_object_update())
+    ['a', 'b', 'c', 1, 2, (1, 2)]
+    >>> sorted(test_object_update([]))
+    ['a', 'b', 'c', 1, 2, (1, 2)]
+    >>> try: test_object_update(object())
+    ... except TypeError: pass
+    ... else: print("NOT RAISED!")
+    """
+    cdef object s1
+    s1 = set([1, (1, 2)])
+    s1.update((1,))
+    s1.update('abc')
+    s1.update(set([1]))
+    s1.update(frozenset((1,2)))
+    if v is not None:
+        s1.update(v)
+    return s1
+
+
 def test_set_clear():
     """
-    >>> type(test_set_clear()) is _set
+    >>> type(test_set_clear()) is set
     True
     >>> list(test_set_clear())
     []
@@ -96,7 +136,7 @@ def test_set_clear_None():
 
 def test_set_list_comp():
     """
-    >>> type(test_set_list_comp()) is _set
+    >>> type(test_set_list_comp()) is set
     True
     >>> sorted(test_set_list_comp())
     [0, 1, 2]
@@ -108,7 +148,7 @@ def test_set_list_comp():
 
 def test_frozenset_list_comp():
     """
-    >>> type(test_frozenset_list_comp()) is _frozenset
+    >>> type(test_frozenset_list_comp()) is frozenset
     True
     >>> sorted(test_frozenset_list_comp())
     [0, 1, 2]
@@ -120,7 +160,7 @@ def test_frozenset_list_comp():
 
 def test_set_pop():
     """
-    >>> type(test_set_pop()) is _set
+    >>> type(test_set_pop()) is set
     True
     >>> list(test_set_pop())
     []
@@ -135,7 +175,7 @@ def test_set_pop():
 @cython.test_fail_if_path_exists("//SimpleCallNode//NameNode")
 def test_object_pop(s):
     """
-    >>> s = _set([2])
+    >>> s = set([2])
     >>> test_object_pop(s)
     2
     >>> list(s)
@@ -162,7 +202,7 @@ def test_noop_pop_exception():
 
 def test_set_discard():
     """
-    >>> type(test_set_discard()) is _set
+    >>> type(test_set_discard()) is set
     True
     >>> sorted(test_set_discard())
     ['12', 233]
@@ -242,7 +282,7 @@ def test_frozenset_sideeffect_unhashable_failure():
 def test_set_of_list():
     """
     >>> s = test_set_of_list()
-    >>> isinstance(s, _set)
+    >>> isinstance(s, set)
     True
     >>> sorted(s)
     [1, 2, 3]
@@ -255,7 +295,7 @@ def test_set_of_list():
 def test_frozenset_of_list():
     """
     >>> s = test_frozenset_of_list()
-    >>> isinstance(s, _frozenset)
+    >>> isinstance(s, frozenset)
     True
     >>> sorted(s)
     [1, 2, 3]
@@ -268,7 +308,7 @@ def test_frozenset_of_list():
 def test_set_of_tuple():
     """
     >>> s = test_set_of_tuple()
-    >>> isinstance(s, _set)
+    >>> isinstance(s, set)
     True
     >>> sorted(s)
     [1, 2, 3]
@@ -281,7 +321,7 @@ def test_set_of_tuple():
 def test_frozenset_of_tuple():
     """
     >>> s = test_frozenset_of_tuple()
-    >>> isinstance(s, _frozenset)
+    >>> isinstance(s, frozenset)
     True
     >>> sorted(s)
     [1, 2, 3]
@@ -297,7 +337,7 @@ def test_frozenset_of_tuple():
 def test_set_of_iterable(x):
     """
     >>> s = test_set_of_iterable([1, 2, 3])
-    >>> isinstance(s, _set)
+    >>> isinstance(s, set)
     True
     >>> sorted(s)
     [1, 2, 3]
@@ -313,13 +353,13 @@ def test_set_of_iterable(x):
 def test_frozenset_of_iterable(x):
     """
     >>> s = test_frozenset_of_iterable([1, 2, 3])
-    >>> isinstance(s, _frozenset)
+    >>> isinstance(s, frozenset)
     True
     >>> sorted(s)
     [1, 2, 3]
 
-    >>> s = test_frozenset_of_iterable(_frozenset([1, 2, 3]))
-    >>> isinstance(s, _frozenset)
+    >>> s = test_frozenset_of_iterable(frozenset([1, 2, 3]))
+    >>> isinstance(s, frozenset)
     True
     >>> sorted(s)
     [1, 2, 3]
@@ -335,11 +375,11 @@ def test_frozenset_of_iterable(x):
 def test_empty_frozenset():
     """
     >>> s = test_empty_frozenset()
-    >>> isinstance(s, _frozenset)
+    >>> isinstance(s, frozenset)
     True
     >>> len(s)
     0
-    >>> sys.version_info < (2,5) or s is frozenset()   # singleton!
+    >>> s is frozenset()   # singleton!
     True
     """
     return frozenset()
@@ -360,7 +400,7 @@ def test_singleton_empty_frozenset():
            frozenset(), frozenset([]), frozenset(()), frozenset(''),
            frozenset(range(0)), frozenset(frozenset()),
            frozenset(f), f]
-    return len(set(map(id, efs))) if sys.version_info >= (2,5) else 1
+    return len(set(map(id, efs)))
 
 
 def sorted(it):
diff --git a/tests/run/struct_conversion.pyx b/tests/run/struct_conversion.pyx
index 9a7c7a25fb3d22965864d833d49f1d068432cdd0..26bd62686a92becd899977ca80a1a0d185bab0b1 100644
--- a/tests/run/struct_conversion.pyx
+++ b/tests/run/struct_conversion.pyx
@@ -3,7 +3,7 @@ cdef struct Point:
     double y
     int color
 
-def test_constructor(x, y, color):
+def test_constructor(x, y, int color):
     """
     >>> sorted(test_constructor(1,2,255).items())
     [('color', 255), ('x', 1.0), ('y', 2.0)]
@@ -13,6 +13,17 @@ def test_constructor(x, y, color):
     cdef Point p = Point(x, y, color)
     return p
 
+
+def return_constructor(x, y, int color):
+    """
+    >>> sorted(return_constructor(1,2,255).items())
+    [('color', 255), ('x', 1.0), ('y', 2.0)]
+    >>> try: return_constructor(1, None, 255)
+    ... except TypeError: pass
+    """
+    return Point(x, y, color)
+
+
 def test_constructor_kwds(x, y, color):
     """
     >>> sorted(test_constructor_kwds(1.25, 2.5, 128).items())
@@ -25,6 +36,19 @@ def test_constructor_kwds(x, y, color):
     cdef Point p = Point(x=x, y=y, color=color)
     return p
 
+
+def return_constructor_kwds(double x, y, color):
+    """
+    >>> sorted(return_constructor_kwds(1.25, 2.5, 128).items())
+    [('color', 128), ('x', 1.25), ('y', 2.5)]
+    >>> return_constructor_kwds(1.25, 2.5, None)
+    Traceback (most recent call last):
+    ...
+    TypeError: an integer is required
+    """
+    return Point(x=x, y=y, color=color)
+
+
 def test_dict_construction(x, y, color):
     """
     >>> sorted(test_dict_construction(4, 5, 64).items())
diff --git a/tests/run/subop.pyx b/tests/run/subop.pyx
index a7e7cbe840accc53017789e9015170927b9365ea..547a0c2c3e9b6e7e2e7bad831297a2d38e7d2ffb 100644
--- a/tests/run/subop.pyx
+++ b/tests/run/subop.pyx
@@ -1,6 +1,10 @@
 cimport cython
 
 
+def bigint(x):
+    print(str(x).rstrip('L'))
+
+
 def mixed_test():
     """
     >>> mixed_test()
@@ -44,6 +48,10 @@ def sub_x_1(x):
     0
     >>> sub_x_1(-1)
     -2
+    >>> bigint(2**50 - 1)
+    1125899906842623
+    >>> bigint(sub_x_1(2**50))
+    1125899906842623
     >>> sub_x_1(1.5)
     0.5
     >>> sub_x_1(-1.5)
@@ -63,6 +71,12 @@ def sub_x_1f(x):
     0.0
     >>> sub_x_1f(-1)
     -2.0
+    >>> 2**52 - 1.0
+    4503599627370495.0
+    >>> sub_x_1f(2**52)
+    4503599627370495.0
+    >>> sub_x_1f(2**60) == 2**60 - 1.0 or sub_x_1f(2**60)
+    True
     >>> sub_x_1f(1.5)
     0.5
     >>> sub_x_1f(-1.5)
@@ -82,6 +96,10 @@ def sub_x_large(x):
     -1073741823
     >>> sub_x_large(-1)
     -1073741825
+    >>> bigint(2**50 - 2**30)
+    1125898833100800
+    >>> bigint(sub_x_large(2**50))
+    1125898833100800
     >>> sub_x_large(2.0**30)
     0.0
     >>> sub_x_large(2.0**30 + 1)
@@ -107,6 +125,10 @@ def sub_1_x(x):
     2
     >>> sub_1_x(1)
     0
+    >>> bigint(1 - 2**50)
+    -1125899906842623
+    >>> bigint(sub_1_x(2**50))
+    -1125899906842623
     >>> sub_1_x(1.5)
     -0.5
     >>> sub_1_x(-1.5)
@@ -126,6 +148,12 @@ def sub_1f_x(x):
     2.0
     >>> sub_1f_x(1)
     0.0
+    >>> 1.0 - 2**52
+    -4503599627370495.0
+    >>> sub_1f_x(2**52)
+    -4503599627370495.0
+    >>> sub_1f_x(2**60) == 1.0 - 2**60 or sub_1f_x(2**60)
+    True
     >>> sub_1f_x(1.5)
     -0.5
     >>> sub_1f_x(-1.5)
diff --git a/tests/run/unpack.pyx b/tests/run/unpack.pyx
index 9c4a32d0d7060368bf812fb79677c0d8c7e5e0b2..becb6fbe876a1f2b2d9bcd9030bef9673ef23ce3 100644
--- a/tests/run/unpack.pyx
+++ b/tests/run/unpack.pyx
@@ -3,12 +3,12 @@
 
 import cython
 
-_set = set
 
 def _it(N):
     for i in range(N):
         yield i
 
+
 cdef class ItCount(object):
     cdef object values
     cdef readonly count
@@ -89,9 +89,9 @@ def unpack_partial(it):
     """
     >>> it = _it(2)
     >>> a = b = c = 0
-    >>> a,b,c = it
-    Traceback (most recent call last):
-    ValueError: need more than 2 values to unpack
+    >>> try: a,b,c = it
+    ... except ValueError: pass
+    ... else: print("DID NOT FAIL!")
     >>> a, b, c
     (0, 0, 0)
     >>> unpack_partial([1,2])
@@ -103,9 +103,9 @@ def unpack_partial(it):
 
     >>> it = ItCount([1,2])
     >>> a = b = c = 0
-    >>> a,b,c = it
-    Traceback (most recent call last):
-    ValueError: need more than 2 values to unpack
+    >>> try: a,b,c = it
+    ... except ValueError: pass
+    ... else: print("DID NOT FAIL!")
     >>> a, b, c
     (0, 0, 0)
     >>> it.count
@@ -153,7 +153,7 @@ def unpack_partial_typed(it):
     (0, 0, 0)
     >>> unpack_partial_typed((1, 'abc', 3))
     (0, 0, 0)
-    >>> unpack_partial_typed(_set([1, 'abc', 3]))
+    >>> unpack_partial_typed(set([1, 'abc', 3]))
     (0, 0, 0)
 
     >>> it = ItCount([1, 'abc', 3])
@@ -222,10 +222,10 @@ def failure_too_many(it):
     Traceback (most recent call last):
     ValueError: too many values to unpack (expected 3)
 
-    >>> a,b,c = _set([1,2,3,4])    # doctest: +ELLIPSIS
+    >>> a,b,c = set([1,2,3,4])    # doctest: +ELLIPSIS
     Traceback (most recent call last):
     ValueError: too many values to unpack...
-    >>> failure_too_many(_set([1,2,3,4]))
+    >>> failure_too_many(set([1,2,3,4]))
     Traceback (most recent call last):
     ValueError: too many values to unpack (expected 3)
 
@@ -239,6 +239,7 @@ def failure_too_many(it):
     a,b,c = it
     return a,b,c
 
+
 def failure_too_few(it):
     """
     >>> try: a,b,c = [1,2]
@@ -253,16 +254,16 @@ def failure_too_few(it):
     Traceback (most recent call last):
     ValueError: need more than 2 values to unpack
 
-    >>> a,b,c = _set([1,2])
-    Traceback (most recent call last):
-    ValueError: need more than 2 values to unpack
-    >>> failure_too_few(_set([1,2]))
+    >>> try: a,b,c = set([1,2])
+    ... except ValueError: pass
+    ... else: print("DID NOT FAIL!")
+    >>> failure_too_few(set([1,2]))
     Traceback (most recent call last):
     ValueError: need more than 2 values to unpack
 
-    >>> a,b,c = _it(2)
-    Traceback (most recent call last):
-    ValueError: need more than 2 values to unpack
+    >>> try: a,b,c = _it(2)
+    ... except ValueError: pass
+    ... else: print("DID NOT FAIL!")
     >>> failure_too_few(_it(2))
     Traceback (most recent call last):
     ValueError: need more than 2 values to unpack
@@ -270,6 +271,7 @@ def failure_too_few(it):
     a,b,c = it
     return a,b,c
 
+
 def _it_failure(N):
     for i in range(N):
         yield i
diff --git a/tests/run/yield_from_pep380.pyx b/tests/run/yield_from_pep380.pyx
index 91045cf558fb54e36e5ce21c862e1e723ae11b10..1bc4d972aacd37d949f7cbc8713f5ce24834c794 100644
--- a/tests/run/yield_from_pep380.pyx
+++ b/tests/run/yield_from_pep380.pyx
@@ -355,6 +355,7 @@ def __test_value_attribute_of_StopIteration_exception():
     pex(e)
     return trace
 
+
 def test_exception_value_crash():
     """
     >>> test_exception_value_crash()
@@ -369,6 +370,50 @@ def test_exception_value_crash():
         return [42]
     return list(g1())
 
+
+def test_return_none():
+    """
+    >>> test_return_none()
+    ['g2']
+    """
+    # There used to be a refcount error in CPython when the return value
+    # stored in the StopIteration has a refcount of 1.
+    def g1():
+        yield from g2()
+    def g2():
+        yield "g2"
+        return None
+    return list(g1())
+
+
+def test_finally_return_none(raise_exc=None):
+    """
+    >>> gen = test_finally_return_none()
+    >>> next(gen)
+    'g2'
+    >>> next(gen)
+    Traceback (most recent call last):
+    StopIteration
+
+    >>> gen = test_finally_return_none()
+    >>> next(gen)
+    'g2'
+    >>> try: gen.throw(ValueError())
+    ... except StopIteration: pass
+    ... else: print("FAILED")
+    """
+    # There used to be a refcount error in CPython when the return value
+    # stored in the StopIteration has a refcount of 1.
+    def g1():
+        yield from g2()
+    def g2():
+        try:
+            yield "g2"
+        finally:
+            return None
+    return g1()
+
+
 def test_generator_return_value():
     """
     >>> _lines(test_generator_return_value())
diff --git a/tests/run/yield_from_py33.pyx b/tests/run/yield_from_py33.pyx
new file mode 100644
index 0000000000000000000000000000000000000000..c219cf0deb6e654782adebced2b085de92e3e093
--- /dev/null
+++ b/tests/run/yield_from_py33.pyx
@@ -0,0 +1,22 @@
+# mode: run
+# tag: generator
+
+def yield_from_gen(values):
+    """
+    >>> def yf(x): yield from x
+    >>> list(yf(yield_from_gen([1, 2, 3, 4])))
+    [1, 2, 3, 4]
+    """
+    for value in values:
+        yield value
+
+
+def yield_from_gen_return(values):
+    """
+    >>> def yf(x): yield from x
+    >>> list(yf(yield_from_gen_return([1, 2, 3, 4])))
+    [1, 2, 3, 4]
+    """
+    for value in values:
+        yield value
+    return 5