diff --git a/Zend/tests/traits/language012.phpt b/Zend/tests/traits/language012.phpt new file mode 100644 index 00000000000..481dd64ec7b --- /dev/null +++ b/Zend/tests/traits/language012.phpt @@ -0,0 +1,27 @@ +--TEST-- +Statics should work in traits, too. +--FILE-- +inc(); +$o->inc(); + +?> +--EXPECTF-- +1 +2 diff --git a/Zend/tests/traits/language013.phpt b/Zend/tests/traits/language013.phpt new file mode 100644 index 00000000000..a55cbbed342 --- /dev/null +++ b/Zend/tests/traits/language013.phpt @@ -0,0 +1,37 @@ +--TEST-- +Statics work like expected for language-based copy'n'paste. No link between methods from the same trait. +--FILE-- +inc(); +$o->inc(); + +$p = new C2(); +$p->inc(); +$p->inc(); + +?> +--EXPECTF-- +1 +2 +1 +2 diff --git a/Zend/zend_closures.c b/Zend/zend_closures.c index 20cbd906695..b40b9222db4 100644 --- a/Zend/zend_closures.c +++ b/Zend/zend_closures.c @@ -398,43 +398,6 @@ void zend_register_closure_ce(TSRMLS_D) /* {{{ */ } /* }}} */ -static int zval_copy_static_var(zval **p TSRMLS_DC, int num_args, va_list args, zend_hash_key *key) /* {{{ */ -{ - HashTable *target = va_arg(args, HashTable*); - zend_bool is_ref; - - if (Z_TYPE_PP(p) & (IS_LEXICAL_VAR|IS_LEXICAL_REF)) { - is_ref = Z_TYPE_PP(p) & IS_LEXICAL_REF; - - if (!EG(active_symbol_table)) { - zend_rebuild_symbol_table(TSRMLS_C); - } - if (zend_hash_quick_find(EG(active_symbol_table), key->arKey, key->nKeyLength, key->h, (void **) &p) == FAILURE) { - if (is_ref) { - zval *tmp; - - ALLOC_INIT_ZVAL(tmp); - Z_SET_ISREF_P(tmp); - zend_hash_quick_add(EG(active_symbol_table), key->arKey, key->nKeyLength, key->h, &tmp, sizeof(zval*), (void**)&p); - } else { - p = &EG(uninitialized_zval_ptr); - zend_error(E_NOTICE,"Undefined variable: %s", key->arKey); - } - } else { - if (is_ref) { - SEPARATE_ZVAL_TO_MAKE_IS_REF(p); - } else if (Z_ISREF_PP(p)) { - SEPARATE_ZVAL(p); - } - } - } - if (zend_hash_quick_add(target, key->arKey, key->nKeyLength, key->h, p, sizeof(zval*), NULL) == SUCCESS) { - Z_ADDREF_PP(p); - } - return ZEND_HASH_APPLY_KEEP; -} -/* }}} */ - ZEND_API void zend_create_closure(zval *res, zend_function *func, zend_class_entry *scope, zval *this_ptr TSRMLS_DC) /* {{{ */ { zend_closure *closure; diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index 879a1dab665..87e494110b7 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -3476,8 +3476,9 @@ static void zend_traits_duplicate_function(zend_function *fe, char *newname) zval tmpZval; ALLOC_HASHTABLE(tmpHash); - zend_hash_init(tmpHash, 2, NULL, ZVAL_PTR_DTOR, 0); - zend_hash_copy(tmpHash, fe->op_array.static_variables, ZVAL_COPY_CTOR, &tmpZval, sizeof(zval)); + zend_hash_init(tmpHash, zend_hash_num_elements(fe->op_array.static_variables), NULL, ZVAL_PTR_DTOR, 0); + zend_hash_apply_with_arguments(tmpHash TSRMLS_CC, (apply_func_args_t)zval_copy_static_var, 1, fe->op_array.static_variables); + fe->op_array.static_variables = tmpHash; } diff --git a/Zend/zend_variables.c b/Zend/zend_variables.c index f6f1ea728e0..67b08b48029 100644 --- a/Zend/zend_variables.c +++ b/Zend/zend_variables.c @@ -188,6 +188,43 @@ ZEND_API void _zval_internal_ptr_dtor_wrapper(zval **zval_ptr) } #endif +ZEND_API int zval_copy_static_var(zval **p TSRMLS_DC, int num_args, va_list args, zend_hash_key *key) /* {{{ */ +{ + HashTable *target = va_arg(args, HashTable*); + zend_bool is_ref; + + if (Z_TYPE_PP(p) & (IS_LEXICAL_VAR|IS_LEXICAL_REF)) { + is_ref = Z_TYPE_PP(p) & IS_LEXICAL_REF; + + if (!EG(active_symbol_table)) { + zend_rebuild_symbol_table(TSRMLS_C); + } + if (zend_hash_quick_find(EG(active_symbol_table), key->arKey, key->nKeyLength, key->h, (void **) &p) == FAILURE) { + if (is_ref) { + zval *tmp; + + ALLOC_INIT_ZVAL(tmp); + Z_SET_ISREF_P(tmp); + zend_hash_quick_add(EG(active_symbol_table), key->arKey, key->nKeyLength, key->h, &tmp, sizeof(zval*), (void**)&p); + } else { + p = &EG(uninitialized_zval_ptr); + zend_error(E_NOTICE,"Undefined variable: %s", key->arKey); + } + } else { + if (is_ref) { + SEPARATE_ZVAL_TO_MAKE_IS_REF(p); + } else if (Z_ISREF_PP(p)) { + SEPARATE_ZVAL(p); + } + } + } + if (zend_hash_quick_add(target, key->arKey, key->nKeyLength, key->h, p, sizeof(zval*), NULL) == SUCCESS) { + Z_ADDREF_PP(p); + } + return ZEND_HASH_APPLY_KEEP; +} +/* }}} */ + /* * Local variables: * tab-width: 4 diff --git a/Zend/zend_variables.h b/Zend/zend_variables.h index 87016433337..baf905fa5cd 100644 --- a/Zend/zend_variables.h +++ b/Zend/zend_variables.h @@ -45,6 +45,7 @@ static zend_always_inline void _zval_copy_ctor(zval *zvalue ZEND_FILE_LINE_DC) _zval_copy_ctor_func(zvalue ZEND_FILE_LINE_RELAY_CC); } +ZEND_API int zval_copy_static_var(zval **p TSRMLS_DC, int num_args, va_list args, zend_hash_key *key); ZEND_API int zend_print_variable(zval *var); ZEND_API void _zval_ptr_dtor(zval **zval_ptr ZEND_FILE_LINE_DC);