From ec965840ce3fa59a9f09e9d09fefacaa617b54d5 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Sat, 20 Aug 2022 15:23:15 +0100 Subject: [PATCH 01/16] Cosmetic stray semi-colon removal after %typemap --- CHANGES | 4 ++-- Doc/Manual/Typemaps.html | 20 ++++++++++---------- Lib/java/java.swg | 2 +- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/CHANGES b/CHANGES index 05834910a..89bcac60c 100644 --- a/CHANGES +++ b/CHANGES @@ -19614,8 +19614,8 @@ Version 1.3.12 (June 2, 2002) typemap must exactly match up with the "in" or "ignore" typemap. For example: - %typemap(in) (char *data, int len) { ... }; - %typemap(freearg) char *data { ... }; + %typemap(in) (char *data, int len) { ... } + %typemap(freearg) char *data { ... } void foo(char *data, int len); diff --git a/Doc/Manual/Typemaps.html b/Doc/Manual/Typemaps.html index 24a68b1ba..8a4f830b9 100644 --- a/Doc/Manual/Typemaps.html +++ b/Doc/Manual/Typemaps.html @@ -1382,16 +1382,16 @@ Below is a list of the typical default types supplied by language modules, showi
-%typemap(in) SWIGTYPE &            { ... default reference handling ...                       };
-%typemap(in) SWIGTYPE *            { ... default pointer handling ...                         };
-%typemap(in) SWIGTYPE *const       { ... default pointer const handling ...                   };
-%typemap(in) SWIGTYPE *const&      { ... default pointer const reference handling ...         };
-%typemap(in) SWIGTYPE[ANY]         { ... 1D fixed size arrays handling ...                    };
-%typemap(in) SWIGTYPE []           { ... unknown sized array handling ...                     };
-%typemap(in) enum SWIGTYPE         { ... default handling for enum values ...                 };
-%typemap(in) const enum SWIGTYPE & { ... default handling for const enum reference values ... };
-%typemap(in) SWIGTYPE (CLASS::*)   { ... default pointer member handling ...                  };
-%typemap(in) SWIGTYPE              { ... simple default handling ...                          };
+%typemap(in) SWIGTYPE &            { ... default reference handling ...                       }
+%typemap(in) SWIGTYPE *            { ... default pointer handling ...                         }
+%typemap(in) SWIGTYPE *const       { ... default pointer const handling ...                   }
+%typemap(in) SWIGTYPE *const&      { ... default pointer const reference handling ...         }
+%typemap(in) SWIGTYPE[ANY]         { ... 1D fixed size arrays handling ...                    }
+%typemap(in) SWIGTYPE []           { ... unknown sized array handling ...                     }
+%typemap(in) enum SWIGTYPE         { ... default handling for enum values ...                 }
+%typemap(in) const enum SWIGTYPE & { ... default handling for const enum reference values ... }
+%typemap(in) SWIGTYPE (CLASS::*)   { ... default pointer member handling ...                  }
+%typemap(in) SWIGTYPE              { ... simple default handling ...                          }
 
diff --git a/Lib/java/java.swg b/Lib/java/java.swg index 19198b7b4..4e65e7c17 100644 --- a/Lib/java/java.swg +++ b/Lib/java/java.swg @@ -700,7 +700,7 @@ Swig::LocalRefGuard $1_refguard(jenv, $input); } SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "$1_type reference is null"); return $null; } %} -%typemap(freearg) SWIGTYPE && %{ delete $1; %}; +%typemap(freearg) SWIGTYPE && %{ delete $1; %} %typemap(out) SWIGTYPE * %{ *($&1_ltype)&$result = $1; %} %typemap(out, fragment="SWIG_PackData", noblock=1) SWIGTYPE (CLASS::*) { From c10a84c77597695e3bdba37f35d251cb826d1d72 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Sat, 20 Aug 2022 22:14:58 +0100 Subject: [PATCH 02/16] Cosmetic stray semi-colon removal after %typemap using quotes --- CHANGES | 40 ++++--- Doc/Manual/Customization.html | 2 +- Doc/Manual/D.html | 2 +- Doc/Manual/Doxygen.html | 2 +- Doc/Manual/Java.html | 10 +- Doc/Manual/Lisp.html | 2 +- Doc/Manual/Php.html | 2 +- Doc/Manual/Ruby.html | 2 +- Doc/Manual/Typemaps.html | 18 +-- Examples/go/goin/example.i | 4 +- Examples/perl5/multimap/example.i | 2 +- Examples/tcl/multimap/example.i | 2 +- Examples/test-suite/autodoc.i | 8 +- Examples/test-suite/default_args.i | 2 +- Examples/test-suite/fragments.i | 2 +- Examples/test-suite/go_director_inout.i | 4 +- Examples/test-suite/ignore_parameter.i | 8 +- .../java_director_exception_feature.i | 2 +- .../java_director_exception_feature_nspace.i | 2 +- Examples/test-suite/java_throws.i | 2 +- Examples/test-suite/java_typemaps_proxy.i | 14 +-- .../test-suite/java_typemaps_typewrapper.i | 8 +- Examples/test-suite/minherit2.i | 20 ++-- Examples/test-suite/overload_extend.i | 2 +- Examples/test-suite/overload_extend2.i | 2 +- Examples/test-suite/php_iterator.i | 2 +- Examples/test-suite/python_flatstaticmethod.i | 4 +- Examples/test-suite/ruby_manual_proxy.i | 2 +- Examples/test-suite/template_whitespace.i | 6 +- Examples/test-suite/typemap_variables.i | 12 +- Lib/cffi/cffi.swg | 110 +++++++++--------- Lib/csharp/std_array.i | 2 +- Lib/csharp/std_list.i | 2 +- Lib/csharp/std_map.i | 2 +- Lib/csharp/std_set.i | 2 +- Lib/csharp/std_vector.i | 2 +- Lib/guile/typemaps.i | 12 +- Lib/lua/luatypemaps.swg | 2 +- Lib/mzscheme/typemaps.i | 10 +- Lib/ocaml/ocaml.swg | 6 +- Lib/php/const.i | 4 +- Lib/php/php.swg | 2 +- Lib/php/std_string.i | 2 +- Lib/php/typemaps.i | 12 +- Lib/python/pyclasses.swg | 2 +- Lib/python/pydocs.swg | 44 +++---- Lib/python/pytypemaps.swg | 2 +- Lib/r/r.swg | 2 +- Lib/r/rtype.swg | 40 +++---- Lib/r/std_vector.i | 14 +-- Lib/ruby/typemaps.i | 4 +- Lib/swig.swg | 4 +- Lib/typemaps/cstrings.swg | 12 +- Lib/typemaps/ptrtypes.swg | 2 +- Lib/typemaps/strings.swg | 4 +- Lib/typemaps/swigobject.swg | 6 +- Lib/typemaps/swigtype.swg | 10 +- Lib/typemaps/valtypes.swg | 4 +- Lib/typemaps/void.swg | 4 +- 59 files changed, 258 insertions(+), 256 deletions(-) diff --git a/CHANGES b/CHANGES index 89bcac60c..3ddd94d2b 100644 --- a/CHANGES +++ b/CHANGES @@ -3137,7 +3137,7 @@ Version 3.0.3 (30 Dec 2014) 2014-09-12: olly [PHP] Add support for specifying any PHP interfaces a wrapped class - implements, e.g.: %typemap("phpinterfaces") MyIterator "Iterator"; + implements, e.g.: %typemap("phpinterfaces") MyIterator "Iterator" 2014-09-11: olly [PHP] Fix throwing a PHP exception through C++ from a subclassed @@ -8396,8 +8396,8 @@ Version 1.3.30 (November 13, 2006) javabase/csbase typemap, eg in the following, 'Me' will be the base class, no matter what Foo is really derived from in the C++ layer. - %typemap(javabase, replace="1") Foo "Me"; - %typemap(csbase, replace="1") Foo "Me"; + %typemap(javabase, replace="1") Foo "Me" + %typemap(csbase, replace="1") Foo "Me" Previously it was not possible for the javabase/csbase typemaps to override the C++ base. @@ -9884,7 +9884,7 @@ Version 1.3.28 (February 12, 2006) solutions is to write: %typemap(in) A * {...} - %typemap(freeag) A * ""; + %typemap(freeag) A * "" overload 'freearg' with an empty definition. @@ -11314,20 +11314,20 @@ Version 1.3.27 (October 15, 2005) then the typemap will be inserted without the block imposed by the brackets, similar to - %typemap(in) Hello "..."; + %typemap(in) Hello "..." So, why you don't just use the quote style?, because: 1.- The quote style doesn't get preprocessed, for example - %typemap(in) Hello "$1= SWIG_macro($1);"; + %typemap(in) Hello "$1= SWIG_macro($1);" here, SWIG_macro doesn't get expanded 2.- Inside a quote typemap, you have to use quotes carefully - %typemap(in) Hello "$1 = \"hello\" "; + %typemap(in) Hello "$1 = \"hello\" " 3.- You can't make emacs and/or other editors to indent inside a string!. @@ -11529,7 +11529,7 @@ Version 1.3.26 (October 9, 2005) %define hello(name, Type) %define name ## a(Type) - %typemap(in) Type "hello;"; + %typemap(in) Type "hello;" %enddef %enddef @@ -13525,7 +13525,7 @@ Version 1.3.23 (November 11, 2004) whereupon the default of 0 was used. You can get the same behaviour for C code by using the "default" typemap: - %typemap(default) int val "$1 = 0;"; + %typemap(default) int val "$1 = 0;" %{ void foo(int val); %} @@ -13854,9 +13854,11 @@ Version 1.3.22 (September 4, 2004) specifiers from the C type. This makes it possible, for instance, to control whether a C "char" argument takes a Lisp character or a Lisp integer value. The default (taking Lisp characters) is done by these built-in typemaps: - %typemap(ffitype) char ":char"; %typemap(lisptype) char "character"; + %typemap(ffitype) char ":char" + %typemap(lisptype) char "character" If char means an integer instead, use these typemaps: - %typemap(ffitype) char ":char"; %typemap(lisptype) char "integer"; + %typemap(ffitype) char ":char" + %typemap(lisptype) char "integer" 08/22/2004: wsfulton As discussed in bug #772453, the SWIG library directory is now installed @@ -18874,9 +18876,9 @@ Version 1.3.14 (August 12, 2002) shadowinterface Note that it is possible to target a particular proxy class: - %typemap(javaimports) Foo "import java.util.*"; + %typemap(javaimports) Foo "import java.util.*" or a particular type wrapper class: - %typemap(javaimports) double* "import java.math.*"; + %typemap(javaimports) double* "import java.math.*" Note that $javaclassname in these typemaps are substituted with either the proxy classname when using proxy classes or the SWIGTYPE class name. @@ -21071,7 +21073,7 @@ Version 1.3.11 (January 31, 2002) Second, a typemap can force a no-match by defining - %typemap(in) sometype "pass"; + %typemap(in) sometype "pass" If this is used, the typemap system will *not* record a typemap match for "sometype". This can be used to block @@ -21079,7 +21081,7 @@ Version 1.3.11 (January 31, 2002) a typemap feature for some type, you could do this. // Do not allow global variables of type 'const char *' to be set. - %typemap(varin) const char * "pass"; + %typemap(varin) const char * "pass" It might also be possible to use this to do subtle and strange things with typemaps. For example, if you wanted to @@ -21093,8 +21095,8 @@ Version 1.3.11 (January 31, 2002) ... return a value ... } /* Block unqualified typemaps defined above */ - %typemap(ignore) const blah * "pass"; - %typemap(argout) const blah * "pass"; + %typemap(ignore) const blah * "pass" + %typemap(argout) const blah * "pass" %typemap(in) const blah * { ... get input value ... } @@ -21871,7 +21873,7 @@ Version 1.3.10 (December 10, 2001) %typemap directive can now accept nearly arbitrary keyword parameters. For example: - %typemap(in,parse="i",doc="integer") int "..."; + %typemap(in,parse="i",doc="integer") int "..." The purpose of the keyword parameters is to supply code generation hints to the target language module. The intepretation of the @@ -23949,7 +23951,7 @@ Version 1.3 Alpha 4 (September 4, 2000) Typemaps can now be specified using string literals like this: - %typemap(in) int "$target = SvIV($source);"; + %typemap(in) int "$target = SvIV($source);" When code is specified like this, it is *NOT* enclosed inside a local scope (as with older typemap declarations). diff --git a/Doc/Manual/Customization.html b/Doc/Manual/Customization.html index 5fe0f5b52..aab3528ac 100644 --- a/Doc/Manual/Customization.html +++ b/Doc/Manual/Customization.html @@ -668,7 +668,7 @@ results. For example:
-%typemap(newfree) char * "free($1);";
+%typemap(newfree) char * "free($1);"
 ...
 %newobject strdup;
 ...
diff --git a/Doc/Manual/D.html b/Doc/Manual/D.html
index 99ee027a1..9e733c401 100644
--- a/Doc/Manual/D.html
+++ b/Doc/Manual/D.html
@@ -278,7 +278,7 @@ Like, $imcall, this special variable is only expanded in the "dout" typemap.
     

This macro is used in the dimports typemap if a dependency on another D type generated by SWIG is added by a custom typemap.

Consider the following code snippet:

-%typemap(dinterfaces) SomeClass "AnInterface, AnotherInterface";
+%typemap(dinterfaces) SomeClass "AnInterface, AnotherInterface"
 

This causes SWIG to add AnInterface and AnotherInterface to the base class list of SomeClass:

diff --git a/Doc/Manual/Doxygen.html b/Doc/Manual/Doxygen.html
index 5b2f7cac6..9d2cc7724 100644
--- a/Doc/Manual/Doxygen.html
+++ b/Doc/Manual/Doxygen.html
@@ -1114,7 +1114,7 @@ name of the type with namespace scope delimiters (::) replaced with a d
 change this, you can define your own typemaps for the custom types, e.g:
 

-%typemap(doctype) MyDate "datetime.date";
+%typemap(doctype) MyDate "datetime.date"
 

diff --git a/Doc/Manual/Java.html b/Doc/Manual/Java.html index 6f1785256..d15ef2f0b 100644 --- a/Doc/Manual/Java.html +++ b/Doc/Manual/Java.html @@ -4218,7 +4218,7 @@ You can copy the code below into an interface file and run SWIG on it and examin %} // Expose C++ exception as a Java Exception by changing the Java base class and providing a getMessage() -%typemap(javabase) MyNS::MyException "java.lang.RuntimeException"; +%typemap(javabase) MyNS::MyException "java.lang.RuntimeException" %rename(getMessage) MyNS::MyException::whatsup; %inline %{ @@ -7065,7 +7065,7 @@ The corrected interface file looks like:

 // class Foo is handled in a different interface file:
 %import "Foo.i"
-%typemap("javapackage") Foo, Foo *, Foo & "com.wombat.foo";
+%typemap("javapackage") Foo, Foo *, Foo & "com.wombat.foo"
 %feature("director") Example;
 
 %inline {
@@ -7093,11 +7093,11 @@ Note the helper macros below, OTHER_PACKAGE_SPEC and ANOTHER_
                                             "package.for.most.classes";
 
 %define OTHER_PACKAGE_SPEC(TYPE...)
-%typemap("javapackage") TYPE, TYPE *, TYPE & "package.for.other.classes";
+%typemap("javapackage") TYPE, TYPE *, TYPE & "package.for.other.classes"
 %enddef
 
 %define ANOTHER_PACKAGE_SPEC(TYPE...)
-%typemap("javapackage") TYPE, TYPE *, TYPE & "package.for.another.set";
+%typemap("javapackage") TYPE, TYPE *, TYPE & "package.for.another.set"
 %enddef
 
 OTHER_PACKAGE_SPEC(Package_2_class_one)
@@ -7291,7 +7291,7 @@ The typemaps to use then are as follows:
 
 
-%typemap(javabase) FileException "java.lang.Exception";
+%typemap(javabase) FileException "java.lang.Exception"
 %typemap(javacode) FileException %{
   public String getMessage() {
     return what();
diff --git a/Doc/Manual/Lisp.html b/Doc/Manual/Lisp.html
index 6eb448a12..6d8463beb 100644
--- a/Doc/Manual/Lisp.html
+++ b/Doc/Manual/Lisp.html
@@ -264,7 +264,7 @@ Let's edit the interface file such that the C type "div_t*" is changed
 
 %module test
 
-%typemap(cin) div_t* ":my-pointer";
+%typemap(cin) div_t* ":my-pointer"
 
 %feature("intern_function", "1");
 %feature("export");
diff --git a/Doc/Manual/Php.html b/Doc/Manual/Php.html
index 51ef01c51..72c914656 100644
--- a/Doc/Manual/Php.html
+++ b/Doc/Manual/Php.html
@@ -836,7 +836,7 @@ so:
 

-%typemap("phpinterfaces") MyIterator "Iterator";
+%typemap("phpinterfaces") MyIterator "Iterator"
 

diff --git a/Doc/Manual/Ruby.html b/Doc/Manual/Ruby.html index 5581cc458..e85faec42 100644 --- a/Doc/Manual/Ruby.html +++ b/Doc/Manual/Ruby.html @@ -1707,7 +1707,7 @@ For example:

%rename("is_it_safe?") is_it_safe();
 
-%typemap(out) int is_it_safe "$result = ($1 != 0) ? Qtrue : Qfalse;";
+%typemap(out) int is_it_safe "$result = ($1 != 0) ? Qtrue : Qfalse;"
 
 int is_it_safe();
diff --git a/Doc/Manual/Typemaps.html b/Doc/Manual/Typemaps.html index 8a4f830b9..3f172d540 100644 --- a/Doc/Manual/Typemaps.html +++ b/Doc/Manual/Typemaps.html @@ -787,7 +787,7 @@ Here are some examples of valid typemap specifications: %typemap(in) int { $1 = PyInt_AsLong($input); } -%typemap(in) int "$1 = PyInt_AsLong($input);"; +%typemap(in) int "$1 = PyInt_AsLong($input);" %typemap(in) int %{ $1 = PyInt_AsLong($input); %} @@ -803,7 +803,7 @@ Here are some examples of valid typemap specifications: } /* Typemap with modifiers */ -%typemap(in, doc="integer") int "$1 = scm_to_int($input);"; +%typemap(in, doc="integer") int "$1 = scm_to_int($input);" /* Typemap applied to patterns of multiple arguments */ %typemap(in) (char *str, int len), @@ -1356,13 +1356,13 @@ const reference are written like this:
-%typemap(in) int           "... convert to int ...";
-%typemap(in) short         "... convert to short ...";
-%typemap(in) float         "... convert to float ...";
+%typemap(in) int           "... convert to int ..."
+%typemap(in) short         "... convert to short ..."
+%typemap(in) float         "... convert to float ..."
 ...
-%typemap(in) const int &   "... convert ...";
-%typemap(in) const short & "... convert ...";
-%typemap(in) const float & "... convert ...";
+%typemap(in) const int &   "... convert ..."
+%typemap(in) const short & "... convert ..."
+%typemap(in) const float & "... convert ..."
 ...
 
@@ -1943,7 +1943,7 @@ Occasionally, typemap code will be specified using a few alternative forms. For
-%typemap(in) int "$1 = PyInt_AsLong($input);";
+%typemap(in) int "$1 = PyInt_AsLong($input);"
 %typemap(in) int %{
 $1 = PyInt_AsLong($input);
 %}
diff --git a/Examples/go/goin/example.i b/Examples/go/goin/example.i
index 1d8289af8..b819b8089 100644
--- a/Examples/go/goin/example.i
+++ b/Examples/go/goin/example.i
@@ -42,8 +42,8 @@ void *string_to_uintptr(char *in)
 
 // These typemaps convert between an array of strings in Go and a
 // const char** that is NULL terminated in C++.
-%typemap(gotype) (const char * const *) "[]string";
-%typemap(imtype) (const char * const *) "uintptr";
+%typemap(gotype) (const char * const *) "[]string"
+%typemap(imtype) (const char * const *) "uintptr"
 %typemap(goin) (const char * const *) {
 	if $input == nil || len($input) == 0 {
 		$result = 0
diff --git a/Examples/perl5/multimap/example.i b/Examples/perl5/multimap/example.i
index 64eb6a7f7..f2dff2418 100644
--- a/Examples/perl5/multimap/example.i
+++ b/Examples/perl5/multimap/example.i
@@ -15,7 +15,7 @@ extern int squareCubed (int n, int *OUTPUT);
 
 extern int    gcd(int x, int y);
 
-%typemap(arginit) (int argc, char *argv[]) "$2 = 0;";
+%typemap(arginit) (int argc, char *argv[]) "$2 = 0;"
 
 %typemap(in) (int argc, char *argv[]) {
   AV *tempav;
diff --git a/Examples/tcl/multimap/example.i b/Examples/tcl/multimap/example.i
index 9a141b65a..42d00225d 100644
--- a/Examples/tcl/multimap/example.i
+++ b/Examples/tcl/multimap/example.i
@@ -14,7 +14,7 @@ extern int squareCubed (int n, int *OUTPUT);
 
 extern int    gcd(int x, int y);
 
-%typemap(arginit) (int argc, char *argv[]) "$2 = 0;";
+%typemap(arginit) (int argc, char *argv[]) "$2 = 0;"
 
 %typemap(in) (int argc, char *argv[]) {
   Tcl_Obj **listobjv = 0;
diff --git a/Examples/test-suite/autodoc.i b/Examples/test-suite/autodoc.i
index efc720155..0716ea631 100644
--- a/Examples/test-suite/autodoc.i
+++ b/Examples/test-suite/autodoc.i
@@ -5,8 +5,8 @@
 %feature("autodoc");
 
 // special typemap and its docs
-%typemap(in) (int c, int d) "$1 = 0; $2 = 0;";
-%typemap(doc,name="hello",type="Tuple") (int c, int d) "hello: int tuple[2]";
+%typemap(in) (int c, int d) "$1 = 0; $2 = 0;"
+%typemap(doc,name="hello",type="Tuple") (int c, int d) "hello: int tuple[2]"
 
 // testing for different documentation levels
 %feature("autodoc","0") A::func0; // names
@@ -69,8 +69,8 @@
 %typemap(doc) (int c, int d);
 
 // docs for some parameters
-%typemap(doc) int a "a: special comment for parameter a";
-%typemap(doc) int b "b: another special comment for parameter b";
+%typemap(doc) int a "a: special comment for parameter a"
+%typemap(doc) int b "b: another special comment for parameter b"
 
 %feature("autodoc","0") C::C(int a, int b, Hola h); // names
 %feature("autodoc","1") D::D(int a, int b, Hola h); // names + types
diff --git a/Examples/test-suite/default_args.i b/Examples/test-suite/default_args.i
index 2f8fdbbd2..fda88f63d 100644
--- a/Examples/test-suite/default_args.i
+++ b/Examples/test-suite/default_args.i
@@ -144,7 +144,7 @@
 %rename(renamed2arg) Foo::renameme(int x) const;
 %rename(renamed1arg) Foo::renameme() const;
 
-%typemap(default) double* null_by_default "$1=0;";
+%typemap(default) double* null_by_default "$1=0;"
 
 %inline %{
   typedef void* MyHandle;
diff --git a/Examples/test-suite/fragments.i b/Examples/test-suite/fragments.i
index 0fad6cf68..e7bcae2a0 100644
--- a/Examples/test-suite/fragments.i
+++ b/Examples/test-suite/fragments.i
@@ -21,7 +21,7 @@ int bar(int a)
 }  
 %}
 
-%typemap(in,fragment="Hi") int hola "$1 = 123;";
+%typemap(in,fragment="Hi") int hola "$1 = 123;"
 
 
 %inline %{
diff --git a/Examples/test-suite/go_director_inout.i b/Examples/test-suite/go_director_inout.i
index c11b963f5..0be3ca1f7 100644
--- a/Examples/test-suite/go_director_inout.i
+++ b/Examples/test-suite/go_director_inout.i
@@ -161,8 +161,8 @@ void *string_to_uintptr(char *in)
 
 // These typemaps convert between an array of strings in Go and a
 // const char** that is NULL terminated in C++.
-%typemap(gotype) (const char * const *) "[]string";
-%typemap(imtype) (const char * const *) "uintptr";
+%typemap(gotype) (const char * const *) "[]string"
+%typemap(imtype) (const char * const *) "uintptr"
 %typemap(goin) (const char * const *) {
 	if $input == nil || len($input) == 0 {
 		$result = 0
diff --git a/Examples/test-suite/ignore_parameter.i b/Examples/test-suite/ignore_parameter.i
index 5650f388c..d47cb5d78 100644
--- a/Examples/test-suite/ignore_parameter.i
+++ b/Examples/test-suite/ignore_parameter.i
@@ -2,11 +2,11 @@
 
 %module ignore_parameter
 
-%typemap(in,numinputs=0) char* a "static const char* hi = \"hello\"; $1 = const_cast(hi);";
-%typemap(in,numinputs=0) int bb "$1 = 101; called_argout = 0;";
-%typemap(in,numinputs=0) double ccc "$1 = 8.8;";
+%typemap(in,numinputs=0) char* a "static const char* hi = \"hello\"; $1 = const_cast(hi);"
+%typemap(in,numinputs=0) int bb "$1 = 101; called_argout = 0;"
+%typemap(in,numinputs=0) double ccc "$1 = 8.8;"
 
-%typemap(freearg) char* a ""; // ensure freearg is not generated (needed for Java at least)
+%typemap(freearg) char* a "" // ensure freearg is not generated (needed for Java at least)
 
 %typemap(argout) int bb "called_argout = 1;"
 
diff --git a/Examples/test-suite/java_director_exception_feature.i b/Examples/test-suite/java_director_exception_feature.i
index 7978ac2a1..dfc85dea5 100644
--- a/Examples/test-suite/java_director_exception_feature.i
+++ b/Examples/test-suite/java_director_exception_feature.i
@@ -139,7 +139,7 @@
 %rename(MyJavaException2) MyNS::Exception2;
 %rename(MyJavaUnexpected) MyNS::Unexpected;
 
-%typemap(javabase) ::MyNS::Exception1,::MyNS::Exception2,::MyNS::Unexpected "java.lang.Exception";
+%typemap(javabase) ::MyNS::Exception1,::MyNS::Exception2,::MyNS::Unexpected "java.lang.Exception"
 %rename(getMessage) what() const;  // Rename all what() methods
 
 namespace MyNS {
diff --git a/Examples/test-suite/java_director_exception_feature_nspace.i b/Examples/test-suite/java_director_exception_feature_nspace.i
index b52c1acf4..f2f73278f 100644
--- a/Examples/test-suite/java_director_exception_feature_nspace.i
+++ b/Examples/test-suite/java_director_exception_feature_nspace.i
@@ -146,7 +146,7 @@
 %rename(MyJavaException2) MyNS::Exception2;
 %rename(MyJavaUnexpected) MyNS::Unexpected;
 
-%typemap(javabase) ::MyNS::Exception1,::MyNS::Exception2,::MyNS::Unexpected "java.lang.Exception";
+%typemap(javabase) ::MyNS::Exception1,::MyNS::Exception2,::MyNS::Unexpected "java.lang.Exception"
 %rename(getMessage) what() const;  // Rename all what() methods
 
 namespace MyNS {
diff --git a/Examples/test-suite/java_throws.i b/Examples/test-suite/java_throws.i
index 7c3b6f328..67d8d4ebc 100644
--- a/Examples/test-suite/java_throws.i
+++ b/Examples/test-suite/java_throws.i
@@ -88,7 +88,7 @@ int ioTest() { return 0; }
 %}
 
 // except feature (%javaexception) specifying a checked exception class for the throws clause
-%typemap(javabase) MyException "Throwable";
+%typemap(javabase) MyException "Throwable"
 %typemap(javacode) MyException %{
   public static final long serialVersionUID = 0x52151000; // Suppress ecj warning
 %}
diff --git a/Examples/test-suite/java_typemaps_proxy.i b/Examples/test-suite/java_typemaps_proxy.i
index 20b86fc01..7e90b5a3f 100644
--- a/Examples/test-suite/java_typemaps_proxy.i
+++ b/Examples/test-suite/java_typemaps_proxy.i
@@ -3,21 +3,21 @@
 %module java_typemaps_proxy
 
 
-%typemap(javaimports) SWIGTYPE "import java.math.*;";
+%typemap(javaimports) SWIGTYPE "import java.math.*;"
 %typemap(javacode) NS::Farewell %{
   public void saybye(BigDecimal num_times) {
     // BigDecimal requires the java.math library
   }
 %}
-%typemap(javaclassmodifiers) NS::Farewell "public final class";
+%typemap(javaclassmodifiers) NS::Farewell "public final class"
 
 %typemap(javaimports) NS::Greeting %{
 import java.util.*; // for EventListener
 import java.lang.*; // for Exception
 %};
 
-%typemap(javabase) NS::Greeting "Exception";
-%typemap(javainterfaces) NS::Greeting "EventListener";
+%typemap(javabase) NS::Greeting "Exception"
+%typemap(javainterfaces) NS::Greeting "EventListener"
 %typemap(javacode) NS::Greeting %{
   public static final long serialVersionUID = 0x52151000; // Suppress ecj warning
   // Pure Java code generated using %typemap(javacode) 
@@ -60,7 +60,7 @@ import java.lang.*; // for Exception
 %}
 
 // get rid of the finalize method for NS::Farewell
-%typemap(javafinalize) NS::Farewell "";
+%typemap(javafinalize) NS::Farewell ""
 
 // Test typemaps are being found for templated classes
 %typemap(javacode) NS::Adieu %{
@@ -89,7 +89,7 @@ namespace NS {
 %template(AdieuIntPtrPtr) NS::Adieu;
 
 // Check the premature garbage collection prevention parameter can be turned off
-%typemap(jtype, nopgcpp="1") Without * "long";
+%typemap(jtype, nopgcpp="1") Without * "long"
 %pragma(java) jniclassclassmodifiers="public class"
 
 %inline %{
@@ -109,7 +109,7 @@ struct With {
 void global_method_with(With *p) {}
 %}
 
-%typemap(jtype, nopgcpp="1") const ConstWithout * "long";
+%typemap(jtype, nopgcpp="1") const ConstWithout * "long"
 %inline %{
 class ConstWithout {
 public:
diff --git a/Examples/test-suite/java_typemaps_typewrapper.i b/Examples/test-suite/java_typemaps_typewrapper.i
index b7bf847ef..d3ee5432b 100644
--- a/Examples/test-suite/java_typemaps_typewrapper.i
+++ b/Examples/test-suite/java_typemaps_typewrapper.i
@@ -3,7 +3,7 @@
 %module java_typemaps_typewrapper
 
 
-%typemap(javaimports) SWIGTYPE * "import java.math.*;";
+%typemap(javaimports) SWIGTYPE * "import java.math.*;"
 %typemap(javacode) Farewell * %{
   public static $javaclassname CreateNullPointer() {
     return new $javaclassname();
@@ -12,15 +12,15 @@
     // BigDecimal requires the java.math library
   }
 %}
-%typemap(javaclassmodifiers) Farewell * "public final class";
+%typemap(javaclassmodifiers) Farewell * "public final class"
 
 %typemap(javaimports) Greeting * %{
 import java.util.*; // for EventListener
 import java.lang.*; // for Exception
 %};
 
-%typemap(javabase) Greeting * "Exception";
-%typemap(javainterfaces) Greeting * "EventListener";
+%typemap(javabase) Greeting * "Exception"
+%typemap(javainterfaces) Greeting * "EventListener"
 %typemap(javacode) Greeting * %{
   public static final long serialVersionUID = 0x52151000; // Suppress ecj warning
   // Pure Java code generated using %typemap(javacode) 
diff --git a/Examples/test-suite/minherit2.i b/Examples/test-suite/minherit2.i
index 2baea6495..965225c07 100644
--- a/Examples/test-suite/minherit2.i
+++ b/Examples/test-suite/minherit2.i
@@ -40,18 +40,18 @@ $importtype(IRemoteAsyncIO)
 #endif
 
 // Modify multiple inherited base classes into inheriting interfaces
-%typemap(javainterfaces) RemoteMpe "IRemoteSyncIO, IRemoteAsyncIO";
-%typemap(javabase, replace="1") RemoteMpe "";
+%typemap(javainterfaces) RemoteMpe "IRemoteSyncIO, IRemoteAsyncIO"
+%typemap(javabase, replace="1") RemoteMpe ""
 
 // Turn the proxy class into an interface
-%typemap(javaclassmodifiers) IRemoteSyncIO "public interface";
-%typemap(javaclassmodifiers) IRemoteAsyncIO "public interface";
-%typemap(javabody) IRemoteSyncIO "";
-%typemap(javabody) IRemoteAsyncIO "";
-%typemap(javafinalize) IRemoteSyncIO "";
-%typemap(javafinalize) IRemoteAsyncIO "";
-%typemap(javadestruct) IRemoteSyncIO "";
-%typemap(javadestruct) IRemoteAsyncIO "";
+%typemap(javaclassmodifiers) IRemoteSyncIO "public interface"
+%typemap(javaclassmodifiers) IRemoteAsyncIO "public interface"
+%typemap(javabody) IRemoteSyncIO ""
+%typemap(javabody) IRemoteAsyncIO ""
+%typemap(javafinalize) IRemoteSyncIO ""
+%typemap(javafinalize) IRemoteAsyncIO ""
+%typemap(javadestruct) IRemoteSyncIO ""
+%typemap(javadestruct) IRemoteAsyncIO ""
 
 // Turn the methods into abstract methods
 %typemap(javaout) void IRemoteSyncIO::syncmethod ";"
diff --git a/Examples/test-suite/overload_extend.i b/Examples/test-suite/overload_extend.i
index acabdd5e8..7a5c03b2e 100644
--- a/Examples/test-suite/overload_extend.i
+++ b/Examples/test-suite/overload_extend.i
@@ -5,7 +5,7 @@
 #include 
 %}
 
-%typemap(default) double y "$1=1000;";
+%typemap(default) double y "$1=1000;"
 #endif
 
 #ifdef SWIGLUA
diff --git a/Examples/test-suite/overload_extend2.i b/Examples/test-suite/overload_extend2.i
index f91738607..ded1e5e3a 100644
--- a/Examples/test-suite/overload_extend2.i
+++ b/Examples/test-suite/overload_extend2.i
@@ -1,6 +1,6 @@
 %module overload_extend2
 
-%typemap(default) int int2 "$1=1000;";
+%typemap(default) int int2 "$1=1000;"
 
 %inline %{
 typedef struct Foo {
diff --git a/Examples/test-suite/php_iterator.i b/Examples/test-suite/php_iterator.i
index 43ab68b55..e0b82a5c4 100644
--- a/Examples/test-suite/php_iterator.i
+++ b/Examples/test-suite/php_iterator.i
@@ -1,7 +1,7 @@
 /* php_iterator.i - PHP-specific testcase for wrapping to a PHP Iterator */
 %module php_iterator
 
-%typemap("phpinterfaces") MyIterator "Iterator";
+%typemap("phpinterfaces") MyIterator "Iterator"
 
 %inline %{
 
diff --git a/Examples/test-suite/python_flatstaticmethod.i b/Examples/test-suite/python_flatstaticmethod.i
index c187e9adc..0e131d669 100644
--- a/Examples/test-suite/python_flatstaticmethod.i
+++ b/Examples/test-suite/python_flatstaticmethod.i
@@ -8,8 +8,8 @@
 %feature("autodoc","0") A::func0static; // names
 %feature("autodoc","1") A::func1static; // names + types
 // special typemap and its docs
-%typemap(in) (int c, int d) "$1 = 0; $2 = 0;";
-%typemap(doc,name="hello",type="Tuple") (int c, int d) "hello: int tuple[2]";
+%typemap(in) (int c, int d) "$1 = 0; $2 = 0;"
+%typemap(doc,name="hello",type="Tuple") (int c, int d) "hello: int tuple[2]"
 
 %extend A {
 static int staticextended(int i) { return i; }
diff --git a/Examples/test-suite/ruby_manual_proxy.i b/Examples/test-suite/ruby_manual_proxy.i
index 2cb154e6a..7cfbfb1b3 100644
--- a/Examples/test-suite/ruby_manual_proxy.i
+++ b/Examples/test-suite/ruby_manual_proxy.i
@@ -1,7 +1,7 @@
 %module ruby_manual_proxy
 
 
-%typemap(in, numinputs=0) SWIGTYPE ** ($*1_ltype temp) "$1 = &temp;";
+%typemap(in, numinputs=0) SWIGTYPE ** ($*1_ltype temp) "$1 = &temp;"
 
 %typemap(argout) SWIGTYPE **OUTPARAM {
   $result = SWIG_Ruby_AppendOutput($result, SWIG_NewPointerObj(*$1, $*1_descriptor, 0));
diff --git a/Examples/test-suite/template_whitespace.i b/Examples/test-suite/template_whitespace.i
index f00b9e857..063dec6d2 100644
--- a/Examples/test-suite/template_whitespace.i
+++ b/Examples/test-suite/template_whitespace.i
@@ -11,9 +11,9 @@ template class map {
 };
 %}
 
-//%typemap(in) vector "$target = new vector();";
-//%typemap(in) vector "$target = new vector();";
-//%typemap(in) map "$target = new map();";
+//%typemap(in) vector "$target = new vector();"
+//%typemap(in) vector "$target = new vector();"
+//%typemap(in) map "$target = new map();"
 
 %inline %{
 void foo(vector v) {}
diff --git a/Examples/test-suite/typemap_variables.i b/Examples/test-suite/typemap_variables.i
index b1ae24fdf..af8dd07d2 100644
--- a/Examples/test-suite/typemap_variables.i
+++ b/Examples/test-suite/typemap_variables.i
@@ -68,12 +68,12 @@
 %clear int Space::nspace;
 %clear int Space::Struct::smember;
 %ignore Space::Struct::member;
-%typemap(varin) int globul "TYPEMAP_VARIABLES_FAIL";
-%typemap(varout, noblock=1, fragment=SWIG_From_frag(int)) int globul "if (!SWIG_IsOK(SWIG_Scilab_SetOutput(pvApiCtx, SWIG_From_int($result)))) return SWIG_ERROR;";
-%typemap(varin) int Space::nspace "TYPEMAP_VARIABLES_FAIL";
-%typemap(varout, noblock=1, fragment=SWIG_From_frag(int)) int Space::nspace "if (!SWIG_IsOK(SWIG_Scilab_SetOutput(pvApiCtx, SWIG_From_int($result)))) return SWIG_ERROR;";
-%typemap(varin) int Space::Struct::smember "TYPEMAP_VARIABLES_FAIL";
-%typemap(varout, noblock=1, fragment=SWIG_From_frag(int)) int Space::Struct::smember "if (!SWIG_IsOK(SWIG_Scilab_SetOutput(pvApiCtx, SWIG_From_int($result)))) return SWIG_ERROR;";
+%typemap(varin) int globul "TYPEMAP_VARIABLES_FAIL"
+%typemap(varout, noblock=1, fragment=SWIG_From_frag(int)) int globul "if (!SWIG_IsOK(SWIG_Scilab_SetOutput(pvApiCtx, SWIG_From_int($result)))) return SWIG_ERROR;"
+%typemap(varin) int Space::nspace "TYPEMAP_VARIABLES_FAIL"
+%typemap(varout, noblock=1, fragment=SWIG_From_frag(int)) int Space::nspace "if (!SWIG_IsOK(SWIG_Scilab_SetOutput(pvApiCtx, SWIG_From_int($result)))) return SWIG_ERROR;"
+%typemap(varin) int Space::Struct::smember "TYPEMAP_VARIABLES_FAIL"
+%typemap(varout, noblock=1, fragment=SWIG_From_frag(int)) int Space::Struct::smember "if (!SWIG_IsOK(SWIG_Scilab_SetOutput(pvApiCtx, SWIG_From_int($result)))) return SWIG_ERROR;"
 #endif
 
 %inline %{
diff --git a/Lib/cffi/cffi.swg b/Lib/cffi/cffi.swg
index 205bf7900..b96d3d4fd 100644
--- a/Lib/cffi/cffi.swg
+++ b/Lib/cffi/cffi.swg
@@ -5,62 +5,62 @@
 
 /* Typespecs for basic types. */
 
-%typemap(cin) void ":void";
+%typemap(cin) void ":void"
 
-%typemap(cin) char ":char";
-%typemap(cin) char * ":string";
-%typemap(cin) unsigned char ":unsigned-char";
-%typemap(cin) signed char ":char";
+%typemap(cin) char ":char"
+%typemap(cin) char * ":string"
+%typemap(cin) unsigned char ":unsigned-char"
+%typemap(cin) signed char ":char"
 
-%typemap(cin) short ":short";
-%typemap(cin) signed short ":short";
-%typemap(cin) unsigned short ":unsigned-short";
+%typemap(cin) short ":short"
+%typemap(cin) signed short ":short"
+%typemap(cin) unsigned short ":unsigned-short"
 
-%typemap(cin) int ":int";
-%typemap(cin) signed int ":int";
-%typemap(cin) unsigned int ":unsigned-int";
+%typemap(cin) int ":int"
+%typemap(cin) signed int ":int"
+%typemap(cin) unsigned int ":unsigned-int"
 
-%typemap(cin) long ":long";
-%typemap(cin) signed long ":long";
-%typemap(cin) unsigned long ":unsigned-long";
+%typemap(cin) long ":long"
+%typemap(cin) signed long ":long"
+%typemap(cin) unsigned long ":unsigned-long"
 
-%typemap(cin) long long ":long-long";
-%typemap(cin) signed long long ":long-long";
-%typemap(cin) unsigned long long ":unsigned-long-long";
+%typemap(cin) long long ":long-long"
+%typemap(cin) signed long long ":long-long"
+%typemap(cin) unsigned long long ":unsigned-long-long"
 
-%typemap(cin) float ":float";
-%typemap(cin) double ":double";
-%typemap(cin) SWIGTYPE ":pointer";
+%typemap(cin) float ":float"
+%typemap(cin) double ":double"
+%typemap(cin) SWIGTYPE ":pointer"
 
-%typemap(cout) void ":void";
+%typemap(cout) void ":void"
 
-%typemap(cout) char ":char";
-%typemap(cout) char * ":string";
-%typemap(cout) unsigned char ":unsigned-char";
-%typemap(cout) signed char ":char";
+%typemap(cout) char ":char"
+%typemap(cout) char * ":string"
+%typemap(cout) unsigned char ":unsigned-char"
+%typemap(cout) signed char ":char"
 
-%typemap(cout) short ":short";
-%typemap(cout) signed short ":short";
-%typemap(cout) unsigned short ":unsigned-short";
+%typemap(cout) short ":short"
+%typemap(cout) signed short ":short"
+%typemap(cout) unsigned short ":unsigned-short"
 
-%typemap(cout) int ":int";
-%typemap(cout) signed int ":int";
-%typemap(cout) unsigned int ":unsigned-int";
+%typemap(cout) int ":int"
+%typemap(cout) signed int ":int"
+%typemap(cout) unsigned int ":unsigned-int"
 
-%typemap(cout) long ":long";
-%typemap(cout) signed long ":long";
-%typemap(cout) unsigned long ":unsigned-long";
+%typemap(cout) long ":long"
+%typemap(cout) signed long ":long"
+%typemap(cout) unsigned long ":unsigned-long"
 
-%typemap(cout) long long ":long-long";
-%typemap(cout) signed long long ":long-long";
-%typemap(cout) unsigned long long ":unsigned-long-long";
+%typemap(cout) long long ":long-long"
+%typemap(cout) signed long long ":long-long"
+%typemap(cout) unsigned long long ":unsigned-long-long"
 
-%typemap(cout) float ":float";
-%typemap(cout) double ":double";
-%typemap(cout) SWIGTYPE ":pointer";
+%typemap(cout) float ":float"
+%typemap(cout) double ":double"
+%typemap(cout) SWIGTYPE ":pointer"
 
 
-%typemap(ctype) bool                       "int";
+%typemap(ctype) bool                       "int"
 %typemap(ctype) char, unsigned char, signed char,
                 short, signed short, unsigned short,
                 int, signed int, unsigned int,
@@ -68,9 +68,9 @@
                 float, double, long double, char *, void *, void,
                 enum SWIGTYPE, SWIGTYPE *,
                 SWIGTYPE[ANY], SWIGTYPE &, SWIGTYPE && "$1_ltype";
-%typemap(ctype) SWIGTYPE                   "$&1_type";
+%typemap(ctype) SWIGTYPE                   "$&1_type"
 
-%typemap(in) bool                          "$1 = (bool)$input;";
+%typemap(in) bool                          "$1 = (bool)$input;"
 %typemap(in) char, unsigned char, signed char,
              short, signed short, unsigned short,
              int, signed int, unsigned int,
@@ -78,10 +78,10 @@
              float, double, long double, char *, void *, void,
              enum SWIGTYPE, SWIGTYPE *,
              SWIGTYPE[ANY], SWIGTYPE &, SWIGTYPE && "$1 = $input;";
-%typemap(in) SWIGTYPE                      "$1 = *$input;";
+%typemap(in) SWIGTYPE                      "$1 = *$input;"
 
-%typemap(out) void                         "";
-%typemap(out) bool                          "$result = (int)$1;";
+%typemap(out) void                         ""
+%typemap(out) bool                          "$result = (int)$1;"
 %typemap(out) char, unsigned char, signed char,
               short, signed short, unsigned short,
               int, signed int, unsigned int,
@@ -114,22 +114,22 @@
                                    SWIGTYPE[ANY], SWIGTYPE { $1 = 1; };
 /* This maps C/C++ types to Lisp classes for overload dispatch */
 
-%typemap(lisptype) bool "cl:boolean";
-%typemap(lisptype) char "cl:character";
-%typemap(lisptype) unsigned char "cl:integer";
-%typemap(lisptype) signed char "cl:integer";
+%typemap(lisptype) bool "cl:boolean"
+%typemap(lisptype) char "cl:character"
+%typemap(lisptype) unsigned char "cl:integer"
+%typemap(lisptype) signed char "cl:integer"
 
-%typemap(lispclass) bool "t";
-%typemap(lispclass) char "cl:character";
+%typemap(lispclass) bool "t"
+%typemap(lispclass) char "cl:character"
 %typemap(lispclass) unsigned char, signed char,
                     short, signed short, unsigned short,
                     int, signed int, unsigned int,
                     long, signed long, unsigned long,
                     enum SWIGTYPE       "cl:integer";
 /* CLOS methods can't be specialized on single-float or double-float */
-%typemap(lispclass) float "cl:number";
-%typemap(lispclass) double "cl:number";
-%typemap(lispclass) char * "cl:string";
+%typemap(lispclass) float "cl:number"
+%typemap(lispclass) double "cl:number"
+%typemap(lispclass) char * "cl:string"
 
 /* Array reference typemaps */
 %apply SWIGTYPE & { SWIGTYPE ((&)[ANY]) }
diff --git a/Lib/csharp/std_array.i b/Lib/csharp/std_array.i
index a4f0f9640..6e7fe9eb4 100644
--- a/Lib/csharp/std_array.i
+++ b/Lib/csharp/std_array.i
@@ -16,7 +16,7 @@
 
 
 %define SWIG_STD_ARRAY_INTERNAL(T, N)
-%typemap(csinterfaces) std::array< T, N > "global::System.IDisposable, global::System.Collections.IEnumerable\n    , global::System.Collections.Generic.IEnumerable<$typemap(cstype, T)>\n";
+%typemap(csinterfaces) std::array< T, N > "global::System.IDisposable, global::System.Collections.IEnumerable\n    , global::System.Collections.Generic.IEnumerable<$typemap(cstype, T)>\n"
 %proxycode %{
   public $csclassname(global::System.Collections.ICollection c) : this() {
     if (c == null)
diff --git a/Lib/csharp/std_list.i b/Lib/csharp/std_list.i
index 674aba0ab..cf6f20238 100644
--- a/Lib/csharp/std_list.i
+++ b/Lib/csharp/std_list.i
@@ -19,7 +19,7 @@
 
 // MACRO for use within the std::list class body
 %define SWIG_STD_LIST_MINIMUM_INTERNAL(CSINTERFACE, CTYPE...)
-%typemap(csinterfaces) std::list< CTYPE > "global::System.IDisposable, global::System.Collections.IEnumerable, global::System.Collections.Generic.CSINTERFACE<$typemap(cstype, CTYPE)>\n";
+%typemap(csinterfaces) std::list< CTYPE > "global::System.IDisposable, global::System.Collections.IEnumerable, global::System.Collections.Generic.CSINTERFACE<$typemap(cstype, CTYPE)>\n"
 
 %apply void *VOID_INT_PTR { std::list< CTYPE >::iterator * };
 
diff --git a/Lib/csharp/std_map.i b/Lib/csharp/std_map.i
index e538a03a1..7a118569a 100644
--- a/Lib/csharp/std_map.i
+++ b/Lib/csharp/std_map.i
@@ -26,7 +26,7 @@
 /* K is the C++ key type, T is the C++ value type */
 %define SWIG_STD_MAP_INTERNAL(K, T, C)
 
-%typemap(csinterfaces) std::map< K, T, C > "global::System.IDisposable \n    , global::System.Collections.Generic.IDictionary<$typemap(cstype, K), $typemap(cstype, T)>\n";
+%typemap(csinterfaces) std::map< K, T, C > "global::System.IDisposable \n    , global::System.Collections.Generic.IDictionary<$typemap(cstype, K), $typemap(cstype, T)>\n"
 %proxycode %{
 
   public $typemap(cstype, T) this[$typemap(cstype, K) key] {
diff --git a/Lib/csharp/std_set.i b/Lib/csharp/std_set.i
index 82f010aff..012152260 100644
--- a/Lib/csharp/std_set.i
+++ b/Lib/csharp/std_set.i
@@ -28,7 +28,7 @@ namespace std {
 template 
 class set {
 
-%typemap(csinterfaces) std::set "global::System.IDisposable, global::System.Collections.Generic.ISet<$typemap(cstype, T)>\n";
+%typemap(csinterfaces) std::set "global::System.IDisposable, global::System.Collections.Generic.ISet<$typemap(cstype, T)>\n"
 %proxycode %{
   void global::System.Collections.Generic.ICollection<$typemap(cstype, T)>.Add($typemap(cstype, T) item) {
       ((global::System.Collections.Generic.ISet<$typemap(cstype, T)>)this).Add(item);
diff --git a/Lib/csharp/std_vector.i b/Lib/csharp/std_vector.i
index ecb10dfbb..a2add584d 100644
--- a/Lib/csharp/std_vector.i
+++ b/Lib/csharp/std_vector.i
@@ -19,7 +19,7 @@
 
 // MACRO for use within the std::vector class body
 %define SWIG_STD_VECTOR_MINIMUM_INTERNAL(CSINTERFACE, CONST_REFERENCE, CTYPE...)
-%typemap(csinterfaces) std::vector< CTYPE > "global::System.IDisposable, global::System.Collections.IEnumerable, global::System.Collections.Generic.CSINTERFACE<$typemap(cstype, CTYPE)>\n";
+%typemap(csinterfaces) std::vector< CTYPE > "global::System.IDisposable, global::System.Collections.IEnumerable, global::System.Collections.Generic.CSINTERFACE<$typemap(cstype, CTYPE)>\n"
 %proxycode %{
   public $csclassname(global::System.Collections.IEnumerable c) : this() {
     if (c == null)
diff --git a/Lib/guile/typemaps.i b/Lib/guile/typemaps.i
index eb0a41422..4381c3dec 100644
--- a/Lib/guile/typemaps.i
+++ b/Lib/guile/typemaps.i
@@ -14,7 +14,7 @@
 %typemap(in) void * {
   $1 = ($1_ltype)SWIG_MustGetPtr($input, NULL, $argnum, 0);
 }
-%typemap(freearg) void * "";
+%typemap(freearg) void * ""
 
 %typemap(varin) SWIGTYPE * {
   $1 = ($1_ltype)SWIG_MustGetPtr($input, $descriptor, 1, 0);
@@ -321,14 +321,14 @@ SIMPLE_MAP(unsigned long long, scm_to_ulong_long, scm_from_ulong_long, integer);
 /* SWIG_scm2str makes a malloc'ed copy of the string, so get rid of it after
    the function call. */
 
-%typemap (freearg) char * "if (must_free$argnum) SWIG_free($1);";
+%typemap (freearg) char * "if (must_free$argnum) SWIG_free($1);"
 %typemap (freearg) char **INPUT, char **BOTH "if (must_free$argnum) SWIG_free(*$1);"
 %typemap (freearg) char **OUTPUT "SWIG_free(*$1);"
   
 /* But this shall not apply if we try to pass a single char by
    reference. */
 
-%typemap (freearg) char *OUTPUT, char *BOTH "";
+%typemap (freearg) char *OUTPUT, char *BOTH ""
 
 /* If we set a string variable, delete the old result first, unless const. */
 
@@ -348,13 +348,13 @@ SIMPLE_MAP(unsigned long long, scm_to_ulong_long, scm_from_ulong_long, integer);
 
 /* Void */
 
-%typemap (out,doc="") void "gswig_result = SCM_UNSPECIFIED;";
+%typemap (out,doc="") void "gswig_result = SCM_UNSPECIFIED;"
 
 /* SCM is passed through */
 
 typedef unsigned long SCM;
-%typemap (in) SCM "$1=$input;";
-%typemap (out) SCM "$result=$1;";
+%typemap (in) SCM "$1=$input;"
+%typemap (out) SCM "$result=$1;"
 %typecheck(SWIG_TYPECHECK_POINTER) SCM "$1=1;";
 
 /* ------------------------------------------------------------
diff --git a/Lib/lua/luatypemaps.swg b/Lib/lua/luatypemaps.swg
index 97ecef41e..fdb9b3a97 100644
--- a/Lib/lua/luatypemaps.swg
+++ b/Lib/lua/luatypemaps.swg
@@ -248,7 +248,7 @@ $1=($1_ltype)&temp;%}
 
 
 // void (must be empty without the SWIG_arg++)
-%typemap(out) void "";
+%typemap(out) void ""
 
 /* void* is a special case
 A function void fn(void*) should take any kind of pointer as a parameter (just like C/C++ does)
diff --git a/Lib/mzscheme/typemaps.i b/Lib/mzscheme/typemaps.i
index ebd0f28da..9a1e676e9 100644
--- a/Lib/mzscheme/typemaps.i
+++ b/Lib/mzscheme/typemaps.i
@@ -111,8 +111,8 @@
   $1 = ($1_type) SWIG_convert_int($input);
 }
 
-%typemap(out) enum SWIGTYPE "$result = scheme_make_integer_value($1);";
-%typemap(varout) enum SWIGTYPE "$result = scheme_make_integer_value($1);";
+%typemap(out) enum SWIGTYPE "$result = scheme_make_integer_value($1);"
+%typemap(varout) enum SWIGTYPE "$result = scheme_make_integer_value($1);"
 
 
 /* Pass-by-value */
@@ -278,12 +278,12 @@ REF_MAP(double, SCHEME_REALP, scheme_real_to_double,
 
 /* Void */
 
-%typemap(out) void "$result = scheme_void;";
+%typemap(out) void "$result = scheme_void;"
 
 /* Pass through Scheme_Object * */
 
-%typemap (in) Scheme_Object * "$1=$input;";
-%typemap (out) Scheme_Object * "$result=$1;";
+%typemap (in) Scheme_Object * "$1=$input;"
+%typemap (out) Scheme_Object * "$result=$1;"
 %typecheck(SWIG_TYPECHECK_POINTER) Scheme_Object * "$1=1;";
 
 
diff --git a/Lib/ocaml/ocaml.swg b/Lib/ocaml/ocaml.swg
index ef0a64c90..7ca48ba08 100644
--- a/Lib/ocaml/ocaml.swg
+++ b/Lib/ocaml/ocaml.swg
@@ -188,12 +188,12 @@ SIMPLE_MAP(unsigned long long,caml_val_ulong,caml_long_val);
 
 /* Void */
 
-%typemap(out) void "$result = Val_unit;";
+%typemap(out) void "$result = Val_unit;"
 
 /* Pass through value */
 
-%typemap (in) CAML_VALUE "$1=$input;";
-%typemap (out) CAML_VALUE "$result=$1;";
+%typemap (in) CAML_VALUE "$1=$input;"
+%typemap (out) CAML_VALUE "$result=$1;"
 
 #if 0
 %include 
diff --git a/Lib/php/const.i b/Lib/php/const.i
index 33060dc04..a74af0d78 100644
--- a/Lib/php/const.i
+++ b/Lib/php/const.i
@@ -54,7 +54,7 @@
 }
 %}
 
-%typemap(classconsttab) SWIGTYPE (CLASS::*) "";
+%typemap(classconsttab) SWIGTYPE (CLASS::*) ""
 
 %typemap(consttab) int,
                    unsigned int,
@@ -100,4 +100,4 @@
 }
 
 /* Handled as a global variable. */
-%typemap(consttab) SWIGTYPE (CLASS::*) "";
+%typemap(consttab) SWIGTYPE (CLASS::*) ""
diff --git a/Lib/php/php.swg b/Lib/php/php.swg
index c2442d24b..26944a1af 100644
--- a/Lib/php/php.swg
+++ b/Lib/php/php.swg
@@ -457,7 +457,7 @@
   SWIG_SetPointerZval($input, SWIG_as_voidptr(new $1_ltype(SWIG_STD_MOVE($1))), $&1_descriptor, 1);
 %}
 
-%typemap(out, phptype="void") void "";
+%typemap(out, phptype="void") void ""
 
 %typemap(out, phptype="string") char [ANY]
 {
diff --git a/Lib/php/std_string.i b/Lib/php/std_string.i
index 8882c0abe..b2039786c 100644
--- a/Lib/php/std_string.i
+++ b/Lib/php/std_string.i
@@ -86,5 +86,5 @@ namespace std {
 
     /* SWIG will apply the non-const typemap above to const string& without
      * this more specific typemap. */
-    %typemap(argout) const string & "";
+    %typemap(argout) const string & ""
 }
diff --git a/Lib/php/typemaps.i b/Lib/php/typemaps.i
index 2f7819097..718469edc 100644
--- a/Lib/php/typemaps.i
+++ b/Lib/php/typemaps.i
@@ -31,8 +31,8 @@
   temp = (Z_TYPE($input) == IS_TRUE);
   $1 = &temp;
 %}
-%typemap(argout) TYPE *INPUT, TYPE &INPUT "";
-%typemap(in,numinputs=0) TYPE *OUTPUT(TYPE temp), TYPE &OUTPUT(TYPE temp) "$1 = &temp;";
+%typemap(argout) TYPE *INPUT, TYPE &INPUT ""
+%typemap(in,numinputs=0) TYPE *OUTPUT(TYPE temp), TYPE &OUTPUT(TYPE temp) "$1 = &temp;"
 %typemap(argout,fragment="t_output_helper") TYPE *OUTPUT, TYPE &OUTPUT
 {
   zval o;
@@ -57,8 +57,8 @@
   temp = (TYPE) zval_get_double(&$input);
   $1 = &temp;
 %}
-%typemap(argout) TYPE *INPUT, TYPE &INPUT "";
-%typemap(in,numinputs=0) TYPE *OUTPUT(TYPE temp), TYPE &OUTPUT(TYPE temp) "$1 = &temp;";
+%typemap(argout) TYPE *INPUT, TYPE &INPUT ""
+%typemap(in,numinputs=0) TYPE *OUTPUT(TYPE temp), TYPE &OUTPUT(TYPE temp) "$1 = &temp;"
 %typemap(argout,fragment="t_output_helper") TYPE *OUTPUT, TYPE &OUTPUT
 {
   zval o;
@@ -82,8 +82,8 @@
   temp = (TYPE) zval_get_long(&$input);
   $1 = &temp;
 %}
-%typemap(argout) TYPE *INPUT, TYPE &INPUT "";
-%typemap(in,numinputs=0) TYPE *OUTPUT(TYPE temp), TYPE &OUTPUT(TYPE temp) "$1 = &temp;";
+%typemap(argout) TYPE *INPUT, TYPE &INPUT ""
+%typemap(in,numinputs=0) TYPE *OUTPUT(TYPE temp), TYPE &OUTPUT(TYPE temp) "$1 = &temp;"
 %typemap(argout,fragment="t_output_helper") TYPE *OUTPUT, TYPE &OUTPUT
 {
   zval o;
diff --git a/Lib/python/pyclasses.swg b/Lib/python/pyclasses.swg
index 9d6299ff1..31ebdd2a1 100644
--- a/Lib/python/pyclasses.swg
+++ b/Lib/python/pyclasses.swg
@@ -43,7 +43,7 @@ namespace swig {
   %apply PyObject * {SwigPtr_PyObject};
   %apply PyObject * const& {SwigPtr_PyObject const&};
 
-  %typemap(typecheck,precedence=SWIG_TYPECHECK_SWIGOBJECT,noblock=1) SwigPtr_PyObject const& "$1 = ($input != 0);";
+  %typemap(typecheck,precedence=SWIG_TYPECHECK_SWIGOBJECT,noblock=1) SwigPtr_PyObject const& "$1 = ($input != 0);"
 
 
   /* For output */
diff --git a/Lib/python/pydocs.swg b/Lib/python/pydocs.swg
index 1eea41b8d..5a25423d4 100644
--- a/Lib/python/pydocs.swg
+++ b/Lib/python/pydocs.swg
@@ -2,43 +2,43 @@
 // Documentation for use with the autodoc feature.
 
 #ifdef SWIG_DOC_DOXYGEN_STYLE
-%typemap(doc) SWIGTYPE "@param $1_name $1_type";
-%typemap(doc) SWIGTYPE * "@param $1_name $1_type";
-%typemap(doc) const SWIGTYPE & "@param $1_name $1_type";
-%typemap(doc) const SWIGTYPE && "@param $1_name $1_type";
-%typemap(doc) enum SWIGTYPE "@param $1_name enum $1_type";
+%typemap(doc) SWIGTYPE "@param $1_name $1_type"
+%typemap(doc) SWIGTYPE * "@param $1_name $1_type"
+%typemap(doc) const SWIGTYPE & "@param $1_name $1_type"
+%typemap(doc) const SWIGTYPE && "@param $1_name $1_type"
+%typemap(doc) enum SWIGTYPE "@param $1_name enum $1_type"
 
-%typemap(doc) SWIGTYPE *INOUT, SWIGTYPE &INOUT "@param $1_name $1_type (input/output)";
-%typemap(doc) SWIGTYPE *INPUT, SWIGTYPE &INPUT "@param $1_name $1_type (input)";
-%typemap(doc) SWIGTYPE *OUTPUT, SWIGTYPE &OUTPUT "@param $1_name $1_type (output)";
+%typemap(doc) SWIGTYPE *INOUT, SWIGTYPE &INOUT "@param $1_name $1_type (input/output)"
+%typemap(doc) SWIGTYPE *INPUT, SWIGTYPE &INPUT "@param $1_name $1_type (input)"
+%typemap(doc) SWIGTYPE *OUTPUT, SWIGTYPE &OUTPUT "@param $1_name $1_type (output)"
 #else
-%typemap(doc) SWIGTYPE "$1_name: $1_type";
-%typemap(doc) SWIGTYPE * "$1_name: $1_type";
-%typemap(doc) const SWIGTYPE & "$1_name: $1_type";
-%typemap(doc) const SWIGTYPE && "$1_name: $1_type";
-%typemap(doc) enum SWIGTYPE "$1_name: enum $1_type";
+%typemap(doc) SWIGTYPE "$1_name: $1_type"
+%typemap(doc) SWIGTYPE * "$1_name: $1_type"
+%typemap(doc) const SWIGTYPE & "$1_name: $1_type"
+%typemap(doc) const SWIGTYPE && "$1_name: $1_type"
+%typemap(doc) enum SWIGTYPE "$1_name: enum $1_type"
 
-%typemap(doc) SWIGTYPE *INOUT, SWIGTYPE &INOUT "$1_name: $1_type (input/output)";
-%typemap(doc) SWIGTYPE *INPUT, SWIGTYPE &INPUT "$1_name: $1_type (input)";
-%typemap(doc) SWIGTYPE *OUTPUT, SWIGTYPE &OUTPUT "$1_name: $1_type (output)";
+%typemap(doc) SWIGTYPE *INOUT, SWIGTYPE &INOUT "$1_name: $1_type (input/output)"
+%typemap(doc) SWIGTYPE *INPUT, SWIGTYPE &INPUT "$1_name: $1_type (input)"
+%typemap(doc) SWIGTYPE *OUTPUT, SWIGTYPE &OUTPUT "$1_name: $1_type (output)"
 #endif
 
 
 // Types to use in Python documentation for the parameters of the given C++ type.
-%typemap(doctype) bool "boolean";
+%typemap(doctype) bool "boolean"
 
 %define int_doctype_for_cppint_type(cppint_type)
-    %typemap(doctype) cppint_type, unsigned cppint_type "int";
+    %typemap(doctype) cppint_type, unsigned cppint_type "int"
 %enddef
 %formacro(int_doctype_for_cppint_type, short, int, long, long long)
 
-%typemap(doctype) size_t "int";
+%typemap(doctype) size_t "int"
 
-%typemap(doctype) enum SWIGTYPE "int";
+%typemap(doctype) enum SWIGTYPE "int"
 
-%typemap(doctype) float, double, long double "float";
+%typemap(doctype) float, double, long double "float"
 
-%typemap(doctype) char*, std::string "string";
+%typemap(doctype) char*, std::string "string"
 
 %typemap(doctype) SWIGTYPE "$1_basetype"
 %typemap(doctype) SWIGTYPE * "$typemap(doctype, $*1_ltype)"
diff --git a/Lib/python/pytypemaps.swg b/Lib/python/pytypemaps.swg
index 0eda17cda..0ae25a686 100644
--- a/Lib/python/pytypemaps.swg
+++ b/Lib/python/pytypemaps.swg
@@ -83,7 +83,7 @@
 { SWIG_PY_POINTER, "$symname", 0, 0, (void *)($value), &$descriptor }
 %typemap(consttab) SWIGTYPE ((* const)(ANY)) = SWIGTYPE ((*)(ANY));
 
-%typemap(constcode) SWIGTYPE ((*)(ANY)) "";
+%typemap(constcode) SWIGTYPE ((*)(ANY)) ""
 %typemap(constcode) SWIGTYPE ((* const)(ANY)) = SWIGTYPE ((*)(ANY));
 
 
diff --git a/Lib/r/r.swg b/Lib/r/r.swg
index 8cf8cdf53..b1962e5ea 100644
--- a/Lib/r/r.swg
+++ b/Lib/r/r.swg
@@ -53,7 +53,7 @@ SWIG_InitializeModule(0);
       assert(all(sapply($input, class) == "$R_class"));
   %}
 
-%typemap(out) void "";
+%typemap(out) void ""
 
 %typemap(in) int *, int[ANY],
 	     signed int *, signed int[ANY],
diff --git a/Lib/r/rtype.swg b/Lib/r/rtype.swg
index 8fe12230b..41f0affe1 100644
--- a/Lib/r/rtype.swg
+++ b/Lib/r/rtype.swg
@@ -3,26 +3,26 @@
    for use in class representations. 
  */
 
-%typemap("rtype") int, int *, int &      "integer";
-%typemap("rtype") long, long *, long &      "integer";
-%typemap("rtype") float, float*, float & "numeric";
-%typemap("rtype") double, double*, double & "numeric";
-%typemap("rtype") char *, char ** "character";
-%typemap("rtype") char            "character";
-%typemap("rtype") string, string *, string & "character";
-%typemap("rtype") std::string, std::string *, std::string & "character";
-%typemap("rtype") bool, bool *    "logical";
-%typemap("rtype") enum SWIGTYPE   "character";
-%typemap("rtype") enum SWIGTYPE *   "character";
-%typemap("rtype") enum SWIGTYPE *const   "character";
-%typemap("rtype") enum SWIGTYPE &  "character";
-%typemap("rtype") const enum SWIGTYPE &  "character";
-%typemap("rtype") enum SWIGTYPE &&  "character";
-%typemap("rtype") SWIGTYPE * "$R_class";
-%typemap("rtype") SWIGTYPE *const "$R_class";
-%typemap("rtype") SWIGTYPE & "$R_class";
-%typemap("rtype") SWIGTYPE && "$R_class";
-%typemap("rtype") SWIGTYPE "$&R_class";
+%typemap("rtype") int, int *, int & "integer"
+%typemap("rtype") long, long *, long & "integer"
+%typemap("rtype") float, float*, float & "numeric"
+%typemap("rtype") double, double*, double & "numeric"
+%typemap("rtype") char *, char ** "character"
+%typemap("rtype") char "character"
+%typemap("rtype") string, string *, string & "character"
+%typemap("rtype") std::string, std::string *, std::string & "character"
+%typemap("rtype") bool, bool * "logical"
+%typemap("rtype") enum SWIGTYPE "character"
+%typemap("rtype") enum SWIGTYPE * "character"
+%typemap("rtype") enum SWIGTYPE *const "character"
+%typemap("rtype") enum SWIGTYPE & "character"
+%typemap("rtype") const enum SWIGTYPE & "character"
+%typemap("rtype") enum SWIGTYPE && "character"
+%typemap("rtype") SWIGTYPE * "$R_class"
+%typemap("rtype") SWIGTYPE *const "$R_class"
+%typemap("rtype") SWIGTYPE & "$R_class"
+%typemap("rtype") SWIGTYPE && "$R_class"
+%typemap("rtype") SWIGTYPE "$&R_class"
 
 %typemap("rtypecheck") int, int &, long, long &
   %{ (is.integer($arg) || is.numeric($arg)) && length($arg) == 1 %}
diff --git a/Lib/r/std_vector.i b/Lib/r/std_vector.i
index 4ec51dc91..93d1c6256 100644
--- a/Lib/r/std_vector.i
+++ b/Lib/r/std_vector.i
@@ -841,7 +841,7 @@
 %typemap("rtypecheck") std::vector, std::vector *, std::vector &
     %{ is.numeric($arg) %}
 %typemap("rtype") std::vector "numeric"
-%typemap("scoercein") std::vector, std::vector *, std::vector & "$input = as.numeric($input);";
+%typemap("scoercein") std::vector, std::vector *, std::vector & "$input = as.numeric($input);"
 
 %typemap_traits_ptr(SWIG_TYPECHECK_VECTOR, std::vector)
 %traits_type_name(std::vector)
@@ -857,7 +857,7 @@
 %typemap("rtypecheck") std::vector, std::vector *, std::vector &
    %{ is.logical($arg) %}
 %typemap("rtype") std::vector "logical"
-%typemap("scoercein") std::vector , std::vector & "$input = as.logical($input);";
+%typemap("scoercein") std::vector , std::vector & "$input = as.logical($input);"
 
 
 %typemap_traits_ptr(SWIG_TYPECHECK_VECTOR, std::vector);
@@ -866,7 +866,7 @@
    %{ is.integer($arg) || is.numeric($arg) %}
 
 %typemap("rtype") std::vector "integer"
-%typemap("scoercein") std::vector , std::vector *, std::vector & "$input = as.integer($input);";
+%typemap("scoercein") std::vector , std::vector *, std::vector & "$input = as.integer($input);"
 
 // strings
 %typemap("rtype") std::vector< std::basic_string >,  
@@ -974,21 +974,21 @@ std::vector< std::basic_string > *,
 %typemap("rtypecheck") std::vector >, std::vector > *, std::vector > &
    %{ is.list($arg) && all(sapply($arg , is.integer) || sapply($arg, is.numeric)) %}
 %typemap("rtype") std::vector >, std::vector > *, std::vector > & "list"
-%typemap("scoercein") std::vector< std::vector >, std::vector > *, std::vector > & "$input = lapply($input, as.integer);";
+%typemap("scoercein") std::vector< std::vector >, std::vector > *, std::vector > & "$input = lapply($input, as.integer);"
 
 %typemap_traits_ptr(SWIG_TYPECHECK_VECTOR, std::vector >);
 %traits_type_name(std::vector< std::vector >);
 %typemap("rtypecheck") std::vector >, std::vector > *, std::vector > &
    %{ is.list($arg) && all(sapply($arg , is.integer) || sapply($arg, is.numeric)) %}
 %typemap("rtype") std::vector >, std::vector > *, std::vector > & "list"
-%typemap("scoercein") std::vector< std::vector >, std::vector > *, std::vector > & "$input = lapply($input, as.integer);";
+%typemap("scoercein") std::vector< std::vector >, std::vector > *, std::vector > & "$input = lapply($input, as.integer);"
 
 %typemap_traits_ptr(SWIG_TYPECHECK_VECTOR, std::vector >);
 %traits_type_name(std::vector< std::vector >);
 %typemap("rtypecheck") std::vector >, std::vector > *, std::vector > &
    %{ is.list($arg) && all(sapply($arg , is.integer) || sapply($arg, is.numeric)) %}
 %typemap("rtype") std::vector >, std::vector > *, std::vector > "list"
-%typemap("scoercein") std::vector< std::vector >, std::vector > *, std::vector > & "$input = lapply($input, as.numeric);";
+%typemap("scoercein") std::vector< std::vector >, std::vector > *, std::vector > & "$input = lapply($input, as.numeric);"
 
 %typemap_traits_ptr(SWIG_TYPECHECK_VECTOR, std::vector >);
 %traits_type_name(std::vector< std::vector >);
@@ -1003,7 +1003,7 @@ std::vector< std::basic_string > *,
 %typemap("rtypecheck") std::vector >, std::vector > *, std::vector > &
    %{ is.list($arg) && all(sapply($arg , is.integer) || sapply($arg, is.numeric)) %}
 %typemap("rtype") std::vector >, std::vector > *, std::vector > & "list"
-%typemap("scoercein") std::vector< std::vector >, std::vector > *, std::vector > & "$input = lapply($input, as.logical);";
+%typemap("scoercein") std::vector< std::vector >, std::vector > *, std::vector > & "$input = lapply($input, as.logical);"
 
 // we don't want these to be given R classes as they
 // have already been turned into R vectors.
diff --git a/Lib/ruby/typemaps.i b/Lib/ruby/typemaps.i
index 1d28b1318..683436469 100644
--- a/Lib/ruby/typemaps.i
+++ b/Lib/ruby/typemaps.i
@@ -139,7 +139,7 @@ output values.
 */
 
 %define OUTPUT_TYPEMAP(type, converter, convtype)
-%typemap(in,numinputs=0) type *OUTPUT($*1_ltype temp), type &OUTPUT($*1_ltype temp) "$1 = &temp;";
+%typemap(in,numinputs=0) type *OUTPUT($*1_ltype temp), type &OUTPUT($*1_ltype temp) "$1 = &temp;"
 %typemap(argout, fragment="output_helper") type *OUTPUT, type &OUTPUT {
    VALUE o = converter(convtype (*$1));
    $result = output_helper($result, o);
@@ -161,7 +161,7 @@ OUTPUT_TYPEMAP(double, rb_float_new, (double));
 
 #undef OUTPUT_TYPEMAP
 
-%typemap(in,numinputs=0) bool *OUTPUT(bool temp), bool &OUTPUT(bool temp) "$1 = &temp;";
+%typemap(in,numinputs=0) bool *OUTPUT(bool temp), bool &OUTPUT(bool temp) "$1 = &temp;"
 %typemap(argout, fragment="output_helper") bool *OUTPUT, bool &OUTPUT {
     VALUE o = (*$1) ? Qtrue : Qfalse;
     $result = output_helper($result, o);
diff --git a/Lib/swig.swg b/Lib/swig.swg
index c9b301426..9148c9153 100644
--- a/Lib/swig.swg
+++ b/Lib/swig.swg
@@ -448,9 +448,9 @@ namespace std {
 /* Set up the typemap for handling new return strings */
 
 #ifdef __cplusplus
-%typemap(newfree) char * "delete [] $1;";
+%typemap(newfree) char * "delete [] $1;"
 #else
-%typemap(newfree) char * "free($1);";
+%typemap(newfree) char * "free($1);"
 #endif
 
 /* Default typemap for handling char * members */
diff --git a/Lib/typemaps/cstrings.swg b/Lib/typemaps/cstrings.swg
index 0aca61101..42ce4d9bb 100644
--- a/Lib/typemaps/cstrings.swg
+++ b/Lib/typemaps/cstrings.swg
@@ -59,7 +59,7 @@
 %typemap(in,noblock=1,numinputs=0) TYPEMAP (Char temp[MAX+1])  {
   $1 = ($1_ltype) temp;
 }
-%typemap(freearg,match="in") TYPEMAP "";
+%typemap(freearg,match="in") TYPEMAP ""
 %typemap(argout,noblock=1,fragment= #SWIG_FromCharPtr ) TYPEMAP {
   $1[MAX] = 0;  
   %append_output(SWIG_FromCharPtr($1));
@@ -85,7 +85,7 @@
 %typemap(in,noblock=1,numinputs=0) TYPEMAP(Char temp[SIZE]) {
   $1 = ($1_ltype) temp;
 }
-%typemap(freearg,match="in") TYPEMAP "";
+%typemap(freearg,match="in") TYPEMAP ""
 %typemap(argout,noblock=1,fragment= #SWIG_FromCharPtrAndSize) TYPEMAP {
   %append_output(SWIG_FromCharPtrAndSize($1,SIZE));
 }
@@ -122,7 +122,7 @@
   temp[n - 1] = 0;                                                             
   $1 = ($1_ltype) temp;                                                    
 }
-%typemap(freearg,match="in") TYPEMAP "";
+%typemap(freearg,match="in") TYPEMAP ""
 %typemap(argout,noblock=1,fragment=#SWIG_FromCharPtr) TYPEMAP {
   $1[MAX] = 0;
   %append_output(SWIG_FromCharPtr($1));
@@ -160,7 +160,7 @@
   if (alloc == SWIG_NEWOBJ) %delete_array(t);
   $1[n-1] = 0;
 }
-%typemap(freearg,match="in") TYPEMAP "";
+%typemap(freearg,match="in") TYPEMAP ""
 %typemap(argout,noblock=1,fragment=#SWIG_FromCharPtr) TYPEMAP { 
   %append_output(SWIG_FromCharPtr($1));
   %delete_array($1);                                  
@@ -247,7 +247,7 @@
 %typemap(in,noblock=1,numinputs=0) TYPEMAP($*1_ltype temp = 0) {
   $1 = &temp;
 }
-%typemap(freearg,match="in") TYPEMAP "";
+%typemap(freearg,match="in") TYPEMAP ""
 %typemap(argout,noblock=1,fragment=#SWIG_FromCharPtr) TYPEMAP { 
   if (*$1) {
     %append_output(SWIG_FromCharPtr(*$1));
@@ -275,7 +275,7 @@
 %typemap(in,noblock=1,numinputs=0) (TYPEMAP, SIZE) ($*1_ltype temp = 0, $*2_ltype tempn) {
   $1 = &temp; $2 = &tempn;
 }
-%typemap(freearg,match="in") (TYPEMAP,SIZE) "";
+%typemap(freearg,match="in") (TYPEMAP,SIZE) ""
 %typemap(argout,noblock=1,fragment=#SWIG_FromCharPtrAndSize)(TYPEMAP,SIZE) {   
   if (*$1) {
     %append_output(SWIG_FromCharPtrAndSize(*$1,*$2));
diff --git a/Lib/typemaps/ptrtypes.swg b/Lib/typemaps/ptrtypes.swg
index e8439e6dc..ca54fcdc2 100644
--- a/Lib/typemaps/ptrtypes.swg
+++ b/Lib/typemaps/ptrtypes.swg
@@ -35,7 +35,7 @@
     $1 = *ptr;
     if (SWIG_IsNewObj(res)) %delete(ptr);
   }
-  %typemap(freearg) Type "";
+  %typemap(freearg) Type ""
   %typemap(in,fragment=frag) const Type & (int res = SWIG_OLDOBJ) {
     Type *ptr = (Type *)0;
     res = asptr_meth($input, &ptr);
diff --git a/Lib/typemaps/strings.swg b/Lib/typemaps/strings.swg
index 5dd57b93d..1237d98df 100644
--- a/Lib/typemaps/strings.swg
+++ b/Lib/typemaps/strings.swg
@@ -266,7 +266,7 @@
   }
   $1 = %reinterpret_cast(temp, $1_ltype);
 }
-%typemap(freearg) Char [ANY], const Char [ANY] "";
+%typemap(freearg) Char [ANY], const Char [ANY] ""
 
 %typemap(in,noblock=1,fragment=#SWIG_AsCharArray) const Char (&)[ANY] (Char temp[$1_dim0], int res)
 {  
@@ -276,7 +276,7 @@
   }
   $1 = &temp;
 }
-%typemap(freearg) const Char (&)[ANY] "";
+%typemap(freearg) const Char (&)[ANY] ""
 
 %typemap(out,fragment=#SWIG_FromCharPtrAndSize,fragment=#SWIG_CharBufLen)
   Char [ANY], const Char[ANY] 
diff --git a/Lib/typemaps/swigobject.swg b/Lib/typemaps/swigobject.swg
index b1e6dc9d8..26c6ba8ed 100644
--- a/Lib/typemaps/swigobject.swg
+++ b/Lib/typemaps/swigobject.swg
@@ -2,7 +2,7 @@
  * Language Object *  - Just pass straight through unmodified
  * ------------------------------------------------------------ */
 
-%typemap(in)   SWIG_Object "$1 = $input;";
+%typemap(in)   SWIG_Object "$1 = $input;"
 
 %typemap(in,noblock=1)   SWIG_Object const & ($*ltype temp)
 {
@@ -30,8 +30,8 @@
 
 #if defined(SWIG_DIRECTOR_TYPEMAPS)
 
-%typemap(directorin) SWIG_Object "$input = $1;";
-%typemap(directorout) SWIG_Object "$result = $input;";
+%typemap(directorin) SWIG_Object "$input = $1;"
+%typemap(directorout) SWIG_Object "$result = $input;"
 
 #endif /* SWIG_DIRECTOR_TYPEMAPS */
 
diff --git a/Lib/typemaps/swigtype.swg b/Lib/typemaps/swigtype.swg
index 52fac3252..0f35dc397 100644
--- a/Lib/typemaps/swigtype.swg
+++ b/Lib/typemaps/swigtype.swg
@@ -9,7 +9,7 @@
   }
   $1 = %reinterpret_cast(argp, $ltype);
 }
-%typemap(freearg) SWIGTYPE * "";
+%typemap(freearg) SWIGTYPE * ""
 
 %typemap(in, noblock=1) SWIGTYPE [] (void *argp = 0, int res = 0) {
   res = SWIG_ConvertPtr($input, &argp,$descriptor, $disown | %convertptr_flags);
@@ -18,7 +18,7 @@
   } 
   $1 = %reinterpret_cast(argp, $ltype);
 }
-%typemap(freearg) SWIGTYPE [] "";
+%typemap(freearg) SWIGTYPE [] ""
 
 
 %typemap(in, noblock=1) SWIGTYPE *const&  (void *argp = 0, int res = 0, $*1_ltype temp) {
@@ -29,7 +29,7 @@
   temp = %reinterpret_cast(argp, $*ltype);
   $1 = %reinterpret_cast(&temp, $1_ltype);
 }
-%typemap(freearg) SWIGTYPE *const& "";
+%typemap(freearg) SWIGTYPE *const& ""
 
 
 /* Reference */
@@ -41,7 +41,7 @@
   if (!argp) { %argument_nullref("$type", $symname, $argnum); }
   $1 = %reinterpret_cast(argp, $ltype);
 }
-%typemap(freearg) SWIGTYPE & "";
+%typemap(freearg) SWIGTYPE & ""
 
 #if defined(__cplusplus) && defined(%implicitconv_flag)
 %typemap(in,noblock=1,implicitconv=1) const SWIGTYPE & (void *argp = 0, int res = 0) {
@@ -76,7 +76,7 @@
   if (!argp) { %argument_nullref("$type", $symname, $argnum); }
   $1 = %reinterpret_cast(argp, $ltype);
 }
-%typemap(freearg) SWIGTYPE && "";
+%typemap(freearg) SWIGTYPE && ""
 
 #if defined(__cplusplus) && defined(%implicitconv_flag)
 %typemap(in,noblock=1,implicitconv=1) const SWIGTYPE && (void *argp = 0, int res = 0) {
diff --git a/Lib/typemaps/valtypes.swg b/Lib/typemaps/valtypes.swg
index 11eac5985..f2f34acfc 100644
--- a/Lib/typemaps/valtypes.swg
+++ b/Lib/typemaps/valtypes.swg
@@ -38,7 +38,7 @@
     } 
     $1 = %static_cast(val,$ltype);
   }
-  %typemap(freearg) Type "";
+  %typemap(freearg) Type ""
   %typemap(in,noblock=1,fragment=frag) const Type & ($*ltype temp, Type val, int ecode = 0) {  
     ecode = asval_meth($input, &val);
     if (!SWIG_IsOK(ecode)) {
@@ -47,7 +47,7 @@
     temp = %static_cast(val, $*ltype);
     $1 = &temp;
   }
-  %typemap(freearg) const Type& "";
+  %typemap(freearg) const Type& ""
 %enddef
 
 /* out */
diff --git a/Lib/typemaps/void.swg b/Lib/typemaps/void.swg
index bbd68ed87..795992bf4 100644
--- a/Lib/typemaps/void.swg
+++ b/Lib/typemaps/void.swg
@@ -10,7 +10,7 @@
     %argument_fail(res, "$type", $symname, $argnum); 
   }
 }
-%typemap(freearg) void * "";
+%typemap(freearg) void * ""
 
 %typemap(in,noblock=1) void * const& ($*ltype temp = 0, int res) {
   res = SWIG_ConvertPtr($input, %as_voidptrptr(&temp), 0, $disown);
@@ -19,7 +19,7 @@
   }
   $1 =  &temp;
 }
-%typemap(freearg) void * const& "";
+%typemap(freearg) void * const& ""
 
 
 /* out */

From 0634883089550070c55e53a9f788a6794f3efaf2 Mon Sep 17 00:00:00 2001
From: William S Fulton 
Date: Wed, 24 Aug 2022 17:52:20 +0100
Subject: [PATCH 03/16] SWIGTYPE && input typemaps now assume object has been
 moved - Java

Implementation tweak - better RAII.
SWIGTYPE && null pointer check.
---
 .../cpp11_rvalue_reference_move_input_runme.java | 16 ++++++++++++++++
 Lib/java/java.swg                                |  6 +++---
 2 files changed, 19 insertions(+), 3 deletions(-)

diff --git a/Examples/test-suite/java/cpp11_rvalue_reference_move_input_runme.java b/Examples/test-suite/java/cpp11_rvalue_reference_move_input_runme.java
index dfc09f217..121c93075 100644
--- a/Examples/test-suite/java/cpp11_rvalue_reference_move_input_runme.java
+++ b/Examples/test-suite/java/cpp11_rvalue_reference_move_input_runme.java
@@ -56,5 +56,21 @@ public class cpp11_rvalue_reference_move_input_runme {
       mo111.delete();
       Counter.check_counts(2, 0, 0, 0, 1, 2);
     }
+
+    {
+      // null check
+      Counter.reset_counts();
+      boolean exception_thrown = false;
+      try {
+        MovableCopyable.movein(null);
+      } catch (NullPointerException e) {
+        if (!e.getMessage().contains("MovableCopyable && is null"))
+          throw new RuntimeException("incorrect exception message");
+        exception_thrown = true;
+      }
+      if (!exception_thrown)
+        throw new RuntimeException("Should have thrown null error");
+      Counter.check_counts(0, 0, 0, 0, 0, 0);
+    }
   }
 }
diff --git a/Lib/java/java.swg b/Lib/java/java.swg
index 4e65e7c17..821b5cdf6 100644
--- a/Lib/java/java.swg
+++ b/Lib/java/java.swg
@@ -695,12 +695,12 @@ Swig::LocalRefGuard $1_refguard(jenv, $input); }
     SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "$1_type reference is null");
     return $null;
   } %}
-%typemap(in) SWIGTYPE && %{ $1 = *($&1_ltype)&$input;
+%typemap(in, fragment="") SWIGTYPE && (std::unique_ptr<$*1_ltype> rvrdeleter) %{ $1 = *($&1_ltype)&$input;
   if (!$1) {
     SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "$1_type reference is null");
     return $null;
-  } %}
-%typemap(freearg) SWIGTYPE && %{ delete $1; %}
+  }
+  rvrdeleter.reset($1); %}
 %typemap(out) SWIGTYPE *
 %{ *($&1_ltype)&$result = $1; %} 
 %typemap(out, fragment="SWIG_PackData", noblock=1) SWIGTYPE (CLASS::*) {

From e139a3651157a42e0086b15ce9df5dcba48cf4b2 Mon Sep 17 00:00:00 2001
From: William S Fulton 
Date: Sat, 20 Aug 2022 15:40:53 +0100
Subject: [PATCH 04/16] SWIGTYPE && input typemaps now assume object has been
 moved

Replicated Java implementation.

Fully implemented for:
- C#
- D
- Guile
- Javascript (UTL)
- Lua
- MzScheme
- Octave (UTL)
- Perl (UTL)
- PHP
- Python (UTL)
- Ruby (UTL)
- Tcl (UTL)

PHP std::auto_ptr std::unique_ptr minor tweaks and testcase corrections
---
 ...cpp11_rvalue_reference_move_input_runme.cs | 66 ++++++++++++++
 .../test-suite/csharp/li_std_wstring_runme.cs |  2 +-
 ...pp11_rvalue_reference_move_input_runme.1.d | 66 ++++++++++++++
 ...pp11_rvalue_reference_move_input_runme.2.d | 67 ++++++++++++++
 ...pp11_rvalue_reference_move_input_runme.scm |  3 +
 ...p11_rvalue_reference_move_input_runme.java |  1 +
 ...cpp11_rvalue_reference_move_input_runme.js | 67 ++++++++++++++
 ...pp11_rvalue_reference_move_input_runme.lua | 56 ++++++++++++
 ...pp11_rvalue_reference_move_input_runme.scm | 54 ++++++++++++
 .../cpp11_rvalue_reference_move_input_runme.m | 64 ++++++++++++++
 ...cpp11_rvalue_reference_move_input_runme.pl | 56 ++++++++++++
 ...pp11_rvalue_reference_move_input_runme.php | 64 ++++++++++++++
 .../php/cpp11_std_unique_ptr_runme.php        | 11 ++-
 .../test-suite/php/li_std_auto_ptr_runme.php  | 11 ++-
 Examples/test-suite/php/tests.php             |  5 ++
 ...cpp11_rvalue_reference_move_input_runme.py | 52 +++++++++++
 ...cpp11_rvalue_reference_move_input_runme.rb | 87 +++++++++++++++++++
 .../cpp11_rvalue_reference_move_input.scm     | 46 ++++++++++
 ...pp11_rvalue_reference_move_input_runme.tcl | 62 +++++++++++++
 Lib/csharp/csharp.swg                         | 12 +--
 Lib/d/dswigtype.swg                           | 11 +--
 Lib/guile/typemaps.i                          | 30 +++++--
 Lib/java/java.swg                             |  4 +-
 Lib/lua/luatypemaps.swg                       | 14 ++-
 Lib/mzscheme/std_auto_ptr.i                   |  3 -
 Lib/mzscheme/std_unique_ptr.i                 |  3 -
 Lib/mzscheme/typemaps.i                       | 20 ++++-
 Lib/php/php.swg                               | 21 ++++-
 Lib/php/std_auto_ptr.i                        |  4 +-
 Lib/php/std_unique_ptr.i                      |  4 +-
 Lib/typemaps/swigtype.swg                     | 11 ++-
 31 files changed, 931 insertions(+), 46 deletions(-)
 create mode 100644 Examples/test-suite/csharp/cpp11_rvalue_reference_move_input_runme.cs
 create mode 100644 Examples/test-suite/d/cpp11_rvalue_reference_move_input_runme.1.d
 create mode 100644 Examples/test-suite/d/cpp11_rvalue_reference_move_input_runme.2.d
 create mode 100644 Examples/test-suite/guile/cpp11_rvalue_reference_move_input_runme.scm
 create mode 100644 Examples/test-suite/javascript/cpp11_rvalue_reference_move_input_runme.js
 create mode 100644 Examples/test-suite/lua/cpp11_rvalue_reference_move_input_runme.lua
 create mode 100644 Examples/test-suite/mzscheme/cpp11_rvalue_reference_move_input_runme.scm
 create mode 100644 Examples/test-suite/octave/cpp11_rvalue_reference_move_input_runme.m
 create mode 100644 Examples/test-suite/perl5/cpp11_rvalue_reference_move_input_runme.pl
 create mode 100644 Examples/test-suite/php/cpp11_rvalue_reference_move_input_runme.php
 create mode 100644 Examples/test-suite/python/cpp11_rvalue_reference_move_input_runme.py
 create mode 100644 Examples/test-suite/ruby/cpp11_rvalue_reference_move_input_runme.rb
 create mode 100644 Examples/test-suite/schemerunme/cpp11_rvalue_reference_move_input.scm
 create mode 100644 Examples/test-suite/tcl/cpp11_rvalue_reference_move_input_runme.tcl

diff --git a/Examples/test-suite/csharp/cpp11_rvalue_reference_move_input_runme.cs b/Examples/test-suite/csharp/cpp11_rvalue_reference_move_input_runme.cs
new file mode 100644
index 000000000..fb7024065
--- /dev/null
+++ b/Examples/test-suite/csharp/cpp11_rvalue_reference_move_input_runme.cs
@@ -0,0 +1,66 @@
+using System;
+using cpp11_rvalue_reference_move_inputNamespace;
+
+public class cpp11_rvalue_reference_move_input_runme {
+  public static void Main() {
+    {
+      // Function containing rvalue reference parameter
+      Counter.reset_counts();
+      MovableCopyable mo = new MovableCopyable(222);
+      Counter.check_counts(1, 0, 0, 0, 0, 0);
+      MovableCopyable.movein(mo);
+      Counter.check_counts(1, 0, 0, 1, 0, 2);
+      if (!MovableCopyable.is_nullptr(mo))
+        throw new ApplicationException("is_nullptr failed");
+      mo.Dispose();
+      Counter.check_counts(1, 0, 0, 1, 0, 2);
+    }
+
+    {
+      // Move constructor test
+      Counter.reset_counts();
+      MovableCopyable mo = new MovableCopyable(222);
+      Counter.check_counts(1, 0, 0, 0, 0, 0);
+      MovableCopyable mo_moved = new MovableCopyable(mo);
+      Counter.check_counts(1, 0, 0, 1, 0, 1);
+      if (!MovableCopyable.is_nullptr(mo))
+        throw new ApplicationException("is_nullptr failed");
+      mo.Dispose();
+      Counter.check_counts(1, 0, 0, 1, 0, 1);
+      mo_moved.Dispose();
+      Counter.check_counts(1, 0, 0, 1, 0, 2);
+    }
+
+    {
+      // Move assignment operator test
+      Counter.reset_counts();
+      MovableCopyable mo111 = new MovableCopyable(111);
+      MovableCopyable mo222 = new MovableCopyable(222);
+      Counter.check_counts(2, 0, 0, 0, 0, 0);
+      mo111.MoveAssign(mo222);
+      Counter.check_counts(2, 0, 0, 0, 1, 1);
+      if (!MovableCopyable.is_nullptr(mo222))
+        throw new ApplicationException("is_nullptr failed");
+      mo222.Dispose();
+      Counter.check_counts(2, 0, 0, 0, 1, 1);
+      mo111.Dispose();
+      Counter.check_counts(2, 0, 0, 0, 1, 2);
+    }
+
+    {
+      // null check
+      Counter.reset_counts();
+      bool exception_thrown = false;
+      try {
+        MovableCopyable.movein(null);
+      } catch (ArgumentNullException e) {
+        if (!e.Message.Contains("MovableCopyable && is null"))
+          throw new ApplicationException("incorrect exception message:" + e);
+        exception_thrown = true;
+      }
+      if (!exception_thrown)
+        throw new ApplicationException("Should have thrown null error");
+      Counter.check_counts(0, 0, 0, 0, 0, 0);
+    }
+  }
+}
diff --git a/Examples/test-suite/csharp/li_std_wstring_runme.cs b/Examples/test-suite/csharp/li_std_wstring_runme.cs
index d2be3d1ff..97dfedbf0 100644
--- a/Examples/test-suite/csharp/li_std_wstring_runme.cs
+++ b/Examples/test-suite/csharp/li_std_wstring_runme.cs
@@ -66,7 +66,7 @@ public class runme
             li_std_wstring.test_reference(null);
             throw new Exception("NULL check failed");
         } catch (ArgumentNullException e) {
-            if (!e.Message.Contains("type is null"))
+            if (!e.Message.Contains("is null"))
                 throw new Exception("Missing text " + e);
         }
         try {
diff --git a/Examples/test-suite/d/cpp11_rvalue_reference_move_input_runme.1.d b/Examples/test-suite/d/cpp11_rvalue_reference_move_input_runme.1.d
new file mode 100644
index 000000000..e6d23868c
--- /dev/null
+++ b/Examples/test-suite/d/cpp11_rvalue_reference_move_input_runme.1.d
@@ -0,0 +1,66 @@
+module cpp11_rvalue_reference_move_input_runme;
+
+import cpp11_rvalue_reference_move_input.Counter;
+import cpp11_rvalue_reference_move_input.MovableCopyable;
+
+void main() {
+  {
+    // Function containing rvalue reference parameter
+    Counter.reset_counts();
+    scope MovableCopyable mo = new MovableCopyable(222);
+    Counter.check_counts(1, 0, 0, 0, 0, 0);
+    MovableCopyable.movein(mo);
+    Counter.check_counts(1, 0, 0, 1, 0, 2);
+    if (!MovableCopyable.is_nullptr(mo))
+      throw new Exception("is_nullptr failed");
+    mo.dispose();
+    Counter.check_counts(1, 0, 0, 1, 0, 2);
+  }
+
+  {
+    // Move constructor test
+    Counter.reset_counts();
+    scope MovableCopyable mo = new MovableCopyable(222);
+    Counter.check_counts(1, 0, 0, 0, 0, 0);
+    MovableCopyable mo_moved = new MovableCopyable(mo);
+    Counter.check_counts(1, 0, 0, 1, 0, 1);
+    if (!MovableCopyable.is_nullptr(mo))
+      throw new Exception("is_nullptr failed");
+    mo.dispose();
+    Counter.check_counts(1, 0, 0, 1, 0, 1);
+    mo_moved.dispose();
+    Counter.check_counts(1, 0, 0, 1, 0, 2);
+  }
+
+  {
+    // Move assignment operator test
+    Counter.reset_counts();
+    scope MovableCopyable mo111 = new MovableCopyable(111);
+    scope MovableCopyable mo222 = new MovableCopyable(222);
+    Counter.check_counts(2, 0, 0, 0, 0, 0);
+    mo111.MoveAssign(mo222);
+    Counter.check_counts(2, 0, 0, 0, 1, 1);
+    if (!MovableCopyable.is_nullptr(mo222))
+      throw new Exception("is_nullptr failed");
+    mo222.dispose();
+    Counter.check_counts(2, 0, 0, 0, 1, 1);
+    mo111.dispose();
+    Counter.check_counts(2, 0, 0, 0, 1, 2);
+  }
+
+  {
+    // null check
+    Counter.reset_counts();
+    bool exception_thrown = false;
+    try {
+      MovableCopyable.movein(null);
+    } catch (Exception e) {
+      if (!canFind(e.msg, "MovableCopyable && is null"))
+        throw new Exception("incorrect exception message:" ~ e.msg);
+      exception_thrown = true;
+    }
+    if (!exception_thrown)
+      throw new Exception("Should have thrown null error");
+    Counter.check_counts(0, 0, 0, 0, 0, 0);
+  }
+}
diff --git a/Examples/test-suite/d/cpp11_rvalue_reference_move_input_runme.2.d b/Examples/test-suite/d/cpp11_rvalue_reference_move_input_runme.2.d
new file mode 100644
index 000000000..5b3e6001a
--- /dev/null
+++ b/Examples/test-suite/d/cpp11_rvalue_reference_move_input_runme.2.d
@@ -0,0 +1,67 @@
+module cpp11_rvalue_reference_move_input_runme;
+
+import cpp11_rvalue_reference_move_input.Counter;
+import cpp11_rvalue_reference_move_input.MovableCopyable;
+import std.algorithm;
+
+void main() {
+  {
+    // Function containing rvalue reference parameter
+    Counter.reset_counts();
+    scope MovableCopyable mo = new MovableCopyable(222);
+    Counter.check_counts(1, 0, 0, 0, 0, 0);
+    MovableCopyable.movein(mo);
+    Counter.check_counts(1, 0, 0, 1, 0, 2);
+    if (!MovableCopyable.is_nullptr(mo))
+      throw new Exception("is_nullptr failed");
+    mo.dispose();
+    Counter.check_counts(1, 0, 0, 1, 0, 2);
+  }
+
+  {
+    // Move constructor test
+    Counter.reset_counts();
+    scope MovableCopyable mo = new MovableCopyable(222);
+    Counter.check_counts(1, 0, 0, 0, 0, 0);
+    MovableCopyable mo_moved = new MovableCopyable(mo);
+    Counter.check_counts(1, 0, 0, 1, 0, 1);
+    if (!MovableCopyable.is_nullptr(mo))
+      throw new Exception("is_nullptr failed");
+    mo.dispose();
+    Counter.check_counts(1, 0, 0, 1, 0, 1);
+    mo_moved.dispose();
+    Counter.check_counts(1, 0, 0, 1, 0, 2);
+  }
+
+  {
+    // Move assignment operator test
+    Counter.reset_counts();
+    scope MovableCopyable mo111 = new MovableCopyable(111);
+    scope MovableCopyable mo222 = new MovableCopyable(222);
+    Counter.check_counts(2, 0, 0, 0, 0, 0);
+    mo111.MoveAssign(mo222);
+    Counter.check_counts(2, 0, 0, 0, 1, 1);
+    if (!MovableCopyable.is_nullptr(mo222))
+      throw new Exception("is_nullptr failed");
+    mo222.dispose();
+    Counter.check_counts(2, 0, 0, 0, 1, 1);
+    mo111.dispose();
+    Counter.check_counts(2, 0, 0, 0, 1, 2);
+  }
+
+  {
+    // null check
+    Counter.reset_counts();
+    bool exception_thrown = false;
+    try {
+      MovableCopyable.movein(null);
+    } catch (Exception e) {
+      if (!canFind(e.msg, "MovableCopyable && is null"))
+        throw new Exception("incorrect exception message:" ~ e.msg);
+      exception_thrown = true;
+    }
+    if (!exception_thrown)
+      throw new Exception("Should have thrown null error");
+    Counter.check_counts(0, 0, 0, 0, 0, 0);
+  }
+}
diff --git a/Examples/test-suite/guile/cpp11_rvalue_reference_move_input_runme.scm b/Examples/test-suite/guile/cpp11_rvalue_reference_move_input_runme.scm
new file mode 100644
index 000000000..6beecf3e8
--- /dev/null
+++ b/Examples/test-suite/guile/cpp11_rvalue_reference_move_input_runme.scm
@@ -0,0 +1,3 @@
+(dynamic-call "scm_init_cpp11_rvalue_reference_move_input_module" (dynamic-link "./libcpp11_rvalue_reference_move_input"))
+(load "testsuite.scm")
+(load "../schemerunme/cpp11_rvalue_reference_move_input.scm")
diff --git a/Examples/test-suite/java/cpp11_rvalue_reference_move_input_runme.java b/Examples/test-suite/java/cpp11_rvalue_reference_move_input_runme.java
index 121c93075..2115bd7ca 100644
--- a/Examples/test-suite/java/cpp11_rvalue_reference_move_input_runme.java
+++ b/Examples/test-suite/java/cpp11_rvalue_reference_move_input_runme.java
@@ -15,6 +15,7 @@ public class cpp11_rvalue_reference_move_input_runme {
   public static void main(String argv[]) {
 
     {
+      // Function containing rvalue reference parameter
       Counter.reset_counts();
       MovableCopyable mo = new MovableCopyable(222);
       Counter.check_counts(1, 0, 0, 0, 0, 0);
diff --git a/Examples/test-suite/javascript/cpp11_rvalue_reference_move_input_runme.js b/Examples/test-suite/javascript/cpp11_rvalue_reference_move_input_runme.js
new file mode 100644
index 000000000..ba432d466
--- /dev/null
+++ b/Examples/test-suite/javascript/cpp11_rvalue_reference_move_input_runme.js
@@ -0,0 +1,67 @@
+var cpp11_rvalue_reference_move_input = require("cpp11_rvalue_reference_move_input");
+
+{
+  // Function containing rvalue reference parameter
+  cpp11_rvalue_reference_move_input.Counter.reset_counts();
+  mo = new cpp11_rvalue_reference_move_input.MovableCopyable(222);
+  cpp11_rvalue_reference_move_input.Counter.check_counts(1, 0, 0, 0, 0, 0);
+  cpp11_rvalue_reference_move_input.MovableCopyable.movein(mo);
+  cpp11_rvalue_reference_move_input.Counter.check_counts(1, 0, 0, 1, 0, 2);
+  if (!cpp11_rvalue_reference_move_input.MovableCopyable.is_nullptr(mo))
+    throw new Error("is_nullptr failed");
+  delete mo;
+  cpp11_rvalue_reference_move_input.Counter.check_counts(1, 0, 0, 1, 0, 2);
+}
+
+{
+  // Move constructor test
+  cpp11_rvalue_reference_move_input.Counter.reset_counts();
+  mo = new cpp11_rvalue_reference_move_input.MovableCopyable(222);
+  cpp11_rvalue_reference_move_input.Counter.check_counts(1, 0, 0, 0, 0, 0);
+  mo_moved = new cpp11_rvalue_reference_move_input.MovableCopyable(mo);
+  cpp11_rvalue_reference_move_input.Counter.check_counts(1, 0, 0, 1, 0, 1);
+  if (!cpp11_rvalue_reference_move_input.MovableCopyable.is_nullptr(mo))
+    throw new Error("is_nullptr failed");
+  delete mo;
+  cpp11_rvalue_reference_move_input.Counter.check_counts(1, 0, 0, 1, 0, 1);
+  // delete mo_moved;
+  // cpp11_rvalue_reference_move_input.Counter.check_counts(1, 0, 0, 1, 0, 2);
+  // Above not deleting the C++ object(node v12) - can't reliably control GC - use the movein function instead to delete
+  cpp11_rvalue_reference_move_input.MovableCopyable.movein(mo_moved);
+  cpp11_rvalue_reference_move_input.Counter.check_counts(1, 0, 0, 2, 0, 3);
+}
+
+{
+  // Move assignment operator test
+  cpp11_rvalue_reference_move_input.Counter.reset_counts();
+  mo111 = new cpp11_rvalue_reference_move_input.MovableCopyable(111);
+  mo222 = new cpp11_rvalue_reference_move_input.MovableCopyable(222);
+  cpp11_rvalue_reference_move_input.Counter.check_counts(2, 0, 0, 0, 0, 0);
+  mo111.MoveAssign(mo222);
+  cpp11_rvalue_reference_move_input.Counter.check_counts(2, 0, 0, 0, 1, 1);
+  if (!cpp11_rvalue_reference_move_input.MovableCopyable.is_nullptr(mo222))
+    throw new Error("is_nullptr failed");
+  delete mo222;
+  cpp11_rvalue_reference_move_input.Counter.check_counts(2, 0, 0, 0, 1, 1);
+  // delete mo111;
+  // cpp11_rvalue_reference_move_input.Counter.check_counts(2, 0, 0, 0, 1, 2);
+  // Above not deleting the C++ object(node v12) - can't reliably control GC - use the movein function instead to delete
+  cpp11_rvalue_reference_move_input.MovableCopyable.movein(mo111);
+  cpp11_rvalue_reference_move_input.Counter.check_counts(2, 0, 0, 1, 1, 3);
+}
+
+{
+  // null check
+  cpp11_rvalue_reference_move_input.Counter.reset_counts();
+  exception_thrown = false;
+  try {
+    cpp11_rvalue_reference_move_input.MovableCopyable.movein(null);
+  } catch (e) {
+    if (!e.message.includes("invalid null reference"))
+      throw new Error("incorrect exception message " + e.message);
+    exception_thrown = true;
+  }
+  if (!exception_thrown)
+    throw new Error("Should have thrown null error");
+  cpp11_rvalue_reference_move_input.Counter.check_counts(0, 0, 0, 0, 0, 0);
+}
diff --git a/Examples/test-suite/lua/cpp11_rvalue_reference_move_input_runme.lua b/Examples/test-suite/lua/cpp11_rvalue_reference_move_input_runme.lua
new file mode 100644
index 000000000..1dfeba7df
--- /dev/null
+++ b/Examples/test-suite/lua/cpp11_rvalue_reference_move_input_runme.lua
@@ -0,0 +1,56 @@
+require("import")	-- the import fn
+import("cpp11_rvalue_reference_move_input")	-- import code
+
+-- catch "undefined" global variables
+local env = _ENV -- Lua 5.2
+if not env then env = getfenv () end -- Lua 5.1
+setmetatable(env, {__index=function (t,i) error("undefined global variable `"..i.."'",2) end})
+
+-- Function containing rvalue reference parameter
+cpp11_rvalue_reference_move_input.Counter.reset_counts()
+mo = cpp11_rvalue_reference_move_input.MovableCopyable(222)
+cpp11_rvalue_reference_move_input.Counter.check_counts(1, 0, 0, 0, 0, 0)
+cpp11_rvalue_reference_move_input.MovableCopyable.movein(mo)
+cpp11_rvalue_reference_move_input.Counter.check_counts(1, 0, 0, 1, 0, 2)
+if not (cpp11_rvalue_reference_move_input.MovableCopyable_is_nullptr(mo)) then
+  error("is_nullptr failed")
+end
+mo = nil
+cpp11_rvalue_reference_move_input.Counter.check_counts(1, 0, 0, 1, 0, 2)
+
+-- Move constructor test
+cpp11_rvalue_reference_move_input.Counter.reset_counts()
+mo = cpp11_rvalue_reference_move_input.MovableCopyable(222)
+cpp11_rvalue_reference_move_input.Counter.check_counts(1, 0, 0, 0, 0, 0)
+mo_moved = cpp11_rvalue_reference_move_input.MovableCopyable(mo)
+cpp11_rvalue_reference_move_input.Counter.check_counts(1, 0, 0, 1, 0, 1)
+if not (cpp11_rvalue_reference_move_input.MovableCopyable_is_nullptr(mo)) then
+  error("is_nullptr failed")
+end
+mo = nil
+cpp11_rvalue_reference_move_input.Counter.check_counts(1, 0, 0, 1, 0, 1)
+mo_moved = nil
+collectgarbage() -- gc nudge needed here
+cpp11_rvalue_reference_move_input.Counter.check_counts(1, 0, 0, 1, 0, 2)
+
+-- Move assignment operator test
+cpp11_rvalue_reference_move_input.Counter.reset_counts()
+mo111 = cpp11_rvalue_reference_move_input.MovableCopyable(111)
+mo222 = cpp11_rvalue_reference_move_input.MovableCopyable(222)
+cpp11_rvalue_reference_move_input.Counter.check_counts(2, 0, 0, 0, 0, 0)
+mo111:MoveAssign(mo222)
+cpp11_rvalue_reference_move_input.Counter.check_counts(2, 0, 0, 0, 1, 1)
+if not (cpp11_rvalue_reference_move_input.MovableCopyable_is_nullptr(mo222)) then
+  error("is_nullptr failed")
+end
+mo222 = nil
+cpp11_rvalue_reference_move_input.Counter.check_counts(2, 0, 0, 0, 1, 1)
+mo111 = nil
+collectgarbage() -- gc nudge needed here
+cpp11_rvalue_reference_move_input.Counter.check_counts(2, 0, 0, 0, 1, 2)
+
+-- null check
+cpp11_rvalue_reference_move_input.Counter.reset_counts()
+s, msg = pcall(function() cpp11_rvalue_reference_move_input.MovableCopyable.movein(nil) end)
+assert(s == false and msg:find("Error in MovableCopyable::movein (arg 1), expected 'MovableCopyable &&' got 'nil'", 1, true))
+cpp11_rvalue_reference_move_input.Counter.check_counts(0, 0, 0, 0, 0, 0)
diff --git a/Examples/test-suite/mzscheme/cpp11_rvalue_reference_move_input_runme.scm b/Examples/test-suite/mzscheme/cpp11_rvalue_reference_move_input_runme.scm
new file mode 100644
index 000000000..8e95a071b
--- /dev/null
+++ b/Examples/test-suite/mzscheme/cpp11_rvalue_reference_move_input_runme.scm
@@ -0,0 +1,54 @@
+(load-extension "cpp11_rvalue_reference_move_input.so")
+(require (lib "defmacro.ss"))
+
+; Copied from ../schemerunme/cpp11_rvalue_reference_move_input.scm and modified for exceptions
+
+; Function containing rvalue reference parameter
+(Counter-reset-counts)
+(define mo (new-MovableCopyable 222))
+(Counter-check-counts 1 0 0 0 0 0)
+(MovableCopyable-movein mo)
+(Counter-check-counts 1 0 0 1 0 2)
+(unless (MovableCopyable-is-nullptr mo)
+  (error "is_nullptr failed"))
+(delete-MovableCopyable mo)
+(Counter-check-counts 1 0 0 1 0 2)
+
+; Move constructor test
+(Counter-reset-counts)
+(define mo (new-MovableCopyable 222))
+(Counter-check-counts 1 0 0 0 0 0)
+(define mo_moved (new-MovableCopyable mo))
+(Counter-check-counts 1 0 0 1 0 1)
+(unless (MovableCopyable-is-nullptr mo)
+  (error "is_nullptr failed"))
+(delete-MovableCopyable mo)
+(Counter-check-counts 1 0 0 1 0 1)
+(delete-MovableCopyable mo_moved)
+(Counter-check-counts 1 0 0 1 0 2)
+
+; Move assignment operator test
+(Counter-reset-counts)
+(define mo111 (new-MovableCopyable 111))
+(define mo222 (new-MovableCopyable 222))
+(Counter-check-counts 2 0 0 0 0 0)
+(MovableCopyable-MoveAssign mo111 mo222)
+(Counter-check-counts 2 0 0 0 1 1)
+(unless (MovableCopyable-is-nullptr mo222)
+  (error "is_nullptr failed"))
+(delete-MovableCopyable mo222)
+(Counter-check-counts 2 0 0 0 1 1)
+(delete-MovableCopyable mo111)
+(Counter-check-counts 2 0 0 0 1 2)
+
+; null check
+(Counter-reset-counts)
+(define exception_thrown "no exception thrown for kin")
+(with-handlers ([exn:fail? (lambda (exn)
+                             (set! exception_thrown (exn-message exn)))])
+  (MovableCopyable-movein '()))
+(unless (string=? exception_thrown "MovableCopyable-movein: swig-type-error (null reference)")
+  (error (format "incorrect exception message: ~a" exception_thrown)))
+(Counter-check-counts 0 0 0 0 0 0)
+
+(exit 0)
diff --git a/Examples/test-suite/octave/cpp11_rvalue_reference_move_input_runme.m b/Examples/test-suite/octave/cpp11_rvalue_reference_move_input_runme.m
new file mode 100644
index 000000000..28b80d920
--- /dev/null
+++ b/Examples/test-suite/octave/cpp11_rvalue_reference_move_input_runme.m
@@ -0,0 +1,64 @@
+# do not dump Octave core
+if exist("crash_dumps_octave_core", "builtin")
+  crash_dumps_octave_core(0);
+endif
+
+cpp11_rvalue_reference_move_input
+
+# Function containing rvalue reference parameter
+Counter.reset_counts();
+mo = MovableCopyable(222);
+Counter.check_counts(1, 0, 0, 0, 0, 0);
+MovableCopyable.movein(mo);
+Counter.check_counts(1, 0, 0, 1, 0, 2);
+if (!MovableCopyable_is_nullptr(mo))
+  error("is_nullptr failed");
+endif
+clear mo;
+Counter.check_counts(1, 0, 0, 1, 0, 2);
+
+# Move constructor test
+Counter.reset_counts();
+mo = MovableCopyable(222);
+Counter.check_counts(1, 0, 0, 0, 0, 0);
+mo_moved = MovableCopyable(mo);
+Counter.check_counts(1, 0, 0, 1, 0, 1);
+if (!MovableCopyable_is_nullptr(mo))
+  error("is_nullptr failed");
+endif
+clear mo;
+Counter.check_counts(1, 0, 0, 1, 0, 1);
+clear mo_moved;
+Counter.check_counts(1, 0, 0, 1, 0, 2);
+
+# Move assignment operator test
+Counter.reset_counts();
+mo111 = MovableCopyable(111);
+mo222 = MovableCopyable(222);
+Counter.check_counts(2, 0, 0, 0, 0, 0);
+mo111.MoveAssign(mo222);
+Counter.check_counts(2, 0, 0, 0, 1, 1);
+if (!MovableCopyable_is_nullptr(mo222))
+  error("is_nullptr failed");
+endif
+clear mo222;
+Counter.check_counts(2, 0, 0, 0, 1, 1);
+clear mo111;
+Counter.check_counts(2, 0, 0, 0, 1, 2);
+
+# null check
+null = []; # NULL pointer
+Counter.reset_counts();
+exception_thrown = false;
+try
+  MovableCopyable.movein(null);
+catch e
+  if (isempty(strfind(e.message, "invalid null reference")))
+    error("incorrect exception message: %s", e.message)
+  endif
+  exception_thrown = true;
+end_try_catch
+if (!exception_thrown)
+  error("Should have thrown null error");
+endif
+Counter.check_counts(0, 0, 0, 0, 0, 0);
diff --git a/Examples/test-suite/perl5/cpp11_rvalue_reference_move_input_runme.pl b/Examples/test-suite/perl5/cpp11_rvalue_reference_move_input_runme.pl
new file mode 100644
index 000000000..f4f419c87
--- /dev/null
+++ b/Examples/test-suite/perl5/cpp11_rvalue_reference_move_input_runme.pl
@@ -0,0 +1,56 @@
+use strict;
+use warnings;
+use Test::More tests => 6;
+BEGIN { use_ok('cpp11_rvalue_reference_move_input') }
+require_ok('cpp11_rvalue_reference_move_input');
+
+{
+  # Function containing rvalue reference parameter
+  cpp11_rvalue_reference_move_input::Counter::reset_counts();
+  my $mo = new cpp11_rvalue_reference_move_input::MovableCopyable(222);
+  cpp11_rvalue_reference_move_input::Counter::check_counts(1, 0, 0, 0, 0, 0);
+  cpp11_rvalue_reference_move_input::MovableCopyable::movein($mo);
+  cpp11_rvalue_reference_move_input::Counter::check_counts(1, 0, 0, 1, 0, 2);
+  is(cpp11_rvalue_reference_move_input::MovableCopyable::is_nullptr($mo), 1, "is_nullptr check");
+  undef $mo;
+  cpp11_rvalue_reference_move_input::Counter::check_counts(1, 0, 0, 1, 0, 2);
+}
+
+{
+  # Move constructor test
+  cpp11_rvalue_reference_move_input::Counter::reset_counts();
+  my $mo = new cpp11_rvalue_reference_move_input::MovableCopyable(222);
+  cpp11_rvalue_reference_move_input::Counter::check_counts(1, 0, 0, 0, 0, 0);
+  my $mo_moved = new cpp11_rvalue_reference_move_input::MovableCopyable($mo);
+  cpp11_rvalue_reference_move_input::Counter::check_counts(1, 0, 0, 1, 0, 1);
+  is(cpp11_rvalue_reference_move_input::MovableCopyable::is_nullptr($mo), 1, "is_nullptr check");
+  undef $mo;
+  cpp11_rvalue_reference_move_input::Counter::check_counts(1, 0, 0, 1, 0, 1);
+  undef $mo_moved;
+  cpp11_rvalue_reference_move_input::Counter::check_counts(1, 0, 0, 1, 0, 2);
+}
+
+{
+  # Move assignment operator test
+  cpp11_rvalue_reference_move_input::Counter::reset_counts();
+  my $mo111 = new cpp11_rvalue_reference_move_input::MovableCopyable(111);
+  my $mo222 = new cpp11_rvalue_reference_move_input::MovableCopyable(222);
+  cpp11_rvalue_reference_move_input::Counter::check_counts(2, 0, 0, 0, 0, 0);
+  $mo111->MoveAssign($mo222);
+  cpp11_rvalue_reference_move_input::Counter::check_counts(2, 0, 0, 0, 1, 1);
+  is(cpp11_rvalue_reference_move_input::MovableCopyable::is_nullptr($mo222), 1, "is_nullptr check");
+  undef $mo222;
+  cpp11_rvalue_reference_move_input::Counter::check_counts(2, 0, 0, 0, 1, 1);
+  undef $mo111;
+  cpp11_rvalue_reference_move_input::Counter::check_counts(2, 0, 0, 0, 1, 2);
+}
+
+{
+  # null check
+  cpp11_rvalue_reference_move_input::Counter::reset_counts();
+  eval {
+    cpp11_rvalue_reference_move_input::MovableCopyable::movein(undef);
+  };
+  like($@, qr/\binvalid null reference/, "Should have thrown null error");
+  cpp11_rvalue_reference_move_input::Counter::check_counts(0, 0, 0, 0, 0, 0);
+}
diff --git a/Examples/test-suite/php/cpp11_rvalue_reference_move_input_runme.php b/Examples/test-suite/php/cpp11_rvalue_reference_move_input_runme.php
new file mode 100644
index 000000000..176134682
--- /dev/null
+++ b/Examples/test-suite/php/cpp11_rvalue_reference_move_input_runme.php
@@ -0,0 +1,64 @@
+MoveAssign($mo222);
+Counter::check_counts(2, 0, 0, 0, 1, 1);
+try {
+    MovableCopyable::is_nullptr($mo222);
+    check::fail("is_nullptr check");
+} catch (TypeError $e) {
+}
+$mo222 = NULL;
+Counter::check_counts(2, 0, 0, 0, 1, 1);
+$mo111 = NULL;
+Counter::check_counts(2, 0, 0, 0, 1, 2);
+
+# null check
+Counter::reset_counts();
+$exception_thrown = false;
+try {
+  MovableCopyable::movein(NULL);
+} catch (TypeError $e) {
+  check::str_contains($e->getMessage(), "Invalid null reference", "incorrect exception message: {$e->getMessage()}");
+  $exception_thrown = true;
+}
+check::equal($exception_thrown, true, "Should have thrown null error");
+Counter::check_counts(0, 0, 0, 0, 0, 0);
+
+check::done();
diff --git a/Examples/test-suite/php/cpp11_std_unique_ptr_runme.php b/Examples/test-suite/php/cpp11_std_unique_ptr_runme.php
index b02fdaa33..2b169e748 100644
--- a/Examples/test-suite/php/cpp11_std_unique_ptr_runme.php
+++ b/Examples/test-suite/php/cpp11_std_unique_ptr_runme.php
@@ -40,20 +40,27 @@ try {
     check::fail("is_nullptr check");
 } catch (TypeError $e) {
 }
+$exception_thrown = false;
 try {
+  takeKlassUniquePtr($kin);
 } catch (TypeError $e) {
-  check::equal($e->getMessage(), "Cannot release ownership as memory is not owned for argument 1 of type 'Klass *' of takeKlassUniquePtr", "Unexpected exception: {$e->getMessage()}");
+  check::equal($e->getMessage(), "Cannot release ownership as memory is not owned for argument 1 of SWIGTYPE_p_Klass of takeKlassUniquePtr", "Unexpected exception: {$e->getMessage()}");
+  $exception_thrown = true;
 }
+check::equal($exception_thrown, true, "double usage of takeKlassUniquePtr should have been an error");
 $kin = NULL; # Should not fail, even though already deleted
 checkCount(0);
 
 $kin = new Klass("KlassInput");
+$exception_thrown = false;
 $notowned = get_not_owned_ptr($kin);
 try {
   takeKlassUniquePtr($notowned);
 } catch (TypeError $e) {
-  check::equal($e->getMessage(), "Cannot release ownership as memory is not owned for argument 1 of type 'Klass *' of takeKlassUniquePtr", "Unexpected exception: {$e->getMessage()}");
+  check::equal($e->getMessage(), "Cannot release ownership as memory is not owned for argument 1 of SWIGTYPE_p_Klass of takeKlassUniquePtr", "Unexpected exception: {$e->getMessage()}");
+  $exception_thrown = true;
 }
+check::equal($exception_thrown, true, "double usage of takeKlassUniquePtr should have been an error");
 checkCount(1);
 $kin = NULL;
 checkCount(0);
diff --git a/Examples/test-suite/php/li_std_auto_ptr_runme.php b/Examples/test-suite/php/li_std_auto_ptr_runme.php
index cba5f2109..16129490a 100644
--- a/Examples/test-suite/php/li_std_auto_ptr_runme.php
+++ b/Examples/test-suite/php/li_std_auto_ptr_runme.php
@@ -40,20 +40,27 @@ try {
     check::fail("is_nullptr check");
 } catch (TypeError $e) {
 }
+$exception_thrown = false;
 try {
+  takeKlassAutoPtr($kin);
 } catch (TypeError $e) {
-  check::equal($e->getMessage(), "Cannot release ownership as memory is not owned for argument 1 of type 'Klass *' of takeKlassAutoPtr", "Unexpected exception: {$e->getMessage()}");
+  check::equal($e->getMessage(), "Cannot release ownership as memory is not owned for argument 1 of SWIGTYPE_p_Klass of takeKlassAutoPtr", "Unexpected exception: {$e->getMessage()}");
+  $exception_thrown = true;
 }
+check::equal($exception_thrown, true, "double usage of takeKlassAutoPtr should have been an error");
 $kin = NULL; # Should not fail, even though already deleted
 checkCount(0);
 
 $kin = new Klass("KlassInput");
+$exception_thrown = false;
 $notowned = get_not_owned_ptr($kin);
 try {
   takeKlassAutoPtr($notowned);
 } catch (TypeError $e) {
-  check::equal($e->getMessage(), "Cannot release ownership as memory is not owned for argument 1 of type 'Klass *' of takeKlassAutoPtr", "Unexpected exception: {$e->getMessage()}");
+  check::equal($e->getMessage(), "Cannot release ownership as memory is not owned for argument 1 of SWIGTYPE_p_Klass of takeKlassAutoPtr", "Unexpected exception: {$e->getMessage()}");
+  $exception_thrown = true;
 }
+check::equal($exception_thrown, true, "double usage of takeKlassAutoPtr should have been an error");
 checkCount(1);
 $kin = NULL;
 checkCount(0);
diff --git a/Examples/test-suite/php/tests.php b/Examples/test-suite/php/tests.php
index 92e554741..0ff20e377 100644
--- a/Examples/test-suite/php/tests.php
+++ b/Examples/test-suite/php/tests.php
@@ -178,6 +178,11 @@ class check {
     return TRUE;
   }
 
+  static function str_contains($a,$b,$message=null) {
+    # Use strpos as PHP function str_contains requires PHP 8
+    return check::equal(strpos($a,$b)!==false,true,$message);
+  }
+
   static function isnull($a,$message=null) {
     return check::equal($a,NULL,$message);
   }
diff --git a/Examples/test-suite/python/cpp11_rvalue_reference_move_input_runme.py b/Examples/test-suite/python/cpp11_rvalue_reference_move_input_runme.py
new file mode 100644
index 000000000..7db7b4c3b
--- /dev/null
+++ b/Examples/test-suite/python/cpp11_rvalue_reference_move_input_runme.py
@@ -0,0 +1,52 @@
+from cpp11_rvalue_reference_move_input import *
+
+# Function containing rvalue reference parameter
+Counter.reset_counts()
+mo = MovableCopyable(222)
+Counter.check_counts(1, 0, 0, 0, 0, 0)
+MovableCopyable.movein(mo)
+Counter.check_counts(1, 0, 0, 1, 0, 2)
+if not MovableCopyable.is_nullptr(mo):
+    raise RuntimeError("is_nullptr check")
+del mo
+Counter.check_counts(1, 0, 0, 1, 0, 2)
+
+# Move constructor test
+Counter.reset_counts()
+mo = MovableCopyable(222)
+Counter.check_counts(1, 0, 0, 0, 0, 0)
+mo_moved = MovableCopyable(mo)
+Counter.check_counts(1, 0, 0, 1, 0, 1)
+if not MovableCopyable.is_nullptr(mo):
+    raise RuntimeError("is_nullptr check")
+del mo
+Counter.check_counts(1, 0, 0, 1, 0, 1)
+del mo_moved
+Counter.check_counts(1, 0, 0, 1, 0, 2)
+
+# Move assignment operator test
+Counter.reset_counts()
+mo111 = MovableCopyable(111)
+mo222 = MovableCopyable(222)
+Counter.check_counts(2, 0, 0, 0, 0, 0)
+mo111.MoveAssign(mo222)
+Counter.check_counts(2, 0, 0, 0, 1, 1)
+if not MovableCopyable.is_nullptr(mo222):
+    raise RuntimeError("is_nullptr check")
+del mo222
+Counter.check_counts(2, 0, 0, 0, 1, 1)
+del mo111
+Counter.check_counts(2, 0, 0, 0, 1, 2)
+
+# null check
+Counter.reset_counts()
+exception_thrown = False
+try:
+    MovableCopyable.movein(None)
+except ValueError as e:
+    if "invalid null reference" not in str(e):
+        raise RuntimeError("incorrect exception message:" + str(e))
+    exception_thrown = True
+if not exception_thrown:
+    raise RuntimeError("Should have thrown null error")
+Counter.check_counts(0, 0, 0, 0, 0, 0)
diff --git a/Examples/test-suite/ruby/cpp11_rvalue_reference_move_input_runme.rb b/Examples/test-suite/ruby/cpp11_rvalue_reference_move_input_runme.rb
new file mode 100644
index 000000000..4b7347d43
--- /dev/null
+++ b/Examples/test-suite/ruby/cpp11_rvalue_reference_move_input_runme.rb
@@ -0,0 +1,87 @@
+#!/usr/bin/env ruby
+
+require 'swig_assert'
+
+require 'cpp11_rvalue_reference_move_input'
+
+# Function containing rvalue reference parameter
+Cpp11_rvalue_reference_move_input::Counter.reset_counts()
+mo = Cpp11_rvalue_reference_move_input::MovableCopyable.new(222)
+Cpp11_rvalue_reference_move_input::Counter.check_counts(1, 0, 0, 0, 0, 0)
+Cpp11_rvalue_reference_move_input::MovableCopyable.movein(mo)
+Cpp11_rvalue_reference_move_input::Counter.check_counts(1, 0, 0, 1, 0, 2)
+exception_thrown = false
+begin
+    Cpp11_rvalue_reference_move_input::MovableCopyable.is_nullptr(mo)
+rescue ObjectPreviouslyDeleted
+    exception_thrown = true
+end
+if (!exception_thrown)
+    raise RuntimeError, "is_nullptr failed to throw"
+end
+mo = nil
+Cpp11_rvalue_reference_move_input::Counter.check_counts(1, 0, 0, 1, 0, 2)
+
+# Move constructor test
+Cpp11_rvalue_reference_move_input::Counter.reset_counts()
+mo = Cpp11_rvalue_reference_move_input::MovableCopyable.new(222)
+Cpp11_rvalue_reference_move_input::Counter.check_counts(1, 0, 0, 0, 0, 0)
+mo_moved = Cpp11_rvalue_reference_move_input::MovableCopyable.new(mo)
+Cpp11_rvalue_reference_move_input::Counter.check_counts(1, 0, 0, 1, 0, 1)
+exception_thrown = false
+begin
+    Cpp11_rvalue_reference_move_input::MovableCopyable.is_nullptr(mo)
+rescue ObjectPreviouslyDeleted
+    exception_thrown = true
+end
+if (!exception_thrown)
+    raise RuntimeError, "is_nullptr failed to throw"
+end
+mo = nil
+Cpp11_rvalue_reference_move_input::Counter.check_counts(1, 0, 0, 1, 0, 1)
+# mo_moved = nil
+# Cpp11_rvalue_reference_move_input::Counter.check_counts(1, 0, 0, 1, 0, 2)
+# Above not deleting the C++ object(node v12) - can't reliably control GC - use the movein function instead to delete
+Cpp11_rvalue_reference_move_input::MovableCopyable.movein(mo_moved)
+Cpp11_rvalue_reference_move_input::Counter.check_counts(1, 0, 0, 2, 0, 3)
+
+# Move assignment operator test
+Cpp11_rvalue_reference_move_input::Counter.reset_counts()
+mo111 = Cpp11_rvalue_reference_move_input::MovableCopyable.new(111)
+mo222 = Cpp11_rvalue_reference_move_input::MovableCopyable.new(222)
+Cpp11_rvalue_reference_move_input::Counter.check_counts(2, 0, 0, 0, 0, 0)
+mo111.MoveAssign(mo222)
+Cpp11_rvalue_reference_move_input::Counter.check_counts(2, 0, 0, 0, 1, 1)
+exception_thrown = false
+begin
+    Cpp11_rvalue_reference_move_input::MovableCopyable.is_nullptr(mo222)
+rescue ObjectPreviouslyDeleted
+    exception_thrown = true
+end
+if (!exception_thrown)
+    raise RuntimeError, "is_nullptr failed to throw"
+end
+mo222 = nil
+Cpp11_rvalue_reference_move_input::Counter.check_counts(2, 0, 0, 0, 1, 1)
+# mo111 = nil
+# Cpp11_rvalue_reference_move_input::Counter.check_counts(2, 0, 0, 0, 1, 2)
+# Above not deleting the C++ object(node v12) - can't reliably control GC - use the movein function instead to delete
+Cpp11_rvalue_reference_move_input::MovableCopyable.movein(mo111)
+Cpp11_rvalue_reference_move_input::Counter.check_counts(2, 0, 0, 1, 1, 3)
+
+# null check
+Cpp11_rvalue_reference_move_input::Counter.reset_counts()
+exception_thrown = false
+begin
+  Cpp11_rvalue_reference_move_input::MovableCopyable.movein(nil)
+rescue ArgumentError => e
+  if (!e.to_s.include? "invalid null reference")
+    raise RuntimeError, "incorrect exception message: #{e.to_s}"
+  end
+  exception_thrown = true
+end
+if (!exception_thrown)
+  raise RuntimeError, "Should have thrown null error"
+end
+Cpp11_rvalue_reference_move_input::Counter.check_counts(0, 0, 0, 0, 0, 0)
+
diff --git a/Examples/test-suite/schemerunme/cpp11_rvalue_reference_move_input.scm b/Examples/test-suite/schemerunme/cpp11_rvalue_reference_move_input.scm
new file mode 100644
index 000000000..303932f98
--- /dev/null
+++ b/Examples/test-suite/schemerunme/cpp11_rvalue_reference_move_input.scm
@@ -0,0 +1,46 @@
+; Function containing rvalue reference parameter
+(Counter-reset-counts)
+(define mo (new-MovableCopyable 222))
+(Counter-check-counts 1 0 0 0 0 0)
+(MovableCopyable-movein mo)
+(Counter-check-counts 1 0 0 1 0 2)
+(unless (MovableCopyable-is-nullptr mo)
+  (error "is_nullptr failed"))
+(delete-MovableCopyable mo)
+(Counter-check-counts 1 0 0 1 0 2)
+
+; Move constructor test
+(Counter-reset-counts)
+(define mo (new-MovableCopyable 222))
+(Counter-check-counts 1 0 0 0 0 0)
+(define mo_moved (new-MovableCopyable mo))
+(Counter-check-counts 1 0 0 1 0 1)
+(unless (MovableCopyable-is-nullptr mo)
+  (error "is_nullptr failed"))
+(delete-MovableCopyable mo)
+(Counter-check-counts 1 0 0 1 0 1)
+(delete-MovableCopyable mo_moved)
+(Counter-check-counts 1 0 0 1 0 2)
+
+; Move assignment operator test
+(Counter-reset-counts)
+(define mo111 (new-MovableCopyable 111))
+(define mo222 (new-MovableCopyable 222))
+(Counter-check-counts 2 0 0 0 0 0)
+(MovableCopyable-MoveAssign mo111 mo222)
+(Counter-check-counts 2 0 0 0 1 1)
+(unless (MovableCopyable-is-nullptr mo222)
+  (error "is_nullptr failed"))
+(delete-MovableCopyable mo222)
+(Counter-check-counts 2 0 0 0 1 1)
+(delete-MovableCopyable mo111)
+(Counter-check-counts 2 0 0 0 1 2)
+
+; null check
+(Counter-reset-counts)
+(expect-throw 'misc-error
+              (MovableCopyable-movein '()))
+; TODO: check the exception message
+(Counter-check-counts 0 0 0 0 0 0)
+
+(exit 0)
diff --git a/Examples/test-suite/tcl/cpp11_rvalue_reference_move_input_runme.tcl b/Examples/test-suite/tcl/cpp11_rvalue_reference_move_input_runme.tcl
new file mode 100644
index 000000000..a81bf398a
--- /dev/null
+++ b/Examples/test-suite/tcl/cpp11_rvalue_reference_move_input_runme.tcl
@@ -0,0 +1,62 @@
+
+if [ catch { load ./cpp11_rvalue_reference_move_input[info sharedlibextension] cpp11_rvalue_reference_move_input} err_msg ] {
+	puts stderr "Could not load shared object:\n$err_msg"
+}
+
+
+# Function containing rvalue reference parameter
+Counter_reset_counts
+MovableCopyable mo 222
+Counter_check_counts 1  0  0  0  0  0
+MovableCopyable_movein mo
+Counter_check_counts 1  0  0  1  0  2
+if {![MovableCopyable_is_nullptr mo]} {
+  error "is_nullptr failed to throw"
+}
+mo -delete
+Counter_check_counts 1  0  0  1  0  2
+
+# Move constructor test
+Counter_reset_counts
+MovableCopyable mo 222
+Counter_check_counts 1  0  0  0  0  0
+MovableCopyable mo_moved mo
+Counter_check_counts 1  0  0  1  0  1
+if {![MovableCopyable_is_nullptr mo]} {
+  error "is_nullptr failed to throw"
+}
+mo -delete
+Counter_check_counts 1  0  0  1  0  1
+mo_moved -delete
+Counter_check_counts 1  0  0  1  0  2
+
+# Move assignment operator test
+Counter_reset_counts
+MovableCopyable mo111 111
+MovableCopyable mo222 222
+Counter_check_counts 2  0  0  0  0  0
+mo111 MoveAssign mo222
+Counter_check_counts 2  0  0  0  1  1
+if {![MovableCopyable_is_nullptr mo222]} {
+  error "is_nullptr failed to throw"
+}
+mo222 -delete
+Counter_check_counts 2  0  0  0  1  1
+mo111 -delete
+Counter_check_counts 2  0  0  0  1  2
+
+# null check
+Counter_reset_counts
+set exception_thrown 0
+if [ catch {
+  MovableCopyable_movein "NULL"
+} e ] {
+  if {[string first "invalid null reference" $e] == -1} {
+    error "incorrect exception message: $e"
+  }
+  set exception_thrown 1
+}
+if {!$exception_thrown} {
+  error "Should have thrown null error"
+}
+Counter_check_counts 0  0  0  0  0  0
diff --git a/Lib/csharp/csharp.swg b/Lib/csharp/csharp.swg
index 60ab388f3..1f80d12a1 100644
--- a/Lib/csharp/csharp.swg
+++ b/Lib/csharp/csharp.swg
@@ -420,14 +420,15 @@ SWIGINTERN const char * SWIG_UnpackData(const char *c, void *ptr, size_t sz) {
 %}
 %typemap(in, canthrow=1) SWIGTYPE & %{ $1 = ($1_ltype)$input;
   if (!$1) {
-    SWIG_CSharpSetPendingExceptionArgument(SWIG_CSharpArgumentNullException, "$1_type type is null", 0);
+    SWIG_CSharpSetPendingExceptionArgument(SWIG_CSharpArgumentNullException, "$1_type is null", 0);
     return $null;
   } %}
-%typemap(in, canthrow=1) SWIGTYPE && %{ $1 = ($1_ltype)$input;
+%typemap(in, canthrow=1, fragment="") SWIGTYPE && (std::unique_ptr<$*1_ltype> rvrdeleter) %{ $1 = ($1_ltype)$input;
   if (!$1) {
-    SWIG_CSharpSetPendingExceptionArgument(SWIG_CSharpArgumentNullException, "$1_type type is null", 0);
+    SWIG_CSharpSetPendingExceptionArgument(SWIG_CSharpArgumentNullException, "$1_type is null", 0);
     return $null;
-  } %}
+  }
+  rvrdeleter.reset($1); %}
 %typemap(out) SWIGTYPE * %{ $result = (void *)$1; %} 
 %typemap(out, fragment="SWIG_PackData") SWIGTYPE (CLASS::*) %{
   char buf[128];
@@ -613,7 +614,8 @@ SWIGINTERN const char * SWIG_UnpackData(const char *c, void *ptr, size_t sz) {
     "$csinput"
 %typemap(csin) char *, char *&, char[ANY], char[] "$csinput"
 %typemap(csin) SWIGTYPE "$&csclassname.getCPtr($csinput)"
-%typemap(csin) SWIGTYPE *, SWIGTYPE &, SWIGTYPE &&, SWIGTYPE [] "$csclassname.getCPtr($csinput)"
+%typemap(csin) SWIGTYPE *, SWIGTYPE &, SWIGTYPE [] "$csclassname.getCPtr($csinput)"
+%typemap(csin) SWIGTYPE && "$csclassname.swigRelease($csinput)"
 %typemap(csin) SWIGTYPE (CLASS::*) "$csclassname.getCMemberPtr($csinput)"
 
 /* The csout typemap is used for converting function return types from the return type
diff --git a/Lib/d/dswigtype.swg b/Lib/d/dswigtype.swg
index 3fb7f6a01..c227519e8 100644
--- a/Lib/d/dswigtype.swg
+++ b/Lib/d/dswigtype.swg
@@ -122,7 +122,7 @@
 
 %typemap(in, canthrow=1) SWIGTYPE & %{ $1 = ($1_ltype)$input;
   if (!$1) {
-    SWIG_DSetPendingException(SWIG_DIllegalArgumentException, "$1_type type is null");
+    SWIG_DSetPendingException(SWIG_DIllegalArgumentException, "$1_type is null");
     return $null;
   } %}
 %typemap(out) SWIGTYPE & "$result = (void *)$1;"
@@ -157,11 +157,12 @@
  * Rvalue reference conversion typemaps.
  */
 
-%typemap(in, canthrow=1) SWIGTYPE && %{ $1 = ($1_ltype)$input;
+%typemap(in, canthrow=1, fragment="") SWIGTYPE && (std::unique_ptr<$*1_ltype> rvrdeleter) %{ $1 = ($1_ltype)$input;
   if (!$1) {
-    SWIG_DSetPendingException(SWIG_DIllegalArgumentException, "$1_type type is null");
+    SWIG_DSetPendingException(SWIG_DIllegalArgumentException, "$1_type is null");
     return $null;
-  } %}
+  }
+  rvrdeleter.reset($1); %}
 %typemap(out) SWIGTYPE && "$result = (void *)$1;"
 
 %typemap(directorin) SWIGTYPE &&
@@ -182,7 +183,7 @@
 
 %typemap(din,
   nativepointer="cast(void*)$dinput"
-) SWIGTYPE && "$dclassname.swigGetCPtr($dinput)"
+) SWIGTYPE && "$dclassname.swigRelease($dinput)"
 %typemap(dout, excode=SWIGEXCODE,
   nativepointer="{\n  auto ret = cast($dtype)$imcall;$excode\n  return ret;\n}") SWIGTYPE && {
   $dclassname ret = new $dclassname($imcall, $owner);$excode
diff --git a/Lib/guile/typemaps.i b/Lib/guile/typemaps.i
index 4381c3dec..37dfaee64 100644
--- a/Lib/guile/typemaps.i
+++ b/Lib/guile/typemaps.i
@@ -4,12 +4,33 @@
  * Guile-specific typemaps
  * ----------------------------------------------------------------------------- */
 
+/* These are defined with a view to eventually merging with those defined for other target languages in swigtypemaps.swg and exception.swg */
+#define %set_output(obj)                  $result = obj
+#define %set_varoutput(obj)               $result = obj
+#define %argument_fail(_code, _type, _name, _argn)	scm_wrong_type_arg((char *) FUNC_NAME, _argn, $input)
+#define %as_voidptr(ptr)		(void*)(ptr)
+#define %argument_nullref(_type, _name, _argn) scm_misc_error(FUNC_NAME, "invalid null reference for argument " #_argn " of type '" _type "'", SCM_EOL)
+#define %releasenotowned_fail(_code, _type, _name, _argn) scm_misc_error(FUNC_NAME, "cannot release ownership as memory is not owned for argument " #_argn " of type '" _type "'", SCM_EOL)
+
 /* Pointers */
 
-%typemap(in) SWIGTYPE *, SWIGTYPE &, SWIGTYPE &&, SWIGTYPE [] {
+%typemap(in) SWIGTYPE *, SWIGTYPE &, SWIGTYPE [] {
   $1 = ($1_ltype)SWIG_MustGetPtr($input, $descriptor, $argnum, 0);
 }
-%typemap(freearg) SWIGTYPE *, SWIGTYPE &, SWIGTYPE &&, SWIGTYPE [] "";
+%typemap(in, noblock=1, fragment="") SWIGTYPE && (void *argp = 0, int res = 0, std::unique_ptr<$*1_ltype> rvrdeleter) {
+  res = SWIG_ConvertPtr($input, &argp, $descriptor, SWIG_POINTER_RELEASE);
+  if (!SWIG_IsOK(res)) {
+    if (res == SWIG_ERROR_RELEASE_NOT_OWNED) {
+      %releasenotowned_fail(res, "$1_type", $symname, $argnum);
+    } else {
+      %argument_fail(res, "$1_type", $symname, $argnum);
+    }
+  }
+  if (!argp) { %argument_nullref("$1_type", $symname, $argnum); }
+  $1 = ($1_ltype)argp;
+  rvrdeleter.reset($1);
+}
+%typemap(freearg) SWIGTYPE *, SWIGTYPE &, SWIGTYPE &&, SWIGTYPE [] ""
 
 %typemap(in) void * {
   $1 = ($1_ltype)SWIG_MustGetPtr($input, NULL, $argnum, 0);
@@ -372,11 +393,6 @@ typedef unsigned long SCM;
  * taken from typemaps/swigtype.swg
  * ------------------------------------------------------------ */
 
-#define %set_output(obj)                  $result = obj
-#define %set_varoutput(obj)               $result = obj
-#define %argument_fail(code, type, name, argn)	scm_wrong_type_arg((char *) FUNC_NAME, argn, $input);
-#define %as_voidptr(ptr)		(void*)(ptr)
-
 %typemap(in) SWIGTYPE (CLASS::*) {
   int res = SWIG_ConvertMember($input, %as_voidptr(&$1), sizeof($1), $descriptor);
   if (!SWIG_IsOK(res)) {
diff --git a/Lib/java/java.swg b/Lib/java/java.swg
index 821b5cdf6..8719818bb 100644
--- a/Lib/java/java.swg
+++ b/Lib/java/java.swg
@@ -692,12 +692,12 @@ Swig::LocalRefGuard $1_refguard(jenv, $input); }
 }
 %typemap(in) SWIGTYPE & %{ $1 = *($&1_ltype)&$input;
   if (!$1) {
-    SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "$1_type reference is null");
+    SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "$1_type is null");
     return $null;
   } %}
 %typemap(in, fragment="") SWIGTYPE && (std::unique_ptr<$*1_ltype> rvrdeleter) %{ $1 = *($&1_ltype)&$input;
   if (!$1) {
-    SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "$1_type reference is null");
+    SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "$1_type is null");
     return $null;
   }
   rvrdeleter.reset($1); %}
diff --git a/Lib/lua/luatypemaps.swg b/Lib/lua/luatypemaps.swg
index fdb9b3a97..7d23917ee 100644
--- a/Lib/lua/luatypemaps.swg
+++ b/Lib/lua/luatypemaps.swg
@@ -151,11 +151,17 @@ SWIGINTERN int SWIG_lua_isnilstring(lua_State *L, int idx) {
   }
 %}
 
-%typemap(in,checkfn="lua_isuserdata") SWIGTYPE&&
-%{
-  if (!SWIG_IsOK(SWIG_ConvertPtr(L,$input,(void**)&$1,$descriptor,$disown))){
-    SWIG_fail_ptr("$symname",$argnum,$descriptor);
+%typemap(in,checkfn="lua_isuserdata",fragment="") SWIGTYPE&& (void *argp = 0, int res = 0, std::unique_ptr<$*1_ltype> rvrdeleter) %{
+  res = SWIG_ConvertPtr(L, $input, &argp, $descriptor, SWIG_POINTER_RELEASE);
+  if (!SWIG_IsOK(res)) {
+    if (res == SWIG_ERROR_RELEASE_NOT_OWNED) {
+      lua_pushfstring(L, "Cannot release ownership as memory is not owned for argument $argnum of type '$1_type' in $symname"); SWIG_fail;
+    } else {
+      SWIG_fail_ptr("$symname", $argnum, $descriptor);
+    }
   }
+  $1 = ($1_ltype)argp;
+  rvrdeleter.reset($1);
 %}
 
 // out is simple
diff --git a/Lib/mzscheme/std_auto_ptr.i b/Lib/mzscheme/std_auto_ptr.i
index a903d0063..dd55230b3 100644
--- a/Lib/mzscheme/std_auto_ptr.i
+++ b/Lib/mzscheme/std_auto_ptr.i
@@ -8,9 +8,6 @@
  * C++ layer when passed as a parameter to a wrapped function.
  * ----------------------------------------------------------------------------- */
 
-#define %argument_fail(code, type, name, argn)	scheme_wrong_type(FUNC_NAME, type, argn, argc, argv);
-#define %set_output(obj)                  $result = obj
-
 %define %auto_ptr(TYPE)
 %typemap(in, noblock=1) std::auto_ptr< TYPE > (void *argp = 0, int res = 0) {
   res = SWIG_ConvertPtr($input, &argp, $descriptor(TYPE *), SWIG_POINTER_RELEASE);
diff --git a/Lib/mzscheme/std_unique_ptr.i b/Lib/mzscheme/std_unique_ptr.i
index 35386a783..af602c342 100644
--- a/Lib/mzscheme/std_unique_ptr.i
+++ b/Lib/mzscheme/std_unique_ptr.i
@@ -8,9 +8,6 @@
  * C++ layer when passed as a parameter to a wrapped function.
  * ----------------------------------------------------------------------------- */
 
-#define %argument_fail(code, type, name, argn)	scheme_wrong_type(FUNC_NAME, type, argn, argc, argv);
-#define %set_output(obj)                  $result = obj
-
 %define %unique_ptr(TYPE)
 %typemap(in, noblock=1) std::unique_ptr< TYPE > (void *argp = 0, int res = 0) {
   res = SWIG_ConvertPtr($input, &argp, $descriptor(TYPE *), SWIG_POINTER_RELEASE);
diff --git a/Lib/mzscheme/typemaps.i b/Lib/mzscheme/typemaps.i
index 9a1e676e9..25c7b7707 100644
--- a/Lib/mzscheme/typemaps.i
+++ b/Lib/mzscheme/typemaps.i
@@ -4,7 +4,7 @@
 
 #define %set_output(obj)                  $result = obj
 #define %set_varoutput(obj)               $result = obj
-#define %argument_fail(code, type, name, argn)	scheme_wrong_type(FUNC_NAME, type, argn, argc, argv);
+#define %argument_fail(code, type, name, argn)	scheme_wrong_type(FUNC_NAME, type, argn, argc, argv)
 #define %as_voidptr(ptr)		(void*)(ptr)
 
 
@@ -72,9 +72,23 @@
 
 #ifdef __cplusplus
 
-%typemap(in) SWIGTYPE &, SWIGTYPE && { 
+%typemap(in) SWIGTYPE & {
   $1 = ($ltype) SWIG_MustGetPtr($input, $descriptor, $argnum, 0);
-  if ($1 == NULL) scheme_signal_error("swig-type-error (null reference)");
+  if ($1 == NULL) scheme_signal_error(FUNC_NAME ": swig-type-error (null reference)");
+}
+
+%typemap(in, noblock=1, fragment="") SWIGTYPE && (void *argp = 0, int res = 0, std::unique_ptr<$*1_ltype> rvrdeleter) {
+  res = SWIG_ConvertPtr($input, &argp, $descriptor, SWIG_POINTER_RELEASE);
+  if (!SWIG_IsOK(res)) {
+    if (res == SWIG_ERROR_RELEASE_NOT_OWNED) {
+      scheme_signal_error(FUNC_NAME ": cannot release ownership as memory is not owned for argument $argnum of type '$1_type'");
+    } else {
+      %argument_fail(res, "$1_type", $symname, $argnum);
+    }
+  }
+  if (argp == NULL) scheme_signal_error(FUNC_NAME ": swig-type-error (null reference)");
+  $1 = ($1_ltype)argp;
+  rvrdeleter.reset($1);
 }
 
 %typemap(out) SWIGTYPE &, SWIGTYPE && {
diff --git a/Lib/php/php.swg b/Lib/php/php.swg
index 26944a1af..04b7075b7 100644
--- a/Lib/php/php.swg
+++ b/Lib/php/php.swg
@@ -125,14 +125,31 @@
   swig_acquire_ownership_obj((void*)$result, own);
 %}
 
-%typemap(in, phptype="SWIGTYPE") SWIGTYPE &,
-             SWIGTYPE &&
+%typemap(in, phptype="SWIGTYPE") SWIGTYPE &
 %{
   if (SWIG_ConvertPtr(&$input, (void **) &$1, $1_descriptor, 0) < 0 || $1 == NULL) {
     zend_type_error("Expected $1_descriptor for argument $argnum of $symname");
     return;
   }
 %}
+%typemap(in, fragment="") SWIGTYPE && (void *argp = 0, int res = 0, std::unique_ptr<$*1_ltype> rvrdeleter) %{
+  res = SWIG_ConvertPtr(&$input, &argp, $descriptor, SWIG_POINTER_RELEASE);
+  if (!SWIG_IsOK(res)) {
+    if (res == SWIG_ERROR_RELEASE_NOT_OWNED) {
+      zend_type_error("Cannot release ownership as memory is not owned for argument $argnum of $1_descriptor of $symname");
+      return;
+    } else {
+      zend_type_error("Expected $1_descriptor for argument $argnum of $symname");
+      return;
+    }
+  }
+  if (!argp) {
+    zend_type_error("Invalid null reference for argument $argnum of $1_descriptor of $symname");
+    return;
+  }
+  $1 = ($1_ltype)argp;
+  rvrdeleter.reset($1);
+%}
 
 %typemap(directorout) SWIGTYPE & ($1_ltype tmp),
 		      SWIGTYPE && ($1_ltype tmp)
diff --git a/Lib/php/std_auto_ptr.i b/Lib/php/std_auto_ptr.i
index 7df497e60..bd07dbdb5 100644
--- a/Lib/php/std_auto_ptr.i
+++ b/Lib/php/std_auto_ptr.i
@@ -13,10 +13,10 @@
   res = SWIG_ConvertPtr(&$input, &argp, $descriptor(TYPE *), SWIG_POINTER_RELEASE);
   if (!SWIG_IsOK(res)) {
     if (res == SWIG_ERROR_RELEASE_NOT_OWNED) {
-      zend_type_error("Cannot release ownership as memory is not owned for argument $argnum of type 'TYPE *' of $symname");
+      zend_type_error("Cannot release ownership as memory is not owned for argument $argnum of $descriptor(TYPE *) of $symname");
       return;
     } else {
-      zend_type_error("Expected TYPE * for argument $argnum of $symname");
+      zend_type_error("Expected $descriptor(TYPE *) for argument $argnum of $symname");
       return;
     }
   }
diff --git a/Lib/php/std_unique_ptr.i b/Lib/php/std_unique_ptr.i
index 591f580cb..168273663 100644
--- a/Lib/php/std_unique_ptr.i
+++ b/Lib/php/std_unique_ptr.i
@@ -13,10 +13,10 @@
   res = SWIG_ConvertPtr(&$input, &argp, $descriptor(TYPE *), SWIG_POINTER_RELEASE);
   if (!SWIG_IsOK(res)) {
     if (res == SWIG_ERROR_RELEASE_NOT_OWNED) {
-      zend_type_error("Cannot release ownership as memory is not owned for argument $argnum of type 'TYPE *' of $symname");
+      zend_type_error("Cannot release ownership as memory is not owned for argument $argnum of $descriptor(TYPE *) of $symname");
       return;
     } else {
-      zend_type_error("Expected TYPE * for argument $argnum of $symname");
+      zend_type_error("Expected $descriptor(TYPE *) for argument $argnum of $symname");
       return;
     }
   }
diff --git a/Lib/typemaps/swigtype.swg b/Lib/typemaps/swigtype.swg
index 0f35dc397..65f558a27 100644
--- a/Lib/typemaps/swigtype.swg
+++ b/Lib/typemaps/swigtype.swg
@@ -68,13 +68,18 @@
 #endif
 
 /* Rvalue reference */
-%typemap(in, noblock=1) SWIGTYPE && (void *argp = 0, int res = 0) {
-  res = SWIG_ConvertPtr($input, &argp, $descriptor, %convertptr_flags);
+%typemap(in, noblock=1, fragment="") SWIGTYPE && (void *argp = 0, int res = 0, std::unique_ptr<$*1_ltype> rvrdeleter) {
+  res = SWIG_ConvertPtr($input, &argp, $descriptor, SWIG_POINTER_RELEASE | %convertptr_flags);
   if (!SWIG_IsOK(res)) {
-    %argument_fail(res, "$type", $symname, $argnum); 
+    if (res == SWIG_ERROR_RELEASE_NOT_OWNED) {
+      %releasenotowned_fail(res, "$type", $symname, $argnum);
+    } else {
+      %argument_fail(res, "$type", $symname, $argnum); 
+    }
   }
   if (!argp) { %argument_nullref("$type", $symname, $argnum); }
   $1 = %reinterpret_cast(argp, $ltype);
+  rvrdeleter.reset($1);
 }
 %typemap(freearg) SWIGTYPE && ""
 

From 3f622ea65efcd8555aff39d6f985e763db20ed8a Mon Sep 17 00:00:00 2001
From: William S Fulton 
Date: Wed, 24 Aug 2022 08:39:36 +0100
Subject: [PATCH 05/16] SWIGTYPE && input typemaps now assume object has been
 moved - Go and OCaml

Not fully implemented and Untested.
Go's implementation needs fixing to fully support typemaps
before this can be done.
OCaml implementation does not have support for releasing ownership
which is required to add error checking preventing double deletes.
---
 Lib/go/go.swg       | 5 +++--
 Lib/ocaml/ocaml.swg | 5 +++--
 2 files changed, 6 insertions(+), 4 deletions(-)

diff --git a/Lib/go/go.swg b/Lib/go/go.swg
index bb7a471cc..348ae5f0d 100644
--- a/Lib/go/go.swg
+++ b/Lib/go/go.swg
@@ -388,8 +388,9 @@
 %typemap(gotype) SWIGTYPE &&
 %{$gotypename%}
 
-%typemap(in) SWIGTYPE &&
-%{ $1 = *($&1_ltype)&$input; %}
+%typemap(in, fragment="") SWIGTYPE && (std::unique_ptr<$*1_ltype> rvrdeleter)
+%{ $1 = *($&1_ltype)&$input;
+rvrdeleter.reset($1); %}
 
 %typemap(out) SWIGTYPE &&
 %{ *($&1_ltype)&$result = $1; %}
diff --git a/Lib/ocaml/ocaml.swg b/Lib/ocaml/ocaml.swg
index 7ca48ba08..09270509d 100644
--- a/Lib/ocaml/ocaml.swg
+++ b/Lib/ocaml/ocaml.swg
@@ -40,9 +40,10 @@
     $1 = ($ltype) caml_ptr_val($input,$1_descriptor);
 }
 
-%typemap(in) SWIGTYPE && {
+%typemap(in, fragment="") SWIGTYPE && (std::unique_ptr<$*1_ltype> rvrdeleter) %{
     $1 = ($ltype) caml_ptr_val($input,$1_descriptor);
-}
+    rvrdeleter.reset($1);
+%}
 
 %typemap(varin) SWIGTYPE & {
     $1 = *(($ltype) caml_ptr_val($input,$1_descriptor));

From 2cfd77b1c05dce14c0f15a710e4f9f4f1ff42d13 Mon Sep 17 00:00:00 2001
From: William S Fulton 
Date: Fri, 26 Aug 2022 23:20:13 +0100
Subject: [PATCH 06/16] Racket - NULL pointer handling

SWIG now converts a C/C++ NULL pointer into a null value by calling
scheme_make_null(), so that scheme's null? is true for a NULL C/C++
pointer value.

Consistency with Guile and needed for a pending commit for handling
NULL and std::unique_ptr.
---
 CHANGES.current                               |  4 ++++
 .../test-suite/guile/null_pointer_runme.scm   |  3 +++
 .../mzscheme/null_pointer_runme.scm           |  3 +++
 .../test-suite/schemerunme/null_pointer.scm   |  8 +++++++
 Lib/mzscheme/mzrun.swg                        | 22 +++++++++++--------
 5 files changed, 31 insertions(+), 9 deletions(-)
 create mode 100644 Examples/test-suite/guile/null_pointer_runme.scm
 create mode 100644 Examples/test-suite/mzscheme/null_pointer_runme.scm
 create mode 100644 Examples/test-suite/schemerunme/null_pointer.scm

diff --git a/CHANGES.current b/CHANGES.current
index edba0d6ec..bb4e85576 100644
--- a/CHANGES.current
+++ b/CHANGES.current
@@ -7,6 +7,10 @@ the issue number to the end of the URL: https://github.com/swig/swig/issues/
 Version 4.1.0 (in progress)
 ===========================
 
+2022-08-26: wsfulton
+            [Racket] SWIG now converts a C/C++ NULL pointer into a null value by calling
+            scheme_make_null(), so that scheme's null? is true for a NULL C/C++ pointer value.
+
 2022-08-18: wsfulton
             [Racket] Add support for std::unique_ptr in std_unique_ptr.i.
             Add support for std::auto_ptr in std_auto_ptr.i.
diff --git a/Examples/test-suite/guile/null_pointer_runme.scm b/Examples/test-suite/guile/null_pointer_runme.scm
new file mode 100644
index 000000000..cad65e898
--- /dev/null
+++ b/Examples/test-suite/guile/null_pointer_runme.scm
@@ -0,0 +1,3 @@
+(dynamic-call "scm_init_null_pointer_module" (dynamic-link "./libnull_pointer"))
+(load "testsuite.scm")
+(load "../schemerunme/null_pointer.scm")
diff --git a/Examples/test-suite/mzscheme/null_pointer_runme.scm b/Examples/test-suite/mzscheme/null_pointer_runme.scm
new file mode 100644
index 000000000..c16e8a0da
--- /dev/null
+++ b/Examples/test-suite/mzscheme/null_pointer_runme.scm
@@ -0,0 +1,3 @@
+(load-extension "null_pointer.so")
+
+(load "../schemerunme/null_pointer.scm")
diff --git a/Examples/test-suite/schemerunme/null_pointer.scm b/Examples/test-suite/schemerunme/null_pointer.scm
new file mode 100644
index 000000000..5b249ff50
--- /dev/null
+++ b/Examples/test-suite/schemerunme/null_pointer.scm
@@ -0,0 +1,8 @@
+(define null '())
+(unless (funk null)
+  (error "funk(null) does not return true"))
+
+(unless (null? (getnull))
+  (error "NULL pointer should be null"))
+
+(exit 0)
diff --git a/Lib/mzscheme/mzrun.swg b/Lib/mzscheme/mzrun.swg
index fed660dfb..57d040812 100644
--- a/Lib/mzscheme/mzrun.swg
+++ b/Lib/mzscheme/mzrun.swg
@@ -144,16 +144,20 @@ mz_free_swig(void *p, void *data) {
 
 static Scheme_Object *
 SWIG_MzScheme_NewPointerObj(void *ptr, swig_type_info *type, int owner) {
-  struct swig_mz_proxy *new_proxy;
-  new_proxy = (struct swig_mz_proxy *) scheme_malloc(sizeof(struct swig_mz_proxy));
-  new_proxy->mztype = swig_type;
-  new_proxy->type = type;
-  new_proxy->object = ptr;
-  new_proxy->own = owner & SWIG_POINTER_OWN;
-  if (new_proxy->own) {
-    scheme_add_finalizer(new_proxy, mz_free_swig, NULL);
+  if (ptr) {
+    struct swig_mz_proxy *new_proxy;
+    new_proxy = (struct swig_mz_proxy *) scheme_malloc(sizeof(struct swig_mz_proxy));
+    new_proxy->mztype = swig_type;
+    new_proxy->type = type;
+    new_proxy->object = ptr;
+    new_proxy->own = owner & SWIG_POINTER_OWN;
+    if (new_proxy->own) {
+      scheme_add_finalizer(new_proxy, mz_free_swig, NULL);
+    }
+    return (Scheme_Object *) new_proxy;
+  } else {
+    return scheme_make_null();
   }
-  return (Scheme_Object *) new_proxy;
 }
 
 static int

From ca9eebcb8dd38adb3fd6036932eb79d05b497dac Mon Sep 17 00:00:00 2001
From: William S Fulton 
Date: Wed, 31 Aug 2022 07:46:14 +0100
Subject: [PATCH 07/16] Octave - SWIG now marshalls a C/C++ NULL pointer into
 the null matrix, []

SWIG has always marshalled the null matrix into a NULL pointer; this remains
and now we have consistency in representing a NULL pointer.

This is a pre-requisite for a pending commit to fully support std::unique_ptr.
---
 CHANGES.current                                 |  7 ++++++-
 Doc/Manual/Octave.html                          |  4 ++++
 Examples/test-suite/octave/null_pointer_runme.m | 10 ++++++++++
 Lib/octave/octrun.swg                           | 11 +++++++----
 4 files changed, 27 insertions(+), 5 deletions(-)

diff --git a/CHANGES.current b/CHANGES.current
index bb4e85576..d06c0736b 100644
--- a/CHANGES.current
+++ b/CHANGES.current
@@ -7,8 +7,13 @@ the issue number to the end of the URL: https://github.com/swig/swig/issues/
 Version 4.1.0 (in progress)
 ===========================
 
+2022-08-28: wsfulton
+            [Octave] SWIG now marshalls a C/C++ NULL pointer into the null matrix, [].
+            SWIG has always marshalled the null matrix into a NULL pointer; this remains
+            and now we have consistency in representing a NULL pointer.
+
 2022-08-26: wsfulton
-            [Racket] SWIG now converts a C/C++ NULL pointer into a null value by calling
+            [Racket] SWIG now marshalls a C/C++ NULL pointer into a null value by calling
             scheme_make_null(), so that scheme's null? is true for a NULL C/C++ pointer value.
 
 2022-08-18: wsfulton
diff --git a/Doc/Manual/Octave.html b/Doc/Manual/Octave.html
index 151957cff..de39a1d96 100644
--- a/Doc/Manual/Octave.html
+++ b/Doc/Manual/Octave.html
@@ -363,6 +363,10 @@ octave:2> f=swigexample.fopen("not there", "r");
 error: value on right hand side of assignment is undefined
 error: evaluating assignment expression near line 2, column 2 
+

+NULL C/C++ pointers are represented by the Octave null matrix, []. +

+

30.3.6 Structures and C++ classes

diff --git a/Examples/test-suite/octave/null_pointer_runme.m b/Examples/test-suite/octave/null_pointer_runme.m index 72362f451..7a49d37f0 100644 --- a/Examples/test-suite/octave/null_pointer_runme.m +++ b/Examples/test-suite/octave/null_pointer_runme.m @@ -6,3 +6,13 @@ endif null_pointer; assert(funk([])); +null_ptr = getnull(); +assert(ismatrix(null_ptr)) +assert(size(null_ptr) == size([])) +assert(isequal([], null_ptr)) + +# Can't use isnull as a test due to null matrix not being copyable... +# n = [] +# isnull(n) # ans = 0 +# isnull([]) # ans = 1 +# isnull(getnull()) # ans = 0 diff --git a/Lib/octave/octrun.swg b/Lib/octave/octrun.swg index 71a907f9b..2973318c4 100644 --- a/Lib/octave/octrun.swg +++ b/Lib/octave/octrun.swg @@ -1547,12 +1547,15 @@ octave_value_typeinfo::register_binary_op(octave_value::op_##name,tid1,tid2,swig SWIGRUNTIME octave_value SWIG_Octave_NewPointerObj(void *ptr, swig_type_info *type, int flags) { int own = (flags &SWIG_POINTER_OWN) ? SWIG_POINTER_OWN : 0; + if (ptr) { #ifdef SWIG_DIRECTORS - Swig::Director *d = Swig::get_rtdir(ptr); - if (d && Swig::swig_director_get_self(d)) - return Swig::swig_director_get_self(d)->as_value(); + Swig::Director *d = Swig::get_rtdir(ptr); + if (d && Swig::swig_director_get_self(d)) + return Swig::swig_director_get_self(d)->as_value(); #endif - return Swig::swig_value_ref(new octave_swig_type(ptr, type, own)); + return Swig::swig_value_ref(new octave_swig_type(ptr, type, own)); + } + return octave_value(Matrix()); // null matrix } SWIGRUNTIME int SWIG_Octave_ConvertPtrAndOwn(octave_value ov, void **ptr, swig_type_info *type, int flags, int *own) { From 7934561874b4f5da4061c62b0c28f6dd35ed05ae Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Wed, 31 Aug 2022 08:35:55 +0100 Subject: [PATCH 08/16] Test/fixes to handle NULL pointer for unique_ptr/auto_ptr Also add missing unique_ptr tests for Lua and Racket. --- Examples/test-suite/cpp11_std_unique_ptr.i | 6 +- .../csharp/cpp11_std_unique_ptr_runme.cs | 8 ++ .../csharp/li_std_auto_ptr_runme.cs | 8 ++ .../d/cpp11_std_unique_ptr_runme.1.d | 8 ++ .../d/cpp11_std_unique_ptr_runme.2.d | 8 ++ .../test-suite/d/li_std_auto_ptr_runme.1.d | 8 ++ .../test-suite/d/li_std_auto_ptr_runme.2.d | 8 ++ .../java/cpp11_std_unique_ptr_runme.java | 8 ++ .../java/li_std_auto_ptr_runme.java | 8 ++ .../javascript/cpp11_std_unique_ptr_runme.js | 8 ++ .../javascript/li_std_auto_ptr_runme.js | 9 ++ Examples/test-suite/li_std_auto_ptr.i | 9 +- .../lua/cpp11_std_unique_ptr_runme.lua | 100 ++++++++++++++++++ .../test-suite/lua/li_std_auto_ptr_runme.lua | 7 ++ .../mzscheme/cpp11_std_unique_ptr_runme.scm | 100 ++++++++++++++++++ .../mzscheme/li_std_auto_ptr_runme.scm | 9 ++ .../octave/cpp11_std_unique_ptr_runme.m | 12 +++ .../test-suite/octave/li_std_auto_ptr_runme.m | 12 +++ .../perl5/cpp11_std_unique_ptr_runme.pl | 9 +- .../test-suite/perl5/li_std_auto_ptr_runme.pl | 9 +- .../php/cpp11_std_unique_ptr_runme.php | 7 ++ .../test-suite/php/li_std_auto_ptr_runme.php | 7 ++ .../python/cpp11_std_unique_ptr_runme.py | 8 ++ .../python/li_std_auto_ptr_runme.py | 8 ++ .../ruby/cpp11_std_unique_ptr_runme.rb | 6 ++ .../test-suite/ruby/li_std_auto_ptr_runme.rb | 6 ++ .../schemerunme/cpp11_std_unique_ptr.scm | 11 ++ .../schemerunme/li_std_auto_ptr.scm | 11 ++ .../tcl/cpp11_std_unique_ptr_runme.tcl | 9 ++ .../test-suite/tcl/li_std_auto_ptr_runme.tcl | 9 ++ Lib/lua/std_auto_ptr.i | 2 +- Lib/lua/std_unique_ptr.i | 2 +- 32 files changed, 434 insertions(+), 6 deletions(-) create mode 100644 Examples/test-suite/lua/cpp11_std_unique_ptr_runme.lua create mode 100644 Examples/test-suite/mzscheme/cpp11_std_unique_ptr_runme.scm diff --git a/Examples/test-suite/cpp11_std_unique_ptr.i b/Examples/test-suite/cpp11_std_unique_ptr.i index 414557507..f1ff84aae 100644 --- a/Examples/test-suite/cpp11_std_unique_ptr.i +++ b/Examples/test-suite/cpp11_std_unique_ptr.i @@ -63,7 +63,7 @@ std::string useKlassRawPtr(Klass* k) { std::string takeKlassUniquePtr(std::unique_ptr k) { // std::cout << "takeKlassUniquePtr " << std::hex << (Klass*)k.get() << std::endl; - std::string s(k->getLabel()); + std::string s(k ? k->getLabel() : "null smart pointer"); // std::cout << "takeKlassUniquePtr string: " << s << std::endl; return s; } @@ -84,6 +84,10 @@ std::unique_ptr makeKlassUniquePtr(const char* label) { return std::unique_ptr(new Klass(label)); } +std::unique_ptr makeNullUniquePtr() { + return std::unique_ptr(); +} + %} #endif diff --git a/Examples/test-suite/csharp/cpp11_std_unique_ptr_runme.cs b/Examples/test-suite/csharp/cpp11_std_unique_ptr_runme.cs index b24b5c204..04fafae42 100644 --- a/Examples/test-suite/csharp/cpp11_std_unique_ptr_runme.cs +++ b/Examples/test-suite/csharp/cpp11_std_unique_ptr_runme.cs @@ -87,6 +87,11 @@ public class cpp11_std_unique_ptr_runme { } // Dispose should not fail, even though already deleted checkCount(0); + cpp11_std_unique_ptr.takeKlassUniquePtr(null); + cpp11_std_unique_ptr.takeKlassUniquePtr(cpp11_std_unique_ptr.make_null()); + checkCount(0); + + // unique_ptr as output Klass k1 = cpp11_std_unique_ptr.makeKlassUniquePtr("first"); if (k1.getLabel() != "first") @@ -110,5 +115,8 @@ public class cpp11_std_unique_ptr_runme { k2.Dispose(); k2 = null; checkCount(0); + + if (cpp11_std_unique_ptr.makeNullUniquePtr() != null) + throw new Exception("null failure"); } } diff --git a/Examples/test-suite/csharp/li_std_auto_ptr_runme.cs b/Examples/test-suite/csharp/li_std_auto_ptr_runme.cs index ebbb23c69..a11b57fec 100644 --- a/Examples/test-suite/csharp/li_std_auto_ptr_runme.cs +++ b/Examples/test-suite/csharp/li_std_auto_ptr_runme.cs @@ -87,6 +87,11 @@ public class li_std_auto_ptr_runme { } // Dispose should not fail, even though already deleted checkCount(0); + li_std_auto_ptr.takeKlassAutoPtr(null); + li_std_auto_ptr.takeKlassAutoPtr(li_std_auto_ptr.make_null()); + checkCount(0); + + // auto_ptr as output Klass k1 = li_std_auto_ptr.makeKlassAutoPtr("first"); if (k1.getLabel() != "first") @@ -110,5 +115,8 @@ public class li_std_auto_ptr_runme { k2.Dispose(); k2 = null; checkCount(0); + + if (li_std_auto_ptr.makeNullAutoPtr() != null) + throw new Exception("null failure"); } } diff --git a/Examples/test-suite/d/cpp11_std_unique_ptr_runme.1.d b/Examples/test-suite/d/cpp11_std_unique_ptr_runme.1.d index ec89a0d28..b83392a85 100644 --- a/Examples/test-suite/d/cpp11_std_unique_ptr_runme.1.d +++ b/Examples/test-suite/d/cpp11_std_unique_ptr_runme.1.d @@ -87,6 +87,11 @@ void main() { } // dispose should not fail, even though already deleted checkCount(0); + takeKlassUniquePtr(null); + takeKlassUniquePtr(make_null()); + checkCount(0); + + // unique_ptr as output Klass k1 = makeKlassUniquePtr("first"); if (k1.getLabel() != "first") @@ -103,4 +108,7 @@ void main() { k2.dispose(); checkCount(0); + + if (makeNullUniquePtr() !is null) + throw new Exception("null failure"); } diff --git a/Examples/test-suite/d/cpp11_std_unique_ptr_runme.2.d b/Examples/test-suite/d/cpp11_std_unique_ptr_runme.2.d index ec89a0d28..b83392a85 100644 --- a/Examples/test-suite/d/cpp11_std_unique_ptr_runme.2.d +++ b/Examples/test-suite/d/cpp11_std_unique_ptr_runme.2.d @@ -87,6 +87,11 @@ void main() { } // dispose should not fail, even though already deleted checkCount(0); + takeKlassUniquePtr(null); + takeKlassUniquePtr(make_null()); + checkCount(0); + + // unique_ptr as output Klass k1 = makeKlassUniquePtr("first"); if (k1.getLabel() != "first") @@ -103,4 +108,7 @@ void main() { k2.dispose(); checkCount(0); + + if (makeNullUniquePtr() !is null) + throw new Exception("null failure"); } diff --git a/Examples/test-suite/d/li_std_auto_ptr_runme.1.d b/Examples/test-suite/d/li_std_auto_ptr_runme.1.d index 382f37e48..3ad86dc61 100644 --- a/Examples/test-suite/d/li_std_auto_ptr_runme.1.d +++ b/Examples/test-suite/d/li_std_auto_ptr_runme.1.d @@ -87,6 +87,11 @@ void main() { } // dispose should not fail, even though already deleted checkCount(0); + takeKlassAutoPtr(null); + takeKlassAutoPtr(make_null()); + checkCount(0); + + // auto_ptr as output Klass k1 = makeKlassAutoPtr("first"); if (k1.getLabel() != "first") @@ -103,4 +108,7 @@ void main() { k2.dispose(); checkCount(0); + + if (makeNullAutoPtr() !is null) + throw new Exception("null failure"); } diff --git a/Examples/test-suite/d/li_std_auto_ptr_runme.2.d b/Examples/test-suite/d/li_std_auto_ptr_runme.2.d index 382f37e48..3ad86dc61 100644 --- a/Examples/test-suite/d/li_std_auto_ptr_runme.2.d +++ b/Examples/test-suite/d/li_std_auto_ptr_runme.2.d @@ -87,6 +87,11 @@ void main() { } // dispose should not fail, even though already deleted checkCount(0); + takeKlassAutoPtr(null); + takeKlassAutoPtr(make_null()); + checkCount(0); + + // auto_ptr as output Klass k1 = makeKlassAutoPtr("first"); if (k1.getLabel() != "first") @@ -103,4 +108,7 @@ void main() { k2.dispose(); checkCount(0); + + if (makeNullAutoPtr() !is null) + throw new Exception("null failure"); } diff --git a/Examples/test-suite/java/cpp11_std_unique_ptr_runme.java b/Examples/test-suite/java/cpp11_std_unique_ptr_runme.java index 7fec2e0cd..6a8b9b8f2 100644 --- a/Examples/test-suite/java/cpp11_std_unique_ptr_runme.java +++ b/Examples/test-suite/java/cpp11_std_unique_ptr_runme.java @@ -107,6 +107,11 @@ public class cpp11_std_unique_ptr_runme { checkCount(0); } + cpp11_std_unique_ptr.takeKlassUniquePtr(null); + cpp11_std_unique_ptr.takeKlassUniquePtr(cpp11_std_unique_ptr.make_null()); + checkCount(0); + + // unique_ptr as output Klass k1 = cpp11_std_unique_ptr.makeKlassUniquePtr("first"); if (!k1.getLabel().equals("first")) @@ -125,5 +130,8 @@ public class cpp11_std_unique_ptr_runme { k2.delete(); k2 = null; checkCount(0); + + if (cpp11_std_unique_ptr.makeNullUniquePtr() != null) + throw new RuntimeException("null failure"); } } diff --git a/Examples/test-suite/java/li_std_auto_ptr_runme.java b/Examples/test-suite/java/li_std_auto_ptr_runme.java index 594908bbd..fd13b9215 100644 --- a/Examples/test-suite/java/li_std_auto_ptr_runme.java +++ b/Examples/test-suite/java/li_std_auto_ptr_runme.java @@ -107,6 +107,11 @@ public class li_std_auto_ptr_runme { checkCount(0); } + li_std_auto_ptr.takeKlassAutoPtr(null); + li_std_auto_ptr.takeKlassAutoPtr(li_std_auto_ptr.make_null()); + checkCount(0); + + // auto_ptr as output Klass k1 = li_std_auto_ptr.makeKlassAutoPtr("first"); if (!k1.getLabel().equals("first")) @@ -125,5 +130,8 @@ public class li_std_auto_ptr_runme { k2.delete(); k2 = null; checkCount(0); + + if (li_std_auto_ptr.makeNullAutoPtr() != null) + throw new RuntimeException("null failure"); } } diff --git a/Examples/test-suite/javascript/cpp11_std_unique_ptr_runme.js b/Examples/test-suite/javascript/cpp11_std_unique_ptr_runme.js index 567af2c29..8f358a4a7 100644 --- a/Examples/test-suite/javascript/cpp11_std_unique_ptr_runme.js +++ b/Examples/test-suite/javascript/cpp11_std_unique_ptr_runme.js @@ -90,6 +90,11 @@ var checkCount = function(expected_count) { checkCount(0); } +cpp11_std_unique_ptr.takeKlassUniquePtr(null); +cpp11_std_unique_ptr.takeKlassUniquePtr(cpp11_std_unique_ptr.make_null()); +checkCount(0); + + // unique_ptr as output k1 = cpp11_std_unique_ptr.makeKlassUniquePtr("first"); if (k1.getLabel() !== "first") @@ -110,3 +115,6 @@ if (k2.getLabel() !== "second") // Above not deleting the C++ object(node v12) - can't reliably control GC cpp11_std_unique_ptr.takeKlassUniquePtr(k2); checkCount(0); + +if (cpp11_std_unique_ptr.makeNullUniquePtr() != null) + throw new Error("null failure"); diff --git a/Examples/test-suite/javascript/li_std_auto_ptr_runme.js b/Examples/test-suite/javascript/li_std_auto_ptr_runme.js index 66eecffda..abe659878 100644 --- a/Examples/test-suite/javascript/li_std_auto_ptr_runme.js +++ b/Examples/test-suite/javascript/li_std_auto_ptr_runme.js @@ -90,6 +90,11 @@ var checkCount = function(expected_count) { checkCount(0); } +li_std_auto_ptr.takeKlassAutoPtr(null); +li_std_auto_ptr.takeKlassAutoPtr(li_std_auto_ptr.make_null()); +checkCount(0); + + // auto_ptr as output k1 = li_std_auto_ptr.makeKlassAutoPtr("first"); if (k1.getLabel() !== "first") @@ -109,4 +114,8 @@ if (k2.getLabel() !== "second") // delete k2; // Above not deleting the C++ object(node v12) - can't reliably control GC li_std_auto_ptr.takeKlassAutoPtr(k2); + +if (li_std_auto_ptr.makeNullAutoPtr() != null) + throw new Error("null failure"); + checkCount(0); diff --git a/Examples/test-suite/li_std_auto_ptr.i b/Examples/test-suite/li_std_auto_ptr.i index c02397c08..c76337c28 100644 --- a/Examples/test-suite/li_std_auto_ptr.i +++ b/Examples/test-suite/li_std_auto_ptr.i @@ -110,11 +110,14 @@ std::string useKlassRawPtr(Klass* k) { std::string takeKlassAutoPtr(std::auto_ptr k) { // std::cout << "takeKlassAutoPtr " << std::hex << (Klass*)k.get() << std::endl; - std::string s(k->getLabel()); + std::string s(k.get() ? k->getLabel() : "null smart pointer"); // std::cout << "takeKlassAutoPtr string: " << s << std::endl; return s; } +Klass *make_null() { + return 0; +} bool is_nullptr(Klass *p) { return p == 0; @@ -128,6 +131,10 @@ std::auto_ptr makeKlassAutoPtr(const char* label) { return std::auto_ptr(new Klass(label)); } +std::auto_ptr makeNullAutoPtr() { + return std::auto_ptr(); +} + %} #endif diff --git a/Examples/test-suite/lua/cpp11_std_unique_ptr_runme.lua b/Examples/test-suite/lua/cpp11_std_unique_ptr_runme.lua new file mode 100644 index 000000000..e22a09728 --- /dev/null +++ b/Examples/test-suite/lua/cpp11_std_unique_ptr_runme.lua @@ -0,0 +1,100 @@ +require("import") -- the import fn +import("cpp11_std_unique_ptr") -- import code + +-- catch "undefined" global variables +local env = _ENV -- Lua 5.2 +if not env then env = getfenv () end -- Lua 5.1 +setmetatable(env, {__index=function (t,i) error("undefined global variable `"..i.."'",2) end}) + + +function checkCount(expected_count) + -- call gc to make unused objects are collected + collectgarbage() + actual_count = cpp11_std_unique_ptr.Klass.getTotal_count() + if not (actual_count == expected_count) then + error("Counts incorrect, expected:"..expected_count.." actual:"..actual_count) + end +end + +--Test raw pointer handling involving virtual inheritance +kini = cpp11_std_unique_ptr.KlassInheritance("KlassInheritanceInput") +checkCount(1) +s = cpp11_std_unique_ptr.useKlassRawPtr(kini) +if not (s == "KlassInheritanceInput") then + error("Incorrect string: "..s) +end +kini = nil +checkCount(0) + +-- unique_ptr as input +kin = cpp11_std_unique_ptr.Klass("KlassInput") +checkCount(1) +s = cpp11_std_unique_ptr.takeKlassUniquePtr(kin) +checkCount(0) +if not (s == "KlassInput") then + error("Incorrect string: "..s) +end +if not (cpp11_std_unique_ptr.is_nullptr(kin)) then + error("is_nullptr failed") +end +kin = nil -- Should not fail, even though already deleted +checkCount(0) + +kin = cpp11_std_unique_ptr.Klass("KlassInput") +checkCount(1) +s = cpp11_std_unique_ptr.takeKlassUniquePtr(kin) +checkCount(0) +if not (s == "KlassInput") then + error("Incorrect string: "..s) +end +if not (cpp11_std_unique_ptr.is_nullptr(kin)) then + error("is_nullptr failed") +end +s, msg = pcall(function() cpp11_std_unique_ptr.takeKlassUniquePtr(kin) end) +assert(s == false and msg == "Cannot release ownership as memory is not owned for argument 1 of type 'Klass *' in takeKlassUniquePtr") + +kin = nil -- Should not fail, even though already deleted +checkCount(0) + +kin = cpp11_std_unique_ptr.Klass("KlassInput") +notowned = cpp11_std_unique_ptr.get_not_owned_ptr(kin) +s, msg = pcall(function() cpp11_std_unique_ptr.takeKlassUniquePtr(notowned) end) +assert(s == false and msg == "Cannot release ownership as memory is not owned for argument 1 of type 'Klass *' in takeKlassUniquePtr") +checkCount(1) +kin = nil +checkCount(0) + +kini = cpp11_std_unique_ptr.KlassInheritance("KlassInheritanceInput") +checkCount(1) +s = cpp11_std_unique_ptr.takeKlassUniquePtr(kini) +checkCount(0) +if not (s == "KlassInheritanceInput") then + error("Incorrect string: "..s) +end +if not (cpp11_std_unique_ptr.is_nullptr(kini)) then + error("is_nullptr failed") +end +kini = nil -- Should not fail, even though already deleted +checkCount(0) + +cpp11_std_unique_ptr.takeKlassUniquePtr(nil); +cpp11_std_unique_ptr.takeKlassUniquePtr(cpp11_std_unique_ptr.make_null()); +checkCount(0); + + +-- unique_ptr as output +k1 = cpp11_std_unique_ptr.makeKlassUniquePtr("first") +k2 = cpp11_std_unique_ptr.makeKlassUniquePtr("second") +checkCount(2) + +k1 = nil +checkCount(1) + +if not (k2:getLabel() == "second") then + error("wrong object label") +end + +k2 = nil +checkCount(0) + +assert(cpp11_std_unique_ptr.makeNullUniquePtr() == nil) diff --git a/Examples/test-suite/lua/li_std_auto_ptr_runme.lua b/Examples/test-suite/lua/li_std_auto_ptr_runme.lua index f677a6e4e..d605af692 100644 --- a/Examples/test-suite/lua/li_std_auto_ptr_runme.lua +++ b/Examples/test-suite/lua/li_std_auto_ptr_runme.lua @@ -77,6 +77,11 @@ end kini = nil -- Should not fail, even though already deleted checkCount(0) +li_std_auto_ptr.takeKlassAutoPtr(nil); +li_std_auto_ptr.takeKlassAutoPtr(li_std_auto_ptr.make_null()); +checkCount(0); + + -- auto_ptr as output k1 = li_std_auto_ptr.makeKlassAutoPtr("first") k2 = li_std_auto_ptr.makeKlassAutoPtr("second") @@ -91,3 +96,5 @@ end k2 = nil checkCount(0) + +assert(li_std_auto_ptr.makeNullAutoPtr() == nil) diff --git a/Examples/test-suite/mzscheme/cpp11_std_unique_ptr_runme.scm b/Examples/test-suite/mzscheme/cpp11_std_unique_ptr_runme.scm new file mode 100644 index 000000000..5996586af --- /dev/null +++ b/Examples/test-suite/mzscheme/cpp11_std_unique_ptr_runme.scm @@ -0,0 +1,100 @@ +(load-extension "cpp11_std_unique_ptr.so") +(require (lib "defmacro.ss")) + +; Copied from ../schemerunme/cpp11_std_unique_ptr.scm and modified for exceptions + +; Define an equivalent to Guile's gc procedure +(define-macro (gc) + `(collect-garbage 'major)) + +(define checkCount + (lambda (expected-count) + (define actual-count (Klass-getTotal-count)) + (unless (= actual-count expected-count) (error (format "Counts incorrect, expected:~a actual:~a" expected-count actual-count))))) + +; Test raw pointer handling involving virtual inheritance +(define kini (new-KlassInheritance "KlassInheritanceInput")) +(checkCount 1) +(define s (useKlassRawPtr kini)) +(unless (string=? s "KlassInheritanceInput") + (error "Incorrect string: " s)) +(set! kini '()) (gc) +(checkCount 0) + +; unique_ptr as input +(define kin (new-Klass "KlassInput")) +(checkCount 1) +(define s (takeKlassUniquePtr kin)) +(checkCount 0) +(unless (string=? s "KlassInput") + (error "Incorrect string: " s)) +(unless (is-nullptr kin) + (error "is_nullptr failed")) +(set! kini '()) (gc) ; Should not fail, even though already deleted +(checkCount 0) + +(define kin (new-Klass "KlassInput")) +(checkCount 1) +(define s (takeKlassUniquePtr kin)) +(checkCount 0) +(unless (string=? s "KlassInput") + (error "Incorrect string: " s)) +(unless (is-nullptr kin) + (error "is_nullptr failed")) + +(define exception_thrown "no exception thrown for kin") +(with-handlers ([exn:fail? (lambda (exn) + (set! exception_thrown (exn-message exn)))]) + (takeKlassUniquePtr kin)) +(unless (string=? exception_thrown "takeKlassUniquePtr: cannot release ownership as memory is not owned for argument 1 of type 'Klass *'") + (error "Wrong or no exception thrown: " exception_thrown)) +(set! kin '()) (gc) ; Should not fail, even though already deleted +(checkCount 0) + +(define kin (new-Klass "KlassInput")) +(define notowned (get-not-owned-ptr kin)) +(set! exception_thrown "no exception thrown for notowned") +(with-handlers ([exn:fail? (lambda (exn) + (set! exception_thrown (exn-message exn)))]) + (takeKlassUniquePtr notowned)) +(unless (string=? exception_thrown "takeKlassUniquePtr: cannot release ownership as memory is not owned for argument 1 of type 'Klass *'") + (error "Wrong or no exception thrown: " exception_thrown)) +(checkCount 1) +(set! kin '()) (gc) +(checkCount 0) + +(define kini (new-KlassInheritance "KlassInheritanceInput")) +(checkCount 1) +(define s (takeKlassUniquePtr kini)) +(checkCount 0) +(unless (string=? s "KlassInheritanceInput") + (error "Incorrect string: " s)) +(unless (is-nullptr kini) + (error "is_nullptr failed")) +(set! kini '()) (gc) ; Should not fail, even though already deleted +(checkCount 0) + +(define null '()) +(takeKlassUniquePtr null) +(takeKlassUniquePtr (make-null)) +(checkCount 0) + + +; unique_ptr as output +(define k1 (makeKlassUniquePtr "first")) +(define k2 (makeKlassUniquePtr "second")) +(checkCount 2) + +(set! k1 '()) (gc) +(checkCount 1) + +(unless (string=? (Klass-getLabel k2) "second") + (error "wrong object label" )) + +(set! k2 '()) (gc) +(checkCount 0) + +(unless (null? (makeNullUniquePtr)) + (error "null failure")) + +(exit 0) diff --git a/Examples/test-suite/mzscheme/li_std_auto_ptr_runme.scm b/Examples/test-suite/mzscheme/li_std_auto_ptr_runme.scm index 6335d4eb8..f52829163 100644 --- a/Examples/test-suite/mzscheme/li_std_auto_ptr_runme.scm +++ b/Examples/test-suite/mzscheme/li_std_auto_ptr_runme.scm @@ -74,6 +74,12 @@ (set! kini '()) (gc) ; Should not fail, even though already deleted (checkCount 0) +(define null '()) +(takeKlassAutoPtr null) +(takeKlassAutoPtr (make-null)) +(checkCount 0) + + ; auto_ptr as output (define k1 (makeKlassAutoPtr "first")) (define k2 (makeKlassAutoPtr "second")) @@ -88,4 +94,7 @@ (set! k2 '()) (gc) (checkCount 0) +(unless (null? (makeNullAutoPtr)) + (error "null failure")) + (exit 0) diff --git a/Examples/test-suite/octave/cpp11_std_unique_ptr_runme.m b/Examples/test-suite/octave/cpp11_std_unique_ptr_runme.m index 7d1c0e41a..fd72a522b 100644 --- a/Examples/test-suite/octave/cpp11_std_unique_ptr_runme.m +++ b/Examples/test-suite/octave/cpp11_std_unique_ptr_runme.m @@ -93,6 +93,13 @@ endif clear kini; # Should not fail, even though already deleted checkCount(0); +null = []; # NULL pointer +null_ptr = make_null(); +takeKlassUniquePtr([]); +takeKlassUniquePtr(null); +takeKlassUniquePtr(null_ptr); +checkCount(0); + # unique_ptr as output k1 = makeKlassUniquePtr("first"); @@ -112,3 +119,8 @@ endif clear k2; checkCount(0); + +null_smart_prt = makeNullUniquePtr(); +assert(ismatrix(null_smart_prt)) +assert(size(null_smart_prt) == size([])) +assert(isequal([], null_smart_prt)) diff --git a/Examples/test-suite/octave/li_std_auto_ptr_runme.m b/Examples/test-suite/octave/li_std_auto_ptr_runme.m index 832d75faf..c8d00afbd 100644 --- a/Examples/test-suite/octave/li_std_auto_ptr_runme.m +++ b/Examples/test-suite/octave/li_std_auto_ptr_runme.m @@ -93,6 +93,13 @@ endif clear kini; # Should not fail, even though already deleted checkCount(0); +null = []; # NULL pointer +null_ptr = make_null(); +takeKlassAutoPtr([]); +takeKlassAutoPtr(null); +takeKlassAutoPtr(null_ptr); +checkCount(0); + # auto_ptr as output k1 = makeKlassAutoPtr("first"); @@ -112,3 +119,8 @@ endif clear k2; checkCount(0); + +null_smart_prt = makeNullAutoPtr(); +assert(ismatrix(null_smart_prt)) +assert(size(null_smart_prt) == size([])) +assert(isequal([], null_smart_prt)) diff --git a/Examples/test-suite/perl5/cpp11_std_unique_ptr_runme.pl b/Examples/test-suite/perl5/cpp11_std_unique_ptr_runme.pl index 3e3e7f4b1..793ba733f 100644 --- a/Examples/test-suite/perl5/cpp11_std_unique_ptr_runme.pl +++ b/Examples/test-suite/perl5/cpp11_std_unique_ptr_runme.pl @@ -1,6 +1,6 @@ use strict; use warnings; -use Test::More tests => 28; +use Test::More tests => 30; BEGIN { use_ok('cpp11_std_unique_ptr') } require_ok('cpp11_std_unique_ptr'); @@ -73,6 +73,11 @@ sub checkCount { checkCount(0); } +cpp11_std_unique_ptr::takeKlassUniquePtr(undef); +cpp11_std_unique_ptr::takeKlassUniquePtr(cpp11_std_unique_ptr::make_null()); +checkCount(0); + + # unique_ptr as output my $k1 = cpp11_std_unique_ptr::makeKlassUniquePtr("first"); my $k2 = cpp11_std_unique_ptr::makeKlassUniquePtr("second"); @@ -85,3 +90,5 @@ is($k2->getLabel, "second", "proper label"); undef $k2; checkCount(0); + +is(cpp11_std_unique_ptr::makeNullUniquePtr(), undef); diff --git a/Examples/test-suite/perl5/li_std_auto_ptr_runme.pl b/Examples/test-suite/perl5/li_std_auto_ptr_runme.pl index cc71d9128..cd68ddedf 100644 --- a/Examples/test-suite/perl5/li_std_auto_ptr_runme.pl +++ b/Examples/test-suite/perl5/li_std_auto_ptr_runme.pl @@ -1,6 +1,6 @@ use strict; use warnings; -use Test::More tests => 28; +use Test::More tests => 30; BEGIN { use_ok('li_std_auto_ptr') } require_ok('li_std_auto_ptr'); @@ -73,6 +73,11 @@ sub checkCount { checkCount(0); } +li_std_auto_ptr::takeKlassAutoPtr(undef); +li_std_auto_ptr::takeKlassAutoPtr(li_std_auto_ptr::make_null()); +checkCount(0); + + # auto_ptr as output my $k1 = li_std_auto_ptr::makeKlassAutoPtr("first"); my $k2 = li_std_auto_ptr::makeKlassAutoPtr("second"); @@ -85,3 +90,5 @@ is($k2->getLabel, "second", "proper label"); undef $k2; checkCount(0); + +is(li_std_auto_ptr::makeNullAutoPtr(), undef); diff --git a/Examples/test-suite/php/cpp11_std_unique_ptr_runme.php b/Examples/test-suite/php/cpp11_std_unique_ptr_runme.php index 2b169e748..77b3f375a 100644 --- a/Examples/test-suite/php/cpp11_std_unique_ptr_runme.php +++ b/Examples/test-suite/php/cpp11_std_unique_ptr_runme.php @@ -79,6 +79,11 @@ try { $kini = NULL; # Should not fail, even though already deleted checkCount(0); +takeKlassUniquePtr(NULL); +takeKlassUniquePtr(make_null()); +checkCount(0); + + # unique_ptr as output $k1 = makeKlassUniquePtr("first"); $k2 = makeKlassUniquePtr("second"); @@ -92,4 +97,6 @@ check::equal($k2->getLabel(), "second", "proper label"); $k2 = NULL; checkCount(0); +check::equal(makeNullUniquePtr(), NULL); + check::done(); diff --git a/Examples/test-suite/php/li_std_auto_ptr_runme.php b/Examples/test-suite/php/li_std_auto_ptr_runme.php index 16129490a..caf604a3c 100644 --- a/Examples/test-suite/php/li_std_auto_ptr_runme.php +++ b/Examples/test-suite/php/li_std_auto_ptr_runme.php @@ -79,6 +79,11 @@ try { $kini = NULL; # Should not fail, even though already deleted checkCount(0); +takeKlassAutoPtr(NULL); +takeKlassAutoPtr(make_null()); +checkCount(0); + + # auto_ptr as output $k1 = makeKlassAutoPtr("first"); $k2 = makeKlassAutoPtr("second"); @@ -92,4 +97,6 @@ check::equal($k2->getLabel(), "second", "proper label"); $k2 = NULL; checkCount(0); +check::equal(makeNullAutoPtr(), NULL); + check::done(); diff --git a/Examples/test-suite/python/cpp11_std_unique_ptr_runme.py b/Examples/test-suite/python/cpp11_std_unique_ptr_runme.py index e822ddf09..ac3f52c23 100644 --- a/Examples/test-suite/python/cpp11_std_unique_ptr_runme.py +++ b/Examples/test-suite/python/cpp11_std_unique_ptr_runme.py @@ -77,6 +77,11 @@ if not is_nullptr(kini): del kini # Should not fail, even though already deleted checkCount(0) +takeKlassUniquePtr(None) +takeKlassUniquePtr(make_null()) +checkCount(0) + + # unique_ptr as output k1 = makeKlassUniquePtr("first") k2 = makeKlassUniquePtr("second") @@ -90,3 +95,6 @@ if k2.getLabel() != "second": del k2 checkCount(0) + +if (makeNullUniquePtr() != None): + raise RuntimeError("null failure") diff --git a/Examples/test-suite/python/li_std_auto_ptr_runme.py b/Examples/test-suite/python/li_std_auto_ptr_runme.py index 9c68f3e52..c3c5424c6 100644 --- a/Examples/test-suite/python/li_std_auto_ptr_runme.py +++ b/Examples/test-suite/python/li_std_auto_ptr_runme.py @@ -77,6 +77,11 @@ if not is_nullptr(kini): del kini # Should not fail, even though already deleted checkCount(0) +takeKlassAutoPtr(None) +takeKlassAutoPtr(make_null()) +checkCount(0) + + # auto_ptr as output k1 = makeKlassAutoPtr("first") k2 = makeKlassAutoPtr("second") @@ -90,3 +95,6 @@ if k2.getLabel() != "second": del k2 checkCount(0) + +if (makeNullAutoPtr() != None): + raise RuntimeError("null failure") diff --git a/Examples/test-suite/ruby/cpp11_std_unique_ptr_runme.rb b/Examples/test-suite/ruby/cpp11_std_unique_ptr_runme.rb index c623b45c5..fd43920b7 100644 --- a/Examples/test-suite/ruby/cpp11_std_unique_ptr_runme.rb +++ b/Examples/test-suite/ruby/cpp11_std_unique_ptr_runme.rb @@ -116,6 +116,11 @@ end kini = nil checkCount(0) +Cpp11_std_unique_ptr::takeKlassUniquePtr(nil) +Cpp11_std_unique_ptr::takeKlassUniquePtr(Cpp11_std_unique_ptr::make_null()) +checkCount(0) + + # unique_ptr as output k1 = Cpp11_std_unique_ptr::makeKlassUniquePtr("first") k2 = Cpp11_std_unique_ptr::makeKlassUniquePtr("second") @@ -131,3 +136,4 @@ gc_check(1) k2 = nil gc_check(0) +swig_assert_equal_simple(Cpp11_std_unique_ptr::makeNullUniquePtr(), nil) diff --git a/Examples/test-suite/ruby/li_std_auto_ptr_runme.rb b/Examples/test-suite/ruby/li_std_auto_ptr_runme.rb index 6780763c0..a6aa09be2 100644 --- a/Examples/test-suite/ruby/li_std_auto_ptr_runme.rb +++ b/Examples/test-suite/ruby/li_std_auto_ptr_runme.rb @@ -116,6 +116,11 @@ end kini = nil checkCount(0) +Li_std_auto_ptr::takeKlassAutoPtr(nil) +Li_std_auto_ptr::takeKlassAutoPtr(Li_std_auto_ptr::make_null()) +checkCount(0) + + # auto_ptr as output k1 = Li_std_auto_ptr::makeKlassAutoPtr("first") k2 = Li_std_auto_ptr::makeKlassAutoPtr("second") @@ -131,3 +136,4 @@ gc_check(1) k2 = nil gc_check(0) +swig_assert_equal_simple(Li_std_auto_ptr::makeNullAutoPtr(), nil) diff --git a/Examples/test-suite/schemerunme/cpp11_std_unique_ptr.scm b/Examples/test-suite/schemerunme/cpp11_std_unique_ptr.scm index 49184005a..b181ffcf3 100644 --- a/Examples/test-suite/schemerunme/cpp11_std_unique_ptr.scm +++ b/Examples/test-suite/schemerunme/cpp11_std_unique_ptr.scm @@ -58,6 +58,14 @@ (set! kini '()) (gc) ; Should not fail, even though already deleted (checkCount 0) +(define null '()) +(takeKlassUniquePtr null) +(define nullnil #nil) +(takeKlassUniquePtr nullnil) +(takeKlassUniquePtr (make-null)) +(checkCount 0) + + ; unique_ptr as output (define k1 (makeKlassUniquePtr "first")) (define k2 (makeKlassUniquePtr "second")) @@ -72,4 +80,7 @@ (set! k2 '()) (gc) (checkCount 0) +(unless (null? (makeNullUniquePtr)) + (error "null failure")) + (exit 0) diff --git a/Examples/test-suite/schemerunme/li_std_auto_ptr.scm b/Examples/test-suite/schemerunme/li_std_auto_ptr.scm index f23a00c41..cad0c8b80 100644 --- a/Examples/test-suite/schemerunme/li_std_auto_ptr.scm +++ b/Examples/test-suite/schemerunme/li_std_auto_ptr.scm @@ -58,6 +58,14 @@ (set! kini '()) (gc) ; Should not fail, even though already deleted (checkCount 0) +(define null '()) +(takeKlassAutoPtr null) +(define nullnil #nil) +(takeKlassAutoPtr nullnil) +(takeKlassAutoPtr (make-null)) +(checkCount 0) + + ; auto_ptr as output (define k1 (makeKlassAutoPtr "first")) (define k2 (makeKlassAutoPtr "second")) @@ -72,4 +80,7 @@ (set! k2 '()) (gc) (checkCount 0) +(unless (null? (makeNullAutoPtr)) + (error "null failure")) + (exit 0) diff --git a/Examples/test-suite/tcl/cpp11_std_unique_ptr_runme.tcl b/Examples/test-suite/tcl/cpp11_std_unique_ptr_runme.tcl index 380985f4e..d61ffb78a 100644 --- a/Examples/test-suite/tcl/cpp11_std_unique_ptr_runme.tcl +++ b/Examples/test-suite/tcl/cpp11_std_unique_ptr_runme.tcl @@ -126,6 +126,11 @@ if {![is_nullptr kini]} { kini -delete # Should not fail, even though already deleted checkCount 0 +takeKlassUniquePtr "NULL" +takeKlassUniquePtr [make_null] +checkCount 0 + + # unique_ptr as output set k1 [makeKlassUniquePtr "first"] set k2 [makeKlassUniquePtr "second"] @@ -140,3 +145,7 @@ if {[$k2 getLabel] != "second"} { $k2 -delete checkCount 0 + +if {[makeNullUniquePtr] != "NULL"} { + error "null failure" +} diff --git a/Examples/test-suite/tcl/li_std_auto_ptr_runme.tcl b/Examples/test-suite/tcl/li_std_auto_ptr_runme.tcl index f88be1aed..d7c019026 100644 --- a/Examples/test-suite/tcl/li_std_auto_ptr_runme.tcl +++ b/Examples/test-suite/tcl/li_std_auto_ptr_runme.tcl @@ -97,6 +97,11 @@ if {![is_nullptr kini]} { kini -delete # Should not fail, even though already deleted checkCount 0 +takeKlassAutoPtr "NULL" +takeKlassAutoPtr [make_null] +checkCount 0 + + # auto_ptr as output set k1 [makeKlassAutoPtr "first"] set k2 [makeKlassAutoPtr "second"] @@ -111,3 +116,7 @@ if {[$k2 getLabel] != "second"} { $k2 -delete checkCount 0 + +if {[makeNullAutoPtr] != "NULL"} { + error "null failure" +} diff --git a/Lib/lua/std_auto_ptr.i b/Lib/lua/std_auto_ptr.i index b0978963b..3952d6dd6 100644 --- a/Lib/lua/std_auto_ptr.i +++ b/Lib/lua/std_auto_ptr.i @@ -9,7 +9,7 @@ * ----------------------------------------------------------------------------- */ %define %auto_ptr(TYPE) -%typemap(in, checkfn="lua_isuserdata", noblock=1) std::auto_ptr< TYPE > (void *argp = 0, int res = 0) { +%typemap(in, checkfn="SWIG_isptrtype", noblock=1) std::auto_ptr< TYPE > (void *argp = 0, int res = 0) { res = SWIG_ConvertPtr(L, $input, &argp, $descriptor(TYPE *), SWIG_POINTER_RELEASE); if (!SWIG_IsOK(res)) { if (res == SWIG_ERROR_RELEASE_NOT_OWNED) { diff --git a/Lib/lua/std_unique_ptr.i b/Lib/lua/std_unique_ptr.i index de84b2497..4c1c1fde5 100644 --- a/Lib/lua/std_unique_ptr.i +++ b/Lib/lua/std_unique_ptr.i @@ -9,7 +9,7 @@ * ----------------------------------------------------------------------------- */ %define %unique_ptr(TYPE) -%typemap(in, checkfn="lua_isuserdata", noblock=1) std::unique_ptr< TYPE > (void *argp = 0, int res = 0) { +%typemap(in, checkfn="SWIG_isptrtype", noblock=1) std::unique_ptr< TYPE > (void *argp = 0, int res = 0) { res = SWIG_ConvertPtr(L, $input, &argp, $descriptor(TYPE *), SWIG_POINTER_RELEASE); if (!SWIG_IsOK(res)) { if (res == SWIG_ERROR_RELEASE_NOT_OWNED) { From 0b1d3e3e868514c9cd0674839ed94fbff5653a21 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Wed, 31 Aug 2022 22:28:18 +0100 Subject: [PATCH 09/16] Docs on rvalue parameter changes --- CHANGES.current | 10 ++++++ Doc/Manual/CPlusPlus11.html | 63 +++++++++++++++++++++++++++++++++++-- 2 files changed, 70 insertions(+), 3 deletions(-) diff --git a/CHANGES.current b/CHANGES.current index d06c0736b..1d99fd0fc 100644 --- a/CHANGES.current +++ b/CHANGES.current @@ -7,6 +7,16 @@ the issue number to the end of the URL: https://github.com/swig/swig/issues/ Version 4.1.0 (in progress) =========================== +2022-08-31: wsfulton + #999 Improve move semantics when using rvalue references. + The SWIGTYPE && input typemaps now assume the object has been moved. + + These typemaps have been changed assuming that after the function call, + the rvalue reference parameter has been moved. The parameter's proxy class + that owns the C++ object thus has the underlying pointer set to null + so that the (moved from, but still valid) C++ object cannot be used again + and the the object is additionally deleted. + 2022-08-28: wsfulton [Octave] SWIG now marshalls a C/C++ NULL pointer into the null matrix, []. SWIG has always marshalled the null matrix into a NULL pointer; this remains diff --git a/Doc/Manual/CPlusPlus11.html b/Doc/Manual/CPlusPlus11.html index 7618b6dbe..ca8d3d575 100644 --- a/Doc/Manual/CPlusPlus11.html +++ b/Doc/Manual/CPlusPlus11.html @@ -98,6 +98,7 @@ class MyClass { ... std::vector<int> numbers; public: + MyClass() : numbers() {} MyClass(MyClass &&other) : numbers(std::move(other.numbers)) {} MyClass & operator=(MyClass &&other) { numbers = std::move(other.numbers); @@ -107,8 +108,8 @@ public:

-Rvalue references are designed for C++ temporaries and so are not very useful when used from non-C++ target languages. -Generally you would just ignore them via %ignore before parsing the class. +Rvalue references are designed for C++ temporaries and are not particularly useful when used from non-C++ target languages. +You could just ignore them via %ignore before parsing the class. For example, ignore the move constructor:

@@ -117,7 +118,39 @@ For example, ignore the move constructor:

-The plan is to ignore move constructors by default in a future version of SWIG. Note that both normal assignment operators as well as move assignment operators are ignored by default in most target languages with the following warning: +However, if you do wrap a function/contructor with an rvalue reference and pass a proxy class to it, SWIG will assume that after the call, the rvalue reference parameter will have been 'moved'. +The proxy class passed as the rvalue reference, will own the underlying C++ object up until it is used as an rvalue reference parameter. +Afterwards, the proxy class will have the underlying C++ pointer set to the nullptr so that the proxy class instance cannot be used again and the underlying (moved from) C++ object will be deleted after the function/constructor call has returned. +

+ +

+In this way, the SWIG proxy class works much like an exclusively owned smart pointer (think of std::unique_ptr), passing ownership to the called C++ function/constructor. +Let's consider an example in Java using the wrapped proxy class from above: +

+ +
+MyClass mc = new MyClass();
+MyClass mc1 = new MyClass(mc); // move constructor
+MyClass mc2 = new MyClass(mc); // move constructor fails
+
+ +

+The second call to the move constructor will fail as the mc proxy instance has been moved. +Each target language handles the moved proxy class slightly differently, but typically you'll get an exception such as in Java: +

+ +
+
+Exception in thread "main" java.lang.RuntimeException: Cannot release ownership as memory is not owned
+	at MyClass.swigRelease(MyClass.java:27)
+	at MyClass.(MyClass.java:55)
+	at runme.main(runme.java:18)
+
+
+ + +

+Note that both normal copy assignment operators as well as move assignment operators are ignored by default in the target languages with the following warning:

@@ -126,6 +159,30 @@ example.i:18: Warning 503: Can't wrap 'operator =' unless renamed to a valid ide
+

+Using a %rename will remove the warning, however, a %rename makes the move constructor available from the target language: +

+
+%rename(MoveAssign) MyClass::operator=(MyClass &&);
+
+ +

+You can then use the move assignment operator, but like the move constructor example above, you cannot use +a proxy class once it has been moved: +

+ +
+MyClass mc = new MyClass();
+MyClass mc2 = mc.MoveAssign(mc);
+MyClass mc3 = mc.MoveAssign(mc); // Use of mc again will fail
+
+ +

+Compatibility note: +SWIG-4.1.0 changed the way that rvalue references were handled and implemented typemaps assuming that the +proxy class would transfer ownership of the underlying C++ object when a function/constructor with an rvalue reference parameter was called. +

+

7.2.1.1 Movable and move-only types

From 4c58bb558f3e4cd4a4870c6bb4a4a9af2e7ba5e0 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Fri, 2 Sep 2022 19:17:38 +0100 Subject: [PATCH 10/16] Fix Racket tests using schemerunme directory For out of source builds --- Examples/test-suite/mzscheme/integers_runme.scm | 2 +- Examples/test-suite/mzscheme/newobject1_runme.scm | 2 +- Examples/test-suite/mzscheme/null_pointer_runme.scm | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Examples/test-suite/mzscheme/integers_runme.scm b/Examples/test-suite/mzscheme/integers_runme.scm index 03c802166..e2e881702 100644 --- a/Examples/test-suite/mzscheme/integers_runme.scm +++ b/Examples/test-suite/mzscheme/integers_runme.scm @@ -6,4 +6,4 @@ ,form #f)) -(load "../schemerunme/integers.scm") +(load (build-path (path-only (path->complete-path (find-system-path 'run-file))) "../schemerunme/integers.scm")) diff --git a/Examples/test-suite/mzscheme/newobject1_runme.scm b/Examples/test-suite/mzscheme/newobject1_runme.scm index c2d7a9809..17333ed5c 100644 --- a/Examples/test-suite/mzscheme/newobject1_runme.scm +++ b/Examples/test-suite/mzscheme/newobject1_runme.scm @@ -6,4 +6,4 @@ (define-macro (gc) `(collect-garbage 'major)) -(load "../schemerunme/newobject1.scm") +(load (build-path (path-only (path->complete-path (find-system-path 'run-file))) "../schemerunme/newobject1.scm")) diff --git a/Examples/test-suite/mzscheme/null_pointer_runme.scm b/Examples/test-suite/mzscheme/null_pointer_runme.scm index c16e8a0da..35f83a4f8 100644 --- a/Examples/test-suite/mzscheme/null_pointer_runme.scm +++ b/Examples/test-suite/mzscheme/null_pointer_runme.scm @@ -1,3 +1,3 @@ (load-extension "null_pointer.so") -(load "../schemerunme/null_pointer.scm") +(load (build-path (path-only (path->complete-path (find-system-path 'run-file))) "../schemerunme/null_pointer.scm")) From de13a0020b11c7bc20da3c3cba9c8b211a869d73 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Sat, 3 Sep 2022 05:37:13 +0100 Subject: [PATCH 11/16] Ocaml typemap typo fix --- Lib/ocaml/ocaml.swg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib/ocaml/ocaml.swg b/Lib/ocaml/ocaml.swg index 09270509d..703b7e448 100644 --- a/Lib/ocaml/ocaml.swg +++ b/Lib/ocaml/ocaml.swg @@ -311,7 +311,7 @@ SIMPLE_MAP(unsigned long long,caml_val_ulong,caml_long_val); /* Array reference typemaps */ %apply SWIGTYPE & { SWIGTYPE ((&)[ANY]) } -%apply SWIGTYPE && { SWIGTYPE ((&)[ANY]) } +%apply SWIGTYPE && { SWIGTYPE ((&&)[ANY]) } /* const pointers */ %apply SWIGTYPE * { SWIGTYPE *const } From c6664703f6c83e64639d6c6b407831fff5b8fdfe Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Sat, 3 Sep 2022 05:49:13 +0100 Subject: [PATCH 12/16] std::auto_ptr emulation fix in test case --- Examples/test-suite/li_std_auto_ptr.i | 1 + 1 file changed, 1 insertion(+) diff --git a/Examples/test-suite/li_std_auto_ptr.i b/Examples/test-suite/li_std_auto_ptr.i index c76337c28..6de33f6cf 100644 --- a/Examples/test-suite/li_std_auto_ptr.i +++ b/Examples/test-suite/li_std_auto_ptr.i @@ -44,6 +44,7 @@ namespace std { auto_ptr(auto_ptr&& a) : ptr(a.ptr) { a.ptr = 0;} ~auto_ptr() { delete ptr; } T *release() { T *p = ptr; ptr = 0; return p; } + T* get() const { return ptr; } void reset(T *p = 0) { delete ptr; ptr = p; } T &operator*() const { return *ptr; } T *operator->() const { return ptr; } From 4588c416467741611aaf7af1820c3f9ae94e3b1c Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Sat, 3 Sep 2022 05:53:54 +0100 Subject: [PATCH 13/16] Temporarily remove rvalue reference python runtime test Work in progress: SWIGTYPE && out typemaps need to take ownership --- .../test-suite/python/cpp11_rvalue_reference_runme.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/Examples/test-suite/python/cpp11_rvalue_reference_runme.py b/Examples/test-suite/python/cpp11_rvalue_reference_runme.py index 85d64a581..46d43a9b1 100644 --- a/Examples/test-suite/python/cpp11_rvalue_reference_runme.py +++ b/Examples/test-suite/python/cpp11_rvalue_reference_runme.py @@ -21,7 +21,8 @@ if a.getAcopy() != 5: rvalueref = a.getAmove() -a.setAmove(rvalueref) -if a.getAcopy() != 5: - raise RunTimeError("after A::setAmove(): int A::getAcopy() value is ", a.getAcopy( - ), " should be 5") +# WIP: out rvalue references not yet modified for taking ownership +# a.setAmove(rvalueref) +# if a.getAcopy() != 5: +# raise RunTimeError("after A::setAmove(): int A::getAcopy() value is ", a.getAcopy( +# ), " should be 5") From 859264ab94daa50c35503f26e840f51e70924130 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Mon, 5 Sep 2022 08:23:58 +0100 Subject: [PATCH 14/16] Remove unnecessary const SWIGTYPE & typemap This is a duplicate of SWIGTYPE & and the typemap rules result in SWIGTYPE & being used if there is no const SWIGTYPE & tyemap. --- Lib/typemaps/swigtype.swg | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/Lib/typemaps/swigtype.swg b/Lib/typemaps/swigtype.swg index 65f558a27..e89e94b0b 100644 --- a/Lib/typemaps/swigtype.swg +++ b/Lib/typemaps/swigtype.swg @@ -56,15 +56,6 @@ { if (SWIG_IsNewObj(res$argnum)) %delete($1); } -#else -%typemap(in,noblock=1) const SWIGTYPE & (void *argp, int res = 0) { - res = SWIG_ConvertPtr($input, &argp, $descriptor, %convertptr_flags); - if (!SWIG_IsOK(res)) { - %argument_fail(res, "$type", $symname, $argnum); - } - if (!argp) { %argument_nullref("$type", $symname, $argnum); } - $1 = %reinterpret_cast(argp, $ltype); -} #endif /* Rvalue reference */ @@ -400,6 +391,7 @@ int res = SWIG_ConvertPtr($input, &vptr, $descriptor, SWIG_POINTER_NO_NULL); $1 = SWIG_CheckState(res); } + %typemap(typecheck,precedence=SWIG_TYPECHECK_POINTER,noblock=1) const SWIGTYPE && { void *vptr = 0; int res = SWIG_ConvertPtr($input, &vptr, $descriptor, SWIG_POINTER_NO_NULL); From c5495fea793a76093e436ffb702f00d233fd8e0a Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Mon, 5 Sep 2022 09:05:44 +0100 Subject: [PATCH 15/16] Remove broken %implicitconv for const SWIGTYPE && Typemaps should be for SWIGTYPE &&, not just const SWIGTYPE &&. Needs updating for new approach where the proxy object is moved for a parameter containing an rvalue reference. --- Lib/typemaps/swigtype.swg | 24 ------------------------ 1 file changed, 24 deletions(-) diff --git a/Lib/typemaps/swigtype.swg b/Lib/typemaps/swigtype.swg index e89e94b0b..42c9c54eb 100644 --- a/Lib/typemaps/swigtype.swg +++ b/Lib/typemaps/swigtype.swg @@ -74,30 +74,6 @@ } %typemap(freearg) SWIGTYPE && "" -#if defined(__cplusplus) && defined(%implicitconv_flag) -%typemap(in,noblock=1,implicitconv=1) const SWIGTYPE && (void *argp = 0, int res = 0) { - res = SWIG_ConvertPtr($input, &argp, $descriptor, %convertptr_flags | %implicitconv_flag); - if (!SWIG_IsOK(res)) { - %argument_fail(res, "$type", $symname, $argnum); - } - if (!argp) { %argument_nullref("$type", $symname, $argnum); } - $1 = %reinterpret_cast(argp, $ltype); -} -%typemap(freearg,noblock=1,match="in",implicitconv=1) const SWIGTYPE && -{ - if (SWIG_IsNewObj(res$argnum)) %delete($1); -} -#else -%typemap(in,noblock=1) const SWIGTYPE && (void *argp, int res = 0) { - res = SWIG_ConvertPtr($input, &argp, $descriptor, %convertptr_flags); - if (!SWIG_IsOK(res)) { - %argument_fail(res, "$type", $symname, $argnum); - } - if (!argp) { %argument_nullref("$type", $symname, $argnum); } - $1 = %reinterpret_cast(argp, $ltype); -} -#endif - /* By value */ #if defined(__cplusplus) && defined(%implicitconv_flag) %typemap(in,implicitconv=1) SWIGTYPE (void *argp, int res = 0) { From 2212af3f4f0906d84ef3aecf4812622af5f3ec7e Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Thu, 8 Sep 2022 08:46:32 +0100 Subject: [PATCH 16/16] rvalue reference outputs Document rvalue reference outputs behaviour Test rvalue reference outputs --- Doc/Manual/CPlusPlus11.html | 83 +++++++++++--- Doc/Manual/Contents.html | 2 + Examples/test-suite/common.mk | 2 +- .../test-suite/cpp11_rvalue_reference_move.i | 52 +++++++++ .../cpp11_rvalue_reference_move_input.i | 37 ------ ...s => cpp11_rvalue_reference_move_runme.cs} | 24 +++- ... => cpp11_rvalue_reference_move_runme.1.d} | 26 ++++- ... => cpp11_rvalue_reference_move_runme.2.d} | 26 ++++- ...pp11_rvalue_reference_move_input_runme.scm | 3 - .../cpp11_rvalue_reference_move_runme.scm | 3 + ...=> cpp11_rvalue_reference_move_runme.java} | 26 ++++- ...cpp11_rvalue_reference_move_input_runme.js | 67 ----------- .../cpp11_rvalue_reference_move_runme.js | 87 ++++++++++++++ ...pp11_rvalue_reference_move_input_runme.lua | 56 --------- .../lua/cpp11_rvalue_reference_move_runme.lua | 66 +++++++++++ ... => cpp11_rvalue_reference_move_runme.scm} | 18 ++- ....m => cpp11_rvalue_reference_move_runme.m} | 23 +++- ...cpp11_rvalue_reference_move_input_runme.pl | 56 --------- .../cpp11_rvalue_reference_move_runme.pl | 70 ++++++++++++ ... => cpp11_rvalue_reference_move_runme.php} | 16 +++ ...y => cpp11_rvalue_reference_move_runme.py} | 19 +++- .../python/cpp11_rvalue_reference_runme.py | 15 ++- ...cpp11_rvalue_reference_move_input_runme.rb | 87 -------------- .../ruby/cpp11_rvalue_reference_move_runme.rb | 106 ++++++++++++++++++ ...ut.scm => cpp11_rvalue_reference_move.scm} | 11 ++ ... => cpp11_rvalue_reference_move_runme.tcl} | 22 +++- 26 files changed, 659 insertions(+), 344 deletions(-) create mode 100644 Examples/test-suite/cpp11_rvalue_reference_move.i delete mode 100644 Examples/test-suite/cpp11_rvalue_reference_move_input.i rename Examples/test-suite/csharp/{cpp11_rvalue_reference_move_input_runme.cs => cpp11_rvalue_reference_move_runme.cs} (71%) rename Examples/test-suite/d/{cpp11_rvalue_reference_move_input_runme.1.d => cpp11_rvalue_reference_move_runme.1.d} (70%) rename Examples/test-suite/d/{cpp11_rvalue_reference_move_input_runme.2.d => cpp11_rvalue_reference_move_runme.2.d} (70%) delete mode 100644 Examples/test-suite/guile/cpp11_rvalue_reference_move_input_runme.scm create mode 100644 Examples/test-suite/guile/cpp11_rvalue_reference_move_runme.scm rename Examples/test-suite/java/{cpp11_rvalue_reference_move_input_runme.java => cpp11_rvalue_reference_move_runme.java} (72%) delete mode 100644 Examples/test-suite/javascript/cpp11_rvalue_reference_move_input_runme.js create mode 100644 Examples/test-suite/javascript/cpp11_rvalue_reference_move_runme.js delete mode 100644 Examples/test-suite/lua/cpp11_rvalue_reference_move_input_runme.lua create mode 100644 Examples/test-suite/lua/cpp11_rvalue_reference_move_runme.lua rename Examples/test-suite/mzscheme/{cpp11_rvalue_reference_move_input_runme.scm => cpp11_rvalue_reference_move_runme.scm} (70%) rename Examples/test-suite/octave/{cpp11_rvalue_reference_move_input_runme.m => cpp11_rvalue_reference_move_runme.m} (72%) delete mode 100644 Examples/test-suite/perl5/cpp11_rvalue_reference_move_input_runme.pl create mode 100644 Examples/test-suite/perl5/cpp11_rvalue_reference_move_runme.pl rename Examples/test-suite/php/{cpp11_rvalue_reference_move_input_runme.php => cpp11_rvalue_reference_move_runme.php} (74%) rename Examples/test-suite/python/{cpp11_rvalue_reference_move_input_runme.py => cpp11_rvalue_reference_move_runme.py} (70%) delete mode 100644 Examples/test-suite/ruby/cpp11_rvalue_reference_move_input_runme.rb create mode 100644 Examples/test-suite/ruby/cpp11_rvalue_reference_move_runme.rb rename Examples/test-suite/schemerunme/{cpp11_rvalue_reference_move_input.scm => cpp11_rvalue_reference_move.scm} (82%) rename Examples/test-suite/tcl/{cpp11_rvalue_reference_move_input_runme.tcl => cpp11_rvalue_reference_move_runme.tcl} (69%) diff --git a/Doc/Manual/CPlusPlus11.html b/Doc/Manual/CPlusPlus11.html index ca8d3d575..ba60fd3f8 100644 --- a/Doc/Manual/CPlusPlus11.html +++ b/Doc/Manual/CPlusPlus11.html @@ -16,6 +16,8 @@
+

7.2.1.1 Rvalue reference inputs

+ +

-However, if you do wrap a function/contructor with an rvalue reference and pass a proxy class to it, SWIG will assume that after the call, the rvalue reference parameter will have been 'moved'. +Rvalue reference parameters are useful as input parameters in C++ for implementing move semantics, such as, +in the move constructor and move assignment operator. +This type of usage can be useful from target languages too to avoid copying large objects. +

+ +

+If you do wrap a function/contructor with an rvalue reference parameter and pass a proxy class to it, SWIG will assume that after the call, the rvalue reference parameter object will have been 'moved'. The proxy class passed as the rvalue reference, will own the underlying C++ object up until it is used as an rvalue reference parameter. Afterwards, the proxy class will have the underlying C++ pointer set to the nullptr so that the proxy class instance cannot be used again and the underlying (moved from) C++ object will be deleted after the function/constructor call has returned.

@@ -136,15 +147,15 @@ MyClass mc2 = new MyClass(mc); // move constructor fails

The second call to the move constructor will fail as the mc proxy instance has been moved. -Each target language handles the moved proxy class slightly differently, but typically you'll get an exception such as in Java: +Each target language handles the moved proxy class slightly differently when attempting to move it again, but typically you'll get an exception such as in Java:

 Exception in thread "main" java.lang.RuntimeException: Cannot release ownership as memory is not owned
-	at MyClass.swigRelease(MyClass.java:27)
-	at MyClass.(MyClass.java:55)
-	at runme.main(runme.java:18)
+        at MyClass.swigRelease(MyClass.java:27)
+        at MyClass.<init>(MyClass.java:55)
+        at runme.main(runme.java:18)
 
@@ -160,15 +171,15 @@ example.i:18: Warning 503: Can't wrap 'operator =' unless renamed to a valid ide

-Using a %rename will remove the warning, however, a %rename makes the move constructor available from the target language: +Using a %rename will remove the warning and also makes the move assignment operator available from the target language:

 %rename(MoveAssign) MyClass::operator=(MyClass &&);
 

-You can then use the move assignment operator, but like the move constructor example above, you cannot use -a proxy class once it has been moved: +You can then use it, but like the move constructor example above, you cannot use +a proxy class once it has already been moved:

@@ -178,12 +189,58 @@ MyClass mc3 = mc.MoveAssign(mc); // Use of mc again will fail
 

-Compatibility note: -SWIG-4.1.0 changed the way that rvalue references were handled and implemented typemaps assuming that the -proxy class would transfer ownership of the underlying C++ object when a function/constructor with an rvalue reference parameter was called. +It is of course perfectly possible in C++ for a function/constructor to not move an object passed to it in an rvalue reference parameter. The assumption that SWIG makes would then not hold and customisation of the appropriate input typemaps would be required. +For scripting languages, this would be for the 'in' typemap and for the non-scripting languages additional typemaps such as the 'javain' typemap, which is used to set the memory ownership of the underlying C++ object for Java, would also need copying and modifying appropriately.

-

7.2.1.1 Movable and move-only types

+

+Compatibility note: +SWIG-4.1.0 changed the way that rvalue reference parameters were handled and implemented typemaps assuming that the +proxy class owns the underlying C++ object and transfers ownership of the object when a function/constructor with an rvalue reference parameter is called. +

+ +

7.2.1.2 Rvalue reference outputs

+ + +

+While rvalue reference parameter inputs are not uncommon in C++ and can be usefully utilised from target languages, this cannot be said for rvalue reference outputs. +Firstly, it is quite unusual in C++ to have functions that return an rvalue reference. +Secondly, these cases are nigh on impossible to use from a target language. +The main problem is these references are for C++ compiler temporaries used on the stack and the target languages use objects on the heap +and the concept of compiler temporary objects doesn't make sense from another language. +

+ +

+Using MyClass from earlier and this C++ code: +

+ +
+void use(MyClass &&mc);
+MyClass && get1();
+MyClass & get2();
+
+ +

+SWIG wraps the get1 and get2 functions more or less identically. +The returned references are converted into pointers that are not owned by the target language. +It means that the following perfectly valid C++ has no equivalent in any of the target languages: +

+ +
+use(get1());
+use(std::move(get2()));
+
+ +

+An attempt to call the equivalent use(get1()) from one of the target languages will result in the ownership failure mentioned in the previous section as the object being passed to the use function is not owned by the proxy class. +In order to own the object, it would need to be cloned for the object to move from the stack to the heap, for which an appropriate clone function would be required, but may not even be available. +Note that a move constructor or copy constructor may slice the object when inheritance is involved. +Alternatively, customising the input rvalue reference typemap, as mentioned in the previous section, could remove the ownership requirement. +Another alternative would be to modify the output rvalue reference typemap to always clone the rvalue reference object. +Fortunately you're highly unlikely to have to solve any of these issues! +

+ +

7.2.1.3 Movable and move-only types

diff --git a/Doc/Manual/Contents.html b/Doc/Manual/Contents.html index 3d8494184..2fdabafa6 100644 --- a/Doc/Manual/Contents.html +++ b/Doc/Manual/Contents.html @@ -298,6 +298,8 @@

  • Rvalue reference and move semantics
  • Generalized constant expressions diff --git a/Examples/test-suite/common.mk b/Examples/test-suite/common.mk index 6ca3aef22..950f62d98 100644 --- a/Examples/test-suite/common.mk +++ b/Examples/test-suite/common.mk @@ -609,7 +609,7 @@ CPP11_TEST_CASES += \ cpp11_rvalue_reference \ cpp11_rvalue_reference2 \ cpp11_rvalue_reference3 \ - cpp11_rvalue_reference_move_input \ + cpp11_rvalue_reference_move \ cpp11_sizeof_object \ cpp11_static_assert \ cpp11_std_array \ diff --git a/Examples/test-suite/cpp11_rvalue_reference_move.i b/Examples/test-suite/cpp11_rvalue_reference_move.i new file mode 100644 index 000000000..04cd2b869 --- /dev/null +++ b/Examples/test-suite/cpp11_rvalue_reference_move.i @@ -0,0 +1,52 @@ +%module cpp11_rvalue_reference_move + +// Testcase for testing rvalue reference input typemaps which assume the object is moved during a function call + +%include "cpp11_move_only_helper.i" + +%catches(std::string) MovableCopyable::check_numbers_match; + +%rename(MoveAssign) MovableCopyable::operator=(MovableCopyable &&); +%ignore MovableCopyable::operator=(const MovableCopyable &); // ignore copy assignment operator, keep move assignment operator +%ignore MovableCopyable::MovableCopyable(const MovableCopyable &); // ignore copy constructor, keep the move constructor + +%inline %{ +#include +using namespace std; + +bool trace = false; + +class MovableCopyable { + int num; +public: + MovableCopyable(int i = 0) : num(i) { if (trace) cout << "MovableCopyable(" << i << ")" << " " << this << endl; Counter::normal_constructor++; } + + MovableCopyable(const MovableCopyable &other) : num(other.num) { if (trace) cout << "MovableCopyable(const MovableCopyable &)" << " " << this << " " << &other << endl; Counter::copy_constructor++;} + MovableCopyable & operator=(const MovableCopyable &other) { if (trace) cout << "operator=(const MovableCopyable &)" << " " << this << " " << &other << endl; Counter::copy_assignment++; num = other.num; return *this; } + + MovableCopyable(MovableCopyable &&other) noexcept : num(std::move(other.num)) { if (trace) cout << "MovableCopyable(MovableCopyable &&)" << " " << this << endl; Counter::move_constructor++; } + MovableCopyable & operator=(MovableCopyable &&other) noexcept { if (trace) cout << "operator=(MovableCopyable &&)" << " " << this << endl; Counter::move_assignment++; num = std::move(other.num); return *this; } + ~MovableCopyable() { if (trace) cout << "~MovableCopyable()" << " " << this << endl; Counter::destructor++; } + + int getNum() { return num; } + + static void movein(MovableCopyable &&mcin) { + MovableCopyable mc = std::move(mcin); + } + + static MovableCopyable && moveout(int i) { + static MovableCopyable instance; + instance = MovableCopyable(i); + return std::move(instance); + } + + static bool is_nullptr(MovableCopyable *p) { + return p == nullptr; + } + + static void check_numbers_match(MovableCopyable *p, int expected_num) { + if (p->num != expected_num) + throw std::string("Numbers don't match"); + } +}; +%} diff --git a/Examples/test-suite/cpp11_rvalue_reference_move_input.i b/Examples/test-suite/cpp11_rvalue_reference_move_input.i deleted file mode 100644 index 69b4fd858..000000000 --- a/Examples/test-suite/cpp11_rvalue_reference_move_input.i +++ /dev/null @@ -1,37 +0,0 @@ -%module cpp11_rvalue_reference_move_input - -// Testcase for testing rvalue reference input typemaps which assume the object is moved during a function call - -%include "cpp11_move_only_helper.i" - -%rename(MoveAssign) MovableCopyable::operator=(MovableCopyable &&); -%ignore MovableCopyable::operator=(const MovableCopyable &); // ignore copy assignment operator, keep move assignment operator -%ignore MovableCopyable::MovableCopyable(const MovableCopyable &); // ignore copy constructor, keep the move constructor - -%inline %{ -#include -using namespace std; - -bool trace = false; - -class MovableCopyable { -public: - MovableCopyable(int i = 0) { if (trace) cout << "MovableCopyable(" << i << ")" << " " << this << endl; Counter::normal_constructor++; } - - MovableCopyable(const MovableCopyable &other) { if (trace) cout << "MovableCopyable(const MovableCopyable &)" << " " << this << " " << &other << endl; Counter::copy_constructor++;} - MovableCopyable & operator=(const MovableCopyable &other) { if (trace) cout << "operator=(const MovableCopyable &)" << " " << this << " " << &other << endl; Counter::copy_assignment++; return *this; } - - MovableCopyable(MovableCopyable &&other) noexcept { if (trace) cout << "MovableCopyable(MovableCopyable &&)" << " " << this << endl; Counter::move_constructor++; } - MovableCopyable & operator=(MovableCopyable &&other) noexcept { if (trace) cout << "operator=(MovableCopyable &&)" << " " << this << endl; Counter::move_assignment++; return *this; } - ~MovableCopyable() { if (trace) cout << "~MovableCopyable()" << " " << this << endl; Counter::destructor++; } - - static void movein(MovableCopyable &&mcin) { - MovableCopyable mc = std::move(mcin); - } - - static bool is_nullptr(MovableCopyable *p) { - return p == nullptr; - } -}; - -%} diff --git a/Examples/test-suite/csharp/cpp11_rvalue_reference_move_input_runme.cs b/Examples/test-suite/csharp/cpp11_rvalue_reference_move_runme.cs similarity index 71% rename from Examples/test-suite/csharp/cpp11_rvalue_reference_move_input_runme.cs rename to Examples/test-suite/csharp/cpp11_rvalue_reference_move_runme.cs index fb7024065..9b2660662 100644 --- a/Examples/test-suite/csharp/cpp11_rvalue_reference_move_input_runme.cs +++ b/Examples/test-suite/csharp/cpp11_rvalue_reference_move_runme.cs @@ -1,7 +1,7 @@ using System; -using cpp11_rvalue_reference_move_inputNamespace; +using cpp11_rvalue_reference_moveNamespace; -public class cpp11_rvalue_reference_move_input_runme { +public class cpp11_rvalue_reference_move_runme { public static void Main() { { // Function containing rvalue reference parameter @@ -62,5 +62,25 @@ public class cpp11_rvalue_reference_move_input_runme { throw new ApplicationException("Should have thrown null error"); Counter.check_counts(0, 0, 0, 0, 0, 0); } + + { + // output + Counter.reset_counts(); + MovableCopyable mc = MovableCopyable.moveout(1234); + Counter.check_counts(2, 0, 0, 0, 1, 1); + MovableCopyable.check_numbers_match(mc, 1234); + + bool exception_thrown = false; + try { + MovableCopyable.movein(mc); + } catch (ApplicationException e) { + if (!e.Message.Contains("Cannot release ownership as memory is not owned")) + throw new ApplicationException("incorrect exception message"); + exception_thrown = true; + } + if (!exception_thrown) + throw new ApplicationException("Should have thrown 'Cannot release ownership as memory is not owned' error"); + Counter.check_counts(2, 0, 0, 0, 1, 1); + } } } diff --git a/Examples/test-suite/d/cpp11_rvalue_reference_move_input_runme.1.d b/Examples/test-suite/d/cpp11_rvalue_reference_move_runme.1.d similarity index 70% rename from Examples/test-suite/d/cpp11_rvalue_reference_move_input_runme.1.d rename to Examples/test-suite/d/cpp11_rvalue_reference_move_runme.1.d index e6d23868c..da1d0da32 100644 --- a/Examples/test-suite/d/cpp11_rvalue_reference_move_input_runme.1.d +++ b/Examples/test-suite/d/cpp11_rvalue_reference_move_runme.1.d @@ -1,7 +1,7 @@ -module cpp11_rvalue_reference_move_input_runme; +module cpp11_rvalue_reference_move_runme; -import cpp11_rvalue_reference_move_input.Counter; -import cpp11_rvalue_reference_move_input.MovableCopyable; +import cpp11_rvalue_reference_move.Counter; +import cpp11_rvalue_reference_move.MovableCopyable; void main() { { @@ -63,4 +63,24 @@ void main() { throw new Exception("Should have thrown null error"); Counter.check_counts(0, 0, 0, 0, 0, 0); } + + { + // output + Counter.reset_counts(); + MovableCopyable mc = MovableCopyable.moveout(1234); + Counter.check_counts(2, 0, 0, 0, 1, 1); + MovableCopyable.check_numbers_match(mc, 1234); + + bool exception_thrown = false; + try { + MovableCopyable.movein(mc); + } catch (Exception e) { + if (!canFind(e.msg, "Cannot release ownership as memory is not owned")) + throw new Exception("incorrect exception message: " ~ e.msg); + exception_thrown = true; + } + if (!exception_thrown) + throw new Exception("Should have thrown 'Cannot release ownership as memory is not owned' error"); + Counter.check_counts(2, 0, 0, 0, 1, 1); + } } diff --git a/Examples/test-suite/d/cpp11_rvalue_reference_move_input_runme.2.d b/Examples/test-suite/d/cpp11_rvalue_reference_move_runme.2.d similarity index 70% rename from Examples/test-suite/d/cpp11_rvalue_reference_move_input_runme.2.d rename to Examples/test-suite/d/cpp11_rvalue_reference_move_runme.2.d index 5b3e6001a..342f34f94 100644 --- a/Examples/test-suite/d/cpp11_rvalue_reference_move_input_runme.2.d +++ b/Examples/test-suite/d/cpp11_rvalue_reference_move_runme.2.d @@ -1,7 +1,7 @@ -module cpp11_rvalue_reference_move_input_runme; +module cpp11_rvalue_reference_move_runme; -import cpp11_rvalue_reference_move_input.Counter; -import cpp11_rvalue_reference_move_input.MovableCopyable; +import cpp11_rvalue_reference_move.Counter; +import cpp11_rvalue_reference_move.MovableCopyable; import std.algorithm; void main() { @@ -64,4 +64,24 @@ void main() { throw new Exception("Should have thrown null error"); Counter.check_counts(0, 0, 0, 0, 0, 0); } + + { + // output + Counter.reset_counts(); + MovableCopyable mc = MovableCopyable.moveout(1234); + Counter.check_counts(2, 0, 0, 0, 1, 1); + MovableCopyable.check_numbers_match(mc, 1234); + + bool exception_thrown = false; + try { + MovableCopyable.movein(mc); + } catch (Exception e) { + if (!canFind(e.msg, "Cannot release ownership as memory is not owned")) + throw new Exception("incorrect exception message: " ~ e.msg); + exception_thrown = true; + } + if (!exception_thrown) + throw new Exception("Should have thrown 'Cannot release ownership as memory is not owned' error"); + Counter.check_counts(2, 0, 0, 0, 1, 1); + } } diff --git a/Examples/test-suite/guile/cpp11_rvalue_reference_move_input_runme.scm b/Examples/test-suite/guile/cpp11_rvalue_reference_move_input_runme.scm deleted file mode 100644 index 6beecf3e8..000000000 --- a/Examples/test-suite/guile/cpp11_rvalue_reference_move_input_runme.scm +++ /dev/null @@ -1,3 +0,0 @@ -(dynamic-call "scm_init_cpp11_rvalue_reference_move_input_module" (dynamic-link "./libcpp11_rvalue_reference_move_input")) -(load "testsuite.scm") -(load "../schemerunme/cpp11_rvalue_reference_move_input.scm") diff --git a/Examples/test-suite/guile/cpp11_rvalue_reference_move_runme.scm b/Examples/test-suite/guile/cpp11_rvalue_reference_move_runme.scm new file mode 100644 index 000000000..30ddff722 --- /dev/null +++ b/Examples/test-suite/guile/cpp11_rvalue_reference_move_runme.scm @@ -0,0 +1,3 @@ +(dynamic-call "scm_init_cpp11_rvalue_reference_move_module" (dynamic-link "./libcpp11_rvalue_reference_move")) +(load "testsuite.scm") +(load "../schemerunme/cpp11_rvalue_reference_move.scm") diff --git a/Examples/test-suite/java/cpp11_rvalue_reference_move_input_runme.java b/Examples/test-suite/java/cpp11_rvalue_reference_move_runme.java similarity index 72% rename from Examples/test-suite/java/cpp11_rvalue_reference_move_input_runme.java rename to Examples/test-suite/java/cpp11_rvalue_reference_move_runme.java index 2115bd7ca..70ba2432f 100644 --- a/Examples/test-suite/java/cpp11_rvalue_reference_move_input_runme.java +++ b/Examples/test-suite/java/cpp11_rvalue_reference_move_runme.java @@ -1,11 +1,11 @@ -import cpp11_rvalue_reference_move_input.*; +import cpp11_rvalue_reference_move.*; -public class cpp11_rvalue_reference_move_input_runme { +public class cpp11_rvalue_reference_move_runme { static { try { - System.loadLibrary("cpp11_rvalue_reference_move_input"); + System.loadLibrary("cpp11_rvalue_reference_move"); } catch (UnsatisfiedLinkError e) { System.err.println("Native code library failed to load. See the chapter on Dynamic Linking Problems in the SWIG Java documentation for help.\n" + e); System.exit(1); @@ -73,5 +73,25 @@ public class cpp11_rvalue_reference_move_input_runme { throw new RuntimeException("Should have thrown null error"); Counter.check_counts(0, 0, 0, 0, 0, 0); } + + { + // output + Counter.reset_counts(); + MovableCopyable mc = MovableCopyable.moveout(1234); + Counter.check_counts(2, 0, 0, 0, 1, 1); + MovableCopyable.check_numbers_match(mc, 1234); + + boolean exception_thrown = false; + try { + MovableCopyable.movein(mc); + } catch (RuntimeException e) { + if (!e.getMessage().contains("Cannot release ownership as memory is not owned")) + throw new RuntimeException("incorrect exception message"); + exception_thrown = true; + } + if (!exception_thrown) + throw new RuntimeException("Should have thrown 'Cannot release ownership as memory is not owned' error"); + Counter.check_counts(2, 0, 0, 0, 1, 1); + } } } diff --git a/Examples/test-suite/javascript/cpp11_rvalue_reference_move_input_runme.js b/Examples/test-suite/javascript/cpp11_rvalue_reference_move_input_runme.js deleted file mode 100644 index ba432d466..000000000 --- a/Examples/test-suite/javascript/cpp11_rvalue_reference_move_input_runme.js +++ /dev/null @@ -1,67 +0,0 @@ -var cpp11_rvalue_reference_move_input = require("cpp11_rvalue_reference_move_input"); - -{ - // Function containing rvalue reference parameter - cpp11_rvalue_reference_move_input.Counter.reset_counts(); - mo = new cpp11_rvalue_reference_move_input.MovableCopyable(222); - cpp11_rvalue_reference_move_input.Counter.check_counts(1, 0, 0, 0, 0, 0); - cpp11_rvalue_reference_move_input.MovableCopyable.movein(mo); - cpp11_rvalue_reference_move_input.Counter.check_counts(1, 0, 0, 1, 0, 2); - if (!cpp11_rvalue_reference_move_input.MovableCopyable.is_nullptr(mo)) - throw new Error("is_nullptr failed"); - delete mo; - cpp11_rvalue_reference_move_input.Counter.check_counts(1, 0, 0, 1, 0, 2); -} - -{ - // Move constructor test - cpp11_rvalue_reference_move_input.Counter.reset_counts(); - mo = new cpp11_rvalue_reference_move_input.MovableCopyable(222); - cpp11_rvalue_reference_move_input.Counter.check_counts(1, 0, 0, 0, 0, 0); - mo_moved = new cpp11_rvalue_reference_move_input.MovableCopyable(mo); - cpp11_rvalue_reference_move_input.Counter.check_counts(1, 0, 0, 1, 0, 1); - if (!cpp11_rvalue_reference_move_input.MovableCopyable.is_nullptr(mo)) - throw new Error("is_nullptr failed"); - delete mo; - cpp11_rvalue_reference_move_input.Counter.check_counts(1, 0, 0, 1, 0, 1); - // delete mo_moved; - // cpp11_rvalue_reference_move_input.Counter.check_counts(1, 0, 0, 1, 0, 2); - // Above not deleting the C++ object(node v12) - can't reliably control GC - use the movein function instead to delete - cpp11_rvalue_reference_move_input.MovableCopyable.movein(mo_moved); - cpp11_rvalue_reference_move_input.Counter.check_counts(1, 0, 0, 2, 0, 3); -} - -{ - // Move assignment operator test - cpp11_rvalue_reference_move_input.Counter.reset_counts(); - mo111 = new cpp11_rvalue_reference_move_input.MovableCopyable(111); - mo222 = new cpp11_rvalue_reference_move_input.MovableCopyable(222); - cpp11_rvalue_reference_move_input.Counter.check_counts(2, 0, 0, 0, 0, 0); - mo111.MoveAssign(mo222); - cpp11_rvalue_reference_move_input.Counter.check_counts(2, 0, 0, 0, 1, 1); - if (!cpp11_rvalue_reference_move_input.MovableCopyable.is_nullptr(mo222)) - throw new Error("is_nullptr failed"); - delete mo222; - cpp11_rvalue_reference_move_input.Counter.check_counts(2, 0, 0, 0, 1, 1); - // delete mo111; - // cpp11_rvalue_reference_move_input.Counter.check_counts(2, 0, 0, 0, 1, 2); - // Above not deleting the C++ object(node v12) - can't reliably control GC - use the movein function instead to delete - cpp11_rvalue_reference_move_input.MovableCopyable.movein(mo111); - cpp11_rvalue_reference_move_input.Counter.check_counts(2, 0, 0, 1, 1, 3); -} - -{ - // null check - cpp11_rvalue_reference_move_input.Counter.reset_counts(); - exception_thrown = false; - try { - cpp11_rvalue_reference_move_input.MovableCopyable.movein(null); - } catch (e) { - if (!e.message.includes("invalid null reference")) - throw new Error("incorrect exception message " + e.message); - exception_thrown = true; - } - if (!exception_thrown) - throw new Error("Should have thrown null error"); - cpp11_rvalue_reference_move_input.Counter.check_counts(0, 0, 0, 0, 0, 0); -} diff --git a/Examples/test-suite/javascript/cpp11_rvalue_reference_move_runme.js b/Examples/test-suite/javascript/cpp11_rvalue_reference_move_runme.js new file mode 100644 index 000000000..c642b4265 --- /dev/null +++ b/Examples/test-suite/javascript/cpp11_rvalue_reference_move_runme.js @@ -0,0 +1,87 @@ +var cpp11_rvalue_reference_move = require("cpp11_rvalue_reference_move"); + +{ + // Function containing rvalue reference parameter + cpp11_rvalue_reference_move.Counter.reset_counts(); + mo = new cpp11_rvalue_reference_move.MovableCopyable(222); + cpp11_rvalue_reference_move.Counter.check_counts(1, 0, 0, 0, 0, 0); + cpp11_rvalue_reference_move.MovableCopyable.movein(mo); + cpp11_rvalue_reference_move.Counter.check_counts(1, 0, 0, 1, 0, 2); + if (!cpp11_rvalue_reference_move.MovableCopyable.is_nullptr(mo)) + throw new Error("is_nullptr failed"); + delete mo; + cpp11_rvalue_reference_move.Counter.check_counts(1, 0, 0, 1, 0, 2); +} + +{ + // Move constructor test + cpp11_rvalue_reference_move.Counter.reset_counts(); + mo = new cpp11_rvalue_reference_move.MovableCopyable(222); + cpp11_rvalue_reference_move.Counter.check_counts(1, 0, 0, 0, 0, 0); + mo_moved = new cpp11_rvalue_reference_move.MovableCopyable(mo); + cpp11_rvalue_reference_move.Counter.check_counts(1, 0, 0, 1, 0, 1); + if (!cpp11_rvalue_reference_move.MovableCopyable.is_nullptr(mo)) + throw new Error("is_nullptr failed"); + delete mo; + cpp11_rvalue_reference_move.Counter.check_counts(1, 0, 0, 1, 0, 1); + // delete mo_moved; + // cpp11_rvalue_reference_move.Counter.check_counts(1, 0, 0, 1, 0, 2); + // Above not deleting the C++ object(node v12) - can't reliably control GC - use the movein function instead to delete + cpp11_rvalue_reference_move.MovableCopyable.movein(mo_moved); + cpp11_rvalue_reference_move.Counter.check_counts(1, 0, 0, 2, 0, 3); +} + +{ + // Move assignment operator test + cpp11_rvalue_reference_move.Counter.reset_counts(); + mo111 = new cpp11_rvalue_reference_move.MovableCopyable(111); + mo222 = new cpp11_rvalue_reference_move.MovableCopyable(222); + cpp11_rvalue_reference_move.Counter.check_counts(2, 0, 0, 0, 0, 0); + mo111.MoveAssign(mo222); + cpp11_rvalue_reference_move.Counter.check_counts(2, 0, 0, 0, 1, 1); + if (!cpp11_rvalue_reference_move.MovableCopyable.is_nullptr(mo222)) + throw new Error("is_nullptr failed"); + delete mo222; + cpp11_rvalue_reference_move.Counter.check_counts(2, 0, 0, 0, 1, 1); + // delete mo111; + // cpp11_rvalue_reference_move.Counter.check_counts(2, 0, 0, 0, 1, 2); + // Above not deleting the C++ object(node v12) - can't reliably control GC - use the movein function instead to delete + cpp11_rvalue_reference_move.MovableCopyable.movein(mo111); + cpp11_rvalue_reference_move.Counter.check_counts(2, 0, 0, 1, 1, 3); +} + +{ + // null check + cpp11_rvalue_reference_move.Counter.reset_counts(); + exception_thrown = false; + try { + cpp11_rvalue_reference_move.MovableCopyable.movein(null); + } catch (e) { + if (!e.message.includes("invalid null reference")) + throw new Error("incorrect exception message " + e.message); + exception_thrown = true; + } + if (!exception_thrown) + throw new Error("Should have thrown null error"); + cpp11_rvalue_reference_move.Counter.check_counts(0, 0, 0, 0, 0, 0); +} + +{ + // output + cpp11_rvalue_reference_move.Counter.reset_counts(); + var mc = cpp11_rvalue_reference_move.MovableCopyable.moveout(1234); + cpp11_rvalue_reference_move.Counter.check_counts(2, 0, 0, 0, 1, 1); + cpp11_rvalue_reference_move.MovableCopyable.check_numbers_match(mc, 1234); + + exception_thrown = false; + try { + cpp11_rvalue_reference_move.MovableCopyable.movein(mc); + } catch (e) { + if (!e.message.includes("cannot release ownership as memory is not owned")) + throw new Error("incorrect exception message " + e.message); + exception_thrown = true; + } + if (!exception_thrown) + throw new Error("Should have thrown 'Cannot release ownership as memory is not owned' error"); + cpp11_rvalue_reference_move.Counter.check_counts(2, 0, 0, 0, 1, 1); +} diff --git a/Examples/test-suite/lua/cpp11_rvalue_reference_move_input_runme.lua b/Examples/test-suite/lua/cpp11_rvalue_reference_move_input_runme.lua deleted file mode 100644 index 1dfeba7df..000000000 --- a/Examples/test-suite/lua/cpp11_rvalue_reference_move_input_runme.lua +++ /dev/null @@ -1,56 +0,0 @@ -require("import") -- the import fn -import("cpp11_rvalue_reference_move_input") -- import code - --- catch "undefined" global variables -local env = _ENV -- Lua 5.2 -if not env then env = getfenv () end -- Lua 5.1 -setmetatable(env, {__index=function (t,i) error("undefined global variable `"..i.."'",2) end}) - --- Function containing rvalue reference parameter -cpp11_rvalue_reference_move_input.Counter.reset_counts() -mo = cpp11_rvalue_reference_move_input.MovableCopyable(222) -cpp11_rvalue_reference_move_input.Counter.check_counts(1, 0, 0, 0, 0, 0) -cpp11_rvalue_reference_move_input.MovableCopyable.movein(mo) -cpp11_rvalue_reference_move_input.Counter.check_counts(1, 0, 0, 1, 0, 2) -if not (cpp11_rvalue_reference_move_input.MovableCopyable_is_nullptr(mo)) then - error("is_nullptr failed") -end -mo = nil -cpp11_rvalue_reference_move_input.Counter.check_counts(1, 0, 0, 1, 0, 2) - --- Move constructor test -cpp11_rvalue_reference_move_input.Counter.reset_counts() -mo = cpp11_rvalue_reference_move_input.MovableCopyable(222) -cpp11_rvalue_reference_move_input.Counter.check_counts(1, 0, 0, 0, 0, 0) -mo_moved = cpp11_rvalue_reference_move_input.MovableCopyable(mo) -cpp11_rvalue_reference_move_input.Counter.check_counts(1, 0, 0, 1, 0, 1) -if not (cpp11_rvalue_reference_move_input.MovableCopyable_is_nullptr(mo)) then - error("is_nullptr failed") -end -mo = nil -cpp11_rvalue_reference_move_input.Counter.check_counts(1, 0, 0, 1, 0, 1) -mo_moved = nil -collectgarbage() -- gc nudge needed here -cpp11_rvalue_reference_move_input.Counter.check_counts(1, 0, 0, 1, 0, 2) - --- Move assignment operator test -cpp11_rvalue_reference_move_input.Counter.reset_counts() -mo111 = cpp11_rvalue_reference_move_input.MovableCopyable(111) -mo222 = cpp11_rvalue_reference_move_input.MovableCopyable(222) -cpp11_rvalue_reference_move_input.Counter.check_counts(2, 0, 0, 0, 0, 0) -mo111:MoveAssign(mo222) -cpp11_rvalue_reference_move_input.Counter.check_counts(2, 0, 0, 0, 1, 1) -if not (cpp11_rvalue_reference_move_input.MovableCopyable_is_nullptr(mo222)) then - error("is_nullptr failed") -end -mo222 = nil -cpp11_rvalue_reference_move_input.Counter.check_counts(2, 0, 0, 0, 1, 1) -mo111 = nil -collectgarbage() -- gc nudge needed here -cpp11_rvalue_reference_move_input.Counter.check_counts(2, 0, 0, 0, 1, 2) - --- null check -cpp11_rvalue_reference_move_input.Counter.reset_counts() -s, msg = pcall(function() cpp11_rvalue_reference_move_input.MovableCopyable.movein(nil) end) -assert(s == false and msg:find("Error in MovableCopyable::movein (arg 1), expected 'MovableCopyable &&' got 'nil'", 1, true)) -cpp11_rvalue_reference_move_input.Counter.check_counts(0, 0, 0, 0, 0, 0) diff --git a/Examples/test-suite/lua/cpp11_rvalue_reference_move_runme.lua b/Examples/test-suite/lua/cpp11_rvalue_reference_move_runme.lua new file mode 100644 index 000000000..773760c8f --- /dev/null +++ b/Examples/test-suite/lua/cpp11_rvalue_reference_move_runme.lua @@ -0,0 +1,66 @@ +require("import") -- the import fn +import("cpp11_rvalue_reference_move") -- import code + +-- catch "undefined" global variables +local env = _ENV -- Lua 5.2 +if not env then env = getfenv () end -- Lua 5.1 +setmetatable(env, {__index=function (t,i) error("undefined global variable `"..i.."'",2) end}) + +-- Function containing rvalue reference parameter +cpp11_rvalue_reference_move.Counter.reset_counts() +mo = cpp11_rvalue_reference_move.MovableCopyable(222) +cpp11_rvalue_reference_move.Counter.check_counts(1, 0, 0, 0, 0, 0) +cpp11_rvalue_reference_move.MovableCopyable.movein(mo) +cpp11_rvalue_reference_move.Counter.check_counts(1, 0, 0, 1, 0, 2) +if not (cpp11_rvalue_reference_move.MovableCopyable_is_nullptr(mo)) then + error("is_nullptr failed") +end +mo = nil +cpp11_rvalue_reference_move.Counter.check_counts(1, 0, 0, 1, 0, 2) + +-- Move constructor test +cpp11_rvalue_reference_move.Counter.reset_counts() +mo = cpp11_rvalue_reference_move.MovableCopyable(222) +cpp11_rvalue_reference_move.Counter.check_counts(1, 0, 0, 0, 0, 0) +mo_moved = cpp11_rvalue_reference_move.MovableCopyable(mo) +cpp11_rvalue_reference_move.Counter.check_counts(1, 0, 0, 1, 0, 1) +if not (cpp11_rvalue_reference_move.MovableCopyable_is_nullptr(mo)) then + error("is_nullptr failed") +end +mo = nil +cpp11_rvalue_reference_move.Counter.check_counts(1, 0, 0, 1, 0, 1) +mo_moved = nil +collectgarbage() -- gc nudge needed here +cpp11_rvalue_reference_move.Counter.check_counts(1, 0, 0, 1, 0, 2) + +-- Move assignment operator test +cpp11_rvalue_reference_move.Counter.reset_counts() +mo111 = cpp11_rvalue_reference_move.MovableCopyable(111) +mo222 = cpp11_rvalue_reference_move.MovableCopyable(222) +cpp11_rvalue_reference_move.Counter.check_counts(2, 0, 0, 0, 0, 0) +mo111:MoveAssign(mo222) +cpp11_rvalue_reference_move.Counter.check_counts(2, 0, 0, 0, 1, 1) +if not (cpp11_rvalue_reference_move.MovableCopyable_is_nullptr(mo222)) then + error("is_nullptr failed") +end +mo222 = nil +cpp11_rvalue_reference_move.Counter.check_counts(2, 0, 0, 0, 1, 1) +mo111 = nil +collectgarbage() -- gc nudge needed here +cpp11_rvalue_reference_move.Counter.check_counts(2, 0, 0, 0, 1, 2) + +-- null check +cpp11_rvalue_reference_move.Counter.reset_counts() +s, msg = pcall(function() cpp11_rvalue_reference_move.MovableCopyable.movein(nil) end) +assert(s == false and msg:find("Error in MovableCopyable::movein (arg 1), expected 'MovableCopyable &&' got 'nil'", 1, true)) +cpp11_rvalue_reference_move.Counter.check_counts(0, 0, 0, 0, 0, 0) + +-- output +cpp11_rvalue_reference_move.Counter.reset_counts() +mc = cpp11_rvalue_reference_move.MovableCopyable.moveout(1234) +cpp11_rvalue_reference_move.Counter.check_counts(2, 0, 0, 0, 1, 1) +cpp11_rvalue_reference_move.MovableCopyable.check_numbers_match(mc, 1234) + +s, msg = pcall(function() cpp11_rvalue_reference_move.MovableCopyable.movein(mc) end) +assert(s == false and msg:find("Cannot release ownership as memory is not owned", 1, true)) +cpp11_rvalue_reference_move.Counter.check_counts(2, 0, 0, 0, 1, 1) diff --git a/Examples/test-suite/mzscheme/cpp11_rvalue_reference_move_input_runme.scm b/Examples/test-suite/mzscheme/cpp11_rvalue_reference_move_runme.scm similarity index 70% rename from Examples/test-suite/mzscheme/cpp11_rvalue_reference_move_input_runme.scm rename to Examples/test-suite/mzscheme/cpp11_rvalue_reference_move_runme.scm index 8e95a071b..6c68fef12 100644 --- a/Examples/test-suite/mzscheme/cpp11_rvalue_reference_move_input_runme.scm +++ b/Examples/test-suite/mzscheme/cpp11_rvalue_reference_move_runme.scm @@ -1,7 +1,7 @@ -(load-extension "cpp11_rvalue_reference_move_input.so") +(load-extension "cpp11_rvalue_reference_move.so") (require (lib "defmacro.ss")) -; Copied from ../schemerunme/cpp11_rvalue_reference_move_input.scm and modified for exceptions +; Copied from ../schemerunme/cpp11_rvalue_reference_move.scm and modified for exceptions ; Function containing rvalue reference parameter (Counter-reset-counts) @@ -51,4 +51,18 @@ (error (format "incorrect exception message: ~a" exception_thrown))) (Counter-check-counts 0 0 0 0 0 0) +; output +(Counter-reset-counts) +(define mc (MovableCopyable-moveout 1234)) +(Counter-check-counts 2 0 0 0 1 1) +(MovableCopyable-check-numbers-match mc 1234) + +(define exception_thrown "no exception thrown for kin") +(with-handlers ([exn:fail? (lambda (exn) + (set! exception_thrown (exn-message exn)))]) + (MovableCopyable-movein mc)) +(unless (string-contains? exception_thrown "cannot release ownership as memory is not owned") + (error (format "incorrect exception message: ~a" exception_thrown))) +(Counter-check-counts 2 0 0 0 1 1) + (exit 0) diff --git a/Examples/test-suite/octave/cpp11_rvalue_reference_move_input_runme.m b/Examples/test-suite/octave/cpp11_rvalue_reference_move_runme.m similarity index 72% rename from Examples/test-suite/octave/cpp11_rvalue_reference_move_input_runme.m rename to Examples/test-suite/octave/cpp11_rvalue_reference_move_runme.m index 28b80d920..5be37cc7e 100644 --- a/Examples/test-suite/octave/cpp11_rvalue_reference_move_input_runme.m +++ b/Examples/test-suite/octave/cpp11_rvalue_reference_move_runme.m @@ -3,7 +3,7 @@ if exist("crash_dumps_octave_core", "builtin") crash_dumps_octave_core(0); endif -cpp11_rvalue_reference_move_input +cpp11_rvalue_reference_move # Function containing rvalue reference parameter Counter.reset_counts(); @@ -62,3 +62,24 @@ if (!exception_thrown) error("Should have thrown null error"); endif Counter.check_counts(0, 0, 0, 0, 0, 0); + + +# output +Counter.reset_counts(); +mc = MovableCopyable.moveout(1234); +Counter.check_counts(2, 0, 0, 0, 1, 1); +MovableCopyable.check_numbers_match(mc, 1234); + +exception_thrown = false; +try + MovableCopyable.movein(mc); +catch e + if (isempty(strfind(e.message, "cannot release ownership as memory is not owned"))) + error("incorrect exception message: %s", e.message) + endif + exception_thrown = true; +end_try_catch +if (!exception_thrown) + error("Should have thrown 'Cannot release ownership as memory is not owned' error"); +endif +Counter.check_counts(2, 0, 0, 0, 1, 1); diff --git a/Examples/test-suite/perl5/cpp11_rvalue_reference_move_input_runme.pl b/Examples/test-suite/perl5/cpp11_rvalue_reference_move_input_runme.pl deleted file mode 100644 index f4f419c87..000000000 --- a/Examples/test-suite/perl5/cpp11_rvalue_reference_move_input_runme.pl +++ /dev/null @@ -1,56 +0,0 @@ -use strict; -use warnings; -use Test::More tests => 6; -BEGIN { use_ok('cpp11_rvalue_reference_move_input') } -require_ok('cpp11_rvalue_reference_move_input'); - -{ - # Function containing rvalue reference parameter - cpp11_rvalue_reference_move_input::Counter::reset_counts(); - my $mo = new cpp11_rvalue_reference_move_input::MovableCopyable(222); - cpp11_rvalue_reference_move_input::Counter::check_counts(1, 0, 0, 0, 0, 0); - cpp11_rvalue_reference_move_input::MovableCopyable::movein($mo); - cpp11_rvalue_reference_move_input::Counter::check_counts(1, 0, 0, 1, 0, 2); - is(cpp11_rvalue_reference_move_input::MovableCopyable::is_nullptr($mo), 1, "is_nullptr check"); - undef $mo; - cpp11_rvalue_reference_move_input::Counter::check_counts(1, 0, 0, 1, 0, 2); -} - -{ - # Move constructor test - cpp11_rvalue_reference_move_input::Counter::reset_counts(); - my $mo = new cpp11_rvalue_reference_move_input::MovableCopyable(222); - cpp11_rvalue_reference_move_input::Counter::check_counts(1, 0, 0, 0, 0, 0); - my $mo_moved = new cpp11_rvalue_reference_move_input::MovableCopyable($mo); - cpp11_rvalue_reference_move_input::Counter::check_counts(1, 0, 0, 1, 0, 1); - is(cpp11_rvalue_reference_move_input::MovableCopyable::is_nullptr($mo), 1, "is_nullptr check"); - undef $mo; - cpp11_rvalue_reference_move_input::Counter::check_counts(1, 0, 0, 1, 0, 1); - undef $mo_moved; - cpp11_rvalue_reference_move_input::Counter::check_counts(1, 0, 0, 1, 0, 2); -} - -{ - # Move assignment operator test - cpp11_rvalue_reference_move_input::Counter::reset_counts(); - my $mo111 = new cpp11_rvalue_reference_move_input::MovableCopyable(111); - my $mo222 = new cpp11_rvalue_reference_move_input::MovableCopyable(222); - cpp11_rvalue_reference_move_input::Counter::check_counts(2, 0, 0, 0, 0, 0); - $mo111->MoveAssign($mo222); - cpp11_rvalue_reference_move_input::Counter::check_counts(2, 0, 0, 0, 1, 1); - is(cpp11_rvalue_reference_move_input::MovableCopyable::is_nullptr($mo222), 1, "is_nullptr check"); - undef $mo222; - cpp11_rvalue_reference_move_input::Counter::check_counts(2, 0, 0, 0, 1, 1); - undef $mo111; - cpp11_rvalue_reference_move_input::Counter::check_counts(2, 0, 0, 0, 1, 2); -} - -{ - # null check - cpp11_rvalue_reference_move_input::Counter::reset_counts(); - eval { - cpp11_rvalue_reference_move_input::MovableCopyable::movein(undef); - }; - like($@, qr/\binvalid null reference/, "Should have thrown null error"); - cpp11_rvalue_reference_move_input::Counter::check_counts(0, 0, 0, 0, 0, 0); -} diff --git a/Examples/test-suite/perl5/cpp11_rvalue_reference_move_runme.pl b/Examples/test-suite/perl5/cpp11_rvalue_reference_move_runme.pl new file mode 100644 index 000000000..756691d03 --- /dev/null +++ b/Examples/test-suite/perl5/cpp11_rvalue_reference_move_runme.pl @@ -0,0 +1,70 @@ +use strict; +use warnings; +use Test::More tests => 7; +BEGIN { use_ok('cpp11_rvalue_reference_move') } +require_ok('cpp11_rvalue_reference_move'); + +{ + # Function containing rvalue reference parameter + cpp11_rvalue_reference_move::Counter::reset_counts(); + my $mo = new cpp11_rvalue_reference_move::MovableCopyable(222); + cpp11_rvalue_reference_move::Counter::check_counts(1, 0, 0, 0, 0, 0); + cpp11_rvalue_reference_move::MovableCopyable::movein($mo); + cpp11_rvalue_reference_move::Counter::check_counts(1, 0, 0, 1, 0, 2); + is(cpp11_rvalue_reference_move::MovableCopyable::is_nullptr($mo), 1, "is_nullptr check"); + undef $mo; + cpp11_rvalue_reference_move::Counter::check_counts(1, 0, 0, 1, 0, 2); +} + +{ + # Move constructor test + cpp11_rvalue_reference_move::Counter::reset_counts(); + my $mo = new cpp11_rvalue_reference_move::MovableCopyable(222); + cpp11_rvalue_reference_move::Counter::check_counts(1, 0, 0, 0, 0, 0); + my $mo_moved = new cpp11_rvalue_reference_move::MovableCopyable($mo); + cpp11_rvalue_reference_move::Counter::check_counts(1, 0, 0, 1, 0, 1); + is(cpp11_rvalue_reference_move::MovableCopyable::is_nullptr($mo), 1, "is_nullptr check"); + undef $mo; + cpp11_rvalue_reference_move::Counter::check_counts(1, 0, 0, 1, 0, 1); + undef $mo_moved; + cpp11_rvalue_reference_move::Counter::check_counts(1, 0, 0, 1, 0, 2); +} + +{ + # Move assignment operator test + cpp11_rvalue_reference_move::Counter::reset_counts(); + my $mo111 = new cpp11_rvalue_reference_move::MovableCopyable(111); + my $mo222 = new cpp11_rvalue_reference_move::MovableCopyable(222); + cpp11_rvalue_reference_move::Counter::check_counts(2, 0, 0, 0, 0, 0); + $mo111->MoveAssign($mo222); + cpp11_rvalue_reference_move::Counter::check_counts(2, 0, 0, 0, 1, 1); + is(cpp11_rvalue_reference_move::MovableCopyable::is_nullptr($mo222), 1, "is_nullptr check"); + undef $mo222; + cpp11_rvalue_reference_move::Counter::check_counts(2, 0, 0, 0, 1, 1); + undef $mo111; + cpp11_rvalue_reference_move::Counter::check_counts(2, 0, 0, 0, 1, 2); +} + +{ + # null check + cpp11_rvalue_reference_move::Counter::reset_counts(); + eval { + cpp11_rvalue_reference_move::MovableCopyable::movein(undef); + }; + like($@, qr/\binvalid null reference/, "Should have thrown null error"); + cpp11_rvalue_reference_move::Counter::check_counts(0, 0, 0, 0, 0, 0); +} + +{ + # output + cpp11_rvalue_reference_move::Counter::reset_counts(); + my $mc = cpp11_rvalue_reference_move::MovableCopyable::moveout(1234); + cpp11_rvalue_reference_move::Counter::check_counts(2, 0, 0, 0, 1, 1); + cpp11_rvalue_reference_move::MovableCopyable::check_numbers_match($mc, 1234); + + eval { + cpp11_rvalue_reference_move::MovableCopyable::movein($mc); + }; + like($@, qr/\bcannot release ownership as memory is not owned\b/, "Should have thrown 'Cannot release ownership as memory is not owned' error"); + cpp11_rvalue_reference_move::Counter::check_counts(2, 0, 0, 0, 1, 1); +} diff --git a/Examples/test-suite/php/cpp11_rvalue_reference_move_input_runme.php b/Examples/test-suite/php/cpp11_rvalue_reference_move_runme.php similarity index 74% rename from Examples/test-suite/php/cpp11_rvalue_reference_move_input_runme.php rename to Examples/test-suite/php/cpp11_rvalue_reference_move_runme.php index 176134682..38bb758ed 100644 --- a/Examples/test-suite/php/cpp11_rvalue_reference_move_input_runme.php +++ b/Examples/test-suite/php/cpp11_rvalue_reference_move_runme.php @@ -61,4 +61,20 @@ try { check::equal($exception_thrown, true, "Should have thrown null error"); Counter::check_counts(0, 0, 0, 0, 0, 0); +# output +Counter::reset_counts(); +$mc = MovableCopyable::moveout(1234); +Counter::check_counts(2, 0, 0, 0, 1, 1); +MovableCopyable::check_numbers_match($mc, 1234); + +$exception_thrown = false; +try { + MovableCopyable::movein($mc); +} catch (TypeError $e) { + check::str_contains($e->getMessage(), "Cannot release ownership as memory is not owned", "incorrect exception message: {$e->getMessage()}"); + $exception_thrown = true; +} +check::equal($exception_thrown, true, "Should have thrown 'Cannot release ownership as memory is not owned' error"); +Counter::check_counts(2, 0, 0, 0, 1, 1); + check::done(); diff --git a/Examples/test-suite/python/cpp11_rvalue_reference_move_input_runme.py b/Examples/test-suite/python/cpp11_rvalue_reference_move_runme.py similarity index 70% rename from Examples/test-suite/python/cpp11_rvalue_reference_move_input_runme.py rename to Examples/test-suite/python/cpp11_rvalue_reference_move_runme.py index 7db7b4c3b..43e586f9a 100644 --- a/Examples/test-suite/python/cpp11_rvalue_reference_move_input_runme.py +++ b/Examples/test-suite/python/cpp11_rvalue_reference_move_runme.py @@ -1,4 +1,4 @@ -from cpp11_rvalue_reference_move_input import * +from cpp11_rvalue_reference_move import * # Function containing rvalue reference parameter Counter.reset_counts() @@ -50,3 +50,20 @@ except ValueError as e: if not exception_thrown: raise RuntimeError("Should have thrown null error") Counter.check_counts(0, 0, 0, 0, 0, 0) + +# output +Counter.reset_counts() +mc = MovableCopyable.moveout(1234) +Counter.check_counts(2, 0, 0, 0, 1, 1) +MovableCopyable.check_numbers_match(mc, 1234) + +exception_thrown = False +try: + MovableCopyable.movein(mc) +except RuntimeError as e: + if "cannot release ownership as memory is not owned" not in str(e): + raise RuntimeError("incorrect exception message:" + str(e)) + exception_thrown = True +if not exception_thrown: + raise RuntimeError("Should have thrown 'Cannot release ownership as memory is not owned' error") +Counter.check_counts(2, 0, 0, 0, 1, 1) diff --git a/Examples/test-suite/python/cpp11_rvalue_reference_runme.py b/Examples/test-suite/python/cpp11_rvalue_reference_runme.py index 46d43a9b1..fad8b76d6 100644 --- a/Examples/test-suite/python/cpp11_rvalue_reference_runme.py +++ b/Examples/test-suite/python/cpp11_rvalue_reference_runme.py @@ -4,25 +4,24 @@ a = cpp11_rvalue_reference.A() a.setAcopy(5) if a.getAcopy() != 5: - raise RunTimeError("int A::getAcopy() value is ", + raise RuntimeError("int A::getAcopy() value is ", a.getAcopy(), " should be 5") ptr = a.getAptr() a.setAptr(ptr) if a.getAcopy() != 5: - raise RunTimeError("after A::setAptr(): int A::getAcopy() value is ", a.getAcopy( + raise RuntimeError("after A::setAptr(): int A::getAcopy() value is ", a.getAcopy( ), " should be 5") a.setAref(ptr) if a.getAcopy() != 5: - raise RunTimeError("after A::setAref(): int A::getAcopy() value is ", a.getAcopy( + raise RuntimeError("after A::setAref(): int A::getAcopy() value is ", a.getAcopy( ), " should be 5") rvalueref = a.getAmove() -# WIP: out rvalue references not yet modified for taking ownership -# a.setAmove(rvalueref) -# if a.getAcopy() != 5: -# raise RunTimeError("after A::setAmove(): int A::getAcopy() value is ", a.getAcopy( -# ), " should be 5") +a.setAref(rvalueref) +if a.getAcopy() != 5: + raise RuntimeError("after A::setAmove(): int A::getAcopy() value is ", a.getAcopy( + ), " should be 5") diff --git a/Examples/test-suite/ruby/cpp11_rvalue_reference_move_input_runme.rb b/Examples/test-suite/ruby/cpp11_rvalue_reference_move_input_runme.rb deleted file mode 100644 index 4b7347d43..000000000 --- a/Examples/test-suite/ruby/cpp11_rvalue_reference_move_input_runme.rb +++ /dev/null @@ -1,87 +0,0 @@ -#!/usr/bin/env ruby - -require 'swig_assert' - -require 'cpp11_rvalue_reference_move_input' - -# Function containing rvalue reference parameter -Cpp11_rvalue_reference_move_input::Counter.reset_counts() -mo = Cpp11_rvalue_reference_move_input::MovableCopyable.new(222) -Cpp11_rvalue_reference_move_input::Counter.check_counts(1, 0, 0, 0, 0, 0) -Cpp11_rvalue_reference_move_input::MovableCopyable.movein(mo) -Cpp11_rvalue_reference_move_input::Counter.check_counts(1, 0, 0, 1, 0, 2) -exception_thrown = false -begin - Cpp11_rvalue_reference_move_input::MovableCopyable.is_nullptr(mo) -rescue ObjectPreviouslyDeleted - exception_thrown = true -end -if (!exception_thrown) - raise RuntimeError, "is_nullptr failed to throw" -end -mo = nil -Cpp11_rvalue_reference_move_input::Counter.check_counts(1, 0, 0, 1, 0, 2) - -# Move constructor test -Cpp11_rvalue_reference_move_input::Counter.reset_counts() -mo = Cpp11_rvalue_reference_move_input::MovableCopyable.new(222) -Cpp11_rvalue_reference_move_input::Counter.check_counts(1, 0, 0, 0, 0, 0) -mo_moved = Cpp11_rvalue_reference_move_input::MovableCopyable.new(mo) -Cpp11_rvalue_reference_move_input::Counter.check_counts(1, 0, 0, 1, 0, 1) -exception_thrown = false -begin - Cpp11_rvalue_reference_move_input::MovableCopyable.is_nullptr(mo) -rescue ObjectPreviouslyDeleted - exception_thrown = true -end -if (!exception_thrown) - raise RuntimeError, "is_nullptr failed to throw" -end -mo = nil -Cpp11_rvalue_reference_move_input::Counter.check_counts(1, 0, 0, 1, 0, 1) -# mo_moved = nil -# Cpp11_rvalue_reference_move_input::Counter.check_counts(1, 0, 0, 1, 0, 2) -# Above not deleting the C++ object(node v12) - can't reliably control GC - use the movein function instead to delete -Cpp11_rvalue_reference_move_input::MovableCopyable.movein(mo_moved) -Cpp11_rvalue_reference_move_input::Counter.check_counts(1, 0, 0, 2, 0, 3) - -# Move assignment operator test -Cpp11_rvalue_reference_move_input::Counter.reset_counts() -mo111 = Cpp11_rvalue_reference_move_input::MovableCopyable.new(111) -mo222 = Cpp11_rvalue_reference_move_input::MovableCopyable.new(222) -Cpp11_rvalue_reference_move_input::Counter.check_counts(2, 0, 0, 0, 0, 0) -mo111.MoveAssign(mo222) -Cpp11_rvalue_reference_move_input::Counter.check_counts(2, 0, 0, 0, 1, 1) -exception_thrown = false -begin - Cpp11_rvalue_reference_move_input::MovableCopyable.is_nullptr(mo222) -rescue ObjectPreviouslyDeleted - exception_thrown = true -end -if (!exception_thrown) - raise RuntimeError, "is_nullptr failed to throw" -end -mo222 = nil -Cpp11_rvalue_reference_move_input::Counter.check_counts(2, 0, 0, 0, 1, 1) -# mo111 = nil -# Cpp11_rvalue_reference_move_input::Counter.check_counts(2, 0, 0, 0, 1, 2) -# Above not deleting the C++ object(node v12) - can't reliably control GC - use the movein function instead to delete -Cpp11_rvalue_reference_move_input::MovableCopyable.movein(mo111) -Cpp11_rvalue_reference_move_input::Counter.check_counts(2, 0, 0, 1, 1, 3) - -# null check -Cpp11_rvalue_reference_move_input::Counter.reset_counts() -exception_thrown = false -begin - Cpp11_rvalue_reference_move_input::MovableCopyable.movein(nil) -rescue ArgumentError => e - if (!e.to_s.include? "invalid null reference") - raise RuntimeError, "incorrect exception message: #{e.to_s}" - end - exception_thrown = true -end -if (!exception_thrown) - raise RuntimeError, "Should have thrown null error" -end -Cpp11_rvalue_reference_move_input::Counter.check_counts(0, 0, 0, 0, 0, 0) - diff --git a/Examples/test-suite/ruby/cpp11_rvalue_reference_move_runme.rb b/Examples/test-suite/ruby/cpp11_rvalue_reference_move_runme.rb new file mode 100644 index 000000000..0a423d6c4 --- /dev/null +++ b/Examples/test-suite/ruby/cpp11_rvalue_reference_move_runme.rb @@ -0,0 +1,106 @@ +#!/usr/bin/env ruby + +require 'swig_assert' + +require 'cpp11_rvalue_reference_move' + +# Function containing rvalue reference parameter +Cpp11_rvalue_reference_move::Counter.reset_counts() +mo = Cpp11_rvalue_reference_move::MovableCopyable.new(222) +Cpp11_rvalue_reference_move::Counter.check_counts(1, 0, 0, 0, 0, 0) +Cpp11_rvalue_reference_move::MovableCopyable.movein(mo) +Cpp11_rvalue_reference_move::Counter.check_counts(1, 0, 0, 1, 0, 2) +exception_thrown = false +begin + Cpp11_rvalue_reference_move::MovableCopyable.is_nullptr(mo) +rescue ObjectPreviouslyDeleted + exception_thrown = true +end +if (!exception_thrown) + raise RuntimeError, "is_nullptr failed to throw" +end +mo = nil +Cpp11_rvalue_reference_move::Counter.check_counts(1, 0, 0, 1, 0, 2) + +# Move constructor test +Cpp11_rvalue_reference_move::Counter.reset_counts() +mo = Cpp11_rvalue_reference_move::MovableCopyable.new(222) +Cpp11_rvalue_reference_move::Counter.check_counts(1, 0, 0, 0, 0, 0) +mo_moved = Cpp11_rvalue_reference_move::MovableCopyable.new(mo) +Cpp11_rvalue_reference_move::Counter.check_counts(1, 0, 0, 1, 0, 1) +exception_thrown = false +begin + Cpp11_rvalue_reference_move::MovableCopyable.is_nullptr(mo) +rescue ObjectPreviouslyDeleted + exception_thrown = true +end +if (!exception_thrown) + raise RuntimeError, "is_nullptr failed to throw" +end +mo = nil +Cpp11_rvalue_reference_move::Counter.check_counts(1, 0, 0, 1, 0, 1) +# mo_moved = nil +# Cpp11_rvalue_reference_move::Counter.check_counts(1, 0, 0, 1, 0, 2) +# Above not deleting the C++ object(node v12) - can't reliably control GC - use the movein function instead to delete +Cpp11_rvalue_reference_move::MovableCopyable.movein(mo_moved) +Cpp11_rvalue_reference_move::Counter.check_counts(1, 0, 0, 2, 0, 3) + +# Move assignment operator test +Cpp11_rvalue_reference_move::Counter.reset_counts() +mo111 = Cpp11_rvalue_reference_move::MovableCopyable.new(111) +mo222 = Cpp11_rvalue_reference_move::MovableCopyable.new(222) +Cpp11_rvalue_reference_move::Counter.check_counts(2, 0, 0, 0, 0, 0) +mo111.MoveAssign(mo222) +Cpp11_rvalue_reference_move::Counter.check_counts(2, 0, 0, 0, 1, 1) +exception_thrown = false +begin + Cpp11_rvalue_reference_move::MovableCopyable.is_nullptr(mo222) +rescue ObjectPreviouslyDeleted + exception_thrown = true +end +if (!exception_thrown) + raise RuntimeError, "is_nullptr failed to throw" +end +mo222 = nil +Cpp11_rvalue_reference_move::Counter.check_counts(2, 0, 0, 0, 1, 1) +# mo111 = nil +# Cpp11_rvalue_reference_move::Counter.check_counts(2, 0, 0, 0, 1, 2) +# Above not deleting the C++ object(node v12) - can't reliably control GC - use the movein function instead to delete +Cpp11_rvalue_reference_move::MovableCopyable.movein(mo111) +Cpp11_rvalue_reference_move::Counter.check_counts(2, 0, 0, 1, 1, 3) + +# null check +Cpp11_rvalue_reference_move::Counter.reset_counts() +exception_thrown = false +begin + Cpp11_rvalue_reference_move::MovableCopyable.movein(nil) +rescue ArgumentError => e + if (!e.to_s.include? "invalid null reference") + raise RuntimeError, "incorrect exception message: #{e.to_s}" + end + exception_thrown = true +end +if (!exception_thrown) + raise RuntimeError, "Should have thrown null error" +end +Cpp11_rvalue_reference_move::Counter.check_counts(0, 0, 0, 0, 0, 0) + +# output +Cpp11_rvalue_reference_move::Counter.reset_counts() +mc = Cpp11_rvalue_reference_move::MovableCopyable.moveout(1234) +Cpp11_rvalue_reference_move::Counter.check_counts(2, 0, 0, 0, 1, 1) +Cpp11_rvalue_reference_move::MovableCopyable.check_numbers_match(mc, 1234) + +exception_thrown = false +begin + Cpp11_rvalue_reference_move::MovableCopyable.movein(mc) +rescue RuntimeError => e + if (!e.to_s.include? "cannot release ownership as memory is not owned") + raise RuntimeError, "incorrect exception message: #{e.to_s}" + end + exception_thrown = true +end +if (!exception_thrown) + raise RuntimeError, "Should have thrown 'Cannot release ownership as memory is not owned' error" +end +Cpp11_rvalue_reference_move::Counter.check_counts(2, 0, 0, 0, 1, 1) diff --git a/Examples/test-suite/schemerunme/cpp11_rvalue_reference_move_input.scm b/Examples/test-suite/schemerunme/cpp11_rvalue_reference_move.scm similarity index 82% rename from Examples/test-suite/schemerunme/cpp11_rvalue_reference_move_input.scm rename to Examples/test-suite/schemerunme/cpp11_rvalue_reference_move.scm index 303932f98..1cbb6115b 100644 --- a/Examples/test-suite/schemerunme/cpp11_rvalue_reference_move_input.scm +++ b/Examples/test-suite/schemerunme/cpp11_rvalue_reference_move.scm @@ -43,4 +43,15 @@ ; TODO: check the exception message (Counter-check-counts 0 0 0 0 0 0) +; output +(Counter-reset-counts) +(define mc (MovableCopyable-moveout 1234)) +(Counter-check-counts 2 0 0 0 1 1) +(MovableCopyable-check-numbers-match mc 1234) + +(expect-throw 'misc-error + (MovableCopyable-movein mc)) +; TODO: check the exception message +(Counter-check-counts 2 0 0 0 1 1) + (exit 0) diff --git a/Examples/test-suite/tcl/cpp11_rvalue_reference_move_input_runme.tcl b/Examples/test-suite/tcl/cpp11_rvalue_reference_move_runme.tcl similarity index 69% rename from Examples/test-suite/tcl/cpp11_rvalue_reference_move_input_runme.tcl rename to Examples/test-suite/tcl/cpp11_rvalue_reference_move_runme.tcl index a81bf398a..876b0425d 100644 --- a/Examples/test-suite/tcl/cpp11_rvalue_reference_move_input_runme.tcl +++ b/Examples/test-suite/tcl/cpp11_rvalue_reference_move_runme.tcl @@ -1,5 +1,5 @@ -if [ catch { load ./cpp11_rvalue_reference_move_input[info sharedlibextension] cpp11_rvalue_reference_move_input} err_msg ] { +if [ catch { load ./cpp11_rvalue_reference_move[info sharedlibextension] cpp11_rvalue_reference_move} err_msg ] { puts stderr "Could not load shared object:\n$err_msg" } @@ -60,3 +60,23 @@ if {!$exception_thrown} { error "Should have thrown null error" } Counter_check_counts 0 0 0 0 0 0 + +# output +Counter_reset_counts +set mc [MovableCopyable_moveout 1234] +Counter_check_counts 2 0 0 0 1 1 +MovableCopyable_check_numbers_match $mc 1234 + +set exception_thrown 0 +if [ catch { + MovableCopyable_movein $mc +} e ] { + if {[string first "cannot release ownership as memory is not owned" $e] == -1} { + error "incorrect exception message: $e" + } + set exception_thrown 1 +} +if {!$exception_thrown} { + error "Should have thrown 'Cannot release ownership as memory is not owned' error" +} +Counter_check_counts 2 0 0 0 1 1