https://gcc.gnu.org/g:338d687e2a32f4e152d26c02319db1cb00401c3f

commit r15-5576-g338d687e2a32f4e152d26c02319db1cb00401c3f
Author: Joseph Myers <josmy...@redhat.com>
Date:   Thu Nov 21 21:46:00 2024 +0000

    c: Give errors more consistently for void parameters [PR114816]
    
    Cases of void parameters, other than a parameter list of (void) (or
    equivalent with a typedef for void) in its entirety, have been made a
    constraint violation in C2Y (N3344 alternative 1 was adopted), as part
    of a series of changes to eliminate unnecessary undefined behavior by
    turning it into constraint violations, implementation-defined behavior
    or something else with stricter bounds on what behavior is allowed.
    Previously, these were implicitly undefined behavior (see DR#295),
    with only some cases listed in Annex J as undefined (but even those
    cases not having wording in the normative text to make them explicitly
    undefined).
    
    As discussed in bug 114816, GCC is not entirely consistent about
    diagnosing such usages; unnamed void parameters get errors when not
    the entire parameter list, while qualified and register void (the
    cases listed in Annex J) get errors as a single unnamed parameter, but
    named void parameters are accepted with a warning (in a declaration
    that's not a definition; it's not possible to define a function with
    incomplete parameter types).
    
    Following C2Y, make all these cases into errors.  The errors are not
    conditional on the standard version, given that this was previously
    implicit undefined behavior.  Since it wasn't possible anyway to
    define such functions, only declare them without defining them (or
    otherwise use such parameters in function type names that can't
    correspond to any defined function), hopefully the risks of
    compatibility issues are small.
    
    Bootstrapped with no regressions for x86-64-pc-linux-gnu.
    
            PR c/114816
    
    gcc/c/
            * c-decl.cc (grokparms): Do not warn for void parameter type here.
            (get_parm_info): Give errors for void parameters even when named.
    
    gcc/testsuite/
            * gcc.dg/c2y-void-parm-1.c: New test.
            * gcc.dg/noncompile/920616-2.c, gcc.dg/noncompile/921116-1.c,
            gcc.dg/parm-incomplete-1.c: Update expected diagnostics.

Diff:
---
 gcc/c/c-decl.cc                            |  23 ++---
 gcc/testsuite/gcc.dg/c2y-void-parm-1.c     | 152 +++++++++++++++++++++++++++++
 gcc/testsuite/gcc.dg/noncompile/920616-2.c |   2 +-
 gcc/testsuite/gcc.dg/noncompile/921116-1.c |   2 +-
 gcc/testsuite/gcc.dg/parm-incomplete-1.c   |   4 +-
 5 files changed, 163 insertions(+), 20 deletions(-)

diff --git a/gcc/c/c-decl.cc b/gcc/c/c-decl.cc
index c58ff4ab2488..a84b35ea23e7 100644
--- a/gcc/c/c-decl.cc
+++ b/gcc/c/c-decl.cc
@@ -8480,8 +8480,8 @@ grokparms (struct c_arg_info *arg_info, bool funcdef_flag)
         or definition of the function.  In the case where the tag was
         first declared within the parameter list, a warning has
         already been given.  If a parameter has void type, then
-        however the function cannot be defined or called, so
-        warn.  */
+        this has already received an error (constraint violation in C2Y,
+        previously implicitly undefined behavior).  */
 
       for (parm = arg_info->parms, typelt = arg_types, parmno = 1;
           parm;
@@ -8508,17 +8508,6 @@ grokparms (struct c_arg_info *arg_info, bool 
funcdef_flag)
                  TREE_TYPE (parm) = error_mark_node;
                  arg_types = NULL_TREE;
                }
-             else if (VOID_TYPE_P (type))
-               {
-                 if (DECL_NAME (parm))
-                   warning_at (input_location, 0,
-                               "parameter %u (%q+D) has void type",
-                               parmno, parm);
-                 else
-                   warning_at (DECL_SOURCE_LOCATION (parm), 0,
-                               "parameter %u has void type",
-                               parmno);
-               }
            }
 
          if (DECL_NAME (parm) && TREE_USED (parm))
@@ -8627,12 +8616,14 @@ get_parm_info (bool ellipsis, tree expr)
          if (TREE_ASM_WRITTEN (decl))
            error_at (b->locus,
                      "parameter %q+D has just a forward declaration", decl);
-         /* Check for (..., void, ...) and issue an error.  */
-         else if (VOID_TYPE_P (type) && !DECL_NAME (decl))
+         /* Check for (..., void, ...) and named void parameters and issue an
+            error.  */
+         else if (VOID_TYPE_P (type))
            {
              if (!gave_void_only_once_err)
                {
-                 error_at (b->locus, "%<void%> must be the only parameter");
+                 error_at (b->locus,
+                           "%<void%> must be the only parameter and unnamed");
                  gave_void_only_once_err = true;
                }
            }
diff --git a/gcc/testsuite/gcc.dg/c2y-void-parm-1.c 
b/gcc/testsuite/gcc.dg/c2y-void-parm-1.c
new file mode 100644
index 000000000000..aff757ee21c4
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/c2y-void-parm-1.c
@@ -0,0 +1,152 @@
+/* Test errors for void parameters (constraint violation in C2Y, previously
+   implicit undefined behavior; bug 114816).  */
+/* { dg-do compile } */
+/* { dg-options "-std=c2y -pedantic-errors" } */
+
+typedef void Void;
+typedef const void CVoid;
+typedef volatile void VVoid;
+
+/* Valid cases.  */
+void f1 (void);
+void f2 (Void);
+void df1 (void) {}
+void df2 (Void) {}
+
+/* All other variants are invalid.  */
+
+void g1 (const void); /* { dg-error "void" } */
+void g2 (CVoid); /* { dg-error "void" } */
+void g3 (volatile void); /* { dg-error "void" } */
+void g4 (VVoid); /* { dg-error "void" } */
+void g5 (register void); /* { dg-error "void" } */
+void g6 (register Void); /* { dg-error "void" } */
+
+void h1 (void x); /* { dg-error "void" } */
+void h2 (Void x); /* { dg-error "void" } */
+void h3 (const void x); /* { dg-error "void" } */
+void h4 (CVoid x); /* { dg-error "void" } */
+void h5 (volatile void x); /* { dg-error "void" } */
+void h6 (VVoid x); /* { dg-error "void" } */
+void h7 (register void x); /* { dg-error "void" } */
+void h8 (register Void x); /* { dg-error "void" } */
+
+void i1 (void, ...); /* { dg-error "void" } */
+void i2 (Void, ...); /* { dg-error "void" } */
+void i3 (const void, ...); /* { dg-error "void" } */
+void i4 (CVoid, ...); /* { dg-error "void" } */
+void i5 (volatile void, ...); /* { dg-error "void" } */
+void i6 (VVoid, ...); /* { dg-error "void" } */
+void i7 (register void, ...); /* { dg-error "void" } */
+void i8 (register Void, ...); /* { dg-error "void" } */
+
+void j1 (void x, ...); /* { dg-error "void" } */
+void j2 (Void x, ...); /* { dg-error "void" } */
+void j3 (const void x, ...); /* { dg-error "void" } */
+void j4 (CVoid x, ...); /* { dg-error "void" } */
+void j5 (volatile void x, ...); /* { dg-error "void" } */
+void j6 (VVoid x, ...); /* { dg-error "void" } */
+void j7 (register void x, ...); /* { dg-error "void" } */
+void j8 (register Void x, ...); /* { dg-error "void" } */
+
+void k1 (int i, void); /* { dg-error "void" } */
+void k2 (int i, Void); /* { dg-error "void" } */
+void k3 (int i, const void); /* { dg-error "void" } */
+void k4 (int i, CVoid); /* { dg-error "void" } */
+void k5 (int i, volatile void); /* { dg-error "void" } */
+void k6 (int i, VVoid); /* { dg-error "void" } */
+void k7 (int i, register void); /* { dg-error "void" } */
+void k8 (int i, register Void); /* { dg-error "void" } */
+void k9 (int i, void x); /* { dg-error "void" } */
+void k10 (int i, Void x); /* { dg-error "void" } */
+void k11 (int i, const void x); /* { dg-error "void" } */
+void k12 (int i, CVoid x); /* { dg-error "void" } */
+void k13 (int i, volatile void x); /* { dg-error "void" } */
+void k14 (int i, VVoid x); /* { dg-error "void" } */
+void k15 (int i, register void x); /* { dg-error "void" } */
+void k16 (int i, register Void x); /* { dg-error "void" } */
+
+void l1 (void, int i); /* { dg-error "void" } */
+void l2 (Void, int i); /* { dg-error "void" } */
+void l3 (const void, int i); /* { dg-error "void" } */
+void l4 (CVoid, int i); /* { dg-error "void" } */
+void l5 (volatile void, int i); /* { dg-error "void" } */
+void l6 (VVoid, int i); /* { dg-error "void" } */
+void l7 (register void, int i); /* { dg-error "void" } */
+void l8 (register Void, int i); /* { dg-error "void" } */
+void l9 (void x, int i); /* { dg-error "void" } */
+void l10 (Void x, int i); /* { dg-error "void" } */
+void l11 (const void x, int i); /* { dg-error "void" } */
+void l12 (CVoid x, int i); /* { dg-error "void" } */
+void l13 (volatile void x, int i); /* { dg-error "void" } */
+void l14 (VVoid x, int i); /* { dg-error "void" } */
+void l15 (register void x, int i); /* { dg-error "void" } */
+void l16 (register Void x, int i); /* { dg-error "void" } */
+
+void dg1 (const void) {} /* { dg-error "void|incomplete" } */
+void dg2 (CVoid) {} /* { dg-error "void|incomplete" } */
+void dg3 (volatile void) {} /* { dg-error "void|incomplete" } */
+void dg4 (VVoid) {} /* { dg-error "void|incomplete" } */
+void dg5 (register void) {} /* { dg-error "void|incomplete" } */
+void dg6 (register Void) {} /* { dg-error "void|incomplete" } */
+
+void dh1 (void x) {} /* { dg-error "void|incomplete" } */
+void dh2 (Void x) {} /* { dg-error "void|incomplete" } */
+void dh3 (const void x) {} /* { dg-error "void|incomplete" } */
+void dh4 (CVoid x) {} /* { dg-error "void|incomplete" } */
+void dh5 (volatile void x) {} /* { dg-error "void|incomplete" } */
+void dh6 (VVoid x) {} /* { dg-error "void|incomplete" } */
+void dh7 (register void x) {} /* { dg-error "void|incomplete" } */
+void dh8 (register Void x) {} /* { dg-error "void|incomplete" } */
+
+void di1 (void, ...) {} /* { dg-error "void|incomplete" } */
+void di2 (Void, ...) {} /* { dg-error "void|incomplete" } */
+void di3 (const void, ...) {} /* { dg-error "void|incomplete" } */
+void di4 (CVoid, ...) {} /* { dg-error "void|incomplete" } */
+void di5 (volatile void, ...) {} /* { dg-error "void|incomplete" } */
+void di6 (VVoid, ...) {} /* { dg-error "void|incomplete" } */
+void di7 (register void, ...) {} /* { dg-error "void|incomplete" } */
+void di8 (register Void, ...) {} /* { dg-error "void|incomplete" } */
+
+void dj1 (void x, ...) {} /* { dg-error "void|incomplete" } */
+void dj2 (Void x, ...) {} /* { dg-error "void|incomplete" } */
+void dj3 (const void x, ...) {} /* { dg-error "void|incomplete" } */
+void dj4 (CVoid x, ...) {} /* { dg-error "void|incomplete" } */
+void dj5 (volatile void x, ...) {} /* { dg-error "void|incomplete" } */
+void dj6 (VVoid x, ...) {} /* { dg-error "void|incomplete" } */
+void dj7 (register void x, ...) {} /* { dg-error "void|incomplete" } */
+void dj8 (register Void x, ...) {} /* { dg-error "void|incomplete" } */
+
+void dk1 (int i, void) {} /* { dg-error "void|incomplete" } */
+void dk2 (int i, Void) {} /* { dg-error "void|incomplete" } */
+void dk3 (int i, const void) {} /* { dg-error "void|incomplete" } */
+void dk4 (int i, CVoid) {} /* { dg-error "void|incomplete" } */
+void dk5 (int i, volatile void) {} /* { dg-error "void|incomplete" } */
+void dk6 (int i, VVoid) {} /* { dg-error "void|incomplete" } */
+void dk7 (int i, register void) {} /* { dg-error "void|incomplete" } */
+void dk8 (int i, register Void) {} /* { dg-error "void|incomplete" } */
+void dk9 (int i, void x) {} /* { dg-error "void|incomplete" } */
+void dk10 (int i, Void x) {} /* { dg-error "void|incomplete" } */
+void dk11 (int i, const void x) {} /* { dg-error "void|incomplete" } */
+void dk12 (int i, CVoid x) {} /* { dg-error "void|incomplete" } */
+void dk13 (int i, volatile void x) {} /* { dg-error "void|incomplete" } */
+void dk14 (int i, VVoid x) {} /* { dg-error "void|incomplete" } */
+void dk15 (int i, register void x) {} /* { dg-error "void|incomplete" } */
+void dk16 (int i, register Void x) {} /* { dg-error "void|incomplete" } */
+
+void dl1 (void, int i) {} /* { dg-error "void|incomplete" } */
+void dl2 (Void, int i) {} /* { dg-error "void|incomplete" } */
+void dl3 (const void, int i) {} /* { dg-error "void|incomplete" } */
+void dl4 (CVoid, int i) {} /* { dg-error "void|incomplete" } */
+void dl5 (volatile void, int i) {} /* { dg-error "void|incomplete" } */
+void dl6 (VVoid, int i) {} /* { dg-error "void|incomplete" } */
+void dl7 (register void, int i) {} /* { dg-error "void|incomplete" } */
+void dl8 (register Void, int i) {} /* { dg-error "void|incomplete" } */
+void dl9 (void x, int i) {} /* { dg-error "void|incomplete" } */
+void dl10 (Void x, int i) {} /* { dg-error "void|incomplete" } */
+void dl11 (const void x, int i) {} /* { dg-error "void|incomplete" } */
+void dl12 (CVoid x, int i) {} /* { dg-error "void|incomplete" } */
+void dl13 (volatile void x, int i) {} /* { dg-error "void|incomplete" } */
+void dl14 (VVoid x, int i) {} /* { dg-error "void|incomplete" } */
+void dl15 (register void x, int i) {} /* { dg-error "void|incomplete" } */
+void dl16 (register Void x, int i) {} /* { dg-error "void|incomplete" } */
diff --git a/gcc/testsuite/gcc.dg/noncompile/920616-2.c 
b/gcc/testsuite/gcc.dg/noncompile/920616-2.c
index e43d00981f40..a31a38e29250 100644
--- a/gcc/testsuite/gcc.dg/noncompile/920616-2.c
+++ b/gcc/testsuite/gcc.dg/noncompile/920616-2.c
@@ -1 +1 @@
-void f(void a,...){}           /* { dg-error "has incomplete type" } */
+void f(void a,...){}           /* { dg-error "void|has incomplete type" } */
diff --git a/gcc/testsuite/gcc.dg/noncompile/921116-1.c 
b/gcc/testsuite/gcc.dg/noncompile/921116-1.c
index 890bbb63404d..3c07450cd4cf 100644
--- a/gcc/testsuite/gcc.dg/noncompile/921116-1.c
+++ b/gcc/testsuite/gcc.dg/noncompile/921116-1.c
@@ -1 +1 @@
-void a (void x) {}     /* { dg-error "has incomplete type" } */
+void a (void x) {}     /* { dg-error "void|has incomplete type" } */
diff --git a/gcc/testsuite/gcc.dg/parm-incomplete-1.c 
b/gcc/testsuite/gcc.dg/parm-incomplete-1.c
index 0c0ae85d86fa..e4122f07c69c 100644
--- a/gcc/testsuite/gcc.dg/parm-incomplete-1.c
+++ b/gcc/testsuite/gcc.dg/parm-incomplete-1.c
@@ -22,6 +22,6 @@ union u;
 
 void v(union u x) { } /* { dg-error "parameter 1 \\('x'\\) has incomplete 
type" } */
 
-void p(void x); /* { dg-warning "parameter 1 \\('x'\\) has void type" } */
+void p(void x); /* { dg-error "'void' must be the only parameter and unnamed" 
} */
 
-void q(const void x); /* { dg-warning "parameter 1 \\('x'\\) has void type" } 
*/
+void q(const void x); /* { dg-error "'void' must be the only parameter and 
unnamed" } */

Reply via email to