From 6a672037c29a44ee505b3d4da8fe348162ff883c Mon Sep 17 00:00:00 2001 From: TermiNexus Date: Thu, 13 Aug 2026 07:44:43 +0800 Subject: [PATCH] =?UTF-8?q?fix(attr):=20=E4=BF=AE=E5=A4=8D=E8=81=94?= =?UTF-8?q?=E5=90=88=E7=B1=BB=E5=9E=8B=E8=BD=AC=E6=8D=A2=20(X=20|=20t.CPtr?= =?UTF-8?q?)(arg)=20=E5=90=8E=E5=B1=9E=E6=80=A7=E8=AE=BF=E9=97=AE=E8=A2=AB?= =?UTF-8?q?=E4=B8=A2=E5=BC=83?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit TPC 联合转换对非 CType 类(ast.Name/ast.Call 等类名)目标类型解析失败, 结果退回 Ptr(i8) 或错误类型,_handle_attr_call_result 的 find_struct_by_pointee 失败后返回 None,属性访问被静默丢弃—— ((ast.Name|t.CPtr)(ov)).id 编译产物 store 0 次(TPV with 语句 asname 未绑定、pool 未定义根因)。修复:从联合 BinOp 提取真实基础类并 bitcast 到 Ptr(类) 再定位成员偏移;新增 _extract_union_base_class 辅助(跳过 CPtr/存储类/限定符修饰符)。 --- lib/core/Handles/HandlesExprAttr.py | 55 ++++++++++++++++++++++++++++- 1 file changed, 54 insertions(+), 1 deletion(-) diff --git a/lib/core/Handles/HandlesExprAttr.py b/lib/core/Handles/HandlesExprAttr.py index d4b154d..0322d6e 100644 --- a/lib/core/Handles/HandlesExprAttr.py +++ b/lib/core/Handles/HandlesExprAttr.py @@ -761,7 +761,25 @@ class ExprAttrHandle(BaseHandle): ObjVal = inner_val if ObjVal is None: ObjVal = self.HandleExprLlvm(Node.value) - if not ObjVal or not isinstance(ObjVal.type, ir.PointerType): + if not ObjVal: + return None + # 联合类型转换 (X | t.CPtr)(arg) 的属性访问(治本修复): + # TPC 联合转换对非 CType 类(如 ast.Name / ast.Call)目标类型解析失败, + # 结果可能退回 Ptr(i8) 或错误类型,导致下方 find_struct_by_pointee 失败、 + # 属性访问被静默丢弃——((ast.Name|t.CPtr)(ov)).id 编译后 store 0 次 + # (with 语句 asname 未绑定、pool 未定义根因)。从联合 BinOp 提取真实 + # 基础类并 bitcast 到 Ptr(类) 再访问成员。 + if isinstance(Node.value, ast.Call) and isinstance(Node.value.func, ast.BinOp) \ + and isinstance(Node.value.func.op, ast.BitOr): + union_cls: str | None = self._extract_union_base_class(Node.value.func) + if union_cls and union_cls in Gen.structs: + target_ty: Any = ir.PointerType(Gen.structs[union_cls]) + if isinstance(ObjVal.type, ir.PointerType): + if ObjVal.type != target_ty: + ObjVal = Gen.builder.bitcast(ObjVal, target_ty, name="cast_union_attr") + elif isinstance(ObjVal.type, ir.IntType): + ObjVal = Gen.builder.inttoptr(ObjVal, target_ty, name="int2ptr_union_attr") + if not isinstance(ObjVal.type, ir.PointerType): return None pointee: Any = ObjVal.type.pointee if isinstance(pointee, ir.PointerType): @@ -789,6 +807,41 @@ class ExprAttrHandle(BaseHandle): return None return self._gep_and_Load_member(Gen, ObjVal, offset, Node.attr, CN, st) + def _extract_union_base_class(self, NodeFunc: ast.BinOp) -> str | None: + """从 (X | t.CPtr) 联合 BinOp 提取第一个非指针/非修饰符的类名 + + X 可以是任意类(如 ast.Name / ast.Call / memhub.MemPool),不限于 + t.CType 子类——联合转换 (X | t.CPtr)(arg) 的属性访问需要真实类名 + 才能 bitcast 到 Ptr(类) 并定位成员偏移。 + """ + if not isinstance(NodeFunc, ast.BinOp) or not isinstance(NodeFunc.op, ast.BitOr): + return None + skip_names = { + 'CPtr', 'CArrayPtr', 'CConst', 'CVolatile', 'CInline', + 'CStatic', 'CExtern', 'CExport', 'CAuto', 'CRegister', + 'CDefine', 'CPass', 'CTypeDefault', 'State', + 'BigEndian', 'LittleEndian', + } + operands: list = [] + + def _collect(node: ast.AST) -> None: + if isinstance(node, ast.BinOp) and isinstance(node.op, ast.BitOr): + _collect(node.left) + _collect(node.right) + else: + operands.append(node) + + _collect(NodeFunc) + for op in operands: + name: str | None = None + if isinstance(op, ast.Attribute): + name = op.attr + elif isinstance(op, ast.Name): + name = op.id + if name and name not in skip_names: + return name + return None + def _handle_attr_subscript_result(self, Node: ast.Attribute) -> ir.Value | None: """处理 arr[i].attr 属性访问""" Gen: LlvmCodeGenerator = self.Trans.LlvmGen