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

Sam McCall via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Tue Jun 6 09:37:01 PDT 2023


This revision was landed with ongoing or failed builds.
This revision was automatically updated to reflect the committed changes.
sammccall marked an inline comment as done.
Closed by commit rG9e932e08a830: [ADT] Fix DenseMapInfo<variant>::isEqual to delegate to DenseMapInfo, not == (authored by sammccall).

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D151557/new/

https://reviews.llvm.org/D151557

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


Index: llvm/unittests/ADT/DenseMapTest.cpp
===================================================================
--- llvm/unittests/ADT/DenseMapTest.cpp
+++ llvm/unittests/ADT/DenseMapTest.cpp
@@ -690,6 +690,10 @@
 struct B : public A {
   using A::A;
 };
+
+struct AlwaysEqType {
+  bool operator==(const AlwaysEqType &RHS) const { return true; }
+};
 } // namespace
 
 namespace llvm {
@@ -702,6 +706,16 @@
     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, 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
Index: llvm/include/llvm/ADT/DenseMapInfo.h
===================================================================
--- llvm/include/llvm/ADT/DenseMapInfo.h
+++ llvm/include/llvm/ADT/DenseMapInfo.h
@@ -318,7 +318,22 @@
   }
 
   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


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D151557.528906.patch
Type: text/x-patch
Size: 2666 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20230606/7cfd3295/attachment.bin>


More information about the llvm-commits mailing list