Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 62 additions & 0 deletions Zend/tests/partial_application/default_const_expr.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
--TEST--
PFA: constant-expression default for a skipped optional parameter
--FILE--
<?php

const K = 7;

function f($a, $b = K, $c = 0) {
return [$a, $b, $c];
}

class C {
const X = 42;
static function m($a, $b = self::X, $c = 0) {
return [$a, $b, $c];
}
}

enum E {
case A;
case B;
}

function g($a, $b = E::A, $c = 0) {
return [$a, $b->name, $c];
}

$p = f(a: 10, c: ?);
var_dump($p(99));

$q = C::m(a: 1, c: ?);
var_dump($q(9));

$r = g(a: 1, c: ?);
var_dump($r(9));

?>
--EXPECT--
array(3) {
[0]=>
int(10)
[1]=>
int(7)
[2]=>
int(99)
}
array(3) {
[0]=>
int(1)
[1]=>
int(42)
[2]=>
int(9)
}
array(3) {
[0]=>
int(1)
[1]=>
string(1) "A"
[2]=>
int(9)
}
32 changes: 18 additions & 14 deletions Zend/zend_partial.c
Original file line number Diff line number Diff line change
Expand Up @@ -569,32 +569,36 @@ static zend_ast *zp_compile_forwarding_call(
}

/* Generate positional arguments */
bool pass_by_name = false;
for (uint32_t offset = 0; offset < argc; offset++) {
if (Z_ISUNDEF(argv[offset])) {
/* Argument was not passed. Pass its default value. */
if (offset < function->common.required_num_args) {
/* Required param was not passed. This can happen due to named
* args. Using the same exception CE and message as
* zend_handle_undef_args(). */
zend_argument_error_ex(zend_ce_argument_count_error, function, offset + 1, "not passed");
goto error;
}
zval default_value;
if (zp_get_param_default_value(&default_value, function, offset) == FAILURE) {
ZEND_ASSERT(EG(exception));
goto error;
}
zend_ast *default_value_ast;
if (Z_TYPE(default_value) == IS_CONSTANT_AST) {
/* Must dup AST because we are going to destroy it */
default_value_ast = zend_ast_dup(Z_ASTVAL(default_value));
if (function->type == ZEND_USER_FUNCTION) {
pass_by_name = true;
} else {
default_value_ast = zend_ast_create_zval(&default_value);
zval default_value;
if (zp_get_param_default_value(&default_value, function, offset) == FAILURE) {
ZEND_ASSERT(EG(exception));
goto error;
}
args_ast = zend_ast_list_add(args_ast, zend_ast_create_zval(&default_value));
}
args_ast = zend_ast_list_add(args_ast, default_value_ast);
} else {
args_ast = zend_ast_list_add(args_ast, zend_ast_create(ZEND_AST_VAR,
zend_ast_create_zval_from_str(zend_string_copy(var_names->params[offset]))));
zend_ast *value_ast = zend_ast_create(ZEND_AST_VAR,
zend_ast_create_zval_from_str(zend_string_copy(var_names->params[offset])));
if (pass_by_name) {
args_ast = zend_ast_list_add(args_ast, zend_ast_create(ZEND_AST_NAMED_ARG,
zend_ast_create_zval_from_str(zp_get_func_param_name(function, offset)),
value_ast));
} else {
args_ast = zend_ast_list_add(args_ast, value_ast);
}
}
}
/* Use unpacking to pass extra named params */
Expand Down
Loading