]> granicus.if.org Git - php/commitdiff
- Abstract methods cannot have defaults for arguments
authorZeev Suraski <zeev@php.net>
Wed, 25 Feb 2004 09:25:37 +0000 (09:25 +0000)
committerZeev Suraski <zeev@php.net>
Wed, 25 Feb 2004 09:25:37 +0000 (09:25 +0000)
- Make function foo($a, $b=null) satisfy both foo($a) and foo($a, $b)
  prototypes

Zend/zend_API.c
Zend/zend_compile.c
Zend/zend_compile.h
Zend/zend_opcode.c

index 3a82e9a9bb1867dcbf7e614f8e02a9097d238fe3..90c12fa8267cd6a0b07f1c51ab7ad0ce082f38b1 100644 (file)
@@ -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;
                }
index d06ca63996d5abf841009f0ab6eb7d511b6d7a87..1826221dfcb4a435ee52c7c79d4383ac9005fb6d 100644 (file)
@@ -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;
 }
 
index 65f4d75421c7a25d21eb4b75efd0287fb88366c7..bb271d9dc289991993c55c7c939c2de3fba6422c 100644 (file)
@@ -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;
index da4f62e197c84b24355f19311caf6a9ad9802683..e4e3901f3d44542835a92a9465a9f2ba33bc07fd 100644 (file)
@@ -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;