aboutsummaryrefslogtreecommitdiff
path: root/gcc/ipa-devirt.c
diff options
context:
space:
mode:
authorJan Hubicka <hubicka@ucw.cz>2014-08-15 01:30:46 +0200
committerJan Hubicka <hubicka@gcc.gnu.org>2014-08-14 23:30:46 +0000
commit56b1f114de93c27600b9b295ff7efcf9caedfc72 (patch)
tree4aece5efbbebf94d2b39aa6940862dedbf57f883 /gcc/ipa-devirt.c
parentaa0a659ca69cf092fcfb6ebb58a749b63a04be48 (diff)
downloadgcc-56b1f114de93c27600b9b295ff7efcf9caedfc72.zip
gcc-56b1f114de93c27600b9b295ff7efcf9caedfc72.tar.gz
gcc-56b1f114de93c27600b9b295ff7efcf9caedfc72.tar.bz2
ipa-utils.h (compare_virtual_tables): Declare.
* ipa-utils.h (compare_virtual_tables): Declare. * ipa-devirt.c (odr_subtypes_equivalent_p): New function * lto-symtab.c (lto_varpool_replace_node): Call compare_virtual_tables. From-SVN: r213990
Diffstat (limited to 'gcc/ipa-devirt.c')
-rw-r--r--gcc/ipa-devirt.c114
1 files changed, 114 insertions, 0 deletions
diff --git a/gcc/ipa-devirt.c b/gcc/ipa-devirt.c
index 0f38655..2d356ad 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.