From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 31746 invoked by alias); 2 Oct 2007 17:49:37 -0000 Received: (qmail 31734 invoked by uid 48); 2 Oct 2007 17:49:27 -0000 Date: Tue, 02 Oct 2007 17:49:00 -0000 Subject: [Bug c/33629] New: bad code with -O2 if pointer dereference followed by null test X-Bugzilla-Reason: CC Message-ID: Reply-To: gcc-bugzilla@gcc.gnu.org To: gcc-bugs@gcc.gnu.org From: "david_albert at axiometric dot com" Mailing-List: contact gcc-bugs-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Archive: List-Post: List-Help: Sender: gcc-bugs-owner@gcc.gnu.org X-SW-Source: 2007-10/txt/msg00154.txt.bz2 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 : 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 : 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