diff --git a/lib/core/Handles/HandlesExprOps.py b/lib/core/Handles/HandlesExprOps.py index 5a090c9..476a7d4 100644 --- a/lib/core/Handles/HandlesExprOps.py +++ b/lib/core/Handles/HandlesExprOps.py @@ -140,9 +140,11 @@ class ExprOpsHandle(BaseHandle): RightVal = Gen.builder.zext(RightVal, LeftVal.type, name="zext_deref_right") elif RightVal.type.width > LeftVal.type.width: LeftVal = Gen.builder.zext(LeftVal, RightVal.type, name="zext_left_deref") - if Op in ('>>', 'RShift') and isinstance(Node.left, ast.Name): - vname: str = Node.left.id - if vname in Gen.var_signedness and Gen.var_signedness[vname]: + # `>>` 的符号性按**左操作数**判定:Name 之外的形态(字段/下标/表达式)也要覆盖。 + # 注意不要退回 emit_binary_op 里那个“残留变量名”判据(已移除,见 ExprGen.emit_binary_op): + # b: int64 = -196608; b >> 1 曾是误判成 lshr 的现场(IntWidthTest Test 5/6)。 + if Op in ('>>', 'RShift'): + if Gen._check_node_unsigned(Node.left): is_unsigned = True # 双指针算术 fail-fast 已**下沉到单一收敛点** `Gen.emit_binary_op` # (LLVMCG/ExprGen.py):BinOp 与 AugAssign(+=、-=、*= …)都经该函数, diff --git a/lib/core/LLVMCG/ExprGen.py b/lib/core/LLVMCG/ExprGen.py index 0adf7c7..203f8a6 100644 --- a/lib/core/LLVMCG/ExprGen.py +++ b/lib/core/LLVMCG/ExprGen.py @@ -179,12 +179,12 @@ class ExprGenMixin: is_unsigned = True elif left.type.width == 16: is_unsigned = True - elif left.type.width == 32: - if self._last_var_name: - is_unsigned = self._is_var_unsigned(self._last_var_name) - elif left.type.width == 64: - if self._last_var_name: - is_unsigned = self._is_var_unsigned(self._last_var_name) + # i32/i64 的符号性**只由调用方按左操作数判定**(调用方拿得到 Node.left, + # 见 HandlesExprOps / HandlesAugAssign)。此前这里又用 self._last_var_name + # 判一次,而它只是“最近见过的变量名”,可能是**上一条表达式残留的别的变量**: + # b: int64 = -196608 + # b >> 1 # 若残留名恰好是某个无符号变量(t.CSizeT 等) ⇒ 误判无符号 ⇒ lshr + # 结果:负数右移变大正数(IntWidthTest Test 5/6 的 FAIL 即此)。 shift_ops: dict[str, Any] = { '>>': self.builder.lshr if is_unsigned else self.builder.ashr, 'RShift': self.builder.lshr if is_unsigned else self.builder.ashr,