Commit 9ada8c82 authored by Robert Bradshaw's avatar Robert Bradshaw

Number of arguments can grow with overridden cdef functions.

parent a4c3ab1c
......@@ -1523,7 +1523,7 @@ class SimpleCallNode(ExprNode):
if func_type.has_varargs:
expected_str = "at least " + expected_str
elif func_type.optional_arg_count:
if actual_nargs > max_nargs:
if actual_nargs < max_nargs:
expected_str = "at least " + expected_str
else:
expected_str = "at most " + str(max_nargs)
......@@ -1569,7 +1569,11 @@ class SimpleCallNode(ExprNode):
arg_list_code.append(arg_code)
if func_type.optional_arg_count:
if expected_nargs == actual_nargs:
arg_list_code.append(func_type.op_args.cast_code('NULL'))
if func_type.old_signature:
struct_type = func_type.old_signature.op_args
else:
struct_type = func_type.op_args
optional_args = struct_type.cast_code('NULL')
else:
optional_arg_code = [str(actual_nargs - expected_nargs)]
for formal_arg, actual_arg in args[expected_nargs:actual_nargs]:
......@@ -1578,7 +1582,11 @@ class SimpleCallNode(ExprNode):
# for formal_arg in formal_args[actual_nargs:max_nargs]:
# optional_arg_code.append(formal_arg.type.cast_code('0'))
optional_arg_struct = '{%s}' % ','.join(optional_arg_code)
arg_list_code.append('&' + func_type.op_args.base_type.cast_code(optional_arg_struct))
optional_args = '&' + func_type.op_args.base_type.cast_code(optional_arg_struct)
if func_type.old_signature and \
func_type.old_signature.op_args != func_type.op_args:
optional_args = func_type.old_signature.op_args.cast_code(optional_args)
arg_list_code.append(optional_args)
for actual_arg in self.args[len(formal_args):]:
arg_list_code.append(actual_arg.result_code)
result = "%s(%s)" % (self.function.result_code,
......
......@@ -345,7 +345,7 @@ class CFuncDeclaratorNode(CDeclaratorNode):
scope.declare_var('n', PyrexTypes.c_int_type, self.pos)
for arg in func_type_args[len(func_type_args)-self.optional_arg_count:]:
scope.declare_var(arg.name, arg.type, arg.pos, allow_pyobject = 1)
struct_cname = Naming.opt_arg_prefix + self.base.name
struct_cname = Naming.opt_arg_prefix + env.mangle(self.base.name)
self.op_args_struct = env.global_scope().declare_struct_or_union(name = struct_cname,
kind = 'struct',
scope = scope,
......
......@@ -584,6 +584,7 @@ class CFuncType(CType):
# with_gil boolean Acquire gil around function body
is_cfunction = 1
old_signature = None
def __init__(self, return_type, args, has_varargs = 0,
exception_value = None, exception_check = 0, calling_convention = "",
......@@ -648,6 +649,49 @@ class CFuncType(CType):
return 0
return 1
def compatible_signature_with(self, other_type, as_cmethod = 0):
return self.compatible_signature_with_resolved_type(other_type.resolve(), as_cmethod)
def compatible_signature_with_resolved_type(self, other_type, as_cmethod):
#print "CFuncType.same_c_signature_as_resolved_type:", \
# self, other_type, "as_cmethod =", as_cmethod ###
if other_type is error_type:
return 1
if not other_type.is_cfunction:
return 0
if self.is_overridable != other_type.is_overridable:
return 0
nargs = len(self.args)
if nargs - self.optional_arg_count != len(other_type.args) - other_type.optional_arg_count:
return 0
if self.optional_arg_count < other_type.optional_arg_count:
return 0
# When comparing C method signatures, the first argument
# is exempt from compatibility checking (the proper check
# is performed elsewhere).
for i in range(as_cmethod, len(other_type.args)):
if not self.args[i].type.same_as(
other_type.args[i].type):
return 0
if self.has_varargs != other_type.has_varargs:
return 0
if not self.return_type.same_as(other_type.return_type):
return 0
if not self.same_calling_convention_as(other_type):
return 0
self.old_signature = other_type
if as_cmethod:
self.args[0] = other_type.args[0]
if self.optional_arg_count and \
self.optional_arg_count == other_type.optional_arg_count:
self.op_args = other_type.op_args
print self.op_args, other_type.op_args, self.optional_arg_count, other_type.optional_arg_count
elif self.optional_arg_count:
print self.op_args, other_type.op_args, self.optional_arg_count, other_type.optional_arg_count
return 1
def narrower_c_signature_than(self, other_type, as_cmethod = 0):
return self.narrower_c_signature_than_resolved_type(other_type.resolve(), as_cmethod)
......@@ -698,6 +742,7 @@ class CFuncType(CType):
arg.type.declaration_code("", for_display, pyrex = pyrex))
if self.optional_arg_count:
arg_decl_list.append(self.op_args.declaration_code(Naming.optional_args_cname))
# arg_decl_list.append(c_void_ptr_type.declaration_code(Naming.optional_args_cname))
if self.has_varargs:
arg_decl_list.append("...")
arg_decl_code = string.join(arg_decl_list, ", ")
......
......@@ -1273,11 +1273,14 @@ class CClassScope(ClassScope):
if defining and entry.func_cname:
error(pos, "'%s' already defined" % name)
#print "CClassScope.declare_cfunction: checking signature" ###
if type.same_c_signature_as(entry.type, as_cmethod = 1):
pass
if type.compatible_signature_with(entry.type, as_cmethod = 1):
entry.type = type
elif type.same_c_signature_as(entry.type, as_cmethod = 1):
print "not compatible", name
# if type.narrower_c_signature_than(entry.type, as_cmethod = 1):
# entry.type = type
else:
print "here"
error(pos, "Signature not compatible with previous declaration")
else:
if self.defined:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment