From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from simark.ca (simark.ca [158.69.221.121]) by sourceware.org (Postfix) with ESMTPS id A7F303857833 for ; Mon, 4 Nov 2024 18:32:31 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org A7F303857833 Authentication-Results: sourceware.org; dmarc=fail (p=none dis=none) header.from=efficios.com Authentication-Results: sourceware.org; spf=fail smtp.mailfrom=efficios.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org A7F303857833 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=158.69.221.121 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1730745159; cv=none; b=WxhRr7f1ihxgqEaZZ3PyfwI6auzQKJ0/VZq7BMA7zBvwh2DkElw6TLIC6sIoq45a/drp4ejxbnLrtW4XjSQzFe/Zb90kMkJsP7Ki6/95PeTgjc0pocTiuZEpNH4d9bLUjmQB+W7WYVlKzimDRWjmgCctcqvlEKxJadII07/Qc9o= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1730745159; c=relaxed/simple; bh=LQjfLW+eB5x9UXnQJBHdREuR0c5JpFeDxEHfrmJgqxk=; h=From:To:Subject:Date:Message-ID:MIME-Version; b=aEsg9+BBDTTbjGs5Quvg0MG0i+6tPqmXzHSjcvxsbyIdCxVI4KY1aWjtKxGsLhL8xMfFZMeNaIx21sMjTd3k8yJWCv5210Be+JQSQXf5nxXGNB0VG/y1VaSHJEBoSoF5askxj27k1E+gDH4c9UEhDFxlXKUV2/bBFGT4K8vQ2BI= ARC-Authentication-Results: i=1; server2.sourceware.org Received: by simark.ca (Postfix, from userid 112) id 56A161E5EA; Mon, 4 Nov 2024 13:32:31 -0500 (EST) X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-Spam-Level: X-Spam-Status: No, score=-1173.5 required=5.0 tests=BAYES_00,GIT_PATCH_0,KAM_DMARC_NONE,KAM_DMARC_STATUS,SPF_HELO_PASS,SPF_SOFTFAIL,TXREP autolearn=ham autolearn_force=no version=3.4.6 Received: from smarchi-efficios.internal.efficios.com (96-127-217-162.qc.cable.ebox.net [96.127.217.162]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (prime256v1) server-digest SHA256) (No client certificate requested) by simark.ca (Postfix) with ESMTPSA id 5C2651E5E1; Mon, 4 Nov 2024 13:32:23 -0500 (EST) From: Simon Marchi To: gdb-patches@sourceware.org Cc: Simon Marchi , Tom Tromey Subject: [PATCH v5 19/25] Convert typedef hash to new hash table Date: Mon, 4 Nov 2024 13:27:50 -0500 Message-ID: <20241104182817.89835-20-simon.marchi@efficios.com> X-Mailer: git-send-email 2.47.0 In-Reply-To: <20241104182817.89835-1-simon.marchi@efficios.com> References: <20241104182817.89835-1-simon.marchi@efficios.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit List-Id: 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 --- gdb/testsuite/gdb.cp/ptype-flags.exp | 25 ++++-- gdb/typeprint.c | 109 ++++----------------------- gdb/typeprint.h | 47 ++++++++++-- 3 files changed, 71 insertions(+), 110 deletions(-) diff --git a/gdb/testsuite/gdb.cp/ptype-flags.exp b/gdb/testsuite/gdb.cp/ptype-flags.exp index bb92da6122ae..476c075f2872 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 456d8dcb00b4..a4553098011c 100644 --- a/gdb/typeprint.c +++ b/gdb/typeprint.c @@ -194,49 +194,16 @@ 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) - { - 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; - } + for (int i = 0; i < TYPE_TYPEDEF_FIELD_COUNT (t); ++i) + m_table.emplace (&TYPE_TYPEDEF_FIELD (t, i)); /* 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 +217,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 +226,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); } } -/* 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 +239,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)->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); gdb::unique_xmalloc_ptr applied = apply_ext_lang_type_printers (flags->global_printers, t); @@ -350,15 +273,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)->name; } return find_global_typedef (flags, t); diff --git a/gdb/typeprint.h b/gdb/typeprint.h index fe43fc148f49..3cba02f7172c 100644 --- a/gdb/typeprint.h +++ b/gdb/typeprint.h @@ -19,8 +19,10 @@ #ifndef TYPEPRINT_H #define TYPEPRINT_H -#include "gdbsupport/gdb-hashtab.h" #include "gdbsupport/gdb_obstack.h" +#include "gdbsupport/unordered_set.h" +#include "gdbtypes.h" +#include "hashtab.h" enum language; struct ui_file; @@ -115,19 +117,21 @@ struct print_offset_data extern const struct type_print_options type_print_raw_options; -/* A hash table holding typedef_field objects. This is more - complicated than an ordinary hash because it must also track the - lifetime of some -- but not all -- of the contained objects. */ +/* A hash table holding decl_field objects. This is more complicated than an + ordinary hash because it must also track the lifetime of some -- but not all + -- of the contained objects. */ 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; @@ -150,9 +154,36 @@ class typedef_hash_table static const char *find_global_typedef (const struct type_print_options *flags, struct type *t); + struct decl_field_type_hash + { + using is_transparent = void; - /* The actual hash table. */ - htab_up m_table; + std::size_t operator() (type *t) 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 (t))); + } + + std::size_t operator() (const decl_field *f) const noexcept + { return (*this) (f->type); } + }; + + struct decl_field_type_eq + { + using is_transparent = void; + + bool operator () (type *t, const decl_field *f) const noexcept + { return types_equal (t, f->type); } + + bool operator() (const decl_field *lhs, + const decl_field *rhs) const noexcept + { return (*this) (lhs->type, rhs); } + }; + + /* The actual hash table of `decl_field *` identified by their type field. */ + gdb::unordered_set + m_table; /* Storage for typedef_field objects that must be synthesized. */ auto_obstack m_storage; -- 2.47.0