Hi! The following testcases segfault because the new range for -frange-for-ext-temps temporary extension extends even the internal TARGET_EXPRs created by get_member_function_from_ptrfunc.
The following patch fixes that by marking those TARGET_EXPR_INTERNAL_P. I'm not calling get_internal_target_expr because I really want to force the TARGET_EXPR creation rather than say mark some existing TARGET_EXPR internal, and get_internal_target_expr doesn't take complain argument either and always uses tf_warning_or_error. Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk? 2025-02-24 Jakub Jelinek <ja...@redhat.com> PR c++/118923 * typeck.cc (get_member_function_from_ptrfunc): Set TARGET_EXPR_INTERNAL_P flag on force_target_expr returned TARGET_EXPRs. * g++.dg/cpp0x/pr118923.C: New test. * g++.dg/cpp1y/pr118923.C: New test. --- gcc/cp/typeck.cc.jj 2025-02-13 19:59:55.463576294 +0100 +++ gcc/cp/typeck.cc 2025-02-20 21:13:51.420841171 +0100 @@ -4218,17 +4218,23 @@ get_member_function_from_ptrfunc (tree * || (!nonvirtual && !DECL_P (instance_ptr) && !TREE_CONSTANT (instance_ptr))) - instance_ptr = instance_save_expr - = force_target_expr (TREE_TYPE (instance_ptr), instance_ptr, - complain); + { + instance_ptr = instance_save_expr + = force_target_expr (TREE_TYPE (instance_ptr), instance_ptr, + complain); + TARGET_EXPR_INTERNAL_P (instance_ptr) = true; + } /* See above comment. */ if (TREE_SIDE_EFFECTS (function) || (!nonvirtual && !DECL_P (function) && !TREE_CONSTANT (function))) - function - = force_target_expr (TREE_TYPE (function), function, complain); + { + function + = force_target_expr (TREE_TYPE (function), function, complain); + TARGET_EXPR_INTERNAL_P (function) = true; + } /* Start by extracting all the information from the PMF itself. */ e3 = pfn_from_ptrmemfunc (function); --- gcc/testsuite/g++.dg/cpp0x/pr118923.C.jj 2025-02-24 11:37:54.638601995 +0100 +++ gcc/testsuite/g++.dg/cpp0x/pr118923.C 2025-02-24 11:39:33.940212633 +0100 @@ -0,0 +1,66 @@ +// PR c++/118923 +// { dg-do run { target c++11 } } +// { dg-additional-options "-frange-for-ext-temps" { target c++23 } } +// { dg-additional-options "-fno-range-for-ext-temps" { target c++20_down } } + +int g; + +struct A { + int a[3]; + A (int x, int y, int z) : a{x, y, z} { if ((g++ & 7) != 4) __builtin_abort (); } + A (const A &x) = delete; + ~A () { if ((g++ & 7) != 7 - 2 * (__cpp_range_based_for >= 202211)) __builtin_abort (); } + int *begin () { return a; } + int *end () { return a + 3; } +}; + +struct B { + B () { if ((g++ & 7) != 3) __builtin_abort (); } + B (const B &) = delete; + ~B () { if ((g++ & 7) != 5 + (__cpp_range_based_for >= 202211)) __builtin_abort (); } +}; + +struct C { + A foo (const B &) { return { 1, 2, 3 }; } + A bar (const B &) { return { 4, 5, 6 }; } + bool baz () { return b; } + bool b = false; + static C c; +}; + +C C::c; + +struct D { + D () { if ((g++ & 5) != 0) __builtin_abort (); } + D (const D &) = delete; + ~D () { if ((g & 7) != 1 && (g & 7) != 6 + (__cpp_range_based_for >= 202211)) __builtin_abort (); g++; } +}; + +inline C * +qux (const D &) +{ + return &C::c; +} + +void +foo () +{ + int z = 1; + auto d = qux (D {})->baz () ? &C::bar : &C::foo; + for (const int &r : (qux (D {})->*d) (B {})) + if (z++ != r) + __builtin_abort (); + C::c.b = true; + d = qux (D {})->baz () ? &C::bar : &C::foo; + for (const int &r : (qux (D {})->*d) (B {})) + if (z++ != r) + __builtin_abort (); +} + +int +main () +{ + foo (); + if (g != 16) + __builtin_abort (); +} --- gcc/testsuite/g++.dg/cpp1y/pr118923.C.jj 2025-02-20 21:17:37.852648770 +0100 +++ gcc/testsuite/g++.dg/cpp1y/pr118923.C 2025-02-20 21:19:46.662108221 +0100 @@ -0,0 +1,38 @@ +// PR c++/118923 +// { dg-do run { target c++14 } } + +struct A { + int a[3] = { 0, 0, 0 }; + int *begin () { return a; } + int *end () { return a + 3; } +}; + +struct B { + A foo () { return { 1, 2, 3 }; } + A bar () { return { 1, 2, 3 }; } + bool baz () { return b; } + bool b = false; + static B c; +}; + +B B::c; + +inline B * +qux () +{ + return &B::c; +} + +void +foo () +{ + auto d = qux ()->baz () ? &B::foo : &B::bar; + for (const int &r : (qux ()->*d) ()) + ; +} + +int +main () +{ + foo (); +} Jakub