SourceForge.net Logo

[Release b]
<t4m_bug_nonexpctor>
Mon Jul 12 18:03:18 WEST 2004

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

"nonexpctor.C", line 14: Error:
  [ISO 14]: The non-exported template 'Alloc < Thread >::Alloc ()' has not been defined.

It is ERR_temp_decl_undef, and it's being reported in function copy_template
[instance.c]. The error disappears when we put a definition (inline or not) for
this constructor before the declaration of class Process. For example, changing
'Alloc();' for 'Alloc() {}'. The error also dissapears when there is no
declaration for the default constructor.

The problem is in function export_template [template.c], it cannot deal with
overloaded functions. In the program nonexpctor.C, it is exporting the copy
constructor 'Alloc::Alloc(const Alloc<T> &)', but not the rest of the list of
overloaded constructors; the default constructor happens to be second in that
list, since it was declared first.

To fix this bug, we can write a new static function named export_templ_over in
file template.c for recursing into the list of overloaded functions of a member
of an exported template class,

/*
    EXPORT AN OVERLOADED FUNCTION TEMPLATE IDENTIFIER

    This routine marks the overloaded function template identifier id as
    having been exported. def is 2 for the first explicit declaration of a
    template, 1 for a redeclaration and 0 otherwise. This function is used
    only by export_template, for recursing into lists of overloaded member
    function identifiers.
*/

static void export_template_over
    PROTO_N ( ( id, def ) )
    PROTO_T ( IDENTIFIER id X int def )
{
    if ( IS_id_function_etc ( id ) ) {
	IDENTIFIER oid = DEREF_id ( id_function_etc_over ( id ) ) ;
	if ( !IS_NULL_id ( oid ) ) export_template_over ( oid, def ) ;
    }
    export_template ( id, def ) ;
}

Then, in function export_template [template.c], in cases id_class_name_tag,
id_class_alias_tag, we change the calls to export_template for calls to
export_template_over, that is, we change

			/* Scan through class members */
			IDENTIFIER pid = DEREF_id ( member_id ( mem ) ) ;
			IDENTIFIER qid = DEREF_id ( member_alt ( mem ) ) ;
			if ( !IS_NULL_id ( pid ) ) {
			    export_template ( pid, def ) ;
			}
			if ( !IS_NULL_id ( qid ) && !EQ_id ( qid, pid ) ) {
			    export_template ( qid, def ) ;
			}

for

			/* Scan through class members */
			IDENTIFIER pid = DEREF_id ( member_id ( mem ) ) ;
			IDENTIFIER qid = DEREF_id ( member_alt ( mem ) ) ;
			if ( !IS_NULL_id ( pid ) ) {
			    export_template_over ( pid, def ) ;
			}
			if ( !IS_NULL_id ( qid ) && !EQ_id ( qid, pid ) ) {
			    export_template_over ( qid, def ) ;
			}

Observe that overloading is not dealt with in the case of non-member
template functions, since they are unrelated to each other and are exported
separately.