From b51faef1cb07c5f0f05f073c8737b2154adcb6e3 Mon Sep 17 00:00:00 2001 From: TermiNexus Date: Wed, 14 Oct 2026 21:12:56 +0800 Subject: [PATCH] =?UTF-8?q?fix(tpc):=20=E5=B8=A6=E6=B3=A8=E8=A7=A3?= =?UTF-8?q?=E9=87=8D=E5=A3=B0=E6=98=8E=E5=86=B2=E7=AA=81=E4=B8=8D=E5=86=8D?= =?UTF-8?q?=E9=9D=99=E9=BB=98=E4=B8=A2=20store=EF=BC=8C=E6=94=B9=E4=B8=BA?= =?UTF-8?q?=20fail-fast=20=E6=8A=A5=E9=94=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 原有变量分支整段包在 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)。现改为捕获后重抛带变量名/两侧类型的清晰错误。 --- lib/core/Handles/HandlesAnnAssign.py | 43 +++++++++++++++++----------- 1 file changed, 27 insertions(+), 16 deletions(-) diff --git a/lib/core/Handles/HandlesAnnAssign.py b/lib/core/Handles/HandlesAnnAssign.py index b4991b1..36dc36f 100644 --- a/lib/core/Handles/HandlesAnnAssign.py +++ b/lib/core/Handles/HandlesAnnAssign.py @@ -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: