This is the mail archive of the
gcc-bugs@gcc.gnu.org
mailing list for the GCC project.
[Bug c++/15069] New: a bit test on a variable of enum type is miscompiled
- From: "gcc-bugzilla at gcc dot gnu dot org" <gcc-bugzilla at gcc dot gnu dot org>
- To: gcc-bugs at gcc dot gnu dot org
- Date: 22 Apr 2004 12:52:19 -0000
- Subject: [Bug c++/15069] New: a bit test on a variable of enum type is miscompiled
- Reply-to: gcc-bugzilla at gcc dot gnu dot org
When testing a bit of a variable with enum type, the test for the
highest bit (bit 2 in my case) is compiled to a bit test for bit 31.
But bit 31 is always zero for all possible values of the enum type.
Environment:
System: Linux honolulu.ilog.fr 2.4.21-0.13mdk #1 Fri Mar 14 15:08:06 EST 2003 i686 unknown unknown GNU/Linux
Architecture: i686
host: i686-pc-linux-gnu
build: i686-pc-linux-gnu
target: i686-pc-linux-gnu
configured with: ../gcc-3.4.0/configure --prefix=/home/haible/gnu/arch/linuxgcc34 --enable-shared --enable-threads --enable-__cxa_atexit --enable-languages=c,c++,f77,java,objc --enable-nls
How-To-Repeat:
============================== bug.cc ===================================
extern "C" void abort (void);
void* allocate_stream (unsigned char strmflags)
{
if (strmflags == 0)
abort ();
return 0;
}
typedef enum {
DIRECTION_PROBE = 0,
DIRECTION_INPUT = 1,
DIRECTION_INPUT_IMMUTABLE = 3,
DIRECTION_OUTPUT = 4,
DIRECTION_IO = 5
} direction_t;
void* make_unbuffered_stream (direction_t direction, int* eltype)
{
unsigned char flags =
(((direction) & (1L<<(0))) ? ((1L<<(4)) | (1L<<(6))) : 0)
| (((direction) & (1L<<(2))) ? ((1L<<(5)) | (1L<<(7))) : 0)
| (((direction) & (1L<<(1))) ? (1L<<(1)) : 0);
if (*eltype == 0)
flags &= ((1L<<(6)) | (1L<<(7))) | (1L<<(1));
else
flags &= ((1L<<(4)) | (1L<<(5))) | (1L<<(1));
return allocate_stream (flags);
}
int main ()
{
int x = 1;
make_unbuffered_stream (DIRECTION_OUTPUT, &x);
return 0;
}
=========================================================================
$ g++ bug.cc
$ ./a.out
Aborted
Here is the assembler code:
======================== g++ -O -S bug.cc ===============================
.file "bug.cc"
.text
.align 2
.globl _Z15allocate_streamh
.type _Z15allocate_streamh, @function
_Z15allocate_streamh:
.LFB2:
pushl %ebp
.LCFI0:
movl %esp, %ebp
.LCFI1:
subl $8, %esp
.LCFI2:
cmpb $0, 8(%ebp)
jne .L2
call abort
.L2:
movl $0, %eax
leave
ret
.LFE2:
.size _Z15allocate_streamh, .-_Z15allocate_streamh
.align 2
.globl _Z22make_unbuffered_stream11direction_tPi
.type _Z22make_unbuffered_stream11direction_tPi, @function
_Z22make_unbuffered_stream11direction_tPi:
.LFB3:
pushl %ebp
.LCFI3:
movl %esp, %ebp
.LCFI4:
subl $8, %esp
.LCFI5:
movl 8(%ebp), %edx
movb %dl, %al
andb $1, %al ; test bit 0 - correct
cmpb $1, %al
sbbl %eax, %eax
notl %eax
andl $80, %eax
testl %edx, %edx ; test bit 31 instead of bit 2 - wrong
jns .L6
orl $160, %eax
.L6:
testb $2, %dl ; test bit 1 - correct
je .L7
orl $2, %eax
.L7:
movb %al, %dl
movl 12(%ebp), %eax
cmpl $0, (%eax)
jne .L8
andb $-62, %dl
jmp .L9
.L8:
andb $50, %dl
.L9:
movzbl %dl, %eax
movl %eax, (%esp)
call _Z15allocate_streamh
leave
ret
.LFE3:
.size _Z22make_unbuffered_stream11direction_tPi, .-_Z22make_unbuffered_stream11direction_tPi
.align 2
.globl main
.type main, @function
main:
.LFB4:
pushl %ebp
.LCFI6:
movl %esp, %ebp
.LCFI7:
subl $24, %esp
.LCFI8:
andl $-16, %esp
subl $16, %esp
movl $1, -4(%ebp)
leal -4(%ebp), %eax
movl %eax, 4(%esp)
movl $4, (%esp)
call _Z22make_unbuffered_stream11direction_tPi
movl $0, %eax
leave
ret
.LFE4:
.size main, .-main
.section .eh_frame,"a",@progbits
.Lframe1:
.long .LECIE1-.LSCIE1
.LSCIE1:
.long 0x0
.byte 0x1
.string "zP"
.uleb128 0x1
.sleb128 -4
.byte 0x8
.uleb128 0x5
.byte 0x0
.long __gxx_personality_v0
.byte 0xc
.uleb128 0x4
.uleb128 0x4
.byte 0x88
.uleb128 0x1
.align 4
.LECIE1:
.LSFDE1:
.long .LEFDE1-.LASFDE1
.LASFDE1:
.long .LASFDE1-.Lframe1
.long .LFB2
.long .LFE2-.LFB2
.uleb128 0x0
.byte 0x4
.long .LCFI0-.LFB2
.byte 0xe
.uleb128 0x8
.byte 0x85
.uleb128 0x2
.byte 0x4
.long .LCFI1-.LCFI0
.byte 0xd
.uleb128 0x5
.align 4
.LEFDE1:
.LSFDE3:
.long .LEFDE3-.LASFDE3
.LASFDE3:
.long .LASFDE3-.Lframe1
.long .LFB3
.long .LFE3-.LFB3
.uleb128 0x0
.byte 0x4
.long .LCFI3-.LFB3
.byte 0xe
.uleb128 0x8
.byte 0x85
.uleb128 0x2
.byte 0x4
.long .LCFI4-.LCFI3
.byte 0xd
.uleb128 0x5
.align 4
.LEFDE3:
.LSFDE5:
.long .LEFDE5-.LASFDE5
.LASFDE5:
.long .LASFDE5-.Lframe1
.long .LFB4
.long .LFE4-.LFB4
.uleb128 0x0
.byte 0x4
.long .LCFI6-.LFB4
.byte 0xe
.uleb128 0x8
.byte 0x85
.uleb128 0x2
.byte 0x4
.long .LCFI7-.LCFI6
.byte 0xd
.uleb128 0x5
.align 4
.LEFDE5:
.section .note.GNU-stack,"",@progbits
.ident "GCC: (GNU) 3.4.0"
=========================================================================
------- Additional Comments From bruno at clisp dot org 2004-04-22 12:52 -------
Fix:
My workaround is to use the C compiler instead of the C++ compiler.
--
Summary: a bit test on a variable of enum type is miscompiled
Product: gcc
Version: 3.4
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: c++
AssignedTo: unassigned at gcc dot gnu dot org
ReportedBy: bruno at clisp dot org
CC: gcc-bugs at gcc dot gnu dot org
GCC build triplet: i686-pc-linux-gnu
GCC host triplet: i686-pc-linux-gnu
GCC target triplet: i686-pc-linux-gnu
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=15069