mirror of
https://github.com/frida/tinycc
synced 2024-12-25 14:36:49 +03:00
Fix more struct inits
anonymous struct members were somewhat broken as the testcase demonstrates. The reason is the jumping through hoops to fiddle with the offsets I once introduced to avoid having to track a cumulative offset. That's now not necessary anymore and actively harmful, doing the obvious thing is now better.
This commit is contained in:
parent
94846d3eef
commit
0344c0b6a0
65
tccgen.c
65
tccgen.c
@ -3588,7 +3588,7 @@ redo:
|
||||
goto redo;
|
||||
}
|
||||
|
||||
static Sym * find_field (CType *type, int v)
|
||||
static Sym * find_field (CType *type, int v, int *cumofs)
|
||||
{
|
||||
Sym *s = type->ref;
|
||||
v |= SYM_FIELD;
|
||||
@ -3596,28 +3596,18 @@ static Sym * find_field (CType *type, int v)
|
||||
if ((s->v & SYM_FIELD) &&
|
||||
(s->type.t & VT_BTYPE) == VT_STRUCT &&
|
||||
(s->v & ~SYM_FIELD) >= SYM_FIRST_ANOM) {
|
||||
Sym *ret = find_field (&s->type, v);
|
||||
if (ret)
|
||||
Sym *ret = find_field (&s->type, v, cumofs);
|
||||
if (ret) {
|
||||
*cumofs += s->c;
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
if (s->v == v)
|
||||
break;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
static void struct_add_offset (Sym *s, int offset)
|
||||
{
|
||||
while ((s = s->next) != NULL) {
|
||||
if ((s->v & SYM_FIELD) &&
|
||||
(s->type.t & VT_BTYPE) == VT_STRUCT &&
|
||||
(s->v & ~SYM_FIELD) >= SYM_FIRST_ANOM) {
|
||||
struct_add_offset(s->type.ref, offset);
|
||||
} else
|
||||
s->c += offset;
|
||||
}
|
||||
}
|
||||
|
||||
static void struct_layout(CType *type, AttributeDef *ad)
|
||||
{
|
||||
int size, align, maxalign, offset, c, bit_pos, bit_size;
|
||||
@ -3767,41 +3757,7 @@ static void struct_layout(CType *type, AttributeDef *ad)
|
||||
printf("\n");
|
||||
#endif
|
||||
|
||||
if (f->v & SYM_FIRST_ANOM && (f->type.t & VT_BTYPE) == VT_STRUCT) {
|
||||
Sym *ass;
|
||||
/* An anonymous struct/union. Adjust member offsets
|
||||
to reflect the real offset of our containing struct.
|
||||
Also set the offset of this anon member inside
|
||||
the outer struct to be zero. Via this it
|
||||
works when accessing the field offset directly
|
||||
(from base object), as well as when recursing
|
||||
members in initializer handling. */
|
||||
int v2 = f->type.ref->v;
|
||||
if (!(v2 & SYM_FIELD) &&
|
||||
(v2 & ~SYM_STRUCT) < SYM_FIRST_ANOM) {
|
||||
Sym **pps;
|
||||
/* This happens only with MS extensions. The
|
||||
anon member has a named struct type, so it
|
||||
potentially is shared with other references.
|
||||
We need to unshare members so we can modify
|
||||
them. */
|
||||
ass = f->type.ref;
|
||||
f->type.ref = sym_push(anon_sym++ | SYM_FIELD,
|
||||
&f->type.ref->type, 0,
|
||||
f->type.ref->c);
|
||||
pps = &f->type.ref->next;
|
||||
while ((ass = ass->next) != NULL) {
|
||||
*pps = sym_push(ass->v, &ass->type, 0, ass->c);
|
||||
pps = &((*pps)->next);
|
||||
}
|
||||
*pps = NULL;
|
||||
}
|
||||
struct_add_offset(f->type.ref, offset);
|
||||
f->c = 0;
|
||||
} else {
|
||||
f->c = offset;
|
||||
}
|
||||
|
||||
f->r = 0;
|
||||
}
|
||||
|
||||
@ -5331,7 +5287,7 @@ special_math_val:
|
||||
inc(1, tok);
|
||||
next();
|
||||
} else if (tok == '.' || tok == TOK_ARROW || tok == TOK_CDOUBLE) {
|
||||
int qualifiers;
|
||||
int qualifiers, cumofs = 0;
|
||||
/* field */
|
||||
if (tok == TOK_ARROW)
|
||||
indir();
|
||||
@ -5346,12 +5302,12 @@ special_math_val:
|
||||
next();
|
||||
if (tok == TOK_CINT || tok == TOK_CUINT)
|
||||
expect("field name");
|
||||
s = find_field(&vtop->type, tok);
|
||||
s = find_field(&vtop->type, tok, &cumofs);
|
||||
if (!s)
|
||||
tcc_error("field not found: %s", get_tok_str(tok & ~SYM_FIELD, &tokc));
|
||||
/* add field offset to pointer */
|
||||
vtop->type = char_pointer_type; /* change type to 'char *' */
|
||||
vpushi(s->c);
|
||||
vpushi(cumofs + s->c);
|
||||
gen_op('+');
|
||||
/* change type to field type, and set to lvalue */
|
||||
vtop->type = s->type;
|
||||
@ -6674,19 +6630,20 @@ static int decl_designator(CType *type, Section *sec, unsigned long c,
|
||||
c += index * elem_size;
|
||||
nb_elems = index_last - index + 1;
|
||||
} else {
|
||||
int cumofs = 0;
|
||||
next();
|
||||
l = tok;
|
||||
struct_field:
|
||||
next();
|
||||
if ((type->t & VT_BTYPE) != VT_STRUCT)
|
||||
expect("struct/union type");
|
||||
f = find_field(type, l);
|
||||
f = find_field(type, l, &cumofs);
|
||||
if (!f)
|
||||
expect("field");
|
||||
if (cur_field)
|
||||
*cur_field = f;
|
||||
type = &f->type;
|
||||
c += f->c;
|
||||
c += cumofs + f->c;
|
||||
}
|
||||
cur_field = NULL;
|
||||
}
|
||||
|
@ -87,6 +87,13 @@ union UV guv = {{6,5}};
|
||||
union UV guv2 = {{.b = 7, .a = 8}};
|
||||
union UV guv3 = {.b = 8, .a = 7};
|
||||
|
||||
struct SSU {
|
||||
int y;
|
||||
struct { int x; };
|
||||
};
|
||||
struct SSU gssu1 = { .y = 5, .x = 3 };
|
||||
struct SSU gssu2 = { 5, 3 };
|
||||
|
||||
/* Under -fms-extensions also the following is valid:
|
||||
union UV2 {
|
||||
struct Anon {u8 a,b;}; // unnamed member, but tagged struct, ...
|
||||
@ -166,6 +173,8 @@ void foo (struct W *w, struct pkthdr *phdr_)
|
||||
int elt = 0x42;
|
||||
/* Range init, overlapping */
|
||||
struct T lt2 = { { [1 ... 5] = 9, [6 ... 10] = elt, [4 ... 7] = elt+1 }, 1 };
|
||||
struct SSU lssu1 = { 5, 3 };
|
||||
struct SSU lssu2 = { .y = 5, .x = 3 };
|
||||
print(ls);
|
||||
print(ls2);
|
||||
print(lt);
|
||||
@ -182,6 +191,8 @@ void foo (struct W *w, struct pkthdr *phdr_)
|
||||
print(lv2);
|
||||
print(lv3);
|
||||
print(lt2);
|
||||
print(lssu1);
|
||||
print(lssu2);
|
||||
print(flow);
|
||||
}
|
||||
#endif
|
||||
@ -272,6 +283,8 @@ int main()
|
||||
print(guv.b);
|
||||
print(guv2);
|
||||
print(guv3);
|
||||
print(gssu1);
|
||||
print(gssu2);
|
||||
print(phdr);
|
||||
foo(&gw, &phdr);
|
||||
//printf("q: %s\n", q);
|
||||
|
@ -17,6 +17,8 @@ guv: 6 5 0 0
|
||||
guv.b: 5
|
||||
guv2: 8 7 0 0
|
||||
guv3: 7 8 0 0
|
||||
gssu1: 5 0 0 0 3 0 0 0
|
||||
gssu2: 5 0 0 0 3 0 0 0
|
||||
phdr: 6 5 4 3 0 0 0 0 0 0 0 0 0 0 0 0 9 8 7 6 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
ls: 1 2 3 4
|
||||
ls2: 1 2 3 4
|
||||
@ -34,6 +36,8 @@ lv: 3 4 5 6 68 61 68 61 0 0 0 0 0 0 0 0 0 0 0 0 2d 2e
|
||||
lv2: 1 2 3 4 68 69 68 69 0 0 0 0 0 0 0 0 0 0 0 0 2f 30
|
||||
lv3: 7 8 9 a 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 32
|
||||
lt2: 0 9 9 9 43 43 43 43 42 42 42 0 0 0 0 0 1
|
||||
lssu1: 5 0 0 0 3 0 0 0
|
||||
lssu2: 5 0 0 0 3 0 0 0
|
||||
flow: 9 8 7 6 0 0 0 0 0 0 0 0 0 0 0 0 6 5 4 3 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
one
|
||||
two
|
||||
|
Loading…
Reference in New Issue
Block a user