GCC screws up pointer->ulong conversion on 32 bit systems

Johannes Pfau nospam at example.com
Sat Nov 9 04:19:19 PST 2013


----------------------------------------------
#include <stdio.h>
#include <stdint.h>

void test(void* p)
{
    uint64_t pl = (uint64_t)p;
    uint64_t p2 = (uint64_t)(int)p;
    int tmp = (int)p;
    uint64_t p3 = (uint64_t)tmp;
    
    printf("%llx %llx %llx\n", pl, p2, p3);
}

void main()
{
    void* p = (void*)0xFFEECCAA;
    test(p);
}
-----------------------------------------------
Output is:
ffffffffffeeccaa ffffffffffeeccaa ffffffffffeeccaa

Expected:
ffeeccaa ffffffffffeeccaa ffffffffffeeccaa

Unfortunately this affects us as well (the bug is in
convert_to_integer). What do you think, is this a valid GCC bug which
should be filed?


I verified the C testcase on ARM and x86. I don't have a x86 gdc right
now, could you test whether the D testcase
http://dpaste.dzfl.pl/abb9a6971
also fails on x86?


The fix is simple:
in gcc/convert.c(convert_to_integer):

/* Convert to an unsigned integer of the correct width first, and
from there widen/truncate to the required type.  Some targets support
the coexistence of multiple valid pointer sizes, so fetch the one we
need from the type.  */
      expr = fold_build1 (CONVERT_EXPR,
			  lang_hooks.types.type_for_size
			    (TYPE_PRECISION (intype), 0),
			  expr);

should be

/* Convert to an unsigned integer of the correct width first, and
from there widen/truncate to the required type.  Some targets support
the coexistence of multiple valid pointer sizes, so fetch the one we
need from the type.  */
      expr = fold_build1 (CONVERT_EXPR,
			  lang_hooks.types.type_for_size
			    (TYPE_PRECISION (intype), 1),
			  expr);


More information about the D.gnu mailing list