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:
1 parent
9f8190d58f
commit
171b0e3eeb
1 file changed
+51
-3
@@ -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, '非指针间(本判据不裁决)')
|
||||
|
||||
Reference in new issue
Block a user