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:
parent
7f9ad65f89
commit
13926748ee
4 changed files with 253 additions and 162 deletions
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue