bs@alice.UucP (Bjarne Stroustrup) (08/09/86)
Here are two nasty bugs we have found in Release 1.1 - and their fixes. Please note that this relates to release 1.1 only. ********************************************************************* ``destroy before return'' bug: class foo { public: foo(); ~foo(); }; foo func(int i) { foo my_foo; return my_foo; } This causes cfront to generate bad code. A bug causes my_foo to be destroyed and THEN returned. There is no compile time warning. This is fixed by adding the code in case NAME: of not_safe() in simpl.c: bit not_safe(Pexpr e) { switch (e->base) { default: return 1; /* case CALL: case G_CALL: case DOT: case REF: case ANAME: return 1; */ case NAME: // if the name is automatic and has a destructor it is not safe // to destroy it before returning an expression depending on it { Pname n = Pname(e); if (n->n_table!=gtbl && n->n_table->t_name==0) { Pname cn = n->tp->is_cl_obj(); if (cn && Pclass(cn->tp)->has_dtor()) return 1; } } case IVAL: case ICON: ******************************************************************* bad code for pointer to function bug: struct X { X(X&); }; void f(register X (*fp)(char*, double)) { (*pf)("arg",1.0)); // produces bad code pf("arg",1.0); // produces good code } The problem shows up as a cc complaint about casts. The problem only occurs when with a pointer to function returning an X for which X(X&) is declared. The fix is in case CALL of expr::print() in print.c: case G_CALL: case CALL: { Pname fn = fct_name; Pname at; if (fn && print_mode==SIMPL) { Pfct f = (Pfct)fn->tp; //error('d',"call%n: %t",fn,f); if (f->base==OVERLOAD) { /* overloaded after call */ Pgen g = (Pgen)f; fct_name = fn = g->fct_list->f; f = (Pfct)fn->tp; } fn->print(); at = (f->f_this) ? f->f_this : (f->f_result) ? f->f_result : f->argtype; } else { //error('d',"e1%k e1->tp %d %d%t",e1->base,e1->tp,e1->tp->base,e1->tp); Pfct f = Pfct(e1->tp); eprint(e1); if (f) { // pointer to fct while (f->base == TYPE) f = Pfct(Pbase(f)->b_name->tp); at = (f->f_result) ? f->f_result : f->argtype; } else // virtual: argtype encoded at = (Pname)e1->e1->tp; } ********************************************************************