From: Zeev Suraski Date: Wed, 25 Feb 2004 09:25:37 +0000 (+0000) Subject: - Abstract methods cannot have defaults for arguments X-Git-Tag: RELEASE_0_2_0~182 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=36a751840dc6382ae89498ed132911047d47a01b;p=php - Abstract methods cannot have defaults for arguments - Make function foo($a, $b=null) satisfy both foo($a) and foo($a, $b) prototypes --- diff --git a/Zend/zend_API.c b/Zend/zend_API.c index 3a82e9a9bb..90c12fa826 100644 --- a/Zend/zend_API.c +++ b/Zend/zend_API.c @@ -1220,11 +1220,14 @@ ZEND_API int zend_register_functions(zend_class_entry *scope, zend_function_entr if (ptr->arg_info) { internal_function->arg_info = ptr->arg_info+1; internal_function->num_args = ptr->num_args; + /* Currently you cannot denote that the function can accept less arguments than num_args */ + internal_function->required_num_args = ptr->num_args; internal_function->pass_rest_by_reference = ptr->arg_info[0].pass_by_reference; internal_function->return_reference = ptr->arg_info[0].return_reference; } else { internal_function->arg_info = NULL; internal_function->num_args = 0; + internal_function->required_num_args = 0; internal_function->pass_rest_by_reference = 0; internal_function->return_reference = 0; } diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index d06ca63996..1826221dfc 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -1135,9 +1135,15 @@ void zend_do_receive_arg(zend_uchar op, znode *var, znode *offset, znode *initia opline->opcode = op; opline->result = *var; opline->op1 = *offset; - if ((op == ZEND_RECV_INIT)) { + if (op == ZEND_RECV_INIT) { + if ((CG(active_class_entry) && CG(active_class_entry)->ce_flags & ZEND_ACC_INTERFACE) + || CG(active_op_array)->fn_flags & ZEND_ACC_ABSTRACT) { + CG(active_op_array)->num_args--; /* invalidate the current arg_info entry */ + zend_error(E_COMPILE_ERROR, "Abstract methods cannot have default values for arguments"); + } opline->op2 = *initialization; } else { + CG(active_op_array)->required_num_args = CG(active_op_array)->num_args; SET_UNUSED(opline->op2); } CG(active_op_array)->arg_info = erealloc(CG(active_op_array)->arg_info, sizeof(zend_arg_info)*(CG(active_op_array)->num_args)); @@ -1710,34 +1716,49 @@ static void do_inherit_method(zend_function *function) static zend_bool zend_do_perform_implementation_check(zend_function *fe) { zend_uint i; + zend_function *proto = fe->common.prototype; - if (!fe->common.prototype) { + if (!proto) { return 1; } - if (fe->common.num_args != fe->common.prototype->common.num_args - || fe->common.pass_rest_by_reference != fe->common.prototype->common.pass_rest_by_reference) { + /* check number of arguments */ + if (proto->common.num_args < fe->common.required_num_args + || proto->common.num_args > fe->common.num_args) { + return 0; + } + + if (proto->common.pass_rest_by_reference + && !fe->common.pass_rest_by_reference) { return 0; } - if (fe->common.prototype->common.return_reference != ZEND_RETURN_REFERENCE_AGNOSTIC - && fe->common.return_reference != fe->common.prototype->common.return_reference) { + if (proto->common.return_reference != ZEND_RETURN_REFERENCE_AGNOSTIC + && fe->common.return_reference != proto->common.return_reference) { return 0; } - for (i=0; i< fe->common.num_args; i++) { - if (ZEND_LOG_XOR(fe->common.arg_info[i].class_name, fe->common.prototype->common.arg_info[i].class_name)) { + for (i=0; i < proto->common.num_args; i++) { + if (ZEND_LOG_XOR(fe->common.arg_info[i].class_name, proto->common.arg_info[i].class_name)) { /* Only one has a type hint and the other one doesn't */ return 0; } if (fe->common.arg_info[i].class_name - && strcmp(fe->common.arg_info[i].class_name, fe->common.prototype->common.arg_info[i].class_name)!=0) { + && strcmp(fe->common.arg_info[i].class_name, proto->common.arg_info[i].class_name)!=0) { return 0; } - if (fe->common.arg_info[i].pass_by_reference != fe->common.prototype->common.arg_info[i].pass_by_reference) { + if (fe->common.arg_info[i].pass_by_reference != proto->common.arg_info[i].pass_by_reference) { return 0; } } + + if (proto->common.pass_rest_by_reference) { + for (i=proto->common.num_args; i < fe->common.num_args; i++) { + if (!fe->common.arg_info[i].pass_by_reference) { + return 0; + } + } + } return 1; } diff --git a/Zend/zend_compile.h b/Zend/zend_compile.h index 65f4d75421..bb271d9dc2 100644 --- a/Zend/zend_compile.h +++ b/Zend/zend_compile.h @@ -151,6 +151,7 @@ struct _zend_op_array { zend_uint fn_flags; union _zend_function *prototype; zend_uint num_args; + zend_uint required_num_args; zend_arg_info *arg_info; zend_bool pass_rest_by_reference; unsigned char return_reference; @@ -201,6 +202,7 @@ typedef struct _zend_internal_function { zend_uint fn_flags; union _zend_function *prototype; zend_uint num_args; + zend_uint required_num_args; zend_arg_info *arg_info; zend_bool pass_rest_by_reference; unsigned char return_reference; @@ -221,6 +223,7 @@ typedef union _zend_function { zend_uint fn_flags; union _zend_function *prototype; zend_uint num_args; + zend_uint required_num_args; zend_arg_info *arg_info; zend_bool pass_rest_by_reference; unsigned char return_reference; diff --git a/Zend/zend_opcode.c b/Zend/zend_opcode.c index da4f62e197..e4e3901f3d 100644 --- a/Zend/zend_opcode.c +++ b/Zend/zend_opcode.c @@ -74,6 +74,7 @@ void init_op_array(zend_op_array *op_array, zend_uchar type, int initial_ops_siz op_array->arg_info = NULL; op_array->num_args = 0; + op_array->required_num_args = 0; op_array->scope = NULL;