remove trailing whitespace
[cython.git] / Cython / Compiler / PyrexTypes.py
index 19dd80dcf982a8da2d85d79abd99b4ec9e110002..2dce098f6333b7caa05276a8bd987b3487b8acc1 100755 (executable)
@@ -1,5 +1,3 @@
-
-
 #
 #   Pyrex - Types
 #
@@ -19,10 +17,10 @@ class BaseType(object):
 
     def cast_code(self, expr_code):
         return "((%s)%s)" % (self.declaration_code(""), expr_code)
-    
+
     def specialization_name(self):
         return self.declaration_code("").replace(" ", "__")
-    
+
     def base_declaration_code(self, base_code, entity_code):
         if entity_code:
             return "%s %s" % (base_code, entity_code)
@@ -51,13 +49,14 @@ class PyrexType(BaseType):
     #  is_typedef            boolean     Is a typedef type
     #  is_string             boolean     Is a C char * type
     #  is_unicode            boolean     Is a UTF-8 encoded C char * type
+    #  is_unicode_char       boolean     Is either Py_UCS4 or Py_UNICODE
     #  is_returncode         boolean     Is used only to signal exceptions
     #  is_error              boolean     Is the dummy error type
     #  is_buffer             boolean     Is buffer access type
     #  has_attributes        boolean     Has C dot-selectable attributes
     #  default_value         string      Initial value
     #
-    #  declaration_code(entity_code, 
+    #  declaration_code(entity_code,
     #      for_display = 0, dll_linkage = None, pyrex = 0)
     #    Returns a code fragment for the declaration of an entity
     #    of this type, given a code fragment for the entity.
@@ -81,7 +80,7 @@ class PyrexType(BaseType):
     #    Coerces array type into pointer type for use as
     #    a formal argument type.
     #
-        
+
     is_pyobject = 0
     is_unspecified = 0
     is_extension_type = 0
@@ -103,49 +102,50 @@ class PyrexType(BaseType):
     is_typedef = 0
     is_string = 0
     is_unicode = 0
+    is_unicode_char = 0
     is_returncode = 0
     is_error = 0
     is_buffer = 0
     has_attributes = 0
     default_value = ""
-    
+
     def resolve(self):
         # If a typedef, returns the base type.
         return self
-    
+
     def specialize(self, values):
         # TODO(danilo): Override wherever it makes sense.
         return self
-    
+
     def literal_code(self, value):
         # Returns a C code fragment representing a literal
         # value of this type.
         return str(value)
-    
+
     def __str__(self):
         return self.declaration_code("", for_display = 1).strip()
-    
+
     def same_as(self, other_type, **kwds):
         return self.same_as_resolved_type(other_type.resolve(), **kwds)
-    
+
     def same_as_resolved_type(self, other_type):
         return self == other_type or other_type is error_type
-    
+
     def subtype_of(self, other_type):
         return self.subtype_of_resolved_type(other_type.resolve())
-    
+
     def subtype_of_resolved_type(self, other_type):
         return self.same_as(other_type)
-    
+
     def assignable_from(self, src_type):
         return self.assignable_from_resolved_type(src_type.resolve())
-    
+
     def assignable_from_resolved_type(self, src_type):
         return self.same_as(src_type)
-    
+
     def as_argument_type(self):
         return self
-    
+
     def is_complete(self):
         # A type is incomplete if it is an unsized array,
         # a struct whose attributes are not defined, etc.
@@ -162,6 +162,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:
@@ -170,6 +176,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
@@ -182,38 +189,38 @@ class CTypedefType(BaseType):
     #  typedef_cname       string
     #  typedef_base_type   PyrexType
     #  typedef_is_external bool
-    
+
     is_typedef = 1
     typedef_is_external = 0
 
     to_py_utility_code = None
     from_py_utility_code = None
-    
-    
+
+
     def __init__(self, name, base_type, cname, is_external=0):
         assert not base_type.is_complex
         self.typedef_name = name
         self.typedef_cname = cname
         self.typedef_base_type = base_type
         self.typedef_is_external = is_external
-    
+
     def resolve(self):
         return self.typedef_base_type.resolve()
-    
-    def declaration_code(self, entity_code, 
+
+    def declaration_code(self, entity_code,
             for_display = 0, dll_linkage = None, pyrex = 0):
         if pyrex or for_display:
             base_code = self.typedef_name
         else:
             base_code = public_decl(self.typedef_cname, dll_linkage)
         return self.base_declaration_code(base_code, entity_code)
-    
+
     def as_argument_type(self):
         return self
 
     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. 
+        # For example, the gmp mpz_t.
         if self.typedef_base_type.is_array:
             base_type = self.typedef_base_type.base_type
             return CPtrType(base_type).cast_code(expr_code)
@@ -222,13 +229,13 @@ class CTypedefType(BaseType):
 
     def __repr__(self):
         return "<CTypedefType %s>" % self.typedef_cname
-    
+
     def __str__(self):
         return self.typedef_name
 
     def _create_utility_code(self, template_utility_code,
                              template_function_name):
-        type_name = self.typedef_cname.replace(" ","_")
+        type_name = self.typedef_cname.replace(" ","_").replace("::","__")
         utility_code = template_utility_code.specialize(
             type     = self.typedef_cname,
             TypeName = type_name)
@@ -239,7 +246,9 @@ class CTypedefType(BaseType):
         if self.typedef_is_external:
             if not self.to_py_utility_code:
                 base_type = self.typedef_base_type
-                if base_type.is_int:
+                if type(base_type) is CIntType:
+                    # Various subclasses have special methods
+                    # that should be inherited.
                     self.to_py_utility_code, self.to_py_function = \
                         self._create_utility_code(c_typedef_int_to_py_function,
                                                   '__Pyx_PyInt_to_py_%s')
@@ -258,7 +267,9 @@ class CTypedefType(BaseType):
         if self.typedef_is_external:
             if not self.from_py_utility_code:
                 base_type = self.typedef_base_type
-                if base_type.is_int:
+                if type(base_type) is CIntType:
+                    # Various subclasses have special methods
+                    # that should be inherited.
                     self.from_py_utility_code, self.from_py_function = \
                         self._create_utility_code(c_typedef_int_from_py_function,
                                                   '__Pyx_PyInt_from_py_%s')
@@ -286,12 +297,13 @@ class CTypedefType(BaseType):
     def __getattr__(self, name):
         return getattr(self.typedef_base_type, name)
 
+
 class BufferType(BaseType):
     #
     #  Delegates most attribute
     #  lookups to the base type. ANYTHING NOT DEFINED
     #  HERE IS DELEGATED!
-    
+
     # dtype            PyrexType
     # ndim             int
     # mode             str
@@ -310,7 +322,7 @@ class BufferType(BaseType):
         self.mode = mode
         self.negative_indices = negative_indices
         self.cast = cast
-    
+
     def as_argument_type(self):
         return self
 
@@ -320,12 +332,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).
@@ -338,26 +345,32 @@ class PyObjectType(PyrexType):
     buffer_defaults = None
     is_extern = False
     is_subclassed = False
-    
+
     def __str__(self):
         return "Python object"
-    
+
     def __repr__(self):
         return "<PyObjectType>"
 
     def can_coerce_to_pyobject(self, env):
         return True
 
+    def default_coerced_ctype(self):
+        "The default C type that this Python type coerces to, or None."
+        return None
+
     def assignable_from(self, src_type):
         # except for pointers, conversion will be attempted
         return not src_type.is_ptr or src_type.is_string
-        
-    def declaration_code(self, entity_code, 
+
+    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:
@@ -366,79 +379,100 @@ class PyObjectType(PyrexType):
             return cname
 
 class BuiltinObjectType(PyObjectType):
+    #  objstruct_cname  string           Name of PyObject struct
 
     is_builtin_type = 1
     has_attributes = 1
     base_type = None
     module_name = '__builtin__'
 
-    alternative_name = None # used for str/bytes duality
+    # fields that let it look like an extension type
+    vtabslot_cname = None
+    vtabstruct_cname = None
+    vtabptr_cname = None
+    typedef_flag = True
+    is_external = True
 
-    def __init__(self, name, cname):
+    def __init__(self, name, cname, objstruct_cname=None):
         self.name = name
-        if name == 'str':
-            self.alternative_name = 'bytes'
-        elif name == 'bytes':
-            self.alternative_name = 'str'
         self.cname = cname
-        self.typeptr_cname = "&" + cname
-                                 
+        self.typeptr_cname = "(&%s)" % cname
+        self.objstruct_cname = objstruct_cname
+
     def set_scope(self, scope):
         self.scope = scope
         if scope:
             scope.parent_type = self
-        
+
     def __str__(self):
         return "%s object" % self.name
-    
+
     def __repr__(self):
         return "<%s>"% self.cname
-        
+
+    def default_coerced_ctype(self):
+        if self.name == 'bytes':
+            return c_char_ptr_type
+        elif self.name == 'bool':
+            return c_bint_type
+        elif self.name == 'float':
+            return c_double_type
+        return None
+
     def assignable_from(self, src_type):
         if isinstance(src_type, BuiltinObjectType):
-            return src_type.name == self.name or (
-                src_type.name == self.alternative_name and
-                src_type.name is not None)
+            return src_type.name == self.name
         elif src_type.is_extension_type:
             return (src_type.module_name == '__builtin__' and
                     src_type.name == self.name)
         else:
             return True
-            
+
     def typeobj_is_available(self):
         return True
-        
+
     def attributes_known(self):
         return True
-        
+
     def subtype_of(self, type):
         return type.is_pyobject and self.assignable_from(type)
-        
-    def type_test_code(self, arg, notnone=False):
+
+    def type_check_function(self, exact=True):
         type_name = self.name
         if type_name == 'str':
-            type_check = 'PyString_CheckExact'
-        elif type_name == 'set':
-            type_check = 'PyAnySet_CheckExact'
+            type_check = 'PyString_Check'
         elif type_name == 'frozenset':
-            type_check = 'PyFrozenSet_CheckExact'
-        elif type_name == 'bool':
-            type_check = 'PyBool_Check'
+            type_check = 'PyFrozenSet_Check'
         else:
-            type_check = 'Py%s_CheckExact' % type_name.capitalize()
+            type_check = 'Py%s_Check' % type_name.capitalize()
+        if exact and type_name not in ('bool', 'slice'):
+            type_check += 'Exact'
+        return type_check
 
+    def isinstance_code(self, arg):
+        return '%s(%s)' % (self.type_check_function(exact=False), arg)
+
+    def type_test_code(self, arg, notnone=False):
+        type_check = self.type_check_function(exact=True)
         check = 'likely(%s(%s))' % (type_check, arg)
         if not notnone:
             check = check + ('||((%s) == Py_None)' % arg)
         error = '(PyErr_Format(PyExc_TypeError, "Expected %s, got %%.200s", Py_TYPE(%s)->tp_name), 0)' % (self.name, arg)
         return check + '||' + error
 
-    def declaration_code(self, entity_code, 
+    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)
+
+    def cast_code(self, expr_code, to_object_struct = False):
+        return "((%s*)%s)" % (
+            to_object_struct and self.objstruct_cname or "PyObject", # self.objstruct_cname may be None
+            expr_code)
 
 
 class PyExtensionType(PyObjectType):
@@ -459,12 +493,12 @@ class PyExtensionType(PyObjectType):
     #  vtabstruct_cname string           Name of C method table struct
     #  vtabptr_cname    string           Name of pointer to C method table
     #  vtable_cname     string           Name of C method table definition
-    
+
     is_extension_type = 1
     has_attributes = 1
-    
+
     objtypedef_cname = None
-    
+
     def __init__(self, name, typedef_flag, base_type, is_external=0):
         self.name = name
         self.scope = None
@@ -481,28 +515,28 @@ class PyExtensionType(PyObjectType):
         self.vtabptr_cname = None
         self.vtable_cname = None
         self.is_external = is_external
-    
+
     def set_scope(self, scope):
         self.scope = scope
         if scope:
             scope.parent_type = self
-    
+
     def subtype_of_resolved_type(self, other_type):
         if other_type.is_extension_type:
             return self is other_type or (
                 self.base_type and self.base_type.subtype_of(other_type))
         else:
             return other_type is py_object_type
-    
+
     def typeobj_is_available(self):
         # Do we have a pointer to the type object?
         return self.typeptr_cname
-    
+
     def typeobj_is_imported(self):
         # If we don't know the C name of the type object but we do
         # 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
@@ -511,20 +545,21 @@ class PyExtensionType(PyObjectType):
                 return self.assignable_from(src_type.base_type)
         return False
 
-    def declaration_code(self, entity_code, 
+    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:
                 objstruct = self.objstruct_cname
             else:
                 objstruct = "struct %s" % self.objstruct_cname
-            base = public_decl(objstruct, dll_linkage)
+            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):
 
@@ -538,14 +573,14 @@ class PyExtensionType(PyObjectType):
 
     def attributes_known(self):
         return self.scope is not None
-    
+
     def __str__(self):
         return self.name
-    
+
     def __repr__(self):
         return "<PyExtensionType %s%s>" % (self.scope.class_name,
             ("", " typedef")[self.typedef_flag])
-    
+
 
 class CType(PyrexType):
     #
@@ -554,7 +589,7 @@ class CType(PyrexType):
     #  to_py_function     string     C function for converting to Python object
     #  from_py_function   string     C function for constructing from Python object
     #
-    
+
     to_py_function = None
     from_py_function = None
     exception_value = None
@@ -562,7 +597,7 @@ class CType(PyrexType):
 
     def create_to_py_utility_code(self, env):
         return self.to_py_function is not None
-        
+
     def create_from_py_utility_code(self, env):
         return self.from_py_function is not None
 
@@ -584,16 +619,23 @@ class CType(PyrexType):
 
 
 class CVoidType(CType):
+    #
+    #   C "void" type
+    #
+
     is_void = 1
-    
+
     def __repr__(self):
         return "<CVoidType>"
-    
-    def declaration_code(self, entity_code, 
+
+    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
 
@@ -605,30 +647,51 @@ class CNumericType(CType):
     #   rank      integer     Relative size
     #   signed    integer     0 = unsigned, 1 = unspecified, 2 = explicitly signed
     #
-    
+
     is_numeric = 1
     default_value = "0"
-    
+    has_attributes = True
+    scope = None
+
     sign_words = ("unsigned ", "", "signed ")
-    
+
     def __init__(self, rank, signed = 1):
         self.rank = rank
         self.signed = signed
-    
+
     def sign_and_name(self):
         s = self.sign_words[self.signed]
         n = rank_to_type_name[self.rank]
         return s + n
-    
+
     def __repr__(self):
         return "<CNumericType %s>" % self.sign_and_name()
-    
-    def declaration_code(self, entity_code, 
+
+    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)
+
+    def attributes_known(self):
+        if self.scope is None:
+            import Symtab
+            self.scope = scope = Symtab.CClassScope(
+                    '',
+                    None,
+                    visibility="extern")
+            scope.parent_type = self
+            scope.directives = {}
+            entry = scope.declare_cfunction(
+                    "conjugate",
+                    CFuncType(self, [CFuncTypeArg("self", self, None)], nogil=True),
+                    pos=None,
+                    defining=1,
+                    cname=" ")
+        return True
 
 
 type_conversion_predeclarations = ""
@@ -706,8 +769,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);
@@ -733,17 +796,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;
 }
 """)
 
@@ -753,20 +827,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);
     }
 }
 """)
@@ -775,27 +856,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, is_returncode = 0):
+    def __init__(self, rank, signed = 1):
         CNumericType.__init__(self, rank, signed)
-        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]
+        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
@@ -809,49 +903,171 @@ class CIntType(CNumericType):
         return src_type.is_int or src_type.is_enum or src_type is error_type
 
 
+class CAnonEnumType(CIntType):
+
+    is_enum = 1
+
+    def sign_and_name(self):
+        return 'int'
+
+
+class CReturnCodeType(CIntType):
+
+    to_py_function = "__Pyx_Owned_Py_None"
+
+    is_returncode = 1
+
+
 class CBIntType(CIntType):
 
     to_py_function = "__Pyx_PyBool_FromLong"
     from_py_function = "__Pyx_PyObject_IsTrue"
-    exception_check = 0
+    exception_check = 1 # for C++ bool
 
     def __repr__(self):
         return "<CNumericType bint>"
 
+    def __str__(self):
+        return 'bint'
 
-class CAnonEnumType(CIntType):
 
-    is_enum = 1
+class CPyUCS4IntType(CIntType):
+    # Py_UCS4
 
-    def sign_and_name(self):
-        return 'int'
+    is_unicode_char = True
 
+    # Py_UCS4 coerces from and to single character unicode strings (or
+    # at most two characters on 16bit Unicode builds), but we also
+    # allow Python integers as input.  The value range for Py_UCS4
+    # is 0..1114111, which is checked when converting from an integer
+    # value.
 
-class CUIntType(CIntType):
-
-    to_py_function = "PyLong_FromUnsignedLong"
-    exception_value = -1
+    to_py_function = "PyUnicode_FromOrdinal"
+    from_py_function = "__Pyx_PyObject_AsPy_UCS4"
 
+    def create_from_py_utility_code(self, env):
+        env.use_utility_code(pyobject_as_py_ucs4_utility_code)
+        return True
 
-class CLongType(CIntType):
+    def sign_and_name(self):
+        return "Py_UCS4"
+
+
+pyobject_as_py_ucs4_utility_code = UtilityCode(
+proto='''
+static CYTHON_INLINE Py_UCS4 __Pyx_PyObject_AsPy_UCS4(PyObject*);
+''',
+impl='''
+static CYTHON_INLINE Py_UCS4 __Pyx_PyObject_AsPy_UCS4(PyObject* x) {
+   long ival;
+   if (PyUnicode_Check(x)) {
+       if (likely(PyUnicode_GET_SIZE(x) == 1)) {
+           return PyUnicode_AS_UNICODE(x)[0];
+       }
+       #if Py_UNICODE_SIZE == 2
+       else if (PyUnicode_GET_SIZE(x) == 2) {
+           Py_UCS4 high_val = PyUnicode_AS_UNICODE(x)[0];
+           if (high_val >= 0xD800 && high_val <= 0xDBFF) {
+               Py_UCS4 low_val = PyUnicode_AS_UNICODE(x)[1];
+               if (low_val >= 0xDC00 && low_val <= 0xDFFF) {
+                   return 0x10000 + (((high_val & ((1<<10)-1)) << 10) | (low_val & ((1<<10)-1)));
+               }
+           }
+       }
+       #endif
+       PyErr_Format(PyExc_ValueError,
+           "only single character unicode strings can be converted to Py_UCS4, got length "
+           #if PY_VERSION_HEX < 0x02050000
+           "%d",
+           #else
+           "%zd",
+           #endif
+           PyUnicode_GET_SIZE(x));
+       return (Py_UCS4)-1;
+   }
+   ival = __Pyx_PyInt_AsLong(x);
+   if (unlikely(ival < 0)) {
+       if (!PyErr_Occurred())
+           PyErr_SetString(PyExc_OverflowError,
+                           "cannot convert negative value to Py_UCS4");
+       return (Py_UCS4)-1;
+   } else if (unlikely(ival > 1114111)) {
+       PyErr_SetString(PyExc_OverflowError,
+                       "value too large to convert to Py_UCS4");
+       return (Py_UCS4)-1;
+   }
+   return (Py_UCS4)ival;
+}
+''')
 
-    to_py_function = "PyInt_FromLong"
 
+class CPyUnicodeIntType(CIntType):
+    # Py_UNICODE
 
-class CULongType(CUIntType):
+    is_unicode_char = True
 
-    to_py_function = "PyLong_FromUnsignedLong"
+    # Py_UNICODE coerces from and to single character unicode strings,
+    # but we also allow Python integers as input.  The value range for
+    # Py_UNICODE is 0..1114111, which is checked when converting from
+    # an integer value.
 
+    to_py_function = "PyUnicode_FromOrdinal"
+    from_py_function = "__Pyx_PyObject_AsPy_UNICODE"
 
-class CLongLongType(CIntType):
+    def create_from_py_utility_code(self, env):
+        env.use_utility_code(pyobject_as_py_unicode_utility_code)
+        return True
 
-    to_py_function = "PyLong_FromLongLong"
+    def sign_and_name(self):
+        return "Py_UNICODE"
+
+pyobject_as_py_unicode_utility_code = UtilityCode(
+proto='''
+static CYTHON_INLINE Py_UNICODE __Pyx_PyObject_AsPy_UNICODE(PyObject*);
+''',
+impl='''
+static CYTHON_INLINE Py_UNICODE __Pyx_PyObject_AsPy_UNICODE(PyObject* x) {
+   static long maxval = 0;
+   long ival;
+   if (PyUnicode_Check(x)) {
+       if (unlikely(PyUnicode_GET_SIZE(x) != 1)) {
+           PyErr_Format(PyExc_ValueError,
+               "only single character unicode strings can be converted to Py_UNICODE, got length "
+               #if PY_VERSION_HEX < 0x02050000
+               "%d",
+               #else
+               "%zd",
+               #endif
+               PyUnicode_GET_SIZE(x));
+           return (Py_UNICODE)-1;
+       }
+       return PyUnicode_AS_UNICODE(x)[0];
+   }
+   if (unlikely(!maxval))
+       maxval = (long)PyUnicode_GetMax();
+   ival = __Pyx_PyInt_AsLong(x);
+   if (unlikely(ival < 0)) {
+       if (!PyErr_Occurred())
+           PyErr_SetString(PyExc_OverflowError,
+                           "cannot 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;
+}
+''')
 
 
-class CULongLongType(CUIntType):
+class CPyHashTType(CIntType):
 
-    to_py_function = "PyLong_FromUnsignedLongLong"
+    to_py_function = "__Pyx_PyInt_FromHash_t"
+    from_py_function = "__Pyx_PyInt_AsHash_t"
 
+    def sign_and_name(self):
+        return "Py_hash_t"
 
 class CPySSizeTType(CIntType):
 
@@ -859,16 +1075,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 "Py_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):
@@ -878,22 +1101,22 @@ class CFloatType(CNumericType):
     from_py_function = "__pyx_PyFloat_AsDouble"
 
     exception_value = -1
-    
+
     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):
         return (src_type.is_numeric and not src_type.is_complex) or src_type is error_type
 
 
 class CComplexType(CNumericType):
-    
+
     is_complex = 1
     to_py_function = "__pyx_PyComplex_FromComplex"
     has_attributes = 1
     scope = None
-    
+
     def __init__(self, real_type):
         while real_type.is_typedef and not real_type.typedef_is_external:
             real_type = real_type.typedef_base_type
@@ -905,7 +1128,7 @@ class CComplexType(CNumericType):
             self.funcsuffix = real_type.math_h_modifier
         else:
             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 = {}
@@ -917,7 +1140,7 @@ class CComplexType(CNumericType):
             return self.real_type == other.real_type
         else:
             return False
-    
+
     def __ne__(self, other):
         if isinstance(self, CComplexType) and isinstance(other, CComplexType):
             return self.real_type != other.real_type
@@ -935,19 +1158,21 @@ class CComplexType(CNumericType):
     def __hash__(self):
         return ~hash(self.real_type)
 
-    def declaration_code(self, entity_code, 
+    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.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):
         # Temporary hack/feature disabling, see #441
         if (not src_type.is_complex and src_type.is_numeric and src_type.is_typedef
@@ -955,12 +1180,12 @@ class CComplexType(CNumericType):
              return False
         else:
             return super(CComplexType, self).assignable_from(src_type)
-        
+
     def assignable_from_resolved_type(self, src_type):
         return (src_type.is_complex and self.real_type.assignable_from_resolved_type(src_type.real_type)
-                    or src_type.is_numeric and self.real_type.assignable_from_resolved_type(src_type) 
+                    or src_type.is_numeric and self.real_type.assignable_from_resolved_type(src_type)
                     or src_type is error_type)
-                    
+
     def attributes_known(self):
         if self.scope is None:
             import Symtab
@@ -969,11 +1194,12 @@ class CComplexType(CNumericType):
                     None,
                     visibility="extern")
             scope.parent_type = self
-            scope.declare_var("real", self.real_type, None, "real", is_cdef=True)
-            scope.declare_var("imag", self.real_type, None, "imag", is_cdef=True)
+            scope.directives = {}
+            scope.declare_var("real", self.real_type, None, cname="real", is_cdef=True)
+            scope.declare_var("imag", self.real_type, None, cname="imag", is_cdef=True)
             entry = scope.declare_cfunction(
                     "conjugate",
-                    CFuncType(self, [CFuncTypeArg("self", self, None)]),
+                    CFuncType(self, [CFuncTypeArg("self", self, None)], nogil=True),
                     pos=None,
                     defining=1,
                     cname="__Pyx_c_conj%s" % self.funcsuffix)
@@ -990,9 +1216,10 @@ class CComplexType(CNumericType):
                              complex_arithmetic_utility_code):
             env.use_utility_code(
                 utility_code.specialize(
-                    self, 
+                    self,
                     real_type = self.real_type.declaration_code(''),
-                    m = self.funcsuffix))
+                    m = self.funcsuffix,
+                    is_float = self.real_type.is_float))
         return True
 
     def create_to_py_utility_code(self, env):
@@ -1007,12 +1234,13 @@ class CComplexType(CNumericType):
                              complex_from_py_utility_code):
             env.use_utility_code(
                 utility_code.specialize(
-                    self, 
+                    self,
                     real_type = self.real_type.declaration_code(''),
-                    m = self.funcsuffix))
+                    m = self.funcsuffix,
+                    is_float = self.real_type.is_float))
         self.from_py_function = "__Pyx_PyComplex_As_" + self.specialization_name()
         return True
-    
+
     def lookup_op(self, nargs, op):
         try:
             return self.binops[nargs, op]
@@ -1027,10 +1255,10 @@ class CComplexType(CNumericType):
 
     def unary_op(self, op):
         return self.lookup_op(1, op)
-        
+
     def binary_op(self, op):
         return self.lookup_op(2, op)
-        
+
 complex_ops = {
     (1, '-'): 'neg',
     (1, 'zero'): 'is_zero',
@@ -1168,11 +1396,17 @@ proto="""
   #ifdef __cplusplus
     #define __Pyx_c_is_zero%(m)s(z) ((z)==(%(real_type)s)0)
     #define __Pyx_c_conj%(m)s(z)    (::std::conj(z))
-    /*#define __Pyx_c_abs%(m)s(z)     (::std::abs(z))*/
+    #if %(is_float)s
+        #define __Pyx_c_abs%(m)s(z)     (::std::abs(z))
+        #define __Pyx_c_pow%(m)s(a, b)  (::std::pow(a, b))
+    #endif
   #else
     #define __Pyx_c_is_zero%(m)s(z) ((z)==0)
     #define __Pyx_c_conj%(m)s(z)    (conj%(m)s(z))
-    /*#define __Pyx_c_abs%(m)s(z)     (cabs%(m)s(z))*/
+    #if %(is_float)s
+        #define __Pyx_c_abs%(m)s(z)     (cabs%(m)s(z))
+        #define __Pyx_c_pow%(m)s(a, b)  (cpow%(m)s(a, b))
+    #endif
  #endif
 #else
     static CYTHON_INLINE int __Pyx_c_eq%(m)s(%(type)s, %(type)s);
@@ -1183,7 +1417,10 @@ proto="""
     static CYTHON_INLINE %(type)s __Pyx_c_neg%(m)s(%(type)s);
     static CYTHON_INLINE int __Pyx_c_is_zero%(m)s(%(type)s);
     static CYTHON_INLINE %(type)s __Pyx_c_conj%(m)s(%(type)s);
-    /*static CYTHON_INLINE %(real_type)s __Pyx_c_abs%(m)s(%(type)s);*/
+    #if %(is_float)s
+        static CYTHON_INLINE %(real_type)s __Pyx_c_abs%(m)s(%(type)s);
+        static CYTHON_INLINE %(type)s __Pyx_c_pow%(m)s(%(type)s, %(type)s);
+    #endif
 #endif
 """,
 impl="""
@@ -1232,46 +1469,91 @@ impl="""
         z.imag = -a.imag;
         return z;
     }
-/*
-    static CYTHON_INLINE %(real_type)s __Pyx_c_abs%(m)s(%(type)s z) {
-#if HAVE_HYPOT
-        return hypot%(m)s(z.real, z.imag);
-#else
-        return sqrt%(m)s(z.real*z.real + z.imag*z.imag);
-#endif
-    }
-*/
+    #if %(is_float)s
+        static CYTHON_INLINE %(real_type)s __Pyx_c_abs%(m)s(%(type)s z) {
+          #if !defined(HAVE_HYPOT) || defined(_MSC_VER)
+            return sqrt%(m)s(z.real*z.real + z.imag*z.imag);
+          #else
+            return hypot%(m)s(z.real, z.imag);
+          #endif
+        }
+        static CYTHON_INLINE %(type)s __Pyx_c_pow%(m)s(%(type)s a, %(type)s b) {
+            %(type)s z;
+            %(real_type)s r, lnr, theta, z_r, z_theta;
+            if (b.imag == 0 && b.real == (int)b.real) {
+                if (b.real < 0) {
+                    %(real_type)s denom = a.real * a.real + a.imag * a.imag;
+                    a.real = a.real / denom;
+                    a.imag = -a.imag / denom;
+                    b.real = -b.real;
+                }
+                switch ((int)b.real) {
+                    case 0:
+                        z.real = 1;
+                        z.imag = 0;
+                        return z;
+                    case 1:
+                        return a;
+                    case 2:
+                        z = __Pyx_c_prod%(m)s(a, a);
+                        return __Pyx_c_prod%(m)s(a, a);
+                    case 3:
+                        z = __Pyx_c_prod%(m)s(a, a);
+                        return __Pyx_c_prod%(m)s(z, a);
+                    case 4:
+                        z = __Pyx_c_prod%(m)s(a, a);
+                        return __Pyx_c_prod%(m)s(z, z);
+                }
+            }
+            if (a.imag == 0) {
+                if (a.real == 0) {
+                    return a;
+                }
+                r = a.real;
+                theta = 0;
+            } else {
+                r = __Pyx_c_abs%(m)s(a);
+                theta = atan2%(m)s(a.imag, a.real);
+            }
+            lnr = log%(m)s(r);
+            z_r = exp%(m)s(lnr * b.real - theta * b.imag);
+            z_theta = theta * b.real + lnr * b.imag;
+            z.real = z_r * cos%(m)s(z_theta);
+            z.imag = z_r * sin%(m)s(z_theta);
+            return z;
+        }
+    #endif
 #endif
 """)
 
 class CArrayType(CType):
     #  base_type     CType              Element type
     #  size          integer or None    Number of elements
-    
+
     is_array = 1
-    
+
     def __init__(self, base_type, size):
         self.base_type = base_type
         self.size = size
-        if base_type is c_char_type:
+        if base_type in (c_char_type, c_uchar_type, c_schar_type):
             self.is_string = 1
-    
+
     def __repr__(self):
         return "<CArrayType %s %s>" % (self.size, repr(self.base_type))
-    
+
     def same_as_resolved_type(self, other_type):
         return ((other_type.is_array and
             self.base_type.same_as(other_type.base_type))
                 or other_type is error_type)
-    
+
     def assignable_from_resolved_type(self, src_type):
         # Can't assign to a variable of an array type
         return 0
-    
+
     def element_ptr_type(self):
         return c_ptr_type(self.base_type)
 
-    def declaration_code(self, entity_code, 
+    def declaration_code(self, entity_code,
             for_display = 0, dll_linkage = None, pyrex = 0):
         if self.size is not None:
             dimension_code = self.size
@@ -1282,38 +1564,38 @@ class CArrayType(CType):
         return self.base_type.declaration_code(
             "%s[%s]" % (entity_code, dimension_code),
             for_display, dll_linkage, pyrex)
-    
+
     def as_argument_type(self):
         return c_ptr_type(self.base_type)
-    
+
     def is_complete(self):
         return self.size is not None
 
 
 class CPtrType(CType):
     #  base_type     CType    Referenced type
-    
+
     is_ptr = 1
     default_value = "0"
-    
+
     def __init__(self, base_type):
         self.base_type = base_type
-    
+
     def __repr__(self):
         return "<CPtrType %s>" % repr(self.base_type)
-    
+
     def same_as_resolved_type(self, other_type):
         return ((other_type.is_ptr and
             self.base_type.same_as(other_type.base_type))
                 or other_type is error_type)
-    
-    def declaration_code(self, entity_code, 
+
+    def declaration_code(self, entity_code,
             for_display = 0, dll_linkage = None, pyrex = 0):
         #print "CPtrType.declaration_code: pointer to", self.base_type ###
         return self.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
@@ -1326,13 +1608,13 @@ class CPtrType(CType):
                 return self.base_type.pointer_assignable_from_resolved_type(other_type)
             else:
                 return 0
-        if (self.base_type.is_cpp_class and other_type.is_ptr 
+        if (self.base_type.is_cpp_class and other_type.is_ptr
                 and other_type.base_type.is_cpp_class and other_type.base_type.is_subclass(self.base_type)):
             return 1
         if other_type.is_array or other_type.is_ptr:
             return self.base_type.is_void or self.base_type.same_as(other_type.base_type)
         return 0
-    
+
     def specialize(self, values):
         base_type = self.base_type.specialize(values)
         if base_type == self.base_type:
@@ -1344,7 +1626,7 @@ class CPtrType(CType):
 class CNullPtrType(CPtrType):
 
     is_null_ptr = 1
-    
+
 
 class CReferenceType(BaseType):
 
@@ -1355,20 +1637,20 @@ class CReferenceType(BaseType):
 
     def __repr__(self):
         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, 
+    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)
-    
+
     def specialize(self, values):
         base_type = self.ref_base_type.specialize(values)
         if base_type == self.ref_base_type:
@@ -1390,10 +1672,10 @@ class CFuncType(CType):
     #  nogil            boolean    Can be called without gil
     #  with_gil         boolean    Acquire gil around function body
     #  templates        [string] or None
-    
+
     is_cfunction = 1
     original_sig = None
-    
+
     def __init__(self, return_type, args, has_varargs = 0,
             exception_value = None, exception_check = 0, calling_convention = "",
             nogil = 0, with_gil = 0, is_overridable = 0, optional_arg_count = 0,
@@ -1409,7 +1691,7 @@ class CFuncType(CType):
         self.with_gil = with_gil
         self.is_overridable = is_overridable
         self.templates = templates
-    
+
     def __repr__(self):
         arg_reprs = map(repr, self.args)
         if self.has_varargs:
@@ -1425,14 +1707,14 @@ class CFuncType(CType):
             self.calling_convention_prefix(),
             ",".join(arg_reprs),
             except_clause)
-    
+
     def calling_convention_prefix(self):
         cc = self.calling_convention
         if cc:
             return cc + " "
         else:
             return ""
-    
+
     def same_c_signature_as(self, other_type, as_cmethod = 0):
         return self.same_c_signature_as_resolved_type(
             other_type.resolve(), as_cmethod)
@@ -1468,7 +1750,7 @@ class CFuncType(CType):
 
     def compatible_signature_with(self, other_type, as_cmethod = 0):
         return self.compatible_signature_with_resolved_type(other_type.resolve(), as_cmethod)
-    
+
     def compatible_signature_with_resolved_type(self, other_type, as_cmethod):
         #print "CFuncType.same_c_signature_as_resolved_type:", \
         #    self, other_type, "as_cmethod =", as_cmethod ###
@@ -1502,11 +1784,11 @@ class CFuncType(CType):
         if as_cmethod:
             self.args[0] = other_type.args[0]
         return 1
-        
-        
+
+
     def narrower_c_signature_than(self, other_type, as_cmethod = 0):
         return self.narrower_c_signature_than_resolved_type(other_type.resolve(), as_cmethod)
-        
+
     def narrower_c_signature_than_resolved_type(self, other_type, as_cmethod):
         if other_type is error_type:
             return 1
@@ -1542,7 +1824,7 @@ class CFuncType(CType):
         sc1 = self.calling_convention == '__stdcall'
         sc2 = other.calling_convention == '__stdcall'
         return sc1 == sc2
-    
+
     def same_exception_signature_as(self, other_type):
         return self.same_exception_signature_as_resolved_type(
             other_type.resolve())
@@ -1550,18 +1832,18 @@ class CFuncType(CType):
     def same_exception_signature_as_resolved_type(self, other_type):
         return self.exception_value == other_type.exception_value \
             and self.exception_check == other_type.exception_check
-    
+
     def same_as_resolved_type(self, other_type, as_cmethod = 0):
         return self.same_c_signature_as_resolved_type(other_type, as_cmethod) \
             and self.same_exception_signature_as_resolved_type(other_type) \
             and self.nogil == other_type.nogil
-    
+
     def pointer_assignable_from_resolved_type(self, other_type):
         return self.same_c_signature_as_resolved_type(other_type) \
             and self.same_exception_signature_as_resolved_type(other_type) \
             and not (self.nogil and not other_type.nogil)
-    
-    def declaration_code(self, entity_code, 
+
+    def declaration_code(self, entity_code,
                          for_display = 0, dll_linkage = None, pyrex = 0,
                          with_calling_convention = 1):
         arg_decl_list = []
@@ -1599,7 +1881,7 @@ class CFuncType(CType):
         return self.return_type.declaration_code(
             "%s%s(%s)%s" % (cc, entity_code, arg_decl_code, trailer),
             for_display, dll_linkage, pyrex)
-    
+
     def function_header_code(self, func_name, arg_code):
         return "%s%s(%s)" % (self.calling_convention_prefix(),
             func_name, arg_code)
@@ -1611,7 +1893,7 @@ class CFuncType(CType):
     def signature_cast_string(self):
         s = self.declaration_code("(*)", with_calling_convention=False)
         return '(%s)' % s
-    
+
     def specialize(self, values):
         if self.templates is None:
             new_templates = None
@@ -1628,7 +1910,7 @@ class CFuncType(CType):
                              is_overridable = self.is_overridable,
                              optional_arg_count = self.optional_arg_count,
                              templates = new_templates)
-    
+
     def opt_arg_cname(self, arg_name):
         return self.op_arg_struct.base_type.scope.lookup(arg_name).cname
 
@@ -1638,7 +1920,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:
@@ -1647,15 +1934,14 @@ 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):
         return "%s:%s" % (self.name, repr(self.type))
-    
+
     def declaration_code(self, for_display = 0):
         return self.type.declaration_code(self.cname, for_display)
-    
+
     def specialize(self, values):
         return CFuncTypeArg(self.name, self.type.specialize(values), self.pos, self.cname)
 
@@ -1669,11 +1955,11 @@ class StructUtilityCode(object):
         return isinstance(other, StructUtilityCode) and self.header == other.header
     def __hash__(self):
         return hash(self.header)
-    
+
     def put_code(self, output):
         code = output['utility_code_def']
         proto = output['utility_code_proto']
-        
+
         code.putln("%s {" % self.header)
         code.putln("PyObject* res;")
         code.putln("PyObject* member;")
@@ -1696,7 +1982,7 @@ class StructUtilityCode(object):
         if self.forward_decl:
             proto.putln(self.type.declaration_code('') + ';')
         proto.putln(self.header + ";")
-        
+
 
 class CStructOrUnionType(CType):
     #  name          string
@@ -1705,12 +1991,12 @@ class CStructOrUnionType(CType):
     #  scope         StructOrUnionScope, or None if incomplete
     #  typedef_flag  boolean
     #  packed        boolean
-    
+
     # entry          Entry
-    
+
     is_struct_or_union = 1
     has_attributes = 1
-    
+
     def __init__(self, name, kind, scope, typedef_flag, cname, packed=False):
         self.name = name
         self.cname = cname
@@ -1723,7 +2009,7 @@ class CStructOrUnionType(CType):
         self.exception_check = True
         self._convert_code = None
         self.packed = packed
-        
+
     def create_to_py_utility_code(self, env):
         if env.outer_scope is None:
             return False
@@ -1738,26 +2024,25 @@ class CStructOrUnionType(CType):
                     return False
             forward_decl = (self.entry.visibility != 'extern')
             self._convert_code = StructUtilityCode(self, forward_decl)
-        
+
         env.use_utility_code(self._convert_code)
         return True
-        
+
     def __repr__(self):
         return "<CStructOrUnionType %s %s%s>" % (self.name, self.cname,
             ("", " typedef")[self.typedef_flag])
 
-    def declaration_code(self, entity_code, 
+    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:
@@ -1779,7 +2064,7 @@ class CStructOrUnionType(CType):
 
     def is_complete(self):
         return self.scope is not None
-    
+
     def attributes_known(self):
         return self.is_complete()
 
@@ -1802,12 +2087,12 @@ class CppClassType(CType):
     #  cname         string
     #  scope         CppClassScope
     #  templates     [string] or None
-    
+
     is_cpp_class = 1
     has_attributes = 1
     exception_check = True
     namespace = None
-    
+
     def __init__(self, name, scope, cname, base_classes, templates = None, template_type = None):
         self.name = name
         self.cname = cname
@@ -1823,11 +2108,11 @@ class CppClassType(CType):
             error(pos, "'%s' type is not a template" % self);
             return PyrexTypes.error_type
         if len(self.templates) != len(template_values):
-            error(pos, "%s templated type receives %d arguments, got %d" % 
+            error(pos, "%s templated type receives %d arguments, got %d" %
                   (self.name, len(self.templates), len(template_values)))
             return error_type
         return self.specialize(dict(zip(self.templates, template_values)))
-    
+
     def specialize(self, values):
         if not self.templates and not self.namespace:
             return self
@@ -1847,20 +2132,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.
@@ -1870,7 +2159,7 @@ class CppClassType(CType):
             if base_class.is_subclass(other_type):
                 return 1
         return 0
-    
+
     def same_as_resolved_type(self, other_type):
         if other_type.is_cpp_class:
             if self == other_type:
@@ -1889,22 +2178,23 @@ class CppClassType(CType):
         if other_type is error_type:
             return True
         return other_type.is_cpp_class and other_type.is_subclass(self)
-    
+
     def attributes_known(self):
         return self.scope is not None
 
 
 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:
             return self.name
-    
+
     def specialize(self, values):
         if self in values:
             return values[self]
@@ -1916,10 +2206,10 @@ class TemplatePlaceholderType(CType):
             return self.name == other_type.name
         else:
             return 0
-        
+
     def __hash__(self):
         return hash(self.name)
-    
+
     def __cmp__(self, other):
         if isinstance(other, TemplatePlaceholderType):
             return cmp(self.name, other.name)
@@ -1942,24 +2232,25 @@ class CEnumType(CType):
         self.cname = cname
         self.values = []
         self.typedef_flag = typedef_flag
-    
+
     def __str__(self):
         return self.name
-    
+
     def __repr__(self):
         return "<CEnumType %s %s%s>" % (self.name, self.cname,
             ("", " typedef")[self.typedef_flag])
-    
-    def declaration_code(self, entity_code, 
+
+    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):
@@ -1967,9 +2258,9 @@ 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):
@@ -1979,32 +2270,32 @@ class CStringType(object):
 
 class CUTF8CharArrayType(CStringType, CArrayType):
     #  C 'char []' type.
-    
+
     is_unicode = 1
-    
+
     to_py_function = "PyUnicode_DecodeUTF8"
     exception_value = "NULL"
-    
+
     def __init__(self, size):
         CArrayType.__init__(self, c_char_type, size)
 
 class CCharArrayType(CStringType, CArrayType):
     #  C 'char []' type.
-    
+
     def __init__(self, size):
         CArrayType.__init__(self, c_char_type, size)
-    
+
 
 class CCharPtrType(CStringType, CPtrType):
     # C 'char *' type.
-    
+
     def __init__(self):
         CPtrType.__init__(self, c_char_type)
 
 
 class CUCharPtrType(CStringType, CPtrType):
     # C 'unsigned char *' type.
-    
+
     to_py_function = "__Pyx_PyBytes_FromUString"
     from_py_function = "__Pyx_PyBytes_AsUString"
 
@@ -2014,39 +2305,39 @@ class CUCharPtrType(CStringType, CPtrType):
 
 class UnspecifiedType(PyrexType):
     # Used as a placeholder until the type can be determined.
-    
+
     is_unspecified = 1
-        
-    def declaration_code(self, entity_code, 
+
+    def declaration_code(self, entity_code,
             for_display = 0, dll_linkage = None, pyrex = 0):
         return "<unspecified>"
-    
+
     def same_as_resolved_type(self, other_type):
         return False
-        
+
 
 class ErrorType(PyrexType):
     # Used to prevent propagation of error messages.
-    
+
     is_error = 1
     exception_value = "0"
     exception_check    = 0
     to_py_function = "dummy"
     from_py_function = "dummy"
-    
+
     def create_to_py_utility_code(self, env):
         return True
-    
+
     def create_from_py_utility_code(self, env):
         return True
-    
-    def declaration_code(self, entity_code, 
+
+    def declaration_code(self, entity_code,
             for_display = 0, dll_linkage = None, pyrex = 0):
         return "<error>"
-    
+
     def same_as_resolved_type(self, other_type):
         return 1
-        
+
     def error_condition(self, result_code):
         return "dummy"
 
@@ -2056,61 +2347,72 @@ 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)
-c_ushort_type =      CIntType(1, 0)
-c_uint_type =        CUIntType(2, 0)
-c_ulong_type =       CULongType(3, 0)
-c_ulonglong_type =   CULongLongType(6, 0)
-
-c_char_type =        CIntType(0, 1)
-c_short_type =       CIntType(1, 1)
-c_int_type =         CIntType(2, 1)
-c_long_type =        CLongType(3, 1)
-c_longlong_type =    CLongLongType(6, 1)
-c_bint_type =        CBIntType(2, 1)
-
-c_schar_type =       CIntType(0, 2)
-c_sshort_type =      CIntType(1, 2)
-c_sint_type =        CIntType(2, 2)
-c_slong_type =       CLongType(3, 2)
-c_slonglong_type =   CLongLongType(6, 2)
+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)
-c_size_t_type =      CSizeTType(5, 0)
 
-c_float_type =       CFloatType(7, math_h_modifier='f')
-c_double_type =      CFloatType(8)
-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_ucs4_type =     CPyUCS4IntType(RANK_LONG-0.5, UNSIGNED)
+c_py_hash_t_type =   CPyHashTType(RANK_LONG+0.5, SIGNED)
+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, 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")
@@ -2119,99 +2421,59 @@ 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_double_complex_type,  # C: float, Python: double => Python wins
+    (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,
+    (0,  0, "Py_UCS4"):    c_py_ucs4_type,
+    (2,  0, "Py_hash_t"):  c_py_hash_t_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. 
+    # 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
@@ -2228,7 +2490,7 @@ def best_match(args, functions, pos=None):
     functions based on how much work must be done to convert the
     arguments, with the following priorities:
       * identical types or pointers to identical types
-      * promotions 
+      * promotions
       * non-Python types
     That is, we prefer functions where no arguments need converted,
     and failing that, functions where only promotions are required, and
@@ -2238,7 +2500,7 @@ def best_match(args, functions, pos=None):
     the same weight, we return None (as there is no best match). If pos
     is not None, we also generate an error.
     """
-    # TODO: args should be a list of types, not a list of Nodes. 
+    # TODO: args should be a list of types, not a list of Nodes.
     actual_nargs = len(args)
 
     candidates = []
@@ -2270,15 +2532,18 @@ def best_match(args, functions, pos=None):
             errors.append((func, error_mesg))
             continue
         candidates.append((func, func_type))
-        
+
     # Optimize the most common case of no overloading...
     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 = []
     bad_types = []
     for func, func_type in candidates:
@@ -2316,56 +2581,81 @@ 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 independent_spanning_type(type1, type2):
+    # Return a type assignable independently from both type1 and
+    # type2, but do not require any interoperability between the two.
+    # For example, in "True * 2", it is safe to assume an integer
+    # result type (so spanning_type() will do the right thing),
+    # whereas "x = True or 2" must evaluate to a type that can hold
+    # both a boolean value and an integer, so this function works
+    # better.
+    if type1 == type2:
+        return type1
+    elif (type1 is c_bint_type or type2 is c_bint_type) and (type1.is_numeric and type2.is_numeric):
+        # special case: if one of the results is a bint and the other
+        # is another C integer, we must prevent returning a numeric
+        # type so that we do not lose the ability to coerce to a
+        # Python bool if we have to.
+        return py_object_type
+    span_type = _spanning_type(type1, type2)
+    if span_type is None:
+        return error_type
+    return span_type
 
 def spanning_type(type1, type2):
-    # Return a type assignable from both type1 and type2.
-    if type1 is py_object_type or type2 is py_object_type:
-        return py_object_type
-    elif type1 == type2:
+    # Return a type assignable from both type1 and type2, or
+    # py_object_type if no better type is found.  Assumes that the
+    # code that calls this will try a coercion afterwards, which will
+    # fail if the types cannot actually coerce to a py_object_type.
+    if type1 == type2:
         return type1
-    elif type1.is_numeric and type2.is_numeric:
+    elif type1 is py_object_type or type2 is py_object_type:
+        return py_object_type
+    elif type1 is c_py_unicode_type or type2 is c_py_unicode_type:
+        # Py_UNICODE behaves more like a string than an int
+        return py_object_type
+    span_type = _spanning_type(type1, type2)
+    if span_type is None:
+        return py_object_type
+    return span_type
+
+def _spanning_type(type1, type2):
+    if type1.is_numeric and type2.is_numeric:
         return widest_numeric_type(type1, type2)
     elif type1.is_builtin_type and type1.name == 'float' and type2.is_numeric:
         return widest_numeric_type(c_double_type, type2)
     elif type2.is_builtin_type and type2.name == 'float' and type1.is_numeric:
         return widest_numeric_type(type1, c_double_type)
-    elif type1.is_pyobject ^ type2.is_pyobject:
-        return py_object_type
     elif type1.is_extension_type and type2.is_extension_type:
-        if type1.typeobj_is_imported() or type2.typeobj_is_imported():
-            return py_object_type
-        while True:
-            if type1.subtype_of(type2):
-                return type2
-            elif type2.subtype_of(type1):
-                return type1
-            type1, type2 = type1.base_type, type2.base_type
-            if type1 is None or type2 is None:
-                return py_object_type
+        return widest_extension_type(type1, type2)
+    elif type1.is_pyobject or type2.is_pyobject:
+        return py_object_type
     elif type1.assignable_from(type2):
         if type1.is_extension_type and type1.typeobj_is_imported():
             # external types are unsafe, so we use PyObject instead
@@ -2377,13 +2667,25 @@ def spanning_type(type1, type2):
             return py_object_type
         return type2
     else:
+        return None
+
+def widest_extension_type(type1, type2):
+    if type1.typeobj_is_imported() or type2.typeobj_is_imported():
         return py_object_type
-    
+    while True:
+        if type1.subtype_of(type2):
+            return type2
+        elif type2.subtype_of(type1):
+            return type1
+        type1, type2 = type1.base_type, type2.base_type
+        if type1 is None or type2 is None:
+            return py_object_type
+
 def simple_c_type(signed, longness, name):
     # Find type descriptor for simple type given name and modifiers.
     # Returns None if arguments don't make sense.
     return modifiers_and_name_to_type.get((signed, longness, name))
-    
+
 def parse_basic_type(name):
     base = None
     if name.startswith('p_'):
@@ -2394,10 +2696,43 @@ 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_UCS4':
+        signed = 0
+    elif name == 'Py_hash_t':
+        signed = 2
+    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.
@@ -2425,23 +2760,10 @@ 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)
-    
+
 def assignable_from(type1, type2):
     return type1.assignable_from(type2)
 
@@ -2460,19 +2782,10 @@ 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_Owned_Py_None(b) (Py_INCREF(Py_None), Py_None)
 #define __Pyx_PyBool_FromLong(b) ((b) ? (Py_INCREF(Py_True), Py_True) : (Py_INCREF(Py_False), Py_False))
 static CYTHON_INLINE int __Pyx_PyObject_IsTrue(PyObject*);
 static CYTHON_INLINE PyObject* __Pyx_PyNumber_Int(PyObject* x);
@@ -2578,4 +2891,3 @@ static CYTHON_INLINE size_t __Pyx_PyInt_AsSize_t(PyObject* x) {
 
 """ + type_conversion_functions
 
-