https://gcc.gnu.org/bugzilla/show_bug.cgi?id=120095
Richard Biener <rguenth at gcc dot gnu.org> changed: What |Removed |Added ---------------------------------------------------------------------------- CC| |rguenth at gcc dot gnu.org --- Comment #5 from Richard Biener <rguenth at gcc dot gnu.org> --- /* If this is not a builtin function, the function type through which the call is made may be different from the type of the function. */ if (!builtin_p) CALL_EXPR_FN (exp) = fold_convert (build_pointer_type (gimple_call_fntype (stmt)), CALL_EXPR_FN (exp)); is probably one issue. Maybe we should do builtin_p = gimple_call_builtin_p (stmt); instead of builtin_p = decl && fndecl_built_in_p (decl); where we fail to verify the function signature against that of the builtin. Note that even with unconditionally converting we ICE, so expand_assignment goes wrong at some point, not expecting the integer return type. It does so in expand_expr_real_1: tree fndecl = get_callee_fndecl (exp), attr; .. /* Check for a built-in function. */ if (fndecl && fndecl_built_in_p (fndecl)) { gcc_assert (DECL_BUILT_IN_CLASS (fndecl) != BUILT_IN_FRONTEND); return expand_builtin (exp, target, subtarget, tmode, ignore); where we then eventually get into the "verification" builtin expansion does. It only checks we have a REAL_TYPE as argument (not whether it is of the correct mode). And it doesn't check the return type. In get_callee_fndecl STRIP_NOPS strips the conversion of the function type as useless because the pointer types have the same mode.