]> granicus.if.org Git - php/commitdiff
- Commit Marcus' cleanup of abstract and static inheritance and improve
authorAndi Gutmans <andi@php.net>
Sat, 23 Nov 2002 20:44:12 +0000 (20:44 +0000)
committerAndi Gutmans <andi@php.net>
Sat, 23 Nov 2002 20:44:12 +0000 (20:44 +0000)
- error messages

Zend/zend_API.c
Zend/zend_API.h
Zend/zend_builtin_functions.c
Zend/zend_compile.c
Zend/zend_compile.h
Zend/zend_execute.c
Zend/zend_execute.h
Zend/zend_language_parser.y
Zend/zend_object_handlers.c

index 47a284da16b28f15596d2540553781120ca0b7cc..548bfe41327e42eb4e83b0a7fc6e844784de3f84 100644 (file)
@@ -1030,7 +1030,7 @@ ZEND_API int zend_startup_module(zend_module_entry *module)
 
 
 /* registers all functions in *library_functions in the function hash */
-int zend_register_functions(zend_function_entry *functions, HashTable *function_table, int type TSRMLS_DC)
+int zend_register_functions(zend_class_entry *scope, zend_function_entry *functions, HashTable *function_table, int type TSRMLS_DC)
 {
        zend_function_entry *ptr = functions;
        zend_function function;
@@ -1054,8 +1054,8 @@ int zend_register_functions(zend_function_entry *functions, HashTable *function_
                internal_function->handler = ptr->handler;
                internal_function->arg_types = ptr->func_arg_types;
                internal_function->function_name = ptr->fname;
-               internal_function->scope = NULL;
-               internal_function->is_static = 0;
+               internal_function->scope = scope;
+               internal_function->fn_flags = 0;
                if (!internal_function->handler) {
                        zend_error(error_type, "Null function defined as active function");
                        zend_unregister_functions(functions, count, target_function_table TSRMLS_CC);
@@ -1114,7 +1114,7 @@ ZEND_API int zend_register_module(zend_module_entry *module)
 #if 0
        zend_printf("%s:  Registering module %d\n", module->name, module->module_number);
 #endif
-       if (module->functions && zend_register_functions(module->functions, NULL, module->type TSRMLS_CC)==FAILURE) {
+       if (module->functions && zend_register_functions(NULL, module->functions, NULL, module->type TSRMLS_CC)==FAILURE) {
                zend_error(E_CORE_WARNING,"%s:  Unable to register functions, unable to load", module->name);
                return FAILURE;
        }
@@ -1246,7 +1246,7 @@ ZEND_API zend_class_entry *zend_register_internal_class(zend_class_entry *orig_c
        zend_hash_init(&class_entry->class_table, 10, NULL, ZEND_CLASS_DTOR, 1);
 
        if (class_entry->builtin_functions) {
-               zend_register_functions(class_entry->builtin_functions, &class_entry->function_table, MODULE_PERSISTENT TSRMLS_CC);
+               zend_register_functions(class_entry, class_entry->builtin_functions, &class_entry->function_table, MODULE_PERSISTENT TSRMLS_CC);
        }
 
        zend_hash_update(CG(class_table), lowercase_name, class_entry->name_length+1, &class_entry, sizeof(zend_class_entry *), NULL);
@@ -1309,7 +1309,7 @@ ZEND_API int zend_disable_function(char *function_name, uint function_name_lengt
                return FAILURE;
        }
        disabled_function[0].fname = function_name;
-       return zend_register_functions(disabled_function, CG(function_table), MODULE_PERSISTENT TSRMLS_CC);
+       return zend_register_functions(NULL, disabled_function, CG(function_table), MODULE_PERSISTENT TSRMLS_CC);
 }
 
 zend_bool zend_is_callable(zval *callable, zend_bool syntax_only, char **callable_name)
index 09ca6e7aabb43e241a53edf7133a56d9951aaf27..530d2400aea323d4b2f883c95659294dace58c5d 100644 (file)
@@ -124,7 +124,7 @@ ZEND_API char *zend_zval_type_name(zval *arg);
 
 /* End of parameter parsing API -- andrei */
 
-int zend_register_functions(zend_function_entry *functions, HashTable *function_table, int type TSRMLS_DC);
+int zend_register_functions(zend_class_entry *scope, zend_function_entry *functions, HashTable *function_table, int type TSRMLS_DC);
 void zend_unregister_functions(zend_function_entry *functions, int count, HashTable *function_table TSRMLS_DC);
 ZEND_API int zend_register_module(zend_module_entry *module_entry);
 
index d87835a7706dafb361ac7cf2132f8c24ec18f261..c5ca12821121123b4a5e28dda9f45c65e93572f8 100644 (file)
@@ -141,7 +141,7 @@ static zend_function_entry builtin_functions[] = {
 
 int zend_startup_builtin_functions(TSRMLS_D)
 {
-       return zend_register_functions(builtin_functions, NULL, MODULE_PERSISTENT TSRMLS_CC);
+       return zend_register_functions(NULL, builtin_functions, NULL, MODULE_PERSISTENT TSRMLS_CC);
 }
 
 
index d0b6d65e9128cfcaccab2d7ee930325245d5b54d..1c283d01680f9eaf1083035e52fc8306c159682d 100644 (file)
@@ -909,7 +909,7 @@ void zend_do_free(znode *op1 TSRMLS_DC)
        }               
 }
 
-void zend_do_begin_function_declaration(znode *function_token, znode *function_name, int is_method, int return_reference, int is_static  TSRMLS_DC)
+void zend_do_begin_function_declaration(znode *function_token, znode *function_name, int is_method, int return_reference, int fn_flags  TSRMLS_DC)
 {
        zend_op_array op_array;
        char *name = function_name->u.constant.value.str.val;
@@ -924,7 +924,7 @@ void zend_do_begin_function_declaration(znode *function_token, znode *function_n
        op_array.function_name = name;
        op_array.arg_types = NULL;
        op_array.return_reference = return_reference;
-       op_array.is_static = is_static;
+       op_array.fn_flags = fn_flags;
 
        op_array.scope = CG(active_class_entry);
 
@@ -1529,9 +1529,29 @@ static void do_inherit_parent_constructor(zend_class_entry *ce)
        ce->__call = ce->parent->__call;
 }
 
+static zend_bool do_inherit_method_check(zend_function *child, zend_function *parent) {
+       register zend_uint child_flags  = child->common.fn_flags;
+       register zend_uint parent_flags = parent->common.fn_flags;
+
+       /* You cannot change from static to non static and vice versa.
+        */
+       if ((child_flags&FN_IS_STATIC) != (parent_flags&FN_IS_STATIC)) {
+               if (child->common.fn_flags & FN_IS_STATIC) {
+                       zend_error(E_COMPILE_ERROR, "Cannot make non static method %s::%s() static in class %s", FN_SCOPE_NAME(parent), child->common.function_name, FN_SCOPE_NAME(child));
+               } else {
+                       zend_error(E_COMPILE_ERROR, "Cannot make static method %s::%s() non static in class %s", FN_SCOPE_NAME(parent), child->common.function_name, FN_SCOPE_NAME(child));
+               }
+       }
+       /* Disallow makeing an inherited method abstract.
+        */
+       if (child_flags & FN_ABSTRACT) {
+               zend_error(E_COMPILE_ERROR, "Cannot redeclare %s::%s() abstract in class %s", FN_SCOPE_NAME(parent), child->common.function_name, FN_SCOPE_NAME(child));
+       }
+       return SUCCESS;
+}
+
 void zend_do_inheritance(zend_class_entry *ce, zend_class_entry *parent_ce)
 {
-       zend_function tmp_zend_function;
        zval *tmp;
 
        /* Perform inheritance */
@@ -1540,7 +1560,7 @@ void zend_do_inheritance(zend_class_entry *ce, zend_class_entry *parent_ce)
        /* STATIC_MEMBERS_FIXME */
 /*     zend_hash_merge(ce->static_members, parent_ce->static_members, (void (*)(void *)) zval_add_ref, (void *) &tmp, sizeof(zval *), 0); */
        zend_hash_merge(&ce->constants_table, &parent_ce->constants_table, (void (*)(void *)) zval_add_ref, (void *) &tmp, sizeof(zval *), 0);
-       zend_hash_merge(&ce->function_table, &parent_ce->function_table, (void (*)(void *)) function_add_ref, &tmp_zend_function, sizeof(zend_function), 0);
+       zend_hash_merge_ex(&ce->function_table, &parent_ce->function_table, (void (*)(void *)) function_add_ref, sizeof(zend_function), (zend_bool (*)(void *, void *))do_inherit_method_check);
        ce->parent = parent_ce;
        if (!ce->handle_property_get)
           ce->handle_property_get      = parent_ce->handle_property_get;
index cbee8622b346e2d2f6faddf02a1da095c9b89f20..fc0a931d492ed791aa635801a5cb087c77e0afc7 100644 (file)
@@ -88,13 +88,17 @@ typedef struct _zend_brk_cont_element {
 } zend_brk_cont_element;
 
 
+#define FN_IS_STATIC 0x00000001
+
+#define FN_ABSTRACT  0x00000002
+
 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_bool is_static;            /* MUST be the fifth element of this struct! */
+       int fn_flags;                           /* MUST be the fifth element of this struct! */
 
        zend_uint *refcount;
 
@@ -129,11 +133,13 @@ typedef struct _zend_internal_function {
        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_bool is_static;            /* MUST be the fifth element of this struct! */
+       int fn_flags;                           /* MUST be the fifth element of this struct! */
 
        void (*handler)(INTERNAL_FUNCTION_PARAMETERS);
 } zend_internal_function;
 
+#define FN_SCOPE_NAME(function)  ((function) && (function)->common.scope ? (function)->common.scope->name : "")
+
 typedef union _zend_function {
        zend_uchar type;        /* MUST be the first element of this struct! */
 
@@ -142,7 +148,7 @@ typedef union _zend_function {
                zend_uchar *arg_types;
                char *function_name;
                zend_class_entry *scope;
-               zend_bool is_static;
+               int fn_flags;
        } common;
        
        zend_op_array op_array;
@@ -289,7 +295,7 @@ void zend_do_add_char(znode *result, znode *op1, znode *op2 TSRMLS_DC);
 void zend_do_add_string(znode *result, znode *op1, znode *op2 TSRMLS_DC);
 void zend_do_add_variable(znode *result, znode *op1, znode *op2 TSRMLS_DC);
 
-void zend_do_begin_function_declaration(znode *function_token, znode *function_name, int is_method, int return_reference, int is_static TSRMLS_DC);
+void zend_do_begin_function_declaration(znode *function_token, znode *function_name, int is_method, int return_reference, int fn_flags TSRMLS_DC);
 void zend_do_end_function_declaration(znode *function_token TSRMLS_DC);
 void zend_do_receive_arg(zend_uchar op, znode *var, znode *offset, znode *initialization, zend_uchar pass_type TSRMLS_DC);
 int zend_do_begin_function_call(znode *function_name TSRMLS_DC);
index bfa36457d59b6af19f64d63152af26525ce2aae3..d918f8e5d7e2b8c3280270016a46b71eea70334b 100644 (file)
@@ -2269,14 +2269,14 @@ int zend_init_method_call_handler(ZEND_OPCODE_HANDLER_ARGS)
                        
        if (EX(object) && EX(object)->type == IS_OBJECT) {
                EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(EX(object), function_name_strval, function_name_strlen TSRMLS_CC);
+               if (!EX(fbc)) {
+                       zend_error(E_ERROR, "Call to undefined function: %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), function_name_strval);
+               }
        } else {
-               zend_error(E_ERROR, "Call to a member function on a non-object");
-       }
-       if (!EX(fbc)) {
-               zend_error(E_ERROR, "Call to undefined function:  %s()", function_name_strval);
+               zend_error(E_ERROR, "Call to a member function %s() on a non-object", function_name_strval);
        }
 
-       if (EX(fbc)->common.is_static) {
+       if (EX(fbc)->common.fn_flags & FN_IS_STATIC) {
                EX(object) = NULL;
        } else {
                if (!PZVAL_IS_REF(EX(object))) {
@@ -2336,7 +2336,7 @@ int zend_init_static_method_call_handler(ZEND_OPCODE_HANDLER_ARGS)
        EX(calling_scope) = ce;
 
        if (zend_hash_find(&ce->function_table, function_name_strval, function_name_strlen+1, (void **) &function)==FAILURE) {
-               zend_error(E_ERROR, "Call to undefined function:  %s()", function_name_strval);
+               zend_error(E_ERROR, "Call to undefined function: %s::%s()", ce->name, function_name_strval);
        }
 
        if (!is_const) {
@@ -2346,7 +2346,7 @@ int zend_init_static_method_call_handler(ZEND_OPCODE_HANDLER_ARGS)
 
        EX(fbc) = function;
 
-       if (function->common.is_static) {
+       if (function->common.fn_flags & FN_IS_STATIC) {
                EX(object) = NULL;
        } else {
                if ((EX(object) = EG(This))) {
index e578842231bfde48fb48a95222d225bc62a396c2..0e13099d993a6cf00ed8f349e3642ce8e9b1f6b2 100644 (file)
@@ -162,6 +162,11 @@ void zend_assign_to_variable_reference(znode *result, zval **variable_ptr_ptr, z
 #define IS_OVERLOADED_OBJECT 1
 #define IS_STRING_OFFSET 2
 
+/* The following tries to resolve the classname of a zval of type object.
+ * Since it is slow it should be only used in error messages.
+ */
+#define Z_OBJ_CLASS_NAME_P(zval) ((zval) && (zval)->type == IS_OBJECT && Z_OBJ_HT_P(zval)->get_class_entry != NULL && Z_OBJ_HT_P(zval)->get_class_entry(zval TSRMLS_CC) ? Z_OBJ_HT_P(zval)->get_class_entry(zval TSRMLS_CC)->name : "")
+
 END_EXTERN_C()
 
 #endif /* ZEND_EXECUTE_H */
index 89217ee7d4471628f3b8828e044c6e7fbaba00c0..43d878993dc620a3dfcb47bd51db8eb7ea93d6dc 100644 (file)
@@ -442,12 +442,12 @@ class_statement:
        |       is_static T_FUNCTION { $2.u.opline_num = CG(zend_lineno); } is_reference T_STRING { zend_do_begin_function_declaration(&$2, &$5, 1, $4.op_type, $1.u.constant.value.lval TSRMLS_CC); } '(' 
                        parameter_list ')' '{' inner_statement_list '}' { zend_do_end_function_declaration(&$2 TSRMLS_CC); }
        |       T_CLASS T_STRING extends_from '{' { zend_do_begin_class_declaration(&$1, &$2, &$3 TSRMLS_CC); } class_statement_list '}' { zend_do_end_class_declaration(&$1 TSRMLS_CC); }
-       |       T_ABSTRACT T_FUNCTION { $2.u.opline_num = CG(zend_lineno); } is_reference T_STRING { zend_do_begin_function_declaration(&$2, &$5, 1, $4.op_type, $1.u.constant.value.lval TSRMLS_CC); } '(' 
+       |       T_ABSTRACT T_FUNCTION { $2.u.opline_num = CG(zend_lineno); } is_reference T_STRING { zend_do_begin_function_declaration(&$2, &$5, 1, $4.op_type, FN_ABSTRACT TSRMLS_CC); } '(' 
                        parameter_list ')' { zend_do_abstract_method(TSRMLS_C); zend_do_end_function_declaration(&$2 TSRMLS_CC); }
 ;
 
 is_static:
-               T_STATIC        { $$.u.constant.value.lval = 1; }
+               T_STATIC        { $$.u.constant.value.lval = FN_IS_STATIC; }
        |       /* empty */ { $$.u.constant.value.lval = 0; }
 ;
        
index 9a3642f0506a9e657703ba7815100e0f981be77f..04ba0bd1bf09966dd6415d385204f14c7779194f 100644 (file)
@@ -397,8 +397,8 @@ static union _zend_function *zend_std_get_method(zval *object, char *method_name
                        call_user_call->type = ZEND_INTERNAL_FUNCTION;
                        call_user_call->handler = zend_std_call_user_call;
                        call_user_call->arg_types = NULL;
-                       call_user_call->scope = NULL;
-                       call_user_call->is_static = 0;
+                       call_user_call->scope = zobj->ce;
+                       call_user_call->fn_flags = 0;
                        call_user_call->function_name = estrndup(method_name, method_len);
 
                        free_alloca(lc_method_name);