fix(php): 修复函数调用参数传递中的对象属性处理问题

- 修改 CompilerBase.php 中的参数解析逻辑,统一使用 parseCallArgValue 方法
- 添加 materializeCallArgValue 和 shouldMaterializeCallArg 辅助方法
- 对数组维度获取和属性获取表达式进行去间接化处理
- 在参数转换过程中添加对象属性的特殊处理
- 新增 default array property 测试用例验证数组属性初始化功能
- 新增 unset on arrays and variables 测试用例验证对象参数传递行为
pull/1/head
韩天峰 3 months ago
parent e208fe11bb
commit 04b3d7de20
  1. 28
      src/Php/CompilerBase.php
  2. 46
      tests/aot/basic/update-object-arg.phpt
  3. 47
      tests/aot/object_property/006.phpt

@ -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)) {

@ -0,0 +1,46 @@
--TEST--
unset on arrays and variables
--FILE--
<?php
class Bar {
public $object;
}
function foo($obj) {
$obj = new ArrayObject();
$obj['hello'] = 'world';
}
function main() {
$bar = new Bar();
$o1 = new stdClass();
$o1->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)
}

@ -0,0 +1,47 @@
--TEST--
default array property
--FILE--
<?php
class Foo
{
public array $board;
public function run(): void
{
$this->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)
}
Loading…
Cancel
Save