[llvm] [ADT] Clean up and fix FoldingSetBase move operations (PR #217453)

Kazu Hirata via llvm-commits llvm-commits at lists.llvm.org
Mon Aug 24 15:54:34 PDT 2026


https://github.com/kazutakahirata updated https://github.com/llvm/llvm-project/pull/217453

>From 0a7aa80be30b14c0a9f5f38fed74b4a67fa70612 Mon Sep 17 00:00:00 2001
From: Kazu Hirata <kazu at google.com>
Date: Mon, 24 Aug 2026 13:59:20 -0700
Subject: [PATCH] Rebase.

---
 llvm/include/llvm/ADT/FoldingSet.h |  6 +++---
 llvm/lib/Support/FoldingSet.cpp    | 19 +++++++++----------
 llvm/unittests/ADT/FoldingSet.cpp  | 17 +++++++++++++++++
 3 files changed, 29 insertions(+), 13 deletions(-)

diff --git a/llvm/include/llvm/ADT/FoldingSet.h b/llvm/include/llvm/ADT/FoldingSet.h
index 74d4b2f08bb19..9b324b337072c 100644
--- a/llvm/include/llvm/ADT/FoldingSet.h
+++ b/llvm/include/llvm/ADT/FoldingSet.h
@@ -299,14 +299,14 @@ class FoldingSetNodeID {
 class FoldingSetBase : public DebugEpochBase {
 protected:
   /// Array of bucket chains.
-  void **Buckets;
+  void **Buckets = nullptr;
 
   /// Length of the Buckets array.  Always a power of 2.
-  unsigned NumBuckets;
+  unsigned NumBuckets = 0;
 
   /// Number of nodes in the folding set. Growth occurs when NumNodes
   /// is greater than twice the number of buckets.
-  unsigned NumNodes;
+  unsigned NumNodes = 0;
 
   LLVM_ABI explicit FoldingSetBase(unsigned Log2InitSize);
   LLVM_ABI FoldingSetBase(FoldingSetBase &&Arg);
diff --git a/llvm/lib/Support/FoldingSet.cpp b/llvm/lib/Support/FoldingSet.cpp
index d4bd863fa9a3f..13aac74280978 100644
--- a/llvm/lib/Support/FoldingSet.cpp
+++ b/llvm/lib/Support/FoldingSet.cpp
@@ -184,23 +184,22 @@ FoldingSetBase::FoldingSetBase(unsigned Log2InitSize) {
 }
 
 FoldingSetBase::FoldingSetBase(FoldingSetBase &&Arg)
-    : Buckets(Arg.Buckets), NumBuckets(Arg.NumBuckets), NumNodes(Arg.NumNodes) {
+    : Buckets(std::exchange(Arg.Buckets, nullptr)),
+      NumBuckets(std::exchange(Arg.NumBuckets, 0)),
+      NumNodes(std::exchange(Arg.NumNodes, 0)) {
   Arg.incrementEpoch();
-  Arg.Buckets = nullptr;
-  Arg.NumBuckets = 0;
-  Arg.NumNodes = 0;
 }
 
 FoldingSetBase &FoldingSetBase::operator=(FoldingSetBase &&RHS) {
+  if (this == &RHS)
+    return *this;
+
   incrementEpoch();
   RHS.incrementEpoch();
   free(Buckets); // This may be null if the set is in a moved-from state.
-  Buckets = RHS.Buckets;
-  NumBuckets = RHS.NumBuckets;
-  NumNodes = RHS.NumNodes;
-  RHS.Buckets = nullptr;
-  RHS.NumBuckets = 0;
-  RHS.NumNodes = 0;
+  Buckets = std::exchange(RHS.Buckets, nullptr);
+  NumBuckets = std::exchange(RHS.NumBuckets, 0);
+  NumNodes = std::exchange(RHS.NumNodes, 0);
   return *this;
 }
 
diff --git a/llvm/unittests/ADT/FoldingSet.cpp b/llvm/unittests/ADT/FoldingSet.cpp
index ff0f253cf355a..168443b21a4ef 100644
--- a/llvm/unittests/ADT/FoldingSet.cpp
+++ b/llvm/unittests/ADT/FoldingSet.cpp
@@ -358,6 +358,23 @@ TEST(FoldingSetTest, ContextualFoldingSetBasic) {
   EXPECT_THAT(Set, SizeIs(0));
 }
 
+TEST(FoldingSetTest, SelfMoveAssignment) {
+  FoldingSet<TrivialPair> Set;
+  TrivialPair T1(10, 100);
+  Set.InsertNode(&T1);
+
+  // Route through a helper lambda to test self-move aliasing without triggering
+  // -Wself-move.
+  auto MoveAssign = [](FoldingSet<TrivialPair> &Dest,
+                       FoldingSet<TrivialPair> &&Src) {
+    Dest = std::move(Src);
+  };
+  MoveAssign(Set, std::move(Set));
+
+  EXPECT_EQ(1u, Set.size());
+  EXPECT_FALSE(Set.empty());
+}
+
 #if LLVM_ENABLE_ABI_BREAKING_CHECKS
 TEST(FoldingSetTest, InsertInvalidatesIterators) {
   FoldingSet<TrivialPair> Set;



More information about the llvm-commits mailing list