Martin Liška <mli...@suse.cz> writes:
> 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));

This adds an xstrdup for name2.  Is that intentional or just a pasto?
The old code assumed that the demangler buffer wouldn't be reused by
the diagnostics machinery, but maybe copying the buffer is more robust.
In that case though, we need to free name2 in the same way that we
already free name1.

In the patch below I went for removing the xstrdup, but I can add
the frees instead if that seems better.

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

This drops the TYPE_DECL test from the original code above, which
causes an ICE for C tags.

Tested on aarch64-linux-gnu and x86_64-linux-gnu.  OK to install?

Thanks,
Richard


2019-12-09  Richard Sandiford  <richard.sandif...@arm.com>

gcc/
        * ipa-utils.h (get_odr_name_for_type): Check for a TYPE_DECL.
        * ipa-devirt.c (warn_types_mismatch): Don't call xstrdup for the
        second demangled name.

gcc/testsuite/
        * gcc.dg/lto/tag-1_0.c, gcc.dg/lto/tag-1_1.c: New test.

Index: gcc/ipa-utils.h
===================================================================
--- gcc/ipa-utils.h     2019-12-09 12:23:47.000000000 +0000
+++ gcc/ipa-utils.h     2019-12-09 12:23:48.326292463 +0000
@@ -256,6 +256,7 @@ get_odr_name_for_type (tree type)
 {
   tree type_name = TYPE_NAME (type);
   if (type_name == NULL_TREE
+      || TREE_CODE (type_name) != TYPE_DECL
       || !DECL_ASSEMBLER_NAME_SET_P (type_name))
     return NULL;
 
Index: gcc/ipa-devirt.c
===================================================================
--- gcc/ipa-devirt.c    2019-12-09 12:23:47.000000000 +0000
+++ gcc/ipa-devirt.c    2019-12-09 12:23:48.326292463 +0000
@@ -1042,7 +1042,7 @@ warn_types_mismatch (tree t1, tree t2, l
     {
       const int opts = DMGL_PARAMS | DMGL_ANSI | DMGL_TYPES;
       char *name1 = xstrdup (cplus_demangle (odr1, opts));
-      char *name2 = xstrdup (cplus_demangle (odr2, opts));
+      char *name2 = cplus_demangle (odr2, opts);
       if (name1 && name2 && strcmp (name1, name2))
        {
          inform (loc_t1,
Index: gcc/testsuite/gcc.dg/lto/tag-1_0.c
===================================================================
--- /dev/null   2019-09-17 11:41:18.176664108 +0100
+++ gcc/testsuite/gcc.dg/lto/tag-1_0.c  2019-12-09 12:23:48.326292463 +0000
@@ -0,0 +1,5 @@
+/* { dg-lto-do link } */
+/* { dg-lto-options { { -Wodr -flto } } }  */
+
+struct foo { int x; };
+struct foo a = {};
Index: gcc/testsuite/gcc.dg/lto/tag-1_1.c
===================================================================
--- /dev/null   2019-09-17 11:41:18.176664108 +0100
+++ gcc/testsuite/gcc.dg/lto/tag-1_1.c  2019-12-09 12:23:48.326292463 +0000
@@ -0,0 +1,6 @@
+struct foo { short x; };
+
+extern struct foo a; /* { dg-lto-warning {type of 'a' does not match original 
declaration} } */
+struct foo *ptr = &a;
+
+int main () { return 0; }

Reply via email to