Browse Source

Fixed issue with statics in traits.

#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.
experimental/lemon
Stefan Marr 16 years ago
parent
commit
e6bd5368ad
  1. 27
      Zend/tests/traits/language012.phpt
  2. 37
      Zend/tests/traits/language013.phpt
  3. 37
      Zend/zend_closures.c
  4. 5
      Zend/zend_compile.c
  5. 37
      Zend/zend_variables.c
  6. 1
      Zend/zend_variables.h

27
Zend/tests/traits/language012.phpt

@ -0,0 +1,27 @@
--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

37
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--
<?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

37
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;

5
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;
}

37
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

1
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);

Loading…
Cancel
Save