#Please review this change, I moved the routine which copies statics from the closure code to zend_variables.c
#Please also have a look to check whether the TSRMLS_DC is correct, and whether it fits with the rest in zend_variables, because there you are using some macro magic and I am not exactly sure what the reason is for that.
--- /dev/null
+--TEST--
+Statics should work in traits, too.
+--FILE--
+<?php
+error_reporting(E_ALL);
+
+trait Counter {
+ public function inc() {
+ static $c = 0;
+ $c = $c + 1;
+ echo "$c\n";
+ }
+}
+
+
+class C1 {
+ use Counter;
+}
+
+$o = new C1();
+$o->inc();
+$o->inc();
+
+?>
+--EXPECTF--
+1
+2
--- /dev/null
+--TEST--
+Statics work like expected for language-based copy'n'paste. No link between methods from the same trait.
+--FILE--
+<?php
+error_reporting(E_ALL);
+
+trait Counter {
+ public function inc() {
+ static $c = 0;
+ $c = $c + 1;
+ echo "$c\n";
+ }
+}
+
+
+class C1 {
+ use Counter;
+}
+
+class C2 {
+ use Counter;
+}
+
+$o = new C1();
+$o->inc();
+$o->inc();
+
+$p = new C2();
+$p->inc();
+$p->inc();
+
+?>
+--EXPECTF--
+1
+2
+1
+2
}
/* }}} */
-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;
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;
}
}
#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
_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);