[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