The problem can be demonstrated with a very simple program (attached), and
it looks to me like a bug in gcc - surely it should overlap stack
assignments for automatic variables which aren't in scope simultaneously?

One solution to rb_eval() might be an ugly union at the top of the function
(second attachment). But it seems wrong to have to do this just to code
around an implementation problem with one particular compiler, albeit a
ubiquitous one.

Regards,

Brian.
/* gcc -Wall -S -o sf.s sf.c */
extern char *src(int);
extern void spill(void);
extern void foo(char*,char*,char*,char*,char*,char*,char*,char*);

int main(void)
{
  switch (src(-1)[0]) {
  case 'a':
    {
      char *a = src(0);
      char *b = src(1);
      char *c = src(2);
      char *d = src(3);
      char *e = src(4);
      char *f = src(5);
      char *g = src(6);
      char *h = src(7);
      spill();
      foo(a,b,c,d,e,f,g,h);
      break;
    }
  case 'b':
    {
      char *a = src(8);
      char *b = src(9);
      char *c = src(10);
      char *d = src(11);
      char *e = src(12);
      char *f = src(13);
      char *g = src(14);
      char *h = src(15);
      spill();
      foo(a,b,c,d,e,f,g,h);
      break;
    }
  }
  return 0;
}
/* gcc -Wall -S -o sf2.s sf2.c */
extern char *src(int);
extern void spill(void);
extern void foo(char*,char*,char*,char*,char*,char*,char*,char*);

int main(void)
{
  union {
    struct {
      char *a, *b, *c, *d, *e, *f, *g, *h;
    } b1;
    struct {
      char *a, *b, *c, *d, *e, *f, *g, *h;
    } b2;
  } u;
  switch (src(-1)[0]) {
  case 'a':
    {
      u.b1.a = src(0);
      u.b1.b = src(1);
      u.b1.c = src(2);
      u.b1.d = src(3);
      u.b1.e = src(4);
      u.b1.f = src(5);
      u.b1.g = src(6);
      u.b1.h = src(7);
      spill();
      foo(u.b1.a,u.b1.b,u.b1.c,u.b1.d,u.b1.e,u.b1.f,u.b1.g,u.b1.h);
      break;
    }
  case 'b':
    {
      u.b2.a = src(8);
      u.b2.b = src(9);
      u.b2.c = src(10);
      u.b2.d = src(11);
      u.b2.e = src(12);
      u.b2.f = src(13);
      u.b2.g = src(14);
      u.b2.h = src(15);
      spill();
      foo(u.b2.a,u.b2.b,u.b2.c,u.b2.d,u.b2.e,u.b2.f,u.b2.g,u.b2.h);
      break;
    }
  }
  return 0;
}