[libcxx] r329460 - Implement P0768r1: Library support for the Spaceship Operator.

Richard Smith via cfe-commits cfe-commits at lists.llvm.org
Fri Apr 6 21:50:28 PDT 2018


On Fri, 6 Apr 2018, 21:04 Eric Fiselier via cfe-commits, <
cfe-commits at lists.llvm.org> wrote:

>
>
> On Fri, Apr 6, 2018 at 4:00 PM, Richard Smith <richard at metafoo.co.uk>
> wrote:
>
>> On 6 April 2018 at 14:37, Eric Fiselier via cfe-commits <
>> cfe-commits at lists.llvm.org> wrote:
>>
>>> Author: ericwf
>>> Date: Fri Apr  6 14:37:23 2018
>>> New Revision: 329460
>>>
>>> URL: http://llvm.org/viewvc/llvm-project?rev=329460&view=rev
>>> Log:
>>> Implement P0768r1: Library support for the Spaceship Operator.
>>>
>>> this patch adds the <compare> header and implements all of it
>>> except for [comp.alg].
>>>
>>> As I understand it, the header is needed by the compiler in
>>> when implementing the semantics of operator<=>. For that reason
>>> I feel it's important to land this header early, despite
>>> all compilers lacking support.
>>>
>>> Added:
>>>     libcxx/trunk/include/compare
>>>     libcxx/trunk/test/libcxx/language.support/cmp/
>>>     libcxx/trunk/test/libcxx/language.support/cmp/version.pass.cpp
>>>     libcxx/trunk/test/std/language.support/cmp/
>>>     libcxx/trunk/test/std/language.support/cmp/cmp.common/
>>>
>>> libcxx/trunk/test/std/language.support/cmp/cmp.common/common_comparison_category.pass.cpp
>>>     libcxx/trunk/test/std/language.support/cmp/cmp.partialord/
>>>
>>> libcxx/trunk/test/std/language.support/cmp/cmp.partialord/partialord.pass.cpp
>>>     libcxx/trunk/test/std/language.support/cmp/cmp.strongeq/
>>>
>>> libcxx/trunk/test/std/language.support/cmp/cmp.strongeq/cmp.strongeq.pass.cpp
>>>     libcxx/trunk/test/std/language.support/cmp/cmp.strongord/
>>>
>>> libcxx/trunk/test/std/language.support/cmp/cmp.strongord/strongord.pass.cpp
>>>     libcxx/trunk/test/std/language.support/cmp/cmp.weakeq/
>>>
>>> libcxx/trunk/test/std/language.support/cmp/cmp.weakeq/cmp.weakeq.pass.cpp
>>>     libcxx/trunk/test/std/language.support/cmp/cmp.weakord/
>>>
>>> libcxx/trunk/test/std/language.support/cmp/cmp.weakord/weakord.pass.cpp
>>> Modified:
>>>     libcxx/trunk/include/CMakeLists.txt
>>>     libcxx/trunk/include/__config
>>>     libcxx/trunk/include/module.modulemap
>>>     libcxx/trunk/test/libcxx/double_include.sh.cpp
>>>     libcxx/trunk/test/support/test_macros.h
>>>
>>> Modified: libcxx/trunk/include/CMakeLists.txt
>>> URL:
>>> http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/CMakeLists.txt?rev=329460&r1=329459&r2=329460&view=diff
>>>
>>> ==============================================================================
>>> --- libcxx/trunk/include/CMakeLists.txt (original)
>>> +++ libcxx/trunk/include/CMakeLists.txt Fri Apr  6 14:37:23 2018
>>> @@ -77,5 +77,4 @@ if (LIBCXX_INSTALL_HEADERS)
>>>      add_custom_target(install-libcxx-headers DEPENDS
>>> install-cxx-headers)
>>>      add_custom_target(install-libcxx-headers-stripped DEPENDS
>>> install-cxx-headers-stripped)
>>>    endif()
>>> -
>>>  endif()
>>>
>>> Modified: libcxx/trunk/include/__config
>>> URL:
>>> http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/__config?rev=329460&r1=329459&r2=329460&view=diff
>>>
>>> ==============================================================================
>>> --- libcxx/trunk/include/__config (original)
>>> +++ libcxx/trunk/include/__config Fri Apr  6 14:37:23 2018
>>> @@ -1196,6 +1196,11 @@ _LIBCPP_FUNC_VIS extern "C" void __sanit
>>>  #define _LIBCPP_HAS_NO_COROUTINES
>>>  #endif
>>>
>>> +// FIXME: Correct this macro when either (A) a feature test macro for
>>> the
>>> +// spaceship operator is provided, or (B) a compiler provides a complete
>>> +// implementation.
>>> +#define _LIBCPP_HAS_NO_SPACESHIP_OPERATOR
>>> +
>>>  // Decide whether to use availability macros.
>>>  #if !defined(_LIBCPP_BUILDING_LIBRARY) &&
>>>         \
>>>      !defined(_LIBCPP_DISABLE_AVAILABILITY) &&
>>>         \
>>>
>>> Added: libcxx/trunk/include/compare
>>> URL:
>>> http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/compare?rev=329460&view=auto
>>>
>>> ==============================================================================
>>> --- libcxx/trunk/include/compare (added)
>>> +++ libcxx/trunk/include/compare Fri Apr  6 14:37:23 2018
>>> @@ -0,0 +1,679 @@
>>> +// -*- C++ -*-
>>> +//===-------------------------- compare
>>> -----------------------------------===//
>>> +//
>>> +//                     The LLVM Compiler Infrastructure
>>> +//
>>> +// This file is dual licensed under the MIT and the University of
>>> Illinois Open
>>> +// Source Licenses. See LICENSE.TXT for details.
>>> +//
>>>
>>> +//===----------------------------------------------------------------------===//
>>> +
>>> +#ifndef _LIBCPP_COMPARE
>>> +#define _LIBCPP_COMPARE
>>> +
>>> +/*
>>> +    compare synopsis
>>> +
>>> +namespace std {
>>> +  // [cmp.categories], comparison category types
>>> +  class weak_equality;
>>> +  class strong_equality;
>>> +  class partial_ordering;
>>> +  class weak_ordering;
>>> +  class strong_ordering;
>>> +
>>> +  // named comparison functions
>>> +  constexpr bool is_eq  (weak_equality cmp) noexcept    { return cmp ==
>>> 0; }
>>> +  constexpr bool is_neq (weak_equality cmp) noexcept    { return cmp !=
>>> 0; }
>>> +  constexpr bool is_lt  (partial_ordering cmp) noexcept { return cmp <
>>> 0; }
>>> +  constexpr bool is_lteq(partial_ordering cmp) noexcept { return cmp <=
>>> 0; }
>>> +  constexpr bool is_gt  (partial_ordering cmp) noexcept { return cmp >
>>> 0; }
>>> +  constexpr bool is_gteq(partial_ordering cmp) noexcept { return cmp >=
>>> 0; }
>>> +
>>> +  // [cmp.common], common comparison category type
>>> +  template<class... Ts>
>>> +  struct common_comparison_category {
>>> +    using type = see below;
>>> +  };
>>> +  template<class... Ts>
>>> +    using common_comparison_category_t = typename
>>> common_comparison_category<Ts...>::type;
>>> +
>>> +  // [cmp.alg], comparison algorithms
>>> +  template<class T> constexpr strong_ordering strong_order(const T& a,
>>> const T& b);
>>> +  template<class T> constexpr weak_ordering weak_order(const T& a,
>>> const T& b);
>>> +  template<class T> constexpr partial_ordering partial_order(const T&
>>> a, const T& b);
>>> +  template<class T> constexpr strong_equality strong_equal(const T& a,
>>> const T& b);
>>> +  template<class T> constexpr weak_equality weak_equal(const T& a,
>>> const T& b);
>>> +}
>>> +*/
>>> +
>>> +#include <__config>
>>> +#include <type_traits>
>>> +#include <array>
>>> +
>>> +#ifndef _LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER
>>> +#pragma GCC system_header
>>> +#endif
>>> +
>>> +_LIBCPP_BEGIN_NAMESPACE_STD
>>> +
>>> +#if _LIBCPP_STD_VER > 17
>>> +
>>> +// exposition only
>>> +enum class _LIBCPP_ENUM_VIS _EqResult : unsigned char {
>>> +  __zero = 0,
>>> +  __equal = __zero,
>>> +  __equiv = __equal,
>>> +  __nonequal = 1,
>>> +  __nonequiv = __nonequal
>>> +};
>>> +
>>> +enum class _LIBCPP_ENUM_VIS _OrdResult : signed char {
>>> +  __less = -1,
>>> +  __greater = 1
>>> +};
>>> +
>>> +enum class _LIBCPP_ENUM_VIS _NCmpResult : signed char {
>>> +  __unordered = -127
>>> +};
>>> +
>>> +struct _CmpUnspecifiedType;
>>> +using _CmpUnspecifiedParam = void (_CmpUnspecifiedType::*)();
>>>
>>
>> FYI, I've been planning to add a __zero_type to the compiler for this (a
>> type that can only be initialized by a literal zero, not e.g. by nullptr).
>> Looks like that would be easy to retrofit here once it's available.
>>
>
> Awesome :-)
>
>
>>
>> +
>>> +class  weak_equality {
>>> +  _LIBCPP_INLINE_VISIBILITY
>>> +  constexpr explicit weak_equality(_EqResult __val) noexcept :
>>> __value_(__val) {}
>>> +
>>> +public:
>>> +  static const weak_equality equivalent;
>>> +  static const weak_equality nonequivalent;
>>> +
>>> +  friend constexpr bool operator==(weak_equality __v,
>>> _CmpUnspecifiedParam) noexcept;
>>> +  friend constexpr bool operator==(_CmpUnspecifiedParam, weak_equality
>>> __v) noexcept;
>>> +  friend constexpr bool operator!=(weak_equality __v,
>>> _CmpUnspecifiedParam) noexcept;
>>> +  friend constexpr bool operator!=(_CmpUnspecifiedParam, weak_equality
>>> __v) noexcept;
>>> +
>>> +#ifndef _LIBCPP_HAS_NO_SPACESHIP_OPERATOR
>>> +  friend constexpr weak_equality operator<=>(weak_equality __v,
>>> _CmpUnspecifiedParam) noexcept;
>>> +  friend constexpr weak_equality operator<=>(_CmpUnspecifiedParam,
>>> weak_equality __v) noexcept;
>>> +#endif
>>> +
>>> +private:
>>> +  _EqResult __value_;
>>> +};
>>> +
>>> +_LIBCPP_INLINE_VAR constexpr weak_equality
>>> weak_equality::equivalent(_EqResult::__equiv);
>>> +_LIBCPP_INLINE_VAR constexpr weak_equality
>>> weak_equality::nonequivalent(_EqResult::__nonequiv);
>>> +
>>> +_LIBCPP_INLINE_VISIBILITY
>>> +inline constexpr bool operator==(weak_equality __v,
>>> _CmpUnspecifiedParam) noexcept {
>>> +  return __v.__value_ == _EqResult::__zero;
>>> +}
>>> +
>>> +_LIBCPP_INLINE_VISIBILITY
>>> +inline constexpr bool operator==(_CmpUnspecifiedParam, weak_equality
>>> __v) noexcept {
>>> +  return __v.__value_ == _EqResult::__zero;
>>> +}
>>> +
>>> +_LIBCPP_INLINE_VISIBILITY
>>> +inline constexpr bool operator!=(weak_equality __v,
>>> _CmpUnspecifiedParam) noexcept {
>>> +  return __v.__value_ != _EqResult::__zero;
>>> +}
>>> +
>>> +_LIBCPP_INLINE_VISIBILITY
>>> +inline constexpr bool operator!=(_CmpUnspecifiedParam, weak_equality
>>> __v) noexcept {
>>> +  return __v.__value_ != _EqResult::__zero;
>>> +}
>>> +
>>> +#ifndef _LIBCPP_HAS_NO_SPACESHIP_OPERATOR
>>> +_LIBCPP_INLINE_VISIBILITY
>>> +inline constexpr weak_equality operator<=>(weak_equality __v,
>>> _CmpUnspecifiedParam) noexcept {
>>> +  return __v;
>>> +}
>>> +
>>> +_LIBCPP_INLINE_VISIBILITY
>>> +inline constexpr weak_equality operator<=>(_CmpUnspecifiedParam,
>>> weak_equality __v) noexcept {
>>> +  return __v;
>>> +}
>>> +#endif
>>> +
>>> +class strong_equality {
>>> +  _LIBCPP_INLINE_VISIBILITY
>>> +  explicit constexpr strong_equality(_EqResult __val) noexcept :
>>> __value_(__val) {}
>>> +
>>> +public:
>>> +  static const strong_equality equal;
>>> +  static const strong_equality nonequal;
>>> +  static const strong_equality equivalent;
>>> +  static const strong_equality nonequivalent;
>>> +
>>> +  // conversion
>>> +  constexpr operator weak_equality() const noexcept {
>>> +    return __value_ == _EqResult::__zero ? weak_equality::equivalent
>>> +          : weak_equality::nonequivalent;
>>> +  }
>>> +
>>> +  // comparisons
>>> +  friend constexpr bool operator==(strong_equality __v,
>>> _CmpUnspecifiedParam) noexcept;
>>> +  friend constexpr bool operator!=(strong_equality __v,
>>> _CmpUnspecifiedParam) noexcept;
>>> +  friend constexpr bool operator==(_CmpUnspecifiedParam,
>>> strong_equality __v) noexcept;
>>> +  friend constexpr bool operator!=(_CmpUnspecifiedParam,
>>> strong_equality __v) noexcept;
>>> +
>>> +#ifndef _LIBCPP_HAS_NO_SPACESHIP_OPERATOR
>>> +  friend constexpr strong_equality operator<=>(strong_equality __v,
>>> _CmpUnspecifiedParam) noexcept;
>>> +  friend constexpr strong_equality operator<=>(_CmpUnspecifiedParam,
>>> strong_equality __v) noexcept;
>>> +#endif
>>> +private:
>>> +  _EqResult __value_;
>>> +};
>>> +
>>> +_LIBCPP_INLINE_VAR constexpr strong_equality
>>> strong_equality::equal(_EqResult::__equal);
>>> +_LIBCPP_INLINE_VAR constexpr strong_equality
>>> strong_equality::nonequal(_EqResult::__nonequal);
>>> +_LIBCPP_INLINE_VAR constexpr strong_equality
>>> strong_equality::equivalent(_EqResult::__equiv);
>>> +_LIBCPP_INLINE_VAR constexpr strong_equality
>>> strong_equality::nonequivalent(_EqResult::__nonequiv);
>>> +
>>> +_LIBCPP_INLINE_VISIBILITY
>>> +constexpr bool operator==(strong_equality __v, _CmpUnspecifiedParam)
>>> noexcept {
>>> +  return __v.__value_ == _EqResult::__zero;
>>> +}
>>> +
>>> +_LIBCPP_INLINE_VISIBILITY
>>> +constexpr bool operator==(_CmpUnspecifiedParam, strong_equality __v)
>>> noexcept {
>>> +  return __v.__value_ == _EqResult::__zero;
>>> +}
>>> +
>>> +_LIBCPP_INLINE_VISIBILITY
>>> +constexpr bool operator!=(strong_equality __v, _CmpUnspecifiedParam)
>>> noexcept {
>>> +  return __v.__value_ != _EqResult::__zero;
>>> +}
>>> +
>>> +_LIBCPP_INLINE_VISIBILITY
>>> +constexpr bool operator!=(_CmpUnspecifiedParam, strong_equality __v)
>>> noexcept {
>>> +  return __v.__value_ != _EqResult::__zero;
>>> +}
>>> +
>>> +#ifndef _LIBCPP_HAS_NO_SPACESHIP_OPERATOR
>>> +_LIBCPP_INLINE_VISIBILITY
>>> +constexpr strong_equality operator<=>(strong_equality __v,
>>> _CmpUnspecifiedParam) noexcept {
>>> +  return __v;
>>> +}
>>> +
>>> +_LIBCPP_INLINE_VISIBILITY
>>> +constexpr strong_equality operator<=>(_CmpUnspecifiedParam,
>>> strong_equality __v) noexcept {
>>> +  return __v;
>>> +}
>>> +#endif // _LIBCPP_HAS_NO_SPACESHIP_OPERATOR
>>> +
>>> +class partial_ordering {
>>> +  using _ValueT = signed char;
>>> +
>>> +  _LIBCPP_INLINE_VISIBILITY
>>> +  explicit constexpr partial_ordering(_EqResult __v) noexcept
>>> +      : __value_(_ValueT(__v)) {}
>>> +
>>> +  _LIBCPP_INLINE_VISIBILITY
>>> +  explicit constexpr partial_ordering(_OrdResult __v) noexcept
>>> +      : __value_(_ValueT(__v)) {}
>>> +
>>> +  _LIBCPP_INLINE_VISIBILITY
>>> +  explicit constexpr partial_ordering(_NCmpResult __v) noexcept
>>> +      : __value_(_ValueT(__v)) {}
>>> +
>>> +  constexpr bool __is_ordered() const noexcept {
>>> +    return __value_ != _ValueT(_NCmpResult::__unordered);
>>> +  }
>>> +public:
>>> +  // valid values
>>> +  static const partial_ordering less;
>>> +  static const partial_ordering equivalent;
>>> +  static const partial_ordering greater;
>>> +  static const partial_ordering unordered;
>>> +
>>> +  // conversion
>>> +  constexpr operator weak_equality() const noexcept {
>>> +    return __value_ == 0 ? weak_equality::equivalent :
>>> weak_equality::nonequivalent;
>>> +  }
>>> +
>>> +  // comparisons
>>> +  friend constexpr bool operator==(partial_ordering __v,
>>> _CmpUnspecifiedParam) noexcept;
>>> +  friend constexpr bool operator!=(partial_ordering __v,
>>> _CmpUnspecifiedParam) noexcept;
>>> +  friend constexpr bool operator< (partial_ordering __v,
>>> _CmpUnspecifiedParam) noexcept;
>>> +  friend constexpr bool operator<=(partial_ordering __v,
>>> _CmpUnspecifiedParam) noexcept;
>>> +  friend constexpr bool operator> (partial_ordering __v,
>>> _CmpUnspecifiedParam) noexcept;
>>> +  friend constexpr bool operator>=(partial_ordering __v,
>>> _CmpUnspecifiedParam) noexcept;
>>> +  friend constexpr bool operator==(_CmpUnspecifiedParam,
>>> partial_ordering __v) noexcept;
>>> +  friend constexpr bool operator!=(_CmpUnspecifiedParam,
>>> partial_ordering __v) noexcept;
>>> +  friend constexpr bool operator< (_CmpUnspecifiedParam,
>>> partial_ordering __v) noexcept;
>>> +  friend constexpr bool operator<=(_CmpUnspecifiedParam,
>>> partial_ordering __v) noexcept;
>>> +  friend constexpr bool operator> (_CmpUnspecifiedParam,
>>> partial_ordering __v) noexcept;
>>> +  friend constexpr bool operator>=(_CmpUnspecifiedParam,
>>> partial_ordering __v) noexcept;
>>> +
>>> +#ifndef _LIBCPP_HAS_NO_SPACESHIP_OPERATOR
>>> +  friend constexpr partial_ordering operator<=>(partial_ordering __v,
>>> _CmpUnspecifiedParam) noexcept;
>>> +  friend constexpr partial_ordering operator<=>(_CmpUnspecifiedParam,
>>> partial_ordering __v) noexcept;
>>> +#endif
>>> +
>>> +private:
>>> +  _ValueT __value_;
>>> +};
>>> +
>>> +_LIBCPP_INLINE_VAR constexpr partial_ordering
>>> partial_ordering::less(_OrdResult::__less);
>>> +_LIBCPP_INLINE_VAR constexpr partial_ordering
>>> partial_ordering::equivalent(_EqResult::__equiv);
>>> +_LIBCPP_INLINE_VAR constexpr partial_ordering
>>> partial_ordering::greater(_OrdResult::__greater);
>>> +_LIBCPP_INLINE_VAR constexpr partial_ordering
>>> partial_ordering::unordered(_NCmpResult ::__unordered);
>>> +
>>> +_LIBCPP_INLINE_VISIBILITY
>>> +constexpr bool operator==(partial_ordering __v, _CmpUnspecifiedParam)
>>> noexcept {
>>> +  return __v.__is_ordered() && __v.__value_ == 0;
>>> +}
>>> +_LIBCPP_INLINE_VISIBILITY
>>> +constexpr bool operator< (partial_ordering __v, _CmpUnspecifiedParam)
>>> noexcept {
>>> +  return __v.__is_ordered() && __v.__value_ < 0;
>>> +}
>>> +_LIBCPP_INLINE_VISIBILITY
>>> +constexpr bool operator<=(partial_ordering __v, _CmpUnspecifiedParam)
>>> noexcept {
>>> +  return __v.__is_ordered() && __v.__value_ <= 0;
>>> +}
>>> +_LIBCPP_INLINE_VISIBILITY
>>> +constexpr bool operator> (partial_ordering __v, _CmpUnspecifiedParam)
>>> noexcept {
>>> +  return __v.__is_ordered() && __v.__value_ > 0;
>>> +}
>>> +_LIBCPP_INLINE_VISIBILITY
>>> +constexpr bool operator>=(partial_ordering __v, _CmpUnspecifiedParam)
>>> noexcept {
>>> +  return __v.__is_ordered() && __v.__value_ >= 0;
>>> +}
>>> +
>>> +_LIBCPP_INLINE_VISIBILITY
>>> +constexpr bool operator==(_CmpUnspecifiedParam, partial_ordering __v)
>>> noexcept {
>>> +  return __v.__is_ordered() && 0 == __v.__value_;
>>> +}
>>> +_LIBCPP_INLINE_VISIBILITY
>>> +constexpr bool operator< (_CmpUnspecifiedParam, partial_ordering __v)
>>> noexcept {
>>> +  return __v.__is_ordered() && 0 < __v.__value_;
>>> +}
>>> +_LIBCPP_INLINE_VISIBILITY
>>> +constexpr bool operator<=(_CmpUnspecifiedParam, partial_ordering __v)
>>> noexcept {
>>> +  return __v.__is_ordered() && 0 <= __v.__value_;
>>> +}
>>> +_LIBCPP_INLINE_VISIBILITY
>>> +constexpr bool operator> (_CmpUnspecifiedParam, partial_ordering __v)
>>> noexcept {
>>> +  return __v.__is_ordered() && 0 > __v.__value_;
>>> +}
>>> +_LIBCPP_INLINE_VISIBILITY
>>> +constexpr bool operator>=(_CmpUnspecifiedParam, partial_ordering __v)
>>> noexcept {
>>> +  return __v.__is_ordered() && 0 >= __v.__value_;
>>> +}
>>> +
>>> +_LIBCPP_INLINE_VISIBILITY
>>> +constexpr bool operator!=(partial_ordering __v, _CmpUnspecifiedParam)
>>> noexcept {
>>> +  return !__v.__is_ordered() || __v.__value_ != 0;
>>> +}
>>> +_LIBCPP_INLINE_VISIBILITY
>>> +constexpr bool operator!=(_CmpUnspecifiedParam, partial_ordering __v)
>>> noexcept {
>>> +  return !__v.__is_ordered() || __v.__value_ != 0;
>>> +}
>>> +
>>> +#ifndef _LIBCPP_HAS_NO_SPACESHIP_OPERATOR
>>> +_LIBCPP_INLINE_VISIBILITY
>>> +constexpr partial_ordering operator<=>(partial_ordering __v,
>>> _CmpUnspecifiedParam) noexcept {
>>> +  return __v;
>>> +}
>>> +_LIBCPP_INLINE_VISIBILITY
>>> +constexpr partial_ordering operator<=>(_CmpUnspecifiedParam,
>>> partial_ordering __v) noexcept {
>>> +  return __v < 0 ? partial_ordering::greater : (__v > 0 ?
>>> partial_ordering::less : __v);
>>> +}
>>> +#endif // _LIBCPP_HAS_NO_SPACESHIP_OPERATOR
>>> +
>>> +class weak_ordering {
>>> +  using _ValueT = signed char;
>>> +
>>> +  _LIBCPP_INLINE_VISIBILITY
>>> +  explicit constexpr weak_ordering(_EqResult __v) noexcept :
>>> __value_(_ValueT(__v)) {}
>>> +  _LIBCPP_INLINE_VISIBILITY
>>> +  explicit constexpr weak_ordering(_OrdResult __v) noexcept :
>>> __value_(_ValueT(__v)) {}
>>> +
>>> +public:
>>> +  static const weak_ordering less;
>>> +  static const weak_ordering equivalent;
>>> +  static const weak_ordering greater;
>>> +
>>> +  // conversions
>>> +  _LIBCPP_INLINE_VISIBILITY
>>> +  constexpr operator weak_equality() const noexcept {
>>> +    return __value_ == 0 ? weak_equality::equivalent
>>> +                         : weak_equality::nonequivalent;
>>> +  }
>>> +
>>> +  _LIBCPP_INLINE_VISIBILITY
>>> +  constexpr operator partial_ordering() const noexcept {
>>> +    return __value_ == 0 ? partial_ordering::equivalent
>>> +        : (__value_ < 0 ? partial_ordering::less :
>>> partial_ordering::greater);
>>> +  }
>>> +
>>> +  // comparisons
>>> +  friend constexpr bool operator==(weak_ordering __v,
>>> _CmpUnspecifiedParam) noexcept;
>>> +  friend constexpr bool operator!=(weak_ordering __v,
>>> _CmpUnspecifiedParam) noexcept;
>>> +  friend constexpr bool operator< (weak_ordering __v,
>>> _CmpUnspecifiedParam) noexcept;
>>> +  friend constexpr bool operator<=(weak_ordering __v,
>>> _CmpUnspecifiedParam) noexcept;
>>> +  friend constexpr bool operator> (weak_ordering __v,
>>> _CmpUnspecifiedParam) noexcept;
>>> +  friend constexpr bool operator>=(weak_ordering __v,
>>> _CmpUnspecifiedParam) noexcept;
>>> +  friend constexpr bool operator==(_CmpUnspecifiedParam, weak_ordering
>>> __v) noexcept;
>>> +  friend constexpr bool operator!=(_CmpUnspecifiedParam, weak_ordering
>>> __v) noexcept;
>>> +  friend constexpr bool operator< (_CmpUnspecifiedParam, weak_ordering
>>> __v) noexcept;
>>> +  friend constexpr bool operator<=(_CmpUnspecifiedParam, weak_ordering
>>> __v) noexcept;
>>> +  friend constexpr bool operator> (_CmpUnspecifiedParam, weak_ordering
>>> __v) noexcept;
>>> +  friend constexpr bool operator>=(_CmpUnspecifiedParam, weak_ordering
>>> __v) noexcept;
>>> +
>>> +#ifndef _LIBCPP_HAS_NO_SPACESHIP_OPERATOR
>>> +  friend constexpr weak_ordering operator<=>(weak_ordering __v,
>>> _CmpUnspecifiedParam) noexcept;
>>> +  friend constexpr weak_ordering operator<=>(_CmpUnspecifiedParam,
>>> weak_ordering __v) noexcept;
>>> +#endif
>>> +
>>> +private:
>>> +  _ValueT __value_;
>>> +};
>>> +
>>> +_LIBCPP_INLINE_VAR constexpr weak_ordering
>>> weak_ordering::less(_OrdResult::__less);
>>> +_LIBCPP_INLINE_VAR constexpr weak_ordering
>>> weak_ordering::equivalent(_EqResult::__equiv);
>>> +_LIBCPP_INLINE_VAR constexpr weak_ordering
>>> weak_ordering::greater(_OrdResult::__greater);
>>> +
>>> +_LIBCPP_INLINE_VISIBILITY
>>> +constexpr bool operator==(weak_ordering __v, _CmpUnspecifiedParam)
>>> noexcept {
>>> +  return __v.__value_ == 0;
>>> +}
>>> +_LIBCPP_INLINE_VISIBILITY
>>> +constexpr bool operator!=(weak_ordering __v, _CmpUnspecifiedParam)
>>> noexcept {
>>> +  return __v.__value_ != 0;
>>> +}
>>> +_LIBCPP_INLINE_VISIBILITY
>>> +constexpr bool operator< (weak_ordering __v, _CmpUnspecifiedParam)
>>> noexcept {
>>> +  return __v.__value_ < 0;
>>> +}
>>> +_LIBCPP_INLINE_VISIBILITY
>>> +constexpr bool operator<=(weak_ordering __v, _CmpUnspecifiedParam)
>>> noexcept {
>>> +  return __v.__value_ <= 0;
>>> +}
>>> +_LIBCPP_INLINE_VISIBILITY
>>> +constexpr bool operator> (weak_ordering __v, _CmpUnspecifiedParam)
>>> noexcept {
>>> +  return __v.__value_ > 0;
>>> +}
>>> +_LIBCPP_INLINE_VISIBILITY
>>> +constexpr bool operator>=(weak_ordering __v, _CmpUnspecifiedParam)
>>> noexcept {
>>> +  return __v.__value_ >= 0;
>>> +}
>>> +_LIBCPP_INLINE_VISIBILITY
>>> +constexpr bool operator==(_CmpUnspecifiedParam, weak_ordering __v)
>>> noexcept {
>>> +  return 0 == __v.__value_;
>>> +}
>>> +_LIBCPP_INLINE_VISIBILITY
>>> +constexpr bool operator!=(_CmpUnspecifiedParam, weak_ordering __v)
>>> noexcept {
>>> +  return 0 != __v.__value_;
>>> +}
>>> +_LIBCPP_INLINE_VISIBILITY
>>> +constexpr bool operator< (_CmpUnspecifiedParam, weak_ordering __v)
>>> noexcept {
>>> +  return 0 < __v.__value_;
>>> +}
>>> +_LIBCPP_INLINE_VISIBILITY
>>> +constexpr bool operator<=(_CmpUnspecifiedParam, weak_ordering __v)
>>> noexcept {
>>> +  return 0 <= __v.__value_;
>>> +}
>>> +_LIBCPP_INLINE_VISIBILITY
>>> +constexpr bool operator> (_CmpUnspecifiedParam, weak_ordering __v)
>>> noexcept {
>>> +  return 0 > __v.__value_;
>>> +}
>>> +_LIBCPP_INLINE_VISIBILITY
>>> +constexpr bool operator>=(_CmpUnspecifiedParam, weak_ordering __v)
>>> noexcept {
>>> +  return 0 >= __v.__value_;
>>> +}
>>> +
>>> +#ifndef _LIBCPP_HAS_NO_SPACESHIP_OPERATOR
>>> +_LIBCPP_INLINE_VISIBILITY
>>> +constexpr weak_ordering operator<=>(weak_ordering __v,
>>> _CmpUnspecifiedParam) noexcept {
>>> +  return __v;
>>> +}
>>> +_LIBCPP_INLINE_VISIBILITY
>>> +constexpr weak_ordering operator<=>(_CmpUnspecifiedParam, weak_ordering
>>> __v) noexcept {
>>> +  return __v < 0 ? weak_ordering::greater : (__v > 0 ?
>>> weak_ordering::less : __v);
>>> +}
>>> +#endif // _LIBCPP_HAS_NO_SPACESHIP_OPERATOR
>>> +
>>> +class strong_ordering {
>>> +  using _ValueT = signed char;
>>> +
>>> +  _LIBCPP_INLINE_VISIBILITY
>>> +  explicit constexpr strong_ordering(_EqResult __v) noexcept :
>>> __value_(_ValueT(__v)) {}
>>> +  _LIBCPP_INLINE_VISIBILITY
>>> +  explicit constexpr strong_ordering(_OrdResult __v) noexcept :
>>> __value_(_ValueT(__v)) {}
>>> +
>>> +public:
>>> +  static const strong_ordering less;
>>> +  static const strong_ordering equal;
>>> +  static const strong_ordering equivalent;
>>> +  static const strong_ordering greater;
>>> +
>>> +  // conversions
>>> +  _LIBCPP_INLINE_VISIBILITY
>>> +  constexpr operator weak_equality() const noexcept {
>>> +    return __value_ == 0 ? weak_equality::equivalent
>>> +                         : weak_equality::nonequivalent;
>>> +  }
>>> +
>>> +  _LIBCPP_INLINE_VISIBILITY
>>> +  constexpr operator strong_equality() const noexcept {
>>> +    return __value_ == 0 ? strong_equality::equal
>>> +                         : strong_equality::nonequal;
>>> +  }
>>> +
>>> +  _LIBCPP_INLINE_VISIBILITY
>>> +  constexpr operator partial_ordering() const noexcept {
>>> +    return __value_ == 0 ? partial_ordering::equivalent
>>> +        : (__value_ < 0 ? partial_ordering::less :
>>> partial_ordering::greater);
>>> +  }
>>> +
>>> +  _LIBCPP_INLINE_VISIBILITY
>>> +  constexpr operator weak_ordering() const noexcept {
>>> +    return __value_ == 0 ? weak_ordering::equivalent
>>> +        : (__value_ < 0 ? weak_ordering::less : weak_ordering::greater);
>>> +  }
>>> +
>>> +  // comparisons
>>> +  friend constexpr bool operator==(strong_ordering __v,
>>> _CmpUnspecifiedParam) noexcept;
>>> +  friend constexpr bool operator!=(strong_ordering __v,
>>> _CmpUnspecifiedParam) noexcept;
>>> +  friend constexpr bool operator< (strong_ordering __v,
>>> _CmpUnspecifiedParam) noexcept;
>>> +  friend constexpr bool operator<=(strong_ordering __v,
>>> _CmpUnspecifiedParam) noexcept;
>>> +  friend constexpr bool operator> (strong_ordering __v,
>>> _CmpUnspecifiedParam) noexcept;
>>> +  friend constexpr bool operator>=(strong_ordering __v,
>>> _CmpUnspecifiedParam) noexcept;
>>> +  friend constexpr bool operator==(_CmpUnspecifiedParam,
>>> strong_ordering __v) noexcept;
>>> +  friend constexpr bool operator!=(_CmpUnspecifiedParam,
>>> strong_ordering __v) noexcept;
>>> +  friend constexpr bool operator< (_CmpUnspecifiedParam,
>>> strong_ordering __v) noexcept;
>>> +  friend constexpr bool operator<=(_CmpUnspecifiedParam,
>>> strong_ordering __v) noexcept;
>>> +  friend constexpr bool operator> (_CmpUnspecifiedParam,
>>> strong_ordering __v) noexcept;
>>> +  friend constexpr bool operator>=(_CmpUnspecifiedParam,
>>> strong_ordering __v) noexcept;
>>> +
>>> +#ifndef _LIBCPP_HAS_NO_SPACESHIP_OPERATOR
>>> +  friend constexpr strong_ordering operator<=>(strong_ordering __v,
>>> _CmpUnspecifiedParam) noexcept;
>>> +  friend constexpr strong_ordering operator<=>(_CmpUnspecifiedParam,
>>> strong_ordering __v) noexcept;
>>> +#endif
>>> +
>>> +private:
>>> +  _ValueT __value_;
>>> +};
>>> +
>>> +_LIBCPP_INLINE_VAR constexpr strong_ordering
>>> strong_ordering::less(_OrdResult::__less);
>>> +_LIBCPP_INLINE_VAR constexpr strong_ordering
>>> strong_ordering::equal(_EqResult::__equal);
>>> +_LIBCPP_INLINE_VAR constexpr strong_ordering
>>> strong_ordering::equivalent(_EqResult::__equiv);
>>> +_LIBCPP_INLINE_VAR constexpr strong_ordering
>>> strong_ordering::greater(_OrdResult::__greater);
>>> +
>>> +_LIBCPP_INLINE_VISIBILITY
>>> +constexpr bool operator==(strong_ordering __v, _CmpUnspecifiedParam)
>>> noexcept {
>>> +  return __v.__value_ == 0;
>>> +}
>>> +_LIBCPP_INLINE_VISIBILITY
>>> +constexpr bool operator!=(strong_ordering __v, _CmpUnspecifiedParam)
>>> noexcept {
>>> +  return __v.__value_ != 0;
>>> +}
>>> +_LIBCPP_INLINE_VISIBILITY
>>> +constexpr bool operator< (strong_ordering __v, _CmpUnspecifiedParam)
>>> noexcept {
>>> +  return __v.__value_ < 0;
>>> +}
>>> +_LIBCPP_INLINE_VISIBILITY
>>> +constexpr bool operator<=(strong_ordering __v, _CmpUnspecifiedParam)
>>> noexcept {
>>> +  return __v.__value_ <= 0;
>>> +}
>>> +_LIBCPP_INLINE_VISIBILITY
>>> +constexpr bool operator> (strong_ordering __v, _CmpUnspecifiedParam)
>>> noexcept {
>>> +  return __v.__value_ > 0;
>>> +}
>>> +_LIBCPP_INLINE_VISIBILITY
>>> +constexpr bool operator>=(strong_ordering __v, _CmpUnspecifiedParam)
>>> noexcept {
>>> +  return __v.__value_ >= 0;
>>> +}
>>> +_LIBCPP_INLINE_VISIBILITY
>>> +constexpr bool operator==(_CmpUnspecifiedParam, strong_ordering __v)
>>> noexcept {
>>> +  return 0 == __v.__value_;
>>> +}
>>> +_LIBCPP_INLINE_VISIBILITY
>>> +constexpr bool operator!=(_CmpUnspecifiedParam, strong_ordering __v)
>>> noexcept {
>>> +  return 0 != __v.__value_;
>>> +}
>>> +_LIBCPP_INLINE_VISIBILITY
>>> +constexpr bool operator< (_CmpUnspecifiedParam, strong_ordering __v)
>>> noexcept {
>>> +  return 0 < __v.__value_;
>>> +}
>>> +_LIBCPP_INLINE_VISIBILITY
>>> +constexpr bool operator<=(_CmpUnspecifiedParam, strong_ordering __v)
>>> noexcept {
>>> +  return 0 <= __v.__value_;
>>> +}
>>> +_LIBCPP_INLINE_VISIBILITY
>>> +constexpr bool operator> (_CmpUnspecifiedParam, strong_ordering __v)
>>> noexcept {
>>> +  return 0 > __v.__value_;
>>> +}
>>> +_LIBCPP_INLINE_VISIBILITY
>>> +constexpr bool operator>=(_CmpUnspecifiedParam, strong_ordering __v)
>>> noexcept {
>>> +  return 0 >= __v.__value_;
>>> +}
>>> +
>>> +#ifndef _LIBCPP_HAS_NO_SPACESHIP_OPERATOR
>>> +_LIBCPP_INLINE_VISIBILITY
>>> +constexpr strong_ordering operator<=>(strong_ordering __v,
>>> _CmpUnspecifiedParam) noexcept {
>>> +  return __v;
>>> +}
>>> +_LIBCPP_INLINE_VISIBILITY
>>> +constexpr strong_ordering operator<=>(_CmpUnspecifiedParam,
>>> strong_ordering __v) noexcept {
>>> +  return __v < 0 ? strong_ordering::greater : (__v > 0 ?
>>> strong_ordering::less : __v);
>>> +}
>>> +#endif // _LIBCPP_HAS_NO_SPACESHIP_OPERATOR
>>> +
>>> +// named comparison functions
>>> +_LIBCPP_INLINE_VISIBILITY
>>> +constexpr bool is_eq(weak_equality __cmp) noexcept    { return __cmp ==
>>> 0; }
>>> +
>>> +_LIBCPP_INLINE_VISIBILITY
>>> +constexpr bool is_neq(weak_equality __cmp) noexcept    { return __cmp
>>> != 0; }
>>> +
>>> +_LIBCPP_INLINE_VISIBILITY
>>> +constexpr bool is_lt(partial_ordering __cmp) noexcept { return __cmp <
>>> 0; }
>>> +
>>> +_LIBCPP_INLINE_VISIBILITY
>>> +constexpr bool is_lteq(partial_ordering __cmp) noexcept { return __cmp
>>> <= 0; }
>>> +
>>> +_LIBCPP_INLINE_VISIBILITY
>>> +constexpr bool is_gt(partial_ordering __cmp) noexcept { return __cmp >
>>> 0; }
>>> +
>>> +_LIBCPP_INLINE_VISIBILITY
>>> +constexpr bool is_gteq(partial_ordering __cmp) noexcept { return __cmp
>>> >= 0; }
>>> +
>>> +namespace __comp_detail {
>>> +
>>> +enum _ClassifyCompCategory : unsigned{
>>> +  _None,
>>> +  _WeakEq,
>>> +  _StrongEq,
>>> +  _PartialOrd,
>>> +  _WeakOrd,
>>> +  _StrongOrd,
>>> +  _CCC_Size
>>> +};
>>> +
>>> +template <class _Tp>
>>> +_LIBCPP_INLINE_VISIBILITY
>>> +constexpr _ClassifyCompCategory __type_to_enum() noexcept {
>>> +  if (is_same_v<_Tp, weak_equality>)
>>> +    return _WeakEq;
>>> +  if (is_same_v<_Tp, strong_equality>)
>>> +    return _StrongEq;
>>> +  if (is_same_v<_Tp, partial_ordering>)
>>> +    return _PartialOrd;
>>> +  if (is_same_v<_Tp, weak_ordering>)
>>> +    return _WeakOrd;
>>> +  if (is_same_v<_Tp, strong_ordering>)
>>> +    return _StrongOrd;
>>> +  return _None;
>>> +}
>>> +
>>> +template <size_t _Size>
>>> +constexpr _ClassifyCompCategory
>>> +__compute_comp_type(std::array<_ClassifyCompCategory, _Size> __types) {
>>> +  std::array<int, _CCC_Size> __seen = {};
>>> +  for (auto __type : __types)
>>> +    ++__seen[__type];
>>> +  if (__seen[_None])
>>> +    return _None;
>>> +  if (__seen[_WeakEq])
>>> +    return _WeakEq;
>>> +  if (__seen[_StrongEq] && (__seen[_PartialOrd] || __seen[_WeakOrd]))
>>> +    return _WeakEq;
>>> +  if (__seen[_StrongEq])
>>> +    return _StrongEq;
>>> +  if (__seen[_PartialOrd])
>>> +    return _PartialOrd;
>>> +  if (__seen[_WeakOrd])
>>> +    return _WeakOrd;
>>> +  return _StrongOrd;
>>> +}
>>>
>>
>> Hmm, it'd be nice to ask the compiler to work this out rather than
>> repeating the algorithm here. For example, something like:
>>
>> template<size_t, typename T> struct CCT { friend T operator<=>(const
>> CCT&, const CCT&); };
>> template<typename N, typename ...T> struct CCC;
>> template<size_t ...N, typename ...T> struct CCC : CCT<N, T>... {
>>   friend auto operator<=>(const CCC&, const CCC&) = default;
>> };
>> template<typename ...T> struct common_comparison_category {
>>   template<typename C> static auto test(int) -> decltype(declval<const
>> C&>() <=> declval<const C&>());
>>   template<typename C> static void test(...);
>>   using type = decltype(test<CCC<std::make_index_sequence<sizeof...(T)>,
>> T...>>(0));
>> }
>>
>> ... should allow you to ask the compiler for the common comparison type.
>>
>
> Looks good to me. Once we actually have a compiler I can do that with I'll
> make the change.
> For now I think it's preferable to have a working implementation.
>
> FYI, I have an almost complete implementation of [expr.spaceship].
>
> I was about to start making ExprConstant work, but I think that requires a
> new AST node to
> represent three-way comparisons. Since <=> builtins return a DeclRefExpr
> for the appropriate
> comparison category type member (ex. strong_equality::equal), and we can't
> build these
> in ExprConstant so it seems appropriate to build them earlier and store
> them in the
> operator expression node (I suspect this problem also arises during
> CodeGen).
>
> Does that seem reasonable?
>

My vague plan had been to add functionality to ASTConstant to look up (and
cache) those members, and query that from CodeGen and ExprConstant (and
also from Sema just as a validity check). I'd prefer not to store the same
list of members on all <=> nodes of the same type.

Have you thought at all about how to represent the rewritten forms of
operators using <=>?

+
>>> +template <class ..._Ts>
>>> +constexpr auto __get_comp_type() {
>>> +  using _CCC = _ClassifyCompCategory;
>>> +  constexpr array<_CCC, sizeof...(_Ts)>
>>> __type_kinds{__comp_detail::__type_to_enum<_Ts>()...};
>>> +  constexpr _CCC _Cat = sizeof...(_Ts) == 0 ? _StrongOrd
>>> +      : __compute_comp_type(__type_kinds);
>>> +  if constexpr (_Cat == _None)
>>> +    return ((void)0);
>>>
>>
>> void() is a more idiomatic way to write this. (Incidentally, this case
>> seems like a bug in the library spec to me --
>> common_comparison_category<...>::type should not exist in the case where
>> there is no common comparison type, for consistency with the other traits.)
>>
>
> I forgot about `void()`. Thanks.
>
> I'll look into the library spec tomorrow, and probably file an issue.
>
>
>>
>>
>>> +  else if constexpr (_Cat == _WeakEq)
>>> +    return weak_equality::equivalent;
>>> +  else if constexpr (_Cat == _StrongEq)
>>> +    return strong_equality::equivalent;
>>> +  else if constexpr (_Cat == _PartialOrd)
>>> +    return partial_ordering::equivalent;
>>> +  else if constexpr (_Cat == _WeakOrd)
>>> +    return weak_ordering::equivalent;
>>> +  else if constexpr (_Cat == _StrongOrd)
>>> +    return strong_ordering::equivalent;
>>> +  else
>>> +    static_assert(_Cat != _Cat, "unhandled case");
>>> +}
>>> +} // namespace __comp_detail
>>> +
>>> +// [cmp.common], common comparison category type
>>> +template<class... _Ts>
>>> +struct _LIBCPP_TEMPLATE_VIS common_comparison_category {
>>> +  using type = decltype(__comp_detail::__get_comp_type<_Ts...>());
>>> +};
>>> +
>>> +template<class... _Ts>
>>> +using common_comparison_category_t = typename
>>> common_comparison_category<_Ts...>::type;
>>> +
>>> +// [cmp.alg], comparison algorithms
>>> +// TODO: unimplemented
>>> +template<class _Tp> constexpr strong_ordering strong_order(const _Tp&
>>> __lhs, const _Tp& __rhs);
>>> +template<class _Tp> constexpr weak_ordering weak_order(const _Tp&
>>> __lhs, const _Tp& __rhs);
>>> +template<class _Tp> constexpr partial_ordering partial_order(const _Tp&
>>> __lhs, const _Tp& __rhs);
>>> +template<class _Tp> constexpr strong_equality strong_equal(const _Tp&
>>> __lhs, const _Tp& __rhs);
>>> +template<class _Tp> constexpr weak_equality weak_equal(const _Tp&
>>> __lhs, const _Tp& __rhs);
>>> +
>>> +#endif // _LIBCPP_STD_VER > 17
>>> +
>>> +_LIBCPP_END_NAMESPACE_STD
>>> +
>>> +#endif // _LIBCPP_COMPARE
>>>
>>> Modified: libcxx/trunk/include/module.modulemap
>>> URL:
>>> http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/module.modulemap?rev=329460&r1=329459&r2=329460&view=diff
>>>
>>> ==============================================================================
>>> --- libcxx/trunk/include/module.modulemap (original)
>>> +++ libcxx/trunk/include/module.modulemap Fri Apr  6 14:37:23 2018
>>> @@ -243,6 +243,10 @@ module std [system] {
>>>      header "codecvt"
>>>      export *
>>>    }
>>> +  module compare {
>>> +    header "compare"
>>> +    export *
>>> +  }
>>>    module complex {
>>>      header "complex"
>>>      export *
>>>
>>> Modified: libcxx/trunk/test/libcxx/double_include.sh.cpp
>>> URL:
>>> http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/libcxx/double_include.sh.cpp?rev=329460&r1=329459&r2=329460&view=diff
>>>
>>> ==============================================================================
>>> --- libcxx/trunk/test/libcxx/double_include.sh.cpp (original)
>>> +++ libcxx/trunk/test/libcxx/double_include.sh.cpp Fri Apr  6 14:37:23
>>> 2018
>>> @@ -41,6 +41,7 @@
>>>  #include <clocale>
>>>  #include <cmath>
>>>  #include <codecvt>
>>> +#include <compare>
>>>  #include <complex>
>>>  #include <complex.h>
>>>  #include <condition_variable>
>>>
>>> Added: libcxx/trunk/test/libcxx/language.support/cmp/version.pass.cpp
>>> URL:
>>> http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/libcxx/language.support/cmp/version.pass.cpp?rev=329460&view=auto
>>>
>>> ==============================================================================
>>> --- libcxx/trunk/test/libcxx/language.support/cmp/version.pass.cpp
>>> (added)
>>> +++ libcxx/trunk/test/libcxx/language.support/cmp/version.pass.cpp Fri
>>> Apr  6 14:37:23 2018
>>> @@ -0,0 +1,20 @@
>>>
>>> +//===----------------------------------------------------------------------===//
>>> +//
>>> +//                     The LLVM Compiler Infrastructure
>>> +//
>>> +// This file is dual licensed under the MIT and the University of
>>> Illinois Open
>>> +// Source Licenses. See LICENSE.TXT for details.
>>> +//
>>>
>>> +//===----------------------------------------------------------------------===//
>>> +
>>> +// <compare>
>>> +
>>> +#include <compare>
>>> +
>>> +#ifndef _LIBCPP_VERSION
>>> +#error _LIBCPP_VERSION not defined
>>> +#endif
>>> +
>>> +int main()
>>> +{
>>> +}
>>>
>>> Added:
>>> libcxx/trunk/test/std/language.support/cmp/cmp.common/common_comparison_category.pass.cpp
>>> URL:
>>> http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/language.support/cmp/cmp.common/common_comparison_category.pass.cpp?rev=329460&view=auto
>>>
>>> ==============================================================================
>>> ---
>>> libcxx/trunk/test/std/language.support/cmp/cmp.common/common_comparison_category.pass.cpp
>>> (added)
>>> +++
>>> libcxx/trunk/test/std/language.support/cmp/cmp.common/common_comparison_category.pass.cpp
>>> Fri Apr  6 14:37:23 2018
>>> @@ -0,0 +1,93 @@
>>>
>>> +//===----------------------------------------------------------------------===//
>>> +//
>>> +//                     The LLVM Compiler Infrastructure
>>> +//
>>> +// This file is dual licensed under the MIT and the University of
>>> Illinois Open
>>> +// Source Licenses. See LICENSE.TXT for details.
>>> +//
>>>
>>> +//===----------------------------------------------------------------------===//
>>> +
>>> +// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17
>>> +
>>> +// <compare>
>>> +
>>> +// template <class ...Ts> struct common_comparison_category
>>> +// template <class ...Ts> using common_comparison_category_t
>>> +
>>> +
>>> +#include <compare>
>>> +#include <type_traits>
>>> +#include <cassert>
>>> +
>>> +#include "test_macros.h"
>>> +
>>> +const volatile void* volatile sink;
>>> +
>>> +template <class Expect, class ...Args>
>>> +void test_cat() {
>>> +  using Cat = std::common_comparison_category<Args...>;
>>> +  using CatT = typename Cat::type;
>>> +  static_assert(std::is_same<CatT,
>>> std::common_comparison_category_t<Args...>>::value, "");
>>> +  static_assert(std::is_same<CatT, Expect>::value, "expected different
>>> category");
>>> +};
>>> +
>>> +
>>> +// [class.spaceship]p4: The 'common comparison type' U of a
>>> possibly-empty list
>>> +//   of 'n' types T0, T1, ..., TN, is defined as follows:
>>> +int main() {
>>> +  using WE = std::weak_equality;
>>> +  using SE = std::strong_equality;
>>> +  using PO = std::partial_ordering;
>>> +  using WO = std::weak_ordering;
>>> +  using SO = std::strong_ordering;
>>> +
>>> +  // [class.spaceship]p4.1: If any Ti is not a comparison category tpe,
>>> U is void.
>>> +  {
>>> +    test_cat<void, void>();
>>> +    test_cat<void, int*>();
>>> +    test_cat<void, SO&>();
>>> +    test_cat<void, SO const>();
>>> +    test_cat<void, SO*>();
>>> +    test_cat<void, SO, void, SO>();
>>> +  }
>>> +
>>> +  // [class.spaceship]p4.2: Otherwise, if at least on Ti is
>>> +  // std::weak_equality, or at least one Ti is std::strong_equality and
>>> at least
>>> +  // one Tj is std::partial_ordering or std::weak_ordering, U is
>>> std::weak_equality
>>> +  {
>>> +    test_cat<WE, WE>();
>>> +    test_cat<WE, SO, WE, SO>();
>>> +    test_cat<WE, SE, SO, PO>();
>>> +    test_cat<WE, WO, SO, SE>();
>>> +  }
>>> +
>>> +  // [class.spaceship]p4.3: Otherwise, if at least one Ti is
>>> std::strong_equality,
>>> +  // U is std::strong_equality
>>> +  {
>>> +    test_cat<SE, SE>();
>>> +    test_cat<SE, SO, SE, SO>();
>>> +  }
>>> +
>>> +  // [class.spaceship]p4.4: Otherwise, if at least one Ti is
>>> std::partial_ordering,
>>> +  // U is std::partial_ordering
>>> +  {
>>> +    test_cat<PO, PO>();
>>> +    test_cat<PO, SO, PO, SO>();
>>> +    test_cat<PO, WO, PO, SO>();
>>> +  }
>>> +
>>> +  // [class.spaceship]p4.5: Otherwise, if at least one Ti is
>>> std::weak_ordering,
>>> +  // U is std::weak_ordering
>>> +  {
>>> +    test_cat<WO, WO>();
>>> +    test_cat<WO, SO, WO, SO>();
>>> +  }
>>> +
>>> +  // [class.spaceship]p4.6: Otherwise, U is std::strong_ordering.
>>> [Note: in
>>> +  // particular this is the result when n is 0. -- end note]
>>> +  {
>>> +    test_cat<SO>(); // empty type list
>>> +    test_cat<SO, SO>();
>>> +    test_cat<SO, SO, SO>();
>>> +  }
>>> +}
>>>
>>> Added:
>>> libcxx/trunk/test/std/language.support/cmp/cmp.partialord/partialord.pass.cpp
>>> URL:
>>> http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/language.support/cmp/cmp.partialord/partialord.pass.cpp?rev=329460&view=auto
>>>
>>> ==============================================================================
>>> ---
>>> libcxx/trunk/test/std/language.support/cmp/cmp.partialord/partialord.pass.cpp
>>> (added)
>>> +++
>>> libcxx/trunk/test/std/language.support/cmp/cmp.partialord/partialord.pass.cpp
>>> Fri Apr  6 14:37:23 2018
>>> @@ -0,0 +1,164 @@
>>>
>>> +//===----------------------------------------------------------------------===//
>>> +//
>>> +//                     The LLVM Compiler Infrastructure
>>> +//
>>> +// This file is dual licensed under the MIT and the University of
>>> Illinois Open
>>> +// Source Licenses. See LICENSE.TXT for details.
>>> +//
>>>
>>> +//===----------------------------------------------------------------------===//
>>> +
>>> +// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17
>>> +
>>> +// <compare>
>>> +
>>> +// class partial_ordering
>>> +
>>> +
>>> +#include <compare>
>>> +#include <type_traits>
>>> +#include <cassert>
>>> +
>>> +#include "test_macros.h"
>>> +
>>> +const volatile void* volatile sink;
>>> +
>>> +void test_static_members() {
>>> +  DoNotOptimize(&std::partial_ordering::less);
>>> +  DoNotOptimize(&std::partial_ordering::equivalent);
>>> +  DoNotOptimize(&std::partial_ordering::greater);
>>> +  DoNotOptimize(&std::partial_ordering::unordered);
>>> +}
>>> +
>>> +void test_signatures() {
>>> +  auto& Eq = std::partial_ordering::equivalent;
>>> +
>>> +  ASSERT_NOEXCEPT(Eq == 0);
>>> +  ASSERT_NOEXCEPT(0 == Eq);
>>> +  ASSERT_NOEXCEPT(Eq != 0);
>>> +  ASSERT_NOEXCEPT(0 != Eq);
>>> +  ASSERT_NOEXCEPT(0 < Eq);
>>> +  ASSERT_NOEXCEPT(Eq < 0);
>>> +  ASSERT_NOEXCEPT(0 <= Eq);
>>> +  ASSERT_NOEXCEPT(Eq <= 0);
>>> +  ASSERT_NOEXCEPT(0 > Eq);
>>> +  ASSERT_NOEXCEPT(Eq > 0);
>>> +  ASSERT_NOEXCEPT(0 >= Eq);
>>> +  ASSERT_NOEXCEPT(Eq >= 0);
>>> +#ifndef TEST_HAS_NO_SPACESHIP_OPERATOR
>>> +  ASSERT_NOEXCEPT(0 <=> Eq);
>>> +  ASSERT_NOEXCEPT(Eq <=> 0);
>>> +  ASSERT_SAME_TYPE(decltype(Eq <=> 0), std::partial_ordering);
>>> +  ASSERT_SAME_TYPE(decltype(0 <=> Eq), std::partial_ordering);
>>> +#endif
>>> +}
>>> +
>>> +constexpr bool test_conversion() {
>>> +  static_assert(std::is_convertible<const std::partial_ordering,
>>> std::weak_equality>::value, "");
>>> +  { // value == 0
>>> +    auto V = std::partial_ordering::equivalent;
>>> +    std::weak_equality WV = V;
>>> +    assert(WV == 0);
>>> +  }
>>> +  std::partial_ordering TestCases[] = {
>>> +      std::partial_ordering::less,
>>> +      std::partial_ordering::greater,
>>> +      std::partial_ordering::unordered
>>> +  };
>>> +  for (auto V : TestCases)
>>> +  { // value != 0
>>> +    std::weak_equality WV = V;
>>> +    assert(WV != 0);
>>> +  }
>>> +  return true;
>>> +}
>>> +
>>> +constexpr bool test_constexpr() {
>>> +  auto& Eq = std::partial_ordering::equivalent;
>>> +  auto& Less = std::partial_ordering::less;
>>> +  auto& Greater = std::partial_ordering::greater;
>>> +  auto& Unord = std::partial_ordering::unordered;
>>> +  struct {
>>> +    std::partial_ordering Value;
>>> +    bool ExpectEq;
>>> +    bool ExpectNeq;
>>> +    bool ExpectLess;
>>> +    bool ExpectGreater;
>>> +  } TestCases[] = {
>>> +      {Eq, true, false, false, false},
>>> +      {Less, false, true, true, false},
>>> +      {Greater, false, true, false, true},
>>> +      {Unord, false, true, false, false}
>>> +  };
>>> +  for (auto TC : TestCases) {
>>> +    auto V = TC.Value;
>>> +    assert((V == 0) == TC.ExpectEq);
>>> +    assert((0 == V) == TC.ExpectEq);
>>> +    assert((V != 0) == TC.ExpectNeq);
>>> +    assert((0 != V) == TC.ExpectNeq);
>>> +
>>> +    assert((V < 0) == TC.ExpectLess);
>>> +    assert((V > 0) == TC.ExpectGreater);
>>> +    assert((V <= 0) == (TC.ExpectLess || TC.ExpectEq));
>>> +    assert((V >= 0) == (TC.ExpectGreater || TC.ExpectEq));
>>> +
>>> +    assert((0 < V) == TC.ExpectGreater);
>>> +    assert((0 > V) == TC.ExpectLess);
>>> +    assert((0 <= V) == (TC.ExpectGreater || TC.ExpectEq));
>>> +    assert((0 >= V) == (TC.ExpectLess || TC.ExpectEq));
>>> +  }
>>> +#ifndef TEST_HAS_NO_SPACESHIP_OPERATOR
>>> +  {
>>> +    std::partial_ordering res = (Eq <=> 0);
>>> +    ((void)res);
>>> +    res = (0 <=> Eq);
>>> +    ((void)res);
>>> +  }
>>> +  enum ExpectRes {
>>> +    ER_Greater,
>>> +    ER_Less,
>>> +    ER_Equiv,
>>> +    ER_Unord
>>> +  };
>>> +  struct {
>>> +    std::partial_ordering Value;
>>> +    ExpectRes Expect;
>>> +  } SpaceshipTestCases[] = {
>>> +      {std::partial_ordering::equivalent, ER_Equiv},
>>> +      {std::partial_ordering::less, ER_Less},
>>> +      {std::partial_ordering::greater, ER_Greater},
>>> +      {std::partial_ordering::unordered, ER_Unord}
>>> +  };
>>> +  for (auto TC : SpaceshipTestCases)
>>> +  {
>>> +    std::partial_ordering Res = (0 <=> TC.Value);
>>> +    switch (TC.Expect) {
>>> +    case ER_Equiv:
>>> +      assert(Res == 0);
>>> +      assert(0 == Res);
>>> +      break;
>>> +    case ER_Less:
>>> +      assert(Res < 0);
>>> +      break;
>>> +    case ER_Greater:
>>> +      assert(Res > 0);
>>> +      break;
>>> +    case ER_Unord:
>>> +      assert(Res != 0);
>>> +      assert(0 != Res);
>>> +      assert((Res < 0) == false);
>>> +      assert((Res > 0) == false);
>>> +      assert((Res == 0) == false);
>>> +      break;
>>> +    }
>>> +  }
>>> +#endif
>>> +
>>> +  return true;
>>> +}
>>> +
>>> +int main() {
>>> +  test_static_members();
>>> +  test_signatures();
>>> +  static_assert(test_conversion(), "conversion test failed");
>>> +  static_assert(test_constexpr(), "constexpr test failed");
>>> +}
>>>
>>> Added:
>>> libcxx/trunk/test/std/language.support/cmp/cmp.strongeq/cmp.strongeq.pass.cpp
>>> URL:
>>> http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/language.support/cmp/cmp.strongeq/cmp.strongeq.pass.cpp?rev=329460&view=auto
>>>
>>> ==============================================================================
>>> ---
>>> libcxx/trunk/test/std/language.support/cmp/cmp.strongeq/cmp.strongeq.pass.cpp
>>> (added)
>>> +++
>>> libcxx/trunk/test/std/language.support/cmp/cmp.strongeq/cmp.strongeq.pass.cpp
>>> Fri Apr  6 14:37:23 2018
>>> @@ -0,0 +1,96 @@
>>>
>>> +//===----------------------------------------------------------------------===//
>>> +//
>>> +//                     The LLVM Compiler Infrastructure
>>> +//
>>> +// This file is dual licensed under the MIT and the University of
>>> Illinois Open
>>> +// Source Licenses. See LICENSE.TXT for details.
>>> +//
>>>
>>> +//===----------------------------------------------------------------------===//
>>> +
>>> +// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17
>>> +
>>> +// <compare>
>>> +
>>> +// class strong_equality
>>> +
>>> +
>>> +#include <compare>
>>> +#include <type_traits>
>>> +#include <cassert>
>>> +
>>> +#include "test_macros.h"
>>> +
>>> +const volatile void* volatile sink;
>>> +
>>> +void test_static_members() {
>>> +  DoNotOptimize(&std::strong_equality::equal);
>>> +  DoNotOptimize(&std::strong_equality::nonequal);
>>> +  DoNotOptimize(&std::strong_equality::equivalent);
>>> +  DoNotOptimize(&std::strong_equality::nonequivalent);
>>> +}
>>> +
>>> +void test_signatures() {
>>> +  auto& Eq = std::strong_equality::equivalent;
>>> +
>>> +  ASSERT_NOEXCEPT(Eq == 0);
>>> +  ASSERT_NOEXCEPT(0 == Eq);
>>> +  ASSERT_NOEXCEPT(Eq != 0);
>>> +  ASSERT_NOEXCEPT(0 != Eq);
>>> +#ifndef TEST_HAS_NO_SPACESHIP_OPERATOR
>>> +  ASSERT_NOEXCEPT(0 <=> Eq);
>>> +  ASSERT_NOEXCEPT(Eq <=> 0);
>>> +  ASSERT_SAME_TYPE(decltype(Eq <=> 0), std::strong_equality);
>>> +  ASSERT_SAME_TYPE(decltype(0 <=> Eq), std::strong_equality);
>>> +#endif
>>> +}
>>> +
>>> +void test_conversion() {
>>> +  constexpr std::weak_equality res = std::strong_equality::equivalent;
>>> +  static_assert(res == 0, "");
>>> +  static_assert(std::is_convertible<const std::strong_equality&,
>>> +      std::weak_equality>::value, "");
>>> +  static_assert(res == 0, "expected equal");
>>> +
>>> +  constexpr std::weak_equality neq_res =
>>> std::strong_equality::nonequivalent;
>>> +  static_assert(neq_res != 0, "expected not equal");
>>> +}
>>> +
>>> +constexpr bool test_constexpr() {
>>> +  auto& Eq = std::strong_equality::equal;
>>> +  auto& NEq = std::strong_equality::nonequal;
>>> +  auto& Equiv = std::strong_equality::equivalent;
>>> +  auto& NEquiv = std::strong_equality::nonequivalent;
>>> +  assert((Eq == 0) == true);
>>> +  assert((0 == Eq) == true);
>>> +  assert((Equiv == 0) == true);
>>> +  assert((0 == Equiv) == true);
>>> +  assert((NEq == 0) == false);
>>> +  assert((0 == NEq) == false);
>>> +  assert((NEquiv == 0) == false);
>>> +  assert((0 == NEquiv) == false);
>>> +
>>> +  assert((Eq != 0) == false);
>>> +  assert((0 != Eq) == false);
>>> +  assert((Equiv != 0) == false);
>>> +  assert((0 != Equiv) == false);
>>> +  assert((NEq != 0) == true);
>>> +  assert((0 != NEq) == true);
>>> +  assert((NEquiv != 0) == true);
>>> +  assert((0 != NEquiv) == true);
>>> +
>>> +#ifndef TEST_HAS_NO_SPACESHIP_OPERATOR
>>> +  std::strong_equality res = (Eq <=> 0);
>>> +  ((void)res);
>>> +  res = (0 <=> Eq);
>>> +  ((void)res);
>>> +#endif
>>> +
>>> +  return true;
>>> +}
>>> +
>>> +int main() {
>>> +  test_static_members();
>>> +  test_signatures();
>>> +  test_conversion();
>>> +  static_assert(test_constexpr(), "constexpr test failed");
>>> +}
>>>
>>> Added:
>>> libcxx/trunk/test/std/language.support/cmp/cmp.strongord/strongord.pass.cpp
>>> URL:
>>> http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/language.support/cmp/cmp.strongord/strongord.pass.cpp?rev=329460&view=auto
>>>
>>> ==============================================================================
>>> ---
>>> libcxx/trunk/test/std/language.support/cmp/cmp.strongord/strongord.pass.cpp
>>> (added)
>>> +++
>>> libcxx/trunk/test/std/language.support/cmp/cmp.strongord/strongord.pass.cpp
>>> Fri Apr  6 14:37:23 2018
>>> @@ -0,0 +1,212 @@
>>>
>>> +//===----------------------------------------------------------------------===//
>>> +//
>>> +//                     The LLVM Compiler Infrastructure
>>> +//
>>> +// This file is dual licensed under the MIT and the University of
>>> Illinois Open
>>> +// Source Licenses. See LICENSE.TXT for details.
>>> +//
>>>
>>> +//===----------------------------------------------------------------------===//
>>> +
>>> +// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17
>>> +
>>> +// <compare>
>>> +
>>> +// class strong_ordering
>>> +
>>> +
>>> +#include <compare>
>>> +#include <type_traits>
>>> +#include <cassert>
>>> +
>>> +#include "test_macros.h"
>>> +
>>> +const volatile void* volatile sink;
>>> +
>>> +void test_static_members() {
>>> +  DoNotOptimize(&std::strong_ordering::less);
>>> +  DoNotOptimize(&std::strong_ordering::equal);
>>> +  DoNotOptimize(&std::strong_ordering::equivalent);
>>> +  DoNotOptimize(&std::strong_ordering::greater);
>>> +}
>>> +
>>> +void test_signatures() {
>>> +  auto& Eq = std::strong_ordering::equivalent;
>>> +
>>> +  ASSERT_NOEXCEPT(Eq == 0);
>>> +  ASSERT_NOEXCEPT(0 == Eq);
>>> +  ASSERT_NOEXCEPT(Eq != 0);
>>> +  ASSERT_NOEXCEPT(0 != Eq);
>>> +  ASSERT_NOEXCEPT(0 < Eq);
>>> +  ASSERT_NOEXCEPT(Eq < 0);
>>> +  ASSERT_NOEXCEPT(0 <= Eq);
>>> +  ASSERT_NOEXCEPT(Eq <= 0);
>>> +  ASSERT_NOEXCEPT(0 > Eq);
>>> +  ASSERT_NOEXCEPT(Eq > 0);
>>> +  ASSERT_NOEXCEPT(0 >= Eq);
>>> +  ASSERT_NOEXCEPT(Eq >= 0);
>>> +#ifndef TEST_HAS_NO_SPACESHIP_OPERATOR
>>> +  ASSERT_NOEXCEPT(0 <=> Eq);
>>> +  ASSERT_NOEXCEPT(Eq <=> 0);
>>> +  ASSERT_SAME_TYPE(decltype(Eq <=> 0), std::strong_ordering);
>>> +  ASSERT_SAME_TYPE(decltype(0 <=> Eq), std::strong_ordering);
>>> +#endif
>>> +}
>>> +
>>> +constexpr bool test_conversion() {
>>> +  static_assert(std::is_convertible<const std::strong_ordering&,
>>> +      std::weak_equality>::value, "");
>>> +  { // value == 0
>>> +    auto V = std::strong_ordering::equivalent;
>>> +    std::weak_equality WV = V;
>>> +    assert(WV == 0);
>>> +  }
>>> +  std::strong_ordering WeakTestCases[] = {
>>> +      std::strong_ordering::less,
>>> +      std::strong_ordering::greater,
>>> +  };
>>> +  for (auto V : WeakTestCases)
>>> +  { // value != 0
>>> +    std::weak_equality WV = V;
>>> +    assert(WV != 0);
>>> +  }
>>> +  static_assert(std::is_convertible<const std::strong_ordering&,
>>> +      std::strong_equality>::value, "");
>>> +  { // value == 0
>>> +    auto V = std::strong_ordering::equivalent;
>>> +    std::strong_equality WV = V;
>>> +    assert(WV == 0);
>>> +  }
>>> +  { // value == 0
>>> +    auto V = std::strong_ordering::equal;
>>> +    std::strong_equality WV = V;
>>> +    assert(WV == 0);
>>> +  }
>>> +  std::strong_ordering StrongTestCases[] = {
>>> +      std::strong_ordering::less,
>>> +      std::strong_ordering::greater,
>>> +  };
>>> +  for (auto V : StrongTestCases)
>>> +  { // value != 0
>>> +    std::strong_equality WV = V;
>>> +    assert(WV != 0);
>>> +  }
>>> +
>>> +  static_assert(std::is_convertible<const std::strong_ordering&,
>>> +      std::partial_ordering>::value, "");
>>> +  { // value == 0
>>> +    auto V = std::strong_ordering::equivalent;
>>> +    std::partial_ordering WV = V;
>>> +    assert(WV == 0);
>>> +  }
>>> +  { // value < 0
>>> +    auto V = std::strong_ordering::less;
>>> +    std::partial_ordering WV = V;
>>> +    assert(WV < 0);
>>> +  }
>>> +  { // value > 0
>>> +    auto V = std::strong_ordering::greater;
>>> +    std::partial_ordering WV = V;
>>> +    assert(WV > 0);
>>> +  }
>>> +
>>> +  static_assert(std::is_convertible<const std::strong_ordering&,
>>> +      std::weak_ordering>::value, "");
>>> +  { // value == 0
>>> +    auto V = std::strong_ordering::equivalent;
>>> +    std::weak_ordering WV = V;
>>> +    assert(WV == 0);
>>> +  }
>>> +  { // value < 0
>>> +    auto V = std::strong_ordering::less;
>>> +    std::weak_ordering WV = V;
>>> +    assert(WV < 0);
>>> +  }
>>> +  { // value > 0
>>> +    auto V = std::strong_ordering::greater;
>>> +    std::weak_ordering WV = V;
>>> +    assert(WV > 0);
>>> +  }
>>> +  return true;
>>> +}
>>> +
>>> +constexpr bool test_constexpr() {
>>> +  auto& Eq = std::strong_ordering::equal;
>>> +  auto& Equiv = std::strong_ordering::equivalent;
>>> +  auto& Less = std::strong_ordering::less;
>>> +  auto& Greater = std::strong_ordering::greater;
>>> +  struct {
>>> +    std::strong_ordering Value;
>>> +    bool ExpectEq;
>>> +    bool ExpectNeq;
>>> +    bool ExpectLess;
>>> +    bool ExpectGreater;
>>> +  } TestCases[] = {
>>> +      {Eq, true, false, false, false},
>>> +      {Equiv, true, false, false, false},
>>> +      {Less, false, true, true, false},
>>> +      {Greater, false, true, false, true},
>>> +  };
>>> +  for (auto TC : TestCases) {
>>> +    auto V = TC.Value;
>>> +    assert((V == 0) == TC.ExpectEq);
>>> +    assert((0 == V) == TC.ExpectEq);
>>> +    assert((V != 0) == TC.ExpectNeq);
>>> +    assert((0 != V) == TC.ExpectNeq);
>>> +
>>> +    assert((V < 0) == TC.ExpectLess);
>>> +    assert((V > 0) == TC.ExpectGreater);
>>> +    assert((V <= 0) == (TC.ExpectLess || TC.ExpectEq));
>>> +    assert((V >= 0) == (TC.ExpectGreater || TC.ExpectEq));
>>> +
>>> +    assert((0 < V) == TC.ExpectGreater);
>>> +    assert((0 > V) == TC.ExpectLess);
>>> +    assert((0 <= V) == (TC.ExpectGreater || TC.ExpectEq));
>>> +    assert((0 >= V) == (TC.ExpectLess || TC.ExpectEq));
>>> +  }
>>> +#ifndef TEST_HAS_NO_SPACESHIP_OPERATOR
>>> +  {
>>> +    std::strong_ordering res = (Eq <=> 0);
>>> +    ((void)res);
>>> +    res = (0 <=> Eq);
>>> +    ((void)res);
>>> +  }
>>> +  enum ExpectRes {
>>> +    ER_Greater,
>>> +    ER_Less,
>>> +    ER_Equiv
>>> +  };
>>> +  struct {
>>> +    std::strong_ordering Value;
>>> +    ExpectRes Expect;
>>> +  } SpaceshipTestCases[] = {
>>> +      {std::strong_ordering::equivalent, ER_Equiv},
>>> +      {std::strong_ordering::less, ER_Less},
>>> +      {std::strong_ordering::greater, ER_Greater},
>>> +  };
>>> +  for (auto TC : SpaceshipTestCases)
>>> +  {
>>> +    std::strong_ordering Res = (0 <=> TC.Value);
>>> +    switch (TC.Expect) {
>>> +    case ER_Equiv:
>>> +      assert(Res == 0);
>>> +      assert(0 == Res);
>>> +      break;
>>> +    case ER_Less:
>>> +      assert(Res < 0);
>>> +      break;
>>> +    case ER_Greater:
>>> +      assert(Res > 0);
>>> +      break;
>>> +    }
>>> +  }
>>> +#endif
>>> +
>>> +  return true;
>>> +}
>>> +
>>> +int main() {
>>> +  test_static_members();
>>> +  test_signatures();
>>> +  static_assert(test_conversion(), "conversion test failed");
>>> +  static_assert(test_constexpr(), "constexpr test failed");
>>> +}
>>>
>>> Added:
>>> libcxx/trunk/test/std/language.support/cmp/cmp.weakeq/cmp.weakeq.pass.cpp
>>> URL:
>>> http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/language.support/cmp/cmp.weakeq/cmp.weakeq.pass.cpp?rev=329460&view=auto
>>>
>>> ==============================================================================
>>> ---
>>> libcxx/trunk/test/std/language.support/cmp/cmp.weakeq/cmp.weakeq.pass.cpp
>>> (added)
>>> +++
>>> libcxx/trunk/test/std/language.support/cmp/cmp.weakeq/cmp.weakeq.pass.cpp
>>> Fri Apr  6 14:37:23 2018
>>> @@ -0,0 +1,70 @@
>>>
>>> +//===----------------------------------------------------------------------===//
>>> +//
>>> +//                     The LLVM Compiler Infrastructure
>>> +//
>>> +// This file is dual licensed under the MIT and the University of
>>> Illinois Open
>>> +// Source Licenses. See LICENSE.TXT for details.
>>> +//
>>>
>>> +//===----------------------------------------------------------------------===//
>>> +
>>> +// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17
>>> +
>>> +// <compare>
>>> +
>>> +// class weak_equality
>>> +
>>> +
>>> +#include <compare>
>>> +#include <cassert>
>>> +#include "test_macros.h"
>>> +
>>> +const volatile void* volatile sink;
>>> +
>>> +void test_static_members() {
>>> +  DoNotOptimize(&std::weak_equality::equivalent);
>>> +  DoNotOptimize(&std::weak_equality::nonequivalent);
>>> +}
>>> +
>>> +void test_signatures() {
>>> +  auto& Eq = std::weak_equality::equivalent;
>>> +
>>> +  ASSERT_NOEXCEPT(Eq == 0);
>>> +  ASSERT_NOEXCEPT(0 == Eq);
>>> +  ASSERT_NOEXCEPT(Eq != 0);
>>> +  ASSERT_NOEXCEPT(0 != Eq);
>>> +#ifndef TEST_HAS_NO_SPACESHIP_OPERATOR
>>> +  ASSERT_NOEXCEPT(0 <=> Eq);
>>> +  ASSERT_NOEXCEPT(Eq <=> 0);
>>> +  ASSERT_SAME_TYPE(decltype(Eq <=> 0), std::weak_equality);
>>> +  ASSERT_SAME_TYPE(decltype(0 <=> Eq), std::weak_equality);
>>> +#endif
>>> +}
>>> +
>>> +constexpr bool test_constexpr() {
>>> +  auto& Eq = std::weak_equality::equivalent;
>>> +  auto& NEq = std::weak_equality::nonequivalent;
>>> +  assert((Eq == 0) == true);
>>> +  assert((0 == Eq) == true);
>>> +  assert((NEq == 0) == false);
>>> +  assert((0 == NEq) == false);
>>> +
>>> +  assert((Eq != 0) == false);
>>> +  assert((0 != Eq) == false);
>>> +  assert((NEq != 0) == true);
>>> +  assert((0 != NEq) == true);
>>> +
>>> +#ifndef TEST_HAS_NO_SPACESHIP_OPERATOR
>>> +  std::weak_equality res = (Eq <=> 0);
>>> +  ((void)res);
>>> +  res = (0 <=> Eq);
>>> +  ((void)res);
>>> +#endif
>>> +
>>> +  return true;
>>> +}
>>> +
>>> +int main() {
>>> +  test_static_members();
>>> +  test_signatures();
>>> +  static_assert(test_constexpr(), "constexpr test failed");
>>> +}
>>>
>>> Added:
>>> libcxx/trunk/test/std/language.support/cmp/cmp.weakord/weakord.pass.cpp
>>> URL:
>>> http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/language.support/cmp/cmp.weakord/weakord.pass.cpp?rev=329460&view=auto
>>>
>>> ==============================================================================
>>> ---
>>> libcxx/trunk/test/std/language.support/cmp/cmp.weakord/weakord.pass.cpp
>>> (added)
>>> +++
>>> libcxx/trunk/test/std/language.support/cmp/cmp.weakord/weakord.pass.cpp Fri
>>> Apr  6 14:37:23 2018
>>> @@ -0,0 +1,169 @@
>>>
>>> +//===----------------------------------------------------------------------===//
>>> +//
>>> +//                     The LLVM Compiler Infrastructure
>>> +//
>>> +// This file is dual licensed under the MIT and the University of
>>> Illinois Open
>>> +// Source Licenses. See LICENSE.TXT for details.
>>> +//
>>>
>>> +//===----------------------------------------------------------------------===//
>>> +
>>> +// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17
>>> +
>>> +// <compare>
>>> +
>>> +// class weak_ordering
>>> +
>>> +
>>> +#include <compare>
>>> +#include <type_traits>
>>> +#include <cassert>
>>> +
>>> +#include "test_macros.h"
>>> +
>>> +const volatile void* volatile sink;
>>> +
>>> +void test_static_members() {
>>> +  DoNotOptimize(&std::weak_ordering::less);
>>> +  DoNotOptimize(&std::weak_ordering::equivalent);
>>> +  DoNotOptimize(&std::weak_ordering::greater);
>>> +}
>>> +
>>> +void test_signatures() {
>>> +  auto& Eq = std::weak_ordering::equivalent;
>>> +
>>> +  ASSERT_NOEXCEPT(Eq == 0);
>>> +  ASSERT_NOEXCEPT(0 == Eq);
>>> +  ASSERT_NOEXCEPT(Eq != 0);
>>> +  ASSERT_NOEXCEPT(0 != Eq);
>>> +  ASSERT_NOEXCEPT(0 < Eq);
>>> +  ASSERT_NOEXCEPT(Eq < 0);
>>> +  ASSERT_NOEXCEPT(0 <= Eq);
>>> +  ASSERT_NOEXCEPT(Eq <= 0);
>>> +  ASSERT_NOEXCEPT(0 > Eq);
>>> +  ASSERT_NOEXCEPT(Eq > 0);
>>> +  ASSERT_NOEXCEPT(0 >= Eq);
>>> +  ASSERT_NOEXCEPT(Eq >= 0);
>>> +#ifndef TEST_HAS_NO_SPACESHIP_OPERATOR
>>> +  ASSERT_NOEXCEPT(0 <=> Eq);
>>> +  ASSERT_NOEXCEPT(Eq <=> 0);
>>> +  ASSERT_SAME_TYPE(decltype(Eq <=> 0), std::weak_ordering);
>>> +  ASSERT_SAME_TYPE(decltype(0 <=> Eq), std::weak_ordering);
>>> +#endif
>>> +}
>>> +
>>> +constexpr bool test_conversion() {
>>> +  static_assert(std::is_convertible<const std::weak_ordering&,
>>> +      std::weak_equality>::value, "");
>>> +  { // value == 0
>>> +    auto V = std::weak_ordering::equivalent;
>>> +    std::weak_equality WV = V;
>>> +    assert(WV == 0);
>>> +  }
>>> +  std::weak_ordering WeakTestCases[] = {
>>> +      std::weak_ordering::less,
>>> +      std::weak_ordering::greater,
>>> +  };
>>> +  for (auto V : WeakTestCases)
>>> +  { // value != 0
>>> +    std::weak_equality WV = V;
>>> +    assert(WV != 0);
>>> +  }
>>> +  static_assert(std::is_convertible<const std::weak_ordering&,
>>> +      std::partial_ordering>::value, "");
>>> +  { // value == 0
>>> +    auto V = std::weak_ordering::equivalent;
>>> +    std::partial_ordering WV = V;
>>> +    assert(WV == 0);
>>> +  }
>>> +  { // value < 0
>>> +    auto V = std::weak_ordering::less;
>>> +    std::partial_ordering WV = V;
>>> +    assert(WV < 0);
>>> +  }
>>> +  { // value > 0
>>> +    auto V = std::weak_ordering::greater;
>>> +    std::partial_ordering WV = V;
>>> +    assert(WV > 0);
>>> +  }
>>> +  return true;
>>> +}
>>> +
>>> +constexpr bool test_constexpr() {
>>> +  auto& Eq = std::weak_ordering::equivalent;
>>> +  auto& Less = std::weak_ordering::less;
>>> +  auto& Greater = std::weak_ordering::greater;
>>> +  struct {
>>> +    std::weak_ordering Value;
>>> +    bool ExpectEq;
>>> +    bool ExpectNeq;
>>> +    bool ExpectLess;
>>> +    bool ExpectGreater;
>>> +  } TestCases[] = {
>>> +      {Eq, true, false, false, false},
>>> +      {Less, false, true, true, false},
>>> +      {Greater, false, true, false, true},
>>> +  };
>>> +  for (auto TC : TestCases) {
>>> +    auto V = TC.Value;
>>> +    assert((V == 0) == TC.ExpectEq);
>>> +    assert((0 == V) == TC.ExpectEq);
>>> +    assert((V != 0) == TC.ExpectNeq);
>>> +    assert((0 != V) == TC.ExpectNeq);
>>> +
>>> +    assert((V < 0) == TC.ExpectLess);
>>> +    assert((V > 0) == TC.ExpectGreater);
>>> +    assert((V <= 0) == (TC.ExpectLess || TC.ExpectEq));
>>> +    assert((V >= 0) == (TC.ExpectGreater || TC.ExpectEq));
>>> +
>>> +    assert((0 < V) == TC.ExpectGreater);
>>> +    assert((0 > V) == TC.ExpectLess);
>>> +    assert((0 <= V) == (TC.ExpectGreater || TC.ExpectEq));
>>> +    assert((0 >= V) == (TC.ExpectLess || TC.ExpectEq));
>>> +  }
>>> +#ifndef TEST_HAS_NO_SPACESHIP_OPERATOR
>>> +  {
>>> +    std::weak_ordering res = (Eq <=> 0);
>>> +    ((void)res);
>>> +    res = (0 <=> Eq);
>>> +    ((void)res);
>>> +  }
>>> +  enum ExpectRes {
>>> +    ER_Greater,
>>> +    ER_Less,
>>> +    ER_Equiv
>>> +  };
>>> +  struct {
>>> +    std::weak_ordering Value;
>>> +    ExpectRes Expect;
>>> +  } SpaceshipTestCases[] = {
>>> +      {std::weak_ordering::equivalent, ER_Equiv},
>>> +      {std::weak_ordering::less, ER_Less},
>>> +      {std::weak_ordering::greater, ER_Greater},
>>> +  };
>>> +  for (auto TC : SpaceshipTestCases)
>>> +  {
>>> +    std::weak_ordering Res = (0 <=> TC.Value);
>>> +    switch (TC.Expect) {
>>> +    case ER_Equiv:
>>> +      assert(Res == 0);
>>> +      assert(0 == Res);
>>> +      break;
>>> +    case ER_Less:
>>> +      assert(Res < 0);
>>> +      break;
>>> +    case ER_Greater:
>>> +      assert(Res > 0);
>>> +      break;
>>> +    }
>>> +  }
>>> +#endif
>>> +
>>> +  return true;
>>> +}
>>> +
>>> +int main() {
>>> +  test_static_members();
>>> +  test_signatures();
>>> +  static_assert(test_conversion(), "conversion test failed");
>>> +  static_assert(test_constexpr(), "constexpr test failed");
>>> +}
>>>
>>> Modified: libcxx/trunk/test/support/test_macros.h
>>> URL:
>>> http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/support/test_macros.h?rev=329460&r1=329459&r2=329460&view=diff
>>>
>>> ==============================================================================
>>> --- libcxx/trunk/test/support/test_macros.h (original)
>>> +++ libcxx/trunk/test/support/test_macros.h Fri Apr  6 14:37:23 2018
>>> @@ -169,6 +169,11 @@
>>>  #define TEST_SAFE_STATIC
>>>  #endif
>>>
>>> +// FIXME: Fix this feature check when either (A) a compiler provides a
>>> complete
>>> +// implementation, or (b) a feature check macro is specified
>>> +#define TEST_HAS_NO_SPACESHIP_OPERATOR
>>> +
>>> +
>>>  #if TEST_STD_VER < 11
>>>  #define ASSERT_NOEXCEPT(...)
>>>  #define ASSERT_NOT_NOEXCEPT(...)
>>>
>>>
>>> _______________________________________________
>>> cfe-commits mailing list
>>> cfe-commits at lists.llvm.org
>>> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
>>>
>>
>>
> _______________________________________________
> cfe-commits mailing list
> cfe-commits at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20180407/dc9d02d3/attachment-0001.html>


More information about the cfe-commits mailing list