History

tccgen: flex arrays etc.

Fixes potential writes past the allocated space with mostly illegal flex array initializers. (60_errors_and_warnings.c :test_var_array) In exchange suspicious precautions such as section_reserve or checks with sec->data_allocated were removed. (There is an hard check 'init_assert()' for now but it's meant to be just temporary) Also, instead of filling holes, always memset(0) structures & arrays on stack. Sometimes more efficient, sometimes isn't. At least we can omit putting null initializers. About array range inititializers: Reparsing tokens has a small problem with sideeffects, for example int c = 0, dd[] = { [0 ... 1] = ++c, [2 ... 3] = ++c }; Also, instead of 'squeeze_multi_relocs()', delete pre-existing relocations in advance. This works even if secondary initializers don't even have relocations, as with [0 ... 7] = &stuff, [4] = NULL Also, in tcc.h: new macro "tcc_internal_error()"

grischka committed 6 years ago

Commit 72b520e1 parent 40395519 files · +309 −222Browse files

Unified · Split

9 files
  1. i386-asm.c +2 −2
  2. tcc.h +2 −3
  3. tccelf.c +3 −39
  4. tccgen.c +216 −160
  5. tccpp.c +8 −7
  6. tests/tests2/60_errors_and_warnings.c +9 −0
  7. tests/tests2/60_errors_and_warnings.expect +4 −1
  8. tests/tests2/90_struct-init.c +55 −8
  9. tests/tests2/90_struct-init.expect +10 −2
i386-asm.c+2−2
@@ -1517,7 +1517,7 @@ ST_FUNC void subst_asm_operand(CString *add_str, · 1516 unmodified lines
1517 } else if (r & VT_LVAL) {1517 } else if (r & VT_LVAL) {
1518 reg = r & VT_VALMASK;1518 reg = r & VT_VALMASK;
1519 if (reg >= VT_CONST)1519 if (reg >= VT_CONST)
1520 tcc_error("internal compiler error");1520 tcc_internal_error("");
1521 snprintf(buf, sizeof(buf), "(%%%s)",1521 snprintf(buf, sizeof(buf), "(%%%s)",
1522#ifdef TCC_TARGET_X86_641522#ifdef TCC_TARGET_X86_64
1523 get_tok_str(TOK_ASM_rax + reg, NULL)1523 get_tok_str(TOK_ASM_rax + reg, NULL)
@@ -1530,7 +1530,7 @@ ST_FUNC void subst_asm_operand(CString *add_str, · 6 unmodified lines
1530 /* register case */1530 /* register case */
1531 reg = r & VT_VALMASK;1531 reg = r & VT_VALMASK;
1532 if (reg >= VT_CONST)1532 if (reg >= VT_CONST)
1533 tcc_error("internal compiler error");1533 tcc_internal_error("");
1534 1534
1535 /* choose register operand size */1535 /* choose register operand size */
1536 if ((sv->type.t & VT_BTYPE) == VT_BYTE ||1536 if ((sv->type.t & VT_BTYPE) == VT_BYTE ||
tcc.h+2−3
@@ -1237,6 +1237,8 @@ PUB_FUNC char *tcc_strdup_debug(const char *str, const char *file, int line); · 1236 unmodified lines
1237PUB_FUNC void _tcc_error_noabort(const char *fmt, ...) PRINTF_LIKE(1,2);1237PUB_FUNC void _tcc_error_noabort(const char *fmt, ...) PRINTF_LIKE(1,2);
1238PUB_FUNC NORETURN void _tcc_error(const char *fmt, ...) PRINTF_LIKE(1,2);1238PUB_FUNC NORETURN void _tcc_error(const char *fmt, ...) PRINTF_LIKE(1,2);
1239PUB_FUNC void _tcc_warning(const char *fmt, ...) PRINTF_LIKE(1,2);1239PUB_FUNC void _tcc_warning(const char *fmt, ...) PRINTF_LIKE(1,2);
1240#define tcc_internal_error(msg) tcc_error("internal compiler error\n"\
1241 "%s:%d: in %s(): " msg, __FILE__,__LINE__,__FUNCTION__)
1240 1242
1241/* other utilities */1243/* other utilities */
1242ST_FUNC void dynarray_add(void *ptab, int *nb_ptr, void *data);1244ST_FUNC void dynarray_add(void *ptab, int *nb_ptr, void *data);
@@ -1507,7 +1509,6 @@ ST_FUNC Section *new_section(TCCState *s1, const char *name, int sh_type, int sh · 264 unmodified lines
1507ST_FUNC void section_realloc(Section *sec, unsigned long new_size);1509ST_FUNC void section_realloc(Section *sec, unsigned long new_size);
1508ST_FUNC size_t section_add(Section *sec, addr_t size, int align);1510ST_FUNC size_t section_add(Section *sec, addr_t size, int align);
1509ST_FUNC void *section_ptr_add(Section *sec, addr_t size);1511ST_FUNC void *section_ptr_add(Section *sec, addr_t size);
1510ST_FUNC void section_reserve(Section *sec, unsigned long size);
1511ST_FUNC Section *find_section(TCCState *s1, const char *name);1512ST_FUNC Section *find_section(TCCState *s1, const char *name);
1512ST_FUNC Section *new_symtab(TCCState *s1, const char *symtab_name, int sh_type, int sh_flags, const char *strtab_name, const char *hash_name, int hash_sh_flags);1513ST_FUNC Section *new_symtab(TCCState *s1, const char *symtab_name, int sh_type, int sh_flags, const char *strtab_name, const char *hash_name, int hash_sh_flags);
1513 1514
@@ -1544,8 +1545,6 @@ ST_FUNC void add_array(TCCState *s1, const char *sec, int c); · 30 unmodified lines
1544ST_FUNC void build_got_entries(TCCState *s1);1545ST_FUNC void build_got_entries(TCCState *s1);
1545#endif1546#endif
1546ST_FUNC struct sym_attr *get_sym_attr(TCCState *s1, int index, int alloc);1547ST_FUNC struct sym_attr *get_sym_attr(TCCState *s1, int index, int alloc);
1547ST_FUNC void squeeze_multi_relocs(Section *sec, size_t oldrelocoffset);
1548
1549ST_FUNC addr_t get_sym_addr(TCCState *s, const char *name, int err, int forc);1548ST_FUNC addr_t get_sym_addr(TCCState *s, const char *name, int err, int forc);
1550ST_FUNC void list_elf_symbols(TCCState *s, void *ctx,1549ST_FUNC void list_elf_symbols(TCCState *s, void *ctx,
1551 void (*symbol_cb)(void *ctx, const char *name, const void *val));1550 void (*symbol_cb)(void *ctx, const char *name, const void *val));
tccelf.c+3−39
@@ -321,14 +321,16 @@ ST_FUNC void *section_ptr_add(Section *sec, addr_t size) · 320 unmodified lines
321 return sec->data + offset;321 return sec->data + offset;
322}322}
323 323
324#ifndef ELF_OBJ_ONLY
324/* reserve at least 'size' bytes from section start */325/* reserve at least 'size' bytes from section start */
325ST_FUNC void section_reserve(Section *sec, unsigned long size)326static void section_reserve(Section *sec, unsigned long size)
326{327{
327 if (size > sec->data_allocated)328 if (size > sec->data_allocated)
328 section_realloc(sec, size);329 section_realloc(sec, size);
329 if (size > sec->data_offset)330 if (size > sec->data_offset)
330 sec->data_offset = size;331 sec->data_offset = size;
331}332}
333#endif
332 334
333static Section *find_section_create (TCCState *s1, const char *name, int create)335static Section *find_section_create (TCCState *s1, const char *name, int create)
334{336{
@@ -762,45 +764,7 @@ ST_FUNC void put_elf_reloc(Section *symtab, Section *s, unsigned long offset, · 427 unmodified lines
762 put_elf_reloca(symtab, s, offset, type, symbol, 0);764 put_elf_reloca(symtab, s, offset, type, symbol, 0);
763}765}
764 766
765/* Remove relocations for section S->reloc starting at oldrelocoffset
766 that are to the same place, retaining the last of them. As side effect
767 the relocations are sorted. Possibly reduces the number of relocs. */
768ST_FUNC void squeeze_multi_relocs(Section *s, size_t oldrelocoffset)
769{
770 Section *sr = s->reloc;
771 ElfW_Rel *r, *dest;
772 ssize_t a;
773 ElfW(Addr) addr;
774
775 if (oldrelocoffset + sizeof(*r) >= sr->data_offset)
776 return;
777 /* The relocs we're dealing with are the result of initializer parsing.
778 So they will be mostly in order and there aren't many of them.
779 Secondly we need a stable sort (which qsort isn't). We use
780 a simple insertion sort. */
781 for (a = oldrelocoffset + sizeof(*r); a < sr->data_offset; a += sizeof(*r)) {
782 ssize_t i = a - sizeof(*r);
783 ElfW_Rel tmp = *(ElfW_Rel*)(sr->data + a);
784 addr = tmp.r_offset;
785 for (; i >= (ssize_t)oldrelocoffset &&
786 ((ElfW_Rel*)(sr->data + i))->r_offset > addr; i -= sizeof(*r)) {
787 *(ElfW_Rel*)(sr->data + i + sizeof(*r)) = *(ElfW_Rel*)(sr->data + i);
788 }
789 *(ElfW_Rel*)(sr->data + i + sizeof(*r)) = tmp;
790 }
791
792 r = (ElfW_Rel*)(sr->data + oldrelocoffset);
793 dest = r;
794 for (; r < (ElfW_Rel*)(sr->data + sr->data_offset); r++) {
795 if (dest->r_offset != r->r_offset)
796 dest++;
797 *dest = *r;
798 }
799 sr->data_offset = (unsigned char*)dest - sr->data + sizeof(*r);
800}
801
802/* put stab debug information */767/* put stab debug information */
803
804ST_FUNC void put_stabs(TCCState *s1, const char *str, int type, int other, int desc,768ST_FUNC void put_stabs(TCCState *s1, const char *str, int type, int other, int desc,
805 unsigned long value)769 unsigned long value)
806{770{
tccgen.c+216−160
@@ -123,6 +123,12 @@ static struct scope { · 122 unmodified lines
123 Sym *lstk, *llstk;123 Sym *lstk, *llstk;
124} *cur_scope, *loop_scope, *root_scope;124} *cur_scope, *loop_scope, *root_scope;
125 125
126typedef struct {
127 Section *sec;
128 int local_offset;
129 Sym *flex_array_ref;
130} init_params;
131
126/********************************************************/132/********************************************************/
127/* stab debug support */133/* stab debug support */
128 134
@@ -218,8 +224,8 @@ static int is_compatible_types(CType *type1, CType *type2); · 89 unmodified lines
218static int parse_btype(CType *type, AttributeDef *ad);224static int parse_btype(CType *type, AttributeDef *ad);
219static CType *type_decl(CType *type, AttributeDef *ad, int *v, int td);225static CType *type_decl(CType *type, AttributeDef *ad, int *v, int td);
220static void parse_expr_type(CType *type);226static void parse_expr_type(CType *type);
221static void init_putv(CType *type, Section *sec, unsigned long c);227static void init_putv(init_params *p, CType *type, unsigned long c);
222static void decl_initializer(CType *type, Section *sec, unsigned long c, int flags);228static void decl_initializer(init_params *p, CType *type, unsigned long c, int flags);
223static void block(int is_expr);229static void block(int is_expr);
224static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r, int has_init, int v, int scope);230static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r, int has_init, int v, int scope);
225static void decl(int l);231static void decl(int l);
@@ -2167,16 +2173,17 @@ ST_FUNC int gv(int rc) · 1941 unmodified lines
2167 } else {2173 } else {
2168 if (is_float(vtop->type.t) && 2174 if (is_float(vtop->type.t) &&
2169 (vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {2175 (vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
2170 unsigned long offset;
2171 /* CPUs usually cannot use float constants, so we store them2176 /* CPUs usually cannot use float constants, so we store them
2172 generically in data segment */2177 generically in data segment */
2178 init_params p = { data_section };
2179 unsigned long offset;
2173 size = type_size(&vtop->type, &align);2180 size = type_size(&vtop->type, &align);
2174 if (NODATA_WANTED)2181 if (NODATA_WANTED)
2175 size = 0, align = 1;2182 size = 0, align = 1;
2176 offset = section_add(data_section, size, align);2183 offset = section_add(p.sec, size, align);
2177 vpush_ref(&vtop->type, data_section, offset, size);2184 vpush_ref(&vtop->type, p.sec, offset, size);
2178 vswap();2185 vswap();
2179 init_putv(&vtop->type, data_section, offset);2186 init_putv(&p, &vtop->type, offset);
2180 vtop->r |= VT_LVAL;2187 vtop->r |= VT_LVAL;
2181 }2188 }
2182#ifdef CONFIG_TCC_BCHECK2189#ifdef CONFIG_TCC_BCHECK
@@ -5444,7 +5451,7 @@ static void parse_builtin_params(int nc, const char *args) · 3261 unmodified lines
5444 type.t = VT_SIZE_T;5451 type.t = VT_SIZE_T;
5445 break;5452 break;
5446 default:5453 default:
5447 tcc_error("internal error");5454 break;
5448 }5455 }
5449 gen_assign_cast(&type);5456 gen_assign_cast(&type);
5450 }5457 }
@@ -6102,7 +6109,8 @@ special_math_val: · 651 unmodified lines
6102 problems */6109 problems */
6103 vseti(VT_LOCAL, loc);6110 vseti(VT_LOCAL, loc);
6104#ifdef CONFIG_TCC_BCHECK6111#ifdef CONFIG_TCC_BCHECK
6105 loc -= tcc_state->do_bounds_check != 0;6112 if (tcc_state->do_bounds_check)
6113 --loc;
6106#endif6114#endif
6107 ret.c = vtop->c;6115 ret.c = vtop->c;
6108 if (ret_nregs < 0)6116 if (ret_nregs < 0)
@@ -7296,23 +7304,6 @@ static void skip_or_save_block(TokenString **str) · 1187 unmodified lines
7296 }7304 }
7297}7305}
7298 7306
7299static void get_init_string(TokenString **str, int has_init)
7300{
7301 if (has_init == 2) {
7302 *str = tok_str_alloc();
7303 /* only get strings */
7304 while (tok == TOK_STR || tok == TOK_LSTR) {
7305 tok_str_add_tok(*str);
7306 next();
7307 }
7308 tok_str_add(*str, -1);
7309 tok_str_add(*str, 0);
7310 }
7311 else
7312 skip_or_save_block(str);
7313 unget_tok(0);
7314}
7315
7316#define EXPR_CONST 17307#define EXPR_CONST 1
7317#define EXPR_ANY 27308#define EXPR_ANY 2
7318 7309
@@ -7343,10 +7334,22 @@ static void parse_init_elem(int expr_type) · 24 unmodified lines
7343 }7334 }
7344}7335}
7345 7336
7337#if 1
7338static void init_assert(init_params *p, int offset)
7339{
7340 if (p->sec ? !NODATA_WANTED && offset > p->sec->data_offset
7341 : !nocode_wanted && offset > p->local_offset)
7342 tcc_internal_error("initializer overflow");
7343}
7344#else
7345#define init_assert(sec, offset)
7346#endif
7347
7346/* put zeros for variable based init */7348/* put zeros for variable based init */
7347static void init_putz(Section *sec, unsigned long c, int size)7349static void init_putz(init_params *p, unsigned long c, int size)
7348{7350{
7349 if (sec) {7351 init_assert(p, c + size);
7352 if (p->sec) {
7350 /* nothing to do because globals are already set to zero */7353 /* nothing to do because globals are already set to zero */
7351 } else {7354 } else {
7352 vpush_global_sym(&func_old_type, TOK_memset);7355 vpush_global_sym(&func_old_type, TOK_memset);
@@ -7365,6 +7368,37 @@ static void init_putz(Section *sec, unsigned long c, int size) · 12 unmodified lines
7365#define DIF_FIRST 17368#define DIF_FIRST 1
7366#define DIF_SIZE_ONLY 27369#define DIF_SIZE_ONLY 2
7367#define DIF_HAVE_ELEM 47370#define DIF_HAVE_ELEM 4
7371#define DIF_CLEAR 8
7372
7373/* delete relocations for specified range c ... c + size. Unfortunatly
7374 in very special cases, relocations may occur unordered */
7375static void decl_design_delrels(Section *sec, int c, int size)
7376{
7377 ElfW_Rel *rel, *rel2, *rel_end;
7378 if (!sec || !sec->reloc)
7379 return;
7380 rel = rel2 = (ElfW_Rel*)sec->reloc->data;
7381 rel_end = (ElfW_Rel*)(sec->reloc->data + sec->reloc->data_offset);
7382 while (rel < rel_end) {
7383 if (rel->r_offset >= c && rel->r_offset < c + size) {
7384 sec->reloc->data_offset -= sizeof *rel;
7385 } else {
7386 if (rel2 != rel)
7387 memcpy(rel2, rel, sizeof *rel);
7388 ++rel2;
7389 }
7390 ++rel;
7391 }
7392}
7393
7394static void decl_design_flex(init_params *p, Sym *ref, int index)
7395{
7396 if (ref == p->flex_array_ref) {
7397 if (index >= ref->c)
7398 ref->c = index + 1;
7399 } else if (ref->c < 0)
7400 tcc_error("flexible array has zero size in this context");
7401}
7368 7402
7369/* t is the array or struct type. c is the array or struct7403/* t is the array or struct type. c is the array or struct
7370 address. cur_field is the pointer to the current7404 address. cur_field is the pointer to the current
@@ -7372,13 +7406,12 @@ static void init_putz(Section *sec, unsigned long c, int size) · 1 unmodified line
7372 index. 'flags' is as in decl_initializer.7406 index. 'flags' is as in decl_initializer.
7373 'al' contains the already initialized length of the7407 'al' contains the already initialized length of the
7374 current container (starting at c). This returns the new length of that. */7408 current container (starting at c). This returns the new length of that. */
7375static int decl_designator(CType *type, Section *sec, unsigned long c,7409static int decl_designator(init_params *p, CType *type, unsigned long c,
7376 Sym **cur_field, int flags, int al, int size)7410 Sym **cur_field, int flags, int al)
7377{7411{
7378 Sym *s, *f;7412 Sym *s, *f;
7379 int index, index_last, align, l, nb_elems, elem_size;7413 int index, index_last, align, l, nb_elems, elem_size;
7380 unsigned long corig = c;7414 unsigned long corig = c;
7381 TokenString *init_str = NULL;
7382 7415
7383 elem_size = 0;7416 elem_size = 0;
7384 nb_elems = 1;7417 nb_elems = 1;
@@ -7406,9 +7439,9 @@ static int decl_designator(CType *type, Section *sec, unsigned long c, · 21 unmodified lines
7406 }7439 }
7407 skip(']');7440 skip(']');
7408 s = type->ref;7441 s = type->ref;
7409 if (index < 0 || (s->c >= 0 && index_last >= s->c) ||7442 decl_design_flex(p, s, index_last);
7410 index_last < index)7443 if (index < 0 || index_last >= s->c || index_last < index)
7411 tcc_error("invalid index");7444 tcc_error("index exceeds array bounds or range is empty");
7412 if (cur_field)7445 if (cur_field)
7413 (*cur_field)->c = index_last;7446 (*cur_field)->c = index_last;
7414 type = pointed_type(type);7447 type = pointed_type(type);
@@ -7444,72 +7477,82 @@ static int decl_designator(CType *type, Section *sec, unsigned long c, · 29 unmodified lines
7444 no_designator:7477 no_designator:
7445 if (type->t & VT_ARRAY) {7478 if (type->t & VT_ARRAY) {
7446 index = (*cur_field)->c;7479 index = (*cur_field)->c;
7447 if (type->ref->c >= 0 && index >= type->ref->c)7480 s = type->ref;
7448 tcc_error("index too large");7481 decl_design_flex(p, s, index);
7482 if (index >= s->c)
7483 tcc_error("too many initializers");
7449 type = pointed_type(type);7484 type = pointed_type(type);
7450 c += index * type_size(type, &align);7485 elem_size = type_size(type, &align);
7486 c += index * elem_size;
7451 } else {7487 } else {
7452 f = *cur_field;7488 f = *cur_field;
7453 while (f && (f->v & SYM_FIRST_ANOM) && (f->type.t & VT_BITFIELD))7489 while (f && (f->v & SYM_FIRST_ANOM) && (f->type.t & VT_BITFIELD))
7454 *cur_field = f = f->next;7490 *cur_field = f = f->next;
7455 if (!f)7491 if (!f)
7456 tcc_error("too many field init");7492 tcc_error("too many initializers");
7457 type = &f->type;7493 type = &f->type;
7458 c += f->c;7494 c += f->c;
7459 }7495 }
7460 }7496 }
7461 7497
7462 /* must put zero in holes (note that doing it that way7498 if (!elem_size) /* for structs */
7463 ensures that it even works with designators) */7499 elem_size = type_size(type, &align);
7464 if (!(flags & DIF_SIZE_ONLY)) {
7465 int zlen = c - (corig + al);
7466 if (type->t & VT_BITFIELD) { /* must include current field too */
7467 zlen += type_size(type, &align);
7468 if (al + zlen > size)
7469 zlen = size - al;
7470 }
7471 if (zlen > 0)
7472 init_putz(sec, corig + al, zlen);
7473 }
7474 7500
7475 if (!(flags & DIF_SIZE_ONLY) && nb_elems > 1) {7501 /* Using designators the same element can be initialized more
7476 get_init_string(&init_str, tok == TOK_STR || tok == TOK_LSTR ? 2 : 0);7502 than once. In that case we need to delete possibly already
7477 begin_macro(init_str, 1);7503 existing relocations. */
7478 next();7504 if (!(flags & DIF_SIZE_ONLY) && c - corig < al) {
7505 decl_design_delrels(p->sec, c, elem_size * nb_elems);
7506 flags &= ~DIF_CLEAR; /* mark stack dirty too */
7479 }7507 }
7480 7508
7481 decl_initializer(type, sec, c, flags & ~DIF_FIRST);7509 decl_initializer(p, type, c, flags & ~DIF_FIRST);
7482 7510
7483 if (!(flags & DIF_SIZE_ONLY) && nb_elems > 1) {7511 if (!(flags & DIF_SIZE_ONLY) && nb_elems > 1) {
7512 Sym aref = {0};
7513 CType t1;
7484 int i;7514 int i;
7485 7515 if (p->sec || (type->t & VT_ARRAY)) {
7486 for(i = 1; i < nb_elems; i++) {7516 /* make init_putv/vstore believe it were a struct */
7487 macro_ptr = init_str->str;7517 aref.c = elem_size;
7488 next();7518 t1.t = VT_STRUCT, t1.ref = &aref;
7489 decl_initializer(type, sec, c + i * elem_size, flags & ~DIF_FIRST);7519 type = &t1;
7490 }7520 }
7491 end_macro();7521 if (p->sec)
7492 next();7522 vpush_ref(type, p->sec, c, elem_size);
7523 else
7524 vset(type, VT_LOCAL|VT_LVAL, c);
7525 for (i = 1; i < nb_elems; i++) {
7526 vdup();
7527 init_putv(p, type, c + elem_size * i);
7528 }
7529 vpop();
7493 }7530 }
7494 7531
7495 c += nb_elems * type_size(type, &align);7532 c += nb_elems * elem_size;
7496 if (c - corig > al)7533 if (c - corig > al)
7497 al = c - corig;7534 al = c - corig;
7498 return al;7535 return al;
7499}7536}
7500 7537
7501/* store a value or an expression directly in global data or in local array */7538/* store a value or an expression directly in global data or in local array */
7502static void init_putv(CType *type, Section *sec, unsigned long c)7539static void init_putv(init_params *p, CType *type, unsigned long c)
7503{7540{
7504 int bt;7541 int bt;
7505 void *ptr;7542 void *ptr;
7506 CType dtype;7543 CType dtype;
7544 int size, align;
7545 Section *sec = p->sec;
7507 7546
7508 dtype = *type;7547 dtype = *type;
7509 dtype.t &= ~VT_CONSTANT; /* need to do that to avoid false warning */7548 dtype.t &= ~VT_CONSTANT; /* need to do that to avoid false warning */
7510 7549
7550 size = type_size(type, &align);
7551 if (type->t & VT_BITFIELD)
7552 size = (BIT_POS(type->t) + BIT_SIZE(type->t) + 7) / 8;
7553 init_assert(p, c + size);
7554
7511 if (sec) {7555 if (sec) {
7512 int size, align;
7513 /* XXX: not portable */7556 /* XXX: not portable */
7514 /* XXX: generate error if incorrect relocation */7557 /* XXX: generate error if incorrect relocation */
7515 gen_assign_cast(&dtype);7558 gen_assign_cast(&dtype);
@@ -7529,8 +7572,6 @@ static void init_putv(CType *type, Section *sec, unsigned long c) · 13 unmodified lines
7529 return;7572 return;
7530 }7573 }
7531 7574
7532 size = type_size(type, &align);
7533 section_reserve(sec, c + size);
7534 ptr = sec->data + c;7575 ptr = sec->data + c;
7535 7576
7536 /* XXX: make code faster ? */7577 /* XXX: make code faster ? */
@@ -7567,12 +7608,6 @@ static void init_putv(CType *type, Section *sec, unsigned long c) · 30 unmodified lines
7567 continue;7608 continue;
7568 if (rel->r_offset < esym->st_value)7609 if (rel->r_offset < esym->st_value)
7569 break;7610 break;
7570 /* Note: if the same fields are initialized multiple
7571 times (possible with designators) then we possibly
7572 add multiple relocations for the same offset here.
7573 That would lead to wrong code, the last reloc needs
7574 to win. We clean this up later after the whole
7575 initializer is parsed. */
7576 put_elf_reloca(symtab_section, sec,7611 put_elf_reloca(symtab_section, sec,
7577 c + rel->r_offset - esym->st_value,7612 c + rel->r_offset - esym->st_value,
7578 ELFW(R_TYPE)(rel->r_info),7613 ELFW(R_TYPE)(rel->r_info),
@@ -7610,10 +7645,10 @@ static void init_putv(CType *type, Section *sec, unsigned long c) · 31 unmodified lines
7610 case VT_BOOL:7645 case VT_BOOL:
7611 vtop->c.i = vtop->c.i != 0;7646 vtop->c.i = vtop->c.i != 0;
7612 case VT_BYTE:7647 case VT_BYTE:
7613 *(char *)ptr |= vtop->c.i;7648 *(char *)ptr = vtop->c.i;
7614 break;7649 break;
7615 case VT_SHORT:7650 case VT_SHORT:
7616 *(short *)ptr |= vtop->c.i;7651 *(short *)ptr = vtop->c.i;
7617 break;7652 break;
7618 case VT_FLOAT:7653 case VT_FLOAT:
7619 *(float*)ptr = vtop->c.f;7654 *(float*)ptr = vtop->c.f;
@@ -7642,7 +7677,7 @@ static void init_putv(CType *type, Section *sec, unsigned long c) · 22 unmodified lines
7642 break;7677 break;
7643#if PTR_SIZE != 87678#if PTR_SIZE != 8
7644 case VT_LLONG:7679 case VT_LLONG:
7645 *(long long *)ptr |= vtop->c.i;7680 *(long long *)ptr = vtop->c.i;
7646 break;7681 break;
7647#else7682#else
7648 case VT_LLONG:7683 case VT_LLONG:
@@ -7654,11 +7689,11 @@ static void init_putv(CType *type, Section *sec, unsigned long c) · 5 unmodified lines
7654 if (vtop->r & VT_SYM)7689 if (vtop->r & VT_SYM)
7655 greloca(sec, vtop->sym, c, R_DATA_PTR, val);7690 greloca(sec, vtop->sym, c, R_DATA_PTR, val);
7656 else7691 else
7657 *(addr_t *)ptr |= val;7692 *(addr_t *)ptr = val;
7658#else7693#else
7659 if (vtop->r & VT_SYM)7694 if (vtop->r & VT_SYM)
7660 greloc(sec, vtop->sym, c, R_DATA_PTR);7695 greloc(sec, vtop->sym, c, R_DATA_PTR);
7661 *(addr_t *)ptr |= val;7696 *(addr_t *)ptr = val;
7662#endif7697#endif
7663 break;7698 break;
7664 }7699 }
@@ -7669,11 +7704,11 @@ static void init_putv(CType *type, Section *sec, unsigned long c) · 4 unmodified lines
7669 if (vtop->r & VT_SYM)7704 if (vtop->r & VT_SYM)
7670 greloca(sec, vtop->sym, c, R_DATA_PTR, val);7705 greloca(sec, vtop->sym, c, R_DATA_PTR, val);
7671 else7706 else
7672 *(int *)ptr |= val;7707 *(int *)ptr = val;
7673#else7708#else
7674 if (vtop->r & VT_SYM)7709 if (vtop->r & VT_SYM)
7675 greloc(sec, vtop->sym, c, R_DATA_PTR);7710 greloc(sec, vtop->sym, c, R_DATA_PTR);
7676 *(int *)ptr |= val;7711 *(int *)ptr = val;
7677#endif7712#endif
7678 break;7713 break;
7679 }7714 }
@@ -7693,8 +7728,7 @@ static void init_putv(CType *type, Section *sec, unsigned long c) · 13 unmodified lines
7693 allocation. 'flags & DIF_FIRST' is true if array '{' must be read (multi7728 allocation. 'flags & DIF_FIRST' is true if array '{' must be read (multi
7694 dimension implicit array init handling). 'flags & DIF_SIZE_ONLY' is true if7729 dimension implicit array init handling). 'flags & DIF_SIZE_ONLY' is true if
7695 size only evaluation is wanted (only for arrays). */7730 size only evaluation is wanted (only for arrays). */
7696static void decl_initializer(CType *type, Section *sec, unsigned long c, 7731static void decl_initializer(init_params *p, CType *type, unsigned long c, int flags)
7697 int flags)
7698{7732{
7699 int len, n, no_oblock, i;7733 int len, n, no_oblock, i;
7700 int size1, align1;7734 int size1, align1;
@@ -7702,13 +7736,17 @@ static void decl_initializer(CType *type, Section *sec, unsigned long c, · 1 unmodified line
7702 Sym indexsym;7736 Sym indexsym;
7703 CType *t1;7737 CType *t1;
7704 7738
7739 /* generate line number info */
7740 if (!p->sec && tcc_state->do_debug)
7741 tcc_debug_line(tcc_state);
7742
7705 if (!(flags & DIF_HAVE_ELEM) && tok != '{' &&7743 if (!(flags & DIF_HAVE_ELEM) && tok != '{' &&
7706 /* In case of strings we have special handling for arrays, so7744 /* In case of strings we have special handling for arrays, so
7707 don't consume them as initializer value (which would commit them7745 don't consume them as initializer value (which would commit them
7708 to some anonymous symbol). */7746 to some anonymous symbol). */
7709 tok != TOK_LSTR && tok != TOK_STR &&7747 tok != TOK_LSTR && tok != TOK_STR &&
7710 !(flags & DIF_SIZE_ONLY)) {7748 !(flags & DIF_SIZE_ONLY)) {
7711 parse_init_elem(!sec ? EXPR_ANY : EXPR_CONST);7749 parse_init_elem(!p->sec ? EXPR_ANY : EXPR_CONST);
7712 flags |= DIF_HAVE_ELEM;7750 flags |= DIF_HAVE_ELEM;
7713 }7751 }
7714 7752
@@ -7718,23 +7756,21 @@ static void decl_initializer(CType *type, Section *sec, unsigned long c, · 3 unmodified lines
7718 The source type might have VT_CONSTANT set, which is7756 The source type might have VT_CONSTANT set, which is
7719 of course assignable to non-const elements. */7757 of course assignable to non-const elements. */
7720 is_compatible_unqualified_types(type, &vtop->type)) {7758 is_compatible_unqualified_types(type, &vtop->type)) {
7721 init_putv(type, sec, c);7759 goto init_putv;
7722 } else if (type->t & VT_ARRAY) {
7723 s = type->ref;
7724 n = s->c;
7725 t1 = pointed_type(type);
7726 size1 = type_size(t1, &align1);
7727 7760
7761 } else if (type->t & VT_ARRAY) {
7728 no_oblock = 1;7762 no_oblock = 1;
7729 if (((flags & DIF_FIRST) && tok != TOK_LSTR && tok != TOK_STR) ||7763 if (((flags & DIF_FIRST) && tok != TOK_LSTR && tok != TOK_STR) ||
7730 tok == '{') {7764 tok == '{') {
7731 if (tok != '{')
7732 tcc_error("character array initializer must be a literal,"
7733 " optionally enclosed in braces");
7734 skip('{');7765 skip('{');
7735 no_oblock = 0;7766 no_oblock = 0;
7736 }7767 }
7737 7768
7769 s = type->ref;
7770 n = s->c;
7771 t1 = pointed_type(type);
7772 size1 = type_size(t1, &align1);
7773
7738 /* only parse strings here if correct type (otherwise: handle7774 /* only parse strings here if correct type (otherwise: handle
7739 them as ((w)char *) expressions */7775 them as ((w)char *) expressions */
7740 if ((tok == TOK_LSTR && 7776 if ((tok == TOK_LSTR &&
@@ -7744,7 +7780,6 @@ static void decl_initializer(CType *type, Section *sec, unsigned long c, · 3 unmodified lines
7744 (t1->t & VT_BTYPE) == VT_INT7780 (t1->t & VT_BTYPE) == VT_INT
7745#endif7781#endif
7746 ) || (tok == TOK_STR && (t1->t & VT_BTYPE) == VT_BYTE)) {7782 ) || (tok == TOK_STR && (t1->t & VT_BTYPE) == VT_BYTE)) {
7747 int nb;
7748 len = 0;7783 len = 0;
7749 cstr_reset(&initstr);7784 cstr_reset(&initstr);
7750 if (size1 != (tok == TOK_STR ? 1 : sizeof(nwchar_t)))7785 if (size1 != (tok == TOK_STR ? 1 : sizeof(nwchar_t)))
@@ -7766,54 +7801,61 @@ static void decl_initializer(CType *type, Section *sec, unsigned long c, · 15 unmodified lines
7766 unget_tok(size1 == 1 ? TOK_STR : TOK_LSTR);7801 unget_tok(size1 == 1 ? TOK_STR : TOK_LSTR);
7767 tokc.str.size = initstr.size;7802 tokc.str.size = initstr.size;
7768 tokc.str.data = initstr.data;7803 tokc.str.data = initstr.data;
7769 indexsym.c = 0;7804 goto do_init_array;
7770 f = &indexsym;
7771 goto do_init_list;
7772 }7805 }
7773 nb = len;7806
7774 if (n >= 0 && len > n)
7775 nb = n;
7776 if (!(flags & DIF_SIZE_ONLY)) {7807 if (!(flags & DIF_SIZE_ONLY)) {
7777 if (sec && !NODATA_WANTED &&7808 int nb = n;
7778 (c + nb > sec->data_allocated))7809 if (len < nb)
7779 nb = sec->data_allocated - c;7810 nb = len;
7780 if (len > nb)7811 if (len > nb)
7781 tcc_warning("initializer-string for array is too long");7812 tcc_warning("initializer-string for array is too long");
7782 /* in order to go faster for common case (char7813 /* in order to go faster for common case (char
7783 string in global variable, we handle it7814 string in global variable, we handle it
7784 specifically */7815 specifically */
7785 if (sec && size1 == 1) {7816 if (p->sec && size1 == 1) {
7817 init_assert(p, c + nb);
7786 if (!NODATA_WANTED)7818 if (!NODATA_WANTED)
7787 memcpy(sec->data + c, initstr.data, nb);7819 memcpy(p->sec->data + c, initstr.data, nb);
7788 } else {7820 } else {
7789 for(i=0;i<nb;i++) {7821 for(i=0;i<n;i++) {
7790 if (size1 == 1)7822 if (i >= nb) {
7823 /* only add trailing zero if enough storage (no
7824 warning in this case since it is standard) */
7825 if (flags & DIF_CLEAR)
7826 break;
7827 if (n - i >= 4) {
7828 init_putz(p, c + i * size1, (n - i) * size1);
7829 break;
7830 }
7831 ch = 0;
7832 } else if (size1 == 1)
7791 ch = ((unsigned char *)initstr.data)[i];7833 ch = ((unsigned char *)initstr.data)[i];
7792 else7834 else
7793 ch = ((nwchar_t *)initstr.data)[i];7835 ch = ((nwchar_t *)initstr.data)[i];
7794 vpushi(ch);7836 vpushi(ch);
7795 init_putv(t1, sec, c + i * size1);7837 init_putv(p, t1, c + i * size1);
7796 }7838 }
7797 }7839 }
7840 } else {
7841 decl_design_flex(p, s, len);
7798 }7842 }
7799 /* only add trailing zero if enough storage (no
7800 warning in this case since it is standard) */
7801 if (n < 0 || len < n) {
7802 if (!(flags & DIF_SIZE_ONLY)) {
7803 vpushi(0);
7804 init_putv(t1, sec, c + (len * size1));
7805 }
7806 len++;
7807 }
7808 len *= size1;
7809 } else {7843 } else {
7844
7845 do_init_array:
7810 indexsym.c = 0;7846 indexsym.c = 0;
7811 f = &indexsym;7847 f = &indexsym;
7812 7848
7813 do_init_list:7849 do_init_list:
7850 /* zero memory once in advance */
7851 if (!(flags & (DIF_CLEAR | DIF_SIZE_ONLY))) {
7852 init_putz(p, c, n*size1);
7853 flags |= DIF_CLEAR;
7854 }
7855
7814 len = 0;7856 len = 0;
7815 while (tok != '}' || (flags & DIF_HAVE_ELEM)) {7857 while (tok != '}' || (flags & DIF_HAVE_ELEM)) {
7816 len = decl_designator(type, sec, c, &f, flags, len, n*size1);7858 len = decl_designator(p, type, c, &f, flags, len);
7817 flags &= ~DIF_HAVE_ELEM;7859 flags &= ~DIF_HAVE_ELEM;
7818 if (type->t & VT_ARRAY) {7860 if (type->t & VT_ARRAY) {
7819 ++indexsym.c;7861 ++indexsym.c;
@@ -7836,16 +7878,9 @@ static void decl_initializer(CType *type, Section *sec, unsigned long c, · 16 unmodified lines
7836 skip(',');7878 skip(',');
7837 }7879 }
7838 }7880 }
7839 /* put zeros at the end */
7840 if (!(flags & DIF_SIZE_ONLY) && len < n*size1)
7841 init_putz(sec, c + len, n*size1 - len);
7842 if (!no_oblock)7881 if (!no_oblock)
7843 skip('}');7882 skip('}');
7844 /* patch type size if needed, which happens only for array types */
7845 if (n < 0)
7846 s->c = size1 == 1 ? len : ((len + size1 - 1)/size1);
7847 } else if ((type->t & VT_BTYPE) == VT_STRUCT) {7883 } else if ((type->t & VT_BTYPE) == VT_STRUCT) {
7848 size1 = 1;
7849 no_oblock = 1;7884 no_oblock = 1;
7850 if ((flags & DIF_FIRST) || tok == '{') {7885 if ((flags & DIF_FIRST) || tok == '{') {
7851 skip('{');7886 skip('{');
@@ -7854,12 +7889,13 @@ static void decl_initializer(CType *type, Section *sec, unsigned long c, · 2 unmodified lines
7854 s = type->ref;7889 s = type->ref;
7855 f = s->next;7890 f = s->next;
7856 n = s->c;7891 n = s->c;
7892 size1 = 1;
7857 goto do_init_list;7893 goto do_init_list;
7858 } else if (tok == '{') {7894 } else if (tok == '{') {
7859 if (flags & DIF_HAVE_ELEM)7895 if (flags & DIF_HAVE_ELEM)
7860 skip(';');7896 skip(';');
7861 next();7897 next();
7862 decl_initializer(type, sec, c, flags & ~DIF_HAVE_ELEM);7898 decl_initializer(p, type, c, flags & ~DIF_HAVE_ELEM);
7863 skip('}');7899 skip('}');
7864 } else if ((flags & DIF_SIZE_ONLY)) {7900 } else if ((flags & DIF_SIZE_ONLY)) {
7865 /* If we supported only ISO C we wouldn't have to accept calling7901 /* If we supported only ISO C we wouldn't have to accept calling
@@ -7877,9 +7913,17 @@ static void decl_initializer(CType *type, Section *sec, unsigned long c, · 11 unmodified lines
7877 string constant to memory too early. */7913 string constant to memory too early. */
7878 if (tok != TOK_STR && tok != TOK_LSTR)7914 if (tok != TOK_STR && tok != TOK_LSTR)
7879 expect("string constant");7915 expect("string constant");
7880 parse_init_elem(!sec ? EXPR_ANY : EXPR_CONST);7916 parse_init_elem(!p->sec ? EXPR_ANY : EXPR_CONST);
7881 }7917 }
7882 init_putv(type, sec, c);7918 init_putv:
7919 if (!p->sec && (flags & DIF_CLEAR) /* container was already zero'd */
7920 && (vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST
7921 && vtop->c.i == 0
7922 && btype_size(type->t & VT_BTYPE) /* not for fp constants */
7923 )
7924 vpop();
7925 else
7926 init_putv(p, type, c);
7883 }7927 }
7884}7928}
7885 7929
@@ -7903,38 +7947,60 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r, · 17 unmodified lines
7903#ifdef CONFIG_TCC_BCHECK7947#ifdef CONFIG_TCC_BCHECK
7904 int bcheck = tcc_state->do_bounds_check && !NODATA_WANTED;7948 int bcheck = tcc_state->do_bounds_check && !NODATA_WANTED;
7905#endif7949#endif
7950 init_params p = {0};
7906 7951
7907 /* Always allocate static or global variables */7952 /* Always allocate static or global variables */
7908 if (v && (r & VT_VALMASK) == VT_CONST)7953 if (v && (r & VT_VALMASK) == VT_CONST)
7909 nocode_wanted |= 0x80000000;7954 nocode_wanted |= 0x80000000;
7910 7955
7911 flexible_array = NULL;7956 flexible_array = NULL;
7912 if ((type->t & VT_BTYPE) == VT_STRUCT) {7957 size = type_size(type, &align);
7958
7959 /* exactly one flexible array may be initialized, either the
7960 toplevel array or the last member of the toplevel struct */
7961
7962 if (size < 0) {
7963 /* If the base type itself was an array type of unspecified size
7964 (like in 'typedef int arr[]; arr x = {1};') then we will
7965 overwrite the unknown size by the real one for this decl.
7966 We need to unshare the ref symbol holding that size. */
7967 type->ref = sym_push(SYM_FIELD, &type->ref->type, 0, type->ref->c);
7968 p.flex_array_ref = type->ref;
7969
7970 } else if (has_init && (type->t & VT_BTYPE) == VT_STRUCT) {
7913 Sym *field = type->ref->next;7971 Sym *field = type->ref->next;
7914 if (field) {7972 if (field) {
7915 while (field->next)7973 while (field->next)
7916 field = field->next;7974 field = field->next;
7917 if (field->type.t & VT_ARRAY && field->type.ref->c < 0)7975 if (field->type.t & VT_ARRAY && field->type.ref->c < 0) {
7918 flexible_array = field;7976 flexible_array = field;
7977 p.flex_array_ref = field->type.ref;
7978 size = -1;
7979 }
7919 }7980 }
7920 }7981 }
7921 7982
7922 size = type_size(type, &align);7983 if (size < 0) {
7923 /* If unknown size, we must evaluate it before7984 /* If unknown size, do a dry-run 1st pass */
7924 evaluating initializers because
7925 initializers can generate global data too
7926 (e.g. string pointers or ISOC99 compound
7927 literals). It also simplifies local
7928 initializers handling */
7929 if (size < 0 || (flexible_array && has_init)) {
7930 if (!has_init) 7985 if (!has_init)
7931 tcc_error("unknown type size");7986 tcc_error("unknown type size");
7932 get_init_string(&init_str, has_init);7987 if (has_init == 2) {
7988 /* only get strings */
7989 init_str = tok_str_alloc();
7990 while (tok == TOK_STR || tok == TOK_LSTR) {
7991 tok_str_add_tok(init_str);
7992 next();
7993 }
7994 tok_str_add(init_str, -1);
7995 tok_str_add(init_str, 0);
7996 } else
7997 skip_or_save_block(&init_str);
7998 unget_tok(0);
7933 7999
7934 /* compute size */8000 /* compute size */
7935 begin_macro(init_str, 1);8001 begin_macro(init_str, 1);
7936 next();8002 next();
7937 decl_initializer(type, NULL, 0, DIF_FIRST | DIF_SIZE_ONLY);8003 decl_initializer(&p, type, 0, DIF_FIRST | DIF_SIZE_ONLY);
7938 /* prepare second initializer parsing */8004 /* prepare second initializer parsing */
7939 macro_ptr = init_str->str;8005 macro_ptr = init_str->str;
7940 next();8006 next();
@@ -7943,13 +8009,14 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r, · 2 unmodified lines
7943 size = type_size(type, &align);8009 size = type_size(type, &align);
7944 if (size < 0) 8010 if (size < 0)
7945 tcc_error("unknown type size");8011 tcc_error("unknown type size");
8012
8013 /* If there's a flex member and it was used in the initializer
8014 adjust size. */
8015 if (flexible_array && flexible_array->type.ref->c > 0)
8016 size += flexible_array->type.ref->c
8017 * pointed_size(&flexible_array->type);
7946 }8018 }
7947 /* If there's a flex member and it was used in the initializer8019
7948 adjust size. */
7949 if (flexible_array &&
7950 flexible_array->type.ref->c > 0)
7951 size += flexible_array->type.ref->c
7952 * pointed_size(&flexible_array->type);
7953 /* take into account specified alignment if bigger */8020 /* take into account specified alignment if bigger */
7954 if (ad->a.aligned) {8021 if (ad->a.aligned) {
7955 int speca = 1 << (ad->a.aligned - 1);8022 int speca = 1 << (ad->a.aligned - 1);
@@ -7972,6 +8039,7 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r, · 16 unmodified lines
7972#endif8039#endif
7973 loc = (loc - size) & -align;8040 loc = (loc - size) & -align;
7974 addr = loc;8041 addr = loc;
8042 p.local_offset = addr + size;
7975#ifdef CONFIG_TCC_BCHECK8043#ifdef CONFIG_TCC_BCHECK
7976 if (bcheck && v) {8044 if (bcheck && v) {
7977 /* add padding between stack variables for bound checking */8045 /* add padding between stack variables for bound checking */
@@ -8088,12 +8156,8 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r, · 110 unmodified lines
8088 cur_scope->vla.loc = addr;8156 cur_scope->vla.loc = addr;
8089 cur_scope->vla.num++;8157 cur_scope->vla.num++;
8090 } else if (has_init) {8158 } else if (has_init) {
8091 size_t oldreloc_offset = 0;8159 p.sec = sec;
8092 if (sec && sec->reloc)8160 decl_initializer(&p, type, addr, DIF_FIRST);
8093 oldreloc_offset = sec->reloc->data_offset;
8094 decl_initializer(type, sec, addr, DIF_FIRST);
8095 if (sec && sec->reloc)
8096 squeeze_multi_relocs(sec, oldreloc_offset);
8097 /* patch flexible array member size back to -1, */8161 /* patch flexible array member size back to -1, */
8098 /* for possible subsequent similar declarations */8162 /* for possible subsequent similar declarations */
8099 if (flexible_array)8163 if (flexible_array)
@@ -8288,14 +8352,6 @@ static int decl0(int l, int is_for_loop_init, Sym *func_sym) · 188 unmodified lines
8288 }8352 }
8289 while (1) { /* iterate thru each declaration */8353 while (1) { /* iterate thru each declaration */
8290 type = btype;8354 type = btype;
8291 /* If the base type itself was an array type of unspecified
8292 size (like in 'typedef int arr[]; arr x = {1};') then
8293 we will overwrite the unknown size by the real one for
8294 this decl. We need to unshare the ref symbol holding
8295 that size. */
8296 if ((type.t & VT_ARRAY) && type.ref->c < 0) {
8297 type.ref = sym_push(SYM_FIELD, &type.ref->type, 0, type.ref->c);
8298 }
8299 ad = adbase;8355 ad = adbase;
8300 type_decl(&type, &ad, &v, TYPE_DIRECT);8356 type_decl(&type, &ad, &v, TYPE_DIRECT);
8301#if 08357#if 0
tccpp.c+8−7
@@ -2586,7 +2586,7 @@ static void parse_number(const char *p) · 2585 unmodified lines
2586 tokc.i = n;2586 tokc.i = n;
2587 }2587 }
2588 if (ch)2588 if (ch)
2589 tcc_error("invalid number\n");2589 tcc_error("invalid number");
2590}2590}
2591 2591
2592 2592
@@ -3674,20 +3674,20 @@ static void tcc_predefs(CString *cstr) · 1081 unmodified lines
3674 "#define __builtin_va_copy(dest,src) (dest)=(src)\n"3674 "#define __builtin_va_copy(dest,src) (dest)=(src)\n"
3675 "#endif\n"3675 "#endif\n"
3676 "#ifdef __leading_underscore\n"3676 "#ifdef __leading_underscore\n"
3677 "#define RENAME(X) __asm__(\"_\"X)\n"3677 "#define __RENAME(X) __asm__(\"_\"X)\n"
3678 "#else\n"3678 "#else\n"
3679 "#define RENAME(X) __asm__(X)\n"3679 "#define __RENAME(X) __asm__(X)\n"
3680 "#endif\n"3680 "#endif\n"
3681 /* TCC BBUILTIN AND BOUNDS ALIASES */3681 /* TCC BBUILTIN AND BOUNDS ALIASES */
3682 "#ifdef __BOUNDS_CHECKING_ON\n"3682 "#ifdef __BOUNDS_CHECKING_ON\n"
3683 "#define __BUILTINBC(ret,name,params) ret __builtin_##name params RENAME(\"__bound_\"#name);\n"3683 "#define __BUILTINBC(ret,name,params) ret __builtin_##name params __RENAME(\"__bound_\"#name);\n"
3684 "#define __BOUND(ret,name,params) ret name params RENAME(\"__bound_\"#name);\n"3684 "#define __BOUND(ret,name,params) ret name params __RENAME(\"__bound_\"#name);\n"
3685 "#else\n"3685 "#else\n"
3686 "#define __BUILTINBC(ret,name,params) ret __builtin_##name params RENAME(#name);\n"3686 "#define __BUILTINBC(ret,name,params) ret __builtin_##name params __RENAME(#name);\n"
3687 "#define __BOUND(ret,name,params)\n"3687 "#define __BOUND(ret,name,params)\n"
3688 "#endif\n"3688 "#endif\n"
3689 "#define __BOTH(ret,name,params) __BUILTINBC(ret,name,params)__BOUND(ret,name,params)\n"3689 "#define __BOTH(ret,name,params) __BUILTINBC(ret,name,params)__BOUND(ret,name,params)\n"
3690 "#define __BUILTIN(ret,name,params) ret __builtin_##name params RENAME(#name);\n"3690 "#define __BUILTIN(ret,name,params) ret __builtin_##name params __RENAME(#name);\n"
3691 "__BOTH(void*,memcpy,(void*,const void*,__SIZE_TYPE__))\n"3691 "__BOTH(void*,memcpy,(void*,const void*,__SIZE_TYPE__))\n"
3692 "__BOTH(void*,memmove,(void*,const void*,__SIZE_TYPE__))\n"3692 "__BOTH(void*,memmove,(void*,const void*,__SIZE_TYPE__))\n"
3693 "__BOTH(void*,memset,(void*,int,__SIZE_TYPE__))\n"3693 "__BOTH(void*,memset,(void*,int,__SIZE_TYPE__))\n"
@@ -3731,6 +3731,7 @@ static void tcc_predefs(CString *cstr) · 37 unmodified lines
3731 "#undef __BOUND\n"3731 "#undef __BOUND\n"
3732 "#undef __BOTH\n"3732 "#undef __BOTH\n"
3733 "#undef __MAYBE_REDIR\n"3733 "#undef __MAYBE_REDIR\n"
3734 "#undef __RENAME\n"
3734 , -1);3735 , -1);
3735}3736}
3736 3737
tests/tests2/60_errors_and_warnings.c+9−0
@@ -346,4 +346,13 @@ static struct var_len { int i; const char str[]; } var_array[] = · 345 unmodified lines
346 { 2, "longlonglonglonglong" },346 { 2, "longlonglonglonglong" },
347 { 3, "tst3" } };347 { 3, "tst3" } };
348 348
349#elif defined test_var_array2
350
351struct c1 { int a; int b[]; };
352struct c1 c1 = { 1, { 2, 3, 4 } };
353
354struct c2 { int c; struct c1 c1; };
355struct c2 c2 = { 1, { 2, { 3, 4, 5 }}};
356
357/******************************************************************/
349#endif358#endif
tests/tests2/60_errors_and_warnings.expect+4−1
@@ -161,4 +161,7 @@ bar : 3 ; 3 · 160 unmodified lines
161\n161\n
162 162
163[test_var_array]163[test_var_array]
16460_errors_and_warnings.c:345: warning: initializer-string for array is too long16460_errors_and_warnings.c:345: error: flexible array has zero size in this context
165
166[test_var_array2]
16760_errors_and_warnings.c:355: error: flexible array has zero size in this context
tests/tests2/90_struct-init.c+55−8
@@ -221,19 +221,66 @@ void sys_ni(void) { printf("ni\n"); } · 220 unmodified lines
221void sys_one(void) { printf("one\n"); }221void sys_one(void) { printf("one\n"); }
222void sys_two(void) { printf("two\n"); }222void sys_two(void) { printf("two\n"); }
223void sys_three(void) { printf("three\n"); }223void sys_three(void) { printf("three\n"); }
224void sys_four(void) { printf("four\n"); }
224typedef void (*fptr)(void);225typedef void (*fptr)(void);
225const fptr table[3] = {226
226 [0 ... 2] = &sys_ni,227#define array_size(a) (sizeof a / sizeof a[0])
227 [0] = sys_one,
228 [1] = sys_two,
229 [2] = sys_three,
230};
231 228
232void test_multi_relocs(void)229void test_multi_relocs(void)
233{230{
234 int i;231 int i;
235 for (i = 0; i < sizeof(table)/sizeof(table[0]); i++)232
236 table[i]();233 static const fptr tabl1[4] = {
234 [0 ... 3] = &sys_ni,
235 [0] = sys_one,
236 [1] = sys_two,
237 [2] = sys_three,
238 sys_four,
239 [1 ... 2] = &sys_ni,
240 [1] = 0,
241 };
242 for (i = 0; i < array_size(tabl1); i++)
243 if (tabl1[i])
244 tabl1[i]();
245 else
246 printf("(0)\n");
247
248 const fptr tabl2[4] = {
249 [0 ... 3] = &sys_ni,
250 [0] = sys_one,
251 [1] = sys_two,
252 [2] = sys_three,
253 sys_four,
254 [1 ... 2] = &sys_ni,
255 [1] = 0,
256 };
257 for (i = 0; i < array_size(tabl2); i++)
258 if (tabl2[i])
259 tabl2[i]();
260 else
261 printf("(0)\n");
262
263 int c = 0;
264 int dd[] = {
265 [0 ... 1] = ++c,
266 [2 ... 3] = ++c
267 };
268 for (i = 0; i < array_size(dd); i++)
269 printf(" %d", dd[i]);
270 printf("\n");
271
272 /* multi-dimensional flex array with range initializers */
273 static char m1[][2][3] = {[0 ... 2]={{3,4,5},{6,7,8}},{{9},10},"abc"};
274 char m2[][2][3] = {[0 ... 2]={{3,4,5},{6,7,8}},{{9},10},"abc"};
275 int g, j, k;
276 for (g = 2; g-- > 0;) {
277 printf("mdfa %s: %d -", "locl\0glob" + g * 5, sizeof m1);
278 for (i = 0; i < array_size(m1); i++)
279 for (j = 0; j < array_size(m1[0]); j++)
280 for (k = 0; k < array_size(m1[0][0]); k++)
281 printf(" %d", (g ? m1:m2)[i][j][k]);
282 printf("\n");
283 }
237}284}
238 285
239void test_init_ranges(void) {286void test_init_ranges(void) {
tests/tests2/90_struct-init.expect+10−2
@@ -41,8 +41,16 @@ lssu2: 5 0 0 0 3 0 0 0 · 40 unmodified lines
41flow: 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 041flow: 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
42ls4: 1 2 3 442ls4: 1 2 3 4
43one43one
44two44(0)
45three45ni
46four
47one
48(0)
49ni
50four
51 1 1 2 2
52mdfa glob: 30 - 3 4 5 6 7 8 3 4 5 6 7 8 3 4 5 6 7 8 9 0 0 10 0 0 97 98 99 0 0 0
53mdfa locl: 30 - 3 4 5 6 7 8 3 4 5 6 7 8 3 4 5 6 7 8 9 0 0 10 0 0 97 98 99 0 0 0
46sea_fill0: okay54sea_fill0: okay
47sea_fill1: okay55sea_fill1: okay
48sea_fill2: okay56sea_fill2: okay