From be1acdb602836c86bcf34c9106069133a3df1603 Mon Sep 17 00:00:00 2001 From: TermiNexus Date: Mon, 28 Sep 2026 15:38:42 +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=20TPC=20=E5=90=8C?= =?UTF-8?q?=E5=8F=A3=E5=BE=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 新增 _is_array_decay(复用 is_array_type + LLVMType.Array 解构 + AssignGen._stg_ty_equal),在 _pointee_convert_reason 的非基本分支里紧接 _is_inheritance_upcast 之后调用 与 TPC 真值表一致:数组→元素指针 ALLOW、反向 DENY、多维只退一层;其余规则(通用指针/层数/完全相同/None/构造物化/标量无损/继承上转)未动 --- App/lib/core/Gen/Expr/ExprGenBase.vp | 39 ++++++++++++++++++++++++++-- 1 file changed, 37 insertions(+), 2 deletions(-) diff --git a/App/lib/core/Gen/Expr/ExprGenBase.vp b/App/lib/core/Gen/Expr/ExprGenBase.vp index 1efca31..489c2bc 100644 --- a/App/lib/core/Gen/Expr/ExprGenBase.vp +++ b/App/lib/core/Gen/Expr/ExprGenBase.vp @@ -619,11 +619,41 @@ novirtual class ExprGenBase: i += 1 return 0 # ============================================================ + # _is_array_decay - 数组退让判据([N]T* → T*,单向) + # + # 规则 2 的豁免:源被指类型是**定长数组** Array(T, N),且目标被指类型恰为该 + # 数组的**元素类型** T ⇒ 允许隐式转换(数组指针 → 元素指针,C/C++ 同口径)。 + # 多维数组按「最外层退让一层」自然处理:Array(Array(T, M), N) 的元素是 + # Array(T, M) ⇒ Array(Array(T,M),N)* → Array(T,M)* 命中;→ T* 不命中 + # (元素是 Array(T,M) ≠ T)。反向 T* → Array(T,N)* 因源被指类型非数组而不命中。 + # 元素类型同一性复用本仓既有 AssignGen._stg_ty_equal(内容比较),不新造表。 + # 返回 1=允许退让 / 0=否。 + # ============================================================ + def _is_array_decay(self, pool: memhub.MemBuddy*, + src_pt: llvmlite.LLVMType*, + dst_pt: llvmlite.LLVMType*) -> int: + """源被指类型是定长数组且目标被指类型是其元素类型:1=是 / 0=否""" + if src_pt is None or dst_pt is None: + return 0 + if self.is_array_type(src_pt) == 0: + return 0 + elem: llvmlite.LLVMType* = None + match src_pt: + case llvmlite.LLVMType.Array(et, _): + elem = et + case _: + return 0 + if elem is None: + return 0 + return self.Gen.AssignGen._stg_ty_equal(pool, elem, dst_pt) + # ============================================================ # _pointee_convert_reason - 被指类型 src_pt → dst_pt(T*→U* 的 T→U 关系)判定码 # # 规则 2:T* → U*(T、U 都非通用指针)允许 ⇔ 被指类型 T → U 无损。 - # 豁免:T、U 都是已注册类且 U 是 T 的基类(含多级)时,Derived* → Base* + # 豁免一:T、U 都是已注册类且 U 是 T 的基类(含多级)时,Derived* → Base* # 继承上转允许(见 _is_inheritance_upcast)。 + # 豁免二:T 是定长数组、U 恰为其元素类型时,数组退让 [N]T* → T* 允许(单向, + # 见 _is_array_decay)。反向 T* → [N]T* 不命中,仍禁止。 # 规则 3:非基本类型 T 与其指针 T* 之间(值/指针互换)一律禁止——此处体现为 # 被指类型一侧是「非基本值类型」、另一侧是「其指针(或其它的基本/非基本类型)」 # 时一律不匹配 ⇒ PC_NONBASIC。 @@ -645,9 +675,14 @@ novirtual class ExprGenBase: return self._ptr_cast_reason(pool, src_pt, dst_pt) # 一侧是非基本类型(结构体/类/联合/数组/函数)→ 一般禁止 if self._is_basic_scalar_ty(src_pt) == 0 or self._is_basic_scalar_ty(dst_pt) == 0: - # 豁免:Derived* → Base* 继承上转(含多级)允许(C++/GCC 同口径) + # 豁免一:Derived* → Base* 继承上转(含多级)允许(C++/GCC 同口径) if self._is_inheritance_upcast(pool, src_pt, dst_pt) != 0: return PC_OK + # 豁免二:数组退让(单向)——源被指类型是定长数组 Array(T, N)、目标被指 + # 类型恰为其元素类型 T ⇒ 允许(数组指针 → 元素指针)。多维按最外层退让 + # 一层;反向 T → Array(T, N) 与其它非基本类型规则不变,仍禁止。 + if self._is_array_decay(pool, src_pt, dst_pt) != 0: + return PC_OK return PC_NONBASIC return self._scalar_convert_reason(src_pt, dst_pt) # ============================================================