This matters when sizeof is directly used in arithmetic, ala "uintptr_t t; t &= -sizeof(long)" (for alignment). When sizeof isn't size_t (as it's specified to be) this masking will truncate the high bits of the uintptr_t object (if uintptr_t is larger than uint).
Unified · Split
| @@ -745,6 +745,12 @@ static int tcc_compile(TCCState *s1) · 744 unmodified lines | ||
| 745 | 745 | char_pointer_type.t = VT_BYTE; |
| 746 | 746 | mk_pointer(&char_pointer_type); |
| 747 | 747 | |
| 748 | +#if PTR_SIZE == 4 | |
| 749 | + size_type.t = VT_INT; | |
| 750 | +#else | |
| 751 | + size_type.t = VT_LLONG; | |
| 752 | +#endif | |
| 753 | + | |
| 748 | 754 | func_old_type.t = VT_FUNC; |
| 749 | 755 | func_old_type.ref = sym_push(SYM_FIELD, &int_type, FUNC_CDECL, FUNC_OLD); |
| 750 | 756 | |
| @@ -1117,7 +1117,7 @@ ST_DATA Sym *local_stack; · 1116 unmodified lines | ||
| 1117 | 1117 | ST_DATA Sym *local_label_stack; |
| 1118 | 1118 | ST_DATA Sym *global_label_stack; |
| 1119 | 1119 | ST_DATA Sym *define_stack; |
| 1120 | −ST_DATA CType char_pointer_type, func_old_type, int_type; | |
| 1120 | +ST_DATA CType char_pointer_type, func_old_type, int_type, size_type; | |
| 1121 | 1121 | ST_DATA SValue vstack[VSTACK_SIZE], *vtop; |
| 1122 | 1122 | ST_DATA int rsym, anon_sym, ind, loc; |
| 1123 | 1123 | |
| @@ -64,7 +64,7 @@ ST_DATA int func_vc; · 63 unmodified lines | ||
| 64 | 64 | ST_DATA int last_line_num, last_ind, func_ind; /* debug last line number and pc */ |
| 65 | 65 | ST_DATA char *funcname; |
| 66 | 66 | |
| 67 | −ST_DATA CType char_pointer_type, func_old_type, int_type; | |
| 67 | +ST_DATA CType char_pointer_type, func_old_type, int_type, size_type; | |
| 68 | 68 | |
| 69 | 69 | /* ------------------------------------------------------------------------- */ |
| 70 | 70 | static void gen_cast(CType *type); |
| @@ -325,6 +325,17 @@ ST_FUNC void vpushi(int v) · 254 unmodified lines | ||
| 325 | 325 | vsetc(&int_type, VT_CONST, &cval); |
| 326 | 326 | } |
| 327 | 327 | |
| 328 | +/* push a pointer sized constant */ | |
| 329 | +static void vpushs(long long v) | |
| 330 | +{ | |
| 331 | + CValue cval; | |
| 332 | + if (PTR_SIZE == 4) | |
| 333 | + cval.i = (int)v; | |
| 334 | + else | |
| 335 | + cval.ull = v; | |
| 336 | + vsetc(&size_type, VT_CONST, &cval); | |
| 337 | +} | |
| 338 | + | |
| 328 | 339 | /* push long long constant */ |
| 329 | 340 | static void vpushll(long long v) |
| 330 | 341 | { |
| @@ -3575,12 +3586,12 @@ ST_FUNC void unary(void) · 3244 unmodified lines | ||
| 3575 | 3586 | if (!(type.t & VT_VLA)) { |
| 3576 | 3587 | if (size < 0) |
| 3577 | 3588 | tcc_error("sizeof applied to an incomplete type"); |
| 3578 | − vpushi(size); | |
| 3589 | + vpushs(size); | |
| 3579 | 3590 | } else { |
| 3580 | 3591 | vla_runtime_type_size(&type, &align); |
| 3581 | 3592 | } |
| 3582 | 3593 | } else { |
| 3583 | − vpushi(align); | |
| 3594 | + vpushs(align); | |
| 3584 | 3595 | } |
| 3585 | 3596 | vtop->type.t |= VT_UNSIGNED; |
| 3586 | 3597 | break; |
| @@ -2155,6 +2155,8 @@ void c99_vla_test(int size1, int size2) · 2154 unmodified lines | ||
| 2155 | 2155 | #endif |
| 2156 | 2156 | } |
| 2157 | 2157 | |
| 2158 | +typedef __SIZE_TYPE__ uintptr_t; | |
| 2159 | + | |
| 2158 | 2160 | void sizeof_test(void) |
| 2159 | 2161 | { |
| 2160 | 2162 | int a; |
| @@ -2175,6 +2177,20 @@ void sizeof_test(void) · 14 unmodified lines | ||
| 2175 | 2177 | ptr = NULL; |
| 2176 | 2178 | printf("sizeof(**ptr) = %d\n", sizeof (**ptr)); |
| 2177 | 2179 | |
| 2180 | + /* The type of sizeof should be as large as a pointer, actually | |
| 2181 | + it should be size_t. */ | |
| 2182 | + printf("sizeof(sizeof(int) = %d\n", sizeof(sizeof(int))); | |
| 2183 | + uintptr_t t = 1; | |
| 2184 | + uintptr_t t2; | |
| 2185 | + /* Effectively <<32, but defined also on 32bit machines. */ | |
| 2186 | + t <<= 16; | |
| 2187 | + t <<= 16; | |
| 2188 | + t++; | |
| 2189 | + /* This checks that sizeof really can be used to manipulate | |
| 2190 | + uintptr_t objects, without truncation. */ | |
| 2191 | + t2 = t & -sizeof(uintptr_t); | |
| 2192 | + printf ("%lu %lu\n", t, t2); | |
| 2193 | + | |
| 2178 | 2194 | /* some alignof tests */ |
| 2179 | 2195 | printf("__alignof__(int) = %d\n", __alignof__(int)); |
| 2180 | 2196 | printf("__alignof__(unsigned int) = %d\n", __alignof__(unsigned int)); |