Bits of cleanup from clang 10 investigation (#475)

I built clang from the `release/10.x` branch to investigate support for the portions of the STL that require concepts. This went swimmingly, until I was blocked by LLVM-44627 "Reversed candidate operator is not found by argument dependent lookup". These are a few fixes and workarounds I discovered in the process of getting some tests to pass before being blocked completely.

Detailed changes:

`<compare>`:
* Workaround LLVM-41991 "c++2a: attributes on defaulted friend functions incorrectly rejected" by using `_NODISCARD` on such functions only for non-clang.

`<concepts>`:
* Fix typo.
* Workaround LLVM-44689 "[concepts] ICE when *this appears in trailing requires-clause" in `std::ranges::swap`.

`<xhash>`:
* Silence clang warning about template parameter shadowing by renaming.

`<xutility>`:
* Clang thinks my `unreachable_sentinel_t` hack is ill-formed.
This commit is contained in:
Casey Carter 2020-01-29 20:01:15 -08:00 коммит произвёл GitHub
Родитель 2bd2bd2db1
Коммит 70db54d8eb
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
4 изменённых файлов: 24 добавлений и 15 удалений

Просмотреть файл

@ -50,7 +50,10 @@ public:
}
#if defined(__cpp_impl_three_way_comparison) && __cpp_impl_three_way_comparison >= 201902L
_NODISCARD friend constexpr bool operator==(const partial_ordering&, const partial_ordering&) noexcept = default;
#ifndef __clang__ // TRANSITION, LLVM-41991
_NODISCARD
#endif // TRANSITION, LLVM-41991
friend constexpr bool operator==(const partial_ordering&, const partial_ordering&) noexcept = default;
#else // ^^^ supports <=> and P1185 / supports neither vvv
_NODISCARD friend constexpr bool operator!=(const partial_ordering _Val, _Literal_zero) noexcept {
return !_Val._Is_ordered || _Val._Value != 0;
@ -138,7 +141,10 @@ public:
}
#if defined(__cpp_impl_three_way_comparison) && __cpp_impl_three_way_comparison >= 201902L
_NODISCARD friend constexpr bool operator==(const weak_ordering&, const weak_ordering&) noexcept = default;
#ifndef __clang__ // TRANSITION, LLVM-41991
_NODISCARD
#endif // TRANSITION, LLVM-41991
friend constexpr bool operator==(const weak_ordering&, const weak_ordering&) noexcept = default;
#else // ^^^ supports <=> and P1185 / supports neither vvv
_NODISCARD friend constexpr bool operator!=(const weak_ordering _Val, _Literal_zero) noexcept {
return _Val._Value != 0;
@ -229,7 +235,10 @@ public:
}
#if defined(__cpp_impl_three_way_comparison) && __cpp_impl_three_way_comparison >= 201902L
_NODISCARD friend constexpr bool operator==(const strong_ordering&, const strong_ordering&) noexcept = default;
#ifndef __clang__ // TRANSITION, LLVM-41991
_NODISCARD
#endif // TRANSITION, LLVM-41991
friend constexpr bool operator==(const strong_ordering&, const strong_ordering&) noexcept = default;
#else // ^^^ supports <=> and P1185 / supports neither vvv
_NODISCARD friend constexpr bool operator!=(const strong_ordering _Val, _Literal_zero) noexcept {
return _Val._Value != 0;

Просмотреть файл

@ -32,7 +32,7 @@ _STD_BEGIN
template <class _Ty1, class _Ty2>
concept _Same_impl = // Must be a distinct concept to provide symmetric subsumption for same_as
#ifdef __clang__
__is_same(_Ty1 _Ty2);
__is_same(_Ty1, _Ty2);
#else // ^^^ use intrinsic / no intrinsic vvv
is_same_v<_Ty1, _Ty2>;
#endif // __clang__
@ -160,7 +160,7 @@ namespace ranges {
template <class _Ty1, class _Ty2, size_t _Size>
constexpr void operator()(_Ty1 (&__t)[_Size], _Ty2 (&__u)[_Size]) const
noexcept(noexcept((*this)(__t[0], __u[0])))
requires requires { (*this)(__t[0], __u[0]); } {
requires requires(const _Cpo& __f) { __f(__t[0], __u[0]); } { // TRANSITION, LLVM-44689
for (size_t __i = 0; __i < _Size; ++__i) {
(*this)(__t[__i], __u[__i]);
}

Просмотреть файл

@ -376,15 +376,15 @@ public:
static constexpr bool _Multi = _Traits::_Multi;
#if !_HAS_IF_CONSTEXPR
template <class _Traits>
friend bool _Hash_equal_elements(const _Hash<_Traits>& _Left, const _Hash<_Traits>& _Right, false_type);
template <class _TraitsT>
friend bool _Hash_equal_elements(const _Hash<_TraitsT>& _Left, const _Hash<_TraitsT>& _Right, false_type);
template <class _Traits>
friend bool _Hash_equal_elements(const _Hash<_Traits>& _Left, const _Hash<_Traits>& _Right, true_type);
template <class _TraitsT>
friend bool _Hash_equal_elements(const _Hash<_TraitsT>& _Left, const _Hash<_TraitsT>& _Right, true_type);
#endif // !_HAS_IF_CONSTEXPR
template <class _Traits>
friend bool _Hash_equal(const _Hash<_Traits>& _Left, const _Hash<_Traits>& _Right);
template <class _TraitsT>
friend bool _Hash_equal(const _Hash<_TraitsT>& _Left, const _Hash<_TraitsT>& _Right);
protected:
_Hash(const _Key_compare& _Parg, const allocator_type& _Al)

Просмотреть файл

@ -3490,21 +3490,21 @@ struct unreachable_sentinel_t;
namespace _Unreachable_sentinel_detail {
struct _Base {
template <weakly_incrementable _Winc>
_NODISCARD friend constexpr bool operator==(unreachable_sentinel_t, const _Winc&) noexcept {
_NODISCARD friend constexpr bool operator==(const unreachable_sentinel_t&, const _Winc&) noexcept {
return false;
}
#if !defined(__cpp_impl_three_way_comparison) || __cpp_impl_three_way_comparison < 201902L
template <weakly_incrementable _Winc>
_NODISCARD friend constexpr bool operator==(const _Winc&, unreachable_sentinel_t) noexcept {
_NODISCARD friend constexpr bool operator==(const _Winc&, const unreachable_sentinel_t&) noexcept {
return false;
}
template <weakly_incrementable _Winc>
_NODISCARD friend constexpr bool operator!=(unreachable_sentinel_t, const _Winc&) noexcept {
_NODISCARD friend constexpr bool operator!=(const unreachable_sentinel_t&, const _Winc&) noexcept {
return true;
}
template <weakly_incrementable _Winc>
_NODISCARD friend constexpr bool operator!=(const _Winc&, unreachable_sentinel_t) noexcept {
_NODISCARD friend constexpr bool operator!=(const _Winc&, const unreachable_sentinel_t&) noexcept {
return true;
}
#endif // !defined(__cpp_impl_three_way_comparison) || __cpp_impl_three_way_comparison < 201902L