]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
c++/modules: memfn merging wrt to obj-ness [PR125035]
authorPatrick Palka <ppalka@redhat.com>
Wed, 29 Apr 2026 12:48:50 +0000 (08:48 -0400)
committerPatrick Palka <ppalka@redhat.com>
Wed, 29 Apr 2026 12:48:50 +0000 (08:48 -0400)
Here we ICE during declaration merging for the streamed-in static A::f
because we incorrectly match with the in-TU iobj A::f instead of the
in-TU static A::f.

The problem is the merge key doesn't have enough information to discern
between two overloads that essentially only differ by whether they have
an object parameter (and whether it's implicit or explicit).  To that end
this patch adds iobj_p and xobj_p bits to merge_key.

PR c++/125035

gcc/cp/ChangeLog:

* module.cc (merge_key): Add iobj_p and xobj_p bits.
(trees_out::key_mergeable) <case MK_named>: Set and stream
merge_key's iobj_p and xobj_p bits.
(check_mergeable_decl) <case FUNCTION_DECL>: Compare merge_key's
iobj_p and xobj_p bits with that of the given function.
(trees_in::key_mergeable): Stream merge_key's iobj_p and xobj_p
bits.

gcc/testsuite/ChangeLog:

* g++.dg/modules/merge-22.h: New test.
* g++.dg/modules/merge-22_a.H: New test.
* g++.dg/modules/merge-22_b.C: New test.

Reviewed-by: Jason Merrill <jason@redhat.com>
gcc/cp/module.cc
gcc/testsuite/g++.dg/modules/merge-22.h [new file with mode: 0644]
gcc/testsuite/g++.dg/modules/merge-22_a.H [new file with mode: 0644]
gcc/testsuite/g++.dg/modules/merge-22_b.C [new file with mode: 0644]

index f2649f76bd79526dbe89a43bc6ce15a62074469e..49330312520ecf8905894dad5d7b6c780337ef48 100644 (file)
@@ -2970,6 +2970,8 @@ static char const *const merge_kind_name[MK_hwm] =
 struct merge_key {
   cp_ref_qualifier ref_q : 2;
   unsigned coro_disc : 2;  /* Discriminator for coroutine transforms.  */
+  unsigned iobj_p : 1;
+  unsigned xobj_p : 1;
   unsigned index;
 
   tree ret;  /* Return type, if appropriate.  */
@@ -2978,7 +2980,7 @@ struct merge_key {
   tree constraints;  /* Constraints.  */
 
   merge_key ()
-    :ref_q (REF_QUAL_NONE), coro_disc (0), index (0),
+    :ref_q (REF_QUAL_NONE), coro_disc (0), iobj_p (0), xobj_p (0), index (0),
      ret (NULL_TREE), args (NULL_TREE),
      constraints (NULL_TREE)
   {
@@ -11898,6 +11900,8 @@ trees_out::key_mergeable (int tag, merge_kind mk, tree decl, tree inner,
 
              key.ref_q = type_memfn_rqual (fn_type);
              key.coro_disc = get_coroutine_discriminator (inner);
+             key.iobj_p = DECL_IOBJ_MEMBER_FUNCTION_P (inner);
+             key.xobj_p = DECL_XOBJ_MEMBER_FUNCTION_P (inner);
              key.args = TYPE_ARG_TYPES (fn_type);
 
              if (tree reqs = get_constraints (inner))
@@ -12035,11 +12039,13 @@ trees_out::key_mergeable (int tag, merge_kind mk, tree decl, tree inner,
       if (streaming_p ())
        {
          /* Check we have enough bits for the index.  */
-         gcc_checking_assert (key.index < (1u << (sizeof (unsigned) * 8 - 4)));
+         gcc_checking_assert (key.index < (1u << (sizeof (unsigned) * 8 - 6)));
 
          unsigned code = ((key.ref_q << 0)
                           | (key.coro_disc << 2)
-                          | (key.index << 4));
+                          | (key.iobj_p << 4)
+                          | (key.xobj_p << 5)
+                          | (key.index << 6));
          u (code);
        }
 
@@ -12118,6 +12124,8 @@ check_mergeable_decl (merge_kind mk, tree decl, tree ovl, merge_key const &key)
            if ((!key.ret
                 || same_type_p (key.ret, fndecl_declared_return_type (m_inner)))
                && type_memfn_rqual (m_type) == key.ref_q
+               && key.iobj_p == DECL_IOBJ_MEMBER_FUNCTION_P (m_inner)
+               && key.xobj_p == DECL_XOBJ_MEMBER_FUNCTION_P (m_inner)
                && compparms (key.args, TYPE_ARG_TYPES (m_type))
                && get_coroutine_discriminator (m_inner) == key.coro_disc
                /* Reject if old is a "C" builtin and new is not "C".
@@ -12257,7 +12265,9 @@ trees_in::key_mergeable (int tag, merge_kind mk, tree decl, tree inner,
       unsigned code = u ();
       key.ref_q = cp_ref_qualifier ((code >> 0) & 3);
       key.coro_disc = (code >> 2) & 3;
-      key.index = code >> 4;
+      key.iobj_p = (code >> 4) & 1;
+      key.xobj_p = (code >> 5) & 1;
+      key.index = code >> 6;
 
       if (mk == MK_enum)
        key.ret = tree_node ();
diff --git a/gcc/testsuite/g++.dg/modules/merge-22.h b/gcc/testsuite/g++.dg/modules/merge-22.h
new file mode 100644 (file)
index 0000000..d23afe3
--- /dev/null
@@ -0,0 +1,39 @@
+struct A {
+  void f(int) const;
+  static void f(const A*, int);
+
+#if __cpp_explicit_this_parameter
+  void g(this A*, int);
+  static void g(A*, int);
+
+  void h(int);
+  void h(this A*, int);
+#endif
+};
+
+template<class T>
+struct B {
+  void f(int) const;
+  static void f(const B*, int);
+
+#if __cpp_explicit_this_parameter
+  void g(this B*, int);
+  static void g(B*, int);
+
+  void h(int);
+  void h(this B*, int);
+#endif
+};
+
+struct C {
+  template<class T> void f(int) const;
+  template<class T> static void f(const C*, int);
+
+#if __cpp_explicit_this_parameter
+  template<class T> void g(this C*, int);
+  template<class T> static void g(C*, int);
+
+  template<class T> void h(int);
+  template<class T> void h(this C*, int);
+#endif
+};
diff --git a/gcc/testsuite/g++.dg/modules/merge-22_a.H b/gcc/testsuite/g++.dg/modules/merge-22_a.H
new file mode 100644 (file)
index 0000000..11e2100
--- /dev/null
@@ -0,0 +1,4 @@
+// PR c++/125035
+// { dg-additional-options "-fmodule-header" }
+
+#include "merge-22.h"
diff --git a/gcc/testsuite/g++.dg/modules/merge-22_b.C b/gcc/testsuite/g++.dg/modules/merge-22_b.C
new file mode 100644 (file)
index 0000000..839cf62
--- /dev/null
@@ -0,0 +1,5 @@
+// PR c++/125035
+// { dg-additional-options "-fmodules -fno-module-lazy" }
+
+#include "merge-22.h"
+import "merge-22_a.H";