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