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 | char_pointer_type.t = VT_BYTE; | 745 | char_pointer_type.t = VT_BYTE; |
| 746 | mk_pointer(&char_pointer_type); | 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 | func_old_type.t = VT_FUNC; | 754 | func_old_type.t = VT_FUNC; |
| 749 | func_old_type.ref = sym_push(SYM_FIELD, &int_type, FUNC_CDECL, FUNC_OLD); | 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 | ST_DATA Sym *local_label_stack; | 1117 | ST_DATA Sym *local_label_stack; |
| 1118 | ST_DATA Sym *global_label_stack; | 1118 | ST_DATA Sym *global_label_stack; |
| 1119 | ST_DATA Sym *define_stack; | 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 | ST_DATA SValue vstack[VSTACK_SIZE], *vtop; | 1121 | ST_DATA SValue vstack[VSTACK_SIZE], *vtop; |
| 1122 | ST_DATA int rsym, anon_sym, ind, loc; | 1122 | ST_DATA int rsym, anon_sym, ind, loc; |
| 1123 | 1123 | ||
| @@ -64,7 +64,7 @@ ST_DATA int func_vc; · 63 unmodified lines | |||
| 64 | ST_DATA int last_line_num, last_ind, func_ind; /* debug last line number and pc */ | 64 | ST_DATA int last_line_num, last_ind, func_ind; /* debug last line number and pc */ |
| 65 | ST_DATA char *funcname; | 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 | static void gen_cast(CType *type); | 70 | static void gen_cast(CType *type); |
| @@ -325,6 +325,17 @@ ST_FUNC void vpushi(int v) · 254 unmodified lines | |||
| 325 | vsetc(&int_type, VT_CONST, &cval); | 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 | /* push long long constant */ | 339 | /* push long long constant */ |
| 329 | static void vpushll(long long v) | 340 | static void vpushll(long long v) |
| 330 | { | 341 | { |
| @@ -3575,12 +3586,12 @@ ST_FUNC void unary(void) · 3244 unmodified lines | |||
| 3575 | if (!(type.t & VT_VLA)) { | 3586 | if (!(type.t & VT_VLA)) { |
| 3576 | if (size < 0) | 3587 | if (size < 0) |
| 3577 | tcc_error("sizeof applied to an incomplete type"); | 3588 | tcc_error("sizeof applied to an incomplete type"); |
| 3578 | vpushi(size); | 3589 | vpushs(size); |
| 3579 | } else { | 3590 | } else { |
| 3580 | vla_runtime_type_size(&type, &align); | 3591 | vla_runtime_type_size(&type, &align); |
| 3581 | } | 3592 | } |
| 3582 | } else { | 3593 | } else { |
| 3583 | vpushi(align); | 3594 | vpushs(align); |
| 3584 | } | 3595 | } |
| 3585 | vtop->type.t |= VT_UNSIGNED; | 3596 | vtop->type.t |= VT_UNSIGNED; |
| 3586 | break; | 3597 | break; |
| @@ -2155,6 +2155,8 @@ void c99_vla_test(int size1, int size2) · 2154 unmodified lines | |||
| 2155 | #endif | 2155 | #endif |
| 2156 | } | 2156 | } |
| 2157 | 2157 | ||
| 2158 | typedef __SIZE_TYPE__ uintptr_t; | ||
| 2159 | |||
| 2158 | void sizeof_test(void) | 2160 | void sizeof_test(void) |
| 2159 | { | 2161 | { |
| 2160 | int a; | 2162 | int a; |
| @@ -2175,6 +2177,20 @@ void sizeof_test(void) · 14 unmodified lines | |||
| 2175 | ptr = NULL; | 2177 | ptr = NULL; |
| 2176 | printf("sizeof(**ptr) = %d\n", sizeof (**ptr)); | 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 | /* some alignof tests */ | 2194 | /* some alignof tests */ |
| 2179 | printf("__alignof__(int) = %d\n", __alignof__(int)); | 2195 | printf("__alignof__(int) = %d\n", __alignof__(int)); |
| 2180 | printf("__alignof__(unsigned int) = %d\n", __alignof__(unsigned int)); | 2196 | printf("__alignof__(unsigned int) = %d\n", __alignof__(unsigned int)); |