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?

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 in frontends with OPT_Wunused_function.
C frontend in c_write_global_declarations_1 ignored the suppression
before, so we need to change that as well.

Tested on x86_64-pc-linux-gnu.

        PR testsuite/123559

gcc/c/ChangeLog:

        * c-decl.cc (c_write_global_declarations_1): Check OPT_Wunused_function
        suppression for "used but never defined" warning.
        * c-typeck.cc (build_asm_expr): Suppress OPT_Wunused_function.

gcc/cp/ChangeLog:

        * semantics.cc (finish_asm_stmt): Suppress OPT_Wunused_function.

gcc/testsuite/ChangeLog:

        * c-c++-common/toplevel-extended-asm-1.c: New test.
---
 gcc/c/c-decl.cc                                      | 7 +++----
 gcc/c/c-typeck.cc                                    | 2 ++
 gcc/cp/semantics.cc                                  | 3 +++
 gcc/testsuite/c-c++-common/toplevel-extended-asm-1.c | 5 +++++
 4 files changed, 13 insertions(+), 4 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..f3c157887c3 100644
--- a/gcc/c/c-decl.cc
+++ b/gcc/c/c-decl.cc
@@ -13669,7 +13669,8 @@ 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_function))
        {
          if (C_DECL_USED (decl))
            {
@@ -13679,9 +13680,7 @@ c_write_global_declarations_1 (tree globals)
                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))
+         else if (warn_unused_function && ! DECL_ARTIFICIAL (decl))
            {
              if (warning (OPT_Wunused_function,
                           "%q+F declared %<static%> but never defined",
diff --git a/gcc/c/c-typeck.cc b/gcc/c/c-typeck.cc
index 098a4b55339..62b8078726e 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_function);
            }
        }
       else
diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc
index 35bc48e49dc..09a29f7040a 100644
--- a/gcc/cp/semantics.cc
+++ b/gcc/cp/semantics.cc
@@ -2494,6 +2494,9 @@ 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_function);
                }
            }
          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

Reply via email to