fix(codegen): 指针强转基座 T*(x) 的字段读写补按需过滤类名通道
(ast.Call*(vinner)).IsVolatile 报属性写入失败:T*(x) 被 parser 的 _consume_ptr_suffix_call 解析成 (T | t.CPtr)(x) 强转调用,结果类型是联合简化后的 i8*,lookup_field(i8,...) 必失败,而按需过滤的类名提取只认 Name/Attribute。新增 _base_class_from_cast_base:从强转注解(func 是 BitOr 联合)取裸类名,读路径、写路径、属性链递归父节点三处接入。取裸名而非模块限定名——lookup_field_by_class 的模块限定分支对「包名可解析、类注册在子模块」的形态会 fail-fast。
This commit is contained in:
1 parent
beccb36b66
commit
0279965074
1 file changed
+66
@@ -832,6 +832,11 @@ novirtual class ExprGenAttr(ExprGenBase.ExprGenBase):
|
||||
# Mod.g,如 GenApi._g_gen)——缺此则 Mod.g.Field[.Field] 的
|
||||
# 接收者类解析不出(末跳 lookup_field 必然失败)。
|
||||
base_class = self._resolve_attr_field_class(pool, trans, at.value, 1)
|
||||
elif at.value.kind() == ast.ASTKind.Call:
|
||||
# 指针强转基座(`(ast.Call*(x)).IsVolatile`):`T*(x)` 的结果
|
||||
# 类型是联合简化后的 i8*,须从强转注解提类名,详见
|
||||
# _base_class_from_cast_base 头注释
|
||||
base_class = self._base_class_from_cast_base(pool, trans, at.value)
|
||||
if base_class is not None:
|
||||
cur_sha1: str = trans.ModuleSha1
|
||||
field_info = self.Gen.StructGen.lookup_field_by_class(base_class, at.attr, cur_sha1, at, trans._from_imports)
|
||||
@@ -1020,6 +1025,10 @@ novirtual class ExprGenAttr(ExprGenBase.ExprGenBase):
|
||||
parent_class = self.Gen.VarGen.var_annot_class_name(var_entry)
|
||||
elif at.value.kind() == ast.ASTKind.Attribute:
|
||||
parent_class = self._resolve_attr_field_class(pool, trans, at.value, allow_module_global)
|
||||
elif at.value.kind() == ast.ASTKind.Call:
|
||||
# 指针强转基座(`(T*(x)).f.g` 的递归父节点):从强转注解提取类名,
|
||||
# 详见 _base_class_from_cast_base 头注释
|
||||
parent_class = self._base_class_from_cast_base(pool, trans, at.value)
|
||||
else: return None
|
||||
if parent_class is None: return None
|
||||
# 在父类中查 at.attr 字段,返回其注解类名
|
||||
@@ -1031,6 +1040,58 @@ novirtual class ExprGenAttr(ExprGenBase.ExprGenBase):
|
||||
if fe is None: return None
|
||||
return self.Gen.StructGen.get_field_annot_class_name(fe)
|
||||
|
||||
# ============================================================
|
||||
# _base_class_from_cast_base - 指针强转基座 `T*(x)` 的类名
|
||||
#
|
||||
# `T*(x)` 被 parser 的 _consume_ptr_suffix_call 解析成 `(T | t.CPtr)(x)`
|
||||
# 强转调用(与手写 `(T | t.CPtr)(x)` 逐字同形),与 `t.CPtr` 取联合后结果
|
||||
# 的 LLVM 类型是**简化后的 i8***。于是 `(ast.Call*(vinner)).IsVolatile`
|
||||
# 这类强转基座的字段访问/写入里 lookup_field(i8, ...) 必然失败。
|
||||
#
|
||||
# 此函数从强转注解 func(BinOp)提取类名,交给既有的「按需过滤」分支
|
||||
# bitcast 回真实结构体类型后查字段——与 Name 变量注解、Attribute 字段注解
|
||||
# 两条路径同口径(见 _resolve_attr_field_class 头注释)。
|
||||
#
|
||||
# 只认 func 是 BinOp 的形态:BinOp 作 callee 只可能是类型注解
|
||||
# (见 CallGenMixin 的联合强转分支),普通函数调用不会命中,故无误伤。
|
||||
#
|
||||
# **取裸类名**(`ast.Call` → `"Call"`)而非 TypeGenResolve
|
||||
# .extract_class_name_from_annotation 的模块限定名:后者对 `ast.Call`
|
||||
# 返回 "ast.Call",而 lookup_field_by_class 的模块限定分支对「模块段可解析、
|
||||
# 但类注册在子模块」的形态会 fail-fast(模块段取到包名 "ast" 的 sha1,类
|
||||
# entry 的 ModuleSha1 却是子模块 exprs 的,find_struct_by_module 必失败)。
|
||||
# 裸名走「按类名查找第一个」回退,与 TPC _extract_union_base_class 同口径。
|
||||
# ============================================================
|
||||
def _base_class_from_cast_base(self, pool: memhub.MemBuddy*,
|
||||
trans: HT.Translator*,
|
||||
node: ast.AST*) -> str:
|
||||
"""`T*(x)` 强转基座的裸类名;非该形态返回 None"""
|
||||
if node is None or trans is None:
|
||||
return None
|
||||
if node.kind() != ast.ASTKind.Call:
|
||||
return None
|
||||
cl_cb: ast.Call* = ast.Call*(node)
|
||||
if cl_cb.func is None or cl_cb.func.kind() != ast.ASTKind.BinOp:
|
||||
return None
|
||||
bo_cb: ast.BinOp* = ast.BinOp*(cl_cb.func)
|
||||
if bo_cb.op != ast.OpKind.BitOr:
|
||||
return None
|
||||
# 联合一侧是 t.CPtr 标记(`T | t.CPtr` / `T**` 展开的嵌套联合)时取另一侧;
|
||||
# 否则(手写 `X | Y`)取左侧——与 parser 的 _make_ptr_type 产物一致。
|
||||
tgt_cb: ast.AST* = bo_cb.left
|
||||
if self.Gen.TypeGenResolve._is_cptr_marker(bo_cb.left, trans._imported_modules) != 0:
|
||||
tgt_cb = bo_cb.right
|
||||
if tgt_cb is None:
|
||||
return None
|
||||
k_cb: int = tgt_cb.kind()
|
||||
if k_cb == ast.ASTKind.Attribute:
|
||||
at_cb: ast.Attribute* = ast.Attribute*(tgt_cb)
|
||||
return at_cb.attr
|
||||
if k_cb == ast.ASTKind.Name:
|
||||
nm_cb: ast.Name* = ast.Name*(tgt_cb)
|
||||
return nm_cb.id
|
||||
return None
|
||||
|
||||
# ============================================================
|
||||
# _resolve_module_global_class_name - 「模块名.全局变量」Mod.g 的结构体类名
|
||||
#
|
||||
@@ -1328,6 +1389,11 @@ novirtual class ExprGenAttr(ExprGenBase.ExprGenBase):
|
||||
# allow_module_global=1:同 translate_attribute(基座可为
|
||||
# 「模块名.全局变量」,如 GenApi._g_gen.TypeGenCDef)
|
||||
base_class = self._resolve_attr_field_class(pool, trans, at.value, 1)
|
||||
elif at.value.kind() == ast.ASTKind.Call:
|
||||
# 指针强转基座(`(ast.Call*(vinner)).IsVolatile = 1`):
|
||||
# `T*(x)` 的结果类型是联合简化后的 i8*,须从强转注解提类名,
|
||||
# 详见 _base_class_from_cast_base 头注释
|
||||
base_class = self._base_class_from_cast_base(pool, trans, at.value)
|
||||
if base_class is not None:
|
||||
cur_sha1: str = None
|
||||
lfi_gp: str = None
|
||||
|
||||
Reference in new issue
Block a user