feat(cast): 放行数组退让([N]T* → T* 单向),与 TPC 同口径
新增 _is_array_decay(复用 is_array_type + LLVMType.Array 解构 + AssignGen._stg_ty_equal),在 _pointee_convert_reason 的非基本分支里紧接 _is_inheritance_upcast 之后调用 与 TPC 真值表一致:数组→元素指针 ALLOW、反向 DENY、多维只退一层;其余规则(通用指针/层数/完全相同/None/构造物化/标量无损/继承上转)未动
This commit is contained in:
1 parent
e2c4c7645e
commit
be1acdb602
1 file changed
+37
-2
@@ -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)
|
||||
# ============================================================
|
||||
|
||||
Reference in new issue
Block a user