[llvm] d37fa5a - Revert "[ADT] Remove CRTP from FoldingSet and ContextualFoldingSet (NFC)" (#216957)
via llvm-commits
llvm-commits at lists.llvm.org
Tue Aug 18 02:26:42 PDT 2026
Author: Simon Pilgrim
Date: 2026-08-18T10:26:37+01:00
New Revision: d37fa5a838db382c4138e9612616cb0ac4ef448a
URL: https://github.com/llvm/llvm-project/commit/d37fa5a838db382c4138e9612616cb0ac4ef448a
DIFF: https://github.com/llvm/llvm-project/commit/d37fa5a838db382c4138e9612616cb0ac4ef448a.diff
LOG: Revert "[ADT] Remove CRTP from FoldingSet and ContextualFoldingSet (NFC)" (#216957)
Reverts llvm/llvm-project#216830 due to breakage on msvc builds
Added:
Modified:
llvm/include/llvm/ADT/FoldingSet.h
Removed:
################################################################################
diff --git a/llvm/include/llvm/ADT/FoldingSet.h b/llvm/include/llvm/ADT/FoldingSet.h
index a200d9bd69782..52ee163cb739c 100644
--- a/llvm/include/llvm/ADT/FoldingSet.h
+++ b/llvm/include/llvm/ADT/FoldingSet.h
@@ -113,8 +113,6 @@ class StringRef;
/// This class provides default implementations for FoldingSetTrait
/// implementations.
template <typename T> struct DefaultFoldingSetTrait {
- struct ContextStorage {};
-
static void Profile(const T &X, FoldingSetNodeID &ID) { X.Profile(ID); }
static void Profile(T &X, FoldingSetNodeID &ID) { X.Profile(ID); }
@@ -144,12 +142,6 @@ struct FoldingSetTrait : public DefaultFoldingSetTrait<T> {};
/// Like DefaultFoldingSetTrait, but for ContextualFoldingSets.
template <typename T, typename Ctx> struct DefaultContextualFoldingSetTrait {
- struct ContextStorage {
- Ctx Context;
- explicit ContextStorage(Ctx Context) : Context(Context) {}
- Ctx getContext() const { return Context; }
- };
-
static void Profile(T &X, FoldingSetNodeID &ID, Ctx Context) {
X.Profile(ID, Context);
}
@@ -441,50 +433,11 @@ inline unsigned DefaultContextualFoldingSetTrait<T, Ctx>::ComputeHash(
//===----------------------------------------------------------------------===//
/// An implementation detail that lets us share code between FoldingSet and
/// ContextualFoldingSet.
-template <class T, class Trait = FoldingSetTrait<T>>
-class FoldingSetImpl : public FoldingSetBase, public Trait::ContextStorage {
- static constexpr FoldingSetBase::FoldingSetInfo Info = {
- // GetNodeProfile
- [](const FoldingSetBase *Base, FoldingSetNode *N, FoldingSetNodeID &ID) {
- if constexpr (std::is_empty_v<typename Trait::ContextStorage>)
- Trait::Profile(*static_cast<T *>(N), ID);
- else
- Trait::Profile(
- *static_cast<T *>(N), ID,
- static_cast<const FoldingSetImpl *>(Base)->getContext());
- },
- // NodeEquals
- [](const FoldingSetBase *Base, FoldingSetNode *N,
- const FoldingSetNodeID &ID, unsigned IDHash,
- FoldingSetNodeID &TempID) {
- if constexpr (std::is_empty_v<typename Trait::ContextStorage>)
- return Trait::Equals(*static_cast<T *>(N), ID, IDHash, TempID);
- else
- return Trait::Equals(
- *static_cast<T *>(N), ID, IDHash, TempID,
- static_cast<const FoldingSetImpl *>(Base)->getContext());
- },
- // ComputeNodeHash
- [](const FoldingSetBase *Base, FoldingSetNode *N,
- FoldingSetNodeID &TempID) {
- if constexpr (std::is_empty_v<typename Trait::ContextStorage>)
- return Trait::ComputeHash(*static_cast<T *>(N), TempID);
- else
- return Trait::ComputeHash(
- *static_cast<T *>(N), TempID,
- static_cast<const FoldingSetImpl *>(Base)->getContext());
- }};
-
-public:
- explicit FoldingSetImpl(unsigned Log2InitSize = 6)
+template <class Derived, class T> class FoldingSetImpl : public FoldingSetBase {
+protected:
+ explicit FoldingSetImpl(unsigned Log2InitSize)
: FoldingSetBase(Log2InitSize) {}
- template <typename C, typename = std::enable_if_t<std::is_constructible_v<
- typename Trait::ContextStorage, C>>>
- explicit FoldingSetImpl(C &&Context, unsigned Log2InitSize = 6)
- : FoldingSetBase(Log2InitSize),
- Trait::ContextStorage(std::forward<C>(Context)) {}
-
FoldingSetImpl(FoldingSetImpl &&Arg) = default;
FoldingSetImpl &operator=(FoldingSetImpl &&RHS) = default;
~FoldingSetImpl() = default;
@@ -503,7 +456,9 @@ class FoldingSetImpl : public FoldingSetBase, public Trait::ContextStorage {
/// Increase the number of buckets such that adding the \p EltCount th node
/// won't cause a rebucket operation. reserve is permitted to allocate more
/// space than requested by EltCount.
- void reserve(unsigned EltCount) { FoldingSetBase::reserve(EltCount, Info); }
+ void reserve(unsigned EltCount) {
+ FoldingSetBase::reserve(EltCount, Derived::getFoldingSetInfo());
+ }
/// Remove a node from the folding set, returning true if one
/// was removed or false if the node was not in the folding set.
@@ -512,21 +467,22 @@ class FoldingSetImpl : public FoldingSetBase, public Trait::ContextStorage {
/// If there is an existing simple Node exactly equal to the specified node,
/// return it. Otherwise, insert 'N' and return it instead.
T *GetOrInsertNode(T *N) {
- return static_cast<T *>(FoldingSetBase::GetOrInsertNode(N, Info));
+ return static_cast<T *>(
+ FoldingSetBase::GetOrInsertNode(N, Derived::getFoldingSetInfo()));
}
/// Look up the node specified by ID. If it exists, return it. If not,
/// return the insertion token that will make insertion faster.
T *FindNodeOrInsertPos(const FoldingSetNodeID &ID, void *&InsertPos) {
- return static_cast<T *>(
- FoldingSetBase::FindNodeOrInsertPos(ID, InsertPos, Info));
+ return static_cast<T *>(FoldingSetBase::FindNodeOrInsertPos(
+ ID, InsertPos, Derived::getFoldingSetInfo()));
}
/// Insert the specified node into the folding set, knowing that
/// it is not already in the folding set. InsertPos must be obtained from
/// FindNodeOrInsertPos.
void InsertNode(T *N, void *InsertPos) {
- FoldingSetBase::InsertNode(N, InsertPos, Info);
+ FoldingSetBase::InsertNode(N, InsertPos, Derived::getFoldingSetInfo());
}
/// Insert the specified node into the folding set, knowing that it is not
@@ -547,8 +503,47 @@ class FoldingSetImpl : public FoldingSetBase, public Trait::ContextStorage {
/// moved-from state is not a valid state for anything other than
/// move-assigning and destroying. This is primarily to enable movable APIs
/// that incorporate these objects.
-template <class T, class Trait = FoldingSetTrait<T>>
-using FoldingSet = FoldingSetImpl<T, Trait>;
+template <class T> class FoldingSet : public FoldingSetImpl<FoldingSet<T>, T> {
+ using Super = FoldingSetImpl<FoldingSet, T>;
+ using Node = typename Super::Node;
+
+ /// Each instantiation of the FoldingSet needs to provide a
+ /// way to convert nodes into a unique specifier.
+ static void GetNodeProfile(const FoldingSetBase *, Node *N,
+ FoldingSetNodeID &ID) {
+ T *TN = static_cast<T *>(N);
+ FoldingSetTrait<T>::Profile(*TN, ID);
+ }
+
+ /// Instantiations may optionally provide a way to compare a
+ /// node with a specified ID.
+ static bool NodeEquals(const FoldingSetBase *, Node *N,
+ const FoldingSetNodeID &ID, unsigned IDHash,
+ FoldingSetNodeID &TempID) {
+ T *TN = static_cast<T *>(N);
+ return FoldingSetTrait<T>::Equals(*TN, ID, IDHash, TempID);
+ }
+
+ /// Instantiations may optionally provide a way to compute a
+ /// hash value directly from a node.
+ static unsigned ComputeNodeHash(const FoldingSetBase *, Node *N,
+ FoldingSetNodeID &TempID) {
+ T *TN = static_cast<T *>(N);
+ return FoldingSetTrait<T>::ComputeHash(*TN, TempID);
+ }
+
+ static const FoldingSetBase::FoldingSetInfo &getFoldingSetInfo() {
+ static constexpr FoldingSetBase::FoldingSetInfo Info = {
+ GetNodeProfile, NodeEquals, ComputeNodeHash};
+ return Info;
+ }
+ friend Super;
+
+public:
+ explicit FoldingSet(unsigned Log2InitSize = 6) : Super(Log2InitSize) {}
+ FoldingSet(FoldingSet &&Arg) = default;
+ FoldingSet &operator=(FoldingSet &&RHS) = default;
+};
//===----------------------------------------------------------------------===//
/// This template class is a further refinement of FoldingSet which provides a
@@ -559,8 +554,58 @@ using FoldingSet = FoldingSetImpl<T, Trait>;
/// function with signature
/// void Profile(FoldingSetNodeID &, Ctx);
template <class T, class Ctx>
-using ContextualFoldingSet =
- FoldingSetImpl<T, ContextualFoldingSetTrait<T, Ctx>>;
+class ContextualFoldingSet
+ : public FoldingSetImpl<ContextualFoldingSet<T, Ctx>, T> {
+ // Unfortunately, this can't derive from FoldingSet<T> because the
+ // construction of the vtable for FoldingSet<T> requires
+ // FoldingSet<T>::GetNodeProfile to be instantiated, which in turn
+ // requires a single-argument T::Profile().
+
+ using Super = FoldingSetImpl<ContextualFoldingSet, T>;
+ using Node = typename Super::Node;
+
+ Ctx Context;
+
+ static const Ctx &getContext(const FoldingSetBase *Base) {
+ return static_cast<const ContextualFoldingSet *>(Base)->Context;
+ }
+
+ /// Each instantiatation of the FoldingSet needs to provide a way to convert
+ /// nodes into a unique specifier.
+ static void GetNodeProfile(const FoldingSetBase *Base, Node *N,
+ FoldingSetNodeID &ID) {
+ T *TN = static_cast<T *>(N);
+ ContextualFoldingSetTrait<T, Ctx>::Profile(*TN, ID, getContext(Base));
+ }
+
+ static bool NodeEquals(const FoldingSetBase *Base, Node *N,
+ const FoldingSetNodeID &ID, unsigned IDHash,
+ FoldingSetNodeID &TempID) {
+ T *TN = static_cast<T *>(N);
+ return ContextualFoldingSetTrait<T, Ctx>::Equals(*TN, ID, IDHash, TempID,
+ getContext(Base));
+ }
+
+ static unsigned ComputeNodeHash(const FoldingSetBase *Base, Node *N,
+ FoldingSetNodeID &TempID) {
+ T *TN = static_cast<T *>(N);
+ return ContextualFoldingSetTrait<T, Ctx>::ComputeHash(*TN, TempID,
+ getContext(Base));
+ }
+
+ static const FoldingSetBase::FoldingSetInfo &getFoldingSetInfo() {
+ static constexpr FoldingSetBase::FoldingSetInfo Info = {
+ GetNodeProfile, NodeEquals, ComputeNodeHash};
+ return Info;
+ }
+ friend Super;
+
+public:
+ explicit ContextualFoldingSet(Ctx Context, unsigned Log2InitSize = 6)
+ : Super(Log2InitSize), Context(Context) {}
+
+ Ctx getContext() const { return Context; }
+};
//===----------------------------------------------------------------------===//
/// This template class combines a FoldingSet and a vector to provide the
More information about the llvm-commits
mailing list