-
- Downloads
libstdc++: Simplify storage of hasher in local iterators
The fix for PR libstdc++/56267 (relating to the lifetime of the hash object stored in a local iterator) has undefined behaviour, as it relies on being able to call a member function on an empty object that never started its lifetime. Although the member function probably doesn't care about the empty object's state, this is still technically undefined because there is no object of that type at that address. It's also possible that the hash object would have a stricter alignment than the _Hash_code_storage object, so that the reinterpret_cast would produce a misaligned pointer. This fix replaces _Local_iterator_base's _Hash_code_storage base-class with a new class template containing a potentially-overlapping (i.e. [[no_unique_address]]) union member. This means that we always have storage of the correct type, and it can be initialized/destroyed when required. We no longer need a reinterpret_cast that gives us a pointer that we should not dereference. It would be nice if we could just use a union containing the _Hash object as a data member of _Local_iterator_base, but that would be an ABI change. The _Hash_code_storage that contains the _Hash object is the first base-class, before the _Node_iterator_base base-class. Making the union a data member of _Local_iterator_base would make it come after the _Node_iterator_base base instead of before it, altering the layout. Since we're changing _Hash_code_storage anyway, we can replace it with a new class template that stores the _Hash object itself in the union, rather than a _Hash_code_base that holds the _Hash. This removes an unnecessary level of indirection in the class hierarchy. This change requires the effects of _Hash_code_base::_M_bucket_index to be inlined into the _Local_iterator_base::_M_incr function, but that's easy. We don't need separate specializations of _Hash_obj_storage for an empty hash function and a non-empty one. Using [[no_unique_address]] gives us an empty base-class when possible. libstdc++-v3/ChangeLog: * include/bits/hashtable_policy.h (_Hash_code_storage): Remove. (_Hash_obj_storage): New class template. Store the hash function as a union member instead of using a byte buffer. (_Local_iterator_base): Use _Hash_obj_storage instead of _Hash_code_storage, adjust members that construct and destroy the hash object. (_Local_iterator_base::_M_incr): Calculate bucket index.
Loading
Please register or sign in to comment