This is the mail archive of the
gcc-bugs@gcc.gnu.org
mailing list for the GCC project.
[Bug c/33629] New: bad code with -O2 if pointer dereference followed by null test
- From: "david_albert at axiometric dot com" <gcc-bugzilla at gcc dot gnu dot org>
- To: gcc-bugs at gcc dot gnu dot org
- Date: 2 Oct 2007 17:49:27 -0000
- Subject: [Bug c/33629] New: bad code with -O2 if pointer dereference followed by null test
- Reply-to: gcc-bugzilla at gcc dot gnu dot org
With optimization level -Os or -O2, the function below will generate code that
does not perform the conditional test. The test is necessary on embedded
systems where de-referencing a pointer to address 0 may be legitimate and would
not cause an exception in the de-reference of b (line 4). The defect occurs in
all tested versions of gcc including native and cross compilers:
host:i686-pc-cygwin/target:arm-elf-gcc/build:3.4.0,
host:i686-pc-cygwin/target:arm-elf-gcc/build:4.2.0 (GNUARM)
host:i686-pc-cygwin/target:i686-pc-cygwin/build:3.4.4
host:i486-linux-gnu/target:i486-linux-gnu/build:4.1.2 (20061115 prerelease -
debian4.1.1-21)
The assembly output shows that the assignment d=c (on line 8) is performed
without performing the conditional test for a non-null value of b (line 7):
-------------------------------------------------
void bad_code(void *a)
{
int *b = a;
int c = *b;
static int d;
if (b) {
d = c;
}
}
$ arm-elf-gcc -c -g -MD -I. -mcpu=arm7tdmi -mthumb-interwork -std=c99 -Os -Wall
-Werror test.c -o test.o
$ arm-elf-objdump -S test.o
test.o: file format elf32-littlearm
Disassembly of section .text:
00000000 <bad_code>:
int c = *b;
static int d;
if (b) {
d = c;
0: e5902000 ldr r2, [r0]
4: e59f3004 ldr r3, [pc, #4] ; 10 <.text+0x10>
8: e5832000 str r2, [r3]
}
}
c: e12fff1e bx lr
10: 00000000 andeq r0, r0, r0
Same code compiled with native cygwin compiler: (3.4.4)
$ gcc -O2 -c test.c -o test.o
$ objdump -S test.o
test.o: file format pe-i386
Disassembly of section .text:
00000000 <_bad_code>:
0: 55 push %ebp
1: 89 e5 mov %esp,%ebp
3: 8b 45 08 mov 0x8(%ebp),%eax
6: 5d pop %ebp
7: 8b 00 mov (%eax),%eax
9: a3 00 00 00 00 mov %eax,0x0
e: c3 ret
f: 90 nop
Same code compiled on Native linux-gnu (4.1.2):
foo.o: file format elf32-i386
Disassembly of section .text:
00000000 <bad_code>:
0: 55 push %ebp
1: 89 e5 mov %esp,%ebp
3: 8b 45 08 mov 0x8(%ebp),%eax
6: 5d pop %ebp
7: 8b 00 mov (%eax),%eax
9: a3 00 00 00 00 mov %eax,0x0
e: c3 ret
It appears that the optimizer takes the dereference of b as an implicit sign
that b can be assumed to be non-zero after that point in the code - certainly,
on a cygwin or linux system, dereferencing a zero address causes a segmentation
fault, but on an embedded arm system, this is the most practical way to access
the interrupt vectors from C.
--
Summary: bad code with -O2 if pointer dereference followed by
null test
Product: gcc
Version: 4.2.1
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: c
AssignedTo: unassigned at gcc dot gnu dot org
ReportedBy: david_albert at axiometric dot com
GCC build triplet: 4.2.1
GCC host triplet: i486-linux-gnu
GCC target triplet: arm-elf-gcc
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=33629