diff --git a/lib/core/LLVMCG/MemoryOps.py b/lib/core/LLVMCG/MemoryOps.py index 1047a2d..42b54a2 100644 --- a/lib/core/LLVMCG/MemoryOps.py +++ b/lib/core/LLVMCG/MemoryOps.py @@ -271,9 +271,11 @@ class MemoryOpsMixin: 规则(用户决定,与 TransPyV 同口径): ① 通用指针(t.CPtr/i8*)为通配:与任何 T* **双向**互转放行(须同级)。 ② T* → U*(皆非通用):允许 ⇔ 被指类型 T → U 无损;非基本类型 - (结构体/类/联合)一律不允许 ⇒ Foo*→Bar* 禁止;**唯一例外**是 + (结构体/类/联合)一律不允许 ⇒ Foo*→Bar* 禁止;**例外**有二: 继承上转 Derived* → Base*(目标被指类型是源被指类型的基类,含多级) - ——见 _IsInheritanceUpcastPointee。下转 Base* → Derived* 仍禁止。 + ——见 _IsInheritanceUpcastPointee;数组退让 [N]T* → T*(目标被指类型 + 是源被指数组的元素类型,单向)——见下。下转 Base* → Derived*、反向 + T* → [N]T* 仍禁止。 ③ 非基本类型 T 与 T* 之间的隐式转换(Foo ↔ Foo*)一律禁止(层数不同); **唯一例外**是「构造物化」——该豁免需 AST 层判据,故在 coerce 调用点 由 _CtorCallStructType 单独放行(本判据只给出「禁」的结论)。 @@ -301,6 +303,14 @@ class MemoryOpsMixin: # 含多级)允许(C++/GCC 同口径);下转/无关类型不命中,仍禁止。 if self._IsInheritanceUpcastPointee(sp, dp): return (True, '继承上转(派生类指针 → 基类指针)') + # 豁免:数组退让(单向)——源的被指类型是定长数组 [N]T、目标的被指类型 + # 恰为该数组的**元素类型** T ⇒ 允许(数组指针 → 元素指针,C/C++ 同口径)。 + # 多维数组按「最外层退让一层」自然处理:[N][M]T* → [M]T* 命中(元素即 + # [M]T),[N][M]T* → T* 不命中(元素是 [M]T ≠ T)。反向 T* → [N]T* 因 + # 源的被指类型非数组而不命中,仍按下方非基本类型禁止。元素类型同一性 + # 复用本处既有的 `==` 口径(与 sp == dp / 数组元素比较一致)。 + if isinstance(sp, ir.ArrayType) and sp.element == dp: + return (True, '数组退让(数组指针 → 元素指针)') return (False, '非基本类型(结构体/类/联合)') if not s_ptr and not d_ptr: return (True, '非指针间(本判据不裁决)')