Skip to content

Commit c8c0365

Browse files
committed
Wrap pipe LHS in a QM_ASSIGN opcode to implicitly block references.
1 parent 80ba4df commit c8c0365

File tree

2 files changed

+52
-32
lines changed

2 files changed

+52
-32
lines changed
Lines changed: 26 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
--TEST--
2-
Pipe operator accepts by-reference functions
2+
Pipe operator rejects by-reference functions.
33
--FILE--
44
<?php
55

@@ -8,12 +8,30 @@ function _modify(int &$a): string {
88
return "foo";
99
}
1010

11-
$a = 5;
12-
$res1 = $a |> '_modify';
11+
function _append(array &$a): string {
12+
$a['bar'] = 'beep';
13+
}
14+
15+
// Simple variables
16+
try {
17+
$a = 5;
18+
$res1 = $a |> _modify(...);
19+
var_dump($res1);
20+
} catch (\Error $e) {
21+
print $e->getMessage() . PHP_EOL;
22+
}
23+
24+
// Complex variables.
25+
try {
26+
$a = ['foo' => 'beep'];
27+
$res2 = $a |> _append(...);
28+
var_dump($res2);
29+
} catch (\Error $e) {
30+
print $e->getMessage() . PHP_EOL;
31+
}
32+
1333

14-
var_dump($res1);
15-
var_dump($a);
1634
?>
17-
--EXPECT--
18-
string(3) "foo"
19-
int(6)
35+
--EXPECTF--
36+
_modify(): Argument #1 ($a) could not be passed by reference
37+
_append(): Argument #1 ($a) could not be passed by reference

Zend/zend_compile.c

Lines changed: 26 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -6412,6 +6412,32 @@ static bool can_match_use_jumptable(zend_ast_list *arms) {
64126412
return 1;
64136413
}
64146414

6415+
static void zend_compile_pipe(znode *result, zend_ast *ast)
6416+
{
6417+
zend_ast *operand_ast = ast->child[0];
6418+
zend_ast *callable_ast = ast->child[1];
6419+
6420+
znode operand_result;
6421+
zend_compile_expr(&operand_result, operand_ast);
6422+
znode wrapped_operand_result;
6423+
zend_emit_op_tmp(&wrapped_operand_result, ZEND_QM_ASSIGN, &operand_result, NULL);
6424+
6425+
/* Turn $foo |> bar(...) into bar($foo). */
6426+
if (callable_ast->kind == ZEND_AST_CALL
6427+
&& callable_ast->child[1]->kind == ZEND_AST_CALLABLE_CONVERT) {
6428+
callable_ast = callable_ast->child[0];
6429+
}
6430+
6431+
znode callable_result;
6432+
zend_compile_expr(&callable_result, callable_ast);
6433+
6434+
zend_ast *fcall_ast = zend_ast_create(ZEND_AST_CALL,
6435+
zend_ast_create_znode(&callable_result),
6436+
zend_ast_create_list(1, ZEND_AST_ARG_LIST, zend_ast_create_znode(&wrapped_operand_result)));
6437+
6438+
zend_compile_expr(result, fcall_ast);
6439+
}
6440+
64156441
static void zend_compile_match(znode *result, zend_ast *ast)
64166442
{
64176443
zend_ast *expr_ast = ast->child[0];
@@ -6598,30 +6624,6 @@ static void zend_compile_match(znode *result, zend_ast *ast)
65986624
efree(jmp_end_opnums);
65996625
}
66006626

6601-
static void zend_compile_pipe(znode *result, zend_ast *ast)
6602-
{
6603-
zend_ast *operand_ast = ast->child[0];
6604-
zend_ast *callable_ast = ast->child[1];
6605-
6606-
znode operand_result;
6607-
zend_compile_expr(&operand_result, operand_ast);
6608-
6609-
/* Turn $foo |> bar(...) into bar($foo). */
6610-
if (callable_ast->kind == ZEND_AST_CALL
6611-
&& callable_ast->child[1]->kind == ZEND_AST_CALLABLE_CONVERT) {
6612-
callable_ast = callable_ast->child[0];
6613-
}
6614-
6615-
znode callable_result;
6616-
zend_compile_expr(&callable_result, callable_ast);
6617-
6618-
zend_ast *fcall_ast = zend_ast_create(ZEND_AST_CALL,
6619-
zend_ast_create_znode(&callable_result),
6620-
zend_ast_create_list(1, ZEND_AST_ARG_LIST, zend_ast_create_znode(&operand_result)));
6621-
6622-
zend_compile_expr(result, fcall_ast);
6623-
}
6624-
66256627
static void zend_compile_try(zend_ast *ast) /* {{{ */
66266628
{
66276629
zend_ast *try_ast = ast->child[0];

0 commit comments

Comments
 (0)