detecting polymorphic virtual methods properly

git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/trunk/SWIG@5511 626c5289-ae23-0410-ae9c-e8d60b6d4f22
This commit is contained in:
Marcelo Matus 2003-12-09 10:36:15 +00:00
commit 833b2f7f0a
6 changed files with 206 additions and 3 deletions

View file

@ -1,5 +1,50 @@
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)
The director protected member support (dirprot)
is disabled by default.

View file

@ -111,6 +111,7 @@ CPP_TEST_CASES += \
director_abstract \
director_basic \
director_exception \
director_detect \
director_finalizer \
director_unroll \
director_wombat \

View 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()
{
}
};
}

View 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"

View 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)

View file

@ -68,6 +68,8 @@ class Allocate : public Dispatcher {
int function_is_defined_in_bases(Node *c, Node *bases) {
Node *b, *temp;
String *name, *type, *local_decl, *base_decl;
SwigType *base_type, *local_type;
if (!bases)
return 0;
@ -79,6 +81,7 @@ class Allocate : public Dispatcher {
} else {
return 0;
}
local_type = SwigType_typedef_resolve_all(type);
/* Width first search */
for (int i = 0; i < Len(bases); i++) {
@ -86,28 +89,38 @@ class Allocate : public Dispatcher {
temp = firstChild (b);
while (temp) {
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_type = SwigType_typedef_resolve_all(base_type);
if ( (checkAttribute(temp, "storage", "virtual")) &&
(checkAttribute(temp, "name", name)) &&
(checkAttribute(temp, "type", type)) &&
(!Strcmp(local_type, base_type)
|| SwigType_issubtype(local_type, base_type)) &&
(!Strcmp(local_decl, base_decl)) ) {
// 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, "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");
Delete(base_decl);
Delete(base_type);
Delete(local_decl);
Delete(local_type);
return 1;
}
Delete(base_decl);
Delete(base_type);
}
temp = nextSibling(temp);
}
}
Delete(local_decl);
Delete(local_type);
for (int j = 0; j < Len(bases); j++) {
b = Getitem(bases,j);
if (function_is_defined_in_bases(c, Getattr(b, "bases")))