[gnu.gcc.bug] Bug with case ranges in unsigned switch with -traditional

thorinn@DIKU.DK (Lars Henrik Mathiesen) (09/12/89)

Viz.

skinfaxe% cat tst.c
main()
{
	unsigned char c;
	int i;

	for (i = 127; i < 130; i++)
		switch(c = i) {
		    case 127:
		    case 128:
		    case 129:
		    	printf("%d\n", c);
			break;
		    default:
			printf("default %d\n", c);
		}
}
skinfaxe% gcc -v -dr -O -traditional -o tst tst.c
gcc version 1.35
 /usr/lib/gnu/gcc-cpp -v -undef -D__GNUC__ -Dsparc -Dsun -Dunix -D__sparc__ -D__sun__ -D__unix__ -D__OPTIMIZE__ -traditional tst.c /tmp/cca01424.cpp
GNU CPP version 1.35
 /usr/lib/gnu/gcc-cc1 /tmp/cca01424.cpp -quiet -dumpbase tst.c -dr -O -traditional -version -o /tmp/cca01424.s
GNU C version 1.35 (sparc) compiled by GNU C version 1.35.
 as -o tst.o /tmp/cca01424.s
 ld -o tst -e start -dc -dp /lib/crt0.o tst.o /usr/lib/gnu/gcc-gnulib -lc
skinfaxe% tst
127
default 128
default 129
skinfaxe% cat tst.c.rtl

;; Function main

(note 1 0 2 "" NOTE_INSN_DELETED)

(note 2 1 3 "" NOTE_INSN_BLOCK_BEG)

(insn 3 2 4 (set (reg/v:SI 65)
       (const_int 127)) -1 (nil)
   (nil))

(note 4 3 46 "" NOTE_INSN_LOOP_BEG)

(jump_insn 46 4 47 (set (pc)
       (label_ref 5)) -1 (nil)
   (nil))

(barrier 47 46 45)

(code_label 45 47 8 11)

(note 8 45 30 "" NOTE_INSN_DELETED)

(insn 30 8 31 (set (reg/v:QI 64)
       (subreg:QI (reg/v:SI 65) 0)) -1 (nil)
   (nil))

(insn 31 30 32 (set (reg:SI 68)
       (sign_extend:SI (reg/v:QI 64))) -1 (nil)
   (nil))

(insn 32 31 33 (set (reg:SI 69)
       (const_int 129)) -1 (nil)
   (nil))

(insn 33 32 34 (set (cc0)
       (compare (reg:SI 68)
           (reg:SI 69))) -1 (nil)
   (nil))

(jump_insn 34 33 35 (set (pc)
       (if_then_else (gtu (cc0)
               (const_int 0))
           (label_ref 22)
           (pc))) -1 (nil)
   (nil))

(insn 35 34 36 (set (reg:SI 70)
       (sign_extend:SI (reg/v:QI 64))) -1 (nil)
   (nil))

(insn 36 35 37 (set (reg:SI 71)
       (const_int 127)) -1 (nil)
   (nil))

(insn 37 36 38 (set (cc0)
       (compare (reg:SI 70)
           (reg:SI 71))) -1 (nil)
   (nil))

(jump_insn 38 37 39 (set (pc)
       (if_then_else (geu (cc0)
               (const_int 0))
           (label_ref 10)
           (pc))) -1 (nil)
   (nil))

(jump_insn 39 38 40 (set (pc)
       (label_ref 22)) -1 (nil)
   (nil))

(barrier 40 39 9)

	.
	.
	.
	.

skinfaxe% 

As seen in insns 31 and 35, a sign-extend is generated for the switch
value, even though it is unsigned. This only happens when
-traditional is used.

The problem seems to be in stmt.c, function emit_case_nodes(). For a
single-valued case the parameter unsignedp is transmitted to
emit_cmp_insn() through the call of do_jump_if_equal(). For case
ranges emit_cmp_insn() is called directly with an argument of 0.
I don't understand the type system well enough to be sure that
`fixing' this is safe, but it sure looks like it needs fixing.

--
Lars Mathiesen, DIKU, U of Copenhagen, Denmark      [uunet!]mcvax!diku!thorinn
Institute of Datalogy -- we're scientists, not engineers.      thorinn@diku.dk