XML writer: use consistent type pointers for type ids and emission tracking

Insertion uses the canonical type, if available, but look-up did
not. Given that type id insertion and look-up also use canonical
types, it makes sense to adjust the remaining code accordingly.

Neither decl_only_type_is_emitted nor record_decl_only_type_as_emitted
do the check, but very few types end up being recorded this way.

The functions write_class_decl and write_union_decl (but not
write_class_decl_opening_tag and write_union_decl_opening_tag which
can be called in other contexts) resolve declaration-only types to a
definition where possible.

To ensure type ids consistently refer to the same canonical type we
should use canonical types and definitions-of-declarations more
consistently.

This change introduces get_exemplar_type to return the exemplar type
that should be used for type id and emitted checks.  That exemplar
type is the canonical type of a given type, or the canonical type of
the definition-of-declaration-only-type when applicable.

However, it does not also change all the write functions to write out
the exemplar types.

	* include/abg-fwd.h (get_exemplar_type): Declare new function.
	* src/abg-ir.cc (get_exemplar_type): Define new function.
	* src/abg-writer.cc (type_has_existing_id): use get_exemplar_type
	for resolution.
	(get_id_for_type): Likewise.
	(record_type_as_emitted): Likewise.
	(type_is_emitted): Likewise.

Reviewed-by: Giuliano Procida <gprocida@google.com>
Signed-off-by: Matthias Maennich <maennich@google.com>
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
This commit is contained in:
Matthias Maennich 2021-12-03 11:46:19 +00:00 committed by Dodji Seketeli
parent 762949ce3e
commit 74a2866e4f
3 changed files with 55 additions and 14 deletions

View File

@ -1393,6 +1393,19 @@ is_non_canonicalized_type(const type_base *);
bool
is_non_canonicalized_type(const type_base_sptr&);
/// For a given type, return its exemplar type.
///
/// For a given type, its exemplar type is either its canonical type
/// or the canonical type of the definition type of a given
/// declaration-only type. If the neither of those two types exist,
/// then the exemplar type is the given type itself.
///
/// @param type the input to consider.
///
/// @return the exemplar type.
type_base*
get_exemplar_type(const type_base* type);
bool
function_decl_is_less_than(const function_decl&f, const function_decl &s);

View File

@ -25232,6 +25232,38 @@ is_non_canonicalized_type(const type_base *t)
return is_declaration_only_class_or_union_type(t) || env->is_void_type(t);
}
/// For a given type, return its exemplar type.
///
/// For a given type, its exemplar type is either its canonical type
/// or the canonical type of the definition type of a given
/// declaration-only type. If the neither of those two types exist,
/// then the exemplar type is the given type itself.
///
/// @param type the input to consider.
///
/// @return the exemplar type.
type_base*
get_exemplar_type(const type_base* type)
{
if (decl_base * decl = is_decl(type))
{
// Make sure we get the real definition of a decl-only type.
decl = look_through_decl_only(decl);
type = is_type(decl);
ABG_ASSERT(type);
}
type_base *exemplar = type->get_naked_canonical_type();
if (!exemplar)
{
// The type has no canonical type. Let's be sure that it's one
// of those rare types that are allowed to be non canonicalized
// in the system.
exemplar = const_cast<type_base*>(type);
ABG_ASSERT(is_non_canonicalized_type(exemplar));
}
return exemplar;
}
/// Test if a given type is allowed to be non canonicalized
///
/// This is a subroutine of hash_as_canonical_type_or_constant.

View File

@ -37,6 +37,7 @@ ABG_BEGIN_EXPORT_DECLARATIONS
#include "abg-writer.h"
#include "abg-libxml-utils.h"
#include "abg-fwd.h"
ABG_END_EXPORT_DECLARATIONS
// </headers defining libabigail's API>
@ -394,10 +395,8 @@ public:
bool
type_has_existing_id(type_base* type) const
{
type_base *c = type->get_naked_canonical_type();
if (c == 0)
c = const_cast<type_base*>(type);
return (m_type_id_map.find(c) != m_type_id_map.end());
type = get_exemplar_type(type);
return m_type_id_map.find(type) != m_type_id_map.end();
}
/// Associate a unique id to a given type. For that, put the type
@ -413,11 +412,9 @@ public:
/// associated to it, create a new one and return it. Otherwise,
/// return the existing id for that type.
interned_string
get_id_for_type(const type_base* t) const
get_id_for_type(type_base* type) const
{
type_base *c = t->get_naked_canonical_type();
if (c == 0)
c = const_cast<type_base*>(t);
type_base* c = get_exemplar_type(type);
type_ptr_map::const_iterator it = m_type_id_map.find(c);
if (it != m_type_id_map.end())
@ -715,11 +712,9 @@ public:
///
/// @param t the type to flag.
void
record_type_as_emitted(const type_base *t)
record_type_as_emitted(const type_base* t)
{
type_base *c = t->get_naked_canonical_type();
if (c == 0)
c = const_cast<type_base*>(t);
type_base* c = get_exemplar_type(t);
m_emitted_type_set.insert(c);
}
@ -730,9 +725,10 @@ public:
/// @return true if the type has already been emitted, false
/// otherwise.
bool
type_is_emitted(const type_base *t) const
type_is_emitted(const type_base* t) const
{
return m_emitted_type_set.find(t) != m_emitted_type_set.end();
type_base* c = get_exemplar_type(t);
return m_emitted_type_set.find(c) != m_emitted_type_set.end();
}
/// Test if a given type has been written out to the XML output.