History

Make sizeof() be of type size_t

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).

Michael Matz committed 14 years ago

Commit 718fd591 parent b068e294 files · +37 −4Browse files

Unified · Split

4 files
  1. libtcc.c +6 −0
  2. tcc.h +1 −1
  3. tccgen.c +14 −3
  4. tests/tcctest.c +16 −0
libtcc.c+6−0
@@ -745,6 +745,12 @@ static int tcc_compile(TCCState *s1) · 744 unmodified lines
745745 char_pointer_type.t = VT_BYTE;
746746 mk_pointer(&char_pointer_type);
747747
748+#if PTR_SIZE == 4
749+ size_type.t = VT_INT;
750+#else
751+ size_type.t = VT_LLONG;
752+#endif
753+
748754 func_old_type.t = VT_FUNC;
749755 func_old_type.ref = sym_push(SYM_FIELD, &int_type, FUNC_CDECL, FUNC_OLD);
750756
tcc.h+1−1
@@ -1117,7 +1117,7 @@ ST_DATA Sym *local_stack; · 1116 unmodified lines
11171117 ST_DATA Sym *local_label_stack;
11181118 ST_DATA Sym *global_label_stack;
11191119 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;
11211121 ST_DATA SValue vstack[VSTACK_SIZE], *vtop;
11221122 ST_DATA int rsym, anon_sym, ind, loc;
11231123
tccgen.c+14−3
@@ -64,7 +64,7 @@ ST_DATA int func_vc; · 63 unmodified lines
6464 ST_DATA int last_line_num, last_ind, func_ind; /* debug last line number and pc */
6565 ST_DATA char *funcname;
6666
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;
6868
6969 /* ------------------------------------------------------------------------- */
7070 static void gen_cast(CType *type);
@@ -325,6 +325,17 @@ ST_FUNC void vpushi(int v) · 254 unmodified lines
325325 vsetc(&int_type, VT_CONST, &cval);
326326 }
327327
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+
328339 /* push long long constant */
329340 static void vpushll(long long v)
330341 {
@@ -3575,12 +3586,12 @@ ST_FUNC void unary(void) · 3244 unmodified lines
35753586 if (!(type.t & VT_VLA)) {
35763587 if (size < 0)
35773588 tcc_error("sizeof applied to an incomplete type");
3578− vpushi(size);
3589+ vpushs(size);
35793590 } else {
35803591 vla_runtime_type_size(&type, &align);
35813592 }
35823593 } else {
3583− vpushi(align);
3594+ vpushs(align);
35843595 }
35853596 vtop->type.t |= VT_UNSIGNED;
35863597 break;
tests/tcctest.c+16−0
@@ -2155,6 +2155,8 @@ void c99_vla_test(int size1, int size2) · 2154 unmodified lines
21552155 #endif
21562156 }
21572157
2158+typedef __SIZE_TYPE__ uintptr_t;
2159+
21582160 void sizeof_test(void)
21592161 {
21602162 int a;
@@ -2175,6 +2177,20 @@ void sizeof_test(void) · 14 unmodified lines
21752177 ptr = NULL;
21762178 printf("sizeof(**ptr) = %d\n", sizeof (**ptr));
21772179
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+
21782194 /* some alignof tests */
21792195 printf("__alignof__(int) = %d\n", __alignof__(int));
21802196 printf("__alignof__(unsigned int) = %d\n", __alignof__(unsigned int));