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;
}
********************************************************************