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