Created attachment 37399 [details] reproducer I don't see where [except.handle] allows such a conversion.
We're missing a check for cv-qualifiers in __pointer_to_member_type_info::__pointer_catch that needs to be done before we compare the pointees. Both pointees have type void() so we need to compare the cv-quals before that info is lost.
Hmm, we don't seem to have the cv-quals in __flags. That's a problem.
When compiled with clang the pointees are different, so the match fails when comparing them. Using Clang: (gdb) step __cxxabiv1::__pbase_type_info::__pointer_catch (this=0x401cc0 <typeinfo for void (A::*)() const>, thrown_type=0x401d10 <typeinfo for void (A::*)()>, thr_obj=0x7fffffffd220, outer=0) at /usr/lib/gcc/x86_64-redhat-linux/6.3.1/../../../../include/c++/6.3.1/cxxabi.h:309 (gdb) step std::type_info::__do_catch (this=0x401c90 <typeinfo for void () const>, thr_type=0x401cf8 <typeinfo for void ()>) at ../../../../libstdc++-v3/libsupc++/tinfo.cc:71 (gdb) p *this $3 = {_vptr.type_info = 0x6030b0 <vtable for __cxxabiv1::__function_type_info@@CXXABI_1.3+16>, __name = 0x401c89 <typeinfo name for void () const> "KFvvE"} (gdb) p *thr_type $4 = {_vptr.type_info = 0x6030b0 <vtable for __cxxabiv1::__function_type_info@@CXXABI_1.3+16>, __name = 0x401cf0 <typeinfo name for void ()> "FvvE"} (gdb) But using GCC the two pointee types are the same: (gdb) p *this $1 = {_vptr.type_info = 0x6030e8 <vtable for __cxxabiv1::__function_type_info@@CXXABI_1.3+16>, __name = 0x401c50 <typeinfo name for void ()> "FvvE"} (gdb) p *thr_type $2 = {_vptr.type_info = 0x6030e8 <vtable for __cxxabiv1::__function_type_info@@CXXABI_1.3+16>, __name = 0x401c50 <typeinfo name for void ()> "FvvE"} So it looks like the problem is in the front-end where the typeinfo object for a pointer to cv-qualified member function has the wrong pointee type.
My front-end debugging skills are pitiful, but I've found something suspicious. ptm_initializer uses TYPE_PTRMEM_POINTED_TO_TYPE to get that pointee type. For this case that expands to TYPE_PTRMEMFUNC_FN_TYPE which is a call to cp_build_qualified_type with the qualifiers from cp_type_quals. But cp_type_quals tries pretty hard to ensure we never get cv-quals for a function type. For the purposes of RTTI, where we really do care about the difference between void() and void()const, do we want the memfn quals instead?
For the attached reproducer this condition is never true in cp_build_qualified_type_real /* But preserve any function-cv-quals on a FUNCTION_TYPE. */ if (TREE_CODE (type) == FUNCTION_TYPE) type_quals |= type_memfn_quals (type); As far as I can tell this is what's supposed to put the cv-quals back onto the function type, so we'd have a pointee of type void() const not void().
Dup of bug 52099. *** This bug has been marked as a duplicate of bug 52099 ***