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.