summaryrefslogtreecommitdiff
path: root/Zend/zend_operators.c
diff options
context:
space:
mode:
authorNikita Popov <nikic@php.net>2015-06-16 19:55:33 +0200
committerNikita Popov <nikic@php.net>2015-06-16 19:55:33 +0200
commitfb346c8f9376d4a0be80e242406c1bb8dbf710f0 (patch)
treeb811032a8d998fbd4d080fdc73bc3d0111aadaa9 /Zend/zend_operators.c
parent4448843b7c72e6fb28b67d20f9cc6b2519ff2798 (diff)
downloadphp-git-fb346c8f9376d4a0be80e242406c1bb8dbf710f0.tar.gz
Support references in convert_to_*
conver_to_* functions now accept REFERENCE values, which will be unwrapped before performing the usual conversion. This is consistent with convert_scalar_to_number and matches the expected behavior in a couple random use-sites I checked. Also includes a couple fixes/cleanups elsewhere and two tests for cases that previously didn't work (though the reference issue existed all over the place).
Diffstat (limited to 'Zend/zend_operators.c')
-rw-r--r--Zend/zend_operators.c44
1 files changed, 36 insertions, 8 deletions
diff --git a/Zend/zend_operators.c b/Zend/zend_operators.c
index 3176cb505b..d7d2591382 100644
--- a/Zend/zend_operators.c
+++ b/Zend/zend_operators.c
@@ -135,17 +135,23 @@ ZEND_API zend_long ZEND_FASTCALL zend_atol(const char *str, int str_len) /* {{{
}
/* }}} */
+static zend_always_inline void zend_unwrap_reference(zval *op) /* {{{ */
+{
+ if (Z_REFCOUNT_P(op) == 1) {
+ ZVAL_UNREF(op);
+ } else {
+ Z_DELREF_P(op);
+ ZVAL_COPY(op, Z_REFVAL_P(op));
+ }
+}
+/* }}} */
+
ZEND_API void ZEND_FASTCALL convert_scalar_to_number(zval *op) /* {{{ */
{
try_again:
switch (Z_TYPE_P(op)) {
case IS_REFERENCE:
- if (Z_REFCOUNT_P(op) == 1) {
- ZVAL_UNREF(op);
- } else {
- Z_DELREF_P(op);
- ZVAL_COPY(op, Z_REFVAL_P(op));
- }
+ zend_unwrap_reference(op);
goto try_again;
case IS_STRING:
{
@@ -284,6 +290,7 @@ ZEND_API void ZEND_FASTCALL convert_to_long_base(zval *op, int base) /* {{{ */
{
zend_long tmp;
+try_again:
switch (Z_TYPE_P(op)) {
case IS_NULL:
case IS_FALSE:
@@ -331,6 +338,9 @@ ZEND_API void ZEND_FASTCALL convert_to_long_base(zval *op, int base) /* {{{ */
}
return;
}
+ case IS_REFERENCE:
+ zend_unwrap_reference(op);
+ goto try_again;
EMPTY_SWITCH_DEFAULT_CASE()
}
}
@@ -340,6 +350,7 @@ ZEND_API void ZEND_FASTCALL convert_to_double(zval *op) /* {{{ */
{
double tmp;
+try_again:
switch (Z_TYPE_P(op)) {
case IS_NULL:
case IS_FALSE:
@@ -388,6 +399,9 @@ ZEND_API void ZEND_FASTCALL convert_to_double(zval *op) /* {{{ */
}
break;
}
+ case IS_REFERENCE:
+ zend_unwrap_reference(op);
+ goto try_again;
EMPTY_SWITCH_DEFAULT_CASE()
}
}
@@ -417,6 +431,7 @@ ZEND_API void ZEND_FASTCALL convert_to_boolean(zval *op) /* {{{ */
{
int tmp;
+try_again:
switch (Z_TYPE_P(op)) {
case IS_FALSE:
case IS_TRUE:
@@ -469,6 +484,9 @@ ZEND_API void ZEND_FASTCALL convert_to_boolean(zval *op) /* {{{ */
}
break;
}
+ case IS_REFERENCE:
+ zend_unwrap_reference(op);
+ goto try_again;
EMPTY_SWITCH_DEFAULT_CASE()
}
}
@@ -482,6 +500,7 @@ ZEND_API void ZEND_FASTCALL _convert_to_cstring(zval *op ZEND_FILE_LINE_DC) /* {
ZEND_API void ZEND_FASTCALL _convert_to_string(zval *op ZEND_FILE_LINE_DC) /* {{{ */
{
+try_again:
switch (Z_TYPE_P(op)) {
case IS_UNDEF:
case IS_NULL:
@@ -534,6 +553,9 @@ ZEND_API void ZEND_FASTCALL _convert_to_string(zval *op ZEND_FILE_LINE_DC) /* {{
}
break;
}
+ case IS_REFERENCE:
+ zend_unwrap_reference(op);
+ goto try_again;
EMPTY_SWITCH_DEFAULT_CASE()
}
}
@@ -553,7 +575,7 @@ static void convert_scalar_to_array(zval *op) /* {{{ */
ZEND_API void ZEND_FASTCALL convert_to_array(zval *op) /* {{{ */
{
-
+try_again:
switch (Z_TYPE_P(op)) {
case IS_ARRAY:
break;
@@ -590,6 +612,9 @@ ZEND_API void ZEND_FASTCALL convert_to_array(zval *op) /* {{{ */
ZVAL_NEW_ARR(op);
zend_hash_init(Z_ARRVAL_P(op), 8, NULL, ZVAL_PTR_DTOR, 0);
break;
+ case IS_REFERENCE:
+ zend_unwrap_reference(op);
+ goto try_again;
default:
convert_scalar_to_array(op);
break;
@@ -599,7 +624,7 @@ ZEND_API void ZEND_FASTCALL convert_to_array(zval *op) /* {{{ */
ZEND_API void ZEND_FASTCALL convert_to_object(zval *op) /* {{{ */
{
-
+try_again:
switch (Z_TYPE_P(op)) {
case IS_ARRAY:
{
@@ -614,6 +639,9 @@ ZEND_API void ZEND_FASTCALL convert_to_object(zval *op) /* {{{ */
case IS_NULL:
object_init(op);
break;
+ case IS_REFERENCE:
+ zend_unwrap_reference(op);
+ goto try_again;
default: {
zval tmp;
ZVAL_COPY_VALUE(&tmp, op);