Tested x86_64-pc-linux-gnu, applying to trunk.
-- 8< --
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.
---
gcc/cp/call.cc | 16 ++++++++------
gcc/testsuite/g++.dg/opt/pmf2.C | 37 +++++++++++++++++++++++++++++++++
2 files changed, 47 insertions(+), 6 deletions(-)
create mode 100644 gcc/testsuite/g++.dg/opt/pmf2.C
diff --git a/gcc/cp/call.cc b/gcc/cp/call.cc
index 143e85760b3..62ad77a2db6 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 00000000000..88c38a8ea2a
--- /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 ();
+}
base-commit: f8a8ef372712495bdf8c829488fdc660c0a28fe9
--
2.55.0