C++ Logo

SG10

Advanced search

Subject: [SG10] On __has_attribute
From: Richard Smith (richard_at_[hidden])
Date: 2014-03-25 17:18:06


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:

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
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?]

*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



SG10 list run by herb.sutter at gmail.com