2017-04-19 13:59:20 -07:00
const tests = @import ( " tests.zig " ) ;
2020-02-25 00:43:21 -08:00
const std = @import ( " std " ) ;
2020-02-25 22:18:23 -08:00
const CrossTarget = std . zig . CrossTarget ;
2017-04-19 13:59:20 -07:00
2019-12-12 11:14:55 -08:00
pub fn addCases ( cases : * tests . TranslateCContext ) void {
2020-03-08 01:26:53 -08:00
cases . add ( " nested loops without blocks " ,
\\void foo() {
\\ while (0) while (0) {}
\\ for (;;) while (0);
\\ for (;;) do {} while (0);
\\}
, & [ _ ] [ ] const u8 {
\\pub export fn foo() void {
\\ while (@as(c_int, 0) != 0) while (@as(c_int, 0) != 0) {};
\\ while (true) while (@as(c_int, 0) != 0) {};
\\ while (true) while (true) {
\\ if (!(@as(c_int, 0) != 0)) break;
\\ };
\\}
} ) ;
2020-03-05 01:22:50 -08:00
cases . add ( " macro comma operator " ,
\\#define foo (foo, bar)
2020-03-06 01:03:56 -08:00
\\#define bar(x) (&x, +3, 4 == 4, 5 * 6, baz(1, 2), 2 % 2, baz(1,2))
2020-03-05 01:22:50 -08:00
, & [ _ ] [ ] const u8 {
\\pub const foo = blk: {
\\ _ = foo;
\\ break :blk bar;
\\};
,
\\pub inline fn bar(x: var) @TypeOf(baz(1, 2)) {
\\ return blk: {
2020-03-08 01:26:53 -08:00
\\ _ = &x;
2020-03-05 01:22:50 -08:00
\\ _ = 3;
2020-03-06 01:03:56 -08:00
\\ _ = 4 == 4;
2020-03-05 01:22:50 -08:00
\\ _ = 5 * 6;
\\ _ = baz(1, 2);
2020-03-06 01:03:56 -08:00
\\ _ = 2 % 2;
2020-03-05 01:22:50 -08:00
\\ break :blk baz(1, 2);
\\ };
\\}
} ) ;
2020-03-05 02:15:12 -08:00
cases . add ( " macro keyword define " ,
\\#define foo 1
\\#define inline 2
, & [ _ ] [ ] const u8 {
\\pub const foo = 1;
,
\\pub const @"inline" = 2;
} ) ;
2020-02-14 13:41:18 -08:00
cases . add ( " macro line continuation " ,
\\#define FOO -\
\\BAR
, & [ _ ] [ ] const u8 {
\\pub const FOO = -BAR;
} ) ;
2020-03-05 01:46:45 -08:00
cases . add ( " struct with atomic field " ,
\\struct arcan_shmif_cont {
\\ struct arcan_shmif_page* addr;
\\};
\\struct arcan_shmif_page {
\\ volatile _Atomic int abufused[12];
\\};
, & [ _ ] [ ] const u8 {
\\pub const struct_arcan_shmif_page = //
,
\\warning: unsupported type: 'Atomic'
\\ @OpaqueType(); //
,
\\ warning: struct demoted to opaque type - unable to translate type of field abufused
, // TODO should be `addr: *struct_arcan_shmif_page`
\\pub const struct_arcan_shmif_cont = extern struct {
\\ addr: [*c]struct_arcan_shmif_page,
\\};
} ) ;
2020-01-30 14:16:52 -08:00
cases . add ( " function prototype translated as optional " ,
\\typedef void (*fnptr_ty)(void);
\\typedef __attribute__((cdecl)) void (*fnptr_attr_ty)(void);
\\struct foo {
\\ __attribute__((cdecl)) void (*foo)(void);
\\ void (*bar)(void);
\\ fnptr_ty baz;
\\ fnptr_attr_ty qux;
\\};
, & [ _ ] [ ] const u8 {
\\pub const fnptr_ty = ?fn () callconv(.C) void;
\\pub const fnptr_attr_ty = ?fn () callconv(.C) void;
\\pub const struct_foo = extern struct {
\\ foo: ?fn () callconv(.C) void,
\\ bar: ?fn () callconv(.C) void,
\\ baz: fnptr_ty,
\\ qux: fnptr_attr_ty,
\\};
} ) ;
2020-01-29 00:55:40 -08:00
cases . add ( " function prototype with parenthesis " ,
\\void (f0) (void *L);
\\void ((f1)) (void *L);
\\void (((f2))) (void *L);
, & [ _ ] [ ] const u8 {
\\pub extern fn f0(L: ?*c_void) void;
\\pub extern fn f1(L: ?*c_void) void;
\\pub extern fn f2(L: ?*c_void) void;
} ) ;
2020-01-20 14:13:20 -08:00
cases . add ( " array initializer w/ typedef " ,
\\typedef unsigned char uuid_t[16];
\\static const uuid_t UUID_NULL __attribute__ ((unused)) = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
, & [ _ ] [ ] const u8 {
\\pub const uuid_t = [16]u8;
2020-01-30 10:53:35 -08:00
\\pub const UUID_NULL: uuid_t = [16]u8{
2020-01-20 14:13:20 -08:00
\\ @bitCast(u8, @truncate(i8, @as(c_int, 0))),
\\ @bitCast(u8, @truncate(i8, @as(c_int, 0))),
\\ @bitCast(u8, @truncate(i8, @as(c_int, 0))),
\\ @bitCast(u8, @truncate(i8, @as(c_int, 0))),
\\ @bitCast(u8, @truncate(i8, @as(c_int, 0))),
\\ @bitCast(u8, @truncate(i8, @as(c_int, 0))),
\\ @bitCast(u8, @truncate(i8, @as(c_int, 0))),
\\ @bitCast(u8, @truncate(i8, @as(c_int, 0))),
\\ @bitCast(u8, @truncate(i8, @as(c_int, 0))),
\\ @bitCast(u8, @truncate(i8, @as(c_int, 0))),
\\ @bitCast(u8, @truncate(i8, @as(c_int, 0))),
\\ @bitCast(u8, @truncate(i8, @as(c_int, 0))),
\\ @bitCast(u8, @truncate(i8, @as(c_int, 0))),
\\ @bitCast(u8, @truncate(i8, @as(c_int, 0))),
\\ @bitCast(u8, @truncate(i8, @as(c_int, 0))),
\\ @bitCast(u8, @truncate(i8, @as(c_int, 0))),
\\};
} ) ;
2020-01-11 09:06:54 -08:00
cases . add ( " empty declaration " ,
\\;
, & [ _ ] [ ] const u8 { " " } ) ;
2020-01-04 02:06:28 -08:00
cases . add ( " #define hex literal with capital X " ,
\\#define VAL 0XF00D
, & [ _ ] [ ] const u8 {
\\pub const VAL = 0xF00D;
} ) ;
2020-01-05 08:47:29 -08:00
cases . add ( " anonymous struct & unions " ,
\\typedef struct {
\\ union {
\\ char x;
\\ struct { int y; };
\\ };
\\} outer;
\\void foo(outer *x) { x->y = x->x; }
, & [ _ ] [ ] const u8 {
\\const struct_unnamed_5 = extern struct {
\\ y: c_int,
\\};
\\const union_unnamed_3 = extern union {
\\ x: u8,
\\ unnamed_4: struct_unnamed_5,
\\};
\\const struct_unnamed_1 = extern struct {
\\ unnamed_2: union_unnamed_3,
\\};
\\pub const outer = struct_unnamed_1;
\\pub export fn foo(arg_x: [*c]outer) void {
\\ var x = arg_x;
\\ x.*.unnamed_2.unnamed_4.y = @bitCast(c_int, @as(c_uint, x.*.unnamed_2.x));
\\}
} ) ;
2020-01-02 08:47:53 -08:00
cases . add ( " union initializer " ,
\\union { int x; char c[4]; }
\\ ua = {1},
\\ ub = {.c={'a','b','b','a'}};
, & [ _ ] [ ] const u8 {
\\const union_unnamed_1 = extern union {
\\ x: c_int,
\\ c: [4]u8,
\\};
\\pub export var ua: union_unnamed_1 = union_unnamed_1{
\\ .x = @as(c_int, 1),
\\};
\\pub export var ub: union_unnamed_1 = union_unnamed_1{
2020-01-30 10:53:35 -08:00
\\ .c = [4]u8{
2020-01-02 08:47:53 -08:00
\\ @bitCast(u8, @truncate(i8, @as(c_int, 'a'))),
\\ @bitCast(u8, @truncate(i8, @as(c_int, 'b'))),
\\ @bitCast(u8, @truncate(i8, @as(c_int, 'b'))),
\\ @bitCast(u8, @truncate(i8, @as(c_int, 'a'))),
\\ },
\\};
} ) ;
cases . add ( " struct initializer - simple " ,
2020-01-05 02:39:01 -08:00
\\typedef struct { int x; } foo;
2020-01-02 08:47:53 -08:00
\\struct {double x,y,z;} s0 = {1.2, 1.3};
\\struct {int sec,min,hour,day,mon,year;} s1 = {.day=31,12,2014,.sec=30,15,17};
\\struct {int x,y;} s2 = {.y = 2, .x=1};
2020-01-05 02:39:01 -08:00
\\foo s3 = { 123 };
2020-01-02 08:47:53 -08:00
, & [ _ ] [ ] const u8 {
\\const struct_unnamed_1 = extern struct {
2020-01-05 02:39:01 -08:00
\\ x: c_int,
\\};
\\pub const foo = struct_unnamed_1;
\\const struct_unnamed_2 = extern struct {
2020-01-02 08:47:53 -08:00
\\ x: f64,
\\ y: f64,
\\ z: f64,
\\};
2020-01-05 02:39:01 -08:00
\\pub export var s0: struct_unnamed_2 = struct_unnamed_2{
2020-01-02 08:47:53 -08:00
\\ .x = 1.2,
\\ .y = 1.3,
\\ .z = 0,
\\};
2020-01-05 02:39:01 -08:00
\\const struct_unnamed_3 = extern struct {
2020-01-02 08:47:53 -08:00
\\ sec: c_int,
\\ min: c_int,
\\ hour: c_int,
\\ day: c_int,
\\ mon: c_int,
\\ year: c_int,
\\};
2020-01-05 02:39:01 -08:00
\\pub export var s1: struct_unnamed_3 = struct_unnamed_3{
2020-01-02 08:47:53 -08:00
\\ .sec = @as(c_int, 30),
\\ .min = @as(c_int, 15),
\\ .hour = @as(c_int, 17),
\\ .day = @as(c_int, 31),
\\ .mon = @as(c_int, 12),
\\ .year = @as(c_int, 2014),
\\};
2020-01-05 02:39:01 -08:00
\\const struct_unnamed_4 = extern struct {
2020-01-02 08:47:53 -08:00
\\ x: c_int,
\\ y: c_int,
\\};
2020-01-05 02:39:01 -08:00
\\pub export var s2: struct_unnamed_4 = struct_unnamed_4{
2020-01-02 08:47:53 -08:00
\\ .x = @as(c_int, 1),
\\ .y = @as(c_int, 2),
\\};
2020-01-05 02:39:01 -08:00
\\pub export var s3: foo = foo{
\\ .x = @as(c_int, 123),
\\};
2020-01-02 08:47:53 -08:00
} ) ;
2020-01-02 01:31:55 -08:00
cases . add ( " simple ptrCast for casts between opaque types " ,
\\struct opaque;
\\struct opaque_2;
\\void function(struct opaque *opaque) {
\\ struct opaque_2 *cast = (struct opaque_2 *)opaque;
\\}
, & [ _ ] [ ] const u8 {
\\pub const struct_opaque = @OpaqueType();
\\pub const struct_opaque_2 = @OpaqueType();
\\pub export fn function(arg_opaque_1: ?*struct_opaque) void {
\\ var opaque_1 = arg_opaque_1;
\\ var cast: ?*struct_opaque_2 = @ptrCast(?*struct_opaque_2, opaque_1);
\\}
} ) ;
2020-01-06 23:36:07 -08:00
cases . add ( " struct initializer - packed " ,
\\struct {int x,y,z;} __attribute__((packed)) s0 = {1, 2};
, & [ _ ] [ ] const u8 {
\\const struct_unnamed_1 = packed struct {
\\ x: c_int,
\\ y: c_int,
\\ z: c_int,
\\};
\\pub export var s0: struct_unnamed_1 = struct_unnamed_1{
\\ .x = @as(c_int, 1),
\\ .y = @as(c_int, 2),
\\ .z = 0,
\\};
} ) ;
2020-01-02 03:13:05 -08:00
cases . add ( " align() attribute " ,
\\__attribute__ ((aligned(128)))
\\extern char my_array[16];
\\__attribute__ ((aligned(128)))
\\void my_fn(void) { }
, & [ _ ] [ ] const u8 {
\\pub extern var my_array: [16]u8 align(128);
\\pub export fn my_fn() align(128) void {}
} ) ;
2020-01-02 02:33:26 -08:00
cases . add ( " linksection() attribute " ,
2020-01-02 03:13:05 -08:00
\\// Use the "segment,section" format to make this test pass when
\\// targeting the mach-o binary format
\\__attribute__ ((__section__("NEAR,.data")))
2020-01-02 02:33:26 -08:00
\\extern char my_array[16];
2020-01-02 03:13:05 -08:00
\\__attribute__ ((__section__("NEAR,.data")))
2020-01-02 02:33:26 -08:00
\\void my_fn(void) { }
, & [ _ ] [ ] const u8 {
2020-01-02 03:13:05 -08:00
\\pub extern var my_array: [16]u8 linksection("NEAR,.data");
\\pub export fn my_fn() linksection("NEAR,.data") void {}
2020-01-02 02:33:26 -08:00
} ) ;
2019-12-21 04:38:32 -08:00
cases . add ( " simple function prototypes " ,
2019-05-10 13:03:54 -07:00
\\void __attribute__((noreturn)) foo(void);
2019-05-10 14:55:29 -07:00
\\int bar(void);
2019-12-09 11:55:51 -08:00
, & [ _ ] [ ] const u8 {
2019-05-10 14:55:29 -07:00
\\pub extern fn foo() noreturn;
\\pub extern fn bar() c_int;
2019-12-09 11:55:51 -08:00
} ) ;
2019-05-10 13:03:54 -07:00
2019-12-21 04:38:32 -08:00
cases . add ( " simple var decls " ,
2019-06-27 23:12:33 -07:00
\\void foo(void) {
\\ int a;
\\ char b = 123;
\\ const int c;
\\ const unsigned d = 440;
2020-01-01 15:10:43 -08:00
\\ int e = 10;
\\ unsigned int f = 10u;
2019-06-27 23:12:33 -07:00
\\}
2019-12-09 11:55:51 -08:00
, & [ _ ] [ ] const u8 {
2019-12-12 06:56:21 -08:00
\\pub export fn foo() void {
2019-06-27 23:12:33 -07:00
\\ var a: c_int = undefined;
2020-01-01 15:10:43 -08:00
\\ var b: u8 = @bitCast(u8, @truncate(i8, @as(c_int, 123)));
2019-06-27 23:12:33 -07:00
\\ const c: c_int = undefined;
2020-01-01 15:10:43 -08:00
\\ const d: c_uint = @bitCast(c_uint, @as(c_int, 440));
\\ var e: c_int = 10;
\\ var f: c_uint = 10;
2019-06-27 23:12:33 -07:00
\\}
2019-12-09 11:55:51 -08:00
} ) ;
2019-06-27 23:12:33 -07:00
2019-12-21 04:38:32 -08:00
cases . add ( " ignore result, explicit function arguments " ,
2019-06-27 23:12:33 -07:00
\\void foo(void) {
\\ int a;
\\ 1;
\\ "hey";
\\ 1 + 1;
\\ 1 - 1;
\\ a = 1;
\\}
2019-12-09 11:55:51 -08:00
, & [ _ ] [ ] const u8 {
2019-12-12 06:56:21 -08:00
\\pub export fn foo() void {
2019-06-27 23:12:33 -07:00
\\ var a: c_int = undefined;
2020-01-01 15:10:43 -08:00
\\ _ = @as(c_int, 1);
2019-11-19 17:29:08 -08:00
\\ _ = "hey";
2020-01-01 15:10:43 -08:00
\\ _ = (@as(c_int, 1) + @as(c_int, 1));
\\ _ = (@as(c_int, 1) - @as(c_int, 1));
2019-06-27 23:12:33 -07:00
\\ a = 1;
\\}
2019-12-09 11:55:51 -08:00
} ) ;
2019-06-27 23:12:33 -07:00
2020-01-01 15:10:43 -08:00
cases . add ( " function with no prototype " ,
\\int foo() {
\\ return 5;
\\}
, & [ _ ] [ ] const u8 {
\\pub export fn foo() c_int {
\\ return 5;
\\}
} ) ;
2019-12-21 04:38:32 -08:00
cases . add ( " variables " ,
2019-12-12 06:56:21 -08:00
\\extern int extern_var;
\\static const int int_var = 13;
2020-03-05 14:04:24 -08:00
\\int foo;
2019-12-12 06:56:21 -08:00
, & [ _ ] [ ] const u8 {
\\pub extern var extern_var: c_int;
\\pub const int_var: c_int = 13;
2020-03-05 14:04:24 -08:00
\\pub export var foo: c_int = undefined;
2019-12-12 06:56:21 -08:00
} ) ;
2019-12-21 04:38:32 -08:00
cases . add ( " const ptr initializer " ,
2019-12-12 06:56:21 -08:00
\\static const char *v0 = "0.0.0";
, & [ _ ] [ ] const u8 {
\\pub var v0: [*c]const u8 = "0.0.0";
} ) ;
2019-12-21 04:38:32 -08:00
cases . add ( " static incomplete array inside function " ,
2019-12-12 11:14:55 -08:00
\\void foo(void) {
\\ static const char v2[] = "2.2.2";
\\}
2019-12-12 06:56:21 -08:00
, & [ _ ] [ ] const u8 {
2019-12-12 11:14:55 -08:00
\\pub export fn foo() void {
\\ const v2: [*c]const u8 = "2.2.2";
\\}
2019-12-12 06:56:21 -08:00
} ) ;
2019-12-21 04:38:32 -08:00
cases . add ( " simple function definition " ,
2019-12-12 06:56:21 -08:00
\\void foo(void) {}
\\static void bar(void) {}
, & [ _ ] [ ] const u8 {
\\pub export fn foo() void {}
2019-12-28 12:28:18 -08:00
\\pub fn bar() callconv(.C) void {}
2019-12-12 06:56:21 -08:00
} ) ;
2019-05-10 14:44:47 -07:00
2019-12-21 04:38:32 -08:00
cases . add ( " typedef void " ,
2019-12-13 07:36:18 -08:00
\\typedef void Foo;
\\Foo fun(Foo *a);
, & [ _ ] [ ] const u8 {
\\pub const Foo = c_void;
,
\\pub extern fn fun(a: ?*Foo) Foo;
} ) ;
2019-12-21 04:38:32 -08:00
cases . add ( " duplicate typedef " ,
2019-12-13 07:36:18 -08:00
\\typedef long foo;
\\typedef int bar;
\\typedef long foo;
\\typedef int baz;
, & [ _ ] [ ] const u8 {
\\pub const foo = c_long;
\\pub const bar = c_int;
\\pub const baz = c_int;
} ) ;
2019-12-21 04:38:32 -08:00
cases . add ( " casting pointers to ints and ints to pointers " ,
2019-12-13 07:36:18 -08:00
\\void foo(void);
\\void bar(void) {
\\ void *func_ptr = foo;
\\ void (*typed_func_ptr)(void) = (void (*)(void)) (unsigned long) func_ptr;
\\}
, & [ _ ] [ ] const u8 {
\\pub extern fn foo() void;
\\pub export fn bar() void {
\\ var func_ptr: ?*c_void = @ptrCast(?*c_void, foo);
2020-01-06 12:34:50 -08:00
\\ var typed_func_ptr: ?fn () callconv(.C) void = @intToPtr(?fn () callconv(.C) void, @intCast(c_ulong, @ptrToInt(func_ptr)));
2019-12-13 07:36:18 -08:00
\\}
} ) ;
2019-12-21 04:38:32 -08:00
cases . add ( " noreturn attribute " ,
2019-12-13 07:36:18 -08:00
\\void foo(void) __attribute__((noreturn));
, & [ _ ] [ ] const u8 {
\\pub extern fn foo() noreturn;
} ) ;
2019-12-21 04:38:32 -08:00
cases . add ( " add, sub, mul, div, rem " ,
2019-12-19 14:10:25 -08:00
\\int s() {
\\ int a, b, c;
2019-12-13 07:36:18 -08:00
\\ c = a + b;
\\ c = a - b;
\\ c = a * b;
\\ c = a / b;
\\ c = a % b;
\\}
2019-12-19 14:10:25 -08:00
\\unsigned u() {
\\ unsigned a, b, c;
2019-12-13 07:36:18 -08:00
\\ c = a + b;
\\ c = a - b;
\\ c = a * b;
\\ c = a / b;
\\ c = a % b;
\\}
, & [ _ ] [ ] const u8 {
2019-12-19 14:10:25 -08:00
\\pub export fn s() c_int {
\\ var a: c_int = undefined;
\\ var b: c_int = undefined;
2019-12-13 07:36:18 -08:00
\\ var c: c_int = undefined;
\\ c = (a + b);
\\ c = (a - b);
\\ c = (a * b);
\\ c = @divTrunc(a, b);
\\ c = @rem(a, b);
\\}
2019-12-19 14:10:25 -08:00
\\pub export fn u() c_uint {
\\ var a: c_uint = undefined;
\\ var b: c_uint = undefined;
2019-12-13 07:36:18 -08:00
\\ var c: c_uint = undefined;
\\ c = (a +% b);
\\ c = (a -% b);
\\ c = (a *% b);
\\ c = (a / b);
\\ c = (a % b);
\\}
} ) ;
2019-12-21 04:38:32 -08:00
cases . add ( " typedef of function in struct field " ,
2019-12-15 21:43:18 -08:00
\\typedef void lws_callback_function(void);
\\struct Foo {
\\ void (*func)(void);
\\ lws_callback_function *callback_http;
\\};
, & [ _ ] [ ] const u8 {
2020-01-06 14:54:16 -08:00
\\pub const lws_callback_function = fn () callconv(.C) void;
2019-12-15 21:43:18 -08:00
\\pub const struct_Foo = extern struct {
2020-01-06 14:54:16 -08:00
\\ func: ?fn () callconv(.C) void,
2019-12-15 21:43:18 -08:00
\\ callback_http: ?lws_callback_function,
\\};
} ) ;
2019-12-21 04:38:32 -08:00
cases . add ( " pointer to struct demoted to opaque due to bit fields " ,
2019-12-15 21:43:18 -08:00
\\struct Foo {
\\ unsigned int: 1;
\\};
\\struct Bar {
\\ struct Foo *foo;
\\};
, & [ _ ] [ ] const u8 {
2019-12-17 12:05:07 -08:00
\\pub const struct_Foo = @OpaqueType();
2019-12-15 21:43:18 -08:00
,
\\pub const struct_Bar = extern struct {
\\ foo: ?*struct_Foo,
\\};
} ) ;
2019-12-21 04:38:32 -08:00
cases . add ( " macro with left shift " ,
2019-12-15 21:43:18 -08:00
\\#define REDISMODULE_READ (1<<0)
, & [ _ ] [ ] const u8 {
\\pub const REDISMODULE_READ = 1 << 0;
} ) ;
2019-12-27 06:37:32 -08:00
cases . add ( " macro with right shift " ,
\\#define FLASH_SIZE 0x200000UL /* 2 MB */
\\#define FLASH_BANK_SIZE (FLASH_SIZE >> 1) /* 1 MB */
, & [ _ ] [ ] const u8 {
\\pub const FLASH_SIZE = @as(c_ulong, 0x200000);
,
\\pub const FLASH_BANK_SIZE = FLASH_SIZE >> 1;
} ) ;
2019-12-21 04:38:32 -08:00
cases . add ( " double define struct " ,
2019-12-15 21:43:18 -08:00
\\typedef struct Bar Bar;
\\typedef struct Foo Foo;
\\
\\struct Foo {
\\ Foo *a;
\\};
\\
\\struct Bar {
\\ Foo *a;
\\};
, & [ _ ] [ ] const u8 {
\\pub const struct_Foo = extern struct {
\\ a: [*c]Foo,
\\};
,
\\pub const Foo = struct_Foo;
,
\\pub const struct_Bar = extern struct {
\\ a: [*c]Foo,
\\};
,
\\pub const Bar = struct_Bar;
} ) ;
2019-12-21 04:38:32 -08:00
cases . add ( " simple struct " ,
2019-12-15 21:43:18 -08:00
\\struct Foo {
\\ int x;
\\ char *y;
\\};
, & [ _ ] [ ] const u8 {
\\const struct_Foo = extern struct {
\\ x: c_int,
\\ y: [*c]u8,
\\};
,
\\pub const Foo = struct_Foo;
} ) ;
2019-12-21 04:38:32 -08:00
cases . add ( " self referential struct with function pointer " ,
2019-12-15 21:43:18 -08:00
\\struct Foo {
\\ void (*derp)(struct Foo *foo);
\\};
, & [ _ ] [ ] const u8 {
\\pub const struct_Foo = extern struct {
2020-01-06 14:54:16 -08:00
\\ derp: ?fn ([*c]struct_Foo) callconv(.C) void,
2019-12-15 21:43:18 -08:00
\\};
,
\\pub const Foo = struct_Foo;
} ) ;
2019-12-21 04:38:32 -08:00
cases . add ( " struct prototype used in func " ,
2019-12-15 21:43:18 -08:00
\\struct Foo;
\\struct Foo *some_func(struct Foo *foo, int x);
, & [ _ ] [ ] const u8 {
\\pub const struct_Foo = @OpaqueType();
,
\\pub extern fn some_func(foo: ?*struct_Foo, x: c_int) ?*struct_Foo;
,
\\pub const Foo = struct_Foo;
} ) ;
2019-12-21 04:38:32 -08:00
cases . add ( " #define an unsigned integer literal " ,
2019-12-15 21:43:18 -08:00
\\#define CHANNEL_COUNT 24
, & [ _ ] [ ] const u8 {
\\pub const CHANNEL_COUNT = 24;
} ) ;
2019-12-21 04:38:32 -08:00
cases . add ( " #define referencing another #define " ,
2019-12-15 21:43:18 -08:00
\\#define THING2 THING1
\\#define THING1 1234
, & [ _ ] [ ] const u8 {
\\pub const THING1 = 1234;
,
\\pub const THING2 = THING1;
} ) ;
2019-12-21 04:38:32 -08:00
cases . add ( " circular struct definitions " ,
2019-12-15 21:43:18 -08:00
\\struct Bar;
\\
\\struct Foo {
\\ struct Bar *next;
\\};
\\
\\struct Bar {
\\ struct Foo *next;
\\};
, & [ _ ] [ ] const u8 {
\\pub const struct_Bar = extern struct {
\\ next: [*c]struct_Foo,
\\};
,
\\pub const struct_Foo = extern struct {
\\ next: [*c]struct_Bar,
\\};
} ) ;
2019-12-21 04:38:32 -08:00
cases . add ( " #define string " ,
2019-12-15 21:43:18 -08:00
\\#define foo "a string"
, & [ _ ] [ ] const u8 {
\\pub const foo = "a string";
} ) ;
2019-12-21 04:38:32 -08:00
cases . add ( " zig keywords in C code " ,
2019-12-15 21:43:18 -08:00
\\struct comptime {
\\ int defer;
\\};
, & [ _ ] [ ] const u8 {
\\pub const struct_comptime = extern struct {
\\ @"defer": c_int,
\\};
,
\\pub const @"comptime" = struct_comptime;
} ) ;
2019-12-21 04:38:32 -08:00
cases . add ( " macro with parens around negative number " ,
2019-12-15 21:43:18 -08:00
\\#define LUA_GLOBALSINDEX (-10002)
, & [ _ ] [ ] const u8 {
\\pub const LUA_GLOBALSINDEX = -10002;
} ) ;
2019-12-21 04:38:32 -08:00
cases . add (
2019-12-15 21:43:18 -08:00
" u integer suffix after 0 (zero) in macro definition " ,
" #define ZERO 0U " ,
& [ _ ] [ ] const u8 {
" pub const ZERO = @as(c_uint, 0); " ,
} ,
) ;
2019-12-21 04:38:32 -08:00
cases . add (
2019-12-15 21:43:18 -08:00
" l integer suffix after 0 (zero) in macro definition " ,
" #define ZERO 0L " ,
& [ _ ] [ ] const u8 {
" pub const ZERO = @as(c_long, 0); " ,
} ,
) ;
2019-12-21 04:38:32 -08:00
cases . add (
2019-12-15 21:43:18 -08:00
" ul integer suffix after 0 (zero) in macro definition " ,
" #define ZERO 0UL " ,
& [ _ ] [ ] const u8 {
" pub const ZERO = @as(c_ulong, 0); " ,
} ,
) ;
2019-12-21 04:38:32 -08:00
cases . add (
2019-12-15 21:43:18 -08:00
" lu integer suffix after 0 (zero) in macro definition " ,
" #define ZERO 0LU " ,
& [ _ ] [ ] const u8 {
" pub const ZERO = @as(c_ulong, 0); " ,
} ,
) ;
2019-12-21 04:38:32 -08:00
cases . add (
2019-12-15 21:43:18 -08:00
" ll integer suffix after 0 (zero) in macro definition " ,
" #define ZERO 0LL " ,
& [ _ ] [ ] const u8 {
" pub const ZERO = @as(c_longlong, 0); " ,
} ,
) ;
2019-12-21 04:38:32 -08:00
cases . add (
2019-12-15 21:43:18 -08:00
" ull integer suffix after 0 (zero) in macro definition " ,
" #define ZERO 0ULL " ,
& [ _ ] [ ] const u8 {
" pub const ZERO = @as(c_ulonglong, 0); " ,
} ,
) ;
2019-12-21 04:38:32 -08:00
cases . add (
2019-12-15 21:43:18 -08:00
" llu integer suffix after 0 (zero) in macro definition " ,
" #define ZERO 0LLU " ,
& [ _ ] [ ] const u8 {
" pub const ZERO = @as(c_ulonglong, 0); " ,
} ,
) ;
2019-12-21 04:38:32 -08:00
cases . add (
2019-12-15 21:43:18 -08:00
" bitwise not on u-suffixed 0 (zero) in macro definition " ,
" #define NOT_ZERO (~0U) " ,
& [ _ ] [ ] const u8 {
" pub const NOT_ZERO = ~@as(c_uint, 0); " ,
} ,
) ;
2020-02-02 00:49:51 -08:00
cases . add ( " float suffixes " ,
\\#define foo 3.14f
\\#define bar 16.e-2l
2020-02-10 06:37:37 -08:00
\\#define FOO 0.12345
\\#define BAR .12345
2020-02-02 00:49:51 -08:00
, & [ _ ] [ ] const u8 {
" pub const foo = @as(f32, 3.14); " ,
" pub const bar = @as(c_longdouble, 16.e-2); " ,
2020-02-10 06:37:37 -08:00
" pub const FOO = 0.12345; " ,
" pub const BAR = 0.12345; " ,
2020-02-02 00:49:51 -08:00
} ) ;
2020-02-04 22:35:30 -08:00
cases . add ( " comments " ,
\\#define foo 1 //foo
\\#define bar /* bar */ 2
, & [ _ ] [ ] const u8 {
" pub const foo = 1; " ,
" pub const bar = 2; " ,
} ) ;
cases . add ( " string prefix " ,
\\#define foo L"hello"
, & [ _ ] [ ] const u8 {
" pub const foo = \" hello \" ; " ,
} ) ;
2019-12-21 04:38:32 -08:00
cases . add ( " null statements " ,
2019-12-17 13:28:13 -08:00
\\void foo(void) {
\\ ;;;;;
\\}
, & [ _ ] [ ] const u8 {
\\pub export fn foo() void {
\\ {}
\\ {}
\\ {}
\\ {}
\\ {}
\\}
} ) ;
2020-02-25 22:18:23 -08:00
if ( std . Target . current . os . tag ! = . windows ) {
2019-12-17 13:28:13 -08:00
// Windows treats this as an enum with type c_int
2019-12-21 04:38:32 -08:00
cases . add ( " big negative enum init values when C ABI supports long long enums " ,
2019-12-17 13:28:13 -08:00
\\enum EnumWithInits {
\\ VAL01 = 0,
\\ VAL02 = 1,
\\ VAL03 = 2,
\\ VAL04 = 3,
\\ VAL05 = -1,
\\ VAL06 = -2,
\\ VAL07 = -3,
\\ VAL08 = -4,
\\ VAL09 = VAL02 + VAL08,
\\ VAL10 = -1000012000,
\\ VAL11 = -1000161000,
\\ VAL12 = -1000174001,
\\ VAL13 = VAL09,
\\ VAL14 = VAL10,
\\ VAL15 = VAL11,
\\ VAL16 = VAL13,
\\ VAL17 = (VAL16 - VAL10 + 1),
\\ VAL18 = 0x1000000000000000L,
\\ VAL19 = VAL18 + VAL18 + VAL18 - 1,
\\ VAL20 = VAL19 + VAL19,
\\ VAL21 = VAL20 + 0xFFFFFFFFFFFFFFFF,
\\ VAL22 = 0xFFFFFFFFFFFFFFFF + 1,
\\ VAL23 = 0xFFFFFFFFFFFFFFFF,
\\};
, & [ _ ] [ ] const u8 {
\\pub const enum_EnumWithInits = extern enum(c_longlong) {
\\ VAL01 = 0,
\\ VAL02 = 1,
\\ VAL03 = 2,
\\ VAL04 = 3,
\\ VAL05 = -1,
\\ VAL06 = -2,
\\ VAL07 = -3,
\\ VAL08 = -4,
\\ VAL09 = -3,
\\ VAL10 = -1000012000,
\\ VAL11 = -1000161000,
\\ VAL12 = -1000174001,
\\ VAL13 = -3,
\\ VAL14 = -1000012000,
\\ VAL15 = -1000161000,
\\ VAL16 = -3,
\\ VAL17 = 1000011998,
\\ VAL18 = 1152921504606846976,
\\ VAL19 = 3458764513820540927,
\\ VAL20 = 6917529027641081854,
\\ VAL21 = 6917529027641081853,
\\ VAL22 = 0,
\\ VAL23 = -1,
2020-01-15 10:40:56 -08:00
\\ _,
2019-12-17 13:28:13 -08:00
\\};
} ) ;
}
2019-12-21 04:38:32 -08:00
cases . add ( " predefined expressions " ,
2019-12-17 13:28:13 -08:00
\\void foo(void) {
\\ __func__;
\\ __FUNCTION__;
\\ __PRETTY_FUNCTION__;
\\}
, & [ _ ] [ ] const u8 {
\\pub export fn foo() void {
\\ _ = "foo";
\\ _ = "foo";
\\ _ = "void foo(void)";
\\}
} ) ;
2019-12-21 04:38:32 -08:00
cases . add ( " constant size array " ,
2019-12-17 13:28:13 -08:00
\\void func(int array[20]);
, & [ _ ] [ ] const u8 {
\\pub extern fn func(array: [*c]c_int) void;
} ) ;
2019-12-21 04:38:32 -08:00
cases . add ( " __cdecl doesn't mess up function pointers " ,
2019-12-17 13:28:13 -08:00
\\void foo(void (__cdecl *fn_ptr)(void));
, & [ _ ] [ ] const u8 {
2020-01-06 14:54:16 -08:00
\\pub extern fn foo(fn_ptr: ?fn () callconv(.C) void) void;
2019-12-17 13:28:13 -08:00
} ) ;
2019-12-21 04:38:32 -08:00
cases . add ( " void cast " ,
2019-12-19 14:10:25 -08:00
\\void foo() {
\\ int a;
2019-12-17 13:28:13 -08:00
\\ (void) a;
\\}
, & [ _ ] [ ] const u8 {
2019-12-19 14:10:25 -08:00
\\pub export fn foo() void {
\\ var a: c_int = undefined;
2019-12-17 13:28:13 -08:00
\\ _ = a;
\\}
} ) ;
2019-12-21 04:38:32 -08:00
cases . add ( " implicit cast to void * " ,
2019-12-19 14:10:25 -08:00
\\void *foo() {
\\ unsigned short *x;
2019-12-17 13:28:13 -08:00
\\ return x;
\\}
, & [ _ ] [ ] const u8 {
2019-12-19 14:10:25 -08:00
\\pub export fn foo() ?*c_void {
\\ var x: [*c]c_ushort = undefined;
2019-12-17 13:28:13 -08:00
\\ return @ptrCast(?*c_void, x);
\\}
} ) ;
2019-12-21 04:38:32 -08:00
cases . add ( " null pointer implicit cast " ,
2019-12-17 13:28:13 -08:00
\\int* foo(void) {
\\ return 0;
\\}
, & [ _ ] [ ] const u8 {
\\pub export fn foo() [*c]c_int {
\\ return null;
\\}
} ) ;
2019-12-21 04:38:32 -08:00
cases . add ( " simple union " ,
2019-12-17 15:04:01 -08:00
\\union Foo {
\\ int x;
\\ double y;
\\};
, & [ _ ] [ ] const u8 {
\\pub const union_Foo = extern union {
\\ x: c_int,
\\ y: f64,
\\};
,
\\pub const Foo = union_Foo;
} ) ;
2019-12-21 04:38:32 -08:00
cases . add ( " string literal " ,
2019-12-17 15:04:01 -08:00
\\const char *foo(void) {
\\ return "bar";
\\}
, & [ _ ] [ ] const u8 {
\\pub export fn foo() [*c]const u8 {
\\ return "bar";
\\}
} ) ;
2019-12-21 04:38:32 -08:00
cases . add ( " return void " ,
2019-12-17 15:04:01 -08:00
\\void foo(void) {
\\ return;
\\}
, & [ _ ] [ ] const u8 {
\\pub export fn foo() void {
\\ return;
\\}
} ) ;
2019-12-21 04:38:32 -08:00
cases . add ( " for loop " ,
2019-12-17 15:04:01 -08:00
\\void foo(void) {
2020-01-02 06:28:01 -08:00
\\ for (int i = 0; i; i++) { }
2019-12-17 15:04:01 -08:00
\\}
, & [ _ ] [ ] const u8 {
\\pub export fn foo() void {
\\ {
\\ var i: c_int = 0;
2020-01-02 06:28:01 -08:00
\\ while (i != 0) : (i += 1) {}
2019-12-17 15:04:01 -08:00
\\ }
\\}
} ) ;
2019-12-21 04:38:32 -08:00
cases . add ( " empty for loop " ,
2019-12-17 15:04:01 -08:00
\\void foo(void) {
\\ for (;;) { }
\\}
, & [ _ ] [ ] const u8 {
\\pub export fn foo() void {
\\ while (true) {}
\\}
} ) ;
2020-01-04 02:49:43 -08:00
cases . add ( " for loop with simple init expression " ,
\\void foo(void) {
\\ int i;
\\ for (i = 3; i; i--) { }
\\}
, & [ _ ] [ ] const u8 {
\\pub export fn foo() void {
\\ var i: c_int = undefined;
\\ {
\\ i = 3;
\\ while (i != 0) : (i -= 1) {}
\\ }
\\}
} ) ;
2019-12-21 04:38:32 -08:00
cases . add ( " break statement " ,
2019-12-17 15:04:01 -08:00
\\void foo(void) {
\\ for (;;) {
\\ break;
\\ }
\\}
, & [ _ ] [ ] const u8 {
\\pub export fn foo() void {
\\ while (true) {
\\ break;
\\ }
\\}
} ) ;
2019-12-21 04:38:32 -08:00
cases . add ( " continue statement " ,
2019-12-17 15:04:01 -08:00
\\void foo(void) {
\\ for (;;) {
\\ continue;
\\ }
\\}
, & [ _ ] [ ] const u8 {
\\pub export fn foo() void {
\\ while (true) {
\\ continue;
\\ }
\\}
} ) ;
2019-12-21 04:38:32 -08:00
cases . add ( " pointer casting " ,
2019-12-19 14:10:25 -08:00
\\float *ptrcast() {
\\ int *a;
2019-12-17 15:04:01 -08:00
\\ return (float *)a;
\\}
, & [ _ ] [ ] const u8 {
2019-12-19 14:10:25 -08:00
\\pub export fn ptrcast() [*c]f32 {
\\ var a: [*c]c_int = undefined;
2019-12-17 15:04:01 -08:00
\\ return @ptrCast([*c]f32, @alignCast(@alignOf(f32), a));
\\}
} ) ;
2019-12-21 04:38:32 -08:00
cases . add ( " pointer conversion with different alignment " ,
2019-12-17 15:04:01 -08:00
\\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;
\\ }
\\}
, & [ _ ] [ ] const u8 {
\\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));
\\ }
\\}
} ) ;
2019-12-21 04:38:32 -08:00
cases . add ( " while on non-bool " ,
2019-12-19 14:10:25 -08:00
\\int while_none_bool() {
\\ int a;
\\ float b;
\\ void *c;
2019-12-18 15:38:42 -08:00
\\ while (a) return 0;
\\ while (b) return 1;
\\ while (c) return 2;
\\ return 3;
\\}
, & [ _ ] [ ] const u8 {
2019-12-19 14:10:25 -08:00
\\pub export fn while_none_bool() c_int {
\\ var a: c_int = undefined;
\\ var b: f32 = undefined;
\\ var c: ?*c_void = undefined;
2019-12-18 15:38:42 -08:00
\\ while (a != 0) return 0;
\\ while (b != 0) return 1;
\\ while (c != null) return 2;
\\ return 3;
\\}
} ) ;
2019-12-21 04:38:32 -08:00
cases . add ( " for on non-bool " ,
2019-12-19 14:10:25 -08:00
\\int for_none_bool() {
\\ int a;
\\ float b;
\\ void *c;
2019-12-18 15:38:42 -08:00
\\ for (;a;) return 0;
\\ for (;b;) return 1;
\\ for (;c;) return 2;
\\ return 3;
\\}
, & [ _ ] [ ] const u8 {
2019-12-19 14:10:25 -08:00
\\pub export fn for_none_bool() c_int {
\\ var a: c_int = undefined;
\\ var b: f32 = undefined;
\\ var c: ?*c_void = undefined;
2019-12-18 15:38:42 -08:00
\\ while (a != 0) return 0;
\\ while (b != 0) return 1;
\\ while (c != null) return 2;
\\ return 3;
\\}
} ) ;
2019-12-21 04:38:32 -08:00
cases . add ( " bitshift " ,
2019-12-18 22:27:35 -08:00
\\int foo(void) {
\\ return (1 << 2) >> 1;
\\}
, & [ _ ] [ ] const u8 {
\\pub export fn foo() c_int {
2020-01-03 19:55:47 -08:00
\\ return (@as(c_int, 1) << @intCast(@import("std").math.Log2Int(c_int), 2)) >> @intCast(@import("std").math.Log2Int(c_int), 1);
2019-12-18 22:27:35 -08:00
\\}
} ) ;
2019-12-21 04:38:32 -08:00
cases . add ( " sizeof " ,
2019-12-18 22:27:35 -08:00
\\#include <stddef.h>
\\size_t size_of(void) {
\\ return sizeof(int);
\\}
, & [ _ ] [ ] const u8 {
\\pub export fn size_of() usize {
\\ return @sizeOf(c_int);
\\}
} ) ;
2019-12-21 04:38:32 -08:00
cases . add ( " normal deref " ,
2019-12-19 14:10:25 -08:00
\\void foo() {
\\ int *x;
2019-12-18 23:39:39 -08:00
\\ *x = 1;
\\}
, & [ _ ] [ ] const u8 {
2019-12-19 14:10:25 -08:00
\\pub export fn foo() void {
\\ var x: [*c]c_int = undefined;
2019-12-18 23:39:39 -08:00
\\ x.?.* = 1;
\\}
} ) ;
2019-12-21 04:38:32 -08:00
cases . add ( " address of operator " ,
2019-12-18 23:39:39 -08:00
\\int foo(void) {
\\ int x = 1234;
\\ int *ptr = &x;
\\ return *ptr;
\\}
, & [ _ ] [ ] const u8 {
\\pub export fn foo() c_int {
\\ var x: c_int = 1234;
\\ var ptr: [*c]c_int = &x;
\\ return ptr.?.*;
\\}
} ) ;
2019-12-21 04:38:32 -08:00
cases . add ( " bin not " ,
2019-12-19 14:10:25 -08:00
\\int foo() {
\\ int x;
2019-12-18 23:39:39 -08:00
\\ return ~x;
\\}
, & [ _ ] [ ] const u8 {
2019-12-19 14:10:25 -08:00
\\pub export fn foo() c_int {
\\ var x: c_int = undefined;
2019-12-18 23:39:39 -08:00
\\ return ~x;
\\}
} ) ;
2019-12-21 04:38:32 -08:00
cases . add ( " bool not " ,
2019-12-19 14:10:25 -08:00
\\int foo() {
\\ int a;
\\ float b;
\\ void *c;
2019-12-18 23:39:39 -08:00
\\ return !(a == 0);
\\ return !a;
\\ return !b;
\\ return !c;
\\}
, & [ _ ] [ ] const u8 {
2019-12-19 14:10:25 -08:00
\\pub export fn foo() c_int {
\\ var a: c_int = undefined;
\\ var b: f32 = undefined;
\\ var c: ?*c_void = undefined;
2020-01-01 15:10:43 -08:00
\\ return !(a == @as(c_int, 0));
2019-12-18 23:39:39 -08:00
\\ return !(a != 0);
\\ return !(b != 0);
\\ return !(c != null);
\\}
} ) ;
2019-12-21 04:38:32 -08:00
cases . add ( " __extension__ cast " ,
2019-12-19 11:30:51 -08:00
\\int foo(void) {
\\ return __extension__ 1;
\\}
, & [ _ ] [ ] const u8 {
\\pub export fn foo() c_int {
\\ return 1;
\\}
} ) ;
2020-02-25 22:18:23 -08:00
if ( std . Target . current . os . tag ! = . windows ) {
2019-12-19 14:10:25 -08:00
// sysv_abi not currently supported on windows
2019-12-21 04:38:32 -08:00
cases . add ( " Macro qualified functions " ,
2019-12-19 14:10:25 -08:00
\\void __attribute__((sysv_abi)) foo(void);
, & [ _ ] [ ] const u8 {
\\pub extern fn foo() void;
} ) ;
}
2019-12-21 04:38:32 -08:00
cases . add ( " Forward-declared enum " ,
2019-12-27 15:57:37 -08:00
\\extern enum enum_ty my_enum;
\\enum enum_ty { FOO };
, & [ _ ] [ ] const u8 {
2020-01-02 08:38:20 -08:00
\\pub const FOO = @enumToInt(enum_enum_ty.FOO);
2020-01-15 11:38:11 -08:00
\\pub const enum_enum_ty = extern enum(c_int) {
2019-12-27 15:57:37 -08:00
\\ FOO,
2020-01-15 10:40:56 -08:00
\\ _,
2019-12-27 15:57:37 -08:00
\\};
\\pub extern var my_enum: enum_enum_ty;
} ) ;
2019-12-21 04:38:32 -08:00
cases . add ( " Parameterless function pointers " ,
2019-12-27 15:50:17 -08:00
\\typedef void (*fn0)();
\\typedef void (*fn1)(char);
, & [ _ ] [ ] const u8 {
2020-01-06 14:54:16 -08:00
\\pub const fn0 = ?fn (...) callconv(.C) void;
\\pub const fn1 = ?fn (u8) callconv(.C) void;
2019-12-27 15:50:17 -08:00
} ) ;
2020-02-25 00:43:21 -08:00
cases . addWithTarget ( " Calling convention " , . {
2020-02-25 22:18:23 -08:00
. cpu_arch = . i386 ,
. os_tag = . linux ,
. abi = . none ,
2019-12-28 12:28:18 -08:00
} ,
\\void __attribute__((fastcall)) foo1(float *a);
\\void __attribute__((stdcall)) foo2(float *a);
\\void __attribute__((vectorcall)) foo3(float *a);
\\void __attribute__((cdecl)) foo4(float *a);
2019-12-29 10:34:54 -08:00
\\void __attribute__((thiscall)) foo5(float *a);
2019-12-28 12:28:18 -08:00
, & [ _ ] [ ] const u8 {
\\pub fn foo1(a: [*c]f32) callconv(.Fastcall) void;
\\pub fn foo2(a: [*c]f32) callconv(.Stdcall) void;
\\pub fn foo3(a: [*c]f32) callconv(.Vectorcall) void;
\\pub extern fn foo4(a: [*c]f32) void;
2019-12-29 10:34:54 -08:00
\\pub fn foo5(a: [*c]f32) callconv(.Thiscall) void;
2019-12-28 12:28:18 -08:00
} ) ;
2020-02-25 22:18:23 -08:00
cases . addWithTarget ( " Calling convention " , CrossTarget . parse ( . {
. arch_os_abi = " arm-linux-none " ,
. cpu_features = " generic+v8_5a " ,
} ) catch unreachable ,
2019-12-28 12:28:18 -08:00
\\void __attribute__((pcs("aapcs"))) foo1(float *a);
\\void __attribute__((pcs("aapcs-vfp"))) foo2(float *a);
, & [ _ ] [ ] const u8 {
\\pub fn foo1(a: [*c]f32) callconv(.AAPCS) void;
\\pub fn foo2(a: [*c]f32) callconv(.AAPCSVFP) void;
} ) ;
2020-02-25 22:18:23 -08:00
cases . addWithTarget ( " Calling convention " , CrossTarget . parse ( . {
. arch_os_abi = " aarch64-linux-none " ,
. cpu_features = " generic+v8_5a " ,
} ) catch unreachable ,
2019-12-28 12:28:18 -08:00
\\void __attribute__((aarch64_vector_pcs)) foo1(float *a);
, & [ _ ] [ ] const u8 {
\\pub fn foo1(a: [*c]f32) callconv(.Vectorcall) void;
} ) ;
2019-12-21 04:38:32 -08:00
cases . add ( " Parameterless function prototypes " ,
2019-05-11 09:05:33 -07:00
\\void a() {}
\\void b(void) {}
\\void c();
\\void d(void);
2019-12-09 11:55:51 -08:00
, & [ _ ] [ ] const u8 {
2019-12-12 06:56:21 -08:00
\\pub export fn a() void {}
\\pub export fn b() void {}
2019-05-11 09:05:33 -07:00
\\pub extern fn c(...) void;
\\pub extern fn d() void;
2019-12-09 11:55:51 -08:00
} ) ;
2019-05-10 20:35:46 -07:00
2019-12-21 04:38:32 -08:00
cases . add ( " variable declarations " ,
2019-12-13 04:55:36 -08:00
\\extern char arr0[] = "hello";
\\static char arr1[] = "hello";
\\char arr2[] = "hello";
, & [ _ ] [ ] const u8 {
\\pub extern var arr0: [*c]u8 = "hello";
\\pub var arr1: [*c]u8 = "hello";
\\pub export var arr2: [*c]u8 = "hello";
} ) ;
2019-12-21 04:38:32 -08:00
cases . add ( " array initializer expr " ,
2019-12-14 00:41:00 -08:00
\\static void foo(void){
\\ char arr[10] ={1};
\\ char *arr1[10] ={0};
\\}
, & [ _ ] [ ] const u8 {
2019-12-28 12:28:18 -08:00
\\pub fn foo() callconv(.C) void {
2020-01-30 10:53:35 -08:00
\\ var arr: [10]u8 = [1]u8{
2020-01-01 15:10:43 -08:00
\\ @bitCast(u8, @truncate(i8, @as(c_int, 1))),
2020-01-30 10:53:35 -08:00
\\ } ++ [1]u8{0} ** 9;
\\ var arr1: [10][*c]u8 = [1][*c]u8{
2019-12-14 00:41:00 -08:00
\\ null,
2020-01-30 10:53:35 -08:00
\\ } ++ [1][*c]u8{null} ** 9;
2019-12-14 00:41:00 -08:00
\\}
} ) ;
2019-12-21 04:38:32 -08:00
cases . add ( " enums " ,
2019-12-14 11:46:54 -08:00
\\typedef enum {
\\ a,
\\ b,
\\ c,
\\} d;
\\enum {
\\ e,
\\ f = 4,
\\ g,
\\} h = e;
\\struct Baz {
\\ enum {
\\ i,
\\ j,
\\ k,
\\ } l;
\\ d m;
\\};
\\enum i {
\\ n,
\\ o,
\\ p,
\\};
, & [ _ ] [ ] const u8 {
2020-01-02 08:38:20 -08:00
\\pub const a = @enumToInt(enum_unnamed_1.a);
\\pub const b = @enumToInt(enum_unnamed_1.b);
\\pub const c = @enumToInt(enum_unnamed_1.c);
2020-01-16 02:50:44 -08:00
\\const enum_unnamed_1 = extern enum(c_int) {
2019-12-14 11:46:54 -08:00
\\ a,
\\ b,
\\ c,
2020-01-15 10:40:56 -08:00
\\ _,
2019-12-14 11:46:54 -08:00
\\};
\\pub const d = enum_unnamed_1;
2020-01-02 08:38:20 -08:00
\\pub const e = @enumToInt(enum_unnamed_2.e);
\\pub const f = @enumToInt(enum_unnamed_2.f);
\\pub const g = @enumToInt(enum_unnamed_2.g);
2020-01-16 02:50:44 -08:00
\\const enum_unnamed_2 = extern enum(c_int) {
2019-12-14 11:46:54 -08:00
\\ e = 0,
\\ f = 4,
\\ g = 5,
2020-01-15 10:40:56 -08:00
\\ _,
2019-12-14 11:46:54 -08:00
\\};
2019-12-22 02:53:57 -08:00
\\pub export var h: enum_unnamed_2 = @intToEnum(enum_unnamed_2, e);
2020-01-02 08:38:20 -08:00
\\pub const i = @enumToInt(enum_unnamed_3.i);
\\pub const j = @enumToInt(enum_unnamed_3.j);
\\pub const k = @enumToInt(enum_unnamed_3.k);
2020-01-16 02:50:44 -08:00
\\const enum_unnamed_3 = extern enum(c_int) {
2019-12-14 11:46:54 -08:00
\\ i,
\\ j,
\\ k,
2020-01-15 10:40:56 -08:00
\\ _,
2019-12-14 11:46:54 -08:00
\\};
\\pub const struct_Baz = extern struct {
\\ l: enum_unnamed_3,
\\ m: d,
\\};
2020-01-02 08:38:20 -08:00
\\pub const n = @enumToInt(enum_i.n);
\\pub const o = @enumToInt(enum_i.o);
\\pub const p = @enumToInt(enum_i.p);
2020-01-16 02:50:44 -08:00
\\pub const enum_i = extern enum(c_int) {
2019-12-14 11:46:54 -08:00
\\ n,
\\ o,
\\ p,
2020-01-15 10:40:56 -08:00
\\ _,
2019-12-14 11:46:54 -08:00
\\};
2019-12-15 04:44:11 -08:00
,
2019-12-14 11:46:54 -08:00
\\pub const Baz = struct_Baz;
} ) ;
2019-12-21 04:38:32 -08:00
cases . add ( " #define a char literal " ,
2019-12-15 04:44:11 -08:00
\\#define A_CHAR 'a'
, & [ _ ] [ ] const u8 {
\\pub const A_CHAR = 'a';
} ) ;
2019-12-21 04:38:32 -08:00
cases . add ( " comment after integer literal " ,
2019-12-15 04:44:11 -08:00
\\#define SDL_INIT_VIDEO 0x00000020 /**< SDL_INIT_VIDEO implies SDL_INIT_EVENTS */
, & [ _ ] [ ] const u8 {
\\pub const SDL_INIT_VIDEO = 0x00000020;
} ) ;
2019-12-21 04:38:32 -08:00
cases . add ( " u integer suffix after hex literal " ,
2019-12-15 04:44:11 -08:00
\\#define SDL_INIT_VIDEO 0x00000020u /**< SDL_INIT_VIDEO implies SDL_INIT_EVENTS */
, & [ _ ] [ ] const u8 {
\\pub const SDL_INIT_VIDEO = @as(c_uint, 0x00000020);
} ) ;
2019-12-21 04:38:32 -08:00
cases . add ( " l integer suffix after hex literal " ,
2019-12-15 04:44:11 -08:00
\\#define SDL_INIT_VIDEO 0x00000020l /**< SDL_INIT_VIDEO implies SDL_INIT_EVENTS */
, & [ _ ] [ ] const u8 {
\\pub const SDL_INIT_VIDEO = @as(c_long, 0x00000020);
} ) ;
2019-12-21 04:38:32 -08:00
cases . add ( " ul integer suffix after hex literal " ,
2019-12-15 04:44:11 -08:00
\\#define SDL_INIT_VIDEO 0x00000020ul /**< SDL_INIT_VIDEO implies SDL_INIT_EVENTS */
, & [ _ ] [ ] const u8 {
\\pub const SDL_INIT_VIDEO = @as(c_ulong, 0x00000020);
} ) ;
2019-12-21 04:38:32 -08:00
cases . add ( " lu integer suffix after hex literal " ,
2019-12-15 04:44:11 -08:00
\\#define SDL_INIT_VIDEO 0x00000020lu /**< SDL_INIT_VIDEO implies SDL_INIT_EVENTS */
, & [ _ ] [ ] const u8 {
\\pub const SDL_INIT_VIDEO = @as(c_ulong, 0x00000020);
} ) ;
2019-12-21 04:38:32 -08:00
cases . add ( " ll integer suffix after hex literal " ,
2019-12-15 04:44:11 -08:00
\\#define SDL_INIT_VIDEO 0x00000020ll /**< SDL_INIT_VIDEO implies SDL_INIT_EVENTS */
, & [ _ ] [ ] const u8 {
\\pub const SDL_INIT_VIDEO = @as(c_longlong, 0x00000020);
} ) ;
2019-12-21 04:38:32 -08:00
cases . add ( " ull integer suffix after hex literal " ,
2019-12-15 04:44:11 -08:00
\\#define SDL_INIT_VIDEO 0x00000020ull /**< SDL_INIT_VIDEO implies SDL_INIT_EVENTS */
, & [ _ ] [ ] const u8 {
\\pub const SDL_INIT_VIDEO = @as(c_ulonglong, 0x00000020);
} ) ;
2019-12-21 04:38:32 -08:00
cases . add ( " llu integer suffix after hex literal " ,
2019-12-15 04:44:11 -08:00
\\#define SDL_INIT_VIDEO 0x00000020llu /**< SDL_INIT_VIDEO implies SDL_INIT_EVENTS */
, & [ _ ] [ ] const u8 {
\\pub const SDL_INIT_VIDEO = @as(c_ulonglong, 0x00000020);
} ) ;
2019-12-21 04:38:32 -08:00
cases . add ( " generate inline func for #define global extern fn " ,
2019-12-15 06:50:20 -08:00
\\extern void (*fn_ptr)(void);
\\#define foo fn_ptr
\\
\\extern char (*fn_ptr2)(int, float);
\\#define bar fn_ptr2
, & [ _ ] [ ] const u8 {
2020-01-06 14:54:16 -08:00
\\pub extern var fn_ptr: ?fn () callconv(.C) void;
2019-12-15 06:50:20 -08:00
,
\\pub inline fn foo() void {
\\ return fn_ptr.?();
\\}
,
2020-01-06 14:54:16 -08:00
\\pub extern var fn_ptr2: ?fn (c_int, f32) callconv(.C) u8;
2019-12-15 06:50:20 -08:00
,
\\pub inline fn bar(arg_1: c_int, arg_2: f32) u8 {
\\ return fn_ptr2.?(arg_1, arg_2);
\\}
} ) ;
2019-12-21 04:38:32 -08:00
cases . add ( " macros with field targets " ,
2019-12-15 06:50:20 -08:00
\\typedef unsigned int GLbitfield;
\\typedef void (*PFNGLCLEARPROC) (GLbitfield mask);
\\typedef void(*OpenGLProc)(void);
\\union OpenGLProcs {
\\ OpenGLProc ptr[1];
\\ struct {
\\ PFNGLCLEARPROC Clear;
\\ } gl;
\\};
\\extern union OpenGLProcs glProcs;
\\#define glClearUnion glProcs.gl.Clear
\\#define glClearPFN PFNGLCLEARPROC
, & [ _ ] [ ] const u8 {
\\pub const GLbitfield = c_uint;
2020-01-06 14:54:16 -08:00
\\pub const PFNGLCLEARPROC = ?fn (GLbitfield) callconv(.C) void;
\\pub const OpenGLProc = ?fn () callconv(.C) void;
2019-12-19 14:10:25 -08:00
\\const struct_unnamed_1 = extern struct {
2019-12-17 12:05:07 -08:00
\\ Clear: PFNGLCLEARPROC,
\\};
2019-12-15 06:50:20 -08:00
\\pub const union_OpenGLProcs = extern union {
\\ ptr: [1]OpenGLProc,
2019-12-17 12:05:07 -08:00
\\ gl: struct_unnamed_1,
2019-12-15 06:50:20 -08:00
\\};
\\pub extern var glProcs: union_OpenGLProcs;
,
\\pub const glClearPFN = PFNGLCLEARPROC;
2019-12-19 10:54:39 -08:00
,
\\pub inline fn glClearUnion(arg_2: GLbitfield) void {
\\ return glProcs.gl.Clear.?(arg_2);
\\}
2019-12-27 15:50:17 -08:00
,
2019-12-15 06:50:20 -08:00
\\pub const OpenGLProcs = union_OpenGLProcs;
} ) ;
2019-12-21 04:38:32 -08:00
cases . add ( " macro pointer cast " ,
2019-12-15 11:32:30 -08:00
\\#define NRF_GPIO ((NRF_GPIO_Type *) NRF_GPIO_BASE)
, & [ _ ] [ ] const u8 {
2020-03-08 01:26:53 -08:00
\\pub const NRF_GPIO = (if (@typeInfo(@TypeOf(NRF_GPIO_BASE)) == .Pointer) @ptrCast([*c]NRF_GPIO_Type, NRF_GPIO_BASE) else if (@typeInfo(@TypeOf(NRF_GPIO_BASE)) == .Int) @intToPtr([*c]NRF_GPIO_Type, NRF_GPIO_BASE) else @as([*c]NRF_GPIO_Type, NRF_GPIO_BASE));
2019-12-15 11:32:30 -08:00
} ) ;
2019-12-21 04:38:32 -08:00
cases . add ( " basic macro function " ,
2019-12-15 23:55:37 -08:00
\\extern int c;
2019-12-15 13:46:35 -08:00
\\#define BASIC(c) (c*2)
2020-02-12 23:09:49 -08:00
\\#define FOO(L,b) (L + b)
2019-12-15 13:46:35 -08:00
, & [ _ ] [ ] const u8 {
2019-12-15 23:55:37 -08:00
\\pub extern var c: c_int;
,
\\pub inline fn BASIC(c_1: var) @TypeOf(c_1 * 2) {
\\ return c_1 * 2;
2019-12-15 21:43:18 -08:00
\\}
2020-02-12 23:09:49 -08:00
,
\\pub inline fn FOO(L: var, b: var) @TypeOf(L + b) {
\\ return L + b;
\\}
2019-12-09 11:55:51 -08:00
} ) ;
2019-07-13 09:38:10 -07:00
2019-12-21 04:38:32 -08:00
cases . add ( " macro defines string literal with hex " ,
2019-12-15 21:43:18 -08:00
\\#define FOO "aoeu\xab derp"
2019-12-20 03:50:34 -08:00
\\#define FOO2 "aoeu\x0007a derp"
\\#define FOO_CHAR '\xfF'
2019-12-09 11:55:51 -08:00
, & [ _ ] [ ] const u8 {
2019-12-15 21:43:18 -08:00
\\pub const FOO = "aoeu\xab derp";
2019-12-14 03:09:35 -08:00
,
2019-12-20 03:50:34 -08:00
\\pub const FOO2 = "aoeu\x7a derp";
,
\\pub const FOO_CHAR = '\xff';
2019-12-09 11:55:51 -08:00
} ) ;
2019-05-11 09:05:33 -07:00
2019-12-27 06:37:32 -08:00
cases . add ( " macro add " ,
\\#define PERIPH_BASE (0x40000000UL) /*!< Base address of : AHB/APB Peripherals */
\\#define D3_APB1PERIPH_BASE (PERIPH_BASE + 0x18000000UL)
\\#define RCC_BASE (D3_AHB1PERIPH_BASE + 0x4400UL)
, & [ _ ] [ ] const u8 {
\\pub const PERIPH_BASE = @as(c_ulong, 0x40000000);
,
\\pub const D3_APB1PERIPH_BASE = PERIPH_BASE + @as(c_ulong, 0x18000000);
,
\\pub const RCC_BASE = D3_AHB1PERIPH_BASE + @as(c_ulong, 0x4400);
} ) ;
2019-12-21 04:38:32 -08:00
cases . add ( " variable aliasing " ,
2019-12-16 02:18:56 -08:00
\\static long a = 2;
\\static long b = 2;
\\static int c = 4;
\\void foo(char c) {
\\ int a;
\\ char b = 123;
\\ b = (char) a;
\\ {
\\ int d = 5;
\\ }
\\ unsigned d = 440;
\\}
, & [ _ ] [ ] const u8 {
2020-01-01 15:10:43 -08:00
\\pub var a: c_long = @bitCast(c_long, @as(c_long, @as(c_int, 2)));
\\pub var b: c_long = @bitCast(c_long, @as(c_long, @as(c_int, 2)));
2019-12-16 02:18:56 -08:00
\\pub var c: c_int = 4;
2019-12-31 17:39:33 -08:00
\\pub export fn foo(arg_c_1: u8) void {
\\ var c_1 = arg_c_1;
2019-12-16 02:18:56 -08:00
\\ var a_2: c_int = undefined;
2020-01-01 15:10:43 -08:00
\\ var b_3: u8 = @bitCast(u8, @truncate(i8, @as(c_int, 123)));
\\ b_3 = @bitCast(u8, @truncate(i8, a_2));
2019-12-16 02:18:56 -08:00
\\ {
\\ var d: c_int = 5;
\\ }
2020-01-01 15:10:43 -08:00
\\ var d: c_uint = @bitCast(c_uint, @as(c_int, 440));
2019-12-16 02:18:56 -08:00
\\}
} ) ;
2019-12-21 04:38:32 -08:00
cases . add ( " comma operator " ,
2019-12-29 01:45:39 -08:00
\\int foo() {
2019-12-16 05:22:37 -08:00
\\ 2, 4;
\\ return 2, 4, 6;
\\}
, & [ _ ] [ ] const u8 {
2019-12-29 01:45:39 -08:00
\\pub export fn foo() c_int {
2020-01-01 15:10:43 -08:00
\\ _ = @as(c_int, 2);
\\ _ = @as(c_int, 4);
\\ _ = @as(c_int, 2);
\\ _ = @as(c_int, 4);
\\ return @as(c_int, 6);
2019-12-16 05:22:37 -08:00
\\}
} ) ;
2019-12-29 01:45:39 -08:00
cases . add ( " worst-case assign " ,
\\int foo() {
2019-12-16 05:59:35 -08:00
\\ int a;
\\ int b;
\\ a = b = 2;
\\}
, & [ _ ] [ ] const u8 {
2019-12-29 01:45:39 -08:00
\\pub export fn foo() c_int {
2019-12-16 05:59:35 -08:00
\\ var a: c_int = undefined;
\\ var b: c_int = undefined;
2019-12-17 00:20:02 -08:00
\\ a = blk: {
2020-01-01 15:10:43 -08:00
\\ const tmp = @as(c_int, 2);
2019-12-31 17:39:33 -08:00
\\ b = tmp;
\\ break :blk tmp;
2019-12-16 05:59:35 -08:00
\\ };
\\}
} ) ;
2019-12-21 04:38:32 -08:00
cases . add ( " while loops " ,
2019-12-16 11:45:38 -08:00
\\int foo() {
\\ int a = 5;
\\ while (2)
\\ a = 2;
\\ while (4) {
\\ int a = 4;
\\ a = 9;
\\ return 6, a;
\\ }
\\ do {
\\ int a = 2;
\\ a = 12;
\\ } while (4);
\\ do
\\ a = 7;
\\ while (4);
\\}
, & [ _ ] [ ] const u8 {
\\pub export fn foo() c_int {
\\ var a: c_int = 5;
2020-01-01 15:10:43 -08:00
\\ while (@as(c_int, 2) != 0) a = 2;
\\ while (@as(c_int, 4) != 0) {
2019-12-31 17:39:33 -08:00
\\ var a_1: c_int = 4;
\\ a_1 = 9;
2020-01-01 15:10:43 -08:00
\\ _ = @as(c_int, 6);
2019-12-31 17:39:33 -08:00
\\ return a_1;
2019-12-16 11:45:38 -08:00
\\ }
\\ while (true) {
2019-12-31 17:39:33 -08:00
\\ var a_1: c_int = 2;
\\ a_1 = 12;
2020-01-01 15:10:43 -08:00
\\ if (!(@as(c_int, 4) != 0)) break;
2019-12-16 11:45:38 -08:00
\\ }
\\ while (true) {
\\ a = 7;
2020-01-01 15:10:43 -08:00
\\ if (!(@as(c_int, 4) != 0)) break;
2019-12-16 11:45:38 -08:00
\\ }
\\}
} ) ;
2019-12-21 04:38:32 -08:00
cases . add ( " for loops " ,
2019-12-16 15:08:08 -08:00
\\int foo() {
\\ for (int i = 2, b = 4; i + 2; i = 2) {
\\ int a = 2;
\\ a = 6, 5, 7;
\\ }
\\ char i = 2;
\\}
, & [ _ ] [ ] const u8 {
\\pub export fn foo() c_int {
\\ {
\\ var i: c_int = 2;
\\ var b: c_int = 4;
2020-01-01 15:10:43 -08:00
\\ while ((i + @as(c_int, 2)) != 0) : (i = 2) {
2019-12-16 15:08:08 -08:00
\\ var a: c_int = 2;
\\ a = 6;
2020-01-01 15:10:43 -08:00
\\ _ = @as(c_int, 5);
\\ _ = @as(c_int, 7);
2019-12-16 15:08:08 -08:00
\\ }
\\ }
2020-01-01 15:10:43 -08:00
\\ var i: u8 = @bitCast(u8, @truncate(i8, @as(c_int, 2)));
2019-12-16 15:08:08 -08:00
\\}
} ) ;
2019-12-21 04:38:32 -08:00
cases . add ( " shadowing primitive types " ,
2019-12-17 00:20:02 -08:00
\\unsigned anyerror = 2;
, & [ _ ] [ ] const u8 {
2020-01-01 15:10:43 -08:00
\\pub export var _anyerror: c_uint = @bitCast(c_uint, @as(c_int, 2));
2019-12-17 00:20:02 -08:00
} ) ;
2019-12-21 04:38:32 -08:00
cases . add ( " floats " ,
2019-12-17 01:15:41 -08:00
\\float a = 3.1415;
\\double b = 3.1415;
\\int c = 3.1415;
\\double d = 3;
, & [ _ ] [ ] const u8 {
\\pub export var a: f32 = @floatCast(f32, 3.1415);
\\pub export var b: f64 = 3.1415;
\\pub export var c: c_int = @floatToInt(c_int, 3.1415);
2020-01-01 15:10:43 -08:00
\\pub export var d: f64 = @intToFloat(f64, @as(c_int, 3));
2019-12-17 01:15:41 -08:00
} ) ;
2019-12-21 04:38:32 -08:00
cases . add ( " conditional operator " ,
2019-12-17 02:06:28 -08:00
\\int bar(void) {
\\ if (2 ? 5 : 5 ? 4 : 6) 2;
\\ return 2 ? 5 : 5 ? 4 : 6;
\\}
, & [ _ ] [ ] const u8 {
\\pub export fn bar() c_int {
2020-01-01 15:10:43 -08:00
\\ if ((if (@as(c_int, 2) != 0) @as(c_int, 5) else (if (@as(c_int, 5) != 0) @as(c_int, 4) else @as(c_int, 6))) != 0) _ = @as(c_int, 2);
\\ return if (@as(c_int, 2) != 0) @as(c_int, 5) else if (@as(c_int, 5) != 0) @as(c_int, 4) else @as(c_int, 6);
2019-12-17 02:06:28 -08:00
\\}
} ) ;
2019-12-21 04:38:32 -08:00
cases . add ( " switch on int " ,
2019-12-17 07:19:28 -08:00
\\int switch_fn(int i) {
\\ int res = 0;
\\ switch (i) {
\\ case 0:
\\ res = 1;
2019-12-20 01:35:21 -08:00
\\ case 1 ... 3:
2019-12-17 07:19:28 -08:00
\\ res = 2;
\\ default:
\\ res = 3 * i;
\\ break;
2019-12-20 01:35:21 -08:00
\\ case 4:
2019-12-17 07:19:28 -08:00
\\ res = 5;
\\ }
\\}
, & [ _ ] [ ] const u8 {
2019-12-31 17:39:33 -08:00
\\pub export fn switch_fn(arg_i: c_int) c_int {
\\ var i = arg_i;
2019-12-17 07:19:28 -08:00
\\ var res: c_int = 0;
\\ __switch: {
\\ __case_2: {
\\ __default: {
\\ __case_1: {
\\ __case_0: {
2019-12-31 17:39:33 -08:00
\\ switch (i) {
2020-01-08 01:19:04 -08:00
\\ @as(c_int, 0) => break :__case_0,
\\ @as(c_int, 1)...@as(c_int, 3) => break :__case_1,
2019-12-17 07:19:28 -08:00
\\ else => break :__default,
2020-01-08 01:19:04 -08:00
\\ @as(c_int, 4) => break :__case_2,
2019-12-17 07:19:28 -08:00
\\ }
\\ }
\\ res = 1;
\\ }
\\ res = 2;
\\ }
2020-01-01 15:10:43 -08:00
\\ res = (@as(c_int, 3) * i);
2019-12-17 07:19:28 -08:00
\\ break :__switch;
\\ }
\\ res = 5;
\\ }
\\}
} ) ;
2020-02-25 22:18:23 -08:00
if ( std . Target . current . os . tag ! = . windows ) {
2020-01-05 11:29:14 -08:00
// When clang uses the <arch>-windows-none triple it behaves as MSVC and
// interprets the inner `struct Bar` as an anonymous structure
cases . add ( " type referenced struct " ,
\\struct Foo {
\\ struct Bar{
\\ int b;
\\ };
\\ struct Bar c;
\\};
, & [ _ ] [ ] const u8 {
\\pub const struct_Bar = extern struct {
\\ b: c_int,
\\};
\\pub const struct_Foo = extern struct {
\\ c: struct_Bar,
\\};
} ) ;
}
2019-12-17 12:05:07 -08:00
2019-12-21 04:38:32 -08:00
cases . add ( " undefined array global " ,
2019-12-17 13:28:13 -08:00
\\int array[100] = {};
2019-12-09 11:55:51 -08:00
, & [ _ ] [ ] const u8 {
2020-01-30 10:53:35 -08:00
\\pub export var array: [100]c_int = [1]c_int{0} ** 100;
2019-12-09 11:55:51 -08:00
} ) ;
2019-05-08 16:21:54 -07:00
2019-12-21 04:38:32 -08:00
cases . add ( " restrict -> noalias " ,
2019-12-17 13:28:13 -08:00
\\void foo(void *restrict bar, void *restrict);
2019-12-09 11:55:51 -08:00
, & [ _ ] [ ] const u8 {
2019-12-19 14:10:25 -08:00
\\pub extern fn foo(noalias bar: ?*c_void, noalias ?*c_void) void;
2019-12-09 11:55:51 -08:00
} ) ;
2019-03-15 08:12:41 -07:00
2019-12-21 04:38:32 -08:00
cases . add ( " assign " ,
2019-12-17 13:28:13 -08:00
\\int max(int a) {
\\ int tmp;
\\ tmp = a;
\\ a = tmp;
2018-08-05 15:40:14 -07:00
\\}
2019-12-09 11:55:51 -08:00
, & [ _ ] [ ] const u8 {
2019-12-31 17:39:33 -08:00
\\pub export fn max(arg_a: c_int) c_int {
\\ var a = arg_a;
2019-12-17 13:28:13 -08:00
\\ var tmp: c_int = undefined;
2019-12-31 17:39:33 -08:00
\\ tmp = a;
\\ a = tmp;
2018-08-05 15:40:14 -07:00
\\}
2019-12-09 11:55:51 -08:00
} ) ;
2018-08-05 15:40:14 -07:00
2019-12-21 04:38:32 -08:00
cases . add ( " chaining assign " ,
2019-12-17 13:28:13 -08:00
\\void max(int a) {
\\ int b, c;
\\ c = b = a;
2018-08-05 15:32:38 -07:00
\\}
2019-12-17 13:28:13 -08:00
, & [ _ ] [ ] const u8 {
2019-12-31 17:39:33 -08:00
\\pub export fn max(arg_a: c_int) void {
\\ var a = arg_a;
2019-12-17 13:28:13 -08:00
\\ var b: c_int = undefined;
\\ var c: c_int = undefined;
\\ c = blk: {
2019-12-31 17:39:33 -08:00
\\ const tmp = a;
\\ b = tmp;
\\ break :blk tmp;
2019-12-17 13:28:13 -08:00
\\ };
2018-08-05 15:32:38 -07:00
\\}
2019-12-09 11:55:51 -08:00
} ) ;
2018-08-05 15:32:38 -07:00
2019-12-21 04:38:32 -08:00
cases . add ( " anonymous enum " ,
2019-12-17 13:28:13 -08:00
\\enum {
\\ One,
\\ Two,
\\};
2019-12-09 11:55:51 -08:00
, & [ _ ] [ ] const u8 {
2020-01-02 08:38:20 -08:00
\\pub const One = @enumToInt(enum_unnamed_1.One);
\\pub const Two = @enumToInt(enum_unnamed_1.Two);
2020-01-16 02:50:44 -08:00
\\const enum_unnamed_1 = extern enum(c_int) {
2019-12-17 13:28:13 -08:00
\\ One,
\\ Two,
2020-01-15 10:40:56 -08:00
\\ _,
2019-12-17 13:28:13 -08:00
\\};
2019-12-09 11:55:51 -08:00
} ) ;
2018-08-05 15:18:24 -07:00
2019-12-21 04:38:32 -08:00
cases . add ( " c style cast " ,
2019-12-17 13:28:13 -08:00
\\int float_to_int(float a) {
\\ return (int)a;
2018-08-05 15:06:39 -07:00
\\}
2019-12-09 11:55:51 -08:00
, & [ _ ] [ ] const u8 {
2019-12-31 17:39:33 -08:00
\\pub export fn float_to_int(arg_a: f32) c_int {
\\ var a = arg_a;
\\ return @floatToInt(c_int, a);
2018-08-05 15:06:39 -07:00
\\}
2019-12-09 11:55:51 -08:00
} ) ;
2018-08-05 15:06:39 -07:00
2020-01-01 15:10:43 -08:00
// TODO translate-c should in theory be able to figure out to drop all these casts
2019-12-21 04:38:32 -08:00
cases . add ( " escape sequences " ,
2019-12-17 15:04:01 -08:00
\\const char *escapes() {
\\char a = '\'',
\\ b = '\\',
\\ c = '\a',
\\ d = '\b',
\\ e = '\f',
\\ f = '\n',
\\ g = '\r',
\\ h = '\t',
\\ i = '\v',
\\ j = '\0',
\\ k = '\"';
\\ return "\'\\\a\b\f\n\r\t\v\0\"";
\\}
\\
, & [ _ ] [ ] const u8 {
\\pub export fn escapes() [*c]const u8 {
2020-01-01 15:10:43 -08:00
\\ var a: u8 = @bitCast(u8, @truncate(i8, @as(c_int, '\'')));
\\ var b: u8 = @bitCast(u8, @truncate(i8, @as(c_int, '\\')));
\\ var c: u8 = @bitCast(u8, @truncate(i8, @as(c_int, '\x07')));
\\ var d: u8 = @bitCast(u8, @truncate(i8, @as(c_int, '\x08')));
\\ var e: u8 = @bitCast(u8, @truncate(i8, @as(c_int, '\x0c')));
\\ var f: u8 = @bitCast(u8, @truncate(i8, @as(c_int, '\n')));
\\ var g: u8 = @bitCast(u8, @truncate(i8, @as(c_int, '\r')));
\\ var h: u8 = @bitCast(u8, @truncate(i8, @as(c_int, '\t')));
\\ var i: u8 = @bitCast(u8, @truncate(i8, @as(c_int, '\x0b')));
\\ var j: u8 = @bitCast(u8, @truncate(i8, @as(c_int, '\x00')));
\\ var k: u8 = @bitCast(u8, @truncate(i8, @as(c_int, '\"')));
2019-12-17 15:04:01 -08:00
\\ return "\'\\\x07\x08\x0c\n\r\t\x0b\x00\"";
\\}
} ) ;
2019-12-21 04:38:32 -08:00
cases . add ( " do loop " ,
2019-12-17 15:04:01 -08:00
\\void foo(void) {
\\ int a = 2;
\\ do {
\\ a = a - 1;
\\ } while (a);
\\
\\ int b = 2;
\\ do
\\ b = b -1;
\\ while (b);
\\}
, & [ _ ] [ ] const u8 {
\\pub export fn foo() void {
\\ var a: c_int = 2;
\\ while (true) {
2020-01-01 15:10:43 -08:00
\\ a = (a - @as(c_int, 1));
2019-12-17 15:04:01 -08:00
\\ if (!(a != 0)) break;
\\ }
\\ var b: c_int = 2;
\\ while (true) {
2020-01-01 15:10:43 -08:00
\\ b = (b - @as(c_int, 1));
2019-12-17 15:04:01 -08:00
\\ if (!(b != 0)) break;
\\ }
\\}
} ) ;
2019-12-21 04:38:32 -08:00
cases . add ( " logical and, logical or, on non-bool values, extra parens " ,
2019-12-17 23:51:40 -08:00
\\enum Foo {
\\ FooA,
\\ FooB,
\\ FooC,
\\};
\\typedef int SomeTypedef;
\\int and_or_non_bool(int a, float b, void *c) {
\\ enum Foo d = FooA;
\\ int e = (a && b);
\\ int f = (b && c);
\\ int g = (a && c);
\\ int h = (a || b);
\\ int i = (b || c);
\\ int j = (a || c);
\\ int k = (a || d);
\\ int l = (d && b);
\\ int m = (c || d);
\\ SomeTypedef td = 44;
\\ int o = (td || b);
\\ int p = (c && td);
\\ return ((((((((((e + f) + g) + h) + i) + j) + k) + l) + m) + o) + p);
\\}
2019-12-09 11:55:51 -08:00
, & [ _ ] [ ] const u8 {
2020-01-16 02:50:44 -08:00
\\pub const enum_Foo = extern enum(c_int) {
2019-12-17 23:51:40 -08:00
\\ A,
\\ B,
\\ C,
2020-01-15 10:40:56 -08:00
\\ _,
2019-12-17 23:51:40 -08:00
\\};
\\pub const SomeTypedef = c_int;
2019-12-31 17:39:33 -08:00
\\pub export fn and_or_non_bool(arg_a: c_int, arg_b: f32, arg_c: ?*c_void) c_int {
\\ var a = arg_a;
\\ var b = arg_b;
\\ var c = arg_c;
2019-12-22 02:53:57 -08:00
\\ var d: enum_Foo = @intToEnum(enum_Foo, FooA);
2019-12-31 17:39:33 -08:00
\\ var e: c_int = @boolToInt(((a != 0) and (b != 0)));
\\ var f: c_int = @boolToInt(((b != 0) and (c != null)));
\\ var g: c_int = @boolToInt(((a != 0) and (c != null)));
\\ var h: c_int = @boolToInt(((a != 0) or (b != 0)));
\\ var i: c_int = @boolToInt(((b != 0) or (c != null)));
\\ var j: c_int = @boolToInt(((a != 0) or (c != null)));
\\ var k: c_int = @boolToInt(((a != 0) or (@enumToInt(d) != 0)));
\\ var l: c_int = @boolToInt(((@enumToInt(d) != 0) and (b != 0)));
\\ var m: c_int = @boolToInt(((c != null) or (@enumToInt(d) != 0)));
2019-12-17 23:51:40 -08:00
\\ var td: SomeTypedef = 44;
2019-12-31 17:39:33 -08:00
\\ var o: c_int = @boolToInt(((td != 0) or (b != 0)));
\\ var p: c_int = @boolToInt(((c != null) and (td != 0)));
2019-12-17 23:51:40 -08:00
\\ return ((((((((((e + f) + g) + h) + i) + j) + k) + l) + m) + o) + p);
\\}
2019-12-18 02:47:35 -08:00
,
2019-12-17 23:51:40 -08:00
\\pub const Foo = enum_Foo;
2019-12-09 11:55:51 -08:00
} ) ;
2017-06-16 11:34:38 -07:00
2019-12-21 04:38:32 -08:00
cases . add ( " qualified struct and enum " ,
2019-12-18 02:47:35 -08:00
\\struct Foo {
\\ int x;
\\ int y;
\\};
\\enum Bar {
\\ BarA,
\\ BarB,
\\};
\\void func(struct Foo *a, enum Bar **b);
, & [ _ ] [ ] const u8 {
\\pub const struct_Foo = extern struct {
\\ x: c_int,
\\ y: c_int,
\\};
2019-12-22 02:53:57 -08:00
,
2020-01-16 02:50:44 -08:00
\\pub const enum_Bar = extern enum(c_int) {
2019-12-18 02:47:35 -08:00
\\ A,
\\ B,
2020-01-15 10:40:56 -08:00
\\ _,
2019-12-18 02:47:35 -08:00
\\};
\\pub extern fn func(a: [*c]struct_Foo, b: [*c][*c]enum_Bar) void;
,
\\pub const Foo = struct_Foo;
\\pub const Bar = enum_Bar;
} ) ;
2019-12-21 04:38:32 -08:00
cases . add ( " bitwise binary operators, simpler parens " ,
2019-12-18 02:47:35 -08:00
\\int max(int a, int b) {
2019-12-18 03:30:34 -08:00
\\ return (a & b) ^ (a | b);
2019-12-18 02:47:35 -08:00
\\}
, & [ _ ] [ ] const u8 {
2019-12-31 17:39:33 -08:00
\\pub export fn max(arg_a: c_int, arg_b: c_int) c_int {
\\ var a = arg_a;
\\ var b = arg_b;
\\ return ((a & b) ^ (a | b));
2019-12-18 02:47:35 -08:00
\\}
} ) ;
2019-12-21 04:38:32 -08:00
cases . add ( " comparison operators (no if) " , // TODO Come up with less contrived tests? Make sure to cover all these comparisons.
2019-12-18 02:47:35 -08:00
\\int test_comparisons(int a, int b) {
\\ int c = (a < b);
\\ int d = (a > b);
\\ int e = (a <= b);
\\ int f = (a >= b);
\\ int g = (c < d);
\\ int h = (e < f);
\\ int i = (g < h);
\\ return i;
\\}
, & [ _ ] [ ] const u8 {
2019-12-31 17:39:33 -08:00
\\pub export fn test_comparisons(arg_a: c_int, arg_b: c_int) c_int {
\\ var a = arg_a;
\\ var b = arg_b;
\\ var c: c_int = @boolToInt((a < b));
\\ var d: c_int = @boolToInt((a > b));
\\ var e: c_int = @boolToInt((a <= b));
\\ var f: c_int = @boolToInt((a >= b));
2019-12-18 15:38:42 -08:00
\\ var g: c_int = @boolToInt((c < d));
\\ var h: c_int = @boolToInt((e < f));
\\ var i: c_int = @boolToInt((g < h));
2019-12-18 02:47:35 -08:00
\\ return i;
\\}
} ) ;
2019-12-21 04:38:32 -08:00
cases . add ( " ==, != " ,
2019-12-18 02:47:35 -08:00
\\int max(int a, int b) {
2019-12-18 03:30:34 -08:00
\\ if (a == b)
\\ return a;
\\ if (a != b)
\\ return b;
\\ return a;
2019-12-18 02:47:35 -08:00
\\}
, & [ _ ] [ ] const u8 {
2019-12-31 17:39:33 -08:00
\\pub export fn max(arg_a: c_int, arg_b: c_int) c_int {
\\ var a = arg_a;
\\ var b = arg_b;
\\ if (a == b) return a;
\\ if (a != b) return b;
\\ return a;
2019-12-18 02:47:35 -08:00
\\}
} ) ;
2019-12-21 04:38:32 -08:00
cases . add ( " typedeffed bool expression " ,
2019-12-18 03:30:34 -08:00
\\typedef char* yes;
\\void foo(void) {
\\ yes a;
\\ if (a) 2;
\\}
, & [ _ ] [ ] const u8 {
\\pub const yes = [*c]u8;
\\pub export fn foo() void {
\\ var a: yes = undefined;
2020-01-01 15:10:43 -08:00
\\ if (a != null) _ = @as(c_int, 2);
2019-12-18 03:30:34 -08:00
\\}
} ) ;
2019-12-21 04:38:32 -08:00
cases . add ( " statement expression " ,
2019-12-18 11:20:38 -08:00
\\int foo(void) {
\\ return ({
\\ int a = 1;
\\ a;
\\ a;
\\ });
\\}
, & [ _ ] [ ] const u8 {
\\pub export fn foo() c_int {
\\ return (blk: {
\\ var a: c_int = 1;
\\ _ = a;
\\ break :blk a;
\\ });
\\}
} ) ;
2019-12-21 04:38:32 -08:00
cases . add ( " field access expression " ,
2019-12-18 12:29:42 -08:00
\\#define ARROW a->b
\\#define DOT a.b
\\extern struct Foo {
\\ int b;
\\}a;
\\float b = 2.0f;
\\int foo(void) {
\\ struct Foo *c;
\\ a.b;
\\ c->b;
\\}
, & [ _ ] [ ] const u8 {
\\pub const struct_Foo = extern struct {
\\ b: c_int,
\\};
\\pub extern var a: struct_Foo;
\\pub export var b: f32 = 2;
\\pub export fn foo() c_int {
\\ var c: [*c]struct_Foo = undefined;
\\ _ = a.b;
\\ _ = c.*.b;
\\}
,
\\pub const DOT = a.b;
,
2020-03-08 01:26:53 -08:00
\\pub const ARROW = a.*.b;
2019-12-18 12:29:42 -08:00
} ) ;
2019-12-21 04:38:32 -08:00
cases . add ( " array access " ,
2019-12-18 12:57:53 -08:00
\\#define ACCESS array[2]
\\int array[100] = {};
\\int foo(int index) {
\\ return array[index];
\\}
, & [ _ ] [ ] const u8 {
2020-01-30 10:53:35 -08:00
\\pub export var array: [100]c_int = [1]c_int{0} ** 100;
2019-12-31 17:39:33 -08:00
\\pub export fn foo(arg_index: c_int) c_int {
\\ var index = arg_index;
2020-01-09 21:08:24 -08:00
\\ return array[@intCast(c_uint, index)];
2019-12-18 12:57:53 -08:00
\\}
,
\\pub const ACCESS = array[2];
} ) ;
2020-01-09 21:08:24 -08:00
cases . add ( " cast signed array index to unsigned " ,
\\void foo() {
\\ int a[10], i = 0;
\\ a[i] = 0;
\\}
, & [ _ ] [ ] const u8 {
\\pub export fn foo() void {
\\ var a: [10]c_int = undefined;
\\ var i: c_int = 0;
\\ a[@intCast(c_uint, i)] = 0;
\\}
} ) ;
cases . add ( " long long array index cast to usize " ,
\\void foo() {
\\ long long a[10], i = 0;
\\ a[i] = 0;
\\}
, & [ _ ] [ ] const u8 {
\\pub export fn foo() void {
\\ var a: [10]c_longlong = undefined;
\\ var i: c_longlong = @bitCast(c_longlong, @as(c_longlong, @as(c_int, 0)));
\\ a[@intCast(usize, i)] = @bitCast(c_longlong, @as(c_longlong, @as(c_int, 0)));
\\}
} ) ;
cases . add ( " unsigned array index skips cast " ,
\\void foo() {
\\ unsigned int a[10], i = 0;
\\ a[i] = 0;
\\}
, & [ _ ] [ ] const u8 {
\\pub export fn foo() void {
\\ var a: [10]c_uint = undefined;
\\ var i: c_uint = @bitCast(c_uint, @as(c_int, 0));
\\ a[i] = @bitCast(c_uint, @as(c_int, 0));
\\}
} ) ;
2019-12-21 04:38:32 -08:00
cases . add ( " macro call " ,
2019-12-18 13:56:39 -08:00
\\#define CALL(arg) bar(arg)
, & [ _ ] [ ] const u8 {
\\pub inline fn CALL(arg: var) @TypeOf(bar(arg)) {
\\ return bar(arg);
\\}
} ) ;
2019-12-21 04:38:32 -08:00
cases . add ( " logical and, logical or " ,
2019-12-18 15:38:42 -08:00
\\int max(int a, int b) {
\\ if (a < b || a == b)
\\ return b;
\\ if (a >= b && a == b)
\\ return a;
\\ return a;
\\}
, & [ _ ] [ ] const u8 {
2019-12-31 17:39:33 -08:00
\\pub export fn max(arg_a: c_int, arg_b: c_int) c_int {
\\ var a = arg_a;
\\ var b = arg_b;
\\ if ((a < b) or (a == b)) return b;
\\ if ((a >= b) and (a == b)) return a;
\\ return a;
2019-12-18 15:38:42 -08:00
\\}
} ) ;
2020-01-01 15:10:43 -08:00
cases . add ( " simple if statement " ,
2019-12-18 15:38:42 -08:00
\\int max(int a, int b) {
\\ if (a < b)
\\ return b;
\\
\\ if (a < b)
\\ return b;
\\ else
\\ return a;
\\
\\ if (a < b) ; else ;
\\}
, & [ _ ] [ ] const u8 {
2019-12-31 17:39:33 -08:00
\\pub export fn max(arg_a: c_int, arg_b: c_int) c_int {
\\ var a = arg_a;
\\ var b = arg_b;
\\ if (a < b) return b;
\\ if (a < b) return b else return a;
\\ if (a < b) {} else {}
2019-12-18 15:38:42 -08:00
\\}
} ) ;
2020-01-01 15:10:43 -08:00
cases . add ( " if statements " ,
\\int foo() {
\\ if (2) {
\\ int a = 2;
\\ }
\\ if (2, 5) {
\\ int a = 2;
\\ }
\\}
, & [ _ ] [ ] const u8 {
\\pub export fn foo() c_int {
\\ if (@as(c_int, 2) != 0) {
\\ var a: c_int = 2;
\\ }
\\ if ((blk: {
\\ _ = @as(c_int, 2);
\\ break :blk @as(c_int, 5);
\\ }) != 0) {
\\ var a: c_int = 2;
\\ }
\\}
} ) ;
2019-12-21 04:38:32 -08:00
cases . add ( " if on non-bool " ,
2019-12-18 15:38:42 -08:00
\\enum SomeEnum { A, B, C };
\\int if_none_bool(int a, float b, void *c, enum SomeEnum d) {
\\ if (a) return 0;
\\ if (b) return 1;
\\ if (c) return 2;
\\ if (d) return 3;
\\ return 4;
\\}
, & [ _ ] [ ] const u8 {
2020-01-16 02:50:44 -08:00
\\pub const enum_SomeEnum = extern enum(c_int) {
2019-12-18 15:38:42 -08:00
\\ A,
\\ B,
\\ C,
2020-01-15 10:40:56 -08:00
\\ _,
2019-12-18 15:38:42 -08:00
\\};
2019-12-31 17:39:33 -08:00
\\pub export fn if_none_bool(arg_a: c_int, arg_b: f32, arg_c: ?*c_void, arg_d: enum_SomeEnum) c_int {
\\ var a = arg_a;
\\ var b = arg_b;
\\ var c = arg_c;
\\ var d = arg_d;
\\ if (a != 0) return 0;
\\ if (b != 0) return 1;
\\ if (c != null) return 2;
\\ if (d != 0) return 3;
2019-12-18 15:38:42 -08:00
\\ return 4;
\\}
} ) ;
2019-12-21 04:38:32 -08:00
cases . add ( " simple data types " ,
2017-04-19 13:59:20 -07:00
\\#include <stdint.h>
\\int foo(char a, unsigned char b, signed char c);
\\int foo(char a, unsigned char b, signed char c); // test a duplicate prototype
\\void bar(uint8_t a, uint16_t b, uint32_t c, uint64_t d);
\\void baz(int8_t a, int16_t b, int32_t c, int64_t d);
2019-12-09 11:55:51 -08:00
, & [ _ ] [ ] const u8 {
2018-01-25 01:10:11 -08:00
\\pub extern fn foo(a: u8, b: u8, c: i8) c_int;
\\pub extern fn bar(a: u8, b: u16, c: u32, d: u64) void;
\\pub extern fn baz(a: i8, b: i16, c: i32, d: i64) void;
2019-12-09 11:55:51 -08:00
} ) ;
2017-04-19 13:59:20 -07:00
2019-12-21 04:38:32 -08:00
cases . add ( " simple function " ,
2017-09-02 01:11:23 -07:00
\\int abs(int a) {
\\ return a < 0 ? -a : a;
\\}
2019-12-09 11:55:51 -08:00
, & [ _ ] [ ] const u8 {
2019-12-31 17:39:33 -08:00
\\pub export fn abs(arg_a: c_int) c_int {
\\ var a = arg_a;
2020-01-01 15:10:43 -08:00
\\ return if (a < @as(c_int, 0)) -a else a;
2019-12-18 23:39:39 -08:00
\\}
} ) ;
2019-12-21 04:38:32 -08:00
cases . add ( " post increment " ,
2019-12-18 23:39:39 -08:00
\\unsigned foo1(unsigned a) {
\\ a++;
\\ return a;
\\}
\\int foo2(int a) {
\\ a++;
\\ return a;
\\}
2019-12-31 14:33:55 -08:00
\\int *foo3(int *a) {
\\ a++;
\\ return a;
\\}
2019-12-18 23:39:39 -08:00
, & [ _ ] [ ] const u8 {
2019-12-31 17:39:33 -08:00
\\pub export fn foo1(arg_a: c_uint) c_uint {
\\ var a = arg_a;
\\ a +%= 1;
\\ return a;
2019-12-18 23:39:39 -08:00
\\}
2019-12-31 17:39:33 -08:00
\\pub export fn foo2(arg_a: c_int) c_int {
\\ var a = arg_a;
\\ a += 1;
\\ return a;
2019-12-18 23:39:39 -08:00
\\}
2019-12-31 17:39:33 -08:00
\\pub export fn foo3(arg_a: [*c]c_int) [*c]c_int {
\\ var a = arg_a;
\\ a += 1;
\\ return a;
2019-12-31 14:33:55 -08:00
\\}
2019-12-18 23:39:39 -08:00
} ) ;
2019-12-21 04:38:32 -08:00
cases . add ( " deref function pointer " ,
2019-12-18 23:39:39 -08:00
\\void foo(void) {}
\\int baz(void) { return 0; }
\\void bar(void) {
\\ void(*f)(void) = foo;
\\ int(*b)(void) = baz;
\\ f();
\\ (*(f))();
\\ foo();
\\ b();
\\ (*(b))();
\\ baz();
\\}
, & [ _ ] [ ] const u8 {
\\pub export fn foo() void {}
\\pub export fn baz() c_int {
\\ return 0;
\\}
\\pub export fn bar() void {
2020-01-06 14:54:16 -08:00
\\ var f: ?fn () callconv(.C) void = foo;
\\ var b: ?fn () callconv(.C) c_int = baz;
2019-12-18 23:39:39 -08:00
\\ f.?();
\\ (f).?();
\\ foo();
\\ _ = b.?();
\\ _ = (b).?();
\\ _ = baz();
2017-09-02 01:11:23 -07:00
\\}
2019-12-09 11:55:51 -08:00
} ) ;
2017-09-02 01:11:23 -07:00
2019-12-21 04:38:32 -08:00
cases . add ( " pre increment/decrement " ,
2019-12-19 00:48:32 -08:00
\\void foo(void) {
\\ int i = 0;
\\ unsigned u = 0;
\\ ++i;
\\ --i;
\\ ++u;
\\ --u;
\\ i = ++i;
\\ i = --i;
\\ u = ++u;
\\ u = --u;
\\}
, & [ _ ] [ ] const u8 {
\\pub export fn foo() void {
\\ var i: c_int = 0;
2020-01-01 15:10:43 -08:00
\\ var u: c_uint = @bitCast(c_uint, @as(c_int, 0));
2019-12-19 00:48:32 -08:00
\\ i += 1;
\\ i -= 1;
\\ u +%= 1;
\\ u -%= 1;
2019-12-22 02:53:57 -08:00
\\ i = (blk: {
2019-12-31 17:39:33 -08:00
\\ const ref = &i;
\\ ref.* += 1;
\\ break :blk ref.*;
2019-12-22 02:53:57 -08:00
\\ });
\\ i = (blk: {
2019-12-31 17:39:33 -08:00
\\ const ref = &i;
\\ ref.* -= 1;
\\ break :blk ref.*;
2019-12-22 02:53:57 -08:00
\\ });
\\ u = (blk: {
2019-12-31 17:39:33 -08:00
\\ const ref = &u;
\\ ref.* +%= 1;
\\ break :blk ref.*;
2019-12-22 02:53:57 -08:00
\\ });
\\ u = (blk: {
2019-12-31 17:39:33 -08:00
\\ const ref = &u;
\\ ref.* -%= 1;
\\ break :blk ref.*;
2019-12-22 02:53:57 -08:00
\\ });
2019-12-19 00:48:32 -08:00
\\}
} ) ;
2019-12-21 04:38:32 -08:00
cases . add ( " shift right assign " ,
2017-09-20 18:16:26 -07:00
\\int log2(unsigned a) {
\\ int i = 0;
\\ while (a > 0) {
2017-09-20 19:12:57 -07:00
\\ a >>= 1;
2017-09-20 18:16:26 -07:00
\\ }
\\ return i;
\\}
2019-12-19 14:10:25 -08:00
, & [ _ ] [ ] const u8 {
2019-12-31 17:39:33 -08:00
\\pub export fn log2(arg_a: c_uint) c_int {
\\ var a = arg_a;
2017-09-20 18:16:26 -07:00
\\ var i: c_int = 0;
2020-01-01 15:10:43 -08:00
\\ while (a > @bitCast(c_uint, @as(c_int, 0))) {
2020-01-03 19:55:47 -08:00
\\ a >>= @intCast(@import("std").math.Log2Int(c_int), 1);
2018-03-07 01:39:32 -08:00
\\ }
2017-09-20 18:16:26 -07:00
\\ return i;
\\}
2019-12-09 11:55:51 -08:00
} ) ;
2017-09-20 19:44:24 -07:00
2019-12-21 04:38:32 -08:00
cases . add ( " shift right assign with a fixed size type " ,
2017-09-20 19:44:24 -07:00
\\#include <stdint.h>
\\int log2(uint32_t a) {
\\ int i = 0;
\\ while (a > 0) {
\\ a >>= 1;
\\ }
\\ return i;
\\}
2019-12-09 11:55:51 -08:00
, & [ _ ] [ ] const u8 {
2019-12-31 17:39:33 -08:00
\\pub export fn log2(arg_a: u32) c_int {
\\ var a = arg_a;
2017-09-20 19:44:24 -07:00
\\ var i: c_int = 0;
2020-01-01 15:10:43 -08:00
\\ while (a > @bitCast(c_uint, @as(c_int, 0))) {
2020-01-03 19:55:47 -08:00
\\ a >>= @intCast(@import("std").math.Log2Int(c_int), 1);
2018-03-07 01:39:32 -08:00
\\ }
2017-09-20 19:44:24 -07:00
\\ return i;
\\}
2019-12-09 11:55:51 -08:00
} ) ;
2017-09-20 20:16:44 -07:00
2019-12-21 04:38:32 -08:00
cases . add ( " compound assignment operators " ,
2017-11-13 20:37:30 -08:00
\\void foo(void) {
\\ int a = 0;
\\ a += (a += 1);
\\ a -= (a -= 1);
\\ a *= (a *= 1);
\\ a &= (a &= 1);
\\ a |= (a |= 1);
\\ a ^= (a ^= 1);
\\ a >>= (a >>= 1);
\\ a <<= (a <<= 1);
\\}
2019-12-09 11:55:51 -08:00
, & [ _ ] [ ] const u8 {
2018-01-25 01:10:11 -08:00
\\pub export fn foo() void {
2017-11-13 20:37:30 -08:00
\\ var a: c_int = 0;
2019-12-19 06:07:33 -08:00
\\ a += (blk: {
2019-12-31 17:39:33 -08:00
\\ const ref = &a;
2020-01-01 15:10:43 -08:00
\\ ref.* = ref.* + @as(c_int, 1);
2019-12-31 17:39:33 -08:00
\\ break :blk ref.*;
2019-03-15 03:17:21 -07:00
\\ });
2019-12-19 06:07:33 -08:00
\\ a -= (blk: {
2019-12-31 17:39:33 -08:00
\\ const ref = &a;
2020-01-01 15:10:43 -08:00
\\ ref.* = ref.* - @as(c_int, 1);
2019-12-31 17:39:33 -08:00
\\ break :blk ref.*;
2019-03-15 03:17:21 -07:00
\\ });
2019-12-19 06:07:33 -08:00
\\ a *= (blk: {
2019-12-31 17:39:33 -08:00
\\ const ref = &a;
2020-01-01 15:10:43 -08:00
\\ ref.* = ref.* * @as(c_int, 1);
2019-12-31 17:39:33 -08:00
\\ break :blk ref.*;
2019-03-15 03:17:21 -07:00
\\ });
2019-12-19 06:07:33 -08:00
\\ a &= (blk: {
2019-12-31 17:39:33 -08:00
\\ const ref = &a;
2020-01-01 15:10:43 -08:00
\\ ref.* = ref.* & @as(c_int, 1);
2019-12-31 17:39:33 -08:00
\\ break :blk ref.*;
2019-03-15 03:17:21 -07:00
\\ });
2019-12-19 06:07:33 -08:00
\\ a |= (blk: {
2019-12-31 17:39:33 -08:00
\\ const ref = &a;
2020-01-01 15:10:43 -08:00
\\ ref.* = ref.* | @as(c_int, 1);
2019-12-31 17:39:33 -08:00
\\ break :blk ref.*;
2019-03-15 03:17:21 -07:00
\\ });
2019-12-19 06:07:33 -08:00
\\ a ^= (blk: {
2019-12-31 17:39:33 -08:00
\\ const ref = &a;
2020-01-01 15:10:43 -08:00
\\ ref.* = ref.* ^ @as(c_int, 1);
2019-12-31 17:39:33 -08:00
\\ break :blk ref.*;
2019-03-15 03:17:21 -07:00
\\ });
2020-01-03 19:55:47 -08:00
\\ a >>= @intCast(@import("std").math.Log2Int(c_int), (blk: {
2019-12-31 17:39:33 -08:00
\\ const ref = &a;
2020-01-03 19:55:47 -08:00
\\ ref.* = ref.* >> @intCast(@import("std").math.Log2Int(c_int), @as(c_int, 1));
2019-12-31 17:39:33 -08:00
\\ break :blk ref.*;
2019-03-15 03:17:21 -07:00
\\ }));
2020-01-03 19:55:47 -08:00
\\ a <<= @intCast(@import("std").math.Log2Int(c_int), (blk: {
2019-12-31 17:39:33 -08:00
\\ const ref = &a;
2020-01-03 19:55:47 -08:00
\\ ref.* = ref.* << @intCast(@import("std").math.Log2Int(c_int), @as(c_int, 1));
2019-12-31 17:39:33 -08:00
\\ break :blk ref.*;
2019-03-15 03:17:21 -07:00
\\ }));
2017-11-13 20:37:30 -08:00
\\}
2019-12-09 11:55:51 -08:00
} ) ;
2017-11-13 21:19:51 -08:00
2019-12-21 04:38:32 -08:00
cases . add ( " compound assignment operators unsigned " ,
2017-11-13 21:19:51 -08:00
\\void foo(void) {
\\ unsigned a = 0;
\\ a += (a += 1);
\\ a -= (a -= 1);
\\ a *= (a *= 1);
\\ a &= (a &= 1);
\\ a |= (a |= 1);
\\ a ^= (a ^= 1);
\\ a >>= (a >>= 1);
\\ a <<= (a <<= 1);
\\}
2019-12-09 11:55:51 -08:00
, & [ _ ] [ ] const u8 {
2018-01-25 01:10:11 -08:00
\\pub export fn foo() void {
2020-01-01 15:10:43 -08:00
\\ var a: c_uint = @bitCast(c_uint, @as(c_int, 0));
2019-12-19 06:07:33 -08:00
\\ a +%= (blk: {
2019-12-31 17:39:33 -08:00
\\ const ref = &a;
2020-01-01 15:10:43 -08:00
\\ ref.* = ref.* +% @bitCast(c_uint, @as(c_int, 1));
2019-12-31 17:39:33 -08:00
\\ break :blk ref.*;
2019-03-15 03:17:21 -07:00
\\ });
2019-12-19 06:07:33 -08:00
\\ a -%= (blk: {
2019-12-31 17:39:33 -08:00
\\ const ref = &a;
2020-01-01 15:10:43 -08:00
\\ ref.* = ref.* -% @bitCast(c_uint, @as(c_int, 1));
2019-12-31 17:39:33 -08:00
\\ break :blk ref.*;
2019-03-15 03:17:21 -07:00
\\ });
2019-12-19 06:07:33 -08:00
\\ a *%= (blk: {
2019-12-31 17:39:33 -08:00
\\ const ref = &a;
2020-01-01 15:10:43 -08:00
\\ ref.* = ref.* *% @bitCast(c_uint, @as(c_int, 1));
2019-12-31 17:39:33 -08:00
\\ break :blk ref.*;
2019-03-15 03:17:21 -07:00
\\ });
2019-12-19 06:07:33 -08:00
\\ a &= (blk: {
2019-12-31 17:39:33 -08:00
\\ const ref = &a;
2020-01-01 15:10:43 -08:00
\\ ref.* = ref.* & @bitCast(c_uint, @as(c_int, 1));
2019-12-31 17:39:33 -08:00
\\ break :blk ref.*;
2019-03-15 03:17:21 -07:00
\\ });
2019-12-19 06:07:33 -08:00
\\ a |= (blk: {
2019-12-31 17:39:33 -08:00
\\ const ref = &a;
2020-01-01 15:10:43 -08:00
\\ ref.* = ref.* | @bitCast(c_uint, @as(c_int, 1));
2019-12-31 17:39:33 -08:00
\\ break :blk ref.*;
2019-03-15 03:17:21 -07:00
\\ });
2019-12-19 06:07:33 -08:00
\\ a ^= (blk: {
2019-12-31 17:39:33 -08:00
\\ const ref = &a;
2020-01-01 15:10:43 -08:00
\\ ref.* = ref.* ^ @bitCast(c_uint, @as(c_int, 1));
2019-12-31 17:39:33 -08:00
\\ break :blk ref.*;
2019-03-15 03:17:21 -07:00
\\ });
2020-01-03 19:55:47 -08:00
\\ a >>= @intCast(@import("std").math.Log2Int(c_uint), (blk: {
2019-12-31 17:39:33 -08:00
\\ const ref = &a;
2020-01-03 19:55:47 -08:00
\\ ref.* = ref.* >> @intCast(@import("std").math.Log2Int(c_int), @as(c_int, 1));
2019-12-31 17:39:33 -08:00
\\ break :blk ref.*;
2019-03-15 03:17:21 -07:00
\\ }));
2020-01-03 19:55:47 -08:00
\\ a <<= @intCast(@import("std").math.Log2Int(c_uint), (blk: {
2019-12-31 17:39:33 -08:00
\\ const ref = &a;
2020-01-03 19:55:47 -08:00
\\ ref.* = ref.* << @intCast(@import("std").math.Log2Int(c_int), @as(c_int, 1));
2019-12-31 17:39:33 -08:00
\\ break :blk ref.*;
2019-03-15 03:17:21 -07:00
\\ }));
2017-11-13 21:19:51 -08:00
\\}
2019-12-09 11:55:51 -08:00
} ) ;
2017-11-13 21:19:51 -08:00
2019-12-21 04:38:32 -08:00
cases . add ( " post increment/decrement " ,
2017-11-13 21:19:51 -08:00
\\void foo(void) {
\\ int i = 0;
\\ unsigned u = 0;
\\ i++;
\\ i--;
\\ u++;
\\ u--;
\\ i = i++;
\\ i = i--;
\\ u = u++;
\\ u = u--;
\\}
2019-12-09 11:55:51 -08:00
, & [ _ ] [ ] const u8 {
2018-01-25 01:10:11 -08:00
\\pub export fn foo() void {
2017-11-13 21:19:51 -08:00
\\ var i: c_int = 0;
2020-01-01 15:10:43 -08:00
\\ var u: c_uint = @bitCast(c_uint, @as(c_int, 0));
2017-11-13 21:19:51 -08:00
\\ i += 1;
\\ i -= 1;
\\ u +%= 1;
\\ u -%= 1;
2019-12-22 02:53:57 -08:00
\\ i = (blk: {
2019-12-31 17:39:33 -08:00
\\ const ref = &i;
\\ const tmp = ref.*;
\\ ref.* += 1;
\\ break :blk tmp;
2019-12-22 02:53:57 -08:00
\\ });
\\ i = (blk: {
2019-12-31 17:39:33 -08:00
\\ const ref = &i;
\\ const tmp = ref.*;
\\ ref.* -= 1;
\\ break :blk tmp;
2019-12-22 02:53:57 -08:00
\\ });
\\ u = (blk: {
2019-12-31 17:39:33 -08:00
\\ const ref = &u;
\\ const tmp = ref.*;
\\ ref.* +%= 1;
\\ break :blk tmp;
2019-12-22 02:53:57 -08:00
\\ });
\\ u = (blk: {
2019-12-31 17:39:33 -08:00
\\ const ref = &u;
\\ const tmp = ref.*;
\\ ref.* -%= 1;
\\ break :blk tmp;
2019-12-22 02:53:57 -08:00
\\ });
2019-12-19 06:07:33 -08:00
\\}
} ) ;
2019-12-21 04:38:32 -08:00
cases . add ( " implicit casts " ,
2019-04-16 14:30:51 -07:00
\\#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);
\\
2019-12-29 01:45:39 -08:00
\\void call() {
2019-04-16 14:30:51 -07:00
\\ 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);
\\}
2019-12-09 11:55:51 -08:00
, & [ _ ] [ ] const u8 {
2019-04-16 14:30:51 -07:00
\\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;
2019-12-29 01:45:39 -08:00
\\pub export fn call() void {
2019-12-19 11:30:51 -08:00
\\ fn_int(@floatToInt(c_int, 3));
\\ fn_int(@floatToInt(c_int, 3));
\\ fn_int(@floatToInt(c_int, 3));
2020-01-01 15:10:43 -08:00
\\ fn_int(@as(c_int, 1094861636));
\\ fn_f32(@intToFloat(f32, @as(c_int, 3)));
\\ fn_f64(@intToFloat(f64, @as(c_int, 3)));
\\ fn_char(@bitCast(u8, @truncate(i8, @as(c_int, '3'))));
\\ fn_char(@bitCast(u8, @truncate(i8, @as(c_int, '\x01'))));
\\ fn_char(@bitCast(u8, @truncate(i8, @as(c_int, 0))));
2019-12-19 11:30:51 -08:00
\\ fn_f32(3);
\\ fn_f64(3);
2020-01-01 15:10:43 -08:00
\\ fn_bool(@as(c_int, 123) != 0);
\\ fn_bool(@as(c_int, 0) != 0);
2019-04-16 14:30:51 -07:00
\\ fn_bool(@ptrToInt(&fn_int) != 0);
\\ fn_int(@intCast(c_int, @ptrToInt(&fn_int)));
2020-01-01 15:10:43 -08:00
\\ fn_ptr(@intToPtr(?*c_void, @as(c_int, 42)));
2019-04-16 14:30:51 -07:00
\\}
2019-12-09 11:55:51 -08:00
} ) ;
2019-04-16 14:30:51 -07:00
2019-12-21 04:38:32 -08:00
cases . add ( " function call " ,
2019-12-19 14:10:25 -08:00
\\static void bar(void) { }
\\void foo(int *(baz)(void)) {
\\ bar();
\\ baz();
\\}
, & [ _ ] [ ] const u8 {
2019-12-28 12:28:18 -08:00
\\pub fn bar() callconv(.C) void {}
2020-01-06 12:34:50 -08:00
\\pub export fn foo(arg_baz: ?fn () callconv(.C) [*c]c_int) void {
2019-12-31 17:39:33 -08:00
\\ var baz = arg_baz;
2019-12-19 14:10:25 -08:00
\\ bar();
2019-12-31 17:39:33 -08:00
\\ _ = baz.?();
2019-12-19 14:10:25 -08:00
\\}
} ) ;
2019-12-21 04:38:32 -08:00
cases . add ( " macro defines string literal with octal " ,
2019-12-19 11:30:51 -08:00
\\#define FOO "aoeu\023 derp"
\\#define FOO2 "aoeu\0234 derp"
\\#define FOO_CHAR '\077'
, & [ _ ] [ ] const u8 {
\\pub const FOO = "aoeu\x13 derp";
,
2019-12-20 08:51:44 -08:00
\\pub const FOO2 = "aoeu\x134 derp";
2019-12-19 11:30:51 -08:00
,
2019-12-20 03:50:34 -08:00
\\pub const FOO_CHAR = '\x3f';
2019-12-19 11:30:51 -08:00
} ) ;
2019-12-21 04:38:32 -08:00
cases . add ( " enums " ,
2019-12-22 02:53:57 -08:00
\\enum Foo {
\\ FooA = 2,
\\ FooB = 5,
\\ Foo1,
\\};
, & [ _ ] [ ] const u8 {
2020-01-02 08:38:20 -08:00
\\pub const FooA = @enumToInt(enum_Foo.A);
\\pub const FooB = @enumToInt(enum_Foo.B);
\\pub const Foo1 = @enumToInt(enum_Foo.@"1");
2020-01-16 02:50:44 -08:00
\\pub const enum_Foo = extern enum(c_int) {
2019-12-22 02:53:57 -08:00
\\ A = 2,
\\ B = 5,
\\ @"1" = 6,
2020-01-15 10:40:56 -08:00
\\ _,
2019-12-22 02:53:57 -08:00
\\};
,
\\pub const Foo = enum_Foo;
} ) ;
2019-12-21 04:38:32 -08:00
cases . add ( " macro cast " ,
2019-12-27 15:50:17 -08:00
\\#define FOO(bar) baz((void *)(baz))
2020-02-14 03:37:39 -08:00
\\#define BAR (void*) a
2019-12-22 02:53:57 -08:00
, & [ _ ] [ ] const u8 {
2020-03-08 01:26:53 -08:00
\\pub inline fn FOO(bar: var) @TypeOf(baz((if (@typeInfo(@TypeOf(baz)) == .Pointer) @ptrCast(*c_void, baz) else if (@typeInfo(@TypeOf(baz)) == .Int) @intToPtr(*c_void, baz) else @as(*c_void, baz)))) {
\\ return baz((if (@typeInfo(@TypeOf(baz)) == .Pointer) @ptrCast(*c_void, baz) else if (@typeInfo(@TypeOf(baz)) == .Int) @intToPtr(*c_void, baz) else @as(*c_void, baz)));
2019-12-22 02:53:57 -08:00
\\}
2020-02-14 03:37:39 -08:00
,
2020-03-08 01:26:53 -08:00
\\pub const BAR = (if (@typeInfo(@TypeOf(a)) == .Pointer) @ptrCast(*c_void, a) else if (@typeInfo(@TypeOf(a)) == .Int) @intToPtr(*c_void, a) else @as(*c_void, a));
2019-12-22 02:53:57 -08:00
} ) ;
2019-12-21 04:38:32 -08:00
cases . add ( " macro conditional operator " ,
2019-12-28 12:32:18 -08:00
\\#define FOO a ? b : c
, & [ _ ] [ ] const u8 {
\\pub const FOO = if (a) b else c;
} ) ;
2019-12-29 07:09:31 -08:00
cases . add ( " do while as expr " ,
\\static void foo(void) {
\\ if (1)
\\ do {} while (0);
\\}
, & [ _ ] [ ] const u8 {
2020-01-02 10:01:38 -08:00
\\pub fn foo() callconv(.C) void {
2020-01-01 15:10:43 -08:00
\\ if (@as(c_int, 1) != 0) while (true) {
\\ if (!(@as(c_int, 0) != 0)) break;
2019-12-29 07:09:31 -08:00
\\ };
\\}
} ) ;
2019-12-29 10:10:20 -08:00
cases . add ( " macro comparisions " ,
\\#define MIN(a, b) ((b) < (a) ? (b) : (a))
\\#define MAX(a, b) ((b) > (a) ? (b) : (a))
, & [ _ ] [ ] const u8 {
\\pub inline fn MIN(a: var, b: var) @TypeOf(if (b < a) b else a) {
\\ return if (b < a) b else a;
\\}
,
\\pub inline fn MAX(a: var, b: var) @TypeOf(if (b > a) b else a) {
\\ return if (b > a) b else a;
\\}
} ) ;
2019-12-31 18:01:49 -08:00
// TODO: detect to use different block labels here
cases . add ( " nested assignment " ,
\\int foo(int *p, int x) {
\\ return *p++ = x;
\\}
, & [ _ ] [ ] const u8 {
\\pub export fn foo(arg_p: [*c]c_int, arg_x: c_int) c_int {
\\ var p = arg_p;
\\ var x = arg_x;
\\ return blk: {
\\ const tmp = x;
\\ (blk: {
\\ const ref = &p;
\\ const tmp_1 = ref.*;
\\ ref.* += 1;
\\ break :blk tmp_1;
\\ }).?.* = tmp;
\\ break :blk tmp;
\\ };
\\}
} ) ;
2020-01-01 15:10:43 -08:00
cases . add ( " widening and truncating integer casting to different signedness " ,
\\unsigned long foo(void) {
\\ return -1;
\\}
\\unsigned short bar(long x) {
\\ return x;
\\}
, & [ _ ] [ ] const u8 {
\\pub export fn foo() c_ulong {
\\ return @bitCast(c_ulong, @as(c_long, -@as(c_int, 1)));
\\}
\\pub export fn bar(arg_x: c_long) c_ushort {
\\ var x = arg_x;
\\ return @bitCast(c_ushort, @truncate(c_short, x));
\\}
} ) ;
2020-01-01 15:53:08 -08:00
cases . add ( " arg name aliasing decl which comes after " ,
\\int foo(int bar) {
\\ bar = 2;
\\}
\\int bar = 4;
, & [ _ ] [ ] const u8 {
\\pub export fn foo(arg_bar_1: c_int) c_int {
\\ var bar_1 = arg_bar_1;
\\ bar_1 = 2;
\\}
\\pub export var bar: c_int = 4;
} ) ;
2020-01-01 16:23:46 -08:00
cases . add ( " arg name aliasing macro which comes after " ,
\\int foo(int bar) {
\\ bar = 2;
\\}
\\#define bar 4
, & [ _ ] [ ] const u8 {
\\pub export fn foo(arg_bar_1: c_int) c_int {
\\ var bar_1 = arg_bar_1;
\\ bar_1 = 2;
\\}
,
\\pub const bar = 4;
} ) ;
2020-01-01 17:54:17 -08:00
cases . add ( " don't export inline functions " ,
\\inline void a(void) {}
\\static void b(void) {}
\\void c(void) {}
2020-01-02 01:51:35 -08:00
\\static void foo() {}
2020-01-01 17:54:17 -08:00
, & [ _ ] [ ] const u8 {
2020-01-02 10:01:38 -08:00
\\pub fn a() callconv(.C) void {}
\\pub fn b() callconv(.C) void {}
2020-01-01 17:54:17 -08:00
\\pub export fn c() void {}
2020-01-02 10:01:38 -08:00
\\pub fn foo() callconv(.C) void {}
2020-01-01 17:54:17 -08:00
} ) ;
2020-01-02 18:36:36 -08:00
cases . add ( " casting away const and volatile " ,
\\void foo(int *a) {}
\\void bar(const int *a) {
\\ foo((int *)a);
\\}
\\void baz(volatile int *a) {
\\ foo((int *)a);
\\}
, & [ _ ] [ ] const u8 {
\\pub export fn foo(arg_a: [*c]c_int) void {
\\ var a = arg_a;
\\}
\\pub export fn bar(arg_a: [*c]const c_int) void {
\\ var a = arg_a;
\\ foo(@intToPtr([*c]c_int, @ptrToInt(a)));
\\}
\\pub export fn baz(arg_a: [*c]volatile c_int) void {
\\ var a = arg_a;
\\ foo(@intToPtr([*c]c_int, @ptrToInt(a)));
\\}
} ) ;
2020-01-05 11:02:28 -08:00
cases . add ( " handling of _Bool type " ,
\\_Bool foo(_Bool x) {
\\ _Bool a = x != 1;
\\ _Bool b = a != 0;
\\ _Bool c = foo;
\\ return foo(c != b);
\\}
, & [ _ ] [ ] const u8 {
\\pub export fn foo(arg_x: bool) bool {
\\ var x = arg_x;
2020-01-07 01:54:42 -08:00
\\ var a: bool = (@intCast(c_int, @bitCast(i1, @intCast(u1, @boolToInt(x)))) != @as(c_int, 1));
\\ var b: bool = (@intCast(c_int, @bitCast(i1, @intCast(u1, @boolToInt(a)))) != @as(c_int, 0));
2020-01-05 11:02:28 -08:00
\\ var c: bool = @ptrToInt(foo) != 0;
2020-01-07 01:54:42 -08:00
\\ return foo((@intCast(c_int, @bitCast(i1, @intCast(u1, @boolToInt(c)))) != @intCast(c_int, @bitCast(i1, @intCast(u1, @boolToInt(b))))));
2020-01-05 11:02:28 -08:00
\\}
} ) ;
2020-01-24 12:32:32 -08:00
cases . add ( " Don't make const parameters mutable " ,
\\int max(const int x, int y) {
\\ return (x > y) ? x : y;
\\}
, & [ _ ] [ ] const u8 {
\\pub export fn max(x: c_int, arg_y: c_int) c_int {
\\ var y = arg_y;
\\ return if (x > y) x else y;
\\}
} ) ;
2017-11-26 17:05:55 -08:00
}