summaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog5
-rw-r--r--gcc/ipa-devirt.c114
-rw-r--r--gcc/ipa-utils.h1
-rw-r--r--gcc/lto/ChangeLog4
-rw-r--r--gcc/lto/lto-symtab.c4
5 files changed, 128 insertions, 0 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 8f731ca5d8f..223e484a368 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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
diff --git a/gcc/ipa-devirt.c b/gcc/ipa-devirt.c
index 0f38655382d..2d356ad73b9 100644
--- a/gcc/ipa-devirt.c
+++ b/gcc/ipa-devirt.c
@@ -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.
diff --git a/gcc/ipa-utils.h b/gcc/ipa-utils.h
index 3801525ae7d..30adc6907d2 100644
--- a/gcc/ipa-utils.h
+++ b/gcc/ipa-utils.h
@@ -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.
diff --git a/gcc/lto/ChangeLog b/gcc/lto/ChangeLog
index 3483711e0db..2e3a1563775 100644
--- a/gcc/lto/ChangeLog
+++ b/gcc/lto/ChangeLog
@@ -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
diff --git a/gcc/lto/lto-symtab.c b/gcc/lto/lto-symtab.c
index 2332225afd4..aae865a0290 100644
--- a/gcc/lto/lto-symtab.c
+++ b/gcc/lto/lto-symtab.c
@@ -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),