diff --git a/libcxx/docs/ReleaseNotes.rst b/libcxx/docs/ReleaseNotes.rst --- a/libcxx/docs/ReleaseNotes.rst +++ b/libcxx/docs/ReleaseNotes.rst @@ -48,6 +48,12 @@ Upcoming Deprecations and Removals ---------------------------------- +API Changes +----------- +- The comparison operators on ``thread::id`` are now defined as free-standing + functions instead of as hidden friends, in conformance with the C++ standard. + Also see `issue 56187 `_. + ABI Affecting Changes --------------------- diff --git a/libcxx/include/__threading_support b/libcxx/include/__threading_support --- a/libcxx/include/__threading_support +++ b/libcxx/include/__threading_support @@ -613,36 +613,12 @@ _LIBCPP_INLINE_VISIBILITY __thread_id() _NOEXCEPT : __id_(0) {} - friend _LIBCPP_INLINE_VISIBILITY - bool operator==(__thread_id __x, __thread_id __y) _NOEXCEPT - { // don't pass id==0 to underlying routines - if (__x.__id_ == 0) return __y.__id_ == 0; - if (__y.__id_ == 0) return false; - return __libcpp_thread_id_equal(__x.__id_, __y.__id_); - } - friend _LIBCPP_INLINE_VISIBILITY - bool operator!=(__thread_id __x, __thread_id __y) _NOEXCEPT - {return !(__x == __y);} - friend _LIBCPP_INLINE_VISIBILITY - bool operator< (__thread_id __x, __thread_id __y) _NOEXCEPT - { // id==0 is always less than any other thread_id - if (__x.__id_ == 0) return __y.__id_ != 0; - if (__y.__id_ == 0) return false; - return __libcpp_thread_id_less(__x.__id_, __y.__id_); - } - friend _LIBCPP_INLINE_VISIBILITY - bool operator<=(__thread_id __x, __thread_id __y) _NOEXCEPT - {return !(__y < __x);} - friend _LIBCPP_INLINE_VISIBILITY - bool operator> (__thread_id __x, __thread_id __y) _NOEXCEPT - {return __y < __x ;} - friend _LIBCPP_INLINE_VISIBILITY - bool operator>=(__thread_id __x, __thread_id __y) _NOEXCEPT - {return !(__x < __y);} - _LIBCPP_INLINE_VISIBILITY void __reset() { __id_ = 0; } + friend _LIBCPP_HIDE_FROM_ABI bool operator==(__thread_id __x, __thread_id __y) _NOEXCEPT; + friend _LIBCPP_HIDE_FROM_ABI bool operator< (__thread_id __x, __thread_id __y) _NOEXCEPT; + template friend _LIBCPP_INLINE_VISIBILITY @@ -658,6 +634,35 @@ friend struct _LIBCPP_TEMPLATE_VIS hash<__thread_id>; }; +inline _LIBCPP_HIDE_FROM_ABI +bool operator==(__thread_id __x, __thread_id __y) _NOEXCEPT { + // Don't pass id==0 to underlying routines + if (__x.__id_ == 0) + return __y.__id_ == 0; + if (__y.__id_ == 0) + return false; + return __libcpp_thread_id_equal(__x.__id_, __y.__id_); +} + +inline _LIBCPP_HIDE_FROM_ABI +bool operator!=(__thread_id __x, __thread_id __y) _NOEXCEPT { + return !(__x == __y); +} + +inline _LIBCPP_HIDE_FROM_ABI +bool operator<(__thread_id __x, __thread_id __y) _NOEXCEPT { + // id==0 is always less than any other thread_id + if (__x.__id_ == 0) + return __y.__id_ != 0; + if (__y.__id_ == 0) + return false; + return __libcpp_thread_id_less(__x.__id_, __y.__id_); +} + +inline _LIBCPP_HIDE_FROM_ABI bool operator<=(__thread_id __x, __thread_id __y) _NOEXCEPT { return !(__y < __x); } +inline _LIBCPP_HIDE_FROM_ABI bool operator>(__thread_id __x, __thread_id __y) _NOEXCEPT { return __y < __x; } +inline _LIBCPP_HIDE_FROM_ABI bool operator>=(__thread_id __x, __thread_id __y) _NOEXCEPT { return !(__x < __y); } + namespace this_thread { diff --git a/libcxx/test/std/thread/thread.threads/thread.thread.class/thread.thread.id/eq.pass.cpp b/libcxx/test/std/thread/thread.threads/thread.thread.class/thread.thread.id/eq.pass.cpp --- a/libcxx/test/std/thread/thread.threads/thread.thread.class/thread.thread.id/eq.pass.cpp +++ b/libcxx/test/std/thread/thread.threads/thread.thread.class/thread.thread.id/eq.pass.cpp @@ -31,5 +31,11 @@ assert(!(id1 == id0)); assert( (id1 != id0)); - return 0; + // Regression tests for https://github.com/llvm/llvm-project/issues/56187 + // libc++ previously declared the comparison operators as hidden friends + // which was non-conforming. + assert(!std::operator==(id1, id0)); + assert(std::operator!=(id1, id0)); + + return 0; } diff --git a/libcxx/test/std/thread/thread.threads/thread.thread.class/thread.thread.id/lt.pass.cpp b/libcxx/test/std/thread/thread.threads/thread.thread.class/thread.thread.id/lt.pass.cpp --- a/libcxx/test/std/thread/thread.threads/thread.thread.class/thread.thread.id/lt.pass.cpp +++ b/libcxx/test/std/thread/thread.threads/thread.thread.class/thread.thread.id/lt.pass.cpp @@ -42,5 +42,13 @@ assert( (id0 >= id2)); } - return 0; + // Regression tests for https://github.com/llvm/llvm-project/issues/56187 + // libc++ previously declared the comparison operators as hidden friends + // which was non-conforming. + assert(!std::operator<(id0, id1)); + assert(std::operator<=(id0, id1)); + assert(!std::operator>(id0, id1)); + assert(std::operator>=(id0, id1)); + + return 0; }