diff options
| author | Techatrix <19954306+Techatrix@users.noreply.github.com> | 2023-10-30 00:02:57 +0100 |
|---|---|---|
| committer | Andrew Kelley <andrew@ziglang.org> | 2024-01-16 16:27:31 -0800 |
| commit | ec358d6db5a10989590e11bbbbd3bed9f81cf1f4 (patch) | |
| tree | bd5affb8ff6bbbb4ea8ac22554c0a782d73bb261 /src | |
| parent | 4ace1f5a7ffeb569e97dc78807a1eacc5565a272 (diff) | |
| download | zig-ec358d6db5a10989590e11bbbbd3bed9f81cf1f4.tar.gz zig-ec358d6db5a10989590e11bbbbd3bed9f81cf1f4.zip | |
sema: fix safe integer arithmetic operations on undefined values
Previously `@as(i64, undefined) +% 1` would produce `@as(@TypeOf(undefined), undefined)` which now gives `@as(i64, undefined)`.
Previously `@as(i64, undefined) +| 1` would hit an assertion which now gives `@as(i64, undefined)`.
Diffstat (limited to 'src')
| -rw-r--r-- | src/Sema.zig | 18 |
1 files changed, 12 insertions, 6 deletions
diff --git a/src/Sema.zig b/src/Sema.zig index 2a30247108..aa624e06e7 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -16140,6 +16140,10 @@ fn analyzeArithmetic( return casted_lhs; } if (maybe_lhs_val) |lhs_val| { + if (lhs_val.isUndef(mod)) { + return mod.undefRef(resolved_type); + } + const val = if (scalar_tag == .ComptimeInt) try sema.intAdd(lhs_val, rhs_val, resolved_type, undefined) else @@ -16202,7 +16206,7 @@ fn analyzeArithmetic( }, .subwrap => { // Integers only; floats are checked above. - // If the RHS is zero, then the other operand is returned, even if it is undefined. + // If the RHS is zero, then the LHS is returned, even if it is undefined. // If either of the operands are undefined, the result is undefined. if (maybe_rhs_val) |rhs_val| { if (rhs_val.isUndef(mod)) { @@ -16223,8 +16227,8 @@ fn analyzeArithmetic( }, .sub_sat => { // Integers only; floats are checked above. - // If the RHS is zero, result is LHS. - // If either of the operands are undefined, result is undefined. + // If the RHS is zero, then the LHS is returned, even if it is undefined. + // If either of the operands are undefined, the result is undefined. if (maybe_rhs_val) |rhs_val| { if (rhs_val.isUndef(mod)) { return mod.undefRef(resolved_type); @@ -16255,7 +16259,9 @@ fn analyzeArithmetic( // If either of the operands are undefined, it's a compile error // because there is a possible value for which the addition would // overflow (max_int), causing illegal behavior. - // For floats: either operand being undef makes the result undef. + // + // For floats: + // If either of the operands are undefined, the result is undefined. // If either of the operands are inf, and the other operand is zero, // the result is nan. // If either of the operands are nan, the result is nan. @@ -38093,7 +38099,7 @@ fn numberAddWrapScalar( ty: Type, ) !Value { const mod = sema.mod; - if (lhs.isUndef(mod) or rhs.isUndef(mod)) return Value.undef; + if (lhs.isUndef(mod) or rhs.isUndef(mod)) return mod.undefValue(ty); if (ty.zigTypeTag(mod) == .ComptimeInt) { return sema.intAdd(lhs, rhs, ty, undefined); @@ -38183,7 +38189,7 @@ fn numberSubWrapScalar( ty: Type, ) !Value { const mod = sema.mod; - if (lhs.isUndef(mod) or rhs.isUndef(mod)) return Value.undef; + if (lhs.isUndef(mod) or rhs.isUndef(mod)) return mod.undefValue(ty); if (ty.zigTypeTag(mod) == .ComptimeInt) { return sema.intSub(lhs, rhs, ty, undefined); |
