Bug 29686 - Fix testing the presence of anonymous data member in a struct

* include/abg-fwd.h (anonymous_data_member_to_class_or_union): Add
	a new overload.
	(anonymous_data_member_exists_in_class): Declare new function.
	* src/abg-dwarf-reader.cc (add_or_update_class_type): Use the new
	anonymous_data_member_exists_in_class function.
	* src/abg-ir.cc (anonymous_data_member_to_class_or_union): Define
	new function.
	* tests/data/test-read-dwarf/test-libandroid.so.abi: Adjust.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
This commit is contained in:
Dodji Seketeli 2023-03-24 23:37:03 +01:00
parent 0ddd051c27
commit e2040f2838
4 changed files with 65 additions and 4 deletions

View File

@ -727,6 +727,13 @@ anonymous_data_member_to_class_or_union(const var_decl*);
class_or_union_sptr
anonymous_data_member_to_class_or_union(const var_decl_sptr&);
class_or_union_sptr
anonymous_data_member_to_class_or_union(const var_decl&);
bool
anonymous_data_member_exists_in_class(const var_decl& anon_dm,
const class_or_union& clazz);
bool
scope_anonymous_or_typedef_named(const decl_base&);

View File

@ -13138,7 +13138,8 @@ add_or_update_class_type(reader& rdr,
die_access_specifier(&child, access);
var_decl_sptr dm(new var_decl(n, t, loc, m));
if (n.empty() && result->find_data_member(dm))
if (n.empty()
&& anonymous_data_member_exists_in_class(*dm, *result))
// dm is an anonymous data member that was already
// present in the current class so let's not add it.
continue;

View File

@ -5951,6 +5951,20 @@ anonymous_data_member_to_class_or_union(const var_decl* d)
return 0;
}
/// Get the @ref class_or_union type of a given anonymous data member.
///
/// @param d the anonymous data member to consider.
///
/// @return the @ref class_or_union type of the anonymous data member
/// @p d.
class_or_union_sptr
anonymous_data_member_to_class_or_union(const var_decl& d)
{
if (is_anonymous_data_member(d))
return is_class_or_union_type(d.get_type());
return class_or_union_sptr();
}
/// Test if a data member has annonymous type or not.
///
/// @param d the data member to consider.
@ -6006,6 +6020,48 @@ anonymous_data_member_to_class_or_union(const var_decl_sptr &d)
return class_or_union_sptr();
}
/// Test if a given anonymous data member exists in a class or union.
///
/// @param anon_dm the anonymous data member to consider.
///
/// @param clazz the class to consider.
///
/// @return true iff @p anon_dm exists in the @clazz.
bool
anonymous_data_member_exists_in_class(const var_decl& anon_dm,
const class_or_union& clazz)
{
if (!anon_dm.get_is_anonymous()
|| !is_class_or_union_type(anon_dm.get_type()))
return false;
class_or_union_sptr cl = is_class_or_union_type(anon_dm.get_type());
ABG_ASSERT(cl);
// Look for the presence of each data member of anon_dm in clazz.
//
// If one data member of anon_dm is not present in clazz, then the
// data member anon_dm is considered to not exist in clazz.
for (auto anon_dm_m : cl->get_non_static_data_members())
{
// If the data member anon_dm_m is not an anonymous data member,
// it's easy to look for it.
if (!is_anonymous_data_member(anon_dm_m))
{
if (!clazz.find_data_member(anon_dm_m->get_name()))
return false;
}
// If anon_dm_m is itself an anonymous data member then recurse
else
{
if (!anonymous_data_member_exists_in_class(*anon_dm_m, clazz))
return false;
}
}
return true;
}
/// Test if the scope of a given decl is anonymous or anonymous with a
/// naming typedef.
///

View File

@ -11061,9 +11061,6 @@
<data-member access='public' layout-offset-in-bits='16'>
<var-decl name='__data_' type-id='72631341' visibility='default' filepath='external/libcxx/include/string' line='761' column='1'/>
</data-member>
<data-member access='public' layout-offset-in-bits='0'>
<var-decl name='' type-id='ac5ab59f' visibility='default' filepath='external/libcxx/include/string' line='756' column='1'/>
</data-member>
</class-decl>
</member-type>
<member-type access='private'>