[net.lang.c++] 1.1 bugs & fixes

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

********************************************************************