Sam McCall via llvm-dev
2018-Aug-10 16:08 UTC
[llvm-dev] GCC 5 and -Wstrict-aliasing in JSON.h
json::Value in JSON.h is a discriminated union. The storage is a char array of appropriate type and alignment. The storage holds one object at a time, it's initialized (and for nontrivial types, destroyed) at the right times to ensure this. The cast is only to the type of object that's already there, there's no magic here. On Fri, Aug 10, 2018, 17:52 Andrew Haley <aph at redhat.com> wrote:> On 08/10/2018 05:30 AM, Liu Hao wrote: > > Only an lvalue of a pointer to (possibly CV-qualified) `void` or a > > pointer to a character type (in C) / any of `char`, `unsigned char` or > > `std::byte` (in C++) can alias objects. > > Yes. > > > That is to say, in order to eliminate the aliasing problem an > > intermediate lvalue pointer is required. > > Not exactly. You can cast a pointer to a pointer to some character > type or the type of the object stored in memory. It does not matter > whether you use an intermediate type or not. Having not seen the test > case, I can't tell whether this rule is followed. > > What you can't do is store as a double, cast the double pointer to a > character pointer, cast that pointer to some other pointer type, and > read from memory. GCC won't give you a warning for that, but it's > still undefined. > > JSON.h seems to hope that if you cast a pointer to T to a pointer to > some union type, magic will happen. It won't work, unless the object > stored in the memory at that address was stored as the union type. > > Do not lie to the compiler or it will get its revenge. > > -- > Andrew Haley > Java Platform Lead Engineer > Red Hat UK Ltd. <https://www.redhat.com> > EAC8 43EB D3EF DB98 CC77 2FAD A5CD 6035 332F A671 >-------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20180810/ba826ae9/attachment.html>
Kim Gräsman via llvm-dev
2018-Aug-10 21:30 UTC
[llvm-dev] GCC 5 and -Wstrict-aliasing in JSON.h
On Fri, Aug 10, 2018 at 6:08 PM, Sam McCall <sam.mccall at gmail.com> wrote:> json::Value in JSON.h is a discriminated union. > The storage is a char array of appropriate type and alignment. The storage > holds one object at a time, it's initialized (and for nontrivial types, > destroyed) at the right times to ensure this. The cast is only to the type > of object that's already there, there's no magic here. > > > On Fri, Aug 10, 2018, 17:52 Andrew Haley <aph at redhat.com> wrote: >> >> Not exactly. You can cast a pointer to a pointer to some character >> type or the type of the object stored in memory. It does not matter >> whether you use an intermediate type or not. Having not seen the test >> case, I can't tell whether this rule is followed.Yes, if Andrew's explanation agrees with the standard, then this code should be benign (if it breaks any of these rules, that's a bug in and of itself). So maybe we're back to figuring out how to silence GCC's warning machinery :) - Kim
Kim Gräsman via llvm-dev
2018-Aug-12 13:19 UTC
[llvm-dev] GCC 5 and -Wstrict-aliasing in JSON.h
I did some more extensive testing and found that all GCCs older than 7 trigger the warning, but only if CMAKE_BUILD_TYPE=Release (which I guess indicates optimizations are enabled). There's a patch up for disabling the warning here: https://reviews.llvm.org/D50607. I still feel a little uncomfortable, because I think Jonathan makes an excellent point -- if GCC thinks there's a strict-aliasing violation (whether the standard agrees or not) and classifies this as undefined behavior, we might invoke the optimizers wrath. The warning is a nice hint that this could happen. While writing this I realized that LH_Mouse's double static_cast also silences the warning, and I think that's a nicer workaround, so I put up a patch for that too, here: https://reviews.llvm.org/D50608 Let me know what you think, - Kim On Fri, Aug 10, 2018 at 11:30 PM Kim Gräsman <kim.grasman at gmail.com> wrote:> > On Fri, Aug 10, 2018 at 6:08 PM, Sam McCall <sam.mccall at gmail.com> wrote: > > json::Value in JSON.h is a discriminated union. > > The storage is a char array of appropriate type and alignment. The storage > > holds one object at a time, it's initialized (and for nontrivial types, > > destroyed) at the right times to ensure this. The cast is only to the type > > of object that's already there, there's no magic here. > > > > > > On Fri, Aug 10, 2018, 17:52 Andrew Haley <aph at redhat.com> wrote: > >> > >> Not exactly. You can cast a pointer to a pointer to some character > >> type or the type of the object stored in memory. It does not matter > >> whether you use an intermediate type or not. Having not seen the test > >> case, I can't tell whether this rule is followed. > > Yes, if Andrew's explanation agrees with the standard, then this code > should be benign (if it breaks any of these rules, that's a bug in and > of itself). > > So maybe we're back to figuring out how to silence GCC's warning machinery :) > > - Kim