diff --git a/test/cases/run/Address_of_function_is_no-op.c b/test/cases/run/Address_of_function_is_no-op.c new file mode 100644 index 0000000..0c4b977 --- /dev/null +++ b/test/cases/run/Address_of_function_is_no-op.c @@ -0,0 +1,22 @@ +#include +#include +typedef int (*myfunc)(int); +int a(int arg) { return arg + 1;} +int b(int arg) { return arg + 2;} +int caller(myfunc fn, int arg) { + return fn(arg); +} +int main() { + myfunc arr[3] = {&a, &b, a}; + myfunc foo = a; + myfunc bar = &(a); + if (foo != bar) abort(); + if (arr[0] == arr[1]) abort(); + if (arr[0] != arr[2]) abort(); + if (caller(b, 40) != 42) abort(); + if (caller(&b, 40) != 42) abort(); + return 0; +} + +// run +// expect=fail diff --git a/test/cases/run/Allow_non-const_char_ptr_string_literals.c b/test/cases/run/Allow_non-const_char_ptr_string_literals.c new file mode 100644 index 0000000..5c1e0bf --- /dev/null +++ b/test/cases/run/Allow_non-const_char_ptr_string_literals.c @@ -0,0 +1,18 @@ +#include +int func(char *x) { return x[0]; } +struct S { char *member; }; +struct S global_struct = { .member = "global" }; +char *g = "global"; +int main(void) { + if (g[0] != 'g') abort(); + if (global_struct.member[0] != 'g') abort(); + char *string = "hello"; + if (string[0] != 'h') abort(); + struct S s = {.member = "hello"}; + if (s.member[0] != 'h') abort(); + if (func("foo") != 'f') abort(); + return 0; +} + +// run +// expect=fail diff --git a/test/cases/run/Array_initializers_(string_literals,_incomplete_arrays).c b/test/cases/run/Array_initializers_(string_literals,_incomplete_arrays).c new file mode 100644 index 0000000..0a0b4b8 --- /dev/null +++ b/test/cases/run/Array_initializers_(string_literals,_incomplete_arrays).c @@ -0,0 +1,36 @@ +#include +#include +extern int foo[]; +int global_arr[] = {1, 2, 3}; +char global_string[] = "hello"; +int main(int argc, char *argv[]) { + if (global_arr[2] != 3) abort(); + if (strlen(global_string) != 5) abort(); + const char *const_str = "hello"; + if (strcmp(const_str, "hello") != 0) abort(); + char empty_str[] = ""; + if (strlen(empty_str) != 0) abort(); + char hello[] = "hello"; + if (strlen(hello) != 5 || sizeof(hello) != 6) abort(); + int empty[] = {}; + if (sizeof(empty) != 0) abort(); + int bar[] = {42}; + if (bar[0] != 42) abort(); + bar[0] = 43; + if (bar[0] != 43) abort(); + int baz[] = {1, [42] = 123, 456}; + if (baz[42] != 123 || baz[43] != 456) abort(); + if (sizeof(baz) != sizeof(int) * 44) abort(); + const char *const names[] = {"first", "second", "third"}; + if (strcmp(names[2], "third") != 0) abort(); + char catted_str[] = "abc" "def"; + if (strlen(catted_str) != 6 || sizeof(catted_str) != 7) abort(); + char catted_trunc_str[2] = "abc" "def"; + if (sizeof(catted_trunc_str) != 2 || catted_trunc_str[0] != 'a' || catted_trunc_str[1] != 'b') abort(); + char big_array_utf8lit[10] = "💯"; + if (strcmp(big_array_utf8lit, "💯") != 0 || big_array_utf8lit[9] != 0) abort(); + return 0; +} + +// run +// expect=fail diff --git a/test/cases/run/Boolean_expression_coerced_to_int.c b/test/cases/run/Boolean_expression_coerced_to_int.c new file mode 100644 index 0000000..a20d3df --- /dev/null +++ b/test/cases/run/Boolean_expression_coerced_to_int.c @@ -0,0 +1,13 @@ +#include +int sign(int v) { + return -(v < 0); +} +int main(void) { + if (sign(-5) != -1) abort(); + if (sign(5) != 0) abort(); + if (sign(0) != 0) abort(); + return 0; +} + +// run +// expect=fail diff --git a/test/cases/run/C_built-ins.c b/test/cases/run/C_built-ins.c new file mode 100644 index 0000000..eee22a6 --- /dev/null +++ b/test/cases/run/C_built-ins.c @@ -0,0 +1,131 @@ +#include +#include +#include +#define M_E 2.71828182845904523536 +#define M_PI_2 1.57079632679489661923 +bool check_clz(unsigned int pos) { + return (__builtin_clz(1 << pos) == (8 * sizeof(unsigned int) - pos - 1)); +} +int main(void) { + if (__builtin_bswap16(0x0102) != 0x0201) abort(); + if (__builtin_bswap32(0x01020304) != 0x04030201) abort(); + if (__builtin_bswap64(0x0102030405060708) != 0x0807060504030201) abort(); + + if (__builtin_signbit(0.0) != 0) abort(); + if (__builtin_signbitf(0.0f) != 0) abort(); + if (__builtin_signbit(1.0) != 0) abort(); + if (__builtin_signbitf(1.0f) != 0) abort(); + if (__builtin_signbit(-1.0) != 1) abort(); + if (__builtin_signbitf(-1.0f) != 1) abort(); + + if (__builtin_popcount(0) != 0) abort(); + if (__builtin_popcount(0b1) != 1) abort(); + if (__builtin_popcount(0b11) != 2) abort(); + if (__builtin_popcount(0b1111) != 4) abort(); + if (__builtin_popcount(0b11111111) != 8) abort(); + + if (__builtin_ctz(0b1) != 0) abort(); + if (__builtin_ctz(0b10) != 1) abort(); + if (__builtin_ctz(0b100) != 2) abort(); + if (__builtin_ctz(0b10000) != 4) abort(); + if (__builtin_ctz(0b100000000) != 8) abort(); + + if (!check_clz(0)) abort(); + if (!check_clz(1)) abort(); + if (!check_clz(2)) abort(); + if (!check_clz(4)) abort(); + if (!check_clz(8)) abort(); + + if (__builtin_sqrt(__builtin_sqrt(__builtin_sqrt(256))) != 2.0) abort(); + if (__builtin_sqrt(__builtin_sqrt(__builtin_sqrt(256.0))) != 2.0) abort(); + if (__builtin_sqrt(__builtin_sqrt(__builtin_sqrt(256.0f))) != 2.0) abort(); + if (__builtin_sqrtf(__builtin_sqrtf(__builtin_sqrtf(256.0f))) != 2.0f) abort(); + + if (__builtin_sin(1.0) != -__builtin_sin(-1.0)) abort(); + if (__builtin_sinf(1.0f) != -__builtin_sinf(-1.0f)) abort(); + if (__builtin_sin(M_PI_2) != 1.0) abort(); + if (__builtin_sinf(M_PI_2) != 1.0f) abort(); + + if (__builtin_cos(1.0) != __builtin_cos(-1.0)) abort(); + if (__builtin_cosf(1.0f) != __builtin_cosf(-1.0f)) abort(); + if (__builtin_cos(0.0) != 1.0) abort(); + if (__builtin_cosf(0.0f) != 1.0f) abort(); + + if (__builtin_exp(0) != 1.0) abort(); + if (__builtin_fabs(__builtin_exp(1.0) - M_E) > 0.00000001) abort(); + if (__builtin_exp(0.0f) != 1.0f) abort(); + + if (__builtin_exp2(0) != 1.0) abort(); + if (__builtin_exp2(4.0) != 16.0) abort(); + if (__builtin_exp2f(0.0f) != 1.0f) abort(); + if (__builtin_exp2f(4.0f) != 16.0f) abort(); + + if (__builtin_log(M_E) != 1.0) abort(); + if (__builtin_log(1.0) != 0.0) abort(); + if (__builtin_logf(1.0f) != 0.0f) abort(); + + if (__builtin_log2(8.0) != 3.0) abort(); + if (__builtin_log2(1.0) != 0.0) abort(); + if (__builtin_log2f(8.0f) != 3.0f) abort(); + if (__builtin_log2f(1.0f) != 0.0f) abort(); + + if (__builtin_log10(1000.0) != 3.0) abort(); + if (__builtin_log10(1.0) != 0.0) abort(); + if (__builtin_log10f(1000.0f) != 3.0f) abort(); + if (__builtin_log10f(1.0f) != 0.0f) abort(); + + if (__builtin_fabs(-42.0f) != 42.0) abort(); + if (__builtin_fabs(-42.0) != 42.0) abort(); + if (__builtin_fabs(-42) != 42.0) abort(); + if (__builtin_fabsf(-42.0f) != 42.0f) abort(); + + if (__builtin_fabs(-42.0f) != 42.0) abort(); + if (__builtin_fabs(-42.0) != 42.0) abort(); + if (__builtin_fabs(-42) != 42.0) abort(); + if (__builtin_fabsf(-42.0f) != 42.0f) abort(); + + if (__builtin_abs(42) != 42) abort(); + if (__builtin_abs(-42) != 42) abort(); + if (__builtin_abs(INT_MIN) != INT_MIN) abort(); + + if (__builtin_floor(42.9) != 42.0) abort(); + if (__builtin_floor(-42.9) != -43.0) abort(); + if (__builtin_floorf(42.9f) != 42.0f) abort(); + if (__builtin_floorf(-42.9f) != -43.0f) abort(); + + if (__builtin_ceil(42.9) != 43.0) abort(); + if (__builtin_ceil(-42.9) != -42) abort(); + if (__builtin_ceilf(42.9f) != 43.0f) abort(); + if (__builtin_ceilf(-42.9f) != -42.0f) abort(); + + if (__builtin_trunc(42.9) != 42.0) abort(); + if (__builtin_truncf(42.9f) != 42.0f) abort(); + if (__builtin_trunc(-42.9) != -42.0) abort(); + if (__builtin_truncf(-42.9f) != -42.0f) abort(); + + if (__builtin_round(0.5) != 1.0) abort(); + if (__builtin_round(-0.5) != -1.0) abort(); + if (__builtin_roundf(0.5f) != 1.0f) abort(); + if (__builtin_roundf(-0.5f) != -1.0f) abort(); + + if (__builtin_strcmp("abc", "abc") != 0) abort(); + if (__builtin_strcmp("abc", "def") >= 0 ) abort(); + if (__builtin_strcmp("def", "abc") <= 0) abort(); + + if (__builtin_strlen("this is a string") != 16) abort(); + + char *s = malloc(6); + __builtin_memcpy(s, "hello", 5); + s[5] = '\0'; + if (__builtin_strlen(s) != 5) abort(); + + __builtin_memset(s, 42, __builtin_strlen(s)); + if (s[0] != 42 || s[1] != 42 || s[2] != 42 || s[3] != 42 || s[4] != 42) abort(); + + free(s); + + return 0; +} + +// run +// expect=fail diff --git a/test/cases/run/Cast-to-union.c b/test/cases/run/Cast-to-union.c new file mode 100644 index 0000000..ac52ae9 --- /dev/null +++ b/test/cases/run/Cast-to-union.c @@ -0,0 +1,22 @@ +#include +struct S { int x; }; +union U { + long l; + double d; + struct S s; +}; +union U bar(union U u) { return u; } +int main(void) { + union U u = (union U) 42L; + if (u.l != 42L) abort(); + u = (union U) 2.0; + if (u.d != 2.0) abort(); + u = bar((union U)4.0); + if (u.d != 4.0) abort(); + u = (union U)(struct S){ .x = 5 }; + if (u.s.x != 5) abort(); + return 0; +} + +// run +// expect=fail diff --git a/test/cases/run/Cast_boolean_expression_result_to_int.c b/test/cases/run/Cast_boolean_expression_result_to_int.c new file mode 100644 index 0000000..a6ef5f4 --- /dev/null +++ b/test/cases/run/Cast_boolean_expression_result_to_int.c @@ -0,0 +1,16 @@ +#include +char foo(char c) { return c; } +int bar(int i) { return i; } +long baz(long l) { return l; } +int main() { + if (foo(1 == 2)) abort(); + if (!foo(1 == 1)) abort(); + if (bar(1 == 2)) abort(); + if (!bar(1 == 1)) abort(); + if (baz(1 == 2)) abort(); + if (!baz(1 == 1)) abort(); + return 0; +} + +// run +// expect=fail diff --git a/test/cases/run/Cast_to_enum_from_larger_integral_type.c b/test/cases/run/Cast_to_enum_from_larger_integral_type.c new file mode 100644 index 0000000..297a171 --- /dev/null +++ b/test/cases/run/Cast_to_enum_from_larger_integral_type.c @@ -0,0 +1,14 @@ +#include +#include +enum Foo { A, B, C }; +static inline enum Foo do_stuff(void) { + int64_t i = 1; + return (enum Foo)i; +} +int main(void) { + if (do_stuff() != B) abort(); + return 0; +} + +// run +// expect=fail diff --git a/test/cases/run/Closure_over_local_in_typeof.c b/test/cases/run/Closure_over_local_in_typeof.c new file mode 100644 index 0000000..dd07095 --- /dev/null +++ b/test/cases/run/Closure_over_local_in_typeof.c @@ -0,0 +1,10 @@ +#include +int main(void) { + int x = 123; + union { typeof(x) val; } u = { x }; + if (u.val != 123) abort(); + return 0; +} + +// run +// expect=fail diff --git a/test/cases/run/Comma_operator_should_create_new_scope.c b/test/cases/run/Comma_operator_should_create_new_scope.c new file mode 100644 index 0000000..a9eb34a --- /dev/null +++ b/test/cases/run/Comma_operator_should_create_new_scope.c @@ -0,0 +1,13 @@ +#include +#include +int main(void) { + if (1 || (abort(), 1)) {} + if (0 && (1, printf("do not print\n"))) {} + int x = 0; + x = (x = 3, 4, x + 1); + if (x != 4) abort(); + return 0; +} + +// run +// expect=fail diff --git a/test/cases/run/Compound_literals.c b/test/cases/run/Compound_literals.c new file mode 100644 index 0000000..7de9d98 --- /dev/null +++ b/test/cases/run/Compound_literals.c @@ -0,0 +1,16 @@ +#include +struct Foo { + int a; + char b[2]; + float c; +}; +int main() { + struct Foo foo; + int x = 1, y = 2; + foo = (struct Foo) {x + y, {'a', 'b'}, 42.0f}; + if (foo.a != x + y || foo.b[0] != 'a' || foo.b[1] != 'b' || foo.c != 42.0f) abort(); + return 0; +} + +// run +// expect=fail diff --git a/test/cases/run/Ensure_side-effects_only_evaluated_once_for_signed_array_indices.c b/test/cases/run/Ensure_side-effects_only_evaluated_once_for_signed_array_indices.c new file mode 100644 index 0000000..85e4d67 --- /dev/null +++ b/test/cases/run/Ensure_side-effects_only_evaluated_once_for_signed_array_indices.c @@ -0,0 +1,16 @@ +#include +int main(void) { + int foo[] = {1, 2, 3, 4}; + int *p = foo; + int idx = 1; + if ((++p)[--idx] != 2) abort(); + if (p != foo + 1) abort(); + if (idx != 0) abort(); + if ((p++)[idx++] != 2) abort(); + if (p != foo + 2) abort(); + if (idx != 1) abort(); + return 0; +} + +// run +// expect=fail diff --git a/test/cases/run/Ensure_while_loop_under_an_if_doesn't_steal_the_else.c b/test/cases/run/Ensure_while_loop_under_an_if_doesn't_steal_the_else.c new file mode 100644 index 0000000..553807f --- /dev/null +++ b/test/cases/run/Ensure_while_loop_under_an_if_doesn't_steal_the_else.c @@ -0,0 +1,17 @@ +#include +void doWork(int id) { } +int reallyDelete(int id) { printf("deleted %d\n", id); return 1; } +int process(int id, int n, int delete) { + if(!delete) + while(n-- > 0) doWork(id); + else + return reallyDelete(id); + return 0; +} +int main(void) { + process(99, 3, 0); + return 0; +} + +// run +// expect=fail diff --git a/test/cases/run/Enum_constant_matches_enum_name,_multiple_enumerations_with_same_value.c b/test/cases/run/Enum_constant_matches_enum_name,_multiple_enumerations_with_same_value.c new file mode 100644 index 0000000..9f2b589 --- /dev/null +++ b/test/cases/run/Enum_constant_matches_enum_name,_multiple_enumerations_with_same_value.c @@ -0,0 +1,15 @@ +#include +enum FOO { + FOO = 1, + BAR = 2, + BAZ = 1, +}; +int main(void) { + enum FOO x = BAZ; + if (x != 1) abort(); + if (x != BAZ) abort(); + if (x != FOO) abort(); +} + +// run +// expect=fail diff --git a/test/cases/run/Enum_constants_are_assigned_correct_type.c b/test/cases/run/Enum_constants_are_assigned_correct_type.c new file mode 100644 index 0000000..da39878 --- /dev/null +++ b/test/cases/run/Enum_constants_are_assigned_correct_type.c @@ -0,0 +1,16 @@ +enum A { A0, A1=0xFFFFFFFF }; +enum B { B0=-1, B1=0xFFFFFFFF }; +enum C { C0=-1, C1=0 }; +enum D { D0, D1=0xFFFFFFFFFFL }; +enum E { E0=-1, E1=0xFFFFFFFFFFL }; +int main(void) { + signed char a0 = A0, a1 = A1; + signed char b0 = B0, b1 = B1; + signed char c0 = C0, c1 = C1; + signed char d0 = D0, d1 = D1; + signed char e0 = E0, e1 = E1; + return 0; +} + +// run +// expect=fail diff --git a/test/cases/run/Flexible_array_with_typedefed_flexible_item.c b/test/cases/run/Flexible_array_with_typedefed_flexible_item.c new file mode 100644 index 0000000..20fdd42 --- /dev/null +++ b/test/cases/run/Flexible_array_with_typedefed_flexible_item.c @@ -0,0 +1,18 @@ +#include +#include +typedef int MARKER[0]; +typedef struct { int x; MARKER y; } Flexible; +#define SIZE 10 +int main(void) { + Flexible *flex = malloc(sizeof(Flexible) + SIZE * sizeof(int)); + for (int i = 0; i < SIZE; i++) { + flex->y[i] = i; + } + for (int i = 0; i < SIZE; i++) { + assert(flex->y[i] == i); + } + return 0; +} + +// run +// expect=fail diff --git a/test/cases/run/Flexible_arrays.c b/test/cases/run/Flexible_arrays.c new file mode 100644 index 0000000..6d7c926 --- /dev/null +++ b/test/cases/run/Flexible_arrays.c @@ -0,0 +1,21 @@ +#include +#include +typedef struct { char foo; int bar; } ITEM; +typedef struct { size_t count; ITEM items[]; } ITEM_LIST; +typedef struct { unsigned char count; int items[]; } INT_LIST; +#define SIZE 10 +int main(void) { + ITEM_LIST *list = malloc(sizeof(ITEM_LIST) + SIZE * sizeof(ITEM)); + for (int i = 0; i < SIZE; i++) list->items[i] = (ITEM) {.foo = i, .bar = i + 1}; + const ITEM_LIST *const c_list = list; + for (int i = 0; i < SIZE; i++) if (c_list->items[i].foo != i || c_list->items[i].bar != i + 1) abort(); + INT_LIST *int_list = malloc(sizeof(INT_LIST) + SIZE * sizeof(int)); + for (int i = 0; i < SIZE; i++) int_list->items[i] = i; + const INT_LIST *const c_int_list = int_list; + const int *const ints = int_list->items; + for (int i = 0; i < SIZE; i++) if (ints[i] != i) abort(); + return 0; +} + +// run +// expect=fail diff --git a/test/cases/run/Function_to_integral.c b/test/cases/run/Function_to_integral.c new file mode 100644 index 0000000..3fef740 --- /dev/null +++ b/test/cases/run/Function_to_integral.c @@ -0,0 +1,13 @@ +// The C standard does not require function pointers to be convertible to any integer type. +// However, POSIX requires that function pointers have the same representation as `void *` +// so that dlsym() can work +#include +int main(void) { +#if defined(__UINTPTR_MAX__) && __has_include() + uintptr_t x = (uintptr_t)main; +#endif + return 0; +} + +// run +// expect=fail diff --git a/test/cases/run/Generic_selections.c b/test/cases/run/Generic_selections.c new file mode 100644 index 0000000..fa08e0e --- /dev/null +++ b/test/cases/run/Generic_selections.c @@ -0,0 +1,34 @@ +#include +#include +#include +#define my_generic_fn(X) _Generic((X), \ + int: abs, \ + char *: strlen, \ + size_t: malloc, \ + default: free \ +)(X) +#define my_generic_val(X) _Generic((X), \ + int: 1, \ + const char *: "bar" \ +) +int main(void) { + if (my_generic_val(100) != 1) abort(); + + const char *foo = "foo"; + const char *bar = my_generic_val(foo); + if (strcmp(bar, "bar") != 0) abort(); + + if (my_generic_fn(-42) != 42) abort(); + if (my_generic_fn("hello") != 5) abort(); + + size_t size = 8192; + uint8_t *mem = my_generic_fn(size); + memset(mem, 42, size); + if (mem[size - 1] != 42) abort(); + my_generic_fn(mem); + + return 0; +} + +// run +// expect=fail diff --git a/test/cases/run/K&R-style_static_function_prototype_+_separate_definition.c b/test/cases/run/K&R-style_static_function_prototype_+_separate_definition.c new file mode 100644 index 0000000..353f842 --- /dev/null +++ b/test/cases/run/K&R-style_static_function_prototype_+_separate_definition.c @@ -0,0 +1,12 @@ +#include +static int foo(); +static int foo(int a, int b) { + return a + b; +} +int main() { + if (foo(40, 2) != 42) abort(); + return 0; +} + +// run +// expect=fail diff --git a/test/cases/run/K&R-style_static_function_prototype_for_unused_function.c b/test/cases/run/K&R-style_static_function_prototype_for_unused_function.c new file mode 100644 index 0000000..b90fc65 --- /dev/null +++ b/test/cases/run/K&R-style_static_function_prototype_for_unused_function.c @@ -0,0 +1,7 @@ +static int foo(); +int main() { + return 0; +} + +// run +// expect=fail diff --git a/test/cases/run/NAN_and_INFINITY.c b/test/cases/run/NAN_and_INFINITY.c new file mode 100644 index 0000000..ee4a2f2 --- /dev/null +++ b/test/cases/run/NAN_and_INFINITY.c @@ -0,0 +1,36 @@ +// TODO: add isnan check for long double once bitfield support is added +// (needed for x86_64-windows-gnu) +// TODO: add isinf check for long double once std.math.isInf supports c_longdouble +#include +#include +#include +union uf { uint32_t u; float f; }; +#define CHECK_NAN(STR, VAL) { \ + union uf unpack = {.f = __builtin_nanf(STR)}; \ + if (!isnan(unpack.f)) abort(); \ + if (unpack.u != VAL) abort(); \ +} +int main(void) { + float f_nan = NAN; + if (!isnan(f_nan)) abort(); + double d_nan = NAN; + if (!isnan(d_nan)) abort(); + CHECK_NAN("0", 0x7FC00000); + CHECK_NAN("", 0x7FC00000); + CHECK_NAN("1", 0x7FC00001); + CHECK_NAN("0x7FC00000", 0x7FC00000); + CHECK_NAN("0x7FC0000F", 0x7FC0000F); + CHECK_NAN("0x7FC000F0", 0x7FC000F0); + CHECK_NAN("0x7FC00F00", 0x7FC00F00); + CHECK_NAN("0x7FC0F000", 0x7FC0F000); + CHECK_NAN("0x7FCF0000", 0x7FCF0000); + CHECK_NAN("0xFFFFFFFF", 0x7FFFFFFF); + float f_inf = INFINITY; + if (!isinf(f_inf)) abort(); + double d_inf = INFINITY; + if (!isinf(d_inf)) abort(); + return 0; +} + +// run +// expect=fail diff --git a/test/cases/run/NDEBUG_disables_assert.c b/test/cases/run/NDEBUG_disables_assert.c new file mode 100644 index 0000000..392f5dc --- /dev/null +++ b/test/cases/run/NDEBUG_disables_assert.c @@ -0,0 +1,10 @@ +#define NDEBUG +#include +int main() { + assert(0); + assert(NULL); + return 0; +} + +// run +// expect=fail diff --git a/test/cases/run/Nested_comma_operator_in_macro.c b/test/cases/run/Nested_comma_operator_in_macro.c new file mode 100644 index 0000000..0dd2bf0 --- /dev/null +++ b/test/cases/run/Nested_comma_operator_in_macro.c @@ -0,0 +1,10 @@ +#include +#define FOO (1, (2, 3)) +int main(void) { + int x = FOO; + if (x != 3) abort(); + return 0; +} + +// run +// expect=fail diff --git a/test/cases/run/Obscure_ways_of_calling_functions.c b/test/cases/run/Obscure_ways_of_calling_functions.c new file mode 100644 index 0000000..6064dad --- /dev/null +++ b/test/cases/run/Obscure_ways_of_calling_functions.c @@ -0,0 +1,34 @@ +#include +static int add(int a, int b) { + return a + b; +} +typedef int (*adder)(int, int); +typedef void (*funcptr)(void); +int main() { + if ((add)(1, 2) != 3) abort(); + if ((&add)(1, 2) != 3) abort(); + if (add(3, 1) != 4) abort(); + if ((*add)(2, 3) != 5) abort(); + if ((**add)(7, -1) != 6) abort(); + if ((***add)(-2, 9) != 7) abort(); + + int (*ptr)(int a, int b); + ptr = add; + + if (ptr(1, 2) != 3) abort(); + if ((*ptr)(3, 1) != 4) abort(); + if ((**ptr)(2, 3) != 5) abort(); + if ((***ptr)(7, -1) != 6) abort(); + if ((****ptr)(-2, 9) != 7) abort(); + + funcptr addr1 = (funcptr)(add); + funcptr addr2 = (funcptr)(&add); + + if (addr1 != addr2) abort(); + if (((int(*)(int, int))addr1)(1, 2) != 3) abort(); + if (((adder)addr2)(1, 2) != 3) abort(); + return 0; +} + +// run +// expect=fail diff --git a/test/cases/run/Remainder_operator_with_negative_integers.c b/test/cases/run/Remainder_operator_with_negative_integers.c new file mode 100644 index 0000000..469d486 --- /dev/null +++ b/test/cases/run/Remainder_operator_with_negative_integers.c @@ -0,0 +1,12 @@ +#include +int main(void) { + int denominator = -2; + int numerator = 5; + if (numerator % denominator != 1) abort(); + numerator = -5; denominator = 2; + if (numerator % denominator != -1) abort(); + return 0; +} + +// run +// expect=fail diff --git a/test/cases/run/Render_array_LHS_as_grouped_node_if_necessary.c b/test/cases/run/Render_array_LHS_as_grouped_node_if_necessary.c new file mode 100644 index 0000000..f3d408e --- /dev/null +++ b/test/cases/run/Render_array_LHS_as_grouped_node_if_necessary.c @@ -0,0 +1,9 @@ +#include +int main(void) { + int arr[] = {40, 41, 42, 43}; + if ((arr + 1)[1] != 42) abort(); + return 0; +} + +// run +// expect=fail diff --git a/test/cases/run/Return_boolean_expression_as_int.c b/test/cases/run/Return_boolean_expression_as_int.c new file mode 100644 index 0000000..f29860f --- /dev/null +++ b/test/cases/run/Return_boolean_expression_as_int.c @@ -0,0 +1,35 @@ +#include +#include +bool actual_bool(void) { return 4 - 1 < 4;} +char char_bool_ret(void) { return 0 || 1; } +short short_bool_ret(void) { return 0 < 1; } +int int_bool_ret(void) { return 1 && 1; } +long long_bool_ret(void) { return !(0 > 1); } +static int GLOBAL = 1; +int nested_scopes(int a, int b) { + if (a == 1) { + int target = 1; + return b == target; + } else { + int target = 2; + if (b == target) { + return GLOBAL == 1; + } + return target == 2; + } +} +int main(void) { + if (!actual_bool()) abort(); + if (!char_bool_ret()) abort(); + if (!short_bool_ret()) abort(); + if (!int_bool_ret()) abort(); + if (!long_bool_ret()) abort(); + if (!nested_scopes(1, 1)) abort(); + if (nested_scopes(1, 2)) abort(); + if (!nested_scopes(0, 2)) abort(); + if (!nested_scopes(0, 3)) abort(); + return 1 != 1; +} + +// run +// expect=fail diff --git a/test/cases/run/Scoped_enums.c b/test/cases/run/Scoped_enums.c new file mode 100644 index 0000000..3778ed6 --- /dev/null +++ b/test/cases/run/Scoped_enums.c @@ -0,0 +1,18 @@ +#include +int main(void) { + enum Foo { A, B, C }; + enum Foo a = B; + if (a != B) abort(); + if (a != 1) abort(); + { + enum Foo { A = 5, B = 6, C = 7 }; + enum Foo a = B; + if (a != B) abort(); + if (a != 6) abort(); + } + if (a != B) abort(); + if (a != 1) abort(); +} + +// run +// expect=fail diff --git a/test/cases/run/Typedef'ed_void_used_as_return_type.c b/test/cases/run/Typedef'ed_void_used_as_return_type.c new file mode 100644 index 0000000..91e1bcb --- /dev/null +++ b/test/cases/run/Typedef'ed_void_used_as_return_type.c @@ -0,0 +1,10 @@ +typedef void V; +V foo(V *f) {} +int main(void) { + int x = 0; + foo(&x); + return 0; +} + +// run +// expect=fail diff --git a/test/cases/run/Underscore_identifiers.c b/test/cases/run/Underscore_identifiers.c new file mode 100644 index 0000000..e8810bd --- /dev/null +++ b/test/cases/run/Underscore_identifiers.c @@ -0,0 +1,12 @@ +#include +int _ = 10; +typedef struct { int _; } S; +int main(void) { + if (_ != 10) abort(); + S foo = { ._ = _ }; + if (foo._ != _) abort(); + return 0; +} + +// run +// expect=fail diff --git a/test/cases/run/Use_correct_break_label_for_statement_expression_in_nested_scope.c b/test/cases/run/Use_correct_break_label_for_statement_expression_in_nested_scope.c new file mode 100644 index 0000000..a68a759 --- /dev/null +++ b/test/cases/run/Use_correct_break_label_for_statement_expression_in_nested_scope.c @@ -0,0 +1,9 @@ +#include +int main(void) { + int x = ({1, ({2; 3;});}); + if (x != 3) abort(); + return 0; +} + +// run +// expect=fail diff --git a/test/cases/run/Variadic_function_call.c b/test/cases/run/Variadic_function_call.c new file mode 100644 index 0000000..6ee798a --- /dev/null +++ b/test/cases/run/Variadic_function_call.c @@ -0,0 +1,11 @@ +#define _NO_CRT_STDIO_INLINE 1 +#include +int main(void) { + printf("%d %d", 1, 2); + return 0; +} + +// run +// expect=fail +// +// 1 2 diff --git a/test/cases/run/Wide,_UTF-16,_and_UTF-32_character_literals.c b/test/cases/run/Wide,_UTF-16,_and_UTF-32_character_literals.c new file mode 100644 index 0000000..cc366d3 --- /dev/null +++ b/test/cases/run/Wide,_UTF-16,_and_UTF-32_character_literals.c @@ -0,0 +1,18 @@ +#include +#include +int main() { + wchar_t wc = L'™'; + int utf16_char = u'™'; + int utf32_char = U'💯'; + if (wc != 8482) abort(); + if (utf16_char != 8482) abort(); + if (utf32_char != 128175) abort(); + unsigned char c = wc; + if (c != 0x22) abort(); + c = utf32_char; + if (c != 0xaf) abort(); + return 0; +} + +// run +// expect=fail diff --git a/test/cases/run/Wide,_UTF-16,_and_UTF-32_string_literals.c b/test/cases/run/Wide,_UTF-16,_and_UTF-32_string_literals.c new file mode 100644 index 0000000..33ae240 --- /dev/null +++ b/test/cases/run/Wide,_UTF-16,_and_UTF-32_string_literals.c @@ -0,0 +1,24 @@ +#include +#include +#include +int main(void) { + const wchar_t *wide_str = L"wide"; + const wchar_t wide_hello[] = L"hello"; + if (wcslen(wide_str) != 4) abort(); + if (wcslen(L"literal") != 7) abort(); + if (wcscmp(wide_hello, L"hello") != 0) abort(); + + const uint16_t *u16_str = u"wide"; + const uint16_t u16_hello[] = u"hello"; + if (u16_str[3] != u'e' || u16_str[4] != 0) abort(); + if (u16_hello[4] != u'o' || u16_hello[5] != 0) abort(); + + const uint32_t *u32_str = U"wide"; + const uint32_t u32_hello[] = U"hello"; + if (u32_str[3] != U'e' || u32_str[4] != 0) abort(); + if (u32_hello[4] != U'o' || u32_hello[5] != 0) abort(); + return 0; +} + +// run +// expect=fail diff --git a/test/cases/run/Zero-initialization_of_global_union.c b/test/cases/run/Zero-initialization_of_global_union.c new file mode 100644 index 0000000..e828809 --- /dev/null +++ b/test/cases/run/Zero-initialization_of_global_union.c @@ -0,0 +1,10 @@ +#include +union U { int x; double y; }; +union U u; +int main(void) { + if (u.x != 0) abort(); + return 0; +} + +// run +// expect=fail diff --git a/test/cases/run/__builtin_choose_expr_(unchosen_expression_is_not_evaluated).c b/test/cases/run/__builtin_choose_expr_(unchosen_expression_is_not_evaluated).c new file mode 100644 index 0000000..e84e323 --- /dev/null +++ b/test/cases/run/__builtin_choose_expr_(unchosen_expression_is_not_evaluated).c @@ -0,0 +1,14 @@ +#include +int main(void) { + int x = 0.0; + int y = 0.0; + int res; + res = __builtin_choose_expr(1, 1, x / y); + if (res != 1) abort(); + res = __builtin_choose_expr(0, x / y, 2); + if (res != 2) abort(); + return 0; +} + +// run +// expect=fail diff --git a/test/cases/run/__builtin_convertvector.c b/test/cases/run/__builtin_convertvector.c new file mode 100644 index 0000000..73e5f57 --- /dev/null +++ b/test/cases/run/__builtin_convertvector.c @@ -0,0 +1,16 @@ +#include +#include +typedef int16_t __v8hi __attribute__((__vector_size__(16))); +typedef uint16_t __v8hu __attribute__((__vector_size__(16))); +int main(int argc, char**argv) { + __v8hi signed_vector = { 1, 2, 3, 4, -1, -2, -3,-4}; + __v8hu unsigned_vector = __builtin_convertvector(signed_vector, __v8hu); + + for (int i = 0; i < 8; i++) { + if (unsigned_vector[i] != (uint16_t)signed_vector[i]) abort(); + } + return 0; +} + +// run +// expect=fail diff --git a/test/cases/run/__builtin_shufflevector.c b/test/cases/run/__builtin_shufflevector.c new file mode 100644 index 0000000..0e1a169 --- /dev/null +++ b/test/cases/run/__builtin_shufflevector.c @@ -0,0 +1,47 @@ +#include +#include +typedef int16_t __v4hi __attribute__((__vector_size__(8))); +typedef int16_t __v8hi __attribute__((__vector_size__(16))); +int main(int argc, char**argv) { + __v8hi v8_a = {0, 1, 2, 3, 4, 5, 6, 7}; + __v8hi v8_b = {100, 200, 300, 400, 500, 600, 700, 800}; + __v8hi shuffled = __builtin_shufflevector(v8_a, v8_b, 0, 1, 2, 3, 8, 9, 10, 11); + for (int i = 0; i < 8; i++) { + if (i < 4) { + if (shuffled[i] != v8_a[i]) abort(); + } else { + if (shuffled[i] != v8_b[i - 4]) abort(); + } + } + shuffled = __builtin_shufflevector( + (__v8hi) {-1, -1, -1, -1, -1, -1, -1, -1}, + (__v8hi) {42, 42, 42, 42, 42, 42, 42, 42}, + 0, 1, 2, 3, 8, 9, 10, 11 + ); + for (int i = 0; i < 8; i++) { + if (i < 4) { + if (shuffled[i] != -1) abort(); + } else { + if (shuffled[i] != 42) abort(); + } + } + __v4hi shuffled_to_fewer_elements = __builtin_shufflevector(v8_a, v8_b, 0, 1, 8, 9); + for (int i = 0; i < 4; i++) { + if (i < 2) { + if (shuffled_to_fewer_elements[i] != v8_a[i]) abort(); + } else { + if (shuffled_to_fewer_elements[i] != v8_b[i - 2]) abort(); + } + } + __v4hi v4_a = {0, 1, 2, 3}; + __v4hi v4_b = {100, 200, 300, 400}; + __v8hi shuffled_to_more_elements = __builtin_shufflevector(v4_a, v4_b, 0, 1, 2, 3, 4, 5, 6, 7); + for (int i = 0; i < 4; i++) { + if (shuffled_to_more_elements[i] != v4_a[i]) abort(); + if (shuffled_to_more_elements[i + 4] != v4_b[i]) abort(); + } + return 0; +} + +// run +// expect=fail diff --git a/test/cases/run/__cleanup___attribute.c b/test/cases/run/__cleanup___attribute.c new file mode 100644 index 0000000..e4211e7 --- /dev/null +++ b/test/cases/run/__cleanup___attribute.c @@ -0,0 +1,18 @@ +#include +static int cleanup_count = 0; +void clean_up(int *final_value) { + if (*final_value != cleanup_count++) abort(); +} +void doit(void) { + int a __attribute__ ((__cleanup__(clean_up))) __attribute__ ((unused)) = 2; + int b __attribute__ ((__cleanup__(clean_up))) __attribute__ ((unused)) = 1; + int c __attribute__ ((__cleanup__(clean_up))) __attribute__ ((unused)) = 0; +} +int main(void) { + doit(); + if (cleanup_count != 3) abort(); + return 0; +} + +// run +// expect=fail diff --git a/test/cases/run/anon_struct_init.c b/test/cases/run/anon_struct_init.c new file mode 100644 index 0000000..8952594 --- /dev/null +++ b/test/cases/run/anon_struct_init.c @@ -0,0 +1,12 @@ +#include +struct {int a; int b;} x = {1, 2}; +int main(int argc, char **argv) { + x.a += 2; + x.b += 1; + if (x.a != 3) abort(); + if (x.b != 3) abort(); + return 0; +} + +// run +// expect=fail diff --git a/test/cases/run/anonymous_struct_&_unions.c b/test/cases/run/anonymous_struct_&_unions.c new file mode 100644 index 0000000..72693dd --- /dev/null +++ b/test/cases/run/anonymous_struct_&_unions.c @@ -0,0 +1,14 @@ +#include +#include +static struct { struct { uint16_t x, y; }; } x = { 1 }; +static struct { union { uint32_t x; uint8_t y; }; } y = { 0x55AA55AA }; +int main(int argc, char **argv) { + if (x.x != 1) abort(); + if (x.y != 0) abort(); + if (y.x != 0x55AA55AA) abort(); + if (y.y != 0xAA) abort(); + return 0; +} + +// run +// expect=fail diff --git a/test/cases/run/array_cast_int_to_uint.c b/test/cases/run/array_cast_int_to_uint.c new file mode 100644 index 0000000..2d5f7bc --- /dev/null +++ b/test/cases/run/array_cast_int_to_uint.c @@ -0,0 +1,17 @@ +#include +static unsigned int hash_binary(int k) +{ + int choose[3] = {-1, -2, 3}; + unsigned int sum = 2; + sum += choose[k]; + return sum; +} + +int main() { + unsigned int x = hash_binary(1); + if (x != 0) abort(); + return 0; +} + +// run +// expect=fail diff --git a/test/cases/run/array_initializer.c b/test/cases/run/array_initializer.c new file mode 100644 index 0000000..af228e8 --- /dev/null +++ b/test/cases/run/array_initializer.c @@ -0,0 +1,15 @@ +#include +int main(int argc, char **argv) { + int a0[4] = {1}; + int a1[4] = {1,2,3,4}; + int s0 = 0, s1 = 0; + for (int i = 0; i < 4; i++) { + s0 += a0[i]; + s1 += a1[i]; + } + if (s0 != 1) abort(); + if (s1 != 10) abort(); +} + +// run +// expect=fail diff --git a/test/cases/run/array_to_pointer_decay.c b/test/cases/run/array_to_pointer_decay.c new file mode 100644 index 0000000..b614039 --- /dev/null +++ b/test/cases/run/array_to_pointer_decay.c @@ -0,0 +1,13 @@ +#include +int main(int argc, char **argv) { + char data[3] = {'a','b','c'}; + if (2[data] != data[2]) abort(); + if ("abc"[1] != data[1]) abort(); + char *as_ptr = data; + if (2[as_ptr] != as_ptr[2]) abort(); + if ("abc"[1] != as_ptr[1]) abort(); + return 0; +} + +// run +// expect=fail diff --git a/test/cases/run/array_value_type_casts_properly.c b/test/cases/run/array_value_type_casts_properly.c new file mode 100644 index 0000000..85ec0e8 --- /dev/null +++ b/test/cases/run/array_value_type_casts_properly.c @@ -0,0 +1,18 @@ +#include +unsigned int choose[53][10]; +static int hash_binary(int k) +{ + choose[0][k] = 3; + int sum = 0; + sum += choose[0][k]; + return sum; +} + +int main() { + int s = hash_binary(4); + if (s != 3) abort(); + return 0; +} + +// run +// expect=fail diff --git a/test/cases/run/array_value_type_casts_properly_use_+=.c b/test/cases/run/array_value_type_casts_properly_use_+=.c new file mode 100644 index 0000000..03a11ee --- /dev/null +++ b/test/cases/run/array_value_type_casts_properly_use_+=.c @@ -0,0 +1,19 @@ +#include +static int hash_binary(int k) +{ + unsigned int choose[1][1] = {{3}}; + int sum = -1; + int prev = 0; + prev = sum += choose[0][0]; + if (sum != 2) abort(); + return sum + prev; +} + +int main() { + int x = hash_binary(4); + if (x != 4) abort(); + return 0; +} + +// run +// expect=fail diff --git a/test/cases/run/assign_bool_result_to_int_or_char.c b/test/cases/run/assign_bool_result_to_int_or_char.c new file mode 100644 index 0000000..fa0bc99 --- /dev/null +++ b/test/cases/run/assign_bool_result_to_int_or_char.c @@ -0,0 +1,13 @@ +#include +#include +bool foo() { return true; } +int main() { + int x = foo(); + if (x != 1) abort(); + signed char c = foo(); + if (c != 1) abort(); + return 0; +} + +// run +// expect=fail diff --git a/test/cases/run/assign_enum_to_int.c b/test/cases/run/assign_enum_to_int.c new file mode 100644 index 0000000..714919c --- /dev/null +++ b/test/cases/run/assign_enum_to_int.c @@ -0,0 +1,15 @@ +#include +typedef enum { + ENUM_0 = 0, + ENUM_1 = 1, +} my_enum_t; + +int main() { + my_enum_t val = ENUM_1; + int x = val; + if (x != 1) abort(); + return 0; +} + +// run +// expect=fail diff --git a/test/cases/run/assign_enum_to_uint,_no_explicit_cast.c b/test/cases/run/assign_enum_to_uint,_no_explicit_cast.c new file mode 100644 index 0000000..65b7dae --- /dev/null +++ b/test/cases/run/assign_enum_to_uint,_no_explicit_cast.c @@ -0,0 +1,15 @@ +#include +typedef enum { + ENUM_0 = 0, + ENUM_1 = 1, +} my_enum_t; + +int main() { + my_enum_t val = ENUM_1; + unsigned int x = val; + if (x != 1) abort(); + return 0; +} + +// run +// expect=fail diff --git a/test/cases/run/assignment_as_expression.c b/test/cases/run/assignment_as_expression.c new file mode 100644 index 0000000..be2ed8e --- /dev/null +++ b/test/cases/run/assignment_as_expression.c @@ -0,0 +1,9 @@ +#include +int main() { + int a, b, c, d = 5; + int e = a = b = c = d; + if (e != 5) abort(); +} + +// run +// expect=fail diff --git a/test/cases/run/basic_vector_expressions.c b/test/cases/run/basic_vector_expressions.c new file mode 100644 index 0000000..96b5a14 --- /dev/null +++ b/test/cases/run/basic_vector_expressions.c @@ -0,0 +1,23 @@ +#include +#include +typedef int16_t __v8hi __attribute__((__vector_size__(16))); +int main(int argc, char**argv) { + __v8hi uninitialized; + __v8hi empty_init = {}; + for (int i = 0; i < 8; i++) { + if (empty_init[i] != 0) abort(); + } + __v8hi partial_init = {0, 1, 2, 3}; + + __v8hi a = {0, 1, 2, 3, 4, 5, 6, 7}; + __v8hi b = (__v8hi) {100, 200, 300, 400, 500, 600, 700, 800}; + + __v8hi sum = a + b; + for (int i = 0; i < 8; i++) { + if (sum[i] != a[i] + b[i]) abort(); + } + return 0; +} + +// run +// expect=fail diff --git a/test/cases/run/block-scope_static_variable_shadows_function_parameter.c b/test/cases/run/block-scope_static_variable_shadows_function_parameter.c new file mode 100644 index 0000000..9a7e44e --- /dev/null +++ b/test/cases/run/block-scope_static_variable_shadows_function_parameter.c @@ -0,0 +1,15 @@ +#include +int func1(int foo) { return foo + 1; } +int func2(void) { + static int foo = 5; + return foo++; +} +int main(void) { + if (func1(42) != 43) abort(); + if (func2() != 5) abort(); + if (func2() != 6) abort(); + return 0; +} + +// run +// expect=fail diff --git a/test/cases/run/boolean_values_and_expressions.c b/test/cases/run/boolean_values_and_expressions.c new file mode 100644 index 0000000..d57635d --- /dev/null +++ b/test/cases/run/boolean_values_and_expressions.c @@ -0,0 +1,18 @@ +#include +static const _Bool false_val = 0; +static const _Bool true_val = 1; +void foo(int x, int y) { + _Bool r = x < y; + if (!r) abort(); + _Bool self = foo; + if (self == false_val) abort(); + if (((r) ? 'a' : 'b') != 'a') abort(); +} +int main(int argc, char **argv) { + foo(2, 5); + if (false_val == true_val) abort(); + return 0; +} + +// run +// expect=fail diff --git a/test/cases/run/break_from_switch_statement.c b/test/cases/run/break_from_switch_statement.c new file mode 100644 index 0000000..42f0854 --- /dev/null +++ b/test/cases/run/break_from_switch_statement.c @@ -0,0 +1,44 @@ +#include +int switcher(int x) { + switch (x) { + case 0: // no braces + x += 1; + break; + case 1: // conditional break + if (x == 1) { + x += 1; + break; + } + x += 100; + case 2: { // braces with fallthrough + x += 1; + } + case 3: // fallthrough to return statement + x += 1; + case 42: { // random out of order case + x += 1; + return x; + } + case 4: { // break within braces + x += 1; + break; + } + case 5: + x += 1; // fallthrough to default + default: + x += 1; + } + return x; +} +int main(void) { + int expected[] = {1, 2, 5, 5, 5, 7, 7}; + for (int i = 0; i < sizeof(expected) / sizeof(int); i++) { + int res = switcher(i); + if (res != expected[i]) abort(); + } + if (switcher(42) != 43) abort(); + return 0; +} + +// run +// expect=fail diff --git a/test/cases/run/case_boolean_and_asterisk.c b/test/cases/run/case_boolean_and_asterisk.c new file mode 100644 index 0000000..57b3d18 --- /dev/null +++ b/test/cases/run/case_boolean_and_asterisk.c @@ -0,0 +1,11 @@ +#include +int main(int argc, char **argv) { + int value = (8 == 9) * 3; + int value2 = 3 * (9 == 9); + if (value != 0) abort(); + if (value2 == 0) abort(); + return 0; +} + +// run +// expect=fail diff --git a/test/cases/run/case_boolean_and_lt.c b/test/cases/run/case_boolean_and_lt.c new file mode 100644 index 0000000..19539ba --- /dev/null +++ b/test/cases/run/case_boolean_and_lt.c @@ -0,0 +1,9 @@ +#include +int main(int argc, char **argv) { + int value = (8 == 9) < 3; + if (value == 0) abort(); + return 0; +} + +// run +// expect=fail diff --git a/test/cases/run/case_boolean_and_plus_converts_bool_to_int.c b/test/cases/run/case_boolean_and_plus_converts_bool_to_int.c new file mode 100644 index 0000000..8078210 --- /dev/null +++ b/test/cases/run/case_boolean_and_plus_converts_bool_to_int.c @@ -0,0 +1,10 @@ +#include +int main(int argc, char **argv) { + int value = (8 == 9) + 3; + int value2 = 3 + (8 == 9); + if (value != value2) abort(); + return 0; +} + +// run +// expect=fail diff --git a/test/cases/run/case_boolean_expression_converted_to_int.c b/test/cases/run/case_boolean_expression_converted_to_int.c new file mode 100644 index 0000000..27979c3 --- /dev/null +++ b/test/cases/run/case_boolean_expression_converted_to_int.c @@ -0,0 +1,9 @@ +#include +int main(int argc, char **argv) { + int value = 1 + 2 * 3 + 4 * 5 + 6 << 7 | 8 == 9; + if (value != 4224) abort(); + return 0; +} + +// run +// expect=fail diff --git a/test/cases/run/case_boolean_expression_on_left_converted_to_int.c b/test/cases/run/case_boolean_expression_on_left_converted_to_int.c new file mode 100644 index 0000000..f165930 --- /dev/null +++ b/test/cases/run/case_boolean_expression_on_left_converted_to_int.c @@ -0,0 +1,9 @@ +#include +int main(int argc, char **argv) { + int value = 8 == 9 | 1 + 2 * 3 + 4 * 5 + 6 << 7; + if (value != 4224) abort(); + return 0; +} + +// run +// expect=fail diff --git a/test/cases/run/cast_RHS_of_compound_assignment_if_necessary,_unused_result.c b/test/cases/run/cast_RHS_of_compound_assignment_if_necessary,_unused_result.c new file mode 100644 index 0000000..43f32b8 --- /dev/null +++ b/test/cases/run/cast_RHS_of_compound_assignment_if_necessary,_unused_result.c @@ -0,0 +1,24 @@ +#include +int main(void) { + signed short val = -1; + val += 1; if (val != 0) abort(); + val -= 1; if (val != -1) abort(); + val *= 2; if (val != -2) abort(); + val /= 2; if (val != -1) abort(); + val %= 2; if (val != -1) abort(); + val <<= 1; if (val != -2) abort(); + val >>= 1; if (val != -1) abort(); + val += 100000000; // compile error if @truncate() not inserted + unsigned short uval = 1; + uval += 1; if (uval != 2) abort(); + uval -= 1; if (uval != 1) abort(); + uval *= 2; if (uval != 2) abort(); + uval /= 2; if (uval != 1) abort(); + uval %= 2; if (uval != 1) abort(); + uval <<= 1; if (uval != 2) abort(); + uval >>= 1; if (uval != 1) abort(); + uval += 100000000; // compile error if @truncate() not inserted +} + +// run +// expect=fail diff --git a/test/cases/run/cast_RHS_of_compound_assignment_if_necessary,_used_result.c b/test/cases/run/cast_RHS_of_compound_assignment_if_necessary,_used_result.c new file mode 100644 index 0000000..f78cb53 --- /dev/null +++ b/test/cases/run/cast_RHS_of_compound_assignment_if_necessary,_used_result.c @@ -0,0 +1,26 @@ +#include +int main(void) { + signed short foo; + signed short val = -1; + foo = (val += 1); if (foo != 0) abort(); + foo = (val -= 1); if (foo != -1) abort(); + foo = (val *= 2); if (foo != -2) abort(); + foo = (val /= 2); if (foo != -1) abort(); + foo = (val %= 2); if (foo != -1) abort(); + foo = (val <<= 1); if (foo != -2) abort(); + foo = (val >>= 1); if (foo != -1) abort(); + foo = (val += 100000000); // compile error if @truncate() not inserted + unsigned short ufoo; + unsigned short uval = 1; + ufoo = (uval += 1); if (ufoo != 2) abort(); + ufoo = (uval -= 1); if (ufoo != 1) abort(); + ufoo = (uval *= 2); if (ufoo != 2) abort(); + ufoo = (uval /= 2); if (ufoo != 1) abort(); + ufoo = (uval %= 2); if (ufoo != 1) abort(); + ufoo = (uval <<= 1); if (ufoo != 2) abort(); + ufoo = (uval >>= 1); if (ufoo != 1) abort(); + ufoo = (uval += 100000000); // compile error if @truncate() not inserted +} + +// run +// expect=fail diff --git a/test/cases/run/cast_builtin_call_result_to_opaque_struct_pointer.c b/test/cases/run/cast_builtin_call_result_to_opaque_struct_pointer.c new file mode 100644 index 0000000..adb10ba --- /dev/null +++ b/test/cases/run/cast_builtin_call_result_to_opaque_struct_pointer.c @@ -0,0 +1,13 @@ +#include +struct foo* make_foo(void) +{ + return (struct foo*)__builtin_strlen("0123456789ABCDEF"); +} +int main(void) { + struct foo *foo_pointer = make_foo(); + if (foo_pointer != (struct foo*)16) abort(); + return 0; +} + +// run +// expect=fail diff --git a/test/cases/run/cast_enum_to_smaller_signed_int.c b/test/cases/run/cast_enum_to_smaller_signed_int.c new file mode 100644 index 0000000..39655c5 --- /dev/null +++ b/test/cases/run/cast_enum_to_smaller_signed_int.c @@ -0,0 +1,16 @@ +#include +#include +typedef enum { + ENUM_0 = 0, + ENUM_384 = 384, +} my_enum_t; + +int main() { + my_enum_t val = ENUM_384; + int8_t x = (int8_t)val; + if (x != (int8_t)384) abort(); + return 0; +} + +// run +// expect=fail diff --git a/test/cases/run/cast_enum_to_smaller_uint.c b/test/cases/run/cast_enum_to_smaller_uint.c new file mode 100644 index 0000000..defe2a8 --- /dev/null +++ b/test/cases/run/cast_enum_to_smaller_uint.c @@ -0,0 +1,16 @@ +#include +#include +typedef enum { + ENUM_0 = 0, + ENUM_257 = 257, +} my_enum_t; + +int main() { + my_enum_t val = ENUM_257; + uint8_t x = (uint8_t)val; + if (x != (uint8_t)257) abort(); + return 0; +} + +// run +// expect=fail diff --git a/test/cases/run/cast_long_long_array_index_to_unsigned.c b/test/cases/run/cast_long_long_array_index_to_unsigned.c new file mode 100644 index 0000000..73242ff --- /dev/null +++ b/test/cases/run/cast_long_long_array_index_to_unsigned.c @@ -0,0 +1,10 @@ +#include +int main(int argc, char **argv) { + long long a[10], i = 0; + a[i] = 0; + if (a[i] != 0) abort(); + return 0; +} + +// run +// expect=fail diff --git a/test/cases/run/cast_negative_enum_to_smaller_signed_int.c b/test/cases/run/cast_negative_enum_to_smaller_signed_int.c new file mode 100644 index 0000000..eaa1285 --- /dev/null +++ b/test/cases/run/cast_negative_enum_to_smaller_signed_int.c @@ -0,0 +1,16 @@ +#include +#include +typedef enum { + ENUM_MINUS_1 = -1, + ENUM_384 = 384, +} my_enum_t; + +int main() { + my_enum_t val = ENUM_MINUS_1; + int8_t x = (int8_t)val; + if (x != -1) abort(); + return 0; +} + +// run +// expect=fail diff --git a/test/cases/run/cast_negative_enum_to_smaller_unsigned_int.c b/test/cases/run/cast_negative_enum_to_smaller_unsigned_int.c new file mode 100644 index 0000000..4f97500 --- /dev/null +++ b/test/cases/run/cast_negative_enum_to_smaller_unsigned_int.c @@ -0,0 +1,16 @@ +#include +#include +typedef enum { + ENUM_MINUS_1 = -1, + ENUM_384 = 384, +} my_enum_t; + +int main() { + my_enum_t val = ENUM_MINUS_1; + uint8_t x = (uint8_t)val; + if (x != (uint8_t)-1) abort(); + return 0; +} + +// run +// expect=fail diff --git a/test/cases/run/cast_signed_array_index_to_unsigned.c b/test/cases/run/cast_signed_array_index_to_unsigned.c new file mode 100644 index 0000000..5243d0c --- /dev/null +++ b/test/cases/run/cast_signed_array_index_to_unsigned.c @@ -0,0 +1,10 @@ +#include +int main(int argc, char **argv) { + int a[10], i = 0; + a[i] = 0; + if (a[i] != 0) abort(); + return 0; +} + +// run +// expect=fail diff --git a/test/cases/run/casting_away_const_and_volatile.c b/test/cases/run/casting_away_const_and_volatile.c new file mode 100644 index 0000000..1c9ed91 --- /dev/null +++ b/test/cases/run/casting_away_const_and_volatile.c @@ -0,0 +1,16 @@ +void foo(int *a) {} +void bar(const int *a) { + foo((int *)a); +} +void baz(volatile int *a) { + foo((int *)a); +} +int main(int argc, char **argv) { + int a = 0; + bar((const int *)&a); + baz((volatile int *)&a); + return 0; +} + +// run +// expect=fail diff --git a/test/cases/run/convert_single-statement_bodies_into_blocks_for_if,else,for,while.c b/test/cases/run/convert_single-statement_bodies_into_blocks_for_if,else,for,while.c new file mode 100644 index 0000000..8459751 --- /dev/null +++ b/test/cases/run/convert_single-statement_bodies_into_blocks_for_if,else,for,while.c @@ -0,0 +1,14 @@ +#include +int foo() { return 1; } +int main(void) { + int i = 0; + if (i == 0) if (i == 0) if (i != 0) i = 1; + if (i != 0) i = 1; else if (i == 0) if (i == 0) i += 1; + for (; i < 10;) for (; i < 10;) i++; + while (i == 100) while (i == 100) foo(); + if (0) do do "string"; while(1); while(1); + return 0; +} + +// run +// expect=fail diff --git a/test/cases/run/division_of_floating_literals.c b/test/cases/run/division_of_floating_literals.c new file mode 100644 index 0000000..43a09d5 --- /dev/null +++ b/test/cases/run/division_of_floating_literals.c @@ -0,0 +1,13 @@ +#define _NO_CRT_STDIO_INLINE 1 +#include +#define PI 3.14159265358979323846f +#define DEG2RAD (PI/180.0f) +int main(void) { + printf("DEG2RAD is: %f", DEG2RAD); + return 0; +} + +// run +// expect=fail +// +// DEG2RAD is: 0.017453 diff --git a/test/cases/run/dollar_sign_in_identifiers.c b/test/cases/run/dollar_sign_in_identifiers.c new file mode 100644 index 0000000..225d797 --- /dev/null +++ b/test/cases/run/dollar_sign_in_identifiers.c @@ -0,0 +1,16 @@ +#include +#define $FOO 2 +#define $foo bar$ +#define $baz($x) ($x + $FOO) +int $$$(int $x$) { return $x$ + $FOO; } +int main() { + int bar$ = 42; + if ($foo != 42) abort(); + if (bar$ != 42) abort(); + if ($baz(bar$) != 44) abort(); + if ($$$(bar$) != 44) abort(); + return 0; +} + +// run +// expect=fail diff --git a/test/cases/run/ensure_array_casts_outside_+=.c b/test/cases/run/ensure_array_casts_outside_+=.c new file mode 100644 index 0000000..6e02af6 --- /dev/null +++ b/test/cases/run/ensure_array_casts_outside_+=.c @@ -0,0 +1,18 @@ +#include +static int hash_binary(int k) +{ + unsigned int choose[3] = {1, 2, 3}; + int sum = -2; + int prev = sum + choose[k]; + if (prev != 0) abort(); + return sum + prev; +} + +int main() { + int x = hash_binary(1); + if (x != -2) abort(); + return 0; +} + +// run +// expect=fail diff --git a/test/cases/run/enum_used_as_boolean_expression.c b/test/cases/run/enum_used_as_boolean_expression.c new file mode 100644 index 0000000..540fd1c --- /dev/null +++ b/test/cases/run/enum_used_as_boolean_expression.c @@ -0,0 +1,11 @@ +#include +enum FOO {BAR, BAZ}; +int main(void) { + enum FOO x = BAR; + if (x) abort(); + if (!BAZ) abort(); + return 0; +} + +// run +// expect=fail diff --git a/test/cases/run/enum_with_value_that_fits_in_c_uint_but_not_c_int.c b/test/cases/run/enum_with_value_that_fits_in_c_uint_but_not_c_int.c new file mode 100644 index 0000000..8764eb3 --- /dev/null +++ b/test/cases/run/enum_with_value_that_fits_in_c_uint_but_not_c_int.c @@ -0,0 +1,10 @@ +#include +enum my_enum { + FORCE_UINT = 0xffffffff +}; +int main(void) { + if(FORCE_UINT != 0xffffffff) abort(); +} + +// run +// expect=fail diff --git a/test/cases/run/failed_macros_are_only_declared_once.c b/test/cases/run/failed_macros_are_only_declared_once.c new file mode 100644 index 0000000..ec8b6cd --- /dev/null +++ b/test/cases/run/failed_macros_are_only_declared_once.c @@ -0,0 +1,10 @@ +#define FOO = +#define FOO = +#define PtrToPtr64(p) ((void *POINTER_64) p) +#define STRUC_ALIGNED_STACK_COPY(t,s) ((CONST t *)(s)) +#define bar = 0x +#define baz = 0b +int main(void) {} + +// run +// expect=fail diff --git a/test/cases/run/forward_declarations.c b/test/cases/run/forward_declarations.c new file mode 100644 index 0000000..611bc08 --- /dev/null +++ b/test/cases/run/forward_declarations.c @@ -0,0 +1,10 @@ +#include +int foo(int); +int foo(int x) { return x + 1; } +int main(int argc, char **argv) { + if (foo(2) != 3) abort(); + return 0; +} + +// run +// expect=fail diff --git a/test/cases/run/function_macro_that_uses_builtin.c b/test/cases/run/function_macro_that_uses_builtin.c new file mode 100644 index 0000000..9818c69 --- /dev/null +++ b/test/cases/run/function_macro_that_uses_builtin.c @@ -0,0 +1,9 @@ +#include +#define FOO(x, y) (__builtin_popcount((x)) + __builtin_strlen((y))) +int main() { + if (FOO(7, "hello!") != 9) abort(); + return 0; +} + +// run +// expect=fail diff --git a/test/cases/run/handle_assert.h.c b/test/cases/run/handle_assert.h.c new file mode 100644 index 0000000..cbfa5dc --- /dev/null +++ b/test/cases/run/handle_assert.h.c @@ -0,0 +1,13 @@ +#include +int main() { + int x = 1; + int *xp = &x; + assert(1); + assert(x != 0); + assert(xp); + assert(*xp); + return 0; +} + +// run +// expect=fail diff --git a/test/cases/run/hello_world.c b/test/cases/run/hello_world.c new file mode 100644 index 0000000..b0b3263 --- /dev/null +++ b/test/cases/run/hello_world.c @@ -0,0 +1,11 @@ +#define _NO_CRT_STDIO_INLINE 1 +#include +int main(int argc, char **argv) { + printf("hello, world!"); + return 0; +} + +// run +// expect=fail +// +// hello, world! diff --git a/test/cases/run/implicit_enum_cast_in_boolean_expression.c b/test/cases/run/implicit_enum_cast_in_boolean_expression.c new file mode 100644 index 0000000..67a8265 --- /dev/null +++ b/test/cases/run/implicit_enum_cast_in_boolean_expression.c @@ -0,0 +1,19 @@ +#include +enum Foo { + FooA, + FooB, + FooC, +}; +int main() { + int a = 0; + float b = 0; + void *c = 0; + enum Foo d = FooA; + if (a || d) abort(); + if (d && b) abort(); + if (c || d) abort(); + return 0; +} + +// run +// expect=fail diff --git a/test/cases/run/multi-character_character_constant.c b/test/cases/run/multi-character_character_constant.c new file mode 100644 index 0000000..ed610e5 --- /dev/null +++ b/test/cases/run/multi-character_character_constant.c @@ -0,0 +1,12 @@ +#include +int main(void) { + int foo = 'abcd'; + switch (foo) { + case 'abcd': break; + default: abort(); + } + return 0; +} + +// run +// expect=fail diff --git a/test/cases/run/nested_same-name_static_locals.c b/test/cases/run/nested_same-name_static_locals.c new file mode 100644 index 0000000..f08af1f --- /dev/null +++ b/test/cases/run/nested_same-name_static_locals.c @@ -0,0 +1,23 @@ +#include +int func(int val) { + static int foo; + if (foo != val) abort(); + { + foo += 1; + static int foo = 2; + if (foo != val + 2) abort(); + foo += 1; + } + return foo; +} +int main(void) { + int foo = 1; + if (func(0) != 1) abort(); + if (func(1) != 2) abort(); + if (func(2) != 3) abort(); + if (foo != 1) abort(); + return 0; +} + +// run +// expect=fail diff --git a/test/cases/run/offsetof.c b/test/cases/run/offsetof.c new file mode 100644 index 0000000..eee5b1d --- /dev/null +++ b/test/cases/run/offsetof.c @@ -0,0 +1,33 @@ +#include +#include +#define container_of(ptr, type, member) ({ \ + const typeof( ((type *)0)->member ) *__mptr = (ptr); \ + (type *)( (char *)__mptr - offsetof(type,member) );}) +typedef struct { + int i; + struct { int x; char y; int z; } s; + float f; +} container; +int main(void) { + if (offsetof(container, i) != 0) abort(); + if (offsetof(container, s) <= offsetof(container, i)) abort(); + if (offsetof(container, f) <= offsetof(container, s)) abort(); + + container my_container; + typeof(my_container.s) *inner_member_pointer = &my_container.s; + float *float_member_pointer = &my_container.f; + int *anon_member_pointer = &my_container.s.z; + container *my_container_p; + + my_container_p = container_of(inner_member_pointer, container, s); + if (my_container_p != &my_container) abort(); + + my_container_p = container_of(float_member_pointer, container, f); + if (my_container_p != &my_container) abort(); + + if (container_of(anon_member_pointer, typeof(my_container.s), z) != inner_member_pointer) abort(); + return 0; +} + +// run +// expect=fail diff --git a/test/cases/run/parenthesized_string_literal.c b/test/cases/run/parenthesized_string_literal.c new file mode 100644 index 0000000..4725724 --- /dev/null +++ b/test/cases/run/parenthesized_string_literal.c @@ -0,0 +1,7 @@ +void foo(const char *s) {} +int main(void) { + foo(("bar")); +} + +// run +// expect=fail diff --git a/test/cases/run/pointer_arithmetic_with_signed_operand.c b/test/cases/run/pointer_arithmetic_with_signed_operand.c new file mode 100644 index 0000000..dcdccea --- /dev/null +++ b/test/cases/run/pointer_arithmetic_with_signed_operand.c @@ -0,0 +1,40 @@ +#include +int main() { + int array[10]; + int *x = &array[5]; + int *y; + int idx = 0; + y = x + ++idx; + if (y != x + 1 || y != &array[6]) abort(); + y = idx + x; + if (y != x + 1 || y != &array[6]) abort(); + y = x - idx; + if (y != x - 1 || y != &array[4]) abort(); + + idx = 0; + y = --idx + x; + if (y != x - 1 || y != &array[4]) abort(); + y = idx + x; + if (y != x - 1 || y != &array[4]) abort(); + y = x - idx; + if (y != x + 1 || y != &array[6]) abort(); + + idx = 1; + x += idx; + if (x != &array[6]) abort(); + x -= idx; + if (x != &array[5]) abort(); + y = (x += idx); + if (y != x || y != &array[6]) abort(); + y = (x -= idx); + if (y != x || y != &array[5]) abort(); + + if (array + idx != &array[1] || array + 1 != &array[1]) abort(); + idx = -1; + if (array - idx != &array[1]) abort(); + + return 0; +} + +// run +// expect=fail diff --git a/test/cases/run/pointer_difference-_C_standard_edge_case.c b/test/cases/run/pointer_difference-_C_standard_edge_case.c new file mode 100644 index 0000000..8846af8 --- /dev/null +++ b/test/cases/run/pointer_difference-_C_standard_edge_case.c @@ -0,0 +1,22 @@ +// C standard: if the expression P points either to an element of an array object or one +// past the last element of an array object, and the expression Q points to the last +// element of the same array object, the expression ((Q)+1)-(P) has the same value as +// ((Q)-(P))+1 and as -((P)-((Q)+1)), and has the value zero if the expression P points +// one past the last element of the array object, even though the expression (Q)+1 +// does not point to an element of the array object +#include +#include +#define SIZE 10 +int main() { + int foo[SIZE]; + int *start = &foo[0]; + int *P = start + SIZE; + int *Q = &foo[SIZE - 1]; + if ((Q + 1) - P != 0) abort(); + if ((Q + 1) - P != (Q - P) + 1) abort(); + if ((Q + 1) - P != -(P - (Q + 1))) abort(); + return 0; +} + +// run +// expect=fail diff --git a/test/cases/run/pointer_difference-_array_of_function_pointers.c b/test/cases/run/pointer_difference-_array_of_function_pointers.c new file mode 100644 index 0000000..f8e3beb --- /dev/null +++ b/test/cases/run/pointer_difference-_array_of_function_pointers.c @@ -0,0 +1,15 @@ +#include +int a(void) { return 1;} +int b(void) { return 2;} +int c(void) { return 3;} +typedef int (*myfunc)(void); +int main() { + myfunc arr[] = {a, b, c, a, b, c}; + myfunc *f1 = &arr[1]; + myfunc *f4 = &arr[4]; + if (f4 - f1 != 3) abort(); + return 0; +} + +// run +// expect=fail diff --git a/test/cases/run/pointer_difference-_scalar_array_with_size_truncation_or_negative_result.c b/test/cases/run/pointer_difference-_scalar_array_with_size_truncation_or_negative_result.c new file mode 100644 index 0000000..7d3b02e --- /dev/null +++ b/test/cases/run/pointer_difference-_scalar_array_with_size_truncation_or_negative_result.c @@ -0,0 +1,20 @@ +#include +#include +#define SIZE 10 +int main() { + int foo[SIZE]; + int *start = &foo[0]; + int *one_past_end = start + SIZE; + ptrdiff_t diff = one_past_end - start; + char diff_char = one_past_end - start; + if (diff != SIZE || diff_char != SIZE) abort(); + diff = start - one_past_end; + if (diff != -SIZE) abort(); + if (one_past_end - foo != SIZE) abort(); + if ((one_past_end - 1) - foo != SIZE - 1) abort(); + if ((start + 1) - foo != 1) abort(); + return 0; +} + +// run +// expect=fail diff --git a/test/cases/run/pointer_difference-_struct_array_with_padding.c b/test/cases/run/pointer_difference-_struct_array_with_padding.c new file mode 100644 index 0000000..2464be3 --- /dev/null +++ b/test/cases/run/pointer_difference-_struct_array_with_padding.c @@ -0,0 +1,22 @@ +#include +#include +#define SIZE 10 +typedef struct my_struct { + int x; + char c; + int y; +} my_struct_t; +int main() { + my_struct_t foo[SIZE]; + my_struct_t *start = &foo[0]; + my_struct_t *one_past_end = start + SIZE; + ptrdiff_t diff = one_past_end - start; + int diff_int = one_past_end - start; + if (diff != SIZE || diff_int != SIZE) abort(); + diff = start - one_past_end; + if (diff != -SIZE) abort(); + return 0; +} + +// run +// expect=fail diff --git a/test/cases/run/pointer_difference-_unary_operators.c b/test/cases/run/pointer_difference-_unary_operators.c new file mode 100644 index 0000000..c2f6aef --- /dev/null +++ b/test/cases/run/pointer_difference-_unary_operators.c @@ -0,0 +1,17 @@ +#include +int main() { + int foo[10]; + int *x = &foo[1]; + const int *y = &foo[5]; + if (y - x++ != 4) abort(); + if (y - x != 3) abort(); + if (y - ++x != 2) abort(); + if (y - x-- != 2) abort(); + if (y - x != 3) abort(); + if (y - --x != 4) abort(); + if (y - &foo[0] != 5) abort(); + return 0; +} + +// run +// expect=fail diff --git a/test/cases/run/scoped_for_loops_with_shadowing.c b/test/cases/run/scoped_for_loops_with_shadowing.c new file mode 100644 index 0000000..6d474eb --- /dev/null +++ b/test/cases/run/scoped_for_loops_with_shadowing.c @@ -0,0 +1,13 @@ +#include +int main() { + int count = 0; + for (int x = 0; x < 2; x++) + for (int x = 0; x < 2; x++) + count++; + + if (count != 4) abort(); + return 0; +} + +// run +// expect=fail diff --git a/test/cases/run/scoped_typedef.c b/test/cases/run/scoped_typedef.c new file mode 100644 index 0000000..e527656 --- /dev/null +++ b/test/cases/run/scoped_typedef.c @@ -0,0 +1,13 @@ +int main(int argc, char **argv) { + typedef int Foo; + typedef Foo Bar; + typedef void (*func)(int); + typedef int uint32_t; + uint32_t a; + Foo i; + Bar j; + return 0; +} + +// run +// expect=fail diff --git a/test/cases/run/signed_array_subscript.c b/test/cases/run/signed_array_subscript.c new file mode 100644 index 0000000..7b2398c --- /dev/null +++ b/test/cases/run/signed_array_subscript.c @@ -0,0 +1,24 @@ +#include +#include +#define TEST_NEGATIVE(type) { type x = -1; if (ptr[x] != 42) abort(); } +#define TEST_UNSIGNED(type) { type x = 2; if (arr[x] != 42) abort(); } +int main(void) { + int arr[] = {40, 41, 42, 43}; + int *ptr = arr + 3; + if (ptr[-1] != 42) abort(); + TEST_NEGATIVE(int); + TEST_NEGATIVE(long); + TEST_NEGATIVE(long long); + TEST_NEGATIVE(int64_t); + TEST_NEGATIVE(__int128); + TEST_UNSIGNED(unsigned); + TEST_UNSIGNED(unsigned long); + TEST_UNSIGNED(unsigned long long); + TEST_UNSIGNED(uint64_t); + TEST_UNSIGNED(size_t); + TEST_UNSIGNED(unsigned __int128); + return 0; +} + +// run +// expect=fail diff --git a/test/cases/run/static_K&R-style_no_prototype_function_declaration_(empty_parameter_list).c b/test/cases/run/static_K&R-style_no_prototype_function_declaration_(empty_parameter_list).c new file mode 100644 index 0000000..b630c2d --- /dev/null +++ b/test/cases/run/static_K&R-style_no_prototype_function_declaration_(empty_parameter_list).c @@ -0,0 +1,11 @@ +#include +static int foo() { + return 42; +} +int main() { + if (foo() != 42) abort(); + return 0; +} + +// run +// expect=fail diff --git a/test/cases/run/static_variable_in_block_scope.c b/test/cases/run/static_variable_in_block_scope.c new file mode 100644 index 0000000..ba2ab55 --- /dev/null +++ b/test/cases/run/static_variable_in_block_scope.c @@ -0,0 +1,14 @@ +#include +int foo() { + static int bar; + bar += 1; + return bar; +} +int main() { + foo(); + foo(); + if (foo() != 3) abort(); +} + +// run +// expect=fail diff --git a/test/cases/run/struct_initializer_-_packed.c b/test/cases/run/struct_initializer_-_packed.c new file mode 100644 index 0000000..50143b0 --- /dev/null +++ b/test/cases/run/struct_initializer_-_packed.c @@ -0,0 +1,13 @@ +#define _NO_CRT_STDIO_INLINE 1 +#include +#include +struct s {uint8_t x,y; + uint32_t z;} __attribute__((packed)) s0 = {1, 2}; +int main() { + /* sizeof nor offsetof currently supported */ + if (((intptr_t)&s0.z - (intptr_t)&s0.x) != 2) abort(); + return 0; +} + +// run +// expect=fail diff --git a/test/cases/run/struct_without_global_declaration_does_not_conflict_with_global_variable_name.c b/test/cases/run/struct_without_global_declaration_does_not_conflict_with_global_variable_name.c new file mode 100644 index 0000000..b8534a4 --- /dev/null +++ b/test/cases/run/struct_without_global_declaration_does_not_conflict_with_global_variable_name.c @@ -0,0 +1,12 @@ +#include +static void foo(struct foobar *unused) {} +static int struct_foobar = 123; +static int foobar = 456; +int main(void) { + if (struct_foobar != 123) abort(); + if (foobar != 456) abort(); + return 0; +} + +// run +// expect=fail diff --git a/test/cases/run/struct_without_global_declaration_does_not_conflict_with_local_variable_name.c b/test/cases/run/struct_without_global_declaration_does_not_conflict_with_local_variable_name.c new file mode 100644 index 0000000..09c13cd --- /dev/null +++ b/test/cases/run/struct_without_global_declaration_does_not_conflict_with_local_variable_name.c @@ -0,0 +1,12 @@ +#include +static void foo(struct foobar *unused) {} +int main(void) { + int struct_foobar = 123; + if (struct_foobar != 123) abort(); + int foobar = 456; + if (foobar != 456) abort(); + return 0; +} + +// run +// expect=fail diff --git a/test/cases/run/switch_case.c b/test/cases/run/switch_case.c new file mode 100644 index 0000000..e2e153b --- /dev/null +++ b/test/cases/run/switch_case.c @@ -0,0 +1,19 @@ +#include +int lottery(unsigned int x) { + switch (x) { + case 3: return 0; + case -1: return 3; + case 8 ... 10: return x; + default: return -1; + } +} +int main(int argc, char **argv) { + if (lottery(2) != -1) abort(); + if (lottery(3) != 0) abort(); + if (lottery(-1) != 3) abort(); + if (lottery(9) != 9) abort(); + return 0; +} + +// run +// expect=fail diff --git a/test/cases/run/ternary_operator.c b/test/cases/run/ternary_operator.c new file mode 100644 index 0000000..7c5aa7f --- /dev/null +++ b/test/cases/run/ternary_operator.c @@ -0,0 +1,17 @@ +#include +static int cnt = 0; +int foo() { cnt++; return 42; } +int main(int argc, char **argv) { + short q = 3; + signed char z0 = q?:1; + if (z0 != 3) abort(); + int z1 = 3?:1; + if (z1 != 3) abort(); + int z2 = foo()?:-1; + if (z2 != 42) abort(); + if (cnt != 1) abort(); + return 0; +} + +// run +// expect=fail diff --git a/test/cases/run/typedef_and_function_pointer.c b/test/cases/run/typedef_and_function_pointer.c new file mode 100644 index 0000000..984c4c8 --- /dev/null +++ b/test/cases/run/typedef_and_function_pointer.c @@ -0,0 +1,16 @@ +#include +typedef struct _Foo Foo; +typedef int Ret; +typedef int Param; +struct _Foo { Ret (*func)(Param p); }; +static Ret add1(Param p) { + return p + 1; +} +int main(int argc, char **argv) { + Foo strct = { .func = add1 }; + if (strct.func(16) != 17) abort(); + return 0; +} + +// run +// expect=fail diff --git a/test/cases/run/typedef_with_multiple_names.c b/test/cases/run/typedef_with_multiple_names.c new file mode 100644 index 0000000..2681eec --- /dev/null +++ b/test/cases/run/typedef_with_multiple_names.c @@ -0,0 +1,14 @@ +#include +typedef struct { + char field; +} a_t, b_t; + +int main(void) { + a_t a = { .field = 42 }; + b_t b = a; + if (b.field != 42) abort(); + return 0; +} + +// run +// expect=fail diff --git a/test/cases/run/typeof_operator.c b/test/cases/run/typeof_operator.c new file mode 100644 index 0000000..3707b4c --- /dev/null +++ b/test/cases/run/typeof_operator.c @@ -0,0 +1,19 @@ +#include +static int FOO = 42; +typedef typeof(FOO) foo_type; +typeof(foo_type) myfunc(typeof(FOO) x) { return (typeof(FOO)) x; } +int main(void) { + int x = FOO; + typeof(x) y = x; + foo_type z = y; + if (x != y) abort(); + if (myfunc(z) != x) abort(); + + const char *my_string = "bar"; + typeof (typeof (my_string)[4]) string_arr = {"a","b","c","d"}; + if (string_arr[0][0] != 'a' || string_arr[3][0] != 'd') abort(); + return 0; +} + +// run +// expect=fail diff --git a/test/cases/run/use_global_scope_for_record_enum_typedef_type_translation_if_needed.c b/test/cases/run/use_global_scope_for_record_enum_typedef_type_translation_if_needed.c new file mode 100644 index 0000000..7c3adf4 --- /dev/null +++ b/test/cases/run/use_global_scope_for_record_enum_typedef_type_translation_if_needed.c @@ -0,0 +1,19 @@ +void bar(void); +void baz(void); +struct foo { int x; }; +void bar() { + struct foo tmp; +} + +void baz() { + struct foo tmp; +} + +int main(void) { + bar(); + baz(); + return 0; +} + +// run +// expect=fail diff --git a/test/cases/run/use_of_unimplemented_builtin_in_unused_function_does_not_prevent_compilation.c b/test/cases/run/use_of_unimplemented_builtin_in_unused_function_does_not_prevent_compilation.c new file mode 100644 index 0000000..c6fbb08 --- /dev/null +++ b/test/cases/run/use_of_unimplemented_builtin_in_unused_function_does_not_prevent_compilation.c @@ -0,0 +1,12 @@ +// See __builtin_alloca_with_align comment in std.zig.c_builtins +#include +void unused() { + __builtin_alloca_with_align(1, 8); +} +int main(void) { + if (__builtin_sqrt(1.0) != 1.0) abort(); + return 0; +} + +// run +// expect=fail diff --git a/test/cases/run/variable_shadowing_type_type.c b/test/cases/run/variable_shadowing_type_type.c new file mode 100644 index 0000000..605909a --- /dev/null +++ b/test/cases/run/variable_shadowing_type_type.c @@ -0,0 +1,8 @@ +#include +int main() { + int type = 1; + if (type != 1) abort(); +} + +// run +// expect=fail diff --git a/test/cases/run/vector_casting.c b/test/cases/run/vector_casting.c new file mode 100644 index 0000000..f4ca1bf --- /dev/null +++ b/test/cases/run/vector_casting.c @@ -0,0 +1,18 @@ +#include +#include +typedef int8_t __v8qi __attribute__((__vector_size__(8))); +typedef uint8_t __v8qu __attribute__((__vector_size__(8))); +int main(int argc, char**argv) { + __v8qi signed_vector = { 1, 2, 3, 4, -1, -2, -3,-4}; + + uint64_t big_int = (uint64_t) signed_vector; + if (big_int != 0x01020304FFFEFDFCULL && big_int != 0xFCFDFEFF04030201ULL) abort(); + __v8qu unsigned_vector = (__v8qu) big_int; + for (int i = 0; i < 8; i++) { + if (unsigned_vector[i] != (uint8_t)signed_vector[i] && unsigned_vector[i] != (uint8_t)signed_vector[7 - i]) abort(); + } + return 0; +} + +// run +// expect=fail diff --git a/test/cases/translate/#define_a_char_literal.c b/test/cases/translate/#define_a_char_literal.c new file mode 100644 index 0000000..1ae5f07 --- /dev/null +++ b/test/cases/translate/#define_a_char_literal.c @@ -0,0 +1,6 @@ +#define A_CHAR 'a' + +// translate +// expect=fail +// +// pub const A_CHAR = 'a'; diff --git a/test/cases/translate/#define_an_unsigned_integer_literal.c b/test/cases/translate/#define_an_unsigned_integer_literal.c new file mode 100644 index 0000000..f1372b7 --- /dev/null +++ b/test/cases/translate/#define_an_unsigned_integer_literal.c @@ -0,0 +1,6 @@ +#define CHANNEL_COUNT 24 + +// translate +// expect=fail +// +// pub const CHANNEL_COUNT = @as(c_int, 24); diff --git a/test/cases/translate/#define_hex_literal_with_capital_X.c b/test/cases/translate/#define_hex_literal_with_capital_X.c new file mode 100644 index 0000000..64b0053 --- /dev/null +++ b/test/cases/translate/#define_hex_literal_with_capital_X.c @@ -0,0 +1,6 @@ +#define VAL 0XF00D + +// translate +// expect=fail +// +// pub const VAL = @import("std").zig.c_translation.promoteIntLiteral(c_int, 0xF00D, .hex); diff --git a/test/cases/translate/#define_referencing_another_#define.c b/test/cases/translate/#define_referencing_another_#define.c new file mode 100644 index 0000000..18b29a2 --- /dev/null +++ b/test/cases/translate/#define_referencing_another_#define.c @@ -0,0 +1,9 @@ +#define THING2 THING1 +#define THING1 1234 + +// translate +// expect=fail +// +// pub const THING1 = @as(c_int, 1234); +// +// pub const THING2 = THING1; diff --git a/test/cases/translate/#define_string.c b/test/cases/translate/#define_string.c new file mode 100644 index 0000000..ce11ea8 --- /dev/null +++ b/test/cases/translate/#define_string.c @@ -0,0 +1,6 @@ +#define foo "a string" + +// translate +// expect=fail +// +// pub const foo = "a string"; diff --git a/test/cases/translate/==,_!=.c b/test/cases/translate/==,_!=.c new file mode 100644 index 0000000..0a8aa6a --- /dev/null +++ b/test/cases/translate/==,_!=.c @@ -0,0 +1,20 @@ +int max(int a, int b) { + if (a == b) + return a; + if (a != b) + return b; + return a; +} + +// translate +// expect=fail +// +// pub export fn max(arg_a: c_int, arg_b: c_int) c_int { +// var a = arg_a; +// _ = &a; +// var b = arg_b; +// _ = &b; +// if (a == b) return a; +// if (a != b) return b; +// return a; +// } diff --git a/test/cases/translate/Assign_expression_from_bool_to_int.c b/test/cases/translate/Assign_expression_from_bool_to_int.c new file mode 100644 index 0000000..71a7187 --- /dev/null +++ b/test/cases/translate/Assign_expression_from_bool_to_int.c @@ -0,0 +1,17 @@ +void foo(void) { + int a; + if (a = 1 > 0) {} +} + +// translate +// expect=fail +// +// pub export fn foo() void { +// var a: c_int = undefined; +// _ = &a; +// if ((blk: { +// const tmp = @intFromBool(@as(c_int, 1) > @as(c_int, 0)); +// a = tmp; +// break :blk tmp; +// }) != 0) {} +// } diff --git a/test/cases/translate/Calling_convention.c b/test/cases/translate/Calling_convention.c new file mode 100644 index 0000000..a315a58 --- /dev/null +++ b/test/cases/translate/Calling_convention.c @@ -0,0 +1,7 @@ +void __attribute__((aarch64_vector_pcs)) foo1(float *a); + +// translate +// expect=fail +// target=aarch64-linux-none +// +// pub extern fn foo1(a: [*c]f32) callconv(.{ .aarch64_vfabi = .{} }) void; diff --git a/test/cases/translate/Demote_function_that_dereference_types_that_contain_opaque_type.c b/test/cases/translate/Demote_function_that_dereference_types_that_contain_opaque_type.c new file mode 100644 index 0000000..262dc35 --- /dev/null +++ b/test/cases/translate/Demote_function_that_dereference_types_that_contain_opaque_type.c @@ -0,0 +1,24 @@ +struct inner { + _Atomic int a; +}; +struct outer { + int thing; + struct inner sub_struct; +}; +void deref(struct outer *s) { + *s; +} + +// translate +// expect=fail +// +// pub const struct_inner = opaque {}; +// +// pub const struct_outer = extern struct { +// thing: c_int = @import("std").mem.zeroes(c_int), +// sub_struct: struct_inner = @import("std").mem.zeroes(struct_inner), +// }; +// +// warning: unable to translate function, demoted to extern +// +// pub extern fn deref(arg_s: ?*struct_outer) void; diff --git a/test/cases/translate/Demote_function_that_dereferences_opaque_type.c b/test/cases/translate/Demote_function_that_dereferences_opaque_type.c new file mode 100644 index 0000000..904b87a --- /dev/null +++ b/test/cases/translate/Demote_function_that_dereferences_opaque_type.c @@ -0,0 +1,14 @@ +struct my_struct { + unsigned a: 1; +}; +void deref(struct my_struct *s) { + *s; +} + +// translate +// expect=fail +// +// warning: cannot dereference opaque type +// +// warning: unable to translate function, demoted to extern +// pub extern fn deref(arg_s: ?*struct_my_struct) void; diff --git a/test/cases/translate/Demote_function_that_initializes_opaque_struct.c b/test/cases/translate/Demote_function_that_initializes_opaque_struct.c new file mode 100644 index 0000000..cf4e05c --- /dev/null +++ b/test/cases/translate/Demote_function_that_initializes_opaque_struct.c @@ -0,0 +1,16 @@ +struct my_struct { + unsigned a: 15; + unsigned: 2; + unsigned b: 15; +}; +void initialize(void) { + struct my_struct S = {.a = 1, .b = 2}; +} + +// translate +// expect=fail +// +// warning: local variable has opaque type +// +// warning: unable to translate function, demoted to extern +// pub extern fn initialize() void; diff --git a/test/cases/translate/Don't_make_const_parameters_mutable.c b/test/cases/translate/Don't_make_const_parameters_mutable.c new file mode 100644 index 0000000..b19c8d1 --- /dev/null +++ b/test/cases/translate/Don't_make_const_parameters_mutable.c @@ -0,0 +1,13 @@ +int max(const int x, int y) { + return (x > y) ? x : y; +} + +// translate +// expect=fail +// +// pub export fn max(x: c_int, arg_y: c_int) c_int { +// _ = &x; +// var y = arg_y; +// _ = &y; +// return if (x > y) x else y; +// } diff --git a/test/cases/translate/Forward-declared_enum.c b/test/cases/translate/Forward-declared_enum.c new file mode 100644 index 0000000..a74ee90 --- /dev/null +++ b/test/cases/translate/Forward-declared_enum.c @@ -0,0 +1,9 @@ +extern enum enum_ty my_enum; +enum enum_ty { FOO }; + +// translate +// expect=fail +// +// pub const FOO: c_int = 0; +// pub const enum_enum_ty = c_int; +// pub extern var my_enum: enum_enum_ty; diff --git a/test/cases/translate/Function_prototype_declared_within_function.c b/test/cases/translate/Function_prototype_declared_within_function.c new file mode 100644 index 0000000..175002c --- /dev/null +++ b/test/cases/translate/Function_prototype_declared_within_function.c @@ -0,0 +1,12 @@ +int foo(void) { + extern int bar(int, int); + return bar(1, 2); +} + +// translate +// expect=fail +// +// pub extern fn bar(c_int, c_int) c_int; +// pub export fn foo() c_int { +// return bar(@as(c_int, 1), @as(c_int, 2)); +// } diff --git a/test/cases/translate/Macro_matching.c b/test/cases/translate/Macro_matching.c new file mode 100644 index 0000000..4e1f655 --- /dev/null +++ b/test/cases/translate/Macro_matching.c @@ -0,0 +1,6 @@ +#define FOO(X) (X ## U) + +// translate +// expect=fail +// +// pub const FOO = @import("std").zig.c_translation.Macros.U_SUFFIX; diff --git a/test/cases/translate/Macro_qualified_functions.c b/test/cases/translate/Macro_qualified_functions.c new file mode 100644 index 0000000..0a9aaf7 --- /dev/null +++ b/test/cases/translate/Macro_qualified_functions.c @@ -0,0 +1,6 @@ +void __attribute__((sysv_abi)) foo(void); + +// translate +// expect=fail +// +// pub extern fn foo() void; diff --git a/test/cases/translate/Macro_redefines_builtin.c b/test/cases/translate/Macro_redefines_builtin.c new file mode 100644 index 0000000..c5658eb --- /dev/null +++ b/test/cases/translate/Macro_redefines_builtin.c @@ -0,0 +1,6 @@ +#define FOO __builtin_popcount + +// translate +// expect=fail +// +// pub const FOO = __builtin_popcount; diff --git a/test/cases/translate/Macro_without_a_value.c b/test/cases/translate/Macro_without_a_value.c new file mode 100644 index 0000000..69e2126 --- /dev/null +++ b/test/cases/translate/Macro_without_a_value.c @@ -0,0 +1,6 @@ +#define FOO + +// translate +// expect=fail +// +// pub const FOO = ""; diff --git a/test/cases/translate/Make_sure_casts_are_grouped.c b/test/cases/translate/Make_sure_casts_are_grouped.c new file mode 100644 index 0000000..92ba061 --- /dev/null +++ b/test/cases/translate/Make_sure_casts_are_grouped.c @@ -0,0 +1,16 @@ +typedef struct +{ + int i; +} +*_XPrivDisplay; +typedef struct _XDisplay Display; +#define DefaultScreen(dpy) (((_XPrivDisplay)(dpy))->default_screen) + + +// translate +// expect=fail +// +// pub inline fn DefaultScreen(dpy: anytype) @TypeOf(@import("std").zig.c_translation.cast(_XPrivDisplay, dpy).*.default_screen) { +// _ = &dpy; +// return @import("std").zig.c_translation.cast(_XPrivDisplay, dpy).*.default_screen; +// } diff --git a/test/cases/translate/Only_consider_public_decls_in_`isBuiltinDefined`.c b/test/cases/translate/Only_consider_public_decls_in_`isBuiltinDefined`.c new file mode 100644 index 0000000..164f727 --- /dev/null +++ b/test/cases/translate/Only_consider_public_decls_in_`isBuiltinDefined`.c @@ -0,0 +1,6 @@ +#define FOO std + +// translate +// expect=fail +// +// pub const FOO = @compileError("unable to translate macro: undefined identifier `std`"); diff --git a/test/cases/translate/Parameterless_function_pointers.c b/test/cases/translate/Parameterless_function_pointers.c new file mode 100644 index 0000000..9df76ff --- /dev/null +++ b/test/cases/translate/Parameterless_function_pointers.c @@ -0,0 +1,8 @@ +typedef void (*fn0)(); +typedef void (*fn1)(char); + +// translate +// expect=fail +// +// pub const fn0 = ?*const fn (...) callconv(.c) void; +// pub const fn1 = ?*const fn (u8) callconv(.c) void; diff --git a/test/cases/translate/Parameterless_function_prototypes.c b/test/cases/translate/Parameterless_function_prototypes.c new file mode 100644 index 0000000..57989e5 --- /dev/null +++ b/test/cases/translate/Parameterless_function_prototypes.c @@ -0,0 +1,20 @@ +void a() {} +void b(void) {} +void c(); +void d(void); +static void e() {} +static void f(void) {} +static void g(); +static void h(void); + +// translate +// expect=fail +// +// pub export fn a() void {} +// pub export fn b() void {} +// pub extern fn c(...) void; +// pub extern fn d() void; +// pub fn e() callconv(.c) void {} +// pub fn f() callconv(.c) void {} +// pub extern fn g() void; +// pub extern fn h() void; diff --git a/test/cases/translate/Pointer_subtraction_with_typedef_linux.c b/test/cases/translate/Pointer_subtraction_with_typedef_linux.c new file mode 100644 index 0000000..91354a5 --- /dev/null +++ b/test/cases/translate/Pointer_subtraction_with_typedef_linux.c @@ -0,0 +1,18 @@ +typedef char* S; +void foo() { + S a, b; + long c = a - b; +} + +// translate +// expect=fail +// target=native-linux +// +// pub export fn foo() void { +// var a: S = undefined; +// _ = &a; +// var b: S = undefined; +// _ = &b; +// var c: c_long = @divExact(@as(c_long, @bitCast(@intFromPtr(a) -% @intFromPtr(b))), @sizeOf(u8)); +// _ = &c; +// } diff --git a/test/cases/translate/Pointer_subtraction_with_typedef_windows.c b/test/cases/translate/Pointer_subtraction_with_typedef_windows.c new file mode 100644 index 0000000..6df8d9d --- /dev/null +++ b/test/cases/translate/Pointer_subtraction_with_typedef_windows.c @@ -0,0 +1,18 @@ +typedef char* S; +void foo() { + S a, b; + long long c = a - b; +} + +// translate +// expect=fail +// target=native-windows-msvc +// +// pub export fn foo() void { +// var a: S = undefined; +// _ = &a; +// var b: S = undefined; +// _ = &b; +// var c: c_longlong = @divExact(@as(c_longlong, @bitCast(@intFromPtr(a) -% @intFromPtr(b))), @sizeOf(u8)); +// _ = &c; +// } diff --git a/test/cases/translate/Simple_array_access_of_pointer_with_non-negative_integer_constant.c b/test/cases/translate/Simple_array_access_of_pointer_with_non-negative_integer_constant.c new file mode 100644 index 0000000..3fde6ab --- /dev/null +++ b/test/cases/translate/Simple_array_access_of_pointer_with_non-negative_integer_constant.c @@ -0,0 +1,11 @@ +void foo(int *p) { + p[0]; + p[1]; +} + +// translate +// expect=fail +// +// _ = p[@as(c_uint, @intCast(@as(c_int, 0)))]; +// +// _ = p[@as(c_uint, @intCast(@as(c_int, 1)))]; diff --git a/test/cases/translate/Undefined_macro_identifier.c b/test/cases/translate/Undefined_macro_identifier.c new file mode 100644 index 0000000..76826dc --- /dev/null +++ b/test/cases/translate/Undefined_macro_identifier.c @@ -0,0 +1,6 @@ +#define FOO BAR + +// translate +// expect=fail +// +// pub const FOO = @compileError("unable to translate macro: undefined identifier `BAR`"); diff --git a/test/cases/translate/Use_@_syntax_for_bare_underscore_identifier_in_macro_or_public_symbol.c b/test/cases/translate/Use_@_syntax_for_bare_underscore_identifier_in_macro_or_public_symbol.c new file mode 100644 index 0000000..8e30bc8 --- /dev/null +++ b/test/cases/translate/Use_@_syntax_for_bare_underscore_identifier_in_macro_or_public_symbol.c @@ -0,0 +1,11 @@ +#define FOO _ +int _ = 42; + +// translate +// expect=fail +// +// pub inline fn FOO() @TypeOf(@"_") { +// return @"_"; +// } +// +// pub export var @"_": c_int = 42; diff --git a/test/cases/translate/__cdecl_doesn't_mess_up_function_pointers.c b/test/cases/translate/__cdecl_doesn't_mess_up_function_pointers.c new file mode 100644 index 0000000..4241548 --- /dev/null +++ b/test/cases/translate/__cdecl_doesn't_mess_up_function_pointers.c @@ -0,0 +1,6 @@ +void foo(void (__cdecl *fn_ptr)(void)); + +// translate +// expect=fail +// +// pub extern fn foo(fn_ptr: ?*const fn () callconv(.c) void) void; diff --git a/test/cases/translate/__extension___cast.c b/test/cases/translate/__extension___cast.c new file mode 100644 index 0000000..371fd45 --- /dev/null +++ b/test/cases/translate/__extension___cast.c @@ -0,0 +1,10 @@ +int foo(void) { + return __extension__ 1; +} + +// translate +// expect=fail +// +// pub export fn foo() c_int { +// return 1; +// } diff --git a/test/cases/translate/add,_sub,_mul,_div,_rem.c b/test/cases/translate/add,_sub,_mul,_div,_rem.c new file mode 100644 index 0000000..9281693 --- /dev/null +++ b/test/cases/translate/add,_sub,_mul,_div,_rem.c @@ -0,0 +1,48 @@ +int s() { + int a, b, c; + c = a + b; + c = a - b; + c = a * b; + c = a / b; + c = a % b; +} +unsigned u() { + unsigned a, b, c; + c = a + b; + c = a - b; + c = a * b; + c = a / b; + c = a % b; +} + +// translate +// expect=fail +// +// pub export fn s() c_int { +// var a: c_int = undefined; +// _ = &a; +// var b: c_int = undefined; +// _ = &b; +// var c: c_int = undefined; +// _ = &c; +// c = a + b; +// c = a - b; +// c = a * b; +// c = @divTrunc(a, b); +// c = @import("std").zig.c_translation.signedRemainder(a, b); +// return 0; +// } +// pub export fn u() c_uint { +// var a: c_uint = undefined; +// _ = &a; +// var b: c_uint = undefined; +// _ = &b; +// var c: c_uint = undefined; +// _ = &c; +// c = a +% b; +// c = a -% b; +// c = a *% b; +// c = a / b; +// c = a % b; +// return 0; +// } diff --git a/test/cases/translate/address_of_operator.c b/test/cases/translate/address_of_operator.c new file mode 100644 index 0000000..4cce54e --- /dev/null +++ b/test/cases/translate/address_of_operator.c @@ -0,0 +1,16 @@ +int foo(void) { + int x = 1234; + int *ptr = &x; + return *ptr; +} + +// translate +// expect=fail +// +// pub export fn foo() c_int { +// var x: c_int = 1234; +// _ = &x; +// var ptr: [*c]c_int = &x; +// _ = &ptr; +// return ptr.*; +// } diff --git a/test/cases/translate/alignof.c b/test/cases/translate/alignof.c new file mode 100644 index 0000000..22d58ff --- /dev/null +++ b/test/cases/translate/alignof.c @@ -0,0 +1,11 @@ +void main() { + int a = _Alignof(int); +} + +// translate +// expect=fail +// +// pub export fn main() void { +// var a: c_int = @as(c_int, @bitCast(@as(c_uint, @truncate(@alignOf(c_int))))); +// _ = &a; +// } diff --git a/test/cases/translate/always_inline_attribute.c b/test/cases/translate/always_inline_attribute.c new file mode 100644 index 0000000..829ddaf --- /dev/null +++ b/test/cases/translate/always_inline_attribute.c @@ -0,0 +1,10 @@ +__attribute__((always_inline)) int foo() { + return 5; +} + +// translate +// expect=fail +// +// pub inline fn foo() c_int { +// return 5; +// } diff --git a/test/cases/translate/anonymous_enum.c b/test/cases/translate/anonymous_enum.c new file mode 100644 index 0000000..e220ce3 --- /dev/null +++ b/test/cases/translate/anonymous_enum.c @@ -0,0 +1,12 @@ +enum { + One, + Two, +}; + +// translate +// expect=fail +// target=native-linux +// +// pub const One: c_int = 0; +// pub const Two: c_int = 1; +// const enum_unnamed_1 = c_uint; diff --git a/test/cases/translate/anonymous_struct_&_unions.c b/test/cases/translate/anonymous_struct_&_unions.c new file mode 100644 index 0000000..d85b175 --- /dev/null +++ b/test/cases/translate/anonymous_struct_&_unions.c @@ -0,0 +1,26 @@ +typedef struct { + union { + char x; + struct { int y; }; + }; +} outer; +void foo(outer *x) { x->y = x->x; } + +// translate +// expect=fail +// +// const struct_unnamed_2 = extern struct { +// y: c_int = @import("std").mem.zeroes(c_int), +// }; +// const union_unnamed_1 = extern union { +// x: u8, +// unnamed_0: struct_unnamed_2, +// }; +// pub const outer = extern struct { +// unnamed_0: union_unnamed_1 = @import("std").mem.zeroes(union_unnamed_1), +// }; +// pub export fn foo(arg_x: [*c]outer) void { +// var x = arg_x; +// _ = &x; +// x.*.unnamed_0.unnamed_0.y = @as(c_int, @bitCast(@as(c_uint, x.*.unnamed_0.x))); +// } diff --git a/test/cases/translate/arg_name_aliasing_decl_which_comes_after.c b/test/cases/translate/arg_name_aliasing_decl_which_comes_after.c new file mode 100644 index 0000000..862e7f4 --- /dev/null +++ b/test/cases/translate/arg_name_aliasing_decl_which_comes_after.c @@ -0,0 +1,14 @@ +void foo(int bar) { + bar = 2; +} +int bar = 4; + +// translate +// expect=fail +// +// pub export fn foo(arg_bar_1: c_int) void { +// var bar_1 = arg_bar_1; +// _ = &bar_1; +// bar_1 = 2; +// } +// pub export var bar: c_int = 4; diff --git a/test/cases/translate/arg_name_aliasing_macro_which_comes_after.c b/test/cases/translate/arg_name_aliasing_macro_which_comes_after.c new file mode 100644 index 0000000..125072f --- /dev/null +++ b/test/cases/translate/arg_name_aliasing_macro_which_comes_after.c @@ -0,0 +1,15 @@ +void foo(int bar) { + bar = 2; +} +#define bar 4 + +// translate +// expect=fail +// +// pub export fn foo(arg_bar_1: c_int) void { +// var bar_1 = arg_bar_1; +// _ = &bar_1; +// bar_1 = 2; +// } +// +// pub const bar = @as(c_int, 4); diff --git a/test/cases/translate/array_access.c b/test/cases/translate/array_access.c new file mode 100644 index 0000000..a5b8045 --- /dev/null +++ b/test/cases/translate/array_access.c @@ -0,0 +1,19 @@ +#define ACCESS array[2] +int array[100] = {}; +int foo(int index) { + return array[index]; +} + +// translate +// expect=fail +// +// pub export var array: [100]c_int = [1]c_int{0} ** 100; +// pub export fn foo(arg_index: c_int) c_int { +// var index = arg_index; +// _ = &index; +// return array[@as(c_uint, @intCast(index))]; +// } +// +// pub inline fn ACCESS() @TypeOf(array[@as(usize, @intCast(@as(c_int, 2)))]) { +// return array[@as(usize, @intCast(@as(c_int, 2)))]; +// } diff --git a/test/cases/translate/array_initializer_expr.c b/test/cases/translate/array_initializer_expr.c new file mode 100644 index 0000000..50324e4 --- /dev/null +++ b/test/cases/translate/array_initializer_expr.c @@ -0,0 +1,18 @@ +static void foo(void){ + char arr[10] ={1}; + char *arr1[10] ={0}; +} + +// translate +// expect=fail +// +// pub fn foo() callconv(.c) void { +// var arr: [10]u8 = [1]u8{ +// 1, +// } ++ [1]u8{0} ** 9; +// _ = &arr; +// var arr1: [10][*c]u8 = [1][*c]u8{ +// null, +// } ++ [1][*c]u8{null} ** 9; +// _ = &arr1; +// } diff --git a/test/cases/translate/array_initializer_with_typedef.c b/test/cases/translate/array_initializer_with_typedef.c new file mode 100644 index 0000000..525a5f1 --- /dev/null +++ b/test/cases/translate/array_initializer_with_typedef.c @@ -0,0 +1,25 @@ +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}; + +// translate +// expect=fail +// +// pub const uuid_t = [16]u8; +// pub const UUID_NULL: uuid_t = [16]u8{ +// 0, +// 0, +// 0, +// 0, +// 0, +// 0, +// 0, +// 0, +// 0, +// 0, +// 0, +// 0, +// 0, +// 0, +// 0, +// 0, +// }; diff --git a/test/cases/translate/assign.c b/test/cases/translate/assign.c new file mode 100644 index 0000000..bb0c1aa --- /dev/null +++ b/test/cases/translate/assign.c @@ -0,0 +1,17 @@ +void max(int a) { + int tmp; + tmp = a; + a = tmp; +} + +// translate +// expect=fail +// +// pub export fn max(arg_a: c_int) void { +// var a = arg_a; +// _ = &a; +// var tmp: c_int = undefined; +// _ = &tmp; +// tmp = a; +// a = tmp; +// } diff --git a/test/cases/translate/basic_macro_function.c b/test/cases/translate/basic_macro_function.c new file mode 100644 index 0000000..ee0a7f7 --- /dev/null +++ b/test/cases/translate/basic_macro_function.c @@ -0,0 +1,24 @@ +extern int c; +#define BASIC(c) (c*2) +#define FOO(L,b) (L + b) +#define BAR() (c*c) + +// translate +// expect=fail +// +// pub extern var c: c_int; +// +// pub inline fn BASIC(c_1: anytype) @TypeOf(c_1 * @as(c_int, 2)) { +// _ = &c_1; +// return c_1 * @as(c_int, 2); +// } +// +// pub inline fn FOO(L: anytype, b: anytype) @TypeOf(L + b) { +// _ = &L; +// _ = &b; +// return L + b; +// } +// +// pub inline fn BAR() @TypeOf(c * c) { +// return c * c; +// } diff --git a/test/cases/translate/big_negative_enum_init_values_when_C_ABI_supports_long_long_enums.c b/test/cases/translate/big_negative_enum_init_values_when_C_ABI_supports_long_long_enums.c new file mode 100644 index 0000000..45b5afc --- /dev/null +++ b/test/cases/translate/big_negative_enum_init_values_when_C_ABI_supports_long_long_enums.c @@ -0,0 +1,55 @@ +// Windows treats this as an enum with type c_int +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, +}; + +// translate +// expect=fail +// target=native-linux +// +// pub const VAL01: c_int = 0; +// pub const VAL02: c_int = 1; +// pub const VAL03: c_int = 2; +// pub const VAL04: c_int = 3; +// pub const VAL05: c_int = -1; +// pub const VAL06: c_int = -2; +// pub const VAL07: c_int = -3; +// pub const VAL08: c_int = -4; +// pub const VAL09: c_int = -3; +// pub const VAL10: c_int = -1000012000; +// pub const VAL11: c_int = -1000161000; +// pub const VAL12: c_int = -1000174001; +// pub const VAL13: c_int = -3; +// pub const VAL14: c_int = -1000012000; +// pub const VAL15: c_int = -1000161000; +// pub const VAL16: c_int = -3; +// pub const VAL17: c_int = 1000011998; +// pub const VAL18: c_longlong = 1152921504606846976; +// pub const VAL19: c_longlong = 3458764513820540927; +// pub const VAL20: c_longlong = 6917529027641081854; +// pub const VAL21: c_longlong = 6917529027641081853; +// pub const VAL22: c_int = 0; +// pub const VAL23: c_longlong = -1; +// pub const enum_EnumWithInits = c_longlong; diff --git a/test/cases/translate/bin_not.c b/test/cases/translate/bin_not.c new file mode 100644 index 0000000..2590408 --- /dev/null +++ b/test/cases/translate/bin_not.c @@ -0,0 +1,13 @@ +int foo() { + int x; + return ~x; +} + +// translate +// expect=fail +// +// pub export fn foo() c_int { +// var x: c_int = undefined; +// _ = &x; +// return ~x; +// } diff --git a/test/cases/translate/binary_conditional_operator_where_condition_is_the_mangle_prefix.c b/test/cases/translate/binary_conditional_operator_where_condition_is_the_mangle_prefix.c new file mode 100644 index 0000000..b6a0669 --- /dev/null +++ b/test/cases/translate/binary_conditional_operator_where_condition_is_the_mangle_prefix.c @@ -0,0 +1,25 @@ +void foo() { + int f = 1; + int n, cond_temp = 1; + if (n = (cond_temp)?:(f)) {} +} + +// translate +// expect=fail +// +// pub export fn foo() void { +// var f: c_int = 1; +// _ = &f; +// var n: c_int = undefined; +// _ = &n; +// var cond_temp: c_int = 1; +// _ = &cond_temp; +// if ((blk: { +// const tmp = blk_1: { +// const cond_temp_2 = cond_temp; +// break :blk_1 if (cond_temp_2 != 0) cond_temp_2 else f; +// }; +// n = tmp; +// break :blk tmp; +// }) != 0) {} +// } diff --git a/test/cases/translate/binary_conditional_operator_where_false_expr_is_the_mangle_prefix.c b/test/cases/translate/binary_conditional_operator_where_false_expr_is_the_mangle_prefix.c new file mode 100644 index 0000000..22cfda7 --- /dev/null +++ b/test/cases/translate/binary_conditional_operator_where_false_expr_is_the_mangle_prefix.c @@ -0,0 +1,25 @@ +void foo() { + int cond_temp = 1; + int n, f = 1; + if (n = (f)?:(cond_temp)) {} +} + +// translate +// expect=fail +// +// pub export fn foo() void { +// var cond_temp: c_int = 1; +// _ = &cond_temp; +// var n: c_int = undefined; +// _ = &n; +// var f: c_int = 1; +// _ = &f; +// if ((blk: { +// const tmp = blk_1: { +// const cond_temp_2 = f; +// break :blk_1 if (cond_temp_2 != 0) cond_temp_2 else cond_temp; +// }; +// n = tmp; +// break :blk tmp; +// }) != 0) {} +// } diff --git a/test/cases/translate/bitshift.c b/test/cases/translate/bitshift.c new file mode 100644 index 0000000..f9753de --- /dev/null +++ b/test/cases/translate/bitshift.c @@ -0,0 +1,10 @@ +int foo(void) { + return (1 << 2) >> 1; +} + +// translate +// expect=fail +// +// pub export fn foo() c_int { +// return (@as(c_int, 1) << @intCast(2)) >> @intCast(1); +// } diff --git a/test/cases/translate/bitwise_binary_operators,_simpler_parens.c b/test/cases/translate/bitwise_binary_operators,_simpler_parens.c new file mode 100644 index 0000000..a11900d --- /dev/null +++ b/test/cases/translate/bitwise_binary_operators,_simpler_parens.c @@ -0,0 +1,14 @@ +int max(int a, int b) { + return (a & b) ^ (a | b); +} + +// translate +// expect=fail +// +// pub export fn max(arg_a: c_int, arg_b: c_int) c_int { +// var a = arg_a; +// _ = &a; +// var b = arg_b; +// _ = &b; +// return (a & b) ^ (a | b); +// } diff --git a/test/cases/translate/bitwise_not_on_u-suffixed_0_(zero)_in_macro_definition.c b/test/cases/translate/bitwise_not_on_u-suffixed_0_(zero)_in_macro_definition.c new file mode 100644 index 0000000..5c40b9b --- /dev/null +++ b/test/cases/translate/bitwise_not_on_u-suffixed_0_(zero)_in_macro_definition.c @@ -0,0 +1,6 @@ +#define NOT_ZERO (~0U) + +// translate +// expect=fail +// +// pub const NOT_ZERO = ~@as(c_uint, 0); diff --git a/test/cases/translate/bool_not.c b/test/cases/translate/bool_not.c new file mode 100644 index 0000000..15ee483 --- /dev/null +++ b/test/cases/translate/bool_not.c @@ -0,0 +1,25 @@ +int foo() { + int a; + float b; + void *c; + return !(a == 0); + return !a; + return !b; + return !c; +} + +// translate +// expect=fail +// +// pub export fn foo() c_int { +// var a: c_int = undefined; +// _ = &a; +// var b: f32 = undefined; +// _ = &b; +// var c: ?*anyopaque = undefined; +// _ = &c; +// return @intFromBool(!(a == @as(c_int, 0))); +// return @intFromBool(!(a != 0)); +// return @intFromBool(!(b != 0)); +// return @intFromBool(!(c != null)); +// } diff --git a/test/cases/translate/break_statement.c b/test/cases/translate/break_statement.c new file mode 100644 index 0000000..4d42d59 --- /dev/null +++ b/test/cases/translate/break_statement.c @@ -0,0 +1,14 @@ +void foo(void) { + for (;;) { + break; + } +} + +// translate +// expect=fail +// +// pub export fn foo() void { +// while (true) { +// break; +// } +// } diff --git a/test/cases/translate/c_booleans_are_just_ints.c b/test/cases/translate/c_booleans_are_just_ints.c new file mode 100644 index 0000000..204500b --- /dev/null +++ b/test/cases/translate/c_booleans_are_just_ints.c @@ -0,0 +1,12 @@ +#define FOO(x) ((x >= 0) + (x >= 0)) +#define BAR 1 && 2 > 4 + +// translate +// expect=fail +// +// pub inline fn FOO(x: anytype) @TypeOf(@intFromBool(x >= @as(c_int, 0)) + @intFromBool(x >= @as(c_int, 0))) { +// _ = &x; +// return @intFromBool(x >= @as(c_int, 0)) + @intFromBool(x >= @as(c_int, 0)); +// } +// +// pub const BAR = (@as(c_int, 1) != 0) and (@as(c_int, 2) > @as(c_int, 4)); diff --git a/test/cases/translate/c_style_cast.c b/test/cases/translate/c_style_cast.c new file mode 100644 index 0000000..1e89bdd --- /dev/null +++ b/test/cases/translate/c_style_cast.c @@ -0,0 +1,12 @@ +int int_from_float(float a) { + return (int)a; +} + +// translate +// expect=fail +// +// pub export fn int_from_float(arg_a: f32) c_int { +// var a = arg_a; +// _ = &a; +// return @as(c_int, @intFromFloat(a)); +// } diff --git a/test/cases/translate/cast_signed_array_index_to_unsigned.c b/test/cases/translate/cast_signed_array_index_to_unsigned.c new file mode 100644 index 0000000..4a9f5b0 --- /dev/null +++ b/test/cases/translate/cast_signed_array_index_to_unsigned.c @@ -0,0 +1,15 @@ +void foo() { + int a[10], i = 0; + a[i] = 0; +} + +// translate +// expect=fail +// +// pub export fn foo() void { +// var a: [10]c_int = undefined; +// _ = &a; +// var i: c_int = 0; +// _ = &i; +// a[@as(c_uint, @intCast(i))] = 0; +// } diff --git a/test/cases/translate/casting_away_const_and_volatile.c b/test/cases/translate/casting_away_const_and_volatile.c new file mode 100644 index 0000000..5ffcc32 --- /dev/null +++ b/test/cases/translate/casting_away_const_and_volatile.c @@ -0,0 +1,25 @@ +void foo(int *a) {} +void bar(const int *a) { + foo((int *)a); +} +void baz(volatile int *a) { + foo((int *)a); +} + +// translate +// expect=fail +// +// pub export fn foo(arg_a: [*c]c_int) void { +// var a = arg_a; +// _ = &a; +// } +// pub export fn bar(arg_a: [*c]const c_int) void { +// var a = arg_a; +// _ = &a; +// foo(@as([*c]c_int, @ptrCast(@volatileCast(@constCast(a))))); +// } +// pub export fn baz(arg_a: [*c]volatile c_int) void { +// var a = arg_a; +// _ = &a; +// foo(@as([*c]c_int, @ptrCast(@volatileCast(@constCast(a))))); +// } diff --git a/test/cases/translate/casting_pointer_to_pointer.c b/test/cases/translate/casting_pointer_to_pointer.c new file mode 100644 index 0000000..7fc2b77 --- /dev/null +++ b/test/cases/translate/casting_pointer_to_pointer.c @@ -0,0 +1,13 @@ +float **ptrptrcast() { + int **a; + return (float **)a; +} + +// translate +// expect=fail +// +// pub export fn ptrptrcast() [*c][*c]f32 { +// var a: [*c][*c]c_int = undefined; +// _ = &a; +// return @as([*c][*c]f32, @ptrCast(@alignCast(a))); +// } diff --git a/test/cases/translate/casting_pointers_to_ints_and_ints_to_pointers.c b/test/cases/translate/casting_pointers_to_ints_and_ints_to_pointers.c new file mode 100644 index 0000000..6bf2b3b --- /dev/null +++ b/test/cases/translate/casting_pointers_to_ints_and_ints_to_pointers.c @@ -0,0 +1,16 @@ +void foo(void); +void bar(void) { + void *func_ptr = foo; + void (*typed_func_ptr)(void) = (void (*)(void)) (unsigned long) func_ptr; +} + +// translate +// expect=fail +// +// pub extern fn foo() void; +// pub export fn bar() void { +// var func_ptr: ?*anyopaque = @as(?*anyopaque, @ptrCast(&foo)); +// _ = &func_ptr; +// var typed_func_ptr: ?*const fn () callconv(.c) void = @as(?*const fn () callconv(.c) void, @ptrFromInt(@as(c_ulong, @intCast(@intFromPtr(func_ptr))))); +// _ = &typed_func_ptr; +// } diff --git a/test/cases/translate/chaining_assign.c b/test/cases/translate/chaining_assign.c new file mode 100644 index 0000000..6bc6408 --- /dev/null +++ b/test/cases/translate/chaining_assign.c @@ -0,0 +1,21 @@ +void max(int a) { + int b, c; + c = b = a; +} + +// translate +// expect=fail +// +// pub export fn max(arg_a: c_int) void { +// var a = arg_a; +// _ = &a; +// var b: c_int = undefined; +// _ = &b; +// var c: c_int = undefined; +// _ = &c; +// c = blk: { +// const tmp = a; +// b = tmp; +// break :blk tmp; +// }; +// } diff --git a/test/cases/translate/comma_operator.c b/test/cases/translate/comma_operator.c new file mode 100644 index 0000000..8316db5 --- /dev/null +++ b/test/cases/translate/comma_operator.c @@ -0,0 +1,21 @@ +int foo() { + 2, 4; + return 2, 4, 6; +} + +// translate +// expect=fail +// +// pub export fn foo() c_int { +// _ = blk: { +// _ = @as(c_int, 2); +// break :blk @as(c_int, 4); +// }; +// return blk: { +// _ = blk_1: { +// _ = @as(c_int, 2); +// break :blk_1 @as(c_int, 4); +// }; +// break :blk @as(c_int, 6); +// }; +// } diff --git a/test/cases/translate/comment_after_integer_literal.c b/test/cases/translate/comment_after_integer_literal.c new file mode 100644 index 0000000..20819ed --- /dev/null +++ b/test/cases/translate/comment_after_integer_literal.c @@ -0,0 +1,6 @@ +#define SDL_INIT_VIDEO 0x00000020 /**< SDL_INIT_VIDEO implies SDL_INIT_EVENTS */ + +// translate +// expect=fail +// +// pub const SDL_INIT_VIDEO = @as(c_int, 0x00000020); diff --git a/test/cases/translate/comments.c b/test/cases/translate/comments.c new file mode 100644 index 0000000..1d426a7 --- /dev/null +++ b/test/cases/translate/comments.c @@ -0,0 +1,9 @@ +#define foo 1 //foo +#define bar /* bar */ 2 + +// translate +// expect=fail +// +// pub const foo = @as(c_int, 1); +// +// pub const bar = @as(c_int, 2); diff --git a/test/cases/translate/comparison_operators_(no_if).c b/test/cases/translate/comparison_operators_(no_if).c new file mode 100644 index 0000000..5ca6497 --- /dev/null +++ b/test/cases/translate/comparison_operators_(no_if).c @@ -0,0 +1,35 @@ +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; +} + +// translate +// expect=fail +// +// pub export fn test_comparisons(arg_a: c_int, arg_b: c_int) c_int { +// var a = arg_a; +// _ = &a; +// var b = arg_b; +// _ = &b; +// var c: c_int = @intFromBool(a < b); +// _ = &c; +// var d: c_int = @intFromBool(a > b); +// _ = &d; +// var e: c_int = @intFromBool(a <= b); +// _ = &e; +// var f: c_int = @intFromBool(a >= b); +// _ = &f; +// var g: c_int = @intFromBool(c < d); +// _ = &g; +// var h: c_int = @intFromBool(e < f); +// _ = &h; +// var i: c_int = @intFromBool(g < h); +// _ = &i; +// return i; +// } diff --git a/test/cases/translate/complex_switch.c b/test/cases/translate/complex_switch.c new file mode 100644 index 0000000..b69a82f --- /dev/null +++ b/test/cases/translate/complex_switch.c @@ -0,0 +1,18 @@ +int main() { + int i = 2; + switch (i) { + case 0: { + case 2:{ + i += 2;} + i += 1; + } + } +} + +// translate +// expect=fail +// +// source.h:5:13: warning: TODO complex switch +// +// source.h:1:5: warning: unable to translate function, demoted to extern +// pub extern fn main() c_int; diff --git a/test/cases/translate/compound_assignment_operators.c b/test/cases/translate/compound_assignment_operators.c new file mode 100644 index 0000000..4f48772 --- /dev/null +++ b/test/cases/translate/compound_assignment_operators.c @@ -0,0 +1,86 @@ +void foo(void) { + int a = 0; + unsigned b = 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); + a /= (a /= 1); + a %= (a %= 1); + b /= (b /= 1); + b %= (b %= 1); +} + +// translate +// expect=fail +// +// pub export fn foo() void { +// var a: c_int = 0; +// _ = &a; +// var b: c_uint = 0; +// _ = &b; +// a += blk: { +// const ref = &a; +// ref.* += @as(c_int, 1); +// break :blk ref.*; +// }; +// a -= blk: { +// const ref = &a; +// ref.* -= @as(c_int, 1); +// break :blk ref.*; +// }; +// a *= blk: { +// const ref = &a; +// ref.* *= @as(c_int, 1); +// break :blk ref.*; +// }; +// a &= blk: { +// const ref = &a; +// ref.* &= @as(c_int, 1); +// break :blk ref.*; +// }; +// a |= blk: { +// const ref = &a; +// ref.* |= @as(c_int, 1); +// break :blk ref.*; +// }; +// a ^= blk: { +// const ref = &a; +// ref.* ^= @as(c_int, 1); +// break :blk ref.*; +// }; +// a >>= @intCast(blk: { +// const ref = &a; +// ref.* >>= @intCast(@as(c_int, 1)); +// break :blk ref.*; +// }); +// a <<= @intCast(blk: { +// const ref = &a; +// ref.* <<= @intCast(@as(c_int, 1)); +// break :blk ref.*; +// }); +// a = @divTrunc(a, blk: { +// const ref = &a; +// ref.* = @divTrunc(ref.*, @as(c_int, 1)); +// break :blk ref.*; +// }); +// a = @import("std").zig.c_translation.signedRemainder(a, blk: { +// const ref = &a; +// ref.* = @import("std").zig.c_translation.signedRemainder(ref.*, @as(c_int, 1)); +// break :blk ref.*; +// }); +// b /= blk: { +// const ref = &b; +// ref.* /= @as(c_uint, @bitCast(@as(c_int, 1))); +// break :blk ref.*; +// }; +// b %= blk: { +// const ref = &b; +// ref.* %= @as(c_uint, @bitCast(@as(c_int, 1))); +// break :blk ref.*; +// }; +// } diff --git a/test/cases/translate/compound_assignment_operators_unsigned.c b/test/cases/translate/compound_assignment_operators_unsigned.c new file mode 100644 index 0000000..1e6147c --- /dev/null +++ b/test/cases/translate/compound_assignment_operators_unsigned.c @@ -0,0 +1,59 @@ +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); +} + +// translate +// expect=fail +// +// pub export fn foo() void { +// var a: c_uint = 0; +// _ = &a; +// a +%= blk: { +// const ref = &a; +// ref.* +%= @as(c_uint, @bitCast(@as(c_int, 1))); +// break :blk ref.*; +// }; +// a -%= blk: { +// const ref = &a; +// ref.* -%= @as(c_uint, @bitCast(@as(c_int, 1))); +// break :blk ref.*; +// }; +// a *%= blk: { +// const ref = &a; +// ref.* *%= @as(c_uint, @bitCast(@as(c_int, 1))); +// break :blk ref.*; +// }; +// a &= blk: { +// const ref = &a; +// ref.* &= @as(c_uint, @bitCast(@as(c_int, 1))); +// break :blk ref.*; +// }; +// a |= blk: { +// const ref = &a; +// ref.* |= @as(c_uint, @bitCast(@as(c_int, 1))); +// break :blk ref.*; +// }; +// a ^= blk: { +// const ref = &a; +// ref.* ^= @as(c_uint, @bitCast(@as(c_int, 1))); +// break :blk ref.*; +// }; +// a >>= @intCast(blk: { +// const ref = &a; +// ref.* >>= @intCast(@as(c_int, 1)); +// break :blk ref.*; +// }); +// a <<= @intCast(blk: { +// const ref = &a; +// ref.* <<= @intCast(@as(c_int, 1)); +// break :blk ref.*; +// }); +// } diff --git a/test/cases/translate/conditional_operator.c b/test/cases/translate/conditional_operator.c new file mode 100644 index 0000000..8ff5aef --- /dev/null +++ b/test/cases/translate/conditional_operator.c @@ -0,0 +1,14 @@ +int bar(void) { + if (2 ? 5 : 5 ? 4 : 6) 2; + return 2 ? 5 : 5 ? 4 : 6; +} + +// translate +// expect=fail +// +// pub export fn bar() c_int { +// if ((if (true) @as(c_int, 5) else if (true) @as(c_int, 4) else @as(c_int, 6)) != 0) { +// _ = @as(c_int, 2); +// } +// return if (true) @as(c_int, 5) else if (true) @as(c_int, 4) else @as(c_int, 6); +// } diff --git a/test/cases/translate/conditional_operator_cast_to_void.c b/test/cases/translate/conditional_operator_cast_to_void.c new file mode 100644 index 0000000..4a8383a --- /dev/null +++ b/test/cases/translate/conditional_operator_cast_to_void.c @@ -0,0 +1,15 @@ +int bar(); +void foo() { + int a; + a ? a = 2 : bar(); +} + +// translate +// expect=fail +// +// pub extern fn bar(...) c_int; +// pub export fn foo() void { +// var a: c_int = undefined; +// _ = &a; +// if (a != 0) a = 2 else _ = bar(); +// } diff --git a/test/cases/translate/const_ptr_initializer.c b/test/cases/translate/const_ptr_initializer.c new file mode 100644 index 0000000..97bd963 --- /dev/null +++ b/test/cases/translate/const_ptr_initializer.c @@ -0,0 +1,6 @@ +static const char *v0 = "0.0.0"; + +// translate +// expect=fail +// +// pub var v0: [*c]const u8 = "0.0.0"; diff --git a/test/cases/translate/constant_size_array.c b/test/cases/translate/constant_size_array.c new file mode 100644 index 0000000..7e05915 --- /dev/null +++ b/test/cases/translate/constant_size_array.c @@ -0,0 +1,6 @@ +void func(int array[20]); + +// translate +// expect=fail +// +// pub extern fn func(array: [*c]c_int) void; diff --git a/test/cases/translate/continue_statement.c b/test/cases/translate/continue_statement.c new file mode 100644 index 0000000..4b01429 --- /dev/null +++ b/test/cases/translate/continue_statement.c @@ -0,0 +1,14 @@ +void foo(void) { + for (;;) { + continue; + } +} + +// translate +// expect=fail +// +// pub export fn foo() void { +// while (true) { +// continue; +// } +// } diff --git a/test/cases/translate/correct_semicolon_after_infixop.c b/test/cases/translate/correct_semicolon_after_infixop.c new file mode 100644 index 0000000..fe6fc91 --- /dev/null +++ b/test/cases/translate/correct_semicolon_after_infixop.c @@ -0,0 +1,10 @@ +#define _IO_ERR_SEEN 0 +#define __ferror_unlocked_body(_fp) (((_fp)->_flags & _IO_ERR_SEEN) != 0) + +// translate +// expect=fail +// +// pub inline fn __ferror_unlocked_body(_fp: anytype) @TypeOf((_fp.*._flags & _IO_ERR_SEEN) != @as(c_int, 0)) { +// _ = &_fp; +// return (_fp.*._flags & _IO_ERR_SEEN) != @as(c_int, 0); +// } diff --git a/test/cases/translate/demote_un-implemented_builtins.c b/test/cases/translate/demote_un-implemented_builtins.c new file mode 100644 index 0000000..3c6fcb1 --- /dev/null +++ b/test/cases/translate/demote_un-implemented_builtins.c @@ -0,0 +1,6 @@ +#define FOO(X) __builtin_alloca_with_align((X), 8) + +// translate +// expect=fail +// +// pub const FOO = @compileError("unable to translate macro: undefined identifier `__builtin_alloca_with_align`"); diff --git a/test/cases/translate/deref_function_pointer.c b/test/cases/translate/deref_function_pointer.c new file mode 100644 index 0000000..0357465 --- /dev/null +++ b/test/cases/translate/deref_function_pointer.c @@ -0,0 +1,32 @@ +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(); +} + +// translate +// expect=fail +// +// pub export fn foo() void {} +// pub export fn baz() c_int { +// return 0; +// } +// pub export fn bar() void { +// var f: ?*const fn () callconv(.c) void = &foo; +// _ = &f; +// var b: ?*const fn () callconv(.c) c_int = &baz; +// _ = &b; +// f.?(); +// f.?(); +// foo(); +// _ = b.?(); +// _ = b.?(); +// _ = baz(); +// } diff --git a/test/cases/translate/discard_unused_local_variables_and_function_parameters.c b/test/cases/translate/discard_unused_local_variables_and_function_parameters.c new file mode 100644 index 0000000..1beaea0 --- /dev/null +++ b/test/cases/translate/discard_unused_local_variables_and_function_parameters.c @@ -0,0 +1,21 @@ +#define FOO(A, B) (A) +int bar(int x, int y) { + return x; +} + +// translate +// expect=fail +// +// pub export fn bar(arg_x: c_int, arg_y: c_int) c_int { +// var x = arg_x; +// _ = &x; +// var y = arg_y; +// _ = &y; +// return x; +// } +// +// pub inline fn FOO(A: anytype, B: anytype) @TypeOf(A) { +// _ = &A; +// _ = &B; +// return A; +// } diff --git a/test/cases/translate/do_loop.c b/test/cases/translate/do_loop.c new file mode 100644 index 0000000..9bdd8b2 --- /dev/null +++ b/test/cases/translate/do_loop.c @@ -0,0 +1,29 @@ +void foo(void) { + int a = 2; + do { + a = a - 1; + } while (a); + + int b = 2; + do + b = b -1; + while (b); +} + +// translate +// expect=fail +// +// pub export fn foo() void { +// var a: c_int = 2; +// _ = &a; +// while (true) { +// a = a - @as(c_int, 1); +// if (!(a != 0)) break; +// } +// var b: c_int = 2; +// _ = &b; +// while (true) { +// b = b - @as(c_int, 1); +// if (!(b != 0)) break; +// } +// } diff --git a/test/cases/translate/do_while_as_expr.c b/test/cases/translate/do_while_as_expr.c new file mode 100644 index 0000000..6b01594 --- /dev/null +++ b/test/cases/translate/do_while_as_expr.c @@ -0,0 +1,13 @@ +static void foo(void) { + if (1) + do {} while (0); +} + +// translate +// expect=fail +// +// pub fn foo() callconv(.c) void { +// if (true) while (true) { +// if (!false) break; +// }; +// } diff --git a/test/cases/translate/do_while_with_breaks.c b/test/cases/translate/do_while_with_breaks.c new file mode 100644 index 0000000..3c7b4b1 --- /dev/null +++ b/test/cases/translate/do_while_with_breaks.c @@ -0,0 +1,48 @@ +void foo(int a) { + do { + if (a) break; + } while (4); + do { + if (a) break; + } while (0); + do { + if (a) break; + } while (a); + do { + break; + } while (3); + do { + break; + } while (0); + do { + break; + } while (a); +} + +// translate +// expect=fail +// +// pub export fn foo(arg_a: c_int) void { +// var a = arg_a; +// _ = &a; +// while (true) { +// if (a != 0) break; +// } +// while (true) { +// if (a != 0) break; +// if (!false) break; +// } +// while (true) { +// if (a != 0) break; +// if (!(a != 0)) break; +// } +// while (true) { +// break; +// } +// while (true) { +// break; +// } +// while (true) { +// break; +// } +// } diff --git a/test/cases/translate/don't_export_inline_functions.c b/test/cases/translate/don't_export_inline_functions.c new file mode 100644 index 0000000..2309c18 --- /dev/null +++ b/test/cases/translate/don't_export_inline_functions.c @@ -0,0 +1,12 @@ +inline void a(void) {} +static void b(void) {} +void c(void) {} +static void foo() {} + +// translate +// expect=fail +// +// pub fn a() callconv(.c) void {} +// pub fn b() callconv(.c) void {} +// pub export fn c() void {} +// pub fn foo() callconv(.c) void {} diff --git a/test/cases/translate/duplicate_typedef.c b/test/cases/translate/duplicate_typedef.c new file mode 100644 index 0000000..bf29cc3 --- /dev/null +++ b/test/cases/translate/duplicate_typedef.c @@ -0,0 +1,11 @@ +typedef long foo; +typedef int bar; +typedef long foo; +typedef int baz; + +// translate +// expect=fail +// +// pub const foo = c_long; +// pub const bar = c_int; +// pub const baz = c_int; diff --git a/test/cases/translate/empty_for_loop.c b/test/cases/translate/empty_for_loop.c new file mode 100644 index 0000000..bbad406 --- /dev/null +++ b/test/cases/translate/empty_for_loop.c @@ -0,0 +1,10 @@ +void foo(void) { + for (;;) { } +} + +// translate +// expect=fail +// +// pub export fn foo() void { +// while (true) {} +// } diff --git a/test/cases/translate/enums_MSVC.c b/test/cases/translate/enums_MSVC.c new file mode 100644 index 0000000..5889480 --- /dev/null +++ b/test/cases/translate/enums_MSVC.c @@ -0,0 +1,51 @@ +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, +}; + +// translate +// expect=fail +// target=native-windows-msvc +// +// pub const a: c_int = 0; +// pub const b: c_int = 1; +// pub const c: c_int = 2; +// pub const d = c_int; +// pub const e: c_int = 0; +// pub const f: c_int = 4; +// pub const g: c_int = 5; +// const enum_unnamed_1 = c_int; +// pub export var h: enum_unnamed_1 = @as(c_uint, @bitCast(e)); +// pub const i: c_int = 0; +// pub const j: c_int = 1; +// pub const k: c_int = 2; +// const enum_unnamed_2 = c_int; +// pub const struct_Baz = extern struct { +// l: enum_unnamed_2 = @import("std").mem.zeroes(enum_unnamed_2), +// m: d = @import("std").mem.zeroes(d), +// }; +// pub const n: c_int = 0; +// pub const o: c_int = 1; +// pub const p: c_int = 2; +// pub const enum_i = c_int; +// +// pub const Baz = struct_Baz; diff --git a/test/cases/translate/enums_linux.c b/test/cases/translate/enums_linux.c new file mode 100644 index 0000000..9acf710 --- /dev/null +++ b/test/cases/translate/enums_linux.c @@ -0,0 +1,51 @@ +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, +}; + +// translate +// expect=fail +// target=native-linux +// +// pub const a: c_int = 0; +// pub const b: c_int = 1; +// pub const c: c_int = 2; +// pub const d = c_uint; +// pub const e: c_int = 0; +// pub const f: c_int = 4; +// pub const g: c_int = 5; +// const enum_unnamed_1 = c_uint; +// pub export var h: enum_unnamed_1 = @as(c_uint, @bitCast(e)); +// pub const i: c_int = 0; +// pub const j: c_int = 1; +// pub const k: c_int = 2; +// const enum_unnamed_2 = c_uint; +// pub const struct_Baz = extern struct { +// l: enum_unnamed_2 = @import("std").mem.zeroes(enum_unnamed_2), +// m: d = @import("std").mem.zeroes(d), +// }; +// pub const n: c_int = 0; +// pub const o: c_int = 1; +// pub const p: c_int = 2; +// pub const enum_i = c_uint; +// +// pub const Baz = struct_Baz; diff --git a/test/cases/translate/escape_sequences.c b/test/cases/translate/escape_sequences.c new file mode 100644 index 0000000..50b6c5c --- /dev/null +++ b/test/cases/translate/escape_sequences.c @@ -0,0 +1,44 @@ +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\""; +} + + +// translate +// expect=fail +// +// pub export fn escapes() [*c]const u8 { +// var a: u8 = '\''; +// _ = &a; +// var b: u8 = '\\'; +// _ = &b; +// var c: u8 = '\x07'; +// _ = &c; +// var d: u8 = '\x08'; +// _ = &d; +// var e: u8 = '\x0c'; +// _ = &e; +// var f: u8 = '\n'; +// _ = &f; +// var g: u8 = '\r'; +// _ = &g; +// var h: u8 = '\t'; +// _ = &h; +// var i: u8 = '\x0b'; +// _ = &i; +// var j: u8 = '\x00'; +// _ = &j; +// var k: u8 = '"'; +// _ = &k; +// return "'\\\x07\x08\x0c\n\r\t\x0b\x00\""; +// } diff --git a/test/cases/translate/extern_array_of_unknown_length.c b/test/cases/translate/extern_array_of_unknown_length.c new file mode 100644 index 0000000..01a3dbb --- /dev/null +++ b/test/cases/translate/extern_array_of_unknown_length.c @@ -0,0 +1,8 @@ +extern int foo[]; + +// translate +// expect=fail +// +// const foo: [*c]c_int = @extern([*c]c_int, .{ +// .name = "foo", +// }); diff --git a/test/cases/translate/field_access_expression.c b/test/cases/translate/field_access_expression.c new file mode 100644 index 0000000..4258788 --- /dev/null +++ b/test/cases/translate/field_access_expression.c @@ -0,0 +1,34 @@ +#define ARROW a->b +#define DOT a.b +extern struct Foo { + int b; +}a; +float b = 2.0f; +void foo(void) { + struct Foo *c; + a.b; + c->b; +} + +// translate +// expect=fail +// +// pub const struct_Foo = extern struct { +// b: c_int = @import("std").mem.zeroes(c_int), +// }; +// pub extern var a: struct_Foo; +// pub export var b: f32 = 2.0; +// pub export fn foo() void { +// var c: [*c]struct_Foo = undefined; +// _ = &c; +// _ = a.b; +// _ = c.*.b; +// } +// +// pub inline fn ARROW() @TypeOf(a.*.b) { +// return a.*.b; +// } +// +// pub inline fn DOT() @TypeOf(a.b) { +// return a.b; +// } diff --git a/test/cases/translate/float_suffixes.c b/test/cases/translate/float_suffixes.c new file mode 100644 index 0000000..52bf4af --- /dev/null +++ b/test/cases/translate/float_suffixes.c @@ -0,0 +1,36 @@ +#define foo 3.14f +#define bar 16.e-2l +#define FOO 0.12345 +#define BAR .12345 +#define baz 1e1 +#define BAZ 42e-3f +#define foobar -73.L +extern const float my_float = 1.0f; +extern const double my_double = 1.0; +extern const long double my_longdouble = 1.0l; +extern const long double my_extended_precision_longdouble = 1.0000000000000003l; + +// translate +// expect=fail +// +// pub const foo = @as(f32, 3.14); +// +// pub const bar = @as(c_longdouble, 16.e-2); +// +// pub const FOO = @as(f64, 0.12345); +// +// pub const BAR = @as(f64, 0.12345); +// +// pub const baz = @as(f64, 1e1); +// +// pub const BAZ = @as(f32, 42e-3); +// +// pub const foobar = -@as(c_longdouble, 73); +// +// pub export const my_float: f32 = 1.0; +// +// pub export const my_double: f64 = 1.0; +// +// pub export const my_longdouble: c_longdouble = 1.0; +// +// pub export const my_extended_precision_longdouble: c_longdouble = 0x1.000000000000159ep0; diff --git a/test/cases/translate/floats.c b/test/cases/translate/floats.c new file mode 100644 index 0000000..8882312 --- /dev/null +++ b/test/cases/translate/floats.c @@ -0,0 +1,12 @@ +float a = 3.1415; +double b = 3.1415; +int c = 3.1415; +double d = 3; + +// translate +// expect=fail +// +// pub export var a: f32 = @as(f32, @floatCast(3.1415)); +// pub export var b: f64 = 3.1415; +// pub export var c: c_int = @as(c_int, @intFromFloat(3.1415)); +// pub export var d: f64 = 3; diff --git a/test/cases/translate/for_loop.c b/test/cases/translate/for_loop.c new file mode 100644 index 0000000..4614b0f --- /dev/null +++ b/test/cases/translate/for_loop.c @@ -0,0 +1,14 @@ +void foo(void) { + for (int i = 0; i; i++) { } +} + +// translate +// expect=fail +// +// pub export fn foo() void { +// { +// var i: c_int = 0; +// _ = &i; +// while (i != 0) : (i += 1) {} +// } +// } diff --git a/test/cases/translate/for_loop_with_simple_init_expression.c b/test/cases/translate/for_loop_with_simple_init_expression.c new file mode 100644 index 0000000..0a79f96 --- /dev/null +++ b/test/cases/translate/for_loop_with_simple_init_expression.c @@ -0,0 +1,16 @@ +void foo(void) { + int i; + for (i = 3; i; i--) { } +} + +// translate +// expect=fail +// +// pub export fn foo() void { +// var i: c_int = undefined; +// _ = &i; +// { +// i = 3; +// while (i != 0) : (i -= 1) {} +// } +// } diff --git a/test/cases/translate/for_loops.c b/test/cases/translate/for_loops.c new file mode 100644 index 0000000..d7dbcb5 --- /dev/null +++ b/test/cases/translate/for_loops.c @@ -0,0 +1,32 @@ +void foo() { + for (int i = 2, b = 4; i + 2; i = 2) { + int a = 2; + a = 6, 5, 7; + } + char i = 2; +} + +// translate +// expect=fail +// +// pub export fn foo() void { +// { +// var i: c_int = 2; +// _ = &i; +// var b: c_int = 4; +// _ = &b; +// while ((i + @as(c_int, 2)) != 0) : (i = 2) { +// var a: c_int = 2; +// _ = &a; +// _ = blk: { +// _ = blk_1: { +// a = 6; +// break :blk_1 @as(c_int, 5); +// }; +// break :blk @as(c_int, 7); +// }; +// } +// } +// var i: u8 = 2; +// _ = &i; +// } diff --git a/test/cases/translate/for_on_non-bool.c b/test/cases/translate/for_on_non-bool.c new file mode 100644 index 0000000..7f9be62 --- /dev/null +++ b/test/cases/translate/for_on_non-bool.c @@ -0,0 +1,25 @@ +int for_none_bool() { + int a; + float b; + void *c; + for (;a;) return 0; + for (;b;) return 1; + for (;c;) return 2; + return 3; +} + +// translate +// expect=fail +// +// pub export fn for_none_bool() c_int { +// var a: c_int = undefined; +// _ = &a; +// var b: f32 = undefined; +// _ = &b; +// var c: ?*anyopaque = undefined; +// _ = &c; +// while (a != 0) return 0; +// while (b != 0) return 1; +// while (c != null) return 2; +// return 3; +// } diff --git a/test/cases/translate/function_call.c b/test/cases/translate/function_call.c new file mode 100644 index 0000000..20efd2f --- /dev/null +++ b/test/cases/translate/function_call.c @@ -0,0 +1,16 @@ +static void bar(void) { } +void foo(int *(baz)(void)) { + bar(); + baz(); +} + +// translate +// expect=fail +// +// pub fn bar() callconv(.c) void {} +// pub export fn foo(arg_baz: ?*const fn () callconv(.c) [*c]c_int) void { +// var baz = arg_baz; +// _ = &baz; +// bar(); +// _ = baz.?(); +// } diff --git a/test/cases/translate/function_prototype_translated_as_optional.c b/test/cases/translate/function_prototype_translated_as_optional.c new file mode 100644 index 0000000..ba0804e --- /dev/null +++ b/test/cases/translate/function_prototype_translated_as_optional.c @@ -0,0 +1,20 @@ +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; +}; + +// translate +// expect=fail +// +// pub const fnptr_ty = ?*const fn () callconv(.c) void; +// pub const fnptr_attr_ty = ?*const fn () callconv(.c) void; +// pub const struct_foo = extern struct { +// foo: ?*const fn () callconv(.c) void = @import("std").mem.zeroes(?*const fn () callconv(.c) void), +// bar: ?*const fn () callconv(.c) void = @import("std").mem.zeroes(?*const fn () callconv(.c) void), +// baz: fnptr_ty = @import("std").mem.zeroes(fnptr_ty), +// qux: fnptr_attr_ty = @import("std").mem.zeroes(fnptr_attr_ty), +// }; diff --git a/test/cases/translate/function_with_no_prototype.c b/test/cases/translate/function_with_no_prototype.c new file mode 100644 index 0000000..2187622 --- /dev/null +++ b/test/cases/translate/function_with_no_prototype.c @@ -0,0 +1,10 @@ +int foo() { + return 5; +} + +// translate +// expect=fail +// +// pub export fn foo() c_int { +// return 5; +// } diff --git a/test/cases/translate/generate_inline_func_for_#define_global_extern_fn.c b/test/cases/translate/generate_inline_func_for_#define_global_extern_fn.c new file mode 100644 index 0000000..ba15382 --- /dev/null +++ b/test/cases/translate/generate_inline_func_for_#define_global_extern_fn.c @@ -0,0 +1,20 @@ +extern void (*fn_ptr)(void); +#define foo fn_ptr + +extern char (*fn_ptr2)(int, float); +#define bar fn_ptr2 + +// translate +// expect=fail +// +// pub extern var fn_ptr: ?*const fn () callconv(.c) void; +// +// pub inline fn foo() void { +// return fn_ptr.?(); +// } +// +// pub extern var fn_ptr2: ?*const fn (c_int, f32) callconv(.c) u8; +// +// pub inline fn bar(arg_1: c_int, arg_2: f32) u8 { +// return fn_ptr2.?(arg_1, arg_2); +// } diff --git a/test/cases/translate/global_assembly.c b/test/cases/translate/global_assembly.c new file mode 100644 index 0000000..2a181e6 --- /dev/null +++ b/test/cases/translate/global_assembly.c @@ -0,0 +1,14 @@ +__asm__(".globl func\n\t" + ".type func, @function\n\t" + "func:\n\t" + ".cfi_startproc\n\t" + "movl $42, %eax\n\t" + "ret\n\t" + ".cfi_endproc"); + +// translate +// expect=fail +// +// comptime { +// asm (".globl func\n\t.type func, @function\n\tfunc:\n\t.cfi_startproc\n\tmovl $42, %eax\n\tret\n\t.cfi_endproc"); +// } diff --git a/test/cases/translate/handling_of__Bool_type.c b/test/cases/translate/handling_of__Bool_type.c new file mode 100644 index 0000000..a6475c7 --- /dev/null +++ b/test/cases/translate/handling_of__Bool_type.c @@ -0,0 +1,21 @@ +_Bool foo(_Bool x) { + _Bool a = x != 1; + _Bool b = a != 0; + _Bool c = foo; + return foo(c != b); +} + +// translate +// expect=fail +// +// pub export fn foo(arg_x: bool) bool { +// var x = arg_x; +// _ = &x; +// var a: bool = @as(c_int, @intFromBool(x)) != @as(c_int, 1); +// _ = &a; +// var b: bool = @as(c_int, @intFromBool(a)) != @as(c_int, 0); +// _ = &b; +// var c: bool = @intFromPtr(&foo) != 0; +// _ = &c; +// return foo(@as(c_int, @intFromBool(c)) != @as(c_int, @intFromBool(b))); +// } diff --git a/test/cases/translate/if_as_while_stmt_has_semicolon.c b/test/cases/translate/if_as_while_stmt_has_semicolon.c new file mode 100644 index 0000000..22fd702 --- /dev/null +++ b/test/cases/translate/if_as_while_stmt_has_semicolon.c @@ -0,0 +1,22 @@ +void foo() { + while (1) if (1) { + int a = 1; + } else { + int b = 2; + } + if (1) if (1) {} +} + +// translate +// expect=fail +// +// pub export fn foo() void { +// while (true) if (true) { +// var a: c_int = 1; +// _ = &a; +// } else { +// var b: c_int = 2; +// _ = &b; +// }; +// if (true) if (true) {}; +// } diff --git a/test/cases/translate/if_on_non-bool.c b/test/cases/translate/if_on_non-bool.c new file mode 100644 index 0000000..24f2d8e --- /dev/null +++ b/test/cases/translate/if_on_non-bool.c @@ -0,0 +1,32 @@ +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; +} + +// translate +// expect=fail +// target=native-linux +// +// pub const A: c_int = 0; +// pub const B: c_int = 1; +// pub const C: c_int = 2; +// pub const enum_SomeEnum = c_uint; +// pub export fn if_none_bool(arg_a: c_int, arg_b: f32, arg_c: ?*anyopaque, arg_d: enum_SomeEnum) c_int { +// var a = arg_a; +// _ = &a; +// var b = arg_b; +// _ = &b; +// var c = arg_c; +// _ = &c; +// var d = arg_d; +// _ = &d; +// if (a != 0) return 0; +// if (b != 0) return 1; +// if (c != null) return 2; +// if (d != 0) return 3; +// return 4; +// } diff --git a/test/cases/translate/if_statements.c b/test/cases/translate/if_statements.c new file mode 100644 index 0000000..0720d57 --- /dev/null +++ b/test/cases/translate/if_statements.c @@ -0,0 +1,25 @@ +void foo() { + if (2) { + int a = 2; + } + if (2, 5) { + int a = 2; + } +} + +// translate +// expect=fail +// +// pub export fn foo() void { +// if (true) { +// var a: c_int = 2; +// _ = &a; +// } +// if ((blk: { +// _ = @as(c_int, 2); +// break :blk @as(c_int, 5); +// }) != 0) { +// var a: c_int = 2; +// _ = &a; +// } +// } diff --git a/test/cases/translate/ignore_result,_explicit_function_arguments.c b/test/cases/translate/ignore_result,_explicit_function_arguments.c new file mode 100644 index 0000000..0650829 --- /dev/null +++ b/test/cases/translate/ignore_result,_explicit_function_arguments.c @@ -0,0 +1,21 @@ +void foo(void) { + int a; + 1; + "hey"; + 1 + 1; + 1 - 1; + a = 1; +} + +// translate +// expect=fail +// +// pub export fn foo() void { +// var a: c_int = undefined; +// _ = &a; +// _ = @as(c_int, 1); +// _ = "hey"; +// _ = @as(c_int, 1) + @as(c_int, 1); +// _ = @as(c_int, 1) - @as(c_int, 1); +// a = 1; +// } diff --git a/test/cases/translate/implicit_cast_to_void_ptr.c b/test/cases/translate/implicit_cast_to_void_ptr.c new file mode 100644 index 0000000..e870a42 --- /dev/null +++ b/test/cases/translate/implicit_cast_to_void_ptr.c @@ -0,0 +1,13 @@ +void *foo() { + unsigned short *x; + return x; +} + +// translate +// expect=fail +// +// pub export fn foo() ?*anyopaque { +// var x: [*c]c_ushort = undefined; +// _ = &x; +// return @as(?*anyopaque, @ptrCast(x)); +// } diff --git a/test/cases/translate/implicit_casts.c b/test/cases/translate/implicit_casts.c new file mode 100644 index 0000000..0fb7c5c --- /dev/null +++ b/test/cases/translate/implicit_casts.c @@ -0,0 +1,53 @@ +#include + +void fn_int(int x); +void fn_f32(float x); +void fn_f64(double x); +void fn_char(char x); +void fn_bool(bool x); +void fn_ptr(void *x); + +void call() { + fn_int(3.0f); + fn_int(3.0); + 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((int)&fn_int); + fn_ptr((void *)42); +} + +// translate +// expect=fail +// +// 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: ?*anyopaque) void; +// pub export fn call() void { +// fn_int(@as(c_int, @intFromFloat(3.0))); +// fn_int(@as(c_int, @intFromFloat(3.0))); +// fn_int(@as(c_int, 1094861636)); +// fn_f32(@as(f32, @floatFromInt(@as(c_int, 3)))); +// fn_f64(@as(f64, @floatFromInt(@as(c_int, 3)))); +// fn_char(@as(u8, @bitCast(@as(i8, @truncate(@as(c_int, '3')))))); +// fn_char(@as(u8, @bitCast(@as(i8, @truncate(@as(c_int, '\x01')))))); +// fn_char(@as(u8, @bitCast(@as(i8, @truncate(@as(c_int, 0)))))); +// fn_f32(3.0); +// fn_f64(3.0); +// fn_bool(@as(c_int, 123) != 0); +// fn_bool(@as(c_int, 0) != 0); +// fn_bool(@intFromPtr(&fn_int) != 0); +// fn_int(@as(c_int, @intCast(@intFromPtr(&fn_int)))); +// fn_ptr(@as(?*anyopaque, @ptrFromInt(@as(c_int, 42)))); +// } diff --git a/test/cases/translate/initializer_list_macro.c b/test/cases/translate/initializer_list_macro.c new file mode 100644 index 0000000..200be92 --- /dev/null +++ b/test/cases/translate/initializer_list_macro.c @@ -0,0 +1,54 @@ +typedef struct Color { + unsigned char r; + unsigned char g; + unsigned char b; + unsigned char a; +} Color; +#define CLITERAL(type) (type) +#define LIGHTGRAY CLITERAL(Color){ 200, 200, 200, 255 } // Light Gray +typedef struct boom_t +{ + int i1; +} boom_t; +#define FOO ((boom_t){1}) +typedef struct { float x; } MyCStruct; +#define A(_x) (MyCStruct) { .x = (_x) } +#define B A(0.f) + +// translate +// expect=fail +// +// pub const struct_Color = extern struct { +// r: u8 = @import("std").mem.zeroes(u8), +// g: u8 = @import("std").mem.zeroes(u8), +// b: u8 = @import("std").mem.zeroes(u8), +// a: u8 = @import("std").mem.zeroes(u8), +// }; +// pub const Color = struct_Color; +// +// pub inline fn CLITERAL(@"type": anytype) @TypeOf(@"type") { +// _ = &@"type"; +// return @"type"; +// } +// +// pub const LIGHTGRAY = @import("std").mem.zeroInit(CLITERAL(Color), .{ @as(c_int, 200), @as(c_int, 200), @as(c_int, 200), @as(c_int, 255) }); +// +// pub const struct_boom_t = extern struct { +// i1: c_int = @import("std").mem.zeroes(c_int), +// }; +// pub const boom_t = struct_boom_t; +// +// pub const FOO = @import("std").mem.zeroInit(boom_t, .{@as(c_int, 1)}); +// +// pub const MyCStruct = extern struct { +// x: f32 = @import("std").mem.zeroes(f32), +// }; +// +// pub inline fn A(_x: anytype) MyCStruct { +// _ = &_x; +// return @import("std").mem.zeroInit(MyCStruct, .{ +// .x = _x, +// }); +// } +// +// pub const B = A(@as(f32, 0)); diff --git a/test/cases/translate/integer_literal_promotion.c b/test/cases/translate/integer_literal_promotion.c new file mode 100644 index 0000000..b5ad2e8 --- /dev/null +++ b/test/cases/translate/integer_literal_promotion.c @@ -0,0 +1,20 @@ +#define GUARANTEED_TO_FIT_1 1024 +#define GUARANTEED_TO_FIT_2 10241024L +#define GUARANTEED_TO_FIT_3 20482048LU +#define MAY_NEED_PROMOTION_1 10241024 +#define MAY_NEED_PROMOTION_2 307230723072L +#define MAY_NEED_PROMOTION_3 819281928192LU +#define MAY_NEED_PROMOTION_HEX 0x80000000 +#define MAY_NEED_PROMOTION_OCT 020000000000 + +// translate +// expect=fail +// +// pub const GUARANTEED_TO_FIT_1 = @as(c_int, 1024); +// pub const GUARANTEED_TO_FIT_2 = @as(c_long, 10241024); +// pub const GUARANTEED_TO_FIT_3 = @as(c_ulong, 20482048); +// pub const MAY_NEED_PROMOTION_1 = @import("std").zig.c_translation.promoteIntLiteral(c_int, 10241024, .decimal); +// pub const MAY_NEED_PROMOTION_2 = @import("std").zig.c_translation.promoteIntLiteral(c_long, 307230723072, .decimal); +// pub const MAY_NEED_PROMOTION_3 = @import("std").zig.c_translation.promoteIntLiteral(c_ulong, 819281928192, .decimal); +// pub const MAY_NEED_PROMOTION_HEX = @import("std").zig.c_translation.promoteIntLiteral(c_int, 0x80000000, .hex); +// pub const MAY_NEED_PROMOTION_OCT = @import("std").zig.c_translation.promoteIntLiteral(c_int, 0o20000000000, .octal); diff --git a/test/cases/translate/l_integer_suffix_after_0_(zero)_in_macro_definition.c b/test/cases/translate/l_integer_suffix_after_0_(zero)_in_macro_definition.c new file mode 100644 index 0000000..c5d6e57 --- /dev/null +++ b/test/cases/translate/l_integer_suffix_after_0_(zero)_in_macro_definition.c @@ -0,0 +1,6 @@ +#define ZERO 0L + +// translate +// expect=fail +// +// pub const ZERO = @as(c_long, 0); diff --git a/test/cases/translate/l_integer_suffix_after_hex_literal.c b/test/cases/translate/l_integer_suffix_after_hex_literal.c new file mode 100644 index 0000000..6084718 --- /dev/null +++ b/test/cases/translate/l_integer_suffix_after_hex_literal.c @@ -0,0 +1,6 @@ +#define SDL_INIT_VIDEO 0x00000020l /**< SDL_INIT_VIDEO implies SDL_INIT_EVENTS */ + +// translate +// expect=fail +// +// pub const SDL_INIT_VIDEO = @as(c_long, 0x00000020); diff --git a/test/cases/translate/leading_zeroes.c b/test/cases/translate/leading_zeroes.c new file mode 100644 index 0000000..0db1c9d --- /dev/null +++ b/test/cases/translate/leading_zeroes.c @@ -0,0 +1,12 @@ +#define O_RDONLY 00 +#define HELLO 000 +#define ZERO 0 +#define WORLD 00000123 + +// translate +// expect=fail +// +// pub const O_RDONLY = @as(c_int, 0o0); +// pub const HELLO = @as(c_int, 0o00); +// pub const ZERO = @as(c_int, 0); +// pub const WORLD = @as(c_int, 0o0000123); diff --git a/test/cases/translate/linksection()_attribute.c b/test/cases/translate/linksection()_attribute.c new file mode 100644 index 0000000..27db9f3 --- /dev/null +++ b/test/cases/translate/linksection()_attribute.c @@ -0,0 +1,12 @@ +// Use the "segment,section" format to make this test pass when +// targeting the mach-o binary format +__attribute__ ((__section__("NEAR,.data"))) +extern char my_array[16]; +__attribute__ ((__section__("NEAR,.data"))) +void my_fn(void) { } + +// translate +// expect=fail +// +// pub extern var my_array: [16]u8 linksection("NEAR,.data"); +// pub export fn my_fn() linksection("NEAR,.data") void {} diff --git a/test/cases/translate/ll_integer_suffix_after_0_(zero)_in_macro_definition.c b/test/cases/translate/ll_integer_suffix_after_0_(zero)_in_macro_definition.c new file mode 100644 index 0000000..c0121ce --- /dev/null +++ b/test/cases/translate/ll_integer_suffix_after_0_(zero)_in_macro_definition.c @@ -0,0 +1,6 @@ +#define ZERO 0LL + +// translate +// expect=fail +// +// pub const ZERO = @as(c_longlong, 0); diff --git a/test/cases/translate/ll_integer_suffix_after_hex_literal.c b/test/cases/translate/ll_integer_suffix_after_hex_literal.c new file mode 100644 index 0000000..804dd86 --- /dev/null +++ b/test/cases/translate/ll_integer_suffix_after_hex_literal.c @@ -0,0 +1,6 @@ +#define SDL_INIT_VIDEO 0x00000020ll /**< SDL_INIT_VIDEO implies SDL_INIT_EVENTS */ + +// translate +// expect=fail +// +// pub const SDL_INIT_VIDEO = @as(c_longlong, 0x00000020); diff --git a/test/cases/translate/llu_integer_suffix_after_0_(zero)_in_macro_definition.c b/test/cases/translate/llu_integer_suffix_after_0_(zero)_in_macro_definition.c new file mode 100644 index 0000000..a1af3a4 --- /dev/null +++ b/test/cases/translate/llu_integer_suffix_after_0_(zero)_in_macro_definition.c @@ -0,0 +1,6 @@ +#define ZERO 0LLU + +// translate +// expect=fail +// +// pub const ZERO = @as(c_ulonglong, 0); diff --git a/test/cases/translate/llu_integer_suffix_after_hex_literal.c b/test/cases/translate/llu_integer_suffix_after_hex_literal.c new file mode 100644 index 0000000..469fc74 --- /dev/null +++ b/test/cases/translate/llu_integer_suffix_after_hex_literal.c @@ -0,0 +1,6 @@ +#define SDL_INIT_VIDEO 0x00000020llu /**< SDL_INIT_VIDEO implies SDL_INIT_EVENTS */ + +// translate +// expect=fail +// +// pub const SDL_INIT_VIDEO = @as(c_ulonglong, 0x00000020); diff --git a/test/cases/translate/logical_and,_logical_or,_on_non-bool_values,_extra_parens.c b/test/cases/translate/logical_and,_logical_or,_on_non-bool_values,_extra_parens.c new file mode 100644 index 0000000..7810a13 --- /dev/null +++ b/test/cases/translate/logical_and,_logical_or,_on_non-bool_values,_extra_parens.c @@ -0,0 +1,69 @@ +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 || (int)d); + int l = ((int)d && b); + int m = (c || (unsigned int)d); + SomeTypedef td = 44; + int o = (td || b); + int p = (c && td); + return ((((((((((e + f) + g) + h) + i) + j) + k) + l) + m) + o) + p); +} + +// translate +// expect=fail +// target=native-linux +// +// pub const FooA: c_int = 0; +// pub const FooB: c_int = 1; +// pub const FooC: c_int = 2; +// pub const enum_Foo = c_uint; +// pub const SomeTypedef = c_int; +// pub export fn and_or_non_bool(arg_a: c_int, arg_b: f32, arg_c: ?*anyopaque) c_int { +// var a = arg_a; +// _ = &a; +// var b = arg_b; +// _ = &b; +// var c = arg_c; +// _ = &c; +// var d: enum_Foo = @as(c_uint, @bitCast(FooA)); +// _ = &d; +// var e: c_int = @intFromBool((a != 0) and (b != 0)); +// _ = &e; +// var f: c_int = @intFromBool((b != 0) and (c != null)); +// _ = &f; +// var g: c_int = @intFromBool((a != 0) and (c != null)); +// _ = &g; +// var h: c_int = @intFromBool((a != 0) or (b != 0)); +// _ = &h; +// var i: c_int = @intFromBool((b != 0) or (c != null)); +// _ = &i; +// var j: c_int = @intFromBool((a != 0) or (c != null)); +// _ = &j; +// var k: c_int = @intFromBool((a != 0) or (@as(c_int, @bitCast(d)) != 0)); +// _ = &k; +// var l: c_int = @intFromBool((@as(c_int, @bitCast(d)) != 0) and (b != 0)); +// _ = &l; +// var m: c_int = @intFromBool((c != null) or (d != 0)); +// _ = &m; +// var td: SomeTypedef = 44; +// _ = &td; +// var o: c_int = @intFromBool((td != 0) or (b != 0)); +// _ = &o; +// var p: c_int = @intFromBool((c != null) and (td != 0)); +// _ = &p; +// return (((((((((e + f) + g) + h) + i) + j) + k) + l) + m) + o) + p; +// } +// +// pub const Foo = enum_Foo; diff --git a/test/cases/translate/logical_and,_logical_or.c b/test/cases/translate/logical_and,_logical_or.c new file mode 100644 index 0000000..bec825b --- /dev/null +++ b/test/cases/translate/logical_and,_logical_or.c @@ -0,0 +1,20 @@ +int max(int a, int b) { + if (a < b || a == b) + return b; + if (a >= b && a == b) + return a; + return a; +} + +// translate +// expect=fail +// +// pub export fn max(arg_a: c_int, arg_b: c_int) c_int { +// var a = arg_a; +// _ = &a; +// var b = arg_b; +// _ = &b; +// if ((a < b) or (a == b)) return b; +// if ((a >= b) and (a == b)) return a; +// return a; +// } diff --git a/test/cases/translate/long_long_array_index_cast_to_usize.c b/test/cases/translate/long_long_array_index_cast_to_usize.c new file mode 100644 index 0000000..cc7c866 --- /dev/null +++ b/test/cases/translate/long_long_array_index_cast_to_usize.c @@ -0,0 +1,15 @@ +void foo() { + long long a[10], i = 0; + a[i] = 0; +} + +// translate +// expect=fail +// +// pub export fn foo() void { +// var a: [10]c_longlong = undefined; +// _ = &a; +// var i: c_longlong = 0; +// _ = &i; +// a[@as(usize, @intCast(i))] = 0; +// } diff --git a/test/cases/translate/lu_integer_suffix_after_0_(zero)_in_macro_definition.c b/test/cases/translate/lu_integer_suffix_after_0_(zero)_in_macro_definition.c new file mode 100644 index 0000000..6729564 --- /dev/null +++ b/test/cases/translate/lu_integer_suffix_after_0_(zero)_in_macro_definition.c @@ -0,0 +1,6 @@ +#define ZERO 0LU + +// translate +// expect=fail +// +// pub const ZERO = @as(c_ulong, 0); diff --git a/test/cases/translate/lu_integer_suffix_after_hex_literal.c b/test/cases/translate/lu_integer_suffix_after_hex_literal.c new file mode 100644 index 0000000..25b2f7c --- /dev/null +++ b/test/cases/translate/lu_integer_suffix_after_hex_literal.c @@ -0,0 +1,6 @@ +#define SDL_INIT_VIDEO 0x00000020lu /**< SDL_INIT_VIDEO implies SDL_INIT_EVENTS */ + +// translate +// expect=fail +// +// pub const SDL_INIT_VIDEO = @as(c_ulong, 0x00000020); diff --git a/test/cases/translate/macro_add.c b/test/cases/translate/macro_add.c new file mode 100644 index 0000000..628435e --- /dev/null +++ b/test/cases/translate/macro_add.c @@ -0,0 +1,13 @@ +#define D3_AHB1PERIPH_BASE 0 +#define PERIPH_BASE (0x40000000UL) /*!< Base address of : AHB/APB Peripherals */ +#define D3_APB1PERIPH_BASE (PERIPH_BASE + 0x18000000UL) +#define RCC_BASE (D3_AHB1PERIPH_BASE + 0x4400UL) + +// translate +// expect=fail +// +// 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); diff --git a/test/cases/translate/macro_call.c b/test/cases/translate/macro_call.c new file mode 100644 index 0000000..bdcfcfc --- /dev/null +++ b/test/cases/translate/macro_call.c @@ -0,0 +1,10 @@ +#define CALL(arg) bar(arg) +int bar(int x) { return x; } + +// translate +// expect=fail +// +// pub inline fn CALL(arg: anytype) @TypeOf(bar(arg)) { +// _ = &arg; +// return bar(arg); +// } diff --git a/test/cases/translate/macro_call_with_no_args.c b/test/cases/translate/macro_call_with_no_args.c new file mode 100644 index 0000000..bda406b --- /dev/null +++ b/test/cases/translate/macro_call_with_no_args.c @@ -0,0 +1,10 @@ +#define CALL(arg) bar() +int bar(void) { return 0; } + +// translate +// expect=fail +// +// pub inline fn CALL(arg: anytype) @TypeOf(bar()) { +// _ = &arg; +// return bar(); +// } diff --git a/test/cases/translate/macro_cast.c b/test/cases/translate/macro_cast.c new file mode 100644 index 0000000..be07972 --- /dev/null +++ b/test/cases/translate/macro_cast.c @@ -0,0 +1,18 @@ +#include +int baz(void *arg) { return 0; } +#define FOO(bar) baz((void *)(baz)) +#define BAR (void*) a +#define BAZ (uint32_t)(2) +#define a 2 + +// translate +// expect=fail +// +// pub inline fn FOO(bar: anytype) @TypeOf(baz(@import("std").zig.c_translation.cast(?*anyopaque, baz))) { +// _ = &bar; +// return baz(@import("std").zig.c_translation.cast(?*anyopaque, baz)); +// } +// +// pub const BAR = @import("std").zig.c_translation.cast(?*anyopaque, a); +// +// pub const BAZ = @import("std").zig.c_translation.cast(u32, @as(c_int, 2)); diff --git a/test/cases/translate/macro_comma_operator.c b/test/cases/translate/macro_comma_operator.c new file mode 100644 index 0000000..9ae0ee5 --- /dev/null +++ b/test/cases/translate/macro_comma_operator.c @@ -0,0 +1,24 @@ +#define foo (foo, bar) +int baz(int x, int y) { return 0; } +#define bar(x) (&x, +3, 4 == 4, 5 * 6, baz(1, 2), 2 % 2, baz(1,2)) + +// translate +// expect=fail +// +// pub const foo = blk_1: { +// _ = &foo; +// break :blk_1 bar; +// }; +// +// pub inline fn bar(x: anytype) @TypeOf(baz(@as(c_int, 1), @as(c_int, 2))) { +// _ = &x; +// return blk_1: { +// _ = &x; +// _ = @as(c_int, 3); +// _ = @as(c_int, 4) == @as(c_int, 4); +// _ = @as(c_int, 5) * @as(c_int, 6); +// _ = baz(@as(c_int, 1), @as(c_int, 2)); +// _ = @import("std").zig.c_translation.MacroArithmetic.rem(@as(c_int, 2), @as(c_int, 2)); +// break :blk_1 baz(@as(c_int, 1), @as(c_int, 2)); +// }; +// } diff --git a/test/cases/translate/macro_comparisons.c b/test/cases/translate/macro_comparisons.c new file mode 100644 index 0000000..2978948 --- /dev/null +++ b/test/cases/translate/macro_comparisons.c @@ -0,0 +1,17 @@ +#define MIN(a, b) ((b) < (a) ? (b) : (a)) +#define MAX(a, b) ((b) > (a) ? (b) : (a)) + +// translate +// expect=fail +// +// pub inline fn MIN(a: anytype, b: anytype) @TypeOf(if (b < a) b else a) { +// _ = &a; +// _ = &b; +// return if (b < a) b else a; +// } +// +// pub inline fn MAX(a: anytype, b: anytype) @TypeOf(if (b > a) b else a) { +// _ = &a; +// _ = &b; +// return if (b > a) b else a; +// } diff --git a/test/cases/translate/macro_conditional_operator.c b/test/cases/translate/macro_conditional_operator.c new file mode 100644 index 0000000..71b7f58 --- /dev/null +++ b/test/cases/translate/macro_conditional_operator.c @@ -0,0 +1,9 @@ + int a, b, c; +#define FOO a ? b : c + +// translate +// expect=fail +// +// pub inline fn FOO() @TypeOf(if (a) b else c) { +// return if (a) b else c; +// } diff --git a/test/cases/translate/macro_defines_hexadecimal_float.c b/test/cases/translate/macro_defines_hexadecimal_float.c new file mode 100644 index 0000000..c2020fc --- /dev/null +++ b/test/cases/translate/macro_defines_hexadecimal_float.c @@ -0,0 +1,18 @@ +#define FOO 0xf7p38 +#define BAR -0X8F.BP5F +#define FOOBAR 0X0P+0 +#define BAZ -0x.0a5dp+12 +#define FOOBAZ 0xfE.P-1l + +// translate +// expect=fail +// +// pub const FOO = @as(f64, 0xf7p38); +// +// pub const BAR = -@as(f32, 0x8F.BP5); +// +// pub const FOOBAR = @as(f64, 0x0P+0); +// +// pub const BAZ = -@as(f64, 0x0.0a5dp+12); +// +// pub const FOOBAZ = @as(c_longdouble, 0xfE.P-1); diff --git a/test/cases/translate/macro_defines_string_literal_with_hex.c b/test/cases/translate/macro_defines_string_literal_with_hex.c new file mode 100644 index 0000000..d23ab75 --- /dev/null +++ b/test/cases/translate/macro_defines_string_literal_with_hex.c @@ -0,0 +1,12 @@ +#define FOO "aoeu\xab derp" +#define FOO2 "aoeu\x0007a derp" +#define FOO_CHAR '\xfF' + +// translate +// expect=fail +// +// pub const FOO = "aoeu\xab derp"; +// +// pub const FOO2 = "aoeu\x7a derp"; +// +// pub const FOO_CHAR = '\xff'; diff --git a/test/cases/translate/macro_defines_string_literal_with_octal.c b/test/cases/translate/macro_defines_string_literal_with_octal.c new file mode 100644 index 0000000..fc5fd79 --- /dev/null +++ b/test/cases/translate/macro_defines_string_literal_with_octal.c @@ -0,0 +1,12 @@ +#define FOO "aoeu\023 derp" +#define FOO2 "aoeu\0234 derp" +#define FOO_CHAR '\077' + +// translate +// expect=fail +// +// pub const FOO = "aoeu\x13 derp"; +// +// pub const FOO2 = "aoeu\x134 derp"; +// +// pub const FOO_CHAR = '\x3f'; diff --git a/test/cases/translate/macro_expressions_respect_C_operator_precedence.c b/test/cases/translate/macro_expressions_respect_C_operator_precedence.c new file mode 100644 index 0000000..88aaf1d --- /dev/null +++ b/test/cases/translate/macro_expressions_respect_C_operator_precedence.c @@ -0,0 +1,20 @@ +int *foo = 0; +#define FOO *((foo) + 2) +#define VALUE (1 + 2 * 3 + 4 * 5 + 6 << 7 | 8 == 9) +#define _AL_READ3BYTES(p) ((*(unsigned char *)(p)) \ + | (*((unsigned char *)(p) + 1) << 8) \ + | (*((unsigned char *)(p) + 2) << 16)) + +// translate +// expect=fail +// +// pub inline fn FOO() @TypeOf((foo + @as(c_int, 2)).*) { +// return (foo + @as(c_int, 2)).*; +// } +// +// pub const VALUE = ((((@as(c_int, 1) + (@as(c_int, 2) * @as(c_int, 3))) + (@as(c_int, 4) * @as(c_int, 5))) + @as(c_int, 6)) << @as(c_int, 7)) | @intFromBool(@as(c_int, 8) == @as(c_int, 9)); +// +// pub inline fn _AL_READ3BYTES(p: anytype) @TypeOf((@import("std").zig.c_translation.cast([*c]u8, p).* | ((@import("std").zig.c_translation.cast([*c]u8, p) + @as(c_int, 1)).* << @as(c_int, 8))) | ((@import("std").zig.c_translation.cast([*c]u8, p) + @as(c_int, 2)).* << @as(c_int, 16))) { +// _ = &p; +// return (@import("std").zig.c_translation.cast([*c]u8, p).* | ((@import("std").zig.c_translation.cast([*c]u8, p) + @as(c_int, 1)).* << @as(c_int, 8))) | ((@import("std").zig.c_translation.cast([*c]u8, p) + @as(c_int, 2)).* << @as(c_int, 16)); +// } diff --git a/test/cases/translate/macro_integer_literal_casts.c b/test/cases/translate/macro_integer_literal_casts.c new file mode 100644 index 0000000..20bec6b --- /dev/null +++ b/test/cases/translate/macro_integer_literal_casts.c @@ -0,0 +1,9 @@ +#define NULL ((void*)0) +#define FOO ((int)0x8000) + +// translate +// expect=fail +// +// pub const NULL = @import("std").zig.c_translation.cast(?*anyopaque, @as(c_int, 0)); +// +// pub const FOO = @import("std").zig.c_translation.cast(c_int, @import("std").zig.c_translation.promoteIntLiteral(c_int, 0x8000, .hex)); diff --git a/test/cases/translate/macro_keyword_define.c b/test/cases/translate/macro_keyword_define.c new file mode 100644 index 0000000..a3a5e57 --- /dev/null +++ b/test/cases/translate/macro_keyword_define.c @@ -0,0 +1,9 @@ +#define foo 1 +#define inline 2 + +// translate +// expect=fail +// +// pub const foo = @as(c_int, 1); +// +// pub const @"inline" = @as(c_int, 2); diff --git a/test/cases/translate/macro_line_continuation.c b/test/cases/translate/macro_line_continuation.c new file mode 100644 index 0000000..38bfc18 --- /dev/null +++ b/test/cases/translate/macro_line_continuation.c @@ -0,0 +1,10 @@ +int BAR = 0; +#define FOO -\ +BAR + +// translate +// expect=fail +// +// pub inline fn FOO() @TypeOf(-BAR) { +// return -BAR; +// } diff --git a/test/cases/translate/macro_pointer_cast.c b/test/cases/translate/macro_pointer_cast.c new file mode 100644 index 0000000..db53f3f --- /dev/null +++ b/test/cases/translate/macro_pointer_cast.c @@ -0,0 +1,8 @@ +#define NRF_GPIO_BASE 0 +typedef struct { int dummy; } NRF_GPIO_Type; +#define NRF_GPIO ((NRF_GPIO_Type *) NRF_GPIO_BASE) + +// translate +// expect=fail +// +// pub const NRF_GPIO = @import("std").zig.c_translation.cast([*c]NRF_GPIO_Type, NRF_GPIO_BASE); diff --git a/test/cases/translate/macro_using_argument_as_struct_name_is_not_translated.c b/test/cases/translate/macro_using_argument_as_struct_name_is_not_translated.c new file mode 100644 index 0000000..c8c25f2 --- /dev/null +++ b/test/cases/translate/macro_using_argument_as_struct_name_is_not_translated.c @@ -0,0 +1,6 @@ +#define FOO(x) struct x + +// translate +// expect=fail +// +// pub const FOO = @compileError("unable to translate macro: untranslatable usage of arg `x`"); diff --git a/test/cases/translate/macro_with_cast_to_unsigned_short,_long,_and_long_long.c b/test/cases/translate/macro_with_cast_to_unsigned_short,_long,_and_long_long.c new file mode 100644 index 0000000..6e94f75 --- /dev/null +++ b/test/cases/translate/macro_with_cast_to_unsigned_short,_long,_and_long_long.c @@ -0,0 +1,10 @@ +#define CURLAUTH_BASIC_BUT_USHORT ((unsigned short) 1) +#define CURLAUTH_BASIC ((unsigned long) 1) +#define CURLAUTH_BASIC_BUT_ULONGLONG ((unsigned long long) 1) + +// translate +// expect=fail +// +// pub const CURLAUTH_BASIC_BUT_USHORT = @import("std").zig.c_translation.cast(c_ushort, @as(c_int, 1)); +// pub const CURLAUTH_BASIC = @import("std").zig.c_translation.cast(c_ulong, @as(c_int, 1)); +// pub const CURLAUTH_BASIC_BUT_ULONGLONG = @import("std").zig.c_translation.cast(c_ulonglong, @as(c_int, 1)); diff --git a/test/cases/translate/macro_with_left_shift.c b/test/cases/translate/macro_with_left_shift.c new file mode 100644 index 0000000..94c282f --- /dev/null +++ b/test/cases/translate/macro_with_left_shift.c @@ -0,0 +1,6 @@ +#define REDISMODULE_READ (1<<0) + +// translate +// expect=fail +// +// pub const REDISMODULE_READ = @as(c_int, 1) << @as(c_int, 0); diff --git a/test/cases/translate/macro_with_nontrivial_cast.c b/test/cases/translate/macro_with_nontrivial_cast.c new file mode 100644 index 0000000..34be39f --- /dev/null +++ b/test/cases/translate/macro_with_nontrivial_cast.c @@ -0,0 +1,9 @@ +#define MAP_FAILED ((void *) -1) +typedef long long LONG_PTR; +#define INVALID_HANDLE_VALUE ((void *)(LONG_PTR)-1) + +// translate +// expect=fail +// +// pub const MAP_FAILED = @import("std").zig.c_translation.cast(?*anyopaque, -@as(c_int, 1)); +// pub const INVALID_HANDLE_VALUE = @import("std").zig.c_translation.cast(?*anyopaque, @import("std").zig.c_translation.cast(LONG_PTR, -@as(c_int, 1))); diff --git a/test/cases/translate/macro_with_parens_around_negative_number.c b/test/cases/translate/macro_with_parens_around_negative_number.c new file mode 100644 index 0000000..4f8d90d --- /dev/null +++ b/test/cases/translate/macro_with_parens_around_negative_number.c @@ -0,0 +1,6 @@ +#define LUA_GLOBALSINDEX (-10002) + +// translate +// expect=fail +// +// pub const LUA_GLOBALSINDEX = -@as(c_int, 10002); diff --git a/test/cases/translate/macro_with_right_shift.c b/test/cases/translate/macro_with_right_shift.c new file mode 100644 index 0000000..d427e15 --- /dev/null +++ b/test/cases/translate/macro_with_right_shift.c @@ -0,0 +1,9 @@ +#define FLASH_SIZE 0x200000UL /* 2 MB */ +#define FLASH_BANK_SIZE (FLASH_SIZE >> 1) /* 1 MB */ + +// translate +// expect=fail +// +// pub const FLASH_SIZE = @as(c_ulong, 0x200000); +// +// pub const FLASH_BANK_SIZE = FLASH_SIZE >> @as(c_int, 1); diff --git a/test/cases/translate/macros_with_field_targets.c b/test/cases/translate/macros_with_field_targets.c new file mode 100644 index 0000000..65b578f --- /dev/null +++ b/test/cases/translate/macros_with_field_targets.c @@ -0,0 +1,35 @@ +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 + +// translate +// expect=fail +// +// pub const GLbitfield = c_uint; +// pub const PFNGLCLEARPROC = ?*const fn (GLbitfield) callconv(.c) void; +// pub const OpenGLProc = ?*const fn () callconv(.c) void; +// const struct_unnamed_1 = extern struct { +// Clear: PFNGLCLEARPROC = @import("std").mem.zeroes(PFNGLCLEARPROC), +// }; +// pub const union_OpenGLProcs = extern union { +// ptr: [1]OpenGLProc, +// gl: struct_unnamed_1, +// }; +// pub extern var glProcs: union_OpenGLProcs; +// +// pub const glClearPFN = PFNGLCLEARPROC; +// +// pub inline fn glClearUnion(arg_2: GLbitfield) void { +// return glProcs.gl.Clear.?(arg_2); +// } +// +// pub const OpenGLProcs = union_OpenGLProcs; diff --git a/test/cases/translate/missing_return_stmt.c b/test/cases/translate/missing_return_stmt.c new file mode 100644 index 0000000..ab4296b --- /dev/null +++ b/test/cases/translate/missing_return_stmt.c @@ -0,0 +1,22 @@ +int foo() {} +int bar() { + int a = 2; +} +int baz() { + return 0; +} + +// translate +// expect=fail +// +// pub export fn foo() c_int { +// return 0; +// } +// pub export fn bar() c_int { +// var a: c_int = 2; +// _ = &a; +// return 0; +// } +// pub export fn baz() c_int { +// return 0; +// } diff --git a/test/cases/translate/multibyte_character_literals.c b/test/cases/translate/multibyte_character_literals.c new file mode 100644 index 0000000..1a4fdf0 --- /dev/null +++ b/test/cases/translate/multibyte_character_literals.c @@ -0,0 +1,6 @@ +#define FOO 'abcd' + +// translate +// expect=fail +// +// pub const FOO = 0x61626364; diff --git a/test/cases/translate/nameless_struct_fields_MSVC.c b/test/cases/translate/nameless_struct_fields_MSVC.c new file mode 100644 index 0000000..8a3ffe1 --- /dev/null +++ b/test/cases/translate/nameless_struct_fields_MSVC.c @@ -0,0 +1,23 @@ +typedef struct NAMED +{ + long name; +} NAMED; + +typedef struct ONENAMEWITHSTRUCT +{ + NAMED; + long b; +} ONENAMEWITHSTRUCT; + +// translate +// expect=fail +// target=native-windows-msvc +// +// pub const struct_NAMED = extern struct { +// name: c_long = @import("std").mem.zeroes(c_long), +// }; +// pub const NAMED = struct_NAMED; +// pub const struct_ONENAMEWITHSTRUCT = extern struct { +// unnamed_0: struct_NAMED = = @import("std").mem.zeroes(struct_NAMED), +// b: c_long = @import("std").mem.zeroes(c_long), +// }; diff --git a/test/cases/translate/nameless_struct_fields_linux.c b/test/cases/translate/nameless_struct_fields_linux.c new file mode 100644 index 0000000..aa57292 --- /dev/null +++ b/test/cases/translate/nameless_struct_fields_linux.c @@ -0,0 +1,22 @@ +typedef struct NAMED +{ + long name; +} NAMED; + +typedef struct ONENAMEWITHSTRUCT +{ + NAMED; + long b; +} ONENAMEWITHSTRUCT; + +// translate +// expect=fail +// target=native-linux +// +// pub const struct_NAMED = extern struct { +// name: c_long = @import("std").mem.zeroes(c_long), +// }; +// pub const NAMED = struct_NAMED; +// pub const struct_ONENAMEWITHSTRUCT = extern struct { +// b: c_long = @import("std").mem.zeroes(c_long), +// }; diff --git a/test/cases/translate/nested_assignment.c b/test/cases/translate/nested_assignment.c new file mode 100644 index 0000000..a9bd0e1 --- /dev/null +++ b/test/cases/translate/nested_assignment.c @@ -0,0 +1,23 @@ +int foo(int *p, int x) { + return *p++ = x; +} + +// translate +// expect=fail +// +// pub export fn foo(arg_p: [*c]c_int, arg_x: c_int) c_int { +// var p = arg_p; +// _ = &p; +// var x = arg_x; +// _ = &x; +// return blk: { +// const tmp = x; +// (blk_1: { +// const ref = &p; +// const tmp_2 = ref.*; +// ref.* += 1; +// break :blk_1 tmp_2; +// }).* = tmp; +// break :blk tmp; +// }; +// } diff --git a/test/cases/translate/nested_loops_without_blocks.c b/test/cases/translate/nested_loops_without_blocks.c new file mode 100644 index 0000000..2d6c386 --- /dev/null +++ b/test/cases/translate/nested_loops_without_blocks.c @@ -0,0 +1,16 @@ +void foo() { + while (0) while (0) {} + for (;;) while (0); + for (;;) do {} while (0); +} + +// translate +// expect=fail +// +// pub export fn foo() void { +// while (false) while (false) {}; +// while (true) while (false) {}; +// while (true) while (true) { +// if (!false) break; +// }; +// } diff --git a/test/cases/translate/normal_deref.c b/test/cases/translate/normal_deref.c new file mode 100644 index 0000000..abf288d --- /dev/null +++ b/test/cases/translate/normal_deref.c @@ -0,0 +1,13 @@ +void foo() { + int *x; + *x = 1; +} + +// translate +// expect=fail +// +// pub export fn foo() void { +// var x: [*c]c_int = undefined; +// _ = &x; +// x.* = 1; +// } diff --git a/test/cases/translate/null_pointer_implicit_cast.c b/test/cases/translate/null_pointer_implicit_cast.c new file mode 100644 index 0000000..59ed949 --- /dev/null +++ b/test/cases/translate/null_pointer_implicit_cast.c @@ -0,0 +1,10 @@ +int* foo(void) { + return 0; +} + +// translate +// expect=fail +// +// pub export fn foo() [*c]c_int { +// return null; +// } diff --git a/test/cases/translate/null_sentinel_arrays_when_initialized_from_string_literal.c b/test/cases/translate/null_sentinel_arrays_when_initialized_from_string_literal.c new file mode 100644 index 0000000..123822a --- /dev/null +++ b/test/cases/translate/null_sentinel_arrays_when_initialized_from_string_literal.c @@ -0,0 +1,45 @@ +#include +char zero[0] = "abc"; +uint32_t zero_w[0] = U"💯💯💯"; +char empty_incomplete[] = ""; +uint32_t empty_incomplete_w[] = U""; +char empty_constant[100] = ""; +uint32_t empty_constant_w[100] = U""; +char incomplete[] = "abc"; +uint32_t incomplete_w[] = U"💯💯💯"; +char truncated[1] = "abc"; +uint32_t truncated_w[1] = U"💯💯💯"; +char extend[5] = "a"; +uint32_t extend_w[5] = U"💯"; +char no_null[3] = "abc"; +uint32_t no_null_w[3] = U"💯💯💯"; + +// translate +// expect=fail +// +// pub export var zero: [0]u8 = [0]u8{}; +// pub export var zero_w: [0]u32 = [0]u32{}; +// pub export var empty_incomplete: [1]u8 = [1]u8{0} ** 1; +// pub export var empty_incomplete_w: [1]u32 = [1]u32{0} ** 1; +// pub export var empty_constant: [100]u8 = [1]u8{0} ** 100; +// pub export var empty_constant_w: [100]u32 = [1]u32{0} ** 100; +// pub export var incomplete: [3:0]u8 = "abc".*; +// pub export var incomplete_w: [3:0]u32 = [3:0]u32{ +// '\u{1f4af}', +// '\u{1f4af}', +// '\u{1f4af}', +// }; +// pub export var truncated: [1]u8 = "abc"[0..1].*; +// pub export var truncated_w: [1]u32 = [1]u32{ +// '\u{1f4af}', +// }; +// pub export var extend: [5]u8 = "a"[0..1].* ++ [1]u8{0} ** 4; +// pub export var extend_w: [5]u32 = [1]u32{ +// '\u{1f4af}', +// } ++ [1]u32{0} ** 4; +// pub export var no_null: [3]u8 = "abc".*; +// pub export var no_null_w: [3]u32 = [3]u32{ +// '\u{1f4af}', +// '\u{1f4af}', +// '\u{1f4af}', +// }; diff --git a/test/cases/translate/null_statements.c b/test/cases/translate/null_statements.c new file mode 100644 index 0000000..747fd75 --- /dev/null +++ b/test/cases/translate/null_statements.c @@ -0,0 +1,8 @@ +void foo(void) { + ;;;;; +} + +// translate +// expect=fail +// +// pub export fn foo() void {} diff --git a/test/cases/translate/pointer_casting.c b/test/cases/translate/pointer_casting.c new file mode 100644 index 0000000..36bc367 --- /dev/null +++ b/test/cases/translate/pointer_casting.c @@ -0,0 +1,13 @@ +float *ptrcast() { + int *a; + return (float *)a; +} + +// translate +// expect=fail +// +// pub export fn ptrcast() [*c]f32 { +// var a: [*c]c_int = undefined; +// _ = &a; +// return @as([*c]f32, @ptrCast(@alignCast(a))); +// } diff --git a/test/cases/translate/pointer_conversion_with_different_alignment.c b/test/cases/translate/pointer_conversion_with_different_alignment.c new file mode 100644 index 0000000..7603c78 --- /dev/null +++ b/test/cases/translate/pointer_conversion_with_different_alignment.c @@ -0,0 +1,43 @@ +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; + } +} + +// translate +// expect=fail +// +// pub export fn test_ptr_cast() void { +// var p: ?*anyopaque = undefined; +// _ = &p; +// { +// var to_char: [*c]u8 = @as([*c]u8, @ptrCast(@alignCast(p))); +// _ = &to_char; +// var to_short: [*c]c_short = @as([*c]c_short, @ptrCast(@alignCast(p))); +// _ = &to_short; +// var to_int: [*c]c_int = @as([*c]c_int, @ptrCast(@alignCast(p))); +// _ = &to_int; +// var to_longlong: [*c]c_longlong = @as([*c]c_longlong, @ptrCast(@alignCast(p))); +// _ = &to_longlong; +// } +// { +// var to_char: [*c]u8 = @as([*c]u8, @ptrCast(@alignCast(p))); +// _ = &to_char; +// var to_short: [*c]c_short = @as([*c]c_short, @ptrCast(@alignCast(p))); +// _ = &to_short; +// var to_int: [*c]c_int = @as([*c]c_int, @ptrCast(@alignCast(p))); +// _ = &to_int; +// var to_longlong: [*c]c_longlong = @as([*c]c_longlong, @ptrCast(@alignCast(p))); +// _ = &to_longlong; +// } +// } diff --git a/test/cases/translate/pointer_to_opaque_demoted_struct.c b/test/cases/translate/pointer_to_opaque_demoted_struct.c new file mode 100644 index 0000000..2aeda35 --- /dev/null +++ b/test/cases/translate/pointer_to_opaque_demoted_struct.c @@ -0,0 +1,16 @@ +typedef struct { + _Atomic int foo; +} Foo; + +typedef struct { + Foo *bar; +} Bar; + +// translate +// expect=fail +// +// source.h:1:9: warning: struct demoted to opaque type - unable to translate type of field foo +// pub const Foo = opaque {}; +// pub const Bar = extern struct { +// bar: ?*Foo = @import("std").mem.zeroes(?*Foo), +// }; diff --git a/test/cases/translate/post_increment.c b/test/cases/translate/post_increment.c new file mode 100644 index 0000000..9d4ce63 --- /dev/null +++ b/test/cases/translate/post_increment.c @@ -0,0 +1,34 @@ +unsigned foo1(unsigned a) { + a++; + return a; +} +int foo2(int a) { + a++; + return a; +} +int *foo3(int *a) { + a++; + return a; +} + +// translate +// expect=fail +// +// pub export fn foo1(arg_a: c_uint) c_uint { +// var a = arg_a; +// _ = &a; +// a +%= 1; +// return a; +// } +// pub export fn foo2(arg_a: c_int) c_int { +// var a = arg_a; +// _ = &a; +// a += 1; +// return a; +// } +// pub export fn foo3(arg_a: [*c]c_int) [*c]c_int { +// var a = arg_a; +// _ = &a; +// a += 1; +// return a; +// } diff --git a/test/cases/translate/post_increment_and_decrement.c b/test/cases/translate/post_increment_and_decrement.c new file mode 100644 index 0000000..d146ef0 --- /dev/null +++ b/test/cases/translate/post_increment_and_decrement.c @@ -0,0 +1,50 @@ +void foo(void) { + int i = 0; + unsigned u = 0; + i++; + i--; + u++; + u--; + i = i++; + i = i--; + u = u++; + u = u--; +} + +// translate +// expect=fail +// +// pub export fn foo() void { +// var i: c_int = 0; +// _ = &i; +// var u: c_uint = 0; +// _ = &u; +// i += 1; +// i -= 1; +// u +%= 1; +// u -%= 1; +// i = blk: { +// const ref = &i; +// const tmp = ref.*; +// ref.* += 1; +// break :blk tmp; +// }; +// i = blk: { +// const ref = &i; +// const tmp = ref.*; +// ref.* -= 1; +// break :blk tmp; +// }; +// u = blk: { +// const ref = &u; +// const tmp = ref.*; +// ref.* +%= 1; +// break :blk tmp; +// }; +// u = blk: { +// const ref = &u; +// const tmp = ref.*; +// ref.* -%= 1; +// break :blk tmp; +// }; +// } diff --git a/test/cases/translate/pre_increment_and_decrement.c b/test/cases/translate/pre_increment_and_decrement.c new file mode 100644 index 0000000..57513b3 --- /dev/null +++ b/test/cases/translate/pre_increment_and_decrement.c @@ -0,0 +1,46 @@ +void foo(void) { + int i = 0; + unsigned u = 0; + ++i; + --i; + ++u; + --u; + i = ++i; + i = --i; + u = ++u; + u = --u; +} + +// translate +// expect=fail +// +// pub export fn foo() void { +// var i: c_int = 0; +// _ = &i; +// var u: c_uint = 0; +// _ = &u; +// i += 1; +// i -= 1; +// u +%= 1; +// u -%= 1; +// i = blk: { +// const ref = &i; +// ref.* += 1; +// break :blk ref.*; +// }; +// i = blk: { +// const ref = &i; +// ref.* -= 1; +// break :blk ref.*; +// }; +// u = blk: { +// const ref = &u; +// ref.* +%= 1; +// break :blk ref.*; +// }; +// u = blk: { +// const ref = &u; +// ref.* -%= 1; +// break :blk ref.*; +// }; +// } diff --git a/test/cases/translate/predefined_expressions.c b/test/cases/translate/predefined_expressions.c new file mode 100644 index 0000000..3ba6884 --- /dev/null +++ b/test/cases/translate/predefined_expressions.c @@ -0,0 +1,14 @@ +void foo(void) { + __func__; + __FUNCTION__; + __PRETTY_FUNCTION__; +} + +// translate +// expect=fail +// +// pub export fn foo() void { +// _ = "foo"; +// _ = "foo"; +// _ = "void foo(void)"; +// } diff --git a/test/cases/translate/restrict_to_noalias.c b/test/cases/translate/restrict_to_noalias.c new file mode 100644 index 0000000..100425f --- /dev/null +++ b/test/cases/translate/restrict_to_noalias.c @@ -0,0 +1,6 @@ +void foo(void *restrict bar, void *restrict); + +// translate +// expect=fail +// +// pub extern fn foo(noalias bar: ?*anyopaque, noalias ?*anyopaque) void; diff --git a/test/cases/translate/return_void.c b/test/cases/translate/return_void.c new file mode 100644 index 0000000..43940c8 --- /dev/null +++ b/test/cases/translate/return_void.c @@ -0,0 +1,10 @@ +void foo(void) { + return; +} + +// translate +// expect=fail +// +// pub export fn foo() void { +// return; +// } diff --git a/test/cases/translate/scoped_typedef.c b/test/cases/translate/scoped_typedef.c new file mode 100644 index 0000000..e8e1169 --- /dev/null +++ b/test/cases/translate/scoped_typedef.c @@ -0,0 +1,48 @@ +void foo() { + typedef union { + int A; + int B; + int C; + } Foo; + Foo a = {0}; + { + typedef union { + int A; + int B; + int C; + } Foo; + Foo a = {0}; + } +} + +// translate +// expect=fail +// +// pub export fn foo() void { +// const union_unnamed_1 = extern union { +// A: c_int, +// B: c_int, +// C: c_int, +// }; +// _ = &union_unnamed_1; +// const Foo = union_unnamed_1; +// _ = &Foo; +// var a: Foo = Foo{ +// .A = @as(c_int, 0), +// }; +// _ = &a; +// { +// const union_unnamed_2 = extern union { +// A: c_int, +// B: c_int, +// C: c_int, +// }; +// _ = &union_unnamed_2; +// const Foo_1 = union_unnamed_2; +// _ = &Foo_1; +// var a_2: Foo_1 = Foo_1{ +// .A = @as(c_int, 0), +// }; +// _ = &a_2; +// } +// } diff --git a/test/cases/translate/self_referential_struct_with_function_pointer.c b/test/cases/translate/self_referential_struct_with_function_pointer.c new file mode 100644 index 0000000..0389d3a --- /dev/null +++ b/test/cases/translate/self_referential_struct_with_function_pointer.c @@ -0,0 +1,12 @@ +struct Foo { + void (*derp)(struct Foo *foo); +}; + +// translate +// expect=fail +// +// pub const struct_Foo = extern struct { +// derp: ?*const fn ([*c]struct_Foo) callconv(.c) void = @import("std").mem.zeroes(?*const fn ([*c]struct_Foo) callconv(.c) void), +// }; +// +// pub const Foo = struct_Foo; diff --git a/test/cases/translate/shadowing_primitive_types.c b/test/cases/translate/shadowing_primitive_types.c new file mode 100644 index 0000000..76bd2e0 --- /dev/null +++ b/test/cases/translate/shadowing_primitive_types.c @@ -0,0 +1,17 @@ +unsigned anyerror = 2; +#define noreturn _Noreturn +typedef enum { + f32, + u32, +} BadEnum; + +// translate +// expect=fail +// +// pub export var @"anyerror": c_uint = 2; +// +// pub const @"noreturn" = @compileError("unable to translate C expr: unexpected token '_Noreturn'"); +// +// pub const @"f32": c_int = 0; +// pub const @"u32": c_int = 1; +// pub const BadEnum = c_uint; diff --git a/test/cases/translate/shift_right_assign.c b/test/cases/translate/shift_right_assign.c new file mode 100644 index 0000000..829c3e0 --- /dev/null +++ b/test/cases/translate/shift_right_assign.c @@ -0,0 +1,21 @@ +int log2(unsigned a) { + int i = 0; + while (a > 0) { + a >>= 1; + } + return i; +} + +// translate +// expect=fail +// +// pub export fn log2(arg_a: c_uint) c_int { +// var a = arg_a; +// _ = &a; +// var i: c_int = 0; +// _ = &i; +// while (a > @as(c_uint, @bitCast(@as(c_int, 0)))) { +// a >>= @intCast(@as(c_int, 1)); +// } +// return i; +// } diff --git a/test/cases/translate/shift_right_assign_with_a_fixed_size_type.c b/test/cases/translate/shift_right_assign_with_a_fixed_size_type.c new file mode 100644 index 0000000..634b1b6 --- /dev/null +++ b/test/cases/translate/shift_right_assign_with_a_fixed_size_type.c @@ -0,0 +1,22 @@ +#include +int log2(uint32_t a) { + int i = 0; + while (a > 0) { + a >>= 1; + } + return i; +} + +// translate +// expect=fail +// +// pub export fn log2(arg_a: u32) c_int { +// var a = arg_a; +// _ = &a; +// var i: c_int = 0; +// _ = &i; +// while (a > @as(u32, @bitCast(@as(c_int, 0)))) { +// a >>= @intCast(@as(c_int, 1)); +// } +// return i; +// } diff --git a/test/cases/translate/simple_data_types.c b/test/cases/translate/simple_data_types.c new file mode 100644 index 0000000..709c810 --- /dev/null +++ b/test/cases/translate/simple_data_types.c @@ -0,0 +1,12 @@ +#include +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); + +// translate +// expect=fail +// +// 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; diff --git a/test/cases/translate/simple_function.c b/test/cases/translate/simple_function.c new file mode 100644 index 0000000..d70193c --- /dev/null +++ b/test/cases/translate/simple_function.c @@ -0,0 +1,12 @@ +int abs(int a) { + return a < 0 ? -a : a; +} + +// translate +// expect=fail +// +// pub export fn abs(arg_a: c_int) c_int { +// var a = arg_a; +// _ = &a; +// return if (a < @as(c_int, 0)) -a else a; +// } diff --git a/test/cases/translate/simple_function_definition.c b/test/cases/translate/simple_function_definition.c new file mode 100644 index 0000000..b109380 --- /dev/null +++ b/test/cases/translate/simple_function_definition.c @@ -0,0 +1,8 @@ +void foo(void) {} +static void bar(void) {} + +// translate +// expect=fail +// +// pub export fn foo() void {} +// pub fn bar() callconv(.c) void {} diff --git a/test/cases/translate/simple_if_statement.c b/test/cases/translate/simple_if_statement.c new file mode 100644 index 0000000..5be214f --- /dev/null +++ b/test/cases/translate/simple_if_statement.c @@ -0,0 +1,25 @@ +int max(int a, int b) { + if (a < b) + return b; + + if (a < b) + return b; + else + return a; + + if (a < b) ; else ; +} + +// translate +// expect=fail +// +// pub export fn max(arg_a: c_int, arg_b: c_int) c_int { +// var a = arg_a; +// _ = &a; +// var b = arg_b; +// _ = &b; +// if (a < b) return b; +// if (a < b) return b else return a; +// if (a < b) {} else {} +// return 0; +// } diff --git a/test/cases/translate/simple_ptrCast_for_casts_between_opaque_types.c b/test/cases/translate/simple_ptrCast_for_casts_between_opaque_types.c new file mode 100644 index 0000000..9c4df5c --- /dev/null +++ b/test/cases/translate/simple_ptrCast_for_casts_between_opaque_types.c @@ -0,0 +1,17 @@ +struct opaque; +struct opaque_2; +void function(struct opaque *opaque) { + struct opaque_2 *cast = (struct opaque_2 *)opaque; +} + +// translate +// expect=fail +// +// pub const struct_opaque = opaque {}; +// pub const struct_opaque_2 = opaque {}; +// pub export fn function(arg_opaque_1: ?*struct_opaque) void { +// var opaque_1 = arg_opaque_1; +// _ = &opaque_1; +// var cast: ?*struct_opaque_2 = @as(?*struct_opaque_2, @ptrCast(opaque_1)); +// _ = &cast; +// } diff --git a/test/cases/translate/simple_var_decls.c b/test/cases/translate/simple_var_decls.c new file mode 100644 index 0000000..9632e13 --- /dev/null +++ b/test/cases/translate/simple_var_decls.c @@ -0,0 +1,26 @@ +void foo(void) { + int a; + char b = 123; + const int c; + const unsigned d = 440; + int e = 10; + unsigned int f = 10u; +} + +// translate +// expect=fail +// +// pub export fn foo() void { +// var a: c_int = undefined; +// _ = &a; +// var b: u8 = 123; +// _ = &b; +// const c: c_int = undefined; +// _ = &c; +// const d: c_uint = @as(c_uint, @bitCast(@as(c_int, 440))); +// _ = &d; +// var e: c_int = 10; +// _ = &e; +// var f: c_uint = 10; +// _ = &f; +// } diff --git a/test/cases/translate/sizeof.c b/test/cases/translate/sizeof.c new file mode 100644 index 0000000..fd6e5e3 --- /dev/null +++ b/test/cases/translate/sizeof.c @@ -0,0 +1,11 @@ +#include +size_t size_of(void) { + return sizeof(int); +} + +// translate +// expect=fail +// +// pub export fn size_of() usize { +// return @sizeOf(c_int); +// } diff --git a/test/cases/translate/statement_expression.c b/test/cases/translate/statement_expression.c new file mode 100644 index 0000000..beabbe9 --- /dev/null +++ b/test/cases/translate/statement_expression.c @@ -0,0 +1,19 @@ +int foo(void) { + return ({ + int a = 1; + a; + a; + }); +} + +// translate +// expect=fail +// +// pub export fn foo() c_int { +// return blk: { +// var a: c_int = 1; +// _ = &a; +// _ = &a; +// break :blk a; +// }; +// } diff --git a/test/cases/translate/static_incomplete_array_inside_function.c b/test/cases/translate/static_incomplete_array_inside_function.c new file mode 100644 index 0000000..ea78eda --- /dev/null +++ b/test/cases/translate/static_incomplete_array_inside_function.c @@ -0,0 +1,13 @@ +void foo(void) { + static const char v2[] = "2.2.2"; +} + +// translate +// expect=fail +// +// pub export fn foo() void { +// const v2 = struct { +// const static: [5:0]u8 = "2.2.2".*; +// }; +// _ = &v2; +// } diff --git a/test/cases/translate/static_local_variable_zero-initialized_if_no_initializer.c b/test/cases/translate/static_local_variable_zero-initialized_if_no_initializer.c new file mode 100644 index 0000000..1df982f --- /dev/null +++ b/test/cases/translate/static_local_variable_zero-initialized_if_no_initializer.c @@ -0,0 +1,20 @@ +struct FOO {int x; int y;}; +int bar(void) { + static struct FOO foo; + return foo.x; +} + +// translate +// expect=fail +// +// pub const struct_FOO = extern struct { +// x: c_int = @import("std").mem.zeroes(c_int), +// y: c_int = @import("std").mem.zeroes(c_int), +// }; +// pub export fn bar() c_int { +// const foo = struct { +// var static: struct_FOO = @import("std").mem.zeroes(struct_FOO); +// }; +// _ = &foo; +// return foo.static.x; +// } diff --git a/test/cases/translate/static_variable_in_block_scope.c b/test/cases/translate/static_variable_in_block_scope.c new file mode 100644 index 0000000..b02f875 --- /dev/null +++ b/test/cases/translate/static_variable_in_block_scope.c @@ -0,0 +1,16 @@ +float bar; +int foo() { + _Thread_local static int bar = 2; +} + +// translate +// expect=fail +// +// pub export var bar: f32 = @import("std").mem.zeroes(f32); +// pub export fn foo() c_int { +// const bar_1 = struct { +// threadlocal var static: c_int = 2; +// }; +// _ = &bar_1; +// return 0; +// } diff --git a/test/cases/translate/string_array_initializer.c b/test/cases/translate/string_array_initializer.c new file mode 100644 index 0000000..bd6c300 --- /dev/null +++ b/test/cases/translate/string_array_initializer.c @@ -0,0 +1,6 @@ +static const char foo[] = {"bar"}; + +// translate +// expect=fail +// +// pub const foo: [3:0]u8 = "bar"; diff --git a/test/cases/translate/string_concatenation_in_macros-_three_strings.c b/test/cases/translate/string_concatenation_in_macros-_three_strings.c new file mode 100644 index 0000000..d45a483 --- /dev/null +++ b/test/cases/translate/string_concatenation_in_macros-_three_strings.c @@ -0,0 +1,6 @@ +#define FOO "a" "b" "c" + +// translate +// expect=fail +// +// pub const FOO = "a" ++ "b" ++ "c"; diff --git a/test/cases/translate/string_concatenation_in_macros-_two_defines.c b/test/cases/translate/string_concatenation_in_macros-_two_defines.c new file mode 100644 index 0000000..0a3bc19 --- /dev/null +++ b/test/cases/translate/string_concatenation_in_macros-_two_defines.c @@ -0,0 +1,12 @@ +#define FOO "hello" +#define BAZ " world" +#define BAR FOO BAZ + +// translate +// expect=fail +// +// pub const FOO = "hello"; +// +// pub const BAZ = " world"; +// +// pub const BAR = FOO ++ BAZ; diff --git a/test/cases/translate/string_concatenation_in_macros-_two_strings.c b/test/cases/translate/string_concatenation_in_macros-_two_strings.c new file mode 100644 index 0000000..94da444 --- /dev/null +++ b/test/cases/translate/string_concatenation_in_macros-_two_strings.c @@ -0,0 +1,9 @@ +#define FOO "a" "b" +#define BAR FOO "c" + +// translate +// expect=fail +// +// pub const FOO = "a" ++ "b"; +// +// pub const BAR = FOO ++ "c"; diff --git a/test/cases/translate/string_concatenation_in_macros.c b/test/cases/translate/string_concatenation_in_macros.c new file mode 100644 index 0000000..ab1e7da --- /dev/null +++ b/test/cases/translate/string_concatenation_in_macros.c @@ -0,0 +1,12 @@ +#define FOO "hello" +#define BAR FOO " world" +#define BAZ "oh, " FOO + +// translate +// expect=fail +// +// pub const FOO = "hello"; +// +// pub const BAR = FOO ++ " world"; +// +// pub const BAZ = "oh, " ++ FOO; diff --git a/test/cases/translate/string_literal.c b/test/cases/translate/string_literal.c new file mode 100644 index 0000000..2c84a07 --- /dev/null +++ b/test/cases/translate/string_literal.c @@ -0,0 +1,10 @@ +const char *foo(void) { + return "bar"; +} + +// translate +// expect=fail +// +// pub export fn foo() [*c]const u8 { +// return "bar"; +// } diff --git a/test/cases/translate/string_prefix.c b/test/cases/translate/string_prefix.c new file mode 100644 index 0000000..bf517f9 --- /dev/null +++ b/test/cases/translate/string_prefix.c @@ -0,0 +1,6 @@ +#define foo L"hello" + +// translate +// expect=fail +// +// pub const foo = "hello"; diff --git a/test/cases/translate/struct_initializer_-_packed.c b/test/cases/translate/struct_initializer_-_packed.c new file mode 100644 index 0000000..b7852d1 --- /dev/null +++ b/test/cases/translate/struct_initializer_-_packed.c @@ -0,0 +1,15 @@ +struct {int x,y,z;} __attribute__((packed)) s0 = {1, 2}; + +// translate +// expect=fail +// +// const struct_unnamed_1 = extern struct { +// x: c_int align(1) = @import("std").mem.zeroes(c_int), +// y: c_int align(1) = @import("std").mem.zeroes(c_int), +// z: c_int align(1) = @import("std").mem.zeroes(c_int), +// }; +// pub export var s0: struct_unnamed_1 = struct_unnamed_1{ +// .x = @as(c_int, 1), +// .y = @as(c_int, 2), +// .z = 0, +// }; diff --git a/test/cases/translate/struct_initializer_-_simple.c b/test/cases/translate/struct_initializer_-_simple.c new file mode 100644 index 0000000..97f464b --- /dev/null +++ b/test/cases/translate/struct_initializer_-_simple.c @@ -0,0 +1,49 @@ +typedef struct { int x; } foo; +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}; +foo s3 = { 123 }; + +// translate +// expect=fail +// +// pub const foo = extern struct { +// x: c_int = @import("std").mem.zeroes(c_int), +// }; +// const struct_unnamed_1 = extern struct { +// x: f64 = @import("std").mem.zeroes(f64), +// y: f64 = @import("std").mem.zeroes(f64), +// z: f64 = @import("std").mem.zeroes(f64), +// }; +// pub export var s0: struct_unnamed_1 = struct_unnamed_1{ +// .x = 1.2, +// .y = 1.3, +// .z = 0, +// }; +// const struct_unnamed_2 = extern struct { +// sec: c_int = @import("std").mem.zeroes(c_int), +// min: c_int = @import("std").mem.zeroes(c_int), +// hour: c_int = @import("std").mem.zeroes(c_int), +// day: c_int = @import("std").mem.zeroes(c_int), +// mon: c_int = @import("std").mem.zeroes(c_int), +// year: c_int = @import("std").mem.zeroes(c_int), +// }; +// pub export var s1: struct_unnamed_2 = struct_unnamed_2{ +// .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), +// }; +// const struct_unnamed_3 = extern struct { +// x: c_int = @import("std").mem.zeroes(c_int), +// y: c_int = @import("std").mem.zeroes(c_int), +// }; +// pub export var s2: struct_unnamed_3 = struct_unnamed_3{ +// .x = @as(c_int, 1), +// .y = @as(c_int, 2), +// }; +// pub export var s3: foo = foo{ +// .x = @as(c_int, 123), +// }; diff --git a/test/cases/translate/struct_with_atomic_field.c b/test/cases/translate/struct_with_atomic_field.c new file mode 100644 index 0000000..161520a --- /dev/null +++ b/test/cases/translate/struct_with_atomic_field.c @@ -0,0 +1,15 @@ +struct arcan_shmif_cont { + struct arcan_shmif_page* addr; +}; +struct arcan_shmif_page { + volatile _Atomic int abufused[12]; +}; + +// translate +// expect=fail +// +// source.h:4:8: warning: struct demoted to opaque type - unable to translate type of field abufused +// pub const struct_arcan_shmif_page = opaque {}; +// pub const struct_arcan_shmif_cont = extern struct { +// addr: ?*struct_arcan_shmif_page = @import("std").mem.zeroes(?*struct_arcan_shmif_page), +// }; diff --git a/test/cases/translate/struct_with_flexible_array.c b/test/cases/translate/struct_with_flexible_array.c new file mode 100644 index 0000000..ccb28e8 --- /dev/null +++ b/test/cases/translate/struct_with_flexible_array.c @@ -0,0 +1,22 @@ +struct foo { int x; int y[]; }; +struct bar { int x; int y[0]; }; + +// translate +// expect=fail +// +// pub const struct_foo = extern struct { +// x: c_int align(4) = @import("std").mem.zeroes(c_int), +// pub fn y(self: anytype) @import("std").zig.c_translation.FlexibleArrayType(@TypeOf(self), c_int) { +// const Intermediate = @import("std").zig.c_translation.FlexibleArrayType(@TypeOf(self), u8); +// const ReturnType = @import("std").zig.c_translation.FlexibleArrayType(@TypeOf(self), c_int); +// return @as(ReturnType, @ptrCast(@alignCast(@as(Intermediate, @ptrCast(self)) + 4))); +// } +// }; +// pub const struct_bar = extern struct { +// x: c_int align(4) = @import("std").mem.zeroes(c_int), +// pub fn y(self: anytype) @import("std").zig.c_translation.FlexibleArrayType(@TypeOf(self), c_int) { +// const Intermediate = @import("std").zig.c_translation.FlexibleArrayType(@TypeOf(self), u8); +// const ReturnType = @import("std").zig.c_translation.FlexibleArrayType(@TypeOf(self), c_int); +// return @as(ReturnType, @ptrCast(@alignCast(@as(Intermediate, @ptrCast(self)) + 4))); +// } +// }; diff --git a/test/cases/translate/switch_on_int.c b/test/cases/translate/switch_on_int.c new file mode 100644 index 0000000..412b04a --- /dev/null +++ b/test/cases/translate/switch_on_int.c @@ -0,0 +1,84 @@ +void switch_fn(int i) { + int res = 0; + switch (i) { + case 0: + res = 1; + case 1 ... 3: + res = 2; + default: + res = 3 * i; + break; + break; + case 7: { + res = 7; + break; + } + case 4: + case 5: + res = 69; + { + res = 5; + return; + } + case 6: + switch (res) { + case 9: break; + } + res = 1; + return; + } +} + +// translate +// expect=fail +// +// pub export fn switch_fn(arg_i: c_int) void { +// var i = arg_i; +// _ = &i; +// var res: c_int = 0; +// _ = &res; +// while (true) { +// switch (i) { +// @as(c_int, 0) => { +// res = 1; +// res = 2; +// res = @as(c_int, 3) * i; +// break; +// }, +// @as(c_int, 1)...@as(c_int, 3) => { +// res = 2; +// res = @as(c_int, 3) * i; +// break; +// }, +// else => { +// res = @as(c_int, 3) * i; +// break; +// }, +// @as(c_int, 7) => { +// { +// res = 7; +// break; +// } +// }, +// @as(c_int, 4), @as(c_int, 5) => { +// res = 69; +// { +// res = 5; +// return; +// } +// }, +// @as(c_int, 6) => { +// while (true) { +// switch (res) { +// @as(c_int, 9) => break, +// else => {}, +// } +// break; +// } +// res = 1; +// return; +// }, +// } +// break; +// } +// } diff --git a/test/cases/translate/typedef_of_function_in_struct_field.c b/test/cases/translate/typedef_of_function_in_struct_field.c new file mode 100644 index 0000000..ba82648 --- /dev/null +++ b/test/cases/translate/typedef_of_function_in_struct_field.c @@ -0,0 +1,14 @@ +typedef void lws_callback_function(void); +struct Foo { + void (*func)(void); + lws_callback_function *callback_http; +}; + +// translate +// expect=fail +// +// pub const lws_callback_function = fn () callconv(.c) void; +// pub const struct_Foo = extern struct { +// func: ?*const fn () callconv(.c) void = @import("std").mem.zeroes(?*const fn () callconv(.c) void), +// callback_http: ?*const lws_callback_function = @import("std").mem.zeroes(?*const lws_callback_function), +// }; diff --git a/test/cases/translate/typedef_void.c b/test/cases/translate/typedef_void.c new file mode 100644 index 0000000..2729dc8 --- /dev/null +++ b/test/cases/translate/typedef_void.c @@ -0,0 +1,9 @@ +typedef void Foo; +Foo fun(Foo *a); + +// translate +// expect=fail +// +// pub const Foo = anyopaque; +// +// pub extern fn fun(a: ?*Foo) void; diff --git a/test/cases/translate/typedeffed_bool_expression.c b/test/cases/translate/typedeffed_bool_expression.c new file mode 100644 index 0000000..6e7cf9d --- /dev/null +++ b/test/cases/translate/typedeffed_bool_expression.c @@ -0,0 +1,17 @@ +typedef char* yes; +void foo(void) { + yes a; + if (a) 2; +} + +// translate +// expect=fail +// +// pub const yes = [*c]u8; +// pub export fn foo() void { +// var a: yes = undefined; +// _ = &a; +// if (a != null) { +// _ = @as(c_int, 2); +// } +// } diff --git a/test/cases/translate/u_integer_suffix_after_0_(zero)_in_macro_definition.c b/test/cases/translate/u_integer_suffix_after_0_(zero)_in_macro_definition.c new file mode 100644 index 0000000..86191bb --- /dev/null +++ b/test/cases/translate/u_integer_suffix_after_0_(zero)_in_macro_definition.c @@ -0,0 +1,6 @@ +#define ZERO 0U + +// translate +// expect=fail +// +// pub const ZERO = @as(c_uint, 0); diff --git a/test/cases/translate/u_integer_suffix_after_hex_literal.c b/test/cases/translate/u_integer_suffix_after_hex_literal.c new file mode 100644 index 0000000..6c04428 --- /dev/null +++ b/test/cases/translate/u_integer_suffix_after_hex_literal.c @@ -0,0 +1,6 @@ +#define SDL_INIT_VIDEO 0x00000020u /**< SDL_INIT_VIDEO implies SDL_INIT_EVENTS */ + +// translate +// expect=fail +// +// pub const SDL_INIT_VIDEO = @as(c_uint, 0x00000020); diff --git a/test/cases/translate/ul_integer_suffix_after_0_(zero)_in_macro_definition.c b/test/cases/translate/ul_integer_suffix_after_0_(zero)_in_macro_definition.c new file mode 100644 index 0000000..0f76a9e --- /dev/null +++ b/test/cases/translate/ul_integer_suffix_after_0_(zero)_in_macro_definition.c @@ -0,0 +1,6 @@ +#define ZERO 0UL + +// translate +// expect=fail +// +// pub const ZERO = @as(c_ulong, 0); diff --git a/test/cases/translate/ul_integer_suffix_after_hex_literal.c b/test/cases/translate/ul_integer_suffix_after_hex_literal.c new file mode 100644 index 0000000..ed80245 --- /dev/null +++ b/test/cases/translate/ul_integer_suffix_after_hex_literal.c @@ -0,0 +1,6 @@ +#define SDL_INIT_VIDEO 0x00000020ul /**< SDL_INIT_VIDEO implies SDL_INIT_EVENTS */ + +// translate +// expect=fail +// +// pub const SDL_INIT_VIDEO = @as(c_ulong, 0x00000020); diff --git a/test/cases/translate/ull_integer_suffix_after_0_(zero)_in_macro_definition.c b/test/cases/translate/ull_integer_suffix_after_0_(zero)_in_macro_definition.c new file mode 100644 index 0000000..b13cad0 --- /dev/null +++ b/test/cases/translate/ull_integer_suffix_after_0_(zero)_in_macro_definition.c @@ -0,0 +1,6 @@ +#define ZERO 0ULL + +// translate +// expect=fail +// +// pub const ZERO = @as(c_ulonglong, 0); diff --git a/test/cases/translate/ull_integer_suffix_after_hex_literal.c b/test/cases/translate/ull_integer_suffix_after_hex_literal.c new file mode 100644 index 0000000..5050697 --- /dev/null +++ b/test/cases/translate/ull_integer_suffix_after_hex_literal.c @@ -0,0 +1,6 @@ +#define SDL_INIT_VIDEO 0x00000020ull /**< SDL_INIT_VIDEO implies SDL_INIT_EVENTS */ + +// translate +// expect=fail +// +// pub const SDL_INIT_VIDEO = @as(c_ulonglong, 0x00000020); diff --git a/test/cases/translate/undefined_array_global.c b/test/cases/translate/undefined_array_global.c new file mode 100644 index 0000000..da32b48 --- /dev/null +++ b/test/cases/translate/undefined_array_global.c @@ -0,0 +1,6 @@ +int array[100] = {}; + +// translate +// expect=fail +// +// pub export var array: [100]c_int = [1]c_int{0} ** 100; diff --git a/test/cases/translate/unnamed_child_types_of_typedef_receive_typedef's_name.c b/test/cases/translate/unnamed_child_types_of_typedef_receive_typedef's_name.c new file mode 100644 index 0000000..cc7a4b5 --- /dev/null +++ b/test/cases/translate/unnamed_child_types_of_typedef_receive_typedef's_name.c @@ -0,0 +1,18 @@ +typedef enum { + FooA, + FooB, +} Foo; +typedef struct { + int a, b; +} Bar; + +// translate +// expect=fail +// +// pub const FooA: c_int = 0; +// pub const FooB: c_int = 1; +// pub const Foo = c_uint; +// pub const Bar = extern struct { +// a: c_int = @import("std").mem.zeroes(c_int), +// b: c_int = @import("std").mem.zeroes(c_int), +// }; diff --git a/test/cases/translate/unsigned_array_index_skips_cast.c b/test/cases/translate/unsigned_array_index_skips_cast.c new file mode 100644 index 0000000..2e5fdb8 --- /dev/null +++ b/test/cases/translate/unsigned_array_index_skips_cast.c @@ -0,0 +1,15 @@ +void foo() { + unsigned int a[10], i = 0; + a[i] = 0; +} + +// translate +// expect=fail +// +// pub export fn foo() void { +// var a: [10]c_uint = undefined; +// _ = &a; +// var i: c_uint = 0; +// _ = &i; +// a[i] = 0; +// } diff --git a/test/cases/translate/unsupport_declare_statement_at_the_last_of_a_compound_statement_which_belongs_to_a_statement_expr.c b/test/cases/translate/unsupport_declare_statement_at_the_last_of_a_compound_statement_which_belongs_to_a_statement_expr.c new file mode 100644 index 0000000..f63cdd3 --- /dev/null +++ b/test/cases/translate/unsupport_declare_statement_at_the_last_of_a_compound_statement_which_belongs_to_a_statement_expr.c @@ -0,0 +1,15 @@ +void somefunc(void) { + int y; + (void)({y=1; _Static_assert(1);}); +} + +// translate +// expect=fail +// +// pub export fn somefunc() void { +// var y: c_int = undefined; +// _ = &y; +// _ = blk: { +// y = 1; +// }; +// } diff --git a/test/cases/translate/use_cast_param_as_macro_fn_return_type.c b/test/cases/translate/use_cast_param_as_macro_fn_return_type.c new file mode 100644 index 0000000..70be8e3 --- /dev/null +++ b/test/cases/translate/use_cast_param_as_macro_fn_return_type.c @@ -0,0 +1,11 @@ +#include +#define SYS_BASE_CACHED 0 +#define MEM_PHYSICAL_TO_K0(x) (void*)((uint32_t)(x) + SYS_BASE_CACHED) + +// translate +// expect=fail +// +// pub inline fn MEM_PHYSICAL_TO_K0(x: anytype) ?*anyopaque { +// _ = &x; +// return @import("std").zig.c_translation.cast(?*anyopaque, @import("std").zig.c_translation.cast(u32, x) + SYS_BASE_CACHED); +// } diff --git a/test/cases/translate/variable_aliasing.c b/test/cases/translate/variable_aliasing.c new file mode 100644 index 0000000..9336b80 --- /dev/null +++ b/test/cases/translate/variable_aliasing.c @@ -0,0 +1,34 @@ +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; +} + +// translate +// expect=fail +// +// pub var a: c_long = 2; +// pub var b: c_long = 2; +// pub var c: c_int = 4; +// pub export fn foo(arg_c_1: u8) void { +// var c_1 = arg_c_1; +// _ = &c_1; +// var a_2: c_int = undefined; +// _ = &a_2; +// var b_3: u8 = 123; +// _ = &b_3; +// b_3 = @as(u8, @bitCast(@as(i8, @truncate(a_2)))); +// { +// var d: c_int = 5; +// _ = &d; +// } +// var d: c_uint = @as(c_uint, @bitCast(@as(c_int, 440))); +// _ = &d; +// } diff --git a/test/cases/translate/variable_declarations.c b/test/cases/translate/variable_declarations.c new file mode 100644 index 0000000..8e27c69 --- /dev/null +++ b/test/cases/translate/variable_declarations.c @@ -0,0 +1,10 @@ +extern char arr0[] = "hello"; +static char arr1[] = "hello"; +char arr2[] = "hello"; + +// translate +// expect=fail +// +// pub export var arr0: [5:0]u8 = "hello".*; +// pub var arr1: [5:0]u8 = "hello".*; +// pub export var arr2: [5:0]u8 = "hello".*; diff --git a/test/cases/translate/variables.c b/test/cases/translate/variables.c new file mode 100644 index 0000000..377cefc --- /dev/null +++ b/test/cases/translate/variables.c @@ -0,0 +1,10 @@ +extern int extern_var; +static const int int_var = 13; +int foo; + +// translate +// expect=fail +// +// pub extern var extern_var: c_int; +// pub const int_var: c_int = 13; +// pub export var foo: c_int = @import("std").mem.zeroes(c_int); diff --git a/test/cases/translate/variables_check_for_opaque_demotion.c b/test/cases/translate/variables_check_for_opaque_demotion.c new file mode 100644 index 0000000..dfe3e3e --- /dev/null +++ b/test/cases/translate/variables_check_for_opaque_demotion.c @@ -0,0 +1,14 @@ +struct A { + _Atomic int a; +} a; +int main(void) { + struct A a; +} + +// translate +// expect=fail +// +// pub const struct_A = opaque {}; +// pub const a = @compileError("non-extern variable has opaque type"); +// +// pub extern fn main() c_int; diff --git a/test/cases/translate/variadic_function_demoted_to_extern.c b/test/cases/translate/variadic_function_demoted_to_extern.c new file mode 100644 index 0000000..0af65ed --- /dev/null +++ b/test/cases/translate/variadic_function_demoted_to_extern.c @@ -0,0 +1,9 @@ +int foo(int bar, ...) { + return 1; +} + +// translate +// expect=fail +// +// warning: TODO unable to translate variadic function, demoted to extern +// pub extern fn foo(bar: c_int, ...) c_int; diff --git a/test/cases/translate/void_cast.c b/test/cases/translate/void_cast.c new file mode 100644 index 0000000..d6eeb77 --- /dev/null +++ b/test/cases/translate/void_cast.c @@ -0,0 +1,13 @@ +void foo() { + int a; + (void) a; +} + +// translate +// expect=fail +// +// pub export fn foo() void { +// var a: c_int = undefined; +// _ = &a; +// _ = &a; +// } diff --git a/test/cases/translate/while_loops.c b/test/cases/translate/while_loops.c new file mode 100644 index 0000000..564648e --- /dev/null +++ b/test/cases/translate/while_loops.c @@ -0,0 +1,46 @@ +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); +} + +// translate +// expect=fail +// +// pub export fn foo() c_int { +// var a: c_int = 5; +// _ = &a; +// while (true) { +// a = 2; +// } +// while (true) { +// var a_1: c_int = 4; +// _ = &a_1; +// a_1 = 9; +// return blk: { +// _ = @as(c_int, 6); +// break :blk a_1; +// }; +// } +// while (true) { +// var a_1: c_int = 2; +// _ = &a_1; +// a_1 = 12; +// } +// while (true) { +// a = 7; +// } +// return 0; +// } diff --git a/test/cases/translate/while_on_non-bool.c b/test/cases/translate/while_on_non-bool.c new file mode 100644 index 0000000..be7edec --- /dev/null +++ b/test/cases/translate/while_on_non-bool.c @@ -0,0 +1,25 @@ +int while_none_bool() { + int a; + float b; + void *c; + while (a) return 0; + while (b) return 1; + while (c) return 2; + return 3; +} + +// translate +// expect=fail +// +// pub export fn while_none_bool() c_int { +// var a: c_int = undefined; +// _ = &a; +// var b: f32 = undefined; +// _ = &b; +// var c: ?*anyopaque = undefined; +// _ = &c; +// while (a != 0) return 0; +// while (b != 0) return 1; +// while (c != null) return 2; +// return 3; +// } diff --git a/test/cases/translate/widening_and_truncating_integer_casting_to_different_signedness.c b/test/cases/translate/widening_and_truncating_integer_casting_to_different_signedness.c new file mode 100644 index 0000000..a6612f0 --- /dev/null +++ b/test/cases/translate/widening_and_truncating_integer_casting_to_different_signedness.c @@ -0,0 +1,18 @@ +unsigned long foo(void) { + return -1; +} +unsigned short bar(long x) { + return x; +} + +// translate +// expect=fail +// +// pub export fn foo() c_ulong { +// return @as(c_ulong, @bitCast(@as(c_long, -@as(c_int, 1)))); +// } +// pub export fn bar(arg_x: c_long) c_ushort { +// var x = arg_x; +// _ = &x; +// return @as(c_ushort, @bitCast(@as(c_short, @truncate(x)))); +// } diff --git a/test/cases/translate/worst-case_assign.c b/test/cases/translate/worst-case_assign.c new file mode 100644 index 0000000..121e59c --- /dev/null +++ b/test/cases/translate/worst-case_assign.c @@ -0,0 +1,20 @@ +void foo() { + int a; + int b; + a = b = 2; +} + +// translate +// expect=fail +// +// pub export fn foo() void { +// var a: c_int = undefined; +// _ = &a; +// var b: c_int = undefined; +// _ = &b; +// a = blk: { +// const tmp = @as(c_int, 2); +// b = tmp; +// break :blk tmp; +// }; +// } diff --git a/test/cases/translate/worst-case_assign_from_mangle_prefix.c b/test/cases/translate/worst-case_assign_from_mangle_prefix.c new file mode 100644 index 0000000..7f75d1b --- /dev/null +++ b/test/cases/translate/worst-case_assign_from_mangle_prefix.c @@ -0,0 +1,19 @@ +void foo() { + int n, tmp = 1; + if (n = tmp) {} +} + +// translate +// expect=fail +// +// pub export fn foo() void { +// var n: c_int = undefined; +// _ = &n; +// var tmp: c_int = 1; +// _ = &tmp; +// if ((blk: { +// const tmp_1 = tmp; +// n = tmp_1; +// break :blk tmp_1; +// }) != 0) {} +// } diff --git a/test/cases/translate/worst-case_assign_to_mangle_prefix.c b/test/cases/translate/worst-case_assign_to_mangle_prefix.c new file mode 100644 index 0000000..86c63dc --- /dev/null +++ b/test/cases/translate/worst-case_assign_to_mangle_prefix.c @@ -0,0 +1,19 @@ +void foo() { + int tmp, n = 1; + if (tmp = n) {} +} + +// translate +// expect=fail +// +// pub export fn foo() void { +// var tmp: c_int = undefined; +// _ = &tmp; +// var n: c_int = 1; +// _ = &n; +// if ((blk: { +// const tmp_1 = n; +// tmp = tmp_1; +// break :blk tmp_1; +// }) != 0) {} +// } diff --git a/test/cases/translate/worst-case_compound_assign_from_mangle_prefix.c b/test/cases/translate/worst-case_compound_assign_from_mangle_prefix.c new file mode 100644 index 0000000..123ce3b --- /dev/null +++ b/test/cases/translate/worst-case_compound_assign_from_mangle_prefix.c @@ -0,0 +1,19 @@ +void foo() { + int n, ref = 1; + if (n += ref) {} +} + +// translate +// expect=fail +// +// pub export fn foo() void { +// var n: c_int = undefined; +// _ = &n; +// var ref: c_int = 1; +// _ = &ref; +// if ((blk: { +// const ref_1 = &n; +// ref_1.* += ref; +// break :blk ref_1.*; +// }) != 0) {} +// } diff --git a/test/cases/translate/worst-case_compound_assign_to_mangle_prefix.c b/test/cases/translate/worst-case_compound_assign_to_mangle_prefix.c new file mode 100644 index 0000000..5e3a74b --- /dev/null +++ b/test/cases/translate/worst-case_compound_assign_to_mangle_prefix.c @@ -0,0 +1,19 @@ +void foo() { + int ref, n = 1; + if (ref += n) {} +} + +// translate +// expect=fail +// +// pub export fn foo() void { +// var ref: c_int = undefined; +// _ = &ref; +// var n: c_int = 1; +// _ = &n; +// if ((blk: { +// const ref_1 = &ref; +// ref_1.* += n; +// break :blk ref_1.*; +// }) != 0) {} +// } diff --git a/test/cases/translate/worst-case_postcrement_mangle_prefix.c b/test/cases/translate/worst-case_postcrement_mangle_prefix.c new file mode 100644 index 0000000..dee164f --- /dev/null +++ b/test/cases/translate/worst-case_postcrement_mangle_prefix.c @@ -0,0 +1,24 @@ +void foo() { + int n, ref = 1; + if (n = ref++) {} +} + +// translate +// expect=fail +// +// pub export fn foo() void { +// var n: c_int = undefined; +// _ = &n; +// var ref: c_int = 1; +// _ = &ref; +// if ((blk: { +// const tmp = blk_1: { +// const ref_2 = &ref; +// const tmp_3 = ref_2.*; +// ref_2.* += 1; +// break :blk_1 tmp_3; +// }; +// n = tmp; +// break :blk tmp; +// }) != 0) {} +// } diff --git a/test/cases/translate/worst-case_precrement_mangle_prefix.c b/test/cases/translate/worst-case_precrement_mangle_prefix.c new file mode 100644 index 0000000..834baef --- /dev/null +++ b/test/cases/translate/worst-case_precrement_mangle_prefix.c @@ -0,0 +1,23 @@ +void foo() { + int n, ref = 1; + if (n = ++ref) {} +} + +// translate +// expect=fail +// +// pub export fn foo() void { +// var n: c_int = undefined; +// _ = &n; +// var ref: c_int = 1; +// _ = &ref; +// if ((blk: { +// const tmp = blk_1: { +// const ref_2 = &ref; +// ref_2.* += 1; +// break :blk_1 ref_2.*; +// }; +// n = tmp; +// break :blk tmp; +// }) != 0) {} +// }