diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md
index cb011b016afcc3a3d59d9c4f1b3345bb2dbb205d_LmdpdGh1Yi9JU1NVRV9URU1QTEFURS9idWdfcmVwb3J0Lm1k..3c2c33d638a8f5028602752643f0e6c26482bf14_LmdpdGh1Yi9JU1NVRV9URU1QTEFURS9idWdfcmVwb3J0Lm1k 100644
--- a/.github/ISSUE_TEMPLATE/bug_report.md
+++ b/.github/ISSUE_TEMPLATE/bug_report.md
@@ -8,7 +8,7 @@
 ---
 
 <!--
-**Note:**
+**PLEASE READ THIS FIRST:**
 - Do not use the bug and feature tracker for support requests. Use the `cython-users` mailing list instead.
 - Did you search for similar issues already? Please do, it helps to save us precious time that we otherwise could not invest into development.
 - Did you try the latest master branch or pre-release? It might already have what you want to report. Also see the [Changelog](https://github.com/cython/cython/blob/master/CHANGES.rst) regarding recent changes.
diff --git a/Cython/Compiler/AutoDocTransforms.py b/Cython/Compiler/AutoDocTransforms.py
index cb011b016afcc3a3d59d9c4f1b3345bb2dbb205d_Q3l0aG9uL0NvbXBpbGVyL0F1dG9Eb2NUcmFuc2Zvcm1zLnB5..3c2c33d638a8f5028602752643f0e6c26482bf14_Q3l0aG9uL0NvbXBpbGVyL0F1dG9Eb2NUcmFuc2Zvcm1zLnB5 100644
--- a/Cython/Compiler/AutoDocTransforms.py
+++ b/Cython/Compiler/AutoDocTransforms.py
@@ -19,6 +19,7 @@
         """
         ExpressionWriter.__init__(self)
         self.description = description
+        self.incomplete = False
 
     def visit_Node(self, node):
         self.put(u"<???>")
@@ -22,6 +23,7 @@
 
     def visit_Node(self, node):
         self.put(u"<???>")
+        self.incomplete = True
         if self.description:
             warning(node.pos,
                     "Failed to convert code to string representation in {0}".format(
@@ -30,8 +32,9 @@
     def visit_LambdaNode(self, node):
         # XXX Should we do better?
         self.put("<lambda>")
+        self.incomplete = True
         if self.description:
             warning(node.pos,
                     "Failed to convert lambda to string representation in {0}".format(
                         self.description), level=1)
 
@@ -33,8 +36,13 @@
         if self.description:
             warning(node.pos,
                     "Failed to convert lambda to string representation in {0}".format(
                         self.description), level=1)
 
+    def visit_UnicodeNode(self, node):
+        # Discard Unicode prefix in annotations. Any tool looking at them
+        # would probably expect Py3 string semantics.
+        self.emit_string(node, "")
+
     def visit_AnnotationNode(self, node):
         self.put(node.string.unicode_value)
 
@@ -47,6 +55,12 @@
         self.class_node = None
 
     def _fmt_expr(self, node):
+        writer = ExpressionWriter()
+        result = writer.write(node)
+        # print(type(node).__name__, '-->', result)
+        return result
+
+    def _fmt_annotation(self, node):
         writer = AnnotationWriter()
         result = writer.write(node)
         # print(type(node).__name__, '-->', result)
@@ -59,7 +73,7 @@
             doc = arg.type.declaration_code(arg.name, for_display=1)
 
         if arg.annotation:
-            annotation = self._fmt_expr(arg.annotation)
+            annotation = self._fmt_annotation(arg.annotation)
             doc = doc + (': %s' % annotation)
             if arg.default:
                 default = self._fmt_expr(arg.default)
@@ -72,7 +86,7 @@
     def _fmt_star_arg(self, arg):
         arg_doc = arg.name
         if arg.annotation:
-            annotation = self._fmt_expr(arg.annotation)
+            annotation = self._fmt_annotation(arg.annotation)
             arg_doc = arg_doc + (': %s' % annotation)
         return arg_doc
 
@@ -118,7 +132,7 @@
             func_doc = '%s.%s' % (cls_name, func_doc)
         ret_doc = None
         if return_expr:
-            ret_doc = self._fmt_expr(return_expr)
+            ret_doc = self._fmt_annotation(return_expr)
         elif return_type:
             ret_doc = self._fmt_ret_type(return_type)
         if ret_doc:
diff --git a/Cython/Compiler/Code.pxd b/Cython/Compiler/Code.pxd
index cb011b016afcc3a3d59d9c4f1b3345bb2dbb205d_Q3l0aG9uL0NvbXBpbGVyL0NvZGUucHhk..3c2c33d638a8f5028602752643f0e6c26482bf14_Q3l0aG9uL0NvbXBpbGVyL0NvZGUucHhk 100644
--- a/Cython/Compiler/Code.pxd
+++ b/Cython/Compiler/Code.pxd
@@ -1,5 +1,4 @@
-
-from __future__ import absolute_import
+# cython: language_level=3
 
 cimport cython
 from ..StringIOTree cimport StringIOTree
diff --git a/Cython/Compiler/Code.py b/Cython/Compiler/Code.py
index cb011b016afcc3a3d59d9c4f1b3345bb2dbb205d_Q3l0aG9uL0NvbXBpbGVyL0NvZGUucHk=..3c2c33d638a8f5028602752643f0e6c26482bf14_Q3l0aG9uL0NvbXBpbGVyL0NvZGUucHk= 100644
--- a/Cython/Compiler/Code.py
+++ b/Cython/Compiler/Code.py
@@ -1145,6 +1145,14 @@
         'end'
     ]
 
+    # h files can only have a much smaller list of sections
+    h_code_layout = [
+        'h_code',
+        'utility_code_proto_before_types',
+        'type_declarations',
+        'utility_code_proto',
+        'end'
+    ]
 
     def __init__(self, writer, module_node, code_config, common_utility_include_dir=None):
         self.filename_table = {}
@@ -1215,6 +1223,11 @@
         code.putln("")
         code.putln("/* --- Runtime support code --- */")
 
+    def initialize_main_h_code(self):
+        rootwriter = self.rootwriter
+        for part in self.h_code_layout:
+            self.parts[part] = rootwriter.insertion_point()
+
     def finalize_main_c_code(self):
         self.close_global_decls()
 
diff --git a/Cython/Compiler/Errors.py b/Cython/Compiler/Errors.py
index cb011b016afcc3a3d59d9c4f1b3345bb2dbb205d_Q3l0aG9uL0NvbXBpbGVyL0Vycm9ycy5weQ==..3c2c33d638a8f5028602752643f0e6c26482bf14_Q3l0aG9uL0NvbXBpbGVyL0Vycm9ycy5weQ== 100644
--- a/Cython/Compiler/Errors.py
+++ b/Cython/Compiler/Errors.py
@@ -24,6 +24,8 @@
 class PyrexWarning(Exception):
     pass
 
+class CannotSpecialize(PyrexError):
+    pass
 
 def context(position):
     source = position[0]
diff --git a/Cython/Compiler/ExprNodes.py b/Cython/Compiler/ExprNodes.py
index cb011b016afcc3a3d59d9c4f1b3345bb2dbb205d_Q3l0aG9uL0NvbXBpbGVyL0V4cHJOb2Rlcy5weQ==..3c2c33d638a8f5028602752643f0e6c26482bf14_Q3l0aG9uL0NvbXBpbGVyL0V4cHJOb2Rlcy5weQ== 100644
--- a/Cython/Compiler/ExprNodes.py
+++ b/Cython/Compiler/ExprNodes.py
@@ -23,8 +23,9 @@
 import operator
 
 from .Errors import (
-    error, warning, InternalError, CompileError, report_error, local_errors)
+    error, warning, InternalError, CompileError, report_error, local_errors,
+    CannotSpecialize)
 from .Code import UtilityCode, TempitaUtilityCode
 from . import StringEncoding
 from . import Naming
 from . import Nodes
@@ -27,8 +28,8 @@
 from .Code import UtilityCode, TempitaUtilityCode
 from . import StringEncoding
 from . import Naming
 from . import Nodes
-from .Nodes import Node, utility_code_for_imports
+from .Nodes import Node, utility_code_for_imports, SingleAssignmentNode, PassStatNode
 from . import PyrexTypes
 from .PyrexTypes import py_object_type, c_long_type, typecast, error_type, \
     unspecified_type
@@ -458,6 +459,9 @@
 
     child_attrs = property(fget=operator.attrgetter('subexprs'))
 
+    def analyse_annotations(self, env):
+        pass
+
     def not_implemented(self, method_name):
         print_call_chain(method_name, "not implemented")
         raise InternalError(
@@ -500,10 +504,6 @@
         else:
             return self.calculate_result_code()
 
-    def _make_move_result_rhs(self, result, allow_move=True):
-        if (self.is_temp and allow_move and
-                self.type.is_cpp_class and not self.type.is_reference):
-            self.has_temp_moved = True
-            return "__PYX_STD_MOVE_IF_SUPPORTED({0})".format(result)
-        else:
+    def _make_move_result_rhs(self, result, optional=False):
+        if optional and not (self.is_temp and self.type.is_cpp_class and not self.type.is_reference):
             return result
@@ -509,3 +509,5 @@
             return result
+        self.has_temp_moved = True
+        return "{}({})".format("__PYX_STD_MOVE_IF_SUPPORTED" if optional else "std::move", result)
 
     def move_result_rhs(self):
@@ -510,5 +512,5 @@
 
     def move_result_rhs(self):
-        return self._make_move_result_rhs(self.result())
+        return self._make_move_result_rhs(self.result(), optional=True)
 
     def move_result_rhs_as(self, type):
@@ -513,8 +515,10 @@
 
     def move_result_rhs_as(self, type):
-        allow_move = (type and not type.is_reference and not type.needs_refcounting)
-        return self._make_move_result_rhs(self.result_as(type),
-                                          allow_move=allow_move)
+        result = self.result_as(type)
+        if not (type.is_reference or type.needs_refcounting):
+            requires_move = type.is_rvalue_reference and self.is_temp
+            result = self._make_move_result_rhs(result, optional=not requires_move)
+        return result
 
     def pythran_result(self, type_=None):
         if is_pythran_supported_node_or_none(self):
@@ -1973,7 +1977,8 @@
     def declare_from_annotation(self, env, as_target=False):
         """Implements PEP 526 annotation typing in a fairly relaxed way.
 
-        Annotations are ignored for global variables, Python class attributes and already declared variables.
-        String literals are allowed and ignored.
-        The ambiguous Python types 'int' and 'long' are ignored and the 'cython.int' form must be used instead.
+        Annotations are ignored for global variables.
+        All other annotations are stored on the entry in the symbol table.
+        String literals are allowed and not evaluated.
+        The ambiguous Python types 'int' and 'long' are not evaluated - the 'cython.int' form must be used instead.
         """
@@ -1979,7 +1984,2 @@
         """
-        if not env.directives['annotation_typing']:
-            return
-        if env.is_module_scope or env.is_py_class_scope:
-            # annotations never create global cdef names and Python classes don't support them anyway
-            return
         name = self.name
@@ -1985,6 +1985,2 @@
         name = self.name
-        if self.entry or env.lookup_here(name) is not None:
-            # already declared => ignore annotation
-            return
-
         annotation = self.annotation
@@ -1990,15 +1986,38 @@
         annotation = self.annotation
-        if annotation.expr.is_string_literal:
-            # name: "description" => not a type, but still a declared variable or attribute
-            atype = None
-        else:
-            _, atype = annotation.analyse_type_annotation(env)
-        if atype is None:
-            atype = unspecified_type if as_target and env.directives['infer_types'] != False else py_object_type
-        if atype.is_fused and env.fused_to_specific:
-            atype = atype.specialize(env.fused_to_specific)
-        self.entry = env.declare_var(name, atype, self.pos, is_cdef=not as_target)
-        self.entry.annotation = annotation.expr
+        entry = self.entry or env.lookup_here(name)
+        if not entry:
+            # annotations never create global cdef names
+            if env.is_module_scope:
+                return
+            if (
+                # name: "description" => not a type, but still a declared variable or attribute
+                annotation.expr.is_string_literal
+                # don't do type analysis from annotations if not asked to, but still collect the annotation
+                or not env.directives['annotation_typing']
+            ):
+                atype = None
+            else:
+                _, atype = annotation.analyse_type_annotation(env)
+            if atype is None:
+                atype = unspecified_type if as_target and env.directives['infer_types'] != False else py_object_type
+            if atype.is_fused and env.fused_to_specific:
+                try:
+                    atype = atype.specialize(env.fused_to_specific)
+                except CannotSpecialize:
+                    error(self.pos,
+                          "'%s' cannot be specialized since its type is not a fused argument to this function" %
+                          self.name)
+                    atype = error_type
+            if as_target and env.is_c_class_scope and not (atype.is_pyobject or atype.is_error):
+                # TODO: this will need revising slightly if either cdef dataclasses or
+                # annotated cdef attributes are implemented
+                atype = py_object_type
+                warning(annotation.pos, "Annotation ignored since class-level attributes must be Python objects. "
+                        "Were you trying to set up an instance attribute?", 2)
+            entry = self.entry = env.declare_var(name, atype, self.pos, is_cdef=not as_target)
+        # Even if the entry already exists, make sure we're supplying an annotation if we can.
+        if annotation and not entry.annotation:
+            entry.annotation = annotation
 
     def analyse_as_module(self, env):
         # Try to interpret this as a reference to a cimported module.
@@ -5770,8 +5789,18 @@
             else:
                 alternatives = overloaded_entry.all_alternatives()
 
-            entry = PyrexTypes.best_match(
-                [arg.type for arg in args], alternatives, self.pos, env, args)
+            # For any argument/parameter pair A/P, if P is a forwarding reference,
+            # use lvalue-reference-to-A for deduction in place of A when the
+            # function call argument is an lvalue. See:
+            # https://en.cppreference.com/w/cpp/language/template_argument_deduction#Deduction_from_a_function_call
+            arg_types = [arg.type for arg in args]
+            if func_type.is_cfunction:
+                for i, formal_arg in enumerate(func_type.args):
+                    if formal_arg.is_forwarding_reference():
+                        if self.args[i].is_lvalue():
+                            arg_types[i] = PyrexTypes.c_ref_type(arg_types[i])
+
+            entry = PyrexTypes.best_match(arg_types, alternatives, self.pos, env, args)
 
             if not entry:
                 self.type = PyrexTypes.error_type
@@ -9037,6 +9066,9 @@
     type = py_object_type
     is_temp = True
 
+    def analyse_annotations(self, env):
+        pass
+
     def infer_type(self, env):
         # TODO: could return 'type' in some cases
         return py_object_type
@@ -9107,6 +9139,26 @@
 
     gil_message = "Constructing Python class"
 
+    def analyse_annotations(self, env):
+        from .AutoDocTransforms import AnnotationWriter
+        position = self.class_def_node.pos
+        dict_items = [
+            DictItemNode(
+                entry.pos,
+                key=IdentifierStringNode(entry.pos, value=entry.name),
+                value=entry.annotation.string
+            )
+            for entry in env.entries.values() if entry.annotation
+        ]
+        # Annotations dict shouldn't exist for classes which don't declare any.
+        if dict_items:
+            annotations_dict = DictNode(position, key_value_pairs=dict_items)
+            lhs = NameNode(position, name=StringEncoding.EncodedString(u"__annotations__"))
+            lhs.entry = env.lookup_here(lhs.name) or env.declare_var(lhs.name, dict_type, position)
+            node = SingleAssignmentNode(position, lhs=lhs, rhs=annotations_dict)
+            node.analyse_declarations(env)
+            self.class_def_node.body.stats.insert(0, node)
+
     def generate_result_code(self, code):
         code.globalstate.use_utility_code(UtilityCode.load_cached("Py3ClassCreate", "ObjectHandling.c"))
         cname = code.intern_identifier(self.name)
@@ -10905,7 +10957,11 @@
         if operand_as_type:
             self.arg_type = operand_as_type
             if self.arg_type.is_fused:
-                self.arg_type = self.arg_type.specialize(env.fused_to_specific)
+                try:
+                    self.arg_type = self.arg_type.specialize(env.fused_to_specific)
+                except CannotSpecialize:
+                    error(self.operand.pos,
+                          "Type cannot be specialized since it is not a fused argument to this function")
             self.__class__ = SizeofTypeNode
             self.check_type()
         else:
diff --git a/Cython/Compiler/FlowControl.pxd b/Cython/Compiler/FlowControl.pxd
index cb011b016afcc3a3d59d9c4f1b3345bb2dbb205d_Q3l0aG9uL0NvbXBpbGVyL0Zsb3dDb250cm9sLnB4ZA==..3c2c33d638a8f5028602752643f0e6c26482bf14_Q3l0aG9uL0NvbXBpbGVyL0Zsb3dDb250cm9sLnB4ZA== 100644
--- a/Cython/Compiler/FlowControl.pxd
+++ b/Cython/Compiler/FlowControl.pxd
@@ -1,4 +1,4 @@
-from __future__ import absolute_import
+# cython: language_level=3
 
 cimport cython
 
diff --git a/Cython/Compiler/FusedNode.py b/Cython/Compiler/FusedNode.py
index cb011b016afcc3a3d59d9c4f1b3345bb2dbb205d_Q3l0aG9uL0NvbXBpbGVyL0Z1c2VkTm9kZS5weQ==..3c2c33d638a8f5028602752643f0e6c26482bf14_Q3l0aG9uL0NvbXBpbGVyL0Z1c2VkTm9kZS5weQ== 100644
--- a/Cython/Compiler/FusedNode.py
+++ b/Cython/Compiler/FusedNode.py
@@ -7,6 +7,7 @@
 from .ExprNodes import CloneNode, ProxyNode, TupleNode
 from .Nodes import FuncDefNode, CFuncDefNode, StatListNode, DefNode
 from ..Utils import OrderedSet
+from .Errors import error, CannotSpecialize
 
 
 class FusedCFuncDefNode(StatListNode):
@@ -141,7 +142,14 @@
             copied_node = copy.deepcopy(self.node)
 
             # Make the types in our CFuncType specific.
-            type = copied_node.type.specialize(fused_to_specific)
+            try:
+                type = copied_node.type.specialize(fused_to_specific)
+            except CannotSpecialize:
+                # unlike for the argument types, specializing the return type can fail
+                error(copied_node.pos, "Return type is a fused type that cannot "
+                      "be determined from the function arguments")
+                self.py_func = None  # this is just to let the compiler exit gracefully
+                return
             entry = copied_node.entry
             type.specialize_entry(entry, cname)
 
diff --git a/Cython/Compiler/Lexicon.py b/Cython/Compiler/Lexicon.py
index cb011b016afcc3a3d59d9c4f1b3345bb2dbb205d_Q3l0aG9uL0NvbXBpbGVyL0xleGljb24ucHk=..3c2c33d638a8f5028602752643f0e6c26482bf14_Q3l0aG9uL0NvbXBpbGVyL0xleGljb24ucHk= 100644
--- a/Cython/Compiler/Lexicon.py
+++ b/Cython/Compiler/Lexicon.py
@@ -77,7 +77,7 @@
     punct = Any(":,;+-*/|&<>=.%`~^?!@")
     diphthong = Str("==", "<>", "!=", "<=", ">=", "<<", ">>", "**", "//",
                     "+=", "-=", "*=", "/=", "%=", "|=", "^=", "&=",
-                    "<<=", ">>=", "**=", "//=", "->", "@=")
+                    "<<=", ">>=", "**=", "//=", "->", "@=", "&&", "||")
     spaces = Rep1(Any(" \t\f"))
     escaped_newline = Str("\\\n")
     lineterm = Eol + Opt(Str("\n"))
diff --git a/Cython/Compiler/ModuleNode.py b/Cython/Compiler/ModuleNode.py
index cb011b016afcc3a3d59d9c4f1b3345bb2dbb205d_Q3l0aG9uL0NvbXBpbGVyL01vZHVsZU5vZGUucHk=..3c2c33d638a8f5028602752643f0e6c26482bf14_Q3l0aG9uL0NvbXBpbGVyL01vZHVsZU5vZGUucHk= 100644
--- a/Cython/Compiler/ModuleNode.py
+++ b/Cython/Compiler/ModuleNode.py
@@ -191,5 +191,5 @@
         h_extension_types = h_entries(env.c_class_entries)
         if h_types or h_vars or h_funcs or h_extension_types:
             result.h_file = replace_suffix_encoded(result.c_file, ".h")
-            h_code = Code.CCodeWriter()
+            h_code_writer = Code.CCodeWriter()
             c_code_config = generate_c_code_config(env, options)
@@ -195,8 +195,12 @@
             c_code_config = generate_c_code_config(env, options)
-            Code.GlobalState(h_code, self, c_code_config)
+            globalstate = Code.GlobalState(h_code_writer, self, c_code_config)
+            globalstate.initialize_main_h_code()  # in-case utility code is used in the header
+            h_code_start = globalstate.parts['h_code']
+            h_code_main = globalstate.parts['type_declarations']
+            h_code_end = globalstate.parts['end']
             if options.generate_pxi:
                 result.i_file = replace_suffix_encoded(result.c_file, ".pxi")
                 i_code = Code.PyrexCodeWriter(result.i_file)
             else:
                 i_code = None
 
@@ -197,8 +201,8 @@
             if options.generate_pxi:
                 result.i_file = replace_suffix_encoded(result.c_file, ".pxi")
                 i_code = Code.PyrexCodeWriter(result.i_file)
             else:
                 i_code = None
 
-            h_code.put_generated_by()
+            h_code_start.put_generated_by()
             h_guard = self.api_name(Naming.h_guard_prefix, env)
@@ -204,6 +208,6 @@
             h_guard = self.api_name(Naming.h_guard_prefix, env)
-            h_code.put_h_guard(h_guard)
-            h_code.putln("")
-            h_code.putln('#include "Python.h"')
-            self.generate_type_header_code(h_types, h_code)
+            h_code_start.put_h_guard(h_guard)
+            h_code_start.putln("")
+            h_code_start.putln('#include "Python.h"')
+            self.generate_type_header_code(h_types, h_code_start)
             if options.capi_reexport_cincludes:
@@ -209,4 +213,4 @@
             if options.capi_reexport_cincludes:
-                self.generate_includes(env, [], h_code)
-            h_code.putln("")
+                self.generate_includes(env, [], h_code_start)
+            h_code_start.putln("")
             api_guard = self.api_name(Naming.api_guard_prefix, env)
@@ -212,7 +216,7 @@
             api_guard = self.api_name(Naming.api_guard_prefix, env)
-            h_code.putln("#ifndef %s" % api_guard)
-            h_code.putln("")
-            self.generate_extern_c_macro_definition(h_code)
-            h_code.putln("")
-            self.generate_dl_import_macro(h_code)
+            h_code_start.putln("#ifndef %s" % api_guard)
+            h_code_start.putln("")
+            self.generate_extern_c_macro_definition(h_code_start)
+            h_code_start.putln("")
+            self.generate_dl_import_macro(h_code_start)
             if h_extension_types:
@@ -218,3 +222,3 @@
             if h_extension_types:
-                h_code.putln("")
+                h_code_main.putln("")
                 for entry in h_extension_types:
@@ -220,5 +224,5 @@
                 for entry in h_extension_types:
-                    self.generate_cclass_header_code(entry.type, h_code)
+                    self.generate_cclass_header_code(entry.type, h_code_main)
                     if i_code:
                         self.generate_cclass_include_code(entry.type, i_code)
             if h_funcs:
@@ -222,5 +226,5 @@
                     if i_code:
                         self.generate_cclass_include_code(entry.type, i_code)
             if h_funcs:
-                h_code.putln("")
+                h_code_main.putln("")
                 for entry in h_funcs:
@@ -226,3 +230,3 @@
                 for entry in h_funcs:
-                    self.generate_public_declaration(entry, h_code, i_code)
+                    self.generate_public_declaration(entry, h_code_main, i_code)
             if h_vars:
@@ -228,3 +232,3 @@
             if h_vars:
-                h_code.putln("")
+                h_code_main.putln("")
                 for entry in h_vars:
@@ -230,13 +234,13 @@
                 for entry in h_vars:
-                    self.generate_public_declaration(entry, h_code, i_code)
-            h_code.putln("")
-            h_code.putln("#endif /* !%s */" % api_guard)
-            h_code.putln("")
-            h_code.putln("/* WARNING: the interface of the module init function changed in CPython 3.5. */")
-            h_code.putln("/* It now returns a PyModuleDef instance instead of a PyModule instance. */")
-            h_code.putln("")
-            h_code.putln("#if PY_MAJOR_VERSION < 3")
+                    self.generate_public_declaration(entry, h_code_main, i_code)
+            h_code_main.putln("")
+            h_code_main.putln("#endif /* !%s */" % api_guard)
+            h_code_main.putln("")
+            h_code_main.putln("/* WARNING: the interface of the module init function changed in CPython 3.5. */")
+            h_code_main.putln("/* It now returns a PyModuleDef instance instead of a PyModule instance. */")
+            h_code_main.putln("")
+            h_code_main.putln("#if PY_MAJOR_VERSION < 3")
             if env.module_name.isascii():
                 py2_mod_name = env.module_name
             else:
                 py2_mod_name = env.module_name.encode("ascii", errors="ignore").decode("utf-8")
@@ -239,10 +243,10 @@
             if env.module_name.isascii():
                 py2_mod_name = env.module_name
             else:
                 py2_mod_name = env.module_name.encode("ascii", errors="ignore").decode("utf-8")
-                h_code.putln('#error "Unicode module names are not supported in Python 2";')
-            h_code.putln("PyMODINIT_FUNC init%s(void);" % py2_mod_name)
-            h_code.putln("#else")
+                h_code_main.putln('#error "Unicode module names are not supported in Python 2";')
+            h_code_main.putln("PyMODINIT_FUNC init%s(void);" % py2_mod_name)
+            h_code_main.putln("#else")
             py3_mod_func_name = self.mod_init_func_cname('PyInit', env)
             warning_string = EncodedString('Use PyImport_AppendInittab("%s", %s) instead of calling %s directly.' % (
                 py2_mod_name, py3_mod_func_name, py3_mod_func_name))
@@ -246,9 +250,9 @@
             py3_mod_func_name = self.mod_init_func_cname('PyInit', env)
             warning_string = EncodedString('Use PyImport_AppendInittab("%s", %s) instead of calling %s directly.' % (
                 py2_mod_name, py3_mod_func_name, py3_mod_func_name))
-            h_code.putln('/* WARNING: %s from Python 3.5 */' % warning_string.rstrip('.'))
-            h_code.putln("PyMODINIT_FUNC %s(void);" % py3_mod_func_name)
-            h_code.putln("")
-            h_code.putln("#if PY_VERSION_HEX >= 0x03050000 "
+            h_code_main.putln('/* WARNING: %s from Python 3.5 */' % warning_string.rstrip('.'))
+            h_code_main.putln("PyMODINIT_FUNC %s(void);" % py3_mod_func_name)
+            h_code_main.putln("")
+            h_code_main.putln("#if PY_VERSION_HEX >= 0x03050000 "
                 "&& (defined(__GNUC__) || defined(__clang__) || defined(_MSC_VER) "
                 "|| (defined(__cplusplus) && __cplusplus >= 201402L))")
@@ -253,7 +257,7 @@
                 "&& (defined(__GNUC__) || defined(__clang__) || defined(_MSC_VER) "
                 "|| (defined(__cplusplus) && __cplusplus >= 201402L))")
-            h_code.putln("#if defined(__cplusplus) && __cplusplus >= 201402L")
-            h_code.putln("[[deprecated(%s)]] inline" % warning_string.as_c_string_literal())
-            h_code.putln("#elif defined(__GNUC__) || defined(__clang__)")
-            h_code.putln('__attribute__ ((__deprecated__(%s), __unused__)) __inline__' % (
+            h_code_main.putln("#if defined(__cplusplus) && __cplusplus >= 201402L")
+            h_code_main.putln("[[deprecated(%s)]] inline" % warning_string.as_c_string_literal())
+            h_code_main.putln("#elif defined(__GNUC__) || defined(__clang__)")
+            h_code_main.putln('__attribute__ ((__deprecated__(%s), __unused__)) __inline__' % (
                 warning_string.as_c_string_literal()))
@@ -259,4 +263,4 @@
                 warning_string.as_c_string_literal()))
-            h_code.putln("#elif defined(_MSC_VER)")
-            h_code.putln('__declspec(deprecated(%s)) __inline' % (
+            h_code_main.putln("#elif defined(_MSC_VER)")
+            h_code_main.putln('__declspec(deprecated(%s)) __inline' % (
                 warning_string.as_c_string_literal()))
@@ -262,6 +266,6 @@
                 warning_string.as_c_string_literal()))
-            h_code.putln('#endif')
-            h_code.putln("static PyObject* __PYX_WARN_IF_INIT_CALLED(PyObject* res) {")
-            h_code.putln("return res;")
-            h_code.putln("}")
+            h_code_main.putln('#endif')
+            h_code_main.putln("static PyObject* __PYX_WARN_IF_INIT_CALLED(PyObject* res) {")
+            h_code_main.putln("return res;")
+            h_code_main.putln("}")
             # Function call is converted to warning macro; uncalled (pointer) is not
@@ -267,3 +271,3 @@
             # Function call is converted to warning macro; uncalled (pointer) is not
-            h_code.putln('#define %s() __PYX_WARN_IF_INIT_CALLED(%s())' % (
+            h_code_main.putln('#define %s() __PYX_WARN_IF_INIT_CALLED(%s())' % (
                 py3_mod_func_name, py3_mod_func_name))
@@ -269,14 +273,12 @@
                 py3_mod_func_name, py3_mod_func_name))
-            h_code.putln('#endif')
-            h_code.putln('#endif')
-            h_code.putln("")
-            h_code.putln("#endif /* !%s */" % h_guard)
-
-            f = open_new_file(result.h_file)
-            try:
-                h_code.copyto(f)
-            finally:
-                f.close()
+            h_code_main.putln('#endif')
+            h_code_main.putln('#endif')
+
+            h_code_end.putln("")
+            h_code_end.putln("#endif /* !%s */" % h_guard)
+
+            with open_new_file(result.h_file) as f:
+                h_code_writer.copyto(f)
 
     def generate_public_declaration(self, entry, h_code, i_code):
         h_code.putln("%s %s;" % (
@@ -499,7 +501,7 @@
             except ImportError:
                 import xml.etree.ElementTree as ET
             coverage_xml = ET.parse(coverage_xml_filename).getroot()
-            for el in coverage_xml.getiterator():
+            for el in coverage_xml.iter():
                 el.tail = None  # save some memory
         else:
             coverage_xml = None
@@ -2745,10 +2747,10 @@
         if fail_compilation_in_py2:
             code.putln('#error "Unicode module names are not supported in Python 2";')
         if self.scope.is_package:
-            code.putln("#if !defined(CYTHON_NO_PYINIT_EXPORT) && (defined(WIN32) || defined(MS_WINDOWS))")
+            code.putln("#if !defined(CYTHON_NO_PYINIT_EXPORT) && (defined(_WIN32) || defined(WIN32) || defined(MS_WINDOWS))")
             code.putln("__Pyx_PyMODINIT_FUNC init__init__(void) { init%s(); }" % py2_mod_name)
             code.putln("#endif")
         code.putln(header2)
         code.putln("#else")
         code.putln("%s CYTHON_SMALL_CODE; /*proto*/" % header3)
         if self.scope.is_package:
@@ -2749,10 +2751,10 @@
             code.putln("__Pyx_PyMODINIT_FUNC init__init__(void) { init%s(); }" % py2_mod_name)
             code.putln("#endif")
         code.putln(header2)
         code.putln("#else")
         code.putln("%s CYTHON_SMALL_CODE; /*proto*/" % header3)
         if self.scope.is_package:
-            code.putln("#if !defined(CYTHON_NO_PYINIT_EXPORT) && (defined(WIN32) || defined(MS_WINDOWS))")
+            code.putln("#if !defined(CYTHON_NO_PYINIT_EXPORT) && (defined(_WIN32) || defined(WIN32) || defined(MS_WINDOWS))")
             code.putln("__Pyx_PyMODINIT_FUNC PyInit___init__(void) { return %s(); }" % (
                 self.mod_init_func_cname('PyInit', env)))
             code.putln("#endif")
diff --git a/Cython/Compiler/Nodes.py b/Cython/Compiler/Nodes.py
index cb011b016afcc3a3d59d9c4f1b3345bb2dbb205d_Q3l0aG9uL0NvbXBpbGVyL05vZGVzLnB5..3c2c33d638a8f5028602752643f0e6c26482bf14_Q3l0aG9uL0NvbXBpbGVyL05vZGVzLnB5 100644
--- a/Cython/Compiler/Nodes.py
+++ b/Cython/Compiler/Nodes.py
@@ -5,6 +5,7 @@
 from __future__ import absolute_import
 
 import cython
+
 cython.declare(sys=object, os=object, copy=object,
                Builtin=object, error=object, warning=object, Naming=object, PyrexTypes=object,
                py_object_type=object, ModuleScope=object, LocalScope=object, ClosureScope=object,
@@ -16,7 +17,7 @@
 from itertools import chain
 
 from . import Builtin
-from .Errors import error, warning, InternalError, CompileError
+from .Errors import error, warning, InternalError, CompileError, CannotSpecialize
 from . import Naming
 from . import PyrexTypes
 from . import TypeSlots
@@ -517,7 +518,12 @@
                 base_type = py_object_type
 
         if base_type.is_fused and env.fused_to_specific:
-            base_type = base_type.specialize(env.fused_to_specific)
+            try:
+                base_type = base_type.specialize(env.fused_to_specific)
+            except CannotSpecialize:
+                error(self.pos,
+                      "'%s' cannot be specialized since its type is not a fused argument to this function" %
+                      self.name)
 
         self.type = base_type
         return self, base_type
@@ -541,9 +547,7 @@
         return self.base.analyse(ptr_type, env, nonempty=nonempty, visibility=visibility, in_pxd=in_pxd)
 
 
-class CReferenceDeclaratorNode(CDeclaratorNode):
-    # base     CDeclaratorNode
-
+class _CReferenceDeclaratorBaseNode(CDeclaratorNode):
     child_attrs = ["base"]
 
     def declared_name(self):
@@ -552,6 +556,8 @@
     def analyse_templates(self):
         return self.base.analyse_templates()
 
+
+class CReferenceDeclaratorNode(_CReferenceDeclaratorBaseNode):
     def analyse(self, base_type, env, nonempty=0, visibility=None, in_pxd=False):
         if base_type.is_pyobject:
             error(self.pos, "Reference base type cannot be a Python object")
@@ -559,6 +565,14 @@
         return self.base.analyse(ref_type, env, nonempty=nonempty, visibility=visibility, in_pxd=in_pxd)
 
 
+class CppRvalueReferenceDeclaratorNode(_CReferenceDeclaratorBaseNode):
+    def analyse(self, base_type, env, nonempty=0, visibility=None, in_pxd=False):
+        if base_type.is_pyobject:
+            error(self.pos, "Rvalue-reference base type cannot be a Python object")
+        ref_type = PyrexTypes.cpp_rvalue_ref_type(base_type)
+        return self.base.analyse(ref_type, env, nonempty=nonempty, visibility=visibility, in_pxd=in_pxd)
+
+
 class CArrayDeclaratorNode(CDeclaratorNode):
     # base        CDeclaratorNode
     # dimension   ExprNode
@@ -773,6 +787,13 @@
                 error(self.pos, "cannot have both '%s' and '%s' "
                       "calling conventions" % (current, callspec))
             func_type.calling_convention = callspec
+
+        if func_type.return_type.is_rvalue_reference:
+            warning(self.pos, "Rvalue-reference as function return type not supported", 1)
+        for arg in func_type.args:
+            if arg.type.is_rvalue_reference and not arg.is_forwarding_reference():
+                warning(self.pos, "Rvalue-reference as function argument not supported", 1)
+
         return self.base.analyse(func_type, env, visibility=visibility, in_pxd=in_pxd)
 
     def declare_optional_arg_struct(self, func_type, env, fused_cname=None):
@@ -1206,7 +1227,12 @@
                 self.type = self.array_declarator.analyse(base_type, env)[1]
 
         if self.type.is_fused and env.fused_to_specific:
-            self.type = self.type.specialize(env.fused_to_specific)
+            try:
+                self.type = self.type.specialize(env.fused_to_specific)
+            except CannotSpecialize:
+                error(self.pos,
+                      "'%s' cannot be specialized since its type is not a fused argument to this function" %
+                      self.name)
 
         return self.type
 
@@ -1378,6 +1404,8 @@
                 return
             if type.is_reference and self.visibility != 'extern':
                 error(declarator.pos, "C++ references cannot be declared; use a pointer instead")
+            if type.is_rvalue_reference and self.visibility != 'extern':
+                error(declarator.pos, "C++ rvalue-references cannot be declared")
             if type.is_cfunction:
                 if 'staticmethod' in env.directives:
                     type.is_static_method = True
@@ -2264,7 +2292,7 @@
             error(arg.pos, "Argument type '%s' is incomplete" % arg.type)
         entry = env.declare_arg(arg.name, arg.type, arg.pos)
         if arg.annotation:
-            entry.annotation = arg.annotation.expr
+            entry.annotation = arg.annotation
         return entry
 
     def generate_arg_type_test(self, arg, code):
@@ -4866,6 +4894,7 @@
         if self.doc_node:
             self.doc_node.analyse_target_declaration(cenv)
         self.body.analyse_declarations(cenv)
+        self.class_result.analyse_annotations(cenv)
 
     def analyse_expressions(self, env):
         if self.bases:
diff --git a/Cython/Compiler/Optimize.py b/Cython/Compiler/Optimize.py
index cb011b016afcc3a3d59d9c4f1b3345bb2dbb205d_Q3l0aG9uL0NvbXBpbGVyL09wdGltaXplLnB5..3c2c33d638a8f5028602752643f0e6c26482bf14_Q3l0aG9uL0NvbXBpbGVyL09wdGltaXplLnB5 100644
--- a/Cython/Compiler/Optimize.py
+++ b/Cython/Compiler/Optimize.py
@@ -192,7 +192,7 @@
     def _optimise_for_loop(self, node, iterable, reversed=False):
         annotation_type = None
         if (iterable.is_name or iterable.is_attribute) and iterable.entry and iterable.entry.annotation:
-            annotation = iterable.entry.annotation
+            annotation = iterable.entry.annotation.expr
             if annotation.is_subscript:
                 annotation = annotation.base  # container base type
             # FIXME: generalise annotation evaluation => maybe provide a "qualified name" also for imported names?
diff --git a/Cython/Compiler/ParseTreeTransforms.pxd b/Cython/Compiler/ParseTreeTransforms.pxd
index cb011b016afcc3a3d59d9c4f1b3345bb2dbb205d_Q3l0aG9uL0NvbXBpbGVyL1BhcnNlVHJlZVRyYW5zZm9ybXMucHhk..3c2c33d638a8f5028602752643f0e6c26482bf14_Q3l0aG9uL0NvbXBpbGVyL1BhcnNlVHJlZVRyYW5zZm9ybXMucHhk 100644
--- a/Cython/Compiler/ParseTreeTransforms.pxd
+++ b/Cython/Compiler/ParseTreeTransforms.pxd
@@ -1,5 +1,4 @@
-
-from __future__ import absolute_import
+# cython: language_level=3
 
 cimport cython
 
diff --git a/Cython/Compiler/Parsing.pxd b/Cython/Compiler/Parsing.pxd
index cb011b016afcc3a3d59d9c4f1b3345bb2dbb205d_Q3l0aG9uL0NvbXBpbGVyL1BhcnNpbmcucHhk..3c2c33d638a8f5028602752643f0e6c26482bf14_Q3l0aG9uL0NvbXBpbGVyL1BhcnNpbmcucHhk 100644
--- a/Cython/Compiler/Parsing.pxd
+++ b/Cython/Compiler/Parsing.pxd
@@ -1,3 +1,5 @@
+# cython: language_level=3
+
 # We declare all of these here to type the first argument.
 
 from __future__ import absolute_import
@@ -24,7 +26,7 @@
 cdef p_test(PyrexScanner s)
 cdef p_test_nocond(PyrexScanner s)
 cdef p_or_test(PyrexScanner s)
-cdef p_rassoc_binop_expr(PyrexScanner s, ops, p_sub_expr_func p_subexpr)
+cdef p_rassoc_binop_expr(PyrexScanner s, unicode op, p_sub_expr_func p_subexpr)
 cdef p_and_test(PyrexScanner s)
 cdef p_not_test(PyrexScanner s)
 cdef p_comparison(PyrexScanner s)
diff --git a/Cython/Compiler/Parsing.py b/Cython/Compiler/Parsing.py
index cb011b016afcc3a3d59d9c4f1b3345bb2dbb205d_Q3l0aG9uL0NvbXBpbGVyL1BhcnNpbmcucHk=..3c2c33d638a8f5028602752643f0e6c26482bf14_Q3l0aG9uL0NvbXBpbGVyL1BhcnNpbmcucHk= 100644
--- a/Cython/Compiler/Parsing.py
+++ b/Cython/Compiler/Parsing.py
@@ -14,7 +14,7 @@
                Builtin=object, ModuleNode=object, Utils=object, _unicode=object, _bytes=object,
                re=object, sys=object, _parse_escape_sequences=object, _parse_escape_sequences_raw=object,
                partial=object, reduce=object, _IS_PY3=cython.bint, _IS_2BYTE_UNICODE=cython.bint,
-               _CDEF_MODIFIERS=tuple)
+               _CDEF_MODIFIERS=tuple, COMMON_BINOP_MISTAKES=dict)
 
 from io import StringIO
 import re
@@ -159,4 +159,6 @@
 
 #or_test: and_test ('or' and_test)*
 
+COMMON_BINOP_MISTAKES = {'||': 'or', '&&': 'and'}
+
 def p_or_test(s):
@@ -162,5 +164,5 @@
 def p_or_test(s):
-    return p_rassoc_binop_expr(s, ('or',), p_and_test)
-
-def p_rassoc_binop_expr(s, ops, p_subexpr):
+    return p_rassoc_binop_expr(s, u'or', p_and_test)
+
+def p_rassoc_binop_expr(s, op, p_subexpr):
     n1 = p_subexpr(s)
@@ -166,5 +168,5 @@
     n1 = p_subexpr(s)
-    if s.sy in ops:
+    if s.sy == op:
         pos = s.position()
         op = s.sy
         s.next()
@@ -168,5 +170,5 @@
         pos = s.position()
         op = s.sy
         s.next()
-        n2 = p_rassoc_binop_expr(s, ops, p_subexpr)
+        n2 = p_rassoc_binop_expr(s, op, p_subexpr)
         n1 = ExprNodes.binop_node(pos, op, n1, n2)
@@ -172,7 +174,12 @@
         n1 = ExprNodes.binop_node(pos, op, n1, n2)
+    elif s.sy in COMMON_BINOP_MISTAKES and COMMON_BINOP_MISTAKES[s.sy] == op:
+        # Only report this for the current operator since we pass through here twice for 'and' and 'or'.
+        warning(s.position(),
+                "Found the C operator '%s', did you mean the Python operator '%s'?" % (s.sy, op),
+                level=1)
     return n1
 
 #and_test: not_test ('and' not_test)*
 
 def p_and_test(s):
     #return p_binop_expr(s, ('and',), p_not_test)
@@ -173,10 +180,10 @@
     return n1
 
 #and_test: not_test ('and' not_test)*
 
 def p_and_test(s):
     #return p_binop_expr(s, ('and',), p_not_test)
-    return p_rassoc_binop_expr(s, ('and',), p_not_test)
+    return p_rassoc_binop_expr(s, u'and', p_not_test)
 
 #not_test: 'not' not_test | comparison
 
@@ -2334,7 +2341,7 @@
                         return p_async_statement(s, ctx, decorators)
                     elif decorators:
                         s.error("Decorators can only be followed by functions or classes")
-                    s.put_back('IDENT', ident_name)  # re-insert original token
+                    s.put_back(u'IDENT', ident_name)  # re-insert original token
                 return p_simple_statement_list(s, ctx, first_statement=first_statement)
 
 
@@ -2556,5 +2563,5 @@
                 s.next()
                 if (s.sy == '*' or s.sy == '**' or s.sy == '&'
                         or (s.sy == 'IDENT' and s.systring in calling_convention_words)):
-                    s.put_back('(', '(')
+                    s.put_back(u'(', u'(')
                 else:
@@ -2560,5 +2567,5 @@
                 else:
-                    s.put_back('(', '(')
-                    s.put_back('IDENT', name)
+                    s.put_back(u'(', u'(')
+                    s.put_back(u'IDENT', name)
                     name = None
             elif s.sy not in ('*', '**', '[', '&'):
@@ -2563,6 +2570,6 @@
                     name = None
             elif s.sy not in ('*', '**', '[', '&'):
-                s.put_back('IDENT', name)
+                s.put_back(u'IDENT', name)
                 name = None
 
     type_node = Nodes.CSimpleBaseTypeNode(pos,
@@ -2703,10 +2710,10 @@
 
         dotted_path.reverse()
         for p in dotted_path:
-            s.put_back('IDENT', p)
-            s.put_back('.', '.')
-
-        s.put_back('IDENT', name)
+            s.put_back(u'IDENT', p)
+            s.put_back(u'.', u'.')
+
+        s.put_back(u'IDENT', name)
         return not is_type and saved[0]
     else:
         return True
@@ -2720,7 +2727,7 @@
         name = s.systring
         s.next()
         result = s.sy == '.'
-        s.put_back('IDENT', name)
+        s.put_back(u'IDENT', name)
         return result
     else:
         return 0
@@ -2858,5 +2865,7 @@
                           assignable, nonempty):
     pos = s.position()
     calling_convention = p_calling_convention(s)
-    if s.sy == '*':
+    if s.sy in ('*', '**'):
+        # scanner returns '**' as a single token
+        is_ptrptr = s.sy == '**'
         s.next()
@@ -2862,4 +2871,6 @@
         s.next()
-        if s.systring == 'const':
-            const_pos = s.position()
+
+        const_pos = s.position()
+        is_const = s.systring == 'const' and s.sy == 'IDENT'
+        if is_const:
             s.next()
@@ -2865,15 +2876,13 @@
             s.next()
-            const_base = p_c_declarator(s, ctx, empty = empty,
-                                       is_type = is_type,
-                                       cmethod_flag = cmethod_flag,
-                                       assignable = assignable,
-                                       nonempty = nonempty)
-            base = Nodes.CConstDeclaratorNode(const_pos, base = const_base)
-        else:
-            base = p_c_declarator(s, ctx, empty = empty, is_type = is_type,
-                                  cmethod_flag = cmethod_flag,
-                                  assignable = assignable, nonempty = nonempty)
-        result = Nodes.CPtrDeclaratorNode(pos,
-            base = base)
-    elif s.sy == '**':  # scanner returns this as a single token
+
+        base = p_c_declarator(s, ctx, empty=empty, is_type=is_type,
+                              cmethod_flag=cmethod_flag,
+                              assignable=assignable, nonempty=nonempty)
+        if is_const:
+            base = Nodes.CConstDeclaratorNode(const_pos, base=base)
+        if is_ptrptr:
+            base = Nodes.CPtrDeclaratorNode(pos, base=base)
+        result = Nodes.CPtrDeclaratorNode(pos, base=base)
+    elif s.sy == '&' or (s.sy == '&&' and s.context.cpp):
+        node_class = Nodes.CppRvalueReferenceDeclaratorNode if s.sy == '&&' else Nodes.CReferenceDeclaratorNode
         s.next()
@@ -2879,16 +2888,8 @@
         s.next()
-        base = p_c_declarator(s, ctx, empty = empty, is_type = is_type,
-                              cmethod_flag = cmethod_flag,
-                              assignable = assignable, nonempty = nonempty)
-        result = Nodes.CPtrDeclaratorNode(pos,
-            base = Nodes.CPtrDeclaratorNode(pos,
-                base = base))
-    elif s.sy == '&':
-        s.next()
-        base = p_c_declarator(s, ctx, empty = empty, is_type = is_type,
-                              cmethod_flag = cmethod_flag,
-                              assignable = assignable, nonempty = nonempty)
-        result = Nodes.CReferenceDeclaratorNode(pos, base = base)
+        base = p_c_declarator(s, ctx, empty=empty, is_type=is_type,
+                              cmethod_flag=cmethod_flag,
+                              assignable=assignable, nonempty=nonempty)
+        result = node_class(pos, base=base)
     else:
         rhs = None
         if s.sy == 'IDENT':
diff --git a/Cython/Compiler/PyrexTypes.py b/Cython/Compiler/PyrexTypes.py
index cb011b016afcc3a3d59d9c4f1b3345bb2dbb205d_Q3l0aG9uL0NvbXBpbGVyL1B5cmV4VHlwZXMucHk=..3c2c33d638a8f5028602752643f0e6c26482bf14_Q3l0aG9uL0NvbXBpbGVyL1B5cmV4VHlwZXMucHk= 100644
--- a/Cython/Compiler/PyrexTypes.py
+++ b/Cython/Compiler/PyrexTypes.py
@@ -5,9 +5,10 @@
 from __future__ import absolute_import
 
 import copy
+import hashlib
 import re
 
 try:
     reduce
 except NameError:
     from functools import reduce
@@ -8,12 +9,13 @@
 import re
 
 try:
     reduce
 except NameError:
     from functools import reduce
+from functools import partial
 
 from Cython.Utils import cached_function
 from .Code import UtilityCode, LazyUtilityCode, TempitaUtilityCode
 from . import StringEncoding
 from . import Naming
 
@@ -14,10 +16,10 @@
 
 from Cython.Utils import cached_function
 from .Code import UtilityCode, LazyUtilityCode, TempitaUtilityCode
 from . import StringEncoding
 from . import Naming
 
-from .Errors import error, warning
+from .Errors import error, warning, CannotSpecialize
 
 
 class BaseType(object):
@@ -45,7 +47,9 @@
     def cast_code(self, expr_code):
         return "((%s)%s)" % (self.empty_declaration_code(), expr_code)
 
-    def empty_declaration_code(self):
+    def empty_declaration_code(self, pyrex=False):
+        if pyrex:
+            return self.declaration_code('', pyrex=True)
         if self._empty_declaration is None:
             self._empty_declaration = self.declaration_code('')
         return self._empty_declaration
@@ -175,6 +179,7 @@
     #  is_ptr                boolean     Is a C pointer type
     #  is_null_ptr           boolean     Is the type of NULL
     #  is_reference          boolean     Is a C reference type
+    #  is_rvalue_reference   boolean     Is a C++ rvalue reference type
     #  is_const              boolean     Is a C const type
     #  is_volatile           boolean     Is a C volatile type
     #  is_cv_qualified       boolean     Is a C const or volatile type
@@ -241,6 +246,7 @@
     is_ptr = 0
     is_null_ptr = 0
     is_reference = 0
+    is_rvalue_reference = 0
     is_const = 0
     is_volatile = 0
     is_cv_qualified = 0
@@ -273,7 +279,8 @@
         return self
 
     def specialize(self, values):
-        # TODO(danilo): Override wherever it makes sense.
+        # Returns the concrete type if this is a fused type, or otherwise the type itself.
+        # May raise Errors.CannotSpecialize on failure
         return self
 
     def literal_code(self, value):
@@ -695,7 +702,6 @@
     def declaration_code(self, entity_code,
             for_display = 0, dll_linkage = None, pyrex = 0):
         # XXX: we put these guards in for now...
-        assert not pyrex
         assert not dll_linkage
         from . import MemoryView
         base_code = StringEncoding.EncodedString(
@@ -699,7 +705,7 @@
         assert not dll_linkage
         from . import MemoryView
         base_code = StringEncoding.EncodedString(
-                        (str(self)) if for_display else MemoryView.memviewslice_cname)
+            str(self) if pyrex or for_display else MemoryView.memviewslice_cname)
         return self.base_declaration_code(
                 base_code,
                 entity_code)
@@ -1827,7 +1833,10 @@
         return 'FusedType(name=%r)' % self.name
 
     def specialize(self, values):
-        return values[self]
+        if self in values:
+            return values[self]
+        else:
+            raise CannotSpecialize()
 
     def get_fused_types(self, result=None, seen=None):
         if result is None:
@@ -2747,8 +2756,7 @@
     is_null_ptr = 1
 
 
-class CReferenceType(BaseType):
-
-    is_reference = 1
+class CReferenceBaseType(BaseType):
+
     is_fake_reference = 0
 
@@ -2753,6 +2761,8 @@
     is_fake_reference = 0
 
+    # Common base type for C reference and C++ rvalue reference types.
+
     def __init__(self, base_type):
         self.ref_base_type = base_type
 
     def __repr__(self):
@@ -2755,18 +2765,8 @@
     def __init__(self, base_type):
         self.ref_base_type = base_type
 
     def __repr__(self):
-        return "<CReferenceType %s>" % repr(self.ref_base_type)
-
-    def __str__(self):
-        return "%s &" % self.ref_base_type
-
-    def declaration_code(self, entity_code,
-            for_display = 0, dll_linkage = None, pyrex = 0):
-        #print "CReferenceType.declaration_code: pointer to", self.base_type ###
-        return self.ref_base_type.declaration_code(
-            "&%s" % entity_code,
-            for_display, dll_linkage, pyrex)
+        return "<%s %s>" % repr(self.__class__.__name__, self.ref_base_type)
 
     def specialize(self, values):
         base_type = self.ref_base_type.specialize(values)
@@ -2782,7 +2782,22 @@
         return getattr(self.ref_base_type, name)
 
 
+class CReferenceType(CReferenceBaseType):
+
+    is_reference = 1
+
+    def __str__(self):
+        return "%s &" % self.ref_base_type
+
+    def declaration_code(self, entity_code,
+            for_display = 0, dll_linkage = None, pyrex = 0):
+        #print "CReferenceType.declaration_code: pointer to", self.base_type ###
+        return self.ref_base_type.declaration_code(
+            "&%s" % entity_code,
+            for_display, dll_linkage, pyrex)
+
+
 class CFakeReferenceType(CReferenceType):
 
     is_fake_reference = 1
 
@@ -2785,10 +2800,7 @@
 class CFakeReferenceType(CReferenceType):
 
     is_fake_reference = 1
 
-    def __repr__(self):
-        return "<CFakeReferenceType %s>" % repr(self.ref_base_type)
-
     def __str__(self):
         return "%s [&]" % self.ref_base_type
 
@@ -2798,6 +2810,20 @@
         return "__Pyx_FakeReference<%s> %s" % (self.ref_base_type.empty_declaration_code(), entity_code)
 
 
+class CppRvalueReferenceType(CReferenceBaseType):
+
+    is_rvalue_reference = 1
+
+    def __str__(self):
+        return "%s &&" % self.ref_base_type
+
+    def declaration_code(self, entity_code,
+            for_display = 0, dll_linkage = None, pyrex = 0):
+        return self.ref_base_type.declaration_code(
+            "&&%s" % entity_code,
+            for_display, dll_linkage, pyrex)
+
+
 class CFuncType(CType):
     #  return_type      CType
     #  args             [CFuncTypeArg]
@@ -3226,8 +3252,7 @@
         if not self.can_coerce_to_pyobject(env):
             return False
         from .UtilityCode import CythonUtilityCode
-        safe_typename = re.sub('[^a-zA-Z0-9]', '__', self.declaration_code("", pyrex=1))
-        to_py_function = "__Pyx_CFunc_%s_to_py" % safe_typename
+        to_py_function = "__Pyx_CFunc_%s_to_py" % type_identifier(self, pyrex=True)
 
         for arg in self.args:
             if not arg.type.is_pyobject and not arg.type.create_from_py_utility_code(env):
@@ -3430,6 +3455,12 @@
     def specialize(self, values):
         return CFuncTypeArg(self.name, self.type.specialize(values), self.pos, self.cname)
 
+    def is_forwarding_reference(self):
+        if self.type.is_rvalue_reference:
+            if (isinstance(self.type.ref_base_type, TemplatePlaceholderType)
+                    and not self.type.ref_base_type.is_cv_qualified):
+                return True
+        return False
 
 class ToPyStructUtilityCode(object):
 
@@ -4901,5 +4932,11 @@
             name = 'int'
     return simple_c_type(signed, longness, name)
 
+
+def _construct_type_from_base(cls, base_type, *args):
+    if base_type is error_type:
+        return error_type
+    return cls(base_type, *args)
+
 def c_array_type(base_type, size):
     # Construct a C array type.
@@ -4904,9 +4941,6 @@
 def c_array_type(base_type, size):
     # Construct a C array type.
-    if base_type is error_type:
-        return error_type
-    else:
-        return CArrayType(base_type, size)
+    return _construct_type_from_base(CArrayType, base_type, size)
 
 def c_ptr_type(base_type):
     # Construct a C pointer type.
@@ -4910,12 +4944,9 @@
 
 def c_ptr_type(base_type):
     # Construct a C pointer type.
-    if base_type is error_type:
-        return error_type
-    elif base_type.is_reference:
-        return CPtrType(base_type.ref_base_type)
-    else:
-        return CPtrType(base_type)
+    if base_type.is_reference:
+        base_type = base_type.ref_base_type
+    return _construct_type_from_base(CPtrType, base_type)
 
 def c_ref_type(base_type):
     # Construct a C reference type
@@ -4919,10 +4950,11 @@
 
 def c_ref_type(base_type):
     # Construct a C reference type
-    if base_type is error_type:
-        return error_type
-    else:
-        return CReferenceType(base_type)
+    return _construct_type_from_base(CReferenceType, base_type)
+
+def cpp_rvalue_ref_type(base_type):
+    # Construct a C++ rvalue reference type
+    return _construct_type_from_base(CppRvalueReferenceType, base_type)
 
 def c_const_type(base_type):
     # Construct a C const type.
@@ -4926,10 +4958,7 @@
 
 def c_const_type(base_type):
     # Construct a C const type.
-    if base_type is error_type:
-        return error_type
-    else:
-        return CConstType(base_type)
+    return _construct_type_from_base(CConstType, base_type)
 
 def c_const_or_volatile_type(base_type, is_const, is_volatile):
     # Construct a C const/volatile type.
@@ -4933,10 +4962,8 @@
 
 def c_const_or_volatile_type(base_type, is_const, is_volatile):
     # Construct a C const/volatile type.
-    if base_type is error_type:
-        return error_type
-    else:
-        return CConstOrVolatileType(base_type, is_const, is_volatile)
+    return _construct_type_from_base(CConstOrVolatileType, base_type, is_const, is_volatile)
+
 
 def same_type(type1, type2):
     return type1.same_as(type2)
@@ -4962,4 +4989,32 @@
 def type_list_identifier(types):
     return cap_length('__and_'.join(type_identifier(type) for type in types))
 
+_special_type_characters = {
+    '__': '__dunder',
+    'const ': '__const_',
+    ' ': '__space_',
+    '*': '__ptr',
+    '&': '__ref',
+    '&&': '__fwref',
+    '[': '__lArr',
+    ']': '__rArr',
+    '<': '__lAng',
+    '>': '__rAng',
+    '(': '__lParen',
+    ')': '__rParen',
+    ',': '__comma_',
+    '...': '__EL',
+    '::': '__in_',
+    ':': '__D',
+}
+
+_escape_special_type_characters = partial(re.compile(
+    # join substrings in reverse order to put longer matches first, e.g. "::" before ":"
+    " ?(%s) ?" % "|".join(re.escape(s) for s in sorted(_special_type_characters, reverse=True))
+).sub, lambda match: _special_type_characters[match.group(1)])
+
+def type_identifier(type, pyrex=False):
+    decl = type.empty_declaration_code(pyrex=pyrex)
+    return type_identifier_from_declaration(decl)
+
 _type_identifier_cache = {}
@@ -4965,7 +5020,6 @@
 _type_identifier_cache = {}
-def type_identifier(type):
-    decl = type.empty_declaration_code()
+def type_identifier_from_declaration(decl):
     safe = _type_identifier_cache.get(decl)
     if safe is None:
         safe = decl
         safe = re.sub(' +', ' ', safe)
@@ -4968,22 +5022,9 @@
     safe = _type_identifier_cache.get(decl)
     if safe is None:
         safe = decl
         safe = re.sub(' +', ' ', safe)
-        safe = re.sub(' ([^a-zA-Z0-9_])', r'\1', safe)
-        safe = re.sub('([^a-zA-Z0-9_]) ', r'\1', safe)
-        safe = (safe.replace('__', '__dunder')
-                    .replace('const ', '__const_')
-                    .replace(' ', '__space_')
-                    .replace('*', '__ptr')
-                    .replace('&', '__ref')
-                    .replace('[', '__lArr')
-                    .replace(']', '__rArr')
-                    .replace('<', '__lAng')
-                    .replace('>', '__rAng')
-                    .replace('(', '__lParen')
-                    .replace(')', '__rParen')
-                    .replace(',', '__comma_')
-                    .replace('::', '__in_'))
+        safe = re.sub(' ?([^a-zA-Z0-9_]) ?', r'\1', safe)
+        safe = _escape_special_type_characters(safe)
         safe = cap_length(re.sub('[^a-zA-Z0-9_]', lambda x: '__%X' % ord(x.group(0)), safe))
         _type_identifier_cache[decl] = safe
     return safe
@@ -4991,5 +5032,5 @@
 def cap_length(s, max_prefix=63, max_len=1024):
     if len(s) <= max_prefix:
         return s
-    else:
-        return '%x__%s__etc' % (abs(hash(s)) % (1<<20), s[:max_len-17])
+    hash_prefix = hashlib.sha256(s.encode('ascii')).hexdigest()[:6]
+    return '%s__%s__etc' % (hash_prefix, s[:max_len-17])
diff --git a/Cython/Compiler/Scanning.pxd b/Cython/Compiler/Scanning.pxd
index cb011b016afcc3a3d59d9c4f1b3345bb2dbb205d_Q3l0aG9uL0NvbXBpbGVyL1NjYW5uaW5nLnB4ZA==..3c2c33d638a8f5028602752643f0e6c26482bf14_Q3l0aG9uL0NvbXBpbGVyL1NjYW5uaW5nLnB4ZA== 100644
--- a/Cython/Compiler/Scanning.pxd
+++ b/Cython/Compiler/Scanning.pxd
@@ -1,4 +1,4 @@
-from __future__ import absolute_import
+# cython: language_level=3
 
 import cython
 
@@ -34,8 +34,8 @@
     cdef public indentation_char
     cdef public int bracket_nesting_level
     cdef readonly bint async_enabled
-    cdef public sy
-    cdef public systring
+    cdef public unicode sy
+    cdef public systring  # EncodedString
 
     cdef long current_level(self)
     #cpdef commentline(self, text)
diff --git a/Cython/Compiler/Tests/TestTypes.py b/Cython/Compiler/Tests/TestTypes.py
index cb011b016afcc3a3d59d9c4f1b3345bb2dbb205d_Q3l0aG9uL0NvbXBpbGVyL1Rlc3RzL1Rlc3RUeXBlcy5weQ==..3c2c33d638a8f5028602752643f0e6c26482bf14_Q3l0aG9uL0NvbXBpbGVyL1Rlc3RzL1Rlc3RUeXBlcy5weQ== 100644
--- a/Cython/Compiler/Tests/TestTypes.py
+++ b/Cython/Compiler/Tests/TestTypes.py
@@ -17,3 +17,59 @@
 
         cenum = PT.CEnumType("E", "cenum", typedef_flag=False)
         assert_widest(PT.c_int_type, cenum, PT.c_int_type)
+
+
+class TestTypeIdentifiers(unittest.TestCase):
+
+    TEST_DATA = [
+        ("char*", "char__ptr"),
+        ("char *", "char__ptr"),
+        ("char **", "char__ptr__ptr"),
+        ("_typedef", "_typedef"),
+        ("__typedef", "__dundertypedef"),
+        ("___typedef", "__dunder_typedef"),
+        ("____typedef", "__dunder__dundertypedef"),
+        ("_____typedef", "__dunder__dunder_typedef"),
+        ("const __typedef", "__const___dundertypedef"),
+        ("int[42]", "int__lArr42__rArr"),
+        ("int[:]", "int__lArr__D__rArr"),
+        ("int[:,:]", "int__lArr__D__comma___D__rArr"),
+        ("int[:,:,:]", "int__lArr__D__comma___D__comma___D__rArr"),
+        ("int[:,:,...]", "int__lArr__D__comma___D__comma___EL__rArr"),
+        ("std::vector", "std__in_vector"),
+        ("std::vector&&", "std__in_vector__fwref"),
+        ("const std::vector", "__const_std__in_vector"),
+        ("const std::vector&", "__const_std__in_vector__ref"),
+        ("const_std", "const_std"),
+    ]
+
+    def test_escape_special_type_characters(self):
+        test_func = PT._escape_special_type_characters  # keep test usage visible for IDEs
+        function_name = "_escape_special_type_characters"
+        self._test_escape(function_name)
+
+    def test_type_identifier_for_declaration(self):
+        test_func = PT.type_identifier_from_declaration  # keep test usage visible for IDEs
+        function_name = test_func.__name__
+        self._test_escape(function_name)
+
+        # differences due to whitespace removal
+        test_data = [
+            ("const &std::vector", "const__refstd__in_vector"),
+            ("const &std::vector<int>", "const__refstd__in_vector__lAngint__rAng"),
+            ("const &&std::vector", "const__fwrefstd__in_vector"),
+            ("const &&&std::vector", "const__fwref__refstd__in_vector"),
+            ("const &&std::vector", "const__fwrefstd__in_vector"),
+            ("void (*func)(int x, float y)",
+             "975d51__void__lParen__ptrfunc__rParen__lParenint__space_x__comma_float__space_y__rParen__etc"),
+            ("float ** (*func)(int x, int[:] y)",
+             "31883a__float__ptr__ptr__lParen__ptrfunc__rParen__lParenint__space_x__comma_int__lArr__D__rArry__rParen__etc"),
+        ]
+        self._test_escape(function_name, test_data)
+
+    def _test_escape(self, func_name, test_data=TEST_DATA):
+        escape = getattr(PT, func_name)
+        for declaration, expected in test_data:
+            escaped_value = escape(declaration)
+            self.assertEqual(escaped_value, expected, "%s('%s') == '%s' != '%s'" % (
+                func_name, declaration, escaped_value, expected))
diff --git a/Cython/Compiler/Visitor.pxd b/Cython/Compiler/Visitor.pxd
index cb011b016afcc3a3d59d9c4f1b3345bb2dbb205d_Q3l0aG9uL0NvbXBpbGVyL1Zpc2l0b3IucHhk..3c2c33d638a8f5028602752643f0e6c26482bf14_Q3l0aG9uL0NvbXBpbGVyL1Zpc2l0b3IucHhk 100644
--- a/Cython/Compiler/Visitor.pxd
+++ b/Cython/Compiler/Visitor.pxd
@@ -1,4 +1,4 @@
-from __future__ import absolute_import
+# cython: language_level=3
 
 cimport cython
 
diff --git a/Cython/Plex/Actions.pxd b/Cython/Plex/Actions.pxd
index cb011b016afcc3a3d59d9c4f1b3345bb2dbb205d_Q3l0aG9uL1BsZXgvQWN0aW9ucy5weGQ=..3c2c33d638a8f5028602752643f0e6c26482bf14_Q3l0aG9uL1BsZXgvQWN0aW9ucy5weGQ= 100644
--- a/Cython/Plex/Actions.pxd
+++ b/Cython/Plex/Actions.pxd
@@ -2,8 +2,7 @@
 
 cdef class Action:
     cdef perform(self, token_stream, text)
-    cpdef same_as(self, other)
 
 cdef class Return(Action):
     cdef object value
     cdef perform(self, token_stream, text)
@@ -6,9 +5,8 @@
 
 cdef class Return(Action):
     cdef object value
     cdef perform(self, token_stream, text)
-    cpdef same_as(self, other)
 
 cdef class Call(Action):
     cdef object function
     cdef perform(self, token_stream, text)
@@ -11,8 +9,7 @@
 
 cdef class Call(Action):
     cdef object function
     cdef perform(self, token_stream, text)
-    cpdef same_as(self, other)
 
 cdef class Method(Action):
     cdef str name
@@ -21,7 +18,6 @@
 cdef class Begin(Action):
     cdef object state_name
     cdef perform(self, token_stream, text)
-    cpdef same_as(self, other)
 
 cdef class Ignore(Action):
     cdef perform(self, token_stream, text)
diff --git a/Cython/Plex/Actions.py b/Cython/Plex/Actions.py
index cb011b016afcc3a3d59d9c4f1b3345bb2dbb205d_Q3l0aG9uL1BsZXgvQWN0aW9ucy5weQ==..3c2c33d638a8f5028602752643f0e6c26482bf14_Q3l0aG9uL1BsZXgvQWN0aW9ucy5weQ== 100644
--- a/Cython/Plex/Actions.py
+++ b/Cython/Plex/Actions.py
@@ -6,8 +6,7 @@
 Actions for use in token specifications
 """
 
-
 class Action(object):
     def perform(self, token_stream, text):
         pass  # abstract
 
@@ -10,10 +9,7 @@
 class Action(object):
     def perform(self, token_stream, text):
         pass  # abstract
 
-    def same_as(self, other):
-        return self is other
-
     def __copy__(self):
         return self  # immutable, no need to copy
 
@@ -33,9 +29,6 @@
     def perform(self, token_stream, text):
         return self.value
 
-    def same_as(self, other):
-        return isinstance(other, Return) and self.value == other.value
-
     def __repr__(self):
         return "Return(%r)" % self.value
 
@@ -54,9 +47,6 @@
     def __repr__(self):
         return "Call(%s)" % self.function.__name__
 
-    def same_as(self, other):
-        return isinstance(other, Call) and self.function is other.function
-
 
 class Method(Action):
     """
@@ -79,9 +69,6 @@
             if self.kwargs is not None else '')
         return "Method(%s%s%s)" % (self.name, ', ' if kwargs else '', kwargs)
 
-    def same_as(self, other):
-        return isinstance(other, Method) and self.name == other.name and self.kwargs == other.kwargs
-
 
 class Begin(Action):
     """
@@ -99,9 +86,6 @@
     def __repr__(self):
         return "Begin(%s)" % self.state_name
 
-    def same_as(self, other):
-        return isinstance(other, Begin) and self.state_name == other.state_name
-
 
 class Ignore(Action):
     """
diff --git a/Cython/Plex/Machines.py b/Cython/Plex/Machines.py
index cb011b016afcc3a3d59d9c4f1b3345bb2dbb205d_Q3l0aG9uL1BsZXgvTWFjaGluZXMucHk=..3c2c33d638a8f5028602752643f0e6c26482bf14_Q3l0aG9uL1BsZXgvTWFjaGluZXMucHk= 100644
--- a/Cython/Plex/Machines.py
+++ b/Cython/Plex/Machines.py
@@ -121,7 +121,8 @@
         return self.number < other.number
 
     def __hash__(self):
-        return id(self)
+        # Prevent overflowing hash values due to arbitrarily large unsigned addresses.
+        return id(self) & maxint
 
 
 class FastMachine(object):
diff --git a/Cython/Utility/CythonFunction.c b/Cython/Utility/CythonFunction.c
index cb011b016afcc3a3d59d9c4f1b3345bb2dbb205d_Q3l0aG9uL1V0aWxpdHkvQ3l0aG9uRnVuY3Rpb24uYw==..3c2c33d638a8f5028602752643f0e6c26482bf14_Q3l0aG9uL1V0aWxpdHkvQ3l0aG9uRnVuY3Rpb24uYw== 100644
--- a/Cython/Utility/CythonFunction.c
+++ b/Cython/Utility/CythonFunction.c
@@ -397,6 +397,7 @@
 
 static PyObject *
 __Pyx_CyFunction_get_is_coroutine(__pyx_CyFunctionObject *op, CYTHON_UNUSED void *context) {
+    int is_coroutine;
     if (op->func_is_coroutine)
         return __Pyx_NewRef(op->func_is_coroutine);
 
@@ -400,8 +401,7 @@
     if (op->func_is_coroutine)
         return __Pyx_NewRef(op->func_is_coroutine);
 
-    int is_coroutine = op->flags & __Pyx_CYFUNCTION_COROUTINE;
-
+    is_coroutine = op->flags & __Pyx_CYFUNCTION_COROUTINE;
 #if PY_VERSION_HEX >= 0x03050000
     if (is_coroutine) {
         PyObject *module, *fromlist, *marker = PYIDENT("_is_coroutine");
diff --git a/Cython/Utility/Embed.c b/Cython/Utility/Embed.c
index cb011b016afcc3a3d59d9c4f1b3345bb2dbb205d_Q3l0aG9uL1V0aWxpdHkvRW1iZWQuYw==..3c2c33d638a8f5028602752643f0e6c26482bf14_Q3l0aG9uL1V0aWxpdHkvRW1iZWQuYw== 100644
--- a/Cython/Utility/Embed.c
+++ b/Cython/Utility/Embed.c
@@ -6,7 +6,7 @@
 
 #if PY_MAJOR_VERSION < 3
 int %(main_method)s(int argc, char** argv) {
-#elif defined(WIN32) || defined(MS_WINDOWS)
+#elif defined(_WIN32) || defined(WIN32) || defined(MS_WINDOWS)
 int %(wmain_method)s(int argc, wchar_t **argv) {
 #else
 static int __Pyx_main(int argc, wchar_t **argv) {
@@ -49,4 +49,5 @@
       }
       Py_XDECREF(m);
     }
+#if PY_VERSION_HEX < 0x03060000
     Py_Finalize();
@@ -52,5 +53,9 @@
     Py_Finalize();
+#else
+    if (Py_FinalizeEx() < 0)
+        return 2;
+#endif
     return 0;
 }
 
 
@@ -53,8 +58,8 @@
     return 0;
 }
 
 
-#if PY_MAJOR_VERSION >= 3 && !defined(WIN32) && !defined(MS_WINDOWS)
+#if PY_MAJOR_VERSION >= 3 && !defined(_WIN32) && !defined(WIN32) && !defined(MS_WINDOWS)
 #include <locale.h>
 
 #if PY_VERSION_HEX < 0x03050000
@@ -200,4 +205,5 @@
         if (res == 0)
             res = __Pyx_main(argc, argv_copy);
         for (i = 0; i < argc; i++) {
+#if PY_VERSION_HEX < 0x03050000
             free(argv_copy2[i]);
@@ -203,4 +209,7 @@
             free(argv_copy2[i]);
+#else
+            PyMem_RawFree(argv_copy2[i]);
+#endif
         }
         free(argv_copy);
         free(argv_copy2);
diff --git a/Cython/Utility/MemoryView.pyx b/Cython/Utility/MemoryView.pyx
index cb011b016afcc3a3d59d9c4f1b3345bb2dbb205d_Q3l0aG9uL1V0aWxpdHkvTWVtb3J5Vmlldy5weXg=..3c2c33d638a8f5028602752643f0e6c26482bf14_Q3l0aG9uL1V0aWxpdHkvTWVtb3J5Vmlldy5weXg= 100644
--- a/Cython/Utility/MemoryView.pyx
+++ b/Cython/Utility/MemoryView.pyx
@@ -1471,7 +1471,8 @@
     cdef Py_ssize_t i
 
     if type.typegroup == 'S':
-        assert type.fields != NULL and type.fields.type != NULL
+        assert type.fields != NULL
+        assert type.fields.type != NULL
 
         if type.flags & __PYX_BUF_FLAGS_PACKED_STRUCT:
             alignment = b'^'
diff --git a/Cython/Utility/ModuleSetupCode.c b/Cython/Utility/ModuleSetupCode.c
index cb011b016afcc3a3d59d9c4f1b3345bb2dbb205d_Q3l0aG9uL1V0aWxpdHkvTW9kdWxlU2V0dXBDb2RlLmM=..3c2c33d638a8f5028602752643f0e6c26482bf14_Q3l0aG9uL1V0aWxpdHkvTW9kdWxlU2V0dXBDb2RlLmM= 100644
--- a/Cython/Utility/ModuleSetupCode.c
+++ b/Cython/Utility/ModuleSetupCode.c
@@ -18,7 +18,7 @@
   #define offsetof(type, member) ( (size_t) & ((type*)0) -> member )
 #endif
 
-#if !defined(WIN32) && !defined(MS_WINDOWS)
+#if !defined(_WIN32) && !defined(WIN32) && !defined(MS_WINDOWS)
   #ifndef __stdcall
     #define __stdcall
   #endif
@@ -1160,7 +1160,7 @@
 
 /////////////// MathInitCode ///////////////
 
-#if defined(WIN32) || defined(MS_WINDOWS)
+#if defined(_WIN32) || defined(WIN32) || defined(MS_WINDOWS)
   #define _USE_MATH_DEFINES
 #endif
 #include <math.h>
@@ -1479,6 +1479,6 @@
   #define __Pyx_RefNannySetupContext(name, acquire_gil) \
           if (acquire_gil) { \
               PyGILState_STATE __pyx_gilstate_save = PyGILState_Ensure(); \
-              __pyx_refnanny = __Pyx_RefNanny->SetupContext((name), __LINE__, __FILE__); \
+              __pyx_refnanny = __Pyx_RefNanny->SetupContext((name), (__LINE__), (__FILE__)); \
               PyGILState_Release(__pyx_gilstate_save); \
           } else { \
@@ -1483,6 +1483,6 @@
               PyGILState_Release(__pyx_gilstate_save); \
           } else { \
-              __pyx_refnanny = __Pyx_RefNanny->SetupContext((name), __LINE__, __FILE__); \
+              __pyx_refnanny = __Pyx_RefNanny->SetupContext((name), (__LINE__), (__FILE__)); \
           }
   #define __Pyx_RefNannyFinishContextNogil() { \
               PyGILState_STATE __pyx_gilstate_save = PyGILState_Ensure(); \
@@ -1491,8 +1491,8 @@
           }
 #else
   #define __Pyx_RefNannySetupContext(name, acquire_gil) \
-          __pyx_refnanny = __Pyx_RefNanny->SetupContext((name), __LINE__, __FILE__)
+          __pyx_refnanny = __Pyx_RefNanny->SetupContext((name), (__LINE__), (__FILE__))
   #define __Pyx_RefNannyFinishContextNogil() __Pyx_RefNannyFinishContext()
 #endif
   #define __Pyx_RefNannyFinishContext() \
           __Pyx_RefNanny->FinishContext(&__pyx_refnanny)
@@ -1495,15 +1495,15 @@
   #define __Pyx_RefNannyFinishContextNogil() __Pyx_RefNannyFinishContext()
 #endif
   #define __Pyx_RefNannyFinishContext() \
           __Pyx_RefNanny->FinishContext(&__pyx_refnanny)
-  #define __Pyx_INCREF(r)  __Pyx_RefNanny->INCREF(__pyx_refnanny, (PyObject *)(r), __LINE__)
-  #define __Pyx_DECREF(r)  __Pyx_RefNanny->DECREF(__pyx_refnanny, (PyObject *)(r), __LINE__)
-  #define __Pyx_GOTREF(r)  __Pyx_RefNanny->GOTREF(__pyx_refnanny, (PyObject *)(r), __LINE__)
-  #define __Pyx_GIVEREF(r) __Pyx_RefNanny->GIVEREF(__pyx_refnanny, (PyObject *)(r), __LINE__)
-  #define __Pyx_XINCREF(r)  do { if((r) != NULL) {__Pyx_INCREF(r); }} while(0)
-  #define __Pyx_XDECREF(r)  do { if((r) != NULL) {__Pyx_DECREF(r); }} while(0)
-  #define __Pyx_XGOTREF(r)  do { if((r) != NULL) {__Pyx_GOTREF(r); }} while(0)
-  #define __Pyx_XGIVEREF(r) do { if((r) != NULL) {__Pyx_GIVEREF(r);}} while(0)
+  #define __Pyx_INCREF(r)  __Pyx_RefNanny->INCREF(__pyx_refnanny, (PyObject *)(r), (__LINE__))
+  #define __Pyx_DECREF(r)  __Pyx_RefNanny->DECREF(__pyx_refnanny, (PyObject *)(r), (__LINE__))
+  #define __Pyx_GOTREF(r)  __Pyx_RefNanny->GOTREF(__pyx_refnanny, (PyObject *)(r), (__LINE__))
+  #define __Pyx_GIVEREF(r) __Pyx_RefNanny->GIVEREF(__pyx_refnanny, (PyObject *)(r), (__LINE__))
+  #define __Pyx_XINCREF(r)  do { if((r) == NULL); else {__Pyx_INCREF(r); }} while(0)
+  #define __Pyx_XDECREF(r)  do { if((r) == NULL); else {__Pyx_DECREF(r); }} while(0)
+  #define __Pyx_XGOTREF(r)  do { if((r) == NULL); else {__Pyx_GOTREF(r); }} while(0)
+  #define __Pyx_XGIVEREF(r) do { if((r) == NULL); else {__Pyx_GIVEREF(r);}} while(0)
 #else
   #define __Pyx_RefNannyDeclarations
   #define __Pyx_RefNannySetupContext(name, acquire_gil)
diff --git a/Cython/Utils.py b/Cython/Utils.py
index cb011b016afcc3a3d59d9c4f1b3345bb2dbb205d_Q3l0aG9uL1V0aWxzLnB5..3c2c33d638a8f5028602752643f0e6c26482bf14_Q3l0aG9uL1V0aWxzLnB5 100644
--- a/Cython/Utils.py
+++ b/Cython/Utils.py
@@ -22,6 +22,7 @@
 import codecs
 import glob
 import shutil
+import tempfile
 from contextlib import contextmanager
 
 from . import __version__ as cython_version
@@ -394,6 +395,5 @@
 
 @contextmanager
 def captured_fd(stream=2, encoding=None):
-    pipe_in = t = None
     orig_stream = os.dup(stream)  # keep copy of original stream
     try:
@@ -398,8 +398,9 @@
     orig_stream = os.dup(stream)  # keep copy of original stream
     try:
-        pipe_in, pipe_out = os.pipe()
-        os.dup2(pipe_out, stream)  # replace stream by copy of pipe
-        try:
-            os.close(pipe_out)  # close original pipe-out stream
-            data = []
+        with tempfile.TemporaryFile(mode="a+b") as temp_file:
+            def read_output(_output=[b'']):
+                if not temp_file.closed:
+                    temp_file.seek(0)
+                    _output[0] = temp_file.read()
+                return _output[0]
 
@@ -405,12 +406,7 @@
 
-            def copy():
-                try:
-                    while True:
-                        d = os.read(pipe_in, 1000)
-                        if d:
-                            data.append(d)
-                        else:
-                            break
-                finally:
-                    os.close(pipe_in)
+            os.dup2(temp_file.fileno(), stream)  # replace stream by copy of pipe
+            try:
+                def get_output():
+                    result = read_output()
+                    return result.decode(encoding) if encoding else result
 
@@ -416,19 +412,8 @@
 
-            def get_output():
-                output = b''.join(data)
-                if encoding:
-                    output = output.decode(encoding)
-                return output
-
-            from threading import Thread
-            t = Thread(target=copy)
-            t.daemon = True  # just in case
-            t.start()
-            yield get_output
-        finally:
-            os.dup2(orig_stream, stream)  # restore original stream
-            if t is not None:
-                t.join()
+                yield get_output
+            finally:
+                os.dup2(orig_stream, stream)  # restore original stream
+                read_output()  # keep the output in case it's used after closing the context manager
     finally:
         os.close(orig_stream)
 
diff --git a/README.rst b/README.rst
index cb011b016afcc3a3d59d9c4f1b3345bb2dbb205d_UkVBRE1FLnJzdA==..3c2c33d638a8f5028602752643f0e6c26482bf14_UkVBRE1FLnJzdA== 100644
--- a/README.rst
+++ b/README.rst
@@ -27,7 +27,7 @@
 Installation:
 -------------
 
-If you already have a C compiler, just do::
+If you already have a C compiler, just run following command::
 
    pip install Cython
 
@@ -71,10 +71,10 @@
 This is a development version of Pyrex, a language
 for writing Python extension modules.
 
-For more info, see:
+For more info, take a look at:
 
 * Doc/About.html for a description of the language
 * INSTALL.txt    for installation instructions
 * USAGE.txt      for usage instructions
 * Demos          for usage examples
 
@@ -75,10 +75,10 @@
 
 * Doc/About.html for a description of the language
 * INSTALL.txt    for installation instructions
 * USAGE.txt      for usage instructions
 * Demos          for usage examples
 
-Comments, suggestions, bug reports, etc. are
+Comments, suggestions, bug reports, etc. are most
 welcome!
 
 Copyright stuff: Pyrex is free of restrictions. You
diff --git a/appveyor.yml b/appveyor.yml
index cb011b016afcc3a3d59d9c4f1b3345bb2dbb205d_YXBwdmV5b3IueW1s..3c2c33d638a8f5028602752643f0e6c26482bf14_YXBwdmV5b3IueW1s 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -24,6 +24,14 @@
       PYTHONIOENCODING: "utf-8"
       PARALLEL: ""
 
+    - PYTHON: "C:\\Python39"
+      PYTHON_VERSION: "3.9"
+      PYTHON_ARCH: "32"
+
+    - PYTHON: "C:\\Python39-x64"
+      PYTHON_VERSION: "3.9"
+      PYTHON_ARCH: "64"
+
     - PYTHON: "C:\\Python38"
       PYTHON_VERSION: "3.8"
       PYTHON_ARCH: "32"
@@ -36,7 +44,8 @@
     - PYTHON: "C:\\Python38-x64"
       PYTHON_VERSION: "3.8"
       PYTHON_ARCH: "64"
+      BACKEND: c,cpp
 
     - PYTHON: "C:\\Python37"
       PYTHON_VERSION: "3.7"
       PYTHON_ARCH: "32"
@@ -39,7 +48,8 @@
 
     - PYTHON: "C:\\Python37"
       PYTHON_VERSION: "3.7"
       PYTHON_ARCH: "32"
+      BACKEND: c,cpp
 
     - PYTHON: "C:\\Python37-x64"
       PYTHON_VERSION: "3.7"
diff --git a/docs/examples/userguide/external_C_code/c_code_docstring.pyx b/docs/examples/userguide/external_C_code/c_code_docstring.pyx
deleted file mode 100644
index cb011b016afcc3a3d59d9c4f1b3345bb2dbb205d_ZG9jcy9leGFtcGxlcy91c2VyZ3VpZGUvZXh0ZXJuYWxfQ19jb2RlL2NfY29kZV9kb2NzdHJpbmcucHl4..0000000000000000000000000000000000000000
--- a/docs/examples/userguide/external_C_code/c_code_docstring.pyx
+++ /dev/null
@@ -1,9 +0,0 @@
-cdef extern from *:
-    """
-    /* This is C code which will be put
-     * in the .c file output by Cython */
-    static long square(long x) {return x * x;}
-    #define assign(x, y) ((x) = (y))
-    """
-    long square(long x)
-    void assign(long& x, long y)
diff --git a/docs/examples/userguide/external_C_code/platform_adaptation.pyx b/docs/examples/userguide/external_C_code/platform_adaptation.pyx
new file mode 100644
index 0000000000000000000000000000000000000000..3c2c33d638a8f5028602752643f0e6c26482bf14_ZG9jcy9leGFtcGxlcy91c2VyZ3VpZGUvZXh0ZXJuYWxfQ19jb2RlL3BsYXRmb3JtX2FkYXB0YXRpb24ucHl4
--- /dev/null
+++ b/docs/examples/userguide/external_C_code/platform_adaptation.pyx
@@ -0,0 +1,14 @@
+cdef extern from *:
+    """
+    #if defined(_WIN32) || defined(MS_WINDOWS) || defined(_MSC_VER)
+      #include <windows.h>
+      #define myapp_sleep(m)  Sleep(m)
+    #else
+      #include <unistd.h>
+      #define myapp_sleep(m)  ((void) usleep((m) * 1000))
+    #endif
+    """
+    # using "myapp_" prefix in the C code to prevent C naming conflicts
+    void msleep "myapp_sleep"(int milliseconds) nogil
+
+msleep(milliseconds=1)
diff --git a/docs/examples/userguide/external_C_code/verbatim_c_code.pyx b/docs/examples/userguide/external_C_code/verbatim_c_code.pyx
new file mode 100644
index 0000000000000000000000000000000000000000..3c2c33d638a8f5028602752643f0e6c26482bf14_ZG9jcy9leGFtcGxlcy91c2VyZ3VpZGUvZXh0ZXJuYWxfQ19jb2RlL3ZlcmJhdGltX2NfY29kZS5weXg=
--- /dev/null
+++ b/docs/examples/userguide/external_C_code/verbatim_c_code.pyx
@@ -0,0 +1,9 @@
+cdef extern from *:
+    """
+    /* This is C code which will be put
+     * in the .c file output by Cython */
+    static long square(long x) {return x * x;}
+    #define assign(x, y) ((x) = (y))
+    """
+    long square(long x)
+    void assign(long& x, long y)
diff --git a/docs/src/tutorial/cython_tutorial.rst b/docs/src/tutorial/cython_tutorial.rst
index cb011b016afcc3a3d59d9c4f1b3345bb2dbb205d_ZG9jcy9zcmMvdHV0b3JpYWwvY3l0aG9uX3R1dG9yaWFsLnJzdA==..3c2c33d638a8f5028602752643f0e6c26482bf14_ZG9jcy9zcmMvdHV0b3JpYWwvY3l0aG9uX3R1dG9yaWFsLnJzdA== 100644
--- a/docs/src/tutorial/cython_tutorial.rst
+++ b/docs/src/tutorial/cython_tutorial.rst
@@ -18,7 +18,7 @@
 equivalent calls to the Python/C API.
 
 But Cython is much more than that, because parameters and variables can be
-declared to have C data types. Code which manipulates Python values and C
+declared to have C data types. Code which manipulates :term:`Python values<Python object>` and C
 values can be freely intermixed, with conversions occurring automatically
 wherever possible. Reference count maintenance and error checking of Python
 operations is also automatic, and the full power of Python's exception
@@ -148,7 +148,7 @@
 and will be copied into a Python list at the end (line 22).
 
 .. NOTE:: You cannot create very large arrays in this manner, because
-          they are allocated on the C function call stack, which is a
+          they are allocated on the C function call :term:`stack<Stack allocation>`, which is a
           rather precious and scarce resource.
           To request larger arrays,
           or even arrays with a length only known at runtime,
diff --git a/docs/src/tutorial/memory_allocation.rst b/docs/src/tutorial/memory_allocation.rst
index cb011b016afcc3a3d59d9c4f1b3345bb2dbb205d_ZG9jcy9zcmMvdHV0b3JpYWwvbWVtb3J5X2FsbG9jYXRpb24ucnN0..3c2c33d638a8f5028602752643f0e6c26482bf14_ZG9jcy9zcmMvdHV0b3JpYWwvbWVtb3J5X2FsbG9jYXRpb24ucnN0 100644
--- a/docs/src/tutorial/memory_allocation.rst
+++ b/docs/src/tutorial/memory_allocation.rst
@@ -20,5 +20,5 @@
 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
+usually :term:`allocated on the stack<Stack allocation>` and passed by value, but for larger and more
 complicated objects (e.g. a dynamically-sized list of doubles), the memory must
@@ -24,5 +24,5 @@
 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 :term:`manually requested and released<Heap allocation>`.  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/pure.rst b/docs/src/tutorial/pure.rst
index cb011b016afcc3a3d59d9c4f1b3345bb2dbb205d_ZG9jcy9zcmMvdHV0b3JpYWwvcHVyZS5yc3Q=..3c2c33d638a8f5028602752643f0e6c26482bf14_ZG9jcy9zcmMvdHV0b3JpYWwvcHVyZS5yc3Q= 100644
--- a/docs/src/tutorial/pure.rst
+++ b/docs/src/tutorial/pure.rst
@@ -82,7 +82,7 @@
 
 
 In the example above, the type of the local variable `a` in `myfunction()`
-is not fixed and will thus be a Python object.  To statically type it, one
+is not fixed and will thus be a :term:`Python object`.  To statically type it, one
 can use Cython's ``@cython.locals`` decorator (see :ref:`magic_attributes`,
 and :ref:`magic_attributes_pxd`).
 
diff --git a/docs/src/userguide/extension_types.rst b/docs/src/userguide/extension_types.rst
index cb011b016afcc3a3d59d9c4f1b3345bb2dbb205d_ZG9jcy9zcmMvdXNlcmd1aWRlL2V4dGVuc2lvbl90eXBlcy5yc3Q=..3c2c33d638a8f5028602752643f0e6c26482bf14_ZG9jcy9zcmMvdXNlcmd1aWRlL2V4dGVuc2lvbl90eXBlcy5yc3Q= 100644
--- a/docs/src/userguide/extension_types.rst
+++ b/docs/src/userguide/extension_types.rst
@@ -11,7 +11,7 @@
 
 As well as creating normal user-defined classes with the Python class
 statement, Cython also lets you create new built-in Python types, known as
-extension types. You define an extension type using the :keyword:`cdef` class
+:term:`extension types<Extension type>`. You define an extension type using the :keyword:`cdef` class
 statement.  Here's an example:
 
 .. literalinclude:: ../../examples/userguide/extension_types/shrubbery.pyx
diff --git a/docs/src/userguide/external_C_code.rst b/docs/src/userguide/external_C_code.rst
index cb011b016afcc3a3d59d9c4f1b3345bb2dbb205d_ZG9jcy9zcmMvdXNlcmd1aWRlL2V4dGVybmFsX0NfY29kZS5yc3Q=..3c2c33d638a8f5028602752643f0e6c26482bf14_ZG9jcy9zcmMvdXNlcmd1aWRlL2V4dGVybmFsX0NfY29kZS5yc3Q= 100644
--- a/docs/src/userguide/external_C_code.rst
+++ b/docs/src/userguide/external_C_code.rst
@@ -335,7 +335,7 @@
 For advanced use cases, Cython allows you to directly write C code
 as "docstring" of a ``cdef extern from`` block:
 
-.. literalinclude:: ../../examples/userguide/external_C_code/c_code_docstring.pyx
+.. literalinclude:: ../../examples/userguide/external_C_code/verbatim_c_code.pyx
 
 The above is essentially equivalent to having the C code in a file
 ``header.h`` and writing ::
@@ -344,6 +344,11 @@
         long square(long x)
         void assign(long& x, long y)
 
+This feature is commonly used for platform specific adaptations at
+compile time, for example:
+
+.. literalinclude:: ../../examples/userguide/external_C_code/platform_adaptation.pyx
+
 It is also possible to combine a header file and verbatim C code::
 
     cdef extern from "badheader.h":
diff --git a/docs/src/userguide/glossary.rst b/docs/src/userguide/glossary.rst
index cb011b016afcc3a3d59d9c4f1b3345bb2dbb205d_ZG9jcy9zcmMvdXNlcmd1aWRlL2dsb3NzYXJ5LnJzdA==..3c2c33d638a8f5028602752643f0e6c26482bf14_ZG9jcy9zcmMvdXNlcmd1aWRlL2dsb3NzYXJ5LnJzdA== 100644
--- a/docs/src/userguide/glossary.rst
+++ b/docs/src/userguide/glossary.rst
@@ -1,3 +1,13 @@
 .. glossary::
 
+   Extension type
+      "Extension type" can refer to either a Cython class defined with ``cdef class`` or more generally to any Python type that is ultimately implemented as a native C struct (including the built-in types like `int` or `dict`).
+      
+   Dynamic allocation
+   Heap allocation
+      A C variable allocated with ``malloc`` (in C) or ``new`` (in C++) is
+      `allocated dynamically/heap allocated <https://en.wikipedia.org/wiki/C_dynamic_memory_allocation>`_.
+      Its lifetime is until the user deletes it explicitly (with ``free`` in C or ``del`` in C++).
+      This can happen in a different function than the allocation.
+
    pointer
@@ -3,2 +13,32 @@
    pointer
-      A **pointer** is a variable that stores the address of another variable (i.e. direct address of the memory location). They allow for dynamic memory allocation and deallocation. They can be used to build dynamic data structures. `Read more <https://en.wikipedia.org/wiki/Pointer_(computer_programming)#C_pointers>`__.
+      A **pointer** is a variable that stores the address of another variable
+      (i.e. direct address of the memory location). They allow for
+      dynamic memory allocation and deallocation. They can be used to build
+      dynamic data structures. `Read more <https://en.wikipedia.org/wiki/Pointer_(computer_programming)#C_pointers>`__.
+      
+   Python object
+      When using Python, the contents of every variable is a Python object
+      (including Cython extension types). Key features of Python objects are that
+      they are passed _by reference_ and that their lifetime is _managed_ automatically
+      so that they are destroyed when no more references exist to them.
+      In Cython, they are distinct from C types, which are passed _by value_ and whose
+      lifetime is managed depending on whether they are allocated on the stack or heap.
+      To explicitly declare a Python object variable in Cython use ``cdef object abc``.
+      Internally in C, they are referred to as ``PyObject*``.
+      
+   Stack allocation
+      A C variable declared within a function as ``cdef SomeType a``
+      is said to be allocated on the stack.
+      It exists for the duration of the function only.
+      
+   Typed memoryview
+      A useful Cython type for getting quick access to blocks of memory.
+      A memoryview alone does not actually own any memory.
+      However, it can be initialized with a Python object that supports the
+      `buffer protocol`_ (typically "array" types, for example a Numpy array).
+      The memoryview keeps a reference to that Python object alive
+      and provides quick access to the memory without needing to go
+      through the Python API of the object and its ``__getitem__``/``__setitem__`` methods.
+      For more information, see :ref:`memoryviews`.
+
+.. _buffer protocol: https://docs.python.org/3/c-api/buffer.html
diff --git a/docs/src/userguide/language_basics.rst b/docs/src/userguide/language_basics.rst
index cb011b016afcc3a3d59d9c4f1b3345bb2dbb205d_ZG9jcy9zcmMvdXNlcmd1aWRlL2xhbmd1YWdlX2Jhc2ljcy5yc3Q=..3c2c33d638a8f5028602752643f0e6c26482bf14_ZG9jcy9zcmMvdXNlcmd1aWRlL2xhbmd1YWdlX2Jhc2ljcy5yc3Q= 100644
--- a/docs/src/userguide/language_basics.rst
+++ b/docs/src/userguide/language_basics.rst
@@ -189,7 +189,7 @@
 There are two kinds of function definition in Cython:
 
 Python functions are defined using the def statement, as in Python. They take
-Python objects as parameters and return Python objects.
+:term:`Python objects<Python object>` as parameters and return Python objects.
 
 C functions are defined using the new :keyword:`cdef` statement. They take
 either Python objects or C values as parameters, and can return either Python
@@ -366,8 +366,10 @@
 Error return values
 -------------------
 
-If you don't do anything special, a function declared with :keyword:`cdef` that
-does not return a Python object has no way of reporting Python exceptions to
-its caller. If an exception is detected in such a function, a warning message
-is printed and the exception is ignored.
+In Python (more specifically, in the CPython runtime), exceptions that occur
+inside of a function are signaled to the caller and propagated up the call stack
+through defined error return values.  For functions that return a Python object
+(and thus, a pointer to such an object), the error return value is simply the
+``NULL`` pointer, so any function returning a Python object has a well-defined
+error return value.
 
@@ -373,8 +375,15 @@
 
-If you want a C function that does not return a Python object to be able to
-propagate exceptions to its caller, you need to declare an exception value for
-it. Here is an example::
+While this is always the case for :keyword:`def` functions, functions
+defined as :keyword:`cdef` or :keyword:`cpdef` can return arbitrary C types,
+which do not have such a well-defined error return value.  Thus, if an
+exception is detected in such a function, a warning message is printed,
+the exception is ignored, and the function returns immediately without
+propagating the exception to its caller.
+
+If you want such a C function to be able to propagate exceptions, you need
+to declare an exception return value for it as a contract with the caller.
+Here is an example::
 
     cdef int spam() except -1:
         ...
 
@@ -377,9 +386,9 @@
 
     cdef int spam() except -1:
         ...
 
-With this declaration, whenever an exception occurs inside spam, it will
-immediately return with the value ``-1``. Furthermore, whenever a call to spam
-returns ``-1``, an exception will be assumed to have occurred and will be
-propagated.
+With this declaration, whenever an exception occurs inside ``spam``, it will
+immediately return with the value ``-1``.  From the caller's side, whenever
+a call to spam returns ``-1``, the caller will assume that an exception has
+occurred and can now process or propagate it.
 
@@ -385,8 +394,12 @@
 
-When you declare an exception value for a function, you should never
-explicitly or implicitly return that value. In particular, if the exceptional return value
-is a ``False`` value, then you should ensure the function will never terminate via an implicit
-or empty return.
+When you declare an exception value for a function, you should never explicitly
+or implicitly return that value.  This includes empty :keyword:`return`
+statements, without a return value, for which Cython inserts the default return
+value (e.g. ``0`` for C number types).  In general, exception return values
+are best chosen from invalid or very unlikely return values of the function,
+such as a negative value for functions that return only non-negative results,
+or a very large value like ``INT_MAX`` for a function that "usually" only
+returns small results.
 
 If all possible return values are legal and you
 can't reserve one entirely for signalling errors, you can use an alternative
@@ -395,9 +408,10 @@
     cdef int spam() except? -1:
         ...
 
-The "?" indicates that the value ``-1`` only indicates a possible error. In this
-case, Cython generates a call to :c:func:`PyErr_Occurred` if the exception value is
-returned, to make sure it really is an error.
+The "?" indicates that the value ``-1`` only signals a possible error. In this
+case, Cython generates a call to :c:func:`PyErr_Occurred` if the exception value
+is returned, to make sure it really received an exception and not just a normal
+result.
 
 There is also a third form of exception value declaration::
 
@@ -405,10 +419,11 @@
         ...
 
 This form causes Cython to generate a call to :c:func:`PyErr_Occurred` after
-every call to spam, regardless of what value it returns. If you have a
-function returning void that needs to propagate errors, you will have to use
-this form, since there isn't any return value to test.
-Otherwise there is little use for this form.
+*every* call to spam, regardless of what value it returns. If you have a
+function returning ``void`` that needs to propagate errors, you will have to
+use this form, since there isn't any error return value to test.
+Otherwise, an explicit error return value allows the C compiler to generate
+more efficient code and is thus generally preferable.
 
 An external C++ function that may raise an exception can be declared with::
 
@@ -418,9 +433,10 @@
 
 Some things to note:
 
-* Exception values can only declared for functions returning an integer, enum,
-  float or pointer type, and the value must be a constant expression.
-  Void functions can only use the ``except *`` form.
+* Exception values can only be declared for functions returning a C integer,
+  enum, float or pointer type, and the value must be a constant expression.
+  Functions that return ``void``, or a struct/union by value, can only use
+  the ``except *`` form.
 * The exception value specification is part of the signature of the function.
   If you're passing a pointer to a function as a parameter or assigning it
   to a variable, the declared type of the parameter or variable must have
@@ -424,11 +440,10 @@
 * The exception value specification is part of the signature of the function.
   If you're passing a pointer to a function as a parameter or assigning it
   to a variable, the declared type of the parameter or variable must have
-  the same exception value specification (or lack thereof). Here is an
-  example of a pointer-to-function declaration with an exception
-  value::
+  the same exception value specification (or lack thereof).  Here is an
+  example of a pointer-to-function declaration with an exception value::
 
       int (*grail)(int, char*) except -1
 
 * You don't need to (and shouldn't) declare exception values for functions
   which return Python objects. Remember that a function with no declared
@@ -430,10 +445,10 @@
 
       int (*grail)(int, char*) except -1
 
 * You don't need to (and shouldn't) declare exception values for functions
   which return Python objects. Remember that a function with no declared
-  return type implicitly returns a Python object. (Exceptions on such functions
-  are implicitly propagated by returning NULL.)
+  return type implicitly returns a Python object. (Exceptions on such
+  functions are implicitly propagated by returning ``NULL``.)
 
 
 .. _checking_return_values_of_non_cython_functions:
@@ -937,4 +952,3 @@
 expressions as for the ``DEF`` statement, although they can evaluate to any
 Python value, and the truth of the result is determined in the usual Python
 way.
-
diff --git a/docs/src/userguide/parallelism.rst b/docs/src/userguide/parallelism.rst
index cb011b016afcc3a3d59d9c4f1b3345bb2dbb205d_ZG9jcy9zcmMvdXNlcmd1aWRlL3BhcmFsbGVsaXNtLnJzdA==..3c2c33d638a8f5028602752643f0e6c26482bf14_ZG9jcy9zcmMvdXNlcmd1aWRlL3BhcmFsbGVsaXNtLnJzdA== 100644
--- a/docs/src/userguide/parallelism.rst
+++ b/docs/src/userguide/parallelism.rst
@@ -118,7 +118,7 @@
 
 .. literalinclude:: ../../examples/userguide/parallelism/simple_sum.pyx
 
-Example with a typed memoryview (e.g. a NumPy array)::
+Example with a :term:`typed memoryview<Typed memoryview>` (e.g. a NumPy array)::
 
     from cython.parallel import prange
 
diff --git a/docs/src/userguide/wrapping_CPlusPlus.rst b/docs/src/userguide/wrapping_CPlusPlus.rst
index cb011b016afcc3a3d59d9c4f1b3345bb2dbb205d_ZG9jcy9zcmMvdXNlcmd1aWRlL3dyYXBwaW5nX0NQbHVzUGx1cy5yc3Q=..3c2c33d638a8f5028602752643f0e6c26482bf14_ZG9jcy9zcmMvdXNlcmd1aWRlL3dyYXBwaW5nX0NQbHVzUGx1cy5yc3Q= 100644
--- a/docs/src/userguide/wrapping_CPlusPlus.rst
+++ b/docs/src/userguide/wrapping_CPlusPlus.rst
@@ -11,8 +11,8 @@
 
 Cython has native support for most of the C++ language.  Specifically:
 
-* C++ objects can be dynamically allocated with ``new`` and ``del`` keywords.
-* C++ objects can be stack-allocated.
+* C++ objects can be :term:`dynamically allocated<Dynamic allocation>` with ``new`` and ``del`` keywords.
+* C++ objects can be :term:`stack-allocated<Stack allocation>`.
 * C++ classes can be declared with the new keyword ``cppclass``.
 * Templated classes and functions are supported.
 * Overloaded functions are supported.
diff --git a/runtests.py b/runtests.py
index cb011b016afcc3a3d59d9c4f1b3345bb2dbb205d_cnVudGVzdHMucHk=..3c2c33d638a8f5028602752643f0e6c26482bf14_cnVudGVzdHMucHk= 100755
--- a/runtests.py
+++ b/runtests.py
@@ -661,7 +661,9 @@
                     continue
                 suite.addTest(
                     self.handle_directory(path, filename))
-        if sys.platform not in ['win32'] and self.add_embedded_test:
+        if (sys.platform not in ['win32'] and self.add_embedded_test
+                # the embedding test is currently broken in Py3.8+, except on Linux.
+                and (sys.version_info < (3, 8) or sys.platform != 'darwin')):
             # Non-Windows makefile.
             if [1 for selector in self.selectors if selector("embedded")] \
                     and not [1 for selector in self.exclude_selectors if selector("embedded")]:
diff --git a/tests/compile/const_decl.pyx b/tests/compile/const_decl.pyx
index cb011b016afcc3a3d59d9c4f1b3345bb2dbb205d_dGVzdHMvY29tcGlsZS9jb25zdF9kZWNsLnB5eA==..3c2c33d638a8f5028602752643f0e6c26482bf14_dGVzdHMvY29tcGlsZS9jb25zdF9kZWNsLnB5eA== 100644
--- a/tests/compile/const_decl.pyx
+++ b/tests/compile/const_decl.pyx
@@ -1,5 +1,5 @@
 # mode: compile
 
-cdef const_args(const int a, const int *b, const (int*) c, int *const d):
+cdef const_args(const int a, const int *b, const (int*) c, int *const d, int **const e, int *const *f):
     print a
     print b[0]
@@ -4,8 +4,12 @@
     print a
     print b[0]
-    b = NULL    # OK, the pointer itself is not const
-    c[0] = 4    # OK, the value is not const
-    d[0] = 7    # OK, the value is not const
+    b = NULL     # OK, the pointer itself is not const
+    c[0] = 4     # OK, the value is not const
+    d[0] = 7     # OK, the value is not const
+    e[0][0] = 1  # OK, the value is not const
+    e[0] = NULL  # OK, the pointed pointer is not const
+    f[0][0] = 1  # OK, the value is not const
+    f = NULL     # OK, the pointer is not const
 
 def call_const_args(x):
     cdef int k = x
@@ -9,4 +13,5 @@
 
 def call_const_args(x):
     cdef int k = x
-    const_args(x, &k, &k, &k)
+    cdef int* arr = [x]
+    const_args(x, &k, &k, &k, &arr, &arr)
diff --git a/tests/compile/cpp_rvalue_reference_binding.pyx b/tests/compile/cpp_rvalue_reference_binding.pyx
new file mode 100644
index 0000000000000000000000000000000000000000..3c2c33d638a8f5028602752643f0e6c26482bf14_dGVzdHMvY29tcGlsZS9jcHBfcnZhbHVlX3JlZmVyZW5jZV9iaW5kaW5nLnB5eA==
--- /dev/null
+++ b/tests/compile/cpp_rvalue_reference_binding.pyx
@@ -0,0 +1,22 @@
+# tag: cpp, cpp11
+# mode: compile
+
+cdef extern from *:
+    """
+    template <typename T>
+    void accept(T&& x) { (void) x; }
+    """
+    cdef void accept[T](T&& x)
+
+cdef int make_int_py() except *:
+    # might raise Python exception (thus needs a temp)
+    return 1
+
+cdef int make_int_cpp() except +:
+    # might raise C++ exception (thus needs a temp)
+    return 1
+
+def test_func_arg():
+    # won't compile if move() isn't called on the temp:
+    accept(make_int_py())
+    accept(make_int_cpp())
diff --git a/tests/compile/extern_packed_struct.pyx b/tests/compile/extern_packed_struct.pyx
deleted file mode 100644
index cb011b016afcc3a3d59d9c4f1b3345bb2dbb205d_dGVzdHMvY29tcGlsZS9leHRlcm5fcGFja2VkX3N0cnVjdC5weXg=..0000000000000000000000000000000000000000
--- a/tests/compile/extern_packed_struct.pyx
+++ /dev/null
@@ -1,5 +0,0 @@
-# mode: compile
-
-cdef extern from *:
-    cdef packed struct MyStruct:
-        char a
diff --git a/tests/compile/packed_structs.pyx b/tests/compile/packed_structs.pyx
new file mode 100644
index 0000000000000000000000000000000000000000..3c2c33d638a8f5028602752643f0e6c26482bf14_dGVzdHMvY29tcGlsZS9wYWNrZWRfc3RydWN0cy5weXg=
--- /dev/null
+++ b/tests/compile/packed_structs.pyx
@@ -0,0 +1,10 @@
+# mode: compile
+
+cdef extern from *:
+    cdef packed struct MyStruct:
+        char a
+
+cdef public packed struct PublicStruct:
+    int a
+    unsigned char b
+    int c
diff --git a/tests/errors/const_decl_errors.pyx b/tests/errors/const_decl_errors.pyx
index cb011b016afcc3a3d59d9c4f1b3345bb2dbb205d_dGVzdHMvZXJyb3JzL2NvbnN0X2RlY2xfZXJyb3JzLnB5eA==..3c2c33d638a8f5028602752643f0e6c26482bf14_dGVzdHMvZXJyb3JzL2NvbnN0X2RlY2xfZXJyb3JzLnB5eA== 100644
--- a/tests/errors/const_decl_errors.pyx
+++ b/tests/errors/const_decl_errors.pyx
@@ -10,10 +10,10 @@
 cdef struct S:
     int member
 
-cdef func(const int a, const int* b, const (int*) c, const S s, int *const d,
+cdef func(const int a, const int* b, const (int*) c, const S s, int *const d, int **const e, int *const *f,
           const S *const t):
     a = 10
     c = NULL
     b[0] = 100
     s.member = 1000
     d = NULL
@@ -14,9 +14,15 @@
           const S *const t):
     a = 10
     c = NULL
     b[0] = 100
     s.member = 1000
     d = NULL
+    e[0][0] = 1  # ok
+    e[0] = NULL  # ok
+    e = NULL     # nok
+    f[0][0] = 1  # ok
+    f[0] = NULL  # nok
+    f = NULL     # ok
     t = &s
 
 cdef volatile object v
@@ -30,6 +36,8 @@
 17:5: Assignment to const dereference
 18:5: Assignment to const attribute 'member'
 19:4: Assignment to const 'd'
-20:4: Assignment to const 't'
-22:5: Const/volatile base type cannot be a Python object
+22:4: Assignment to const 'e'
+24:5: Assignment to const dereference
+26:4: Assignment to const 't'
+28:5: Const/volatile base type cannot be a Python object
 """
diff --git a/tests/errors/cpp_rvalue_reference_support.pyx b/tests/errors/cpp_rvalue_reference_support.pyx
new file mode 100644
index 0000000000000000000000000000000000000000..3c2c33d638a8f5028602752643f0e6c26482bf14_dGVzdHMvZXJyb3JzL2NwcF9ydmFsdWVfcmVmZXJlbmNlX3N1cHBvcnQucHl4
--- /dev/null
+++ b/tests/errors/cpp_rvalue_reference_support.pyx
@@ -0,0 +1,32 @@
+# mode: error
+# tag: werror, cpp, cpp11
+
+# These tests check for unsupported use of rvalue-references (&&)
+# and should be removed or cleaned up when support is added.
+
+cdef int&& x
+
+cdef void foo(int&& x):
+    pass
+
+cdef int&& bar():
+    pass
+
+cdef extern from *:
+    """
+    void baz(int x, int&& y) {}
+
+    template <typename T>
+    void qux(const T&& x) {}
+    """
+    cdef void baz(int x, int&& y)
+    cdef void qux[T](const T&& x)
+
+
+_ERRORS="""
+7:8: C++ rvalue-references cannot be declared
+9:13: Rvalue-reference as function argument not supported
+12:14: Rvalue-reference as function return type not supported
+22:17: Rvalue-reference as function argument not supported
+23:20: Rvalue-reference as function argument not supported
+"""
diff --git a/tests/errors/e_binop_and.pyx b/tests/errors/e_binop_and.pyx
new file mode 100644
index 0000000000000000000000000000000000000000..3c2c33d638a8f5028602752643f0e6c26482bf14_dGVzdHMvZXJyb3JzL2VfYmlub3BfYW5kLnB5eA==
--- /dev/null
+++ b/tests/errors/e_binop_and.pyx
@@ -0,0 +1,14 @@
+# mode: error
+# tag: and, binop, warnings
+
+def test_and(a, b):
+    return a && b
+
+
+_WARNINGS = """
+5:13: Found the C operator '&&', did you mean the Python operator 'and'?
+"""
+
+_ERRORS = """
+5:13: Syntax error in simple statement list
+"""
diff --git a/tests/errors/e_binop_or.pyx b/tests/errors/e_binop_or.pyx
new file mode 100644
index 0000000000000000000000000000000000000000..3c2c33d638a8f5028602752643f0e6c26482bf14_dGVzdHMvZXJyb3JzL2VfYmlub3Bfb3IucHl4
--- /dev/null
+++ b/tests/errors/e_binop_or.pyx
@@ -0,0 +1,14 @@
+# mode: error
+# tag: or, binop, warnings
+
+def test_or(a, b):
+    return a || b
+
+
+_WARNINGS = """
+5:13: Found the C operator '||', did you mean the Python operator 'or'?
+"""
+
+_ERRORS = """
+5:13: Syntax error in simple statement list
+"""
diff --git a/tests/errors/e_cpp_references.pyx b/tests/errors/e_cpp_references.pyx
new file mode 100644
index 0000000000000000000000000000000000000000..3c2c33d638a8f5028602752643f0e6c26482bf14_dGVzdHMvZXJyb3JzL2VfY3BwX3JlZmVyZW5jZXMucHl4
--- /dev/null
+++ b/tests/errors/e_cpp_references.pyx
@@ -0,0 +1,10 @@
+# mode: error
+# tag: cpp, cpp11
+
+cdef foo(object& x): pass
+cdef bar(object&& x): pass
+
+_ERRORS="""
+4:15: Reference base type cannot be a Python object
+5:15: Rvalue-reference base type cannot be a Python object
+"""
diff --git a/tests/errors/fused_types.pyx b/tests/errors/fused_types.pyx
index cb011b016afcc3a3d59d9c4f1b3345bb2dbb205d_dGVzdHMvZXJyb3JzL2Z1c2VkX3R5cGVzLnB5eA==..3c2c33d638a8f5028602752643f0e6c26482bf14_dGVzdHMvZXJyb3JzL2Z1c2VkX3R5cGVzLnB5eA== 100644
--- a/tests/errors/fused_types.pyx
+++ b/tests/errors/fused_types.pyx
@@ -76,6 +76,16 @@
 
 func(x, y)
 
+cdef floating return_type_unfindable1(cython.integral x):
+    return 1.0
+
+cpdef floating return_type_unfindable2(cython.integral x):
+    return 1.0
+
+cdef void contents_unfindable1(cython.integral x):
+    z: floating = 1  # note: cdef variables also fail with an error but not by the time this test aborts
+    sz = sizeof(floating)
+
 
 _ERRORS = u"""
 11:15: fused_type does not take keyword arguments
@@ -92,4 +102,13 @@
 46:9: Fused types not allowed here
 61:0: Invalid use of fused types, type cannot be specialized
 61:29: ambiguous overloaded method
+# Possibly duplicates the errors more often than we want
+79:5: Return type is a fused type that cannot be determined from the function arguments
+82:6: Return type is a fused type that cannot be determined from the function arguments
+86:4: 'z' cannot be specialized since its type is not a fused argument to this function
+86:4: 'z' cannot be specialized since its type is not a fused argument to this function
+86:4: 'z' cannot be specialized since its type is not a fused argument to this function
+87:24: Type cannot be specialized since it is not a fused argument to this function
+87:24: Type cannot be specialized since it is not a fused argument to this function
+87:24: Type cannot be specialized since it is not a fused argument to this function
 """
diff --git a/tests/memoryview/cfunc_convert_with_memoryview.pyx b/tests/memoryview/cfunc_convert_with_memoryview.pyx
new file mode 100644
index 0000000000000000000000000000000000000000..3c2c33d638a8f5028602752643f0e6c26482bf14_dGVzdHMvbWVtb3J5dmlldy9jZnVuY19jb252ZXJ0X3dpdGhfbWVtb3J5dmlldy5weXg=
--- /dev/null
+++ b/tests/memoryview/cfunc_convert_with_memoryview.pyx
@@ -0,0 +1,51 @@
+# mode: run
+# tag: autowrap
+# cython: always_allow_keywords=True
+
+cdef void memoryview_func_a(double [:] x):
+    x[0] = 1
+
+cdef void memoryview_func_b(double [::1] x):
+    x[0] = 2
+
+cdef void memoryview_func_c(int [:] x):
+    x[0] = 1
+
+cdef void memoryview_func_d(int [:] x):
+    x[0] = 2
+
+cdef void memoryview_func_e(int [:,::1] x):
+    x[0,0] = 4
+
+cdef void memoryview_func_f(int [::1,:] x):
+    x[0,0] = 4
+
+
+def test_memview_wrapping():
+    """
+    We're mainly concerned that the code compiles without the names clashing
+    >>> test_memview_wrapping()
+    1.0
+    2.0
+    1
+    2
+    """
+    cdef a = memoryview_func_a
+    cdef b = memoryview_func_b
+    cdef c = memoryview_func_c
+    cdef d = memoryview_func_d
+    cdef e = memoryview_func_e
+    cdef f = memoryview_func_f
+    cdef double[1] double_arr = [0]
+    cdef int[1] int_arr = [0]
+
+    a(<double[:1]> double_arr)
+    print(double_arr[0])
+    b(<double[:1:1]> double_arr)
+    print(double_arr[0])
+    c(<int[:1]> int_arr)
+    print(int_arr[0])
+    d(<int[:1:1]> int_arr)
+    print(int_arr[0])
+    # don't call e and f because it's harder without needing extra dependencies
+    # it's mostly a compile test for them
diff --git a/tests/run/annotation_typing.pyx b/tests/run/annotation_typing.pyx
index cb011b016afcc3a3d59d9c4f1b3345bb2dbb205d_dGVzdHMvcnVuL2Fubm90YXRpb25fdHlwaW5nLnB5eA==..3c2c33d638a8f5028602752643f0e6c26482bf14_dGVzdHMvcnVuL2Fubm90YXRpb25fdHlwaW5nLnB5eA== 100644
--- a/tests/run/annotation_typing.pyx
+++ b/tests/run/annotation_typing.pyx
@@ -262,6 +262,10 @@
     return price, ndigits
 
 
+cdef class ClassAttribute:
+    cls_attr : float = 1.
+
+
 _WARNINGS = """
 8:32: Strings should no longer be used for type declarations. Use 'cython.int' etc. directly.
 8:47: Dicts should no longer be used as type annotations. Use 'cython.int' etc. directly.
@@ -271,6 +275,7 @@
 8:85: Strings should no longer be used for type declarations. Use 'cython.int' etc. directly.
 242:44: Unknown type declaration in annotation, ignoring
 249:29: Ambiguous types in annotation, ignoring
+266:15: Annotation ignored since class-level attributes must be Python objects. Were you trying to set up an instance attribute?
 # BUG:
 46:6: 'pytypes_cpdef' redeclared
 120:0: 'struct_io' redeclared
diff --git a/tests/run/cfunc_convert.pyx b/tests/run/cfunc_convert.pyx
index cb011b016afcc3a3d59d9c4f1b3345bb2dbb205d_dGVzdHMvcnVuL2NmdW5jX2NvbnZlcnQucHl4..3c2c33d638a8f5028602752643f0e6c26482bf14_dGVzdHMvcnVuL2NmdW5jX2NvbnZlcnQucHl4 100644
--- a/tests/run/cfunc_convert.pyx
+++ b/tests/run/cfunc_convert.pyx
@@ -1,4 +1,5 @@
 # mode: run
+# tag: autowrap
 # cython: always_allow_keywords=True
 
 cimport cython
diff --git a/tests/run/constants.pyx b/tests/run/constants.pyx
new file mode 100644
index 0000000000000000000000000000000000000000..3c2c33d638a8f5028602752643f0e6c26482bf14_dGVzdHMvcnVuL2NvbnN0YW50cy5weXg=
--- /dev/null
+++ b/tests/run/constants.pyx
@@ -0,0 +1,287 @@
+import sys
+IS_PY3 = sys.version_info[0] >= 3
+
+cimport cython
+
+DEF INT_VAL = 1
+
+def _func(a,b,c):
+    return a+b+c
+
+@cython.test_fail_if_path_exists("//AddNode")
+def add():
+    """
+    >>> add() == 1+2+3+4
+    True
+    """
+    return 1+2+3+4
+
+#@cython.test_fail_if_path_exists("//AddNode")
+def add_var(a):
+    """
+    >>> add_var(10) == 1+2+10+3+4
+    True
+    """
+    return 1+2 +a+ 3+4
+
+@cython.test_fail_if_path_exists("//AddNode", "//SubNode")
+def neg():
+    """
+    >>> neg() == -1 -2 - (-3+4)
+    True
+    """
+    return -1 -2 - (-3+4)
+
+@cython.test_fail_if_path_exists("//AddNode", "//MulNode", "//DivNode")
+def long_int_mix():
+    """
+    >>> long_int_mix() == 1 + (2 * 3) // 2
+    True
+    >>> if IS_PY3: type(long_int_mix()) is int  or type(long_int_mix())
+    ... else:      type(long_int_mix()) is long or type(long_int_mix())
+    True
+    """
+    return 1L + (2 * 3L) // 2
+
+@cython.test_fail_if_path_exists("//AddNode", "//MulNode", "//DivNode")
+def char_int_mix():
+    """
+    >>> char_int_mix() == 1 + (ord(' ') * 3) // 2 + ord('A')
+    True
+    """
+    return 1L + (c' ' * 3L) // 2 + c'A'
+
+@cython.test_fail_if_path_exists("//AddNode", "//MulNode")
+def int_cast():
+    """
+    >>> int_cast() == 1 + 2 * 6000
+    True
+    """
+    return <int>(1 + 2 * 6000)
+
+@cython.test_fail_if_path_exists("//MulNode")
+def mul():
+    """
+    >>> mul() == 1*60*1000
+    True
+    """
+    return 1*60*1000
+
+@cython.test_fail_if_path_exists("//AddNode", "//MulNode")
+def arithm():
+    """
+    >>> arithm() == 9*2+3*8//6-10
+    True
+    """
+    return 9*2+3*8//6-10
+
+@cython.test_fail_if_path_exists("//AddNode", "//MulNode")
+def parameters():
+    """
+    >>> parameters() == _func(-1 -2, - (-3+4), 1*2*3)
+    True
+    """
+    return _func(-1 -2, - (-3+4), 1*2*3)
+
+#@cython.test_fail_if_path_exists("//AddNode")
+def lists():
+    """
+    >>> lists() == [1,2,3] + [4,5,6]
+    True
+    """
+    return [1,2,3] + [4,5,6]
+
+@cython.test_fail_if_path_exists("//MulNode")
+def multiplied_lists_right_len1():
+    """
+    >>> multiplied_lists_right_len1() == [1] * 5
+    True
+    """
+    return [1] * 5
+
+@cython.test_fail_if_path_exists("//MulNode")
+def multiplied_lists_right():
+    """
+    >>> multiplied_lists_right() == [1,2,3] * 5
+    True
+    """
+    return [1,2,3] * 5
+
+@cython.test_fail_if_path_exists("//MulNode")
+def multiplied_lists_left():
+    """
+    >>> multiplied_lists_left() == [1,2,3] * 5
+    True
+    """
+    return 5 * [1,2,3]
+
+@cython.test_fail_if_path_exists("//MulNode")
+def multiplied_lists_neg():
+    """
+    >>> multiplied_lists_neg() == [1,2,3] * -5
+    True
+    """
+    return [1,2,3] * -5
+
+@cython.test_fail_if_path_exists("//MulNode")
+def multiplied_lists_nonconst(x):
+    """
+    >>> multiplied_lists_nonconst(5) == [1,2,3] * 5
+    True
+    >>> multiplied_lists_nonconst(-5) == [1,2,3] * -5
+    True
+    >>> multiplied_lists_nonconst(0) == [1,2,3] * 0
+    True
+
+    >>> try: [1,2,3] * 'abc'
+    ... except TypeError: pass
+    >>> try: multiplied_nonconst_tuple_arg('abc')
+    ... except TypeError: pass
+    >>> try: [1,2,3] * 1.0
+    ... except TypeError: pass
+    >>> try: multiplied_nonconst_tuple_arg(1.0)
+    ... except TypeError: pass
+    """
+    return [1,2,3] * x
+
+@cython.test_assert_path_exists("//MulNode")
+def multiplied_lists_nonconst_left(x):
+    """
+    >>> multiplied_lists_nonconst_left(5) == 5 * [1,2,3]
+    True
+    >>> multiplied_lists_nonconst_left(-5) == -5 * [1,2,3]
+    True
+    >>> multiplied_lists_nonconst_left(0) == 0 * [1,2,3]
+    True
+    """
+    return x * [1,2,3]
+
+
+@cython.test_fail_if_path_exists("//MulNode")
+def multiplied_nonconst_list_const_int(x):
+    """
+    >>> multiplied_nonconst_list_const_int(2)
+    [1, 2, 3, 1, 2, 3]
+    """
+    return [1,x,3] * 2
+
+
+@cython.test_fail_if_path_exists("//MulNode//ListNode")
+def multiplied_lists_nonconst_expression(x):
+    """
+    >>> multiplied_lists_nonconst_expression(5) == [1,2,3] * (5 * 2)
+    True
+    >>> multiplied_lists_nonconst_expression(-5) == [1,2,3] * (-5 * 2)
+    True
+    >>> multiplied_lists_nonconst_expression(0) == [1,2,3] * (0 * 2)
+    True
+    """
+    return [1,2,3] * (x*2)
+
+cdef side_effect(int x):
+    print x
+    return x
+
+@cython.test_fail_if_path_exists("//MulNode")
+def multiplied_lists_with_side_effects():
+    """
+    >>> multiplied_lists_with_side_effects() == [1,2,3] * 5
+    1
+    2
+    3
+    True
+    """
+    return [side_effect(1), side_effect(2), side_effect(3)] * 5
+
+@cython.test_fail_if_path_exists("//MulNode")
+def multiplied_lists_nonconst_with_side_effects(x):
+    """
+    >>> multiplied_lists_nonconst_with_side_effects(5) == [1,2,3] * 5
+    1
+    2
+    3
+    True
+    """
+    return [side_effect(1), side_effect(2), side_effect(3)] * x
+
+@cython.test_fail_if_path_exists("//MulNode")
+def multiplied_nonconst_tuple_arg(x):
+    """
+    >>> multiplied_nonconst_tuple_arg(5) == (1,2) * 5
+    True
+    >>> multiplied_nonconst_tuple_arg(-5) == (1,2) * -5
+    True
+    >>> multiplied_nonconst_tuple_arg(0) == (1,2) * 0
+    True
+
+    >>> try: (1,2) * 'abc'
+    ... except TypeError: pass
+    >>> try: multiplied_nonconst_tuple_arg('abc')
+    ... except TypeError: pass
+    >>> try: (1,2) * 1.0
+    ... except TypeError: pass
+    >>> try: multiplied_nonconst_tuple_arg(1.0)
+    ... except TypeError: pass
+    """
+    return (1,2) * x
+
+@cython.test_fail_if_path_exists("//MulNode")
+def multiplied_nonconst_tuple_int_arg(int x):
+    """
+    >>> multiplied_nonconst_tuple_int_arg(5) == (1,2) * 5
+    True
+    """
+    return (1,2) * x
+
+@cython.test_fail_if_path_exists("//MulNode")
+def multiplied_nonconst_tuple(x):
+    """
+    >>> multiplied_nonconst_tuple(5) == (1,2) * (5+1)
+    True
+    """
+    return (1,2) * (x + 1)
+
+MULT = 5
+
+@cython.test_fail_if_path_exists("//MulNode")
+def multiplied_global_nonconst_tuple():
+    """
+    >>> multiplied_global_nonconst_tuple() == (1,2,3) * 5
+    1
+    2
+    3
+    True
+    """
+    return (side_effect(1), side_effect(2), side_effect(3)) * MULT
+
+@cython.test_fail_if_path_exists("//MulNode")
+def multiplied_const_tuple():
+    """
+    >>> multiplied_const_tuple() == (1,2) * 5
+    True
+    """
+    return (1,2) * 5
+
+@cython.test_fail_if_path_exists("//MulNode")
+def multiplied_const_tuple_len1():
+    """
+    >>> multiplied_const_tuple_len1() == (1,) * 5
+    True
+    """
+    return (1,) * 5
+
+@cython.test_fail_if_path_exists("//PrimaryCmpNode")
+def compile_time_DEF():
+    """
+    >>> compile_time_DEF()
+    (1, False, True, True, False)
+    """
+    return INT_VAL, INT_VAL == 0, INT_VAL != 0, INT_VAL == 1, INT_VAL != 1
+
+@cython.test_fail_if_path_exists("//PrimaryCmpNode")
+def cascaded_compare():
+    """
+    >>> cascaded_compare()
+    True
+    """
+    return 1 < 2 < 3 < 4
diff --git a/tests/run/consts.pyx b/tests/run/consts.pyx
deleted file mode 100644
index cb011b016afcc3a3d59d9c4f1b3345bb2dbb205d_dGVzdHMvcnVuL2NvbnN0cy5weXg=..0000000000000000000000000000000000000000
--- a/tests/run/consts.pyx
+++ /dev/null
@@ -1,287 +0,0 @@
-import sys
-IS_PY3 = sys.version_info[0] >= 3
-
-cimport cython
-
-DEF INT_VAL = 1
-
-def _func(a,b,c):
-    return a+b+c
-
-@cython.test_fail_if_path_exists("//AddNode")
-def add():
-    """
-    >>> add() == 1+2+3+4
-    True
-    """
-    return 1+2+3+4
-
-#@cython.test_fail_if_path_exists("//AddNode")
-def add_var(a):
-    """
-    >>> add_var(10) == 1+2+10+3+4
-    True
-    """
-    return 1+2 +a+ 3+4
-
-@cython.test_fail_if_path_exists("//AddNode", "//SubNode")
-def neg():
-    """
-    >>> neg() == -1 -2 - (-3+4)
-    True
-    """
-    return -1 -2 - (-3+4)
-
-@cython.test_fail_if_path_exists("//AddNode", "//MulNode", "//DivNode")
-def long_int_mix():
-    """
-    >>> long_int_mix() == 1 + (2 * 3) // 2
-    True
-    >>> if IS_PY3: type(long_int_mix()) is int  or type(long_int_mix())
-    ... else:      type(long_int_mix()) is long or type(long_int_mix())
-    True
-    """
-    return 1L + (2 * 3L) // 2
-
-@cython.test_fail_if_path_exists("//AddNode", "//MulNode", "//DivNode")
-def char_int_mix():
-    """
-    >>> char_int_mix() == 1 + (ord(' ') * 3) // 2 + ord('A')
-    True
-    """
-    return 1L + (c' ' * 3L) // 2 + c'A'
-
-@cython.test_fail_if_path_exists("//AddNode", "//MulNode")
-def int_cast():
-    """
-    >>> int_cast() == 1 + 2 * 6000
-    True
-    """
-    return <int>(1 + 2 * 6000)
-
-@cython.test_fail_if_path_exists("//MulNode")
-def mul():
-    """
-    >>> mul() == 1*60*1000
-    True
-    """
-    return 1*60*1000
-
-@cython.test_fail_if_path_exists("//AddNode", "//MulNode")
-def arithm():
-    """
-    >>> arithm() == 9*2+3*8//6-10
-    True
-    """
-    return 9*2+3*8//6-10
-
-@cython.test_fail_if_path_exists("//AddNode", "//MulNode")
-def parameters():
-    """
-    >>> parameters() == _func(-1 -2, - (-3+4), 1*2*3)
-    True
-    """
-    return _func(-1 -2, - (-3+4), 1*2*3)
-
-#@cython.test_fail_if_path_exists("//AddNode")
-def lists():
-    """
-    >>> lists() == [1,2,3] + [4,5,6]
-    True
-    """
-    return [1,2,3] + [4,5,6]
-
-@cython.test_fail_if_path_exists("//MulNode")
-def multiplied_lists_right_len1():
-    """
-    >>> multiplied_lists_right_len1() == [1] * 5
-    True
-    """
-    return [1] * 5
-
-@cython.test_fail_if_path_exists("//MulNode")
-def multiplied_lists_right():
-    """
-    >>> multiplied_lists_right() == [1,2,3] * 5
-    True
-    """
-    return [1,2,3] * 5
-
-@cython.test_fail_if_path_exists("//MulNode")
-def multiplied_lists_left():
-    """
-    >>> multiplied_lists_left() == [1,2,3] * 5
-    True
-    """
-    return 5 * [1,2,3]
-
-@cython.test_fail_if_path_exists("//MulNode")
-def multiplied_lists_neg():
-    """
-    >>> multiplied_lists_neg() == [1,2,3] * -5
-    True
-    """
-    return [1,2,3] * -5
-
-@cython.test_fail_if_path_exists("//MulNode")
-def multiplied_lists_nonconst(x):
-    """
-    >>> multiplied_lists_nonconst(5) == [1,2,3] * 5
-    True
-    >>> multiplied_lists_nonconst(-5) == [1,2,3] * -5
-    True
-    >>> multiplied_lists_nonconst(0) == [1,2,3] * 0
-    True
-
-    >>> try: [1,2,3] * 'abc'
-    ... except TypeError: pass
-    >>> try: multiplied_nonconst_tuple_arg('abc')
-    ... except TypeError: pass
-    >>> try: [1,2,3] * 1.0
-    ... except TypeError: pass
-    >>> try: multiplied_nonconst_tuple_arg(1.0)
-    ... except TypeError: pass
-    """
-    return [1,2,3] * x
-
-@cython.test_assert_path_exists("//MulNode")
-def multiplied_lists_nonconst_left(x):
-    """
-    >>> multiplied_lists_nonconst_left(5) == 5 * [1,2,3]
-    True
-    >>> multiplied_lists_nonconst_left(-5) == -5 * [1,2,3]
-    True
-    >>> multiplied_lists_nonconst_left(0) == 0 * [1,2,3]
-    True
-    """
-    return x * [1,2,3]
-
-
-@cython.test_fail_if_path_exists("//MulNode")
-def multiplied_nonconst_list_const_int(x):
-    """
-    >>> multiplied_nonconst_list_const_int(2)
-    [1, 2, 3, 1, 2, 3]
-    """
-    return [1,x,3] * 2
-
-
-@cython.test_fail_if_path_exists("//MulNode//ListNode")
-def multiplied_lists_nonconst_expression(x):
-    """
-    >>> multiplied_lists_nonconst_expression(5) == [1,2,3] * (5 * 2)
-    True
-    >>> multiplied_lists_nonconst_expression(-5) == [1,2,3] * (-5 * 2)
-    True
-    >>> multiplied_lists_nonconst_expression(0) == [1,2,3] * (0 * 2)
-    True
-    """
-    return [1,2,3] * (x*2)
-
-cdef side_effect(int x):
-    print x
-    return x
-
-@cython.test_fail_if_path_exists("//MulNode")
-def multiplied_lists_with_side_effects():
-    """
-    >>> multiplied_lists_with_side_effects() == [1,2,3] * 5
-    1
-    2
-    3
-    True
-    """
-    return [side_effect(1), side_effect(2), side_effect(3)] * 5
-
-@cython.test_fail_if_path_exists("//MulNode")
-def multiplied_lists_nonconst_with_side_effects(x):
-    """
-    >>> multiplied_lists_nonconst_with_side_effects(5) == [1,2,3] * 5
-    1
-    2
-    3
-    True
-    """
-    return [side_effect(1), side_effect(2), side_effect(3)] * x
-
-@cython.test_fail_if_path_exists("//MulNode")
-def multiplied_nonconst_tuple_arg(x):
-    """
-    >>> multiplied_nonconst_tuple_arg(5) == (1,2) * 5
-    True
-    >>> multiplied_nonconst_tuple_arg(-5) == (1,2) * -5
-    True
-    >>> multiplied_nonconst_tuple_arg(0) == (1,2) * 0
-    True
-
-    >>> try: (1,2) * 'abc'
-    ... except TypeError: pass
-    >>> try: multiplied_nonconst_tuple_arg('abc')
-    ... except TypeError: pass
-    >>> try: (1,2) * 1.0
-    ... except TypeError: pass
-    >>> try: multiplied_nonconst_tuple_arg(1.0)
-    ... except TypeError: pass
-    """
-    return (1,2) * x
-
-@cython.test_fail_if_path_exists("//MulNode")
-def multiplied_nonconst_tuple_int_arg(int x):
-    """
-    >>> multiplied_nonconst_tuple_int_arg(5) == (1,2) * 5
-    True
-    """
-    return (1,2) * x
-
-@cython.test_fail_if_path_exists("//MulNode")
-def multiplied_nonconst_tuple(x):
-    """
-    >>> multiplied_nonconst_tuple(5) == (1,2) * (5+1)
-    True
-    """
-    return (1,2) * (x + 1)
-
-MULT = 5
-
-@cython.test_fail_if_path_exists("//MulNode")
-def multiplied_global_nonconst_tuple():
-    """
-    >>> multiplied_global_nonconst_tuple() == (1,2,3) * 5
-    1
-    2
-    3
-    True
-    """
-    return (side_effect(1), side_effect(2), side_effect(3)) * MULT
-
-@cython.test_fail_if_path_exists("//MulNode")
-def multiplied_const_tuple():
-    """
-    >>> multiplied_const_tuple() == (1,2) * 5
-    True
-    """
-    return (1,2) * 5
-
-@cython.test_fail_if_path_exists("//MulNode")
-def multiplied_const_tuple_len1():
-    """
-    >>> multiplied_const_tuple_len1() == (1,) * 5
-    True
-    """
-    return (1,) * 5
-
-@cython.test_fail_if_path_exists("//PrimaryCmpNode")
-def compile_time_DEF():
-    """
-    >>> compile_time_DEF()
-    (1, False, True, True, False)
-    """
-    return INT_VAL, INT_VAL == 0, INT_VAL != 0, INT_VAL == 1, INT_VAL != 1
-
-@cython.test_fail_if_path_exists("//PrimaryCmpNode")
-def cascaded_compare():
-    """
-    >>> cascaded_compare()
-    True
-    """
-    return 1 < 2 < 3 < 4
diff --git a/tests/run/cpp_forwarding_ref.pyx b/tests/run/cpp_forwarding_ref.pyx
new file mode 100644
index 0000000000000000000000000000000000000000..3c2c33d638a8f5028602752643f0e6c26482bf14_dGVzdHMvcnVuL2NwcF9mb3J3YXJkaW5nX3JlZi5weXg=
--- /dev/null
+++ b/tests/run/cpp_forwarding_ref.pyx
@@ -0,0 +1,37 @@
+# mode: run
+# tag: cpp, cpp11
+
+from libcpp.utility cimport move
+
+
+cdef extern from *:
+    """
+    #include <utility>
+
+    const char* f(int& x) {
+        (void) x;
+        return "lvalue-ref";
+    }
+
+    const char* f(int&& x) {
+        (void) x;
+        return "rvalue-ref";
+    }
+
+    template <typename T>
+    const char* foo(T&& x)
+    {
+        return f(std::forward<T>(x));
+    }
+    """
+    const char* foo[T](T&& x)
+
+
+def test_forwarding_ref():
+    """
+    >>> test_forwarding_ref()
+    """
+    cdef int x = 1
+    assert foo(x) == b"lvalue-ref"
+    assert foo(<int>(1)) == b"rvalue-ref"
+    assert foo(move(x)) == b"rvalue-ref"
diff --git a/tests/run/cython3.pyx b/tests/run/cython3.pyx
index cb011b016afcc3a3d59d9c4f1b3345bb2dbb205d_dGVzdHMvcnVuL2N5dGhvbjMucHl4..3c2c33d638a8f5028602752643f0e6c26482bf14_dGVzdHMvcnVuL2N5dGhvbjMucHl4 100644
--- a/tests/run/cython3.pyx
+++ b/tests/run/cython3.pyx
@@ -16,6 +16,7 @@
 
 >>> except_as_deletes
 True
+
 >>> no_match_does_not_touch_target
 True
 """
@@ -25,6 +26,7 @@
 if not IS_PY2:
     __doc__ = __doc__.replace(" u'", " '")
 
+
 def locals_function(a, b=2):
     x = 'abc'
     return locals()
@@ -352,7 +354,7 @@
 
 
 def non_ascii_unprefixed_str():
-    u"""
+    """
     >>> s = non_ascii_unprefixed_str()
     >>> isinstance(s, bytes)
     False
@@ -365,7 +367,7 @@
 
 
 def non_ascii_raw_str():
-    u"""
+    """
     >>> s = non_ascii_raw_str()
     >>> isinstance(s, bytes)
     False
@@ -378,7 +380,7 @@
 
 
 def non_ascii_raw_prefixed_unicode():
-    u"""
+    """
     >>> s = non_ascii_raw_prefixed_unicode()
     >>> isinstance(s, bytes)
     False
@@ -616,5 +618,5 @@
     >>> len(annotation_syntax.__annotations__)
     5
     >>> print(annotation_syntax.__annotations__['a'])
-    u'test new test'
+    'test new test'
     >>> print(annotation_syntax.__annotations__['b'])
@@ -620,3 +622,3 @@
     >>> print(annotation_syntax.__annotations__['b'])
-    u'other'
+    'other'
     >>> print(annotation_syntax.__annotations__['args'])
@@ -622,3 +624,3 @@
     >>> print(annotation_syntax.__annotations__['args'])
-    u'ARGS'
+    'ARGS'
     >>> print(annotation_syntax.__annotations__['kwargs'])
@@ -624,3 +626,3 @@
     >>> print(annotation_syntax.__annotations__['kwargs'])
-    u'KWARGS'
+    'KWARGS'
     >>> print(annotation_syntax.__annotations__['return'])
@@ -626,5 +628,5 @@
     >>> print(annotation_syntax.__annotations__['return'])
-    u'ret'
+    'ret'
     """
     result : int = a + b
 
@@ -648,6 +650,6 @@
     >>> ret, arg = sorted(async_def_annotations.__annotations__.items())
     >>> print(ret[0]); print(ret[1])
     return
-    u'float'
+    'float'
     >>> print(arg[0]); print(arg[1])
     x
@@ -652,6 +654,6 @@
     >>> print(arg[0]); print(arg[1])
     x
-    u'int'
+    'int'
     """
     return float(x)
 
diff --git a/tests/run/decorators_T593.pyx b/tests/run/decorators_T593.pyx
index cb011b016afcc3a3d59d9c4f1b3345bb2dbb205d_dGVzdHMvcnVuL2RlY29yYXRvcnNfVDU5My5weXg=..3c2c33d638a8f5028602752643f0e6c26482bf14_dGVzdHMvcnVuL2RlY29yYXRvcnNfVDU5My5weXg= 100644
--- a/tests/run/decorators_T593.pyx
+++ b/tests/run/decorators_T593.pyx
@@ -110,7 +110,7 @@
 
 class Bar(metaclass=Base):
    """
-   >>> [n for n in Bar._order if n != "__qualname__"]
+   >>> [n for n in Bar._order if n not in {"__qualname__", "__annotations__"}]
    ['__module__', '__doc__', 'bar']
    """
    @property
diff --git a/tests/run/embedsignatures.pyx b/tests/run/embedsignatures.pyx
index cb011b016afcc3a3d59d9c4f1b3345bb2dbb205d_dGVzdHMvcnVuL2VtYmVkc2lnbmF0dXJlcy5weXg=..3c2c33d638a8f5028602752643f0e6c26482bf14_dGVzdHMvcnVuL2VtYmVkc2lnbmF0dXJlcy5weXg= 100644
--- a/tests/run/embedsignatures.pyx
+++ b/tests/run/embedsignatures.pyx
@@ -462,7 +462,7 @@
 Foo.m05(self, a: 1 + 2j, b: +2j, c: -2j) -> complex
 
 >>> print(Foo.m06.__doc__)
-Foo.m06(self, a: 'abc', b: b'abc', c: u'abc') -> (str, bytes, unicode)
+Foo.m06(self, a: 'abc', b: b'abc', c: 'abc') -> (str, bytes, unicode)
 
 >>> print(Foo.m07.__doc__)
 Foo.m07(self, a: [1, 2, 3], b: []) -> list
diff --git a/tests/run/locals_T732.pyx b/tests/run/locals_T732.pyx
index cb011b016afcc3a3d59d9c4f1b3345bb2dbb205d_dGVzdHMvcnVuL2xvY2Fsc19UNzMyLnB5eA==..3c2c33d638a8f5028602752643f0e6c26482bf14_dGVzdHMvcnVuL2xvY2Fsc19UNzMyLnB5eA== 100644
--- a/tests/run/locals_T732.pyx
+++ b/tests/run/locals_T732.pyx
@@ -23,7 +23,7 @@
     >>> klass = test_class_locals_and_dir()
     >>> 'visible' in klass.locs and 'not_visible' not in klass.locs
     True
-    >>> [n for n in klass.names if n != "__qualname__"]
+    >>> [n for n in klass.names if n not in {"__qualname__", "__annotations__"}]
     ['__module__', 'visible']
     """
     not_visible = 1234
diff --git a/tests/run/metaclass.pyx b/tests/run/metaclass.pyx
index cb011b016afcc3a3d59d9c4f1b3345bb2dbb205d_dGVzdHMvcnVuL21ldGFjbGFzcy5weXg=..3c2c33d638a8f5028602752643f0e6c26482bf14_dGVzdHMvcnVuL21ldGFjbGFzcy5weXg= 100644
--- a/tests/run/metaclass.pyx
+++ b/tests/run/metaclass.pyx
@@ -69,7 +69,7 @@
     321
     >>> obj.metaclass_was_here
     True
-    >>> [n for n in obj._order if n != "__qualname__"]
+    >>> [n for n in obj._order if n not in {"__qualname__", "__annotations__"}]
     ['__module__', '__doc__', 'bar', 'metaclass_was_here']
     """
     bar = 321
@@ -81,7 +81,7 @@
     345
     >>> obj.metaclass_was_here
     True
-    >>> [n for n in obj._order if n != "__qualname__"]
+    >>> [n for n in obj._order if n not in {"__qualname__", "__annotations__"}]
     ['__module__', '__doc__', 'bar', 'metaclass_was_here']
     """
     bar = 345
@@ -109,7 +109,7 @@
     123
     >>> obj.bar
     321
-    >>> [n for n in obj._order if n != "__qualname__"]
+    >>> [n for n in obj._order if n not in {"__qualname__", "__annotations__"}]
     ['__module__', '__doc__', 'bar', 'foo']
     """
     bar = 321
@@ -122,7 +122,7 @@
     567
     >>> obj.bar
     321
-    >>> [n for n in obj._order if n != "__qualname__"]
+    >>> [n for n in obj._order if n not in {"__qualname__", "__annotations__"}]
     ['__module__', '__doc__', 'bar', 'foo']
     """
     bar = 321
diff --git a/tests/run/pep526_variable_annotations.py b/tests/run/pep526_variable_annotations.py
index cb011b016afcc3a3d59d9c4f1b3345bb2dbb205d_dGVzdHMvcnVuL3BlcDUyNl92YXJpYWJsZV9hbm5vdGF0aW9ucy5weQ==..3c2c33d638a8f5028602752643f0e6c26482bf14_dGVzdHMvcnVuL3BlcDUyNl92YXJpYWJsZV9hbm5vdGF0aW9ucy5weQ== 100644
--- a/tests/run/pep526_variable_annotations.py
+++ b/tests/run/pep526_variable_annotations.py
@@ -156,6 +156,8 @@
 37:19: Unknown type declaration in annotation, ignoring
 38:12: Unknown type declaration in annotation, ignoring
 39:18: Unknown type declaration in annotation, ignoring
+57:19: Unknown type declaration in annotation, ignoring
+73:11: Annotation ignored since class-level attributes must be Python objects. Were you trying to set up an instance attribute?
 73:19: Unknown type declaration in annotation, ignoring
 # FIXME: these are sort-of evaluated now, so the warning is misleading
 126:21: Unknown type declaration in annotation, ignoring
diff --git a/tests/run/pyclass_annotations_pep526.py b/tests/run/pyclass_annotations_pep526.py
new file mode 100644
index 0000000000000000000000000000000000000000..3c2c33d638a8f5028602752643f0e6c26482bf14_dGVzdHMvcnVuL3B5Y2xhc3NfYW5ub3RhdGlvbnNfcGVwNTI2LnB5
--- /dev/null
+++ b/tests/run/pyclass_annotations_pep526.py
@@ -0,0 +1,47 @@
+# cython: language_level=3
+# mode: run
+# tag: pure3.7, pep526, pep484
+
+from __future__ import annotations
+
+try:
+    from typing import ClassVar
+except ImportError:  # Py<=3.5
+    ClassVar = {int: int}
+
+
+class PyAnnotatedClass:
+    """
+    >>> PyAnnotatedClass.__annotations__["CLASS_VAR"]
+    'ClassVar[int]'
+    >>> PyAnnotatedClass.__annotations__["obj"]
+    'str'
+    >>> PyAnnotatedClass.__annotations__["literal"]
+    "'int'"
+    >>> PyAnnotatedClass.__annotations__["recurse"]
+    "'PyAnnotatedClass'"
+    >>> PyAnnotatedClass.__annotations__["default"]
+    'bool'
+    >>> PyAnnotatedClass.CLASS_VAR
+    1
+    >>> PyAnnotatedClass.default
+    False
+    >>> PyAnnotatedClass.obj
+    Traceback (most recent call last):
+      ...
+    AttributeError: type object 'PyAnnotatedClass' has no attribute 'obj'
+    """
+    CLASS_VAR: ClassVar[int] = 1
+    obj: str
+    literal: "int"
+    recurse: "PyAnnotatedClass"
+    default: bool = False
+
+
+class PyVanillaClass:
+    """
+    >>> PyVanillaClass.__annotations__
+    Traceback (most recent call last):
+      ...
+    AttributeError: type object 'PyVanillaClass' has no attribute '__annotations__'
+    """
diff --git a/tests/run/test_grammar.py b/tests/run/test_grammar.py
index cb011b016afcc3a3d59d9c4f1b3345bb2dbb205d_dGVzdHMvcnVuL3Rlc3RfZ3JhbW1hci5weQ==..3c2c33d638a8f5028602752643f0e6c26482bf14_dGVzdHMvcnVuL3Rlc3RfZ3JhbW1hci5weQ== 100644
--- a/tests/run/test_grammar.py
+++ b/tests/run/test_grammar.py
@@ -477,8 +477,7 @@
             def __init__(self, x):
                 self.x: int = x
 
-        # FIXME: implement class annotations
-        #self.assertEqual(C.__annotations__, {'_C__foo': int, 's': str})
+        self.assertEqual(C.__annotations__, {'_C__foo': 'int', 's': 'str'})
         with self.assertRaises(NameError):
             class CBad:
                 no_such_name_defined.attr: int = 0
@@ -487,7 +486,7 @@
                 x: int
                 x.y: list = []
 
-    @skip("Class annotations not implemented")
+    @skip("Not currently supported: https://github.com/cython/cython/issues/3839")
     def test_var_annot_metaclass_semantics(self):
         class CMeta(type):
             @classmethod