aboutsummaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
Diffstat (limited to 'test')
-rw-r--r--test/behavior/call.zig68
-rw-r--r--test/behavior/union.zig28
-rw-r--r--test/cases/compile_errors/invalid_tail_call.zig12
-rw-r--r--test/cases/compile_errors/non-comptime-parameter-used-as-array-size.zig16
-rw-r--r--test/cases/compile_errors/runtime_to_comptime_num.zig31
-rw-r--r--test/cases/compile_errors/shifting_without_int_type_or_comptime_known.zig23
-rw-r--r--test/cases/compile_errors/stage1/obj/shifting_without_int_type_or_comptime_known.zig9
-rw-r--r--test/cases/taill_call_noreturn.zig18
8 files changed, 196 insertions, 9 deletions
diff --git a/test/behavior/call.zig b/test/behavior/call.zig
index eafd2ef4e9..37c6ce3691 100644
--- a/test/behavior/call.zig
+++ b/test/behavior/call.zig
@@ -261,3 +261,71 @@ test "arguments to comptime parameters generated in comptime blocks" {
};
S.foo(S.fortyTwo());
}
+
+test "forced tail call" {
+ if (builtin.zig_backend == .stage1) return error.SkipZigTest;
+ if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
+ if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
+ if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
+ if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
+ if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
+
+ if (builtin.zig_backend == .stage2_llvm) {
+ // Only attempt this test on targets we know have tail call support in LLVM.
+ if (builtin.cpu.arch != .x86_64 and builtin.cpu.arch != .aarch64) {
+ return error.SkipZigTest;
+ }
+ }
+
+ const S = struct {
+ fn fibonacciTailInternal(n: u16, a: u16, b: u16) u16 {
+ if (n == 0) return a;
+ if (n == 1) return b;
+ return @call(
+ .{ .modifier = .always_tail },
+ fibonacciTailInternal,
+ .{ n - 1, b, a + b },
+ );
+ }
+
+ fn fibonacciTail(n: u16) u16 {
+ return fibonacciTailInternal(n, 0, 1);
+ }
+ };
+ try expect(S.fibonacciTail(10) == 55);
+}
+
+test "inline call preserves tail call" {
+ if (builtin.zig_backend == .stage1) return error.SkipZigTest;
+ if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
+ if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
+ if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
+ if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
+ if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
+
+ if (builtin.zig_backend == .stage2_llvm) {
+ // Only attempt this test on targets we know have tail call support in LLVM.
+ if (builtin.cpu.arch != .x86_64 and builtin.cpu.arch != .aarch64) {
+ return error.SkipZigTest;
+ }
+ }
+
+ const max = std.math.maxInt(u16);
+ const S = struct {
+ var a: u16 = 0;
+ fn foo() void {
+ return bar();
+ }
+
+ inline fn bar() void {
+ if (a == max) return;
+ // Stack overflow if not tail called
+ var buf: [max]u16 = undefined;
+ buf[a] = a;
+ a += 1;
+ return @call(.{ .modifier = .always_tail }, foo, .{});
+ }
+ };
+ S.foo();
+ try expect(S.a == std.math.maxInt(u16));
+}
diff --git a/test/behavior/union.zig b/test/behavior/union.zig
index 5d6b084be5..79bc1861e4 100644
--- a/test/behavior/union.zig
+++ b/test/behavior/union.zig
@@ -1324,3 +1324,31 @@ test "union and enum field order doesn't match" {
x = .b;
try expect(x == .b);
}
+
+test "@unionInit uses tag value instead of field index" {
+ if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
+ if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
+ if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
+ if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
+ if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
+
+ const E = enum(u8) {
+ b = 255,
+ a = 3,
+ };
+ const U = union(E) {
+ a: usize,
+ b: isize,
+ };
+ var i: isize = -1;
+ var u = @unionInit(U, "b", i);
+ {
+ var a = u.b;
+ try expect(a == i);
+ }
+ {
+ var a = &u.b;
+ try expect(a.* == i);
+ }
+ try expect(@enumToInt(u) == 255);
+}
diff --git a/test/cases/compile_errors/invalid_tail_call.zig b/test/cases/compile_errors/invalid_tail_call.zig
new file mode 100644
index 0000000000..cdeb9df930
--- /dev/null
+++ b/test/cases/compile_errors/invalid_tail_call.zig
@@ -0,0 +1,12 @@
+fn myFn(_: usize) void {
+ return;
+}
+pub export fn entry() void {
+ @call(.{ .modifier = .always_tail }, myFn, .{0});
+}
+
+// error
+// backend=llvm
+// target=native
+//
+// :5:5: error: unable to perform tail call: type of function being called 'fn(usize) void' does not match type of calling function 'fn() callconv(.C) void'
diff --git a/test/cases/compile_errors/non-comptime-parameter-used-as-array-size.zig b/test/cases/compile_errors/non-comptime-parameter-used-as-array-size.zig
new file mode 100644
index 0000000000..b5495480ed
--- /dev/null
+++ b/test/cases/compile_errors/non-comptime-parameter-used-as-array-size.zig
@@ -0,0 +1,16 @@
+export fn entry() void {
+ const llamas1 = makeLlamas(5);
+ const llamas2 = makeLlamas(5);
+ _ = llamas1;
+ _ = llamas2;
+}
+
+fn makeLlamas(count: usize) [count]u8 {
+ _ = count;
+}
+
+// error
+// target=native
+//
+// :8:30: error: unable to resolve comptime value
+// :8:30: note: array length must be comptime known
diff --git a/test/cases/compile_errors/runtime_to_comptime_num.zig b/test/cases/compile_errors/runtime_to_comptime_num.zig
new file mode 100644
index 0000000000..2275e35c43
--- /dev/null
+++ b/test/cases/compile_errors/runtime_to_comptime_num.zig
@@ -0,0 +1,31 @@
+pub export fn entry() void {
+ var a: u32 = 0;
+ _ = @as(comptime_int, a);
+}
+pub export fn entry2() void{
+ var a: u32 = 0;
+ _ = @as(comptime_float, a);
+}
+pub export fn entry3() void{
+ comptime var aa: comptime_float = 0.0;
+ var a: f32 = 4;
+ aa = a;
+}
+pub export fn entry4() void{
+ comptime var aa: comptime_int = 0.0;
+ var a: f32 = 4;
+ aa = a;
+}
+
+// error
+// backend=stage2
+// target=native
+//
+// :3:27: error: unable to resolve comptime value
+// :3:27: note: value being casted to 'comptime_int' must be comptime known
+// :7:29: error: unable to resolve comptime value
+// :7:29: note: value being casted to 'comptime_float' must be comptime known
+// :12:10: error: unable to resolve comptime value
+// :12:10: note: value being casted to 'comptime_float' must be comptime known
+// :17:10: error: unable to resolve comptime value
+// :17:10: note: value being casted to 'comptime_int' must be comptime known
diff --git a/test/cases/compile_errors/shifting_without_int_type_or_comptime_known.zig b/test/cases/compile_errors/shifting_without_int_type_or_comptime_known.zig
new file mode 100644
index 0000000000..7e68baed62
--- /dev/null
+++ b/test/cases/compile_errors/shifting_without_int_type_or_comptime_known.zig
@@ -0,0 +1,23 @@
+export fn entry(x: u8) u8 {
+ return 0x11 << x;
+}
+export fn entry1(x: u8) u8 {
+ return 0x11 >> x;
+}
+export fn entry2() void {
+ var x: u5 = 1;
+ _ = @shlExact(12345, x);
+}
+export fn entry3() void {
+ var x: u5 = 1;
+ _ = @shrExact(12345, x);
+}
+
+// error
+// backend=stage2
+// target=native
+//
+// :2:17: error: LHS of shift must be a fixed-width integer type, or RHS must be a comptime known
+// :5:17: error: LHS of shift must be a fixed-width integer type, or RHS must be a comptime known
+// :9:9: error: LHS of shift must be a fixed-width integer type, or RHS must be a comptime known
+// :13:9: error: LHS of shift must be a fixed-width integer type, or RHS must be a comptime known
diff --git a/test/cases/compile_errors/stage1/obj/shifting_without_int_type_or_comptime_known.zig b/test/cases/compile_errors/stage1/obj/shifting_without_int_type_or_comptime_known.zig
deleted file mode 100644
index 4d875575d0..0000000000
--- a/test/cases/compile_errors/stage1/obj/shifting_without_int_type_or_comptime_known.zig
+++ /dev/null
@@ -1,9 +0,0 @@
-export fn entry(x: u8) u8 {
- return 0x11 << x;
-}
-
-// error
-// backend=stage1
-// target=native
-//
-// tmp.zig:2:17: error: LHS of shift must be a fixed-width integer type, or RHS must be compile-time known
diff --git a/test/cases/taill_call_noreturn.zig b/test/cases/taill_call_noreturn.zig
new file mode 100644
index 0000000000..fabb9e729b
--- /dev/null
+++ b/test/cases/taill_call_noreturn.zig
@@ -0,0 +1,18 @@
+const std = @import("std");
+const builtin = std.builtin;
+pub fn foo(message: []const u8, stack_trace: ?*builtin.StackTrace) noreturn {
+ @call(.{ .modifier = .always_tail }, bar, .{ message, stack_trace });
+}
+pub fn bar(message: []const u8, stack_trace: ?*builtin.StackTrace) noreturn {
+ _ = message;
+ _ = stack_trace;
+ std.process.exit(0);
+}
+
+pub fn main() void {
+ foo("foo", null);
+}
+
+// run
+// backend=llvm
+// target=x86_64-linux,x86_64-macos,aarch64-linux,aarch64-macos