fix ticket #644: infer type of C-API optimised methods of builtin types as Python...
[cython.git] / Cython / Compiler / ExprNodes.py
index ddce68088c8431c024865879328898c0b366c2a1..93eba7cc2eb07e4583e5926cfdeccfaba01e35c8 100755 (executable)
@@ -2,9 +2,19 @@
 #   Pyrex - Parse tree nodes for expressions
 #
 
+import cython
+from cython import set
+cython.declare(error=object, warning=object, warn_once=object, InternalError=object,
+               CompileError=object, UtilityCode=object, StringEncoding=object, operator=object,
+               Naming=object, Nodes=object, PyrexTypes=object, py_object_type=object,
+               list_type=object, tuple_type=object, set_type=object, dict_type=object, \
+               unicode_type=object, str_type=object, bytes_type=object, type_type=object,
+               Builtin=object, Symtab=object, Utils=object, find_coercion_error=object,
+               debug_disposal_code=object, debug_temp_alloc=object, debug_coercion=object)
+
 import operator
 
-from Errors import error, warning, warn_once, InternalError
+from Errors import error, warning, warn_once, InternalError, CompileError
 from Errors import hold_errors, release_errors, held_errors, report_error
 from Code import UtilityCode
 import StringEncoding
@@ -21,16 +31,15 @@ import Symtab
 import Options
 from Cython import Utils
 from Annotate import AnnotationItem
-from Cython import Utils
 
 from Cython.Debugging import print_call_chain
 from DebugFlags import debug_disposal_code, debug_temp_alloc, \
     debug_coercion
 
 try:
-    set
-except NameError:
-    from sets import Set as set
+    from __builtin__ import basestring
+except ImportError:
+    basestring = str # Python 3
 
 class NotConstant(object):
     def __repr__(self):
@@ -61,14 +70,14 @@ class ExprNode(Node):
     #  result_code  string       Code fragment
     #  result_ctype string       C type of result_code if different from type
     #  is_temp      boolean      Result is in a temporary variable
-    #  is_sequence_constructor  
+    #  is_sequence_constructor
     #               boolean      Is a list or tuple constructor expression
     #  is_starred   boolean      Is a starred expression (e.g. '*a')
     #  saved_subexpr_nodes
     #               [ExprNode or [ExprNode or None] or None]
     #                            Cached result of subexpr_nodes()
     #  use_managed_ref boolean   use ref-counted temps/assignments/etc.
-    
+
     result_ctype = None
     type = None
     temp_code = None
@@ -101,8 +110,8 @@ class ExprNode(Node):
     #  'subexprs' class attribute of ExprNodes, which should
     #  contain a list of the names of attributes which can
     #  hold sub-nodes or sequences of sub-nodes.
-    #  
-    #  The framework makes use of a number of abstract methods. 
+    #
+    #  The framework makes use of a number of abstract methods.
     #  Their responsibilities are as follows.
     #
     #    Declaration Analysis phase
@@ -125,7 +134,7 @@ class ExprNode(Node):
     #
     #      analyse_target_types
     #        Called during the Analyse Types phase to analyse
-    #        the LHS of an assignment or argument of a del 
+    #        the LHS of an assignment or argument of a del
     #        statement. Similar responsibilities to analyse_types.
     #
     #      target_code
@@ -136,9 +145,9 @@ class ExprNode(Node):
     #      check_const
     #        - Check that this node and its subnodes form a
     #          legal constant expression. If so, do nothing,
-    #          otherwise call not_const. 
+    #          otherwise call not_const.
     #
-    #        The default implementation of check_const 
+    #        The default implementation of check_const
     #        assumes that the expression is not constant.
     #
     #      check_const_addr
@@ -147,7 +156,7 @@ class ExprNode(Node):
     #          constant. Otherwise, call addr_not_const.
     #
     #        The default implementation of calc_const_addr
-    #        assumes that the expression is not a constant 
+    #        assumes that the expression is not a constant
     #        lvalue.
     #
     #   Code Generation phase
@@ -168,8 +177,8 @@ class ExprNode(Node):
     #              sub-expressions.
     #
     #          calculate_result_code
-    #            - Should return a C code fragment evaluating to the 
-    #              result. This is only called when the result is not 
+    #            - Should return a C code fragment evaluating to the
+    #              result. This is only called when the result is not
     #              a temporary.
     #
     #      generate_assignment_code
@@ -187,10 +196,10 @@ class ExprNode(Node):
     #        - Call generate_disposal_code on all sub-expressions.
     #
     #
-    
+
     is_sequence_constructor = 0
     is_attribute = 0
-    
+
     saved_subexpr_nodes = None
     is_temp = 0
     is_target = 0
@@ -202,19 +211,20 @@ class ExprNode(Node):
         _get_child_attrs = operator.attrgetter('subexprs')
     except AttributeError:
         # Python 2.3
-        def _get_child_attrs(self):
+        def __get_child_attrs(self):
             return self.subexprs
+        _get_child_attrs = __get_child_attrs
     child_attrs = property(fget=_get_child_attrs)
-        
+
     def not_implemented(self, method_name):
         print_call_chain(method_name, "not implemented") ###
         raise InternalError(
             "%s.%s not implemented" %
                 (self.__class__.__name__, method_name))
-                
+
     def is_lvalue(self):
         return 0
-    
+
     def is_ephemeral(self):
         #  An ephemeral node is one whose result is in
         #  a Python temporary and we suspect there are no
@@ -235,21 +245,21 @@ class ExprNode(Node):
                 else:
                     nodes.append(item)
         return nodes
-        
+
     def result(self):
         if self.is_temp:
             return self.temp_code
         else:
             return self.calculate_result_code()
-    
+
     def result_as(self, type = None):
         #  Return the result code cast to the specified C type.
         return typecast(type, self.ctype(), self.result())
-    
+
     def py_result(self):
         #  Return the result code cast to PyObject *.
         return self.result_as(py_object_type)
-    
+
     def ctype(self):
         #  Return the native C type of the result (i.e. the
         #  C type of the result_code expression).
@@ -285,18 +295,18 @@ class ExprNode(Node):
     def compile_time_value(self, denv):
         #  Return value of compile-time expression, or report error.
         error(self.pos, "Invalid compile-time expression")
-    
+
     def compile_time_value_error(self, e):
         error(self.pos, "Error in compile-time expression: %s: %s" % (
             e.__class__.__name__, e))
-    
+
     # ------------- Declaration Analysis ----------------
-    
+
     def analyse_target_declaration(self, env):
         error(self.pos, "Cannot assign to or delete this")
-    
+
     # ------------- Expression Analysis ----------------
-    
+
     def analyse_const_expression(self, env):
         #  Called during the analyse_declarations phase of a
         #  constant expression. Analyses the expression's type,
@@ -304,25 +314,25 @@ class ExprNode(Node):
         #  and determines its value.
         self.analyse_types(env)
         return self.check_const()
-    
+
     def analyse_expressions(self, env):
         #  Convenience routine performing both the Type
-        #  Analysis and Temp Allocation phases for a whole 
+        #  Analysis and Temp Allocation phases for a whole
         #  expression.
         self.analyse_types(env)
-    
+
     def analyse_target_expression(self, env, rhs):
         #  Convenience routine performing both the Type
         #  Analysis and Temp Allocation phases for the LHS of
         #  an assignment.
         self.analyse_target_types(env)
-    
+
     def analyse_boolean_expression(self, env):
         #  Analyse expression and coerce to a boolean.
         self.analyse_types(env)
         bool = self.coerce_to_boolean(env)
         return bool
-    
+
     def analyse_temp_boolean_expression(self, env):
         #  Analyse boolean expression and coerce result into
         #  a temporary. This is used when a branch is to be
@@ -335,17 +345,17 @@ class ExprNode(Node):
         return self.coerce_to_boolean(env).coerce_to_simple(env)
 
     # --------------- Type Inference -----------------
-    
+
     def type_dependencies(self, env):
         # Returns the list of entries whose types must be determined
         # before the type of self can be infered.
         if hasattr(self, 'type') and self.type is not None:
             return ()
         return sum([node.type_dependencies(env) for node in self.subexpr_nodes()], ())
-    
+
     def infer_type(self, env):
-        # Attempt to deduce the type of self. 
-        # Differs from analyse_types as it avoids unnecessary 
+        # Attempt to deduce the type of self.
+        # Differs from analyse_types as it avoids unnecessary
         # analysis of subexpressions, but can assume everything
         # in self.type_dependencies() has been resolved.
         if hasattr(self, 'type') and self.type is not None:
@@ -354,27 +364,27 @@ class ExprNode(Node):
             return self.entry.type
         else:
             self.not_implemented("infer_type")
-    
+
     # --------------- Type Analysis ------------------
-    
+
     def analyse_as_module(self, env):
         # If this node can be interpreted as a reference to a
         # cimported module, return its scope, else None.
         return None
-        
+
     def analyse_as_type(self, env):
         # If this node can be interpreted as a reference to a
         # type, return that type, else None.
         return None
-    
+
     def analyse_as_extension_type(self, env):
         # If this node can be interpreted as a reference to an
         # extension type, return its type, else None.
         return None
-    
+
     def analyse_types(self, env):
         self.not_implemented("analyse_types")
-    
+
     def analyse_target_types(self, env):
         self.analyse_types(env)
 
@@ -392,33 +402,33 @@ class ExprNode(Node):
     def check_const(self):
         self.not_const()
         return False
-    
+
     def not_const(self):
         error(self.pos, "Not allowed in a constant expression")
-    
+
     def check_const_addr(self):
         self.addr_not_const()
         return False
-    
+
     def addr_not_const(self):
         error(self.pos, "Address is not constant")
 
     # ----------------- Result Allocation -----------------
-    
+
     def result_in_temp(self):
         #  Return true if result is in a temporary owned by
         #  this node or one of its subexpressions. Overridden
         #  by certain nodes which can share the result of
         #  a subnode.
         return self.is_temp
-            
+
     def target_code(self):
         #  Return code fragment for use as LHS of a C assignment.
         return self.calculate_result_code()
-    
+
     def calculate_result_code(self):
         self.not_implemented("calculate_result_code")
-    
+
 #    def release_target_temp(self, env):
 #        #  Release temporaries used by LHS of an assignment.
 #        self.release_subexpr_temps(env)
@@ -448,16 +458,16 @@ class ExprNode(Node):
         self.temp_code = None
 
     # ---------------- Code Generation -----------------
-    
+
     def make_owned_reference(self, code):
         #  If result is a pyobject, make sure we own
         #  a reference to it.
         if self.type.is_pyobject and not self.result_in_temp():
             code.put_incref(self.result(), self.ctype())
-    
+
     def generate_evaluation_code(self, code):
         code.mark_pos(self.pos)
-        
+
         #  Generate code to evaluate this node and
         #  its sub-expressions, and dispose of any
         #  temporary results of its sub-expressions.
@@ -476,10 +486,10 @@ class ExprNode(Node):
     def generate_subexpr_evaluation_code(self, code):
         for node in self.subexpr_nodes():
             node.generate_evaluation_code(code)
-    
+
     def generate_result_code(self, code):
         self.not_implemented("generate_result_code")
-    
+
     def generate_disposal_code(self, code):
         if self.is_temp:
             if self.type.is_pyobject:
@@ -493,7 +503,7 @@ class ExprNode(Node):
         #  of all sub-expressions.
         for node in self.subexpr_nodes():
             node.generate_disposal_code(code)
-    
+
     def generate_post_assignment_code(self, code):
         if self.is_temp:
             if self.type.is_pyobject:
@@ -503,10 +513,10 @@ class ExprNode(Node):
 
     def generate_assignment_code(self, rhs, code):
         #  Stub method for nodes which are not legal as
-        #  the LHS of an assignment. An error will have 
+        #  the LHS of an assignment. An error will have
         #  been reported earlier.
         pass
-    
+
     def generate_deletion_code(self, code):
         #  Stub method for nodes that are not legal as
         #  the argument of a del statement. An error
@@ -519,7 +529,7 @@ class ExprNode(Node):
                 self.release_temp_result(code)
         else:
             self.free_subexpr_temps(code)
-    
+
     def free_subexpr_temps(self, code):
         for sub in self.subexpr_nodes():
             sub.free_temps(code)
@@ -528,13 +538,13 @@ class ExprNode(Node):
         pass
 
     # ---------------- Annotation ---------------------
-    
+
     def annotate(self, code):
         for node in self.subexpr_nodes():
             node.annotate(code)
-    
+
     # ----------------- Coercion ----------------------
-    
+
     def coerce_to(self, dst_type, env):
         #   Coerce the result so that it can be assigned to
         #   something of type dst_type. If processing is necessary,
@@ -559,6 +569,9 @@ class ExprNode(Node):
         if self.check_for_coercion_error(dst_type):
             return self
 
+        if dst_type.is_reference:
+            dst_type = dst_type.ref_base_type
+
         if dst_type.is_pyobject:
             if not src.type.is_pyobject:
                 if dst_type is bytes_type and src.type.is_int:
@@ -570,7 +583,7 @@ class ExprNode(Node):
                     src = PyTypeTestNode(src, dst_type, env)
         elif src.type.is_pyobject:
             src = CoerceFromPyTypeNode(dst_type, src, env)
-        elif (dst_type.is_complex 
+        elif (dst_type.is_complex
               and src_type != dst_type
               and dst_type.assignable_from(src_type)):
             src = CoerceToComplexNode(src, dst_type, env)
@@ -615,31 +628,31 @@ class ExprNode(Node):
             return CoerceToBooleanNode(self, env)
         else:
             if not (type.is_int or type.is_enum or type.is_error):
-                error(self.pos, 
+                error(self.pos,
                     "Type '%s' not acceptable as a boolean" % type)
             return self
-    
+
     def coerce_to_integer(self, env):
         # If not already some C integer type, coerce to longint.
         if self.type.is_int:
             return self
         else:
             return self.coerce_to(PyrexTypes.c_long_type, env)
-    
+
     def coerce_to_temp(self, env):
         #  Ensure that the result is in a temporary.
         if self.result_in_temp():
             return self
         else:
             return CoerceToTempNode(self, env)
-    
+
     def coerce_to_simple(self, env):
         #  Ensure that the result is simple (see is_simple).
         if self.is_simple():
             return self
         else:
             return self.coerce_to_temp(env)
-    
+
     def is_simple(self):
         #  A node is simple if its result is something that can
         #  be referred to without performing any operations, e.g.
@@ -648,7 +661,11 @@ class ExprNode(Node):
         return self.result_in_temp()
 
     def may_be_none(self):
-        return self.type.is_pyobject
+        if not self.type.is_pyobject:
+            return False
+        if self.constant_result not in (not_a_constant, constant_value_not_set):
+            return self.constant_result is not None
+        return True
 
     def as_cython_attribute(self):
         return None
@@ -665,7 +682,7 @@ class ExprNode(Node):
 class AtomicExprNode(ExprNode):
     #  Abstract base class for expression nodes which have
     #  no sub-expressions.
-    
+
     subexprs = []
 
     # Override to optimize -- we know we have no children
@@ -676,10 +693,10 @@ class AtomicExprNode(ExprNode):
 
 class PyConstNode(AtomicExprNode):
     #  Abstract base class for constant Python values.
-    
+
     is_literal = 1
     type = py_object_type
-    
+
     def is_simple(self):
         return 1
 
@@ -688,7 +705,7 @@ class PyConstNode(AtomicExprNode):
 
     def analyse_types(self, env):
         pass
-    
+
     def calculate_result_code(self):
         return self.value
 
@@ -698,11 +715,11 @@ class PyConstNode(AtomicExprNode):
 
 class NoneNode(PyConstNode):
     #  The constant value None
-    
+
     value = "Py_None"
 
     constant_result = None
-    
+
     nogil_check = None
 
     def compile_time_value(self, denv):
@@ -714,7 +731,7 @@ class NoneNode(PyConstNode):
 
 class EllipsisNode(PyConstNode):
     #  '...' in a subscript list.
-    
+
     value = "Py_Ellipsis"
 
     constant_result = Ellipsis
@@ -727,7 +744,7 @@ class ConstNode(AtomicExprNode):
     # Abstract base type for literal constant nodes.
     #
     # value     string      C code fragment
-    
+
     is_literal = 1
     nogil_check = None
 
@@ -739,10 +756,10 @@ class ConstNode(AtomicExprNode):
 
     def analyse_types(self, env):
         pass # Types are held in class variables
-    
+
     def check_const(self):
         return True
-    
+
     def get_constant_c_result_code(self):
         return self.calculate_result_code()
 
@@ -762,7 +779,7 @@ class BoolNode(ConstNode):
 
     def compile_time_value(self, denv):
         return self.value
-    
+
     def calculate_result_code(self):
         return str(int(self.value))
 
@@ -781,10 +798,10 @@ class CharNode(ConstNode):
 
     def calculate_constant_result(self):
         self.constant_result = ord(self.value)
-    
+
     def compile_time_value(self, denv):
         return ord(self.value)
-    
+
     def calculate_result_code(self):
         return "'%s'" % StringEncoding.escape_char(self.value)
 
@@ -793,29 +810,69 @@ class IntNode(ConstNode):
 
     # unsigned     "" or "U"
     # longness     "" or "L" or "LL"
+    # is_c_literal   True/False/None   creator considers this a C integer literal
 
     unsigned = ""
     longness = ""
+    is_c_literal = None # unknown
 
     def __init__(self, pos, **kwds):
         ExprNode.__init__(self, pos, **kwds)
         if 'type' not in kwds:
-            rank = max(1, len(self.longness))
-            sign = not self.unsigned
-            self.type = PyrexTypes.modifiers_and_name_to_type[sign, rank, "int"]
+            self.type = self.find_suitable_type_for_value()
+
+    def find_suitable_type_for_value(self):
+        if self.constant_result is constant_value_not_set:
+            try:
+                self.calculate_constant_result()
+            except ValueError:
+                pass
+        # we ignore 'is_c_literal = True' and instead map signed 32bit
+        # integers as C long values
+        if self.is_c_literal or \
+               self.constant_result in (constant_value_not_set, not_a_constant) or \
+               self.unsigned or self.longness == 'LL':
+            # clearly a C literal
+            rank = (self.longness == 'LL') and 2 or 1
+            suitable_type = PyrexTypes.modifiers_and_name_to_type[not self.unsigned, rank, "int"]
+            if self.type:
+                suitable_type = PyrexTypes.widest_numeric_type(suitable_type, self.type)
+        else:
+            # C literal or Python literal - split at 32bit boundary
+            if self.constant_result >= -2**31 and self.constant_result < 2**31:
+                if self.type and self.type.is_int:
+                    suitable_type = self.type
+                else:
+                    suitable_type = PyrexTypes.c_long_type
+            else:
+                suitable_type = PyrexTypes.py_object_type
+        return suitable_type
 
     def coerce_to(self, dst_type, env):
         if self.type is dst_type:
             return self
         elif dst_type.is_float:
-            float_value = float(self.value)
-            return FloatNode(self.pos, value=repr(float_value), constant_result=float_value)
-        node = IntNode(self.pos, value=self.value, constant_result=self.constant_result,
-                       unsigned=self.unsigned, longness=self.longness)
+            if self.constant_result is not not_a_constant:
+                float_value = float(self.constant_result)
+                return FloatNode(self.pos, value=repr(float_value), type=dst_type,
+                                 constant_result=float_value)
+            else:
+                return FloatNode(self.pos, value=self.value, type=dst_type,
+                                 constant_result=not_a_constant)
         if dst_type.is_numeric and not dst_type.is_complex:
+            node = IntNode(self.pos, value=self.value, constant_result=self.constant_result,
+                           type = dst_type, is_c_literal = True,
+                           unsigned=self.unsigned, longness=self.longness)
             return node
-        if dst_type.is_pyobject:
-            node.type = PyrexTypes.py_object_type
+        elif dst_type.is_pyobject:
+            node = IntNode(self.pos, value=self.value, constant_result=self.constant_result,
+                           type = PyrexTypes.py_object_type, is_c_literal = False,
+                           unsigned=self.unsigned, longness=self.longness)
+        else:
+            # FIXME: not setting the type here to keep it working with
+            # complex numbers. Should they be special cased?
+            node = IntNode(self.pos, value=self.value, constant_result=self.constant_result,
+                           unsigned=self.unsigned, longness=self.longness)
         # We still need to perform normal coerce_to processing on the
         # result, because we might be coercing to an extension type,
         # in which case a type test node will be needed.
@@ -830,19 +887,28 @@ class IntNode(ConstNode):
     def generate_evaluation_code(self, code):
         if self.type.is_pyobject:
             # pre-allocate a Python version of the number
-            self.result_code = code.get_py_num(self.value, self.longness)
+            plain_integer_string = self.value_as_c_integer_string(plain_digits=True)
+            self.result_code = code.get_py_num(plain_integer_string, self.longness)
         else:
             self.result_code = self.get_constant_c_result_code()
-    
+
     def get_constant_c_result_code(self):
+        return self.value_as_c_integer_string() + self.unsigned + self.longness
+
+    def value_as_c_integer_string(self, plain_digits=False):
         value = self.value
         if isinstance(value, basestring) and len(value) > 2:
             # must convert C-incompatible Py3 oct/bin notations
             if value[1] in 'oO':
-                value = value[0] + value[2:] # '0o123' => '0123'
+                if plain_digits:
+                    value = int(value[2:], 8)
+                else:
+                    value = value[0] + value[2:] # '0o123' => '0123'
             elif value[1] in 'bB':
                 value = int(value[2:], 2)
-        return str(value) + self.unsigned + self.longness
+            elif plain_digits and value[1] in 'xX':
+                value = int(value[2:], 16)
+        return str(value)
 
     def calculate_result_code(self):
         return self.result_code
@@ -862,7 +928,7 @@ class FloatNode(ConstNode):
 
     def compile_time_value(self, denv):
         return float(self.value)
-    
+
     def calculate_result_code(self):
         strval = self.value
         assert isinstance(strval, (str, unicode))
@@ -882,14 +948,15 @@ class BytesNode(ConstNode):
     #
     # value      BytesLiteral
 
-    type = PyrexTypes.c_char_ptr_type
+    # start off as Python 'bytes' to support len() in O(1)
+    type = bytes_type
 
     def compile_time_value(self, denv):
         return self.value
 
     def analyse_as_type(self, env):
         type = PyrexTypes.parse_basic_type(self.value)
-        if type is not None:    
+        if type is not None:
             return type
         from TreeFragment import TreeFragment
         pos = (self.pos[0], self.pos[1], self.pos[2]-7)
@@ -903,11 +970,13 @@ class BytesNode(ConstNode):
         return len(self.value) == 1
 
     def coerce_to_boolean(self, env):
-        # This is special because we start off as a C char*.  Testing
-        # that for truth directly would yield the wrong result.
+        # This is special because testing a C char* for truth directly
+        # would yield the wrong result.
         return BoolNode(self.pos, value=bool(self.value))
 
     def coerce_to(self, dst_type, env):
+        if self.type == dst_type:
+            return self
         if dst_type.is_int:
             if not self.can_coerce_to_char_literal():
                 error(self.pos, "Only single-character string literals can be coerced into ints.")
@@ -918,21 +987,20 @@ class BytesNode(ConstNode):
             return CharNode(self.pos, value=self.value)
 
         node = BytesNode(self.pos, value=self.value)
-        if dst_type == PyrexTypes.c_char_ptr_type:
-            node.type = PyrexTypes.c_char_ptr_type
+        if dst_type.is_pyobject:
+            if dst_type in (py_object_type, Builtin.bytes_type):
+                node.type = Builtin.bytes_type
+            else:
+                self.check_for_coercion_error(dst_type, fail=True)
+                return node
+        elif dst_type == PyrexTypes.c_char_ptr_type:
+            node.type = dst_type
             return node
         elif dst_type == PyrexTypes.c_uchar_ptr_type:
             node.type = PyrexTypes.c_char_ptr_type
             return CastNode(node, PyrexTypes.c_uchar_ptr_type)
-
-        if not self.type.is_pyobject:
-            if dst_type in (py_object_type, Builtin.bytes_type):
-                node.type = Builtin.bytes_type
-            elif dst_type.is_pyobject:
-                self.fail_assignment(dst_type)
-                return self
-        elif dst_type.is_pyobject and dst_type is not py_object_type:
-            self.check_for_coercion_error(dst_type, fail=True)
+        elif dst_type.assignable_from(PyrexTypes.c_char_ptr_type):
+            node.type = dst_type
             return node
 
         # We still need to perform normal coerce_to processing on the
@@ -940,11 +1008,6 @@ class BytesNode(ConstNode):
         # in which case a type test node will be needed.
         return ConstNode.coerce_to(node, dst_type, env)
 
-    def as_py_string_node(self, env):
-        # Return a new BytesNode with the same value as this node
-        # but whose type is a Python type instead of a C type.
-        return BytesNode(self.pos, value = self.value, type = Builtin.bytes_type)
-
     def generate_evaluation_code(self, code):
         if self.type.is_pyobject:
             self.result_code = code.get_py_string_const(self.value)
@@ -953,7 +1016,7 @@ class BytesNode(ConstNode):
 
     def get_constant_c_result_code(self):
         return None # FIXME
-    
+
     def calculate_result_code(self):
         return self.result_code
 
@@ -1011,7 +1074,7 @@ class UnicodeNode(PyConstNode):
 
     def calculate_result_code(self):
         return self.result_code
-        
+
     def compile_time_value(self, env):
         return self.value
 
@@ -1020,8 +1083,8 @@ class StringNode(PyConstNode):
     # A Python str object, i.e. a byte string in Python 2.x and a
     # unicode string in Python 3.x
     #
-    # value          BytesLiteral
-    # unicode_value  EncodedString
+    # value          BytesLiteral (or EncodedString with ASCII content)
+    # unicode_value  EncodedString or None
     # is_identifier  boolean
 
     type = str_type
@@ -1038,12 +1101,13 @@ class StringNode(PyConstNode):
             self.check_for_coercion_error(dst_type, fail=True)
 
         # this will be a unicode string in Py3, so make sure we can decode it
-        if self.value.encoding:
-            encoding = self.value.encoding
+        if self.value.encoding and isinstance(self.value, StringEncoding.BytesLiteral):
             try:
-                self.value.decode(encoding)
+                self.value.decode(self.value.encoding)
             except UnicodeDecodeError:
-                error(self.pos, "String decoding as '%s' failed. Consider using a byte string or unicode string explicitly, or adjust the source code encoding." % encoding)
+                error(self.pos, ("Decoding unprefixed string literal from '%s' failed. Consider using"
+                                 "a byte string or unicode string explicitly, "
+                                 "or adjust the source code encoding.") % self.value.encoding)
 
         return self
 
@@ -1059,7 +1123,7 @@ class StringNode(PyConstNode):
 
     def calculate_result_code(self):
         return self.result_code
-        
+
     def compile_time_value(self, env):
         return self.value
 
@@ -1079,10 +1143,10 @@ class LongNode(AtomicExprNode):
 
     def calculate_constant_result(self):
         self.constant_result = Utils.str_to_number(self.value)
-    
+
     def compile_time_value(self, denv):
         return Utils.str_to_number(self.value)
-    
+
     def analyse_types(self, env):
         self.is_temp = 1
 
@@ -1104,15 +1168,15 @@ class ImagNode(AtomicExprNode):
     #  Imaginary number literal
     #
     #  value   float    imaginary part
-    
+
     type = PyrexTypes.c_double_complex_type
 
     def calculate_constant_result(self):
         self.constant_result = complex(0.0, self.value)
-    
+
     def compile_time_value(self, denv):
         return complex(0.0, self.value)
-    
+
     def analyse_types(self, env):
         self.type.create_declaration_utility_code(env)
 
@@ -1147,16 +1211,16 @@ class ImagNode(AtomicExprNode):
                     float(self.value),
                     code.error_goto_if_null(self.result(), self.pos)))
             code.put_gotref(self.py_result())
-        
+
 
 class NewExprNode(AtomicExprNode):
 
     # C++ new statement
     #
     # cppclass              node                 c++ class to create
-    
+
     type = None
-    
+
     def infer_type(self, env):
         type = self.cppclass.analyse_as_type(env)
         if type is None or not type.is_cpp_class:
@@ -1174,7 +1238,7 @@ class NewExprNode(AtomicExprNode):
         self.entry = constructor
         self.type = constructor.type
         return self.type
-    
+
     def analyse_types(self, env):
         if self.type is None:
             self.infer_type(env)
@@ -1184,7 +1248,7 @@ class NewExprNode(AtomicExprNode):
 
     def generate_result_code(self, code):
         pass
-   
+
     def calculate_result_code(self):
         return "new " + self.class_type.declaration_code("")
 
@@ -1195,7 +1259,7 @@ class NameNode(AtomicExprNode):
     #  name            string    Python name of the variable
     #  entry           Entry     Symbol table entry
     #  type_entry      Entry     For extension type names, the original type entry
-    
+
     is_name = True
     is_cython_module = False
     cython_attribute = None
@@ -1208,12 +1272,12 @@ class NameNode(AtomicExprNode):
         node = NameNode(pos)
         node.analyse_types(env, entry=entry)
         return node
-        
+
     def as_cython_attribute(self):
         return self.cython_attribute
-    
+
     create_analysed_rvalue = staticmethod(create_analysed_rvalue)
-    
+
     def type_dependencies(self, env):
         if self.entry is None:
             self.entry = env.lookup(self.name)
@@ -1221,7 +1285,7 @@ class NameNode(AtomicExprNode):
             return (self.entry,)
         else:
             return ()
-    
+
     def infer_type(self, env):
         if self.entry is None:
             self.entry = env.lookup(self.name)
@@ -1232,9 +1296,12 @@ class NameNode(AtomicExprNode):
             # Unfortunately the type attribute of type objects
             # is used for the pointer to the type they represent.
             return type_type
+        elif self.entry.type.is_cfunction:
+            # special case: referring to a C function must return its pointer
+            return PyrexTypes.CPtrType(self.entry.type)
         else:
             return self.entry.type
-    
+
     def compile_time_value(self, denv):
         try:
             return denv.lookup(self.name)
@@ -1245,7 +1312,7 @@ class NameNode(AtomicExprNode):
         if not self.entry or self.entry.type.is_pyobject:
             return None
         return self.entry.cname
-    
+
     def coerce_to(self, dst_type, env):
         #  If coercing to a generic pyobject and this is a builtin
         #  C function with a Python equivalent, manufacture a NameNode
@@ -1263,7 +1330,7 @@ class NameNode(AtomicExprNode):
                     node.analyse_rvalue_entry(env)
                     return node
         return super(NameNode, self).coerce_to(dst_type, env)
-    
+
     def analyse_as_module(self, env):
         # Try to interpret this as a reference to a cimported module.
         # Returns the module scope, or None.
@@ -1273,7 +1340,7 @@ class NameNode(AtomicExprNode):
         if entry and entry.as_module:
             return entry.as_module
         return None
-        
+
     def analyse_as_type(self, env):
         if self.cython_attribute:
             type = PyrexTypes.parse_basic_type(self.cython_attribute)
@@ -1288,7 +1355,7 @@ class NameNode(AtomicExprNode):
             return entry.type
         else:
             return None
-    
+
     def analyse_as_extension_type(self, env):
         # Try to interpret this as a reference to an extension type.
         # Returns the extension type, or None.
@@ -1299,7 +1366,7 @@ class NameNode(AtomicExprNode):
             return entry.type
         else:
             return None
-    
+
     def analyse_target_declaration(self, env):
         if not self.entry:
             self.entry = env.lookup_here(self.name)
@@ -1315,7 +1382,7 @@ class NameNode(AtomicExprNode):
         env.control_flow.set_state(self.pos, (self.name, 'source'), 'assignment')
         if self.entry.is_declared_generic:
             self.result_ctype = py_object_type
-    
+
     def analyse_types(self, env):
         if self.entry is None:
             self.entry = env.lookup(self.name)
@@ -1333,7 +1400,7 @@ class NameNode(AtomicExprNode):
             if entry.utility_code:
                 env.use_utility_code(entry.utility_code)
         self.analyse_rvalue_entry(env)
-        
+
     def analyse_target_types(self, env):
         self.analyse_entry(env)
         if not self.is_lvalue():
@@ -1344,7 +1411,7 @@ class NameNode(AtomicExprNode):
         if self.entry.type.is_buffer:
             import Buffer
             Buffer.used_buffer_aux_vars(self.entry)
-                
+
     def analyse_rvalue_entry(self, env):
         #print "NameNode.analyse_rvalue_entry:", self.name ###
         #print "Entry:", self.entry.__dict__ ###
@@ -1364,8 +1431,8 @@ class NameNode(AtomicExprNode):
         if self.is_used_as_rvalue:
             entry = self.entry
             if entry.is_builtin:
-                if not Options.cache_builtins: # cached builtins are ok
-                self.gil_error()
+                if not Options.cache_builtins: # cached builtins are ok
+                    self.gil_error()
             elif entry.is_pyglobal:
                 self.gil_error()
 
@@ -1385,29 +1452,29 @@ class NameNode(AtomicExprNode):
         entry = self.entry
         if entry.is_type and entry.type.is_extension_type:
             self.type_entry = entry
-        if not (entry.is_const or entry.is_variable 
+        if not (entry.is_const or entry.is_variable
             or entry.is_builtin or entry.is_cfunction
             or entry.is_cpp_class):
                 if self.entry.as_variable:
                     self.entry = self.entry.as_variable
                 else:
-                    error(self.pos, 
+                    error(self.pos,
                           "'%s' is not a constant, variable or function identifier" % self.name)
 
     def is_simple(self):
         #  If it's not a C variable, it'll be in a temp.
         return 1
-    
+
     def calculate_target_results(self, env):
         pass
-    
+
     def check_const(self):
         entry = self.entry
         if entry is not None and not (entry.is_const or entry.is_cfunction or entry.is_builtin):
             self.not_const()
             return False
         return True
-    
+
     def check_const_addr(self):
         entry = self.entry
         if not (entry.is_cglobal or entry.is_cfunction or entry.is_builtin):
@@ -1419,18 +1486,18 @@ class NameNode(AtomicExprNode):
         return self.entry.is_variable and \
             not self.entry.type.is_array and \
             not self.entry.is_readonly
-    
+
     def is_ephemeral(self):
         #  Name nodes are never ephemeral, even if the
         #  result is in a temporary.
         return 0
-    
+
     def calculate_result_code(self):
         entry = self.entry
         if not entry:
             return "<error>" # There was an error earlier
         return entry.cname
-    
+
     def generate_result_code(self, code):
         assert hasattr(self, 'entry')
         entry = self.entry
@@ -1438,6 +1505,21 @@ class NameNode(AtomicExprNode):
             return # There was an error earlier
         if entry.is_builtin and Options.cache_builtins:
             return # Lookup already cached
+        elif entry.is_pyclass_attr:
+            assert entry.type.is_pyobject, "Python global or builtin not a Python object"
+            interned_cname = code.intern_identifier(self.entry.name)
+            if entry.is_builtin:
+                namespace = Naming.builtins_cname
+            else: # entry.is_pyglobal
+                namespace = entry.scope.namespace_cname
+            code.putln(
+                '%s = PyObject_GetItem(%s, %s); %s' % (
+                self.result(),
+                namespace,
+                interned_cname,
+                code.error_goto_if_null(self.result(), self.pos)))
+            code.put_gotref(self.py_result())
+
         elif entry.is_pyglobal or entry.is_builtin:
             assert entry.type.is_pyobject, "Python global or builtin not a Python object"
             interned_cname = code.intern_identifier(self.entry.name)
@@ -1449,11 +1531,11 @@ class NameNode(AtomicExprNode):
             code.putln(
                 '%s = __Pyx_GetName(%s, %s); %s' % (
                 self.result(),
-                namespace, 
+                namespace,
                 interned_cname,
                 code.error_goto_if_null(self.result(), self.pos)))
             code.put_gotref(self.py_result())
-            
+
         elif entry.is_local and False:
             # control flow not good enough yet
             assigned = entry.scope.control_flow.get_state((entry.name, 'initialized'), self.pos)
@@ -1473,7 +1555,7 @@ class NameNode(AtomicExprNode):
         if (self.entry.type.is_ptr and isinstance(rhs, ListNode)
             and not self.lhs_of_first_assignment):
             error(self.pos, "Literal list must be assigned to pointer at time of declaration")
-        
+
         # is_pyglobal seems to be True for module level-globals only.
         # We use this to access class->tp_dict if necessary.
         if entry.is_pyglobal:
@@ -1492,8 +1574,16 @@ class NameNode(AtomicExprNode):
                 rhs.free_temps(code)
                 # in Py2.6+, we need to invalidate the method cache
                 code.putln("PyType_Modified(%s);" %
-                           entry.scope.parent_type.typeptr_cname)
-            else: 
+                            entry.scope.parent_type.typeptr_cname)
+            elif entry.is_pyclass_attr:
+                code.put_error_if_neg(self.pos,
+                    'PyObject_SetItem(%s, %s, %s)' % (
+                        namespace,
+                        interned_cname,
+                        rhs.py_result()))
+                rhs.generate_disposal_code(code)
+                rhs.free_temps(code)
+            else:
                 code.put_error_if_neg(self.pos,
                     'PyObject_SetAttr(%s, %s, %s)' % (
                         namespace,
@@ -1561,22 +1651,29 @@ class NameNode(AtomicExprNode):
         Buffer.put_assign_to_buffer(self.result(), rhstmp, buffer_aux, self.entry.type,
                                     is_initialized=not self.lhs_of_first_assignment,
                                     pos=self.pos, code=code)
-        
+
         if not pretty_rhs:
             code.putln("%s = 0;" % rhstmp)
             code.funcstate.release_temp(rhstmp)
-    
+
     def generate_deletion_code(self, code):
         if self.entry is None:
             return # There was an error earlier
         if not self.entry.is_pyglobal:
             error(self.pos, "Deletion of local or C global name not supported")
             return
-        code.put_error_if_neg(self.pos, 
-            '__Pyx_DelAttrString(%s, "%s")' % (
-                Naming.module_cname,
-                self.entry.name))
-                
+        if self.entry.is_pyclass_attr:
+            namespace = self.entry.scope.namespace_cname
+            code.put_error_if_neg(self.pos,
+                'PyMapping_DelItemString(%s, "%s")' % (
+                    namespace,
+                    self.entry.name))
+        else:
+            code.put_error_if_neg(self.pos,
+                '__Pyx_DelAttrString(%s, "%s")' % (
+                    Naming.module_cname,
+                    self.entry.name))
+
     def annotate(self, code):
         if hasattr(self, 'is_called') and self.is_called:
             pos = (self.pos[0], self.pos[1], self.pos[2] - len(self.name) - 1)
@@ -1584,16 +1681,16 @@ class NameNode(AtomicExprNode):
                 code.annotate(pos, AnnotationItem('py_call', 'python function', size=len(self.name)))
             else:
                 code.annotate(pos, AnnotationItem('c_call', 'c function', size=len(self.name)))
-            
+
 class BackquoteNode(ExprNode):
     #  `expr`
     #
     #  arg    ExprNode
-    
+
     type = py_object_type
-    
+
     subexprs = ['arg']
-    
+
     def analyse_types(self, env):
         self.arg.analyse_types(env)
         self.arg = self.arg.coerce_to_pyobject(env)
@@ -1611,21 +1708,21 @@ class BackquoteNode(ExprNode):
                 self.arg.py_result(),
                 code.error_goto_if_null(self.result(), self.pos)))
         code.put_gotref(self.py_result())
-        
+
 
 
 class ImportNode(ExprNode):
     #  Used as part of import statement implementation.
-    #  Implements result = 
+    #  Implements result =
     #    __import__(module_name, globals(), None, name_list)
     #
     #  module_name   StringNode            dotted name of module
     #  name_list     ListNode or None      list of names to be imported
-    
+
     type = py_object_type
-    
+
     subexprs = ['module_name', 'name_list']
-    
+
     def analyse_types(self, env):
         self.module_name.analyse_types(env)
         self.module_name = self.module_name.coerce_to_pyobject(env)
@@ -1660,20 +1757,22 @@ class IteratorNode(ExprNode):
     #  Implements result = iter(sequence)
     #
     #  sequence   ExprNode
-    
+
     type = py_object_type
-    
+
     subexprs = ['sequence']
-    
+
     def analyse_types(self, env):
         self.sequence.analyse_types(env)
-        if isinstance(self.sequence, SliceIndexNode) and \
-               (self.sequence.base.type.is_array or self.sequence.base.type.is_ptr) \
-               or self.sequence.type.is_array and self.sequence.type.size is not None:
+        if (self.sequence.type.is_array or self.sequence.type.is_ptr) and \
+                not self.sequence.type.is_string:
             # C array iteration will be transformed later on
-            pass
+            self.type = self.sequence.type
         else:
             self.sequence = self.sequence.coerce_to_pyobject(env)
+            if self.sequence.type is list_type or \
+                   self.sequence.type is tuple_type:
+                self.sequence = self.sequence.as_none_safe_node("'NoneType' object is not iterable")
         self.is_temp = 1
 
     gil_message = "Iterating over Python object"
@@ -1686,38 +1785,34 @@ class IteratorNode(ExprNode):
         code.funcstate.release_temp(self.counter_cname)
 
     def generate_result_code(self, code):
+        if self.sequence.type.is_array or self.sequence.type.is_ptr:
+            raise InternalError("for in carray slice not transformed")
         is_builtin_sequence = self.sequence.type is list_type or \
                               self.sequence.type is tuple_type
-        may_be_a_sequence = is_builtin_sequence or not self.sequence.type.is_builtin_type
-        if is_builtin_sequence:
-            code.putln(
-                "if (likely(%s != Py_None)) {" % self.sequence.py_result())
-        elif may_be_a_sequence:
+        may_be_a_sequence = not self.sequence.type.is_builtin_type
+        if may_be_a_sequence:
             code.putln(
                 "if (PyList_CheckExact(%s) || PyTuple_CheckExact(%s)) {" % (
                     self.sequence.py_result(),
                     self.sequence.py_result()))
-        if may_be_a_sequence:
+        if is_builtin_sequence or may_be_a_sequence:
             code.putln(
                 "%s = 0; %s = %s; __Pyx_INCREF(%s);" % (
                     self.counter_cname,
                     self.result(),
                     self.sequence.py_result(),
                     self.result()))
-            code.putln("} else {")
-        if is_builtin_sequence:
-            code.putln(
-                'PyErr_SetString(PyExc_TypeError, "\'NoneType\' object is not iterable"); %s' %
-                code.error_goto(self.pos))
-        else:
+        if not is_builtin_sequence:
+            if may_be_a_sequence:
+                code.putln("} else {")
             code.putln("%s = -1; %s = PyObject_GetIter(%s); %s" % (
                     self.counter_cname,
                     self.result(),
                     self.sequence.py_result(),
                     code.error_goto_if_null(self.result(), self.pos)))
             code.put_gotref(self.py_result())
-        if may_be_a_sequence:
-            code.putln("}")
+            if may_be_a_sequence:
+                code.putln("}")
 
 
 class NextNode(AtomicExprNode):
@@ -1727,14 +1822,16 @@ class NextNode(AtomicExprNode):
     #  The iterator is not owned by this node.
     #
     #  iterator   ExprNode
-    
+
     type = py_object_type
-    
+
     def __init__(self, iterator, env):
         self.pos = iterator.pos
         self.iterator = iterator
+        if iterator.type.is_ptr or iterator.type.is_array:
+            self.type = iterator.type.base_type
         self.is_temp = 1
-    
+
     def generate_result_code(self, code):
         sequence_type = self.iterator.sequence.type
         if sequence_type is list_type:
@@ -1787,15 +1884,15 @@ class ExcValueNode(AtomicExprNode):
     #  Node created during analyse_types phase
     #  of an ExceptClauseNode to fetch the current
     #  exception value.
-    
+
     type = py_object_type
-    
+
     def __init__(self, pos, env):
         ExprNode.__init__(self, pos)
 
     def set_var(self, var):
         self.var = var
-    
+
     def calculate_result_code(self):
         return self.var
 
@@ -1816,17 +1913,17 @@ class TempNode(ExprNode):
     # the regular cycle.
 
     subexprs = []
-    
+
     def __init__(self, pos, type, env):
         ExprNode.__init__(self, pos)
         self.type = type
         if type.is_pyobject:
             self.result_ctype = py_object_type
         self.is_temp = 1
-        
+
     def analyse_types(self, env):
         return self.type
-    
+
     def generate_result_code(self, code):
         pass
 
@@ -1847,19 +1944,19 @@ class TempNode(ExprNode):
     # Do not participate in normal temp alloc/dealloc:
     def allocate_temp_result(self, code):
         pass
-    
+
     def release_temp_result(self, code):
         pass
 
 class PyTempNode(TempNode):
     #  TempNode holding a Python value.
-    
+
     def __init__(self, pos, env):
         TempNode.__init__(self, pos, PyrexTypes.py_object_type, env)
 
 class RawCNameExprNode(ExprNode):
     subexprs = []
-    
+
     def __init__(self, pos, type=None):
         self.pos = pos
         self.type = type
@@ -1894,7 +1991,7 @@ class IndexNode(ExprNode):
     #  indices is used on buffer access, index on non-buffer access.
     #  The former contains a clean list of index parameters, the
     #  latter whatever Python object is needed for index access.
-    
+
     subexprs = ['base', 'index', 'indices']
     indices = None
 
@@ -1913,13 +2010,13 @@ class IndexNode(ExprNode):
             return base[index]
         except Exception, e:
             self.compile_time_value_error(e)
-    
+
     def is_ephemeral(self):
         return self.base.is_ephemeral()
-    
+
     def analyse_target_declaration(self, env):
         pass
-        
+
     def analyse_as_type(self, env):
         base_type = self.base.analyse_as_type(env)
         if base_type and not base_type.is_pyobject:
@@ -1930,22 +2027,23 @@ class IndexNode(ExprNode):
                     template_values = [self.index]
                 import Nodes
                 type_node = Nodes.TemplatedTypeNode(
-                    pos = self.pos, 
-                    positional_args = template_values, 
+                    pos = self.pos,
+                    positional_args = template_values,
                     keyword_args = None)
                 return type_node.analyse(env, base_type = base_type)
             else:
                 return PyrexTypes.CArrayType(base_type, int(self.index.compile_time_value(env)))
         return None
-    
+
     def type_dependencies(self, env):
-        return self.base.type_dependencies(env)
-    
+        return self.base.type_dependencies(env) + self.index.type_dependencies(env)
+
     def infer_type(self, env):
         base_type = self.base.infer_type(env)
         if isinstance(self.index, SliceNode):
             # slicing!
             if base_type.is_string:
+                # sliced C strings must coerce to Python
                 return bytes_type
             elif base_type in (unicode_type, bytes_type, str_type, list_type, tuple_type):
                 # slicing these returns the same type
@@ -1954,12 +2052,6 @@ class IndexNode(ExprNode):
                 # TODO: Handle buffers (hopefully without too much redundancy).
                 return py_object_type
 
-        if isinstance(self.base, BytesNode):
-            # Py2/3 return different types on indexing bytes objects
-            # and we can't be sure if we are slicing, so we can't do
-            # any better than this:
-            return py_object_type
-
         index_type = self.index.infer_type(env)
         if index_type and index_type.is_int or isinstance(self.index, (IntNode, LongNode)):
             # indexing!
@@ -1972,19 +2064,26 @@ class IndexNode(ExprNode):
                 # to receive it, throw it away, and potentially rebuild it
                 # on a subsequent PyObject coercion.
                 return PyrexTypes.c_py_unicode_type
+            elif isinstance(self.base, BytesNode):
+                #if env.global_scope().context.language_level >= 3:
+                #    # infering 'char' can be made to work in Python 3 mode
+                #    return PyrexTypes.c_char_type
+                # Py2/3 return different types on indexing bytes objects
+                return py_object_type
             elif base_type.is_ptr or base_type.is_array:
                 return base_type.base_type
 
+        # may be slicing or indexing, we don't know
         if base_type is unicode_type:
             # this type always returns its own type on Python indexing/slicing
             return base_type
         else:
             # TODO: Handle buffers (hopefully without too much redundancy).
             return py_object_type
-    
+
     def analyse_types(self, env):
         self.analyse_base_and_index_types(env, getting = 1)
-    
+
     def analyse_target_types(self, env):
         self.analyse_base_and_index_types(env, setting = 1)
 
@@ -2004,8 +2103,9 @@ class IndexNode(ExprNode):
             # error messages
             self.type = PyrexTypes.error_type
             return
-        
+
         is_slice = isinstance(self.index, SliceNode)
+        # Potentially overflowing index value.
         if not is_slice and isinstance(self.index, IntNode) and Utils.long_literal(self.index.value):
             self.index = self.index.coerce_to_pyobject(env)
 
@@ -2017,7 +2117,6 @@ class IndexNode(ExprNode):
         skip_child_analysis = False
         buffer_access = False
         if self.base.type.is_buffer:
-            assert hasattr(self.base, "entry") # Must be a NameNode-like node
             if self.indices:
                 indices = self.indices
             else:
@@ -2032,6 +2131,8 @@ class IndexNode(ExprNode):
                     x.analyse_types(env)
                     if not x.type.is_int:
                         buffer_access = False
+            if buffer_access:
+                assert hasattr(self.base, "entry") # Must be a NameNode-like node
 
         # On cloning, indices is cloned. Otherwise, unpack index into indices
         assert not (buffer_access and isinstance(self.index, CloneNode))
@@ -2090,7 +2191,9 @@ class IndexNode(ExprNode):
             else:
                 if base_type.is_ptr or base_type.is_array:
                     self.type = base_type.base_type
-                    if self.index.type.is_pyobject:
+                    if is_slice:
+                        self.type = base_type
+                    elif self.index.type.is_pyobject:
                         self.index = self.index.coerce_to(
                             PyrexTypes.c_py_ssize_t_type, env)
                     elif not self.index.type.is_int:
@@ -2132,7 +2235,7 @@ class IndexNode(ExprNode):
 
     def check_const_addr(self):
         return self.base.check_const_addr() and self.index.check_const()
-    
+
     def is_lvalue(self):
         return 1
 
@@ -2145,10 +2248,12 @@ class IndexNode(ExprNode):
             return "PyTuple_GET_ITEM(%s, %s)" % (self.base.result(), self.index.result())
         elif self.base.type is unicode_type and self.type is PyrexTypes.c_py_unicode_type:
             return "PyUnicode_AS_UNICODE(%s)[%s]" % (self.base.result(), self.index.result())
+        elif (self.type.is_ptr or self.type.is_array) and self.type == self.base.type:
+            error(self.pos, "Invalid use of pointer slice")
         else:
             return "(%s[%s])" % (
                 self.base.result(), self.index.result())
-            
+
     def extra_index_params(self):
         if self.index.type.is_int:
             if self.original_index_type.signed:
@@ -2166,7 +2271,7 @@ class IndexNode(ExprNode):
         else:
             for i in self.indices:
                 i.generate_evaluation_code(code)
-        
+
     def generate_subexpr_disposal_code(self, code):
         self.base.generate_disposal_code(code)
         if not self.indices:
@@ -2234,7 +2339,7 @@ class IndexNode(ExprNode):
                         self.extra_index_params(),
                         self.result(),
                         code.error_goto(self.pos)))
-            
+
     def generate_setitem_code(self, value_code, code):
         if self.index.type.is_int:
             function = "__Pyx_SetItemInt"
@@ -2245,12 +2350,12 @@ class IndexNode(ExprNode):
             if self.base.type is dict_type:
                 function = "PyDict_SetItem"
             # It would seem that we could specialized lists/tuples, but that
-            # shouldn't happen here. 
-            # Both PyList_SetItem PyTuple_SetItem and a Py_ssize_t as input, 
-            # not a PyObject*, and bad conversion here would give the wrong 
-            # exception. Also, tuples are supposed to be immutable, and raise 
-            # TypeErrors when trying to set their entries (PyTuple_SetItem 
-            # is for creating new tuples from). 
+            # shouldn't happen here.
+            # Both PyList_SetItem PyTuple_SetItem and a Py_ssize_t as input,
+            # not a PyObject*, and bad conversion here would give the wrong
+            # exception. Also, tuples are supposed to be immutable, and raise
+            # TypeErrors when trying to set their entries (PyTuple_SetItem
+            # is for creating new tuples from).
             else:
                 function = "PyObject_SetItem"
         code.putln(
@@ -2280,7 +2385,7 @@ class IndexNode(ExprNode):
             code.putln("*%s %s= %s;" % (ptr, op, rhs_code))
             code.put_giveref("*%s" % ptr)
             code.funcstate.release_temp(ptr)
-        else: 
+        else:
             # Simple case
             code.putln("*%s %s= %s;" % (ptrexpr, op, rhs.result()))
 
@@ -2298,7 +2403,7 @@ class IndexNode(ExprNode):
         self.free_subexpr_temps(code)
         rhs.generate_disposal_code(code)
         rhs.free_temps(code)
-    
+
     def generate_deletion_code(self, code):
         self.generate_subexpr_evaluation_code(code)
         #if self.type.is_pyobject:
@@ -2350,7 +2455,7 @@ class SliceIndexNode(ExprNode):
     #  base      ExprNode
     #  start     ExprNode or None
     #  stop      ExprNode or None
-    
+
     subexprs = ['base', 'start', 'stop']
 
     def infer_type(self, env):
@@ -2380,10 +2485,10 @@ class SliceIndexNode(ExprNode):
             return base[start:stop]
         except Exception, e:
             self.compile_time_value_error(e)
-    
+
     def analyse_target_declaration(self, env):
         pass
-    
+
     def analyse_target_types(self, env):
         self.analyse_types(env)
         # when assigning, we must accept any Python type
@@ -2399,7 +2504,9 @@ class SliceIndexNode(ExprNode):
         base_type = self.base.type
         if base_type.is_string:
             self.type = bytes_type
-        elif base_type.is_array or base_type.is_ptr:
+        elif base_type.is_ptr:
+            self.type = base_type
+        elif base_type.is_array:
             # we need a ptr type here instead of an array type, as
             # array types can result in invalid type casts in the C
             # code
@@ -2444,19 +2551,19 @@ class SliceIndexNode(ExprNode):
                         code.error_goto_if_null(self.result(), self.pos)))
         else:
             code.putln(
-                "%s = PySequence_GetSlice(%s, %s, %s); %s" % (
+                "%s = __Pyx_PySequence_GetSlice(%s, %s, %s); %s" % (
                     self.result(),
                     self.base.py_result(),
                     self.start_code(),
                     self.stop_code(),
                     code.error_goto_if_null(self.result(), self.pos)))
         code.put_gotref(self.py_result())
-    
+
     def generate_assignment_code(self, rhs, code):
         self.generate_subexpr_evaluation_code(code)
         if self.type.is_pyobject:
-            code.put_error_if_neg(self.pos, 
-                "PySequence_SetSlice(%s, %s, %s, %s)" % (
+            code.put_error_if_neg(self.pos,
+                "__Pyx_PySequence_SetSlice(%s, %s, %s, %s)" % (
                     self.base.py_result(),
                     self.start_code(),
                     self.stop_code(),
@@ -2493,11 +2600,12 @@ class SliceIndexNode(ExprNode):
             return
         self.generate_subexpr_evaluation_code(code)
         code.put_error_if_neg(self.pos,
-            "PySequence_DelSlice(%s, %s, %s)" % (
+            "__Pyx_PySequence_DelSlice(%s, %s, %s)" % (
                 self.base.py_result(),
                 self.start_code(),
                 self.stop_code()))
         self.generate_subexpr_disposal_code(code)
+        self.free_subexpr_temps(code)
 
     def generate_slice_guard_code(self, code, target_size):
         if not self.base.type.is_array:
@@ -2546,13 +2654,13 @@ class SliceIndexNode(ExprNode):
                         target_size, check))
             code.putln(code.error_goto(self.pos))
             code.putln("}")
-    
+
     def start_code(self):
         if self.start:
             return self.start.result()
         else:
             return "0"
-    
+
     def stop_code(self):
         if self.stop:
             return self.stop.result()
@@ -2560,11 +2668,11 @@ class SliceIndexNode(ExprNode):
             return self.base.type.size
         else:
             return "PY_SSIZE_T_MAX"
-    
+
     def calculate_result_code(self):
         # self.result() is not used, but this method must exist
         return "<unused>"
-    
+
 
 class SliceNode(ExprNode):
     #  start:stop:step in subscript list
@@ -2572,7 +2680,7 @@ class SliceNode(ExprNode):
     #  start     ExprNode
     #  stop      ExprNode
     #  step      ExprNode
-    
+
     type = py_object_type
     is_temp = 1
 
@@ -2598,7 +2706,7 @@ class SliceNode(ExprNode):
             self.compile_time_value_error(e)
 
     subexprs = ['start', 'stop', 'step']
-    
+
     def analyse_types(self, env):
         self.start.analyse_types(env)
         self.stop.analyse_types(env)
@@ -2613,8 +2721,8 @@ class SliceNode(ExprNode):
         code.putln(
             "%s = PySlice_New(%s, %s, %s); %s" % (
                 self.result(),
-                self.start.py_result(), 
-                self.stop.py_result(), 
+                self.start.py_result(),
+                self.stop.py_result(),
                 self.step.py_result(),
                 code.error_goto_if_null(self.result(), self.pos)))
         code.put_gotref(self.py_result())
@@ -2653,7 +2761,7 @@ class CallNode(ExprNode):
             self.function.set_cname(type.declaration_code(""))
             self.analyse_c_function_call(env)
             return True
-    
+
     def is_lvalue(self):
         return self.type.is_reference
 
@@ -2677,15 +2785,18 @@ class SimpleCallNode(CallNode):
     #  coerced_self   ExprNode or None     used internally
     #  wrapper_call   bool                 used internally
     #  has_optional_args   bool            used internally
-    
+    #  nogil          bool                 used internally
+
     subexprs = ['self', 'coerced_self', 'function', 'args', 'arg_tuple']
-    
+
     self = None
     coerced_self = None
     arg_tuple = None
     wrapper_call = False
     has_optional_args = False
-    
+    nogil = False
+    analysed = False
+
     def compile_time_value(self, denv):
         function = self.function.compile_time_value(denv)
         args = [arg.compile_time_value(denv) for arg in self.args]
@@ -2693,12 +2804,12 @@ class SimpleCallNode(CallNode):
             return function(*args)
         except Exception, e:
             self.compile_time_value_error(e)
-            
+
     def type_dependencies(self, env):
         # TODO: Update when Danilo's C++ code merged in to handle the
         # the case of function overloading.
         return self.function.type_dependencies(env)
-    
+
     def infer_type(self, env):
         function = self.function
         func_type = function.infer_type(env)
@@ -2738,6 +2849,9 @@ class SimpleCallNode(CallNode):
     def analyse_types(self, env):
         if self.analyse_as_type_constructor(env):
             return
+        if self.analysed:
+            return
+        self.analysed = True
         function = self.function
         function.is_called = 1
         self.function.analyse_types(env)
@@ -2779,13 +2893,18 @@ class SimpleCallNode(CallNode):
                 arg.analyse_types(env)
             if self.self and func_type.args:
                 # Coerce 'self' to the type expected by the method.
-                expected_type = func_type.args[0].type
+                self_arg = func_type.args[0]
+                if self_arg.not_none: # C methods must do the None test for self at *call* time
+                    self.self = self.self.as_none_safe_node(
+                        "'NoneType' object has no attribute '%s'" % self.function.entry.name,
+                        'PyExc_AttributeError')
+                expected_type = self_arg.type
                 self.coerced_self = CloneNode(self.self).coerce_to(
                     expected_type, env)
                 # Insert coerced 'self' argument into argument list.
                 self.args.insert(0, self.coerced_self)
             self.analyse_c_function_call(env)
-    
+
     def function_type(self):
         # Return the type of the function being called, coercing a function
         # pointer to a function if necessary.
@@ -2793,7 +2912,7 @@ class SimpleCallNode(CallNode):
         if func_type.is_ptr:
             func_type = func_type.base_type
         return func_type
-    
+
     def analyse_c_function_call(self, env):
         if self.function.type is error_type:
             self.type = error_type
@@ -2834,11 +2953,23 @@ class SimpleCallNode(CallNode):
         # Coerce arguments
         for i in range(min(max_nargs, actual_nargs)):
             formal_type = func_type.args[i].type
-            self.args[i] = self.args[i].coerce_to(formal_type, env)
+            arg = self.args[i].coerce_to(formal_type, env)
+            if arg.type.is_pyobject and not env.nogil and (arg.is_attribute or not arg.is_simple):
+                # we do not own the argument's reference, but we must
+                # make sure it cannot be collected before we return
+                # from the function, so we create an owned temp
+                # reference to it
+                arg = arg.coerce_to_temp(env)
+            self.args[i] = arg
         for i in range(max_nargs, actual_nargs):
-            if self.args[i].type.is_pyobject:
-                error(self.args[i].pos, 
-                    "Python object cannot be passed as a varargs parameter")
+            arg = self.args[i]
+            if arg.type.is_pyobject:
+                arg_ctype = arg.type.default_coerced_ctype()
+                if arg_ctype is None:
+                    error(self.args[i].pos,
+                          "Python object cannot be passed as a varargs parameter")
+                else:
+                    self.args[i] = arg.coerce_to(arg_ctype, env)
         # Calc result type and code fragment
         if isinstance(self.function, NewExprNode):
             self.type = PyrexTypes.CPtrType(self.function.class_type)
@@ -2850,6 +2981,12 @@ class SimpleCallNode(CallNode):
         elif func_type.exception_value is not None \
                  or func_type.exception_check:
             self.is_temp = 1
+        # Called in 'nogil' context?
+        self.nogil = env.nogil
+        if (self.nogil and
+            func_type.exception_check and
+            func_type.exception_check != '+'):
+            env.use_utility_code(pyerr_occurred_withgil_utility_code)
         # C++ exception handler
         if func_type.exception_check == '+':
             if func_type.exception_value is None:
@@ -2857,37 +2994,37 @@ class SimpleCallNode(CallNode):
 
     def calculate_result_code(self):
         return self.c_call_code()
-    
+
     def c_call_code(self):
         func_type = self.function_type()
         if self.type is PyrexTypes.error_type or not func_type.is_cfunction:
             return "<error>"
         formal_args = func_type.args
         arg_list_code = []
-        args = zip(formal_args, self.args)
+        args = list(zip(formal_args, self.args))
         max_nargs = len(func_type.args)
         expected_nargs = max_nargs - func_type.optional_arg_count
         actual_nargs = len(self.args)
         for formal_arg, actual_arg in args[:expected_nargs]:
                 arg_code = actual_arg.result_as(formal_arg.type)
                 arg_list_code.append(arg_code)
-                
+
         if func_type.is_overridable:
             arg_list_code.append(str(int(self.wrapper_call or self.function.entry.is_unbound_cmethod)))
-                
+
         if func_type.optional_arg_count:
             if expected_nargs == actual_nargs:
                 optional_args = 'NULL'
             else:
                 optional_args = "&%s" % self.opt_arg_struct
             arg_list_code.append(optional_args)
-            
+
         for actual_arg in self.args[len(formal_args):]:
             arg_list_code.append(actual_arg.result())
         result = "%s(%s)" % (self.function.result(),
             ', '.join(arg_list_code))
         return result
-    
+
     def generate_result_code(self, code):
         func_type = self.function_type()
         if func_type.is_pyobject:
@@ -2909,7 +3046,7 @@ class SimpleCallNode(CallNode):
                         self.opt_arg_struct,
                         Naming.pyrex_prefix + "n",
                         len(self.args) - expected_nargs))
-                args = zip(func_type.args, self.args)
+                args = list(zip(func_type.args, self.args))
                 for formal_arg, actual_arg in args[expected_nargs:actual_nargs]:
                     code.putln("%s.%s = %s;" % (
                             self.opt_arg_struct,
@@ -2924,7 +3061,10 @@ class SimpleCallNode(CallNode):
                 if exc_val is not None:
                     exc_checks.append("%s == %s" % (self.result(), exc_val))
                 if exc_check:
-                    exc_checks.append("PyErr_Occurred()")
+                    if self.nogil:
+                        exc_checks.append("__Pyx_ErrOccurredWithGIL()")
+                    else:
+                        exc_checks.append("PyErr_Occurred()")
             if self.is_temp or exc_checks:
                 rhs = self.c_call_code()
                 if self.result():
@@ -2945,6 +3085,8 @@ class SimpleCallNode(CallNode):
                             func_type.exception_value.entry.cname)
                     else:
                         raise_py_exception = '%s(); if (!PyErr_Occurred()) PyErr_SetString(PyExc_RuntimeError , "Error converting c++ exception.")' % func_type.exception_value.entry.cname
+                    if self.nogil:
+                        raise_py_exception = 'Py_BLOCK_THREADS; %s; Py_UNBLOCK_THREADS' % raise_py_exception
                     code.putln(
                     "try {%s%s;} catch(...) {%s; %s}" % (
                         lhs,
@@ -3011,9 +3153,9 @@ class GeneralCallNode(CallNode):
     #  positional_args  ExprNode          Tuple of positional arguments
     #  keyword_args     ExprNode or None  Dict of keyword arguments
     #  starstar_arg     ExprNode or None  Dict of extra keyword args
-    
+
     type = py_object_type
-    
+
     subexprs = ['function', 'positional_args', 'keyword_args', 'starstar_arg']
 
     nogil_check = Node.gil_error
@@ -3028,10 +3170,10 @@ class GeneralCallNode(CallNode):
             return function(*positional_args, **keyword_args)
         except Exception, e:
             self.compile_time_value_error(e)
-            
+
     def explicit_args_kwds(self):
         if self.starstar_arg or not isinstance(self.positional_args, TupleNode):
-            raise PostParseError(self.pos,
+            raise CompileError(self.pos,
                 'Compile-time keyword arguments must be explicit.')
         return self.positional_args.args, self.keyword_args
 
@@ -3067,14 +3209,14 @@ class GeneralCallNode(CallNode):
         else:
             self.type = py_object_type
         self.is_temp = 1
-        
+
     def generate_result_code(self, code):
         if self.type.is_error: return
         kwargs_call_function = "PyEval_CallObjectWithKeywords"
         if self.keyword_args and self.starstar_arg:
-            code.put_error_if_neg(self.pos, 
+            code.put_error_if_neg(self.pos,
                 "PyDict_Update(%s, %s)" % (
-                    self.keyword_args.py_result(), 
+                    self.keyword_args.py_result(),
                     self.starstar_arg.py_result()))
             keyword_code = self.keyword_args.py_result()
         elif self.keyword_args:
@@ -3110,12 +3252,12 @@ class AsTupleNode(ExprNode):
     #  the * argument of a function call.
     #
     #  arg    ExprNode
-    
+
     subexprs = ['arg']
 
     def calculate_constant_result(self):
         self.constant_result = tuple(self.base.constant_result)
-    
+
     def compile_time_value(self, denv):
         arg = self.arg.compile_time_value(denv)
         try:
@@ -3142,7 +3284,7 @@ class AsTupleNode(ExprNode):
                 self.arg.py_result(),
                 code.error_goto_if_null(self.result(), self.pos)))
         code.put_gotref(self.py_result())
-    
+
 
 class AttributeNode(ExprNode):
     #  obj.attribute
@@ -3158,10 +3300,10 @@ class AttributeNode(ExprNode):
     #  member               string    C name of struct member
     #  is_called            boolean   Function call is being done on result
     #  entry                Entry     Symbol table entry of attribute
-    
+
     is_attribute = 1
     subexprs = ['obj']
-    
+
     type = PyrexTypes.error_type
     entry = None
     is_called = 0
@@ -3183,7 +3325,7 @@ class AttributeNode(ExprNode):
                 # must be a cpdef function
                 self.is_temp = 1
                 self.entry = entry.as_variable
-                self.analyse_as_python_attribute(env) 
+                self.analyse_as_python_attribute(env)
                 return self
         return ExprNode.coerce_to(self, dst_type, env)
 
@@ -3204,32 +3346,39 @@ class AttributeNode(ExprNode):
             return getattr(obj, attr)
         except Exception, e:
             self.compile_time_value_error(e)
-    
+
     def type_dependencies(self, env):
         return self.obj.type_dependencies(env)
-    
+
     def infer_type(self, env):
         if self.analyse_as_cimported_attribute(env, 0):
             return self.entry.type
         elif self.analyse_as_unbound_cmethod(env):
             return self.entry.type
         else:
-            self.analyse_attribute(env, obj_type = self.obj.infer_type(env))
+            obj_type = self.obj.infer_type(env)
+            self.analyse_attribute(env, obj_type = obj_type)
+            if obj_type.is_builtin_type and self.type.is_cfunction:
+                # special case: C-API replacements for C methods of
+                # builtin types cannot be inferred as C functions as
+                # that would prevent their use as bound methods
+                self.type = py_object_type
+                return py_object_type
             return self.type
 
     def analyse_target_declaration(self, env):
         pass
-    
+
     def analyse_target_types(self, env):
         self.analyse_types(env, target = 1)
-    
+
     def analyse_types(self, env, target = 0):
         if self.analyse_as_cimported_attribute(env, target):
             return
         if not target and self.analyse_as_unbound_cmethod(env):
             return
         self.analyse_as_ordinary_attribute(env, target)
-    
+
     def analyse_as_cimported_attribute(self, env, target):
         # Try to interpret this as a reference to an imported
         # C const, type, var or function. If successful, mutates
@@ -3244,7 +3393,7 @@ class AttributeNode(ExprNode):
                     self.mutate_into_name_node(env, entry, target)
                     return 1
         return 0
-    
+
     def analyse_as_unbound_cmethod(self, env):
         # Try to interpret this as a reference to an unbound
         # C method of an extension type. If successful, mutates
@@ -3265,17 +3414,17 @@ class AttributeNode(ExprNode):
                 self.mutate_into_name_node(env, ubcm_entry, None)
                 return 1
         return 0
-        
+
     def analyse_as_type(self, env):
         module_scope = self.obj.analyse_as_module(env)
         if module_scope:
             return module_scope.lookup_type(self.attribute)
         if not isinstance(self.obj, (UnicodeNode, StringNode, BytesNode)):
             base_type = self.obj.analyse_as_type(env)
-            if base_type and hasattr(base_type, 'scope'):
+            if base_type and hasattr(base_type, 'scope') and base_type.scope is not None:
                 return base_type.scope.lookup_type(self.attribute)
         return None
-    
+
     def analyse_as_extension_type(self, env):
         # Try to interpret this as a reference to an extension type
         # in a cimported module. Returns the extension type, or None.
@@ -3285,7 +3434,7 @@ class AttributeNode(ExprNode):
             if entry and entry.is_type and entry.type.is_extension_type:
                 return entry.type
         return None
-    
+
     def analyse_as_module(self, env):
         # Try to interpret this as a reference to a cimported module
         # in another cimported module. Returns the module scope, or None.
@@ -3295,7 +3444,7 @@ class AttributeNode(ExprNode):
             if entry and entry.as_module:
                 return entry.as_module
         return None
-                
+
     def mutate_into_name_node(self, env, entry, target):
         # Mutate this node into a NameNode and complete the
         # analyse_types phase.
@@ -3308,7 +3457,7 @@ class AttributeNode(ExprNode):
             NameNode.analyse_target_types(self, env)
         else:
             NameNode.analyse_rvalue_entry(self, env)
-    
+
     def analyse_as_ordinary_attribute(self, env, target):
         self.obj.analyse_types(env)
         self.analyse_attribute(env)
@@ -3322,7 +3471,9 @@ class AttributeNode(ExprNode):
             if not target:
                 self.is_temp = 1
                 self.result_ctype = py_object_type
-    
+        elif target and self.obj.type.is_builtin_type:
+            error(self.pos, "Assignment to an immutable object field")
+
     def analyse_attribute(self, env, obj_type = None):
         # Look up attribute and set self.type and self.member.
         self.is_py_attr = 0
@@ -3337,7 +3488,7 @@ class AttributeNode(ExprNode):
         if obj_type.is_ptr or obj_type.is_array:
             obj_type = obj_type.base_type
             self.op = "->"
-        elif obj_type.is_extension_type:
+        elif obj_type.is_extension_type or obj_type.is_builtin_type:
             self.op = "->"
         else:
             self.op = "."
@@ -3348,8 +3499,8 @@ class AttributeNode(ExprNode):
                 if entry and entry.is_member:
                     entry = None
             else:
-                error(self.pos, 
-                    "Cannot select attribute of incomplete type '%s'" 
+                error(self.pos,
+                    "Cannot select attribute of incomplete type '%s'"
                     % obj_type)
                 self.type = PyrexTypes.error_type
                 return
@@ -3368,7 +3519,7 @@ class AttributeNode(ExprNode):
                     # method of an extension type, so we treat it like a Python
                     # attribute.
                     pass
-        # If we get here, the base object is not a struct/union/extension 
+        # If we get here, the base object is not a struct/union/extension
         # type, or it is an extension type and the attribute is either not
         # declared or is declared as a Python method. Treat it as a Python
         # attribute reference.
@@ -3405,13 +3556,13 @@ class AttributeNode(ExprNode):
             return 1
         else:
             return NameNode.is_lvalue(self)
-    
+
     def is_ephemeral(self):
         if self.obj:
             return self.obj.is_ephemeral()
         else:
             return NameNode.is_ephemeral(self)
-    
+
     def calculate_result_code(self):
         #print "AttributeNode.calculate_result_code:", self.member ###
         #print "...obj node =", self.obj, "code", self.obj.result() ###
@@ -3422,15 +3573,18 @@ class AttributeNode(ExprNode):
         if self.entry and self.entry.is_cmethod:
             if obj.type.is_extension_type:
                 return "((struct %s *)%s%s%s)->%s" % (
-                    obj.type.vtabstruct_cname, obj_code, self.op, 
+                    obj.type.vtabstruct_cname, obj_code, self.op,
                     obj.type.vtabslot_cname, self.member)
             else:
                 return self.member
         elif obj.type.is_complex:
             return "__Pyx_C%s(%s)" % (self.member.upper(), obj_code)
         else:
+            if obj.type.is_builtin_type and self.entry and self.entry.is_variable:
+                # accessing a field of a builtin type, need to cast better than result_as() does
+                obj_code = obj.type.cast_code(obj.result(), to_object_struct = True)
             return "%s%s%s" % (obj_code, self.op, self.member)
-    
+
     def generate_result_code(self, code):
         interned_attr_cname = code.intern_identifier(self.attribute)
         if self.is_py_attr:
@@ -3448,12 +3602,12 @@ class AttributeNode(ExprNode):
                   and self.needs_none_check
                   and code.globalstate.directives['nonecheck']):
                 self.put_nonecheck(code)
-    
+
     def generate_assignment_code(self, rhs, code):
         interned_attr_cname = code.intern_identifier(self.attribute)
         self.obj.generate_evaluation_code(code)
         if self.is_py_attr:
-            code.put_error_if_neg(self.pos, 
+            code.put_error_if_neg(self.pos,
                 'PyObject_SetAttr(%s, %s, %s)' % (
                     self.obj.py_result(),
                     interned_attr_cname,
@@ -3486,12 +3640,12 @@ class AttributeNode(ExprNode):
             rhs.free_temps(code)
         self.obj.generate_disposal_code(code)
         self.obj.free_temps(code)
-    
+
     def generate_deletion_code(self, code):
         interned_attr_cname = code.intern_identifier(self.attribute)
         self.obj.generate_evaluation_code(code)
         if self.is_py_attr or (isinstance(self.entry.scope, Symtab.PropertyScope)
-                               and self.entry.scope.entries.has_key(u'__del__')):
+                               and u'__del__' in self.entry.scope.entries):
             code.put_error_if_neg(self.pos,
                 'PyObject_DelAttr(%s, %s)' % (
                     self.obj.py_result(),
@@ -3500,7 +3654,7 @@ class AttributeNode(ExprNode):
             error(self.pos, "Cannot delete C attribute of extension type")
         self.obj.generate_disposal_code(code)
         self.obj.free_temps(code)
-        
+
     def annotate(self, code):
         if self.is_py_attr:
             code.annotate(self.pos, AnnotationItem('py_attr', 'python attribute', size=len(self.attribute)))
@@ -3573,9 +3727,9 @@ class SequenceNode(ExprNode):
     #  iterator                ExprNode
     #  unpacked_items          [ExprNode] or None
     #  coerced_unpacked_items  [ExprNode] or None
-    
+
     subexprs = ['args']
-    
+
     is_sequence_constructor = 1
     unpacked_items = None
 
@@ -3606,8 +3760,8 @@ class SequenceNode(ExprNode):
             arg = self.args[i]
             if not skip_children: arg.analyse_types(env)
             self.args[i] = arg.coerce_to_pyobject(env)
-        self.type = py_object_type
         self.is_temp = 1
+        # not setting self.type here, subtypes do this
 
     def may_be_none(self):
         return False
@@ -3632,7 +3786,7 @@ class SequenceNode(ExprNode):
 
     def generate_result_code(self, code):
         self.generate_operation_code(code)
-    
+
     def generate_assignment_code(self, rhs, code):
         if self.starred_assignment:
             self.generate_starred_assignment_code(rhs, code)
@@ -3654,8 +3808,8 @@ class SequenceNode(ExprNode):
             tuple_check = "PyTuple_CheckExact(%s)"
         code.putln(
             "if (%s && likely(PyTuple_GET_SIZE(%s) == %s)) {" % (
-                tuple_check % rhs.py_result(), 
-                rhs.py_result(), 
+                tuple_check % rhs.py_result(),
+                rhs.py_result(),
                 len(self.args)))
         code.putln("PyObject* tuple = %s;" % rhs.py_result())
         for item in self.unpacked_items:
@@ -3674,7 +3828,7 @@ class SequenceNode(ExprNode):
         for i in range(len(self.args)):
             self.args[i].generate_assignment_code(
                 self.coerced_unpacked_items[i], code)
-                 
+
         code.putln("} else {")
 
         if rhs.type is tuple_type:
@@ -3800,7 +3954,7 @@ class SequenceNode(ExprNode):
 
 class TupleNode(SequenceNode):
     #  Tuple constructor.
-    
+
     type = tuple_type
 
     gil_message = "Constructing Python tuple"
@@ -3811,10 +3965,16 @@ class TupleNode(SequenceNode):
             self.is_literal = 1
         else:
             SequenceNode.analyse_types(self, env, skip_children)
-            
+            for child in self.args:
+                if not child.is_literal:
+                    break
+            else:
+                self.is_temp = 0
+                self.is_literal = 1
+
     def calculate_result_code(self):
         if len(self.args) > 0:
-            error(self.pos, "Positive length tuples must be constructed.")
+            return self.result_code
         else:
             return Naming.empty_tuple
 
@@ -3828,11 +3988,18 @@ class TupleNode(SequenceNode):
             return tuple(values)
         except Exception, e:
             self.compile_time_value_error(e)
-    
+
     def generate_operation_code(self, code):
         if len(self.args) == 0:
             # result_code is Naming.empty_tuple
             return
+        if self.is_literal:
+            # non-empty cached tuple => result is global constant,
+            # creation code goes into separate code writer
+            self.result_code = code.get_py_const(py_object_type, 'tuple_', cleanup_level=2)
+            code = code.get_cached_constants_writer()
+            code.mark_pos(self.pos)
+
         code.putln(
             "%s = PyTuple_New(%s); %s" % (
                 self.result(),
@@ -3849,7 +4016,9 @@ class TupleNode(SequenceNode):
                     i,
                     arg.py_result()))
             code.put_giveref(arg.py_result())
-    
+        if self.is_literal:
+            code.put_giveref(self.py_result())
+
     def generate_subexpr_disposal_code(self, code):
         # We call generate_post_assignment_code here instead
         # of generate_disposal_code, because values were stored
@@ -3862,17 +4031,18 @@ class TupleNode(SequenceNode):
 
 class ListNode(SequenceNode):
     #  List constructor.
-    
+
     # obj_conversion_errors    [PyrexError]   used internally
     # orignial_args            [ExprNode]     used internally
 
     obj_conversion_errors = []
+    type = list_type
 
     gil_message = "Constructing Python list"
-    
+
     def type_dependencies(self, env):
         return ()
-    
+
     def infer_type(self, env):
         # TOOD: Infer non-object list arrays.
         return list_type
@@ -3885,10 +4055,9 @@ class ListNode(SequenceNode):
         hold_errors()
         self.original_args = list(self.args)
         SequenceNode.analyse_types(self, env)
-        self.type = list_type
         self.obj_conversion_errors = held_errors()
         release_errors(ignore=True)
-        
+
     def coerce_to(self, dst_type, env):
         if dst_type.is_pyobject:
             for err in self.obj_conversion_errors:
@@ -3896,7 +4065,7 @@ class ListNode(SequenceNode):
             self.obj_conversion_errors = []
             if not self.type.subtype_of(dst_type):
                 error(self.pos, "Cannot coerce list to type '%s'" % dst_type)
-        elif dst_type.is_ptr:
+        elif dst_type.is_ptr and dst_type.base_type is not PyrexTypes.c_void_type:
             base_type = dst_type.base_type
             self.type = PyrexTypes.CArrayType(base_type, len(self.args))
             for i in range(len(self.original_args)):
@@ -3919,11 +4088,11 @@ class ListNode(SequenceNode):
             self.type = error_type
             error(self.pos, "Cannot coerce list to type '%s'" % dst_type)
         return self
-        
+
     def release_temp(self, env):
         if self.type.is_array:
-            # To be valid C++, we must allocate the memory on the stack 
-            # manually and be sure not to reuse it for something else. 
+            # To be valid C++, we must allocate the memory on the stack
+            # manually and be sure not to reuse it for something else.
             pass
         else:
             SequenceNode.release_temp(self, env)
@@ -3988,49 +4157,98 @@ class ScopedExprNode(ExprNode):
     subexprs = []
     expr_scope = None
 
-    def analyse_types(self, env):
-        # nothing to do here, the children will be analysed separately
+    # does this node really have a local scope, e.g. does it leak loop
+    # variables or not?  non-leaking Py3 behaviour is default, except
+    # for list comprehensions where the behaviour differs in Py2 and
+    # Py3 (set in Parsing.py based on parser context)
+    has_local_scope = True
+
+    def init_scope(self, outer_scope, expr_scope=None):
+        if expr_scope is not None:
+            self.expr_scope = expr_scope
+        elif self.has_local_scope:
+            self.expr_scope = Symtab.GeneratorExpressionScope(outer_scope)
+        else:
+            self.expr_scope = None
+
+    def analyse_declarations(self, env):
+        self.init_scope(env)
+
+    def analyse_scoped_declarations(self, env):
+        # this is called with the expr_scope as env
         pass
 
-    def analyse_expressions(self, env):
-        # nothing to do here, the children will be analysed separately
+    def analyse_types(self, env):
+        # no recursion here, the children will be analysed separately below
         pass
 
     def analyse_scoped_expressions(self, env):
         # this is called with the expr_scope as env
         pass
 
-    def init_scope(self, outer_scope, expr_scope=None):
-        self.expr_scope = expr_scope
+    def generate_evaluation_code(self, code):
+        # set up local variables and free their references on exit
+        generate_inner_evaluation_code = super(ScopedExprNode, self).generate_evaluation_code
+        if not self.has_local_scope or not self.expr_scope.var_entries:
+            # no local variables => delegate, done
+            generate_inner_evaluation_code(code)
+            return
+
+        code.putln('{ /* enter inner scope */')
+        py_entries = []
+        for entry in self.expr_scope.var_entries:
+            if not entry.in_closure:
+                code.put_var_declaration(entry)
+                if entry.type.is_pyobject and entry.used:
+                    py_entries.append(entry)
+        if not py_entries:
+            # no local Python references => no cleanup required
+            generate_inner_evaluation_code(code)
+            code.putln('} /* exit inner scope */')
+            return
+        for entry in py_entries:
+            code.put_init_var_to_py_none(entry)
+
+        # must free all local Python references at each exit point
+        old_loop_labels = tuple(code.new_loop_labels())
+        old_error_label = code.new_error_label()
+
+        generate_inner_evaluation_code(code)
+
+        # normal (non-error) exit
+        for entry in py_entries:
+            code.put_var_decref(entry)
+
+        # error/loop body exit points
+        exit_scope = code.new_label('exit_scope')
+        code.put_goto(exit_scope)
+        for label, old_label in ([(code.error_label, old_error_label)] +
+                                 list(zip(code.get_loop_labels(), old_loop_labels))):
+            if code.label_used(label):
+                code.put_label(label)
+                for entry in py_entries:
+                    code.put_var_decref(entry)
+                code.put_goto(old_label)
+        code.put_label(exit_scope)
+        code.putln('} /* exit inner scope */')
+
+        code.set_loop_labels(old_loop_labels)
+        code.error_label = old_error_label
 
 
 class ComprehensionNode(ScopedExprNode):
     subexprs = ["target"]
     child_attrs = ["loop", "append"]
 
-    # leak loop variables or not?  non-leaking Py3 behaviour is
-    # default, except for list comprehensions where the behaviour
-    # differs in Py2 and Py3 (see Parsing.py)
-    has_local_scope = True
-
     def infer_type(self, env):
         return self.target.infer_type(env)
 
     def analyse_declarations(self, env):
         self.append.target = self # this is used in the PyList_Append of the inner loop
         self.init_scope(env)
-        if self.expr_scope is not None:
-            self.loop.analyse_declarations(self.expr_scope)
-        else:
-            self.loop.analyse_declarations(env)
 
-    def init_scope(self, outer_scope, expr_scope=None):
-        if expr_scope is not None:
-            self.expr_scope = expr_scope
-        elif self.has_local_scope:
-            self.expr_scope = Symtab.GeneratorExpressionScope(outer_scope)
-        else:
-            self.expr_scope = None
+    def analyse_scoped_declarations(self, env):
+        self.loop.analyse_declarations(env)
 
     def analyse_types(self, env):
         self.target.analyse_expressions(env)
@@ -4038,9 +4256,6 @@ class ComprehensionNode(ScopedExprNode):
         if not self.has_local_scope:
             self.loop.analyse_expressions(env)
 
-    def analyse_expressions(self, env):
-        self.analyse_types(env)
-
     def analyse_scoped_expressions(self, env):
         if self.has_local_scope:
             self.loop.analyse_expressions(env)
@@ -4050,7 +4265,7 @@ class ComprehensionNode(ScopedExprNode):
 
     def calculate_result_code(self):
         return self.target.result()
-    
+
     def generate_result_code(self, code):
         self.generate_operation_code(code)
 
@@ -4068,7 +4283,7 @@ class ComprehensionAppendNode(Node):
     child_attrs = ['expr']
 
     type = PyrexTypes.c_int_type
-    
+
     def analyse_expressions(self, env):
         self.expr.analyse_expressions(env)
         if not self.expr.type.is_pyobject:
@@ -4142,21 +4357,17 @@ class GeneratorExpressionNode(ScopedExprNode):
 
     type = py_object_type
 
-    def analyse_declarations(self, env):
-        self.init_scope(env)
-        self.loop.analyse_declarations(self.expr_scope)
-
-    def init_scope(self, outer_scope, expr_scope=None):
-        if expr_scope is not None:
-            self.expr_scope = expr_scope
-        else:
-            self.expr_scope = Symtab.GeneratorExpressionScope(outer_scope)
+    def analyse_scoped_declarations(self, env):
+        self.loop.analyse_declarations(env)
 
     def analyse_types(self, env):
+        if not self.has_local_scope:
+            self.loop.analyse_expressions(env)
         self.is_temp = True
 
     def analyse_scoped_expressions(self, env):
-        self.loop.analyse_expressions(env)
+        if self.has_local_scope:
+            self.loop.analyse_expressions(env)
 
     def may_be_none(self):
         return False
@@ -4176,14 +4387,29 @@ class InlinedGeneratorExpressionNode(GeneratorExpressionNode):
     # orig_func      String           the name of the builtin function this node replaces
 
     child_attrs = ["loop"]
+    loop_analysed = False
+
+    def infer_type(self, env):
+        return self.result_node.infer_type(env)
 
     def analyse_types(self, env):
+        if not self.has_local_scope:
+            self.loop_analysed = True
+            self.loop.analyse_expressions(env)
         self.type = self.result_node.type
         self.is_temp = True
 
+    def analyse_scoped_expressions(self, env):
+        self.loop_analysed = True
+        GeneratorExpressionNode.analyse_scoped_expressions(self, env)
+
     def coerce_to(self, dst_type, env):
-        if self.orig_func == 'sum' and dst_type.is_numeric:
-            # we can optimise by dropping the aggregation variable into C
+        if self.orig_func == 'sum' and dst_type.is_numeric and not self.loop_analysed:
+            # We can optimise by dropping the aggregation variable and
+            # the add operations into C.  This can only be done safely
+            # before analysing the loop body, after that, the result
+            # reference type will have infected expressions and
+            # assignments.
             self.result_node.type = self.type = dst_type
             return self
         return GeneratorExpressionNode.coerce_to(self, dst_type, env)
@@ -4201,7 +4427,7 @@ class SetNode(ExprNode):
     subexprs = ['args']
 
     gil_message = "Constructing Python set"
-    
+
     def analyse_types(self, env):
         for i in range(len(self.args)):
             arg = self.args[i]
@@ -4248,7 +4474,7 @@ class DictNode(ExprNode):
     #  key_value_pairs  [DictItemNode]
     #
     # obj_conversion_errors    [PyrexError]   used internally
-    
+
     subexprs = ['key_value_pairs']
     is_temp = 1
     type = dict_type
@@ -4258,7 +4484,7 @@ class DictNode(ExprNode):
     def calculate_constant_result(self):
         self.constant_result = dict([
                 item.constant_result for item in self.key_value_pairs])
-    
+
     def compile_time_value(self, denv):
         pairs = [(item.key.compile_time_value(denv), item.value.compile_time_value(denv))
             for item in self.key_value_pairs]
@@ -4266,10 +4492,10 @@ class DictNode(ExprNode):
             return dict(pairs)
         except Exception, e:
             self.compile_time_value_error(e)
-    
+
     def type_dependencies(self, env):
         return ()
-    
+
     def infer_type(self, env):
         # TOOD: Infer struct constructors.
         return dict_type
@@ -4283,7 +4509,7 @@ class DictNode(ExprNode):
 
     def may_be_none(self):
         return False
-        
+
     def coerce_to(self, dst_type, env):
         if dst_type.is_pyobject:
             self.release_errors()
@@ -4315,7 +4541,7 @@ class DictNode(ExprNode):
             self.type = error_type
             error(self.pos, "Cannot interpret dict as type '%s'" % dst_type)
         return self
-    
+
     def release_errors(self):
         for err in self.obj_conversion_errors:
             report_error(err)
@@ -4338,7 +4564,7 @@ class DictNode(ExprNode):
         for item in self.key_value_pairs:
             item.generate_evaluation_code(code)
             if self.type.is_pyobject:
-                code.put_error_if_neg(self.pos, 
+                code.put_error_if_neg(self.pos,
                     "PyDict_SetItem(%s, %s, %s)" % (
                         self.result(),
                         item.key.py_result(),
@@ -4350,11 +4576,11 @@ class DictNode(ExprNode):
                         item.value.result()))
             item.generate_disposal_code(code)
             item.free_temps(code)
-            
+
     def annotate(self, code):
         for item in self.key_value_pairs:
             item.annotate(code)
-            
+
 class DictItemNode(ExprNode):
     # Represents a single item in a DictNode
     #
@@ -4367,13 +4593,13 @@ class DictItemNode(ExprNode):
     def calculate_constant_result(self):
         self.constant_result = (
             self.key.constant_result, self.value.constant_result)
-            
+
     def analyse_types(self, env):
         self.key.analyse_types(env)
         self.value.analyse_types(env)
         self.key = self.key.coerce_to_pyobject(env)
         self.value = self.value.coerce_to_pyobject(env)
-        
+
     def generate_evaluation_code(self, code):
         self.key.generate_evaluation_code(code)
         self.value.generate_evaluation_code(code)
@@ -4385,12 +4611,19 @@ class DictItemNode(ExprNode):
     def free_temps(self, code):
         self.key.free_temps(code)
         self.value.free_temps(code)
-        
+
     def __iter__(self):
         return iter([self.key, self.value])
 
+class ModuleNameMixin(object):
+    def set_mod_name(self, env):
+        self.module_name = env.global_scope().qualified_name
+
+    def get_py_mod_name(self, code):
+        return code.get_py_string_const(
+                 self.module_name, identifier=True)
 
-class ClassNode(ExprNode):
+class ClassNode(ExprNode, ModuleNameMixin):
     #  Helper class used in the implementation of Python
     #  class definitions. Constructs a class object given
     #  a name, tuple of bases and class dictionary.
@@ -4399,8 +4632,8 @@ class ClassNode(ExprNode):
     #  bases        ExprNode           Base class tuple
     #  dict         ExprNode           Class dict (not owned by this node)
     #  doc          ExprNode or None   Doc string
-    #  module_name  string             Name of defining module
-    
+    #  module_name  EncodedString      Name of defining module
+
     subexprs = ['bases', 'doc']
 
     def analyse_types(self, env):
@@ -4408,30 +4641,179 @@ class ClassNode(ExprNode):
         if self.doc:
             self.doc.analyse_types(env)
             self.doc = self.doc.coerce_to_pyobject(env)
-        self.module_name = env.global_scope().qualified_name
         self.type = py_object_type
         self.is_temp = 1
         env.use_utility_code(create_class_utility_code);
+        #TODO(craig,haoyu) This should be moved to a better place
+        self.set_mod_name(env)
 
     def may_be_none(self):
-        return False
+        return True
 
     gil_message = "Constructing Python class"
 
     def generate_result_code(self, code):
         cname = code.intern_identifier(self.name)
+
         if self.doc:
-            code.put_error_if_neg(self.pos, 
+            code.put_error_if_neg(self.pos,
                 'PyDict_SetItemString(%s, "__doc__", %s)' % (
                     self.dict.py_result(),
                     self.doc.py_result()))
+        py_mod_name = self.get_py_mod_name(code)
         code.putln(
-            '%s = __Pyx_CreateClass(%s, %s, %s, "%s"); %s' % (
+            '%s = __Pyx_CreateClass(%s, %s, %s, %s); %s' % (
                 self.result(),
                 self.bases.py_result(),
                 self.dict.py_result(),
                 cname,
-                self.module_name,
+                py_mod_name,
+                code.error_goto_if_null(self.result(), self.pos)))
+        code.put_gotref(self.py_result())
+
+
+class Py3ClassNode(ExprNode):
+    #  Helper class used in the implementation of Python3+
+    #  class definitions. Constructs a class object given
+    #  a name, tuple of bases and class dictionary.
+    #
+    #  name         EncodedString      Name of the class
+    #  dict         ExprNode           Class dict (not owned by this node)
+    #  module_name  EncodedString      Name of defining module
+
+    subexprs = []
+
+    def analyse_types(self, env):
+        self.type = py_object_type
+        self.is_temp = 1
+
+    def may_be_none(self):
+        return True
+
+    gil_message = "Constructing Python class"
+
+    def generate_result_code(self, code):
+        code.globalstate.use_utility_code(create_py3class_utility_code)
+        cname = code.intern_identifier(self.name)
+        code.putln(
+            '%s = __Pyx_Py3ClassCreate(%s, %s, %s, %s, %s); %s' % (
+                self.result(),
+                self.metaclass.result(),
+                cname,
+                self.bases.py_result(),
+                self.dict.py_result(),
+                self.mkw.py_result(),
+                code.error_goto_if_null(self.result(), self.pos)))
+        code.put_gotref(self.py_result())
+
+class KeywordArgsNode(ExprNode):
+    # Helper class for keyword arguments
+    #
+    # keyword_args ExprNode or None     Keyword arguments
+    # starstar_arg ExprNode or None     Extra arguments
+
+    subexprs = ['keyword_args', 'starstar_arg']
+
+    def analyse_types(self, env):
+        if self.keyword_args:
+            self.keyword_args.analyse_types(env)
+        if self.starstar_arg:
+            self.starstar_arg.analyse_types(env)
+            # make sure we have a Python object as **kwargs mapping
+            self.starstar_arg = \
+                self.starstar_arg.coerce_to_pyobject(env)
+        self.type = py_object_type
+        self.is_temp = 1
+
+    gil_message = "Constructing Keyword Args"
+
+    def generate_result_code(self, code):
+        if self.keyword_args and self.starstar_arg:
+            code.put_error_if_neg(self.pos,
+                "PyDict_Update(%s, %s)" % (
+                    self.keyword_args.py_result(),
+                    self.starstar_arg.py_result()))
+        if self.keyword_args:
+            code.putln("%s = %s;" % (self.result(), self.keyword_args.result()))
+            code.put_incref(self.keyword_args.result(), self.keyword_args.ctype())
+        elif self.starstar_arg:
+            code.putln(
+                "%s = PyDict_Copy(%s); %s" % (
+                    self.result(),
+                    self.starstar_arg.py_result(),
+                    code.error_goto_if_null(self.result(), self.pos)))
+            code.put_gotref(self.py_result())
+        else:
+            code.putln(
+                "%s = PyDict_New(); %s" % (
+                    self.result(),
+                    code.error_goto_if_null(self.result(), self.pos)))
+            code.put_gotref(self.py_result())
+
+class PyClassMetaclassNode(ExprNode):
+    # Helper class holds Python3 metaclass object
+    #
+    #  bases        ExprNode           Base class tuple (not owned by this node)
+    #  mkw          ExprNode           Class keyword arguments (not owned by this node)
+
+    subexprs = []
+
+    def analyse_types(self, env):
+        self.type = py_object_type
+        self.is_temp = True
+
+    def may_be_none(self):
+        return True
+
+    def generate_result_code(self, code):
+        code.putln(
+            "%s = __Pyx_Py3MetaclassGet(%s, %s); %s" % (
+                self.result(),
+                self.bases.result(),
+                self.mkw.result(),
+                code.error_goto_if_null(self.result(), self.pos)))
+        code.put_gotref(self.py_result())
+
+class PyClassNamespaceNode(ExprNode, ModuleNameMixin):
+    # Helper class holds Python3 namespace object
+    #
+    # All this are not owned by this node
+    #  metaclass    ExprNode           Metaclass object
+    #  bases        ExprNode           Base class tuple
+    #  mkw          ExprNode           Class keyword arguments
+    #  doc          ExprNode or None   Doc string (owned)
+
+    subexprs = ['doc']
+
+    def analyse_types(self, env):
+        self.bases.analyse_types(env)
+        if self.doc:
+            self.doc.analyse_types(env)
+            self.doc = self.doc.coerce_to_pyobject(env)
+        self.type = py_object_type
+        self.is_temp = 1
+        #TODO(craig,haoyu) This should be moved to a better place
+        self.set_mod_name(env)
+
+    def may_be_none(self):
+        return True
+
+    def generate_result_code(self, code):
+        cname = code.intern_identifier(self.name)
+        py_mod_name = self.get_py_mod_name(code)
+        if self.doc:
+            doc_code = self.doc.result()
+        else:
+            doc_code = '(PyObject *) NULL'
+        code.putln(
+            "%s = __Pyx_Py3MetaclassPrepare(%s, %s, %s, %s, %s, %s); %s" % (
+                self.result(),
+                self.metaclass.result(),
+                self.bases.result(),
+                cname,
+                self.mkw.result(),
+                py_mod_name,
+                doc_code,
                 code.error_goto_if_null(self.result(), self.pos)))
         code.put_gotref(self.py_result())
 
@@ -4442,9 +4824,9 @@ class BoundMethodNode(ExprNode):
     #
     #  function      ExprNode   Function object
     #  self_object   ExprNode   self object
-    
+
     subexprs = ['function']
-    
+
     def analyse_types(self, env):
         self.function.analyse_types(env)
         self.type = py_object_type
@@ -4468,12 +4850,12 @@ class UnboundMethodNode(ExprNode):
     #  object from a class and a function.
     #
     #  function      ExprNode   Function object
-    
+
     type = py_object_type
     is_temp = 1
-    
+
     subexprs = ['function']
-    
+
     def analyse_types(self, env):
         self.function.analyse_types(env)
 
@@ -4493,29 +4875,33 @@ class UnboundMethodNode(ExprNode):
         code.put_gotref(self.py_result())
 
 
-class PyCFunctionNode(ExprNode):
+class PyCFunctionNode(ExprNode, ModuleNameMixin):
     #  Helper class used in the implementation of Python
     #  class definitions. Constructs a PyCFunction object
     #  from a PyMethodDef struct.
     #
-    #  pymethdef_cname   string   PyMethodDef structure
+    #  pymethdef_cname   string             PyMethodDef structure
     #  self_object       ExprNode or None
     #  binding           bool
+    #  module_name       EncodedString      Name of defining module
 
     subexprs = []
     self_object = None
     binding = False
-    
+
     type = py_object_type
     is_temp = 1
-    
+
     def analyse_types(self, env):
         if self.binding:
             env.use_utility_code(binding_cfunc_utility_code)
 
+        #TODO(craig,haoyu) This should be moved to a better place
+        self.set_mod_name(env)
+
     def may_be_none(self):
         return False
-    
+
     gil_message = "Constructing Python function"
 
     def self_result_code(self):
@@ -4527,25 +4913,31 @@ class PyCFunctionNode(ExprNode):
 
     def generate_result_code(self, code):
         if self.binding:
-            constructor = "%s_New" % Naming.binding_cfunc
+            constructor = "%s_NewEx" % Naming.binding_cfunc
         else:
-            constructor = "PyCFunction_New"
+            constructor = "PyCFunction_NewEx"
+        py_mod_name = self.get_py_mod_name(code)
         code.putln(
-            "%s = %s(&%s, %s); %s" % (
+            '%s = %s(&%s, %s, %s); %s' % (
                 self.result(),
                 constructor,
                 self.pymethdef_cname,
                 self.self_result_code(),
+                py_mod_name,
                 code.error_goto_if_null(self.result(), self.pos)))
         code.put_gotref(self.py_result())
 
 class InnerFunctionNode(PyCFunctionNode):
     # Special PyCFunctionNode that depends on a closure class
     #
+
     binding = True
-    
+    needs_self_code = True
+
     def self_result_code(self):
-        return "((PyObject*)%s)" % Naming.cur_scope_cname
+        if self.needs_self_code:
+            return "((PyObject*)%s)" % (Naming.cur_scope_cname)
+        return "NULL"
 
 class LambdaNode(InnerFunctionNode):
     # Lambda expression node (only used as a function reference)
@@ -4563,7 +4955,6 @@ class LambdaNode(InnerFunctionNode):
     name = StringEncoding.EncodedString('<lambda>')
 
     def analyse_declarations(self, env):
-        #self.def_node.needs_closure = self.needs_closure
         self.def_node.analyse_declarations(env)
         self.pymethdef_cname = self.def_node.entry.pymethdef_cname
         env.add_lambda_def(self.def_node)
@@ -4619,14 +5010,14 @@ class UnopNode(ExprNode):
     #      - Check operand type and coerce if needed.
     #      - Determine result type and result code fragment.
     #      - Allocate temporary for result if needed.
-    
+
     subexprs = ['operand']
     infix = True
 
     def calculate_constant_result(self):
         func = compile_time_unary_operators[self.operator]
         self.constant_result = func(self.operand.constant_result)
-    
+
     def compile_time_value(self, denv):
         func = compile_time_unary_operators.get(self.operator)
         if not func:
@@ -4638,7 +5029,7 @@ class UnopNode(ExprNode):
             return func(operand)
         except Exception, e:
             self.compile_time_value_error(e)
-    
+
     def infer_type(self, env):
         operand_type = self.operand.infer_type(env)
         if operand_type.is_pyobject:
@@ -4656,10 +5047,10 @@ class UnopNode(ExprNode):
             self.analyse_cpp_operation(env)
         else:
             self.analyse_c_operation(env)
-    
+
     def check_const(self):
         return self.operand.check_const()
-    
+
     def is_py_operation(self):
         return self.operand.type.is_pyobject
 
@@ -4670,24 +5061,24 @@ class UnopNode(ExprNode):
     def is_cpp_operation(self):
         type = self.operand.type
         return type.is_cpp_class
-    
+
     def coerce_operand_to_pyobject(self, env):
         self.operand = self.operand.coerce_to_pyobject(env)
-    
+
     def generate_result_code(self, code):
         if self.operand.type.is_pyobject:
             self.generate_py_operation_code(code)
-    
+
     def generate_py_operation_code(self, code):
         function = self.py_operation_function()
         code.putln(
             "%s = %s(%s); %s" % (
-                self.result(), 
-                function, 
+                self.result(),
+                function,
                 self.operand.py_result(),
                 code.error_goto_if_null(self.result(), self.pos)))
         code.put_gotref(self.py_result())
-        
+
     def type_error(self):
         if not self.operand.type.is_error:
             error(self.pos, "Invalid operand type for '%s' (%s)" %
@@ -4714,11 +5105,11 @@ class NotNode(ExprNode):
     #  'not' operator
     #
     #  operand   ExprNode
-    
+
     type = PyrexTypes.c_bint_type
 
     subexprs = ['operand']
-    
+
     def calculate_constant_result(self):
         self.constant_result = not self.operand.constant_result
 
@@ -4731,29 +5122,29 @@ class NotNode(ExprNode):
 
     def infer_type(self, env):
         return PyrexTypes.c_bint_type
-    
+
     def analyse_types(self, env):
         self.operand.analyse_types(env)
         self.operand = self.operand.coerce_to_boolean(env)
-    
+
     def calculate_result_code(self):
         return "(!%s)" % self.operand.result()
-    
+
     def generate_result_code(self, code):
         pass
 
 
 class UnaryPlusNode(UnopNode):
     #  unary '+' operator
-    
+
     operator = '+'
-    
+
     def analyse_c_operation(self, env):
         self.type = self.operand.type
-    
+
     def py_operation_function(self):
         return "PyNumber_Positive"
-    
+
     def calculate_result_code(self):
         if self.is_cpp_operation():
             return "(+%s)" % self.operand.result()
@@ -4763,9 +5154,9 @@ class UnaryPlusNode(UnopNode):
 
 class UnaryMinusNode(UnopNode):
     #  unary '-' operator
-    
+
     operator = '-'
-    
+
     def analyse_c_operation(self, env):
         if self.operand.type.is_numeric:
             self.type = self.operand.type
@@ -4773,10 +5164,10 @@ class UnaryMinusNode(UnopNode):
             self.type_error()
         if self.type.is_complex:
             self.infix = False
-    
+
     def py_operation_function(self):
         return "PyNumber_Negative"
-    
+
     def calculate_result_code(self):
         if self.infix:
             return "(-%s)" % self.operand.result()
@@ -4799,7 +5190,7 @@ class TildeNode(UnopNode):
 
     def py_operation_function(self):
         return "PyNumber_Invert"
-    
+
     def calculate_result_code(self):
         return "(~%s)" % self.operand.result()
 
@@ -4813,7 +5204,7 @@ class DereferenceNode(CUnopNode):
     #  unary * operator
 
     operator = '*'
-    
+
     def analyse_c_operation(self, env):
         if self.operand.type.is_ptr:
             self.type = self.operand.type.base_type
@@ -4826,7 +5217,7 @@ class DereferenceNode(CUnopNode):
 
 class DecrementIncrementNode(CUnopNode):
     #  unary ++/-- operator
-    
+
     def analyse_c_operation(self, env):
         if self.operand.type.is_ptr or self.operand.type.is_numeric:
             self.type = self.operand.type
@@ -4847,9 +5238,9 @@ class AmpersandNode(ExprNode):
     #  The C address-of operator.
     #
     #  operand  ExprNode
-    
+
     subexprs = ['operand']
-    
+
     def infer_type(self, env):
         return PyrexTypes.c_ptr_type(self.operand.infer_type(env))
 
@@ -4863,21 +5254,21 @@ class AmpersandNode(ExprNode):
             self.error("Cannot take address of Python variable")
             return
         self.type = PyrexTypes.c_ptr_type(argtype)
-    
+
     def check_const(self):
         return self.operand.check_const_addr()
-    
+
     def error(self, mess):
         error(self.pos, mess)
         self.type = PyrexTypes.error_type
         self.result_code = "<error>"
-    
+
     def calculate_result_code(self):
         return "(&%s)" % self.operand.result()
 
     def generate_result_code(self, code):
         pass
-    
+
 
 unop_node_classes = {
     "+":  UnaryPlusNode,
@@ -4886,14 +5277,14 @@ unop_node_classes = {
 }
 
 def unop_node(pos, operator, operand):
-    # Construct unnop node of appropriate class for 
+    # Construct unnop node of appropriate class for
     # given operator.
     if isinstance(operand, IntNode) and operator == '-':
-        return IntNode(pos = operand.pos, value = str(-int(operand.value, 0)))
+        return IntNode(pos = operand.pos, value = str(-Utils.str_to_number(operand.value)))
     elif isinstance(operand, UnopNode) and operand.operator == operator:
         warning(pos, "Python has no increment/decrement operator: %s%sx = %s(%sx) = x" % ((operator,)*4), 5)
-    return unop_node_classes[operator](pos, 
-        operator = operator, 
+    return unop_node_classes[operator](pos,
+        operator = operator,
         operand = operand)
 
 
@@ -4906,19 +5297,19 @@ class TypecastNode(ExprNode):
     #
     #  If used from a transform, one can if wanted specify the attribute
     #  "type" directly and leave base_type and declarator to None
-    
+
     subexprs = ['operand']
     base_type = declarator = type = None
-    
+
     def type_dependencies(self, env):
         return ()
-    
+
     def infer_type(self, env):
         if self.type is None:
             base_type = self.base_type.analyse(env)
             _, self.type = self.declarator.analyse(base_type, env)
         return self.type
-    
+
     def analyse_types(self, env):
         if self.type is None:
             base_type = self.base_type.analyse(env)
@@ -4946,7 +5337,7 @@ class TypecastNode(ExprNode):
                     if not (self.operand.type.base_type.is_void or self.operand.type.base_type.is_struct):
                         error(self.pos, "Python objects cannot be cast from pointers of primitive types")
                 else:
-                    # Should this be an error? 
+                    # Should this be an error?
                     warning(self.pos, "No conversion from %s to %s, python object pointer used." % (self.operand.type, self.type))
                 self.operand = self.operand.coerce_to_simple(env)
         elif from_py and not to_py:
@@ -4974,7 +5365,7 @@ class TypecastNode(ExprNode):
         # we usually do not know the result of a type cast at code
         # generation time
         pass
-    
+
     def calculate_result_code(self):
         if self.type.is_complex:
             operand_result = self.operand.result()
@@ -4987,15 +5378,15 @@ class TypecastNode(ExprNode):
             return "%s(%s, %s)" % (
                     self.type.from_parts,
                     real_part,
-                    imag_part)    
+                    imag_part)
         else:
             return self.type.cast_code(self.operand.result())
-    
+
     def get_constant_c_result_code(self):
         operand_result = self.operand.get_constant_c_result_code()
         if operand_result:
             return self.type.cast_code(operand_result)
-    
+
     def result_as(self, type):
         if self.type.is_pyobject and not self.is_temp:
             #  Optimise away some unnecessary casting
@@ -5014,7 +5405,7 @@ class TypecastNode(ExprNode):
 
 class SizeofNode(ExprNode):
     #  Abstract base class for sizeof(x) expression nodes.
-    
+
     type = PyrexTypes.c_size_t_type
 
     def check_const(self):
@@ -5029,10 +5420,10 @@ class SizeofTypeNode(SizeofNode):
     #
     #  base_type   CBaseTypeNode
     #  declarator  CDeclaratorNode
-    
+
     subexprs = []
     arg_type = None
-    
+
     def analyse_types(self, env):
         # we may have incorrectly interpreted a dotted name as a type rather than an attribute
         # this could be better handled by more uniformly treating types as runtime-available objects
@@ -5053,7 +5444,7 @@ class SizeofTypeNode(SizeofNode):
             _, arg_type = self.declarator.analyse(base_type, env)
             self.arg_type = arg_type
         self.check_type()
-        
+
     def check_type(self):
         arg_type = self.arg_type
         if arg_type.is_pyobject and not arg_type.is_extension_type:
@@ -5062,7 +5453,7 @@ class SizeofTypeNode(SizeofNode):
             error(self.pos, "Cannot take sizeof void")
         elif not arg_type.is_complete():
             error(self.pos, "Cannot take sizeof incomplete type '%s'" % arg_type)
-        
+
     def calculate_result_code(self):
         if self.arg_type.is_extension_type:
             # the size of the pointer is boring
@@ -5071,15 +5462,15 @@ class SizeofTypeNode(SizeofNode):
         else:
             arg_code = self.arg_type.declaration_code("")
         return "(sizeof(%s))" % arg_code
-    
+
 
 class SizeofVarNode(SizeofNode):
     #  C sizeof function applied to a variable
     #
     #  operand   ExprNode
-    
+
     subexprs = ['operand']
-    
+
     def analyse_types(self, env):
         # We may actually be looking at a type rather than a variable...
         # If we are, traditional analysis would fail...
@@ -5090,10 +5481,10 @@ class SizeofVarNode(SizeofNode):
             self.check_type()
         else:
             self.operand.analyse_types(env)
-    
+
     def calculate_result_code(self):
         return "(sizeof(%s))" % self.operand.result()
-    
+
     def generate_result_code(self, code):
         pass
 
@@ -5102,12 +5493,12 @@ class TypeofNode(ExprNode):
     #
     #  operand   ExprNode
     #  literal   StringNode # internal
-    
+
     literal = None
     type = py_object_type
-    
+
     subexprs = ['literal'] # 'operand' will be ignored after type analysis!
-    
+
     def analyse_types(self, env):
         self.operand.analyse_types(env)
         self.literal = StringNode(
@@ -5120,7 +5511,7 @@ class TypeofNode(ExprNode):
 
     def generate_evaluation_code(self, code):
         self.literal.generate_evaluation_code(code)
-    
+
     def calculate_result_code(self):
         return self.literal.calculate_result_code()
 
@@ -5178,8 +5569,9 @@ class BinopNode(ExprNode):
     #      - Check operand types and coerce if needed.
     #      - Determine result type and result code fragment.
     #      - Allocate temporary for result if needed.
-    
+
     subexprs = ['operand1', 'operand2']
+    inplace = False
 
     def calculate_constant_result(self):
         func = compile_time_binary_operators[self.operator]
@@ -5195,14 +5587,17 @@ class BinopNode(ExprNode):
             return func(operand1, operand2)
         except Exception, e:
             self.compile_time_value_error(e)
-    
+
     def infer_type(self, env):
         return self.result_type(self.operand1.infer_type(env),
                                 self.operand2.infer_type(env))
-    
+
     def analyse_types(self, env):
         self.operand1.analyse_types(env)
         self.operand2.analyse_types(env)
+        self.analyse_operation(env)
+
+    def analyse_operation(self, env):
         if self.is_py_operation():
             self.coerce_operands_to_pyobjects(env)
             self.type = self.result_type(self.operand1.type,
@@ -5213,17 +5608,17 @@ class BinopNode(ExprNode):
             self.analyse_cpp_operation(env)
         else:
             self.analyse_c_operation(env)
-    
+
     def is_py_operation(self):
         return self.is_py_operation_types(self.operand1.type, self.operand2.type)
-    
+
     def is_py_operation_types(self, type1, type2):
         return type1.is_pyobject or type2.is_pyobject
 
     def is_cpp_operation(self):
         return (self.operand1.type.is_cpp_class
             or self.operand2.type.is_cpp_class)
-    
+
     def analyse_cpp_operation(self, env):
         type1 = self.operand1.type
         type2 = self.operand2.type
@@ -5240,7 +5635,7 @@ class BinopNode(ExprNode):
             self.operand1 = self.operand1.coerce_to(func_type.args[0].type, env)
             self.operand2 = self.operand2.coerce_to(func_type.args[1].type, env)
         self.type = func_type.return_type
-    
+
     def result_type(self, type1, type2):
         if self.is_py_operation_types(type1, type2):
             if type2.is_string:
@@ -5274,55 +5669,55 @@ class BinopNode(ExprNode):
     def nogil_check(self, env):
         if self.is_py_operation():
             self.gil_error()
-        
+
     def coerce_operands_to_pyobjects(self, env):
         self.operand1 = self.operand1.coerce_to_pyobject(env)
         self.operand2 = self.operand2.coerce_to_pyobject(env)
-    
+
     def check_const(self):
         return self.operand1.check_const() and self.operand2.check_const()
-    
+
     def generate_result_code(self, code):
         #print "BinopNode.generate_result_code:", self.operand1, self.operand2 ###
         if self.operand1.type.is_pyobject:
             function = self.py_operation_function()
-            if function == "PyNumber_Power":
+            if self.operator == '**':
                 extra_args = ", Py_None"
             else:
                 extra_args = ""
             code.putln(
                 "%s = %s(%s, %s%s); %s" % (
-                    self.result(), 
-                    function, 
+                    self.result(),
+                    function,
                     self.operand1.py_result(),
                     self.operand2.py_result(),
                     extra_args,
                     code.error_goto_if_null(self.result(), self.pos)))
             code.put_gotref(self.py_result())
-    
+
     def type_error(self):
         if not (self.operand1.type.is_error
                 or self.operand2.type.is_error):
             error(self.pos, "Invalid operand types for '%s' (%s; %s)" %
-                (self.operator, self.operand1.type, 
+                (self.operator, self.operand1.type,
                     self.operand2.type))
         self.type = PyrexTypes.error_type
 
 
 class CBinopNode(BinopNode):
-    
+
     def analyse_types(self, env):
         BinopNode.analyse_types(self, env)
         if self.is_py_operation():
             self.type = PyrexTypes.error_type
-    
+
     def py_operation_function():
         return ""
-        
+
     def calculate_result_code(self):
         return "(%s %s %s)" % (
-            self.operand1.result(), 
-            self.operator, 
+            self.operand1.result(),
+            self.operator,
             self.operand2.result())
 
 
@@ -5333,9 +5728,9 @@ def c_binop_constructor(operator):
 
 class NumBinopNode(BinopNode):
     #  Binary operation taking numeric arguments.
-    
+
     infix = True
-    
+
     def analyse_c_operation(self, env):
         type1 = self.operand1.type
         type2 = self.operand2.type
@@ -5348,10 +5743,15 @@ class NumBinopNode(BinopNode):
         if not self.infix or (type1.is_numeric and type2.is_numeric):
             self.operand1 = self.operand1.coerce_to(self.type, env)
             self.operand2 = self.operand2.coerce_to(self.type, env)
-    
+
     def compute_c_result_type(self, type1, type2):
         if self.c_types_okay(type1, type2):
-            return PyrexTypes.widest_numeric_type(type1, type2)
+            widest_type = PyrexTypes.widest_numeric_type(type1, type2)
+            if widest_type is PyrexTypes.c_bint_type:
+                if self.operator not in '|^&':
+                    # False + False == 0 # not False!
+                    widest_type = PyrexTypes.c_int_type
+            return widest_type
         else:
             return None
 
@@ -5362,7 +5762,7 @@ class NumBinopNode(BinopNode):
             return "(%s %s %s)" % (value1, self.operator, value2)
         else:
             return None
-    
+
     def c_types_okay(self, type1, type2):
         #print "NumBinopNode.c_types_okay:", type1, type2 ###
         return (type1.is_numeric  or type1.is_enum) \
@@ -5371,8 +5771,8 @@ class NumBinopNode(BinopNode):
     def calculate_result_code(self):
         if self.infix:
             return "(%s %s %s)" % (
-                self.operand1.result(), 
-                self.operator, 
+                self.operand1.result(),
+                self.operator,
                 self.operand2.result())
         else:
             func = self.type.binary_op(self.operator)
@@ -5382,14 +5782,17 @@ class NumBinopNode(BinopNode):
                 func,
                 self.operand1.result(),
                 self.operand2.result())
-    
+
     def is_py_operation_types(self, type1, type2):
         return (type1 is PyrexTypes.c_py_unicode_type or
                 type2 is PyrexTypes.c_py_unicode_type or
                 BinopNode.is_py_operation_types(self, type1, type2))
-    
+
     def py_operation_function(self):
-        return self.py_functions[self.operator]
+        fuction = self.py_functions[self.operator]
+        if self.inplace:
+            fuction = fuction.replace('PyNumber_', 'PyNumber_InPlace')
+        return fuction
 
     py_functions = {
         "|":        "PyNumber_Or",
@@ -5406,19 +5809,18 @@ class NumBinopNode(BinopNode):
         "**":       "PyNumber_Power"
     }
 
-
 class IntBinopNode(NumBinopNode):
     #  Binary operation taking integer arguments.
-    
+
     def c_types_okay(self, type1, type2):
         #print "IntBinopNode.c_types_okay:", type1, type2 ###
         return (type1.is_int or type1.is_enum) \
             and (type2.is_int or type2.is_enum)
 
-    
+
 class AddNode(NumBinopNode):
     #  '+' operator.
-    
+
     def is_py_operation_types(self, type1, type2):
         if type1.is_string and type2.is_string:
             return 1
@@ -5438,7 +5840,7 @@ class AddNode(NumBinopNode):
 
 class SubNode(NumBinopNode):
     #  '-' operator.
-    
+
     def compute_c_result_type(self, type1, type2):
         if (type1.is_ptr or type1.is_array) and (type2.is_int or type2.is_enum):
             return type1
@@ -5451,7 +5853,7 @@ class SubNode(NumBinopNode):
 
 class MulNode(NumBinopNode):
     #  '*' operator.
-    
+
     def is_py_operation_types(self, type1, type2):
         if (type1.is_string and type2.is_int) \
             or (type2.is_string and type1.is_int):
@@ -5462,7 +5864,7 @@ class MulNode(NumBinopNode):
 
 class DivNode(NumBinopNode):
     #  '/' or '//' operator.
-    
+
     cdivision = None
     truedivision = None   # == "unknown" if operator == '/'
     ctruedivision = False
@@ -5495,12 +5897,12 @@ class DivNode(NumBinopNode):
         except Exception, e:
             self.compile_time_value_error(e)
 
-    def analyse_types(self, env):
+    def analyse_operation(self, env):
         if self.cdivision or env.directives['cdivision']:
             self.ctruedivision = False
         else:
             self.ctruedivision = self.truedivision
-        NumBinopNode.analyse_types(self, env)
+        NumBinopNode.analyse_operation(self, env)
         if self.is_cpp_operation():
             self.cdivision = True
         if not self.type.is_pyobject:
@@ -5532,14 +5934,14 @@ class DivNode(NumBinopNode):
     def generate_evaluation_code(self, code):
         if not self.type.is_pyobject and not self.type.is_complex:
             if self.cdivision is None:
-                self.cdivision = (code.globalstate.directives['cdivision'] 
+                self.cdivision = (code.globalstate.directives['cdivision']
                                     or not self.type.signed
                                     or self.type.is_float)
             if not self.cdivision:
                 code.globalstate.use_utility_code(div_int_utility_code.specialize(self.type))
         NumBinopNode.generate_evaluation_code(self, code)
         self.generate_div_warning_code(code)
-    
+
     def generate_div_warning_code(self, code):
         if not self.type.is_pyobject:
             if self.zerodivision_check:
@@ -5554,7 +5956,7 @@ class DivNode(NumBinopNode):
                 if self.type.is_int and self.type.signed and self.operator != '%':
                     code.globalstate.use_utility_code(division_overflow_test_code)
                     code.putln("else if (sizeof(%s) == sizeof(long) && unlikely(%s == -1) && unlikely(UNARY_NEG_WOULD_OVERFLOW(%s))) {" % (
-                                    self.type.declaration_code(''), 
+                                    self.type.declaration_code(''),
                                     self.operand2.result(),
                                     self.operand1.result()))
                     code.putln('PyErr_Format(PyExc_OverflowError, "value too large to perform division");')
@@ -5569,7 +5971,7 @@ class DivNode(NumBinopNode):
                 code.put("if (__Pyx_cdivision_warning()) ")
                 code.put_goto(code.error_label)
                 code.putln("}")
-    
+
     def calculate_result_code(self):
         if self.type.is_complex:
             return NumBinopNode.calculate_result_code(self)
@@ -5589,7 +5991,7 @@ class DivNode(NumBinopNode):
         else:
             return "__Pyx_div_%s(%s, %s)" % (
                     self.type.specialization_name(),
-                    self.operand1.result(), 
+                    self.operand1.result(),
                     self.operand2.result())
 
 
@@ -5606,7 +6008,7 @@ class ModNode(DivNode):
             return "integer division or modulo by zero"
         else:
             return "float divmod()"
-    
+
     def generate_evaluation_code(self, code):
         if not self.type.is_pyobject:
             if self.cdivision is None:
@@ -5619,45 +6021,56 @@ class ModNode(DivNode):
                         mod_float_utility_code.specialize(self.type, math_h_modifier=self.type.math_h_modifier))
         NumBinopNode.generate_evaluation_code(self, code)
         self.generate_div_warning_code(code)
-    
+
     def calculate_result_code(self):
         if self.cdivision:
             if self.type.is_float:
                 return "fmod%s(%s, %s)" % (
                     self.type.math_h_modifier,
-                    self.operand1.result(), 
+                    self.operand1.result(),
                     self.operand2.result())
             else:
                 return "(%s %% %s)" % (
-                    self.operand1.result(), 
+                    self.operand1.result(),
                     self.operand2.result())
         else:
             return "__Pyx_mod_%s(%s, %s)" % (
                     self.type.specialization_name(),
-                    self.operand1.result(), 
+                    self.operand1.result(),
                     self.operand2.result())
 
 class PowNode(NumBinopNode):
     #  '**' operator.
-    
+
     def analyse_c_operation(self, env):
         NumBinopNode.analyse_c_operation(self, env)
         if self.type.is_complex:
-            error(self.pos, "complex powers not yet supported")
-            self.pow_func = "<error>"
+            if self.type.real_type.is_float:
+                self.operand1 = self.operand1.coerce_to(self.type, env)
+                self.operand2 = self.operand2.coerce_to(self.type, env)
+                self.pow_func = "__Pyx_c_pow" + self.type.real_type.math_h_modifier
+            else:
+                error(self.pos, "complex int powers not supported")
+                self.pow_func = "<error>"
         elif self.type.is_float:
-            self.pow_func = "pow"
+            self.pow_func = "pow" + self.type.math_h_modifier
         else:
             self.pow_func = "__Pyx_pow_%s" % self.type.declaration_code('').replace(' ', '_')
             env.use_utility_code(
-                    int_pow_utility_code.specialize(func_name=self.pow_func, 
+                    int_pow_utility_code.specialize(func_name=self.pow_func,
                                                 type=self.type.declaration_code('')))
 
     def calculate_result_code(self):
+        # Work around MSVC overloading ambiguity.
+        def typecast(operand):
+            if self.type == operand.type:
+                return operand.result()
+            else:
+                return self.type.cast_code(operand.result())
         return "%s(%s, %s)" % (
-            self.pow_func, 
-            self.operand1.result(), 
-            self.operand2.result())
+            self.pow_func,
+            typecast(self.operand1),
+            typecast(self.operand2))
 
 
 # Note: This class is temporarily "shut down" into an ineffective temp
@@ -5672,9 +6085,9 @@ class BoolBinopNode(ExprNode):
     #  operator     string
     #  operand1     ExprNode
     #  operand2     ExprNode
-    
+
     subexprs = ['operand1', 'operand2']
-    
+
     def infer_type(self, env):
         type1 = self.operand1.infer_type(env)
         type2 = self.operand2.infer_type(env)
@@ -5695,7 +6108,7 @@ class BoolBinopNode(ExprNode):
             self.constant_result = \
                 self.operand1.constant_result or \
                 self.operand2.constant_result
-    
+
     def compile_time_value(self, denv):
         if self.operator == 'and':
             return self.operand1.compile_time_value(denv) \
@@ -5703,7 +6116,7 @@ class BoolBinopNode(ExprNode):
         else:
             return self.operand1.compile_time_value(denv) \
                 or self.operand2.compile_time_value(denv)
-    
+
     def coerce_to_boolean(self, env):
         return BoolBinopNode(
             self.pos,
@@ -5719,7 +6132,7 @@ class BoolBinopNode(ExprNode):
         self.type = PyrexTypes.independent_spanning_type(self.operand1.type, self.operand2.type)
         self.operand1 = self.operand1.coerce_to(self.type, env)
         self.operand2 = self.operand2.coerce_to(self.type, env)
-        
+
         # For what we're about to do, it's vital that
         # both operands be temp nodes.
         self.operand1 = self.operand1.coerce_to_simple(env)
@@ -5730,7 +6143,7 @@ class BoolBinopNode(ExprNode):
 
     def check_const(self):
         return self.operand1.check_const() and self.operand2.check_const()
-    
+
     def generate_evaluation_code(self, code):
         code.mark_pos(self.pos)
         self.operand1.generate_evaluation_code(code)
@@ -5758,7 +6171,7 @@ class BoolBinopNode(ExprNode):
         self.operand1.generate_post_assignment_code(code)
         self.operand1.free_temps(code)
         code.putln("}")
-    
+
     def generate_operand1_test(self, code):
         #  Generate code to test the truth of the first operand.
         if self.type.is_pyobject:
@@ -5780,15 +6193,15 @@ class CondExprNode(ExprNode):
     #  test        ExprNode
     #  true_val    ExprNode
     #  false_val   ExprNode
-    
+
     true_val = None
     false_val = None
-    
+
     subexprs = ['test', 'true_val', 'false_val']
-    
+
     def type_dependencies(self, env):
         return self.true_val.type_dependencies(env) + self.false_val.type_dependencies(env)
-    
+
     def infer_type(self, env):
         return PyrexTypes.independent_spanning_type(self.true_val.infer_type(env),
                                                     self.false_val.infer_type(env))
@@ -5811,22 +6224,22 @@ class CondExprNode(ExprNode):
         self.is_temp = 1
         if self.type == PyrexTypes.error_type:
             self.type_error()
-        
+
     def type_error(self):
         if not (self.true_val.type.is_error or self.false_val.type.is_error):
             error(self.pos, "Incompatable types in conditional expression (%s; %s)" %
                 (self.true_val.type, self.false_val.type))
         self.type = PyrexTypes.error_type
-    
+
     def check_const(self):
-        return (self.test.check_const() 
+        return (self.test.check_const()
             and self.true_val.check_const()
             and self.false_val.check_const())
-    
+
     def generate_evaluation_code(self, code):
         # Because subexprs may not be evaluated we can use a more optimal
         # subexpr allocation strategy than the default, so override evaluation_code.
-        
+
         code.mark_pos(self.pos)
         self.allocate_temp_result(code)
         self.test.generate_evaluation_code(code)
@@ -5858,7 +6271,9 @@ richcmp_constants = {
 class CmpNode(object):
     #  Mixin class containing code common to PrimaryCmpNodes
     #  and CascadedCmpNodes.
-    
+
+    special_bool_cmp_function = None
+
     def infer_type(self, env):
         # TODO: Actually implement this (after merging with -unstable).
         return py_object_type
@@ -5977,6 +6392,12 @@ class CmpNode(object):
                 self.invalid_types_error(operand1, op, operand2)
                 new_common_type = error_type
 
+        if new_common_type.is_string and (isinstance(operand1, BytesNode) or
+                                          isinstance(operand2, BytesNode)):
+            # special case when comparing char* to bytes literal: must
+            # compare string values!
+            new_common_type = bytes_type
+
         # recursively merge types
         if common_type is None or new_common_type.is_error:
             common_type = new_common_type
@@ -6011,6 +6432,7 @@ class CmpNode(object):
 
     def is_python_result(self):
         return ((self.has_python_operands() and
+                 self.special_bool_cmp_function is None and
                  self.operator not in ('is', 'is_not', 'in', 'not_in') and
                  not self.is_c_string_contains() and
                  not self.is_ptr_contains())
@@ -6022,40 +6444,56 @@ class CmpNode(object):
                  and (self.operand2.type.is_string or self.operand2.type is bytes_type)) or
                 (self.operand1.type is PyrexTypes.c_py_unicode_type
                  and self.operand2.type is unicode_type))
-    
+
     def is_ptr_contains(self):
         if self.operator in ('in', 'not_in'):
-            iterator = self.operand2
-            if iterator.type.is_ptr or iterator.type.is_array:
-                return iterator.type.base_type is not PyrexTypes.c_char_type
-            if (isinstance(iterator, IndexNode) and
-                isinstance(iterator.index, (SliceNode, CoerceFromPyTypeNode)) and
-                (iterator.base.type.is_array or iterator.base.type.is_ptr)):
-                return iterator.base.type.base_type is not PyrexTypes.c_char_type
-
-    def generate_operation_code(self, code, result_code, 
+            container_type = self.operand2.type
+            return (container_type.is_ptr or container_type.is_array) \
+                and not container_type.is_string
+
+    def find_special_bool_compare_function(self, env):
+        if self.operator in ('==', '!='):
+            type1, type2 = self.operand1.type, self.operand2.type
+            if type1.is_pyobject and type2.is_pyobject:
+                if type1 is Builtin.unicode_type or type2 is Builtin.unicode_type:
+                    env.use_utility_code(pyunicode_equals_utility_code)
+                    self.special_bool_cmp_function = "__Pyx_PyUnicode_Equals"
+                    return True
+        return False
+
+    def generate_operation_code(self, code, result_code,
             operand1, op , operand2):
         if self.type.is_pyobject:
             coerce_result = "__Pyx_PyBool_FromLong"
         else:
             coerce_result = ""
-        if 'not' in op: 
+        if 'not' in op:
             negation = "!"
-        else: 
+        else:
             negation = ""
-        if op == 'in' or op == 'not_in':
+        if self.special_bool_cmp_function:
+            if operand1.type.is_pyobject:
+                result1 = operand1.py_result()
+            else:
+                result1 = operand1.result()
+            if operand2.type.is_pyobject:
+                result2 = operand2.py_result()
+            else:
+                result2 = operand2.result()
+            code.putln("%s = %s(%s, %s, %s); %s" % (
+                result_code,
+                self.special_bool_cmp_function,
+                result1,
+                result2,
+                richcmp_constants[op],
+                code.error_goto_if_neg(result_code, self.pos)))
+        elif op == 'in' or op == 'not_in':
             code.globalstate.use_utility_code(contains_utility_code)
             if self.type.is_pyobject:
                 coerce_result = "__Pyx_PyBoolOrNull_FromLong"
             if op == 'not_in':
                 negation = "__Pyx_NegateNonNeg"
             if operand2.type is dict_type:
-                code.globalstate.use_utility_code(
-                    raise_none_iter_error_utility_code)
-                code.putln("if (unlikely(%s == Py_None)) {" % operand2.py_result())
-                code.putln("__Pyx_RaiseNoneNotIterableError(); %s" %
-                           code.error_goto(self.pos))
-                code.putln("} else {")
                 method = "PyDict_Contains"
             else:
                 method = "PySequence_Contains"
@@ -6071,33 +6509,30 @@ class CmpNode(object):
                     coerce_result,
                     negation,
                     method,
-                    operand2.py_result(), 
-                    operand1.py_result(), 
+                    operand2.py_result(),
+                    operand1.py_result(),
                     got_ref,
                     error_clause(result_code, self.pos)))
-            if operand2.type is dict_type:
-                code.putln("}")
-                    
         elif (operand1.type.is_pyobject
             and op not in ('is', 'is_not')):
                 code.putln("%s = PyObject_RichCompare(%s, %s, %s); %s" % (
-                        result_code, 
-                        operand1.py_result(), 
-                        operand2.py_result(), 
+                        result_code,
+                        operand1.py_result(),
+                        operand2.py_result(),
                         richcmp_constants[op],
                         code.error_goto_if_null(result_code, self.pos)))
                 code.put_gotref(result_code)
         elif operand1.type.is_complex:
-            if op == "!=": 
+            if op == "!=":
                 negation = "!"
-            else: 
+            else:
                 negation = ""
             code.putln("%s = %s(%s%s(%s, %s));" % (
-                result_code, 
+                result_code,
                 coerce_result,
                 negation,
-                operand1.type.unary_op('eq'), 
-                operand1.result(), 
+                operand1.type.unary_op('eq'),
+                operand1.result(),
                 operand2.result()))
         else:
             type1 = operand1.type
@@ -6112,10 +6547,10 @@ class CmpNode(object):
             code1 = operand1.result_as(common_type)
             code2 = operand2.result_as(common_type)
             code.putln("%s = %s(%s %s %s);" % (
-                result_code, 
-                coerce_result, 
-                code1, 
-                self.c_operator(op), 
+                result_code,
+                coerce_result,
+                code1,
+                self.c_operator(op),
                 code2))
 
     def c_operator(self, op):
@@ -6125,7 +6560,7 @@ class CmpNode(object):
             return "!="
         else:
             return op
-    
+
 contains_utility_code = UtilityCode(
 proto="""
 static CYTHON_INLINE long __Pyx_NegateNonNeg(long b) { return unlikely(b < 0) ? b : !b; }
@@ -6166,6 +6601,46 @@ static CYTHON_INLINE int __Pyx_UnicodeContains(PyObject* unicode, Py_UNICODE cha
 }
 """)
 
+pyunicode_equals_utility_code = UtilityCode(
+proto="""
+static CYTHON_INLINE int __Pyx_PyUnicode_Equals(PyObject* s1, PyObject* s2, int equals); /*proto*/
+""",
+impl="""
+static CYTHON_INLINE int __Pyx_PyUnicode_Equals(PyObject* s1, PyObject* s2, int equals) {
+    if (s1 == s2) {   /* as done by PyObject_RichCompareBool(); also catches the (interned) empty string */
+        return (equals == Py_EQ);
+    } else if (PyUnicode_CheckExact(s1) & PyUnicode_CheckExact(s2)) {
+        if (PyUnicode_GET_SIZE(s1) != PyUnicode_GET_SIZE(s2)) {
+            return (equals == Py_NE);
+        } else if (PyUnicode_GET_SIZE(s1) == 1) {
+            if (equals == Py_EQ)
+                return (PyUnicode_AS_UNICODE(s1)[0] == PyUnicode_AS_UNICODE(s2)[0]);
+            else
+                return (PyUnicode_AS_UNICODE(s1)[0] != PyUnicode_AS_UNICODE(s2)[0]);
+        } else {
+            int result = PyUnicode_Compare(s1, s2);
+            if ((result == -1) && unlikely(PyErr_Occurred()))
+                return -1;
+            return (equals == Py_EQ) ? (result == 0) : (result != 0);
+        }
+    } else if ((s1 == Py_None) & (s2 == Py_None)) {
+        return (equals == Py_EQ);
+    } else if ((s1 == Py_None) & PyUnicode_CheckExact(s2)) {
+        return (equals == Py_NE);
+    } else if ((s2 == Py_None) & PyUnicode_CheckExact(s1)) {
+        return (equals == Py_NE);
+    } else {
+        int result;
+        PyObject* py_result = PyObject_RichCompare(s1, s2, equals);
+        if (!py_result)
+            return -1;
+        result = __Pyx_PyObject_IsTrue(py_result);
+        Py_DECREF(py_result);
+        return result;
+    }
+}
+""")
+
 
 class PrimaryCmpNode(ExprNode, CmpNode):
     #  Non-cascaded comparison or first comparison of
@@ -6175,14 +6650,14 @@ class PrimaryCmpNode(ExprNode, CmpNode):
     #  operand1      ExprNode
     #  operand2      ExprNode
     #  cascade       CascadedCmpNode
-    
+
     #  We don't use the subexprs mechanism, because
     #  things here are too complicated for it to handle.
     #  Instead, we override all the framework methods
     #  which use it.
-    
+
     child_attrs = ['operand1', 'operand2', 'cascade']
-    
+
     cascade = None
 
     def infer_type(self, env):
@@ -6194,7 +6669,7 @@ class PrimaryCmpNode(ExprNode, CmpNode):
 
     def calculate_constant_result(self):
         self.calculate_cascaded_constant_result(self.operand1.constant_result)
-    
+
     def compile_time_value(self, denv):
         operand1 = self.operand1.compile_time_value(denv)
         return self.cascaded_compile_time_value(operand1, denv)
@@ -6234,8 +6709,14 @@ class PrimaryCmpNode(ExprNode, CmpNode):
                 # Will be transformed by IterationTransform
                 return
             else:
+                if self.operand2.type is dict_type:
+                    self.operand2 = self.operand2.as_none_safe_node("'NoneType' object is not iterable")
                 common_type = py_object_type
                 self.is_pycmp = True
+        elif self.find_special_bool_compare_function(env):
+            common_type = None # if coercion needed, the method call above has already done it
+            self.is_pycmp = False # result is bint
+            self.is_temp = True # must check for error return
         else:
             common_type = self.find_common_type(env, self.operator, self.operand1)
             self.is_pycmp = common_type.is_pyobject
@@ -6258,7 +6739,7 @@ class PrimaryCmpNode(ExprNode, CmpNode):
             cdr = cdr.cascade
         if self.is_pycmp or self.cascade:
             self.is_temp = 1
-    
+
     def analyse_cpp_comparison(self, env):
         type1 = self.operand1.type
         type2 = self.operand2.type
@@ -6278,11 +6759,11 @@ class PrimaryCmpNode(ExprNode, CmpNode):
             self.operand1 = self.operand1.coerce_to(func_type.args[0].type, env)
             self.operand2 = self.operand2.coerce_to(func_type.args[1].type, env)
         self.type = func_type.return_type
-    
+
     def has_python_operands(self):
         return (self.operand1.type.is_pyobject
             or self.operand2.type.is_pyobject)
-    
+
     def check_const(self):
         if self.cascade:
             self.not_const()
@@ -6298,8 +6779,8 @@ class PrimaryCmpNode(ExprNode, CmpNode):
                 negation = ""
             return "(%s%s(%s, %s))" % (
                 negation,
-                self.operand1.type.binary_op('=='), 
-                self.operand1.result(), 
+                self.operand1.type.binary_op('=='),
+                self.operand1.result(),
                 self.operand2.result())
         elif self.is_c_string_contains():
             if self.operand2.type is bytes_type:
@@ -6313,7 +6794,7 @@ class PrimaryCmpNode(ExprNode, CmpNode):
             return "(%s%s(%s, %s))" % (
                 negation,
                 method,
-                self.operand2.result(), 
+                self.operand2.result(),
                 self.operand1.result())
         else:
             return "(%s %s %s)" % (
@@ -6326,7 +6807,7 @@ class PrimaryCmpNode(ExprNode, CmpNode):
         self.operand2.generate_evaluation_code(code)
         if self.is_temp:
             self.allocate_temp_result(code)
-            self.generate_operation_code(code, self.result(), 
+            self.generate_operation_code(code, self.result(),
                 self.operand1, self.operator, self.operand2)
             if self.cascade:
                 self.cascade.generate_evaluation_code(code,
@@ -6341,13 +6822,13 @@ class PrimaryCmpNode(ExprNode, CmpNode):
         #  so only need to dispose of the two main operands.
         self.operand1.generate_disposal_code(code)
         self.operand2.generate_disposal_code(code)
-        
+
     def free_subexpr_temps(self, code):
         #  If this is called, it is a non-cascaded cmp,
         #  so only need to dispose of the two main operands.
         self.operand1.free_temps(code)
         self.operand2.free_temps(code)
-        
+
     def annotate(self, code):
         self.operand1.annotate(code)
         self.operand2.annotate(code)
@@ -6356,9 +6837,9 @@ class PrimaryCmpNode(ExprNode, CmpNode):
 
 
 class CascadedCmpNode(Node, CmpNode):
-    #  A CascadedCmpNode is not a complete expression node. It 
-    #  hangs off the side of another comparison node, shares 
-    #  its left operand with that node, and shares its result 
+    #  A CascadedCmpNode is not a complete expression node. It
+    #  hangs off the side of another comparison node, shares
+    #  its left operand with that node, and shares its result
     #  with the PrimaryCmpNode at the head of the chain.
     #
     #  operator      string
@@ -6388,9 +6869,11 @@ class CascadedCmpNode(Node, CmpNode):
 
     def has_python_operands(self):
         return self.operand2.type.is_pyobject
-        
+
     def coerce_operands_to_pyobjects(self, env):
         self.operand2 = self.operand2.coerce_to_pyobject(env)
+        if self.operand2.type is dict_type and self.operator in ('in', 'not_in'):
+            self.operand2 = self.operand2.as_none_safe_node("'NoneType' object is not iterable")
         if self.cascade:
             self.cascade.coerce_operands_to_pyobjects(env)
 
@@ -6399,7 +6882,7 @@ class CascadedCmpNode(Node, CmpNode):
             #self.operand2 = self.operand2.coerce_to_temp(env) #CTT
             self.operand2 = self.operand2.coerce_to_simple(env)
             self.cascade.coerce_cascaded_operands_to_temp(env)
-    
+
     def generate_evaluation_code(self, code, result, operand1):
         if self.type.is_pyobject:
             code.putln("if (__Pyx_PyObject_IsTrue(%s)) {" % result)
@@ -6407,7 +6890,7 @@ class CascadedCmpNode(Node, CmpNode):
         else:
             code.putln("if (%s) {" % result)
         self.operand2.generate_evaluation_code(code)
-        self.generate_operation_code(code, result, 
+        self.generate_operation_code(code, result,
             operand1, self.operator, self.operand2)
         if self.cascade:
             self.cascade.generate_evaluation_code(
@@ -6440,13 +6923,14 @@ binop_node_classes = {
     "**":       PowNode
 }
 
-def binop_node(pos, operator, operand1, operand2):
-    # Construct binop node of appropriate class for 
+def binop_node(pos, operator, operand1, operand2, inplace=False):
+    # Construct binop node of appropriate class for
     # given operator.
-    return binop_node_classes[operator](pos, 
-        operator = operator, 
-        operand1 = operand1, 
-        operand2 = operand2)
+    return binop_node_classes[operator](pos,
+        operator = operator,
+        operand1 = operand1,
+        operand2 = operand2,
+        inplace = inplace)
 
 #-------------------------------------------------------------------
 #
@@ -6463,10 +6947,10 @@ class CoercionNode(ExprNode):
     #  Abstract base class for coercion nodes.
     #
     #  arg       ExprNode       node being coerced
-    
+
     subexprs = ['arg']
     constant_result = not_a_constant
-    
+
     def __init__(self, arg):
         self.pos = arg.pos
         self.arg = arg
@@ -6476,7 +6960,7 @@ class CoercionNode(ExprNode):
     def calculate_constant_result(self):
         # constant folding can break type coercion, so this is disabled
         pass
-            
+
     def annotate(self, code):
         self.arg.annotate(code)
         if self.arg.type != self.type:
@@ -6486,14 +6970,14 @@ class CoercionNode(ExprNode):
 
 class CastNode(CoercionNode):
     #  Wrap a node in a C type cast.
-    
+
     def __init__(self, arg, new_type):
         CoercionNode.__init__(self, arg)
         self.type = new_type
 
     def may_be_none(self):
         return self.arg.may_be_none()
-    
+
     def calculate_result_code(self):
         return self.arg.result_as(self.type)
 
@@ -6517,7 +7001,7 @@ class PyTypeTestNode(CoercionNode):
 
     nogil_check = Node.gil_error
     gil_message = "Python type test"
-    
+
     def analyse_types(self, env):
         pass
 
@@ -6525,10 +7009,10 @@ class PyTypeTestNode(CoercionNode):
         if self.notnone:
             return False
         return self.arg.may_be_none()
-    
+
     def result_in_temp(self):
         return self.arg.result_in_temp()
-    
+
     def is_ephemeral(self):
         return self.arg.is_ephemeral()
 
@@ -6538,7 +7022,7 @@ class PyTypeTestNode(CoercionNode):
 
     def calculate_result_code(self):
         return self.arg.result()
-    
+
     def generate_result_code(self, code):
         if self.type.typeobj_is_available():
             if not self.type.is_builtin_type:
@@ -6550,7 +7034,7 @@ class PyTypeTestNode(CoercionNode):
         else:
             error(self.pos, "Cannot test type of extern C class "
                 "without type object name specification")
-                
+
     def generate_post_assignment_code(self, code):
         self.arg.generate_post_assignment_code(code)
 
@@ -6581,7 +7065,7 @@ class NoneCheckNode(CoercionNode):
 
     def calculate_result_code(self):
         return self.arg.result()
-    
+
     def generate_result_code(self, code):
         code.putln(
             "if (unlikely(%s == Py_None)) {" % self.arg.result())
@@ -6602,7 +7086,7 @@ class NoneCheckNode(CoercionNode):
 class CoerceToPyTypeNode(CoercionNode):
     #  This node is used to convert a C data type
     #  to a Python object.
-    
+
     type = py_object_type
     is_temp = 1
 
@@ -6611,12 +7095,17 @@ class CoerceToPyTypeNode(CoercionNode):
         if not arg.type.create_to_py_utility_code(env):
             error(arg.pos,
                   "Cannot convert '%s' to Python object" % arg.type)
-        if type is not py_object_type:
-            self.type = py_object_type
-        elif arg.type.is_string:
-            self.type = bytes_type
-        elif arg.type is PyrexTypes.c_py_unicode_type:
-            self.type = unicode_type
+        if type is py_object_type:
+            # be specific about some known types
+            if arg.type.is_string:
+                self.type = bytes_type
+            elif arg.type is PyrexTypes.c_py_unicode_type:
+                self.type = unicode_type
+            elif arg.type.is_complex:
+                self.type = Builtin.complex_type
+        else:
+            # FIXME: check that the target type and the resulting type are compatible
+            pass
 
     gil_message = "Converting to Python object"
 
@@ -6631,7 +7120,7 @@ class CoerceToPyTypeNode(CoercionNode):
             return self.arg.coerce_to_temp(env)
         else:
             return CoerceToBooleanNode(self, env)
-    
+
     def coerce_to_integer(self, env):
         # If not already some C integer type, coerce to longint.
         if self.arg.type.is_int:
@@ -6646,9 +7135,9 @@ class CoerceToPyTypeNode(CoercionNode):
     def generate_result_code(self, code):
         function = self.arg.type.to_py_function
         code.putln('%s = %s(%s); %s' % (
-            self.result(), 
-            function, 
-            self.arg.result(), 
+            self.result(),
+            function,
+            self.arg.result(),
             code.error_goto_if_null(self.result(), self.pos)))
         code.put_gotref(self.py_result())
 
@@ -6707,7 +7196,7 @@ class CoerceFromPyTypeNode(CoercionNode):
         if self.type.is_string and self.arg.is_ephemeral():
             error(arg.pos,
                   "Obtaining char * from temporary Python value")
-    
+
     def analyse_types(self, env):
         # The arg is always already analysed
         pass
@@ -6719,7 +7208,7 @@ class CoerceFromPyTypeNode(CoercionNode):
         if self.type.is_enum:
             rhs = typecast(self.type, c_long_type, rhs)
         code.putln('%s = %s; %s' % (
-            self.result(), 
+            self.result(),
             rhs,
             code.error_goto_if(self.type.error_condition(self.result()), self.pos)))
         if self.type.is_pyobject:
@@ -6729,7 +7218,7 @@ class CoerceFromPyTypeNode(CoercionNode):
 class CoerceToBooleanNode(CoercionNode):
     #  This node is used when a result needs to be used
     #  in a boolean context.
-    
+
     type = PyrexTypes.c_bint_type
 
     _special_builtins = {
@@ -6749,13 +7238,13 @@ class CoerceToBooleanNode(CoercionNode):
             self.gil_error()
 
     gil_message = "Truth-testing Python object"
-    
+
     def check_const(self):
         if self.is_temp:
             self.not_const()
             return False
         return self.arg.check_const()
-    
+
     def calculate_result_code(self):
         return "(%s != 0)" % self.arg.result()
 
@@ -6772,8 +7261,8 @@ class CoerceToBooleanNode(CoercionNode):
         else:
             code.putln(
                 "%s = __Pyx_PyObject_IsTrue(%s); %s" % (
-                    self.result(), 
-                    self.arg.py_result(), 
+                    self.result(),
+                    self.arg.py_result(),
                     code.error_goto_if_neg(self.result(), self.pos)))
 
 class CoerceToComplexNode(CoercionNode):
@@ -6796,7 +7285,7 @@ class CoerceToComplexNode(CoercionNode):
                 self.type.from_parts,
                 real_part,
                 imag_part)
-    
+
     def generate_result_code(self, code):
         pass
 
@@ -6818,7 +7307,7 @@ class CoerceToTempNode(CoercionNode):
     def analyse_types(self, env):
         # The arg is always already analysed
         pass
-        
+
     def coerce_to_boolean(self, env):
         self.arg = self.arg.coerce_to_boolean(env)
         if self.arg.is_simple():
@@ -6841,12 +7330,12 @@ class CloneNode(CoercionNode):
     #  to be used multiple times. The argument node's result must
     #  be in a temporary. This node "borrows" the result from the
     #  argument node, and does not generate any evaluation or
-    #  disposal code for it. The original owner of the argument 
+    #  disposal code for it. The original owner of the argument
     #  node is responsible for doing those things.
-    
+
     subexprs = [] # Arg is not considered a subexpr
     nogil_check = None
-    
+
     def __init__(self, arg):
         CoercionNode.__init__(self, arg)
         if hasattr(arg, 'type'):
@@ -6854,13 +7343,13 @@ class CloneNode(CoercionNode):
             self.result_ctype = arg.result_ctype
         if hasattr(arg, 'entry'):
             self.entry = arg.entry
-            
+
     def result(self):
         return self.arg.result()
-    
+
     def type_dependencies(self, env):
         return self.arg.type_dependencies(env)
-    
+
     def infer_type(self, env):
         return self.arg.infer_type(env)
 
@@ -6870,27 +7359,27 @@ class CloneNode(CoercionNode):
         self.is_temp = 1
         if hasattr(self.arg, 'entry'):
             self.entry = self.arg.entry
-    
+
     def generate_evaluation_code(self, code):
         pass
 
     def generate_result_code(self, code):
         pass
-        
+
     def generate_disposal_code(self, code):
         pass
-                
+
     def free_temps(self, code):
         pass
 
 
 class ModuleRefNode(ExprNode):
     # Simple returns the module object
-    
+
     type = py_object_type
     is_temp = False
     subexprs = []
-    
+
     def analyse_types(self, env):
         pass
 
@@ -6905,11 +7394,11 @@ class ModuleRefNode(ExprNode):
 
 class DocstringRefNode(ExprNode):
     # Extracts the docstring of the body element
-    
+
     subexprs = ['body']
     type = py_object_type
     is_temp = True
-    
+
     def __init__(self, pos, body):
         ExprNode.__init__(self, pos)
         assert body.type.is_pyobject
@@ -7056,36 +7545,176 @@ static CYTHON_INLINE int __Pyx_TypeTest(PyObject *obj, PyTypeObject *type) {
 
 #------------------------------------------------------------------------------------
 
+find_py2_metaclass_utility_code = UtilityCode(
+proto = '''
+static PyObject *__Pyx_FindPy2Metaclass(PyObject *bases); /*proto*/
+''',
+impl = '''
+static PyObject *__Pyx_FindPy2Metaclass(PyObject *bases) {
+    PyObject *metaclass;
+    /* Default metaclass */
+#if PY_MAJOR_VERSION < 3
+    if (PyTuple_Check(bases) && PyTuple_GET_SIZE(bases) > 0) {
+        PyObject *base = PyTuple_GET_ITEM(bases, 0);
+        metaclass = PyObject_GetAttrString(base, "__class__");
+        if (!metaclass) {
+            PyErr_Clear();
+            metaclass = (PyObject*) Py_TYPE(base);
+        }
+    } else {
+        metaclass = (PyObject *) &PyClass_Type;
+    }
+#else
+    if (PyTuple_Check(bases) && PyTuple_GET_SIZE(bases) > 0) {
+        PyObject *base = PyTuple_GET_ITEM(bases, 0);
+        metaclass = (PyObject*) Py_TYPE(base);
+    } else {
+        metaclass = (PyObject *) &PyType_Type;
+    }
+#endif
+    Py_INCREF(metaclass);
+    return metaclass;
+}
+''')
+
 create_class_utility_code = UtilityCode(
 proto = """
-static PyObject *__Pyx_CreateClass(PyObject *bases, PyObject *dict, PyObject *name, const char *modname); /*proto*/
+static PyObject *__Pyx_CreateClass(PyObject *bases, PyObject *dict, PyObject *name,
+                                   PyObject *modname); /*proto*/
 """,
 impl = """
-static PyObject *__Pyx_CreateClass(
-    PyObject *bases, PyObject *dict, PyObject *name, const char *modname)
-{
-    PyObject *py_modname;
-    PyObject *result = 0;
+static PyObject *__Pyx_CreateClass(PyObject *bases, PyObject *dict, PyObject *name,
+                                   PyObject *modname) {
+    PyObject *result;
+    PyObject *metaclass;
 
-    #if PY_MAJOR_VERSION < 3
-    py_modname = PyString_FromString(modname);
-    #else
-    py_modname = PyUnicode_FromString(modname);
-    #endif
-    if (!py_modname)
-        goto bad;
-    if (PyDict_SetItemString(dict, "__module__", py_modname) < 0)
-        goto bad;
-    #if PY_MAJOR_VERSION < 3
-    result = PyClass_New(bases, dict, name);
+    if (PyDict_SetItemString(dict, "__module__", modname) < 0)
+        return NULL;
+
+    /* Python2 __metaclass__ */
+    metaclass = PyDict_GetItemString(dict, "__metaclass__");
+    if (metaclass) {
+        Py_INCREF(metaclass);
+    } else {
+        metaclass = __Pyx_FindPy2Metaclass(bases);
+    }
+    result = PyObject_CallFunctionObjArgs(metaclass, name, bases, dict, NULL);
+    Py_DECREF(metaclass);
+    return result;
+}
+""",
+requires = [find_py2_metaclass_utility_code])
+
+#------------------------------------------------------------------------------------
+
+create_py3class_utility_code = UtilityCode(
+proto = """
+static PyObject *__Pyx_Py3MetaclassGet(PyObject *bases, PyObject *mkw); /*proto*/
+static PyObject *__Pyx_Py3MetaclassPrepare(PyObject *metaclass, PyObject *bases, PyObject *name, PyObject *mkw, PyObject *modname, PyObject *doc); /*proto*/
+static PyObject *__Pyx_Py3ClassCreate(PyObject *metaclass, PyObject *name, PyObject *bases, PyObject *dict, PyObject *mkw); /*proto*/
+""",
+impl = """
+PyObject *__Pyx_Py3MetaclassGet(PyObject *bases, PyObject *mkw) {
+    PyObject *metaclass = PyDict_GetItemString(mkw, "metaclass");
+    if (metaclass) {
+        Py_INCREF(metaclass);
+        if (PyDict_DelItemString(mkw, "metaclass") < 0) {
+            Py_DECREF(metaclass);
+            return NULL;
+        }
+        return metaclass;
+    }
+    return __Pyx_FindPy2Metaclass(bases);
+}
+
+PyObject *__Pyx_Py3MetaclassPrepare(PyObject *metaclass, PyObject *bases, PyObject *name, PyObject *mkw,
+                                    PyObject *modname, PyObject *doc) {
+    PyObject *prep;
+    PyObject *pargs;
+    PyObject *ns;
+    PyObject *str;
+
+    prep = PyObject_GetAttrString(metaclass, "__prepare__");
+    if (!prep) {
+        if (!PyErr_ExceptionMatches(PyExc_AttributeError))
+            return NULL;
+        PyErr_Clear();
+        return PyDict_New();
+    }
+    pargs = PyTuple_New(2);
+    if (!pargs) {
+        Py_DECREF(prep);
+        return NULL;
+    }
+
+    Py_INCREF(name);
+    Py_INCREF(bases);
+    PyTuple_SET_ITEM(pargs, 0, name);
+    PyTuple_SET_ITEM(pargs, 1, bases);
+
+    ns = PyObject_Call(prep, pargs, mkw);
+
+    Py_DECREF(prep);
+    Py_DECREF(pargs);
+
+    if (ns == NULL)
+        return NULL;
+
+    /* Required here to emulate assignment order */
+    /* XXX: use consts here */
+    #if PY_MAJOR_VERSION >= 3
+    str = PyUnicode_FromString("__module__");
     #else
-    result = PyObject_CallFunctionObjArgs((PyObject *)&PyType_Type, name, bases, dict, NULL);
+    str = PyString_FromString("__module__");
     #endif
-bad:
-    Py_XDECREF(py_modname);
+    if (!str) {
+        Py_DECREF(ns);
+        return NULL;
+    }
+
+    if (PyObject_SetItem(ns, str, modname) < 0) {
+        Py_DECREF(ns);
+        Py_DECREF(str);
+        return NULL;
+    }
+    Py_DECREF(str);
+    if (doc) {
+        #if PY_MAJOR_VERSION >= 3
+        str = PyUnicode_FromString("__doc__");
+        #else
+        str = PyString_FromString("__doc__");
+        #endif
+        if (!str) {
+            Py_DECREF(ns);
+            return NULL;
+        }
+        if (PyObject_SetItem(ns, str, doc) < 0) {
+            Py_DECREF(ns);
+            Py_DECREF(str);
+            return NULL;
+        }
+        Py_DECREF(str);
+    }
+    return ns;
+}
+
+PyObject *__Pyx_Py3ClassCreate(PyObject *metaclass, PyObject *name, PyObject *bases, PyObject *dict, PyObject *mkw) {
+    PyObject *result;
+    PyObject *margs = PyTuple_New(3);
+    if (!margs)
+        return NULL;
+    Py_INCREF(name);
+    Py_INCREF(bases);
+    Py_INCREF(dict);
+    PyTuple_SET_ITEM(margs, 0, name);
+    PyTuple_SET_ITEM(margs, 1, bases);
+    PyTuple_SET_ITEM(margs, 2, dict);
+    result = PyObject_Call(metaclass, margs, mkw);
+    Py_DECREF(margs);
     return result;
 }
-""")
+""",
+requires = [find_py2_metaclass_utility_code])
 
 #------------------------------------------------------------------------------------
 
@@ -7119,6 +7748,25 @@ static void __Pyx_CppExn2PyErr() {
 impl = ""
 )
 
+pyerr_occurred_withgil_utility_code= UtilityCode(
+proto = """
+static CYTHON_INLINE int __Pyx_ErrOccurredWithGIL(void); /* proto */
+""",
+impl = """
+static CYTHON_INLINE int __Pyx_ErrOccurredWithGIL(void) {
+  int err;
+  #ifdef WITH_THREAD
+  PyGILState_STATE _save = PyGILState_Ensure();
+  #endif
+  err = !!PyErr_Occurred();
+  #ifdef WITH_THREAD
+  PyGILState_Release(_save);
+  #endif
+  return err;
+}
+"""
+)
+
 #------------------------------------------------------------------------------------
 
 raise_noneattr_error_utility_code = UtilityCode(
@@ -7155,7 +7803,6 @@ static CYTHON_INLINE void __Pyx_RaiseNoneNotIterableError(void) {
 
 getitem_dict_utility_code = UtilityCode(
 proto = """
-
 #if PY_MAJOR_VERSION >= 3
 static PyObject *__Pyx_PyDict_GetItem(PyObject *d, PyObject* key) {
     PyObject *value;
@@ -7175,7 +7822,7 @@ static PyObject *__Pyx_PyDict_GetItem(PyObject *d, PyObject* key) {
 #else
     #define __Pyx_PyDict_GetItem(d, key) PyObject_GetItem(d, key)
 #endif
-""", 
+""",
 requires = [raise_noneindex_error_utility_code])
 
 #------------------------------------------------------------------------------------
@@ -7374,7 +8021,7 @@ static CYTHON_INLINE void __Pyx_RaiseNeedMoreValuesError(Py_ssize_t index) {
 tuple_unpacking_error_code = UtilityCode(
 proto = """
 static void __Pyx_UnpackTupleError(PyObject *, Py_ssize_t index); /*proto*/
-""", 
+""",
 impl = """
 static void __Pyx_UnpackTupleError(PyObject *t, Py_ssize_t index) {
     if (t == Py_None) {
@@ -7385,7 +8032,7 @@ static void __Pyx_UnpackTupleError(PyObject *t, Py_ssize_t index) {
       __Pyx_RaiseTooManyValuesError(index);
     }
 }
-""", 
+""",
 requires = [raise_none_iter_error_utility_code,
             raise_need_more_values_to_unpack,
             raise_too_many_values_to_unpack]
@@ -7448,7 +8095,7 @@ static PyObject* __Pyx_PyEval_CallObjectWithKeywords(PyObject *callable, PyObjec
         return result; /* may be NULL */
     }
 }
-""", 
+""",
 )
 
 
@@ -7527,9 +8174,9 @@ static int __Pyx_cdivision_warning(void); /* proto */
 """,
 impl="""
 static int __Pyx_cdivision_warning(void) {
-    return PyErr_WarnExplicit(PyExc_RuntimeWarning, 
+    return PyErr_WarnExplicit(PyExc_RuntimeWarning,
                               "division with oppositely signed operands, C and Python semantics differ",
-                              %(FILENAME)s, 
+                              %(FILENAME)s,
                               %(LINENO)s,
                               __Pyx_MODULE_NAME,
                               NULL);
@@ -7555,17 +8202,17 @@ typedef struct {
     PyCFunctionObject func;
 } %(binding_cfunc)s_object;
 
-PyTypeObject %(binding_cfunc)s_type;
-PyTypeObject *%(binding_cfunc)s = NULL;
+static PyTypeObject %(binding_cfunc)s_type;
+static PyTypeObject *%(binding_cfunc)s = NULL;
 
-PyObject *%(binding_cfunc)s_NewEx(PyMethodDef *ml, PyObject *self, PyObject *module); /* proto */
+static PyObject *%(binding_cfunc)s_NewEx(PyMethodDef *ml, PyObject *self, PyObject *module); /* proto */
 #define %(binding_cfunc)s_New(ml, self) %(binding_cfunc)s_NewEx(ml, self, NULL)
 
-int %(binding_cfunc)s_init(void); /* proto */
+static int %(binding_cfunc)s_init(void); /* proto */
 """ % Naming.__dict__,
 impl="""
 
-PyObject *%(binding_cfunc)s_NewEx(PyMethodDef *ml, PyObject *self, PyObject *module) {
+static PyObject *%(binding_cfunc)s_NewEx(PyMethodDef *ml, PyObject *self, PyObject *module) {
        %(binding_cfunc)s_object *op = PyObject_GC_New(%(binding_cfunc)s_object, %(binding_cfunc)s);
     if (op == NULL)
         return NULL;
@@ -7591,7 +8238,7 @@ static PyObject *%(binding_cfunc)s_descr_get(PyObject *func, PyObject *obj, PyOb
        return PyMethod_New(func, obj, type);
 }
 
-int %(binding_cfunc)s_init(void) {
+static int %(binding_cfunc)s_init(void) {
     %(binding_cfunc)s_type = PyCFunction_Type;
     %(binding_cfunc)s_type.tp_name = __Pyx_NAMESTR("cython_binding_builtin_function_or_method");
     %(binding_cfunc)s_type.tp_dealloc = (destructor)%(binding_cfunc)s_dealloc;