1const std = @import("std");
2const tests = @import("tests.zig");
3const nl = std.cstr.line_sep;
4
5pub fn addCases(cases: *tests.RunTranslatedCContext) void {
6    cases.add("dereference address of",
7        \\#include <stdlib.h>
8        \\int main(void) {
9        \\    int i = 0;
10        \\    *&i = 42;
11        \\    if (i != 42) abort();
12        \\	  return 0;
13        \\}
14    , "");
15
16    cases.add("division of floating literals",
17        \\#define _NO_CRT_STDIO_INLINE 1
18        \\#include <stdio.h>
19        \\#define PI 3.14159265358979323846f
20        \\#define DEG2RAD (PI/180.0f)
21        \\int main(void) {
22        \\    printf("DEG2RAD is: %f\n", DEG2RAD);
23        \\    return 0;
24        \\}
25    , "DEG2RAD is: 0.017453" ++ nl);
26
27    cases.add("use global scope for record/enum/typedef type translation if needed",
28        \\void bar(void);
29        \\void baz(void);
30        \\struct foo { int x; };
31        \\void bar() {
32        \\	struct foo tmp;
33        \\}
34        \\
35        \\void baz() {
36        \\	struct foo tmp;
37        \\}
38        \\
39        \\int main(void) {
40        \\	bar();
41        \\	baz();
42        \\	return 0;
43        \\}
44    , "");
45
46    cases.add("failed macros are only declared once",
47        \\#define FOO =
48        \\#define FOO =
49        \\#define PtrToPtr64(p) ((void *POINTER_64) p)
50        \\#define STRUC_ALIGNED_STACK_COPY(t,s) ((CONST t *)(s))
51        \\#define bar = 0x
52        \\#define baz = 0b
53        \\int main(void) {}
54    , "");
55
56    cases.add("parenthesized string literal",
57        \\void foo(const char *s) {}
58        \\int main(void) {
59        \\	foo(("bar"));
60        \\}
61    , "");
62
63    cases.add("variable shadowing type type",
64        \\#include <stdlib.h>
65        \\int main() {
66        \\    int type = 1;
67        \\    if (type != 1) abort();
68        \\}
69    , "");
70
71    cases.add("assignment as expression",
72        \\#include <stdlib.h>
73        \\int main() {
74        \\    int a, b, c, d = 5;
75        \\    int e = a = b = c = d;
76        \\    if (e != 5) abort();
77        \\}
78    , "");
79
80    cases.add("static variable in block scope",
81        \\#include <stdlib.h>
82        \\int foo() {
83        \\    static int bar;
84        \\    bar += 1;
85        \\    return bar;
86        \\}
87        \\int main() {
88        \\    foo();
89        \\    foo();
90        \\    if (foo() != 3) abort();
91        \\}
92    , "");
93
94    cases.add("array initializer",
95        \\#include <stdlib.h>
96        \\int main(int argc, char **argv) {
97        \\    int a0[4] = {1};
98        \\    int a1[4] = {1,2,3,4};
99        \\    int s0 = 0, s1 = 0;
100        \\    for (int i = 0; i < 4; i++) {
101        \\        s0 += a0[i];
102        \\        s1 += a1[i];
103        \\    }
104        \\    if (s0 != 1) abort();
105        \\    if (s1 != 10) abort();
106        \\}
107    , "");
108
109    cases.add("forward declarations",
110        \\#include <stdlib.h>
111        \\int foo(int);
112        \\int foo(int x) { return x + 1; }
113        \\int main(int argc, char **argv) {
114        \\    if (foo(2) != 3) abort();
115        \\    return 0;
116        \\}
117    , "");
118
119    cases.add("typedef and function pointer",
120        \\#include <stdlib.h>
121        \\typedef struct _Foo Foo;
122        \\typedef int Ret;
123        \\typedef int Param;
124        \\struct _Foo { Ret (*func)(Param p); };
125        \\static Ret add1(Param p) {
126        \\    return p + 1;
127        \\}
128        \\int main(int argc, char **argv) {
129        \\    Foo strct = { .func = add1 };
130        \\    if (strct.func(16) != 17) abort();
131        \\    return 0;
132        \\}
133    , "");
134
135    cases.add("ternary operator",
136        \\#include <stdlib.h>
137        \\static int cnt = 0;
138        \\int foo() { cnt++; return 42; }
139        \\int main(int argc, char **argv) {
140        \\  short q = 3;
141        \\  signed char z0 = q?:1;
142        \\  if (z0 != 3) abort();
143        \\  int z1 = 3?:1;
144        \\  if (z1 != 3) abort();
145        \\  int z2 = foo()?:-1;
146        \\  if (z2 != 42) abort();
147        \\  if (cnt != 1) abort();
148        \\  return 0;
149        \\}
150    , "");
151
152    cases.add("switch case",
153        \\#include <stdlib.h>
154        \\int lottery(unsigned int x) {
155        \\    switch (x) {
156        \\        case 3: return 0;
157        \\        case -1: return 3;
158        \\        case 8 ... 10: return x;
159        \\        default: return -1;
160        \\    }
161        \\}
162        \\int main(int argc, char **argv) {
163        \\    if (lottery(2) != -1) abort();
164        \\    if (lottery(3) != 0) abort();
165        \\    if (lottery(-1) != 3) abort();
166        \\    if (lottery(9) != 9) abort();
167        \\    return 0;
168        \\}
169    , "");
170
171    cases.add("boolean values and expressions",
172        \\#include <stdlib.h>
173        \\static const _Bool false_val = 0;
174        \\static const _Bool true_val = 1;
175        \\void foo(int x, int y) {
176        \\    _Bool r = x < y;
177        \\    if (!r) abort();
178        \\    _Bool self = foo;
179        \\    if (self == false_val) abort();
180        \\    if (((r) ? 'a' : 'b') != 'a') abort();
181        \\}
182        \\int main(int argc, char **argv) {
183        \\    foo(2, 5);
184        \\    if (false_val == true_val) abort();
185        \\    return 0;
186        \\}
187    , "");
188
189    cases.add("hello world",
190        \\#define _NO_CRT_STDIO_INLINE 1
191        \\#include <stdio.h>
192        \\int main(int argc, char **argv) {
193        \\    printf("hello, world!\n");
194        \\    return 0;
195        \\}
196    , "hello, world!" ++ nl);
197
198    cases.add("anon struct init",
199        \\#include <stdlib.h>
200        \\struct {int a; int b;} x = {1, 2};
201        \\int main(int argc, char **argv) {
202        \\    x.a += 2;
203        \\    x.b += 1;
204        \\    if (x.a != 3) abort();
205        \\    if (x.b != 3) abort();
206        \\    return 0;
207        \\}
208    , "");
209
210    cases.add("casting away const and volatile",
211        \\void foo(int *a) {}
212        \\void bar(const int *a) {
213        \\    foo((int *)a);
214        \\}
215        \\void baz(volatile int *a) {
216        \\    foo((int *)a);
217        \\}
218        \\int main(int argc, char **argv) {
219        \\    int a = 0;
220        \\    bar((const int *)&a);
221        \\    baz((volatile int *)&a);
222        \\    return 0;
223        \\}
224    , "");
225
226    cases.add("anonymous struct & unions",
227        \\#include <stdlib.h>
228        \\#include <stdint.h>
229        \\static struct { struct { uint16_t x, y; }; } x = { 1 };
230        \\static struct { union { uint32_t x; uint8_t y; }; } y = { 0x55AA55AA };
231        \\int main(int argc, char **argv) {
232        \\    if (x.x != 1) abort();
233        \\    if (x.y != 0) abort();
234        \\    if (y.x != 0x55AA55AA) abort();
235        \\    if (y.y != 0xAA) abort();
236        \\    return 0;
237        \\}
238    , "");
239
240    cases.add("array to pointer decay",
241        \\#include <stdlib.h>
242        \\int main(int argc, char **argv) {
243        \\    char data[3] = {'a','b','c'};
244        \\    if (2[data] != data[2]) abort();
245        \\    if ("abc"[1] != data[1]) abort();
246        \\    char *as_ptr = data;
247        \\    if (2[as_ptr] != as_ptr[2]) abort();
248        \\    if ("abc"[1] != as_ptr[1]) abort();
249        \\    return 0;
250        \\}
251    , "");
252
253    cases.add("struct initializer - packed",
254        \\#define _NO_CRT_STDIO_INLINE 1
255        \\#include <stdint.h>
256        \\#include <stdlib.h>
257        \\struct s {uint8_t x,y;
258        \\          uint32_t z;} __attribute__((packed)) s0 = {1, 2};
259        \\int main() {
260        \\  /* sizeof nor offsetof currently supported */
261        \\  if (((intptr_t)&s0.z - (intptr_t)&s0.x) != 2) abort();
262        \\  return 0;
263        \\}
264    , "");
265
266    cases.add("cast signed array index to unsigned",
267        \\#include <stdlib.h>
268        \\int main(int argc, char **argv) {
269        \\  int a[10], i = 0;
270        \\  a[i] = 0;
271        \\  if (a[i] != 0) abort();
272        \\  return 0;
273        \\}
274    , "");
275
276    cases.add("cast long long array index to unsigned",
277        \\#include <stdlib.h>
278        \\int main(int argc, char **argv) {
279        \\  long long a[10], i = 0;
280        \\  a[i] = 0;
281        \\  if (a[i] != 0) abort();
282        \\  return 0;
283        \\}
284    , "");
285
286    cases.add("case boolean expression converted to int",
287        \\#include <stdlib.h>
288        \\int main(int argc, char **argv) {
289        \\  int value = 1 + 2 * 3 + 4 * 5 + 6 << 7 | 8 == 9;
290        \\  if (value != 4224) abort();
291        \\  return 0;
292        \\}
293    , "");
294
295    cases.add("case boolean expression on left converted to int",
296        \\#include <stdlib.h>
297        \\int main(int argc, char **argv) {
298        \\  int value = 8 == 9 | 1 + 2 * 3 + 4 * 5 + 6 << 7;
299        \\  if (value != 4224) abort();
300        \\  return 0;
301        \\}
302    , "");
303
304    cases.add("case boolean and operator+ converts bool to int",
305        \\#include <stdlib.h>
306        \\int main(int argc, char **argv) {
307        \\  int value = (8 == 9) + 3;
308        \\  int value2 = 3 + (8 == 9);
309        \\  if (value != value2) abort();
310        \\  return 0;
311        \\}
312    , "");
313
314    cases.add("case boolean and operator<",
315        \\#include <stdlib.h>
316        \\int main(int argc, char **argv) {
317        \\  int value = (8 == 9) < 3;
318        \\  if (value == 0) abort();
319        \\  return 0;
320        \\}
321    , "");
322
323    cases.add("case boolean and operator*",
324        \\#include <stdlib.h>
325        \\int main(int argc, char **argv) {
326        \\  int value = (8 == 9) * 3;
327        \\  int value2 = 3 * (9 == 9);
328        \\  if (value != 0) abort();
329        \\  if (value2 == 0) abort();
330        \\  return 0;
331        \\}
332    , "");
333
334    cases.add("scoped typedef",
335        \\int main(int argc, char **argv) {
336        \\  typedef int Foo;
337        \\  typedef Foo Bar;
338        \\  typedef void (*func)(int);
339        \\  typedef int uint32_t;
340        \\  uint32_t a;
341        \\  Foo i;
342        \\  Bar j;
343        \\  return 0;
344        \\}
345    , "");
346
347    cases.add("scoped for loops with shadowing",
348        \\#include <stdlib.h>
349        \\int main() {
350        \\    int count = 0;
351        \\    for (int x = 0; x < 2; x++)
352        \\        for (int x = 0; x < 2; x++)
353        \\            count++;
354        \\
355        \\    if (count != 4) abort();
356        \\    return 0;
357        \\}
358    , "");
359
360    cases.add("array value type casts properly",
361        \\#include <stdlib.h>
362        \\unsigned int choose[53][10];
363        \\static int hash_binary(int k)
364        \\{
365        \\    choose[0][k] = 3;
366        \\    int sum = 0;
367        \\    sum += choose[0][k];
368        \\    return sum;
369        \\}
370        \\
371        \\int main() {
372        \\    int s = hash_binary(4);
373        \\    if (s != 3) abort();
374        \\    return 0;
375        \\}
376    , "");
377
378    cases.add("array value type casts properly use +=",
379        \\#include <stdlib.h>
380        \\static int hash_binary(int k)
381        \\{
382        \\    unsigned int choose[1][1] = {{3}};
383        \\    int sum = -1;
384        \\    int prev = 0;
385        \\    prev = sum += choose[0][0];
386        \\    if (sum != 2) abort();
387        \\    return sum + prev;
388        \\}
389        \\
390        \\int main() {
391        \\    int x = hash_binary(4);
392        \\    if (x != 4) abort();
393        \\    return 0;
394        \\}
395    , "");
396
397    cases.add("ensure array casts outside +=",
398        \\#include <stdlib.h>
399        \\static int hash_binary(int k)
400        \\{
401        \\    unsigned int choose[3] = {1, 2, 3};
402        \\    int sum = -2;
403        \\    int prev = sum + choose[k];
404        \\    if (prev != 0) abort();
405        \\    return sum + prev;
406        \\}
407        \\
408        \\int main() {
409        \\    int x = hash_binary(1);
410        \\    if (x != -2) abort();
411        \\    return 0;
412        \\}
413    , "");
414
415    cases.add("array cast int to uint",
416        \\#include <stdlib.h>
417        \\static unsigned int hash_binary(int k)
418        \\{
419        \\    int choose[3] = {-1, -2, 3};
420        \\    unsigned int sum = 2;
421        \\    sum += choose[k];
422        \\    return sum;
423        \\}
424        \\
425        \\int main() {
426        \\    unsigned int x = hash_binary(1);
427        \\    if (x != 0) abort();
428        \\    return 0;
429        \\}
430    , "");
431
432    cases.add("assign enum to uint, no explicit cast",
433        \\#include <stdlib.h>
434        \\typedef enum {
435        \\    ENUM_0 = 0,
436        \\    ENUM_1 = 1,
437        \\} my_enum_t;
438        \\
439        \\int main() {
440        \\    my_enum_t val = ENUM_1;
441        \\    unsigned int x = val;
442        \\    if (x != 1) abort();
443        \\    return 0;
444        \\}
445    , "");
446
447    cases.add("assign enum to int",
448        \\#include <stdlib.h>
449        \\typedef enum {
450        \\    ENUM_0 = 0,
451        \\    ENUM_1 = 1,
452        \\} my_enum_t;
453        \\
454        \\int main() {
455        \\    my_enum_t val = ENUM_1;
456        \\    int x = val;
457        \\    if (x != 1) abort();
458        \\    return 0;
459        \\}
460    , "");
461
462    cases.add("cast enum to smaller uint",
463        \\#include <stdlib.h>
464        \\#include <stdint.h>
465        \\typedef enum {
466        \\    ENUM_0 = 0,
467        \\    ENUM_257 = 257,
468        \\} my_enum_t;
469        \\
470        \\int main() {
471        \\    my_enum_t val = ENUM_257;
472        \\    uint8_t x = (uint8_t)val;
473        \\    if (x != (uint8_t)257) abort();
474        \\    return 0;
475        \\}
476    , "");
477
478    cases.add("cast enum to smaller signed int",
479        \\#include <stdlib.h>
480        \\#include <stdint.h>
481        \\typedef enum {
482        \\    ENUM_0 = 0,
483        \\    ENUM_384 = 384,
484        \\} my_enum_t;
485        \\
486        \\int main() {
487        \\    my_enum_t val = ENUM_384;
488        \\    int8_t x = (int8_t)val;
489        \\    if (x != (int8_t)384) abort();
490        \\    return 0;
491        \\}
492    , "");
493
494    cases.add("cast negative enum to smaller signed int",
495        \\#include <stdlib.h>
496        \\#include <stdint.h>
497        \\typedef enum {
498        \\    ENUM_MINUS_1 = -1,
499        \\    ENUM_384 = 384,
500        \\} my_enum_t;
501        \\
502        \\int main() {
503        \\    my_enum_t val = ENUM_MINUS_1;
504        \\    int8_t x = (int8_t)val;
505        \\    if (x != -1) abort();
506        \\    return 0;
507        \\}
508    , "");
509
510    cases.add("cast negative enum to smaller unsigned int",
511        \\#include <stdlib.h>
512        \\#include <stdint.h>
513        \\typedef enum {
514        \\    ENUM_MINUS_1 = -1,
515        \\    ENUM_384 = 384,
516        \\} my_enum_t;
517        \\
518        \\int main() {
519        \\    my_enum_t val = ENUM_MINUS_1;
520        \\    uint8_t x = (uint8_t)val;
521        \\    if (x != (uint8_t)-1) abort();
522        \\    return 0;
523        \\}
524    , "");
525
526    cases.add("implicit enum cast in boolean expression",
527        \\#include <stdlib.h>
528        \\enum Foo {
529        \\    FooA,
530        \\    FooB,
531        \\    FooC,
532        \\};
533        \\int main() {
534        \\    int a = 0;
535        \\    float b = 0;
536        \\    void *c = 0;
537        \\    enum Foo d = FooA;
538        \\    if (a || d) abort();
539        \\    if (d && b) abort();
540        \\    if (c || d) abort();
541        \\    return 0;
542        \\}
543    , "");
544
545    cases.add("issue #6707 cast builtin call result to opaque struct pointer",
546        \\#include <stdlib.h>
547        \\struct foo* make_foo(void)
548        \\{
549        \\    return (struct foo*)__builtin_strlen("0123456789ABCDEF");
550        \\}
551        \\int main(void) {
552        \\    struct foo *foo_pointer = make_foo();
553        \\    if (foo_pointer != (struct foo*)16) abort();
554        \\    return 0;
555        \\}
556    , "");
557
558    cases.add("C built-ins",
559        \\#include <stdlib.h>
560        \\#include <limits.h>
561        \\#include <stdbool.h>
562        \\#define M_E    2.71828182845904523536
563        \\#define M_PI_2 1.57079632679489661923
564        \\bool check_clz(unsigned int pos) {
565        \\    return (__builtin_clz(1 << pos) == (8 * sizeof(unsigned int) - pos - 1));
566        \\}
567        \\int main(void) {
568        \\    if (__builtin_bswap16(0x0102) != 0x0201) abort();
569        \\    if (__builtin_bswap32(0x01020304) != 0x04030201) abort();
570        \\    if (__builtin_bswap64(0x0102030405060708) != 0x0807060504030201) abort();
571        \\
572        \\    if (__builtin_signbit(0.0) != 0) abort();
573        \\    if (__builtin_signbitf(0.0f) != 0) abort();
574        \\    if (__builtin_signbit(1.0) != 0) abort();
575        \\    if (__builtin_signbitf(1.0f) != 0) abort();
576        \\    if (__builtin_signbit(-1.0) != 1) abort();
577        \\    if (__builtin_signbitf(-1.0f) != 1) abort();
578        \\
579        \\    if (__builtin_popcount(0) != 0) abort();
580        \\    if (__builtin_popcount(0b1) != 1) abort();
581        \\    if (__builtin_popcount(0b11) != 2) abort();
582        \\    if (__builtin_popcount(0b1111) != 4) abort();
583        \\    if (__builtin_popcount(0b11111111) != 8) abort();
584        \\
585        \\    if (__builtin_ctz(0b1) != 0) abort();
586        \\    if (__builtin_ctz(0b10) != 1) abort();
587        \\    if (__builtin_ctz(0b100) != 2) abort();
588        \\    if (__builtin_ctz(0b10000) != 4) abort();
589        \\    if (__builtin_ctz(0b100000000) != 8) abort();
590        \\
591        \\    if (!check_clz(0)) abort();
592        \\    if (!check_clz(1)) abort();
593        \\    if (!check_clz(2)) abort();
594        \\    if (!check_clz(4)) abort();
595        \\    if (!check_clz(8)) abort();
596        \\
597        \\    if (__builtin_sqrt(__builtin_sqrt(__builtin_sqrt(256))) != 2.0) abort();
598        \\    if (__builtin_sqrt(__builtin_sqrt(__builtin_sqrt(256.0))) != 2.0) abort();
599        \\    if (__builtin_sqrt(__builtin_sqrt(__builtin_sqrt(256.0f))) != 2.0) abort();
600        \\    if (__builtin_sqrtf(__builtin_sqrtf(__builtin_sqrtf(256.0f))) != 2.0f) abort();
601        \\
602        \\    if (__builtin_sin(1.0) != -__builtin_sin(-1.0)) abort();
603        \\    if (__builtin_sinf(1.0f) != -__builtin_sinf(-1.0f)) abort();
604        \\    if (__builtin_sin(M_PI_2) != 1.0) abort();
605        \\    if (__builtin_sinf(M_PI_2) != 1.0f) abort();
606        \\
607        \\    if (__builtin_cos(1.0) != __builtin_cos(-1.0)) abort();
608        \\    if (__builtin_cosf(1.0f) != __builtin_cosf(-1.0f)) abort();
609        \\    if (__builtin_cos(0.0) != 1.0) abort();
610        \\    if (__builtin_cosf(0.0f) != 1.0f) abort();
611        \\
612        \\    if (__builtin_exp(0) != 1.0) abort();
613        \\    if (__builtin_fabs(__builtin_exp(1.0) - M_E) > 0.00000001) abort();
614        \\    if (__builtin_exp(0.0f) != 1.0f) abort();
615        \\
616        \\    if (__builtin_exp2(0) != 1.0) abort();
617        \\    if (__builtin_exp2(4.0) != 16.0) abort();
618        \\    if (__builtin_exp2f(0.0f) != 1.0f) abort();
619        \\    if (__builtin_exp2f(4.0f) != 16.0f) abort();
620        \\
621        \\    if (__builtin_log(M_E) != 1.0) abort();
622        \\    if (__builtin_log(1.0) != 0.0) abort();
623        \\    if (__builtin_logf(1.0f) != 0.0f) abort();
624        \\
625        \\    if (__builtin_log2(8.0) != 3.0) abort();
626        \\    if (__builtin_log2(1.0) != 0.0) abort();
627        \\    if (__builtin_log2f(8.0f) != 3.0f) abort();
628        \\    if (__builtin_log2f(1.0f) != 0.0f) abort();
629        \\
630        \\    if (__builtin_log10(1000.0) != 3.0) abort();
631        \\    if (__builtin_log10(1.0) != 0.0) abort();
632        \\    if (__builtin_log10f(1000.0f) != 3.0f) abort();
633        \\    if (__builtin_log10f(1.0f) != 0.0f) abort();
634        \\
635        \\    if (__builtin_fabs(-42.0f) != 42.0) abort();
636        \\    if (__builtin_fabs(-42.0) != 42.0) abort();
637        \\    if (__builtin_fabs(-42) != 42.0) abort();
638        \\    if (__builtin_fabsf(-42.0f) != 42.0f) abort();
639        \\
640        \\    if (__builtin_fabs(-42.0f) != 42.0) abort();
641        \\    if (__builtin_fabs(-42.0) != 42.0) abort();
642        \\    if (__builtin_fabs(-42) != 42.0) abort();
643        \\    if (__builtin_fabsf(-42.0f) != 42.0f) abort();
644        \\
645        \\    if (__builtin_abs(42) != 42) abort();
646        \\    if (__builtin_abs(-42) != 42) abort();
647        \\    if (__builtin_abs(INT_MIN) != INT_MIN) abort();
648        \\
649        \\    if (__builtin_floor(42.9) != 42.0) abort();
650        \\    if (__builtin_floor(-42.9) != -43.0) abort();
651        \\    if (__builtin_floorf(42.9f) != 42.0f) abort();
652        \\    if (__builtin_floorf(-42.9f) != -43.0f) abort();
653        \\
654        \\    if (__builtin_ceil(42.9) != 43.0) abort();
655        \\    if (__builtin_ceil(-42.9) != -42) abort();
656        \\    if (__builtin_ceilf(42.9f) != 43.0f) abort();
657        \\    if (__builtin_ceilf(-42.9f) != -42.0f) abort();
658        \\
659        \\    if (__builtin_trunc(42.9) != 42.0) abort();
660        \\    if (__builtin_truncf(42.9f) != 42.0f) abort();
661        \\    if (__builtin_trunc(-42.9) != -42.0) abort();
662        \\    if (__builtin_truncf(-42.9f) != -42.0f) abort();
663        \\
664        \\    if (__builtin_round(0.5) != 1.0) abort();
665        \\    if (__builtin_round(-0.5) != -1.0) abort();
666        \\    if (__builtin_roundf(0.5f) != 1.0f) abort();
667        \\    if (__builtin_roundf(-0.5f) != -1.0f) abort();
668        \\
669        \\    if (__builtin_strcmp("abc", "abc") != 0) abort();
670        \\    if (__builtin_strcmp("abc", "def") >= 0 ) abort();
671        \\    if (__builtin_strcmp("def", "abc") <= 0) abort();
672        \\
673        \\    if (__builtin_strlen("this is a string") != 16) abort();
674        \\
675        \\    char *s = malloc(6);
676        \\    __builtin_memcpy(s, "hello", 5);
677        \\    s[5] = '\0';
678        \\    if (__builtin_strlen(s) != 5) abort();
679        \\
680        \\    __builtin_memset(s, 42, __builtin_strlen(s));
681        \\    if (s[0] != 42 || s[1] != 42 || s[2] != 42 || s[3] != 42 || s[4] != 42) abort();
682        \\
683        \\    free(s);
684        \\
685        \\    return 0;
686        \\}
687    , "");
688
689    cases.add("function macro that uses builtin",
690        \\#include <stdlib.h>
691        \\#define FOO(x, y) (__builtin_popcount((x)) + __builtin_strlen((y)))
692        \\int main() {
693        \\    if (FOO(7, "hello!") != 9) abort();
694        \\    return 0;
695        \\}
696    , "");
697
698    cases.add("assign bool result to int or char",
699        \\#include <stdlib.h>
700        \\#include <stdbool.h>
701        \\bool foo() { return true; }
702        \\int main() {
703        \\    int x = foo();
704        \\    if (x != 1) abort();
705        \\    signed char c = foo();
706        \\    if (c != 1) abort();
707        \\    return 0;
708        \\}
709    , "");
710
711    cases.add("static K&R-style no prototype function declaration (empty parameter list)",
712        \\#include <stdlib.h>
713        \\static int foo() {
714        \\    return 42;
715        \\}
716        \\int main() {
717        \\    if (foo() != 42) abort();
718        \\    return 0;
719        \\}
720    , "");
721
722    cases.add("K&R-style static function prototype for unused function",
723        \\static int foo();
724        \\int main() {
725        \\    return 0;
726        \\}
727    , "");
728
729    cases.add("K&R-style static function prototype + separate definition",
730        \\#include <stdlib.h>
731        \\static int foo();
732        \\static int foo(int a, int b) {
733        \\    return a + b;
734        \\}
735        \\int main() {
736        \\    if (foo(40, 2) != 42) abort();
737        \\    return 0;
738        \\}
739    , "");
740
741    cases.add("dollar sign in identifiers",
742        \\#include <stdlib.h>
743        \\#define $FOO 2
744        \\#define $foo bar$
745        \\#define $baz($x) ($x + $FOO)
746        \\int $$$(int $x$) { return $x$ + $FOO; }
747        \\int main() {
748        \\    int bar$ = 42;
749        \\    if ($foo != 42) abort();
750        \\    if (bar$ != 42) abort();
751        \\    if ($baz(bar$) != 44) abort();
752        \\    if ($$$(bar$) != 44) abort();
753        \\    return 0;
754        \\}
755    , "");
756
757    cases.add("Cast boolean expression result to int",
758        \\#include <stdlib.h>
759        \\char foo(char c) { return c; }
760        \\int  bar(int i)  { return i; }
761        \\long baz(long l) { return l; }
762        \\int main() {
763        \\    if (foo(1 == 2)) abort();
764        \\    if (!foo(1 == 1)) abort();
765        \\    if (bar(1 == 2)) abort();
766        \\    if (!bar(1 == 1)) abort();
767        \\    if (baz(1 == 2)) abort();
768        \\    if (!baz(1 == 1)) abort();
769        \\    return 0;
770        \\}
771    , "");
772
773    cases.add("Wide, UTF-16, and UTF-32 character literals",
774        \\#include <wchar.h>
775        \\#include <stdlib.h>
776        \\int main() {
777        \\    wchar_t wc = L'™';
778        \\    int utf16_char = u'™';
779        \\    int utf32_char = U'��';
780        \\    if (wc != 8482) abort();
781        \\    if (utf16_char != 8482) abort();
782        \\    if (utf32_char != 128175) abort();
783        \\    unsigned char c = wc;
784        \\    if (c != 0x22) abort();
785        \\    c = utf32_char;
786        \\    if (c != 0xaf) abort();
787        \\    return 0;
788        \\}
789    , "");
790
791    cases.add("Variadic function call",
792        \\#define _NO_CRT_STDIO_INLINE 1
793        \\#include <stdio.h>
794        \\int main(void) {
795        \\    printf("%d %d\n", 1, 2);
796        \\    return 0;
797        \\}
798    , "1 2" ++ nl);
799
800    cases.add("multi-character character constant",
801        \\#include <stdlib.h>
802        \\int main(void) {
803        \\    int foo = 'abcd';
804        \\    switch (foo) {
805        \\        case 'abcd': break;
806        \\        default: abort();
807        \\    }
808        \\    return 0;
809        \\}
810    , "");
811
812    cases.add("Array initializers (string literals, incomplete arrays)",
813        \\#include <stdlib.h>
814        \\#include <string.h>
815        \\extern int foo[];
816        \\int global_arr[] = {1, 2, 3};
817        \\char global_string[] = "hello";
818        \\int main(int argc, char *argv[]) {
819        \\    if (global_arr[2] != 3) abort();
820        \\    if (strlen(global_string) != 5) abort();
821        \\    const char *const_str = "hello";
822        \\    if (strcmp(const_str, "hello") != 0) abort();
823        \\    char empty_str[] = "";
824        \\    if (strlen(empty_str) != 0) abort();
825        \\    char hello[] = "hello";
826        \\    if (strlen(hello) != 5 || sizeof(hello) != 6) abort();
827        \\    int empty[] = {};
828        \\    if (sizeof(empty) != 0) abort();
829        \\    int bar[] = {42};
830        \\    if (bar[0] != 42) abort();
831        \\    bar[0] = 43;
832        \\    if (bar[0] != 43) abort();
833        \\    int baz[] = {1, [42] = 123, 456};
834        \\    if (baz[42] != 123 || baz[43] != 456) abort();
835        \\    if (sizeof(baz) != sizeof(int) * 44) abort();
836        \\    const char *const names[] = {"first", "second", "third"};
837        \\    if (strcmp(names[2], "third") != 0) abort();
838        \\    char catted_str[] = "abc" "def";
839        \\    if (strlen(catted_str) != 6 || sizeof(catted_str) != 7) abort();
840        \\    char catted_trunc_str[2] = "abc" "def";
841        \\    if (sizeof(catted_trunc_str) != 2 || catted_trunc_str[0] != 'a' || catted_trunc_str[1] != 'b') abort();
842        \\    char big_array_utf8lit[10] = "��";
843        \\    if (strcmp(big_array_utf8lit, "��") != 0 || big_array_utf8lit[9] != 0) abort();
844        \\    return 0;
845        \\}
846    , "");
847
848    cases.add("Wide, UTF-16, and UTF-32 string literals",
849        \\#include <stdlib.h>
850        \\#include <stdint.h>
851        \\#include <wchar.h>
852        \\int main(void) {
853        \\    const wchar_t *wide_str = L"wide";
854        \\    const wchar_t wide_hello[] = L"hello";
855        \\    if (wcslen(wide_str) != 4) abort();
856        \\    if (wcslen(L"literal") != 7) abort();
857        \\    if (wcscmp(wide_hello, L"hello") != 0) abort();
858        \\
859        \\    const uint16_t *u16_str = u"wide";
860        \\    const uint16_t u16_hello[] = u"hello";
861        \\    if (u16_str[3] != u'e' || u16_str[4] != 0) abort();
862        \\    if (u16_hello[4] != u'o' || u16_hello[5] != 0) abort();
863        \\
864        \\    const uint32_t *u32_str = U"wide";
865        \\    const uint32_t u32_hello[] = U"hello";
866        \\    if (u32_str[3] != U'e' || u32_str[4] != 0) abort();
867        \\    if (u32_hello[4] != U'o' || u32_hello[5] != 0) abort();
868        \\    return 0;
869        \\}
870    , "");
871
872    cases.add("Address of function is no-op",
873        \\#include <stdlib.h>
874        \\#include <stdbool.h>
875        \\typedef int (*myfunc)(int);
876        \\int a(int arg) { return arg + 1;}
877        \\int b(int arg) { return arg + 2;}
878        \\int caller(myfunc fn, int arg) {
879        \\    return fn(arg);
880        \\}
881        \\int main() {
882        \\    myfunc arr[3] = {&a, &b, a};
883        \\    myfunc foo = a;
884        \\    myfunc bar = &(a);
885        \\    if (foo != bar) abort();
886        \\    if (arr[0] == arr[1]) abort();
887        \\    if (arr[0] != arr[2]) abort();
888        \\    if (caller(b, 40) != 42) abort();
889        \\    if (caller(&b, 40) != 42) abort();
890        \\    return 0;
891        \\}
892    , "");
893
894    cases.add("Obscure ways of calling functions; issue #4124",
895        \\#include <stdlib.h>
896        \\static int add(int a, int b) {
897        \\    return a + b;
898        \\}
899        \\typedef int (*adder)(int, int);
900        \\typedef void (*funcptr)(void);
901        \\int main() {
902        \\    if ((add)(1, 2) != 3) abort();
903        \\    if ((&add)(1, 2) != 3) abort();
904        \\    if (add(3, 1) != 4) abort();
905        \\    if ((*add)(2, 3) != 5) abort();
906        \\    if ((**add)(7, -1) != 6) abort();
907        \\    if ((***add)(-2, 9) != 7) abort();
908        \\
909        \\    int (*ptr)(int a, int b);
910        \\    ptr = add;
911        \\
912        \\    if (ptr(1, 2) != 3) abort();
913        \\    if ((*ptr)(3, 1) != 4) abort();
914        \\    if ((**ptr)(2, 3) != 5) abort();
915        \\    if ((***ptr)(7, -1) != 6) abort();
916        \\    if ((****ptr)(-2, 9) != 7) abort();
917        \\
918        \\    funcptr addr1 = (funcptr)(add);
919        \\    funcptr addr2 = (funcptr)(&add);
920        \\
921        \\    if (addr1 != addr2) abort();
922        \\    if (((int(*)(int, int))addr1)(1, 2) != 3) abort();
923        \\    if (((adder)addr2)(1, 2) != 3) abort();
924        \\    return 0;
925        \\}
926    , "");
927
928    cases.add("Return boolean expression as int; issue #6215",
929        \\#include <stdlib.h>
930        \\#include <stdbool.h>
931        \\bool  actual_bool(void)    { return 4 - 1 < 4;}
932        \\char  char_bool_ret(void)  { return 0 || 1; }
933        \\short short_bool_ret(void) { return 0 < 1; }
934        \\int   int_bool_ret(void)   { return 1 && 1; }
935        \\long  long_bool_ret(void)  { return !(0 > 1); }
936        \\static int GLOBAL = 1;
937        \\int nested_scopes(int a, int b) {
938        \\    if (a == 1) {
939        \\        int target = 1;
940        \\        return b == target;
941        \\    } else {
942        \\        int target = 2;
943        \\        if (b == target) {
944        \\            return GLOBAL == 1;
945        \\        }
946        \\        return target == 2;
947        \\    }
948        \\}
949        \\int main(void) {
950        \\    if (!actual_bool()) abort();
951        \\    if (!char_bool_ret()) abort();
952        \\    if (!short_bool_ret()) abort();
953        \\    if (!int_bool_ret()) abort();
954        \\    if (!long_bool_ret()) abort();
955        \\    if (!nested_scopes(1, 1)) abort();
956        \\    if (nested_scopes(1, 2)) abort();
957        \\    if (!nested_scopes(0, 2)) abort();
958        \\    if (!nested_scopes(0, 3)) abort();
959        \\    return 1 != 1;
960        \\}
961    , "");
962
963    cases.add("Comma operator should create new scope; issue #7989",
964        \\#include <stdlib.h>
965        \\#include <stdio.h>
966        \\int main(void) {
967        \\    if (1 || (abort(), 1)) {}
968        \\    if (0 && (1, printf("do not print\n"))) {}
969        \\    int x = 0;
970        \\    x = (x = 3, 4, x + 1);
971        \\    if (x != 4) abort();
972        \\    return 0;
973        \\}
974    , "");
975
976    cases.add("Use correct break label for statement expression in nested scope",
977        \\#include <stdlib.h>
978        \\int main(void) {
979        \\    int x = ({1, ({2; 3;});});
980        \\    if (x != 3) abort();
981        \\    return 0;
982        \\}
983    , "");
984
985    cases.add("pointer difference: scalar array w/ size truncation or negative result. Issue #7216",
986        \\#include <stdlib.h>
987        \\#include <stddef.h>
988        \\#define SIZE 10
989        \\int main() {
990        \\    int foo[SIZE];
991        \\    int *start = &foo[0];
992        \\    int *one_past_end = start + SIZE;
993        \\    ptrdiff_t diff = one_past_end - start;
994        \\    char diff_char = one_past_end - start;
995        \\    if (diff != SIZE || diff_char != SIZE) abort();
996        \\    diff = start - one_past_end;
997        \\    if (diff != -SIZE) abort();
998        \\    if (one_past_end - foo != SIZE) abort();
999        \\    if ((one_past_end - 1) - foo != SIZE - 1) abort();
1000        \\    if ((start + 1) - foo != 1) abort();
1001        \\    return 0;
1002        \\}
1003    , "");
1004
1005    // C standard: if the expression P points either to an element of an array object or one
1006    // past the last element of an array object, and the expression Q points to the last
1007    // element of the same array object, the expression ((Q)+1)-(P) has the same value as
1008    // ((Q)-(P))+1 and as -((P)-((Q)+1)), and has the value zero if the expression P points
1009    // one past the last element of the array object, even though the expression (Q)+1
1010    // does not point to an element of the array object
1011    cases.add("pointer difference: C standard edge case",
1012        \\#include <stdlib.h>
1013        \\#include <stddef.h>
1014        \\#define SIZE 10
1015        \\int main() {
1016        \\    int foo[SIZE];
1017        \\    int *start = &foo[0];
1018        \\    int *P = start + SIZE;
1019        \\    int *Q = &foo[SIZE - 1];
1020        \\    if ((Q + 1) - P != 0) abort();
1021        \\    if ((Q + 1) - P != (Q - P) + 1) abort();
1022        \\    if ((Q + 1) - P != -(P - (Q + 1))) abort();
1023        \\    return 0;
1024        \\}
1025    , "");
1026
1027    cases.add("pointer difference: unary operators",
1028        \\#include <stdlib.h>
1029        \\int main() {
1030        \\    int foo[10];
1031        \\    int *x = &foo[1];
1032        \\    const int *y = &foo[5];
1033        \\    if (y - x++ != 4) abort();
1034        \\    if (y - x != 3) abort();
1035        \\    if (y - ++x != 2) abort();
1036        \\    if (y - x-- != 2) abort();
1037        \\    if (y - x != 3) abort();
1038        \\    if (y - --x != 4) abort();
1039        \\    if (y - &foo[0] != 5) abort();
1040        \\    return 0;
1041        \\}
1042    , "");
1043
1044    cases.add("pointer difference: struct array with padding",
1045        \\#include <stdlib.h>
1046        \\#include <stddef.h>
1047        \\#define SIZE 10
1048        \\typedef struct my_struct {
1049        \\    int x;
1050        \\    char c;
1051        \\    int y;
1052        \\} my_struct_t;
1053        \\int main() {
1054        \\    my_struct_t foo[SIZE];
1055        \\    my_struct_t *start = &foo[0];
1056        \\    my_struct_t *one_past_end = start + SIZE;
1057        \\    ptrdiff_t diff = one_past_end - start;
1058        \\    int diff_int = one_past_end - start;
1059        \\    if (diff != SIZE || diff_int != SIZE) abort();
1060        \\    diff = start - one_past_end;
1061        \\    if (diff != -SIZE) abort();
1062        \\    return 0;
1063        \\}
1064    , "");
1065
1066    cases.add("pointer difference: array of function pointers",
1067        \\#include <stdlib.h>
1068        \\int a(void) { return 1;}
1069        \\int b(void) { return 2;}
1070        \\int c(void) { return 3;}
1071        \\typedef int (*myfunc)(void);
1072        \\int main() {
1073        \\    myfunc arr[] = {a, b, c, a, b, c};
1074        \\    myfunc *f1 = &arr[1];
1075        \\    myfunc *f4 = &arr[4];
1076        \\    if (f4 - f1 != 3) abort();
1077        \\    return 0;
1078        \\}
1079    , "");
1080
1081    cases.add("typeof operator",
1082        \\#include <stdlib.h>
1083        \\static int FOO = 42;
1084        \\typedef typeof(FOO) foo_type;
1085        \\typeof(foo_type) myfunc(typeof(FOO) x) { return (typeof(FOO)) x; }
1086        \\int main(void) {
1087        \\    int x = FOO;
1088        \\    typeof(x) y = x;
1089        \\    foo_type z = y;
1090        \\    if (x != y) abort();
1091        \\    if (myfunc(z) != x) abort();
1092        \\
1093        \\    const char *my_string = "bar";
1094        \\    typeof (typeof (my_string)[4]) string_arr = {"a","b","c","d"};
1095        \\    if (string_arr[0][0] != 'a' || string_arr[3][0] != 'd') abort();
1096        \\    return 0;
1097        \\}
1098    , "");
1099
1100    cases.add("offsetof",
1101        \\#include <stddef.h>
1102        \\#include <stdlib.h>
1103        \\#define container_of(ptr, type, member) ({                      \
1104        \\        const typeof( ((type *)0)->member ) *__mptr = (ptr);    \
1105        \\        (type *)( (char *)__mptr - offsetof(type,member) );})
1106        \\typedef struct {
1107        \\    int i;
1108        \\    struct { int x; char y; int z; } s;
1109        \\    float f;
1110        \\} container;
1111        \\int main(void) {
1112        \\    if (offsetof(container, i) != 0) abort();
1113        \\    if (offsetof(container, s) <= offsetof(container, i)) abort();
1114        \\    if (offsetof(container, f) <= offsetof(container, s)) abort();
1115        \\
1116        \\    container my_container;
1117        \\    typeof(my_container.s) *inner_member_pointer = &my_container.s;
1118        \\    float *float_member_pointer = &my_container.f;
1119        \\    int *anon_member_pointer = &my_container.s.z;
1120        \\    container *my_container_p;
1121        \\
1122        \\    my_container_p = container_of(inner_member_pointer, container, s);
1123        \\    if (my_container_p != &my_container) abort();
1124        \\
1125        \\    my_container_p = container_of(float_member_pointer, container, f);
1126        \\    if (my_container_p != &my_container) abort();
1127        \\
1128        \\    if (container_of(anon_member_pointer, typeof(my_container.s), z) != inner_member_pointer) abort();
1129        \\    return 0;
1130        \\}
1131    , "");
1132
1133    cases.add("handle assert.h",
1134        \\#include <assert.h>
1135        \\int main() {
1136        \\    int x = 1;
1137        \\    int *xp = &x;
1138        \\    assert(1);
1139        \\    assert(x != 0);
1140        \\    assert(xp);
1141        \\    assert(*xp);
1142        \\    return 0;
1143        \\}
1144    , "");
1145
1146    cases.add("NDEBUG disables assert",
1147        \\#define NDEBUG
1148        \\#include <assert.h>
1149        \\int main() {
1150        \\    assert(0);
1151        \\    assert(NULL);
1152        \\    return 0;
1153        \\}
1154    , "");
1155
1156    cases.add("pointer arithmetic with signed operand",
1157        \\#include <stdlib.h>
1158        \\int main() {
1159        \\    int array[10];
1160        \\    int *x = &array[5];
1161        \\    int *y;
1162        \\    int idx = 0;
1163        \\    y = x + ++idx;
1164        \\    if (y != x + 1 || y != &array[6]) abort();
1165        \\    y = idx + x;
1166        \\    if (y != x + 1 || y != &array[6]) abort();
1167        \\    y = x - idx;
1168        \\    if (y != x - 1 || y != &array[4]) abort();
1169        \\
1170        \\    idx = 0;
1171        \\    y = --idx + x;
1172        \\    if (y != x - 1 || y != &array[4]) abort();
1173        \\    y = idx + x;
1174        \\    if (y != x - 1 || y != &array[4]) abort();
1175        \\    y = x - idx;
1176        \\    if (y != x + 1 || y != &array[6]) abort();
1177        \\
1178        \\    idx = 1;
1179        \\    x += idx;
1180        \\    if (x != &array[6]) abort();
1181        \\    x -= idx;
1182        \\    if (x != &array[5]) abort();
1183        \\    y = (x += idx);
1184        \\    if (y != x || y != &array[6]) abort();
1185        \\    y = (x -= idx);
1186        \\    if (y != x || y != &array[5]) abort();
1187        \\
1188        \\    if (array + idx != &array[1] || array + 1 != &array[1]) abort();
1189        \\    idx = -1;
1190        \\    if (array - idx != &array[1]) abort();
1191        \\
1192        \\    return 0;
1193        \\}
1194    , "");
1195
1196    cases.add("Compound literals",
1197        \\#include <stdlib.h>
1198        \\struct Foo {
1199        \\    int a;
1200        \\    char b[2];
1201        \\    float c;
1202        \\};
1203        \\int main() {
1204        \\    struct Foo foo;
1205        \\    int x = 1, y = 2;
1206        \\    foo = (struct Foo) {x + y, {'a', 'b'}, 42.0f};
1207        \\    if (foo.a != x + y || foo.b[0] != 'a' || foo.b[1] != 'b' || foo.c != 42.0f) abort();
1208        \\    return 0;
1209        \\}
1210    , "");
1211
1212    cases.add("Generic selections",
1213        \\#include <stdlib.h>
1214        \\#include <string.h>
1215        \\#include <stdint.h>
1216        \\#define my_generic_fn(X) _Generic((X),    \
1217        \\              int: abs,                   \
1218        \\              char *: strlen,             \
1219        \\              size_t: malloc,             \
1220        \\              default: free               \
1221        \\)(X)
1222        \\#define my_generic_val(X) _Generic((X),   \
1223        \\              int: 1,                     \
1224        \\              const char *: "bar"         \
1225        \\)
1226        \\int main(void) {
1227        \\    if (my_generic_val(100) != 1) abort();
1228        \\
1229        \\    const char *foo = "foo";
1230        \\    const char *bar = my_generic_val(foo);
1231        \\    if (strcmp(bar, "bar") != 0) abort();
1232        \\
1233        \\    if (my_generic_fn(-42) != 42) abort();
1234        \\    if (my_generic_fn("hello") != 5) abort();
1235        \\
1236        \\    size_t size = 8192;
1237        \\    uint8_t *mem = my_generic_fn(size);
1238        \\    memset(mem, 42, size);
1239        \\    if (mem[size - 1] != 42) abort();
1240        \\    my_generic_fn(mem);
1241        \\
1242        \\    return 0;
1243        \\}
1244    , "");
1245
1246    // See __builtin_alloca_with_align comment in std.zig.c_builtins
1247    cases.add("use of unimplemented builtin in unused function does not prevent compilation",
1248        \\#include <stdlib.h>
1249        \\void unused() {
1250        \\    __builtin_alloca_with_align(1, 8);
1251        \\}
1252        \\int main(void) {
1253        \\    if (__builtin_sqrt(1.0) != 1.0) abort();
1254        \\    return 0;
1255        \\}
1256    , "");
1257
1258    cases.add("convert single-statement bodies into blocks for if/else/for/while. issue #8159",
1259        \\#include <stdlib.h>
1260        \\int foo() { return 1; }
1261        \\int main(void) {
1262        \\    int i = 0;
1263        \\    if (i == 0) if (i == 0) if (i != 0) i = 1;
1264        \\    if (i != 0) i = 1; else if (i == 0) if (i == 0) i += 1;
1265        \\    for (; i < 10;) for (; i < 10;) i++;
1266        \\    while (i == 100) while (i == 100) foo();
1267        \\    if (0) do do "string"; while(1); while(1);
1268        \\    return 0;
1269        \\}
1270    , "");
1271
1272    cases.add("cast RHS of compound assignment if necessary, unused result",
1273        \\#include <stdlib.h>
1274        \\int main(void) {
1275        \\   signed short val = -1;
1276        \\   val += 1; if (val != 0) abort();
1277        \\   val -= 1; if (val != -1) abort();
1278        \\   val *= 2; if (val != -2) abort();
1279        \\   val /= 2; if (val != -1) abort();
1280        \\   val %= 2; if (val != -1) abort();
1281        \\   val <<= 1; if (val != -2) abort();
1282        \\   val >>= 1; if (val != -1) abort();
1283        \\   val += 100000000;       // compile error if @truncate() not inserted
1284        \\   unsigned short uval = 1;
1285        \\   uval += 1; if (uval != 2) abort();
1286        \\   uval -= 1; if (uval != 1) abort();
1287        \\   uval *= 2; if (uval != 2) abort();
1288        \\   uval /= 2; if (uval != 1) abort();
1289        \\   uval %= 2; if (uval != 1) abort();
1290        \\   uval <<= 1; if (uval != 2) abort();
1291        \\   uval >>= 1; if (uval != 1) abort();
1292        \\   uval += 100000000;      // compile error if @truncate() not inserted
1293        \\}
1294    , "");
1295
1296    cases.add("cast RHS of compound assignment if necessary, used result",
1297        \\#include <stdlib.h>
1298        \\int main(void) {
1299        \\   signed short foo;
1300        \\   signed short val = -1;
1301        \\   foo = (val += 1); if (foo != 0) abort();
1302        \\   foo = (val -= 1); if (foo != -1) abort();
1303        \\   foo = (val *= 2); if (foo != -2) abort();
1304        \\   foo = (val /= 2); if (foo != -1) abort();
1305        \\   foo = (val %= 2); if (foo != -1) abort();
1306        \\   foo = (val <<= 1); if (foo != -2) abort();
1307        \\   foo = (val >>= 1); if (foo != -1) abort();
1308        \\   foo = (val += 100000000);    // compile error if @truncate() not inserted
1309        \\   unsigned short ufoo;
1310        \\   unsigned short uval = 1;
1311        \\   ufoo = (uval += 1); if (ufoo != 2) abort();
1312        \\   ufoo = (uval -= 1); if (ufoo != 1) abort();
1313        \\   ufoo = (uval *= 2); if (ufoo != 2) abort();
1314        \\   ufoo = (uval /= 2); if (ufoo != 1) abort();
1315        \\   ufoo = (uval %= 2); if (ufoo != 1) abort();
1316        \\   ufoo = (uval <<= 1); if (ufoo != 2) abort();
1317        \\   ufoo = (uval >>= 1); if (ufoo != 1) abort();
1318        \\   ufoo = (uval += 100000000);  // compile error if @truncate() not inserted
1319        \\}
1320    , "");
1321
1322    cases.add("basic vector expressions",
1323        \\#include <stdlib.h>
1324        \\#include <stdint.h>
1325        \\typedef int16_t  __v8hi __attribute__((__vector_size__(16)));
1326        \\int main(int argc, char**argv) {
1327        \\    __v8hi uninitialized;
1328        \\    __v8hi empty_init = {};
1329        \\    __v8hi partial_init = {0, 1, 2, 3};
1330        \\
1331        \\    __v8hi a = {0, 1, 2, 3, 4, 5, 6, 7};
1332        \\    __v8hi b = (__v8hi) {100, 200, 300, 400, 500, 600, 700, 800};
1333        \\
1334        \\    __v8hi sum = a + b;
1335        \\    for (int i = 0; i < 8; i++) {
1336        \\        if (sum[i] != a[i] + b[i]) abort();
1337        \\    }
1338        \\    return 0;
1339        \\}
1340    , "");
1341
1342    cases.add("__builtin_shufflevector",
1343        \\#include <stdlib.h>
1344        \\#include <stdint.h>
1345        \\typedef int16_t  __v4hi __attribute__((__vector_size__(8)));
1346        \\typedef int16_t  __v8hi __attribute__((__vector_size__(16)));
1347        \\int main(int argc, char**argv) {
1348        \\    __v8hi v8_a = {0, 1, 2, 3, 4, 5, 6, 7};
1349        \\    __v8hi v8_b = {100, 200, 300, 400, 500, 600, 700, 800};
1350        \\    __v8hi shuffled = __builtin_shufflevector(v8_a, v8_b, 0, 1, 2, 3, 8, 9, 10, 11);
1351        \\    for (int i = 0; i < 8; i++) {
1352        \\        if (i < 4) {
1353        \\            if (shuffled[i] != v8_a[i]) abort();
1354        \\        } else {
1355        \\            if (shuffled[i] != v8_b[i - 4]) abort();
1356        \\        }
1357        \\    }
1358        \\    shuffled = __builtin_shufflevector(
1359        \\        (__v8hi) {-1, -1, -1, -1, -1, -1, -1, -1},
1360        \\        (__v8hi) {42, 42, 42, 42, 42, 42, 42, 42},
1361        \\        0, 1, 2, 3, 8, 9, 10, 11
1362        \\    );
1363        \\    for (int i = 0; i < 8; i++) {
1364        \\        if (i < 4) {
1365        \\            if (shuffled[i] != -1) abort();
1366        \\        } else {
1367        \\            if (shuffled[i] != 42) abort();
1368        \\        }
1369        \\    }
1370        \\    __v4hi shuffled_to_fewer_elements = __builtin_shufflevector(v8_a, v8_b, 0, 1, 8, 9);
1371        \\    for (int i = 0; i < 4; i++) {
1372        \\        if (i < 2) {
1373        \\            if (shuffled_to_fewer_elements[i] != v8_a[i]) abort();
1374        \\        } else {
1375        \\            if (shuffled_to_fewer_elements[i] != v8_b[i - 2]) abort();
1376        \\        }
1377        \\    }
1378        \\    __v4hi v4_a = {0, 1, 2, 3};
1379        \\    __v4hi v4_b = {100, 200, 300, 400};
1380        \\    __v8hi shuffled_to_more_elements = __builtin_shufflevector(v4_a, v4_b, 0, 1, 2, 3, 4, 5, 6, 7);
1381        \\    for (int i = 0; i < 4; i++) {
1382        \\        if (shuffled_to_more_elements[i] != v4_a[i]) abort();
1383        \\        if (shuffled_to_more_elements[i + 4] != v4_b[i]) abort();
1384        \\    }
1385        \\    return 0;
1386        \\}
1387    , "");
1388
1389    cases.add("__builtin_convertvector",
1390        \\#include <stdlib.h>
1391        \\#include <stdint.h>
1392        \\typedef int16_t  __v8hi __attribute__((__vector_size__(16)));
1393        \\typedef uint16_t __v8hu __attribute__((__vector_size__(16)));
1394        \\int main(int argc, char**argv) {
1395        \\    __v8hi signed_vector = { 1, 2, 3, 4, -1, -2, -3,-4};
1396        \\    __v8hu unsigned_vector = __builtin_convertvector(signed_vector, __v8hu);
1397        \\
1398        \\    for (int i = 0; i < 8; i++) {
1399        \\        if (unsigned_vector[i] != (uint16_t)signed_vector[i]) abort();
1400        \\    }
1401        \\    return 0;
1402        \\}
1403    , "");
1404
1405    cases.add("vector casting",
1406        \\#include <stdlib.h>
1407        \\#include <stdint.h>
1408        \\typedef int8_t __v8qi __attribute__((__vector_size__(8)));
1409        \\typedef uint8_t __v8qu __attribute__((__vector_size__(8)));
1410        \\int main(int argc, char**argv) {
1411        \\    __v8qi signed_vector = { 1, 2, 3, 4, -1, -2, -3,-4};
1412        \\
1413        \\    uint64_t big_int = (uint64_t) signed_vector;
1414        \\    if (big_int != 0x01020304FFFEFDFCULL && big_int != 0xFCFDFEFF04030201ULL) abort();
1415        \\    __v8qu unsigned_vector = (__v8qu) big_int;
1416        \\    for (int i = 0; i < 8; i++) {
1417        \\        if (unsigned_vector[i] != (uint8_t)signed_vector[i] && unsigned_vector[i] != (uint8_t)signed_vector[7 - i]) abort();
1418        \\    }
1419        \\    return 0;
1420        \\}
1421    , "");
1422
1423    cases.add("break from switch statement. Issue #8387",
1424        \\#include <stdlib.h>
1425        \\int switcher(int x) {
1426        \\    switch (x) {
1427        \\        case 0:      // no braces
1428        \\            x += 1;
1429        \\            break;
1430        \\        case 1:      // conditional break
1431        \\            if (x == 1) {
1432        \\                x += 1;
1433        \\                break;
1434        \\            }
1435        \\            x += 100;
1436        \\        case 2: {    // braces with fallthrough
1437        \\            x += 1;
1438        \\        }
1439        \\        case 3:      // fallthrough to return statement
1440        \\            x += 1;
1441        \\        case 42: {   // random out of order case
1442        \\            x += 1;
1443        \\            return x;
1444        \\        }
1445        \\        case 4: {    // break within braces
1446        \\            x += 1;
1447        \\            break;
1448        \\        }
1449        \\        case 5:
1450        \\            x += 1;  // fallthrough to default
1451        \\        default:
1452        \\            x += 1;
1453        \\    }
1454        \\    return x;
1455        \\}
1456        \\int main(void) {
1457        \\    int expected[] = {1, 2, 5, 5, 5, 7, 7};
1458        \\    for (int i = 0; i < sizeof(expected) / sizeof(int); i++) {
1459        \\        int res = switcher(i);
1460        \\        if (res != expected[i]) abort();
1461        \\    }
1462        \\    if (switcher(42) != 43) abort();
1463        \\    return 0;
1464        \\}
1465    , "");
1466
1467    cases.add("Cast to enum from larger integral type. Issue #6011",
1468        \\#include <stdint.h>
1469        \\#include <stdlib.h>
1470        \\enum Foo { A, B, C };
1471        \\static inline enum Foo do_stuff(void) {
1472        \\    int64_t i = 1;
1473        \\    return (enum Foo)i;
1474        \\}
1475        \\int main(void) {
1476        \\    if (do_stuff() != B) abort();
1477        \\    return 0;
1478        \\}
1479    , "");
1480
1481    cases.add("Render array LHS as grouped node if necessary",
1482        \\#include <stdlib.h>
1483        \\int main(void) {
1484        \\    int arr[] = {40, 41, 42, 43};
1485        \\    if ((arr + 1)[1] != 42) abort();
1486        \\    return 0;
1487        \\}
1488    , "");
1489
1490    cases.add("typedef with multiple names",
1491        \\#include <stdlib.h>
1492        \\typedef struct {
1493        \\    char field;
1494        \\} a_t, b_t;
1495        \\
1496        \\int main(void) {
1497        \\    a_t a = { .field = 42 };
1498        \\    b_t b = a;
1499        \\    if (b.field != 42) abort();
1500        \\    return 0;
1501        \\}
1502    , "");
1503
1504    cases.add("__cleanup__ attribute",
1505        \\#include <stdlib.h>
1506        \\static int cleanup_count = 0;
1507        \\void clean_up(int *final_value) {
1508        \\    if (*final_value != cleanup_count++) abort();
1509        \\}
1510        \\void doit(void) {
1511        \\    int a __attribute__ ((__cleanup__(clean_up))) __attribute__ ((unused)) = 2;
1512        \\    int b __attribute__ ((__cleanup__(clean_up))) __attribute__ ((unused)) = 1;
1513        \\    int c __attribute__ ((__cleanup__(clean_up))) __attribute__ ((unused)) = 0;
1514        \\}
1515        \\int main(void) {
1516        \\    doit();
1517        \\    if (cleanup_count != 3) abort();
1518        \\    return 0;
1519        \\}
1520    , "");
1521
1522    cases.add("enum used as boolean expression",
1523        \\#include <stdlib.h>
1524        \\enum FOO {BAR, BAZ};
1525        \\int main(void) {
1526        \\    enum FOO x = BAR;
1527        \\    if (x) abort();
1528        \\    if (!BAZ) abort();
1529        \\    return 0;
1530        \\}
1531    , "");
1532
1533    cases.add("Flexible arrays",
1534        \\#include <stdlib.h>
1535        \\#include <stdint.h>
1536        \\typedef struct { char foo; int bar; } ITEM;
1537        \\typedef struct { size_t count; ITEM items[]; } ITEM_LIST;
1538        \\typedef struct { unsigned char count; int items[]; } INT_LIST;
1539        \\#define SIZE 10
1540        \\int main(void) {
1541        \\    ITEM_LIST *list = malloc(sizeof(ITEM_LIST) + SIZE * sizeof(ITEM));
1542        \\    for (int i = 0; i < SIZE; i++) list->items[i] = (ITEM) {.foo = i, .bar = i + 1};
1543        \\    const ITEM_LIST *const c_list = list;
1544        \\    for (int i = 0; i < SIZE; i++) if (c_list->items[i].foo != i || c_list->items[i].bar != i + 1) abort();
1545        \\    INT_LIST *int_list = malloc(sizeof(INT_LIST) + SIZE * sizeof(int));
1546        \\    for (int i = 0; i < SIZE; i++) int_list->items[i] = i;
1547        \\    const INT_LIST *const c_int_list = int_list;
1548        \\    const int *const ints = int_list->items;
1549        \\    for (int i = 0; i < SIZE; i++) if (ints[i] != i) abort();
1550        \\    return 0;
1551        \\}
1552    , "");
1553
1554    cases.add("enum with value that fits in c_uint but not c_int, issue #8003",
1555        \\#include <stdlib.h>
1556        \\enum my_enum {
1557        \\    FORCE_UINT = 0xffffffff
1558        \\};
1559        \\int main(void) {
1560        \\    if(FORCE_UINT != 0xffffffff) abort();
1561        \\}
1562    , "");
1563
1564    cases.add("block-scope static variable shadows function parameter. Issue #8208",
1565        \\#include <stdlib.h>
1566        \\int func1(int foo) { return foo + 1; }
1567        \\int func2(void) {
1568        \\    static int foo = 5;
1569        \\    return foo++;
1570        \\}
1571        \\int main(void) {
1572        \\    if (func1(42) != 43) abort();
1573        \\    if (func2() != 5) abort();
1574        \\    if (func2() != 6) abort();
1575        \\    return 0;
1576        \\}
1577    , "");
1578
1579    cases.add("nested same-name static locals",
1580        \\#include <stdlib.h>
1581        \\int func(int val) {
1582        \\    static int foo;
1583        \\    if (foo != val) abort();
1584        \\    {
1585        \\        foo += 1;
1586        \\        static int foo = 2;
1587        \\        if (foo != val + 2) abort();
1588        \\        foo += 1;
1589        \\    }
1590        \\    return foo;
1591        \\}
1592        \\int main(void) {
1593        \\    int foo = 1;
1594        \\    if (func(0) != 1) abort();
1595        \\    if (func(1) != 2) abort();
1596        \\    if (func(2) != 3) abort();
1597        \\    if (foo != 1) abort();
1598        \\    return 0;
1599        \\}
1600    , "");
1601
1602    cases.add("Enum constants are assigned correct type. Issue #9153",
1603        \\enum A { A0, A1=0xFFFFFFFF };
1604        \\enum B { B0=-1, B1=0xFFFFFFFF };
1605        \\enum C { C0=-1, C1=0 };
1606        \\enum D { D0, D1=0xFFFFFFFFFFL };
1607        \\enum E { E0=-1, E1=0xFFFFFFFFFFL };
1608        \\int main(void) {
1609        \\   signed char a0 = A0, a1 = A1;
1610        \\   signed char b0 = B0, b1 = B1;
1611        \\   signed char c0 = C0, c1 = C1;
1612        \\   signed char d0 = D0, d1 = D1;
1613        \\   signed char e0 = E0, e1 = E1;
1614        \\   return 0;
1615        \\}
1616    , "");
1617
1618    cases.add("Enum constant matches enum name; multiple enumerations with same value",
1619        \\#include <stdlib.h>
1620        \\enum FOO {
1621        \\    FOO = 1,
1622        \\    BAR = 2,
1623        \\    BAZ = 1,
1624        \\};
1625        \\int main(void) {
1626        \\    enum FOO x = BAZ;
1627        \\    if (x != 1) abort();
1628        \\    if (x != BAZ) abort();
1629        \\    if (x != FOO) abort();
1630        \\}
1631    , "");
1632
1633    cases.add("Scoped enums",
1634        \\#include <stdlib.h>
1635        \\int main(void) {
1636        \\   enum Foo { A, B, C };
1637        \\   enum Foo a = B;
1638        \\   if (a != B) abort();
1639        \\   if (a != 1) abort();
1640        \\   {
1641        \\      enum Foo { A = 5, B = 6, C = 7 };
1642        \\      enum Foo a = B;
1643        \\      if (a != B) abort();
1644        \\      if (a != 6) abort();
1645        \\   }
1646        \\   if (a != B) abort();
1647        \\   if (a != 1) abort();
1648        \\}
1649    , "");
1650
1651    cases.add("Underscore identifiers",
1652        \\#include <stdlib.h>
1653        \\int _ = 10;
1654        \\typedef struct { int _; } S;
1655        \\int main(void) {
1656        \\    if (_ != 10) abort();
1657        \\    S foo = { ._ = _ };
1658        \\    if (foo._ != _) abort();
1659        \\    return 0;
1660        \\}
1661    , "");
1662
1663    cases.add("__builtin_choose_expr (unchosen expression is not evaluated)",
1664        \\#include <stdlib.h>
1665        \\int main(void) {
1666        \\    int x = 0.0;
1667        \\    int y = 0.0;
1668        \\    int res;
1669        \\    res = __builtin_choose_expr(1, 1, x / y);
1670        \\    if (res != 1) abort();
1671        \\    res = __builtin_choose_expr(0, x / y, 2);
1672        \\    if (res != 2) abort();
1673        \\    return 0;
1674        \\}
1675    , "");
1676
1677    // TODO: add isnan check for long double once bitfield support is added
1678    //       (needed for x86_64-windows-gnu)
1679    // TODO: add isinf check for long double once std.math.isInf supports c_longdouble
1680    cases.add("NAN and INFINITY",
1681        \\#include <math.h>
1682        \\#include <stdint.h>
1683        \\#include <stdlib.h>
1684        \\union uf { uint32_t u; float f; };
1685        \\#define CHECK_NAN(STR, VAL) { \
1686        \\    union uf unpack = {.f = __builtin_nanf(STR)}; \
1687        \\    if (!isnan(unpack.f)) abort(); \
1688        \\    if (unpack.u != VAL) abort(); \
1689        \\}
1690        \\int main(void) {
1691        \\    float f_nan = NAN;
1692        \\    if (!isnan(f_nan)) abort();
1693        \\    double d_nan = NAN;
1694        \\    if (!isnan(d_nan)) abort();
1695        \\    CHECK_NAN("0", 0x7FC00000);
1696        \\    CHECK_NAN("", 0x7FC00000);
1697        \\    CHECK_NAN("1", 0x7FC00001);
1698        \\    CHECK_NAN("0x7FC00000", 0x7FC00000);
1699        \\    CHECK_NAN("0x7FC0000F", 0x7FC0000F);
1700        \\    CHECK_NAN("0x7FC000F0", 0x7FC000F0);
1701        \\    CHECK_NAN("0x7FC00F00", 0x7FC00F00);
1702        \\    CHECK_NAN("0x7FC0F000", 0x7FC0F000);
1703        \\    CHECK_NAN("0x7FCF0000", 0x7FCF0000);
1704        \\    CHECK_NAN("0xFFFFFFFF", 0x7FFFFFFF);
1705        \\    float f_inf = INFINITY;
1706        \\    if (!isinf(f_inf)) abort();
1707        \\    double d_inf = INFINITY;
1708        \\    if (!isinf(d_inf)) abort();
1709        \\    return 0;
1710        \\}
1711    , "");
1712
1713    cases.add("signed array subscript. Issue #8556",
1714        \\#include <stdint.h>
1715        \\#include <stdlib.h>
1716        \\#define TEST_NEGATIVE(type) { type x = -1; if (ptr[x] != 42) abort(); }
1717        \\#define TEST_UNSIGNED(type) { type x = 2; if (arr[x] != 42) abort(); }
1718        \\int main(void) {
1719        \\    int arr[] = {40, 41, 42, 43};
1720        \\    int *ptr = arr + 3;
1721        \\    if (ptr[-1] != 42) abort();
1722        \\    TEST_NEGATIVE(int);
1723        \\    TEST_NEGATIVE(long);
1724        \\    TEST_NEGATIVE(long long);
1725        \\    TEST_NEGATIVE(int64_t);
1726        \\    TEST_NEGATIVE(__int128);
1727        \\    TEST_UNSIGNED(unsigned);
1728        \\    TEST_UNSIGNED(unsigned long);
1729        \\    TEST_UNSIGNED(unsigned long long);
1730        \\    TEST_UNSIGNED(uint64_t);
1731        \\    TEST_UNSIGNED(size_t);
1732        \\    TEST_UNSIGNED(unsigned __int128);
1733        \\    return 0;
1734        \\}
1735    , "");
1736
1737    cases.add("Ensure side-effects only evaluated once for signed array indices",
1738        \\#include <stdlib.h>
1739        \\int main(void) {
1740        \\    int foo[] = {1, 2, 3, 4};
1741        \\    int *p = foo;
1742        \\    int idx = 1;
1743        \\    if ((++p)[--idx] != 2) abort();
1744        \\    if (p != foo + 1) abort();
1745        \\    if (idx != 0) abort();
1746        \\    if ((p++)[idx++] != 2) abort();
1747        \\    if (p != foo + 2) abort();
1748        \\    if (idx != 1) abort();
1749        \\    return 0;
1750        \\}
1751    , "");
1752
1753    cases.add("Allow non-const char* string literals. Issue #9126",
1754        \\#include <stdlib.h>
1755        \\int func(char *x) { return x[0]; }
1756        \\struct S { char *member; };
1757        \\struct S global_struct = { .member = "global" };
1758        \\char *g = "global";
1759        \\int main(void) {
1760        \\   if (g[0] != 'g') abort();
1761        \\   if (global_struct.member[0] != 'g') abort();
1762        \\   char *string = "hello";
1763        \\   if (string[0] != 'h') abort();
1764        \\   struct S s = {.member = "hello"};
1765        \\   if (s.member[0] != 'h') abort();
1766        \\   if (func("foo") != 'f') abort();
1767        \\   return 0;
1768        \\}
1769    , "");
1770
1771    cases.add("Ensure while loop under an if doesn't steal the else. Issue #9953",
1772        \\#include <stdio.h>
1773        \\void doWork(int id) { }
1774        \\int reallyDelete(int id) { printf("deleted %d\n", id); return 1; }
1775        \\int process(int id, int n, int delete) {
1776        \\    if(!delete)
1777        \\        while(n-- > 0) doWork(id);
1778        \\    else
1779        \\        return reallyDelete(id);
1780        \\    return 0;
1781        \\}
1782        \\int main(void) {
1783        \\    process(99, 3, 0);
1784        \\    return 0;
1785        \\}
1786    , "");
1787
1788    cases.add("Remainder operator with negative integers. Issue #10176",
1789        \\#include <stdlib.h>
1790        \\int main(void) {
1791        \\    int denominator = -2;
1792        \\    int numerator = 5;
1793        \\    if (numerator % denominator != 1) abort();
1794        \\    numerator = -5; denominator = 2;
1795        \\    if (numerator % denominator != -1) abort();
1796        \\    return 0;
1797        \\}
1798    , "");
1799
1800    cases.add("Boolean expression coerced to int. Issue #10175",
1801        \\#include <stdlib.h>
1802        \\int sign(int v) {
1803        \\    return -(v < 0);
1804        \\}
1805        \\int main(void) {
1806        \\    if (sign(-5) != -1) abort();
1807        \\    if (sign(5) != 0) abort();
1808        \\    if (sign(0) != 0) abort();
1809        \\    return 0;
1810        \\}
1811    , "");
1812}
1813