diff options
author | Jan Hubicka <hubicka@ucw.cz> | 2014-08-15 01:30:46 +0200 |
---|---|---|
committer | Jan Hubicka <hubicka@gcc.gnu.org> | 2014-08-14 23:30:46 +0000 |
commit | 56b1f114de93c27600b9b295ff7efcf9caedfc72 (patch) | |
tree | 4aece5efbbebf94d2b39aa6940862dedbf57f883 /gcc/ipa-devirt.c | |
parent | aa0a659ca69cf092fcfb6ebb58a749b63a04be48 (diff) | |
download | gcc-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.c | 114 |
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. |