Skip to content

Commit cad6ed2

Browse files
authored
zend_ast: Surround function by parens when exporting calls to function stored in property (php#22376)
* zend_ast: Surround function by parens when exporting calls to function stored in property The extra parentheses are needed to disambiguate method calls from calls to a function stored in a property. Fixes php#22373. * zend_ast: Avoid needless indirection through `zend_ast_export_ns_name()`
1 parent a1059f4 commit cad6ed2

3 files changed

Lines changed: 50 additions & 6 deletions

File tree

NEWS

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ PHP NEWS
2828
invalid variable names). (timwolla)
2929
. Fixed bug GH-22291 (AST pretty printing does not correctly handle braces
3030
in string interpolation). (timwolla)
31+
. Fixed bug GH-22373 (AST pretty-printing drops meaningful parentheses
32+
surrounding property access). (timwolla)
3133

3234
- BCMath:
3335
. Added NUL-byte validation to BCMath functions. (jorgsowa)

Zend/zend_ast.c

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2535,12 +2535,18 @@ static ZEND_COLD void zend_ast_export_ex(smart_str *str, zend_ast *ast, int prio
25352535
break;
25362536
case ZEND_AST_CALL: {
25372537
zend_ast *left = ast->child[0];
2538-
if (left->kind == ZEND_AST_ARROW_FUNC || left->kind == ZEND_AST_CLOSURE) {
2539-
smart_str_appendc(str, '(');
2540-
zend_ast_export_ns_name(str, left, 0, indent);
2541-
smart_str_appendc(str, ')');
2542-
} else {
2543-
zend_ast_export_ns_name(str, left, 0, indent);
2538+
switch (left->kind) {
2539+
/* ZEND_AST_ZVAL is a regular function call. */
2540+
case ZEND_AST_ZVAL:
2541+
/* ZEND_AST_VAR ($foo()) is unambiguous without parens. */
2542+
case ZEND_AST_VAR:
2543+
zend_ast_export_ns_name(str, left, 0, indent);
2544+
break;
2545+
default:
2546+
smart_str_appendc(str, '(');
2547+
zend_ast_export_ex(str, left, 0, indent);
2548+
smart_str_appendc(str, ')');
2549+
break;
25442550
}
25452551
smart_str_appendc(str, '(');
25462552
zend_ast_export_ex(str, ast->child[1], 0, indent);
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
--TEST--
2+
GH-22373: AST pretty-printing drops meaningful parentheses surrounding property access
3+
--FILE--
4+
<?php
5+
6+
class Foo {
7+
public static Closure $sf = strrev(...);
8+
9+
public function __construct(
10+
public Closure $f = strrev(...),
11+
) {
12+
try {
13+
assert(($this->f)('abc') !== 'cba');
14+
} catch (Error $e) {
15+
echo $e->getMessage(), PHP_EOL;
16+
}
17+
try {
18+
assert(($this?->f)('abc') !== 'cba');
19+
} catch (Error $e) {
20+
echo $e->getMessage(), PHP_EOL;
21+
}
22+
try {
23+
assert((self::$sf)('abc') !== 'cba');
24+
} catch (Error $e) {
25+
echo $e->getMessage(), PHP_EOL;
26+
}
27+
}
28+
}
29+
30+
new Foo();
31+
32+
?>
33+
--EXPECT--
34+
assert(($this->f)('abc') !== 'cba')
35+
assert(($this?->f)('abc') !== 'cba')
36+
assert((self::$sf)('abc') !== 'cba')

0 commit comments

Comments
 (0)