<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">On 6 April 2018 at 14:37, Eric Fiselier via cfe-commits <span dir="ltr"><<a href="mailto:cfe-commits@lists.llvm.org" target="_blank">cfe-commits@lists.llvm.org</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: ericwf<br>
Date: Fri Apr  6 14:37:23 2018<br>
New Revision: 329460<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=329460&view=rev" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project?rev=329460&view=rev</a><br>
Log:<br>
Implement P0768r1: Library support for the Spaceship Operator.<br>
<br>
this patch adds the <compare> header and implements all of it<br>
except for [comp.alg].<br>
<br>
As I understand it, the header is needed by the compiler in<br>
when implementing the semantics of operator<=>. For that reason<br>
I feel it's important to land this header early, despite<br>
all compilers lacking support.<br>
<br>
Added:<br>
    libcxx/trunk/include/compare<br>
    libcxx/trunk/test/libcxx/<wbr>language.support/cmp/<br>
    libcxx/trunk/test/libcxx/<wbr>language.support/cmp/version.<wbr>pass.cpp<br>
    libcxx/trunk/test/std/<wbr>language.support/cmp/<br>
    libcxx/trunk/test/std/<wbr>language.support/cmp/cmp.<wbr>common/<br>
    libcxx/trunk/test/std/<wbr>language.support/cmp/cmp.<wbr>common/common_comparison_<wbr>category.pass.cpp<br>
    libcxx/trunk/test/std/<wbr>language.support/cmp/cmp.<wbr>partialord/<br>
    libcxx/trunk/test/std/<wbr>language.support/cmp/cmp.<wbr>partialord/partialord.pass.cpp<br>
    libcxx/trunk/test/std/<wbr>language.support/cmp/cmp.<wbr>strongeq/<br>
    libcxx/trunk/test/std/<wbr>language.support/cmp/cmp.<wbr>strongeq/cmp.strongeq.pass.cpp<br>
    libcxx/trunk/test/std/<wbr>language.support/cmp/cmp.<wbr>strongord/<br>
    libcxx/trunk/test/std/<wbr>language.support/cmp/cmp.<wbr>strongord/strongord.pass.cpp<br>
    libcxx/trunk/test/std/<wbr>language.support/cmp/cmp.<wbr>weakeq/<br>
    libcxx/trunk/test/std/<wbr>language.support/cmp/cmp.<wbr>weakeq/cmp.weakeq.pass.cpp<br>
    libcxx/trunk/test/std/<wbr>language.support/cmp/cmp.<wbr>weakord/<br>
    libcxx/trunk/test/std/<wbr>language.support/cmp/cmp.<wbr>weakord/weakord.pass.cpp<br>
Modified:<br>
    libcxx/trunk/include/<wbr>CMakeLists.txt<br>
    libcxx/trunk/include/__config<br>
    libcxx/trunk/include/module.<wbr>modulemap<br>
    libcxx/trunk/test/libcxx/<wbr>double_include.sh.cpp<br>
    libcxx/trunk/test/support/<wbr>test_macros.h<br>
<br>
Modified: libcxx/trunk/include/<wbr>CMakeLists.txt<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/CMakeLists.txt?rev=329460&r1=329459&r2=329460&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/libcxx/trunk/include/<wbr>CMakeLists.txt?rev=329460&r1=<wbr>329459&r2=329460&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- libcxx/trunk/include/<wbr>CMakeLists.txt (original)<br>
+++ libcxx/trunk/include/<wbr>CMakeLists.txt Fri Apr  6 14:37:23 2018<br>
@@ -77,5 +77,4 @@ if (LIBCXX_INSTALL_HEADERS)<br>
     add_custom_target(install-<wbr>libcxx-headers DEPENDS install-cxx-headers)<br>
     add_custom_target(install-<wbr>libcxx-headers-stripped DEPENDS install-cxx-headers-stripped)<br>
   endif()<br>
-<br>
 endif()<br>
<br>
Modified: libcxx/trunk/include/__config<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/__config?rev=329460&r1=329459&r2=329460&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/libcxx/trunk/include/_<wbr>_config?rev=329460&r1=329459&<wbr>r2=329460&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- libcxx/trunk/include/__config (original)<br>
+++ libcxx/trunk/include/__config Fri Apr  6 14:37:23 2018<br>
@@ -1196,6 +1196,11 @@ _LIBCPP_FUNC_VIS extern "C" void __sanit<br>
 #define _LIBCPP_HAS_NO_COROUTINES<br>
 #endif<br>
<br>
+// FIXME: Correct this macro when either (A) a feature test macro for the<br>
+// spaceship operator is provided, or (B) a compiler provides a complete<br>
+// implementation.<br>
+#define _LIBCPP_HAS_NO_SPACESHIP_<wbr>OPERATOR<br>
+<br>
 // Decide whether to use availability macros.<br>
 #if !defined(_LIBCPP_BUILDING_<wbr>LIBRARY) &&                                      \<br>
     !defined(_LIBCPP_DISABLE_<wbr>AVAILABILITY) &&                                  \<br>
<br>
Added: libcxx/trunk/include/compare<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/compare?rev=329460&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/libcxx/trunk/include/<wbr>compare?rev=329460&view=auto</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- libcxx/trunk/include/compare (added)<br>
+++ libcxx/trunk/include/compare Fri Apr  6 14:37:23 2018<br>
@@ -0,0 +1,679 @@<br>
+// -*- C++ -*-<br>
+//===------------------------<wbr>-- compare ------------------------------<wbr>-----===//<br>
+//<br>
+//                     The LLVM Compiler Infrastructure<br>
+//<br>
+// This file is dual licensed under the MIT and the University of Illinois Open<br>
+// Source Licenses. See LICENSE.TXT for details.<br>
+//<br>
+//===------------------------<wbr>------------------------------<wbr>----------------===//<br>
+<br>
+#ifndef _LIBCPP_COMPARE<br>
+#define _LIBCPP_COMPARE<br>
+<br>
+/*<br>
+    compare synopsis<br>
+<br>
+namespace std {<br>
+  // [cmp.categories], comparison category types<br>
+  class weak_equality;<br>
+  class strong_equality;<br>
+  class partial_ordering;<br>
+  class weak_ordering;<br>
+  class strong_ordering;<br>
+<br>
+  // named comparison functions<br>
+  constexpr bool is_eq  (weak_equality cmp) noexcept    { return cmp == 0; }<br>
+  constexpr bool is_neq (weak_equality cmp) noexcept    { return cmp != 0; }<br>
+  constexpr bool is_lt  (partial_ordering cmp) noexcept { return cmp < 0; }<br>
+  constexpr bool is_lteq(partial_ordering cmp) noexcept { return cmp <= 0; }<br>
+  constexpr bool is_gt  (partial_ordering cmp) noexcept { return cmp > 0; }<br>
+  constexpr bool is_gteq(partial_ordering cmp) noexcept { return cmp >= 0; }<br>
+<br>
+  // [cmp.common], common comparison category type<br>
+  template<class... Ts><br>
+  struct common_comparison_category {<br>
+    using type = see below;<br>
+  };<br>
+  template<class... Ts><br>
+    using common_comparison_category_t = typename common_comparison_category<Ts.<wbr>..>::type;<br>
+<br>
+  // [cmp.alg], comparison algorithms<br>
+  template<class T> constexpr strong_ordering strong_order(const T& a, const T& b);<br>
+  template<class T> constexpr weak_ordering weak_order(const T& a, const T& b);<br>
+  template<class T> constexpr partial_ordering partial_order(const T& a, const T& b);<br>
+  template<class T> constexpr strong_equality strong_equal(const T& a, const T& b);<br>
+  template<class T> constexpr weak_equality weak_equal(const T& a, const T& b);<br>
+}<br>
+*/<br>
+<br>
+#include <__config><br>
+#include <type_traits><br>
+#include <array><br>
+<br>
+#ifndef _LIBCPP_HAS_NO_PRAGMA_SYSTEM_<wbr>HEADER<br>
+#pragma GCC system_header<br>
+#endif<br>
+<br>
+_LIBCPP_BEGIN_NAMESPACE_STD<br>
+<br>
+#if _LIBCPP_STD_VER > 17<br>
+<br>
+// exposition only<br>
+enum class _LIBCPP_ENUM_VIS _EqResult : unsigned char {<br>
+  __zero = 0,<br>
+  __equal = __zero,<br>
+  __equiv = __equal,<br>
+  __nonequal = 1,<br>
+  __nonequiv = __nonequal<br>
+};<br>
+<br>
+enum class _LIBCPP_ENUM_VIS _OrdResult : signed char {<br>
+  __less = -1,<br>
+  __greater = 1<br>
+};<br>
+<br>
+enum class _LIBCPP_ENUM_VIS _NCmpResult : signed char {<br>
+  __unordered = -127<br>
+};<br>
+<br>
+struct _CmpUnspecifiedType;<br>
+using _CmpUnspecifiedParam = void (_CmpUnspecifiedType::*)();<br></blockquote><div><br></div><div>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.</div><div><br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
+<br>
+class  weak_equality {<br>
+  _LIBCPP_INLINE_VISIBILITY<br>
+  constexpr explicit weak_equality(_EqResult __val) noexcept : __value_(__val) {}<br>
+<br>
+public:<br>
+  static const weak_equality equivalent;<br>
+  static const weak_equality nonequivalent;<br>
+<br>
+  friend constexpr bool operator==(weak_equality __v, _CmpUnspecifiedParam) noexcept;<br>
+  friend constexpr bool operator==(_<wbr>CmpUnspecifiedParam, weak_equality __v) noexcept;<br>
+  friend constexpr bool operator!=(weak_equality __v, _CmpUnspecifiedParam) noexcept;<br>
+  friend constexpr bool operator!=(_<wbr>CmpUnspecifiedParam, weak_equality __v) noexcept;<br>
+<br>
+#ifndef _LIBCPP_HAS_NO_SPACESHIP_<wbr>OPERATOR<br>
+  friend constexpr weak_equality operator<=>(weak_equality __v, _CmpUnspecifiedParam) noexcept;<br>
+  friend constexpr weak_equality operator<=>(_<wbr>CmpUnspecifiedParam, weak_equality __v) noexcept;<br>
+#endif<br>
+<br>
+private:<br>
+  _EqResult __value_;<br>
+};<br>
+<br>
+_LIBCPP_INLINE_VAR constexpr weak_equality weak_equality::equivalent(_<wbr>EqResult::__equiv);<br>
+_LIBCPP_INLINE_VAR constexpr weak_equality weak_equality::nonequivalent(_<wbr>EqResult::__nonequiv);<br>
+<br>
+_LIBCPP_INLINE_VISIBILITY<br>
+inline constexpr bool operator==(weak_equality __v, _CmpUnspecifiedParam) noexcept {<br>
+  return __v.__value_ == _EqResult::__zero;<br>
+}<br>
+<br>
+_LIBCPP_INLINE_VISIBILITY<br>
+inline constexpr bool operator==(_<wbr>CmpUnspecifiedParam, weak_equality __v) noexcept {<br>
+  return __v.__value_ == _EqResult::__zero;<br>
+}<br>
+<br>
+_LIBCPP_INLINE_VISIBILITY<br>
+inline constexpr bool operator!=(weak_equality __v, _CmpUnspecifiedParam) noexcept {<br>
+  return __v.__value_ != _EqResult::__zero;<br>
+}<br>
+<br>
+_LIBCPP_INLINE_VISIBILITY<br>
+inline constexpr bool operator!=(_<wbr>CmpUnspecifiedParam, weak_equality __v) noexcept {<br>
+  return __v.__value_ != _EqResult::__zero;<br>
+}<br>
+<br>
+#ifndef _LIBCPP_HAS_NO_SPACESHIP_<wbr>OPERATOR<br>
+_LIBCPP_INLINE_VISIBILITY<br>
+inline constexpr weak_equality operator<=>(weak_equality __v, _CmpUnspecifiedParam) noexcept {<br>
+  return __v;<br>
+}<br>
+<br>
+_LIBCPP_INLINE_VISIBILITY<br>
+inline constexpr weak_equality operator<=>(_<wbr>CmpUnspecifiedParam, weak_equality __v) noexcept {<br>
+  return __v;<br>
+}<br>
+#endif<br>
+<br>
+class strong_equality {<br>
+  _LIBCPP_INLINE_VISIBILITY<br>
+  explicit constexpr strong_equality(_EqResult __val) noexcept : __value_(__val) {}<br>
+<br>
+public:<br>
+  static const strong_equality equal;<br>
+  static const strong_equality nonequal;<br>
+  static const strong_equality equivalent;<br>
+  static const strong_equality nonequivalent;<br>
+<br>
+  // conversion<br>
+  constexpr operator weak_equality() const noexcept {<br>
+    return __value_ == _EqResult::__zero ? weak_equality::equivalent<br>
+          : weak_equality::nonequivalent;<br>
+  }<br>
+<br>
+  // comparisons<br>
+  friend constexpr bool operator==(strong_equality __v, _CmpUnspecifiedParam) noexcept;<br>
+  friend constexpr bool operator!=(strong_equality __v, _CmpUnspecifiedParam) noexcept;<br>
+  friend constexpr bool operator==(_<wbr>CmpUnspecifiedParam, strong_equality __v) noexcept;<br>
+  friend constexpr bool operator!=(_<wbr>CmpUnspecifiedParam, strong_equality __v) noexcept;<br>
+<br>
+#ifndef _LIBCPP_HAS_NO_SPACESHIP_<wbr>OPERATOR<br>
+  friend constexpr strong_equality operator<=>(strong_equality __v, _CmpUnspecifiedParam) noexcept;<br>
+  friend constexpr strong_equality operator<=>(_<wbr>CmpUnspecifiedParam, strong_equality __v) noexcept;<br>
+#endif<br>
+private:<br>
+  _EqResult __value_;<br>
+};<br>
+<br>
+_LIBCPP_INLINE_VAR constexpr strong_equality strong_equality::equal(_<wbr>EqResult::__equal);<br>
+_LIBCPP_INLINE_VAR constexpr strong_equality strong_equality::nonequal(_<wbr>EqResult::__nonequal);<br>
+_LIBCPP_INLINE_VAR constexpr strong_equality strong_equality::equivalent(_<wbr>EqResult::__equiv);<br>
+_LIBCPP_INLINE_VAR constexpr strong_equality strong_equality::<wbr>nonequivalent(_EqResult::__<wbr>nonequiv);<br>
+<br>
+_LIBCPP_INLINE_VISIBILITY<br>
+constexpr bool operator==(strong_equality __v, _CmpUnspecifiedParam) noexcept {<br>
+  return __v.__value_ == _EqResult::__zero;<br>
+}<br>
+<br>
+_LIBCPP_INLINE_VISIBILITY<br>
+constexpr bool operator==(_<wbr>CmpUnspecifiedParam, strong_equality __v) noexcept {<br>
+  return __v.__value_ == _EqResult::__zero;<br>
+}<br>
+<br>
+_LIBCPP_INLINE_VISIBILITY<br>
+constexpr bool operator!=(strong_equality __v, _CmpUnspecifiedParam) noexcept {<br>
+  return __v.__value_ != _EqResult::__zero;<br>
+}<br>
+<br>
+_LIBCPP_INLINE_VISIBILITY<br>
+constexpr bool operator!=(_<wbr>CmpUnspecifiedParam, strong_equality __v) noexcept {<br>
+  return __v.__value_ != _EqResult::__zero;<br>
+}<br>
+<br>
+#ifndef _LIBCPP_HAS_NO_SPACESHIP_<wbr>OPERATOR<br>
+_LIBCPP_INLINE_VISIBILITY<br>
+constexpr strong_equality operator<=>(strong_equality __v, _CmpUnspecifiedParam) noexcept {<br>
+  return __v;<br>
+}<br>
+<br>
+_LIBCPP_INLINE_VISIBILITY<br>
+constexpr strong_equality operator<=>(_<wbr>CmpUnspecifiedParam, strong_equality __v) noexcept {<br>
+  return __v;<br>
+}<br>
+#endif // _LIBCPP_HAS_NO_SPACESHIP_<wbr>OPERATOR<br>
+<br>
+class partial_ordering {<br>
+  using _ValueT = signed char;<br>
+<br>
+  _LIBCPP_INLINE_VISIBILITY<br>
+  explicit constexpr partial_ordering(_EqResult __v) noexcept<br>
+      : __value_(_ValueT(__v)) {}<br>
+<br>
+  _LIBCPP_INLINE_VISIBILITY<br>
+  explicit constexpr partial_ordering(_OrdResult __v) noexcept<br>
+      : __value_(_ValueT(__v)) {}<br>
+<br>
+  _LIBCPP_INLINE_VISIBILITY<br>
+  explicit constexpr partial_ordering(_NCmpResult __v) noexcept<br>
+      : __value_(_ValueT(__v)) {}<br>
+<br>
+  constexpr bool __is_ordered() const noexcept {<br>
+    return __value_ != _ValueT(_NCmpResult::__<wbr>unordered);<br>
+  }<br>
+public:<br>
+  // valid values<br>
+  static const partial_ordering less;<br>
+  static const partial_ordering equivalent;<br>
+  static const partial_ordering greater;<br>
+  static const partial_ordering unordered;<br>
+<br>
+  // conversion<br>
+  constexpr operator weak_equality() const noexcept {<br>
+    return __value_ == 0 ? weak_equality::equivalent : weak_equality::nonequivalent;<br>
+  }<br>
+<br>
+  // comparisons<br>
+  friend constexpr bool operator==(partial_ordering __v, _CmpUnspecifiedParam) noexcept;<br>
+  friend constexpr bool operator!=(partial_ordering __v, _CmpUnspecifiedParam) noexcept;<br>
+  friend constexpr bool operator< (partial_ordering __v, _CmpUnspecifiedParam) noexcept;<br>
+  friend constexpr bool operator<=(partial_ordering __v, _CmpUnspecifiedParam) noexcept;<br>
+  friend constexpr bool operator> (partial_ordering __v, _CmpUnspecifiedParam) noexcept;<br>
+  friend constexpr bool operator>=(partial_ordering __v, _CmpUnspecifiedParam) noexcept;<br>
+  friend constexpr bool operator==(_<wbr>CmpUnspecifiedParam, partial_ordering __v) noexcept;<br>
+  friend constexpr bool operator!=(_<wbr>CmpUnspecifiedParam, partial_ordering __v) noexcept;<br>
+  friend constexpr bool operator< (_CmpUnspecifiedParam, partial_ordering __v) noexcept;<br>
+  friend constexpr bool operator<=(_<wbr>CmpUnspecifiedParam, partial_ordering __v) noexcept;<br>
+  friend constexpr bool operator> (_CmpUnspecifiedParam, partial_ordering __v) noexcept;<br>
+  friend constexpr bool operator>=(_<wbr>CmpUnspecifiedParam, partial_ordering __v) noexcept;<br>
+<br>
+#ifndef _LIBCPP_HAS_NO_SPACESHIP_<wbr>OPERATOR<br>
+  friend constexpr partial_ordering operator<=>(partial_ordering __v, _CmpUnspecifiedParam) noexcept;<br>
+  friend constexpr partial_ordering operator<=>(_<wbr>CmpUnspecifiedParam, partial_ordering __v) noexcept;<br>
+#endif<br>
+<br>
+private:<br>
+  _ValueT __value_;<br>
+};<br>
+<br>
+_LIBCPP_INLINE_VAR constexpr partial_ordering partial_ordering::less(_<wbr>OrdResult::__less);<br>
+_LIBCPP_INLINE_VAR constexpr partial_ordering partial_ordering::equivalent(_<wbr>EqResult::__equiv);<br>
+_LIBCPP_INLINE_VAR constexpr partial_ordering partial_ordering::greater(_<wbr>OrdResult::__greater);<br>
+_LIBCPP_INLINE_VAR constexpr partial_ordering partial_ordering::unordered(_<wbr>NCmpResult ::__unordered);<br>
+<br>
+_LIBCPP_INLINE_VISIBILITY<br>
+constexpr bool operator==(partial_ordering __v, _CmpUnspecifiedParam) noexcept {<br>
+  return __v.__is_ordered() && __v.__value_ == 0;<br>
+}<br>
+_LIBCPP_INLINE_VISIBILITY<br>
+constexpr bool operator< (partial_ordering __v, _CmpUnspecifiedParam) noexcept {<br>
+  return __v.__is_ordered() && __v.__value_ < 0;<br>
+}<br>
+_LIBCPP_INLINE_VISIBILITY<br>
+constexpr bool operator<=(partial_ordering __v, _CmpUnspecifiedParam) noexcept {<br>
+  return __v.__is_ordered() && __v.__value_ <= 0;<br>
+}<br>
+_LIBCPP_INLINE_VISIBILITY<br>
+constexpr bool operator> (partial_ordering __v, _CmpUnspecifiedParam) noexcept {<br>
+  return __v.__is_ordered() && __v.__value_ > 0;<br>
+}<br>
+_LIBCPP_INLINE_VISIBILITY<br>
+constexpr bool operator>=(partial_ordering __v, _CmpUnspecifiedParam) noexcept {<br>
+  return __v.__is_ordered() && __v.__value_ >= 0;<br>
+}<br>
+<br>
+_LIBCPP_INLINE_VISIBILITY<br>
+constexpr bool operator==(_<wbr>CmpUnspecifiedParam, partial_ordering __v) noexcept {<br>
+  return __v.__is_ordered() && 0 == __v.__value_;<br>
+}<br>
+_LIBCPP_INLINE_VISIBILITY<br>
+constexpr bool operator< (_CmpUnspecifiedParam, partial_ordering __v) noexcept {<br>
+  return __v.__is_ordered() && 0 < __v.__value_;<br>
+}<br>
+_LIBCPP_INLINE_VISIBILITY<br>
+constexpr bool operator<=(_<wbr>CmpUnspecifiedParam, partial_ordering __v) noexcept {<br>
+  return __v.__is_ordered() && 0 <= __v.__value_;<br>
+}<br>
+_LIBCPP_INLINE_VISIBILITY<br>
+constexpr bool operator> (_CmpUnspecifiedParam, partial_ordering __v) noexcept {<br>
+  return __v.__is_ordered() && 0 > __v.__value_;<br>
+}<br>
+_LIBCPP_INLINE_VISIBILITY<br>
+constexpr bool operator>=(_<wbr>CmpUnspecifiedParam, partial_ordering __v) noexcept {<br>
+  return __v.__is_ordered() && 0 >= __v.__value_;<br>
+}<br>
+<br>
+_LIBCPP_INLINE_VISIBILITY<br>
+constexpr bool operator!=(partial_ordering __v, _CmpUnspecifiedParam) noexcept {<br>
+  return !__v.__is_ordered() || __v.__value_ != 0;<br>
+}<br>
+_LIBCPP_INLINE_VISIBILITY<br>
+constexpr bool operator!=(_<wbr>CmpUnspecifiedParam, partial_ordering __v) noexcept {<br>
+  return !__v.__is_ordered() || __v.__value_ != 0;<br>
+}<br>
+<br>
+#ifndef _LIBCPP_HAS_NO_SPACESHIP_<wbr>OPERATOR<br>
+_LIBCPP_INLINE_VISIBILITY<br>
+constexpr partial_ordering operator<=>(partial_ordering __v, _CmpUnspecifiedParam) noexcept {<br>
+  return __v;<br>
+}<br>
+_LIBCPP_INLINE_VISIBILITY<br>
+constexpr partial_ordering operator<=>(_<wbr>CmpUnspecifiedParam, partial_ordering __v) noexcept {<br>
+  return __v < 0 ? partial_ordering::greater : (__v > 0 ? partial_ordering::less : __v);<br>
+}<br>
+#endif // _LIBCPP_HAS_NO_SPACESHIP_<wbr>OPERATOR<br>
+<br>
+class weak_ordering {<br>
+  using _ValueT = signed char;<br>
+<br>
+  _LIBCPP_INLINE_VISIBILITY<br>
+  explicit constexpr weak_ordering(_EqResult __v) noexcept : __value_(_ValueT(__v)) {}<br>
+  _LIBCPP_INLINE_VISIBILITY<br>
+  explicit constexpr weak_ordering(_OrdResult __v) noexcept : __value_(_ValueT(__v)) {}<br>
+<br>
+public:<br>
+  static const weak_ordering less;<br>
+  static const weak_ordering equivalent;<br>
+  static const weak_ordering greater;<br>
+<br>
+  // conversions<br>
+  _LIBCPP_INLINE_VISIBILITY<br>
+  constexpr operator weak_equality() const noexcept {<br>
+    return __value_ == 0 ? weak_equality::equivalent<br>
+                         : weak_equality::nonequivalent;<br>
+  }<br>
+<br>
+  _LIBCPP_INLINE_VISIBILITY<br>
+  constexpr operator partial_ordering() const noexcept {<br>
+    return __value_ == 0 ? partial_ordering::equivalent<br>
+        : (__value_ < 0 ? partial_ordering::less : partial_ordering::greater);<br>
+  }<br>
+<br>
+  // comparisons<br>
+  friend constexpr bool operator==(weak_ordering __v, _CmpUnspecifiedParam) noexcept;<br>
+  friend constexpr bool operator!=(weak_ordering __v, _CmpUnspecifiedParam) noexcept;<br>
+  friend constexpr bool operator< (weak_ordering __v, _CmpUnspecifiedParam) noexcept;<br>
+  friend constexpr bool operator<=(weak_ordering __v, _CmpUnspecifiedParam) noexcept;<br>
+  friend constexpr bool operator> (weak_ordering __v, _CmpUnspecifiedParam) noexcept;<br>
+  friend constexpr bool operator>=(weak_ordering __v, _CmpUnspecifiedParam) noexcept;<br>
+  friend constexpr bool operator==(_<wbr>CmpUnspecifiedParam, weak_ordering __v) noexcept;<br>
+  friend constexpr bool operator!=(_<wbr>CmpUnspecifiedParam, weak_ordering __v) noexcept;<br>
+  friend constexpr bool operator< (_CmpUnspecifiedParam, weak_ordering __v) noexcept;<br>
+  friend constexpr bool operator<=(_<wbr>CmpUnspecifiedParam, weak_ordering __v) noexcept;<br>
+  friend constexpr bool operator> (_CmpUnspecifiedParam, weak_ordering __v) noexcept;<br>
+  friend constexpr bool operator>=(_<wbr>CmpUnspecifiedParam, weak_ordering __v) noexcept;<br>
+<br>
+#ifndef _LIBCPP_HAS_NO_SPACESHIP_<wbr>OPERATOR<br>
+  friend constexpr weak_ordering operator<=>(weak_ordering __v, _CmpUnspecifiedParam) noexcept;<br>
+  friend constexpr weak_ordering operator<=>(_<wbr>CmpUnspecifiedParam, weak_ordering __v) noexcept;<br>
+#endif<br>
+<br>
+private:<br>
+  _ValueT __value_;<br>
+};<br>
+<br>
+_LIBCPP_INLINE_VAR constexpr weak_ordering weak_ordering::less(_<wbr>OrdResult::__less);<br>
+_LIBCPP_INLINE_VAR constexpr weak_ordering weak_ordering::equivalent(_<wbr>EqResult::__equiv);<br>
+_LIBCPP_INLINE_VAR constexpr weak_ordering weak_ordering::greater(_<wbr>OrdResult::__greater);<br>
+<br>
+_LIBCPP_INLINE_VISIBILITY<br>
+constexpr bool operator==(weak_ordering __v, _CmpUnspecifiedParam) noexcept {<br>
+  return __v.__value_ == 0;<br>
+}<br>
+_LIBCPP_INLINE_VISIBILITY<br>
+constexpr bool operator!=(weak_ordering __v, _CmpUnspecifiedParam) noexcept {<br>
+  return __v.__value_ != 0;<br>
+}<br>
+_LIBCPP_INLINE_VISIBILITY<br>
+constexpr bool operator< (weak_ordering __v, _CmpUnspecifiedParam) noexcept {<br>
+  return __v.__value_ < 0;<br>
+}<br>
+_LIBCPP_INLINE_VISIBILITY<br>
+constexpr bool operator<=(weak_ordering __v, _CmpUnspecifiedParam) noexcept {<br>
+  return __v.__value_ <= 0;<br>
+}<br>
+_LIBCPP_INLINE_VISIBILITY<br>
+constexpr bool operator> (weak_ordering __v, _CmpUnspecifiedParam) noexcept {<br>
+  return __v.__value_ > 0;<br>
+}<br>
+_LIBCPP_INLINE_VISIBILITY<br>
+constexpr bool operator>=(weak_ordering __v, _CmpUnspecifiedParam) noexcept {<br>
+  return __v.__value_ >= 0;<br>
+}<br>
+_LIBCPP_INLINE_VISIBILITY<br>
+constexpr bool operator==(_<wbr>CmpUnspecifiedParam, weak_ordering __v) noexcept {<br>
+  return 0 == __v.__value_;<br>
+}<br>
+_LIBCPP_INLINE_VISIBILITY<br>
+constexpr bool operator!=(_<wbr>CmpUnspecifiedParam, weak_ordering __v) noexcept {<br>
+  return 0 != __v.__value_;<br>
+}<br>
+_LIBCPP_INLINE_VISIBILITY<br>
+constexpr bool operator< (_CmpUnspecifiedParam, weak_ordering __v) noexcept {<br>
+  return 0 < __v.__value_;<br>
+}<br>
+_LIBCPP_INLINE_VISIBILITY<br>
+constexpr bool operator<=(_<wbr>CmpUnspecifiedParam, weak_ordering __v) noexcept {<br>
+  return 0 <= __v.__value_;<br>
+}<br>
+_LIBCPP_INLINE_VISIBILITY<br>
+constexpr bool operator> (_CmpUnspecifiedParam, weak_ordering __v) noexcept {<br>
+  return 0 > __v.__value_;<br>
+}<br>
+_LIBCPP_INLINE_VISIBILITY<br>
+constexpr bool operator>=(_<wbr>CmpUnspecifiedParam, weak_ordering __v) noexcept {<br>
+  return 0 >= __v.__value_;<br>
+}<br>
+<br>
+#ifndef _LIBCPP_HAS_NO_SPACESHIP_<wbr>OPERATOR<br>
+_LIBCPP_INLINE_VISIBILITY<br>
+constexpr weak_ordering operator<=>(weak_ordering __v, _CmpUnspecifiedParam) noexcept {<br>
+  return __v;<br>
+}<br>
+_LIBCPP_INLINE_VISIBILITY<br>
+constexpr weak_ordering operator<=>(_<wbr>CmpUnspecifiedParam, weak_ordering __v) noexcept {<br>
+  return __v < 0 ? weak_ordering::greater : (__v > 0 ? weak_ordering::less : __v);<br>
+}<br>
+#endif // _LIBCPP_HAS_NO_SPACESHIP_<wbr>OPERATOR<br>
+<br>
+class strong_ordering {<br>
+  using _ValueT = signed char;<br>
+<br>
+  _LIBCPP_INLINE_VISIBILITY<br>
+  explicit constexpr strong_ordering(_EqResult __v) noexcept : __value_(_ValueT(__v)) {}<br>
+  _LIBCPP_INLINE_VISIBILITY<br>
+  explicit constexpr strong_ordering(_OrdResult __v) noexcept : __value_(_ValueT(__v)) {}<br>
+<br>
+public:<br>
+  static const strong_ordering less;<br>
+  static const strong_ordering equal;<br>
+  static const strong_ordering equivalent;<br>
+  static const strong_ordering greater;<br>
+<br>
+  // conversions<br>
+  _LIBCPP_INLINE_VISIBILITY<br>
+  constexpr operator weak_equality() const noexcept {<br>
+    return __value_ == 0 ? weak_equality::equivalent<br>
+                         : weak_equality::nonequivalent;<br>
+  }<br>
+<br>
+  _LIBCPP_INLINE_VISIBILITY<br>
+  constexpr operator strong_equality() const noexcept {<br>
+    return __value_ == 0 ? strong_equality::equal<br>
+                         : strong_equality::nonequal;<br>
+  }<br>
+<br>
+  _LIBCPP_INLINE_VISIBILITY<br>
+  constexpr operator partial_ordering() const noexcept {<br>
+    return __value_ == 0 ? partial_ordering::equivalent<br>
+        : (__value_ < 0 ? partial_ordering::less : partial_ordering::greater);<br>
+  }<br>
+<br>
+  _LIBCPP_INLINE_VISIBILITY<br>
+  constexpr operator weak_ordering() const noexcept {<br>
+    return __value_ == 0 ? weak_ordering::equivalent<br>
+        : (__value_ < 0 ? weak_ordering::less : weak_ordering::greater);<br>
+  }<br>
+<br>
+  // comparisons<br>
+  friend constexpr bool operator==(strong_ordering __v, _CmpUnspecifiedParam) noexcept;<br>
+  friend constexpr bool operator!=(strong_ordering __v, _CmpUnspecifiedParam) noexcept;<br>
+  friend constexpr bool operator< (strong_ordering __v, _CmpUnspecifiedParam) noexcept;<br>
+  friend constexpr bool operator<=(strong_ordering __v, _CmpUnspecifiedParam) noexcept;<br>
+  friend constexpr bool operator> (strong_ordering __v, _CmpUnspecifiedParam) noexcept;<br>
+  friend constexpr bool operator>=(strong_ordering __v, _CmpUnspecifiedParam) noexcept;<br>
+  friend constexpr bool operator==(_<wbr>CmpUnspecifiedParam, strong_ordering __v) noexcept;<br>
+  friend constexpr bool operator!=(_<wbr>CmpUnspecifiedParam, strong_ordering __v) noexcept;<br>
+  friend constexpr bool operator< (_CmpUnspecifiedParam, strong_ordering __v) noexcept;<br>
+  friend constexpr bool operator<=(_<wbr>CmpUnspecifiedParam, strong_ordering __v) noexcept;<br>
+  friend constexpr bool operator> (_CmpUnspecifiedParam, strong_ordering __v) noexcept;<br>
+  friend constexpr bool operator>=(_<wbr>CmpUnspecifiedParam, strong_ordering __v) noexcept;<br>
+<br>
+#ifndef _LIBCPP_HAS_NO_SPACESHIP_<wbr>OPERATOR<br>
+  friend constexpr strong_ordering operator<=>(strong_ordering __v, _CmpUnspecifiedParam) noexcept;<br>
+  friend constexpr strong_ordering operator<=>(_<wbr>CmpUnspecifiedParam, strong_ordering __v) noexcept;<br>
+#endif<br>
+<br>
+private:<br>
+  _ValueT __value_;<br>
+};<br>
+<br>
+_LIBCPP_INLINE_VAR constexpr strong_ordering strong_ordering::less(_<wbr>OrdResult::__less);<br>
+_LIBCPP_INLINE_VAR constexpr strong_ordering strong_ordering::equal(_<wbr>EqResult::__equal);<br>
+_LIBCPP_INLINE_VAR constexpr strong_ordering strong_ordering::equivalent(_<wbr>EqResult::__equiv);<br>
+_LIBCPP_INLINE_VAR constexpr strong_ordering strong_ordering::greater(_<wbr>OrdResult::__greater);<br>
+<br>
+_LIBCPP_INLINE_VISIBILITY<br>
+constexpr bool operator==(strong_ordering __v, _CmpUnspecifiedParam) noexcept {<br>
+  return __v.__value_ == 0;<br>
+}<br>
+_LIBCPP_INLINE_VISIBILITY<br>
+constexpr bool operator!=(strong_ordering __v, _CmpUnspecifiedParam) noexcept {<br>
+  return __v.__value_ != 0;<br>
+}<br>
+_LIBCPP_INLINE_VISIBILITY<br>
+constexpr bool operator< (strong_ordering __v, _CmpUnspecifiedParam) noexcept {<br>
+  return __v.__value_ < 0;<br>
+}<br>
+_LIBCPP_INLINE_VISIBILITY<br>
+constexpr bool operator<=(strong_ordering __v, _CmpUnspecifiedParam) noexcept {<br>
+  return __v.__value_ <= 0;<br>
+}<br>
+_LIBCPP_INLINE_VISIBILITY<br>
+constexpr bool operator> (strong_ordering __v, _CmpUnspecifiedParam) noexcept {<br>
+  return __v.__value_ > 0;<br>
+}<br>
+_LIBCPP_INLINE_VISIBILITY<br>
+constexpr bool operator>=(strong_ordering __v, _CmpUnspecifiedParam) noexcept {<br>
+  return __v.__value_ >= 0;<br>
+}<br>
+_LIBCPP_INLINE_VISIBILITY<br>
+constexpr bool operator==(_<wbr>CmpUnspecifiedParam, strong_ordering __v) noexcept {<br>
+  return 0 == __v.__value_;<br>
+}<br>
+_LIBCPP_INLINE_VISIBILITY<br>
+constexpr bool operator!=(_<wbr>CmpUnspecifiedParam, strong_ordering __v) noexcept {<br>
+  return 0 != __v.__value_;<br>
+}<br>
+_LIBCPP_INLINE_VISIBILITY<br>
+constexpr bool operator< (_CmpUnspecifiedParam, strong_ordering __v) noexcept {<br>
+  return 0 < __v.__value_;<br>
+}<br>
+_LIBCPP_INLINE_VISIBILITY<br>
+constexpr bool operator<=(_<wbr>CmpUnspecifiedParam, strong_ordering __v) noexcept {<br>
+  return 0 <= __v.__value_;<br>
+}<br>
+_LIBCPP_INLINE_VISIBILITY<br>
+constexpr bool operator> (_CmpUnspecifiedParam, strong_ordering __v) noexcept {<br>
+  return 0 > __v.__value_;<br>
+}<br>
+_LIBCPP_INLINE_VISIBILITY<br>
+constexpr bool operator>=(_<wbr>CmpUnspecifiedParam, strong_ordering __v) noexcept {<br>
+  return 0 >= __v.__value_;<br>
+}<br>
+<br>
+#ifndef _LIBCPP_HAS_NO_SPACESHIP_<wbr>OPERATOR<br>
+_LIBCPP_INLINE_VISIBILITY<br>
+constexpr strong_ordering operator<=>(strong_ordering __v, _CmpUnspecifiedParam) noexcept {<br>
+  return __v;<br>
+}<br>
+_LIBCPP_INLINE_VISIBILITY<br>
+constexpr strong_ordering operator<=>(_<wbr>CmpUnspecifiedParam, strong_ordering __v) noexcept {<br>
+  return __v < 0 ? strong_ordering::greater : (__v > 0 ? strong_ordering::less : __v);<br>
+}<br>
+#endif // _LIBCPP_HAS_NO_SPACESHIP_<wbr>OPERATOR<br>
+<br>
+// named comparison functions<br>
+_LIBCPP_INLINE_VISIBILITY<br>
+constexpr bool is_eq(weak_equality __cmp) noexcept    { return __cmp == 0; }<br>
+<br>
+_LIBCPP_INLINE_VISIBILITY<br>
+constexpr bool is_neq(weak_equality __cmp) noexcept    { return __cmp != 0; }<br>
+<br>
+_LIBCPP_INLINE_VISIBILITY<br>
+constexpr bool is_lt(partial_ordering __cmp) noexcept { return __cmp < 0; }<br>
+<br>
+_LIBCPP_INLINE_VISIBILITY<br>
+constexpr bool is_lteq(partial_ordering __cmp) noexcept { return __cmp <= 0; }<br>
+<br>
+_LIBCPP_INLINE_VISIBILITY<br>
+constexpr bool is_gt(partial_ordering __cmp) noexcept { return __cmp > 0; }<br>
+<br>
+_LIBCPP_INLINE_VISIBILITY<br>
+constexpr bool is_gteq(partial_ordering __cmp) noexcept { return __cmp >= 0; }<br>
+<br>
+namespace __comp_detail {<br>
+<br>
+enum _ClassifyCompCategory : unsigned{<br>
+  _None,<br>
+  _WeakEq,<br>
+  _StrongEq,<br>
+  _PartialOrd,<br>
+  _WeakOrd,<br>
+  _StrongOrd,<br>
+  _CCC_Size<br>
+};<br>
+<br>
+template <class _Tp><br>
+_LIBCPP_INLINE_VISIBILITY<br>
+constexpr _ClassifyCompCategory __type_to_enum() noexcept {<br>
+  if (is_same_v<_Tp, weak_equality>)<br>
+    return _WeakEq;<br>
+  if (is_same_v<_Tp, strong_equality>)<br>
+    return _StrongEq;<br>
+  if (is_same_v<_Tp, partial_ordering>)<br>
+    return _PartialOrd;<br>
+  if (is_same_v<_Tp, weak_ordering>)<br>
+    return _WeakOrd;<br>
+  if (is_same_v<_Tp, strong_ordering>)<br>
+    return _StrongOrd;<br>
+  return _None;<br>
+}<br>
+<br>
+template <size_t _Size><br>
+constexpr _ClassifyCompCategory<br>
+__compute_comp_type(std::<wbr>array<_ClassifyCompCategory, _Size> __types) {<br>
+  std::array<int, _CCC_Size> __seen = {};<br>
+  for (auto __type : __types)<br>
+    ++__seen[__type];<br>
+  if (__seen[_None])<br>
+    return _None;<br>
+  if (__seen[_WeakEq])<br>
+    return _WeakEq;<br>
+  if (__seen[_StrongEq] && (__seen[_PartialOrd] || __seen[_WeakOrd]))<br>
+    return _WeakEq;<br>
+  if (__seen[_StrongEq])<br>
+    return _StrongEq;<br>
+  if (__seen[_PartialOrd])<br>
+    return _PartialOrd;<br>
+  if (__seen[_WeakOrd])<br>
+    return _WeakOrd;<br>
+  return _StrongOrd;<br>
+}<br></blockquote><div><br></div><div>Hmm, it'd be nice to ask the compiler to work this out rather than repeating the algorithm here. For example, something like:</div><div><br></div><div>template<size_t, typename T> struct CCT { friend T operator<=>(const CCT&, const CCT&); };</div><div>template<typename N, typename ...T> struct CCC;</div><div><div style="color:rgb(34,34,34);font-family:arial,sans-serif;font-size:small;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;background-color:rgb(255,255,255);text-decoration-style:initial;text-decoration-color:initial">template<size_t ...N, typename ...T> struct CCC : CCT<N, T>... {</div></div><div>  friend auto operator<=>(const CCC&, const CCC&) = default;</div><div>};</div><div>template<typename ...T> struct common_comparison_category {</div><div>  template<typename C> static auto test(int) -> decltype(declval<const C&>() <=> declval<const C&>());<br></div><div><span style="color:rgb(34,34,34);font-family:arial,sans-serif;font-size:small;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;background-color:rgb(255,255,255);text-decoration-style:initial;text-decoration-color:initial;float:none;display:inline">  template<typename C> static void test(...);</span></div><div>  using type = decltype(test<<span style="color:rgb(34,34,34);font-family:arial,sans-serif;font-size:small;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;background-color:rgb(255,255,255);text-decoration-style:initial;text-decoration-color:initial;float:none;display:inline">CCC<std::make_index_sequence<sizeof...(T)>, T...></span>>(0));<br></div><div>}</div><div><br></div><div>... should allow you to ask the compiler for the common comparison type.</div><div> <br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
+<br>
+template <class ..._Ts><br>
+constexpr auto __get_comp_type() {<br>
+  using _CCC = _ClassifyCompCategory;<br>
+  constexpr array<_CCC, sizeof...(_Ts)> __type_kinds{__comp_detail::__<wbr>type_to_enum<_Ts>()...};<br>
+  constexpr _CCC _Cat = sizeof...(_Ts) == 0 ? _StrongOrd<br>
+      : __compute_comp_type(__type_<wbr>kinds);<br>
+  if constexpr (_Cat == _None)<br>
+    return ((void)0);<br></blockquote><div><br></div><div>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.)</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
+  else if constexpr (_Cat == _WeakEq)<br>
+    return weak_equality::equivalent;<br>
+  else if constexpr (_Cat == _StrongEq)<br>
+    return strong_equality::equivalent;<br>
+  else if constexpr (_Cat == _PartialOrd)<br>
+    return partial_ordering::equivalent;<br>
+  else if constexpr (_Cat == _WeakOrd)<br>
+    return weak_ordering::equivalent;<br>
+  else if constexpr (_Cat == _StrongOrd)<br>
+    return strong_ordering::equivalent;<br>
+  else<br>
+    static_assert(_Cat != _Cat, "unhandled case");<br>
+}<br>
+} // namespace __comp_detail<br>
+<br>
+// [cmp.common], common comparison category type<br>
+template<class... _Ts><br>
+struct _LIBCPP_TEMPLATE_VIS common_comparison_category {<br>
+  using type = decltype(__comp_detail::__get_<wbr>comp_type<_Ts...>());<br>
+};<br>
+<br>
+template<class... _Ts><br>
+using common_comparison_category_t = typename common_comparison_category<_<wbr>Ts...>::type;<br>
+<br>
+// [cmp.alg], comparison algorithms<br>
+// TODO: unimplemented<br>
+template<class _Tp> constexpr strong_ordering strong_order(const _Tp& __lhs, const _Tp& __rhs);<br>
+template<class _Tp> constexpr weak_ordering weak_order(const _Tp& __lhs, const _Tp& __rhs);<br>
+template<class _Tp> constexpr partial_ordering partial_order(const _Tp& __lhs, const _Tp& __rhs);<br>
+template<class _Tp> constexpr strong_equality strong_equal(const _Tp& __lhs, const _Tp& __rhs);<br>
+template<class _Tp> constexpr weak_equality weak_equal(const _Tp& __lhs, const _Tp& __rhs);<br>
+<br>
+#endif // _LIBCPP_STD_VER > 17<br>
+<br>
+_LIBCPP_END_NAMESPACE_STD<br>
+<br>
+#endif // _LIBCPP_COMPARE<br>
<br>
Modified: libcxx/trunk/include/module.<wbr>modulemap<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/module.modulemap?rev=329460&r1=329459&r2=329460&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/libcxx/trunk/include/<wbr>module.modulemap?rev=329460&<wbr>r1=329459&r2=329460&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- libcxx/trunk/include/module.<wbr>modulemap (original)<br>
+++ libcxx/trunk/include/module.<wbr>modulemap Fri Apr  6 14:37:23 2018<br>
@@ -243,6 +243,10 @@ module std [system] {<br>
     header "codecvt"<br>
     export *<br>
   }<br>
+  module compare {<br>
+    header "compare"<br>
+    export *<br>
+  }<br>
   module complex {<br>
     header "complex"<br>
     export *<br>
<br>
Modified: libcxx/trunk/test/libcxx/<wbr>double_include.sh.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/libcxx/double_include.sh.cpp?rev=329460&r1=329459&r2=329460&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/libcxx/trunk/test/<wbr>libcxx/double_include.sh.cpp?<wbr>rev=329460&r1=329459&r2=<wbr>329460&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- libcxx/trunk/test/libcxx/<wbr>double_include.sh.cpp (original)<br>
+++ libcxx/trunk/test/libcxx/<wbr>double_include.sh.cpp Fri Apr  6 14:37:23 2018<br>
@@ -41,6 +41,7 @@<br>
 #include <clocale><br>
 #include <cmath><br>
 #include <codecvt><br>
+#include <compare><br>
 #include <complex><br>
 #include <complex.h><br>
 #include <condition_variable><br>
<br>
Added: libcxx/trunk/test/libcxx/<wbr>language.support/cmp/version.<wbr>pass.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/libcxx/language.support/cmp/version.pass.cpp?rev=329460&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/libcxx/trunk/test/<wbr>libcxx/language.support/cmp/<wbr>version.pass.cpp?rev=329460&<wbr>view=auto</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- libcxx/trunk/test/libcxx/<wbr>language.support/cmp/version.<wbr>pass.cpp (added)<br>
+++ libcxx/trunk/test/libcxx/<wbr>language.support/cmp/version.<wbr>pass.cpp Fri Apr  6 14:37:23 2018<br>
@@ -0,0 +1,20 @@<br>
+//===------------------------<wbr>------------------------------<wbr>----------------===//<br>
+//<br>
+//                     The LLVM Compiler Infrastructure<br>
+//<br>
+// This file is dual licensed under the MIT and the University of Illinois Open<br>
+// Source Licenses. See LICENSE.TXT for details.<br>
+//<br>
+//===------------------------<wbr>------------------------------<wbr>----------------===//<br>
+<br>
+// <compare><br>
+<br>
+#include <compare><br>
+<br>
+#ifndef _LIBCPP_VERSION<br>
+#error _LIBCPP_VERSION not defined<br>
+#endif<br>
+<br>
+int main()<br>
+{<br>
+}<br>
<br>
Added: libcxx/trunk/test/std/<wbr>language.support/cmp/cmp.<wbr>common/common_comparison_<wbr>category.pass.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/language.support/cmp/cmp.common/common_comparison_category.pass.cpp?rev=329460&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/libcxx/trunk/test/std/<wbr>language.support/cmp/cmp.<wbr>common/common_comparison_<wbr>category.pass.cpp?rev=329460&<wbr>view=auto</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- libcxx/trunk/test/std/<wbr>language.support/cmp/cmp.<wbr>common/common_comparison_<wbr>category.pass.cpp (added)<br>
+++ libcxx/trunk/test/std/<wbr>language.support/cmp/cmp.<wbr>common/common_comparison_<wbr>category.pass.cpp Fri Apr  6 14:37:23 2018<br>
@@ -0,0 +1,93 @@<br>
+//===------------------------<wbr>------------------------------<wbr>----------------===//<br>
+//<br>
+//                     The LLVM Compiler Infrastructure<br>
+//<br>
+// This file is dual licensed under the MIT and the University of Illinois Open<br>
+// Source Licenses. See LICENSE.TXT for details.<br>
+//<br>
+//===------------------------<wbr>------------------------------<wbr>----------------===//<br>
+<br>
+// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17<br>
+<br>
+// <compare><br>
+<br>
+// template <class ...Ts> struct common_comparison_category<br>
+// template <class ...Ts> using common_comparison_category_t<br>
+<br>
+<br>
+#include <compare><br>
+#include <type_traits><br>
+#include <cassert><br>
+<br>
+#include "test_macros.h"<br>
+<br>
+const volatile void* volatile sink;<br>
+<br>
+template <class Expect, class ...Args><br>
+void test_cat() {<br>
+  using Cat = std::common_comparison_<wbr>category<Args...>;<br>
+  using CatT = typename Cat::type;<br>
+  static_assert(std::is_same<<wbr>CatT, std::common_comparison_<wbr>category_t<Args...>>::value, "");<br>
+  static_assert(std::is_same<<wbr>CatT, Expect>::value, "expected different category");<br>
+};<br>
+<br>
+<br>
+// [class.spaceship]p4: The 'common comparison type' U of a possibly-empty list<br>
+//   of 'n' types T0, T1, ..., TN, is defined as follows:<br>
+int main() {<br>
+  using WE = std::weak_equality;<br>
+  using SE = std::strong_equality;<br>
+  using PO = std::partial_ordering;<br>
+  using WO = std::weak_ordering;<br>
+  using SO = std::strong_ordering;<br>
+<br>
+  // [class.spaceship]p4.1: If any Ti is not a comparison category tpe, U is void.<br>
+  {<br>
+    test_cat<void, void>();<br>
+    test_cat<void, int*>();<br>
+    test_cat<void, SO&>();<br>
+    test_cat<void, SO const>();<br>
+    test_cat<void, SO*>();<br>
+    test_cat<void, SO, void, SO>();<br>
+  }<br>
+<br>
+  // [class.spaceship]p4.2: Otherwise, if at least on Ti is<br>
+  // std::weak_equality, or at least one Ti is std::strong_equality and at least<br>
+  // one Tj is std::partial_ordering or std::weak_ordering, U is std::weak_equality<br>
+  {<br>
+    test_cat<WE, WE>();<br>
+    test_cat<WE, SO, WE, SO>();<br>
+    test_cat<WE, SE, SO, PO>();<br>
+    test_cat<WE, WO, SO, SE>();<br>
+  }<br>
+<br>
+  // [class.spaceship]p4.3: Otherwise, if at least one Ti is std::strong_equality,<br>
+  // U is std::strong_equality<br>
+  {<br>
+    test_cat<SE, SE>();<br>
+    test_cat<SE, SO, SE, SO>();<br>
+  }<br>
+<br>
+  // [class.spaceship]p4.4: Otherwise, if at least one Ti is std::partial_ordering,<br>
+  // U is std::partial_ordering<br>
+  {<br>
+    test_cat<PO, PO>();<br>
+    test_cat<PO, SO, PO, SO>();<br>
+    test_cat<PO, WO, PO, SO>();<br>
+  }<br>
+<br>
+  // [class.spaceship]p4.5: Otherwise, if at least one Ti is std::weak_ordering,<br>
+  // U is std::weak_ordering<br>
+  {<br>
+    test_cat<WO, WO>();<br>
+    test_cat<WO, SO, WO, SO>();<br>
+  }<br>
+<br>
+  // [class.spaceship]p4.6: Otherwise, U is std::strong_ordering. [Note: in<br>
+  // particular this is the result when n is 0. -- end note]<br>
+  {<br>
+    test_cat<SO>(); // empty type list<br>
+    test_cat<SO, SO>();<br>
+    test_cat<SO, SO, SO>();<br>
+  }<br>
+}<br>
<br>
Added: libcxx/trunk/test/std/<wbr>language.support/cmp/cmp.<wbr>partialord/partialord.pass.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/language.support/cmp/cmp.partialord/partialord.pass.cpp?rev=329460&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/libcxx/trunk/test/std/<wbr>language.support/cmp/cmp.<wbr>partialord/partialord.pass.<wbr>cpp?rev=329460&view=auto</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- libcxx/trunk/test/std/<wbr>language.support/cmp/cmp.<wbr>partialord/partialord.pass.cpp (added)<br>
+++ libcxx/trunk/test/std/<wbr>language.support/cmp/cmp.<wbr>partialord/partialord.pass.cpp Fri Apr  6 14:37:23 2018<br>
@@ -0,0 +1,164 @@<br>
+//===------------------------<wbr>------------------------------<wbr>----------------===//<br>
+//<br>
+//                     The LLVM Compiler Infrastructure<br>
+//<br>
+// This file is dual licensed under the MIT and the University of Illinois Open<br>
+// Source Licenses. See LICENSE.TXT for details.<br>
+//<br>
+//===------------------------<wbr>------------------------------<wbr>----------------===//<br>
+<br>
+// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17<br>
+<br>
+// <compare><br>
+<br>
+// class partial_ordering<br>
+<br>
+<br>
+#include <compare><br>
+#include <type_traits><br>
+#include <cassert><br>
+<br>
+#include "test_macros.h"<br>
+<br>
+const volatile void* volatile sink;<br>
+<br>
+void test_static_members() {<br>
+  DoNotOptimize(&std::partial_<wbr>ordering::less);<br>
+  DoNotOptimize(&std::partial_<wbr>ordering::equivalent);<br>
+  DoNotOptimize(&std::partial_<wbr>ordering::greater);<br>
+  DoNotOptimize(&std::partial_<wbr>ordering::unordered);<br>
+}<br>
+<br>
+void test_signatures() {<br>
+  auto& Eq = std::partial_ordering::<wbr>equivalent;<br>
+<br>
+  ASSERT_NOEXCEPT(Eq == 0);<br>
+  ASSERT_NOEXCEPT(0 == Eq);<br>
+  ASSERT_NOEXCEPT(Eq != 0);<br>
+  ASSERT_NOEXCEPT(0 != Eq);<br>
+  ASSERT_NOEXCEPT(0 < Eq);<br>
+  ASSERT_NOEXCEPT(Eq < 0);<br>
+  ASSERT_NOEXCEPT(0 <= Eq);<br>
+  ASSERT_NOEXCEPT(Eq <= 0);<br>
+  ASSERT_NOEXCEPT(0 > Eq);<br>
+  ASSERT_NOEXCEPT(Eq > 0);<br>
+  ASSERT_NOEXCEPT(0 >= Eq);<br>
+  ASSERT_NOEXCEPT(Eq >= 0);<br>
+#ifndef TEST_HAS_NO_SPACESHIP_OPERATOR<br>
+  ASSERT_NOEXCEPT(0 <=> Eq);<br>
+  ASSERT_NOEXCEPT(Eq <=> 0);<br>
+  ASSERT_SAME_TYPE(decltype(Eq <=> 0), std::partial_ordering);<br>
+  ASSERT_SAME_TYPE(decltype(0 <=> Eq), std::partial_ordering);<br>
+#endif<br>
+}<br>
+<br>
+constexpr bool test_conversion() {<br>
+  static_assert(std::is_<wbr>convertible<const std::partial_ordering, std::weak_equality>::value, "");<br>
+  { // value == 0<br>
+    auto V = std::partial_ordering::<wbr>equivalent;<br>
+    std::weak_equality WV = V;<br>
+    assert(WV == 0);<br>
+  }<br>
+  std::partial_ordering TestCases[] = {<br>
+      std::partial_ordering::less,<br>
+      std::partial_ordering::<wbr>greater,<br>
+      std::partial_ordering::<wbr>unordered<br>
+  };<br>
+  for (auto V : TestCases)<br>
+  { // value != 0<br>
+    std::weak_equality WV = V;<br>
+    assert(WV != 0);<br>
+  }<br>
+  return true;<br>
+}<br>
+<br>
+constexpr bool test_constexpr() {<br>
+  auto& Eq = std::partial_ordering::<wbr>equivalent;<br>
+  auto& Less = std::partial_ordering::less;<br>
+  auto& Greater = std::partial_ordering::<wbr>greater;<br>
+  auto& Unord = std::partial_ordering::<wbr>unordered;<br>
+  struct {<br>
+    std::partial_ordering Value;<br>
+    bool ExpectEq;<br>
+    bool ExpectNeq;<br>
+    bool ExpectLess;<br>
+    bool ExpectGreater;<br>
+  } TestCases[] = {<br>
+      {Eq, true, false, false, false},<br>
+      {Less, false, true, true, false},<br>
+      {Greater, false, true, false, true},<br>
+      {Unord, false, true, false, false}<br>
+  };<br>
+  for (auto TC : TestCases) {<br>
+    auto V = TC.Value;<br>
+    assert((V == 0) == TC.ExpectEq);<br>
+    assert((0 == V) == TC.ExpectEq);<br>
+    assert((V != 0) == TC.ExpectNeq);<br>
+    assert((0 != V) == TC.ExpectNeq);<br>
+<br>
+    assert((V < 0) == TC.ExpectLess);<br>
+    assert((V > 0) == TC.ExpectGreater);<br>
+    assert((V <= 0) == (TC.ExpectLess || TC.ExpectEq));<br>
+    assert((V >= 0) == (TC.ExpectGreater || TC.ExpectEq));<br>
+<br>
+    assert((0 < V) == TC.ExpectGreater);<br>
+    assert((0 > V) == TC.ExpectLess);<br>
+    assert((0 <= V) == (TC.ExpectGreater || TC.ExpectEq));<br>
+    assert((0 >= V) == (TC.ExpectLess || TC.ExpectEq));<br>
+  }<br>
+#ifndef TEST_HAS_NO_SPACESHIP_OPERATOR<br>
+  {<br>
+    std::partial_ordering res = (Eq <=> 0);<br>
+    ((void)res);<br>
+    res = (0 <=> Eq);<br>
+    ((void)res);<br>
+  }<br>
+  enum ExpectRes {<br>
+    ER_Greater,<br>
+    ER_Less,<br>
+    ER_Equiv,<br>
+    ER_Unord<br>
+  };<br>
+  struct {<br>
+    std::partial_ordering Value;<br>
+    ExpectRes Expect;<br>
+  } SpaceshipTestCases[] = {<br>
+      {std::partial_ordering::<wbr>equivalent, ER_Equiv},<br>
+      {std::partial_ordering::less, ER_Less},<br>
+      {std::partial_ordering::<wbr>greater, ER_Greater},<br>
+      {std::partial_ordering::<wbr>unordered, ER_Unord}<br>
+  };<br>
+  for (auto TC : SpaceshipTestCases)<br>
+  {<br>
+    std::partial_ordering Res = (0 <=> TC.Value);<br>
+    switch (TC.Expect) {<br>
+    case ER_Equiv:<br>
+      assert(Res == 0);<br>
+      assert(0 == Res);<br>
+      break;<br>
+    case ER_Less:<br>
+      assert(Res < 0);<br>
+      break;<br>
+    case ER_Greater:<br>
+      assert(Res > 0);<br>
+      break;<br>
+    case ER_Unord:<br>
+      assert(Res != 0);<br>
+      assert(0 != Res);<br>
+      assert((Res < 0) == false);<br>
+      assert((Res > 0) == false);<br>
+      assert((Res == 0) == false);<br>
+      break;<br>
+    }<br>
+  }<br>
+#endif<br>
+<br>
+  return true;<br>
+}<br>
+<br>
+int main() {<br>
+  test_static_members();<br>
+  test_signatures();<br>
+  static_assert(test_conversion(<wbr>), "conversion test failed");<br>
+  static_assert(test_constexpr()<wbr>, "constexpr test failed");<br>
+}<br>
<br>
Added: libcxx/trunk/test/std/<wbr>language.support/cmp/cmp.<wbr>strongeq/cmp.strongeq.pass.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/language.support/cmp/cmp.strongeq/cmp.strongeq.pass.cpp?rev=329460&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/libcxx/trunk/test/std/<wbr>language.support/cmp/cmp.<wbr>strongeq/cmp.strongeq.pass.<wbr>cpp?rev=329460&view=auto</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- libcxx/trunk/test/std/<wbr>language.support/cmp/cmp.<wbr>strongeq/cmp.strongeq.pass.cpp (added)<br>
+++ libcxx/trunk/test/std/<wbr>language.support/cmp/cmp.<wbr>strongeq/cmp.strongeq.pass.cpp Fri Apr  6 14:37:23 2018<br>
@@ -0,0 +1,96 @@<br>
+//===------------------------<wbr>------------------------------<wbr>----------------===//<br>
+//<br>
+//                     The LLVM Compiler Infrastructure<br>
+//<br>
+// This file is dual licensed under the MIT and the University of Illinois Open<br>
+// Source Licenses. See LICENSE.TXT for details.<br>
+//<br>
+//===------------------------<wbr>------------------------------<wbr>----------------===//<br>
+<br>
+// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17<br>
+<br>
+// <compare><br>
+<br>
+// class strong_equality<br>
+<br>
+<br>
+#include <compare><br>
+#include <type_traits><br>
+#include <cassert><br>
+<br>
+#include "test_macros.h"<br>
+<br>
+const volatile void* volatile sink;<br>
+<br>
+void test_static_members() {<br>
+  DoNotOptimize(&std::strong_<wbr>equality::equal);<br>
+  DoNotOptimize(&std::strong_<wbr>equality::nonequal);<br>
+  DoNotOptimize(&std::strong_<wbr>equality::equivalent);<br>
+  DoNotOptimize(&std::strong_<wbr>equality::nonequivalent);<br>
+}<br>
+<br>
+void test_signatures() {<br>
+  auto& Eq = std::strong_equality::<wbr>equivalent;<br>
+<br>
+  ASSERT_NOEXCEPT(Eq == 0);<br>
+  ASSERT_NOEXCEPT(0 == Eq);<br>
+  ASSERT_NOEXCEPT(Eq != 0);<br>
+  ASSERT_NOEXCEPT(0 != Eq);<br>
+#ifndef TEST_HAS_NO_SPACESHIP_OPERATOR<br>
+  ASSERT_NOEXCEPT(0 <=> Eq);<br>
+  ASSERT_NOEXCEPT(Eq <=> 0);<br>
+  ASSERT_SAME_TYPE(decltype(Eq <=> 0), std::strong_equality);<br>
+  ASSERT_SAME_TYPE(decltype(0 <=> Eq), std::strong_equality);<br>
+#endif<br>
+}<br>
+<br>
+void test_conversion() {<br>
+  constexpr std::weak_equality res = std::strong_equality::<wbr>equivalent;<br>
+  static_assert(res == 0, "");<br>
+  static_assert(std::is_<wbr>convertible<const std::strong_equality&,<br>
+      std::weak_equality>::value, "");<br>
+  static_assert(res == 0, "expected equal");<br>
+<br>
+  constexpr std::weak_equality neq_res = std::strong_equality::<wbr>nonequivalent;<br>
+  static_assert(neq_res != 0, "expected not equal");<br>
+}<br>
+<br>
+constexpr bool test_constexpr() {<br>
+  auto& Eq = std::strong_equality::equal;<br>
+  auto& NEq = std::strong_equality::<wbr>nonequal;<br>
+  auto& Equiv = std::strong_equality::<wbr>equivalent;<br>
+  auto& NEquiv = std::strong_equality::<wbr>nonequivalent;<br>
+  assert((Eq == 0) == true);<br>
+  assert((0 == Eq) == true);<br>
+  assert((Equiv == 0) == true);<br>
+  assert((0 == Equiv) == true);<br>
+  assert((NEq == 0) == false);<br>
+  assert((0 == NEq) == false);<br>
+  assert((NEquiv == 0) == false);<br>
+  assert((0 == NEquiv) == false);<br>
+<br>
+  assert((Eq != 0) == false);<br>
+  assert((0 != Eq) == false);<br>
+  assert((Equiv != 0) == false);<br>
+  assert((0 != Equiv) == false);<br>
+  assert((NEq != 0) == true);<br>
+  assert((0 != NEq) == true);<br>
+  assert((NEquiv != 0) == true);<br>
+  assert((0 != NEquiv) == true);<br>
+<br>
+#ifndef TEST_HAS_NO_SPACESHIP_OPERATOR<br>
+  std::strong_equality res = (Eq <=> 0);<br>
+  ((void)res);<br>
+  res = (0 <=> Eq);<br>
+  ((void)res);<br>
+#endif<br>
+<br>
+  return true;<br>
+}<br>
+<br>
+int main() {<br>
+  test_static_members();<br>
+  test_signatures();<br>
+  test_conversion();<br>
+  static_assert(test_constexpr()<wbr>, "constexpr test failed");<br>
+}<br>
<br>
Added: libcxx/trunk/test/std/<wbr>language.support/cmp/cmp.<wbr>strongord/strongord.pass.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/language.support/cmp/cmp.strongord/strongord.pass.cpp?rev=329460&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/libcxx/trunk/test/std/<wbr>language.support/cmp/cmp.<wbr>strongord/strongord.pass.cpp?<wbr>rev=329460&view=auto</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- libcxx/trunk/test/std/<wbr>language.support/cmp/cmp.<wbr>strongord/strongord.pass.cpp (added)<br>
+++ libcxx/trunk/test/std/<wbr>language.support/cmp/cmp.<wbr>strongord/strongord.pass.cpp Fri Apr  6 14:37:23 2018<br>
@@ -0,0 +1,212 @@<br>
+//===------------------------<wbr>------------------------------<wbr>----------------===//<br>
+//<br>
+//                     The LLVM Compiler Infrastructure<br>
+//<br>
+// This file is dual licensed under the MIT and the University of Illinois Open<br>
+// Source Licenses. See LICENSE.TXT for details.<br>
+//<br>
+//===------------------------<wbr>------------------------------<wbr>----------------===//<br>
+<br>
+// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17<br>
+<br>
+// <compare><br>
+<br>
+// class strong_ordering<br>
+<br>
+<br>
+#include <compare><br>
+#include <type_traits><br>
+#include <cassert><br>
+<br>
+#include "test_macros.h"<br>
+<br>
+const volatile void* volatile sink;<br>
+<br>
+void test_static_members() {<br>
+  DoNotOptimize(&std::strong_<wbr>ordering::less);<br>
+  DoNotOptimize(&std::strong_<wbr>ordering::equal);<br>
+  DoNotOptimize(&std::strong_<wbr>ordering::equivalent);<br>
+  DoNotOptimize(&std::strong_<wbr>ordering::greater);<br>
+}<br>
+<br>
+void test_signatures() {<br>
+  auto& Eq = std::strong_ordering::<wbr>equivalent;<br>
+<br>
+  ASSERT_NOEXCEPT(Eq == 0);<br>
+  ASSERT_NOEXCEPT(0 == Eq);<br>
+  ASSERT_NOEXCEPT(Eq != 0);<br>
+  ASSERT_NOEXCEPT(0 != Eq);<br>
+  ASSERT_NOEXCEPT(0 < Eq);<br>
+  ASSERT_NOEXCEPT(Eq < 0);<br>
+  ASSERT_NOEXCEPT(0 <= Eq);<br>
+  ASSERT_NOEXCEPT(Eq <= 0);<br>
+  ASSERT_NOEXCEPT(0 > Eq);<br>
+  ASSERT_NOEXCEPT(Eq > 0);<br>
+  ASSERT_NOEXCEPT(0 >= Eq);<br>
+  ASSERT_NOEXCEPT(Eq >= 0);<br>
+#ifndef TEST_HAS_NO_SPACESHIP_OPERATOR<br>
+  ASSERT_NOEXCEPT(0 <=> Eq);<br>
+  ASSERT_NOEXCEPT(Eq <=> 0);<br>
+  ASSERT_SAME_TYPE(decltype(Eq <=> 0), std::strong_ordering);<br>
+  ASSERT_SAME_TYPE(decltype(0 <=> Eq), std::strong_ordering);<br>
+#endif<br>
+}<br>
+<br>
+constexpr bool test_conversion() {<br>
+  static_assert(std::is_<wbr>convertible<const std::strong_ordering&,<br>
+      std::weak_equality>::value, "");<br>
+  { // value == 0<br>
+    auto V = std::strong_ordering::<wbr>equivalent;<br>
+    std::weak_equality WV = V;<br>
+    assert(WV == 0);<br>
+  }<br>
+  std::strong_ordering WeakTestCases[] = {<br>
+      std::strong_ordering::less,<br>
+      std::strong_ordering::greater,<br>
+  };<br>
+  for (auto V : WeakTestCases)<br>
+  { // value != 0<br>
+    std::weak_equality WV = V;<br>
+    assert(WV != 0);<br>
+  }<br>
+  static_assert(std::is_<wbr>convertible<const std::strong_ordering&,<br>
+      std::strong_equality>::value, "");<br>
+  { // value == 0<br>
+    auto V = std::strong_ordering::<wbr>equivalent;<br>
+    std::strong_equality WV = V;<br>
+    assert(WV == 0);<br>
+  }<br>
+  { // value == 0<br>
+    auto V = std::strong_ordering::equal;<br>
+    std::strong_equality WV = V;<br>
+    assert(WV == 0);<br>
+  }<br>
+  std::strong_ordering StrongTestCases[] = {<br>
+      std::strong_ordering::less,<br>
+      std::strong_ordering::greater,<br>
+  };<br>
+  for (auto V : StrongTestCases)<br>
+  { // value != 0<br>
+    std::strong_equality WV = V;<br>
+    assert(WV != 0);<br>
+  }<br>
+<br>
+  static_assert(std::is_<wbr>convertible<const std::strong_ordering&,<br>
+      std::partial_ordering>::value, "");<br>
+  { // value == 0<br>
+    auto V = std::strong_ordering::<wbr>equivalent;<br>
+    std::partial_ordering WV = V;<br>
+    assert(WV == 0);<br>
+  }<br>
+  { // value < 0<br>
+    auto V = std::strong_ordering::less;<br>
+    std::partial_ordering WV = V;<br>
+    assert(WV < 0);<br>
+  }<br>
+  { // value > 0<br>
+    auto V = std::strong_ordering::greater;<br>
+    std::partial_ordering WV = V;<br>
+    assert(WV > 0);<br>
+  }<br>
+<br>
+  static_assert(std::is_<wbr>convertible<const std::strong_ordering&,<br>
+      std::weak_ordering>::value, "");<br>
+  { // value == 0<br>
+    auto V = std::strong_ordering::<wbr>equivalent;<br>
+    std::weak_ordering WV = V;<br>
+    assert(WV == 0);<br>
+  }<br>
+  { // value < 0<br>
+    auto V = std::strong_ordering::less;<br>
+    std::weak_ordering WV = V;<br>
+    assert(WV < 0);<br>
+  }<br>
+  { // value > 0<br>
+    auto V = std::strong_ordering::greater;<br>
+    std::weak_ordering WV = V;<br>
+    assert(WV > 0);<br>
+  }<br>
+  return true;<br>
+}<br>
+<br>
+constexpr bool test_constexpr() {<br>
+  auto& Eq = std::strong_ordering::equal;<br>
+  auto& Equiv = std::strong_ordering::<wbr>equivalent;<br>
+  auto& Less = std::strong_ordering::less;<br>
+  auto& Greater = std::strong_ordering::greater;<br>
+  struct {<br>
+    std::strong_ordering Value;<br>
+    bool ExpectEq;<br>
+    bool ExpectNeq;<br>
+    bool ExpectLess;<br>
+    bool ExpectGreater;<br>
+  } TestCases[] = {<br>
+      {Eq, true, false, false, false},<br>
+      {Equiv, true, false, false, false},<br>
+      {Less, false, true, true, false},<br>
+      {Greater, false, true, false, true},<br>
+  };<br>
+  for (auto TC : TestCases) {<br>
+    auto V = TC.Value;<br>
+    assert((V == 0) == TC.ExpectEq);<br>
+    assert((0 == V) == TC.ExpectEq);<br>
+    assert((V != 0) == TC.ExpectNeq);<br>
+    assert((0 != V) == TC.ExpectNeq);<br>
+<br>
+    assert((V < 0) == TC.ExpectLess);<br>
+    assert((V > 0) == TC.ExpectGreater);<br>
+    assert((V <= 0) == (TC.ExpectLess || TC.ExpectEq));<br>
+    assert((V >= 0) == (TC.ExpectGreater || TC.ExpectEq));<br>
+<br>
+    assert((0 < V) == TC.ExpectGreater);<br>
+    assert((0 > V) == TC.ExpectLess);<br>
+    assert((0 <= V) == (TC.ExpectGreater || TC.ExpectEq));<br>
+    assert((0 >= V) == (TC.ExpectLess || TC.ExpectEq));<br>
+  }<br>
+#ifndef TEST_HAS_NO_SPACESHIP_OPERATOR<br>
+  {<br>
+    std::strong_ordering res = (Eq <=> 0);<br>
+    ((void)res);<br>
+    res = (0 <=> Eq);<br>
+    ((void)res);<br>
+  }<br>
+  enum ExpectRes {<br>
+    ER_Greater,<br>
+    ER_Less,<br>
+    ER_Equiv<br>
+  };<br>
+  struct {<br>
+    std::strong_ordering Value;<br>
+    ExpectRes Expect;<br>
+  } SpaceshipTestCases[] = {<br>
+      {std::strong_ordering::<wbr>equivalent, ER_Equiv},<br>
+      {std::strong_ordering::less, ER_Less},<br>
+      {std::strong_ordering::<wbr>greater, ER_Greater},<br>
+  };<br>
+  for (auto TC : SpaceshipTestCases)<br>
+  {<br>
+    std::strong_ordering Res = (0 <=> TC.Value);<br>
+    switch (TC.Expect) {<br>
+    case ER_Equiv:<br>
+      assert(Res == 0);<br>
+      assert(0 == Res);<br>
+      break;<br>
+    case ER_Less:<br>
+      assert(Res < 0);<br>
+      break;<br>
+    case ER_Greater:<br>
+      assert(Res > 0);<br>
+      break;<br>
+    }<br>
+  }<br>
+#endif<br>
+<br>
+  return true;<br>
+}<br>
+<br>
+int main() {<br>
+  test_static_members();<br>
+  test_signatures();<br>
+  static_assert(test_conversion(<wbr>), "conversion test failed");<br>
+  static_assert(test_constexpr()<wbr>, "constexpr test failed");<br>
+}<br>
<br>
Added: libcxx/trunk/test/std/<wbr>language.support/cmp/cmp.<wbr>weakeq/cmp.weakeq.pass.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/language.support/cmp/cmp.weakeq/cmp.weakeq.pass.cpp?rev=329460&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/libcxx/trunk/test/std/<wbr>language.support/cmp/cmp.<wbr>weakeq/cmp.weakeq.pass.cpp?<wbr>rev=329460&view=auto</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- libcxx/trunk/test/std/<wbr>language.support/cmp/cmp.<wbr>weakeq/cmp.weakeq.pass.cpp (added)<br>
+++ libcxx/trunk/test/std/<wbr>language.support/cmp/cmp.<wbr>weakeq/cmp.weakeq.pass.cpp Fri Apr  6 14:37:23 2018<br>
@@ -0,0 +1,70 @@<br>
+//===------------------------<wbr>------------------------------<wbr>----------------===//<br>
+//<br>
+//                     The LLVM Compiler Infrastructure<br>
+//<br>
+// This file is dual licensed under the MIT and the University of Illinois Open<br>
+// Source Licenses. See LICENSE.TXT for details.<br>
+//<br>
+//===------------------------<wbr>------------------------------<wbr>----------------===//<br>
+<br>
+// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17<br>
+<br>
+// <compare><br>
+<br>
+// class weak_equality<br>
+<br>
+<br>
+#include <compare><br>
+#include <cassert><br>
+#include "test_macros.h"<br>
+<br>
+const volatile void* volatile sink;<br>
+<br>
+void test_static_members() {<br>
+  DoNotOptimize(&std::weak_<wbr>equality::equivalent);<br>
+  DoNotOptimize(&std::weak_<wbr>equality::nonequivalent);<br>
+}<br>
+<br>
+void test_signatures() {<br>
+  auto& Eq = std::weak_equality::<wbr>equivalent;<br>
+<br>
+  ASSERT_NOEXCEPT(Eq == 0);<br>
+  ASSERT_NOEXCEPT(0 == Eq);<br>
+  ASSERT_NOEXCEPT(Eq != 0);<br>
+  ASSERT_NOEXCEPT(0 != Eq);<br>
+#ifndef TEST_HAS_NO_SPACESHIP_OPERATOR<br>
+  ASSERT_NOEXCEPT(0 <=> Eq);<br>
+  ASSERT_NOEXCEPT(Eq <=> 0);<br>
+  ASSERT_SAME_TYPE(decltype(Eq <=> 0), std::weak_equality);<br>
+  ASSERT_SAME_TYPE(decltype(0 <=> Eq), std::weak_equality);<br>
+#endif<br>
+}<br>
+<br>
+constexpr bool test_constexpr() {<br>
+  auto& Eq = std::weak_equality::<wbr>equivalent;<br>
+  auto& NEq = std::weak_equality::<wbr>nonequivalent;<br>
+  assert((Eq == 0) == true);<br>
+  assert((0 == Eq) == true);<br>
+  assert((NEq == 0) == false);<br>
+  assert((0 == NEq) == false);<br>
+<br>
+  assert((Eq != 0) == false);<br>
+  assert((0 != Eq) == false);<br>
+  assert((NEq != 0) == true);<br>
+  assert((0 != NEq) == true);<br>
+<br>
+#ifndef TEST_HAS_NO_SPACESHIP_OPERATOR<br>
+  std::weak_equality res = (Eq <=> 0);<br>
+  ((void)res);<br>
+  res = (0 <=> Eq);<br>
+  ((void)res);<br>
+#endif<br>
+<br>
+  return true;<br>
+}<br>
+<br>
+int main() {<br>
+  test_static_members();<br>
+  test_signatures();<br>
+  static_assert(test_constexpr()<wbr>, "constexpr test failed");<br>
+}<br>
<br>
Added: libcxx/trunk/test/std/<wbr>language.support/cmp/cmp.<wbr>weakord/weakord.pass.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/language.support/cmp/cmp.weakord/weakord.pass.cpp?rev=329460&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/libcxx/trunk/test/std/<wbr>language.support/cmp/cmp.<wbr>weakord/weakord.pass.cpp?rev=<wbr>329460&view=auto</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- libcxx/trunk/test/std/<wbr>language.support/cmp/cmp.<wbr>weakord/weakord.pass.cpp (added)<br>
+++ libcxx/trunk/test/std/<wbr>language.support/cmp/cmp.<wbr>weakord/weakord.pass.cpp Fri Apr  6 14:37:23 2018<br>
@@ -0,0 +1,169 @@<br>
+//===------------------------<wbr>------------------------------<wbr>----------------===//<br>
+//<br>
+//                     The LLVM Compiler Infrastructure<br>
+//<br>
+// This file is dual licensed under the MIT and the University of Illinois Open<br>
+// Source Licenses. See LICENSE.TXT for details.<br>
+//<br>
+//===------------------------<wbr>------------------------------<wbr>----------------===//<br>
+<br>
+// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17<br>
+<br>
+// <compare><br>
+<br>
+// class weak_ordering<br>
+<br>
+<br>
+#include <compare><br>
+#include <type_traits><br>
+#include <cassert><br>
+<br>
+#include "test_macros.h"<br>
+<br>
+const volatile void* volatile sink;<br>
+<br>
+void test_static_members() {<br>
+  DoNotOptimize(&std::weak_<wbr>ordering::less);<br>
+  DoNotOptimize(&std::weak_<wbr>ordering::equivalent);<br>
+  DoNotOptimize(&std::weak_<wbr>ordering::greater);<br>
+}<br>
+<br>
+void test_signatures() {<br>
+  auto& Eq = std::weak_ordering::<wbr>equivalent;<br>
+<br>
+  ASSERT_NOEXCEPT(Eq == 0);<br>
+  ASSERT_NOEXCEPT(0 == Eq);<br>
+  ASSERT_NOEXCEPT(Eq != 0);<br>
+  ASSERT_NOEXCEPT(0 != Eq);<br>
+  ASSERT_NOEXCEPT(0 < Eq);<br>
+  ASSERT_NOEXCEPT(Eq < 0);<br>
+  ASSERT_NOEXCEPT(0 <= Eq);<br>
+  ASSERT_NOEXCEPT(Eq <= 0);<br>
+  ASSERT_NOEXCEPT(0 > Eq);<br>
+  ASSERT_NOEXCEPT(Eq > 0);<br>
+  ASSERT_NOEXCEPT(0 >= Eq);<br>
+  ASSERT_NOEXCEPT(Eq >= 0);<br>
+#ifndef TEST_HAS_NO_SPACESHIP_OPERATOR<br>
+  ASSERT_NOEXCEPT(0 <=> Eq);<br>
+  ASSERT_NOEXCEPT(Eq <=> 0);<br>
+  ASSERT_SAME_TYPE(decltype(Eq <=> 0), std::weak_ordering);<br>
+  ASSERT_SAME_TYPE(decltype(0 <=> Eq), std::weak_ordering);<br>
+#endif<br>
+}<br>
+<br>
+constexpr bool test_conversion() {<br>
+  static_assert(std::is_<wbr>convertible<const std::weak_ordering&,<br>
+      std::weak_equality>::value, "");<br>
+  { // value == 0<br>
+    auto V = std::weak_ordering::<wbr>equivalent;<br>
+    std::weak_equality WV = V;<br>
+    assert(WV == 0);<br>
+  }<br>
+  std::weak_ordering WeakTestCases[] = {<br>
+      std::weak_ordering::less,<br>
+      std::weak_ordering::greater,<br>
+  };<br>
+  for (auto V : WeakTestCases)<br>
+  { // value != 0<br>
+    std::weak_equality WV = V;<br>
+    assert(WV != 0);<br>
+  }<br>
+  static_assert(std::is_<wbr>convertible<const std::weak_ordering&,<br>
+      std::partial_ordering>::value, "");<br>
+  { // value == 0<br>
+    auto V = std::weak_ordering::<wbr>equivalent;<br>
+    std::partial_ordering WV = V;<br>
+    assert(WV == 0);<br>
+  }<br>
+  { // value < 0<br>
+    auto V = std::weak_ordering::less;<br>
+    std::partial_ordering WV = V;<br>
+    assert(WV < 0);<br>
+  }<br>
+  { // value > 0<br>
+    auto V = std::weak_ordering::greater;<br>
+    std::partial_ordering WV = V;<br>
+    assert(WV > 0);<br>
+  }<br>
+  return true;<br>
+}<br>
+<br>
+constexpr bool test_constexpr() {<br>
+  auto& Eq = std::weak_ordering::<wbr>equivalent;<br>
+  auto& Less = std::weak_ordering::less;<br>
+  auto& Greater = std::weak_ordering::greater;<br>
+  struct {<br>
+    std::weak_ordering Value;<br>
+    bool ExpectEq;<br>
+    bool ExpectNeq;<br>
+    bool ExpectLess;<br>
+    bool ExpectGreater;<br>
+  } TestCases[] = {<br>
+      {Eq, true, false, false, false},<br>
+      {Less, false, true, true, false},<br>
+      {Greater, false, true, false, true},<br>
+  };<br>
+  for (auto TC : TestCases) {<br>
+    auto V = TC.Value;<br>
+    assert((V == 0) == TC.ExpectEq);<br>
+    assert((0 == V) == TC.ExpectEq);<br>
+    assert((V != 0) == TC.ExpectNeq);<br>
+    assert((0 != V) == TC.ExpectNeq);<br>
+<br>
+    assert((V < 0) == TC.ExpectLess);<br>
+    assert((V > 0) == TC.ExpectGreater);<br>
+    assert((V <= 0) == (TC.ExpectLess || TC.ExpectEq));<br>
+    assert((V >= 0) == (TC.ExpectGreater || TC.ExpectEq));<br>
+<br>
+    assert((0 < V) == TC.ExpectGreater);<br>
+    assert((0 > V) == TC.ExpectLess);<br>
+    assert((0 <= V) == (TC.ExpectGreater || TC.ExpectEq));<br>
+    assert((0 >= V) == (TC.ExpectLess || TC.ExpectEq));<br>
+  }<br>
+#ifndef TEST_HAS_NO_SPACESHIP_OPERATOR<br>
+  {<br>
+    std::weak_ordering res = (Eq <=> 0);<br>
+    ((void)res);<br>
+    res = (0 <=> Eq);<br>
+    ((void)res);<br>
+  }<br>
+  enum ExpectRes {<br>
+    ER_Greater,<br>
+    ER_Less,<br>
+    ER_Equiv<br>
+  };<br>
+  struct {<br>
+    std::weak_ordering Value;<br>
+    ExpectRes Expect;<br>
+  } SpaceshipTestCases[] = {<br>
+      {std::weak_ordering::<wbr>equivalent, ER_Equiv},<br>
+      {std::weak_ordering::less, ER_Less},<br>
+      {std::weak_ordering::greater, ER_Greater},<br>
+  };<br>
+  for (auto TC : SpaceshipTestCases)<br>
+  {<br>
+    std::weak_ordering Res = (0 <=> TC.Value);<br>
+    switch (TC.Expect) {<br>
+    case ER_Equiv:<br>
+      assert(Res == 0);<br>
+      assert(0 == Res);<br>
+      break;<br>
+    case ER_Less:<br>
+      assert(Res < 0);<br>
+      break;<br>
+    case ER_Greater:<br>
+      assert(Res > 0);<br>
+      break;<br>
+    }<br>
+  }<br>
+#endif<br>
+<br>
+  return true;<br>
+}<br>
+<br>
+int main() {<br>
+  test_static_members();<br>
+  test_signatures();<br>
+  static_assert(test_conversion(<wbr>), "conversion test failed");<br>
+  static_assert(test_constexpr()<wbr>, "constexpr test failed");<br>
+}<br>
<br>
Modified: libcxx/trunk/test/support/<wbr>test_macros.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/support/test_macros.h?rev=329460&r1=329459&r2=329460&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/libcxx/trunk/test/<wbr>support/test_macros.h?rev=<wbr>329460&r1=329459&r2=329460&<wbr>view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- libcxx/trunk/test/support/<wbr>test_macros.h (original)<br>
+++ libcxx/trunk/test/support/<wbr>test_macros.h Fri Apr  6 14:37:23 2018<br>
@@ -169,6 +169,11 @@<br>
 #define TEST_SAFE_STATIC<br>
 #endif<br>
<br>
+// FIXME: Fix this feature check when either (A) a compiler provides a complete<br>
+// implementation, or (b) a feature check macro is specified<br>
+#define TEST_HAS_NO_SPACESHIP_OPERATOR<br>
+<br>
+<br>
 #if TEST_STD_VER < 11<br>
 #define ASSERT_NOEXCEPT(...)<br>
 #define ASSERT_NOT_NOEXCEPT(...)<br>
<br>
<br>
______________________________<wbr>_________________<br>
cfe-commits mailing list<br>
<a href="mailto:cfe-commits@lists.llvm.org">cfe-commits@lists.llvm.org</a><br>
<a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/<wbr>mailman/listinfo/cfe-commits</a><br>
</blockquote></div><br></div></div>