]> granicus.if.org Git - php/commitdiff
Add 'final'
authorZeev Suraski <zeev@php.net>
Mon, 24 Feb 2003 12:05:58 +0000 (12:05 +0000)
committerZeev Suraski <zeev@php.net>
Mon, 24 Feb 2003 12:05:58 +0000 (12:05 +0000)
Zend/zend_compile.c
Zend/zend_compile.h
Zend/zend_language_parser.y
Zend/zend_language_scanner.l

index e2c714a76237466d80eecb563e3f046e2be5ffb7..9512fb47d49233ed946b8c22fe87f5f8777637a8 100644 (file)
@@ -916,6 +916,9 @@ int zend_do_verify_access_types(znode *current_access_type, znode *new_modifier)
                && ((current_access_type->u.constant.value.lval & ZEND_ACC_PPP_MASK) != (new_modifier->u.constant.value.lval & ZEND_ACC_PPP_MASK))) {
                zend_error(E_COMPILE_ERROR, "Multiple access type modifiers are not allowed");
        }
+       if ((current_access_type->u.constant.value.lval | new_modifier->u.constant.value.lval) && (ZEND_ACC_PRIVATE | ZEND_ACC_FINAL)) {
+               zend_error(E_COMPILE_ERROR, "Cannot use the final modifier on a private class member");
+       }
        return (current_access_type->u.constant.value.lval | new_modifier->u.constant.value.lval);
 }
 
@@ -1602,6 +1605,11 @@ static zend_bool do_inherit_method_check(HashTable *child_function_table, zend_f
                }
                return 1; /* method doesn't exist in child, copy from parent */
        }
+
+       if (parent_flags & ZEND_ACC_FINAL) {
+               zend_error(E_COMPILE_ERROR, "Cannot override final method %s::%s()", ZEND_FN_SCOPE_NAME(parent), child->common.function_name);
+       }
+
        child_flags     = child->common.fn_flags;
        /* You cannot change from static to non static and vice versa.
         */
@@ -1645,6 +1653,9 @@ static zend_bool do_inherit_property_access_check(HashTable *target_ht, zend_pro
        }
 
        if (zend_hash_quick_find(&ce->properties_info, hash_key->arKey, hash_key->nKeyLength, hash_key->h, (void **) &child_info)==SUCCESS) {
+               if (parent_info->flags & ZEND_ACC_FINAL) {
+                       zend_error(E_COMPILE_ERROR, "Cannot override final property %s::$%s", parent_ce->name, hash_key->arKey);
+               }
                if ((child_info->flags & ZEND_ACC_PPP_MASK) > (parent_info->flags & ZEND_ACC_PPP_MASK)) {
                        zend_error(E_COMPILE_ERROR, "Access level to %s::$%s must be %s (as in class %s)%s", ce->name, hash_key->arKey, zend_visibility_string(parent_info->flags), parent_ce->name, (parent_info->flags&ZEND_ACC_PUBLIC) ? "" : " or weaker");
                } else if (child_info->flags & ZEND_ACC_IMPLICIT_PUBLIC) {
index 4a970881f8c5c80a6809e0b70b4df0422b91c6e9..65805f293eb454472ad6b7ae4f3d3578f8e78296 100644 (file)
@@ -91,6 +91,7 @@ typedef struct _zend_brk_cont_element {
 
 #define ZEND_ACC_STATIC                0x01
 #define ZEND_ACC_ABSTRACT      0x02
+#define ZEND_ACC_FINAL         0x04
 
 /* The order of those must be kept - public < protected < private */
 #define ZEND_ACC_PUBLIC                0x10
index 0ed55aa1a7f229abb36adc33fa3e473508700208..04df71db3807100613ce3394eb610bf2b6d4199c 100644 (file)
 %token T_THROW
 %token T_USE
 %token T_GLOBAL
-%right T_STATIC T_ABSTRACT T_PRIVATE T_PROTECTED T_PUBLIC
+%right T_STATIC T_ABSTRACT T_FINAL T_PRIVATE T_PROTECTED T_PUBLIC
 %token T_VAR
 %token T_UNSET
 %token T_ISSET
@@ -510,6 +510,7 @@ member_modifier:
        |       T_PRIVATE                               { $$.u.constant.value.lval = ZEND_ACC_PRIVATE; }
        |       T_STATIC                                { $$.u.constant.value.lval = ZEND_ACC_STATIC; }
        |       T_ABSTRACT                              { $$.u.constant.value.lval = ZEND_ACC_ABSTRACT; }
+       |       T_FINAL                                 { $$.u.constant.value.lval = ZEND_ACC_FINAL; }
 ;
 
 class_variable_declaration:
index 5869132cf5656c7423d96e7beb56b39e648d9b1a..e062689b97ca94ee74e7a56bfb7acb47f0d846e2 100644 (file)
@@ -732,6 +732,10 @@ NAMESPACE_NAME ({LABEL}":")+{LABEL}
        return T_ABSTRACT;
 }
 
+<ST_IN_SCRIPTING>"final" {
+       return T_FINAL;
+}
+
 <ST_IN_SCRIPTING>"private" {
        return T_PRIVATE;
 }