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) { } | ^~~~~~~~~~