C++ Logo

liaison

Advanced search

Re: [wg14/wg21 liaison] [isocpp-core] Ignorability of attributes: draft wording, and concern about __has_c_attribute

From: Aaron Ballman <aaron_at_[hidden]>
Date: Wed, 8 Feb 2023 10:50:52 -0500
On Wed, Feb 8, 2023 at 10:33 AM Timur Doumler <cpp_at_[hidden]> wrote:
>
> Hi Aaron,
>
>
> I'm available at various times this week; mornings work better for me
> than afternoons (Issaquah time).
>
>
> Great. JF said we can have a slot this morning. I hope to see you there!

I'll be there, thanks!

> FWIW, I think the current EWG direction is a problem. Consider:
>
> struct Empty {};
>
> struct Whatever {
> #if __has_cpp_attribute(no_unique_address)
> [[no_unique_address]]
> #endif
> Empty E;
> int Val;
> };
>
>
> I think this is a great code example to illustrate the disconnect that wehave here.
>
> If the implementation is required to return true despite not
> implementing the semantics of the attribute, it (effectively) can
> never implement the semantics of that attribute without introducing a
> silent ABI break. In my experience, users care whether an attribute
> does what it says on the tin and they use __has_cpp_attribute to tell
> them that. Poll 2 breaks that expectation and leaves the programmer
> with no alternatives.
>
>
> You are assuming here that there are only two alternatives: either the attribute "does what it says on the tin" (is "useful") or it doesn't. At the heart of the issue is that this is actually not a yes/no question, and does not always have a yes/no answer for many (most?) attributes. For example, it would be a perfectly standard-conforming implementation of [[no_unique_address]] if its semantics (= the subobject is overlapping) only kick in during a certain phase of the moon, or only if the name of the object starts with the letter 'q'. What do you return from __has_cpp_attribute then?

What value is returned is a matter of QoI. If you think your users are
not going to be upset by returning a nonzero value when the semantics
only kick in during certain moon phases, have at it. Everything about
attribute semantics is QoI, so the decision to tell users "I support
this attribute" is reasonable to also leave to QoI.

> Simultaneously, it was my impression yesterday that EWG thinks Poll 1 is not a reasonable or feasible direction, as we have no way of defining what those "useful" or "observable" semantics would be that are required for __has_cpp_attribute to return a positive value in the Poll 1 scenario.
>
>
> Attributes themselves (the bits within the [[]]) are not portable,
> even for the standard attributes.
>
>
> Exactly, So if you, as the user, rely on whether or not the semantics of the attribute kick in, and whether or not they will break your ABI, you have already lost, regardless of how __has_cpp_attribute is specified.

If we (the committees) intend an attribute to be reliable, we would
have used syntax for it other than attribute syntax, because we're
aware that everything to do with the semantics of the attribute is a
recommendation. That we have added attributes where users want
reliable semantics is the root cause of the problem.

> On the other hand, whether the compiler can recognise, parse, and syntax-check a standard attribute *is* a meaningful yes/no question, so if we want __has_cpp_attribute to do something useful, that is the one useful thing that we can specify it to do. Perhaps C should reconsider their direction on this one?

Feel free to file a comment for CD2, but I'd be strongly opposed to
it. I've been asking around to see what less senior programmers think
of the EWG direction on the poll yesterday. I've yet to find someone
who understands it, even after I explain the reasoning as best I can.
Universally, the response has been "but I thought __has_cpp_attribute
told me if the attribute does the thing, why would I care if it parses
but doesn't do anything?". I think the current direction is going to
break a lot of user expectations.

> The recommendation is that
> implementations implement the standard attribute and its recommended
> practices. If the implementation feels that they've done that, they
> should return the expected nonzero value for that attribute. If they
> don't feel like they've done that, they should return zero. To me,
> this is solidly QoI and EWG doesn't need to define anything there.
> However, I also wasn't able to make it to the EWG discussion of this
> topic, so perhaps there's nuance I'm not getting from the meeting
> minutes.
>
>
> This seems like the only viable alternative: to leave it vague what it means to "support" an attribute, and to live with the current implementation divergence. But then I don't think you will be able to rely on code like your snippet above to behave the way you expect.

Correct, that's my suggestion. And I think there's possibly a
specification mechanism to make this more clear:

* Normatively define __has_cpp_attribute as returning 0 for all
standard attributes.
* In each attribute's Recommended Practice clause, add a sentence
along the lines of "If this recommendation is implemented, it is
additionally recommended to return the value <blah> from
__has_cpp_attribute when <yada> is given as the operand."

The basic idea here is: all attributes, even standard attributes, are
not portable, so admit that. They're merely recommendations. If you do
what the standard recommends you do, then users will expect to be able
to test for it with __has_cpp_attribute, and this ties the "attribute
does what it says on the tin" more closely to "what does
__has_cpp_attribute return". It's not going to be 100% perfect because
a malicious implementation could do the recommendation but not the
__has_cpp_attribute bits (or vice versa), but that's QoI and not a
situation I'm worried about for an inherently nonportable construct.

~Aaron

>
> Cheers,
> Timur

Received on 2023-02-08 15:51:07