Bug 29857 - dwarf-reader: Resolve decl-only unions

When looking at https://sourceware.org/bugzilla/show_bug.cgi?id=29857
I noticed that decl-only unions where not resolved to their definition
union, unlike what is done for classes and enums.

At type canonicalization, a type A defined in a translation unit TU,
that depends on a decl-only union U will compare different from a type
A defined in a translation unit TU', that depends on the definition of
U, even though the types A should be equal.

This patch teaches the decl-only class resolver to also resolve
decl-only unions, as opposed to resolving just decl-only classes.

	* include/abg-fwd.h (typedef classes_or_unions_type): Declare new
	typedef.
	(lookup_union_types): Declare new function.
	* src/abg-dwarf-reader.cc (reader::decl_only_classes_map_): Change
	the type of this from string_classes_map to
	string_classes_or_unions_map.
	(reader::declaration_only_classes): Return a
	string_classes_or_unions_map, no more a string_classes_map.
	(reader::{maybe_schedule_declaration_only_class_for_resolution,
	is_decl_only_class_scheduled_for_resolution}): Handle
	class_or_union, not just class_decl.  This is a way to make this
	handle unions as well as classes.
	(get_opaque_version_of_type): Adjust.
	* src/abg-ir.cc (lookup_union_types): Define new function.
	* tests/data/test-annotate/test19-pr19023-libtcmalloc_and_profiler.so.abi:
	Adjust.
	* tests/data/test-read-dwarf/test19-pr19023-libtcmalloc_and_profiler.so.abi:
	Adjust.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
This commit is contained in:
Dodji Seketeli 2022-12-16 15:52:14 +01:00 committed by Dodji Seketeli
parent 10dd604e18
commit fc71e519bb
5 changed files with 9235 additions and 9173 deletions

View File

@ -162,6 +162,9 @@ typedef shared_ptr<class_decl> class_decl_sptr;
/// Convenience typedef for a vector of @ref class_decl_sptr
typedef vector<class_decl_sptr> classes_type;
/// Convenience typedef for a vector of @ref class_or_union_sptr
typedef vector<class_or_union_sptr> classes_or_unions_type;
/// Convenience typedef for a weak pointer on a @ref class_decl.
typedef weak_ptr<class_decl> class_decl_wptr;
@ -1140,6 +1143,9 @@ lookup_class_type(const interned_string&, const corpus&);
const type_base_wptrs_type*
lookup_class_types(const interned_string&, const corpus&);
const type_base_wptrs_type*
lookup_union_types(const interned_string&, const corpus&);
bool
lookup_decl_only_class_types(const interned_string&,
const corpus&,
@ -1148,6 +1154,9 @@ lookup_decl_only_class_types(const interned_string&,
const type_base_wptrs_type*
lookup_class_types(const string&, const corpus&);
const type_base_wptrs_type*
lookup_union_types(const string&, const corpus&);
class_decl_sptr
lookup_class_type_per_location(const interned_string&, const corpus&);

View File

@ -263,6 +263,10 @@ typedef stack<scope_decl*> scope_stack_type;
/// value is also a dwarf offset.
typedef unordered_map<Dwarf_Off, Dwarf_Off> offset_offset_map_type;
/// Convenience typedef for a map which key is a string and which
/// value is a vector of smart pointer to a class_or_union_sptr.
typedef unordered_map<string, classes_or_unions_type> string_classes_or_unions_map;
/// Convenience typedef for a map which key is a string and which
/// value is a vector of smart pointer to a class.
typedef unordered_map<string, classes_type> string_classes_map;
@ -1832,7 +1836,7 @@ public:
die_function_type_map_type type_unit_die_wip_function_types_map_;
die_function_decl_map_type die_function_with_no_symbol_map_;
vector<type_base_sptr> types_to_canonicalize_;
string_classes_map decl_only_classes_map_;
string_classes_or_unions_map decl_only_classes_map_;
string_enums_map decl_only_enums_map_;
die_tu_map_type die_tu_map_;
translation_unit_sptr cur_tu_;
@ -3879,7 +3883,7 @@ public:
/// @return a map of string -> vector of classes where the key is
/// the fully qualified name of the class and the value is the
/// vector of declaration-only class.
const string_classes_map&
const string_classes_or_unions_map&
declaration_only_classes() const
{return decl_only_classes_map_;}
@ -3890,7 +3894,7 @@ public:
/// @return a map of string -> vector of classes where the key is
/// the fully qualified name of the class and the value is the
/// vector of declaration-only class.
string_classes_map&
string_classes_or_unions_map&
declaration_only_classes()
{return decl_only_classes_map_;}
@ -3900,18 +3904,18 @@ public:
///
/// @param klass the class to consider.
void
maybe_schedule_declaration_only_class_for_resolution(class_decl_sptr& klass)
maybe_schedule_declaration_only_class_for_resolution(const class_or_union_sptr& cou)
{
if (klass->get_is_declaration_only()
&& klass->get_definition_of_declaration() == 0)
if (cou->get_is_declaration_only()
&& cou->get_definition_of_declaration() == 0)
{
string qn = klass->get_qualified_name();
string_classes_map::iterator record =
string qn = cou->get_qualified_name();
string_classes_or_unions_map::iterator record =
declaration_only_classes().find(qn);
if (record == declaration_only_classes().end())
declaration_only_classes()[qn].push_back(klass);
declaration_only_classes()[qn].push_back(cou);
else
record->second.push_back(klass);
record->second.push_back(cou);
}
}
@ -3923,10 +3927,10 @@ public:
/// @return true iff @p klass is a declaration-only class and if
/// it's been scheduled for resolution to a defined class.
bool
is_decl_only_class_scheduled_for_resolution(class_decl_sptr& klass)
is_decl_only_class_scheduled_for_resolution(const class_or_union_sptr& cou)
{
if (klass->get_is_declaration_only())
return (declaration_only_classes().find(klass->get_qualified_name())
if (cou->get_is_declaration_only())
return (declaration_only_classes().find(cou->get_qualified_name())
!= declaration_only_classes().end());
return false;
@ -3967,13 +3971,13 @@ public:
{
vector<string> resolved_classes;
for (string_classes_map::iterator i =
for (string_classes_or_unions_map::iterator i =
declaration_only_classes().begin();
i != declaration_only_classes().end();
++i)
{
bool to_resolve = false;
for (classes_type::iterator j = i->second.begin();
for (classes_or_unions_type::iterator j = i->second.begin();
j != i->second.end();
++j)
if ((*j)->get_is_declaration_only()
@ -4015,6 +4019,9 @@ public:
// declarations which name is i->first.
const type_base_wptrs_type *classes =
lookup_class_types(i->first, *corpus());
if (!classes)
classes = lookup_union_types(i->first, *corpus());
if (!classes)
continue;
@ -4024,15 +4031,15 @@ public:
// should stay ordered by using the TU path as key to ensure
// stability of the order of classe definitions in ABIXML
// output.
map<string, class_decl_sptr> per_tu_class_map;
map<string, class_or_union_sptr> per_tu_class_map;
for (type_base_wptrs_type::const_iterator c = classes->begin();
c != classes->end();
++c)
{
class_decl_sptr klass = is_class_type(type_base_sptr(*c));
class_or_union_sptr klass = is_class_or_union_type(type_base_sptr(*c));
ABG_ASSERT(klass);
klass = is_class_type(look_through_decl_only_class(klass));
klass = is_class_or_union_type(look_through_decl_only_class(klass));
if (klass->get_is_declaration_only())
continue;
@ -4052,7 +4059,7 @@ public:
// either to the definitions that are in the same TU as
// the declaration, or to the definition found elsewhere,
// if there is only one such definition.
for (classes_type::iterator j = i->second.begin();
for (classes_or_unions_type::iterator j = i->second.begin();
j != i->second.end();
++j)
{
@ -4061,7 +4068,7 @@ public:
{
string tu_path =
(*j)->get_translation_unit()->get_absolute_path();
map<string, class_decl_sptr>::const_iterator e =
map<string, class_or_union_sptr>::const_iterator e =
per_tu_class_map.find(tu_path);
if (e != per_tu_class_map.end())
(*j)->set_definition_of_declaration(e->second);
@ -4077,8 +4084,8 @@ public:
// definition. Otherwise, we are in the case
// 3/ described above.
map<string,
class_decl_sptr>::const_iterator it;
class_decl_sptr first_class =
class_or_union_sptr>::const_iterator it;
class_or_union_sptr first_class =
per_tu_class_map.begin()->second;
bool all_class_definitions_are_equal = true;
for (it = per_tu_class_map.begin();
@ -4124,7 +4131,8 @@ public:
cerr << "Here are the "
<< num_decl_only_classes - num_resolved
<< " unresolved class declarations:\n";
for (string_classes_map::iterator i = declaration_only_classes().begin();
for (string_classes_or_unions_map::iterator i =
declaration_only_classes().begin();
i != declaration_only_classes().end();
++i)
cerr << " " << i->first << "\n";
@ -13230,9 +13238,7 @@ add_or_update_union_type(reader& rdr,
rdr.associate_die_to_type(die, result, where_offset);
// TODO: maybe schedule declaration-only union for result like we do
// for classes:
// rdr.maybe_schedule_declaration_only_class_for_resolution(result);
rdr.maybe_schedule_declaration_only_class_for_resolution(result);
Dwarf_Die child;
bool has_child = (dwarf_child(die, &child) == 0);
@ -14779,7 +14785,7 @@ get_opaque_version_of_type(reader &rdr,
//
if (tag == DW_TAG_structure_type || tag == DW_TAG_class_type)
{
string_classes_map::const_iterator i =
string_classes_or_unions_map::const_iterator i =
rdr.declaration_only_classes().find(qualified_name);
if (i != rdr.declaration_only_classes().end())
result = i->second.back();

View File

@ -12419,6 +12419,22 @@ lookup_decl_only_class_types(const interned_string& qualified_name,
return !result.empty();
}
/// Look into a given corpus to find the union type*s* that have a
/// given qualified name.
///
/// @param qualified_name the qualified name of the type to look for.
///
/// @param corp the corpus to look into.
///
/// @return the vector of union types named @p qualified_name.
const type_base_wptrs_type *
lookup_union_types(const interned_string& qualified_name, const corpus& corp)
{
const istring_type_base_wptrs_map_type& m = corp.get_types().union_types();
return lookup_types_in_map(qualified_name, m);
}
/// Look into a given corpus to find the class type*s* that have a
/// given qualified name.
///
@ -12426,7 +12442,7 @@ lookup_decl_only_class_types(const interned_string& qualified_name,
///
/// @param corp the corpus to look into.
///
/// @return the vector of class types that which name is @p qualified_name.
/// @return the vector of class types which name is @p qualified_name.
const type_base_wptrs_type*
lookup_class_types(const string& qualified_name, const corpus& corp)
{
@ -12434,6 +12450,21 @@ lookup_class_types(const string& qualified_name, const corpus& corp)
return lookup_class_types(s, corp);
}
/// Look into a given corpus to find the union types that have a given
/// qualified name.
///
/// @param qualified_name the qualified name of the type to look for.
///
/// @param corp the corpus to look into.
///
/// @return the vector of union types which name is @p qualified_name.
const type_base_wptrs_type *
lookup_union_types(const string& qualified_name, const corpus& corp)
{
interned_string s = corp.get_environment().intern(qualified_name);
return lookup_union_types(s, corp);
}
/// Look up a @ref class_decl from a given corpus by its location.
///
/// @param loc the location to consider.