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
This commit is contained in:
Jan Hubicka 2014-08-15 01:30:46 +02:00 committed by Jan Hubicka
parent aa0a659ca6
commit 56b1f114de
5 changed files with 128 additions and 0 deletions

View 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

View 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.

View 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.

View 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

View 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),