Hi! For middle-end pointer conversions are useless, which means the gimplifier can change the type of the value being gimplified. gimplify_call_expr is careful about this and remembers the fnptrtype early before gimplification and else /* Remember the original function type. */ CALL_EXPR_FN (*expr_p) = build1 (NOP_EXPR, fnptrtype, CALL_EXPR_FN (*expr_p)); it at the end if needed, but my cp_gimplify_expr changes didn't do that (and unfortunately got backported to 9.x already).
The following patch fixes it similarly to what gimplify_call_expr uses. I haven't changed gimplify_to_rvalue to do that, as it is quite specific to the CALL_EXPR_FN, while there is just one caller right now, if more are added, most likely they won't need such behavior or it might be even harmful, because the NOP_EXPR then is not is_gimple_val. Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk and 9.3? 2019-10-23 Jakub Jelinek <ja...@redhat.com> PR c++/92201 * cp-gimplify.c (cp_gimplify_expr): If gimplify_to_rvalue changes the function pointer type, re-add cast to the original one. * g++.dg/other/pr92201.C: New test. --- gcc/cp/cp-gimplify.c.jj 2019-10-18 00:16:09.905545389 +0200 +++ gcc/cp/cp-gimplify.c 2019-10-23 20:49:30.255410883 +0200 @@ -838,11 +838,17 @@ cp_gimplify_expr (tree *expr_p, gimple_s && CALL_EXPR_FN (*expr_p) && cp_get_callee_fndecl_nofold (*expr_p) == NULL_TREE) { + tree fnptrtype = TREE_TYPE (CALL_EXPR_FN (*expr_p)); enum gimplify_status t = gimplify_to_rvalue (&CALL_EXPR_FN (*expr_p), pre_p, NULL, is_gimple_call_addr); if (t == GS_ERROR) ret = GS_ERROR; + /* GIMPLE considers most pointer conversion useless, but for + calls we actually care about the exact function pointer type. */ + else if (TREE_TYPE (CALL_EXPR_FN (*expr_p)) != fnptrtype) + CALL_EXPR_FN (*expr_p) + = build1 (NOP_EXPR, fnptrtype, CALL_EXPR_FN (*expr_p)); } if (!CALL_EXPR_FN (*expr_p)) /* Internal function call. */; --- gcc/testsuite/g++.dg/other/pr92201.C.jj 2019-10-23 20:59:41.375139038 +0200 +++ gcc/testsuite/g++.dg/other/pr92201.C 2019-10-23 20:58:33.068175381 +0200 @@ -0,0 +1,7 @@ +// PR c++/92201 + +int +foo (void (*p) ()) +{ + return (*reinterpret_cast<int (*)()> (p)) (); +} Jakub