Files
TheRock/compiler/amd-llvm/libcxx/test/std/utilities/variant/variant.relops/relops.pass.cpp
T
derek.holloway 7502bf64a4
CodeQL / Analyze (actions) (push) Canceled after 0s
CodeQL / Analyze (python) (push) Canceled after 0s
pre-commit / pre-commit (push) Canceled after 0s
Multi-Arch CI / setup (push) Canceled after 0s
Publish build_manylinux_x86_64 images / publish_build_manylinux_x86_64 (push) Canceled after 0s
Setup (Multi-Arch) / setup (push) Canceled after 0s
Multi-Arch CI / Linux::${{ fromJSON(needs.setup.outputs.linux_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubi10 image / publish_no_rocm_image_ubi10 (push) Canceled after 0s
Multi-Arch CI / Windows::${{ fromJSON(needs.setup.outputs.windows_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Multi-Arch CI / Manifest Diff (push) Canceled after 0s
TheRock Manifest Diff Report / Generate Manifest Diff Report (push) Canceled after 0s
Multi-Arch CI / CI Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_ocl_rt images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_rocgdb images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Unit Tests / Unit Tests :: ubuntu-24.04 (push) Canceled after 0s
Unit Tests / Unit Tests :: windows-2022 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_media (push) Canceled after 0s
Unit Tests / Unit Tests Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_openmpi (push) Canceled after 0s
Flatten subprojects into a single base monorepo
2026-09-02 16:34:47 -07:00

392 lines
12 KiB
C++

//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
// UNSUPPORTED: c++03, c++11, c++14
// <variant>
// template <class ...Types>
// constexpr bool
// operator==(variant<Types...> const&, variant<Types...> const&) noexcept;
//
// template <class ...Types>
// constexpr bool
// operator!=(variant<Types...> const&, variant<Types...> const&) noexcept;
//
// template <class ...Types>
// constexpr bool
// operator<(variant<Types...> const&, variant<Types...> const&) noexcept;
//
// template <class ...Types>
// constexpr bool
// operator>(variant<Types...> const&, variant<Types...> const&) noexcept;
//
// template <class ...Types>
// constexpr bool
// operator<=(variant<Types...> const&, variant<Types...> const&) noexcept;
//
// template <class ...Types>
// constexpr bool
// operator>=(variant<Types...> const&, variant<Types...> const&) noexcept;
#include <cassert>
#include <type_traits>
#include <utility>
#include <variant>
#include "test_comparisons.h"
#include "test_macros.h"
#if TEST_STD_VER >= 26
// Test SFINAE.
// ==
static_assert(HasOperatorEqual<std::variant<EqualityComparable>>);
static_assert(HasOperatorEqual<std::variant<EqualityComparable, int, long>>);
static_assert(!HasOperatorEqual<std::variant<NonComparable>>);
static_assert(!HasOperatorEqual<std::variant<NonComparable, EqualityComparable>>);
// >
static_assert(HasOperatorGreaterThan<std::variant<ThreeWayComparable>>);
static_assert(HasOperatorGreaterThan<std::variant<ThreeWayComparable, int, long>>);
static_assert(!HasOperatorGreaterThan<std::variant<NonComparable>>);
static_assert(!HasOperatorGreaterThan<std::variant<NonComparable, ThreeWayComparable>>);
// >=
static_assert(HasOperatorGreaterThanEqual<std::variant<ThreeWayComparable>>);
static_assert(HasOperatorGreaterThanEqual<std::variant<ThreeWayComparable, int, long>>);
static_assert(!HasOperatorGreaterThanEqual<std::variant<NonComparable>>);
static_assert(!HasOperatorGreaterThanEqual<std::variant<NonComparable, ThreeWayComparable>>);
// <
static_assert(HasOperatorLessThan<std::variant<ThreeWayComparable>>);
static_assert(HasOperatorLessThan<std::variant<ThreeWayComparable, int, long>>);
static_assert(!HasOperatorLessThan<std::variant<NonComparable>>);
static_assert(!HasOperatorLessThan<std::variant<NonComparable, ThreeWayComparable>>);
// <=
static_assert(HasOperatorLessThanEqual<std::variant<ThreeWayComparable>>);
static_assert(HasOperatorLessThanEqual<std::variant<ThreeWayComparable, int, long>>);
static_assert(!HasOperatorLessThanEqual<std::variant<NonComparable>>);
static_assert(!HasOperatorLessThanEqual<std::variant<NonComparable, ThreeWayComparable>>);
// !=
static_assert(HasOperatorNotEqual<std::variant<EqualityComparable>>);
static_assert(HasOperatorNotEqual<std::variant<EqualityComparable, int, long>>);
static_assert(!HasOperatorNotEqual<std::variant<NonComparable>>);
static_assert(!HasOperatorNotEqual<std::variant<NonComparable, EqualityComparable>>);
#endif
#ifndef TEST_HAS_NO_EXCEPTIONS
struct MakeEmptyT {
MakeEmptyT() = default;
MakeEmptyT(MakeEmptyT &&) { throw 42; }
MakeEmptyT &operator=(MakeEmptyT &&) { throw 42; }
};
inline bool operator==(const MakeEmptyT &, const MakeEmptyT &) {
assert(false);
return false;
}
inline bool operator!=(const MakeEmptyT &, const MakeEmptyT &) {
assert(false);
return false;
}
inline bool operator<(const MakeEmptyT &, const MakeEmptyT &) {
assert(false);
return false;
}
inline bool operator<=(const MakeEmptyT &, const MakeEmptyT &) {
assert(false);
return false;
}
inline bool operator>(const MakeEmptyT &, const MakeEmptyT &) {
assert(false);
return false;
}
inline bool operator>=(const MakeEmptyT &, const MakeEmptyT &) {
assert(false);
return false;
}
template <class Variant> void makeEmpty(Variant &v) {
Variant v2(std::in_place_type<MakeEmptyT>);
try {
v = std::move(v2);
assert(false);
} catch (...) {
assert(v.valueless_by_exception());
}
}
#endif // TEST_HAS_NO_EXCEPTIONS
struct MyBool {
bool value;
constexpr explicit MyBool(bool v) : value(v) {}
constexpr operator bool() const noexcept { return value; }
};
struct ComparesToMyBool {
int value = 0;
};
inline constexpr MyBool operator==(const ComparesToMyBool& LHS, const ComparesToMyBool& RHS) noexcept {
return MyBool(LHS.value == RHS.value);
}
inline constexpr MyBool operator!=(const ComparesToMyBool& LHS, const ComparesToMyBool& RHS) noexcept {
return MyBool(LHS.value != RHS.value);
}
inline constexpr MyBool operator<(const ComparesToMyBool& LHS, const ComparesToMyBool& RHS) noexcept {
return MyBool(LHS.value < RHS.value);
}
inline constexpr MyBool operator<=(const ComparesToMyBool& LHS, const ComparesToMyBool& RHS) noexcept {
return MyBool(LHS.value <= RHS.value);
}
inline constexpr MyBool operator>(const ComparesToMyBool& LHS, const ComparesToMyBool& RHS) noexcept {
return MyBool(LHS.value > RHS.value);
}
inline constexpr MyBool operator>=(const ComparesToMyBool& LHS, const ComparesToMyBool& RHS) noexcept {
return MyBool(LHS.value >= RHS.value);
}
template <class T1, class T2>
void test_equality_basic() {
{
using V = std::variant<T1, T2>;
constexpr V v1(std::in_place_index<0>, T1{42});
constexpr V v2(std::in_place_index<0>, T1{42});
static_assert(v1 == v2, "");
static_assert(v2 == v1, "");
static_assert(!(v1 != v2), "");
static_assert(!(v2 != v1), "");
}
{
using V = std::variant<T1, T2>;
constexpr V v1(std::in_place_index<0>, T1{42});
constexpr V v2(std::in_place_index<0>, T1{43});
static_assert(!(v1 == v2), "");
static_assert(!(v2 == v1), "");
static_assert(v1 != v2, "");
static_assert(v2 != v1, "");
}
{
using V = std::variant<T1, T2>;
constexpr V v1(std::in_place_index<0>, T1{42});
constexpr V v2(std::in_place_index<1>, T2{42});
static_assert(!(v1 == v2), "");
static_assert(!(v2 == v1), "");
static_assert(v1 != v2, "");
static_assert(v2 != v1, "");
}
{
using V = std::variant<T1, T2>;
constexpr V v1(std::in_place_index<1>, T2{42});
constexpr V v2(std::in_place_index<1>, T2{42});
static_assert(v1 == v2, "");
static_assert(v2 == v1, "");
static_assert(!(v1 != v2), "");
static_assert(!(v2 != v1), "");
}
}
void test_equality() {
test_equality_basic<int, long>();
test_equality_basic<ComparesToMyBool, int>();
test_equality_basic<int, ComparesToMyBool>();
test_equality_basic<ComparesToMyBool, ComparesToMyBool>();
#ifndef TEST_HAS_NO_EXCEPTIONS
{
using V = std::variant<int, MakeEmptyT>;
V v1;
V v2;
makeEmpty(v2);
assert(!(v1 == v2));
assert(!(v2 == v1));
assert(v1 != v2);
assert(v2 != v1);
}
{
using V = std::variant<int, MakeEmptyT>;
V v1;
makeEmpty(v1);
V v2;
assert(!(v1 == v2));
assert(!(v2 == v1));
assert(v1 != v2);
assert(v2 != v1);
}
{
using V = std::variant<int, MakeEmptyT>;
V v1;
makeEmpty(v1);
V v2;
makeEmpty(v2);
assert(v1 == v2);
assert(v2 == v1);
assert(!(v1 != v2));
assert(!(v2 != v1));
}
#endif
}
template <class Var>
constexpr bool test_less(const Var &l, const Var &r, bool expect_less,
bool expect_greater) {
static_assert(std::is_same_v<decltype(l < r), bool>, "");
static_assert(std::is_same_v<decltype(l <= r), bool>, "");
static_assert(std::is_same_v<decltype(l > r), bool>, "");
static_assert(std::is_same_v<decltype(l >= r), bool>, "");
return ((l < r) == expect_less) && (!(l >= r) == expect_less) &&
((l > r) == expect_greater) && (!(l <= r) == expect_greater);
}
template <class T1, class T2>
void test_relational_basic() {
{ // same index, same value
using V = std::variant<T1, T2>;
constexpr V v1(std::in_place_index<0>, T1{1});
constexpr V v2(std::in_place_index<0>, T1{1});
static_assert(test_less(v1, v2, false, false), "");
}
{ // same index, value < other_value
using V = std::variant<T1, T2>;
constexpr V v1(std::in_place_index<0>, T1{0});
constexpr V v2(std::in_place_index<0>, T1{1});
static_assert(test_less(v1, v2, true, false), "");
}
{ // same index, value > other_value
using V = std::variant<T1, T2>;
constexpr V v1(std::in_place_index<0>, T1{1});
constexpr V v2(std::in_place_index<0>, T1{0});
static_assert(test_less(v1, v2, false, true), "");
}
{ // LHS.index() < RHS.index()
using V = std::variant<T1, T2>;
constexpr V v1(std::in_place_index<0>, T1{0});
constexpr V v2(std::in_place_index<1>, T2{0});
static_assert(test_less(v1, v2, true, false), "");
}
{ // LHS.index() > RHS.index()
using V = std::variant<T1, T2>;
constexpr V v1(std::in_place_index<1>, T2{0});
constexpr V v2(std::in_place_index<0>, T1{0});
static_assert(test_less(v1, v2, false, true), "");
}
}
void test_relational() {
test_relational_basic<int, long>();
test_relational_basic<ComparesToMyBool, int>();
test_relational_basic<int, ComparesToMyBool>();
test_relational_basic<ComparesToMyBool, ComparesToMyBool>();
#ifndef TEST_HAS_NO_EXCEPTIONS
{ // LHS.index() < RHS.index(), RHS is empty
using V = std::variant<int, MakeEmptyT>;
V v1;
V v2;
makeEmpty(v2);
assert(test_less(v1, v2, false, true));
}
{ // LHS.index() > RHS.index(), LHS is empty
using V = std::variant<int, MakeEmptyT>;
V v1;
makeEmpty(v1);
V v2;
assert(test_less(v1, v2, true, false));
}
{ // LHS.index() == RHS.index(), LHS and RHS are empty
using V = std::variant<int, MakeEmptyT>;
V v1;
makeEmpty(v1);
V v2;
makeEmpty(v2);
assert(test_less(v1, v2, false, false));
}
#endif
}
struct A1 {
bool operator==(const A1&) const { return true; }
bool operator!=(const A1&) const { return true; }
bool operator<(const A1&) const { return true; }
bool operator>(const A1&) const { return true; }
bool operator<=(const A1&) const { return true; }
bool operator>=(const A1&) const { return true; }
};
struct A2 {
bool operator==(const A2&) const { return true; }
bool operator!=(const A2&) const { return true; }
bool operator<(const A2&) const { return true; }
bool operator>(const A2&) const { return true; }
bool operator<=(const A2&) const { return true; }
bool operator>=(const A2&) const { return true; }
};
struct Array;
using Var1 = std::variant<A1, Array>;
using Var2 = std::variant<A2, Array>;
struct Array {
Var1* ptr;
template <class Other>
friend constexpr bool operator==(const Array& lhs, const Other& rhs) {
return *lhs.ptr == *rhs.ptr;
}
template <class Other>
friend constexpr bool operator!=(const Array& lhs, const Other& rhs) {
return *lhs.ptr != *rhs.ptr;
}
template <class Other>
friend constexpr bool operator<(const Array& lhs, const Other& rhs) {
return *lhs.ptr < *rhs.ptr;
}
template <class Other>
friend constexpr bool operator>(const Array& lhs, const Other& rhs) {
return *lhs.ptr > *rhs.ptr;
}
template <class Other>
friend constexpr bool operator<=(const Array& lhs, const Other& rhs) {
return *lhs.ptr <= *rhs.ptr;
}
template <class Other>
friend constexpr bool operator>=(const Array& lhs, const Other& rhs) {
return *lhs.ptr >= *rhs.ptr;
}
};
// See https://llvm.org/PR182232
void test_recursive() {
(void)(Var2{} == Var2{});
(void)(Var2{} != Var2{});
(void)(Var2{} < Var2{});
(void)(Var2{} > Var2{});
(void)(Var2{} <= Var2{});
(void)(Var2{} >= Var2{});
}
int main(int, char**) {
test_equality();
test_relational();
return 0;
}