cleaned up lambda cname mangeling by moving it into the Scope class
[cython.git] / Cython / Compiler / Nodes.py
index cbc4533bd639cb09d0973e1fc6f53d631736df01..977447dc3f9c2e6fcb2105a93d5cda9c720a494e 100644 (file)
@@ -3,15 +3,17 @@
 #   Pyrex - Parse tree nodes
 #
 
-import sys, os, time, copy
+import cython
+from cython import set
+cython.declare(sys=object, os=object, time=object, copy=object,
+               Builtin=object, error=object, warning=object, Naming=object, PyrexTypes=object,
+               py_object_type=object, ModuleScope=object, LocalScope=object, ClosureScope=object, \
+               StructOrUnionScope=object, PyClassScope=object, CClassScope=object,
+               CppClassScope=object, UtilityCode=object, EncodedString=object,
+               absolute_path_length=cython.Py_ssize_t)
 
-try:
-    set
-except NameError:
-    # Python 2.3
-    from sets import Set as set
+import sys, os, time, copy
 
-import Code
 import Builtin
 from Errors import error, warning, InternalError
 import Naming
@@ -21,7 +23,7 @@ from PyrexTypes import py_object_type, error_type, CFuncType
 from Symtab import ModuleScope, LocalScope, ClosureScope, \
     StructOrUnionScope, PyClassScope, CClassScope, CppClassScope
 from Cython.Utils import open_new_file, replace_suffix
-from Code import UtilityCode
+from Code import UtilityCode, ClosureTempAllocator
 from StringEncoding import EncodedString, escape_byte_string, split_string_literal
 import Options
 import ControlFlow
@@ -35,7 +37,7 @@ def relative_position(pos):
     don't want to have to regnerate and compile all the source code
     whenever the Python install directory moves (which could happen,
     e.g,. when distributing binaries.)
-    
+
     INPUT:
         a position tuple -- (absolute filename, line number column position)
 
@@ -47,7 +49,7 @@ def relative_position(pos):
     """
     global absolute_path_length
     if absolute_path_length==0:
-        absolute_path_length = len(os.path.abspath(os.getcwd())) 
+        absolute_path_length = len(os.path.abspath(os.getcwd()))
     return (pos[0].get_filenametable_entry()[absolute_path_length+1:], pos[1])
 
 def embed_position(pos, docstring):
@@ -87,8 +89,8 @@ def write_func_call(func):
             node, code = args[:2]
             marker = '                    /* %s -> %s.%s %s */' % (
                     ' ' * code.call_level,
-                    node.__class__.__name__, 
-                    func.__name__, 
+                    node.__class__.__name__,
+                    func.__name__,
                     node.pos[1:])
             pristine = code.buffer.stream.tell()
             code.putln(marker)
@@ -108,7 +110,7 @@ def write_func_call(func):
 
 class VerboseCodeWriter(type):
     # Set this as a metaclass to trace function calls in code.
-    # This slows down code generation and makes much larger files. 
+    # This slows down code generation and makes much larger files.
     def __new__(cls, name, bases, attrs):
         attrs = dict(attrs)
         for mname, m in attrs.items():
@@ -124,7 +126,7 @@ class Node(object):
 
     if DebugFlags.debug_trace_code_generation:
         __metaclass__ = VerboseCodeWriter
-    
+
     is_name = 0
     is_literal = 0
     temps = None
@@ -133,20 +135,20 @@ class Node(object):
     # containing nodes considered "children" in the tree. Each such attribute
     # can either contain a single node or a list of nodes. See Visitor.py.
     child_attrs = None
-    
+
     def __init__(self, pos, **kw):
         self.pos = pos
         self.__dict__.update(kw)
-    
+
     gil_message = "Operation"
 
     nogil_check = None
 
     def gil_error(self, env=None):
         error(self.pos, "%s not allowed without gil" % self.gil_message)
-    
+
     cpp_message = "Operation"
-    
+
     def cpp_check(self, env):
         if not env.is_cpp():
             self.cpp_error()
@@ -166,8 +168,8 @@ class Node(object):
             if isinstance(value, list):
                 setattr(result, attrname, [x for x in value])
         return result
-    
-    
+
+
     #
     #  There are 4 phases of parse tree processing, applied in order to
     #  all the statements in a given scope-block:
@@ -184,7 +186,7 @@ class Node(object):
     #  (2) analyse_expressions
     #         Determine the result types of expressions and fill in the
     #         'type' attribute of each ExprNode. Insert coercion nodes into the
-    #         tree where needed to convert to and from Python objects. 
+    #         tree where needed to convert to and from Python objects.
     #         Allocate temporary locals for intermediate results. Fill
     #         in the 'result_code' attribute of each ExprNode with a C code
     #         fragment.
@@ -194,26 +196,26 @@ class Node(object):
     #         Recursively applies the 3 processing phases to the bodies of
     #         functions.
     #
-    
+
     def analyse_control_flow(self, env):
         pass
-    
+
     def analyse_declarations(self, env):
         pass
-    
+
     def analyse_expressions(self, env):
         raise InternalError("analyse_expressions not implemented for %s" % \
             self.__class__.__name__)
-    
+
     def generate_code(self, code):
         raise InternalError("generate_code not implemented for %s" % \
             self.__class__.__name__)
-            
+
     def annotate(self, code):
         # mro does the wrong thing
         if isinstance(self, BlockNode):
             self.body.annotate(code)
-            
+
     def end_pos(self):
         try:
             return self._end_pos
@@ -243,7 +245,7 @@ class Node(object):
         if id(self) in encountered:
             return "<%s (0x%x) -- already output>" % (self.__class__.__name__, id(self))
         encountered.add(id(self))
-        
+
         def dump_child(x, level):
             if isinstance(x, Node):
                 return x.dump(level, filter_out, cutoff-1, encountered)
@@ -251,9 +253,9 @@ class Node(object):
                 return "[%s]" % ", ".join([dump_child(item, level) for item in x])
             else:
                 return repr(x)
-            
-        
-        attrs = [(key, value) for key, value in self.__dict__.iteritems() if key not in filter_out]
+
+
+        attrs = [(key, value) for key, value in self.__dict__.items() if key not in filter_out]
         if len(attrs) == 0:
             return "<%s (0x%x)>" % (self.__class__.__name__, id(self))
         else:
@@ -284,7 +286,7 @@ class CompilerDirectivesNode(Node):
         env.directives = self.directives
         self.body.analyse_declarations(env)
         env.directives = old
-    
+
     def analyse_expressions(self, env):
         old = env.directives
         env.directives = self.directives
@@ -298,19 +300,19 @@ class CompilerDirectivesNode(Node):
         self.body.generate_function_definitions(env, code)
         env.directives = env_old
         code.globalstate.directives = code_old
-            
+
     def generate_execution_code(self, code):
         old = code.globalstate.directives
         code.globalstate.directives = self.directives
         self.body.generate_execution_code(code)
         code.globalstate.directives = old
-            
+
     def annotate(self, code):
         old = code.globalstate.directives
         code.globalstate.directives = self.directives
         self.body.annotate(code)
         code.globalstate.directives = old
-        
+
 class BlockNode(object):
     #  Mixin class for nodes representing a declaration block.
 
@@ -319,18 +321,21 @@ class BlockNode(object):
         for entry in entries:
             code.globalstate.add_cached_builtin_decl(entry)
         del entries[:]
-        
+
+    def generate_lambda_definitions(self, env, code):
+        for node in env.lambda_defs:
+            node.generate_function_definitions(env, code)
 
 class StatListNode(Node):
     # stats     a list of StatNode
-    
+
     child_attrs = ["stats"]
 
     def create_analysed(pos, env, *args, **kw):
         node = StatListNode(pos, *args, **kw)
         return node # No node-specific analysis necesarry
     create_analysed = staticmethod(create_analysed)
-    
+
     def analyse_control_flow(self, env):
         for stat in self.stats:
             stat.analyse_control_flow(env)
@@ -339,27 +344,27 @@ class StatListNode(Node):
         #print "StatListNode.analyse_declarations" ###
         for stat in self.stats:
             stat.analyse_declarations(env)
-    
+
     def analyse_expressions(self, env):
         #print "StatListNode.analyse_expressions" ###
         for stat in self.stats:
             stat.analyse_expressions(env)
-    
+
     def generate_function_definitions(self, env, code):
         #print "StatListNode.generate_function_definitions" ###
         for stat in self.stats:
             stat.generate_function_definitions(env, code)
-            
+
     def generate_execution_code(self, code):
         #print "StatListNode.generate_execution_code" ###
         for stat in self.stats:
             code.mark_pos(stat.pos)
             stat.generate_execution_code(code)
-            
+
     def annotate(self, code):
         for stat in self.stats:
             stat.annotate(code)
-    
+
 
 class StatNode(Node):
     #
@@ -373,10 +378,10 @@ class StatNode(Node):
     #  (2) generate_execution_code
     #        Emit C code for executable statements.
     #
-    
+
     def generate_function_definitions(self, env, code):
         pass
-    
+
     def generate_execution_code(self, code):
         raise InternalError("generate_execution_code not implemented for %s" % \
             self.__class__.__name__)
@@ -385,9 +390,9 @@ class StatNode(Node):
 class CDefExternNode(StatNode):
     #  include_file   string or None
     #  body           StatNode
-    
+
     child_attrs = ["body"]
-    
+
     def analyse_declarations(self, env):
         if self.include_file:
             env.add_include_file(self.include_file)
@@ -395,16 +400,16 @@ class CDefExternNode(StatNode):
         env.in_cinclude = 1
         self.body.analyse_declarations(env)
         env.in_cinclude = old_cinclude_flag
-    
+
     def analyse_expressions(self, env):
         pass
-    
+
     def generate_execution_code(self, code):
         pass
 
     def annotate(self, code):
         self.body.annotate(code)
-        
+
 
 class CDeclaratorNode(Node):
     # Part of a C declaration.
@@ -413,11 +418,11 @@ class CDeclaratorNode(Node):
     #
     #   analyse
     #      Returns (name, type) pair where name is the
-    #      CNameDeclaratorNode of the name being declared 
+    #      CNameDeclaratorNode of the name being declared
     #      and type is the type it is being declared as.
     #
     #  calling_convention  string   Calling convention of CFuncDeclaratorNode
-    #                               for which this is a base 
+    #                               for which this is a base
 
     child_attrs = []
 
@@ -428,14 +433,14 @@ class CNameDeclaratorNode(CDeclaratorNode):
     #  name    string             The Pyrex name being declared
     #  cname   string or None     C name, if specified
     #  default ExprNode or None   the value assigned on declaration
-    
+
     child_attrs = ['default']
-    
+
     default = None
-    
+
     def analyse(self, base_type, env, nonempty = 0):
         if nonempty and self.name == '':
-            # May have mistaken the name for the type. 
+            # May have mistaken the name for the type.
             if base_type.is_ptr or base_type.is_array or base_type.is_buffer:
                 error(self.pos, "Missing argument name")
             elif base_type.is_void:
@@ -445,10 +450,10 @@ class CNameDeclaratorNode(CDeclaratorNode):
                 base_type = py_object_type
         self.type = base_type
         return self, base_type
-        
+
 class CPtrDeclaratorNode(CDeclaratorNode):
     # base     CDeclaratorNode
-    
+
     child_attrs = ["base"]
 
     def analyse(self, base_type, env, nonempty = 0):
@@ -475,7 +480,7 @@ class CArrayDeclaratorNode(CDeclaratorNode):
     # dimension   ExprNode
 
     child_attrs = ["base", "dimension"]
-    
+
     def analyse(self, base_type, env, nonempty = 0):
         if base_type.is_cpp_class:
             from ExprNodes import TupleNode
@@ -524,13 +529,13 @@ class CFuncDeclaratorNode(CDeclaratorNode):
     # exception_check  boolean    True if PyErr_Occurred check needed
     # nogil            boolean    Can be called without gil
     # with_gil         boolean    Acquire gil around function body
-    
+
     child_attrs = ["base", "args", "exception_value"]
 
     overridable = 0
     optional_arg_count = 0
 
-    def analyse(self, return_type, env, nonempty = 0):
+    def analyse(self, return_type, env, nonempty = 0, directive_locals = {}):
         if nonempty:
             nonempty -= 1
         func_type_args = []
@@ -538,8 +543,19 @@ class CFuncDeclaratorNode(CDeclaratorNode):
             name_declarator, type = arg_node.analyse(env, nonempty = nonempty,
                                                      is_self_arg = (i == 0 and env.is_c_class_scope))
             name = name_declarator.name
+            if name in directive_locals:
+                type_node = directive_locals[name]
+                other_type = type_node.analyse_as_type(env)
+                if other_type is None:
+                    error(type_node.pos, "Not a type")
+                elif (type is not PyrexTypes.py_object_type 
+                      and not type.same_as(other_type)):
+                    error(self.base.pos, "Signature does not agree with previous declaration")
+                    error(type_node.pos, "Previous declaration here")
+                else:
+                    type = other_type
             if name_declarator.cname:
-                error(self.pos, 
+                error(self.pos,
                     "Function argument cannot have C name specification")
             # Turn *[] argument into **
             if type.is_array:
@@ -553,7 +569,7 @@ class CFuncDeclaratorNode(CDeclaratorNode):
                 self.optional_arg_count += 1
             elif self.optional_arg_count:
                 error(self.pos, "Non-default argument follows default argument")
-        
+
         if self.optional_arg_count:
             scope = StructOrUnionScope()
             arg_count_member = '%sn' % Naming.pyrex_prefix
@@ -569,7 +585,7 @@ class CFuncDeclaratorNode(CDeclaratorNode):
                                         cname = struct_cname)
             self.op_args_struct.defined_in_pxd = 1
             self.op_args_struct.used = 1
-        
+
         exc_val = None
         exc_check = 0
         if self.exception_check == '+':
@@ -602,14 +618,11 @@ class CFuncDeclaratorNode(CDeclaratorNode):
                             error(self.exception_value.pos,
                                   "Exception value incompatible with function return type")
             exc_check = self.exception_check
-        if return_type.is_array:
-            error(self.pos,
-                "Function cannot return an array")
         if return_type.is_cfunction:
             error(self.pos,
                 "Function cannot return a function")
         func_type = PyrexTypes.CFuncType(
-            return_type, func_type_args, self.has_varargs, 
+            return_type, func_type_args, self.has_varargs,
             optional_arg_count = self.optional_arg_count,
             exception_value = exc_val, exception_check = exc_check,
             calling_convention = self.base.calling_convention,
@@ -646,6 +659,9 @@ class CArgDeclNode(Node):
     is_self_arg = 0
     is_type_arg = 0
     is_generic = 1
+    kw_only = 0
+    not_none = 0
+    or_none = 0
     type = None
     name_declarator = None
     default_value = None
@@ -668,11 +684,11 @@ class CArgDeclNode(Node):
             base_type = self.base_type.analyse(env, could_be_name = could_be_name)
             if hasattr(self.base_type, 'arg_name') and self.base_type.arg_name:
                 self.declarator.name = self.base_type.arg_name
-            # The parser is unable to resolve the ambiguity of [] as part of the 
-            # type (e.g. in buffers) or empty declarator (as with arrays). 
+            # The parser is unable to resolve the ambiguity of [] as part of the
+            # type (e.g. in buffers) or empty declarator (as with arrays).
             # This is only arises for empty multi-dimensional arrays.
-            if (base_type.is_array 
-                    and isinstance(self.base_type, TemplatedTypeNode) 
+            if (base_type.is_array
+                    and isinstance(self.base_type, TemplatedTypeNode)
                     and isinstance(self.declarator, CArrayDeclaratorNode)):
                 declarator = self.declarator
                 while isinstance(declarator.base, CArrayDeclaratorNode):
@@ -705,17 +721,17 @@ class CBaseTypeNode(Node):
     #
     #   analyse
     #     Returns the type.
-    
+
     pass
-    
+
     def analyse_as_type(self, env):
         return self.analyse(env)
-    
+
 class CAnalysedBaseTypeNode(Node):
     # type            type
-    
+
     child_attrs = []
-    
+
     def analyse(self, env, could_be_name = False):
         return self.type
 
@@ -731,7 +747,10 @@ class CSimpleBaseTypeNode(CBaseTypeNode):
 
     child_attrs = []
     arg_name = None   # in case the argument name was interpreted as a type
-    
+    module_path = []
+    is_basic_c_type = False
+    complex = False
+
     def analyse(self, env, could_be_name = False):
         # Return type descriptor.
         #print "CSimpleBaseTypeNode.analyse: is_self_arg =", self.is_self_arg ###
@@ -781,13 +800,21 @@ class CSimpleBaseTypeNode(CBaseTypeNode):
                 error(self.pos, "can only complexify c numeric types")
             type = PyrexTypes.CComplexType(type)
             type.create_declaration_utility_code(env)
+        elif type is Builtin.complex_type:
+            # Special case: optimise builtin complex type into C's
+            # double complex.  The parser cannot do this (as for the
+            # normal scalar types) as the user may have redeclared the
+            # 'complex' type.  Testing for the exact type here works.
+            type = PyrexTypes.c_double_complex_type
+            type.create_declaration_utility_code(env)
+            self.complex = True
         if type:
             return type
         else:
             return PyrexTypes.error_type
 
 class CNestedBaseTypeNode(CBaseTypeNode):
-    # For C++ classes that live inside other C++ classes. 
+    # For C++ classes that live inside other C++ classes.
 
     # name             string
     # base_type        CBaseTypeNode
@@ -823,12 +850,12 @@ class TemplatedTypeNode(CBaseTypeNode):
     dtype_node = None
 
     name = None
-    
+
     def analyse(self, env, could_be_name = False, base_type = None):
         if base_type is None:
             base_type = self.base_type_node.analyse(env)
         if base_type.is_error: return base_type
-        
+
         if base_type.is_cpp_class:
             # Templated class
             if self.keyword_args and self.keyword_args.key_value_pairs:
@@ -843,7 +870,7 @@ class TemplatedTypeNode(CBaseTypeNode):
                         return error_type
                     template_types.append(type)
                 self.type = base_type.specialize_here(self.pos, template_types)
-        
+
         elif base_type.is_pyobject:
             # Buffer
             import Buffer
@@ -858,10 +885,10 @@ class TemplatedTypeNode(CBaseTypeNode):
             if sys.version_info[0] < 3:
                 # Py 2.x enforces byte strings as keyword arguments ...
                 options = dict([ (name.encode('ASCII'), value)
-                                 for name, value in options.iteritems() ])
+                                 for name, value in options.items() ])
 
             self.type = PyrexTypes.BufferType(base_type, **options)
-        
+
         else:
             # Array
             empty_declarator = CNameDeclaratorNode(self.pos, name="", cname=None)
@@ -869,23 +896,23 @@ class TemplatedTypeNode(CBaseTypeNode):
                 error(self.pos, "invalid array declaration")
                 self.type = PyrexTypes.error_type
             else:
-                # It would be nice to merge this class with CArrayDeclaratorNode, 
+                # It would be nice to merge this class with CArrayDeclaratorNode,
                 # but arrays are part of the declaration, not the type...
                 if not self.positional_args:
                     dimension = None
                 else:
                     dimension = self.positional_args[0]
-                self.array_declarator = CArrayDeclaratorNode(self.pos, 
-                    base = empty_declarator, 
+                self.array_declarator = CArrayDeclaratorNode(self.pos,
+                    base = empty_declarator,
                     dimension = dimension)
                 self.type = self.array_declarator.analyse(base_type, env)[1]
-        
+
         return self.type
 
 class CComplexBaseTypeNode(CBaseTypeNode):
     # base_type   CBaseTypeNode
     # declarator  CDeclaratorNode
-    
+
     child_attrs = ["base_type", "declarator"]
 
     def analyse(self, env, could_be_name = False):
@@ -903,15 +930,17 @@ class CVarDefNode(StatNode):
     #  in_pxd        boolean
     #  api           boolean
 
-    #  decorators    [cython.locals(...)] or None 
+    #  decorators    [cython.locals(...)] or None
     #  directive_locals { string : NameNode } locals defined by cython.locals(...)
 
     child_attrs = ["base_type", "declarators"]
-    
+
     decorators = None
-    directive_locals = {}
-    
+    directive_locals = None
+
     def analyse_declarations(self, env, dest_scope = None):
+        if self.directive_locals is None:
+            self.directive_locals = {}
         if not dest_scope:
             dest_scope = env
         self.dest_scope = dest_scope
@@ -926,9 +955,12 @@ class CVarDefNode(StatNode):
         else:
             need_property = False
         visibility = self.visibility
-            
+
         for declarator in self.declarators:
-            name_declarator, type = declarator.analyse(base_type, env)
+            if isinstance(declarator, CFuncDeclaratorNode):
+                name_declarator, type = declarator.analyse(base_type, env, directive_locals=self.directive_locals)
+            else:
+                name_declarator, type = declarator.analyse(base_type, env)
             if not type.is_complete():
                 if not (self.visibility == 'extern' and type.is_array):
                     error(declarator.pos,
@@ -946,17 +978,17 @@ class CVarDefNode(StatNode):
                     cname = cname, visibility = self.visibility, in_pxd = self.in_pxd,
                     api = self.api)
                 if entry is not None:
-                    entry.directive_locals = self.directive_locals
+                    entry.directive_locals = copy.copy(self.directive_locals)
             else:
                 if self.directive_locals:
-                    s.error("Decorators can only be followed by functions")
+                    error(self.pos, "Decorators can only be followed by functions")
                 if self.in_pxd and self.visibility != 'extern':
-                    error(self.pos, 
+                    error(self.pos,
                         "Only 'extern' C variable declaration allowed in .pxd file")
                 entry = dest_scope.declare_var(name, type, declarator.pos,
-                            cname = cname, visibility = visibility, is_cdef = 1)
+                            cname=cname, visibility=visibility, api=self.api, is_cdef=1)
                 entry.needs_property = need_property
-    
+
 
 class CStructOrUnionDefNode(StatNode):
     #  name          string
@@ -964,11 +996,12 @@ class CStructOrUnionDefNode(StatNode):
     #  kind          "struct" or "union"
     #  typedef_flag  boolean
     #  visibility    "public" or "private"
+    #  api           boolean
     #  in_pxd        boolean
     #  attributes    [CVarDefNode] or None
     #  entry         Entry
     #  packed        boolean
-    
+
     child_attrs = ["attributes"]
 
     def analyse_declarations(self, env):
@@ -979,7 +1012,8 @@ class CStructOrUnionDefNode(StatNode):
             scope = StructOrUnionScope(self.name)
         self.entry = env.declare_struct_or_union(
             self.name, self.kind, scope, self.typedef_flag, self.pos,
-            self.cname, visibility = self.visibility, packed = self.packed)
+            self.cname, visibility = self.visibility, api = self.api,
+            packed = self.packed)
         if self.attributes is not None:
             if self.in_pxd and not env.in_cinclude:
                 self.entry.defined_in_pxd = 1
@@ -999,7 +1033,7 @@ class CStructOrUnionDefNode(StatNode):
                         if type == self.entry.type:
                             need_typedef_indirection = True
                 if need_typedef_indirection:
-                    # C can't handle typedef structs that refer to themselves. 
+                    # C can't handle typedef structs that refer to themselves.
                     struct_entry = self.entry
                     self.entry = env.declare_typedef(
                         self.name, struct_entry.type, self.pos,
@@ -1008,10 +1042,10 @@ class CStructOrUnionDefNode(StatNode):
                     # FIXME: this might be considered a hack ;-)
                     struct_entry.cname = struct_entry.type.cname = \
                                          '_' + self.entry.type.typedef_cname
-    
+
     def analyse_expressions(self, env):
         pass
-    
+
     def generate_execution_code(self, code):
         pass
 
@@ -1047,6 +1081,8 @@ class CppClassNode(CStructOrUnionDefNode):
         self.entry = env.declare_cpp_class(
             self.name, scope, self.pos,
             self.cname, base_class_types, visibility = self.visibility, templates = template_types)
+        if self.entry is None:
+            return
         self.entry.is_cpp_class = 1
         if self.attributes is not None:
             if self.in_pxd and not env.in_cinclude:
@@ -1060,15 +1096,16 @@ class CEnumDefNode(StatNode):
     #  items          [CEnumDefItemNode]
     #  typedef_flag   boolean
     #  visibility     "public" or "private"
+    #  api            boolean
     #  in_pxd         boolean
     #  entry          Entry
     
     child_attrs = ["items"]
-    
+
     def analyse_declarations(self, env):
         self.entry = env.declare_enum(self.name, self.pos,
             cname = self.cname, typedef_flag = self.typedef_flag,
-            visibility = self.visibility)
+            visibility = self.visibility, api = self.api)
         if self.items is not None:
             if self.in_pxd and not env.in_cinclude:
                 self.entry.defined_in_pxd = 1
@@ -1079,7 +1116,7 @@ class CEnumDefNode(StatNode):
         pass
 
     def generate_execution_code(self, code):
-        if self.visibility == 'public':
+        if self.visibility == 'public' or self.api:
             temp = code.funcstate.allocate_temp(PyrexTypes.py_object_type, manage_ref=True)
             for item in self.entry.enum_values:
                 code.putln("%s = PyInt_FromLong(%s); %s" % (
@@ -1088,8 +1125,8 @@ class CEnumDefNode(StatNode):
                         code.error_goto_if_null(temp, item.pos)))
                 code.put_gotref(temp)
                 code.putln('if (__Pyx_SetAttrString(%s, "%s", %s) < 0) %s' % (
-                        Naming.module_cname, 
-                        item.name, 
+                        Naming.module_cname,
+                        item.name,
                         temp,
                         code.error_goto(item.pos)))
                 code.put_decref_clear(temp, PyrexTypes.py_object_type)
@@ -1100,7 +1137,7 @@ class CEnumDefItemNode(StatNode):
     #  name     string
     #  cname    string or None
     #  value    ExprNode or None
-    
+
     child_attrs = ["value"]
 
     def analyse_declarations(self, env, enum_entry):
@@ -1111,7 +1148,7 @@ class CEnumDefItemNode(StatNode):
                 self.value.analyse_const_expression(env)
         entry = env.declare_const(self.name, enum_entry.type, 
             self.value, self.pos, cname = self.cname,
-            visibility = enum_entry.visibility)
+            visibility = enum_entry.visibility, api = enum_entry.api)
         enum_entry.enum_values.append(entry)
 
 
@@ -1119,17 +1156,18 @@ class CTypeDefNode(StatNode):
     #  base_type    CBaseTypeNode
     #  declarator   CDeclaratorNode
     #  visibility   "public" or "private"
+    #  api          boolean
     #  in_pxd       boolean
 
     child_attrs = ["base_type", "declarator"]
-    
+
     def analyse_declarations(self, env):
         base = self.base_type.analyse(env)
         name_declarator, type = self.declarator.analyse(base, env)
         name = name_declarator.name
         cname = name_declarator.cname
         entry = env.declare_typedef(name, type, self.pos,
-            cname = cname, visibility = self.visibility)
+            cname = cname, visibility = self.visibility, api = self.api)
         if self.in_pxd and not env.in_cinclude:
             entry.defined_in_pxd = 1
     
@@ -1148,13 +1186,15 @@ class FuncDefNode(StatNode, BlockNode):
     #  needs_closure   boolean        Whether or not this function has inner functions/classes/yield
     #  needs_outer_scope boolean      Whether or not this function requires outer scope
     #  directive_locals { string : NameNode } locals defined by cython.locals(...)
-    
+
     py_func = None
     assmt = None
     needs_closure = False
     needs_outer_scope = False
+    is_generator = False
+    is_generator_body = False
     modifiers = []
-    
+
     def analyse_default_values(self, env):
         genv = env.global_scope()
         default_seen = 0
@@ -1173,9 +1213,25 @@ class FuncDefNode(StatNode, BlockNode):
             elif default_seen:
                 error(arg.pos, "Non-default argument following default argument")
 
+    def align_argument_type(self, env, arg):
+        directive_locals = self.directive_locals
+        type = arg.type
+        if arg.name in directive_locals:
+            type_node = directive_locals[arg.name]
+            other_type = type_node.analyse_as_type(env)
+            if other_type is None:
+                error(type_node.pos, "Not a type")
+            elif (type is not PyrexTypes.py_object_type 
+                    and not type.same_as(other_type)):
+                error(arg.base_type.pos, "Signature does not agree with previous declaration")
+                error(type_node.pos, "Previous declaration here")
+            else:
+                arg.type = other_type
+        return arg
+
     def need_gil_acquisition(self, lenv):
         return 0
-        
+
     def create_local_scope(self, env):
         genv = env
         while genv.is_py_class_scope or genv.is_c_class_scope:
@@ -1195,7 +1251,10 @@ class FuncDefNode(StatNode, BlockNode):
         self.local_scope = lenv
         lenv.directives = env.directives
         return lenv
-                
+
+    def generate_function_body(self, env, code):
+        self.body.generate_execution_code(code)
+
     def generate_function_definitions(self, env, code):
         import Buffer
 
@@ -1209,8 +1268,7 @@ class FuncDefNode(StatNode, BlockNode):
         # Generate closure function definitions
         self.body.generate_function_definitions(lenv, code)
         # generate lambda function definitions
-        for node in lenv.lambda_defs:
-            node.generate_function_definitions(lenv, code)
+        self.generate_lambda_definitions(lenv, code)
 
         is_getbuffer_slot = (self.entry.name == "__getbuffer__" and
                              self.entry.scope.is_c_class_scope)
@@ -1229,17 +1287,18 @@ class FuncDefNode(StatNode, BlockNode):
                 if (self.entry.name == '__long__' and
                     not self.entry.scope.lookup_here('__int__')):
                     preprocessor_guard = None
-        
+
         profile = code.globalstate.directives['profile']
+        if profile and lenv.nogil:
+            warning(self.pos, "Cannot profile nogil function.", 1)
+            profile = False
         if profile:
-            if lenv.nogil:
-                error(self.pos, "Cannot profile nogil function.")
             code.globalstate.use_utility_code(profile_utility_code)
 
         # Generate C code for header and body of function
         code.enter_cfunc_scope()
         code.return_from_error_cleanup_label = code.new_label()
-            
+
         # ----- Top-level constants used by this function
         code.mark_pos(self.pos)
         self.generate_cached_builtins_decls(lenv, code)
@@ -1251,7 +1310,7 @@ class FuncDefNode(StatNode, BlockNode):
 
         with_pymethdef = self.needs_assignment_synthesis(env, code)
         if self.py_func:
-            self.py_func.generate_function_header(code, 
+            self.py_func.generate_function_header(code,
                 with_pymethdef = with_pymethdef,
                 proto_only=True)
         self.generate_function_header(code,
@@ -1279,10 +1338,12 @@ class FuncDefNode(StatNode, BlockNode):
             if self.return_type.is_pyobject:
                 init = " = NULL"
             code.putln(
-                "%s%s;" % 
+                "%s%s;" %
                     (self.return_type.declaration_code(Naming.retval_cname),
                      init))
         tempvardecl_code = code.insertion_point()
+        if not lenv.nogil:
+            code.put_declare_refcount_context()
         self.generate_keyword_list(code)
         if profile:
             code.put_trace_declarations()
@@ -1306,7 +1367,7 @@ class FuncDefNode(StatNode, BlockNode):
             code.putln("%s = (%s)%s->tp_new(%s, %s, NULL);" % (
                 Naming.cur_scope_cname,
                 lenv.scope_class.type.declaration_code(''),
-                lenv.scope_class.type.typeptr_cname, 
+                lenv.scope_class.type.typeptr_cname,
                 lenv.scope_class.type.typeptr_cname,
                 Naming.empty_tuple))
             code.putln("if (unlikely(!%s)) {" % Naming.cur_scope_cname)
@@ -1337,13 +1398,13 @@ class FuncDefNode(StatNode, BlockNode):
             code.put_trace_call(self.entry.name, self.pos)
         # ----- Fetch arguments
         self.generate_argument_parsing_code(env, code)
-        # If an argument is assigned to in the body, we must 
+        # If an argument is assigned to in the body, we must
         # incref it to properly keep track of refcounts.
         for entry in lenv.arg_entries:
             if entry.type.is_pyobject:
-                if entry.assignments and not entry.in_closure:
+                if (acquire_gil or entry.assignments) and not entry.in_closure:
                     code.put_var_incref(entry)
-        # ----- Initialise local variables 
+        # ----- Initialise local variables
         for entry in lenv.var_entries:
             if entry.type.is_pyobject and entry.init_to_none and entry.used:
                 code.put_init_var_to_py_none(entry)
@@ -1362,7 +1423,7 @@ class FuncDefNode(StatNode, BlockNode):
         # -------------------------
         # ----- Function body -----
         # -------------------------
-        self.body.generate_execution_code(code)
+        self.generate_function_body(env, code)
 
         # ----- Default return value
         code.putln("")
@@ -1390,7 +1451,7 @@ class FuncDefNode(StatNode, BlockNode):
                 code.globalstate.use_utility_code(restore_exception_utility_code)
                 code.putln("{ PyObject *__pyx_type, *__pyx_value, *__pyx_tb;")
                 code.putln("__Pyx_ErrFetch(&__pyx_type, &__pyx_value, &__pyx_tb);")
-                for entry in lenv.buffer_entries:                    
+                for entry in lenv.buffer_entries:
                     Buffer.put_release_buffer_code(code, entry)
                     #code.putln("%s = 0;" % entry.cname)
                 code.putln("__Pyx_ErrRestore(__pyx_type, __pyx_value, __pyx_tb);}")
@@ -1398,7 +1459,7 @@ class FuncDefNode(StatNode, BlockNode):
             err_val = self.error_value()
             exc_check = self.caller_will_check_exceptions()
             if err_val is not None or exc_check:
-                # TODO: Fix exception tracing (though currently unused by cProfile). 
+                # TODO: Fix exception tracing (though currently unused by cProfile).
                 # code.globalstate.use_utility_code(get_exception_tuple_utility_code)
                 # code.put_trace_exception()
                 code.putln('__Pyx_AddTraceback("%s");' % self.entry.qualified_name)
@@ -1406,7 +1467,7 @@ class FuncDefNode(StatNode, BlockNode):
                 warning(self.entry.pos, "Unraisable exception in function '%s'." \
                             % self.entry.qualified_name, 0)
                 code.putln(
-                    '__Pyx_WriteUnraisable("%s");' % 
+                    '__Pyx_WriteUnraisable("%s");' %
                         self.entry.qualified_name)
                 env.use_utility_code(unraisable_exception_utility_code)
                 env.use_utility_code(restore_exception_utility_code)
@@ -1439,23 +1500,19 @@ class FuncDefNode(StatNode, BlockNode):
             for entry in lenv.var_entries:
                 if lenv.control_flow.get_state((entry.name, 'initialized')) is not True:
                     entry.xdecref_cleanup = 1
-        
+
         for entry in lenv.var_entries:
             if entry.type.is_pyobject:
                 if entry.used and not entry.in_closure:
                     code.put_var_decref(entry)
-                elif entry.in_closure and self.needs_closure:
-                    code.put_giveref(entry.cname)
         # Decref any increfed args
         for entry in lenv.arg_entries:
             if entry.type.is_pyobject:
-                if entry.in_closure:
-                    code.put_var_giveref(entry)
-                elif entry.assignments:
+                if (acquire_gil or entry.assignments) and not entry.in_closure:
                     code.put_var_decref(entry)
         if self.needs_closure:
             code.put_decref(Naming.cur_scope_cname, lenv.scope_class.type)
-                
+
         # ----- Return
         # This code is duplicated in ModuleNode.generate_module_init_func
         if not lenv.nogil:
@@ -1468,7 +1525,7 @@ class FuncDefNode(StatNode, BlockNode):
 
         if self.entry.is_special and self.entry.name == "__hash__":
             # Returning -1 for __hash__ is supposed to signal an error
-            # We do as Python instances and coerce -1 into -2. 
+            # We do as Python instances and coerce -1 into -2.
             code.putln("if (unlikely(%s == -1) && !PyErr_Occurred()) %s = -2;" % (
                     Naming.retval_cname, Naming.retval_cname))
 
@@ -1479,7 +1536,7 @@ class FuncDefNode(StatNode, BlockNode):
                 code.put_trace_return("Py_None")
         if not lenv.nogil:
             code.put_finish_refcount_context()
-        
+
         if acquire_gil:
             code.putln("#ifdef WITH_THREAD")
             code.putln("PyGILState_Release(_save);")
@@ -1487,7 +1544,7 @@ class FuncDefNode(StatNode, BlockNode):
 
         if not self.return_type.is_void:
             code.putln("return %s;" % Naming.retval_cname)
-            
+
         code.putln("}")
 
         if preprocessor_guard:
@@ -1508,7 +1565,7 @@ class FuncDefNode(StatNode, BlockNode):
             error(arg.pos,
                 "Argument type '%s' is incomplete" % arg.type)
         return env.declare_arg(arg.name, arg.type, arg.pos)
-    
+
     def generate_arg_type_test(self, arg, code):
         # Generate type test for one argument.
         if arg.type.typeobj_is_available():
@@ -1517,7 +1574,7 @@ class FuncDefNode(StatNode, BlockNode):
             arg_code = "((PyObject *)%s)" % arg.entry.cname
             code.putln(
                 'if (unlikely(!__Pyx_ArgTypeTest(%s, %s, %d, "%s", %s))) %s' % (
-                    arg_code, 
+                    arg_code,
                     typeptr_cname,
                     arg.accept_none,
                     arg.name,
@@ -1529,13 +1586,12 @@ class FuncDefNode(StatNode, BlockNode):
 
     def generate_arg_none_check(self, arg, code):
         # Generate None check for one argument.
-        code.globalstate.use_utility_code(arg_type_test_utility_code)
         code.putln('if (unlikely(((PyObject *)%s) == Py_None)) {' % arg.entry.cname)
         code.putln('''PyErr_Format(PyExc_TypeError, "Argument '%s' must not be None"); %s''' % (
             arg.name,
             code.error_goto(arg.pos)))
         code.putln('}')
-        
+
     def generate_wrapper_functions(self, code):
         pass
 
@@ -1567,20 +1623,24 @@ class FuncDefNode(StatNode, BlockNode):
         info = self.local_scope.arg_entries[1].cname
         # Python 3.0 betas have a bug in memoryview which makes it call
         # getbuffer with a NULL parameter. For now we work around this;
-        # the following line should be removed when this bug is fixed.
-        code.putln("if (%s == NULL) return 0;" % info) 
+        # the following block should be removed when this bug is fixed.
+        code.putln("if (%s != NULL) {" % info)
         code.putln("%s->obj = Py_None; __Pyx_INCREF(Py_None);" % info)
         code.put_giveref("%s->obj" % info) # Do not refnanny object within structs
+        code.putln("}")
 
     def getbuffer_error_cleanup(self, code):
         info = self.local_scope.arg_entries[1].cname
+        code.putln("if (%s != NULL && %s->obj != NULL) {"
+                   % (info, info))
         code.put_gotref("%s->obj" % info)
-        code.putln("__Pyx_DECREF(%s->obj); %s->obj = NULL;" %
-                   (info, info))
+        code.putln("__Pyx_DECREF(%s->obj); %s->obj = NULL;"
+                   % (info, info))
+        code.putln("}")
 
     def getbuffer_normal_cleanup(self, code):
         info = self.local_scope.arg_entries[1].cname
-        code.putln("if (%s->obj == Py_None) {" % info)
+        code.putln("if (%s != NULL && %s->obj == Py_None) {" % (info, info))
         code.put_gotref("Py_None")
         code.putln("__Pyx_DECREF(Py_None); %s->obj = NULL;" % info)
         code.putln("}")
@@ -1601,23 +1661,30 @@ class CFuncDefNode(FuncDefNode):
     #  py_func       wrapper for calling from Python
     #  overridable   whether or not this is a cpdef function
     #  inline_in_pxd whether this is an inline function in a pxd file
-    
+
     child_attrs = ["base_type", "declarator", "body", "py_func"]
 
     inline_in_pxd = False
     decorators = None
-    directive_locals = {}
+    directive_locals = None
 
     def unqualified_name(self):
         return self.entry.name
-        
+
     def analyse_declarations(self, env):
+        if self.directive_locals is None:
+            self.directive_locals = {}
         self.directive_locals.update(env.directives['locals'])
         base_type = self.base_type.analyse(env)
         # The 2 here is because we need both function and argument names.
-        name_declarator, type = self.declarator.analyse(base_type, env, nonempty = 2 * (self.body is not None))
+        if isinstance(self.declarator, CFuncDeclaratorNode):
+            name_declarator, type = self.declarator.analyse(base_type, env,
+                                                            nonempty = 2 * (self.body is not None),
+                                                            directive_locals = self.directive_locals)
+        else:
+            name_declarator, type = self.declarator.analyse(base_type, env, nonempty = 2 * (self.body is not None))
         if not type.is_cfunction:
-            error(self.pos, 
+            error(self.pos,
                 "Suite attached to non-function declaration")
         # Remember the actual type according to the function header
         # written here, because the type in the symbol table entry
@@ -1630,28 +1697,34 @@ class CFuncDefNode(FuncDefNode):
             declarator = declarator.base
         self.args = declarator.args
         for formal_arg, type_arg in zip(self.args, type.args):
+            self.align_argument_type(env, type_arg)
             formal_arg.type = type_arg.type
             formal_arg.name = type_arg.name
             formal_arg.cname = type_arg.cname
+            if type_arg.type.is_buffer and 'inline' in self.modifiers:
+                warning(formal_arg.pos, "Buffer unpacking not optimized away.", 1)
         name = name_declarator.name
         cname = name_declarator.cname
         self.entry = env.declare_cfunction(
-            name, type, self.pos, 
+            name, type, self.pos,
             cname = cname, visibility = self.visibility,
             defining = self.body is not None,
             api = self.api, modifiers = self.modifiers)
         self.entry.inline_func_in_pxd = self.inline_in_pxd
         self.return_type = type.return_type
-        
+        if self.return_type.is_array and visibility != 'extern':
+            error(self.pos,
+                "Function cannot return an array")
+
         if self.overridable and not env.is_module_scope:
             if len(self.args) < 1 or not self.args[0].type.is_pyobject:
                 # An error will be produced in the cdef function
                 self.overridable = False
-            
+
         if self.overridable:
             import ExprNodes
             py_func_body = self.call_self_node(is_module_scope = env.is_module_scope)
-            self.py_func = DefNode(pos = self.pos, 
+            self.py_func = DefNode(pos = self.pos,
                                    name = self.entry.name,
                                    args = self.args,
                                    star_arg = None,
@@ -1668,7 +1741,7 @@ class CFuncDefNode(FuncDefNode):
                 self.override = OverrideCheckNode(self.pos, py_func = self.py_func)
                 self.body = StatListNode(self.pos, stats=[self.override, self.body])
         self.create_local_scope(env)
-    
+
     def call_self_node(self, omit_optional_args=0, is_module_scope=0):
         import ExprNodes
         args = self.type.args
@@ -1683,7 +1756,7 @@ class CFuncDefNode(FuncDefNode):
         skip_dispatch = not is_module_scope or Options.lookup_module_cpdef
         c_call = ExprNodes.SimpleCallNode(self.pos, function=cfunc, args=[ExprNodes.NameNode(self.pos, name=n) for n in arg_names[1-is_module_scope:]], wrapper_call=skip_dispatch)
         return ReturnStatNode(pos=self.pos, return_type=PyrexTypes.py_object_type, value=c_call)
-    
+
     def declare_arguments(self, env):
         for arg in self.type.args:
             if not arg.name:
@@ -1719,7 +1792,6 @@ class CFuncDefNode(FuncDefNode):
     def generate_function_header(self, code, with_pymethdef, with_opt_args = 1, with_dispatch = 1, cname = None):
         arg_decls = []
         type = self.type
-        visibility = self.entry.visibility
         for arg in type.args[:len(type.args)-type.optional_arg_count]:
             arg_decls.append(arg.declaration_code())
         if with_dispatch and self.overridable:
@@ -1733,24 +1805,20 @@ class CFuncDefNode(FuncDefNode):
         if cname is None:
             cname = self.entry.func_cname
         entity = type.function_header_code(cname, ', '.join(arg_decls))
-        if visibility == 'public':
-            dll_linkage = "DL_EXPORT"
+        if self.entry.visibility == 'private':
+            storage_class = "static "
         else:
-            dll_linkage = None
-        header = self.return_type.declaration_code(entity,
-            dll_linkage = dll_linkage)
-        if visibility == 'extern':
-            storage_class = "%s " % Naming.extern_c_macro
-        elif visibility == 'public':
             storage_class = ""
-        else:
-            storage_class = "static "
+        dll_linkage = None
+        modifiers = ""
         if 'inline' in self.modifiers:
             self.modifiers[self.modifiers.index('inline')] = 'cython_inline'
-        code.putln("%s%s %s {" % (
-            storage_class,
-            ' '.join(self.modifiers).upper(), # macro forms 
-            header))
+        if self.modifiers:
+            modifiers = "%s " % ' '.join(self.modifiers).upper()
+        
+        header = self.return_type.declaration_code(entity, dll_linkage=dll_linkage)
+        #print (storage_class, modifiers, header)
+        code.putln("%s%s%s {" % (storage_class, modifiers, header))
 
     def generate_argument_declarations(self, env, code):
         for arg in self.args:
@@ -1761,7 +1829,7 @@ class CFuncDefNode(FuncDefNode):
 
     def generate_keyword_list(self, code):
         pass
-        
+
     def generate_argument_parsing_code(self, env, code):
         i = 0
         if self.type.optional_arg_count:
@@ -1777,10 +1845,10 @@ class CFuncDefNode(FuncDefNode):
             for _ in range(self.type.optional_arg_count):
                 code.putln('}')
             code.putln('}')
-    
+
     def generate_argument_conversion_code(self, code):
         pass
-    
+
     def generate_argument_type_tests(self, code):
         # Generate type tests for args whose type in a parent
         # class is a supertype of the declared type.
@@ -1796,13 +1864,13 @@ class CFuncDefNode(FuncDefNode):
         else:
             #return None
             return self.entry.type.exception_value
-            
+
     def caller_will_check_exceptions(self):
         return self.entry.type.exception_check
-        
+
     def generate_wrapper_functions(self, code):
         # If the C signature of a function has changed, we need to generate
-        # wrappers to put in the slots here. 
+        # wrappers to put in the slots here.
         k = 0
         entry = self.entry
         func_type = entry.type
@@ -1811,10 +1879,10 @@ class CFuncDefNode(FuncDefNode):
             entry = entry.prev_entry
             entry.func_cname = "%s%swrap_%s" % (self.entry.func_cname, Naming.pyrex_prefix, k)
             code.putln()
-            self.generate_function_header(code, 
+            self.generate_function_header(code,
                                           0,
-                                          with_dispatch = entry.type.is_overridable, 
-                                          with_opt_args = entry.type.optional_arg_count, 
+                                          with_dispatch = entry.type.is_overridable,
+                                          with_opt_args = entry.type.optional_arg_count,
                                           cname = entry.func_cname)
             if not self.return_type.is_void:
                 code.put('return ')
@@ -1830,7 +1898,7 @@ class CFuncDefNode(FuncDefNode):
                 arglist.append('NULL')
             code.putln('%s(%s);' % (self.entry.func_cname, ', '.join(arglist)))
             code.putln('}')
-        
+
 
 class PyArgDeclNode(Node):
     # Argument which must be a Python object (used
@@ -1869,7 +1937,7 @@ class DefNode(FuncDefNode):
     #  when the def statement is inside a Python class definition.
     #
     #  assmt   AssignmentNode   Function construction/assignment
-    
+
     child_attrs = ["args", "star_arg", "starstar_arg", "body", "decorators"]
 
     lambda_name = None
@@ -1878,11 +1946,15 @@ class DefNode(FuncDefNode):
     num_required_kw_args = 0
     reqd_kw_flags_cname = "0"
     is_wrapper = 0
+    no_assignment_synthesis = 0
     decorators = None
     return_type_annotation = None
     entry = None
     acquire_gil = 0
     self_in_stararg = 0
+    star_arg = None
+    starstar_arg = None
+    doc = None
 
     def __init__(self, pos, **kwds):
         FuncDefNode.__init__(self, pos, **kwds)
@@ -1897,7 +1969,7 @@ class DefNode(FuncDefNode):
         self.num_kwonly_args = k
         self.num_required_kw_args = rk
         self.num_required_args = r
-        
+
     def as_cfunction(self, cfunc=None, scope=None):
         if self.star_arg:
             error(self.star_arg.pos, "cdef function cannot have star argument")
@@ -1938,7 +2010,7 @@ class DefNode(FuncDefNode):
             exception_value = None
         else:
             exception_value = ExprNodes.ConstNode(self.pos, value=cfunc_type.exception_value, type=cfunc_type.return_type)
-        declarator = CFuncDeclaratorNode(self.pos, 
+        declarator = CFuncDeclaratorNode(self.pos,
                                          base = CNameDeclaratorNode(self.pos, name=self.name, cname=None),
                                          args = self.args,
                                          has_varargs = False,
@@ -1946,7 +2018,7 @@ class DefNode(FuncDefNode):
                                          exception_value = exception_value,
                                          with_gil = cfunc_type.with_gil,
                                          nogil = cfunc_type.nogil)
-        return CFuncDefNode(self.pos, 
+        return CFuncDefNode(self.pos,
                             modifiers = [],
                             base_type = CAnalysedBaseTypeNode(self.pos, type=cfunc_type.return_type),
                             declarator = declarator,
@@ -1959,7 +2031,18 @@ class DefNode(FuncDefNode):
                             visibility = 'private',
                             api = False,
                             directive_locals = getattr(cfunc, 'directive_locals', {}))
-    
+
+    def is_cdef_func_compatible(self):
+        """Determines if the function's signature is compatible with a
+        cdef function.  This can be used before calling
+        .as_cfunction() to see if that will be successful.
+        """
+        if self.needs_closure:
+            return False
+        if self.star_arg or self.starstar_arg:
+            return False
+        return True
+
     def analyse_declarations(self, env):
         self.is_classmethod = self.is_staticmethod = False
         if self.decorators:
@@ -1976,7 +2059,7 @@ class DefNode(FuncDefNode):
             # staticmethod() was overridden - not much we can do here ...
             self.is_staticmethod = False
 
-        if self.name == '__new__':
+        if self.name == '__new__' and env.is_py_class_scope:
             self.is_staticmethod = 1
 
         self.analyse_argument_types(env)
@@ -1993,28 +2076,18 @@ class DefNode(FuncDefNode):
         allow_none_for_extension_args = env.directives['allow_none_for_extension_args']
         for arg in self.args:
             if hasattr(arg, 'name'):
-                type = arg.type
                 name_declarator = None
             else:
                 base_type = arg.base_type.analyse(env)
                 name_declarator, type = \
                     arg.declarator.analyse(base_type, env)
                 arg.name = name_declarator.name
-            if arg.name in directive_locals:
-                type_node = directive_locals[arg.name]
-                other_type = type_node.analyse_as_type(env)
-                if other_type is None:
-                    error(type_node.pos, "Not a type")
-                elif (type is not PyrexTypes.py_object_type 
-                        and not type.same_as(other_type)):
-                    error(arg.base_type.pos, "Signature does not agree with previous declaration")
-                    error(type_node.pos, "Previous declaration here")
-                else:
-                    type = other_type
+                arg.type = type
+            self.align_argument_type(env, arg)
             if name_declarator and name_declarator.cname:
                 error(self.pos,
                     "Python function argument cannot have C name specification")
-            arg.type = type.as_argument_type()
+            arg.type = arg.type.as_argument_type()
             arg.hdr_type = None
             arg.needs_conversion = 0
             arg.needs_type_test = 0
@@ -2043,6 +2116,8 @@ class DefNode(FuncDefNode):
 
     def analyse_signature(self, env):
         if self.entry.is_special:
+            if self.decorators:
+                error(self.pos, "special functions of cdef classes cannot have decorators")
             self.entry.trivial_signature = len(self.args) == 1 and not (self.star_arg or self.starstar_arg)
         elif not env.directives['always_allow_keywords'] and not (self.star_arg or self.starstar_arg):
             # Use the simpler calling signature for zero- and one-argument functions.
@@ -2129,16 +2204,17 @@ class DefNode(FuncDefNode):
 
     def signature_has_generic_args(self):
         return self.entry.signature.has_generic_args
-    
+
     def declare_pyfunction(self, env):
         #print "DefNode.declare_pyfunction:", self.name, "in", env ###
         name = self.name
         entry = env.lookup_here(name)
         if entry and entry.type.is_cfunction and not self.is_wrapper:
             warning(self.pos, "Overriding cdef method with def method.", 5)
-        entry = env.declare_pyfunction(name, self.pos)
+        entry = env.declare_pyfunction(name, self.pos, allow_redefine=not self.is_wrapper)
         self.entry = entry
-        prefix = env.scope_prefix
+        prefix = env.next_id(env.scope_prefix)
+
         entry.func_cname = \
             Naming.pyfunc_prefix + prefix + name
         entry.pymethdef_cname = \
@@ -2156,14 +2232,7 @@ class DefNode(FuncDefNode):
             entry.doc = None
 
     def declare_lambda_function(self, env):
-        name = self.name
-        prefix = env.scope_prefix
-        func_cname = \
-            Naming.lambda_func_prefix + u'funcdef' + prefix + self.lambda_name
-        entry = env.declare_lambda_function(func_cname, self.pos)
-        entry.pymethdef_cname = \
-            Naming.lambda_func_prefix + u'methdef' + prefix + self.lambda_name
-        entry.qualified_name = env.qualify_name(self.lambda_name)
+        entry = env.declare_lambda_function(self.lambda_name, self.pos)
         entry.doc = None
         self.entry = entry
 
@@ -2203,7 +2272,7 @@ class DefNode(FuncDefNode):
             entry.xdecref_cleanup = 1
             arg.entry = entry
             env.control_flow.set_state((), (arg.name, 'initialized'), True)
-            
+
     def analyse_expressions(self, env):
         self.local_scope.directives = env.directives
         self.analyse_default_values(env)
@@ -2212,7 +2281,11 @@ class DefNode(FuncDefNode):
             self.synthesize_assignment_node(env)
 
     def needs_assignment_synthesis(self, env, code=None):
+        if self.no_assignment_synthesis:
+            return False
         # Should enable for module level as well, that will require more testing...
+        if self.entry.is_anonymous:
+            return True
         if env.is_module_scope:
             if code is None:
                 return env.directives['binding']
@@ -2242,7 +2315,7 @@ class DefNode(FuncDefNode):
             rhs = rhs)
         self.assmt.analyse_declarations(env)
         self.assmt.analyse_expressions(env)
-            
+
     def generate_function_header(self, code, with_pymethdef, proto_only=0):
         arg_code_list = []
         sig = self.entry.signature
@@ -2258,6 +2331,8 @@ class DefNode(FuncDefNode):
                         arg.hdr_type.declaration_code(arg.hdr_cname))
         if not self.entry.is_special and sig.method_flags() == [TypeSlots.method_noargs]:
             arg_code_list.append("CYTHON_UNUSED PyObject *unused")
+        if (self.entry.scope.is_c_class_scope and self.entry.name == "__ipow__"):
+            arg_code_list.append("CYTHON_UNUSED PyObject *unused")
         if sig.has_generic_args:
             arg_code_list.append(
                 "PyObject *%s, PyObject *%s"
@@ -2285,7 +2360,7 @@ class DefNode(FuncDefNode):
                     "struct wrapperbase %s;" % self.entry.wrapperbase_cname)
         if with_pymethdef:
             code.put(
-                "static PyMethodDef %s = " % 
+                "static PyMethodDef %s = " %
                     self.entry.pymethdef_cname)
             code.put_pymethoddef(self.entry, ";", allow_skip=False)
         code.putln("%s {" % header)
@@ -2311,8 +2386,8 @@ class DefNode(FuncDefNode):
             code.putln("0};")
 
     def generate_argument_parsing_code(self, env, code):
-        # Generate PyArg_ParseTuple call for generic
-        # arguments, if any.
+        # Generate fast equivalent of PyArg_ParseTuple call for
+        # generic arguments, if any, including args/kwargs
         if self.entry.signature.has_dummy_arg and not self.self_in_stararg:
             # get rid of unused argument warning
             code.putln("%s = %s;" % (Naming.self_cname, Naming.self_cname))
@@ -2368,9 +2443,9 @@ class DefNode(FuncDefNode):
                 self.generate_arg_decref(self.star_arg, code)
                 if self.starstar_arg:
                     if self.starstar_arg.entry.xdecref_cleanup:
-                        code.put_var_xdecref(self.starstar_arg.entry)
+                        code.put_var_xdecref_clear(self.starstar_arg.entry)
                     else:
-                        code.put_var_decref(self.starstar_arg.entry)
+                        code.put_var_decref_clear(self.starstar_arg.entry)
             code.putln('__Pyx_AddTraceback("%s");' % self.entry.qualified_name)
             # The arguments are put into the closure one after the
             # other, so when type errors are found, all references in
@@ -2389,14 +2464,24 @@ class DefNode(FuncDefNode):
         if code.label_used(end_label):
             code.put_label(end_label)
 
+        # fix refnanny view on closure variables here, instead of
+        # doing it separately for each arg parsing special case
+        if self.star_arg and self.star_arg.entry.in_closure:
+            code.put_var_giveref(self.star_arg.entry)
+        if self.starstar_arg and self.starstar_arg.entry.in_closure:
+            code.put_var_giveref(self.starstar_arg.entry)
+        for arg in self.args:
+            if arg.type.is_pyobject and arg.entry.in_closure:
+                code.put_var_giveref(arg.entry)
+
     def generate_arg_assignment(self, arg, item, code):
         if arg.type.is_pyobject:
             if arg.is_generic:
                 item = PyrexTypes.typecast(arg.type, PyrexTypes.py_object_type, item)
             entry = arg.entry
-            code.putln("%s = %s;" % (entry.cname, item))
             if entry.in_closure:
-                code.put_var_incref(entry)
+                code.put_incref(item, PyrexTypes.py_object_type)
+            code.putln("%s = %s;" % (entry.cname, item))
         else:
             func = arg.type.from_py_function
             if func:
@@ -2407,14 +2492,14 @@ class DefNode(FuncDefNode):
                     code.error_goto_if(arg.type.error_condition(arg.entry.cname), arg.pos)))
             else:
                 error(arg.pos, "Cannot convert Python object argument to type '%s'" % arg.type)
-    
+
     def generate_arg_xdecref(self, arg, code):
         if arg:
-            code.put_var_xdecref(arg.entry)
-    
+            code.put_var_xdecref_clear(arg.entry)
+
     def generate_arg_decref(self, arg, code):
         if arg:
-            code.put_var_decref(arg.entry)
+            code.put_var_decref_clear(arg.entry)
 
     def generate_stararg_copy_code(self, code):
         if not self.star_arg:
@@ -2425,8 +2510,6 @@ class DefNode(FuncDefNode):
                     self.name, Naming.args_cname, self.error_value()))
             code.putln("}")
 
-        code.globalstate.use_utility_code(keyword_string_check_utility_code)
-
         if self.starstar_arg:
             if self.star_arg:
                 kwarg_check = "unlikely(%s)" % Naming.kwds_cname
@@ -2435,6 +2518,7 @@ class DefNode(FuncDefNode):
         else:
             kwarg_check = "unlikely(%s) && unlikely(PyDict_Size(%s) > 0)" % (
                 Naming.kwds_cname, Naming.kwds_cname)
+        code.globalstate.use_utility_code(keyword_string_check_utility_code)
         code.putln(
             "if (%s && unlikely(!__Pyx_CheckKeywordStrings(%s, \"%s\", %d))) return %s;" % (
                 kwarg_check, Naming.kwds_cname, self.name,
@@ -2498,8 +2582,6 @@ class DefNode(FuncDefNode):
         has_fixed_positional_count = not self.star_arg and \
             min_positional_args == max_positional_args
 
-        code.globalstate.use_utility_code(raise_double_keywords_utility_code)
-        code.globalstate.use_utility_code(raise_argtuple_invalid_utility_code)
         if self.num_required_kw_args:
             code.globalstate.use_utility_code(raise_keyword_required_utility_code)
 
@@ -2590,6 +2672,7 @@ class DefNode(FuncDefNode):
         if code.label_used(argtuple_error_label):
             code.put_goto(success_label)
             code.put_label(argtuple_error_label)
+            code.globalstate.use_utility_code(raise_argtuple_invalid_utility_code)
             code.put('__Pyx_RaiseArgtupleInvalid("%s", %d, %d, %d, PyTuple_GET_SIZE(%s)); ' % (
                     self.name, has_fixed_positional_count,
                     min_positional_args, max_positional_args,
@@ -2617,19 +2700,18 @@ class DefNode(FuncDefNode):
             code.putln('if (PyTuple_GET_SIZE(%s) > %d) {' % (
                     Naming.args_cname,
                     max_positional_args))
-            code.put('%s = PyTuple_GetSlice(%s, %d, PyTuple_GET_SIZE(%s)); ' % (
+            code.putln('%s = PyTuple_GetSlice(%s, %d, PyTuple_GET_SIZE(%s));' % (
                     self.star_arg.entry.cname, Naming.args_cname,
                     max_positional_args, Naming.args_cname))
-            code.put_gotref(self.star_arg.entry.cname)
+            code.putln("if (unlikely(!%s)) {" % self.star_arg.entry.cname)
             if self.starstar_arg:
-                code.putln("")
-                code.putln("if (unlikely(!%s)) {" % self.star_arg.entry.cname)
-                code.put_decref(self.starstar_arg.entry.cname, py_object_type)
-                code.putln('return %s;' % self.error_value())
-                code.putln('}')
-            else:
-                code.putln("if (unlikely(!%s)) return %s;" % (
-                        self.star_arg.entry.cname, self.error_value()))
+                code.put_decref_clear(self.starstar_arg.entry.cname, py_object_type)
+            if self.needs_closure:
+                code.put_decref(Naming.cur_scope_cname, self.local_scope.scope_class.type)
+            code.put_finish_refcount_context()
+            code.putln('return %s;' % self.error_value())
+            code.putln('}')
+            code.put_gotref(self.star_arg.entry.cname)
             code.putln('} else {')
             code.put("%s = %s; " % (self.star_arg.entry.cname, Naming.empty_tuple))
             code.put_incref(Naming.empty_tuple, py_object_type)
@@ -2712,6 +2794,7 @@ class DefNode(FuncDefNode):
                             # kwargs) that were passed into positional
                             # arguments up to this point
                             code.putln('else {')
+                            code.globalstate.use_utility_code(raise_argtuple_invalid_utility_code)
                             code.put('__Pyx_RaiseArgtupleInvalid("%s", %d, %d, %d, %d); ' % (
                                     self.name, has_fixed_positional_count,
                                     min_positional_args, max_positional_args, i))
@@ -2798,9 +2881,9 @@ class DefNode(FuncDefNode):
             if arg.needs_conversion:
                 self.generate_arg_conversion(arg, code)
             elif arg.entry.in_closure:
-                code.putln('%s = %s;' % (arg.entry.cname, arg.hdr_cname))
                 if arg.type.is_pyobject:
-                    code.put_var_incref(arg.entry)
+                    code.put_incref(arg.hdr_cname, py_object_type)
+                code.putln('%s = %s;' % (arg.entry.cname, arg.hdr_cname))
 
     def generate_arg_conversion(self, arg, code):
         # Generate conversion code for one argument.
@@ -2823,7 +2906,7 @@ class DefNode(FuncDefNode):
                 error(arg.pos,
                     "Cannot convert 1 argument from '%s' to '%s'" %
                         (old_type, new_type))
-    
+
     def generate_arg_conversion_from_pyobject(self, arg, code):
         new_type = arg.type
         func = new_type.from_py_function
@@ -2834,14 +2917,14 @@ class DefNode(FuncDefNode):
             if new_type.is_enum:
                 rhs = PyrexTypes.typecast(new_type, PyrexTypes.c_long_type, rhs)
             code.putln("%s = %s; %s" % (
-                lhs, 
+                lhs,
                 rhs,
                 code.error_goto_if(new_type.error_condition(arg.entry.cname), arg.pos)))
         else:
-            error(arg.pos, 
-                "Cannot convert Python object argument to type '%s'" 
+            error(arg.pos,
+                "Cannot convert Python object argument to type '%s'"
                     % new_type)
-    
+
     def generate_arg_conversion_to_pyobject(self, arg, code):
         old_type = arg.hdr_type
         func = old_type.to_py_function
@@ -2857,34 +2940,174 @@ class DefNode(FuncDefNode):
                 "Cannot convert argument of type '%s' to Python object"
                     % old_type)
 
-    def generate_argument_type_tests(self, code):
-        # Generate type tests for args whose signature
-        # type is PyObject * and whose declared type is
-        # a subtype thereof.
-        for arg in self.args:
-            if arg.needs_type_test:
-                self.generate_arg_type_test(arg, code)
-            elif not arg.accept_none and arg.type.is_pyobject:
-                self.generate_arg_none_check(arg, code)
+    def generate_argument_type_tests(self, code):
+        # Generate type tests for args whose signature
+        # type is PyObject * and whose declared type is
+        # a subtype thereof.
+        for arg in self.args:
+            if arg.needs_type_test:
+                self.generate_arg_type_test(arg, code)
+            elif not arg.accept_none and arg.type.is_pyobject:
+                self.generate_arg_none_check(arg, code)
+
+    def error_value(self):
+        return self.entry.signature.error_value
+
+    def caller_will_check_exceptions(self):
+        return 1
+
+
+class GeneratorDefNode(DefNode):
+    # Generator DefNode.
+    #
+    # gbody          GeneratorBodyDefNode
+    #
+
+    is_generator = True
+    needs_closure = True
+
+    child_attrs = DefNode.child_attrs + ["gbody"]
+
+    def __init__(self, **kwargs):
+        # XXX: don't actually needs a body
+        kwargs['body'] = StatListNode(kwargs['pos'], stats=[])
+        super(GeneratorDefNode, self).__init__(**kwargs)
+
+    def analyse_declarations(self, env):
+        super(GeneratorDefNode, self).analyse_declarations(env)
+        self.gbody.local_scope = self.local_scope
+        self.gbody.analyse_declarations(env)
+
+    def generate_function_body(self, env, code):
+        body_cname = self.gbody.entry.func_cname
+        generator_cname = '%s->%s' % (Naming.cur_scope_cname, Naming.obj_base_cname)
+
+        code.putln('%s.resume_label = 0;' % generator_cname)
+        code.putln('%s.body = (__pyx_generator_body_t) %s;' % (generator_cname, body_cname))
+        code.put_giveref(Naming.cur_scope_cname)
+        code.put_finish_refcount_context()
+        code.putln("return (PyObject *) %s;" % Naming.cur_scope_cname);
+
+    def generate_function_definitions(self, env, code):
+        self.gbody.generate_function_header(code, proto=True)
+        super(GeneratorDefNode, self).generate_function_definitions(env, code)
+        self.gbody.generate_function_definitions(env, code)
+
+
+class GeneratorBodyDefNode(DefNode):
+    # Generator body DefNode.
+    #
+
+    is_generator_body = True
+
+    def __init__(self, pos=None, name=None, body=None):
+        super(GeneratorBodyDefNode, self).__init__(pos=pos, body=body, name=name, doc=None,
+                                                   args=[],
+                                                   star_arg=None, starstar_arg=None)
+
+    def declare_generator_body(self, env):
+        prefix = env.next_id(env.scope_prefix)
+        name = env.next_id('generator')
+        entry = env.declare_var(prefix + name, py_object_type, self.pos, visibility='private')
+        entry.func_cname = Naming.genbody_prefix + prefix + name
+        entry.qualified_name = EncodedString(self.name)
+        self.entry = entry
+
+    def analyse_declarations(self, env):
+        self.analyse_argument_types(env)
+        self.declare_generator_body(env)
+
+    def generate_function_header(self, code, proto=False):
+        header = "static PyObject *%s(%s, PyObject *%s)" % (
+            self.entry.func_cname,
+            self.local_scope.scope_class.type.declaration_code(Naming.cur_scope_cname),
+            Naming.sent_value_cname)
+        if proto:
+            code.putln('%s; /* proto */' % header)
+        else:
+            code.putln('%s /* generator body */\n{' % header);
+
+    def generate_function_definitions(self, env, code):
+        lenv = self.local_scope
+
+        # Generate closure function definitions
+        self.body.generate_function_definitions(lenv, code)
+
+        # Generate C code for header and body of function
+        code.enter_cfunc_scope()
+        code.return_from_error_cleanup_label = code.new_label()
+
+        # ----- Top-level constants used by this function
+        code.mark_pos(self.pos)
+        self.generate_cached_builtins_decls(lenv, code)
+        # ----- Function header
+        code.putln("")
+        self.generate_function_header(code)
+        # ----- Local variables
+        code.putln("PyObject *%s = NULL;" % Naming.retval_cname)
+        tempvardecl_code = code.insertion_point()
+        code.put_declare_refcount_context()
+        code.put_setup_refcount_context(self.entry.name)
+
+        # ----- Resume switch point.
+        code.funcstate.init_closure_temps(lenv.scope_class.type.scope)
+        resume_code = code.insertion_point()
+        first_run_label = code.new_label('first_run')
+        code.use_label(first_run_label)
+        code.put_label(first_run_label)
+        code.putln('%s' %
+                   (code.error_goto_if_null(Naming.sent_value_cname, self.pos)))
+
+        # ----- Function body
+        self.generate_function_body(env, code)
+        code.putln('PyErr_SetNone(PyExc_StopIteration); %s' % code.error_goto(self.pos))
+        # ----- Error cleanup
+        if code.error_label in code.labels_used:
+            code.put_goto(code.return_label)
+            code.put_label(code.error_label)
+            for cname, type in code.funcstate.all_managed_temps():
+                code.put_xdecref(cname, type)
+            code.putln('__Pyx_AddTraceback("%s");' % self.entry.qualified_name)
+
+        # ----- Non-error return cleanup
+        code.put_label(code.return_label)
+        code.put_xdecref(Naming.retval_cname, py_object_type)
+        code.putln('%s->%s.resume_label = -1;' % (Naming.cur_scope_cname, Naming.obj_base_cname))
+        code.put_finish_refcount_context()
+        code.putln('return NULL;');
+        code.putln("}")
+
+        # ----- Go back and insert temp variable declarations
+        tempvardecl_code.put_temp_declarations(code.funcstate)
+        # ----- Generator resume code
+        resume_code.putln("switch (%s->%s.resume_label) {" % (Naming.cur_scope_cname, Naming.obj_base_cname));
+        resume_code.putln("case 0: goto %s;" % first_run_label)
+
+        from ParseTreeTransforms import YieldNodeCollector
+        collector = YieldNodeCollector()
+        collector.visitchildren(self)
+        for yield_expr in collector.yields:
+            resume_code.putln("case %d: goto %s;" % (yield_expr.label_num, yield_expr.label_name));
+        resume_code.putln("default: /* CPython raises the right error here */");
+        resume_code.put_finish_refcount_context()
+        resume_code.putln("return NULL;");
+        resume_code.putln("}");
+
+        code.exit_cfunc_scope()
+
 
-    def error_value(self):
-        return self.entry.signature.error_value
-    
-    def caller_will_check_exceptions(self):
-        return 1
-            
 class OverrideCheckNode(StatNode):
     # A Node for dispatching to the def method if it
-    # is overriden. 
+    # is overriden.
     #
     #  py_func
     #
     #  args
     #  func_temp
     #  body
-    
+
     child_attrs = ['body']
-    
+
     body = None
 
     def analyse_expressions(self, env):
@@ -2897,11 +3120,11 @@ class OverrideCheckNode(StatNode):
         self.func_node = ExprNodes.RawCNameExprNode(self.pos, py_object_type)
         call_tuple = ExprNodes.TupleNode(self.pos, args=[ExprNodes.NameNode(self.pos, name=arg.name) for arg in self.args[first_arg:]])
         call_node = ExprNodes.SimpleCallNode(self.pos,
-                                             function=self.func_node, 
+                                             function=self.func_node,
                                              args=[ExprNodes.NameNode(self.pos, name=arg.name) for arg in self.args[first_arg:]])
         self.body = ReturnStatNode(self.pos, value=call_node)
         self.body.analyse_expressions(env)
-        
+
     def generate_execution_code(self, code):
         interned_attr_cname = code.intern_identifier(self.py_func.entry.name)
         # Check to see if we are an extension type
@@ -2955,7 +3178,7 @@ class PyClassDefNode(ClassDefNode):
     child_attrs = ["body", "dict", "metaclass", "mkw", "bases", "classobj", "target"]
     decorators = None
     py3_style_class = False # Python3 style class (bases+kwargs)
-    
+
     def __init__(self, pos, name, bases, doc, body, decorators = None,
                  keyword_args = None, starstar_arg = None):
         StatNode.__init__(self, pos)
@@ -3005,7 +3228,7 @@ class PyClassDefNode(ClassDefNode):
             self.classobj = ExprNodes.ClassNode(pos, name = name,
                     bases = bases, dict = self.dict, doc = doc_node)
         self.target = ExprNodes.NameNode(pos, name = name)
-        
+
     def as_cclass(self):
         """
         Return this node as if it were declared as an extension class
@@ -3036,8 +3259,8 @@ class PyClassDefNode(ClassDefNode):
         else:
             error(self.classobj.bases.args.pos, "C class may only have one base class")
             return None
-        
-        return CClassDefNode(self.pos, 
+
+        return CClassDefNode(self.pos,
                              visibility = 'private',
                              module_name = None,
                              class_name = self.name,
@@ -3047,21 +3270,21 @@ class PyClassDefNode(ClassDefNode):
                              body = self.body,
                              in_pxd = False,
                              doc = self.doc)
-        
+
     def create_scope(self, env):
         genv = env
         while genv.is_py_class_scope or genv.is_c_class_scope:
             genv = genv.outer_scope
         cenv = self.scope = PyClassScope(name = self.name, outer_scope = genv)
         return cenv
-    
+
     def analyse_declarations(self, env):
         self.target.analyse_target_declaration(env)
         cenv = self.create_scope(env)
         cenv.directives = env.directives
         cenv.class_obj_cname = self.target.entry.cname
         self.body.analyse_declarations(cenv)
-    
+
     def analyse_expressions(self, env):
         if self.py3_style_class:
             self.bases.analyse_expressions(env)
@@ -3073,10 +3296,11 @@ class PyClassDefNode(ClassDefNode):
         cenv = self.scope
         self.body.analyse_expressions(cenv)
         self.target.analyse_target_expression(env, self.classobj)
-    
+
     def generate_function_definitions(self, env, code):
+        self.generate_lambda_definitions(self.scope, code)
         self.body.generate_function_definitions(self.scope, code)
-    
+
     def generate_execution_code(self, code):
         code.pyclass_stack.append(self)
         cenv = self.scope
@@ -3131,6 +3355,7 @@ class CClassDefNode(ClassDefNode):
     objstruct_name = None
     typeobj_name = None
     decorators = None
+    shadow = False
 
     def analyse_declarations(self, env):
         #print "CClassDefNode.analyse_declarations:", self.class_name
@@ -3149,8 +3374,8 @@ class CClassDefNode(ClassDefNode):
             error(self.pos, "Object struct name specification required for "
                 "C class defined in 'extern from' block")
         self.base_type = None
-        # Now that module imports are cached, we need to 
-        # import the modules for extern classes. 
+        # Now that module imports are cached, we need to
+        # import the modules for extern classes.
         if self.module_name:
             self.module = None
             for module in env.cimported_modules:
@@ -3177,7 +3402,9 @@ class CClassDefNode(ClassDefNode):
                 if base_class_entry:
                     if not base_class_entry.is_type:
                         error(self.pos, "'%s' is not a type name" % self.base_class_name)
-                    elif not base_class_entry.type.is_extension_type:
+                    elif not base_class_entry.type.is_extension_type and \
+                             not (base_class_entry.type.is_builtin_type and \
+                                  base_class_entry.type.objstruct_cname):
                         error(self.pos, "'%s' is not an extension type" % self.base_class_name)
                     elif not base_class_entry.type.is_complete():
                         error(self.pos, "Base class '%s' of type '%s' is incomplete" % (
@@ -3186,6 +3413,10 @@ class CClassDefNode(ClassDefNode):
                              base_class_entry.type.scope.directives['final']:
                         error(self.pos, "Base class '%s' of type '%s' is final" % (
                             self.base_class_name, self.class_name))
+                    elif base_class_entry.type.is_builtin_type and \
+                             base_class_entry.type.name in ('tuple', 'str', 'bytes'):
+                        error(self.pos, "inheritance from PyVarObject types like '%s' is not currently supported"
+                              % base_class_entry.type.name)
                     else:
                         self.base_type = base_class_entry.type
         has_body = self.body is not None
@@ -3198,11 +3429,13 @@ class CClassDefNode(ClassDefNode):
             home_scope = env
 
         if self.visibility == 'extern':
-            if self.module_name == '__builtin__' and self.class_name in Builtin.builtin_types:
+            if (self.module_name == '__builtin__' and
+                self.class_name in Builtin.builtin_types and
+                env.qualified_name[:8] != 'cpython.'): # allow overloaded names for cimporting from cpython
                 warning(self.pos, "%s already a builtin Cython type" % self.class_name, 1)
 
         self.entry = home_scope.declare_c_class(
-            name = self.class_name, 
+            name = self.class_name,
             pos = self.pos,
             defining = has_body and self.in_pxd,
             implementing = has_body and not self.in_pxd,
@@ -3213,16 +3446,19 @@ class CClassDefNode(ClassDefNode):
             visibility = self.visibility,
             typedef_flag = self.typedef_flag,
             api = self.api,
-            buffer_defaults = buffer_defaults)
+            buffer_defaults = buffer_defaults, 
+            shadow = self.shadow)
+        if self.shadow:
+            home_scope.lookup(self.class_name).as_variable = self.entry
         if home_scope is not env and self.visibility == 'extern':
-            env.add_imported_entry(self.class_name, self.entry, pos)
+            env.add_imported_entry(self.class_name, self.entry, self.pos)
         self.scope = scope = self.entry.type.scope
         if scope is not None:
             scope.directives = env.directives
 
         if self.doc and Options.docstrings:
             scope.doc = embed_position(self.pos, self.doc)
-            
+
         if has_body:
             self.body.analyse_declarations(scope)
             if self.in_pxd:
@@ -3230,23 +3466,23 @@ class CClassDefNode(ClassDefNode):
             else:
                 scope.implemented = 1
         env.allocate_vtable_names(self.entry)
-        
+
     def analyse_expressions(self, env):
         if self.body:
             scope = self.entry.type.scope
             self.body.analyse_expressions(scope)
-    
+
     def generate_function_definitions(self, env, code):
         if self.body:
-            self.body.generate_function_definitions(
-                self.entry.type.scope, code)
-    
+            self.generate_lambda_definitions(self.scope, code)
+            self.body.generate_function_definitions(self.scope, code)
+
     def generate_execution_code(self, code):
         # This is needed to generate evaluation code for
         # default values of method arguments.
         if self.body:
             self.body.generate_execution_code(code)
-            
+
     def annotate(self, code):
         if self.body:
             self.body.annotate(code)
@@ -3258,7 +3494,7 @@ class PropertyNode(StatNode):
     #  name   string
     #  doc    EncodedString or None    Doc string
     #  body   StatListNode
-    
+
     child_attrs = ["body"]
 
     def analyse_declarations(self, env):
@@ -3269,7 +3505,7 @@ class PropertyNode(StatNode):
 
     def analyse_expressions(self, env):
         self.body.analyse_expressions(env)
-    
+
     def generate_function_definitions(self, env, code):
         self.body.generate_function_definitions(env, code)
 
@@ -3284,7 +3520,7 @@ class GlobalNode(StatNode):
     # Global variable declaration.
     #
     # names    [string]
-    
+
     child_attrs = []
 
     def analyse_declarations(self, env):
@@ -3293,7 +3529,25 @@ class GlobalNode(StatNode):
 
     def analyse_expressions(self, env):
         pass
-    
+
+    def generate_execution_code(self, code):
+        pass
+
+
+class NonlocalNode(StatNode):
+    # Nonlocal variable declaration via the 'nonlocal' keyword.
+    #
+    # names    [string]
+
+    child_attrs = []
+
+    def analyse_declarations(self, env):
+        for name in self.names:
+            env.declare_nonlocal(name, self.pos)
+
+    def analyse_expressions(self, env):
+        pass
+
     def generate_execution_code(self, code):
         pass
 
@@ -3304,7 +3558,7 @@ class ExprStatNode(StatNode):
     #  expr   ExprNode
 
     child_attrs = ["expr"]
-    
+
     def analyse_declarations(self, env):
         import ExprNodes
         if isinstance(self.expr, ExprNodes.GeneralCallNode):
@@ -3320,10 +3574,17 @@ class ExprStatNode(StatNode):
                     else:
                         env.declare_var(var.value, type, var.pos, is_cdef = True)
                 self.__class__ = PassStatNode
-    
+
     def analyse_expressions(self, env):
+        self.expr.result_is_used = False # hint that .result() may safely be left empty
         self.expr.analyse_expressions(env)
-    
+
+    def nogil_check(self, env):
+        if self.expr.type.is_pyobject and self.expr.is_temp:
+            self.gil_error()
+
+    gil_message = "Discarding owned Python object"
+
     def generate_execution_code(self, code):
         self.expr.generate_evaluation_code(code)
         if not self.expr.is_temp and self.expr.result():
@@ -3357,7 +3618,7 @@ class AssignmentNode(StatNode):
     def generate_execution_code(self, code):
         self.generate_rhs_evaluation_code(code)
         self.generate_assignment_code(code)
-        
+
 
 class SingleAssignmentNode(AssignmentNode):
     #  The simplest case:
@@ -3367,23 +3628,23 @@ class SingleAssignmentNode(AssignmentNode):
     #  lhs      ExprNode      Left hand side
     #  rhs      ExprNode      Right hand side
     #  first    bool          Is this guaranteed the first assignment to lhs?
-    
+
     child_attrs = ["lhs", "rhs"]
     first = False
     declaration_only = False
 
     def analyse_declarations(self, env):
         import ExprNodes
-        
+
         # handle declarations of the form x = cython.foo()
         if isinstance(self.rhs, ExprNodes.CallNode):
             func_name = self.rhs.function.as_cython_attribute()
             if func_name:
                 args, kwds = self.rhs.explicit_args_kwds()
-                
+
                 if func_name in ['declare', 'typedef']:
                     if len(args) > 2 or kwds is not None:
-                        error(rhs.pos, "Can only declare one type at a time.")
+                        error(self.rhs.pos, "Can only declare one type at a time.")
                         return
                     type = args[0].analyse_as_type(env)
                     if type is None:
@@ -3410,11 +3671,11 @@ class SingleAssignmentNode(AssignmentNode):
                         if not isinstance(lhs, ExprNodes.NameNode):
                             error(lhs.pos, "Invalid declaration.")
                         env.declare_typedef(lhs.name, type, self.pos, visibility='private')
-                    
+
                 elif func_name in ['struct', 'union']:
                     self.declaration_only = True
                     if len(args) > 0 or kwds is None:
-                        error(rhs.pos, "Struct or union members must be given by name.")
+                        error(self.rhs.pos, "Struct or union members must be given by name.")
                         return
                     members = []
                     for member, type_node in kwds.key_value_pairs:
@@ -3432,12 +3693,12 @@ class SingleAssignmentNode(AssignmentNode):
                     env.declare_struct_or_union(name, func_name, scope, False, self.rhs.pos)
                     for member, type, pos in members:
                         scope.declare_var(member, type, pos)
-                    
+
         if self.declaration_only:
             return
         else:
             self.lhs.analyse_target_declaration(env)
-    
+
     def analyse_types(self, env, use_temp = 0):
         self.rhs.analyse_types(env)
         self.lhs.analyse_target_types(env)
@@ -3445,10 +3706,10 @@ class SingleAssignmentNode(AssignmentNode):
         self.rhs = self.rhs.coerce_to(self.lhs.type, env)
         if use_temp:
             self.rhs = self.rhs.coerce_to_temp(env)
-    
+
     def generate_rhs_evaluation_code(self, code):
         self.rhs.generate_evaluation_code(code)
-    
+
     def generate_assignment_code(self, code):
         self.lhs.generate_assignment_code(self.rhs, code)
 
@@ -3471,14 +3732,14 @@ class CascadedAssignmentNode(AssignmentNode):
     #  Used internally:
     #
     #  coerced_rhs_list   [ExprNode]   RHS coerced to type of each LHS
-    
+
     child_attrs = ["lhs_list", "rhs", "coerced_rhs_list"]
     coerced_rhs_list = None
 
     def analyse_declarations(self, env):
         for lhs in self.lhs_list:
             lhs.analyse_target_declaration(env)
-    
+
     def analyse_types(self, env, use_temp = 0):
         self.rhs.analyse_types(env)
         if not self.rhs.is_simple():
@@ -3497,7 +3758,7 @@ class CascadedAssignmentNode(AssignmentNode):
 
     def generate_rhs_evaluation_code(self, code):
         self.rhs.generate_evaluation_code(code)
-    
+
     def generate_assignment_code(self, code):
         for i in range(len(self.lhs_list)):
             lhs = self.lhs_list[i]
@@ -3516,7 +3777,7 @@ class CascadedAssignmentNode(AssignmentNode):
             lhs = self.lhs_list[i].annotate(code)
             rhs = self.coerced_rhs_list[i].annotate(code)
         self.rhs.annotate(code)
-        
+
 
 class ParallelAssignmentNode(AssignmentNode):
     #  A combined packing/unpacking assignment:
@@ -3531,13 +3792,13 @@ class ParallelAssignmentNode(AssignmentNode):
     #  before assigning to any of the left hand sides.
     #
     #  stats     [AssignmentNode]   The constituent assignments
-    
+
     child_attrs = ["stats"]
 
     def analyse_declarations(self, env):
         for stat in self.stats:
             stat.analyse_declarations(env)
-    
+
     def analyse_expressions(self, env):
         for stat in self.stats:
             stat.analyse_types(env, use_temp = 1)
@@ -3547,7 +3808,7 @@ class ParallelAssignmentNode(AssignmentNode):
 #            stat.analyse_expressions_1(env, use_temp = 1)
 #        for stat in self.stats:
 #            stat.analyse_expressions_2(env)
-    
+
     def generate_execution_code(self, code):
         for stat in self.stats:
             stat.generate_rhs_evaluation_code(code)
@@ -3575,18 +3836,18 @@ class InPlaceAssignmentNode(AssignmentNode):
     #  op       char          one of "+-*/%^&|"
     #  dup     (ExprNode)     copy of lhs used for operation (auto-generated)
     #
-    #  This code is a bit tricky because in order to obey Python 
-    #  semantics the sub-expressions (e.g. indices) of the lhs must 
-    #  not be evaluated twice. So we must re-use the values calculated 
-    #  in evaluation phase for the assignment phase as well. 
-    #  Fortunately, the type of the lhs node is fairly constrained 
-    #  (it must be a NameNode, AttributeNode, or IndexNode).     
-    
+    #  This code is a bit tricky because in order to obey Python
+    #  semantics the sub-expressions (e.g. indices) of the lhs must
+    #  not be evaluated twice. So we must re-use the values calculated
+    #  in evaluation phase for the assignment phase as well.
+    #  Fortunately, the type of the lhs node is fairly constrained
+    #  (it must be a NameNode, AttributeNode, or IndexNode).
+
     child_attrs = ["lhs", "rhs"]
 
     def analyse_declarations(self, env):
         self.lhs.analyse_target_declaration(env)
-        
+
     def analyse_types(self, env):
         self.rhs.analyse_types(env)
         self.lhs.analyse_target_types(env)
@@ -3618,7 +3879,7 @@ class InPlaceAssignmentNode(AssignmentNode):
     def annotate(self, code):
         self.lhs.annotate(code)
         self.rhs.annotate(code)
-    
+
     def create_binop_node(self):
         import ExprNodes
         return ExprNodes.binop_node(self.pos, self.operator, self.lhs, self.rhs)
@@ -3655,7 +3916,7 @@ class PrintStatNode(StatNode):
         if len(self.arg_tuple.args) == 1 and self.append_newline:
             arg = self.arg_tuple.args[0]
             arg.generate_evaluation_code(code)
-            
+
             code.putln(
                 "if (__Pyx_PrintOne(%s, %s) < 0) %s" % (
                     stream_result,
@@ -3733,13 +3994,13 @@ class DelStatNode(StatNode):
     #  del statement
     #
     #  args     [ExprNode]
-    
+
     child_attrs = ["args"]
 
     def analyse_declarations(self, env):
         for arg in self.args:
             arg.analyse_target_declaration(env)
-    
+
     def analyse_expressions(self, env):
         for arg in self.args:
             arg.analyse_target_expression(env, None)
@@ -3778,10 +4039,10 @@ class PassStatNode(StatNode):
     #  pass statement
 
     child_attrs = []
-    
+
     def analyse_expressions(self, env):
         pass
-    
+
     def generate_execution_code(self, code):
         pass
 
@@ -3792,7 +4053,7 @@ class BreakStatNode(StatNode):
 
     def analyse_expressions(self, env):
         pass
-    
+
     def generate_execution_code(self, code):
         if not code.break_label:
             error(self.pos, "break statement not inside loop")
@@ -3806,7 +4067,7 @@ class ContinueStatNode(StatNode):
 
     def analyse_expressions(self, env):
         pass
-    
+
     def generate_execution_code(self, code):
         if code.funcstate.in_try_finally:
             error(self.pos, "continue statement inside try of try...finally")
@@ -3821,7 +4082,7 @@ class ReturnStatNode(StatNode):
     #
     #  value         ExprNode or None
     #  return_type   PyrexType
-    
+
     child_attrs = ["value"]
 
     def analyse_expressions(self, env):
@@ -3833,7 +4094,7 @@ class ReturnStatNode(StatNode):
         if self.value:
             self.value.analyse_types(env)
             if return_type.is_void or return_type.is_returncode:
-                error(self.value.pos, 
+                error(self.value.pos,
                     "Return with value in void function")
             else:
                 self.value = self.value.coerce_to(env.return_type, env)
@@ -3881,7 +4142,7 @@ class ReturnStatNode(StatNode):
     def generate_function_definitions(self, env, code):
         if self.value is not None:
             self.value.generate_function_definitions(env, code)
-        
+
     def annotate(self, code):
         if self.value:
             self.value.annotate(code)
@@ -3893,7 +4154,7 @@ class RaiseStatNode(StatNode):
     #  exc_type    ExprNode or None
     #  exc_value   ExprNode or None
     #  exc_tb      ExprNode or None
-    
+
     child_attrs = ["exc_type", "exc_value", "exc_tb"]
 
     def analyse_expressions(self, env):
@@ -3906,12 +4167,28 @@ class RaiseStatNode(StatNode):
         if self.exc_tb:
             self.exc_tb.analyse_types(env)
             self.exc_tb = self.exc_tb.coerce_to_pyobject(env)
-        env.use_utility_code(raise_utility_code)
+        # special cases for builtin exceptions
+        self.builtin_exc_name = None
+        if self.exc_type and not self.exc_value and not self.exc_tb:
+            exc = self.exc_type
+            import ExprNodes
+            if (isinstance(exc, ExprNodes.SimpleCallNode) and 
+                not (exc.args or (exc.arg_tuple is not None and 
+                                  exc.arg_tuple.args))):
+                exc = exc.function # extract the exception type
+            if exc.is_name and exc.entry.is_builtin:
+                self.builtin_exc_name = exc.name
+                if self.builtin_exc_name == 'MemoryError':
+                    self.exc_type = None # has a separate implementation
 
     nogil_check = Node.gil_error
     gil_message = "Raising exception"
 
     def generate_execution_code(self, code):
+        if self.builtin_exc_name == 'MemoryError':
+            code.putln('PyErr_NoMemory(); %s' % code.error_goto(self.pos))
+            return
+
         if self.exc_type:
             self.exc_type.generate_evaluation_code(code)
             type_code = self.exc_type.py_result()
@@ -3927,6 +4204,7 @@ class RaiseStatNode(StatNode):
             tb_code = self.exc_tb.py_result()
         else:
             tb_code = "0"
+        code.globalstate.use_utility_code(raise_utility_code)
         code.putln(
             "__Pyx_Raise(%s, %s, %s);" % (
                 type_code,
@@ -3978,14 +4256,14 @@ class ReraiseStatNode(StatNode):
             code.putln(code.error_goto(self.pos))
         else:
             error(self.pos, "Reraise not inside except clause")
-        
+
 
 class AssertStatNode(StatNode):
     #  assert statement
     #
     #  cond    ExprNode
     #  value   ExprNode or None
-    
+
     child_attrs = ["cond", "value"]
 
     def analyse_expressions(self, env):
@@ -3996,9 +4274,9 @@ class AssertStatNode(StatNode):
 
     nogil_check = Node.gil_error
     gil_message = "Raising exception"
-    
+
     def generate_execution_code(self, code):
-        code.putln("#ifndef PYREX_WITHOUT_ASSERTIONS")
+        code.putln("#ifndef CYTHON_WITHOUT_ASSERTIONS")
         self.cond.generate_evaluation_code(code)
         code.putln(
             "if (unlikely(!%s)) {" %
@@ -4039,7 +4317,7 @@ class IfStatNode(StatNode):
     #  else_clause  StatNode or None
 
     child_attrs = ["if_clauses", "else_clause"]
-    
+
     def analyse_control_flow(self, env):
         env.start_branching(self.pos)
         for if_clause in self.if_clauses:
@@ -4054,7 +4332,7 @@ class IfStatNode(StatNode):
             if_clause.analyse_declarations(env)
         if self.else_clause:
             self.else_clause.analyse_declarations(env)
-    
+
     def analyse_expressions(self, env):
         for if_clause in self.if_clauses:
             if_clause.analyse_expressions(env)
@@ -4090,15 +4368,15 @@ class IfClauseNode(Node):
     #
     #  condition   ExprNode
     #  body        StatNode
-    
+
     child_attrs = ["condition", "body"]
 
     def analyse_control_flow(self, env):
         self.body.analyse_control_flow(env)
-        
+
     def analyse_declarations(self, env):
         self.body.analyse_declarations(env)
-    
+
     def analyse_expressions(self, env):
         self.condition = \
             self.condition.analyse_temp_boolean_expression(env)
@@ -4128,14 +4406,14 @@ class IfClauseNode(Node):
     def annotate(self, code):
         self.condition.annotate(code)
         self.body.annotate(code)
-        
+
 
 class SwitchCaseNode(StatNode):
     # Generated in the optimization of an if-elif-else node
     #
     # conditions    [ExprNode]
     # body          StatNode
-    
+
     child_attrs = ['conditions', 'body']
 
     def generate_execution_code(self, code):
@@ -4150,7 +4428,7 @@ class SwitchCaseNode(StatNode):
         for cond in self.conditions:
             cond.generate_function_definitions(env, code)
         self.body.generate_function_definitions(env, code)
-        
+
     def annotate(self, code):
         for cond in self.conditions:
             cond.annotate(code)
@@ -4162,9 +4440,9 @@ class SwitchStatNode(StatNode):
     # test          ExprNode
     # cases         [SwitchCaseNode]
     # else_clause   StatNode or None
-    
+
     child_attrs = ['test', 'cases', 'else_clause']
-    
+
     def generate_execution_code(self, code):
         self.test.generate_evaluation_code(code)
         code.putln("switch (%s) {" % self.test.result())
@@ -4189,9 +4467,9 @@ class SwitchStatNode(StatNode):
             case.annotate(code)
         if self.else_clause is not None:
             self.else_clause.annotate(code)
-            
+
 class LoopNode(object):
-    
+
     def analyse_control_flow(self, env):
         env.start_branching(self.pos)
         self.body.analyse_control_flow(env)
@@ -4200,7 +4478,7 @@ class LoopNode(object):
             self.else_clause.analyse_control_flow(env)
         env.finish_branching(self.end_pos())
 
-    
+
 class WhileStatNode(LoopNode, StatNode):
     #  while statement
     #
@@ -4214,14 +4492,14 @@ class WhileStatNode(LoopNode, StatNode):
         self.body.analyse_declarations(env)
         if self.else_clause:
             self.else_clause.analyse_declarations(env)
-    
+
     def analyse_expressions(self, env):
         self.condition = \
             self.condition.analyse_temp_boolean_expression(env)
         self.body.analyse_expressions(env)
         if self.else_clause:
             self.else_clause.analyse_expressions(env)
-    
+
     def generate_execution_code(self, code):
         old_loop_labels = code.new_loop_labels()
         code.putln(
@@ -4270,10 +4548,10 @@ class ForInStatNode(LoopNode, StatNode):
     #  body          StatNode
     #  else_clause   StatNode
     #  item          NextNode       used internally
-    
+
     child_attrs = ["target", "iterator", "body", "else_clause"]
     item = None
-    
+
     def analyse_declarations(self, env):
         self.target.analyse_target_declaration(env)
         self.body.analyse_declarations(env)
@@ -4285,7 +4563,12 @@ class ForInStatNode(LoopNode, StatNode):
         self.target.analyse_target_types(env)
         self.iterator.analyse_expressions(env)
         self.item = ExprNodes.NextNode(self.iterator, env)
-        self.item = self.item.coerce_to(self.target.type, env)
+        if (self.iterator.type.is_ptr or self.iterator.type.is_array) and \
+            self.target.type.assignable_from(self.iterator.type):
+            # C array slice optimization.
+            pass
+        else:
+            self.item = self.item.coerce_to(self.target.type, env)
         self.body.analyse_expressions(env)
         if self.else_clause:
             self.else_clause.analyse_expressions(env)
@@ -4393,7 +4676,7 @@ class ForFromStatNode(LoopNode, StatNode):
             if isinstance(self.step, ExprNodes.UnaryMinusNode):
                 warning(self.step.pos, "Probable infinite loop in for-from-by statment. Consider switching the directions of the relations.", 2)
             self.step.analyse_types(env)
-        
+
         target_type = self.target.type
         if self.target.type.is_numeric:
             loop_type = self.target.type
@@ -4410,7 +4693,7 @@ class ForFromStatNode(LoopNode, StatNode):
         if not self.bound2.is_literal:
             self.bound2 = self.bound2.coerce_to_temp(env)
         if self.step is not None:
-            self.step = self.step.coerce_to(loop_type, env)            
+            self.step = self.step.coerce_to(loop_type, env)
             if not self.step.is_literal:
                 self.step = self.step.coerce_to_temp(env)
 
@@ -4433,7 +4716,7 @@ class ForFromStatNode(LoopNode, StatNode):
         self.body.analyse_expressions(env)
         if self.else_clause:
             self.else_clause.analyse_expressions(env)
-            
+
     def generate_execution_code(self, code):
         old_loop_labels = code.new_loop_labels()
         from_range = self.from_range
@@ -4468,19 +4751,19 @@ class ForFromStatNode(LoopNode, StatNode):
         self.body.generate_execution_code(code)
         code.put_label(code.continue_label)
         if self.py_loopvar_node:
-            # This mess is to make for..from loops with python targets behave 
-            # exactly like those with C targets with regards to re-assignment 
-            # of the loop variable. 
+            # This mess is to make for..from loops with python targets behave
+            # exactly like those with C targets with regards to re-assignment
+            # of the loop variable.
             import ExprNodes
             if self.target.entry.is_pyglobal:
-                # We know target is a NameNode, this is the only ugly case. 
+                # We know target is a NameNode, this is the only ugly case.
                 target_node = ExprNodes.PyTempNode(self.target.pos, None)
                 target_node.allocate(code)
                 interned_cname = code.intern_identifier(self.target.entry.name)
                 code.globalstate.use_utility_code(ExprNodes.get_name_interned_utility_code)
                 code.putln("%s = __Pyx_GetName(%s, %s); %s" % (
                                 target_node.result(),
-                                Naming.module_cname, 
+                                Naming.module_cname,
                                 interned_cname,
                                 code.error_goto_if_null(target_node.result(), self.target.pos)))
                 code.put_gotref(target_node.result())
@@ -4494,8 +4777,8 @@ class ForFromStatNode(LoopNode, StatNode):
                 target_node.release(code)
         code.putln("}")
         if self.py_loopvar_node:
-            # This is potentially wasteful, but we don't want the semantics to 
-            # depend on whether or not the loop is a python type. 
+            # This is potentially wasteful, but we don't want the semantics to
+            # depend on whether or not the loop is a python type.
             self.py_loopvar_node.generate_evaluation_code(code)
             self.target.generate_assignment_code(self.py_loopvar_node, code)
         if from_range:
@@ -4518,7 +4801,7 @@ class ForFromStatNode(LoopNode, StatNode):
         if self.step is not None:
             self.step.generate_disposal_code(code)
             self.step.free_temps(code)
-    
+
     relation_table = {
         # {relop : (initial offset, increment op)}
         '<=': ("",   "++"),
@@ -4536,7 +4819,7 @@ class ForFromStatNode(LoopNode, StatNode):
         self.body.generate_function_definitions(env, code)
         if self.else_clause is not None:
             self.else_clause.generate_function_definitions(env, code)
-    
+
     def annotate(self, code):
         self.target.annotate(code)
         self.bound1.annotate(code)
@@ -4551,7 +4834,7 @@ class ForFromStatNode(LoopNode, StatNode):
 class WithStatNode(StatNode):
     """
     Represents a Python with statement.
-    
+
     This is only used at parse tree level; and is not present in
     analysis or generation phases.
     """
@@ -4568,19 +4851,19 @@ class TryExceptStatNode(StatNode):
     #  else_clause      StatNode or None
 
     child_attrs = ["body", "except_clauses", "else_clause"]
-    
+
     def analyse_control_flow(self, env):
         env.start_branching(self.pos)
         self.body.analyse_control_flow(env)
         successful_try = env.control_flow # grab this for later
         env.next_branch(self.body.end_pos())
         env.finish_branching(self.body.end_pos())
-        
+
         env.start_branching(self.except_clauses[0].pos)
         for except_clause in self.except_clauses:
             except_clause.analyse_control_flow(env)
             env.next_branch(except_clause.end_pos())
-            
+
         # the else cause it executed only when the try clause finishes
         env.control_flow.incoming = successful_try
         if self.else_clause:
@@ -4625,12 +4908,12 @@ class TryExceptStatNode(StatNode):
         try_continue_label = code.new_label('try_continue')
         try_end_label = code.new_label('try_end')
 
+        exc_save_vars = [code.funcstate.allocate_temp(py_object_type, False)
+                         for i in xrange(3)]
         code.putln("{")
-        code.putln("PyObject %s;" %
-                   ', '.join(['*%s' % var for var in Naming.exc_save_vars]))
         code.putln("__Pyx_ExceptionSave(%s);" %
-                   ', '.join(['&%s' % var for var in Naming.exc_save_vars]))
-        for var in Naming.exc_save_vars:
+                   ', '.join(['&%s' % var for var in exc_save_vars]))
+        for var in exc_save_vars:
             code.put_xgotref(var)
         code.putln(
             "/*try:*/ {")
@@ -4649,14 +4932,15 @@ class TryExceptStatNode(StatNode):
             self.else_clause.generate_execution_code(code)
             code.putln(
                 "}")
-        for var in Naming.exc_save_vars:
+        for var in exc_save_vars:
             code.put_xdecref_clear(var, py_object_type)
         code.put_goto(try_end_label)
         if code.label_used(try_return_label):
             code.put_label(try_return_label)
-            for var in Naming.exc_save_vars: code.put_xgiveref(var)
+            for var in exc_save_vars:
+                code.put_xgiveref(var)
             code.putln("__Pyx_ExceptionReset(%s);" %
-                       ', '.join(Naming.exc_save_vars))
+                       ', '.join(exc_save_vars))
             code.put_goto(old_return_label)
         code.put_label(our_error_label)
         for temp_name, type in temps_to_clean_up:
@@ -4668,9 +4952,10 @@ class TryExceptStatNode(StatNode):
         if error_label_used or not self.has_default_clause:
             if error_label_used:
                 code.put_label(except_error_label)
-            for var in Naming.exc_save_vars: code.put_xgiveref(var)
+            for var in exc_save_vars:
+                code.put_xgiveref(var)
             code.putln("__Pyx_ExceptionReset(%s);" %
-                       ', '.join(Naming.exc_save_vars))
+                       ', '.join(exc_save_vars))
             code.put_goto(old_error_label)
 
         for exit_label, old_label in zip(
@@ -4679,19 +4964,24 @@ class TryExceptStatNode(StatNode):
 
             if code.label_used(exit_label):
                 code.put_label(exit_label)
-                for var in Naming.exc_save_vars: code.put_xgiveref(var)
+                for var in exc_save_vars:
+                    code.put_xgiveref(var)
                 code.putln("__Pyx_ExceptionReset(%s);" %
-                           ', '.join(Naming.exc_save_vars))
+                           ', '.join(exc_save_vars))
                 code.put_goto(old_label)
 
         if code.label_used(except_end_label):
             code.put_label(except_end_label)
-            for var in Naming.exc_save_vars: code.put_xgiveref(var)
+            for var in exc_save_vars:
+                code.put_xgiveref(var)
             code.putln("__Pyx_ExceptionReset(%s);" %
-                       ', '.join(Naming.exc_save_vars))
+                       ', '.join(exc_save_vars))
         code.put_label(try_end_label)
         code.putln("}")
 
+        for cname in exc_save_vars:
+            code.funcstate.release_temp(cname)
+
         code.return_label = old_return_label
         code.break_label = old_break_label
         code.continue_label = old_continue_label
@@ -4727,7 +5017,7 @@ class ExceptClauseNode(Node):
     # excinfo_target is never set by the parser, but can be set by a transform
     # in order to extract more extensive information about the exception as a
     # sys.exc_info()-style tuple into a target variable
-    
+
     child_attrs = ["pattern", "target", "body", "exc_value", "excinfo_target"]
 
     exc_value = None
@@ -4739,7 +5029,7 @@ class ExceptClauseNode(Node):
         if self.excinfo_target is not None:
             self.excinfo_target.analyse_target_declaration(env)
         self.body.analyse_declarations(env)
-    
+
     def analyse_expressions(self, env):
         import ExprNodes
         genv = env.global_scope()
@@ -4791,13 +5081,13 @@ class ExceptClauseNode(Node):
             code.put_goto(end_label)
             code.putln("}")
             return
-        
+
         exc_vars = [code.funcstate.allocate_temp(py_object_type,
                                                  manage_ref=True)
                     for i in xrange(3)]
         code.putln('__Pyx_AddTraceback("%s");' % self.function_name)
         # We always have to fetch the exception value even if
-        # there is no target, because this also normalises the 
+        # there is no target, because this also normalises the
         # exception and stores it in the thread state.
         code.globalstate.use_utility_code(get_exception_utility_code)
         exc_args = "&%s, &%s, &%s" % tuple(exc_vars)
@@ -4826,7 +5116,7 @@ class ExceptClauseNode(Node):
         for var in exc_vars:
             code.putln("__Pyx_DECREF(%s); %s = 0;" % (var, var))
         code.put_goto(end_label)
-        
+
         if code.label_used(code.break_label):
             code.put_label(code.break_label)
             for var in exc_vars:
@@ -4851,7 +5141,7 @@ class ExceptClauseNode(Node):
         if self.target is not None:
             self.target.generate_function_definitions(env, code)
         self.body.generate_function_definitions(env, code)
-        
+
     def annotate(self, code):
         if self.pattern:
             for pattern in self.pattern:
@@ -4877,9 +5167,9 @@ class TryFinallyStatNode(StatNode):
     #  it on exit.
 
     child_attrs = ["body", "finally_clause"]
-    
+
     preserve_exception = 1
-    
+
     disallow_continue_in_try_finally = 0
     # There doesn't seem to be any point in disallowing
     # continue in the try block, since we have no problem
@@ -4889,7 +5179,7 @@ class TryFinallyStatNode(StatNode):
         node = TryFinallyStatNode(pos, body=body, finally_clause=finally_clause)
         return node
     create_analysed = staticmethod(create_analysed)
-    
+
     def analyse_control_flow(self, env):
         env.start_branching(self.pos)
         self.body.analyse_control_flow(env)
@@ -4900,7 +5190,7 @@ class TryFinallyStatNode(StatNode):
     def analyse_declarations(self, env):
         self.body.analyse_declarations(env)
         self.finally_clause.analyse_declarations(env)
-    
+
     def analyse_expressions(self, env):
         self.body.analyse_expressions(env)
         self.finally_clause.analyse_expressions(env)
@@ -4956,7 +5246,7 @@ class TryFinallyStatNode(StatNode):
                 new_label = new_labels[i]
                 #if new_label and new_label != "<try>":
                 if new_label == new_error_label and self.preserve_exception:
-                    self.put_error_catcher(code, 
+                    self.put_error_catcher(code,
                         new_error_label, i+1, catch_label, temps_to_clean_up)
                 else:
                     code.put('%s: ' % new_label)
@@ -5023,7 +5313,7 @@ class TryFinallyStatNode(StatNode):
                     Naming.exc_lineno_name, Naming.lineno_cname))
         code.put_goto(catch_label)
         code.putln("}")
-            
+
     def put_error_uncatcher(self, code, i, error_label):
         code.globalstate.use_utility_code(restore_exception_utility_code)
         code.putln(
@@ -5054,7 +5344,7 @@ class GILStatNode(TryFinallyStatNode):
     #   state   string   'gil' or 'nogil'
 
 #    child_attrs = []
-    
+
     preserve_exception = 0
 
     def __init__(self, pos, state, body):
@@ -5081,7 +5371,7 @@ class GILStatNode(TryFinallyStatNode):
             code.putln("#endif")
         else:
             code.putln("#ifdef WITH_THREAD")
-            code.putln("PyThreadState *_save;")
+            code.putln("PyThreadState *_save = NULL;")
             code.putln("#endif")
             code.putln("Py_UNBLOCK_THREADS")
         TryFinallyStatNode.generate_execution_code(self, code)
@@ -5114,7 +5404,7 @@ class CImportStatNode(StatNode):
     #  as_name       string or None   Name specified in "as" clause, if any
 
     child_attrs = []
-    
+
     def analyse_declarations(self, env):
         if not env.is_module_scope:
             error(self.pos, "cimport only allowed at module level")
@@ -5139,17 +5429,17 @@ class CImportStatNode(StatNode):
 
     def analyse_expressions(self, env):
         pass
-    
+
     def generate_execution_code(self, code):
         pass
-    
+
 
 class FromCImportStatNode(StatNode):
     #  from ... cimport statement
     #
     #  module_name     string                        Qualified name of module
     #  imported_names  [(pos, name, as_name, kind)]  Names to be imported
-    
+
     child_attrs = []
 
     def analyse_declarations(self, env):
@@ -5181,11 +5471,11 @@ class FromCImportStatNode(StatNode):
                         else:
                             error(pos, "Name '%s' not declared in module '%s'"
                                 % (name, self.module_name))
-                        
+
                 if entry:
                     local_name = as_name or name
                     env.add_imported_entry(local_name, entry, pos)
-    
+
     def declaration_matches(self, entry, kind):
         if not entry.is_type:
             return 0
@@ -5202,7 +5492,7 @@ class FromCImportStatNode(StatNode):
 
     def analyse_expressions(self, env):
         pass
-    
+
     def generate_execution_code(self, code):
         pass
 
@@ -5218,7 +5508,7 @@ class FromImportStatNode(StatNode):
 
     child_attrs = ["module"]
     import_star = 0
-    
+
     def analyse_declarations(self, env):
         for name, target in self.items:
             if name == "*":
@@ -5229,7 +5519,7 @@ class FromImportStatNode(StatNode):
                 self.import_star = 1
             else:
                 target.analyse_target_declaration(env)
-    
+
     def analyse_expressions(self, env):
         import ExprNodes
         self.module.analyse_expressions(env)
@@ -5256,14 +5546,14 @@ class FromImportStatNode(StatNode):
                         if entry.type.module_name == module.qualified_name:
                             continue
                     except AttributeError:
-                        pass 
+                        pass
                 target.analyse_target_expression(env, None)
                 if target.type is py_object_type:
                     coerced_item = None
                 else:
                     coerced_item = self.item.coerce_to(target.type, env)
                 self.interned_items.append((name, target, coerced_item))
-    
+
     def generate_execution_code(self, code):
         self.module.generate_evaluation_code(code)
         if self.import_star:
@@ -5313,7 +5603,7 @@ utility_function_predeclarations = \
   #elif defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
     #define CYTHON_INLINE inline
   #else
-    #define CYTHON_INLINE 
+    #define CYTHON_INLINE
   #endif
 #endif
 
@@ -5321,14 +5611,14 @@ utility_function_predeclarations = \
 #ifndef CYTHON_UNUSED
 # if defined(__GNUC__)
 #   if !(defined(__cplusplus)) || (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4))
-#     define CYTHON_UNUSED __attribute__ ((__unused__)) 
+#     define CYTHON_UNUSED __attribute__ ((__unused__))
 #   else
 #     define CYTHON_UNUSED
 #   endif
 # elif defined(__ICC) || defined(__INTEL_COMPILER)
-#   define CYTHON_UNUSED __attribute__ ((__unused__)) 
+#   define CYTHON_UNUSED __attribute__ ((__unused__))
 # else
-#   define CYTHON_UNUSED 
+#   define CYTHON_UNUSED
 # endif
 #endif
 
@@ -5341,7 +5631,7 @@ if Options.gcc_branch_hints:
     """
 #ifdef __GNUC__
 /* Test for GCC > 2.95 */
-#if __GNUC__ > 2 || (__GNUC__ == 2 && (__GNUC_MINOR__ > 95)) 
+#if __GNUC__ > 2 || (__GNUC__ == 2 && (__GNUC_MINOR__ > 95))
 #define likely(x)   __builtin_expect(!!(x), 1)
 #define unlikely(x) __builtin_expect(!!(x), 0)
 #else /* __GNUC__ > 2 ... */
@@ -5815,6 +6105,31 @@ static void __Pyx_ExceptionReset(PyObject *type, PyObject *value, PyObject *tb)
 
 #------------------------------------------------------------------------------------
 
+swap_exception_utility_code = UtilityCode(
+proto = """
+static CYTHON_INLINE void __Pyx_ExceptionSwap(PyObject **type, PyObject **value, PyObject **tb); /*proto*/
+""",
+impl = """
+static CYTHON_INLINE void __Pyx_ExceptionSwap(PyObject **type, PyObject **value, PyObject **tb) {
+    PyObject *tmp_type, *tmp_value, *tmp_tb;
+    PyThreadState *tstate = PyThreadState_GET();
+
+    tmp_type = tstate->exc_type;
+    tmp_value = tstate->exc_value;
+    tmp_tb = tstate->exc_traceback;
+
+    tstate->exc_type = *type;
+    tstate->exc_value = *value;
+    tstate->exc_traceback = *tb;
+
+    *type = tmp_type;
+    *value = tmp_value;
+    *tb = tmp_tb;
+}
+""")
+
+#------------------------------------------------------------------------------------
+
 arg_type_test_utility_code = UtilityCode(
 proto = """
 static int __Pyx_ArgTypeTest(PyObject *obj, PyTypeObject *type, int none_allowed,
@@ -6072,7 +6387,8 @@ invalid_keyword:
 bad:
     return -1;
 }
-""")
+""",
+requires=[raise_double_keywords_utility_code])
 
 #------------------------------------------------------------------------------------
 
@@ -6216,25 +6532,26 @@ bad:
 
 get_vtable_utility_code = UtilityCode(
 proto = """
-static int __Pyx_GetVtable(PyObject *dict, void *vtabptr); /*proto*/
+static void* __Pyx_GetVtable(PyObject *dict); /*proto*/
 """,
 impl = r"""
-static int __Pyx_GetVtable(PyObject *dict, void *vtabptr) {
+static void* __Pyx_GetVtable(PyObject *dict) {
+    void* ptr;
     PyObject *ob = PyMapping_GetItemString(dict, (char *)"__pyx_vtable__");
     if (!ob)
         goto bad;
 #if PY_VERSION_HEX >= 0x02070000 && !(PY_MAJOR_VERSION==3&&PY_MINOR_VERSION==0)
-    *(void **)vtabptr = PyCapsule_GetPointer(ob, 0);
+    ptr = PyCapsule_GetPointer(ob, 0);
 #else
-    *(void **)vtabptr = PyCObject_AsVoidPtr(ob);
+    ptr = PyCObject_AsVoidPtr(ob);
 #endif
-    if (!*(void **)vtabptr)
-        goto bad;
+    if (!ptr && !PyErr_Occurred())
+        PyErr_SetString(PyExc_RuntimeError, "invalid vtable found for imported type");
     Py_DECREF(ob);
-    return 0;
+    return ptr;
 bad:
     Py_XDECREF(ob);
-    return -1;
+    return NULL;
 }
 """)
 
@@ -6291,8 +6608,8 @@ proto="""
 
 #------------------------------------------------------------------------------------
 
-# Note that cPython ignores PyTrace_EXCEPTION, 
-# but maybe some other profilers don't. 
+# Note that cPython ignores PyTrace_EXCEPTION,
+# but maybe some other profilers don't.
 
 profile_utility_code = UtilityCode(proto="""
 #ifndef CYTHON_PROFILE
@@ -6320,7 +6637,7 @@ profile_utility_code = UtilityCode(proto="""
   #define __Pyx_TraceDeclarations                                  \\
   static PyCodeObject *%(FRAME_CODE)s = NULL;                      \\
   CYTHON_FRAME_MODIFIER PyFrameObject *%(FRAME)s = NULL;           \\
-  int __Pyx_use_tracing = 0;                                                         
+  int __Pyx_use_tracing = 0;
 
   #define __Pyx_TraceCall(funcname, srcfile, firstlineno)                            \\
   if (unlikely(PyThreadState_GET()->use_tracing && PyThreadState_GET()->c_profilefunc)) {      \\
@@ -6350,12 +6667,12 @@ profile_utility_code = UtilityCode(proto="""
 #else
 
   #define __Pyx_TraceDeclarations
-  #define __Pyx_TraceCall(funcname, srcfile, firstlineno) 
-  #define __Pyx_TraceException() 
-  #define __Pyx_TraceReturn(result) 
+  #define __Pyx_TraceCall(funcname, srcfile, firstlineno)
+  #define __Pyx_TraceException()
+  #define __Pyx_TraceReturn(result)
 
 #endif /* CYTHON_PROFILE */
-""" 
+"""
 % {
     "FRAME": Naming.frame_cname,
     "FRAME_CODE": Naming.frame_code_cname,
@@ -6422,10 +6739,10 @@ static PyCodeObject *__Pyx_createFrameCodeObject(const char *funcname, const cha
         %(EMPTY_BYTES)s   /*PyObject *lnotab*/
     );
 
-bad: 
+bad:
     Py_XDECREF(py_srcfile);
     Py_XDECREF(py_funcname);
-    
+
     return py_code;
 }