On Fri, Jan 30, 2026 at 09:41:32AM +0100, Michal Jires wrote:
> On Thu, 2026-01-29 at 17:14:46 +0100, Jakub Jelinek wrote:
> > On Thu, Jan 29, 2026 at 05:12:08PM +0100, Michal Jires wrote:
> > > That would work for C++ frontend, but the C frontend does not check
> > > suppresed warnings for "used but never defined".
> > 
> > Then the C FE should honor that too.
> > 
> > > Which I presume would change warnings with some inputs.
> > > But if that would not be an issue, your solutions seems better.
> > 
> > It is not an issue.  If something has suppressed the warning, it has done
> > that for a reason.
> > 
> >     Jakub
> > 
> 
> Great, then this should be ok?

Sorry, I haven't studied all the code in detail.
So, we have in cgraphunit.cc
  if (TREE_CODE (decl) == FUNCTION_DECL
      && DECL_INITIAL (decl) == 0
      && DECL_EXTERNAL (decl)
      && ! DECL_ARTIFICIAL (decl)
      && ! TREE_PUBLIC (decl))
    {
      if (warning_suppressed_p (decl, OPT_Wunused))
        ;
      else if (snode->referred_to_p (/*include_self=*/false))
        pedwarn (input_location, 0, "%q+F used but never defined", decl);
      else
        warning (OPT_Wunused_function, "%q+F declared %<static%> but never "
                                       "defined", decl);
    }
and in c/c-decl.cc
      /* Check for used but undefined static functions using the C
         standard's definition of "used", and set TREE_NO_WARNING so
         that check_global_declaration doesn't repeat the check.  */
      if (TREE_CODE (decl) == FUNCTION_DECL
          && DECL_INITIAL (decl) == NULL_TREE
          && DECL_EXTERNAL (decl)
          && !TREE_PUBLIC (decl))
        {
          if (C_DECL_USED (decl))
            {
              /* TODO: Add OPT_Wundefined-inline.  */
              if (pedwarn (input_location, 0, "%q+F used but never defined",
                           decl))
                suppress_warning (decl /* OPT_Wundefined-inline.  */);
            }
          /* For -Wunused-function warn about unused static prototypes.  */
          else if (warn_unused_function
                   && ! DECL_ARTIFICIAL (decl)
                   && ! warning_suppressed_p (decl, OPT_Wunused_function))
            {
              if (warning (OPT_Wunused_function,
                           "%q+F declared %<static%> but never defined",
                           decl))
                suppress_warning (decl, OPT_Wunused_function);
            }
        }
and in cp/decl.cc
          if (warn_unused_function
              && TREE_CODE (decl) == FUNCTION_DECL
              && DECL_INITIAL (decl) == 0
              && DECL_EXTERNAL (decl)
              && !TREE_PUBLIC (decl)
              && !DECL_ARTIFICIAL (decl)
              && !DECL_FRIEND_PSEUDO_TEMPLATE_INSTANTIATION (decl)
              && !warning_suppressed_p (decl, OPT_Wunused_function))
            warning_at (DECL_SOURCE_LOCATION (decl),
                        OPT_Wunused_function,
                        "%qF declared %<static%> but never defined", decl);
and then tons of spots which do suppress_warning (decl, OPT_Wunused); but
except for the above one none that do suppress_warning (decl,
OPT_Wunused_function);
The first question is why Martin S. made up OPT_Wudefined-inline, that makes
no sense, the pedwarn is about any undefined functions, not just inline.

Given the number of OPT_Wunused suppressions:
it grep suppress_warning.*Wunused[^_] .
gcc/c/c-decl.cc:      suppress_warning (olddecl, OPT_Wunused);
gcc/c/c-typeck.cc:      suppress_warning (last, OPT_Wunused);
gcc/cp/call.cc:   suppress_warning (val, OPT_Wunused);
gcc/cp/call.cc:          suppress_warning (val, OPT_Wunused);
gcc/cp/decl2.cc:        suppress_warning (decl, OPT_Wunused);
gcc/cp/decl2.cc:            suppress_warning (decl, OPT_Wunused);
gcc/cp/decl2.cc:        suppress_warning (decl, OPT_Wunused);
gcc/cp/pt.cc:      suppress_warning (decl, OPT_Wunused);
gcc/cp/pt.cc:   suppress_warning (clone, OPT_Wunused);
gcc/cp/tree.cc:    suppress_warning (TYPE_SIZE (t), OPT_Wunused);
gcc/objc/objc-act.cc:      suppress_warning (compound_expr, OPT_Wunused);
gcc/objc/objc-act.cc:  suppress_warning (compound_expr, OPT_Wunused);
gcc/rust/backend/rust-tree.cc:    suppress_warning (TYPE_SIZE (t), OPT_Wunused);
and because cgraphunit.cc uses it I'd think we probably should honor and use 
that
suppression, at least to guard the C pedwarn, and probably suppress both
OPT_Wunused and OPT_Wunused_function in the C/C++ asm handling.
So
-              /* TODO: Add OPT_Wundefined-inline.  */
-              if (pedwarn (input_location, 0, "%q+F used but never defined",
-                           decl))
-                suppress_warning (decl /* OPT_Wundefined-inline.  */);
+              if (!warning_suppressed_p (decl, OPT_Wunused)
+                  && pedwarn (input_location, 0, "%q+F used but never defined",
+                              decl))
+                suppress_warning (decl, OPT_Wunused);
and
+           else if (TREE_CODE (TREE_OPERAND (t, 0)) == FUNCTION_DECL)
+             {
+               suppress_warning (TREE_OPERAND (t, 0), OPT_Wunused);
+               suppress_warning (TREE_OPERAND (t, 0), OPT_Wunused_function);
+             }
Or similarly to cgraphunit.cc use warning_suppressed_p (decl, OPT_Wunused)
to guard both the pedwarn and warn_unused_function and use it in C++ FE too
and suppress_warning (decl, OPT_Wunused); instead of OPT_Wunused_function.

Note, -Wunused warning enables -Wunused-function by default, but one can
use -Wunused -Wno-unused-function or -Wno-unused -Wunused-function and the
warning suppression code isn't aware of that relationship and just records
the particular OPT_* value it is called with.
And, if we want to make the code even better, both in the cgraphunit.cc
and cp/decl.cc and for the pedwarn in c/c-decl.cc use
  if ({pedwarn,warning,warning_at} (...))
    suppress_warning (decl, OPT_Wunused);

        Jakub

Reply via email to