diff options
| author | hryx <codroid@gmail.com> | 2019-05-12 02:00:49 -0700 |
|---|---|---|
| committer | hryx <codroid@gmail.com> | 2019-05-12 02:00:49 -0700 |
| commit | 3787f3428625e830fd852a8f5a40c7d8a2d429f6 (patch) | |
| tree | 23fb493b9d2f07c7abe57955874682959936319a /test | |
| parent | 16aee1f58a80295f7599a8290d764a5c7040c373 (diff) | |
| parent | edcc7c72d1a684a8a16ca23ad26689f2cce4e803 (diff) | |
| download | zig-3787f3428625e830fd852a8f5a40c7d8a2d429f6.tar.gz zig-3787f3428625e830fd852a8f5a40c7d8a2d429f6.zip | |
Merge branch 'master' into rebased
Diffstat (limited to 'test')
| -rw-r--r-- | test/compile_errors.zig | 113 | ||||
| -rw-r--r-- | test/runtime_safety.zig | 20 | ||||
| -rw-r--r-- | test/stage1/behavior.zig | 3 | ||||
| -rw-r--r-- | test/stage1/behavior/bit_shifting.zig | 10 | ||||
| -rw-r--r-- | test/stage1/behavior/bugs/1607.zig | 15 | ||||
| -rw-r--r-- | test/stage1/behavior/bugs/2114.zig | 19 | ||||
| -rw-r--r-- | test/stage1/behavior/bugs/2346.zig | 6 | ||||
| -rw-r--r-- | test/stage1/behavior/enum.zig | 39 | ||||
| -rw-r--r-- | test/stage1/behavior/math.zig | 7 | ||||
| -rw-r--r-- | test/stage1/behavior/pointers.zig | 50 | ||||
| -rw-r--r-- | test/stage1/behavior/sizeof_and_typeof.zig | 7 | ||||
| -rw-r--r-- | test/stage1/behavior/struct.zig | 22 | ||||
| -rw-r--r-- | test/stage1/behavior/syntax.zig | 8 | ||||
| -rw-r--r-- | test/stage1/behavior/union.zig | 37 | ||||
| -rw-r--r-- | test/tests.zig | 36 | ||||
| -rw-r--r-- | test/translate_c.zig | 215 |
16 files changed, 522 insertions, 85 deletions
diff --git a/test/compile_errors.zig b/test/compile_errors.zig index a31605b02a..297673235d 100644 --- a/test/compile_errors.zig +++ b/test/compile_errors.zig @@ -3,6 +3,64 @@ const builtin = @import("builtin"); pub fn addCases(cases: *tests.CompileErrorContext) void { cases.add( + "peer cast then implicit cast const pointer to mutable C pointer", + \\export fn func() void { + \\ var strValue: [*c]u8 = undefined; + \\ strValue = strValue orelse c""; + \\} + , + "tmp.zig:3:32: error: cast discards const qualifier", + ); + + cases.add( + "overflow in enum value allocation", + \\const Moo = enum(u8) { + \\ Last = 255, + \\ Over, + \\}; + \\pub fn main() void { + \\ var y = Moo.Last; + \\} + , + "tmp.zig:3:5: error: enumeration value 256 too large for type 'u8'", + ); + + cases.add( + "attempt to cast enum literal to error", + \\export fn entry() void { + \\ switch (error.Hi) { + \\ .Hi => {}, + \\ } + \\} + , + "tmp.zig:3:9: error: expected type 'error{Hi}', found '(enum literal)'", + ); + + cases.add( + "@sizeOf bad type", + \\export fn entry() void { + \\ _ = @sizeOf(@typeOf(null)); + \\} + , + "tmp.zig:2:17: error: no size available for type '(null)'", + ); + + cases.add( + "Generic function where return type is self-referenced", + \\fn Foo(comptime T: type) Foo(T) { + \\ return struct{ x: T }; + \\} + \\export fn entry() void { + \\ const t = Foo(u32) { + \\ .x = 1 + \\ }; + \\} + , + "tmp.zig:1:29: error: evaluation exceeded 1000 backwards branches", + "tmp.zig:1:29: note: called from here", + ); + + cases.add( "@ptrToInt 0 to non optional pointer", \\export fn entry() void { \\ var b = @intToPtr(*i32, 0); @@ -553,15 +611,6 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { ); cases.add( - "threadlocal qualifier on local variable", - \\export fn entry() void { - \\ threadlocal var x: i32 = 1234; - \\} - , - "tmp.zig:2:5: error: function-local variable 'x' cannot be threadlocal", - ); - - cases.add( "@bitCast same size but bit count mismatch", \\export fn entry(byte: u8) void { \\ var oops = @bitCast(u7, byte); @@ -839,7 +888,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { \\ _ = &x == null; \\} , - "tmp.zig:3:12: error: only optionals (not '*i32') can compare to null", + "tmp.zig:3:12: error: comparison of '*i32' with null", ); cases.add( @@ -5347,8 +5396,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { "tmp.zig:12:20: note: referenced here", ); - cases.add( - "specify enum tag type that is too small", + cases.add("specify enum tag type that is too small", \\const Small = enum (u2) { \\ One, \\ Two, @@ -5360,9 +5408,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { \\export fn entry() void { \\ var x = Small.One; \\} - , - "tmp.zig:1:21: error: 'u2' too small to hold all bits; must be at least 'u3'", - ); + , "tmp.zig:6:5: error: enumeration value 4 too large for type 'u2'"); cases.add( "specify non-integer enum tag type", @@ -5413,22 +5459,6 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { ); cases.add( - "non unsigned integer enum tag type", - \\const Small = enum(i2) { - \\ One, - \\ Two, - \\ Three, - \\ Four, - \\}; - \\ - \\export fn entry() void { - \\ var y = Small.Two; - \\} - , - "tmp.zig:1:20: error: expected unsigned integer, found 'i2'", - ); - - cases.add( "struct fields with value assignments", \\const MultipleChoice = struct { \\ A: i32 = 20, @@ -5486,8 +5516,8 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { \\ var x = MultipleChoice.C; \\} , - "tmp.zig:6:9: error: enum tag value 60 already taken", - "tmp.zig:4:9: note: other occurrence here", + "tmp.zig:6:5: error: enum tag value 60 already taken", + "tmp.zig:4:5: note: other occurrence here", ); cases.add( @@ -5892,4 +5922,21 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { , "tmp.zig:3:23: error: expected type '[]u32', found '*const u32'", ); + + cases.add( + "for loop body expression ignored", + \\fn returns() usize { + \\ return 2; + \\} + \\export fn f1() void { + \\ for ("hello") |_| returns(); + \\} + \\export fn f2() void { + \\ var x: anyerror!i32 = error.Bad; + \\ for ("hello") |_| returns() else unreachable; + \\} + , + "tmp.zig:5:30: error: expression value is ignored", + "tmp.zig:9:30: error: expression value is ignored", + ); } diff --git a/test/runtime_safety.zig b/test/runtime_safety.zig index 78b45ac05f..b10accd213 100644 --- a/test/runtime_safety.zig +++ b/test/runtime_safety.zig @@ -1,6 +1,26 @@ const tests = @import("tests.zig"); pub fn addCases(cases: *tests.CompareOutputContext) void { + cases.addRuntimeSafety(".? operator on null pointer", + \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn { + \\ @import("std").os.exit(126); + \\} + \\pub fn main() void { + \\ var ptr: ?*i32 = null; + \\ var b = ptr.?; + \\} + ); + + cases.addRuntimeSafety(".? operator on C pointer", + \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn { + \\ @import("std").os.exit(126); + \\} + \\pub fn main() void { + \\ var ptr: [*c]i32 = null; + \\ var b = ptr.?; + \\} + ); + cases.addRuntimeSafety("@ptrToInt address zero to non-optional pointer", \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn { \\ @import("std").os.exit(126); diff --git a/test/stage1/behavior.zig b/test/stage1/behavior.zig index da90660bf1..bc3be172ab 100644 --- a/test/stage1/behavior.zig +++ b/test/stage1/behavior.zig @@ -20,9 +20,12 @@ comptime { _ = @import("behavior/bugs/1442.zig"); _ = @import("behavior/bugs/1486.zig"); _ = @import("behavior/bugs/1500.zig"); + _ = @import("behavior/bugs/1607.zig"); _ = @import("behavior/bugs/1851.zig"); _ = @import("behavior/bugs/1914.zig"); _ = @import("behavior/bugs/2006.zig"); + _ = @import("behavior/bugs/2114.zig"); + _ = @import("behavior/bugs/2346.zig"); _ = @import("behavior/bugs/394.zig"); _ = @import("behavior/bugs/421.zig"); _ = @import("behavior/bugs/529.zig"); diff --git a/test/stage1/behavior/bit_shifting.zig b/test/stage1/behavior/bit_shifting.zig index 610acc06c2..1877c8cdcb 100644 --- a/test/stage1/behavior/bit_shifting.zig +++ b/test/stage1/behavior/bit_shifting.zig @@ -86,3 +86,13 @@ fn testShardedTable(comptime Key: type, comptime mask_bit_count: comptime_int, c expect(table.get(@intCast(Key, i)) == node); } } + +// #2225 +test "comptime shr of BigInt" { + comptime { + var n0 = 0xdeadbeef0000000000000000; + std.debug.assert(n0 >> 64 == 0xdeadbeef); + var n1 = 17908056155735594659; + std.debug.assert(n1 >> 64 == 0); + } +} diff --git a/test/stage1/behavior/bugs/1607.zig b/test/stage1/behavior/bugs/1607.zig new file mode 100644 index 0000000000..f32eeb03d6 --- /dev/null +++ b/test/stage1/behavior/bugs/1607.zig @@ -0,0 +1,15 @@ +const std = @import("std"); +const testing = std.testing; + +const a = []u8{ 1, 2, 3 }; + +fn checkAddress(s: []const u8) void { + for (s) |*i, j| { + testing.expect(i == &a[j]); + } +} + +test "slices pointing at the same address as global array." { + checkAddress(a); + comptime checkAddress(a); +} diff --git a/test/stage1/behavior/bugs/2114.zig b/test/stage1/behavior/bugs/2114.zig new file mode 100644 index 0000000000..61ea2675b9 --- /dev/null +++ b/test/stage1/behavior/bugs/2114.zig @@ -0,0 +1,19 @@ +const std = @import("std"); +const expect = std.testing.expect; +const math = std.math; + +fn ctz(x: var) usize { + return @ctz(x); +} + +test "fixed" { + testClz(); + comptime testClz(); +} + +fn testClz() void { + expect(ctz(u128(0x40000000000000000000000000000000)) == 126); + expect(math.rotl(u128, u128(0x40000000000000000000000000000000), u8(1)) == u128(0x80000000000000000000000000000000)); + expect(ctz(u128(0x80000000000000000000000000000000)) == 127); + expect(ctz(math.rotl(u128, u128(0x40000000000000000000000000000000), u8(1))) == 127); +} diff --git a/test/stage1/behavior/bugs/2346.zig b/test/stage1/behavior/bugs/2346.zig new file mode 100644 index 0000000000..c8cea34813 --- /dev/null +++ b/test/stage1/behavior/bugs/2346.zig @@ -0,0 +1,6 @@ +test "fixed" { + const a: *void = undefined; + const b: *[1]void = a; + const c: *[0]u8 = undefined; + const d: []u8 = c; +} diff --git a/test/stage1/behavior/enum.zig b/test/stage1/behavior/enum.zig index f584fc265a..8a5edaa3dd 100644 --- a/test/stage1/behavior/enum.zig +++ b/test/stage1/behavior/enum.zig @@ -923,3 +923,42 @@ test "peer type resolution with enum literal" { expect(Items.two == .two); expect(.two == Items.two); } + +test "enum literal in array literal" { + const Items = enum { + one, + two, + }; + + const array = []Items { + .one, + .two, + }; + + expect(array[0] == .one); + expect(array[1] == .two); +} + +test "signed integer as enum tag" { + const SignedEnum = enum(i2) { + A0 = -1, + A1 = 0, + A2 = 1, + }; + + expect(@enumToInt(SignedEnum.A0) == -1); + expect(@enumToInt(SignedEnum.A1) == 0); + expect(@enumToInt(SignedEnum.A2) == 1); +} + +test "enum value allocation" { + const LargeEnum = enum(u32) { + A0 = 0x80000000, + A1, + A2, + }; + + expect(@enumToInt(LargeEnum.A0) == 0x80000000); + expect(@enumToInt(LargeEnum.A1) == 0x80000001); + expect(@enumToInt(LargeEnum.A2) == 0x80000002); +} diff --git a/test/stage1/behavior/math.zig b/test/stage1/behavior/math.zig index 23dc6d1feb..acbd9209df 100644 --- a/test/stage1/behavior/math.zig +++ b/test/stage1/behavior/math.zig @@ -632,3 +632,10 @@ fn testNanEqNan(comptime F: type) void { expect(!(nan1 < nan2)); expect(!(nan1 <= nan2)); } + +test "128-bit multiplication" { + var a: i128 = 3; + var b: i128 = 2; + var c = a * b; + expect(c == 6); +} diff --git a/test/stage1/behavior/pointers.zig b/test/stage1/behavior/pointers.zig index be47718358..50b36fe583 100644 --- a/test/stage1/behavior/pointers.zig +++ b/test/stage1/behavior/pointers.zig @@ -150,3 +150,53 @@ test "allowzero pointer and slice" { expect(@typeInfo(@typeOf(ptr)).Pointer.is_allowzero); expect(@typeInfo(@typeOf(slice)).Pointer.is_allowzero); } + +test "assign null directly to C pointer and test null equality" { + var x: [*c]i32 = null; + expect(x == null); + expect(null == x); + expect(!(x != null)); + expect(!(null != x)); + if (x) |same_x| { + @panic("fail"); + } + var otherx: i32 = undefined; + expect((x orelse &otherx) == &otherx); + + const y: [*c]i32 = null; + comptime expect(y == null); + comptime expect(null == y); + comptime expect(!(y != null)); + comptime expect(!(null != y)); + if (y) |same_y| @panic("fail"); + const othery: i32 = undefined; + comptime expect((y orelse &othery) == &othery); + + var n: i32 = 1234; + var x1: [*c]i32 = &n; + expect(!(x1 == null)); + expect(!(null == x1)); + expect(x1 != null); + expect(null != x1); + expect(x1.?.* == 1234); + if (x1) |same_x1| { + expect(same_x1.* == 1234); + } else { + @panic("fail"); + } + expect((x1 orelse &otherx) == x1); + + const nc: i32 = 1234; + const y1: [*c]const i32 = &nc; + comptime expect(!(y1 == null)); + comptime expect(!(null == y1)); + comptime expect(y1 != null); + comptime expect(null != y1); + comptime expect(y1.?.* == 1234); + if (y1) |same_y1| { + expect(same_y1.* == 1234); + } else { + @compileError("fail"); + } + comptime expect((y1 orelse &othery) == y1); +} diff --git a/test/stage1/behavior/sizeof_and_typeof.zig b/test/stage1/behavior/sizeof_and_typeof.zig index 58a6c81759..cfad311e06 100644 --- a/test/stage1/behavior/sizeof_and_typeof.zig +++ b/test/stage1/behavior/sizeof_and_typeof.zig @@ -67,3 +67,10 @@ test "@bitOffsetOf" { expect(@byteOffsetOf(A, "f") * 8 == @bitOffsetOf(A, "f")); expect(@byteOffsetOf(A, "g") * 8 == @bitOffsetOf(A, "g")); } + +test "@sizeOf on compile-time types" { + expect(@sizeOf(comptime_int) == 0); + expect(@sizeOf(comptime_float) == 0); + expect(@sizeOf(@typeOf(.hi)) == 0); + expect(@sizeOf(@typeOf(type)) == 0); +} diff --git a/test/stage1/behavior/struct.zig b/test/stage1/behavior/struct.zig index 62fb41ca28..114f06982b 100644 --- a/test/stage1/behavior/struct.zig +++ b/test/stage1/behavior/struct.zig @@ -2,8 +2,7 @@ const std = @import("std"); const expect = std.testing.expect; const expectEqualSlices = std.testing.expectEqualSlices; const builtin = @import("builtin"); -const maxInt = std.math.maxInt; - +const maxInt = std.math.maxInt; const StructWithNoFields = struct { fn add(a: i32, b: i32) i32 { return a + b; @@ -505,3 +504,22 @@ test "packed struct with u0 field access" { var s = S{ .f0 = 0 }; comptime expect(s.f0 == 0); } + +const S0 = struct{ + bar: S1, + + pub const S1 = struct{ + value: u8, + }; + + fn init() @This() { + return S0{ .bar = S1{ .value = 123 } }; + } +}; + +var g_foo: S0 = S0.init(); + +test "access to global struct fields" { + g_foo.bar.value = 42; + expect(g_foo.bar.value == 42); +} diff --git a/test/stage1/behavior/syntax.zig b/test/stage1/behavior/syntax.zig index 451e396142..12df8a4315 100644 --- a/test/stage1/behavior/syntax.zig +++ b/test/stage1/behavior/syntax.zig @@ -1,6 +1,14 @@ // Test trailing comma syntax // zig fmt: off +extern var a: c_int; +extern "c" var b: c_int; +export var c: c_int = 0; +threadlocal var d: c_int; +extern threadlocal var e: c_int; +extern "c" threadlocal var f: c_int; +export threadlocal var g: c_int = 0; + const struct_trailing_comma = struct { x: i32, y: i32, }; const struct_no_comma = struct { x: i32, y: i32 }; const struct_fn_no_comma = struct { fn m() void {} y: i32 }; diff --git a/test/stage1/behavior/union.zig b/test/stage1/behavior/union.zig index bbba867667..b8bb9a51b8 100644 --- a/test/stage1/behavior/union.zig +++ b/test/stage1/behavior/union.zig @@ -365,3 +365,40 @@ test "@enumToInt works on unions" { expect(@enumToInt(b) == 1); expect(@enumToInt(c) == 2); } + +const Attribute = union(enum) { + A: bool, + B: u8, +}; + +fn setAttribute(attr: Attribute) void {} + +fn Setter(attr: Attribute) type { + return struct{ + fn set() void { + setAttribute(attr); + } + }; +} + +test "comptime union field value equality" { + const a0 = Setter(Attribute{ .A = false }); + const a1 = Setter(Attribute{ .A = true }); + const a2 = Setter(Attribute{ .A = false }); + + const b0 = Setter(Attribute{ .B = 5 }); + const b1 = Setter(Attribute{ .B = 9 }); + const b2 = Setter(Attribute{ .B = 5 }); + + expect(a0 == a0); + expect(a1 == a1); + expect(a0 == a2); + + expect(b0 == b0); + expect(b1 == b1); + expect(b0 == b2); + + expect(a0 != b0); + expect(a0 != a1); + expect(b0 != b1); +} diff --git a/test/tests.zig b/test/tests.zig index 61fd0426f1..4b67cf0f6c 100644 --- a/test/tests.zig +++ b/test/tests.zig @@ -903,6 +903,7 @@ pub const TranslateCContext = struct { sources: ArrayList(SourceFile), expected_lines: ArrayList([]const u8), allow_warnings: bool, + stage2: bool, const SourceFile = struct { filename: []const u8, @@ -955,7 +956,8 @@ pub const TranslateCContext = struct { var zig_args = ArrayList([]const u8).init(b.allocator); zig_args.append(b.zig_exe) catch unreachable; - zig_args.append("translate-c") catch unreachable; + const translate_c_cmd = if (self.case.stage2) "translate-c-2" else "translate-c"; + zig_args.append(translate_c_cmd) catch unreachable; zig_args.append(b.pathFromRoot(root_src)) catch unreachable; warn("Test {}/{} {}...", self.test_index + 1, self.context.test_index, self.name); @@ -1052,6 +1054,7 @@ pub const TranslateCContext = struct { .sources = ArrayList(TestCase.SourceFile).init(self.b.allocator), .expected_lines = ArrayList([]const u8).init(self.b.allocator), .allow_warnings = allow_warnings, + .stage2 = false, }; tc.addSourceFile(filename, source); @@ -1072,6 +1075,34 @@ pub const TranslateCContext = struct { self.addCase(tc); } + pub fn add_both(self: *TranslateCContext, name: []const u8, source: []const u8, expected_lines: ...) void { + for ([]bool{ false, true }) |stage2| { + const tc = self.create(false, "source.h", name, source, expected_lines); + tc.stage2 = stage2; + self.addCase(tc); + } + } + + pub fn addC_both(self: *TranslateCContext, name: []const u8, source: []const u8, expected_lines: ...) void { + for ([]bool{ false, true }) |stage2| { + const tc = self.create(false, "source.c", name, source, expected_lines); + tc.stage2 = stage2; + self.addCase(tc); + } + } + + pub fn add_2(self: *TranslateCContext, name: []const u8, source: []const u8, expected_lines: ...) void { + const tc = self.create(false, "source.h", name, source, expected_lines); + tc.stage2 = true; + self.addCase(tc); + } + + pub fn addC_2(self: *TranslateCContext, name: []const u8, source: []const u8, expected_lines: ...) void { + const tc = self.create(false, "source.c", name, source, expected_lines); + tc.stage2 = true; + self.addCase(tc); + } + pub fn addAllowWarnings(self: *TranslateCContext, name: []const u8, source: []const u8, expected_lines: ...) void { const tc = self.create(true, "source.h", name, source, expected_lines); self.addCase(tc); @@ -1080,7 +1111,8 @@ pub const TranslateCContext = struct { pub fn addCase(self: *TranslateCContext, case: *const TestCase) void { const b = self.b; - const annotated_case_name = fmt.allocPrint(self.b.allocator, "translate-c {}", case.name) catch unreachable; + const translate_c_cmd = if (case.stage2) "translate-c-2" else "translate-c"; + const annotated_case_name = fmt.allocPrint(self.b.allocator, "{} {}", translate_c_cmd, case.name) catch unreachable; 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 cd8e7cb6d0..930442f293 100644 --- a/test/translate_c.zig +++ b/test/translate_c.zig @@ -1,7 +1,66 @@ const tests = @import("tests.zig"); const builtin = @import("builtin"); +// add_both - test for stage1 and stage2, in #include mode +// add - test stage1 only, in #include mode +// add_2 - test stage2 only, in #include mode +// addC_both - test for stage1 and stage2, in -c mode +// addC - test stage1 only, in -c mode +// addC_2 - test stage2 only, in -c mode + pub fn addCases(cases: *tests.TranslateCContext) void { + /////////////// Cases that pass for both stage1/stage2 //////////////// + cases.add_both("simple function prototypes", + \\void __attribute__((noreturn)) foo(void); + \\int bar(void); + , + \\pub extern fn foo() noreturn; + \\pub extern fn bar() c_int; + ); + + /////////////// Cases that pass for only stage2 //////////////// + cases.add_2("Parameterless function prototypes", + \\void a() {} + \\void b(void) {} + \\void c(); + \\void d(void); + , + \\pub export fn a() void {} + \\pub export fn b() void {} + \\pub extern fn c(...) void; + \\pub extern fn d() void; + ); + + cases.add_2("simple function definition", + \\void foo(void) {} + \\static void bar(void) {} + , + \\pub export fn foo() void {} + \\pub extern fn bar() void {} + ); + + /////////////// Cases for only stage1 which are TODO items for stage2 //////////////// + + cases.add("macro with left shift", + \\#define REDISMODULE_READ (1<<0) + , + \\pub const REDISMODULE_READ = 1 << 0; + ); + + cases.add("casting pointers to ints and ints to pointers", + \\void foo(void); + \\void bar(void) { + \\ void *func_ptr = foo; + \\ void (*typed_func_ptr)(void) = (void (*)(void)) (unsigned long) func_ptr; + \\} + , + \\pub extern fn foo() void; + \\pub fn bar() void { + \\ var func_ptr: ?*c_void = @ptrCast(?*c_void, foo); + \\ var typed_func_ptr: ?extern fn() void = @intToPtr(?extern fn() void, c_ulong(@ptrToInt(func_ptr))); + \\} + ); + if (builtin.os != builtin.Os.windows) { // Windows treats this as an enum with type c_int cases.add("big negative enum init values when C ABI supports long long enums", @@ -72,7 +131,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\ _ = c"void foo(void)"; \\} ); - + cases.add("ignore result", \\void foo() { \\ int a; @@ -648,11 +707,11 @@ pub fn addCases(cases: *tests.TranslateCContext) void { , \\pub export fn and_or_none_bool(a: c_int, b: f32, c: ?*c_void) c_int { \\ if ((a != 0) and (b != 0)) return 0; - \\ if ((b != 0) and (c != 0)) return 1; - \\ if ((a != 0) and (c != 0)) return 2; + \\ if ((b != 0) and (c != null)) return 1; + \\ if ((a != 0) and (c != null)) return 2; \\ if ((a != 0) or (b != 0)) return 3; - \\ if ((b != 0) or (c != 0)) return 4; - \\ if ((a != 0) or (c != 0)) return 5; + \\ if ((b != 0) or (c != null)) return 4; + \\ if ((a != 0) or (c != null)) return 5; \\ return 6; \\} ); @@ -832,7 +891,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\} , \\pub export fn foo() [*c]c_int { - \\ return 0; + \\ return null; \\} ); @@ -1334,7 +1393,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\} , \\fn ptrcast(a: [*c]c_int) [*c]f32 { - \\ return @ptrCast([*c]f32, a); + \\ return @ptrCast([*c]f32, @alignCast(@alignOf(f32), a)); \\} ); @@ -1360,7 +1419,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\ return !(a == 0); \\ return !(a != 0); \\ return !(b != 0); - \\ return !(c != 0); + \\ return !(c != null); \\} ); @@ -1417,7 +1476,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\pub fn if_none_bool(a: c_int, b: f32, c: ?*c_void, d: enum_SomeEnum) c_int { \\ if (a != 0) return 0; \\ if (b != 0) return 1; - \\ if (c != 0) return 2; + \\ if (c != null) return 2; \\ if (d != @bitCast(enum_SomeEnum, @TagType(enum_SomeEnum)(0))) return 3; \\ return 4; \\} @@ -1434,7 +1493,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\pub fn while_none_bool(a: c_int, b: f32, c: ?*c_void) c_int { \\ while (a != 0) return 0; \\ while (b != 0) return 1; - \\ while (c != 0) return 2; + \\ while (c != null) return 2; \\ return 3; \\} ); @@ -1450,7 +1509,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\pub fn for_none_bool(a: c_int, b: f32, c: ?*c_void) c_int { \\ while (a != 0) return 0; \\ while (b != 0) return 1; - \\ while (c != 0) return 2; + \\ while (c != null) return 2; \\ return 3; \\} ); @@ -1497,14 +1556,6 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\} ); - cases.addC("Parameterless function prototypes", - \\void foo() {} - \\void bar(void) {} - , - \\pub export fn foo() void {} - \\pub export fn bar() void {} - ); - cases.addC( "u integer suffix after 0 (zero) in macro definition", "#define ZERO 0U", @@ -1553,33 +1604,101 @@ pub fn addCases(cases: *tests.TranslateCContext) void { "pub const NOT_ZERO = ~c_uint(0);", ); - // cases.add("empty array with initializer", - // "int a[4] = {};" - // , - // "pub var a: [4]c_int = [1]c_int{0} ** 4;" - // ); - - // cases.add("array with initialization", - // "int a[4] = {1, 2, 3, 4};" - // , - // "pub var a: [4]c_int = [4]c_int{1, 2, 3, 4};" - // ); - - // cases.add("array with incomplete initialization", - // "int a[4] = {3, 4};" - // , - // "pub var a: [4]c_int = [2]c_int{3, 4} ++ ([1]c_int{0} ** 2);" - // ); - - // cases.add("2D array with initialization", - // "int a[3][3] = { {1, 2, 3}, {4, 5, 6}, {7, 8, 9} };" - // , - // "pub var a: [3][3]c_int = [3][3]c_int{[3]c_int{1, 2, 3}, [3]c_int{4, 5, 6}, [3]c_int{7, 8, 9}};" - // ); - - // cases.add("2D array with incomplete initialization", - // "int a[3][3] = { {1, 2}, {4, 5, 6} };" - // , - // "pub var a: [3][3]c_int = [2][3]c_int{[2]c_int{1, 2} ++ [1]c_int{0}, [3]c_int{4, 5, 6}} ++ [1][3]c_int{[1]c_int{0} ** 3};" - // ); + cases.addC("implicit casts", + \\#include <stdbool.h> + \\ + \\void fn_int(int x); + \\void fn_f32(float x); + \\void fn_f64(double x); + \\void fn_char(char x); + \\void fn_bool(bool x); + \\void fn_ptr(void *x); + \\ + \\void call(int q) { + \\ fn_int(3.0f); + \\ fn_int(3.0); + \\ fn_int(3.0L); + \\ fn_int('ABCD'); + \\ fn_f32(3); + \\ fn_f64(3); + \\ fn_char('3'); + \\ fn_char('\x1'); + \\ fn_char(0); + \\ fn_f32(3.0f); + \\ fn_f64(3.0); + \\ fn_bool(123); + \\ fn_bool(0); + \\ fn_bool(&fn_int); + \\ fn_int(&fn_int); + \\ fn_ptr(42); + \\} + , + \\pub extern fn fn_int(x: c_int) void; + \\pub extern fn fn_f32(x: f32) void; + \\pub extern fn fn_f64(x: f64) void; + \\pub extern fn fn_char(x: u8) void; + \\pub extern fn fn_bool(x: bool) void; + \\pub extern fn fn_ptr(x: ?*c_void) void; + \\pub export fn call(q: c_int) void { + \\ fn_int(@floatToInt(c_int, 3.000000)); + \\ fn_int(@floatToInt(c_int, 3.000000)); + \\ fn_int(@floatToInt(c_int, 3.000000)); + \\ fn_int(1094861636); + \\ fn_f32(@intToFloat(f32, 3)); + \\ fn_f64(@intToFloat(f64, 3)); + \\ fn_char(u8('3')); + \\ fn_char(u8('\x01')); + \\ fn_char(u8(0)); + \\ fn_f32(3.000000); + \\ fn_f64(3.000000); + \\ fn_bool(true); + \\ fn_bool(false); + \\ fn_bool(@ptrToInt(&fn_int) != 0); + \\ fn_int(@intCast(c_int, @ptrToInt(&fn_int))); + \\ fn_ptr(@intToPtr(?*c_void, 42)); + \\} + ); + + cases.addC("pointer conversion with different alignment", + \\void test_ptr_cast() { + \\ void *p; + \\ { + \\ char *to_char = (char *)p; + \\ short *to_short = (short *)p; + \\ int *to_int = (int *)p; + \\ long long *to_longlong = (long long *)p; + \\ } + \\ { + \\ char *to_char = p; + \\ short *to_short = p; + \\ int *to_int = p; + \\ long long *to_longlong = p; + \\ } + \\} + , + \\pub export fn test_ptr_cast() void { + \\ var p: ?*c_void = undefined; + \\ { + \\ var to_char: [*c]u8 = @ptrCast([*c]u8, @alignCast(@alignOf(u8), p)); + \\ var to_short: [*c]c_short = @ptrCast([*c]c_short, @alignCast(@alignOf(c_short), p)); + \\ var to_int: [*c]c_int = @ptrCast([*c]c_int, @alignCast(@alignOf(c_int), p)); + \\ var to_longlong: [*c]c_longlong = @ptrCast([*c]c_longlong, @alignCast(@alignOf(c_longlong), p)); + \\ } + \\ { + \\ var to_char: [*c]u8 = @ptrCast([*c]u8, @alignCast(@alignOf(u8), p)); + \\ var to_short: [*c]c_short = @ptrCast([*c]c_short, @alignCast(@alignOf(c_short), p)); + \\ var to_int: [*c]c_int = @ptrCast([*c]c_int, @alignCast(@alignOf(c_int), p)); + \\ var to_longlong: [*c]c_longlong = @ptrCast([*c]c_longlong, @alignCast(@alignOf(c_longlong), p)); + \\ } + \\} + ); + + /////////////// Cases for only stage1 because stage2 behavior is better //////////////// + cases.addC("Parameterless function prototypes", + \\void foo() {} + \\void bar(void) {} + , + \\pub export fn foo() void {} + \\pub export fn bar() void {} + ); } |
