Topic: Allow char pointers to traverse any part of a
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Tue, 13 Jun 2017 17:05:34 -0700 (PDT)
Raw View
------=_Part_1878_1768419833.1497398734867
Content-Type: multipart/alternative;
boundary="----=_Part_1879_2098867981.1497398734867"
------=_Part_1879_2098867981.1497398734867
Content-Type: text/plain; charset="UTF-8"
On Tuesday, June 13, 2017 at 6:06:48 PM UTC-4, Myriachan wrote:
>
> Currently, offsetof has limited use, because the only useful defined way
> to use the value returned by offsetof is to access members of a field in a
> char array after the class has been copied to it.
>
> My proposal is to allow char pointer arithmetic to traverse any part of
> the dynamic type of an object, rather than merely being limited to the
> subobject from which the pointer was originally derived. Such an adjusted
> char pointer would be allowed to cast back to non-char pointer type, then
> accessed, provided that all aliasing rules are followed. That is, if you
> cast back to non-char object pointer type and dereference, the type must
> more-or-less match the dynamic type of the object or subobject. (I suppose
> if you write rather than read, you might end up ending the lifetime of the
> object and reusing its storage, which would be legal, but not what you
> wanted.)
>
> struct Meow
> {
> int x;
> int y;
> };
>
> int BadReadY(Meow *meow)
> {
> // This function has undefined behavior despite this being true.
> static_assert(offsetof(Meow, y) == offsetof(Meow, x) +
> sizeof(Meow::x));
>
> int *p = &meow->x;
> return p[1];
> }
>
> int GoodReadY(Meow *meow)
> {
> static_assert(offsetof(Meow, y) == offsetof(Meow, x) +
> sizeof(Meow::x));
>
> char *p = reinterpret_cast<char *>(&meow->x);
> return *reinterpret_cast<int *>(p + sizeof(Meow::x));
> }
>
>
> The reason for the change is to permit the following kind of code.
> Developers do this anyway already, despite having undefined behavior under
> the current Standard ([expr.add]/4).
>
> #define CONTAINING_RECORD(address, type, field) \
> reinterpret_cast<type *>(reinterpret_cast<char *>(address) -
> offsetof(type, field))
>
Your example doesn't make your use case. Your use case is specifically
about accessing a member subobject of the `type` at the `address`. Your
example however is about jumping from sibling object to sibling object.
In the example, `(&meow->x)` is a pointer to an `int`. The dynamic type of
that object is `*int*`, not `Meow`. So by your own definition, that example
would still be UB.
If you want something that makes your `CONTAINING_RECORD` work, then what
you would say is that converting a `T*` into a byte pointer (ie: either
`char*`, `unsigned char*`, or `std::byte*`) means that you are pointing to
the beginning of an array of bytes, the size of which is `sizeof(T)`, the
array storing the object representation of that `T`.
But if you want your `GoodReadY` to work, then you have to do something
different. You have to say that converting a pointer to a `T*` into a byte
pointer gives you a pointer into the *middle* of an array of bytes (or at
least potentially the middle). The size of the array and location of that
pointer within the array depend on the size of the outermost containing
class and the location of that subobject within the container. That's not
merely the "dynamic type" of what you're casting from.
Personally, I much prefer the former to the latter. I don't like the idea
of being able to jump from sibling subobject to sibling subobject. If you
want to make that jump, I feel that you should have to start with a pointer
to the object that they're both subobjects of.
Whether this would be legal for non-standard-layout types is a separate
> issue; see
> http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0545r0.html
>
> Melissa
>
--
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 email 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/15ba79a9-a1c5-4044-bfcb-0c8cc18ca9a6%40isocpp.org.
------=_Part_1879_2098867981.1497398734867
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Tuesday, June 13, 2017 at 6:06:48 PM UTC-4, Myriachan w=
rote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8e=
x;border-left: 1px #ccc solid;padding-left: 1ex;"><div>Currently, offsetof =
has limited use, because the only useful defined way to use the value retur=
ned by offsetof is to access members of a field in a char array after the c=
lass has been copied to it.<br><br>My proposal is to allow char pointer ari=
thmetic to traverse any part of the dynamic type of an object, rather than =
merely being limited to the subobject from which the pointer was originally=
derived. Such an adjusted char pointer would be allowed to cast back to no=
n-char pointer type, then accessed, provided that all aliasing rules are fo=
llowed.=C2=A0 That is, if you cast back to non-char object pointer type and=
dereference, the type must more-or-less match the dynamic type of the obje=
ct or subobject.=C2=A0 (I suppose if you write rather than read, you might =
end up ending the lifetime of the object and reusing its storage, which wou=
ld be legal, but not what you wanted.)<br><br>struct Meow<br>{<br>=C2=A0=C2=
=A0=C2=A0 int x;<br>=C2=A0=C2=A0=C2=A0 int y;<br>};<br><br>int BadReadY(Meo=
w *meow)<br>{<br>=C2=A0=C2=A0=C2=A0 // This function has undefined behavior=
despite this being true.<br>=C2=A0=C2=A0=C2=A0 static_assert(offsetof(Meow=
, y) =3D=3D offsetof(Meow, x) + sizeof(Meow::x));<br><br>=C2=A0=C2=A0=C2=A0=
int *p =3D &meow->x;<br>=C2=A0=C2=A0=C2=A0 return p[1];<br>}<br><br=
>int GoodReadY(Meow *meow)<br>{<br>=C2=A0=C2=A0=C2=A0 static_assert(offseto=
f(Meow, y) =3D=3D offsetof(Meow, x) + sizeof(Meow::x));<br><br>=C2=A0=C2=A0=
=C2=A0 char *p =3D reinterpret_cast<char *>(&meow->x);<br>=C2=
=A0=C2=A0=C2=A0 return *reinterpret_cast<int *>(p + sizeof(Meow::x));=
<br>}<br><br><br>The reason for the change is to permit the following kind =
of code.=C2=A0 Developers do this anyway already, despite having undefined =
behavior under the current Standard ([expr.add]/4).=C2=A0</div></blockquote=
><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;bo=
rder-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><br>#define =
CONTAINING_RECORD(address, type, field) \<br>=C2=A0=C2=A0=C2=A0 reinterpret=
_cast<type *>(reinterpret_cast<char *>(address) - offsetof(type=
, field))<br></div></blockquote><div><br>Your example doesn't make your=
use case. Your use case is specifically about accessing a member subobject=
of the `type` at the `address`. Your example however is about jumping from=
sibling object to sibling object.<br><br>In the example, `(&meow->x=
)` is a pointer to an `int`. The dynamic type of that object is `<b>int</b>=
`, not `Meow`. So by your own definition, that example would still be UB.<b=
r><br>If you want something that makes your `CONTAINING_RECORD` work, then =
what you would say is that converting a `T*` into a byte pointer (ie: eithe=
r `char*`, `unsigned char*`, or `std::byte*`) means that you are pointing t=
o the beginning of an array of bytes, the size of which is `sizeof(T)`, the=
array storing the object representation of that `T`.<br><br>But if you wan=
t your `GoodReadY` to work, then you have to do something different. You ha=
ve to say that converting a pointer to a `T*` into a byte pointer gives you=
a pointer into the <i>middle</i> of an array of bytes (or at least potenti=
ally the middle). The size of the array and location of that pointer within=
the array depend on the size of the outermost containing class and the loc=
ation of that subobject within the container. That's not merely the &qu=
ot;dynamic type" of what you're casting from.<br><br>Personally, I=
much prefer the former to the latter. I don't like the idea of being a=
ble to jump from sibling subobject to sibling subobject. If you want to mak=
e that jump, I feel that you should have to start with a pointer to the obj=
ect that they're both subobjects of.<br><br></div><blockquote class=3D"=
gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc so=
lid;padding-left: 1ex;"><div dir=3D"ltr">Whether this would be legal for no=
n-standard-layout types is a separate issue; see <a href=3D"http://www.open=
-std.org/jtc1/sc22/wg21/docs/papers/2017/p0545r0.html" target=3D"_blank" re=
l=3D"nofollow" onmousedown=3D"this.href=3D'http://www.google.com/url?q\=
x3dhttp%3A%2F%2Fwww.open-std.org%2Fjtc1%2Fsc22%2Fwg21%2Fdocs%2Fpapers%2F201=
7%2Fp0545r0.html\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNFalGaDAvn26ATHMR9E=
3IxB2kfbxw';return true;" onclick=3D"this.href=3D'http://www.google=
..com/url?q\x3dhttp%3A%2F%2Fwww.open-std.org%2Fjtc1%2Fsc22%2Fwg21%2Fdocs%2Fp=
apers%2F2017%2Fp0545r0.html\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNFalGaDA=
vn26ATHMR9E3IxB2kfbxw';return true;">http://www.open-std.org/jtc1/<wbr>=
sc22/wg21/docs/papers/2017/<wbr>p0545r0.html</a><br><br>Melissa<br></div></=
blockquote></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/15ba79a9-a1c5-4044-bfcb-0c8cc18ca9a6%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/15ba79a9-a1c5-4044-bfcb-0c8cc18ca9a6=
%40isocpp.org</a>.<br />
------=_Part_1879_2098867981.1497398734867--
------=_Part_1878_1768419833.1497398734867--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Tue, 13 Jun 2017 17:06:12 -0700 (PDT)
Raw View
------=_Part_4557_1337276810.1497398772452
Content-Type: multipart/alternative;
boundary="----=_Part_4558_1842887796.1497398772452"
------=_Part_4558_1842887796.1497398772452
Content-Type: text/plain; charset="UTF-8"
On Tuesday, June 13, 2017 at 8:05:35 PM UTC-4, Nicol Bolas wrote:
>
> Your example doesn't make your use case.
>
"match" your use case. Sorry about that.
--
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 email 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/b2c8e7d5-f7f5-41c0-90a9-d427c6ec5717%40isocpp.org.
------=_Part_4558_1842887796.1497398772452
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Tuesday, June 13, 2017 at 8:05:35 PM UTC-4, Nicol Bolas=
wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.=
8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div>Y=
our example doesn't make your use case.</div></div></blockquote><div><b=
r>"match" your use case. Sorry about that.<br></div></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/b2c8e7d5-f7f5-41c0-90a9-d427c6ec5717%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/b2c8e7d5-f7f5-41c0-90a9-d427c6ec5717=
%40isocpp.org</a>.<br />
------=_Part_4558_1842887796.1497398772452--
------=_Part_4557_1337276810.1497398772452--
.
Author: Myriachan <myriachan@gmail.com>
Date: Wed, 14 Jun 2017 14:53:21 -0700 (PDT)
Raw View
------=_Part_6_23269773.1497477201294
Content-Type: multipart/alternative;
boundary="----=_Part_7_1149393825.1497477201294"
------=_Part_7_1149393825.1497477201294
Content-Type: text/plain; charset="UTF-8"
On Tuesday, June 13, 2017 at 5:05:35 PM UTC-7, Nicol Bolas wrote:
>
> Your example doesn't make your use case. Your use case is specifically
> about accessing a member subobject of the `type` at the `address`. Your
> example however is about jumping from sibling object to sibling object.
>
> In the example, `(&meow->x)` is a pointer to an `int`. The dynamic type of
> that object is `*int*`, not `Meow`. So by your own definition, that
> example would still be UB.
>
>
I don't know the proper word for it, but I meant by "dynamic type" the type
of the top-level container that was constructed at that location. What I'm
saying is that pointer arithmetic on char pointers ought to be well-defined
anywhere within Meow, because Meow is the dynamic type of the entire block
of memory. In my opinion, the two pointers below ought not just compare
equal, but be semantically equal as well, capable of the same range of
pointer arithmetic:
Meow meow;
char *a = reinterpret_cast<char *>(&meow) + offsetof(Meow, y);
char *b = reinterpret_cast<char *>(&meow.y);
assert(a == b); // passes
a -= offsetof(Meow, y); // points to beginning of meow
b -= offsetof(Meow, y); // undefined behavior: b points to beginning
"char array" of size sizeof(int), so subtracting a positive number is out
of range.
Having different semantics for identical pointers of identical type that
compare equal seems broken to me, and would be fixed by what I'm proposing.
If you want something that makes your `CONTAINING_RECORD` work, then what
> you would say is that converting a `T*` into a byte pointer (ie: either
> `char*`, `unsigned char*`, or `std::byte*`) means that you are pointing to
> the beginning of an array of bytes, the size of which is `sizeof(T)`, the
> array storing the object representation of that `T`.
>
>
That's exactly what I'm proposing: when you drop to the level of byte
pointers, the structure concept degenerates to a byte array of the dynamic
type.
Note that CONTAINING_RECORD is a Microsoft macro and not my invention.
It's more or less required in order to make use of the lockless linked
lists in Windows NT (InterlockedPushEntrySList and friends). The actual
Windows macro uses C casts, but is the same idea.
> But if you want your `GoodReadY` to work, then you have to do something
> different. You have to say that converting a pointer to a `T*` into a byte
> pointer gives you a pointer into the *middle* of an array of bytes (or at
> least potentially the middle). The size of the array and location of that
> pointer within the array depend on the size of the outermost containing
> class and the location of that subobject within the container. That's not
> merely the "dynamic type" of what you're casting from.
>
> Personally, I much prefer the former to the latter. I don't like the idea
> of being able to jump from sibling subobject to sibling subobject. If you
> want to make that jump, I feel that you should have to start with a pointer
> to the object that they're both subobjects of.
>
>
The reason for the change is to make well-defined certain programming
styles that exist today, and resolve some inconsistencies in the Standard
regarding object lifetime and pointer arithmetic. Many customized memory
allocators today are currently exploiting undefined behavior because they
do the classic trick of storing memory management headers prior to the
logical memory block. Subtracting from a pointer to the logical object is
undefined behavior under the current rules, simply because of how the
pointer was derived.
To resolve that, we can simply say that byte pointers are allowed to
traverse within any block of allocated storage.
Melissa
--
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 email 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/86bf1a8b-d6d2-48ce-94d1-0646c38eef7e%40isocpp.org.
------=_Part_7_1149393825.1497477201294
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Tuesday, June 13, 2017 at 5:05:35 PM UTC-7, Nicol Bolas=
wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.=
8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr">Your e=
xample doesn't make your use case. Your use case is specifically about =
accessing a member subobject of the `type` at the `address`. Your example h=
owever is about jumping from sibling object to sibling object.<br><div><br>=
In the example, `(&meow->x)` is a pointer to an `int`. The dynamic t=
ype of that object is `<b>int</b>`, not `Meow`. So by your own definition, =
that example would still be UB.<br><br></div></div></blockquote><div><br>I =
don't know the proper word for it, but I meant by "dynamic type&qu=
ot; the type of the top-level container that was constructed at that locati=
on.=C2=A0 What I'm saying is that pointer arithmetic on char pointers o=
ught to be well-defined anywhere within Meow, because Meow is the dynamic t=
ype of the entire block of memory.=C2=A0 In my opinion, the two pointers be=
low ought not just compare equal, but be semantically equal as well, capabl=
e of the same range of pointer arithmetic:<br><br>Meow meow;<br>char *a =3D=
reinterpret_cast<char *>(&meow) + offsetof(Meow, y);<br>char *b =
=3D reinterpret_cast<char *>(&meow.y);<br>assert(a =3D=3D b);=C2=
=A0=C2=A0 // passes<br>a -=3D offsetof(Meow, y);=C2=A0=C2=A0 // points to b=
eginning of meow<br>b -=3D offsetof(Meow, y);=C2=A0=C2=A0 // undefined beha=
vior: b points to beginning "char array" of size sizeof(int), so =
subtracting a positive number is out of range.<br><br>Having different sema=
ntics for identical pointers of identical type that compare equal seems bro=
ken to me, and would be fixed by what I'm proposing.<br><br></div><bloc=
kquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-l=
eft: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div>If you want s=
omething that makes your `CONTAINING_RECORD` work, then what you would say =
is that converting a `T*` into a byte pointer (ie: either `char*`, `unsigne=
d char*`, or `std::byte*`) means that you are pointing to the beginning of =
an array of bytes, the size of which is `sizeof(T)`, the array storing the =
object representation of that `T`.<br><br></div></div></blockquote><div><br=
>That's exactly what I'm proposing: when you drop to the level of b=
yte pointers, the structure concept degenerates to a byte array of the dyna=
mic type.<br><br>Note that CONTAINING_RECORD is a Microsoft macro and not m=
y invention.=C2=A0 It's more or less required in order to make use of t=
he lockless linked lists in Windows NT (InterlockedPushEntrySList and frien=
ds).=C2=A0 The actual Windows macro uses C casts, but is the same idea.<br>=
=C2=A0<br></div><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin=
-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"lt=
r"><div>But if you want your `GoodReadY` to work, then you have to do somet=
hing different. You have to say that converting a pointer to a `T*` into a =
byte pointer gives you a pointer into the <i>middle</i> of an array of byte=
s (or at least potentially the middle). The size of the array and location =
of that pointer within the array depend on the size of the outermost contai=
ning class and the location of that subobject within the container. That=
9;s not merely the "dynamic type" of what you're casting from=
..<br><br>Personally, I much prefer the former to the latter. I don't li=
ke the idea of being able to jump from sibling subobject to sibling subobje=
ct. If you want to make that jump, I feel that you should have to start wit=
h a pointer to the object that they're both subobjects of.</div><br></d=
iv></blockquote><div><br>The reason for the change is to make well-defined =
certain programming styles that exist today, and resolve some inconsistenci=
es in the Standard regarding object lifetime and pointer arithmetic.=C2=A0 =
Many customized memory allocators today are currently exploiting undefined =
behavior because they do the classic trick of storing memory management hea=
ders prior to the logical memory block.=C2=A0 Subtracting from a pointer to=
the logical object is undefined behavior under the current rules, simply b=
ecause of how the pointer was derived.<br><br>To resolve that, we can simpl=
y say that byte pointers are allowed to traverse within any block of alloca=
ted storage.<br><br>Melissa<br></div></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/86bf1a8b-d6d2-48ce-94d1-0646c38eef7e%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/86bf1a8b-d6d2-48ce-94d1-0646c38eef7e=
%40isocpp.org</a>.<br />
------=_Part_7_1149393825.1497477201294--
------=_Part_6_23269773.1497477201294--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Thu, 15 Jun 2017 08:14:22 -0700 (PDT)
Raw View
------=_Part_485_1291009857.1497539662105
Content-Type: multipart/alternative;
boundary="----=_Part_486_1745515808.1497539662107"
------=_Part_486_1745515808.1497539662107
Content-Type: text/plain; charset="UTF-8"
On Wednesday, June 14, 2017 at 5:53:21 PM UTC-4, Myriachan wrote:
>
> On Tuesday, June 13, 2017 at 5:05:35 PM UTC-7, Nicol Bolas wrote:
>>
>> Your example doesn't make your use case. Your use case is specifically
>> about accessing a member subobject of the `type` at the `address`. Your
>> example however is about jumping from sibling object to sibling object.
>>
>> In the example, `(&meow->x)` is a pointer to an `int`. The dynamic type
>> of that object is `*int*`, not `Meow`. So by your own definition, that
>> example would still be UB.
>>
>>
> I don't know the proper word for it, but I meant by "dynamic type" the
> type of the top-level container that was constructed at that location.
> What I'm saying is that pointer arithmetic on char pointers ought to be
> well-defined anywhere within Meow, because Meow is the dynamic type of the
> entire block of memory. In my opinion, the two pointers below ought not
> just compare equal, but be semantically equal as well, capable of the same
> range of pointer arithmetic:
>
> Meow meow;
> char *a = reinterpret_cast<char *>(&meow) + offsetof(Meow, y);
> char *b = reinterpret_cast<char *>(&meow.y);
> assert(a == b); // passes
> a -= offsetof(Meow, y); // points to beginning of meow
> b -= offsetof(Meow, y); // undefined behavior: b points to beginning
> "char array" of size sizeof(int), so subtracting a positive number is out
> of range.
>
> Having different semantics for identical pointers of identical type that
> compare equal seems broken to me, and would be fixed by what I'm proposing.
>
> If you want something that makes your `CONTAINING_RECORD` work, then what
>> you would say is that converting a `T*` into a byte pointer (ie: either
>> `char*`, `unsigned char*`, or `std::byte*`) means that you are pointing to
>> the beginning of an array of bytes, the size of which is `sizeof(T)`, the
>> array storing the object representation of that `T`.
>>
>>
> That's exactly what I'm proposing: when you drop to the level of byte
> pointers, the structure concept degenerates to a byte array of the dynamic
> type.
>
But that's *not* what you're proposing. You just said so: "I meant by
"dynamic type" the type of the top-level container that was constructed at
that location." The description I gave defined the boundary of the byte
array based on the object you cast from. So if you start with a `int*`, and
you cast it to a byte pointer, then it can *only* be moved around within
`sizeof(T)`.
Note that CONTAINING_RECORD is a Microsoft macro and not my invention.
> It's more or less required in order to make use of the lockless linked
> lists in Windows NT (InterlockedPushEntrySList and friends). The actual
> Windows macro uses C casts, but is the same idea.
>
>
>> But if you want your `GoodReadY` to work, then you have to do something
>> different. You have to say that converting a pointer to a `T*` into a byte
>> pointer gives you a pointer into the *middle* of an array of bytes (or
>> at least potentially the middle). The size of the array and location of
>> that pointer within the array depend on the size of the outermost
>> containing class and the location of that subobject within the container.
>> That's not merely the "dynamic type" of what you're casting from.
>>
>> Personally, I much prefer the former to the latter. I don't like the idea
>> of being able to jump from sibling subobject to sibling subobject. If you
>> want to make that jump, I feel that you should have to start with a pointer
>> to the object that they're both subobjects of.
>>
>>
> The reason for the change is to make well-defined certain programming
> styles that exist today, and resolve some inconsistencies in the Standard
> regarding object lifetime and pointer arithmetic. Many customized memory
> allocators today are currently exploiting undefined behavior because they
> do the classic trick of storing memory management headers prior to the
> logical memory block. Subtracting from a pointer to the logical object is
> undefined behavior under the current rules, simply because of how the
> pointer was derived.
>
> To resolve that, we can simply say that byte pointers are allowed to
> traverse within any block of allocated storage.
>
And that's not what you just said. Again, "I meant by "dynamic type" the
type of the top-level container that was constructed at that location."
That's not "any block of allocated storage". In just this one post, you've
explained 3 completely different ideas of what you want: pointer arithmetic
within the type the pointer was when cast to a byte, pointer arithmetic
within the "top-level container" object, and pointer arithmetic within "any
block of allocated storage". These are not the same things.
Note: I'm not arguing against the idea. I'm trying to figure out what the
scope of the feature you really want is supposed to be.
Consider the following code:
struct X
{
float a;
int b;
};
struct Y
{
float q;
X r;
};
struct Z
{
X x;
Y y;
};
void func1()
{
auto mem = new std::aligned_union_t<X>;
auto x_ptr = new(mem) X;
auto byte_ptr = reinterpret_cast<std::byte*>(&x_ptr);
byte_ptr += offsetof(X, b);
auto b_ptr = reinterpret_cast<int*>(byte_ptr);
*b_ptr = 5;
x_ptr->b = 10;
assert(*b_ptr == x_ptr->b); //Always true.
}
void func2()
{
auto mem = new std::aligned_union_t<X>;
auto x_ptr = new(mem) X;
auto byte_ptr = reinterpret_cast<std::byte*>(&x_ptr.a);
byte_ptr -= offsetof(X, a);
byte_ptr += offsetof(X, b);
auto b_ptr = reinterpret_cast<int*>(byte_ptr);
*b_ptr = 5;
x_ptr->b = 10;
assert(*b_ptr == x_ptr->b); //Always true.
}
void func3()
{
//Creates two independent objects in the same allocation.
//Does not actually construct a Z.
auto mem = new std::aligned_union_t<Z>;
auto mem_ptr = reinterpret_cast<std::byte*>(mem);
auto x_ptr = new(mem_ptr + offsetof(Z, x)) X;
auto y_ptr = new(mem_ptr + offsetof(Z, y)) Y;
auto byte_ptr = reinterpret_cast<std::byte*>(&x_ptr);
byte_ptr -= offsetof(Z, x);
byte_ptr += offsetof(Z, y);
byte_ptr += offsetof(Y, r);
byte_ptr += offsetof(X, b);
auto b_ptr = reinterpret_cast<int*>(byte_ptr);
*b_ptr = 5;
y_ptr->r.b = 10;
assert(*b_ptr == y_ptr->r.b); //Always true.
}
Which of these functions do you want to work? If you want all of them to
work, then what you're talking about that "block of allocated storage"
thing. That means that byte pointer arithmetic should act as though the
entire allocation were a byte array. And casting to a byte pointer means
getting a pointer to an element in the array.
Note that when I say "byte pointer", I mean any of the three byte types,
not just `std::byte`.
--
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 email 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/5b71dba8-ce50-4134-9f8d-1d022fa22df3%40isocpp.org.
------=_Part_486_1745515808.1497539662107
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Wednesday, June 14, 2017 at 5:53:21 PM UTC-4, Myriachan=
wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.=
8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr">On Tue=
sday, June 13, 2017 at 5:05:35 PM UTC-7, Nicol Bolas wrote:<blockquote clas=
s=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc =
solid;padding-left:1ex"><div dir=3D"ltr">Your example doesn't make your=
use case. Your use case is specifically about accessing a member subobject=
of the `type` at the `address`. Your example however is about jumping from=
sibling object to sibling object.<br><div><br>In the example, `(&meow-=
>x)` is a pointer to an `int`. The dynamic type of that object is `<b>in=
t</b>`, not `Meow`. So by your own definition, that example would still be =
UB.<br><br></div></div></blockquote><div><br>I don't know the proper wo=
rd for it, but I meant by "dynamic type" the type of the top-leve=
l container that was constructed at that location.=C2=A0 What I'm sayin=
g is that pointer arithmetic on char pointers ought to be well-defined anyw=
here within Meow, because Meow is the dynamic type of the entire block of m=
emory.=C2=A0 In my opinion, the two pointers below ought not just compare e=
qual, but be semantically equal as well, capable of the same range of point=
er arithmetic:<br><br>Meow meow;<br>char *a =3D reinterpret_cast<char *&=
gt;(&meow) + offsetof(Meow, y);<br>char *b =3D reinterpret_cast<char=
*>(&meow.y);<br>assert(a =3D=3D b);=C2=A0=C2=A0 // passes<br>a -=3D=
offsetof(Meow, y);=C2=A0=C2=A0 // points to beginning of meow<br>b -=3D of=
fsetof(Meow, y);=C2=A0=C2=A0 // undefined behavior: b points to beginning &=
quot;char array" of size sizeof(int), so subtracting a positive number=
is out of range.<br><br>Having different semantics for identical pointers =
of identical type that compare equal seems broken to me, and would be fixed=
by what I'm proposing.<br><br></div><blockquote class=3D"gmail_quote" =
style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left=
:1ex"><div dir=3D"ltr"><div>If you want something that makes your `CONTAINI=
NG_RECORD` work, then what you would say is that converting a `T*` into a b=
yte pointer (ie: either `char*`, `unsigned char*`, or `std::byte*`) means t=
hat you are pointing to the beginning of an array of bytes, the size of whi=
ch is `sizeof(T)`, the array storing the object representation of that `T`.=
<br><br></div></div></blockquote><div><br>That's exactly what I'm p=
roposing: when you drop to the level of byte pointers, the structure concep=
t degenerates to a byte array of the dynamic type.<br></div></div></blockqu=
ote><div><br>But that's <i>not</i> what you're proposing. You just =
said so: "I meant by "dynamic type" the type of the top-leve=
l container that was constructed at that location." The description I =
gave defined the boundary of the byte array based on the object you cast fr=
om. So if you start with a `int*`, and you cast it to a byte pointer, then =
it can <i>only</i> be moved around within `sizeof(T)`.<br><br></div><blockq=
uote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-lef=
t: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div>Note that CONTA=
INING_RECORD is a Microsoft macro and not my invention.=C2=A0 It's more=
or less required in order to make use of the lockless linked lists in Wind=
ows NT (InterlockedPushEntrySList and friends).=C2=A0 The actual Windows ma=
cro uses C casts, but is the same idea.<br>=C2=A0<br></div><blockquote clas=
s=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc =
solid;padding-left:1ex"><div dir=3D"ltr"><div>But if you want your `GoodRea=
dY` to work, then you have to do something different. You have to say that =
converting a pointer to a `T*` into a byte pointer gives you a pointer into=
the <i>middle</i> of an array of bytes (or at least potentially the middle=
). The size of the array and location of that pointer within the array depe=
nd on the size of the outermost containing class and the location of that s=
ubobject within the container. That's not merely the "dynamic type=
" of what you're casting from.<br><br>Personally, I much prefer th=
e former to the latter. I don't like the idea of being able to jump fro=
m sibling subobject to sibling subobject. If you want to make that jump, I =
feel that you should have to start with a pointer to the object that they&#=
39;re both subobjects of.</div><br></div></blockquote><div><br>The reason f=
or the change is to make well-defined certain programming styles that exist=
today, and resolve some inconsistencies in the Standard regarding object l=
ifetime and pointer arithmetic.=C2=A0 Many customized memory allocators tod=
ay are currently exploiting undefined behavior because they do the classic =
trick of storing memory management headers prior to the logical memory bloc=
k.=C2=A0 Subtracting from a pointer to the logical object is undefined beha=
vior under the current rules, simply because of how the pointer was derived=
..<br><br>To resolve that, we can simply say that byte pointers are allowed =
to traverse within any block of allocated storage.<br></div></div></blockqu=
ote><div><br>And that's not what you just said. Again, "I meant by=
"dynamic type" the type of the top-level container that was cons=
tructed at that location." That's not "any block of allocated=
storage". In just this one post, you've explained 3 completely di=
fferent ideas of what you want: pointer arithmetic within the type the poin=
ter was when cast to a byte, pointer arithmetic within the "top-level =
container" object, and pointer arithmetic within "any block of al=
located storage". These are not the same things.<br><br>Note: I'm =
not arguing against the idea. I'm trying to figure out what=20
the scope of the feature you really want is supposed to be.<br><br>Consider=
the following code:<br><br><div style=3D"background-color: rgb(250, 250, 2=
50); border-color: rgb(187, 187, 187); border-style: solid; border-width: 1=
px; overflow-wrap: break-word;" class=3D"prettyprint"><code class=3D"pretty=
print"><div class=3D"subprettyprint"><span style=3D"color: #008;" class=3D"=
styled-by-prettify">struct</span><span style=3D"color: #000;" class=3D"styl=
ed-by-prettify"> X<br></span><span style=3D"color: #660;" class=3D"styled-b=
y-prettify">{</span><span style=3D"color: #000;" class=3D"styled-by-prettif=
y"><br>=C2=A0 =C2=A0 </span><span style=3D"color: #008;" class=3D"styled-by=
-prettify">float</span><span style=3D"color: #000;" class=3D"styled-by-pret=
tify"> a</span><span style=3D"color: #660;" class=3D"styled-by-prettify">;<=
/span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =
=C2=A0 </span><span style=3D"color: #008;" class=3D"styled-by-prettify">int=
</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> b</span><=
span style=3D"color: #660;" class=3D"styled-by-prettify">;</span><span styl=
e=3D"color: #000;" class=3D"styled-by-prettify"><br></span><span style=3D"c=
olor: #660;" class=3D"styled-by-prettify">};</span><span style=3D"color: #0=
00;" class=3D"styled-by-prettify"><br><br></span><span style=3D"color: #008=
;" class=3D"styled-by-prettify">struct</span><span style=3D"color: #000;" c=
lass=3D"styled-by-prettify"> Y<br></span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">{</span><span style=3D"color: #000;" class=3D"style=
d-by-prettify"><br>=C2=A0 =C2=A0 </span><span style=3D"color: #008;" class=
=3D"styled-by-prettify">float</span><span style=3D"color: #000;" class=3D"s=
tyled-by-prettify"> q</span><span style=3D"color: #660;" class=3D"styled-by=
-prettify">;</span><span style=3D"color: #000;" class=3D"styled-by-prettify=
"><br>=C2=A0 =C2=A0 X r</span><span style=3D"color: #660;" class=3D"styled-=
by-prettify">;</span><span style=3D"color: #000;" class=3D"styled-by-pretti=
fy"><br></span><span style=3D"color: #660;" class=3D"styled-by-prettify">};=
</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br><br></=
span><span style=3D"color: #008;" class=3D"styled-by-prettify">struct</span=
><span style=3D"color: #000;" class=3D"styled-by-prettify"> Z<br></span><sp=
an style=3D"color: #660;" class=3D"styled-by-prettify">{</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 X x</span>=
<span style=3D"color: #660;" class=3D"styled-by-prettify">;</span><span sty=
le=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 Y y</spa=
n><span style=3D"color: #660;" class=3D"styled-by-prettify">;</span><span s=
tyle=3D"color: #000;" class=3D"styled-by-prettify"><br></span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">};</span><span style=3D"colo=
r: #000;" class=3D"styled-by-prettify"><br><br></span><span style=3D"color:=
#008;" class=3D"styled-by-prettify">void</span><span style=3D"color: #000;=
" class=3D"styled-by-prettify"> func1</span><span style=3D"color: #660;" cl=
ass=3D"styled-by-prettify">()</span><span style=3D"color: #000;" class=3D"s=
tyled-by-prettify"><br></span><span style=3D"color: #660;" class=3D"styled-=
by-prettify">{</span><span style=3D"color: #000;" class=3D"styled-by-pretti=
fy"><br>=C2=A0 =C2=A0 </span><span style=3D"color: #008;" class=3D"styled-b=
y-prettify">auto</span><span style=3D"color: #000;" class=3D"styled-by-pret=
tify"> mem </span><span style=3D"color: #660;" class=3D"styled-by-prettify"=
>=3D</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </spa=
n><span style=3D"color: #008;" class=3D"styled-by-prettify">new</span><span=
style=3D"color: #000;" class=3D"styled-by-prettify"> std</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">::</span><span style=3D"colo=
r: #000;" class=3D"styled-by-prettify">aligned_union_t</span><span style=3D=
"color: #660;" class=3D"styled-by-prettify"><</span><span style=3D"color=
: #000;" class=3D"styled-by-prettify">X</span><span style=3D"color: #660;" =
class=3D"styled-by-prettify">>;</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 </span><span style=3D"color: #008=
;" class=3D"styled-by-prettify">auto</span><span style=3D"color: #000;" cla=
ss=3D"styled-by-prettify"> x_ptr </span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">=3D</span><span style=3D"color: #000;" class=3D"sty=
led-by-prettify"> </span><span style=3D"color: #008;" class=3D"styled-by-pr=
ettify">new</span><span style=3D"color: #660;" class=3D"styled-by-prettify"=
>(</span><span style=3D"color: #000;" class=3D"styled-by-prettify">mem</spa=
n><span style=3D"color: #660;" class=3D"styled-by-prettify">)</span><span s=
tyle=3D"color: #000;" class=3D"styled-by-prettify"> X</span><span style=3D"=
color: #660;" class=3D"styled-by-prettify">;</span><span style=3D"color: #0=
00;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 <br>=C2=A0 =C2=A0 </spa=
n><span style=3D"color: #008;" class=3D"styled-by-prettify">auto</span><spa=
n style=3D"color: #000;" class=3D"styled-by-prettify"> byte_ptr </span><spa=
n style=3D"color: #660;" class=3D"styled-by-prettify">=3D</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color=
: #008;" class=3D"styled-by-prettify">reinterpret_cast</span><span style=3D=
"color: #660;" class=3D"styled-by-prettify"><</span><span style=3D"color=
: #000;" class=3D"styled-by-prettify">std</span><span style=3D"color: #660;=
" class=3D"styled-by-prettify">::</span><span style=3D"color: #008;" class=
=3D"styled-by-prettify">byte</span><span style=3D"color: #660;" class=3D"st=
yled-by-prettify">*>(&</span><span style=3D"color: #000;" class=3D"s=
tyled-by-prettify">x_ptr</span><span style=3D"color: #660;" class=3D"styled=
-by-prettify">);</span><span style=3D"color: #000;" class=3D"styled-by-pret=
tify"><br>=C2=A0 =C2=A0 byte_ptr </span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">+=3D</span><span style=3D"color: #000;" class=3D"st=
yled-by-prettify"> offsetof</span><span style=3D"color: #660;" class=3D"sty=
led-by-prettify">(</span><span style=3D"color: #000;" class=3D"styled-by-pr=
ettify">X</span><span style=3D"color: #660;" class=3D"styled-by-prettify">,=
</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> b</span><=
span style=3D"color: #660;" class=3D"styled-by-prettify">);</span><span sty=
le=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 </span><=
span style=3D"color: #008;" class=3D"styled-by-prettify">auto</span><span s=
tyle=3D"color: #000;" class=3D"styled-by-prettify"> b_ptr </span><span styl=
e=3D"color: #660;" class=3D"styled-by-prettify">=3D</span><span style=3D"co=
lor: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #008=
;" class=3D"styled-by-prettify">reinterpret_cast</span><span style=3D"color=
: #660;" class=3D"styled-by-prettify"><</span><span style=3D"color: #008=
;" class=3D"styled-by-prettify">int</span><span style=3D"color: #660;" clas=
s=3D"styled-by-prettify">*>(</span><span style=3D"color: #000;" class=3D=
"styled-by-prettify">byte_ptr</span><span style=3D"color: #660;" class=3D"s=
tyled-by-prettify">);</span><span style=3D"color: #000;" class=3D"styled-by=
-prettify"><br><br>=C2=A0 =C2=A0 </span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">*</span><span style=3D"color: #000;" class=3D"style=
d-by-prettify">b_ptr </span><span style=3D"color: #660;" class=3D"styled-by=
-prettify">=3D</span><span style=3D"color: #000;" class=3D"styled-by-pretti=
fy"> </span><span style=3D"color: #066;" class=3D"styled-by-prettify">5</sp=
an><span style=3D"color: #660;" class=3D"styled-by-prettify">;</span><span =
style=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 x_ptr=
</span><span style=3D"color: #660;" class=3D"styled-by-prettify">-></spa=
n><span style=3D"color: #000;" class=3D"styled-by-prettify">b </span><span =
style=3D"color: #660;" class=3D"styled-by-prettify">=3D</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color=
: #066;" class=3D"styled-by-prettify">10</span><span style=3D"color: #660;"=
class=3D"styled-by-prettify">;</span><span style=3D"color: #000;" class=3D=
"styled-by-prettify"><br>=C2=A0 =C2=A0 </span><span style=3D"color: #008;" =
class=3D"styled-by-prettify">assert</span><span style=3D"color: #660;" clas=
s=3D"styled-by-prettify">(*</span><span style=3D"color: #000;" class=3D"sty=
led-by-prettify">b_ptr </span><span style=3D"color: #660;" class=3D"styled-=
by-prettify">=3D=3D</span><span style=3D"color: #000;" class=3D"styled-by-p=
rettify"> x_ptr</span><span style=3D"color: #660;" class=3D"styled-by-prett=
ify">-></span><span style=3D"color: #000;" class=3D"styled-by-prettify">=
b</span><span style=3D"color: #660;" class=3D"styled-by-prettify">);</span>=
<span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span sty=
le=3D"color: #800;" class=3D"styled-by-prettify">//Always true.</span><span=
style=3D"color: #000;" class=3D"styled-by-prettify"><br></span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">}</span><span style=3D"color=
: #000;" class=3D"styled-by-prettify"><br><br></span><span style=3D"color: =
#008;" class=3D"styled-by-prettify">void</span><span style=3D"color: #000;"=
class=3D"styled-by-prettify"> func2</span><span style=3D"color: #660;" cla=
ss=3D"styled-by-prettify">()</span><span style=3D"color: #000;" class=3D"st=
yled-by-prettify"><br></span><span style=3D"color: #660;" class=3D"styled-b=
y-prettify">{</span><span style=3D"color: #000;" class=3D"styled-by-prettif=
y"><br>=C2=A0 =C2=A0 </span><span style=3D"color: #008;" class=3D"styled-by=
-prettify">auto</span><span style=3D"color: #000;" class=3D"styled-by-prett=
ify"> mem </span><span style=3D"color: #660;" class=3D"styled-by-prettify">=
=3D</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span=
><span style=3D"color: #008;" class=3D"styled-by-prettify">new</span><span =
style=3D"color: #000;" class=3D"styled-by-prettify"> std</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">::</span><span style=3D"colo=
r: #000;" class=3D"styled-by-prettify">aligned_union_t</span><span style=3D=
"color: #660;" class=3D"styled-by-prettify"><</span><span style=3D"color=
: #000;" class=3D"styled-by-prettify">X</span><span style=3D"color: #660;" =
class=3D"styled-by-prettify">>;</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 </span><span style=3D"color: #008=
;" class=3D"styled-by-prettify">auto</span><span style=3D"color: #000;" cla=
ss=3D"styled-by-prettify"> x_ptr </span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">=3D</span><span style=3D"color: #000;" class=3D"sty=
led-by-prettify"> </span><span style=3D"color: #008;" class=3D"styled-by-pr=
ettify">new</span><span style=3D"color: #660;" class=3D"styled-by-prettify"=
>(</span><span style=3D"color: #000;" class=3D"styled-by-prettify">mem</spa=
n><span style=3D"color: #660;" class=3D"styled-by-prettify">)</span><span s=
tyle=3D"color: #000;" class=3D"styled-by-prettify"> X</span><span style=3D"=
color: #660;" class=3D"styled-by-prettify">;</span><span style=3D"color: #0=
00;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 <br>=C2=A0 =C2=A0 </spa=
n><span style=3D"color: #008;" class=3D"styled-by-prettify">auto</span><spa=
n style=3D"color: #000;" class=3D"styled-by-prettify"> byte_ptr </span><spa=
n style=3D"color: #660;" class=3D"styled-by-prettify">=3D</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color=
: #008;" class=3D"styled-by-prettify">reinterpret_cast</span><span style=3D=
"color: #660;" class=3D"styled-by-prettify"><</span><span style=3D"color=
: #000;" class=3D"styled-by-prettify">std</span><span style=3D"color: #660;=
" class=3D"styled-by-prettify">::</span><span style=3D"color: #008;" class=
=3D"styled-by-prettify">byte</span><span style=3D"color: #660;" class=3D"st=
yled-by-prettify">*>(&</span><span style=3D"color: #000;" class=3D"s=
tyled-by-prettify">x_ptr</span><span style=3D"color: #660;" class=3D"styled=
-by-prettify">.</span><span style=3D"color: #000;" class=3D"styled-by-prett=
ify">a</span><span style=3D"color: #660;" class=3D"styled-by-prettify">);</=
span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =
=C2=A0 byte_ptr </span><span style=3D"color: #660;" class=3D"styled-by-pret=
tify">-=3D</span><span style=3D"color: #000;" class=3D"styled-by-prettify">=
offsetof</span><span style=3D"color: #660;" class=3D"styled-by-prettify">(=
</span><span style=3D"color: #000;" class=3D"styled-by-prettify">X</span><s=
pan style=3D"color: #660;" class=3D"styled-by-prettify">,</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"> a</span><span style=3D"colo=
r: #660;" class=3D"styled-by-prettify">);</span><span style=3D"color: #000;=
" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 byte_ptr </span><span styl=
e=3D"color: #660;" class=3D"styled-by-prettify">+=3D</span><span style=3D"c=
olor: #000;" class=3D"styled-by-prettify"> offsetof</span><span style=3D"co=
lor: #660;" class=3D"styled-by-prettify">(</span><span style=3D"color: #000=
;" class=3D"styled-by-prettify">X</span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">,</span><span style=3D"color: #000;" class=3D"style=
d-by-prettify"> b</span><span style=3D"color: #660;" class=3D"styled-by-pre=
ttify">);</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><=
br>=C2=A0 =C2=A0 </span><span style=3D"color: #008;" class=3D"styled-by-pre=
ttify">auto</span><span style=3D"color: #000;" class=3D"styled-by-prettify"=
> b_ptr </span><span style=3D"color: #660;" class=3D"styled-by-prettify">=
=3D</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span=
><span style=3D"color: #008;" class=3D"styled-by-prettify">reinterpret_cast=
</span><span style=3D"color: #660;" class=3D"styled-by-prettify"><</span=
><span style=3D"color: #008;" class=3D"styled-by-prettify">int</span><span =
style=3D"color: #660;" class=3D"styled-by-prettify">*>(</span><span styl=
e=3D"color: #000;" class=3D"styled-by-prettify">byte_ptr</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">);</span><span style=3D"colo=
r: #000;" class=3D"styled-by-prettify"><br><br>=C2=A0 =C2=A0 </span><span s=
tyle=3D"color: #660;" class=3D"styled-by-prettify">*</span><span style=3D"c=
olor: #000;" class=3D"styled-by-prettify">b_ptr </span><span style=3D"color=
: #660;" class=3D"styled-by-prettify">=3D</span><span style=3D"color: #000;=
" class=3D"styled-by-prettify"> </span><span style=3D"color: #066;" class=
=3D"styled-by-prettify">5</span><span style=3D"color: #660;" class=3D"style=
d-by-prettify">;</span><span style=3D"color: #000;" class=3D"styled-by-pret=
tify"><br>=C2=A0 =C2=A0 x_ptr</span><span style=3D"color: #660;" class=3D"s=
tyled-by-prettify">-></span><span style=3D"color: #000;" class=3D"styled=
-by-prettify">b </span><span style=3D"color: #660;" class=3D"styled-by-pret=
tify">=3D</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> =
</span><span style=3D"color: #066;" class=3D"styled-by-prettify">10</span><=
span style=3D"color: #660;" class=3D"styled-by-prettify">;</span><span styl=
e=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 </span><s=
pan style=3D"color: #008;" class=3D"styled-by-prettify">assert</span><span =
style=3D"color: #660;" class=3D"styled-by-prettify">(*</span><span style=3D=
"color: #000;" class=3D"styled-by-prettify">b_ptr </span><span style=3D"col=
or: #660;" class=3D"styled-by-prettify">=3D=3D</span><span style=3D"color: =
#000;" class=3D"styled-by-prettify"> x_ptr</span><span style=3D"color: #660=
;" class=3D"styled-by-prettify">-></span><span style=3D"color: #000;" cl=
ass=3D"styled-by-prettify">b</span><span style=3D"color: #660;" class=3D"st=
yled-by-prettify">);</span><span style=3D"color: #000;" class=3D"styled-by-=
prettify"> </span><span style=3D"color: #800;" class=3D"styled-by-prettify"=
>//Always true.</span><span style=3D"color: #000;" class=3D"styled-by-prett=
ify"><br></span><span style=3D"color: #660;" class=3D"styled-by-prettify">}=
</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br><br></=
span><span style=3D"color: #008;" class=3D"styled-by-prettify">void</span><=
span style=3D"color: #000;" class=3D"styled-by-prettify"> func3</span><span=
style=3D"color: #660;" class=3D"styled-by-prettify">()</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"><br></span><span style=3D"co=
lor: #660;" class=3D"styled-by-prettify">{</span><span style=3D"color: #000=
;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 </span><span style=3D"col=
or: #800;" class=3D"styled-by-prettify">//Creates two independent objects i=
n the same allocation.</span><span style=3D"color: #000;" class=3D"styled-b=
y-prettify"><br>=C2=A0 =C2=A0 </span><span style=3D"color: #800;" class=3D"=
styled-by-prettify">//Does not actually construct a Z.</span><span style=3D=
"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 </span><span =
style=3D"color: #008;" class=3D"styled-by-prettify">auto</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"> mem </span><span style=3D"c=
olor: #660;" class=3D"styled-by-prettify">=3D</span><span style=3D"color: #=
000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #008;" cla=
ss=3D"styled-by-prettify">new</span><span style=3D"color: #000;" class=3D"s=
tyled-by-prettify"> std</span><span style=3D"color: #660;" class=3D"styled-=
by-prettify">::</span><span style=3D"color: #000;" class=3D"styled-by-prett=
ify">aligned_union_t</span><span style=3D"color: #660;" class=3D"styled-by-=
prettify"><</span><span style=3D"color: #000;" class=3D"styled-by-pretti=
fy">Z</span><span style=3D"color: #660;" class=3D"styled-by-prettify">>;=
</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0=
=C2=A0 </span><span style=3D"color: #008;" class=3D"styled-by-prettify">au=
to</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> mem_ptr=
</span><span style=3D"color: #660;" class=3D"styled-by-prettify">=3D</span=
><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span st=
yle=3D"color: #008;" class=3D"styled-by-prettify">reinterpret_cast</span><s=
pan style=3D"color: #660;" class=3D"styled-by-prettify"><</span><span st=
yle=3D"color: #000;" class=3D"styled-by-prettify">std</span><span style=3D"=
color: #660;" class=3D"styled-by-prettify">::</span><span style=3D"color: #=
008;" class=3D"styled-by-prettify">byte</span><span style=3D"color: #660;" =
class=3D"styled-by-prettify">*>(</span><span style=3D"color: #000;" clas=
s=3D"styled-by-prettify">mem</span><span style=3D"color: #660;" class=3D"st=
yled-by-prettify">);</span><span style=3D"color: #000;" class=3D"styled-by-=
prettify"><br>=C2=A0 =C2=A0 </span><span style=3D"color: #008;" class=3D"st=
yled-by-prettify">auto</span><span style=3D"color: #000;" class=3D"styled-b=
y-prettify"> x_ptr </span><span style=3D"color: #660;" class=3D"styled-by-p=
rettify">=3D</span><span style=3D"color: #000;" class=3D"styled-by-prettify=
"> </span><span style=3D"color: #008;" class=3D"styled-by-prettify">new</sp=
an><span style=3D"color: #660;" class=3D"styled-by-prettify">(</span><span =
style=3D"color: #000;" class=3D"styled-by-prettify">mem_ptr </span><span st=
yle=3D"color: #660;" class=3D"styled-by-prettify">+</span><span style=3D"co=
lor: #000;" class=3D"styled-by-prettify"> offsetof</span><span style=3D"col=
or: #660;" class=3D"styled-by-prettify">(</span><span style=3D"color: #000;=
" class=3D"styled-by-prettify">Z</span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">,</span><span style=3D"color: #000;" class=3D"style=
d-by-prettify"> x</span><span style=3D"color: #660;" class=3D"styled-by-pre=
ttify">))</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> =
X</span><span style=3D"color: #660;" class=3D"styled-by-prettify">;</span><=
span style=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 =
</span><span style=3D"color: #008;" class=3D"styled-by-prettify">auto</span=
><span style=3D"color: #000;" class=3D"styled-by-prettify"> y_ptr </span><s=
pan style=3D"color: #660;" class=3D"styled-by-prettify">=3D</span><span sty=
le=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"col=
or: #008;" class=3D"styled-by-prettify">new</span><span style=3D"color: #66=
0;" class=3D"styled-by-prettify">(</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify">mem_ptr </span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">+</span><span style=3D"color: #000;" class=3D"style=
d-by-prettify"> offsetof</span><span style=3D"color: #660;" class=3D"styled=
-by-prettify">(</span><span style=3D"color: #000;" class=3D"styled-by-prett=
ify">Z</span><span style=3D"color: #660;" class=3D"styled-by-prettify">,</s=
pan><span style=3D"color: #000;" class=3D"styled-by-prettify"> y</span><spa=
n style=3D"color: #660;" class=3D"styled-by-prettify">))</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"> Y</span><span style=3D"colo=
r: #660;" class=3D"styled-by-prettify">;</span><span style=3D"color: #000;"=
class=3D"styled-by-prettify"><br><br>=C2=A0 =C2=A0 </span><span style=3D"c=
olor: #008;" class=3D"styled-by-prettify">auto</span><span style=3D"color: =
#000;" class=3D"styled-by-prettify"> byte_ptr </span><span style=3D"color: =
#660;" class=3D"styled-by-prettify">=3D</span><span style=3D"color: #000;" =
class=3D"styled-by-prettify"> </span><span style=3D"color: #008;" class=3D"=
styled-by-prettify">reinterpret_cast</span><span style=3D"color: #660;" cla=
ss=3D"styled-by-prettify"><</span><span style=3D"color: #000;" class=3D"=
styled-by-prettify">std</span><span style=3D"color: #660;" class=3D"styled-=
by-prettify">::</span><span style=3D"color: #008;" class=3D"styled-by-prett=
ify">byte</span><span style=3D"color: #660;" class=3D"styled-by-prettify">*=
>(&</span><span style=3D"color: #000;" class=3D"styled-by-prettify">=
x_ptr</span><span style=3D"color: #660;" class=3D"styled-by-prettify">);</s=
pan><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =
=C2=A0 byte_ptr </span><span style=3D"color: #660;" class=3D"styled-by-pret=
tify">-=3D</span><span style=3D"color: #000;" class=3D"styled-by-prettify">=
offsetof</span><span style=3D"color: #660;" class=3D"styled-by-prettify">(=
</span><span style=3D"color: #000;" class=3D"styled-by-prettify">Z</span><s=
pan style=3D"color: #660;" class=3D"styled-by-prettify">,</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"> x</span><span style=3D"colo=
r: #660;" class=3D"styled-by-prettify">);</span><span style=3D"color: #000;=
" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 byte_ptr </span><span styl=
e=3D"color: #660;" class=3D"styled-by-prettify">+=3D</span><span style=3D"c=
olor: #000;" class=3D"styled-by-prettify"> offsetof</span><span style=3D"co=
lor: #660;" class=3D"styled-by-prettify">(</span><span style=3D"color: #000=
;" class=3D"styled-by-prettify">Z</span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">,</span><span style=3D"color: #000;" class=3D"style=
d-by-prettify"> y</span><span style=3D"color: #660;" class=3D"styled-by-pre=
ttify">);</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><=
br>=C2=A0 =C2=A0 byte_ptr </span><span style=3D"color: #660;" class=3D"styl=
ed-by-prettify">+=3D</span><span style=3D"color: #000;" class=3D"styled-by-=
prettify"> offsetof</span><span style=3D"color: #660;" class=3D"styled-by-p=
rettify">(</span><span style=3D"color: #000;" class=3D"styled-by-prettify">=
Y</span><span style=3D"color: #660;" class=3D"styled-by-prettify">,</span><=
span style=3D"color: #000;" class=3D"styled-by-prettify"> r</span><span sty=
le=3D"color: #660;" class=3D"styled-by-prettify">);</span><span style=3D"co=
lor: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 byte_ptr </span>=
<span style=3D"color: #660;" class=3D"styled-by-prettify">+=3D</span><span =
style=3D"color: #000;" class=3D"styled-by-prettify"> offsetof</span><span s=
tyle=3D"color: #660;" class=3D"styled-by-prettify">(</span><span style=3D"c=
olor: #000;" class=3D"styled-by-prettify">X</span><span style=3D"color: #66=
0;" class=3D"styled-by-prettify">,</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"> b</span><span style=3D"color: #660;" class=3D"styl=
ed-by-prettify">);</span><span style=3D"color: #000;" class=3D"styled-by-pr=
ettify"><br>=C2=A0 =C2=A0 </span><span style=3D"color: #008;" class=3D"styl=
ed-by-prettify">auto</span><span style=3D"color: #000;" class=3D"styled-by-=
prettify"> b_ptr </span><span style=3D"color: #660;" class=3D"styled-by-pre=
ttify">=3D</span><span style=3D"color: #000;" class=3D"styled-by-prettify">=
</span><span style=3D"color: #008;" class=3D"styled-by-prettify">reinterpr=
et_cast</span><span style=3D"color: #660;" class=3D"styled-by-prettify"><=
;</span><span style=3D"color: #008;" class=3D"styled-by-prettify">int</span=
><span style=3D"color: #660;" class=3D"styled-by-prettify">*>(</span><sp=
an style=3D"color: #000;" class=3D"styled-by-prettify">byte_ptr</span><span=
style=3D"color: #660;" class=3D"styled-by-prettify">);</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"><br><br>=C2=A0 =C2=A0 </span=
><span style=3D"color: #660;" class=3D"styled-by-prettify">*</span><span st=
yle=3D"color: #000;" class=3D"styled-by-prettify">b_ptr </span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">=3D</span><span style=3D"col=
or: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #066;=
" class=3D"styled-by-prettify">5</span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">;</span><span style=3D"color: #000;" class=3D"style=
d-by-prettify"><br>=C2=A0 =C2=A0 y_ptr</span><span style=3D"color: #660;" c=
lass=3D"styled-by-prettify">-></span><span style=3D"color: #000;" class=
=3D"styled-by-prettify">r</span><span style=3D"color: #660;" class=3D"style=
d-by-prettify">.</span><span style=3D"color: #000;" class=3D"styled-by-pret=
tify">b </span><span style=3D"color: #660;" class=3D"styled-by-prettify">=
=3D</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span=
><span style=3D"color: #066;" class=3D"styled-by-prettify">10</span><span s=
tyle=3D"color: #660;" class=3D"styled-by-prettify">;</span><span style=3D"c=
olor: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 </span><span st=
yle=3D"color: #008;" class=3D"styled-by-prettify">assert</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">(*</span><span style=3D"colo=
r: #000;" class=3D"styled-by-prettify">b_ptr </span><span style=3D"color: #=
660;" class=3D"styled-by-prettify">=3D=3D</span><span style=3D"color: #000;=
" class=3D"styled-by-prettify"> y_ptr</span><span style=3D"color: #660;" cl=
ass=3D"styled-by-prettify">-></span><span style=3D"color: #000;" class=
=3D"styled-by-prettify">r</span><span style=3D"color: #660;" class=3D"style=
d-by-prettify">.</span><span style=3D"color: #000;" class=3D"styled-by-pret=
tify">b</span><span style=3D"color: #660;" class=3D"styled-by-prettify">);<=
/span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><sp=
an style=3D"color: #800;" class=3D"styled-by-prettify">//Always true.</span=
><span style=3D"color: #000;" class=3D"styled-by-prettify"><br></span><span=
style=3D"color: #660;" class=3D"styled-by-prettify">}</span><span style=3D=
"color: #000;" class=3D"styled-by-prettify"><br></span></div></code></div><=
br>Which of these functions do you want to work? If you want all of them to=
work, then what you're talking about that "block of allocated sto=
rage" thing. That means that byte pointer arithmetic should act as tho=
ugh the entire allocation were a byte array. And casting to a byte pointer =
means getting a pointer to an element in the array.<br><br>Note that when I=
say "byte pointer", I mean any of the three byte types, not just=
`std::byte`.<br></div></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/5b71dba8-ce50-4134-9f8d-1d022fa22df3%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/5b71dba8-ce50-4134-9f8d-1d022fa22df3=
%40isocpp.org</a>.<br />
------=_Part_486_1745515808.1497539662107--
------=_Part_485_1291009857.1497539662105--
.
Author: Edward Catmur <ed@catmur.co.uk>
Date: Fri, 16 Jun 2017 01:45:57 -0700 (PDT)
Raw View
------=_Part_1022_930733883.1497602758033
Content-Type: multipart/alternative;
boundary="----=_Part_1023_1886959503.1497602758035"
------=_Part_1023_1886959503.1497602758035
Content-Type: text/plain; charset="UTF-8"
Your proposed feature would inhibit certain optimizations that are
currently performed. For example:
int f(Meow* m, int* i) {
m->x = 42;
reinterpret_cast<Meow*>(reinterpret_cast<char*>(i) -
sizeof(Meow::x))->x = 99; // #1
return m->x;
}
int g() {
Meow m;
return f(&m, &m.y);
}
Since #1 is UB when called from g, the compiler can optimize g to return
42, and indeed icc does so at -O2.
In your motivating example, CONTAINING_RECORD is provided by the vendor so
they can perform whatever magic is necessary to suppress such
optimizations. For other use cases, it is currently permissible to traverse
to a containing object from any of:
* a base class subobject
* a union member subobject of a standard-layout union
* the initial non-static data member of a standard-layout class
The latter two are covered by the pointer-interconvertibility rules (since
P0137r1).
Would it be possible to apply any of the above permitted techniques to your
use cases?
On Thursday, 15 June 2017 16:14:22 UTC+1, Nicol Bolas wrote:
>
> On Wednesday, June 14, 2017 at 5:53:21 PM UTC-4, Myriachan wrote:
>>
>> On Tuesday, June 13, 2017 at 5:05:35 PM UTC-7, Nicol Bolas wrote:
>>>
>>> Your example doesn't make your use case. Your use case is specifically
>>> about accessing a member subobject of the `type` at the `address`. Your
>>> example however is about jumping from sibling object to sibling object.
>>>
>>> In the example, `(&meow->x)` is a pointer to an `int`. The dynamic type
>>> of that object is `*int*`, not `Meow`. So by your own definition, that
>>> example would still be UB.
>>>
>>>
>> I don't know the proper word for it, but I meant by "dynamic type" the
>> type of the top-level container that was constructed at that location.
>> What I'm saying is that pointer arithmetic on char pointers ought to be
>> well-defined anywhere within Meow, because Meow is the dynamic type of the
>> entire block of memory. In my opinion, the two pointers below ought not
>> just compare equal, but be semantically equal as well, capable of the same
>> range of pointer arithmetic:
>>
>> Meow meow;
>> char *a = reinterpret_cast<char *>(&meow) + offsetof(Meow, y);
>> char *b = reinterpret_cast<char *>(&meow.y);
>> assert(a == b); // passes
>> a -= offsetof(Meow, y); // points to beginning of meow
>> b -= offsetof(Meow, y); // undefined behavior: b points to beginning
>> "char array" of size sizeof(int), so subtracting a positive number is out
>> of range.
>>
>> Having different semantics for identical pointers of identical type that
>> compare equal seems broken to me, and would be fixed by what I'm proposing.
>>
>> If you want something that makes your `CONTAINING_RECORD` work, then what
>>> you would say is that converting a `T*` into a byte pointer (ie: either
>>> `char*`, `unsigned char*`, or `std::byte*`) means that you are pointing to
>>> the beginning of an array of bytes, the size of which is `sizeof(T)`, the
>>> array storing the object representation of that `T`.
>>>
>>>
>> That's exactly what I'm proposing: when you drop to the level of byte
>> pointers, the structure concept degenerates to a byte array of the dynamic
>> type.
>>
>
> But that's *not* what you're proposing. You just said so: "I meant by
> "dynamic type" the type of the top-level container that was constructed at
> that location." The description I gave defined the boundary of the byte
> array based on the object you cast from. So if you start with a `int*`, and
> you cast it to a byte pointer, then it can *only* be moved around within
> `sizeof(T)`.
>
> Note that CONTAINING_RECORD is a Microsoft macro and not my invention.
>> It's more or less required in order to make use of the lockless linked
>> lists in Windows NT (InterlockedPushEntrySList and friends). The actual
>> Windows macro uses C casts, but is the same idea.
>>
>>
>>> But if you want your `GoodReadY` to work, then you have to do something
>>> different. You have to say that converting a pointer to a `T*` into a byte
>>> pointer gives you a pointer into the *middle* of an array of bytes (or
>>> at least potentially the middle). The size of the array and location of
>>> that pointer within the array depend on the size of the outermost
>>> containing class and the location of that subobject within the container.
>>> That's not merely the "dynamic type" of what you're casting from.
>>>
>>> Personally, I much prefer the former to the latter. I don't like the
>>> idea of being able to jump from sibling subobject to sibling subobject. If
>>> you want to make that jump, I feel that you should have to start with a
>>> pointer to the object that they're both subobjects of.
>>>
>>>
>> The reason for the change is to make well-defined certain programming
>> styles that exist today, and resolve some inconsistencies in the Standard
>> regarding object lifetime and pointer arithmetic. Many customized memory
>> allocators today are currently exploiting undefined behavior because they
>> do the classic trick of storing memory management headers prior to the
>> logical memory block. Subtracting from a pointer to the logical object is
>> undefined behavior under the current rules, simply because of how the
>> pointer was derived.
>>
>> To resolve that, we can simply say that byte pointers are allowed to
>> traverse within any block of allocated storage.
>>
>
> And that's not what you just said. Again, "I meant by "dynamic type" the
> type of the top-level container that was constructed at that location."
> That's not "any block of allocated storage". In just this one post, you've
> explained 3 completely different ideas of what you want: pointer arithmetic
> within the type the pointer was when cast to a byte, pointer arithmetic
> within the "top-level container" object, and pointer arithmetic within "any
> block of allocated storage". These are not the same things.
>
> Note: I'm not arguing against the idea. I'm trying to figure out what the
> scope of the feature you really want is supposed to be.
>
> Consider the following code:
>
> struct X
> {
> float a;
> int b;
> };
>
> struct Y
> {
> float q;
> X r;
> };
>
> struct Z
> {
> X x;
> Y y;
> };
>
> void func1()
> {
> auto mem = new std::aligned_union_t<X>;
> auto x_ptr = new(mem) X;
>
> auto byte_ptr = reinterpret_cast<std::byte*>(&x_ptr);
> byte_ptr += offsetof(X, b);
> auto b_ptr = reinterpret_cast<int*>(byte_ptr);
>
> *b_ptr = 5;
> x_ptr->b = 10;
> assert(*b_ptr == x_ptr->b); //Always true.
> }
>
> void func2()
> {
> auto mem = new std::aligned_union_t<X>;
> auto x_ptr = new(mem) X;
>
> auto byte_ptr = reinterpret_cast<std::byte*>(&x_ptr.a);
> byte_ptr -= offsetof(X, a);
> byte_ptr += offsetof(X, b);
> auto b_ptr = reinterpret_cast<int*>(byte_ptr);
>
> *b_ptr = 5;
> x_ptr->b = 10;
> assert(*b_ptr == x_ptr->b); //Always true.
> }
>
> void func3()
> {
> //Creates two independent objects in the same allocation.
> //Does not actually construct a Z.
> auto mem = new std::aligned_union_t<Z>;
> auto mem_ptr = reinterpret_cast<std::byte*>(mem);
> auto x_ptr = new(mem_ptr + offsetof(Z, x)) X;
> auto y_ptr = new(mem_ptr + offsetof(Z, y)) Y;
>
> auto byte_ptr = reinterpret_cast<std::byte*>(&x_ptr);
> byte_ptr -= offsetof(Z, x);
> byte_ptr += offsetof(Z, y);
> byte_ptr += offsetof(Y, r);
> byte_ptr += offsetof(X, b);
> auto b_ptr = reinterpret_cast<int*>(byte_ptr);
>
> *b_ptr = 5;
> y_ptr->r.b = 10;
> assert(*b_ptr == y_ptr->r.b); //Always true.
> }
>
> Which of these functions do you want to work? If you want all of them to
> work, then what you're talking about that "block of allocated storage"
> thing. That means that byte pointer arithmetic should act as though the
> entire allocation were a byte array. And casting to a byte pointer means
> getting a pointer to an element in the array.
>
> Note that when I say "byte pointer", I mean any of the three byte types,
> not just `std::byte`.
>
--
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 email 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/58941597-209a-4aa4-aae5-024d2f581666%40isocpp.org.
------=_Part_1023_1886959503.1497602758035
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">Your proposed feature would inhibit certain optimizations =
that are currently performed. For example:<div><br></div><div>int f(Meow* m=
, int* i) {</div><div>=C2=A0 =C2=A0 m->x =3D 42;</div><div>=C2=A0 =C2=A0=
reinterpret_cast<Meow*>(reinterpret_cast<char*>(i) - sizeof(Me=
ow::x))->x =3D 99; // #1</div><div>=C2=A0 =C2=A0 return m->x;<br></di=
v><div>}</div><div>int g() {</div><div>=C2=A0 Meow m;</div><div>=C2=A0 retu=
rn f(&m, &m.y);</div><div>}</div><div><br></div><div>Since #1 is UB=
when called from g, the compiler can optimize g to return 42, and indeed i=
cc does so at -O2.</div><div><br></div><div>In your motivating example, CON=
TAINING_RECORD is provided by the vendor so they can perform whatever magic=
is necessary to suppress such optimizations. For other use cases, it is cu=
rrently permissible to traverse to a containing object from any of:</div><d=
iv>* a base class subobject</div><div>* a union member subobject of a stand=
ard-layout union</div><div>* the initial non-static data member of a standa=
rd-layout class</div><div>The latter two are covered by the pointer-interco=
nvertibility rules (since P0137r1).</div><div><br></div><div>Would it be po=
ssible to apply any of the above permitted techniques to your use cases?</d=
iv><div><br></div><div>On Thursday, 15 June 2017 16:14:22 UTC+1, Nicol Bola=
s wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: =
0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr">On W=
ednesday, June 14, 2017 at 5:53:21 PM UTC-4, Myriachan wrote:<blockquote cl=
ass=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #cc=
c solid;padding-left:1ex"><div dir=3D"ltr">On Tuesday, June 13, 2017 at 5:0=
5:35 PM UTC-7, Nicol Bolas wrote:<blockquote class=3D"gmail_quote" style=3D=
"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><d=
iv dir=3D"ltr">Your example doesn't make your use case. Your use case i=
s specifically about accessing a member subobject of the `type` at the `add=
ress`. Your example however is about jumping from sibling object to sibling=
object.<br><div><br>In the example, `(&meow->x)` is a pointer to an=
`int`. The dynamic type of that object is `<b>int</b>`, not `Meow`. So by =
your own definition, that example would still be UB.<br><br></div></div></b=
lockquote><div><br>I don't know the proper word for it, but I meant by =
"dynamic type" the type of the top-level container that was const=
ructed at that location.=C2=A0 What I'm saying is that pointer arithmet=
ic on char pointers ought to be well-defined anywhere within Meow, because =
Meow is the dynamic type of the entire block of memory.=C2=A0 In my opinion=
, the two pointers below ought not just compare equal, but be semantically =
equal as well, capable of the same range of pointer arithmetic:<br><br>Meow=
meow;<br>char *a =3D reinterpret_cast<char *>(&meow) + offsetof(=
Meow, y);<br>char *b =3D reinterpret_cast<char *>(&meow.y);<br>as=
sert(a =3D=3D b);=C2=A0=C2=A0 // passes<br>a -=3D offsetof(Meow, y);=C2=A0=
=C2=A0 // points to beginning of meow<br>b -=3D offsetof(Meow, y);=C2=A0=C2=
=A0 // undefined behavior: b points to beginning "char array" of =
size sizeof(int), so subtracting a positive number is out of range.<br><br>=
Having different semantics for identical pointers of identical type that co=
mpare equal seems broken to me, and would be fixed by what I'm proposin=
g.<br><br></div><blockquote class=3D"gmail_quote" style=3D"margin:0;margin-=
left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><d=
iv>If you want something that makes your `CONTAINING_RECORD` work, then wha=
t you would say is that converting a `T*` into a byte pointer (ie: either `=
char*`, `unsigned char*`, or `std::byte*`) means that you are pointing to t=
he beginning of an array of bytes, the size of which is `sizeof(T)`, the ar=
ray storing the object representation of that `T`.<br><br></div></div></blo=
ckquote><div><br>That's exactly what I'm proposing: when you drop t=
o the level of byte pointers, the structure concept degenerates to a byte a=
rray of the dynamic type.<br></div></div></blockquote><div><br>But that'=
;s <i>not</i> what you're proposing. You just said so: "I meant by=
"dynamic type" the type of the top-level container that was cons=
tructed at that location." The description I gave defined the boundary=
of the byte array based on the object you cast from. So if you start with =
a `int*`, and you cast it to a byte pointer, then it can <i>only</i> be mov=
ed around within `sizeof(T)`.<br><br></div><blockquote class=3D"gmail_quote=
" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-le=
ft:1ex"><div dir=3D"ltr"><div>Note that CONTAINING_RECORD is a Microsoft ma=
cro and not my invention.=C2=A0 It's more or less required in order to =
make use of the lockless linked lists in Windows NT (InterlockedPushEntrySL=
ist and friends).=C2=A0 The actual Windows macro uses C casts, but is the s=
ame idea.<br>=C2=A0<br></div><blockquote class=3D"gmail_quote" style=3D"mar=
gin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><div d=
ir=3D"ltr"><div>But if you want your `GoodReadY` to work, then you have to =
do something different. You have to say that converting a pointer to a `T*`=
into a byte pointer gives you a pointer into the <i>middle</i> of an array=
of bytes (or at least potentially the middle). The size of the array and l=
ocation of that pointer within the array depend on the size of the outermos=
t containing class and the location of that subobject within the container.=
That's not merely the "dynamic type" of what you're cast=
ing from.<br><br>Personally, I much prefer the former to the latter. I don&=
#39;t like the idea of being able to jump from sibling subobject to sibling=
subobject. If you want to make that jump, I feel that you should have to s=
tart with a pointer to the object that they're both subobjects of.</div=
><br></div></blockquote><div><br>The reason for the change is to make well-=
defined certain programming styles that exist today, and resolve some incon=
sistencies in the Standard regarding object lifetime and pointer arithmetic=
..=C2=A0 Many customized memory allocators today are currently exploiting un=
defined behavior because they do the classic trick of storing memory manage=
ment headers prior to the logical memory block.=C2=A0 Subtracting from a po=
inter to the logical object is undefined behavior under the current rules, =
simply because of how the pointer was derived.<br><br>To resolve that, we c=
an simply say that byte pointers are allowed to traverse within any block o=
f allocated storage.<br></div></div></blockquote><div><br>And that's no=
t what you just said. Again, "I meant by "dynamic type" the =
type of the top-level container that was constructed at that location."=
; That's not "any block of allocated storage". In just this o=
ne post, you've explained 3 completely different ideas of what you want=
: pointer arithmetic within the type the pointer was when cast to a byte, p=
ointer arithmetic within the "top-level container" object, and po=
inter arithmetic within "any block of allocated storage". These a=
re not the same things.<br><br>Note: I'm not arguing against the idea. =
I'm trying to figure out what=20
the scope of the feature you really want is supposed to be.<br><br>Consider=
the following code:<br><br><div style=3D"background-color:rgb(250,250,250)=
;border-color:rgb(187,187,187);border-style:solid;border-width:1px"><code><=
div><span style=3D"color:#008">struct</span><span style=3D"color:#000"> X<b=
r></span><span style=3D"color:#660">{</span><span style=3D"color:#000"><br>=
=C2=A0 =C2=A0 </span><span style=3D"color:#008">float</span><span style=3D"=
color:#000"> a</span><span style=3D"color:#660">;</span><span style=3D"colo=
r:#000"><br>=C2=A0 =C2=A0 </span><span style=3D"color:#008">int</span><span=
style=3D"color:#000"> b</span><span style=3D"color:#660">;</span><span sty=
le=3D"color:#000"><br></span><span style=3D"color:#660">};</span><span styl=
e=3D"color:#000"><br><br></span><span style=3D"color:#008">struct</span><sp=
an style=3D"color:#000"> Y<br></span><span style=3D"color:#660">{</span><sp=
an style=3D"color:#000"><br>=C2=A0 =C2=A0 </span><span style=3D"color:#008"=
>float</span><span style=3D"color:#000"> q</span><span style=3D"color:#660"=
>;</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 X r</span><span style=
=3D"color:#660">;</span><span style=3D"color:#000"><br></span><span style=
=3D"color:#660">};</span><span style=3D"color:#000"><br><br></span><span st=
yle=3D"color:#008">struct</span><span style=3D"color:#000"> Z<br></span><sp=
an style=3D"color:#660">{</span><span style=3D"color:#000"><br>=C2=A0 =C2=
=A0 X x</span><span style=3D"color:#660">;</span><span style=3D"color:#000"=
><br>=C2=A0 =C2=A0 Y y</span><span style=3D"color:#660">;</span><span style=
=3D"color:#000"><br></span><span style=3D"color:#660">};</span><span style=
=3D"color:#000"><br><br></span><span style=3D"color:#008">void</span><span =
style=3D"color:#000"> func1</span><span style=3D"color:#660">()</span><span=
style=3D"color:#000"><br></span><span style=3D"color:#660">{</span><span s=
tyle=3D"color:#000"><br>=C2=A0 =C2=A0 </span><span style=3D"color:#008">aut=
o</span><span style=3D"color:#000"> mem </span><span style=3D"color:#660">=
=3D</span><span style=3D"color:#000"> </span><span style=3D"color:#008">new=
</span><span style=3D"color:#000"> std</span><span style=3D"color:#660">::<=
/span><span style=3D"color:#000">aligned_union_t</span><span style=3D"color=
:#660"><</span><span style=3D"color:#000">X</span><span style=3D"color:#=
660">>;</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 </span><span =
style=3D"color:#008">auto</span><span style=3D"color:#000"> x_ptr </span><s=
pan style=3D"color:#660">=3D</span><span style=3D"color:#000"> </span><span=
style=3D"color:#008">new</span><span style=3D"color:#660">(</span><span st=
yle=3D"color:#000">mem</span><span style=3D"color:#660">)</span><span style=
=3D"color:#000"> X</span><span style=3D"color:#660">;</span><span style=3D"=
color:#000"><br>=C2=A0 =C2=A0 <br>=C2=A0 =C2=A0 </span><span style=3D"color=
:#008">auto</span><span style=3D"color:#000"> byte_ptr </span><span style=
=3D"color:#660">=3D</span><span style=3D"color:#000"> </span><span style=3D=
"color:#008">reinterpret_cast</span><span style=3D"color:#660"><</span><=
span style=3D"color:#000">std</span><span style=3D"color:#660">::</span><sp=
an style=3D"color:#008">byte</span><span style=3D"color:#660">*>(&</=
span><span style=3D"color:#000"><wbr>x_ptr</span><span style=3D"color:#660"=
>);</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 byte_ptr </span><spa=
n style=3D"color:#660">+=3D</span><span style=3D"color:#000"> offsetof</spa=
n><span style=3D"color:#660">(</span><span style=3D"color:#000">X</span><sp=
an style=3D"color:#660">,</span><span style=3D"color:#000"> b</span><span s=
tyle=3D"color:#660">);</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 <=
/span><span style=3D"color:#008">auto</span><span style=3D"color:#000"> b_p=
tr </span><span style=3D"color:#660">=3D</span><span style=3D"color:#000"> =
</span><span style=3D"color:#008">reinterpret_cast</span><span style=3D"col=
or:#660"><</span><span style=3D"color:#008">int</span><span style=3D"col=
or:#660">*>(</span><span style=3D"color:#000">byte_<wbr>ptr</span><span =
style=3D"color:#660">);</span><span style=3D"color:#000"><br><br>=C2=A0 =C2=
=A0 </span><span style=3D"color:#660">*</span><span style=3D"color:#000">b_=
ptr </span><span style=3D"color:#660">=3D</span><span style=3D"color:#000">=
</span><span style=3D"color:#066">5</span><span style=3D"color:#660">;</sp=
an><span style=3D"color:#000"><br>=C2=A0 =C2=A0 x_ptr</span><span style=3D"=
color:#660">-></span><span style=3D"color:#000">b </span><span style=3D"=
color:#660">=3D</span><span style=3D"color:#000"> </span><span style=3D"col=
or:#066">10</span><span style=3D"color:#660">;</span><span style=3D"color:#=
000"><br>=C2=A0 =C2=A0 </span><span style=3D"color:#008">assert</span><span=
style=3D"color:#660">(*</span><span style=3D"color:#000">b_ptr </span><spa=
n style=3D"color:#660">=3D=3D</span><span style=3D"color:#000"> x_ptr</span=
><span style=3D"color:#660">-></span><span style=3D"color:#000">b</span>=
<span style=3D"color:#660">);</span><span style=3D"color:#000"> </span><spa=
n style=3D"color:#800">//Always true.</span><span style=3D"color:#000"><br>=
</span><span style=3D"color:#660">}</span><span style=3D"color:#000"><br><b=
r></span><span style=3D"color:#008">void</span><span style=3D"color:#000"> =
func2</span><span style=3D"color:#660">()</span><span style=3D"color:#000">=
<br></span><span style=3D"color:#660">{</span><span style=3D"color:#000"><b=
r>=C2=A0 =C2=A0 </span><span style=3D"color:#008">auto</span><span style=3D=
"color:#000"> mem </span><span style=3D"color:#660">=3D</span><span style=
=3D"color:#000"> </span><span style=3D"color:#008">new</span><span style=3D=
"color:#000"> std</span><span style=3D"color:#660">::</span><span style=3D"=
color:#000">aligned_union_t</span><span style=3D"color:#660"><</span><sp=
an style=3D"color:#000">X</span><span style=3D"color:#660">>;</span><spa=
n style=3D"color:#000"><br>=C2=A0 =C2=A0 </span><span style=3D"color:#008">=
auto</span><span style=3D"color:#000"> x_ptr </span><span style=3D"color:#6=
60">=3D</span><span style=3D"color:#000"> </span><span style=3D"color:#008"=
>new</span><span style=3D"color:#660">(</span><span style=3D"color:#000">me=
m</span><span style=3D"color:#660">)</span><span style=3D"color:#000"> X</s=
pan><span style=3D"color:#660">;</span><span style=3D"color:#000"><br>=C2=
=A0 =C2=A0 <br>=C2=A0 =C2=A0 </span><span style=3D"color:#008">auto</span><=
span style=3D"color:#000"> byte_ptr </span><span style=3D"color:#660">=3D</=
span><span style=3D"color:#000"> </span><span style=3D"color:#008">reinterp=
ret_cast</span><span style=3D"color:#660"><</span><span style=3D"color:#=
000">std</span><span style=3D"color:#660">::</span><span style=3D"color:#00=
8">byte</span><span style=3D"color:#660">*>(&</span><span style=3D"c=
olor:#000"><wbr>x_ptr</span><span style=3D"color:#660">.</span><span style=
=3D"color:#000">a</span><span style=3D"color:#660">);</span><span style=3D"=
color:#000"><br>=C2=A0 =C2=A0 byte_ptr </span><span style=3D"color:#660">-=
=3D</span><span style=3D"color:#000"> offsetof</span><span style=3D"color:#=
660">(</span><span style=3D"color:#000">X</span><span style=3D"color:#660">=
,</span><span style=3D"color:#000"> a</span><span style=3D"color:#660">);</=
span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 byte_ptr </span><span sty=
le=3D"color:#660">+=3D</span><span style=3D"color:#000"> offsetof</span><sp=
an style=3D"color:#660">(</span><span style=3D"color:#000">X</span><span st=
yle=3D"color:#660">,</span><span style=3D"color:#000"> b</span><span style=
=3D"color:#660">);</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 </spa=
n><span style=3D"color:#008">auto</span><span style=3D"color:#000"> b_ptr <=
/span><span style=3D"color:#660">=3D</span><span style=3D"color:#000"> </sp=
an><span style=3D"color:#008">reinterpret_cast</span><span style=3D"color:#=
660"><</span><span style=3D"color:#008">int</span><span style=3D"color:#=
660">*>(</span><span style=3D"color:#000">byte_<wbr>ptr</span><span styl=
e=3D"color:#660">);</span><span style=3D"color:#000"><br><br>=C2=A0 =C2=A0 =
</span><span style=3D"color:#660">*</span><span style=3D"color:#000">b_ptr =
</span><span style=3D"color:#660">=3D</span><span style=3D"color:#000"> </s=
pan><span style=3D"color:#066">5</span><span style=3D"color:#660">;</span><=
span style=3D"color:#000"><br>=C2=A0 =C2=A0 x_ptr</span><span style=3D"colo=
r:#660">-></span><span style=3D"color:#000">b </span><span style=3D"colo=
r:#660">=3D</span><span style=3D"color:#000"> </span><span style=3D"color:#=
066">10</span><span style=3D"color:#660">;</span><span style=3D"color:#000"=
><br>=C2=A0 =C2=A0 </span><span style=3D"color:#008">assert</span><span sty=
le=3D"color:#660">(*</span><span style=3D"color:#000">b_ptr </span><span st=
yle=3D"color:#660">=3D=3D</span><span style=3D"color:#000"> x_ptr</span><sp=
an style=3D"color:#660">-></span><span style=3D"color:#000">b</span><spa=
n style=3D"color:#660">);</span><span style=3D"color:#000"> </span><span st=
yle=3D"color:#800">//Always true.</span><span style=3D"color:#000"><br></sp=
an><span style=3D"color:#660">}</span><span style=3D"color:#000"><br><br></=
span><span style=3D"color:#008">void</span><span style=3D"color:#000"> func=
3</span><span style=3D"color:#660">()</span><span style=3D"color:#000"><br>=
</span><span style=3D"color:#660">{</span><span style=3D"color:#000"><br>=
=C2=A0 =C2=A0 </span><span style=3D"color:#800">//Creates two independent o=
bjects in the same allocation.</span><span style=3D"color:#000"><br>=C2=A0 =
=C2=A0 </span><span style=3D"color:#800">//Does not actually construct a Z.=
</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 </span><span style=3D"c=
olor:#008">auto</span><span style=3D"color:#000"> mem </span><span style=3D=
"color:#660">=3D</span><span style=3D"color:#000"> </span><span style=3D"co=
lor:#008">new</span><span style=3D"color:#000"> std</span><span style=3D"co=
lor:#660">::</span><span style=3D"color:#000">aligned_union_t</span><span s=
tyle=3D"color:#660"><</span><span style=3D"color:#000">Z</span><span sty=
le=3D"color:#660">>;</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =
</span><span style=3D"color:#008">auto</span><span style=3D"color:#000"> me=
m_ptr </span><span style=3D"color:#660">=3D</span><span style=3D"color:#000=
"> </span><span style=3D"color:#008">reinterpret_cast</span><span style=3D"=
color:#660"><</span><span style=3D"color:#000">std</span><span style=3D"=
color:#660">::</span><span style=3D"color:#008">byte</span><span style=3D"c=
olor:#660">*>(</span><span style=3D"color:#000">m<wbr>em</span><span sty=
le=3D"color:#660">);</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 </s=
pan><span style=3D"color:#008">auto</span><span style=3D"color:#000"> x_ptr=
</span><span style=3D"color:#660">=3D</span><span style=3D"color:#000"> </=
span><span style=3D"color:#008">new</span><span style=3D"color:#660">(</spa=
n><span style=3D"color:#000">mem_ptr </span><span style=3D"color:#660">+</s=
pan><span style=3D"color:#000"> offsetof</span><span style=3D"color:#660">(=
</span><span style=3D"color:#000">Z</span><span style=3D"color:#660">,</spa=
n><span style=3D"color:#000"> x</span><span style=3D"color:#660">))</span><=
span style=3D"color:#000"> X</span><span style=3D"color:#660">;</span><span=
style=3D"color:#000"><br>=C2=A0 =C2=A0 </span><span style=3D"color:#008">a=
uto</span><span style=3D"color:#000"> y_ptr </span><span style=3D"color:#66=
0">=3D</span><span style=3D"color:#000"> </span><span style=3D"color:#008">=
new</span><span style=3D"color:#660">(</span><span style=3D"color:#000">mem=
_ptr </span><span style=3D"color:#660">+</span><span style=3D"color:#000"> =
offsetof</span><span style=3D"color:#660">(</span><span style=3D"color:#000=
">Z</span><span style=3D"color:#660">,</span><span style=3D"color:#000"> y<=
/span><span style=3D"color:#660">))</span><span style=3D"color:#000"> Y</sp=
an><span style=3D"color:#660">;</span><span style=3D"color:#000"><br><br>=
=C2=A0 =C2=A0 </span><span style=3D"color:#008">auto</span><span style=3D"c=
olor:#000"> byte_ptr </span><span style=3D"color:#660">=3D</span><span styl=
e=3D"color:#000"> </span><span style=3D"color:#008">reinterpret_cast</span>=
<span style=3D"color:#660"><</span><span style=3D"color:#000">std</span>=
<span style=3D"color:#660">::</span><span style=3D"color:#008">byte</span><=
span style=3D"color:#660">*>(&</span><span style=3D"color:#000"><wbr=
>x_ptr</span><span style=3D"color:#660">);</span><span style=3D"color:#000"=
><br>=C2=A0 =C2=A0 byte_ptr </span><span style=3D"color:#660">-=3D</span><s=
pan style=3D"color:#000"> offsetof</span><span style=3D"color:#660">(</span=
><span style=3D"color:#000">Z</span><span style=3D"color:#660">,</span><spa=
n style=3D"color:#000"> x</span><span style=3D"color:#660">);</span><span s=
tyle=3D"color:#000"><br>=C2=A0 =C2=A0 byte_ptr </span><span style=3D"color:=
#660">+=3D</span><span style=3D"color:#000"> offsetof</span><span style=3D"=
color:#660">(</span><span style=3D"color:#000">Z</span><span style=3D"color=
:#660">,</span><span style=3D"color:#000"> y</span><span style=3D"color:#66=
0">);</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 byte_ptr </span><s=
pan style=3D"color:#660">+=3D</span><span style=3D"color:#000"> offsetof</s=
pan><span style=3D"color:#660">(</span><span style=3D"color:#000">Y</span><=
span style=3D"color:#660">,</span><span style=3D"color:#000"> r</span><span=
style=3D"color:#660">);</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0=
byte_ptr </span><span style=3D"color:#660">+=3D</span><span style=3D"color=
:#000"> offsetof</span><span style=3D"color:#660">(</span><span style=3D"co=
lor:#000">X</span><span style=3D"color:#660">,</span><span style=3D"color:#=
000"> b</span><span style=3D"color:#660">);</span><span style=3D"color:#000=
"><br>=C2=A0 =C2=A0 </span><span style=3D"color:#008">auto</span><span styl=
e=3D"color:#000"> b_ptr </span><span style=3D"color:#660">=3D</span><span s=
tyle=3D"color:#000"> </span><span style=3D"color:#008">reinterpret_cast</sp=
an><span style=3D"color:#660"><</span><span style=3D"color:#008">int</sp=
an><span style=3D"color:#660">*>(</span><span style=3D"color:#000">byte_=
<wbr>ptr</span><span style=3D"color:#660">);</span><span style=3D"color:#00=
0"><br><br>=C2=A0 =C2=A0 </span><span style=3D"color:#660">*</span><span st=
yle=3D"color:#000">b_ptr </span><span style=3D"color:#660">=3D</span><span =
style=3D"color:#000"> </span><span style=3D"color:#066">5</span><span style=
=3D"color:#660">;</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 y_ptr<=
/span><span style=3D"color:#660">-></span><span style=3D"color:#000">r</=
span><span style=3D"color:#660">.</span><span style=3D"color:#000">b </span=
><span style=3D"color:#660">=3D</span><span style=3D"color:#000"> </span><s=
pan style=3D"color:#066">10</span><span style=3D"color:#660">;</span><span =
style=3D"color:#000"><br>=C2=A0 =C2=A0 </span><span style=3D"color:#008">as=
sert</span><span style=3D"color:#660">(*</span><span style=3D"color:#000">b=
_ptr </span><span style=3D"color:#660">=3D=3D</span><span style=3D"color:#0=
00"> y_ptr</span><span style=3D"color:#660">-></span><span style=3D"colo=
r:#000">r</span><span style=3D"color:#660">.</span><span style=3D"color:#00=
0">b</span><span style=3D"color:#660">);</span><span style=3D"color:#000"> =
</span><span style=3D"color:#800">//Always true.</span><span style=3D"color=
:#000"><br></span><span style=3D"color:#660">}</span><span style=3D"color:#=
000"><br></span></div></code></div><br>Which of these functions do you want=
to work? If you want all of them to work, then what you're talking abo=
ut that "block of allocated storage" thing. That means that byte =
pointer arithmetic should act as though the entire allocation were a byte a=
rray. And casting to a byte pointer means getting a pointer to an element i=
n the array.<br><br>Note that when I say "byte pointer", I mean a=
ny of the three byte types, not just `std::byte`.<br></div></div></blockquo=
te></div></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/58941597-209a-4aa4-aae5-024d2f581666%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/58941597-209a-4aa4-aae5-024d2f581666=
%40isocpp.org</a>.<br />
------=_Part_1023_1886959503.1497602758035--
------=_Part_1022_930733883.1497602758033--
.
Author: Hyman Rosen <hyman.rosen@gmail.com>
Date: Fri, 16 Jun 2017 10:31:37 -0400
Raw View
--001a11c14cdcd1d437055214a5e7
Content-Type: text/plain; charset="UTF-8"
And gcc at -O2 optimizes this code to have g() return 99.
_Z1gv:
movl $99, %eax
ret
Taking away the ability for optimizers to break code by assuming that
undefined behavior never happens is an unalloyed good.
On Fri, Jun 16, 2017 at 4:45 AM, Edward Catmur <ed@catmur.co.uk> wrote:
> Your proposed feature would inhibit certain optimizations that are
> currently performed. For example:
>
> int f(Meow* m, int* i) {
> m->x = 42;
> reinterpret_cast<Meow*>(reinterpret_cast<char*>(i) -
> sizeof(Meow::x))->x = 99; // #1
> return m->x;
> }
> int g() {
> Meow m;
> return f(&m, &m.y);
> }
>
> Since #1 is UB when called from g, the compiler can optimize g to return
> 42, and indeed icc does so at -O2.
>
> In your motivating example, CONTAINING_RECORD is provided by the vendor so
> they can perform whatever magic is necessary to suppress such
> optimizations. For other use cases, it is currently permissible to traverse
> to a containing object from any of:
> * a base class subobject
> * a union member subobject of a standard-layout union
> * the initial non-static data member of a standard-layout class
> The latter two are covered by the pointer-interconvertibility rules (since
> P0137r1).
>
> Would it be possible to apply any of the above permitted techniques to
> your use cases?
>
> On Thursday, 15 June 2017 16:14:22 UTC+1, Nicol Bolas wrote:
>>
>> On Wednesday, June 14, 2017 at 5:53:21 PM UTC-4, Myriachan wrote:
>>>
>>> On Tuesday, June 13, 2017 at 5:05:35 PM UTC-7, Nicol Bolas wrote:
>>>>
>>>> Your example doesn't make your use case. Your use case is specifically
>>>> about accessing a member subobject of the `type` at the `address`. Your
>>>> example however is about jumping from sibling object to sibling object.
>>>>
>>>> In the example, `(&meow->x)` is a pointer to an `int`. The dynamic type
>>>> of that object is `*int*`, not `Meow`. So by your own definition, that
>>>> example would still be UB.
>>>>
>>>>
>>> I don't know the proper word for it, but I meant by "dynamic type" the
>>> type of the top-level container that was constructed at that location.
>>> What I'm saying is that pointer arithmetic on char pointers ought to be
>>> well-defined anywhere within Meow, because Meow is the dynamic type of the
>>> entire block of memory. In my opinion, the two pointers below ought not
>>> just compare equal, but be semantically equal as well, capable of the same
>>> range of pointer arithmetic:
>>>
>>> Meow meow;
>>> char *a = reinterpret_cast<char *>(&meow) + offsetof(Meow, y);
>>> char *b = reinterpret_cast<char *>(&meow.y);
>>> assert(a == b); // passes
>>> a -= offsetof(Meow, y); // points to beginning of meow
>>> b -= offsetof(Meow, y); // undefined behavior: b points to beginning
>>> "char array" of size sizeof(int), so subtracting a positive number is out
>>> of range.
>>>
>>> Having different semantics for identical pointers of identical type that
>>> compare equal seems broken to me, and would be fixed by what I'm proposing.
>>>
>>> If you want something that makes your `CONTAINING_RECORD` work, then
>>>> what you would say is that converting a `T*` into a byte pointer (ie:
>>>> either `char*`, `unsigned char*`, or `std::byte*`) means that you are
>>>> pointing to the beginning of an array of bytes, the size of which is
>>>> `sizeof(T)`, the array storing the object representation of that `T`.
>>>>
>>>>
>>> That's exactly what I'm proposing: when you drop to the level of byte
>>> pointers, the structure concept degenerates to a byte array of the dynamic
>>> type.
>>>
>>
>> But that's *not* what you're proposing. You just said so: "I meant by
>> "dynamic type" the type of the top-level container that was constructed at
>> that location." The description I gave defined the boundary of the byte
>> array based on the object you cast from. So if you start with a `int*`, and
>> you cast it to a byte pointer, then it can *only* be moved around within
>> `sizeof(T)`.
>>
>> Note that CONTAINING_RECORD is a Microsoft macro and not my invention.
>>> It's more or less required in order to make use of the lockless linked
>>> lists in Windows NT (InterlockedPushEntrySList and friends). The actual
>>> Windows macro uses C casts, but is the same idea.
>>>
>>>
>>>> But if you want your `GoodReadY` to work, then you have to do something
>>>> different. You have to say that converting a pointer to a `T*` into a byte
>>>> pointer gives you a pointer into the *middle* of an array of bytes (or
>>>> at least potentially the middle). The size of the array and location of
>>>> that pointer within the array depend on the size of the outermost
>>>> containing class and the location of that subobject within the container.
>>>> That's not merely the "dynamic type" of what you're casting from.
>>>>
>>>> Personally, I much prefer the former to the latter. I don't like the
>>>> idea of being able to jump from sibling subobject to sibling subobject. If
>>>> you want to make that jump, I feel that you should have to start with a
>>>> pointer to the object that they're both subobjects of.
>>>>
>>>>
>>> The reason for the change is to make well-defined certain programming
>>> styles that exist today, and resolve some inconsistencies in the Standard
>>> regarding object lifetime and pointer arithmetic. Many customized memory
>>> allocators today are currently exploiting undefined behavior because they
>>> do the classic trick of storing memory management headers prior to the
>>> logical memory block. Subtracting from a pointer to the logical object is
>>> undefined behavior under the current rules, simply because of how the
>>> pointer was derived.
>>>
>>> To resolve that, we can simply say that byte pointers are allowed to
>>> traverse within any block of allocated storage.
>>>
>>
>> And that's not what you just said. Again, "I meant by "dynamic type" the
>> type of the top-level container that was constructed at that location."
>> That's not "any block of allocated storage". In just this one post, you've
>> explained 3 completely different ideas of what you want: pointer arithmetic
>> within the type the pointer was when cast to a byte, pointer arithmetic
>> within the "top-level container" object, and pointer arithmetic within "any
>> block of allocated storage". These are not the same things.
>>
>> Note: I'm not arguing against the idea. I'm trying to figure out what the
>> scope of the feature you really want is supposed to be.
>>
>> Consider the following code:
>>
>> struct X
>> {
>> float a;
>> int b;
>> };
>>
>> struct Y
>> {
>> float q;
>> X r;
>> };
>>
>> struct Z
>> {
>> X x;
>> Y y;
>> };
>>
>> void func1()
>> {
>> auto mem = new std::aligned_union_t<X>;
>> auto x_ptr = new(mem) X;
>>
>> auto byte_ptr = reinterpret_cast<std::byte*>(&x_ptr);
>> byte_ptr += offsetof(X, b);
>> auto b_ptr = reinterpret_cast<int*>(byte_ptr);
>>
>> *b_ptr = 5;
>> x_ptr->b = 10;
>> assert(*b_ptr == x_ptr->b); //Always true.
>> }
>>
>> void func2()
>> {
>> auto mem = new std::aligned_union_t<X>;
>> auto x_ptr = new(mem) X;
>>
>> auto byte_ptr = reinterpret_cast<std::byte*>(&x_ptr.a);
>> byte_ptr -= offsetof(X, a);
>> byte_ptr += offsetof(X, b);
>> auto b_ptr = reinterpret_cast<int*>(byte_ptr);
>>
>> *b_ptr = 5;
>> x_ptr->b = 10;
>> assert(*b_ptr == x_ptr->b); //Always true.
>> }
>>
>> void func3()
>> {
>> //Creates two independent objects in the same allocation.
>> //Does not actually construct a Z.
>> auto mem = new std::aligned_union_t<Z>;
>> auto mem_ptr = reinterpret_cast<std::byte*>(mem);
>> auto x_ptr = new(mem_ptr + offsetof(Z, x)) X;
>> auto y_ptr = new(mem_ptr + offsetof(Z, y)) Y;
>>
>> auto byte_ptr = reinterpret_cast<std::byte*>(&x_ptr);
>> byte_ptr -= offsetof(Z, x);
>> byte_ptr += offsetof(Z, y);
>> byte_ptr += offsetof(Y, r);
>> byte_ptr += offsetof(X, b);
>> auto b_ptr = reinterpret_cast<int*>(byte_ptr);
>>
>> *b_ptr = 5;
>> y_ptr->r.b = 10;
>> assert(*b_ptr == y_ptr->r.b); //Always true.
>> }
>>
>> Which of these functions do you want to work? If you want all of them to
>> work, then what you're talking about that "block of allocated storage"
>> thing. That means that byte pointer arithmetic should act as though the
>> entire allocation were a byte array. And casting to a byte pointer means
>> getting a pointer to an element in the array.
>>
>> Note that when I say "byte pointer", I mean any of the three byte types,
>> not just `std::byte`.
>>
> --
> 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
> email 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/58941597-209a-4aa4-
> aae5-024d2f581666%40isocpp.org
> <https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/58941597-209a-4aa4-aae5-024d2f581666%40isocpp.org?utm_medium=email&utm_source=footer>
> .
>
--
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 email 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/CAHSYqdbYcF4njx2L3dm2vw5AfDmCH6JoV0EnL2yoYpBVcU%2BqoQ%40mail.gmail.com.
--001a11c14cdcd1d437055214a5e7
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">And gcc at -O2 optimizes this code to have g() return 99.<=
br><div><br>_Z1gv:</div><div>=C2=A0 =C2=A0 movl =C2=A0 =C2=A0$99, %eax</div=
><div>=C2=A0 =C2=A0 ret<br><br>Taking away the ability for optimizers to br=
eak code by assuming that undefined behavior never happens is an unalloyed =
good.</div></div><div class=3D"gmail_extra"><br><div class=3D"gmail_quote">=
On Fri, Jun 16, 2017 at 4:45 AM, Edward Catmur <span dir=3D"ltr"><<a hre=
f=3D"mailto:ed@catmur.co.uk" target=3D"_blank">ed@catmur.co.uk</a>></spa=
n> wrote:<br><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;b=
order-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr">Your proposed =
feature would inhibit certain optimizations that are currently performed. F=
or example:<div><br></div><div>int f(Meow* m, int* i) {</div><div>=C2=A0 =
=C2=A0 m->x =3D 42;</div><div>=C2=A0 =C2=A0 reinterpret_cast<Meow*>=
;(<wbr>reinterpret_cast<char*>(i) - sizeof(Meow::x))->x =3D 99; //=
#1</div><div>=C2=A0 =C2=A0 return m->x;<br></div><div>}</div><div>int g=
() {</div><div>=C2=A0 Meow m;</div><div>=C2=A0 return f(&m, &m.y);<=
/div><div>}</div><div><br></div><div>Since #1 is UB when called from g, the=
compiler can optimize g to return 42, and indeed icc does so at -O2.</div>=
<div><br></div><div>In your motivating example, CONTAINING_RECORD is provid=
ed by the vendor so they can perform whatever magic is necessary to suppres=
s such optimizations. For other use cases, it is currently permissible to t=
raverse to a containing object from any of:</div><div>* a base class subobj=
ect</div><div>* a union member subobject of a standard-layout union</div><d=
iv>* the initial non-static data member of a standard-layout class</div><di=
v>The latter two are covered by the pointer-interconvertibility rules (sinc=
e P0137r1).</div><div><br></div><div>Would it be possible to apply any of t=
he above permitted techniques to your use cases?</div><div><div class=3D"h5=
"><div><br></div><div>On Thursday, 15 June 2017 16:14:22 UTC+1, Nicol Bolas=
wrote:<blockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8=
ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr">On Wednesd=
ay, June 14, 2017 at 5:53:21 PM UTC-4, Myriachan wrote:<blockquote class=3D=
"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc soli=
d;padding-left:1ex"><div dir=3D"ltr">On Tuesday, June 13, 2017 at 5:05:35 P=
M UTC-7, Nicol Bolas wrote:<blockquote class=3D"gmail_quote" style=3D"margi=
n:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=
=3D"ltr">Your example doesn't make your use case. Your use case is spec=
ifically about accessing a member subobject of the `type` at the `address`.=
Your example however is about jumping from sibling object to sibling objec=
t.<br><div><br>In the example, `(&meow->x)` is a pointer to an `int`=
.. The dynamic type of that object is `<b>int</b>`, not `Meow`. So by your o=
wn definition, that example would still be UB.<br><br></div></div></blockqu=
ote><div><br>I don't know the proper word for it, but I meant by "=
dynamic type" the type of the top-level container that was constructed=
at that location.=C2=A0 What I'm saying is that pointer arithmetic on =
char pointers ought to be well-defined anywhere within Meow, because Meow i=
s the dynamic type of the entire block of memory.=C2=A0 In my opinion, the =
two pointers below ought not just compare equal, but be semantically equal =
as well, capable of the same range of pointer arithmetic:<br><br>Meow meow;=
<br>char *a =3D reinterpret_cast<char *>(&meow) + offsetof(Meow, =
y);<br>char *b =3D reinterpret_cast<char *>(&meow.y);<br>assert(a=
=3D=3D b);=C2=A0=C2=A0 // passes<br>a -=3D offsetof(Meow, y);=C2=A0=C2=A0 =
// points to beginning of meow<br>b -=3D offsetof(Meow, y);=C2=A0=C2=A0 // =
undefined behavior: b points to beginning "char array" of size si=
zeof(int), so subtracting a positive number is out of range.<br><br>Having =
different semantics for identical pointers of identical type that compare e=
qual seems broken to me, and would be fixed by what I'm proposing.<br><=
br></div><blockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.=
8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div>If y=
ou want something that makes your `CONTAINING_RECORD` work, then what you w=
ould say is that converting a `T*` into a byte pointer (ie: either `char*`,=
`unsigned char*`, or `std::byte*`) means that you are pointing to the begi=
nning of an array of bytes, the size of which is `sizeof(T)`, the array sto=
ring the object representation of that `T`.<br><br></div></div></blockquote=
><div><br>That's exactly what I'm proposing: when you drop to the l=
evel of byte pointers, the structure concept degenerates to a byte array of=
the dynamic type.<br></div></div></blockquote><div><br>But that's <i>n=
ot</i> what you're proposing. You just said so: "I meant by "=
dynamic type" the type of the top-level container that was constructed=
at that location." The description I gave defined the boundary of the=
byte array based on the object you cast from. So if you start with a `int*=
`, and you cast it to a byte pointer, then it can <i>only</i> be moved arou=
nd within `sizeof(T)`.<br><br></div><blockquote class=3D"gmail_quote" style=
=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"=
><div dir=3D"ltr"><div>Note that CONTAINING_RECORD is a Microsoft macro and=
not my invention.=C2=A0 It's more or less required in order to make us=
e of the lockless linked lists in Windows NT (InterlockedPushEntrySList and=
friends).=C2=A0 The actual Windows macro uses C casts, but is the same ide=
a.<br>=C2=A0<br></div><blockquote class=3D"gmail_quote" style=3D"margin:0;m=
argin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"l=
tr"><div>But if you want your `GoodReadY` to work, then you have to do some=
thing different. You have to say that converting a pointer to a `T*` into a=
byte pointer gives you a pointer into the <i>middle</i> of an array of byt=
es (or at least potentially the middle). The size of the array and location=
of that pointer within the array depend on the size of the outermost conta=
ining class and the location of that subobject within the container. That&#=
39;s not merely the "dynamic type" of what you're casting fro=
m.<br><br>Personally, I much prefer the former to the latter. I don't l=
ike the idea of being able to jump from sibling subobject to sibling subobj=
ect. If you want to make that jump, I feel that you should have to start wi=
th a pointer to the object that they're both subobjects of.</div><br></=
div></blockquote><div><br>The reason for the change is to make well-defined=
certain programming styles that exist today, and resolve some inconsistenc=
ies in the Standard regarding object lifetime and pointer arithmetic.=C2=A0=
Many customized memory allocators today are currently exploiting undefined=
behavior because they do the classic trick of storing memory management he=
aders prior to the logical memory block.=C2=A0 Subtracting from a pointer t=
o the logical object is undefined behavior under the current rules, simply =
because of how the pointer was derived.<br><br>To resolve that, we can simp=
ly say that byte pointers are allowed to traverse within any block of alloc=
ated storage.<br></div></div></blockquote><div><br>And that's not what =
you just said. Again, "I meant by "dynamic type" the type of=
the top-level container that was constructed at that location." That&=
#39;s not "any block of allocated storage". In just this one post=
, you've explained 3 completely different ideas of what you want: point=
er arithmetic within the type the pointer was when cast to a byte, pointer =
arithmetic within the "top-level container" object, and pointer a=
rithmetic within "any block of allocated storage". These are not =
the same things.<br><br>Note: I'm not arguing against the idea. I'm=
trying to figure out what=20
the scope of the feature you really want is supposed to be.<br><br>Consider=
the following code:<br><br><div style=3D"background-color:rgb(250,250,250)=
;border-color:rgb(187,187,187);border-style:solid;border-width:1px"><code><=
div><span style=3D"color:#008">struct</span><span style=3D"color:#000"> X<b=
r></span><span style=3D"color:#660">{</span><span style=3D"color:#000"><br>=
=C2=A0 =C2=A0 </span><span style=3D"color:#008">float</span><span style=3D"=
color:#000"> a</span><span style=3D"color:#660">;</span><span style=3D"colo=
r:#000"><br>=C2=A0 =C2=A0 </span><span style=3D"color:#008">int</span><span=
style=3D"color:#000"> b</span><span style=3D"color:#660">;</span><span sty=
le=3D"color:#000"><br></span><span style=3D"color:#660">};</span><span styl=
e=3D"color:#000"><br><br></span><span style=3D"color:#008">struct</span><sp=
an style=3D"color:#000"> Y<br></span><span style=3D"color:#660">{</span><sp=
an style=3D"color:#000"><br>=C2=A0 =C2=A0 </span><span style=3D"color:#008"=
>float</span><span style=3D"color:#000"> q</span><span style=3D"color:#660"=
>;</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 X r</span><span style=
=3D"color:#660">;</span><span style=3D"color:#000"><br></span><span style=
=3D"color:#660">};</span><span style=3D"color:#000"><br><br></span><span st=
yle=3D"color:#008">struct</span><span style=3D"color:#000"> Z<br></span><sp=
an style=3D"color:#660">{</span><span style=3D"color:#000"><br>=C2=A0 =C2=
=A0 X x</span><span style=3D"color:#660">;</span><span style=3D"color:#000"=
><br>=C2=A0 =C2=A0 Y y</span><span style=3D"color:#660">;</span><span style=
=3D"color:#000"><br></span><span style=3D"color:#660">};</span><span style=
=3D"color:#000"><br><br></span><span style=3D"color:#008">void</span><span =
style=3D"color:#000"> func1</span><span style=3D"color:#660">()</span><span=
style=3D"color:#000"><br></span><span style=3D"color:#660">{</span><span s=
tyle=3D"color:#000"><br>=C2=A0 =C2=A0 </span><span style=3D"color:#008">aut=
o</span><span style=3D"color:#000"> mem </span><span style=3D"color:#660">=
=3D</span><span style=3D"color:#000"> </span><span style=3D"color:#008">new=
</span><span style=3D"color:#000"> std</span><span style=3D"color:#660">::<=
/span><span style=3D"color:#000">aligned_union_t</span><span style=3D"color=
:#660"><</span><span style=3D"color:#000">X</span><span style=3D"color:#=
660">>;</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 </span><span =
style=3D"color:#008">auto</span><span style=3D"color:#000"> x_ptr </span><s=
pan style=3D"color:#660">=3D</span><span style=3D"color:#000"> </span><span=
style=3D"color:#008">new</span><span style=3D"color:#660">(</span><span st=
yle=3D"color:#000">mem</span><span style=3D"color:#660">)</span><span style=
=3D"color:#000"> X</span><span style=3D"color:#660">;</span><span style=3D"=
color:#000"><br>=C2=A0 =C2=A0 <br>=C2=A0 =C2=A0 </span><span style=3D"color=
:#008">auto</span><span style=3D"color:#000"> byte_ptr </span><span style=
=3D"color:#660">=3D</span><span style=3D"color:#000"> </span><span style=3D=
"color:#008">reinterpret_cast</span><span style=3D"color:#660"><</span><=
span style=3D"color:#000">std</span><span style=3D"color:#660">::</span><sp=
an style=3D"color:#008">byte</span><span style=3D"color:#660">*>(&</=
span><span style=3D"color:#000"><wbr>x_ptr</span><span style=3D"color:#660"=
>);</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 byte_ptr </span><spa=
n style=3D"color:#660">+=3D</span><span style=3D"color:#000"> offsetof</spa=
n><span style=3D"color:#660">(</span><span style=3D"color:#000">X</span><sp=
an style=3D"color:#660">,</span><span style=3D"color:#000"> b</span><span s=
tyle=3D"color:#660">);</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 <=
/span><span style=3D"color:#008">auto</span><span style=3D"color:#000"> b_p=
tr </span><span style=3D"color:#660">=3D</span><span style=3D"color:#000"> =
</span><span style=3D"color:#008">reinterpret_cast</span><span style=3D"col=
or:#660"><</span><span style=3D"color:#008">int</span><span style=3D"col=
or:#660">*>(</span><span style=3D"color:#000">byte_pt<wbr>r</span><span =
style=3D"color:#660">);</span><span style=3D"color:#000"><br><br>=C2=A0 =C2=
=A0 </span><span style=3D"color:#660">*</span><span style=3D"color:#000">b_=
ptr </span><span style=3D"color:#660">=3D</span><span style=3D"color:#000">=
</span><span style=3D"color:#066">5</span><span style=3D"color:#660">;</sp=
an><span style=3D"color:#000"><br>=C2=A0 =C2=A0 x_ptr</span><span style=3D"=
color:#660">-></span><span style=3D"color:#000">b </span><span style=3D"=
color:#660">=3D</span><span style=3D"color:#000"> </span><span style=3D"col=
or:#066">10</span><span style=3D"color:#660">;</span><span style=3D"color:#=
000"><br>=C2=A0 =C2=A0 </span><span style=3D"color:#008">assert</span><span=
style=3D"color:#660">(*</span><span style=3D"color:#000">b_ptr </span><spa=
n style=3D"color:#660">=3D=3D</span><span style=3D"color:#000"> x_ptr</span=
><span style=3D"color:#660">-></span><span style=3D"color:#000">b</span>=
<span style=3D"color:#660">);</span><span style=3D"color:#000"> </span><spa=
n style=3D"color:#800">//Always true.</span><span style=3D"color:#000"><br>=
</span><span style=3D"color:#660">}</span><span style=3D"color:#000"><br><b=
r></span><span style=3D"color:#008">void</span><span style=3D"color:#000"> =
func2</span><span style=3D"color:#660">()</span><span style=3D"color:#000">=
<br></span><span style=3D"color:#660">{</span><span style=3D"color:#000"><b=
r>=C2=A0 =C2=A0 </span><span style=3D"color:#008">auto</span><span style=3D=
"color:#000"> mem </span><span style=3D"color:#660">=3D</span><span style=
=3D"color:#000"> </span><span style=3D"color:#008">new</span><span style=3D=
"color:#000"> std</span><span style=3D"color:#660">::</span><span style=3D"=
color:#000">aligned_union_t</span><span style=3D"color:#660"><</span><sp=
an style=3D"color:#000">X</span><span style=3D"color:#660">>;</span><spa=
n style=3D"color:#000"><br>=C2=A0 =C2=A0 </span><span style=3D"color:#008">=
auto</span><span style=3D"color:#000"> x_ptr </span><span style=3D"color:#6=
60">=3D</span><span style=3D"color:#000"> </span><span style=3D"color:#008"=
>new</span><span style=3D"color:#660">(</span><span style=3D"color:#000">me=
m</span><span style=3D"color:#660">)</span><span style=3D"color:#000"> X</s=
pan><span style=3D"color:#660">;</span><span style=3D"color:#000"><br>=C2=
=A0 =C2=A0 <br>=C2=A0 =C2=A0 </span><span style=3D"color:#008">auto</span><=
span style=3D"color:#000"> byte_ptr </span><span style=3D"color:#660">=3D</=
span><span style=3D"color:#000"> </span><span style=3D"color:#008">reinterp=
ret_cast</span><span style=3D"color:#660"><</span><span style=3D"color:#=
000">std</span><span style=3D"color:#660">::</span><span style=3D"color:#00=
8">byte</span><span style=3D"color:#660">*>(&</span><span style=3D"c=
olor:#000"><wbr>x_ptr</span><span style=3D"color:#660">.</span><span style=
=3D"color:#000">a</span><span style=3D"color:#660">);</span><span style=3D"=
color:#000"><br>=C2=A0 =C2=A0 byte_ptr </span><span style=3D"color:#660">-=
=3D</span><span style=3D"color:#000"> offsetof</span><span style=3D"color:#=
660">(</span><span style=3D"color:#000">X</span><span style=3D"color:#660">=
,</span><span style=3D"color:#000"> a</span><span style=3D"color:#660">);</=
span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 byte_ptr </span><span sty=
le=3D"color:#660">+=3D</span><span style=3D"color:#000"> offsetof</span><sp=
an style=3D"color:#660">(</span><span style=3D"color:#000">X</span><span st=
yle=3D"color:#660">,</span><span style=3D"color:#000"> b</span><span style=
=3D"color:#660">);</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 </spa=
n><span style=3D"color:#008">auto</span><span style=3D"color:#000"> b_ptr <=
/span><span style=3D"color:#660">=3D</span><span style=3D"color:#000"> </sp=
an><span style=3D"color:#008">reinterpret_cast</span><span style=3D"color:#=
660"><</span><span style=3D"color:#008">int</span><span style=3D"color:#=
660">*>(</span><span style=3D"color:#000">byte_pt<wbr>r</span><span styl=
e=3D"color:#660">);</span><span style=3D"color:#000"><br><br>=C2=A0 =C2=A0 =
</span><span style=3D"color:#660">*</span><span style=3D"color:#000">b_ptr =
</span><span style=3D"color:#660">=3D</span><span style=3D"color:#000"> </s=
pan><span style=3D"color:#066">5</span><span style=3D"color:#660">;</span><=
span style=3D"color:#000"><br>=C2=A0 =C2=A0 x_ptr</span><span style=3D"colo=
r:#660">-></span><span style=3D"color:#000">b </span><span style=3D"colo=
r:#660">=3D</span><span style=3D"color:#000"> </span><span style=3D"color:#=
066">10</span><span style=3D"color:#660">;</span><span style=3D"color:#000"=
><br>=C2=A0 =C2=A0 </span><span style=3D"color:#008">assert</span><span sty=
le=3D"color:#660">(*</span><span style=3D"color:#000">b_ptr </span><span st=
yle=3D"color:#660">=3D=3D</span><span style=3D"color:#000"> x_ptr</span><sp=
an style=3D"color:#660">-></span><span style=3D"color:#000">b</span><spa=
n style=3D"color:#660">);</span><span style=3D"color:#000"> </span><span st=
yle=3D"color:#800">//Always true.</span><span style=3D"color:#000"><br></sp=
an><span style=3D"color:#660">}</span><span style=3D"color:#000"><br><br></=
span><span style=3D"color:#008">void</span><span style=3D"color:#000"> func=
3</span><span style=3D"color:#660">()</span><span style=3D"color:#000"><br>=
</span><span style=3D"color:#660">{</span><span style=3D"color:#000"><br>=
=C2=A0 =C2=A0 </span><span style=3D"color:#800">//Creates two independent o=
bjects in the same allocation.</span><span style=3D"color:#000"><br>=C2=A0 =
=C2=A0 </span><span style=3D"color:#800">//Does not actually construct a Z.=
</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 </span><span style=3D"c=
olor:#008">auto</span><span style=3D"color:#000"> mem </span><span style=3D=
"color:#660">=3D</span><span style=3D"color:#000"> </span><span style=3D"co=
lor:#008">new</span><span style=3D"color:#000"> std</span><span style=3D"co=
lor:#660">::</span><span style=3D"color:#000">aligned_union_t</span><span s=
tyle=3D"color:#660"><</span><span style=3D"color:#000">Z</span><span sty=
le=3D"color:#660">>;</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =
</span><span style=3D"color:#008">auto</span><span style=3D"color:#000"> me=
m_ptr </span><span style=3D"color:#660">=3D</span><span style=3D"color:#000=
"> </span><span style=3D"color:#008">reinterpret_cast</span><span style=3D"=
color:#660"><</span><span style=3D"color:#000">std</span><span style=3D"=
color:#660">::</span><span style=3D"color:#008">byte</span><span style=3D"c=
olor:#660">*>(</span><span style=3D"color:#000">m<wbr>em</span><span sty=
le=3D"color:#660">);</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 </s=
pan><span style=3D"color:#008">auto</span><span style=3D"color:#000"> x_ptr=
</span><span style=3D"color:#660">=3D</span><span style=3D"color:#000"> </=
span><span style=3D"color:#008">new</span><span style=3D"color:#660">(</spa=
n><span style=3D"color:#000">mem_ptr </span><span style=3D"color:#660">+</s=
pan><span style=3D"color:#000"> offsetof</span><span style=3D"color:#660">(=
</span><span style=3D"color:#000">Z</span><span style=3D"color:#660">,</spa=
n><span style=3D"color:#000"> x</span><span style=3D"color:#660">))</span><=
span style=3D"color:#000"> X</span><span style=3D"color:#660">;</span><span=
style=3D"color:#000"><br>=C2=A0 =C2=A0 </span><span style=3D"color:#008">a=
uto</span><span style=3D"color:#000"> y_ptr </span><span style=3D"color:#66=
0">=3D</span><span style=3D"color:#000"> </span><span style=3D"color:#008">=
new</span><span style=3D"color:#660">(</span><span style=3D"color:#000">mem=
_ptr </span><span style=3D"color:#660">+</span><span style=3D"color:#000"> =
offsetof</span><span style=3D"color:#660">(</span><span style=3D"color:#000=
">Z</span><span style=3D"color:#660">,</span><span style=3D"color:#000"> y<=
/span><span style=3D"color:#660">))</span><span style=3D"color:#000"> Y</sp=
an><span style=3D"color:#660">;</span><span style=3D"color:#000"><br><br>=
=C2=A0 =C2=A0 </span><span style=3D"color:#008">auto</span><span style=3D"c=
olor:#000"> byte_ptr </span><span style=3D"color:#660">=3D</span><span styl=
e=3D"color:#000"> </span><span style=3D"color:#008">reinterpret_cast</span>=
<span style=3D"color:#660"><</span><span style=3D"color:#000">std</span>=
<span style=3D"color:#660">::</span><span style=3D"color:#008">byte</span><=
span style=3D"color:#660">*>(&</span><span style=3D"color:#000"><wbr=
>x_ptr</span><span style=3D"color:#660">);</span><span style=3D"color:#000"=
><br>=C2=A0 =C2=A0 byte_ptr </span><span style=3D"color:#660">-=3D</span><s=
pan style=3D"color:#000"> offsetof</span><span style=3D"color:#660">(</span=
><span style=3D"color:#000">Z</span><span style=3D"color:#660">,</span><spa=
n style=3D"color:#000"> x</span><span style=3D"color:#660">);</span><span s=
tyle=3D"color:#000"><br>=C2=A0 =C2=A0 byte_ptr </span><span style=3D"color:=
#660">+=3D</span><span style=3D"color:#000"> offsetof</span><span style=3D"=
color:#660">(</span><span style=3D"color:#000">Z</span><span style=3D"color=
:#660">,</span><span style=3D"color:#000"> y</span><span style=3D"color:#66=
0">);</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 byte_ptr </span><s=
pan style=3D"color:#660">+=3D</span><span style=3D"color:#000"> offsetof</s=
pan><span style=3D"color:#660">(</span><span style=3D"color:#000">Y</span><=
span style=3D"color:#660">,</span><span style=3D"color:#000"> r</span><span=
style=3D"color:#660">);</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0=
byte_ptr </span><span style=3D"color:#660">+=3D</span><span style=3D"color=
:#000"> offsetof</span><span style=3D"color:#660">(</span><span style=3D"co=
lor:#000">X</span><span style=3D"color:#660">,</span><span style=3D"color:#=
000"> b</span><span style=3D"color:#660">);</span><span style=3D"color:#000=
"><br>=C2=A0 =C2=A0 </span><span style=3D"color:#008">auto</span><span styl=
e=3D"color:#000"> b_ptr </span><span style=3D"color:#660">=3D</span><span s=
tyle=3D"color:#000"> </span><span style=3D"color:#008">reinterpret_cast</sp=
an><span style=3D"color:#660"><</span><span style=3D"color:#008">int</sp=
an><span style=3D"color:#660">*>(</span><span style=3D"color:#000">byte_=
pt<wbr>r</span><span style=3D"color:#660">);</span><span style=3D"color:#00=
0"><br><br>=C2=A0 =C2=A0 </span><span style=3D"color:#660">*</span><span st=
yle=3D"color:#000">b_ptr </span><span style=3D"color:#660">=3D</span><span =
style=3D"color:#000"> </span><span style=3D"color:#066">5</span><span style=
=3D"color:#660">;</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 y_ptr<=
/span><span style=3D"color:#660">-></span><span style=3D"color:#000">r</=
span><span style=3D"color:#660">.</span><span style=3D"color:#000">b </span=
><span style=3D"color:#660">=3D</span><span style=3D"color:#000"> </span><s=
pan style=3D"color:#066">10</span><span style=3D"color:#660">;</span><span =
style=3D"color:#000"><br>=C2=A0 =C2=A0 </span><span style=3D"color:#008">as=
sert</span><span style=3D"color:#660">(*</span><span style=3D"color:#000">b=
_ptr </span><span style=3D"color:#660">=3D=3D</span><span style=3D"color:#0=
00"> y_ptr</span><span style=3D"color:#660">-></span><span style=3D"colo=
r:#000">r</span><span style=3D"color:#660">.</span><span style=3D"color:#00=
0">b</span><span style=3D"color:#660">);</span><span style=3D"color:#000"> =
</span><span style=3D"color:#800">//Always true.</span><span style=3D"color=
:#000"><br></span><span style=3D"color:#660">}</span><span style=3D"color:#=
000"><br></span></div></code></div><br>Which of these functions do you want=
to work? If you want all of them to work, then what you're talking abo=
ut that "block of allocated storage" thing. That means that byte =
pointer arithmetic should act as though the entire allocation were a byte a=
rray. And casting to a byte pointer means getting a pointer to an element i=
n the array.<br><br>Note that when I say "byte pointer", I mean a=
ny of the three byte types, not just `std::byte`.<br></div></div></blockquo=
te></div></div></div></div><div><div class=3D"h5">
<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" target=3D"_=
blank">std-proposals+unsubscribe@<wbr>isocpp.org</a>.<br>
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org" target=3D"_blank">std-proposals@isocpp.org</a>.<br></div></div>
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/58941597-209a-4aa4-aae5-024d2f581666%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter" target=3D"_blank">=
https://groups.google.com/a/<wbr>isocpp.org/d/msgid/std-<wbr>proposals/5894=
1597-209a-4aa4-<wbr>aae5-024d2f581666%40isocpp.org</a><wbr>.<br>
</blockquote></div><br></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/CAHSYqdbYcF4njx2L3dm2vw5AfDmCH6JoV0En=
L2yoYpBVcU%2BqoQ%40mail.gmail.com?utm_medium=3Demail&utm_source=3Dfooter">h=
ttps://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAHSYqdbYcF4njx=
2L3dm2vw5AfDmCH6JoV0EnL2yoYpBVcU%2BqoQ%40mail.gmail.com</a>.<br />
--001a11c14cdcd1d437055214a5e7--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Fri, 16 Jun 2017 07:49:19 -0700 (PDT)
Raw View
------=_Part_1351_605896416.1497624559229
Content-Type: multipart/alternative;
boundary="----=_Part_1352_1902101335.1497624559229"
------=_Part_1352_1902101335.1497624559229
Content-Type: text/plain; charset="UTF-8"
On Friday, June 16, 2017 at 4:45:58 AM UTC-4, Edward Catmur wrote:
>
> Your proposed feature would inhibit certain optimizations that are
> currently performed. For example:
>
> int f(Meow* m, int* i) {
> m->x = 42;
> reinterpret_cast<Meow*>(reinterpret_cast<char*>(i) -
> sizeof(Meow::x))->x = 99; // #1
> return m->x;
> }
> int g() {
> Meow m;
> return f(&m, &m.y);
> }
>
> Since #1 is UB when called from g, the compiler can optimize g to return
> 42, and indeed icc does so at -O2.
>
I don't think this example is a good example of the problem. Yes, this
feature would mean the compiler can't just throw the operation away.
*That's the point*.
A better example of an optimization problem would be showing us code that
is *currently* well-defined, where the compiler would be unable to optimize
something away due to the new rules.
--
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 email 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/eec3de06-cc04-4049-b801-78734fafbecb%40isocpp.org.
------=_Part_1352_1902101335.1497624559229
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Friday, June 16, 2017 at 4:45:58 AM UTC-4, Edward Catmu=
r wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0=
..8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr">Your =
proposed feature would inhibit certain optimizations that are currently per=
formed. For example:<div><br></div><div>int f(Meow* m, int* i) {</div><div>=
=C2=A0 =C2=A0 m->x =3D 42;</div><div>=C2=A0 =C2=A0 reinterpret_cast<M=
eow*>(<wbr>reinterpret_cast<char*>(i) - sizeof(Meow::x))->x =3D=
99; // #1</div><div>=C2=A0 =C2=A0 return m->x;<br></div><div>}</div><di=
v>int g() {</div><div>=C2=A0 Meow m;</div><div>=C2=A0 return f(&m, &=
;m.y);</div><div>}</div><div><br></div><div>Since #1 is UB when called from=
g, the compiler can optimize g to return 42, and indeed icc does so at -O2=
..</div></div></blockquote><div><br>I don't think this example is a good=
example of the problem. Yes, this feature would mean the compiler can'=
t just throw the operation away.<br><br><i>That's the point</i>.<br><br=
>A better example of an optimization problem would be showing us code that =
is <i>currently</i> well-defined, where the compiler would be unable to opt=
imize something away due to the new rules.</div></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/eec3de06-cc04-4049-b801-78734fafbecb%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/eec3de06-cc04-4049-b801-78734fafbecb=
%40isocpp.org</a>.<br />
------=_Part_1352_1902101335.1497624559229--
------=_Part_1351_605896416.1497624559229--
.
Author: Myriachan <myriachan@gmail.com>
Date: Fri, 16 Jun 2017 13:04:12 -0700 (PDT)
Raw View
------=_Part_1706_1979028600.1497643452434
Content-Type: multipart/alternative;
boundary="----=_Part_1707_507734464.1497643452435"
------=_Part_1707_507734464.1497643452435
Content-Type: text/plain; charset="UTF-8"
On Friday, June 16, 2017 at 7:49:19 AM UTC-7, Nicol Bolas wrote:
>
> On Friday, June 16, 2017 at 4:45:58 AM UTC-4, Edward Catmur wrote:
>>
>> Your proposed feature would inhibit certain optimizations that are
>> currently performed. For example:
>>
>> int f(Meow* m, int* i) {
>> m->x = 42;
>> reinterpret_cast<Meow*>(reinterpret_cast<char*>(i) -
>> sizeof(Meow::x))->x = 99; // #1
>> return m->x;
>> }
>> int g() {
>> Meow m;
>> return f(&m, &m.y);
>> }
>>
>> Since #1 is UB when called from g, the compiler can optimize g to return
>> 42, and indeed icc does so at -O2.
>>
>
> I don't think this example is a good example of the problem. Yes, this
> feature would mean the compiler can't just throw the operation away.
>
> *That's the point*.
>
> A better example of an optimization problem would be showing us code that
> is *currently* well-defined, where the compiler would be unable to
> optimize something away due to the new rules.
>
This.
Which of these functions do you want to work? If you want all of them to
> work, then what you're talking about that "block of allocated storage"
> thing. That means that byte pointer arithmetic should act as though the
> entire allocation were a byte array. And casting to a byte pointer means
> getting a pointer to an element in the array.
>
> Note that when I say "byte pointer", I mean any of the three byte types,
> not just `std::byte`.
>
All three examples ought to work.
Systems programs use and will continue to use C and C++, and we need the
ability to do this kind of low-level memory manipulation sometimes. If we
were willing to entirely forego the ability to sometimes drop the abstract
representations, we'd probably be coding in C# or Java.
For optimization reasons, it's fine that most of the time the abstract
requirements have to be met. It's just that we need some way to drop the
abstractions to accomplish some memory management or manual optimization
task, and we'd rather not have to code it in assembly language.
The accepted mechanism to override aliasing restrictions is to
reinterpret_cast to char *, unsigned char *, or std::byte *. This would
just be an extension that removes some of the pointer checking, too.
Other times, we need the low-level abstractions to get around limitations
in the language. For example, CONTAINING_RECORD could be replaced by
Thiago's operator - definition for member pointers if it existed:
Meow meow;
int *p = &meow.y;
Meow *kitty = &(p->*(-&Meow::y));
assert(kitty == &meow);
This feature seems unlikely to be added for various reasons. (It would
break ABI compatibility, for one: both Microsoft and the UNIX Itanium ABIs
use -1 to represent null data member pointers currently, and an offset of
-1 would become a valid member pointer with this feature.)
Melissa
--
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 email 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/d43f405b-e8ba-40df-840b-84aa70880201%40isocpp.org.
------=_Part_1707_507734464.1497643452435
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Friday, June 16, 2017 at 7:49:19 AM UTC-7, Nicol Bolas =
wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8=
ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr">On Frid=
ay, June 16, 2017 at 4:45:58 AM UTC-4, Edward Catmur wrote:<blockquote clas=
s=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc =
solid;padding-left:1ex"><div dir=3D"ltr">Your proposed feature would inhibi=
t certain optimizations that are currently performed. For example:<div><br>=
</div><div>int f(Meow* m, int* i) {</div><div>=C2=A0 =C2=A0 m->x =3D 42;=
</div><div>=C2=A0 =C2=A0 reinterpret_cast<Meow*>(<wbr>reinterpret_cas=
t<char*>(i) - sizeof(Meow::x))->x =3D 99; // #1</div><div>=C2=A0 =
=C2=A0 return m->x;<br></div><div>}</div><div>int g() {</div><div>=C2=A0=
Meow m;</div><div>=C2=A0 return f(&m, &m.y);</div><div>}</div><div=
><br></div><div>Since #1 is UB when called from g, the compiler can optimiz=
e g to return 42, and indeed icc does so at -O2.</div></div></blockquote><d=
iv><br>I don't think this example is a good example of the problem. Yes=
, this feature would mean the compiler can't just throw the operation a=
way.<br><br><i>That's the point</i>.<br><br>A better example of an opti=
mization problem would be showing us code that is <i>currently</i> well-def=
ined, where the compiler would be unable to optimize something away due to =
the new rules.</div></div></blockquote><div><br>This.<br><br><blockquote cl=
ass=3D"gmail_quote" style=3D"margin: 0px 0px 0px 0.8ex; border-left: 1px so=
lid rgb(204, 204, 204); padding-left: 1ex;">Which of these functions do you=
want to work? If you want all of them to
work, then what you're talking about that "block of allocated sto=
rage"=20
thing. That means that byte pointer arithmetic should act as though the=20
entire allocation were a byte array. And casting to a byte pointer means
getting a pointer to an element in the array.<br><br>Note that when I say =
"byte pointer", I mean any of the three byte types, not just `std=
::byte`.<br></blockquote><br>All three examples ought to work.<br><br>Syste=
ms programs use and will continue to use C and C++, and we need the ability=
to do this kind of low-level memory manipulation sometimes.=C2=A0 If we we=
re willing to entirely forego the ability to sometimes drop the abstract re=
presentations, we'd probably be coding in C# or Java.<br><br>For optimi=
zation reasons, it's fine that most of the time the abstract requiremen=
ts have to be met.=C2=A0 It's just that we need some way to drop the ab=
stractions to accomplish some memory management or manual optimization task=
, and we'd rather not have to code it in assembly language.<br><br>The =
accepted mechanism to override aliasing restrictions is to reinterpret_cast=
to char *, unsigned char *, or std::byte *.=C2=A0 This would just be an ex=
tension that removes some of the pointer checking, too.<br><br>Other times,=
we need the low-level abstractions to get around limitations in the langua=
ge.=C2=A0 For example, CONTAINING_RECORD could be replaced by Thiago's =
operator - definition for member pointers if it existed:<br><br><div style=
=3D"background-color: rgb(250, 250, 250); border-color: rgb(187, 187, 187);=
border-style: solid; border-width: 1px; overflow-wrap: break-word;" class=
=3D"prettyprint"><code class=3D"prettyprint"><div class=3D"subprettyprint">=
<span style=3D"color: #606;" class=3D"styled-by-prettify">Meow</span><span =
style=3D"color: #000;" class=3D"styled-by-prettify"> meow</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">;</span><span style=3D"color=
: #000;" class=3D"styled-by-prettify"><br></span><span style=3D"color: #008=
;" class=3D"styled-by-prettify">int</span><span style=3D"color: #000;" clas=
s=3D"styled-by-prettify"> </span><span style=3D"color: #660;" class=3D"styl=
ed-by-prettify">*</span><span style=3D"color: #000;" class=3D"styled-by-pre=
ttify">p </span><span style=3D"color: #660;" class=3D"styled-by-prettify">=
=3D</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span=
><span style=3D"color: #660;" class=3D"styled-by-prettify">&</span><spa=
n style=3D"color: #000;" class=3D"styled-by-prettify">meow</span><span styl=
e=3D"color: #660;" class=3D"styled-by-prettify">.</span><span style=3D"colo=
r: #000;" class=3D"styled-by-prettify">y</span><span style=3D"color: #660;"=
class=3D"styled-by-prettify">;</span><span style=3D"color: #000;" class=3D=
"styled-by-prettify"><br></span><span style=3D"color: #606;" class=3D"style=
d-by-prettify">Meow</span><span style=3D"color: #000;" class=3D"styled-by-p=
rettify"> </span><span style=3D"color: #660;" class=3D"styled-by-prettify">=
*</span><span style=3D"color: #000;" class=3D"styled-by-prettify">kitty </s=
pan><span style=3D"color: #660;" class=3D"styled-by-prettify">=3D</span><sp=
an style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">&(</span><span style=3D"=
color: #000;" class=3D"styled-by-prettify">p</span><span style=3D"color: #6=
60;" class=3D"styled-by-prettify">->*(-&</span><span style=3D"color:=
#606;" class=3D"styled-by-prettify">Meow</span><span style=3D"color: #660;=
" class=3D"styled-by-prettify">::</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify">y</span><span style=3D"color: #660;" class=3D"style=
d-by-prettify">));</span><span style=3D"color: #000;" class=3D"styled-by-pr=
ettify"><br></span><span style=3D"color: #008;" class=3D"styled-by-prettify=
">assert</span><span style=3D"color: #660;" class=3D"styled-by-prettify">(<=
/span><span style=3D"color: #000;" class=3D"styled-by-prettify">kitty </spa=
n><span style=3D"color: #660;" class=3D"styled-by-prettify">=3D=3D</span><s=
pan style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">&</span><span style=3D"c=
olor: #000;" class=3D"styled-by-prettify">meow</span><span style=3D"color: =
#660;" class=3D"styled-by-prettify">);</span></div></code></div><br>This fe=
ature seems unlikely to be added for various reasons.=C2=A0 (It would break=
ABI compatibility, for one: both Microsoft and the UNIX Itanium ABIs use -=
1 to represent null data member pointers currently, and an offset of -1 wou=
ld become a valid member pointer with this feature.)<br><br>Melissa<br></di=
v></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/d43f405b-e8ba-40df-840b-84aa70880201%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/d43f405b-e8ba-40df-840b-84aa70880201=
%40isocpp.org</a>.<br />
------=_Part_1707_507734464.1497643452435--
------=_Part_1706_1979028600.1497643452434--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Fri, 16 Jun 2017 14:07:05 -0700 (PDT)
Raw View
------=_Part_1660_1377784459.1497647225931
Content-Type: multipart/alternative;
boundary="----=_Part_1661_867062561.1497647225932"
------=_Part_1661_867062561.1497647225932
Content-Type: text/plain; charset="UTF-8"
On Friday, June 16, 2017 at 4:04:12 PM UTC-4, Myriachan wrote:
>
> On Friday, June 16, 2017 at 7:49:19 AM UTC-7, Nicol Bolas wrote:
>>
>> On Friday, June 16, 2017 at 4:45:58 AM UTC-4, Edward Catmur wrote:
>>>
>>> Your proposed feature would inhibit certain optimizations that are
>>> currently performed. For example:
>>>
>>> int f(Meow* m, int* i) {
>>> m->x = 42;
>>> reinterpret_cast<Meow*>(reinterpret_cast<char*>(i) -
>>> sizeof(Meow::x))->x = 99; // #1
>>> return m->x;
>>> }
>>> int g() {
>>> Meow m;
>>> return f(&m, &m.y);
>>> }
>>>
>>> Since #1 is UB when called from g, the compiler can optimize g to return
>>> 42, and indeed icc does so at -O2.
>>>
>>
>> I don't think this example is a good example of the problem. Yes, this
>> feature would mean the compiler can't just throw the operation away.
>>
>> *That's the point*.
>>
>> A better example of an optimization problem would be showing us code that
>> is *currently* well-defined, where the compiler would be unable to
>> optimize something away due to the new rules.
>>
>
> This.
>
> Which of these functions do you want to work? If you want all of them to
>> work, then what you're talking about that "block of allocated storage"
>> thing. That means that byte pointer arithmetic should act as though the
>> entire allocation were a byte array. And casting to a byte pointer means
>> getting a pointer to an element in the array.
>>
>> Note that when I say "byte pointer", I mean any of the three byte types,
>> not just `std::byte`.
>>
>
> All three examples ought to work.
>
Then the proposal should not mention the "dynamic type" of the initial
pointer. It should only be talking about pointer arithmetic within the
contiguous region of storage that the object previously had been in.
Also, since you're in the neighborhood, you might also want to fix the
"pointer arithmetic with contiguous objects" problem (aka: why we can't
legally write `std::vector`). Namely, the fact that, technically speaking,
if you create two objects of the same type contiguously, you cannot use
pointer arithmetic to jump from one to the other:
struct X {...};
std::aligned_storage_t<sizeof(X) * 4, alignof(X)> storage;
auto ptr = reinterpret_cast<std::byte*>(&storage);
X *x_array = new (ptr) X;
new(ptr + sizeof(X)) X;
new(ptr + 2 * sizeof(X)) X;
new(ptr + 3 * sizeof(X)) X;
x_array[2]; //UB
The fix for this would be to allow pointer arithmetic to work based on the
the presence of a contiguous sequence of objects of the same dynamic type,
rather than the current wording which works based off of arrays (treating a
single object as an array of size 1). Arrays would naturally create
contiguous sequences of such objects, but users could do so as well, as in
the case above.
--
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 email 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/b7d48388-6ea3-4345-99b2-fe63a1ab5dbf%40isocpp.org.
------=_Part_1661_867062561.1497647225932
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Friday, June 16, 2017 at 4:04:12 PM UTC-4, Myriachan wr=
ote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex=
;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr">On Friday=
, June 16, 2017 at 7:49:19 AM UTC-7, Nicol Bolas wrote:<blockquote class=3D=
"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc soli=
d;padding-left:1ex"><div dir=3D"ltr">On Friday, June 16, 2017 at 4:45:58 AM=
UTC-4, Edward Catmur wrote:<blockquote class=3D"gmail_quote" style=3D"marg=
in:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><div di=
r=3D"ltr">Your proposed feature would inhibit certain optimizations that ar=
e currently performed. For example:<div><br></div><div>int f(Meow* m, int* =
i) {</div><div>=C2=A0 =C2=A0 m->x =3D 42;</div><div>=C2=A0 =C2=A0 reinte=
rpret_cast<Meow*>(<wbr>reinterpret_cast<char*>(i) - sizeof(Meow=
::x))->x =3D 99; // #1</div><div>=C2=A0 =C2=A0 return m->x;<br></div>=
<div>}</div><div>int g() {</div><div>=C2=A0 Meow m;</div><div>=C2=A0 return=
f(&m, &m.y);</div><div>}</div><div><br></div><div>Since #1 is UB w=
hen called from g, the compiler can optimize g to return 42, and indeed icc=
does so at -O2.</div></div></blockquote><div><br>I don't think this ex=
ample is a good example of the problem. Yes, this feature would mean the co=
mpiler can't just throw the operation away.<br><br><i>That's the po=
int</i>.<br><br>A better example of an optimization problem would be showin=
g us code that is <i>currently</i> well-defined, where the compiler would b=
e unable to optimize something away due to the new rules.</div></div></bloc=
kquote><div><br>This.<br><br><blockquote class=3D"gmail_quote" style=3D"mar=
gin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1=
ex">Which of these functions do you want to work? If you want all of them t=
o
work, then what you're talking about that "block of allocated sto=
rage"=20
thing. That means that byte pointer arithmetic should act as though the=20
entire allocation were a byte array. And casting to a byte pointer means
getting a pointer to an element in the array.<br><br>Note that when I say =
"byte pointer", I mean any of the three byte types, not just `std=
::byte`.<br></blockquote><br>All three examples ought to work.<br></div></d=
iv></blockquote><div><br>Then the proposal should not mention the "dyn=
amic type" of the initial pointer. It should only be talking about poi=
nter arithmetic within the contiguous region of storage that the object pre=
viously had been in.<br><br>Also, since you're in the neighborhood, you=
might also want to fix the "pointer arithmetic with contiguous object=
s" problem (aka: why we can't legally write `std::vector`). Namely=
, the fact that, technically speaking, if you create two objects of the sam=
e type contiguously, you cannot use pointer arithmetic to jump from one to =
the other:<br><br><div style=3D"background-color: rgb(250, 250, 250); borde=
r-color: rgb(187, 187, 187); border-style: solid; border-width: 1px; overfl=
ow-wrap: break-word;" class=3D"prettyprint"><code class=3D"prettyprint"><di=
v class=3D"subprettyprint"><span style=3D"color: #008;" class=3D"styled-by-=
prettify">struct</span><span style=3D"color: #000;" class=3D"styled-by-pret=
tify"> X </span><span style=3D"color: #660;" class=3D"styled-by-prettify">{=
....};</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br><=
br>std</span><span style=3D"color: #660;" class=3D"styled-by-prettify">::</=
span><span style=3D"color: #000;" class=3D"styled-by-prettify">aligned_stor=
age_t</span><span style=3D"color: #660;" class=3D"styled-by-prettify"><<=
/span><span style=3D"color: #008;" class=3D"styled-by-prettify">sizeof</spa=
n><span style=3D"color: #660;" class=3D"styled-by-prettify">(</span><span s=
tyle=3D"color: #000;" class=3D"styled-by-prettify">X</span><span style=3D"c=
olor: #660;" class=3D"styled-by-prettify">)</span><span style=3D"color: #00=
0;" class=3D"styled-by-prettify"> </span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">*</span><span style=3D"color: #000;" class=3D"style=
d-by-prettify"> </span><span style=3D"color: #066;" class=3D"styled-by-pret=
tify">4</span><span style=3D"color: #660;" class=3D"styled-by-prettify">,</=
span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><spa=
n style=3D"color: #008;" class=3D"styled-by-prettify">alignof</span><span s=
tyle=3D"color: #660;" class=3D"styled-by-prettify">(</span><span style=3D"c=
olor: #000;" class=3D"styled-by-prettify">X</span><span style=3D"color: #66=
0;" class=3D"styled-by-prettify">)></span><span style=3D"color: #000;" c=
lass=3D"styled-by-prettify"> storage</span><span style=3D"color: #660;" cla=
ss=3D"styled-by-prettify">;</span><span style=3D"color: #000;" class=3D"sty=
led-by-prettify"><br></span><span style=3D"color: #008;" class=3D"styled-by=
-prettify">auto</span><span style=3D"color: #000;" class=3D"styled-by-prett=
ify"> ptr </span><span style=3D"color: #660;" class=3D"styled-by-prettify">=
=3D</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span=
><span style=3D"color: #008;" class=3D"styled-by-prettify">reinterpret_cast=
</span><span style=3D"color: #660;" class=3D"styled-by-prettify"><</span=
><span style=3D"color: #000;" class=3D"styled-by-prettify">std</span><span =
style=3D"color: #660;" class=3D"styled-by-prettify">::</span><span style=3D=
"color: #008;" class=3D"styled-by-prettify">byte</span><span style=3D"color=
: #660;" class=3D"styled-by-prettify">*>(&</span><span style=3D"colo=
r: #000;" class=3D"styled-by-prettify">storage</span><span style=3D"color: =
#660;" class=3D"styled-by-prettify">);</span><span style=3D"color: #000;" c=
lass=3D"styled-by-prettify"><br>X </span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">*</span><span style=3D"color: #000;" class=3D"style=
d-by-prettify">x_array </span><span style=3D"color: #660;" class=3D"styled-=
by-prettify">=3D</span><span style=3D"color: #000;" class=3D"styled-by-pret=
tify"> </span><span style=3D"color: #008;" class=3D"styled-by-prettify">new=
</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><s=
pan style=3D"color: #660;" class=3D"styled-by-prettify">(</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify">ptr</span><span style=3D"col=
or: #660;" class=3D"styled-by-prettify">)</span><span style=3D"color: #000;=
" class=3D"styled-by-prettify"> X</span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">;</span><span style=3D"color: #000;" class=3D"style=
d-by-prettify"><br></span><span style=3D"color: #008;" class=3D"styled-by-p=
rettify">new</span><span style=3D"color: #660;" class=3D"styled-by-prettify=
">(</span><span style=3D"color: #000;" class=3D"styled-by-prettify">ptr </s=
pan><span style=3D"color: #660;" class=3D"styled-by-prettify">+</span><span=
style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D=
"color: #008;" class=3D"styled-by-prettify">sizeof</span><span style=3D"col=
or: #660;" class=3D"styled-by-prettify">(</span><span style=3D"color: #000;=
" class=3D"styled-by-prettify">X</span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">))</span><span style=3D"color: #000;" class=3D"styl=
ed-by-prettify"> X</span><span style=3D"color: #660;" class=3D"styled-by-pr=
ettify">;</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><=
br></span><span style=3D"color: #008;" class=3D"styled-by-prettify">new</sp=
an><span style=3D"color: #660;" class=3D"styled-by-prettify">(</span><span =
style=3D"color: #000;" class=3D"styled-by-prettify">ptr </span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">+</span><span style=3D"color=
: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #066;" =
class=3D"styled-by-prettify">2</span><span style=3D"color: #000;" class=3D"=
styled-by-prettify"> </span><span style=3D"color: #660;" class=3D"styled-by=
-prettify">*</span><span style=3D"color: #000;" class=3D"styled-by-prettify=
"> </span><span style=3D"color: #008;" class=3D"styled-by-prettify">sizeof<=
/span><span style=3D"color: #660;" class=3D"styled-by-prettify">(</span><sp=
an style=3D"color: #000;" class=3D"styled-by-prettify">X</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">))</span><span style=3D"colo=
r: #000;" class=3D"styled-by-prettify"> X</span><span style=3D"color: #660;=
" class=3D"styled-by-prettify">;</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"><br></span><span style=3D"color: #008;" class=3D"st=
yled-by-prettify">new</span><span style=3D"color: #660;" class=3D"styled-by=
-prettify">(</span><span style=3D"color: #000;" class=3D"styled-by-prettify=
">ptr </span><span style=3D"color: #660;" class=3D"styled-by-prettify">+</s=
pan><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span=
style=3D"color: #066;" class=3D"styled-by-prettify">3</span><span style=3D=
"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #=
660;" class=3D"styled-by-prettify">*</span><span style=3D"color: #000;" cla=
ss=3D"styled-by-prettify"> </span><span style=3D"color: #008;" class=3D"sty=
led-by-prettify">sizeof</span><span style=3D"color: #660;" class=3D"styled-=
by-prettify">(</span><span style=3D"color: #000;" class=3D"styled-by-pretti=
fy">X</span><span style=3D"color: #660;" class=3D"styled-by-prettify">))</s=
pan><span style=3D"color: #000;" class=3D"styled-by-prettify"> X</span><spa=
n style=3D"color: #660;" class=3D"styled-by-prettify">;</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"><br>x_array</span><span styl=
e=3D"color: #660;" class=3D"styled-by-prettify">[</span><span style=3D"colo=
r: #066;" class=3D"styled-by-prettify">2</span><span style=3D"color: #660;"=
class=3D"styled-by-prettify">];</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"> </span><span style=3D"color: #800;" class=3D"style=
d-by-prettify">//UB</span></div></code></div><br>The fix for this would be =
to allow pointer arithmetic to work based on the the presence of a contiguo=
us sequence of objects of the same dynamic type, rather than the current wo=
rding which works based off of arrays (treating a single object as an array=
of size 1). Arrays would naturally create contiguous sequences of such obj=
ects, but users could do so as well, as in the case above.</div></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/b7d48388-6ea3-4345-99b2-fe63a1ab5dbf%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/b7d48388-6ea3-4345-99b2-fe63a1ab5dbf=
%40isocpp.org</a>.<br />
------=_Part_1661_867062561.1497647225932--
------=_Part_1660_1377784459.1497647225931--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Fri, 16 Jun 2017 14:14:41 -0700 (PDT)
Raw View
------=_Part_1735_960121149.1497647681760
Content-Type: multipart/alternative;
boundary="----=_Part_1736_209025624.1497647681760"
------=_Part_1736_209025624.1497647681760
Content-Type: text/plain; charset="UTF-8"
On Friday, June 16, 2017 at 5:07:06 PM UTC-4, Nicol Bolas wrote:
>
> Then the proposal should not mention the "dynamic type" of the initial
> pointer. It should only be talking about pointer arithmetic within the
> contiguous region of storage that the object previously had been in.
>
OK, let me try saying that again. The proposal should state that users can
only perform byte pointer arithmetic within the total region of storage
which the initial object (the one the pointer was cast from) was created
within.
The standard says nothing about the relationship between
static/automatic/thread storage duration objects and their regions of
memory. So each of them effectively lives in its own pool of memory; you
can't jump from one object to the other.
But dynamic storage duration objects live within a region of memory that
could come from a dynamic allocations or even static/automatic/thread
regions of memory. As such, multiple "top-level" objects can exist within
the same region of memory.
So it has to be based on the overall region of memory that the object is
stored within, but should not be limited to just the region used by that
object.
--
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 email 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/8606bcb6-8542-4e32-99ef-ed2b968e161a%40isocpp.org.
------=_Part_1736_209025624.1497647681760
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Friday, June 16, 2017 at 5:07:06 PM UTC-4, Nicol Bolas =
wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8=
ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div>Th=
en the proposal should not mention the "dynamic type" of the init=
ial pointer. It should only be talking about pointer arithmetic within the =
contiguous region of storage that the object previously had been in.<br></d=
iv></div></blockquote><div><br>OK, let me try saying that again. The propos=
al should state that users can only perform byte pointer arithmetic within =
the total region of storage which the initial object (the one the pointer w=
as cast from) was created within. <br><br>The standard says nothing about t=
he relationship between static/automatic/thread storage duration objects an=
d their regions of memory. So each of them effectively lives in its own poo=
l of memory; you can't jump from one object to the other.<br><br>But dy=
namic storage duration objects live within a region of memory that could co=
me from a dynamic allocations or even static/automatic/thread regions of me=
mory. As such, multiple "top-level" objects can exist within the =
same region of memory.<br><br>So it has to be based on the overall region o=
f memory that the object is stored within, but should not be limited to jus=
t the region used by that object.<br></div></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/8606bcb6-8542-4e32-99ef-ed2b968e161a%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/8606bcb6-8542-4e32-99ef-ed2b968e161a=
%40isocpp.org</a>.<br />
------=_Part_1736_209025624.1497647681760--
------=_Part_1735_960121149.1497647681760--
.
Author: Myriachan <myriachan@gmail.com>
Date: Fri, 16 Jun 2017 14:41:10 -0700 (PDT)
Raw View
------=_Part_1765_152618944.1497649270602
Content-Type: multipart/alternative;
boundary="----=_Part_1766_338042563.1497649270603"
------=_Part_1766_338042563.1497649270603
Content-Type: text/plain; charset="UTF-8"
On Friday, June 16, 2017 at 2:07:06 PM UTC-7, Nicol Bolas wrote:
>
> Then the proposal should not mention the "dynamic type" of the initial
> pointer. It should only be talking about pointer arithmetic within the
> contiguous region of storage that the object previously had been in.
>
> Also, since you're in the neighborhood, you might also want to fix the
> "pointer arithmetic with contiguous objects" problem (aka: why we can't
> legally write `std::vector`). Namely, the fact that, technically speaking,
> if you create two objects of the same type contiguously, you cannot use
> pointer arithmetic to jump from one to the other:
>
> struct X {...};
>
> std::aligned_storage_t<sizeof(X) * 4, alignof(X)> storage;
> auto ptr = reinterpret_cast<std::byte*>(&storage);
> X *x_array = new (ptr) X;
> new(ptr + sizeof(X)) X;
> new(ptr + 2 * sizeof(X)) X;
> new(ptr + 3 * sizeof(X)) X;
> x_array[2]; //UB
>
> The fix for this would be to allow pointer arithmetic to work based on the
> the presence of a contiguous sequence of objects of the same dynamic type,
> rather than the current wording which works based off of arrays (treating a
> single object as an array of size 1). Arrays would naturally create
> contiguous sequences of such objects, but users could do so as well, as in
> the case above.
>
One problem I see with trying to fix it directly is that objects of the
same type that happen to be adjacent in memory could then be accessible:
struct S { int x; int y; } s;
static_assert(offsetof(S, y) == offsetof(S, x) + sizeof(S::x));
s.y = 42;
(&s.x)[1] = 666;
return s.y; // returns 666
With the fix to the Standard as you describe, wouldn't this either have to
be well-defined or ill-formed (static_assert failure) and never undefined
behavior? Is that a desirable outcome?
By the way, this fix to pointer arithmetic would imply that the flexible
array member paradigm from C works.
Melissa
--
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 email 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/0f9e4b98-edc2-48fc-82e3-535e34120ece%40isocpp.org.
------=_Part_1766_338042563.1497649270603
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Friday, June 16, 2017 at 2:07:06 PM UTC-7, Nicol Bolas =
wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8=
ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr">Then th=
e proposal should not mention the "dynamic type" of the initial p=
ointer. It should only be talking about pointer arithmetic within the conti=
guous region of storage that the object previously had been in.<br><div><br=
>Also, since you're in the neighborhood, you might also want to fix the=
"pointer arithmetic with contiguous objects" problem (aka: why w=
e can't legally write `std::vector`). Namely, the fact that, technicall=
y speaking, if you create two objects of the same type contiguously, you ca=
nnot use pointer arithmetic to jump from one to the other:<br><br><div styl=
e=3D"background-color:rgb(250,250,250);border-color:rgb(187,187,187);border=
-style:solid;border-width:1px"><code><div><span style=3D"color:#008">struct=
</span><span style=3D"color:#000"> X </span><span style=3D"color:#660">{...=
};</span><span style=3D"color:#000"><br><br>std</span><span style=3D"color:=
#660">::</span><span style=3D"color:#000">aligned_storage_t</span><span sty=
le=3D"color:#660"><</span><span style=3D"color:#008">sizeof</span><span =
style=3D"color:#660">(</span><span style=3D"color:#000"><wbr>X</span><span =
style=3D"color:#660">)</span><span style=3D"color:#000"> </span><span style=
=3D"color:#660">*</span><span style=3D"color:#000"> </span><span style=3D"c=
olor:#066">4</span><span style=3D"color:#660">,</span><span style=3D"color:=
#000"> </span><span style=3D"color:#008">alignof</span><span style=3D"color=
:#660">(</span><span style=3D"color:#000">X</span><span style=3D"color:#660=
">)></span><span style=3D"color:#000"> storage</span><span style=3D"colo=
r:#660">;</span><span style=3D"color:#000"><br></span><span style=3D"color:=
#008">auto</span><span style=3D"color:#000"> ptr </span><span style=3D"colo=
r:#660">=3D</span><span style=3D"color:#000"> </span><span style=3D"color:#=
008">reinterpret_cast</span><span style=3D"color:#660"><</span><span sty=
le=3D"color:#000">std</span><span style=3D"color:#660">::</span><span style=
=3D"color:#008">byte</span><span style=3D"color:#660">*>(&</span><sp=
an style=3D"color:#000"><wbr>storage</span><span style=3D"color:#660">);</s=
pan><span style=3D"color:#000"><br>X </span><span style=3D"color:#660">*</s=
pan><span style=3D"color:#000">x_array </span><span style=3D"color:#660">=
=3D</span><span style=3D"color:#000"> </span><span style=3D"color:#008">new=
</span><span style=3D"color:#000"> </span><span style=3D"color:#660">(</spa=
n><span style=3D"color:#000">ptr</span><span style=3D"color:#660">)</span><=
span style=3D"color:#000"> X</span><span style=3D"color:#660">;</span><span=
style=3D"color:#000"><br></span><span style=3D"color:#008">new</span><span=
style=3D"color:#660">(</span><span style=3D"color:#000">ptr </span><span s=
tyle=3D"color:#660">+</span><span style=3D"color:#000"> </span><span style=
=3D"color:#008">sizeof</span><span style=3D"color:#660">(</span><span style=
=3D"color:#000">X</span><span style=3D"color:#660">))</span><span style=3D"=
color:#000"> X</span><span style=3D"color:#660">;</span><span style=3D"colo=
r:#000"><br></span><span style=3D"color:#008">new</span><span style=3D"colo=
r:#660">(</span><span style=3D"color:#000">ptr </span><span style=3D"color:=
#660">+</span><span style=3D"color:#000"> </span><span style=3D"color:#066"=
>2</span><span style=3D"color:#000"> </span><span style=3D"color:#660">*</s=
pan><span style=3D"color:#000"> </span><span style=3D"color:#008">sizeof</s=
pan><span style=3D"color:#660">(</span><span style=3D"color:#000">X</span><=
span style=3D"color:#660">))</span><span style=3D"color:#000"> X</span><spa=
n style=3D"color:#660">;</span><span style=3D"color:#000"><br></span><span =
style=3D"color:#008">new</span><span style=3D"color:#660">(</span><span sty=
le=3D"color:#000">ptr </span><span style=3D"color:#660">+</span><span style=
=3D"color:#000"> </span><span style=3D"color:#066">3</span><span style=3D"c=
olor:#000"> </span><span style=3D"color:#660">*</span><span style=3D"color:=
#000"> </span><span style=3D"color:#008">sizeof</span><span style=3D"color:=
#660">(</span><span style=3D"color:#000">X</span><span style=3D"color:#660"=
>))</span><span style=3D"color:#000"> X</span><span style=3D"color:#660">;<=
/span><span style=3D"color:#000"><br>x_array</span><span style=3D"color:#66=
0">[</span><span style=3D"color:#066">2</span><span style=3D"color:#660">];=
</span><span style=3D"color:#000"> </span><span style=3D"color:#800">//UB</=
span></div></code></div><br>The fix for this would be to allow pointer arit=
hmetic to work based on the the presence of a contiguous sequence of object=
s of the same dynamic type, rather than the current wording which works bas=
ed off of arrays (treating a single object as an array of size 1). Arrays w=
ould naturally create contiguous sequences of such objects, but users could=
do so as well, as in the case above.</div></div></blockquote><div><br>One =
problem I see with trying to fix it directly is that objects of the same ty=
pe that happen to be adjacent in memory could then be accessible:<br><br><d=
iv style=3D"background-color: rgb(250, 250, 250); border-color: rgb(187, 18=
7, 187); border-style: solid; border-width: 1px; overflow-wrap: break-word;=
" class=3D"prettyprint"><code class=3D"prettyprint"><div class=3D"subpretty=
print"><span style=3D"color: #008;" class=3D"styled-by-prettify">struct</sp=
an><span style=3D"color: #000;" class=3D"styled-by-prettify"> S </span><spa=
n style=3D"color: #660;" class=3D"styled-by-prettify">{</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color=
: #008;" class=3D"styled-by-prettify">int</span><span style=3D"color: #000;=
" class=3D"styled-by-prettify"> x</span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">;</span><span style=3D"color: #000;" class=3D"style=
d-by-prettify"> </span><span style=3D"color: #008;" class=3D"styled-by-pret=
tify">int</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> =
y</span><span style=3D"color: #660;" class=3D"styled-by-prettify">;</span><=
span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span styl=
e=3D"color: #660;" class=3D"styled-by-prettify">}</span><span style=3D"colo=
r: #000;" class=3D"styled-by-prettify"> s</span><span style=3D"color: #660;=
" class=3D"styled-by-prettify">;</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"><br></span><span style=3D"color: #008;" class=3D"st=
yled-by-prettify">static_assert</span><span style=3D"color: #660;" class=3D=
"styled-by-prettify">(</span><span style=3D"color: #000;" class=3D"styled-b=
y-prettify">offsetof</span><span style=3D"color: #660;" class=3D"styled-by-=
prettify">(</span><span style=3D"color: #000;" class=3D"styled-by-prettify"=
>S</span><span style=3D"color: #660;" class=3D"styled-by-prettify">,</span>=
<span style=3D"color: #000;" class=3D"styled-by-prettify"> y</span><span st=
yle=3D"color: #660;" class=3D"styled-by-prettify">)</span><span style=3D"co=
lor: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #660=
;" class=3D"styled-by-prettify">=3D=3D</span><span style=3D"color: #000;" c=
lass=3D"styled-by-prettify"> offsetof</span><span style=3D"color: #660;" cl=
ass=3D"styled-by-prettify">(</span><span style=3D"color: #000;" class=3D"st=
yled-by-prettify">S</span><span style=3D"color: #660;" class=3D"styled-by-p=
rettify">,</span><span style=3D"color: #000;" class=3D"styled-by-prettify">=
x</span><span style=3D"color: #660;" class=3D"styled-by-prettify">)</span>=
<span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span sty=
le=3D"color: #660;" class=3D"styled-by-prettify">+</span><span style=3D"col=
or: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #008;=
" class=3D"styled-by-prettify">sizeof</span><span style=3D"color: #660;" cl=
ass=3D"styled-by-prettify">(</span><span style=3D"color: #000;" class=3D"st=
yled-by-prettify">S</span><span style=3D"color: #660;" class=3D"styled-by-p=
rettify">::</span><span style=3D"color: #000;" class=3D"styled-by-prettify"=
>x</span><span style=3D"color: #660;" class=3D"styled-by-prettify">));</spa=
n><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>s</span><sp=
an style=3D"color: #660;" class=3D"styled-by-prettify">.</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify">y </span><span style=3D"colo=
r: #660;" class=3D"styled-by-prettify">=3D</span><span style=3D"color: #000=
;" class=3D"styled-by-prettify"> </span><span style=3D"color: #066;" class=
=3D"styled-by-prettify">42</span><span style=3D"color: #660;" class=3D"styl=
ed-by-prettify">;</span><span style=3D"color: #000;" class=3D"styled-by-pre=
ttify"><br></span><span style=3D"color: #660;" class=3D"styled-by-prettify"=
>(&</span><span style=3D"color: #000;" class=3D"styled-by-prettify">s</=
span><span style=3D"color: #660;" class=3D"styled-by-prettify">.</span><spa=
n style=3D"color: #000;" class=3D"styled-by-prettify">x</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">)[</span><span style=3D"colo=
r: #066;" class=3D"styled-by-prettify">1</span><span style=3D"color: #660;"=
class=3D"styled-by-prettify">]</span><span style=3D"color: #000;" class=3D=
"styled-by-prettify"> </span><span style=3D"color: #660;" class=3D"styled-b=
y-prettify">=3D</span><span style=3D"color: #000;" class=3D"styled-by-prett=
ify"> </span><span style=3D"color: #066;" class=3D"styled-by-prettify">666<=
/span><span style=3D"color: #660;" class=3D"styled-by-prettify">;</span><sp=
an style=3D"color: #000;" class=3D"styled-by-prettify"><br></span><span sty=
le=3D"color: #008;" class=3D"styled-by-prettify">return</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"> s</span><span style=3D"colo=
r: #660;" class=3D"styled-by-prettify">.</span><span style=3D"color: #000;"=
class=3D"styled-by-prettify">y</span><span style=3D"color: #660;" class=3D=
"styled-by-prettify">;</span><span style=3D"color: #000;" class=3D"styled-b=
y-prettify"> =C2=A0</span><span style=3D"color: #800;" class=3D"styled-by-p=
rettify">// returns 666</span><span style=3D"color: #000;" class=3D"styled-=
by-prettify"><br></span></div></code></div><br>With the fix to the Standard=
as you describe, wouldn't this either have to be well-defined or ill-f=
ormed (static_assert failure) and never undefined behavior?=C2=A0 Is that a=
desirable outcome?<br><br>By the way, this fix to pointer arithmetic would=
imply that the flexible array member paradigm from C works.<br><br>Melissa=
<br></div></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/0f9e4b98-edc2-48fc-82e3-535e34120ece%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/0f9e4b98-edc2-48fc-82e3-535e34120ece=
%40isocpp.org</a>.<br />
------=_Part_1766_338042563.1497649270603--
------=_Part_1765_152618944.1497649270602--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Fri, 16 Jun 2017 15:16:52 -0700 (PDT)
Raw View
------=_Part_1785_367478150.1497651412536
Content-Type: multipart/alternative;
boundary="----=_Part_1786_1698932015.1497651412537"
------=_Part_1786_1698932015.1497651412537
Content-Type: text/plain; charset="UTF-8"
On Friday, June 16, 2017 at 5:41:10 PM UTC-4, Myriachan wrote:
>
> On Friday, June 16, 2017 at 2:07:06 PM UTC-7, Nicol Bolas wrote:
>>
>> Then the proposal should not mention the "dynamic type" of the initial
>> pointer. It should only be talking about pointer arithmetic within the
>> contiguous region of storage that the object previously had been in.
>>
>> Also, since you're in the neighborhood, you might also want to fix the
>> "pointer arithmetic with contiguous objects" problem (aka: why we can't
>> legally write `std::vector`). Namely, the fact that, technically speaking,
>> if you create two objects of the same type contiguously, you cannot use
>> pointer arithmetic to jump from one to the other:
>>
>> struct X {...};
>>
>> std::aligned_storage_t<sizeof(X) * 4, alignof(X)> storage;
>> auto ptr = reinterpret_cast<std::byte*>(&storage);
>> X *x_array = new (ptr) X;
>> new(ptr + sizeof(X)) X;
>> new(ptr + 2 * sizeof(X)) X;
>> new(ptr + 3 * sizeof(X)) X;
>> x_array[2]; //UB
>>
>> The fix for this would be to allow pointer arithmetic to work based on
>> the the presence of a contiguous sequence of objects of the same dynamic
>> type, rather than the current wording which works based off of arrays
>> (treating a single object as an array of size 1). Arrays would naturally
>> create contiguous sequences of such objects, but users could do so as well,
>> as in the case above.
>>
>
> One problem I see with trying to fix it directly is that objects of the
> same type that happen to be adjacent in memory could then be accessible:
>
> struct S { int x; int y; } s;
> static_assert(offsetof(S, y) == offsetof(S, x) + sizeof(S::x));
> s.y = 42;
> (&s.x)[1] = 666;
> return s.y; // returns 666
>
> With the fix to the Standard as you describe, wouldn't this either have to
> be well-defined or ill-formed (static_assert failure) and never undefined
> behavior?
>
I suppose so. It's not like people don't write code that does that as it
currently stands. The usual method is by creating a union between a struct
and an array (which is UB to access the wrong one), but sometimes people
just return a pointer to the first member and expect pointer arithmetic to
just work.
> Is that a desirable outcome?
>
I don't think it is an *undesirable* outcome. That is, I don't think it
breaks anything.
By the way, this fix to pointer arithmetic would imply that the flexible
> array member paradigm from C works.
>
Only if it actually contains objects of that type.
--
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 email 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/4c00ff11-c8d6-4c18-81d5-8dc1fe866d92%40isocpp.org.
------=_Part_1786_1698932015.1497651412537
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Friday, June 16, 2017 at 5:41:10 PM UTC-4, Myriachan wr=
ote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex=
;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr">On Friday=
, June 16, 2017 at 2:07:06 PM UTC-7, Nicol Bolas wrote:<blockquote class=3D=
"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc soli=
d;padding-left:1ex"><div dir=3D"ltr">Then the proposal should not mention t=
he "dynamic type" of the initial pointer. It should only be talki=
ng about pointer arithmetic within the contiguous region of storage that th=
e object previously had been in.<br><div><br>Also, since you're in the =
neighborhood, you might also want to fix the "pointer arithmetic with =
contiguous objects" problem (aka: why we can't legally write `std:=
:vector`). Namely, the fact that, technically speaking, if you create two o=
bjects of the same type contiguously, you cannot use pointer arithmetic to =
jump from one to the other:<br><br><div style=3D"background-color:rgb(250,2=
50,250);border-color:rgb(187,187,187);border-style:solid;border-width:1px">=
<code><div><span style=3D"color:#008">struct</span><span style=3D"color:#00=
0"> X </span><span style=3D"color:#660">{...};</span><span style=3D"color:#=
000"><br><br>std</span><span style=3D"color:#660">::</span><span style=3D"c=
olor:#000">aligned_storage_t</span><span style=3D"color:#660"><</span><s=
pan style=3D"color:#008">sizeof</span><span style=3D"color:#660">(</span><s=
pan style=3D"color:#000"><wbr>X</span><span style=3D"color:#660">)</span><s=
pan style=3D"color:#000"> </span><span style=3D"color:#660">*</span><span s=
tyle=3D"color:#000"> </span><span style=3D"color:#066">4</span><span style=
=3D"color:#660">,</span><span style=3D"color:#000"> </span><span style=3D"c=
olor:#008">alignof</span><span style=3D"color:#660">(</span><span style=3D"=
color:#000">X</span><span style=3D"color:#660">)></span><span style=3D"c=
olor:#000"> storage</span><span style=3D"color:#660">;</span><span style=3D=
"color:#000"><br></span><span style=3D"color:#008">auto</span><span style=
=3D"color:#000"> ptr </span><span style=3D"color:#660">=3D</span><span styl=
e=3D"color:#000"> </span><span style=3D"color:#008">reinterpret_cast</span>=
<span style=3D"color:#660"><</span><span style=3D"color:#000">std</span>=
<span style=3D"color:#660">::</span><span style=3D"color:#008">byte</span><=
span style=3D"color:#660">*>(&</span><span style=3D"color:#000"><wbr=
>storage</span><span style=3D"color:#660">);</span><span style=3D"color:#00=
0"><br>X </span><span style=3D"color:#660">*</span><span style=3D"color:#00=
0">x_array </span><span style=3D"color:#660">=3D</span><span style=3D"color=
:#000"> </span><span style=3D"color:#008">new</span><span style=3D"color:#0=
00"> </span><span style=3D"color:#660">(</span><span style=3D"color:#000">p=
tr</span><span style=3D"color:#660">)</span><span style=3D"color:#000"> X</=
span><span style=3D"color:#660">;</span><span style=3D"color:#000"><br></sp=
an><span style=3D"color:#008">new</span><span style=3D"color:#660">(</span>=
<span style=3D"color:#000">ptr </span><span style=3D"color:#660">+</span><s=
pan style=3D"color:#000"> </span><span style=3D"color:#008">sizeof</span><s=
pan style=3D"color:#660">(</span><span style=3D"color:#000">X</span><span s=
tyle=3D"color:#660">))</span><span style=3D"color:#000"> X</span><span styl=
e=3D"color:#660">;</span><span style=3D"color:#000"><br></span><span style=
=3D"color:#008">new</span><span style=3D"color:#660">(</span><span style=3D=
"color:#000">ptr </span><span style=3D"color:#660">+</span><span style=3D"c=
olor:#000"> </span><span style=3D"color:#066">2</span><span style=3D"color:=
#000"> </span><span style=3D"color:#660">*</span><span style=3D"color:#000"=
> </span><span style=3D"color:#008">sizeof</span><span style=3D"color:#660"=
>(</span><span style=3D"color:#000">X</span><span style=3D"color:#660">))</=
span><span style=3D"color:#000"> X</span><span style=3D"color:#660">;</span=
><span style=3D"color:#000"><br></span><span style=3D"color:#008">new</span=
><span style=3D"color:#660">(</span><span style=3D"color:#000">ptr </span><=
span style=3D"color:#660">+</span><span style=3D"color:#000"> </span><span =
style=3D"color:#066">3</span><span style=3D"color:#000"> </span><span style=
=3D"color:#660">*</span><span style=3D"color:#000"> </span><span style=3D"c=
olor:#008">sizeof</span><span style=3D"color:#660">(</span><span style=3D"c=
olor:#000">X</span><span style=3D"color:#660">))</span><span style=3D"color=
:#000"> X</span><span style=3D"color:#660">;</span><span style=3D"color:#00=
0"><br>x_array</span><span style=3D"color:#660">[</span><span style=3D"colo=
r:#066">2</span><span style=3D"color:#660">];</span><span style=3D"color:#0=
00"> </span><span style=3D"color:#800">//UB</span></div></code></div><br>Th=
e fix for this would be to allow pointer arithmetic to work based on the th=
e presence of a contiguous sequence of objects of the same dynamic type, ra=
ther than the current wording which works based off of arrays (treating a s=
ingle object as an array of size 1). Arrays would naturally create contiguo=
us sequences of such objects, but users could do so as well, as in the case=
above.</div></div></blockquote><div><br>One problem I see with trying to f=
ix it directly is that objects of the same type that happen to be adjacent =
in memory could then be accessible:<br><br><div style=3D"background-color:r=
gb(250,250,250);border-color:rgb(187,187,187);border-style:solid;border-wid=
th:1px"><code><div><span style=3D"color:#008">struct</span><span style=3D"c=
olor:#000"> S </span><span style=3D"color:#660">{</span><span style=3D"colo=
r:#000"> </span><span style=3D"color:#008">int</span><span style=3D"color:#=
000"> x</span><span style=3D"color:#660">;</span><span style=3D"color:#000"=
> </span><span style=3D"color:#008">int</span><span style=3D"color:#000"> y=
</span><span style=3D"color:#660">;</span><span style=3D"color:#000"> </spa=
n><span style=3D"color:#660">}</span><span style=3D"color:#000"> s</span><s=
pan style=3D"color:#660">;</span><span style=3D"color:#000"><br></span><spa=
n style=3D"color:#008">static_assert</span><span style=3D"color:#660">(</sp=
an><span style=3D"color:#000">offsetof</span><span style=3D"color:#660">(</=
span><span style=3D"color:#000">S</span><span style=3D"color:#660">,</span>=
<span style=3D"color:#000"> y</span><span style=3D"color:#660">)</span><spa=
n style=3D"color:#000"> </span><span style=3D"color:#660">=3D=3D</span><spa=
n style=3D"color:#000"> offsetof</span><span style=3D"color:#660">(</span><=
span style=3D"color:#000">S</span><span style=3D"color:#660">,</span><span =
style=3D"color:#000"> x</span><span style=3D"color:#660">)</span><span styl=
e=3D"color:#000"> </span><span style=3D"color:#660">+</span><span style=3D"=
color:#000"> </span><span style=3D"color:#008">sizeof</span><span style=3D"=
color:#660">(</span><span style=3D"color:#000">S</span><span style=3D"color=
:#660">::</span><span style=3D"color:#000">x</span><span style=3D"color:#66=
0">));</span><span style=3D"color:#000"><br>s</span><span style=3D"color:#6=
60">.</span><span style=3D"color:#000">y </span><span style=3D"color:#660">=
=3D</span><span style=3D"color:#000"> </span><span style=3D"color:#066">42<=
/span><span style=3D"color:#660">;</span><span style=3D"color:#000"><br></s=
pan><span style=3D"color:#660">(&</span><span style=3D"color:#000">s</s=
pan><span style=3D"color:#660">.</span><span style=3D"color:#000">x</span><=
span style=3D"color:#660">)[</span><span style=3D"color:#066">1</span><span=
style=3D"color:#660">]</span><span style=3D"color:#000"> </span><span styl=
e=3D"color:#660">=3D</span><span style=3D"color:#000"> </span><span style=
=3D"color:#066">666</span><span style=3D"color:#660">;</span><span style=3D=
"color:#000"><br></span><span style=3D"color:#008">return</span><span style=
=3D"color:#000"> s</span><span style=3D"color:#660">.</span><span style=3D"=
color:#000">y</span><span style=3D"color:#660">;</span><span style=3D"color=
:#000"> =C2=A0</span><span style=3D"color:#800">// returns 666</span><span =
style=3D"color:#000"><br></span></div></code></div><br>With the fix to the =
Standard as you describe, wouldn't this either have to be well-defined =
or ill-formed (static_assert failure) and never undefined behavior?</div></=
div></blockquote><div><br>I suppose so. It's not like people don't =
write code that does that as it currently stands. The usual method is by cr=
eating a union between a struct and an array (which is UB to access the wro=
ng one), but sometimes people just return a pointer to the first member and=
expect pointer arithmetic to just work.<br>=C2=A0</div><blockquote class=
=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #cc=
c solid;padding-left: 1ex;"><div dir=3D"ltr"><div>Is that a desirable outco=
me?<br></div></div></blockquote><div><br>I don't think it is an <i>unde=
sirable</i> outcome. That is, I don't think it breaks anything.<br><br>=
</div><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8=
ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div>By=
the way, this fix to pointer arithmetic would imply that the flexible arra=
y member paradigm from C works.<br></div></div></blockquote><div><br>Only i=
f it actually contains objects of that type.<br></div></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/4c00ff11-c8d6-4c18-81d5-8dc1fe866d92%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/4c00ff11-c8d6-4c18-81d5-8dc1fe866d92=
%40isocpp.org</a>.<br />
------=_Part_1786_1698932015.1497651412537--
------=_Part_1785_367478150.1497651412536--
.
Author: Myriachan <myriachan@gmail.com>
Date: Mon, 19 Jun 2017 15:30:59 -0700 (PDT)
Raw View
------=_Part_3844_1927956462.1497911459943
Content-Type: multipart/alternative;
boundary="----=_Part_3845_981891436.1497911459944"
------=_Part_3845_981891436.1497911459944
Content-Type: text/plain; charset="UTF-8"
On Friday, June 16, 2017 at 3:16:52 PM UTC-7, Nicol Bolas wrote:
>
> On Friday, June 16, 2017 at 5:41:10 PM UTC-4, Myriachan wrote:
>>
>> One problem I see with trying to fix it directly is that objects of the
>> same type that happen to be adjacent in memory could then be accessible:
>>
>>
> struct S { int x; int y; } s;
>> static_assert(offsetof(S, y) == offsetof(S, x) + sizeof(S::x));
>> s.y = 42;
>> (&s.x)[1] = 666;
>> return s.y; // returns 666
>>
>> With the fix to the Standard as you describe, wouldn't this either have
>> to be well-defined or ill-formed (static_assert failure) and never
>> undefined behavior?
>>
>
> I suppose so. It's not like people don't write code that does that as it
> currently stands. The usual method is by creating a union between a struct
> and an array (which is UB to access the wrong one), but sometimes people
> just return a pointer to the first member and expect pointer arithmetic to
> just work.
>
>
I work on a project whose 3-vector class has float x, y, z and expects &((&x)[2])
== &z, so I definitely agree that programmers are doing that anyway. >.<
As for unions, there should probably be something done to legitimize
wrong-member union access when the member selection operator is being used
from the union type. The major compilers accept this, and it seems to even
be taught by some as an acceptable solution to avoiding pointer aliasing
problems.
Is that a desirable outcome?
>>
>
> I don't think it is an *undesirable* outcome. That is, I don't think it
> breaks anything.
>
>
Yes, it can only put defined behavior to actions that currently have
undefined behavior, so it's not a breaking change.
My only worry would be with this potentially inhibiting certain compiler
optimizations that compilers already do. Someone above in the thread
pointed out that Intel C++ seems to assume that programmers won't reference
a structure member using a pointer to another structure member of the same
type.
By the way, this fix to pointer arithmetic would imply that the flexible
>> array member paradigm from C works.
>>
>
> Only if it actually contains objects of that type.
>
Having to use do new[](pointer) int[25]; (plus std::launder in some
situations) seems like a reasonable requirement for using flexible array
members.
Adding C's int member[]; syntax to C++ is a separate issue; [1] is often
used as a way around this with current compilers.
Melissa
--
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 email 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/f8439997-c982-4ee4-975e-59763df55012%40isocpp.org.
------=_Part_3845_981891436.1497911459944
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br>On Friday, June 16, 2017 at 3:16:52 PM UTC-7, Nicol Bo=
las wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left:=
0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr">On =
Friday, June 16, 2017 at 5:41:10 PM UTC-4, Myriachan wrote:<blockquote clas=
s=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc =
solid;padding-left:1ex"><div dir=3D"ltr">One problem I see with trying to f=
ix it directly is that objects of the same type that happen to be adjacent =
in memory could then be accessible:<br><div>=C2=A0</div></div></blockquote>=
</div></blockquote><blockquote class=3D"gmail_quote" style=3D"margin: 0;mar=
gin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D=
"ltr"><blockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex=
;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div><div st=
yle=3D"background-color:rgb(250,250,250);border-color:rgb(187,187,187);bord=
er-style:solid;border-width:1px"><code><div><span style=3D"color:#008">stru=
ct</span><span style=3D"color:#000"> S </span><span style=3D"color:#660">{<=
/span><span style=3D"color:#000"> </span><span style=3D"color:#008">int</sp=
an><span style=3D"color:#000"> x</span><span style=3D"color:#660">;</span><=
span style=3D"color:#000"> </span><span style=3D"color:#008">int</span><spa=
n style=3D"color:#000"> y</span><span style=3D"color:#660">;</span><span st=
yle=3D"color:#000"> </span><span style=3D"color:#660">}</span><span style=
=3D"color:#000"> s</span><span style=3D"color:#660">;</span><span style=3D"=
color:#000"><br></span><span style=3D"color:#008">static_assert</span><span=
style=3D"color:#660">(</span><span style=3D"color:#000">offsetof</span><sp=
an style=3D"color:#660">(</span><span style=3D"color:#000">S</span><span st=
yle=3D"color:#660">,</span><span style=3D"color:#000"> y</span><span style=
=3D"color:#660">)</span><span style=3D"color:#000"> </span><span style=3D"c=
olor:#660">=3D=3D</span><span style=3D"color:#000"> offsetof</span><span st=
yle=3D"color:#660">(</span><span style=3D"color:#000">S</span><span style=
=3D"color:#660">,</span><span style=3D"color:#000"> x</span><span style=3D"=
color:#660">)</span><span style=3D"color:#000"> </span><span style=3D"color=
:#660">+</span><span style=3D"color:#000"> </span><span style=3D"color:#008=
">sizeof</span><span style=3D"color:#660">(</span><span style=3D"color:#000=
">S</span><span style=3D"color:#660">::</span><span style=3D"color:#000">x<=
/span><span style=3D"color:#660">));</span><span style=3D"color:#000"><br>s=
</span><span style=3D"color:#660">.</span><span style=3D"color:#000">y </sp=
an><span style=3D"color:#660">=3D</span><span style=3D"color:#000"> </span>=
<span style=3D"color:#066">42</span><span style=3D"color:#660">;</span><spa=
n style=3D"color:#000"><br></span><span style=3D"color:#660">(&</span><=
span style=3D"color:#000">s</span><span style=3D"color:#660">.</span><span =
style=3D"color:#000">x</span><span style=3D"color:#660">)[</span><span styl=
e=3D"color:#066">1</span><span style=3D"color:#660">]</span><span style=3D"=
color:#000"> </span><span style=3D"color:#660">=3D</span><span style=3D"col=
or:#000"> </span><span style=3D"color:#066">666</span><span style=3D"color:=
#660">;</span><span style=3D"color:#000"><br></span><span style=3D"color:#0=
08">return</span><span style=3D"color:#000"> s</span><span style=3D"color:#=
660">.</span><span style=3D"color:#000">y</span><span style=3D"color:#660">=
;</span><span style=3D"color:#000"> =C2=A0</span><span style=3D"color:#800"=
>// returns 666</span><span style=3D"color:#000"><br></span></div></code></=
div><br>With the fix to the Standard as you describe, wouldn't this eit=
her have to be well-defined or ill-formed (static_assert failure) and never=
undefined behavior?</div></div></blockquote><div><br>I suppose so. It'=
s not like people don't write code that does that as it currently stand=
s. The usual method is by creating a union between a struct and an array (w=
hich is UB to access the wrong one), but sometimes people just return a poi=
nter to the first member and expect pointer arithmetic to just work.<br>=C2=
=A0</div></div></blockquote><div><br>I work on a project whose 3-vector cla=
ss has <span style=3D"font-family: courier new,monospace;">float x, y, z</s=
pan> and expects <span style=3D"font-family: courier new,monospace;">&(=
(&x)[2]) =3D=3D &z</span>, so I definitely agree that programmers a=
re doing that anyway. >.<<br><br>As for unions, there should probably=
be something done to legitimize wrong-member union access when the member =
selection operator is being used from the union type.=C2=A0 The major compi=
lers accept this, and it seems to even be taught by some as an acceptable s=
olution to avoiding pointer aliasing problems.<br><br></div><blockquote cla=
ss=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #=
ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><blockquote class=3D"gmail_q=
uote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;paddin=
g-left:1ex"><div dir=3D"ltr"><div>Is that a desirable outcome?<br></div></d=
iv></blockquote><div><br>I don't think it is an <i>undesirable</i> outc=
ome. That is, I don't think it breaks anything.<br><br></div></div></bl=
ockquote><div><br>Yes, it can only put defined behavior to actions that cur=
rently have undefined behavior, so it's not a breaking change.<br><br>M=
y only worry would be with this potentially inhibiting certain compiler opt=
imizations that compilers already do.=C2=A0 Someone above in the thread poi=
nted out that Intel C++ seems to assume that programmers won't referenc=
e a structure member using a pointer to another structure member of the sam=
e type.<br><br></div><blockquote class=3D"gmail_quote" style=3D"margin: 0;m=
argin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=
=3D"ltr"><div></div><blockquote class=3D"gmail_quote" style=3D"margin:0;mar=
gin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr=
"><div>By the way, this fix to pointer arithmetic would imply that the flex=
ible array member paradigm from C works.<br></div></div></blockquote><div><=
br>Only if it actually contains objects of that type.<br></div></div></bloc=
kquote><div><br>Having to use do <span style=3D"font-family: courier new,mo=
nospace;">new[](pointer) int[25];</span> (plus <span style=3D"font-family: =
courier new,monospace;">std::launder</span> in some situations) seems like =
a reasonable requirement for using flexible array members.<br><br>Adding C&=
#39;s <span style=3D"font-family: courier new,monospace;">int member[];</sp=
an> syntax to C++ is a separate issue; <span style=3D"font-family: courier =
new,monospace;">[1]</span> is often used as a way around this with current =
compilers.<br><br>Melissa<br></div></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/f8439997-c982-4ee4-975e-59763df55012%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/f8439997-c982-4ee4-975e-59763df55012=
%40isocpp.org</a>.<br />
------=_Part_3845_981891436.1497911459944--
------=_Part_3844_1927956462.1497911459943--
.