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 {
}
-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) {
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;
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);
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;
}
}
#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);
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);
;
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: