diff --git a/CHANGES.current b/CHANGES.current index d7f25ae92..c3cb5f951 100644 --- a/CHANGES.current +++ b/CHANGES.current @@ -7,6 +7,11 @@ the issue number to the end of the URL: https://github.com/swig/swig/issues/ Version 4.1.0 (in progress) =========================== +2022-02-17: olly + [PHP] https://sourceforge.net/p/swig/bugs/1211/ + Fix to call cleanup code in exception situations and not to invoke + the freearg typemap twice in certain situations. + 2022-02-15: olly #300 #368 Improve parser handling of % followed immediately by an identifier. If it's not a recognised directive the scanner diff --git a/Examples/test-suite/common.mk b/Examples/test-suite/common.mk index 25ca2d512..6f9fd4a2f 100644 --- a/Examples/test-suite/common.mk +++ b/Examples/test-suite/common.mk @@ -234,6 +234,7 @@ CPP_TEST_CASES += \ evil_diamond_ns \ evil_diamond_prop \ exception_classname \ + exception_memory_leak \ exception_order \ extend \ extend_constructor_destructor \ diff --git a/Examples/test-suite/r_memory_leak.i b/Examples/test-suite/exception_memory_leak.i similarity index 68% rename from Examples/test-suite/r_memory_leak.i rename to Examples/test-suite/exception_memory_leak.i index a240097e3..835c936fc 100644 --- a/Examples/test-suite/r_memory_leak.i +++ b/Examples/test-suite/exception_memory_leak.i @@ -1,4 +1,4 @@ -%module r_memory_leak +%module exception_memory_leak %include @@ -8,33 +8,38 @@ } %typemap(freearg) Foo* foo { - printf(" \" Object deleted\"\n"); + Foo::inc_freearg_count(); delete $1; } %typemap(out) Foo* verify_no_memory_leak { if ($1 == NULL) SWIG_exception_fail(SWIG_RuntimeError, "Let's see how the bindings manage this exception!"); + $1 = NULL; } -%typemap(scoerceout) Foo* - %{ if (!is.null($result) && !is.logical($result)) {$result <- new("$R_class", ref=$result) ;}; %} %inline %{ #include class Foo { static unsigned count; + static unsigned freearg_count; public: Foo() { ++count; } ~Foo() { --count; } static unsigned get_count() { return count; } + static unsigned get_freearg_count() { return freearg_count; } +#ifndef SWIG + static void inc_freearg_count() { ++freearg_count; } +#endif }; unsigned Foo::count = 0; + unsigned Foo::freearg_count = 0; static Foo* trigger_internal_swig_exception(const std::string& message, Foo* foo) { return (message == "null") ? NULL : foo; - }; + } %} diff --git a/Examples/test-suite/php/exception_memory_leak_runme.php b/Examples/test-suite/php/exception_memory_leak_runme.php new file mode 100644 index 000000000..6ff035cde --- /dev/null +++ b/Examples/test-suite/php/exception_memory_leak_runme.php @@ -0,0 +1,23 @@ +code, "\tWRONG_PARAM_COUNT;\n}\n\n"); Printf(f->code, " if(!arg) {\n"); Printf(f->code, " zend_throw_exception(zend_ce_type_error, \"this pointer is NULL\", 0);\n"); + Printf(f->code, " return;\n"); Printf(f->code, " }\n"); Printf(f->code, " arg2 = Z_STR(args[0]);\n\n"); @@ -1405,7 +1406,7 @@ public: Printv(f->code, outarg, NIL); } - if (cleanup) { + if (static_setter && cleanup) { Printv(f->code, cleanup, NIL); } @@ -1698,8 +1699,10 @@ public: "#ifndef SWIG_PHP_INTERFACE_", interface, "_CE\n", " {\n", " zend_class_entry *swig_interface_ce = zend_lookup_class(zend_string_init(\"", interface, "\", sizeof(\"", interface, "\") - 1, 0));\n", - " if (!swig_interface_ce) zend_throw_exception(zend_ce_error, \"Interface \\\"", interface, "\\\" not found\", 0);\n", - " zend_do_implement_interface(SWIG_Php_ce_", class_name, ", swig_interface_ce);\n", + " if (swig_interface_ce)\n", + " zend_do_implement_interface(SWIG_Php_ce_", class_name, ", swig_interface_ce);\n", + " else\n", + " zend_throw_exception(zend_ce_error, \"Interface \\\"", interface, "\\\" not found\", 0);\n", " }\n", "#endif\n", NIL);