'Create a copy of the original c(p)def function for all specialized
versions.'

def copy_cdef(self, env):

    permutations = self.node.type.get_all_specialized_permutations()
    if (self.node.entry in env.cfunc_entries):
        env.cfunc_entries.remove(self.node.entry)
    self.orig_py_func = orig_py_func = self.node.py_func
    self.node.py_func = None
    if orig_py_func:
        env.pyfunc_entries.remove(orig_py_func.entry)
    fused_types = self.node.type.get_fused_types()
    self.fused_compound_types = fused_types
    for (cname, fused_to_specific) in permutations:
        copied_node = copy.deepcopy(self.node)
        type = copied_node.type.specialize(fused_to_specific)
        entry = copied_node.entry
        copied_node.type = type
        (entry.type, type.entry) = (type, entry)
        entry.used = (entry.used or self.node.entry.defined_in_pxd or env.is_c_class_scope or entry.is_cmethod)
        if self.node.cfunc_declarator.optional_arg_count:
            self.node.cfunc_declarator.declare_optional_arg_struct(type, env, fused_cname=cname)
        copied_node.return_type = type.return_type
        self.create_new_local_scope(copied_node, env, fused_to_specific)
        self._specialize_function_args(copied_node.cfunc_declarator.args, fused_to_specific)
        type.specialize_entry(entry, cname)
        env.cfunc_entries.append(entry)
        copied_node.declare_cpdef_wrapper(env)
        if copied_node.py_func:
            env.pyfunc_entries.remove(copied_node.py_func.entry)
            self.specialize_copied_def(copied_node.py_func, cname, self.node.entry.as_variable, fused_to_specific, fused_types)
        if (not self.replace_fused_typechecks(copied_node)):
            break
    if orig_py_func:
        self.py_func = self.make_fused_cpdef(orig_py_func, env, is_def=False)
    else:
        self.py_func = orig_py_func
