templated function overloading support

git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/trunk@6394 626c5289-ae23-0410-ae9c-e8d60b6d4f22
This commit is contained in:
William S Fulton 2004-10-16 20:41:17 +00:00
commit 77eef87058
4 changed files with 253 additions and 162 deletions

View file

@ -382,11 +382,11 @@ static void add_symbols(Node *n) {
Swig_warning(0,Getfile(n),Getline(n), "%s\n", wrn); Swig_warning(0,Getfile(n),Getline(n), "%s\n", wrn);
} }
c = Swig_symbol_add(symname,n); c = Swig_symbol_add(symname,n);
if (c != n) { if (c != n) {
/* symbol conflict attempting to add in the new symbol */
if (Getattr(n,"sym:weak")) { if (Getattr(n,"sym:weak")) {
Setattr(n,"sym:name",symname); Setattr(n,"sym:name",symname);
} else if ((Strcmp(nodeType(n),"template") == 0) && (Strcmp(Getattr(n,"templatetype"),"cdecl") == 0)) {
Setattr(n,"sym:name",symname);
} else { } else {
String *e = NewString(""); String *e = NewString("");
String *en = NewString(""); String *en = NewString("");
@ -892,7 +892,6 @@ static void default_arguments(Node *n) {
} }
if (default_args) { if (default_args) {
ParmList* newparms = 0; ParmList* newparms = 0;
/* Create a parameter list for the new function by copying all /* Create a parameter list for the new function by copying all
but the last (defaulted) parameter */ but the last (defaulted) parameter */
{ {
@ -933,14 +932,12 @@ static void default_arguments(Node *n) {
if (throws) Setattr(new_function,"throws",CopyParmList(throws)); if (throws) Setattr(new_function,"throws",CopyParmList(throws));
} }
/* copy template specific attributes */ /* copy specific attributes for global (or in a namespace) template functions - these are not templated class methods */
if (Strcmp(nodeType(function),"template") == 0) { if (Strcmp(nodeType(function),"template") == 0) {
Node *templatetype = Getattr(function,"templatetype"); Node *templatetype = Getattr(function,"templatetype");
Node *symname = Getattr(function,"sym:name");
Node *symtypename = Getattr(function,"sym:typename"); Node *symtypename = Getattr(function,"sym:typename");
Parm *templateparms = Getattr(function,"templateparms"); Parm *templateparms = Getattr(function,"templateparms");
if (templatetype) Setattr(new_function,"templatetype",Copy(templatetype)); if (templatetype) Setattr(new_function,"templatetype",Copy(templatetype));
if (symname) Setattr(new_function,"sym:name",Copy(symname));
if (symtypename) Setattr(new_function,"sym:typename",Copy(symtypename)); if (symtypename) Setattr(new_function,"sym:typename",Copy(symtypename));
if (templateparms) Setattr(new_function,"templateparms",CopyParmList(templateparms)); if (templateparms) Setattr(new_function,"templateparms",CopyParmList(templateparms));
} }
@ -2097,17 +2094,27 @@ template_directive: SWIGTEMPLATE LPAREN idstringopt RPAREN idcolonnt LESSTHAN va
} }
p = nextSibling(p); p = nextSibling(p);
} }
/* Look for the template */
if (n && (Strcmp(nodeType(n),"template") == 0)) { /* Look for the template */
Parm *tparms = Getattr(n,"templateparms"); {
Node *nn = n;
Node *linklistend = 0;
while (nn) {
Node *templnode = 0;
if (Strcmp(nodeType(nn),"template") == 0) {
int nnisclass = (Strcmp(Getattr(nn,"templatetype"),"class") == 0); /* if not a templated class it is a templated function */
Parm *tparms = Getattr(nn,"templateparms");
if (!tparms) { if (!tparms) {
specialized = 1; specialized = 1;
} }
if (!specialized && ((ParmList_len($7) > ParmList_len(tparms)))) { if (nnisclass && !specialized && ((ParmList_len($7) > ParmList_len(tparms)))) {
Swig_error(cparse_file, cparse_line, "Too many template parameters. Maximum of %d.\n", ParmList_len(tparms)); Swig_error(cparse_file, cparse_line, "Too many template parameters. Maximum of %d.\n", ParmList_len(tparms));
} else if (!specialized && ((ParmList_len($7) < ParmList_numrequired(tparms)))) { } else if (nnisclass && !specialized && ((ParmList_len($7) < ParmList_numrequired(tparms)))) {
Swig_error(cparse_file, cparse_line, "Not enough template parameters specified. %d required.\n", ParmList_numrequired(tparms)); Swig_error(cparse_file, cparse_line, "Not enough template parameters specified. %d required.\n", ParmList_numrequired(tparms));
} else if (!nnisclass && ((ParmList_len($7) != ParmList_len(tparms)))) {
/* must be an overloaded templated method - ignore it as it is overloaded with a different number of template parameters */
nn = Getattr(nn,"sym:nextSibling"); /* repeat for overloaded templated functions */
continue;
} else { } else {
int def_supplied = 0; int def_supplied = 0;
/* Expand the template */ /* Expand the template */
@ -2140,50 +2147,51 @@ template_directive: SWIGTEMPLATE LPAREN idstringopt RPAREN idcolonnt LESSTHAN va
} }
} }
$$ = copy_node(n); templnode = copy_node(nn);
/* We need to set the node name based on name used to instantiate */ /* We need to set the node name based on name used to instantiate */
Setattr($$,"name",Copy($5)); Setattr(templnode,"name",Copy($5));
if (!specialized) { if (!specialized) {
Delattr($$,"sym:typename"); Delattr(templnode,"sym:typename");
} else { } else {
Setattr($$,"sym:typename","1"); Setattr(templnode,"sym:typename","1");
} }
if ($3) { if ($3) {
Swig_cparse_template_expand($$,$3,temparms); Swig_cparse_template_expand(templnode,$3,temparms);
Setattr($$,"sym:name",$3); Setattr(templnode,"sym:name",$3);
} else { } else {
static int cnt = 0; static int cnt = 0;
String *nname = NewStringf("__dummy_%d__", cnt++); String *nname = NewStringf("__dummy_%d__", cnt++);
Swig_cparse_template_expand($$,nname,temparms); Swig_cparse_template_expand(templnode,nname,temparms);
Setattr($$,"sym:name",nname); Setattr(templnode,"sym:name",nname);
if (!Swig_template_extmode()) { if (!Swig_template_extmode()) {
Setattr($$,"feature:ignore","1"); Setattr(templnode,"feature:ignore","1");
} else { } else {
Setattr($$,"feature:onlychildren", Setattr(templnode,"feature:onlychildren",
"typemap,typemapitem,typemapcopy,typedef,types,fragment"); "typemap,typemapitem,typemapcopy,typedef,types,fragment");
} }
} }
Delattr($$,"templatetype"); Delattr(templnode,"templatetype");
Setattr($$,"template",n); Setattr(templnode,"template",nn);
tnode = $$; tnode = templnode;
Setfile($$,cparse_file); Setfile(templnode,cparse_file);
Setline($$,cparse_line); Setline(templnode,cparse_line);
Delete(temparms); Delete(temparms);
add_symbols_copy($$); add_symbols_copy(templnode);
if (Strcmp(nodeType($$),"class") == 0) {
if (Strcmp(nodeType(templnode),"class") == 0) {
/* Identify pure abstract methods */ /* Identify pure abstract methods */
Setattr($$,"abstract", pure_abstract(firstChild($$))); Setattr(templnode,"abstract", pure_abstract(firstChild(templnode)));
/* Set up inheritance in symbol table */ /* Set up inheritance in symbol table */
{ {
Symtab *csyms; Symtab *csyms;
List *baselist = Getattr($$,"baselist"); List *baselist = Getattr(templnode,"baselist");
csyms = Swig_symbol_current(); csyms = Swig_symbol_current();
Swig_symbol_setscope(Getattr($$,"symtab")); Swig_symbol_setscope(Getattr(templnode,"symtab"));
if (baselist) { if (baselist) {
List *bases = make_inherit_list(Getattr($$,"name"),baselist); List *bases = make_inherit_list(Getattr(templnode,"name"),baselist);
if (bases) { if (bases) {
Iterator s; Iterator s;
for (s = First(bases); s.item; s = Next(s)) { for (s = First(bases); s.item; s = Next(s)) {
@ -2206,18 +2214,18 @@ template_directive: SWIGTEMPLATE LPAREN idstringopt RPAREN idcolonnt LESSTHAN va
String *clsname; String *clsname;
Node *am; Node *am;
if (Namespaceprefix) { if (Namespaceprefix) {
clsname = NewStringf("%s::%s", Namespaceprefix, Getattr($$,"name")); clsname = NewStringf("%s::%s", Namespaceprefix, Getattr(templnode,"name"));
} else { } else {
clsname = Getattr($$,"name"); clsname = Getattr(templnode,"name");
} }
am = Getattr(extendhash,clsname); am = Getattr(extendhash,clsname);
if (am) { if (am) {
Symtab *st = Swig_symbol_current(); Symtab *st = Swig_symbol_current();
Swig_symbol_setscope(Getattr($$,"symtab")); Swig_symbol_setscope(Getattr(templnode,"symtab"));
/* Printf(stdout,"%s: %s %x %x\n", Getattr($$,"name"), clsname, Swig_symbol_current(), Getattr($$,"symtab")); */ /* Printf(stdout,"%s: %s %x %x\n", Getattr(templnode,"name"), clsname, Swig_symbol_current(), Getattr(templnode,"symtab")); */
merge_extensions($$,am); merge_extensions(templnode,am);
Swig_symbol_setscope(st); Swig_symbol_setscope(st);
appendChild($$,am); appendChild(templnode,am);
Delattr(extendhash,clsname); Delattr(extendhash,clsname);
} }
} }
@ -2226,17 +2234,27 @@ template_directive: SWIGTEMPLATE LPAREN idstringopt RPAREN idcolonnt LESSTHAN va
{ {
if (Namespaceprefix) { if (Namespaceprefix) {
String *temp = NewStringf("%s::%s", Namespaceprefix, Getattr($$,"name")); String *temp = NewStringf("%s::%s", Namespaceprefix, Getattr(templnode,"name"));
Setattr(classes,temp,$$); Setattr(classes,temp,templnode);
} else { } else {
Setattr(classes,Swig_symbol_qualifiedscopename($$),$$); Setattr(classes,Swig_symbol_qualifiedscopename(templnode),templnode);
} }
} }
} }
} }
if ($$ && nspace) { if (templnode && nspace) {
appendChild(nspace_inner,$$); appendChild(nspace_inner,templnode);
$$ = nspace; templnode = nspace;
}
/* all the overloaded templated functions are added into a linked list */
if (!linklistend) {
$$ = templnode;
} else {
set_nextSibling(linklistend,templnode);
}
linklistend = templnode;
}
nn = Getattr(nn,"sym:nextSibling"); /* repeat for overloaded templated functions. If a templated class there will never be a sibling. */
} }
} }
Swig_symbol_setscope(tscope); Swig_symbol_setscope(tscope);

View file

@ -281,7 +281,7 @@ Swig_cparse_template_expand(Node *n, String *rname, ParmList *tparms) {
{ {
Parm *tp = Getattr(n,"templateparms"); Parm *tp = Getattr(n,"templateparms");
Parm *p = tparms; Parm *p = tparms;
/* Printf(stdout,"%s\n", ParmList_str(tp)); */ /* Printf(stdout,"%s\n", ParmList_str_defaultargs(tp)); */
if (tp) { if (tp) {
while (p && tp) { while (p && tp) {
@ -381,13 +381,13 @@ Swig_cparse_template_expand(Node *n, String *rname, ParmList *tparms) {
} }
/* ----------------------------------------------------------------------------- /* -----------------------------------------------------------------------------
* cparse_template_locate() * template_locate()
* *
* Search for a template that matches name with given parameters. * Search for a template that matches name with given parameters.
* ----------------------------------------------------------------------------- */ * ----------------------------------------------------------------------------- */
Node * static Node *
Swig_cparse_template_locate(String *name, Parm *tparms) { template_locate(String *name, Parm *tparms) {
Node *n; Node *n;
String *tname, *rname = 0; String *tname, *rname = 0;
Node *templ; Node *templ;
@ -543,7 +543,7 @@ Swig_cparse_template_locate(String *name, Parm *tparms) {
Delete(rname); Delete(rname);
Delete(mpartials); Delete(mpartials);
if ((template_debug) && (n)) { if ((template_debug) && (n)) {
Printf(stdout,"Node: %x\n", n); Printf(stdout,"Node: %p\n", n);
Swig_print_node(n); Swig_print_node(n);
} }
Delete(parms); Delete(parms);
@ -551,4 +551,58 @@ Swig_cparse_template_locate(String *name, Parm *tparms) {
} }
/* -----------------------------------------------------------------------------
* Swig_cparse_template_locate()
*
* Search for a template that matches name with given parameters.
* For templated classes finds the specialized template should there be one.
* For templated functions finds the unspecialized template even if a specialized
* template exists.
* ----------------------------------------------------------------------------- */
Node *
Swig_cparse_template_locate(String *name, Parm *tparms) {
Node *n = 0;
n = template_locate(name, tparms); /* this function does what we want for templated classes */
if (n) {
int isclass = 0;
assert(Strcmp(nodeType(n),"template") == 0);
isclass = (Strcmp(Getattr(n,"templatetype"),"class") == 0);
if (!isclass) {
/* If not a templated class we must have a templated function.
The template found is not necessarily the one we want when dealing with templated
functions. We don't want any specialized templated functions as they won't have
the default parameters. Lets look for the unspecialized template. Also make sure
the number of template parameters is correct as it is possible to overload a
templated function with different numbers of template parameters. */
if (template_debug) {
Printf(stdout," Not a templated class, seeking most appropriate templated function\n");
}
n = Swig_symbol_clookup_local(name,0);
while (n) {
Parm *tparmsfound = Getattr(n,"templateparms");
if (ParmList_len(tparms) == ParmList_len(tparmsfound)) {
/* successful match */
break;
}
/* repeat until we find a match with correct number of templated parameters */
n = Getattr(n,"sym:nextSibling");
}
if (!n) {
Swig_error(cparse_file, cparse_line, "Template '%s' undefined.\n", name);
}
if ((template_debug) && (n)) {
Printf(stdout,"Templated function found: %p\n", n);
Swig_print_node(n);
}
}
}
return n;
}

View file

@ -192,6 +192,12 @@ int are_equivalent_nodes(Node* a, Node* b, int a_inclass)
ap = nextSibling(ap); ap = nextSibling(ap);
bp = nextSibling(bp); bp = nextSibling(bp);
} }
{
Node *a_template = Getattr(a,"template");
Node *b_template = Getattr(b,"template");
/* Not equivalent if one is a template instantiation (via %template) and the other is a non-templated function */
if ((a_template && !b_template) || (!a_template && b_template)) return 0;
}
return 1; return 1;
} }
} }

View file

@ -180,8 +180,9 @@ Swig_symbol_dump_symtable() {
{ {
Hash* cst = Getattr(current_symtab, "csymtab"); Hash* cst = Getattr(current_symtab, "csymtab");
Swig_print_tree(cst); Swig_print_tree(cst);
Printf(stdout, "DUMPING SYMTABLE middle =======================================\n"); /*
Swig_print_tree(Getattr(cst, "NumSpace")); Swig_print_tree(Getattr(cst, "NumSpace"));
*/
} }
Printf(stdout, "DUMPING SYMTABLE end =======================================\n"); Printf(stdout, "DUMPING SYMTABLE end =======================================\n");
} }
@ -675,7 +676,11 @@ Swig_symbol_add(String_or_char *symname, Node *n) {
if (Cmp(nstorage,"typedef") == 0) { if (Cmp(nstorage,"typedef") == 0) {
return c; return c;
} }
/* Okay. Walk down the list of symbols and see if we get a declarator match */ /* Okay. Walk down the list of symbols and see if we get a declarator match */
{
int n_template = (Strcmp(nodeType(n),"template") == 0) && (Strcmp(Getattr(n,"templatetype"),"cdecl") == 0);
int n_plain_cdecl = (Strcmp(nodeType(n),"cdecl") == 0);
cn = c; cn = c;
pn = 0; pn = 0;
while (cn) { while (cn) {
@ -683,13 +688,21 @@ Swig_symbol_add(String_or_char *symname, Node *n) {
if (!(u1 || u2)) { if (!(u1 || u2)) {
if (Cmp(ndecl,decl) == 0) { if (Cmp(ndecl,decl) == 0) {
/* Declarator conflict */ /* Declarator conflict */
/* Now check we don't have a non-templated function overloaded by a templated function with same params,
* eg void foo(); template<typename> void foo(); */
int cn_template = (Strcmp(nodeType(cn),"template") == 0) && (Strcmp(Getattr(cn,"templatetype"),"cdecl") == 0);
int cn_plain_cdecl = (Strcmp(nodeType(cn),"cdecl") == 0);
if (!((n_template && cn_plain_cdecl) || (cn_template && n_plain_cdecl))) {
/* found a conflict */
return cn; return cn;
} }
} }
}
cl = cn; cl = cn;
cn = Getattr(cn,"sym:nextSibling"); cn = Getattr(cn,"sym:nextSibling");
pn++; pn++;
} }
}
/* Well, we made it this far. Guess we can drop the symbol in place */ /* Well, we made it this far. Guess we can drop the symbol in place */
Setattr(n,"sym:symtab",current_symtab); Setattr(n,"sym:symtab",current_symtab);
Setattr(n,"sym:name",symname); Setattr(n,"sym:name",symname);