[committed] c: C2x removal of unprototyped functions

Message ID alpine.DEB.2.22.394.2209011911410.550568@digraph.polyomino.org.uk
State New, archived
Headers
Series [committed] c: C2x removal of unprototyped functions |

Commit Message

Joseph Myers Sept. 1, 2022, 7:12 p.m. UTC
  C2x has completely removed unprototyped functions, so that () now
means the same as (void) in both function declarations and
definitions, where previously that change had been made for
definitions only.  Implement this accordingly.

This is a change where GNU/Linux distribution builders might wish to
try builds with a -std=gnu2x default to start early on getting old
code fixed that still has () declarations for functions taking
arguments, in advance of GCC moving to -std=gnu2x as default maybe in
GCC 14 or 15; I don't know how much such code is likely to be in
current use.

Bootstrapped with no regressions for x86_64-pc-linux-gnu.

gcc/c/
	* c-decl.cc (grokparms): Handle () in a function declaration the
	same as (void) for C2X.

gcc/testsuite/
	* gcc.dg/c11-unproto-3.c, gcc.dg/c2x-unproto-3.c,
	gcc.dg/c2x-unproto-4.c: New tests.
	* gcc.dg/c2x-old-style-definition-6.c, gcc.dg/c2x-unproto-1.c,
	gcc.dg/c2x-unproto-2.c: Update for removal of unprototyped
	functions.
  

Comments

Jeff Law Sept. 1, 2022, 9:18 p.m. UTC | #1
On 9/1/2022 1:12 PM, Joseph Myers wrote:
> C2x has completely removed unprototyped functions, so that () now
> means the same as (void) in both function declarations and
> definitions, where previously that change had been made for
> definitions only.  Implement this accordingly.
>
> This is a change where GNU/Linux distribution builders might wish to
> try builds with a -std=gnu2x default to start early on getting old
> code fixed that still has () declarations for functions taking
> arguments, in advance of GCC moving to -std=gnu2x as default maybe in
> GCC 14 or 15; I don't know how much such code is likely to be in
> current use.
Happy to see this happen (dropping unprototyped funtions).  IIRC older 
versions of autoconf are going to generate code that runs afoul of this 
problem as well.

jeff
  
Richard Biener Sept. 2, 2022, 6:16 a.m. UTC | #2
On Thu, Sep 1, 2022 at 11:18 PM Jeff Law via Gcc-patches
<gcc-patches@gcc.gnu.org> wrote:
>
>
>
> On 9/1/2022 1:12 PM, Joseph Myers wrote:
> > C2x has completely removed unprototyped functions, so that () now
> > means the same as (void) in both function declarations and
> > definitions, where previously that change had been made for
> > definitions only.  Implement this accordingly.
> >
> > This is a change where GNU/Linux distribution builders might wish to
> > try builds with a -std=gnu2x default to start early on getting old
> > code fixed that still has () declarations for functions taking
> > arguments, in advance of GCC moving to -std=gnu2x as default maybe in
> > GCC 14 or 15; I don't know how much such code is likely to be in
> > current use.
> Happy to see this happen (dropping unprototyped funtions).  IIRC older
> versions of autoconf are going to generate code that runs afoul of this
> problem as well.

To catch these cases with a diagnostic earlier is
-Wstrict-prototypes -Wold-style-declaration enough to diagnose all cases
that the new standard will reject?

I suppose -W*-c2x-compat are not the correct vehicle to diagnose these?

Thanks,
Richard.

>
> jeff
>
  
Joseph Myers Sept. 5, 2022, 7:51 p.m. UTC | #3
On Fri, 2 Sep 2022, Richard Biener via Gcc-patches wrote:

> To catch these cases with a diagnostic earlier is
> -Wstrict-prototypes -Wold-style-declaration enough to diagnose all cases
> that the new standard will reject?

I think so.

> I suppose -W*-c2x-compat are not the correct vehicle to diagnose these?

It could probably be made to diagnose such cases (it doesn't come 
automatically because this change involves changed semantics for syntax 
that's valid in both standard versions).
  

Patch

diff --git a/gcc/c/c-decl.cc b/gcc/c/c-decl.cc
index 804314dd0f2..34f8feda897 100644
--- a/gcc/c/c-decl.cc
+++ b/gcc/c/c-decl.cc
@@ -7868,7 +7868,7 @@  grokparms (struct c_arg_info *arg_info, bool funcdef_flag)
       error ("%<[*]%> not allowed in other than function prototype scope");
     }
 
-  if (arg_types == NULL_TREE && !funcdef_flag
+  if (arg_types == NULL_TREE && !funcdef_flag && !flag_isoc2x
       && !in_system_header_at (input_location))
     warning (OPT_Wstrict_prototypes,
 	     "function declaration isn%'t a prototype");
@@ -7896,9 +7896,8 @@  grokparms (struct c_arg_info *arg_info, bool funcdef_flag)
       tree parm, type, typelt;
       unsigned int parmno;
 
-      /* In C2X, convert () in a function definition to (void).  */
+      /* In C2X, convert () to (void).  */
       if (flag_isoc2x
-	  && funcdef_flag
 	  && !arg_types
 	  && !arg_info->parms)
 	arg_types = arg_info->types = void_list_node;
diff --git a/gcc/testsuite/gcc.dg/c11-unproto-3.c b/gcc/testsuite/gcc.dg/c11-unproto-3.c
new file mode 100644
index 00000000000..b0e4bf3d5b1
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/c11-unproto-3.c
@@ -0,0 +1,19 @@ 
+/* Test function declarations without prototypes for C11.  */
+/* { dg-do compile } */
+/* { dg-options "-std=c11 -pedantic-errors" } */
+
+void f1 ();
+void
+f1a (void)
+{
+  f1 (1, 2);
+}
+
+void f2 ();
+void f2 (int);
+
+void f3 ();
+
+_Static_assert (_Generic (f3,
+			  void (*) (int) : 1,
+			  default : 3) == 1, "unprototyped test");
diff --git a/gcc/testsuite/gcc.dg/c2x-old-style-definition-6.c b/gcc/testsuite/gcc.dg/c2x-old-style-definition-6.c
index fc0e778446d..72bfd56f00a 100644
--- a/gcc/testsuite/gcc.dg/c2x-old-style-definition-6.c
+++ b/gcc/testsuite/gcc.dg/c2x-old-style-definition-6.c
@@ -1,16 +1,16 @@ 
-/* Test old-style function definitions not in C2x: () does not give
-   type with a prototype except for function definitions.  */
+/* Test old-style function definitions not in C2x: () gives a type with
+   a prototype for all declarations.  */
 /* { dg-do compile } */
 /* { dg-options "-std=c2x" } */
 
-void f1 ();
+void f1 (); /* { dg-message "declared here" } */
 
-/* Prototyped function returning a pointer to unprototyped function.  */
+/* Prototyped function returning a pointer to a function with no arguments.  */
 void (*f2 (void))() { return f1; }
 
 void
 g (void)
 {
-  f1 (1);
-  f2 () (1);
+  f1 (1); /* { dg-error "too many arguments" } */
+  f2 () (1); /* { dg-error "too many arguments" } */
 }
diff --git a/gcc/testsuite/gcc.dg/c2x-unproto-1.c b/gcc/testsuite/gcc.dg/c2x-unproto-1.c
index aa87d78610e..d21c6a712fb 100644
--- a/gcc/testsuite/gcc.dg/c2x-unproto-1.c
+++ b/gcc/testsuite/gcc.dg/c2x-unproto-1.c
@@ -1,25 +1,21 @@ 
-/* Test compatibility of unprototyped and prototyped function types (C2x made
-   the case of types affected by default argument promotions compatible, before
-   removing unprototyped functions completely).  Test affected usages are not
-   accepted for C2x.  */
+/* Test compatibility of prototyped function types with and without arguments
+   (C2x made the case of types affected by default argument promotions
+   compatible, before removing unprototyped functions completely).  Test
+   affected usages are not accepted for C2x.  */
 /* { dg-do compile } */
 /* { dg-options "-std=c2x -pedantic-errors" } */
 
 void f1 (); /* { dg-message "previous declaration" } */
 void f1 (float); /* { dg-error "conflicting types" } */
-/* { dg-message "default promotion" "" { target *-*-* } .-1 } */
 
 void f2 (float); /* { dg-message "previous declaration" } */
 void f2 (); /* { dg-error "conflicting types" } */
-/* { dg-message "default promotion" "" { target *-*-* } .-1 } */
 
 void f3 (); /* { dg-message "previous declaration" } */
 void f3 (char); /* { dg-error "conflicting types" } */
-/* { dg-message "default promotion" "" { target *-*-* } .-1 } */
 
 void f4 (char); /* { dg-message "previous declaration" } */
 void f4 (); /* { dg-error "conflicting types" } */
-/* { dg-message "default promotion" "" { target *-*-* } .-1 } */
 
 /* Built-in function case.  */
 float sqrtf (); /* { dg-warning "conflicting types for built-in function" } */
diff --git a/gcc/testsuite/gcc.dg/c2x-unproto-2.c b/gcc/testsuite/gcc.dg/c2x-unproto-2.c
index 3d5ae9d8460..533fb743b4e 100644
--- a/gcc/testsuite/gcc.dg/c2x-unproto-2.c
+++ b/gcc/testsuite/gcc.dg/c2x-unproto-2.c
@@ -1,22 +1,18 @@ 
-/* Test compatibility of unprototyped and prototyped function types (C2x made
-   the case of types affected by default argument promotions compatible, before
-   removing unprototyped functions completely).  Test always-invalid-in-C2x
-   usages, in C2X mode.  */
+/* Test compatibility of prototyped function types without arguments and with
+   variable arguments (C2x made the case of types affected by default argument
+   promotions compatible, before removing unprototyped functions completely).
+   Test always-invalid-in-C2x usages, in C2X mode.  */
 /* { dg-do compile } */
 /* { dg-options "-std=c2x -pedantic-errors" } */
 
 void f1 (); /* { dg-message "previous declaration" } */
 void f1 (int, ...); /* { dg-error "conflicting types" } */
-/* { dg-message "ellipsis" "" { target *-*-* } .-1 } */
 
 void f2 (int, ...); /* { dg-message "previous declaration" } */
 void f2 (); /* { dg-error "conflicting types" } */
-/* { dg-message "ellipsis" "" { target *-*-* } .-1 } */
 
 void f3 (); /* { dg-message "previous declaration" } */
 void f3 (char, ...); /* { dg-error "conflicting types" } */
-/* { dg-message "ellipsis" "" { target *-*-* } .-1 } */
 
 void f4 (char, ...); /* { dg-message "previous declaration" } */
 void f4 (); /* { dg-error "conflicting types" } */
-/* { dg-message "ellipsis" "" { target *-*-* } .-1 } */
diff --git a/gcc/testsuite/gcc.dg/c2x-unproto-3.c b/gcc/testsuite/gcc.dg/c2x-unproto-3.c
new file mode 100644
index 00000000000..762f8b21034
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/c2x-unproto-3.c
@@ -0,0 +1,20 @@ 
+/* Test that declaring a function with () is the same as (void) in C2X.  Valid
+   use cases.  */
+/* { dg-do compile } */
+/* { dg-options "-std=c2x -pedantic-errors -Wstrict-prototypes" } */
+
+void f1 ();
+void f1 (void);
+
+void f2 (void);
+void f2 ();
+
+typedef void T1 ();
+typedef void T1 (void);
+
+void f3 ();
+
+_Static_assert (_Generic (f3,
+			  void (*) (int) : 1,
+			  void (*) (void) : 2,
+			  default : 3) == 2);
diff --git a/gcc/testsuite/gcc.dg/c2x-unproto-4.c b/gcc/testsuite/gcc.dg/c2x-unproto-4.c
new file mode 100644
index 00000000000..fceff22b1af
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/c2x-unproto-4.c
@@ -0,0 +1,15 @@ 
+/* Test that declaring a function with () is the same as (void) in C2X.
+   Invalid use cases.  */
+/* { dg-do compile } */
+/* { dg-options "-std=c2x -pedantic-errors" } */
+
+void f1 (); /* { dg-message "previous declaration" } */
+void f1 (int); /* { dg-error "conflicting types" } */
+
+void f2 (); /* { dg-message "declared here" } */
+
+void
+f3 (void)
+{
+  f2 (1); /* { dg-error "too many arguments" } */
+}