boot2

Playing with the boostrap
git clone https://git.ryansepassi.com/git/boot2.git
Log | Files | Refs | README

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 }