C++ Logo

std-discussion

Advanced search

Re: Is the intent of [class.cdtor] p2 to disallow aliasing, and is the wording strong enough to be useful?

From: Jan Schultke <janschultke_at_[hidden]>
Date: Sat, 5 Aug 2023 13:27:31 +0200
Thank you for the explanation. I'm decreasingly convinced that this is
meant to disallow aliasing as time goes on.

Whatever the intent is, the wording isn't strong enough for `noalias`
in GCC at this time, so I've filed a bug report:
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110912 (it's worth a
read. GCC devs actually cite this very paragraph as the reason why
`noalias` is applied to constructor parameters.

Personally, I would be in favor of removing the paragraph completely.
It's either not utilized at all (LLVM), or utilized incorrectly (GCC),
and just introduces more unspecified behavior for seemingly very
little benefit. Alternatively, it should be strengthened so that
`noalias` can be applied.

On Sat, Aug 5, 2023 at 4:45 AM Matthew House via Std-Discussion
<std-discussion_at_[hidden]> wrote:
>
> On Fri, Aug 4, 2023 at 7:02 PM Jan Schultke via Std-Discussion
> <std-discussion_at_[hidden]> wrote:
> >
> > The issue starts with the following code gen: https://godbolt.org/z/PYTohPTKr
> >
> > Here, adding `__restrict` improves the code gen, but it doesn't for
> > GCC. GCC seems to assume that no aliasing can take place between
> > `this` and other parameters passed into the function. LLVM does not
> > add `noalias` without `__restrict`.
> >
> > [class.cdtor] p2 says:
> > > During the construction of an object, if the value of the
> > > object or any of its subobjects is accessed through a
> > > glvalue that is not obtained, directly or indirectly,
> > > from the constructor's this pointer, the value
> > > of the object or subobject thus obtained is unspecified.
> >
> > I believe that this paragraph's intent is to disallow aliasing, e.g.
> > between `this` and rvalue reference passed into the move constructor.
> > However, the wording is very difficult to implement.
> > - GCC simply assumes `noalias`, which also assumes that writing to the
> > aforementioned glvlaue will make its value unspecified. The paragraph
> > only talks about the obtained value though.
> > - clang does not assume anything, and possibly misses optimizations as a result.
> >
> > Am I interpreting the intent correctly? If so, how can the wording be
> > improved to fully disallow aliasing, as intended, so that we can just
> > add `noalias` here, as is already done?
>
> I was complaining about this clause a while back; "the value... thus
> obtained is unspecified" is a remarkably weak criterion compared to
> the full UB of 'noalias' or '__restrict'. You can find the thread at
> <https://lists.isocpp.org/std-discussion/2022/12/1952.php>.
> Originally, the clause only applied to const objects under
> construction, but it was later changed to apply to all objects. I
> wasn't able to find any definite rationale of why the original clause
> was added or why it was expanded; one can speculate that it was to
> allow compilers to blanket-substitute 'global_const_object.field' with
> its final computed value, but that doesn't work when the value can
> also change in the destructor. Unless it's meant to help classes with
> nontrivial constructors but trivial destructors?
>
> Regardless, I don't think applying '__restrict' to every implicit
> 'this' parameter would even be desirable here. I have an example at
> <https://github.com/cplusplus/CWG/issues/206> of how it would break
> classes holding self-referential pointers: suppose that derived
> classes B and C share a virtual base class A, and A's constructor
> stores a pointer to one of its fields in another field. When A's
> constructor is called from B's constructor, it stores a pointer
> derived from A's 'this' pointer, which is derived from B's 'this'
> pointer. But if C's constructor then tries to access the field (which
> is an indirect subobject of C) via the pointer (derived from B's
> 'this'), then it breaks the rules of the clause. If the constructor
> also modifies the pointee directly, with an lvalue derived from C's
> 'this', then it also breaks the rules of '__restrict'.
>
> Personally, I'd be in favor of removing the clause entirely, if the
> compiler writers are misinterpreting it as implying '__restrict'. It
> can't be strengthened into a full '__restrict' without resulting in
> the self-referential issue, at least not without a guarantee that the
> annotation only applies to the outermost constructor and not to
> subobject constructors.
> --
> Std-Discussion mailing list
> Std-Discussion_at_[hidden]
> https://lists.isocpp.org/mailman/listinfo.cgi/std-discussion

Received on 2023-08-05 11:27:43