https://gcc.gnu.org/bugzilla/show_bug.cgi?id=92761
Bug ID: 92761 Summary: hash_table::expand invokes assignment on invalid objects Product: gcc Version: 10.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: bootstrap Assignee: unassigned at gcc dot gnu.org Reporter: msebor at gcc dot gnu.org Target Milestone: --- The GCC internal hash_table::expand() function invokes the assignment operator on invalid/empty elements. The following test case inserted into the C++ parser (where I ran into the problem) reproduces the bug: struct S { S (): p (&p) { } S (const S &s): p (&p) { gcc_assert (s.p == &s.p); } S& operator= (const S &s) { gcc_assert (s.p == &s.p); return *this; } ~S () { gcc_assert (p == &p); } void *p; }; hash_map<tree, S> x; static void test_hash_table () { for (int i = 0; i != 32; ++i) x.put ((tree)i, S ()); x.empty (); } /* Parse one entire translation unit. */ void c_parse_file (void) { test_hash_table (); ... } internal compiler error: in operator=, at cp/parser.c:43418 0xaeed4f S::operator=(S const&) /src/gcc/61339/gcc/cp/parser.c:43418 0xaf3a7e hash_map<tree_node*, S, simple_hashmap_traits<default_hash_traits<tree_node*>, S> >::hash_entry::operator=(hash_map<tree_node*, S, simple_hashmap_traits<default_hash_traits<tree_node*>, S> >::hash_entry const&) /src/gcc/61339/gcc/hash-map.h:42 0xaf3c24 hash_table<hash_map<tree_node*, S, simple_hashmap_traits<default_hash_traits<tree_node*>, S> >::hash_entry, false, xcallocator>::expand() /src/gcc/61339/gcc/hash-table.h:822 0xaf21a7 hash_table<hash_map<tree_node*, S, simple_hashmap_traits<default_hash_traits<tree_node*>, S> >::hash_entry, false, xcallocator>::find_slot_with_hash(tree_node* const&, unsigned int, insert_option) /src/gcc/61339/gcc/hash-table.h:962 0xaf02e4 hash_map<tree_node*, S, simple_hashmap_traits<default_hash_traits<tree_node*>, S> >::put(tree_node* const&, S const&) /src/gcc/61339/gcc/hash-map.h:165 0xaea3b8 test_hash_table /src/gcc/61339/gcc/cp/parser.c:43428 0xaea3e5 c_parse_file() /src/gcc/61339/gcc/cp/parser.c:43438 0xcd34ab c_common_parse_file() /src/gcc/61339/gcc/c-family/c-opts.c:1185 Please submit a full bug report, As the stack trace shows, the problem is due to expand() directly assigning to the (invalid) lvalue obtained from find_empty_slot_for_expand: template<typename Descriptor, bool Lazy, template<typename Type> class Allocator> void hash_table<Descriptor, Lazy, Allocator>::expand () { value_type *oentries = m_entries; ... value_type *p = oentries; do { value_type &x = *p; if (!is_empty (x) && !is_deleted (x)) { value_type *q = find_empty_slot_for_expand (Descriptor::hash (x)); *q = x; <<< q points to a empty slot with no object in it } p++; } while (p < olimit); ... }