templated function overloading support

git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/trunk/SWIG@6394 626c5289-ae23-0410-ae9c-e8d60b6d4f22
This commit is contained in:
William S Fulton 2004-10-16 20:41:17 +00:00
commit 13926748ee
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);
}
c = Swig_symbol_add(symname,n);
if (c != n) {
/* symbol conflict attempting to add in the new symbol */
if (Getattr(n,"sym:weak")) {
Setattr(n,"sym:name",symname);
} else if ((Strcmp(nodeType(n),"template") == 0) && (Strcmp(Getattr(n,"templatetype"),"cdecl") == 0)) {
Setattr(n,"sym:name",symname);
} else {
String *e = NewString("");
String *en = NewString("");
@ -892,7 +892,6 @@ static void default_arguments(Node *n) {
}
if (default_args) {
ParmList* newparms = 0;
/* Create a parameter list for the new function by copying all
but the last (defaulted) parameter */
{
@ -933,14 +932,12 @@ static void default_arguments(Node *n) {
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) {
Node *templatetype = Getattr(function,"templatetype");
Node *symname = Getattr(function,"sym:name");
Node *symtypename = Getattr(function,"sym:typename");
Parm *templateparms = Getattr(function,"templateparms");
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 (templateparms) Setattr(new_function,"templateparms",CopyParmList(templateparms));
}
@ -2097,147 +2094,168 @@ template_directive: SWIGTEMPLATE LPAREN idstringopt RPAREN idcolonnt LESSTHAN va
}
p = nextSibling(p);
}
/* Look for the template */
{
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) {
specialized = 1;
}
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));
} 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));
} 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 {
int def_supplied = 0;
/* Expand the template */
ParmList *temparms;
if (specialized) temparms = CopyParmList($7);
else temparms = CopyParmList(tparms);
if (n && (Strcmp(nodeType(n),"template") == 0)) {
Parm *tparms = Getattr(n,"templateparms");
if (!tparms) {
specialized = 1;
}
if (!specialized && ((ParmList_len($7) > 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)))) {
Swig_error(cparse_file, cparse_line, "Not enough template parameters specified. %d required.\n", ParmList_numrequired(tparms));
} else {
int def_supplied = 0;
/* Expand the template */
ParmList *temparms;
if (specialized) temparms = CopyParmList($7);
else temparms = CopyParmList(tparms);
/* Create typedef's and arguments */
p = $7;
tp = temparms;
while (p) {
String *value = Getattr(p,"value");
if (def_supplied) {
Setattr(p,"default","1");
}
if (value) {
Setattr(tp,"value",value);
} else {
SwigType *ty = Getattr(p,"type");
if (ty) {
Setattr(tp,"type",ty);
}
Delattr(tp,"value");
}
p = nextSibling(p);
tp = nextSibling(tp);
if (!p && tp) {
p = tp;
def_supplied = 1;
}
}
/* Create typedef's and arguments */
p = $7;
tp = temparms;
while (p) {
String *value = Getattr(p,"value");
if (def_supplied) {
Setattr(p,"default","1");
}
if (value) {
Setattr(tp,"value",value);
} else {
SwigType *ty = Getattr(p,"type");
if (ty) {
Setattr(tp,"type",ty);
}
Delattr(tp,"value");
}
p = nextSibling(p);
tp = nextSibling(tp);
if (!p && tp) {
p = tp;
def_supplied = 1;
}
}
templnode = copy_node(nn);
/* We need to set the node name based on name used to instantiate */
Setattr(templnode,"name",Copy($5));
if (!specialized) {
Delattr(templnode,"sym:typename");
} else {
Setattr(templnode,"sym:typename","1");
}
if ($3) {
Swig_cparse_template_expand(templnode,$3,temparms);
Setattr(templnode,"sym:name",$3);
} else {
static int cnt = 0;
String *nname = NewStringf("__dummy_%d__", cnt++);
Swig_cparse_template_expand(templnode,nname,temparms);
Setattr(templnode,"sym:name",nname);
if (!Swig_template_extmode()) {
Setattr(templnode,"feature:ignore","1");
} else {
Setattr(templnode,"feature:onlychildren",
"typemap,typemapitem,typemapcopy,typedef,types,fragment");
}
}
Delattr(templnode,"templatetype");
Setattr(templnode,"template",nn);
tnode = templnode;
Setfile(templnode,cparse_file);
Setline(templnode,cparse_line);
Delete(temparms);
add_symbols_copy(templnode);
$$ = copy_node(n);
/* We need to set the node name based on name used to instantiate */
Setattr($$,"name",Copy($5));
if (!specialized) {
Delattr($$,"sym:typename");
} else {
Setattr($$,"sym:typename","1");
}
if ($3) {
Swig_cparse_template_expand($$,$3,temparms);
Setattr($$,"sym:name",$3);
} else {
static int cnt = 0;
String *nname = NewStringf("__dummy_%d__", cnt++);
Swig_cparse_template_expand($$,nname,temparms);
Setattr($$,"sym:name",nname);
if (!Swig_template_extmode()) {
Setattr($$,"feature:ignore","1");
} else {
Setattr($$,"feature:onlychildren",
"typemap,typemapitem,typemapcopy,typedef,types,fragment");
}
}
Delattr($$,"templatetype");
Setattr($$,"template",n);
tnode = $$;
Setfile($$,cparse_file);
Setline($$,cparse_line);
Delete(temparms);
add_symbols_copy($$);
if (Strcmp(nodeType($$),"class") == 0) {
if (Strcmp(nodeType(templnode),"class") == 0) {
/* Identify pure abstract methods */
Setattr($$,"abstract", pure_abstract(firstChild($$)));
/* Set up inheritance in symbol table */
{
Symtab *csyms;
List *baselist = Getattr($$,"baselist");
csyms = Swig_symbol_current();
Swig_symbol_setscope(Getattr($$,"symtab"));
if (baselist) {
List *bases = make_inherit_list(Getattr($$,"name"),baselist);
if (bases) {
Iterator s;
for (s = First(bases); s.item; s = Next(s)) {
Symtab *st = Getattr(s.item,"symtab");
if (st) {
Swig_symbol_inherit(st);
}
}
}
}
Swig_symbol_setscope(csyms);
}
/* Identify pure abstract methods */
Setattr(templnode,"abstract", pure_abstract(firstChild(templnode)));
/* Set up inheritance in symbol table */
{
Symtab *csyms;
List *baselist = Getattr(templnode,"baselist");
csyms = Swig_symbol_current();
Swig_symbol_setscope(Getattr(templnode,"symtab"));
if (baselist) {
List *bases = make_inherit_list(Getattr(templnode,"name"),baselist);
if (bases) {
Iterator s;
for (s = First(bases); s.item; s = Next(s)) {
Symtab *st = Getattr(s.item,"symtab");
if (st) {
Swig_symbol_inherit(st);
}
}
}
}
Swig_symbol_setscope(csyms);
}
/* Merge in addmethods for this class */
/* !!! This may be broken. We may have to add the addmethods at the beginning of
the class */
if (extendhash) {
String *clsname;
Node *am;
if (Namespaceprefix) {
clsname = NewStringf("%s::%s", Namespaceprefix, Getattr($$,"name"));
} else {
clsname = Getattr($$,"name");
}
am = Getattr(extendhash,clsname);
if (am) {
Symtab *st = Swig_symbol_current();
Swig_symbol_setscope(Getattr($$,"symtab"));
/* Printf(stdout,"%s: %s %x %x\n", Getattr($$,"name"), clsname, Swig_symbol_current(), Getattr($$,"symtab")); */
merge_extensions($$,am);
Swig_symbol_setscope(st);
appendChild($$,am);
Delattr(extendhash,clsname);
}
}
/* Add to classes hash */
if (!classes) classes = NewHash();
/* Merge in addmethods for this class */
/* !!! This may be broken. We may have to add the addmethods at the beginning of
the class */
if (extendhash) {
String *clsname;
Node *am;
if (Namespaceprefix) {
clsname = NewStringf("%s::%s", Namespaceprefix, Getattr(templnode,"name"));
} else {
clsname = Getattr(templnode,"name");
}
am = Getattr(extendhash,clsname);
if (am) {
Symtab *st = Swig_symbol_current();
Swig_symbol_setscope(Getattr(templnode,"symtab"));
/* Printf(stdout,"%s: %s %x %x\n", Getattr(templnode,"name"), clsname, Swig_symbol_current(), Getattr(templnode,"symtab")); */
merge_extensions(templnode,am);
Swig_symbol_setscope(st);
appendChild(templnode,am);
Delattr(extendhash,clsname);
}
}
/* Add to classes hash */
if (!classes) classes = NewHash();
{
if (Namespaceprefix) {
String *temp = NewStringf("%s::%s", Namespaceprefix, Getattr($$,"name"));
Setattr(classes,temp,$$);
} else {
Setattr(classes,Swig_symbol_qualifiedscopename($$),$$);
}
}
}
}
if ($$ && nspace) {
appendChild(nspace_inner,$$);
$$ = nspace;
}
{
if (Namespaceprefix) {
String *temp = NewStringf("%s::%s", Namespaceprefix, Getattr(templnode,"name"));
Setattr(classes,temp,templnode);
} else {
Setattr(classes,Swig_symbol_qualifiedscopename(templnode),templnode);
}
}
}
}
if (templnode && nspace) {
appendChild(nspace_inner,templnode);
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);
Namespaceprefix = Swig_symbol_qualifiedscopename(0);

View file

@ -281,7 +281,7 @@ Swig_cparse_template_expand(Node *n, String *rname, ParmList *tparms) {
{
Parm *tp = Getattr(n,"templateparms");
Parm *p = tparms;
/* Printf(stdout,"%s\n", ParmList_str(tp)); */
/* Printf(stdout,"%s\n", ParmList_str_defaultargs(tp)); */
if (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.
* ----------------------------------------------------------------------------- */
Node *
Swig_cparse_template_locate(String *name, Parm *tparms) {
static Node *
template_locate(String *name, Parm *tparms) {
Node *n;
String *tname, *rname = 0;
Node *templ;
@ -543,7 +543,7 @@ Swig_cparse_template_locate(String *name, Parm *tparms) {
Delete(rname);
Delete(mpartials);
if ((template_debug) && (n)) {
Printf(stdout,"Node: %x\n", n);
Printf(stdout,"Node: %p\n", n);
Swig_print_node(n);
}
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);
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;
}
}