aboutsummaryrefslogtreecommitdiff
path: root/gcc/c
diff options
context:
space:
mode:
authorRichard Sandiford <richard.sandiford@arm.com>2019-10-01 08:56:25 +0000
committerRichard Sandiford <rsandifo@gcc.gnu.org>2019-10-01 08:56:25 +0000
commit558798156b41fcbe5ba68b75171708cad135b041 (patch)
tree7e71706fa542a6dc326eaee82cfdf1611bdeaf7d /gcc/c
parent8209db250f305cc79fd751c3ed056fb9ff551a83 (diff)
downloadgcc-558798156b41fcbe5ba68b75171708cad135b041.zip
gcc-558798156b41fcbe5ba68b75171708cad135b041.tar.gz
gcc-558798156b41fcbe5ba68b75171708cad135b041.tar.bz2
[C] Avoid aka types that just add tags
diag-aka-1.c tests that: struct T { int i; } T; void *a; T *t = a; produces: request for implicit conversion from 'void *' to 'T *' {aka 'struct T *'} ... But printing an aka for the tag seems a bit redundant when the tag name is the same as the typedef name. It's probably not going to be telling the user anything they don't already know, and can be distracting if "T" rather than "struct T" is the preferred choice for an exported interface. This is even more true if the tag is anonymous; e.g.: struct { int i; } T; void *a; T *t = a; gives: request for implicit conversion from 'void *' to 'T *' {aka 'struct <anonymous> *'} Rather than just drop the test above, the patch instead tests for: struct T { int i; } *T; where seeing the tag definitely helps. 2019-10-01 Richard Sandiford <richard.sandiford@arm.com> gcc/c/ * c-objc-common.c (useful_aka_type_p): New function. (print_type): Use it to decide whether an aka type is worth printing. gcc/testsuite/ * gcc.dg/diag-aka-1.c (T): Turn into a pointer typedef. (foo): Update accordingly. * gcc.dg/diag-aka-4.c: New test. From-SVN: r276395
Diffstat (limited to 'gcc/c')
-rw-r--r--gcc/c/ChangeLog5
-rw-r--r--gcc/c/c-objc-common.c69
2 files changed, 73 insertions, 1 deletions
diff --git a/gcc/c/ChangeLog b/gcc/c/ChangeLog
index fa0bbc8..3156e35 100644
--- a/gcc/c/ChangeLog
+++ b/gcc/c/ChangeLog
@@ -1,3 +1,8 @@
+2019-10-01 Richard Sandiford <richard.sandiford@arm.com>
+
+ * c-objc-common.c (useful_aka_type_p): New function.
+ (print_type): Use it to decide whether an aka type is worth printing.
+
2019-09-27 Jakub Jelinek <jakub@redhat.com>
PR c++/88203
diff --git a/gcc/c/c-objc-common.c b/gcc/c/c-objc-common.c
index 2b76737..e1f3b2e 100644
--- a/gcc/c/c-objc-common.c
+++ b/gcc/c/c-objc-common.c
@@ -62,6 +62,73 @@ c_objc_common_init (void)
return c_common_init ();
}
+/* Return true if it's worth saying that TYPE1 is also known as TYPE2. */
+
+static bool
+useful_aka_type_p (tree type1, tree type2)
+{
+ 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 (typedef_variant_p (type1))
+ {
+ /* Saying that "foo" is also known as "struct foo" or
+ "struct <anonymous>" is unlikely to be useful, since users of
+ structure-like types would already know that they're structures.
+ The same applies to unions and enums; in general, printing the
+ tag is only useful if it has a different name. */
+ tree_code code = TREE_CODE (type2);
+ tree id2 = TYPE_IDENTIFIER (type2);
+ if ((code == RECORD_TYPE || code == UNION_TYPE || code == ENUMERAL_TYPE)
+ && (!id2 || TYPE_IDENTIFIER (type1) == id2))
+ return false;
+
+ return true;
+ }
+ else
+ {
+ switch (TREE_CODE (type1))
+ {
+ case POINTER_TYPE:
+ case REFERENCE_TYPE:
+ return useful_aka_type_p (TREE_TYPE (type1), TREE_TYPE (type2));
+
+ case ARRAY_TYPE:
+ return (useful_aka_type_p (TYPE_DOMAIN (type1), TYPE_DOMAIN (type2))
+ || useful_aka_type_p (TREE_TYPE (type1), TREE_TYPE (type2)));
+
+ case FUNCTION_TYPE:
+ {
+ tree args1 = TYPE_ARG_TYPES (type1);
+ tree args2 = TYPE_ARG_TYPES (type2);
+ while (args1 != args2)
+ {
+ /* 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);
+ }
+ return useful_aka_type_p (TREE_TYPE (type1), TREE_TYPE (type2));
+ }
+
+ default:
+ return true;
+ }
+ }
+}
+
/* Print T to CPP. */
static void
@@ -83,7 +150,7 @@ 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) && t != TYPE_CANONICAL (t))
+ if (TYPE_CANONICAL (t) && useful_aka_type_p (t, TYPE_CANONICAL (t)))
{
c_pretty_printer cpp2;
/* Print the stripped version into a temporary printer. */