Skip to content

wrong results with union and strict-aliasing #22099

@brunodefraine

Description

@brunodefraine
Bugzilla Link 21725
Version 3.4
OS Linux
CC @aelovikov-intel,@compnerd,@hfinkel,@kosarev,@dobbelaj-snps,@sunfishcode,@RalfJung,@regehr,@zygoloid,@sanjoy,@seanm

Extended Description

The following testcase produces wrong results with '-O1' and higher (tested with llvm-3.4 and llvm-3.5).

#include <stdio.h>

union U {
	short s;
	int i;
} u;

int v = 987;
union U* up = &u;

int main()
{
	for (int i = 0; i < 2; ++i) {
		u.s = v;         // 987
		up->i = 123;     // 123
	}
	printf("%d\n", up->i);   // 123     clang: 123
	printf("%d\n", u.i);     // 123     clang: 987 ******
	printf("%d\n", up->i);   // 123     clang: 987 ******
	printf("%d\n", u.i);     // 123     clang: 987 ******
	return 0;
}

Disabling 'strict-aliasing' makes the problem go away.
We do believe that the behavior should be the same with and without strict-aliasing.

It seems that initially, the write to 'u.s' is moved out of the loop.
(more exactly, after the loop)
Later on the loop is removed, with only the write to 'up->i' remaining.
As the store to 'u.s' is still following, the end result is not what we expect to see.

Metadata

Metadata

Assignees

No one assigned

    Labels

    TBAAType-Based Alias Analysis / Strict AliasingbugzillaIssues migrated from bugzillaclang:codegenIR generation bugs: mangling, exceptions, etc.miscompilation

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions