[committed] c: C2x removal of unprototyped functions
Commit Message
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
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
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
>
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).
@@ -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;
new file mode 100644
@@ -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");
@@ -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" } */
}
@@ -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" } */
@@ -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 } */
new file mode 100644
@@ -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);
new file mode 100644
@@ -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" } */
+}