Avoid adding the same base class twice
authorDodji Seketeli <dodji@redhat.com>
Mon, 4 Jan 2016 15:48:33 +0000 (16:48 +0100)
committerDodji Seketeli <dodji@redhat.com>
Mon, 4 Jan 2016 18:58:02 +0000 (19:58 +0100)
When looking at bug
https://sourceware.org/bugzilla/show_bug.cgi?id=19355, it appears that
some class have the same base class more than once.

Here is why.

Sometime in the DWARF, a given class is declared briefly, and then
later, it's amended.  Sometimes, when the class is updated, the debug
info contains redundant information, like base classes that were
previously expressed, and which are expressed again in the updated
version of the class.  The DWARF reader needs to not add that
duplicated information.

It appears the DWARF reader fails to recognize redundant base class
specifiers.  The native xml reader which is supposed to recognize
those, has some logic error that prevents it from working correctly.

This patch fixes both the DWARF and native xml readers.

The patch has no test because the r300_dri.so binary is really big and
still takes too much time to process, for it to be a practical
candidate for the regression test suite.

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

index 21f48ae..387c745 100644 (file)
@@ -6752,6 +6752,8 @@ build_class_type_and_add_to_ir(read_context&      ctxt,
                                               is_virt));
              if (b->get_is_declaration_only())
                assert(ctxt.is_decl_only_class_scheduled_for_resolution(b));
+             if (result->find_base_class(b->get_qualified_name()))
+               continue;
              result->add_base_specifier(base);
            }
          // Handle data members.
index 3c19481..81e50a4 100644 (file)
@@ -3379,20 +3379,13 @@ build_class_decl(read_context&          ctxt,
        return previous_declaration;
     }
 
-  // A flag to know if we are reading a class definition, that we've
-  // read before, but to which we'll maybe need to add new data
-  // members, member types, or base classes.
-  bool updating = false;
   if (!is_decl_only && previous_definition)
-    {
-      decl = previous_definition;
-      // So, we are precisely in the case where we've read this class
-      // definition before, but we might need to update it to add some
-      // new stuff to it; we might thus find the new stuff to add in
-      // the current (new) incarnation of that definition that we are
-      // currently reading.
-      updating = true;
-    }
+    // We are in the case where we've read this class definition
+    // before, but we might need to update it to add some new stuff to
+    // it; we might thus find the new stuff to add in the current
+    // (new) incarnation of that definition that we are currently
+    // reading.
+    decl = previous_definition;
   else
     {
       if (is_decl_only)
@@ -3484,8 +3477,7 @@ build_class_decl(read_context&            ctxt,
            (ctxt.build_or_get_type_decl(type_id, true));
          assert(b);
 
-         if (updating
-             && previous_definition->find_base_class(b->get_qualified_name()))
+         if (decl->find_base_class(b->get_qualified_name()))
            // We are in updating mode for this class.  The version of
            // the class we have already has this base class, so we
            // are not going to add it again.
@@ -3563,8 +3555,7 @@ build_class_decl(read_context&            ctxt,
              if (shared_ptr<var_decl> v =
                  build_var_decl(ctxt, p, /*add_to_current_scope=*/false))
                {
-                 if (updating
-                     && previous_definition->find_data_member(v->get_name()))
+                 if (decl->find_data_member(v->get_name()))
                    {
                      // We are in updating mode and the current
                      // version of this class already has this data
@@ -3573,7 +3564,7 @@ build_class_decl(read_context&            ctxt,
                      // built (and that was pushed to the current
                      // stack of decls built) and move on.
                      decl_base_sptr d = ctxt.pop_decl();
-                     is_var_decl(d);
+                     assert(is_var_decl(d));
                      continue;
                    }
                  decl->add_data_member(v, access,