Date: Thu, 28 Oct 2021 08:22:35 +0800
On Wed, 27 Oct 2021 at 21:41, <language.lawyer_at_[hidden]> wrote:
> On 27/10/2021 16:24, Yongwei Wu wrote:
> > On Wed, 27 Oct 2021 at 20:36, <language.lawyer_at_[hidden]> wrote:
> >
> >> On 27/10/2021 15:22, Yongwei Wu via Std-Discussion wrote:
> >>> On Wed, 27 Oct 2021 at 19:57, <language.lawyer_at_[hidden]> wrote:
> >>>
> >>>> On 27/10/2021 14:44, Yongwei Wu via Std-Discussion wrote:
> >>>>> When looking up the exact wording of aliasing rules in C++, I am
> >>>> surprised
> >>>>> to find that much content seems to be gone in the C++20 (draft,
> N4860)
> >>>>> under 7.2.1 p11. Specifically, there is no mention of the validity of
> >>>>> aliasing with "a type that is a (possibly cv-qualified) base class
> type
> >>>> of
> >>>>> the dynamic type of the object", which existed in earlier C++
> >> standards.
> >>>>>
> >>>>> Also the online link: https://eel.is/c++draft/basic.lval#11
> >>>>>
> >>>>> I do not think the standard has changed the rule, so I must have
> missed
> >>>>> something. Can anyone point to me how to read the rules, maybe
> pointing
> >>>> me
> >>>>> to a discussion of the wording change?
> >>>>
> >>>> https://wg21.cmeerw.net/cwg/issue2051
> >>>>
> >>>>
> >>
> https://stackoverflow.com/questions/56878519/what-happened-to-the-aggregate-or-union-type-that-includes-one-of-the-aforement
> >>>>
> >>>> TL;DR the removed rules have never been applicable.
> >>>>
> >>>
> >>> Thanks for the info. But the issue is not completely resolved for me.
> >>>
> >>> Say:
> >>>
> >>> struct A { … };
> >>> struct B : A { … };
> >>> A* pA = new B{…};
> >>>
> >>> Is using pA->… to access the base-class fields undefined behaviour?
> >>>
> >>> Interpreting the rules literally, it seems to be the case … but that
> >> seems
> >>> very surprising to me.
> >>
> >> According to the current C++ model, access only happens to the object
> >> denoted by a glvalue. Access to a subobject doesn't count as access to
> the
> >> containing object.
> >> And the evaluation of the object expression of a class member access
> >> expression *itself* (i.e. ignoring what happens in its subexpressions)
> is
> >> not considered access to the class object it denotes.
> >>
> >
> > Let me understand it better by an example:
> >
> > struct A { uint32_t v1; uint32_t v2; };
> > struct B { uint32_t v1; uint16_t v2; };
> > A a;
> > B* pB = reinterpret_cast<B*>(&a);
> >
> > Question: Is reading pB->v1 undefined behaviour?
>
> It is, but not because of strict aliasing rules violation.
> There is no explicit wording saying that this has undefined behavior.
> [expr.ref]/(6.1) could be read as that an object of type A doesn't have a
> member subobject corresponding to B::v1 and thus this bullet doesn't apply
> and the behavior is undefined by omission. Yes, this sounds weak.
> [expr.ref] should explicitly say something like that the type of the object
> expression, ignoring qualifiers, shall be the same as its dynamic type,
> otherwise the behavior is undefined.
>
I agree it is rather weak. I am still not able to determine from [expr.rf]/
7.6.1.5 that pB->v1 is undefined behaviour from the text. I do not think it
applies, and it does not mention undefined behaviour at all.
Maybe the intention is the same, but it is simply not clear from the text
that base-class access is defined and unrelated-class access is undefined.
It is clearer in C++17 [basic.lval]/6.10.
> I believe it was the case in C++17. Does the new definition of "access"
> (in
> > 3.1) imply that pB->v1 is no longer undefined?
>
> I think the definition of "access" was the same in C++17.
>
In C++17 "access" was defined as "to read or modify the value of an
object". In C++20 "access" is explicitly limited to "only objects of scalar
type". Yes, maybe the intentions are the same...
> On 27/10/2021 16:24, Yongwei Wu wrote:
> > On Wed, 27 Oct 2021 at 20:36, <language.lawyer_at_[hidden]> wrote:
> >
> >> On 27/10/2021 15:22, Yongwei Wu via Std-Discussion wrote:
> >>> On Wed, 27 Oct 2021 at 19:57, <language.lawyer_at_[hidden]> wrote:
> >>>
> >>>> On 27/10/2021 14:44, Yongwei Wu via Std-Discussion wrote:
> >>>>> When looking up the exact wording of aliasing rules in C++, I am
> >>>> surprised
> >>>>> to find that much content seems to be gone in the C++20 (draft,
> N4860)
> >>>>> under 7.2.1 p11. Specifically, there is no mention of the validity of
> >>>>> aliasing with "a type that is a (possibly cv-qualified) base class
> type
> >>>> of
> >>>>> the dynamic type of the object", which existed in earlier C++
> >> standards.
> >>>>>
> >>>>> Also the online link: https://eel.is/c++draft/basic.lval#11
> >>>>>
> >>>>> I do not think the standard has changed the rule, so I must have
> missed
> >>>>> something. Can anyone point to me how to read the rules, maybe
> pointing
> >>>> me
> >>>>> to a discussion of the wording change?
> >>>>
> >>>> https://wg21.cmeerw.net/cwg/issue2051
> >>>>
> >>>>
> >>
> https://stackoverflow.com/questions/56878519/what-happened-to-the-aggregate-or-union-type-that-includes-one-of-the-aforement
> >>>>
> >>>> TL;DR the removed rules have never been applicable.
> >>>>
> >>>
> >>> Thanks for the info. But the issue is not completely resolved for me.
> >>>
> >>> Say:
> >>>
> >>> struct A { … };
> >>> struct B : A { … };
> >>> A* pA = new B{…};
> >>>
> >>> Is using pA->… to access the base-class fields undefined behaviour?
> >>>
> >>> Interpreting the rules literally, it seems to be the case … but that
> >> seems
> >>> very surprising to me.
> >>
> >> According to the current C++ model, access only happens to the object
> >> denoted by a glvalue. Access to a subobject doesn't count as access to
> the
> >> containing object.
> >> And the evaluation of the object expression of a class member access
> >> expression *itself* (i.e. ignoring what happens in its subexpressions)
> is
> >> not considered access to the class object it denotes.
> >>
> >
> > Let me understand it better by an example:
> >
> > struct A { uint32_t v1; uint32_t v2; };
> > struct B { uint32_t v1; uint16_t v2; };
> > A a;
> > B* pB = reinterpret_cast<B*>(&a);
> >
> > Question: Is reading pB->v1 undefined behaviour?
>
> It is, but not because of strict aliasing rules violation.
> There is no explicit wording saying that this has undefined behavior.
> [expr.ref]/(6.1) could be read as that an object of type A doesn't have a
> member subobject corresponding to B::v1 and thus this bullet doesn't apply
> and the behavior is undefined by omission. Yes, this sounds weak.
> [expr.ref] should explicitly say something like that the type of the object
> expression, ignoring qualifiers, shall be the same as its dynamic type,
> otherwise the behavior is undefined.
>
I agree it is rather weak. I am still not able to determine from [expr.rf]/
7.6.1.5 that pB->v1 is undefined behaviour from the text. I do not think it
applies, and it does not mention undefined behaviour at all.
Maybe the intention is the same, but it is simply not clear from the text
that base-class access is defined and unrelated-class access is undefined.
It is clearer in C++17 [basic.lval]/6.10.
> I believe it was the case in C++17. Does the new definition of "access"
> (in
> > 3.1) imply that pB->v1 is no longer undefined?
>
> I think the definition of "access" was the same in C++17.
>
In C++17 "access" was defined as "to read or modify the value of an
object". In C++20 "access" is explicitly limited to "only objects of scalar
type". Yes, maybe the intentions are the same...
-- Yongwei Wu URL: http://wyw.dcweb.cn/
Received on 2021-10-27 19:22:51