fix(TPC): 继承链 vtable 状态追溯 + 默认参数检查信息缺失保护

- _resolve_class_flags 沿 class_parent 链追溯 vtable 状态:Stmt/ExprNode 空中间基类(@t.CVTable 无方法)跨模块未注册 class_vtable,子类 IsCVTable 误判为 False → __before_init__ base=0 不写 vtable → 实例 vtable=null → 虚调用段错误。改为沿链查找任一祖先有 vtable 即继承。

- 函数调用严格参数检查:默认参数信息缺失(跨模块 stub 加载/并行编译时序未同步)时跳过检查,避免 fatal_error 误报缺少必需参数。
This commit is contained in:
TermiNexus committed 2026-08-10 23:01:43 +08:00
1 parent a941179826
commit d687216772
2 files changed
+32 -8

No files matched your search

+17 -2
View File
@@ -442,8 +442,23 @@ class ClassHandle(BaseHandle):
# 继承链统一 vtable(与 TPV _detect_vtable_status 一致):
# 父类有 vtable → 子类启用;父类无 vtable → 子类不启用(静态);
# 父类 vtable 状态未知(跨模块/未注册)→ 保守启用。
parent_has_vtable: bool = (ParentClassName in Gen.class_vtable
or ParentClassName in Gen._cross_module_vtable_classes)
# 沿继承链追溯父类的 vtable 状态(支持空中间基类 Stmt/ExprNode):
# Stmt/ExprNode 无方法但 @t.CVTable,跨模块加载时 _has_methods_prescan=False
# 未注册 class_vtable,若只查直接父类会误判子类为静态类 →
# __before_init__ base=0 不写 vtable → 实例 vtable 为 null → 虚调用段错误。
# 修复:沿 class_parent 链向上查,任一祖先有 vtable 即判定子类有 vtable。
_parent_has_vtable: bool = False
_p_chain: str | None = ParentClassName
_p_visited_chain: set[str] = {ClassName}
_class_parent_map: dict = getattr(Gen, 'class_parent', {})
while _p_chain and _p_chain not in _p_visited_chain:
_p_visited_chain.add(_p_chain)
if (_p_chain in Gen.class_vtable
or _p_chain in Gen._cross_module_vtable_classes):
_parent_has_vtable = True
break
_p_chain = _class_parent_map.get(_p_chain)
parent_has_vtable: bool = _parent_has_vtable
parent_known: bool = (ParentClassName in class_graph
or ParentClassName in Gen.class_members
or ParentClassName in Gen.structs)
+15 -6
View File
@@ -1445,12 +1445,21 @@ class ExprCallHandle(BaseHandle):
func_defaults = gv
break
total_params: int = len(exact_param_names)
num_defaults: int = len(func_defaults) if func_defaults else 0
min_args: int = total_params - num_defaults
# 只检查必需参数(有默认值的参数允许缺失)
for i in range(min_args):
if i >= provided and i not in kw_provided:
raise Exception(f"调用 {ModulePath}.{func_name}() 缺少必需参数 '{exact_param_names[i]}',该参数没有默认值")
if func_defaults is None:
# 默认参数信息缺失(跨模块 stub 加载:vpi/stub 只含参数
# 类型不含默认值;或并行编译时序导致定义模块的默认参数
# 尚未注册到共享表)→ 无法准确计算必需参数数量,
# 跳过严格检查避免误报(如 HandlesType.fatal_error 的
# err_type/col_start/col_end 默认值未同步时误报"缺 arg3")。
# 同文件函数的参数检查由 FunctionDef 路径(L1983)覆盖。
pass
else:
num_defaults: int = len(func_defaults)
min_args: int = total_params - num_defaults
# 只检查必需参数(有默认值的参数允许缺失)
for i in range(min_args):
if i >= provided and i not in kw_provided:
raise Exception(f"调用 {ModulePath}.{func_name}() 缺少必需参数 '{exact_param_names[i]}',该参数没有默认值")
elif ModulePath in Gen.ModuleSha1Map and len(Node.args) == 0:
func = Gen.functions.get(mangled_name)
if func and len(func.function_type.args) > 0: