From a75424b6e51bee05b0092635457a5ed0fd25f5b7 Mon Sep 17 00:00:00 2001 From: Dodji Seketeli Date: Tue, 13 Aug 2024 17:20:22 +0200 Subject: [PATCH] reader: Avoid duplicating recursive types Sometimes, building a sub-type of a complex type can trigger the building of the complex type itself. This is in the case of a recursive complex type where one of its sub-types has the complex type as a sub-type. In those cases, the complex type should not be duplicated. This patch ensures that. * src/abg-reader.cc (build_qualified_type_decl) (build_pointer_type_def, build_reference_type_def) (build_ptr_to_mbr_type, build_subrange_type, build_array_type_def) (build_enum_type_decl, build_typedef_decl): After a sub-type is built, check if the complex type we are looking at is built too. If it is, then return it. Signed-off-by: Dodji Seketeli --- src/abg-reader.cc | 93 ++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 83 insertions(+), 10 deletions(-) diff --git a/src/abg-reader.cc b/src/abg-reader.cc index ed08eb75..0805166a 100644 --- a/src/abg-reader.cc +++ b/src/abg-reader.cc @@ -4291,6 +4291,13 @@ build_qualified_type_decl(reader& rdr, rdr.build_or_get_type_decl(type_id, true); ABG_ASSERT(underlying_type); + if (type_base_sptr t = rdr.get_type_decl(id)) + { + qualified_type_def_sptr result = is_qualified_type(t); + ABG_ASSERT(result); + return result; + } + qualified_type_def_sptr decl; if (type_base_sptr t = rdr.get_type_decl(id)) { @@ -4368,6 +4375,13 @@ build_pointer_type_def(reader& rdr, rdr.build_or_get_type_decl(type_id, true); ABG_ASSERT(pointed_to_type); + if (type_base_sptr t = rdr.get_type_decl(id)) + { + pointer_type_def_sptr result = is_pointer_type(t); + ABG_ASSERT(result); + return result; + } + pointer_type_def_sptr t; if (rdr.get_environment().is_void_type(pointed_to_type)) t = is_pointer_type(build_ir_node_for_void_pointer_type(rdr)); @@ -4457,6 +4471,15 @@ build_reference_type_def(reader& rdr, rdr.build_or_get_type_decl(type_id, /*add_to_current_scope=*/ true); ABG_ASSERT(pointed_to_type); + // The call to rdr.build_or_get_type_decl above might have triggered + // the building of the current type. If so, then return it. + if (type_base_sptr t = rdr.get_type_decl(id)) + { + reference_type_def_sptr result = is_reference_type(t); + ABG_ASSERT(result); + return result; + } + // Create the reference type /before/ the pointed-to type. After // the creation, the type is 'keyed' using // rdr.push_and_key_type_decl. This means that the type can be @@ -4538,6 +4561,13 @@ build_ptr_to_mbr_type(reader& rdr, if (!member_type) return nil; + if (type_base_sptr t = rdr.get_type_decl(id)) + { + ptr_to_mbr_type_sptr result = is_ptr_to_mbr_type(t); + ABG_ASSERT(result); + return result; + } + string containing_type_id; if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "containing-type-id")) containing_type_id = CHAR_STR(s); @@ -4548,6 +4578,13 @@ build_ptr_to_mbr_type(reader& rdr, if (!is_typedef_of_maybe_qualified_class_or_union_type(containing_type)) return nil; + if (type_base_sptr t = rdr.get_type_decl(id)) + { + ptr_to_mbr_type_sptr result = is_ptr_to_mbr_type(t); + ABG_ASSERT(result); + return result; + } + result.reset(new ptr_to_mbr_type(rdr.get_environment(), member_type, containing_type, size_in_bits, alignment_in_bits, @@ -4755,6 +4792,13 @@ build_subrange_type(reader& rdr, ABG_ASSERT(underlying_type); } + if (type_base_sptr t = rdr.get_type_decl(id)) + { + array_type_def::subrange_sptr result = is_subrange_type(t); + ABG_ASSERT(result); + return result; + } + location loc; read_location(rdr, node, loc); @@ -4846,16 +4890,6 @@ build_array_type_def(reader& rdr, if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "type-id")) type_id = CHAR_STR(s); - // maybe building the type of array elements triggered building this - // one in the mean time ... - if (decl_base_sptr d = rdr.get_decl_for_xml_node(node)) - { - array_type_def_sptr result = - dynamic_pointer_cast(d); - ABG_ASSERT(result); - return result; - } - size_t size_in_bits = 0, alignment_in_bits = 0; bool has_size_in_bits = false; char *endptr; @@ -4908,6 +4942,15 @@ build_array_type_def(reader& rdr, rdr.build_or_get_type_decl(type_id, true); ABG_ASSERT(type); + // maybe building the type of array elements triggered building this + // one in the mean time ... + if (type_base_sptr t = rdr.get_type_decl(id)) + { + array_type_def_sptr result = is_array_type(t); + ABG_ASSERT(result); + return result; + } + array_type_def_sptr ar_type(new array_type_def(type, subranges, loc)); // Read the stash from the XML node and stash it into the IR node. read_hash_and_stash(node, ar_type); @@ -5040,6 +5083,13 @@ build_enum_type_decl(reader& rdr, ABG_ASSERT(!id.empty()); + if (type_base_sptr t = rdr.get_type_decl(id)) + { + enum_type_decl_sptr result = is_enum_type(t); + ABG_ASSERT(result); + return result; + } + string base_type_id; enum_type_decl::enumerators enums; for (xmlNodePtr n = xmlFirstElementChild(node); @@ -5082,6 +5132,13 @@ build_enum_type_decl(reader& rdr, rdr.build_or_get_type_decl(base_type_id, true); ABG_ASSERT(underlying_type); + if (type_base_sptr t = rdr.get_type_decl(id)) + { + enum_type_decl_sptr result = is_enum_type(t); + ABG_ASSERT(result); + return result; + } + enum_type_decl_sptr t(new enum_type_decl(name, loc, underlying_type, enums, linkage_name)); @@ -5133,6 +5190,13 @@ build_typedef_decl(reader& rdr, id = CHAR_STR(s); ABG_ASSERT(!id.empty()); + if (type_base_sptr t = rdr.get_type_decl(id)) + { + typedef_decl_sptr result = is_typedef(t); + ABG_ASSERT(result); + return result; + } + string name; if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "name")) name = xml::unescape_xml_string(CHAR_STR(s)); @@ -5148,6 +5212,15 @@ build_typedef_decl(reader& rdr, type_base_sptr underlying_type(rdr.build_or_get_type_decl(type_id, true)); ABG_ASSERT(underlying_type); + // Maybe the building of the underlying type triggered the building + // of the current type. If so, then return it. + if (type_base_sptr t = rdr.get_type_decl(id)) + { + typedef_decl_sptr result = is_typedef(t); + ABG_ASSERT(result); + return result; + } + typedef_decl_sptr t(new typedef_decl(name, underlying_type, loc)); maybe_set_artificial_location(rdr, node, t);