diff options
-rw-r--r-- | gdb/python/py-type.c | 91 | ||||
-rw-r--r-- | gdb/testsuite/gdb.python/py-arch.exp | 5 | ||||
-rw-r--r-- | gdb/testsuite/gdb.python/py-type.exp | 15 |
3 files changed, 96 insertions, 15 deletions
diff --git a/gdb/python/py-type.c b/gdb/python/py-type.c index 11a96d5..dbc355c 100644 --- a/gdb/python/py-type.c +++ b/gdb/python/py-type.c @@ -1162,8 +1162,11 @@ typy_richcompare (PyObject *self, PyObject *other, int op) +/* Forward declaration, see below. */ +static void set_type (type_object *obj, struct type *type); + /* Deleter that saves types when an objfile is being destroyed. */ -struct typy_deleter +struct typy_deleter_for_objfile_owned { void operator() (type_object *obj) { @@ -1181,25 +1184,54 @@ struct typy_deleter type_object *next = obj->next; copied_types.clear (); - obj->type = copy_type_recursive (obj->type, copied_types); - obj->next = NULL; - obj->prev = NULL; + /* Set a copied (now arch-owned) type. As a side-effect this + adds OBJ to per-arch list. We do not need to remove it from + per-objfile list since the objfile is going to go completely + anyway. */ + set_type (obj, copy_type_recursive (obj->type, copied_types)); obj = next; } } }; -static const registry<objfile>::key<type_object, typy_deleter> +/* Deleter that is used when an arch is is about to be freed. */ +struct typy_deleter_for_arch_owned +{ + void operator() (type_object *obj) + { + while (obj) + { + type_object *next = obj->next; + + obj->type = nullptr; + + obj->next = nullptr; + obj->prev = nullptr; + + obj = next; + } + } +}; + + + +static const registry<objfile>::key<type_object, typy_deleter_for_objfile_owned> typy_objfile_data_key; +static const registry<gdbarch>::key<type_object, typy_deleter_for_arch_owned> + typy_gdbarch_data_key; static void set_type (type_object *obj, struct type *type) { + gdb_assert (type != nullptr); + obj->type = type; - obj->prev = NULL; - if (type != nullptr && type->objfile_owner () != nullptr) + obj->prev = nullptr; + + /* Can it really happen that type is NULL? */ + if (type->objfile_owner () != nullptr) { struct objfile *objfile = type->objfile_owner (); @@ -1209,9 +1241,15 @@ set_type (type_object *obj, struct type *type) typy_objfile_data_key.set (objfile, obj); } else - obj->next = NULL; -} + { + struct gdbarch *arch = type->arch_owner (); + obj->next = typy_gdbarch_data_key.get (arch); + if (obj->next) + obj->next->prev = obj; + typy_gdbarch_data_key.set (arch, obj); + } +} static void typy_dealloc (PyObject *obj) { @@ -1219,13 +1257,19 @@ typy_dealloc (PyObject *obj) if (type->prev) type->prev->next = type->next; - else if (type->type != nullptr && type->type->objfile_owner () != nullptr) + else if (type->type != nullptr) { - /* Must reset head of list. */ - struct objfile *objfile = type->type->objfile_owner (); - - if (objfile) - typy_objfile_data_key.set (objfile, type->next); + if (type->type->is_objfile_owned ()) + { + /* Must reset head of list. */ + struct objfile *objfile = type->type->objfile_owner (); + typy_objfile_data_key.set (objfile, type->next); + } + else + { + struct gdbarch *arch = type->type->arch_owner (); + typy_gdbarch_data_key.set (arch, type->next); + } } if (type->next) type->next->prev = type->prev; @@ -1473,6 +1517,23 @@ type_to_type_object (struct type *type) return gdbpy_handle_gdb_exception (nullptr, except); } + /* Look if there's already a gdb.Type object for given TYPE + and if so, return it. */ + if (type->is_objfile_owned ()) + type_obj = typy_objfile_data_key.get (type->objfile_owner ()); + else + type_obj = typy_gdbarch_data_key.get (type->arch_owner ()); + + while (type_obj != nullptr) + { + if (type_obj->type == type) + { + Py_INCREF (type_obj); + return (PyObject*)type_obj; + } + type_obj = type_obj->next; + } + type_obj = PyObject_New (type_object, &type_object_type); if (type_obj) set_type (type_obj, type); diff --git a/gdb/testsuite/gdb.python/py-arch.exp b/gdb/testsuite/gdb.python/py-arch.exp index c76fc778..c294011 100644 --- a/gdb/testsuite/gdb.python/py-arch.exp +++ b/gdb/testsuite/gdb.python/py-arch.exp @@ -108,6 +108,11 @@ gdb_test "python print(arch.void_type())" \ "void" \ "get void type" +# Test type identity +gdb_test "python print(arch.integer_type(32) is arch.integer_type(32))" \ + "True" \ + "arch.integer_type(32) always return the same Python object" + # Test for gdb.architecture_names(). First we're going to grab the # complete list of architecture names using the 'complete' command. set arch_names [] diff --git a/gdb/testsuite/gdb.python/py-type.exp b/gdb/testsuite/gdb.python/py-type.exp index 7e469c9..c9d4353 100644 --- a/gdb/testsuite/gdb.python/py-type.exp +++ b/gdb/testsuite/gdb.python/py-type.exp @@ -324,6 +324,19 @@ proc test_type_equality {} { } } +# Test type identity +proc test_type_identity {} { + gdb_test_no_output "python v1 = gdb.parse_and_eval('global_unsigned_int')" + gdb_test_no_output "python v2 = gdb.parse_and_eval('global_unsigned_int')" + + gdb_test "python print(v1.type is v2.type)" "True" + + gdb_test_no_output "python t1 = gdb.lookup_type ('char')" + gdb_test_no_output "python t2 = gdb.lookup_type ('char')" + + gdb_test "python print(t1 is t2)" "True" +} + # Test the gdb.Type.is_scalar property. proc test_is_scalar { lang } { if {$lang == "c++"} { @@ -376,6 +389,7 @@ if { [build_inferior "${binfile}" "c"] == 0 } { test_is_scalar "c" test_is_signed "c" test_type_equality + test_type_identity } } @@ -392,6 +406,7 @@ if { [build_inferior "${binfile}-cxx" "c++"] == 0 } { test_is_scalar "c++" test_is_signed "c++" test_type_equality + test_type_identity } } |