On Mon, Sep 30, 2019 at 3:21 PM Richard Sandiford <richard.sandif...@arm.com> wrote: > > 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. > > This patch stops the aka code looking through typedefs if all of > the following are true: > > (1) the typedef is built into the compiler or comes from a system header > > (2) the target of the typedef is anonymous or has a name in the > implementation namespace > > (3) the target type is a tag type or vector type, which have in common that: > (a) we print their type names if they have one > (b) what we print for anonymous types isn't all that useful > ("struct <anonymous>" etc. for tag types, pseudo-C "__vector(N) T" > for vector types) > > The C side does this by recursively looking for the aka type, like the > C++ side already does. This in turn makes "aka" work for distinct type > copies like __Int8x8_t on aarch64, fixing the ??? in aarch64/diag_aka_1.c. > > On the C++ side, strip_typedefs had: > > /* Explicitly get the underlying type, as TYPE_MAIN_VARIANT doesn't > strip typedefs with attributes. */ > result = TYPE_MAIN_VARIANT (DECL_ORIGINAL_TYPE (TYPE_NAME (t))); > result = strip_typedefs (result); > > Applying TYPE_MAIN_VARIANT predates the strip_typedefs call, with the > comment originally contrasting with plain: > > result = TYPE_MAIN_VARIANT (t); > > But the recursive call to strip_typedefs will apply TYPE_MAIN_VARIANT, > so it doesn't seem necessary to do it here too. I think there was also > a missing "remove_attributes" argument, since wrapping something in a > typedef shouldn't change which attributes get removed. > > Tested on aarch64-linux-gnu and x86_64-linux-gnu. OK to install?
In other context (debug-info) we also look at DECL_ARTIFICIAL, not sure if that is set on compiler-generated TYPE_DECLs. > Richard > > > 2019-09-30 Richard Sandiford <richard.sandif...@arm.com> > > gcc/c-family/ > * c-common.h (user_facing_original_type_p): Declare. > * c-common.c (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/cp/ > * cp-tree.h (STF_USER_VISIBLE): New constant. > (strip_typedefs, strip_typedefs_expr): Take a flags argument. > * tree.c (strip_typedefs, strip_typedefs_expr): Likewise, > updating mutual calls accordingly. When STF_USER_VISIBLE is true, > only look through typedefs if user_facing_original_type_p. > * error.c (dump_template_bindings, type_to_string): Pass > STF_USER_VISIBLE to strip_typedefs. > (dump_type): Likewise, unless pp_c_flag_gnu_v3 is set. > > gcc/testsuite/ > * g++.dg/diagnostic/aka5.h: New test. > * g++.dg/diagnostic/aka5a.C: Likewise. > * g++.dg/diagnostic/aka5b.C: Likewise. > * g++.target/aarch64/diag_aka_1.C: Likewise. > * gcc.dg/diag-aka-5.h: Likewise. > * 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-09-30 13:54:16.000000000 +0100 > +++ gcc/c-family/c-common.h 2019-09-30 14:16:45.002103890 +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-09-30 13:54:16.000000000 +0100 > +++ gcc/c-family/c-common.c 2019-09-30 14:16:45.002103890 +0100 > @@ -7713,6 +7713,55 @@ 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)) > + { > + const char *name = IDENTIFIER_POINTER (orig_id); > + if (name[0] != '_' || (name[1] != '_' && !ISUPPER (name[1]))) > + 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-09-30 14:08:26.597671509 +0100 > +++ gcc/c/c-objc-common.c 2019-09-30 14:16:45.002103890 +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/cp/cp-tree.h > =================================================================== > --- gcc/cp/cp-tree.h 2019-09-30 13:54:16.000000000 +0100 > +++ gcc/cp/cp-tree.h 2019-09-30 14:16:45.006103863 +0100 > @@ -5672,6 +5672,13 @@ #define TFF_NO_OMIT_DEFAULT_TEMPLATE_ARG > #define TFF_NO_TEMPLATE_BINDINGS (1 << 13) > #define TFF_POINTER (1 << 14) > > +/* These constants can be used as bit flags to control strip_typedefs. > + > + STF_USER_VISIBLE: use heuristics to try to avoid stripping user-facing > + aliases of internal details. This is intended for diagnostics, > + where it should (for example) give more useful "aka" types. */ > +const unsigned int STF_USER_VISIBLE = 1U; > + > /* Returns the TEMPLATE_DECL associated to a TEMPLATE_TEMPLATE_PARM > node. */ > #define TEMPLATE_TEMPLATE_PARM_TEMPLATE_DECL(NODE) \ > @@ -7228,8 +7235,10 @@ extern int zero_init_p > (const_tree); > extern bool check_abi_tag_redeclaration (const_tree, > const_tree, > const_tree); > extern bool check_abi_tag_args (tree, tree); > -extern tree strip_typedefs (tree, bool * = NULL); > -extern tree strip_typedefs_expr (tree, bool * = NULL); > +extern tree strip_typedefs (tree, bool * = NULL, > + unsigned int = 0); > +extern tree strip_typedefs_expr (tree, bool * = NULL, > + unsigned int = 0); > extern tree copy_binfo (tree, tree, tree, > tree *, int); > extern int member_p (const_tree); > Index: gcc/cp/tree.c > =================================================================== > --- gcc/cp/tree.c 2019-09-30 13:54:16.000000000 +0100 > +++ gcc/cp/tree.c 2019-09-30 14:16:45.006103863 +0100 > @@ -1431,7 +1431,10 @@ apply_identity_attributes (tree result, > return cp_build_type_attribute_variant (result, new_attribs); > } > > -/* Builds a qualified variant of T that is not a typedef variant. > +/* Builds a qualified variant of T that is either not a typedef variant > + (the default behavior) or not a typedef variant of a user-facing type > + (if FLAGS contains STF_USER_FACING). > + > E.g. consider the following declarations: > typedef const int ConstInt; > typedef ConstInt* PtrConstInt; > @@ -1456,7 +1459,7 @@ apply_identity_attributes (tree result, > stripped. */ > > tree > -strip_typedefs (tree t, bool *remove_attributes) > +strip_typedefs (tree t, bool *remove_attributes, unsigned int flags) > { > tree result = NULL, type = NULL, t0 = NULL; > > @@ -1471,7 +1474,7 @@ strip_typedefs (tree t, bool *remove_att > for (; t; t = TREE_CHAIN (t)) > { > gcc_assert (!TREE_PURPOSE (t)); > - tree elt = strip_typedefs (TREE_VALUE (t), remove_attributes); > + tree elt = strip_typedefs (TREE_VALUE (t), remove_attributes, > flags); > if (elt != TREE_VALUE (t)) > changed = true; > vec_safe_push (vec, elt); > @@ -1494,28 +1497,29 @@ strip_typedefs (tree t, bool *remove_att > switch (TREE_CODE (t)) > { > case POINTER_TYPE: > - type = strip_typedefs (TREE_TYPE (t), remove_attributes); > + type = strip_typedefs (TREE_TYPE (t), remove_attributes, flags); > result = build_pointer_type (type); > break; > case REFERENCE_TYPE: > - type = strip_typedefs (TREE_TYPE (t), remove_attributes); > + type = strip_typedefs (TREE_TYPE (t), remove_attributes, flags); > result = cp_build_reference_type (type, TYPE_REF_IS_RVALUE (t)); > break; > case OFFSET_TYPE: > - t0 = strip_typedefs (TYPE_OFFSET_BASETYPE (t), remove_attributes); > - type = strip_typedefs (TREE_TYPE (t), remove_attributes); > + t0 = strip_typedefs (TYPE_OFFSET_BASETYPE (t), remove_attributes, > flags); > + type = strip_typedefs (TREE_TYPE (t), remove_attributes, flags); > result = build_offset_type (t0, type); > break; > case RECORD_TYPE: > if (TYPE_PTRMEMFUNC_P (t)) > { > - t0 = strip_typedefs (TYPE_PTRMEMFUNC_FN_TYPE (t), > remove_attributes); > + t0 = strip_typedefs (TYPE_PTRMEMFUNC_FN_TYPE (t), > + remove_attributes, flags); > result = build_ptrmemfunc_type (t0); > } > break; > case ARRAY_TYPE: > - type = strip_typedefs (TREE_TYPE (t), remove_attributes); > - t0 = strip_typedefs (TYPE_DOMAIN (t), remove_attributes); > + type = strip_typedefs (TREE_TYPE (t), remove_attributes, flags); > + t0 = strip_typedefs (TYPE_DOMAIN (t), remove_attributes, flags); > result = build_cplus_array_type (type, t0); > break; > case FUNCTION_TYPE: > @@ -1534,7 +1538,7 @@ strip_typedefs (tree t, bool *remove_att > && (TYPE_ATTRIBUTES (t) || TYPE_USER_ALIGN (t))) > is_variant = true; > > - type = strip_typedefs (TREE_TYPE (t), remove_attributes); > + type = strip_typedefs (TREE_TYPE (t), remove_attributes, flags); > tree canon_spec = (flag_noexcept_type > ? canonical_eh_spec (TYPE_RAISES_EXCEPTIONS (t)) > : NULL_TREE); > @@ -1548,7 +1552,7 @@ strip_typedefs (tree t, bool *remove_att > if (arg_node == void_list_node) > break; > arg_type = strip_typedefs (TREE_VALUE (arg_node), > - remove_attributes); > + remove_attributes, flags); > gcc_assert (arg_type); > if (arg_type == TREE_VALUE (arg_node) && !changed) > continue; > @@ -1612,9 +1616,10 @@ strip_typedefs (tree t, bool *remove_att > tree arg = TREE_VEC_ELT (args, i); > tree strip_arg; > if (TYPE_P (arg)) > - strip_arg = strip_typedefs (arg, remove_attributes); > + strip_arg = strip_typedefs (arg, remove_attributes, flags); > else > - strip_arg = strip_typedefs_expr (arg, remove_attributes); > + strip_arg = strip_typedefs_expr (arg, remove_attributes, > + flags); > TREE_VEC_ELT (new_args, i) = strip_arg; > if (strip_arg != arg) > changed = true; > @@ -1630,7 +1635,7 @@ strip_typedefs (tree t, bool *remove_att > else > ggc_free (new_args); > } > - tree ctx = strip_typedefs (TYPE_CONTEXT (t), remove_attributes); > + tree ctx = strip_typedefs (TYPE_CONTEXT (t), remove_attributes, > flags); > if (!changed && ctx == TYPE_CONTEXT (t) && !typedef_variant_p (t)) > return t; > tree name = fullname; > @@ -1643,7 +1648,7 @@ strip_typedefs (tree t, bool *remove_att > break; > case DECLTYPE_TYPE: > result = strip_typedefs_expr (DECLTYPE_TYPE_EXPR (t), > - remove_attributes); > + remove_attributes, flags); > if (result == DECLTYPE_TYPE_EXPR (t)) > result = NULL_TREE; > else > @@ -1653,7 +1658,8 @@ strip_typedefs (tree t, bool *remove_att > tf_none)); > break; > case UNDERLYING_TYPE: > - type = strip_typedefs (UNDERLYING_TYPE_TYPE (t), remove_attributes); > + type = strip_typedefs (UNDERLYING_TYPE_TYPE (t), > + remove_attributes, flags); > result = finish_underlying_type (type); > break; > default: > @@ -1664,15 +1670,18 @@ strip_typedefs (tree t, bool *remove_att > { > if (typedef_variant_p (t)) > { > - /* Explicitly get the underlying type, as TYPE_MAIN_VARIANT doesn't > - strip typedefs with attributes. */ > - result = TYPE_MAIN_VARIANT (DECL_ORIGINAL_TYPE (TYPE_NAME (t))); > - result = strip_typedefs (result); > + if ((flags & STF_USER_VISIBLE) > + && !user_facing_original_type_p (t)) > + return t; > + result = strip_typedefs (DECL_ORIGINAL_TYPE (TYPE_NAME (t)), > + remove_attributes, flags); > } > else > result = TYPE_MAIN_VARIANT (t); > } > - gcc_assert (!typedef_variant_p (result)); > + gcc_assert (!typedef_variant_p (result) > + || ((flags & STF_USER_VISIBLE) > + && !user_facing_original_type_p (result))); > > if (COMPLETE_TYPE_P (result) && !COMPLETE_TYPE_P (t)) > /* If RESULT is complete and T isn't, it's likely the case that T > @@ -1721,7 +1730,7 @@ strip_typedefs (tree t, bool *remove_att > sizeof(TT) is replaced by sizeof(T). */ > > tree > -strip_typedefs_expr (tree t, bool *remove_attributes) > +strip_typedefs_expr (tree t, bool *remove_attributes, unsigned int flags) > { > unsigned i,n; > tree r, type, *ops; > @@ -1738,7 +1747,7 @@ strip_typedefs_expr (tree t, bool *remov > /* Some expressions have type operands, so let's handle types here rather > than check TYPE_P in multiple places below. */ > if (TYPE_P (t)) > - return strip_typedefs (t, remove_attributes); > + return strip_typedefs (t, remove_attributes, flags); > > code = TREE_CODE (t); > switch (code) > @@ -1752,8 +1761,10 @@ strip_typedefs_expr (tree t, bool *remov > > case TRAIT_EXPR: > { > - tree type1 = strip_typedefs (TRAIT_EXPR_TYPE1 (t), remove_attributes); > - tree type2 = strip_typedefs (TRAIT_EXPR_TYPE2 (t), remove_attributes); > + tree type1 = strip_typedefs (TRAIT_EXPR_TYPE1 (t), > + remove_attributes, flags); > + tree type2 = strip_typedefs (TRAIT_EXPR_TYPE2 (t), > + remove_attributes, flags); > if (type1 == TRAIT_EXPR_TYPE1 (t) > && type2 == TRAIT_EXPR_TYPE2 (t)) > return t; > @@ -1770,7 +1781,8 @@ strip_typedefs_expr (tree t, bool *remov > tree it; > for (it = t; it; it = TREE_CHAIN (it)) > { > - tree val = strip_typedefs_expr (TREE_VALUE (it), > remove_attributes); > + tree val = strip_typedefs_expr (TREE_VALUE (it), > + remove_attributes, flags); > vec_safe_push (vec, val); > if (val != TREE_VALUE (it)) > changed = true; > @@ -1796,7 +1808,7 @@ strip_typedefs_expr (tree t, bool *remov > for (i = 0; i < n; ++i) > { > tree op = strip_typedefs_expr (TREE_VEC_ELT (t, i), > - remove_attributes); > + remove_attributes, flags); > vec->quick_push (op); > if (op != TREE_VEC_ELT (t, i)) > changed = true; > @@ -1820,18 +1832,19 @@ strip_typedefs_expr (tree t, bool *remov > vec<constructor_elt, va_gc> *vec > = vec_safe_copy (CONSTRUCTOR_ELTS (t)); > n = CONSTRUCTOR_NELTS (t); > - type = strip_typedefs (TREE_TYPE (t), remove_attributes); > + type = strip_typedefs (TREE_TYPE (t), remove_attributes, flags); > for (i = 0; i < n; ++i) > { > constructor_elt *e = &(*vec)[i]; > - tree op = strip_typedefs_expr (e->value, remove_attributes); > + tree op = strip_typedefs_expr (e->value, remove_attributes, > flags); > if (op != e->value) > { > changed = true; > e->value = op; > } > gcc_checking_assert > - (e->index == strip_typedefs_expr (e->index, remove_attributes)); > + (e->index == strip_typedefs_expr (e->index, remove_attributes, > + flags)); > } > > if (!changed && type == TREE_TYPE (t)) > @@ -1875,12 +1888,13 @@ strip_typedefs_expr (tree t, bool *remov > case REINTERPRET_CAST_EXPR: > case CAST_EXPR: > case NEW_EXPR: > - type = strip_typedefs (type, remove_attributes); > + type = strip_typedefs (type, remove_attributes, flags); > /* fallthrough */ > > default: > for (i = 0; i < n; ++i) > - ops[i] = strip_typedefs_expr (TREE_OPERAND (t, i), remove_attributes); > + ops[i] = strip_typedefs_expr (TREE_OPERAND (t, i), > + remove_attributes, flags); > break; > } > > Index: gcc/cp/error.c > =================================================================== > --- gcc/cp/error.c 2019-09-30 13:54:16.000000000 +0100 > +++ gcc/cp/error.c 2019-09-30 14:16:45.006103863 +0100 > @@ -409,7 +409,7 @@ dump_template_bindings (cxx_pretty_print > pop_deferring_access_checks (); > /* Strip typedefs. We can't just use TFF_CHASE_TYPEDEF because > pp_simple_type_specifier doesn't know about it. */ > - t = strip_typedefs (t); > + t = strip_typedefs (t, NULL, STF_USER_VISIBLE); > dump_type (pp, t, TFF_PLAIN_IDENTIFIER); > } > } > @@ -448,7 +448,11 @@ dump_type (cxx_pretty_printer *pp, tree > || DECL_SELF_REFERENCE_P (decl) > || (!flag_pretty_templates > && DECL_LANG_SPECIFIC (decl) && DECL_TEMPLATE_INFO (decl))) > - t = strip_typedefs (t); > + { > + unsigned int stf_flags = (!(pp->flags & pp_c_flag_gnu_v3) > + ? STF_USER_VISIBLE : 0); > + t = strip_typedefs (t, NULL, stf_flags); > + } > else if (alias_template_specialization_p (t)) > { > dump_alias_template_specialization (pp, t, flags); > @@ -3195,7 +3199,7 @@ type_to_string (tree typ, int verbose, b > && !uses_template_parms (typ)) > { > int aka_start, aka_len; char *p; > - tree aka = strip_typedefs (typ); > + tree aka = strip_typedefs (typ, NULL, STF_USER_VISIBLE); > if (quote && *quote) > pp_end_quote (cxx_pp, show_color); > pp_string (cxx_pp, " {aka"); > Index: gcc/testsuite/g++.dg/diagnostic/aka5.h > =================================================================== > --- /dev/null 2019-09-17 11:41:18.176664108 +0100 > +++ gcc/testsuite/g++.dg/diagnostic/aka5.h 2019-09-30 14:16:45.006103863 > +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/g++.dg/diagnostic/aka5a.C > =================================================================== > --- /dev/null 2019-09-17 11:41:18.176664108 +0100 > +++ gcc/testsuite/g++.dg/diagnostic/aka5a.C 2019-09-30 14:16:45.010103832 > +0100 > @@ -0,0 +1,127 @@ > +#define IS_SYSTEM_HEADER > +#include "aka5.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; > +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; > +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 (s s1) > +{ > + ue1 = s1; // { dg-error {cannot convert 's' to 'user_enum' in assignment} } > + ue2 = s1; // { dg-error {cannot convert 's' to 'user_enum_copy' {aka > 'user_enum'} in assignment} } > + ue_ptr1 = &s1; // { dg-error {cannot convert 's\*' to 'user_enum_ptr' {aka > 'user_enum\*'} in assignment} } > + ue_ptr2 = &s1; // { dg-error {cannot convert 's\*' to 'user_enum\*' in > assignment} } > + const_ue_ptr1 = &s1; // { dg-error {cannot convert 's\*' to 'const > user_enum\*' in assignment} } > + const_ue_ptr2 = &s1; // { dg-error {cannot convert 's\*' to 'const > user_enum_copy\*' {aka 'const user_enum\*'} in assignment} } > + volatile_ue_ptr1 = &s1; // { dg-error {cannot convert 's\*' to 'volatile > user_enum\*' in assignment} } > + volatile_ue_ptr2 = &s1; // { dg-error {cannot convert 's\*' to 'volatile > user_enum_copy\*' {aka 'volatile user_enum\*'} in assignment} } > + ue_array_ptr1 = &s1; // { dg-error {cannot convert 's\*' to 'user_enum > \(\*\)\[10\]' in assignment} } > + ue_array_ptr2 = &s1; // { dg-error {cannot convert 's\*' to > 'user_enum_copy \(\*\)\[10\]' {aka 'user_enum \(\*\)\[10\]'} in assignment} } > + ue_fn_ptr1 = &s1; // { dg-error {cannot convert 's\*' to 'user_enum > \(\*\)\(\)' in assignment} } > + ue_fn_ptr2 = &s1; // { dg-error {cannot convert 's\*' to 'void > \(\*\)\(user_enum\)' in assignment} } > + ue_fn_ptr3 = &s1; // { dg-error {cannot convert 's\*' to 'void > \(\*\)\(user_enum, \.\.\.\)' in assignment} } > + ue_fn_ptr4 = &s1; // { dg-error {cannot convert 's\*' to 'user_enum_copy > \(\*\)\(\)' {aka 'user_enum \(\*\)\(\)'} in assignment} } > + ue_fn_ptr5 = &s1; // { dg-error {cannot convert 's\*' to 'void > \(\*\)\(user_enum_copy\)' {aka 'void \(\*\)\(user_enum\)'} in assignment} } > + ue_fn_ptr6 = &s1; // { dg-error {cannot convert 's\*' to 'void > \(\*\)\(user_enum_copy, \.\.\.\)' {aka 'void \(\*\)\(user_enum, \.\.\.\)'} in > assignment} } > + unsafe_ue_fn_ptr1 = &s1; // { dg-error {cannot convert 's\*' to 'user_enum > \(__attribute__\(\(transaction_unsafe\)\) \*\)\(\)' in assignment} } > + unsafe_ue_fn_ptr2 = &s1; // { dg-error {cannot convert 's\*' to > 'user_enum_copy \(__attribute__\(\(transaction_unsafe\)\) \*\)\(\)' {aka > 'user_enum \(__attribute__\(\(transaction_unsafe\)\) \*\)\(\)'} in > assignment} } > + > + us1 = s1; // { dg-error {no match for 'operator=' in 'us1 = s1' \(operand > types are 'user_struct' and 's'\)} } > + us2 = s1; // { dg-error {no match for 'operator=' in 'us2 = s1' \(operand > types are 'user_struct_copy' {aka 'user_struct'} and 's'\)} } > + us_ptr1 = &s1; // { dg-error {cannot convert 's\*' to 'user_struct_ptr' > {aka 'user_struct\*'} in assignment} } > + us_ptr2 = &s1; // { dg-error {cannot convert 's\*' to 'user_struct\*' in > assignment} } > + const_us_ptr1 = &s1; // { dg-error {cannot convert 's\*' to 'const > user_struct\*' in assignment} } > + const_us_ptr2 = &s1; // { dg-error {cannot convert 's\*' to 'const > user_struct_copy\*' {aka 'const user_struct\*'} in assignment} } > + > + uu1 = s1; // { dg-error {no match for 'operator=' in 'uu1 = s1' \(operand > types are 'user_union' and 's'\)} } > + uu2 = s1; // { dg-error {no match for 'operator=' in 'uu2 = s1' \(operand > types are 'user_union_copy' {aka 'user_union'} and 's'\)} } > + uu_ptr1 = &s1; // { dg-error {cannot convert 's\*' to 'user_union_ptr' > {aka 'user_union\*'} in assignment} } > + uu_ptr2 = &s1; // { dg-error {cannot convert 's\*' to 'user_union\*' in > assignment} } > + const_uu_ptr1 = &s1; // { dg-error {cannot convert 's\*' to 'const > user_union\*' in assignment} } > + const_uu_ptr2 = &s1; // { dg-error {cannot convert 's\*' to 'const > user_union_copy\*' {aka 'const user_union\*'} in assignment} } > + > + uv1 = s1; // { dg-error {cannot convert 's' to 'user_vector' in > assignment} } > + uv2 = s1; // { dg-error {cannot convert 's' to 'user_vector_copy' {aka > 'user_vector'} in assignment} } > + uv_ptr1 = &s1; // { dg-error {cannot convert 's\*' to 'user_vector_ptr' > {aka 'user_vector\*'} in assignment} } > + uv_ptr2 = &s1; // { dg-error {cannot convert 's\*' to 'user_vector\*' in > assignment} } > + const_uv_ptr1 = &s1; // { dg-error {cannot convert 's\*' to 'const > user_vector\*' in assignment} } > + const_uv_ptr2 = &s1; // { dg-error {cannot convert 's\*' to 'const > user_vector_copy\*' {aka 'const user_vector\*'} in assignment} } > + > + ui1 = s1; // { dg-error {cannot convert 's' to 'user_int' {aka 'int'} in > assignment} } > + ui2 = s1; // { dg-error {cannot convert 's' to 'user_int_copy' {aka 'int'} > in assignment} } > + ui_ptr1 = &s1; // { dg-error {cannot convert 's\*' to 'user_int_ptr' {aka > 'int\*'} in assignment} } > + ui_ptr2 = &s1; // { dg-error {cannot convert 's\*' to 'user_int\*' {aka > 'int\*'} in assignment} } > + const_ui_ptr1 = &s1; // { dg-error {cannot convert 's\*' to 'const > user_int\*' {aka 'const int\*'} in assignment} } > + const_ui_ptr2 = &s1; // { dg-error {cannot convert 's\*' to 'const > user_int_copy\*' {aka 'const int\*'} in assignment} } > + volatile_ui_ptr1 = &s1; // { dg-error {cannot convert 's\*' to 'volatile > user_int\*' {aka 'volatile int\*'} in assignment} } > + volatile_ui_ptr2 = &s1; // { dg-error {cannot convert 's\*' to 'volatile > user_int_copy\*' {aka 'volatile int\*'} in assignment} } > + ui_array_ptr1 = &s1; // { dg-error {cannot convert 's\*' to 'user_int > \(\*\)\[10\]' {aka 'int \(\*\)\[10\]'} in assignment} } > + ui_array_ptr2 = &s1; // { dg-error {cannot convert 's\*' to 'user_int_copy > \(\*\)\[10\]' {aka 'int \(\*\)\[10\]'} in assignment} } > + ui_fn_ptr1 = &s1; // { dg-error {cannot convert 's\*' to 'user_int > \(\*\)\(\)' {aka 'int \(\*\)\(\)'} in assignment} } > + ui_fn_ptr2 = &s1; // { dg-error {cannot convert 's\*' to 'void > \(\*\)\(user_int\)' {aka 'void \(\*\)\(int\)'} in assignment} } > + ui_fn_ptr3 = &s1; // { dg-error {cannot convert 's\*' to 'void > \(\*\)\(user_int, \.\.\.\)' {aka 'void \(\*\)\(int, \.\.\.\)'} in assignment} > } > + ui_fn_ptr4 = &s1; // { dg-error {cannot convert 's\*' to 'user_int_copy > \(\*\)\(\)' {aka 'int \(\*\)\(\)'} in assignment} } > + ui_fn_ptr5 = &s1; // { dg-error {cannot convert 's\*' to 'void > \(\*\)\(user_int_copy\)' {aka 'void \(\*\)\(int\)'} in assignment} } > + ui_fn_ptr6 = &s1; // { dg-error {cannot convert 's\*' to 'void > \(\*\)\(user_int_copy, \.\.\.\)' {aka 'void \(\*\)\(int, \.\.\.\)'} in > assignment} } > + unsafe_ui_fn_ptr1 = &s1; // { dg-error {cannot convert 's\*' to 'user_int > \(__attribute__\(\(transaction_unsafe\)\) \*\)\(\)' {aka 'int > \(__attribute__\(\(transaction_unsafe\)\) \*\)\(\)'} in assignment} } > + unsafe_ui_fn_ptr2 = &s1; // { dg-error {cannot convert 's\*' to > 'user_int_copy \(__attribute__\(\(transaction_unsafe\)\) \*\)\(\)' {aka 'int > \(__attribute__\(\(transaction_unsafe\)\) \*\)\(\)'} in assignment} } > +} > Index: gcc/testsuite/g++.dg/diagnostic/aka5b.C > =================================================================== > --- /dev/null 2019-09-17 11:41:18.176664108 +0100 > +++ gcc/testsuite/g++.dg/diagnostic/aka5b.C 2019-09-30 14:16:45.010103832 > +0100 > @@ -0,0 +1,127 @@ > +#include "aka5.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; > +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; > +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 (s s1) > +{ > + ue1 = s1; // { dg-error {cannot convert 's' to 'user_enum' {aka > '__internal_enum'} in assignment} } > + ue2 = s1; // { dg-error {cannot convert 's' to 'user_enum_copy' {aka > '__internal_enum'} in assignment} } > + ue_ptr1 = &s1; // { dg-error {cannot convert 's\*' to 'user_enum_ptr' {aka > '__internal_enum\*'} in assignment} } > + ue_ptr2 = &s1; // { dg-error {cannot convert 's\*' to 'user_enum\*' {aka > '__internal_enum\*'} in assignment} } > + const_ue_ptr1 = &s1; // { dg-error {cannot convert 's\*' to 'const > user_enum\*' {aka 'const __internal_enum\*'} in assignment} } > + const_ue_ptr2 = &s1; // { dg-error {cannot convert 's\*' to 'const > user_enum_copy\*' {aka 'const __internal_enum\*'} in assignment} } > + volatile_ue_ptr1 = &s1; // { dg-error {cannot convert 's\*' to 'volatile > user_enum\*' {aka 'volatile __internal_enum\*'} in assignment} } > + volatile_ue_ptr2 = &s1; // { dg-error {cannot convert 's\*' to 'volatile > user_enum_copy\*' {aka 'volatile __internal_enum\*'} in assignment} } > + ue_array_ptr1 = &s1; // { dg-error {cannot convert 's\*' to 'user_enum > \(\*\)\[10\]' {aka '__internal_enum \(\*\)\[10\]'} in assignment} } > + ue_array_ptr2 = &s1; // { dg-error {cannot convert 's\*' to > 'user_enum_copy \(\*\)\[10\]' {aka '__internal_enum \(\*\)\[10\]'} in > assignment} } > + ue_fn_ptr1 = &s1; // { dg-error {cannot convert 's\*' to 'user_enum > \(\*\)\(\)' {aka '__internal_enum \(\*\)\(\)'} in assignment} } > + ue_fn_ptr2 = &s1; // { dg-error {cannot convert 's\*' to 'void > \(\*\)\(user_enum\)' {aka 'void \(\*\)\(__internal_enum\)'} in assignment} } > + ue_fn_ptr3 = &s1; // { dg-error {cannot convert 's\*' to 'void > \(\*\)\(user_enum, \.\.\.\)' {aka 'void \(\*\)\(__internal_enum, \.\.\.\)'} > in assignment} } > + ue_fn_ptr4 = &s1; // { dg-error {cannot convert 's\*' to 'user_enum_copy > \(\*\)\(\)' {aka '__internal_enum \(\*\)\(\)'} in assignment} } > + ue_fn_ptr5 = &s1; // { dg-error {cannot convert 's\*' to 'void > \(\*\)\(user_enum_copy\)' {aka 'void \(\*\)\(__internal_enum\)'} in > assignment} } > + ue_fn_ptr6 = &s1; // { dg-error {cannot convert 's\*' to 'void > \(\*\)\(user_enum_copy, \.\.\.\)' {aka 'void \(\*\)\(__internal_enum, > \.\.\.\)'} in assignment} } > + unsafe_ue_fn_ptr1 = &s1; // { dg-error {cannot convert 's\*' to 'user_enum > \(__attribute__\(\(transaction_unsafe\)\) \*\)\(\)' {aka '__internal_enum > \(__attribute__\(\(transaction_unsafe\)\) \*\)\(\)'} in assignment} } > + unsafe_ue_fn_ptr2 = &s1; // { dg-error {cannot convert 's\*' to > 'user_enum_copy \(__attribute__\(\(transaction_unsafe\)\) \*\)\(\)' {aka > '__internal_enum \(__attribute__\(\(transaction_unsafe\)\) \*\)\(\)'} in > assignment} } > + > + us1 = s1; // { dg-error {no match for 'operator=' in 'us1 = s1' \(operand > types are 'user_struct' {aka '__internal_struct'} and 's'\)} } > + us2 = s1; // { dg-error {no match for 'operator=' in 'us2 = s1' \(operand > types are 'user_struct_copy' {aka '__internal_struct'} and 's'\)} } > + us_ptr1 = &s1; // { dg-error {cannot convert 's\*' to 'user_struct_ptr' > {aka '__internal_struct\*'} in assignment} } > + us_ptr2 = &s1; // { dg-error {cannot convert 's\*' to 'user_struct\*' {aka > '__internal_struct\*'} in assignment} } > + const_us_ptr1 = &s1; // { dg-error {cannot convert 's\*' to 'const > user_struct\*' {aka 'const __internal_struct\*'} in assignment} } > + const_us_ptr2 = &s1; // { dg-error {cannot convert 's\*' to 'const > user_struct_copy\*' {aka 'const __internal_struct\*'} in assignment} } > + > + uu1 = s1; // { dg-error {no match for 'operator=' in 'uu1 = s1' \(operand > types are 'user_union' {aka '__internal_union'} and 's'\)} } > + uu2 = s1; // { dg-error {no match for 'operator=' in 'uu2 = s1' \(operand > types are 'user_union_copy' {aka '__internal_union'} and 's'\)} } > + uu_ptr1 = &s1; // { dg-error {cannot convert 's\*' to 'user_union_ptr' > {aka '__internal_union\*'} in assignment} } > + uu_ptr2 = &s1; // { dg-error {cannot convert 's\*' to 'user_union\*' {aka > '__internal_union\*'} in assignment} } > + const_uu_ptr1 = &s1; // { dg-error {cannot convert 's\*' to 'const > user_union\*' {aka 'const __internal_union\*'} in assignment} } > + const_uu_ptr2 = &s1; // { dg-error {cannot convert 's\*' to 'const > user_union_copy\*' {aka 'const __internal_union\*'} in assignment} } > + > + uv1 = s1; // { dg-error {cannot convert 's' to 'user_vector' {aka > '__vector\([48]\) unsigned int'} in assignment} } > + uv2 = s1; // { dg-error {cannot convert 's' to 'user_vector_copy' {aka > '__vector\([48]\) unsigned int'} in assignment} } > + uv_ptr1 = &s1; // { dg-error {cannot convert 's\*' to 'user_vector_ptr' > {aka '__vector\([48]\) unsigned int\*'} in assignment} } > + uv_ptr2 = &s1; // { dg-error {cannot convert 's\*' to 'user_vector\*' {aka > '__vector\([48]\) unsigned int\*'} in assignment} } > + const_uv_ptr1 = &s1; // { dg-error {cannot convert 's\*' to 'const > user_vector\*' {aka 'const __vector\([48]\) unsigned int\*'} in assignment} } > + const_uv_ptr2 = &s1; // { dg-error {cannot convert 's\*' to 'const > user_vector_copy\*' {aka 'const __vector\([48]\) unsigned int\*'} in > assignment} } > + > + ui1 = s1; // { dg-error {cannot convert 's' to 'user_int' {aka 'int'} in > assignment} } > + ui2 = s1; // { dg-error {cannot convert 's' to 'user_int_copy' {aka 'int'} > in assignment} } > + ui_ptr1 = &s1; // { dg-error {cannot convert 's\*' to 'user_int_ptr' {aka > 'int\*'} in assignment} } > + ui_ptr2 = &s1; // { dg-error {cannot convert 's\*' to 'user_int\*' {aka > 'int\*'} in assignment} } > + const_ui_ptr1 = &s1; // { dg-error {cannot convert 's\*' to 'const > user_int\*' {aka 'const int\*'} in assignment} } > + const_ui_ptr2 = &s1; // { dg-error {cannot convert 's\*' to 'const > user_int_copy\*' {aka 'const int\*'} in assignment} } > + volatile_ui_ptr1 = &s1; // { dg-error {cannot convert 's\*' to 'volatile > user_int\*' {aka 'volatile int\*'} in assignment} } > + volatile_ui_ptr2 = &s1; // { dg-error {cannot convert 's\*' to 'volatile > user_int_copy\*' {aka 'volatile int\*'} in assignment} } > + ui_array_ptr1 = &s1; // { dg-error {cannot convert 's\*' to 'user_int > \(\*\)\[10\]' {aka 'int \(\*\)\[10\]'} in assignment} } > + ui_array_ptr2 = &s1; // { dg-error {cannot convert 's\*' to 'user_int_copy > \(\*\)\[10\]' {aka 'int \(\*\)\[10\]'} in assignment} } > + ui_fn_ptr1 = &s1; // { dg-error {cannot convert 's\*' to 'user_int > \(\*\)\(\)' {aka 'int \(\*\)\(\)'} in assignment} } > + ui_fn_ptr2 = &s1; // { dg-error {cannot convert 's\*' to 'void > \(\*\)\(user_int\)' {aka 'void \(\*\)\(int\)'} in assignment} } > + ui_fn_ptr3 = &s1; // { dg-error {cannot convert 's\*' to 'void > \(\*\)\(user_int, \.\.\.\)' {aka 'void \(\*\)\(int, \.\.\.\)'} in assignment} > } > + ui_fn_ptr4 = &s1; // { dg-error {cannot convert 's\*' to 'user_int_copy > \(\*\)\(\)' {aka 'int \(\*\)\(\)'} in assignment} } > + ui_fn_ptr5 = &s1; // { dg-error {cannot convert 's\*' to 'void > \(\*\)\(user_int_copy\)' {aka 'void \(\*\)\(int\)'} in assignment} } > + ui_fn_ptr6 = &s1; // { dg-error {cannot convert 's\*' to 'void > \(\*\)\(user_int_copy, \.\.\.\)' {aka 'void \(\*\)\(int, \.\.\.\)'} in > assignment} } > + unsafe_ui_fn_ptr1 = &s1; // { dg-error {cannot convert 's\*' to 'user_int > \(__attribute__\(\(transaction_unsafe\)\) \*\)\(\)' {aka 'int > \(__attribute__\(\(transaction_unsafe\)\) \*\)\(\)'} in assignment} } > + unsafe_ui_fn_ptr2 = &s1; // { dg-error {cannot convert 's\*' to > 'user_int_copy \(__attribute__\(\(transaction_unsafe\)\) \*\)\(\)' {aka 'int > \(__attribute__\(\(transaction_unsafe\)\) \*\)\(\)'} in assignment} } > +} > + > Index: gcc/testsuite/g++.target/aarch64/diag_aka_1.C > =================================================================== > --- /dev/null 2019-09-17 11:41:18.176664108 +0100 > +++ gcc/testsuite/g++.target/aarch64/diag_aka_1.C 2019-09-30 > 14:16:45.010103832 +0100 > @@ -0,0 +1,13 @@ > +#include <arm_neon.h> > + > +typedef int16x4_t myvec; > + > +void f (float x) > +{ > + __Int8x8_t y1 = x; // { dg-error {cannot convert 'float' to '__Int8x8_t' > in initialization} } > + __Int8x8_t *ptr1 = &x; // { dg-error {cannot convert 'float\*' to > '__Int8x8_t\*' in initialization} } > + int8x8_t y2 = x; // { dg-error {cannot convert 'float' to 'int8x8_t' in > initialization} } > + int8x8_t *ptr2 = &x; // { dg-error {cannot convert 'float\*' to > 'int8x8_t\*' in initialization} } > + myvec y3 = x; // { dg-error {cannot convert 'float' to 'myvec' {aka > 'int16x4_t'} in initialization} } > + myvec *ptr3 = &x; // { dg-error {cannot convert 'float\*' to 'myvec\*' > {aka 'int16x4_t\*'} in initialization} } > +} > 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-09-30 14:16:45.010103832 +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-09-30 14:16:45.010103832 +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-09-30 14:16:45.010103832 +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-09-30 > 14:01:05.908830119 +0100 > +++ gcc/testsuite/gcc.target/aarch64/diag_aka_1.c 2019-09-30 > 14:16:45.010103832 +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 \*'} } */ > }