struct-init: Support range inits for local vars

Implement missing support for range init for local variables.
master
Michael Matz 2016-08-06 22:38:26 +02:00
parent 4cb7047f0f
commit 4e46c22d5c
3 changed files with 33 additions and 17 deletions

View File

@ -5713,7 +5713,8 @@ static void parse_init_elem(int expr_type)
/* t is the array or struct type. c is the array or struct
address. cur_field is the pointer to the current
value, for arrays the 'c' member contains the current index.
value, for arrays the 'c' member contains the current start
index and the 'r' contains the end index (in case of range init).
'size_only' is true if only size info is needed (only used
in arrays) */
static void decl_designator(CType *type, Section *sec, unsigned long c,
@ -5748,8 +5749,10 @@ static void decl_designator(CType *type, Section *sec, unsigned long c,
index_last = index;
}
skip(']');
if (!notfirst)
(*cur_field)->c = index_last;
if (!notfirst) {
(*cur_field)->c = index;
(*cur_field)->r = index_last;
}
type = pointed_type(type);
elem_size = type_size(type, &align);
c += index * elem_size;
@ -5812,17 +5815,25 @@ static void decl_designator(CType *type, Section *sec, unsigned long c,
uint8_t *src, *dst;
int i;
if (!sec)
tcc_error("range init not supported yet for dynamic storage");
c_end = c + nb_elems * elem_size;
if (c_end > sec->data_allocated)
section_realloc(sec, c_end);
src = sec->data + c;
dst = src;
for(i = 1; i < nb_elems; i++) {
dst += elem_size;
memcpy(dst, src, elem_size);
}
if (!sec) {
vset(type, VT_LOCAL|VT_LVAL, c);
for (i = 1; i < nb_elems; i++) {
vset(type, VT_LOCAL|VT_LVAL, c + elem_size * i);
vswap();
vstore();
}
vpop();
} else {
c_end = c + nb_elems * elem_size;
if (c_end > sec->data_allocated)
section_realloc(sec, c_end);
src = sec->data + c;
dst = src;
for(i = 1; i < nb_elems; i++) {
dst += elem_size;
memcpy(dst, src, elem_size);
}
}
}
}
@ -6014,7 +6025,7 @@ static void decl_initializer(CType *type, Section *sec, unsigned long c,
!(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 a non-const elements. */
of course assignable to non-const elements. */
is_compatible_parameter_types(type, &vtop->type)) {
init_putv(type, sec, c);
} else if (type->t & VT_ARRAY) {
@ -6088,6 +6099,7 @@ static void decl_initializer(CType *type, Section *sec, unsigned long c,
}
} else {
indexsym.c = 0;
indexsym.r = 0;
f = &indexsym;
do_init_list:
@ -6102,8 +6114,7 @@ static void decl_initializer(CType *type, Section *sec, unsigned long c,
(index - array_length) * size1);
}
if (type->t & VT_ARRAY) {
index++;
indexsym.c++;
index = indexsym.c = ++indexsym.r;
} else {
index = index + type_size(&f->type, &align1);
if (s->type.t == TOK_UNION)

View File

@ -148,6 +148,9 @@ void foo (struct W *w, struct pkthdr *phdr_)
struct V lv3 = {((struct S){7,8,{9,10}}), ((const struct W *)w)->t.t, 50};
const struct pkthdr *phdr = phdr_;
struct flowi6 flow = { .daddr = phdr->daddr, .saddr = phdr->saddr };
int elt = 0x42;
/* Range init, overlapping */
struct T lt2 = { { [1 ... 5] = 9, [6 ... 10] = elt, [4 ... 7] = elt+1 }, 1 };
print(ls);
print(ls2);
print(lt);
@ -163,6 +166,7 @@ void foo (struct W *w, struct pkthdr *phdr_)
print(lv);
print(lv2);
print(lv3);
print(lt2);
print(flow);
}
#endif

View File

@ -33,4 +33,5 @@ ls3: 1 2 3 4
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
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