[gnu.g++.bug] g++ bug on Sun3 version?

cchris@BBN.COM (Carl Christofferson) (09/13/89)

  We recently installed g++ on a Sun3, and I proceeded to try out a very
simple minded program of the hello.c variety.  To my surprise, I got
a segmentation violation.  After much wrangling I decided that it was in
fact a compiler bug, although I am not at all certain it isn't just an
installation problem.  I need help in either case.
  The program bug.cc can be compiled with BUG=0 (bug is off) or BUG=1 (bug
is on) and if this re-produces the problem on someone else's Sun3
installation then we have verification.
	It seems that under certain conditions the compiler messes up parameter
passing.  The specifics are illustrated in the enclosed file, bugon.out.
When evaluating an expression the compiler loads the stack with all the
parameters, then calls the functions that act on the parameters in order.
Kind of like:
			 return (foo(a,b), bar(d))
evaluating like:
			push d
			push a
			push b
			call foo
			popd 1
			call bar
			popd 2
Actually, the real example is somewhat more complex.  In anycase, the
bug appears because of context:
			blat(e,f);
			return (foo(a,b), bar(d))
Which might reasonably look like this:
			push e
			push f
			call blat
			pop 2
			push d
			push a
			push b
			call foo
			popd 1
			call bar
			popd 2
The compiler seems to want to produce this:
			push e
			push f
			call blat
			pop 2
			replace e with d
			replace f with a
			push b
			call foo
			popd 1
			call bar
			popd 2
And instead does something like this:
			push e
			push f
			call blat
			pop 2
			push d
			replace f with a
			replace d with b
			call foo
			popd 1
			call bar
			popd 2
And so by the time bar is called the stack doesn't have the correct
parameter on it.

Well, that is the best I can do by way of explanation at the moment
If it isn't enough, write or call.  Thanks, I eagerly await reply.

Carl Christofferson
cchris@bbn.com
(206) 746-6800
14100 SE 36th St.
Bellevue, WA 98006


######################## Enclosure #1
_main:
_main:			linkw	a6,#-0x10
_main+4:		moveml	a2/a3,sp@-
_main+8:		clrl	sp@-
_main+0xa:		movl	#0x40000000,sp@-
_main+0x10:		clrl	sp@-
_main+0x12:		movl	#0x3ff00000,sp@-
_main+0x18:		lea	a6@(-0x10),a2
_main+0x1c:		movl	a2,sp@-
_main+0x1e:		jsr	_complex_PScomplex_DF_DF:l
// Here is where the stack gets messed up:
_main+0x24:		pea	_op$alshift_expr_Sostream_Scomplex+0x5c
_main+0x28:		lea	sp@(4),a3
_main+0x2c:		movl	a2,a0
_main+0x2e:		movl	a3,a1
_main+0x30:		movl	a2@,a3@
_main+0x32:		addqw	#4,a1
_main+0x34:		addqw	#4,a0
_main+0x36:		movl	a0@+,a1@+
_main+0x38:		movl	a0@+,a1@+
_main+0x3a:		movl	a0@,a1@
// The stack is messed up by here.
_main+0x3c:		movl	#0x20046,sp@
_main+0x42:		bsr	_op$alshift_expr_Sostream_Scomplex
_main+0x46:		addw	#0x14,a7
_main+0x4a:		movl	d0,sp@-
_main+0x4c:		bsrl	_op$alshift_expr_PSostream_PQI
_main+0x52:		clrl	d0
_main+0x54:		moveml	a6@(-0x18),a2/a3
_main+0x5a:		unlk	a6
_main+0x5c:		rts

######################## Enclosure #2
#include <stream.h>
#include <math.h>

#define bugon 1
#define bugoff 0

//
// Here is the parameter problem inducing code.
// It appears that ALL three of the conditions must be
// true before this particular problem arises.  That is,
// the overload function for '<<' must pass 'complex' by value,
// the complex class must not have a constructor with a complex argument
// (curiously this isn't used even if it is declared)
// and the constructor from two real values must not be inline.
//
#if BUG==bugon
#define CONDITION1 complex
#define CONDITION2
#define CONDITION3
#else if BUG==bugon
#define CONDITION1 complex&
#define CONDITION2 complex(complex& c);
#define CONDITION3 inline
#endif else if BUG==bugon

class complex
{
protected:
  double           re;
  double           im;

public:
                   complex();
									 CONDITION2
                   complex(double r, double i = 0.0);
                   ~complex();
  friend ostream&  operator << (ostream& s, CONDITION1 x);

};


inline complex:: complex() {}
inline complex::~complex() {}

CONDITION3 complex::complex(double r, double i = 0.0)
{
  re = r; im = i;
}

ostream& operator << (ostream& s, CONDITION1 x)
{
  return s << "(" << x.re << ", " << x.im << ")" ;
}

int
main()
{
	complex x(1,2);
	cout << x << "\n";
	return 0;
}

######################## Enclosure #3
## The Makefile
GXX = g++
LIBDIR = /usr/local/lib
TFLAGS = -DLDXX=\"$(LIBDIR)/gcc-ld++\" -DCRT1X=\"$(LIBDIR)/crt1+.o\"

GFLAGS = -g -O -fchar-charconst -I/usr/local/lib/g++-include -I. -fstrength-reduce
#GFLAGS = -g -O -fchar-charconst -I../g++-include -I. -fstrength-reduce -mgnu

# all g++ files should have extension .cc
.SUFFIXES: .cc .o
.cc.o:
	$(GXX) $(GFLAGS) -c  $<

.o:
	$(GXX) $< -o $*

bugon.o: bug.cc
	$(GXX) $(GFLAGS) -DBUG=1 -c bug.cc
	mv bug.o bugon.o

bugoff.o: bug.cc
	$(GXX) $(GFLAGS) -DBUG=0 -c bug.cc
	mv bug.o bugoff.o

bugon: bugon.o
	$(GXX) bugon.o -o bugon
	adb bugon <adb.in2 >bugon.out

bugoff: bugoff.o
	$(GXX) bugoff.o -o bugoff
	adb bugoff <adb.in2 >bugoff.out

bug: bug.o
	$(GXX) bug.o -o bug
	adb bug <adb.in2 >bug.out

tom@tnosoes.UUCP (Tom Vijlbrief) (09/14/89)

There is a problem with parameter passing with call by value.
Use -fno-defer-pop to fix this.

I assume Michael fixed this bug in g++1.36 but I have no access to his
latest compiler.

Tom
===============================================================================
Tom Vijlbrief
TNO Institute for Perception
P.O. Box 23				Phone: +31 34 63 562 11
3769 ZG  Soesterberg			E-mail: tnosoes!tom@mcvax.cwi.nl
The Netherlands				    or:	uunet!mcvax!tnosoes!tom
===============================================================================