Thank you for the patch!

On 12/22/25 3:19 AM, Alex Yesmanchyk wrote:
Consider the following pr38612.cc file:

Your patch should add this to the testsuite.

--

struct Base {};
struct X;                       // X derived from Base later but incomplete here
struct Y {};                    // Y not derived from Base

int test1(int Base::* p2m, X* object)
{
     return object->*p2m;        // fails because X is incomplete
}

struct X : Base
{
};

int test2(int Base::* p2m, X* object)
{
     return object->*p2m;        // OK
}       

int test3(int Base::* p2m, Y* object)
{
     return object->*p2m;        // fails because Y is not derived from Base
}

--

Now for test1 and test3 it produces the following errors:

pr38612.cc: In function 'int test1(int Base::*, X*)':
pr38612.cc:8:21: error: pointer to member type 'int' incompatible \
with incomplete object type 'X'

This is an existing issue, but printing 'int' here is wrong, it should be 'int Base::*'. That seems to be a matter of passing ptrmem_type to the error call instead of type.

     8 |     return object->*p2m;        // fails because X is incomplete
       |                     ^~~
pr38612.cc: In function 'int test3(int Base::*, Y*)':
pr38612.cc:22:21: error: pointer to member type 'int' incompatible \
with object type 'Y' because 'Y' is not derived from 'Base'

Likewise.

You also need ChangeLog entries for your patch.

I've adjusted your patch as follows; any objection?

From d4a8a5fdd52ec46f9f694f60b12f18c7cdbaf27d Mon Sep 17 00:00:00 2001
From: Alex Yesmanchyk <[email protected]>
Date: Mon, 26 Jan 2026 18:16:53 +0800
Subject: [PATCH] c++: Error diagnostics for pointer-to-member type [PR38612]
To: [email protected]

Consider the following ptrtomem4.C file.

Now for test1 and test3 it produces the following errors:

ptrtomem4.C: In function 'int test1(int Base::*, X*)':
ptrtomem4.C:8:21: error: pointer to member type 'int' incompatible with incomplete object type 'X'
ptrtomem4.C: In function 'int test3(int Base::*, Y*)':
ptrtomem4.C:22:21: error: pointer to member type 'int' incompatible with object type 'Y' because 'Y' is not derived from 'Base'

	PR c++/38612

gcc/cp/ChangeLog:

	* typeck2.cc (build_m_component_ref): Improve class mismatch
	diagnostic.

gcc/testsuite/ChangeLog:

	* g++.dg/diagnostic/ptrtomem4.C: New test.

Signed-off-by: Alex Yesmanchyk <[email protected]>
Co-authored-by: Jason Merrill <[email protected]>
---
 gcc/cp/typeck2.cc                           | 12 +++++++++--
 gcc/testsuite/g++.dg/diagnostic/ptrtomem4.C | 24 +++++++++++++++++++++
 2 files changed, 34 insertions(+), 2 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/diagnostic/ptrtomem4.C

diff --git a/gcc/cp/typeck2.cc b/gcc/cp/typeck2.cc
index 1e5e3b24a23..f18c5a7499e 100644
--- a/gcc/cp/typeck2.cc
+++ b/gcc/cp/typeck2.cc
@@ -2459,8 +2459,16 @@ build_m_component_ref (tree datum, tree component, tsubst_flags_t complain)
 	{
 	mismatch:
 	  if (complain & tf_error)
-	    error ("pointer to member type %qT incompatible with object "
-		   "type %qT", type, objtype);
+	    {
+	      if (COMPLETE_TYPE_P (objtype))
+		error ("pointer to member type %qT incompatible "
+		       "with object type %qT because %qT is not "
+		       "derived from %qT", ptrmem_type, objtype,
+		       objtype, ctype);
+	      else
+		error ("pointer to member type %qT incompatible with "
+		       "incomplete object type %qT", ptrmem_type, objtype);
+	    }
 	  return error_mark_node;
 	}
       else if (binfo == error_mark_node)
diff --git a/gcc/testsuite/g++.dg/diagnostic/ptrtomem4.C b/gcc/testsuite/g++.dg/diagnostic/ptrtomem4.C
new file mode 100644
index 00000000000..564c28b4300
--- /dev/null
+++ b/gcc/testsuite/g++.dg/diagnostic/ptrtomem4.C
@@ -0,0 +1,24 @@
+// PR c++/38612
+
+struct Base {};
+struct X;    // X derived from Base later but incomplete here
+struct Y {}; // Y not derived from Base
+
+int test1(int Base::* p2m, X* object)
+{
+    return object->*p2m; // { dg-error "int Base::.' incompatible with incomplete object type 'X'" }
+}
+
+struct X : Base
+{
+};
+
+int test2(int Base::* p2m, X* object)
+{
+    return object->*p2m;        // OK
+}
+
+int test3(int Base::* p2m, Y* object)
+{
+    return object->*p2m;        // { dg-error "int Base::.' incompatible with object type 'Y' because 'Y' is not derived from 'Base'" }
+}
-- 
2.52.0

Reply via email to