]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
c2y: Allow unspecified arrays in generic association.
authorMartin Uecker <uecker@tugraz.at>
Sun, 12 Oct 2025 18:00:22 +0000 (20:00 +0200)
committerMartin Uecker <uecker@gcc.gnu.org>
Tue, 21 Oct 2025 17:26:45 +0000 (19:26 +0200)
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
gcc/c/c-parser.cc
gcc/c/c-tree.h
gcc/testsuite/gcc.dg/c2y-generic-6.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/c2y-generic-7.c [new file with mode: 0644]

index 4a940d5eec33e361563f85faadf9176d1d02b5d7..061892ac95b89ee642221af82bac6d213be615fc 100644 (file)
@@ -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.  */
index 1d212b51fcda54106d758be63895ffd2c10c665e..56fb0be25b5334fa30a41f9fd2e0e894475fb3a4 100644 (file)
@@ -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);
index 162add0522acb2d30223edcd4e051e5e16574b85..f367cda35d7c5db3529b67cb456d9c33b998e1d0 100644 (file)
@@ -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 (file)
index 0000000..7220d94
--- /dev/null
@@ -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 (file)
index 0000000..6ca046c
--- /dev/null
@@ -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;
+}
+