From 04b3d7de20b7ae52c027c8bd50d484b6003e9461 Mon Sep 17 00:00:00 2001 From: tianfenghan Date: Wed, 10 Jun 2026 19:23:12 +0800 Subject: [PATCH] =?UTF-8?q?fix(php):=20=E4=BF=AE=E5=A4=8D=E5=87=BD?= =?UTF-8?q?=E6=95=B0=E8=B0=83=E7=94=A8=E5=8F=82=E6=95=B0=E4=BC=A0=E9=80=92?= =?UTF-8?q?=E4=B8=AD=E7=9A=84=E5=AF=B9=E8=B1=A1=E5=B1=9E=E6=80=A7=E5=A4=84?= =?UTF-8?q?=E7=90=86=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 修改 CompilerBase.php 中的参数解析逻辑,统一使用 parseCallArgValue 方法 - 添加 materializeCallArgValue 和 shouldMaterializeCallArg 辅助方法 - 对数组维度获取和属性获取表达式进行去间接化处理 - 在参数转换过程中添加对象属性的特殊处理 - 新增 default array property 测试用例验证数组属性初始化功能 - 新增 unset on arrays and variables 测试用例验证对象参数传递行为 --- src/Php/CompilerBase.php | 28 +++++++++++++-- tests/aot/basic/update-object-arg.phpt | 46 +++++++++++++++++++++++++ tests/aot/object_property/006.phpt | 47 ++++++++++++++++++++++++++ 3 files changed, 119 insertions(+), 2 deletions(-) create mode 100644 tests/aot/basic/update-object-arg.phpt create mode 100644 tests/aot/object_property/006.phpt diff --git a/src/Php/CompilerBase.php b/src/Php/CompilerBase.php index 0a9b00fa..58d4a83a 100644 --- a/src/Php/CompilerBase.php +++ b/src/Php/CompilerBase.php @@ -2740,7 +2740,7 @@ class CompilerBase extends \PhpAot\Core\Translator if (array_key_exists($arg->name->name, $namedArgs)) { $this->fatalError($arg, "Duplicate named argument `{$arg->name->name}`"); } - $namedArgs[$arg->name->name] = $this->parseArg($arg); + $namedArgs[$arg->name->name] = $this->parseCallArgValue($arg); } $tmpVar = $this->genTmpVarName(); @@ -2868,12 +2868,34 @@ class CompilerBase extends \PhpAot\Core\Translator return $tmpVar; } } - $list_args[] = $this->parseArg($arg); + $list_args[] = $this->parseCallArgValue($arg); } return Symbol::argList() . '{' . implode(', ', $list_args) . '}'; } + protected function parseCallArgValue(Node\Arg $arg): string + { + return $this->materializeCallArgValue($arg->value, $this->parseArg($arg)); + } + + protected function materializeCallArgValue(NodeAbstract $value, string $expr): string + { + if (!$this->shouldMaterializeCallArg($value)) { + return $expr; + } + return 'php_deindirect(' . $expr . ')'; + } + + protected function shouldMaterializeCallArg(NodeAbstract $value): bool + { + if ($value instanceof Expr\ArrayDimFetch) { + return !$this->isStdContainerExpr($value); + } + + return $value instanceof Expr\PropertyFetch; + } + /** * 展开 refval() 调用中的数组元素或对象属性,返回对应的 C++ 引用表达式。 * 若为普通变量则返回 null,由调用方自行处理。 @@ -3513,6 +3535,8 @@ class CompilerBase extends \PhpAot\Core\Translator return $this->convertToRef($arg->value); } + $expr = $this->materializeCallArgValue($arg->value, $expr); + $this->checkVarAssignExpr($arg, $argInfo->type, $type); if ($argInfo->type === self::TYPE_VAR && $this->isVarExpr($arg->value)) { diff --git a/tests/aot/basic/update-object-arg.phpt b/tests/aot/basic/update-object-arg.phpt new file mode 100644 index 00000000..de5705b0 --- /dev/null +++ b/tests/aot/basic/update-object-arg.phpt @@ -0,0 +1,46 @@ +--TEST-- +unset on arrays and variables +--FILE-- +a = 1; + $o1->b = 2; + $o1->c = 3; + $bar->object = $o1; + foo($bar->object); + var_dump($bar->object); + + $arr = ['object' => $o1]; + foo($arr['object']); + var_dump($arr['object']); +} +?> +--EXPECTF-- +object(stdClass)#%d (3) { + ["a"]=> + int(1) + ["b"]=> + int(2) + ["c"]=> + int(3) +} +object(stdClass)#%d (3) { + ["a"]=> + int(1) + ["b"]=> + int(2) + ["c"]=> + int(3) +} diff --git a/tests/aot/object_property/006.phpt b/tests/aot/object_property/006.phpt new file mode 100644 index 00000000..07c0a34c --- /dev/null +++ b/tests/aot/object_property/006.phpt @@ -0,0 +1,47 @@ +--TEST-- +default array property +--FILE-- +board = []; + $board = []; + for ($i = 0; $i < 4; $i++) { + $this->board[$i] = 999 + $i; + $board[$i] = 112 * $i; + } + var_dump($board); + var_dump($this->board); + } +} + +function main() { + $o = new Foo; + $o->run(); +} +?> +--EXPECT-- +array(4) { + [0]=> + int(0) + [1]=> + int(112) + [2]=> + int(224) + [3]=> + int(336) +} +array(4) { + [0]=> + int(999) + [1]=> + int(1000) + [2]=> + int(1001) + [3]=> + int(1002) +} \ No newline at end of file