egcs-1.0.3a: Bug with local classes in function templates

Florian Weimer fw@cygnus.stuttgart.netsurf.de
Thu Jun 11 01:46:00 GMT 1998


Hi!

Alexandre Oliva <oliva@dcc.unicamp.br> writes:

> Florian Weimer <fw@cygnus.stuttgart.netsurf.de> writes:
> 
> > #include <vector>
> > main () { vector<int&> vec; int i = 1; vec.push_back(i); }
> 
> The May 30 snapshot prints lots of error messages, as expected.  You
> can't create containers of reference types.

I knew that, the code was intended for educational purposes only. ;)

I've finally taken the hint and downloaded and built egcs-19980608,
but alas, it's got the same old bug I spotted in almost every
gcc-based C compiler (but failed to report until now).

Here's the code that triggers the bug:

----------------------------------------------------------------------
/* From glibc-2.05c, /usr/include/__math.h */

#include <stdio.h>

extern __inline double
sin (double __x)
{
  register double __value;
  __asm __volatile__
    ("fsin"
     : "=t" (__value) : "0" (__x));

  return __value;
}

extern __inline double
cos (double __x)
{
  register double __value;
  __asm __volatile__
    ("fcos"
     : "=t" (__value): "0" (__x));

  return __value;
}

extern __inline double
exp (double __x)
{
  register double __value, __exponent;
  __asm __volatile__
    ("fldl2e			# e^x = 2^(x * log2(e))\n\t"
     "fmul	%%st(1)		# x * log2(e)\n\t"
     "fstl	%%st(1)\n\t"
     "frndint			# int(x * log2(e))\n\t"
     "fxch\n\t"
     "fsub	%%st(1)		# fract(x * log2(e))\n\t"
     "f2xm1			# 2^(fract(x * log2(e))) - 1\n\t"
     : "=t" (__value), "=u" (__exponent) : "0" (__x));
  __value += 1.0;
  __asm __volatile__
    ("fscale"
     : "=t" (__value) : "0" (__value), "u" (__exponent));

  return __value;
}

/* From Python 1.5b2 */

typedef struct {
  double real;
  double imag;
} Py_complex;

/* compiled incorrectly */

Py_complex 
c_exp(x)
     Py_complex x;
{
  Py_complex r;
  double l = exp(x.real);
  r.real = l*cos(x.imag);
  r.imag = l*sin(x.imag);
  return r;
}

int main(void)
{
  Py_complex x, y;
  x.real = 1.0;
  x.imag = 1.0;
  
  y = c_exp(x);
  printf("(%f, %f)\n", y.real, y.imag);
  
  return 0;
}
----------------------------------------------------------------------

Here's the command line I used 

[fw@deneb /tmp]$ /opt/egcs-ss/bin/gcc --version
egcs-2.91.40
[fw@deneb /tmp]$ /opt/egcs-ss/bin/gcc -Wall -O2 -fomit-frame-pointer -fpic bug.c
[fw@deneb /tmp]$ ./a.out 
Segmentation fault (core dumped)
[fw@deneb /tmp]$ 

Looking at the machine code generated for c_exp(), I can image why the
program crashes:

----------------------------------------------------------------------
c_exp:
	subl $32,%esp
	pushl %ebx
	call .LPR0
	addl $_GLOBAL_OFFSET_TABLE_,%ebx
	movl 40(%esp),%edx
	fldl 44(%esp)
#APP
	fldl2e			# e^x = 2^(x * log2(e))
	fmul	%st(1)		# x * log2(e)
	fstl	%st(1)
	frndint			# int(x * log2(e))
	fxch
	fsub	%st(1)		# fract(x * log2(e))
	f2xm1			# 2^(fract(x * log2(e))) - 1
	
#NO_APP
	faddl .LC0@GOTOFF(%ebx)
#APP
	fscale
#NO_APP
	fstp %st(1)
	fstpl (%esp)
----------------------------------------------------------------------

The last instruction above destroys the saved value of the caller's
%ebx register. :( (I was a bit surprised when I discovered this. gcc
2.7.2.x miscompiles the code as well, but uses the return address as
if it was the pointer for the struct return.)

Florian



More information about the Gcc-bugs mailing list