| @@ -93,7 +93,7 @@ static int parse_btype(CType *type, AttributeDef *ad); · 92 unmodified lines |
| 93 | 93 | static CType *type_decl(CType *type, AttributeDef *ad, int *v, int td); |
| 94 | 94 | static void parse_expr_type(CType *type); |
| 95 | 95 | static void init_putv(CType *type, Section *sec, unsigned long c); |
| 96 | | −static void decl_initializer(CType *type, Section *sec, unsigned long c, int first, int size_only); |
| 96 | +static void decl_initializer(CType *type, Section *sec, unsigned long c, int flags); |
| 97 | 97 | static void block(int *bsym, int *csym, int is_expr); |
| 98 | 98 | static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r, int has_init, int v, int scope); |
| 99 | 99 | static void decl(int l); |
| @@ -6596,14 +6596,18 @@ static void init_putz(Section *sec, unsigned long c, int size) · 6496 unmodified lines |
| 6596 | 6596 | } |
| 6597 | 6597 | } |
| 6598 | 6598 | |
| 6599 | +#define DIF_FIRST 1 |
| 6600 | +#define DIF_SIZE_ONLY 2 |
| 6601 | +#define DIF_HAVE_ELEM 4 |
| 6602 | + |
| 6599 | 6603 | /* t is the array or struct type. c is the array or struct |
| 6600 | 6604 | address. cur_field is the pointer to the current |
| 6601 | 6605 | field, for arrays the 'c' member contains the current start |
| 6602 | | − index. 'size_only' is true if only size info is needed (only used |
| 6603 | | − in arrays). al contains the already initialized length of the |
| 6606 | + index. 'flags' is as in decl_initializer. |
| 6607 | + 'al' contains the already initialized length of the |
| 6604 | 6608 | current container (starting at c). This returns the new length of that. */ |
| 6605 | 6609 | static int decl_designator(CType *type, Section *sec, unsigned long c, |
| 6606 | | − Sym **cur_field, int size_only, int al) |
| 6610 | + Sym **cur_field, int flags, int al) |
| 6607 | 6611 | { |
| 6608 | 6612 | Sym *s, *f; |
| 6609 | 6613 | int index, index_last, align, l, nb_elems, elem_size; |
| @@ -6611,6 +6615,8 @@ static int decl_designator(CType *type, Section *sec, unsigned long c, · 1 unmodified line |
| 6611 | 6615 | |
| 6612 | 6616 | elem_size = 0; |
| 6613 | 6617 | nb_elems = 1; |
| 6618 | + if (flags & DIF_HAVE_ELEM) |
| 6619 | + goto no_designator; |
| 6614 | 6620 | if (gnu_ext && (l = is_label()) != 0) |
| 6615 | 6621 | goto struct_field; |
| 6616 | 6622 | /* NOTE: we only support ranges for last designator */ |
| @@ -6659,6 +6665,7 @@ static int decl_designator(CType *type, Section *sec, unsigned long c, · 42 unmodified lines |
| 6659 | 6665 | expect("="); |
| 6660 | 6666 | } |
| 6661 | 6667 | } else { |
| 6668 | + no_designator: |
| 6662 | 6669 | if (type->t & VT_ARRAY) { |
| 6663 | 6670 | index = (*cur_field)->c; |
| 6664 | 6671 | if (type->ref->c >= 0 && index >= type->ref->c) |
| @@ -6677,12 +6684,12 @@ static int decl_designator(CType *type, Section *sec, unsigned long c, · 12 unmodified lines |
| 6677 | 6684 | } |
| 6678 | 6685 | /* must put zero in holes (note that doing it that way |
| 6679 | 6686 | ensures that it even works with designators) */ |
| 6680 | | − if (!size_only && c - corig > al) |
| 6687 | + if (!(flags & DIF_SIZE_ONLY) && c - corig > al) |
| 6681 | 6688 | init_putz(sec, corig + al, c - corig - al); |
| 6682 | | − decl_initializer(type, sec, c, 0, size_only); |
| 6689 | + decl_initializer(type, sec, c, flags & ~DIF_FIRST); |
| 6683 | 6690 | |
| 6684 | 6691 | /* XXX: make it more general */ |
| 6685 | | − if (!size_only && nb_elems > 1) { |
| 6692 | + if (!(flags & DIF_SIZE_ONLY) && nb_elems > 1) { |
| 6686 | 6693 | unsigned long c_end; |
| 6687 | 6694 | uint8_t *src, *dst; |
| 6688 | 6695 | int i; |
| @@ -6905,33 +6912,29 @@ static void init_putv(CType *type, Section *sec, unsigned long c) · 216 unmodified lines |
| 6905 | 6912 | |
| 6906 | 6913 | /* 't' contains the type and storage info. 'c' is the offset of the |
| 6907 | 6914 | object in section 'sec'. If 'sec' is NULL, it means stack based |
| 6908 | | − allocation. 'first' is true if array '{' must be read (multi |
| 6909 | | − dimension implicit array init handling). 'size_only' is true if |
| 6915 | + allocation. 'flags & DIF_FIRST' is true if array '{' must be read (multi |
| 6916 | + dimension implicit array init handling). 'flags & DIF_SIZE_ONLY' is true if |
| 6910 | 6917 | size only evaluation is wanted (only for arrays). */ |
| 6911 | 6918 | static void decl_initializer(CType *type, Section *sec, unsigned long c, |
| 6912 | | − int first, int size_only) |
| 6919 | + int flags) |
| 6913 | 6920 | { |
| 6914 | 6921 | int len, n, no_oblock, nb, i; |
| 6915 | 6922 | int size1, align1; |
| 6916 | | − int have_elem; |
| 6917 | 6923 | Sym *s, *f; |
| 6918 | 6924 | Sym indexsym; |
| 6919 | 6925 | CType *t1; |
| 6920 | 6926 | |
| 6921 | | − /* If we currently are at an '}' or ',' we have read an initializer |
| 6922 | | − element in one of our callers, and not yet consumed it. */ |
| 6923 | | − have_elem = tok == '}' || tok == ','; |
| 6924 | | − if (!have_elem && tok != '{' && |
| 6927 | + if (!(flags & DIF_HAVE_ELEM) && tok != '{' && |
| 6925 | 6928 | /* In case of strings we have special handling for arrays, so |
| 6926 | 6929 | don't consume them as initializer value (which would commit them |
| 6927 | 6930 | to some anonymous symbol). */ |
| 6928 | 6931 | tok != TOK_LSTR && tok != TOK_STR && |
| 6929 | | − !size_only) { |
| 6932 | + !(flags & DIF_SIZE_ONLY)) { |
| 6930 | 6933 | parse_init_elem(!sec ? EXPR_ANY : EXPR_CONST); |
| 6931 | | − have_elem = 1; |
| 6934 | + flags |= DIF_HAVE_ELEM; |
| 6932 | 6935 | } |
| 6933 | 6936 | |
| 6934 | | − if (have_elem && |
| 6937 | + if ((flags & DIF_HAVE_ELEM) && |
| 6935 | 6938 | !(type->t & VT_ARRAY) && |
| 6936 | 6939 | /* Use i_c_parameter_t, to strip toplevel qualifiers. |
| 6937 | 6940 | The source type might have VT_CONSTANT set, which is |
| @@ -6945,15 +6948,13 @@ static void decl_initializer(CType *type, Section *sec, unsigned long c, · 7 unmodified lines |
| 6945 | 6948 | size1 = type_size(t1, &align1); |
| 6946 | 6949 | |
| 6947 | 6950 | no_oblock = 1; |
| 6948 | | − if ((first && tok != TOK_LSTR && tok != TOK_STR) || |
| 6951 | + if (((flags & DIF_FIRST) && tok != TOK_LSTR && tok != TOK_STR) || |
| 6949 | 6952 | tok == '{') { |
| 6950 | 6953 | if (tok != '{') |
| 6951 | 6954 | tcc_error("character array initializer must be a literal," |
| 6952 | 6955 | " optionally enclosed in braces"); |
| 6953 | 6956 | skip('{'); |
| 6954 | 6957 | no_oblock = 0; |
| 6955 | | − if (tok == ',') |
| 6956 | | − tcc_error("unexpected ','"); |
| 6957 | 6958 | } |
| 6958 | 6959 | |
| 6959 | 6960 | /* only parse strings here if correct type (otherwise: handle |
| @@ -6978,7 +6979,7 @@ static void decl_initializer(CType *type, Section *sec, unsigned long c, · 18 unmodified lines |
| 6978 | 6979 | nb = cstr_len; |
| 6979 | 6980 | if (n >= 0 && nb > (n - len)) |
| 6980 | 6981 | nb = n - len; |
| 6981 | | − if (!size_only) { |
| 6982 | + if (!(flags & DIF_SIZE_ONLY)) { |
| 6982 | 6983 | if (cstr_len > nb) |
| 6983 | 6984 | tcc_warning("initializer-string for array is too long"); |
| 6984 | 6985 | /* in order to go faster for common case (char |
| @@ -7004,7 +7005,7 @@ static void decl_initializer(CType *type, Section *sec, unsigned long c, · 19 unmodified lines |
| 7004 | 7005 | /* only add trailing zero if enough storage (no |
| 7005 | 7006 | warning in this case since it is standard) */ |
| 7006 | 7007 | if (n < 0 || len < n) { |
| 7007 | | − if (!size_only) { |
| 7008 | + if (!(flags & DIF_SIZE_ONLY)) { |
| 7008 | 7009 | vpushi(0); |
| 7009 | 7010 | init_putv(t1, sec, c + (len * size1)); |
| 7010 | 7011 | } |
| @@ -7017,9 +7018,9 @@ static void decl_initializer(CType *type, Section *sec, unsigned long c, · 6 unmodified lines |
| 7017 | 7018 | |
| 7018 | 7019 | do_init_list: |
| 7019 | 7020 | len = 0; |
| 7020 | | − while (tok != '}' || have_elem) { |
| 7021 | | − len = decl_designator(type, sec, c, &f, size_only, len); |
| 7022 | | − have_elem = 0; |
| 7021 | + while (tok != '}' || (flags & DIF_HAVE_ELEM)) { |
| 7022 | + len = decl_designator(type, sec, c, &f, flags, len); |
| 7023 | + flags &= ~DIF_HAVE_ELEM; |
| 7023 | 7024 | if (type->t & VT_ARRAY) { |
| 7024 | 7025 | ++indexsym.c; |
| 7025 | 7026 | /* special test for multi dimensional arrays (may not |
| @@ -7042,7 +7043,7 @@ static void decl_initializer(CType *type, Section *sec, unsigned long c, · 16 unmodified lines |
| 7042 | 7043 | } |
| 7043 | 7044 | } |
| 7044 | 7045 | /* put zeros at the end */ |
| 7045 | | − if (!size_only && len < n*size1) |
| 7046 | + if (!(flags & DIF_SIZE_ONLY) && len < n*size1) |
| 7046 | 7047 | init_putz(sec, c + len, n*size1 - len); |
| 7047 | 7048 | if (!no_oblock) |
| 7048 | 7049 | skip('}'); |
| @@ -7052,7 +7053,7 @@ static void decl_initializer(CType *type, Section *sec, unsigned long c, · 3 unmodified lines |
| 7052 | 7053 | } else if ((type->t & VT_BTYPE) == VT_STRUCT) { |
| 7053 | 7054 | size1 = 1; |
| 7054 | 7055 | no_oblock = 1; |
| 7055 | | − if (first || tok == '{') { |
| 7056 | + if ((flags & DIF_FIRST) || tok == '{') { |
| 7056 | 7057 | skip('{'); |
| 7057 | 7058 | no_oblock = 0; |
| 7058 | 7059 | } |
| @@ -7061,20 +7062,22 @@ static void decl_initializer(CType *type, Section *sec, unsigned long c, · 2 unmodified lines |
| 7061 | 7062 | n = s->c; |
| 7062 | 7063 | goto do_init_list; |
| 7063 | 7064 | } else if (tok == '{') { |
| 7065 | + if (flags & DIF_HAVE_ELEM) |
| 7066 | + skip(';'); |
| 7064 | 7067 | next(); |
| 7065 | | − decl_initializer(type, sec, c, first, size_only); |
| 7068 | + decl_initializer(type, sec, c, flags & ~DIF_HAVE_ELEM); |
| 7066 | 7069 | skip('}'); |
| 7067 | | − } else if (size_only) { |
| 7070 | + } else if ((flags & DIF_SIZE_ONLY)) { |
| 7068 | 7071 | /* If we supported only ISO C we wouldn't have to accept calling |
| 7069 | | − this on anything than an array size_only==1 (and even then |
| 7072 | + this on anything than an array if DIF_SIZE_ONLY (and even then |
| 7070 | 7073 | only on the outermost level, so no recursion would be needed), |
| 7071 | 7074 | because initializing a flex array member isn't supported. |
| 7072 | 7075 | But GNU C supports it, so we need to recurse even into |
| 7073 | | − subfields of structs and arrays when size_only is set. */ |
| 7076 | + subfields of structs and arrays when DIF_SIZE_ONLY is set. */ |
| 7074 | 7077 | /* just skip expression */ |
| 7075 | 7078 | skip_or_save_block(NULL); |
| 7076 | 7079 | } else { |
| 7077 | | − if (!have_elem) { |
| 7080 | + if (!(flags & DIF_HAVE_ELEM)) { |
| 7078 | 7081 | /* This should happen only when we haven't parsed |
| 7079 | 7082 | the init element above for fear of committing a |
| 7080 | 7083 | string constant to memory too early. */ |
| @@ -7154,7 +7157,7 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r, · 73 unmodified lines |
| 7154 | 7157 | /* compute size */ |
| 7155 | 7158 | begin_macro(init_str, 1); |
| 7156 | 7159 | next(); |
| 7157 | | − decl_initializer(type, NULL, 0, 1, 1); |
| 7160 | + decl_initializer(type, NULL, 0, DIF_FIRST | DIF_SIZE_ONLY); |
| 7158 | 7161 | /* prepare second initializer parsing */ |
| 7159 | 7162 | macro_ptr = init_str->str; |
| 7160 | 7163 | next(); |
| @@ -7321,7 +7324,7 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r, · 160 unmodified lines |
| 7321 | 7324 | size_t oldreloc_offset = 0; |
| 7322 | 7325 | if (sec && sec->reloc) |
| 7323 | 7326 | oldreloc_offset = sec->reloc->data_offset; |
| 7324 | | − decl_initializer(type, sec, addr, 1, 0); |
| 7327 | + decl_initializer(type, sec, addr, DIF_FIRST); |
| 7325 | 7328 | if (sec && sec->reloc) |
| 7326 | 7329 | squeeze_multi_relocs(sec, oldreloc_offset); |
| 7327 | 7330 | /* patch flexible array member size back to -1, */ |