Distinguish the debug message for the case of self-move-assigned swiss tables. PiperOrigin-RevId: 671484965 Change-Id: Ia1da7db0db1f776d48c74efaeab7252445208088
diff --git a/absl/container/internal/raw_hash_set.h b/absl/container/internal/raw_hash_set.h index f5463fb..03ec5b0 100644 --- a/absl/container/internal/raw_hash_set.h +++ b/absl/container/internal/raw_hash_set.h
@@ -545,7 +545,10 @@ kAboveMaxValidCapacity = ~size_t{} - 100, kReentrance, kDestroyed, + + // These two must be last because we use `>= kMovedFrom` to mean moved-from. kMovedFrom, + kSelfMovedFrom, }; // Returns a pointer to a control byte group that can be used by empty tables. @@ -2911,7 +2914,7 @@ ABSL_ATTRIBUTE_REINITIALIZES void clear() { if (SwisstableGenerationsEnabled() && - capacity() == InvalidCapacity::kMovedFrom) { + capacity() >= InvalidCapacity::kMovedFrom) { common().set_capacity(DefaultCapacity()); } AssertNotDebugCapacity(); @@ -3596,7 +3599,7 @@ inline void destructor_impl() { if (SwisstableGenerationsEnabled() && - capacity() == InvalidCapacity::kMovedFrom) { + capacity() >= InvalidCapacity::kMovedFrom) { return; } if (capacity() == 0) return; @@ -3778,7 +3781,8 @@ // than using NDEBUG) to avoid issues in which NDEBUG is enabled in some // translation units but not in others. if (SwisstableGenerationsEnabled()) { - that.common().set_capacity(InvalidCapacity::kMovedFrom); + that.common().set_capacity(this == &that ? InvalidCapacity::kSelfMovedFrom + : InvalidCapacity::kMovedFrom); } if (!SwisstableGenerationsEnabled() || capacity() == DefaultCapacity() || capacity() > kAboveMaxValidCapacity) { @@ -3908,7 +3912,12 @@ assert(capacity() != InvalidCapacity::kDestroyed && "Use of destroyed hash table."); if (SwisstableGenerationsEnabled() && - ABSL_PREDICT_FALSE(capacity() == InvalidCapacity::kMovedFrom)) { + ABSL_PREDICT_FALSE(capacity() >= InvalidCapacity::kMovedFrom)) { + if (capacity() == InvalidCapacity::kSelfMovedFrom) { + // If this log triggers, then a hash table was move-assigned to itself + // and then used again later without being reinitialized. + ABSL_RAW_LOG(FATAL, "Use of self-move-assigned hash table."); + } ABSL_RAW_LOG(FATAL, "Use of moved-from hash table."); } }
diff --git a/absl/container/internal/raw_hash_set_test.cc b/absl/container/internal/raw_hash_set_test.cc index f69fca3..79c00fd 100644 --- a/absl/container/internal/raw_hash_set_test.cc +++ b/absl/container/internal/raw_hash_set_test.cc
@@ -2093,7 +2093,7 @@ t = std::move(*&t); if (SwisstableGenerationsEnabled()) { // NOLINTNEXTLINE(bugprone-use-after-move) - EXPECT_DEATH_IF_SUPPORTED(t.contains("a"), ""); + EXPECT_DEATH_IF_SUPPORTED(t.contains("a"), "self-move-assigned"); } // As long as we don't crash, it's fine. } @@ -3689,14 +3689,14 @@ t1.insert(1); t2 = std::move(t1); // NOLINTNEXTLINE(bugprone-use-after-move) - EXPECT_DEATH_IF_SUPPORTED(t1.contains(1), ""); + EXPECT_DEATH_IF_SUPPORTED(t1.contains(1), "moved-from"); } { ABSL_ATTRIBUTE_UNUSED IntTable t1; t1.insert(1); ABSL_ATTRIBUTE_UNUSED IntTable t2(std::move(t1)); // NOLINTNEXTLINE(bugprone-use-after-move) - EXPECT_DEATH_IF_SUPPORTED(t1.contains(1), ""); + EXPECT_DEATH_IF_SUPPORTED(t1.contains(1), "moved-from"); t1.clear(); // Clearing a moved-from table is allowed. } }