Bug 38612 - Vague error diagnostics for pointer-to-member type incompatibility
Summary: Vague error diagnostics for pointer-to-member type incompatibility
Status: NEW
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 4.3.2
: P3 enhancement
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords: diagnostic, easyhack, patch
Depends on:
Blocks:
 
Reported: 2008-12-23 15:50 UTC by Michael Bruck
Modified: 2015-03-27 15:31 UTC (History)
6 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2014-05-30 00:00:00


Attachments
Broader test case for incomplete base and object types (187 bytes, text/plain)
2008-12-24 00:48 UTC, Michael Bruck
Details
proposed patch to gcc/cp/typeck2.c (400 bytes, patch)
2008-12-24 00:52 UTC, Michael Bruck
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Michael Bruck 2008-12-23 15:50:58 UTC
Consider this example:

--

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 A
}

--

produces the following errors:

In function 'int test1(int Base::*, X*)':
error: pointer to member type 'int' incompatible with object type 'X'
In function 'int test3(int Base::*, Y*)':
error: pointer to member type 'int' incompatible with object type 'Y'

The error messages could be made more useful to the user by

a) including the class type of the pointer to member type or the full p2m type (this might be a bug, depending on whether the programmer's intention was to actually print that instead of the rather uninteresting pointed-to type)

b) adding to the message for test1 something that points out that X was incomplete when evaluated.
The code in cp/typeck2.c build_m_component_ref() uses a shortcut here to print the identical message for two errors that have very different implications from the user's perspective.
Comment 1 Michael Bruck 2008-12-23 15:53:29 UTC
in the example the last comment should read
// fails because Y is not derived from Base
instead of
// fails because Y is not derived from A

Comment 2 Michael Bruck 2008-12-24 00:48:11 UTC
Created attachment 16977 [details]
Broader test case for incomplete base and object types

test1 shows the case where the base type is incomplete
test2 shows the case where the object type is incomplete
test3 shows the case where the object type is incompatible (to which the original error message is taylored)
Comment 3 Michael Bruck 2008-12-24 00:52:32 UTC
Created attachment 16978 [details]
proposed patch to gcc/cp/typeck2.c

- changes type in error message from type to ptrmem_type as was 
  probably intended originally
- adds distinct messages for the two cases where incomplete types
  were evaluated
Comment 4 Manuel López-Ibáñez 2014-05-30 14:18:42 UTC
I agree the diagnostic could be much better but I'm not fully convinced by your proposal.

Clang++ says:

pr38612.cc:7:16: error: left hand operand to ->* must be a pointer to class compatible with the right hand operand, but is 'X'
  return object->*p2m;// fails because X is incomplete
               ^
pr38612.cc:2:8: note: forward declaration of 'X'
struct X;// X derived from Base later but incomplete here
       ^
pr38612.cc:21:16: error: left hand operand to ->* must be a pointer to class compatible with the right hand operand, but is 'Y *'
  return object->*p2m;// fails because Y is not derived from A
               ^

which to me is only slightly better. 

I think I would like to get:

pr38612.cc:7:16: error: right hand operand 'Base::*' to '->*' is not compatible with left-hand operand 'X *' because 'X' is not a complete type
  return object->*p2m;// fails because X is incomplete
               ^
pr38612.cc:2:8: note: forward declaration of 'X'
struct X;// X derived from Base later but incomplete here
       ^
pr38612.cc:21:16: error: right hand operand 'Base::*' to '->*' is not compatible with left-hand operand 'Y *' because 'Y' is not derived from 'Base'
  return object->*p2m;// fails because Y is not derived from A
               ^
pr38612.cc:3:8: note: 'Y' declared here
struct Y {};// Y not derived from Base
       ^

What do you think?

Jason?
Comment 5 Jason Merrill 2014-05-30 14:44:02 UTC
(In reply to Manuel López-Ibáñez from comment #4)

Those sound good to me.
Comment 6 Michael Bruck 2014-06-03 18:57:54 UTC
(In reply to Manuel López-Ibáñez from comment #4)
> 
> What do you think?
> 
Looks great. My main beef was that the two errors were merged into one diagnostic.