Commit a5d34b45a67 for php

commit a5d34b45a670bb70ea05e012d832b7186cdfda34
Author: Jorg Sowa <jorg.sowa@gmail.com>
Date:   Thu Nov 12 15:45:37 2026 +0100

    Fix AST export of property hook parameters and attributes (GH-25421)

    set(int $v) => $v was exported as set => $v, and hook attributes were
    dropped.

    Closes GH-25421

diff --git a/NEWS b/NEWS
index 92cf423f60a..191b829f6f9 100644
--- a/NEWS
+++ b/NEWS
@@ -34,6 +34,8 @@ PHP                                                                        NEWS
   . Fixed bug GH-25311 (Assertion ret == SUCCESS in array_map()/array_filter()
     after delayed out-of-memory). (ndossche)
   . Fixed AST export of by-reference property hooks. (Jorg Sowa)
+  . Fixed AST export of property hook parameter lists and attributes.
+    (Jorg Sowa)

 - Curl:
   . Fixed curl_reset() retaining CURLOPT_PRIVATE after reset. (lacatoire)
diff --git a/Zend/tests/property_hooks/ast_printing_params_attributes.phpt b/Zend/tests/property_hooks/ast_printing_params_attributes.phpt
new file mode 100644
index 00000000000..b5277c8c0a9
--- /dev/null
+++ b/Zend/tests/property_hooks/ast_printing_params_attributes.phpt
@@ -0,0 +1,65 @@
+--TEST--
+Hook parameter list and attributes AST printing
+--FILE--
+<?php
+
+try {
+    assert(false && new class {
+        public int $prop1 {
+            set(int $value) => $value * 2;
+        }
+        public $prop2 {
+            #[A]
+            get => $this->prop2;
+            #[A(1), B]
+            #[C]
+            final set($value) {
+                $this->prop2 = $value;
+            }
+        }
+        public string $prop3 {
+            set(#[SensitiveParameter] string|int $value) => (string) $value;
+        }
+        public $prop4 {
+            #[A] final &get => $this->prop4;
+        }
+        public function __construct(
+            public int $prop5 {
+                #[A]
+                set(int $value) => $value + 1;
+            },
+        ) {}
+    });
+} catch (Error $e) {
+    echo $e->getMessage(), "\n";
+}
+
+?>
+--EXPECT--
+assert(false && new class {
+    public int $prop1 {
+        set(int $value) => $value * 2;
+    }
+    public $prop2 {
+        #[A]
+        get => $this->prop2;
+        #[A(1), B]
+        #[C]
+        final set($value) {
+            $this->prop2 = $value;
+        }
+    }
+    public string $prop3 {
+        set(#[SensitiveParameter] string|int $value) => (string)$value;
+    }
+    public $prop4 {
+        #[A]
+        final &get => $this->prop4;
+    }
+    public function __construct(public int $prop5 {
+        #[A]
+        set(int $value) => $value + 1;
+    }) {
+    }
+
+})
diff --git a/Zend/zend_ast.c b/Zend/zend_ast.c
index 1fb4b8a28e4..e884ba897d8 100644
--- a/Zend/zend_ast.c
+++ b/Zend/zend_ast.c
@@ -2255,6 +2255,9 @@ static ZEND_COLD void zend_ast_export_hook_list(smart_str *str, const zend_ast_l

 	for (uint32_t i = 0; i < hook_list->children; i++) {
 		const zend_ast_decl *hook = (const zend_ast_decl *)hook_list->child[i];
+		if (hook->child[4]) {
+			zend_ast_export_attributes(str, hook->child[4], indent, 1);
+		}
 		if (hook->flags & ZEND_ACC_FINAL) {
 			smart_str_appends(str, "final ");
 		}
@@ -2262,6 +2265,11 @@ static ZEND_COLD void zend_ast_export_hook_list(smart_str *str, const zend_ast_l
 			smart_str_appendc(str, '&');
 		}
 		smart_str_append(str, hook->name);
+		if (hook->child[0]) {
+			smart_str_appendc(str, '(');
+			zend_ast_export_ex(str, hook->child[0], 0, indent);
+			smart_str_appendc(str, ')');
+		}
 		zend_ast *body = hook->child[2];
 		if (body == NULL) {
 			smart_str_appendc(str, ';');