mirror of https://github.com/swig/swig
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:
parent
84dc1cc4f6
commit
575efcdd53
|
@ -1,3 +1,13 @@
|
|||
Version 1.3.34 (in progress)
|
||||
============================
|
||||
|
||||
11/30/2007: wsfulton
|
||||
Fix using statements using a base class method where the methods were overloaded.
|
||||
Depending on the order of the using statements and method declarations, these
|
||||
were previously generating uncompileable wrappers, eg:
|
||||
|
||||
struct Derived : Base {
|
||||
virtual void funk();
|
||||
using Base::funk;
|
||||
};
|
||||
|
||||
|
|
|
@ -2,10 +2,33 @@ from using_composition import *
|
|||
|
||||
f = FooBar()
|
||||
if f.blah(3) != 3:
|
||||
raise RuntimeError,"blah(int)"
|
||||
raise RuntimeError,"FooBar::blah(int)"
|
||||
|
||||
if f.blah(3.5) != 3.5:
|
||||
raise RuntimeError,"blah(double)"
|
||||
raise RuntimeError,"FooBar::blah(double)"
|
||||
|
||||
if f.blah("hello") != "hello":
|
||||
raise RuntimeError,"blah(char *)"
|
||||
raise RuntimeError,"FooBar::blah(char *)"
|
||||
|
||||
|
||||
f = FooBar2()
|
||||
if f.blah(3) != 3:
|
||||
raise RuntimeError,"FooBar2::blah(int)"
|
||||
|
||||
if f.blah(3.5) != 3.5:
|
||||
raise RuntimeError,"FooBar2::blah(double)"
|
||||
|
||||
if f.blah("hello") != "hello":
|
||||
raise RuntimeError,"FooBar2::blah(char *)"
|
||||
|
||||
|
||||
f = FooBar3()
|
||||
if f.blah(3) != 3:
|
||||
raise RuntimeError,"FooBar3::blah(int)"
|
||||
|
||||
if f.blah(3.5) != 3.5:
|
||||
raise RuntimeError,"FooBar3::blah(double)"
|
||||
|
||||
if f.blah("hello") != "hello":
|
||||
raise RuntimeError,"FooBar3::blah(char *)"
|
||||
|
||||
|
|
|
@ -2,7 +2,48 @@ from using_inherit import *
|
|||
|
||||
b = Bar()
|
||||
if b.test(3) != 3:
|
||||
raise RuntimeError,"test(int)"
|
||||
raise RuntimeError,"Bar::test(int)"
|
||||
|
||||
if b.test(3.5) != 3.5:
|
||||
raise RuntimeError, "test(double)"
|
||||
raise RuntimeError, "Bar::test(double)"
|
||||
|
||||
|
||||
b = Bar2()
|
||||
if b.test(3) != 6:
|
||||
raise RuntimeError,"Bar2::test(int)"
|
||||
|
||||
if b.test(3.5) != 7.0:
|
||||
raise RuntimeError, "Bar2::test(double)"
|
||||
|
||||
|
||||
b = Bar3()
|
||||
if b.test(3) != 6:
|
||||
raise RuntimeError,"Bar3::test(int)"
|
||||
|
||||
if b.test(3.5) != 7.0:
|
||||
raise RuntimeError, "Bar3::test(double)"
|
||||
|
||||
|
||||
b = Bar4()
|
||||
if b.test(3) != 6:
|
||||
raise RuntimeError,"Bar4::test(int)"
|
||||
|
||||
if b.test(3.5) != 7.0:
|
||||
raise RuntimeError, "Bar4::test(double)"
|
||||
|
||||
|
||||
b = Fred1()
|
||||
if b.test(3) != 3:
|
||||
raise RuntimeError,"Fred1::test(int)"
|
||||
|
||||
if b.test(3.5) != 7.0:
|
||||
raise RuntimeError, "Fred1::test(double)"
|
||||
|
||||
|
||||
b = Fred2()
|
||||
if b.test(3) != 3:
|
||||
raise RuntimeError,"Fred2::test(int)"
|
||||
|
||||
if b.test(3.5) != 7.0:
|
||||
raise RuntimeError, "Fred2::test(double)"
|
||||
|
||||
|
|
|
@ -15,14 +15,42 @@ include Using_composition
|
|||
|
||||
f = FooBar.new
|
||||
if f.blah(3) != 3
|
||||
raise RuntimeError,"blah(int)"
|
||||
raise RuntimeError,"FooBar::blah(int)"
|
||||
end
|
||||
|
||||
if f.blah(3.5) != 3.5
|
||||
raise RuntimeError,"blah(double)"
|
||||
raise RuntimeError,"FooBar::blah(double)"
|
||||
end
|
||||
|
||||
if f.blah("hello") != "hello"
|
||||
raise RuntimeError,"blah(char *)"
|
||||
raise RuntimeError,"FooBar::blah(char *)"
|
||||
end
|
||||
|
||||
|
||||
f = FooBar2.new
|
||||
if f.blah(3) != 3
|
||||
raise RuntimeError,"FooBar2::blah(int)"
|
||||
end
|
||||
|
||||
if f.blah(3.5) != 3.5
|
||||
raise RuntimeError,"FooBar2::blah(double)"
|
||||
end
|
||||
|
||||
if f.blah("hello") != "hello"
|
||||
raise RuntimeError,"FooBar2::blah(char *)"
|
||||
end
|
||||
|
||||
|
||||
f = FooBar3.new
|
||||
if f.blah(3) != 3
|
||||
raise RuntimeError,"FooBar3::blah(int)"
|
||||
end
|
||||
|
||||
if f.blah(3.5) != 3.5
|
||||
raise RuntimeError,"FooBar3::blah(double)"
|
||||
end
|
||||
|
||||
if f.blah("hello") != "hello"
|
||||
raise RuntimeError,"FooBar3::blah(char *)"
|
||||
end
|
||||
|
||||
|
|
|
@ -15,10 +15,60 @@ include Using_inherit
|
|||
|
||||
b = Bar.new
|
||||
if b.test(3) != 3
|
||||
raise RuntimeError,"test(int)"
|
||||
raise RuntimeError,"Bar::test(int)"
|
||||
end
|
||||
|
||||
if b.test(3.5) != 3.5
|
||||
raise RuntimeError, "test(double)"
|
||||
raise RuntimeError, "Bar::test(double)"
|
||||
end
|
||||
|
||||
b = Bar2.new
|
||||
if b.test(3) != 6
|
||||
raise RuntimeError,"Bar2::test(int)"
|
||||
end
|
||||
|
||||
if b.test(3.5) != 7.0
|
||||
raise RuntimeError, "Bar2::test(double)"
|
||||
end
|
||||
|
||||
|
||||
b = Bar3.new
|
||||
if b.test(3) != 6
|
||||
raise RuntimeError,"Bar3::test(int)"
|
||||
end
|
||||
|
||||
if b.test(3.5) != 7.0
|
||||
raise RuntimeError, "Bar3::test(double)"
|
||||
end
|
||||
|
||||
|
||||
b = Bar4.new
|
||||
if b.test(3) != 6
|
||||
raise RuntimeError,"Bar4::test(int)"
|
||||
end
|
||||
|
||||
if b.test(3.5) != 7.0
|
||||
raise RuntimeError, "Bar4::test(double)"
|
||||
end
|
||||
|
||||
|
||||
b = Fred1.new
|
||||
if b.test(3) != 3
|
||||
raise RuntimeError,"Fred1::test(int)"
|
||||
end
|
||||
|
||||
if b.test(3.5) != 7.0
|
||||
raise RuntimeError, "Fred1::test(double)"
|
||||
end
|
||||
|
||||
|
||||
b = Fred2.new
|
||||
if b.test(3) != 3
|
||||
raise RuntimeError,"Fred2::test(int)"
|
||||
end
|
||||
|
||||
if b.test(3.5) != 7.0
|
||||
raise RuntimeError, "Fred2::test(double)"
|
||||
end
|
||||
|
||||
|
||||
|
|
|
@ -26,4 +26,18 @@ public:
|
|||
char *blah(char *x) { return x; }
|
||||
};
|
||||
|
||||
class FooBar2 : public Foo, public Bar {
|
||||
public:
|
||||
char *blah(char *x) { return x; }
|
||||
using Foo::blah;
|
||||
using Bar::blah;
|
||||
};
|
||||
|
||||
class FooBar3 : public Foo, public Bar {
|
||||
public:
|
||||
using Foo::blah;
|
||||
char *blah(char *x) { return x; }
|
||||
using Bar::blah;
|
||||
};
|
||||
|
||||
%}
|
||||
|
|
|
@ -17,5 +17,38 @@ public:
|
|||
using Foo::test;
|
||||
};
|
||||
|
||||
class Bar2 : public Foo {
|
||||
public:
|
||||
int test(int x) { return x*2; }
|
||||
double test(double x) { return x*2; };
|
||||
using Foo::test;
|
||||
};
|
||||
|
||||
class Bar3 : public Foo {
|
||||
public:
|
||||
int test(int x) { return x*2; }
|
||||
double test(double x) { return x*2; };
|
||||
using Foo::test;
|
||||
};
|
||||
|
||||
class Bar4 : public Foo {
|
||||
public:
|
||||
int test(int x) { return x*2; }
|
||||
using Foo::test;
|
||||
double test(double x) { return x*2; };
|
||||
};
|
||||
|
||||
class Fred1 : public Foo {
|
||||
public:
|
||||
using Foo::test;
|
||||
double test(double x) { return x*2; };
|
||||
};
|
||||
|
||||
class Fred2 : public Foo {
|
||||
public:
|
||||
double test(double x) { return x*2; };
|
||||
using Foo::test;
|
||||
};
|
||||
|
||||
%}
|
||||
|
||||
|
|
|
@ -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))) {
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue