From 718fd591fa93ff254a9ca68a0ad2ff8a55756489 Mon Sep 17 00:00:00 2001 From: Michael Matz Date: Mon, 16 Apr 2012 01:13:25 +0200 Subject: [PATCH 8/9] 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). --- libtcc.c | 6 ++++++ tcc.h | 2 +- tccgen.c | 17 ++++++++++++++--- tests/tcctest.c | 16 ++++++++++++++++ 4 files changed, 37 insertions(+), 4 deletions(-) diff --git a/libtcc.c b/libtcc.c index c6b8d38..01280de 100644 --- a/libtcc.c +++ b/libtcc.c @@ -745,6 +745,12 @@ static int tcc_compile(TCCState *s1) char_pointer_type.t = VT_BYTE; mk_pointer(&char_pointer_type); +#if PTR_SIZE == 4 + size_type.t = VT_INT; +#else + size_type.t = VT_LLONG; +#endif + func_old_type.t = VT_FUNC; func_old_type.ref = sym_push(SYM_FIELD, &int_type, FUNC_CDECL, FUNC_OLD); diff --git a/tcc.h b/tcc.h index 95d5030..a674f92 100644 --- a/tcc.h +++ b/tcc.h @@ -1117,7 +1117,7 @@ ST_DATA Sym *local_stack; ST_DATA Sym *local_label_stack; ST_DATA Sym *global_label_stack; ST_DATA Sym *define_stack; -ST_DATA CType char_pointer_type, func_old_type, int_type; +ST_DATA CType char_pointer_type, func_old_type, int_type, size_type; ST_DATA SValue vstack[VSTACK_SIZE], *vtop; ST_DATA int rsym, anon_sym, ind, loc; diff --git a/tccgen.c b/tccgen.c index 6031611..36a1879 100644 --- a/tccgen.c +++ b/tccgen.c @@ -64,7 +64,7 @@ ST_DATA int func_vc; ST_DATA int last_line_num, last_ind, func_ind; /* debug last line number and pc */ ST_DATA char *funcname; -ST_DATA CType char_pointer_type, func_old_type, int_type; +ST_DATA CType char_pointer_type, func_old_type, int_type, size_type; /* ------------------------------------------------------------------------- */ static void gen_cast(CType *type); @@ -325,6 +325,17 @@ ST_FUNC void vpushi(int v) vsetc(&int_type, VT_CONST, &cval); } +/* push a pointer sized constant */ +static void vpushs(long long v) +{ + CValue cval; + if (PTR_SIZE == 4) + cval.i = (int)v; + else + cval.ull = v; + vsetc(&size_type, VT_CONST, &cval); +} + /* push long long constant */ static void vpushll(long long v) { @@ -3575,12 +3586,12 @@ ST_FUNC void unary(void) if (!(type.t & VT_VLA)) { if (size < 0) tcc_error("sizeof applied to an incomplete type"); - vpushi(size); + vpushs(size); } else { vla_runtime_type_size(&type, &align); } } else { - vpushi(align); + vpushs(align); } vtop->type.t |= VT_UNSIGNED; break; diff --git a/tests/tcctest.c b/tests/tcctest.c index eeabb7c..9598fa4 100644 --- a/tests/tcctest.c +++ b/tests/tcctest.c @@ -2155,6 +2155,8 @@ void c99_vla_test(int size1, int size2) #endif } +typedef __SIZE_TYPE__ uintptr_t; + void sizeof_test(void) { int a; @@ -2175,6 +2177,20 @@ void sizeof_test(void) ptr = NULL; printf("sizeof(**ptr) = %d\n", sizeof (**ptr)); + /* The type of sizeof should be as large as a pointer, actually + it should be size_t. */ + printf("sizeof(sizeof(int) = %d\n", sizeof(sizeof(int))); + uintptr_t t = 1; + uintptr_t t2; + /* Effectively <<32, but defined also on 32bit machines. */ + t <<= 16; + t <<= 16; + t++; + /* This checks that sizeof really can be used to manipulate + uintptr_t objects, without truncation. */ + t2 = t & -sizeof(uintptr_t); + printf ("%lu %lu\n", t, t2); + /* some alignof tests */ printf("__alignof__(int) = %d\n", __alignof__(int)); printf("__alignof__(unsigned int) = %d\n", __alignof__(unsigned int)); -- 1.7.3.4