fix(aot): 解决数组键为0时的C++编译歧义问题

- 添加VALUE_ZERO常量用于表示数字0键
- 实现parseArrayKey方法统一处理数组键解析逻辑
- 修复0键在C++中可能产生的空指针与整数二义性错误
- 更新数组测试用例以验证0键正确处理
- 重构数组键处理代码减少重复逻辑
- 添加相关测试文件验证不同数组场景
pull/1/head
韩天峰 4 months ago
parent 2ca129b0c1
commit 165d683f5a
  1. 31
      src/Php/CompilerBase.php
  2. 0
      tests/aot/array/001.phpt
  3. 0
      tests/aot/array/002.phpt
  4. 22
      tests/aot/array/003.phpt
  5. 18
      tests/aot/array/004.phpt
  6. 18
      tests/aot/array/005.phpt
  7. 14
      tests/aot/array_003.phpt

@ -70,6 +70,7 @@ class CompilerBase extends \PhpAot\Core\Translator
public const string VALUE_NAN = 'std::numeric_limits<double>::quiet_NaN()';
public const string VALUE_INF = 'std::numeric_limits<double>::infinity()';
public const string VALUE_NULL = 'php::null';
public const string VALUE_ZERO = 'php::zero';
public const string LITERAL_STRINGS = '_literal_strings';
public const string ANON_CLASS = '_anon_class_';
public const string STATIC_VAR = '_static_var_';
@ -956,6 +957,19 @@ class CompilerBase extends \PhpAot\Core\Translator
return $list;
}
protected function parseArrayKey(NodeAbstract $expr): string
{
$key = $this->parseIdentifier($expr);
if (str_starts_with($key, self::LITERAL_STRINGS)) {
$key = "{$key}.str()";
} elseif ($key === '0L') {
// 0 在 C++ 中是一个特殊的值,存在二义性,既是空指针,也是整数,这会导致产生 ambiguous 错误
// 必须转为 php::zero 常量,保证作为 key 时正确匹配到 IntKeyMap
$key = self::VALUE_ZERO;
}
return $key;
}
protected function parseIdentifier(NodeAbstract $expr): string
{
$type = $expr->getType();
@ -1941,14 +1955,8 @@ class CompilerBase extends \PhpAot\Core\Translator
foreach ($items as $item) {
$value = $this->parseIdentifier($item->value);
if ($item->key) {
$key = $this->parseIdentifier($item->key);
if (str_starts_with($key, self::LITERAL_STRINGS)) {
$key = "{$key}.toStdString()";
} elseif ($key === '0L') {
$key = 'php::zero';
}
$list[] = $this->getIndent() . '{ ' . $key . ', ' .
self::TYPE_VAR . '(' . $value . ') }';
$key = $this->parseArrayKey($item->key);
$list[] = $this->getIndent() . '{ ' . $key . ', ' . self::TYPE_VAR . '(' . $value . ') }';
} else {
$list[] = $this->getIndent() . self::TYPE_VAR . '(' . $value . ')';
}
@ -4858,12 +4866,7 @@ class CompilerBase extends \PhpAot\Core\Translator
if ($item->unpack) {
$this->context->beforeStmtLines[] = $this->getIndent() . $tmpVar . '.merge(' . $value . ');';
} elseif ($item->key) {
$key = $this->parseIdentifier($item->key);
if (str_starts_with($key, self::LITERAL_STRINGS)) {
$key = "{$key}.toStdString()";
} elseif ($key === '0L') {
$key = 'php::zero';
}
$key = $this->parseArrayKey($item->key);
$this->context->beforeStmtLines[] = $this->getIndent() . $tmpVar . '.set(' . $key . ', ' . $value . ');';
} else {
$this->context->beforeStmtLines[] = $this->getIndent() . $tmpVar . '.append(' . $value . ');';

@ -0,0 +1,22 @@
--TEST--
Array 003
--FILE--
<?php
$key = 100;
$array2 = [
$key => 'foo',
1000 => 'bar',
0 => 'baz',
];
var_dump($array2);
?>
--EXPECT--
array(3) {
[100]=>
string(3) "foo"
[1000]=>
string(3) "bar"
[0]=>
string(3) "baz"
}

@ -0,0 +1,18 @@
--TEST--
Array 003
--FILE--
<?php
$array2 = [
'foo', 'bar', 'baz',
];
var_dump($array2);
?>
--EXPECT--
array(3) {
[0]=>
string(3) "foo"
[1]=>
string(3) "bar"
[2]=>
string(3) "baz"
}

@ -0,0 +1,18 @@
--TEST--
Array 003
--FILE--
<?php
$array2 = [
'foo' => 100, 'bar' => 'php', 'baz' => true,
];
var_dump($array2);
?>
--EXPECT--
array(3) {
["foo"]=>
int(100)
["bar"]=>
string(3) "php"
["baz"]=>
bool(true)
}

@ -1,14 +0,0 @@
--TEST--
Array 003
--FILE--
<?php
$key = 100;
$array2 = [
$key => 'foo',
1000 => 'bar',
];
var_dump(count($array2));
?>
--EXPECT--
int(2)
Loading…
Cancel
Save