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.
 

Reply via email to