diff --git a/llvm/include/llvm/ADT/STLExtras.h b/llvm/include/llvm/ADT/STLExtras.h index 23da931a63de1..d9c6b9ac5f1d7 100644 --- a/llvm/include/llvm/ADT/STLExtras.h +++ b/llvm/include/llvm/ADT/STLExtras.h @@ -2682,6 +2682,17 @@ template using has_sizeof = decltype(sizeof(T)); template constexpr bool is_incomplete_v = !is_detected::value; +// Detect types with equality comparison operators. +namespace detail { +template +using has_equality_comparison = + decltype(std::declval() == std::declval()); +} // namespace detail + +/// Detects when type `const T` can be compared for equality with `const U`. +template +constexpr bool has_equality_comparison_v = + is_detected::value; } // end namespace llvm namespace std { diff --git a/llvm/unittests/ADT/STLExtrasTest.cpp b/llvm/unittests/ADT/STLExtrasTest.cpp index fe71945e4a794..a2eb251c98588 100644 --- a/llvm/unittests/ADT/STLExtrasTest.cpp +++ b/llvm/unittests/ADT/STLExtrasTest.cpp @@ -1777,8 +1777,43 @@ TEST(STLExtrasTest, ReverseConditionally) { struct Foo; struct Bar {}; -static_assert(is_incomplete_v, "Foo is incomplete"); -static_assert(!is_incomplete_v, "Bar is defined"); +TEST(STLExtrasTest, HasEqualityComparison) { + static_assert(is_incomplete_v, "Foo is incomplete"); + static_assert(!is_incomplete_v, "Bar is defined"); + + struct NoEqualityComparison {}; + static_assert(!has_equality_comparison_v); + + // Mutating equality comparison doesn't count. + struct MutatingEqualityComparison { + bool operator==(MutatingEqualityComparison &Other) { return false; } + }; + static_assert(!has_equality_comparison_v); + + struct PrivateEqualityComparison { + private: + bool operator==(const PrivateEqualityComparison &Other) const { + return false; + } + }; + static_assert(!has_equality_comparison_v); + + struct PublicEqualityComparison { + bool operator==(const PublicEqualityComparison &Other) const { + return false; + } + }; + static_assert(has_equality_comparison_v); + + struct StructA {}; + struct StructB { + bool operator==(const StructA &Other) const { return false; } + }; + static_assert(!has_equality_comparison_v); + static_assert(has_equality_comparison_v); + + SUCCEED(); +} TEST(STLExtrasTest, Search) { // Test finding a subsequence in the middle.