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 <dodji@redhat.com>
This commit is contained in:
Dodji Seketeli 2024-08-13 17:20:22 +02:00
parent 217ba7fdb8
commit a75424b6e5

View File

@ -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<array_type_def>(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);