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]>
---
 gcc/c-family/c-attribs.cc            | 21 ++++++++++++++++++++-
 gcc/doc/extend.texi                  |  3 ++-
 gcc/testsuite/gcc.dg/attr-callback.c |  8 ++++++++
 3 files changed, 30 insertions(+), 2 deletions(-)

diff --git a/gcc/c-family/c-attribs.cc b/gcc/c-family/c-attribs.cc
index aecfdcda490..e6ad795949d 100644
--- a/gcc/c-family/c-attribs.cc
+++ b/gcc/c-family/c-attribs.cc
@@ -4687,6 +4687,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)
@@ -4699,7 +4708,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)
@@ -4733,6 +4742,16 @@ 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;
+      *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 225f75e7217..2b3956bd66e 100644
--- a/gcc/doc/extend.texi
+++ b/gcc/doc/extend.texi
@@ -2372,7 +2372,8 @@ 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
 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
diff --git a/gcc/testsuite/gcc.dg/attr-callback.c 
b/gcc/testsuite/gcc.dg/attr-callback.c
index 74c8287471b..3837af1b118 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;
-- 
2.55.0

Reply via email to