fix(php): 修复抽象类方法调用和实例化错误检查

- 添加了抽象类不能被实例化的检查,在编译时抛出错误
- 修复了方法准备逻辑,确保抽象方法在非抽象类中的正确验证
- 更新了测试期望输出以匹配新的错误格式
- 优化了错误堆栈跟踪的显示格式
pull/1/head
韩天峰 5 months ago
parent f3fd30c662
commit d919ee280c
  1. 6
      src/Php/CompilerBase.php
  2. 8
      src/Php/Preprocessor.php
  3. 9
      tests/core/classes/abstract.phpt

@ -2921,6 +2921,12 @@ class CompilerBase extends \PhpAot\Core\Translator
$cePtr = 'php_get_called_ce(this_)'; $cePtr = 'php_get_called_ce(this_)';
} else { } else {
$className = $this->getNamespacedClassName($className); $className = $this->getNamespacedClassName($className);
if ($this->hasNativeClass($className)) {
$classDef = $this->getClassDef($className);
if ($classDef->flags & Modifiers::ABSTRACT) {
$this->fatalError($expr, "abstract class `$className` cannot be instantiated");
}
}
$cePtr = $this->getClassEntryPtr($className); $cePtr = $this->getClassEntryPtr($className);
} }
} else { } else {

@ -225,7 +225,7 @@ class Preprocessor extends CompilerBase
case 'Stmt_EnumCase': case 'Stmt_EnumCase':
break; break;
case 'Stmt_ClassMethod': case 'Stmt_ClassMethod':
$this->prepareMethod($v); $this->prepareMethod($v, $class);
break; break;
case 'Stmt_Expression': case 'Stmt_Expression':
$this->foundStrayCode($v); $this->foundStrayCode($v);
@ -240,11 +240,15 @@ class Preprocessor extends CompilerBase
return $code; return $code;
} }
protected function prepareMethod(Node\Stmt\ClassMethod $v): void protected function prepareMethod(Node\Stmt\ClassMethod $v, Node\Stmt\Class_|Node\Stmt\Trait_|Node\Stmt\Enum_ $class): void
{ {
$abstract = $v->flags & Modifiers::ABSTRACT; $abstract = $v->flags & Modifiers::ABSTRACT;
if (!$abstract) { if (!$abstract) {
$this->prepareFunction($v) . PHP_EOL; $this->prepareFunction($v) . PHP_EOL;
} else {
if (!($class->flags & Modifiers::ABSTRACT)) {
$this->fatalError($v, "Class {$this->class} cannot override non-abstract method {$v->name}");
}
} }
$fullClassName = $this->getFullClassName(); $fullClassName = $this->getFullClassName();

@ -27,9 +27,8 @@ function main() {
--EXPECTF-- --EXPECTF--
Call to function show() Call to function show()
Fatal error: Uncaught Error: Cannot call abstract method fail::show() in %s:%d Fatal error: Uncaught Error: Cannot call abstract method fail::show() in %s
Stack trace: Stack trace:
#0 [internal function]: pass->error() #0 Unknown(0) : %s
#1 Unknown(0) : %s #1 {main}
#2 {main} thrown in Unknown(0) : %s
thrown in %s on line %d

Loading…
Cancel
Save