From 3bc3c48dee022325908a86f8422470a6c30c4828 Mon Sep 17 00:00:00 2001 From: TermiNexus Date: Tue, 29 Sep 2026 12:44:03 +0800 Subject: [PATCH] =?UTF-8?q?fix(tpc):=20=E6=B3=A8=E8=A7=A3=E8=A7=A3?= =?UTF-8?q?=E6=9E=90=E8=A1=A5=E9=BD=90=E3=80=8C=E6=9C=89=E7=B1=BB=E5=AE=9A?= =?UTF-8?q?=E4=B9=89=20=E2=87=92=20=E6=98=AF=E7=B1=BB=E3=80=8D=E2=80=94?= =?UTF-8?q?=E2=80=94=E6=A8=A1=E5=9D=97=E5=88=AB=E5=90=8D=E5=8D=A0=E8=A3=B8?= =?UTF-8?q?=E5=90=8D=E5=AF=BC=E8=87=B4=E7=B1=BB=E5=BC=95=E7=94=A8=E9=80=80?= =?UTF-8?q?=E5=8C=96=E6=88=90=20i8**?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 类别:a 编译器缺陷(根因修复)。 现场:TransPyV Generator.vp:200 `self.ExprGenFstr = SubExprGenFstr` 报 「指针隐式转换已禁止(层数不同):%\"a7b68c79f39cb4d3.ExprGenFstr\"* → i8**」, 成员槽来源明细显示:class_members[Generator] 下标 11 声明槽类型正确 (%\"a7b68c79f39cb4d3.ExprGenFstr\"*),但布局 struct '47382dc8277c9d28.Generator' 的 elements[11]=i8**(set_body 只能设一次 → 错布局被永久冻结)。 已核对 temp/47382dc8277c9d28.stub.ll:declare 侧该槽逐字正确 (%"a7b68c79f39cb4d3.ExprGenFstr"*),Generator.vp 46 个字段全写作 `rawptr[X.X]`;.vpi 里注解文本也是 `rawptr[ExprGenFstr.ExprGenFstr]`。 真根因:`import lib.core.Gen.Expr.ExprGenFstr as ExprGenFstr` 的**模块别名**与 模块内 `class ExprGenFstr` 同名,平坦符号表(无前缀)一个名字只留一个条目 ⇒ TypeAnnotationResolver._from_node_attribute / _from_node_name 命中别名条目时 Copy 出「无基类型」的空 CTypeInfo ⇒ rawptr 下标分支按 `PtrCount = slice + rawptr(1)` 得 void 指针链(i8*/i8**),类身份尽失; 该值经成员提取(SymbolExtractor._collect_members → CTypeInfo.FromNode) 写进跨模块共享符号表,再由 FuncGen.setup_from_symbol_table 建出 struct body → 槽被冻结成 i8**。哪一字段中招取决于别名/类条目谁最后写入平坦表, 故三次构建分别命中 TypeGenCDef / ExprGenFstr(时变、非固定字段)。 修复:新增 TypeAnnotationResolver._RecoverTypeFromNamespaces —— 平坦条目 **不是类型**(模块别名/函数/变量/define/枚举成员占位)时,按 _namespaces 找回同名 typedef / 结构体(struct·renum·exception)/ 枚举条目,与 LLVMTypeMapper._resolve_name 既有「同名冲突找回类型」分支逐条同构(同一条 规则源)。挂接三处:_from_node_attribute 的条目分支与无条目分支、 _from_node_name 的条目分支。 口径细节:结构体表示与本文件既有 promotion 逐字一致 (BaseType=CStruct(name) + IsStruct + Name,**不加** PtrCount)—— rawptr[X] 的层数由 rawptr 分支自己 +1,此处再加会得 X**。 --- lib/core/TypeAnnotationResolver.py | 77 ++++++++++++++++++++++++++++++ 1 file changed, 77 insertions(+) diff --git a/lib/core/TypeAnnotationResolver.py b/lib/core/TypeAnnotationResolver.py index a6a8724..ec526e3 100644 --- a/lib/core/TypeAnnotationResolver.py +++ b/lib/core/TypeAnnotationResolver.py @@ -425,6 +425,54 @@ class TypeAnnotationResolver: TypeName: str = Node.value return TypeAnnotationResolver.from_type_name(TypeName) + @staticmethod + def _RecoverTypeFromNamespaces(TypeName: str, SymbolTable: dict | SymbolTable) -> CTypeInfo | None: + """平坦条目不是"类型"时,按命名空间找回同名**类型**条目(找不到 → None)。 + + 与 LLVMTypeMapper._resolve_name 的"同名冲突:平坦条目被 define / 枚举成员 / + 函数占位时找回类型"逐分支同构(同一条规则源):优先 typedef,其次结构体 + (struct / renum / exception 均置 IsStruct),再次枚举。 + + 必要性:平坦表(无前缀)一个名字只留一个条目,而 `import path as X` 的**模块 + 别名**与模块内 `class X` 同名(TransPyV 的 Generator 47 个 `rawptr[X.X]` 字段 + 全是这种形态)。条目被别名占住时,本解析器返回"无基类型"的空 CTypeInfo ⇒ + `rawptr[X.X]` 退化成 void 指针链(i8*/i8**),而 stub 声明侧是 + `%".X"*` ⇒ struct 布局里该槽被 set_body 冻结成 i8**(不可重设), + 赋值时报"指针隐式转换已禁止(层数不同)"。 + """ + _Namespaces: Any = getattr(SymbolTable, '_namespaces', None) + if not isinstance(_Namespaces, dict): + return None + for _NsSyms in _Namespaces.values(): + if not isinstance(_NsSyms, dict): + continue + _Cand: Any = _NsSyms.get(TypeName) + if _Cand is None: + continue + if getattr(_Cand, 'IsTypedef', False): + _R: CTypeInfo = _Cand.Copy() + _R.IsTypedef = True + if _R.BaseType is None: + _R.BaseType = t._CTypedef(TypeName) + return _R + if getattr(_Cand, 'IsStruct', False) or getattr(_Cand, 'IsRenum', False): + # 结构体表示与本文件既有 promotion(_from_node_name / _from_node_attribute + # 的 `BaseType = t.CStruct(name=...); IsStruct = True`)**逐字同口径**: + # 类引用不额外加指针层(PtrCount 保持 0)——本文件里 `rawptr[X]` 的层数 + # 由 rawptr 分支自己 +1,若此处再加一层会得到 `X**`。 + _R = CTypeInfo() + _R.BaseType = t.CStruct(name=TypeName) + _R.IsStruct = True + _R.Name = TypeName + return _R + if getattr(_Cand, 'IsEnum', False): + _R = CTypeInfo() + _R.BaseType = t.CInt() + _R.IsEnum = True + _R.Name = TypeName + return _R + return None + @staticmethod def _from_node_name(Node: ast.Name, SymbolTable: dict | SymbolTable) -> CTypeInfo: """处理 ast.Name 节点""" @@ -538,6 +586,18 @@ class TypeAnnotationResolver: if Entry.BaseType is None and (Entry.IsStruct or Entry.Name): Entry.BaseType = t.CStruct(name=TypeName) Entry.IsStruct = True + if (Entry.BaseType is None and not Entry.IsStruct and not Entry.IsEnum + and not Entry.IsTypedef and not Entry.IsCpythonObject and not Entry.Name): + # 平坦条目不是"类型"(同名**模块别名** / 函数 / 变量 / define / + # 枚举成员占住裸名):直接 return Entry 会得到"无基类型"的空 + # CTypeInfo ⇒ `rawptr[X]` 之类注解退化成 void 指针链 + # (i8*/i8**),struct 布局里该槽被 set_body 永久冻结。 + # 与上方 _from_node_attribute 及 LLVMTypeMapper._resolve_name + # 的"同名冲突找回类型"同一条规则源。 + _RecoveredName: CTypeInfo | None = TypeAnnotationResolver._RecoverTypeFromNamespaces( + TypeName, SymbolTable) + if _RecoveredName is not None: + return _RecoveredName return Entry elif isinstance(Entry, dict): if Entry.get('type') == 'typedef': @@ -1088,7 +1148,24 @@ class TypeAnnotationResolver: if Result.BaseType is None and (Result.IsStruct or Result.IsCpythonObject or Result.Name): Result.BaseType = t.CStruct(name=TypeName) Result.IsStruct = True + if (Result.BaseType is None and not Result.IsStruct and not Result.IsEnum + and not Result.IsTypedef and not Result.IsCpythonObject and not Result.Name): + # 平坦条目不是"类型"(同名**模块别名** / 函数 / 变量 / define / + # 枚举成员占住了裸名):Copy 得到的是"无基类型"的空 CTypeInfo ⇒ + # `rawptr[Mod.Cls]` 之类注解退化成 void 指针链(i8*/i8**), + # struct 布局里该槽被 set_body 永久冻结(现场:Generator 的 + # ExprGenFstr 槽 = i8**,而声明槽是 %"…ExprGenFstr"*,赋值时报 + # "层数不同")。与 LLVMTypeMapper._resolve_name 的"同名冲突找回 + # 类型"同一条规则源:按命名空间找回同名 typedef/结构体/枚举。 + _Recovered: CTypeInfo | None = TypeAnnotationResolver._RecoverTypeFromNamespaces( + TypeName, SymbolTable) + if _Recovered is not None: + return _Recovered return Result + _Recovered2: CTypeInfo | None = TypeAnnotationResolver._RecoverTypeFromNamespaces( + TypeName, SymbolTable) + if _Recovered2 is not None: + return _Recovered2 return CTypeInfo() if FullName in SymbolTable: