[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
Fri May 26 06:00:46 PDT 2023


sammccall created this revision.
sammccall added reviewers: kadircet, IncludeGuardian.
Herald added a project: All.
sammccall requested review of this revision.
Herald added a project: LLVM.
Herald added a subscriber: llvm-commits.

Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D151557

Files:
  llvm/include/llvm/ADT/DenseMapInfo.h


Index: llvm/include/llvm/ADT/DenseMapInfo.h
===================================================================
--- llvm/include/llvm/ADT/DenseMapInfo.h
+++ llvm/include/llvm/ADT/DenseMapInfo.h
@@ -290,6 +290,32 @@
   }
 };
 
+namespace detail {
+// Helpers for DenseMapInfo<std::variant>
+
+// Returns a pointer to std::get<Index>(Val), where Index is not constant.
+template <class V, size_t... Indices>
+static const void *variantGetDynamic(const V &Val, int Index,
+                                     std::index_sequence<Indices...>) {
+  const void *Result = nullptr;
+  unsigned I = 0;
+  (((I++ == Index) ? (Result = &std::get<Indices>(Val), true) : false) || ...);
+  return Result;
+}
+
+// Visitor to check equality of values stored in variants.
+// Assumes both values have the same type.
+struct EqVisitor {
+  const void *ErasedRHSVal; // Points to the value stored in B.
+
+  template <class T> bool operator()(const T &LHSVal) const {
+    const T &RHSVal = *reinterpret_cast<const T *>(ErasedRHSVal);
+    return DenseMapInfo<T>::eq(LHSVal, RHSVal);
+  }
+};
+
+} // namespace detail
+
 // Provide DenseMapInfo for variants whose all alternatives have DenseMapInfo.
 template <typename... Ts> struct DenseMapInfo<std::variant<Ts...>> {
   using Variant = std::variant<Ts...>;
@@ -318,7 +344,17 @@
   }
 
   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))
+    // This is surprisingly fiddly:
+    //  - there's no get() for a runtime index (see detail::variantGetDynamic)
+    //  - we know the types are the same, but std::visit(V, LHS, RHS) doesn't
+    // We erase the type held in RHS to void*, and dispatch over LHS.
+    return std::visit<bool>(
+        detail::EqVisitor{
+            dyn_get(RHS, RHS.index(), std::index_sequence_for<Ts...>{})},
+        LHS);
   }
 };
 } // end namespace llvm


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D151557.526036.patch
Type: text/x-patch
Size: 2043 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20230526/67cb7ef5/attachment.bin>


More information about the llvm-commits mailing list