| @@ -81,6 +81,7 @@ ST_DATA int func_vc; · 80 unmodified lines |
| 81 | 81 | static int last_line_num, new_file, func_ind; /* debug info control */ |
| 82 | 82 | ST_DATA const char *funcname; |
| 83 | 83 | ST_DATA CType int_type, func_old_type, char_pointer_type; |
| 84 | +static CString initstr; |
| 84 | 85 | |
| 85 | 86 | #if PTR_SIZE == 4 |
| 86 | 87 | #define VT_SIZE_T (VT_INT | VT_UNSIGNED) |
| @@ -779,6 +780,7 @@ ST_FUNC void tccgen_init(TCCState *s1) · 692 unmodified lines |
| 779 | 780 | #ifdef precedence_parser |
| 780 | 781 | init_prec(); |
| 781 | 782 | #endif |
| 783 | + cstr_new(&initstr); |
| 782 | 784 | } |
| 783 | 785 | |
| 784 | 786 | ST_FUNC int tccgen_compile(TCCState *s1) |
| @@ -810,6 +812,7 @@ ST_FUNC int tccgen_compile(TCCState *s1) · 25 unmodified lines |
| 810 | 812 | |
| 811 | 813 | ST_FUNC void tccgen_finish(TCCState *s1) |
| 812 | 814 | { |
| 815 | + cstr_free(&initstr); |
| 813 | 816 | free_inline_functions(s1); |
| 814 | 817 | sym_pop(&global_stack, NULL, 0); |
| 815 | 818 | sym_pop(&local_stack, NULL, 0); |
| @@ -3219,7 +3222,6 @@ redo: · 2403 unmodified lines |
| 3219 | 3222 | gen_cast_s(VT_INT); |
| 3220 | 3223 | #endif |
| 3221 | 3224 | type1 = vtop[-1].type; |
| 3222 | | − type1.t &= ~VT_ARRAY; |
| 3223 | 3225 | if (vtop[-1].type.t & VT_VLA) |
| 3224 | 3226 | vla_runtime_pointed_size(&vtop[-1].type); |
| 3225 | 3227 | else { |
| @@ -3249,6 +3251,7 @@ redo: · 23 unmodified lines |
| 3249 | 3251 | { |
| 3250 | 3252 | gen_opic(op); |
| 3251 | 3253 | } |
| 3254 | + type1.t &= ~VT_ARRAY; |
| 3252 | 3255 | /* put again type if gen_opic() swaped operands */ |
| 3253 | 3256 | vtop->type = type1; |
| 3254 | 3257 | } |
| @@ -7229,12 +7232,12 @@ static void parse_init_elem(int expr_type) · 3974 unmodified lines |
| 7229 | 7232 | /* NOTE: symbols are accepted, as well as lvalue for anon symbols |
| 7230 | 7233 | (compound literals). */ |
| 7231 | 7234 | if (((vtop->r & (VT_VALMASK | VT_LVAL)) != VT_CONST |
| 7232 | | − && ((vtop->r & (VT_SYM|VT_LVAL)) != (VT_SYM|VT_LVAL) |
| 7233 | | − || vtop->sym->v < SYM_FIRST_ANOM)) |
| 7235 | + && ((vtop->r & (VT_SYM|VT_LVAL)) != (VT_SYM|VT_LVAL) |
| 7236 | + || vtop->sym->v < SYM_FIRST_ANOM)) |
| 7234 | 7237 | #ifdef TCC_TARGET_PE |
| 7235 | 7238 | || ((vtop->r & VT_SYM) && vtop->sym->a.dllimport) |
| 7236 | 7239 | #endif |
| 7237 | | − ) |
| 7240 | + ) |
| 7238 | 7241 | tcc_error("initializer element is not constant"); |
| 7239 | 7242 | break; |
| 7240 | 7243 | case EXPR_ANY: |
| @@ -7442,7 +7445,7 @@ static void init_putv(CType *type, Section *sec, unsigned long c) · 201 unmodified lines |
| 7442 | 7445 | anonymous one. That is, there's no difference in vtop |
| 7443 | 7446 | between '(void *){x}' and '&(void *){x}'. Ignore |
| 7444 | 7447 | pointer typed entities here. Hopefully no real code |
| 7445 | | − will every use compound literals with scalar type. */ |
| 7448 | + will ever use compound literals with scalar type. */ |
| 7446 | 7449 | (vtop->type.t & VT_BTYPE) != VT_PTR) { |
| 7447 | 7450 | /* These come from compound literals, memcpy stuff over. */ |
| 7448 | 7451 | Section *ssec; |
| @@ -7450,7 +7453,7 @@ static void init_putv(CType *type, Section *sec, unsigned long c) · 1 unmodified line |
| 7450 | 7453 | ElfW_Rel *rel; |
| 7451 | 7454 | esym = elfsym(vtop->sym); |
| 7452 | 7455 | ssec = tcc_state->sections[esym->st_shndx]; |
| 7453 | | − memmove (ptr, ssec->data + esym->st_value, size); |
| 7456 | + memmove (ptr, ssec->data + esym->st_value + (int)vtop->c.i, size); |
| 7454 | 7457 | if (ssec->reloc) { |
| 7455 | 7458 | /* We need to copy over all memory contents, and that |
| 7456 | 7459 | includes relocations. Use the fact that relocs are |
| @@ -7593,7 +7596,7 @@ static void init_putv(CType *type, Section *sec, unsigned long c) · 136 unmodified lines |
| 7593 | 7596 | static void decl_initializer(CType *type, Section *sec, unsigned long c, |
| 7594 | 7597 | int flags) |
| 7595 | 7598 | { |
| 7596 | | − int len, n, no_oblock, nb, i; |
| 7599 | + int len, n, no_oblock, i; |
| 7597 | 7600 | int size1, align1; |
| 7598 | 7601 | Sym *s, *f; |
| 7599 | 7602 | Sym indexsym; |
| @@ -7641,41 +7644,54 @@ static void decl_initializer(CType *type, Section *sec, unsigned long c, · 41 unmodified lines |
| 7641 | 7644 | (t1->t & VT_BTYPE) == VT_INT |
| 7642 | 7645 | #endif |
| 7643 | 7646 | ) || (tok == TOK_STR && (t1->t & VT_BTYPE) == VT_BYTE)) { |
| 7647 | + int nb; |
| 7644 | 7648 | len = 0; |
| 7649 | + cstr_reset(&initstr); |
| 7650 | + if (size1 != (tok == TOK_STR ? 1 : sizeof(nwchar_t))) |
| 7651 | + tcc_error("unhandled string literal merging"); |
| 7645 | 7652 | while (tok == TOK_STR || tok == TOK_LSTR) { |
| 7646 | | − int cstr_len, ch; |
| 7647 | | − |
| 7648 | | − /* compute maximum number of chars wanted */ |
| 7653 | + if (initstr.size) |
| 7654 | + initstr.size -= size1; |
| 7649 | 7655 | if (tok == TOK_STR) |
| 7650 | | − cstr_len = tokc.str.size; |
| 7656 | + len += tokc.str.size; |
| 7651 | 7657 | else |
| 7652 | | − cstr_len = tokc.str.size / sizeof(nwchar_t); |
| 7653 | | − cstr_len--; |
| 7654 | | − nb = cstr_len; |
| 7655 | | − if (n >= 0 && nb > (n - len)) |
| 7656 | | − nb = n - len; |
| 7657 | | − if (!(flags & DIF_SIZE_ONLY)) { |
| 7658 | | − if (cstr_len > nb) |
| 7659 | | − tcc_warning("initializer-string for array is too long"); |
| 7660 | | − /* in order to go faster for common case (char |
| 7661 | | − string in global variable, we handle it |
| 7662 | | − specifically */ |
| 7663 | | − if (sec && tok == TOK_STR && size1 == 1) { |
| 7664 | | − if (!NODATA_WANTED) |
| 7665 | | − memcpy(sec->data + c + len, tokc.str.data, nb); |
| 7666 | | − } else { |
| 7667 | | − for(i=0;i<nb;i++) { |
| 7668 | | − if (tok == TOK_STR) |
| 7669 | | − ch = ((unsigned char *)tokc.str.data)[i]; |
| 7670 | | − else |
| 7671 | | − ch = ((nwchar_t *)tokc.str.data)[i]; |
| 7672 | | − vpushi(ch); |
| 7673 | | − init_putv(t1, sec, c + (len + i) * size1); |
| 7674 | | − } |
| 7658 | + len += tokc.str.size / sizeof(nwchar_t); |
| 7659 | + len--; |
| 7660 | + cstr_cat(&initstr, tokc.str.data, tokc.str.size); |
| 7661 | + next(); |
| 7662 | + } |
| 7663 | + if (tok != ')' && tok != '}' && tok != ',' && tok != ';' |
| 7664 | + && tok != TOK_EOF) { |
| 7665 | + /* Not a lone literal but part of a bigger expression. */ |
| 7666 | + unget_tok(size1 == 1 ? TOK_STR : TOK_LSTR); |
| 7667 | + tokc.str.size = initstr.size; |
| 7668 | + tokc.str.data = initstr.data; |
| 7669 | + indexsym.c = 0; |
| 7670 | + f = &indexsym; |
| 7671 | + goto do_init_list; |
| 7672 | + } |
| 7673 | + nb = len; |
| 7674 | + if (n >= 0 && len > n) |
| 7675 | + nb = n; |
| 7676 | + if (!(flags & DIF_SIZE_ONLY)) { |
| 7677 | + if (len > nb) |
| 7678 | + tcc_warning("initializer-string for array is too long"); |
| 7679 | + /* in order to go faster for common case (char |
| 7680 | + string in global variable, we handle it |
| 7681 | + specifically */ |
| 7682 | + if (sec && size1 == 1) { |
| 7683 | + if (!NODATA_WANTED) |
| 7684 | + memcpy(sec->data + c, initstr.data, nb); |
| 7685 | + } else { |
| 7686 | + for(i=0;i<nb;i++) { |
| 7687 | + if (size1 == 1) |
| 7688 | + ch = ((unsigned char *)initstr.data)[i]; |
| 7689 | + else |
| 7690 | + ch = ((nwchar_t *)initstr.data)[i]; |
| 7691 | + vpushi(ch); |
| 7692 | + init_putv(t1, sec, c + i * size1); |
| 7675 | 7693 | } |
| 7676 | 7694 | } |
| 7677 | | − len += nb; |
| 7678 | | − next(); |
| 7679 | 7695 | } |
| 7680 | 7696 | /* only add trailing zero if enough storage (no |
| 7681 | 7697 | warning in this case since it is standard) */ |