kit

kit
git clone https://git.ryansepassi.com/git/kit.git
Log | Files | Refs | README

C-parser test corpus

Coverage matrix for test/parse/. Each cases/<name>.c is one row; the behavioral oracle is test_main's return value mod 256, identical to test/cg/. Group prefixes track C11 §6.x section numbers; the file name itself is the case identifier.

This corpus extends test/cg/CORPUS.md upward: cg fixtures drive cg directly with hand-built Operands and prove codegen primitives in isolation; the parser cases prove the C front-end issues the right cg sequence end-to-end. Anything visible at runtime that the parser is expected to lower must have a parse-level row here.

Test paths per case (run.sh, sourced from test/cg/run.sh):

W (DWARF directives) is reserved; once the parser drives Debug it will read <name>.dwarf sidecars and reuse cg-check-dwarf.

Sidecars (each missing file uses the documented default):

Status legend

Until the parser lands, every row that exercises a parser feature is expected to FAIL — the build's parse_c stub panics on entry, so paths D and --emit both report nonzero. The corpus is fixed in advance so each parser-feature landing flips a known set of · rows to with no case authoring required mid-implementation.

Spine

Initial landing — proves the harness wiring, diagnostic flow, and exit-code oracle end to end. Every spine row reduces to a single int test_main(void) { return EXPR; } with no declarations beyond the function definition itself.

Case Status Body Expected
6_5_01_return_const return 42; 42
6_5_02_add return 1 + 2; 3
6_5_03_sub_mul return 7 * 3 - 4; 17
6_8_01_if_else int x; if (1) x = 7; else x = 99; return x; 7
6_8_02_while_sum int s=0,i=0; while (i<10) { s+=i; i++; } return s; 45
6_8_03_for_sum int s=0; for (int i=1; i<=10; i++) s+=i; return s; 55

Negative spine (one case per spec area; expands as the parser learns to diagnose more):

Case Status Surface Notes
cases_err/6_5_undeclared · identifier resolution return q; — no such identifier

§6.2 Concepts

Most of §6.2 is exercised implicitly by other rows (block scope by 6_8_12, internal/external linkage by 6_7_03/6_7_04, automatic storage by every local). The cases here pin down behaviors with no natural home elsewhere.

Case Status Body Expected
6_2_1_01_param_shadow helper int f(int x){{int x=42; return x;}}; return f(99); — block decl shadows function parameter 42
6_2_1_02_label_in_nested_block goto done; { done: r=42; } — label declared inside nested block has function scope 42
6_2_2_01_extern_in_block_inherits_internal · full TU: static int g=42; int test_main(void){extern int g; return g;}extern redeclares to inherit internal linkage 42
6_2_3_01_tag_ord_namespace struct s { int v; }; int s = 42; struct s t = {0}; return s + t.v; 42
6_2_3_01b_member_namespace_two_structs struct A{int x;}; struct B{int x;}; ... return a.x+b.x; — same member name in distinct struct types 42
6_2_3_02_label_namespace int s = 0; goto s; s = 99; s: return 42; 42
6_2_4_01_static_keeps_value helper int next(){static int n=40; return ++n;}; next(); return next(); 42
6_2_4_02_auto_reinit_each_iteration for(int i=0;i<6;i++){int x=i; s+=x;} — local re-initialized each iteration; 0+1+...+5=15 15
6_2_4_03_static_local_zero_init helper int f(){static int n; return ++n;}; f()+f() — static local zero-initialized 3
6_2_5_01_void_func_no_value helper void f(int *p){*p=42;} int x; f(&x); return x; 42
6_2_5_01b_unsigned_wrap unsigned char u=255; u++; return u; — modular wrap to 0 0
6_2_5_02_incomplete_array_completed full TU: extern int a[]; int a[3]={0,0,42}; ...return a[2]; — incomplete array completed by later definition 42
6_2_7_01_composite_array_size · full TU: extern int a[]; int a[3]={40,0,0}; extern int a[3]; ...sizeof(a)/sizeof(a[0]) — composite type from compatible decls 42
6_2_8_01_char_weakest_align return (int)_Alignof(char); — char has alignment 1 1

§6.3 Conversions

Implicit and explicit conversions. 6_5_23_cast covers narrowing via explicit cast; rows here fill in the rest of the conversion matrix.

Case Status Body Expected
6_3_1_1_01_char_promotion char c = 'A'; return c - '@' + 41; 42
6_3_1_3_01_signed_to_unsigned int n = -1; unsigned u = (unsigned)n; return (int)(u & 0xff); 255
6_3_1_3_02_unsigned_narrow unsigned u = 0x100002aU; int n = (int)u; return n; 42
6_3_1_4_01_float_to_int double d = 42.9; return (int)d; 42
6_3_1_4_02_int_to_float int n = 42; double d = n; return (int)d; 42
6_3_1_8_01_usual_arith_mixed int s = -1; unsigned u = 1; return (s + u) ? 0 : 42; 42
6_3_2_1_01_array_to_ptr int a[3] = {0,0,42}; int *p = a; return p[2]; 42
6_3_2_1_02_func_to_ptr helper id; int (*fp)(int) = id; return fp(42); 42
6_3_2_2_01_void_cast_discard (void)42; return 42; 42
6_3_2_3_01_null_ptr_cmp int *p = 0; return p ? 99 : 42; 42
6_3_2_3_02_void_ptr_roundtrip int x=42; void *v=&x; int *p=(int*)v; return *p; 42
6_3_1_2_01_bool_from_ptr _Bool b=(int*)&x ? 1 : 0; return b ? 42 : 0; — non-null pointer → _Bool 1 42
6_3_1_2_02_bool_from_float _Bool b = 0.0; return b ? 99 : 42; — zero float → _Bool 0 42
6_3_1_3_03_uchar_wrap int n = -1; unsigned char c = (unsigned char)n; return c; — modular reduction mod 256 255
6_3_1_8_02_signed_wins long a=40; unsigned int b=2; return (int)(a+b); — signed long rank > unsigned int → result is long 42
6_3_2_3_03_null_void_cast int *p = (void*)0; return p ? 99 : 42;(void*)0 is null pointer constant 42

§6.4 Lexical Elements

Case Status Body Expected
6_4_4_4_01_wide_char_ucn RED L'\u00a3' == 163 ? 42 : 0 — universal character names in wide character constants 42
6_4_4_4_02_wide_char_hex_escape RED L'\x012a' == 298 ? 42 : 0 — wide character constants must not be byte-truncated 42
6_4_5_03_wide_string_sizeof RED sizeof(L"*") * 5 + 2 — wide string literal element type/width 42

§6.5 Expressions

Drives the entire expression grammar. One row per production where the behavior is observable through test_main. Spine rows above repeat here for completeness once they're real cases.

Case Status Body Expected
6_5_01_return_const return 42; 42
6_5_02_add return 1 + 2; 3
6_5_03_sub_mul return 7 * 3 - 4; 17
6_5_04_div_mod return 23 / 4 + 23 % 4; 8
6_5_05_bitwise_and return (~3) & 0xff; 252
6_5_06_bitwise_or_xor return (0xa5 ^ 0x5a) & 0xff; 255
6_5_07_shift return (1<<5) \| (16>>1); 40
6_5_08_unary_neg return -7; 249
6_5_09_logical_not return !0 + !!5; 2
6_5_10_cmp_eq return (5 == 5) + (5 == 6); 1
6_5_11_cmp_lt return (-1 < 1); 1
6_5_12_logical_and_skip int s=0; (0) && (s=99); return s; 0
6_5_13_logical_or_skip int s=0; (1) \|\| (s=99); return s; 0
6_5_14_ternary return (5>3) ? 42 : 7; 42
6_5_15_comma int x; return (x=1, x=42, x); 42
6_5_16_assign int x; x = 42; return x; 42
6_5_17_compound_assign int x = 40; x += 2; return x; 42
6_5_18_pre_inc int x = 41; return ++x; 42
6_5_19_post_inc int x = 42; x++; return x; 43; reads as 43
6_5_20_addr_deref int x = 42; int *p = &x; return *p; 42
6_5_21_sizeof_int return (int)sizeof(int); 4
6_5_22_sizeof_expr int a[7]; return (int)(sizeof(a)/sizeof(int)); 7
6_5_23_cast return (int)(unsigned char)(-1); 255
6_5_24_func_call helper int id(int x){return x;} + return id(42); 42
6_5_25_unary_plus return +42; 42
6_5_26_pre_dec int x = 43; return --x; 42
6_5_27_post_dec int x = 43; x--; return x; 42
6_5_28_arrow struct S{int v;} s={42}; struct S *p=&s; return p->v; 42
6_5_29_compound_literal int *p = (int[]){10, 32}; return p[0]+p[1]; 42
6_5_30_generic_selection int x=42; return _Generic((x), int: x, default: 0); 42
6_5_31_subscript_commute int a[5]={0,0,42,0,0}; return 2[a]; 42
6_5_32_string_subscript return "*"[0]; 42
6_5_33_regalloc_spill 12-arg sum12(x1+0, ..., x12+0) — exceeds the 10-INT scratch pool, exercises spill_reg/reload_reg and the cg_call avs-in-flight fallback 78
cg_postdec_while_count while (n-- > 0) must test the old value after duplicating a register-backed local 42
cg_x64_fp_format_fixed_digits fixed decimal digit extraction from 12.375 with a helper call and output calls; repro for x64 caller-saved FP values and post-decrement rounding 42
6_5_36_fp_arith (a + b) / b * c - 36.0 over double — pins parser dispatch to BO_FADD/FSUB/FMUL/FDIV 42
6_5_37_fp_int_promote int + double — usual arithmetic conversion promotes the int side to double before BO_FADD 42
6_5_38_fp_float_widen float + double — float widens to double before BO_FADD 42
6_5_39_float_arith float * float stays at single precision (BO_FMUL with type=0) 42
6_5_40_ptr_add int *p=a; p=p+3; return *p;ptr+int with stride scaling (4-byte element) 42
6_5_41_ptr_sub_ptr int *p=a+4; int *q=a+1; return (int)(p-q); — pointer subtraction yields ptrdiff 3
6_5_42_ptr_arith_stride double a[3]={...}; double *p=a+2; return (int)*p; — stride = sizeof(double) = 8 42
6_5_43_signed_rshift int x=-256; (x>>4)+58 — arithmetic right-shift on signed value 42
6_5_44_relational_all (3>1)+(1<3)+(2<=2)+(2>=2)+(1!=2)+(2==2) — covers >, <=, >=, != 6
6_5_45_ptr_eq_null (p==0)+(q!=0)+(p!=q) — pointer equality with null and pointer-vs-pointer != 3
6_5_46_ptr_relcmp (p<q)+(q>p)+(p<=p) — relational comparison of pointers into same array 3
6_5_46b_cmp_to_bool_init _Bool b = (1 != 0); — comparison result is assignable through _Bool conversion 42
6_5_47_ternary_arith_conv int c=1; double r = c ? 1 : 2.5; return (int)(r+41.0); — ternary arms get usual arithmetic conversion to double 42
6_5_48_ternary_ptr_null int *p = 1 ? &x : 0; return *p; — one arm pointer, other null pointer constant 42
6_5_49_compound_assign_sub int x=44; x-=2; return x;-= operator 42
6_5_50_compound_assign_shift int x=336; x>>=3; return x;>>= operator (336>>3=42) 42
6_5_51_compound_assign_bitwise x=0xff; x&=0x7f; x^=0x55; x\|=0x00;&=, ^=, \|= 42
6_5_52_compound_assign_ptr int *p=a; p+=4; return *p;+= with pointer LHS 42
6_5_53_sizeof_vla_runtime int n=7; int a[n]; return (int)sizeof(a); — sizeof on VLA evaluated at runtime 28
6_5_54_sizeof_deref_ptr double *p=&x; return (int)sizeof(*p); — sizeof on dereferenced pointer; operand not evaluated 8
6_5_55_generic_default_branch _Generic((double)x, int: 0, default: 42) — falls through to default 42
6_5_56_compound_literal_struct struct S s = (struct S){.a=20,.b=22}; return s.a+s.b; — struct compound literal with designated init 42
6_5_57_unsigned_wrap_add unsigned x=0xFFFFFFFFU; x+=1; return (int)(x & 0xff); — unsigned addition wraps modulo 2^32 0
6_5_58_large_integer_immediates 64-bit boundary integer literals including INT64_MAX, top-bit unsigned, and all-ones materialize correctly 42
6_5_71_fp_unary_neg_zero -0.0f, -0.0, and unary - on float zero preserve the negative sign bit 0
6_5_65_file_scope_compound_literal RED static int *p = (int[]){42}; return p[0]; — file-scope compound literal has static storage duration 42
6_5_2_5_01_compound_literal_flat_struct RED (struct O){1,2,39} initializes nested struct members without inner braces 42
6_5_2_5_02_compound_literal_designated_continue RED (struct S){.a[1]=20,22,0} continues from the next subobject after a designator 42
6_5_3_4_04_sizeof_vla_param_row sizeof(a[0]) where a is an adjusted int a[n][m] parameter is evaluated at runtime 42
6_5_6_01_ptr_diff_assign_to_long long d = p - q; — pointer subtraction yields ptrdiff_t and is assignable to a wider integer without a cast 42

§6.5.2.2 Aggregate function arguments

Aggregate-by-value argument passing. The classification boundary on all three ABIs is 16 bytes: aggregates ≤16B go through ABI_ARG_DIRECT in 1 or 2 GPRs, larger ones through ABI_ARG_INDIRECT with a caller-side copy (BYVAL). Each row exercises one cell of the (1-reg / 2-reg / copy) × (homogeneous / mixed-field) matrix.

Case Status Body Expected
6_5_2_2_01_struct_param_1reg struct S{int a,b;}; int take(struct S s){return s.a+s.b;} — 8-byte struct, 1-part DIRECT 42
6_5_2_2_02_struct_param_2reg struct S{long a,b;}; long take(struct S s){return s.a+s.b;} — 16-byte struct, 2-part DIRECT 42
6_5_2_2_03_struct_param_2reg_mixed struct S{int a,b,c,d;}; — 16-byte struct of four ints; 2-part DIRECT with sub-8B chunking 42
6_5_2_2_04_struct_param_large struct S{int a[8];}; — 32-byte struct, INDIRECT/BYVAL caller copy 42
6_5_2_2_05_struct_param_with_scalars int take(int pre, struct S s, int post) — 2-reg struct between scalar args; arg-cursor accounting 42

§6.6 Constant expressions

Case Status Body Expected
6_6_01_enum_const enum { K = 42 }; return K; 42
6_6_02_const_expr_init int x = 1+2*3; return x; 7
6_6_03_array_size_const int a[3+4] = {0}; return (int)sizeof a / (int)sizeof a[0]; 7
6_6_04_alignof_array_size int a[_Alignof(long long)]; return (int)sizeof(a)/sizeof(a[0]);_Alignof in array-size constant 8
6_6_05_addr_const_static_init full TU: static int g=7; static int *p=&g; ...return *p*6; — address constant in static initializer 42
6_6_06_addr_const_arith_init full TU: static int arr[4]={0,0,0,42}; static int *p=arr+3; ...return *p; — address constant + ICE in static initializer 42
6_6_07_enum_array_bound file scope: typedef enum {A,B,C,N} E; static const int marks[N]={10,12,20}; — enum constant as array bound 42
6_6_08_func_addr_static_init static int helper(int x){return x;} + static const FN g = helper; — function designator as static-init address constant (no &) 42
6_6_09_func_addr_array_static static const FN ops[2] = {add1, dbl}; — array of function-pointer static-init constants 42
6_6_10_logical_cond_const logical && / || and ?: in integer constant expressions 42

§6.7 Declarations

Case Status Body Expected
6_7_01_typedef typedef int I; I x = 42; return x; 42
6_7_02_static_local static int s = 42; return s; 42
6_7_03_static_global static int g = 42; int test_main(void){return g;} 42
6_7_04_extern_resolved extern int g; int g = 42; return g; 42
6_7_05_const_qualifier const int c = 42; return c; 42
6_7_06_struct_basic struct S { int a, b; } s = {10, 32}; return s.a + s.b; 42
6_7_07_union_basic union U { int i; char c[4]; } u; u.i = 42; return u.i; 42
6_7_08_enum_basic enum E { A = 40, B }; return B + 1; 42
6_7_09_alignof return (int)_Alignof(double); 8
6_5_3_4_01_gnu_alignof_alias return (int)__alignof__(double) * 5 + 2; — GNU __alignof__ is recognized as an alias for _Alignof 42

§6.7.1 Storage-class specifiers

static/extern/typedef are exercised by 6_7_016_7_04; rows here cover register and other specifier interactions.

Case Status Body Expected
6_7_1_01_register_sizeof register int x=42; return (int)sizeof(x)>0?x:0;sizeof is legal on a register variable 42
6_7_1_02_register_multi_decl register int x=40, y=2; return x+y; — multi-declarator with register 42
6_7_1_03_thread_local_basic _Thread_local int x=42; return x;_Thread_local accepted as a storage-class specifier on a file-scope object 42
6_7_file_scope_register register int x; return sizeof(x)==sizeof(int)?42:1; — GNU-compatible file-scope register declaration accepted 42

§6.7.2 Type specifiers

Each integer/floating type the runtime can return through test_main. Conversion behavior between types lives in §6.3; rows here only check that the type round-trips through a declaration and back to int.

Case Status Body Expected
6_7_2_01_short short x = 42; return x; 42
6_7_2_02_long long x = 42L; return (int)x; 42
6_7_2_03_long_long long long x = 42LL; return (int)x; 42
6_7_2_04_unsigned unsigned x = 42U; return (int)x; 42
6_7_2_01b_unsigned_long_long unsigned long long x = 42ULL; return (int)x;unsigned long long multiset 42
6_7_2_05_signed_char signed char c = 42; return c; 42
6_7_2_06_unsigned_char unsigned char c = 200; return c; 200
6_7_2_07_unsigned_short unsigned short s = 42; return s; 42
6_7_2_08_unsigned_long unsigned long x = 42UL; return (int)x; 42
6_7_2_09_bool _Bool b = 5; return b ? 42 : 0; 42
6_7_2_10_float float f = 42.0f; return (int)f; 42
6_7_2_11_double double d = 42.5; return (int)d; 42
6_7_2_12_long_double · long double d = 42.0L; return (int)d; 42
6_7_2_13_complex (deferred) _Complex is optional in C11

§6.7.2.1 Structure and union details

Edge cases beyond the basic struct/union rows — bitfields, anonymous members, self-reference through pointers, and forward declarations.

Case Status Body Expected
6_7_2_1_01_bitfield struct {unsigned a:5, b:3;} s={2,5}; return s.b*8 + s.a; 42
6_7_2_1_02_anon_struct struct S{int x; struct{int y;};} s={0,42}; return s.y; 42
6_7_2_1_03_anon_union struct S{int x; union{int a,b;};} s; s.x=0; s.a=42; return s.b; 42
6_7_2_1_04_self_ref struct N{int v; struct N *next;}; struct N b={42,0}, a={0,&b}; return a.next->v; 42
6_7_2_1_05_forward_tag struct S; struct S *p; struct S{int v;}; struct S s={42}; p=&s; return p->v; 42
6_7_2_1_06_flex_array (deferred) flexible array members need allocator support
6_7_2_1_07_signed_bitfield struct {signed int s:8;} b={-1}; return (b.s<0)?42:0; — signed bitfield sign extension 42
6_7_2_1_08_zero_width_bitfield struct {unsigned a:4; unsigned:0; unsigned b:4;} — zero-width bitfield forces next field into new storage unit 42
6_7_2_1_09_bool_bitfield struct {_Bool b:1;} s; s.b=1; return s.b?42:0;_Bool bitfield 42
6_7_2_1_10_static_bitfield_pack static struct {unsigned a:5; unsigned b:3;} g={2,5}; return g.b*8+g.a; — static packed bit-field initializer 42

§6.7.2.2 Enumeration specifiers

Case Status Body Expected
6_7_2_2_01_enum_restart enum C{X=20, Y, Z=20, W}; return Y+W; — auto-increment restarts after explicit =; duplicate values allowed (Y=21, W=21) 42

§6.7.2.3 Tags

Case Status Body Expected
6_7_2_3_01_tag_inner_scope outer struct S{int v;}; { struct S{int v;}; struct S s={42}; ...} — inner-scope tag shadows outer; distinct types 42

§6.7.3 Type qualifiers

const is covered by 6_7_05_const_qualifier; rows here cover the remaining qualifier forms and pointer-qualifier interactions.

Case Status Body Expected
6_7_3_01_volatile volatile int x = 42; return x; 42
6_7_3_02_restrict_param helper int rd(int *restrict p){return *p;} + caller 42
6_7_3_03_const_pointer int x=42; int *const p=&x; return *p; 42
6_7_3_04_ptr_to_const const int x=42; const int *p=&x; return *p; 42
6_7_3_05_atomic _Atomic int x = 42; return x; 42
6_7_3_06_repeated_const const const int x = 42; return x; — repeated qualifier is idempotent 42
6_7_3_07_const_array_typedef typedef int A[3]; const A a={10,20,12}; return a[0]+a[1]+a[2];const outside typedef makes elements const 42

§6.7.4 Function specifiers

Case Status Body Expected
6_7_4_01_inline static inline int id(int x){return x;} + return id(42); 42
6_7_4_02_noreturn full TU: _Noreturn void die(void){for(;;);} int test_main(void){return 42;} (declared, not called) 42
6_7_4_03_extern_inline static inline int add1(int x){return x+1;} return add1(41); — inline definition (note: clang extern inline requires non-static external def; case uses static inline form to avoid ODR hazard) 42
6_7_4_04_repeated_inline static inline inline int id(int x){return x;} — repeated function specifier is idempotent 42

§6.7.5 Alignment specifier

Case Status Body Expected
6_7_5_01_alignas_obj _Alignas(16) static char buf[16]; return (((unsigned long)buf)&15) ? 0 : 42; 42
6_7_5_02_alignas_type _Alignas(double) static char buf[8]; return (int)_Alignof(double) * 5 + 2; 42
6_7_5_03_alignas_zero · _Alignas(0) static int x = 42;_Alignas(0) has no effect; object gets natural alignment 42
6_7_5_04_alignas_multi _Alignas(16) _Alignas(8) static char buf[16]; — strictest _Alignas wins 42

§6.7.6 Declarators

Pointer/array/function declarator combinations beyond the basic forms already exercised in §6.5 and §6.7.

Case Status Body Expected
6_7_6_01_ptr_to_ptr int x=42; int *p=&x; int **pp=&p; return **pp; 42
6_7_6_02_array_2d int a[2][3]={{0,0,0},{0,0,42}}; return a[1][2]; 42
6_7_6_03_array_of_ptr int x=42; int *a[2]={0,&x}; return *a[1]; 42
6_7_6_04_funcptr_decl int id(int x){return x;} int (*fp)(int)=id; return fp(42); 42
6_7_6_05_funcptr_returning_ptr helper returns int*; int *(*fp)(int*)=...; return *fp(&x); 42
6_7_6_06_array_static_n helper int rd(int p[static 3]){return p[2];}; int a[3]={0,0,42}; return rd(a); 42
6_7_6_07_vla_local int n=7; int a[n]; for(int i=0;i<n;i++) a[i]=i*7; return a[n-1]; 42
6_7_6_08_variadic_decl helper int sum(int n, ...) summing two ints; sum(2, 20, 22) 42
6_7_6_09_ptr_to_array int b[3]={0,0,42}; int (*pa)[3]=&b; return (*pa)[2]; — pointer-to-array declarator 42
6_7_6_10_array_of_funcptr int (*ops[2])(int)={add1,sub1}; return ops[0](ops[1](42)); — block-scope array of function pointers 42
6_7_6_11_func_returning_funcptr typedef int (*FP)(int); FP getfp(void){return id;} return getfp()(42); — function returning function pointer 42
6_7_6_12_vla_param int sum_vla(int n, int a[n]){...} — VLA dimension from earlier param; param adjusted to pointer 42
6_7_6_13_star_in_proto int total(int n, int a[*]); int total(int n, int a[n]){...}[*] in non-definition prototype 42
6_7_6_14_func_param_adjust int apply(int f(int), int x){return f(x);} — function parameter adjusted to pointer-to-function 42
6_7_6_15_multidim_vla_local RED int a[n][m]; a[n-1][m-1]=42; return a[5][6]; — multiple VLA dimensions in one declarator 42
6_7_6_16_vla_param_2d int a[n][m] parameter passed a 2D array; runtime stride must use m 42
6_7_6_17_vla_param_3d int a[n][m][k] parameter passed a 3D array; nested runtime strides must compose 42
6_7_6_18_file_scope_array_bound_paren static int marks[(2+5)] = {...}; — parenthesized integer constant expression in a file-scope array bound 42
6_7_6_19_paren_declarator_name int (helper)(int x){...} and (helper)(42) — the C grammar lists '(' declarator ')' as a direct-declarator; lua / glibc headers wrap public names in parens to defeat macro expansion 42
6_7_6_20_func_returning_funcptr_no_typedef int (*pick(int x))(void){...} — function declarator with an inline function-pointer return type (the classic signal() shape, used by sqlite VFS xDlSym). 6_7_6_11 covers the typedef'd form; this row pins the inline declarator 42

§6.7.7 Type names

Case Status Body Expected
6_7_7_01_abstract_ptr_array_cast ((int(*)[3])v)[0][2] — abstract declarator int(*)[3] in cast 42

§6.7.8 Type definitions

6_7_01_typedef covers the simplest case (typedef int I); rows here cover compound typedef targets.

Case Status Body Expected
6_7_8_01_typedef_struct typedef struct{int v;} S; S s={42}; return s.v; 42
6_7_8_02_typedef_funcptr typedef int (*FP)(int); int id(int x){return x;} FP f=id; return f(42); 42
6_7_8_03_typedef_array typedef int A[3]; A a={0,0,42}; return a[2]; 42
6_7_8_04_typedef_qualified typedef const int CI; CI x = 42; return x; 42
6_7_8_05_typedef_vla_size_fixed · int f(int n){typedef int B[n]; n+=10; B a; ...} — VLA typedef captures size at definition 36
6_7_8_06_typedef_multi_decl typedef int TWICE, (*PFUNC)(int); — multiple declarators in one typedef 42

§6.7.9 Initialization

Case Status Body Expected
6_7_9_01_scalar_init int x = 42; return x; 42
6_7_9_02_array_brace int a[3] = {10, 20, 12}; return a[0]+a[1]+a[2]; 42
6_7_9_03_partial_zero int a[5] = {42}; return a[0] + a[4]; 42
6_7_9_04_designated int a[5] = {[2] = 42}; return a[2]; 42
6_7_9_05_struct_init struct S {int a,b;} s={40,2}; return s.a+s.b; 42
6_7_9_06_string_init char s[] = "hi"; return s[0]+s[1]+s[2]; 'h'+'i'
6_7_9_07_designated_struct struct S{int a,b,c;} s={.b=42}; return s.b; 42
6_7_9_08_nested_designated int a[2][3] = {[1][2] = 42}; return a[1][2]; 42
6_7_9_09_struct_in_array struct P{int x,y;} a[2] = {{0,0},{0,42}}; return a[1].y; 42
6_7_9_10_zero_init_static full TU: static int g[3]; int test_main(void){return g[0]+g[1]+g[2]+42;} 42
6_7_9_11_array_size_from_init int x[] = {10, 12, 20}; return x[0]+x[1]+x[2]; — array of unknown size; size from init list 42
6_7_9_12_designator_override int a[3] = {[1]=99, [1]=42, [0]=0}; — later designator overrides earlier 42
6_7_9_13_string_init_fixed_larger char s[6] = "hi"; — char array larger than string literal; excess elements zero-filled (sum = 'h'+'i'+0+0+0+0) 209
6_7_9_14_struct_copy_init struct S src={20,22}; struct S dst=src; return dst.a+dst.b; — struct init from compatible struct expression 42
6_7_9_15_union_designated_nonfirst union U{int a; int b;} u={.b=42}; return u.b; — designated init of non-first union member 42
6_7_9_16_enum_designator enum {X=2}; int a[4]={[X]=42}; return a[X]; — enum constant as array designator 42
6_7_9_17_inconsistent_bracket_init struct T{int a[2];int b;} w[2]={{1},2}; — flat init consumed into subaggregate without inner braces 3
6_7_9_18_static_init_string_ptr static const S g = { .s = "hi" }; — string literal as address constant in pointer-slot static init 209
6_7_9_19_static_init_string_array static const char* const names[2] = {"a","b"}; — array-of-pointer static init with string literals 42
6_7_9_20_array_of_struct_with_array_field static const S t[] = { {10u,{1,2}}, {15u,{3,11}} }; — file-scope incomplete array of struct with trailing fixed-size array field 42
6_7_9_21_array_of_struct_size_from_init static const S t[] = { {10,12}, {7,13} }; — file-scope incomplete-array-of-struct sized from init list 44
6_7_9_22_static_union_designated_nonfirst static union U{int a; int b;} g={.b=42}; return g.b; — static-storage union designated init 42
6_7_9_23_static_ptr_null_const_expr static int* p = 1 - 1; return p == 0 ? 42 : 0; — null pointer constant via integer constant expression 42
6_7_9_24_flat_array_init RED int a[2][2] = {1,2,3,36}; — braces may be elided for nested array initialization 42
6_7_9_25_flat_struct_init RED struct O o = {1,2,39}; — braces may be elided for nested struct initialization 42
6_7_9_26_designated_continue_subobject RED struct S s = {.a[1]=20,22,0}; — initializer continues after the designated subobject 42
6_7_9_27_static_flat_array_init RED file-scope static int a[2][2] = {1,2,3,36}; 42
6_7_9_28_static_flat_struct_init RED file-scope static struct O o = {1,2,39}; 42
6_7_9_29_unknown_bound_nested_init RED int a[][2] = {1,2,3,36}; — unknown outer bound is completed from a flat nested initializer 42
6_7_9_30_static_init_neg_float static const double tab[2] = { -1.0, 43.0 }; — static initializer of arithmetic type permits unary - on a floating constant (§6.6 arithmetic constant expression) 42

§6.7.10 Static assertions

Case Status Body Expected
6_7_10_01_static_assert_pass _Static_assert(sizeof(int) >= 2, "wide int"); return 42; 42
6_7_10_02_static_assert_const _Static_assert(1+1 == 2, "math"); return 42; 42
6_7_10_03_static_assert_file_scope full TU: _Static_assert(sizeof(long)>=4,"long"); at file scope 42

§6.8 Statements

Case Status Body Expected
6_8_01_if_else int x; if (1) x=7; else x=99; return x; 7
6_8_02_while_sum sum 0..9 with while 45
6_8_03_for_sum sum 1..10 with for 55
6_8_04_do_while int i=0; do { i=42; } while (0); return i; 42
6_8_05_break for (i=0;;i++) if (i==42) break; return i; 42
6_8_06_continue sum of evens in [0,20) via continue 90
6_8_07_switch_case three-arm switch returns 42 on case 2 42
6_8_08_switch_fallthrough case 1: r+=10; case 2: r+=20; on input 1 30
6_8_09_switch_default unmatched switch hits default 7
6_8_10_goto_forward goto L; r=99; L: return 42; 42
6_8_11_goto_backward counter loop built with goto 10
6_8_12_block_scope inner { int x=42; } shadows outer 42
6_8_13_compound_decl_mix declarations interleaved with statements (C99) 42
6_8_14_return_void void f(void){return;}; f(); return 42; 42
6_8_15_null_statement for (int i=0;i<42;i++) ; return i; 42
6_8_16_dangling_else if (1) if (0) r=1; else r=42; — else binds to inner if 42
6_8_17_switch_char_ctrl switch on char c=2; matches case 2 42
6_8_18_switch_no_match_no_default switch(99) with no matching case and no default; r unchanged 7
6_8_19_switch_nested_dup_case nested switch with case 1/case 2 in inner — inner case 2 wins 42
6_8_20_switch_hidden_scope int x=99; initializer jumped over by switch; case 1: r=42 still reached 42
6_8_21_for_infinite_break for(;;){ i++; if(i==42) break; } — infinite loop terminated by break 42
6_8_23_continue_do_while continue in do..while restarts the loop; sum of odd i in [1,10] = 1+3+5+7+9 25
6_8_24_break_switch_in_loop break inside switch inside for-loop exits switch, not loop; loop reaches case 3 3
6_8_25_continue_inside_switch continue inside switch's case 0: continues the enclosing for-loop; s=1+3=4 4
6_8_26_goto_into_nested_block goto inner; where label is inside a nested block 42
6_8_27_label_on_null_stmt end: ; — label applied to a null statement 42
6_8_28_return_narrow_convert unsigned char narrow(int x){return x;} — 298 & 0xff = 42; narrowing on return 42

GNU labels as values (computed goto)

name tier description exit
gnu_labels_as_values_threaded direct-threaded bytecode interpreter: function-local static void *const tab[] = {&&op,...} + goto *tab[*pc++]; (3+4)*5 35
gnu_label_addr_basic void *p = &&done; goto *p; — take a label address and branch to it 7
gnu_label_addr_runtime_table automatic void *tab[] = {&&even, &&odd}; goto *tab[n&1]; (runtime array of label addresses) 20
gnu_label_addr_mixed_goto mixes named goto with computed goto * to address-taken labels 11
gnu_label_addr_compare label addresses are comparable: if (next == &&op_halt) where op_halt is also a computed-goto target 7

Negative cases (cases_err/): gnu_label_addr_file_scope (&& outside a function), gnu_computed_goto_no_targets (goto *p with no address-taken label), gnu_computed_goto_non_pointer (goto * on a non-pointer), gnu_label_addr_after_computed_goto (taking a label address after the first computed goto), gnu_label_addr_undefined (&& of an undefined label).

§6.8.6.4 Aggregate return values

Aggregate-by-value return. Mirrors §6.5.2.2: ≤16B uses ABI_ARG_DIRECT in 1 or 2 return registers; larger uses ABI_ARG_INDIRECT with the caller passing a hidden destination pointer (sret) that the callee memcpys into before ret.

Case Status Body Expected
6_8_6_4_01_struct_return_1reg struct S{int a,b;}; struct S mk(void){...} — 8-byte struct returned in one reg 42
6_8_6_4_02_struct_return_2reg struct S{long a,b;}; struct S mk(void){...} — 16-byte struct returned across two regs 42
6_8_6_4_03_struct_return_large struct S{int a[8];}; struct S mk(void){...} — 32-byte struct returned via sret pointer 42
6_8_6_4_04_struct_return_call_chain take(mk()) — 2-reg return immediately fed as 2-reg byval arg with no named local 42

§6.9 External definitions

Case Status Body Expected
6_9_01_two_functions helper + caller in one TU 42
6_9_02_recursive_function factorial(5) 120
6_9_03_tentative_def file-scope int g; (tentative) + use 0
6_9_04_static_func static int helper(...) + caller 42
6_9_05_proto_then_def forward declaration before body 42
6_9_06_variadic_func sum(int n, ...) over va_arg; sum(2,20,22) (paired with builtin_03) 42
6_9_07_global_const full TU: const int g = 42; int test_main(void){return g;} 42
6_9_08_global_struct_init full TU: struct S{int v;} g={42}; int test_main(void){return g.v;} 42
6_9_09_static_data_array full TU: static int g[3] = {0, 0, 42}; int test_main(void){return g[2];} 42
6_9_10_kr_function_def (deferred) K&R-style definitions are C90 carryover; revisit if needed
6_9_11_tentative_multi full TU: int g; int g; — two tentative defs merge; return g+42 42
6_9_12_tentative_incomplete_array full TU: int arr[]; int arr[3]; — tentative + completing decl; return arr[0]+arr[1]+arr[2]+42 42
6_9_13_extern_func_def full TU: extern int helper(int x){return x+1;} — extern on a definition; helper(41) 42
6_9_14_kr_function_def_params RED old-style function definition with declaration-list int add(a,b) int a; int b; 42
6_9_15_kr_function_def_promoted_char RED old-style definition with promoted char parameter declaration 42
6_9_16_block_scope_func_decl block-scope int helper(void); has external linkage and calls the later file-scope definition 42

§6.10 Preprocessing directives

Most preprocessor coverage lives under test/pp/; rows here only exist when a directive interacts with the parse-runner's end-to-end pipeline in a way test/pp/ cannot catch on its own.

Case Status Body Expected
6_10_warning_directive #warning "..." followed by a valid TU — non-fatal diagnostic, parsing continues 42

Builtins

The freestanding runtime advertises a handful of __builtin_* entries (see doc/builtins.md). Cases here verify the parser routes them through cg's intrinsic / asm machinery rather than treating them as ordinary calls.

Case Status Body Expected
builtin_01_alloca int *p = (int *)__builtin_alloca(4); *p=42; return *p; 42
builtin_02_expect if (__builtin_expect(1, 1)) return 42; return 0; 42
builtin_03_va_list uses __builtin_va_start/__builtin_va_arg/__builtin_va_end summing three ints 42
builtin_04_offsetof struct S {int a, b;}; return (int)__builtin_offsetof(struct S, b) * 10 + 2; 42
builtin_05_va_copy walks varargs twice via __builtin_va_copy 42
builtin_06_atomic_load __atomic_load_n(&x, __ATOMIC_RELAXED) — RELAXED-ordered load via LDUR 42
builtin_07_atomic_fetch_add __atomic_fetch_add(&x, 2, __ATOMIC_RELAXED) — LL/SC RMW loop 42
builtin_08_atomic_store_n __atomic_store_n(&x, 42, __ATOMIC_RELEASE) — RELEASE store via STLR 42
builtin_09_atomic_exchange_n __atomic_exchange_n(&x, 99, __ATOMIC_SEQ_CST) — RMW XCHG, returns prior 42
builtin_10_atomic_fetch_sub __atomic_fetch_sub with ACQ_REL — LDAXR/STLXR loop 42
builtin_11_atomic_fetch_and __atomic_fetch_and with RELAXED — RMW AND combine 42
builtin_12_atomic_fetch_or __atomic_fetch_or with ACQUIRE — LDAXR/STXR loop 42
builtin_13_atomic_fetch_xor __atomic_fetch_xor with SEQ_CST — RMW EOR combine 42
builtin_14_atomic_long 8-byte atomic on longsf=1 path through ldxr/stxr 42
builtin_15_atomic_pointer atomic load of a pointer-typed variable; result deref'd through array 42
builtin_16_atomic_thread_fence __atomic_thread_fence(__ATOMIC_SEQ_CST) — emits DMB ISH 42
builtin_17_atomic_cas_success __atomic_compare_exchange_n matching path: stores desired, returns 1 42
builtin_18_atomic_cas_failure CAS mismatch: writes prior to *expected, returns 0 42
builtin_19_atomic_cas_loop lock-free increment via CAS retry loop (ACQ_REL/ACQUIRE pair) 42
builtin_20_ctz __builtin_ctz(1u<<5) + 37 — count trailing zeros, low-bit case 42
builtin_21_ctz_high __builtin_ctz(0x80000000u) - 31 + 42 — high-bit case (31 trailing zeros) 42
builtin_22_ctz_long_widths __builtin_ctzl + __builtin_ctzll; operand type selects intrinsic width 42
builtin_23_atomic_long_literal_convert store/RMW integer literals converted to unsigned long atomic object type 42
builtin_24_atomic_lock_free target-aware lock-free folding through if, &&, and ||; dead 16-byte atomic arms suppress codegen 42
builtin_25_atomic_fetch_nand __atomic_fetch_nand lowers to atomic NAND RMW 42
builtin_26_sadd_overflow signed/unsigned typed overflow builtins store result and return overflow flag 42

Variadic coverage

Extra rows pinning down the per-class routing on AAPCS64 — the GP and FP save areas are independent and each va_arg walks its class's cursor, so mixed and class-only sequences both need direct exercise.

Case Status Body Expected
variadic_01_zero_args sum(0) — no ... args; tests that va_start on an empty trailing list still produces a usable cursor 42
variadic_02_many_ints 12 variadic ints — exhausts the GP save area (x1..x7) and forces the va_arg stack-overflow path 42
variadic_03_long va_arg(ap, long) — 8-byte int via the GP save area 42
variadic_04_pointer passes int* through ... and reads them back via va_arg(ap, int*) 42
variadic_05_double three doubles through ... — exercises the FP save area v0..v7 and 16-byte stride 42
variadic_06_mixed interleaved int/double ...; per-class cursors run independently 42
variadic_07_nested_call va_copy to a separate cursor that's passed by va_list* to a helper, then the original cursor walked again 42

Negative cases (cases_err/)

Case Status Surface Notes
6_5_undeclared · identifier resolution return q;
6_5_addr_of_bitfield RED lvalue / bit-field address of a bit-field must be rejected; currently accepted
6_5_cast_scalar_from_struct RED cast constraints casting a struct expression to int must be rejected; currently accepted
6_5_cond_incompatible_ptr RED conditional operator int * vs double * arms are incompatible; currently accepted
6_5_lvalue_required · assignment LHS 1 = 2;
6_5_lvalue_array_assign assignment LHS assigning to an array object
6_5_pointer_add_pointer RED pointer arithmetic p + q for two pointers must be rejected; currently accepted
6_5_rel_incompatible_ptr RED pointer comparison relational compare of incompatible pointer types; currently accepted
6_5_scalar_required_if RED scalar expression struct expression used as if condition; currently accepted
6_5_sizeof_bitfield RED sizeof sizeof cannot be applied to a bit-field; currently accepted
6_5_sizeof_function sizeof sizeof cannot be applied to a function designator
6_5_type_mismatch · implicit conversion assigning int* to int
6_5_address_of_register RED register storage taking the address of a register object must be rejected; currently accepted
6_5_void_pointer_arith RED pointer arithmetic arithmetic on void * is not C11; currently accepted
6_6_array_bound_float RED integer constant expr floating array bound must be rejected; currently accepted
6_6_static_init_nonconstant static initializer file-scope static initializer from non-constant object
6_7_redefinition · linkage / scope two int x = … at file scope
6_8_break_outside_loop · break/continue scope break; outside iteration
6_9_redefinition_function · external definition two definitions of f
6_5_member_not_in_struct · member access s.zzz for unknown field
6_5_call_non_function · call expression int x; x();
6_5_arrow_on_non_pointer · member access struct S s; s->v;
6_5_sizeof_incomplete · sizeof struct S; return sizeof(struct S);
6_7_2_storage_class_combo · declaration static extern int x;
6_7_2_tag_wrong_kind tag redeclaring a struct tag as a union in the same scope
6_7_2_1_bitfield_bad_type RED bitfield float bit-field accepted pending extended-type policy
6_7_2_1_bitfield_named_zero_width bitfield named zero-width bit-field
6_7_2_1_bitfield_negative_width bitfield negative bit-field width
6_7_2_1_bitfield_nonconstant_width bitfield bit-field width that is not an integer constant expression
6_7_2_two_struct_defs · tag two struct S { ... }; definitions in same scope
6_7_2_1_bitfield_too_wide · bitfield unsigned a:33; exceeds underlying type
6_7_2_1_duplicate_member RED struct member duplicate member name in one struct; currently accepted
6_7_2_1_flex_array_not_last RED flexible array flexible array member not last; currently accepted
6_7_2_1_flex_array_only_member RED flexible array flexible array member in otherwise empty struct; currently accepted
6_7_2_1_member_static RED struct member specs storage-class specifier in struct member declaration; currently accepted
6_7_2_1_member_extern RED struct member specs storage-class specifier in struct member declaration; currently accepted
6_7_2_1_member_typedef RED struct member specs typedef in struct member declaration; currently accepted
6_7_2_1_member_thread_local RED struct member specs _Thread_local in struct member declaration; currently accepted
6_7_2_1_member_inline RED struct member specs inline in struct member declaration; currently accepted
6_7_2_1_member_noreturn RED struct member specs _Noreturn in struct member declaration; currently accepted
6_7_2_4_atomic_qualified_type RED _Atomic type specifier _Atomic(const int) violates C11 constraints; currently accepted
6_7_2_4_atomic_array_type RED _Atomic type specifier _Atomic(int[2]) violates C11 constraints; currently accepted
6_7_2_4_atomic_atomic_type RED _Atomic type specifier nested atomic type violates C11 constraints; currently accepted
6_7_2_void_object RED object type object declared with type void; currently accepted
6_7_3_const_assign · const violation const int x = 0; x = 1;
6_7_3_restrict_object RED qualifier constraints restrict used on a non-pointer object; currently accepted
6_7_4_inline_object RED function specifier inline used on an object declaration; currently accepted
6_7_4_noreturn_object RED function specifier _Noreturn used on an object declaration; currently accepted
6_7_5_alignas_weaker_than_natural RED alignment specifier nonzero _Alignas weaker than natural alignment; currently accepted
6_7_5_alignas_non_power_of_two RED alignment specifier invalid _Alignas(3); currently accepted
6_7_5_alignas_bitfield RED alignment specifier _Alignas applied to a bit-field; currently accepted
6_7_5_alignas_typedef RED alignment specifier _Alignas applied to a typedef declaration; currently accepted
6_7_5_alignas_function RED alignment specifier _Alignas applied to a function definition; currently accepted
6_7_6_param_auto RED parameter declaration non-register storage-class specifier on parameter; currently accepted
6_7_6_param_extern RED parameter declaration non-register storage-class specifier on parameter; currently accepted
6_7_6_param_typedef RED parameter declaration typedef storage-class specifier on parameter; currently accepted
6_7_6_param_thread_local RED parameter declaration _Thread_local storage-class specifier on parameter; currently accepted
6_7_6_static_param_scalar RED parameter declaration static on scalar parameter; currently accepted
6_7_6_function_returning_array function declarator function returning array
6_7_6_function_returning_function function declarator function returning function
6_7_6_variadic_not_last function declarator variadic marker not in final position
6_7_file_scope_auto RED storage class auto at file scope; currently accepted
6_7_storage_class_static_thread_local_function RED storage class _Thread_local on a function definition; currently accepted
6_7_thread_local_block_auto RED storage class block-scope _Thread_local without static/extern; currently accepted
6_7_thread_local_function RED storage class _Thread_local on a function definition; currently accepted
6_7_thread_local_typedef RED storage class _Thread_local in a typedef declaration; currently accepted
6_7_type_spec_bool_int RED declaration specifiers invalid _Bool int specifier combination; currently accepted
6_7_type_spec_char_int RED declaration specifiers invalid char int specifier combination; currently accepted
6_7_type_spec_float_double RED declaration specifiers invalid float double specifier combination; currently accepted
6_7_type_spec_long_float RED declaration specifiers invalid long float specifier combination; currently accepted
6_7_type_spec_short_char RED declaration specifiers invalid short char specifier combination; currently accepted
6_7_type_spec_signed_double RED declaration specifiers invalid signed double specifier combination; currently accepted
6_7_type_spec_too_many_longs RED declaration specifiers invalid long long long specifier combination; currently accepted
6_7_type_spec_unsigned_double RED declaration specifiers invalid unsigned double specifier combination; currently accepted
6_7_9_excess_scalar_init initializer too many initializers for scalar object
6_7_9_invalid_array_designator initializer array designator index that is not an integer constant expression
6_7_9_invalid_struct_designator initializer designator names no member of the target struct
6_7_9_invalid_union_designator initializer designator names no member of the target union
6_7_10_static_assert_fail static assertion _Static_assert(0, "fail");
6_8_case_outside_switch · switch scope case 1: outside any switch
6_8_continue_outside_loop · iteration scope continue; outside iteration
6_8_default_outside_switch · switch scope default: outside switch
6_8_duplicate_case · switch two case 1: in same switch
6_8_duplicate_default · switch two default: labels in same switch
6_8_goto_undefined_label · goto goto missing; with no matching label
6_8_goto_into_vla_scope RED goto goto into scope of a variably modified object; currently accepted
6_8_switch_float RED switch floating controlling expression in switch; currently accepted
6_8_duplicate_label · label two L: in the same function
6_9_void_param_with_other · function declarator int f(void, int);

Multi-TU (deferred)

Multi-TU cases live under cases/<name>/{a.c,b.c} (test/link convention) and exercise inter-TU resolution. Deferred until the single-TU corpus is green; the harness already builds an ObjBuilder* per TU, so wiring is mainly extending run.sh to compile each file in a case directory and hand both objects to link_add_obj.

Non-goals