https://gcc.gnu.org/g:701d8e7e60b85809cae348c1e9edb3b0f4924325

commit r15-5369-g701d8e7e60b85809cae348c1e9edb3b0f4924325
Author: Florian Weimer <fwei...@redhat.com>
Date:   Sun Nov 17 19:42:33 2024 +0100

    c: Implement -Wdeprecated-non-prototype
    
    This warning covers the C23 incompibilities resulting from using
    () as parameter lists in function declarations.
    
    The warning name comes from Clang.  The implementation is not
    perfect because GCC treats these two declarations as equivalent:
    
      void f ();
      void f (not_a_type);
    
    This is a bit confusing because they are clearly visually distinct.
    However, as of GCC 14, the second form is an error by default, so
    treating both the same as far as  -Wdeprecated-non-prototype does
    not seem so bad from a user experience view.
    
    gcc/c-family/
    
            PR c/95445
            * c-opts.cc (c_common_post_options): Initialize
            warn_deprecated_non_prototype.
            * c.opt (Wdeprecated-non-prototype): New option.
            * c.opt.urls: Regenerate.
    
    gcc/c/
    
            PR c/95445
            * c-decl.cc (start_function): Warn about parameters
            after parameter-less declaration.
            * c-typeck.cc (build_function_call_vec): Pass fntype
            to convert_arguments.
            (convert_arguments): Change argument to fntype and
            compute typelist.  Warn about parameter list mismatches
            on first parameter.
    
    gcc/
    
            PR c/95445
            * doc/invoke.texi: Document -Wdeprecated-non-prototype.
    
    gcc/testsuite/
    
            PR c/95445
            * gcc.dg/Wdeprecated-non-prototype-1.c: New test.
            * gcc.dg/Wdeprecated-non-prototype-2.c: New test.
            * gcc.dg/Wdeprecated-non-prototype-3.c: New test.
            * gcc.dg/Wdeprecated-non-prototype-4.c: New test.

Diff:
---
 gcc/c-family/c-opts.cc                             |  3 +++
 gcc/c-family/c.opt                                 |  4 ++++
 gcc/c-family/c.opt.urls                            |  3 +++
 gcc/c/c-decl.cc                                    | 18 +++++++++++++++
 gcc/c/c-typeck.cc                                  | 26 ++++++++++++++++++----
 gcc/doc/invoke.texi                                | 12 +++++++++-
 gcc/testsuite/gcc.dg/Wdeprecated-non-prototype-1.c | 24 ++++++++++++++++++++
 gcc/testsuite/gcc.dg/Wdeprecated-non-prototype-2.c | 22 ++++++++++++++++++
 gcc/testsuite/gcc.dg/Wdeprecated-non-prototype-3.c | 18 +++++++++++++++
 gcc/testsuite/gcc.dg/Wdeprecated-non-prototype-4.c | 22 ++++++++++++++++++
 10 files changed, 147 insertions(+), 5 deletions(-)

diff --git a/gcc/c-family/c-opts.cc b/gcc/c-family/c-opts.cc
index f66a0a0ca888..3a3464ccc3f2 100644
--- a/gcc/c-family/c-opts.cc
+++ b/gcc/c-family/c-opts.cc
@@ -1006,6 +1006,9 @@ c_common_post_options (const char **pfilename)
       = ((pedantic && !flag_isoc23 && warn_c11_c23_compat != 0)
         || warn_c11_c23_compat > 0);
 
+  if (warn_deprecated_non_prototype == -1)
+    warn_deprecated_non_prototype = warn_c11_c23_compat > 0;
+
   /* -Wshift-negative-value is enabled by -Wextra in C99 and C++11 to C++17
      modes.  */
   if (warn_shift_negative_value == -1)
diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt
index 8224c82bfdf8..220421accf47 100644
--- a/gcc/c-family/c.opt
+++ b/gcc/c-family/c.opt
@@ -668,6 +668,10 @@ Wdeprecated-literal-operator
 C++ ObjC++ Var(warn_deprecated_literal_operator) Warning
 Warn about deprecated space between "" and suffix in a user-defined literal 
operator.
 
+Wdeprecated-non-prototype
+C ObjC Var(warn_deprecated_non_prototype) Init(-1) Warning
+Warn about calls with arguments to functions declared without parameters.
+
 Wdesignated-init
 C ObjC Var(warn_designated_init) Init(1) Warning
 Warn about positional initialization of structs requiring designated 
initializers.
diff --git a/gcc/c-family/c.opt.urls b/gcc/c-family/c.opt.urls
index 04f8e2ee0087..91918c492047 100644
--- a/gcc/c-family/c.opt.urls
+++ b/gcc/c-family/c.opt.urls
@@ -307,6 +307,9 @@ 
UrlSuffix(gcc/C_002b_002b-Dialect-Options.html#index-Wdeprecated-enum-float-conv
 Wdeprecated-literal-operator
 
UrlSuffix(gcc/C_002b_002b-Dialect-Options.html#index-Wdeprecated-literal-operator)
 
+Wdeprecated-non-prototype
+UrlSuffix(gcc/Warning-Options.html#index-Wdeprecated-non-prototype)
+
 Wdesignated-init
 UrlSuffix(gcc/Warning-Options.html#index-Wdesignated-init)
 
diff --git a/gcc/c/c-decl.cc b/gcc/c/c-decl.cc
index 7e65bd04b11e..1128d72ccb03 100644
--- a/gcc/c/c-decl.cc
+++ b/gcc/c/c-decl.cc
@@ -10750,6 +10750,24 @@ start_function (struct c_declspecs *declspecs, struct 
c_declarator *declarator,
        }
     }
 
+  /* Optionally warn about C23 compatibility.  */
+  if (warn_deprecated_non_prototype
+      && old_decl != NULL_TREE
+      && TREE_CODE (oldtype) == FUNCTION_TYPE
+      && !TYPE_ARG_TYPES (oldtype)
+      && !TYPE_NO_NAMED_ARGS_STDARG_P (oldtype)
+      && (TYPE_ARG_TYPES (newtype)
+         && TREE_VALUE (TYPE_ARG_TYPES (newtype)) != void_type_node))
+    {
+      bool warned = warning_at (loc, OPT_Wdeprecated_non_prototype,
+                               "ISO C23 does not allow defining"
+                               " parameters for function %qE declared"
+                               " without parameters",
+                               decl1);
+      if (warned)
+       inform (DECL_SOURCE_LOCATION (old_decl), "declared here");
+    }
+
   /* Optionally warn of old-fashioned def with no previous prototype.  */
   if (warn_strict_prototypes
       && old_decl != error_mark_node
diff --git a/gcc/c/c-typeck.cc b/gcc/c/c-typeck.cc
index 9212a8ebc0a9..26ee0ebf91f0 100644
--- a/gcc/c/c-typeck.cc
+++ b/gcc/c/c-typeck.cc
@@ -3813,7 +3813,7 @@ build_function_call_vec (location_t loc, vec<location_t> 
arg_loc,
   /* Convert the parameters to the types declared in the
      function prototype, or apply default promotions.  */
 
-  nargs = convert_arguments (loc, arg_loc, TYPE_ARG_TYPES (fntype), params,
+  nargs = convert_arguments (loc, arg_loc, fntype, params,
                             origtypes, function, fundecl);
   if (nargs < 0)
     return error_mark_node;
@@ -4108,9 +4108,9 @@ convert_argument (location_t ploc, tree function, tree 
fundecl,
 }
 
 /* Convert the argument expressions in the vector VALUES
-   to the types in the list TYPELIST.
+   to the types in the list TYPE_ARG_TYPES (FNTYPE).
 
-   If TYPELIST is exhausted, or when an element has NULL as its type,
+   If the list is exhausted, or when an element has NULL as its type,
    perform the default conversions.
 
    ORIGTYPES is the original types of the expressions in VALUES.  This
@@ -4129,10 +4129,11 @@ convert_argument (location_t ploc, tree function, tree 
fundecl,
    failure.  */
 
 static int
-convert_arguments (location_t loc, vec<location_t> arg_loc, tree typelist,
+convert_arguments (location_t loc, vec<location_t> arg_loc, tree fntype,
                   vec<tree, va_gc> *values, vec<tree, va_gc> *origtypes,
                   tree function, tree fundecl)
 {
+  tree typelist = TYPE_ARG_TYPES (fntype);
   unsigned int parmnum;
   bool error_args = false;
   const bool type_generic = fundecl
@@ -4265,6 +4266,23 @@ convert_arguments (location_t loc, vec<location_t> 
arg_loc, tree typelist,
          builtin_typetail = NULL_TREE;
        }
 
+      if (!typetail && parmnum == 0 && !TYPE_NO_NAMED_ARGS_STDARG_P (fntype))
+       {
+         bool warned;
+         if (selector)
+           warned = warning_at (loc, OPT_Wdeprecated_non_prototype,
+                                "ISO C23 does not allow arguments"
+                                " for method %qE declared without parameters",
+                                function);
+         else
+           warned = warning_at (loc, OPT_Wdeprecated_non_prototype,
+                                "ISO C23 does not allow arguments"
+                                " for function %qE declared without 
parameters",
+                                function);
+         if (warned)
+           inform_declaration (fundecl);
+       }
+
       if (selector && argnum > 2)
        {
          rname = selector;
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 8aeccb1953a7..c73025e2d0ec 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -520,7 +520,7 @@ Objective-C and Objective-C++ Dialects}.
 }
 
 @item C and Objective-C-only Warning Options
-@gccoptlist{-Wbad-function-cast -Wmissing-declarations
+@gccoptlist{-Wbad-function-cast -Wdeprecated-non-prototype 
-Wmissing-declarations
 -Wmissing-parameter-name -Wmissing-parameter-type
 -Wdeclaration-missing-parameter-type -Wmissing-prototypes
 -Wmissing-variable-declarations -Wnested-externs -Wold-style-declaration
@@ -10050,6 +10050,16 @@ is not considered an old-style definition in C23 mode, 
because it is
 equivalent to @samp{(void)} in that case, but is considered an
 old-style definition for older standards.
 
+@opindex Wdeprecated-non-prototype
+@opindex Wno-deprecated-non-prototype
+@item -Wdeprecated-non-prototype @r{(C and Objective-C only)}
+Warn if a function declarated with an empty parameter list @samp{()} is
+called with one or more arguments, or if a function definition with one
+or more parameters is encountered after such a declaration.  Both cases
+are errors in C23 and later dialects  of C.
+
+This warning is also enabled by @option{-Wc11-c23-compat}.
+
 @opindex Wmissing-parameter-name
 @opindex Wno-missing-parameter-name
 @item -Wmissing-parameter-name @r{(C and Objective-C only)}
diff --git a/gcc/testsuite/gcc.dg/Wdeprecated-non-prototype-1.c 
b/gcc/testsuite/gcc.dg/Wdeprecated-non-prototype-1.c
new file mode 100644
index 000000000000..2be88a3bcbe4
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Wdeprecated-non-prototype-1.c
@@ -0,0 +1,24 @@
+/* { dg-do compile } */
+/* { dg-options "-std=gnu17 -Wdeprecated-non-prototype" } */
+
+void f1 ();
+void f2 (); /* { dg-note "declared here" } */
+void f3 (...);
+
+void
+g ()
+{
+  f1 ();
+  f2 (1); /* { dg-warning "does not allow arguments for function" } */
+  f3 (1);
+}
+
+void
+f1 ()
+{
+}
+
+void
+f2 (int i) /* { dg-warning "does not allow defining parameters for function" } 
*/
+{
+}
diff --git a/gcc/testsuite/gcc.dg/Wdeprecated-non-prototype-2.c 
b/gcc/testsuite/gcc.dg/Wdeprecated-non-prototype-2.c
new file mode 100644
index 000000000000..0503ab29c756
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Wdeprecated-non-prototype-2.c
@@ -0,0 +1,22 @@
+/* { dg-do compile } */
+/* { dg-options "-std=gnu17 -Wc11-c23-compat" } */
+
+void f1 ();
+void f2 (); /* { dg-note "declared here" } */
+
+void
+g ()
+{
+  f1 ();
+  f2 (1); /* { dg-warning "does not allow arguments for function" } */
+}
+
+void
+f1 ()
+{
+}
+
+void
+f2 (int i) /* { dg-warning "does not allow defining parameters for function" } 
*/
+{
+}
diff --git a/gcc/testsuite/gcc.dg/Wdeprecated-non-prototype-3.c 
b/gcc/testsuite/gcc.dg/Wdeprecated-non-prototype-3.c
new file mode 100644
index 000000000000..82929a3b996e
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Wdeprecated-non-prototype-3.c
@@ -0,0 +1,18 @@
+/* { dg-do compile } */
+/* { dg-options "-std=gnu17 -Wdeprecated-non-prototype 
-Wno-declaration-missing-parameter-type" } */
+
+void f1 (not_a_type); /* { dg-note "declared here" } */
+void f2 (not_a_type); /* { dg-note "declared here" } */
+
+void
+g ()
+{
+  /* This is not ideal, but the GCC type system does not capture the number of
+     arguments in a non-prototype function declaration.  */
+  f1 (1); /* { dg-warning "does not allow arguments for function" } */
+}
+
+void
+f2 (int not_a_type) /* { dg-warning "does not allow defining parameters" } */
+{
+}
diff --git a/gcc/testsuite/gcc.dg/Wdeprecated-non-prototype-4.c 
b/gcc/testsuite/gcc.dg/Wdeprecated-non-prototype-4.c
new file mode 100644
index 000000000000..bb4b9166b258
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Wdeprecated-non-prototype-4.c
@@ -0,0 +1,22 @@
+/* { dg-do compile } */
+/* { dg-options "-std=gnu17 -Wc11-c23-compat -Wno-deprecated-non-prototype" } 
*/
+
+void f1 ();
+void f2 ();
+
+void
+g ()
+{
+  f1 ();
+  f2 (1);
+}
+
+void
+f1 ()
+{
+}
+
+void
+f2 (int i)
+{
+}

Reply via email to