Using declarations, directors and overloaded methods

Language::unrollVirtualMethods was assuming that the using
declaration would only introduce one method. Fix this by adding
in all the overloaded methods from a base class.

Affects code generation in C# and Java, but I was not able
to construct a test that failed before this commit.
This commit is contained in:
William S Fulton 2022-03-10 21:11:18 +00:00
parent 8a8532d823
commit 50518d4e77
4 changed files with 167 additions and 12 deletions

View File

@ -0,0 +1,70 @@
using System;
namespace director_using_member_scopesNamespace {
public class runme
{
static void Main()
{
runme r = new runme();
r.run();
}
void run()
{
NativeWindowType nwt = new NativeWindowType();
{
MyApplicationContextSDL a = new MyApplicationContextSDL();
if (ApplicationContextBase.call_setWindowGrab(a, nwt, true) != 100)
throw new Exception("failed");
if (ApplicationContextSDL.call_setWindowGrab(a, nwt, true) != 100)
throw new Exception("failed");
}
{
MyACSDL a = new MyACSDL();
if (ACB.call_setWindowGrab(a, nwt, true) != 100)
throw new Exception("failed");
if (ACB.call_setWindowGrab(a, "hi", 0) != 200)
throw new Exception("failed");
if (ACSDL.call_setWindowGrab(a, nwt, true) != 100)
throw new Exception("failed");
if (ACSDL.call_setWindowGrab(a, "hi", 0) != 200)
throw new Exception("failed");
}
}
}
class MyApplicationContextSDL: ApplicationContextSDL
{
public MyApplicationContextSDL() : base()
{
}
public override int setWindowGrab(NativeWindowType win, bool grab)
{
return 100;
}
}
class MyACSDL: ACSDL
{
public MyACSDL() : base()
{
}
public override int setWindowGrab(NativeWindowType win, bool grab)
{
return 100;
}
public override int setWindowGrab(string s, int val)
{
return 200;
}
}
}

View File

@ -2,7 +2,7 @@
// Similar to using_member_scopes but for directors
#if !defined(SWIGGO)
#if !defined(SWIGGO) // TODO: fix Go crash
%feature("director");
// Python,Java,C# no diffs in generated code when adding in nodirector. Go not happy even without %nodirector.
@ -18,13 +18,36 @@ namespace OgreBites
class ApplicationContextBase {
public:
virtual ~ApplicationContextBase() {}
virtual void setWindowGrab(NativeWindowType* win, bool grab = true) {}
void setWindowGrab(bool grab = true) {}
virtual int setWindowGrab(NativeWindowType* win, bool grab = true) { return 0; }
int setWindowGrab(bool grab = true) { return 5; }
static int call_setWindowGrab(ApplicationContextBase* ptr, NativeWindowType* win, bool grab) { return ptr->setWindowGrab(win, grab); }
};
class ApplicationContextSDL : public ApplicationContextBase {
public:
using ApplicationContextBase::setWindowGrab;
void setWindowGrab(NativeWindowType* win, bool grab) {} // This should not be added again as it exists in base class
int setWindowGrab(NativeWindowType* win, bool grab) { return 10; } // This should not be added again as it exists in base class
static int call_setWindowGrab(ApplicationContextSDL* ptr, NativeWindowType* win, bool grab) { return ptr->setWindowGrab(win, grab); }
};
class ACB {
public:
virtual ~ACB() {}
virtual int setWindowGrab(NativeWindowType* win, bool grab = true) { return 0; }
virtual int setWindowGrab(const char *s, int val) { return 1; } // Additional method compared to ApplicationContextBase
int setWindowGrab(bool grab = true) { return 5; }
static int call_setWindowGrab(ACB* ptr, NativeWindowType* win, bool grab) { return ptr->setWindowGrab(win, grab); }
static int call_setWindowGrab(ACB* ptr, const char *s, int val) { return ptr->setWindowGrab(s, val); }
};
class ACSDL : public ACB {
public:
using ACB::setWindowGrab; // This introduces two methods, not one method like ApplicationContextSDL
int setWindowGrab(NativeWindowType* win, bool grab) { return 10; } // This should not be added again as it exists in base class
static int call_setWindowGrab(ACSDL* ptr, NativeWindowType* win, bool grab) { return ptr->setWindowGrab(win, grab); }
static int call_setWindowGrab(ACSDL* ptr, const char *s, int val) { return ptr->setWindowGrab(s, val); }
};
}
%}

View File

@ -0,0 +1,64 @@
import director_using_member_scopes.*;
public class director_using_member_scopes_runme {
static {
try {
System.loadLibrary("director_using_member_scopes");
} catch (UnsatisfiedLinkError e) {
System.err.println("Native code library failed to load. See the chapter on Dynamic Linking Problems in the SWIG Java documentation for help.\n" + e);
System.exit(1);
}
}
public static void main(String argv[]) {
NativeWindowType nwt = new NativeWindowType();
{
director_using_member_scopes_MyApplicationContextSDL a = new director_using_member_scopes_MyApplicationContextSDL();
if (ApplicationContextBase.call_setWindowGrab(a, nwt, true) != 100)
throw new RuntimeException("failed");
if (ApplicationContextSDL.call_setWindowGrab(a, nwt, true) != 100)
throw new RuntimeException("failed");
}
{
director_using_member_scopes_MyACSDL a = new director_using_member_scopes_MyACSDL();
if (ACB.call_setWindowGrab(a, nwt, true) != 100)
throw new RuntimeException("failed");
if (ACB.call_setWindowGrab(a, "hi", 0) != 200)
throw new RuntimeException("failed");
if (ACSDL.call_setWindowGrab(a, nwt, true) != 100)
throw new RuntimeException("failed");
if (ACSDL.call_setWindowGrab(a, "hi", 0) != 200)
throw new RuntimeException("failed");
}
}
}
class director_using_member_scopes_MyApplicationContextSDL extends ApplicationContextSDL {
@Override
public int setWindowGrab(NativeWindowType win, boolean grab)
{
return 100;
}
}
class director_using_member_scopes_MyACSDL extends ACSDL {
@Override
public int setWindowGrab(NativeWindowType win, boolean grab)
{
return 100;
}
@Override
public int setWindowGrab(String s, int val)
{
return 200;
}
}

View File

@ -1948,16 +1948,14 @@ int Language::unrollVirtualMethods(Node *n, Node *parent, List *vm, int &virtual
// find the methods that need directors
String *classname = Getattr(n, "name");
for (Node *ni = Getattr(n, "firstChild"); ni; ni = nextSibling(ni)) {
for (Node *ni = firstChild(n); ni; ni = nextSibling(ni)) {
/* we only need to check the virtual members */
String *nodeType = Getattr(ni, "nodeType");
int is_using = (Cmp(nodeType, "using") == 0);
Node *nn = is_using ? firstChild(ni) : ni; /* assume there is only one child node for "using" nodes */
if (is_using) {
if (!nn)
continue; // A using node with no added functions, or a using node with private access
if (Equal(nodeType(ni), "using")) {
for (Node *nn = firstChild(ni); nn; nn = Getattr(nn, "sym:nextSibling")) {
unrollOneVirtualMethod(classname, nn, parent, vm, virtual_destructor, protectedbase);
}
}
unrollOneVirtualMethod(classname, nn, parent, vm, virtual_destructor, protectedbase);
unrollOneVirtualMethod(classname, ni, parent, vm, virtual_destructor, protectedbase);
}
/*