feat(cast): 放行数组退让([N]T* → T* 单向),与继承上转同处判据

在 _ClassifyPtrImplicitConvert 的“被指类型非基本”分支里、继承上转之后加数组退让分支:源的被指类型是 ir.ArrayType 且其 element 与目标被指类型相同 ⇒ 放行(C/C++ 同口径)

判据顺序(两侧一致):层数不同即禁 → 完全相同放行 → 通用指针通配 → 标量无损/有损 → 继承上转 → 数组退让 → 否则 DENY;反向 T*→[N]T*、多维只退一层([N][M]T*→[M]T* 放行、→T* 不放行)
This commit is contained in:
TermiNexus committed 2026-09-28 15:38:41 +08:00
1 parent 171b0e3eeb
commit 97c196bfc7
1 file changed
+12 -2
+12 -2
View File
@@ -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, '非指针间(本判据不裁决)')