Handle removal of old-style function definitions in C2x
diff mbox series

Message ID alpine.DEB.2.21.1911080121400.6360@digraph.polyomino.org.uk
State New
Headers show
Series
  • Handle removal of old-style function definitions in C2x
Related show

Commit Message

Joseph Myers Nov. 8, 2019, 1:22 a.m. UTC
C2x removes support for old-style function definitions with identifier
lists, changing () in function definitions to be equivalent to (void)
(while () in declarations that are not definitions still gives an
unprototyped type).

This patch updates GCC accordingly.  The new semantics for () are
implemented for C2x mode (meaning () in function definitions isn't
diagnosed by -Wold-style-definition in that mode).
-Wold-style-definition is enabled by default, and turned into a
pedwarn, for C2x.

Bootstrapped with no regressions on x86_64-pc-linux-gnu.  Applied to 
mainline.

gcc:
2019-11-08  Joseph Myers  <joseph@codesourcery.com>

	* doc/invoke.texi (-Wold-style-definition): Document () not being
	considered an old-style definition for C2x.

gcc/c:
2019-11-08  Joseph Myers  <joseph@codesourcery.com>

	* c-decl.c (grokparms): Convert () in a function definition to
	(void) for C2x.
	(store_parm_decls_oldstyle): Pedwarn for C2x.
	(store_parm_decls): Update comment about () not generating a
	prototype.

gcc/c-family:
2019-11-08  Joseph Myers  <joseph@codesourcery.com>

	* c.opt (Wold-style-definition): Initialize to -1.
	* c-opts.c (c_common_post_options): Set warn_old_style_definition
	to flag_isoc2x if not set explicitly.

gcc/testsuite:
2019-11-08  Joseph Myers  <joseph@codesourcery.com>

	* gcc.dg/c11-old-style-definition-1.c,
	gcc.dg/c11-old-style-definition-2.c,
	gcc.dg/c2x-old-style-definition-1.c,
	gcc.dg/c2x-old-style-definition-2.c,
	gcc.dg/c2x-old-style-definition-3.c,
	gcc.dg/c2x-old-style-definition-4.c,
	gcc.dg/c2x-old-style-definition-5.c,
	gcc.dg/c2x-old-style-definition-6.c: New tests.

Patch
diff mbox series

Index: gcc/c/c-decl.c
===================================================================
--- gcc/c/c-decl.c	(revision 277935)
+++ gcc/c/c-decl.c	(working copy)
@@ -7416,6 +7416,13 @@  grokparms (struct c_arg_info *arg_info, bool funcd
       tree parm, type, typelt;
       unsigned int parmno;
 
+      /* In C2X, convert () in a function definition to (void).  */
+      if (flag_isoc2x
+	  && funcdef_flag
+	  && !arg_types
+	  && !arg_info->parms)
+	arg_types = arg_info->types = void_list_node;
+
       /* If there is a parameter of incomplete type in a definition,
 	 this is an error.  In a declaration this is valid, and a
 	 struct or union type may be completed later, before any calls
@@ -9261,8 +9268,15 @@  store_parm_decls_oldstyle (tree fndecl, const stru
   hash_set<tree> seen_args;
 
   if (!in_system_header_at (input_location))
-    warning_at (DECL_SOURCE_LOCATION (fndecl),
-		OPT_Wold_style_definition, "old-style function definition");
+    {
+      if (flag_isoc2x)
+	pedwarn (DECL_SOURCE_LOCATION (fndecl),
+		 OPT_Wold_style_definition, "old-style function definition");
+      else
+	warning_at (DECL_SOURCE_LOCATION (fndecl),
+		    OPT_Wold_style_definition,
+		    "old-style function definition");
+    }
 
   /* Match each formal parameter name with its declaration.  Save each
      decl in the appropriate TREE_PURPOSE slot of the parmids chain.  */
@@ -9578,11 +9592,10 @@  store_parm_decls (void)
   struct c_arg_info *arg_info = current_function_arg_info;
   current_function_arg_info = 0;
 
-  /* True if this definition is written with a prototype.  Note:
-     despite C99 6.7.5.3p14, we can *not* treat an empty argument
-     list in a function definition as equivalent to (void) -- an
-     empty argument list specifies the function has no parameters,
-     but only (void) sets up a prototype for future calls.  */
+  /* True if this definition is written with a prototype.  In C2X, an
+     empty argument list was converted to (void) in grokparms; in
+     older C standard versions, it does not give the function a type
+     with a prototype for future calls.  */
   proto = arg_info->types != 0;
 
   if (proto)
Index: gcc/c-family/c-opts.c
===================================================================
--- gcc/c-family/c-opts.c	(revision 277935)
+++ gcc/c-family/c-opts.c	(working copy)
@@ -904,6 +904,10 @@  c_common_post_options (const char **pfilename)
   if (warn_implicit_int == -1)
     warn_implicit_int = flag_isoc99;
 
+  /* -Wold-style-definition is enabled by default for C2X.  */
+  if (warn_old_style_definition == -1)
+    warn_old_style_definition = flag_isoc2x;
+
   /* -Wshift-overflow is enabled by default in C99 and C++11 modes.  */
   if (warn_shift_overflow == -1)
     warn_shift_overflow = cxx_dialect >= cxx11 || flag_isoc99;
Index: gcc/c-family/c.opt
===================================================================
--- gcc/c-family/c.opt	(revision 277935)
+++ gcc/c-family/c.opt	(working copy)
@@ -960,7 +960,7 @@  C ObjC Var(warn_old_style_declaration) Warning Ena
 Warn for obsolescent usage in a declaration.
 
 Wold-style-definition
-C ObjC Var(warn_old_style_definition) Warning
+C ObjC Var(warn_old_style_definition) Init(-1) Warning
 Warn if an old-style parameter definition is used.
 
 Wopenmp-simd
Index: gcc/doc/invoke.texi
===================================================================
--- gcc/doc/invoke.texi	(revision 277935)
+++ gcc/doc/invoke.texi	(working copy)
@@ -7334,7 +7334,10 @@  is also enabled by @option{-Wextra}.
 @opindex Wold-style-definition
 @opindex Wno-old-style-definition
 Warn if an old-style function definition is used.  A warning is given
-even if there is a previous prototype.
+even if there is a previous prototype.  A definition using @samp{()}
+is not considered an old-style definition in C2X mode, because it is
+equivalent to @samp{(void)} in that case, but is considered an
+old-style definition for older standards.
 
 @item -Wmissing-parameter-type @r{(C and Objective-C only)}
 @opindex Wmissing-parameter-type
Index: gcc/testsuite/gcc.dg/c11-old-style-definition-1.c
===================================================================
--- gcc/testsuite/gcc.dg/c11-old-style-definition-1.c	(nonexistent)
+++ gcc/testsuite/gcc.dg/c11-old-style-definition-1.c	(working copy)
@@ -0,0 +1,9 @@ 
+/* Test old-style function definitions not in C2x: allowed in C11.  */
+/* { dg-do compile } */
+/* { dg-options "-std=c11 -pedantic-errors" } */
+
+void
+f (x)
+     int x;
+{
+}
Index: gcc/testsuite/gcc.dg/c11-old-style-definition-2.c
===================================================================
--- gcc/testsuite/gcc.dg/c11-old-style-definition-2.c	(nonexistent)
+++ gcc/testsuite/gcc.dg/c11-old-style-definition-2.c	(working copy)
@@ -0,0 +1,15 @@ 
+/* Test old-style function definitions not in C2x: () does not give
+   type with a prototype for older standards.  */
+/* { dg-do compile } */
+/* { dg-options "-std=c11" } */
+
+void
+f ()
+{
+}
+
+void
+g (void)
+{
+  f (1);
+}
Index: gcc/testsuite/gcc.dg/c2x-old-style-definition-1.c
===================================================================
--- gcc/testsuite/gcc.dg/c2x-old-style-definition-1.c	(nonexistent)
+++ gcc/testsuite/gcc.dg/c2x-old-style-definition-1.c	(working copy)
@@ -0,0 +1,9 @@ 
+/* Test old-style function definitions not in C2x: warnings.  */
+/* { dg-do compile } */
+/* { dg-options "-std=c2x" } */
+
+void
+f (x) /* { dg-warning "old-style function definition" } */
+     int x;
+{
+}
Index: gcc/testsuite/gcc.dg/c2x-old-style-definition-2.c
===================================================================
--- gcc/testsuite/gcc.dg/c2x-old-style-definition-2.c	(nonexistent)
+++ gcc/testsuite/gcc.dg/c2x-old-style-definition-2.c	(working copy)
@@ -0,0 +1,9 @@ 
+/* Test old-style function definitions not in C2x: errors.  */
+/* { dg-do compile } */
+/* { dg-options "-std=c2x -pedantic-errors" } */
+
+void
+f (x) /* { dg-error "old-style function definition" } */
+     int x;
+{
+}
Index: gcc/testsuite/gcc.dg/c2x-old-style-definition-3.c
===================================================================
--- gcc/testsuite/gcc.dg/c2x-old-style-definition-3.c	(nonexistent)
+++ gcc/testsuite/gcc.dg/c2x-old-style-definition-3.c	(working copy)
@@ -0,0 +1,10 @@ 
+/* Test old-style function definitions not in C2x: warnings disabled
+   by -Wno-old-style-definition.  */
+/* { dg-do compile } */
+/* { dg-options "-std=c2x -Wno-old-style-definition" } */
+
+void
+f (x)
+     int x;
+{
+}
Index: gcc/testsuite/gcc.dg/c2x-old-style-definition-4.c
===================================================================
--- gcc/testsuite/gcc.dg/c2x-old-style-definition-4.c	(nonexistent)
+++ gcc/testsuite/gcc.dg/c2x-old-style-definition-4.c	(working copy)
@@ -0,0 +1,15 @@ 
+/* Test old-style function definitions not in C2x: () gives type with
+   a prototype.  */
+/* { dg-do compile } */
+/* { dg-options "-std=c2x" } */
+
+void
+f ()
+{
+}
+
+void
+g (void)
+{
+  f (1); /* { dg-error "too many arguments to function" } */
+}
Index: gcc/testsuite/gcc.dg/c2x-old-style-definition-5.c
===================================================================
--- gcc/testsuite/gcc.dg/c2x-old-style-definition-5.c	(nonexistent)
+++ gcc/testsuite/gcc.dg/c2x-old-style-definition-5.c	(working copy)
@@ -0,0 +1,9 @@ 
+/* Test old-style function definitions not in C2x: () does not warn
+   with -Wold-style-definition.  */
+/* { dg-do compile } */
+/* { dg-options "-std=c2x -Wold-style-definition" } */
+
+void
+f ()
+{
+}
Index: gcc/testsuite/gcc.dg/c2x-old-style-definition-6.c
===================================================================
--- gcc/testsuite/gcc.dg/c2x-old-style-definition-6.c	(nonexistent)
+++ gcc/testsuite/gcc.dg/c2x-old-style-definition-6.c	(working copy)
@@ -0,0 +1,16 @@ 
+/* Test old-style function definitions not in C2x: () does not give
+   type with a prototype except for function definitions.  */
+/* { dg-do compile } */
+/* { dg-options "-std=c2x" } */
+
+void f1 ();
+
+/* Prototyped function returning a pointer to unprototyped function.  */
+void (*f2 (void))() { return f1; }
+
+void
+g (void)
+{
+  f1 (1);
+  f2 () (1);
+}