[cfe-dev] [PATCH] New syntax and functionality for __has_attribute

Aaron Ballman aaron at aaronballman.com
Sat Jan 11 12:06:45 PST 2014

On Sat, Jan 11, 2014 at 2:41 PM, dblaikie at gmail.com <dblaikie at gmail.com> wrote:
> On Sat Jan 11 2014 at 10:57:22 AM, Aaron Ballman <aaron at aaronballman.com>
> wrote:
>> On Sat, Jan 11, 2014 at 1:49 PM, dblaikie at gmail.com <dblaikie at gmail.com>
>> wrote:
>> > I'm not sure this is necessary - do any compilers (including different
>> > versions of clang itself, which I believe is the main use of
>> > has_attribute)
>> > support the same attribute but in differing syntaxes?
>> Yes, clang has numerous attributes instances of this. I believe GCC
>> does as well. For instance, it's quite common to have a GNU spelling
>> and a C++11 syntax for the same attribute. There are also cases where
>> attributes with the same spelling but different syntax provide
>> differing semantics, such as the aligned attribute (which has five
>> different syntaxes).
> Sorry, I'm not trying to be obtuse, but I'm not sure if/how that answers my
> question.

It's likely I didn't understand the question, so keep poking me until
I get it right. :-)

> What I'm asking is, is there ever a case where a compile-time check is
> required to decide which syntax to use? (where two compilers (including two
> different versions of the same compiler) have support for the same attribute
> but in disparate syntaxes?)
> The existence of an attribute with more than one, or less than all syntaxes
> is not an issue - if in every compiler that implements the attribute it is
> implemented in the same set of syntaxes, then there's no need to query which
> syntax is valid, is there? It would be a universal constant.

I may still be totally misunderstanding your concern, so I apologize
if I'm being dense. But yes, there are cases where this comes up.
Going back to my dllexport example since I think it's the most
easily-recognizable. Here's a probably example of using this code in a
cross-compiler code base:

#if __has_attribute(dllexport)
  #define DLLEXPORT __attribute__((dllexport))
  #define DLLEXPORT

void func(void) DLLEXPORT;

If you were to use this code today in clang, it would fail to compile.
 __has_attribute(dllexport) will be replaced with 1, and so the
resulting code would become: void func(void)
__attribute__((dllexport));  However, we do not support dllexport with
that syntax (we only support __declspec(dllexport)). So the code would
look reasonable, but fail to compile.

We could solve this by making __has_attribute *only* correspond to
GNU-style attributes, but that's not how it works currently, and such
a change could break existing code that currently works.

Not every compiler implements the same set of attributes, which is why
__has_attribute exists in the first place. Furthermore, not every
compiler implements a given attribute with the same set of syntaxes
(such as dllexport, which is implemented in gcc as both a GNU-style
and an MS-style attribute, but it only an MS-style attribute in
clang). Even in situations where the compiler *does* implement all of
the syntaxes consistently, it can be beneficial to know which syntax
you are referring to within the context of __has_attribute because
attribute placement is different between varying attribute syntaxes.

Does that clear things up, or am I still not understanding your concerns?

>> > Otherwise it just
>> > seems an invariant of the attribute and not something that would need
>> > compile time tests for because it won't vary by compilation
>> I strongly disagree. Consider the dllexport example I had given.
>> Supporting that is currently guess-work with __has_attribute because
>> we only respond back that the attribute is known, but not a particular
>> syntax.
> Wouldn't it be documented somewhere? Why would it need to be queried
> dynamically (at compile-time)? That would only be necessary if the attribute
> was supported with different syntaxes in different compilers. Is that the
> case?

Yes, it is the case where the attribute is supported in different
syntaxes in different compilers. That's why I keep picking on
dllexport as an example. MSVC and clang support it as
__declspec(dllexport) only, GCC supports it as __declspec(dllexport)
or __attribute__((dllexport)).


More information about the cfe-dev mailing list