diff options
author | Vas Crabb <vas@vastheman.com> | 2021-09-22 05:58:42 +1000 |
---|---|---|
committer | Vas Crabb <vas@vastheman.com> | 2021-09-22 05:58:42 +1000 |
commit | 2bfa21eb2a6fd9af7429a347026c50aec045f590 (patch) | |
tree | 9565dec73cad2451237a8fcd7e1570c0164ec072 /src/lib | |
parent | 86c005377d62adf7996f3d6def3046e3fde1da27 (diff) |
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.
Diffstat (limited to 'src/lib')
-rw-r--r-- | src/lib/util/delegate.h | 35 |
1 files 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<void (*)()>(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<void (*)()>(m_function); + } // getters static delegate_generic_class *real_object(delegate_generic_class *original) { return original; } |