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