https://gcc.gnu.org/bugzilla/show_bug.cgi?id=123399
--- Comment #5 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
For the bar case it is
/* 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. */
if (!dofold)
return build1 (CONVERT_EXPR, type, expr);
expr = fold_build1 (CONVERT_EXPR,
lang_hooks.types.type_for_size
(TYPE_PRECISION (intype), 0),
expr);
return fold_convert (type, expr);
in convert_to_integer_1 which adds the extra cast (surprisingly only in cp_fold
during cp_fold_function).
But that is done only for CONVERT_EXPR and not for NOP_EXPR:
else if (code == CONVERT_EXPR
&& SCALAR_TYPE_P (TREE_TYPE (x))
&& op0 != void_node)
/* During parsing we used convert_to_*_nofold; re-convert now using the
folding variants, since fold() doesn't do those transformations. */
x = fold (convert (TREE_TYPE (x), op0));
Note, the C FE even has -Wpointer-to-int-cast warning for stuff like that, C++
doesn't.