Fix directors and allprotected mode and using declarations.

Fixes recently introduced seg fault, but this has never worked properly.

Closes #2616
This commit is contained in:
William S Fulton 2023-06-24 11:43:15 +01:00
parent 808066fc1e
commit 49e60c7d56
7 changed files with 94 additions and 7 deletions

View File

@ -7,6 +7,11 @@ the issue number to the end of the URL: https://github.com/swig/swig/issues/
Version 4.2.0 (in progress)
===========================
2023-06-24: wsfulton
#2616 Fix directors and allprotected mode and using declarations.
Previously SWIG either seg faulted or generated code that did not
compile.
2023-06-20: olly
#2486 Fix handling of template in array size, which was being
rejected by SWIG because the type string contains '<' not followed

View File

@ -85,3 +85,34 @@ public:
};
%}
%ignore AllProtectedTop;
%feature("director") AllProtectedBottom;
%inline %{
class AllProtectedTop {
public:
virtual ~AllProtectedTop() {}
void doSomething(int row) {}
void doSomething() {}
void usingOverloaded(int row) {}
void usingOverloaded() {}
void usingSingle() {}
void private1() {}
void private2() {}
void private2(int) {}
};
class AllProtectedBottom : public AllProtectedTop {
public:
virtual void apb() {}
protected:
// allprotected makes the following public in the director class
using AllProtectedTop::usingOverloaded;
using AllProtectedTop::usingSingle;
void doSomething(int row) {}
void doSomething() {}
private:
using AllProtectedTop::private1;
using AllProtectedTop::private2;
};
%}

View File

@ -27,6 +27,9 @@ public class runme
ProtectedBase pb = new ProtectedDerived("ProtectedDerived");
// ProtectedDerived's destructor should be called via the Dispose(disposing) virtual call
pb.Dispose();
MyAllProtectedBottom mapb = new MyAllProtectedBottom();
mapb.callProtectedMethods();
}
}
@ -83,3 +86,14 @@ class MyProtectedBase : ProtectedBase
throw new Exception("Failed");
}
}
class MyAllProtectedBottom : AllProtectedBottom
{
public void callProtectedMethods() {
usingOverloaded();
usingOverloaded(99);
usingSingle();
doSomething();
doSomething(99);
}
}

View File

@ -2,12 +2,16 @@ module allprotected_runme;
import allprotected.Klass;
import allprotected.ProtectedBase;
import allprotected.AllProtectedBottom;
import std.conv : text;
import std.exception : enforce;
void main() {
auto mpb = new MyProtectedBase("MyProtectedBase");
mpb.accessProtected();
MyAllProtectedBottom mapb = new MyAllProtectedBottom();
mapb.callProtectedMethods();
}
class MyProtectedBase : ProtectedBase {
@ -61,3 +65,15 @@ public:
enforce(ae == ProtectedBase.AnEnum.EnumVal1);
}
}
class MyAllProtectedBottom : AllProtectedBottom
{
public:
void callProtectedMethods() {
usingOverloaded();
usingOverloaded(99);
usingSingle();
doSomething();
doSomething(99);
}
}

View File

@ -14,6 +14,9 @@ public class allprotected_runme {
{
MyProtectedBase mpb = new MyProtectedBase("MyProtectedBase");
mpb.accessProtected();
MyAllProtectedBottom mapb = new MyAllProtectedBottom();
mapb.callProtectedMethods();
}
}
@ -72,3 +75,13 @@ class MyProtectedBase extends ProtectedBase
}
}
class MyAllProtectedBottom extends AllProtectedBottom
{
void callProtectedMethods() {
usingOverloaded();
usingOverloaded(99);
usingSingle();
doSomething();
doSomething(99);
}
}

View File

@ -2195,7 +2195,7 @@ int Language::classDirector(Node *n) {
Node *ni;
String *using_protected_members_code = NewString("");
for (ni = Getattr(n, "firstChild"); ni; ni = nextSibling(ni)) {
Node *nodeType = Getattr(ni, "nodeType");
Node *nodeType = nodeType(ni);
if (Cmp(nodeType, "destructor") == 0 && GetFlag(ni, "final")) {
String *classtype = Getattr(n, "classtype");
SWIG_WARN_NODE_BEGIN(ni);
@ -2206,13 +2206,18 @@ int Language::classDirector(Node *n) {
Delete(using_protected_members_code);
return SWIG_OK;
}
bool cdeclaration = (Cmp(nodeType, "cdecl") == 0);
if (cdeclaration && !GetFlag(ni, "feature:ignore")) {
if (isNonVirtualProtectedAccess(ni)) {
Node *overloaded = Getattr(ni, "sym:overloaded");
Node *nn = ni;
bool cdeclaration = Equal(nodeType, "cdecl");
if (!cdeclaration && Equal(nodeType, "using")) {
nn = Getattr(ni, "firstChild");
cdeclaration = nn && Equal(nodeType(nn), "cdecl") ? true : false;
}
if (cdeclaration && !GetFlag(nn, "feature:ignore")) {
if (isNonVirtualProtectedAccess(nn)) {
Node *overloaded = Getattr(nn, "sym:overloaded");
// emit the using base::member statement (but only once if the method is overloaded)
if (!overloaded || (overloaded && (overloaded == ni)))
Printf(using_protected_members_code, " using %s::%s;\n", SwigType_namestr(ClassName), Getattr(ni, "name"));
if (!overloaded || (overloaded && (overloaded == nn)))
Printf(using_protected_members_code, " using %s::%s;\n", SwigType_namestr(ClassName), Getattr(nn, "name"));
}
}
}

View File

@ -1081,6 +1081,9 @@ class TypePass:private Dispatcher {
Symtab *st = Getattr(n, "sym:symtab");
assert(st);
Setattr(nn, "sym:symtab", st);
// The real parent is the "using" declaration node, but subsequent code generally handles
// and expects a class member to point to the parent class node
Setattr(nn, "parentNode", parentNode(n));
if (!GetFlag(nn, "feature:ignore")) {
ParmList *parms = CopyParmList(Getattr(c, "parms"));