Commit f6c9428b97a for php
commit f6c9428b97aa0f5ee38abbc3398dc833eb3e2eac
Author: mainframe98 <k.s.werf@hotmail.com>
Date: Sun Oct 18 20:04:46 2026 +0200
zend_test: Fix function and constant imports in compile_to_ast and add support for grouping
While writing a test for it, I discovered the logic for printing
the AST representation of use statements was broken and grouping
did not work. That has been fixed and incorporated into the test.
Closes GH-24418.
diff --git a/NEWS b/NEWS
index e07d065e385..b52fdfe6dc8 100644
--- a/NEWS
+++ b/NEWS
@@ -26,6 +26,8 @@ PHP NEWS
. Fixed bug GH-24321 (ZTS: global_map_ptr_last survives zend_shutdown(),
so an in-process engine restart keeps growing the map_ptr table).
(David Carlier)
+ . Fix function and constant imports in compile_to_ast and add support
+ for grouping. (Klaas Skelte van der Werf)
- Date:
. Fixed bug GH-20503 (Assertion failure with ext/date DateInterval property
diff --git a/Zend/zend_ast.c b/Zend/zend_ast.c
index a39f8d30820..4e640a321d1 100644
--- a/Zend/zend_ast.c
+++ b/Zend/zend_ast.c
@@ -2046,9 +2046,9 @@ static ZEND_COLD void zend_ast_export_ex(smart_str *str, zend_ast *ast, int prio
break;
case ZEND_AST_USE:
smart_str_appends(str, "use ");
- if (ast->attr == T_FUNCTION) {
+ if (ast->attr == ZEND_SYMBOL_FUNCTION) {
smart_str_appends(str, "function ");
- } else if (ast->attr == T_CONST) {
+ } else if (ast->attr == ZEND_SYMBOL_CONST) {
smart_str_appends(str, "const ");
}
goto simple_list;
@@ -2489,6 +2489,19 @@ static ZEND_COLD void zend_ast_export_ex(smart_str *str, zend_ast *ast, int prio
}
break;
case ZEND_AST_USE_ELEM:
+ if (ast->attr == ZEND_SYMBOL_FUNCTION) {
+ smart_str_appends(str, "function ");
+ } else if (ast->attr == ZEND_SYMBOL_CONST) {
+ smart_str_appends(str, "const ");
+ }
+
+ zend_ast_export_name(str, ast->child[0], 0, indent);
+
+ if (ast->child[1]) {
+ smart_str_appends(str, " as ");
+ zend_ast_export_name(str, ast->child[1], 0, indent);
+ }
+ break;
case ZEND_AST_TRAIT_ALIAS:
zend_ast_export_name(str, ast->child[0], 0, indent);
if (ast->attr & ZEND_ACC_PUBLIC) {
@@ -2510,6 +2523,18 @@ static ZEND_COLD void zend_ast_export_ex(smart_str *str, zend_ast *ast, int prio
smart_str_appends(str, ": ");
ast = ast->child[1];
goto tail_call;
+ case ZEND_AST_GROUP_USE:
+ smart_str_appends(str, "use ");
+ if (ast->attr == ZEND_SYMBOL_FUNCTION) {
+ smart_str_appends(str, "function ");
+ } else if (ast->attr == ZEND_SYMBOL_CONST) {
+ smart_str_appends(str, "const ");
+ }
+ smart_str_append(str, zend_ast_get_str(ast->child[0]));
+ smart_str_appends(str, "\\{");
+ zend_ast_export_list(str, zend_ast_get_list(ast->child[1]), true, 20, indent);
+ smart_str_appends(str, "}");
+ break;
/* 3 child nodes */
case ZEND_AST_METHOD_CALL:
diff --git a/ext/zend_test/tests/compile_to_ast/namespace.phpt b/ext/zend_test/tests/compile_to_ast/namespace.phpt
new file mode 100644
index 00000000000..ee0165a2600
--- /dev/null
+++ b/ext/zend_test/tests/compile_to_ast/namespace.phpt
@@ -0,0 +1,68 @@
+--TEST--
+AST can be recreated (namespace)
+--EXTENSIONS--
+zend_test
+--FILE--
+<?php
+
+namespace Foo {
+ class FooTest {
+ }
+
+ function fn_foo() {
+ }
+
+ function fn_bar() {
+ }
+}
+
+namespace Bar {
+ class BarTest {
+ }
+
+ function fn_bar() {
+ }
+}
+
+namespace {
+ use function Bar\fn_bar;
+ use Foo\{function fn_foo, FooTest, function fn_bar as fn_foobar};
+
+ new FooTest();
+ fn_bar();
+ fn_foobar();
+
+ echo zend_test_compile_to_ast(file_get_contents( __FILE__ ));
+}
+
+?>
+--EXPECT--
+namespace Foo {
+ class FooTest {
+ }
+
+ function fn_foo() {
+ }
+
+ function fn_bar() {
+ }
+
+}
+
+namespace Bar {
+ class BarTest {
+ }
+
+ function fn_bar() {
+ }
+
+}
+
+namespace {
+ use function Bar\fn_bar;
+ use Foo\{function fn_foo, FooTest, function fn_bar as fn_foobar};
+ new FooTest();
+ fn_bar();
+ fn_foobar();
+ echo zend_test_compile_to_ast(file_get_contents(__FILE__));
+}