aboutsummaryrefslogtreecommitdiff
path: root/test
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 /test
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 'test')
-rw-r--r--test/cases/compile_errors/add_on_undefined_value.zig20
-rw-r--r--test/cases/compile_errors/add_sat_on_undefined_value.zig31
-rw-r--r--test/cases/compile_errors/add_wrap_on_undefined_value.zig31
-rw-r--r--test/cases/compile_errors/mult_on_undefined_value.zig34
-rw-r--r--test/cases/compile_errors/mult_sat_on_undefined_value.zig38
-rw-r--r--test/cases/compile_errors/mult_wrap_on_undefined_value.zig38
-rw-r--r--test/cases/compile_errors/sub_on_undefined_value.zig16
-rw-r--r--test/cases/compile_errors/sub_sat_on_undefined_value.zig25
-rw-r--r--test/cases/compile_errors/sub_wrap_on_undefined_value.zig25
9 files changed, 249 insertions, 9 deletions
diff --git a/test/cases/compile_errors/add_on_undefined_value.zig b/test/cases/compile_errors/add_on_undefined_value.zig
index b59de233c5..eb081a8510 100644
--- a/test/cases/compile_errors/add_on_undefined_value.zig
+++ b/test/cases/compile_errors/add_on_undefined_value.zig
@@ -1,10 +1,24 @@
comptime {
- const a: i64 = undefined;
- _ = a + a;
+ const undef: i64 = undefined;
+ const not_undef: i64 = 32;
+
+ // If either of the operands are zero, then the other operand is returned.
+ @compileLog(undef + 0);
+ @compileLog(not_undef + 0);
+ @compileLog(0 + undef);
+ @compileLog(0 + not_undef);
+
+ _ = undef + undef;
}
// error
// backend=stage2
// target=native
//
-// :3:13: error: use of undefined value here causes undefined behavior
+// :11:17: error: use of undefined value here causes undefined behavior
+//
+// Compile Log Output:
+// @as(i64, undefined)
+// @as(i64, 32)
+// @as(i64, undefined)
+// @as(i64, 32)
diff --git a/test/cases/compile_errors/add_sat_on_undefined_value.zig b/test/cases/compile_errors/add_sat_on_undefined_value.zig
new file mode 100644
index 0000000000..e23a985d1a
--- /dev/null
+++ b/test/cases/compile_errors/add_sat_on_undefined_value.zig
@@ -0,0 +1,31 @@
+comptime {
+ const undef: i64 = undefined;
+ const not_undef: i64 = 32;
+
+ // If either of the operands are zero, then the other operand is returned.
+ @compileLog(undef +| 0);
+ @compileLog(not_undef +| 0);
+ @compileLog(0 +| undef);
+ @compileLog(0 +| not_undef);
+ // If either of the operands are undefined, the result is undefined.
+ @compileLog(undef +| 1);
+ @compileLog(not_undef +| 1);
+ @compileLog(1 +| undef);
+ @compileLog(1 +| not_undef);
+}
+
+// error
+// backend=stage2
+// target=native
+//
+// :6:5: error: found compile log statement
+//
+// Compile Log Output:
+// @as(i64, undefined)
+// @as(i64, 32)
+// @as(i64, undefined)
+// @as(i64, 32)
+// @as(i64, undefined)
+// @as(i64, 33)
+// @as(i64, undefined)
+// @as(i64, 33)
diff --git a/test/cases/compile_errors/add_wrap_on_undefined_value.zig b/test/cases/compile_errors/add_wrap_on_undefined_value.zig
new file mode 100644
index 0000000000..b957485735
--- /dev/null
+++ b/test/cases/compile_errors/add_wrap_on_undefined_value.zig
@@ -0,0 +1,31 @@
+comptime {
+ const undef: i64 = undefined;
+ const not_undef: i64 = 32;
+
+ // If either of the operands are zero, then the other operand is returned.
+ @compileLog(undef +% 0);
+ @compileLog(not_undef +% 0);
+ @compileLog(0 +% undef);
+ @compileLog(0 +% not_undef);
+ // If either of the operands are undefined, the result is undefined.
+ @compileLog(undef +% 1);
+ @compileLog(not_undef +% 1);
+ @compileLog(1 +% undef);
+ @compileLog(1 +% not_undef);
+}
+
+// error
+// backend=stage2
+// target=native
+//
+// :6:5: error: found compile log statement
+//
+// Compile Log Output:
+// @as(i64, undefined)
+// @as(i64, 32)
+// @as(i64, undefined)
+// @as(i64, 32)
+// @as(i64, undefined)
+// @as(i64, 33)
+// @as(i64, undefined)
+// @as(i64, 33)
diff --git a/test/cases/compile_errors/mult_on_undefined_value.zig b/test/cases/compile_errors/mult_on_undefined_value.zig
index 1e65797153..3516253d5c 100644
--- a/test/cases/compile_errors/mult_on_undefined_value.zig
+++ b/test/cases/compile_errors/mult_on_undefined_value.zig
@@ -1,10 +1,38 @@
comptime {
- const a: i64 = undefined;
- _ = a * a;
+ const undef: i64 = undefined;
+ const not_undef: i64 = 32;
+
+ // If either of the operands are zero, the result is zero.
+ @compileLog(undef * 0);
+ @compileLog(not_undef * 0);
+ @compileLog(0 * undef);
+ @compileLog(0 * not_undef);
+
+ // If either of the operands are one, the result is the other
+ // operand, even if it is undefined.
+ @compileLog(undef * 1);
+ @compileLog(not_undef * 1);
+ @compileLog(1 * undef);
+ @compileLog(1 * not_undef);
+
+ // 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.
+ _ = undef * undef;
}
// error
// backend=stage2
// target=native
//
-// :3:13: error: use of undefined value here causes undefined behavior
+// :21:17: error: use of undefined value here causes undefined behavior
+//
+// Compile Log Output:
+// @as(i64, 0)
+// @as(i64, 0)
+// @as(i64, 0)
+// @as(i64, 0)
+// @as(i64, undefined)
+// @as(i64, 32)
+// @as(i64, undefined)
+// @as(i64, 32)
diff --git a/test/cases/compile_errors/mult_sat_on_undefined_value.zig b/test/cases/compile_errors/mult_sat_on_undefined_value.zig
new file mode 100644
index 0000000000..987161c8ed
--- /dev/null
+++ b/test/cases/compile_errors/mult_sat_on_undefined_value.zig
@@ -0,0 +1,38 @@
+comptime {
+ const undef: i64 = undefined;
+ const not_undef: i64 = 32;
+
+ // If either of the operands are zero, the result is zero.
+ @compileLog(undef *| 0);
+ @compileLog(not_undef *| 0);
+ @compileLog(0 *| undef);
+ @compileLog(0 *| not_undef);
+
+ // If either of the operands are one, result is the other operand.
+ @compileLog(undef *| 1);
+ @compileLog(not_undef *| 1);
+ @compileLog(1 *| undef);
+ @compileLog(1 *| not_undef);
+
+ // If either of the operands are undefined, result is undefined.
+ @compileLog(undef *| 2);
+ @compileLog(2 *| undef);
+}
+
+// error
+// backend=stage2
+// target=native
+//
+// :6:5: error: found compile log statement
+//
+// Compile Log Output:
+// @as(i64, 0)
+// @as(i64, 0)
+// @as(i64, 0)
+// @as(i64, 0)
+// @as(i64, undefined)
+// @as(i64, 32)
+// @as(i64, undefined)
+// @as(i64, 32)
+// @as(i64, undefined)
+// @as(i64, undefined)
diff --git a/test/cases/compile_errors/mult_wrap_on_undefined_value.zig b/test/cases/compile_errors/mult_wrap_on_undefined_value.zig
new file mode 100644
index 0000000000..2ecb6753f6
--- /dev/null
+++ b/test/cases/compile_errors/mult_wrap_on_undefined_value.zig
@@ -0,0 +1,38 @@
+comptime {
+ const undef: i64 = undefined;
+ const not_undef: i64 = 32;
+
+ // If either of the operands are zero, the result is zero.
+ @compileLog(undef *% 0);
+ @compileLog(not_undef *% 0);
+ @compileLog(0 *% undef);
+ @compileLog(0 *% not_undef);
+
+ // If either of the operands are one, result is the other operand.
+ @compileLog(undef *% 1);
+ @compileLog(not_undef *% 1);
+ @compileLog(1 *% undef);
+ @compileLog(1 *% not_undef);
+
+ // If either of the operands are undefined, result is undefined.
+ @compileLog(undef *% 2);
+ @compileLog(2 *% undef);
+}
+
+// error
+// backend=stage2
+// target=native
+//
+// :6:5: error: found compile log statement
+//
+// Compile Log Output:
+// @as(i64, 0)
+// @as(i64, 0)
+// @as(i64, 0)
+// @as(i64, 0)
+// @as(i64, undefined)
+// @as(i64, 32)
+// @as(i64, undefined)
+// @as(i64, 32)
+// @as(i64, undefined)
+// @as(i64, undefined)
diff --git a/test/cases/compile_errors/sub_on_undefined_value.zig b/test/cases/compile_errors/sub_on_undefined_value.zig
index de305be576..5d2510f263 100644
--- a/test/cases/compile_errors/sub_on_undefined_value.zig
+++ b/test/cases/compile_errors/sub_on_undefined_value.zig
@@ -1,10 +1,20 @@
comptime {
- const a: i64 = undefined;
- _ = a - a;
+ const undef: i64 = undefined;
+ const not_undef: i64 = 32;
+
+ // If the rhs is zero, then the other operand is returned, even if it is undefined.
+ @compileLog(undef - 0);
+ @compileLog(not_undef - 0);
+
+ _ = undef - undef;
}
// error
// backend=stage2
// target=native
//
-// :3:13: error: use of undefined value here causes undefined behavior
+// :9:17: error: use of undefined value here causes undefined behavior
+//
+// Compile Log Output:
+// @as(i64, undefined)
+// @as(i64, 32)
diff --git a/test/cases/compile_errors/sub_sat_on_undefined_value.zig b/test/cases/compile_errors/sub_sat_on_undefined_value.zig
new file mode 100644
index 0000000000..967f24130e
--- /dev/null
+++ b/test/cases/compile_errors/sub_sat_on_undefined_value.zig
@@ -0,0 +1,25 @@
+comptime {
+ const undef: i64 = undefined;
+ const not_undef: i64 = 32;
+
+ // If the RHS is zero, then the LHS is returned, even if it is undefined.
+ @compileLog(undef -| 0);
+ @compileLog(not_undef -| 0);
+ // If either of the operands are undefined, the result is undefined.
+ @compileLog(undef -| not_undef);
+ @compileLog(not_undef -| undef);
+ @compileLog(undef -| undef);
+}
+
+// error
+// backend=stage2
+// target=native
+//
+// :6:5: error: found compile log statement
+//
+// Compile Log Output:
+// @as(i64, undefined)
+// @as(i64, 32)
+// @as(i64, undefined)
+// @as(i64, undefined)
+// @as(i64, undefined)
diff --git a/test/cases/compile_errors/sub_wrap_on_undefined_value.zig b/test/cases/compile_errors/sub_wrap_on_undefined_value.zig
new file mode 100644
index 0000000000..12dfeff4e5
--- /dev/null
+++ b/test/cases/compile_errors/sub_wrap_on_undefined_value.zig
@@ -0,0 +1,25 @@
+comptime {
+ const undef: i64 = undefined;
+ const not_undef: i64 = 32;
+
+ // If the RHS is zero, then the LHS is returned, even if it is undefined.
+ @compileLog(undef -% 0);
+ @compileLog(not_undef -% 0);
+ // If either of the operands are undefined, the result is undefined.
+ @compileLog(undef -% not_undef);
+ @compileLog(not_undef -% undef);
+ @compileLog(undef -% undef);
+}
+
+// error
+// backend=stage2
+// target=native
+//
+// :6:5: error: found compile log statement
+//
+// Compile Log Output:
+// @as(i64, undefined)
+// @as(i64, 32)
+// @as(i64, undefined)
+// @as(i64, undefined)
+// @as(i64, undefined)