| @@ -78,6 +78,7 @@ static void block(int *bsym, int *csym, int *case_sym, int *def_sym, int case_re · 77 unmodified lines |
| 78 | static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r, int has_init, int v, int scope); | 78 | static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r, int has_init, int v, int scope); |
| 79 | static void expr_eq(void); | 79 | static void expr_eq(void); |
| 80 | static void unary_type(CType *type); | 80 | static void unary_type(CType *type); |
| | 81 | static void vla_runtime_type_size(CType *type, int *a); |
| 81 | static int is_compatible_parameter_types(CType *type1, CType *type2); | 82 | static int is_compatible_parameter_types(CType *type1, CType *type2); |
| 82 | static void expr_type(CType *type); | 83 | static void expr_type(CType *type); |
| 83 | | 84 | |
| @@ -1455,6 +1456,12 @@ static int pointed_size(CType *type) · 1371 unmodified lines |
| 1455 | return type_size(pointed_type(type), &align); | 1456 | return type_size(pointed_type(type), &align); |
| 1456 | } | 1457 | } |
| 1457 | | 1458 | |
| | 1459 | static void vla_runtime_pointed_size(CType *type) |
| | 1460 | { |
| | 1461 | int align; |
| | 1462 | vla_runtime_type_size(pointed_type(type), &align); |
| | 1463 | } |
| | 1464 | |
| 1458 | static inline int is_null_pointer(SValue *p) | 1465 | static inline int is_null_pointer(SValue *p) |
| 1459 | { | 1466 | { |
| 1460 | if ((p->r & (VT_VALMASK | VT_LVAL | VT_SYM)) != VT_CONST) | 1467 | if ((p->r & (VT_VALMASK | VT_LVAL | VT_SYM)) != VT_CONST) |
| @@ -1543,11 +1550,20 @@ ST_FUNC void gen_op(int op) · 82 unmodified lines |
| 1543 | } | 1550 | } |
| 1544 | /* if both pointers, then it must be the '-' op */ | 1551 | /* if both pointers, then it must be the '-' op */ |
| 1545 | if (bt1 == VT_PTR && bt2 == VT_PTR) { | 1552 | if (bt1 == VT_PTR && bt2 == VT_PTR) { |
| | 1553 | int ptr1_is_vla; |
| | 1554 | |
| | 1555 | ptr1_is_vla = 0; |
| 1546 | if (op != '-') | 1556 | if (op != '-') |
| 1547 | error("cannot use pointers here"); | 1557 | error("cannot use pointers here"); |
| 1548 | check_comparison_pointer_types(vtop - 1, vtop, op); | 1558 | check_comparison_pointer_types(vtop - 1, vtop, op); |
| 1549 | /* XXX: check that types are compatible */ | 1559 | /* XXX: check that types are compatible */ |
| 1550 | u = pointed_size(&vtop[-1].type); | 1560 | if (vtop[-1].type.t & VT_VLA) { |
| | 1561 | vla_runtime_pointed_size(&vtop[-1].type); |
| | 1562 | vrott(3); |
| | 1563 | ptr1_is_vla = 1; |
| | 1564 | } else { |
| | 1565 | u = pointed_size(&vtop[-1].type); |
| | 1566 | } |
| 1551 | gen_opic(op); | 1567 | gen_opic(op); |
| 1552 | /* set to integer type */ | 1568 | /* set to integer type */ |
| 1553 | #ifdef TCC_TARGET_X86_64 | 1569 | #ifdef TCC_TARGET_X86_64 |
| @@ -1555,7 +1571,10 @@ ST_FUNC void gen_op(int op) · 1 unmodified line |
| 1555 | #else | 1571 | #else |
| 1556 | vtop->type.t = VT_INT; | 1572 | vtop->type.t = VT_INT; |
| 1557 | #endif | 1573 | #endif |
| 1558 | vpushi(u); | 1574 | if (ptr1_is_vla) |
| | 1575 | vswap(); |
| | 1576 | else |
| | 1577 | vpushi(u); |
| 1559 | gen_op(TOK_PDIV); | 1578 | gen_op(TOK_PDIV); |
| 1560 | } else { | 1579 | } else { |
| 1561 | /* exactly one pointer : must be '+' or '-'. */ | 1580 | /* exactly one pointer : must be '+' or '-'. */ |
| @@ -1567,16 +1586,20 @@ ST_FUNC void gen_op(int op) · 5 unmodified lines |
| 1567 | swap(&t1, &t2); | 1586 | swap(&t1, &t2); |
| 1568 | } | 1587 | } |
| 1569 | type1 = vtop[-1].type; | 1588 | type1 = vtop[-1].type; |
| 1570 | type1.t &= ~VT_ARRAY; | 1589 | type1.t &= ~(VT_ARRAY|VT_VLA); |
| 1571 | u = pointed_size(&vtop[-1].type); | 1590 | if (vtop[-1].type.t & VT_VLA) |
| 1572 | if (u < 0) | 1591 | vla_runtime_pointed_size(&vtop[-1].type); |
| 1573 | error("unknown array element size"); | 1592 | else { |
| | 1593 | u = pointed_size(&vtop[-1].type); |
| | 1594 | if (u < 0) |
| | 1595 | error("unknown array element size"); |
| 1574 | #ifdef TCC_TARGET_X86_64 | 1596 | #ifdef TCC_TARGET_X86_64 |
| 1575 | vpushll(u); | 1597 | vpushll(u); |
| 1576 | #else | 1598 | #else |
| 1577 | /* XXX: cast to int ? (long long case) */ | 1599 | /* XXX: cast to int ? (long long case) */ |
| 1578 | vpushi(u); | 1600 | vpushi(u); |
| 1579 | #endif | 1601 | #endif |
| | 1602 | } |
| 1580 | gen_op('*'); | 1603 | gen_op('*'); |
| 1581 | #ifdef CONFIG_TCC_BCHECK | 1604 | #ifdef CONFIG_TCC_BCHECK |
| 1582 | /* if evaluating constant expression, no code should be | 1605 | /* if evaluating constant expression, no code should be |
| @@ -1932,7 +1955,7 @@ static void gen_cast(CType *type) · 349 unmodified lines |
| 1932 | vtop->type = *type; | 1955 | vtop->type = *type; |
| 1933 | } | 1956 | } |
| 1934 | | 1957 | |
| 1935 | /* return type size. Put alignment at 'a' */ | 1958 | /* return type size as known at compile time. Put alignment at 'a' */ |
| 1936 | ST_FUNC int type_size(CType *type, int *a) | 1959 | ST_FUNC int type_size(CType *type, int *a) |
| 1937 | { | 1960 | { |
| 1938 | Sym *s; | 1961 | Sym *s; |
| @@ -1945,7 +1968,10 @@ ST_FUNC int type_size(CType *type, int *a) · 6 unmodified lines |
| 1945 | *a = s->r; | 1968 | *a = s->r; |
| 1946 | return s->c; | 1969 | return s->c; |
| 1947 | } else if (bt == VT_PTR) { | 1970 | } else if (bt == VT_PTR) { |
| 1948 | if (type->t & VT_ARRAY) { | 1971 | if (type->t & VT_VLA) { |
| | 1972 | *a = 1; |
| | 1973 | return 0; |
| | 1974 | } else if (type->t & VT_ARRAY) { |
| 1949 | int ts; | 1975 | int ts; |
| 1950 | | 1976 | |
| 1951 | s = type->ref; | 1977 | s = type->ref; |
| @@ -1992,6 +2018,30 @@ ST_FUNC int type_size(CType *type, int *a) · 40 unmodified lines |
| 1992 | } | 2018 | } |
| 1993 | } | 2019 | } |
| 1994 | | 2020 | |
| | 2021 | /* push type size as known at runtime time on top of value stack. Put |
| | 2022 | alignment at 'a' */ |
| | 2023 | ST_FUNC void vla_runtime_type_size(CType *type, int *a) |
| | 2024 | { |
| | 2025 | if (type->t & VT_VLA) { |
| | 2026 | Sym *s; |
| | 2027 | |
| | 2028 | s = type->ref; |
| | 2029 | vla_runtime_type_size(&s->type, a); |
| | 2030 | vpushv(s->s); |
| | 2031 | if ((vtop->r & (VT_SYM|VT_LVAL|VT_VALMASK)) != VT_CONST) { |
| | 2032 | gv_dup(); |
| | 2033 | vswap(); |
| | 2034 | vpop(); |
| | 2035 | } |
| | 2036 | gen_op('*'); |
| | 2037 | } else { |
| | 2038 | int size; |
| | 2039 | |
| | 2040 | size = type_size(type, a); |
| | 2041 | vpushi(size); |
| | 2042 | } |
| | 2043 | } |
| | 2044 | |
| 1995 | /* return the pointed type of t */ | 2045 | /* return the pointed type of t */ |
| 1996 | static inline CType *pointed_type(CType *type) | 2046 | static inline CType *pointed_type(CType *type) |
| 1997 | { | 2047 | { |
| @@ -3103,25 +3153,43 @@ static void post_type(CType *type, AttributeDef *ad) · 1105 unmodified lines |
| 3103 | type->t = t1 | VT_FUNC; | 3153 | type->t = t1 | VT_FUNC; |
| 3104 | type->ref = s; | 3154 | type->ref = s; |
| 3105 | } else if (tok == '[') { | 3155 | } else if (tok == '[') { |
| | 3156 | SValue *last_vtop = NULL; |
| | 3157 | |
| 3106 | /* array definition */ | 3158 | /* array definition */ |
| 3107 | next(); | 3159 | next(); |
| 3108 | if (tok == TOK_RESTRICT1) | 3160 | if (tok == TOK_RESTRICT1) |
| 3109 | next(); | 3161 | next(); |
| 3110 | n = -1; | 3162 | n = -1; |
| 3111 | if (tok != ']') { | 3163 | if (tok != ']') { |
| 3112 | n = expr_const(); | 3164 | gexpr(); |
| 3113 | if (n < 0) | 3165 | if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) { |
| 3114 | error("invalid array size"); | 3166 | n = vtop->c.i; |
| | 3167 | last_vtop = vtop; |
| | 3168 | if (n < 0) |
| | 3169 | error("invalid array size"); |
| | 3170 | } else { |
| | 3171 | if (!is_integer_btype(vtop->type.t & VT_BTYPE)) |
| | 3172 | error("size of variable length array should be an integer"); |
| | 3173 | type->t |= VT_VLA; |
| | 3174 | last_vtop = vtop; |
| | 3175 | } |
| 3115 | } | 3176 | } |
| 3116 | skip(']'); | 3177 | skip(']'); |
| 3117 | /* parse next post type */ | 3178 | /* parse next post type */ |
| 3118 | t1 = type->t & VT_STORAGE; | 3179 | t1 = type->t & (VT_STORAGE|VT_VLA); |
| 3119 | type->t &= ~VT_STORAGE; | 3180 | type->t &= ~(VT_STORAGE|VT_VLA); |
| 3120 | post_type(type, ad); | 3181 | post_type(type, ad); |
| | 3182 | t1 |= type->t & VT_VLA; |
| 3121 | | 3183 | |
| 3122 | /* we push a anonymous symbol which will contain the array | 3184 | /* we push an anonymous symbol which will contain the array |
| 3123 | element type */ | 3185 | element type */ |
| 3124 | s = sym_push(SYM_FIELD, type, 0, n); | 3186 | s = sym_push(SYM_FIELD, type, 0, n); |
| | 3187 | if (t1 & VT_VLA) { |
| | 3188 | s->s = last_vtop; // That's ok, we don't need n with VLA |
| | 3189 | } else { |
| | 3190 | if (n >= 0) |
| | 3191 | vpop(); |
| | 3192 | } |
| 3125 | type->t = t1 | VT_ARRAY | VT_PTR; | 3193 | type->t = t1 | VT_ARRAY | VT_PTR; |
| 3126 | type->ref = s; | 3194 | type->ref = s; |
| 3127 | } | 3195 | } |
| @@ -3490,11 +3558,18 @@ ST_FUNC void unary(void) · 362 unmodified lines |
| 3490 | next(); | 3558 | next(); |
| 3491 | in_sizeof++; | 3559 | in_sizeof++; |
| 3492 | unary_type(&type); // Perform a in_sizeof = 0; | 3560 | unary_type(&type); // Perform a in_sizeof = 0; |
| 3493 | size = type_size(&type, &align); | 3561 | if ((t == TOK_SIZEOF) && (type.t & VT_VLA)) { |
| | 3562 | vla_runtime_type_size(&type, &align); |
| | 3563 | size = 0; |
| | 3564 | } else { |
| | 3565 | size = type_size(&type, &align); |
| | 3566 | } |
| 3494 | if (t == TOK_SIZEOF) { | 3567 | if (t == TOK_SIZEOF) { |
| 3495 | if (size < 0) | 3568 | if (!(type.t & VT_VLA)) { |
| 3496 | error("sizeof applied to an incomplete type"); | 3569 | if (size < 0) |
| 3497 | vpushi(size); | 3570 | error("sizeof applied to an incomplete type"); |
| | 3571 | vpushi(size); |
| | 3572 | } |
| 3498 | } else { | 3573 | } else { |
| 3499 | vpushi(align); | 3574 | vpushi(align); |
| 3500 | } | 3575 | } |
| @@ -3653,7 +3728,10 @@ ST_FUNC void unary(void) · 152 unmodified lines |
| 3653 | } else { | 3728 | } else { |
| 3654 | r = s->r; | 3729 | r = s->r; |
| 3655 | } | 3730 | } |
| 3656 | vset(&s->type, r, s->c); | 3731 | if (s->type.t & VT_VLA) |
| | 3732 | vpushv(s->s); |
| | 3733 | else |
| | 3734 | vset(&s->type, r, s->c); |
| 3657 | /* if forward reference, we must point to s */ | 3735 | /* if forward reference, we must point to s */ |
| 3658 | if (vtop->r & VT_SYM) { | 3736 | if (vtop->r & VT_SYM) { |
| 3659 | vtop->sym = s; | 3737 | vtop->sym = s; |
| @@ -4782,7 +4860,18 @@ static void decl_initializer(CType *type, Section *sec, unsigned long c, · 1122 unmodified lines |
| 4782 | Sym *s, *f; | 4860 | Sym *s, *f; |
| 4783 | CType *t1; | 4861 | CType *t1; |
| 4784 | | 4862 | |
| 4785 | if (type->t & VT_ARRAY) { | 4863 | if (type->t & VT_VLA) { |
| | 4864 | int a; |
| | 4865 | CValue retcval; |
| | 4866 | |
| | 4867 | vpush_global_sym(&func_old_type, TOK_alloca); |
| | 4868 | vla_runtime_type_size(type, &a); |
| | 4869 | gfunc_call(1); |
| | 4870 | |
| | 4871 | /* return value */ |
| | 4872 | retcval.i = 0; |
| | 4873 | vsetc(type, REG_IRET, &retcval); |
| | 4874 | } else if (type->t & VT_ARRAY) { |
| 4786 | s = type->ref; | 4875 | s = type->ref; |
| 4787 | n = s->c; | 4876 | n = s->c; |
| 4788 | array_length = 0; | 4877 | array_length = 0; |
| @@ -5013,6 +5102,7 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r, · 224 unmodified lines |
| 5013 | ParseState saved_parse_state = {0}; | 5102 | ParseState saved_parse_state = {0}; |
| 5014 | TokenString init_str; | 5103 | TokenString init_str; |
| 5015 | Section *sec; | 5104 | Section *sec; |
| | 5105 | Sym *vla = NULL; |
| 5016 | | 5106 | |
| 5017 | size = type_size(type, &align); | 5107 | size = type_size(type, &align); |
| 5018 | /* If unknown size, we must evaluate it before | 5108 | /* If unknown size, we must evaluate it before |
| @@ -5078,8 +5168,12 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r, · 59 unmodified lines |
| 5078 | if ((r & VT_VALMASK) == VT_LOCAL) { | 5168 | if ((r & VT_VALMASK) == VT_LOCAL) { |
| 5079 | sec = NULL; | 5169 | sec = NULL; |
| 5080 | #ifdef CONFIG_TCC_BCHECK | 5170 | #ifdef CONFIG_TCC_BCHECK |
| 5081 | if (tcc_state->do_bounds_check && (type->t & VT_ARRAY)) | 5171 | if (tcc_state->do_bounds_check && (type->t & VT_ARRAY)) { |
| 5082 | loc--; | 5172 | if (type->t & VT_VLA) |
| | 5173 | warning("Array bound check don't work for VLA"); |
| | 5174 | else |
| | 5175 | loc--; |
| | 5176 | } |
| 5083 | #endif | 5177 | #endif |
| 5084 | loc = (loc - size) & -align; | 5178 | loc = (loc - size) & -align; |
| 5085 | addr = loc; | 5179 | addr = loc; |
| @@ -5087,7 +5181,8 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r, · 1 unmodified line |
| 5087 | /* handles bounds */ | 5181 | /* handles bounds */ |
| 5088 | /* XXX: currently, since we do only one pass, we cannot track | 5182 | /* XXX: currently, since we do only one pass, we cannot track |
| 5089 | '&' operators, so we add only arrays */ | 5183 | '&' operators, so we add only arrays */ |
| 5090 | if (tcc_state->do_bounds_check && (type->t & VT_ARRAY)) { | 5184 | if (tcc_state->do_bounds_check && (type->t & VT_ARRAY) && |
| | 5185 | !(type->t & VT_VLA)) { |
| 5091 | unsigned long *bounds_ptr; | 5186 | unsigned long *bounds_ptr; |
| 5092 | /* add padding between regions */ | 5187 | /* add padding between regions */ |
| 5093 | loc--; | 5188 | loc--; |
| @@ -5099,7 +5194,7 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r, · 5 unmodified lines |
| 5099 | #endif | 5194 | #endif |
| 5100 | if (v) { | 5195 | if (v) { |
| 5101 | /* local variable */ | 5196 | /* local variable */ |
| 5102 | sym_push(v, type, r, addr); | 5197 | vla = sym_push(v, type, r, addr); |
| 5103 | } else { | 5198 | } else { |
| 5104 | /* push local reference */ | 5199 | /* push local reference */ |
| 5105 | vset(type, r, addr); | 5200 | vset(type, r, addr); |
| @@ -5214,8 +5309,10 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r, · 108 unmodified lines |
| 5214 | } | 5309 | } |
| 5215 | #endif | 5310 | #endif |
| 5216 | } | 5311 | } |
| 5217 | if (has_init) { | 5312 | if (has_init || (type->t & VT_VLA)) { |
| 5218 | decl_initializer(type, sec, addr, 1, 0); | 5313 | decl_initializer(type, sec, addr, 1, 0); |
| | 5314 | if (type->t & VT_VLA) |
| | 5315 | vla->s = vtop; |
| 5219 | /* restore parse state if needed */ | 5316 | /* restore parse state if needed */ |
| 5220 | if (init_str.str) { | 5317 | if (init_str.str) { |
| 5221 | tok_str_free(init_str.str); | 5318 | tok_str_free(init_str.str); |
| @@ -5584,9 +5681,12 @@ ST_FUNC void decl(int l) · 362 unmodified lines |
| 5584 | if (!(type.t & VT_ARRAY)) | 5681 | if (!(type.t & VT_ARRAY)) |
| 5585 | r |= lvalue_type(type.t); | 5682 | r |= lvalue_type(type.t); |
| 5586 | has_init = (tok == '='); | 5683 | has_init = (tok == '='); |
| | 5684 | if (has_init && (type.t & VT_VLA)) |
| | 5685 | error("Variable length array cannot be initialized"); |
| 5587 | if ((btype.t & VT_EXTERN) || | 5686 | if ((btype.t & VT_EXTERN) || |
| 5588 | ((type.t & VT_ARRAY) && (type.t & VT_STATIC) && | 5687 | ((type.t & VT_ARRAY) && (!(type.t & VT_VLA)) && |
| 5589 | !has_init && l == VT_CONST && type.ref->c < 0)) { | 5688 | (type.t & VT_STATIC) && !has_init && l == VT_CONST && |
| | 5689 | type.ref->c < 0)) { |
| 5590 | /* external variable */ | 5690 | /* external variable */ |
| 5591 | /* NOTE: as GCC, uninitialized global static | 5691 | /* NOTE: as GCC, uninitialized global static |
| 5592 | arrays of null size are considered as | 5692 | arrays of null size are considered as |