I tracked it down to this:
/* Allow conversions between integral types and pointers only if there is no sign or zero extension involved. */ if (((POINTER_TYPE_P (type) && INTEGRAL_TYPE_P (TREE_TYPE (op))) || (POINTER_TYPE_P (TREE_TYPE (op)) && INTEGRAL_TYPE_P (type))) && TYPE_PRECISION (type) == TYPE_PRECISION (TREE_TYPE (op))) return false; The code does not do what the comment says. It also requires that there be no truncation. However, of course, other parts of the compiler complain about truncation as well. The root cause is this: ptr = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (ptr), ptr, fold_convert (sizetype, vtable)); We fold_convert to sizetype, without regard for whether it's the same precision as TREE_TYPE (ptr). vtable is the right size, ptr is the right size, but we're creating an intermediate that's the wrong size. Can we put in a calculate-unsigned-for-type call here? That should be sizetype for everyone else, but the special type for m32c.