Re: [std-discussion] Is this union aliasing code well-defined?
On October 29, 2017 2:46:42 AM GMT+01:00, Yubin Ruan wrote: >On 10/27/2017 04:54 PM, Richard Biener wrote: >> On Fri, Oct 27, 2017 at 3:00 PM, Yubin Ruan >wrote: >>> +Cc gcc-list. >>> >>> Does any gcc developer have any comments? >> >> See PR82224. The code is valid. >> >>> On Mon, Sep 25, 2017 at 01:41:55PM -0700, Myriachan wrote: This question that "supercat" posted on Stack Overflow ran into an interesting problem: >https://stackoverflow.com/questions/46205744/is-this-use-of-unions-strictly-conforming/ A copy of the code involved is as follows: struct s1 {unsigned short x;}; struct s2 {unsigned short x;}; union s1s2 { struct s1 v1; struct s2 v2; }; static int read_s1x(struct s1 *p) { return p->x; } static void write_s2x(struct s2 *p, int v) { p->x=v;} int test(union s1s2 *p1, union s1s2 *p2, union s1s2 *p3) { if (read_s1x(&p1->v1)) { unsigned short temp; temp = p3->v1.x; p3->v2.x = temp; write_s2x(&p2->v2,1234); temp = p3->v2.x; p3->v1.x = temp; } return read_s1x(&p1->v1); } int test2(int x) { union s1s2 q[2]; q->v1.x = 4321; return test(q,q+x,q+x); } #include int main(void) { printf("%d\n",test2(0)); } Both GCC and Clang in -fstrict-aliasing mode with optimizations are >acting as if they ran into undefined behavior, and return 4321 instead of >the expected 1234. This happens in both C and C++ mode. Intel C++ and >Visual C++ return the expected 1234. All four compilers hardwire the >result as a constant parameter to printf rather than call test2 or modify >memory at runtime. From my reading of the C++ Standard, particularly [class.union]/5, assignment expressions through a union member access changes the >active member of the union (if the union member has a trivial default >constructor, which it does here, being C code). Taking the address of p2->v2 >and p1->v1 ought to be legal because those are the active members of the union >at the time their pointers are taken. Is this a well-defined program, or is there subtle undefined >behavior happening here? > >Thanks. > >As put in my stackoverflow answer[1], I believe this behavior is >specified in >the GCC-online-doc, in section `-fstrict-alisgin'[2]: > >Pay special attention to code like this: > >union a_union { > int i; > double d; >}; > >int f() { > union a_union t; > t.d = 3.0; > return t.i; >} > >The practice of reading from a different union member than the one most >recently written to (called *type-punning*) is common. Even with > *-fstrict-aliasing*, type-punning is allowed, provided the memory is > accessed through the union type. So, the code above works as expected. >See Structures unions enumerations and bit-fields implementation. >However, this code might not: > >int f() { > union a_union t; > int* ip; > t.d = 3.0; > ip = &t.i; > return *ip; >} The difference is that in the original example the dynamic type of the memory is changed by a store to the union member via the union type. So this doesn't apply. Richard. > Similarly, access by taking the address, casting the resulting pointer > and dereferencing the result has undefined behavior, even if the cast >uses a union type, e.g.: > >int f() { > double d = 3.0; > return ((union a_union *) &d)->i; >} > >The -fstrict-aliasing option is enabled at levels -O2, -O3, -Os. > >I think the second example above is similar to the OP's question >(although the >C standard might not say so... so from my perspective if the second >example >above is true, the OP's code is invalid. > >Do anyone have any comment? > >Yubin > >[1]: >https://stackoverflow.com/questions/46205744/is-this-use-of-unions-strictly-conforming/46968235?noredirect=1#comment80930683_46968235 >[2]: https://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html
Re: [std-discussion] Is this union aliasing code well-defined?
On Fri, Oct 27, 2017 at 9:00 AM, Yubin Ruan wrote: > ... > On Mon, Sep 25, 2017 at 01:41:55PM -0700, Myriachan wrote: >> This question that "supercat" posted on Stack Overflow ran into an >> interesting problem: >> >> https://stackoverflow.com/questions/46205744/is-this-use-of-unions-strictly-conforming/ >> >> A copy of the code involved is as follows: >> >> struct s1 {unsigned short x;}; >> struct s2 {unsigned short x;}; >> union s1s2 { struct s1 v1; struct s2 v2; }; >> >> static int read_s1x(struct s1 *p) { return p->x; } >> static void write_s2x(struct s2 *p, int v) { p->x=v;} >> >> int test(union s1s2 *p1, union s1s2 *p2, union s1s2 *p3) >> { >> if (read_s1x(&p1->v1)) >> { >> unsigned short temp; >> temp = p3->v1.x; >> p3->v2.x = temp; >> write_s2x(&p2->v2,1234); >> temp = p3->v2.x; >> p3->v1.x = temp; >> } >> return read_s1x(&p1->v1); >> } >> int test2(int x) >> { >> union s1s2 q[2]; >> q->v1.x = 4321; >> return test(q,q+x,q+x); >> } >> #include >> int main(void) >> { >> printf("%d\n",test2(0)); >> } >> >> >> Both GCC and Clang in -fstrict-aliasing mode with optimizations are acting >> as if they ran into undefined behavior, and return 4321 instead of the >> expected 1234. This happens in both C and C++ mode. Intel C++ and Visual >> C++ return the expected 1234. All four compilers hardwire the result as a >> constant parameter to printf rather than call test2 or modify memory at >> runtime. C++ is different than C, and C++ is more strict. Unlike C, you cannot access the inactive members of a union in C++. It is undefined behavior. If you compile with Sun's C++ compiler it actually issues a warning for doing so. Clang, GCC, ICC and MSVC does not issue a warning. Also see https://stackoverflow.com/questions/11373203/accessing-inactive-union-member-and-undefined-behavior. Jeff
Re: Problems in IPA passes
Hi Jeff, On 28 October 2017 at 18:28, Jeff Law wrote: > > Jan, > > What's the purpose behind calling vrp_meet and > extract_range_from_unary_expr from within the IPA passes? This is used such that when we have an argument to a function and this for which we know the VR and this intern is passed as a parameter to another. For example: void foo (int i) { ... bar (unary_op (i)) ... } This is mainly to share what is done in tree-vrp. > > AFAICT that is not safe to do. Various paths through those routines > will access static objects within tree-vrp.c which may not be > initialized when IPA runs (vrp_equiv_obstack, vr_value). IPA-VRP does not track equivalence and vr_value is not used. Thanks, Kugan > > While this seems to be working today, it's a failure waiting to happen. > > Is there any way you can avoid using those routines? I can't believe > you really need all the complexity of those routines, particularly > extract_range_from_unary_expr. Plus it's just downright fugly from a > modularity standpoint. > > > ? > > Jeff
gcc-8-20171029 is now available
Snapshot gcc-8-20171029 is now available on ftp://gcc.gnu.org/pub/gcc/snapshots/8-20171029/ and on various mirrors, see http://gcc.gnu.org/mirrors.html for details. This snapshot has been generated from the GCC 8 SVN branch with the following options: svn://gcc.gnu.org/svn/gcc/trunk revision 254205 You'll find: gcc-8-20171029.tar.xzComplete GCC SHA256=77d7b00d24911bfc7b6f15a19191a8d7341844fd8a0ba1187ce34e4b832a SHA1=5b8ca9ff022c97e2a1752fcfbbe7613ae05ff113 Diffs from 8-20171022 are available in the diffs/ subdirectory. When a particular snapshot is ready for public consumption the LATEST-8 link is updated and a message is sent to the gcc list. Please do not use a snapshot before it has been announced that way.
Re: [std-discussion] Is this union aliasing code well-defined?
In math, once you reach a contradiction, you realize that one of your premises was false. In religion, once you reach a contradiction, you write books of theology to paper over the mess. I guess we know what category type-based alias analysis falls under.