fix(gen): 复合赋值取消「右值有符号 vs 左值无符号」拦截,与二元 x = x op y 口径一致(修 sizet += int 误报)
This commit is contained in:
1 parent
c9562a6e04
commit
c0ff5c9d96
1 file changed
+9
-11
@@ -1446,11 +1446,15 @@ novirtual class AssignGenMixin:
|
||||
# Double-pointer arithmetic: delegate the check to ExprGenOps.fail_if_double_ptr_binop
|
||||
self.Gen.ExprGenOps.fail_if_double_ptr_binop(pool, op, lhs, rhs, node, 1)
|
||||
|
||||
# x op= y 的操作数约束(fail-fast,先于运算与提升):
|
||||
# ① y 的有效宽度必须 <= x 的宽度。变量按其 LLVM 类型宽度;常量按其值的**最小可存宽度**
|
||||
# (所以 `u8 += 1` 合法、`u8 += 300` 报错)。y 更宽 = 隐式收窄,必须先显式收窄再写。
|
||||
# ② 不允许 y 显式有符号而 x 无符号:负值经符号扩展会变成巨大的无符号值,属静默语义改变。
|
||||
# 移位(<<= / >>=)**豁免** ①②:计数不是写回目标的值,改用静态范围检查(见下方)。
|
||||
# x op= y 的操作数宽度约束(fail-fast,先于运算与提升):
|
||||
# y 的有效宽度必须 <= x 的宽度。变量按其 LLVM 类型宽度;常量按其值的**最小可存宽度**
|
||||
# (所以 `u8 += 1` 合法、`u8 += 300` 报错)。y 更宽 = 隐式收窄,必须先显式收窄再写。
|
||||
# 移位(<<= / >>=)**豁免**:计数不是写回目标的值,改用静态范围检查(见下方)。
|
||||
#
|
||||
# 说明:右值有符号而左值无符号**不再单独拦截**——拓宽方向已由 sext/zext 规则统一决定
|
||||
# (i 类 sext、u 类 zext,见 wiki/Implicit.md §1.1),且二元形态 `x = x op y` 本就允许
|
||||
# (如 `sizet += int` 里 int 先拓宽到 u64 再相加)。两条路径口径必须一致,否则同一语义
|
||||
# 换个写法就报错。
|
||||
y_node_aa: ast.AST* = None
|
||||
if node is not None and node.kind() == ast.ASTKind.AugAssign: y_node_aa = ast.AugAssign*(node).value
|
||||
if lhs_bits != 0 and rhs_bits != 0 and op != ast.OpKind.LShift and op != ast.OpKind.RShift:
|
||||
@@ -1460,12 +1464,6 @@ novirtual class AssignGenMixin:
|
||||
if cn_aa.const_kind == ast.CONST_INT: y_bits_eff = self.define_min_width(cn_aa.int_val)
|
||||
if y_bits_eff > lhs_bits:
|
||||
self.Gen.TypeGenErr.fatal_error(node, f"[VPC] augmented assignment operand too wide: the right-hand side needs {y_bits_eff} bits, " f"but the target provides only {lhs_bits} bits; an implicit narrowing is forbidden. " f"Fix: narrow the right-hand side explicitly (e.g. uint{lhs_bits}(...) / int{lhs_bits}(...)) before the operation.", "CastError")
|
||||
x_uns_aa: int = 0
|
||||
if lhs_node is not None: x_uns_aa = self.Gen.ExprGenOps._node_type_unsigned(pool, lhs_node, trans)
|
||||
y_sgn_aa: int = 0
|
||||
if y_node_aa is not None: y_sgn_aa = self.Gen.ExprGenOps._node_type_signed(pool, y_node_aa, trans)
|
||||
if x_uns_aa != 0 and y_sgn_aa != 0:
|
||||
self.Gen.TypeGenErr.fatal_error(node, "[VPC] augmented assignment operand signedness conflict: the right-hand side is explicitly signed " "while the target is unsigned; sign extension would turn negative values into huge unsigned values. " "Fix: use an unsigned right-hand side (e.g. uint32(...)), or make the target signed.", "CastError")
|
||||
|
||||
# Integer op: type promotion
|
||||
if lhs_bits > rhs_bits and rhs_bits > 0: rhs = self.Gen.ExprGenBase.coerce_to_type(builder, rhs, lhs.Ty, node, trans)
|
||||
|
||||
Reference in new issue
Block a user