Thanks Joseph for your comments. This version
- renumbers the tests,
- adds a test that shows that size expressions in
the type name are not evaluated,
- adds a comment for GENERIC_ASSOC and mentions it
in the comment for grokdeclarator.
Bootstrapped and regression tested on x86_64.
To allow unspecified arrays in generic association add a new
declaration context GENERIC_ASSOC for grokdeclarator and new
function grokgenassoc to be used by the parser. The error
about unspecified array is moved from build_array_declarator
to grokdeclarator to be able to check for this.
gcc/c/ChangeLog:
* c-decl.cc (build_array_declarator): Remove error.
(grokgenassoc): New function.
(grokdeclarator): Add error.
* c-parser.cc (c_parser_generic_selection): Use grokgenassoc.
* c-tree.h (grokgenassoc): Add prototype.
gcc/testsuite/ChangeLog:
* gcc.dg/c2y-generic-6.c: New test.
* gcc.dg/c2y-generic-7.c: New test.
---
gcc/c/c-decl.cc | 70 +++++++++++++++++++---------
gcc/c/c-parser.cc | 2 +-
gcc/c/c-tree.h | 1 +
gcc/testsuite/gcc.dg/c2y-generic-6.c | 11 +++++
gcc/testsuite/gcc.dg/c2y-generic-7.c | 15 ++++++
5 files changed, 76 insertions(+), 23 deletions(-)
create mode 100644 gcc/testsuite/gcc.dg/c2y-generic-6.c
create mode 100644 gcc/testsuite/gcc.dg/c2y-generic-7.c
diff --git a/gcc/c/c-decl.cc b/gcc/c/c-decl.cc
index 4a940d5eec3..061892ac95b 100644
--- a/gcc/c/c-decl.cc
+++ b/gcc/c/c-decl.cc
@@ -71,7 +71,8 @@ enum decl_context
FUNCDEF, /* Function definition */
PARM, /* Declaration of parm before function
body */
FIELD, /* Declaration inside struct or union */
- TYPENAME}; /* Typename (inside cast or sizeof) */
+ TYPENAME, /* Typename (inside cast or sizeof) */
+ GENERIC_ASSOC }; /* Typename in generic association */
/* States indicating how grokdeclarator() should handle declspecs marked
with __attribute__((deprecated)) or __attribute__((unavailable)).
@@ -5455,20 +5456,12 @@ build_array_declarator (location_t loc,
pedwarn_c90 (loc, OPT_Wpedantic,
"ISO C90 does not support %<static%> or type "
"qualifiers in parameter array declarators");
- if (vla_unspec_p)
- pedwarn_c90 (loc, OPT_Wpedantic,
- "ISO C90 does not support %<[*]%> array declarators");
if (vla_unspec_p)
{
- if (!current_scope->parm_flag)
- {
- /* C99 6.7.5.2p4 */
- error_at (loc, "%<[*]%> not allowed in other than "
- "function prototype scope");
- declarator->u.array.vla_unspec_p = false;
- return NULL;
- }
- current_scope->had_vla_unspec = true;
+ pedwarn_c90 (loc, OPT_Wpedantic,
+ "ISO C90 does not support %<[*]%> array declarators");
+ if (current_scope->parm_flag)
+ current_scope->had_vla_unspec = true;
}
return declarator;
}
@@ -5574,6 +5567,29 @@ groktypename (struct c_type_name *type_name, tree *expr,
return type;
}
+
+/* Decode a "typename", such as "int **", returning a ..._TYPE node,
+ as for groktypename but setting the context to GENERIC_ASSOC. */
+
+tree
+grokgenassoc (struct c_type_name *type_name)
+{
+ tree type;
+ tree attrs = type_name->specs->attrs;
+
+ type_name->specs->attrs = NULL_TREE;
+
+ type = grokdeclarator (type_name->declarator, type_name->specs,
GENERIC_ASSOC,
+ false, NULL, &attrs, NULL, NULL, DEPRECATED_NORMAL);
+
+ /* Apply attributes. */
+ attrs = c_warn_type_attributes (type, attrs);
+ decl_attributes (&type, attrs, 0);
+
+ return type;
+}
+
+
/* Looks up the most recent pushed declaration corresponding to DECL. */
static tree
@@ -6772,6 +6788,7 @@ build_arg_spec_attribute (tree type, bool static_p, tree
attrs)
or before a function body). Make a PARM_DECL, or return void_type_node.
TYPENAME if for a typename (in a cast or sizeof).
Don't make a DECL node; just return the ..._TYPE node.
+ GENERIC_ASSOC for typenames in a generic association.
FIELD for a struct or union field; make a FIELD_DECL.
INITIALIZED is true if the decl has an initializer.
WIDTH is non-NULL for bit-fields, and is a pointer to an INTEGER_CST node
@@ -6908,6 +6925,7 @@ grokdeclarator (const struct c_declarator *declarator,
{
gcc_assert (decl_context == PARM
|| decl_context == TYPENAME
+ || decl_context == GENERIC_ASSOC
|| (decl_context == FIELD
&& declarator->kind == cdk_id));
gcc_assert (!initialized);
@@ -7481,14 +7499,6 @@ grokdeclarator (const struct c_declarator *declarator,
itype = build_index_type (NULL_TREE);
}
- if (array_parm_vla_unspec_p)
- {
- /* C99 6.7.5.2p4 */
- if (decl_context == TYPENAME)
- warning (0, "%<[*]%> not in a declaration");
- size_varies = true;
- }
-
/* Complain about arrays of incomplete types. */
if (!COMPLETE_TYPE_P (type))
{
@@ -7527,6 +7537,22 @@ grokdeclarator (const struct c_declarator *declarator,
type = c_build_array_type (type, itype);
}
+ if (array_parm_vla_unspec_p)
+ {
+ /* C99 6.7.5.2p4 */
+ if (decl_context == TYPENAME)
+ warning (0, "%<[*]%> not in a declaration");
+ else if (decl_context != GENERIC_ASSOC
+ && decl_context != PARM
+ && decl_context != FIELD)
+ {
+ error ("%<[*]%> not allowed in other than function
prototype scope "
+ "or generic association");
+ type = error_mark_node;
+ }
+ size_varies = true;
+ }
+
if (type != error_mark_node)
{
/* The GCC extension for zero-length arrays differs from
@@ -7898,7 +7924,7 @@ grokdeclarator (const struct c_declarator *declarator,
/* If this is a type name (such as, in a cast or sizeof),
compute the type and return it now. */
- if (decl_context == TYPENAME)
+ if (decl_context == TYPENAME || decl_context == GENERIC_ASSOC)
{
/* Note that the grammar rejects storage classes in typenames
and fields. */
diff --git a/gcc/c/c-parser.cc b/gcc/c/c-parser.cc
index ea0294f0738..1d331c4370f 100644
--- a/gcc/c/c-parser.cc
+++ b/gcc/c/c-parser.cc
@@ -11240,7 +11240,7 @@ c_parser_generic_selection (c_parser *parser)
c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
return error_expr;
}
- assoc.type = groktypename (type_name, NULL, NULL);
+ assoc.type = grokgenassoc (type_name);
if (assoc.type == error_mark_node)
{
c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
diff --git a/gcc/c/c-tree.h b/gcc/c/c-tree.h
index 162add0522a..f367cda35d7 100644
--- a/gcc/c/c-tree.h
+++ b/gcc/c/c-tree.h
@@ -713,6 +713,7 @@ extern struct c_arg_info *get_parm_info (bool, tree);
extern tree grokfield (location_t, struct c_declarator *,
struct c_declspecs *, tree, tree *, tree *);
extern tree groktypename (struct c_type_name *, tree *, bool *);
+extern tree grokgenassoc (struct c_type_name *);
extern tree grokparm (const struct c_parm *, tree *);
extern tree implicitly_declare (location_t, tree);
extern void keep_next_level (void);
diff --git a/gcc/testsuite/gcc.dg/c2y-generic-6.c
b/gcc/testsuite/gcc.dg/c2y-generic-6.c
new file mode 100644
index 00000000000..7220d940144
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/c2y-generic-6.c
@@ -0,0 +1,11 @@
+/* { dg-do "compile" } */
+/* { dg-options "-std=c2y -Wpedantic" } */
+
+void f()
+{
+ _Generic(1, int[*]: 1, default: 0);
+ _Generic(1, int(*)[*]: 1, default: 0);
+ _Generic(1, int[sizeof(int[*])]: 1, default: 0); /* { dg-warning
"not in a declaration" } */
+ _Generic(1, struct { int a[*]; }: 1, default: 0); /* { dg-warning
"variably modified" } */
+}
+
diff --git a/gcc/testsuite/gcc.dg/c2y-generic-7.c
b/gcc/testsuite/gcc.dg/c2y-generic-7.c
new file mode 100644
index 00000000000..6ca046c90a8
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/c2y-generic-7.c
@@ -0,0 +1,15 @@
+/* { dg-do "run" } */
+/* { dg-options "-std=c2y" } */
+
+int main()
+{
+ int n = 1;
+ int a[1];
+ _Generic(typeof(a), int[n++]: 0);
+ float b[1];
+ _Generic(typeof(b), int[n++]: 0, default: 1);
+ if (n != 1)
+ __builtin_abort();
+ return 0;
+}
+
--
2.47.3