diff options
author | Richard Sandiford <richard.sandiford@arm.com> | 2019-10-14 08:05:52 +0000 |
---|---|---|
committer | Richard Sandiford <rsandifo@gcc.gnu.org> | 2019-10-14 08:05:52 +0000 |
commit | 56898e437a538c7edc0724a3650f5cb81c9d5721 (patch) | |
tree | 94c4cbef454873ea3d58380d67930ee520289c86 /gcc/c-family | |
parent | b9424661f58de6c0aa9dc4c855c1fd913cc06282 (diff) | |
download | gcc-56898e437a538c7edc0724a3650f5cb81c9d5721.zip gcc-56898e437a538c7edc0724a3650f5cb81c9d5721.tar.gz gcc-56898e437a538c7edc0724a3650f5cb81c9d5721.tar.bz2 |
[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
Diffstat (limited to 'gcc/c-family')
-rw-r--r-- | gcc/c-family/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/c-family/c-common.c | 47 | ||||
-rw-r--r-- | gcc/c-family/c-common.h | 1 |
3 files changed, 54 insertions, 0 deletions
diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog index 2b63689..cb3b9cf 100644 --- a/gcc/c-family/ChangeLog +++ b/gcc/c-family/ChangeLog @@ -1,3 +1,9 @@ +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> * 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 909f52a..483d874 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 db7f26e..3bc021b 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<tree, va_gc> *make_tree_vector (void); extern void release_tree_vector (vec<tree, va_gc> *); |