This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
Re: [std-discussion] Is this union aliasing code well-defined?
- From: Jeffrey Walton <noloader at gmail dot com>
- To: Yubin Ruan <ablacktshirt at gmail dot com>
- Cc: std-discussion at isocpp dot org, gcc-list <gcc at gcc dot gnu dot org>
- Date: Sun, 29 Oct 2017 04:18:56 -0400
- Subject: Re: [std-discussion] Is this union aliasing code well-defined?
- Authentication-results: sourceware.org; auth=none
- References: <128124e9-3df8-41bf-99da-3675429fcb42@isocpp.org> <20171027130038.GB11592@HP>
- Reply-to: noloader at gmail dot com
On Fri, Oct 27, 2017 at 9:00 AM, Yubin Ruan <ablacktshirt@gmail.com> 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 <stdio.h>
>> 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