[gnu.gcc.bug] unsigned longs in gcc 1.37 on decstation

bstocker@DIANA.CAIR.DU.EDU (Bob Stocker) (02/23/90)

I ran across the following bug in gcc Version 1.37 running on a
DECsystem 5400 under RISC Ultrix Version 3.1C (Revision 41).

Gcc was configured for a decstation and, with two exceptions, was
compiled according to the instructions in gcc-1.37/INSTALL.  First, I
changed the declaration of tree_code_name in config/out-mips.c from

	extern char *tree_code_name[];
to

	extern char **tree_code_name;

so that it would be compatible with the declarations of tree_code_name
in g++-1.36.4/tree.h.  Second, since gcc on a decstation does not
support the -g flag, I used the command

          make CC=stage1/gcc CFLAGS="-O -Bstage1/"

to recompile gcc with itself.

The following shell script displays the bug:

csh> strings /vmunix | grep Ultrix
strings /vmunix | grep Ultrix
Ultrix V3.1C (Rev. 41) System #1: Fri Jan  5 11:48:15 MST 1990

csh> gcc -v
gcc -v
gcc version 1.37

csh> cd ~/test
cd ~/test

csh> cat gccbug.c
cat gccbug.c
#define SHORTBITS	16
#define I_SHIFT         SHORTBITS
#define I_MAXNUM	((unsigned long)65535L)

unsigned long down(unsigned long x)
{
  return (x >> I_SHIFT) & I_MAXNUM;
}

main() {
  unsigned short a[2];
  unsigned short b[2];
  unsigned long hi = 1;
  unsigned short* ap = &a[0];
  unsigned short* bp = &b[0];
  unsigned short* topb = &b[2];
  a[0] = 1; a[1] = 0;
  b[0] = 0; b[1] = 1;
  while (bp < topb) {
    printf("%lu + %u + %lu - %u = ", hi, *ap, I_MAXNUM, *bp);
    hi += (unsigned long)(*ap++) + I_MAXNUM - (unsigned long)(*bp++);
    printf("%lu\n", hi);
    hi = down(hi);
  }
}

csh> gcc gccbug.c
gcc gccbug.c

csh> a.out
a.out
1 + 1 + 65535 - 0 = 1
0 + 0 + 65535 - 1 = 4294967294

The native C compiler produces code that runs correctly.

I first ran into this bug when I compiled libg++-1.36.3/src/Integer.cc
with g++ version 1.36.4 (based on GCC 1.36.93).  Lines similar to the
one that produces the bug appear several places in Integer.cc.  I
found that splitting those lines into lines like

    hi += (unsigned long)(*ap++) + I_MAXNUM;
    hi -= (unsigned long)(*bp++);

got around the problem.

Please let me know if I can provide you with any further information
or can help you in any other way.

Bob Stocker
Director of Academic Computing
University of Denver
bstocker@du.edu