detecting polymorphic virtual methods properly
git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/trunk@5511 626c5289-ae23-0410-ae9c-e8d60b6d4f22
This commit is contained in:
parent
86edc68494
commit
8199b93d1d
6 changed files with 206 additions and 3 deletions
|
|
@ -1,5 +1,50 @@
|
||||||
Version 1.3.20 (In progress)
|
Version 1.3.20 (In progress)
|
||||||
============================
|
============================
|
||||||
|
12/08/2003: mmatus (Marcelo Matus)
|
||||||
|
The virtual method detections now properly
|
||||||
|
treats the following cases:
|
||||||
|
|
||||||
|
namespace foo { typedef int Int; }
|
||||||
|
struct A {};
|
||||||
|
typedef A B;
|
||||||
|
|
||||||
|
struct Foo {
|
||||||
|
virtual ~Foo() {}
|
||||||
|
|
||||||
|
virtual Foo* cloner() = 0;
|
||||||
|
virtual int get_value() = 0;
|
||||||
|
virtual A* get_class() = 0;
|
||||||
|
virtual void just_do_it() = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Bar : Foo
|
||||||
|
{
|
||||||
|
Bar* cloner();
|
||||||
|
foo::Int get_value();
|
||||||
|
B* get_class();
|
||||||
|
void just_do_it();
|
||||||
|
};
|
||||||
|
|
||||||
|
All the Foo and Bar methods are virtual. A new attribute
|
||||||
|
"virtual:type" record the base polymorphic type. In the
|
||||||
|
previous cases we have:
|
||||||
|
|
||||||
|
type : Bar virtual:type : Foo
|
||||||
|
type : foo::Int virtual:type : int
|
||||||
|
type : B virtual:type : A
|
||||||
|
type : void virtual:type : void
|
||||||
|
|
||||||
|
This attribute is useful in languages (java+directors)
|
||||||
|
that could have problems redefining Bar* Bar::cloner().
|
||||||
|
|
||||||
|
If you never had code like the above, you will see no
|
||||||
|
effects. But if you have some code like that, you
|
||||||
|
will see some effects since some methods that
|
||||||
|
before were not properly treated as virtual,
|
||||||
|
will start to act like that. This could enlarge
|
||||||
|
your director classes.
|
||||||
|
|
||||||
|
|
||||||
12/08/2003: mmatus (Marcelo Matus)
|
12/08/2003: mmatus (Marcelo Matus)
|
||||||
The director protected member support (dirprot)
|
The director protected member support (dirprot)
|
||||||
is disabled by default.
|
is disabled by default.
|
||||||
|
|
|
||||||
|
|
@ -111,6 +111,7 @@ CPP_TEST_CASES += \
|
||||||
director_abstract \
|
director_abstract \
|
||||||
director_basic \
|
director_basic \
|
||||||
director_exception \
|
director_exception \
|
||||||
|
director_detect \
|
||||||
director_finalizer \
|
director_finalizer \
|
||||||
director_unroll \
|
director_unroll \
|
||||||
director_wombat \
|
director_wombat \
|
||||||
|
|
|
||||||
65
SWIG/Examples/test-suite/director_detect.i
Normal file
65
SWIG/Examples/test-suite/director_detect.i
Normal file
|
|
@ -0,0 +1,65 @@
|
||||||
|
%module(directors="1") director_detect
|
||||||
|
|
||||||
|
%{
|
||||||
|
#include <string>
|
||||||
|
#include <iostream>
|
||||||
|
%}
|
||||||
|
|
||||||
|
%include "std_string.i"
|
||||||
|
|
||||||
|
%feature("director") Bar;
|
||||||
|
|
||||||
|
%newobject Foo::cloner();
|
||||||
|
%newobject Bar::cloner();
|
||||||
|
|
||||||
|
|
||||||
|
%inline {
|
||||||
|
namespace foo { typedef int Int; }
|
||||||
|
|
||||||
|
struct A
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef A B;
|
||||||
|
|
||||||
|
struct Foo {
|
||||||
|
virtual ~Foo() {}
|
||||||
|
virtual Foo* cloner() = 0;
|
||||||
|
virtual int get_value() = 0;
|
||||||
|
virtual A* get_class() = 0;
|
||||||
|
|
||||||
|
virtual void just_do_it() = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
class Bar : public Foo
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Foo* base()
|
||||||
|
{
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
Bar* cloner()
|
||||||
|
{
|
||||||
|
return new Bar();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
foo::Int get_value()
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
B* get_class()
|
||||||
|
{
|
||||||
|
return new B();
|
||||||
|
}
|
||||||
|
|
||||||
|
void just_do_it()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
36
SWIG/Examples/test-suite/python/director_detect_runme.py
Normal file
36
SWIG/Examples/test-suite/python/director_detect_runme.py
Normal file
|
|
@ -0,0 +1,36 @@
|
||||||
|
import director_detect
|
||||||
|
|
||||||
|
class MyBar(director_detect.Bar):
|
||||||
|
def __init__(self, val = 2):
|
||||||
|
director_detect.Bar.__init__(self)
|
||||||
|
self.val = val
|
||||||
|
|
||||||
|
def get_value(self):
|
||||||
|
self.val += 1
|
||||||
|
return self.val
|
||||||
|
|
||||||
|
def get_class(self):
|
||||||
|
self.val += 1
|
||||||
|
return director_detect.A()
|
||||||
|
|
||||||
|
def just_do_it(self):
|
||||||
|
self.val += 1
|
||||||
|
|
||||||
|
def clone(self):
|
||||||
|
return MyBar(self.val)
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
b = MyBar()
|
||||||
|
|
||||||
|
f = b.base()
|
||||||
|
|
||||||
|
v = f.get_value()
|
||||||
|
a = f.get_class()
|
||||||
|
f.just_do_it()
|
||||||
|
|
||||||
|
c = b.clone()
|
||||||
|
vc = c.get_value()
|
||||||
|
|
||||||
|
if (v != 3) or (b.val != 5) or (vc != 6):
|
||||||
|
raise RuntimeError,"Bad virtual detection"
|
||||||
43
SWIG/Examples/test-suite/ruby/director_detect_runme.rb
Normal file
43
SWIG/Examples/test-suite/ruby/director_detect_runme.rb
Normal file
|
|
@ -0,0 +1,43 @@
|
||||||
|
require 'director_detect'
|
||||||
|
|
||||||
|
class MyBar < Director_detect::Bar
|
||||||
|
def initialize(v)
|
||||||
|
@val = v
|
||||||
|
end
|
||||||
|
|
||||||
|
def get_value
|
||||||
|
@val = @val + 1
|
||||||
|
end
|
||||||
|
|
||||||
|
def get_class
|
||||||
|
@val = @val + 1
|
||||||
|
Director_detect::A
|
||||||
|
end
|
||||||
|
|
||||||
|
def just_do_it
|
||||||
|
@val = @val + 1
|
||||||
|
end
|
||||||
|
|
||||||
|
def clone
|
||||||
|
MyBar.new(@val)
|
||||||
|
end
|
||||||
|
|
||||||
|
def val
|
||||||
|
@val
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
b = MyBar.new(2)
|
||||||
|
|
||||||
|
f = b
|
||||||
|
|
||||||
|
v = f.get_value
|
||||||
|
a = f.get_class
|
||||||
|
f.just_do_it
|
||||||
|
|
||||||
|
c = b.clone
|
||||||
|
vc = c.get_value
|
||||||
|
|
||||||
|
raise RuntimeError if (v != 3) || (b.val != 5) || (vc != 6)
|
||||||
|
|
||||||
|
|
@ -68,6 +68,8 @@ class Allocate : public Dispatcher {
|
||||||
int function_is_defined_in_bases(Node *c, Node *bases) {
|
int function_is_defined_in_bases(Node *c, Node *bases) {
|
||||||
Node *b, *temp;
|
Node *b, *temp;
|
||||||
String *name, *type, *local_decl, *base_decl;
|
String *name, *type, *local_decl, *base_decl;
|
||||||
|
SwigType *base_type, *local_type;
|
||||||
|
|
||||||
if (!bases)
|
if (!bases)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
|
@ -79,6 +81,7 @@ class Allocate : public Dispatcher {
|
||||||
} else {
|
} else {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
local_type = SwigType_typedef_resolve_all(type);
|
||||||
|
|
||||||
/* Width first search */
|
/* Width first search */
|
||||||
for (int i = 0; i < Len(bases); i++) {
|
for (int i = 0; i < Len(bases); i++) {
|
||||||
|
|
@ -86,28 +89,38 @@ class Allocate : public Dispatcher {
|
||||||
temp = firstChild (b);
|
temp = firstChild (b);
|
||||||
while (temp) {
|
while (temp) {
|
||||||
base_decl = Getattr(temp, "decl");
|
base_decl = Getattr(temp, "decl");
|
||||||
if (base_decl) {
|
base_type = Getattr(temp, "type");
|
||||||
|
if (base_decl && base_type) {
|
||||||
base_decl = SwigType_typedef_resolve_all(base_decl);
|
base_decl = SwigType_typedef_resolve_all(base_decl);
|
||||||
|
base_type = SwigType_typedef_resolve_all(base_type);
|
||||||
|
|
||||||
if ( (checkAttribute(temp, "storage", "virtual")) &&
|
if ( (checkAttribute(temp, "storage", "virtual")) &&
|
||||||
(checkAttribute(temp, "name", name)) &&
|
(checkAttribute(temp, "name", name)) &&
|
||||||
(checkAttribute(temp, "type", type)) &&
|
(!Strcmp(local_type, base_type)
|
||||||
|
|| SwigType_issubtype(local_type, base_type)) &&
|
||||||
(!Strcmp(local_decl, base_decl)) ) {
|
(!Strcmp(local_decl, base_decl)) ) {
|
||||||
// Indicate a virtual method in the derived class, that is, not the virtual method definition in a base class
|
// Indicate a virtual method in the derived class, that is, not the virtual method definition in a base class
|
||||||
Setattr(c, "storage", "virtual");
|
Setattr(c, "storage", "virtual");
|
||||||
Setattr(c, "virtual:derived", "1");
|
Setattr(c, "virtual:derived", "1");
|
||||||
if (virtual_elimination_mode)
|
// record the virtual base type in case some language needs it
|
||||||
|
Setattr(c, "virtual:type", Getattr(temp, "type"));
|
||||||
|
if (virtual_elimination_mode && !Strcmp(local_type, base_type))
|
||||||
Setattr(c, "feature:ignore", "1");
|
Setattr(c, "feature:ignore", "1");
|
||||||
|
|
||||||
Delete(base_decl);
|
Delete(base_decl);
|
||||||
|
Delete(base_type);
|
||||||
Delete(local_decl);
|
Delete(local_decl);
|
||||||
|
Delete(local_type);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
Delete(base_decl);
|
Delete(base_decl);
|
||||||
|
Delete(base_type);
|
||||||
}
|
}
|
||||||
temp = nextSibling(temp);
|
temp = nextSibling(temp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Delete(local_decl);
|
Delete(local_decl);
|
||||||
|
Delete(local_type);
|
||||||
for (int j = 0; j < Len(bases); j++) {
|
for (int j = 0; j < Len(bases); j++) {
|
||||||
b = Getitem(bases,j);
|
b = Getitem(bases,j);
|
||||||
if (function_is_defined_in_bases(c, Getattr(b, "bases")))
|
if (function_is_defined_in_bases(c, Getattr(b, "bases")))
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue