From 165d683f5ac50a37017bcdfc1e176057fc295341 Mon Sep 17 00:00:00 2001 From: tianfenghan Date: Thu, 16 Apr 2026 16:02:23 +0800 Subject: [PATCH] =?UTF-8?q?fix(aot):=20=E8=A7=A3=E5=86=B3=E6=95=B0?= =?UTF-8?q?=E7=BB=84=E9=94=AE=E4=B8=BA0=E6=97=B6=E7=9A=84C++=E7=BC=96?= =?UTF-8?q?=E8=AF=91=E6=AD=A7=E4=B9=89=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 添加VALUE_ZERO常量用于表示数字0键 - 实现parseArrayKey方法统一处理数组键解析逻辑 - 修复0键在C++中可能产生的空指针与整数二义性错误 - 更新数组测试用例以验证0键正确处理 - 重构数组键处理代码减少重复逻辑 - 添加相关测试文件验证不同数组场景 --- src/Php/CompilerBase.php | 31 +++++++++++--------- tests/aot/{array_001.phpt => array/001.phpt} | 0 tests/aot/{array_002.phpt => array/002.phpt} | 0 tests/aot/array/003.phpt | 22 ++++++++++++++ tests/aot/array/004.phpt | 18 ++++++++++++ tests/aot/array/005.phpt | 18 ++++++++++++ tests/aot/array_003.phpt | 14 --------- 7 files changed, 75 insertions(+), 28 deletions(-) rename tests/aot/{array_001.phpt => array/001.phpt} (100%) rename tests/aot/{array_002.phpt => array/002.phpt} (100%) create mode 100644 tests/aot/array/003.phpt create mode 100644 tests/aot/array/004.phpt create mode 100644 tests/aot/array/005.phpt delete mode 100644 tests/aot/array_003.phpt diff --git a/src/Php/CompilerBase.php b/src/Php/CompilerBase.php index 491a89f5..6266b229 100644 --- a/src/Php/CompilerBase.php +++ b/src/Php/CompilerBase.php @@ -70,6 +70,7 @@ class CompilerBase extends \PhpAot\Core\Translator public const string VALUE_NAN = 'std::numeric_limits::quiet_NaN()'; public const string VALUE_INF = 'std::numeric_limits::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 . ');'; diff --git a/tests/aot/array_001.phpt b/tests/aot/array/001.phpt similarity index 100% rename from tests/aot/array_001.phpt rename to tests/aot/array/001.phpt diff --git a/tests/aot/array_002.phpt b/tests/aot/array/002.phpt similarity index 100% rename from tests/aot/array_002.phpt rename to tests/aot/array/002.phpt diff --git a/tests/aot/array/003.phpt b/tests/aot/array/003.phpt new file mode 100644 index 00000000..1d9b2915 --- /dev/null +++ b/tests/aot/array/003.phpt @@ -0,0 +1,22 @@ +--TEST-- +Array 003 +--FILE-- + 'foo', + 1000 => 'bar', + 0 => 'baz', +]; +var_dump($array2); +?> +--EXPECT-- +array(3) { + [100]=> + string(3) "foo" + [1000]=> + string(3) "bar" + [0]=> + string(3) "baz" +} \ No newline at end of file diff --git a/tests/aot/array/004.phpt b/tests/aot/array/004.phpt new file mode 100644 index 00000000..26eb095b --- /dev/null +++ b/tests/aot/array/004.phpt @@ -0,0 +1,18 @@ +--TEST-- +Array 003 +--FILE-- + +--EXPECT-- +array(3) { + [0]=> + string(3) "foo" + [1]=> + string(3) "bar" + [2]=> + string(3) "baz" +} \ No newline at end of file diff --git a/tests/aot/array/005.phpt b/tests/aot/array/005.phpt new file mode 100644 index 00000000..eedd9aa2 --- /dev/null +++ b/tests/aot/array/005.phpt @@ -0,0 +1,18 @@ +--TEST-- +Array 003 +--FILE-- + 100, 'bar' => 'php', 'baz' => true, +]; +var_dump($array2); +?> +--EXPECT-- +array(3) { + ["foo"]=> + int(100) + ["bar"]=> + string(3) "php" + ["baz"]=> + bool(true) +} \ No newline at end of file diff --git a/tests/aot/array_003.phpt b/tests/aot/array_003.phpt deleted file mode 100644 index 070c22cc..00000000 --- a/tests/aot/array_003.phpt +++ /dev/null @@ -1,14 +0,0 @@ ---TEST-- -Array 003 ---FILE-- - 'foo', - 1000 => 'bar', -]; -var_dump(count($array2)); -?> ---EXPECT-- -int(2) \ No newline at end of file