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