fix(codegen): 指针强转基座 T*(x) 的字段写入补联合类名通道

与读取侧 _handle_attr_call_result 的联合分支同口径:_get_attr_ptr 新增 Call 基座分支,用 _extract_union_base_class 取裸类名后 bitcast/inttoptr 回 Ptr(类) 再 GEP 成员。此前写入侧只认 Name/Attribute/Subscript,强转基座的字段写入静默返回 None。
This commit is contained in:
TermiNexus committed 2026-09-27 16:02:40 +08:00
1 parent 5825e7e000
commit e33ac795ed
1 file changed
+29
+29
View File
@@ -1527,6 +1527,35 @@ class ExprAttrHandle(BaseHandle):
if offset is not None:
MemberPtr = Gen.builder.gep(SubPtr, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), offset)], name=Node.attr)
return MemberPtr
elif isinstance(Node.value, ast.Call):
# 指针强转基座(`(ast.Call*(vinner)).IsVolatile = 1`):`T*(x)` 被 vast 的
# _ConsumePtrSuffixCall 解析为 `(T | t.CPtr)(x)` 强转调用,结果类型是联合
# 简化后的 i8*(struct 身份丢失),故须从强转注解(func 是 BitOr 联合)
# 提真实类名,bitcast/inttoptr 回 Ptr(类) 后 GEP 成员。
# 与读取侧 _handle_attr_call_result 的联合分支(_extract_union_base_class)
# 逐字同口径;此前写入侧只认 Name/Attribute/Subscript,强转基座的字段
# 写入一律静默返回 None。
ObjVal: Any = self.HandleExprLlvm(Node.value)
if ObjVal is not None and isinstance(Node.value.func, ast.BinOp) \
and isinstance(Node.value.func.op, ast.BitOr):
UnionCls: str | None = self._extract_union_base_class(Node.value.func)
if UnionCls and UnionCls in Gen.structs:
ST: Any = Gen.structs[UnionCls]
if isinstance(ST, ir.IdentifiedStructType) and (ST.elements is None or len(ST.elements) == 0):
self.Trans.ImportHandler._TryLoadStructFromStub(UnionCls, Gen)
ST = Gen.structs.get(UnionCls, ST)
TargetPtrTy: Any = ir.PointerType(ST)
if isinstance(ObjVal.type, ir.PointerType):
if ObjVal.type != TargetPtrTy:
ObjVal = Gen.builder.bitcast(ObjVal, TargetPtrTy, name=f"cast_{UnionCls}")
elif isinstance(ObjVal.type, ir.IntType):
ObjVal = Gen.builder.inttoptr(ObjVal, TargetPtrTy, name=f"int2ptr_{UnionCls}")
else:
return None
offset: int | None = Gen._get_member_offset(Node.attr, UnionCls)
if offset is not None:
MemberPtr = Gen.builder.gep(ObjVal, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), offset)], name=Node.attr)
return MemberPtr
return None
def _HandleSliceLlvm(self, base_val: ir.Value, slice_node: ast.Slice | ast.Index, base_ast: ast.AST) -> ir.Value | None: