From 1ce204d4b24754bf3ab7dd6c365897354356e3cd Mon Sep 17 00:00:00 2001 From: tianfenghan Date: Sun, 1 Mar 2026 16:39:40 +0800 Subject: [PATCH] =?UTF-8?q?fix(aot):=20=E4=BF=AE=E5=A4=8DAOT=E7=BC=96?= =?UTF-8?q?=E8=AF=91=E4=B8=AD=E7=9A=84=E5=91=BD=E5=90=8D=E7=A9=BA=E9=97=B4?= =?UTF-8?q?=E5=92=8C=E9=9D=99=E6=80=81=E8=B0=83=E7=94=A8=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 修正了getNativeName方法中类名和命名空间参数的顺序 - 添加了对包含反斜杠的函数名进行转义处理 - 修复了常量解析时的类名获取逻辑 - 正确实现了魔术常量__FUNCTION__、__CLASS__和__METHOD__的完整命名空间支持 - 修正了self和static关键字的处理,使其在AOT编译时都使用编译期确定的类名 - 修复了方法调用时类名的命名空间解析和占位符生成逻辑 - 添加了对静态属性访问的支持 --- src/Php/CompilerBase.php | 29 ++++++++++++++++++++--------- tests/aot/class-namespace.phpt | 29 +++++++++++++++++++++++++++++ tests/aot/class-static-001.phpt | 32 ++++++++++++++++++++++++++++++++ 3 files changed, 81 insertions(+), 9 deletions(-) create mode 100644 tests/aot/class-namespace.phpt create mode 100644 tests/aot/class-static-001.phpt diff --git a/src/Php/CompilerBase.php b/src/Php/CompilerBase.php index dac0b2b7..d55d7ca2 100644 --- a/src/Php/CompilerBase.php +++ b/src/Php/CompilerBase.php @@ -1476,7 +1476,7 @@ class CompilerBase extends \PhpAot\Core\Translator if (!$class->hasMethod($method)) { return false; } - return $this->getNativeName($method, $class->name, $class->namespace); + return $this->getNativeName($method, $class->namespace, $class->name); } protected function getClassDef(string $name): ClassDef @@ -2059,6 +2059,9 @@ class CompilerBase extends \PhpAot\Core\Translator } foreach ($possibleFunctionNames as $name) { + if (str_contains($name, '\\')) { + $name = $this->escapeNamespace($name); + } // 在预处理阶段检测到函数声明,但是未定义,说明在当前文件,但是顺序错误 // 跳过,稍后再处理 if (isset($this->functionDeclInFile[$name]) @@ -2696,7 +2699,8 @@ class CompilerBase extends \PhpAot\Core\Translator if ($this->isNameExpr($expr->name)) { if (str_contains($name, '::')) { $ns = explode('::', $name)[0]; - $ce = $this->getClassEntryPtr($ns[0]); + $fullName = $this->getNamespacedClassName($ns[0]); + $ce = $this->getClassEntryPtr($fullName); return 'php::constant(' . $ce . ', ' . $this->getLiteralString($ns[1]) . ')'; } return 'php::constant(nullptr, ' . $this->getLiteralString($name) . ')'; @@ -2873,6 +2877,8 @@ class CompilerBase extends \PhpAot\Core\Translator protected function parseMagicConst(MagicConst $expr): string { + $class = ($this->namespace ? $this->namespace . '\\' : '') . $this->class; + $function = ($this->namespace ? $this->namespace . '\\' : '') . $this->function; switch ($expr->getType()) { case 'Scalar_MagicConst_Dir': return '"' . $this->escapeString($this->dir) . '"'; @@ -2881,11 +2887,11 @@ class CompilerBase extends \PhpAot\Core\Translator case 'Scalar_MagicConst_Line': return (string) $expr->getStartLine(); case 'Scalar_MagicConst_Function': - return '"' . $this->escapeString($this->function) . '"'; + return '"' . $this->escapeString($function) . '"'; case 'Scalar_MagicConst_Class': - return '"' . $this->escapeString($this->class) . '"'; + return '"' . $this->escapeString($class) . '"'; case 'Scalar_MagicConst_Method': - return '"' . $this->escapeString($this->class) . '::' . $this->escapeString($this->method) . '"'; + return '"' . $this->escapeString($class) . '::' . $this->escapeString($this->method) . '"'; default: abort($expr); } @@ -3362,7 +3368,11 @@ class CompilerBase extends \PhpAot\Core\Translator } return $id; } - if ($id === 'self') { + /** + * 对 static 的支持存在问题,静态编译时无法获得实际运行时的子类名,所以只能使用 self + * self 是在编译期确定的,而 static 是运行时确定的,但使用 AOT 编译为可执行文件后,运行时类的名称是无法确定的 + */ + if ($id === 'self' or $id === 'static') { $id = $this->getNamespacedClassName($this->class); } if ($this->isNameExpr($node) or $this->isIdExpr($node)) { @@ -3400,6 +3410,7 @@ class CompilerBase extends \PhpAot\Core\Translator } elseif ($class === 'parent') { return $this->parseParentMethodCall($expr); } + $class = $this->getNamespacedClassName($class); _do_call: $method = $this->parseIdentifier($expr->name); @@ -3411,7 +3422,7 @@ class CompilerBase extends \PhpAot\Core\Translator try { $args = $this->parseNativeCallArgs($expr->args, $nativeFunc); } catch (PlaceHolder) { - return $this->genPlaceHolder($this->genArray([$this->genCharPtr($class), $this->genCharPtr($method)])); + return $this->genPlaceHolder($this->genArray([$this->genCharPtr($class, true), $this->genCharPtr($method)])); } if ($args) { return self::PREFIX . $nativeFunc . '(php::null_object, ' . $args . ')'; @@ -3422,7 +3433,7 @@ class CompilerBase extends \PhpAot\Core\Translator } $ce = $this->getClassEntryPtr($class); $fn = $ce . ', ' . $this->getFuncPtr($class . '::' . $method, false); - $placeHolder = $this->genArray([$this->genCharPtr($class), $this->genCharPtr($method)]); + $placeHolder = $this->genArray([$this->genCharPtr($class, true), $this->genCharPtr($method)]); } $call = 'php::call'; if (empty($expr->args)) { @@ -3524,7 +3535,7 @@ class CompilerBase extends \PhpAot\Core\Translator { $class = $this->parseIdentifier($expr->class); $self = false; - if ($class === 'self' or $class === 'this_') { + if ($class === 'self' or $class === 'this_' or $class === 'static') { $self = true; $class = $this->class; } diff --git a/tests/aot/class-namespace.phpt b/tests/aot/class-namespace.phpt new file mode 100644 index 00000000..e3ad7cab --- /dev/null +++ b/tests/aot/class-namespace.phpt @@ -0,0 +1,29 @@ +--TEST-- +class namespace +--FILE-- + +--EXPECT-- +string(18) "Test\Session::init" +string(8) "Test\foo" \ No newline at end of file diff --git a/tests/aot/class-static-001.phpt b/tests/aot/class-static-001.phpt new file mode 100644 index 00000000..183b42c9 --- /dev/null +++ b/tests/aot/class-static-001.phpt @@ -0,0 +1,32 @@ +--TEST-- +class static +--FILE-- + +--EXPECT-- +string(5) "hello" +string(5) "world" +string(3) "foo"