Bug 29686 - Fix testing the presence of anonymous data member in a struct
authorDodji Seketeli <dodji@redhat.com>
Fri, 24 Mar 2023 22:37:03 +0000 (23:37 +0100)
committerDodji Seketeli <dodji@redhat.com>
Fri, 24 Mar 2023 22:37:03 +0000 (23:37 +0100)
* 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>
include/abg-fwd.h
src/abg-dwarf-reader.cc
src/abg-ir.cc
tests/data/test-read-dwarf/test-libandroid.so.abi

index 747a625c49d17faeda981625924a506186be631c..25e67395d8a2dcdfea8a58d0b016619f834dc222 100644 (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&);
 
index 37367dbaf54bd7ad5bc9512a68bce57975c97b5d..5ca1cee712bc607cf4268aa6efd15b579375e8b7 100644 (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;
index 514013c7657c455a4f1bd14c8e80a90dbe8b40ec..a5b8e90a1a98f2c874e93107074b774291b18282 100644 (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.
 ///
index 8b15c0e994c1279ace30e9a30dbc7fcd0454ef61..4ef47d7ad29445def15f0d034e8a2a5cb6cf179e 100644 (file)
               <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'>