On 12/13/18 4:39 PM, Jakub Jelinek wrote:
On Thu, Dec 13, 2018 at 02:05:29PM -0700, Martin Sebor wrote:
So how is the builtin defined then?  Is the argument always an expression
and you only return whether its type has the attribute, or do something
different if the expression is of certain kind?

For a DECL the built-in looks at both the DECL_ATTRIBUTES and
the DECL's type's TYPE_ATTRIBUTES.  For expressions, it just
looks at TYPE_ATTRIBUTES of the expression's type.  I'm not
sure that this is necessarily the cleanest design but it's
meant to follow how attributes are applied to DECLs.  Sometimes
they get applied to the DECL itself and other times to its type.
This has been causing confusion to both users and GCC devs such
as myself so at some point I'd like to make this clearer somehow.
Not sure exactly how yet.

But some users of the attribute look for the attribute on TYPE_ATTRIBUTES,
other on DECL_ATTRIBUTES, and the attributes have bools which say to what
they apply.  So, I think the API need to be very clear whether the attribute
is on a decl or on a type.

If it is similar to say sizeof/__alignof__ etc., where it accepts either
a type (for which one can use __typeof/decltype etc.), in which case it
would check the type attributes, or an expression and in that case require
it to be a decl and use decl attributes, one API is fine, but supporting
arbitrary expressions and sometimes looking at type, other times at decl
or both is not a good design.

It's as good as the design of GCC attributes allows.  Based on
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));

It wouldn't if the built-in differentiated between decls and types.

Even if/when we make these function attributes (and others like it)
apply to types as I think we should so it's possible to apply them
to function pointers as users expect, there still will be others
that will apply only to the function decls.  The distinction
between when GCC chooses to apply an attribute to a function decl
vs to its type is not intuitive and cannot very well be, and neither
would be an API that queried just a decl attribute or just a type
attribute.  The most common use case is to query whether a function
has been declared with an attribute -- it doesn't matter whether
it's on its unique type or on its decl.  (The others might perhaps
be useful too, but a lot less often.)

Martin

Reply via email to