diff --git a/lib/core/Handles/HandlesBase.py b/lib/core/Handles/HandlesBase.py index 503d675..090d953 100644 --- a/lib/core/Handles/HandlesBase.py +++ b/lib/core/Handles/HandlesBase.py @@ -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。