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

Reply via email to