aboutsummaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
authortgschultz <tgschultz@gmail.com>2018-05-11 21:36:02 -0500
committerGitHub <noreply@github.com>2018-05-11 21:36:02 -0500
commit8c1872543c8cf76215cc4bf3ced4637bb1065a4e (patch)
tree72dfebb643ab61579e3fb8dd58cd4610ffe876fa /test
parent7186e92c86982950d0aa7c0c2deef9ef96bc1264 (diff)
parent6e821078f625a03eb8b7794c983da0f7793366ab (diff)
downloadzig-8c1872543c8cf76215cc4bf3ced4637bb1065a4e.tar.gz
zig-8c1872543c8cf76215cc4bf3ced4637bb1065a4e.zip
Merge pull request #1 from zig-lang/master
Sync with zig-lang/zig master
Diffstat (limited to 'test')
-rw-r--r--test/behavior.zig3
-rw-r--r--test/cases/atomics.zig50
-rw-r--r--test/cases/bugs/920.zig60
-rw-r--r--test/cases/coroutines.zig54
-rw-r--r--test/cases/defer.zig11
-rw-r--r--test/cases/enum.zig9
-rw-r--r--test/cases/error.zig66
-rw-r--r--test/cases/eval.zig23
-rw-r--r--test/cases/fn.zig17
-rw-r--r--test/cases/fn_in_struct_in_comptime.zig17
-rw-r--r--test/cases/math.zig41
-rw-r--r--test/cases/reflection.zig24
-rw-r--r--test/cases/type_info.zig200
-rw-r--r--test/cases/union.zig22
-rw-r--r--test/compile_errors.zig95
-rw-r--r--test/tests.zig9
-rw-r--r--test/translate_c.zig43
17 files changed, 728 insertions, 16 deletions
diff --git a/test/behavior.zig b/test/behavior.zig
index de39b20dad..d700faaebc 100644
--- a/test/behavior.zig
+++ b/test/behavior.zig
@@ -12,6 +12,7 @@ comptime {
_ = @import("cases/bugs/655.zig");
_ = @import("cases/bugs/656.zig");
_ = @import("cases/bugs/828.zig");
+ _ = @import("cases/bugs/920.zig");
_ = @import("cases/cast.zig");
_ = @import("cases/const_slice_child.zig");
_ = @import("cases/coroutines.zig");
@@ -35,6 +36,7 @@ comptime {
_ = @import("cases/pub_enum/index.zig");
_ = @import("cases/ref_var_in_if_after_if_2nd_switch_prong.zig");
_ = @import("cases/reflection.zig");
+ _ = @import("cases/type_info.zig");
_ = @import("cases/sizeof_and_typeof.zig");
_ = @import("cases/slice.zig");
_ = @import("cases/struct.zig");
@@ -51,4 +53,5 @@ comptime {
_ = @import("cases/var_args.zig");
_ = @import("cases/void.zig");
_ = @import("cases/while.zig");
+ _ = @import("cases/fn_in_struct_in_comptime.zig");
}
diff --git a/test/cases/atomics.zig b/test/cases/atomics.zig
index e8e81b76e6..d406285d29 100644
--- a/test/cases/atomics.zig
+++ b/test/cases/atomics.zig
@@ -1,12 +1,24 @@
-const assert = @import("std").debug.assert;
+const std = @import("std");
+const assert = std.debug.assert;
const builtin = @import("builtin");
const AtomicRmwOp = builtin.AtomicRmwOp;
const AtomicOrder = builtin.AtomicOrder;
test "cmpxchg" {
var x: i32 = 1234;
- while (!@cmpxchg(&x, 1234, 5678, AtomicOrder.SeqCst, AtomicOrder.SeqCst)) {}
+ if (@cmpxchgWeak(i32, &x, 99, 5678, AtomicOrder.SeqCst, AtomicOrder.SeqCst)) |x1| {
+ assert(x1 == 1234);
+ } else {
+ @panic("cmpxchg should have failed");
+ }
+
+ while (@cmpxchgWeak(i32, &x, 1234, 5678, AtomicOrder.SeqCst, AtomicOrder.SeqCst)) |x1| {
+ assert(x1 == 1234);
+ }
assert(x == 5678);
+
+ assert(@cmpxchgStrong(i32, &x, 5678, 42, AtomicOrder.SeqCst, AtomicOrder.SeqCst) == null);
+ assert(x == 42);
}
test "fence" {
@@ -15,13 +27,45 @@ test "fence" {
x = 5678;
}
-test "atomicrmw" {
+test "atomicrmw and atomicload" {
var data: u8 = 200;
testAtomicRmw(&data);
assert(data == 42);
+ testAtomicLoad(&data);
}
fn testAtomicRmw(ptr: &u8) void {
const prev_value = @atomicRmw(u8, ptr, AtomicRmwOp.Xchg, 42, AtomicOrder.SeqCst);
assert(prev_value == 200);
+ comptime {
+ var x: i32 = 1234;
+ const y: i32 = 12345;
+ assert(@atomicLoad(i32, &x, AtomicOrder.SeqCst) == 1234);
+ assert(@atomicLoad(i32, &y, AtomicOrder.SeqCst) == 12345);
+ }
+}
+
+fn testAtomicLoad(ptr: &u8) void {
+ const x = @atomicLoad(u8, ptr, AtomicOrder.SeqCst);
+ assert(x == 42);
+}
+
+test "cmpxchg with ptr" {
+ var data1: i32 = 1234;
+ var data2: i32 = 5678;
+ var data3: i32 = 9101;
+ var x: &i32 = &data1;
+ if (@cmpxchgWeak(&i32, &x, &data2, &data3, AtomicOrder.SeqCst, AtomicOrder.SeqCst)) |x1| {
+ assert(x1 == &data1);
+ } else {
+ @panic("cmpxchg should have failed");
+ }
+
+ while (@cmpxchgWeak(&i32, &x, &data1, &data3, AtomicOrder.SeqCst, AtomicOrder.SeqCst)) |x1| {
+ assert(x1 == &data1);
+ }
+ assert(x == &data3);
+
+ assert(@cmpxchgStrong(&i32, &x, &data3, &data2, AtomicOrder.SeqCst, AtomicOrder.SeqCst) == null);
+ assert(x == &data2);
}
diff --git a/test/cases/bugs/920.zig b/test/cases/bugs/920.zig
new file mode 100644
index 0000000000..13c03a304f
--- /dev/null
+++ b/test/cases/bugs/920.zig
@@ -0,0 +1,60 @@
+const std = @import("std");
+const math = std.math;
+const Random = std.rand.Random;
+
+const ZigTable = struct {
+ r: f64,
+ x: [257]f64,
+ f: [257]f64,
+
+ pdf: fn(f64) f64,
+ is_symmetric: bool,
+ zero_case: fn(&Random, f64) f64,
+};
+
+fn ZigTableGen(comptime is_symmetric: bool, comptime r: f64, comptime v: f64, comptime f: fn(f64) f64,
+ comptime f_inv: fn(f64) f64, comptime zero_case: fn(&Random, f64) f64) ZigTable {
+ var tables: ZigTable = undefined;
+
+ tables.is_symmetric = is_symmetric;
+ tables.r = r;
+ tables.pdf = f;
+ tables.zero_case = zero_case;
+
+ tables.x[0] = v / f(r);
+ tables.x[1] = r;
+
+ for (tables.x[2..256]) |*entry, i| {
+ const last = tables.x[2 + i - 1];
+ *entry = f_inv(v / last + f(last));
+ }
+ tables.x[256] = 0;
+
+ for (tables.f[0..]) |*entry, i| {
+ *entry = f(tables.x[i]);
+ }
+
+ return tables;
+}
+
+const norm_r = 3.6541528853610088;
+const norm_v = 0.00492867323399;
+
+fn norm_f(x: f64) f64 { return math.exp(-x * x / 2.0); }
+fn norm_f_inv(y: f64) f64 { return math.sqrt(-2.0 * math.ln(y)); }
+fn norm_zero_case(random: &Random, u: f64) f64 { return 0.0; }
+
+const NormalDist = blk: {
+ @setEvalBranchQuota(30000);
+ break :blk ZigTableGen(true, norm_r, norm_v, norm_f, norm_f_inv, norm_zero_case);
+};
+
+test "bug 920 fixed" {
+ const NormalDist1 = blk: {
+ break :blk ZigTableGen(true, norm_r, norm_v, norm_f, norm_f_inv, norm_zero_case);
+ };
+
+ for (NormalDist1.f) |_, i| {
+ std.debug.assert(NormalDist1.f[i] == NormalDist.f[i]);
+ }
+}
diff --git a/test/cases/coroutines.zig b/test/cases/coroutines.zig
index 922c1a7e58..3aa2912429 100644
--- a/test/cases/coroutines.zig
+++ b/test/cases/coroutines.zig
@@ -1,4 +1,5 @@
const std = @import("std");
+const builtin = @import("builtin");
const assert = std.debug.assert;
var x: i32 = 1;
@@ -189,3 +190,56 @@ async fn failing() !void {
suspend;
return error.Fail;
}
+
+test "error return trace across suspend points - early return" {
+ const p = nonFailing();
+ resume p;
+ const p2 = try async<std.debug.global_allocator> printTrace(p);
+ cancel p2;
+}
+
+test "error return trace across suspend points - async return" {
+ const p = nonFailing();
+ const p2 = try async<std.debug.global_allocator> printTrace(p);
+ resume p;
+ cancel p2;
+}
+
+fn nonFailing() promise->error!void {
+ return async<std.debug.global_allocator> suspendThenFail() catch unreachable;
+}
+
+async fn suspendThenFail() error!void {
+ suspend;
+ return error.Fail;
+}
+
+async fn printTrace(p: promise->error!void) void {
+ (await p) catch |e| {
+ std.debug.assert(e == error.Fail);
+ if (@errorReturnTrace()) |trace| {
+ assert(trace.index == 1);
+ } else switch (builtin.mode) {
+ builtin.Mode.Debug, builtin.Mode.ReleaseSafe => @panic("expected return trace"),
+ builtin.Mode.ReleaseFast, builtin.Mode.ReleaseSmall => {},
+ }
+ };
+}
+
+test "break from suspend" {
+ var buf: [500]u8 = undefined;
+ var a = &std.heap.FixedBufferAllocator.init(buf[0..]).allocator;
+ var my_result: i32 = 1;
+ const p = try async<a> testBreakFromSuspend(&my_result);
+ cancel p;
+ std.debug.assert(my_result == 2);
+}
+
+async fn testBreakFromSuspend(my_result: &i32) void {
+ s: suspend |p| {
+ break :s;
+ }
+ *my_result += 1;
+ suspend;
+ *my_result += 1;
+}
diff --git a/test/cases/defer.zig b/test/cases/defer.zig
index a989af18c2..5470b4bbd0 100644
--- a/test/cases/defer.zig
+++ b/test/cases/defer.zig
@@ -41,3 +41,14 @@ fn testBreakContInDefer(x: usize) void {
assert(i == 5);
}
}
+
+test "defer and labeled break" {
+ var i = usize(0);
+
+ blk: {
+ defer i += 1;
+ break :blk;
+ }
+
+ assert(i == 1);
+}
diff --git a/test/cases/enum.zig b/test/cases/enum.zig
index 644c989b04..0a2658eaf7 100644
--- a/test/cases/enum.zig
+++ b/test/cases/enum.zig
@@ -392,3 +392,12 @@ test "enum with 1 field but explicit tag type should still have the tag type" {
const Enum = enum(u8) { B = 2 };
comptime @import("std").debug.assert(@sizeOf(Enum) == @sizeOf(u8));
}
+
+test "empty extern enum with members" {
+ const E = extern enum {
+ A,
+ B,
+ C,
+ };
+ assert(@sizeOf(E) == @sizeOf(c_int));
+}
diff --git a/test/cases/error.zig b/test/cases/error.zig
index e64bf02c91..2a1433df5b 100644
--- a/test/cases/error.zig
+++ b/test/cases/error.zig
@@ -175,3 +175,69 @@ fn baz_1() !i32 {
fn quux_1() !i32 {
return error.C;
}
+
+
+test "error: fn returning empty error set can be passed as fn returning any error" {
+ entry();
+ comptime entry();
+}
+
+fn entry() void {
+ foo2(bar2);
+}
+
+fn foo2(f: fn()error!void) void {
+ const x = f();
+}
+
+fn bar2() (error{}!void) { }
+
+
+test "error: Zero sized error set returned with value payload crash" {
+ _ = foo3(0);
+ _ = comptime foo3(0);
+}
+
+const Error = error{};
+fn foo3(b: usize) Error!usize {
+ return b;
+}
+
+
+test "error: Infer error set from literals" {
+ _ = nullLiteral("n") catch |err| handleErrors(err);
+ _ = floatLiteral("n") catch |err| handleErrors(err);
+ _ = intLiteral("n") catch |err| handleErrors(err);
+ _ = comptime nullLiteral("n") catch |err| handleErrors(err);
+ _ = comptime floatLiteral("n") catch |err| handleErrors(err);
+ _ = comptime intLiteral("n") catch |err| handleErrors(err);
+}
+
+fn handleErrors(err: var) noreturn {
+ switch (err) {
+ error.T => {}
+ }
+
+ unreachable;
+}
+
+fn nullLiteral(str: []const u8) !?i64 {
+ if (str[0] == 'n')
+ return null;
+
+ return error.T;
+}
+
+fn floatLiteral(str: []const u8) !?f64 {
+ if (str[0] == 'n')
+ return 1.0;
+
+ return error.T;
+}
+
+fn intLiteral(str: []const u8) !?i64 {
+ if (str[0] == 'n')
+ return 1;
+
+ return error.T;
+}
diff --git a/test/cases/eval.zig b/test/cases/eval.zig
index d6f7afe864..364db5e152 100644
--- a/test/cases/eval.zig
+++ b/test/cases/eval.zig
@@ -513,3 +513,26 @@ test "array concat of slices gives slice" {
assert(std.mem.eql(u8, c, "aoeuasdf"));
}
}
+
+test "comptime shlWithOverflow" {
+ const ct_shifted: u64 = comptime amt: {
+ var amt = u64(0);
+ _ = @shlWithOverflow(u64, ~u64(0), 16, &amt);
+ break :amt amt;
+ };
+
+ const rt_shifted: u64 = amt: {
+ var amt = u64(0);
+ _ = @shlWithOverflow(u64, ~u64(0), 16, &amt);
+ break :amt amt;
+ };
+
+ assert(ct_shifted == rt_shifted);
+}
+
+test "runtime 128 bit integer division" {
+ var a: u128 = 152313999999999991610955792383;
+ var b: u128 = 10000000000000000000;
+ var c = a / b;
+ assert(c == 15231399999);
+}
diff --git a/test/cases/fn.zig b/test/cases/fn.zig
index e492f6036c..5388deac10 100644
--- a/test/cases/fn.zig
+++ b/test/cases/fn.zig
@@ -94,3 +94,20 @@ test "inline function call" {
}
fn add(a: i32, b: i32) i32 { return a + b; }
+
+
+test "number literal as an argument" {
+ numberLiteralArg(3);
+ comptime numberLiteralArg(3);
+}
+
+fn numberLiteralArg(a: var) void {
+ assert(a == 3);
+}
+
+test "assign inline fn to const variable" {
+ const a = inlineFn;
+ a();
+}
+
+inline fn inlineFn() void { }
diff --git a/test/cases/fn_in_struct_in_comptime.zig b/test/cases/fn_in_struct_in_comptime.zig
new file mode 100644
index 0000000000..4f181d7ffb
--- /dev/null
+++ b/test/cases/fn_in_struct_in_comptime.zig
@@ -0,0 +1,17 @@
+const assert = @import("std").debug.assert;
+
+fn get_foo() fn(&u8)usize {
+ comptime {
+ return struct {
+ fn func(ptr: &u8) usize {
+ var u = @ptrToInt(ptr);
+ return u;
+ }
+ }.func;
+ }
+}
+
+test "define a function in an anonymous struct in comptime" {
+ const foo = get_foo();
+ assert(foo(@intToPtr(&u8, 12345)) == 12345);
+}
diff --git a/test/cases/math.zig b/test/cases/math.zig
index 574aa39bb1..13704ecd4b 100644
--- a/test/cases/math.zig
+++ b/test/cases/math.zig
@@ -349,6 +349,31 @@ test "big number shifting" {
}
}
+test "big number multi-limb shift and mask" {
+ comptime {
+ var a = 0xefffffffa0000001eeeeeeefaaaaaaab;
+
+ assert(u32(a & 0xffffffff) == 0xaaaaaaab);
+ a >>= 32;
+ assert(u32(a & 0xffffffff) == 0xeeeeeeef);
+ a >>= 32;
+ assert(u32(a & 0xffffffff) == 0xa0000001);
+ a >>= 32;
+ assert(u32(a & 0xffffffff) == 0xefffffff);
+ a >>= 32;
+
+ assert(a == 0);
+ }
+}
+
+test "big number multi-limb partial shift right" {
+ comptime {
+ var a = 0x1ffffffffeeeeeeee;
+ a >>= 16;
+ assert(a == 0x1ffffffffeeee);
+ }
+}
+
test "xor" {
test_xor();
comptime test_xor();
@@ -402,3 +427,19 @@ test "comptime float rem int" {
assert(x == 1.0);
}
}
+
+test "@sqrt" {
+ testSqrt(f64, 12.0);
+ comptime testSqrt(f64, 12.0);
+ testSqrt(f32, 13.0);
+ comptime testSqrt(f32, 13.0);
+
+ const x = 14.0;
+ const y = x * x;
+ const z = @sqrt(@typeOf(y), y);
+ comptime assert(z == x);
+}
+
+fn testSqrt(comptime T: type, x: T) void {
+ assert(@sqrt(T, x * x) == x);
+}
diff --git a/test/cases/reflection.zig b/test/cases/reflection.zig
index 18a766d9fc..0abc46c9de 100644
--- a/test/cases/reflection.zig
+++ b/test/cases/reflection.zig
@@ -1,5 +1,6 @@
const assert = @import("std").debug.assert;
const mem = @import("std").mem;
+const reflection = this;
test "reflection: array, pointer, nullable, error union type child" {
comptime {
@@ -56,7 +57,30 @@ test "reflection: enum member types and names" {
}
+test "reflection: @field" {
+ var f = Foo {
+ .one = 42,
+ .two = true,
+ .three = void{},
+ };
+
+ assert(f.one == f.one);
+ assert(@field(f, "o" ++ "ne") == f.one);
+ assert(@field(f, "t" ++ "wo") == f.two);
+ assert(@field(f, "th" ++ "ree") == f.three);
+ assert(@field(Foo, "const" ++ "ant") == Foo.constant);
+ assert(@field(Bar, "O" ++ "ne") == Bar.One);
+ assert(@field(Bar, "T" ++ "wo") == Bar.Two);
+ assert(@field(Bar, "Th" ++ "ree") == Bar.Three);
+ assert(@field(Bar, "F" ++ "our") == Bar.Four);
+ assert(@field(reflection, "dum" ++ "my")(true, 1, 2) == dummy(true, 1, 2));
+ @field(f, "o" ++ "ne") = 4;
+ assert(f.one == 4);
+}
+
const Foo = struct {
+ const constant = 52;
+
one: i32,
two: bool,
three: void,
diff --git a/test/cases/type_info.zig b/test/cases/type_info.zig
new file mode 100644
index 0000000000..f10703e3ee
--- /dev/null
+++ b/test/cases/type_info.zig
@@ -0,0 +1,200 @@
+const assert = @import("std").debug.assert;
+const mem = @import("std").mem;
+const TypeInfo = @import("builtin").TypeInfo;
+const TypeId = @import("builtin").TypeId;
+
+test "type info: tag type, void info" {
+ comptime {
+ assert(@TagType(TypeInfo) == TypeId);
+ const void_info = @typeInfo(void);
+ assert(TypeId(void_info) == TypeId.Void);
+ assert(void_info.Void == {});
+ }
+}
+
+test "type info: integer, floating point type info" {
+ comptime {
+ const u8_info = @typeInfo(u8);
+ assert(TypeId(u8_info) == TypeId.Int);
+ assert(!u8_info.Int.is_signed);
+ assert(u8_info.Int.bits == 8);
+
+ const f64_info = @typeInfo(f64);
+ assert(TypeId(f64_info) == TypeId.Float);
+ assert(f64_info.Float.bits == 64);
+ }
+}
+
+test "type info: pointer type info" {
+ comptime {
+ const u32_ptr_info = @typeInfo(&u32);
+ assert(TypeId(u32_ptr_info) == TypeId.Pointer);
+ assert(u32_ptr_info.Pointer.is_const == false);
+ assert(u32_ptr_info.Pointer.is_volatile == false);
+ assert(u32_ptr_info.Pointer.alignment == 4);
+ assert(u32_ptr_info.Pointer.child == u32);
+ }
+}
+
+test "type info: slice type info" {
+ comptime {
+ const u32_slice_info = @typeInfo([]u32);
+ assert(TypeId(u32_slice_info) == TypeId.Slice);
+ assert(u32_slice_info.Slice.is_const == false);
+ assert(u32_slice_info.Slice.is_volatile == false);
+ assert(u32_slice_info.Slice.alignment == 4);
+ assert(u32_slice_info.Slice.child == u32);
+ }
+}
+
+test "type info: array type info" {
+ comptime {
+ const arr_info = @typeInfo([42]bool);
+ assert(TypeId(arr_info) == TypeId.Array);
+ assert(arr_info.Array.len == 42);
+ assert(arr_info.Array.child == bool);
+ }
+}
+
+test "type info: nullable type info" {
+ comptime {
+ const null_info = @typeInfo(?void);
+ assert(TypeId(null_info) == TypeId.Nullable);
+ assert(null_info.Nullable.child == void);
+ }
+}
+
+test "type info: promise info" {
+ comptime {
+ const null_promise_info = @typeInfo(promise);
+ assert(TypeId(null_promise_info) == TypeId.Promise);
+ assert(null_promise_info.Promise.child == @typeOf(undefined));
+
+ const promise_info = @typeInfo(promise->usize);
+ assert(TypeId(promise_info) == TypeId.Promise);
+ assert(promise_info.Promise.child == usize);
+ }
+
+}
+
+test "type info: error set, error union info" {
+ comptime {
+ const TestErrorSet = error {
+ First,
+ Second,
+ Third,
+ };
+
+ const error_set_info = @typeInfo(TestErrorSet);
+ assert(TypeId(error_set_info) == TypeId.ErrorSet);
+ assert(error_set_info.ErrorSet.errors.len == 3);
+ assert(mem.eql(u8, error_set_info.ErrorSet.errors[0].name, "First"));
+ assert(error_set_info.ErrorSet.errors[2].value == usize(TestErrorSet.Third));
+
+ const error_union_info = @typeInfo(TestErrorSet!usize);
+ assert(TypeId(error_union_info) == TypeId.ErrorUnion);
+ assert(error_union_info.ErrorUnion.error_set == TestErrorSet);
+ assert(error_union_info.ErrorUnion.payload == usize);
+ }
+}
+
+test "type info: enum info" {
+ comptime {
+ const Os = @import("builtin").Os;
+
+ const os_info = @typeInfo(Os);
+ assert(TypeId(os_info) == TypeId.Enum);
+ assert(os_info.Enum.layout == TypeInfo.ContainerLayout.Auto);
+ assert(os_info.Enum.fields.len == 32);
+ assert(mem.eql(u8, os_info.Enum.fields[1].name, "ananas"));
+ assert(os_info.Enum.fields[10].value == 10);
+ assert(os_info.Enum.tag_type == u5);
+ assert(os_info.Enum.defs.len == 0);
+ }
+}
+
+test "type info: union info" {
+ comptime {
+ const typeinfo_info = @typeInfo(TypeInfo);
+ assert(TypeId(typeinfo_info) == TypeId.Union);
+ assert(typeinfo_info.Union.layout == TypeInfo.ContainerLayout.Auto);
+ assert(typeinfo_info.Union.tag_type == TypeId);
+ assert(typeinfo_info.Union.fields.len == 26);
+ assert(typeinfo_info.Union.fields[4].enum_field != null);
+ assert((??typeinfo_info.Union.fields[4].enum_field).value == 4);
+ assert(typeinfo_info.Union.fields[4].field_type == @typeOf(@typeInfo(u8).Int));
+ assert(typeinfo_info.Union.defs.len == 21);
+
+ const TestNoTagUnion = union {
+ Foo: void,
+ Bar: u32,
+ };
+
+ const notag_union_info = @typeInfo(TestNoTagUnion);
+ assert(TypeId(notag_union_info) == TypeId.Union);
+ assert(notag_union_info.Union.tag_type == @typeOf(undefined));
+ assert(notag_union_info.Union.layout == TypeInfo.ContainerLayout.Auto);
+ assert(notag_union_info.Union.fields.len == 2);
+ assert(notag_union_info.Union.fields[0].enum_field == null);
+ assert(notag_union_info.Union.fields[1].field_type == u32);
+
+ const TestExternUnion = extern union {
+ foo: &c_void,
+ };
+
+ const extern_union_info = @typeInfo(TestExternUnion);
+ assert(extern_union_info.Union.layout == TypeInfo.ContainerLayout.Extern);
+ assert(extern_union_info.Union.tag_type == @typeOf(undefined));
+ assert(extern_union_info.Union.fields[0].enum_field == null);
+ assert(extern_union_info.Union.fields[0].field_type == &c_void);
+ }
+}
+
+test "type info: struct info" {
+ comptime {
+ const struct_info = @typeInfo(TestStruct);
+ assert(TypeId(struct_info) == TypeId.Struct);
+ assert(struct_info.Struct.layout == TypeInfo.ContainerLayout.Packed);
+ assert(struct_info.Struct.fields.len == 3);
+ assert(struct_info.Struct.fields[1].offset == null);
+ assert(struct_info.Struct.fields[2].field_type == &TestStruct);
+ assert(struct_info.Struct.defs.len == 2);
+ assert(struct_info.Struct.defs[0].is_pub);
+ assert(!struct_info.Struct.defs[0].data.Fn.is_extern);
+ assert(struct_info.Struct.defs[0].data.Fn.lib_name == null);
+ assert(struct_info.Struct.defs[0].data.Fn.return_type == void);
+ assert(struct_info.Struct.defs[0].data.Fn.fn_type == fn(&const TestStruct)void);
+ }
+}
+
+const TestStruct = packed struct {
+ const Self = this;
+
+ fieldA: usize,
+ fieldB: void,
+ fieldC: &Self,
+
+ pub fn foo(self: &const Self) void {}
+};
+
+test "type info: function type info" {
+ comptime {
+ const fn_info = @typeInfo(@typeOf(foo));
+ assert(TypeId(fn_info) == TypeId.Fn);
+ assert(fn_info.Fn.calling_convention == TypeInfo.CallingConvention.Unspecified);
+ assert(fn_info.Fn.is_generic);
+ assert(fn_info.Fn.args.len == 2);
+ assert(fn_info.Fn.is_var_args);
+ assert(fn_info.Fn.return_type == @typeOf(undefined));
+ assert(fn_info.Fn.async_allocator_type == @typeOf(undefined));
+
+ const test_instance: TestStruct = undefined;
+ const bound_fn_info = @typeInfo(@typeOf(test_instance.foo));
+ assert(TypeId(bound_fn_info) == TypeId.BoundFn);
+ assert(bound_fn_info.BoundFn.args[0].arg_type == &const TestStruct);
+ }
+}
+
+fn foo(comptime a: usize, b: bool, args: ...) usize {
+ return 0;
+}
diff --git a/test/cases/union.zig b/test/cases/union.zig
index dc2a7c3414..f1fef46657 100644
--- a/test/cases/union.zig
+++ b/test/cases/union.zig
@@ -45,6 +45,16 @@ test "basic unions" {
assert(foo.float == 12.34);
}
+test "comptime union field access" {
+ comptime {
+ var foo = Foo { .int = 0 };
+ assert(foo.int == 0);
+
+ foo = Foo { .float = 42.42 };
+ assert(foo.float == 42.42);
+ }
+}
+
test "init union with runtime value" {
var foo: Foo = undefined;
@@ -262,3 +272,15 @@ const PartialInstWithPayload = union(enum) {
Compiled: i32,
};
+
+test "access a member of tagged union with conflicting enum tag name" {
+ const Bar = union(enum) {
+ A: A,
+ B: B,
+
+ const A = u8;
+ const B = void;
+ };
+
+ comptime assert(Bar.A == u8);
+}
diff --git a/test/compile_errors.zig b/test/compile_errors.zig
index bed5aa1b63..300f27cb6a 100644
--- a/test/compile_errors.zig
+++ b/test/compile_errors.zig
@@ -1,6 +1,55 @@
const tests = @import("tests.zig");
pub fn addCases(cases: &tests.CompileErrorContext) void {
+ cases.add("invalid deref on switch target",
+ \\comptime {
+ \\ var tile = Tile.Empty;
+ \\ switch (*tile) {
+ \\ Tile.Empty => {},
+ \\ Tile.Filled => {},
+ \\ }
+ \\}
+ \\const Tile = enum {
+ \\ Empty,
+ \\ Filled,
+ \\};
+ ,
+ ".tmp_source.zig:3:13: error: invalid deref on switch target");
+
+ cases.add("invalid field access in comptime",
+ \\comptime { var x = doesnt_exist.whatever; }
+ ,
+ ".tmp_source.zig:1:20: error: use of undeclared identifier 'doesnt_exist'");
+
+ cases.add("suspend inside suspend block",
+ \\const std = @import("std");
+ \\
+ \\export fn entry() void {
+ \\ var buf: [500]u8 = undefined;
+ \\ var a = &std.heap.FixedBufferAllocator.init(buf[0..]).allocator;
+ \\ const p = (async<a> foo()) catch unreachable;
+ \\ cancel p;
+ \\}
+ \\
+ \\async fn foo() void {
+ \\ suspend |p| {
+ \\ suspend |p1| {
+ \\ }
+ \\ }
+ \\}
+ ,
+ ".tmp_source.zig:12:9: error: cannot suspend inside suspend block",
+ ".tmp_source.zig:11:5: note: other suspend block here");
+
+ cases.add("assign inline fn to non-comptime var",
+ \\export fn entry() void {
+ \\ var a = b;
+ \\}
+ \\inline fn b() void { }
+ ,
+ ".tmp_source.zig:2:5: error: functions marked inline must be stored in const or comptime var",
+ ".tmp_source.zig:4:8: note: declared here");
+
cases.add("wrong type passed to @panic",
\\export fn entry() void {
\\ var e = error.Foo;
@@ -1385,17 +1434,17 @@ pub fn addCases(cases: &tests.CompileErrorContext) void {
\\const AtomicOrder = @import("builtin").AtomicOrder;
\\export fn f() void {
\\ var x: i32 = 1234;
- \\ while (!@cmpxchg(&x, 1234, 5678, AtomicOrder.Monotonic, AtomicOrder.SeqCst)) {}
+ \\ while (!@cmpxchgWeak(i32, &x, 1234, 5678, AtomicOrder.Monotonic, AtomicOrder.SeqCst)) {}
\\}
- , ".tmp_source.zig:4:72: error: failure atomic ordering must be no stricter than success");
+ , ".tmp_source.zig:4:81: error: failure atomic ordering must be no stricter than success");
cases.add("atomic orderings of cmpxchg - success Monotonic or stricter",
\\const AtomicOrder = @import("builtin").AtomicOrder;
\\export fn f() void {
\\ var x: i32 = 1234;
- \\ while (!@cmpxchg(&x, 1234, 5678, AtomicOrder.Unordered, AtomicOrder.Unordered)) {}
+ \\ while (!@cmpxchgWeak(i32, &x, 1234, 5678, AtomicOrder.Unordered, AtomicOrder.Unordered)) {}
\\}
- , ".tmp_source.zig:4:49: error: success atomic ordering must be Monotonic or stricter");
+ , ".tmp_source.zig:4:58: error: success atomic ordering must be Monotonic or stricter");
cases.add("negation overflow in function evaluation",
\\const y = neg(-128);
@@ -1723,7 +1772,7 @@ pub fn addCases(cases: &tests.CompileErrorContext) void {
\\}
\\
\\export fn entry() usize { return @sizeOf(@typeOf(bar)); }
- , ".tmp_source.zig:10:16: error: parameter of type '(integer literal)' requires comptime");
+ , ".tmp_source.zig:10:16: error: compiler bug: integer and float literals in var args function must be casted");
cases.add("assign too big number to u16",
\\export fn foo() void {
@@ -2451,11 +2500,11 @@ pub fn addCases(cases: &tests.CompileErrorContext) void {
\\const AtomicOrder = @import("builtin").AtomicOrder;
\\export fn entry() bool {
\\ var x: i32 align(1) = 1234;
- \\ while (!@cmpxchg(&x, 1234, 5678, AtomicOrder.SeqCst, AtomicOrder.SeqCst)) {}
+ \\ while (!@cmpxchgWeak(i32, &x, 1234, 5678, AtomicOrder.SeqCst, AtomicOrder.SeqCst)) {}
\\ return x == 5678;
\\}
,
- ".tmp_source.zig:4:23: error: expected pointer alignment of at least 4, found 1");
+ ".tmp_source.zig:4:32: error: expected type '&i32', found '&align(1) i32'");
cases.add("wrong size to an array literal",
\\comptime {
@@ -2525,10 +2574,10 @@ pub fn addCases(cases: &tests.CompileErrorContext) void {
cases.add("wrong types given to atomic order args in cmpxchg",
\\export fn entry() void {
\\ var x: i32 = 1234;
- \\ while (!@cmpxchg(&x, 1234, 5678, u32(1234), u32(1234))) {}
+ \\ while (!@cmpxchgWeak(i32, &x, 1234, 5678, u32(1234), u32(1234))) {}
\\}
,
- ".tmp_source.zig:3:41: error: expected type 'AtomicOrder', found 'u32'");
+ ".tmp_source.zig:3:50: error: expected type 'AtomicOrder', found 'u32'");
cases.add("wrong types given to @export",
\\extern fn entry() void { }
@@ -3160,4 +3209,32 @@ pub fn addCases(cases: &tests.CompileErrorContext) void {
\\}
,
".tmp_source.zig:5:42: error: zero-bit field 'val' in struct 'Empty' has no offset");
+
+ cases.add("invalid union field access in comptime",
+ \\const Foo = union {
+ \\ Bar: u8,
+ \\ Baz: void,
+ \\};
+ \\comptime {
+ \\ var foo = Foo {.Baz = {}};
+ \\ const bar_val = foo.Bar;
+ \\}
+ ,
+ ".tmp_source.zig:7:24: error: accessing union field 'Bar' while field 'Baz' is set");
+
+ cases.add("getting return type of generic function",
+ \\fn generic(a: var) void {}
+ \\comptime {
+ \\ _ = @typeOf(generic).ReturnType;
+ \\}
+ ,
+ ".tmp_source.zig:3:25: error: ReturnType has not been resolved because 'fn(var)var' is generic");
+
+ cases.add("getting @ArgType of generic function",
+ \\fn generic(a: var) void {}
+ \\comptime {
+ \\ _ = @ArgType(@typeOf(generic), 0);
+ \\}
+ ,
+ ".tmp_source.zig:3:36: error: @ArgType could not resolve the type of arg 0 because 'fn(var)var' is generic");
}
diff --git a/test/tests.zig b/test/tests.zig
index 19a4f82b74..5fbb56b736 100644
--- a/test/tests.zig
+++ b/test/tests.zig
@@ -152,7 +152,7 @@ pub fn addPkgTests(b: &build.Builder, test_filter: ?[]const u8, root_src: []cons
const step = b.step(b.fmt("test-{}", name), desc);
for (test_targets) |test_target| {
const is_native = (test_target.os == builtin.os and test_target.arch == builtin.arch);
- for ([]Mode{Mode.Debug, Mode.ReleaseSafe, Mode.ReleaseFast}) |mode| {
+ for ([]Mode{Mode.Debug, Mode.ReleaseSafe, Mode.ReleaseFast, Mode.ReleaseSmall}) |mode| {
for ([]bool{false, true}) |link_libc| {
if (link_libc and !is_native) {
// don't assume we have a cross-compiling libc set up
@@ -451,7 +451,7 @@ pub const CompareOutputContext = struct {
self.step.dependOn(&run_and_cmp_output.step);
},
Special.None => {
- for ([]Mode{Mode.Debug, Mode.ReleaseSafe, Mode.ReleaseFast}) |mode| {
+ for ([]Mode{Mode.Debug, Mode.ReleaseSafe, Mode.ReleaseFast, Mode.ReleaseSmall}) |mode| {
const annotated_case_name = fmt.allocPrint(self.b.allocator, "{} {} ({})",
"compare-output", case.name, @tagName(mode)) catch unreachable;
if (self.test_filter) |filter| {
@@ -583,6 +583,7 @@ pub const CompileErrorContext = struct {
Mode.Debug => {},
Mode.ReleaseSafe => zig_args.append("--release-safe") catch unreachable,
Mode.ReleaseFast => zig_args.append("--release-fast") catch unreachable,
+ Mode.ReleaseSmall => zig_args.append("--release-small") catch unreachable,
}
warn("Test {}/{} {}...", self.test_index+1, self.context.test_index, self.name);
@@ -704,7 +705,7 @@ pub const CompileErrorContext = struct {
pub fn addCase(self: &CompileErrorContext, case: &const TestCase) void {
const b = self.b;
- for ([]Mode{Mode.Debug, Mode.ReleaseSafe, Mode.ReleaseFast}) |mode| {
+ for ([]Mode{Mode.Debug, Mode.ReleaseFast}) |mode| {
const annotated_case_name = fmt.allocPrint(self.b.allocator, "compile-error {} ({})",
case.name, @tagName(mode)) catch unreachable;
if (self.test_filter) |filter| {
@@ -772,7 +773,7 @@ pub const BuildExamplesContext = struct {
pub fn addAllArgs(self: &BuildExamplesContext, root_src: []const u8, link_libc: bool) void {
const b = self.b;
- for ([]Mode{Mode.Debug, Mode.ReleaseSafe, Mode.ReleaseFast}) |mode| {
+ for ([]Mode{Mode.Debug, Mode.ReleaseSafe, Mode.ReleaseFast, Mode.ReleaseSmall}) |mode| {
const annotated_case_name = fmt.allocPrint(self.b.allocator, "build {} ({})",
root_src, @tagName(mode)) catch unreachable;
if (self.test_filter) |filter| {
diff --git a/test/translate_c.zig b/test/translate_c.zig
index 9a69c2b03e..2cd59f6f75 100644
--- a/test/translate_c.zig
+++ b/test/translate_c.zig
@@ -1,6 +1,27 @@
const tests = @import("tests.zig");
pub fn addCases(cases: &tests.TranslateCContext) void {
+ cases.add("double define struct",
+ \\typedef struct Bar Bar;
+ \\typedef struct Foo Foo;
+ \\
+ \\struct Foo {
+ \\ Foo *a;
+ \\};
+ \\
+ \\struct Bar {
+ \\ Foo *a;
+ \\};
+ ,
+ \\pub const struct_Foo = extern struct {
+ \\ a: ?&Foo,
+ \\};
+ \\pub const Foo = struct_Foo;
+ \\pub const struct_Bar = extern struct {
+ \\ a: ?&Foo,
+ \\};
+ );
+
cases.addAllowWarnings("simple data types",
\\#include <stdint.h>
\\int foo(char a, unsigned char b, signed char c);
@@ -53,6 +74,28 @@ pub fn addCases(cases: &tests.TranslateCContext) void {
\\pub const Foo = enum_Foo;
);
+ cases.add("enums",
+ \\enum Foo {
+ \\ FooA = 2,
+ \\ FooB = 5,
+ \\ Foo1,
+ \\};
+ ,
+ \\pub const enum_Foo = extern enum {
+ \\ A = 2,
+ \\ B = 5,
+ \\ @"1" = 6,
+ \\};
+ ,
+ \\pub const FooA = enum_Foo.A;
+ ,
+ \\pub const FooB = enum_Foo.B;
+ ,
+ \\pub const Foo1 = enum_Foo.@"1";
+ ,
+ \\pub const Foo = enum_Foo;
+ );
+
cases.add("restrict -> noalias",
\\void foo(void *restrict bar, void *restrict);
,