]> granicus.if.org Git - php/commitdiff
Initial support for enforcing prototype of abstract/interface method implementations
authorZeev Suraski <zeev@php.net>
Sat, 29 Mar 2003 11:19:38 +0000 (11:19 +0000)
committerZeev Suraski <zeev@php.net>
Sat, 29 Mar 2003 11:19:38 +0000 (11:19 +0000)
Zend/zend_API.c
Zend/zend_compile.c
Zend/zend_compile.h

index bcc68d03c65d6d164cb1702fa4ee7b13e913fb85..1ab36bf29e4549efaa7f7f01a7a680831c5c8c63 100644 (file)
@@ -1166,6 +1166,7 @@ int zend_register_functions(zend_class_entry *scope, zend_function_entry *functi
                internal_function->scope = scope;
                internal_function->fn_flags = ZEND_ACC_PUBLIC;
                internal_function->ns = EG(active_namespace);
+               internal_function->prototype = NULL;
                if (!internal_function->handler) {
                        zend_error(error_type, "Null function defined as active function");
                        zend_unregister_functions(functions, count, target_function_table TSRMLS_CC);
index 139186ca545f8e254fab38203638f6bdd7fdb018..2730e78b03e93813639c1efb2f3ca6028d8007ee 100644 (file)
@@ -1630,6 +1630,53 @@ static void do_inherit_method(zend_function *function)
 }
 
 
+static zend_bool zend_do_perform_implementation_check(zend_function *fe)
+{
+       zend_op *op, *proto_op;
+
+       if (!fe->common.prototype) {
+               return 1;
+       }
+
+       if ((fe->common.arg_types && !fe->common.prototype->common.arg_types)
+               || (!fe->common.arg_types && fe->common.prototype->common.arg_types)) {
+               return 0;
+       }
+
+       if (fe->common.arg_types) {
+               if (fe->common.arg_types[0] != fe->common.prototype->common.arg_types[0]) {
+                       return 0;
+               }
+               if (memcmp(fe->common.arg_types+1, fe->common.prototype->common.arg_types+1, fe->common.arg_types[0]*sizeof(zend_uchar)) != 0) {
+                       return 0;
+               }
+       }
+
+       if (fe->common.prototype->type == ZEND_INTERNAL_FUNCTION) {
+               return 1; /* nothing further we can do here */
+       }
+       
+       op = fe->op_array.opcodes;
+       proto_op = fe->common.prototype->op_array.opcodes;
+
+       while (proto_op->opcode != ZEND_RAISE_ABSTRACT_ERROR) {
+               if (proto_op->opcode != op->opcode) {
+                       return 0;
+               }
+               switch (proto_op->opcode) {
+                       case ZEND_FETCH_CLASS:
+                               if (zend_binary_zval_strcasecmp(&op->op2.u.constant, &proto_op->op2.u.constant)!=0) {
+                                       return 0;
+                               }
+                               break;
+               }
+               proto_op++;
+               op++;
+       }
+       return 1;
+}
+
+
 static zend_bool do_inherit_method_check(HashTable *child_function_table, zend_function *parent, zend_hash_key *hash_key, zend_class_entry *child_ce)
 {
        zend_uint child_flags;
@@ -1676,6 +1723,16 @@ static zend_bool do_inherit_method_check(HashTable *child_function_table, zend_f
                }
        }
 
+       if (parent_flags & (ZEND_ACC_ABSTRACT|ZEND_ACC_ABSTRACT)) {
+               child->common.prototype = parent;
+       } else if (parent->common.prototype) {
+               child->common.prototype = parent->common.prototype;
+       }
+
+       if (!zend_do_perform_implementation_check(child)) {
+               zend_error(E_COMPILE_ERROR, "Declaration of %s::%s() must be the same as %s::%s()", ZEND_FN_SCOPE_NAME(child), child->common.function_name, ZEND_FN_SCOPE_NAME(child->common.prototype), child->common.prototype->common.function_name);
+       }
+
        return 0;
 }
 
index 2cd1669fcf1dc6a9ce9affb0747e270f860e5538..c522fc01b1d99a0dab83d72f2e4ee7ec8566da90 100644 (file)
@@ -116,13 +116,15 @@ typedef struct _zend_property_info {
 
 
 struct _zend_op_array {
-       zend_uchar type;                        /* MUST be the first element of this struct! */
-
-       zend_uchar *arg_types;          /* MUST be the second element of this struct! */
-       char *function_name;            /* MUST be the third element of this struct! */
-       zend_class_entry *scope;        /* MUST be the fourth element of this struct! */
-       zend_uint fn_flags;                             /* MUST be the fifth element of this struct! */
+       /* Common elements */
+       zend_uchar type;
+       zend_uchar *arg_types;
+       char *function_name;            
+       zend_class_entry *scope;
+       zend_uint fn_flags;
        zend_namespace *ns;
+       union _zend_function *prototype;
+       /* END of common elements */
 
        zend_uint *refcount;
 
@@ -154,13 +156,15 @@ struct _zend_op_array {
 
 
 typedef struct _zend_internal_function {
-       zend_uchar type;                        /* MUST be the first element of this struct! */
-
-       zend_uchar *arg_types;          /* MUST be the second element of this struct! */
-       char *function_name;            /* MUST be the third element of this struct! */
-       zend_class_entry *scope;        /* MUST be the fourth element of this struct! */
-       zend_uint fn_flags;                             /* MUST be the fifth element of this struct! */
+       /* Common elements */
+       zend_uchar type;
+       zend_uchar *arg_types;
+       char *function_name;            
+       zend_class_entry *scope;
+       zend_uint fn_flags;     
        zend_namespace *ns;
+       union _zend_function *prototype;
+       /* END of common elements */
 
        void (*handler)(INTERNAL_FUNCTION_PARAMETERS);
 } zend_internal_function;
@@ -177,6 +181,7 @@ typedef union _zend_function {
                zend_class_entry *scope;
                zend_uint fn_flags;
                zend_namespace *ns;
+               union _zend_function *prototype;
        } common;
        
        zend_op_array op_array;