C++ Logo

std-proposals

Advanced search

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

From: Jason McKesson <jmckesson_at_[hidden]>
Date: Fri, 5 May 2023 09:51:46 -0400
On Fri, May 5, 2023 at 4:16 AM Marcin Jaczewski
<marcinjaczewski86_at_[hidden]> wrote:
>
> pt., 5 maj 2023 o 03:34 Jason McKesson via Std-Proposals
> <std-proposals_at_[hidden]> 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"?
> > > >> [...]
> > > >> I personally would prefer that you could disable attributes in one TU
> > > >> and still could link with the rest of the program that had enabled
> > > >> them.
> > > >> And I call this "ignorable" (same as `-O3` could be integrable but
> > > >> critical for any program).
> > > >> But of course currently standard do not work this way, and
> > > >> `[[no_unique_address]]` or `[[trivially_relocatable]]` would break if
> > > >> you link two TU that have diffrent interpretation of them.
> > > >
> > > >
> > > > Actually, [[trivially_relocatable]] has no direct effect on ABI at all; that's one of its design principles.
> > > > Now, in some sense, everything in the entire world — as long as it's observable — is ABI. Consider:
> > > >
> > >
> > > Ok, I mixed it with the similar Clang attribute that did affect the call ABI.
> > >
> > > > // https://godbolt.org/z/foxvdEsfP
> > > > struct [[trivially_relocatable]] S {
> > > > [[no_unique_address]] int i;
> > > > boost::container::vector<int> v;
> > > > };
> > > > inline int f() { return sizeof(S); }
> > > > inline bool g() { return std::is_trivially_relocatable_v<S>; }
> > > >
> > > > If you ignore the attributes in one TU, then `f` and `g` start returning 32 and 0 instead of 24 and 1; and since they're `inline` and need to have the same behavior in all TUs, that's an ODR violation.
> > > >
> > > > But [[trivially_relocatable]] deliberately doesn't affect ABI in any sense other than being observable via the type trait. It doesn't affect the calling convention, or size or alignment or mangling or anything like that. This makes [[trivially_relocatable]] one big step less ABI-ful than [[no_unique_address]], which directly affects struct layout and thus calling convention. (But it remains more ABI-ful than [[nodiscard]] or [[deprecated]], neither of which can even be used to create an ODR violation, as far as I know.)
> > > >
> > > >
> > > >> 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. We deal with this "dialectization" of C++ in at least a couple of ways:
> > > > - Feature-test macros, so you can portably tell whether your code will be accepted by the compiler with the semantics you expect. As you notice, we already have feature-test macros even for attributes, because in general their semantics do matter to working programmers.
> > > > - A general fear, in WG21, of "splitting the language" into dialects (e.g. `-fno-exceptions` or Embedded C++), which manifests as a resistance to "epochs"-type proposals and also as relentless pressure on vendors to implement everything in the current standard (and as close to "nothing else" as possible), so that code that uses exactly what's in the standard will be more-or-less "portable" across all vendors. This includes supporting the standard attributes.
> > > >
> > > > 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.
> > > >
> > > > –Arthur
> > >
> > > 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.

But this isn't the only non-syntax-presenting language change in
C++20. Or C++17 for that matter. That's why they standardized all of
those feature test macros. So if your code had used one of those,
you'd just use the feature test macro to give it a hard error.

Basically, treat these attribute features the way you would treat any
other non-syntax-presenting language change.

Received on 2023-05-05 13:51:57