SourceForge.net Logo

[Release b]
<t4m_bug_dtor_const>
Wed Jun 23 15:42:59 WEST 2004

In the current release of tendra4minix (a), after fixing
<t4m_bug_applyfunctempl>, the program dtor_const.C produces this error,

"dtor_const.C", line 6: Error:
  [ISO 14.7.1]: In instantiation of template 'Hola < int >::~Hola' (at line 6).
  [ISO 12.6.2]: In special member function 'Hola < int >::~Hola ()'.
  [ISO 8.5]: In initialization of 'Hola < int >::i'.
  [ISO 8.5]: 'const' objects should be initialized.

This is the error ERR_dcl_init_const generated in init_default [construct.c]
and reported in constr_error [construct.c]. It is reported only for polymorphic
(= having virtual functions) template classes.

Function make_destr_prelude [construct.c], called from ctor_none [construct.c]
(which is always called from the parser) at hashid_destr_tag, creates a dummy
initializer for destructors of polymorphic classes; this initializer is used
for resetting virtual tables just before destruction takes place.

The error happens when copy_exp [copy.c] is instantiating this initializer,
which has kind DEFAULT_PRELUDE; copy_exp calls copy_ctor [construct.c], as it
should do for any initializer, and then copy_ctor immediately calls make_constr
[construct.c], since there are no arguments for this initializer. make_constr
calls init_empty_mem [construct.c] for each data member of the class, and
finally init_empty_mem calls init_default [construct.c] to create the default
initializer. It is in init_default when the error is generated.

The error does not happen during class template analysis because the
initializer expression built by make_destr_prelude is added to the destructor
body after make_constr has been called (see ctor_none [construct.c]). And it
does not happen with non-template classes because they are not copied
(= instantiated), and make_constr is never called again for them.

Assuming that DEFAULT_PRELUDE is only used to reset virtual tables, as the
comment at make_destr_prelude says, we can fix this problem just adding
the condition 'n == DEFAULT_PRELUDE' to the conditional

    /* Everything else is alright in these cases */
    if ( n == DEFAULT_COPY || n == DEFAULT_DESTR || n == DEFAULT_DELETE ) {
	return ( NULL_exp ) ;
    }

in function init_default [construct.c], obtaining

    /* Everything else is alright in these cases */
    if ( n == DEFAULT_COPY || n == DEFAULT_DESTR || n == DEFAULT_DELETE
	|| n == DEFAULT_PRELUDE ) {
	return ( NULL_exp ) ;
    }

Note: the resetting of virtual tables for data members is supposed to be done
inside their own destructors, thus in theory we could even avoid calling
init_default when n == DEFAULT_PRELUDE, but in this way the change is
minimal.

Question: How come members of template classes don't get reinitialized at the
beginning of destructors due to the instantiation of the DEFAULT_PRELUDE
initializer? Members of built-in types and enumerations should be initialized
explicitly inside special functions. For members of class types, init_default
calls find_constr [construct.c] to find the appropriate constructor, but
find_constr returns NULL_id when the kind of the special function requested is
DEFAULT_PRELUDE (see dtor_const_c.C for an example).