Marek Polacek <pola...@redhat.com> writes:
> On Thu, Oct 10, 2019 at 08:00:53PM +0100, Richard Sandiford wrote:
>> Ping
>> 
>> Richard Sandiford <richard.sandif...@arm.com> writes:
>> > The current aka diagnostics can sometimes leak internal details that
>> > seem more likely to be distracting than useful.  E.g. on aarch64:
>> >
>> >   void f (va_list *va) { *va = 1; }
>> >
>> > gives:
>> >
>> >   incompatible types when assigning to type ‘va_list’ {aka ‘__va_list’} 
>> > from type ‘int’
>> >
>> > where __va_list isn't something the user is expected to know about.
>> > A similar thing happens for C++ on the arm_neon.h-based:
>> >
>> >   float x;
>> >   int8x8_t y = x;
>> >
>> > which gives:
>> >
>> >   cannot convert ‘float’ to ‘int8x8_t’ {aka ‘__Int8x8_t’} in initialization
>> >
>> > This is accurate -- and __Int8x8_t is defined by the AArch64 PCS --
>> > but it's not going to be meaningful to most users.
>
> Agreed.
>
>> +/* Return true if it is worth exposing the DECL_ORIGINAL_TYPE of TYPE to
>> +   the user in diagnostics, false if it would be better to use TYPE itself.
>> +   TYPE is known to satisfy typedef_variant_p.  */
>> +
>> +bool
>> +user_facing_original_type_p (const_tree type)
>> +{
>> +  gcc_assert (typedef_variant_p (type));
>> +  tree decl = TYPE_NAME (type);
>> +
>> +  /* Look through any typedef in "user" code.  */
>> +  if (!DECL_IN_SYSTEM_HEADER (decl) && !DECL_IS_BUILTIN (decl))
>> +    return true;
>> +
>> +  /* If the original type is also named and is in the user namespace,
>> +     assume it too is a user-facing type.  */
>> +  tree orig_type = DECL_ORIGINAL_TYPE (decl);
>> +  if (tree orig_id = TYPE_IDENTIFIER (orig_type))
>> +    {
>> +      const char *name = IDENTIFIER_POINTER (orig_id);
>> +      if (name[0] != '_' || (name[1] != '_' && !ISUPPER (name[1])))
>> +    return true;
>
> This looks like name_reserved_for_implementation_p.
>
> The rest looks fine to me!

Ah, nice!  I'd looked for a helper but missed that one.

Here's just the C parts, with that change.  Tested on aarch64-linux-gnu
and x86_64-linux-gnu.  OK to install?

Richard


2019-10-11  Richard Sandiford  <richard.sandif...@arm.com>

gcc/c-family/
        * c-common.h (user_facing_original_type_p): Declare.
        * c-common.c: Include c-spellcheck.h.
        (user_facing_original_type_p): New function.

gcc/c/
        * c-objc-common.c (useful_aka_type_p): Replace with...
        (get_aka_type): ...this new function.  Given the original type,
        decide which aka type to print (if any).  Only look through typedefs
        if user_facing_original_type_p.
        (print_type): Update accordingly.

gcc/testsuite/
        * gcc.dg/diag-aka-5.h: New test.
        * gcc.dg/diag-aka-5a.c: Likewise.
        * gcc.dg/diag-aka-5b.c: Likewise.
        * gcc.target/aarch64/diag_aka_1.c (f): Expect an aka to be printed
        for myvec.

Index: gcc/c-family/c-common.h
===================================================================
--- gcc/c-family/c-common.h     2019-10-08 09:23:43.000000000 +0100
+++ gcc/c-family/c-common.h     2019-10-11 15:12:08.552939853 +0100
@@ -1063,6 +1063,7 @@ extern tree builtin_type_for_size (int,
 extern void c_common_mark_addressable_vec (tree);
 
 extern void set_underlying_type (tree);
+extern bool user_facing_original_type_p (const_tree);
 extern void record_types_used_by_current_var_decl (tree);
 extern vec<tree, va_gc> *make_tree_vector (void);
 extern void release_tree_vector (vec<tree, va_gc> *);
Index: gcc/c-family/c-common.c
===================================================================
--- gcc/c-family/c-common.c     2019-10-08 09:23:43.000000000 +0100
+++ gcc/c-family/c-common.c     2019-10-11 15:12:08.552939853 +0100
@@ -48,6 +48,7 @@ #define GCC_C_COMMON_C
 #include "gimplify.h"
 #include "substring-locations.h"
 #include "spellcheck.h"
+#include "c-spellcheck.h"
 #include "selftest.h"
 
 cpp_reader *parse_in;          /* Declared in c-pragma.h.  */
@@ -7713,6 +7714,52 @@ set_underlying_type (tree x)
     }
 }
 
+/* Return true if it is worth exposing the DECL_ORIGINAL_TYPE of TYPE to
+   the user in diagnostics, false if it would be better to use TYPE itself.
+   TYPE is known to satisfy typedef_variant_p.  */
+
+bool
+user_facing_original_type_p (const_tree type)
+{
+  gcc_assert (typedef_variant_p (type));
+  tree decl = TYPE_NAME (type);
+
+  /* Look through any typedef in "user" code.  */
+  if (!DECL_IN_SYSTEM_HEADER (decl) && !DECL_IS_BUILTIN (decl))
+    return true;
+
+  /* If the original type is also named and is in the user namespace,
+     assume it too is a user-facing type.  */
+  tree orig_type = DECL_ORIGINAL_TYPE (decl);
+  if (tree orig_id = TYPE_IDENTIFIER (orig_type))
+    if (!name_reserved_for_implementation_p (IDENTIFIER_POINTER (orig_id)))
+      return true;
+
+  switch (TREE_CODE (orig_type))
+    {
+    /* Don't look through to an anonymous vector type, since the syntax
+       we use for them in diagnostics isn't real C or C++ syntax.
+       And if ORIG_TYPE is named but in the implementation namespace,
+       TYPE is likely to be more meaningful to the user.  */
+    case VECTOR_TYPE:
+      return false;
+
+    /* Don't expose anonymous tag types that are presumably meant to be
+       known by their typedef name.  Also don't expose tags that are in
+       the implementation namespace, such as:
+
+         typedef struct __foo foo;  */
+    case RECORD_TYPE:
+    case UNION_TYPE:
+    case ENUMERAL_TYPE:
+      return false;
+
+    /* Look through to anything else.  */
+    default:
+      return true;
+    }
+}
+
 /* Record the types used by the current global variable declaration
    being parsed, so that we can decide later to emit their debug info.
    Those types are in types_used_by_cur_var_decl, and we are going to
Index: gcc/c/c-objc-common.c
===================================================================
--- gcc/c/c-objc-common.c       2019-10-08 09:23:43.000000000 +0100
+++ gcc/c/c-objc-common.c       2019-10-11 15:12:08.552939853 +0100
@@ -28,6 +28,8 @@ Software Foundation; either version 3, o
 #include "langhooks.h"
 #include "c-objc-common.h"
 #include "gcc-rich-location.h"
+#include "stringpool.h"
+#include "attribs.h"
 
 static bool c_tree_printer (pretty_printer *, text_info *, const char *,
                            int, bool, bool, bool, bool *, const char **);
@@ -62,71 +64,120 @@ c_objc_common_init (void)
   return c_common_init ();
 }
 
-/* Return true if it's worth saying that TYPE1 is also known as TYPE2.  */
+/* Decide whether it's worth saying that TYPE is also known as some other
+   type.  Return the other type if so, otherwise return TYPE.  */
 
-static bool
-useful_aka_type_p (tree type1, tree type2)
+static tree
+get_aka_type (tree type)
 {
-  if (type1 == type2)
-    return false;
-
-  if (type1 == error_mark_node || type2 == error_mark_node)
-    return false;
-
-  if (TREE_CODE (type1) != TREE_CODE (type2))
-    return true;
+  if (type == error_mark_node)
+    return type;
 
-  if (typedef_variant_p (type1))
+  tree result;
+  if (typedef_variant_p (type))
     {
       /* Saying that "foo" is also known as "struct foo" or
         "struct <anonymous>" is unlikely to be useful, since users of
         structure-like types would already know that they're structures.
         The same applies to unions and enums; in general, printing the
         tag is only useful if it has a different name.  */
-      tree_code code = TREE_CODE (type2);
-      tree id2 = TYPE_IDENTIFIER (type2);
+      tree orig_type = DECL_ORIGINAL_TYPE (TYPE_NAME (type));
+      tree_code code = TREE_CODE (orig_type);
+      tree orig_id = TYPE_IDENTIFIER (orig_type);
       if ((code == RECORD_TYPE || code == UNION_TYPE || code == ENUMERAL_TYPE)
-         && (!id2 || TYPE_IDENTIFIER (type1) == id2))
-       return false;
+         && (!orig_id || TYPE_IDENTIFIER (type) == orig_id))
+       return type;
 
-      return true;
+      if (!user_facing_original_type_p (type))
+       return type;
+
+      result = get_aka_type (orig_type);
     }
   else
     {
-      switch (TREE_CODE (type1))
+      tree canonical = TYPE_CANONICAL (type);
+      if (canonical && TREE_CODE (type) != TREE_CODE (canonical))
+       return canonical;
+
+      /* Recursive calls might choose a middle ground between TYPE
+        (which has no typedefs stripped) and CANONICAL (which has
+        all typedefs stripped).  So try to reuse TYPE or CANONICAL if
+        convenient, but be prepared to create a new type if necessary.  */
+      switch (TREE_CODE (type))
        {
        case POINTER_TYPE:
        case REFERENCE_TYPE:
-         return useful_aka_type_p (TREE_TYPE (type1), TREE_TYPE (type2));
+         {
+           tree target_type = get_aka_type (TREE_TYPE (type));
+
+           if (target_type == TREE_TYPE (type))
+             return type;
+
+           if (canonical && target_type == TREE_TYPE (canonical))
+             return canonical;
+
+           result = (TREE_CODE (type) == POINTER_TYPE
+                     ? build_pointer_type (target_type)
+                     : build_reference_type (target_type));
+           break;
+         }
 
        case ARRAY_TYPE:
-         return (useful_aka_type_p (TYPE_DOMAIN (type1), TYPE_DOMAIN (type2))
-                 || useful_aka_type_p (TREE_TYPE (type1), TREE_TYPE (type2)));
+         {
+           tree element_type = get_aka_type (TREE_TYPE (type));
+           tree index_type = (TYPE_DOMAIN (type)
+                              ? get_aka_type (TYPE_DOMAIN (type))
+                              : NULL_TREE);
+
+           if (element_type == TREE_TYPE (type)
+               && index_type == TYPE_DOMAIN (type))
+             return type;
+
+           if (canonical
+               && element_type == TREE_TYPE (canonical)
+               && index_type == TYPE_DOMAIN (canonical))
+             return canonical;
+
+           result = build_array_type (element_type, index_type,
+                                      TYPE_TYPELESS_STORAGE (type));
+           break;
+         }
 
        case FUNCTION_TYPE:
          {
-           tree args1 = TYPE_ARG_TYPES (type1);
-           tree args2 = TYPE_ARG_TYPES (type2);
-           while (args1 != args2)
+           tree return_type = get_aka_type (TREE_TYPE (type));
+
+           tree args = TYPE_ARG_TYPES (type);
+           if (args == error_mark_node)
+             return type;
+
+           auto_vec<tree, 32> arg_types;
+           bool type_ok_p = true;
+           while (args && args != void_list_node)
              {
-               /* Although this shouldn't happen, it seems to wrong to assert
-                  for it in a diagnostic routine.  */
-               if (!args1 || args1 == void_type_node)
-                 return true;
-               if (!args2 || args2 == void_type_node)
-                 return true;
-               if (useful_aka_type_p (TREE_VALUE (args1), TREE_VALUE (args2)))
-                 return true;
-               args1 = TREE_CHAIN (args1);
-               args2 = TREE_CHAIN (args2);
+               tree arg_type = get_aka_type (TREE_VALUE (args));
+               arg_types.safe_push (arg_type);
+               type_ok_p &= (arg_type == TREE_VALUE (args));
+               args = TREE_CHAIN (args);
              }
-           return useful_aka_type_p (TREE_TYPE (type1), TREE_TYPE (type2));
+
+           if (type_ok_p && return_type == TREE_TYPE (type))
+             return type;
+
+           unsigned int i;
+           tree arg_type;
+           FOR_EACH_VEC_ELT_REVERSE (arg_types, i, arg_type)
+             args = tree_cons (NULL_TREE, arg_type, args);
+           result = build_function_type (return_type, args);
+           break;
          }
 
        default:
-         return true;
+         return canonical ? canonical : type;
        }
     }
+  return build_type_attribute_qual_variant (result, TYPE_ATTRIBUTES (type),
+                                           TYPE_QUALS (type));
 }
 
 /* Print T to CPP.  */
@@ -150,11 +201,12 @@ print_type (c_pretty_printer *cpp, tree
      stripped version.  But sometimes the stripped version looks
      exactly the same, so we don't want it after all.  To avoid
      printing it in that case, we play ugly obstack games.  */
-  if (TYPE_CANONICAL (t) && useful_aka_type_p (t, TYPE_CANONICAL (t)))
+  tree aka_type = get_aka_type (t);
+  if (aka_type != t)
     {
       c_pretty_printer cpp2;
       /* Print the stripped version into a temporary printer.  */
-      cpp2.type_id (TYPE_CANONICAL (t));
+      cpp2.type_id (aka_type);
       struct obstack *ob2 = cpp2.buffer->obstack;
       /* Get the stripped version from the temporary printer.  */
       const char *aka = (char *) obstack_base (ob2);
@@ -174,7 +226,7 @@ print_type (c_pretty_printer *cpp, tree
       pp_c_whitespace (cpp);
       if (*quoted)
        pp_begin_quote (cpp, pp_show_color (cpp));
-      cpp->type_id (TYPE_CANONICAL (t));
+      cpp->type_id (aka_type);
       if (*quoted)
        pp_end_quote (cpp, pp_show_color (cpp));
       pp_right_brace (cpp);
Index: gcc/testsuite/gcc.dg/diag-aka-5.h
===================================================================
--- /dev/null   2019-09-17 11:41:18.176664108 +0100
+++ gcc/testsuite/gcc.dg/diag-aka-5.h   2019-10-11 15:12:08.552939853 +0100
@@ -0,0 +1,22 @@
+#ifdef IS_SYSTEM_HEADER
+#pragma GCC system_header
+#endif
+
+typedef enum __internal_enum { A, B } user_enum;
+typedef user_enum *user_enum_ptr;
+
+typedef struct __internal_struct { int i; } user_struct;
+typedef user_struct user_struct_copy;
+typedef user_struct *user_struct_ptr;
+
+typedef union __internal_union { int i; } user_union;
+typedef user_union user_union_copy;
+typedef user_union *user_union_ptr;
+
+typedef unsigned int user_vector __attribute__((__vector_size__(16)));
+typedef user_vector user_vector_copy;
+typedef user_vector *user_vector_ptr;
+
+typedef int user_int;
+typedef user_int user_int_copy;
+typedef user_int *user_int_ptr;
Index: gcc/testsuite/gcc.dg/diag-aka-5a.c
===================================================================
--- /dev/null   2019-09-17 11:41:18.176664108 +0100
+++ gcc/testsuite/gcc.dg/diag-aka-5a.c  2019-10-11 15:12:08.552939853 +0100
@@ -0,0 +1,135 @@
+#define IS_SYSTEM_HEADER
+#include "diag-aka-5.h"
+
+typedef user_enum user_enum_copy;
+
+struct s { int i; };
+
+user_enum ue1;
+user_enum_copy ue2;
+user_enum_ptr ue_ptr1;
+user_enum *ue_ptr2;
+const user_enum *const_ue_ptr1;
+const user_enum_copy *const_ue_ptr2;
+volatile user_enum *volatile_ue_ptr1;
+volatile user_enum_copy *volatile_ue_ptr2;
+__extension__ _Atomic user_enum *atomic_ue_ptr1;
+__extension__ _Atomic user_enum_copy *atomic_ue_ptr2;
+user_enum (*ue_array_ptr1)[10];
+user_enum_copy (*ue_array_ptr2)[10];
+user_enum (*ue_fn_ptr1) (void);
+void (*ue_fn_ptr2) (user_enum);
+void (*ue_fn_ptr3) (user_enum, ...);
+user_enum_copy (*ue_fn_ptr4) (void);
+void (*ue_fn_ptr5) (user_enum_copy);
+void (*ue_fn_ptr6) (user_enum_copy, ...);
+user_enum (*__attribute__((__transaction_unsafe__)) unsafe_ue_fn_ptr1) (void);
+user_enum_copy (*__attribute__((__transaction_unsafe__)) unsafe_ue_fn_ptr2) 
(void);
+
+user_struct us1;
+user_struct_copy us2;
+user_struct_ptr us_ptr1;
+user_struct *us_ptr2;
+const user_struct *const_us_ptr1;
+const user_struct_copy *const_us_ptr2;
+
+user_union uu1;
+user_union_copy uu2;
+user_union_ptr uu_ptr1;
+user_union *uu_ptr2;
+const user_union *const_uu_ptr1;
+const user_union_copy *const_uu_ptr2;
+
+user_vector uv1;
+user_vector_copy uv2;
+user_vector_ptr uv_ptr1;
+user_vector *uv_ptr2;
+const user_vector *const_uv_ptr1;
+const user_vector_copy *const_uv_ptr2;
+
+user_int ui1;
+user_int_copy ui2;
+user_int_ptr ui_ptr1;
+user_int *ui_ptr2;
+const user_int *const_ui_ptr1;
+const user_int_copy *const_ui_ptr2;
+volatile user_int *volatile_ui_ptr1;
+volatile user_int_copy *volatile_ui_ptr2;
+__extension__ _Atomic user_int *atomic_ui_ptr1;
+__extension__ _Atomic user_int_copy *atomic_ui_ptr2;
+user_int (*ui_array_ptr1)[10];
+user_int_copy (*ui_array_ptr2)[10];
+user_int (*ui_fn_ptr1) (void);
+void (*ui_fn_ptr2) (user_int);
+void (*ui_fn_ptr3) (user_int, ...);
+user_int_copy (*ui_fn_ptr4) (void);
+void (*ui_fn_ptr5) (user_int_copy);
+void (*ui_fn_ptr6) (user_int_copy, ...);
+user_int (*__attribute__((__transaction_unsafe__)) unsafe_ui_fn_ptr1) (void);
+user_int_copy (*__attribute__((__transaction_unsafe__)) unsafe_ui_fn_ptr2) 
(void);
+
+void f (struct s s)
+{
+  ue1 = s; /* { dg-error {assigning to type 'user_enum' from type 'struct s'} 
} */
+  ue2 = s; /* { dg-error {assigning to type 'user_enum_copy' {aka 'user_enum'} 
from type 'struct s'} } */
+  ue_ptr1 = &s; /* { dg-error {assignment to 'user_enum_ptr' {aka 'user_enum 
\*'} from incompatible pointer type 'struct s \*'} } */
+  ue_ptr2 = &s; /* { dg-error {assignment to 'user_enum \*' from incompatible 
pointer type 'struct s \*'} } */
+  const_ue_ptr1 = &s; /* { dg-error {assignment to 'const user_enum \*' from 
incompatible pointer type 'struct s \*'} } */
+  const_ue_ptr2 = &s; /* { dg-error {assignment to 'const user_enum_copy \*' 
{aka 'const user_enum \*'} from incompatible pointer type 'struct s \*'} } */
+  volatile_ue_ptr1 = &s; /* { dg-error {assignment to 'volatile user_enum \*' 
from incompatible pointer type 'struct s \*'} } */
+  volatile_ue_ptr2 = &s; /* { dg-error {assignment to 'volatile user_enum_copy 
\*' {aka 'volatile user_enum \*'} from incompatible pointer type 'struct s \*'} 
} */
+  atomic_ue_ptr1 = &s; /* { dg-error {assignment to '_Atomic user_enum \*' 
from incompatible pointer type 'struct s \*'} } */
+  atomic_ue_ptr2 = &s; /* { dg-error {assignment to '_Atomic user_enum_copy 
\*' {aka '_Atomic user_enum \*'} from incompatible pointer type 'struct s \*'} 
} */
+  ue_array_ptr1 = &s; /* { dg-error {assignment to 'user_enum \(\*\)\[10\]' 
from incompatible pointer type 'struct s \*'} } */
+  ue_array_ptr2 = &s; /* { dg-error {assignment to 'user_enum_copy 
\(\*\)\[10\]' {aka 'user_enum \(\*\)\[10\]'} from incompatible pointer type 
'struct s \*'} } */
+  ue_fn_ptr1 = &s; /* { dg-error {assignment to 'user_enum \(\*\)\(void\)' 
from incompatible pointer type 'struct s \*'} } */
+  ue_fn_ptr2 = &s; /* { dg-error {assignment to 'void \(\*\)\(user_enum\)' 
from incompatible pointer type 'struct s \*'} } */
+  ue_fn_ptr3 = &s; /* { dg-error {assignment to 'void \(\*\)\(user_enum, 
\.\.\.\)' from incompatible pointer type 'struct s \*'} } */
+  ue_fn_ptr4 = &s; /* { dg-error {assignment to 'user_enum_copy 
\(\*\)\(void\)' {aka 'user_enum \(\*\)\(void\)'} from incompatible pointer type 
'struct s \*'} } */
+  ue_fn_ptr5 = &s; /* { dg-error {assignment to 'void 
\(\*\)\(user_enum_copy\)' {aka 'void \(\*\)\(user_enum\)'} from incompatible 
pointer type 'struct s \*'} } */
+  ue_fn_ptr6 = &s; /* { dg-error {assignment to 'void \(\*\)\(user_enum_copy, 
\.\.\.\)' {aka 'void \(\*\)\(user_enum, \.\.\.\)'} from incompatible pointer 
type 'struct s \*'} } */
+  unsafe_ue_fn_ptr1 = &s; /* { dg-error {assignment to 'user_enum 
\(__attribute__\(\(transaction_unsafe\)\) \*\)\(void\)' from incompatible 
pointer type 'struct s \*'} } */
+  unsafe_ue_fn_ptr2 = &s; /* { dg-error {assignment to 'user_enum_copy 
\(__attribute__\(\(transaction_unsafe\)\) \*\)\(void\)' {aka 'user_enum 
\(__attribute__\(\(transaction_unsafe\)\) \*\)\(void\)'} from incompatible 
pointer type 'struct s \*'} } */
+
+  us1 = s; /* { dg-error {assigning to type 'user_struct' from type 'struct 
s'} } */
+  us2 = s; /* { dg-error {assigning to type 'user_struct_copy' {aka 
'user_struct'} from type 'struct s'} } */
+  us_ptr1 = &s; /* { dg-error {assignment to 'user_struct_ptr' {aka 
'user_struct \*'} from incompatible pointer type 'struct s \*'} } */
+  us_ptr2 = &s; /* { dg-error {assignment to 'user_struct \*' from 
incompatible pointer type 'struct s \*'} } */
+  const_us_ptr1 = &s; /* { dg-error {assignment to 'const user_struct \*' from 
incompatible pointer type 'struct s \*'} } */
+  const_us_ptr2 = &s; /* { dg-error {assignment to 'const user_struct_copy \*' 
{aka 'const user_struct \*'} from incompatible pointer type 'struct s \*'} } */
+
+  uu1 = s; /* { dg-error {assigning to type 'user_union' from type 'struct s'} 
} */
+  uu2 = s; /* { dg-error {assigning to type 'user_union_copy' {aka 
'user_union'} from type 'struct s'} } */
+  uu_ptr1 = &s; /* { dg-error {assignment to 'user_union_ptr' {aka 'user_union 
\*'} from incompatible pointer type 'struct s \*'} } */
+  uu_ptr2 = &s; /* { dg-error {assignment to 'user_union \*' from incompatible 
pointer type 'struct s \*'} } */
+  const_uu_ptr1 = &s; /* { dg-error {assignment to 'const user_union \*' from 
incompatible pointer type 'struct s \*'} } */
+  const_uu_ptr2 = &s; /* { dg-error {assignment to 'const user_union_copy \*' 
{aka 'const user_union \*'} from incompatible pointer type 'struct s \*'} } */
+
+  uv1 = s; /* { dg-error {assigning to type 'user_vector' from type 'struct 
s'} } */
+  uv2 = s; /* { dg-error {assigning to type 'user_vector_copy' {aka 
'user_vector'} from type 'struct s'} } */
+  uv_ptr1 = &s; /* { dg-error {assignment to 'user_vector_ptr' {aka 
'user_vector \*'} from incompatible pointer type 'struct s \*'} } */
+  uv_ptr2 = &s; /* { dg-error {assignment to 'user_vector \*' from 
incompatible pointer type 'struct s \*'} } */
+  const_uv_ptr1 = &s; /* { dg-error {assignment to 'const user_vector \*' from 
incompatible pointer type 'struct s \*'} } */
+  const_uv_ptr2 = &s; /* { dg-error {assignment to 'const user_vector_copy \*' 
{aka 'const user_vector \*'} from incompatible pointer type 'struct s \*'} } */
+
+  ui1 = s; /* { dg-error {assigning to type 'user_int' {aka 'int'} from type 
'struct s'} } */
+  ui2 = s; /* { dg-error {assigning to type 'user_int_copy' {aka 'int'} from 
type 'struct s'} } */
+  ui_ptr1 = &s; /* { dg-error {assignment to 'user_int_ptr' {aka 'int \*'} 
from incompatible pointer type 'struct s \*'} } */
+  ui_ptr2 = &s; /* { dg-error {assignment to 'user_int \*' {aka 'int \*'} from 
incompatible pointer type 'struct s \*'} } */
+  const_ui_ptr1 = &s; /* { dg-error {assignment to 'const user_int \*' {aka 
'const int \*'} from incompatible pointer type 'struct s \*'} } */
+  const_ui_ptr2 = &s; /* { dg-error {assignment to 'const user_int_copy \*' 
{aka 'const int \*'} from incompatible pointer type 'struct s \*'} } */
+  volatile_ui_ptr1 = &s; /* { dg-error {assignment to 'volatile user_int \*' 
{aka 'volatile int \*'} from incompatible pointer type 'struct s \*'} } */
+  volatile_ui_ptr2 = &s; /* { dg-error {assignment to 'volatile user_int_copy 
\*' {aka 'volatile int \*'} from incompatible pointer type 'struct s \*'} } */
+  atomic_ui_ptr1 = &s; /* { dg-error {assignment to '_Atomic user_int \*' {aka 
'_Atomic int \*'} from incompatible pointer type 'struct s \*'} } */
+  atomic_ui_ptr2 = &s; /* { dg-error {assignment to '_Atomic user_int_copy \*' 
{aka '_Atomic int \*'} from incompatible pointer type 'struct s \*'} } */
+  ui_array_ptr1 = &s; /* { dg-error {assignment to 'user_int \(\*\)\[10\]' 
{aka 'int \(\*\)\[10\]'} from incompatible pointer type 'struct s \*'} } */
+  ui_array_ptr2 = &s; /* { dg-error {assignment to 'user_int_copy 
\(\*\)\[10\]' {aka 'int \(\*\)\[10\]'} from incompatible pointer type 'struct s 
\*'} } */
+  ui_fn_ptr1 = &s; /* { dg-error {assignment to 'user_int \(\*\)\(void\)' {aka 
'int \(\*\)\(void\)'} from incompatible pointer type 'struct s \*'} } */
+  ui_fn_ptr2 = &s; /* { dg-error {assignment to 'void \(\*\)\(user_int\)' {aka 
'void \(\*\)\(int\)'} from incompatible pointer type 'struct s \*'} } */
+  ui_fn_ptr3 = &s; /* { dg-error {assignment to 'void \(\*\)\(user_int, 
\.\.\.\)' {aka 'void \(\*\)\(int, \.\.\.\)'} from incompatible pointer type 
'struct s \*'} } */
+  ui_fn_ptr4 = &s; /* { dg-error {assignment to 'user_int_copy \(\*\)\(void\)' 
{aka 'int \(\*\)\(void\)'} from incompatible pointer type 'struct s \*'} } */
+  ui_fn_ptr5 = &s; /* { dg-error {assignment to 'void \(\*\)\(user_int_copy\)' 
{aka 'void \(\*\)\(int\)'} from incompatible pointer type 'struct s \*'} } */
+  ui_fn_ptr6 = &s; /* { dg-error {assignment to 'void \(\*\)\(user_int_copy, 
\.\.\.\)' {aka 'void \(\*\)\(int, \.\.\.\)'} from incompatible pointer type 
'struct s \*'} } */
+  unsafe_ui_fn_ptr1 = &s; /* { dg-error {assignment to 'user_int 
\(__attribute__\(\(transaction_unsafe\)\) \*\)\(void\)' {aka 'int 
\(__attribute__\(\(transaction_unsafe\)\) \*\)\(void\)'} from incompatible 
pointer type 'struct s \*'} } */
+  unsafe_ui_fn_ptr2 = &s; /* { dg-error {assignment to 'user_int_copy 
\(__attribute__\(\(transaction_unsafe\)\) \*\)\(void\)' {aka 'int 
\(__attribute__\(\(transaction_unsafe\)\) \*\)\(void\)'} from incompatible 
pointer type 'struct s \*'} } */
+}
Index: gcc/testsuite/gcc.dg/diag-aka-5b.c
===================================================================
--- /dev/null   2019-09-17 11:41:18.176664108 +0100
+++ gcc/testsuite/gcc.dg/diag-aka-5b.c  2019-10-11 15:12:08.552939853 +0100
@@ -0,0 +1,134 @@
+#include "diag-aka-5.h"
+
+typedef user_enum user_enum_copy;
+
+struct s { int i; };
+
+user_enum ue1;
+user_enum_copy ue2;
+user_enum_ptr ue_ptr1;
+user_enum *ue_ptr2;
+const user_enum *const_ue_ptr1;
+const user_enum_copy *const_ue_ptr2;
+volatile user_enum *volatile_ue_ptr1;
+volatile user_enum_copy *volatile_ue_ptr2;
+__extension__ _Atomic user_enum *atomic_ue_ptr1;
+__extension__ _Atomic user_enum_copy *atomic_ue_ptr2;
+user_enum (*ue_array_ptr1)[10];
+user_enum_copy (*ue_array_ptr2)[10];
+user_enum (*ue_fn_ptr1) (void);
+void (*ue_fn_ptr2) (user_enum);
+void (*ue_fn_ptr3) (user_enum, ...);
+user_enum_copy (*ue_fn_ptr4) (void);
+void (*ue_fn_ptr5) (user_enum_copy);
+void (*ue_fn_ptr6) (user_enum_copy, ...);
+user_enum (*__attribute__((__transaction_unsafe__)) unsafe_ue_fn_ptr1) (void);
+user_enum_copy (*__attribute__((__transaction_unsafe__)) unsafe_ue_fn_ptr2) 
(void);
+
+user_struct us1;
+user_struct_copy us2;
+user_struct_ptr us_ptr1;
+user_struct *us_ptr2;
+const user_struct *const_us_ptr1;
+const user_struct_copy *const_us_ptr2;
+
+user_union uu1;
+user_union_copy uu2;
+user_union_ptr uu_ptr1;
+user_union *uu_ptr2;
+const user_union *const_uu_ptr1;
+const user_union_copy *const_uu_ptr2;
+
+user_vector uv1;
+user_vector_copy uv2;
+user_vector_ptr uv_ptr1;
+user_vector *uv_ptr2;
+const user_vector *const_uv_ptr1;
+const user_vector_copy *const_uv_ptr2;
+
+user_int ui1;
+user_int_copy ui2;
+user_int_ptr ui_ptr1;
+user_int *ui_ptr2;
+const user_int *const_ui_ptr1;
+const user_int_copy *const_ui_ptr2;
+volatile user_int *volatile_ui_ptr1;
+volatile user_int_copy *volatile_ui_ptr2;
+__extension__ _Atomic user_int *atomic_ui_ptr1;
+__extension__ _Atomic user_int_copy *atomic_ui_ptr2;
+user_int (*ui_array_ptr1)[10];
+user_int_copy (*ui_array_ptr2)[10];
+user_int (*ui_fn_ptr1) (void);
+void (*ui_fn_ptr2) (user_int);
+void (*ui_fn_ptr3) (user_int, ...);
+user_int_copy (*ui_fn_ptr4) (void);
+void (*ui_fn_ptr5) (user_int_copy);
+void (*ui_fn_ptr6) (user_int_copy, ...);
+user_int (*__attribute__((__transaction_unsafe__)) unsafe_ui_fn_ptr1) (void);
+user_int_copy (*__attribute__((__transaction_unsafe__)) unsafe_ui_fn_ptr2) 
(void);
+
+void f (struct s s)
+{
+  ue1 = s; /* { dg-error {assigning to type 'user_enum' {aka 'enum 
__internal_enum'} from type 'struct s'} } */
+  ue2 = s; /* { dg-error {assigning to type 'user_enum_copy' {aka 'enum 
__internal_enum'} from type 'struct s'} } */
+  ue_ptr1 = &s; /* { dg-error {assignment to 'user_enum_ptr' {aka 'enum 
__internal_enum \*'} from incompatible pointer type 'struct s \*'} } */
+  ue_ptr2 = &s; /* { dg-error {assignment to 'user_enum \*' {aka 'enum 
__internal_enum \*'} from incompatible pointer type 'struct s \*'} } */
+  const_ue_ptr1 = &s; /* { dg-error {assignment to 'const user_enum \*' {aka 
'const enum __internal_enum \*'} from incompatible pointer type 'struct s \*'} 
} */
+  const_ue_ptr2 = &s; /* { dg-error {assignment to 'const user_enum_copy \*' 
{aka 'const enum __internal_enum \*'} from incompatible pointer type 'struct s 
\*'} } */
+  volatile_ue_ptr1 = &s; /* { dg-error {assignment to 'volatile user_enum \*' 
{aka 'volatile enum __internal_enum \*'} from incompatible pointer type 'struct 
s \*'} } */
+  volatile_ue_ptr2 = &s; /* { dg-error {assignment to 'volatile user_enum_copy 
\*' {aka 'volatile enum __internal_enum \*'} from incompatible pointer type 
'struct s \*'} } */
+  atomic_ue_ptr1 = &s; /* { dg-error {assignment to '_Atomic user_enum \*' 
{aka '_Atomic enum __internal_enum \*'} from incompatible pointer type 'struct 
s \*'} } */
+  atomic_ue_ptr2 = &s; /* { dg-error {assignment to '_Atomic user_enum_copy 
\*' {aka '_Atomic enum __internal_enum \*'} from incompatible pointer type 
'struct s \*'} } */
+  ue_array_ptr1 = &s; /* { dg-error {assignment to 'user_enum \(\*\)\[10\]' 
{aka 'enum __internal_enum \(\*\)\[10\]'} from incompatible pointer type 
'struct s \*'} } */
+  ue_array_ptr2 = &s; /* { dg-error {assignment to 'user_enum_copy 
\(\*\)\[10\]' {aka 'enum __internal_enum \(\*\)\[10\]'} from incompatible 
pointer type 'struct s \*'} } */
+  ue_fn_ptr1 = &s; /* { dg-error {assignment to 'user_enum \(\*\)\(void\)' 
{aka 'enum __internal_enum \(\*\)\(void\)'} from incompatible pointer type 
'struct s \*'} } */
+  ue_fn_ptr2 = &s; /* { dg-error {assignment to 'void \(\*\)\(user_enum\)' 
{aka 'void \(\*\)\(enum __internal_enum\)'} from incompatible pointer type 
'struct s \*'} } */
+  ue_fn_ptr3 = &s; /* { dg-error {assignment to 'void \(\*\)\(user_enum, 
\.\.\.\)' {aka 'void \(\*\)\(enum __internal_enum, \.\.\.\)'} from incompatible 
pointer type 'struct s \*'} } */
+  ue_fn_ptr4 = &s; /* { dg-error {assignment to 'user_enum_copy 
\(\*\)\(void\)' {aka 'enum __internal_enum \(\*\)\(void\)'} from incompatible 
pointer type 'struct s \*'} } */
+  ue_fn_ptr5 = &s; /* { dg-error {assignment to 'void 
\(\*\)\(user_enum_copy\)' {aka 'void \(\*\)\(enum __internal_enum\)'} from 
incompatible pointer type 'struct s \*'} } */
+  ue_fn_ptr6 = &s; /* { dg-error {assignment to 'void \(\*\)\(user_enum_copy, 
\.\.\.\)' {aka 'void \(\*\)\(enum __internal_enum, \.\.\.\)'} from incompatible 
pointer type 'struct s \*'} } */
+  unsafe_ue_fn_ptr1 = &s; /* { dg-error {assignment to 'user_enum 
\(__attribute__\(\(transaction_unsafe\)\) \*\)\(void\)' {aka 'enum 
__internal_enum \(__attribute__\(\(transaction_unsafe\)\) \*\)\(void\)'} from 
incompatible pointer type 'struct s \*'} } */
+  unsafe_ue_fn_ptr2 = &s; /* { dg-error {assignment to 'user_enum_copy 
\(__attribute__\(\(transaction_unsafe\)\) \*\)\(void\)' {aka 'enum 
__internal_enum \(__attribute__\(\(transaction_unsafe\)\) \*\)\(void\)'} from 
incompatible pointer type 'struct s \*'} } */
+
+  us1 = s; /* { dg-error {assigning to type 'user_struct' {aka 'struct 
__internal_struct'} from type 'struct s'} } */
+  us2 = s; /* { dg-error {assigning to type 'user_struct_copy' {aka 'struct 
__internal_struct'} from type 'struct s'} } */
+  us_ptr1 = &s; /* { dg-error {assignment to 'user_struct_ptr' {aka 'struct 
__internal_struct \*'} from incompatible pointer type 'struct s \*'} } */
+  us_ptr2 = &s; /* { dg-error {assignment to 'user_struct \*' {aka 'struct 
__internal_struct \*'} from incompatible pointer type 'struct s \*'} } */
+  const_us_ptr1 = &s; /* { dg-error {assignment to 'const user_struct \*' {aka 
'const struct __internal_struct \*'} from incompatible pointer type 'struct s 
\*'} } */
+  const_us_ptr2 = &s; /* { dg-error {assignment to 'const user_struct_copy \*' 
{aka 'const struct __internal_struct \*'} from incompatible pointer type 
'struct s \*'} } */
+
+  uu1 = s; /* { dg-error {assigning to type 'user_union' {aka 'union 
__internal_union'} from type 'struct s'} } */
+  uu2 = s; /* { dg-error {assigning to type 'user_union_copy' {aka 'union 
__internal_union'} from type 'struct s'} } */
+  uu_ptr1 = &s; /* { dg-error {assignment to 'user_union_ptr' {aka 'union 
__internal_union \*'} from incompatible pointer type 'struct s \*'} } */
+  uu_ptr2 = &s; /* { dg-error {assignment to 'user_union \*' {aka 'union 
__internal_union \*'} from incompatible pointer type 'struct s \*'} } */
+  const_uu_ptr1 = &s; /* { dg-error {assignment to 'const user_union \*' {aka 
'const union __internal_union \*'} from incompatible pointer type 'struct s 
\*'} } */
+  const_uu_ptr2 = &s; /* { dg-error {assignment to 'const user_union_copy \*' 
{aka 'const union __internal_union \*'} from incompatible pointer type 'struct 
s \*'} } */
+
+  uv1 = s; /* { dg-error {assigning to type 'user_vector' {aka 
'__vector\([48]\) unsigned int'} from type 'struct s'} } */
+  uv2 = s; /* { dg-error {assigning to type 'user_vector_copy' {aka 
'__vector\([48]\) unsigned int'} from type 'struct s'} } */
+  uv_ptr1 = &s; /* { dg-error {assignment to 'user_vector_ptr' {aka 
'__vector\([48]\) unsigned int \*'} from incompatible pointer type 'struct s 
\*'} } */
+  uv_ptr2 = &s; /* { dg-error {assignment to 'user_vector \*' {aka 
'__vector\([48]\) unsigned int \*'} from incompatible pointer type 'struct s 
\*'} } */
+  const_uv_ptr1 = &s; /* { dg-error {assignment to 'const user_vector \*' {aka 
'const __vector\([48]\) unsigned int \*'} from incompatible pointer type 
'struct s \*'} } */
+  const_uv_ptr2 = &s; /* { dg-error {assignment to 'const user_vector_copy \*' 
{aka 'const __vector\([48]\) unsigned int \*'} from incompatible pointer type 
'struct s \*'} } */
+
+  ui1 = s; /* { dg-error {assigning to type 'user_int' {aka 'int'} from type 
'struct s'} } */
+  ui2 = s; /* { dg-error {assigning to type 'user_int_copy' {aka 'int'} from 
type 'struct s'} } */
+  ui_ptr1 = &s; /* { dg-error {assignment to 'user_int_ptr' {aka 'int \*'} 
from incompatible pointer type 'struct s \*'} } */
+  ui_ptr2 = &s; /* { dg-error {assignment to 'user_int \*' {aka 'int \*'} from 
incompatible pointer type 'struct s \*'} } */
+  const_ui_ptr1 = &s; /* { dg-error {assignment to 'const user_int \*' {aka 
'const int \*'} from incompatible pointer type 'struct s \*'} } */
+  const_ui_ptr2 = &s; /* { dg-error {assignment to 'const user_int_copy \*' 
{aka 'const int \*'} from incompatible pointer type 'struct s \*'} } */
+  volatile_ui_ptr1 = &s; /* { dg-error {assignment to 'volatile user_int \*' 
{aka 'volatile int \*'} from incompatible pointer type 'struct s \*'} } */
+  volatile_ui_ptr2 = &s; /* { dg-error {assignment to 'volatile user_int_copy 
\*' {aka 'volatile int \*'} from incompatible pointer type 'struct s \*'} } */
+  atomic_ui_ptr1 = &s; /* { dg-error {assignment to '_Atomic user_int \*' {aka 
'_Atomic int \*'} from incompatible pointer type 'struct s \*'} } */
+  atomic_ui_ptr2 = &s; /* { dg-error {assignment to '_Atomic user_int_copy \*' 
{aka '_Atomic int \*'} from incompatible pointer type 'struct s \*'} } */
+  ui_array_ptr1 = &s; /* { dg-error {assignment to 'user_int \(\*\)\[10\]' 
{aka 'int \(\*\)\[10\]'} from incompatible pointer type 'struct s \*'} } */
+  ui_array_ptr2 = &s; /* { dg-error {assignment to 'user_int_copy 
\(\*\)\[10\]' {aka 'int \(\*\)\[10\]'} from incompatible pointer type 'struct s 
\*'} } */
+  ui_fn_ptr1 = &s; /* { dg-error {assignment to 'user_int \(\*\)\(void\)' {aka 
'int \(\*\)\(void\)'} from incompatible pointer type 'struct s \*'} } */
+  ui_fn_ptr2 = &s; /* { dg-error {assignment to 'void \(\*\)\(user_int\)' {aka 
'void \(\*\)\(int\)'} from incompatible pointer type 'struct s \*'} } */
+  ui_fn_ptr3 = &s; /* { dg-error {assignment to 'void \(\*\)\(user_int, 
\.\.\.\)' {aka 'void \(\*\)\(int, \.\.\.\)'} from incompatible pointer type 
'struct s \*'} } */
+  ui_fn_ptr4 = &s; /* { dg-error {assignment to 'user_int_copy \(\*\)\(void\)' 
{aka 'int \(\*\)\(void\)'} from incompatible pointer type 'struct s \*'} } */
+  ui_fn_ptr5 = &s; /* { dg-error {assignment to 'void \(\*\)\(user_int_copy\)' 
{aka 'void \(\*\)\(int\)'} from incompatible pointer type 'struct s \*'} } */
+  ui_fn_ptr6 = &s; /* { dg-error {assignment to 'void \(\*\)\(user_int_copy, 
\.\.\.\)' {aka 'void \(\*\)\(int, \.\.\.\)'} from incompatible pointer type 
'struct s \*'} } */
+  unsafe_ui_fn_ptr1 = &s; /* { dg-error {assignment to 'user_int 
\(__attribute__\(\(transaction_unsafe\)\) \*\)\(void\)' {aka 'int 
\(__attribute__\(\(transaction_unsafe\)\) \*\)\(void\)'} from incompatible 
pointer type 'struct s \*'} } */
+  unsafe_ui_fn_ptr2 = &s; /* { dg-error {assignment to 'user_int_copy 
\(__attribute__\(\(transaction_unsafe\)\) \*\)\(void\)' {aka 'int 
\(__attribute__\(\(transaction_unsafe\)\) \*\)\(void\)'} from incompatible 
pointer type 'struct s \*'} } */
+}
Index: gcc/testsuite/gcc.target/aarch64/diag_aka_1.c
===================================================================
--- gcc/testsuite/gcc.target/aarch64/diag_aka_1.c       2019-10-08 
09:23:43.000000000 +0100
+++ gcc/testsuite/gcc.target/aarch64/diag_aka_1.c       2019-10-11 
15:12:08.552939853 +0100
@@ -8,7 +8,6 @@ void f (float x)
   __Int8x8_t *ptr1 = &x; /* { dg-error {initialization of '__Int8x8_t \*' from 
incompatible pointer type 'float \*'} } */
   int8x8_t y2 = x; /* { dg-error {incompatible types when initializing type 
'int8x8_t' using type 'float'} } */
   int8x8_t *ptr2 = &x; /* { dg-error {initialization of 'int8x8_t \*' from 
incompatible pointer type 'float \*'} } */
-  /* ??? For these it would be better to print an aka for 'int16x4_t'.  */
-  myvec y3 = x; /* { dg-error {incompatible types when initializing type 
'myvec' using type 'float'} } */
-  myvec *ptr3 = &x; /* { dg-error {initialization of 'myvec \*' from 
incompatible pointer type 'float \*'} } */
+  myvec y3 = x; /* { dg-error {incompatible types when initializing type 
'myvec' {aka 'int16x4_t'} using type 'float'} } */
+  myvec *ptr3 = &x; /* { dg-error {initialization of 'myvec \*' {aka 
'int16x4_t \*'} from incompatible pointer type 'float \*'} } */
 }

Reply via email to