On Thu, 2026-01-22 at 13:13:36 +0100, Jakub Jelinek wrote:
> > +         walk_tree (&t, walk_through_asm_defined_symbol, NULL, NULL);
> 
> Why?
> Immediately above this there is
>               if (TREE_CODE (t) != ADDR_EXPR
>                   || !(TREE_CODE (TREE_OPERAND (t, 0)) == FUNCTION_DECL
>                        || (VAR_P (TREE_OPERAND (t, 0))
>                            && is_global_var (TREE_OPERAND (t, 0)))))
>               error
> So, why not simply add
>             else
>               TREE_ASM_WRITTEN (TREE_OPERAND (t, 0)) = 1;
> with a comment?
I wrongly assumed these are represented differently:
asm("%cc0:" :: ":"(asm_fn));
asm("%cc0:" :: ":"(&asm_fn));

> And do it for C as well and add a testcase for it into c-c++-common
> with dg-bogus?
> 
>       Jakub
> 

Thanks, following v2 is now for both C and C++.

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, so we need
to have a tree flag to mark a symbol as defined in assembly to disable
the warning.
TREE_ASM_WRITTEN seems to be usable for this purpose; written symbols
are always defined, and the symbol will be written separately by
toplevel assembly.

Tested on x86_64-pc-linux-gnu.

        PR testsuite/123559

gcc/c/ChangeLog:

        * c-decl.cc (c_write_global_declarations_1): Check asm symbols.
        * c-typeck.cc (build_asm_expr): Mark asm symbols.

gcc/ChangeLog:

        * cgraphunit.cc (check_global_declaration): Check asm symbols.

gcc/cp/ChangeLog:

        * decl.cc (wrapup_namespace_globals): Check asm symbols.
        * semantics.cc (finish_asm_stmt): Mark asm symbols.

gcc/testsuite/ChangeLog:

        * c-c++-common/toplevel-extended-asm-1.c: New test.
---
 gcc/c/c-decl.cc                                      | 4 +++-
 gcc/c/c-typeck.cc                                    | 3 +++
 gcc/cgraphunit.cc                                    | 4 +++-
 gcc/cp/decl.cc                                       | 2 ++
 gcc/cp/semantics.cc                                  | 3 +++
 gcc/testsuite/c-c++-common/toplevel-extended-asm-1.c | 5 +++++
 6 files changed, 19 insertions(+), 2 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..b2d7eeb888f 100644
--- a/gcc/c/c-decl.cc
+++ b/gcc/c/c-decl.cc
@@ -13669,7 +13669,9 @@ 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)
+         /* Symbols defined in assembly.  */
+         && !TREE_ASM_WRITTEN (decl))
        {
          if (C_DECL_USED (decl))
            {
diff --git a/gcc/c/c-typeck.cc b/gcc/c/c-typeck.cc
index 04b33111f62..a4ad8cbd34e 100644
--- a/gcc/c/c-typeck.cc
+++ b/gcc/c/c-typeck.cc
@@ -13169,6 +13169,9 @@ build_asm_expr (location_t loc, tree string, tree 
outputs, tree inputs,
                                 "of a function or non-automatic variable");
                  input = error_mark_node;
                }
+             else
+               /* Mark symbol defined in asm.  */
+               TREE_ASM_WRITTEN (TREE_OPERAND (t, 0)) = 1;
            }
        }
       else
diff --git a/gcc/cgraphunit.cc b/gcc/cgraphunit.cc
index 88c1071c8de..401e016b8ca 100644
--- a/gcc/cgraphunit.cc
+++ b/gcc/cgraphunit.cc
@@ -1106,7 +1106,9 @@ check_global_declaration (symtab_node *snode)
       && DECL_INITIAL (decl) == 0
       && DECL_EXTERNAL (decl)
       && ! DECL_ARTIFICIAL (decl)
-      && ! TREE_PUBLIC (decl))
+      && ! TREE_PUBLIC (decl)
+      /* Symbols defined in assembly.  */
+      && ! TREE_ASM_WRITTEN (decl))
     {
       if (warning_suppressed_p (decl, OPT_Wunused))
        ;
diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc
index 46a17a596ed..27244293e8d 100644
--- a/gcc/cp/decl.cc
+++ b/gcc/cp/decl.cc
@@ -1013,6 +1013,8 @@ wrapup_namespace_globals ()
              && DECL_EXTERNAL (decl)
              && !TREE_PUBLIC (decl)
              && !DECL_ARTIFICIAL (decl)
+             /* Symbols defined in assembly.  */
+             && !TREE_ASM_WRITTEN (decl)
              && !DECL_FRIEND_PSEUDO_TEMPLATE_INSTANTIATION (decl)
              && !warning_suppressed_p (decl, OPT_Wunused_function))
            warning_at (DECL_SOURCE_LOCATION (decl),
diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc
index 78d717cade3..4e3810e19e9 100644
--- a/gcc/cp/semantics.cc
+++ b/gcc/cp/semantics.cc
@@ -2492,6 +2492,9 @@ finish_asm_stmt (location_t loc, int volatile_p, tree 
string,
                                "of a function or non-automatic variable");
                      operand = error_mark_node;
                    }
+                 else
+                   /* Mark symbol defined in asm.  */
+                   TREE_ASM_WRITTEN (TREE_OPERAND (t, 0)) = 1;
                }
            }
          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