https://gcc.gnu.org/g:4b0865a0562575358c93edac3d7c20a10422c628

commit r17-3896-g4b0865a0562575358c93edac3d7c20a10422c628
Author: Josef Melcr <[email protected]>
Date:   Mon Aug 10 16:56:32 2026 +0200

    Reject variadic functions in callback_only attribute handler
    
    The attribute's implementation and handler assume that the described
    functions are not variadic.  However, there were no checks for this in
    the attribute handler.  That wasn't a major issue since the attribute
    wasn't available to users, but that is no longer the case.  This patch
    adds the missing checks and documentation.
    
    gcc/c-family/ChangeLog:
    
            * c-attribs.cc (handle_callback_only_attribute): Reject variadic
            dispatching or callback functions.
    
    gcc/ChangeLog:
    
            * doc/extend.texi: Add a line saying variadic functions are
            unsupported to the callback_only description.
    
    gcc/testsuite/ChangeLog:
    
            * gcc.dg/attr-callback.c: Add testcases for variadic functions.
    
    Signed-off-by: Josef Melcr <[email protected]>

Diff:
---
 gcc/c-family/c-attribs.cc            | 20 +++++++++++++++++++-
 gcc/doc/extend.texi                  | 21 +++++++++++----------
 gcc/testsuite/gcc.dg/attr-callback.c |  8 ++++++++
 3 files changed, 38 insertions(+), 11 deletions(-)

diff --git a/gcc/c-family/c-attribs.cc b/gcc/c-family/c-attribs.cc
index b3d5407ec0b3..9e1fdc8087d9 100644
--- a/gcc/c-family/c-attribs.cc
+++ b/gcc/c-family/c-attribs.cc
@@ -4692,6 +4692,15 @@ handle_callback_only_attribute (tree *node, tree name, 
tree args,
       *no_add_attrs = true;
     }
 
+  tree decl_type = TREE_TYPE (decl);
+  if (stdarg_p (decl_type))
+    {
+      warning_at (DECL_SOURCE_LOCATION (decl), OPT_Wattributes,
+                 "%qE attribute cannot be used on variadic functions", name);
+      *no_add_attrs = true;
+      return NULL_TREE;
+    }
+
   tree val = positional_argument (decl, name, TREE_VALUE (args), POINTER_TYPE,
                                  1, POSARG_ZERO);
   if (!val)
@@ -4704,7 +4713,7 @@ handle_callback_only_attribute (tree *node, tree name, 
tree args,
   /* We have to use the function type for validation, as
      DECL_ARGUMENTS returns NULL at this point.  */
   int callback_fn_idx = TREE_INT_CST_LOW (val);
-  tree decl_type_args = TYPE_ARG_TYPES (TREE_TYPE (decl));
+  tree decl_type_args = TYPE_ARG_TYPES (decl_type);
   tree it;
   for (it = decl_type_args; it != NULL_TREE; it = TREE_CHAIN (it))
     if (it == void_list_node)
@@ -4738,6 +4747,15 @@ handle_callback_only_attribute (tree *node, tree name, 
tree args,
     }
 
   tree type_args = TYPE_ARG_TYPES (cfn_pointee_type);
+
+  if (stdarg_p (cfn_pointee_type))
+    {
+      warning_at (DECL_SOURCE_LOCATION (decl), OPT_Wattributes,
+                 "%qE callback function cannot be variadic", name);
+      *no_add_attrs = true;
+      return NULL_TREE;
+    }
+
   /* Compare the length of the list of argument indices
      and the real number of parameters the callback takes.  */
   unsigned cfn_nargs = list_length (TREE_CHAIN (args));
diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi
index a4981eb0debd..a9e4dfd5616d 100644
--- a/gcc/doc/extend.texi
+++ b/gcc/doc/extend.texi
@@ -2358,30 +2358,31 @@ may be silently skipped when generating BTF.
 @cindex functions with callbacks
 @item callback_only
 The @code{callback_only} attribute specifies that the annotated function may
-call the specified callback function. The first parameter identifies the index
+call the specified callback function.  The first parameter identifies the index
 of the callback function, the rest of the arguments specify the indices of the
-arguments of the indirect call. All indices start from 1. If the function takes
+arguments of the indirect call.  All indices start from 1.  If the function 
takes
 the implicit @code{this} pointer, it is referred to by the index 1, with the
-rest of the arguments starting at index 2. The index 0 marks an argument not
+rest of the arguments starting at index 2.  The index 0 marks an argument not
 present in the arguments of the annotated function, an argument which is
-modified before calling the callback function. The annotated function must pass
+modified before calling the callback function.  The annotated function must 
pass
 the specified arguments in the specified order to the callback function, which
-must be callable with the number, order and type of the arguments. The
+must be callable with the number, order and type of the arguments.  The
 specified pointer to the callback may not escape the translation unit of the
-annotated function and it may not be captured. The annotated function is
+annotated function and it may not be captured.  The annotated function is
 required to pass the arguments through, it may not change or dereference them.
-The arguments also may not escape. The attribute may be used multiple times per
+The arguments also may not escape.  The attribute may be used multiple times 
per
 function, though only one @code{callback_only} attribute may be used per
-function parameter.
+function parameter.  Neither the dispatching function nor the callback function
+may be variadic.
 
 The attribute exposes the potentially hidden callsite in the annotated
 function, enabling interprocedural optimizations which may not be possible
-without the attribute. It is most useful for annotating functions from
+without the attribute.  It is most useful for annotating functions from
 dynamically linked libraries, as their bodies are not available during
 compilation.
 
 This attribute is similar to the clang @code{callback} attribute but it is not
-compatible with it. The clang implementation allows identifiers as arguments,
+compatible with it.  The clang implementation allows identifiers as arguments,
 marks an unknown argument with -1 and the @code{this} pointer with the index 0.
 
 An example usage:
diff --git a/gcc/testsuite/gcc.dg/attr-callback.c 
b/gcc/testsuite/gcc.dg/attr-callback.c
index 74c8287471bd..3837af1b1188 100755
--- a/gcc/testsuite/gcc.dg/attr-callback.c
+++ b/gcc/testsuite/gcc.dg/attr-callback.c
@@ -67,6 +67,14 @@ unknown_fn(char (*)(float*, double*), float*, double*, 
int*); /* { dg-warning "c
 void
 not_a_fn(int, int); /* { dg-warning "refers to" } */
 
+[[gnu::callback_only(1, 2)]]
+void
+vararg_1(void (*)(int*), int*, ...); /* { dg-warning "cannot be used on 
variadic functions" } */
+
+[[gnu::callback_only(1, 2)]]
+void
+vararg_2(void (*)(int*, ...), int*); /* { dg-warning "callback function cannot 
be variadic" } */
+
 struct S
 {
   int x;

Reply via email to