On Fri, 2026-01-30 at 15:56:56 +0100, Jakub Jelinek wrote:
>
> The question is if all those suppressions which suppress Wunused mean
> to suppress also the cgraphunit.c and C++ FE pedwarn/warning or not.
> Right now it will as they work the same, but if ever the code
> is changed to use different bits between the two, it would regress.
>
> decl2.cc- /* Suppress warning from check_global_declaration if needed.
> */
> decl2.cc- if (d)
> decl2.cc: suppress_warning (decl, OPT_Wunused);
> etc. at least in the C++ FE mean to disable the cgraphunit.cc diagnostics.
>
> So I think going for OPT_Wunused for suppress_warning/warning_suppressed_p
> would be easiest.
>
Alright, v5 is suppressing OPT_Wunused.
Michal
---
Static symbols defined in assembly cause wrong "used but never defined"
warning.
static void asm_fn();
asm("%cc0:" :: ":"(&asm_fn));
This happens in C,C++ frontends before cgraph is created where the
relevant flags are located.
We can suppress these warnings with OPT_Wunused.
C,C++ frontends and cgraphunit suppressed OPT_Wunused and
OPT_Wunused_function interchangeably, so we unify suppression to
only OPT_Wunused.
PR testsuite/123559
gcc/c/ChangeLog:
* c-decl.cc (c_write_global_declarations_1): Check and suppress
OPT_Wunused.
* c-typeck.cc (build_asm_expr): Suppress OPT_Wunused.
gcc/ChangeLog:
* cgraphunit.cc (check_global_declaration): Suppress OPT_Wunused.
gcc/cp/ChangeLog:
* decl.cc (wrapup_namespace_globals): Check and suppress OPT_Wunused.
* semantics.cc (finish_asm_stmt): Suppress OPT_Wunused.
gcc/testsuite/ChangeLog:
* c-c++-common/toplevel-extended-asm-1.c: New test.
---
gcc/c/c-decl.cc | 12 +++++-------
gcc/c/c-typeck.cc | 2 ++
gcc/cgraphunit.cc | 12 +++++++++---
gcc/cp/decl.cc | 11 +++++++----
gcc/cp/semantics.cc | 2 ++
gcc/testsuite/c-c++-common/toplevel-extended-asm-1.c | 5 +++++
6 files changed, 30 insertions(+), 14 deletions(-)
create mode 100644 gcc/testsuite/c-c++-common/toplevel-extended-asm-1.c
diff --git a/gcc/c/c-decl.cc b/gcc/c/c-decl.cc
index 7e94430435c..3be19c61ff8 100644
--- a/gcc/c/c-decl.cc
+++ b/gcc/c/c-decl.cc
@@ -13669,24 +13669,22 @@ c_write_global_declarations_1 (tree globals)
if (TREE_CODE (decl) == FUNCTION_DECL
&& DECL_INITIAL (decl) == NULL_TREE
&& DECL_EXTERNAL (decl)
- && !TREE_PUBLIC (decl))
+ && !TREE_PUBLIC (decl)
+ && !warning_suppressed_p (decl, OPT_Wunused))
{
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. */);
+ suppress_warning (decl, OPT_Wunused);
}
/* For -Wunused-function warn about unused static prototypes. */
- else if (warn_unused_function
- && ! DECL_ARTIFICIAL (decl)
- && ! warning_suppressed_p (decl, OPT_Wunused_function))
+ else if (warn_unused_function && ! DECL_ARTIFICIAL (decl))
{
if (warning (OPT_Wunused_function,
"%q+F declared %<static%> but never defined",
decl))
- suppress_warning (decl, OPT_Wunused_function);
+ suppress_warning (decl, OPT_Wunused);
}
}
diff --git a/gcc/c/c-typeck.cc b/gcc/c/c-typeck.cc
index 098a4b55339..dc803dc6388 100644
--- a/gcc/c/c-typeck.cc
+++ b/gcc/c/c-typeck.cc
@@ -13170,6 +13170,8 @@ build_asm_expr (location_t loc, tree string, tree
outputs, tree inputs,
"of a function or non-automatic variable");
input = error_mark_node;
}
+ else if (TREE_CODE (TREE_OPERAND (t, 0)) == FUNCTION_DECL)
+ suppress_warning (TREE_OPERAND (t, 0), OPT_Wunused);
}
}
else
diff --git a/gcc/cgraphunit.cc b/gcc/cgraphunit.cc
index 88c1071c8de..0c269b28758 100644
--- a/gcc/cgraphunit.cc
+++ b/gcc/cgraphunit.cc
@@ -1111,10 +1111,16 @@ check_global_declaration (symtab_node *snode)
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);
+ {
+ if (pedwarn (input_location, 0, "%q+F used but never defined", decl))
+ suppress_warning (decl, OPT_Wunused);
+ }
else
- warning (OPT_Wunused_function, "%q+F declared %<static%> but never "
- "defined", decl);
+ {
+ if (warning (OPT_Wunused_function,
+ "%q+F declared %<static%> but never defined", decl))
+ suppress_warning (decl, OPT_Wunused);
+ }
}
/* Warn about static fns or vars defined but not used. */
diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc
index 270158510df..41b965cef66 100644
--- a/gcc/cp/decl.cc
+++ b/gcc/cp/decl.cc
@@ -1015,10 +1015,13 @@ wrapup_namespace_globals ()
&& !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);
+ && !warning_suppressed_p (decl, OPT_Wunused))
+ {
+ if (warning_at (DECL_SOURCE_LOCATION (decl), OPT_Wunused_function,
+ "%qF declared %<static%> but never defined",
+ decl))
+ suppress_warning (decl, OPT_Wunused);
+ }
if (VAR_P (decl)
&& DECL_EXTERNAL (decl)
diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc
index 35bc48e49dc..f3c9227b7c0 100644
--- a/gcc/cp/semantics.cc
+++ b/gcc/cp/semantics.cc
@@ -2494,6 +2494,8 @@ finish_asm_stmt (location_t loc, int volatile_p, tree
string,
"of a function or non-automatic variable");
operand = error_mark_node;
}
+ else if (TREE_CODE (TREE_OPERAND (t, 0)) == FUNCTION_DECL)
+ suppress_warning (TREE_OPERAND (t, 0), OPT_Wunused);
}
}
else
diff --git a/gcc/testsuite/c-c++-common/toplevel-extended-asm-1.c
b/gcc/testsuite/c-c++-common/toplevel-extended-asm-1.c
new file mode 100644
index 00000000000..531c9423165
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/toplevel-extended-asm-1.c
@@ -0,0 +1,5 @@
+/* { dg-do compile } */
+/* { dg-options "-Wall" } */
+
+static void asm_fn(); /* { dg-bogus "but never defined" } */
+asm("%cc0:" :: ":"(&asm_fn));
--
2.52.0