[gnu.g++.bug] three bugs in g++-1.31

russo@M.CS.UIUC.EDU (Vince Russo) (12/19/88)

I have included below examples of three bugs I have found in g++-1.31.
The third one is quite nasty.

Sorry if you have seen these before. I not sure postings to the gnu news groups
are getting mailed from our site so I decided to mail these myself directly.

		--Vince Russo
		russo@cs.uiuc.edu

----------------------------------------------------------------

			--ONE--


The following rather contrived C++ program causes g++-1.31 to abort.
The failure occurs in the switch statement in simpl_cst_equal() in tree.c.
The default: case was being reached. The value of code1 is INDIRECT_REF.
A bug fix I tried that worked was to add a case INDIRECT_REF:
that just returned 0 to the switch statement. It was just a shot in the
dark, is it correct?

The example is a small sample of how to create a printf without varargs.
Admittedly, the "*(printArgs *)0" is ugly, but (I think) nonetheless valid.
Creating a static instance of printArgs and replacing the "*(printArgs *) 0"
with that instance as the default argument causes the bug to go away.
I'd rather like to avoid this since pushing a constant "0" as the default
argument is cheaper on most architectures than pushing the address of
this default instance.

-----------------------------------------------
class printArgs {
public:
	union {
		void * p;
		long l;
	};
	printArgs( void * pp );
	printArgs( long ll );
	printArgs();
};

inline printArgs::printArgs( void * pp ) { p = pp; }
inline printArgs::printArgs( long ll ) { l = ll; }
inline printArgs::printArgs() {}

class Console {
protected:
public:
	void printf( const char * f, printArgs& a1 = *(printArgs *) 0,
		printArgs& a2 = *(printArgs *) 0 );
} theConsole;

inline void
Printf( const char * f, printArgs& a1 = *(printArgs *) 0,
	printArgs& a2 = *(printArgs *) 0)
{
	theConsole.printf( f, a1, a2 );
}

x()
{
	Printf( "Hello %s", "world" );
}


----------------------------------------------------------------------

			--TWO--


The following simple program causes:

Failed assertion at  __LINE__ 4236 of `cplus-typeck.c'.
/home/srg/russo/bin/g++: Program c++ got fatal signal 6.

in g++-1.31.0.

I'm not sure what the proper behaviour should be (cfront allows the implicit
cast of  "Module * const" to "void *"), but crashing is probably not it :-)
----------------------------------------------------------------------------
struct Module {
	int stuff;
};

static Module * const ModuleTable = 0;

void
pp( const char *, void * )
{
}

static void
InitModuleTable()
{
	pp( "Filling in entries of module table at %x\n", ModuleTable );
}
/* End of text from m.cs.uiuc.edu:gnu.g++.bug */

----------------------------------------------------------

			--THREE--


Virtual destructors in g++-1.31 compile to infinite loops.
----------------------------------------------------------
For example:

class Object {
public:
	Object()		{ printf( "Object::Object()\n" ); }
	virtual ~Object()	{ printf( "Object::~Object()\n" ); }
};

class SubObject : public Object {
public:
	SubObject()		{ printf( "SubObject::SubObject()\n" ); }
	~SubObject()		{ printf( "SubObject::~SubObject()\n" ); }
};

main()
{
	Object * a = new SubObject();
	delete a;
}

----------------------------
Generates the following machine code for SubObject::SubObject.
----------------------------

	.align 16
__$_SubObject:
	enter [r3],0
	movd 8(fp),r3
	adjspb $-8
	cmpqd $0,r3
	beq .L10
	addr @.LC3,tos
	bsr ?_printf
	cmpqd $0,tos # adjsp -4
	movd 0(r3),r0			<<- this will fetch the v-table addr.
	movd 12(fp),tos
	movd r3,tos
	movd 4(r0),r0			<<- this will fetch the address of
					    __$_SubObject NOT __$_Object
	jsr r0
	addr @__vt$Object,0(r3)		<<- This seems to be the bug.
					    The assignment should have been
					    before the destructor function						    lookup fetched the vtable addr.
.L10:
	exit [r3]
	ret 0

	.align 2
__vt$SubObject:
	.word 0
	.word 0
	.double __$_SubObject
	.align 2
__vt$Object:
	.word 0
	.word 0
	.double __$_Object