support arbitrarily sized typedef integral types
[cython.git] / Cython / Compiler / PyrexTypes.py
index 1ca8e4cf973527798b7beb11b773aa46c13d035d..37e1cd0446711599b630a09fb8c4a65aeaa9eb99 100755 (executable)
@@ -1,5 +1,3 @@
-
-
 #
 #   Pyrex - Types
 #
@@ -20,7 +18,7 @@ class BaseType(object):
     def cast_code(self, expr_code):
         return "((%s)%s)" % (self.declaration_code(""), expr_code)
     
-    def specalization_name(self):
+    def specialization_name(self):
         return self.declaration_code("").replace(" ", "__")
     
     def base_declaration_code(self, base_code, entity_code):
@@ -56,7 +54,6 @@ class PyrexType(BaseType):
     #  is_buffer             boolean     Is buffer access type
     #  has_attributes        boolean     Has C dot-selectable attributes
     #  default_value         string      Initial value
-    #  pymemberdef_typecode  string      Type code for PyMemberDef struct
     #
     #  declaration_code(entity_code, 
     #      for_display = 0, dll_linkage = None, pyrex = 0)
@@ -109,7 +106,6 @@ class PyrexType(BaseType):
     is_buffer = 0
     has_attributes = 0
     default_value = ""
-    pymemberdef_typecode = None
     
     def resolve(self):
         # If a typedef, returns the base type.
@@ -164,6 +160,12 @@ class PyrexType(BaseType):
         return 1
 
 
+def public_decl(base_code, dll_linkage):
+    if dll_linkage:
+        return "%s(%s)" % (dll_linkage, base_code)
+    else:
+        return base_code
+    
 def create_typedef_type(name, base_type, cname, is_external=0):
     if base_type.is_complex:
         if is_external:
@@ -172,6 +174,7 @@ def create_typedef_type(name, base_type, cname, is_external=0):
     else:
         return CTypedefType(name, base_type, cname, is_external)
 
+
 class CTypedefType(BaseType):
     #
     #  Pseudo-type defined with a ctypedef statement in a
@@ -198,18 +201,6 @@ class CTypedefType(BaseType):
         self.typedef_cname = cname
         self.typedef_base_type = base_type
         self.typedef_is_external = is_external
-        # Make typecodes in external typedefs use typesize-neutral macros
-        if is_external:
-            typecode = None
-            if base_type.is_int:
-                if base_type.signed == 0:
-                    typecode = "__Pyx_T_UNSIGNED_INT"
-                else:
-                    typecode = "__Pyx_T_SIGNED_INT"
-            elif base_type.is_float and not rank_to_type_name[base_type.rank] == "long double":
-                typecode = "__Pyx_T_FLOATING"
-            if typecode:
-                self.pymemberdef_typecode = "%s(%s)" % (typecode, cname)
     
     def resolve(self):
         return self.typedef_base_type.resolve()
@@ -228,8 +219,9 @@ class CTypedefType(BaseType):
     def cast_code(self, expr_code):
         # If self is really an array (rather than pointer), we can't cast.
         # For example, the gmp mpz_t. 
-        if self.typedef_base_type.is_ptr:
-            return self.typedef_base_type.cast_code(expr_code)
+        if self.typedef_base_type.is_array:
+            base_type = self.typedef_base_type.base_type
+            return CPtrType(base_type).cast_code(expr_code)
         else:
             return BaseType.cast_code(self, expr_code)
 
@@ -299,6 +291,7 @@ class CTypedefType(BaseType):
     def __getattr__(self, name):
         return getattr(self.typedef_base_type, name)
 
+
 class BufferType(BaseType):
     #
     #  Delegates most attribute
@@ -333,12 +326,7 @@ class BufferType(BaseType):
     def __repr__(self):
         return "<BufferType %r>" % self.base
 
-def public_decl(base, dll_linkage):
-    if dll_linkage:
-        return "%s(%s)" % (dll_linkage, base)
-    else:
-        return base
-    
+
 class PyObjectType(PyrexType):
     #
     #  Base class for all Python object types (reference-counted).
@@ -348,7 +336,6 @@ class PyObjectType(PyrexType):
     name = "object"
     is_pyobject = 1
     default_value = "0"
-    pymemberdef_typecode = "T_OBJECT"
     buffer_defaults = None
     is_extern = False
     is_subclassed = False
@@ -369,9 +356,11 @@ class PyObjectType(PyrexType):
     def declaration_code(self, entity_code, 
             for_display = 0, dll_linkage = None, pyrex = 0):
         if pyrex or for_display:
-            return self.base_declaration_code("object", entity_code)
+            base_code = "object"
         else:
-            return "%s *%s" % (public_decl("PyObject", dll_linkage), entity_code)
+            base_code = public_decl("PyObject", dll_linkage)
+            entity_code = "*%s" % entity_code
+        return self.base_declaration_code(base_code, entity_code)
 
     def as_pyobject(self, cname):
         if (not self.is_complete()) or self.is_extension_type:
@@ -450,9 +439,11 @@ class BuiltinObjectType(PyObjectType):
     def declaration_code(self, entity_code, 
             for_display = 0, dll_linkage = None, pyrex = 0):
         if pyrex or for_display:
-            return self.base_declaration_code(self.name, entity_code)
+            base_code = self.name
         else:
-            return "%s *%s" % (public_decl("PyObject", dll_linkage), entity_code)
+            base_code = public_decl("PyObject", dll_linkage)
+            entity_code = "*%s" % entity_code
+        return self.base_declaration_code(base_code, entity_code)
 
 
 class PyExtensionType(PyObjectType):
@@ -517,20 +508,29 @@ class PyExtensionType(PyObjectType):
         # know which module it's defined in, it will be imported.
         return self.typeobj_cname is None and self.module_name is not None
     
+    def assignable_from(self, src_type):
+        if self == src_type:
+            return True
+        if isinstance(src_type, PyExtensionType):
+            if src_type.base_type is not None:
+                return self.assignable_from(src_type.base_type)
+        return False
+
     def declaration_code(self, entity_code, 
             for_display = 0, dll_linkage = None, pyrex = 0, deref = 0):
         if pyrex or for_display:
-            return self.base_declaration_code(self.name, entity_code)
+            base_code = self.name
         else:
             if self.typedef_flag:
-                base_format = "%s"
+                objstruct = self.objstruct_cname
             else:
-                base_format = "struct %s"
-            base = public_decl(base_format % self.objstruct_cname, dll_linkage)
+                objstruct = "struct %s" % self.objstruct_cname
+            base_code = public_decl(objstruct, dll_linkage)
             if deref:
-                return "%s %s" % (base,  entity_code)
+                assert not entity_code
             else:
-                return "%s *%s" % (base,  entity_code)
+                entity_code = "*%s" % entity_code
+        return self.base_declaration_code(base_code, entity_code)
 
     def type_test_code(self, py_arg, notnone=False):
 
@@ -590,6 +590,10 @@ class CType(PyrexType):
 
 
 class CVoidType(CType):
+    #
+    #   C "void" type
+    #
+
     is_void = 1
     
     def __repr__(self):
@@ -597,8 +601,11 @@ class CVoidType(CType):
     
     def declaration_code(self, entity_code, 
             for_display = 0, dll_linkage = None, pyrex = 0):
-        base = public_decl("void", dll_linkage)
-        return self.base_declaration_code(base, entity_code)
+        if pyrex or for_display:
+            base_code = "void"
+        else:
+            base_code = public_decl("void", dll_linkage)
+        return self.base_declaration_code(base_code, entity_code)
     
     def is_complete(self):
         return 0
@@ -617,10 +624,9 @@ class CNumericType(CType):
     
     sign_words = ("unsigned ", "", "signed ")
     
-    def __init__(self, rank, signed = 1, pymemberdef_typecode = None):
+    def __init__(self, rank, signed = 1):
         self.rank = rank
         self.signed = signed
-        self.pymemberdef_typecode = pymemberdef_typecode
     
     def sign_and_name(self):
         s = self.sign_words[self.signed]
@@ -632,10 +638,12 @@ class CNumericType(CType):
     
     def declaration_code(self, entity_code, 
             for_display = 0, dll_linkage = None, pyrex = 0):
-        base = public_decl(self.sign_and_name(), dll_linkage)
-        if for_display:
-            base = base.replace('PY_LONG_LONG', 'long long')
-        return self.base_declaration_code(base,  entity_code)
+        type_name = self.sign_and_name()
+        if pyrex or for_display:
+            base_code = type_name.replace('PY_LONG_LONG', 'long long')
+        else:
+            base_code = public_decl(type_name, dll_linkage)
+        return self.base_declaration_code(base_code, entity_code)
 
 
 type_conversion_predeclarations = ""
@@ -713,8 +721,8 @@ static CYTHON_INLINE %(type)s __Pyx_PyInt_from_py_%(TypeName)s(PyObject *);
 """,
 impl="""
 static CYTHON_INLINE %(type)s __Pyx_PyInt_from_py_%(TypeName)s(PyObject* x) {
-    const %(type)s neg_one = (%(type)s)-1, const_zero = 0;
-    const int is_unsigned = neg_one > const_zero;
+    const %(type)s neg_one = (%(type)s)-1, const_zero = (%(type)s)0;
+    const int is_unsigned = const_zero < neg_one;
     if (sizeof(%(type)s) == sizeof(char)) {
         if (is_unsigned)
             return (%(type)s)__Pyx_PyInt_AsUnsignedChar(x);
@@ -740,17 +748,28 @@ static CYTHON_INLINE %(type)s __Pyx_PyInt_from_py_%(TypeName)s(PyObject* x) {
             return (%(type)s)__Pyx_PyInt_AsUnsignedLongLong(x);
         else
             return (%(type)s)__Pyx_PyInt_AsSignedLongLong(x);
-#if 0
-    } else if (sizeof(%(type)s) > sizeof(short) &&
-               sizeof(%(type)s) < sizeof(int)) { /*  __int32 ILP64 ? */
-        if (is_unsigned)
-            return (%(type)s)__Pyx_PyInt_AsUnsignedInt(x);
-        else
-            return (%(type)s)__Pyx_PyInt_AsSignedInt(x);
-#endif
+    }  else {
+        %(type)s val;
+        PyObject *v = __Pyx_PyNumber_Int(x);
+        #if PY_VERSION_HEX < 0x03000000
+        if (likely(v) && !PyLong_Check(v)) {
+            PyObject *tmp = v;
+            v = PyNumber_Long(tmp);
+            Py_DECREF(tmp);
+        }
+        #endif
+        if (likely(v)) {
+            int one = 1; int is_little = (int)*(unsigned char *)&one;
+            unsigned char *bytes = (unsigned char *)&val;
+            int ret = _PyLong_AsByteArray((PyLongObject *)v,
+                                          bytes, sizeof(val),
+                                          is_little, !is_unsigned);
+            Py_DECREF(v);
+            if (likely(!ret))
+                return val;
+        }
+        return (%(type)s)-1;
     }
-    PyErr_SetString(PyExc_TypeError, "%(TypeName)s");
-    return (%(type)s)-1;
 }
 """)
 
@@ -760,20 +779,27 @@ static CYTHON_INLINE PyObject *__Pyx_PyInt_to_py_%(TypeName)s(%(type)s);
 """,
 impl="""
 static CYTHON_INLINE PyObject *__Pyx_PyInt_to_py_%(TypeName)s(%(type)s val) {
-    const %(type)s neg_one = (%(type)s)-1, const_zero = 0;
-    const int is_unsigned = neg_one > const_zero;
-    if (sizeof(%(type)s) <  sizeof(long)) {
+    const %(type)s neg_one = (%(type)s)-1, const_zero = (%(type)s)0;
+    const int is_unsigned = const_zero < neg_one;
+    if ((sizeof(%(type)s) == sizeof(char))  ||
+        (sizeof(%(type)s) == sizeof(short))) {
         return PyInt_FromLong((long)val);
-    } else if (sizeof(%(type)s) == sizeof(long)) {
+    } else if ((sizeof(%(type)s) == sizeof(int)) ||
+               (sizeof(%(type)s) == sizeof(long))) {
         if (is_unsigned)
             return PyLong_FromUnsignedLong((unsigned long)val);
         else
             return PyInt_FromLong((long)val);
-    } else { /* (sizeof(%(type)s) > sizeof(long)) */
+    } else if (sizeof(%(type)s) == sizeof(PY_LONG_LONG)) {
         if (is_unsigned)
             return PyLong_FromUnsignedLongLong((unsigned PY_LONG_LONG)val);
         else
             return PyLong_FromLongLong((PY_LONG_LONG)val);
+    } else {
+        int one = 1; int little = (int)*(unsigned char *)&one;
+        unsigned char *bytes = (unsigned char *)&val;
+        return _PyLong_FromByteArray(bytes, sizeof(%(type)s), 
+                                     little, !is_unsigned);
     }
 }
 """)
@@ -782,27 +808,40 @@ class CIntType(CNumericType):
 
     is_int = 1
     typedef_flag = 0
-    to_py_function = "PyInt_FromLong"
-    from_py_function = "__Pyx_PyInt_AsInt"
+    to_py_function = None
+    from_py_function = None
     exception_value = -1
 
-    def __init__(self, rank, signed, pymemberdef_typecode = None, is_returncode = 0):
-        CNumericType.__init__(self, rank, signed, pymemberdef_typecode)
-        self.is_returncode = is_returncode
-        if self.from_py_function == "__Pyx_PyInt_AsInt":
-            self.from_py_function = self.get_type_conversion()
-
-    def get_type_conversion(self):
-        ctype = self.declaration_code('')
-        bits = ctype.split(" ", 1)
-        if len(bits) == 1:
-            sign_word, type_name = "", bits[0]
+    def __init__(self, rank, signed = 1):
+        CNumericType.__init__(self, rank, signed)
+        if self.to_py_function is None:
+            self.to_py_function = self.get_to_py_type_conversion()
+        if self.from_py_function is None:
+            self.from_py_function = self.get_from_py_type_conversion()
+
+    def get_to_py_type_conversion(self):
+        if self.rank < list(rank_to_type_name).index('int'):
+            # This assumes sizeof(short) < sizeof(int)
+            return "PyInt_FromLong"
         else:
-            sign_word, type_name = bits
-        type_name = type_name.replace("PY_LONG_LONG","long long")
-        SignWord  = sign_word.title()
-        TypeName  = type_name.title().replace(" ", "")
-        if "Long" in TypeName:
+            # Py{Int|Long}_From[Unsigned]Long[Long]
+            Prefix = "Int"
+            SignWord = ""
+            TypeName = "Long"
+            if not self.signed:
+                Prefix = "Long"
+                SignWord = "Unsigned"
+            if self.rank >= list(rank_to_type_name).index('PY_LONG_LONG'):
+                Prefix = "Long"
+                TypeName = "LongLong"
+            return "Py%s_From%s%s" % (Prefix, SignWord, TypeName)
+
+    def get_from_py_type_conversion(self):
+        type_name = rank_to_type_name[self.rank]
+        type_name = type_name.replace("PY_LONG_LONG", "long long")
+        TypeName = type_name.title().replace(" ", "")
+        SignWord = self.sign_words[self.signed].strip().title()
+        if self.rank >= list(rank_to_type_name).index('long'):
             utility_code = c_long_from_py_function
         else:
             utility_code = c_int_from_py_function
@@ -816,16 +855,6 @@ class CIntType(CNumericType):
         return src_type.is_int or src_type.is_enum or src_type is error_type
 
 
-class CBIntType(CIntType):
-
-    to_py_function = "__Pyx_PyBool_FromLong"
-    from_py_function = "__Pyx_PyObject_IsTrue"
-    exception_check = 0
-
-    def __repr__(self):
-        return "<CNumericType bint>"
-
-
 class CAnonEnumType(CIntType):
 
     is_enum = 1
@@ -834,30 +863,34 @@ class CAnonEnumType(CIntType):
         return 'int'
 
 
-class CUIntType(CIntType):
-
-    to_py_function = "PyLong_FromUnsignedLong"
-    exception_value = -1
-
+class CReturnCodeType(CIntType):
 
-class CLongType(CIntType):
+    is_returncode = 1
 
-    to_py_function = "PyInt_FromLong"
 
+class CBIntType(CIntType):
 
-class CULongType(CUIntType):
-
-    to_py_function = "PyLong_FromUnsignedLong"
+    to_py_function = "__Pyx_PyBool_FromLong"
+    from_py_function = "__Pyx_PyObject_IsTrue"
+    exception_check = 0
 
+    def __repr__(self):
+        return "<CNumericType bint>"
 
-class CLongLongType(CIntType):
 
-    to_py_function = "PyLong_FromLongLong"
+class CPyUnicodeIntType(CIntType):
+    # Py_UNICODE
 
+    # Conversion from a unicode string to Py_UNICODE at runtime is not
+    # currently supported and may never be - we only convert from and
+    # to integers here.  The maximum value for a Py_UNICODE is
+    # 1114111, so PyInt_FromLong() will do just fine here.
 
-class CULongLongType(CUIntType):
+    to_py_function = "PyInt_FromLong"
+    from_py_function = "__Pyx_PyInt_AsPy_UNICODE"
 
-    to_py_function = "PyLong_FromUnsignedLongLong"
+    def sign_and_name(self):
+        return "Py_UNICODE"
 
 
 class CPySSizeTType(CIntType):
@@ -866,16 +899,23 @@ class CPySSizeTType(CIntType):
     from_py_function = "__Pyx_PyIndex_AsSsize_t"
 
     def sign_and_name(self):
-        return rank_to_type_name[self.rank]
+        return "Py_ssize_t"
 
+class CSSizeTType(CIntType):
 
-class CSizeTType(CUIntType):
+    to_py_function = "PyInt_FromSsize_t"
+    from_py_function = "PyInt_AsSsize_t"
+
+    def sign_and_name(self):
+        return "ssize_t"
+
+class CSizeTType(CIntType):
 
     to_py_function = "__Pyx_PyInt_FromSize_t"
     from_py_function = "__Pyx_PyInt_AsSize_t"
 
     def sign_and_name(self):
-        return rank_to_type_name[self.rank]
+        return "size_t"
 
 
 class CFloatType(CNumericType):
@@ -886,8 +926,8 @@ class CFloatType(CNumericType):
 
     exception_value = -1
     
-    def __init__(self, rank, pymemberdef_typecode = None, math_h_modifier = ''):
-        CNumericType.__init__(self, rank, 1, pymemberdef_typecode)
+    def __init__(self, rank, math_h_modifier = ''):
+        CNumericType.__init__(self, rank, 1)
         self.math_h_modifier = math_h_modifier
     
     def assignable_from_resolved_type(self, src_type):
@@ -907,16 +947,16 @@ class CComplexType(CNumericType):
         if real_type.is_typedef and real_type.typedef_is_external:
             # The below is not actually used: Coercions are currently disabled
             # so that complex types of external types can not be created
-            self.funcsuffix = "_%s" % real_type.specalization_name()
+            self.funcsuffix = "_%s" % real_type.specialization_name()
         elif hasattr(real_type, 'math_h_modifier'):
             self.funcsuffix = real_type.math_h_modifier
         else:
-            self.funcsuffix = "_%s" % real_type.specalization_name()
+            self.funcsuffix = "_%s" % real_type.specialization_name()
     
         self.real_type = real_type
         CNumericType.__init__(self, real_type.rank + 0.5, real_type.signed)
         self.binops = {}
-        self.from_parts = "%s_from_parts" % self.specalization_name()
+        self.from_parts = "%s_from_parts" % self.specialization_name()
         self.default_value = "%s(0, 0)" % self.from_parts
 
     def __eq__(self, other):
@@ -944,15 +984,17 @@ class CComplexType(CNumericType):
 
     def declaration_code(self, entity_code, 
             for_display = 0, dll_linkage = None, pyrex = 0):
-        if for_display:
-            base = public_decl(self.real_type.sign_and_name() + " complex", dll_linkage)
+        if pyrex or for_display:
+            real_code = self.real_type.declaration_code("", for_display, dll_linkage, pyrex)
+            base_code = "%s complex" % real_code
         else:
-            base = public_decl(self.sign_and_name(), dll_linkage)
-        return self.base_declaration_code(base entity_code)
+            base_code = public_decl(self.sign_and_name(), dll_linkage)
+        return self.base_declaration_code(base_code, entity_code)
 
     def sign_and_name(self):
-        real_type_name = self.real_type.specalization_name()
+        real_type_name = self.real_type.specialization_name()
         real_type_name = real_type_name.replace('long__double','long_double')
+        real_type_name = real_type_name.replace('PY_LONG_LONG','long_long')
         return Naming.type_prefix + real_type_name + "_complex"
     
     def assignable_from(self, src_type):
@@ -994,7 +1036,7 @@ class CComplexType(CNumericType):
         env.use_utility_code(complex_real_imag_utility_code)
         for utility_code in (complex_type_utility_code,
                              complex_from_parts_utility_code,
-                             complex_arithmatic_utility_code):
+                             complex_arithmetic_utility_code):
             env.use_utility_code(
                 utility_code.specialize(
                     self, 
@@ -1017,7 +1059,7 @@ class CComplexType(CNumericType):
                     self, 
                     real_type = self.real_type.declaration_code(''),
                     m = self.funcsuffix))
-        self.from_py_function = "__Pyx_PyComplex_As_" + self.specalization_name()
+        self.from_py_function = "__Pyx_PyComplex_As_" + self.specialization_name()
         return True
     
     def lookup_op(self, nargs, op):
@@ -1163,7 +1205,7 @@ static %(type)s __Pyx_PyComplex_As_%(type_name)s(PyObject* o) {
 }
 """)
 
-complex_arithmatic_utility_code = UtilityCode(
+complex_arithmetic_utility_code = UtilityCode(
 proto="""
 #if CYTHON_CCOMPLEX
     #define __Pyx_c_eq%(m)s(a, b)   ((a)==(b))
@@ -1353,43 +1395,40 @@ class CNullPtrType(CPtrType):
     is_null_ptr = 1
     
 
-class CReferenceType(CType):
+class CReferenceType(BaseType):
 
     is_reference = 1
 
     def __init__(self, base_type):
-        self.base_type = base_type
+        self.ref_base_type = base_type
 
     def __repr__(self):
-        return "<CReferenceType %s>" % repr(self.base_type)
-
-    def same_as_resolved_type(self, other_type):
-        return other_type.is_reference and self.base_type.same_as(other_type.base_type)
+        return "<CReferenceType %s>" % repr(self.ref_base_type)
     
+    def __str__(self):
+        return "%s &" % self.ref_base_type
+
+    def as_argument_type(self):
+        return self
+
     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.base_type.declaration_code(
+        return self.ref_base_type.declaration_code(
             "&%s" % entity_code,
             for_display, dll_linkage, pyrex)
     
-    def assignable_from_resolved_type(self, other_type):
-        if other_type is error_type:
-            return 1
-        elif other_type.is_reference and self.base_type == other_type.base_type:
-            return 1
-        elif other_type == self.base_type:
-            return 1
-        else: #for now
-            return 0
-        
     def specialize(self, values):
-        base_type = self.base_type.specialize(values)
-        if base_type == self.base_type:
+        base_type = self.ref_base_type.specialize(values)
+        if base_type == self.ref_base_type:
             return self
         else:
             return CReferenceType(base_type)
 
+    def __getattr__(self, name):
+        return getattr(self.ref_base_type, name)
+
+
 class CFuncType(CType):
     #  return_type      CType
     #  args             [CFuncTypeArg]
@@ -1648,7 +1687,12 @@ class CFuncTypeArg(object):
     #  cname      string
     #  type       PyrexType
     #  pos        source file position
-    
+
+    # FIXME: is this the right setup? should None be allowed here?
+    not_none = False
+    or_none = False
+    accept_none = True
+
     def __init__(self, name, type, pos, cname=None):
         self.name = name
         if cname is not None:
@@ -1657,7 +1701,6 @@ class CFuncTypeArg(object):
             self.cname = Naming.var_prefix + name
         self.type = type
         self.pos = pos
-        self.not_none = False
         self.needs_type_test = False # TODO: should these defaults be set in analyse_types()?
     
     def __repr__(self):
@@ -1758,16 +1801,15 @@ class CStructOrUnionType(CType):
 
     def declaration_code(self, entity_code, 
             for_display = 0, dll_linkage = None, pyrex = 0):
-        if pyrex:
-            return self.base_declaration_code(self.name, entity_code)
+        if pyrex or for_display:
+            base_code = self.name
         else:
-            if for_display:
-                base = self.name
-            elif self.typedef_flag:
-                base = self.cname
+            if self.typedef_flag:
+                base_code = self.cname
             else:
-                base = "%s %s" % (self.kind, self.cname)
-            return self.base_declaration_code(public_decl(base, dll_linkage), entity_code)
+                base_code = "%s %s" % (self.kind, self.cname)
+            base_code = public_decl(base_code, dll_linkage)
+        return self.base_declaration_code(base_code, entity_code)
 
     def __eq__(self, other):
         try:
@@ -1857,20 +1899,24 @@ class CppClassType(CType):
             specialized.namespace = self.namespace.specialize(values)
         return specialized
 
-    def declaration_code(self, entity_code, for_display = 0, dll_linkage = None, pyrex = 0):
+    def declaration_code(self, entity_code,
+            for_display = 0, dll_linkage = None, pyrex = 0):
         if self.templates:
-            template_strings = [param.declaration_code('', for_display, pyrex) for param in self.templates]
-            templates = "<" + ",".join(template_strings) + ">"
+            template_strings = [param.declaration_code('', for_display, None, pyrex)
+                                for param in self.templates]
+            templates = "<%s>" % ",".join(template_strings)
+            if templates[-2:] == ">>":
+                templates = templates[:-2] + "> >"
         else:
             templates = ""
-        if for_display or pyrex:
-            name = self.name
+        if pyrex or for_display:
+            base_code = "%s%s" % (self.name, templates)
         else:
+            base_code = "%s%s" % (self.cname, templates)
             if self.namespace is not None:
-                name = "%s::%s" % (self.namespace.declaration_code(''), self.cname)
-            else:
-                name = self.cname
-        return "%s%s %s" % (name, templates, entity_code)
+                base_code = "%s::%s" % (self.namespace.declaration_code(''), base_code)
+            base_code = public_decl(base_code, dll_linkage)
+        return self.base_declaration_code(base_code, entity_code)
 
     def is_subclass(self, other_type):
         # TODO(danilo): Handle templates.
@@ -1909,7 +1955,8 @@ class TemplatePlaceholderType(CType):
     def __init__(self, name):
         self.name = name
     
-    def declaration_code(self, entity_code, for_display = 0, dll_linkage = None, pyrex = 0):
+    def declaration_code(self, entity_code, 
+            for_display = 0, dll_linkage = None, pyrex = 0):
         if entity_code:
             return self.name + " " + entity_code
         else:
@@ -1962,14 +2009,15 @@ class CEnumType(CType):
     
     def declaration_code(self, entity_code, 
             for_display = 0, dll_linkage = None, pyrex = 0):
-        if pyrex:
-            return self.base_declaration_code(self.cname, entity_code)
+        if pyrex or for_display:
+            base_code = self.name
         else:
             if self.typedef_flag:
-                base = self.cname
+                base_code = self.cname
             else:
-                base = "enum %s" % self.cname
-            return self.base_declaration_code(public_decl(base, dll_linkage), entity_code)
+                base_code = "enum %s" % self.cname
+            base_code = public_decl(base_code, dll_linkage)
+        return self.base_declaration_code(base_code, entity_code)
 
 
 class CStringType(object):
@@ -1978,8 +2026,8 @@ class CStringType(object):
     is_string = 1
     is_unicode = 0
     
-    to_py_function = "__Pyx_PyBytes_FromString"
-    from_py_function = "__Pyx_PyBytes_AsString"
+    to_py_function = "PyBytes_FromString"
+    from_py_function = "PyBytes_AsString"
     exception_value = "NULL"
 
     def literal_code(self, value):
@@ -1990,7 +2038,6 @@ class CStringType(object):
 class CUTF8CharArrayType(CStringType, CArrayType):
     #  C 'char []' type.
     
-    pymemberdef_typecode = "T_STRING_INPLACE"
     is_unicode = 1
     
     to_py_function = "PyUnicode_DecodeUTF8"
@@ -2002,8 +2049,6 @@ class CUTF8CharArrayType(CStringType, CArrayType):
 class CCharArrayType(CStringType, CArrayType):
     #  C 'char []' type.
     
-    pymemberdef_typecode = "T_STRING_INPLACE"
-    
     def __init__(self, size):
         CArrayType.__init__(self, c_char_type, size)
     
@@ -2011,8 +2056,6 @@ class CCharArrayType(CStringType, CArrayType):
 class CCharPtrType(CStringType, CPtrType):
     # C 'char *' type.
     
-    pymemberdef_typecode = "T_STRING"
-    
     def __init__(self):
         CPtrType.__init__(self, c_char_type)
 
@@ -2020,8 +2063,6 @@ class CCharPtrType(CStringType, CPtrType):
 class CUCharPtrType(CStringType, CPtrType):
     # C 'unsigned char *' type.
     
-    pymemberdef_typecode = "T_STRING"
-    
     to_py_function = "__Pyx_PyBytes_FromUString"
     from_py_function = "__Pyx_PyBytes_AsUString"
 
@@ -2073,61 +2114,70 @@ rank_to_type_name = (
     "short",        # 1
     "int",          # 2
     "long",         # 3
-    "Py_ssize_t",   # 4
-    "size_t",       # 5
-    "PY_LONG_LONG", # 6
-    "float",        # 7
-    "double",       # 8
-    "long double",  # 9
+    "PY_LONG_LONG", # 4
+    "float",        # 5
+    "double",       # 6
+    "long double",  # 7
 )
 
-py_object_type = PyObjectType()
-
-c_void_type =         CVoidType()
-c_void_ptr_type =     CPtrType(c_void_type)
-c_void_ptr_ptr_type = CPtrType(c_void_ptr_type)
-
-c_uchar_type =       CIntType(0, 0, "T_UBYTE")
-c_ushort_type =      CIntType(1, 0, "T_USHORT")
-c_uint_type =        CUIntType(2, 0, "T_UINT")
-c_ulong_type =       CULongType(3, 0, "T_ULONG")
-c_ulonglong_type =   CULongLongType(6, 0, "T_ULONGLONG")
-
-c_char_type =        CIntType(0, 1, "T_CHAR")
-c_short_type =       CIntType(1, 1, "T_SHORT")
-c_int_type =         CIntType(2, 1, "T_INT")
-c_long_type =        CLongType(3, 1, "T_LONG")
-c_longlong_type =    CLongLongType(6, 1, "T_LONGLONG")
-c_bint_type =        CBIntType(2, 1, "T_INT")
-
-c_schar_type =       CIntType(0, 2, "T_CHAR")
-c_sshort_type =      CIntType(1, 2, "T_SHORT")
-c_sint_type =        CIntType(2, 2, "T_INT")
-c_slong_type =       CLongType(3, 2, "T_LONG")
-c_slonglong_type =   CLongLongType(6, 2, "T_LONGLONG")
+RANK_INT  = list(rank_to_type_name).index('int')
+RANK_LONG = list(rank_to_type_name).index('long')
+UNSIGNED = 0
+SIGNED = 2
 
-c_py_ssize_t_type =  CPySSizeTType(4, 2, "T_PYSSIZET")
-c_size_t_type =      CSizeTType(5, 0, "T_SIZET")
 
-c_float_type =       CFloatType(7, "T_FLOAT", math_h_modifier='f')
-c_double_type =      CFloatType(8, "T_DOUBLE")
-c_longdouble_type =  CFloatType(9, math_h_modifier='l')
+py_object_type = PyObjectType()
 
-c_double_complex_type = CComplexType(c_double_type)
+c_void_type =        CVoidType()
+
+c_uchar_type =       CIntType(0, UNSIGNED)
+c_ushort_type =      CIntType(1, UNSIGNED)
+c_uint_type =        CIntType(2, UNSIGNED)
+c_ulong_type =       CIntType(3, UNSIGNED)
+c_ulonglong_type =   CIntType(4, UNSIGNED)
+
+c_char_type =        CIntType(0)
+c_short_type =       CIntType(1)
+c_int_type =         CIntType(2)
+c_long_type =        CIntType(3)
+c_longlong_type =    CIntType(4)
+
+c_schar_type =       CIntType(0, SIGNED)
+c_sshort_type =      CIntType(1, SIGNED)
+c_sint_type =        CIntType(2, SIGNED)
+c_slong_type =       CIntType(3, SIGNED)
+c_slonglong_type =   CIntType(4, SIGNED)
+
+c_float_type =       CFloatType(5, math_h_modifier='f')
+c_double_type =      CFloatType(6)
+c_longdouble_type =  CFloatType(7, math_h_modifier='l')
+
+c_float_complex_type =      CComplexType(c_float_type)
+c_double_complex_type =     CComplexType(c_double_type)
+c_longdouble_complex_type = CComplexType(c_longdouble_type)
+
+c_anon_enum_type =   CAnonEnumType(-1)
+c_returncode_type =  CReturnCodeType(RANK_INT)
+c_bint_type =        CBIntType(RANK_INT)
+c_py_unicode_type =  CPyUnicodeIntType(RANK_INT-0.5, UNSIGNED)
+c_py_ssize_t_type =  CPySSizeTType(RANK_LONG+0.5, SIGNED)
+c_ssize_t_type =     CSSizeTType(RANK_LONG+0.5, SIGNED)
+c_size_t_type =      CSizeTType(RANK_LONG+0.5, UNSIGNED)
 
 c_null_ptr_type =     CNullPtrType(c_void_type)
+c_void_ptr_type =     CPtrType(c_void_type)
+c_void_ptr_ptr_type = CPtrType(c_void_ptr_type)
 c_char_array_type =   CCharArrayType(None)
 c_char_ptr_type =     CCharPtrType()
 c_uchar_ptr_type =    CUCharPtrType()
 c_utf8_char_array_type = CUTF8CharArrayType(None)
 c_char_ptr_ptr_type = CPtrType(c_char_ptr_type)
 c_int_ptr_type =      CPtrType(c_int_type)
+c_py_unicode_ptr_type = CPtrType(c_py_unicode_type)
 c_py_ssize_t_ptr_type =  CPtrType(c_py_ssize_t_type)
+c_ssize_t_ptr_type =  CPtrType(c_ssize_t_type)
 c_size_t_ptr_type =  CPtrType(c_size_t_type)
 
-c_returncode_type =   CIntType(2, 1, "T_INT", is_returncode = 1)
-
-c_anon_enum_type =    CAnonEnumType(-1, 1)
 
 # the Py_buffer type is defined in Builtin.py
 c_py_buffer_type = CStructOrUnionType("Py_buffer", "struct", None, 1, "Py_buffer")
@@ -2136,99 +2186,57 @@ c_py_buffer_ptr_type = CPtrType(c_py_buffer_type)
 error_type =    ErrorType()
 unspecified_type = UnspecifiedType()
 
-sign_and_rank_to_type = {
-    #(signed, rank)
-    (0, 0): c_uchar_type,
-    (0, 1): c_ushort_type,
-    (0, 2): c_uint_type,
-    (0, 3): c_ulong_type,
-    (0, 6): c_ulonglong_type,
-
-    (1, 0): c_char_type,
-    (1, 1): c_short_type,
-    (1, 2): c_int_type,
-    (1, 3): c_long_type,
-    (1, 6): c_longlong_type,
-
-    (2, 0): c_schar_type,
-    (2, 1): c_sshort_type,
-    (2, 2): c_sint_type,
-    (2, 3): c_slong_type,
-    (2, 6): c_slonglong_type,
-
-    (0, 4): c_py_ssize_t_type,
-    (1, 4): c_py_ssize_t_type,
-    (2, 4): c_py_ssize_t_type,
-    (0, 5): c_size_t_type,
-    (1, 5): c_size_t_type,
-    (2, 5): c_size_t_type,
-
-    (1, 7): c_float_type,
-    (1, 8): c_double_type,
-    (1, 9): c_longdouble_type,
-# In case we're mixing unsigned ints and floats...
-    (0, 7): c_float_type,
-    (0, 8): c_double_type,
-    (0, 9): c_longdouble_type,
-}
-
 modifiers_and_name_to_type = {
-    #(signed, longness, name)
-    (0, 0, "char"): c_uchar_type,
+    #(signed, longness, name) : type
+    (0,  0, "char"): c_uchar_type,
+    (1,  0, "char"): c_char_type,
+    (2,  0, "char"): c_schar_type,
+
     (0, -1, "int"): c_ushort_type,
-    (0, 0, "int"): c_uint_type,
-    (0, 1, "int"): c_ulong_type,
-    (0, 2, "int"): c_ulonglong_type,
-    (1, 0, "void"): c_void_type,
-    (1, 0, "char"): c_char_type,
+    (0,  0, "int"): c_uint_type,
+    (0,  1, "int"): c_ulong_type,
+    (0,  2, "int"): c_ulonglong_type,
+
     (1, -1, "int"): c_short_type,
-    (1, 0, "int"): c_int_type,
-    (1, 1, "int"): c_long_type,
-    (1, 2, "int"): c_longlong_type,
-    (1, 0, "float"): c_float_type,
-    (1, 0, "double"): c_double_type,
-    (1, 1, "double"): c_longdouble_type,
-    (1, 0, "object"): py_object_type,
-    (1, 0, "bint"): c_bint_type,
-    (2, 0, "char"): c_schar_type,
+    (1,  0, "int"): c_int_type,
+    (1,  1, "int"): c_long_type,
+    (1,  2, "int"): c_longlong_type,
+
     (2, -1, "int"): c_sshort_type,
-    (2, 0, "int"): c_sint_type,
-    (2, 1, "int"): c_slong_type,
-    (2, 2, "int"): c_slonglong_type,
+    (2,  0, "int"): c_sint_type,
+    (2,  1, "int"): c_slong_type,
+    (2,  2, "int"): c_slonglong_type,
 
-    (2, 0, "Py_ssize_t"): c_py_ssize_t_type,
-    (0, 0, "size_t") : c_size_t_type,
+    (1,  0, "float"):  c_float_type,
+    (1,  0, "double"): c_double_type,
+    (1,  1, "double"): c_longdouble_type,
 
-    (1, 0, "long"): c_long_type,
-    (1, 0, "short"): c_short_type,
-    (1, 0, "longlong"): c_longlong_type,
-    (1, 0, "bint"): c_bint_type,
-}
+    (1,  0, "complex"):  c_float_complex_type,
+    (1,  0, "floatcomplex"):  c_float_complex_type,
+    (1,  0, "doublecomplex"): c_double_complex_type,
+    (1,  1, "doublecomplex"): c_longdouble_complex_type,
 
-def is_promotion0(src_type, dst_type):
-    if src_type.is_numeric and dst_type.is_numeric:
-        if src_type.is_int and dst_type.is_int:
-            if src_type.is_enum: 
-                return True
-            elif src_type.signed:
-                return dst_type.signed and src_type.rank <= dst_type.rank
-            elif dst_type.signed: # and not src_type.signed
-                src_type.rank < dst_type.rank
-            else:
-                return src_type.rank <= dst_type.rank
-        elif src_type.is_float and dst_type.is_float:
-            return src_type.rank <= dst_type.rank
-        else:
-            return False
-    else:
-        return False
+    #
+    (1,  0, "void"): c_void_type,
+
+    (1,  0, "bint"):       c_bint_type,
+    (0,  0, "Py_UNICODE"): c_py_unicode_type,
+    (2,  0, "Py_ssize_t"): c_py_ssize_t_type,
+    (2,  0, "ssize_t") :   c_ssize_t_type,
+    (0,  0, "size_t") :    c_size_t_type,
+
+    (1,  0, "object"): py_object_type,
+}
 
 def is_promotion(src_type, dst_type):
     # It's hard to find a hard definition of promotion, but empirical
     # evidence suggests that the below is all that's allowed. 
     if src_type.is_numeric:
         if dst_type.same_as(c_int_type):
-            return src_type.is_enum or (src_type.is_int and (not src_type.signed) + src_type.rank < dst_type.rank)
+            unsigned = (not src_type.signed)
+            return (src_type.is_enum or
+                    (src_type.is_int and
+                     unsigned + src_type.rank < dst_type.rank))
         elif dst_type.same_as(c_double_type):
             return src_type.is_float and src_type.rank <= dst_type.rank
     return False
@@ -2292,8 +2300,11 @@ def best_match(args, functions, pos=None):
     if len(candidates) == 1:
         return candidates[0][0]
     elif len(candidates) == 0:
-        if len(errors) == 1 and pos is not None:
-            error(pos, errors[0][1])
+        if pos is not None:
+            if len(errors) == 1:
+                error(pos, errors[0][1])
+            else:
+                error(pos, "no suitable method found")
         return None
         
     possibilities = []
@@ -2304,9 +2315,7 @@ def best_match(args, functions, pos=None):
             src_type = args[i].type
             dst_type = func_type.args[i].type
             if dst_type.assignable_from(src_type):
-                if src_type == dst_type or (dst_type.is_reference and \
-                                            src_type == dst_type.base_type) \
-                                        or dst_type.same_as(src_type):
+                if src_type == dst_type or dst_type.same_as(src_type):
                     pass # score 0
                 elif is_promotion(src_type, dst_type):
                     score[2] += 1
@@ -2335,30 +2344,31 @@ def best_match(args, functions, pos=None):
             error(pos, "no suitable method found")
     return None
 
-
 def widest_numeric_type(type1, type2):
     # Given two numeric types, return the narrowest type
     # encompassing both of them.
     if type1 == type2:
-        return type1
-    if type1.is_complex:
-        if type2.is_complex:
-            return CComplexType(widest_numeric_type(type1.real_type, type2.real_type))
-        else:
-            return CComplexType(widest_numeric_type(type1.real_type, type2))
-    elif type2.is_complex:
-        return CComplexType(widest_numeric_type(type1, type2.real_type))
-    if type1.is_enum and type2.is_enum:
-        return c_int_type
-    elif type1 is type2:
-        return type1
-    elif (type1.signed and type2.signed) or (not type1.signed and not type2.signed):
-        if type2.rank > type1.rank:
-            return type2
-        else:
-            return type1
+        widest_type = type1
+    elif type1.is_complex or type2.is_complex:
+        def real_type(ntype):
+            if ntype.is_complex:
+                return ntype.real_type
+            return ntype
+        widest_type = CComplexType(
+            widest_numeric_type(
+                real_type(type1), 
+                real_type(type2)))
+    elif type1.is_enum and type2.is_enum:
+        widest_type = c_int_type
+    elif type1.rank < type2.rank:
+        widest_type = type2
+    elif type1.rank > type2.rank:
+        widest_type = type1
+    elif type1.signed < type2.signed:
+        widest_type = type1
     else:
-        return sign_and_rank_to_type[min(type1.signed, type2.signed), max(type1.rank, type2.rank)]
+        widest_type = type2
+    return widest_type
 
 def spanning_type(type1, type2):
     # Return a type assignable from both type1 and type2.
@@ -2413,10 +2423,39 @@ def parse_basic_type(name):
         base = parse_basic_type(name[:-1])
     if base:
         return CPtrType(base)
-    elif name.startswith('u'):
-        return simple_c_type(0, 0, name[1:])
+    #
+    basic_type = simple_c_type(1, 0, name)
+    if basic_type:
+        return basic_type
+    #
+    signed = 1
+    longness = 0
+    if name == 'Py_UNICODE':
+        signed = 0
+    elif name == 'Py_ssize_t':
+        signed = 2
+    elif name == 'ssize_t':
+        signed = 2
+    elif name == 'size_t':
+        signed = 0
     else:
-        return simple_c_type(1, 0, name)
+        if name.startswith('u'):
+            name = name[1:]
+            signed = 0
+        elif (name.startswith('s') and 
+              not name.startswith('short')):
+            name = name[1:]
+            signed = 2
+        longness = 0
+        while name.startswith('short'):
+            name = name.replace('short', '', 1).strip()
+            longness -= 1
+        while name.startswith('long'):
+            name = name.replace('long', '', 1).strip()
+            longness += 1
+        if longness != 0 and not name:
+            name = 'int'
+    return simple_c_type(signed, longness, name)
 
 def c_array_type(base_type, size):
     # Construct a C array type.
@@ -2444,19 +2483,6 @@ def c_ref_type(base_type):
         return error_type
     else:
         return CReferenceType(base_type)
-        
-def Node_to_type(node, env):
-    from ExprNodes import NameNode, AttributeNode, StringNode, error
-    if isinstance(node, StringNode):
-        node = NameNode(node.pos, name=node.value)
-    if isinstance(node, NameNode) and node.name in rank_to_type_name:
-        return simple_c_type(1, 0, node.name)
-    elif isinstance(node, (AttributeNode, NameNode)):
-        node.analyze_types(env)
-        if not node.entry.is_type:
-            pass
-    else:
-        error(node.pos, "Bad type")
 
 def same_type(type1, type2):
     return type1.same_as(type2)
@@ -2479,83 +2505,15 @@ def typecast(to_type, from_type, expr_code):
 type_conversion_predeclarations = """
 /* Type Conversion Predeclarations */
 
-#if PY_MAJOR_VERSION < 3
-#define __Pyx_PyBytes_FromString          PyString_FromString
-#define __Pyx_PyBytes_FromStringAndSize   PyString_FromStringAndSize
-#define __Pyx_PyBytes_AsString            PyString_AsString
-#else
-#define __Pyx_PyBytes_FromString          PyBytes_FromString
-#define __Pyx_PyBytes_FromStringAndSize   PyBytes_FromStringAndSize
-#define __Pyx_PyBytes_AsString            PyBytes_AsString
-#endif
-
-#define __Pyx_PyBytes_FromUString(s)      __Pyx_PyBytes_FromString((char*)s)
-#define __Pyx_PyBytes_AsUString(s)        ((unsigned char*) __Pyx_PyBytes_AsString(s))
+#define __Pyx_PyBytes_FromUString(s) PyBytes_FromString((char*)s)
+#define __Pyx_PyBytes_AsUString(s)   ((unsigned char*) PyBytes_AsString(s))
 
 #define __Pyx_PyBool_FromLong(b) ((b) ? (Py_INCREF(Py_True), Py_True) : (Py_INCREF(Py_False), Py_False))
 static CYTHON_INLINE int __Pyx_PyObject_IsTrue(PyObject*);
 static CYTHON_INLINE PyObject* __Pyx_PyNumber_Int(PyObject* x);
 
-#if !defined(T_PYSSIZET)
-#if PY_VERSION_HEX < 0x02050000
-#define T_PYSSIZET T_INT
-#elif !defined(T_LONGLONG)
-#define T_PYSSIZET \\
-        ((sizeof(Py_ssize_t) == sizeof(int))  ? T_INT  : \\
-        ((sizeof(Py_ssize_t) == sizeof(long)) ? T_LONG : -1))
-#else
-#define T_PYSSIZET \\
-        ((sizeof(Py_ssize_t) == sizeof(int))          ? T_INT      : \\
-        ((sizeof(Py_ssize_t) == sizeof(long))         ? T_LONG     : \\
-        ((sizeof(Py_ssize_t) == sizeof(PY_LONG_LONG)) ? T_LONGLONG : -1)))
-#endif
-#endif
-
-
-#if !defined(T_ULONGLONG)
-#define __Pyx_T_UNSIGNED_INT(x) \\
-        ((sizeof(x) == sizeof(unsigned char))  ? T_UBYTE : \\
-        ((sizeof(x) == sizeof(unsigned short)) ? T_USHORT : \\
-        ((sizeof(x) == sizeof(unsigned int))   ? T_UINT : \\
-        ((sizeof(x) == sizeof(unsigned long))  ? T_ULONG : -1))))
-#else
-#define __Pyx_T_UNSIGNED_INT(x) \\
-        ((sizeof(x) == sizeof(unsigned char))  ? T_UBYTE : \\
-        ((sizeof(x) == sizeof(unsigned short)) ? T_USHORT : \\
-        ((sizeof(x) == sizeof(unsigned int))   ? T_UINT : \\
-        ((sizeof(x) == sizeof(unsigned long))  ? T_ULONG : \\
-        ((sizeof(x) == sizeof(unsigned PY_LONG_LONG)) ? T_ULONGLONG : -1)))))
-#endif
-#if !defined(T_LONGLONG)
-#define __Pyx_T_SIGNED_INT(x) \\
-        ((sizeof(x) == sizeof(char))  ? T_BYTE : \\
-        ((sizeof(x) == sizeof(short)) ? T_SHORT : \\
-        ((sizeof(x) == sizeof(int))   ? T_INT : \\
-        ((sizeof(x) == sizeof(long))  ? T_LONG : -1))))
-#else
-#define __Pyx_T_SIGNED_INT(x) \\
-        ((sizeof(x) == sizeof(char))  ? T_BYTE : \\
-        ((sizeof(x) == sizeof(short)) ? T_SHORT : \\
-        ((sizeof(x) == sizeof(int))   ? T_INT : \\
-        ((sizeof(x) == sizeof(long))  ? T_LONG : \\
-        ((sizeof(x) == sizeof(PY_LONG_LONG))   ? T_LONGLONG : -1)))))
-#endif
-
-#define __Pyx_T_FLOATING(x) \\
-        ((sizeof(x) == sizeof(float)) ? T_FLOAT : \\
-        ((sizeof(x) == sizeof(double)) ? T_DOUBLE : -1))
-
-#if !defined(T_SIZET)
-#if !defined(T_ULONGLONG)
-#define T_SIZET \\
-        ((sizeof(size_t) == sizeof(unsigned int))  ? T_UINT  : \\
-        ((sizeof(size_t) == sizeof(unsigned long)) ? T_ULONG : -1))
-#else
-#define T_SIZET \\
-        ((sizeof(size_t) == sizeof(unsigned int))          ? T_UINT      : \\
-        ((sizeof(size_t) == sizeof(unsigned long))         ? T_ULONG     : \\
-        ((sizeof(size_t) == sizeof(unsigned PY_LONG_LONG)) ? T_ULONGLONG : -1)))
-#endif
+#ifdef Py_USING_UNICODE
+static CYTHON_INLINE Py_UNICODE __Pyx_PyInt_AsPy_UNICODE(PyObject*);
 #endif
 
 static CYTHON_INLINE Py_ssize_t __Pyx_PyIndex_AsSsize_t(PyObject*);
@@ -2566,12 +2524,13 @@ static CYTHON_INLINE size_t __Pyx_PyInt_AsSize_t(PyObject*);
 
 """ + type_conversion_predeclarations
 
+# Note: __Pyx_PyObject_IsTrue is written to minimize branching.
 type_conversion_functions = """
 /* Type Conversion Functions */
 
 static CYTHON_INLINE int __Pyx_PyObject_IsTrue(PyObject* x) {
-   if (x == Py_True) return 1;
-   else if ((x == Py_False) | (x == Py_None)) return 0;
+   int is_true = x == Py_True;
+   if (is_true | (x == Py_False) | (x == Py_None)) return is_true;
    else return PyObject_IsTrue(x);
 }
 
@@ -2621,6 +2580,26 @@ static CYTHON_INLINE PyObject* __Pyx_PyNumber_Int(PyObject* x) {
   return res;
 }
 
+#ifdef Py_USING_UNICODE
+static CYTHON_INLINE Py_UNICODE __Pyx_PyInt_AsPy_UNICODE(PyObject* x) {
+   long ival = __Pyx_PyInt_AsLong(x);
+   static long maxval = 0;
+   if (unlikely(!maxval))
+       maxval = (long)PyUnicode_GetMax();
+   if (unlikely(ival < 0)) {
+       if (!PyErr_Occurred())
+           PyErr_SetString(PyExc_OverflowError,
+                           "can't convert negative value to Py_UNICODE");
+       return (Py_UNICODE)-1;
+   } else if (unlikely(ival > maxval)) {
+       PyErr_SetString(PyExc_OverflowError,
+                       "value too large to convert to Py_UNICODE");
+       return (Py_UNICODE)-1;
+   }
+   return (Py_UNICODE)ival;
+}
+#endif
+
 static CYTHON_INLINE Py_ssize_t __Pyx_PyIndex_AsSsize_t(PyObject* b) {
   Py_ssize_t ival;
   PyObject* x = PyNumber_Index(b);
@@ -2658,4 +2637,3 @@ static CYTHON_INLINE size_t __Pyx_PyInt_AsSize_t(PyObject* x) {
 
 """ + type_conversion_functions
 
-