[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