Topic: A pointer to type X can point to an object of
Author: Edward Catmur <ed@catmur.co.uk>
Date: Mon, 29 Aug 2016 14:43:52 -0700 (PDT)
Raw View
------=_Part_8_474496683.1472507032723
Content-Type: multipart/alternative;
boundary="----=_Part_9_974195081.1472507032724"
------=_Part_9_974195081.1472507032724
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
On Sunday, 28 August 2016 10:58:56 UTC+1, Kazutoshi SATODA wrote:
>
> Given this example code:=20
>
> struct X {...};=20
> struct Y {...};=20
> X oX;=20
> Y oY;=20
> X* pX =3D reinterpret_cast<X*>(&oY);=20
>
> P0137R1 (http://wg21.link/P0137R1) introduces possibilities where=20
> "pX points to oY" by reinterpret_cast like the above. A similar=20
> interpretation is shown in a recent discussion, and the author of=20
> P0137R1 agreed on.=20
>
> https://groups.google.com/a/isocpp.org/d/msg/std-discussion/XYvVlTc3-to/B=
9wdNcYzBAAJ=20
> On 2016/08/18 3:44 +0900, Kazutoshi Satoda wrote:=20
> > The result of reinterpret_cast<Base*>(&d), which is the value of pb, is=
=20
> > defined as static_cast<Base*>(static_cast<void*>(&d)) (in 5.2.10 p7),=
=20
> > and the both static_cast are defined as "the pointer value is unchanged=
=20
> > by the conversion" (4.11 p2, 5.2.9 p13) then the result points to d as=
=20
> > &d does.=20
>
> https://groups.google.com/a/isocpp.org/d/msg/std-discussion/XYvVlTc3-to/N=
5R0qoU7BAAJ=20
> On 2016/08/18 6:06 +0900, Richard Smith wrote:=20
> > The Base and Derived objects are not pointer-interconvertible, because=
=20
> > Derived is not a standard-layout class type. Therefore pb is a pointer=
=20
> > of type Base* that points to the d object, not to its Base subobject.=
=20
>
> Previous definition of "point to" in C++14 was:=20
> > ... If an object of type T is located at an address A, a pointer of=20
> > type cv T* whose value is the address A is said to point to that=20
> > object, regardless of how the value was obtained. ...=20
> Then, a pointer to type X could point to an object only of type X.=20
>
> I think the situation "pX points to oY" causes some problems:=20
>
> - The semantics of "pX + 1"=20
>
> 5.7 [expr.add] p4 says:=20
> > When an expression that has integral type is added to or subtracted=
=20
> > from a pointer, the result has the type of the pointer operand. If=
=20
> > the expression P points to element x[i] of an array object x with n=
=20
> > elements, the expressions P + J and J + P (where J has the value j)=
=20
> > point to the (possibly-hypothetical) element=20
> > x[i + j] if 0 <=3D i + j <=3D n; otherwise, the behavior is undefin=
ed.=20
> > Likewise, the expression P - J points to the (possibly-hypothetical=
)=20
> > element x[i =E2=88=92 j] if 0 <=3D i =E2=88=92 j <=3D n; otherwise,=
the behavior is=20
> > undefined.=20
>
> To fulfill this definition, pX + 1 must produce a pointer to type X=
=20
> whose value is past the end of oY (note that a non-array object is=20
> considered to be an array of 1 element here).=20
> Producing such a value requires sizeof(Y) which compilers can't know=
=20
> in general unless the type information is tracked at runtime.=20
>
> Proposed resolution (edits by <ins> and <del>):=20
> When an expression that has integral type is added to or subtracted=
=20
> from a pointer <ins>to T</ins>, the result has the type of the=20
> pointer operand. If the expression P points to element x[i] of an=
=20
> array object x <del>with n elements</del><ins>of type T2[n] where=
=20
> T2 is similar to T</ins>, ...=20
>
> The resolution makes pX + 1 cause undefined behavior.=20
>
I think that [expr.add]/6 handles this, if a little clumsily:
> For addition or subtraction, if the expressions P or Q have type =E2=80=
=9Cpointer=20
to cv T=E2=80=9D, where T and the array
element type are not similar (4.4), the behavior is undefined.
It seems apparent that the "array element type" here is the runtime type Y=
=20
whereas T is X.
[expr.static.cast] handles this better for derived-base conversions (p2 and=
=20
p11); the use "actually" makes it clear that the runtime type is what=20
matters.
- The semantics of "pX->...", along with "*pX"=20
>
> 5.2.5 [expr.ref] p2 says:=20
> > For the first option (dot) the first expression shall have complete=
=20
> > class type. For the second option (arrow) the first expression shal=
l=20
> > have pointer to complete class type. The expression E1->E2 is=20
> > converted to the equivalent form (*(E1)).E2; the remainder of 5.2.5=
=20
> > will address only the first option (dot). In either case, the=20
> > id-expression shall name a member of the class or of one of its bas=
e=20
> > classes. ...=20
> and bullet (4.2) in p4 says:=20
> > - If E2 is a non-static data member and the type of E1 is=20
> > "cq1 vq1 X", and the type of E2 is "cq2 vq2 T", the expression=20
> > designates the named member of the object designated by the first=
=20
> > expression.=20
> As for (*(E1)), 5.3.1 [expr.unary.op] p1 says:=20
> > The unary * operator performs indirection: the expression to which=
=20
> > it is applied shall be a pointer to an object type, or a pointer to=
=20
> > a function type and the result is an lvalue referring to the object=
=20
> > or function to which the expression points. If the type of the=20
> > expression is "pointer to T," the type of the result is "T."=20
>
> *pX is an lvalue referring to oY, while the type of the expression=20
> is X. Then E2 shall name a member of X, which might not name a=20
> member of Y, that (for example) render the bullet (4.2) nonsense.=20
>
Agreed, that's pretty nasty.
I think this adds another case to be handled by CWG issue #232.=20
> "Is indirection through a null pointer undefined behavior?"=20
> http://wg21.cmeerw.net/cwg/issue232=20
> <http://www.google.com/url?q=3Dhttp%3A%2F%2Fwg21.cmeerw.net%2Fcwg%2Fissue=
232&sa=3DD&sntz=3D1&usg=3DAFQjCNEQQh29NqvMp8Jx9_fOw85hOL3iEg>=20
> (which is in "drafting" status for 10 years...)=20
>
> I suspect there are more problems like these.=20
>
[conv.lval]/1 would seem to be another one, also following=20
[expr.unary.op]/1.
I'll try to make these to be NB comments. Please correct me if the=20
> analysis are wrong. Ideas about the resolution are also welcome.=20
>
Tightening [expr.unary.op]/1 would probably deal with the majority of=20
cases, but might be viewed as too stringent (it's the old chestnut of=20
whether &*expr is equivalent to expr...) as with CWG 232.
Thanks for your work on this.
--=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp=
..org/d/msgid/std-proposals/02ee460f-bf1f-461a-9dda-9f664e28fde0%40isocpp.or=
g.
------=_Part_9_974195081.1472507032724
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Sunday, 28 August 2016 10:58:56 UTC+1, Kazutoshi SATODA=
wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0=
..8ex;border-left: 1px #ccc solid;padding-left: 1ex;">Given this example cod=
e:
<br>
<br>=C2=A0 struct X {...};
<br>=C2=A0 struct Y {...};
<br>=C2=A0 X oX;
<br>=C2=A0 Y oY;
<br>=C2=A0 X* pX =3D reinterpret_cast<X*>(&oY);
<br>
<br>P0137R1 (<a href=3D"http://wg21.link/P0137R1" target=3D"_blank" rel=3D"=
nofollow" onmousedown=3D"this.href=3D'http://www.google.com/url?q\x3dht=
tp%3A%2F%2Fwg21.link%2FP0137R1\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNFQMP=
fDNB_C0lVaNSHeOBUsZtdFkg';return true;" onclick=3D"this.href=3D'htt=
p://www.google.com/url?q\x3dhttp%3A%2F%2Fwg21.link%2FP0137R1\x26sa\x3dD\x26=
sntz\x3d1\x26usg\x3dAFQjCNFQMPfDNB_C0lVaNSHeOBUsZtdFkg';return true;">h=
ttp://wg21.link/P0137R1</a>) introduces possibilities where
<br>"pX points to oY" by reinterpret_cast like the above. A simil=
ar
<br>interpretation is shown in a recent discussion, and the author of
<br>P0137R1 agreed on.
<br><a href=3D"https://groups.google.com/a/isocpp.org/d/msg/std-discussion/=
XYvVlTc3-to/B9wdNcYzBAAJ" target=3D"_blank" rel=3D"nofollow" onmousedown=3D=
"this.href=3D'https://groups.google.com/a/isocpp.org/d/msg/std-discussi=
on/XYvVlTc3-to/B9wdNcYzBAAJ';return true;" onclick=3D"this.href=3D'=
https://groups.google.com/a/isocpp.org/d/msg/std-discussion/XYvVlTc3-to/B9w=
dNcYzBAAJ';return true;">https://groups.google.com/a/<wbr>isocpp.org/d/=
msg/std-<wbr>discussion/XYvVlTc3-to/<wbr>B9wdNcYzBAAJ</a>
<br>On 2016/08/18 3:44 +0900, Kazutoshi Satoda wrote:
<br>> The result of reinterpret_cast<Base*>(&d), which is the =
value of pb, is
<br>> defined as static_cast<Base*>(static_<wbr>cast<void*>(=
&d)) (in 5.2.10 p7),
<br>> and the both static_cast are defined as "the pointer value is=
unchanged
<br>> by the conversion" (4.11 p2, 5.2.9 p13) then the result point=
s to d as
<br>> &d does.
<br><a href=3D"https://groups.google.com/a/isocpp.org/d/msg/std-discussion/=
XYvVlTc3-to/N5R0qoU7BAAJ" target=3D"_blank" rel=3D"nofollow" onmousedown=3D=
"this.href=3D'https://groups.google.com/a/isocpp.org/d/msg/std-discussi=
on/XYvVlTc3-to/N5R0qoU7BAAJ';return true;" onclick=3D"this.href=3D'=
https://groups.google.com/a/isocpp.org/d/msg/std-discussion/XYvVlTc3-to/N5R=
0qoU7BAAJ';return true;">https://groups.google.com/a/<wbr>isocpp.org/d/=
msg/std-<wbr>discussion/XYvVlTc3-to/<wbr>N5R0qoU7BAAJ</a>
<br>On 2016/08/18 6:06 +0900, Richard Smith wrote:
<br>> The Base and Derived objects are not pointer-interconvertible, bec=
ause
<br>> Derived is not a standard-layout class type. Therefore pb is a poi=
nter
<br>> of type Base* that points to the d object, not to its Base subobje=
ct.
<br>
<br>Previous definition of "point to" in C++14 was:
<br>> ... If an object of type T is located at an address A, a pointer o=
f
<br>> type cv T* whose value is the address A is said to point to that
<br>> object, regardless of how the value was obtained. ...
<br>Then, a pointer to type X could point to an object only of type X.
<br>
<br>I think the situation "pX points to oY" causes some problems:
<br>
<br>=C2=A0 - The semantics of "pX + 1"
<br>
<br>=C2=A0 =C2=A0 5.7 [expr.add] p4 says:
<br>=C2=A0 =C2=A0 > When an expression that has integral type is added t=
o or subtracted
<br>=C2=A0 =C2=A0 > from a pointer, the result has the type of the point=
er operand. If
<br>=C2=A0 =C2=A0 > the expression P points to element x[i] of an array =
object x with n
<br>=C2=A0 =C2=A0 > elements, the expressions P + J and J + P (where J h=
as the value j)
<br>=C2=A0 =C2=A0 > point to the (possibly-hypothetical) element
<br>=C2=A0 =C2=A0 > x[i + j] if 0 <=3D i + j <=3D n; otherwise, th=
e behavior is undefined.
<br>=C2=A0 =C2=A0 > Likewise, the expression P - J points to the (possib=
ly-hypothetical)
<br>=C2=A0 =C2=A0 > element x[i =E2=88=92 j] if 0 <=3D i =E2=88=92 j =
<=3D n; otherwise, the behavior is
<br>=C2=A0 =C2=A0 > undefined.
<br>
<br>=C2=A0 =C2=A0 To fulfill this definition, pX + 1 must produce a pointer=
to type X
<br>=C2=A0 =C2=A0 whose value is past the end of oY (note that a non-array =
object is
<br>=C2=A0 =C2=A0 considered to be an array of 1 element here).
<br>=C2=A0 =C2=A0 Producing such a value requires sizeof(Y) which compilers=
can't know
<br>=C2=A0 =C2=A0 in general unless the type information is tracked at runt=
ime.
<br>
<br>=C2=A0 =C2=A0 Proposed resolution (edits by <ins> and <del>=
):
<br>=C2=A0 =C2=A0 =C2=A0 When an expression that has integral type is added=
to or subtracted
<br>=C2=A0 =C2=A0 =C2=A0 from a pointer <ins>to T</ins>, the re=
sult has the type of the
<br>=C2=A0 =C2=A0 =C2=A0 pointer operand. If the expression P points to ele=
ment x[i] of an
<br>=C2=A0 =C2=A0 =C2=A0 array object x <del>with n elements</del&=
gt;<ins>of type T2[n] where
<br>=C2=A0 =C2=A0 =C2=A0 T2 is similar to T</ins>, ...
<br>
<br>=C2=A0 =C2=A0 The resolution makes pX + 1 cause undefined behavior.
<br></blockquote><div><br></div><div>I think that [expr.add]/6 handles this=
, if a little clumsily:</div><div><br></div><div>> For addition or subtr=
action, if the expressions P or Q have type =E2=80=9Cpointer to cv T=E2=80=
=9D, where T and the array</div><div>element type are not similar (4.4), th=
e behavior is undefined.</div><div><br></div><div>It seems apparent that th=
e "array element type" here is the runtime type Y whereas T is X.=
</div><div><br></div><div>[expr.static.cast] handles this better for derive=
d-base conversions (p2 and p11); the use "actually" makes it clea=
r that the runtime type is what matters.</div><div><br></div><blockquote cl=
ass=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px =
#ccc solid;padding-left: 1ex;">=C2=A0 - The semantics of "pX->...&q=
uot;, along with "*pX"
<br>
<br>=C2=A0 =C2=A0 5.2.5 [expr.ref] p2 says:
<br>=C2=A0 =C2=A0 > For the first option (dot) the first expression shal=
l have complete
<br>=C2=A0 =C2=A0 > class type. For the second option (arrow) the first =
expression shall
<br>=C2=A0 =C2=A0 > have pointer to complete class type. The expression =
E1->E2 is
<br>=C2=A0 =C2=A0 > converted to the equivalent form (*(E1)).E2; the rem=
ainder of 5.2.5
<br>=C2=A0 =C2=A0 > will address only the first option (dot). In either =
case, the
<br>=C2=A0 =C2=A0 > id-expression shall name a member of the class or of=
one of its base
<br>=C2=A0 =C2=A0 > classes. ...
<br>=C2=A0 =C2=A0 and bullet (4.2) in p4 says:
<br>=C2=A0 =C2=A0 > - If E2 is a non-static data member and the type of =
E1 is
<br>=C2=A0 =C2=A0 > =C2=A0 "cq1 vq1 X", and the type of E2 is =
"cq2 vq2 T", the expression
<br>=C2=A0 =C2=A0 > =C2=A0 designates the named member of the object des=
ignated by the first
<br>=C2=A0 =C2=A0 > =C2=A0 expression.
<br>=C2=A0 =C2=A0 As for (*(E1)), 5.3.1 [expr.unary.op] p1 says:
<br>=C2=A0 =C2=A0 > The unary * operator performs indirection: the expre=
ssion to which
<br>=C2=A0 =C2=A0 > it is applied shall be a pointer to an object type, =
or a pointer to
<br>=C2=A0 =C2=A0 > a function type and the result is an lvalue referrin=
g to the object
<br>=C2=A0 =C2=A0 > or function to which the expression points. If the t=
ype of the
<br>=C2=A0 =C2=A0 > expression is "pointer to T," the type of =
the result is "T."
<br>
<br>=C2=A0 =C2=A0 *pX is an lvalue referring to oY, while the type of the e=
xpression
<br>=C2=A0 =C2=A0 is X. Then E2 shall name a member of X, which might not n=
ame a
<br>=C2=A0 =C2=A0 member of Y, that (for example) render the bullet (4.2) n=
onsense.
<br></blockquote><div><br></div><div>Agreed, that's pretty nasty.</div>=
<div><br></div><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-=
left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">=C2=A0 =C2=A0 I=
think this adds another case to be handled by CWG issue #232.
<br>=C2=A0 =C2=A0 "Is indirection through a null pointer undefined beh=
avior?"
<br>=C2=A0 =C2=A0 <a href=3D"http://www.google.com/url?q=3Dhttp%3A%2F%2Fwg2=
1.cmeerw.net%2Fcwg%2Fissue232&sa=3DD&sntz=3D1&usg=3DAFQjCNEQQh2=
9NqvMp8Jx9_fOw85hOL3iEg" target=3D"_blank" rel=3D"nofollow" onmousedown=3D"=
this.href=3D'http://www.google.com/url?q\x3dhttp%3A%2F%2Fwg21.cmeerw.ne=
t%2Fcwg%2Fissue232\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNEQQh29NqvMp8Jx9_=
fOw85hOL3iEg';return true;" onclick=3D"this.href=3D'http://www.goog=
le.com/url?q\x3dhttp%3A%2F%2Fwg21.cmeerw.net%2Fcwg%2Fissue232\x26sa\x3dD\x2=
6sntz\x3d1\x26usg\x3dAFQjCNEQQh29NqvMp8Jx9_fOw85hOL3iEg';return true;">=
http://wg21.cmeerw.net/cwg/<wbr>issue232</a>
<br>=C2=A0 =C2=A0 (which is in "drafting" status for 10 years...)
<br>
<br>I suspect there are more problems like these.
<br></blockquote><div><br></div><div>[conv.lval]/1 would seem to be another=
one, also following [expr.unary.op]/1.</div><div><br></div><blockquote cla=
ss=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #=
ccc solid;padding-left: 1ex;">I'll try to make these to be NB comments.=
Please correct me if the
<br>analysis are wrong. Ideas about the resolution are also welcome.
<br></blockquote><div><br></div><div>Tightening [expr.unary.op]/1 would pro=
bably deal with the majority of cases, but might be viewed as too stringent=
(it's the old chestnut of whether &*expr is equivalent to expr...)=
as with CWG 232.</div><div><br></div><div>Thanks for your work on this.</d=
iv></div>
<p></p>
-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/02ee460f-bf1f-461a-9dda-9f664e28fde0%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/02ee460f-bf1f-461a-9dda-9f664e28fde0=
%40isocpp.org</a>.<br />
------=_Part_9_974195081.1472507032724--
------=_Part_8_474496683.1472507032723--
.
Author: Kazutoshi Satoda <k_satoda@f2.dion.ne.jp>
Date: Wed, 31 Aug 2016 02:04:35 +0900
Raw View
On 2016/08/30 6:43 +0900, Edward Catmur wrote:
> On Sunday, 28 August 2016 10:58:56 UTC+1, Kazutoshi SATODA wrote:
....
>> I think the situation "pX points to oY" causes some problems:=20
>>
>> - The semantics of "pX + 1"=20
>> Proposed resolution (edits by <ins> and <del>):=20
>> When an expression that has integral type is added to or subtracte=
d=20
>> from a pointer <ins>to T</ins>, the result has the type of the=20
>> pointer operand. If the expression P points to element x[i] of an=
=20
>> array object x <del>with n elements</del><ins>of type T2[n] where=
=20
>> T2 is similar to T</ins>, ...=20
>>
>> The resolution makes pX + 1 cause undefined behavior.=20
>=20
> I think that [expr.add]/6 handles this, if a little clumsily:
>=20
>> For addition or subtraction, if the expressions P or Q have type =E2=80=
=9Cpointer=20
>> to cv T=E2=80=9D, where T and the array
>> element type are not similar (4.4), the behavior is undefined.
>=20
> It seems apparent that the "array element type" here is the runtime type =
Y=20
> whereas T is X.
Aha, I missed that paragraph, which was added by CWG #1504.
http://wg21.cmeerw.net/cwg/issue1504.
I'm happy to withdraw this one. Thank you very much.
>> - The semantics of "pX->...", along with "*pX"=20
....
> Tightening [expr.unary.op]/1 would probably deal with the majority of=20
> cases, but might be viewed as too stringent (it's the old chestnut of=20
> whether &*expr is equivalent to expr...) as with CWG 232.
As for &*expr, I'm wondering that just borrowing the C wording may be
feasible. It says (from WG14 N1570 6.5.3.2 p3):
> The unary & operator yields the address of its operand. If the operand
> has type "type", the result has type "pointer to type". If the operand
> is the result of a unary * operator, neither that operator nor the
> & operator is evaluated and the result is as if both were omitted,
> except that the constraints on the operators still apply and the result
> is not an lvalue.
.... with some additional words to exclude overloaded cases, of course.
--=20
k_satoda
--=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp=
..org/d/msgid/std-proposals/a8839f89-5b4e-e5ea-273c-3cbde7b0a145%40f2.dion.n=
e.jp.
.