@@ -280,6 +280,15 @@ constexpr bool SwisstableGenerationsEnabled() { return false; }
280
280
constexpr size_t NumGenerationBytes () { return 0 ; }
281
281
#endif
282
282
283
+ // Returns true if we should assert that the table is not accessed after it has
284
+ // been destroyed or during the destruction of the table.
285
+ constexpr bool SwisstableAssertAccessToDestroyedTable () {
286
+ #ifndef NDEBUG
287
+ return true ;
288
+ #endif
289
+ return SwisstableGenerationsEnabled ();
290
+ }
291
+
283
292
template <typename AllocType>
284
293
void SwapAlloc (AllocType& lhs, AllocType& rhs,
285
294
std::true_type /* propagate_on_container_swap */ ) {
@@ -1358,6 +1367,13 @@ class CommonFields : public CommonFieldsGenerationInfo {
1358
1367
CommonFields (const CommonFields&) = delete ;
1359
1368
CommonFields& operator =(const CommonFields&) = delete ;
1360
1369
1370
+ // Copy with guarantee that it is not SOO.
1371
+ CommonFields (non_soo_tag_t , const CommonFields& that)
1372
+ : capacity_(that.capacity_),
1373
+ size_ (that.size_),
1374
+ heap_or_soo_(that.heap_or_soo_) {
1375
+ }
1376
+
1361
1377
// Movable
1362
1378
CommonFields (CommonFields&& that) = default;
1363
1379
CommonFields& operator =(CommonFields&&) = default ;
@@ -2807,9 +2823,9 @@ class raw_hash_set {
2807
2823
2808
2824
~raw_hash_set () {
2809
2825
destructor_impl ();
2810
- # ifndef NDEBUG
2811
- common ().set_capacity (InvalidCapacity::kDestroyed );
2812
- # endif
2826
+ if constexpr ( SwisstableAssertAccessToDestroyedTable ()) {
2827
+ common ().set_capacity (InvalidCapacity::kDestroyed );
2828
+ }
2813
2829
}
2814
2830
2815
2831
iterator begin () ABSL_ATTRIBUTE_LIFETIME_BOUND {
@@ -3540,10 +3556,17 @@ class raw_hash_set {
3540
3556
void destroy_slots () {
3541
3557
ABSL_SWISSTABLE_ASSERT (!is_soo ());
3542
3558
if (PolicyTraits::template destroy_is_trivial<Alloc>()) return ;
3543
- IterateOverFullSlots (common (), sizeof (slot_type),
3544
- [&](const ctrl_t *, void * slot) {
3545
- this ->destroy (static_cast <slot_type*>(slot));
3546
- });
3559
+ auto destroy_slot = [&](const ctrl_t *, void * slot) {
3560
+ this ->destroy (static_cast <slot_type*>(slot));
3561
+ };
3562
+ if constexpr (SwisstableAssertAccessToDestroyedTable ()) {
3563
+ CommonFields common_copy (non_soo_tag_t {}, this ->common ());
3564
+ common ().set_capacity (InvalidCapacity::kDestroyed );
3565
+ IterateOverFullSlots (common_copy, sizeof (slot_type), destroy_slot);
3566
+ common ().set_capacity (common_copy.capacity ());
3567
+ } else {
3568
+ IterateOverFullSlots (common (), sizeof (slot_type), destroy_slot);
3569
+ }
3547
3570
}
3548
3571
3549
3572
void dealloc () {
@@ -3781,8 +3804,11 @@ class raw_hash_set {
3781
3804
assert (capacity () != InvalidCapacity::kReentrance &&
3782
3805
" Reentrant container access during element construction/destruction "
3783
3806
" is not allowed." );
3784
- assert (capacity () != InvalidCapacity::kDestroyed &&
3785
- " Use of destroyed hash table." );
3807
+ if constexpr (SwisstableAssertAccessToDestroyedTable ()) {
3808
+ if (capacity () == InvalidCapacity::kDestroyed ) {
3809
+ ABSL_RAW_LOG (FATAL, " Use of destroyed hash table." );
3810
+ }
3811
+ }
3786
3812
if (SwisstableGenerationsEnabled () &&
3787
3813
ABSL_PREDICT_FALSE (capacity () >= InvalidCapacity::kMovedFrom )) {
3788
3814
if (capacity () == InvalidCapacity::kSelfMovedFrom ) {
0 commit comments