diff --git a/tccgen.c b/tccgen.c index 5265e49..a852375 100644 --- a/tccgen.c +++ b/tccgen.c @@ -2633,18 +2633,22 @@ static void gen_cast(CType *type) tcc_warning("nonportable conversion from pointer to char/short"); } force_charshort_cast(dbt); -#if PTR_SIZE == 4 } else if ((dbt & VT_BTYPE) == VT_INT) { /* scalar to int */ if ((sbt & VT_BTYPE) == VT_LLONG) { +#if PTR_SIZE == 4 /* from long long: just take low order word */ lexpand(); vpop(); - } +#else + vpushi(0xffffffff); + vtop->type.t |= VT_UNSIGNED; + gen_op('&'); +#endif + } /* if lvalue and single word type, nothing to do because the lvalue already contains the real type size (see VT_LVAL_xxx constants) */ -#endif } } } else if ((dbt & VT_BTYPE) == VT_PTR && !(vtop->r & VT_LVAL)) { diff --git a/tests/tcctest.c b/tests/tcctest.c index f807966..56d51dc 100644 --- a/tests/tcctest.c +++ b/tests/tcctest.c @@ -2491,6 +2491,11 @@ void longlong_test(void) a = 0x123; long long *p = &a; llshift(*p, 5); + + /* shortening followed by widening */ + unsigned long long u = 0x8000000000000001ULL; + u = (unsigned)(u + 1); + printf("long long u=" ULONG_LONG_FORMAT "\n", u); } void manyarg_test(void)