Fix using statements for overloaded methods

git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/trunk@10176 626c5289-ae23-0410-ae9c-e8d60b6d4f22
This commit is contained in:
William S Fulton 2007-11-30 22:34:50 +00:00
commit 575efcdd53
9 changed files with 317 additions and 52 deletions

View file

@ -564,7 +564,6 @@ class TypePass:private Dispatcher {
* ------------------------------------------------------------ */
virtual int cDeclaration(Node *n) {
if (NoExcept) {
Delattr(n, "throws");
}
@ -777,6 +776,35 @@ class TypePass:private Dispatcher {
return enumDeclaration(n);
}
#ifdef DEBUG_OVERLOADED
static void show_overloaded(Node *n) {
Node *c = Getattr(n, "sym:overloaded");
Node *checkoverloaded = c;
Printf(stdout, "-------------------- overloaded start %s sym:overloaded():%p -------------------------------\n", Getattr(n, "name"), c);
while (c) {
if (Getattr(c, "error")) {
c = Getattr(c, "sym:nextSibling");
continue;
}
if (Getattr(c, "sym:overloaded") != checkoverloaded) {
Printf(stdout, "sym:overloaded error c:%p checkoverloaded:%p\n", c, checkoverloaded);
Swig_print_node(c);
exit (1);
}
String *decl = Strcmp(nodeType(c), "using") == 0 ? NewString("------") : Getattr(c, "decl");
Printf(stdout, " show_overloaded %s::%s(%s) [%s] nodeType:%s\n", parentNode(c) ? Getattr(parentNode(c), "name") : "NOPARENT", Getattr(c, "name"), decl, Getattr(c, "sym:overname"), nodeType(c));
if (!Getattr(c, "sym:overloaded")) {
Printf(stdout, "sym:overloaded error.....%p\n", c);
Swig_print_node(c);
exit (1);
}
c = Getattr(c, "sym:nextSibling");
}
Printf(stdout, "-------------------- overloaded end %s -------------------------------\n", Getattr(n, "name"));
}
#endif
/* ------------------------------------------------------------
* usingDeclaration()
* ------------------------------------------------------------ */
@ -816,10 +844,8 @@ class TypePass:private Dispatcher {
Swig_warning(WARN_PARSE_USING_UNDEF, Getfile(n), Getline(n), "Nothing known about '%s'.\n", SwigType_namestr(Getattr(n, "uname")));
}
} else {
/* Only a single symbol is being used. There are only a few symbols that
we actually care about. These are typedef, class declarations, and enum */
String *ntype = nodeType(ns);
if (Strcmp(ntype, "cdecl") == 0) {
if (checkAttribute(ns, "storage", "typedef")) {
@ -841,9 +867,15 @@ class TypePass:private Dispatcher {
|| (Getattr(c, "feature:extend") && !Getattr(c, "code"))
|| GetFlag(c, "feature:ignore"))) {
/* Don't generate a method if the method is overridden in this class,
* for example don't generate another m(bool) should there be a Base::m(bool) :
* struct Derived : Base {
* void m(bool);
* using Base::m;
* };
*/
String *csymname = Getattr(c, "sym:name");
if (!csymname || (Strcmp(csymname, symname) == 0)) {
/* Check for existence in overload list already */
{
String *decl = Getattr(c, "decl");
Node *over = Getattr(n, "sym:overloaded");
@ -918,6 +950,75 @@ class TypePass:private Dispatcher {
}
}
}
/* Hack the parse tree symbol table for overloaded methods. Replace the "using" node with the
* list of overloaded methods we have just added in as child nodes to the "using" node.
* The node will still exist, it is just the symbol table linked list of overloaded methods
* which is hacked. */
if (Getattr(n, "sym:overloaded"))
{
#ifdef DEBUG_OVERLOADED
show_overloaded(n);
#endif
int cnt = 0;
Node *debugnode = n;
if (!firstChild(n)) {
// Remove from overloaded list ('using' node does not actually end up adding in any methods)
Node *ps = Getattr(n, "sym:previousSibling");
Node *ns = Getattr(n, "sym:nextSibling");
if (ps) {
Setattr(ps, "sym:nextSibling", ns);
}
if (ns) {
Setattr(ns, "sym:previousSibling", ps);
}
} else {
// The 'using' node results in methods being added in - slot in the these methods here
Node *ps = Getattr(n, "sym:previousSibling");
Node *ns = Getattr(n, "sym:nextSibling");
Node *fc = firstChild(n);
Node *pp = fc;
Node *firstoverloaded = Getattr(n, "sym:overloaded");
if (firstoverloaded == n) {
// This 'using' node we are cutting out was the first node in the overloaded list.
// Change the first node in the list to its first sibling
Delattr(firstoverloaded, "sym:overloaded");
Node *nnn = Getattr(firstoverloaded, "sym:nextSibling");
firstoverloaded = fc;
while (nnn) {
Setattr(nnn, "sym:overloaded", firstoverloaded);
nnn = Getattr(nnn, "sym:nextSibling");
}
}
while (pp) {
Node *ppn = Getattr(pp, "sym:nextSibling");
Setattr(pp, "sym:overloaded", firstoverloaded);
Setattr(pp, "sym:overname", NewStringf("%s_%d", Getattr(n, "sym:overname"), cnt++));
if (ppn)
pp = ppn;
else
break;
}
if (ps) {
Setattr(ps, "sym:nextSibling", fc);
Setattr(fc, "sym:previousSibling", ps);
}
if (ns) {
Setattr(ns, "sym:previousSibling", pp);
Setattr(pp, "sym:nextSibling", ns);
}
debugnode = firstoverloaded;
}
Delattr(n, "sym:previousSibling");
Delattr(n, "sym:nextSibling");
Delattr(n, "sym:overloaded");
Delattr(n, "sym:overname");
#ifdef DEBUG_OVERLOADED
show_overloaded(debugnode);
#endif
clean_overloaded(n); // Needed?
}
}
}
} else if ((Strcmp(ntype, "class") == 0) || ((Strcmp(ntype, "classforward") == 0))) {

View file

@ -46,19 +46,17 @@ int is_member_director(Node *member) {
return is_member_director(Getattr(member, "parentNode"), member);
}
/* Clean overloaded list. Removes templates, ignored, and errors */
void clean_overloaded(Node *n) {
Node *nn = Getattr(n, "sym:overloaded");
Node *first = 0;
int cnt = 0;
while (nn) {
String *ntype = nodeType(nn);
if ((GetFlag(nn, "feature:ignore")) ||
(Getattr(nn, "error")) ||
(Strcmp(ntype, "template") == 0) ||
((Strcmp(ntype, "cdecl") == 0) && is_protected(nn) && !is_member_director(nn)) || ((Strcmp(ntype, "using") == 0) && !firstChild(nn))) {
((Strcmp(ntype, "cdecl") == 0) && is_protected(nn) && !is_member_director(nn))) {
/* Remove from overloaded list */
Node *ps = Getattr(nn, "sym:previousSibling");
Node *ns = Getattr(nn, "sym:nextSibling");
@ -73,40 +71,6 @@ void clean_overloaded(Node *n) {
Delattr(nn, "sym:overloaded");
nn = ns;
continue;
} else if ((Strcmp(ntype, "using") == 0)) {
/* A possibly dangerous parse tree hack. We're going to
cut the parse tree node out and stick in the resolved
using declarations */
Node *ps = Getattr(nn, "sym:previousSibling");
Node *ns = Getattr(nn, "sym:nextSibling");
Node *un = firstChild(nn);
Node *pn = un;
if (!first) {
first = un;
}
while (pn) {
Node *ppn = Getattr(pn, "sym:nextSibling");
Setattr(pn, "sym:overloaded", first);
Setattr(pn, "sym:overname", NewStringf("%s_%d", Getattr(nn, "sym:overname"), cnt++));
if (ppn)
pn = ppn;
else
break;
}
if (ps) {
Setattr(ps, "sym:nextSibling", un);
Setattr(un, "sym:previousSibling", ps);
}
if (ns) {
Setattr(ns, "sym:previousSibling", pn);
Setattr(pn, "sym:nextSibling", ns);
}
if (!first) {
first = un;
Setattr(nn, "sym:overloaded", first);
}
} else {
if (!first)
first = nn;
@ -115,6 +79,7 @@ void clean_overloaded(Node *n) {
nn = Getattr(nn, "sym:nextSibling");
}
if (!first || (first && !Getattr(first, "sym:nextSibling"))) {
Delattr(n, "sym:overloaded");
if (Getattr(n, "sym:overloaded"))
Delattr(n, "sym:overloaded");
}
}