From 5d1e8d893c27ff3edf7698cc5244df24da56e77e Mon Sep 17 00:00:00 2001 From: tianfenghan Date: Tue, 12 May 2026 14:53:05 +0800 Subject: [PATCH] =?UTF-8?q?refactor(aot):=20=E4=BC=98=E5=8C=96=20unsafe=5F?= =?UTF-8?q?cast=20=E7=B1=BB=E5=9E=8B=E8=BD=AC=E6=8D=A2=E5=AE=9E=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 将 std::unsafe_cast 的类型检查逻辑重构为统一的模板函数 - 修改异常类型从 RuntimeException 为 TypeError - 更新编译器代码生成以使用新的类型转换函数 - 添加对 std::map 和 std::unordered_map 的类型转换支持 - 创建新的测试用例验证各种容器类型的 unsafe_cast 行为 - 修正现有测试用例中的异常类型断言 --- src/Php/CompilerBase.php | 24 +++--------------------- src/Php/Parser/StdContainerParser.php | 4 ++-- tests/aot/std-array/008.phpt | 22 ++++++++++++++++++++++ tests/aot/std-map/006.phpt | 22 ++++++++++++++++++++++ tests/aot/std-unordered-map/006.phpt | 22 ++++++++++++++++++++++ tests/aot/std-vector/007.phpt | 2 +- tests/aot/std-vector/008.phpt | 2 +- 7 files changed, 73 insertions(+), 25 deletions(-) create mode 100644 tests/aot/std-array/008.phpt create mode 100644 tests/aot/std-map/006.phpt create mode 100644 tests/aot/std-unordered-map/006.phpt diff --git a/src/Php/CompilerBase.php b/src/Php/CompilerBase.php index 5e5761ae..445374ea 100644 --- a/src/Php/CompilerBase.php +++ b/src/Php/CompilerBase.php @@ -5482,13 +5482,7 @@ class CompilerBase extends \PhpAot\Core\Translator if ($type === self::TYPE_STD_ARRAY) { $info = $this->context->stdArrays[$name]; if (isset($info['unsafePtr'])) { - $unsafePtrBox = $this->genTmpVarName(); - $code .= 'auto *' . $unsafePtrBox . ' = ' . $info['unsafePtr'] . '.toBox();' . PHP_EOL; - $code .= $this->getIndent() . 'if (UNEXPECTED(' . $unsafePtrBox . '->type_id != ' . $info['typeId'] . ')) {' . PHP_EOL; - $code .= $this->getIndent() . ' php::throwException("RuntimeException", "std::unsafe_cast(): UnsafePtr type mismatch");' . PHP_EOL; - $code .= $this->getIndent() . '}' . PHP_EOL; - $code .= $this->getIndent(); - $code .= 'auto &' . $name . ' = *reinterpret_cast<' . $info['decl'] . '*>(' . $unsafePtrBox . '->ptr);'; + $code .= 'auto &' . $name . ' = php_unsafe_cast<' . $info['decl'] . '>(' . $info['unsafePtr'] . ', ' . $info['typeId'] . ');'; } elseif ($info['bytes'] > self::MAX_BYTES_IN_STACK) { $code .= "auto {$name}_unique_ptr = std::make_unique<{$info['decl']}>();\n"; $code .= $this->getIndent() . ' auto &' . $name . ' = *' . $name . '_unique_ptr;'; @@ -5498,13 +5492,7 @@ class CompilerBase extends \PhpAot\Core\Translator } elseif ($type === self::TYPE_STD_VECTOR) { $info = $this->context->stdContainers[$name]; if (isset($info['unsafePtr'])) { - $unsafePtrBox = $this->genTmpVarName(); - $code .= 'auto *' . $unsafePtrBox . ' = ' . $info['unsafePtr'] . '.toBox();' . PHP_EOL; - $code .= $this->getIndent() . 'if (UNEXPECTED(' . $unsafePtrBox . '->type_id != ' . $info['typeId'] . ')) {' . PHP_EOL; - $code .= $this->getIndent() . ' php::throwException("RuntimeException", "std::unsafe_cast(): UnsafePtr type mismatch");' . PHP_EOL; - $code .= $this->getIndent() . '}' . PHP_EOL; - $code .= $this->getIndent(); - $code .= 'auto &' . $name . ' = *reinterpret_cast<' . $info['decl'] . '*>(' . $unsafePtrBox . '->ptr);'; + $code .= 'auto &' . $name . ' = php_unsafe_cast<' . $info['decl'] . '>(' . $info['unsafePtr'] . ', ' . $info['typeId'] . ');'; } else { $code .= $info['decl'] . ' ' . $name; if ($info['size'] !== null) { @@ -5517,13 +5505,7 @@ class CompilerBase extends \PhpAot\Core\Translator } elseif ($type === self::TYPE_STD_MAP || $type === self::TYPE_STD_UNORDERED_MAP) { $info = $this->context->stdContainers[$name]; if (isset($info['unsafePtr'])) { - $unsafePtrBox = $this->genTmpVarName(); - $code .= 'auto *' . $unsafePtrBox . ' = ' . $info['unsafePtr'] . '.toBox();' . PHP_EOL; - $code .= $this->getIndent() . 'if (UNEXPECTED(' . $unsafePtrBox . '->type_id != ' . $info['typeId'] . ')) {' . PHP_EOL; - $code .= $this->getIndent() . ' php::throwException("RuntimeException", "std::unsafe_cast(): UnsafePtr type mismatch");' . PHP_EOL; - $code .= $this->getIndent() . '}' . PHP_EOL; - $code .= $this->getIndent(); - $code .= 'auto &' . $name . ' = *reinterpret_cast<' . $info['decl'] . '*>(' . $unsafePtrBox . '->ptr);'; + $code .= 'auto &' . $name . ' = php_unsafe_cast<' . $info['decl'] . '>(' . $info['unsafePtr'] . ', ' . $info['typeId'] . ');'; } else { $code .= $info['decl'] . ' ' . $name . '{};'; } diff --git a/src/Php/Parser/StdContainerParser.php b/src/Php/Parser/StdContainerParser.php index 04d126ac..6fa54879 100644 --- a/src/Php/Parser/StdContainerParser.php +++ b/src/Php/Parser/StdContainerParser.php @@ -422,7 +422,7 @@ trait StdContainerParser $this->addLocalVar($var, self::TYPE_STD_ARRAY); $this->parseStdArray($var, $typeExpr); $this->context->stdArrays[$var]['unsafePtr'] = $unsafePtr; - return '// reinterpret_cast<' . $this->context->stdArrays[$var]['decl'] . '*>(' . $unsafePtr . ')'; + return '// php_unsafe_cast<' . $this->context->stdArrays[$var]['decl'] . '>(' . $unsafePtr . ')'; } if ($containerType === 'vector') { @@ -436,7 +436,7 @@ trait StdContainerParser $this->parseStdUnorderedMap($var, $typeExpr); } $this->context->stdContainers[$var]['unsafePtr'] = $unsafePtr; - return '// reinterpret_cast<' . $this->context->stdContainers[$var]['decl'] . '*>(' . $unsafePtr . ')'; + return '// php_unsafe_cast<' . $this->context->stdContainers[$var]['decl'] . '>(' . $unsafePtr . ')'; } protected function parseStdMapKeyType(NodeAbstract $expr, string $owner): string diff --git a/tests/aot/std-array/008.phpt b/tests/aot/std-array/008.phpt new file mode 100644 index 00000000..d95dc6c9 --- /dev/null +++ b/tests/aot/std-array/008.phpt @@ -0,0 +1,22 @@ +--TEST-- +std array: unsafe_cast type mismatch +--FILE-- +getMessage(), "\n"; + } +} +?> +--EXPECT-- +std::unsafe_cast(): UnsafePtr type mismatch diff --git a/tests/aot/std-map/006.phpt b/tests/aot/std-map/006.phpt new file mode 100644 index 00000000..8a21f7c4 --- /dev/null +++ b/tests/aot/std-map/006.phpt @@ -0,0 +1,22 @@ +--TEST-- +std map: unsafe_cast type mismatch +--FILE-- +getMessage(), "\n"; + } +} +?> +--EXPECT-- +std::unsafe_cast(): UnsafePtr type mismatch diff --git a/tests/aot/std-unordered-map/006.phpt b/tests/aot/std-unordered-map/006.phpt new file mode 100644 index 00000000..b85ae61e --- /dev/null +++ b/tests/aot/std-unordered-map/006.phpt @@ -0,0 +1,22 @@ +--TEST-- +std unordered map: unsafe_cast type mismatch +--FILE-- +getMessage(), "\n"; + } +} +?> +--EXPECT-- +std::unsafe_cast(): UnsafePtr type mismatch diff --git a/tests/aot/std-vector/007.phpt b/tests/aot/std-vector/007.phpt index 1aa8d0d1..5855c0da 100644 --- a/tests/aot/std-vector/007.phpt +++ b/tests/aot/std-vector/007.phpt @@ -13,7 +13,7 @@ function main() { try { std_vector_unsafe_ptr_type_mismatch($ptr); - } catch (RuntimeException $e) { + } catch (TypeError $e) { echo $e->getMessage(), "\n"; } } diff --git a/tests/aot/std-vector/008.phpt b/tests/aot/std-vector/008.phpt index a2cc2fb5..95d2e843 100644 --- a/tests/aot/std-vector/008.phpt +++ b/tests/aot/std-vector/008.phpt @@ -21,7 +21,7 @@ function main() { try { std_vector_unsafe_ptr_class_type_mismatch($ptr); - } catch (RuntimeException $e) { + } catch (TypeError $e) { echo $e->getMessage(), "\n"; } }