[llvm] 9e932e0 - [ADT] Fix DenseMapInfo<variant>::isEqual to delegate to DenseMapInfo, not ==

Sam McCall via llvm-commits llvm-commits at lists.llvm.org
Tue Jun 6 09:36:59 PDT 2023


Author: Sam McCall
Date: 2023-06-06T18:36:37+02:00
New Revision: 9e932e08a8300f3366ace04ba8fda4946db406b9

URL: https://github.com/llvm/llvm-project/commit/9e932e08a8300f3366ace04ba8fda4946db406b9
DIFF: https://github.com/llvm/llvm-project/commit/9e932e08a8300f3366ace04ba8fda4946db406b9.diff

LOG: [ADT] Fix DenseMapInfo<variant>::isEqual to delegate to DenseMapInfo, not ==

Differential Revision: https://reviews.llvm.org/D151557

Added: 
    

Modified: 
    llvm/include/llvm/ADT/DenseMapInfo.h
    llvm/unittests/ADT/DenseMapTest.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm/ADT/DenseMapInfo.h b/llvm/include/llvm/ADT/DenseMapInfo.h
index 1c00fb699cc22..2c227be0082ab 100644
--- a/llvm/include/llvm/ADT/DenseMapInfo.h
+++ b/llvm/include/llvm/ADT/DenseMapInfo.h
@@ -318,7 +318,22 @@ template <typename... Ts> struct DenseMapInfo<std::variant<Ts...>> {
   }
 
   static bool isEqual(const Variant &LHS, const Variant &RHS) {
-    return LHS == RHS;
+    if (LHS.index() != RHS.index())
+      return false;
+    if (LHS.valueless_by_exception())
+      return true;
+    // We want to dispatch to DenseMapInfo<T>::isEqual(LHS.get(I), RHS.get(I))
+    // We know the types are the same, but std::visit(V, LHS, RHS) doesn't.
+    // We erase the type held in LHS to void*, and dispatch over RHS.
+    const void *ErasedLHS =
+        std::visit([](const auto &LHS) -> const void * { return &LHS; }, LHS);
+    return std::visit(
+        [&](const auto &RHS) -> bool {
+          using T = std::remove_cv_t<std::remove_reference_t<decltype(RHS)>>;
+          return DenseMapInfo<T>::isEqual(*static_cast<const T *>(ErasedLHS),
+                                          RHS);
+        },
+        RHS);
   }
 };
 } // end namespace llvm

diff  --git a/llvm/unittests/ADT/DenseMapTest.cpp b/llvm/unittests/ADT/DenseMapTest.cpp
index 79d57d35265c2..ba5cd4c4fca4d 100644
--- a/llvm/unittests/ADT/DenseMapTest.cpp
+++ b/llvm/unittests/ADT/DenseMapTest.cpp
@@ -690,6 +690,10 @@ struct A {
 struct B : public A {
   using A::A;
 };
+
+struct AlwaysEqType {
+  bool operator==(const AlwaysEqType &RHS) const { return true; }
+};
 } // namespace
 
 namespace llvm {
@@ -702,6 +706,16 @@ struct DenseMapInfo<T, std::enable_if_t<std::is_base_of_v<A, T>>> {
     return LHS.value == RHS.value;
   }
 };
+
+template <> struct DenseMapInfo<AlwaysEqType> {
+  using T = AlwaysEqType;
+  static inline T getEmptyKey() { return {}; }
+  static inline T getTombstoneKey() { return {}; }
+  static unsigned getHashValue(const T &Val) { return 0; }
+  static bool isEqual(const T &LHS, const T &RHS) {
+    return false;
+  }
+};
 } // namespace llvm
 
 namespace {
@@ -725,16 +739,20 @@ TEST(DenseMapCustomTest, SFINAEMapInfo) {
 }
 
 TEST(DenseMapCustomTest, VariantSupport) {
-  using variant = std::variant<int, int>;
+  using variant = std::variant<int, int, AlwaysEqType>;
   DenseMap<variant, int> Map;
   variant Keys[] = {
       variant(std::in_place_index<0>, 1),
       variant(std::in_place_index<1>, 1),
+      variant(std::in_place_index<2>),
   };
   Map.try_emplace(Keys[0], 0);
   Map.try_emplace(Keys[1], 1);
   EXPECT_THAT(Map, testing::SizeIs(2));
   EXPECT_NE(DenseMapInfo<variant>::getHashValue(Keys[0]),
             DenseMapInfo<variant>::getHashValue(Keys[1]));
+  // Check that isEqual dispatches to isEqual of underlying type, and not to
+  // operator==.
+  EXPECT_FALSE(DenseMapInfo<variant>::isEqual(Keys[2], Keys[2]));
 }
 } // namespace


        


More information about the llvm-commits mailing list