From 56898e437a538c7edc0724a3650f5cb81c9d5721 Mon Sep 17 00:00:00 2001 From: Richard Sandiford Date: Mon, 14 Oct 2019 08:05:52 +0000 Subject: [PATCH] [C] Avoid exposing internal details in aka types MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit 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 " etc. for tag types, pseudo-C "__vector(N) T" for vector types) The patch does this by recursively looking for the aka type, like the C++ frontend 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. 2019-10-14 Richard Sandiford gcc/c-family/ * c-common.h (user_facing_original_type_p): Declare. * c-common.c: Include c-spellcheck.h. (user_facing_original_type_p): New function. gcc/c/ * c-objc-common.c (useful_aka_type_p): Replace with... (get_aka_type): ...this new function. Given the original type, decide which aka type to print (if any). Only look through typedefs if user_facing_original_type_p. (print_type): Update accordingly. gcc/testsuite/ * gcc.dg/diag-aka-5.h: New test. * gcc.dg/diag-aka-5a.c: Likewise. * gcc.dg/diag-aka-5b.c: Likewise. * gcc.target/aarch64/diag_aka_1.c (f): Expect an aka to be printed for myvec. From-SVN: r276951 --- gcc/c-family/ChangeLog | 6 + gcc/c-family/c-common.c | 47 ++++++ gcc/c-family/c-common.h | 1 + gcc/c/ChangeLog | 8 ++ gcc/c/c-objc-common.c | 130 ++++++++++++----- gcc/testsuite/ChangeLog | 8 ++ gcc/testsuite/gcc.dg/diag-aka-5.h | 22 +++ gcc/testsuite/gcc.dg/diag-aka-5a.c | 135 ++++++++++++++++++ gcc/testsuite/gcc.dg/diag-aka-5b.c | 134 +++++++++++++++++ gcc/testsuite/gcc.target/aarch64/diag_aka_1.c | 5 +- 10 files changed, 454 insertions(+), 42 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/diag-aka-5.h create mode 100644 gcc/testsuite/gcc.dg/diag-aka-5a.c create mode 100644 gcc/testsuite/gcc.dg/diag-aka-5b.c diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog index 2b63689bc7a..cb3b9cfa98e 100644 --- a/gcc/c-family/ChangeLog +++ b/gcc/c-family/ChangeLog @@ -1,3 +1,9 @@ +2019-10-14 Richard Sandiford + + * c-common.h (user_facing_original_type_p): Declare. + * c-common.c: Include c-spellcheck.h. + (user_facing_original_type_p): New function. + 2019-10-12 Jakub Jelinek * c-common.h (c_omp_mark_declare_variant, diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c index 909f52a922a..483d874bc3a 100644 --- a/gcc/c-family/c-common.c +++ b/gcc/c-family/c-common.c @@ -48,6 +48,7 @@ along with GCC; see the file COPYING3. If not see #include "gimplify.h" #include "substring-locations.h" #include "spellcheck.h" +#include "c-spellcheck.h" #include "selftest.h" cpp_reader *parse_in; /* Declared in c-pragma.h. */ @@ -7713,6 +7714,52 @@ set_underlying_type (tree x) } } +/* Return true if it is worth exposing the DECL_ORIGINAL_TYPE of TYPE to + the user in diagnostics, false if it would be better to use TYPE itself. + TYPE is known to satisfy typedef_variant_p. */ + +bool +user_facing_original_type_p (const_tree type) +{ + gcc_assert (typedef_variant_p (type)); + tree decl = TYPE_NAME (type); + + /* Look through any typedef in "user" code. */ + if (!DECL_IN_SYSTEM_HEADER (decl) && !DECL_IS_BUILTIN (decl)) + return true; + + /* If the original type is also named and is in the user namespace, + assume it too is a user-facing type. */ + tree orig_type = DECL_ORIGINAL_TYPE (decl); + if (tree orig_id = TYPE_IDENTIFIER (orig_type)) + if (!name_reserved_for_implementation_p (IDENTIFIER_POINTER (orig_id))) + return true; + + switch (TREE_CODE (orig_type)) + { + /* Don't look through to an anonymous vector type, since the syntax + we use for them in diagnostics isn't real C or C++ syntax. + And if ORIG_TYPE is named but in the implementation namespace, + TYPE is likely to be more meaningful to the user. */ + case VECTOR_TYPE: + return false; + + /* Don't expose anonymous tag types that are presumably meant to be + known by their typedef name. Also don't expose tags that are in + the implementation namespace, such as: + + typedef struct __foo foo; */ + case RECORD_TYPE: + case UNION_TYPE: + case ENUMERAL_TYPE: + return false; + + /* Look through to anything else. */ + default: + return true; + } +} + /* Record the types used by the current global variable declaration being parsed, so that we can decide later to emit their debug info. Those types are in types_used_by_cur_var_decl, and we are going to diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h index db7f26eec53..3bc021b65d9 100644 --- a/gcc/c-family/c-common.h +++ b/gcc/c-family/c-common.h @@ -1063,6 +1063,7 @@ extern tree builtin_type_for_size (int, bool); 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 *make_tree_vector (void); extern void release_tree_vector (vec *); diff --git a/gcc/c/ChangeLog b/gcc/c/ChangeLog index c76baf060a7..23310ce0e43 100644 --- a/gcc/c/ChangeLog +++ b/gcc/c/ChangeLog @@ -1,3 +1,11 @@ +2019-10-14 Richard Sandiford + + * 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. + 2019-10-14 Jakub Jelinek * c-parser.c (c_parser_omp_all_clauses): Change bool NESTED_P argument diff --git a/gcc/c/c-objc-common.c b/gcc/c/c-objc-common.c index e1f3b2ee436..10d72c57dfb 100644 --- a/gcc/c/c-objc-common.c +++ b/gcc/c/c-objc-common.c @@ -28,6 +28,8 @@ along with GCC; see the file COPYING3. If not see #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 " 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 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 t, bool *quoted) 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 t, bool *quoted) 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); diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 5db77a788d5..7385c334505 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,11 @@ +2019-10-14 Richard Sandiford + + * gcc.dg/diag-aka-5.h: New test. + * gcc.dg/diag-aka-5a.c: Likewise. + * gcc.dg/diag-aka-5b.c: Likewise. + * gcc.target/aarch64/diag_aka_1.c (f): Expect an aka to be printed + for myvec. + 2019-10-14 Jakub Jelinek * c-c++-common/gomp/declare-variant-7.c: Add tests for clauses not diff --git a/gcc/testsuite/gcc.dg/diag-aka-5.h b/gcc/testsuite/gcc.dg/diag-aka-5.h new file mode 100644 index 00000000000..0c7404d7664 --- /dev/null +++ b/gcc/testsuite/gcc.dg/diag-aka-5.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/gcc.dg/diag-aka-5a.c b/gcc/testsuite/gcc.dg/diag-aka-5a.c new file mode 100644 index 00000000000..8768a79204a --- /dev/null +++ b/gcc/testsuite/gcc.dg/diag-aka-5a.c @@ -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 \*'} } */ +} diff --git a/gcc/testsuite/gcc.dg/diag-aka-5b.c b/gcc/testsuite/gcc.dg/diag-aka-5b.c new file mode 100644 index 00000000000..e0ec7c816a2 --- /dev/null +++ b/gcc/testsuite/gcc.dg/diag-aka-5b.c @@ -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 \*'} } */ +} diff --git a/gcc/testsuite/gcc.target/aarch64/diag_aka_1.c b/gcc/testsuite/gcc.target/aarch64/diag_aka_1.c index 59e24f48bd5..98dffead6a8 100644 --- a/gcc/testsuite/gcc.target/aarch64/diag_aka_1.c +++ b/gcc/testsuite/gcc.target/aarch64/diag_aka_1.c @@ -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 \*'} } */ } -- 2.30.2