From f8a1abf8e3dc2ef5cb47a13f14e6a7ec8113a46f Mon Sep 17 00:00:00 2001 From: Jan Hubicka Date: Tue, 29 Mar 2016 21:37:55 +0200 Subject: [PATCH] re PR lto/70283 (bogus vtable mismatch warnings) PR ipa/70283 * ipa-devirt.c (methods_equal_p): New function. (compare_virtual_tables): Use it. * cgraph.h (symbol_table::symbol_suffix_separator): Declare. * cgraphclones.c (clone_function_name_1): Use symbol_table::symbol_suffix_separator. * coverage.c (build_var): Likewise. * symtab.c (symbol_table::symbol_suffix_separator): New. From-SVN: r234532 --- gcc/ChangeLog | 11 +++++++++++ gcc/cgraph.h | 3 +++ gcc/cgraphclones.c | 8 +------- gcc/coverage.c | 6 +----- gcc/ipa-devirt.c | 44 ++++++++++++++++++++++++++++++++++---------- gcc/symtab.c | 14 ++++++++++++++ 6 files changed, 64 insertions(+), 22 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 042757895d66..866531fe0214 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,14 @@ +2016-03-10 Jan Hubicka + + PR ipa/70283 + * ipa-devirt.c (methods_equal_p): New function. + (compare_virtual_tables): Use it. + * cgraph.h (symbol_table::symbol_suffix_separator): Declare. + * cgraphclones.c (clone_function_name_1): Use + symbol_table::symbol_suffix_separator. + * coverage.c (build_var): Likewise. + * symtab.c (symbol_table::symbol_suffix_separator): New. + 2016-03-29 Jakub Jelinek PR rtl-optimization/70429 diff --git a/gcc/cgraph.h b/gcc/cgraph.h index d0345c698c51..e92928523992 100644 --- a/gcc/cgraph.h +++ b/gcc/cgraph.h @@ -2173,6 +2173,9 @@ public: FILE* GTY ((skip)) dump_file; + /* Return symbol used to separate symbol name from suffix. */ + static char symbol_suffix_separator (); + private: /* Allocate new callgraph node. */ inline cgraph_node * allocate_cgraph_symbol (void); diff --git a/gcc/cgraphclones.c b/gcc/cgraphclones.c index 354655e85d20..07ceb1a80d49 100644 --- a/gcc/cgraphclones.c +++ b/gcc/cgraphclones.c @@ -512,13 +512,7 @@ clone_function_name_1 (const char *name, const char *suffix) prefix = XALLOCAVEC (char, len + strlen (suffix) + 2); memcpy (prefix, name, len); strcpy (prefix + len + 1, suffix); -#ifndef NO_DOT_IN_LABEL - prefix[len] = '.'; -#elif !defined NO_DOLLAR_IN_LABEL - prefix[len] = '$'; -#else - prefix[len] = '_'; -#endif + prefix[len] = symbol_table::symbol_suffix_separator (); ASM_FORMAT_PRIVATE_NAME (tmp_name, prefix, clone_fn_id_num++); return get_identifier (tmp_name); } diff --git a/gcc/coverage.c b/gcc/coverage.c index e3bab61f4b61..b1fce7d0e7a4 100644 --- a/gcc/coverage.c +++ b/gcc/coverage.c @@ -745,11 +745,7 @@ build_var (tree fn_decl, tree type, int counter) else sprintf (buf, "__gcov%u_", counter); len = strlen (buf); -#ifndef NO_DOT_IN_LABEL - buf[len - 1] = '.'; -#elif !defined NO_DOLLAR_IN_LABEL - buf[len - 1] = '$'; -#endif + buf[len - 1] = symbol_table::symbol_suffix_separator (); memcpy (buf + len, fn_name, fn_name_len + 1); DECL_NAME (var) = get_identifier (buf); TREE_STATIC (var) = 1; diff --git a/gcc/ipa-devirt.c b/gcc/ipa-devirt.c index 4df171bc1160..069495105bfb 100644 --- a/gcc/ipa-devirt.c +++ b/gcc/ipa-devirt.c @@ -705,6 +705,29 @@ odr_subtypes_equivalent_p (tree t1, tree t2, return odr_types_equivalent_p (t1, t2, false, NULL, visited, loc1, loc2); } +/* Return true if DECL1 and DECL2 are identical methods. Consider + name equivalent to name.localalias.xyz. */ + +static bool +methods_equal_p (tree decl1, tree decl2) +{ + if (DECL_ASSEMBLER_NAME (decl1) == DECL_ASSEMBLER_NAME (decl2)) + return true; + const char sep = symbol_table::symbol_suffix_separator (); + + const char *name1 = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl1)); + const char *ptr1 = strchr (name1, sep); + int len1 = ptr1 ? ptr1 - name1 : strlen (name1); + + const char *name2 = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl2)); + const char *ptr2 = strchr (name2, sep); + int len2 = ptr2 ? ptr2 - name2 : strlen (name2); + + if (len1 != len2) + return false; + return !strncmp (name1, name2, len1); +} + /* Compare two virtual tables, PREVAILING and VTABLE and output ODR violation warnings. */ @@ -758,8 +781,8 @@ compare_virtual_tables (varpool_node *prevailing, varpool_node *vtable) accept the other case. */ while (!end2 && (end1 - || (DECL_ASSEMBLER_NAME (ref1->referred->decl) - != DECL_ASSEMBLER_NAME (ref2->referred->decl) + || (methods_equal_p (ref1->referred->decl, + ref2->referred->decl) && TREE_CODE (ref1->referred->decl) == FUNCTION_DECL)) && TREE_CODE (ref2->referred->decl) != FUNCTION_DECL) { @@ -785,8 +808,7 @@ compare_virtual_tables (varpool_node *prevailing, varpool_node *vtable) } while (!end1 && (end2 - || (DECL_ASSEMBLER_NAME (ref2->referred->decl) - != DECL_ASSEMBLER_NAME (ref1->referred->decl) + || (methods_equal_p (ref2->referred->decl, ref1->referred->decl) && TREE_CODE (ref2->referred->decl) == FUNCTION_DECL)) && TREE_CODE (ref1->referred->decl) != FUNCTION_DECL) { @@ -823,8 +845,7 @@ compare_virtual_tables (varpool_node *prevailing, varpool_node *vtable) if (!end1 && !end2) { - if (DECL_ASSEMBLER_NAME (ref1->referred->decl) - == DECL_ASSEMBLER_NAME (ref2->referred->decl)) + if (methods_equal_p (ref1->referred->decl, ref2->referred->decl)) continue; class_type->odr_violated = true; @@ -920,11 +941,14 @@ compare_virtual_tables (varpool_node *prevailing, varpool_node *vtable) "unit"); gcc_assert (TREE_CODE (ref2->referred->decl) == FUNCTION_DECL); - inform (DECL_SOURCE_LOCATION (ref1->referred->decl), - "virtual method %qD", ref1->referred->decl); - inform (DECL_SOURCE_LOCATION (ref2->referred->decl), + inform (DECL_SOURCE_LOCATION + (ref1->referred->ultimate_alias_target ()->decl), + "virtual method %qD", + ref1->referred->ultimate_alias_target ()->decl); + inform (DECL_SOURCE_LOCATION + (ref2->referred->ultimate_alias_target ()->decl), "ought to match virtual method %qD but does not", - ref2->referred->decl); + ref2->referred->ultimate_alias_target ()->decl); } else inform (DECL_SOURCE_LOCATION diff --git a/gcc/symtab.c b/gcc/symtab.c index 523c95dd29ea..2d7705e657cb 100644 --- a/gcc/symtab.c +++ b/gcc/symtab.c @@ -2137,3 +2137,17 @@ symtab_node::definition_alignment () call_for_symbol_and_aliases (get_alignment_1, &align, true); return align; } + +/* Return symbol used to separate symbol name from suffix. */ + +char +symbol_table::symbol_suffix_separator () +{ +#ifndef NO_DOT_IN_LABEL + return '.'; +#elif !defined NO_DOLLAR_IN_LABEL + return '$'; +#else + return '_'; +#endif +}