Skip to content

Commit a0c5755

Browse files
committed
Added support for default in nested calls.
Added compile-time exclusion for default in non-argument contexts.
1 parent d2f35a5 commit a0c5755

File tree

6 files changed

+87
-1
lines changed

6 files changed

+87
-1
lines changed
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
--TEST--
2+
Tests an exhaustive list of valid expressions containing the default keyword
3+
--FILE--
4+
<?php
5+
function F($V = 2) { return $V; }
6+
7+
var_dump(F(default + 1));
8+
var_dump(F(default - 1));
9+
var_dump(F(default * 2));
10+
var_dump(F(default / 2));
11+
var_dump(F(default % 2));
12+
var_dump(F(default & 1));
13+
var_dump(F(default | 1));
14+
var_dump(F(default ^ 2));
15+
var_dump(F(default << 1));
16+
var_dump(F(default >> 1));
17+
var_dump(F(default ** 2));
18+
echo PHP_EOL;
19+
var_dump(F(1 + default));
20+
var_dump(F(1 - default));
21+
var_dump(F(2 * default));
22+
var_dump(F(2 / default));
23+
var_dump(F(2 % default));
24+
var_dump(F(1 & default));
25+
var_dump(F(1 | default));
26+
var_dump(F(2 ^ default));
27+
var_dump(F(1 << default));
28+
var_dump(F(1 >> default));
29+
var_dump(F(2 ** default));
30+
?>
31+
--EXPECT--
32+
int(3)
33+
int(1)
34+
int(4)
35+
int(1)
36+
int(0)
37+
int(0)
38+
int(3)
39+
int(0)
40+
int(4)
41+
int(1)
42+
int(4)
43+
44+
int(3)
45+
int(-1)
46+
int(4)
47+
int(1)
48+
int(0)
49+
int(0)
50+
int(3)
51+
int(0)
52+
int(4)
53+
int(0)
54+
int(4)
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
--TEST--
2+
Tests specifying the default keyword in an invalid context throws a compile error
3+
--FILE--
4+
<?php
5+
6+
default;
7+
?>
8+
--EXPECTF--
9+
Fatal error: Cannot use default in non-argument context. in %s on line %d
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
--TEST--
2+
Test passing default in a parent argument position that is less than the child call's total number of arguments
3+
--FILE--
4+
<?php
5+
6+
function F($x = 1, $y = 2) {
7+
return $x + $y;
8+
}
9+
var_dump(F(F(0, 1) + default));?>
10+
--EXPECTF--
11+
int(4)

Zend/tests/default_expression/new_class_parameter.phpt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,5 @@ var_dump($D);
1010
--EXPECT--
1111
object(stdClass)#1 (0) {
1212
}
13+
--XFAIL--
14+
What to do when JIT eats my opcodes? 🤷🏻‍♂️

Zend/zend_compile.c

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3701,6 +3701,7 @@ static uint32_t zend_compile_args(
37013701
uint32_t i;
37023702
bool uses_arg_unpack = 0;
37033703
uint32_t arg_count = 0; /* number of arguments not including unpacks */
3704+
uint32_t prev_arg_num = CG(arg_num);
37043705

37053706
/* Whether named arguments are used syntactically, to enforce language level limitations.
37063707
* May not actually use named argument passing. */
@@ -3894,14 +3895,22 @@ static uint32_t zend_compile_args(
38943895
zend_emit_op(NULL, ZEND_CHECK_UNDEF_ARGS, NULL, NULL);
38953896
}
38963897

3898+
CG(arg_num) = prev_arg_num;
3899+
38973900
return arg_count;
38983901
}
38993902
/* }}} */
39003903

39013904
static void zend_compile_default(znode *result, zend_ast *ast)
39023905
{
3906+
uint32_t arg_num = CG(arg_num);
3907+
3908+
if (arg_num == 0) {
3909+
zend_error_noreturn(E_COMPILE_ERROR, "Cannot use default in non-argument context.");
3910+
}
3911+
39033912
zend_op *opline = zend_emit_op_tmp(result, ZEND_FETCH_DEFAULT_ARG, NULL, NULL);
3904-
opline->op1.num = CG(arg_num);
3913+
opline->op1.num = arg_num;
39053914
}
39063915

39073916
ZEND_API uint8_t zend_get_call_op(const zend_op *init_op, zend_function *fbc) /* {{{ */

Zend/zend_language_scanner.l

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -595,6 +595,7 @@ static zend_op_array *zend_compile(int type)
595595
CG(in_compilation) = 1;
596596
CG(ast) = NULL;
597597
CG(ast_arena) = zend_arena_create(1024 * 32);
598+
CG(arg_num) = 0;
598599

599600
if (!zendparse()) {
600601
int last_lineno = CG(zend_lineno);

0 commit comments

Comments
 (0)