[gcc r17-2722] c++: vrp and pmf conversion [PR126310]

Jason Merrill via Gcc-cvs <[email protected]>
Newsgroups gmane.comp.gcc.cvs
Message-ID <[email protected]>
https://gcc.gnu.org/g:0e429acc24a2305c77da1229c456788e50edcae9

commit r17-2722-g0e429acc24a2305c77da1229c456788e50edcae9
Author: Jason Merrill <[email protected]>
Date:   Sun Jul 26 12:44:22 2026 -0400

    c++: vrp and pmf conversion [PR126310]
    
    Here when trying to convert to EncodeFnTy, aka void (sub::*)(int&&), we were
    instead converting to void (sub::*)(ValuePart&&), and the optimization added
    by r16-5887 got confused by the values in the array initializer having
    different RECORD_TYPEs (with different FIELD_DECLs) from the type of the
    array.
    
    So let's correct the conversion to actually end with the requested type.
    
            PR c++/126310
    
    gcc/cp/ChangeLog:
    
            * call.cc (standard_conversion): Don't build a mixed METHOD_TYPE if
            it isn't needed.
    
    gcc/testsuite/ChangeLog:
    
            * g++.dg/opt/pmf2.C: New test.

Diff:
---
 gcc/cp/call.cc                  | 16 ++++++++++------
 gcc/testsuite/g++.dg/opt/pmf2.C | 37 +++++++++++++++++++++++++++++++++++++
 2 files changed, 47 insertions(+), 6 deletions(-)

diff --git a/gcc/cp/call.cc b/gcc/cp/call.cc
index 143e85760b3b..62ad77a2db6f 100644
--- a/gcc/cp/call.cc
+++ b/gcc/cp/call.cc
@@ -1546,12 +1546,16 @@ standard_conversion (tree to, tree from, tree expr, bool c_cast_p,
 
       if (!same_type_p (fbase, tbase))
 	{
-	  from = build_memfn_type (fstat,
-				   tbase,
-				   cp_type_quals (tbase),
-				   type_memfn_rqual (tofn));
-	  from = build_ptrmemfunc_type (build_pointer_type (from));
-	  conv = build_conv (ck_pmem, from, conv);
+	  tree first = to;
+	  if (!same_type_p (tstat, fstat))
+	    {
+	      first = build_memfn_type (fstat,
+					tbase,
+					cp_type_quals (tbase),
+					type_memfn_rqual (tofn));
+	      first = build_ptrmemfunc_type (build_pointer_type (first));
+	    }
+	  conv = build_conv (ck_pmem, first, conv);
 	  conv->base_p = true;
 	}
       if (fnptr_conv_p (tstat, fstat))
diff --git a/gcc/testsuite/g++.dg/opt/pmf2.C b/gcc/testsuite/g++.dg/opt/pmf2.C
new file mode 100644
index 000000000000..88c38a8ea2a4
--- /dev/null
+++ b/gcc/testsuite/g++.dg/opt/pmf2.C
@@ -0,0 +1,37 @@
+// PR c++/126310
+// { dg-do run { target c++11 } }
+// { dg-additional-options -O }
+
+typedef int ValuePart;
+struct base0  {
+  int t;
+};
+struct base1 {
+  void gg(ValuePart&&) {symbols = 1; }
+  int symbols;
+};
+struct sub : base0, base1 {};
+
+using EncodeFnTy = void (sub::*)(int&&);
+static const EncodeFnTy encode_fns[]
+{
+    &sub::gg,
+    &sub::gg
+};
+
+[[gnu::noinline,gnu::noclone]]
+void f(sub &m, bool i)
+{
+ (&m->*encode_fns[i])(0);
+}
+int main()
+{
+    sub a;
+    a.t = 0;
+    a.symbols = 0;
+    f(a, 0);
+    if (a.t != 0)
+      __builtin_abort ();
+    if (a.symbols != 1)
+      __builtin_abort ();
+}
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.