C++ Logo

std-proposals

Advanced search

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

From: Arthur O'Dwyer <arthur.j.odwyer_at_[hidden]>
Date: Thu, 4 May 2023 13:57:32 -0400
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:

// 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 <https://godbolt.org/z/7ovMM6db4>. (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

Received on 2023-05-04 17:57:47