From: Michal Jires Date: Fri, 30 Jan 2026 15:42:48 +0000 (+0100) Subject: c,c++: Fix incorrect warning with asm defined symbols X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=fa20d1d7095122c7fc0e701b08ec383a60404bb0;p=thirdparty%2Fgcc.git c,c++: Fix incorrect warning with asm defined symbols 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. --- diff --git a/gcc/c/c-decl.cc b/gcc/c/c-decl.cc index 7dddc23b5e1..ea0eaec0bb5 100644 --- a/gcc/c/c-decl.cc +++ b/gcc/c/c-decl.cc @@ -13679,25 +13679,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)) - { - if (warning (OPT_Wunused_function, - "%q+F declared % but never defined", - decl)) - suppress_warning (decl, OPT_Wunused_function); - } + && warning (OPT_Wunused_function, + "%q+F declared % but never defined", + decl)) + suppress_warning (decl, OPT_Wunused); } wrapup_global_declaration_1 (decl); 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..b0a0061abb5 100644 --- a/gcc/cgraphunit.cc +++ b/gcc/cgraphunit.cc @@ -1111,10 +1111,13 @@ 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); - else - warning (OPT_Wunused_function, "%q+F declared % but never " - "defined", decl); + { + if (pedwarn (input_location, 0, "%q+F used but never defined", decl)) + suppress_warning (decl, OPT_Wunused); + } + else if (warning (OPT_Wunused_function, + "%q+F declared % 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 6dabf349bef..c6aac6a8779 100644 --- a/gcc/cp/decl.cc +++ b/gcc/cp/decl.cc @@ -1015,10 +1015,11 @@ 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 % but never defined", decl); + && !warning_suppressed_p (decl, OPT_Wunused) + && warning_at (DECL_SOURCE_LOCATION (decl), OPT_Wunused_function, + "%qF declared % 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 fb1be25edf5..236bc625c25 100644 --- a/gcc/cp/semantics.cc +++ b/gcc/cp/semantics.cc @@ -2495,6 +2495,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));