[PATCH] c++/modules: PTRMEM_CST member considered unused [PR124981]

Patrick Palka ppalka@redhat.com
Wed Apr 22 20:19:16 GMT 2026


Tested on x86_64-pc-linux-gnu, does this look OK for 17/16.2?

-- >8 --

Here from the importer side the specialization A<B, &B::g> has already
been instantiated in module M, so we stream it in rather than
instantiate it.  We then proceed to instantiate A<B, &B::g>::f() whose
definition invokes the pointer-to-member &B::g, clearly a use, but it
turns out that nothing has marked B::g as used in _b.C and we complain
at link time about an undefined reference.

Without modules we would have marked B::g as used during instantiation
of A<B, &B::g> via mark_template_arguments_used.  But this instantiaton
happens in module M, not the importer.

This patch fixes this by force setting TREE_USED on PTRMEM_CST_MEMBER
during stream-in, via the RTU macro, which seems sufficient to ensure
B::g gets emitted.  I don't fully understand the reason for this RTU macro
but it's already used for streaming in operands of tcc_expression nodes
and BASELINK_FUNCTIONS so using it for PTRMEM_CST_MEMBER doesn't seem too
out of place.

	PR c++/124981

gcc/cp/ChangeLog:

	* module.cc (trees_in::core_vals) <case PTRMEM_CST>: Use RTU
	instead of RT to stream PTRMEM_CST_MEMBER.

gcc/testsuite/ChangeLog:

	* g++.dg/modules/ptrmem-1_a.C: New test.
	* g++.dg/modules/ptrmem-1_b.C: New test.
---
 gcc/cp/module.cc                          |  2 +-
 gcc/testsuite/g++.dg/modules/ptrmem-1_a.C | 21 +++++++++++++++++++++
 gcc/testsuite/g++.dg/modules/ptrmem-1_b.C | 10 ++++++++++
 3 files changed, 32 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/g++.dg/modules/ptrmem-1_a.C
 create mode 100644 gcc/testsuite/g++.dg/modules/ptrmem-1_b.C

diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc
index e5547f7d029f..61e9e70936bd 100644
--- a/gcc/cp/module.cc
+++ b/gcc/cp/module.cc
@@ -7443,7 +7443,7 @@ trees_in::core_vals (tree t)
       break;
 
     case PTRMEM_CST:
-      RT (((lang_tree_node *)t)->ptrmem.member);
+      RTU (((lang_tree_node *)t)->ptrmem.member);
       break;
 
     case STATIC_ASSERT:
diff --git a/gcc/testsuite/g++.dg/modules/ptrmem-1_a.C b/gcc/testsuite/g++.dg/modules/ptrmem-1_a.C
new file mode 100644
index 000000000000..ca16c39bea3b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/ptrmem-1_a.C
@@ -0,0 +1,21 @@
+// PR c++/124981
+// { dg-additional-options "-fmodules" }
+// { dg-module-cmi M }
+
+export module M;
+
+template<class T, void (T::*F)() const>
+struct A {
+  void f(const T& t) {
+    (t.*F)();
+  }
+};
+
+export
+template<class T>
+struct B {
+  void g() const { }
+  A<B, &B::g> m;
+};
+
+B<void> b;
diff --git a/gcc/testsuite/g++.dg/modules/ptrmem-1_b.C b/gcc/testsuite/g++.dg/modules/ptrmem-1_b.C
new file mode 100644
index 000000000000..5c65bfc1fb10
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/ptrmem-1_b.C
@@ -0,0 +1,10 @@
+// PR c++/124981
+// { dg-additional-options "-fmodules" }
+// { dg-module-do link }
+
+import M;
+
+int main() {
+  B<void> b;
+  b.m.f(b);
+}
-- 
2.54.0.rc1.54.g60f07c4f5c



More information about the Libstdc++ mailing list