From 892caec201744b4af004ecaa5db18a60c3dbc2dc Mon Sep 17 00:00:00 2001 From: David Nadlinger Date: Sat, 8 Jan 2011 21:05:49 +0000 Subject: [PATCH] [D] Fixed a bug in the loop breaking code for directors leading to a superclass implementation erroneously being called. The situation in which this would previously happen is illustrated in the new "director_alternating" test case. Currently broken for C# and Java. Thanks to Jimmy Cao for reporting this. git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/trunk@12380 626c5289-ae23-0410-ae9c-e8d60b6d4f22 --- Examples/test-suite/common.mk | 1 + .../d/director_alternating_runme.2.d | 7 ++++ Examples/test-suite/director_alternating.i | 36 +++++++++++++++++++ .../test-suite/director_alternating_runme.1.d | 7 ++++ .../python/director_alternating_runme.py | 5 +++ Source/Modules/d.cxx | 17 ++++++--- 6 files changed, 69 insertions(+), 4 deletions(-) create mode 100644 Examples/test-suite/d/director_alternating_runme.2.d create mode 100644 Examples/test-suite/director_alternating.i create mode 100644 Examples/test-suite/director_alternating_runme.1.d create mode 100644 Examples/test-suite/python/director_alternating_runme.py diff --git a/Examples/test-suite/common.mk b/Examples/test-suite/common.mk index f25238382..d2b9bc254 100644 --- a/Examples/test-suite/common.mk +++ b/Examples/test-suite/common.mk @@ -154,6 +154,7 @@ CPP_TEST_CASES += \ derived_nested \ destructor_reprotected \ director_abstract \ + director_alternating \ director_basic \ director_classes \ director_classic \ diff --git a/Examples/test-suite/d/director_alternating_runme.2.d b/Examples/test-suite/d/director_alternating_runme.2.d new file mode 100644 index 000000000..27bd262fd --- /dev/null +++ b/Examples/test-suite/d/director_alternating_runme.2.d @@ -0,0 +1,7 @@ +module director_alternating_runme; + +import director_alternating.director_alternating; + +void main() { + assert(getBar().id() == idFromGetBar()); +} diff --git a/Examples/test-suite/director_alternating.i b/Examples/test-suite/director_alternating.i new file mode 100644 index 000000000..6e3ef4f24 --- /dev/null +++ b/Examples/test-suite/director_alternating.i @@ -0,0 +1,36 @@ +// Checks if calls to a method being defined in the base class, not +// overridden in the subclass, but again overridden in a class derived from +// the first subclass are dispatched correctly. +%module(directors="1") director_alternating; + +%feature("director") Foo; + +%inline %{ +struct Foo { + virtual ~Foo() {} + virtual int id() { + return 0; + } +}; + +struct Bar : Foo {}; + +struct Baz : Bar { + virtual int id() { + return 2; + } +}; + +// Note that even though the return value is of type Bar*, it really points to +// an instance of Baz (in which id() has been overridden). +Bar *getBar() { + static Baz baz; + return &baz; +} + +// idFromGetBar() obviously is equivalent to getBar()->id() in C++ – this +// should be true from the target language as well. +int idFromGetBar() { + return getBar()->id(); +} +%} diff --git a/Examples/test-suite/director_alternating_runme.1.d b/Examples/test-suite/director_alternating_runme.1.d new file mode 100644 index 000000000..27bd262fd --- /dev/null +++ b/Examples/test-suite/director_alternating_runme.1.d @@ -0,0 +1,7 @@ +module director_alternating_runme; + +import director_alternating.director_alternating; + +void main() { + assert(getBar().id() == idFromGetBar()); +} diff --git a/Examples/test-suite/python/director_alternating_runme.py b/Examples/test-suite/python/director_alternating_runme.py new file mode 100644 index 000000000..a92ae1c5c --- /dev/null +++ b/Examples/test-suite/python/director_alternating_runme.py @@ -0,0 +1,5 @@ +from director_alternating import * + +id = getBar().id() +if id != idFromGetBar(): + raise RuntimeError, "Got wrong id: " + str(id) diff --git a/Source/Modules/d.cxx b/Source/Modules/d.cxx index 4fdc25fac..9937452a9 100644 --- a/Source/Modules/d.cxx +++ b/Source/Modules/d.cxx @@ -2630,6 +2630,8 @@ private: if (!static_flag) { Printf(imcall, "cast(void*)swigCPtr"); } + + String *proxy_param_types = NewString(""); // Write the parameter list for the proxy function declaration and the // wrapper function call. @@ -2704,10 +2706,13 @@ private: "No dtype typemap defined for %s\n", SwigType_str(pt, 0)); } - if (gencomma >= 2) + if (gencomma >= 2) { Printf(function_code, ", "); + Printf(proxy_param_types, ", "); + } gencomma = 2; Printf(function_code, "%s %s", proxy_type, param_name); + Append(proxy_param_types, proxy_type); Delete(proxy_type); } @@ -2772,9 +2777,11 @@ private: String *excode = NewString(""); if (!Cmp(return_type, "void")) - Printf(excode, "if (this.classinfo == %s.classinfo) %s; else %s", proxy_class_name, imcall, ex_imcall); + Printf(excode, "if (swigIsMethodOverridden!(%s delegate(%s), %s function(%s), %s)()) %s; else %s", + return_type, proxy_param_types, return_type, proxy_param_types, proxy_function_name, ex_imcall, imcall); else - Printf(excode, "((this.classinfo == %s.classinfo) ? %s : %s)", proxy_class_name, imcall, ex_imcall); + Printf(excode, "((swigIsMethodOverridden!(%s delegate(%s), %s function(%s), %s)()) ? %s : %s)", + return_type, proxy_param_types, return_type, proxy_param_types, proxy_function_name, ex_imcall, imcall); Clear(imcall); Printv(imcall, excode, NIL); @@ -2788,6 +2795,8 @@ private: Swig_warning(WARN_D_TYPEMAP_DOUT_UNDEF, input_file, line_number, "No dout typemap defined for %s\n", SwigType_str(t, 0)); } + + Delete(proxy_param_types); // The whole function body is now in stored tm (if there was a matching type // map, of course), so simply append it to the code buffer. The braces are @@ -3418,7 +3427,7 @@ private: // Only emit it if the proxy class has at least one method. if (first_class_dmethod < curr_class_dmethod) { Printf(proxy_class_body_code, "\n"); - Printf(proxy_class_body_code, "private bool swigIsMethodOverridden(DelegateType, FunctionType, alias fn)() {\n"); + Printf(proxy_class_body_code, "private bool swigIsMethodOverridden(DelegateType, FunctionType, alias fn)() %s{\n", (d_version > 1) ? "const " : ""); Printf(proxy_class_body_code, " DelegateType dg = &fn;\n"); Printf(proxy_class_body_code, " return dg.funcptr != SwigNonVirtualAddressOf!(FunctionType, fn);\n"); Printf(proxy_class_body_code, "}\n");