aboutsummaryrefslogtreecommitdiff
path: root/src/Sema.zig
diff options
context:
space:
mode:
authorTechatrix <19954306+Techatrix@users.noreply.github.com>2023-10-30 00:02:57 +0100
committerAndrew Kelley <andrew@ziglang.org>2024-01-16 16:27:31 -0800
commitec358d6db5a10989590e11bbbbd3bed9f81cf1f4 (patch)
treebd5affb8ff6bbbb4ea8ac22554c0a782d73bb261 /src/Sema.zig
parent4ace1f5a7ffeb569e97dc78807a1eacc5565a272 (diff)
downloadzig-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/Sema.zig')
-rw-r--r--src/Sema.zig18
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);