summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndi Gutmans <andi@php.net>1999-12-11 12:14:21 +0000
committerAndi Gutmans <andi@php.net>1999-12-11 12:14:21 +0000
commit0e2f4cc32645885fd9de086732efff3fd84bfe98 (patch)
treeabb1380b03f4301bea3a6e4aa5dcaf727b0eff9b
parent3ebf98f1489b012ac6d2d39c84909beafe79adeb (diff)
downloadphp-git-0e2f4cc32645885fd9de086732efff3fd84bfe98.tar.gz
- Support returning references
-rw-r--r--Zend/zend_execute.c37
1 files changed, 28 insertions, 9 deletions
diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c
index a2d8d30feb..c7a7924343 100644
--- a/Zend/zend_execute.c
+++ b/Zend/zend_execute.c
@@ -378,7 +378,7 @@ static inline void zend_assign_to_variable(znode *result, znode *op1, znode *op2
*/
/* break missing intentionally */
case IS_CONST:
- if (PZVAL_IS_REF(value)) {
+ if (PZVAL_IS_REF(value) && value->refcount > 0) {
variable_ptr = *variable_ptr_ptr = (zval *) emalloc(sizeof(zval));
*variable_ptr = *value;
zval_copy_ctor(variable_ptr);
@@ -1544,17 +1544,36 @@ do_fcall_common:
}
break;
case ZEND_RETURN: {
- zval *retval = get_zval_ptr(&opline->op1, Ts, &EG(free_op1), BP_VAR_R);
+ zval *retval_ptr;
+ zval **retval_ptr_ptr;
- if (!EG(free_op1)) { /* Not a temp var */
+ if (opline->extended_value) {
+ retval_ptr_ptr = get_zval_ptr_ptr(&opline->op1, Ts, BP_VAR_R);
+ SEPARATE_ZVAL(retval_ptr_ptr);
+ (*retval_ptr_ptr)->is_ref = 1;
+ (*retval_ptr_ptr)->refcount++;
efree(*EG(return_value_ptr_ptr));
- /* Still need to check for reference */
- *EG(return_value_ptr_ptr) = retval;
- retval->refcount++;
+ (*EG(return_value_ptr_ptr)) = (*retval_ptr_ptr);
} else {
- **EG(return_value_ptr_ptr) = *retval;
- (*EG(return_value_ptr_ptr))->refcount = 1;
- (*EG(return_value_ptr_ptr))->is_ref = 0;
+ retval_ptr = get_zval_ptr(&opline->op1, Ts, &EG(free_op1), BP_VAR_R);
+
+ if (!EG(free_op1)) { /* Not a temp var */
+
+ if (PZVAL_IS_REF(retval_ptr) && retval_ptr->refcount > 0) {
+ **EG(return_value_ptr_ptr) = *retval_ptr;
+ (*EG(return_value_ptr_ptr))->is_ref = 0;
+ (*EG(return_value_ptr_ptr))->refcount = 1;
+ zval_copy_ctor(*EG(return_value_ptr_ptr));
+ } else {
+ efree(*EG(return_value_ptr_ptr));
+ *EG(return_value_ptr_ptr) = retval_ptr;
+ retval_ptr->refcount++;
+ }
+ } else {
+ **EG(return_value_ptr_ptr) = *retval_ptr;
+ (*EG(return_value_ptr_ptr))->refcount = 1;
+ (*EG(return_value_ptr_ptr))->is_ref = 0;
+ }
}
#if SUPPORT_INTERACTIVE
op_array->last_executed_op_number = opline-op_array->opcodes;