diff options
author | Simon Marchi <simon.marchi@efficios.com> | 2024-08-19 15:03:51 +0000 |
---|---|---|
committer | Simon Marchi <simon.marchi@efficios.com> | 2024-08-23 14:37:54 -0400 |
commit | 134a3c34a5185e8173b9971cbd8da65a318dfacf (patch) | |
tree | 2edd3c326b3d1ec8a6a4f77fd9058aa225278eb3 | |
parent | c2dfac7b848822a6382e85a0233f58433ce57dee (diff) | |
download | binutils-134a3c34a5185e8173b9971cbd8da65a318dfacf.zip binutils-134a3c34a5185e8173b9971cbd8da65a318dfacf.tar.gz binutils-134a3c34a5185e8173b9971cbd8da65a318dfacf.tar.bz2 |
Convert typedef hash to new hash table
This converts the typedef hash to use the new hash table.
This patch found a latent bug in the typedef code. Previously, the
hash function looked at the type name, but the hash equality function
used types_equal -- but that strips typedefs, meaning that equality of
types did not imply equality of hashes. This patch fixes the problem
and updates the relevant test.
Change-Id: I0d10236b01e74bac79621244a1c0c56f90d65594
Co-Authored-By: Tom Tromey <tom@tromey.com>
-rw-r--r-- | gdb/testsuite/gdb.cp/ptype-flags.exp | 25 | ||||
-rw-r--r-- | gdb/typeprint.c | 108 | ||||
-rw-r--r-- | gdb/typeprint.h | 25 |
3 files changed, 55 insertions, 103 deletions
diff --git a/gdb/testsuite/gdb.cp/ptype-flags.exp b/gdb/testsuite/gdb.cp/ptype-flags.exp index bb92da6..476c075 100644 --- a/gdb/testsuite/gdb.cp/ptype-flags.exp +++ b/gdb/testsuite/gdb.cp/ptype-flags.exp @@ -78,10 +78,18 @@ proc do_check_holder {name {flags ""} {show_typedefs 1} {show_methods 1} proc do_check_typedef_holder {name {flags ""} {show_typedefs 1} {show_methods 1} {raw 0}} { - set contents { - { field public "double a;" } - { field public "ns::scoped_double b;" } - { field public "global_double c;" } + if {$raw} { + set contents { + { field public "double a;" } + { field public "ns::scoped_double b;" } + { field public "global_double c;" } + } + } else { + set contents { + { field public "class_double a;" } + { field public "class_double b;" } + { field public "class_double c;" } + } } if {$show_typedefs} { @@ -89,8 +97,13 @@ proc do_check_typedef_holder {name {flags ""} {show_typedefs 1} {show_methods 1} } if {$show_methods} { - lappend contents { method private "double method1(ns::scoped_double);" } - lappend contents { method private "double method2(global_double);" } + if {$raw} { + lappend contents { method private "double method1(ns::scoped_double);" } + lappend contents { method private "double method2(global_double);" } + } else { + lappend contents { method private "class_double method1(class_double);" } + lappend contents { method private "class_double method2(class_double);" } + } } if {$raw} { diff --git a/gdb/typeprint.c b/gdb/typeprint.c index 2e1c5ea..5e3935f 100644 --- a/gdb/typeprint.c +++ b/gdb/typeprint.c @@ -194,49 +194,19 @@ print_offset_data::finish (struct type *type, int level, -/* A hash function for a typedef_field. */ - -static hashval_t -hash_typedef_field (const void *p) -{ - const struct decl_field *tf = (const struct decl_field *) p; - - return htab_hash_string (TYPE_SAFE_NAME (tf->type)); -} - -/* An equality function for a typedef field. */ - -static int -eq_typedef_field (const void *a, const void *b) -{ - const struct decl_field *tfa = (const struct decl_field *) a; - const struct decl_field *tfb = (const struct decl_field *) b; - - return types_equal (tfa->type, tfb->type); -} - /* See typeprint.h. */ void typedef_hash_table::recursively_update (struct type *t) { - int i; - - for (i = 0; i < TYPE_TYPEDEF_FIELD_COUNT (t); ++i) + for (int i = 0; i < TYPE_TYPEDEF_FIELD_COUNT (t); ++i) { - struct decl_field *tdef = &TYPE_TYPEDEF_FIELD (t, i); - void **slot; - - slot = htab_find_slot (m_table.get (), tdef, INSERT); - /* Only add a given typedef name once. Really this shouldn't - happen; but it is safe enough to do the updates breadth-first - and thus use the most specific typedef. */ - if (*slot == NULL) - *slot = tdef; + decl_field *child_type = &TYPE_TYPEDEF_FIELD (t, i); + m_table.emplace (child_type->type, child_type); } /* Recurse into superclasses. */ - for (i = 0; i < TYPE_N_BASECLASSES (t); ++i) + for (int i = 0; i < TYPE_N_BASECLASSES (t); ++i) recursively_update (TYPE_BASECLASS (t, i)); } @@ -250,7 +220,6 @@ typedef_hash_table::add_template_parameters (struct type *t) for (i = 0; i < TYPE_N_TEMPLATE_ARGUMENTS (t); ++i) { struct decl_field *tf; - void **slot; /* We only want type-valued template parameters in the hash. */ if (TYPE_TEMPLATE_ARGUMENT (t, i)->aclass () != LOC_TYPEDEF) @@ -260,45 +229,10 @@ typedef_hash_table::add_template_parameters (struct type *t) tf->name = TYPE_TEMPLATE_ARGUMENT (t, i)->linkage_name (); tf->type = TYPE_TEMPLATE_ARGUMENT (t, i)->type (); - slot = htab_find_slot (m_table.get (), tf, INSERT); - if (*slot == NULL) - *slot = tf; + m_table.emplace (tf->type, tf); } } -/* See typeprint.h. */ - -typedef_hash_table::typedef_hash_table () - : m_table (htab_create_alloc (10, hash_typedef_field, eq_typedef_field, - NULL, xcalloc, xfree)) -{ -} - -/* Helper function for typedef_hash_table::copy. */ - -static int -copy_typedef_hash_element (void **slot, void *nt) -{ - htab_t new_table = (htab_t) nt; - void **new_slot; - - new_slot = htab_find_slot (new_table, *slot, INSERT); - if (*new_slot == NULL) - *new_slot = *slot; - - return 1; -} - -/* See typeprint.h. */ - -typedef_hash_table::typedef_hash_table (const typedef_hash_table &table) -{ - m_table.reset (htab_create_alloc (10, hash_typedef_field, eq_typedef_field, - NULL, xcalloc, xfree)); - htab_traverse_noresize (table.m_table.get (), copy_typedef_hash_element, - m_table.get ()); -} - /* Look up the type T in the global typedef hash. If it is found, return the typedef name. If it is not found, apply the type-printers, if any, given by start_script_type_printers and return the @@ -308,29 +242,21 @@ const char * typedef_hash_table::find_global_typedef (const struct type_print_options *flags, struct type *t) { - void **slot; - struct decl_field tf, *new_tf; - if (flags->global_typedefs == NULL) return NULL; - tf.name = NULL; - tf.type = t; - - slot = htab_find_slot (flags->global_typedefs->m_table.get (), &tf, INSERT); - if (*slot != NULL) - { - new_tf = (struct decl_field *) *slot; - return new_tf->name; - } + if (auto it = flags->global_typedefs->m_table.find (t); + it != flags->global_typedefs->m_table.end ()) + return it->second->name; /* Put an entry into the hash table now, in case apply_ext_lang_type_printers recurses. */ - new_tf = XOBNEW (&flags->global_typedefs->m_storage, struct decl_field); + decl_field *new_tf + = XOBNEW (&flags->global_typedefs->m_storage, struct decl_field); new_tf->name = NULL; new_tf->type = t; - *slot = new_tf; + flags->global_typedefs->m_table.emplace (new_tf->type, new_tf); gdb::unique_xmalloc_ptr<char> applied = apply_ext_lang_type_printers (flags->global_printers, t); @@ -350,15 +276,9 @@ typedef_hash_table::find_typedef (const struct type_print_options *flags, { if (flags->local_typedefs != NULL) { - struct decl_field tf, *found; - - tf.name = NULL; - tf.type = t; - htab_t table = flags->local_typedefs->m_table.get (); - found = (struct decl_field *) htab_find (table, &tf); - - if (found != NULL) - return found->name; + if (auto iter = flags->local_typedefs->m_table.find (t); + iter != flags->local_typedefs->m_table.end ()) + return iter->second->name; } return find_global_typedef (flags, t); diff --git a/gdb/typeprint.h b/gdb/typeprint.h index e14d70e..7dacc15 100644 --- a/gdb/typeprint.h +++ b/gdb/typeprint.h @@ -20,6 +20,8 @@ #define TYPEPRINT_H #include "gdbsupport/gdb_obstack.h" +#include "gdbsupport/unordered_set.h" +#include "gdbtypes.h" enum language; struct ui_file; @@ -123,10 +125,12 @@ class typedef_hash_table public: /* Create a new typedef-lookup hash table. */ - typedef_hash_table (); + typedef_hash_table () = default; /* Copy a typedef hash. */ - typedef_hash_table (const typedef_hash_table &); + typedef_hash_table (const typedef_hash_table &other) + : m_table (other.m_table) + {} typedef_hash_table &operator= (const typedef_hash_table &) = delete; @@ -149,9 +153,24 @@ private: static const char *find_global_typedef (const struct type_print_options *flags, struct type *t); + struct hash + { + std::size_t operator() (type *type) const noexcept + { + /* Use check_typedef: the hash must agree with equals, and types_equal + strips typedefs. */ + return htab_hash_string (TYPE_SAFE_NAME (check_typedef (type))); + } + }; + + struct eq + { + bool operator() (type *lhs, type *rhs) const noexcept + { return types_equal (lhs, rhs); } + }; /* The actual hash table. */ - htab_up m_table; + gdb::unordered_map<type *, decl_field *, hash, eq> m_table; /* Storage for typedef_field objects that must be synthesized. */ auto_obstack m_storage; |