https://gcc.gnu.org/bugzilla/show_bug.cgi?id=118509
--- Comment #13 from GCC Commits <cvs-commit at gcc dot gnu.org> --- The master branch has been updated by Jakub Jelinek <ja...@gcc.gnu.org>: https://gcc.gnu.org/g:d9d0eeea93d39d304c7420e87f4b903d89f2e9fa commit r15-7057-gd9d0eeea93d39d304c7420e87f4b903d89f2e9fa Author: Jakub Jelinek <ja...@redhat.com> Date: Mon Jan 20 10:26:49 2025 +0100 tree, c++: Consider TARGET_EXPR invariant like SAVE_EXPR [PR118509] My October PR117259 fix to get_member_function_from_ptrfunc to use a TARGET_EXPR rather than SAVE_EXPR unfortunately caused some regressions as well as the following testcase shows. What happens is that get_member_function_from_ptrfunc -> build_base_path calls save_expr, so since the PR117259 change in mnay cases it will call save_expr on a TARGET_EXPR. And, for some strange reason a TARGET_EXPR is not considered an invariant, so we get a SAVE_EXPR wrapped around the TARGET_EXPR. That SAVE_EXPR <TARGET_EXPR <...>> gets initially added only to the second operand of ?:, so at that point it would still work fine during expansion. But unfortunately an expression with that subexpression is handed to the caller also through *instance_ptrptr = instance_ptr; and gets evaluated once again when computing the first argument to the method. So, essentially, we end up with (TARGET_EXPR <D.2907, ...>, (... ? ... SAVE_EXPR <TARGET_EXPR <D.2907, ...> ... : ...)) (... SAVE_EXPR <TARGET_EXPR <D.2907, ...> ..., ...); and while D.2907 is initialized during gimplification in the code dominating everything that uses it, the extra temporary created for the SAVE_EXPR is initialized only conditionally (if the ?: condition is true) but then used unconditionally, so we get pmf-4.C: In function âvoid foo(C, B*)â: pmf-4.C:12:11: warning: â<anonymous>â may be used uninitialized [-Wmaybe-uninitialized] 12 | (y->*x) (); | ~~~~~~~~^~ pmf-4.C:12:11: note: â<anonymous>â was declared here 12 | (y->*x) (); | ~~~~~~~~^~ diagnostic and wrong-code issue too. The following patch fixes it by considering a TARGET_EXPR invariant for SAVE_EXPR purposes the same as SAVE_EXPR is. Really creating another temporary for it is just a waste of the IL. Unfortunately I had to tweak the omp matching code to be able to accept TARGET_EXPR the same as SAVE_EXPR. 2025-01-20 Jakub Jelinek <ja...@redhat.com> PR c++/118509 gcc/ * tree.cc (tree_invariant_p_1): Return true for TARGET_EXPR too. gcc/c-family/ * c-omp.cc (c_finish_omp_for): Handle TARGET_EXPR in first operand of COMPOUND_EXPR incr the same as SAVE_EXPR. gcc/testsuite/ * g++.dg/expr/pmf-4.C: New test.