From: pasieka%sureal@cs.umass.edu
Subject: GCC 2.2.2 bug
Organization: GNUs Not Usenet
Distribution: gnu
Date: Fri, 11 Dec 1992 16:54:13 GMT

Version of GCC: 2.2.2
Machine Type: Vax (Sun3 equivalent)

Compiling the enclosed output of cpp and executing the program results
in output which I believe illustrates a bug.

The problem occurs when I am setting up a single linked list's next
pointers. The line:

	test_a->next = ++test_a;

results in an error when the location of the 'next' element of the
structure is first. My guess is that the register allocation processing
does not recognize that the register will be modified before it can be
used to store the resulting value. In the case where the location of
the 'next' element of the structure is not first, there is no problem.

I will be testing this with GCC 2.3.1 after I get the compiler
compiled. This is not likely in the *immediate* future but likely
within the next month.

The original C program is as follows:

/* Start ------------------------------------------------------------------- */
struct a {
  struct a *next;
  int index;
};

struct b {
  int index;
  struct b *next;
};

main ()
{
  int i;
  struct a *anchor_a, *test_a;
  struct b *anchor_b, *test_b;

  /* malloc an array of 11 structs each */
  anchor_a = test_a = (struct a *)malloc (11*sizeof (struct a));
  anchor_b = test_b = (struct b *)malloc (11*sizeof (struct b));

  /* Initialize the nnext and index values */
  for (i=0 ; i<11; i++) {
    anchor_a[i].next = (struct a *)0;
    anchor_a[i].index = -1;
    anchor_b[i].index = -1;
    anchor_b[i].next = (struct b *)0;
  }

  /* Link the first 10 of struct a's together in a single linked list */
  for (i=0 ; i<10; i++) {
    test_a->index = i;
    test_a->next = ++test_a;
  }

  /* Link the first 10 of struct b's together in a single linked list */
  for (i=0 ; i<10; i++) {
    test_b->index = i;
    test_b->next = ++test_b;
  }

  /* Print out the structs index and the index of the next */

  printf ("For structs where the first element is the next pointer:\n");
  for (i=0, test_a=anchor_a ; i<10; i++, test_a++) {
    printf ("\t0x%x (%d) -> 0x%x (%d)\n",
	    (int)test_a, i,
	    (int)test_a->next, test_a->next->index);
  }
  printf("\n");
  printf ("For structs where the next pointer is not the first element:\n");
  for (i=0, test_b=anchor_b ; i<10; i++, test_b++) {
    printf ("\t0x%x (%d) -> 0x%x (%d)\n",
	    (int)test_b, i,
	    (int)test_b->next, test_b->next->index);
  }

  return 0;
}
/* End --------------------------------------------------------------------- */

The program after cpp (not much different):

/* Start ------------------------------------------------------------------- */
# 1 "../../../test/bugs/preincrement.c"

struct a {
  struct a *next;
  int index;
};

struct b {
  int index;
  struct b *next;
};

main ()
{
  int i;
  struct a *anchor_a, *test_a;
  struct b *anchor_b, *test_b;

   
  anchor_a = test_a = (struct a *)malloc (11*sizeof (struct a));
  anchor_b = test_b = (struct b *)malloc (11*sizeof (struct b));

   
  for (i=0 ; i<11; i++) {
    anchor_a[i].next = (struct a *)0;
    anchor_a[i].index = -1;
    anchor_b[i].index = -1;
    anchor_b[i].next = (struct b *)0;
  }

   
  for (i=0 ; i<10; i++) {
    test_a->index = i;
    test_a->next = ++test_a;
  }

   
  for (i=0 ; i<10; i++) {
    test_b->index = i;
    test_b->next = ++test_b;
  }

   

  printf ("For structs where the first element is the next pointer:\n");
  for (i=0, test_a=anchor_a ; i<10; i++, test_a++) {
    printf ("\t0x%x (%d) -> 0x%x (%d)\n",
	    (int)test_a, i,
	    (int)test_a->next, test_a->next->index);
  }
  printf("\n");
  printf ("For structs where the next pointer is not the first element:\n");
  for (i=0, test_b=anchor_b ; i<10; i++, test_b++) {
    printf ("\t0x%x (%d) -> 0x%x (%d)\n",
	    (int)test_b, i,
	    (int)test_b->next, test_b->next->index);
  }

  return 0;
}
/* End --------------------------------------------------------------------- */

The output I get is:

For structs where the first element is the next pointer:
	0x1c04 (0) -> 0x0 (-1051042096)
	0x1c0c (1) -> 0x1c0c (1)
	0x1c14 (2) -> 0x1c14 (2)
	0x1c1c (3) -> 0x1c1c (3)
	0x1c24 (4) -> 0x1c24 (4)
	0x1c2c (5) -> 0x1c2c (5)
	0x1c34 (6) -> 0x1c34 (6)
	0x1c3c (7) -> 0x1c3c (7)
	0x1c44 (8) -> 0x1c44 (8)
	0x1c4c (9) -> 0x1c4c (9)

For structs where the next pointer is not the first element:
	0x1c84 (0) -> 0x1c8c (1)
	0x1c8c (1) -> 0x1c94 (2)
	0x1c94 (2) -> 0x1c9c (3)
	0x1c9c (3) -> 0x1ca4 (4)
	0x1ca4 (4) -> 0x1cac (5)
	0x1cac (5) -> 0x1cb4 (6)
	0x1cb4 (6) -> 0x1cbc (7)
	0x1cbc (7) -> 0x1cc4 (8)
	0x1cc4 (8) -> 0x1ccc (9)
	0x1ccc (9) -> 0x1cd4 (-1)

Notice that in the first set of output, the next pointers are incorrectly set.

Please feel free to contact me about this if I can provide more
information. I can be reached via email at pasieka@cs.umass.edu or by
phone at 413/545-2447.

-- Michael

Newsgroups: gnu.gcc.bug