| @@ -3181,6 +3181,22 @@ static void parse_attribute(AttributeDef *ad) · 3180 unmodified lines |
| 3181 | } | 3181 | } |
| 3182 | } | 3182 | } |
| 3183 | | 3183 | |
| | 3184 | static Sym * find_field (CType *type, int v) |
| | 3185 | { |
| | 3186 | Sym *s = type->ref; |
| | 3187 | v |= SYM_FIELD; |
| | 3188 | while ((s = s->next) != NULL) { |
| | 3189 | if ((s->v & SYM_FIELD) && (s->v & ~SYM_FIELD) >= SYM_FIRST_ANOM) { |
| | 3190 | Sym *ret = find_field (&s->type, v); |
| | 3191 | if (ret) |
| | 3192 | return ret; |
| | 3193 | } |
| | 3194 | if (s->v == v) |
| | 3195 | break; |
| | 3196 | } |
| | 3197 | return s; |
| | 3198 | } |
| | 3199 | |
| 3184 | /* enum/struct/union declaration. u is either VT_ENUM or VT_STRUCT */ | 3200 | /* enum/struct/union declaration. u is either VT_ENUM or VT_STRUCT */ |
| 3185 | static void struct_decl(CType *type, AttributeDef *ad, int u) | 3201 | static void struct_decl(CType *type, AttributeDef *ad, int u) |
| 3186 | { | 3202 | { |
| @@ -3404,13 +3420,40 @@ static void struct_decl(CType *type, AttributeDef *ad, int u) · 217 unmodified lines |
| 3404 | #endif | 3420 | #endif |
| 3405 | } | 3421 | } |
| 3406 | if (v == 0 && (type1.t & VT_BTYPE) == VT_STRUCT) { | 3422 | if (v == 0 && (type1.t & VT_BTYPE) == VT_STRUCT) { |
| | 3423 | /* An anonymous struct/union. Adjust member offsets |
| | 3424 | to reflect the real offset of our containing struct. |
| | 3425 | Also set the offset of this anon member inside |
| | 3426 | the outer struct to be zero. Via this it |
| | 3427 | works when accessing the field offset directly |
| | 3428 | (from base object), as well as when recursing |
| | 3429 | members in initializer handling. */ |
| | 3430 | int v2 = btype.ref->v; |
| | 3431 | if (!(v2 & SYM_FIELD) && |
| | 3432 | (v2 & ~SYM_STRUCT) < SYM_FIRST_ANOM) { |
| | 3433 | Sym **pps; |
| | 3434 | /* This happens only with MS extensions. The |
| | 3435 | anon member has a named struct type, so it |
| | 3436 | potentially is shared with other references. |
| | 3437 | We need to unshare members so we can modify |
| | 3438 | them. */ |
| | 3439 | ass = type1.ref; |
| | 3440 | type1.ref = sym_push(anon_sym++ | SYM_FIELD, |
| | 3441 | &type1.ref->type, 0, |
| | 3442 | type1.ref->c); |
| | 3443 | pps = &type1.ref->next; |
| | 3444 | while ((ass = ass->next) != NULL) { |
| | 3445 | *pps = sym_push(ass->v, &ass->type, 0, ass->c); |
| | 3446 | pps = &((*pps)->next); |
| | 3447 | } |
| | 3448 | *pps = NULL; |
| | 3449 | } |
| 3407 | ass = type1.ref; | 3450 | ass = type1.ref; |
| 3408 | while ((ass = ass->next) != NULL) { | 3451 | while ((ass = ass->next) != NULL) |
| 3409 | ss = sym_push(ass->v, &ass->type, 0, offset + ass->c); | 3452 | ass->c += offset; |
| 3410 | *ps = ss; | 3453 | offset = 0; |
| 3411 | ps = &ss->next; | 3454 | v = anon_sym++; |
| 3412 | } | 3455 | } |
| 3413 | } else if (v) { | 3456 | if (v) { |
| 3414 | ss = sym_push(v | SYM_FIELD, &type1, 0, offset); | 3457 | ss = sym_push(v | SYM_FIELD, &type1, 0, offset); |
| 3415 | *ps = ss; | 3458 | *ps = ss; |
| 3416 | ps = &ss->next; | 3459 | ps = &ss->next; |
| @@ -4536,13 +4579,7 @@ ST_FUNC void unary(void) · 1119 unmodified lines |
| 4536 | next(); | 4579 | next(); |
| 4537 | if (tok == TOK_CINT || tok == TOK_CUINT) | 4580 | if (tok == TOK_CINT || tok == TOK_CUINT) |
| 4538 | expect("field name"); | 4581 | expect("field name"); |
| 4539 | s = vtop->type.ref; | 4582 | s = find_field(&vtop->type, tok); |
| 4540 | /* find field */ | | |
| 4541 | tok |= SYM_FIELD; | | |
| 4542 | while ((s = s->next) != NULL) { | | |
| 4543 | if (s->v == tok) | | |
| 4544 | break; | | |
| 4545 | } | | |
| 4546 | if (!s) | 4583 | if (!s) |
| 4547 | tcc_error("field not found: %s", get_tok_str(tok & ~SYM_FIELD, &tokc)); | 4584 | tcc_error("field not found: %s", get_tok_str(tok & ~SYM_FIELD, &tokc)); |
| 4548 | /* add field offset to pointer */ | 4585 | /* add field offset to pointer */ |
| @@ -5729,14 +5766,7 @@ static void decl_designator(CType *type, Section *sec, unsigned long c, · 1180 unmodified lines |
| 5729 | struct_field: | 5766 | struct_field: |
| 5730 | if ((type->t & VT_BTYPE) != VT_STRUCT) | 5767 | if ((type->t & VT_BTYPE) != VT_STRUCT) |
| 5731 | expect("struct/union type"); | 5768 | expect("struct/union type"); |
| 5732 | s = type->ref; | 5769 | f = find_field(type, l); |
| 5733 | l |= SYM_FIELD; | | |
| 5734 | f = s->next; | | |
| 5735 | while (f) { | | |
| 5736 | if (f->v == l) | | |
| 5737 | break; | | |
| 5738 | f = f->next; | | |
| 5739 | } | | |
| 5740 | if (!f) | 5770 | if (!f) |
| 5741 | expect("field"); | 5771 | expect("field"); |
| 5742 | if (!notfirst) | 5772 | if (!notfirst) |