the manual a function declaration like
__attribute__ ((alloc_size (1), malloc))
void* allocate (unsigned);
should have those two attributes applied to it. Yet, alloc_size
is actually applied to its type (but not to its decl) while malloc
to the function's decl but not its type (bug 88397).
I'm pretty sure most users still expect the following to pass:
_Static_assert (__builtin_has_attribute (allocate, alloc_size));
_Static_assert (__builtin_has_attribute (allocate, malloc));
Users shouldn't expect this. If anything, we should document what
attributes are type attributes and which attributes are declaration
attributes.
I designed the built-in based on what I expect.
The programs that care about whether a function is declared,
say with attribute alloc_align or malloc, do not and should
not have to worry about whether the attribute is on the decl
or on its type -- in the expected use cases it makes no
difference. Those that might care whether an attribute is
on the type can easily check the type:
__builtin_has_attribute (__typeof__ (allocate), alloc_size)
(I would expect GCC to apply an attribute either to a decl or
to a type but not to both.)
I do agree that whether an attribute applies to a function or
its type should be reviewed and where it makes sense documented.
More than that, some attributes that currently only apply to
function decls should be changed to apply to (function) types
instead so that calls via pointers to such functions can get
the same benefits as calls to the functions themselves. Malloc
is an example (bug 88397).
With the way you're proposing, users could check the type attributes
simply through __typeof/decltype etc., but couldn't test solely the
declaration attributes.
I'm not proposing anything -- what I described is the design.
I don't know of a use case for testing the decl alone for
attributes. In all those I can think of, what matters is
the union of attributes between the decl and its type.
But I'm not opposed to enhancing the function if an important
use case does turn up that's not supported. For what you are
asking for this should already do it so I don't see a need to
change anything:
#define decl_has_attribute(d, ...) \
(__builtin_has_attribute (d, __VA_ARGS__) \
&& !__builtin_has_attribute (__typeof__ (d), __VA_ARGS__))
Martin