<div dir="ltr">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:<div>
<br></div><div>1) Implementations have attribute syntaxes other than C++ attributes (both for historical reasons and as an ongoing concern to support attributes in C), and</div><div>2) We need a mechanism to determine whether the attribute-detection feature is available.</div>
<div><br></div><div>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:</div>
<div><br></div><div><br></div><div>Option A:</div><div>---------</div><div><br></div><div> __has_attribute([[deprecated]])</div><div> __has_attribute(__attribute__((some_gnu_thing)))</div><div> __has_attribute(__declspec(foobar))</div>
<div> __has_attribute([clsid])</div><div><br></div><div>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__).</div>
<div><br></div><div>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.</div>
<div><br></div><div><br></div><div>Option B:</div><div>---------</div><div><br></div><div>A simpler approach would be to acknowledge point (1) in the macro name, giving:</div><div><br></div><div> __has_cpp_attribute ( attribute-token )</div>
<div><br></div><div>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.</div>
<div><br></div><div><br></div><div>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:</div><div><br></div><div><br></div><div>
<font size="4">Testing for the presence of an attribute: __has_cpp_attribute<br></font><br></div><div>[some introductory text]</div><div><br><b>Syntax</b><br><br> <i>has-attribute-expression:</i><br> <font face="courier new, monospace">__has_cpp_attribute</font> <font face="courier new, monospace">(</font> <i>attribute-scoped-token</i> <font face="courier new, monospace">)</font><br>
<br><b>Semantics</b><br><br>A <i>has-attribute-expression</i> shall appear only in the controlling constant expression of a <font face="courier new, monospace">#if</font> or <font face="courier new, monospace">#elif</font> directive ([cpp.cond] 16.1). The <i>has-attribute-expression</i> is replaced by the pp-number 1 if the implementation supports an attribute with the specified name, and by the pp-number 0 otherwise.<br>
<br>The <font face="courier new, monospace">#ifdef</font> and <font face="courier new, monospace">#ifndef</font> directives, and the <font face="courier new, monospace">defined</font> conditional inclusion operator, shall treat <font face="courier new, monospace">__has_cpp_attribute</font> as if it were the name of a defined macro. The identifier <span style="font-family:'courier new',monospace">__has_cpp_attribute</span> shall not appear in any context not mentioned in this section.</div>
<div><br></div><div>An implementation should only claim to support an <i>attribute-token</i> with no <i>attribute-namespace</i> 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 <i>attribute-token</i> with an <i>attribute-namespace</i> if it follows the behavior specified by the vendor identified by the <i>attribute-namespace</i>.</div>
<div><br></div><div>[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?]<br>
<br><b>Example</b><br><br>This demonstrates a way to use the attribute <font face="courier new, monospace">[[deprecated]]</font> only if it is available.<br><br><font face="courier new, monospace">#ifdef __has_cpp_attribute<br>
# if __has_cpp_attribute(deprecated)<br># define ATTR_DEPRECATED(msg) [[deprecated(msg)]]<br># endif<br>#endif</font></div></div>