History

struct-init: Correctly parse unnamed member initializers

For union U { struct {int a,b}; int c; }; union U u = {{ 1, 2, }}; The unnamed first member of union U needs to actually exist in the structure so initializer parsing isn't confused about the double braces. That means also the a and b members must be part of _that_, not of union U directly. Which in turn means we need to do a bit more work for field lookup. See the testcase extension for more things that need to work.

Michael Matz committed 10 years ago

Commit 9e86ebe1 parent 21da73c3 files · +78 −21Browse files

Unified · Split

3 files
  1. tccgen.c +51 −21
  2. tests/tests2/86-struct-init.c +23 −0
  3. tests/tests2/86-struct-init.expect +4 −0
tccgen.c+51−21
@@ -3181,6 +3181,22 @@ static void parse_attribute(AttributeDef *ad) · 3180 unmodified lines
3181 }3181 }
3182}3182}
3183 3183
3184static 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 */
3185static void struct_decl(CType *type, AttributeDef *ad, int u)3201static 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#endif3420#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)
tests/tests2/86-struct-init.c+23−0
@@ -77,6 +77,25 @@ struct SU { · 76 unmodified lines
77};77};
78struct SU gsu = {5,6};78struct SU gsu = {5,6};
79 79
80/* Unnamed struct/union members aren't ISO C, but it's a widely accepted
81 extension. See below for further extensions to that under -fms-extension.*/
82union UV {
83 struct {u8 a,b;};
84 struct S s;
85};
86union UV guv = {{6,5}};
87union UV guv2 = {{.b = 7, .a = 8}};
88union UV guv3 = {.b = 8, .a = 7};
89
90/* Under -fms-extensions also the following is valid:
91union UV2 {
92 struct Anon {u8 a,b;}; // unnamed member, but tagged struct, ...
93 struct S s;
94};
95struct Anon gan = { 10, 11 }; // ... which makes it available here.
96union UV2 guv4 = {{4,3}}; // and the other inits from above as well
97*/
98
80#include <stdio.h>99#include <stdio.h>
81void print_ (const char *name, const u8 *p, long size)100void print_ (const char *name, const u8 *p, long size)
82{101{
@@ -144,6 +163,10 @@ int main() · 61 unmodified lines
144 print(sinit16);163 print(sinit16);
145 print(gw);164 print(gw);
146 print(gsu);165 print(gsu);
166 print(guv);
167 print(guv.b);
168 print(guv2);
169 print(guv3);
147 foo(&gw);170 foo(&gw);
148 //printf("q: %s\n", q);171 //printf("q: %s\n", q);
149 return 0;172 return 0;
tests/tests2/86-struct-init.expect+4−0
@@ -13,6 +13,10 @@ gv3: 7 8 9 a 68 6f 68 6f 0 0 0 0 0 0 0 0 0 0 0 0 31 32 · 12 unmodified lines
13sinit16: 1 0 0 0 2 0 0 013sinit16: 1 0 0 0 2 0 0 0
14gw: 1 2 3 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 014gw: 1 2 3 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
15gsu: 5 615gsu: 5 6
16guv: 6 5 0 0
17guv.b: 5
18guv2: 8 7 0 0
19guv3: 7 8 0 0
16ls: 1 2 3 420ls: 1 2 3 4
17ls2: 1 2 3 421ls2: 1 2 3 4
18lt: 68 65 6c 6c 6f 0 0 0 0 0 0 0 0 0 0 0 2a22lt: 68 65 6c 6c 6f 0 0 0 0 0 0 0 0 0 0 0 2a

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t