fix(tpc): 字段解析「内层是类却成通用指针」当场 fail-fast(降级源头定位)
承接 b8ed33a2 / 7fb0e498:前两者修的是**结果**(错位 body),本次收**源头** ——
class_members 在某个早期 pass 被解析出 i8**(void 基座 + 2 层),随后被冻进
struct body。CollectAnnAssignMember 是字段类型的唯一汇总点,在此加判据式 fail-fast:
判据(只拦"必属类型信息丢失"的组合):注解是指针包装(rawptr[T] / t.CPtr[T] /
裸名 CPtr[T] / `T | t.CPtr` 联合)且其**内层节点(Name/Attribute)的名字在
Gen.structs 或 Gen._struct_sha1_map 中有类定义**,而解析出的 BaseType 却是
t.CVoid ⇒ 必定是解析路径把类丢了,响亮失败并附完整判据:
解析结果 BaseType/PtrCount/IsStruct/IsTypedef/Name
符号表[内层名] => IsTypedef/BaseType/PtrCount/IsStruct/IsRenum/IsModuleAlias/IsEnumMember
Gen.structs 命中 / _struct_sha1_map 命中
放行:rawptr[rawptr] 这类本就 void 基座的多层指针、模块名、泛型特化实参(内层非
Name/Attribute)—— 不误伤合法写法。
This commit is contained in:
1 parent
7fb0e49854
commit
02d89b0900
1 file changed
+65
-1
@@ -14,7 +14,8 @@ from lib.includes import t
|
||||
from lib.includes.t import CTypeRegistry
|
||||
from lib.core.TypeSpec import TypeSpec, SymbolMeta, FIELD_ROUTES
|
||||
from lib.core.SymbolUtils import (
|
||||
IsPtrSubscriptNode, IsListAnnotation, FixedArrayKeywordAnnotationError)
|
||||
IsPtrSubscriptNode, IsListAnnotation, IsCPtrMarkerNode,
|
||||
FlattenUnionOperands, FixedArrayKeywordAnnotationError)
|
||||
from lib.core.VLogger import get_logger as _vlog
|
||||
|
||||
|
||||
@@ -1044,8 +1045,71 @@ class BaseHandle:
|
||||
f"IsTypedef={getattr(TypeInfo, 'IsTypedef', None)} "
|
||||
f"Name={getattr(TypeInfo, 'Name', None)})—— 拒绝静默退化为 i8*"
|
||||
)
|
||||
# 「内层是类引用却解析成通用指针」fail-fast(降级源头定位):
|
||||
# `rawptr[Mod.Class]` / `Mod.Class | t.CPtr` 的语义是"指向该类",内层若确实是
|
||||
# 已定义类,解析结果必须带该类 BaseType;退化成 void 基座(i8* / 多一层 i8**)
|
||||
# 就是类型信息被丢掉 —— 该值一旦进 class_members 就会被冻进 struct body
|
||||
# (llvmlite set_body 只能设一次),后期只修表不修体(现场:Generator 第 3/11
|
||||
# 槽 i8**)。此处响亮失败并附判据,使降级**当场暴露**而非留到赋值时报"层数不同"。
|
||||
self._CheckPtrAnnotationKeepsClass(item.annotation, TypeInfo, VarName, AnnotationText)
|
||||
return VarName, MemberType, TypeInfo
|
||||
|
||||
def _CheckPtrAnnotationKeepsClass(self, Annotation: ast.AST, Info: CTypeInfo | None,
|
||||
MemberName: str, AnnotationText: str) -> None:
|
||||
"""指针包装注解的内层是**已定义类**时,解析结果不得退化成 void 基座(fail-fast)。
|
||||
|
||||
只拦"必属类型信息丢失"的组合:内层节点(Name / Attribute)的名字在
|
||||
`Gen.structs`(本模块已建)或 `Gen._struct_sha1_map`(预扫描的类→模块映射)
|
||||
中有类定义,而解析出的 `BaseType` 却是 `t.CVoid`。其余一律放行
|
||||
(`rawptr[rawptr]` 这类本就 void 基座的多层指针、模块名、泛型特化实参等)。
|
||||
"""
|
||||
if Info is None or Info.BaseType is None:
|
||||
return
|
||||
if not (Info.BaseType is t.CVoid or isinstance(Info.BaseType, t.CVoid)):
|
||||
return
|
||||
Inner: ast.AST | None = None
|
||||
if isinstance(Annotation, ast.Subscript) and IsPtrSubscriptNode(Annotation, self.Trans.SymbolTable):
|
||||
Inner = Annotation.slice
|
||||
elif isinstance(Annotation, ast.BinOp) and isinstance(Annotation.op, ast.BitOr):
|
||||
for Side in FlattenUnionOperands(Annotation):
|
||||
if not IsCPtrMarkerNode(Side, self.Trans.SymbolTable):
|
||||
Inner = Side
|
||||
break
|
||||
if Inner is None:
|
||||
return
|
||||
InnerName: str | None = None
|
||||
if isinstance(Inner, ast.Name):
|
||||
InnerName = Inner.id
|
||||
elif isinstance(Inner, ast.Attribute):
|
||||
InnerName = Inner.attr
|
||||
if not InnerName or InnerName in ('rawptr', 'CPtr'):
|
||||
return
|
||||
Gen: Any = getattr(self.Trans, 'LlvmGen', None)
|
||||
if Gen is None:
|
||||
return
|
||||
if (InnerName not in getattr(Gen, 'structs', {})
|
||||
and InnerName not in getattr(Gen, '_struct_sha1_map', {})):
|
||||
return
|
||||
_e: Any = None
|
||||
try:
|
||||
_e = self.Trans.SymbolTable.lookup(InnerName)
|
||||
except Exception:
|
||||
_e = None
|
||||
raise ValueError(
|
||||
f"[FATAL] 成员 '{MemberName}' 的注解 '{AnnotationText}' 内层 '{InnerName}' "
|
||||
f"是**已定义类**,却被解析成通用指针(类型信息丢失)—— 拒绝静默降级:"
|
||||
f"解析结果 BaseType={Info.BaseType} PtrCount={getattr(Info, 'PtrCount', None)} "
|
||||
f"IsStruct={getattr(Info, 'IsStruct', None)} IsTypedef={getattr(Info, 'IsTypedef', None)} "
|
||||
f"Name={getattr(Info, 'Name', None)};"
|
||||
f"符号表['{InnerName}'] => IsTypedef={getattr(_e, 'IsTypedef', None)} "
|
||||
f"BaseType={getattr(_e, 'BaseType', None)} PtrCount={getattr(_e, 'PtrCount', None)} "
|
||||
f"IsStruct={getattr(_e, 'IsStruct', None)} IsRenum={getattr(_e, 'IsRenum', None)} "
|
||||
f"IsModuleAlias={getattr(_e, 'IsModuleAlias', None)} "
|
||||
f"IsEnumMember={getattr(_e, 'IsEnumMember', None)};"
|
||||
f"Gen.structs 命中={'有' if InnerName in getattr(Gen, 'structs', {}) else '无'} "
|
||||
f"_struct_sha1_map 命中={getattr(Gen, '_struct_sha1_map', {}).get(InnerName)!r}"
|
||||
)
|
||||
|
||||
def LookupFunctionSymbol(self, name: str, *, module_path: str | None = None) -> CTypeInfo | None:
|
||||
"""查找函数符号,先尝试 module_path.name,再回退到 name。
|
||||
|
||||
|
||||
Reference in new issue
Block a user