aboutsummaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
authorTakeshi Yoneda <takeshi@tetrate.io>2021-08-09 14:39:26 +0900
committerTakeshi Yoneda <takeshi@tetrate.io>2021-08-09 14:39:26 +0900
commit97560cd915008f04addc2c30af087aa89c162b02 (patch)
tree8aed12c207ff84cc256a0c78955c23b61129ba22 /test
parent7814a2bd4a3ec22cd9548c622f7dc837dba968f7 (diff)
parent799fedf612aa8742c446b015c12d21707a1dbec0 (diff)
downloadzig-97560cd915008f04addc2c30af087aa89c162b02.tar.gz
zig-97560cd915008f04addc2c30af087aa89c162b02.zip
Merge remote-tracking branch 'origin' into libc-wasi-test
Diffstat (limited to 'test')
-rw-r--r--test/behavior.zig22
-rw-r--r--test/behavior/basic.zig164
-rw-r--r--test/behavior/bool.zig44
-rw-r--r--test/behavior/bugs/6456.zig2
-rw-r--r--test/behavior/eval.zig714
-rw-r--r--test/behavior/eval_stage1.zig717
-rw-r--r--test/behavior/generics.zig143
-rw-r--r--test/behavior/generics_stage1.zig110
-rw-r--r--test/behavior/if.zig42
-rw-r--r--test/behavior/if_stage1.zig45
-rw-r--r--test/behavior/maximum_minimum.zig58
-rw-r--r--test/behavior/misc.zig267
-rw-r--r--test/behavior/pointers.zig301
-rw-r--r--test/behavior/pointers_stage1.zig305
-rw-r--r--test/behavior/select.zig25
-rw-r--r--test/behavior/translate_c_macros.h12
-rw-r--r--test/behavior/translate_c_macros.zig13
-rw-r--r--test/behavior/typename.zig111
-rw-r--r--test/behavior/widening.zig11
-rw-r--r--test/cases.zig7
-rw-r--r--test/run_translated_c.zig92
-rw-r--r--test/stage1/c_abi/cfuncs.c89
-rw-r--r--test/stage1/c_abi/main.zig87
-rw-r--r--test/stage2/arm.zig22
-rw-r--r--test/stage2/cbe.zig8
-rw-r--r--test/stage2/wasm.zig128
-rw-r--r--test/standalone.zig2
-rw-r--r--test/standalone/objc/Foo.h7
-rw-r--r--test/standalone/objc/Foo.m11
-rw-r--r--test/standalone/objc/build.zig36
-rw-r--r--test/standalone/objc/test.m12
-rw-r--r--test/tests.zig21
-rw-r--r--test/translate_c.zig15
33 files changed, 2181 insertions, 1462 deletions
diff --git a/test/behavior.zig b/test/behavior.zig
index 0055638335..a800b38458 100644
--- a/test/behavior.zig
+++ b/test/behavior.zig
@@ -2,11 +2,14 @@ const builtin = @import("builtin");
test {
// Tests that pass for both.
- {}
+ _ = @import("behavior/bool.zig");
+ _ = @import("behavior/basic.zig");
+ _ = @import("behavior/generics.zig");
+ _ = @import("behavior/eval.zig");
+ _ = @import("behavior/pointers.zig");
+ _ = @import("behavior/if.zig");
- if (builtin.zig_is_stage2) {
- // Tests that only pass for stage2.
- } else {
+ if (!builtin.zig_is_stage2) {
// Tests that only pass for stage1.
_ = @import("behavior/align.zig");
_ = @import("behavior/alignof.zig");
@@ -20,7 +23,6 @@ test {
_ = @import("behavior/bit_shifting.zig");
_ = @import("behavior/bitcast.zig");
_ = @import("behavior/bitreverse.zig");
- _ = @import("behavior/bool.zig");
_ = @import("behavior/bugs/1025.zig");
_ = @import("behavior/bugs/1076.zig");
_ = @import("behavior/bugs/1111.zig");
@@ -89,35 +91,37 @@ test {
_ = @import("behavior/enum.zig");
_ = @import("behavior/enum_with_members.zig");
_ = @import("behavior/error.zig");
- _ = @import("behavior/eval.zig");
+ _ = @import("behavior/eval_stage1.zig");
_ = @import("behavior/field_parent_ptr.zig");
_ = @import("behavior/floatop.zig");
_ = @import("behavior/fn.zig");
_ = @import("behavior/fn_in_struct_in_comptime.zig");
_ = @import("behavior/fn_delegation.zig");
_ = @import("behavior/for.zig");
- _ = @import("behavior/generics.zig");
+ _ = @import("behavior/generics_stage1.zig");
_ = @import("behavior/hasdecl.zig");
_ = @import("behavior/hasfield.zig");
- _ = @import("behavior/if.zig");
+ _ = @import("behavior/if_stage1.zig");
_ = @import("behavior/import.zig");
_ = @import("behavior/incomplete_struct_param_tld.zig");
_ = @import("behavior/inttoptr.zig");
_ = @import("behavior/ir_block_deps.zig");
_ = @import("behavior/math.zig");
+ _ = @import("behavior/maximum_minimum.zig");
_ = @import("behavior/merge_error_sets.zig");
_ = @import("behavior/misc.zig");
_ = @import("behavior/muladd.zig");
_ = @import("behavior/namespace_depends_on_compile_var.zig");
_ = @import("behavior/null.zig");
_ = @import("behavior/optional.zig");
- _ = @import("behavior/pointers.zig");
+ _ = @import("behavior/pointers_stage1.zig");
_ = @import("behavior/popcount.zig");
_ = @import("behavior/ptrcast.zig");
_ = @import("behavior/pub_enum.zig");
_ = @import("behavior/ref_var_in_if_after_if_2nd_switch_prong.zig");
_ = @import("behavior/reflection.zig");
_ = @import("behavior/shuffle.zig");
+ _ = @import("behavior/select.zig");
_ = @import("behavior/sizeof_and_typeof.zig");
_ = @import("behavior/slice.zig");
_ = @import("behavior/slice_sentinel_comptime.zig");
diff --git a/test/behavior/basic.zig b/test/behavior/basic.zig
new file mode 100644
index 0000000000..1372dfaeeb
--- /dev/null
+++ b/test/behavior/basic.zig
@@ -0,0 +1,164 @@
+const std = @import("std");
+const mem = std.mem;
+const expect = std.testing.expect;
+
+// normal comment
+
+/// this is a documentation comment
+/// doc comment line 2
+fn emptyFunctionWithComments() void {}
+
+test "empty function with comments" {
+ emptyFunctionWithComments();
+}
+
+test "truncate" {
+ try expect(testTruncate(0x10fd) == 0xfd);
+ comptime try expect(testTruncate(0x10fd) == 0xfd);
+}
+fn testTruncate(x: u32) u8 {
+ return @truncate(u8, x);
+}
+
+const g1: i32 = 1233 + 1;
+var g2: i32 = 0;
+
+test "global variables" {
+ try expect(g2 == 0);
+ g2 = g1;
+ try expect(g2 == 1234);
+}
+
+test "comptime keyword on expressions" {
+ const x: i32 = comptime x: {
+ break :x 1 + 2 + 3;
+ };
+ try expect(x == comptime 6);
+}
+
+test "type equality" {
+ try expect(*const u8 != *u8);
+}
+
+test "pointer dereferencing" {
+ var x = @as(i32, 3);
+ const y = &x;
+
+ y.* += 1;
+
+ try expect(x == 4);
+ try expect(y.* == 4);
+}
+
+test "const expression eval handling of variables" {
+ var x = true;
+ while (x) {
+ x = false;
+ }
+}
+
+test "character literals" {
+ try expect('\'' == single_quote);
+}
+const single_quote = '\'';
+
+test "non const ptr to aliased type" {
+ const int = i32;
+ try expect(?*int == ?*i32);
+}
+
+test "cold function" {
+ thisIsAColdFn();
+ comptime thisIsAColdFn();
+}
+
+fn thisIsAColdFn() void {
+ @setCold(true);
+}
+
+test "unicode escape in character literal" {
+ var a: u24 = '\u{01f4a9}';
+ try expect(a == 128169);
+}
+
+test "unicode character in character literal" {
+ try expect('💩' == 128169);
+}
+
+fn first4KeysOfHomeRow() []const u8 {
+ return "aoeu";
+}
+
+test "return string from function" {
+ try expect(mem.eql(u8, first4KeysOfHomeRow(), "aoeu"));
+}
+
+test "hex escape" {
+ try expect(mem.eql(u8, "\x68\x65\x6c\x6c\x6f", "hello"));
+}
+
+test "multiline string" {
+ const s1 =
+ \\one
+ \\two)
+ \\three
+ ;
+ const s2 = "one\ntwo)\nthree";
+ try expect(mem.eql(u8, s1, s2));
+}
+
+test "multiline string comments at start" {
+ const s1 =
+ //\\one
+ \\two)
+ \\three
+ ;
+ const s2 = "two)\nthree";
+ try expect(mem.eql(u8, s1, s2));
+}
+
+test "multiline string comments at end" {
+ const s1 =
+ \\one
+ \\two)
+ //\\three
+ ;
+ const s2 = "one\ntwo)";
+ try expect(mem.eql(u8, s1, s2));
+}
+
+test "multiline string comments in middle" {
+ const s1 =
+ \\one
+ //\\two)
+ \\three
+ ;
+ const s2 = "one\nthree";
+ try expect(mem.eql(u8, s1, s2));
+}
+
+test "multiline string comments at multiple places" {
+ const s1 =
+ \\one
+ //\\two
+ \\three
+ //\\four
+ \\five
+ ;
+ const s2 = "one\nthree\nfive";
+ try expect(mem.eql(u8, s1, s2));
+}
+
+test "call result of if else expression" {
+ try expect(mem.eql(u8, f2(true), "a"));
+ try expect(mem.eql(u8, f2(false), "b"));
+}
+fn f2(x: bool) []const u8 {
+ return (if (x) fA else fB)();
+}
+fn fA() []const u8 {
+ return "a";
+}
+fn fB() []const u8 {
+ return "b";
+}
diff --git a/test/behavior/bool.zig b/test/behavior/bool.zig
index dfa02a6bfd..447f9e02e6 100644
--- a/test/behavior/bool.zig
+++ b/test/behavior/bool.zig
@@ -33,3 +33,47 @@ test "compile time bool not" {
try expect(not_global_f);
try expect(!not_global_t);
}
+
+test "short circuit" {
+ try testShortCircuit(false, true);
+ comptime try testShortCircuit(false, true);
+}
+
+fn testShortCircuit(f: bool, t: bool) !void {
+ var hit_1 = f;
+ var hit_2 = f;
+ var hit_3 = f;
+ var hit_4 = f;
+
+ if (t or x: {
+ try expect(f);
+ break :x f;
+ }) {
+ hit_1 = t;
+ }
+ if (f or x: {
+ hit_2 = t;
+ break :x f;
+ }) {
+ try expect(f);
+ }
+
+ if (t and x: {
+ hit_3 = t;
+ break :x f;
+ }) {
+ try expect(f);
+ }
+ if (f and x: {
+ try expect(f);
+ break :x f;
+ }) {
+ try expect(f);
+ } else {
+ hit_4 = t;
+ }
+ try expect(hit_1);
+ try expect(hit_2);
+ try expect(hit_3);
+ try expect(hit_4);
+}
diff --git a/test/behavior/bugs/6456.zig b/test/behavior/bugs/6456.zig
index 8078ab147f..44fdfd69ba 100644
--- a/test/behavior/bugs/6456.zig
+++ b/test/behavior/bugs/6456.zig
@@ -13,7 +13,7 @@ test "issue 6456" {
comptime {
var fields: []const StructField = &[0]StructField{};
- var it = std.mem.tokenize(text, "\n");
+ var it = std.mem.tokenize(u8, text, "\n");
while (it.next()) |name| {
fields = fields ++ &[_]StructField{StructField{
.alignment = 0,
diff --git a/test/behavior/eval.zig b/test/behavior/eval.zig
index 566ed74e2d..a97aab7bb3 100644
--- a/test/behavior/eval.zig
+++ b/test/behavior/eval.zig
@@ -63,146 +63,12 @@ fn constExprEvalOnSingleExprBlocksFn(x: i32, b: bool) i32 {
return result;
}
-test "statically initialized list" {
- try expect(static_point_list[0].x == 1);
- try expect(static_point_list[0].y == 2);
- try expect(static_point_list[1].x == 3);
- try expect(static_point_list[1].y == 4);
-}
-const Point = struct {
- x: i32,
- y: i32,
-};
-const static_point_list = [_]Point{
- makePoint(1, 2),
- makePoint(3, 4),
-};
-fn makePoint(x: i32, y: i32) Point {
- return Point{
- .x = x,
- .y = y,
- };
-}
-
-test "static eval list init" {
- try expect(static_vec3.data[2] == 1.0);
- try expect(vec3(0.0, 0.0, 3.0).data[2] == 3.0);
-}
-const static_vec3 = vec3(0.0, 0.0, 1.0);
-pub const Vec3 = struct {
- data: [3]f32,
-};
-pub fn vec3(x: f32, y: f32, z: f32) Vec3 {
- return Vec3{
- .data = [_]f32{
- x,
- y,
- z,
- },
- };
-}
-
test "constant expressions" {
var array: [array_size]u8 = undefined;
try expect(@sizeOf(@TypeOf(array)) == 20);
}
const array_size: u8 = 20;
-test "constant struct with negation" {
- try expect(vertices[0].x == -0.6);
-}
-const Vertex = struct {
- x: f32,
- y: f32,
- r: f32,
- g: f32,
- b: f32,
-};
-const vertices = [_]Vertex{
- Vertex{
- .x = -0.6,
- .y = -0.4,
- .r = 1.0,
- .g = 0.0,
- .b = 0.0,
- },
- Vertex{
- .x = 0.6,
- .y = -0.4,
- .r = 0.0,
- .g = 1.0,
- .b = 0.0,
- },
- Vertex{
- .x = 0.0,
- .y = 0.6,
- .r = 0.0,
- .g = 0.0,
- .b = 1.0,
- },
-};
-
-test "statically initialized struct" {
- st_init_str_foo.x += 1;
- try expect(st_init_str_foo.x == 14);
-}
-const StInitStrFoo = struct {
- x: i32,
- y: bool,
-};
-var st_init_str_foo = StInitStrFoo{
- .x = 13,
- .y = true,
-};
-
-test "statically initalized array literal" {
- const y: [4]u8 = st_init_arr_lit_x;
- try expect(y[3] == 4);
-}
-const st_init_arr_lit_x = [_]u8{
- 1,
- 2,
- 3,
- 4,
-};
-
-test "const slice" {
- comptime {
- const a = "1234567890";
- try expect(a.len == 10);
- const b = a[1..2];
- try expect(b.len == 1);
- try expect(b[0] == '2');
- }
-}
-
-test "try to trick eval with runtime if" {
- try expect(testTryToTrickEvalWithRuntimeIf(true) == 10);
-}
-
-fn testTryToTrickEvalWithRuntimeIf(b: bool) usize {
- comptime var i: usize = 0;
- inline while (i < 10) : (i += 1) {
- const result = if (b) false else true;
- _ = result;
- }
- comptime {
- return i;
- }
-}
-
-test "inlined loop has array literal with elided runtime scope on first iteration but not second iteration" {
- var runtime = [1]i32{3};
- comptime var i: usize = 0;
- inline while (i < 2) : (i += 1) {
- const result = if (i == 0) [1]i32{2} else runtime;
- _ = result;
- }
- comptime {
- try expect(i == 2);
- }
-}
-
fn max(comptime T: type, a: T, b: T) T {
if (T == bool) {
return a or b;
@@ -229,52 +95,6 @@ test "inlined block and runtime block phi" {
}
}
-const CmdFn = struct {
- name: []const u8,
- func: fn (i32) i32,
-};
-
-const cmd_fns = [_]CmdFn{
- CmdFn{
- .name = "one",
- .func = one,
- },
- CmdFn{
- .name = "two",
- .func = two,
- },
- CmdFn{
- .name = "three",
- .func = three,
- },
-};
-fn one(value: i32) i32 {
- return value + 1;
-}
-fn two(value: i32) i32 {
- return value + 2;
-}
-fn three(value: i32) i32 {
- return value + 3;
-}
-
-fn performFn(comptime prefix_char: u8, start_value: i32) i32 {
- var result: i32 = start_value;
- comptime var i = 0;
- inline while (i < cmd_fns.len) : (i += 1) {
- if (cmd_fns[i].name[0] == prefix_char) {
- result = cmd_fns[i].func(result);
- }
- }
- return result;
-}
-
-test "comptime iterate over fn ptr list" {
- try expect(performFn('t', 1) == 6);
- try expect(performFn('o', 0) == 1);
- try expect(performFn('w', 99) == 99);
-}
-
test "eval @setRuntimeSafety at compile-time" {
const result = comptime fnWithSetRuntimeSafety();
try expect(result == 1234);
@@ -285,90 +105,6 @@ fn fnWithSetRuntimeSafety() i32 {
return 1234;
}
-test "eval @setFloatMode at compile-time" {
- const result = comptime fnWithFloatMode();
- try expect(result == 1234.0);
-}
-
-fn fnWithFloatMode() f32 {
- @setFloatMode(std.builtin.FloatMode.Strict);
- return 1234.0;
-}
-
-const SimpleStruct = struct {
- field: i32,
-
- fn method(self: *const SimpleStruct) i32 {
- return self.field + 3;
- }
-};
-
-var simple_struct = SimpleStruct{ .field = 1234 };
-
-const bound_fn = simple_struct.method;
-
-test "call method on bound fn referring to var instance" {
- try expect(bound_fn() == 1237);
-}
-
-test "ptr to local array argument at comptime" {
- comptime {
- var bytes: [10]u8 = undefined;
- modifySomeBytes(bytes[0..]);
- try expect(bytes[0] == 'a');
- try expect(bytes[9] == 'b');
- }
-}
-
-fn modifySomeBytes(bytes: []u8) void {
- bytes[0] = 'a';
- bytes[9] = 'b';
-}
-
-test "comparisons 0 <= uint and 0 > uint should be comptime" {
- testCompTimeUIntComparisons(1234);
-}
-fn testCompTimeUIntComparisons(x: u32) void {
- if (!(0 <= x)) {
- @compileError("this condition should be comptime known");
- }
- if (0 > x) {
- @compileError("this condition should be comptime known");
- }
- if (!(x >= 0)) {
- @compileError("this condition should be comptime known");
- }
- if (x < 0) {
- @compileError("this condition should be comptime known");
- }
-}
-
-test "const ptr to variable data changes at runtime" {
- try expect(foo_ref.name[0] == 'a');
- foo_ref.name = "b";
- try expect(foo_ref.name[0] == 'b');
-}
-
-const Foo = struct {
- name: []const u8,
-};
-
-var foo_contents = Foo{ .name = "a" };
-const foo_ref = &foo_contents;
-
-test "create global array with for loop" {
- try expect(global_array[5] == 5 * 5);
- try expect(global_array[9] == 9 * 9);
-}
-
-const global_array = x: {
- var result: [10]usize = undefined;
- for (result) |*item, index| {
- item.* = index * index;
- }
- break :x result;
-};
-
test "compile-time downcast when the bits fit" {
comptime {
const spartan_count: u16 = 255;
@@ -377,231 +113,6 @@ test "compile-time downcast when the bits fit" {
}
}
-const hi1 = "hi";
-const hi2 = hi1;
-test "const global shares pointer with other same one" {
- try assertEqualPtrs(&hi1[0], &hi2[0]);
- comptime try expect(&hi1[0] == &hi2[0]);
-}
-fn assertEqualPtrs(ptr1: *const u8, ptr2: *const u8) !void {
- try expect(ptr1 == ptr2);
-}
-
-test "@setEvalBranchQuota" {
- comptime {
- // 1001 for the loop and then 1 more for the expect fn call
- @setEvalBranchQuota(1002);
- var i = 0;
- var sum = 0;
- while (i < 1001) : (i += 1) {
- sum += i;
- }
- try expect(sum == 500500);
- }
-}
-
-test "float literal at compile time not lossy" {
- try expect(16777216.0 + 1.0 == 16777217.0);
- try expect(9007199254740992.0 + 1.0 == 9007199254740993.0);
-}
-
-test "f32 at compile time is lossy" {
- try expect(@as(f32, 1 << 24) + 1 == 1 << 24);
-}
-
-test "f64 at compile time is lossy" {
- try expect(@as(f64, 1 << 53) + 1 == 1 << 53);
-}
-
-test "f128 at compile time is lossy" {
- try expect(@as(f128, 10384593717069655257060992658440192.0) + 1 == 10384593717069655257060992658440192.0);
-}
-
-test {
- comptime try expect(@as(f128, 1 << 113) == 10384593717069655257060992658440192);
-}
-
-pub fn TypeWithCompTimeSlice(comptime field_name: []const u8) type {
- _ = field_name;
- return struct {
- pub const Node = struct {};
- };
-}
-
-test "string literal used as comptime slice is memoized" {
- const a = "link";
- const b = "link";
- comptime try expect(TypeWithCompTimeSlice(a).Node == TypeWithCompTimeSlice(b).Node);
- comptime try expect(TypeWithCompTimeSlice("link").Node == TypeWithCompTimeSlice("link").Node);
-}
-
-test "comptime slice of undefined pointer of length 0" {
- const slice1 = @as([*]i32, undefined)[0..0];
- try expect(slice1.len == 0);
- const slice2 = @as([*]i32, undefined)[100..100];
- try expect(slice2.len == 0);
-}
-
-fn copyWithPartialInline(s: []u32, b: []u8) void {
- comptime var i: usize = 0;
- inline while (i < 4) : (i += 1) {
- s[i] = 0;
- s[i] |= @as(u32, b[i * 4 + 0]) << 24;
- s[i] |= @as(u32, b[i * 4 + 1]) << 16;
- s[i] |= @as(u32, b[i * 4 + 2]) << 8;
- s[i] |= @as(u32, b[i * 4 + 3]) << 0;
- }
-}
-
-test "binary math operator in partially inlined function" {
- var s: [4]u32 = undefined;
- var b: [16]u8 = undefined;
-
- for (b) |*r, i|
- r.* = @intCast(u8, i + 1);
-
- copyWithPartialInline(s[0..], b[0..]);
- try expect(s[0] == 0x1020304);
- try expect(s[1] == 0x5060708);
- try expect(s[2] == 0x90a0b0c);
- try expect(s[3] == 0xd0e0f10);
-}
-
-test "comptime function with the same args is memoized" {
- comptime {
- try expect(MakeType(i32) == MakeType(i32));
- try expect(MakeType(i32) != MakeType(f64));
- }
-}
-
-fn MakeType(comptime T: type) type {
- return struct {
- field: T,
- };
-}
-
-test "comptime function with mutable pointer is not memoized" {
- comptime {
- var x: i32 = 1;
- const ptr = &x;
- increment(ptr);
- increment(ptr);
- try expect(x == 3);
- }
-}
-
-fn increment(value: *i32) void {
- value.* += 1;
-}
-
-fn generateTable(comptime T: type) [1010]T {
- var res: [1010]T = undefined;
- var i: usize = 0;
- while (i < 1010) : (i += 1) {
- res[i] = @intCast(T, i);
- }
- return res;
-}
-
-fn doesAlotT(comptime T: type, value: usize) T {
- @setEvalBranchQuota(5000);
- const table = comptime blk: {
- break :blk generateTable(T);
- };
- return table[value];
-}
-
-test "@setEvalBranchQuota at same scope as generic function call" {
- try expect(doesAlotT(u32, 2) == 2);
-}
-
-test "comptime slice of slice preserves comptime var" {
- comptime {
- var buff: [10]u8 = undefined;
- buff[0..][0..][0] = 1;
- try expect(buff[0..][0..][0] == 1);
- }
-}
-
-test "comptime slice of pointer preserves comptime var" {
- comptime {
- var buff: [10]u8 = undefined;
- var a = @ptrCast([*]u8, &buff);
- a[0..1][0] = 1;
- try expect(buff[0..][0..][0] == 1);
- }
-}
-
-const SingleFieldStruct = struct {
- x: i32,
-
- fn read_x(self: *const SingleFieldStruct) i32 {
- return self.x;
- }
-};
-test "const ptr to comptime mutable data is not memoized" {
- comptime {
- var foo = SingleFieldStruct{ .x = 1 };
- try expect(foo.read_x() == 1);
- foo.x = 2;
- try expect(foo.read_x() == 2);
- }
-}
-
-test "array concat of slices gives slice" {
- comptime {
- var a: []const u8 = "aoeu";
- var b: []const u8 = "asdf";
- const c = a ++ b;
- try expect(std.mem.eql(u8, c, "aoeuasdf"));
- }
-}
-
-test "comptime shlWithOverflow" {
- const ct_shifted: u64 = comptime amt: {
- var amt = @as(u64, 0);
- _ = @shlWithOverflow(u64, ~@as(u64, 0), 16, &amt);
- break :amt amt;
- };
-
- const rt_shifted: u64 = amt: {
- var amt = @as(u64, 0);
- _ = @shlWithOverflow(u64, ~@as(u64, 0), 16, &amt);
- break :amt amt;
- };
-
- try expect(ct_shifted == rt_shifted);
-}
-
-test "comptime shl" {
- var a: u128 = 3;
- var b: u7 = 63;
- var c: u128 = 3 << 63;
- try expectEqual(a << b, c);
-}
-
-test "runtime 128 bit integer division" {
- var a: u128 = 152313999999999991610955792383;
- var b: u128 = 10000000000000000000;
- var c = a / b;
- try expect(c == 15231399999);
-}
-
-pub const Info = struct {
- version: u8,
-};
-
-pub const diamond_info = Info{ .version = 0 };
-
-test "comptime modification of const struct field" {
- comptime {
- var res = diamond_info;
- res.version = 1;
- try expect(diamond_info.version == 0);
- try expect(res.version == 1);
- }
-}
-
test "pointer to type" {
comptime {
var T: type = i32;
@@ -614,233 +125,8 @@ test "pointer to type" {
}
}
-test "slice of type" {
- comptime {
- var types_array = [_]type{ i32, f64, type };
- for (types_array) |T, i| {
- switch (i) {
- 0 => try expect(T == i32),
- 1 => try expect(T == f64),
- 2 => try expect(T == type),
- else => unreachable,
- }
- }
- for (types_array[0..]) |T, i| {
- switch (i) {
- 0 => try expect(T == i32),
- 1 => try expect(T == f64),
- 2 => try expect(T == type),
- else => unreachable,
- }
- }
- }
-}
-
-const Wrapper = struct {
- T: type,
-};
-
-fn wrap(comptime T: type) Wrapper {
- return Wrapper{ .T = T };
-}
-
-test "function which returns struct with type field causes implicit comptime" {
- const ty = wrap(i32).T;
- try expect(ty == i32);
-}
-
-test "call method with comptime pass-by-non-copying-value self parameter" {
- const S = struct {
- a: u8,
-
- fn b(comptime s: @This()) u8 {
- return s.a;
- }
- };
-
- const s = S{ .a = 2 };
- var b = s.b();
- try expect(b == 2);
-}
-
-test "@tagName of @typeInfo" {
- const str = @tagName(@typeInfo(u8));
- try expect(std.mem.eql(u8, str, "Int"));
-}
-
-test "setting backward branch quota just before a generic fn call" {
- @setEvalBranchQuota(1001);
- loopNTimes(1001);
-}
-
-fn loopNTimes(comptime n: usize) void {
- comptime var i = 0;
- inline while (i < n) : (i += 1) {}
-}
-
-test "variable inside inline loop that has different types on different iterations" {
- try testVarInsideInlineLoop(.{ true, @as(u32, 42) });
-}
-
-fn testVarInsideInlineLoop(args: anytype) !void {
- comptime var i = 0;
- inline while (i < args.len) : (i += 1) {
- const x = args[i];
- if (i == 0) try expect(x);
- if (i == 1) try expect(x == 42);
- }
-}
-
-test "inline for with same type but different values" {
- var res: usize = 0;
- inline for ([_]type{ [2]u8, [1]u8, [2]u8 }) |T| {
- var a: T = undefined;
- res += a.len;
- }
- try expect(res == 5);
-}
-
-test "refer to the type of a generic function" {
- const Func = fn (type) void;
- const f: Func = doNothingWithType;
- f(i32);
-}
-
-fn doNothingWithType(comptime T: type) void {
- _ = T;
-}
-
-test "zero extend from u0 to u1" {
- var zero_u0: u0 = 0;
- var zero_u1: u1 = zero_u0;
- try expect(zero_u1 == 0);
-}
-
-test "bit shift a u1" {
- var x: u1 = 1;
- var y = x << 0;
- try expect(y == 1);
-}
-
-test "comptime pointer cast array and then slice" {
- const array = [_]u8{ 1, 2, 3, 4, 5, 6, 7, 8 };
-
- const ptrA: [*]const u8 = @ptrCast([*]const u8, &array);
- const sliceA: []const u8 = ptrA[0..2];
-
- const ptrB: [*]const u8 = &array;
- const sliceB: []const u8 = ptrB[0..2];
-
- try expect(sliceA[1] == 2);
- try expect(sliceB[1] == 2);
-}
-
-test "slice bounds in comptime concatenation" {
- const bs = comptime blk: {
- const b = "........1........";
- break :blk b[8..9];
- };
- const str = "" ++ bs;
- try expect(str.len == 1);
- try expect(std.mem.eql(u8, str, "1"));
-
- const str2 = bs ++ "";
- try expect(str2.len == 1);
- try expect(std.mem.eql(u8, str2, "1"));
-}
-
-test "comptime bitwise operators" {
- comptime {
- try expect(3 & 1 == 1);
- try expect(3 & -1 == 3);
- try expect(-3 & -1 == -3);
- try expect(3 | -1 == -1);
- try expect(-3 | -1 == -1);
- try expect(3 ^ -1 == -4);
- try expect(-3 ^ -1 == 2);
- try expect(~@as(i8, -1) == 0);
- try expect(~@as(i128, -1) == 0);
- try expect(18446744073709551615 & 18446744073709551611 == 18446744073709551611);
- try expect(-18446744073709551615 & -18446744073709551611 == -18446744073709551615);
- try expect(~@as(u128, 0) == 0xffffffffffffffffffffffffffffffff);
- }
-}
-
-test "*align(1) u16 is the same as *align(1:0:2) u16" {
- comptime {
- try expect(*align(1:0:2) u16 == *align(1) u16);
- try expect(*align(2:0:2) u16 == *u16);
- }
-}
-
-test "array concatenation forces comptime" {
- var a = oneItem(3) ++ oneItem(4);
- try expect(std.mem.eql(i32, &a, &[_]i32{ 3, 4 }));
-}
-
-test "array multiplication forces comptime" {
- var a = oneItem(3) ** scalar(2);
- try expect(std.mem.eql(i32, &a, &[_]i32{ 3, 3 }));
-}
-
-fn oneItem(x: i32) [1]i32 {
- return [_]i32{x};
-}
-
-fn scalar(x: u32) u32 {
- return x;
-}
-
test "no undeclared identifier error in unanalyzed branches" {
if (false) {
lol_this_doesnt_exist = nonsense;
}
}
-
-test "comptime assign int to optional int" {
- comptime {
- var x: ?i32 = null;
- x = 2;
- x.? *= 10;
- try expectEqual(20, x.?);
- }
-}
-
-test "return 0 from function that has u0 return type" {
- const S = struct {
- fn foo_zero() u0 {
- return 0;
- }
- };
- comptime {
- if (S.foo_zero() != 0) {
- @compileError("test failed");
- }
- }
-}
-
-test "two comptime calls with array default initialized to undefined" {
- const S = struct {
- const CrossTarget = struct {
- dynamic_linker: DynamicLinker = DynamicLinker{},
-
- pub fn parse() void {
- var result: CrossTarget = .{};
- result.getCpuArch();
- }
-
- pub fn getCpuArch(self: CrossTarget) void {
- _ = self;
- }
- };
-
- const DynamicLinker = struct {
- buffer: [255]u8 = undefined,
- };
- };
-
- comptime {
- S.CrossTarget.parse();
- S.CrossTarget.parse();
- }
-}
diff --git a/test/behavior/eval_stage1.zig b/test/behavior/eval_stage1.zig
new file mode 100644
index 0000000000..3599d5a477
--- /dev/null
+++ b/test/behavior/eval_stage1.zig
@@ -0,0 +1,717 @@
+const std = @import("std");
+const expect = std.testing.expect;
+const expectEqual = std.testing.expectEqual;
+
+test "statically initialized list" {
+ try expect(static_point_list[0].x == 1);
+ try expect(static_point_list[0].y == 2);
+ try expect(static_point_list[1].x == 3);
+ try expect(static_point_list[1].y == 4);
+}
+const Point = struct {
+ x: i32,
+ y: i32,
+};
+const static_point_list = [_]Point{
+ makePoint(1, 2),
+ makePoint(3, 4),
+};
+fn makePoint(x: i32, y: i32) Point {
+ return Point{
+ .x = x,
+ .y = y,
+ };
+}
+
+test "static eval list init" {
+ try expect(static_vec3.data[2] == 1.0);
+ try expect(vec3(0.0, 0.0, 3.0).data[2] == 3.0);
+}
+const static_vec3 = vec3(0.0, 0.0, 1.0);
+pub const Vec3 = struct {
+ data: [3]f32,
+};
+pub fn vec3(x: f32, y: f32, z: f32) Vec3 {
+ return Vec3{
+ .data = [_]f32{
+ x,
+ y,
+ z,
+ },
+ };
+}
+
+test "constant struct with negation" {
+ try expect(vertices[0].x == -0.6);
+}
+const Vertex = struct {
+ x: f32,
+ y: f32,
+ r: f32,
+ g: f32,
+ b: f32,
+};
+const vertices = [_]Vertex{
+ Vertex{
+ .x = -0.6,
+ .y = -0.4,
+ .r = 1.0,
+ .g = 0.0,
+ .b = 0.0,
+ },
+ Vertex{
+ .x = 0.6,
+ .y = -0.4,
+ .r = 0.0,
+ .g = 1.0,
+ .b = 0.0,
+ },
+ Vertex{
+ .x = 0.0,
+ .y = 0.6,
+ .r = 0.0,
+ .g = 0.0,
+ .b = 1.0,
+ },
+};
+
+test "statically initialized struct" {
+ st_init_str_foo.x += 1;
+ try expect(st_init_str_foo.x == 14);
+}
+const StInitStrFoo = struct {
+ x: i32,
+ y: bool,
+};
+var st_init_str_foo = StInitStrFoo{
+ .x = 13,
+ .y = true,
+};
+
+test "statically initalized array literal" {
+ const y: [4]u8 = st_init_arr_lit_x;
+ try expect(y[3] == 4);
+}
+const st_init_arr_lit_x = [_]u8{
+ 1,
+ 2,
+ 3,
+ 4,
+};
+
+test "const slice" {
+ comptime {
+ const a = "1234567890";
+ try expect(a.len == 10);
+ const b = a[1..2];
+ try expect(b.len == 1);
+ try expect(b[0] == '2');
+ }
+}
+
+test "try to trick eval with runtime if" {
+ try expect(testTryToTrickEvalWithRuntimeIf(true) == 10);
+}
+
+fn testTryToTrickEvalWithRuntimeIf(b: bool) usize {
+ comptime var i: usize = 0;
+ inline while (i < 10) : (i += 1) {
+ const result = if (b) false else true;
+ _ = result;
+ }
+ comptime {
+ return i;
+ }
+}
+
+test "inlined loop has array literal with elided runtime scope on first iteration but not second iteration" {
+ var runtime = [1]i32{3};
+ comptime var i: usize = 0;
+ inline while (i < 2) : (i += 1) {
+ const result = if (i == 0) [1]i32{2} else runtime;
+ _ = result;
+ }
+ comptime {
+ try expect(i == 2);
+ }
+}
+
+const CmdFn = struct {
+ name: []const u8,
+ func: fn (i32) i32,
+};
+
+const cmd_fns = [_]CmdFn{
+ CmdFn{
+ .name = "one",
+ .func = one,
+ },
+ CmdFn{
+ .name = "two",
+ .func = two,
+ },
+ CmdFn{
+ .name = "three",
+ .func = three,
+ },
+};
+fn one(value: i32) i32 {
+ return value + 1;
+}
+fn two(value: i32) i32 {
+ return value + 2;
+}
+fn three(value: i32) i32 {
+ return value + 3;
+}
+
+fn performFn(comptime prefix_char: u8, start_value: i32) i32 {
+ var result: i32 = start_value;
+ comptime var i = 0;
+ inline while (i < cmd_fns.len) : (i += 1) {
+ if (cmd_fns[i].name[0] == prefix_char) {
+ result = cmd_fns[i].func(result);
+ }
+ }
+ return result;
+}
+
+test "comptime iterate over fn ptr list" {
+ try expect(performFn('t', 1) == 6);
+ try expect(performFn('o', 0) == 1);
+ try expect(performFn('w', 99) == 99);
+}
+
+test "eval @setFloatMode at compile-time" {
+ const result = comptime fnWithFloatMode();
+ try expect(result == 1234.0);
+}
+
+fn fnWithFloatMode() f32 {
+ @setFloatMode(std.builtin.FloatMode.Strict);
+ return 1234.0;
+}
+
+const SimpleStruct = struct {
+ field: i32,
+
+ fn method(self: *const SimpleStruct) i32 {
+ return self.field + 3;
+ }
+};
+
+var simple_struct = SimpleStruct{ .field = 1234 };
+
+const bound_fn = simple_struct.method;
+
+test "call method on bound fn referring to var instance" {
+ try expect(bound_fn() == 1237);
+}
+
+test "ptr to local array argument at comptime" {
+ comptime {
+ var bytes: [10]u8 = undefined;
+ modifySomeBytes(bytes[0..]);
+ try expect(bytes[0] == 'a');
+ try expect(bytes[9] == 'b');
+ }
+}
+
+fn modifySomeBytes(bytes: []u8) void {
+ bytes[0] = 'a';
+ bytes[9] = 'b';
+}
+
+test "comparisons 0 <= uint and 0 > uint should be comptime" {
+ testCompTimeUIntComparisons(1234);
+}
+fn testCompTimeUIntComparisons(x: u32) void {
+ if (!(0 <= x)) {
+ @compileError("this condition should be comptime known");
+ }
+ if (0 > x) {
+ @compileError("this condition should be comptime known");
+ }
+ if (!(x >= 0)) {
+ @compileError("this condition should be comptime known");
+ }
+ if (x < 0) {
+ @compileError("this condition should be comptime known");
+ }
+}
+
+test "const ptr to variable data changes at runtime" {
+ try expect(foo_ref.name[0] == 'a');
+ foo_ref.name = "b";
+ try expect(foo_ref.name[0] == 'b');
+}
+
+const Foo = struct {
+ name: []const u8,
+};
+
+var foo_contents = Foo{ .name = "a" };
+const foo_ref = &foo_contents;
+
+test "create global array with for loop" {
+ try expect(global_array[5] == 5 * 5);
+ try expect(global_array[9] == 9 * 9);
+}
+
+const global_array = x: {
+ var result: [10]usize = undefined;
+ for (result) |*item, index| {
+ item.* = index * index;
+ }
+ break :x result;
+};
+
+const hi1 = "hi";
+const hi2 = hi1;
+test "const global shares pointer with other same one" {
+ try assertEqualPtrs(&hi1[0], &hi2[0]);
+ comptime try expect(&hi1[0] == &hi2[0]);
+}
+fn assertEqualPtrs(ptr1: *const u8, ptr2: *const u8) !void {
+ try expect(ptr1 == ptr2);
+}
+
+test "@setEvalBranchQuota" {
+ comptime {
+ // 1001 for the loop and then 1 more for the expect fn call
+ @setEvalBranchQuota(1002);
+ var i = 0;
+ var sum = 0;
+ while (i < 1001) : (i += 1) {
+ sum += i;
+ }
+ try expect(sum == 500500);
+ }
+}
+
+test "float literal at compile time not lossy" {
+ try expect(16777216.0 + 1.0 == 16777217.0);
+ try expect(9007199254740992.0 + 1.0 == 9007199254740993.0);
+}
+
+test "f32 at compile time is lossy" {
+ try expect(@as(f32, 1 << 24) + 1 == 1 << 24);
+}
+
+test "f64 at compile time is lossy" {
+ try expect(@as(f64, 1 << 53) + 1 == 1 << 53);
+}
+
+test "f128 at compile time is lossy" {
+ try expect(@as(f128, 10384593717069655257060992658440192.0) + 1 == 10384593717069655257060992658440192.0);
+}
+
+test {
+ comptime try expect(@as(f128, 1 << 113) == 10384593717069655257060992658440192);
+}
+
+pub fn TypeWithCompTimeSlice(comptime field_name: []const u8) type {
+ _ = field_name;
+ return struct {
+ pub const Node = struct {};
+ };
+}
+
+test "string literal used as comptime slice is memoized" {
+ const a = "link";
+ const b = "link";
+ comptime try expect(TypeWithCompTimeSlice(a).Node == TypeWithCompTimeSlice(b).Node);
+ comptime try expect(TypeWithCompTimeSlice("link").Node == TypeWithCompTimeSlice("link").Node);
+}
+
+test "comptime slice of undefined pointer of length 0" {
+ const slice1 = @as([*]i32, undefined)[0..0];
+ try expect(slice1.len == 0);
+ const slice2 = @as([*]i32, undefined)[100..100];
+ try expect(slice2.len == 0);
+}
+
+fn copyWithPartialInline(s: []u32, b: []u8) void {
+ comptime var i: usize = 0;
+ inline while (i < 4) : (i += 1) {
+ s[i] = 0;
+ s[i] |= @as(u32, b[i * 4 + 0]) << 24;
+ s[i] |= @as(u32, b[i * 4 + 1]) << 16;
+ s[i] |= @as(u32, b[i * 4 + 2]) << 8;
+ s[i] |= @as(u32, b[i * 4 + 3]) << 0;
+ }
+}
+
+test "binary math operator in partially inlined function" {
+ var s: [4]u32 = undefined;
+ var b: [16]u8 = undefined;
+
+ for (b) |*r, i|
+ r.* = @intCast(u8, i + 1);
+
+ copyWithPartialInline(s[0..], b[0..]);
+ try expect(s[0] == 0x1020304);
+ try expect(s[1] == 0x5060708);
+ try expect(s[2] == 0x90a0b0c);
+ try expect(s[3] == 0xd0e0f10);
+}
+
+test "comptime function with the same args is memoized" {
+ comptime {
+ try expect(MakeType(i32) == MakeType(i32));
+ try expect(MakeType(i32) != MakeType(f64));
+ }
+}
+
+fn MakeType(comptime T: type) type {
+ return struct {
+ field: T,
+ };
+}
+
+test "comptime function with mutable pointer is not memoized" {
+ comptime {
+ var x: i32 = 1;
+ const ptr = &x;
+ increment(ptr);
+ increment(ptr);
+ try expect(x == 3);
+ }
+}
+
+fn increment(value: *i32) void {
+ value.* += 1;
+}
+
+fn generateTable(comptime T: type) [1010]T {
+ var res: [1010]T = undefined;
+ var i: usize = 0;
+ while (i < 1010) : (i += 1) {
+ res[i] = @intCast(T, i);
+ }
+ return res;
+}
+
+fn doesAlotT(comptime T: type, value: usize) T {
+ @setEvalBranchQuota(5000);
+ const table = comptime blk: {
+ break :blk generateTable(T);
+ };
+ return table[value];
+}
+
+test "@setEvalBranchQuota at same scope as generic function call" {
+ try expect(doesAlotT(u32, 2) == 2);
+}
+
+test "comptime slice of slice preserves comptime var" {
+ comptime {
+ var buff: [10]u8 = undefined;
+ buff[0..][0..][0] = 1;
+ try expect(buff[0..][0..][0] == 1);
+ }
+}
+
+test "comptime slice of pointer preserves comptime var" {
+ comptime {
+ var buff: [10]u8 = undefined;
+ var a = @ptrCast([*]u8, &buff);
+ a[0..1][0] = 1;
+ try expect(buff[0..][0..][0] == 1);
+ }
+}
+
+const SingleFieldStruct = struct {
+ x: i32,
+
+ fn read_x(self: *const SingleFieldStruct) i32 {
+ return self.x;
+ }
+};
+test "const ptr to comptime mutable data is not memoized" {
+ comptime {
+ var foo = SingleFieldStruct{ .x = 1 };
+ try expect(foo.read_x() == 1);
+ foo.x = 2;
+ try expect(foo.read_x() == 2);
+ }
+}
+
+test "array concat of slices gives slice" {
+ comptime {
+ var a: []const u8 = "aoeu";
+ var b: []const u8 = "asdf";
+ const c = a ++ b;
+ try expect(std.mem.eql(u8, c, "aoeuasdf"));
+ }
+}
+
+test "comptime shlWithOverflow" {
+ const ct_shifted: u64 = comptime amt: {
+ var amt = @as(u64, 0);
+ _ = @shlWithOverflow(u64, ~@as(u64, 0), 16, &amt);
+ break :amt amt;
+ };
+
+ const rt_shifted: u64 = amt: {
+ var amt = @as(u64, 0);
+ _ = @shlWithOverflow(u64, ~@as(u64, 0), 16, &amt);
+ break :amt amt;
+ };
+
+ try expect(ct_shifted == rt_shifted);
+}
+
+test "comptime shl" {
+ var a: u128 = 3;
+ var b: u7 = 63;
+ var c: u128 = 3 << 63;
+ try expectEqual(a << b, c);
+}
+
+test "runtime 128 bit integer division" {
+ var a: u128 = 152313999999999991610955792383;
+ var b: u128 = 10000000000000000000;
+ var c = a / b;
+ try expect(c == 15231399999);
+}
+
+pub const Info = struct {
+ version: u8,
+};
+
+pub const diamond_info = Info{ .version = 0 };
+
+test "comptime modification of const struct field" {
+ comptime {
+ var res = diamond_info;
+ res.version = 1;
+ try expect(diamond_info.version == 0);
+ try expect(res.version == 1);
+ }
+}
+
+test "slice of type" {
+ comptime {
+ var types_array = [_]type{ i32, f64, type };
+ for (types_array) |T, i| {
+ switch (i) {
+ 0 => try expect(T == i32),
+ 1 => try expect(T == f64),
+ 2 => try expect(T == type),
+ else => unreachable,
+ }
+ }
+ for (types_array[0..]) |T, i| {
+ switch (i) {
+ 0 => try expect(T == i32),
+ 1 => try expect(T == f64),
+ 2 => try expect(T == type),
+ else => unreachable,
+ }
+ }
+ }
+}
+
+const Wrapper = struct {
+ T: type,
+};
+
+fn wrap(comptime T: type) Wrapper {
+ return Wrapper{ .T = T };
+}
+
+test "function which returns struct with type field causes implicit comptime" {
+ const ty = wrap(i32).T;
+ try expect(ty == i32);
+}
+
+test "call method with comptime pass-by-non-copying-value self parameter" {
+ const S = struct {
+ a: u8,
+
+ fn b(comptime s: @This()) u8 {
+ return s.a;
+ }
+ };
+
+ const s = S{ .a = 2 };
+ var b = s.b();
+ try expect(b == 2);
+}
+
+test "@tagName of @typeInfo" {
+ const str = @tagName(@typeInfo(u8));
+ try expect(std.mem.eql(u8, str, "Int"));
+}
+
+test "setting backward branch quota just before a generic fn call" {
+ @setEvalBranchQuota(1001);
+ loopNTimes(1001);
+}
+
+fn loopNTimes(comptime n: usize) void {
+ comptime var i = 0;
+ inline while (i < n) : (i += 1) {}
+}
+
+test "variable inside inline loop that has different types on different iterations" {
+ try testVarInsideInlineLoop(.{ true, @as(u32, 42) });
+}
+
+fn testVarInsideInlineLoop(args: anytype) !void {
+ comptime var i = 0;
+ inline while (i < args.len) : (i += 1) {
+ const x = args[i];
+ if (i == 0) try expect(x);
+ if (i == 1) try expect(x == 42);
+ }
+}
+
+test "inline for with same type but different values" {
+ var res: usize = 0;
+ inline for ([_]type{ [2]u8, [1]u8, [2]u8 }) |T| {
+ var a: T = undefined;
+ res += a.len;
+ }
+ try expect(res == 5);
+}
+
+test "refer to the type of a generic function" {
+ const Func = fn (type) void;
+ const f: Func = doNothingWithType;
+ f(i32);
+}
+
+fn doNothingWithType(comptime T: type) void {
+ _ = T;
+}
+
+test "zero extend from u0 to u1" {
+ var zero_u0: u0 = 0;
+ var zero_u1: u1 = zero_u0;
+ try expect(zero_u1 == 0);
+}
+
+test "bit shift a u1" {
+ var x: u1 = 1;
+ var y = x << 0;
+ try expect(y == 1);
+}
+
+test "comptime pointer cast array and then slice" {
+ const array = [_]u8{ 1, 2, 3, 4, 5, 6, 7, 8 };
+
+ const ptrA: [*]const u8 = @ptrCast([*]const u8, &array);
+ const sliceA: []const u8 = ptrA[0..2];
+
+ const ptrB: [*]const u8 = &array;
+ const sliceB: []const u8 = ptrB[0..2];
+
+ try expect(sliceA[1] == 2);
+ try expect(sliceB[1] == 2);
+}
+
+test "slice bounds in comptime concatenation" {
+ const bs = comptime blk: {
+ const b = "........1........";
+ break :blk b[8..9];
+ };
+ const str = "" ++ bs;
+ try expect(str.len == 1);
+ try expect(std.mem.eql(u8, str, "1"));
+
+ const str2 = bs ++ "";
+ try expect(str2.len == 1);
+ try expect(std.mem.eql(u8, str2, "1"));
+}
+
+test "comptime bitwise operators" {
+ comptime {
+ try expect(3 & 1 == 1);
+ try expect(3 & -1 == 3);
+ try expect(-3 & -1 == -3);
+ try expect(3 | -1 == -1);
+ try expect(-3 | -1 == -1);
+ try expect(3 ^ -1 == -4);
+ try expect(-3 ^ -1 == 2);
+ try expect(~@as(i8, -1) == 0);
+ try expect(~@as(i128, -1) == 0);
+ try expect(18446744073709551615 & 18446744073709551611 == 18446744073709551611);
+ try expect(-18446744073709551615 & -18446744073709551611 == -18446744073709551615);
+ try expect(~@as(u128, 0) == 0xffffffffffffffffffffffffffffffff);
+ }
+}
+
+test "*align(1) u16 is the same as *align(1:0:2) u16" {
+ comptime {
+ try expect(*align(1:0:2) u16 == *align(1) u16);
+ try expect(*align(2:0:2) u16 == *u16);
+ }
+}
+
+test "array concatenation forces comptime" {
+ var a = oneItem(3) ++ oneItem(4);
+ try expect(std.mem.eql(i32, &a, &[_]i32{ 3, 4 }));
+}
+
+test "array multiplication forces comptime" {
+ var a = oneItem(3) ** scalar(2);
+ try expect(std.mem.eql(i32, &a, &[_]i32{ 3, 3 }));
+}
+
+fn oneItem(x: i32) [1]i32 {
+ return [_]i32{x};
+}
+
+fn scalar(x: u32) u32 {
+ return x;
+}
+
+test "comptime assign int to optional int" {
+ comptime {
+ var x: ?i32 = null;
+ x = 2;
+ x.? *= 10;
+ try expectEqual(20, x.?);
+ }
+}
+
+test "return 0 from function that has u0 return type" {
+ const S = struct {
+ fn foo_zero() u0 {
+ return 0;
+ }
+ };
+ comptime {
+ if (S.foo_zero() != 0) {
+ @compileError("test failed");
+ }
+ }
+}
+
+test "two comptime calls with array default initialized to undefined" {
+ const S = struct {
+ const CrossTarget = struct {
+ dynamic_linker: DynamicLinker = DynamicLinker{},
+
+ pub fn parse() void {
+ var result: CrossTarget = .{};
+ result.getCpuArch();
+ }
+
+ pub fn getCpuArch(self: CrossTarget) void {
+ _ = self;
+ }
+ };
+
+ const DynamicLinker = struct {
+ buffer: [255]u8 = undefined,
+ };
+ };
+
+ comptime {
+ S.CrossTarget.parse();
+ S.CrossTarget.parse();
+ }
+}
diff --git a/test/behavior/generics.zig b/test/behavior/generics.zig
index 104752607a..67fb1def8b 100644
--- a/test/behavior/generics.zig
+++ b/test/behavior/generics.zig
@@ -1,11 +1,29 @@
const std = @import("std");
+const builtin = @import("builtin");
const testing = std.testing;
const expect = testing.expect;
const expectEqual = testing.expectEqual;
+test "one param, explicit comptime" {
+ var x: usize = 0;
+ x += checkSize(i32);
+ x += checkSize(bool);
+ x += checkSize(bool);
+ try expect(x == 6);
+}
+
+fn checkSize(comptime T: type) usize {
+ return @sizeOf(T);
+}
+
test "simple generic fn" {
try expect(max(i32, 3, -1) == 3);
- try expect(max(f32, 0.123, 0.456) == 0.456);
+ try expect(max(u8, 1, 100) == 100);
+ if (!builtin.zig_is_stage2) {
+ // TODO: stage2 is incorrectly emitting the following:
+ // error: cast of value 1.23e-01 to type 'f32' loses information
+ try expect(max(f32, 0.123, 0.456) == 0.456);
+ }
try expect(add(2, 3) == 5);
}
@@ -40,130 +58,23 @@ test "fn with comptime args" {
try expect(sameButWithFloats(0.43, 0.49) == 0.49);
}
-test "var params" {
+test "anytype params" {
try expect(max_i32(12, 34) == 34);
try expect(max_f64(1.2, 3.4) == 3.4);
+ comptime {
+ try expect(max_i32(12, 34) == 34);
+ try expect(max_f64(1.2, 3.4) == 3.4);
+ }
}
-test {
- comptime try expect(max_i32(12, 34) == 34);
- comptime try expect(max_f64(1.2, 3.4) == 3.4);
-}
-
-fn max_var(a: anytype, b: anytype) @TypeOf(a + b) {
+fn max_anytype(a: anytype, b: anytype) @TypeOf(a, b) {
return if (a > b) a else b;
}
fn max_i32(a: i32, b: i32) i32 {
- return max_var(a, b);
+ return max_anytype(a, b);
}
fn max_f64(a: f64, b: f64) f64 {
- return max_var(a, b);
-}
-
-pub fn List(comptime T: type) type {
- return SmallList(T, 8);
-}
-
-pub fn SmallList(comptime T: type, comptime STATIC_SIZE: usize) type {
- return struct {
- items: []T,
- length: usize,
- prealloc_items: [STATIC_SIZE]T,
- };
-}
-
-test "function with return type type" {
- var list: List(i32) = undefined;
- var list2: List(i32) = undefined;
- list.length = 10;
- list2.length = 10;
- try expect(list.prealloc_items.len == 8);
- try expect(list2.prealloc_items.len == 8);
-}
-
-test "generic struct" {
- var a1 = GenNode(i32){
- .value = 13,
- .next = null,
- };
- var b1 = GenNode(bool){
- .value = true,
- .next = null,
- };
- try expect(a1.value == 13);
- try expect(a1.value == a1.getVal());
- try expect(b1.getVal());
-}
-fn GenNode(comptime T: type) type {
- return struct {
- value: T,
- next: ?*GenNode(T),
- fn getVal(n: *const GenNode(T)) T {
- return n.value;
- }
- };
-}
-
-test "const decls in struct" {
- try expect(GenericDataThing(3).count_plus_one == 4);
-}
-fn GenericDataThing(comptime count: isize) type {
- return struct {
- const count_plus_one = count + 1;
- };
-}
-
-test "use generic param in generic param" {
- try expect(aGenericFn(i32, 3, 4) == 7);
-}
-fn aGenericFn(comptime T: type, comptime a: T, b: T) T {
- return a + b;
-}
-
-test "generic fn with implicit cast" {
- try expect(getFirstByte(u8, &[_]u8{13}) == 13);
- try expect(getFirstByte(u16, &[_]u16{
- 0,
- 13,
- }) == 0);
-}
-fn getByte(ptr: ?*const u8) u8 {
- return ptr.?.*;
-}
-fn getFirstByte(comptime T: type, mem: []const T) u8 {
- return getByte(@ptrCast(*const u8, &mem[0]));
-}
-
-const foos = [_]fn (anytype) bool{
- foo1,
- foo2,
-};
-
-fn foo1(arg: anytype) bool {
- return arg;
-}
-fn foo2(arg: anytype) bool {
- return !arg;
-}
-
-test "array of generic fns" {
- try expect(foos[0](true));
- try expect(!foos[1](true));
-}
-
-test "generic fn keeps non-generic parameter types" {
- const A = 128;
-
- const S = struct {
- fn f(comptime T: type, s: []T) !void {
- try expect(A != @typeInfo(@TypeOf(s)).Pointer.alignment);
- }
- };
-
- // The compiler monomorphizes `S.f` for `T=u8` on its first use, check that
- // `x` type not affect `s` parameter type.
- var x: [16]u8 align(A) = undefined;
- try S.f(u8, &x);
+ return max_anytype(a, b);
}
diff --git a/test/behavior/generics_stage1.zig b/test/behavior/generics_stage1.zig
new file mode 100644
index 0000000000..4b768a5b4f
--- /dev/null
+++ b/test/behavior/generics_stage1.zig
@@ -0,0 +1,110 @@
+const std = @import("std");
+const testing = std.testing;
+const expect = testing.expect;
+const expectEqual = testing.expectEqual;
+
+pub fn List(comptime T: type) type {
+ return SmallList(T, 8);
+}
+
+pub fn SmallList(comptime T: type, comptime STATIC_SIZE: usize) type {
+ return struct {
+ items: []T,
+ length: usize,
+ prealloc_items: [STATIC_SIZE]T,
+ };
+}
+
+test "function with return type type" {
+ var list: List(i32) = undefined;
+ var list2: List(i32) = undefined;
+ list.length = 10;
+ list2.length = 10;
+ try expect(list.prealloc_items.len == 8);
+ try expect(list2.prealloc_items.len == 8);
+}
+
+test "generic struct" {
+ var a1 = GenNode(i32){
+ .value = 13,
+ .next = null,
+ };
+ var b1 = GenNode(bool){
+ .value = true,
+ .next = null,
+ };
+ try expect(a1.value == 13);
+ try expect(a1.value == a1.getVal());
+ try expect(b1.getVal());
+}
+fn GenNode(comptime T: type) type {
+ return struct {
+ value: T,
+ next: ?*GenNode(T),
+ fn getVal(n: *const GenNode(T)) T {
+ return n.value;
+ }
+ };
+}
+
+test "const decls in struct" {
+ try expect(GenericDataThing(3).count_plus_one == 4);
+}
+fn GenericDataThing(comptime count: isize) type {
+ return struct {
+ const count_plus_one = count + 1;
+ };
+}
+
+test "use generic param in generic param" {
+ try expect(aGenericFn(i32, 3, 4) == 7);
+}
+fn aGenericFn(comptime T: type, comptime a: T, b: T) T {
+ return a + b;
+}
+
+test "generic fn with implicit cast" {
+ try expect(getFirstByte(u8, &[_]u8{13}) == 13);
+ try expect(getFirstByte(u16, &[_]u16{
+ 0,
+ 13,
+ }) == 0);
+}
+fn getByte(ptr: ?*const u8) u8 {
+ return ptr.?.*;
+}
+fn getFirstByte(comptime T: type, mem: []const T) u8 {
+ return getByte(@ptrCast(*const u8, &mem[0]));
+}
+
+const foos = [_]fn (anytype) bool{
+ foo1,
+ foo2,
+};
+
+fn foo1(arg: anytype) bool {
+ return arg;
+}
+fn foo2(arg: anytype) bool {
+ return !arg;
+}
+
+test "array of generic fns" {
+ try expect(foos[0](true));
+ try expect(!foos[1](true));
+}
+
+test "generic fn keeps non-generic parameter types" {
+ const A = 128;
+
+ const S = struct {
+ fn f(comptime T: type, s: []T) !void {
+ try expect(A != @typeInfo(@TypeOf(s)).Pointer.alignment);
+ }
+ };
+
+ // The compiler monomorphizes `S.f` for `T=u8` on its first use, check that
+ // `x` type not affect `s` parameter type.
+ var x: [16]u8 align(A) = undefined;
+ try S.f(u8, &x);
+}
diff --git a/test/behavior/if.zig b/test/behavior/if.zig
index e8c84f4570..191d4817df 100644
--- a/test/behavior/if.zig
+++ b/test/behavior/if.zig
@@ -65,45 +65,3 @@ test "labeled break inside comptime if inside runtime if" {
}
try expect(answer == 42);
}
-
-test "const result loc, runtime if cond, else unreachable" {
- const Num = enum {
- One,
- Two,
- };
-
- var t = true;
- const x = if (t) Num.Two else unreachable;
- try expect(x == .Two);
-}
-
-test "if prongs cast to expected type instead of peer type resolution" {
- const S = struct {
- fn doTheTest(f: bool) !void {
- var x: i32 = 0;
- x = if (f) 1 else 2;
- try expect(x == 2);
-
- var b = true;
- const y: i32 = if (b) 1 else 2;
- try expect(y == 1);
- }
- };
- try S.doTheTest(false);
- comptime try S.doTheTest(false);
-}
-
-test "while copies its payload" {
- const S = struct {
- fn doTheTest() !void {
- var tmp: ?i32 = 10;
- if (tmp) |value| {
- // Modify the original variable
- tmp = null;
- try expectEqual(@as(i32, 10), value);
- } else unreachable;
- }
- };
- try S.doTheTest();
- comptime try S.doTheTest();
-}
diff --git a/test/behavior/if_stage1.zig b/test/behavior/if_stage1.zig
new file mode 100644
index 0000000000..36500fbaee
--- /dev/null
+++ b/test/behavior/if_stage1.zig
@@ -0,0 +1,45 @@
+const std = @import("std");
+const expect = std.testing.expect;
+const expectEqual = std.testing.expectEqual;
+
+test "const result loc, runtime if cond, else unreachable" {
+ const Num = enum {
+ One,
+ Two,
+ };
+
+ var t = true;
+ const x = if (t) Num.Two else unreachable;
+ try expect(x == .Two);
+}
+
+test "if prongs cast to expected type instead of peer type resolution" {
+ const S = struct {
+ fn doTheTest(f: bool) !void {
+ var x: i32 = 0;
+ x = if (f) 1 else 2;
+ try expect(x == 2);
+
+ var b = true;
+ const y: i32 = if (b) 1 else 2;
+ try expect(y == 1);
+ }
+ };
+ try S.doTheTest(false);
+ comptime try S.doTheTest(false);
+}
+
+test "while copies its payload" {
+ const S = struct {
+ fn doTheTest() !void {
+ var tmp: ?i32 = 10;
+ if (tmp) |value| {
+ // Modify the original variable
+ tmp = null;
+ try expectEqual(@as(i32, 10), value);
+ } else unreachable;
+ }
+ };
+ try S.doTheTest();
+ comptime try S.doTheTest();
+}
diff --git a/test/behavior/maximum_minimum.zig b/test/behavior/maximum_minimum.zig
new file mode 100644
index 0000000000..5fef818f2b
--- /dev/null
+++ b/test/behavior/maximum_minimum.zig
@@ -0,0 +1,58 @@
+const std = @import("std");
+const builtin = @import("builtin");
+const mem = std.mem;
+const expect = std.testing.expect;
+const expectEqual = std.testing.expectEqual;
+const Vector = std.meta.Vector;
+
+test "@maximum" {
+ const S = struct {
+ fn doTheTest() !void {
+ try expectEqual(@as(i32, 10), @maximum(@as(i32, -3), @as(i32, 10)));
+ try expectEqual(@as(f32, 3.2), @maximum(@as(f32, 3.2), @as(f32, 0.68)));
+
+ var a: Vector(4, i32) = [4]i32{ 2147483647, -2, 30, 40 };
+ var b: Vector(4, i32) = [4]i32{ 1, 2147483647, 3, 4 };
+ var x = @maximum(a, b);
+ try expect(mem.eql(i32, &@as([4]i32, x), &[4]i32{ 2147483647, 2147483647, 30, 40 }));
+
+ var c: Vector(4, f32) = [4]f32{ 0, 0.4, -2.4, 7.8 };
+ var d: Vector(4, f32) = [4]f32{ -0.23, 0.42, -0.64, 0.9 };
+ var y = @maximum(c, d);
+ try expect(mem.eql(f32, &@as([4]f32, y), &[4]f32{ 0, 0.42, -0.64, 7.8 }));
+
+ var e: Vector(2, f32) = [2]f32{ 0, std.math.qnan_f32 };
+ var f: Vector(2, f32) = [2]f32{ std.math.qnan_f32, 0 };
+ var z = @maximum(e, f);
+ try expect(mem.eql(f32, &@as([2]f32, z), &[2]f32{ 0, 0 }));
+ }
+ };
+ try S.doTheTest();
+ comptime try S.doTheTest();
+}
+
+test "@minimum" {
+ const S = struct {
+ fn doTheTest() !void {
+ try expectEqual(@as(i32, -3), @minimum(@as(i32, -3), @as(i32, 10)));
+ try expectEqual(@as(f32, 0.68), @minimum(@as(f32, 3.2), @as(f32, 0.68)));
+
+ var a: Vector(4, i32) = [4]i32{ 2147483647, -2, 30, 40 };
+ var b: Vector(4, i32) = [4]i32{ 1, 2147483647, 3, 4 };
+ var x = @minimum(a, b);
+ try expect(mem.eql(i32, &@as([4]i32, x), &[4]i32{ 1, -2, 3, 4 }));
+
+ var c: Vector(4, f32) = [4]f32{ 0, 0.4, -2.4, 7.8 };
+ var d: Vector(4, f32) = [4]f32{ -0.23, 0.42, -0.64, 0.9 };
+ var y = @minimum(c, d);
+ try expect(mem.eql(f32, &@as([4]f32, y), &[4]f32{ -0.23, 0.4, -2.4, 0.9 }));
+
+ var e: Vector(2, f32) = [2]f32{ 0, std.math.qnan_f32 };
+ var f: Vector(2, f32) = [2]f32{ std.math.qnan_f32, 0 };
+ var z = @maximum(e, f);
+ try expect(mem.eql(f32, &@as([2]f32, z), &[2]f32{ 0, 0 }));
+ }
+ };
+ try S.doTheTest();
+ comptime try S.doTheTest();
+}
diff --git a/test/behavior/misc.zig b/test/behavior/misc.zig
index 6fabbf487b..466be00bd3 100644
--- a/test/behavior/misc.zig
+++ b/test/behavior/misc.zig
@@ -5,94 +5,6 @@ const expectEqualStrings = std.testing.expectEqualStrings;
const mem = std.mem;
const builtin = @import("builtin");
-// normal comment
-
-/// this is a documentation comment
-/// doc comment line 2
-fn emptyFunctionWithComments() void {}
-
-test "empty function with comments" {
- emptyFunctionWithComments();
-}
-
-comptime {
- @export(disabledExternFn, .{ .name = "disabledExternFn", .linkage = .Internal });
-}
-
-fn disabledExternFn() callconv(.C) void {}
-
-test "call disabled extern fn" {
- disabledExternFn();
-}
-
-test "short circuit" {
- try testShortCircuit(false, true);
- comptime try testShortCircuit(false, true);
-}
-
-fn testShortCircuit(f: bool, t: bool) !void {
- var hit_1 = f;
- var hit_2 = f;
- var hit_3 = f;
- var hit_4 = f;
-
- if (t or x: {
- try expect(f);
- break :x f;
- }) {
- hit_1 = t;
- }
- if (f or x: {
- hit_2 = t;
- break :x f;
- }) {
- try expect(f);
- }
-
- if (t and x: {
- hit_3 = t;
- break :x f;
- }) {
- try expect(f);
- }
- if (f and x: {
- try expect(f);
- break :x f;
- }) {
- try expect(f);
- } else {
- hit_4 = t;
- }
- try expect(hit_1);
- try expect(hit_2);
- try expect(hit_3);
- try expect(hit_4);
-}
-
-test "truncate" {
- try expect(testTruncate(0x10fd) == 0xfd);
-}
-fn testTruncate(x: u32) u8 {
- return @truncate(u8, x);
-}
-
-fn first4KeysOfHomeRow() []const u8 {
- return "aoeu";
-}
-
-test "return string from function" {
- try expect(mem.eql(u8, first4KeysOfHomeRow(), "aoeu"));
-}
-
-const g1: i32 = 1233 + 1;
-var g2: i32 = 0;
-
-test "global variables" {
- try expect(g2 == 0);
- g2 = g1;
- try expect(g2 == 1234);
-}
-
test "memcpy and memset intrinsics" {
var foo: [20]u8 = undefined;
var bar: [20]u8 = undefined;
@@ -103,13 +15,6 @@ test "memcpy and memset intrinsics" {
if (bar[11] != 'A') unreachable;
}
-test "builtin static eval" {
- const x: i32 = comptime x: {
- break :x 1 + 2 + 3;
- };
- try expect(x == comptime 6);
-}
-
test "slicing" {
var array: [20]i32 = undefined;
@@ -135,10 +40,6 @@ test "constant equal function pointers" {
fn emptyFn() void {}
-test "hex escape" {
- try expect(mem.eql(u8, "\x68\x65\x6c\x6c\x6f", "hello"));
-}
-
test "string concatenation" {
try expect(mem.eql(u8, "OK" ++ " IT " ++ "WORKED", "OK IT WORKED"));
}
@@ -157,59 +58,7 @@ test "string escapes" {
try expectEqualStrings("\u{1234}\u{069}\u{1}", "\xe1\x88\xb4\x69\x01");
}
-test "multiline string" {
- const s1 =
- \\one
- \\two)
- \\three
- ;
- const s2 = "one\ntwo)\nthree";
- try expect(mem.eql(u8, s1, s2));
-}
-
-test "multiline string comments at start" {
- const s1 =
- //\\one
- \\two)
- \\three
- ;
- const s2 = "two)\nthree";
- try expect(mem.eql(u8, s1, s2));
-}
-
-test "multiline string comments at end" {
- const s1 =
- \\one
- \\two)
- //\\three
- ;
- const s2 = "one\ntwo)";
- try expect(mem.eql(u8, s1, s2));
-}
-
-test "multiline string comments in middle" {
- const s1 =
- \\one
- //\\two)
- \\three
- ;
- const s2 = "one\nthree";
- try expect(mem.eql(u8, s1, s2));
-}
-
-test "multiline string comments at multiple places" {
- const s1 =
- \\one
- //\\two
- \\three
- //\\four
- \\five
- ;
- const s2 = "one\nthree\nfive";
- try expect(mem.eql(u8, s1, s2));
-}
-
-test "multiline C string" {
+test "multiline string literal is null terminated" {
const s1 =
\\one
\\two)
@@ -219,10 +68,6 @@ test "multiline C string" {
try expect(std.cstr.cmp(s1, s2) == 0);
}
-test "type equality" {
- try expect(*const u8 != *u8);
-}
-
const global_a: i32 = 1234;
const global_b: *const i32 = &global_a;
const global_c: *const f32 = @ptrCast(*const f32, global_b);
@@ -258,17 +103,6 @@ fn testCastUndefined(x: []const u8) void {
_ = x;
}
-test "cast small unsigned to larger signed" {
- try expect(castSmallUnsignedToLargerSigned1(200) == @as(i16, 200));
- try expect(castSmallUnsignedToLargerSigned2(9999) == @as(i64, 9999));
-}
-fn castSmallUnsignedToLargerSigned1(x: u8) i16 {
- return x;
-}
-fn castSmallUnsignedToLargerSigned2(x: u16) i64 {
- return x;
-}
-
test "implicit cast after unreachable" {
try expect(outer() == 1234);
}
@@ -279,37 +113,6 @@ fn outer() i64 {
return inner();
}
-test "pointer dereferencing" {
- var x = @as(i32, 3);
- const y = &x;
-
- y.* += 1;
-
- try expect(x == 4);
- try expect(y.* == 4);
-}
-
-test "call result of if else expression" {
- try expect(mem.eql(u8, f2(true), "a"));
- try expect(mem.eql(u8, f2(false), "b"));
-}
-fn f2(x: bool) []const u8 {
- return (if (x) fA else fB)();
-}
-fn fA() []const u8 {
- return "a";
-}
-fn fB() []const u8 {
- return "b";
-}
-
-test "const expression eval handling of variables" {
- var x = true;
- while (x) {
- x = false;
- }
-}
-
test "constant enum initialization with differing sizes" {
try test3_1(test3_foo);
try test3_2(test3_bar);
@@ -348,11 +151,6 @@ fn test3_2(f: Test3Foo) !void {
}
}
-test "character literals" {
- try expect('\'' == single_quote);
-}
-const single_quote = '\'';
-
test "take address of parameter" {
try testTakeAddressOfParameter(12.34);
}
@@ -401,11 +199,6 @@ fn testPointerToVoidReturnType2() *const void {
return &test_pointer_to_void_return_type_x;
}
-test "non const ptr to aliased type" {
- const int = i32;
- try expect(?*int == ?*i32);
-}
-
test "array 2D const double ptr" {
const rect_2d_vertexes = [_][1]f32{
[_]f32{1.0},
@@ -420,46 +213,6 @@ fn testArray2DConstDoublePtr(ptr: *const f32) !void {
try expect(ptr2[1] == 2.0);
}
-const AStruct = struct {
- x: i32,
-};
-const AnEnum = enum {
- One,
- Two,
-};
-const AUnionEnum = union(enum) {
- One: i32,
- Two: void,
-};
-const AUnion = union {
- One: void,
- Two: void,
-};
-
-test "@typeName" {
- const Struct = struct {};
- const Union = union {
- unused: u8,
- };
- const Enum = enum {
- Unused,
- };
- comptime {
- try expect(mem.eql(u8, @typeName(i64), "i64"));
- try expect(mem.eql(u8, @typeName(*usize), "*usize"));
- // https://github.com/ziglang/zig/issues/675
- try expect(mem.eql(u8, "behavior.misc.TypeFromFn(u8)", @typeName(TypeFromFn(u8))));
- try expect(mem.eql(u8, @typeName(Struct), "Struct"));
- try expect(mem.eql(u8, @typeName(Union), "Union"));
- try expect(mem.eql(u8, @typeName(Enum), "Enum"));
- }
-}
-
-fn TypeFromFn(comptime T: type) type {
- _ = T;
- return struct {};
-}
-
test "double implicit cast in same expression" {
var x = @as(i32, @as(u16, nine()));
try expect(x == 9);
@@ -535,15 +288,6 @@ test "function closes over local const" {
try expect(x == 1);
}
-test "cold function" {
- thisIsAColdFn();
- comptime thisIsAColdFn();
-}
-
-fn thisIsAColdFn() void {
- @setCold(true);
-}
-
const PackedStruct = packed struct {
a: u8,
b: u8,
@@ -657,15 +401,6 @@ test "thread local variable" {
try expect(S.t == 1235);
}
-test "unicode escape in character literal" {
- var a: u24 = '\u{01f4a9}';
- try expect(a == 128169);
-}
-
-test "unicode character in character literal" {
- try expect('💩' == 128169);
-}
-
test "result location zero sized array inside struct field implicit cast to slice" {
const E = struct {
entries: []u32,
diff --git a/test/behavior/pointers.zig b/test/behavior/pointers.zig
index bb95d3c219..4fcd78b1d6 100644
--- a/test/behavior/pointers.zig
+++ b/test/behavior/pointers.zig
@@ -15,22 +15,6 @@ fn testDerefPtr() !void {
try expect(x == 1235);
}
-const Foo1 = struct {
- x: void,
-};
-
-test "dereference pointer again" {
- try testDerefPtrOneVal();
- comptime try testDerefPtrOneVal();
-}
-
-fn testDerefPtrOneVal() !void {
- // Foo1 satisfies the OnePossibleValueYes criteria
- const x = &Foo1{ .x = {} };
- const y = x.*;
- try expect(@TypeOf(y.x) == void);
-}
-
test "pointer arithmetic" {
var ptr: [*]const u8 = "abcd";
@@ -60,288 +44,3 @@ test "double pointer parsing" {
fn PtrOf(comptime T: type) type {
return *T;
}
-
-test "assigning integer to C pointer" {
- var x: i32 = 0;
- var ptr: [*c]u8 = 0;
- var ptr2: [*c]u8 = x;
- if (false) {
- ptr;
- ptr2;
- }
-}
-
-test "implicit cast single item pointer to C pointer and back" {
- var y: u8 = 11;
- var x: [*c]u8 = &y;
- var z: *u8 = x;
- z.* += 1;
- try expect(y == 12);
-}
-
-test "C pointer comparison and arithmetic" {
- const S = struct {
- fn doTheTest() !void {
- var ptr1: [*c]u32 = 0;
- var ptr2 = ptr1 + 10;
- try expect(ptr1 == 0);
- try expect(ptr1 >= 0);
- try expect(ptr1 <= 0);
- // expect(ptr1 < 1);
- // expect(ptr1 < one);
- // expect(1 > ptr1);
- // expect(one > ptr1);
- try expect(ptr1 < ptr2);
- try expect(ptr2 > ptr1);
- try expect(ptr2 >= 40);
- try expect(ptr2 == 40);
- try expect(ptr2 <= 40);
- ptr2 -= 10;
- try expect(ptr1 == ptr2);
- }
- };
- try S.doTheTest();
- comptime try S.doTheTest();
-}
-
-test "peer type resolution with C pointers" {
- var ptr_one: *u8 = undefined;
- var ptr_many: [*]u8 = undefined;
- var ptr_c: [*c]u8 = undefined;
- var t = true;
- var x1 = if (t) ptr_one else ptr_c;
- var x2 = if (t) ptr_many else ptr_c;
- var x3 = if (t) ptr_c else ptr_one;
- var x4 = if (t) ptr_c else ptr_many;
- try expect(@TypeOf(x1) == [*c]u8);
- try expect(@TypeOf(x2) == [*c]u8);
- try expect(@TypeOf(x3) == [*c]u8);
- try expect(@TypeOf(x4) == [*c]u8);
-}
-
-test "implicit casting between C pointer and optional non-C pointer" {
- var slice: []const u8 = "aoeu";
- const opt_many_ptr: ?[*]const u8 = slice.ptr;
- var ptr_opt_many_ptr = &opt_many_ptr;
- var c_ptr: [*c]const [*c]const u8 = ptr_opt_many_ptr;
- try expect(c_ptr.*.* == 'a');
- ptr_opt_many_ptr = c_ptr;
- try expect(ptr_opt_many_ptr.*.?[1] == 'o');
-}
-
-test "implicit cast error unions with non-optional to optional pointer" {
- const S = struct {
- fn doTheTest() !void {
- try expectError(error.Fail, foo());
- }
- fn foo() anyerror!?*u8 {
- return bar() orelse error.Fail;
- }
- fn bar() ?*u8 {
- return null;
- }
- };
- try S.doTheTest();
- comptime try S.doTheTest();
-}
-
-test "initialize const optional C pointer to null" {
- const a: ?[*c]i32 = null;
- try expect(a == null);
- comptime try expect(a == null);
-}
-
-test "compare equality of optional and non-optional pointer" {
- const a = @intToPtr(*const usize, 0x12345678);
- const b = @intToPtr(?*usize, 0x12345678);
- try expect(a == b);
- try expect(b == a);
-}
-
-test "allowzero pointer and slice" {
- var ptr = @intToPtr([*]allowzero i32, 0);
- var opt_ptr: ?[*]allowzero i32 = ptr;
- try expect(opt_ptr != null);
- try expect(@ptrToInt(ptr) == 0);
- var runtime_zero: usize = 0;
- var slice = ptr[runtime_zero..10];
- comptime try expect(@TypeOf(slice) == []allowzero i32);
- try expect(@ptrToInt(&slice[5]) == 20);
-
- comptime try expect(@typeInfo(@TypeOf(ptr)).Pointer.is_allowzero);
- comptime try expect(@typeInfo(@TypeOf(slice)).Pointer.is_allowzero);
-}
-
-test "assign null directly to C pointer and test null equality" {
- var x: [*c]i32 = null;
- try expect(x == null);
- try expect(null == x);
- try expect(!(x != null));
- try expect(!(null != x));
- if (x) |same_x| {
- _ = same_x;
- @panic("fail");
- }
- var otherx: i32 = undefined;
- try expect((x orelse &otherx) == &otherx);
-
- const y: [*c]i32 = null;
- comptime try expect(y == null);
- comptime try expect(null == y);
- comptime try expect(!(y != null));
- comptime try expect(!(null != y));
- if (y) |same_y| {
- _ = same_y;
- @panic("fail");
- }
- const othery: i32 = undefined;
- comptime try expect((y orelse &othery) == &othery);
-
- var n: i32 = 1234;
- var x1: [*c]i32 = &n;
- try expect(!(x1 == null));
- try expect(!(null == x1));
- try expect(x1 != null);
- try expect(null != x1);
- try expect(x1.?.* == 1234);
- if (x1) |same_x1| {
- try expect(same_x1.* == 1234);
- } else {
- @panic("fail");
- }
- try expect((x1 orelse &otherx) == x1);
-
- const nc: i32 = 1234;
- const y1: [*c]const i32 = &nc;
- comptime try expect(!(y1 == null));
- comptime try expect(!(null == y1));
- comptime try expect(y1 != null);
- comptime try expect(null != y1);
- comptime try expect(y1.?.* == 1234);
- if (y1) |same_y1| {
- try expect(same_y1.* == 1234);
- } else {
- @compileError("fail");
- }
- comptime try expect((y1 orelse &othery) == y1);
-}
-
-test "null terminated pointer" {
- const S = struct {
- fn doTheTest() !void {
- var array_with_zero = [_:0]u8{ 'h', 'e', 'l', 'l', 'o' };
- var zero_ptr: [*:0]const u8 = @ptrCast([*:0]const u8, &array_with_zero);
- var no_zero_ptr: [*]const u8 = zero_ptr;
- var zero_ptr_again = @ptrCast([*:0]const u8, no_zero_ptr);
- try expect(std.mem.eql(u8, std.mem.spanZ(zero_ptr_again), "hello"));
- }
- };
- try S.doTheTest();
- comptime try S.doTheTest();
-}
-
-test "allow any sentinel" {
- const S = struct {
- fn doTheTest() !void {
- var array = [_:std.math.minInt(i32)]i32{ 1, 2, 3, 4 };
- var ptr: [*:std.math.minInt(i32)]i32 = &array;
- try expect(ptr[4] == std.math.minInt(i32));
- }
- };
- try S.doTheTest();
- comptime try S.doTheTest();
-}
-
-test "pointer sentinel with enums" {
- const S = struct {
- const Number = enum {
- one,
- two,
- sentinel,
- };
-
- fn doTheTest() !void {
- var ptr: [*:.sentinel]const Number = &[_:.sentinel]Number{ .one, .two, .two, .one };
- try expect(ptr[4] == .sentinel); // TODO this should be comptime try expect, see #3731
- }
- };
- try S.doTheTest();
- comptime try S.doTheTest();
-}
-
-test "pointer sentinel with optional element" {
- const S = struct {
- fn doTheTest() !void {
- var ptr: [*:null]const ?i32 = &[_:null]?i32{ 1, 2, 3, 4 };
- try expect(ptr[4] == null); // TODO this should be comptime try expect, see #3731
- }
- };
- try S.doTheTest();
- comptime try S.doTheTest();
-}
-
-test "pointer sentinel with +inf" {
- const S = struct {
- fn doTheTest() !void {
- const inf = std.math.inf_f32;
- var ptr: [*:inf]const f32 = &[_:inf]f32{ 1.1, 2.2, 3.3, 4.4 };
- try expect(ptr[4] == inf); // TODO this should be comptime try expect, see #3731
- }
- };
- try S.doTheTest();
- comptime try S.doTheTest();
-}
-
-test "pointer to array at fixed address" {
- const array = @intToPtr(*volatile [1]u32, 0x10);
- // Silly check just to reference `array`
- try expect(@ptrToInt(&array[0]) == 0x10);
-}
-
-test "pointer arithmetic affects the alignment" {
- {
- var ptr: [*]align(8) u32 = undefined;
- var x: usize = 1;
-
- try expect(@typeInfo(@TypeOf(ptr)).Pointer.alignment == 8);
- const ptr1 = ptr + 1; // 1 * 4 = 4 -> lcd(4,8) = 4
- try expect(@typeInfo(@TypeOf(ptr1)).Pointer.alignment == 4);
- const ptr2 = ptr + 4; // 4 * 4 = 16 -> lcd(16,8) = 8
- try expect(@typeInfo(@TypeOf(ptr2)).Pointer.alignment == 8);
- const ptr3 = ptr + 0; // no-op
- try expect(@typeInfo(@TypeOf(ptr3)).Pointer.alignment == 8);
- const ptr4 = ptr + x; // runtime-known addend
- try expect(@typeInfo(@TypeOf(ptr4)).Pointer.alignment == 4);
- }
- {
- var ptr: [*]align(8) [3]u8 = undefined;
- var x: usize = 1;
-
- const ptr1 = ptr + 17; // 3 * 17 = 51
- try expect(@typeInfo(@TypeOf(ptr1)).Pointer.alignment == 1);
- const ptr2 = ptr + x; // runtime-known addend
- try expect(@typeInfo(@TypeOf(ptr2)).Pointer.alignment == 1);
- const ptr3 = ptr + 8; // 3 * 8 = 24 -> lcd(8,24) = 8
- try expect(@typeInfo(@TypeOf(ptr3)).Pointer.alignment == 8);
- const ptr4 = ptr + 4; // 3 * 4 = 12 -> lcd(8,12) = 4
- try expect(@typeInfo(@TypeOf(ptr4)).Pointer.alignment == 4);
- }
-}
-
-test "@ptrToInt on null optional at comptime" {
- {
- const pointer = @intToPtr(?*u8, 0x000);
- const x = @ptrToInt(pointer);
- _ = x;
- comptime try expect(0 == @ptrToInt(pointer));
- }
- {
- const pointer = @intToPtr(?*u8, 0xf00);
- comptime try expect(0xf00 == @ptrToInt(pointer));
- }
-}
-
-test "indexing array with sentinel returns correct type" {
- var s: [:0]const u8 = "abc";
- try testing.expectEqualSlices(u8, "*const u8", @typeName(@TypeOf(&s[0])));
-}
diff --git a/test/behavior/pointers_stage1.zig b/test/behavior/pointers_stage1.zig
new file mode 100644
index 0000000000..aea123a5c3
--- /dev/null
+++ b/test/behavior/pointers_stage1.zig
@@ -0,0 +1,305 @@
+const std = @import("std");
+const testing = std.testing;
+const expect = testing.expect;
+const expectError = testing.expectError;
+
+const Foo1 = struct {
+ x: void,
+};
+
+test "dereference pointer again" {
+ try testDerefPtrOneVal();
+ comptime try testDerefPtrOneVal();
+}
+
+fn testDerefPtrOneVal() !void {
+ // Foo1 satisfies the OnePossibleValueYes criteria
+ const x = &Foo1{ .x = {} };
+ const y = x.*;
+ try expect(@TypeOf(y.x) == void);
+}
+
+test "assigning integer to C pointer" {
+ var x: i32 = 0;
+ var ptr: [*c]u8 = 0;
+ var ptr2: [*c]u8 = x;
+ if (false) {
+ ptr;
+ ptr2;
+ }
+}
+
+test "implicit cast single item pointer to C pointer and back" {
+ var y: u8 = 11;
+ var x: [*c]u8 = &y;
+ var z: *u8 = x;
+ z.* += 1;
+ try expect(y == 12);
+}
+
+test "C pointer comparison and arithmetic" {
+ const S = struct {
+ fn doTheTest() !void {
+ var ptr1: [*c]u32 = 0;
+ var ptr2 = ptr1 + 10;
+ try expect(ptr1 == 0);
+ try expect(ptr1 >= 0);
+ try expect(ptr1 <= 0);
+ // expect(ptr1 < 1);
+ // expect(ptr1 < one);
+ // expect(1 > ptr1);
+ // expect(one > ptr1);
+ try expect(ptr1 < ptr2);
+ try expect(ptr2 > ptr1);
+ try expect(ptr2 >= 40);
+ try expect(ptr2 == 40);
+ try expect(ptr2 <= 40);
+ ptr2 -= 10;
+ try expect(ptr1 == ptr2);
+ }
+ };
+ try S.doTheTest();
+ comptime try S.doTheTest();
+}
+
+test "peer type resolution with C pointers" {
+ var ptr_one: *u8 = undefined;
+ var ptr_many: [*]u8 = undefined;
+ var ptr_c: [*c]u8 = undefined;
+ var t = true;
+ var x1 = if (t) ptr_one else ptr_c;
+ var x2 = if (t) ptr_many else ptr_c;
+ var x3 = if (t) ptr_c else ptr_one;
+ var x4 = if (t) ptr_c else ptr_many;
+ try expect(@TypeOf(x1) == [*c]u8);
+ try expect(@TypeOf(x2) == [*c]u8);
+ try expect(@TypeOf(x3) == [*c]u8);
+ try expect(@TypeOf(x4) == [*c]u8);
+}
+
+test "implicit casting between C pointer and optional non-C pointer" {
+ var slice: []const u8 = "aoeu";
+ const opt_many_ptr: ?[*]const u8 = slice.ptr;
+ var ptr_opt_many_ptr = &opt_many_ptr;
+ var c_ptr: [*c]const [*c]const u8 = ptr_opt_many_ptr;
+ try expect(c_ptr.*.* == 'a');
+ ptr_opt_many_ptr = c_ptr;
+ try expect(ptr_opt_many_ptr.*.?[1] == 'o');
+}
+
+test "implicit cast error unions with non-optional to optional pointer" {
+ const S = struct {
+ fn doTheTest() !void {
+ try expectError(error.Fail, foo());
+ }
+ fn foo() anyerror!?*u8 {
+ return bar() orelse error.Fail;
+ }
+ fn bar() ?*u8 {
+ return null;
+ }
+ };
+ try S.doTheTest();
+ comptime try S.doTheTest();
+}
+
+test "initialize const optional C pointer to null" {
+ const a: ?[*c]i32 = null;
+ try expect(a == null);
+ comptime try expect(a == null);
+}
+
+test "compare equality of optional and non-optional pointer" {
+ const a = @intToPtr(*const usize, 0x12345678);
+ const b = @intToPtr(?*usize, 0x12345678);
+ try expect(a == b);
+ try expect(b == a);
+}
+
+test "allowzero pointer and slice" {
+ var ptr = @intToPtr([*]allowzero i32, 0);
+ var opt_ptr: ?[*]allowzero i32 = ptr;
+ try expect(opt_ptr != null);
+ try expect(@ptrToInt(ptr) == 0);
+ var runtime_zero: usize = 0;
+ var slice = ptr[runtime_zero..10];
+ comptime try expect(@TypeOf(slice) == []allowzero i32);
+ try expect(@ptrToInt(&slice[5]) == 20);
+
+ comptime try expect(@typeInfo(@TypeOf(ptr)).Pointer.is_allowzero);
+ comptime try expect(@typeInfo(@TypeOf(slice)).Pointer.is_allowzero);
+}
+
+test "assign null directly to C pointer and test null equality" {
+ var x: [*c]i32 = null;
+ try expect(x == null);
+ try expect(null == x);
+ try expect(!(x != null));
+ try expect(!(null != x));
+ if (x) |same_x| {
+ _ = same_x;
+ @panic("fail");
+ }
+ var otherx: i32 = undefined;
+ try expect((x orelse &otherx) == &otherx);
+
+ const y: [*c]i32 = null;
+ comptime try expect(y == null);
+ comptime try expect(null == y);
+ comptime try expect(!(y != null));
+ comptime try expect(!(null != y));
+ if (y) |same_y| {
+ _ = same_y;
+ @panic("fail");
+ }
+ const othery: i32 = undefined;
+ comptime try expect((y orelse &othery) == &othery);
+
+ var n: i32 = 1234;
+ var x1: [*c]i32 = &n;
+ try expect(!(x1 == null));
+ try expect(!(null == x1));
+ try expect(x1 != null);
+ try expect(null != x1);
+ try expect(x1.?.* == 1234);
+ if (x1) |same_x1| {
+ try expect(same_x1.* == 1234);
+ } else {
+ @panic("fail");
+ }
+ try expect((x1 orelse &otherx) == x1);
+
+ const nc: i32 = 1234;
+ const y1: [*c]const i32 = &nc;
+ comptime try expect(!(y1 == null));
+ comptime try expect(!(null == y1));
+ comptime try expect(y1 != null);
+ comptime try expect(null != y1);
+ comptime try expect(y1.?.* == 1234);
+ if (y1) |same_y1| {
+ try expect(same_y1.* == 1234);
+ } else {
+ @compileError("fail");
+ }
+ comptime try expect((y1 orelse &othery) == y1);
+}
+
+test "null terminated pointer" {
+ const S = struct {
+ fn doTheTest() !void {
+ var array_with_zero = [_:0]u8{ 'h', 'e', 'l', 'l', 'o' };
+ var zero_ptr: [*:0]const u8 = @ptrCast([*:0]const u8, &array_with_zero);
+ var no_zero_ptr: [*]const u8 = zero_ptr;
+ var zero_ptr_again = @ptrCast([*:0]const u8, no_zero_ptr);
+ try expect(std.mem.eql(u8, std.mem.spanZ(zero_ptr_again), "hello"));
+ }
+ };
+ try S.doTheTest();
+ comptime try S.doTheTest();
+}
+
+test "allow any sentinel" {
+ const S = struct {
+ fn doTheTest() !void {
+ var array = [_:std.math.minInt(i32)]i32{ 1, 2, 3, 4 };
+ var ptr: [*:std.math.minInt(i32)]i32 = &array;
+ try expect(ptr[4] == std.math.minInt(i32));
+ }
+ };
+ try S.doTheTest();
+ comptime try S.doTheTest();
+}
+
+test "pointer sentinel with enums" {
+ const S = struct {
+ const Number = enum {
+ one,
+ two,
+ sentinel,
+ };
+
+ fn doTheTest() !void {
+ var ptr: [*:.sentinel]const Number = &[_:.sentinel]Number{ .one, .two, .two, .one };
+ try expect(ptr[4] == .sentinel); // TODO this should be comptime try expect, see #3731
+ }
+ };
+ try S.doTheTest();
+ comptime try S.doTheTest();
+}
+
+test "pointer sentinel with optional element" {
+ const S = struct {
+ fn doTheTest() !void {
+ var ptr: [*:null]const ?i32 = &[_:null]?i32{ 1, 2, 3, 4 };
+ try expect(ptr[4] == null); // TODO this should be comptime try expect, see #3731
+ }
+ };
+ try S.doTheTest();
+ comptime try S.doTheTest();
+}
+
+test "pointer sentinel with +inf" {
+ const S = struct {
+ fn doTheTest() !void {
+ const inf = std.math.inf_f32;
+ var ptr: [*:inf]const f32 = &[_:inf]f32{ 1.1, 2.2, 3.3, 4.4 };
+ try expect(ptr[4] == inf); // TODO this should be comptime try expect, see #3731
+ }
+ };
+ try S.doTheTest();
+ comptime try S.doTheTest();
+}
+
+test "pointer to array at fixed address" {
+ const array = @intToPtr(*volatile [1]u32, 0x10);
+ // Silly check just to reference `array`
+ try expect(@ptrToInt(&array[0]) == 0x10);
+}
+
+test "pointer arithmetic affects the alignment" {
+ {
+ var ptr: [*]align(8) u32 = undefined;
+ var x: usize = 1;
+
+ try expect(@typeInfo(@TypeOf(ptr)).Pointer.alignment == 8);
+ const ptr1 = ptr + 1; // 1 * 4 = 4 -> lcd(4,8) = 4
+ try expect(@typeInfo(@TypeOf(ptr1)).Pointer.alignment == 4);
+ const ptr2 = ptr + 4; // 4 * 4 = 16 -> lcd(16,8) = 8
+ try expect(@typeInfo(@TypeOf(ptr2)).Pointer.alignment == 8);
+ const ptr3 = ptr + 0; // no-op
+ try expect(@typeInfo(@TypeOf(ptr3)).Pointer.alignment == 8);
+ const ptr4 = ptr + x; // runtime-known addend
+ try expect(@typeInfo(@TypeOf(ptr4)).Pointer.alignment == 4);
+ }
+ {
+ var ptr: [*]align(8) [3]u8 = undefined;
+ var x: usize = 1;
+
+ const ptr1 = ptr + 17; // 3 * 17 = 51
+ try expect(@typeInfo(@TypeOf(ptr1)).Pointer.alignment == 1);
+ const ptr2 = ptr + x; // runtime-known addend
+ try expect(@typeInfo(@TypeOf(ptr2)).Pointer.alignment == 1);
+ const ptr3 = ptr + 8; // 3 * 8 = 24 -> lcd(8,24) = 8
+ try expect(@typeInfo(@TypeOf(ptr3)).Pointer.alignment == 8);
+ const ptr4 = ptr + 4; // 3 * 4 = 12 -> lcd(8,12) = 4
+ try expect(@typeInfo(@TypeOf(ptr4)).Pointer.alignment == 4);
+ }
+}
+
+test "@ptrToInt on null optional at comptime" {
+ {
+ const pointer = @intToPtr(?*u8, 0x000);
+ const x = @ptrToInt(pointer);
+ _ = x;
+ comptime try expect(0 == @ptrToInt(pointer));
+ }
+ {
+ const pointer = @intToPtr(?*u8, 0xf00);
+ comptime try expect(0xf00 == @ptrToInt(pointer));
+ }
+}
+
+test "indexing array with sentinel returns correct type" {
+ var s: [:0]const u8 = "abc";
+ try testing.expectEqualSlices(u8, "*const u8", @typeName(@TypeOf(&s[0])));
+}
diff --git a/test/behavior/select.zig b/test/behavior/select.zig
new file mode 100644
index 0000000000..5c69094413
--- /dev/null
+++ b/test/behavior/select.zig
@@ -0,0 +1,25 @@
+const std = @import("std");
+const builtin = @import("builtin");
+const mem = std.mem;
+const expect = std.testing.expect;
+const Vector = std.meta.Vector;
+
+test "@select" {
+ const S = struct {
+ fn doTheTest() !void {
+ var a: Vector(4, bool) = [4]bool{ true, false, true, false };
+ var b: Vector(4, i32) = [4]i32{ -1, 4, 999, -31 };
+ var c: Vector(4, i32) = [4]i32{ -5, 1, 0, 1234 };
+ var abc = @select(i32, a, b, c);
+ try expect(mem.eql(i32, &@as([4]i32, abc), &[4]i32{ -1, 1, 999, 1234 }));
+
+ var x: Vector(4, bool) = [4]bool{ false, false, false, true };
+ var y: Vector(4, f32) = [4]f32{ 0.001, 33.4, 836, -3381.233 };
+ var z: Vector(4, f32) = [4]f32{ 0.0, 312.1, -145.9, 9993.55 };
+ var xyz = @select(f32, x, y, z);
+ try expect(mem.eql(f32, &@as([4]f32, xyz), &[4]f32{ 0.0, 312.1, -145.9, -3381.233 }));
+ }
+ };
+ try S.doTheTest();
+ comptime try S.doTheTest();
+}
diff --git a/test/behavior/translate_c_macros.h b/test/behavior/translate_c_macros.h
index 6f458684c7..bff4cdfe23 100644
--- a/test/behavior/translate_c_macros.h
+++ b/test/behavior/translate_c_macros.h
@@ -18,3 +18,15 @@ struct Foo {
#define SIZE_OF_FOO sizeof(struct Foo)
#define MAP_FAILED ((void *) -1)
+
+#define IGNORE_ME_1(x) ((void)(x))
+#define IGNORE_ME_2(x) ((const void)(x))
+#define IGNORE_ME_3(x) ((volatile void)(x))
+#define IGNORE_ME_4(x) ((const volatile void)(x))
+#define IGNORE_ME_5(x) ((volatile const void)(x))
+
+#define IGNORE_ME_6(x) (void)(x)
+#define IGNORE_ME_7(x) (const void)(x)
+#define IGNORE_ME_8(x) (volatile void)(x)
+#define IGNORE_ME_9(x) (const volatile void)(x)
+#define IGNORE_ME_10(x) (volatile const void)(x)
diff --git a/test/behavior/translate_c_macros.zig b/test/behavior/translate_c_macros.zig
index 8de06ae8ea..0daf4cec90 100644
--- a/test/behavior/translate_c_macros.zig
+++ b/test/behavior/translate_c_macros.zig
@@ -24,3 +24,16 @@ test "reference to a struct type" {
test "cast negative integer to pointer" {
try expectEqual(@intToPtr(?*c_void, @bitCast(usize, @as(isize, -1))), h.MAP_FAILED);
}
+
+test "casting to void with a macro" {
+ h.IGNORE_ME_1(42);
+ h.IGNORE_ME_2(42);
+ h.IGNORE_ME_3(42);
+ h.IGNORE_ME_4(42);
+ h.IGNORE_ME_5(42);
+ h.IGNORE_ME_6(42);
+ h.IGNORE_ME_7(42);
+ h.IGNORE_ME_8(42);
+ h.IGNORE_ME_9(42);
+ h.IGNORE_ME_10(42);
+}
diff --git a/test/behavior/typename.zig b/test/behavior/typename.zig
index bf8464244b..4d87e0030c 100644
--- a/test/behavior/typename.zig
+++ b/test/behavior/typename.zig
@@ -2,6 +2,113 @@ const std = @import("std");
const expect = std.testing.expect;
const expectEqualSlices = std.testing.expectEqualSlices;
-test "slice" {
- try expectEqualSlices(u8, "[]u8", @typeName([]u8));
+// Most tests here can be comptime but use runtime so that a stacktrace
+// can show failure location.
+//
+// Note certain results of `@typeName()` expect `behavior.zig` to be the
+// root file. Running a test against this file as root will result in
+// failures.
+
+// CAUTION: this test is source-location sensitive.
+test "anon fn param - source-location sensitive" {
+ // https://github.com/ziglang/zig/issues/9339
+ try expectEqualSlices(u8, @typeName(TypeFromFn(struct {})), "behavior.typename.TypeFromFn(behavior.typename.struct:15:52)");
+ try expectEqualSlices(u8, @typeName(TypeFromFn(union { unused: u8 })), "behavior.typename.TypeFromFn(behavior.typename.union:16:52)");
+ try expectEqualSlices(u8, @typeName(TypeFromFn(enum { unused })), "behavior.typename.TypeFromFn(behavior.typename.enum:17:52)");
+
+ try expectEqualSlices(
+ u8,
+ @typeName(TypeFromFn3(struct {}, union { unused: u8 }, enum { unused })),
+ "behavior.typename.TypeFromFn3(behavior.typename.struct:21:31,behavior.typename.union:21:42,behavior.typename.enum:21:64)",
+ );
+}
+
+// CAUTION: this test is source-location sensitive.
+test "anon field init" {
+ const Foo = .{
+ .T1 = struct {},
+ .T2 = union { unused: u8 },
+ .T3 = enum { unused },
+ };
+
+ try expectEqualSlices(u8, @typeName(Foo.T1), "behavior.typename.struct:29:15");
+ try expectEqualSlices(u8, @typeName(Foo.T2), "behavior.typename.union:30:15");
+ try expectEqualSlices(u8, @typeName(Foo.T3), "behavior.typename.enum:31:15");
+}
+
+test "basic" {
+ try expectEqualSlices(u8, @typeName(i64), "i64");
+ try expectEqualSlices(u8, @typeName(*usize), "*usize");
+ try expectEqualSlices(u8, @typeName([]u8), "[]u8");
+}
+
+test "top level decl" {
+ try expectEqualSlices(u8, @typeName(A_Struct), "A_Struct");
+ try expectEqualSlices(u8, @typeName(A_Union), "A_Union");
+ try expectEqualSlices(u8, @typeName(A_Enum), "A_Enum");
+
+ // regular fn, without error
+ try expectEqualSlices(u8, @typeName(@TypeOf(regular)), "fn() void");
+ // regular fn inside struct, with error
+ try expectEqualSlices(u8, @typeName(@TypeOf(B.doTest)), "fn() @typeInfo(@typeInfo(@TypeOf(behavior.typename.B.doTest)).Fn.return_type.?).ErrorUnion.error_set!void");
+ // generic fn
+ try expectEqualSlices(u8, @typeName(@TypeOf(TypeFromFn)), "fn(type) anytype");
+}
+
+const A_Struct = struct {};
+const A_Union = union {
+ unused: u8,
+};
+const A_Enum = enum {
+ unused,
+};
+
+fn regular() void {}
+
+test "fn body decl" {
+ try B.doTest();
+}
+
+const B = struct {
+ fn doTest() !void {
+ const B_Struct = struct {};
+ const B_Union = union {
+ unused: u8,
+ };
+ const B_Enum = enum {
+ unused,
+ };
+
+ try expectEqualSlices(u8, @typeName(B_Struct), "B_Struct");
+ try expectEqualSlices(u8, @typeName(B_Union), "B_Union");
+ try expectEqualSlices(u8, @typeName(B_Enum), "B_Enum");
+ }
+};
+
+test "fn param" {
+ // https://github.com/ziglang/zig/issues/675
+ try expectEqualSlices(u8, @typeName(TypeFromFn(u8)), "behavior.typename.TypeFromFn(u8)");
+ try expectEqualSlices(u8, @typeName(TypeFromFn(A_Struct)), "behavior.typename.TypeFromFn(behavior.typename.A_Struct)");
+ try expectEqualSlices(u8, @typeName(TypeFromFn(A_Union)), "behavior.typename.TypeFromFn(behavior.typename.A_Union)");
+ try expectEqualSlices(u8, @typeName(TypeFromFn(A_Enum)), "behavior.typename.TypeFromFn(behavior.typename.A_Enum)");
+
+ try expectEqualSlices(u8, @typeName(TypeFromFn2(u8, bool)), "behavior.typename.TypeFromFn2(u8,bool)");
+}
+
+fn TypeFromFn(comptime T: type) type {
+ _ = T;
+ return struct {};
+}
+
+fn TypeFromFn2(comptime T1: type, comptime T2: type) type {
+ _ = T1;
+ _ = T2;
+ return struct {};
+}
+
+fn TypeFromFn3(comptime T1: type, comptime T2: type, comptime T3: type) type {
+ _ = T1;
+ _ = T2;
+ _ = T3;
+ return struct {};
}
diff --git a/test/behavior/widening.zig b/test/behavior/widening.zig
index dfa70ac4b2..19abf767b8 100644
--- a/test/behavior/widening.zig
+++ b/test/behavior/widening.zig
@@ -37,3 +37,14 @@ test "float widening f16 to f128" {
var y: f128 = x;
try expect(x == y);
}
+
+test "cast small unsigned to larger signed" {
+ try expect(castSmallUnsignedToLargerSigned1(200) == @as(i16, 200));
+ try expect(castSmallUnsignedToLargerSigned2(9999) == @as(i64, 9999));
+}
+fn castSmallUnsignedToLargerSigned1(x: u8) i16 {
+ return x;
+}
+fn castSmallUnsignedToLargerSigned2(x: u16) i64 {
+ return x;
+}
diff --git a/test/cases.zig b/test/cases.zig
index 39d6128e8c..6510329238 100644
--- a/test/cases.zig
+++ b/test/cases.zig
@@ -1182,10 +1182,11 @@ pub fn addCases(ctx: *TestContext) !void {
var case = ctx.obj("extern variable has no type", linux_x64);
case.addError(
\\comptime {
- \\ _ = foo;
+ \\ const x = foo + foo;
+ \\ _ = x;
\\}
\\extern var foo: i32;
- , &[_][]const u8{":2:9: error: unable to resolve comptime value"});
+ , &[_][]const u8{":2:15: error: unable to resolve comptime value"});
case.addError(
\\export fn entry() void {
\\ _ = foo;
@@ -1571,7 +1572,7 @@ pub fn addCases(ctx: *TestContext) !void {
\\ const x = asm volatile ("syscall"
\\ : [o] "{rax}" (-> number)
\\ : [number] "{rax}" (231),
- \\ [arg1] "{rdi}" (code)
+ \\ [arg1] "{rdi}" (60)
\\ : "rcx", "r11", "memory"
\\ );
\\ _ = x;
diff --git a/test/run_translated_c.zig b/test/run_translated_c.zig
index 4953896636..2e579b06c7 100644
--- a/test/run_translated_c.zig
+++ b/test/run_translated_c.zig
@@ -1243,7 +1243,7 @@ pub fn addCases(cases: *tests.RunTranslatedCContext) void {
\\}
, "");
- // See __builtin_alloca_with_align comment in std.c.builtins
+ // See __builtin_alloca_with_align comment in std.zig.c_builtins
cases.add("use of unimplemented builtin in unused function does not prevent compilation",
\\#include <stdlib.h>
\\void unused() {
@@ -1659,4 +1659,94 @@ pub fn addCases(cases: *tests.RunTranslatedCContext) void {
\\ return 0;
\\}
, "");
+
+ cases.add("__builtin_choose_expr (unchosen expression is not evaluated)",
+ \\#include <stdlib.h>
+ \\int main(void) {
+ \\ int x = 0.0;
+ \\ int y = 0.0;
+ \\ int res;
+ \\ res = __builtin_choose_expr(1, 1, x / y);
+ \\ if (res != 1) abort();
+ \\ res = __builtin_choose_expr(0, x / y, 2);
+ \\ if (res != 2) abort();
+ \\ return 0;
+ \\}
+ , "");
+
+ // TODO: add isnan check for long double once bitfield support is added
+ // (needed for x86_64-windows-gnu)
+ // TODO: add isinf check for long double once std.math.isInf supports c_longdouble
+ cases.add("NAN and INFINITY",
+ \\#include <math.h>
+ \\#include <stdint.h>
+ \\#include <stdlib.h>
+ \\union uf { uint32_t u; float f; };
+ \\#define CHECK_NAN(STR, VAL) { \
+ \\ union uf unpack = {.f = __builtin_nanf(STR)}; \
+ \\ if (!isnan(unpack.f)) abort(); \
+ \\ if (unpack.u != VAL) abort(); \
+ \\}
+ \\int main(void) {
+ \\ float f_nan = NAN;
+ \\ if (!isnan(f_nan)) abort();
+ \\ double d_nan = NAN;
+ \\ if (!isnan(d_nan)) abort();
+ \\ CHECK_NAN("0", 0x7FC00000);
+ \\ CHECK_NAN("", 0x7FC00000);
+ \\ CHECK_NAN("1", 0x7FC00001);
+ \\ CHECK_NAN("0x7FC00000", 0x7FC00000);
+ \\ CHECK_NAN("0x7FC0000F", 0x7FC0000F);
+ \\ CHECK_NAN("0x7FC000F0", 0x7FC000F0);
+ \\ CHECK_NAN("0x7FC00F00", 0x7FC00F00);
+ \\ CHECK_NAN("0x7FC0F000", 0x7FC0F000);
+ \\ CHECK_NAN("0x7FCF0000", 0x7FCF0000);
+ \\ CHECK_NAN("0xFFFFFFFF", 0x7FFFFFFF);
+ \\ float f_inf = INFINITY;
+ \\ if (!isinf(f_inf)) abort();
+ \\ double d_inf = INFINITY;
+ \\ if (!isinf(d_inf)) abort();
+ \\ return 0;
+ \\}
+ , "");
+
+ cases.add("signed array subscript. Issue #8556",
+ \\#include <stdint.h>
+ \\#include <stdlib.h>
+ \\#define TEST_NEGATIVE(type) { type x = -1; if (ptr[x] != 42) abort(); }
+ \\#define TEST_UNSIGNED(type) { type x = 2; if (arr[x] != 42) abort(); }
+ \\int main(void) {
+ \\ int arr[] = {40, 41, 42, 43};
+ \\ int *ptr = arr + 3;
+ \\ if (ptr[-1] != 42) abort();
+ \\ TEST_NEGATIVE(int);
+ \\ TEST_NEGATIVE(long);
+ \\ TEST_NEGATIVE(long long);
+ \\ TEST_NEGATIVE(int64_t);
+ \\ TEST_NEGATIVE(__int128);
+ \\ TEST_UNSIGNED(unsigned);
+ \\ TEST_UNSIGNED(unsigned long);
+ \\ TEST_UNSIGNED(unsigned long long);
+ \\ TEST_UNSIGNED(uint64_t);
+ \\ TEST_UNSIGNED(size_t);
+ \\ TEST_UNSIGNED(unsigned __int128);
+ \\ return 0;
+ \\}
+ , "");
+
+ cases.add("Ensure side-effects only evaluated once for signed array indices",
+ \\#include <stdlib.h>
+ \\int main(void) {
+ \\ int foo[] = {1, 2, 3, 4};
+ \\ int *p = foo;
+ \\ int idx = 1;
+ \\ if ((++p)[--idx] != 2) abort();
+ \\ if (p != foo + 1) abort();
+ \\ if (idx != 0) abort();
+ \\ if ((p++)[idx++] != 2) abort();
+ \\ if (p != foo + 2) abort();
+ \\ if (idx != 1) abort();
+ \\ return 0;
+ \\}
+ , "");
}
diff --git a/test/stage1/c_abi/cfuncs.c b/test/stage1/c_abi/cfuncs.c
index a3b8c9a8c6..0182462716 100644
--- a/test/stage1/c_abi/cfuncs.c
+++ b/test/stage1/c_abi/cfuncs.c
@@ -61,7 +61,20 @@ struct SmallStructInts {
uint8_t c;
uint8_t d;
};
+
void zig_small_struct_ints(struct SmallStructInts);
+struct SmallStructInts zig_ret_small_struct_ints();
+
+struct MedStructMixed {
+ uint32_t a;
+ float b;
+ float c;
+ uint32_t d;
+};
+
+void zig_med_struct_mixed(struct MedStructMixed);
+struct MedStructMixed zig_ret_med_struct_mixed();
+
struct SplitStructInts {
uint64_t a;
@@ -70,6 +83,14 @@ struct SplitStructInts {
};
void zig_split_struct_ints(struct SplitStructInts);
+struct SplitStructMixed {
+ uint64_t a;
+ uint8_t b;
+ float c;
+};
+void zig_split_struct_mixed(struct SplitStructMixed);
+struct SplitStructMixed zig_ret_split_struct_mixed();
+
struct BigStruct zig_big_struct_both(struct BigStruct);
typedef struct Vector3 {
@@ -122,6 +143,16 @@ void run_c_tests(void) {
}
{
+ struct MedStructMixed s = {1234, 100.0f, 1337.0f};
+ zig_med_struct_mixed(s);
+ }
+
+ {
+ struct SplitStructMixed s = {1234, 100, 1337.0f};
+ zig_split_struct_mixed(s);
+ }
+
+ {
struct BigStruct s = {30, 31, 32, 33, 34};
struct BigStruct res = zig_big_struct_both(s);
assert_or_panic(res.a == 20);
@@ -230,6 +261,44 @@ void c_small_struct_ints(struct SmallStructInts x) {
assert_or_panic(x.b == 2);
assert_or_panic(x.c == 3);
assert_or_panic(x.d == 4);
+
+ struct SmallStructInts y = zig_ret_small_struct_ints();
+
+ assert_or_panic(y.a == 1);
+ assert_or_panic(y.b == 2);
+ assert_or_panic(y.c == 3);
+ assert_or_panic(y.d == 4);
+}
+
+struct SmallStructInts c_ret_small_struct_ints() {
+ struct SmallStructInts s = {
+ .a = 1,
+ .b = 2,
+ .c = 3,
+ .d = 4,
+ };
+ return s;
+}
+
+void c_med_struct_mixed(struct MedStructMixed x) {
+ assert_or_panic(x.a == 1234);
+ assert_or_panic(x.b == 100.0f);
+ assert_or_panic(x.c == 1337.0f);
+
+ struct MedStructMixed y = zig_ret_med_struct_mixed();
+
+ assert_or_panic(y.a == 1234);
+ assert_or_panic(y.b == 100.0f);
+ assert_or_panic(y.c == 1337.0f);
+}
+
+struct MedStructMixed c_ret_med_struct_mixed() {
+ struct MedStructMixed s = {
+ .a = 1234,
+ .b = 100.0,
+ .c = 1337.0,
+ };
+ return s;
}
void c_split_struct_ints(struct SplitStructInts x) {
@@ -238,6 +307,26 @@ void c_split_struct_ints(struct SplitStructInts x) {
assert_or_panic(x.c == 1337);
}
+void c_split_struct_mixed(struct SplitStructMixed x) {
+ assert_or_panic(x.a == 1234);
+ assert_or_panic(x.b == 100);
+ assert_or_panic(x.c == 1337.0f);
+ struct SplitStructMixed y = zig_ret_split_struct_mixed();
+
+ assert_or_panic(y.a == 1234);
+ assert_or_panic(y.b == 100);
+ assert_or_panic(y.c == 1337.0f);
+}
+
+struct SplitStructMixed c_ret_split_struct_mixed() {
+ struct SplitStructMixed s = {
+ .a = 1234,
+ .b = 100,
+ .c = 1337.0f,
+ };
+ return s;
+}
+
struct BigStruct c_big_struct_both(struct BigStruct x) {
assert_or_panic(x.a == 1);
assert_or_panic(x.b == 2);
diff --git a/test/stage1/c_abi/main.zig b/test/stage1/c_abi/main.zig
index ed5cad7c56..b8137334ec 100644
--- a/test/stage1/c_abi/main.zig
+++ b/test/stage1/c_abi/main.zig
@@ -1,4 +1,5 @@
const std = @import("std");
+const print = std.debug.print;
const expect = std.testing.expect;
extern fn run_c_tests() void;
@@ -170,6 +171,34 @@ export fn zig_big_union(x: BigUnion) void {
expect(x.a.e == 5) catch @panic("test failure");
}
+const MedStructMixed = extern struct {
+ a: u32,
+ b: f32,
+ c: f32,
+ d: u32 = 0,
+};
+extern fn c_med_struct_mixed(MedStructMixed) void;
+extern fn c_ret_med_struct_mixed() MedStructMixed;
+
+test "C ABI medium struct of ints and floats" {
+ var s = MedStructMixed{
+ .a = 1234,
+ .b = 100.0,
+ .c = 1337.0,
+ };
+ c_med_struct_mixed(s);
+ var s2 = c_ret_med_struct_mixed();
+ expect(s2.a == 1234) catch @panic("test failure");
+ expect(s2.b == 100.0) catch @panic("test failure");
+ expect(s2.c == 1337.0) catch @panic("test failure");
+}
+
+export fn zig_med_struct_mixed(x: MedStructMixed) void {
+ expect(x.a == 1234) catch @panic("test failure");
+ expect(x.b == 100.0) catch @panic("test failure");
+ expect(x.c == 1337.0) catch @panic("test failure");
+}
+
const SmallStructInts = extern struct {
a: u8,
b: u8,
@@ -177,6 +206,7 @@ const SmallStructInts = extern struct {
d: u8,
};
extern fn c_small_struct_ints(SmallStructInts) void;
+extern fn c_ret_small_struct_ints() SmallStructInts;
test "C ABI small struct of ints" {
var s = SmallStructInts{
@@ -186,6 +216,11 @@ test "C ABI small struct of ints" {
.d = 4,
};
c_small_struct_ints(s);
+ var s2 = c_ret_small_struct_ints();
+ expect(s2.a == 1) catch @panic("test failure");
+ expect(s2.b == 2) catch @panic("test failure");
+ expect(s2.c == 3) catch @panic("test failure");
+ expect(s2.d == 4) catch @panic("test failure");
}
export fn zig_small_struct_ints(x: SmallStructInts) void {
@@ -217,6 +252,33 @@ export fn zig_split_struct_ints(x: SplitStructInt) void {
expect(x.c == 1337) catch @panic("test failure");
}
+const SplitStructMixed = extern struct {
+ a: u64,
+ b: u8,
+ c: f32,
+};
+extern fn c_split_struct_mixed(SplitStructMixed) void;
+extern fn c_ret_split_struct_mixed() SplitStructMixed;
+
+test "C ABI split struct of ints and floats" {
+ var s = SplitStructMixed{
+ .a = 1234,
+ .b = 100,
+ .c = 1337.0,
+ };
+ c_split_struct_mixed(s);
+ var s2 = c_ret_split_struct_mixed();
+ expect(s2.a == 1234) catch @panic("test failure");
+ expect(s2.b == 100) catch @panic("test failure");
+ expect(s2.c == 1337.0) catch @panic("test failure");
+}
+
+export fn zig_split_struct_mixed(x: SplitStructMixed) void {
+ expect(x.a == 1234) catch @panic("test failure");
+ expect(x.b == 100) catch @panic("test failure");
+ expect(x.c == 1337.0) catch @panic("test failure");
+}
+
extern fn c_big_struct_both(BigStruct) BigStruct;
test "C ABI sret and byval together" {
@@ -315,6 +377,31 @@ export fn zig_ret_i64() i64 {
return -1;
}
+export fn zig_ret_small_struct_ints() SmallStructInts {
+ return .{
+ .a = 1,
+ .b = 2,
+ .c = 3,
+ .d = 4,
+ };
+}
+
+export fn zig_ret_med_struct_mixed() MedStructMixed {
+ return .{
+ .a = 1234,
+ .b = 100.0,
+ .c = 1337.0,
+ };
+}
+
+export fn zig_ret_split_struct_mixed() SplitStructMixed {
+ return .{
+ .a = 1234,
+ .b = 100,
+ .c = 1337.0,
+ };
+}
+
extern fn c_ret_bool() bool;
extern fn c_ret_u8() u8;
extern fn c_ret_u16() u16;
diff --git a/test/stage2/arm.zig b/test/stage2/arm.zig
index 6b4f569757..103b058a54 100644
--- a/test/stage2/arm.zig
+++ b/test/stage2/arm.zig
@@ -300,6 +300,28 @@ pub fn addCases(ctx: *TestContext) !void {
}
{
+ var case = ctx.exe("enums", linux_arm);
+ case.addCompareOutput(
+ \\const Number = enum { one, two, three };
+ \\
+ \\pub fn main() void {
+ \\ var x: Number = .one;
+ \\ var y = Number.two;
+ \\ var z = @intToEnum(Number, 2);
+ \\ assert(@enumToInt(x) == 0);
+ \\ assert(@enumToInt(y) == 1);
+ \\ assert(@enumToInt(z) == 2);
+ \\}
+ \\
+ \\fn assert(ok: bool) void {
+ \\ if (!ok) unreachable; // assertion failure
+ \\}
+ ,
+ "",
+ );
+ }
+
+ {
var case = ctx.exe("recursive fibonacci", linux_arm);
case.addCompareOutput(
\\pub fn main() void {
diff --git a/test/stage2/cbe.zig b/test/stage2/cbe.zig
index 6427e2e3b8..aa1022257b 100644
--- a/test/stage2/cbe.zig
+++ b/test/stage2/cbe.zig
@@ -49,7 +49,7 @@ pub fn addCases(ctx: *TestContext) !void {
\\export fn foo() callconv(y) c_int {
\\ return 0;
\\}
- \\var y: i32 = 1234;
+ \\var y: @import("std").builtin.CallingConvention = .C;
, &.{
":2:22: error: unable to resolve comptime value",
":5:26: error: unable to resolve comptime value",
@@ -240,6 +240,10 @@ pub fn addCases(ctx: *TestContext) !void {
if (host_supports_custom_stack_size) {
var case = ctx.exeFromCompiledC("@setEvalBranchQuota", .{});
+ // TODO when adding result location support to function calls, revisit this test
+ // case. It can go back to what it was before, with `y` being comptime known.
+ // Because the ret_ptr will passed in with the inline fn call, and there will
+ // only be 1 store to it, and it will be comptime known.
case.addCompareOutput(
\\pub export fn main() i32 {
\\ @setEvalBranchQuota(1001);
@@ -247,7 +251,7 @@ pub fn addCases(ctx: *TestContext) !void {
\\ return y - 1;
\\}
\\
- \\fn rec(n: usize) callconv(.Inline) usize {
+ \\inline fn rec(n: i32) i32 {
\\ if (n <= 1) return n;
\\ return rec(n - 1);
\\}
diff --git a/test/stage2/wasm.zig b/test/stage2/wasm.zig
index f746be99d2..ab400f0a53 100644
--- a/test/stage2/wasm.zig
+++ b/test/stage2/wasm.zig
@@ -114,6 +114,27 @@ pub fn addCases(ctx: *TestContext) !void {
, "25\n");
case.addCompareOutput(
+ \\pub export fn _start() i32 {
+ \\ var i: i32 = 2147483647;
+ \\ return i +% 1;
+ \\}
+ , "-2147483648\n");
+
+ case.addCompareOutput(
+ \\pub export fn _start() i32 {
+ \\ var i: i4 = 7;
+ \\ return i +% 1;
+ \\}
+ , "0\n");
+
+ case.addCompareOutput(
+ \\pub export fn _start() u32 {
+ \\ var i: u8 = 255;
+ \\ return i +% 1;
+ \\}
+ , "0\n");
+
+ case.addCompareOutput(
\\pub export fn _start() u32 {
\\ var i: u32 = 5;
\\ i += 20;
@@ -134,6 +155,27 @@ pub fn addCases(ctx: *TestContext) !void {
, "15\n");
case.addCompareOutput(
+ \\pub export fn _start() i32 {
+ \\ var i: i32 = -2147483648;
+ \\ return i -% 1;
+ \\}
+ , "2147483647\n");
+
+ case.addCompareOutput(
+ \\pub export fn _start() i32 {
+ \\ var i: i7 = -64;
+ \\ return i -% 1;
+ \\}
+ , "63\n");
+
+ case.addCompareOutput(
+ \\pub export fn _start() u32 {
+ \\ var i: u4 = 0;
+ \\ return i -% 1;
+ \\}
+ , "15\n");
+
+ case.addCompareOutput(
\\pub export fn _start() u32 {
\\ var i: u32 = 5;
\\ i -= 3;
@@ -158,6 +200,27 @@ pub fn addCases(ctx: *TestContext) !void {
, "350\n");
case.addCompareOutput(
+ \\pub export fn _start() i32 {
+ \\ var i: i32 = 2147483647;
+ \\ return i *% 2;
+ \\}
+ , "-2\n");
+
+ case.addCompareOutput(
+ \\pub export fn _start() u32 {
+ \\ var i: u3 = 3;
+ \\ return i *% 3;
+ \\}
+ , "1\n");
+
+ case.addCompareOutput(
+ \\pub export fn _start() i32 {
+ \\ var i: i4 = 3;
+ \\ return i *% 3;
+ \\}
+ , "1\n");
+
+ case.addCompareOutput(
\\pub export fn _start() u32 {
\\ var i: u32 = 352;
\\ i /= 7; // i = 50
@@ -612,4 +675,69 @@ pub fn addCases(ctx: *TestContext) !void {
\\}
, "42\n");
}
+
+ {
+ var case = ctx.exe("wasm integer widening", wasi);
+
+ case.addCompareOutput(
+ \\pub export fn _start() u64 {
+ \\ var x: u32 = 5;
+ \\ return x;
+ \\}
+ , "5\n");
+ }
+
+ {
+ var case = ctx.exe("wasm optionals", wasi);
+
+ case.addCompareOutput(
+ \\pub export fn _start() u32 {
+ \\ var x: ?u32 = 5;
+ \\ var y: u32 = 0;
+ \\ if (x) |val| {
+ \\ y = val;
+ \\ }
+ \\ return y;
+ \\}
+ , "5\n");
+
+ case.addCompareOutput(
+ \\pub export fn _start() u32 {
+ \\ var x: ?u32 = null;
+ \\ var y: u32 = 0;
+ \\ if (x) |val| {
+ \\ y = val;
+ \\ }
+ \\ return y;
+ \\}
+ , "0\n");
+
+ case.addCompareOutput(
+ \\pub export fn _start() u32 {
+ \\ var x: ?u32 = 5;
+ \\ return x.?;
+ \\}
+ , "5\n");
+
+ case.addCompareOutput(
+ \\pub export fn _start() u32 {
+ \\ var x: u32 = 5;
+ \\ var y: ?u32 = x;
+ \\ return y.?;
+ \\}
+ , "5\n");
+
+ case.addCompareOutput(
+ \\pub export fn _start() u32 {
+ \\ var val: ?u32 = 5;
+ \\ while (val) |*v| {
+ \\ v.* -= 1;
+ \\ if (v.* == 2) {
+ \\ val = null;
+ \\ }
+ \\ }
+ \\ return 0;
+ \\}
+ , "0\n");
+ }
}
diff --git a/test/standalone.zig b/test/standalone.zig
index a483097f4a..9a32701ddd 100644
--- a/test/standalone.zig
+++ b/test/standalone.zig
@@ -37,6 +37,8 @@ pub fn addCases(cases: *tests.StandaloneContext) void {
if (std.Target.current.os.tag == .linux) {
cases.addBuildFile("test/standalone/pie/build.zig", .{});
}
+ // Try to build and run an Objective-C executable.
+ cases.addBuildFile("test/standalone/objc/build.zig", .{ .build_modes = true, .requires_macos_sdk = true });
// Ensure the development tools are buildable.
cases.add("tools/gen_spirv_spec.zig");
diff --git a/test/standalone/objc/Foo.h b/test/standalone/objc/Foo.h
new file mode 100644
index 0000000000..05cb7df39b
--- /dev/null
+++ b/test/standalone/objc/Foo.h
@@ -0,0 +1,7 @@
+#import <Foundation/Foundation.h>
+
+@interface Foo : NSObject
+
+- (NSString *)name;
+
+@end
diff --git a/test/standalone/objc/Foo.m b/test/standalone/objc/Foo.m
new file mode 100644
index 0000000000..6fc9b1edf0
--- /dev/null
+++ b/test/standalone/objc/Foo.m
@@ -0,0 +1,11 @@
+#import "Foo.h"
+
+@implementation Foo
+
+- (NSString *)name
+{
+ NSString *str = [[NSString alloc] initWithFormat:@"Zig"];
+ return str;
+}
+
+@end
diff --git a/test/standalone/objc/build.zig b/test/standalone/objc/build.zig
new file mode 100644
index 0000000000..7fdec514e7
--- /dev/null
+++ b/test/standalone/objc/build.zig
@@ -0,0 +1,36 @@
+const std = @import("std");
+const Builder = std.build.Builder;
+const CrossTarget = std.zig.CrossTarget;
+
+fn isRunnableTarget(t: CrossTarget) bool {
+ // TODO I think we might be able to run this on Linux via Darling.
+ // Add a check for that here, and return true if Darling is available.
+ if (t.isNative() and t.getOsTag() == .macos)
+ return true
+ else
+ return false;
+}
+
+pub fn build(b: *Builder) void {
+ const mode = b.standardReleaseOptions();
+ const target = b.standardTargetOptions(.{});
+
+ const test_step = b.step("test", "Test the program");
+
+ const exe = b.addExecutable("test", null);
+ b.default_step.dependOn(&exe.step);
+ exe.addIncludeDir(".");
+ exe.addCSourceFile("Foo.m", &[0][]const u8{});
+ exe.addCSourceFile("test.m", &[0][]const u8{});
+ exe.setBuildMode(mode);
+ exe.setTarget(target);
+ exe.linkLibC();
+ // TODO when we figure out how to ship framework stubs for cross-compilation,
+ // populate paths to the sysroot here.
+ exe.linkFramework("Foundation");
+
+ if (isRunnableTarget(target)) {
+ const run_cmd = exe.run();
+ test_step.dependOn(&run_cmd.step);
+ }
+}
diff --git a/test/standalone/objc/test.m b/test/standalone/objc/test.m
new file mode 100644
index 0000000000..3c81316788
--- /dev/null
+++ b/test/standalone/objc/test.m
@@ -0,0 +1,12 @@
+#import "Foo.h"
+#import <assert.h>
+
+int main(int argc, char *argv[])
+{
+ @autoreleasepool {
+ Foo *foo = [[Foo alloc] init];
+ NSString *result = [foo name];
+ assert([result isEqualToString:@"Zig"]);
+ return 0;
+ }
+}
diff --git a/test/tests.zig b/test/tests.zig
index d83701ff6a..a427bbefeb 100644
--- a/test/tests.zig
+++ b/test/tests.zig
@@ -391,7 +391,14 @@ pub fn addRuntimeSafetyTests(b: *build.Builder, test_filter: ?[]const u8, modes:
return cases.step;
}
-pub fn addStandaloneTests(b: *build.Builder, test_filter: ?[]const u8, modes: []const Mode, skip_non_native: bool, target: std.zig.CrossTarget) *build.Step {
+pub fn addStandaloneTests(
+ b: *build.Builder,
+ test_filter: ?[]const u8,
+ modes: []const Mode,
+ skip_non_native: bool,
+ enable_macos_sdk: bool,
+ target: std.zig.CrossTarget,
+) *build.Step {
const cases = b.allocator.create(StandaloneContext) catch unreachable;
cases.* = StandaloneContext{
.b = b,
@@ -400,6 +407,7 @@ pub fn addStandaloneTests(b: *build.Builder, test_filter: ?[]const u8, modes: []
.test_filter = test_filter,
.modes = modes,
.skip_non_native = skip_non_native,
+ .enable_macos_sdk = enable_macos_sdk,
.target = target,
};
@@ -768,7 +776,7 @@ pub const StackTracesContext = struct {
var buf = ArrayList(u8).init(b.allocator);
defer buf.deinit();
if (stderr.len != 0 and stderr[stderr.len - 1] == '\n') stderr = stderr[0 .. stderr.len - 1];
- var it = mem.split(stderr, "\n");
+ var it = mem.split(u8, stderr, "\n");
process_lines: while (it.next()) |line| {
if (line.len == 0) continue;
@@ -839,6 +847,7 @@ pub const StandaloneContext = struct {
test_filter: ?[]const u8,
modes: []const Mode,
skip_non_native: bool,
+ enable_macos_sdk: bool,
target: std.zig.CrossTarget,
pub fn addC(self: *StandaloneContext, root_src: []const u8) void {
@@ -849,9 +858,15 @@ pub const StandaloneContext = struct {
self.addAllArgs(root_src, false);
}
- pub fn addBuildFile(self: *StandaloneContext, build_file: []const u8, features: struct { build_modes: bool = false, cross_targets: bool = false }) void {
+ pub fn addBuildFile(self: *StandaloneContext, build_file: []const u8, features: struct {
+ build_modes: bool = false,
+ cross_targets: bool = false,
+ requires_macos_sdk: bool = false,
+ }) void {
const b = self.b;
+ if (features.requires_macos_sdk and !self.enable_macos_sdk) return;
+
const annotated_case_name = b.fmt("build {s}", .{build_file});
if (self.test_filter) |filter| {
if (mem.indexOf(u8, annotated_case_name, filter) == null) return;
diff --git a/test/translate_c.zig b/test/translate_c.zig
index 1ceaf15e5c..6ddc2107ee 100644
--- a/test/translate_c.zig
+++ b/test/translate_c.zig
@@ -3461,11 +3461,11 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
\\pub const MAY_NEED_PROMOTION_OCT = @import("std").zig.c_translation.promoteIntLiteral(c_int, 0o20000000000, .octal);
});
- // See __builtin_alloca_with_align comment in std.c.builtins
+ // See __builtin_alloca_with_align comment in std.zig.c_builtins
cases.add("demote un-implemented builtins",
\\#define FOO(X) __builtin_alloca_with_align((X), 8)
, &[_][]const u8{
- \\pub const FOO = @compileError("TODO implement function '__builtin_alloca_with_align' in std.c.builtins");
+ \\pub const FOO = @compileError("TODO implement function '__builtin_alloca_with_align' in std.zig.c_builtins");
});
cases.add("null sentinel arrays when initialized from string literal. Issue #8256",
@@ -3630,4 +3630,15 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
, &[_][]const u8{
\\pub const FOO = @import("std").zig.c_translation.Macros.U_SUFFIX;
});
+
+ cases.add("Simple array access of pointer with non-negative integer constant",
+ \\void foo(int *p) {
+ \\ p[0];
+ \\ p[1];
+ \\}
+ , &[_][]const u8{
+ \\_ = p[@intCast(c_uint, @as(c_int, 0))];
+ ,
+ \\_ = p[@intCast(c_uint, @as(c_int, 1))];
+ });
}