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_)';
} else {
$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);
}
} else {

@ -225,7 +225,7 @@ class Preprocessor extends CompilerBase
case 'Stmt_EnumCase':
break;
case 'Stmt_ClassMethod':
$this->prepareMethod($v);
$this->prepareMethod($v, $class);
break;
case 'Stmt_Expression':
$this->foundStrayCode($v);
@ -240,11 +240,15 @@ class Preprocessor extends CompilerBase
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;
if (!$abstract) {
$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();

@ -27,9 +27,8 @@ function main() {
--EXPECTF--
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:
#0 [internal function]: pass->error()
#1 Unknown(0) : %s
#2 {main}
thrown in %s on line %d
#0 Unknown(0) : %s
#1 {main}
thrown in Unknown(0) : %s

Loading…
Cancel
Save