http://gcc.gnu.org/bugzilla/show_bug.cgi?id=46824
--- Comment #6 from Dodji Seketeli <dodji at gcc dot gnu.org> 2011-03-10 21:20:52 UTC --- Thank you for reducing this. Here is what I understand from the reduced test case. For the expression "*p" the compiler uses overload resolution to determine which operator "*" to use. As there is no user provided operator*() that can take an instance of Ptr in argument, the only choice left is to consider the built-in operator*() as a viable candidate for overload resolution. But then the note in [over.built]/1 says: because built-in operators take only operands with non-class type, and operator overload resolution occurs only when an operand expression originally has class or enumeration type, operator overload resolution can resolve to a built-in operator only when an operand has a class type that has a user-defined conversion to a non-class type appropriate for the operator, or when an operand has an enumeration type that can be converted to a type appropriate for the operator. As there is no user-defined conversion operator that would convert Ptr into a pointer to native type, the built-in operator*() is not a viable candidate. Thus I believe the test case is ill-formed and the user-defined conversion operator that converts Ptr to Incomplete* seems to be of little use in this case. So for the built-in operator to be selected, we'd need e.g, a user-defined conversion operator Ptr::operator int* (). Otherwise we'd need a user-defined operator 'something Ptr::operator*()'.