Permalink
Browse files

- Abstract methods cannot have defaults for arguments

- Make function foo($a, $b=null) satisfy both foo($a) and foo($a, $b)
  prototypes
  • Loading branch information...
1 parent 0cfb59f commit 36a751840dc6382ae89498ed132911047d47a01b @zsuraski zsuraski committed Feb 25, 2004
Showing with 38 additions and 10 deletions.
  1. +3 −0 Zend/zend_API.c
  2. +31 −10 Zend/zend_compile.c
  3. +3 −0 Zend/zend_compile.h
  4. +1 −0 Zend/zend_opcode.c
View
@@ -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;
}
View
@@ -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;
}
View
@@ -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;
View
@@ -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;

0 comments on commit 36a7518

Please sign in to comment.