https://gcc.gnu.org/bugzilla/show_bug.cgi?id=117976
Bug ID: 117976 Summary: ubsan false positive invoking pointer to derived member with base class type Product: gcc Version: 15.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: sanitizer Assignee: unassigned at gcc dot gnu.org Reporter: rs2740 at gmail dot com CC: dodji at gcc dot gnu.org, dvyukov at gcc dot gnu.org, jakub at gcc dot gnu.org, kcc at gcc dot gnu.org Target Milestone: --- struct B1 { virtual ~B1() = default; int x; }; struct B2 { virtual ~B2() = default; int y; }; struct D : B1, B2 { int x; void f() {} }; int main() { D d; B2* b = &d; auto mptr = static_cast<void (B2::*)()>(&D::f); (b->*mptr)(); } This example should be valid. [expr.static.cast]/12: > A prvalue of type “pointer to member of D of type cv1 T” can be converted to a > prvalue of type “pointer to member of B of type cv2 T”, where D is a complete > class type and B is a base class of D, if cv2 is the same cv-qualification > as, > or greater cv-qualification than, cv1. [...] If class B contains the original > member, or is a base class of the class containing the original member, the > resulting pointer to member points to the original member. Otherwise, the > behavior is undefined. > [Note 6: Although class B need not contain the original member, the dynamic > type of the object with which indirection through the pointer to member is > performed must contain the original member; see [expr.mptr.oper]. — end note] The "original member" is D::f; B2 is a base class of D, so the resulting pointer to member points to the original member. The dynamic type of the object is D, which does contain the original member. However, g++ -fsanitize=undefined && ./a.out complains: test.cpp:20:15: runtime error: member call on address 0x7fffffff8d80 which does not point to an object of type 'B2' 0x7fffffff8d80: note: object is of type 'D' ff ff ff ff 68 14 40 00 00 00 00 00 0d 14 40 00 00 00 00 00 88 14 40 00 00 00 00 00 00 00 00 00 ^~~~~~~~~~~~~~~~~~~~~~~ vptr for 'D' Using clang++ reports no errors. PR92678 looks similar, though that one is calling through the derived type instead of the base type.