fix(call): 跨模块返回类型解析兜底修复——star import 候选验证失败时先验证原模块(stdlib.malloc extern def 不再误归 stdint);包模块 vpi 未命中时经 reexport 定位定义模块查返回注解(fltk.Fl_Input_value 返回 str 不再退化 i32)

This commit is contained in:
TermiNexus committed 2026-09-01 21:23:12 +08:00
1 parent 131f3a9a4d
commit 75db09e18a
1 file changed
+44 -5
+44 -5
View File
@@ -784,6 +784,36 @@ class CallGenMixin(CallGenBase.CallGenBase):
VpiReader._ensure_vpi_ret_annot_loaded(mod_ret_sha1, self.Gen.CallGenBase.TempDir)
ret_annot_fc: str = VpiReader._lookup_vpi_ret_annot(
mod_ret_sha1, None, func_name)
if ret_annot_fc is None:
# 包模块 vpi 未命中(函数定义在子模块,如
# fltk.Fl_Input_value 实际在 fltk._cfl_input):
# 经 reexport 定位定义模块(star import 多候选
# 逐个查返回注解)再查 vpi。
rr_src: str = self.Gen.ImportsGen.lookup_reexport(mod_ret_sha1, func_name)
if rr_src is None:
rr_src = self._lookup_reexport_from_vpi(pool, mod_ret_sha1, func_name)
if rr_src is not None:
rr_total: t.CSizeT = string.strlen(rr_src)
rr_i: t.CSizeT = 0
while rr_i < rr_total and ret_annot_fc is None:
while rr_i < rr_total and rr_src[rr_i] == ' ':
rr_i += 1
if rr_i >= rr_total:
break
rr_start: t.CSizeT = rr_i
while rr_i < rr_total and rr_src[rr_i] != ' ':
rr_i += 1
rr_len: t.CSizeT = rr_i - rr_start
rr_buf: str = pool.alloc(rr_len + 1)
if rr_buf is not None:
string.strncpy(rr_buf, rr_src + rr_start, rr_len)
rr_buf[rr_len] = '\0'
rr_sha1: str = self._lookup_module_sha1(rr_buf)
if rr_sha1 is not None:
VpiReader._ensure_vpi_ret_annot_loaded(
rr_sha1, self.Gen.CallGenBase.TempDir)
ret_annot_fc = VpiReader._lookup_vpi_ret_annot(
rr_sha1, None, func_name)
if ret_annot_fc is not None:
vpi_ret_ty = VpiReader._resolve_vpi_ret_annot_str(
pool, ret_annot_fc,
@@ -1209,11 +1239,20 @@ class CallGenMixin(CallGenBase.CallGenBase):
rs_found = 1
break
if rs_found == 0:
# 无验证通过(非 extern 函数):仍用首个候选作为
# 定义模块(保持旧行为,普通跨模块函数带 sha1 前缀)
reexport_sha1: str = self._lookup_module_sha1(reexport_src)
if reexport_sha1 is not None:
mod_sha1 = reexport_sha1
# star import 候选验证全部失败:func_name 可能定义在
# 原模块自身(extern def 如 stdlib.malloc 定义在 stdlib,
# 而 stdlib 又 `from stdint import *` 产生误候选 stdint)。
# 先验证原模块:extern/State → 裸名(rs_found=1 下方置裸名)。
if self.Gen.CallGenBase.is_cexport_func(mod_sha1, func_name) != 0 or \
self._is_state_func_from_vpi(pool, mod_sha1, func_name) != 0:
rs_found = 1
call_name = func_name
else:
# 原模块未定义:回退首个候选(旧行为,普通跨模块
# 函数带 sha1 前缀,如 ast._lexer_init 定义在 ast.lexer)
reexport_sha1: str = self._lookup_module_sha1(reexport_src)
if reexport_sha1 is not None:
mod_sha1 = reexport_sha1
# CExport 函数定义用裸名(@strlen),跨模块调用需用裸名而非 @{sha1}.func
if rs_found != 0:
pass # 已验证 reexport 定义模块并置裸名