fix(类型转换): int→i1 目标改为真值归一化 != 0,不再 trunc 取最低位
类别:a(编译器缺陷)。`b: bool = f()`(f 运行时返回偶数非零,如 2)此前经 coerce_to_type 的窄化分支走 trunc ⇒ 最低位 0 ⇒ false,而同一值在 `if 2:` / `bool(2)`(icmp ne 0)为真 —— 两处判据相反(静默语义分裂)。 - ExprGenBase.coerce_to_type:整数窄化分支前先判目标位宽 == 1 ⇒ `icmp ne x, 0` (C 6.3.1.2 的 _Bool 转换语义)。归一化不丢位,故对 i1 目标不再适用下方 「窄化截断溢出」常量诊断(先返回)——`b: bool = 2` 由编译期 OverflowError 变为正确的 true。 - CallGenCtor._translate_t_type_cast:显式 `t.CBool(x)` 与隐式落存储同一判据。 判据与 bool(x)(CallGenDispatch.vp:255-281)、条件归一化(AsyncGenMixin.vp:1611 _normalize_cond)、and/or 操作数三处统一。App/ 与 includes/ 全量检索未见 `: bool = …(& | >> | // | |)` 位提取写法,既有代码无依赖 trunc 取最低位的点。 生效需重新自举 TransPyV.exe(并清缓存)。
This commit is contained in:
1 parent
ef4421db20
commit
2a798dd643
2 files changed
+18
No files matched your search
@@ -686,6 +686,13 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase):
|
||||
return llvmlite.build_zext(builder, val, target_ty)
|
||||
return llvmlite.build_sext(builder, val, target_ty)
|
||||
else:
|
||||
# 目标 i1(bool / t.CBool):显式强转 `t.CBool(x)` 与隐式落存储
|
||||
# **同一判据** —— 真值归一化 `x != 0 → 1/0`(coerce_to_type 的同名
|
||||
# 分支、CallGenDispatch 的 bool(x)、条件归一化三处一致),不是
|
||||
# trunc(取最低位,会让 x=2 得 false 而 `if 2:` 为真)。
|
||||
if target_bits == 1:
|
||||
zero_tc: llvmlite.Value* = llvmlite.const_int(pool, val_bits, 0)
|
||||
return llvmlite.build_icmp(builder, llvmlite.ICMP_NE, val, zero_tc)
|
||||
return llvmlite.build_trunc(builder, val, target_ty)
|
||||
|
||||
# 整数 → 浮点: sitofp
|
||||
|
||||
@@ -865,6 +865,17 @@ novirtual class ExprGenBase:
|
||||
if val_bits != 0 and target_bits != 0:
|
||||
if val_bits == target_bits:
|
||||
return val
|
||||
# 目标 i1(bool / t.CBool):**真值归一化** `x != 0 → 1/0`(C 6.3.1.2 的
|
||||
# _Bool 转换语义),不是 trunc(取最低位)。判据与 `bool(x)`
|
||||
# (CallGenDispatch.vp:255-281)、条件归一化(AsyncGenMixin.vp:1611
|
||||
# _normalize_cond)、and/or 操作数三处**同一**:同一个运行时值 2 在
|
||||
# `if 2:` 里为真,赋给 bool 变量/字段/形参必须同样为真。此处此前走 trunc
|
||||
# ⇒ 值 2 取最低位得 0 → false,与条件上下文结论相反(静默语义分裂);
|
||||
# 值 3 得 true 而同值域下 `!= 0` 亦为 true,故只在偶数非零时暴露。
|
||||
# 归一化不丢位 ⇒ 下方「窄化截断溢出」常量诊断对 i1 目标不适用(先返回)。
|
||||
if target_bits == 1:
|
||||
zero_i1: llvmlite.Value* = llvmlite.const_int(builder.Pool, val_bits, 0)
|
||||
return llvmlite.build_icmp(builder, llvmlite.ICMP_NE, val, zero_i1)
|
||||
if val_bits < target_bits:
|
||||
# 统一 zext/sext(问题2修正):i1/i8 默认 zext;AST 节点解析为
|
||||
# 无符号类型(t.CUIntXXT 强转/无符号类型名)走 zext;否则 sext。
|
||||
|
||||
Reference in new issue
Block a user