
[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.