]> sourceware.org Git - libabigail.git/commitdiff
Handle several virtual member functions having the same vtable offset
authorDodji Seketeli <dodji@redhat.com>
Fri, 13 Jan 2017 21:46:36 +0000 (22:46 +0100)
committerDodji Seketeli <dodji@redhat.com>
Mon, 16 Jan 2017 20:00:54 +0000 (21:00 +0100)
In the DWARF for C++, it can happens that a virtual constructor leads
to several (up to 3) destructor functions that all have the same
vtable offset.  That vtable offset is the same as the offset of the
virtual destructor that the user actually defined in her source code.

This patch adds a map data structure to the private data of
class_decl.  That map associates a vtable offset X to a vector of
virtual member functions that have the same vtable offset X.

That new map is populated whenever a virtual member function is added
to the class.

* include/abg-ir.h (class_or_union::virtual_mem_fn_map_type):
Define new typedef.
(class_decl::get_virtual_mem_fns_map): Declare new accessor.
* src/abg-ir.cc (class_decl::priv::virtual_mem_fns_map_): New data
member.
(class_decl::get_virtual_mem_fns_map): Define new accessor.
(fixup_virtual_member_function): Populate the new virtual member
functions map.
(class_decl::on_canonical_type_set): Sort the virtual member
function vectors stored in the new virtual member functions map.
(class_decl::add_member_function): Call
set_member_function_is_virtual *after* calling
set_member_function_vtable_offset because the former updates the
virtual function map, so it needs the vtable offset.
* src/abg-dwarf-reader.cc (finish_member_function_reading):
Likewise.
* src/abg-reader.cc (build_class_decl): Likewise.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
include/abg-ir.h
src/abg-dwarf-reader.cc
src/abg-ir.cc
src/abg-reader.cc

index 729a40db522422c8d937cd8ae91c7358108a0d9b..cd76bcf04113f35ae669e5dbb08cadb6d5146147 100644 (file)
@@ -3207,6 +3207,7 @@ public:
   typedef vector<type_base_sptr>                       member_types;
   typedef vector<var_decl_sptr>                        data_members;
   typedef vector<method_decl_sptr>             member_functions;
+  typedef unordered_map<unsigned, member_functions> virtual_mem_fn_map_type;
   typedef unordered_map<string, method_decl*> string_mem_fn_ptr_map_type;
   /// @}
 
@@ -3473,6 +3474,9 @@ public:
   const member_functions&
   get_virtual_mem_fns() const;
 
+  const virtual_mem_fn_map_type&
+  get_virtual_mem_fns_map() const;
+
   void
   sort_virtual_mem_fns();
 
index d5aca0d5afc24e42019dcde8d2b16aa26fb8e6ca..5eb3071770914d2cb05eca0b94d57584e617af0b 100644 (file)
@@ -10535,8 +10535,8 @@ finish_member_function_reading(Dwarf_Die*                 die,
       is_static = true;
   }
   set_member_access_specifier(m, access);
-  set_member_function_is_virtual(m, is_virtual);
   set_member_function_vtable_offset(m, vindex);
+  set_member_function_is_virtual(m, is_virtual);
   set_member_is_static(m, is_static);
   set_member_function_is_ctor(m, is_ctor);
   set_member_function_is_dtor(m, is_dtor);
index fd2d9f75d916f9d2700b85dc9fe078f482ca9439..0811729c72db7ba068b46bc7b9fb90ae4704f9cd 100644 (file)
@@ -15584,7 +15584,8 @@ struct class_decl::priv
   base_specs                   bases_;
   unordered_map<string, base_spec_sptr>        bases_map_;
   member_functions             virtual_mem_fns_;
-  bool                         is_struct_;
+  virtual_mem_fn_map_type                      virtual_mem_fns_map_;
+  bool                                         is_struct_;
 
   priv()
     : is_struct_(false)
@@ -15696,6 +15697,12 @@ void
 class_decl::on_canonical_type_set()
 {
   sort_virtual_mem_fns();
+
+  for (class_decl::virtual_mem_fn_map_type::iterator i =
+        priv_->virtual_mem_fns_map_.begin();
+       i != priv_->virtual_mem_fns_map_.end();
+       ++i)
+    sort_virtual_member_functions(i->second);
 }
 
 const class_decl_sptr
@@ -15763,6 +15770,25 @@ const class_decl::member_functions&
 class_decl::get_virtual_mem_fns() const
 {return priv_->virtual_mem_fns_;}
 
+/// Get the map that associates a virtual table offset to the virtual
+/// member functions with that virtual table offset.
+///
+/// Usually, there should be a 1:1 mapping between a given vtable
+/// offset and virtual member functions of that vtable offset.  But
+/// because of some implementation details, there can be several C++
+/// destructor functions that are *generated* by compilers, for a
+/// given destructor that is defined in the source code.  If the
+/// destructor is virtual then those generated functions have some
+/// DWARF attributes in common with the constructor that the user
+/// actually defined in its source code.  Among those attributes are
+/// the vtable offset of the destructor.
+///
+/// @return the map that associates a virtual table offset to the
+/// virtual member functions with that virtual table offset.
+const class_decl::virtual_mem_fn_map_type&
+class_decl::get_virtual_mem_fns_map() const
+{return priv_->virtual_mem_fns_map_;}
+
 /// Sort the virtual member functions by their virtual index.
 void
 class_decl::sort_virtual_mem_fns()
@@ -16336,8 +16362,8 @@ class_decl::add_member_function(method_decl_sptr f,
 {
   class_or_union::add_member_function(f, a, is_static, is_ctor,
                                      is_dtor, is_const);
-  set_member_function_is_virtual(f, is_virtual);
   set_member_function_vtable_offset(f, vtable_offset);
+  set_member_function_is_virtual(f, is_virtual);
 
   if (is_virtual)
     sort_virtual_member_functions(priv_->virtual_mem_fns_);
@@ -16345,8 +16371,8 @@ class_decl::add_member_function(method_decl_sptr f,
 
 /// When a virtual member function has seen its virtualness set by
 /// set_member_function_is_virtual(), this function ensures that the
-/// member function is added to the specific vectors of virtual member
-/// function of its class.
+/// member function is added to the specific vectors and maps of
+/// virtual member function of its class.
 ///
 /// @param method the method to fixup.
 void
@@ -16356,7 +16382,8 @@ fixup_virtual_member_function(method_decl_sptr method)
     return;
 
   class_decl_sptr klass = is_class_type(method->get_type()->get_class_type());
-  class_decl::member_functions::iterator m;
+
+  class_decl::member_functions::const_iterator m;
   for (m = klass->priv_->virtual_mem_fns_.begin();
        m != klass->priv_->virtual_mem_fns_.end();
        ++m)
@@ -16364,6 +16391,26 @@ fixup_virtual_member_function(method_decl_sptr method)
       break;
   if (m == klass->priv_->virtual_mem_fns_.end())
     klass->priv_->virtual_mem_fns_.push_back(method);
+
+  // Build or udpate the map that associates a vtable offset to the
+  // number of virtual member functions that "point" to it.
+  size_t voffset = get_member_function_vtable_offset(method);
+  class_decl::virtual_mem_fn_map_type::iterator i =
+    klass->priv_->virtual_mem_fns_map_.find(voffset);
+  if (i == klass->priv_->virtual_mem_fns_map_.end())
+    {
+      class_decl::member_functions virtual_mem_fns_at_voffset;
+      virtual_mem_fns_at_voffset.push_back(method);
+      klass->priv_->virtual_mem_fns_map_[voffset] = virtual_mem_fns_at_voffset;
+    }
+  else
+    {
+      for (m = i->second.begin() ; m != i->second.end(); ++m)
+       if (m->get() == method.get())
+         break;
+      if (m == i->second.end())
+       i->second.push_back(method);
+    }
 }
 
 /// Return true iff the class has no entity in its scope.
index b773fdf6c754f51c7fef217ec38e6cf71ba88e8c..e1dc0e0fcd85f0332e8485c88c872a4cbf942091 100644 (file)
@@ -4182,8 +4182,8 @@ build_class_decl(read_context&            ctxt,
                  assert(m);
                  set_member_access_specifier(m, access);
                  set_member_is_static(m, is_static);
-                 set_member_function_is_virtual(m, is_virtual);
                  set_member_function_vtable_offset(m, vtable_offset);
+                 set_member_function_is_virtual(m, is_virtual);
                  set_member_function_is_ctor(m, is_ctor);
                  set_member_function_is_dtor(m, is_dtor);
                  set_member_function_is_const(m, is_const);
This page took 0.063929 seconds and 5 git commands to generate.