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