From 10bce48f104de56503b17954ed79f019df3252e3 Mon Sep 17 00:00:00 2001 From: Richard Sandiford Date: Tue, 22 Oct 2019 07:47:07 +0000 Subject: [PATCH] [C++] Avoid exposing internal details in aka types This patch extends r276951 to work for C++ too. 2019-10-22 Richard Sandiford 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. From-SVN: r277281 --- gcc/cp/ChangeLog | 11 ++ gcc/cp/cp-tree.h | 13 +- gcc/cp/error.c | 10 +- gcc/cp/tree.c | 80 ++++++----- gcc/testsuite/ChangeLog | 7 + gcc/testsuite/g++.dg/diagnostic/aka5.h | 22 +++ gcc/testsuite/g++.dg/diagnostic/aka5a.C | 127 ++++++++++++++++++ gcc/testsuite/g++.dg/diagnostic/aka5b.C | 127 ++++++++++++++++++ gcc/testsuite/g++.target/aarch64/diag_aka_1.C | 13 ++ 9 files changed, 372 insertions(+), 38 deletions(-) create mode 100644 gcc/testsuite/g++.dg/diagnostic/aka5.h create mode 100644 gcc/testsuite/g++.dg/diagnostic/aka5a.C create mode 100644 gcc/testsuite/g++.dg/diagnostic/aka5b.C create mode 100644 gcc/testsuite/g++.target/aarch64/diag_aka_1.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 4218901b854..2b15bf722ca 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,14 @@ +2019-10-22 Richard Sandiford + + * 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. + 2019-10-21 Kamlesh Kumar Jason Merrill diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 8c11ac5dd35..e9d54466289 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -5722,6 +5722,13 @@ enum auto_deduction_context #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) \ @@ -7259,8 +7266,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); diff --git a/gcc/cp/error.c b/gcc/cp/error.c index 30166f9c4ec..83b8b12e4bd 100644 --- a/gcc/cp/error.c +++ b/gcc/cp/error.c @@ -410,7 +410,7 @@ dump_template_bindings (cxx_pretty_printer *pp, tree parms, tree args, 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); } } @@ -449,7 +449,11 @@ dump_type (cxx_pretty_printer *pp, tree t, int flags) || 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); @@ -3205,7 +3209,7 @@ type_to_string (tree typ, int verbose, bool postprocessed, bool *quote, && !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"); diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c index a004bb1aa7f..9d63736a394 100644 --- a/gcc/cp/tree.c +++ b/gcc/cp/tree.c @@ -1431,7 +1431,10 @@ apply_identity_attributes (tree result, tree attribs, bool *remove_attributes) 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, tree attribs, bool *remove_attributes) 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_attributes) 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_attributes) 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_attributes) && (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_attributes) 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_attributes) 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_attributes) 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_attributes) 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_attributes) 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_attributes) { 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_attributes) 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 *remove_attributes) /* 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 *remove_attributes) 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 *remove_attributes) 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 *remove_attributes) 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 *remove_attributes) vec *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 *remove_attributes) 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; } diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index d63c7b52378..b0edb291b0e 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,10 @@ +2019-10-22 Richard Sandiford + + * 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. + 2019-10-22 Iain Sandoe * gcc.dg/Wnonnull.c: Provide prototypes for strlen and memcpy. diff --git a/gcc/testsuite/g++.dg/diagnostic/aka5.h b/gcc/testsuite/g++.dg/diagnostic/aka5.h new file mode 100644 index 00000000000..0c7404d7664 --- /dev/null +++ b/gcc/testsuite/g++.dg/diagnostic/aka5.h @@ -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; diff --git a/gcc/testsuite/g++.dg/diagnostic/aka5a.C b/gcc/testsuite/g++.dg/diagnostic/aka5a.C new file mode 100644 index 00000000000..e9d4c02f61d --- /dev/null +++ b/gcc/testsuite/g++.dg/diagnostic/aka5a.C @@ -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} } +} diff --git a/gcc/testsuite/g++.dg/diagnostic/aka5b.C b/gcc/testsuite/g++.dg/diagnostic/aka5b.C new file mode 100644 index 00000000000..6942be3eef1 --- /dev/null +++ b/gcc/testsuite/g++.dg/diagnostic/aka5b.C @@ -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} } +} + diff --git a/gcc/testsuite/g++.target/aarch64/diag_aka_1.C b/gcc/testsuite/g++.target/aarch64/diag_aka_1.C new file mode 100644 index 00000000000..6b489981f9c --- /dev/null +++ b/gcc/testsuite/g++.target/aarch64/diag_aka_1.C @@ -0,0 +1,13 @@ +#include + +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} } +} -- 2.30.2