From 2bfa21eb2a6fd9af7429a347026c50aec045f590 Mon Sep 17 00:00:00 2001 From: Vas Crabb Date: Wed, 22 Sep 2021 05:58:42 +1000 Subject: util/delegate.h: Make comparison operators more technically correct. For Itanium ABI, two null member function pointers should compare equal even if the undefined bits differ. For MSVC ABI, there's all sorts of complexity around what happens when you compare pointers to member functions for different inheritance types. You'll still occasionally get weird results comparing pointers to members of different classes. --- src/lib/util/delegate.h | 35 ++++++++++++++++++++++++++++++++--- 1 file changed, 32 insertions(+), 3 deletions(-) diff --git a/src/lib/util/delegate.h b/src/lib/util/delegate.h index f79f8a110ad..223467d2fbc 100644 --- a/src/lib/util/delegate.h +++ b/src/lib/util/delegate.h @@ -402,7 +402,7 @@ public: // comparison helpers bool operator==(const delegate_mfp_itanium &rhs) const { - return (m_function == rhs.m_function) && (m_this_delta == rhs.m_this_delta); + return (isnull() && rhs.isnull()) || ((m_function == rhs.m_function) && (m_this_delta == rhs.m_this_delta)); } bool isnull() const @@ -496,8 +496,37 @@ public: } // comparison helpers - bool operator==(const delegate_mfp_msvc &rhs) const { return m_function == rhs.m_function; } - bool isnull() const { return !reinterpret_cast(m_function); } + bool operator==(const delegate_mfp_msvc &rhs) const + { + if (m_function != rhs.m_function) + { + return false; + } + else if (sizeof(single_base_equiv) == m_size) + { + return (sizeof(single_base_equiv) == rhs.m_size) || (!rhs.m_this_delta && ((sizeof(multi_base_equiv) == rhs.m_size) || !rhs.m_vt_index)); + } + else if (sizeof(multi_base_equiv) == m_size) + { + if (sizeof(unknown_base_equiv) == rhs.m_size) + return (m_this_delta == rhs.m_this_delta) && !rhs.m_vt_index; + else + return (sizeof(single_base_equiv) == rhs.m_size) ? !m_this_delta : (m_this_delta == rhs.m_this_delta); + } + else if (sizeof(unknown_base_equiv) == rhs.m_size) + { + return (m_this_delta == rhs.m_this_delta) && (m_vt_index == rhs.m_vt_index) && (!m_vt_index || (m_vptr_offs == rhs.m_vptr_offs)); + } + else + { + return !m_vt_index && ((sizeof(multi_base_equiv) == rhs.m_size) ? (m_this_delta == rhs.m_this_delta) : !m_this_delta); + } + } + + bool isnull() const + { + return !reinterpret_cast(m_function); + } // getters static delegate_generic_class *real_object(delegate_generic_class *original) { return original; } -- cgit v1.2.3