fix(tpc): 注解解析补齐「有类定义 ⇒ 是类」——模块别名占裸名导致类引用退化成 i8**
类别: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**。
This commit is contained in:
1 parent
fd212b3ff8
commit
3bc3c48dee
1 file changed
+77
@@ -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 声明侧是
|
||||
`%"<sha>.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:
|
||||
|
||||
Reference in new issue
Block a user