fix(TypeGenResolve): 「保留裸名」取证对 CTypedef/内置标量/泛型形参不再报 ERROR
【b 机制漏豁免】取证日志(df1244d 加入)的前提是"这是个**类名**":只有类名存在
"{定义模块SHA1}.类" 这第二个 mangling 形式,留裸名才可能与它分裂。CTypedef /
语言内置标量 / 泛型形参的名域就是它自身,保留裸名即规范形式(TPC 侧
SymbolUtils.NormalizeGenericArgName 同口径),对它报 ERROR 是纯噪声。
现场:编译 includes/traceback.vp 时,TracebackState.FrameAddr 的注解
`t.CArray[uint64, TRACEBACK_FRAME_BUF]`(traceback.vp:532)经规则 1.5 递归规范化
实参 'uint64' ⇒ 规则 5.5 取不到 SHA1 ⇒ 每次编译刷一条
"[类型实参归属] 裸类名 'uint64' 本次保留裸名…"。'uint64' 是 includes/builtins.vp 的
`typedef uint64 = t.CUInt64T`,不进类归属是预期行为,不是缺陷。
修法:新增 `_is_non_class_type_name(pool, name)`(正向白名单,不猜):
① CTypedef 动态表命中(Phase1 1b register_ctypedef_from_source 文本扫描注册);
② builtins 兜底 `_lookup_builtins_typedef`(与 resolve_typedef_or_map 同一口径:
builtins 始终在编译链内,但其 typedef 不随 from_imports 注入 ⇒ 表可能 miss;
命中即幂等注册进表);
③ 语言内置标量/字符串(int/char/bool/float/double/str/bytes/void,与
_resolve_annot_type_name 的跳过清单同口径);
④ 泛型形参名(单字母大写 T/U/V…,特化前出现在实参位属正常)。
门控只对「结构体表里根本没有该名」(_bare_entry is None)豁免:若它确是已注册的类
(.vpi 半条目)只是缺定义模块 SHA1,那是真正的归属缺口,照旧报出,不被同名 typedef 掩盖。
未验证:本改动需重新自举 TransPyV.exe 才生效(TPC 侧无对应逻辑)。vast 解析通过。
This commit is contained in:
1 parent
0e5ebd07ba
commit
d63787f8fc
1 file changed
+71
-13
@@ -261,6 +261,50 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase):
|
||||
# fcount=-1 = opaque 哨兵(区别于空结构体 {}:后者 fcount==0 是"完整定义、
|
||||
# 可 alloca");与 llvmlite 的跨模块 opaque 声明同一表示。
|
||||
return llvmlite.Struct(pool, None, -1, full)
|
||||
|
||||
def _is_non_class_type_name(self, pool: memhub.MemBuddy*, name: str) -> int:
|
||||
"""该类型名是否**本就无类归属**(CTypedef / 语言内置标量 / 泛型形参)——不是类名。
|
||||
|
||||
用途:`_norm_type_arg_name` 的"保留裸名"取证门控。该取证的前提是"这是个**类名**"
|
||||
—— 类名有 "{定义模块SHA1}.类" 这一 mangling 形式,留在裸名才会与带前缀形式分裂;
|
||||
而下列名字的名域就是它自身,不存在第二个形式(TPC 侧
|
||||
`SymbolUtils.NormalizeGenericArgName` 同样原样保留)⇒ 对它报 ERROR 是纯噪声。
|
||||
现场(2026-09-30):includes/traceback.vp:532
|
||||
`FrameAddr: t.CArray[uint64, TRACEBACK_FRAME_BUF]` 的实参 'uint64' 是
|
||||
includes/builtins.vp 的 `typedef uint64 = t.CUInt64T`,不进类归属是**预期**,
|
||||
却每次编译刷一条 ERROR。
|
||||
|
||||
判据(正向白名单,逐条可查,不猜):
|
||||
① CTypedef 动态表命中 —— typedef 唯一真源(Phase1 1b 的
|
||||
register_ctypedef_from_source 文本扫描注册;表在文件边界被 clear 后重建,
|
||||
故紧跟 ② 的 builtins 兜底,与 `resolve_typedef_or_map` 的"统一口径"一致);
|
||||
② builtins.vp 的 typedef(如 `typedef uint64 = t.CUInt64T`):builtins 始终
|
||||
在编译链内,但其 typedef 不随当前文件 from_imports 注入 ⇒ 表可能 miss,
|
||||
必须走与 `resolve_typedef_or_map` 同一兜底(命中即注册进表,幂等);
|
||||
③ 语言内置标量/字符串名 —— 与 `_resolve_annot_type_name` 的跳过清单同口径;
|
||||
④ 泛型形参名(单字母大写,T/U/V…)—— 特化前出现在实参位属正常。
|
||||
"""
|
||||
if name is None or name[0] == '\0':
|
||||
return 0
|
||||
if self.Gen.TypeGenCType is not None:
|
||||
_ts_nc: str = self.Gen.TypeGenCType.lookup_ctypedef(name)
|
||||
if _ts_nc is not None and self.Gen.TypeGenCType.CTypedefFound != 0:
|
||||
return 1
|
||||
if self._lookup_builtins_typedef(pool, name) is not None:
|
||||
return 1
|
||||
if string.strcmp(name, "int") == 0: return 1
|
||||
if string.strcmp(name, "char") == 0: return 1
|
||||
if string.strcmp(name, "bool") == 0: return 1
|
||||
if string.strcmp(name, "float") == 0: return 1
|
||||
if string.strcmp(name, "double") == 0: return 1
|
||||
if string.strcmp(name, "str") == 0: return 1
|
||||
if string.strcmp(name, "bytes") == 0: return 1
|
||||
if string.strcmp(name, "void") == 0: return 1
|
||||
if string.strlen(name) == 1:
|
||||
if name[0] >= 'A' and name[0] <= 'Z':
|
||||
return 1
|
||||
return 0
|
||||
|
||||
def _norm_type_arg_name(self, pool: memhub.MemBuddy*,
|
||||
type_name: str,
|
||||
from_imports: str) -> str:
|
||||
@@ -289,7 +333,9 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase):
|
||||
vs 目标 %"…list[rawptr[AST]]"*;includes/ast/base.vp:357
|
||||
`children = list[rawptr[AST]](self.pool, 8)` 同族反向:字段侧裸名 vs
|
||||
构造侧带前缀)
|
||||
6. 仍查不到:返回原串(内置类型名等,保持原样)
|
||||
6. 仍查不到:返回原串(CTypedef / 内置标量 / 泛型形参等**非类名**保持原样;
|
||||
它们本就没有"带前缀形式"可分裂,故也不触发下方的"保留裸名"取证日志 ——
|
||||
判据见 _is_non_class_type_name)
|
||||
|
||||
返回 None 表示 type_name 为 None。
|
||||
"""
|
||||
@@ -560,18 +606,18 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase):
|
||||
string.strncpy(_sha_b, _tp_nm, _sp_l - 1)
|
||||
_sha_b[_sp_l - 1] = '\0'
|
||||
_def_sha1 = _sha_b
|
||||
# ⑤ **本文件顶层类名真源**(与"窗口"、与类定义顺序无关):Translator 的文件
|
||||
# 入口已把"本文件顶层 ClassDef 的类名 + 本文件模块 SHA1"登记进 StructGen
|
||||
# (register_file_classes)。模块级变量/前向声明**早于**类定义被翻译
|
||||
# (Translator.vp:592-601 < :602 translate_children)时,CurDefModuleSha1
|
||||
# 尚为 None ⇒ ①②③④ 全落空,裸类名(如 base.vp:148 `_append_child(...,
|
||||
# lst: list[rawptr[AST]])` 的形参)会被冻结成裸名版本并与带 SHA1 形式分裂。
|
||||
# 判据是**正向事实**:该名字确由本文件声明(且本文件模块 SHA1 已知)⇒ 不猜。
|
||||
if _def_sha1 is None:
|
||||
_file_sha: str = self.Gen.StructGen.get_file_module_sha1()
|
||||
if _file_sha is not None:
|
||||
if self.Gen.StructGen.is_file_class(pool, type_name) != 0:
|
||||
_def_sha1 = _file_sha
|
||||
# ⑤ **本文件顶层类名真源**(与"窗口"、与类定义顺序无关):Translator 的文件
|
||||
# 入口已把"本文件顶层 ClassDef 的类名 + 本文件模块 SHA1"登记进 StructGen
|
||||
# (register_file_classes)。模块级变量/前向声明**早于**类定义被翻译
|
||||
# (Translator.vp:592-601 < :602 translate_children)时,CurDefModuleSha1
|
||||
# 尚为 None ⇒ ①②③④ 全落空,裸类名(如 base.vp:148 `_append_child(...,
|
||||
# lst: list[rawptr[AST]])` 的形参)会被冻结成裸名版本并与带 SHA1 形式分裂。
|
||||
# 判据是**正向事实**:该名字确由本文件声明(且本文件模块 SHA1 已知)⇒ 不猜。
|
||||
if _def_sha1 is None:
|
||||
_file_sha: str = self.Gen.StructGen.get_file_module_sha1()
|
||||
if _file_sha is not None:
|
||||
if self.Gen.StructGen.is_file_class(pool, type_name) != 0:
|
||||
_def_sha1 = _file_sha
|
||||
if _def_sha1 is not None:
|
||||
res_d: str = self._concat_sha1_class(pool, _def_sha1, type_name)
|
||||
if res_d is not None:
|
||||
@@ -592,6 +638,18 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase):
|
||||
if _def_mod is not None and _w_cls_cur is not None:
|
||||
if string.strcmp(_w_cls_cur, type_name) != 0:
|
||||
_w_need_log = 1
|
||||
# 门控(2026-09-30):取证的前提是"这是个**类名**"——只有类名存在
|
||||
# "{定义模块SHA1}.类" 这第二个形式可分裂。CTypedef(如 builtins.vp 的
|
||||
# `typedef uint64 = t.CUInt64T`)/ 语言内置标量 / 泛型形参的名域就是它自身,
|
||||
# 保留裸名即规范形式(TPC NormalizeGenericArgName 同口径)⇒ 不对它们报错。
|
||||
# 现场:includes/traceback.vp:532 `t.CArray[uint64, TRACEBACK_FRAME_BUF]`
|
||||
# 每编译一次刷一条与真因无关的 ERROR。
|
||||
# 只对**结构体表里根本没有该名**(_bare_entry is None)的情形豁免:若它确
|
||||
# 是已注册的类(如 .vpi 半条目)只是缺定义模块 SHA1,那是真正的归属缺口,
|
||||
# 照旧报出(不被同名 typedef 掩盖)。
|
||||
if _w_need_log != 0 and _bare_entry is None \
|
||||
and self._is_non_class_type_name(pool, type_name) != 0:
|
||||
_w_need_log = 0
|
||||
if _w_need_log != 0:
|
||||
_w_mod: str = "None"
|
||||
if _def_mod is not None: _w_mod = _def_mod
|
||||
|
||||
Reference in new issue
Block a user