fix(cast): 补继承上转豁免(Derived*→Base* 允许隐式转换),修 MemBuddy*→MemManager* 被规则③误拦

_ClassifyPtrImplicitConvert 由 staticmethod 改实例方法(全仓 5 处调用均为 self./Gen.,无 unbound 调用);新增 _ClassNameOfPointee(复用 Gen.find_struct_by_pointee + 短名回退)与 _IsInheritanceUpcastPointee(复用 Gen._get_mro_chain);两指针皆非基本标量时先判上转再判禁

保持:Base*→Derived* 仍禁(下转须显式强转)、无关结构体互转仍禁、通用指针通配/层数/完全相同/None/构造物化/标量无损口径不变
This commit is contained in:
TermiNexus committed 2026-09-28 15:29:41 +08:00
1 parent 9f8190d58f
commit 171b0e3eeb
1 file changed
+51 -3
+51 -3
View File
@@ -222,14 +222,58 @@ class MemoryOpsMixin:
return False
return False
@staticmethod
def _ClassifyPtrImplicitConvert(Src: Any, Dst: Any) -> tuple[bool, str]:
def _ClassNameOfPointee(self, Pointee: Any) -> str | None:
"""把 LLVM 被指类型映射到已注册类名(复用本仓既有 find_struct_by_pointee;
身份比较失败时按短名(去 sha1 前缀)回退匹配 Gen.structs,与 HandlesAssign
既有回退同口径)。非结构体 / 未注册 → None。不新造表。
"""
if Pointee is None:
return None
Found: Any = self.find_struct_by_pointee(Pointee)
if Found:
return Found[0]
if isinstance(Pointee, ir.IdentifiedStructType):
PShort: str = self._extract_short_name(Pointee.name)
if PShort:
for CN, ST in self.structs.items():
if isinstance(ST, ir.IdentifiedStructType) and \
self._extract_short_name(ST.name) == PShort:
return CN
return None
def _IsInheritanceUpcastPointee(self, SrcPointee: Any, DstPointee: Any) -> bool:
"""继承上转判据:SrcPointee → DstPointee 是否为「派生类 → 基类」(含多级)。
复用本仓既有继承判据:_ClassNameOfPointee(→ find_struct_by_pointee)取
类名,Gen._get_mro_chain 取 MRO 线性化(含自身,父类在后)。目标类名落在
源类名 MRO 链「自身之后」⇒ 允许上转(Derived* → Base*,C++/GCC 同口径);
下转(Base* → Derived*)与无关类型(Foo* ↔ Bar*)不命中 ⇒ False。
"""
SrcName: str | None = self._ClassNameOfPointee(SrcPointee)
if not SrcName:
return False
DstName: str | None = self._ClassNameOfPointee(DstPointee)
if not DstName:
return False
SrcShort: str = self._extract_short_name(SrcName)
DstShort: str = self._extract_short_name(DstName)
if SrcShort == DstShort:
return False
Chain: list[str] = self._get_mro_chain(SrcName)
for Anc in Chain[1:]:
if self._extract_short_name(Anc) == DstShort:
return True
return False
def _ClassifyPtrImplicitConvert(self, Src: Any, Dst: Any) -> tuple[bool, str]:
"""隐式转换判据:返回 (Allowed, Reason)。
规则(用户决定,与 TransPyV 同口径):
① 通用指针(t.CPtr/i8*)为通配:与任何 T* **双向**互转放行(须同级)。
② T* → U*(皆非通用):允许 ⇔ 被指类型 T → U 无损;非基本类型
(结构体/类/联合)一律不允许 ⇒ Foo*→Bar* 禁止。
(结构体/类/联合)一律不允许 ⇒ Foo*→Bar* 禁止;**唯一例外**是
继承上转 Derived* → Base*(目标被指类型是源被指类型的基类,含多级)
——见 _IsInheritanceUpcastPointee。下转 Base* → Derived* 仍禁止。
③ 非基本类型 T 与 T* 之间的隐式转换(Foo ↔ Foo*)一律禁止(层数不同);
**唯一例外**是「构造物化」——该豁免需 AST 层判据,故在 coerce 调用点
由 _CtorCallStructType 单独放行(本判据只给出「禁」的结论)。
@@ -253,6 +297,10 @@ class MemoryOpsMixin:
if MemoryOpsMixin._ScalarConvertLossless(sp, dp):
return (True, '被指类型无损')
return (False, '被指类型有损')
# 豁免:Derived* → Base* 继承上转(目标被指类型是源被指类型的基类,
# 含多级)允许(C++/GCC 同口径);下转/无关类型不命中,仍禁止。
if self._IsInheritanceUpcastPointee(sp, dp):
return (True, '继承上转(派生类指针 → 基类指针)')
return (False, '非基本类型(结构体/类/联合)')
if not s_ptr and not d_ptr:
return (True, '非指针间(本判据不裁决)')