mirror of
https://github.com/mirror/tinycc.git
synced 2025-03-24 10:00:07 +08:00
tccgen: Allow struct init from struct
Example: struct S {int x,y;} a = {1, 2}, b = {3, 4}, c[] = {a, b}, // new d[] = {b, (struct S){5,6}}; // new
This commit is contained in:
parent
0c6adcbe53
commit
719d96665e
41
tccgen.c
41
tccgen.c
@ -8124,20 +8124,22 @@ static void decl_initializer(init_params *p, CType *type, unsigned long c, int f
|
||||
don't consume them as initializer value (which would commit them
|
||||
to some anonymous symbol). */
|
||||
tok != TOK_LSTR && tok != TOK_STR &&
|
||||
!(flags & DIF_SIZE_ONLY)) {
|
||||
(!(flags & DIF_SIZE_ONLY)
|
||||
/* a struct may be initialized from a struct of same type, as in
|
||||
struct {int x,y;} a = {1,2}, b = {3,4}, c[] = {a,b};
|
||||
In that case we need to parse the element in order to check
|
||||
it for compatibility below */
|
||||
|| (type->t & VT_BTYPE) == VT_STRUCT)
|
||||
) {
|
||||
int ncw_prev = nocode_wanted;
|
||||
if ((flags & DIF_SIZE_ONLY) && !p->sec)
|
||||
++nocode_wanted;
|
||||
parse_init_elem(!p->sec ? EXPR_ANY : EXPR_CONST);
|
||||
nocode_wanted = ncw_prev;
|
||||
flags |= DIF_HAVE_ELEM;
|
||||
}
|
||||
|
||||
if ((flags & DIF_HAVE_ELEM) &&
|
||||
!(type->t & VT_ARRAY) &&
|
||||
/* Use i_c_parameter_t, to strip toplevel qualifiers.
|
||||
The source type might have VT_CONSTANT set, which is
|
||||
of course assignable to non-const elements. */
|
||||
is_compatible_unqualified_types(type, &vtop->type)) {
|
||||
goto init_putv;
|
||||
|
||||
} else if (type->t & VT_ARRAY) {
|
||||
if (type->t & VT_ARRAY) {
|
||||
no_oblock = 1;
|
||||
if (((flags & DIF_FIRST) && tok != TOK_LSTR && tok != TOK_STR) ||
|
||||
tok == '{') {
|
||||
@ -8258,6 +8260,14 @@ static void decl_initializer(init_params *p, CType *type, unsigned long c, int f
|
||||
}
|
||||
if (!no_oblock)
|
||||
skip('}');
|
||||
|
||||
} else if ((flags & DIF_HAVE_ELEM)
|
||||
/* Use i_c_parameter_t, to strip toplevel qualifiers.
|
||||
The source type might have VT_CONSTANT set, which is
|
||||
of course assignable to non-const elements. */
|
||||
&& is_compatible_unqualified_types(type, &vtop->type)) {
|
||||
goto one_elem;
|
||||
|
||||
} else if ((type->t & VT_BTYPE) == VT_STRUCT) {
|
||||
no_oblock = 1;
|
||||
if ((flags & DIF_FIRST) || tok == '{') {
|
||||
@ -8269,13 +8279,15 @@ static void decl_initializer(init_params *p, CType *type, unsigned long c, int f
|
||||
n = s->c;
|
||||
size1 = 1;
|
||||
goto do_init_list;
|
||||
|
||||
} else if (tok == '{') {
|
||||
if (flags & DIF_HAVE_ELEM)
|
||||
skip(';');
|
||||
next();
|
||||
decl_initializer(p, type, c, flags & ~DIF_HAVE_ELEM);
|
||||
skip('}');
|
||||
} else if ((flags & DIF_SIZE_ONLY)) {
|
||||
|
||||
} else one_elem: if ((flags & DIF_SIZE_ONLY)) {
|
||||
/* If we supported only ISO C we wouldn't have to accept calling
|
||||
this on anything than an array if DIF_SIZE_ONLY (and even then
|
||||
only on the outermost level, so no recursion would be needed),
|
||||
@ -8283,7 +8295,11 @@ static void decl_initializer(init_params *p, CType *type, unsigned long c, int f
|
||||
But GNU C supports it, so we need to recurse even into
|
||||
subfields of structs and arrays when DIF_SIZE_ONLY is set. */
|
||||
/* just skip expression */
|
||||
skip_or_save_block(NULL);
|
||||
if (flags & DIF_HAVE_ELEM)
|
||||
vpop();
|
||||
else
|
||||
skip_or_save_block(NULL);
|
||||
|
||||
} else {
|
||||
if (!(flags & DIF_HAVE_ELEM)) {
|
||||
/* This should happen only when we haven't parsed
|
||||
@ -8293,7 +8309,6 @@ static void decl_initializer(init_params *p, CType *type, unsigned long c, int f
|
||||
expect("string constant");
|
||||
parse_init_elem(!p->sec ? EXPR_ANY : EXPR_CONST);
|
||||
}
|
||||
init_putv:
|
||||
if (!p->sec && (flags & DIF_CLEAR) /* container was already zero'd */
|
||||
&& (vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST
|
||||
&& vtop->c.i == 0
|
||||
|
@ -342,6 +342,35 @@ test_zero_init (void)
|
||||
test_correct_filling (&d.a);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void test_init_struct_from_struct(void)
|
||||
{
|
||||
int i = 0;
|
||||
struct S {int x,y;}
|
||||
a = {1,2},
|
||||
b = {3,4},
|
||||
c[] = {a,b},
|
||||
d[] = {++i, ++i, ++i, ++i},
|
||||
e[] = {b, (struct S){5,6}}
|
||||
;
|
||||
|
||||
printf("%s: %d %d %d %d - %d %d %d %d - %d %d %d %d\n",
|
||||
__FUNCTION__,
|
||||
c[0].x,
|
||||
c[0].y,
|
||||
c[1].x,
|
||||
c[1].y,
|
||||
d[0].x,
|
||||
d[0].y,
|
||||
d[1].x,
|
||||
d[1].y,
|
||||
e[0].x,
|
||||
e[0].y,
|
||||
e[1].x,
|
||||
e[1].y
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
@ -373,5 +402,6 @@ int main()
|
||||
test_multi_relocs();
|
||||
test_zero_init();
|
||||
test_init_ranges();
|
||||
test_init_struct_from_struct();
|
||||
return 0;
|
||||
}
|
||||
|
@ -55,3 +55,4 @@ sea_fill0: okay
|
||||
sea_fill1: okay
|
||||
sea_fill2: okay
|
||||
1438
|
||||
test_init_struct_from_struct: 1 2 3 4 - 1 2 3 4 - 3 4 5 6
|
||||
|
Loading…
Reference in New Issue
Block a user