It’s likely I didn’t understand the question, so keep poking me until
I get it right.
Let’s see how we go.
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:
#define DLLEXPORT attribute((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.
Sure - my argument here is this is /potentially/ just a lack of documentation. It’s perhaps no more relevant than having a macro that tells you whether the return type is written “ func();” or “func() void” - it’s an invariant of the language (or an invariant of the language extension, in the attribute case), not something that needs compile-time detection.
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.
I don’t think that’s necessary. If each attribute has a documented list of syntaxes/valid places, that should be sufficient.
Not every compiler implements the same set of attributes, which is why
__has_attribute exists in the first place.
Sure - I get that, I’m not questioning the motivation for __has_attribute as it stands today. I’m questioning the value of the ability to query for particular attribute syntax/spelling support that’s being added here.
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
OK - this is what I’m interested in, but on further consideration I think there’s an even stronger requirement:
For the has_feature per-syntax checking to be useful, we would have to be in a world in which two compilers (including different versions of the same compiler) support the same attribute in non-overlapping syntaxes.
Anyone trying to write portable code isn’t going to write:
#define DLLEXPORT attribute((dllexport))
#define DLLEXPORT declspec(dllexport)
They’re just going to use the common subset that all compiler support (because generally these attributes have been implemented for compatibility with other compilers, yes?), thus just preferring the MS syntax in all cases.
One difference would be that having specific syntax feature detection would allow safe fallback - if someone had written the dllexport with GCC syntax using this new feature then on Clang it would’ve silently not exported (do people actually ever want that? For some attributes there’s a logical fallback to just not use the attribute, dllexport/import doesn’t seem to be one of those - but that’s an aside) - whereas without the syntax-specific check you’d get an error and need to update the attribute syntax used in the DLLEXPORT macro to the one that’s common between GCC and Clang (& whatever else).
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.
Again, this knowledge would be gained through explicit compiler documentation (as any other language feature or language extension) - not necessarily meriting a compile-time query system.
Does that clear things up, or am I still not understanding your concerns?
We’re closer on the concerns, but I’m still not quite understanding the justification.
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
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
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)
Yep, it’s a useful example (except I’m not sure it has a logical fallback, so I’m not sure how much people would actually conditionalize/feature-detect its use - and I assume GCC’s support for multiple syntaxes is more or less by accident (I assume they support all attributes in all syntaxes just as a consequence of their implementation) & really the only one people /really/ would use would be the declspec version).