2017-04-19 13:59:20 -07:00
|
|
|
const tests = @import("tests.zig");
|
|
|
|
|
2018-01-25 01:10:11 -08:00
|
|
|
pub fn addCases(cases: &tests.TranslateCContext) void {
|
2017-04-19 13:59:20 -07:00
|
|
|
cases.addAllowWarnings("simple data types",
|
|
|
|
\\#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);
|
|
|
|
,
|
2018-01-25 01:10:11 -08:00
|
|
|
\\pub extern fn foo(a: u8, b: u8, c: i8) c_int;
|
2017-04-19 13:59:20 -07:00
|
|
|
,
|
2018-01-25 01:10:11 -08:00
|
|
|
\\pub extern fn bar(a: u8, b: u16, c: u32, d: u64) void;
|
2017-04-19 13:59:20 -07:00
|
|
|
,
|
2018-01-25 01:10:11 -08:00
|
|
|
\\pub extern fn baz(a: i8, b: i16, c: i32, d: i64) void;
|
2017-04-19 13:59:20 -07:00
|
|
|
);
|
|
|
|
|
|
|
|
cases.add("noreturn attribute",
|
|
|
|
\\void foo(void) __attribute__((noreturn));
|
|
|
|
,
|
2018-01-25 01:10:11 -08:00
|
|
|
\\pub extern fn foo() noreturn;
|
2017-04-19 13:59:20 -07:00
|
|
|
);
|
|
|
|
|
2017-10-01 18:42:33 -07:00
|
|
|
cases.addC("simple function",
|
2017-09-02 01:11:23 -07:00
|
|
|
\\int abs(int a) {
|
|
|
|
\\ return a < 0 ? -a : a;
|
|
|
|
\\}
|
|
|
|
,
|
2018-01-25 01:10:11 -08:00
|
|
|
\\export fn abs(a: c_int) c_int {
|
2017-09-02 01:11:23 -07:00
|
|
|
\\ return if (a < 0) -a else a;
|
|
|
|
\\}
|
|
|
|
);
|
|
|
|
|
2017-04-19 13:59:20 -07:00
|
|
|
cases.add("enums",
|
|
|
|
\\enum Foo {
|
|
|
|
\\ FooA,
|
|
|
|
\\ FooB,
|
|
|
|
\\ Foo1,
|
|
|
|
\\};
|
|
|
|
,
|
|
|
|
\\pub const enum_Foo = extern enum {
|
|
|
|
\\ A,
|
|
|
|
\\ B,
|
|
|
|
\\ @"1",
|
|
|
|
\\};
|
|
|
|
,
|
2017-09-04 21:21:02 -07:00
|
|
|
\\pub const FooA = enum_Foo.A;
|
2017-04-19 13:59:20 -07:00
|
|
|
,
|
2017-09-04 21:21:02 -07:00
|
|
|
\\pub const FooB = enum_Foo.B;
|
2017-04-19 13:59:20 -07:00
|
|
|
,
|
2017-09-04 21:21:02 -07:00
|
|
|
\\pub const Foo1 = enum_Foo.@"1";
|
2017-04-19 13:59:20 -07:00
|
|
|
,
|
2017-09-02 01:11:23 -07:00
|
|
|
\\pub const Foo = enum_Foo;
|
2017-04-19 13:59:20 -07:00
|
|
|
);
|
|
|
|
|
|
|
|
cases.add("restrict -> noalias",
|
|
|
|
\\void foo(void *restrict bar, void *restrict);
|
|
|
|
,
|
2018-01-25 01:10:11 -08:00
|
|
|
\\pub extern fn foo(noalias bar: ?&c_void, noalias arg1: ?&c_void) void;
|
2017-04-19 13:59:20 -07:00
|
|
|
);
|
|
|
|
|
|
|
|
cases.add("simple struct",
|
|
|
|
\\struct Foo {
|
|
|
|
\\ int x;
|
|
|
|
\\ char *y;
|
|
|
|
\\};
|
|
|
|
,
|
|
|
|
\\const struct_Foo = extern struct {
|
|
|
|
\\ x: c_int,
|
|
|
|
\\ y: ?&u8,
|
|
|
|
\\};
|
|
|
|
,
|
|
|
|
\\pub const Foo = struct_Foo;
|
|
|
|
);
|
|
|
|
|
|
|
|
cases.add("qualified struct and enum",
|
|
|
|
\\struct Foo {
|
|
|
|
\\ int x;
|
|
|
|
\\ int y;
|
|
|
|
\\};
|
|
|
|
\\enum Bar {
|
|
|
|
\\ BarA,
|
|
|
|
\\ BarB,
|
|
|
|
\\};
|
|
|
|
\\void func(struct Foo *a, enum Bar **b);
|
|
|
|
,
|
|
|
|
\\pub const struct_Foo = extern struct {
|
|
|
|
\\ x: c_int,
|
|
|
|
\\ y: c_int,
|
|
|
|
\\};
|
|
|
|
,
|
|
|
|
\\pub const enum_Bar = extern enum {
|
|
|
|
\\ A,
|
|
|
|
\\ B,
|
|
|
|
\\};
|
|
|
|
,
|
2017-09-04 21:21:02 -07:00
|
|
|
\\pub const BarA = enum_Bar.A;
|
2017-04-19 13:59:20 -07:00
|
|
|
,
|
2017-09-04 21:21:02 -07:00
|
|
|
\\pub const BarB = enum_Bar.B;
|
2017-04-19 13:59:20 -07:00
|
|
|
,
|
2018-01-25 01:10:11 -08:00
|
|
|
\\pub extern fn func(a: ?&struct_Foo, b: ?&(?&enum_Bar)) void;
|
2017-04-19 13:59:20 -07:00
|
|
|
,
|
|
|
|
\\pub const Foo = struct_Foo;
|
|
|
|
,
|
|
|
|
\\pub const Bar = enum_Bar;
|
|
|
|
);
|
|
|
|
|
|
|
|
cases.add("constant size array",
|
|
|
|
\\void func(int array[20]);
|
|
|
|
,
|
2018-01-25 01:10:11 -08:00
|
|
|
\\pub extern fn func(array: ?&c_int) void;
|
2017-04-19 13:59:20 -07:00
|
|
|
);
|
|
|
|
|
|
|
|
cases.add("self referential struct with function pointer",
|
|
|
|
\\struct Foo {
|
|
|
|
\\ void (*derp)(struct Foo *foo);
|
|
|
|
\\};
|
|
|
|
,
|
|
|
|
\\pub const struct_Foo = extern struct {
|
2018-01-25 01:10:11 -08:00
|
|
|
\\ derp: ?extern fn(?&struct_Foo) void,
|
2017-04-19 13:59:20 -07:00
|
|
|
\\};
|
|
|
|
,
|
|
|
|
\\pub const Foo = struct_Foo;
|
|
|
|
);
|
|
|
|
|
|
|
|
cases.add("struct prototype used in func",
|
|
|
|
\\struct Foo;
|
|
|
|
\\struct Foo *some_func(struct Foo *foo, int x);
|
|
|
|
,
|
|
|
|
\\pub const struct_Foo = @OpaqueType();
|
|
|
|
,
|
2018-01-25 01:10:11 -08:00
|
|
|
\\pub extern fn some_func(foo: ?&struct_Foo, x: c_int) ?&struct_Foo;
|
2017-04-19 13:59:20 -07:00
|
|
|
,
|
|
|
|
\\pub const Foo = struct_Foo;
|
|
|
|
);
|
|
|
|
|
|
|
|
cases.add("#define a char literal",
|
|
|
|
\\#define A_CHAR 'a'
|
|
|
|
,
|
|
|
|
\\pub const A_CHAR = 97;
|
|
|
|
);
|
|
|
|
|
|
|
|
cases.add("#define an unsigned integer literal",
|
|
|
|
\\#define CHANNEL_COUNT 24
|
|
|
|
,
|
|
|
|
\\pub const CHANNEL_COUNT = 24;
|
|
|
|
);
|
|
|
|
|
|
|
|
cases.add("#define referencing another #define",
|
|
|
|
\\#define THING2 THING1
|
|
|
|
\\#define THING1 1234
|
|
|
|
,
|
|
|
|
\\pub const THING1 = 1234;
|
|
|
|
,
|
|
|
|
\\pub const THING2 = THING1;
|
|
|
|
);
|
|
|
|
|
|
|
|
cases.add("variables",
|
|
|
|
\\extern int extern_var;
|
|
|
|
\\static const int int_var = 13;
|
|
|
|
,
|
|
|
|
\\pub extern var extern_var: c_int;
|
|
|
|
,
|
|
|
|
\\pub const int_var: c_int = 13;
|
|
|
|
);
|
|
|
|
|
|
|
|
cases.add("circular struct definitions",
|
|
|
|
\\struct Bar;
|
|
|
|
\\
|
|
|
|
\\struct Foo {
|
|
|
|
\\ struct Bar *next;
|
|
|
|
\\};
|
|
|
|
\\
|
|
|
|
\\struct Bar {
|
|
|
|
\\ struct Foo *next;
|
|
|
|
\\};
|
|
|
|
,
|
|
|
|
\\pub const struct_Bar = extern struct {
|
|
|
|
\\ next: ?&struct_Foo,
|
|
|
|
\\};
|
|
|
|
,
|
|
|
|
\\pub const struct_Foo = extern struct {
|
|
|
|
\\ next: ?&struct_Bar,
|
|
|
|
\\};
|
|
|
|
);
|
|
|
|
|
|
|
|
cases.add("typedef void",
|
|
|
|
\\typedef void Foo;
|
|
|
|
\\Foo fun(Foo *a);
|
|
|
|
,
|
|
|
|
\\pub const Foo = c_void;
|
|
|
|
,
|
2018-01-25 01:10:11 -08:00
|
|
|
\\pub extern fn fun(a: ?&Foo) Foo;
|
2017-04-19 13:59:20 -07:00
|
|
|
);
|
|
|
|
|
|
|
|
cases.add("generate inline func for #define global extern fn",
|
|
|
|
\\extern void (*fn_ptr)(void);
|
|
|
|
\\#define foo fn_ptr
|
|
|
|
\\
|
|
|
|
\\extern char (*fn_ptr2)(int, float);
|
|
|
|
\\#define bar fn_ptr2
|
|
|
|
,
|
2018-01-25 01:10:11 -08:00
|
|
|
\\pub extern var fn_ptr: ?extern fn() void;
|
2017-04-19 13:59:20 -07:00
|
|
|
,
|
2018-01-25 01:10:11 -08:00
|
|
|
\\pub inline fn foo() void {
|
2017-12-21 21:50:30 -08:00
|
|
|
\\ return (??fn_ptr)();
|
2017-09-04 21:45:09 -07:00
|
|
|
\\}
|
2017-04-19 13:59:20 -07:00
|
|
|
,
|
2018-01-25 01:10:11 -08:00
|
|
|
\\pub extern var fn_ptr2: ?extern fn(c_int, f32) u8;
|
2017-04-19 13:59:20 -07:00
|
|
|
,
|
2018-01-25 01:10:11 -08:00
|
|
|
\\pub inline fn bar(arg0: c_int, arg1: f32) u8 {
|
2017-12-21 21:50:30 -08:00
|
|
|
\\ return (??fn_ptr2)(arg0, arg1);
|
2017-09-04 21:45:09 -07:00
|
|
|
\\}
|
2017-04-19 13:59:20 -07:00
|
|
|
);
|
|
|
|
|
|
|
|
cases.add("#define string",
|
|
|
|
\\#define foo "a string"
|
|
|
|
,
|
2017-09-04 21:52:05 -07:00
|
|
|
\\pub const foo = c"a string";
|
2017-04-19 13:59:20 -07:00
|
|
|
);
|
|
|
|
|
|
|
|
cases.add("__cdecl doesn't mess up function pointers",
|
|
|
|
\\void foo(void (__cdecl *fn_ptr)(void));
|
|
|
|
,
|
2018-01-25 01:10:11 -08:00
|
|
|
\\pub extern fn foo(fn_ptr: ?extern fn() void) void;
|
2017-04-19 13:59:20 -07:00
|
|
|
);
|
|
|
|
|
|
|
|
cases.add("comment after integer literal",
|
|
|
|
\\#define SDL_INIT_VIDEO 0x00000020 /**< SDL_INIT_VIDEO implies SDL_INIT_EVENTS */
|
|
|
|
,
|
|
|
|
\\pub const SDL_INIT_VIDEO = 32;
|
|
|
|
);
|
|
|
|
|
2017-06-16 11:34:38 -07:00
|
|
|
cases.add("u integer suffix after hex literal",
|
|
|
|
\\#define SDL_INIT_VIDEO 0x00000020u /**< SDL_INIT_VIDEO implies SDL_INIT_EVENTS */
|
|
|
|
,
|
2017-09-04 21:52:05 -07:00
|
|
|
\\pub const SDL_INIT_VIDEO = c_uint(32);
|
2017-06-16 11:34:38 -07:00
|
|
|
);
|
|
|
|
|
|
|
|
cases.add("l integer suffix after hex literal",
|
|
|
|
\\#define SDL_INIT_VIDEO 0x00000020l /**< SDL_INIT_VIDEO implies SDL_INIT_EVENTS */
|
|
|
|
,
|
2017-09-04 21:52:05 -07:00
|
|
|
\\pub const SDL_INIT_VIDEO = c_long(32);
|
2017-06-16 11:34:38 -07:00
|
|
|
);
|
|
|
|
|
|
|
|
cases.add("ul integer suffix after hex literal",
|
|
|
|
\\#define SDL_INIT_VIDEO 0x00000020ul /**< SDL_INIT_VIDEO implies SDL_INIT_EVENTS */
|
|
|
|
,
|
2017-09-04 21:52:05 -07:00
|
|
|
\\pub const SDL_INIT_VIDEO = c_ulong(32);
|
2017-06-16 11:34:38 -07:00
|
|
|
);
|
|
|
|
|
|
|
|
cases.add("lu integer suffix after hex literal",
|
|
|
|
\\#define SDL_INIT_VIDEO 0x00000020lu /**< SDL_INIT_VIDEO implies SDL_INIT_EVENTS */
|
|
|
|
,
|
2017-09-04 21:52:05 -07:00
|
|
|
\\pub const SDL_INIT_VIDEO = c_ulong(32);
|
2017-06-16 11:34:38 -07:00
|
|
|
);
|
|
|
|
|
|
|
|
cases.add("ll integer suffix after hex literal",
|
|
|
|
\\#define SDL_INIT_VIDEO 0x00000020ll /**< SDL_INIT_VIDEO implies SDL_INIT_EVENTS */
|
|
|
|
,
|
2017-09-04 21:52:05 -07:00
|
|
|
\\pub const SDL_INIT_VIDEO = c_longlong(32);
|
2017-06-16 11:34:38 -07:00
|
|
|
);
|
|
|
|
|
|
|
|
cases.add("ull integer suffix after hex literal",
|
|
|
|
\\#define SDL_INIT_VIDEO 0x00000020ull /**< SDL_INIT_VIDEO implies SDL_INIT_EVENTS */
|
|
|
|
,
|
2017-09-04 21:52:05 -07:00
|
|
|
\\pub const SDL_INIT_VIDEO = c_ulonglong(32);
|
2017-06-16 11:34:38 -07:00
|
|
|
);
|
|
|
|
|
|
|
|
cases.add("llu integer suffix after hex literal",
|
|
|
|
\\#define SDL_INIT_VIDEO 0x00000020llu /**< SDL_INIT_VIDEO implies SDL_INIT_EVENTS */
|
|
|
|
,
|
2017-09-04 21:52:05 -07:00
|
|
|
\\pub const SDL_INIT_VIDEO = c_ulonglong(32);
|
2017-06-16 11:34:38 -07:00
|
|
|
);
|
|
|
|
|
2017-04-19 13:59:20 -07:00
|
|
|
cases.add("zig keywords in C code",
|
|
|
|
\\struct comptime {
|
|
|
|
\\ int defer;
|
|
|
|
\\};
|
|
|
|
,
|
|
|
|
\\pub const struct_comptime = extern struct {
|
|
|
|
\\ @"defer": c_int,
|
|
|
|
\\};
|
|
|
|
,
|
|
|
|
\\pub const @"comptime" = struct_comptime;
|
|
|
|
);
|
|
|
|
|
2017-09-10 13:35:56 -07:00
|
|
|
cases.add("macro defines string literal with hex",
|
|
|
|
\\#define FOO "aoeu\xab derp"
|
|
|
|
\\#define FOO2 "aoeu\x0007a derp"
|
|
|
|
\\#define FOO_CHAR '\xfF'
|
|
|
|
,
|
|
|
|
\\pub const FOO = c"aoeu\xab derp";
|
|
|
|
,
|
|
|
|
\\pub const FOO2 = c"aoeuz derp";
|
|
|
|
,
|
|
|
|
\\pub const FOO_CHAR = 255;
|
|
|
|
);
|
|
|
|
|
2017-04-19 13:59:20 -07:00
|
|
|
cases.add("macro defines string literal with octal",
|
|
|
|
\\#define FOO "aoeu\023 derp"
|
|
|
|
\\#define FOO2 "aoeu\0234 derp"
|
|
|
|
\\#define FOO_CHAR '\077'
|
|
|
|
,
|
2017-09-04 21:52:05 -07:00
|
|
|
\\pub const FOO = c"aoeu\x13 derp";
|
2017-04-19 13:59:20 -07:00
|
|
|
,
|
2017-09-04 21:52:05 -07:00
|
|
|
\\pub const FOO2 = c"aoeu\x134 derp";
|
2017-04-19 13:59:20 -07:00
|
|
|
,
|
|
|
|
\\pub const FOO_CHAR = 63;
|
|
|
|
);
|
2017-09-09 21:20:09 -07:00
|
|
|
|
|
|
|
cases.add("macro with parens around negative number",
|
|
|
|
\\#define LUA_GLOBALSINDEX (-10002)
|
|
|
|
,
|
|
|
|
\\pub const LUA_GLOBALSINDEX = -10002;
|
|
|
|
);
|
2017-09-20 18:16:26 -07:00
|
|
|
|
2017-10-01 18:42:33 -07:00
|
|
|
cases.addC("post increment",
|
2017-09-20 21:27:13 -07:00
|
|
|
\\unsigned foo1(unsigned a) {
|
|
|
|
\\ a++;
|
|
|
|
\\ return a;
|
|
|
|
\\}
|
|
|
|
\\int foo2(int a) {
|
|
|
|
\\ a++;
|
|
|
|
\\ return a;
|
|
|
|
\\}
|
|
|
|
,
|
2018-01-25 01:10:11 -08:00
|
|
|
\\pub export fn foo1(_arg_a: c_uint) c_uint {
|
2017-09-20 21:27:13 -07:00
|
|
|
\\ var a = _arg_a;
|
|
|
|
\\ a +%= 1;
|
|
|
|
\\ return a;
|
|
|
|
\\}
|
2018-01-25 01:10:11 -08:00
|
|
|
\\pub export fn foo2(_arg_a: c_int) c_int {
|
2017-09-20 21:27:13 -07:00
|
|
|
\\ var a = _arg_a;
|
|
|
|
\\ a += 1;
|
|
|
|
\\ return a;
|
|
|
|
\\}
|
|
|
|
);
|
|
|
|
|
2017-10-01 18:42:33 -07:00
|
|
|
cases.addC("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;
|
|
|
|
\\}
|
|
|
|
,
|
2018-01-25 01:10:11 -08:00
|
|
|
\\pub export fn log2(_arg_a: c_uint) c_int {
|
2017-09-20 18:16:26 -07:00
|
|
|
\\ var a = _arg_a;
|
|
|
|
\\ var i: c_int = 0;
|
|
|
|
\\ while (a > c_uint(0)) {
|
2017-09-20 19:12:57 -07:00
|
|
|
\\ a >>= @import("std").math.Log2Int(c_uint)(1);
|
2018-03-07 01:39:32 -08:00
|
|
|
\\ }
|
2017-09-20 18:16:26 -07:00
|
|
|
\\ return i;
|
|
|
|
\\}
|
|
|
|
);
|
2017-09-20 19:44:24 -07:00
|
|
|
|
2017-10-01 18:42:33 -07:00
|
|
|
cases.addC("if statement",
|
2017-09-20 21:27:13 -07:00
|
|
|
\\int max(int a, int b) {
|
|
|
|
\\ if (a < b)
|
|
|
|
\\ return b;
|
|
|
|
\\
|
|
|
|
\\ if (a < b)
|
|
|
|
\\ return b;
|
|
|
|
\\ else
|
|
|
|
\\ return a;
|
|
|
|
\\}
|
|
|
|
,
|
2018-01-25 01:10:11 -08:00
|
|
|
\\pub export fn max(a: c_int, b: c_int) c_int {
|
2017-09-20 21:27:13 -07:00
|
|
|
\\ if (a < b) return b;
|
|
|
|
\\ if (a < b) return b else return a;
|
|
|
|
\\}
|
|
|
|
);
|
|
|
|
|
2017-10-01 18:42:33 -07:00
|
|
|
cases.addC("==, !=",
|
2017-09-20 21:47:43 -07:00
|
|
|
\\int max(int a, int b) {
|
|
|
|
\\ if (a == b)
|
|
|
|
\\ return a;
|
|
|
|
\\ if (a != b)
|
|
|
|
\\ return b;
|
|
|
|
\\ return a;
|
|
|
|
\\}
|
|
|
|
,
|
2018-01-25 01:10:11 -08:00
|
|
|
\\pub export fn max(a: c_int, b: c_int) c_int {
|
2017-09-20 21:47:43 -07:00
|
|
|
\\ if (a == b) return a;
|
|
|
|
\\ if (a != b) return b;
|
|
|
|
\\ return a;
|
|
|
|
\\}
|
|
|
|
);
|
|
|
|
|
2017-10-01 18:42:33 -07:00
|
|
|
cases.addC("add, sub, mul, div, rem",
|
2017-09-20 22:36:33 -07:00
|
|
|
\\int s(int a, int b) {
|
|
|
|
\\ int c;
|
|
|
|
\\ c = a + b;
|
|
|
|
\\ c = a - b;
|
|
|
|
\\ c = a * b;
|
|
|
|
\\ c = a / b;
|
|
|
|
\\ c = a % b;
|
|
|
|
\\}
|
|
|
|
\\unsigned u(unsigned a, unsigned b) {
|
|
|
|
\\ unsigned c;
|
|
|
|
\\ c = a + b;
|
|
|
|
\\ c = a - b;
|
|
|
|
\\ c = a * b;
|
|
|
|
\\ c = a / b;
|
|
|
|
\\ c = a % b;
|
|
|
|
\\}
|
|
|
|
,
|
2018-01-25 01:10:11 -08:00
|
|
|
\\pub export fn s(a: c_int, b: c_int) c_int {
|
2018-01-16 06:21:48 -08:00
|
|
|
\\ var c: c_int = undefined;
|
2017-09-20 22:36:33 -07:00
|
|
|
\\ c = (a + b);
|
|
|
|
\\ c = (a - b);
|
|
|
|
\\ c = (a * b);
|
|
|
|
\\ c = @divTrunc(a, b);
|
|
|
|
\\ c = @rem(a, b);
|
|
|
|
\\}
|
2018-01-25 01:10:11 -08:00
|
|
|
\\pub export fn u(a: c_uint, b: c_uint) c_uint {
|
2018-01-16 06:21:48 -08:00
|
|
|
\\ var c: c_uint = undefined;
|
2017-09-20 22:36:33 -07:00
|
|
|
\\ c = (a +% b);
|
|
|
|
\\ c = (a -% b);
|
|
|
|
\\ c = (a *% b);
|
|
|
|
\\ c = (a / b);
|
|
|
|
\\ c = (a % b);
|
|
|
|
\\}
|
|
|
|
);
|
|
|
|
|
2017-10-01 18:42:33 -07:00
|
|
|
cases.addC("bitwise binary operators",
|
2017-09-20 22:04:51 -07:00
|
|
|
\\int max(int a, int b) {
|
|
|
|
\\ return (a & b) ^ (a | b);
|
|
|
|
\\}
|
|
|
|
,
|
2018-01-25 01:10:11 -08:00
|
|
|
\\pub export fn max(a: c_int, b: c_int) c_int {
|
2017-09-20 22:04:51 -07:00
|
|
|
\\ return (a & b) ^ (a | b);
|
|
|
|
\\}
|
|
|
|
);
|
|
|
|
|
2017-10-01 18:42:33 -07:00
|
|
|
cases.addC("logical and, logical or",
|
2017-09-20 21:37:56 -07:00
|
|
|
\\int max(int a, int b) {
|
|
|
|
\\ if (a < b || a == b)
|
|
|
|
\\ return b;
|
|
|
|
\\ if (a >= b && a == b)
|
|
|
|
\\ return a;
|
|
|
|
\\ return a;
|
|
|
|
\\}
|
|
|
|
,
|
2018-01-25 01:10:11 -08:00
|
|
|
\\pub export fn max(a: c_int, b: c_int) c_int {
|
2017-09-20 21:37:56 -07:00
|
|
|
\\ if ((a < b) or (a == b)) return b;
|
|
|
|
\\ if ((a >= b) and (a == b)) return a;
|
|
|
|
\\ return a;
|
|
|
|
\\}
|
|
|
|
);
|
|
|
|
|
2017-10-01 18:42:33 -07:00
|
|
|
cases.addC("assign",
|
2017-09-20 22:14:39 -07:00
|
|
|
\\int max(int a) {
|
|
|
|
\\ int tmp;
|
|
|
|
\\ tmp = a;
|
2017-09-20 22:41:07 -07:00
|
|
|
\\ a = tmp;
|
2017-09-20 22:14:39 -07:00
|
|
|
\\}
|
|
|
|
,
|
2018-01-25 01:10:11 -08:00
|
|
|
\\pub export fn max(_arg_a: c_int) c_int {
|
2017-09-20 22:41:07 -07:00
|
|
|
\\ var a = _arg_a;
|
2018-01-16 06:21:48 -08:00
|
|
|
\\ var tmp: c_int = undefined;
|
2017-09-20 22:14:39 -07:00
|
|
|
\\ tmp = a;
|
2017-09-20 22:41:07 -07:00
|
|
|
\\ a = tmp;
|
2017-09-20 22:14:39 -07:00
|
|
|
\\}
|
|
|
|
);
|
|
|
|
|
2017-10-01 18:42:33 -07:00
|
|
|
cases.addC("chaining assign",
|
2017-09-20 23:45:46 -07:00
|
|
|
\\void max(int a) {
|
|
|
|
\\ int b, c;
|
|
|
|
\\ c = b = a;
|
|
|
|
\\}
|
|
|
|
,
|
2018-01-25 01:10:11 -08:00
|
|
|
\\pub export fn max(a: c_int) void {
|
2018-01-16 06:21:48 -08:00
|
|
|
\\ var b: c_int = undefined;
|
|
|
|
\\ var c: c_int = undefined;
|
2017-12-21 21:50:30 -08:00
|
|
|
\\ c = x: {
|
2017-09-20 23:45:46 -07:00
|
|
|
\\ const _tmp = a;
|
|
|
|
\\ b = _tmp;
|
2017-12-21 21:50:30 -08:00
|
|
|
\\ break :x _tmp;
|
2017-09-20 23:45:46 -07:00
|
|
|
\\ };
|
|
|
|
\\}
|
|
|
|
);
|
|
|
|
|
2017-10-01 18:42:33 -07:00
|
|
|
cases.addC("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;
|
|
|
|
\\}
|
|
|
|
,
|
2018-01-25 01:10:11 -08:00
|
|
|
\\pub export fn log2(_arg_a: u32) c_int {
|
2017-09-20 19:44:24 -07:00
|
|
|
\\ var a = _arg_a;
|
|
|
|
\\ var i: c_int = 0;
|
|
|
|
\\ while (a > c_uint(0)) {
|
|
|
|
\\ a >>= u5(1);
|
2018-03-07 01:39:32 -08:00
|
|
|
\\ }
|
2017-09-20 19:44:24 -07:00
|
|
|
\\ return i;
|
|
|
|
\\}
|
|
|
|
);
|
2017-09-20 20:16:44 -07:00
|
|
|
|
|
|
|
cases.add("anonymous enum",
|
|
|
|
\\enum {
|
|
|
|
\\ One,
|
|
|
|
\\ Two,
|
|
|
|
\\};
|
|
|
|
,
|
|
|
|
\\pub const One = 0;
|
|
|
|
\\pub const Two = 1;
|
|
|
|
);
|
2017-09-20 21:02:18 -07:00
|
|
|
|
2017-10-01 18:42:33 -07:00
|
|
|
cases.addC("function call",
|
2017-09-20 21:02:18 -07:00
|
|
|
\\static void bar(void) { }
|
|
|
|
\\void foo(void) { bar(); }
|
|
|
|
,
|
2018-01-25 01:10:11 -08:00
|
|
|
\\pub fn bar() void {}
|
|
|
|
\\pub export fn foo() void {
|
2017-09-20 21:02:18 -07:00
|
|
|
\\ bar();
|
|
|
|
\\}
|
|
|
|
);
|
2017-09-20 21:54:08 -07:00
|
|
|
|
2017-10-01 18:42:33 -07:00
|
|
|
cases.addC("field access expression",
|
2017-09-20 21:54:08 -07:00
|
|
|
\\struct Foo {
|
|
|
|
\\ int field;
|
|
|
|
\\};
|
|
|
|
\\int read_field(struct Foo *foo) {
|
|
|
|
\\ return foo->field;
|
|
|
|
\\}
|
|
|
|
,
|
|
|
|
\\pub const struct_Foo = extern struct {
|
|
|
|
\\ field: c_int,
|
|
|
|
\\};
|
2018-01-25 01:10:11 -08:00
|
|
|
\\pub export fn read_field(foo: ?&struct_Foo) c_int {
|
2017-09-20 21:54:08 -07:00
|
|
|
\\ return (??foo).field;
|
|
|
|
\\}
|
|
|
|
);
|
2017-09-20 22:04:43 -07:00
|
|
|
|
2017-10-01 18:42:33 -07:00
|
|
|
cases.addC("null statements",
|
2017-09-20 22:04:43 -07:00
|
|
|
\\void foo(void) {
|
|
|
|
\\ ;;;;;
|
|
|
|
\\}
|
|
|
|
,
|
2018-01-25 01:10:11 -08:00
|
|
|
\\pub export fn foo() void {}
|
2017-09-20 22:04:43 -07:00
|
|
|
);
|
2017-09-20 22:22:50 -07:00
|
|
|
|
|
|
|
cases.add("undefined array global",
|
|
|
|
\\int array[100];
|
|
|
|
,
|
|
|
|
\\pub var array: [100]c_int = undefined;
|
|
|
|
);
|
2017-09-20 22:38:16 -07:00
|
|
|
|
2017-10-01 18:42:33 -07:00
|
|
|
cases.addC("array access",
|
2017-09-20 22:38:16 -07:00
|
|
|
\\int array[100];
|
|
|
|
\\int foo(int index) {
|
|
|
|
\\ return array[index];
|
|
|
|
\\}
|
|
|
|
,
|
|
|
|
\\pub var array: [100]c_int = undefined;
|
2018-01-25 01:10:11 -08:00
|
|
|
\\pub export fn foo(index: c_int) c_int {
|
2017-09-20 22:38:16 -07:00
|
|
|
\\ return array[index];
|
|
|
|
\\}
|
|
|
|
);
|
|
|
|
|
2017-09-20 22:54:51 -07:00
|
|
|
|
2017-10-01 18:42:33 -07:00
|
|
|
cases.addC("c style cast",
|
2017-09-20 22:54:51 -07:00
|
|
|
\\int float_to_int(float a) {
|
|
|
|
\\ return (int)a;
|
|
|
|
\\}
|
|
|
|
,
|
2018-01-25 01:10:11 -08:00
|
|
|
\\pub export fn float_to_int(a: f32) c_int {
|
2017-09-20 22:54:51 -07:00
|
|
|
\\ return c_int(a);
|
|
|
|
\\}
|
|
|
|
);
|
2017-09-20 23:31:52 -07:00
|
|
|
|
2017-10-01 18:42:33 -07:00
|
|
|
cases.addC("implicit cast to void *",
|
2017-09-20 23:31:52 -07:00
|
|
|
\\void *foo(unsigned short *x) {
|
|
|
|
\\ return x;
|
|
|
|
\\}
|
|
|
|
,
|
2018-01-25 01:10:11 -08:00
|
|
|
\\pub export fn foo(x: ?&c_ushort) ?&c_void {
|
2017-09-20 23:31:52 -07:00
|
|
|
\\ return @ptrCast(?&c_void, x);
|
|
|
|
\\}
|
|
|
|
);
|
2017-09-20 23:37:42 -07:00
|
|
|
|
2017-10-01 18:42:33 -07:00
|
|
|
cases.addC("sizeof",
|
2017-09-20 23:37:42 -07:00
|
|
|
\\#include <stddef.h>
|
|
|
|
\\size_t size_of(void) {
|
|
|
|
\\ return sizeof(int);
|
|
|
|
\\}
|
|
|
|
,
|
2018-01-25 01:10:11 -08:00
|
|
|
\\pub export fn size_of() usize {
|
2017-09-20 23:37:42 -07:00
|
|
|
\\ return @sizeOf(c_int);
|
|
|
|
\\}
|
|
|
|
);
|
2017-11-13 18:39:46 -08:00
|
|
|
|
|
|
|
cases.addC("null pointer implicit cast",
|
|
|
|
\\int* foo(void) {
|
|
|
|
\\ return 0;
|
|
|
|
\\}
|
|
|
|
,
|
2018-01-25 01:10:11 -08:00
|
|
|
\\pub export fn foo() ?&c_int {
|
2017-11-13 18:39:46 -08:00
|
|
|
\\ return null;
|
|
|
|
\\}
|
|
|
|
);
|
2017-09-20 23:31:52 -07:00
|
|
|
|
2017-11-13 18:59:32 -08:00
|
|
|
cases.addC("comma operator",
|
|
|
|
\\int foo(void) {
|
|
|
|
\\ return 1, 2;
|
|
|
|
\\}
|
|
|
|
,
|
2018-01-25 01:10:11 -08:00
|
|
|
\\pub export fn foo() c_int {
|
2017-12-21 21:50:30 -08:00
|
|
|
\\ return x: {
|
2017-11-13 18:59:32 -08:00
|
|
|
\\ _ = 1;
|
2017-12-21 21:50:30 -08:00
|
|
|
\\ break :x 2;
|
2017-11-13 18:59:32 -08:00
|
|
|
\\ };
|
|
|
|
\\}
|
|
|
|
);
|
2017-11-13 19:33:41 -08:00
|
|
|
|
2017-11-13 19:49:53 -08:00
|
|
|
cases.addC("bitshift",
|
|
|
|
\\int foo(void) {
|
|
|
|
\\ return (1 << 2) >> 1;
|
|
|
|
\\}
|
|
|
|
,
|
2018-01-25 01:10:11 -08:00
|
|
|
\\pub export fn foo() c_int {
|
2017-11-13 19:49:53 -08:00
|
|
|
\\ return (1 << @import("std").math.Log2Int(c_int)(2)) >> @import("std").math.Log2Int(c_int)(1);
|
|
|
|
\\}
|
|
|
|
);
|
|
|
|
|
2017-11-13 20:37:30 -08:00
|
|
|
cases.addC("compound assignment operators",
|
|
|
|
\\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);
|
|
|
|
\\}
|
|
|
|
,
|
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;
|
2017-12-21 21:50:30 -08:00
|
|
|
\\ a += x: {
|
2017-11-13 20:37:30 -08:00
|
|
|
\\ const _ref = &a;
|
|
|
|
\\ (*_ref) = ((*_ref) + 1);
|
2017-12-21 21:50:30 -08:00
|
|
|
\\ break :x *_ref;
|
2017-11-13 20:37:30 -08:00
|
|
|
\\ };
|
2017-12-21 21:50:30 -08:00
|
|
|
\\ a -= x: {
|
2017-11-13 20:37:30 -08:00
|
|
|
\\ const _ref = &a;
|
|
|
|
\\ (*_ref) = ((*_ref) - 1);
|
2017-12-21 21:50:30 -08:00
|
|
|
\\ break :x *_ref;
|
2017-11-13 20:37:30 -08:00
|
|
|
\\ };
|
2017-12-21 21:50:30 -08:00
|
|
|
\\ a *= x: {
|
2017-11-13 20:37:30 -08:00
|
|
|
\\ const _ref = &a;
|
|
|
|
\\ (*_ref) = ((*_ref) * 1);
|
2017-12-21 21:50:30 -08:00
|
|
|
\\ break :x *_ref;
|
2017-11-13 20:37:30 -08:00
|
|
|
\\ };
|
2017-12-21 21:50:30 -08:00
|
|
|
\\ a &= x: {
|
2017-11-13 20:37:30 -08:00
|
|
|
\\ const _ref = &a;
|
|
|
|
\\ (*_ref) = ((*_ref) & 1);
|
2017-12-21 21:50:30 -08:00
|
|
|
\\ break :x *_ref;
|
2017-11-13 20:37:30 -08:00
|
|
|
\\ };
|
2017-12-21 21:50:30 -08:00
|
|
|
\\ a |= x: {
|
2017-11-13 20:37:30 -08:00
|
|
|
\\ const _ref = &a;
|
|
|
|
\\ (*_ref) = ((*_ref) | 1);
|
2017-12-21 21:50:30 -08:00
|
|
|
\\ break :x *_ref;
|
2017-11-13 20:37:30 -08:00
|
|
|
\\ };
|
2017-12-21 21:50:30 -08:00
|
|
|
\\ a ^= x: {
|
2017-11-13 20:37:30 -08:00
|
|
|
\\ const _ref = &a;
|
|
|
|
\\ (*_ref) = ((*_ref) ^ 1);
|
2017-12-21 21:50:30 -08:00
|
|
|
\\ break :x *_ref;
|
2017-11-13 20:37:30 -08:00
|
|
|
\\ };
|
2017-12-21 21:50:30 -08:00
|
|
|
\\ a >>= @import("std").math.Log2Int(c_int)(x: {
|
2017-11-13 20:37:30 -08:00
|
|
|
\\ const _ref = &a;
|
2017-11-26 17:05:55 -08:00
|
|
|
\\ (*_ref) = ((*_ref) >> @import("std").math.Log2Int(c_int)(1));
|
2017-12-21 21:50:30 -08:00
|
|
|
\\ break :x *_ref;
|
2017-11-13 20:37:30 -08:00
|
|
|
\\ });
|
2017-12-21 21:50:30 -08:00
|
|
|
\\ a <<= @import("std").math.Log2Int(c_int)(x: {
|
2017-11-13 20:37:30 -08:00
|
|
|
\\ const _ref = &a;
|
2017-11-26 17:05:55 -08:00
|
|
|
\\ (*_ref) = ((*_ref) << @import("std").math.Log2Int(c_int)(1));
|
2017-12-21 21:50:30 -08:00
|
|
|
\\ break :x *_ref;
|
2017-11-13 20:37:30 -08:00
|
|
|
\\ });
|
|
|
|
\\}
|
|
|
|
);
|
2017-11-13 21:19:51 -08:00
|
|
|
|
|
|
|
cases.addC("compound assignment operators unsigned",
|
|
|
|
\\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);
|
|
|
|
\\}
|
|
|
|
,
|
2018-01-25 01:10:11 -08:00
|
|
|
\\pub export fn foo() void {
|
2017-11-13 21:19:51 -08:00
|
|
|
\\ var a: c_uint = c_uint(0);
|
2017-12-21 21:50:30 -08:00
|
|
|
\\ a +%= x: {
|
2017-11-13 21:19:51 -08:00
|
|
|
\\ const _ref = &a;
|
|
|
|
\\ (*_ref) = ((*_ref) +% c_uint(1));
|
2017-12-21 21:50:30 -08:00
|
|
|
\\ break :x *_ref;
|
2017-11-13 21:19:51 -08:00
|
|
|
\\ };
|
2017-12-21 21:50:30 -08:00
|
|
|
\\ a -%= x: {
|
2017-11-13 21:19:51 -08:00
|
|
|
\\ const _ref = &a;
|
|
|
|
\\ (*_ref) = ((*_ref) -% c_uint(1));
|
2017-12-21 21:50:30 -08:00
|
|
|
\\ break :x *_ref;
|
2017-11-13 21:19:51 -08:00
|
|
|
\\ };
|
2017-12-21 21:50:30 -08:00
|
|
|
\\ a *%= x: {
|
2017-11-13 21:19:51 -08:00
|
|
|
\\ const _ref = &a;
|
|
|
|
\\ (*_ref) = ((*_ref) *% c_uint(1));
|
2017-12-21 21:50:30 -08:00
|
|
|
\\ break :x *_ref;
|
2017-11-13 21:19:51 -08:00
|
|
|
\\ };
|
2017-12-21 21:50:30 -08:00
|
|
|
\\ a &= x: {
|
2017-11-13 21:19:51 -08:00
|
|
|
\\ const _ref = &a;
|
|
|
|
\\ (*_ref) = ((*_ref) & c_uint(1));
|
2017-12-21 21:50:30 -08:00
|
|
|
\\ break :x *_ref;
|
2017-11-13 21:19:51 -08:00
|
|
|
\\ };
|
2017-12-21 21:50:30 -08:00
|
|
|
\\ a |= x: {
|
2017-11-13 21:19:51 -08:00
|
|
|
\\ const _ref = &a;
|
|
|
|
\\ (*_ref) = ((*_ref) | c_uint(1));
|
2017-12-21 21:50:30 -08:00
|
|
|
\\ break :x *_ref;
|
2017-11-13 21:19:51 -08:00
|
|
|
\\ };
|
2017-12-21 21:50:30 -08:00
|
|
|
\\ a ^= x: {
|
2017-11-13 21:19:51 -08:00
|
|
|
\\ const _ref = &a;
|
|
|
|
\\ (*_ref) = ((*_ref) ^ c_uint(1));
|
2017-12-21 21:50:30 -08:00
|
|
|
\\ break :x *_ref;
|
2017-11-13 21:19:51 -08:00
|
|
|
\\ };
|
2017-12-21 21:50:30 -08:00
|
|
|
\\ a >>= @import("std").math.Log2Int(c_uint)(x: {
|
2017-11-13 21:19:51 -08:00
|
|
|
\\ const _ref = &a;
|
2017-11-26 17:05:55 -08:00
|
|
|
\\ (*_ref) = ((*_ref) >> @import("std").math.Log2Int(c_uint)(1));
|
2017-12-21 21:50:30 -08:00
|
|
|
\\ break :x *_ref;
|
2017-11-13 21:19:51 -08:00
|
|
|
\\ });
|
2017-12-21 21:50:30 -08:00
|
|
|
\\ a <<= @import("std").math.Log2Int(c_uint)(x: {
|
2017-11-13 21:19:51 -08:00
|
|
|
\\ const _ref = &a;
|
2017-11-26 17:05:55 -08:00
|
|
|
\\ (*_ref) = ((*_ref) << @import("std").math.Log2Int(c_uint)(1));
|
2017-12-21 21:50:30 -08:00
|
|
|
\\ break :x *_ref;
|
2017-11-13 21:19:51 -08:00
|
|
|
\\ });
|
|
|
|
\\}
|
|
|
|
);
|
|
|
|
|
2017-11-13 19:33:41 -08:00
|
|
|
cases.addC("duplicate typedef",
|
|
|
|
\\typedef long foo;
|
|
|
|
\\typedef int bar;
|
|
|
|
\\typedef long foo;
|
|
|
|
\\typedef int baz;
|
|
|
|
,
|
|
|
|
\\pub const foo = c_long;
|
|
|
|
\\pub const bar = c_int;
|
|
|
|
\\pub const baz = c_int;
|
|
|
|
);
|
2017-11-13 21:19:51 -08:00
|
|
|
|
|
|
|
cases.addC("post increment/decrement",
|
|
|
|
\\void foo(void) {
|
|
|
|
\\ int i = 0;
|
|
|
|
\\ unsigned u = 0;
|
|
|
|
\\ i++;
|
|
|
|
\\ i--;
|
|
|
|
\\ u++;
|
|
|
|
\\ u--;
|
|
|
|
\\ i = i++;
|
|
|
|
\\ i = i--;
|
|
|
|
\\ u = u++;
|
|
|
|
\\ u = u--;
|
|
|
|
\\}
|
|
|
|
,
|
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;
|
|
|
|
\\ var u: c_uint = c_uint(0);
|
|
|
|
\\ i += 1;
|
|
|
|
\\ i -= 1;
|
|
|
|
\\ u +%= 1;
|
|
|
|
\\ u -%= 1;
|
2017-12-21 21:50:30 -08:00
|
|
|
\\ i = x: {
|
2017-11-13 21:19:51 -08:00
|
|
|
\\ const _ref = &i;
|
|
|
|
\\ const _tmp = *_ref;
|
|
|
|
\\ (*_ref) += 1;
|
2017-12-21 21:50:30 -08:00
|
|
|
\\ break :x _tmp;
|
2017-11-13 21:19:51 -08:00
|
|
|
\\ };
|
2017-12-21 21:50:30 -08:00
|
|
|
\\ i = x: {
|
2017-11-13 21:19:51 -08:00
|
|
|
\\ const _ref = &i;
|
|
|
|
\\ const _tmp = *_ref;
|
|
|
|
\\ (*_ref) -= 1;
|
2017-12-21 21:50:30 -08:00
|
|
|
\\ break :x _tmp;
|
2017-11-13 21:19:51 -08:00
|
|
|
\\ };
|
2017-12-21 21:50:30 -08:00
|
|
|
\\ u = x: {
|
2017-11-13 21:19:51 -08:00
|
|
|
\\ const _ref = &u;
|
|
|
|
\\ const _tmp = *_ref;
|
|
|
|
\\ (*_ref) +%= 1;
|
2017-12-21 21:50:30 -08:00
|
|
|
\\ break :x _tmp;
|
2017-11-13 21:19:51 -08:00
|
|
|
\\ };
|
2017-12-21 21:50:30 -08:00
|
|
|
\\ u = x: {
|
2017-11-13 21:19:51 -08:00
|
|
|
\\ const _ref = &u;
|
|
|
|
\\ const _tmp = *_ref;
|
|
|
|
\\ (*_ref) -%= 1;
|
2017-12-21 21:50:30 -08:00
|
|
|
\\ break :x _tmp;
|
2017-11-13 21:19:51 -08:00
|
|
|
\\ };
|
|
|
|
\\}
|
|
|
|
);
|
2017-11-13 21:56:20 -08:00
|
|
|
|
2017-11-24 13:36:39 -08:00
|
|
|
cases.addC("pre increment/decrement",
|
|
|
|
\\void foo(void) {
|
|
|
|
\\ int i = 0;
|
|
|
|
\\ unsigned u = 0;
|
|
|
|
\\ ++i;
|
|
|
|
\\ --i;
|
|
|
|
\\ ++u;
|
|
|
|
\\ --u;
|
|
|
|
\\ i = ++i;
|
|
|
|
\\ i = --i;
|
|
|
|
\\ u = ++u;
|
|
|
|
\\ u = --u;
|
|
|
|
\\}
|
|
|
|
,
|
2018-01-25 01:10:11 -08:00
|
|
|
\\pub export fn foo() void {
|
2017-11-24 13:36:39 -08:00
|
|
|
\\ var i: c_int = 0;
|
|
|
|
\\ var u: c_uint = c_uint(0);
|
|
|
|
\\ i += 1;
|
|
|
|
\\ i -= 1;
|
|
|
|
\\ u +%= 1;
|
|
|
|
\\ u -%= 1;
|
2017-12-21 21:50:30 -08:00
|
|
|
\\ i = x: {
|
2017-11-24 13:36:39 -08:00
|
|
|
\\ const _ref = &i;
|
|
|
|
\\ (*_ref) += 1;
|
2017-12-21 21:50:30 -08:00
|
|
|
\\ break :x *_ref;
|
2017-11-24 13:36:39 -08:00
|
|
|
\\ };
|
2017-12-21 21:50:30 -08:00
|
|
|
\\ i = x: {
|
2017-11-24 13:36:39 -08:00
|
|
|
\\ const _ref = &i;
|
|
|
|
\\ (*_ref) -= 1;
|
2017-12-21 21:50:30 -08:00
|
|
|
\\ break :x *_ref;
|
2017-11-24 13:36:39 -08:00
|
|
|
\\ };
|
2017-12-21 21:50:30 -08:00
|
|
|
\\ u = x: {
|
2017-11-24 13:36:39 -08:00
|
|
|
\\ const _ref = &u;
|
|
|
|
\\ (*_ref) +%= 1;
|
2017-12-21 21:50:30 -08:00
|
|
|
\\ break :x *_ref;
|
2017-11-24 13:36:39 -08:00
|
|
|
\\ };
|
2017-12-21 21:50:30 -08:00
|
|
|
\\ u = x: {
|
2017-11-24 13:36:39 -08:00
|
|
|
\\ const _ref = &u;
|
|
|
|
\\ (*_ref) -%= 1;
|
2017-12-21 21:50:30 -08:00
|
|
|
\\ break :x *_ref;
|
2017-11-24 13:36:39 -08:00
|
|
|
\\ };
|
|
|
|
\\}
|
|
|
|
);
|
|
|
|
|
2017-11-13 21:56:20 -08:00
|
|
|
cases.addC("do loop",
|
|
|
|
\\void foo(void) {
|
|
|
|
\\ int a = 2;
|
|
|
|
\\ do {
|
|
|
|
\\ a--;
|
|
|
|
\\ } while (a != 0);
|
|
|
|
\\
|
|
|
|
\\ int b = 2;
|
|
|
|
\\ do
|
|
|
|
\\ b--;
|
|
|
|
\\ while (b != 0);
|
|
|
|
\\}
|
|
|
|
,
|
2018-01-25 01:10:11 -08:00
|
|
|
\\pub export fn foo() void {
|
2017-11-13 21:56:20 -08:00
|
|
|
\\ var a: c_int = 2;
|
|
|
|
\\ while (true) {
|
|
|
|
\\ a -= 1;
|
|
|
|
\\ if (!(a != 0)) break;
|
2018-03-07 01:39:32 -08:00
|
|
|
\\ }
|
2017-11-13 21:56:20 -08:00
|
|
|
\\ var b: c_int = 2;
|
|
|
|
\\ while (true) {
|
|
|
|
\\ b -= 1;
|
|
|
|
\\ if (!(b != 0)) break;
|
2018-03-07 01:39:32 -08:00
|
|
|
\\ }
|
2017-11-13 21:56:20 -08:00
|
|
|
\\}
|
|
|
|
);
|
2017-11-13 23:10:13 -08:00
|
|
|
|
|
|
|
cases.addC("deref function pointer",
|
|
|
|
\\void foo(void) {}
|
2017-11-26 17:05:55 -08:00
|
|
|
\\void baz(void) {}
|
2017-11-13 23:10:13 -08:00
|
|
|
\\void bar(void) {
|
|
|
|
\\ void(*f)(void) = foo;
|
|
|
|
\\ f();
|
|
|
|
\\ (*(f))();
|
2017-11-26 17:05:55 -08:00
|
|
|
\\ baz();
|
2017-11-13 23:10:13 -08:00
|
|
|
\\}
|
|
|
|
,
|
2018-01-25 01:10:11 -08:00
|
|
|
\\pub export fn foo() void {}
|
|
|
|
\\pub export fn baz() void {}
|
|
|
|
\\pub export fn bar() void {
|
|
|
|
\\ var f: ?extern fn() void = foo;
|
2017-11-13 23:10:13 -08:00
|
|
|
\\ (??f)();
|
|
|
|
\\ (??f)();
|
2017-11-26 17:05:55 -08:00
|
|
|
\\ baz();
|
2017-11-13 23:10:13 -08:00
|
|
|
\\}
|
|
|
|
);
|
|
|
|
|
|
|
|
cases.addC("normal deref",
|
|
|
|
\\void foo(int *x) {
|
|
|
|
\\ *x = 1;
|
|
|
|
\\}
|
|
|
|
,
|
2018-01-25 01:10:11 -08:00
|
|
|
\\pub export fn foo(x: ?&c_int) void {
|
2017-12-07 09:27:29 -08:00
|
|
|
\\ (*??x) = 1;
|
2017-11-13 23:10:13 -08:00
|
|
|
\\}
|
|
|
|
);
|
2017-11-16 20:54:33 -08:00
|
|
|
|
|
|
|
cases.add("simple union",
|
|
|
|
\\union Foo {
|
|
|
|
\\ int x;
|
|
|
|
\\ double y;
|
|
|
|
\\};
|
|
|
|
,
|
|
|
|
\\pub const union_Foo = extern union {
|
|
|
|
\\ x: c_int,
|
|
|
|
\\ y: f64,
|
|
|
|
\\};
|
|
|
|
,
|
|
|
|
\\pub const Foo = union_Foo;
|
|
|
|
);
|
|
|
|
|
2017-11-17 09:11:03 -08:00
|
|
|
cases.add("address of operator",
|
|
|
|
\\int foo(void) {
|
|
|
|
\\ int x = 1234;
|
|
|
|
\\ int *ptr = &x;
|
|
|
|
\\ return *ptr;
|
|
|
|
\\}
|
|
|
|
,
|
2018-01-25 01:10:11 -08:00
|
|
|
\\pub fn foo() c_int {
|
2017-11-17 09:11:03 -08:00
|
|
|
\\ var x: c_int = 1234;
|
|
|
|
\\ var ptr: ?&c_int = &x;
|
2017-12-07 09:27:29 -08:00
|
|
|
\\ return *??ptr;
|
2017-11-17 09:11:03 -08:00
|
|
|
\\}
|
|
|
|
);
|
2017-11-24 16:26:05 -08:00
|
|
|
|
|
|
|
cases.add("string literal",
|
|
|
|
\\const char *foo(void) {
|
|
|
|
\\ return "bar";
|
|
|
|
\\}
|
|
|
|
,
|
2018-01-25 01:10:11 -08:00
|
|
|
\\pub fn foo() ?&const u8 {
|
2017-11-24 16:26:05 -08:00
|
|
|
\\ return c"bar";
|
|
|
|
\\}
|
|
|
|
);
|
2017-11-24 21:25:47 -08:00
|
|
|
|
|
|
|
cases.add("return void",
|
|
|
|
\\void foo(void) {
|
|
|
|
\\ return;
|
|
|
|
\\}
|
|
|
|
,
|
2018-01-25 01:10:11 -08:00
|
|
|
\\pub fn foo() void {
|
2017-11-24 21:25:47 -08:00
|
|
|
\\ return;
|
|
|
|
\\}
|
|
|
|
);
|
2017-11-24 21:57:48 -08:00
|
|
|
|
|
|
|
cases.add("for loop",
|
|
|
|
\\void foo(void) {
|
|
|
|
\\ for (int i = 0; i < 10; i += 1) { }
|
|
|
|
\\}
|
|
|
|
,
|
2018-01-25 01:10:11 -08:00
|
|
|
\\pub fn foo() void {
|
2017-11-24 21:57:48 -08:00
|
|
|
\\ {
|
|
|
|
\\ var i: c_int = 0;
|
2018-03-07 01:39:32 -08:00
|
|
|
\\ while (i < 10) : (i += 1) {}
|
|
|
|
\\ }
|
2017-11-24 21:57:48 -08:00
|
|
|
\\}
|
|
|
|
);
|
2017-11-25 08:56:17 -08:00
|
|
|
|
2017-11-25 17:34:05 -08:00
|
|
|
cases.add("empty for loop",
|
|
|
|
\\void foo(void) {
|
|
|
|
\\ for (;;) { }
|
|
|
|
\\}
|
|
|
|
,
|
2018-01-25 01:10:11 -08:00
|
|
|
\\pub fn foo() void {
|
2018-03-07 01:39:32 -08:00
|
|
|
\\ while (true) {}
|
2017-11-25 17:34:05 -08:00
|
|
|
\\}
|
|
|
|
);
|
|
|
|
|
2017-11-25 08:56:17 -08:00
|
|
|
cases.add("break statement",
|
|
|
|
\\void foo(void) {
|
|
|
|
\\ for (;;) {
|
|
|
|
\\ break;
|
|
|
|
\\ }
|
|
|
|
\\}
|
|
|
|
,
|
2018-01-25 01:10:11 -08:00
|
|
|
\\pub fn foo() void {
|
2017-11-25 08:56:17 -08:00
|
|
|
\\ while (true) {
|
|
|
|
\\ break;
|
2018-03-07 01:39:32 -08:00
|
|
|
\\ }
|
2017-11-25 08:56:17 -08:00
|
|
|
\\}
|
|
|
|
);
|
|
|
|
|
|
|
|
cases.add("continue statement",
|
|
|
|
\\void foo(void) {
|
|
|
|
\\ for (;;) {
|
|
|
|
\\ continue;
|
|
|
|
\\ }
|
|
|
|
\\}
|
|
|
|
,
|
2018-01-25 01:10:11 -08:00
|
|
|
\\pub fn foo() void {
|
2017-11-25 08:56:17 -08:00
|
|
|
\\ while (true) {
|
|
|
|
\\ continue;
|
2018-03-07 01:39:32 -08:00
|
|
|
\\ }
|
2017-11-25 08:56:17 -08:00
|
|
|
\\}
|
|
|
|
);
|
2017-11-25 17:34:05 -08:00
|
|
|
|
2017-11-22 08:01:43 -08:00
|
|
|
cases.add("macros with field targets",
|
|
|
|
\\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
|
|
|
|
,
|
|
|
|
\\pub const GLbitfield = c_uint;
|
|
|
|
,
|
2018-01-25 01:10:11 -08:00
|
|
|
\\pub const PFNGLCLEARPROC = ?extern fn(GLbitfield) void;
|
2017-11-22 08:01:43 -08:00
|
|
|
,
|
2018-01-25 01:10:11 -08:00
|
|
|
\\pub const OpenGLProc = ?extern fn() void;
|
2017-11-22 08:01:43 -08:00
|
|
|
,
|
|
|
|
\\pub const union_OpenGLProcs = extern union {
|
|
|
|
\\ ptr: [1]OpenGLProc,
|
|
|
|
\\ gl: extern struct {
|
|
|
|
\\ Clear: PFNGLCLEARPROC,
|
|
|
|
\\ },
|
|
|
|
\\};
|
|
|
|
,
|
|
|
|
\\pub extern var glProcs: union_OpenGLProcs;
|
|
|
|
,
|
|
|
|
\\pub const glClearPFN = PFNGLCLEARPROC;
|
|
|
|
,
|
2018-01-25 01:10:11 -08:00
|
|
|
\\pub inline fn glClearUnion(arg0: GLbitfield) void {
|
2017-12-21 21:50:30 -08:00
|
|
|
\\ return (??glProcs.gl.Clear)(arg0);
|
2017-11-27 23:37:00 -08:00
|
|
|
\\}
|
2017-11-22 08:01:43 -08:00
|
|
|
,
|
|
|
|
\\pub const OpenGLProcs = union_OpenGLProcs;
|
|
|
|
);
|
2017-11-26 13:03:56 -08:00
|
|
|
|
2017-11-26 14:30:43 -08:00
|
|
|
cases.add("variable name shadowing",
|
|
|
|
\\int foo(void) {
|
|
|
|
\\ int x = 1;
|
|
|
|
\\ {
|
|
|
|
\\ int x = 2;
|
|
|
|
\\ x += 1;
|
|
|
|
\\ }
|
|
|
|
\\ return x;
|
|
|
|
\\}
|
|
|
|
,
|
2018-01-25 01:10:11 -08:00
|
|
|
\\pub fn foo() c_int {
|
2017-11-26 14:30:43 -08:00
|
|
|
\\ var x: c_int = 1;
|
|
|
|
\\ {
|
|
|
|
\\ var x_0: c_int = 2;
|
|
|
|
\\ x_0 += 1;
|
2018-03-07 01:39:32 -08:00
|
|
|
\\ }
|
2017-11-26 14:30:43 -08:00
|
|
|
\\ return x;
|
|
|
|
\\}
|
|
|
|
);
|
2017-09-20 23:31:52 -07:00
|
|
|
|
2017-11-26 17:05:55 -08:00
|
|
|
cases.add("pointer casting",
|
|
|
|
\\float *ptrcast(int *a) {
|
|
|
|
\\ return (float *)a;
|
|
|
|
\\}
|
|
|
|
,
|
2018-01-25 01:10:11 -08:00
|
|
|
\\fn ptrcast(a: ?&c_int) ?&f32 {
|
2017-11-26 17:05:55 -08:00
|
|
|
\\ return @ptrCast(?&f32, a);
|
|
|
|
\\}
|
|
|
|
);
|
2017-11-27 18:00:05 -08:00
|
|
|
|
|
|
|
cases.add("bin not",
|
|
|
|
\\int foo(int x) {
|
|
|
|
\\ return ~x;
|
|
|
|
\\}
|
|
|
|
,
|
2018-01-25 01:10:11 -08:00
|
|
|
\\pub fn foo(x: c_int) c_int {
|
2017-11-27 18:00:05 -08:00
|
|
|
\\ return ~x;
|
|
|
|
\\}
|
|
|
|
);
|
2017-11-28 00:17:28 -08:00
|
|
|
|
2018-03-06 03:04:14 -08:00
|
|
|
cases.add("bool not",
|
|
|
|
\\int foo(int x) {
|
|
|
|
\\ return !(x == 0);
|
|
|
|
\\ return !x;
|
|
|
|
\\}
|
|
|
|
,
|
|
|
|
\\pub fn foo(x: c_int) c_int {
|
|
|
|
\\ return !(x == 0);
|
|
|
|
\\ return !__to_bool_expr: {
|
|
|
|
\\ const _tmp = x;
|
|
|
|
\\ break :__to_bool_expr @bitCast(@IntType(false, @sizeOf(@typeOf(_tmp)) * 8), _tmp) != 0;
|
|
|
|
\\ };
|
|
|
|
\\}
|
|
|
|
);
|
|
|
|
|
2017-11-28 00:17:28 -08:00
|
|
|
cases.add("primitive types included in defined symbols",
|
|
|
|
\\int foo(int u32) {
|
|
|
|
\\ return u32;
|
|
|
|
\\}
|
|
|
|
,
|
2018-01-25 01:10:11 -08:00
|
|
|
\\pub fn foo(u32_0: c_int) c_int {
|
2017-11-28 00:17:28 -08:00
|
|
|
\\ return u32_0;
|
|
|
|
\\}
|
|
|
|
);
|
2017-11-28 20:44:45 -08:00
|
|
|
|
|
|
|
cases.add("const ptr initializer",
|
|
|
|
\\static const char *v0 = "0.0.0";
|
|
|
|
,
|
|
|
|
\\pub var v0: ?&const u8 = c"0.0.0";
|
|
|
|
);
|
2017-11-29 18:50:38 -08:00
|
|
|
|
|
|
|
cases.add("static incomplete array inside function",
|
|
|
|
\\void foo(void) {
|
|
|
|
\\ static const char v2[] = "2.2.2";
|
|
|
|
\\}
|
|
|
|
,
|
2018-01-25 01:10:11 -08:00
|
|
|
\\pub fn foo() void {
|
2017-11-29 18:50:38 -08:00
|
|
|
\\ const v2: &const u8 = c"2.2.2";
|
|
|
|
\\}
|
|
|
|
);
|
2017-12-07 09:27:29 -08:00
|
|
|
|
|
|
|
cases.add("macro pointer cast",
|
2018-03-06 03:04:14 -08:00
|
|
|
\\#define NRF_GPIO ((NRF_GPIO_Type *) NRF_GPIO_BASE)
|
2017-12-07 09:27:29 -08:00
|
|
|
,
|
2017-12-08 09:28:21 -08:00
|
|
|
\\pub const NRF_GPIO = if (@typeId(@typeOf(NRF_GPIO_BASE)) == @import("builtin").TypeId.Pointer) @ptrCast(&NRF_GPIO_Type, NRF_GPIO_BASE) else if (@typeId(@typeOf(NRF_GPIO_BASE)) == @import("builtin").TypeId.Int) @intToPtr(&NRF_GPIO_Type, NRF_GPIO_BASE) else (&NRF_GPIO_Type)(NRF_GPIO_BASE);
|
2017-12-07 09:27:29 -08:00
|
|
|
);
|
2018-01-16 06:48:28 -08:00
|
|
|
|
|
|
|
cases.add("if on int",
|
|
|
|
\\int if_int(int i) {
|
|
|
|
\\ if (i) {
|
|
|
|
\\ return 0;
|
|
|
|
\\ } else {
|
|
|
|
\\ return 1;
|
|
|
|
\\ }
|
|
|
|
\\}
|
|
|
|
,
|
2018-03-06 02:57:51 -08:00
|
|
|
\\pub fn if_int(i: c_int) c_int {
|
|
|
|
\\ if (__to_bool_expr: {
|
|
|
|
\\ const _tmp = i;
|
|
|
|
\\ break :__to_bool_expr @bitCast(@IntType(false, @sizeOf(@typeOf(_tmp)) * 8), _tmp) != 0;
|
|
|
|
\\ }) {
|
|
|
|
\\ return 0;
|
|
|
|
\\ } else {
|
|
|
|
\\ return 1;
|
2018-03-07 01:39:32 -08:00
|
|
|
\\ }
|
2018-03-06 02:57:51 -08:00
|
|
|
\\}
|
|
|
|
);
|
|
|
|
|
|
|
|
cases.add("while on int",
|
|
|
|
\\int while_int(int i) {
|
|
|
|
\\ while (i) {
|
|
|
|
\\ return 0;
|
|
|
|
\\ }
|
|
|
|
\\}
|
|
|
|
,
|
|
|
|
\\pub fn while_int(i: c_int) c_int {
|
|
|
|
\\ while (__to_bool_expr: {
|
|
|
|
\\ const _tmp = i;
|
|
|
|
\\ break :__to_bool_expr @bitCast(@IntType(false, @sizeOf(@typeOf(_tmp)) * 8), _tmp) != 0;
|
|
|
|
\\ }) {
|
|
|
|
\\ return 0;
|
2018-03-07 01:39:32 -08:00
|
|
|
\\ }
|
2018-03-06 02:57:51 -08:00
|
|
|
\\}
|
|
|
|
);
|
|
|
|
|
|
|
|
cases.add("for on int",
|
|
|
|
\\int for_int(int i) {
|
|
|
|
\\ for (;i;) {
|
|
|
|
\\ return 0;
|
|
|
|
\\ }
|
|
|
|
\\
|
|
|
|
\\ for (int j = 4;j;j--) {
|
|
|
|
\\ return 0;
|
|
|
|
\\ }
|
2018-01-16 06:48:28 -08:00
|
|
|
\\}
|
2018-03-06 02:57:51 -08:00
|
|
|
,
|
|
|
|
\\pub fn for_int(i: c_int) c_int {
|
|
|
|
\\ while (__to_bool_expr: {
|
|
|
|
\\ const _tmp = i;
|
|
|
|
\\ break :__to_bool_expr @bitCast(@IntType(false, @sizeOf(@typeOf(_tmp)) * 8), _tmp) != 0;
|
|
|
|
\\ }) {
|
|
|
|
\\ return 0;
|
2018-03-07 01:39:32 -08:00
|
|
|
\\ }
|
2018-03-06 02:57:51 -08:00
|
|
|
\\ {
|
|
|
|
\\ var j: c_int = 4;
|
|
|
|
\\ while (__to_bool_expr: {
|
|
|
|
\\ const _tmp = j;
|
|
|
|
\\ break :__to_bool_expr @bitCast(@IntType(false, @sizeOf(@typeOf(_tmp)) * 8), _tmp) != 0;
|
|
|
|
\\ }) : (j -= 1) {
|
|
|
|
\\ return 0;
|
2018-03-07 01:39:32 -08:00
|
|
|
\\ }
|
|
|
|
\\ }
|
2018-03-06 02:57:51 -08:00
|
|
|
\\}
|
2018-01-16 06:48:28 -08:00
|
|
|
);
|
2018-03-08 01:29:29 -08:00
|
|
|
|
|
|
|
cases.add("for on int",
|
|
|
|
\\int switch_fn(int i) {
|
|
|
|
\\ int res = 0;
|
|
|
|
\\ switch (i) {
|
|
|
|
\\ case 0:
|
|
|
|
\\ res = 1;
|
|
|
|
\\ case 1:
|
|
|
|
\\ res = 2;
|
|
|
|
\\ default:
|
|
|
|
\\ res = 3 * i;
|
|
|
|
\\ break;
|
|
|
|
\\ case 2:
|
|
|
|
\\ res = 5;
|
|
|
|
\\ }
|
|
|
|
\\}
|
|
|
|
,
|
|
|
|
\\pub fn switch_fn(i: c_int) c_int {
|
|
|
|
\\ var res: c_int = 0;
|
|
|
|
\\ __switch: {
|
|
|
|
\\ __case_2: {
|
|
|
|
\\ __default: {
|
|
|
|
\\ __case_1: {
|
|
|
|
\\ __case_0: {
|
|
|
|
\\ switch (i) {
|
|
|
|
\\ 0 => break :__case_0,
|
|
|
|
\\ 1 => break :__case_1,
|
|
|
|
\\ else => break :__default,
|
|
|
|
\\ 2 => break :__case_2,
|
|
|
|
\\ }
|
|
|
|
\\ }
|
|
|
|
\\ res = 1;
|
|
|
|
\\ }
|
|
|
|
\\ res = 2;
|
|
|
|
\\ }
|
|
|
|
\\ res = (3 * i);
|
|
|
|
\\ break :__switch;
|
|
|
|
\\ }
|
|
|
|
\\ res = 5;
|
|
|
|
\\ }
|
|
|
|
\\}
|
|
|
|
);
|
2017-11-26 17:05:55 -08:00
|
|
|
}
|