Hello. The patches makes a small refactoring in ipa-devirt.c and comes up with a handy debugging function debug_tree_odr_name.
Patch can bootstrap on x86_64-linux-gnu and survives regression tests. Ready to be installed? Thanks, Martin gcc/ChangeLog: 2019-12-02 Martin Liska <mli...@suse.cz> * ipa-devirt.c (warn_types_mismatch): Use get_odr_name_for_type. * print-tree.c (debug_tree_odr_name): New. * print-tree.h (debug_tree_odr_name): New. * tree.h (get_odr_name_for_type): New. gcc/testsuite/ChangeLog: 2019-12-02 Martin Liska <mli...@suse.cz> * g++.dg/lto/odr-7_0.C: New test. * g++.dg/lto/odr-7_1.C: New test. --- gcc/ipa-devirt.c | 21 +++++++-------------- gcc/print-tree.c | 17 +++++++++++++++++ gcc/print-tree.h | 1 + gcc/testsuite/g++.dg/lto/odr-7_0.C | 18 ++++++++++++++++++ gcc/testsuite/g++.dg/lto/odr-7_1.C | 13 +++++++++++++ gcc/tree.h | 13 +++++++++++++ 6 files changed, 69 insertions(+), 14 deletions(-) create mode 100644 gcc/testsuite/g++.dg/lto/odr-7_0.C create mode 100644 gcc/testsuite/g++.dg/lto/odr-7_1.C
diff --git a/gcc/ipa-devirt.c b/gcc/ipa-devirt.c index a884a465a5d..e53461b1f5c 100644 --- a/gcc/ipa-devirt.c +++ b/gcc/ipa-devirt.c @@ -1036,20 +1036,13 @@ warn_types_mismatch (tree t1, tree t2, location_t loc1, location_t loc2) /* If types have mangled ODR names and they are different, it is most informative to output those. This also covers types defined in different namespaces. */ - if (TYPE_NAME (mt1) && TYPE_NAME (mt2) - && TREE_CODE (TYPE_NAME (mt1)) == TYPE_DECL - && TREE_CODE (TYPE_NAME (mt2)) == TYPE_DECL - && DECL_ASSEMBLER_NAME_SET_P (TYPE_NAME (mt1)) - && DECL_ASSEMBLER_NAME_SET_P (TYPE_NAME (mt2)) - && DECL_ASSEMBLER_NAME (TYPE_NAME (mt1)) - != DECL_ASSEMBLER_NAME (TYPE_NAME (mt2))) - { - char *name1 = xstrdup (cplus_demangle - (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (TYPE_NAME (mt1))), - DMGL_PARAMS | DMGL_ANSI | DMGL_TYPES)); - char *name2 = cplus_demangle - (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (TYPE_NAME (mt2))), - DMGL_PARAMS | DMGL_ANSI | DMGL_TYPES); + const char *odr1 = get_odr_name_for_type (mt1); + const char *odr2 = get_odr_name_for_type (mt2); + if (odr1 != NULL && odr2 != NULL && odr1 != odr2) + { + const int opts = DMGL_PARAMS | DMGL_ANSI | DMGL_TYPES; + char *name1 = xstrdup (cplus_demangle (odr1, opts)); + char *name2 = xstrdup (cplus_demangle (odr2, opts)); if (name1 && name2 && strcmp (name1, name2)) { inform (loc_t1, diff --git a/gcc/print-tree.c b/gcc/print-tree.c index bd09ec4d7a7..5e728a2641a 100644 --- a/gcc/print-tree.c +++ b/gcc/print-tree.c @@ -34,6 +34,7 @@ along with GCC; see the file COPYING3. If not see #include "tree-cfg.h" #include "dumpfile.h" #include "print-tree.h" +#include "demangle.h" /* Define the hash table of nodes already seen. Such nodes are not repeated; brief cross-references are used. */ @@ -1141,6 +1142,22 @@ debug_raw (const tree_node *ptr) fprintf (stderr, "<nil>\n"); } +/* Print ODR name of a TYPE if available. + Use demangler when option DEMANGLE is used. */ + +DEBUG_FUNCTION void +debug_tree_odr_name (tree type, bool demangle) +{ + const char *odr = get_odr_name_for_type (type); + if (demangle) + { + const int opts = DMGL_PARAMS | DMGL_ANSI | DMGL_TYPES; + odr = cplus_demangle (odr, opts); + } + + fprintf (stderr, "%s\n", odr); +} + static void dump_tree_via_hooks (const tree_node *ptr, dump_flags_t options) { diff --git a/gcc/print-tree.h b/gcc/print-tree.h index cbea48c486e..10b8df53ac7 100644 --- a/gcc/print-tree.h +++ b/gcc/print-tree.h @@ -23,6 +23,7 @@ along with GCC; see the file COPYING3. If not see extern void debug_tree (tree); extern void debug_raw (const tree_node &ref); extern void debug_raw (const tree_node *ptr); +extern void debug_tree_odr_name (tree, bool demangle = true); extern void debug (const tree_node &ref); extern void debug (const tree_node *ptr); extern void debug_verbose (const tree_node &ref); diff --git a/gcc/testsuite/g++.dg/lto/odr-7_0.C b/gcc/testsuite/g++.dg/lto/odr-7_0.C new file mode 100644 index 00000000000..e33b8192bc1 --- /dev/null +++ b/gcc/testsuite/g++.dg/lto/odr-7_0.C @@ -0,0 +1,18 @@ +// { dg-lto-do link } + +struct bar // { dg-lto-message "type name 'bar' should match type name 'foobar<float>'" } +{ + int xxx; +}; + +struct foo // { dg-lto-warning "8: 'struct foo' violates the C\\+\\+ One Definition Rule" } +{ + bar a; +}; + +foo myfoo2; + +int +main() +{ +} diff --git a/gcc/testsuite/g++.dg/lto/odr-7_1.C b/gcc/testsuite/g++.dg/lto/odr-7_1.C new file mode 100644 index 00000000000..464bd895900 --- /dev/null +++ b/gcc/testsuite/g++.dg/lto/odr-7_1.C @@ -0,0 +1,13 @@ +template <class T> +struct foobar +{ + int xxx; + T pes; +}; + +struct foo +{ + foobar<float> a; +}; + +foo myfoo; diff --git a/gcc/tree.h b/gcc/tree.h index 0f3cc5d7e5a..40a4fde6aec 100644 --- a/gcc/tree.h +++ b/gcc/tree.h @@ -6222,6 +6222,19 @@ fndecl_built_in_p (const_tree node, built_in_function name) && DECL_FUNCTION_CODE (node) == name); } +/* If TYPE has mangled ODR name, return it. Otherwise return NULL. */ + +inline const char * +get_odr_name_for_type (tree type) +{ + tree type_name = TYPE_NAME (type); + if (type_name == NULL_TREE + || !DECL_ASSEMBLER_NAME_SET_P (type_name)) + return NULL; + + return IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (type_name)); +} + /* A struct for encapsulating location information about an operator and the operation built from it.