https://gcc.gnu.org/bugzilla/show_bug.cgi?id=93875

            Bug ID: 93875
           Summary: confusing type in an error about an invalid call to a
                    specialization on data member pointer
           Product: gcc
           Version: 10.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: msebor at gcc dot gnu.org
  Target Milestone: ---

The first part of the note after the first error below is confusing: what is
'int MemDataPtr::* <anonymous> = -1' supposed to refer to?  I gather
<anonymous> refers to the (unnamed) member in the typedef MemDataPtr, and the
-1 refers to the internal representation of the member pointer (all ones).  But
if that's correct, since the member in the definition of a member pointer type
is necessarily always omitted, the <anonymous> part seems not just superfluous,
it's incorrect -- there can never be anything but <anonymous> in such a
message.  Printing -1 instead of the MemDataPtr{0} in the source (or one of the
equivalents) when MemDataPtr{-1} is invalid is also incorrect and can be
misleading, especially when there is a -1 in the source code.

I happen to be working with the internal representation of member pointers and
how they're mangled and having to remember when to translate between -1 and 0
and when not makes things even more confusing than they already are.

In contrast to data member pointers, messages involving function member
pointers are clearer: 'int (A::* <anonymous>)() = ((int (A::*)())0)', although
a little too verbose, can't be mistaken for a -1.  The <anonymous> part could
be left out here as well.

It should be possible to do better by tweaking cp/error.c.

$ cat z.C && gcc -S -Wall z.C
struct A;

typedef int A::*MemDataPtr;
typedef int (A::*MemFuncPtr)();

template <MemDataPtr> void f (MemDataPtr) { }
template <MemFuncPtr> void g (MemFuncPtr) { }

void h ()
{
  f<MemDataPtr{0}>(-1);
  g<MemFuncPtr{0}>(-1);
}
z.C: In function ‘void h()’:
z.C:11:20: error: cannot convert ‘int’ to ‘MemDataPtr’ {aka ‘int A::*’}
   11 |   f<MemDataPtr{0}>(-1);
      |                    ^~
      |                    |
      |                    int
z.C:6:31: note:   initializing argument 1 of ‘void f(MemDataPtr) [with int A::*
<anonymous> = -1; MemDataPtr = int A::*]’
    6 | template <MemDataPtr> void f (MemDataPtr) { }
      |                               ^~~~~~~~~~
z.C:12:20: error: cannot convert ‘int’ to ‘MemFuncPtr’ {aka ‘int (A::*)()’}
   12 |   g<MemFuncPtr{0}>(-1);
      |                    ^~
      |                    |
      |                    int
z.C:7:31: note:   initializing argument 1 of ‘void g(MemFuncPtr) [with int
(A::* <anonymous>)() = ((int (A::*)())0); MemFuncPtr = int (A::*)()]’
    7 | template <MemFuncPtr> void g (MemFuncPtr) { }
      |                               ^~~~~~~~~~

Reply via email to