C++ Logo

SG10

Advanced search

Subject: Re: [SG10] On __has_attribute
From: Aaron Ballman (aaron_at_[hidden])
Date: 2014-08-15 08:00:18


On Thu, Mar 27, 2014 at 4:22 PM, Aaron Ballman <aaron_at_[hidden]> wrote:
>> Last Monday we discussed the idea of adding an extensible mechanism to
>> detect the presence of an attribute to SG10's recommendations, based on
>> Clang's __has_attribute feature. Two important observations:
>>
>> 1) Implementations have attribute syntaxes other than C++ attributes (both
>> for historical reasons and as an ongoing concern to support attributes in
>> C), and
>> 2) We need a mechanism to determine whether the attribute-detection feature
>> is available.
>>
>> Point (1) implies that we should not reserve the global name
>> __has_attribute for *only* C++ attributes, so we considered the idea of a
>> macro that takes the syntactic form of the attribute as an argument,
>> leading us to:
>>
>>
>> Option A:
>> ---------
>>
>> __has_attribute([[deprecated]])
>> __has_attribute(__attribute__((some_gnu_thing)))
>> __has_attribute(__declspec(foobar))
>> __has_attribute([clsid])
>>
>> The natural way to address (2) with this model is to use a preprocessor
>> defined(__has_attribute) check, matching our recommendation for
>> __has_include. However, this presents a problem: that check will succeed
>> for existing versions of Clang, but existing versions of Clang do not
>> support an attribute-syntax argument to __has_attribute (only the name of a
>> GNU __attribute__).
>>
>> So, Option A would need to use either a feature-test macro (maybe
>> __cpp_has_attribute), or a different macro name (maybe
>> __has_attribute_syntax), in order to provide a way to portably check for
>> the feature.
>>
>>
>> Option B:
>> ---------
>>
>> A simpler approach would be to acknowledge point (1) in the macro name,
>> giving:
>>
>> __has_cpp_attribute ( attribute-token )
>>
>> Programs would test for the existence of this feature in the preprocessor
>> with defined(__has_cpp_attribute), consistent with how they would check for
>> __has_include. Vendors could choose to augment this with
>> __has_gnu_attribute, __has_declspec_attribute, ... for the other syntaxes.
>>
>>
>> At this point, I think Option B is superior to Option A. Therefore, my
>> first draft of a suggested addition to our recommendations is the following:
>
> I agree that Option B is preferable.
>
>>
>>
>> Testing for the presence of an attribute: __has_cpp_attribute
>>
>> [some introductory text]
>>
>> *Syntax*
>>
>> *has-attribute-expression:*
>> __has_cpp_attribute ( *attribute-scoped-token* )
>>
>> *Semantics*
>>
>> A *has-attribute-expression* shall appear only in the controlling constant
>> expression of a #if or #elif directive ([cpp.cond] 16.1). The
>> *has-attribute-expression* is replaced by the pp-number 1 if the
>> implementation supports an attribute with the specified name, and by the
>> p-number 0 otherwise.
>
> Do we want to consider any ideas for attribute versioning? For
> instance, say there was a desire to allow [[noreturn]] on a lambda.
> With this proposal, there's no way to differentiate between versions
> of the [[noreturn]] attribute. We could use a feature test macro, but
> that's what this proposal really is.
>
> We could support this by changing the pp-number replacement (0 means
> not found, > 0 supported, but you could check the constant value to
> see what version is supported).

Gently pinging this.

Note: if it's a door we wish to leave open for the future, we could
accomplish this with a minor wording modification to what we have
already. Something like:

The has-attribute-expression is replaced by <del>the pp-number
1</del><ins>a nonzero pp-number</ins> if the implementation supports
an attribute with the specified name, and by the pp-number 0
otherwise.

>
>>
>> The #ifdef and #ifndef directives, and the defined conditional inclusion
>> operator, shall treat __has_cpp_attribute as if it were the name of a
>> defined macro. The identifier __has_cpp_attribute shall not appear in any
>> context not mentioned in this section.
>>
>> An implementation should only claim to support an *attribute-token* with no
>> *attribute-namespace* if it follows the behavior specified by a draft of
>> the C++ standard or of a technical specification produced by ISO/IEC
>> JTC1/SC22/WG21. An implementation should only claim to support an
>> *attribute-token* with an *attribute-namespace* if it follows the behavior
>> specified by the vendor identified by the *attribute-namespace*.
>>
>> [OPEN QUESTION: Do we want to provide recommendations like this last
>> paragraph at all? If so, should we list the currently-know
>> attribute-namespaces? Having a centralized list of them is useful, and this
>> seems like a good place to maintain that list. Would it be in-scope for the
>> features SG to maintain a list of the known vendor extension attributes?]
>
> I agree that this paragraph can go.
>
>>
>> *Example*
>>
>> This demonstrates a way to use the attribute [[deprecated]] only if it is
>> available.
>>
>> #ifdef __has_cpp_attribute
>> # if __has_cpp_attribute(deprecated)
>> # define ATTR_DEPRECATED(msg) [[deprecated(msg)]]
>> # endif
>> #endif
>
> ~Aaron

~Aaron


SG10 list run by herb.sutter at gmail.com