fix(tpc): 带注解重声明冲突不再静默丢 store,改为 fail-fast 报错

原有变量分支整段包在 try/except Exception 里,隐式窄化抛出的 FailFastError 被吞成一条 strict 警告 ⇒ alloca 已建、store 整条丢失 ⇒ 之后 load 读到未初始化栈槽(运行期随机崩溃,且无任何编译期提示)。现场:ViperC 由 TPC 引导时 Converter.vp 'di: sizet = ai - (an - dn)'(di 已由 for 循环绑定为 int/i32)→ 生成的 viperc.exe 在 list[AST*].get 处 ASan 越界读(READ 0x1296f00c1808)。现改为捕获后重抛带变量名/两侧类型的清晰错误。
This commit is contained in:
TermiNexus committed 2026-10-14 21:12:56 +08:00
1 parent 5f1d2c3300
commit b51faef1cb
1 file changed
+27 -16
+27 -16
View File
@@ -891,23 +891,34 @@ class AnnAssignHandle(BaseHandle):
Gen._record_var_signedness(VarName, IsUnsigned)
return
if InitValue:
try:
VarPtr: ir.Value = Gen.variables[VarName]
if isinstance(VarPtr.type, ir.PointerType):
TargetType: ir.Type = VarPtr.type.pointee
if InitValue.type != TargetType:
# 统一走 `_coerce_value`(隐式转换的唯一收敛点):
# 此前这里手写 `zext/trunc`,整型加宽一律 zext ⇒ 负常量被当无符号
# 处理(现场:`b: int64 = -196608` 落成 0x00000000FFFD0000 大正数,
# IntWidthTest Test 5/6 的 FAIL)。`_coerce_value` 对 i32→i64 用
# `sext` 保持符号,隐式窄化亦按规则 fail-fast。
# 【不再静默兜底】此前整段包在 `try/except Exception` 里,转换/落址失败
# 只记一条 strict 警告就继续 ⇒ alloca 已建、store 被跳过 ⇒ 之后 load 读到
# 未初始化栈槽(运行期随机崩溃)。现场:ViperC 由 TPC 引导时
# Converter.vp `di: sizet = ai - (an - dn)` 与 for 循环变量 `di`(int/i32)
# 冲突 → store 整条丢失 → 生成的 viperc.exe 在 list[AST*].get 处
# ASan 越界读(READ 0x1296f00c1808)。
VarPtr: ir.Value = Gen.variables[VarName]
if isinstance(VarPtr.type, ir.PointerType):
TargetType: ir.Type = VarPtr.type.pointee
if InitValue.type != TargetType:
# 统一走 `_coerce_value`(隐式转换的唯一收敛点):
# 此前这里手写 `zext/trunc`,整型加宽一律 zext ⇒ 负常量被当无符号
# 处理(现场:`b: int64 = -196608` 落成 0x00000000FFFD0000 大正数,
# IntWidthTest Test 5/6 的 FAIL)。`_coerce_value` 对 i32→i64 用
# `sext` 保持符号,隐式窄化亦按规则 fail-fast。
from lib.core.LLVMCG.FuncGen import FailFastError
try:
_coerced: ir.Value | None = Gen._coerce_value(InitValue, TargetType, Node)
if _coerced is not None:
InitValue = _coerced
Gen._store(InitValue, VarPtr)
except Exception as _e:
if _config_mode == "strict":
self.Trans.LogWarning(f"异常被忽略: {_e}")
except FailFastError as _cce:
raise FailFastError(
f"带注解重声明冲突:变量 '{VarName}' 已有存储类型 {TargetType}"
f"(来自前面的声明或循环变量),此处注解声明的右值类型为 "
f"{InitValue.type},无法收窄进既有存储;请改用另一个变量名,"
f"或让既有声明与注解类型一致。原始错误:{_cce}"
) from None
if _coerced is not None:
InitValue = _coerced
Gen._store(InitValue, VarPtr)
Gen._record_var_signedness(VarName, IsUnsigned)
return
if VarName in Gen.global_vars: