GCC generates bad code with zero length array and -O3
Affects | Status | Importance | Assigned to | Milestone | |
---|---|---|---|---|---|
gcc |
Fix Released
|
Medium
|
|||
gcc-5 (Ubuntu) |
New
|
Undecided
|
Unassigned | ||
gcc-6 (Ubuntu) |
Fix Released
|
Undecided
|
Unassigned |
Bug Description
With the program below, if I compile it with '-O3 -DFLEX' I get good code but if I compile it with '-O3 -UFLEX' then I get bad code. The program is (unfortunately) not runnable but if you generate
assembly language you can see that the good version has a loop with ldr/str/ldr/str and the bad
version has a loop with ldr/ldr/str/str. I.e. the second load has been moved to be before the first store and if they are referencing the same memory that will result in incorrect behavior.
It is unclear to me why declaring the array 'o' at the end of struct 's' as a zero length array
instead of a C99 flexible array would affect the code generation but it does. The version with
the flexible array works, the version with a zero length array does not work (i.e. it moves the
second load up to before the first store).
Test case (compile with -O3 and either -DFLEX or -UFLEX):
struct q {
int b;
};
struct r {
int n;
struct q slot[0];
};
struct s {
int n;
#ifdef FLEX
long int o[];
#else
long int o[0];
#endif
};
extern int x, y, m;
extern struct s *a;
extern struct r *b;
extern void bar();
int foo() {
int i,j;
for (i = 0; i < m; i++) {
a->o[i] = sizeof(*a);
b = ((struct r *)(((char *)a) + a->o[a->n]));
for (j = 0; j < 10; j++) {
b->slot[j].b = 0;
}
bar();
}
}
ProblemType: Bug
DistroRelease: Ubuntu 16.04
Package: gcc 4:5.3.1-1ubuntu1
Uname: Linux 4.10.0-
ApportVersion: 2.20.1-0ubuntu2.5
Architecture: arm64
Date: Fri Apr 21 16:07:53 2017
JournalErrors:
Error: command ['journalctl', '-b', '--priority=
No journal files were opened due to insufficient permissions.
ProcEnviron:
TERM=xterm-
PATH=(custom, no user)
XDG_RUNTIME_
LANG=en_US.UTF-8
SHELL=/bin/bash
SourcePackage: gcc-defaults
UpgradeStatus: No upgrade log present (probably fresh install)
Changed in gcc-defaults: | |
importance: | Unknown → Medium |
status: | Unknown → In Progress |
affects: | gcc-defaults → gcc |
affects: | gcc-defaults (Ubuntu) → gcc-6 (Ubuntu) |
Changed in gcc: | |
status: | In Progress → Fix Released |
Created attachment 41274
Test case
GCC should treat zero length arrays like C99 flexible arrays when they are
at the end of a structure. I.e. recognize that accesses to that array may
go beyond the end of the structure. GCC has been treating zero length
arrays and flexible arrays differently since at least 5.0.
This was found on aarch64 but the bug is not platform specific. A test case aliasing and either -UFLEX or -DFLEX you can see the store/store load/store for
is attached, it cannot be run but if compiled for aarch64 with
-O2 -fno-strict-
different code. In the -UFLEX case it generates a load/load/
sequence and in the -DFLEX case it generates load/store/
the code in the main loop.
See also:
https:/ /gcc.gnu. org/ml/ gcc/2017- 04/msg00118. html /gcc.gnu. org/ml/ gcc-patches/ 2017-04/ msg01257. html
https:/