C++ Logo

std-proposals

Advanced search

Re: [std-proposals] [Draft Proposal] Required attribute syntax

From: Marcin Jaczewski <marcinjaczewski86_at_[hidden]>
Date: Fri, 5 May 2023 20:36:11 +0200
pt., 5 maj 2023 o 17:57 Arthur O'Dwyer <arthur.j.odwyer_at_[hidden]> napisał(a):
>
> On Fri, May 5, 2023 at 11:34 AM Marcin Jaczewski wrote:
>>
>> pt., 5 maj 2023 o 15:52 Jason McKesson napisał(a):
>> > On Fri, May 5, 2023 at 4:16 AM Marcin Jaczewski <marcinjaczewski86_at_[hidden]> wrote:
>> > > pt., 5 maj 2023 o 03:34 Jason McKesson napisał(a):
>> > > >
>> > > > On Thu, May 4, 2023 at 6:20 PM Marcin Jaczewski via Std-Proposals
>> > > > <std-proposals_at_[hidden]> wrote:
>> > > > >
>> > > > > czw., 4 maj 2023 o 19:57 Arthur O'Dwyer <arthur.j.odwyer_at_[hidden]> napisał(a):
>> > > > > >
>> > > > > > On Thu, May 4, 2023 at 1:29 PM Marcin Jaczewski <marcinjaczewski86_at_[hidden]> wrote:
>> > > > > >>
>> > > > > >> czw., 4 maj 2023 o 16:39 Arthur O'Dwyer napisał(a):
>> > > > > >> > Marcin Jaczewski wrote:
>> > > > > >> >>
>> > > > > >> >> But attributes "failure" should be preferably "invisible" and "undetectable"?
>> > > > > >> [...]
>> > > > > >
>> > > > > >> This means to have "portable" programs for both these attributes your
>> > > > > >> headers need to have:
>> > > > > >> ```
>> > > > > >> #if !__atturibte_supported(no_unique_address) ||
>> > > > > >> !__atturibte_supported(trivially_relocatable)
>> > > > > >> #error "please install new compiler"
>> > > > > >> #endif
>> > > > > >> ```
>> > > > > >
>> > > > > > Yes, but that's true of literally everything in the language. You can't use structured bindings unless the compiler supports them. You can't use concepts unless the compiler supports them. You can't use `std::flat_map` unless the library supports it. And so on, and so on, forever. [...]
>> > > > > > In other words, attributes aren't any more special than keywords in these respects. You can't use any of C++ without compiler support for it.
>> > > > >
>> > > > > But you miss again my point, I can use attributes like
>> > > > > `[[fallthrough]]` even if the compiler does not know what it is, it's
>> > > > > enough that my IDE knows it or other external tool.
>> > > > > I can even use it in code that could be compiled in C++11 standard.
>> > > > > This is why I name them "ignorable" (of course this does not apply to
>> > > > > all as you did point out).
>> > > > > This is why I would prefer if `no_unique_address` or
>> > > > > `trivially_relocatable` would be contextual keyword as
>> > > > > trying to compile it in an unsupported compiler will be hard error
>> > > > > and there will be no problems with UB if some mixed TU are linked.
>> > > >
>> > > > You assume that a compiler will give a hard error if it doesn't
>> > > > support it. Because `no_unique_address` is largely based on
>> > > > unspecified behavior, an implementation can "support it" without
>> > > > actually doing anything different. Changing that has nothing to do
>> > > > with the syntax which invokes the behavior and has everything to do
>> > > > with the behavior itself.
>> > >
>> > > I was comparing attributes to contextual keywords.
>> > > if the compiler encounters some random `[[x]]` attribute then by definition
>> > > it will skip over it, but if it encounters some random unexpected token `x` then
>> > > it will signal a hard error.
>> > >
>> > > And yes, from a standard perspective NUA is an unspecified behavior,
>> > > but from ABI
>> > > perspective this is a critical one. If compiler is owner of ABI (like
>> > > MSVC), then it can do anything he want with
>> > > it, but if not then e.g. Itanium C++ ABI defines how this attribute should work.
>> > >
>> > > This means in case NUA or other similar functionality would be
>> > > prefered to have hard error
>> > > when the compiler does not know how to handle it.
>> >
>> > So what is the scenario we're talking about? It must be something
>> > where you've written code that requires C++20 and you want the
>> > compiler to error if it is being compiled in C++17 or before.
>>
>> Simple header file of my library that is publicly available, I compile
>> dll using C++20
>> and really on its features. And if some else grab by headers and try link
>> to my dll I would prefer hard error if compiler do not support NUA or
>> interpret it diffrent than my compiler.
>
>
> So use:
> - `__has_cpp_attribute(no_unique_address)`
> - `-W3` or higher on MSVC, to diagnose unrecognized or misspelled attributes (GCC and Clang diagnose by default, even without `-Wall`)
> - `static_assert` and/or unit-test, to ensure that the behavior you expect to happen is, in fact, happening.
>

Only `static_assert` will work. Others will not work if the compiler
knows this attribute but decides not to implement it,
or if the user compiles without enabled warnings.

> Both Marcin and Sebastian seem to be laboring under the incorrect assumption that unrecognized C++ attributes are simply ignored by the compiler, so that if the compiler doesn't support a particular attribute, the failure mode will be silent. This is certainly wrong today, and in fact I don't think it's ever been right. If the compiler silently ignored "unknown" attributes, then you'd be in the horrible position that
>
> struct S {
> [[nouniqueaddress]] int x;
> };
>
> would silently Do The Wrong Thing, simply because you left off the underscores.

There is a difference between an ill-formed program and a diagnosing
warning. This code you show is still a well-formed C++ program and by
default most compilers will accept it.
And your example show why I think this NUA is bad, as if you did use
`[[no_return]]` then your program is still correct, you only miss the
benefits that a correct attribute would give.

> In actual fact, the Standard deliberately reserves a namespace for standard attributes (namely, any name not containing `::`), and compilers will diagnose any misspelled or unrecognized attribute in that namespace.
> In vendor-specific namespaces, the "morally right" behavior is more confusing to reason about, but the facts on the ground are the same: All three vendors treat [[unexpectednamespace::nouniqueaddress]] in exactly the same way as [[nouniqueaddress]]. There's no way to turn on warnings for the latter without also getting warnings for the former.
> https://godbolt.org/z/9qbjzTd1d
>
> So, if you misspell an attribute — or if you try to use an attribute that's not supported by your compiler vendor, which comes to the same thing, from the compiler's point of view — you'll get a diagnostic and have to fix your code. This is the same thing that happens if you try to use any other new syntax or compiler feature: If it's supported, your code works as intended. If it's not supported, all bets are off; so we provide feature flags and things that allow you to engineer around that situation.
>
> –Arthur

Why not follow this logic to its conclusion, and make that any wrong
use of attributes should cause the program to be ill-formed?

Overall reading again https://eel.is/c++draft/dcl.attr#grammar-6 I see
that I do not diverge far from things standard said:

"""
For an attribute-token (including an attribute-scoped-token) not
specified in this document, the behavior is implementation-defined;
any such attribute-token that is not recognized by the implementation
is ignored.
[Note 4:
A program is ill-formed if it contains an attribute specified in
[dcl.attr] that violates the rules specifying to which entity or
statement the attribute can apply or the syntax rules for the
attribute's attribute-argument-clause, if any.
— end note]
[Note 5:
The attributes specified in [dcl.attr] have optional semantics: given
a well-formed program, removing all instances of any one of those
attributes results in a program whose set of possible executions
([intro.abstract]) for a given input is a subset of those of the
original program for the same input, absent implementation-defined
guarantees with respect to that attribute.
— end note]
An attribute-token is reserved for future standardization if

(6.1)
it is not an attribute-scoped-token and is not specified in this document, or
(6.2)
it is an attribute-scoped-token and its attribute-namespace is std
followed by zero or more digits.

Each implementation should choose a distinctive name for the
attribute-namespace in an attribute-scoped-token.
"""

Received on 2023-05-05 18:36:24