diff --git a/CHANGES.current b/CHANGES.current index f1555953a..eb43f5720 100644 --- a/CHANGES.current +++ b/CHANGES.current @@ -1,5 +1,14 @@ Version 1.3.18 (In progress) ============================ +03/13/2003: mrose (Mark Rose) + Fixed a bug in the virtual method unrolling for directors. + The order of unrolling is now from base to derived, to ensure + that the most derived implementation of a director method is + found. + + Director methods for pure virtual methods now throw + DIRECTOR_PURE_VIRTUAL_EXCEPTION if _up is set. + 03/11/2003: beazley Fixed subtle bug in the application of SwigValueWrapper<> to template classes with default constructors. Reported by diff --git a/Examples/python/check.list b/Examples/python/check.list index f00dad1e2..fa651ae24 100644 --- a/Examples/python/check.list +++ b/Examples/python/check.list @@ -10,7 +10,6 @@ funcptr funcptr2 functor import -import template mpointer multimap diff --git a/Lib/python/director.swg b/Lib/python/director.swg index 5cca9dd5c..9f3e77192 100644 --- a/Lib/python/director.swg +++ b/Lib/python/director.swg @@ -35,6 +35,10 @@ public: /* any python exception that occurs during a director method call */ class SWIG_DIRECTOR_METHOD_EXCEPTION: public SWIG_DIRECTOR_EXCEPTION { }; +/* attempt to call a pure virtual method via a director method */ +class SWIG_DIRECTOR_PURE_VIRTUAL_EXCEPTION: public SWIG_DIRECTOR_EXCEPTION { }; + + /* simple thread abstraction for pthreads or win32 */ #ifdef __THREAD__ #define __PTHREAD__ diff --git a/Source/Modules/lang.cxx b/Source/Modules/lang.cxx index 3476bb79c..71988035d 100644 --- a/Source/Modules/lang.cxx +++ b/Source/Modules/lang.cxx @@ -1378,6 +1378,19 @@ int Language::unrollVirtualMethods(Node *n, if (Getattr(n, "feature:director")) default_director = 1; if (Getattr(n, "feature:nodirector")) default_director = -1; } + // recurse through all base classes to build the vtable + List* bl = Getattr(n, "bases"); + if (bl) { + Node* bi; + for (bi = Firstitem(bl); bi; bi = Nextitem(bl)) { + int virtual_base = 0; + unrollVirtualMethods(bi, parent, vm, default_director, virtual_destructor, virtual_base); + if (virtual_base) { + has_virtual = 1; + } + } + } + // find the methods that need directors classname = Getattr(n, "name"); for (ni = Getattr(n, "firstChild"); ni; ni = nextSibling(ni)) { nodeType = Getattr(ni, "nodeType"); @@ -1397,7 +1410,16 @@ int Language::unrollVirtualMethods(Node *n, if (Getattr(ni, "feature:director")) director = 1; if (Getattr(ni, "feature:nodirector")) director = 0; } - if ((director == 1) && !Getattr(vm, method_id)) { + // if this method has a director in a base class, we must + // either override it or remove it (otherwise the director + // method will use the wrong class for superclass calls) + if (Getattr(vm, method_id)) { + if (director == 0) director = 1; + else if (director < 0) { + Delattr(vm, method_id); + } + } + if (director == 1) { String *fqname = NewString(""); Printf(fqname, "%s::%s", classname, name); Hash *item = NewHash(); @@ -1419,17 +1441,6 @@ int Language::unrollVirtualMethods(Node *n, else { } } - List* bl = Getattr(n, "bases"); - if (bl) { - Node* bi; - for (bi = Firstitem(bl); bi; bi = Nextitem(bl)) { - int virtual_base = 0; - unrollVirtualMethods(bi, parent, vm, default_director, virtual_destructor, virtual_base); - if (virtual_base) { - has_virtual = 1; - } - } - } if (has_virtual) { Setattr(n, "hasVirtual", "1"); } diff --git a/Source/Modules/python.cxx b/Source/Modules/python.cxx index 0886ffbee..43a7ae5a2 100644 --- a/Source/Modules/python.cxx +++ b/Source/Modules/python.cxx @@ -1270,9 +1270,18 @@ public: String *tm; String *wrap_args; String *return_type; + String *value = Getattr(n, "value"); + String *storage = Getattr(n,"storage"); + bool pure_virtual = false; int status = SWIG_OK; int idx; + if (Cmp(storage,"virtual") == 0) { + if (Cmp(value,"0") == 0) { + pure_virtual = true; + } + } + classname = Getattr(parent, "sym:name"); type = Getattr(n, "type"); name = Getattr(n, "name"); @@ -1446,7 +1455,11 @@ public: /* direct call to superclass if _up is set */ Printf(w->code, "if (__get_up()) {\n"); - Printf(w->code, "return %s;\n", Swig_method_call(super,l)); + if (pure_virtual) { + Printf(w->code, "throw SWIG_DIRECTOR_PURE_VIRTUAL_EXCEPTION();\n"); + } else { + Printf(w->code, "return %s;\n", Swig_method_call(super,l)); + } Printf(w->code, "}\n"); /* check that have a wrapped Python object */