126-offsetof-const.c (2897B)
1 /* The offsetof idiom in static initializers, as used by tcc.c's 2 * options_W[] / options_f[] / options_m[] tables (line 18026 of 3 * tcc.flat.c): 4 * 5 * ((size_t) &((T *)0)->FIELD) 6 * 7 * Outer cast to integer type, address-of a member access through a 8 * null pointer of the parent struct type. The expression is evaluated 9 * at translation time and equals offsetof(T, FIELD). Required only at 10 * static-initializer / const-expr granularity; runtime address-of is 11 * already supported. 12 * 13 * Also exercises the same form through anonymous union members, since 14 * struct Sym in tcc.c relies on that combination. 15 */ 16 17 struct Inner { 18 int a; 19 int b; 20 int c; 21 }; 22 23 struct Outer { 24 int first; 25 long second; 26 int third; 27 union { 28 int anon_x; 29 long anon_y; 30 }; 31 int trailing; 32 }; 33 34 struct Flag { unsigned long off; int mask; const char *name; }; 35 36 /* File-scope static array — the precise tcc.c shape. */ 37 static const struct Flag options[] = { 38 { ((unsigned long) &((struct Outer *)0)->first), 0, "first" }, 39 { ((unsigned long) &((struct Outer *)0)->second), 1, "second" }, 40 { ((unsigned long) &((struct Outer *)0)->third), 2, "third" }, 41 { ((unsigned long) &((struct Outer *)0)->anon_x), 3, "anon_x" }, 42 { ((unsigned long) &((struct Outer *)0)->anon_y), 4, "anon_y" }, 43 { ((unsigned long) &((struct Outer *)0)->trailing), 5, "trailing" }, 44 { 0, 0, 0 } 45 }; 46 47 /* Plain scalar inits to confirm the cast on its own works. */ 48 static unsigned long off_a = (unsigned long) &((struct Inner *)0)->a; 49 static unsigned long off_b = (unsigned long) &((struct Inner *)0)->b; 50 static unsigned long off_c = (unsigned long) &((struct Inner *)0)->c; 51 52 /* Designator using `.` rather than `->`, taken via dereference. */ 53 static unsigned long off_dot_b = (unsigned long) &(*(struct Inner *)0).b; 54 55 int main(int argc, char **argv) { 56 struct Outer o; 57 char *base = (char *) &o; 58 59 if (off_a != 0) return 1; 60 if (off_b != sizeof(int)) return 2; 61 if (off_c != sizeof(int) * 2) return 3; 62 if (off_dot_b != sizeof(int)) return 4; 63 64 if (options[0].off != (unsigned long)((char *)&o.first - base)) return 10; 65 if (options[1].off != (unsigned long)((char *)&o.second - base)) return 11; 66 if (options[2].off != (unsigned long)((char *)&o.third - base)) return 12; 67 if (options[3].off != (unsigned long)((char *)&o.anon_x - base)) return 13; 68 if (options[4].off != (unsigned long)((char *)&o.anon_y - base)) return 14; 69 if (options[5].off != (unsigned long)((char *)&o.trailing - base)) return 15; 70 71 if (options[0].mask != 0) return 20; 72 if (options[5].mask != 5) return 21; 73 if (options[6].off != 0 || options[6].mask != 0 || options[6].name != 0) return 22; 74 75 return 0; 76 }