summaryrefslogtreecommitdiff
path: root/gdb/typeprint.c
diff options
context:
space:
mode:
authorTom Tromey <tromey@redhat.com>2012-11-12 17:37:32 +0000
committerTom Tromey <tromey@redhat.com>2012-11-12 17:37:32 +0000
commit463288d719fec19e54633a159200f759633f21ea (patch)
tree0595da6eece3a3bb7bbb898309bdc24cbac38265 /gdb/typeprint.c
parentfb60d514dcc6cb25180be2cf4ebdfe228b010ef9 (diff)
downloadgdb-463288d719fec19e54633a159200f759633f21ea.tar.gz
* c-typeprint.c (find_typedef_for_canonicalize,
print_name_maybe_canonical): New functions. (c_print_type): Look up type name. (cp_type_print_derivation_info): Add flags argument. Use print_name_maybe_canonical. (cp_type_print_method_args): Add wrapping. (c_type_print_varspec_prefix): Use print_name_maybe_canonical. (c_type_print_template_args): New function. (c_type_print_base): Change wrapping. Use print_name_maybe_canonical. <TYPE_CODE_STRUCT>: Possibly create a typedef hash, and do type name lookups. * gdbtypes.c (types_equal): No longer static. * gdbtypes.h (types_equal): Declare. * typeprint.c (type_print_raw_options, default_ptype_flags): Update. (struct typedef_hash_table): New. (hash_typedef_field, eq_typedef_field, recursively_update_typedef_hash, add_template_parameters, create_typedef_hash, free_typedef_hash, do_free_typedef_hash, make_cleanup_free_typedef_hash, copy_typedef_hash_element, copy_typedef_hash, find_typedef_in_hash): New functions. * typeprint.h (struct type_print_options) <local_typedefs>: New field. (recursively_update_typedef_hash, add_template_parameters, create_typedef_hash, free_typedef_hash, make_cleanup_free_typedef_hash, copy_typedef_hash, find_typedef_in_hash): Declare. testsuite * gdb.base/call-sc.exp: Use "ptype/r". * gdb.base/volatile.exp: Don't expect "int". * gdb.cp/ptype-flags.cc: New file. * gdb.cp/ptype-flags.exp: New file. * gdb.cp/templates.exp: Use ptype/r. (test_ptype_of_templates, test_template_typedef): Likewise. * lib/cp-support.exp (cp_test_ptype_class): Add in_ptype_arg argument. Handle template names and template parameters. * gdb.mi/mi-var-cmd.exp: Accept "long". * gdb.mi/mi-var-child.exp: Accept "long". * gdb.mi/mi-var-display.exp: Accept "long". * gdb.mi/mi2-var-child.exp: Accept "long".
Diffstat (limited to 'gdb/typeprint.c')
-rw-r--r--gdb/typeprint.c196
1 files changed, 194 insertions, 2 deletions
diff --git a/gdb/typeprint.c b/gdb/typeprint.c
index 509b3ee3632..0e1c93c0a8c 100644
--- a/gdb/typeprint.c
+++ b/gdb/typeprint.c
@@ -51,7 +51,8 @@ const struct type_print_options type_print_raw_options =
{
1, /* raw */
1, /* print_methods */
- 1 /* print_typedefs */
+ 1, /* print_typedefs */
+ NULL /* local_typedefs */
};
/* The default flags for 'ptype' and 'whatis'. */
@@ -60,11 +61,202 @@ static struct type_print_options default_ptype_flags =
{
0, /* raw */
1, /* print_methods */
- 1 /* print_typedefs */
+ 1, /* print_typedefs */
+ NULL /* local_typedefs */
};
+/* 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. */
+
+struct typedef_hash_table
+{
+ /* The actual hash table. */
+ htab_t table;
+
+ /* Storage for typedef_field objects that must be synthesized. */
+ struct obstack storage;
+};
+
+/* A hash function for a typedef_field. */
+
+static hashval_t
+hash_typedef_field (const void *p)
+{
+ const struct typedef_field *tf = p;
+ struct type *t = check_typedef (tf->type);
+
+ return htab_hash_string (TYPE_SAFE_NAME (t));
+}
+
+/* An equality function for a typedef field. */
+
+static int
+eq_typedef_field (const void *a, const void *b)
+{
+ const struct typedef_field *tfa = a;
+ const struct typedef_field *tfb = b;
+
+ return types_equal (tfa->type, tfb->type);
+}
+
+/* Add typedefs from T to the hash table TABLE. */
+
+void
+recursively_update_typedef_hash (struct typedef_hash_table *table,
+ struct type *t)
+{
+ int i;
+
+ if (table == NULL)
+ return;
+
+ for (i = 0; i < TYPE_TYPEDEF_FIELD_COUNT (t); ++i)
+ {
+ struct typedef_field *tdef = &TYPE_TYPEDEF_FIELD (t, i);
+ void **slot;
+
+ slot = htab_find_slot (table->table, 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;
+ }
+
+ /* Recurse into superclasses. */
+ for (i = 0; i < TYPE_N_BASECLASSES (t); ++i)
+ recursively_update_typedef_hash (table, TYPE_BASECLASS (t, i));
+}
+
+/* Add template parameters from T to the typedef hash TABLE. */
+
+void
+add_template_parameters (struct typedef_hash_table *table, struct type *t)
+{
+ int i;
+
+ if (table == NULL)
+ return;
+
+ for (i = 0; i < TYPE_N_TEMPLATE_ARGUMENTS (t); ++i)
+ {
+ struct typedef_field *tf;
+ void **slot;
+
+ /* We only want type-valued template parameters in the hash. */
+ if (SYMBOL_CLASS (TYPE_TEMPLATE_ARGUMENT (t, i)) != LOC_TYPEDEF)
+ continue;
+
+ tf = XOBNEW (&table->storage, struct typedef_field);
+ tf->name = SYMBOL_LINKAGE_NAME (TYPE_TEMPLATE_ARGUMENT (t, i));
+ tf->type = SYMBOL_TYPE (TYPE_TEMPLATE_ARGUMENT (t, i));
+
+ slot = htab_find_slot (table->table, tf, INSERT);
+ if (*slot == NULL)
+ *slot = tf;
+ }
+}
+
+/* Create a new typedef-lookup hash table. */
+
+struct typedef_hash_table *
+create_typedef_hash (void)
+{
+ struct typedef_hash_table *result;
+
+ result = XNEW (struct typedef_hash_table);
+ result->table = htab_create_alloc (10, hash_typedef_field, eq_typedef_field,
+ NULL, xcalloc, xfree);
+ obstack_init (&result->storage);
+
+ return result;
+}
+
+/* Free a typedef field table. */
+
+void
+free_typedef_hash (struct typedef_hash_table *table)
+{
+ if (table != NULL)
+ {
+ htab_delete (table->table);
+ obstack_free (&table->storage, NULL);
+ xfree (table);
+ }
+}
+
+/* A cleanup for freeing a typedef_hash_table. */
+
+static void
+do_free_typedef_hash (void *arg)
+{
+ free_typedef_hash (arg);
+}
+
+/* Return a new cleanup that frees TABLE. */
+
+struct cleanup *
+make_cleanup_free_typedef_hash (struct typedef_hash_table *table)
+{
+ return make_cleanup (do_free_typedef_hash, table);
+}
+
+/* Helper function for copy_typedef_hash. */
+
+static int
+copy_typedef_hash_element (void **slot, void *nt)
+{
+ htab_t new_table = nt;
+ void **new_slot;
+
+ new_slot = htab_find_slot (new_table, *slot, INSERT);
+ if (*new_slot == NULL)
+ *new_slot = *slot;
+
+ return 1;
+}
+
+/* Copy a typedef hash. */
+
+struct typedef_hash_table *
+copy_typedef_hash (struct typedef_hash_table *table)
+{
+ struct typedef_hash_table *result;
+
+ if (table == NULL)
+ return NULL;
+
+ result = create_typedef_hash ();
+ htab_traverse_noresize (table->table, copy_typedef_hash_element,
+ result->table);
+ return result;
+}
+
+/* Look up the type T in the typedef hash table in with FLAGS. If T
+ is in the table, return its short (class-relative) typedef name.
+ Otherwise return NULL. If the table is NULL, this always returns
+ NULL. */
+
+const char *
+find_typedef_in_hash (const struct type_print_options *flags, struct type *t)
+{
+ struct typedef_field tf, *found;
+
+ if (flags->local_typedefs == NULL)
+ return NULL;
+
+ tf.name = NULL;
+ tf.type = t;
+ found = htab_find (flags->local_typedefs->table, &tf);
+
+ return found == NULL ? NULL : found->name;
+}
+
+
+
/* Print a description of a type in the format of a
typedef for the current language.
NEW is the new name for a type TYPE. */