From 535aa63293341a662ba534d17cc17bd7c00d56e4 Mon Sep 17 00:00:00 2001 From: Zeev Suraski Date: Mon, 24 Feb 2003 12:05:58 +0000 Subject: [PATCH] Add 'final' --- Zend/zend_compile.c | 11 +++++++++++ Zend/zend_compile.h | 1 + Zend/zend_language_parser.y | 3 ++- Zend/zend_language_scanner.l | 4 ++++ 4 files changed, 18 insertions(+), 1 deletion(-) diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index e2c714a762..9512fb47d4 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -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) { diff --git a/Zend/zend_compile.h b/Zend/zend_compile.h index 4a970881f8..65805f293e 100644 --- a/Zend/zend_compile.h +++ b/Zend/zend_compile.h @@ -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 diff --git a/Zend/zend_language_parser.y b/Zend/zend_language_parser.y index 0ed55aa1a7..04df71db38 100644 --- a/Zend/zend_language_parser.y +++ b/Zend/zend_language_parser.y @@ -112,7 +112,7 @@ %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: diff --git a/Zend/zend_language_scanner.l b/Zend/zend_language_scanner.l index 5869132cf5..e062689b97 100644 --- a/Zend/zend_language_scanner.l +++ b/Zend/zend_language_scanner.l @@ -732,6 +732,10 @@ NAMESPACE_NAME ({LABEL}":")+{LABEL} return T_ABSTRACT; } +"final" { + return T_FINAL; +} + "private" { return T_PRIVATE; } -- 2.50.1