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