mirror of
https://github.com/php/php-src.git
synced 2026-03-24 00:02:20 +01:00
Make ASSIGN, ASSIGN_OP, INC and DEC opcodes to return IS_TMP_VAR instead of IS_VAR.
This helps to avoid unnecessary IS_REFERENCE checks. This changes some notices "Only variables should be passed by reference" to exception "Cannot pass parameter %d by reference". Also, for consistency, compile-time fatal error "Only variables can be passed by reference" was converted to exception "Cannot pass parameter %d by reference"
This commit is contained in:
@@ -125,6 +125,11 @@ PHP 8.0 UPGRADE NOTES
|
||||
warning.
|
||||
. Uncaught exceptions now go through "clean shutdown", which means that
|
||||
destructors will be called after an uncaught exception.
|
||||
. Compile time fatal error "Only variables can be passed by reference" has been
|
||||
delayed until run-time and converted to "Cannot pass parameter by reference"
|
||||
exception.
|
||||
. Some "Only variables should be passed by reference" notices have been converted
|
||||
to "Cannot pass parameter by reference" exception.
|
||||
|
||||
- COM:
|
||||
. Removed the ability to import case-insensitive constants from type
|
||||
|
||||
@@ -11,6 +11,8 @@ PHP 8.0 INTERNALS UPGRADE NOTES
|
||||
h. zend_value_error()
|
||||
i. get_closure() object handler
|
||||
j. compare_objects() and compare() object handlers
|
||||
k. The 'I' length modifier
|
||||
l. Some VM instructions switched to IS_TMP_VAR result insted of IS_VAR
|
||||
|
||||
2. Build system changes
|
||||
a. Abstract
|
||||
@@ -89,6 +91,13 @@ PHP 8.0 INTERNALS UPGRADE NOTES
|
||||
The 'v' format from the custom snprintf and spprintf implementations has
|
||||
been removed. Use the standard 's' format instead.
|
||||
|
||||
l. Some VM instructions switched to IS_TMP_VAR result insted of IS_VAR.
|
||||
Actually, all assignments (ZEND_ASSIGN, ZEND_ASSIGN_DIM, ZEND_ASSIGN_OBJ,
|
||||
ZEND_ASSIGN_STATIC_PROP), all compound assignments (ZEND_ASSIGN_OP,
|
||||
ZEND_ASSIGN_DIM_OP, ZEND_ASSIGN_OBJ_OP, ZEND_ASSIGN_STATIC_PROP_OP) and all
|
||||
pre increments/decrements (ZEND_PRE_INC, ZEND_PRE_DEC, ZEND_PRE_INC_OBJ
|
||||
ZEND_PRE_DEC_OBJ, ZEND_PRE_INC_STATIC_PROP ZEND_PRE_DEC_STATIC_PROP).
|
||||
|
||||
========================
|
||||
2. Build system changes
|
||||
========================
|
||||
|
||||
@@ -3,23 +3,31 @@ Bug #72038 (Function calls with values to a by-ref parameter don't always throw
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
test($foo = new stdClass);
|
||||
var_dump($foo);
|
||||
test($bar = 2);
|
||||
var_dump($bar);
|
||||
test($baz = &$bar);
|
||||
var_dump($baz);
|
||||
try {
|
||||
test($foo = new stdClass);
|
||||
var_dump($foo);
|
||||
} catch (Throwable $e) {
|
||||
echo "Exception: " . $e->getMessage() . "\n";
|
||||
}
|
||||
try {
|
||||
test($bar = 2);
|
||||
var_dump($bar);
|
||||
} catch (Throwable $e) {
|
||||
echo "Exception: " . $e->getMessage() . "\n";
|
||||
}
|
||||
try {
|
||||
test($baz = &$bar);
|
||||
var_dump($baz);
|
||||
} catch (Throwable $e) {
|
||||
echo "Exception: " . $e->getMessage() . "\n";
|
||||
}
|
||||
|
||||
function test(&$param) {
|
||||
$param = 1;
|
||||
}
|
||||
|
||||
?>
|
||||
--EXPECTF--
|
||||
Notice: Only variables should be passed by reference in %s on line %d
|
||||
object(stdClass)#1 (0) {
|
||||
}
|
||||
|
||||
Notice: Only variables should be passed by reference in %s on line %d
|
||||
int(2)
|
||||
--EXPECT--
|
||||
Exception: Cannot pass parameter 1 by reference
|
||||
Exception: Cannot pass parameter 1 by reference
|
||||
int(1)
|
||||
|
||||
@@ -12,4 +12,7 @@ change(list($val) = $array);
|
||||
var_dump($array);
|
||||
?>
|
||||
--EXPECTF--
|
||||
Fatal error: Only variables can be passed by reference in %s on line %d
|
||||
Fatal error: Uncaught Error: Cannot pass parameter 1 by reference in %s:%d
|
||||
Stack trace:
|
||||
#0 {main}
|
||||
thrown in %s on line %d
|
||||
|
||||
@@ -4,20 +4,23 @@ Bug #78154: SEND_VAR_NO_REF does not always send reference
|
||||
<?php
|
||||
|
||||
namespace {
|
||||
var_dump(similar_text('a', 'a', $c=0x44444444));
|
||||
var_dump($c);
|
||||
try {
|
||||
var_dump(similar_text('a', 'a', $c=0x44444444));
|
||||
var_dump($c);
|
||||
} catch (Throwable $e) {
|
||||
echo "Exception: " . $e->getMessage() . "\n";
|
||||
}
|
||||
}
|
||||
namespace Foo {
|
||||
var_dump(similar_text('a', 'a', $d=0x44444444));
|
||||
var_dump($d);
|
||||
try {
|
||||
var_dump(similar_text('a', 'a', $d=0x44444444));
|
||||
var_dump($d);
|
||||
} catch (\Throwable $e) {
|
||||
echo "Exception: " . $e->getMessage() . "\n";
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
--EXPECTF--
|
||||
Notice: Only variables should be passed by reference in %s on line %d
|
||||
int(1)
|
||||
int(1145324612)
|
||||
|
||||
Notice: Only variables should be passed by reference in %s on line %d
|
||||
int(1)
|
||||
int(1145324612)
|
||||
--EXPECT--
|
||||
Exception: Cannot pass parameter 3 by reference
|
||||
Exception: Cannot pass parameter 3 by reference
|
||||
|
||||
@@ -11,4 +11,7 @@ foo(1);
|
||||
echo "Done\n";
|
||||
?>
|
||||
--EXPECTF--
|
||||
Fatal error: Only variables can be passed by reference in %s on line %d
|
||||
Fatal error: Uncaught Error: Cannot pass parameter 1 by reference in %s:%d
|
||||
Stack trace:
|
||||
#0 {main}
|
||||
thrown in %s on line %d
|
||||
|
||||
@@ -9,4 +9,7 @@ test(1);
|
||||
|
||||
?>
|
||||
--EXPECTF--
|
||||
Fatal error: Only variables can be passed by reference in %s on line %d
|
||||
Fatal error: Uncaught Error: Cannot pass parameter 1 by reference in %s:%d
|
||||
Stack trace:
|
||||
#0 {main}
|
||||
thrown in %s on line %d
|
||||
|
||||
@@ -718,7 +718,8 @@ void zend_do_free(znode *op1) /* {{{ */
|
||||
if (op1->op_type == IS_TMP_VAR) {
|
||||
zend_op *opline = &CG(active_op_array)->opcodes[CG(active_op_array)->last-1];
|
||||
|
||||
while (opline->opcode == ZEND_END_SILENCE) {
|
||||
while (opline->opcode == ZEND_END_SILENCE ||
|
||||
opline->opcode == ZEND_OP_DATA) {
|
||||
opline--;
|
||||
}
|
||||
|
||||
@@ -738,6 +739,22 @@ void zend_do_free(znode *op1) /* {{{ */
|
||||
opline->opcode -= 2;
|
||||
opline->result_type = IS_UNUSED;
|
||||
return;
|
||||
case ZEND_ASSIGN:
|
||||
case ZEND_ASSIGN_DIM:
|
||||
case ZEND_ASSIGN_OBJ:
|
||||
case ZEND_ASSIGN_STATIC_PROP:
|
||||
case ZEND_ASSIGN_OP:
|
||||
case ZEND_ASSIGN_DIM_OP:
|
||||
case ZEND_ASSIGN_OBJ_OP:
|
||||
case ZEND_ASSIGN_STATIC_PROP_OP:
|
||||
case ZEND_PRE_INC_STATIC_PROP:
|
||||
case ZEND_PRE_DEC_STATIC_PROP:
|
||||
case ZEND_PRE_INC_OBJ:
|
||||
case ZEND_PRE_DEC_OBJ:
|
||||
case ZEND_PRE_INC:
|
||||
case ZEND_PRE_DEC:
|
||||
opline->result_type = IS_UNUSED;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2921,7 +2938,7 @@ void zend_compile_assign(znode *result, zend_ast *ast) /* {{{ */
|
||||
zend_delayed_compile_var(&var_node, var_ast, BP_VAR_W, 0);
|
||||
zend_compile_expr(&expr_node, expr_ast);
|
||||
zend_delayed_compile_end(offset);
|
||||
zend_emit_op(result, ZEND_ASSIGN, &var_node, &expr_node);
|
||||
zend_emit_op_tmp(result, ZEND_ASSIGN, &var_node, &expr_node);
|
||||
return;
|
||||
case ZEND_AST_STATIC_PROP:
|
||||
offset = zend_delayed_compile_begin();
|
||||
@@ -2930,6 +2947,8 @@ void zend_compile_assign(znode *result, zend_ast *ast) /* {{{ */
|
||||
|
||||
opline = zend_delayed_compile_end(offset);
|
||||
opline->opcode = ZEND_ASSIGN_STATIC_PROP;
|
||||
opline->result_type = IS_TMP_VAR;
|
||||
result->op_type = IS_TMP_VAR;
|
||||
|
||||
zend_emit_op_data(&expr_node);
|
||||
return;
|
||||
@@ -2953,6 +2972,8 @@ void zend_compile_assign(znode *result, zend_ast *ast) /* {{{ */
|
||||
|
||||
opline = zend_delayed_compile_end(offset);
|
||||
opline->opcode = ZEND_ASSIGN_DIM;
|
||||
opline->result_type = IS_TMP_VAR;
|
||||
result->op_type = IS_TMP_VAR;
|
||||
|
||||
opline = zend_emit_op_data(&expr_node);
|
||||
return;
|
||||
@@ -2963,6 +2984,8 @@ void zend_compile_assign(znode *result, zend_ast *ast) /* {{{ */
|
||||
|
||||
opline = zend_delayed_compile_end(offset);
|
||||
opline->opcode = ZEND_ASSIGN_OBJ;
|
||||
opline->result_type = IS_TMP_VAR;
|
||||
result->op_type = IS_TMP_VAR;
|
||||
|
||||
zend_emit_op_data(&expr_node);
|
||||
return;
|
||||
@@ -3086,7 +3109,7 @@ void zend_compile_compound_assign(znode *result, zend_ast *ast) /* {{{ */
|
||||
zend_delayed_compile_var(&var_node, var_ast, BP_VAR_RW, 0);
|
||||
zend_compile_expr(&expr_node, expr_ast);
|
||||
zend_delayed_compile_end(offset);
|
||||
opline = zend_emit_op(result, ZEND_ASSIGN_OP, &var_node, &expr_node);
|
||||
opline = zend_emit_op_tmp(result, ZEND_ASSIGN_OP, &var_node, &expr_node);
|
||||
opline->extended_value = opcode;
|
||||
return;
|
||||
case ZEND_AST_STATIC_PROP:
|
||||
@@ -3098,6 +3121,8 @@ void zend_compile_compound_assign(znode *result, zend_ast *ast) /* {{{ */
|
||||
cache_slot = opline->extended_value;
|
||||
opline->opcode = ZEND_ASSIGN_STATIC_PROP_OP;
|
||||
opline->extended_value = opcode;
|
||||
opline->result_type = IS_TMP_VAR;
|
||||
result->op_type = IS_TMP_VAR;
|
||||
|
||||
opline = zend_emit_op_data(&expr_node);
|
||||
opline->extended_value = cache_slot;
|
||||
@@ -3110,6 +3135,8 @@ void zend_compile_compound_assign(znode *result, zend_ast *ast) /* {{{ */
|
||||
opline = zend_delayed_compile_end(offset);
|
||||
opline->opcode = ZEND_ASSIGN_DIM_OP;
|
||||
opline->extended_value = opcode;
|
||||
opline->result_type = IS_TMP_VAR;
|
||||
result->op_type = IS_TMP_VAR;
|
||||
|
||||
zend_emit_op_data(&expr_node);
|
||||
return;
|
||||
@@ -3122,6 +3149,8 @@ void zend_compile_compound_assign(znode *result, zend_ast *ast) /* {{{ */
|
||||
cache_slot = opline->extended_value;
|
||||
opline->opcode = ZEND_ASSIGN_OBJ_OP;
|
||||
opline->extended_value = opcode;
|
||||
opline->result_type = IS_TMP_VAR;
|
||||
result->op_type = IS_TMP_VAR;
|
||||
|
||||
opline = zend_emit_op_data(&expr_node);
|
||||
opline->extended_value = cache_slot;
|
||||
@@ -3236,11 +3265,9 @@ uint32_t zend_compile_args(zend_ast *ast, zend_function *fbc) /* {{{ */
|
||||
opcode = ZEND_SEND_VAR_EX;
|
||||
}
|
||||
} else {
|
||||
if (fbc) {
|
||||
/* Delay "Only variables can be passed by reference" error to execution */
|
||||
if (fbc && !ARG_MUST_BE_SENT_BY_REF(fbc, arg_num)) {
|
||||
opcode = ZEND_SEND_VAL;
|
||||
if (ARG_MUST_BE_SENT_BY_REF(fbc, arg_num)) {
|
||||
zend_error_noreturn(E_COMPILE_ERROR, "Only variables can be passed by reference");
|
||||
}
|
||||
} else {
|
||||
opcode = ZEND_SEND_VAL_EX;
|
||||
}
|
||||
@@ -7577,13 +7604,17 @@ void zend_compile_pre_incdec(znode *result, zend_ast *ast) /* {{{ */
|
||||
if (var_ast->kind == ZEND_AST_PROP) {
|
||||
zend_op *opline = zend_compile_prop(result, var_ast, BP_VAR_RW, 0);
|
||||
opline->opcode = ast->kind == ZEND_AST_PRE_INC ? ZEND_PRE_INC_OBJ : ZEND_PRE_DEC_OBJ;
|
||||
opline->result_type = IS_TMP_VAR;
|
||||
result->op_type = IS_TMP_VAR;
|
||||
} else if (var_ast->kind == ZEND_AST_STATIC_PROP) {
|
||||
zend_op *opline = zend_compile_static_prop(result, var_ast, BP_VAR_RW, 0, 0);
|
||||
opline->opcode = ast->kind == ZEND_AST_PRE_INC ? ZEND_PRE_INC_STATIC_PROP : ZEND_PRE_DEC_STATIC_PROP;
|
||||
opline->result_type = IS_TMP_VAR;
|
||||
result->op_type = IS_TMP_VAR;
|
||||
} else {
|
||||
znode var_node;
|
||||
zend_compile_var(&var_node, var_ast, BP_VAR_RW, 0);
|
||||
zend_emit_op(result, ast->kind == ZEND_AST_PRE_INC ? ZEND_PRE_INC : ZEND_PRE_DEC,
|
||||
zend_emit_op_tmp(result, ast->kind == ZEND_AST_PRE_INC ? ZEND_PRE_INC : ZEND_PRE_DEC,
|
||||
&var_node, NULL);
|
||||
}
|
||||
}
|
||||
@@ -7764,20 +7795,26 @@ void zend_compile_assign_coalesce(znode *result, zend_ast *ast) /* {{{ */
|
||||
opline = &CG(active_op_array)->opcodes[CG(active_op_array)->last-1];
|
||||
switch (var_ast->kind) {
|
||||
case ZEND_AST_VAR:
|
||||
zend_emit_op(&assign_node, ZEND_ASSIGN, &var_node_w, &default_node);
|
||||
zend_emit_op_tmp(&assign_node, ZEND_ASSIGN, &var_node_w, &default_node);
|
||||
break;
|
||||
case ZEND_AST_STATIC_PROP:
|
||||
opline->opcode = ZEND_ASSIGN_STATIC_PROP;
|
||||
opline->result_type = IS_TMP_VAR;
|
||||
var_node_w.op_type = IS_TMP_VAR;
|
||||
zend_emit_op_data(&default_node);
|
||||
assign_node = var_node_w;
|
||||
break;
|
||||
case ZEND_AST_DIM:
|
||||
opline->opcode = ZEND_ASSIGN_DIM;
|
||||
opline->result_type = IS_TMP_VAR;
|
||||
var_node_w.op_type = IS_TMP_VAR;
|
||||
zend_emit_op_data(&default_node);
|
||||
assign_node = var_node_w;
|
||||
break;
|
||||
case ZEND_AST_PROP:
|
||||
opline->opcode = ZEND_ASSIGN_OBJ;
|
||||
opline->result_type = IS_TMP_VAR;
|
||||
var_node_w.op_type = IS_TMP_VAR;
|
||||
zend_emit_op_data(&default_node);
|
||||
assign_node = var_node_w;
|
||||
break;
|
||||
|
||||
@@ -250,13 +250,38 @@ static void zend_optimize_block(zend_basic_block *block, zend_op_array *op_array
|
||||
case ZEND_FREE:
|
||||
if (opline->op1_type == IS_TMP_VAR) {
|
||||
src = VAR_SOURCE(opline->op1);
|
||||
if (src &&
|
||||
(src->opcode == ZEND_BOOL || src->opcode == ZEND_BOOL_NOT)) {
|
||||
/* T = BOOL(X), FREE(T) => T = BOOL(X) */
|
||||
/* The remaining BOOL is removed by a separate optimization */
|
||||
VAR_SOURCE(opline->op1) = NULL;
|
||||
MAKE_NOP(opline);
|
||||
++(*opt_count);
|
||||
if (src) {
|
||||
switch (src->opcode) {
|
||||
case ZEND_BOOL:
|
||||
case ZEND_BOOL_NOT:
|
||||
/* T = BOOL(X), FREE(T) => T = BOOL(X) */
|
||||
/* The remaining BOOL is removed by a separate optimization */
|
||||
VAR_SOURCE(opline->op1) = NULL;
|
||||
MAKE_NOP(opline);
|
||||
++(*opt_count);
|
||||
break;
|
||||
case ZEND_ASSIGN:
|
||||
case ZEND_ASSIGN_DIM:
|
||||
case ZEND_ASSIGN_OBJ:
|
||||
case ZEND_ASSIGN_STATIC_PROP:
|
||||
case ZEND_ASSIGN_OP:
|
||||
case ZEND_ASSIGN_DIM_OP:
|
||||
case ZEND_ASSIGN_OBJ_OP:
|
||||
case ZEND_ASSIGN_STATIC_PROP_OP:
|
||||
case ZEND_PRE_INC:
|
||||
case ZEND_PRE_DEC:
|
||||
case ZEND_PRE_INC_OBJ:
|
||||
case ZEND_PRE_DEC_OBJ:
|
||||
case ZEND_PRE_INC_STATIC_PROP:
|
||||
case ZEND_PRE_DEC_STATIC_PROP:
|
||||
src->result_type = IS_UNUSED;
|
||||
VAR_SOURCE(opline->op1) = NULL;
|
||||
MAKE_NOP(opline);
|
||||
++(*opt_count);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (opline->op1_type == IS_VAR) {
|
||||
src = VAR_SOURCE(opline->op1);
|
||||
@@ -1649,7 +1674,7 @@ static void zend_t_usage(zend_cfg *cfg, zend_op_array *op_array, zend_bitset use
|
||||
|
||||
while (opline >= end) {
|
||||
/* usage checks */
|
||||
if (opline->result_type == IS_VAR) {
|
||||
if (opline->result_type & (IS_VAR|IS_TMP_VAR)) {
|
||||
if (!zend_bitset_in(usage, VAR_NUM(opline->result.var))) {
|
||||
switch (opline->opcode) {
|
||||
case ZEND_ASSIGN_OP:
|
||||
@@ -1666,13 +1691,6 @@ static void zend_t_usage(zend_cfg *cfg, zend_op_array *op_array, zend_bitset use
|
||||
case ZEND_DO_FCALL_BY_NAME:
|
||||
opline->result_type = IS_UNUSED;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
zend_bitset_excl(usage, VAR_NUM(opline->result.var));
|
||||
}
|
||||
} else if (opline->result_type == IS_TMP_VAR) {
|
||||
if (!zend_bitset_in(usage, VAR_NUM(opline->result.var))) {
|
||||
switch (opline->opcode) {
|
||||
case ZEND_POST_INC:
|
||||
case ZEND_POST_DEC:
|
||||
case ZEND_POST_INC_OBJ:
|
||||
|
||||
@@ -427,7 +427,7 @@ static void place_essa_pis(
|
||||
pi_range_not_equals(pi, -1, 1);
|
||||
}
|
||||
}
|
||||
} else if (opline->op1_type == IS_VAR &&
|
||||
} else if (opline->op1_type == IS_TMP_VAR &&
|
||||
((opline-1)->opcode == ZEND_PRE_INC ||
|
||||
(opline-1)->opcode == ZEND_PRE_DEC) &&
|
||||
opline->op1.var == (opline-1)->result.var &&
|
||||
|
||||
@@ -16,4 +16,9 @@ var_dump(preg_match_all($regex, $subject, 'test'));
|
||||
echo "Done";
|
||||
?>
|
||||
--EXPECTF--
|
||||
Fatal error: Only variables can be passed by reference in %spreg_match_all_error3.php on line %d
|
||||
*** Testing preg_match_all() : error conditions ***
|
||||
|
||||
Fatal error: Uncaught Error: Cannot pass parameter 3 by reference in %s:%d
|
||||
Stack trace:
|
||||
#0 {main}
|
||||
thrown in %s on line %d
|
||||
|
||||
@@ -8,4 +8,7 @@ function f() {
|
||||
var_dump(next(array(1, 2)));
|
||||
?>
|
||||
--EXPECTF--
|
||||
Fatal error: Only variables can be passed by reference in %s on line %d
|
||||
Fatal error: Uncaught Error: Cannot pass parameter 1 by reference in %s:%d
|
||||
Stack trace:
|
||||
#0 {main}
|
||||
thrown in %s on line %d
|
||||
|
||||
@@ -15,4 +15,7 @@ prev - ensure we cannot pass a temporary
|
||||
var_dump(prev(array(1, 2)));
|
||||
?>
|
||||
--EXPECTF--
|
||||
Fatal error: Only variables can be passed by reference in %s on line %d
|
||||
Fatal error: Uncaught Error: Cannot pass parameter 1 by reference in %s:%d
|
||||
Stack trace:
|
||||
#0 {main}
|
||||
thrown in %s on line %d
|
||||
|
||||
@@ -16,4 +16,7 @@ Basic class support - attempting to pass a class constant by reference.
|
||||
var_dump(aclass::myConst);
|
||||
?>
|
||||
--EXPECTF--
|
||||
Fatal error: Only variables can be passed by reference in %s on line 12
|
||||
Fatal error: Uncaught Error: Cannot pass parameter 1 by reference in %s:%d
|
||||
Stack trace:
|
||||
#0 {main}
|
||||
thrown in %s on line %d
|
||||
|
||||
@@ -12,4 +12,7 @@ f(2);
|
||||
|
||||
?>
|
||||
--EXPECTF--
|
||||
Fatal error: Only variables can be passed by reference in %s on line 8
|
||||
Fatal error: Uncaught Error: Cannot pass parameter 1 by reference in %s:%d
|
||||
Stack trace:
|
||||
#0 {main}
|
||||
thrown in %s on line %d
|
||||
|
||||
@@ -9,42 +9,52 @@ function f(&$a) {
|
||||
}
|
||||
|
||||
echo "\n\n---> Pass constant assignment by reference:\n";
|
||||
f($a="a.original");
|
||||
var_dump($a);
|
||||
try {
|
||||
f($a="a.original");
|
||||
var_dump($a);
|
||||
} catch (Throwable $e) {
|
||||
echo "Exception: " . $e->getMessage() ."\n";
|
||||
}
|
||||
|
||||
echo "\n\n---> Pass variable assignment by reference:\n";
|
||||
unset($a);
|
||||
$a = "a.original";
|
||||
f($b = $a);
|
||||
var_dump($a);
|
||||
try {
|
||||
unset($a);
|
||||
$a = "a.original";
|
||||
f($b = $a);
|
||||
var_dump($a);
|
||||
} catch (Throwable $e) {
|
||||
echo "Exception: " . $e->getMessage() ."\n";
|
||||
}
|
||||
|
||||
echo "\n\n---> Pass reference assignment by reference:\n";
|
||||
unset($a, $b);
|
||||
$a = "a.original";
|
||||
f($b =& $a);
|
||||
var_dump($a);
|
||||
try {
|
||||
unset($a, $b);
|
||||
$a = "a.original";
|
||||
f($b =& $a);
|
||||
var_dump($a);
|
||||
} catch (Throwable $e) {
|
||||
echo "Exception: " . $e->getMessage() ."\n";
|
||||
}
|
||||
|
||||
echo "\n\n---> Pass concat assignment by reference:\n";
|
||||
unset($a, $b);
|
||||
$b = "b.original";
|
||||
$a = "a.original";
|
||||
f($b .= $a);
|
||||
var_dump($a);
|
||||
try {
|
||||
unset($a, $b);
|
||||
$b = "b.original";
|
||||
$a = "a.original";
|
||||
f($b .= $a);
|
||||
var_dump($a);
|
||||
} catch (Throwable $e) {
|
||||
echo "Exception: " . $e->getMessage() ."\n";
|
||||
}
|
||||
|
||||
?>
|
||||
--EXPECTF--
|
||||
--EXPECT--
|
||||
---> Pass constant assignment by reference:
|
||||
|
||||
Notice: Only variables should be passed by reference in %s on line 9
|
||||
string(10) "a.original"
|
||||
string(10) "a.original"
|
||||
Exception: Cannot pass parameter 1 by reference
|
||||
|
||||
|
||||
---> Pass variable assignment by reference:
|
||||
|
||||
Notice: Only variables should be passed by reference in %s on line 15
|
||||
string(10) "a.original"
|
||||
string(10) "a.original"
|
||||
Exception: Cannot pass parameter 1 by reference
|
||||
|
||||
|
||||
---> Pass reference assignment by reference:
|
||||
@@ -53,7 +63,4 @@ string(9) "a.changed"
|
||||
|
||||
|
||||
---> Pass concat assignment by reference:
|
||||
|
||||
Notice: Only variables should be passed by reference in %s on line 28
|
||||
string(20) "b.originala.original"
|
||||
string(10) "a.original"
|
||||
Exception: Cannot pass parameter 1 by reference
|
||||
|
||||
Reference in New Issue
Block a user