From 97c196bfc7ad92dd4e1c2e019ea214293ecc8694 Mon Sep 17 00:00:00 2001 From: TermiNexus Date: Mon, 28 Sep 2026 15:38:41 +0800 Subject: [PATCH] =?UTF-8?q?feat(cast):=20=E6=94=BE=E8=A1=8C=E6=95=B0?= =?UTF-8?q?=E7=BB=84=E9=80=80=E8=AE=A9=EF=BC=88[N]T*=20=E2=86=92=20T*=20?= =?UTF-8?q?=E5=8D=95=E5=90=91=EF=BC=89=EF=BC=8C=E4=B8=8E=E7=BB=A7=E6=89=BF?= =?UTF-8?q?=E4=B8=8A=E8=BD=AC=E5=90=8C=E5=A4=84=E5=88=A4=E6=8D=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 在 _ClassifyPtrImplicitConvert 的“被指类型非基本”分支里、继承上转之后加数组退让分支:源的被指类型是 ir.ArrayType 且其 element 与目标被指类型相同 ⇒ 放行(C/C++ 同口径) 判据顺序(两侧一致):层数不同即禁 → 完全相同放行 → 通用指针通配 → 标量无损/有损 → 继承上转 → 数组退让 → 否则 DENY;反向 T*→[N]T*、多维只退一层([N][M]T*→[M]T* 放行、→T* 不放行) --- lib/core/LLVMCG/MemoryOps.py | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) 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, '非指针间(本判据不裁决)')