From 6317e26576b371b9d7dbce81130ff33a4010f28f Mon Sep 17 00:00:00 2001 From: Zeev Suraski Date: Mon, 10 Feb 2003 12:46:58 +0000 Subject: [PATCH] - Treat $this->foo inside class X as an implicit 'public $foo' if X::$foo is not explicitly declared - Forbid multiple declaration of the same variable --- Zend/zend_compile.c | 20 ++++++++++++++++---- Zend/zend_compile.h | 3 ++- Zend/zend_language_parser.y | 8 ++++---- 3 files changed, 22 insertions(+), 9 deletions(-) diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index df345cbcb1..4156e7b552 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -1619,6 +1619,8 @@ 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 ((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) { + return 1; /* Inherit from the parent */ } return 0; /* Don't copy from parent */ } else { @@ -2209,12 +2211,18 @@ void mangle_property_name(char **dest, int *dest_length, char *src1, int src1_le } -void zend_do_declare_property(znode *var_name, znode *value TSRMLS_DC) +void zend_do_declare_property(znode *var_name, znode *value, zend_uint access_type TSRMLS_DC) { zval *property; zend_property_info property_info; + zend_property_info *existing_property_info; HashTable *target_symbol_table; + if (zend_hash_find(&CG(active_class_entry)->properties_info, var_name->u.constant.value.str.val, var_name->u.constant.value.str.len+1, (void **) &existing_property_info)==SUCCESS) { + if (!(existing_property_info->flags & ZEND_ACC_IMPLICIT_PUBLIC)) { + zend_error(E_COMPILE_ERROR, "Cannot redeclare %s::$%s", CG(active_class_entry)->name, var_name->u.constant.value.str.val); + } + } ALLOC_ZVAL(property); if (value) { @@ -2224,13 +2232,13 @@ void zend_do_declare_property(znode *var_name, znode *value TSRMLS_DC) property->type = IS_NULL; } - if (CG(access_type) & ZEND_ACC_STATIC) { + if (access_type & ZEND_ACC_STATIC) { target_symbol_table = CG(active_class_entry)->static_members; } else { target_symbol_table = &CG(active_class_entry)->default_properties; } - switch (CG(access_type) & ZEND_ACC_PPP_MASK) { + switch (access_type & ZEND_ACC_PPP_MASK) { case ZEND_ACC_PRIVATE: { char *priv_name; int priv_name_length; @@ -2257,7 +2265,7 @@ void zend_do_declare_property(znode *var_name, znode *value TSRMLS_DC) property_info.name_length = var_name->u.constant.value.str.len; break; } - property_info.flags = CG(access_type); + property_info.flags = access_type; property_info.h = zend_get_hash_value(property_info.name, property_info.name_length+1); zend_hash_update(&CG(active_class_entry)->properties_info, var_name->u.constant.value.str.val, var_name->u.constant.value.str.len+1, &property_info, sizeof(zend_property_info), NULL); @@ -2326,6 +2334,10 @@ void zend_do_fetch_property(znode *result, znode *object, znode *property TSRMLS break; } *result = opline_ptr->result; + if (CG(active_class_entry) + && !zend_hash_exists(&CG(active_class_entry)->properties_info, property->u.constant.value.str.val, property->u.constant.value.str.len+1)) { + zend_do_declare_property(property, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_IMPLICIT_PUBLIC TSRMLS_CC); + } return; } } diff --git a/Zend/zend_compile.h b/Zend/zend_compile.h index fa54846ed1..f590044d48 100644 --- a/Zend/zend_compile.h +++ b/Zend/zend_compile.h @@ -99,6 +99,7 @@ typedef struct _zend_brk_cont_element { #define ZEND_ACC_PPP_MASK (ZEND_ACC_PUBLIC | ZEND_ACC_PROTECTED | ZEND_ACC_PRIVATE) #define ZEND_ACC_CHANGED 0x80 +#define ZEND_ACC_IMPLICIT_PUBLIC 0x100 char *zend_visibility_string(zend_uint fn_flags); @@ -357,7 +358,7 @@ void zend_do_default_before_statement(znode *case_list, znode *default_token TSR void zend_do_begin_class_declaration(znode *class_token, znode *class_name, znode *parent_class_name TSRMLS_DC); void zend_do_end_class_declaration(znode *class_token TSRMLS_DC); -void zend_do_declare_property(znode *var_name, znode *value TSRMLS_DC); +void zend_do_declare_property(znode *var_name, znode *value, zend_uint access_type TSRMLS_DC); void zend_do_declare_class_constant(znode *var_name, znode *value TSRMLS_DC); void zend_do_fetch_property(znode *result, znode *object, znode *property TSRMLS_DC); diff --git a/Zend/zend_language_parser.y b/Zend/zend_language_parser.y index 672b5f4d04..2310a655af 100644 --- a/Zend/zend_language_parser.y +++ b/Zend/zend_language_parser.y @@ -474,10 +474,10 @@ access_modifier: ; class_variable_declaration: - class_variable_declaration ',' T_VARIABLE { zend_do_declare_property(&$3, NULL TSRMLS_CC); } - | class_variable_declaration ',' T_VARIABLE '=' static_scalar { zend_do_declare_property(&$3, &$5 TSRMLS_CC); } - | T_VARIABLE { zend_do_declare_property(&$1, NULL TSRMLS_CC); } - | T_VARIABLE '=' static_scalar { zend_do_declare_property(&$1, &$3 TSRMLS_CC); } + class_variable_declaration ',' T_VARIABLE { zend_do_declare_property(&$3, NULL, CG(access_type) TSRMLS_CC); } + | class_variable_declaration ',' T_VARIABLE '=' static_scalar { zend_do_declare_property(&$3, &$5, CG(access_type) TSRMLS_CC); } + | T_VARIABLE { zend_do_declare_property(&$1, NULL, CG(access_type) TSRMLS_CC); } + | T_VARIABLE '=' static_scalar { zend_do_declare_property(&$1, &$3, CG(access_type) TSRMLS_CC); } ; class_constant_declaration: -- 2.50.1