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.
}
}