fix(tpv): extern declare 返回类型含真实类型时不再误归 Void + 白名单兜底

vpi 注入 extern declare 时 has_state→Void 无条件触发:注解 HANDLE | t.State(FindFirstFileA/GetStdHandle)被归为 void → declare 返回 void,运行期 FindFirstFileA 句柄丢失 → 文件存在性判断失效(文件实际存在但报不存在)。修复:仅纯标记注解归 Void;含真实类型但解析 miss 时回退外部函数返回类型白名单(FindFirstFileA/GetStdHandle→i8*),GenApi 新增 infer_external_func_ret_ty 委托。
This commit is contained in:
TermiNexus committed 2026-08-29 12:03:12 +08:00
1 parent efc8f7948f
commit 2b2c242d14
2 files changed
+39 -1

No files matched your search

+21 -1
View File
@@ -1863,8 +1863,28 @@ def _inject_function_declare(pool: memhub.MemBuddy | t.CPtr,
pool, fd.returns, imported_modules, from_imports, trans)
# 如果返回类型是纯 t.State(无实际类型),用 Void
if ret_ty is None and fd.returns is not None:
if has_state != 0:
# t.State/t.CExtern 是存储类装饰器标记,非真实返回类型。
# 注解 "HANDLE | t.State"(FindFirstFileA)含真实类型 → 不能归 Void
# (此前无条件 has_state→Void,extern declare 返回 void,运行期
# FindFirstFileA 句柄丢失 → 文件存在性判断失效根因)。
# 仅纯标记注解(t.State/t.CExtern/t.CExport 单独出现)才返回 Void。
is_pure_marker_rt: int = 0
rk2_rt: int = fd.returns.kind()
if rk2_rt == ast.ASTKind.Name or rk2_rt == ast.ASTKind.Constant:
is_pure_marker_rt = 1
elif rk2_rt == ast.ASTKind.Attribute:
pm_at: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(fd.returns)
if pm_at.attr is not None and (string.strcmp(pm_at.attr, "State") == 0
or string.strcmp(pm_at.attr, "CExtern") == 0
or string.strcmp(pm_at.attr, "CExport") == 0):
is_pure_marker_rt = 1
if is_pure_marker_rt != 0:
ret_ty = llvmlite.Void(pool)
elif has_state != 0 or has_extern != 0 or has_export != 0:
# 含真实类型但解析失败:回退外部函数返回类型白名单
# (FindFirstFileA/GetStdHandle → i8* HANDLE 等),避免默认 i32
# 截断指针(vpi 缓存/AST 解析 miss 时的稳健兜底)。
ret_ty = GenApi.infer_external_func_ret_ty(pool, fd.name)
# 默认返回 i32
if ret_ty is None:
ret_ty = i32_ty
+18
View File
@@ -126,6 +126,24 @@ def resolve_typedef_or_map(pool: memhub.MemBuddy | t.CPtr,
return None
# ---------------- infer_external_func_ret_ty(委托 CallGenLib._infer_external_func_ret_ty) ----------------
def infer_external_func_ret_ty(pool: memhub.MemBuddy | t.CPtr,
func_name: str) -> llvmlite.LLVMType | t.CPtr:
"""委托到 gen.CallGenLib._infer_external_func_ret_ty(外部函数返回类型白名单)
vpi 注入 extern declare 时返回类型解析 miss 的兜底:FindFirstFileA/
GetStdHandle 等 Win32 HANDLE 返回函数 → i8*,避免默认 i32/void 导致
声明签名错误(运行期 FindFirstFileA 句柄丢失 → 文件存在性判断失效根因)。
fatal_if_unknown=0:白名单未命中返回默认 i32(不 fail-fast,注入上下文
无法收敛判断交给调用侧)。
"""
import lib.core.Gen.Generator as Generator
g: Generator.Generator | t.CPtr = (Generator.Generator | t.CPtr)(t.CVoid(_g_gen, t.CPtr))
if g is not None:
return g.CallGenLib._infer_external_func_ret_ty(pool, func_name, None, 0)
return None
# ---------------- get_current_file(委托 TypeGenResolve.get_current_file) ----------------
def get_current_file() -> str:
"""委托到 gen.get_current_file(原 Handles 壳)"""