* ipa-utils.h (compare_virtual_tables): Declare.
authorhubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 14 Aug 2014 23:30:46 +0000 (23:30 +0000)
committerhubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 14 Aug 2014 23:30:46 +0000 (23:30 +0000)
* ipa-devirt.c (odr_subtypes_equivalent_p): New function

* lto-symtab.c (lto_varpool_replace_node): Call compare_virtual_tables.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@213990 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/ipa-devirt.c
gcc/ipa-utils.h
gcc/lto/ChangeLog
gcc/lto/lto-symtab.c

index 8f731ca..223e484 100644 (file)
@@ -1,3 +1,8 @@
+2014-08-14  Jan Hubicka  <hubicka@ucw.cz>
+
+       * ipa-utils.h (compare_virtual_tables): Declare.
+       * ipa-devirt.c (odr_subtypes_equivalent_p): New function
+
 2014-08-14  Marek Polacek  <polacek@redhat.com>
 
        DR 458
index 0f38655..2d356ad 100644 (file)
@@ -485,6 +485,120 @@ odr_subtypes_equivalent_p (tree t1, tree t2, hash_set<tree> *visited)
   return types_same_for_odr (t1, t2);
 }
 
+/* Compare two virtual tables, PREVAILING and VTABLE and output ODR
+   violation warings.  */
+
+void
+compare_virtual_tables (varpool_node *prevailing, varpool_node *vtable)
+{
+  int n1, n2;
+  if (DECL_VIRTUAL_P (prevailing->decl) != DECL_VIRTUAL_P (vtable->decl))
+    {
+      odr_violation_reported = true;
+      if (DECL_VIRTUAL_P (prevailing->decl))
+       {
+         varpool_node *tmp = prevailing;
+         prevailing = vtable;
+         vtable = tmp;
+       }
+      if (warning_at (DECL_SOURCE_LOCATION (TYPE_NAME (DECL_CONTEXT (vtable->decl))),
+                     OPT_Wodr,
+                     "virtual table of type %qD violates one definition rule",
+                     DECL_CONTEXT (vtable->decl)))
+       inform (DECL_SOURCE_LOCATION (prevailing->decl),
+               "variable of same assembler name as the virtual table is "
+               "defined in another translation unit");
+      return;
+    }
+  if (!prevailing->definition || !vtable->definition)
+    return;
+  for (n1 = 0, n2 = 0; true; n1++, n2++)
+    {
+      struct ipa_ref *ref1, *ref2;
+      bool end1, end2;
+      end1 = !prevailing->iterate_reference (n1, ref1);
+      end2 = !vtable->iterate_reference (n2, ref2);
+      if (end1 && end2)
+       return;
+      if (!end1 && !end2
+         && DECL_ASSEMBLER_NAME (ref1->referred->decl)
+            != DECL_ASSEMBLER_NAME (ref2->referred->decl)
+         && !n2
+         && !DECL_VIRTUAL_P (ref2->referred->decl)
+         && DECL_VIRTUAL_P (ref1->referred->decl))
+       {
+         if (warning_at (DECL_SOURCE_LOCATION (TYPE_NAME (DECL_CONTEXT (vtable->decl))), 0,
+                         "virtual table of type %qD contains RTTI information",
+                         DECL_CONTEXT (vtable->decl)))
+           {
+             inform (DECL_SOURCE_LOCATION (TYPE_NAME (DECL_CONTEXT (prevailing->decl))),
+                     "but is prevailed by one without from other translation unit");
+             inform (DECL_SOURCE_LOCATION (TYPE_NAME (DECL_CONTEXT (prevailing->decl))),
+                     "RTTI will not work on this type");
+           }
+         n2++;
+          end2 = !vtable->iterate_reference (n2, ref2);
+       }
+      if (!end1 && !end2
+         && DECL_ASSEMBLER_NAME (ref1->referred->decl)
+            != DECL_ASSEMBLER_NAME (ref2->referred->decl)
+         && !n1
+         && !DECL_VIRTUAL_P (ref1->referred->decl)
+         && DECL_VIRTUAL_P (ref2->referred->decl))
+       {
+         n1++;
+          end1 = !vtable->iterate_reference (n1, ref1);
+       }
+      if (end1 || end2)
+       {
+         if (end1)
+           {
+             varpool_node *tmp = prevailing;
+             prevailing = vtable;
+             vtable = tmp;
+             ref1 = ref2;
+           }
+         if (warning_at (DECL_SOURCE_LOCATION
+                           (TYPE_NAME (DECL_CONTEXT (vtable->decl))), 0,
+                         "virtual table of type %qD violates "
+                         "one definition rule",
+                         DECL_CONTEXT (vtable->decl)))
+           {
+             inform (DECL_SOURCE_LOCATION
+                      (TYPE_NAME (DECL_CONTEXT (prevailing->decl))),
+                     "the conflicting type defined in another translation "
+                     "unit");
+             inform (DECL_SOURCE_LOCATION
+                       (TYPE_NAME (DECL_CONTEXT (ref1->referring->decl))),
+                     "contains additional virtual method %qD",
+                     ref1->referred->decl);
+           }
+         return;
+       }
+      if (DECL_ASSEMBLER_NAME (ref1->referred->decl)
+         != DECL_ASSEMBLER_NAME (ref2->referred->decl))
+       {
+         if (warning_at (DECL_SOURCE_LOCATION
+                           (TYPE_NAME (DECL_CONTEXT (vtable->decl))), 0,
+                         "virtual table of type %qD violates "
+                         "one definition rule  ",
+                         DECL_CONTEXT (vtable->decl)))
+           {
+             inform (DECL_SOURCE_LOCATION 
+                       (TYPE_NAME (DECL_CONTEXT (prevailing->decl))),
+                     "the conflicting type defined in another translation "
+                     "unit");
+             inform (DECL_SOURCE_LOCATION (ref1->referred->decl),
+                     "virtual method %qD", ref1->referred->decl);
+             inform (DECL_SOURCE_LOCATION (ref2->referred->decl),
+                     "ought to match virtual method %qD but does not",
+                     ref2->referred->decl);
+             return;
+           }
+       }
+    }
+}
+
 /* Output ODR violation warning about T1 and T2 with REASON.
    Display location of ST1 and ST2 if REASON speaks about field or
    method of the type.
index 3801525..30adc69 100644 (file)
@@ -101,6 +101,7 @@ bool get_polymorphic_call_info_from_invariant (ipa_polymorphic_call_context *,
 bool decl_maybe_in_construction_p (tree, tree, gimple, tree);
 tree vtable_pointer_value_to_binfo (const_tree);
 bool vtable_pointer_value_to_vtable (const_tree, tree *, unsigned HOST_WIDE_INT *);
+void compare_virtual_tables (varpool_node *, varpool_node *);
 bool contains_polymorphic_type_p (const_tree);
 
 /* Return vector containing possible targets of polymorphic call E.
index 3483711..2e3a156 100644 (file)
@@ -1,3 +1,7 @@
+2014-08-14  Jan Hubicka  <hubicka@ucw.cz>
+
+       * lto-symtab.c (lto_varpool_replace_node): Call compare_virtual_tables.
+
 2014-08-14  Richard Biener  <rguenther@suse.de>
 
        PR lto/62067
index 2332225..aae865a 100644 (file)
@@ -117,6 +117,10 @@ lto_varpool_replace_node (varpool_node *vnode,
       && vnode->decl != prevailing_node->decl)
     DECL_INITIAL (vnode->decl) = error_mark_node;
 
+  /* Check and report ODR violations on virtual tables.  */
+  if (DECL_VIRTUAL_P (vnode->decl) || DECL_VIRTUAL_P (prevailing_node->decl))
+    compare_virtual_tables (prevailing_node, vnode);
+
   if (vnode->tls_model != prevailing_node->tls_model)
     {
       error_at (DECL_SOURCE_LOCATION (vnode->decl),