Commit 56898e43 by Richard Sandiford Committed by Richard Sandiford

[C] Avoid exposing internal details in aka types

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 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  <richard.sandiford@arm.com>

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

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

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

From-SVN: r276951
parent b9424661
2019-10-14 Richard Sandiford <richard.sandiford@arm.com>
* 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 <jakub@redhat.com> 2019-10-12 Jakub Jelinek <jakub@redhat.com>
* c-common.h (c_omp_mark_declare_variant, * c-common.h (c_omp_mark_declare_variant,
......
...@@ -48,6 +48,7 @@ along with GCC; see the file COPYING3. If not see ...@@ -48,6 +48,7 @@ along with GCC; see the file COPYING3. If not see
#include "gimplify.h" #include "gimplify.h"
#include "substring-locations.h" #include "substring-locations.h"
#include "spellcheck.h" #include "spellcheck.h"
#include "c-spellcheck.h"
#include "selftest.h" #include "selftest.h"
cpp_reader *parse_in; /* Declared in c-pragma.h. */ cpp_reader *parse_in; /* Declared in c-pragma.h. */
...@@ -7713,6 +7714,52 @@ set_underlying_type (tree x) ...@@ -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 /* Record the types used by the current global variable declaration
being parsed, so that we can decide later to emit their debug info. 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 Those types are in types_used_by_cur_var_decl, and we are going to
......
...@@ -1063,6 +1063,7 @@ extern tree builtin_type_for_size (int, bool); ...@@ -1063,6 +1063,7 @@ extern tree builtin_type_for_size (int, bool);
extern void c_common_mark_addressable_vec (tree); extern void c_common_mark_addressable_vec (tree);
extern void set_underlying_type (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 void record_types_used_by_current_var_decl (tree);
extern vec<tree, va_gc> *make_tree_vector (void); extern vec<tree, va_gc> *make_tree_vector (void);
extern void release_tree_vector (vec<tree, va_gc> *); extern void release_tree_vector (vec<tree, va_gc> *);
......
2019-10-14 Richard Sandiford <richard.sandiford@arm.com>
* 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 <jakub@redhat.com> 2019-10-14 Jakub Jelinek <jakub@redhat.com>
* c-parser.c (c_parser_omp_all_clauses): Change bool NESTED_P argument * c-parser.c (c_parser_omp_all_clauses): Change bool NESTED_P argument
......
...@@ -28,6 +28,8 @@ along with GCC; see the file COPYING3. If not see ...@@ -28,6 +28,8 @@ along with GCC; see the file COPYING3. If not see
#include "langhooks.h" #include "langhooks.h"
#include "c-objc-common.h" #include "c-objc-common.h"
#include "gcc-rich-location.h" #include "gcc-rich-location.h"
#include "stringpool.h"
#include "attribs.h"
static bool c_tree_printer (pretty_printer *, text_info *, const char *, static bool c_tree_printer (pretty_printer *, text_info *, const char *,
int, bool, bool, bool, bool *, const char **); int, bool, bool, bool, bool *, const char **);
...@@ -62,71 +64,120 @@ c_objc_common_init (void) ...@@ -62,71 +64,120 @@ c_objc_common_init (void)
return c_common_init (); 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 static tree
useful_aka_type_p (tree type1, tree type2) get_aka_type (tree type)
{ {
if (type1 == type2) if (type == error_mark_node)
return false; return type;
if (type1 == error_mark_node || type2 == error_mark_node)
return false;
if (TREE_CODE (type1) != TREE_CODE (type2)) tree result;
return true; if (typedef_variant_p (type))
if (typedef_variant_p (type1))
{ {
/* Saying that "foo" is also known as "struct foo" or /* Saying that "foo" is also known as "struct foo" or
"struct <anonymous>" is unlikely to be useful, since users of "struct <anonymous>" is unlikely to be useful, since users of
structure-like types would already know that they're structures. structure-like types would already know that they're structures.
The same applies to unions and enums; in general, printing the The same applies to unions and enums; in general, printing the
tag is only useful if it has a different name. */ tag is only useful if it has a different name. */
tree_code code = TREE_CODE (type2); tree orig_type = DECL_ORIGINAL_TYPE (TYPE_NAME (type));
tree id2 = TYPE_IDENTIFIER (type2); tree_code code = TREE_CODE (orig_type);
tree orig_id = TYPE_IDENTIFIER (orig_type);
if ((code == RECORD_TYPE || code == UNION_TYPE || code == ENUMERAL_TYPE) if ((code == RECORD_TYPE || code == UNION_TYPE || code == ENUMERAL_TYPE)
&& (!id2 || TYPE_IDENTIFIER (type1) == id2)) && (!orig_id || TYPE_IDENTIFIER (type) == orig_id))
return false; return type;
return true; if (!user_facing_original_type_p (type))
return type;
result = get_aka_type (orig_type);
} }
else 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 POINTER_TYPE:
case REFERENCE_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: 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: case FUNCTION_TYPE:
{ {
tree args1 = TYPE_ARG_TYPES (type1); tree return_type = get_aka_type (TREE_TYPE (type));
tree args2 = TYPE_ARG_TYPES (type2);
while (args1 != args2) 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 tree arg_type = get_aka_type (TREE_VALUE (args));
for it in a diagnostic routine. */ arg_types.safe_push (arg_type);
if (!args1 || args1 == void_type_node) type_ok_p &= (arg_type == TREE_VALUE (args));
return true; args = TREE_CHAIN (args);
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);
} }
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: default:
return true; return canonical ? canonical : type;
} }
} }
return build_type_attribute_qual_variant (result, TYPE_ATTRIBUTES (type),
TYPE_QUALS (type));
} }
/* Print T to CPP. */ /* Print T to CPP. */
...@@ -150,11 +201,12 @@ print_type (c_pretty_printer *cpp, tree t, bool *quoted) ...@@ -150,11 +201,12 @@ print_type (c_pretty_printer *cpp, tree t, bool *quoted)
stripped version. But sometimes the stripped version looks stripped version. But sometimes the stripped version looks
exactly the same, so we don't want it after all. To avoid exactly the same, so we don't want it after all. To avoid
printing it in that case, we play ugly obstack games. */ 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; c_pretty_printer cpp2;
/* Print the stripped version into a temporary printer. */ /* 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; struct obstack *ob2 = cpp2.buffer->obstack;
/* Get the stripped version from the temporary printer. */ /* Get the stripped version from the temporary printer. */
const char *aka = (char *) obstack_base (ob2); const char *aka = (char *) obstack_base (ob2);
...@@ -174,7 +226,7 @@ print_type (c_pretty_printer *cpp, tree t, bool *quoted) ...@@ -174,7 +226,7 @@ print_type (c_pretty_printer *cpp, tree t, bool *quoted)
pp_c_whitespace (cpp); pp_c_whitespace (cpp);
if (*quoted) if (*quoted)
pp_begin_quote (cpp, pp_show_color (cpp)); pp_begin_quote (cpp, pp_show_color (cpp));
cpp->type_id (TYPE_CANONICAL (t)); cpp->type_id (aka_type);
if (*quoted) if (*quoted)
pp_end_quote (cpp, pp_show_color (cpp)); pp_end_quote (cpp, pp_show_color (cpp));
pp_right_brace (cpp); pp_right_brace (cpp);
......
2019-10-14 Richard Sandiford <richard.sandiford@arm.com>
* 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 <jakub@redhat.com> 2019-10-14 Jakub Jelinek <jakub@redhat.com>
* c-c++-common/gomp/declare-variant-7.c: Add tests for clauses not * c-c++-common/gomp/declare-variant-7.c: Add tests for clauses not
......
#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;
#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 \*'} } */
}
#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 \*'} } */
}
...@@ -8,7 +8,6 @@ void f (float x) ...@@ -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 *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 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 \*'} } */ 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' {aka 'int16x4_t'} using type 'float'} } */
myvec y3 = x; /* { dg-error {incompatible types when initializing type 'myvec' using type 'float'} } */ myvec *ptr3 = &x; /* { dg-error {initialization of 'myvec \*' {aka 'int16x4_t \*'} from incompatible pointer type 'float \*'} } */
myvec *ptr3 = &x; /* { dg-error {initialization of 'myvec \*' from incompatible pointer type 'float \*'} } */
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment