From 82a6fe02e3772e6f09097a221fbb5756b622318e Mon Sep 17 00:00:00 2001 From: Rokas Kupstys Date: Thu, 6 Sep 2018 14:21:54 +0300 Subject: [PATCH 001/662] Improve correctness of SwigDerivedClassHasMethod() by making sure only methods that have `override` are used connected by director. C# does not treat `virtual` methods of child classes as overriding (ass opposed to c++). In order to override a method it must have `override` specified. Previous version of this method treated `virtual void foo()` or `void foo()` in a subclass as methods that override virtual method of parent class. This resulted in `SwigDirectorConnect()` creating delegates and connecting them to a native class. Presence of such methods caused needless roundtrip through managed layer while in the end correct native function was called. This is the old code flow: ```cpp void SwigDirector_MyClass::nonOverride() { if (!swig_callbacknonOverride) { // 0. swig_callbacknonOverride is set MyClass::nonOverride(); return; } else { swig_callbacknonOverride(); // 1. this is called because wrapper mistakenly assumes overriding } } SWIGEXPORT void SWIGSTDCALL CSharp_director_basicNamespace_MyClass_nonOverrideSwigExplicitMyClass(void * jarg1) { MyClass *arg1 = (MyClass *) 0 ; arg1 = (MyClass *)jarg1; (arg1)->MyClass::nonOverride(); // 5. Correct method called in the end } ``` ```cs private void SwigDirectornonOverride() { nonOverride(); // 2. } public virtual void nonOverride() { if (SwigDerivedClassHasMethod("nonOverride", swigMethodTypes4)) // 3. This returns `true` director_basicPINVOKE.MyClass_nonOverrideSwigExplicitMyClass(swigCPtr); // 4. Native method of director class called explicitly else director_basicPINVOKE.MyClass_nonOverride(swigCPtr); } ``` This is the new code flow: ```cpp void SwigDirector_MyClass::nonOverride() { if (!swig_callbacknonOverride) { // 0. swig_callbacknonOverride is not set MyClass::nonOverride(); // 1. Calls correct method immediately return; } else { swig_callbacknonOverride(); } } ``` --- Source/Modules/csharp.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Modules/csharp.cxx b/Source/Modules/csharp.cxx index bd00ffaf3..75ee34023 100644 --- a/Source/Modules/csharp.cxx +++ b/Source/Modules/csharp.cxx @@ -1953,7 +1953,7 @@ public: Printf(proxy_class_code, " private bool SwigDerivedClassHasMethod(string methodName, global::System.Type[] methodTypes) {\n"); Printf(proxy_class_code, " global::System.Reflection.MethodInfo methodInfo = this.GetType().GetMethod(methodName, global::System.Reflection.BindingFlags.Public | global::System.Reflection.BindingFlags.NonPublic | global::System.Reflection.BindingFlags.Instance, null, methodTypes, null);\n"); - Printf(proxy_class_code, " bool hasDerivedMethod = methodInfo.DeclaringType.IsSubclassOf(typeof(%s));\n", proxy_class_name); + Printf(proxy_class_code, " bool hasDerivedMethod = methodInfo.IsVirtual && methodInfo.DeclaringType.IsSubclassOf(typeof(%s)) && methodInfo.DeclaringType != methodInfo.GetBaseDefinition().DeclaringType;\n", proxy_class_name); /* Could add this code to cover corner case where the GetMethod() returns a method which allows type * promotion, eg it will return foo(double), if looking for foo(int). if (hasDerivedMethod) { From 15f9403e06989cd1f6f592bbe52c1a735f94372b Mon Sep 17 00:00:00 2001 From: Rokas Kupstys Date: Wed, 26 Sep 2018 12:20:38 +0300 Subject: [PATCH 002/662] Fix expanded director_basic test. Since we are mixing `new` and `override` a class instance may have multiple methods with the same name. in case of director_basic test one method comes from `MyClassMiddle` (one that participates in dynamic dispatch) and one comes from `MyClassEnd` (one with `new` keyword). Therefore all methods have to be checked. --- Source/Modules/csharp.cxx | 31 +++++++++++++++++++++++++++---- 1 file changed, 27 insertions(+), 4 deletions(-) diff --git a/Source/Modules/csharp.cxx b/Source/Modules/csharp.cxx index 75ee34023..2fa3eff25 100644 --- a/Source/Modules/csharp.cxx +++ b/Source/Modules/csharp.cxx @@ -1951,9 +1951,32 @@ public: // Only emit if there is at least one director method Printf(proxy_class_code, "\n"); Printf(proxy_class_code, " private bool SwigDerivedClassHasMethod(string methodName, global::System.Type[] methodTypes) {\n"); - Printf(proxy_class_code, - " global::System.Reflection.MethodInfo methodInfo = this.GetType().GetMethod(methodName, global::System.Reflection.BindingFlags.Public | global::System.Reflection.BindingFlags.NonPublic | global::System.Reflection.BindingFlags.Instance, null, methodTypes, null);\n"); - Printf(proxy_class_code, " bool hasDerivedMethod = methodInfo.IsVirtual && methodInfo.DeclaringType.IsSubclassOf(typeof(%s)) && methodInfo.DeclaringType != methodInfo.GetBaseDefinition().DeclaringType;\n", proxy_class_name); + Printf(proxy_class_code, " global::System.Reflection.MethodInfo[] methodInfos = this.GetType().GetMethods(\n"); + Printf(proxy_class_code, " global::System.Reflection.BindingFlags.Public | global::System.Reflection.BindingFlags.NonPublic | global::System.Reflection.BindingFlags.Instance);\n"); + Printf(proxy_class_code, " foreach (global::System.Reflection.MethodInfo methodInfo in methodInfos) {\n"); + Printf(proxy_class_code, " if (methodInfo.DeclaringType == null)\n"); + Printf(proxy_class_code, " continue;\n\n"); + Printf(proxy_class_code, " if (methodInfo.Name != methodName)\n"); + Printf(proxy_class_code, " continue;\n\n"); + Printf(proxy_class_code, " var parameters = methodInfo.GetParameters();\n"); + Printf(proxy_class_code, " if (parameters.Length != methodTypes.Length)\n"); + Printf(proxy_class_code, " continue;\n\n"); + Printf(proxy_class_code, " bool parametersMatch = true;\n"); + Printf(proxy_class_code, " for (var i = 0; i < parameters.Length; i++) {\n"); + Printf(proxy_class_code, " if (parameters[i].ParameterType != methodTypes[i]) {\n"); + Printf(proxy_class_code, " parametersMatch = false;\n"); + Printf(proxy_class_code, " break;\n"); + Printf(proxy_class_code, " }\n"); + Printf(proxy_class_code, " }\n\n"); + Printf(proxy_class_code, " if (!parametersMatch)\n"); + Printf(proxy_class_code, " continue;\n\n"); + Printf(proxy_class_code, " if (methodInfo.IsVirtual && (methodInfo.DeclaringType.IsSubclassOf(typeof(%s))) &&\n", proxy_class_name); + Printf(proxy_class_code, " methodInfo.DeclaringType != methodInfo.GetBaseDefinition().DeclaringType) {\n"); + Printf(proxy_class_code, " return true;\n"); + Printf(proxy_class_code, " }\n"); + Printf(proxy_class_code, " }\n\n"); + Printf(proxy_class_code, " return false;\n"); + /* Could add this code to cover corner case where the GetMethod() returns a method which allows type * promotion, eg it will return foo(double), if looking for foo(int). if (hasDerivedMethod) { @@ -1973,7 +1996,7 @@ public: } } */ - Printf(proxy_class_code, " return hasDerivedMethod;\n"); + //Printf(proxy_class_code, " return hasDerivedMethod;\n"); Printf(proxy_class_code, " }\n"); } From c1258323b113033988240d3838f0001608163876 Mon Sep 17 00:00:00 2001 From: Seth R Johnson Date: Tue, 9 May 2017 14:36:14 -0400 Subject: [PATCH 003/662] Fix missing include in SWIG typemap --- Lib/carrays.i | 6 ++++++ Lib/cdata.i | 4 +++- Lib/cpointer.i | 6 ++++++ Lib/swig.swg | 36 ++++++++++++++++++++---------------- 4 files changed, 35 insertions(+), 17 deletions(-) diff --git a/Lib/carrays.i b/Lib/carrays.i index 3a9c3cfee..0aa3eee89 100644 --- a/Lib/carrays.i +++ b/Lib/carrays.i @@ -5,6 +5,12 @@ * pointers as arrays. * ----------------------------------------------------------------------------- */ +#ifndef __cplusplus +// C uses free/calloc/malloc +%include "swigfragments.swg" +%fragment(""); +#endif + /* ----------------------------------------------------------------------------- * %array_functions(TYPE,NAME) * diff --git a/Lib/cdata.i b/Lib/cdata.i index 23b7211e7..e058fe28b 100644 --- a/Lib/cdata.i +++ b/Lib/cdata.i @@ -68,7 +68,7 @@ static jbyteArray SWIG_JavaArrayOutCDATA(JNIEnv *jenv, char *result, jsize sz) { /* ----------------------------------------------------------------------------- - * %cdata(TYPE [, NAME]) + * %cdata(TYPE [, NAME]) * * Convert raw C data to a binary string. * ----------------------------------------------------------------------------- */ @@ -107,6 +107,8 @@ SWIGCDATA cdata_##NAME(TYPE *ptr, int nelements); %cdata(void); +%fragment(""); + /* Memory move function. Due to multi-argument typemaps this appears to be wrapped as void memmove(void *data, const char *s); */ void memmove(void *data, const void *indata, int inlen); diff --git a/Lib/cpointer.i b/Lib/cpointer.i index 881c511fc..5eca6fae1 100644 --- a/Lib/cpointer.i +++ b/Lib/cpointer.i @@ -5,6 +5,12 @@ * pointer objects. * ----------------------------------------------------------------------------- */ +#ifndef __cplusplus +// C uses free/calloc/malloc +%include "swigfragments.swg" +%fragment(""); +#endif + /* ----------------------------------------------------------------------------- * %pointer_class(type,name) * diff --git a/Lib/swig.swg b/Lib/swig.swg index 6dc215dcf..c215e8d89 100644 --- a/Lib/swig.swg +++ b/Lib/swig.swg @@ -442,6 +442,10 @@ namespace std { * Default char * and C array typemaps * ----------------------------------------------------------------------------- */ +%fragment("", "runtime") %{ +#include +%} + /* Set up the typemap for handling new return strings */ #ifdef __cplusplus @@ -453,7 +457,7 @@ namespace std { /* Default typemap for handling char * members */ #ifdef __cplusplus -%typemap(memberin) char * { +%typemap(memberin,fragment="") char * { delete [] $1; if ($input) { $1 = ($1_type) (new char[strlen((const char *)$input)+1]); @@ -462,7 +466,7 @@ namespace std { $1 = 0; } } -%typemap(memberin,warning=SWIGWARN_TYPEMAP_CHARLEAK_MSG) const char * { +%typemap(memberin,warning=SWIGWARN_TYPEMAP_CHARLEAK_MSG,fragment="") const char * { if ($input) { $1 = ($1_type) (new char[strlen((const char *)$input)+1]); strcpy((char *)$1, (const char *)$input); @@ -470,7 +474,7 @@ namespace std { $1 = 0; } } -%typemap(globalin) char * { +%typemap(globalin,fragment="") char * { delete [] $1; if ($input) { $1 = ($1_type) (new char[strlen((const char *)$input)+1]); @@ -479,7 +483,7 @@ namespace std { $1 = 0; } } -%typemap(globalin,warning=SWIGWARN_TYPEMAP_CHARLEAK_MSG) const char * { +%typemap(globalin,warning=SWIGWARN_TYPEMAP_CHARLEAK_MSG,fragment="") const char * { if ($input) { $1 = ($1_type) (new char[strlen((const char *)$input)+1]); strcpy((char *)$1, (const char *)$input); @@ -488,7 +492,7 @@ namespace std { } } #else -%typemap(memberin) char * { +%typemap(memberin,fragment="") char * { free($1); if ($input) { $1 = ($1_type) malloc(strlen((const char *)$input)+1); @@ -497,7 +501,7 @@ namespace std { $1 = 0; } } -%typemap(memberin,warning=SWIGWARN_TYPEMAP_CHARLEAK_MSG) const char * { +%typemap(memberin,warning=SWIGWARN_TYPEMAP_CHARLEAK_MSG,fragment="") const char * { if ($input) { $1 = ($1_type) malloc(strlen((const char *)$input)+1); strcpy((char *)$1, (const char *)$input); @@ -505,7 +509,7 @@ namespace std { $1 = 0; } } -%typemap(globalin) char * { +%typemap(globalin,fragment="") char * { free($1); if ($input) { $1 = ($1_type) malloc(strlen((const char *)$input)+1); @@ -514,7 +518,7 @@ namespace std { $1 = 0; } } -%typemap(globalin,warning=SWIGWARN_TYPEMAP_CHARLEAK_MSG) const char * { +%typemap(globalin,warning=SWIGWARN_TYPEMAP_CHARLEAK_MSG,fragment="") const char * { if ($input) { $1 = ($1_type) malloc(strlen((const char *)$input)+1); strcpy((char *)$1, (const char *)$input); @@ -527,7 +531,7 @@ namespace std { /* Character array handling */ -%typemap(memberin) char [ANY] { +%typemap(memberin,fragment="") char [ANY] { if($input) { strncpy((char*)$1, (const char *)$input, $1_dim0-1); $1[$1_dim0-1] = 0; @@ -536,7 +540,7 @@ namespace std { } } -%typemap(globalin) char [ANY] { +%typemap(globalin,fragment="") char [ANY] { if($input) { strncpy((char*)$1, (const char *)$input, $1_dim0-1); $1[$1_dim0-1] = 0; @@ -545,25 +549,25 @@ namespace std { } } -%typemap(memberin) char [] { +%typemap(memberin,fragment="") char [] { if ($input) strcpy((char *)$1, (const char *)$input); else $1[0] = 0; } -%typemap(globalin) char [] { +%typemap(globalin,fragment="") char [] { if ($input) strcpy((char *)$1, (const char *)$input); else $1[0] = 0; } /* memberin/globalin typemap for arrays. */ -%typemap(memberin) SWIGTYPE [ANY] { +%typemap(memberin,fragment="") SWIGTYPE [ANY] { size_t ii; $1_basetype *b = ($1_basetype *) $1; for (ii = 0; ii < (size_t)$1_size; ii++) b[ii] = *(($1_basetype *) $input + ii); } -%typemap(globalin) SWIGTYPE [ANY] { +%typemap(globalin,fragment="") SWIGTYPE [ANY] { size_t ii; $1_basetype *b = ($1_basetype *) $1; for (ii = 0; ii < (size_t)$1_size; ii++) b[ii] = *(($1_basetype *) $input + ii); @@ -571,7 +575,7 @@ namespace std { /* memberin/globalin typemap for double arrays. */ -%typemap(memberin) SWIGTYPE [ANY][ANY] { +%typemap(memberin,fragment="") SWIGTYPE [ANY][ANY] { $basetype (*inp)[$1_dim1] = ($basetype (*)[$1_dim1])($input); $basetype (*dest)[$1_dim1] = ($basetype (*)[$1_dim1])($1); size_t ii = 0; @@ -583,7 +587,7 @@ namespace std { } } -%typemap(globalin) SWIGTYPE [ANY][ANY] { +%typemap(globalin,fragment="") SWIGTYPE [ANY][ANY] { $basetype (*inp)[$1_dim1] = ($basetype (*)[$1_dim1])($input); $basetype (*dest)[$1_dim1] = ($basetype (*)[$1_dim1])($1); size_t ii = 0; From feeb2516aedfc19fdc1eefe233dec9bc5593fe2b Mon Sep 17 00:00:00 2001 From: Seth R Johnson Date: Tue, 7 Nov 2017 18:35:00 -0500 Subject: [PATCH 004/662] "Include what you use" for tests Many of these tests implicitly required the target language library files to include the headers upstream. --- Examples/test-suite/default_args.i | 59 ++++++++++--------- Examples/test-suite/director_thread.i | 2 +- Examples/test-suite/li_cdata.i | 4 ++ Examples/test-suite/li_cdata_cpp.i | 4 ++ Examples/test-suite/li_std_except.i | 2 + Examples/test-suite/memberin_extend.i | 1 + Examples/test-suite/mod.h | 2 +- Examples/test-suite/namespace_typemap.i | 1 + Examples/test-suite/nested_extend_c.i | 4 ++ Examples/test-suite/operator_overload_break.i | 1 + Examples/test-suite/operator_pointer_ref.i | 2 + .../test-suite/smart_pointer_const_overload.i | 4 ++ Examples/test-suite/special_variable_macros.i | 2 + Examples/test-suite/string_simple.i | 1 + .../testdir/inctest/subdir2/hello.i | 1 + Examples/test-suite/threads.i | 1 + Examples/test-suite/typedef_struct.i | 1 + 17 files changed, 61 insertions(+), 31 deletions(-) diff --git a/Examples/test-suite/default_args.i b/Examples/test-suite/default_args.i index 6b680f561..2f8fdbbd2 100644 --- a/Examples/test-suite/default_args.i +++ b/Examples/test-suite/default_args.i @@ -18,6 +18,7 @@ %{ #define TESTCASE_THROW1(T1) #define TESTCASE_THROW2(T1, T2) +#include %} %include @@ -71,7 +72,7 @@ class EnumClass { public: enum speed { FAST, SLOW }; - // Note: default values should be EnumClass::FAST and SWEET + // Note: default values should be EnumClass::FAST and SWEET bool blah(speed s = FAST, flavor f = SWEET) { return (s == FAST && f == SWEET); }; }; @@ -83,16 +84,16 @@ // casts const char * casts1(const char *m = (const char *) NULL) { - char *ret = NULL; - if (m) { + char *ret = NULL; + if (m) { ret = new char[strlen(m)+1]; strcpy(ret, m); } return ret; } const char * casts2(const char *m = (const char *) "Hello") { - char *ret = NULL; - if (m) { + char *ret = NULL; + if (m) { ret = new char[strlen(m)+1]; strcpy(ret, m); } @@ -108,16 +109,16 @@ char chartest6(char c = '\x43') { return c; } // 'C' // namespaces - namespace AType { - enum AType { NoType }; - } + namespace AType { + enum AType { NoType }; + } void dummy(AType::AType aType = AType::NoType) {} - namespace A { - namespace B { - int CONST_NUM = 10; - } + namespace A { + namespace B { + int CONST_NUM = 10; + } int afunction(int i = B::CONST_NUM) { return i; } - } + } // references int reftest1(const int &x = 42) { return x; } @@ -131,7 +132,7 @@ void test(int x = Oak + Fir + Cedar) {} }; enum Tree::types chops(enum Tree::types type) { return type; } - + %} // Rename a class member @@ -155,11 +156,11 @@ static int spam; Foo(){} - + Foo(int x, int y = 0, int z = 0){} void meth(int x, int y = 0, int z = 0){} - + // Use a renamed member as a default argument. SWIG has to resolve // bar to Foo::bar and not Foo::spam. SWIG-1.3.11 got this wrong. // (Different default parameter wrapping in SWIG-1.3.23 ensures SWIG doesn't have to resolve these symbols). @@ -189,20 +190,20 @@ // tests valuewrapper %feature("compactdefaultargs") MyClass2::set; %inline %{ - enum MyType { Val1, Val2 }; + enum MyType { Val1, Val2 }; - class MyClass1 - { - public: + class MyClass1 + { + public: MyClass1(MyType myType) {} - }; + }; - class MyClass2 - { - public : + class MyClass2 + { + public : void set(MyClass1 cl1 = Val1) {} - // This could have been written : set(MyClass1 cl1 = MyClass1(Val1)) - // But it works in C++ since there is a "conversion" constructor in MyClass1. + // This could have been written : set(MyClass1 cl1 = MyClass1(Val1)) + // But it works in C++ since there is a "conversion" constructor in MyClass1. void set2(MyClass1 cl1 = Val1) {} }; %} @@ -281,7 +282,7 @@ struct ConstMethods { }; %} -// const methods +// const methods // runtime test needed to check that the const method is called struct ConstMethods { int coo(double d = 0.0) const; @@ -305,8 +306,8 @@ struct ConstMethods { return(x+p); } - typedef struct Pointf { - double x,y; + typedef struct Pointf { + double x,y; } Pointf; } %} diff --git a/Examples/test-suite/director_thread.i b/Examples/test-suite/director_thread.i index c4564737f..649ab2538 100644 --- a/Examples/test-suite/director_thread.i +++ b/Examples/test-suite/director_thread.i @@ -20,7 +20,6 @@ #ifdef _WIN32 #include #include -#include #else #include #include @@ -30,6 +29,7 @@ #endif #include +#include #include "swig_examples_lock.h" class Foo; diff --git a/Examples/test-suite/li_cdata.i b/Examples/test-suite/li_cdata.i index 2180af96e..4e1a01e4e 100644 --- a/Examples/test-suite/li_cdata.i +++ b/Examples/test-suite/li_cdata.i @@ -5,4 +5,8 @@ %cdata(int); %cdata(double); +%{ +#include +%} + void *malloc(size_t size); diff --git a/Examples/test-suite/li_cdata_cpp.i b/Examples/test-suite/li_cdata_cpp.i index 2d7d300e4..80ff2932b 100644 --- a/Examples/test-suite/li_cdata_cpp.i +++ b/Examples/test-suite/li_cdata_cpp.i @@ -5,4 +5,8 @@ %cdata(int); %cdata(double); +%{ +#include +%} + void *malloc(size_t size); diff --git a/Examples/test-suite/li_std_except.i b/Examples/test-suite/li_std_except.i index 60bce999d..9bf70cd3f 100644 --- a/Examples/test-suite/li_std_except.i +++ b/Examples/test-suite/li_std_except.i @@ -9,6 +9,8 @@ %} %inline %{ + #include + #include struct E1 : public std::exception { }; diff --git a/Examples/test-suite/memberin_extend.i b/Examples/test-suite/memberin_extend.i index c6eb10526..43251973f 100644 --- a/Examples/test-suite/memberin_extend.i +++ b/Examples/test-suite/memberin_extend.i @@ -11,6 +11,7 @@ struct ExtendMe { %{ #include +#include std::map ExtendMeStringMap; void ExtendMe_thing_set(ExtendMe *self, const char *val) { char *old_val = ExtendMeStringMap[self]; diff --git a/Examples/test-suite/mod.h b/Examples/test-suite/mod.h index aae629850..60eb36b77 100644 --- a/Examples/test-suite/mod.h +++ b/Examples/test-suite/mod.h @@ -1,4 +1,4 @@ - +#include class C; diff --git a/Examples/test-suite/namespace_typemap.i b/Examples/test-suite/namespace_typemap.i index 9c74715f0..e7b91b9d4 100644 --- a/Examples/test-suite/namespace_typemap.i +++ b/Examples/test-suite/namespace_typemap.i @@ -2,6 +2,7 @@ %module namespace_typemap %{ +#include namespace test { /* A minimalistic string class */ class string_class { diff --git a/Examples/test-suite/nested_extend_c.i b/Examples/test-suite/nested_extend_c.i index f1d7ff2c8..67ca86578 100644 --- a/Examples/test-suite/nested_extend_c.i +++ b/Examples/test-suite/nested_extend_c.i @@ -12,6 +12,10 @@ #endif +%{ +#include "stdlib.h" +%} + #if !defined(SWIGOCTAVE) && !defined(SWIG_JAVASCRIPT_V8) %extend hiA { hiA() { diff --git a/Examples/test-suite/operator_overload_break.i b/Examples/test-suite/operator_overload_break.i index a948f2d49..809498fa7 100644 --- a/Examples/test-suite/operator_overload_break.i +++ b/Examples/test-suite/operator_overload_break.i @@ -18,6 +18,7 @@ %{ #include +#include using namespace std; %} diff --git a/Examples/test-suite/operator_pointer_ref.i b/Examples/test-suite/operator_pointer_ref.i index 84182da0d..cd4ed2db0 100644 --- a/Examples/test-suite/operator_pointer_ref.i +++ b/Examples/test-suite/operator_pointer_ref.i @@ -4,6 +4,8 @@ #if defined(_MSC_VER) #pragma warning(disable: 4996) // 'strdup': The POSIX name for this item is deprecated. Instead, use the ISO C++ conformant name: _strdup. See online help for details. #endif +#include +#include %} %rename(AsCharStarRef) operator char*&; diff --git a/Examples/test-suite/smart_pointer_const_overload.i b/Examples/test-suite/smart_pointer_const_overload.i index 75a137b73..526bcc9bd 100644 --- a/Examples/test-suite/smart_pointer_const_overload.i +++ b/Examples/test-suite/smart_pointer_const_overload.i @@ -3,6 +3,10 @@ %warnfilter(SWIGWARN_LANG_OVERLOAD_IGNORED) Bar::operator->; // Overloaded method Bar::operator ->() ignored %warnfilter(SWIGWARN_LANG_OVERLOAD_IGNORED) Bar2::operator->; // Overloaded method Bar2::operator ->() ignored +%{ +#include +%} + %inline %{ int CONST_ACCESS = 1; int MUTABLE_ACCESS = 2; diff --git a/Examples/test-suite/special_variable_macros.i b/Examples/test-suite/special_variable_macros.i index ca2edaa98..98d108b6b 100644 --- a/Examples/test-suite/special_variable_macros.i +++ b/Examples/test-suite/special_variable_macros.i @@ -9,6 +9,8 @@ #if defined(_MSC_VER) #pragma warning(disable: 4996) // 'strdup': The POSIX name for this item is deprecated. Instead, use the ISO C++ conformant name: _strdup. See online help for details. #endif +#include +#include %} %ignore Name::operator=; diff --git a/Examples/test-suite/string_simple.i b/Examples/test-suite/string_simple.i index c319aa1ef..839d56d9b 100644 --- a/Examples/test-suite/string_simple.i +++ b/Examples/test-suite/string_simple.i @@ -3,6 +3,7 @@ %newobject copy_string; %inline %{ +#include #include const char* copy_string(const char* str) { size_t len = strlen(str); diff --git a/Examples/test-suite/testdir/inctest/subdir2/hello.i b/Examples/test-suite/testdir/inctest/subdir2/hello.i index ed172b1fd..e87b43759 100644 --- a/Examples/test-suite/testdir/inctest/subdir2/hello.i +++ b/Examples/test-suite/testdir/inctest/subdir2/hello.i @@ -3,6 +3,7 @@ %{ typedef char * TypedefString; +#include %} diff --git a/Examples/test-suite/threads.i b/Examples/test-suite/threads.i index 7c6b09be0..28c55945e 100644 --- a/Examples/test-suite/threads.i +++ b/Examples/test-suite/threads.i @@ -9,6 +9,7 @@ %inline %{ #include + #include struct Kerfuffle { std::string StdString(std::string str) { return str; diff --git a/Examples/test-suite/typedef_struct.i b/Examples/test-suite/typedef_struct.i index 185e81105..b9a670cf5 100644 --- a/Examples/test-suite/typedef_struct.i +++ b/Examples/test-suite/typedef_struct.i @@ -31,6 +31,7 @@ #define MS_NOOVERRIDE -1111 +#include %} From c041ac6d1cda407baa338bd016c0a68f2f0c6834 Mon Sep 17 00:00:00 2001 From: Seth R Johnson Date: Fri, 23 Mar 2018 15:04:00 -0400 Subject: [PATCH 005/662] Move fragment to swigfragments --- Examples/test-suite/char_strings.i | 5 +++-- Examples/test-suite/threads_exception.i | 1 + Examples/test-suite/varargs.i | 4 ++++ Lib/cdata.i | 2 ++ Lib/swig.swg | 4 ---- Lib/swigfragments.swg | 4 ++++ 6 files changed, 14 insertions(+), 6 deletions(-) diff --git a/Examples/test-suite/char_strings.i b/Examples/test-suite/char_strings.i index 9a87df4e3..aa3b125ce 100644 --- a/Examples/test-suite/char_strings.i +++ b/Examples/test-suite/char_strings.i @@ -11,6 +11,7 @@ below. %{ #include +#include #define OTHERLAND_MSG "Little message from the safe world." #define CPLUSPLUS_MSG "A message from the deep dark world of C++, where anything is possible." @@ -150,11 +151,11 @@ const char global_const_char_array2[sizeof(CPLUSPLUS_MSG)+1] = CPLUSPLUS_MSG; %inline { struct Formatpos; struct OBFormat; - + static int GetNextFormat(Formatpos& itr, const char*& str,OBFormat*& pFormat) { return 0; } - + } diff --git a/Examples/test-suite/threads_exception.i b/Examples/test-suite/threads_exception.i index 4708633db..776e84231 100644 --- a/Examples/test-suite/threads_exception.i +++ b/Examples/test-suite/threads_exception.i @@ -13,6 +13,7 @@ %} %{ +#include struct A {}; %} diff --git a/Examples/test-suite/varargs.i b/Examples/test-suite/varargs.i index dd56cb073..b4143da7c 100644 --- a/Examples/test-suite/varargs.i +++ b/Examples/test-suite/varargs.i @@ -7,6 +7,10 @@ %varargs(int mode = 0) Foo::statictest(const char*fmt, ...); %varargs(2, int mode = 0) test_plenty(const char*fmt, ...); +%{ +#include +%} + %inline %{ char *test(const char *fmt, ...) { return (char *) fmt; diff --git a/Lib/cdata.i b/Lib/cdata.i index e058fe28b..e82843b3a 100644 --- a/Lib/cdata.i +++ b/Lib/cdata.i @@ -4,6 +4,8 @@ * SWIG library file containing macros for manipulating raw C data as strings. * ----------------------------------------------------------------------------- */ +%include + %{ typedef struct SWIGCDATA { char *data; diff --git a/Lib/swig.swg b/Lib/swig.swg index c215e8d89..d719a139c 100644 --- a/Lib/swig.swg +++ b/Lib/swig.swg @@ -442,10 +442,6 @@ namespace std { * Default char * and C array typemaps * ----------------------------------------------------------------------------- */ -%fragment("", "runtime") %{ -#include -%} - /* Set up the typemap for handling new return strings */ #ifdef __cplusplus diff --git a/Lib/swigfragments.swg b/Lib/swigfragments.swg index 63bb6c8f4..a2b467bce 100644 --- a/Lib/swigfragments.swg +++ b/Lib/swigfragments.swg @@ -29,6 +29,10 @@ #include %} +%fragment("", "header") %{ +#include +%} + %fragment("", "header") %{ #include %} From f0bb77221a3c0a88e65d87b6a611b9e180b16108 Mon Sep 17 00:00:00 2001 From: Markus Friedrich Date: Sun, 24 Nov 2019 14:55:36 +0100 Subject: [PATCH 006/662] Bugfix for octave 4.4 With octave 4.4 the function virtual bool octave_base_value::is_object() const was renamed to virtual bool octave_base_value::isobject() const As noted in CHANGES "2012-03-26: xavier98", is_object() must return true for swig types whereas octave_base_value::is_object returns false per default. --- Lib/octave/octrun.swg | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Lib/octave/octrun.swg b/Lib/octave/octrun.swg index ff614e681..48f179a21 100644 --- a/Lib/octave/octrun.swg +++ b/Lib/octave/octrun.swg @@ -1098,8 +1098,13 @@ SWIGRUNTIME void swig_acquire_ownership_obj(void *vptr, int own); octave_value subsasgn(const std::string &ops, const std::list < octave_value_list > &idx, const octave_value &rhs) { return ptr->subsasgn(ops, idx, rhs); } +#if SWIG_OCTAVE_PREREQ(4,2,0) + virtual bool isobject() const + { return ptr->is_object(); } +#else virtual bool is_object() const { return ptr->is_object(); } +#endif virtual bool is_string() const { return ptr->is_string(); } From 7271ea805a8344ecc83180e0d2ee2bc8190e9636 Mon Sep 17 00:00:00 2001 From: Markus Friedrich Date: Sun, 24 Nov 2019 15:01:55 +0100 Subject: [PATCH 007/662] Added a octave test for the concatenation operator. Swig types can be used by the operators [a,b] or [a;b] if an octave overload functions horzcat.m or vertcat.m are added in a @swig_ref subdirectory. This requires that is_object() (isobject() for octave >= 4.4) returns true for swig types which is ensured by the swig octave runtime. --- Examples/octave/operator/@swig_ref/horzcat.m | 6 ++++++ Examples/octave/operator/runme.m | 4 ++++ 2 files changed, 10 insertions(+) create mode 100644 Examples/octave/operator/@swig_ref/horzcat.m diff --git a/Examples/octave/operator/@swig_ref/horzcat.m b/Examples/octave/operator/@swig_ref/horzcat.m new file mode 100644 index 000000000..00fdfd5ce --- /dev/null +++ b/Examples/octave/operator/@swig_ref/horzcat.m @@ -0,0 +1,6 @@ +% test octaves concatenation operator +function ret=horzcat(a, b) + % return the concatenation of two ComplexVal values as a cell array. + % (not really useful but it tests the concatenation of swig_ref objects) + ret={a, b}; +end diff --git a/Examples/octave/operator/runme.m b/Examples/octave/operator/runme.m index e17494a84..4aad26064 100644 --- a/Examples/octave/operator/runme.m +++ b/Examples/octave/operator/runme.m @@ -42,3 +42,7 @@ if swig_octave_prereq(3,8,0) printf("conj(a) = %s\n", disp(conj(a))); printf("exp(a) = %s\n", disp(exp(a))); endif + +# concatenation operator +g = [a, b, c]; +printf("g = %s\n",disp(g)); From 3fe47b4b46562d96c45d8d2ea9a9dca7bd0d143e Mon Sep 17 00:00:00 2001 From: Hirokazu MORIKAWA Date: Sat, 1 May 2021 09:25:03 +0900 Subject: [PATCH 008/662] [javascript][v8] SWIG_V8_VERSION generation method corrected. "SWIG_V8_VERSION" generation method was incorrectly fixed. Signed-off-by: Hirokazu MORIKAWA --- Lib/javascript/v8/javascriptruntime.swg | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Lib/javascript/v8/javascriptruntime.swg b/Lib/javascript/v8/javascriptruntime.swg index 115554a5a..59909389e 100644 --- a/Lib/javascript/v8/javascriptruntime.swg +++ b/Lib/javascript/v8/javascriptruntime.swg @@ -58,7 +58,10 @@ #if defined(V8_MAJOR_VERSION) && defined(V8_MINOR_VERSION) #undef SWIG_V8_VERSION -#define SWIG_V8_VERSION (V8_MAJOR_VERSION * 256 + V8_MINOR_VERSION) +#define SWIG_V8_VERSION ((V8_MAJOR_VERSION / 10) * 4096 + \ + (V8_MAJOR_VERSION % 10) * 256 + \ + (V8_MINOR_VERSION / 10) * 16 + \ + (V8_MINOR_VERSION % 10)) #endif #include From 46ec93785a1a74e869d035a4a794d214b5186a00 Mon Sep 17 00:00:00 2001 From: Lindley French Date: Wed, 23 Jun 2021 00:00:37 -0700 Subject: [PATCH 009/662] Expose to javaout typemaps. --- Source/Modules/java.cxx | 1 + 1 file changed, 1 insertion(+) diff --git a/Source/Modules/java.cxx b/Source/Modules/java.cxx index 958da8ed1..614431192 100644 --- a/Source/Modules/java.cxx +++ b/Source/Modules/java.cxx @@ -3179,6 +3179,7 @@ public: else Replaceall(tm, "$owner", "false"); substituteClassname(t, tm); + Replaceall(tm, "$imfuncname", overloaded_name); Replaceall(tm, "$jnicall", imcall); } else { Swig_warning(WARN_JAVA_TYPEMAP_JAVAOUT_UNDEF, input_file, line_number, "No javaout typemap defined for %s\n", SwigType_str(t, 0)); From 112f9d59eab046486ab9eeef238cb16507b9246a Mon Sep 17 00:00:00 2001 From: Lindley French Date: Thu, 24 Jun 2021 15:49:49 -0700 Subject: [PATCH 010/662] Also expose in proxyClassFunctionHandler --- Source/Modules/java.cxx | 1 + 1 file changed, 1 insertion(+) diff --git a/Source/Modules/java.cxx b/Source/Modules/java.cxx index 614431192..9fc340954 100644 --- a/Source/Modules/java.cxx +++ b/Source/Modules/java.cxx @@ -2694,6 +2694,7 @@ public: Replaceall(imcall, "$imfuncname", intermediary_function_name); } + Replaceall(tm, "$imfuncname", intermediary_function_name); Replaceall(tm, "$jnicall", imcall); } else { Swig_warning(WARN_JAVA_TYPEMAP_JAVAOUT_UNDEF, input_file, line_number, "No javaout typemap defined for %s\n", SwigType_str(t, 0)); From 119222be770546ee7fdc19c1b603d66a23c1c302 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Tue, 9 Nov 2021 23:20:31 +0100 Subject: [PATCH 011/662] Refactor code in Language::staticmemberfunctionHandler() No real changes, just move the test for "code" to the outer scope to facilitate the upcoming changes. This commit is best viewed ignoring whitespace-only changes. --- Source/Modules/lang.cxx | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/Source/Modules/lang.cxx b/Source/Modules/lang.cxx index 66aebdea1..3064d22f9 100644 --- a/Source/Modules/lang.cxx +++ b/Source/Modules/lang.cxx @@ -1320,16 +1320,18 @@ int Language::staticmemberfunctionHandler(Node *n) { Delete(mrename); mrename = mangled; - if (Getattr(n, "sym:overloaded") && code) { - Append(cname, Getattr(defaultargs ? defaultargs : n, "sym:overname")); - } + if (code) { + if (Getattr(n, "sym:overloaded")) { + Append(cname, Getattr(defaultargs ? defaultargs : n, "sym:overname")); + } - if (!defaultargs && code) { - /* Hmmm. An added static member. We have to create a little wrapper for this */ - String *mangled_cname = Swig_name_mangle(cname); - Swig_add_extension_code(n, mangled_cname, parms, type, code, CPlusPlus, 0); - Setattr(n, "extendname", mangled_cname); - Delete(mangled_cname); + if (!defaultargs) { + /* Hmmm. An added static member. We have to create a little wrapper for this */ + String *mangled_cname = Swig_name_mangle(cname); + Swig_add_extension_code(n, mangled_cname, parms, type, code, CPlusPlus, 0); + Setattr(n, "extendname", mangled_cname); + Delete(mangled_cname); + } } } From 26bf86322b18040e2f2156c34a47b44c927d1399 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Tue, 9 Nov 2021 23:33:31 +0100 Subject: [PATCH 012/662] Use SWIG-specific for non-overloaded synthesized functions too This avoids conflicts between such functions, which are generated when using %extend to add static methods to an existing class, and the actual wrapper functions generated by the backend. This shouldn't result in any user-visible changes. --- Source/Modules/lang.cxx | 3 +++ Source/Swig/cwrap.c | 15 ++++++++++++--- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/Source/Modules/lang.cxx b/Source/Modules/lang.cxx index 3064d22f9..196ff47a9 100644 --- a/Source/Modules/lang.cxx +++ b/Source/Modules/lang.cxx @@ -1321,8 +1321,11 @@ int Language::staticmemberfunctionHandler(Node *n) { mrename = mangled; if (code) { + // See Swig_MethodToFunction() for the explanation of this code. if (Getattr(n, "sym:overloaded")) { Append(cname, Getattr(defaultargs ? defaultargs : n, "sym:overname")); + } else { + Append(cname, "__SWIG"); } if (!defaultargs) { diff --git a/Source/Swig/cwrap.c b/Source/Swig/cwrap.c index d6e5e0cdc..0d8008ef0 100644 --- a/Source/Swig/cwrap.c +++ b/Source/Swig/cwrap.c @@ -1076,9 +1076,18 @@ int Swig_MethodToFunction(Node *n, const_String_or_char_ptr nspace, String *clas /* Check if the method is overloaded. If so, and it has code attached, we append an extra suffix to avoid a name-clash in the generated wrappers. This allows overloaded methods to be defined - in C. */ - if (Getattr(n, "sym:overloaded") && code) { - Append(mangled, Getattr(defaultargs ? defaultargs : n, "sym:overname")); + in C. + + But when not using the suffix used for overloaded functions, we still need to ensure that the + wrapper name doesn't conflict with any wrapper functions, so make it sufficiently unique by + appending a suffix similar to the one used for overloaded functions to it. + */ + if (code) { + if (Getattr(n, "sym:overloaded")) { + Append(mangled, Getattr(defaultargs ? defaultargs : n, "sym:overname")); + } else { + Append(mangled, "__SWIG"); + } } /* See if there is any code that we need to emit */ From 6a56426f8f4887f649d06b83c0becbaa69bc6fe3 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Tue, 2 Nov 2021 19:42:11 +0100 Subject: [PATCH 013/662] Use JSC version available in Ubuntu 20.04 in the CI builds Use the newer OS and JavaScript Core library versions for the CI build, we don't have to remain with the old version here, as the newer one works too. --- .github/workflows/ci.yml | 1 - Tools/CI-linux-install.sh | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3bfa687a2..d66a5f240 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -78,7 +78,6 @@ jobs: CPPSTD: c++14 - SWIGLANG: javascript ENGINE: jsc - os: ubuntu-18.04 # libwebkitgtk-dev dependency not available in 20.04. - SWIGLANG: javascript ENGINE: v8 os: ubuntu-18.04 # libv8-dev only actually provides v8 in 18.04. diff --git a/Tools/CI-linux-install.sh b/Tools/CI-linux-install.sh index 6edce572b..7bd141080 100644 --- a/Tools/CI-linux-install.sh +++ b/Tools/CI-linux-install.sh @@ -55,7 +55,7 @@ case "$SWIGLANG" in fi ;; "jsc") - $RETRY sudo apt-get install -qq libwebkitgtk-dev + $RETRY sudo apt-get install -qq libjavascriptcoregtk-4.0-dev ;; "v8") $RETRY sudo apt-get install -qq libv8-dev From 0304bdb82baaf5da94b6273c93e2623f1522a2a0 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Sat, 27 Nov 2021 13:26:15 +0000 Subject: [PATCH 014/662] GHA: Add testing of node 17 Also remove duplicate test of node 14 --- .github/workflows/ci.yml | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d66a5f240..ab8c68d1f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -70,11 +70,7 @@ jobs: CPPSTD: c++11 - SWIGLANG: javascript ENGINE: node - VER: '14' - CPPSTD: c++11 - - SWIGLANG: javascript - ENGINE: node - VER: '16' + VER: '17' CPPSTD: c++14 - SWIGLANG: javascript ENGINE: jsc @@ -250,7 +246,7 @@ jobs: GCC: 11 - SWIGLANG: javascript ENGINE: node - VER: '16' + VER: '17' CPPSTD: c++17 GCC: 11 - SWIGLANG: lua From ebe14e6e2ae9ae59d7cbc32877b5e138c194cc5a Mon Sep 17 00:00:00 2001 From: John Senneker Date: Tue, 30 Nov 2021 16:13:17 -0500 Subject: [PATCH 015/662] Fixed crashes when using embedded Python interpreters. Fixes #2101. There are 3 related changes made here: 1. Move the SWIG_globals() singleton into pyrun from pyint so it is visible to SWIG_Python_DestroyModule(). The static globals varlink has been extracted out of the function so that it can be set to NULL in SWIG_Python_DestroyModule(), which fixes the issue described in #2101. (Now when the second interpreter starts up, the Swig_Globals_global pointer will be NULL, so it knows it has to create a new one.) 2. Remove a Py_DECREF on the globals varlink. The decrement is now performed by DestroyModule(), so there's no need to do it in SWIG_init(). 3. Fixed similar issue with SWIG_Python_TypeCache(). --- Lib/python/pyinit.swg | 214 ----------------------------------- Lib/python/pyrun.swg | 227 +++++++++++++++++++++++++++++++++++++- Source/Modules/python.cxx | 1 - 3 files changed, 225 insertions(+), 217 deletions(-) diff --git a/Lib/python/pyinit.swg b/Lib/python/pyinit.swg index a6d609d56..dfd3940ec 100644 --- a/Lib/python/pyinit.swg +++ b/Lib/python/pyinit.swg @@ -30,220 +30,6 @@ SWIGINTERN PyObject *SWIG_PyStaticMethod_New(PyObject *SWIGUNUSEDPARM(self), PyO extern "C" { #endif -/* Python-specific SWIG API */ -#define SWIG_newvarlink() SWIG_Python_newvarlink() -#define SWIG_addvarlink(p, name, get_attr, set_attr) SWIG_Python_addvarlink(p, name, get_attr, set_attr) -#define SWIG_InstallConstants(d, constants) SWIG_Python_InstallConstants(d, constants) - -/* ----------------------------------------------------------------------------- - * global variable support code. - * ----------------------------------------------------------------------------- */ - -typedef struct swig_globalvar { - char *name; /* Name of global variable */ - PyObject *(*get_attr)(void); /* Return the current value */ - int (*set_attr)(PyObject *); /* Set the value */ - struct swig_globalvar *next; -} swig_globalvar; - -typedef struct swig_varlinkobject { - PyObject_HEAD - swig_globalvar *vars; -} swig_varlinkobject; - -SWIGINTERN PyObject * -swig_varlink_repr(swig_varlinkobject *SWIGUNUSEDPARM(v)) { -#if PY_VERSION_HEX >= 0x03000000 - return PyUnicode_InternFromString(""); -#else - return PyString_FromString(""); -#endif -} - -SWIGINTERN PyObject * -swig_varlink_str(swig_varlinkobject *v) { -#if PY_VERSION_HEX >= 0x03000000 - PyObject *str = PyUnicode_InternFromString("("); - PyObject *tail; - PyObject *joined; - swig_globalvar *var; - for (var = v->vars; var; var=var->next) { - tail = PyUnicode_FromString(var->name); - joined = PyUnicode_Concat(str, tail); - Py_DecRef(str); - Py_DecRef(tail); - str = joined; - if (var->next) { - tail = PyUnicode_InternFromString(", "); - joined = PyUnicode_Concat(str, tail); - Py_DecRef(str); - Py_DecRef(tail); - str = joined; - } - } - tail = PyUnicode_InternFromString(")"); - joined = PyUnicode_Concat(str, tail); - Py_DecRef(str); - Py_DecRef(tail); - str = joined; -#else - PyObject *str = PyString_FromString("("); - swig_globalvar *var; - for (var = v->vars; var; var=var->next) { - PyString_ConcatAndDel(&str,PyString_FromString(var->name)); - if (var->next) PyString_ConcatAndDel(&str,PyString_FromString(", ")); - } - PyString_ConcatAndDel(&str,PyString_FromString(")")); -#endif - return str; -} - -SWIGINTERN void -swig_varlink_dealloc(swig_varlinkobject *v) { - swig_globalvar *var = v->vars; - while (var) { - swig_globalvar *n = var->next; - free(var->name); - free(var); - var = n; - } -} - -SWIGINTERN PyObject * -swig_varlink_getattr(swig_varlinkobject *v, char *n) { - PyObject *res = NULL; - swig_globalvar *var = v->vars; - while (var) { - if (strcmp(var->name,n) == 0) { - res = (*var->get_attr)(); - break; - } - var = var->next; - } - if (res == NULL && !PyErr_Occurred()) { - PyErr_Format(PyExc_AttributeError, "Unknown C global variable '%s'", n); - } - return res; -} - -SWIGINTERN int -swig_varlink_setattr(swig_varlinkobject *v, char *n, PyObject *p) { - int res = 1; - swig_globalvar *var = v->vars; - while (var) { - if (strcmp(var->name,n) == 0) { - res = (*var->set_attr)(p); - break; - } - var = var->next; - } - if (res == 1 && !PyErr_Occurred()) { - PyErr_Format(PyExc_AttributeError, "Unknown C global variable '%s'", n); - } - return res; -} - -SWIGINTERN PyTypeObject* -swig_varlink_type(void) { - static char varlink__doc__[] = "Swig var link object"; - static PyTypeObject varlink_type; - static int type_init = 0; - if (!type_init) { - const PyTypeObject tmp = { -#if PY_VERSION_HEX >= 0x03000000 - PyVarObject_HEAD_INIT(NULL, 0) -#else - PyObject_HEAD_INIT(NULL) - 0, /* ob_size */ -#endif - "swigvarlink", /* tp_name */ - sizeof(swig_varlinkobject), /* tp_basicsize */ - 0, /* tp_itemsize */ - (destructor) swig_varlink_dealloc, /* tp_dealloc */ - 0, /* tp_print */ - (getattrfunc) swig_varlink_getattr, /* tp_getattr */ - (setattrfunc) swig_varlink_setattr, /* tp_setattr */ - 0, /* tp_compare */ - (reprfunc) swig_varlink_repr, /* tp_repr */ - 0, /* tp_as_number */ - 0, /* tp_as_sequence */ - 0, /* tp_as_mapping */ - 0, /* tp_hash */ - 0, /* tp_call */ - (reprfunc) swig_varlink_str, /* tp_str */ - 0, /* tp_getattro */ - 0, /* tp_setattro */ - 0, /* tp_as_buffer */ - 0, /* tp_flags */ - varlink__doc__, /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* tp_iter -> tp_weaklist */ - 0, /* tp_del */ - 0, /* tp_version_tag */ -#if PY_VERSION_HEX >= 0x03040000 - 0, /* tp_finalize */ -#endif -#if PY_VERSION_HEX >= 0x03080000 - 0, /* tp_vectorcall */ -#endif -#if (PY_VERSION_HEX >= 0x03080000) && (PY_VERSION_HEX < 0x03090000) - 0, /* tp_print */ -#endif -#ifdef COUNT_ALLOCS - 0, /* tp_allocs */ - 0, /* tp_frees */ - 0, /* tp_maxalloc */ - 0, /* tp_prev */ - 0 /* tp_next */ -#endif - }; - varlink_type = tmp; - type_init = 1; - if (PyType_Ready(&varlink_type) < 0) - return NULL; - } - return &varlink_type; -} - -/* Create a variable linking object for use later */ -SWIGINTERN PyObject * -SWIG_Python_newvarlink(void) { - swig_varlinkobject *result = PyObject_NEW(swig_varlinkobject, swig_varlink_type()); - if (result) { - result->vars = 0; - } - return ((PyObject*) result); -} - -SWIGINTERN void -SWIG_Python_addvarlink(PyObject *p, const char *name, PyObject *(*get_attr)(void), int (*set_attr)(PyObject *p)) { - swig_varlinkobject *v = (swig_varlinkobject *) p; - swig_globalvar *gv = (swig_globalvar *) malloc(sizeof(swig_globalvar)); - if (gv) { - size_t size = strlen(name)+1; - gv->name = (char *)malloc(size); - if (gv->name) { - memcpy(gv->name, name, size); - gv->get_attr = get_attr; - gv->set_attr = set_attr; - gv->next = v->vars; - } - } - v->vars = gv; -} - -SWIGINTERN PyObject * -SWIG_globals(void) { - static PyObject *globals = 0; - if (!globals) { - globals = SWIG_newvarlink(); - } - return globals; -} - /* ----------------------------------------------------------------------------- * constants/methods manipulation * ----------------------------------------------------------------------------- */ diff --git a/Lib/python/pyrun.swg b/Lib/python/pyrun.swg index 0025184d1..17992453b 100644 --- a/Lib/python/pyrun.swg +++ b/Lib/python/pyrun.swg @@ -214,6 +214,222 @@ SWIG_Python_CheckNoKeywords(PyObject *kwargs, const char *name) { #define SWIG_STATIC_POINTER(var) var = 0; if (!var) var #endif +/* Python-specific SWIG API */ +#define SWIG_newvarlink() SWIG_Python_newvarlink() +#define SWIG_addvarlink(p, name, get_attr, set_attr) SWIG_Python_addvarlink(p, name, get_attr, set_attr) +#define SWIG_InstallConstants(d, constants) SWIG_Python_InstallConstants(d, constants) + +/* ----------------------------------------------------------------------------- + * global variable support code. + * ----------------------------------------------------------------------------- */ + +typedef struct swig_globalvar { + char *name; /* Name of global variable */ + PyObject *(*get_attr)(void); /* Return the current value */ + int (*set_attr)(PyObject *); /* Set the value */ + struct swig_globalvar *next; +} swig_globalvar; + +typedef struct swig_varlinkobject { + PyObject_HEAD + swig_globalvar *vars; +} swig_varlinkobject; + +SWIGINTERN PyObject * +swig_varlink_repr(swig_varlinkobject *SWIGUNUSEDPARM(v)) { +#if PY_VERSION_HEX >= 0x03000000 + return PyUnicode_InternFromString(""); +#else + return PyString_FromString(""); +#endif +} + +SWIGINTERN PyObject * +swig_varlink_str(swig_varlinkobject *v) { +#if PY_VERSION_HEX >= 0x03000000 + PyObject *str = PyUnicode_InternFromString("("); + PyObject *tail; + PyObject *joined; + swig_globalvar *var; + for (var = v->vars; var; var=var->next) { + tail = PyUnicode_FromString(var->name); + joined = PyUnicode_Concat(str, tail); + Py_DecRef(str); + Py_DecRef(tail); + str = joined; + if (var->next) { + tail = PyUnicode_InternFromString(", "); + joined = PyUnicode_Concat(str, tail); + Py_DecRef(str); + Py_DecRef(tail); + str = joined; + } + } + tail = PyUnicode_InternFromString(")"); + joined = PyUnicode_Concat(str, tail); + Py_DecRef(str); + Py_DecRef(tail); + str = joined; +#else + PyObject *str = PyString_FromString("("); + swig_globalvar *var; + for (var = v->vars; var; var=var->next) { + PyString_ConcatAndDel(&str,PyString_FromString(var->name)); + if (var->next) PyString_ConcatAndDel(&str,PyString_FromString(", ")); + } + PyString_ConcatAndDel(&str,PyString_FromString(")")); +#endif + return str; +} + +SWIGINTERN void +swig_varlink_dealloc(swig_varlinkobject *v) { + swig_globalvar *var = v->vars; + while (var) { + swig_globalvar *n = var->next; + free(var->name); + free(var); + var = n; + } +} + +SWIGINTERN PyObject * +swig_varlink_getattr(swig_varlinkobject *v, char *n) { + PyObject *res = NULL; + swig_globalvar *var = v->vars; + while (var) { + if (strcmp(var->name,n) == 0) { + res = (*var->get_attr)(); + break; + } + var = var->next; + } + if (res == NULL && !PyErr_Occurred()) { + PyErr_Format(PyExc_AttributeError, "Unknown C global variable '%s'", n); + } + return res; +} + +SWIGINTERN int +swig_varlink_setattr(swig_varlinkobject *v, char *n, PyObject *p) { + int res = 1; + swig_globalvar *var = v->vars; + while (var) { + if (strcmp(var->name,n) == 0) { + res = (*var->set_attr)(p); + break; + } + var = var->next; + } + if (res == 1 && !PyErr_Occurred()) { + PyErr_Format(PyExc_AttributeError, "Unknown C global variable '%s'", n); + } + return res; +} + +SWIGINTERN PyTypeObject* +swig_varlink_type(void) { + static char varlink__doc__[] = "Swig var link object"; + static PyTypeObject varlink_type; + static int type_init = 0; + if (!type_init) { + const PyTypeObject tmp = { +#if PY_VERSION_HEX >= 0x03000000 + PyVarObject_HEAD_INIT(NULL, 0) +#else + PyObject_HEAD_INIT(NULL) + 0, /* ob_size */ +#endif + "swigvarlink", /* tp_name */ + sizeof(swig_varlinkobject), /* tp_basicsize */ + 0, /* tp_itemsize */ + (destructor) swig_varlink_dealloc, /* tp_dealloc */ + 0, /* tp_print */ + (getattrfunc) swig_varlink_getattr, /* tp_getattr */ + (setattrfunc) swig_varlink_setattr, /* tp_setattr */ + 0, /* tp_compare */ + (reprfunc) swig_varlink_repr, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + (reprfunc) swig_varlink_str, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + 0, /* tp_flags */ + varlink__doc__, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* tp_iter -> tp_weaklist */ + 0, /* tp_del */ + 0, /* tp_version_tag */ +#if PY_VERSION_HEX >= 0x03040000 + 0, /* tp_finalize */ +#endif +#if PY_VERSION_HEX >= 0x03080000 + 0, /* tp_vectorcall */ +#endif +#if (PY_VERSION_HEX >= 0x03080000) && (PY_VERSION_HEX < 0x03090000) + 0, /* tp_print */ +#endif +#ifdef COUNT_ALLOCS + 0, /* tp_allocs */ + 0, /* tp_frees */ + 0, /* tp_maxalloc */ + 0, /* tp_prev */ + 0 /* tp_next */ +#endif + }; + varlink_type = tmp; + type_init = 1; + if (PyType_Ready(&varlink_type) < 0) + return NULL; + } + return &varlink_type; +} + +/* Create a variable linking object for use later */ +SWIGINTERN PyObject * +SWIG_Python_newvarlink(void) { + swig_varlinkobject *result = PyObject_NEW(swig_varlinkobject, swig_varlink_type()); + if (result) { + result->vars = 0; + } + return ((PyObject*) result); +} + +SWIGINTERN void +SWIG_Python_addvarlink(PyObject *p, const char *name, PyObject *(*get_attr)(void), int (*set_attr)(PyObject *p)) { + swig_varlinkobject *v = (swig_varlinkobject *) p; + swig_globalvar *gv = (swig_globalvar *) malloc(sizeof(swig_globalvar)); + if (gv) { + size_t size = strlen(name)+1; + gv->name = (char *)malloc(size); + if (gv->name) { + memcpy(gv->name, name, size); + gv->get_attr = get_attr; + gv->set_attr = set_attr; + gv->next = v->vars; + } + } + v->vars = gv; +} + + +static PyObject *Swig_Globals_global = NULL; + +SWIGINTERN PyObject * +SWIG_globals(void) { + if (Swig_Globals_global == NULL) { + Swig_Globals_global = SWIG_newvarlink(); + } + return Swig_Globals_global; +} + /* ----------------------------------------------------------------------------- * Pointer declarations * ----------------------------------------------------------------------------- */ @@ -1390,11 +1606,15 @@ SWIG_Python_NewPackedObj(void *ptr, size_t sz, swig_type_info *type) { void *SWIG_ReturnGlobalTypeList(void *); #endif +static PyObject *Swig_TypeCache_global = NULL; + /* The python cached type query */ SWIGRUNTIME PyObject * SWIG_Python_TypeCache(void) { - static PyObject *SWIG_STATIC_POINTER(cache) = PyDict_New(); - return cache; + if (Swig_TypeCache_global == NULL) { + Swig_TypeCache_global = PyDict_New(); + } + return Swig_TypeCache_global; } SWIGRUNTIME swig_module_info * @@ -1431,7 +1651,10 @@ SWIG_Python_DestroyModule(PyObject *obj) } Py_DECREF(SWIG_This()); Swig_This_global = NULL; + Py_DECREF(SWIG_globals()); + Swig_Globals_global = NULL; Py_DECREF(SWIG_Python_TypeCache()); + Swig_TypeCache_global = NULL; } SWIGRUNTIME void diff --git a/Source/Modules/python.cxx b/Source/Modules/python.cxx index 7d618635e..8682e6917 100644 --- a/Source/Modules/python.cxx +++ b/Source/Modules/python.cxx @@ -3424,7 +3424,6 @@ public: Printf(f_init, "#endif\n"); Printf(f_init, "\t }\n"); Printf(f_init, "\t PyDict_SetItemString(md, \"%s\", globals);\n", global_name); - Printf(f_init, "\t Py_DECREF(globals);\n"); if (builtin) Printf(f_init, "\t SwigPyBuiltin_AddPublicSymbol(public_interface, \"%s\");\n", global_name); have_globals = 1; From 26d693105a61da8fa1c679bc4425452021351499 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Wed, 1 Dec 2021 18:13:15 +0000 Subject: [PATCH 016/662] GHA: Test node versions 6,8,10 Test the documented minimum version 6 and some later versions as was done on Travis. Using ubuntu-18.04 as I couldn't get these versions to work on newer ubuntu-20.04 (some horrid c++ compilation errors) --- .github/workflows/ci.yml | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ab8c68d1f..5374c5428 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -64,6 +64,21 @@ jobs: VER: '1.17' - SWIGLANG: guile - SWIGLANG: java + - SWIGLANG: javascript + ENGINE: node + VER: '6' + CPPSTD: c++11 + os: ubuntu-18.04 + - SWIGLANG: javascript + ENGINE: node + VER: '8' + CPPSTD: c++11 + os: ubuntu-18.04 + - SWIGLANG: javascript + ENGINE: node + VER: '10' + CPPSTD: c++11 + os: ubuntu-18.04 - SWIGLANG: javascript ENGINE: node VER: '12' From 160b8c5da38ea2c1ef5c23a45cd4e5f65a2f8ec1 Mon Sep 17 00:00:00 2001 From: John Senneker Date: Wed, 1 Dec 2021 15:15:24 -0500 Subject: [PATCH 017/662] Added extern "C" block that was removed in previous commit. --- Lib/python/pyrun.swg | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Lib/python/pyrun.swg b/Lib/python/pyrun.swg index 17992453b..a49cbb5b3 100644 --- a/Lib/python/pyrun.swg +++ b/Lib/python/pyrun.swg @@ -214,6 +214,10 @@ SWIG_Python_CheckNoKeywords(PyObject *kwargs, const char *name) { #define SWIG_STATIC_POINTER(var) var = 0; if (!var) var #endif +#ifdef __cplusplus +extern "C" { +#endif + /* Python-specific SWIG API */ #define SWIG_newvarlink() SWIG_Python_newvarlink() #define SWIG_addvarlink(p, name, get_attr, set_attr) SWIG_Python_addvarlink(p, name, get_attr, set_attr) @@ -430,6 +434,10 @@ SWIG_globals(void) { return Swig_Globals_global; } +#ifdef __cplusplus +} +#endif + /* ----------------------------------------------------------------------------- * Pointer declarations * ----------------------------------------------------------------------------- */ From e30dfeaab981d3eda82775130bb61446da1782a9 Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Thu, 2 Dec 2021 14:01:27 +1300 Subject: [PATCH 018/662] [js] Update docs re v8 support We require at least node v6 (which means v8 v5.0) since 7ba19e758632c8aeddcf82ddf48a05f34e218bc9 so updated the manual to reflect this. --- Doc/Manual/Javascript.html | 20 +++----------------- 1 file changed, 3 insertions(+), 17 deletions(-) diff --git a/Doc/Manual/Javascript.html b/Doc/Manual/Javascript.html index 54bd68521..ab8657510 100644 --- a/Doc/Manual/Javascript.html +++ b/Doc/Manual/Javascript.html @@ -89,24 +89,10 @@ $ swig -javascript -jsc example.i
 $ swig -c++ -javascript -jsc example.i
-

The V8 code that SWIG generates should work with most versions from 3.11.10. -However, the only early version that receives some testing is 3.14.5, which is -still shipped with Ubuntu for some reason. Other than that it's probably safer -to assume that versions earlier than 5.0 are no longer supported. Keep in mind -that these are V8 versions, not Node.js. To give some perspective, Node.js v6.0 +

The V8 code that SWIG generates requires at least V8 5.0. Keep in mind +that this is theV8 version, not Node.js. To give some perspective, Node.js v6.0 uses V8 5.0, v12.0 - 7.4, v14.0 - 8.1...

-

The API headers for V8 >= 4.3.10 define constants which SWIG can use to -determine the V8 version it is compiling for. For versions < 4.3.10, you -need to specify the V8 version when running SWIG. This is specified as a hex -constant, but the constant is read as pairs of decimal digits, so for V8 -3.25.30 use constant 0x032530. This scheme can't represent components > 99, -but this constant is only useful for V8 < 4.3.10, and no V8 versions from -that era had a component > 99. For example:

-
-
-$ swig -c++ -javascript -v8 -DV8_VERSION=0x032530 example.i
-
-

If you're targeting V8 >= 4.3.10, you would just run swig like so:

+

To generate code for V8, you would run swig like so:

 $ swig -c++ -javascript -v8 example.i
From 7c97bd5ab305527d1c14a264325e11ae59f2f6b1 Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Thu, 2 Dec 2021 14:02:59 +1300 Subject: [PATCH 019/662] [js] Remove code to handle v8 < 5.0 We require at least node v6 which means v8 5.0, so code to handle older v8 is no longer useful. --- Lib/javascript/v8/javascriptcode.swg | 96 +-------- Lib/javascript/v8/javascripthelpers.swg | 30 --- Lib/javascript/v8/javascriptinit.swg | 8 - Lib/javascript/v8/javascriptrun.swg | 247 +----------------------- Lib/javascript/v8/javascriptruntime.swg | 34 +--- Lib/javascript/v8/javascriptstrings.swg | 8 - Tools/javascript/v8_shell.cxx | 50 ----- 7 files changed, 10 insertions(+), 463 deletions(-) diff --git a/Lib/javascript/v8/javascriptcode.swg b/Lib/javascript/v8/javascriptcode.swg index 2abed9488..dcda0ee63 100644 --- a/Lib/javascript/v8/javascriptcode.swg +++ b/Lib/javascript/v8/javascriptcode.swg @@ -105,17 +105,10 @@ fail: %{ if(args.Length() == $jsargcount) { errorHandler.err.Clear(); -#if (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x031903) - self = $jswrapper(args, errorHandler); - if(errorHandler.err.IsEmpty()) { - SWIGV8_ESCAPE(self); - } -#else $jswrapper(args, errorHandler); if(errorHandler.err.IsEmpty()) { return; } -#endif } %} @@ -127,22 +120,8 @@ fail: %fragment ("js_dtor", "templates") %{ -#if (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x031710) -static void $jswrapper(v8::Persistent< v8::Value > object, void *parameter) { - SWIGV8_Proxy *proxy = static_cast(parameter); -#elif (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x031900) -static void $jswrapper(v8::Isolate *isolate, v8::Persistent object, void *parameter) { - SWIGV8_Proxy *proxy = static_cast(parameter); -#elif (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < SWIGV8_SETWEAK_VERSION) -static void $jswrapper(v8::Isolate *isolate, v8::Persistent *object, SWIGV8_Proxy *proxy) { -#elif (V8_MAJOR_VERSION-0) < 5 -static void $jswrapper(const v8::WeakCallbackData &data) { - v8::Local object = data.GetValue(); +static void $jswrapper(const v8::WeakCallbackInfo &data) { SWIGV8_Proxy *proxy = data.GetParameter(); -#else - static void $jswrapper(const v8::WeakCallbackInfo &data) { - SWIGV8_Proxy *proxy = data.GetParameter(); -#endif if(proxy->swigCMemOwn && proxy->swigCObject) { #ifdef SWIGRUNTIME_DEBUG @@ -151,20 +130,6 @@ static void $jswrapper(const v8::WeakCallbackData &dat $jsfree proxy->swigCObject; } delete proxy; - -#if (V8_MAJOR_VERSION-0) < 5 - object.Clear(); -#endif - -#if (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x031710) - object.Dispose(); -#elif (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x031900) - object.Dispose(isolate); -#elif (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x032100) - object->Dispose(isolate); -#elif (V8_MAJOR_VERSION-0) < 5 - object->Dispose(); -#endif } %} @@ -176,40 +141,14 @@ static void $jswrapper(const v8::WeakCallbackData &dat * ----------------------------------------------------------------------------- */ %fragment ("js_dtoroverride", "templates") %{ -#if (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x031710) -static void $jswrapper(v8::Persistent object, void *parameter) { - SWIGV8_Proxy *proxy = static_cast(parameter); -#elif (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x031900) -static void $jswrapper(v8::Isolate *isolate, v8::Persistent object, void *parameter) { - SWIGV8_Proxy *proxy = static_cast(parameter); -#elif (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < SWIGV8_SETWEAK_VERSION) -static void $jswrapper(v8::Isolate *isolate, v8::Persistent< v8::Object> *object, SWIGV8_Proxy *proxy) { -#elif (V8_MAJOR_VERSION-0) < 5 -static void $jswrapper(const v8::WeakCallbackData &data) { - v8::Local object = data.GetValue(); - SWIGV8_Proxy *proxy = data.GetParameter(); -#else static void $jswrapper(const v8::WeakCallbackInfo &data) { SWIGV8_Proxy *proxy = data.GetParameter(); -#endif if(proxy->swigCMemOwn && proxy->swigCObject) { $jstype arg1 = ($jstype)proxy->swigCObject; ${destructor_action} } delete proxy; - -#if (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x031710) - object.Dispose(); -#elif (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x031900) - object.Dispose(isolate); -#elif (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x032100) - object->Dispose(isolate); -#elif (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < SWIGV8_SETWEAK_VERSION) - object->Dispose(); -#elif (V8_MAJOR_VERSION-0) < 5 - object.Clear(); -#endif } %} @@ -221,11 +160,7 @@ static void $jswrapper(const v8::WeakCallbackInfo &data) { * ----------------------------------------------------------------------------- */ %fragment("js_getter", "templates") %{ -#if (V8_MAJOR_VERSION-0) < 5 -static SwigV8ReturnValue $jswrapper(v8::Local property, const SwigV8PropertyCallbackInfo &info) { -#else static SwigV8ReturnValue $jswrapper(v8::Local property, const SwigV8PropertyCallbackInfo &info) { -#endif SWIGV8_HANDLESCOPE(); SWIGV8_VALUE jsresult; @@ -247,11 +182,7 @@ fail: * ----------------------------------------------------------------------------- */ %fragment("js_setter", "templates") %{ -#if (V8_MAJOR_VERSION-0) < 5 -static void $jswrapper(v8::Local property, v8::Local value, const SwigV8PropertyCallbackInfoVoid &info) { -#else static void $jswrapper(v8::Local property, v8::Local value, const SwigV8PropertyCallbackInfoVoid &info) { -#endif SWIGV8_HANDLESCOPE(); $jslocals @@ -344,17 +275,10 @@ fail: if(args.Length() == $jsargcount) { errorHandler.err.Clear(); -#if (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x031903) - jsresult = $jswrapper(args, errorHandler); - if(errorHandler.err.IsEmpty()) { - SWIGV8_ESCAPE(jsresult); - } -#else $jswrapper(args, errorHandler); if(errorHandler.err.IsEmpty()) { return; } -#endif } %} @@ -394,15 +318,11 @@ fail: %{ if (SWIGTYPE_p$jsbaseclass->clientdata && !(static_cast(SWIGTYPE_p$jsbaseclass->clientdata)->class_templ.IsEmpty())) { -#if (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x031903) - $jsmangledname_class->Inherit(static_cast(SWIGTYPE_p$jsbaseclass->clientdata)->class_templ); -#else $jsmangledname_class->Inherit( v8::Local::New( v8::Isolate::GetCurrent(), static_cast(SWIGTYPE_p$jsbaseclass->clientdata)->class_templ) ); -#endif #ifdef SWIGRUNTIME_DEBUG printf("Inheritance successful $jsmangledname $jsbaseclass\n"); @@ -425,10 +345,7 @@ fail: SWIGV8_FUNCTION_TEMPLATE $jsmangledname_class_0 = SWIGV8_CreateClassTemplate("$jsname"); $jsmangledname_class_0->SetCallHandler($jsctor); $jsmangledname_class_0->Inherit($jsmangledname_class); -#if (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x031903) - $jsmangledname_class_0->SetHiddenPrototype(true); - v8::Handle $jsmangledname_obj = $jsmangledname_class_0->GetFunction(); -#elif (SWIG_V8_VERSION < 0x0704) +#if (SWIG_V8_VERSION < 0x0704) $jsmangledname_class_0->SetHiddenPrototype(true); v8::Local $jsmangledname_obj = $jsmangledname_class_0->GetFunction(); #else @@ -444,12 +361,7 @@ fail: * ----------------------------------------------------------------------------- */ %fragment("jsv8_register_class", "templates") %{ -#if (V8_MAJOR_VERSION-0) < 5 - $jsparent_obj->Set(SWIGV8_SYMBOL_NEW("$jsname"), $jsmangledname_obj); -#else SWIGV8_MAYBE_CHECK($jsparent_obj->Set(context, SWIGV8_SYMBOL_NEW("$jsname"), $jsmangledname_obj)); -#endif - %} /* ----------------------------------------------------------------------------- @@ -469,11 +381,7 @@ fail: * ----------------------------------------------------------------------------- */ %fragment("jsv8_register_namespace", "templates") %{ -#if (V8_MAJOR_VERSION-0) < 5 - $jsparent_obj->Set(SWIGV8_SYMBOL_NEW("$jsname"), $jsmangledname_obj); -#else SWIGV8_MAYBE_CHECK($jsparent_obj->Set(context, SWIGV8_SYMBOL_NEW("$jsname"), $jsmangledname_obj)); -#endif %} /* ----------------------------------------------------------------------------- diff --git a/Lib/javascript/v8/javascripthelpers.swg b/Lib/javascript/v8/javascripthelpers.swg index fdbff000e..ea303fa3d 100644 --- a/Lib/javascript/v8/javascripthelpers.swg +++ b/Lib/javascript/v8/javascripthelpers.swg @@ -1,22 +1,9 @@ %insert(runtime) %{ -// Note: since 3.19 there are new CallBack types, since 03.21.9 the old ones have been removed -#if (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x031903) -typedef v8::InvocationCallback SwigV8FunctionCallback; -typedef v8::AccessorGetter SwigV8AccessorGetterCallback; -typedef v8::AccessorSetter SwigV8AccessorSetterCallback; -typedef v8::AccessorInfo SwigV8PropertyCallbackInfoVoid; -#elif (V8_MAJOR_VERSION-0) < 5 -typedef v8::FunctionCallback SwigV8FunctionCallback; -typedef v8::AccessorGetterCallback SwigV8AccessorGetterCallback; -typedef v8::AccessorSetterCallback SwigV8AccessorSetterCallback; -typedef v8::PropertyCallbackInfo SwigV8PropertyCallbackInfoVoid; -#else typedef v8::FunctionCallback SwigV8FunctionCallback; typedef v8::AccessorNameGetterCallback SwigV8AccessorGetterCallback; typedef v8::AccessorNameSetterCallback SwigV8AccessorSetterCallback; typedef v8::PropertyCallbackInfo SwigV8PropertyCallbackInfoVoid; -#endif /** * Creates a class template for a class with specified initialization function. @@ -62,11 +49,7 @@ SWIGRUNTIME void SWIGV8_AddMemberVariable(SWIGV8_FUNCTION_TEMPLATE class_templ, */ SWIGRUNTIME void SWIGV8_AddStaticFunction(SWIGV8_OBJECT obj, const char* symbol, const SwigV8FunctionCallback& _func, v8::Local context) { -#if (V8_MAJOR_VERSION-0) < 5 - obj->Set(SWIGV8_SYMBOL_NEW(symbol), SWIGV8_FUNCTEMPLATE_NEW(_func)->GetFunction()); -#else SWIGV8_MAYBE_CHECK(obj->Set(context, SWIGV8_SYMBOL_NEW(symbol), SWIGV8_FUNCTEMPLATE_NEW(_func)->GetFunction(context).ToLocalChecked())); -#endif } /** @@ -75,27 +58,15 @@ SWIGRUNTIME void SWIGV8_AddStaticFunction(SWIGV8_OBJECT obj, const char* symbol, SWIGRUNTIME void SWIGV8_AddStaticVariable(SWIGV8_OBJECT obj, const char* symbol, SwigV8AccessorGetterCallback getter, SwigV8AccessorSetterCallback setter, v8::Local context) { -#if (V8_MAJOR_VERSION-0) < 5 - obj->SetAccessor(SWIGV8_SYMBOL_NEW(symbol), getter, setter); -#else SWIGV8_MAYBE_CHECK(obj->SetAccessor(context, SWIGV8_SYMBOL_NEW(symbol), getter, setter)); -#endif } -#if (V8_MAJOR_VERSION-0) < 5 -SWIGRUNTIME void JS_veto_set_variable(v8::Local property, v8::Local value, const SwigV8PropertyCallbackInfoVoid& info) -#else SWIGRUNTIME void JS_veto_set_variable(v8::Local property, v8::Local value, const SwigV8PropertyCallbackInfoVoid& info) -#endif { char buffer[256]; char msg[512]; int res; -#if (V8_MAJOR_VERSION-0) < 5 - property->WriteUtf8(buffer, 256); - res = sprintf(msg, "Tried to write read-only variable: %s.", buffer); -#else v8::Local sproperty; if (property->ToString(SWIGV8_CURRENT_CONTEXT()).ToLocal(&sproperty)) { SWIGV8_WRITE_UTF8(sproperty, buffer, 256); @@ -104,7 +75,6 @@ SWIGRUNTIME void JS_veto_set_variable(v8::Local property, v8::Local context, swig_module_info *swig_module) v8::Local global_obj = context->Global(); v8::Local mod = SWIGV8_EXTERNAL_NEW(swig_module); assert(!mod.IsEmpty()); -#if (V8_MAJOR_VERSION-0) < 5 - global_obj->SetHiddenValue(SWIGV8_STRING_NEW("swig_module_info_data"), mod); -#else v8::Local privateKey = v8::Private::ForApi(v8::Isolate::GetCurrent(), SWIGV8_STRING_NEW("swig_module_info_data")); global_obj->SetPrivate(context, privateKey, mod); -#endif } SWIGRUNTIME swig_module_info * SWIG_V8_GetModule(v8::Local context) { v8::Local global_obj = context->Global(); -#if (V8_MAJOR_VERSION-0) < 5 - v8::Local moduleinfo = global_obj->GetHiddenValue(SWIGV8_STRING_NEW("swig_module_info_data")); -#else v8::Local privateKey = v8::Private::ForApi(v8::Isolate::GetCurrent(), SWIGV8_STRING_NEW("swig_module_info_data")); v8::Local moduleinfo; if (!global_obj->GetPrivate(context, privateKey).ToLocal(&moduleinfo)) return 0; -#endif if (moduleinfo.IsEmpty() || moduleinfo->IsNull() || moduleinfo->IsUndefined()) { diff --git a/Lib/javascript/v8/javascriptrun.swg b/Lib/javascript/v8/javascriptrun.swg index 2df342416..518b19a8f 100644 --- a/Lib/javascript/v8/javascriptrun.swg +++ b/Lib/javascript/v8/javascriptrun.swg @@ -4,56 +4,26 @@ * Useful table of versions: https://nodejs.org/en/download/releases/ * ---------------------------------------------------------------------------*/ -// First v8 version that uses "SetWeak" and not "MakeWeak" - -#define SWIGV8_SETWEAK_VERSION 0x032224 - -#if (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x031803) -#define SWIGV8_STRING_NEW2(cstr, len) v8::String::New(cstr, len) -#elif (SWIG_V8_VERSION < 0x0704) +#if (SWIG_V8_VERSION < 0x0704) #define SWIGV8_STRING_NEW2(cstr, len) v8::String::NewFromUtf8(v8::Isolate::GetCurrent(), cstr, v8::String::kNormalString, len) #else #define SWIGV8_STRING_NEW2(cstr, len) (v8::String::NewFromUtf8(v8::Isolate::GetCurrent(), cstr, v8::NewStringType::kNormal, len)).ToLocalChecked() #endif -#if (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x031903) -typedef v8::Handle SwigV8ReturnValue; -typedef v8::Arguments SwigV8Arguments; -typedef v8::AccessorInfo SwigV8PropertyCallbackInfo; -#define SWIGV8_RETURN(val) return scope.Close(val) -#define SWIGV8_RETURN_INFO(val, info) return scope.Close(val) -#else typedef void SwigV8ReturnValue; typedef v8::FunctionCallbackInfo SwigV8Arguments; typedef v8::PropertyCallbackInfo SwigV8PropertyCallbackInfo; #define SWIGV8_RETURN(val) args.GetReturnValue().Set(val); return #define SWIGV8_RETURN_INFO(val, info) info.GetReturnValue().Set(val); return -#endif -#if (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x032117) -#define SWIGV8_HANDLESCOPE() v8::HandleScope scope -#define SWIGV8_HANDLESCOPE_ESC() v8::HandleScope scope -#define SWIGV8_ESCAPE(val) return scope.Close(val) -#elif (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x032224) -#define SWIGV8_HANDLESCOPE() v8::HandleScope scope(v8::Isolate::GetCurrent()); -#define SWIGV8_HANDLESCOPE_ESC() v8::HandleScope scope(v8::Isolate::GetCurrent()); -#define SWIGV8_ESCAPE(val) return scope.Close(val) -#else #define SWIGV8_HANDLESCOPE() v8::HandleScope scope(v8::Isolate::GetCurrent()); #define SWIGV8_HANDLESCOPE_ESC() v8::EscapableHandleScope scope(v8::Isolate::GetCurrent()); #define SWIGV8_ESCAPE(val) return scope.Escape(val) -#endif -#if (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x032224) -#define SWIGV8_ADJUST_MEMORY(size) v8::V8::AdjustAmountOfExternalAllocatedMemory(size) -#define SWIGV8_CURRENT_CONTEXT() v8::Context::GetCurrent() -#define SWIGV8_THROW_EXCEPTION(err) v8::ThrowException(err) -#define SWIGV8_STRING_NEW(str) v8::String::New(str) -#define SWIGV8_SYMBOL_NEW(sym) v8::String::NewSymbol(sym) -#else #define SWIGV8_ADJUST_MEMORY(size) v8::Isolate::GetCurrent()->AdjustAmountOfExternalAllocatedMemory(size) #define SWIGV8_CURRENT_CONTEXT() v8::Isolate::GetCurrent()->GetCurrentContext() #define SWIGV8_THROW_EXCEPTION(err) v8::Isolate::GetCurrent()->ThrowException(err) + #if (SWIG_V8_VERSION < 0x0704) #define SWIGV8_STRING_NEW(str) v8::String::NewFromUtf8(v8::Isolate::GetCurrent(), str, v8::String::kNormalString) #define SWIGV8_SYMBOL_NEW(sym) v8::String::NewFromUtf8(v8::Isolate::GetCurrent(), sym, v8::String::kNormalString) @@ -61,37 +31,13 @@ typedef v8::PropertyCallbackInfo SwigV8PropertyCallbackInfo; #define SWIGV8_STRING_NEW(str) (v8::String::NewFromUtf8(v8::Isolate::GetCurrent(), str, v8::NewStringType::kNormal)).ToLocalChecked() #define SWIGV8_SYMBOL_NEW(sym) (v8::String::NewFromUtf8(v8::Isolate::GetCurrent(), sym, v8::NewStringType::kNormal)).ToLocalChecked() #endif -#endif -#if (V8_MAJOR_VERSION-0) < 5 -#define SWIGV8_MAYBE_CHECK(maybe) maybe -#elif (SWIG_V8_VERSION < 0x0704) +#if (SWIG_V8_VERSION < 0x0704) #define SWIGV8_MAYBE_CHECK(maybe) maybe.FromJust() #else #define SWIGV8_MAYBE_CHECK(maybe) maybe.Check() #endif -#if (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x032318) -#define SWIGV8_ARRAY_NEW(size) v8::Array::New(size) -#define SWIGV8_BOOLEAN_NEW(bool) v8::Boolean::New(bool) -#define SWIGV8_EXTERNAL_NEW(val) v8::External::New(val) -#define SWIGV8_FUNCTEMPLATE_NEW(func) v8::FunctionTemplate::New(func) -#define SWIGV8_FUNCTEMPLATE_NEW_VOID() v8::FunctionTemplate::New() -#define SWIGV8_INT32_NEW(num) v8::Int32::New(num) -#define SWIGV8_INTEGER_NEW(num) v8::Integer::New(num) -#define SWIGV8_INTEGER_NEW_UNS(num) v8::Integer::NewFromUnsigned(num) -#define SWIGV8_NUMBER_NEW(num) v8::Number::New(num) -#define SWIGV8_OBJECT_NEW() v8::Object::New() -#define SWIGV8_UNDEFINED() v8::Undefined() -#define SWIGV8_ARRAY v8::Handle -#define SWIGV8_FUNCTION_TEMPLATE v8::Handle -#define SWIGV8_OBJECT v8::Handle -#define SWIGV8_OBJECT_TEMPLATE v8::Handle -#define SWIGV8_VALUE v8::Handle -#define SWIGV8_NULL() v8::Null() -#define SWIGV8_ARRAY_GET(array, index) (array)->Get(index) -#define SWIGV8_ARRAY_SET(array, index, value) (array)->Set(index, value) -#else #define SWIGV8_ARRAY_NEW(size) v8::Array::New(v8::Isolate::GetCurrent(), size) #define SWIGV8_BOOLEAN_NEW(bool) v8::Boolean::New(v8::Isolate::GetCurrent(), bool) #define SWIGV8_EXTERNAL_NEW(val) v8::External::New(v8::Isolate::GetCurrent(), val) @@ -111,17 +57,10 @@ typedef v8::PropertyCallbackInfo SwigV8PropertyCallbackInfo; #define SWIGV8_NULL() v8::Null(v8::Isolate::GetCurrent()) #define SWIGV8_ARRAY_GET(array, index) (array)->Get(SWIGV8_CURRENT_CONTEXT(), index).ToLocalChecked() #define SWIGV8_ARRAY_SET(array, index, value) SWIGV8_MAYBE_CHECK((array)->Set(SWIGV8_CURRENT_CONTEXT(), index, value)) -#endif -#if (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x031710) -#define SWIGV8_SET_CLASS_TEMPL(class_templ, class) class_templ = v8::Persistent::New(class); -#elif (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x031900) -#define SWIGV8_SET_CLASS_TEMPL(class_templ, class) class_templ = v8::Persistent::New(v8::Isolate::GetCurrent(), class); -#else #define SWIGV8_SET_CLASS_TEMPL(class_templ, class) class_templ.Reset(v8::Isolate::GetCurrent(), class); -#endif -#if (V8_MAJOR_VERSION-0) < 6 || (SWIG_V8_VERSION < 0x0608) +#if SWIG_V8_VERSION < 0x0608 #define SWIGV8_TO_OBJECT(handle) (handle)->ToObject() #define SWIGV8_TO_STRING(handle) (handle)->ToString() #define SWIGV8_NUMBER_VALUE(handle) (handle)->NumberValue() @@ -208,23 +147,8 @@ public: }; ~SWIGV8_Proxy() { -#if (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x031710) - handle.ClearWeak(); - handle.Dispose(); -#elif (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x032100) - handle.ClearWeak(v8::Isolate::GetCurrent()); - handle.Dispose(v8::Isolate::GetCurrent()); -#elif (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < SWIGV8_SETWEAK_VERSION) - handle.ClearWeak(); - handle.Dispose(); -#else handle.ClearWeak(); handle.Reset(); -#endif - -#if (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < SWIGV8_SETWEAK_VERSION) - handle.Clear(); -#endif SWIGV8_ADJUST_MEMORY(-SWIGV8_AVG_OBJ_SIZE); } @@ -239,17 +163,7 @@ class SWIGV8_ClientData { public: v8::Persistent class_templ; -#if (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x031710) - void (*dtor) (v8::Persistent< v8::Value> object, void *parameter); -#elif (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x031900) - void (*dtor) (v8::Isolate *isolate, v8::Persistent< v8::Value> object, void *parameter); -#elif (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < SWIGV8_SETWEAK_VERSION) - void (*dtor) (v8::Isolate *isolate, v8::Persistent< v8::Object > *object, SWIGV8_Proxy *proxy); -#elif (V8_MAJOR_VERSION-0) < 5 - void (*dtor) (const v8::WeakCallbackData &data); -#else void (*dtor) (const v8::WeakCallbackInfo &data); -#endif }; SWIGRUNTIME v8::Persistent SWIGV8_SWIGTYPE_Proxy_class_templ; @@ -259,12 +173,7 @@ SWIGRUNTIME int SWIG_V8_ConvertInstancePtr(SWIGV8_OBJECT objRef, void **ptr, swi if(objRef->InternalFieldCount() < 1) return SWIG_ERROR; -#if (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x031511) - v8::Handle cdataRef = objRef->GetInternalField(0); - SWIGV8_Proxy *cdata = static_cast(v8::External::Unwrap(cdataRef)); -#else SWIGV8_Proxy *cdata = static_cast(objRef->GetAlignedPointerFromInternalField(0)); -#endif if(cdata == NULL) { return SWIG_ERROR; @@ -292,22 +201,8 @@ SWIGRUNTIME int SWIG_V8_ConvertInstancePtr(SWIGV8_OBJECT objRef, void **ptr, swi } -#if (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x031710) -SWIGRUNTIME void SWIGV8_Proxy_DefaultDtor(v8::Persistent< v8::Value > object, void *parameter) { - SWIGV8_Proxy *proxy = static_cast(parameter); -#elif (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x031900) -SWIGRUNTIME void SWIGV8_Proxy_DefaultDtor(v8::Isolate *, v8::Persistent< v8::Value > object, void *parameter) { - SWIGV8_Proxy *proxy = static_cast(parameter); -#elif (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < SWIGV8_SETWEAK_VERSION) -SWIGRUNTIME void SWIGV8_Proxy_DefaultDtor(v8::Isolate *, v8::Persistent< v8::Object > *object, SWIGV8_Proxy *proxy) { -#elif (V8_MAJOR_VERSION-0) < 5 -SWIGRUNTIME void SWIGV8_Proxy_DefaultDtor(const v8::WeakCallbackData &data) { - SWIGV8_Proxy *proxy = data.GetParameter(); -#else SWIGRUNTIME void SWIGV8_Proxy_DefaultDtor(const v8::WeakCallbackInfo &data) { SWIGV8_Proxy *proxy = data.GetParameter(); -#endif - delete proxy; } @@ -319,12 +214,7 @@ SWIGRUNTIME int SWIG_V8_GetInstancePtr(SWIGV8_VALUE valRef, void **ptr) { if(objRef->InternalFieldCount() < 1) return SWIG_ERROR; -#if (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x031511) - v8::Handle cdataRef = objRef->GetInternalField(0); - SWIGV8_Proxy *cdata = static_cast(v8::External::Unwrap(cdataRef)); -#else SWIGV8_Proxy *cdata = static_cast(objRef->GetAlignedPointerFromInternalField(0)); -#endif if(cdata == NULL) { return SWIG_ERROR; @@ -341,58 +231,17 @@ SWIGRUNTIME void SWIGV8_SetPrivateData(SWIGV8_OBJECT obj, void *ptr, swig_type_i cdata->swigCMemOwn = (flags & SWIG_POINTER_OWN) ? 1 : 0; cdata->info = info; -#if (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x031511) - obj->SetPointerInInternalField(0, cdata); -#else obj->SetAlignedPointerInInternalField(0, cdata); -#endif -#if (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x031710) - cdata->handle = v8::Persistent::New(obj); -#elif (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x031900) - cdata->handle = v8::Persistent::New(v8::Isolate::GetCurrent(), obj); -#else cdata->handle.Reset(v8::Isolate::GetCurrent(), obj); -#endif -#if (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x031710) - // clientdata must be set for owned data as we need to register the dtor - if(cdata->swigCMemOwn && (SWIGV8_ClientData*)info->clientdata) { - cdata->handle.MakeWeak(cdata, ((SWIGV8_ClientData*)info->clientdata)->dtor); - } else { - cdata->handle.MakeWeak(cdata, SWIGV8_Proxy_DefaultDtor); - } -#elif (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x031918) - if(cdata->swigCMemOwn && (SWIGV8_ClientData*)info->clientdata) { - cdata->handle.MakeWeak(v8::Isolate::GetCurrent(), cdata, ((SWIGV8_ClientData*)info->clientdata)->dtor); - } else { - cdata->handle.MakeWeak(v8::Isolate::GetCurrent(), cdata, SWIGV8_Proxy_DefaultDtor); - } -#elif (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < SWIGV8_SETWEAK_VERSION) - if(cdata->swigCMemOwn && (SWIGV8_ClientData*)info->clientdata) { - cdata->handle.MakeWeak(cdata, ((SWIGV8_ClientData*)info->clientdata)->dtor); - } else { - cdata->handle.MakeWeak(cdata, SWIGV8_Proxy_DefaultDtor); - } -#elif (V8_MAJOR_VERSION-0) < 5 - if(cdata->swigCMemOwn && (SWIGV8_ClientData*)info->clientdata) { - cdata->handle.SetWeak(cdata, ((SWIGV8_ClientData*)info->clientdata)->dtor); - } else { - cdata->handle.SetWeak(cdata, SWIGV8_Proxy_DefaultDtor); - } -#else if(cdata->swigCMemOwn && (SWIGV8_ClientData*)info->clientdata) { cdata->handle.SetWeak(cdata, ((SWIGV8_ClientData*)info->clientdata)->dtor, v8::WeakCallbackType::kParameter); } else { cdata->handle.SetWeak(cdata, SWIGV8_Proxy_DefaultDtor, v8::WeakCallbackType::kParameter); } -#endif -#if (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x031710) - cdata->handle.MarkIndependent(); -#elif (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x032100) - cdata->handle.MarkIndependent(v8::Isolate::GetCurrent()); -#elif (SWIG_V8_VERSION < 0x0704) +#if (SWIG_V8_VERSION < 0x0704) cdata->handle.MarkIndependent(); // Looks like future versions do not require that anymore: // https://monorail-prod.appspot.com/p/chromium/issues/detail?id=923361#c11 @@ -420,21 +269,10 @@ SWIGRUNTIME SWIGV8_VALUE SWIG_V8_NewPointerObj(void *ptr, swig_type_info *info, SWIGV8_FUNCTION_TEMPLATE class_templ; if (ptr == NULL) { -#if (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x031903) - SWIGV8_ESCAPE(SWIGV8_NULL()); -#else v8::Local result = SWIGV8_NULL(); SWIGV8_ESCAPE(result); -#endif } -#if (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x031903) - if(info->clientdata != 0) { - class_templ = ((SWIGV8_ClientData*) info->clientdata)->class_templ; - } else { - class_templ = SWIGV8_SWIGTYPE_Proxy_class_templ; - } -#else v8::Isolate *isolate = v8::Isolate::GetCurrent(); if(info->clientdata != 0) { @@ -442,13 +280,8 @@ SWIGRUNTIME SWIGV8_VALUE SWIG_V8_NewPointerObj(void *ptr, swig_type_info *info, } else { class_templ = v8::Local::New(isolate, SWIGV8_SWIGTYPE_Proxy_class_templ); } -#endif -#if (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x031903) - v8::Local result = class_templ->InstanceTemplate()->NewInstance(); -#else v8::Local result = class_templ->InstanceTemplate()->NewInstance(SWIGV8_CURRENT_CONTEXT()).ToLocalChecked(); -#endif SWIGV8_SetPrivateData(result, ptr, info, flags); @@ -543,14 +376,10 @@ int SwigV8Packed_Check(SWIGV8_VALUE valRef) { SWIGV8_OBJECT objRef = SWIGV8_TO_OBJECT(valRef); if(objRef->InternalFieldCount() < 1) return false; -#if (V8_MAJOR_VERSION-0) < 5 - v8::Handle flag = objRef->GetHiddenValue(SWIGV8_STRING_NEW("__swig__packed_data__")); -#else v8::Local privateKey = v8::Private::ForApi(v8::Isolate::GetCurrent(), SWIGV8_STRING_NEW("__swig__packed_data__")); v8::Local flag; if (!objRef->GetPrivate(SWIGV8_CURRENT_CONTEXT(), privateKey).ToLocal(&flag)) return false; -#endif return (flag->IsBoolean() && SWIGV8_BOOLEAN_VALUE(flag)); } @@ -563,12 +392,7 @@ swig_type_info *SwigV8Packed_UnpackData(SWIGV8_VALUE valRef, void *ptr, size_t s SWIGV8_OBJECT objRef = SWIGV8_TO_OBJECT(valRef); -#if (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x031511) - v8::Handle cdataRef = objRef->GetInternalField(0); - sobj = static_cast(v8::External::Unwrap(cdataRef)); -#else sobj = static_cast(objRef->GetAlignedPointerFromInternalField(0)); -#endif if (sobj == NULL || sobj->size != size) return 0; memcpy(ptr, sobj->data, size); return sobj->type; @@ -591,38 +415,9 @@ int SWIGV8_ConvertPacked(SWIGV8_VALUE valRef, void *ptr, size_t sz, swig_type_in return SWIG_OK; } -#if (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x031710) -SWIGRUNTIME void _wrap_SwigV8PackedData_delete(v8::Persistent< v8::Value > object, void *parameter) { - SwigV8PackedData *cdata = static_cast(parameter); -#elif (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x031900) -SWIGRUNTIME void _wrap_SwigV8PackedData_delete(v8::Isolate *isolate, v8::Persistent object, void *parameter) { - SwigV8PackedData *cdata = static_cast(parameter); -#elif (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < SWIGV8_SETWEAK_VERSION) -SWIGRUNTIME void _wrap_SwigV8PackedData_delete(v8::Isolate *isolate, v8::Persistent *object, SwigV8PackedData *cdata) { -#elif (V8_MAJOR_VERSION-0) < 5 -SWIGRUNTIME void _wrap_SwigV8PackedData_delete(const v8::WeakCallbackData &data) { - v8::Local object = data.GetValue(); - SwigV8PackedData *cdata = data.GetParameter(); -#else SWIGRUNTIME void _wrap_SwigV8PackedData_delete(const v8::WeakCallbackInfo &data) { SwigV8PackedData *cdata = data.GetParameter(); -#endif - delete cdata; - -#if (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x031710) - object.Clear(); - object.Dispose(); -#elif (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x031900) - object.Clear(); - object.Dispose(isolate); -#elif (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x032100) - object->Dispose(isolate); -#elif (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < SWIGV8_SETWEAK_VERSION) - object->Dispose(); -#elif (V8_MAJOR_VERSION-0) < 5 - object.Clear(); -#endif } SWIGRUNTIME @@ -633,46 +428,16 @@ SWIGV8_VALUE SWIGV8_NewPackedObj(void *data, size_t size, swig_type_info *type) // v8::Handle obj = SWIGV8_OBJECT_NEW(); v8::Local obj = SWIGV8_OBJECT_NEW(); -#if (V8_MAJOR_VERSION-0) < 5 - obj->SetHiddenValue(SWIGV8_STRING_NEW("__swig__packed_data__"), SWIGV8_BOOLEAN_NEW(true)); -#else v8::Local privateKey = v8::Private::ForApi(v8::Isolate::GetCurrent(), SWIGV8_STRING_NEW("__swig__packed_data__")); obj->SetPrivate(SWIGV8_CURRENT_CONTEXT(), privateKey, SWIGV8_BOOLEAN_NEW(true)); -#endif -#if (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x031511) - obj->SetPointerInInternalField(0, cdata); -#else obj->SetAlignedPointerInInternalField(0, cdata); -#endif -#if (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x031710) - cdata->handle = v8::Persistent::New(obj); -#elif (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x031900) - cdata->handle = v8::Persistent::New(v8::Isolate::GetCurrent(), obj); -#else cdata->handle.Reset(v8::Isolate::GetCurrent(), obj); -#endif - -#if (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x031710) - cdata->handle.MakeWeak(cdata, _wrap_SwigV8PackedData_delete); -#elif (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x031918) - cdata->handle.MakeWeak(v8::Isolate::GetCurrent(), cdata, _wrap_SwigV8PackedData_delete); -#elif (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < SWIGV8_SETWEAK_VERSION) - cdata->handle.MakeWeak(cdata, _wrap_SwigV8PackedData_delete); -#elif (V8_MAJOR_VERSION-0) < 5 - cdata->handle.SetWeak(cdata, _wrap_SwigV8PackedData_delete); -// v8::V8::SetWeak(&cdata->handle, cdata, _wrap_SwigV8PackedData_delete); -#else cdata->handle.SetWeak(cdata, _wrap_SwigV8PackedData_delete, v8::WeakCallbackType::kParameter); -#endif -#if (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x031710) - cdata->handle.MarkIndependent(); -#elif (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x032100) - cdata->handle.MarkIndependent(v8::Isolate::GetCurrent()); -#elif (SWIG_V8_VERSION < 0x0704) +#if (SWIG_V8_VERSION < 0x0704) cdata->handle.MarkIndependent(); // Looks like future versions do not require that anymore: // https://monorail-prod.appspot.com/p/chromium/issues/detail?id=923361#c11 diff --git a/Lib/javascript/v8/javascriptruntime.swg b/Lib/javascript/v8/javascriptruntime.swg index 59909389e..4e93fc4c1 100644 --- a/Lib/javascript/v8/javascriptruntime.swg +++ b/Lib/javascript/v8/javascriptruntime.swg @@ -7,36 +7,8 @@ // ---------------- // // v8 added version macros V8_MAJOR_VERSION, V8_MINOR_VERSION, V8_BUILD_NUMBER -// and V8_PATCH_LEVEL in version 4.3.0. SWIG generated code uses these if -// they are defined - to support earlier versions you can specify the V8 version -// in use via the command line when you run SWIG: -// -// swig -c++ -javascript -v8 -DV8_VERSION=0x032530 example.i -// -// Or code in the interface file using SWIG_V8_VERSION: -// -// %begin %{#define SWIG_V8_VERSION 0x031110%} -// -// This is specified as a hex constant, but the constant is read as pairs of -// decimal digits, so for V8 3.25.30 use constant 0x032530. This scheme can't -// represent components > 99, but this constant is only useful for V8 < 4.3.0, -// and no V8 versions from that era had a component > 99. - -%define %swig_v8_define_version(version) -%insert("runtime") %{ -#ifndef SWIG_V8_VERSION -#define SWIG_V8_VERSION version -#endif -%} -%enddef - -#ifdef V8_VERSION -%swig_v8_define_version(V8_VERSION) -#else -// HACK: defining a default version -%swig_v8_define_version(0x031110) -#endif - +// and V8_PATCH_LEVEL in version 4.3.0. SWIG doesn't support anything that +// old so SWIG generated code can rely on these. // Node support // ------------ @@ -56,13 +28,11 @@ %insert(runtime) %{ #include -#if defined(V8_MAJOR_VERSION) && defined(V8_MINOR_VERSION) #undef SWIG_V8_VERSION #define SWIG_V8_VERSION ((V8_MAJOR_VERSION / 10) * 4096 + \ (V8_MAJOR_VERSION % 10) * 256 + \ (V8_MINOR_VERSION / 10) * 16 + \ (V8_MINOR_VERSION % 10)) -#endif #include #include diff --git a/Lib/javascript/v8/javascriptstrings.swg b/Lib/javascript/v8/javascriptstrings.swg index aaf1b9302..8dc2d945e 100644 --- a/Lib/javascript/v8/javascriptstrings.swg +++ b/Lib/javascript/v8/javascriptstrings.swg @@ -7,11 +7,7 @@ SWIGINTERN int SWIG_AsCharPtrAndSize(SWIGV8_VALUE valRef, char** cptr, size_t* psize, int *alloc) { if(valRef->IsString()) { -%#if (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x031903) - v8::Handle js_str = v8::Handle::Cast(valRef); -%#else v8::Local js_str = v8::Local::Cast(valRef); -%#endif size_t len = SWIGV8_UTF8_LENGTH(js_str) + 1; char* cstr = (char*) %new_array(len, char); @@ -53,11 +49,7 @@ SWIG_FromCharPtrAndSize(const char* carray, size_t size) // TODO: handle extra long strings return SWIGV8_UNDEFINED(); } else { -%#if (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x031903) - v8::Handle js_str = SWIGV8_STRING_NEW2(carray, size); -%#else v8::Local js_str = SWIGV8_STRING_NEW2(carray, size); -%#endif return js_str; } } else { diff --git a/Tools/javascript/v8_shell.cxx b/Tools/javascript/v8_shell.cxx index 5001bc25a..b74dd7d2b 100644 --- a/Tools/javascript/v8_shell.cxx +++ b/Tools/javascript/v8_shell.cxx @@ -13,57 +13,24 @@ typedef int (*V8ExtensionInitializer) (v8::Handle module); // Note: these typedefs and defines are used to deal with v8 API changes since version 3.19.00 -#if (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x031903) -typedef v8::Handle SwigV8ReturnValue; -typedef v8::Arguments SwigV8Arguments; -typedef v8::AccessorInfo SwigV8PropertyCallbackInfo; -#define SWIGV8_RETURN(val) return scope.Close(val) -#define SWIGV8_RETURN_INFO(val, info) return scope.Close(val) -#else typedef void SwigV8ReturnValue; typedef v8::FunctionCallbackInfo SwigV8Arguments; typedef v8::PropertyCallbackInfo SwigV8PropertyCallbackInfo; #define SWIGV8_RETURN(val) args.GetReturnValue().Set(val); return #define SWIGV8_RETURN_INFO(val, info) info.GetReturnValue().Set(val); return -#endif - -#if (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x032117) -#define SWIGV8_HANDLESCOPE() v8::HandleScope scope -#define SWIGV8_HANDLESCOPE_ESC() v8::HandleScope scope -#define SWIGV8_ESCAPE(val) return scope.Close(val) -#elif (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x032318) -#define SWIGV8_HANDLESCOPE() v8::HandleScope scope(v8::Isolate::GetCurrent()); -#define SWIGV8_HANDLESCOPE_ESC() v8::HandleScope scope(v8::Isolate::GetCurrent()); -#define SWIGV8_ESCAPE(val) return scope.Close(val) -#else #define SWIGV8_HANDLESCOPE() v8::HandleScope scope(v8::Isolate::GetCurrent()); #define SWIGV8_HANDLESCOPE_ESC() v8::EscapableHandleScope scope(v8::Isolate::GetCurrent()); #define SWIGV8_ESCAPE(val) return scope.Escape(val) -#endif -#if (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x032318) -#define SWIGV8_CURRENT_CONTEXT() v8::Context::GetCurrent() -#define SWIGV8_STRING_NEW(str) v8::String::New(str) -#define SWIGV8_FUNCTEMPLATE_NEW(func) v8::FunctionTemplate::New(func) -#define SWIGV8_OBJECT_NEW() v8::Object::New() -#define SWIGV8_EXTERNAL_NEW(val) v8::External::New(val) -#define SWIGV8_UNDEFINED() v8::Undefined() -#else #define SWIGV8_CURRENT_CONTEXT() v8::Isolate::GetCurrent()->GetCurrentContext() #define SWIGV8_STRING_NEW(str) v8::String::NewFromUtf8(v8::Isolate::GetCurrent(), str) #define SWIGV8_FUNCTEMPLATE_NEW(func) v8::FunctionTemplate::New(v8::Isolate::GetCurrent(), func) #define SWIGV8_OBJECT_NEW() v8::Object::New(v8::Isolate::GetCurrent()) #define SWIGV8_EXTERNAL_NEW(val) v8::External::New(v8::Isolate::GetCurrent(), val) #define SWIGV8_UNDEFINED() v8::Undefined(v8::Isolate::GetCurrent()) -#endif - -#if (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x031900) -typedef v8::Persistent SwigV8Context; -#else typedef v8::Local SwigV8Context; -#endif class V8Shell: public JSShell { @@ -149,13 +116,7 @@ bool V8Shell::RunScript(const std::string &scriptPath) { context->Exit(); -#if (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x031710) - context.Dispose(); -#elif (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x031900) - context.Dispose(v8::Isolate::GetCurrent()); -#else // context.Dispose(); -#endif // v8::V8::Dispose(); @@ -193,13 +154,7 @@ bool V8Shell::RunShell() { context->Exit(); -#if (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x031710) - context.Dispose(); -#elif (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x031900) - context.Dispose(v8::Isolate::GetCurrent()); -#else // context.Dispose(); -#endif // v8::V8::Dispose(); @@ -249,13 +204,8 @@ SwigV8Context V8Shell::CreateShellContext() { global->Set(SWIGV8_STRING_NEW("require"), SWIGV8_FUNCTEMPLATE_NEW(V8Shell::Require)); global->Set(SWIGV8_STRING_NEW("version"), SWIGV8_FUNCTEMPLATE_NEW(V8Shell::Version)); -#if (V8_MAJOR_VERSION-0) < 4 && (SWIG_V8_VERSION < 0x031900) - SwigV8Context context = v8::Context::New(NULL, global); - return context; -#else SwigV8Context context = v8::Context::New(v8::Isolate::GetCurrent(), NULL, global); return context; -#endif } v8::Handle V8Shell::Import(const std::string &module_path) From bebb3d4c21658db58dddc30378a837e97713dd9f Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Thu, 2 Dec 2021 14:31:28 +1300 Subject: [PATCH 020/662] [ci] Remove CI build for unsupported v8 3.14 We only support v8 5.0 and later now. libv8-dev is no longer packaged in newer Ubuntu releases, so it seems there isn't an easy way to update this to test a supported v8 version, but really v8 via node is the configuration people will actually use anyway. --- .github/workflows/ci.yml | 3 --- 1 file changed, 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5374c5428..d23482a76 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -89,9 +89,6 @@ jobs: CPPSTD: c++14 - SWIGLANG: javascript ENGINE: jsc - - SWIGLANG: javascript - ENGINE: v8 - os: ubuntu-18.04 # libv8-dev only actually provides v8 in 18.04. - SWIGLANG: lua - SWIGLANG: lua VER: '5.3' From c25df7480751ef49db4eadffc6f45ef77b647572 Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Thu, 2 Dec 2021 18:00:39 +1300 Subject: [PATCH 021/662] [php7] Use destructor action if present If there's a destructor, use its action instead of free(ptr) (for C)/delete ptr (for C++). Fixes #2108 --- Examples/test-suite/php/newobject2_runme.php | 17 ++++++++++ Source/Modules/php.cxx | 35 +++++++++++++++----- 2 files changed, 43 insertions(+), 9 deletions(-) create mode 100644 Examples/test-suite/php/newobject2_runme.php diff --git a/Examples/test-suite/php/newobject2_runme.php b/Examples/test-suite/php/newobject2_runme.php new file mode 100644 index 000000000..f20a6a4f9 --- /dev/null +++ b/Examples/test-suite/php/newobject2_runme.php @@ -0,0 +1,17 @@ +std);\n"); - // expand %delete typemap instead of SWIG_remove? - Printf(s, " if (obj->newobject)\n"); - Printf(s, " SWIG_remove((%s *)obj->ptr);\n", Getattr(n, "classtype")); + Printf(s, " if (obj->newobject)"); + String * type = Getattr(n, "classtype"); + if (destructor_action) { + Printv(s, + " {\n", + type, " * arg1 = (", type, " *)obj->ptr;\n", + destructor_action, "\n", + " }\n", NIL); + } else if (CPlusPlus) { + Printf(s, "\n delete (%s *)obj->ptr;\n", type); + } else { + Printf(s, "\n free(obj->ptr);\n", type); + } Printf(s, "}\n\n"); } @@ -371,9 +383,6 @@ public: Printf(s_header, "}\n"); Printf(s_header, "#endif\n\n"); - Printf(s_header, "#ifdef __cplusplus\n#define SWIG_remove(PTR) delete PTR\n"); - Printf(s_header, "#else\n#define SWIG_remove(PTR) free(PTR)\n#endif\n\n"); - if (directorsEnabled()) { // Insert director runtime Swig_insert_file("director_common.swg", s_header); @@ -1132,10 +1141,12 @@ public: } } - if (Cmp(nodeType, "destructor") == 0) { + if (wrapperType == destructor) { // We don't explicitly wrap the destructor for PHP - Zend manages the // reference counting, and the user can just do `$obj = null;' or similar // to remove a reference to an object. + Setattr(n, "wrap:name", wname); + (void)emit_action(n); return SWIG_OK; } @@ -1535,6 +1546,7 @@ public: String *base_class = NULL; class_name = symname; + destructor_action = NULL; Printf(all_cs_entry, "static zend_function_entry class_%s_functions[] = {\n", class_name); @@ -1811,8 +1823,13 @@ public: /* ------------------------------------------------------------ * destructorHandler() * ------------------------------------------------------------ */ - //virtual int destructorHandler(Node *n) { - //} + virtual int destructorHandler(Node *n) { + wrapperType = destructor; + Language::destructorHandler(n); + destructor_action = Getattr(n, "wrap:action"); + wrapperType = standard; + return SWIG_OK; + } /* ------------------------------------------------------------ * memberconstantHandler() From e2384796f0e389fe6f3da9b247db9624cb06aeda Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Thu, 2 Dec 2021 08:56:00 +0000 Subject: [PATCH 022/662] Add Python embedded interpreters fix to changes file --- CHANGES.current | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGES.current b/CHANGES.current index 0abed204a..f87ba0afe 100644 --- a/CHANGES.current +++ b/CHANGES.current @@ -7,6 +7,9 @@ the issue number to the end of the URL: https://github.com/swig/swig/issues/ Version 4.1.0 (in progress) =========================== +2021-12-02: jsenn + [Python] #2102 Fixed crashes when using embedded Python interpreters. + 2021-11-12: wsfulton [Javascript] v8 and node only. Fix mismatched new char[] and free() when wrapping C code char arrays. Now calloc is now used instead of From a5f85beb2da59c91386b99b1b509220dca61670b Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Thu, 2 Dec 2021 11:38:41 +0000 Subject: [PATCH 023/662] HTML doc fixes --- Doc/Manual/Contents.html | 2 +- Doc/Manual/Php.html | 3 ++- Doc/Manual/Windows.html | 4 ++-- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/Doc/Manual/Contents.html b/Doc/Manual/Contents.html index 47b41186e..cf72febef 100644 --- a/Doc/Manual/Contents.html +++ b/Doc/Manual/Contents.html @@ -96,7 +96,7 @@
  • Building swig.exe on Windows diff --git a/Doc/Manual/Php.html b/Doc/Manual/Php.html index 5aea878b2..ed2587f1b 100644 --- a/Doc/Manual/Php.html +++ b/Doc/Manual/Php.html @@ -161,7 +161,7 @@ default extension directory, you also need to specify the path, for example:

    -	extension=/path/to/modulename.so
    +        extension=/path/to/modulename.so
     

    @@ -426,6 +426,7 @@ taking the integer argument.

    32.2.5 Pointers and References

    +

    Since SWIG 4.1.0, SWIG wraps C/C++ classes directly with PHP objects. Pointers to other types are also wrapped as PHP objects - mostly this is an diff --git a/Doc/Manual/Windows.html b/Doc/Manual/Windows.html index eae9ffb84..82d79435f 100644 --- a/Doc/Manual/Windows.html +++ b/Doc/Manual/Windows.html @@ -34,7 +34,7 @@

  • Building swig.exe on Windows @@ -298,7 +298,7 @@ swig.exe -help
    -python -c++ -o C:\Temp\doxygen_parsing.cpp C:\swig\Examples\test-suite\doxygen_parsing.i
  • -

    3.3.1.2 Building swig.exe using MSYS2

    +

    3.3.1.2 Building swig.exe using MSYS2

    From 5bdc20781bf458dcafb5b5469e0a1253f067d56f Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Thu, 2 Dec 2021 11:53:13 +0000 Subject: [PATCH 024/662] Remove bom in Windows.html --- Doc/Manual/Windows.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Doc/Manual/Windows.html b/Doc/Manual/Windows.html index 82d79435f..0e4ffc3e2 100644 --- a/Doc/Manual/Windows.html +++ b/Doc/Manual/Windows.html @@ -1,4 +1,4 @@ - + Getting started on Windows From 8432d3f89b09e6511370cfea1765fabf224e10d9 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Sat, 4 Dec 2021 09:35:51 +0000 Subject: [PATCH 025/662] GHA: Test currently supported php versions 7.0-8.1 --- .github/workflows/ci.yml | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d23482a76..b690b829a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -95,9 +95,19 @@ jobs: - SWIGLANG: octave CPPSTD: c++11 - SWIGLANG: perl5 + - SWIGLANG: php + VER: '7.0' + - SWIGLANG: php + VER: '7.1' + - SWIGLANG: php + VER: '7.2' + - SWIGLANG: php + VER: '7.3' - SWIGLANG: php VER: '7.4' - SWIGLANG: php + - SWIGLANG: php + VER: '8.1' - SWIGLANG: python - SWIGLANG: python PY3: 3 From ee3c9bd69755bfc81e411059b901bf2f265d5915 Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Fri, 3 Dec 2021 16:09:07 +1300 Subject: [PATCH 026/662] [php] Check fooCount() in newobject1_runme.php --- Examples/test-suite/php/newobject1_runme.php | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Examples/test-suite/php/newobject1_runme.php b/Examples/test-suite/php/newobject1_runme.php index a495ab15d..464f09b0b 100644 --- a/Examples/test-suite/php/newobject1_runme.php +++ b/Examples/test-suite/php/newobject1_runme.php @@ -9,9 +9,16 @@ check::classes(array('Foo')); // No new vars check::globals(array()); +check::equal(Foo::fooCount(), 0, "no Foo objects expected"); $foo = Foo::makeFoo(); check::equal(get_class($foo), "Foo", "static failed"); +check::equal(Foo::fooCount(), 1, "1 Foo object expected"); $bar = $foo->makeMore(); check::equal(get_class($bar), "Foo", "regular failed"); +check::equal(Foo::fooCount(), 2, "2 Foo objects expected"); +$foo = null; +check::equal(Foo::fooCount(), 1, "1 Foo object expected"); +$bar = null; +check::equal(Foo::fooCount(), 0, "no Foo objects expected"); check::done(); From 883b42dc708199db0f05f7fc0e72974b75eac001 Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Fri, 3 Dec 2021 16:15:39 +1300 Subject: [PATCH 027/662] [php] Ensure _runme.php calls check::done() This function doesn't do anything currently so these missing calls are a latent issue. It could be used for e.g. memory leak checking in the future though, and it's potentially a useful place to add code when debugging. --- .../test-suite/php/cpp11_strongly_typed_enumerations_runme.php | 2 ++ Examples/test-suite/php/exception_order_runme.php | 2 ++ Examples/test-suite/php/member_pointer_const_runme.php | 2 ++ Examples/test-suite/php/newobject3_runme.php | 2 ++ Examples/test-suite/php/overload_return_type_runme.php | 2 ++ Examples/test-suite/php/preproc_constants_c_runme.php | 2 ++ Examples/test-suite/php/preproc_constants_runme.php | 2 ++ Examples/test-suite/php/swig_exception_runme.php | 2 ++ Examples/test-suite/php/threads_exception_runme.php | 2 ++ Examples/test-suite/php/virtual_vs_nonvirtual_base_runme.php | 2 ++ 10 files changed, 20 insertions(+) diff --git a/Examples/test-suite/php/cpp11_strongly_typed_enumerations_runme.php b/Examples/test-suite/php/cpp11_strongly_typed_enumerations_runme.php index 82296deb7..ca327d502 100644 --- a/Examples/test-suite/php/cpp11_strongly_typed_enumerations_runme.php +++ b/Examples/test-suite/php/cpp11_strongly_typed_enumerations_runme.php @@ -164,3 +164,5 @@ enumCheck($class1->class1Test2(Class1::Enum12_Val5c), 1121); enumCheck(globalTest1(Enum1_Val5a), 13); enumCheck(globalTest2(Class1::Enum12_Val5c), 1121); #enumCheck(globalTest3(Class1::Struct1.Enum12_Val5f), 3121); + +check::done(); diff --git a/Examples/test-suite/php/exception_order_runme.php b/Examples/test-suite/php/exception_order_runme.php index 9a2c9118b..fb9870659 100644 --- a/Examples/test-suite/php/exception_order_runme.php +++ b/Examples/test-suite/php/exception_order_runme.php @@ -35,3 +35,5 @@ try { } catch (Exception $e) { check::equal($e->getMessage(), 'C++ E2 * exception thrown', ''); } + +check::done(); diff --git a/Examples/test-suite/php/member_pointer_const_runme.php b/Examples/test-suite/php/member_pointer_const_runme.php index 3f55549a8..bd8eaa87c 100644 --- a/Examples/test-suite/php/member_pointer_const_runme.php +++ b/Examples/test-suite/php/member_pointer_const_runme.php @@ -57,3 +57,5 @@ check::equal(3, member_pointer_const::call1(member_pointer_const::ADD_BY_VALUE, check::equal(7, member_pointer_const::call2(member_pointer_const::ADD_BY_VALUE, 3, 4), "Add by pointer"); check::equal(11, member_pointer_const::call3(member_pointer_const::ADD_BY_VALUE, 5, 6), "Add by reference"); */ + +check::done(); diff --git a/Examples/test-suite/php/newobject3_runme.php b/Examples/test-suite/php/newobject3_runme.php index 8efa9891d..29e16be61 100644 --- a/Examples/test-suite/php/newobject3_runme.php +++ b/Examples/test-suite/php/newobject3_runme.php @@ -13,3 +13,5 @@ check::isnull($factory->create(0), "create(0) should be NULL"); check::isnull($factory->create(7, -1), "create(7, -1) should be NULL"); check::isnull($factory->create(0, -1), "create(0, -1) should be NULL"); check::isnull($factory->create("bad", -1), "create(\"bad\", -1) should be NULL"); + +check::done(); diff --git a/Examples/test-suite/php/overload_return_type_runme.php b/Examples/test-suite/php/overload_return_type_runme.php index 5f01bbe19..f03a85d7f 100644 --- a/Examples/test-suite/php/overload_return_type_runme.php +++ b/Examples/test-suite/php/overload_return_type_runme.php @@ -8,3 +8,5 @@ check::classname("A", $b->foo("test")); check::equal(overload_return_type::foo(), 1, "overload_return_type::foo() should be 1"); check::equal(overload_return_type::bar(), 1, "overload_return_type::bar() should be 1"); + +check::done(); diff --git a/Examples/test-suite/php/preproc_constants_c_runme.php b/Examples/test-suite/php/preproc_constants_c_runme.php index a26892b42..411f7d766 100644 --- a/Examples/test-suite/php/preproc_constants_c_runme.php +++ b/Examples/test-suite/php/preproc_constants_c_runme.php @@ -64,3 +64,5 @@ check::equal(gettype(preproc_constants_c::EXPR_CONDITIONAL), "double", "preproc_ check::equal(gettype(preproc_constants_c::EXPR_MIXED1), "double", "preproc_constants.EXPR_MIXED1 has unexpected type"); check::equal(gettype(preproc_constants_c::EXPR_WCHAR_MAX), "integer", "preproc_constants.EXPR_WCHAR_MAX has unexpected type"); check::equal(gettype(preproc_constants_c::EXPR_WCHAR_MIN), "integer", "preproc_constants.EXPR_WCHAR_MIN has unexpected type"); + +check::done(); diff --git a/Examples/test-suite/php/preproc_constants_runme.php b/Examples/test-suite/php/preproc_constants_runme.php index 7f45a1bae..80f1a9a59 100644 --- a/Examples/test-suite/php/preproc_constants_runme.php +++ b/Examples/test-suite/php/preproc_constants_runme.php @@ -63,3 +63,5 @@ check::equal(gettype(preproc_constants::EXPR_CONDITIONAL), "double", "preproc_co check::equal(gettype(preproc_constants::EXPR_MIXED1), "double", "preproc_constants.EXPR_MIXED1 has unexpected type"); check::equal(gettype(preproc_constants::EXPR_WCHAR_MAX), "integer", "preproc_constants.EXPR_WCHAR_MAX has unexpected type"); check::equal(gettype(preproc_constants::EXPR_WCHAR_MIN), "integer", "preproc_constants.EXPR_WCHAR_MIN has unexpected type"); + +check::done(); diff --git a/Examples/test-suite/php/swig_exception_runme.php b/Examples/test-suite/php/swig_exception_runme.php index 37a7a59ee..c218890e4 100644 --- a/Examples/test-suite/php/swig_exception_runme.php +++ b/Examples/test-suite/php/swig_exception_runme.php @@ -28,3 +28,5 @@ $e = NULL; if (Shape::nshapes() != 0) { check::fail("Shape::nshapes() should be 0, actually ".Shape::nshapes()); } + +check::done(); diff --git a/Examples/test-suite/php/threads_exception_runme.php b/Examples/test-suite/php/threads_exception_runme.php index 38873dffd..21313aead 100644 --- a/Examples/test-suite/php/threads_exception_runme.php +++ b/Examples/test-suite/php/threads_exception_runme.php @@ -40,3 +40,5 @@ foreach (Array(1,2,3,4) as $i) { } catch (Exception $e) { } } + +check::done(); diff --git a/Examples/test-suite/php/virtual_vs_nonvirtual_base_runme.php b/Examples/test-suite/php/virtual_vs_nonvirtual_base_runme.php index abfb4d307..183825971 100644 --- a/Examples/test-suite/php/virtual_vs_nonvirtual_base_runme.php +++ b/Examples/test-suite/php/virtual_vs_nonvirtual_base_runme.php @@ -6,3 +6,5 @@ $fail = new SimpleClassFail(); $work = new SimpleClassWork(); check::equal($work->getInner()->get(), $fail->getInner()->get(), "should both be 10"); + +check::done(); From 852eab7db33c5cfe073a9c8af983b7482a854075 Mon Sep 17 00:00:00 2001 From: Robert Fries Date: Wed, 12 May 2021 19:44:17 -0400 Subject: [PATCH 028/662] Allow swig wrapped modules to compile with -Bsymbolic --- Lib/octave/octrun.swg | 8 ++++++++ Lib/octave/octruntime.swg | 2 ++ 2 files changed, 10 insertions(+) diff --git a/Lib/octave/octrun.swg b/Lib/octave/octrun.swg index 1069e0e54..a7291df14 100644 --- a/Lib/octave/octrun.swg +++ b/Lib/octave/octrun.swg @@ -1178,6 +1178,10 @@ SWIGRUNTIME void swig_acquire_ownership_obj(void *vptr, int own); #endif { return ptr->print(os, pr_as_read_syntax); } +#if SWIG_OCTAVE_PREREQ(4,4,0) + static void set_type_id(int type_id) { t_id=type_id; } +#endif + virtual type_conv_info numeric_conversion_function(void) const { return octave_base_value::type_conv_info (default_numeric_conversion_function, octave_scalar::static_type_id ()); @@ -1285,6 +1289,10 @@ SWIGRUNTIME void swig_acquire_ownership_obj(void *vptr, int own); # endif #endif +#if SWIG_OCTAVE_PREREQ(4,4,0) + static void set_type_id(int type_id) { t_id=type_id; } +#endif + private: #if !SWIG_OCTAVE_PREREQ(4,0,0) DECLARE_OCTAVE_ALLOCATOR; diff --git a/Lib/octave/octruntime.swg b/Lib/octave/octruntime.swg index a397fb7c1..ca69e44c4 100644 --- a/Lib/octave/octruntime.swg +++ b/Lib/octave/octruntime.swg @@ -295,9 +295,11 @@ DEFUN_DLD( SWIG_name, args, nargout, SWIG_name_usage ) { for (int i = 0; i < types.numel(); ++i) { if (types(i) == octave_swig_ref::static_type_name()) { register_octave_swig_ref = false; + octave_swig_ref::set_type_id(i); } if (types(i) == octave_swig_packed::static_type_name()) { register_octave_swig_packed = false; + octave_swig_packed::set_type_id(i); } } if (register_octave_swig_ref) { From 81f9e6600f2b4a53465aa07991834d8239e82fb7 Mon Sep 17 00:00:00 2001 From: Robert Fries Date: Wed, 12 May 2021 19:45:24 -0400 Subject: [PATCH 029/662] Octave module lets examples and tests work with Octave-6 * Try-catch replacement for check of error_state * Add execute method in addition to call * Replace oct_mach_info with octave::mach_info * Call from interpreter: global_varval global_assign * Assign a global name requires locating the stack which requires interpreter to tree evaluator to callStack * Do not use discard_error_messages or discard_warning_messages --- Lib/octave/octcontainer.swg | 11 +++++- Lib/octave/octrun.swg | 69 ++++++++++++++++++++++++++++++++++--- Lib/octave/octruntime.swg | 12 +++++-- 3 files changed, 83 insertions(+), 9 deletions(-) diff --git a/Lib/octave/octcontainer.swg b/Lib/octave/octcontainer.swg index 80d593f4f..394c90bac 100644 --- a/Lib/octave/octcontainer.swg +++ b/Lib/octave/octcontainer.swg @@ -569,8 +569,17 @@ namespace swig { } else { return octseq.check() ? SWIG_OK : SWIG_ERROR; } - } catch (std::exception& e) { + } +%#if SWIG_OCTAVE_PREREQ(6,0,0) + catch (octave::execution_exception& exec) { + } +%#endif + catch (std::exception& e) { +%#if SWIG_OCTAVE_PREREQ(6,0,0) + if (seq) // Know that octave is not in an error state +%#else if (seq&&!error_state) +%#endif error("swig type error: %s",e.what()); return SWIG_ERROR; } diff --git a/Lib/octave/octrun.swg b/Lib/octave/octrun.swg index a7291df14..5100825e7 100644 --- a/Lib/octave/octrun.swg +++ b/Lib/octave/octrun.swg @@ -171,7 +171,16 @@ SWIGRUNTIME void swig_acquire_ownership_obj(void *vptr, int own); octave_function* function_value(bool = false) { return this; } +#if SWIG_OCTAVE_PREREQ(6,0,0) octave_value_list call(octave::tree_evaluator& tw, int nargout = 0, const octave_value_list& args = octave_value_list()) { + return execute(tw,nargout,args); + } +#endif +#if SWIG_OCTAVE_PREREQ(6,0,0) + octave_value_list execute(octave::tree_evaluator& tw, int nargout = 0, const octave_value_list& args = octave_value_list()) { +#else + octave_value_list call(octave::tree_evaluator& tw, int nargout = 0, const octave_value_list& args = octave_value_list()) { +#endif octave_value_list all_args; all_args.append(first_args); all_args.append(args); @@ -456,10 +465,20 @@ SWIGRUNTIME void swig_acquire_ownership_obj(void *vptr, int own); // Fill in dim_vector for (int k=0;k a; + try { + a = out.int_vector_value(); + } + catch (octave::execution_exception& oee) { + return dim_vector(1,1); + } +#else Array a = out.int_vector_value(); if (error_state) return dim_vector(1,1); +#endif dim_vector d; d.resize(a.numel() < 2 ? 2 : a.numel()); d(0) = d(1) = 1; @@ -874,7 +903,11 @@ SWIGRUNTIME void swig_acquire_ownership_obj(void *vptr, int own); } virtual bool load_binary (std::istream& is, bool swap, - oct_mach_info::float_format fmt) { +#if SWIG_OCTAVE_PREREQ(6,0,0) + octave::mach_info::float_format fmt) { +#else + oct_mach_info::float_format fmt) { +#endif return true; } @@ -1142,7 +1175,11 @@ SWIGRUNTIME void swig_acquire_ownership_obj(void *vptr, int own); { return ptr->save_binary(os, save_as_floats); } virtual bool load_binary (std::istream& is, bool swap, - oct_mach_info::float_format fmt) +#if SWIG_OCTAVE_PREREQ(6,0,0) + octave::mach_info::float_format fmt) +#else + oct_mach_info::float_format fmt) +#endif { return ptr->load_binary(is, swap, fmt); } #if defined (HAVE_HDF5) @@ -1261,7 +1298,11 @@ SWIGRUNTIME void swig_acquire_ownership_obj(void *vptr, int own); } virtual bool load_binary (std::istream& is, bool swap, - oct_mach_info::float_format fmt) { +#if SWIG_OCTAVE_PREREQ(6,0,0) + octave::mach_info::float_format fmt) { +#else + oct_mach_info::float_format fmt) { +#endif return true; } @@ -1515,16 +1556,24 @@ SWIGRUNTIMEINLINE void SWIG_Octave_SetConstant(octave_swig_type *module_ns, cons } SWIGRUNTIMEINLINE octave_value SWIG_Octave_GetGlobalValue(std::string name) { +#if SWIG_OCTAVE_PREREQ(6,0,0) + octave::interpreter *interp = octave::interpreter::the_interpreter (); + return interp->global_varval(name); +#else #if SWIG_OCTAVE_PREREQ(4,4,0) octave::symbol_table& symtab = octave::interpreter::the_interpreter()->get_symbol_table(); return symtab.global_varval(name); #else return get_global_value(name, true); #endif +#endif } SWIGRUNTIME void SWIG_Octave_SetGlobalValue(std::string name, const octave_value& value) { -#if SWIG_OCTAVE_PREREQ(4,4,0) +#if SWIG_OCTAVE_PREREQ(6,0,0) + octave::interpreter *interp = octave::interpreter::the_interpreter (); + interp->global_assign(name, value); +#elif SWIG_OCTAVE_PREREQ(4,4,0) octave::symbol_table& symtab = octave::interpreter::the_interpreter()->get_symbol_table(); symtab.global_assign(name, value); #else @@ -1534,10 +1583,20 @@ SWIGRUNTIME void SWIG_Octave_SetGlobalValue(std::string name, const octave_value SWIGRUNTIME void SWIG_Octave_LinkGlobalValue(std::string name) { #if SWIG_OCTAVE_PREREQ(4,4,0) - octave::symbol_table& symtab = octave::interpreter::the_interpreter()->get_symbol_table(); octave::symbol_scope symscope = octave::interpreter::the_interpreter()->get_current_scope(); +#if SWIG_OCTAVE_PREREQ(6,0,0) + octave::interpreter *interp = octave::interpreter::the_interpreter (); + interp->assign(name, interp->global_varval(name)); + octave::tree_evaluator& tree_eval = interp->get_evaluator(); + octave::call_stack& callStack = tree_eval.get_call_stack(); + std::shared_ptr stackFrame = callStack.get_current_stack_frame(); + octave::symbol_record sym=symscope.lookup_symbol(name); + stackFrame->mark_global(sym); +#else + octave::symbol_table& symtab = octave::interpreter::the_interpreter()->get_symbol_table(); symscope.assign(name, symtab.global_varval(name)); symscope.mark_global(name); +#endif #else #if !SWIG_OCTAVE_PREREQ(3,2,0) link_to_global_variable(curr_sym_tab->lookup(name, true)); diff --git a/Lib/octave/octruntime.swg b/Lib/octave/octruntime.swg index ca69e44c4..e76151f14 100644 --- a/Lib/octave/octruntime.swg +++ b/Lib/octave/octruntime.swg @@ -19,7 +19,8 @@ static bool SWIG_init_user(octave_swig_type* module_ns); SWIGINTERN bool SWIG_Octave_LoadModule(std::string name) { bool retn = false; { -#if SWIG_OCTAVE_PREREQ(4,2,0) +#if SWIG_OCTAVE_PREREQ(6,0,0) +#elif SWIG_OCTAVE_PREREQ(4,2,0) octave::unwind_protect frame; frame.protect_var(discard_error_messages); discard_error_messages = true; frame.protect_var(discard_warning_messages); discard_warning_messages = true; @@ -62,7 +63,8 @@ SWIGINTERN bool SWIG_Octave_LoadModule(std::string name) { SWIGINTERN bool SWIG_Octave_InstallFunction(octave_function *octloadfcn, std::string name) { bool retn = false; { -#if SWIG_OCTAVE_PREREQ(4,2,0) +#if SWIG_OCTAVE_PREREQ(6,0,0) +#elif SWIG_OCTAVE_PREREQ(4,2,0) octave::unwind_protect frame; frame.protect_var(discard_error_messages); discard_error_messages = true; frame.protect_var(discard_warning_messages); discard_warning_messages = true; @@ -316,7 +318,11 @@ DEFUN_DLD( SWIG_name, args, nargout, SWIG_name_usage ) { SWIG_InitializeModule(0); SWIG_PropagateClientData(); -#if SWIG_OCTAVE_PREREQ(4,4,0) +#if SWIG_OCTAVE_PREREQ(6,0,0) + octave::tree_evaluator& tree_eval = octave::interpreter::the_interpreter()->get_evaluator(); + octave::call_stack& stack = tree_eval.get_call_stack(); + octave_function *me = stack.current_function(); +#elif SWIG_OCTAVE_PREREQ(4,4,0) octave::call_stack& stack = octave::interpreter::the_interpreter()->get_call_stack(); octave_function *me = stack.current(); #else From 983b91694fc9891e9c01f968cbbcdde96339434d Mon Sep 17 00:00:00 2001 From: Robert Fries Date: Wed, 12 May 2021 20:22:30 -0400 Subject: [PATCH 030/662] Additional changes due to name changes in octave-6 * is_map to isstruct, is_object to isobject --- Lib/octave/octrun.swg | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/Lib/octave/octrun.swg b/Lib/octave/octrun.swg index 5100825e7..fda4596d6 100644 --- a/Lib/octave/octrun.swg +++ b/Lib/octave/octrun.swg @@ -660,7 +660,11 @@ SWIGRUNTIME void swig_acquire_ownership_obj(void *vptr, int own); return true; } +#if SWIG_OCTAVE_PREREQ(6,0,0) + virtual bool isstruct() const { +#else virtual bool is_map() const { +#endif return true; } @@ -808,7 +812,11 @@ SWIGRUNTIME void swig_acquire_ownership_obj(void *vptr, int own); return as_value(); } +#if SWIG_OCTAVE_PREREQ(6,0,0) + virtual bool isobject() const { +#else virtual bool is_object() const { +#endif return true; } @@ -1117,8 +1125,13 @@ SWIGRUNTIME void swig_acquire_ownership_obj(void *vptr, int own); bool is_defined() const { return ptr->is_defined(); } +#if SWIG_OCTAVE_PREREQ(6,0,0) + virtual bool isstruct() const + { return ptr->isstruct(); } +#else virtual bool is_map() const { return ptr->is_map(); } +#endif virtual octave_value subsref(const std::string &ops, const std::list < octave_value_list > &idx) { return ptr->subsref(ops, idx); } @@ -1129,8 +1142,13 @@ SWIGRUNTIME void swig_acquire_ownership_obj(void *vptr, int own); octave_value subsasgn(const std::string &ops, const std::list < octave_value_list > &idx, const octave_value &rhs) { return ptr->subsasgn(ops, idx, rhs); } +#if SWIG_OCTAVE_PREREQ(6,0,0) + virtual bool isobject() const + { return ptr->isobject(); } +#else virtual bool is_object() const { return ptr->is_object(); } +#endif virtual bool is_string() const { return ptr->is_string(); } From 3947df87a20bf7d7df91b1d5b96d748692fbf34e Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Sun, 5 Dec 2021 22:24:51 +0000 Subject: [PATCH 031/662] GHA: Test Octave 6.4 --- .github/workflows/ci.yml | 5 +++-- Tools/CI-linux-install.sh | 10 ++++++++-- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b690b829a..d328befb0 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -94,6 +94,9 @@ jobs: VER: '5.3' - SWIGLANG: octave CPPSTD: c++11 + - SWIGLANG: octave + VER: '6.4' + CPPSTD: c++11 - SWIGLANG: perl5 - SWIGLANG: php VER: '7.0' @@ -196,8 +199,6 @@ jobs: CPPSTD: c++11 - SWIGLANG: lua CPPSTD: c++11 - # - SWIGLANG: octave - # CPPSTD: c++11 - SWIGLANG: perl5 CPPSTD: c++11 - SWIGLANG: php diff --git a/Tools/CI-linux-install.sh b/Tools/CI-linux-install.sh index 7bd141080..1c6686d86 100644 --- a/Tools/CI-linux-install.sh +++ b/Tools/CI-linux-install.sh @@ -79,8 +79,14 @@ case "$SWIGLANG" in $RETRY sudo apt-get -qq install ocaml camlp4 ;; "octave") - $RETRY sudo apt-get -qq update - $RETRY sudo apt-get -qq install liboctave-dev + if [[ "$VER" ]]; then + $RETRY sudo add-apt-repository -y ppa:devacom/science + $RETRY sudo apt-get -qq update + $RETRY sudo apt-get -qq install "liboctave-dev=$VER.*" + else + $RETRY sudo apt-get -qq update + $RETRY sudo apt-get -qq install liboctave-dev + fi ;; "php") if [[ "$VER" ]]; then From 5ada46bcce5bd01632c8bd2566980a943a412cfc Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Sun, 5 Dec 2021 22:26:25 +0000 Subject: [PATCH 032/662] Whitespace consistency fix in CI-linux-install.sh --- Tools/CI-linux-install.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Tools/CI-linux-install.sh b/Tools/CI-linux-install.sh index 1c6686d86..99614550c 100644 --- a/Tools/CI-linux-install.sh +++ b/Tools/CI-linux-install.sh @@ -103,9 +103,9 @@ case "$SWIGLANG" in $RETRY sudo apt-get -qq update $RETRY sudo apt-get -qq install python${VER}-dev WITHLANG=$SWIGLANG$PY3=$SWIGLANG$VER - else - $RETRY sudo apt-get install -qq python${PY3}-dev - WITHLANG=$SWIGLANG$PY3 + else + $RETRY sudo apt-get install -qq python${PY3}-dev + WITHLANG=$SWIGLANG$PY3 fi ;; "r") From e0935404a8bb7dae1c984149448ce655a030123e Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Sun, 5 Dec 2021 22:31:05 +0000 Subject: [PATCH 033/662] Add Octave 6 to changes file --- CHANGES.current | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGES.current b/CHANGES.current index f87ba0afe..cadbbadfb 100644 --- a/CHANGES.current +++ b/CHANGES.current @@ -7,6 +7,11 @@ the issue number to the end of the URL: https://github.com/swig/swig/issues/ Version 4.1.0 (in progress) =========================== +2021-12-05: rwf1 + [Octave] #2020 #1893 Add support for Octave 6 up to and including 6.4. + Also add support for compiling with -Bsymbolic which is used by default + by mkoctfile. + 2021-12-02: jsenn [Python] #2102 Fixed crashes when using embedded Python interpreters. From e902ab516087ef512ea9b3e06564cb246edcc50d Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Mon, 6 Dec 2021 23:11:07 +0100 Subject: [PATCH 034/662] Add Python 3.11 support: use Py_SET_TYPE() On Python 3.9 and newer, SwigPyBuiltin_SetMetaType() now calls Py_SET_TYPE(). Py_TYPE() can no longer be usd as an l-value on Python 3.11: * https://docs.python.org/dev/c-api/structures.html#c.Py_SET_TYPE * https://docs.python.org/dev/whatsnew/3.11.html#c-api-changes --- Lib/python/builtin.swg | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Lib/python/builtin.swg b/Lib/python/builtin.swg index 4f31a8d54..ec092233d 100644 --- a/Lib/python/builtin.swg +++ b/Lib/python/builtin.swg @@ -414,7 +414,11 @@ SwigPyBuiltin_ThisClosure (PyObject *self, void *SWIGUNUSEDPARM(closure)) { SWIGINTERN void SwigPyBuiltin_SetMetaType (PyTypeObject *type, PyTypeObject *metatype) { +#if PY_VERSION_HEX >= 0x030900A4 + Py_SET_TYPE(type, metatype); +#else Py_TYPE(type) = metatype; +#endif } From c0c7a8dba06c2dc0fddb6d1e9e56f3eab0fb8271 Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Wed, 8 Dec 2021 13:06:16 +1300 Subject: [PATCH 035/662] [php] Fix two incorrect PHP 8 conditionals The correct macro to test is PHP_MAJOR_VERSION so these two PHP 8 cases weren't ever used, which hid that the PHP8 version of the code was broken in one of them. Highlighted in #2113. --- Lib/exception.i | 8 ++++---- Lib/php/phpinterfaces.i | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Lib/exception.i b/Lib/exception.i index 7508b409b..5cdea58e8 100644 --- a/Lib/exception.i +++ b/Lib/exception.i @@ -14,14 +14,14 @@ #ifdef SWIGPHP %{ -#if PHP_MAJOR >= 8 -# define SWIG_HANDLE_VALUE_ERROR_FOR_PHP8 code == SWIG_ValueError ? zend_ce_value_error : +#if PHP_MAJOR_VERSION >= 8 +# define SWIG_HANDLE_VALUE_ERROR_FOR_PHP8(code) code == SWIG_ValueError ? zend_ce_value_error : #else -# define SWIG_HANDLE_VALUE_ERROR_FOR_PHP8 +# define SWIG_HANDLE_VALUE_ERROR_FOR_PHP8(code) #endif #define SWIG_exception(code, msg) do { zend_throw_exception( \ code == SWIG_TypeError ? zend_ce_type_error : \ - SWIG_HANDLE_VALUE_ERROR_FOR_PHP8 \ + SWIG_HANDLE_VALUE_ERROR_FOR_PHP8(code) \ code == SWIG_DivisionByZero ? zend_ce_division_by_zero_error : \ code == SWIG_SyntaxError ? zend_ce_parse_error : \ code == SWIG_OverflowError ? zend_ce_arithmetic_error : \ diff --git a/Lib/php/phpinterfaces.i b/Lib/php/phpinterfaces.i index dda219d91..5b1da8b79 100644 --- a/Lib/php/phpinterfaces.i +++ b/Lib/php/phpinterfaces.i @@ -54,7 +54,7 @@ #define SWIG_PHP_INTERFACE_JsonSerializable_HEADER "ext/json/php_json.h" // New in PHP 8.0. -#if PHP_MAJOR >= 8 +#if PHP_MAJOR_VERSION >= 8 # define SWIG_PHP_INTERFACE_Stringable_CE zend_ce_stringable # define SWIG_PHP_INTERFACE_Stringable_HEADER "zend_interfaces.h" #endif From c60507ef70212d7d3215d754f7fdfcb00d590454 Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Wed, 8 Dec 2021 13:09:43 +1300 Subject: [PATCH 036/662] [php] configure: Check for php8.1 binary --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 9bf45c765..e5730cbf0 100644 --- a/configure.ac +++ b/configure.ac @@ -2082,7 +2082,7 @@ if test x"${PHPBIN}" = xno; then PHP= else if test "x$PHPBIN" = xyes; then - AC_CHECK_PROGS(PHP, [php8.0 php7.4 php7.3 php7.2 php7.1 php7.0 php]) + AC_CHECK_PROGS(PHP, [php8.1 php8.0 php7.4 php7.3 php7.2 php7.1 php7.0 php]) else PHP=$PHPBIN fi From fd013c344ac063b9feffc3023bbeee8d7159c841 Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Fri, 10 Dec 2021 17:10:35 +1300 Subject: [PATCH 037/662] [php] Remove unused variable SWIG_module_entry hasn't actually been used for any of git history which is over 19 years. --- Source/Modules/php.cxx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Source/Modules/php.cxx b/Source/Modules/php.cxx index e39ad4dbe..f7decbf3c 100644 --- a/Source/Modules/php.cxx +++ b/Source/Modules/php.cxx @@ -471,8 +471,7 @@ public: Printf(s_init, " NO_VERSION_YET,\n"); } Printf(s_init, " STANDARD_MODULE_PROPERTIES\n"); - Printf(s_init, "};\n"); - Printf(s_init, "zend_module_entry* SWIG_module_entry = &%s_module_entry;\n\n", module); + Printf(s_init, "};\n\n"); Printf(s_init, "#ifdef __cplusplus\n"); Printf(s_init, "extern \"C\" {\n"); From 4467c94fe9e4433a376bdaddaa54ad8b4edb5891 Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Fri, 10 Dec 2021 18:34:21 +1300 Subject: [PATCH 038/662] Fix removeNode() to really unset previousSibling There was a typo in attribute name so we attempted to remove the non-existent attribute prevSibling instead. --- Source/Swig/tree.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Swig/tree.c b/Source/Swig/tree.c index 46571fc09..e2162b7f1 100644 --- a/Source/Swig/tree.c +++ b/Source/Swig/tree.c @@ -225,7 +225,7 @@ void removeNode(Node *n) { /* Delete attributes */ Delattr(n,"parentNode"); Delattr(n,"nextSibling"); - Delattr(n,"prevSibling"); + Delattr(n,"previousSibling"); } /* ----------------------------------------------------------------------------- From bf68b377e609b81b4bbb81c70769568a46f18484 Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Mon, 13 Dec 2021 08:53:23 +1300 Subject: [PATCH 039/662] Remove unused code from PHP backend These are leftovers from the work on wrapping using only PHP's C API. --- Source/Modules/php.cxx | 47 ------------------------------------------ 1 file changed, 47 deletions(-) diff --git a/Source/Modules/php.cxx b/Source/Modules/php.cxx index f7decbf3c..f48ab34b9 100644 --- a/Source/Modules/php.cxx +++ b/Source/Modules/php.cxx @@ -494,7 +494,6 @@ public: * things are being called in the wrong order */ - // Printv(s_init,s_resourcetypes,NIL); Printf(s_oinit, " /* end oinit subsection */\n"); Printf(s_init, "%s\n", s_oinit); @@ -831,31 +830,6 @@ public: * functionWrapper() * ------------------------------------------------------------ */ - /* Helper method for PHP::functionWrapper */ - bool is_class(SwigType *t) { - Node *n = classLookup(t); - if (n) { - String *r = Getattr(n, "php:proxy"); // Set by classDeclaration() - if (!r) - r = Getattr(n, "sym:name"); // Not seen by classDeclaration yet, but this is the name - if (r) - return true; - } - return false; - } - - /* Helper method for PHP::functionWrapper to get class name for parameter*/ - String *get_class_name(SwigType *t) { - Node *n = classLookup(t); - String *r = NULL; - if (n) { - r = Getattr(n, "php:proxy"); // Set by classDeclaration() - if (!r) - r = Getattr(n, "sym:name"); // Not seen by classDeclaration yet, but this is the name - } - return r; - } - /* Helper function to check if class is wrapped */ bool is_class_wrapped(String *className) { if (!className) @@ -864,18 +838,6 @@ public: return n && Getattr(n, "classtype") != NULL; } - /* Is special return type */ - bool is_param_type_pointer(SwigType *t) { - - if (SwigType_ispointer(t) || - SwigType_ismemberpointer(t) || - SwigType_isreference(t) || - SwigType_isarray(t)) - return true; - - return false; - } - void generate_magic_property_methods(Node *class_node, String *base_class) { if (Equal(base_class, "Exception") || !is_class_wrapped(base_class)) { base_class = NULL; @@ -1254,7 +1216,6 @@ public: String *source; /* Skip ignored arguments */ - //while (Getattr(p,"tmap:ignore")) { p = Getattr(p,"tmap:ignore:next");} while (checkAttribute(p, "tmap:in:numinputs", "0")) { p = Getattr(p, "tmap:in:next"); } @@ -1268,14 +1229,6 @@ public: Printf(f->code, "\tif(arg_count > %d) {\n", i); } - String *paramType_class = NULL; - bool paramType_valid = is_class(pt); - - if (paramType_valid) { - paramType_class = get_class_name(pt); - Chop(paramType_class); - } - if ((tm = Getattr(p, "tmap:in"))) { Replaceall(tm, "$input", source); Setattr(p, "emit:input", source); From 7d704023068f527de19275de713b5010e191ba11 Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Mon, 13 Dec 2021 09:07:50 +1300 Subject: [PATCH 040/662] Update PHP source comment We no longer wrap anything as a PHP resource. --- Source/Modules/php.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Modules/php.cxx b/Source/Modules/php.cxx index f48ab34b9..2d346d273 100644 --- a/Source/Modules/php.cxx +++ b/Source/Modules/php.cxx @@ -2171,7 +2171,7 @@ public: static PHP *maininstance = 0; // Collect non-class pointer types from the type table so we can set up PHP -// resource types for them later. +// classes for them later. // // NOTE: it's a function NOT A PHP::METHOD extern "C" { From 48bb7e0e95bd597efe2e9e9a09a39db97498533d Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Mon, 13 Dec 2021 09:14:13 +1300 Subject: [PATCH 041/662] Simplify PHP backend code --- Source/Modules/php.cxx | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/Source/Modules/php.cxx b/Source/Modules/php.cxx index 2d346d273..e5c61c2a2 100644 --- a/Source/Modules/php.cxx +++ b/Source/Modules/php.cxx @@ -99,8 +99,6 @@ static Hash *zend_types = 0; static int shadow = 1; -static String *wrapping_member_constant = NULL; - // These static variables are used to pass some state from Handlers into functionWrapper static enum { standard = 0, @@ -1397,6 +1395,7 @@ public: SwigType_remember(type); + String *wrapping_member_constant = Getattr(n, "memberconstantHandler:sym:name"); if (!wrapping_member_constant) { { tm = Swig_typemap_lookup("consttab", n, name, 0); @@ -1783,17 +1782,6 @@ public: return SWIG_OK; } - /* ------------------------------------------------------------ - * memberconstantHandler() - * ------------------------------------------------------------ */ - - virtual int memberconstantHandler(Node *n) { - wrapping_member_constant = Getattr(n, "sym:name"); - Language::memberconstantHandler(n); - wrapping_member_constant = NULL; - return SWIG_OK; - } - int classDirectorInit(Node *n) { String *declaration = Swig_director_declaration(n); Printf(f_directors_h, "%s\n", declaration); From b78f0ee263220c49c4b08295f5d40b0cce624043 Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Mon, 13 Dec 2021 09:30:42 +1300 Subject: [PATCH 042/662] [php] Add runme for long_long testcase --- Examples/test-suite/php/long_long_runme.php | 61 +++++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100644 Examples/test-suite/php/long_long_runme.php diff --git a/Examples/test-suite/php/long_long_runme.php b/Examples/test-suite/php/long_long_runme.php new file mode 100644 index 000000000..ac6c2dfb1 --- /dev/null +++ b/Examples/test-suite/php/long_long_runme.php @@ -0,0 +1,61 @@ + Date: Mon, 13 Dec 2021 09:31:11 +1300 Subject: [PATCH 043/662] [php] Remove redundant in typemap for bool This typemap which would wrap C++ bool as PHP int is later overridden by another which wraps it as PHP bool. The current result is what we want so just remove the redundant one. --- Lib/php/php.swg | 1 - 1 file changed, 1 deletion(-) diff --git a/Lib/php/php.swg b/Lib/php/php.swg index 6e4ee2d2f..b8722ace8 100644 --- a/Lib/php/php.swg +++ b/Lib/php/php.swg @@ -219,7 +219,6 @@ unsigned long, signed char, unsigned char, - bool, size_t %{ RETVAL_LONG($1); From 4c7febfb80b2c51cae24d9894402000aea909d00 Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Mon, 13 Dec 2021 09:33:26 +1300 Subject: [PATCH 044/662] Make DOH Char macro more robust For example, `Char(foo)[0]` now works to get the first character of DOH String `foo`. Previously this gave a confusing error because it expanded to `(char *) Data(foo)[0]` and the `[0]` binds more tightly than the `(char *)`. --- Source/DOH/doh.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/DOH/doh.h b/Source/DOH/doh.h index fd0530e9c..a948bc849 100644 --- a/Source/DOH/doh.h +++ b/Source/DOH/doh.h @@ -364,7 +364,7 @@ extern void DohMemoryDebug(void); #define Push(s,x) DohInsertitem(s,DOH_BEGIN,x) #define Len DohLen #define Data DohData -#define Char (char *) Data +#define Char(X) ((char *) Data(X)) #define Cmp DohCmp #define Equal DohEqual #define Setline DohSetline From 98b8578731832572427ed8fc1d63df50b9570680 Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Mon, 13 Dec 2021 15:55:22 +1300 Subject: [PATCH 045/662] [php] Tidy up code which processes in typemaps The only functional change is that we now recover after WARN_TYPEMAP_IN_UNDEF better (or at least like most of the other SWIG backends do). --- Source/Modules/php.cxx | 44 ++++++++++++++++++++---------------------- 1 file changed, 21 insertions(+), 23 deletions(-) diff --git a/Source/Modules/php.cxx b/Source/Modules/php.cxx index e5c61c2a2..12be53f48 100644 --- a/Source/Modules/php.cxx +++ b/Source/Modules/php.cxx @@ -1211,43 +1211,41 @@ public: // This may mean looking at Language::memberfunctionHandler for (i = 0, p = l; i < num_arguments; i++) { - String *source; - /* Skip ignored arguments */ while (checkAttribute(p, "tmap:in:numinputs", "0")) { p = Getattr(p, "tmap:in:next"); } - SwigType *pt = Getattr(p, "type"); - - source = NewStringf("args[%d]", i); - /* Check if optional */ if (i >= num_required) { Printf(f->code, "\tif(arg_count > %d) {\n", i); } - if ((tm = Getattr(p, "tmap:in"))) { - Replaceall(tm, "$input", source); - Setattr(p, "emit:input", source); - Printf(f->code, "%s\n", tm); - if (i == 0 && Getattr(p, "self")) { - Printf(f->code, "\tif(!arg1) {\n"); - Printf(f->code, "\t zend_throw_exception(zend_ce_type_error, \"this pointer is NULL\", 0);\n"); - Printf(f->code, "\t return;\n"); - Printf(f->code, "\t}\n"); - } - p = Getattr(p, "tmap:in:next"); - if (i >= num_required) { - Printf(f->code, "}\n"); - } - continue; - } else { + tm = Getattr(p, "tmap:in"); + if (!tm) { + SwigType *pt = Getattr(p, "type"); Swig_warning(WARN_TYPEMAP_IN_UNDEF, input_file, line_number, "Unable to use type %s as a function argument.\n", SwigType_str(pt, 0)); + p = nextSibling(p); + continue; } - if (i >= num_required) { + + String *source = NewStringf("args[%d]", i); + Replaceall(tm, "$input", source); + Setattr(p, "emit:input", source); + Printf(f->code, "%s\n", tm); + if (i == 0 && Getattr(p, "self")) { + Printf(f->code, "\tif(!arg1) {\n"); + Printf(f->code, "\t zend_throw_exception(zend_ce_type_error, \"this pointer is NULL\", 0);\n"); + Printf(f->code, "\t return;\n"); Printf(f->code, "\t}\n"); } + + if (i >= num_required) { + Printf(f->code, "}\n"); + } + + p = Getattr(p, "tmap:in:next"); + Delete(source); } From fa2f9dc5da405586ba3857dd515ae84b7868819f Mon Sep 17 00:00:00 2001 From: tytan652 Date: Tue, 14 Dec 2021 11:42:50 +0100 Subject: [PATCH 046/662] [lua] Fix maybe-uninitialized warning in generated code --- Lib/lua/luarun.swg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib/lua/luarun.swg b/Lib/lua/luarun.swg index 6ef2c6f15..1de9cc829 100644 --- a/Lib/lua/luarun.swg +++ b/Lib/lua/luarun.swg @@ -1796,7 +1796,7 @@ SWIGRUNTIME int SWIG_Lua_ConvertPtr(lua_State *L,int index,void **ptr,swig_type SWIGRUNTIME void* SWIG_Lua_MustGetPtr(lua_State *L,int index,swig_type_info *type,int flags, int argnum,const char *func_name){ - void *result; + void *result = 0; if (!SWIG_IsOK(SWIG_ConvertPtr(L,index,&result,type,flags))){ luaL_error (L,"Error in %s, expected a %s at argument number %d\n", func_name,(type && type->str)?type->str:"void*",argnum); From 7418da9e5d63451cfd3941f7e4ed91c19ba1f73d Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Mon, 13 Dec 2021 18:46:20 +1300 Subject: [PATCH 047/662] Fix transposed outputs in internals doc --- Doc/Devel/internals.html | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/Doc/Devel/internals.html b/Doc/Devel/internals.html index c9082d3f6..0fc6623e8 100644 --- a/Doc/Devel/internals.html +++ b/Doc/Devel/internals.html @@ -441,12 +441,12 @@ Resulting output:

    -hash len: 5
    -get: hashval2
    -hash item: hashval5 [h5]
    -hash item: hashval1 [h1]
    -hash item: hashval2 [h2]
    -hash item: hashval3 [h3]
    +list len: 5
    +get: listval2
    +list item: newlistval1
    +list item: listval2
    +list item: listval3
    +list item: listval5
     
    @@ -494,12 +494,12 @@ Resulting output:
    -list len: 5
    -get: listval2
    -list item: newlistval1
    -list item: listval2
    -list item: listval3
    -list item: listval5
    +hash len: 5
    +get: hashval2
    +hash item: hashval5 [h5]
    +hash item: hashval1 [h1]
    +hash item: hashval2 [h2]
    +hash item: hashval3 [h3]
     
    From 6ef820acf919885701d8e623e074ea00d13be979 Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Wed, 15 Dec 2021 19:30:17 +1300 Subject: [PATCH 048/662] [php] Simplify creating overload dispatch name --- Source/Modules/php.cxx | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/Source/Modules/php.cxx b/Source/Modules/php.cxx index 12be53f48..cf5876aca 100644 --- a/Source/Modules/php.cxx +++ b/Source/Modules/php.cxx @@ -1029,7 +1029,6 @@ public: String *wname = NewStringEmpty(); String *overloadwname = NULL; int overloaded = 0; - String *overname = 0; String *modes = NULL; bool static_setter = false; bool static_getter = false; @@ -1047,18 +1046,13 @@ public: if (Getattr(n, "sym:overloaded")) { overloaded = 1; - overname = Getattr(n, "sym:overname"); + overloadwname = NewString(Swig_name_wrapper(iname)); + Printf(overloadwname, "%s", Getattr(n, "sym:overname")); } else { if (!addSymbol(iname, n)) return SWIG_ERROR; } - if (overname) { - // Test for overloading - overloadwname = NewString(Swig_name_wrapper(iname)); - Printf(overloadwname, "%s", overname); - } - if (constructor) { wname = NewString("__construct"); } else if (wrapperType == membervar) { From 9ffa15b3075dc2cf79e9425de0c8653680317e69 Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Wed, 15 Dec 2021 19:40:06 +1300 Subject: [PATCH 049/662] Tweak source whitespace to match SWIG conventions --- Lib/php/typemaps.i | 1 + Source/Modules/php.cxx | 136 ++++++++++++++++++++--------------------- 2 files changed, 68 insertions(+), 69 deletions(-) diff --git a/Lib/php/typemaps.i b/Lib/php/typemaps.i index 94b351113..3cfa3f0f7 100644 --- a/Lib/php/typemaps.i +++ b/Lib/php/typemaps.i @@ -153,6 +153,7 @@ INT_TYPEMAP(long long); ZVAL_STRING($result, temp); } %} + INT_TYPEMAP(unsigned long long); %typemap(argout,fragment="t_output_helper") unsigned long long *OUTPUT { diff --git a/Source/Modules/php.cxx b/Source/Modules/php.cxx index cf5876aca..732f1ce61 100644 --- a/Source/Modules/php.cxx +++ b/Source/Modules/php.cxx @@ -1,5 +1,5 @@ /* ----------------------------------------------------------------------------- - * This file is part of SWIG, which is licensed as a whole under version 3 + * This file is part of SWIG, which is licensed as a whole under version 3 * (or any later version) of the GNU General Public License. Some additional * terms also apply to certain portions of SWIG. The full details of the SWIG * license and copyrights can be found in the LICENSE and COPYRIGHT files @@ -139,7 +139,7 @@ static void print_creation_free_wrapper(Node *n) { Printf(s, " zend_object_std_dtor(&obj->std);\n"); Printf(s, " if (obj->newobject)"); - String * type = Getattr(n, "classtype"); + String *type = Getattr(n, "classtype"); if (destructor_action) { Printv(s, " {\n", @@ -155,7 +155,7 @@ static void print_creation_free_wrapper(Node *n) { } Printf(s, "/* Object Creation Method for class %s */\n",class_name); - Printf(s, "zend_object * %s_object_new(zend_class_entry *ce) {\n",class_name); + Printf(s, "zend_object *%s_object_new(zend_class_entry *ce) {\n",class_name); Printf(s, " swig_object_wrapper *obj = (swig_object_wrapper*)zend_object_alloc(sizeof(swig_object_wrapper), ce);\n"); Printf(s, " zend_object_std_init(&obj->std, ce);\n"); Printf(s, " object_properties_init(&obj->std, ce);\n"); @@ -178,7 +178,7 @@ static void SwigPHP_emit_pointer_type_registrations() { Printf(s_wrappers, "static zend_object_handlers swig_ptr_object_handlers;\n\n"); Printf(s_wrappers, "/* Object Creation Method for pointer wrapping class */\n"); - Printf(s_wrappers, "static zend_object * swig_ptr_object_new(zend_class_entry *ce) {\n"); + Printf(s_wrappers, "static zend_object *swig_ptr_object_new(zend_class_entry *ce) {\n"); Printf(s_wrappers, " swig_object_wrapper *obj = (swig_object_wrapper*)zend_object_alloc(sizeof(swig_object_wrapper), ce);\n"); Printf(s_wrappers, " zend_object_std_init(&obj->std, ce);\n"); Printf(s_wrappers, " object_properties_init(&obj->std, ce);\n"); @@ -436,7 +436,7 @@ public: /* start the init section */ { - String * s_init_old = s_init; + String *s_init_old = s_init; s_init = NewString("/* init section */\n"); Printv(s_init, "zend_module_entry ", module, "_module_entry = {\n", NIL); Printf(s_init, " STANDARD_MODULE_HEADER,\n"); @@ -639,9 +639,9 @@ public: (Cmp(fname, "__construct") != 0); } else { if (overload) { - Printf(f_h, "ZEND_NAMED_FUNCTION(%s);\n", fname); + Printf(f_h, "ZEND_NAMED_FUNCTION(%s);\n", fname); } else { - Printf(f_h, "PHP_FUNCTION(%s);\n", fname); + Printf(f_h, "PHP_FUNCTION(%s);\n", fname); } } // We want to only emit each different arginfo once, as that reduces the @@ -656,9 +656,9 @@ public: for (Parm *p = l; p; p = Getattr(p, "tmap:in:next")) { if (skip_this) { skip_this = false; - continue; + continue; } - String* tmap_in_numinputs = Getattr(p, "tmap:in:numinputs"); + String *tmap_in_numinputs = Getattr(p, "tmap:in:numinputs"); // tmap:in:numinputs is unset for varargs, which we don't count here. if (!tmap_in_numinputs || Equal(tmap_in_numinputs, "0")) { /* Ignored parameter */ @@ -676,7 +676,7 @@ public: --num_arguments; --num_required; } - String * arginfo_code; + String *arginfo_code; if (overflowed) { // We overflowed the bitmap so just generate a unique name - this only // happens for a function with more parameters than bits in a long @@ -710,7 +710,7 @@ public: skip_this = false; continue; } - String* tmap_in_numinputs = Getattr(p, "tmap:in:numinputs"); + String *tmap_in_numinputs = Getattr(p, "tmap:in:numinputs"); // tmap:in:numinputs is unset for varargs, which we don't count here. if (!tmap_in_numinputs || Equal(tmap_in_numinputs, "0")) { /* Ignored parameter */ @@ -721,7 +721,7 @@ public: Printf(s_arginfo, "ZEND_END_ARG_INFO()\n"); } - String * s = cs_entry; + String *s = cs_entry; if (!s) s = s_entry; if (cname && Cmp(Getattr(n, "storage"), "friend") != 0) { Printf(all_cs_entry, " PHP_ME(%s%s,%s,swig_arginfo_%s,%s)\n", prefix, cname, fname, arginfo_code, modes); @@ -770,10 +770,10 @@ public: if (constructor) { // Renamed constructor - turn into static factory method if (Cmp(class_name, Getattr(n, "constructorHandler:sym:name")) != 0) { - constructorRenameOverload = true; - wname = Copy(Getattr(n, "constructorHandler:sym:name")); + constructorRenameOverload = true; + wname = Copy(Getattr(n, "constructorHandler:sym:name")); } else { - wname = NewString("__construct"); + wname = NewString("__construct"); } } else if (class_name) { wname = Getattr(n, "wrapper:method:name"); @@ -784,7 +784,7 @@ public: if (constructor) { modes = NewString("ZEND_ACC_PUBLIC | ZEND_ACC_CTOR"); if (constructorRenameOverload) { - Append(modes, " | ZEND_ACC_STATIC"); + Append(modes, " | ZEND_ACC_STATIC"); } } else if (wrapperType == staticmemberfn || Cmp(Getattr(n, "storage"), "static") == 0) { modes = NewString("ZEND_ACC_PUBLIC | ZEND_ACC_STATIC"); @@ -832,7 +832,7 @@ public: bool is_class_wrapped(String *className) { if (!className) return false; - Node * n = symbolLookup(className); + Node *n = symbolLookup(className); return n && Getattr(n, "classtype") != NULL; } @@ -984,27 +984,25 @@ public: } bool is_setter_method(Node *n) { - const char *p = GetChar(n, "sym:name"); - if (strlen(p) > 4) { - p += strlen(p) - 4; - if (strcmp(p, "_set") == 0) { - return true; - } + if (strlen(p) > 4) { + p += strlen(p) - 4; + if (strcmp(p, "_set") == 0) { + return true; } - return false; + } + return false; } bool is_getter_method(Node *n) { - const char *p = GetChar(n, "sym:name"); - if (strlen(p) > 4) { - p += strlen(p) - 4; - if (strcmp(p, "_get") == 0) { - return true; - } + if (strlen(p) > 4) { + p += strlen(p) - 4; + if (strcmp(p, "_get") == 0) { + return true; } - return false; + } + return false; } virtual int functionWrapper(Node *n) { @@ -1037,7 +1035,7 @@ public: if (constructor) { Append(modes, " | ZEND_ACC_CTOR"); - } + } if (wrapperType == staticmemberfn || Cmp(Getattr(n, "storage"), "static") == 0) { Append(modes, " | ZEND_ACC_STATIC"); } @@ -1058,9 +1056,9 @@ public: } else if (wrapperType == membervar) { wname = Copy(Getattr(n, "membervariableHandler:sym:name")); if (is_setter_method(n)) { - Append(wname, "_set"); + Append(wname, "_set"); } else if (is_getter_method(n)) { - Append(wname, "_get"); + Append(wname, "_get"); } } else if (wrapperType == memberfn) { wname = Getattr(n, "memberfunctionHandler:sym:name"); @@ -1069,28 +1067,28 @@ public: wname = Getattr(n, "staticmembervariableHandler:sym:name"); /* We get called twice for getter and setter methods. But to maintain - compatibility, Shape::nshapes() is being used for both setter and - getter methods. So using static_setter and static_getter variables - to generate half of the code each time. + compatibility, Shape::nshapes() is being used for both setter and + getter methods. So using static_setter and static_getter variables + to generate half of the code each time. */ static_setter = is_setter_method(n); if (is_getter_method(n)) { - // This is to overcome types that can't be set and hence no setter. - if (Cmp(Getattr(n, "feature:immutable"), "1") != 0) - static_getter = true; + // This is to overcome types that can't be set and hence no setter. + if (Cmp(Getattr(n, "feature:immutable"), "1") != 0) + static_getter = true; } } else if (wrapperType == staticmemberfn) { wname = Getattr(n, "staticmemberfunctionHandler:sym:name"); } else { if (class_name) { - if (Cmp(Getattr(n, "storage"), "friend") == 0 && Cmp(Getattr(n, "view"), "globalfunctionHandler") == 0) { - wname = iname; - } else { - wname = Getattr(n, "destructorHandler:sym:name"); - } + if (Cmp(Getattr(n, "storage"), "friend") == 0 && Cmp(Getattr(n, "view"), "globalfunctionHandler") == 0) { + wname = iname; + } else { + wname = Getattr(n, "destructorHandler:sym:name"); + } } else { - wname = iname; + wname = iname; } } @@ -1114,9 +1112,9 @@ public: if (!overloaded) { if (!static_getter) { - if (class_name && Cmp(Getattr(n, "storage"), "friend") != 0) { - Printv(f->def, "PHP_METHOD(", prefix, class_name, ",", wname, ") {\n", NIL); - } else { + if (class_name && Cmp(Getattr(n, "storage"), "friend") != 0) { + Printv(f->def, "PHP_METHOD(", prefix, class_name, ",", wname, ") {\n", NIL); + } else { if (wrap_nonclass_global) { Printv(f->def, "PHP_METHOD(", fake_class_name(), ",", wname, ") {\n", " PHP_FN(", wname, ")(INTERNAL_FUNCTION_PARAM_PASSTHRU);\n", @@ -1126,7 +1124,7 @@ public: if (wrap_nonclass_fake_class) { Printv(f->def, "PHP_FUNCTION(", wname, ") {\n", NIL); } - } + } } } else { Printv(f->def, "ZEND_NAMED_FUNCTION(", overloadwname, ") {\n", NIL); @@ -1181,9 +1179,9 @@ public: Printf(f->code, "\tWRONG_PARAM_COUNT;\n\n"); } else if (static_setter || static_getter) { if (num_arguments == 0) { - Printf(f->code, "if(ZEND_NUM_ARGS() == 0) {\n"); + Printf(f->code, "if(ZEND_NUM_ARGS() == 0) {\n"); } else { - Printf(f->code, "if(ZEND_NUM_ARGS() == %d && zend_get_parameters_array_ex(%d, args) == SUCCESS) {\n", num_arguments, num_arguments); + Printf(f->code, "if(ZEND_NUM_ARGS() == %d && zend_get_parameters_array_ex(%d, args) == SUCCESS) {\n", num_arguments, num_arguments); } } else { if (num_arguments == 0) { @@ -1392,24 +1390,24 @@ public: { tm = Swig_typemap_lookup("consttab", n, name, 0); Replaceall(tm, "$value", value); - if (Getattr(n, "tmap:consttab:rinit")) { - Printf(r_init, "%s\n", tm); - } else { - Printf(s_cinit, "%s\n", tm); - } + if (Getattr(n, "tmap:consttab:rinit")) { + Printf(r_init, "%s\n", tm); + } else { + Printf(s_cinit, "%s\n", tm); + } } { - tm = Swig_typemap_lookup("classconsttab", n, name, 0); + tm = Swig_typemap_lookup("classconsttab", n, name, 0); - Replaceall(tm, "$class", fake_class_name()); - Replaceall(tm, "$const_name", iname); + Replaceall(tm, "$class", fake_class_name()); + Replaceall(tm, "$const_name", iname); Replaceall(tm, "$value", value); - if (Getattr(n, "tmap:classconsttab:rinit")) { - Printf(r_init, "%s\n", tm); - } else { - Printf(s_cinit, "%s\n", tm); - } + if (Getattr(n, "tmap:classconsttab:rinit")) { + Printf(r_init, "%s\n", tm); + } else { + Printf(s_cinit, "%s\n", tm); + } } } else { tm = Swig_typemap_lookup("classconsttab", n, name, 0); @@ -1417,9 +1415,9 @@ public: Replaceall(tm, "$const_name", wrapping_member_constant); Replaceall(tm, "$value", value); if (Getattr(n, "tmap:classconsttab:rinit")) { - Printf(r_init, "%s\n", tm); + Printf(r_init, "%s\n", tm); } else { - Printf(s_cinit, "%s\n", tm); + Printf(s_cinit, "%s\n", tm); } } @@ -1915,7 +1913,7 @@ public: Append(w->def, " {"); Append(declaration, ";\n"); - /* declare method return value + /* declare method return value * if the return value is a reference or const reference, a specialized typemap must * handle it, including declaration of c_result ($result). */ @@ -2018,7 +2016,7 @@ public: /* wrap complex arguments to zvals */ Append(w->code, wrap_args); - const char * funcname = GetChar(n, "sym:name"); + const char *funcname = GetChar(n, "sym:name"); Append(w->code, "{\n"); Append(w->code, "#if PHP_MAJOR_VERSION < 8\n"); Printf(w->code, "zval swig_funcname;\n"); From 6253583809d66f399cacba251f55bbda6487b6cc Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Fri, 17 Dec 2021 09:37:00 +1300 Subject: [PATCH 050/662] Rename php_fetch_object with swig_ prefix We shouldn't be using symbols starting `php` as that risks collisions with future symbols defined by PHP. --- Lib/php/phprun.swg | 6 +++--- Source/Modules/php.cxx | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Lib/php/phprun.swg b/Lib/php/phprun.swg index a3569a783..6f0cc9650 100644 --- a/Lib/php/phprun.swg +++ b/Lib/php/phprun.swg @@ -81,10 +81,10 @@ typedef struct { zend_object std; } swig_object_wrapper; -#define SWIG_Z_FETCH_OBJ_P(zv) php_fetch_object(Z_OBJ_P(zv)) +#define SWIG_Z_FETCH_OBJ_P(zv) swig_php_fetch_object(Z_OBJ_P(zv)) static inline -swig_object_wrapper * php_fetch_object(zend_object *obj) { +swig_object_wrapper * swig_php_fetch_object(zend_object *obj) { return (swig_object_wrapper *)((char *)obj - XtOffsetOf(swig_object_wrapper, std)); } @@ -115,7 +115,7 @@ SWIG_SetPointerZval(zval *z, void *ptr, swig_type_info *type, int newobject) { obj = ce->create_object(ce); ZVAL_OBJ(z, obj); } - value = php_fetch_object(obj); + value = swig_php_fetch_object(obj); value->ptr = ptr; value->newobject = (newobject & 1); value->type = type; diff --git a/Source/Modules/php.cxx b/Source/Modules/php.cxx index 732f1ce61..e778a735d 100644 --- a/Source/Modules/php.cxx +++ b/Source/Modules/php.cxx @@ -134,7 +134,7 @@ static void print_creation_free_wrapper(Node *n) { Printf(s, " swig_object_wrapper *obj = 0;\n"); Printf(s, " if (!object)\n"); Printf(s, " return;\n"); - Printf(s, " obj = php_fetch_object(object);\n"); + Printf(s, " obj = swig_php_fetch_object(object);\n"); Printf(s, " zend_object_std_dtor(&obj->std);\n"); @@ -198,7 +198,7 @@ static void SwigPHP_emit_pointer_type_registrations() { Append(s_wrappers, "#if PHP_MAJOR_VERSION < 8\n"); Printf(s_wrappers, " swig_object_wrapper *obj = SWIG_Z_FETCH_OBJ_P(z);\n"); Append(s_wrappers, "#else\n"); - Printf(s_wrappers, " swig_object_wrapper *obj = php_fetch_object(zobj);\n"); + Printf(s_wrappers, " swig_object_wrapper *obj = swig_php_fetch_object(zobj);\n"); Append(s_wrappers, "#endif\n"); Printv(s_wrappers, " sprintf(buf, \"SWIGPointer(%p,owned=%d)\", obj->ptr, obj->newobject);\n", NIL); Printf(s_wrappers, " ZVAL_STRING(retval, buf);\n"); From 5da86a14132ae96d885ef12ad04cf771bdb5dd57 Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Fri, 17 Dec 2021 09:38:44 +1300 Subject: [PATCH 051/662] Make some generated functions static --- Source/Modules/php.cxx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Source/Modules/php.cxx b/Source/Modules/php.cxx index e778a735d..3a62282d8 100644 --- a/Source/Modules/php.cxx +++ b/Source/Modules/php.cxx @@ -124,13 +124,13 @@ static void print_creation_free_wrapper(Node *n) { String *s = s_creation; Printf(s, "/* class entry for %s */\n",class_name); - Printf(s, "zend_class_entry *SWIGTYPE_%s_ce;\n\n",class_name); + Printf(s, "static zend_class_entry *SWIGTYPE_%s_ce;\n\n",class_name); Printf(s, "/* class object handlers for %s */\n",class_name); - Printf(s, "zend_object_handlers %s_object_handlers;\n\n",class_name); + Printf(s, "static zend_object_handlers %s_object_handlers;\n\n",class_name); if (Getattr(n, "has_destructor")) { Printf(s, "/* Garbage Collection Method for class %s */\n",class_name); - Printf(s, "void %s_free_storage(zend_object *object) {\n",class_name); + Printf(s, "static void %s_free_storage(zend_object *object) {\n",class_name); Printf(s, " swig_object_wrapper *obj = 0;\n"); Printf(s, " if (!object)\n"); Printf(s, " return;\n"); @@ -155,7 +155,7 @@ static void print_creation_free_wrapper(Node *n) { } Printf(s, "/* Object Creation Method for class %s */\n",class_name); - Printf(s, "zend_object *%s_object_new(zend_class_entry *ce) {\n",class_name); + Printf(s, "static zend_object *%s_object_new(zend_class_entry *ce) {\n",class_name); Printf(s, " swig_object_wrapper *obj = (swig_object_wrapper*)zend_object_alloc(sizeof(swig_object_wrapper), ce);\n"); Printf(s, " zend_object_std_init(&obj->std, ce);\n"); Printf(s, " object_properties_init(&obj->std, ce);\n"); From 78f5404727f18e821267b0500e811baf8042d892 Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Fri, 17 Dec 2021 10:11:52 +1300 Subject: [PATCH 052/662] Improve generated object handlers Do more initialisation at module load time. Use a shared set of handlers for cases when the C/C++ object is destroyed with free(). Most of the code in the free_obj and create_object handlers is the same for every wrapped class so factor that out into common functions. --- Lib/php/phprun.swg | 21 ++++++ Source/Modules/php.cxx | 143 +++++++++++++++++++++-------------------- 2 files changed, 95 insertions(+), 69 deletions(-) diff --git a/Lib/php/phprun.swg b/Lib/php/phprun.swg index 6f0cc9650..426efe104 100644 --- a/Lib/php/phprun.swg +++ b/Lib/php/phprun.swg @@ -206,3 +206,24 @@ static swig_module_info *SWIG_Php_GetModule() { static void SWIG_Php_SetModule(swig_module_info *pointer, int module_number) { REGISTER_LONG_CONSTANT(const_name, (long) pointer, CONST_CS | CONST_PERSISTENT); } + +/* Common parts of the "create_object" object handler. */ +static zend_object *SWIG_Php_do_create_object(zend_class_entry *ce, zend_object_handlers *handlers) { + swig_object_wrapper *obj = (swig_object_wrapper*)zend_object_alloc(sizeof(swig_object_wrapper), ce); + zend_object_std_init(&obj->std, ce); + object_properties_init(&obj->std, ce); + obj->std.handlers = handlers; + obj->newobject = 1; + return &obj->std; +} + +/* Common parts of the "free_obj" object handler. + Returns void* pointer if the C/C++ object should be destroyed. */ +static void* SWIG_Php_free_obj(zend_object *object) { + if (object) { + swig_object_wrapper *obj = swig_php_fetch_object(object); + zend_object_std_dtor(&obj->std); + if (obj->newobject) return obj->ptr; + } + return NULL; +} diff --git a/Source/Modules/php.cxx b/Source/Modules/php.cxx index 3a62282d8..b83995956 100644 --- a/Source/Modules/php.cxx +++ b/Source/Modules/php.cxx @@ -74,9 +74,6 @@ static String *fake_class_name() { static String *result = NULL; if (!result) { result = Len(prefix) ? prefix : module; - if (!s_creation) { - s_creation = NewStringEmpty(); - } if (!fake_cs_entry) { fake_cs_entry = NewStringf("static zend_function_entry class_%s_functions[] = {\n", result); } @@ -116,56 +113,6 @@ extern "C" { static void (*r_prevtracefunc) (const SwigType *t, String *mangled, String *clientdata) = 0; } -static void print_creation_free_wrapper(Node *n) { - if (!s_creation) { - s_creation = NewStringEmpty(); - } - - String *s = s_creation; - - Printf(s, "/* class entry for %s */\n",class_name); - Printf(s, "static zend_class_entry *SWIGTYPE_%s_ce;\n\n",class_name); - Printf(s, "/* class object handlers for %s */\n",class_name); - Printf(s, "static zend_object_handlers %s_object_handlers;\n\n",class_name); - - if (Getattr(n, "has_destructor")) { - Printf(s, "/* Garbage Collection Method for class %s */\n",class_name); - Printf(s, "static void %s_free_storage(zend_object *object) {\n",class_name); - Printf(s, " swig_object_wrapper *obj = 0;\n"); - Printf(s, " if (!object)\n"); - Printf(s, " return;\n"); - Printf(s, " obj = swig_php_fetch_object(object);\n"); - - Printf(s, " zend_object_std_dtor(&obj->std);\n"); - - Printf(s, " if (obj->newobject)"); - String *type = Getattr(n, "classtype"); - if (destructor_action) { - Printv(s, - " {\n", - type, " * arg1 = (", type, " *)obj->ptr;\n", - destructor_action, "\n", - " }\n", NIL); - } else if (CPlusPlus) { - Printf(s, "\n delete (%s *)obj->ptr;\n", type); - } else { - Printf(s, "\n free(obj->ptr);\n", type); - } - Printf(s, "}\n\n"); - } - - Printf(s, "/* Object Creation Method for class %s */\n",class_name); - Printf(s, "static zend_object *%s_object_new(zend_class_entry *ce) {\n",class_name); - Printf(s, " swig_object_wrapper *obj = (swig_object_wrapper*)zend_object_alloc(sizeof(swig_object_wrapper), ce);\n"); - Printf(s, " zend_object_std_init(&obj->std, ce);\n"); - Printf(s, " object_properties_init(&obj->std, ce);\n"); - Printf(s, " %s_object_handlers.offset = XtOffsetOf(swig_object_wrapper, std);\n", class_name); - if (Getattr(n, "has_destructor")) { - Printf(s, " %s_object_handlers.free_obj = %s_free_storage;\n", class_name, class_name); - } - Printf(s, " obj->std.handlers = &%s_object_handlers;\n obj->newobject = 1;\n return &obj->std;\n}\n\n\n",class_name); -} - static void SwigPHP_emit_pointer_type_registrations() { if (!zend_types) return; @@ -208,17 +155,13 @@ static void SwigPHP_emit_pointer_type_registrations() { Printf(s_wrappers, "}\n\n"); Printf(s_oinit, "\n /* Register classes to represent non-class pointer types */\n"); - Printf(s_oinit, " memcpy(&swig_ptr_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers));\n"); + Printf(s_oinit, " swig_ptr_object_handlers = *zend_get_std_object_handlers();\n"); Printf(s_oinit, " swig_ptr_object_handlers.offset = XtOffsetOf(swig_object_wrapper, std);\n"); Printf(s_oinit, " swig_ptr_object_handlers.cast_object = swig_ptr_cast_object;\n"); while (ki.key) { String *type = ki.key; - if (!s_creation) { - s_creation = NewStringEmpty(); - } - Printf(s_creation, "/* class entry for pointer to %s */\n", type); Printf(s_creation, "zend_class_entry *SWIGTYPE_%s_ce;\n\n", type); @@ -309,6 +252,7 @@ public: r_shutdown = NewStringEmpty(); s_header = NewString("/* header section */\n"); s_wrappers = NewString("/* wrapper section */\n"); + s_creation = NewStringEmpty(); /* subsections of the init section */ s_vdecl = NewString("/* vdecl subsection */\n"); s_cinit = NewString(" /* cinit subsection */\n"); @@ -428,11 +372,9 @@ public: Language::top(n); SwigPHP_emit_pointer_type_registrations(); - if (s_creation) { - Dump(s_creation, s_header); - Delete(s_creation); - s_creation = NULL; - } + Dump(s_creation, s_header); + Delete(s_creation); + s_creation = NULL; /* start the init section */ { @@ -1616,9 +1558,75 @@ public: Delete(interfaces); } - Printf(s_oinit, " SWIGTYPE_%s_ce->create_object = %s_object_new;\n", class_name, class_name); - Printf(s_oinit, " memcpy(&%s_object_handlers,zend_get_std_object_handlers(), sizeof(zend_object_handlers));\n", class_name); - Printf(s_oinit, " %s_object_handlers.clone_obj = NULL;\n", class_name); + Language::classHandler(n); + + static bool emitted_base_object_handlers = false; + if (!emitted_base_object_handlers) { + Printf(s_creation, "static zend_object_handlers SWIGTYPE_base_object_handlers;\n\n"); + + // Set up a base zend_object_handlers structure which we can use as-is + // for classes without a destructor, and copy as the basis for other + // classes. + Printf(s_oinit, " SWIGTYPE_base_object_handlers = *zend_get_std_object_handlers();\n"); + Printf(s_oinit, " SWIGTYPE_base_object_handlers.offset = XtOffsetOf(swig_object_wrapper, std);\n"); + Printf(s_oinit, " SWIGTYPE_base_object_handlers.clone_obj = NULL;\n"); + emitted_base_object_handlers = true; + } + + Printf(s_creation, "static zend_class_entry *SWIGTYPE_%s_ce;\n\n", class_name); + + if (Getattr(n, "has_destructor")) { + if (destructor_action ? Equal(destructor_action, "free((char *) arg1);") : !CPlusPlus) { + // We can use a single function if the destructor action calls free() + // (either explicitly or as the default in C-mode) since free() doesn't + // care about the object's type. We currently only check for the exact + // code that Swig_cdestructor_call() emits. + static bool emitted_common_cdestructor = false; + if (!emitted_common_cdestructor) { + Printf(s_creation, "static zend_object_handlers SWIGTYPE_common_c_object_handlers;\n\n"); + Printf(s_creation, "static void SWIG_Php_common_c_free_obj(zend_object *object) {free(SWIG_Php_free_obj(object));}\n\n"); + Printf(s_creation, "static zend_object *SWIG_Php_common_c_create_object(zend_class_entry *ce) {return SWIG_Php_do_create_object(ce, &SWIGTYPE_common_c_object_handlers);}\n"); + + Printf(s_oinit, " SWIGTYPE_common_c_object_handlers = SWIGTYPE_base_object_handlers;\n"); + Printf(s_oinit, " SWIGTYPE_common_c_object_handlers.free_obj = SWIG_Php_common_c_free_obj;\n"); + + emitted_common_cdestructor = true; + } + + Printf(s_oinit, " SWIGTYPE_%s_ce->create_object = SWIG_Php_common_c_create_object;\n", class_name); + } else { + Printf(s_creation, "static zend_object_handlers %s_object_handlers;\n", class_name); + Printf(s_creation, "static zend_object *SWIG_Php_create_object_%s(zend_class_entry *ce) {return SWIG_Php_do_create_object(ce, &%s_object_handlers);}\n", class_name, class_name); + + Printf(s_creation, "static void SWIG_Php_free_obj_%s(zend_object *object) {",class_name); + String *type = Getattr(n, "classtype"); + // Special case handling the delete call generated by + // Swig_cppdestructor_call() and generate simpler code. + if (destructor_action && !Equal(destructor_action, "delete arg1;")) { + Printv(s_creation, "\n" + " ", type, " *arg1 = (" , type, " *)SWIG_Php_free_obj(object);\n" + " if (arg1) {\n" + " ", destructor_action, "\n" + " }\n", NIL); + } else { + Printf(s_creation, "delete (%s *)SWIG_Php_free_obj(object);", type); + } + Printf(s_creation, "}\n\n"); + + Printf(s_oinit, " SWIGTYPE_%s_ce->create_object = SWIG_Php_create_object_%s;\n", class_name, class_name); + Printf(s_oinit, " %s_object_handlers = SWIGTYPE_base_object_handlers;\n", class_name); + Printf(s_oinit, " %s_object_handlers.free_obj = SWIG_Php_free_obj_%s;\n", class_name, class_name); + } + } else { + static bool emitted_destructorless_create_object = false; + if (!emitted_destructorless_create_object) { + emitted_destructorless_create_object = true; + Printf(s_creation, "static zend_object *SWIG_Php_create_object(zend_class_entry *ce) {return SWIG_Php_do_create_object(ce, &SWIGTYPE_base_object_handlers);}\n", class_name); + } + + Printf(s_oinit, " SWIGTYPE_%s_ce->create_object = SWIG_Php_create_object;\n", class_name); + } + // If not defined we aren't wrapping any functions which use this type as a // parameter or return value, in which case we don't need the clientdata // set. @@ -1627,9 +1635,6 @@ public: Printf(s_oinit, "#endif\n"); Printf(s_oinit, "\n"); - Language::classHandler(n); - - print_creation_free_wrapper(n); generate_magic_property_methods(n, base_class); Printf(all_cs_entry, " ZEND_FE_END\n};\n\n"); From f976927d52cb323a1ba782de17e3181f8dba21dc Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Fri, 17 Dec 2021 12:25:40 +1300 Subject: [PATCH 053/662] Fix source code comment typo --- Source/Modules/php.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Modules/php.cxx b/Source/Modules/php.cxx index b83995956..836c2059e 100644 --- a/Source/Modules/php.cxx +++ b/Source/Modules/php.cxx @@ -1521,7 +1521,7 @@ public: String *interface = Getitem(interface_list, i); // We generate conditional code in both minit and rinit - then we or the user // just need to define SWIG_PHP_INTERFACE_xxx_CE (and optionally - // SWIG_PHP_INTERFACE_xxx_CE) to handle interface `xxx` at minit-time. + // SWIG_PHP_INTERFACE_xxx_HEADER) to handle interface `xxx` at minit-time. Printv(s_header, "#ifdef SWIG_PHP_INTERFACE_", interface, "_HEADER\n", "# include SWIG_PHP_INTERFACE_", interface, "_HEADER\n", From cf802c63f2b1192d1c6a6ef764fca22294bd88b3 Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Fri, 17 Dec 2021 17:14:54 +1300 Subject: [PATCH 054/662] Improve naming of zend_class_entry structs Previously the zend_class_entry for Foo was named SWIGTYPE_Foo_ce, but this can collide in some cases - e.g. if there's a class named p_Foo then its zend_class entry will be SWIGTYPE_p_Foo_ce, but that's the same as the swig_type_info for a class named p_Foo_ce. --- Lib/php/const.i | 12 ++++----- Source/Modules/php.cxx | 57 +++++++++++++++++++++--------------------- 2 files changed, 35 insertions(+), 34 deletions(-) diff --git a/Lib/php/const.i b/Lib/php/const.i index 3b40c2c7f..6e83ffe88 100644 --- a/Lib/php/const.i +++ b/Lib/php/const.i @@ -12,22 +12,22 @@ unsigned char, signed char, enum SWIGTYPE %{ - zend_declare_class_constant_long(SWIGTYPE_$class_ce, "$const_name", sizeof("$const_name") - 1, ($1_type)$value); + zend_declare_class_constant_long(SWIG_Php_ce_$class, "$const_name", sizeof("$const_name") - 1, ($1_type)$value); %} %typemap(classconsttab) bool %{ - zend_declare_class_constant_bool(SWIGTYPE_$class_ce, "$const_name", sizeof("$const_name") - 1, ($1_type)$value); + zend_declare_class_constant_bool(SWIG_Php_ce_$class, "$const_name", sizeof("$const_name") - 1, ($1_type)$value); %} %typemap(classconsttab) float, double %{ - zend_declare_class_constant_double(SWIGTYPE_$class_ce, "$const_name", sizeof("$const_name") - 1, $value); + zend_declare_class_constant_double(SWIG_Php_ce_$class, "$const_name", sizeof("$const_name") - 1, $value); %} %typemap(classconsttab) char %{ { char swig_char = $value; - zend_declare_class_constant_stringl(SWIGTYPE_$class_ce, "$const_name", sizeof("$const_name") - 1, &swig_char, 1); + zend_declare_class_constant_stringl(SWIG_Php_ce_$class, "$const_name", sizeof("$const_name") - 1, &swig_char, 1); } %} @@ -35,7 +35,7 @@ const char *, char [], const char [] %{ - zend_declare_class_constant_string(SWIGTYPE_$class_ce, "$const_name", sizeof("$const_name") - 1, $value); + zend_declare_class_constant_string(SWIG_Php_ce_$class, "$const_name", sizeof("$const_name") - 1, $value); %} // This creates a zend_object to wrap the pointer, and we can't do that @@ -50,7 +50,7 @@ ZVAL_UNDEF(&z); SWIG_SetPointerZval(&z, (void*)$value, $1_descriptor, 0); zval_copy_ctor(&z); - zend_declare_class_constant(SWIGTYPE_$class_ce, "$const_name", sizeof("$const_name") - 1, &z); + zend_declare_class_constant(SWIG_Php_ce_$class, "$const_name", sizeof("$const_name") - 1, &z); } %} diff --git a/Source/Modules/php.cxx b/Source/Modules/php.cxx index 836c2059e..f3dac4bfb 100644 --- a/Source/Modules/php.cxx +++ b/Source/Modules/php.cxx @@ -77,10 +77,11 @@ static String *fake_class_name() { if (!fake_cs_entry) { fake_cs_entry = NewStringf("static zend_function_entry class_%s_functions[] = {\n", result); } - Printf(s_creation, "/* class entry for %s */\n",result); - Printf(s_creation, "zend_class_entry *SWIGTYPE_%s_ce;\n\n",result); + + Printf(s_creation, "zend_class_entry *SWIG_Php_ce_%s;\n\n",result); + Printf(s_oinit, " INIT_CLASS_ENTRY(internal_ce, \"%s\", class_%s_functions);\n", result, result); - Printf(s_oinit, " SWIGTYPE_%s_ce = zend_register_internal_class(&internal_ce);\n", result); + Printf(s_oinit, " SWIG_Php_ce_%s = zend_register_internal_class(&internal_ce);\n", result); Printf(s_oinit, "\n"); } return result; @@ -163,12 +164,12 @@ static void SwigPHP_emit_pointer_type_registrations() { String *type = ki.key; Printf(s_creation, "/* class entry for pointer to %s */\n", type); - Printf(s_creation, "zend_class_entry *SWIGTYPE_%s_ce;\n\n", type); + Printf(s_creation, "zend_class_entry *SWIG_Php_ce_%s;\n\n", type); Printf(s_oinit, " INIT_CLASS_ENTRY(internal_ce, \"%s\\\\%s\", NULL);\n", "SWIG", type); - Printf(s_oinit, " SWIGTYPE_%s_ce = zend_register_internal_class(&internal_ce);\n", type); - Printf(s_oinit, " SWIGTYPE_%s_ce->create_object = swig_ptr_object_new;\n", type); - Printf(s_oinit, " SWIG_TypeClientData(SWIGTYPE%s,SWIGTYPE_%s_ce);\n", type, type); + Printf(s_oinit, " SWIG_Php_ce_%s = zend_register_internal_class(&internal_ce);\n", type); + Printf(s_oinit, " SWIG_Php_ce_%s->create_object = swig_ptr_object_new;\n", type); + Printf(s_oinit, " SWIG_TypeClientData(SWIGTYPE%s,SWIG_Php_ce_%s);\n", type, type); Printf(s_oinit, "\n"); ki = Next(ki); @@ -1480,15 +1481,15 @@ public: } if (Equal(base_class, "Exception")) { - Printf(s_oinit, " SWIGTYPE_%s_ce = zend_register_internal_class_ex(&internal_ce, zend_ce_exception);\n", class_name); + Printf(s_oinit, " SWIG_Php_ce_%s = zend_register_internal_class_ex(&internal_ce, zend_ce_exception);\n", class_name); } else if (is_class_wrapped(base_class)) { - Printf(s_oinit, " SWIGTYPE_%s_ce = zend_register_internal_class_ex(&internal_ce, SWIGTYPE_%s_ce);\n", class_name, base_class); + Printf(s_oinit, " SWIG_Php_ce_%s = zend_register_internal_class_ex(&internal_ce, SWIG_Php_ce_%s);\n", class_name, base_class); } else { - Printf(s_oinit, " SWIGTYPE_%s_ce = zend_register_internal_class(&internal_ce);\n", class_name); + Printf(s_oinit, " SWIG_Php_ce_%s = zend_register_internal_class(&internal_ce);\n", class_name); } if (Getattr(n, "abstracts") && !GetFlag(n, "feature:notabstract")) { - Printf(s_oinit, " SWIGTYPE_%s_ce->ce_flags |= ZEND_ACC_EXPLICIT_ABSTRACT_CLASS;\n", class_name); + Printf(s_oinit, " SWIG_Php_ce_%s->ce_flags |= ZEND_ACC_EXPLICIT_ABSTRACT_CLASS;\n", class_name); } { @@ -1529,7 +1530,7 @@ public: NIL); Printv(s_oinit, "#ifdef SWIG_PHP_INTERFACE_", interface, "_CE\n", - " zend_do_implement_interface(SWIGTYPE_", class_name, "_ce, SWIG_PHP_INTERFACE_", interface, "_CE);\n", + " zend_do_implement_interface(SWIG_Php_ce_", class_name, ", SWIG_PHP_INTERFACE_", interface, "_CE);\n", "#endif\n", NIL); Printv(r_init_prefix, @@ -1537,7 +1538,7 @@ public: " {\n", " zend_class_entry *swig_interface_ce = zend_lookup_class(zend_string_init(\"", interface, "\", sizeof(\"", interface, "\") - 1, 0));\n", " if (!swig_interface_ce) zend_throw_exception(zend_ce_error, \"Interface \\\"", interface, "\\\" not found\", 0);\n", - " zend_do_implement_interface(SWIGTYPE_", class_name, "_ce, swig_interface_ce);\n", + " zend_do_implement_interface(SWIG_Php_ce_", class_name, ", swig_interface_ce);\n", " }\n", "#endif\n", NIL); @@ -1562,18 +1563,18 @@ public: static bool emitted_base_object_handlers = false; if (!emitted_base_object_handlers) { - Printf(s_creation, "static zend_object_handlers SWIGTYPE_base_object_handlers;\n\n"); + Printf(s_creation, "static zend_object_handlers Swig_Php_base_object_handlers;\n\n"); // Set up a base zend_object_handlers structure which we can use as-is // for classes without a destructor, and copy as the basis for other // classes. - Printf(s_oinit, " SWIGTYPE_base_object_handlers = *zend_get_std_object_handlers();\n"); - Printf(s_oinit, " SWIGTYPE_base_object_handlers.offset = XtOffsetOf(swig_object_wrapper, std);\n"); - Printf(s_oinit, " SWIGTYPE_base_object_handlers.clone_obj = NULL;\n"); + Printf(s_oinit, " Swig_Php_base_object_handlers = *zend_get_std_object_handlers();\n"); + Printf(s_oinit, " Swig_Php_base_object_handlers.offset = XtOffsetOf(swig_object_wrapper, std);\n"); + Printf(s_oinit, " Swig_Php_base_object_handlers.clone_obj = NULL;\n"); emitted_base_object_handlers = true; } - Printf(s_creation, "static zend_class_entry *SWIGTYPE_%s_ce;\n\n", class_name); + Printf(s_creation, "static zend_class_entry *SWIG_Php_ce_%s;\n\n", class_name); if (Getattr(n, "has_destructor")) { if (destructor_action ? Equal(destructor_action, "free((char *) arg1);") : !CPlusPlus) { @@ -1583,17 +1584,17 @@ public: // code that Swig_cdestructor_call() emits. static bool emitted_common_cdestructor = false; if (!emitted_common_cdestructor) { - Printf(s_creation, "static zend_object_handlers SWIGTYPE_common_c_object_handlers;\n\n"); + Printf(s_creation, "static zend_object_handlers Swig_Php_common_c_object_handlers;\n\n"); Printf(s_creation, "static void SWIG_Php_common_c_free_obj(zend_object *object) {free(SWIG_Php_free_obj(object));}\n\n"); - Printf(s_creation, "static zend_object *SWIG_Php_common_c_create_object(zend_class_entry *ce) {return SWIG_Php_do_create_object(ce, &SWIGTYPE_common_c_object_handlers);}\n"); + Printf(s_creation, "static zend_object *SWIG_Php_common_c_create_object(zend_class_entry *ce) {return SWIG_Php_do_create_object(ce, &Swig_Php_common_c_object_handlers);}\n"); - Printf(s_oinit, " SWIGTYPE_common_c_object_handlers = SWIGTYPE_base_object_handlers;\n"); - Printf(s_oinit, " SWIGTYPE_common_c_object_handlers.free_obj = SWIG_Php_common_c_free_obj;\n"); + Printf(s_oinit, " Swig_Php_common_c_object_handlers = Swig_Php_base_object_handlers;\n"); + Printf(s_oinit, " Swig_Php_common_c_object_handlers.free_obj = SWIG_Php_common_c_free_obj;\n"); emitted_common_cdestructor = true; } - Printf(s_oinit, " SWIGTYPE_%s_ce->create_object = SWIG_Php_common_c_create_object;\n", class_name); + Printf(s_oinit, " SWIG_Php_ce_%s->create_object = SWIG_Php_common_c_create_object;\n", class_name); } else { Printf(s_creation, "static zend_object_handlers %s_object_handlers;\n", class_name); Printf(s_creation, "static zend_object *SWIG_Php_create_object_%s(zend_class_entry *ce) {return SWIG_Php_do_create_object(ce, &%s_object_handlers);}\n", class_name, class_name); @@ -1613,25 +1614,25 @@ public: } Printf(s_creation, "}\n\n"); - Printf(s_oinit, " SWIGTYPE_%s_ce->create_object = SWIG_Php_create_object_%s;\n", class_name, class_name); - Printf(s_oinit, " %s_object_handlers = SWIGTYPE_base_object_handlers;\n", class_name); + Printf(s_oinit, " SWIG_Php_ce_%s->create_object = SWIG_Php_create_object_%s;\n", class_name, class_name); + Printf(s_oinit, " %s_object_handlers = Swig_Php_base_object_handlers;\n", class_name); Printf(s_oinit, " %s_object_handlers.free_obj = SWIG_Php_free_obj_%s;\n", class_name, class_name); } } else { static bool emitted_destructorless_create_object = false; if (!emitted_destructorless_create_object) { emitted_destructorless_create_object = true; - Printf(s_creation, "static zend_object *SWIG_Php_create_object(zend_class_entry *ce) {return SWIG_Php_do_create_object(ce, &SWIGTYPE_base_object_handlers);}\n", class_name); + Printf(s_creation, "static zend_object *SWIG_Php_create_object(zend_class_entry *ce) {return SWIG_Php_do_create_object(ce, &Swig_Php_base_object_handlers);}\n", class_name); } - Printf(s_oinit, " SWIGTYPE_%s_ce->create_object = SWIG_Php_create_object;\n", class_name); + Printf(s_oinit, " SWIG_Php_ce_%s->create_object = SWIG_Php_create_object;\n", class_name); } // If not defined we aren't wrapping any functions which use this type as a // parameter or return value, in which case we don't need the clientdata // set. Printf(s_oinit, "#ifdef SWIGTYPE_p%s\n", SwigType_manglestr(Getattr(n, "classtypeobj"))); - Printf(s_oinit, " SWIG_TypeClientData(SWIGTYPE_p%s,SWIGTYPE_%s_ce);\n", SwigType_manglestr(Getattr(n, "classtypeobj")), class_name); + Printf(s_oinit, " SWIG_TypeClientData(SWIGTYPE_p%s,SWIG_Php_ce_%s);\n", SwigType_manglestr(Getattr(n, "classtypeobj")), class_name); Printf(s_oinit, "#endif\n"); Printf(s_oinit, "\n"); From 4672318b427b7d826dd447653f9ddff4900f199d Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Fri, 17 Dec 2021 22:32:07 +1300 Subject: [PATCH 055/662] Make some generated variables static --- Source/Modules/php.cxx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Source/Modules/php.cxx b/Source/Modules/php.cxx index f3dac4bfb..510e7ea58 100644 --- a/Source/Modules/php.cxx +++ b/Source/Modules/php.cxx @@ -78,7 +78,7 @@ static String *fake_class_name() { fake_cs_entry = NewStringf("static zend_function_entry class_%s_functions[] = {\n", result); } - Printf(s_creation, "zend_class_entry *SWIG_Php_ce_%s;\n\n",result); + Printf(s_creation, "static zend_class_entry *SWIG_Php_ce_%s;\n\n",result); Printf(s_oinit, " INIT_CLASS_ENTRY(internal_ce, \"%s\", class_%s_functions);\n", result, result); Printf(s_oinit, " SWIG_Php_ce_%s = zend_register_internal_class(&internal_ce);\n", result); @@ -164,7 +164,7 @@ static void SwigPHP_emit_pointer_type_registrations() { String *type = ki.key; Printf(s_creation, "/* class entry for pointer to %s */\n", type); - Printf(s_creation, "zend_class_entry *SWIG_Php_ce_%s;\n\n", type); + Printf(s_creation, "static zend_class_entry *SWIG_Php_ce_%s;\n\n", type); Printf(s_oinit, " INIT_CLASS_ENTRY(internal_ce, \"%s\\\\%s\", NULL);\n", "SWIG", type); Printf(s_oinit, " SWIG_Php_ce_%s = zend_register_internal_class(&internal_ce);\n", type); From 499fb747073e2ff66086bd5a7698ccdd35850df2 Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Sat, 18 Dec 2021 11:24:00 +1300 Subject: [PATCH 056/662] Remove unused Printf parameters --- Source/Modules/php.cxx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Source/Modules/php.cxx b/Source/Modules/php.cxx index 510e7ea58..4320032d3 100644 --- a/Source/Modules/php.cxx +++ b/Source/Modules/php.cxx @@ -845,7 +845,7 @@ public: Printf(all_cs_entry, " PHP_ME(%s%s,__get,swig_arginfo_1,ZEND_ACC_PUBLIC)\n", prefix, class_name); Printf(f->code, "PHP_METHOD(%s%s,__get) {\n",prefix, class_name); - Printf(f->code, " swig_object_wrapper *arg = SWIG_Z_FETCH_OBJ_P(ZEND_THIS);\n", class_name); + Printf(f->code, " swig_object_wrapper *arg = SWIG_Z_FETCH_OBJ_P(ZEND_THIS);\n"); Printf(f->code, " zval args[1];\n zval tempZval;\n zend_string *arg2 = 0;\n\n"); Printf(f->code, " if(ZEND_NUM_ARGS() != 1 || zend_get_parameters_array_ex(1, args) != SUCCESS) {\n"); Printf(f->code, "\tWRONG_PARAM_COUNT;\n}\n\n"); @@ -878,7 +878,7 @@ public: Printf(all_cs_entry, " PHP_ME(%s%s,__isset,swig_arginfo_1,ZEND_ACC_PUBLIC)\n", prefix, class_name); Printf(f->code, "PHP_METHOD(%s%s,__isset) {\n",prefix, class_name); - Printf(f->code, " swig_object_wrapper *arg = SWIG_Z_FETCH_OBJ_P(ZEND_THIS);\n", class_name); + Printf(f->code, " swig_object_wrapper *arg = SWIG_Z_FETCH_OBJ_P(ZEND_THIS);\n"); Printf(f->code, " zval args[1];\n zend_string *arg2 = 0;\n\n"); Printf(f->code, " if(ZEND_NUM_ARGS() != 1 || zend_get_parameters_array_ex(1, args) != SUCCESS) {\n"); Printf(f->code, "\tWRONG_PARAM_COUNT;\n}\n\n"); From f04d741d1c752f3af87c90820ee1d386e56a924d Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Sat, 18 Dec 2021 14:06:36 +1300 Subject: [PATCH 057/662] [php] Actually implement abstract_inherit_runme.php The previous version didn't really test anything useful. Now we check that trying to instantiate any of the abstract classes fails with the expected error. --- .../test-suite/php/abstract_inherit_runme.php | 15 +++++++++++---- TODO | 4 ---- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/Examples/test-suite/php/abstract_inherit_runme.php b/Examples/test-suite/php/abstract_inherit_runme.php index 6a0180d78..376a2adaa 100644 --- a/Examples/test-suite/php/abstract_inherit_runme.php +++ b/Examples/test-suite/php/abstract_inherit_runme.php @@ -3,10 +3,17 @@ require "tests.php"; check::classes(array('Foo','Bar','Spam','NRFilter_i','NRRCFilter_i','NRRCFilterpro_i','NRRCFilterpri_i')); -// This constructor attempt should fail as there isn't one -//$spam=new Spam(); -//check::equal(0,$spam->blah(),"spam object method"); -//check::equal(0,Spam::blah($spam),"spam class method"); +// We shouldn't be able to instantiate any of these classes since they are all +// abstract (in each case there's a pure virtual function in the base class +// which isn't implemented). +foreach (array('Foo','Bar','Spam','NRFilter_i','NRRCFilter_i','NRRCFilterpro_i','NRRCFilterpri_i')as $class) { + try { + $obj = eval("new $class();"); + check::fail("Should not be able to instantiate abstract class $class"); + } catch (Error $e) { + check::equal($e->getMessage(), "Cannot instantiate abstract class $class", "Unexpected exception: {$e->getMessage()}"); + } +} check::done(); diff --git a/TODO b/TODO index 38ab4605d..d01168e5f 100644 --- a/TODO +++ b/TODO @@ -204,10 +204,6 @@ PHP mapping to the same object in case it gets twice destroyed. And check if ref count destroying is even working, see smart_pointer_rename -* Work out how classes without even inherited constructors should - interact with the php "new " notation. - See: abstract_inherit_wrap.cpptest - ** Look at pass by point and passby ref, Make sometype** to be auto allocated Make sometype& and sometype* to be autoallocated IF THEY ARE NOT From cc5395a669588f7c9b6347dfc65ed69e0f5221d0 Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Sat, 18 Dec 2021 14:38:49 +1300 Subject: [PATCH 058/662] [php] Add more checks to some PHP testcases --- .../php/abstract_inherit_ok_runme.php | 19 +++++++++++++++++-- .../test-suite/php/arrays_scope_runme.php | 4 ++++ Examples/test-suite/php/php_pragma_runme.php | 7 +++++++ 3 files changed, 28 insertions(+), 2 deletions(-) diff --git a/Examples/test-suite/php/abstract_inherit_ok_runme.php b/Examples/test-suite/php/abstract_inherit_ok_runme.php index 6cfea2341..add4191c2 100644 --- a/Examples/test-suite/php/abstract_inherit_ok_runme.php +++ b/Examples/test-suite/php/abstract_inherit_ok_runme.php @@ -2,9 +2,24 @@ require "tests.php"; -check::classes(array('Foo','Spam')); -$spam=new Spam(); +// No new functions +check::functions(array()); +check::classes(array('Foo','Spam')); + +// No new vars +check::globals(array()); + +// We shouldn't be able to instantiate abstract class Foo. +$class = 'Foo'; +try { + $obj = eval("new $class();"); + check::fail("Should not be able to instantiate abstract class $class"); +} catch (Error $e) { + check::equal($e->getMessage(), "Cannot instantiate abstract class $class", "Unexpected exception: {$e->getMessage()}"); +} + +$spam=new Spam(); check::equal(0,$spam->blah(),"spam object method"); check::done(); diff --git a/Examples/test-suite/php/arrays_scope_runme.php b/Examples/test-suite/php/arrays_scope_runme.php index f18037ca7..8455b837c 100644 --- a/Examples/test-suite/php/arrays_scope_runme.php +++ b/Examples/test-suite/php/arrays_scope_runme.php @@ -10,5 +10,9 @@ check::classes(array('arrays_scope','Bar')); check::globals(array()); $bar=new bar(); +$bar->blah($bar->adata, $bar->bdata, $bar->cdata); +// Like C/C++, SWIG treats `int asize[ASIZE]` as `int*` so there's no checking +// of the passed array size. +$bar->blah($bar->bdata, $bar->cdata, $bar->adata); check::done(); diff --git a/Examples/test-suite/php/php_pragma_runme.php b/Examples/test-suite/php/php_pragma_runme.php index e70f2ceda..cf297701d 100644 --- a/Examples/test-suite/php/php_pragma_runme.php +++ b/Examples/test-suite/php/php_pragma_runme.php @@ -2,6 +2,13 @@ require "tests.php"; +// No new functions +check::functions(array()); +// No new classes +check::classes(array()); +// No new vars +check::globals(array()); + check::equal('1.5',(new ReflectionExtension('php_pragma'))->getVersion(),"1.5==version(php_pragma)"); check::done(); From dee8b65823a9468288e37585ce9482a51bb98a13 Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Sat, 18 Dec 2021 14:41:06 +1300 Subject: [PATCH 059/662] [php] Always use Date: Sat, 18 Dec 2021 15:01:04 +1300 Subject: [PATCH 060/662] TODO: Remove stale PHP entry Ref count destroying has worked for years (and is explicitly tested by swig_exception_runme.php). --- TODO | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/TODO b/TODO index d01168e5f..1fcc992ac 100644 --- a/TODO +++ b/TODO @@ -201,8 +201,7 @@ PHP ** When returning wrapped objects via alternate constructors if that pointer value already exists "out there" as a resource we should use the same resource, we can't have multiple ref-counted resources - mapping to the same object in case it gets twice destroyed. And check - if ref count destroying is even working, see smart_pointer_rename + mapping to the same object in case it gets twice destroyed. ** Look at pass by point and passby ref, Make sometype** to be auto allocated From 7d75e3eb7e760846f8569ecea0e6a379029c9db6 Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Sat, 18 Dec 2021 15:30:38 +1300 Subject: [PATCH 061/662] [PHP] Add new PHP 8.1 keyword Add PHP keyword 'readonly' (added in 8.1) to the list SWIG knows to automatically rename. This keyword is special in that PHP allows it to be used as a function (or method) name. --- CHANGES.current | 5 +++++ Examples/test-suite/php_namewarn_rename.i | 14 ++++++++++++++ Lib/php/phpkw.swg | 9 +++++++++ 3 files changed, 28 insertions(+) diff --git a/CHANGES.current b/CHANGES.current index cadbbadfb..fc56246c6 100644 --- a/CHANGES.current +++ b/CHANGES.current @@ -7,6 +7,11 @@ the issue number to the end of the URL: https://github.com/swig/swig/issues/ Version 4.1.0 (in progress) =========================== +2021-12-18: olly + [PHP] Add PHP keyword 'readonly' (added in 8.1) to the list SWIG + knows to automatically rename. This keyword is special in that PHP + allows it to be used as a function (or method) name. + 2021-12-05: rwf1 [Octave] #2020 #1893 Add support for Octave 6 up to and including 6.4. Also add support for compiling with -Bsymbolic which is used by default diff --git a/Examples/test-suite/php_namewarn_rename.i b/Examples/test-suite/php_namewarn_rename.i index bb54dba5e..d70cad770 100644 --- a/Examples/test-suite/php_namewarn_rename.i +++ b/Examples/test-suite/php_namewarn_rename.i @@ -8,6 +8,7 @@ %warnfilter(SWIGWARN_PARSE_KEYWORD) null; %warnfilter(SWIGWARN_PARSE_KEYWORD) True; %warnfilter(SWIGWARN_PARSE_KEYWORD) FALSE; +%warnfilter(SWIGWARN_PARSE_KEYWORD) ns::readonly; #endif %ignore prev::operator++; @@ -50,4 +51,17 @@ class FALSE { }; + + // PHP 8.1 made `readonly` a keyword, but (unlike any other keyword it seems) + // it may still be used as a function name. + namespace ns { + class readonly { }; + } + + class readonly_should_be_ok_as_method { + public: + bool readonly() const { return true; } + }; + + bool readonly() { return false; } %} diff --git a/Lib/php/phpkw.swg b/Lib/php/phpkw.swg index e431fc2e4..b6855ce9a 100644 --- a/Lib/php/phpkw.swg +++ b/Lib/php/phpkw.swg @@ -5,6 +5,9 @@ /* Keyword (case insensitive) */ #define PHPKW(x) %keywordwarn("'" `x` "' is a PHP keyword, renaming to 'c_" `x` "'",sourcefmt="%(lower)s",rename="c_%s") `x` +/* Keyword, except ok as a function */ +#define PHPKW_ok_as_function(x) %keywordwarn("'" `x` "' is a PHP keyword, renaming to 'c_" `x` "'",%$not %$isfunction,sourcefmt="%(lower)s",rename="c_%s") `x` + /* Class (case insensitive) */ #define PHPCN(x) %keywordwarn("'" `x` "' is a PHP reserved class name, renaming to 'c_" `x` "'",%$isclass,sourcefmt="%(lower)s",rename="c_%s") `x` @@ -84,6 +87,11 @@ PHPKW(while); PHPKW(xor); PHPKW(yield); +/* PHP 8.1 made `readonly` a keyword, but (unlike any other keyword it seems) + * it may still be used as a function name. + */ +PHPKW_ok_as_function(readonly); + // Compile-time "magic" constants // From: http://php.net/manual/en/reserved.keywords.php // also at: http://php.net/manual/en/language.constants.predefined.php @@ -869,6 +877,7 @@ PHPFN(unset); // "Language construct" PHPFN(usort); #undef PHPKW +#undef PHPKW_ok_as_function #undef PHPBN1a #undef PHPBN1b #undef PHPBN1 From a7f2c3d19b898d9c1d6e836164cb69df567aa7ff Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Sat, 18 Dec 2021 18:45:52 +1300 Subject: [PATCH 062/662] [php] Add overload_simple_runme.php --- .../test-suite/php/overload_simple_runme.php | 194 ++++++++++++++++++ 1 file changed, 194 insertions(+) create mode 100644 Examples/test-suite/php/overload_simple_runme.php diff --git a/Examples/test-suite/php/overload_simple_runme.php b/Examples/test-suite/php/overload_simple_runme.php new file mode 100644 index 000000000..3cba1d35b --- /dev/null +++ b/Examples/test-suite/php/overload_simple_runme.php @@ -0,0 +1,194 @@ +foo(3), "foo:int", "Spam::foo:int"); + +check::equal($s->foo(3.0), "foo:double", "Spam::foo(double)"); + +check::equal($s->foo("hello"), "foo:char *", "Spam::foo:char *"); + +check::equal($s->foo($f), "foo:Foo *", "Spam::foo(Foo *)"); + +check::equal($s->foo($b), "foo:Bar *", "Spam::foo(Bar *)"); + +check::equal($s->foo($v), "foo:void *", "Spam::foo(void *)"); + +check::equal(Spam::bar(3), "bar:int", "Spam::bar(int)"); + +check::equal(Spam::bar(3.0), "bar:double", "Spam::bar(double)"); + +check::equal(Spam::bar("hello"), "bar:char *", "Spam::bar(char *)"); + +check::equal(Spam::bar($f), "bar:Foo *", "Spam::bar(Foo *)"); + +check::equal(Spam::bar($b), "bar:Bar *", "Spam::bar(Bar *)"); + +check::equal(Spam::bar($v), "bar:void *", "Spam::bar(void *)"); + +# Test constructors + +$s = new Spam(); +check::is_a($s, "spam"); + +check::equal($s->type, "none", "Spam()"); + +$s = new Spam(3); +check::is_a($s, "spam"); + +check::equal($s->type, "int", "Spam(int)"); + +$s = new Spam(3.0); +check::is_a($s, "spam"); +check::equal($s->type, "double", "Spam(double)"); + +$s = new Spam("hello"); +check::is_a($s, "spam"); +check::equal($s->type, "char *", "Spam(char *)"); + +$s = new Spam($f); +check::is_a($s, "spam"); +check::equal($s->type, "Foo *", "Spam(Foo *)"); + +$s = new Spam($b); +check::is_a($s, "spam"); +check::equal($s->type, "Bar *", "Spam(Bar *)"); + +$s = new Spam($v); +check::is_a($s, "spam"); +check::equal($s->type, "void *", "Spam(void *)"); + +# +# Combine dispatch +# + +check::equal(overload_simple::fid(3, 3.0), "fid:intdouble", "fid(int,double)"); + +check::equal(overload_simple::fid(3.0, 3), "fid:doubleint", "fid(double,int)"); + +check::equal(overload_simple::fid(3.0, 3.0), "fid:doubledouble", "fid(double,double)"); + +check::equal(overload_simple::fid(3, 3), "fid:intint", "fid(int,int)"); + +check::equal(false, overload_simple::fbool(false), "fbool(bool)"); +check::equal(true, overload_simple::fbool(true), "fbool(bool)"); +check::equal(2, overload_simple::fbool(2), "fbool(int)"); + +# int and object overload + +check::equal(overload_simple::int_object(1), 1, "int_object(1)"); +check::equal(overload_simple::int_object(0), 0, "int_object(0)"); +check::equal(overload_simple::int_object(NULL), 999, "int_object(Spam*)"); +check::equal(overload_simple::int_object($s), 999, "int_object(Spam*)"); + +function check($args, $want) { + if ($want === NULL) { + try { + eval("return Spam::bar($args);"); + check::fail("Expected exception"); + } catch (TypeError $e) { + check::equal(substr($e->getMessage(), 0, 35), "No matching function for overloaded", "Not the expected I expected"); + } + return; + } + check::equal(eval("return Spam::bar($args);"), "bar:$want", "bar($args) => $want"); +} + +# normal use patterns +check("11", 'int'); +check("11.0", 'double'); +check("'11'", 'char *'); +check("'11.0'", 'char *'); +check("-13", 'int'); +check("-13.0", 'double'); +check("'-13'", 'char *'); +check("'-13.0'", 'char *'); + +check("' '", 'char *'); +check("' 11 '", 'char *'); + +# Check TypeError is thrown when the wrong type is passed. +check("array()", NULL); +# FIXME: These need fixing +#check("function(){}", NULL); +#check("new stdClass()", NULL); + +check::done(); From 69b580dfb6e39b5463213908b443a86265bdb23c Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Sun, 19 Dec 2021 13:03:48 +1300 Subject: [PATCH 063/662] [php] Use SWIG_TypeCheckStruct to check types We have the swig_type_info available and SWIG_TypeCheckStruct is more efficient because it uses a pointer comparison instead of the string comparison SWIG_TypeCheck uses (this change speeds up `make check-php-test-suite` by about 10%). --- Lib/php/phprun.swg | 54 +++++++++++++++------------------------------- Lib/swigrun.swg | 2 +- 2 files changed, 18 insertions(+), 38 deletions(-) diff --git a/Lib/php/phprun.swg b/Lib/php/phprun.swg index 426efe104..69b00bc4b 100644 --- a/Lib/php/phprun.swg +++ b/Lib/php/phprun.swg @@ -122,42 +122,6 @@ SWIG_SetPointerZval(zval *z, void *ptr, swig_type_info *type, int newobject) { } } -/* This pointer conversion routine takes the native pointer p (along with - its type name) and converts it by calling appropriate casting functions - according to ty. The resultant pointer is returned, or NULL is returned - if the pointer can't be cast. - - This is called by SWIG_ConvertPtr which gets the type name from the - swig_object_wrapper. */ -static void * -SWIG_ConvertPtrData(void * p, const char *type_name, swig_type_info *ty, int *own) { - swig_cast_info *tc; - void *result = 0; - - if (!ty) { - /* They don't care about the target type, so just pass on the pointer! */ - return p; - } - - if (! type_name) { - /* can't convert p to ptr type ty if we don't know what type p is */ - return NULL; - } - - /* convert and cast p from type_name to ptr as ty. */ - tc = SWIG_TypeCheck(type_name, ty); - if (tc) { - int newmemory = 0; - result = SWIG_TypeCast(tc, p, &newmemory); - if (newmemory == SWIG_CAST_NEW_MEMORY) { - assert(own); /* badly formed typemap which will lead to a memory leak - it must set and use own to delete *ptr */ - if (own) - *own |= SWIG_CAST_NEW_MEMORY; - } - } - return result; -} - /* We wrap C/C++ pointers as PHP objects. */ static int SWIG_ConvertPtrAndOwn(zval *z, void **ptr, swig_type_info *ty, int flags, swig_owntype *own) { @@ -172,7 +136,23 @@ SWIG_ConvertPtrAndOwn(zval *z, void **ptr, swig_type_info *ty, int flags, swig_o switch (Z_TYPE_P(z)) { case IS_OBJECT: { swig_object_wrapper *value = SWIG_Z_FETCH_OBJ_P(z); - *ptr = SWIG_ConvertPtrData(value->ptr, value->type->name, ty, own); + if (!ty) { + /* They don't care about the target type, so just pass on the pointer! */ + *ptr = value->ptr; + } else { + swig_cast_info *tc = SWIG_TypeCheckStruct(value->type, ty); + if (tc) { + int newmemory = 0; + *ptr = SWIG_TypeCast(tc, value->ptr, &newmemory); + if (newmemory == SWIG_CAST_NEW_MEMORY) { + assert(own); /* badly formed typemap which will lead to a memory leak - it must set and use own to delete *ptr */ + if (own) + *own |= SWIG_CAST_NEW_MEMORY; + } + } else { + *ptr = NULL; + } + } if (*ptr == NULL) return SWIG_ERROR; if (flags & SWIG_POINTER_DISOWN) { value->newobject = 0; diff --git a/Lib/swigrun.swg b/Lib/swigrun.swg index 5f3159916..de0db2dc3 100644 --- a/Lib/swigrun.swg +++ b/Lib/swigrun.swg @@ -290,7 +290,7 @@ SWIG_TypeCheck(const char *c, swig_type_info *ty) { Identical to SWIG_TypeCheck, except strcmp is replaced with a pointer comparison */ SWIGRUNTIME swig_cast_info * -SWIG_TypeCheckStruct(swig_type_info *from, swig_type_info *ty) { +SWIG_TypeCheckStruct(const swig_type_info *from, swig_type_info *ty) { if (ty) { swig_cast_info *iter = ty->cast; while (iter) { From 7a9bf3307f9436c0f48eecd155c721c86a0f4058 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Tue, 21 Dec 2021 22:36:01 +0000 Subject: [PATCH 064/662] Remove C++ comments from preproc C test Closes issue #2127 --- Examples/test-suite/preproc.i | 77 +++++++++++++++++------------------ 1 file changed, 38 insertions(+), 39 deletions(-) diff --git a/Examples/test-suite/preproc.i b/Examples/test-suite/preproc.i index 1bcdcf7ac..04398b25a 100644 --- a/Examples/test-suite/preproc.i +++ b/Examples/test-suite/preproc.i @@ -13,11 +13,11 @@ %{ #if defined(__clang__) -//Suppress: warning: use of logical '&&' with constant operand [-Wconstant-logical-operand] +/*Suppress: warning: use of logical '&&' with constant operand [-Wconstant-logical-operand]*/ #pragma clang diagnostic ignored "-Wconstant-logical-operand" #endif #if defined(_MSC_VER) - #pragma warning(disable: 4003) // not enough actual parameters for macro 'FOO2' + #pragma warning(disable: 4003) /* not enough actual parameters for macro 'FOO2' */ #endif %} @@ -72,14 +72,14 @@ extern "C" TYPEMAP_LIST_VECTOR_INPUT_OUTPUT(boolean) -// preproc_3 +/* preproc_3 */ #define Sum( A, B, \ C) \ A + B + C -// preproc_4 +/* preproc_4 */ %{ int hello0() { @@ -102,33 +102,30 @@ TYPEMAP_LIST_VECTOR_INPUT_OUTPUT(boolean) #define HELLO_TYPE(A, B) ARITH_RTYPE(A, ARITH_RTYPE(A,B)) -// -// These two work fine -// int hello0(); ARITH_RTYPE(double,int) hello1(); -// -// This doesn't work with 1.3.17+ ( but it was ok in 1.3.16 ) -// it gets expanded as (using -E) -// -// ARITH_RTYPE(double,int) hello2(); -// +/* + This doesn't work with 1.3.17+ ( but it was ok in 1.3.16 ) + it gets expanded as (using -E) + + ARITH_RTYPE(double,int) hello2(); +*/ HELLO_TYPE(double,int) hello2(); #define min(x,y) ((x) < (y)) ? (x) : (y) int f(int min); -// preproc_5 +/* preproc_5 */ -%warnfilter(SWIGWARN_PARSE_REDEFINED) A5; // Ruby, wrong constant name -%warnfilter(SWIGWARN_RUBY_WRONG_NAME) a5; // Ruby, wrong constant name -%warnfilter(SWIGWARN_RUBY_WRONG_NAME) b5; // Ruby, wrong constant name -%warnfilter(SWIGWARN_RUBY_WRONG_NAME) c5; // Ruby, wrong constant name -%warnfilter(SWIGWARN_RUBY_WRONG_NAME) d5; // Ruby, wrong constant name +%warnfilter(SWIGWARN_PARSE_REDEFINED) A5; /* Ruby, wrong constant name */ +%warnfilter(SWIGWARN_RUBY_WRONG_NAME) a5; /* Ruby, wrong constant name */ +%warnfilter(SWIGWARN_RUBY_WRONG_NAME) b5; /* Ruby, wrong constant name */ +%warnfilter(SWIGWARN_RUBY_WRONG_NAME) c5; /* Ruby, wrong constant name */ +%warnfilter(SWIGWARN_RUBY_WRONG_NAME) d5; /* Ruby, wrong constant name */ -// Various preprocessor bits of nastiness. +/* Various preprocessor bits of nastiness. */ /* Test argument name substitution */ @@ -138,7 +135,7 @@ int f(int min); %constant char *a5 = foo(hello,world); %constant int b5 = bar(3,4); -// Wrap your brain around this one ;-) +/* Wrap your brain around this one ;-) */ %{ #define cat(x,y) x ## y @@ -168,7 +165,7 @@ NAME 42 #define C4"Hello" -// preproc_6 +/* preproc_6 */ %warnfilter(SWIGWARN_PARSE_REDEFINED) A6; /* Ruby, wrong constant name */ %warnfilter(SWIGWARN_RUBY_WRONG_NAME) a6; /* Ruby, wrong constant name */ @@ -206,7 +203,7 @@ NAME 42 MACRO2(int) -// cpp_macro_noarg. Tests to make sure macros with no arguments work right. +/* cpp_macro_noarg. Tests to make sure macros with no arguments work right. */ #define MACROWITHARG(x) something(x) typedef int MACROWITHARG; @@ -373,8 +370,10 @@ int methodX(int x); int methodX(int x) { return x+100; } %} -// Comma in macro - https://github.com/swig/swig/issues/974 (for /* */) -// and https://github.com/swig/swig/pull/1166 (for //) +/* + Comma in macro - https://github.com/swig/swig/issues/974 (for C comments) + and https://github.com/swig/swig/pull/1166 (for //) +*/ %inline %{ #define swig__attribute__(x) #define TCX_PACKED(d) d swig__attribute__ ((__packed__)) @@ -394,19 +393,19 @@ TCX_PACKED (typedef struct tcxMessageBugImpl TCX_PACKED (typedef struct tcxMessageTestImpl2 { - int mHeader; ///< comment + int mHeader; /**< comment */ }) tcxMessageTest2; TCX_PACKED (typedef struct tcxMessageBugImpl2 { - int mBid; ///< Bid price and size, check PresentMap if available in message + int mBid; /**< Bid price and size, check PresentMap if available in message */ }) tcxMessageBug2; %} -// Regression tests for https://github.com/swig/swig/pull/1111 +/* Regression tests for https://github.com/swig/swig/pull/1111 */ %{ static int foo_func(int x) { return x; } static int foo_func2() { return 0; } @@ -422,22 +421,22 @@ static int baz_func(int a, int b, int c) { return a + b - c; } #define FOOVAR(...) foo_func(__VA_ARGS__) #define BARVAR(...) bar_func(__VA_ARGS__) #define BAZVAR(...) baz_func(__VA_ARGS__) -// This has probably always worked, but make sure that the fix to accept -// an empty X doesn't cause this case to be incorrectly expanded: +/* This has probably always worked, but make sure that the fix to accept + an empty X doesn't cause this case to be incorrectly expanded:*/ const int FOO = 7; -// BAR was incorrectly expanded here, causing: -// Error: Syntax error in input(1). +/* BAR was incorrectly expanded here, causing: + Error: Syntax error in input(1). */ const int BAR = 6; -// This has probably always worked, but make sure that the fix to accept -// an empty X doesn't stop a non-empty X from working: +/* This has probably always worked, but make sure that the fix to accept + an empty X doesn't stop a non-empty X from working: */ FOO(int x) -// FOO() didn't used to get expanded here, causing: -// Syntax error in input(1). +/* FOO() didn't used to get expanded here, causing: + Syntax error in input(1). */ FOO2() -// Check BAR2() still gets expanded here. +/* Check BAR2() still gets expanded here. */ BAR2() { - // Regression test - this used to fail with: - // Error: Macro 'BAZ' expects 3 arguments + /* Regression test - this used to fail with: + Error: Macro 'BAZ' expects 3 arguments */ BAZ(,2,3); BARVAR(); FOOVAR(1); From 1b22fef8ad531c768b10353bbb8e625c23d85b5c Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Wed, 22 Dec 2021 12:18:40 +1300 Subject: [PATCH 065/662] [php] Add missing runmes for overload_* testcases --- .../test-suite/php/overload_bool_runme.php | 42 +++++++ .../php/overload_complicated_runme.php | 39 +++++++ .../test-suite/php/overload_copy_runme.php | 13 +++ .../test-suite/php/overload_extend2_runme.php | 16 +++ .../php/overload_extend_c_runme.php | 11 ++ .../test-suite/php/overload_extend_runme.php | 11 ++ .../test-suite/php/overload_subtype_runme.php | 11 ++ .../php/overload_template_fast_runme.php | 110 ++++++++++++++++++ .../php/overload_template_runme.php | 110 ++++++++++++++++++ 9 files changed, 363 insertions(+) create mode 100644 Examples/test-suite/php/overload_bool_runme.php create mode 100644 Examples/test-suite/php/overload_complicated_runme.php create mode 100644 Examples/test-suite/php/overload_copy_runme.php create mode 100644 Examples/test-suite/php/overload_extend2_runme.php create mode 100644 Examples/test-suite/php/overload_extend_c_runme.php create mode 100644 Examples/test-suite/php/overload_extend_runme.php create mode 100644 Examples/test-suite/php/overload_subtype_runme.php create mode 100644 Examples/test-suite/php/overload_template_fast_runme.php create mode 100644 Examples/test-suite/php/overload_template_runme.php diff --git a/Examples/test-suite/php/overload_bool_runme.php b/Examples/test-suite/php/overload_bool_runme.php new file mode 100644 index 000000000..e477330ef --- /dev/null +++ b/Examples/test-suite/php/overload_bool_runme.php @@ -0,0 +1,42 @@ +hip(false), 701, "Test 1 failed"); + +check::equal($p->hip($pInt), 702, "Test 2 failed"); + +# Reverse the order for the above +check::equal($p->hop($pInt), 805, "Test 3 failed"); + +check::equal($p->hop(false), 801, "Test 4 failed"); + +# Few more variations and order shuffled +check::equal($p->pop(false), 901, "Test 5 failed"); + +check::equal($p->pop($pInt), 904, "Test 6 failed"); + +check::equal($p->pop(), 905, "Test 7 failed"); + +# Overload on const only +check::equal($p->bop($pInt), 1001, "Test 8 failed"); + +check::equal($p->bip($pInt), 2002, "Test 9 failed"); + +# Globals +check::equal(muzak(false), 3001, "Test 10 failed"); + +check::equal(muzak($pInt), 3002, "Test 11 failed"); + +check::done(); diff --git a/Examples/test-suite/php/overload_copy_runme.php b/Examples/test-suite/php/overload_copy_runme.php new file mode 100644 index 000000000..893a715c5 --- /dev/null +++ b/Examples/test-suite/php/overload_copy_runme.php @@ -0,0 +1,13 @@ +test(3), 1, '$f->test(3)'); +check::equal($f->test("hello"), 2, '$f->test("hello")'); +check::equal($f->test(3.5, 2.5), 3, '$f->test(3.5, 2.5)'); +check::equal($f->test("hello", 20), 1020, '$f->test("hello", 20)'); +check::equal($f->test("hello", 20, 100), 120, '$f->test("hello", 20, 100)'); + +// C default args +check::equal($f->test($f), 30, '$f->test(f)'); +check::equal($f->test($f, 100), 120, '$f->test(f, 100)'); +check::equal($f->test($f, 100, 200), 300, '$f->test(f, 100, 200)'); + +check::done(); diff --git a/Examples/test-suite/php/overload_extend_c_runme.php b/Examples/test-suite/php/overload_extend_c_runme.php new file mode 100644 index 000000000..55f426c13 --- /dev/null +++ b/Examples/test-suite/php/overload_extend_c_runme.php @@ -0,0 +1,11 @@ +test(), 0, '$f->test()'); +check::equal($f->test(3), 1, '$f->test(3)'); +check::equal($f->test("hello"), 2, '$f->test("hello")'); +check::equal($f->test(3.0, 2.0), 5.0, '$f->test(3, 2)'); +check::equal($f->test(3.0), 1003.0, '$f->test(3.0)'); + +check::done(); diff --git a/Examples/test-suite/php/overload_extend_runme.php b/Examples/test-suite/php/overload_extend_runme.php new file mode 100644 index 000000000..89c0499eb --- /dev/null +++ b/Examples/test-suite/php/overload_extend_runme.php @@ -0,0 +1,11 @@ +test(), 0, '$f->test()'); +check::equal($f->test(3), 1, '$f->test(3)'); +check::equal($f->test("hello"), 2, '$f->test("hello")'); +check::equal($f->test(3.0, 2.0), 5.0, '$f->test(3.0, 2.0)'); +check::equal($f->test(3.0), 1003.0, '$f->test(3.0)'); + +check::done(); diff --git a/Examples/test-suite/php/overload_subtype_runme.php b/Examples/test-suite/php/overload_subtype_runme.php new file mode 100644 index 000000000..f12025cf8 --- /dev/null +++ b/Examples/test-suite/php/overload_subtype_runme.php @@ -0,0 +1,11 @@ +foo(1); + + +check::done(); diff --git a/Examples/test-suite/php/overload_template_runme.php b/Examples/test-suite/php/overload_template_runme.php new file mode 100644 index 000000000..7aa19f693 --- /dev/null +++ b/Examples/test-suite/php/overload_template_runme.php @@ -0,0 +1,110 @@ +foo(1); + + +check::done(); From 2d76057571a77609060d6c6c05f151ec608aa58d Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Wed, 22 Dec 2021 19:06:00 +0000 Subject: [PATCH 066/662] preproc_cpp test for testing preprocessor and C++ Move C++ comment testing into here. See 7a9bf3307f9436c0f48eecd155c721c86a0f4058. --- Examples/test-suite/preproc.i | 1 + Examples/test-suite/preproc_cpp.i | 36 +++++++++++++++++++ .../test-suite/python/preproc_cpp_runme.py | 4 +++ 3 files changed, 41 insertions(+) create mode 100644 Examples/test-suite/preproc_cpp.i create mode 100644 Examples/test-suite/python/preproc_cpp_runme.py diff --git a/Examples/test-suite/preproc.i b/Examples/test-suite/preproc.i index 04398b25a..feff7b489 100644 --- a/Examples/test-suite/preproc.i +++ b/Examples/test-suite/preproc.i @@ -373,6 +373,7 @@ int methodX(int x) { return x+100; } /* Comma in macro - https://github.com/swig/swig/issues/974 (for C comments) and https://github.com/swig/swig/pull/1166 (for //) + Also see preproc_cpp.i */ %inline %{ #define swig__attribute__(x) diff --git a/Examples/test-suite/preproc_cpp.i b/Examples/test-suite/preproc_cpp.i new file mode 100644 index 000000000..c81f9a74f --- /dev/null +++ b/Examples/test-suite/preproc_cpp.i @@ -0,0 +1,36 @@ +%module preproc_cpp + + +// Comma in macro - https://github.com/swig/swig/issues/974 (for /* */) +// and https://github.com/swig/swig/pull/1166 (for //) +// Also see preproc.i +%inline %{ +#define swig__attribute__(x) +#define TCX_PACKED(d) d swig__attribute__ ((__packed__)) + + +TCX_PACKED (typedef struct tcxMessageTestImpl +{ + int mHeader; /**< comment */ +}) tcxMessageTest; + + +TCX_PACKED (typedef struct tcxMessageBugImpl +{ + int mBid; /**< Bid price and size, check PresentMap if available in message */ +}) tcxMessageBug; + + +TCX_PACKED (typedef struct tcxMessageTestImpl2 +{ + int mHeader; ///< comment +}) tcxMessageTest2; + + +TCX_PACKED (typedef struct tcxMessageBugImpl2 +{ + int mBid; ///< Bid price and size, check PresentMap if available in message +}) tcxMessageBug2; + + +%} diff --git a/Examples/test-suite/python/preproc_cpp_runme.py b/Examples/test-suite/python/preproc_cpp_runme.py new file mode 100644 index 000000000..8c3e21237 --- /dev/null +++ b/Examples/test-suite/python/preproc_cpp_runme.py @@ -0,0 +1,4 @@ +import preproc_cpp + +t1 = preproc_cpp.tcxMessageTest() +t2 = preproc_cpp.tcxMessageBug() From 860731e0ead11c370834eca032fbbce3607057a3 Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Thu, 23 Dec 2021 11:55:47 +1300 Subject: [PATCH 067/662] Remove redundant test cases With C++ comments changed to C comments, these are now identical to the two cases just above, aside from the `2` suffix on the names. Follow-on for #2027. --- Examples/test-suite/preproc.i | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/Examples/test-suite/preproc.i b/Examples/test-suite/preproc.i index feff7b489..a69973f13 100644 --- a/Examples/test-suite/preproc.i +++ b/Examples/test-suite/preproc.i @@ -392,18 +392,6 @@ TCX_PACKED (typedef struct tcxMessageBugImpl }) tcxMessageBug; -TCX_PACKED (typedef struct tcxMessageTestImpl2 -{ - int mHeader; /**< comment */ -}) tcxMessageTest2; - - -TCX_PACKED (typedef struct tcxMessageBugImpl2 -{ - int mBid; /**< Bid price and size, check PresentMap if available in message */ -}) tcxMessageBug2; - - %} /* Regression tests for https://github.com/swig/swig/pull/1111 */ From 9f87d81faec219baf2e2ca2da1bb2b4812958ae8 Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Thu, 23 Dec 2021 16:18:07 +1300 Subject: [PATCH 068/662] Clean up testcase source whitespace --- Examples/test-suite/li_factory.i | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/Examples/test-suite/li_factory.i b/Examples/test-suite/li_factory.i index 7c59d53b2..233c9c36b 100644 --- a/Examples/test-suite/li_factory.i +++ b/Examples/test-suite/li_factory.i @@ -18,32 +18,30 @@ POINT, CIRCLE }; - - virtual ~Geometry() {} + + virtual ~Geometry() {} virtual int draw() = 0; static Geometry *create(GeomType i); - virtual Geometry *clone() = 0; + virtual Geometry *clone() = 0; }; struct Point : Geometry { int draw() { return 1; } - double width() { return 1.0; } - Geometry *clone() { return new Point(); } + double width() { return 1.0; } + Geometry *clone() { return new Point(); } }; struct Circle : Geometry { int draw() { return 2; } - double radius() { return 1.5; } - Geometry *clone() { return new Circle(); } - }; + double radius() { return 1.5; } + Geometry *clone() { return new Circle(); } + }; Geometry *Geometry::create(GeomType type) { switch (type) { case POINT: return new Point(); - case CIRCLE: return new Circle(); + case CIRCLE: return new Circle(); default: return 0; } } } - - From c42e8970a4d51198472f6dcf196c5c0916aab033 Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Fri, 24 Dec 2021 15:53:00 +1300 Subject: [PATCH 069/662] [php] Improve wording in the manual --- Doc/Manual/Php.html | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/Doc/Manual/Php.html b/Doc/Manual/Php.html index ed2587f1b..7c970d169 100644 --- a/Doc/Manual/Php.html +++ b/Doc/Manual/Php.html @@ -50,18 +50,21 @@

    -In this chapter, we discuss SWIG's support of PHP. SWIG currently supports -generating wrappers for PHP7 and PHP8. Support for PHP5 was removed in SWIG -4.0.0 and support for PHP4 was removed in SWIG 1.3.37. +In this chapter, we discuss SWIG's support of PHP. Currently any PHP7 or PHP8 +release should work.

    -Currently any PHP7 or PHP8 release should work. +Support for PHP7 was added in SWIG 3.0.11 and for PHP8 in 4.1.0. +Support for PHP5 was removed in SWIG 4.0.0 and support for PHP4 was removed in +SWIG 1.3.37. There never was a PHP6 release. +

    +

    In order to use this module, you will need to have a copy of the PHP -include files to compile the SWIG generated files. If you installed +include files to compile the SWIG generated C/C++ sources. If you installed PHP from a binary package, you may need to install a "php-dev" or "php-devel" package for these to be installed. You can find out where these files are by running php-config --includes. To use the built PHP module you From fa36d6fd289f9294489c6bcfcfe6069562ea8474 Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Fri, 24 Dec 2021 16:43:25 +1300 Subject: [PATCH 070/662] [python] Add 3.10 to Python versions in configure --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index e5730cbf0..8073bfdb3 100644 --- a/configure.ac +++ b/configure.ac @@ -812,7 +812,7 @@ else if test x"$PYOSNAME" = x"nt" -a x"$PYSEPARATOR" = x"\\" -a $PYVER -ge 3; then PYTHON3="$PYTHON" else - for py_ver in 3 3.9 3.8 3.7 3.6 3.5 3.4 3.3 3.2 ""; do + for py_ver in 3 3.10 3.9 3.8 3.7 3.6 3.5 3.4 3.3 3.2 ""; do AC_CHECK_PROGS(PYTHON3, [python$py_ver]) if test -n "$PYTHON3"; then AC_CHECK_PROGS(PY3CONFIG, [$PYTHON3-config]) From 9e95f7f996c616a931253c0ab795f00feb499f0a Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Wed, 29 Dec 2021 15:48:40 +1300 Subject: [PATCH 071/662] [php] Add director_ownership_runme.php This serves as a regression test for https://sourceforge.net/p/swig/bugs/1339/ which was presumably fixed by the change to use PHP's C API to wrap classes. --- .../php/director_ownership_runme.php | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 Examples/test-suite/php/director_ownership_runme.php diff --git a/Examples/test-suite/php/director_ownership_runme.php b/Examples/test-suite/php/director_ownership_runme.php new file mode 100644 index 000000000..a78fb9c03 --- /dev/null +++ b/Examples/test-suite/php/director_ownership_runme.php @@ -0,0 +1,28 @@ +thisown = false; + $container->set_content($content); +} + +$container = new Container(); + +// make a content in PHP (newobject is 1) +$content_php = new ContentDerived(); + +// make a content in C++ (newobject is 1) +$content_cpp = make_content(); + +set_content_and_release($container, $content_php); +check::equal($container->get_content()->get_name(), "ContentDerived", "get_content() not ContentDerived"); + +set_content_and_release($container, $content_cpp); +check::equal($container->get_content()->get_name(), "ContentDerived", "get_content() not ContentDerived"); + +check::done(); From 130813b32042da76bafafc37ed3695fcdf02c871 Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Wed, 29 Dec 2021 19:15:08 +1300 Subject: [PATCH 072/662] Escape a literal > in PHP.html --- Doc/Manual/Php.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Doc/Manual/Php.html b/Doc/Manual/Php.html index 7c970d169..8f8ab39c4 100644 --- a/Doc/Manual/Php.html +++ b/Doc/Manual/Php.html @@ -1162,7 +1162,7 @@ should suffice in most cases:

    -If you only need to support SWIG >= 4.1.0, you can just use the +If you only need to support SWIG >= 4.1.0, you can just use the ($error != NULL) condition.

    From 48eba82ac8847f8422710fac677875baf88566df Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Wed, 29 Dec 2021 19:16:36 +1300 Subject: [PATCH 073/662] Remove obsolete code to set SWIG_V8_VERSION We've dropped support for the old V8 versions which lacked version macros, and SWIG_V8_VERSION now gets automatically defined by Lib/javascript/v8/javascriptruntime.swg which will #undef it first if it's already defined. --- Tools/javascript/Makefile.in | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/Tools/javascript/Makefile.in b/Tools/javascript/Makefile.in index 5eeec0785..6335d0a65 100644 --- a/Tools/javascript/Makefile.in +++ b/Tools/javascript/Makefile.in @@ -32,12 +32,6 @@ JSCENABLED = @JSCENABLED@ srcdir = @srcdir@ -ifneq (, $(V8_VERSION)) - JSV8_VERSION=$(V8_VERSION) -else - JSV8_VERSION=0x031110 -endif - # Regenerate Makefile if Makefile.in or config.status have changed. Makefile: $(srcdir)/Makefile.in ../../config.status cd ../.. && $(SHELL) ./config.status Tools/javascript/Makefile @@ -45,7 +39,7 @@ Makefile: $(srcdir)/Makefile.in ../../config.status # These settings are provided by 'configure' (see '/configure.in') ifeq (1, $(JSV8ENABLED)) JS_INTERPRETER_SRC_V8 = v8_shell.cxx -JS_INTERPRETER_ENABLE_V8 = -DENABLE_V8 -DSWIG_V8_VERSION=$(JSV8_VERSION) -DV8_DEPRECATION_WARNINGS +JS_INTERPRETER_ENABLE_V8 = -DENABLE_V8 -DV8_DEPRECATION_WARNINGS endif ifeq (1, $(JSCENABLED)) From d73f933c4bb5ca1f327870554f75a87372964162 Mon Sep 17 00:00:00 2001 From: ERROR Date: Tue, 4 Jan 2022 06:12:56 +0700 Subject: [PATCH 074/662] Support std::array in Golang (#2045) Support std::array in Golang Closes #2045 --- Examples/test-suite/cpp11_std_array.i | 2 +- .../test-suite/go/cpp11_std_array_runme.go | 68 +++++++++++++++++++ Lib/go/std_array.i | 43 ++++++++++++ 3 files changed, 112 insertions(+), 1 deletion(-) create mode 100644 Examples/test-suite/go/cpp11_std_array_runme.go create mode 100644 Lib/go/std_array.i diff --git a/Examples/test-suite/cpp11_std_array.i b/Examples/test-suite/cpp11_std_array.i index 3d4771551..9dc11ce9e 100644 --- a/Examples/test-suite/cpp11_std_array.i +++ b/Examples/test-suite/cpp11_std_array.i @@ -1,6 +1,6 @@ %module cpp11_std_array -#if defined(SWIGPYTHON) || defined(SWIGRUBY) || defined(SWIGJAVA) || defined(SWIGCSHARP) +#if defined(SWIGPYTHON) || defined(SWIGRUBY) || defined(SWIGJAVA) || defined(SWIGCSHARP) || defined(SWIGGO) %{ #include diff --git a/Examples/test-suite/go/cpp11_std_array_runme.go b/Examples/test-suite/go/cpp11_std_array_runme.go new file mode 100644 index 000000000..97b5df2ec --- /dev/null +++ b/Examples/test-suite/go/cpp11_std_array_runme.go @@ -0,0 +1,68 @@ +package main + +import ( + "fmt" + "swigtests/cpp11_std_array" +) + +func CompareContainers(actual cpp11_std_array.ArrayInt6, expected [6]int) error { + if int(actual.Size()) != len(expected) { + return fmt.Errorf("Sizes are different: %d %d", actual.Size(), len(expected)) + } + for i := 0; i < int(actual.Size()); i++ { + actualValue := actual.Get(i) + expectedValue := expected[i] + if actualValue != expectedValue { + return fmt.Errorf("Value is wrong for element %d. Expected %d got: %d", i, expectedValue, actualValue) + } + } + if actual.IsEmpty() { + return fmt.Errorf("ai should not be empty") + } + return nil +} + +func main() { + ai := cpp11_std_array.NewArrayInt6() + ps := [6]int{0, 0, 0, 0, 0, 0} + CompareContainers(ai, ps) + + vals := [6]int{10, 20, 30, 40, 50, 60} + for i := 0; i < len(vals); i++ { + ai.Set(i, vals[i]) + } + CompareContainers(ai, vals); + + // Check return + vals = [6]int{-2, -1, 0, 0, 1, 2} + CompareContainers(cpp11_std_array.ArrayOutVal(), vals); + CompareContainers(cpp11_std_array.ArrayOutConstRef(), vals); + CompareContainers(cpp11_std_array.ArrayOutRef(), vals); + CompareContainers(cpp11_std_array.ArrayOutPtr(), vals); + + // Check passing arguments + vals = [6]int{9, 8, 7, 6, 5, 4} + valsArrayInt6 := cpp11_std_array.NewArrayInt6() + for i := 0; i < len(vals); i++ { + valsArrayInt6.Set(i, vals[i]) + } + + ai = cpp11_std_array.ArrayInVal(valsArrayInt6); + CompareContainers(ai, vals); + + ai = cpp11_std_array.ArrayInConstRef(valsArrayInt6); + CompareContainers(ai, vals); + + ai = cpp11_std_array.NewArrayInt6(valsArrayInt6); + cpp11_std_array.ArrayInRef(ai); + CompareContainers(ai, vals); + + ai = cpp11_std_array.NewArrayInt6(valsArrayInt6); + cpp11_std_array.ArrayInPtr(ai); + CompareContainers(ai, vals); + + // Fill + ai.Fill(111) + vals = [6]int{111, 111, 111, 111, 111, 111} + CompareContainers(ai, vals); +} diff --git a/Lib/go/std_array.i b/Lib/go/std_array.i new file mode 100644 index 000000000..36c790e3c --- /dev/null +++ b/Lib/go/std_array.i @@ -0,0 +1,43 @@ +/* ----------------------------------------------------------------------------- + * std_array.i + * ----------------------------------------------------------------------------- */ + +%include + +namespace std { + + template class array { + public: + typedef size_t size_type; + typedef ptrdiff_t difference_type; + typedef T value_type; + typedef value_type* pointer; + typedef const value_type* const_pointer; + typedef value_type& reference; + typedef const value_type& const_reference; + + array(); + array(const array& other); + + size_type size() const; + %rename(isEmpty) empty; + bool empty() const; + void fill(const T& u); + %extend { + const_reference get(int i) throw (std::out_of_range) { + int size = int(self->size()); + if (i>=0 && isize()); + if (i>=0 && i Date: Sat, 8 Jan 2022 16:29:18 +0000 Subject: [PATCH 075/662] Add recent change to changes file --- CHANGES.current | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGES.current b/CHANGES.current index fc56246c6..6632f0126 100644 --- a/CHANGES.current +++ b/CHANGES.current @@ -7,11 +7,17 @@ the issue number to the end of the URL: https://github.com/swig/swig/issues/ Version 4.1.0 (in progress) =========================== +2022-01-04: juierror + [Go] #2045 Add support for std::array in std_array.i. + 2021-12-18: olly [PHP] Add PHP keyword 'readonly' (added in 8.1) to the list SWIG knows to automatically rename. This keyword is special in that PHP allows it to be used as a function (or method) name. +2021-12-07: vstinner + [Python] #2116 Python 3.11 support: use Py_SET_TYPE() + 2021-12-05: rwf1 [Octave] #2020 #1893 Add support for Octave 6 up to and including 6.4. Also add support for compiling with -Bsymbolic which is used by default From 0a400f5230818c7a1245d05dd87db45c422cc3db Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Sat, 8 Jan 2022 19:22:49 +0000 Subject: [PATCH 076/662] Building distribution fixes and pcre version display [skip-ci] --- Tools/mkdist.py | 12 ++++++------ Tools/mkwindows.sh | 3 ++- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/Tools/mkdist.py b/Tools/mkdist.py index 4fba4701d..3d631607a 100755 --- a/Tools/mkdist.py +++ b/Tools/mkdist.py @@ -42,18 +42,18 @@ if dirname.lower() != dirname: sys.exit(3) # If directory and tarball exist, remove it -print("Removing " + dirname) if check_dir_exists(dirpath): + print("Removing " + dirpath) run_command("rm", "-rf", dirpath) -print("Removing " + dirname + ".tar if exists") filename = dirpath + ".tar" if check_file_exists(filename): + print("Removing " + filename) run_command("rm", "-rf", filename) -print("Removing " + dirname + ".tar.gz if exists") filename += ".gz" if check_file_exists(filename): + print("Removing " + filename) run_command("rm", "-rf", filename) # Grab the code from git @@ -89,10 +89,10 @@ if not skip_checks: print("Tagging release") tag = "v" + version -force = "-f " if force_tag else "" +force = "-f" if force_tag else "" command = ["git", "tag", "-a", "-m", "'Release version " + version + "'"] -force and command.extend(force, tag) -not force and command.append(tag) +force and command.append(force) +command.append(tag) run_command(*command) == 0 or failed() outdir = dirname + "/" diff --git a/Tools/mkwindows.sh b/Tools/mkwindows.sh index e6ae84350..5e4d2f0fd 100755 --- a/Tools/mkwindows.sh +++ b/Tools/mkwindows.sh @@ -115,8 +115,9 @@ if test -f "$tarball"; then ./configure $extraconfigureoptions --without-alllang echo "Compiling (quietly)..." make > build.log - echo "Simple check to see if swig.exe runs..." + echo "Simple check to see if swig.exe runs and show versions..." env LD_LIBRARY_PATH= PATH= $wine ./swig.exe -version || exit 1 + env LD_LIBRARY_PATH= PATH= $wine ./swig.exe -pcreversion || exit 1 echo "Simple check to see if ccache-swig.exe runs..." env LD_LIBRARY_PATH= PATH= $wine ./CCache/ccache-swig.exe -V || exit 1 echo "Creating $swigwinbasename.zip..." From b98c78441f996fe911c360264d9e60df7fc96d26 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Mon, 10 Jan 2022 20:13:16 +0000 Subject: [PATCH 077/662] GHA debug via ssh info --- .github/workflows/ci.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d328befb0..c4212a42c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -332,6 +332,10 @@ jobs: with: key: ${{ matrix.os || 'ubuntu-20.04' }}-${{ matrix.compiler || 'gcc' }}${{ matrix.GCC }} +# Uncomment to debug via ssh, see https://github.com/mxschmitt/action-tmate +# - name: Setup tmate session +# uses: mxschmitt/action-tmate@v3 + - name: Install Dependencies run: | set -x From 761099720966c2d6701a1dc1473e918de3571665 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Mon, 9 Aug 2021 13:13:17 +0200 Subject: [PATCH 078/662] Stop using Travis CI which doesn't work any longer Unfortunately Travis CI can't be used for building open source projects any longer in practice, as extra credits must be manually requested every time from Travis support, which is just infeasible, as this would need to be done every couple of days if not more often, and support reply time is anything from a couple of days to more than a month. So stop even trying to use it, as it doesn't work anyhow, and switch to using GitHub Actions only. Closes #2067 --- .travis.yml | 499 ---------------------------------- RELEASENOTES | 1 + Tools/brew-install | 25 -- Tools/travis-linux-install.sh | 11 - Tools/travis-osx-install.sh | 41 --- 5 files changed, 1 insertion(+), 576 deletions(-) delete mode 100644 .travis.yml delete mode 100755 Tools/brew-install delete mode 100755 Tools/travis-linux-install.sh delete mode 100755 Tools/travis-osx-install.sh diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index c11479fed..000000000 --- a/.travis.yml +++ /dev/null @@ -1,499 +0,0 @@ -language: cpp -matrix: - include: - - compiler: clang - os: linux - env: SWIGLANG= - dist: xenial - - compiler: gcc - os: linux - env: SWIGLANG= - dist: xenial - - compiler: gcc - os: linux - env: SWIGLANG= BUILDSYSTEM=cmake - dist: xenial - - os: linux - env: SWIGLANG= GCC=4.4 - dist: xenial - - os: linux - env: SWIGLANG= GCC=4.6 - dist: xenial - - os: linux - env: SWIGLANG= GCC=4.7 - dist: xenial - - os: linux - env: SWIGLANG= GCC=4.8 - dist: xenial - - os: linux - env: SWIGLANG= GCC=4.9 - dist: xenial - - os: linux - env: SWIGLANG= GCC=6 - dist: xenial - - os: linux - env: SWIGLANG= GCC=7 - dist: xenial - - os: linux - env: SWIGLANG= GCC=8 - dist: xenial - - os: linux - env: SWIGLANG= GCC=9 - dist: xenial - - os: linux - env: SWIGLANG= GCC=10 - dist: focal - - compiler: gcc - os: linux - env: SWIGLANG=csharp - dist: xenial - - compiler: gcc - os: linux - env: SWIGLANG=d VER=2.066.0 - dist: xenial - - compiler: gcc - os: linux - env: SWIGLANG=d VER=2.086.1 - dist: xenial - - compiler: gcc - os: linux - env: SWIGLANG=go VER=1.3 - dist: xenial - - compiler: gcc - os: linux - env: SWIGLANG=go VER=1.8 - dist: xenial - - compiler: gcc - os: linux - env: SWIGLANG=go VER=1.12 CSTD=gnu99 - dist: xenial - - compiler: gcc - os: linux - env: SWIGLANG=go VER=1.16 CSTD=gnu99 - dist: xenial - - compiler: gcc - os: linux - env: SWIGLANG=guile - dist: xenial - - compiler: gcc - os: linux - env: SWIGLANG=java - dist: xenial - - compiler: gcc - os: linux - env: SWIGLANG=javascript ENGINE=node VER=6 CPP11=1 - dist: xenial - - compiler: gcc - os: linux - env: SWIGLANG=javascript ENGINE=node VER=8 CPP11=1 - dist: xenial - - compiler: gcc - os: linux - env: SWIGLANG=javascript ENGINE=node VER=10 CPP11=1 - dist: xenial - - compiler: gcc - os: linux - env: SWIGLANG=javascript ENGINE=node VER=12 CPP11=1 - dist: xenial - - compiler: gcc - os: linux - env: SWIGLANG=javascript ENGINE=node VER=14 CPP11=1 - dist: xenial - - compiler: gcc - os: linux - env: SWIGLANG=javascript ENGINE=node VER=16 CPP14=1 - dist: xenial - - compiler: gcc - os: linux - env: SWIGLANG=javascript ENGINE=jsc - dist: xenial - - compiler: gcc - os: linux - env: SWIGLANG=javascript ENGINE=v8 - dist: xenial - - compiler: gcc - os: linux - env: SWIGLANG=lua - dist: xenial - - compiler: gcc - os: linux - env: SWIGLANG=lua VER=5.3 - dist: xenial - - compiler: gcc - os: linux - env: SWIGLANG=mzscheme - dist: xenial - - compiler: gcc - os: linux - env: SWIGLANG=ocaml - dist: xenial - - compiler: gcc - os: linux - env: SWIGLANG=octave SWIGJOBS=-j2 - dist: xenial # Octave v4.0.0 - - compiler: gcc - os: linux - env: SWIGLANG=octave SWIGJOBS=-j2 CPP11=1 - dist: bionic # Octave v4.2.2 - - compiler: gcc - os: linux - env: SWIGLANG=perl5 - dist: xenial - - compiler: gcc - os: linux - env: SWIGLANG=php VER=7.4 - dist: xenial - - compiler: gcc - os: linux - env: SWIGLANG=php VER=8.0 - dist: xenial - - compiler: gcc - os: linux - env: SWIGLANG=php VER=7.0 CONFIGOPTS=--enable-cpp11-testing CPPSTD=c++11 - dist: bionic - - compiler: gcc - os: linux - env: SWIGLANG=php VER=7.1 CONFIGOPTS=--enable-cpp11-testing CPPSTD=c++11 - dist: bionic - - compiler: gcc - os: linux - env: SWIGLANG=php VER=7.2 CONFIGOPTS=--enable-cpp11-testing CPPSTD=c++11 - dist: bionic - - compiler: gcc - os: linux - env: SWIGLANG=php VER=7.3 CONFIGOPTS=--enable-cpp11-testing CPPSTD=c++11 - dist: bionic - - compiler: gcc - os: linux - env: SWIGLANG=php VER=7.4 CONFIGOPTS=--enable-cpp11-testing CPPSTD=c++11 - dist: bionic - - compiler: gcc - os: linux - env: SWIGLANG=php VER=8.0 CONFIGOPTS=--enable-cpp11-testing CPPSTD=c++11 - dist: bionic - - compiler: gcc - os: linux - env: SWIGLANG=python # 2.7 - dist: xenial - - compiler: gcc - os: linux - env: SWIGLANG=python PY3=3 VER=3.2 - dist: xenial - - compiler: gcc - os: linux - env: SWIGLANG=python PY3=3 VER=3.3 - dist: xenial - - compiler: gcc - os: linux - env: SWIGLANG=python PY3=3 VER=3.4 - dist: xenial - - compiler: gcc - os: linux - env: SWIGLANG=python PY3=3 VER=3.5 - dist: xenial - - compiler: gcc - os: linux - env: SWIGLANG=python PY3=3 VER=3.6 - dist: xenial - - compiler: gcc - os: linux - env: SWIGLANG=python PY3=3 VER=3.7 - dist: xenial - - compiler: gcc - os: linux - env: SWIGLANG=python PY3=3 VER=3.8 - dist: xenial - - compiler: gcc - os: linux - env: SWIGLANG=python PY3=3 VER=3.9 - dist: xenial - - compiler: gcc - os: linux - env: SWIGLANG=python SWIG_FEATURES=-builtin - dist: xenial - - compiler: gcc - os: linux - env: SWIGLANG=python SWIG_FEATURES="-builtin -O" - dist: xenial - - os: linux - env: SWIGLANG=python SWIG_FEATURES=-builtin GCC=6 CPP11=1 - dist: xenial - - os: linux - env: SWIGLANG=python SWIG_FEATURES=-builtin GCC=6 CPP11=1 PY3=3 VER=3.9 - dist: xenial - - compiler: gcc - os: linux - env: SWIGLANG=python SWIG_FEATURES=-builtin PY3=3 VER=3.4 - dist: xenial - - compiler: gcc - os: linux - env: SWIGLANG=python SWIG_FEATURES=-builtin PY3=3 VER=3.5 - dist: xenial - - compiler: gcc - os: linux - env: SWIGLANG=python SWIG_FEATURES=-builtin PY3=3 VER=3.7 - dist: xenial - - compiler: gcc - os: linux - env: SWIGLANG=python SWIG_FEATURES=-builtin PY3=3 VER=3.8 - dist: xenial - - compiler: gcc - os: linux - env: SWIGLANG=python SWIG_FEATURES=-builtin PY3=3 VER=3.9 - dist: xenial - - compiler: gcc - os: linux - env: SWIGLANG=python SWIG_FEATURES="-builtin -O" PY3=3 VER=3.9 - dist: xenial - - compiler: gcc - os: linux - env: SWIGLANG=python SWIG_FEATURES=-builtin PY3=3 VER=3.9 SWIGOPTPY3= - dist: xenial - - compiler: gcc - os: linux - env: SWIGLANG=python SWIG_FEATURES=-O - dist: xenial - - compiler: gcc - os: linux - env: SWIGLANG=python SWIG_FEATURES=-O PY3=3 VER=3.9 - dist: xenial - - compiler: gcc - os: linux - env: SWIGLANG=r - dist: xenial - - compiler: gcc - os: linux - env: SWIGLANG=ruby VER=1.9 - dist: xenial - - compiler: gcc - os: linux - env: SWIGLANG=ruby VER=2.0 - dist: xenial - - compiler: gcc - os: linux - env: SWIGLANG=ruby VER=2.1 - dist: xenial - - compiler: gcc - os: linux - env: SWIGLANG=ruby VER=2.2 - dist: xenial - - compiler: gcc - os: linux - env: SWIGLANG=ruby VER=2.3 - dist: xenial - - compiler: gcc - os: linux - env: SWIGLANG=ruby VER=2.4 - dist: xenial - - compiler: gcc - os: linux - env: SWIGLANG=ruby VER=2.5 - dist: xenial - - compiler: gcc - os: linux - env: SWIGLANG=ruby VER=2.6 - dist: xenial - - compiler: gcc - os: linux - env: SWIGLANG=ruby VER=2.7 - dist: xenial - - compiler: gcc - os: linux - env: SWIGLANG=ruby VER=3.0 CSTD=c99 - dist: xenial - - compiler: gcc - os: linux - env: SWIGLANG=scilab - dist: xenial - - compiler: gcc - os: linux - env: SWIGLANG=tcl - dist: xenial - - os: linux - env: SWIGLANG=csharp CPP11=1 - dist: xenial - - os: linux - env: SWIGLANG=go VER=1.6 CPP11=1 - dist: xenial - - os: linux - env: SWIGLANG=java CPP11=1 - dist: xenial - - os: linux - env: SWIGLANG=python CPP11=1 - dist: xenial - - os: linux - env: SWIGLANG=r CPP11=1 # Note: making 'R CMD SHLIB' use a different compiler is non-trivial - dist: xenial - - os: linux - env: SWIGLANG=ruby CPP11=1 - dist: xenial - - os: linux - env: SWIGLANG=tcl CPP11=1 - dist: xenial - - os: linux - env: SWIGLANG=csharp GCC=6 CPP14=1 - dist: xenial - - os: linux - env: SWIGLANG=go VER=1.6 GCC=6 CPP14=1 - dist: xenial - - os: linux - env: SWIGLANG=java GCC=6 CPP14=1 - dist: xenial - - os: linux - env: SWIGLANG=python GCC=6 CPP14=1 - dist: xenial - - os: linux - env: SWIGLANG=ruby GCC=6 CPP14=1 - dist: xenial - - os: linux - env: SWIGLANG=tcl GCC=6 CPP14=1 - dist: xenial - - os: linux - env: SWIGLANG=java GCC=7 CPP14=1 - dist: xenial - - os: linux - env: SWIGLANG=python GCC=7 CPP14=1 - dist: xenial - - os: linux - env: SWIGLANG=csharp GCC=8 CPP17=1 - dist: xenial - - os: linux - env: SWIGLANG=java GCC=8 CPP17=1 - dist: xenial - - os: linux - env: SWIGLANG=python GCC=8 CPP17=1 PY3=3 VER=3.9 - dist: xenial - - os: linux - env: SWIGLANG=csharp GCC=9 CPP17=1 - dist: xenial - - os: linux - env: SWIGLANG=java GCC=9 CPP17=1 - dist: xenial - - os: linux - env: SWIGLANG=python GCC=9 CPP17=1 PY3=3 VER=3.9 - dist: xenial - - os: linux - arch: s390x - env: SWIGLANG=ruby CPP11=1 - dist: xenial - - compiler: gcc - os: osx - osx_image: xcode12.2 - env: SWIGLANG= - - compiler: clang - os: osx - osx_image: xcode12.2 - env: SWIGLANG= BUILDSYSTEM=cmake - - compiler: clang - os: osx - osx_image: xcode12.2 - env: SWIGLANG= - - compiler: clang - os: osx - osx_image: xcode12.2 - env: SWIGLANG=csharp - - compiler: clang - os: osx - osx_image: xcode12.2 - env: SWIGLANG=go CSTD=gnu99 - - compiler: clang - os: osx - osx_image: xcode12.2 - env: SWIGLANG=guile CSTD=c11 - - compiler: clang - os: osx - osx_image: xcode12.2 - env: SWIGLANG=java - - compiler: clang - os: osx - osx_image: xcode12.2 - env: SWIGLANG=lua -# octave-6.1 not working -# - compiler: clang -# os: osx -# osx_image: xcode12.2 -# env: SWIGLANG=octave SWIGJOBS=-j2 CPP11=1 - - compiler: clang - os: osx - osx_image: xcode12.2 - env: SWIGLANG=perl5 - - compiler: clang - os: osx - osx_image: xcode12.2 - env: SWIGLANG=python - - compiler: clang - os: osx - osx_image: xcode12.2 - env: SWIGLANG=python PY3=3 - - compiler: clang - os: osx - osx_image: xcode12.2 - env: SWIGLANG=ruby - - compiler: clang - os: osx - osx_image: xcode12.2 - env: SWIGLANG=tcl - - compiler: clang - os: osx - osx_image: xcode12.2 - env: SWIGLANG=java CPP17=1 - - compiler: clang - os: osx - osx_image: xcode12.2 - env: SWIGLANG=python PY3=3 CPP17=1 - - allow_failures: - # Newer version of D not yet working/supported - - compiler: gcc - os: linux - env: SWIGLANG=d VER=2.086.1 - dist: xenial - # Experimental languages - - compiler: gcc - os: linux - env: SWIGLANG=mzscheme - dist: xenial - - compiler: gcc - os: linux - env: SWIGLANG=ocaml - dist: xenial - -before_install: - - date -u - - uname -a - - if test "$TRAVIS_OS_NAME" = "linux"; then lscpu; grep "model name" /proc/cpuinfo || echo 'Unknown CPU model'; grep "MemTotal" /proc/meminfo || echo 'Unknown system memory amount'; fi - - if test "$TRAVIS_OS_NAME" = "osx"; then sysctl -a | grep brand_string; fi - # Travis overrides CC environment with compiler predefined values - - if test -n "$GCC"; then export CC="gcc-$GCC" && export CXX="g++-$GCC"; fi -install: - - if test "$TRAVIS_OS_NAME" = "linux"; then source Tools/travis-linux-install.sh; fi - - if test "$TRAVIS_OS_NAME" = "osx"; then source Tools/travis-osx-install.sh; fi - - ls -la $(which $CC) $(which $CXX) && $CC --version && $CXX --version -script: - - if test "$BUILDSYSTEM" = "cmake"; then cmake --version && mkdir -p build/build && cd build/build && CXXFLAGS="-Wall -Wextra -Werror" CFLAGS="-Wall -Wextra -Werror" cmake -DCMAKE_INSTALL_PREFIX=~/.local ../.. && make install && ctest --output-on-failure -V && exit 0; fi - - echo 'Configuring...' && echo -en 'travis_fold:start:script.1\\r' - - if test -n "$CPP11"; then CONFIGOPTS+=(--enable-cpp11-testing "CXXFLAGS=-std=c++11 $CXXFLAGS" "CFLAGS=-std=c11 $CFLAGS") && export CSTD=c11 && export CPPSTD=c++11; fi - - if test -n "$CPP14"; then CONFIGOPTS+=(--enable-cpp11-testing "CXXFLAGS=-std=c++14 $CXXFLAGS" "CFLAGS=-std=c11 $CFLAGS") && export CSTD=c11 && export CPPSTD=c++14; fi - - if test -n "$CPP17"; then CONFIGOPTS+=(--enable-cpp11-testing "CXXFLAGS=-std=c++17 $CXXFLAGS" "CFLAGS=-std=c17 $CFLAGS") && export CSTD=c17 && export CPPSTD=c++17; fi - - if test -n "$SWIGLANG"; then CONFIGOPTS+=(--without-alllang --with-$WITHLANG); fi - - echo "${CONFIGOPTS[@]}" - - ./autogen.sh && mkdir -p build/build && cd build/build && ../../configure "${CONFIGOPTS[@]}" - - echo -en 'travis_fold:end:script.1\\r' - - make -s $SWIGJOBS - - ./swig -version && ./swig -pcreversion - - if test -z "$SWIGLANG"; then make -s $SWIGJOBS check-ccache; fi - - if test -z "$SWIGLANG"; then make -s $SWIGJOBS check-errors-test-suite; fi - - echo 'Installing...' && echo -en 'travis_fold:start:script.2\\r' - - if test -z "$SWIGLANG"; then sudo make -s install && swig -version && ccache-swig -V; fi - - echo -en 'travis_fold:end:script.2\\r' - # Stricter compile flags for examples. Various headers and SWIG generated code prevents full use of -pedantic. - - if test -n "$SWIGLANG"; then cflags=$($TRAVIS_BUILD_DIR/Tools/testflags.py --language $SWIGLANG --cflags --std=$CSTD --compiler=$CC) && echo $cflags; fi - - if test -n "$SWIGLANG"; then cxxflags=$($TRAVIS_BUILD_DIR/Tools/testflags.py --language $SWIGLANG --cxxflags --std=$CPPSTD --compiler=$CC) && echo $cxxflags; fi - - if test -n "$SWIGLANG"; then make -s check-$SWIGLANG-version; fi - - if test -n "$SWIGLANG"; then make check-$SWIGLANG-enabled; fi - - if test -n "$SWIGLANG"; then make $SWIGJOBS check-$SWIGLANG-examples CFLAGS="$cflags" CXXFLAGS="$cxxflags"; fi - - if test -n "$SWIGLANG"; then make $SWIGJOBS check-$SWIGLANG-test-suite CFLAGS="$cflags" CXXFLAGS="$cxxflags"; fi - - echo 'Cleaning...' && echo -en 'travis_fold:start:script.3\\r' - # Skip on osx as often fails with: rm: Resource temporarily unavailable - - if test "$TRAVIS_OS_NAME" != "osx"; then make check-maintainer-clean && ../../configure $CONFIGOPTS; fi - - echo -en 'travis_fold:end:script.3\\r' diff --git a/RELEASENOTES b/RELEASENOTES index da60d543f..c05ccc4ec 100644 --- a/RELEASENOTES +++ b/RELEASENOTES @@ -10,6 +10,7 @@ published on the SWIG web site at http://swig.org/release.html. SWIG-4.1.0 summary: - Add PHP 8 support. - PHP wrapping is now done entirely via PHP's C API - no more .php wrapper. +- GitHub Actions is now used instead of Travis CI for continuous integration. SWIG-4.0.2 summary: - A few fixes around doxygen comment handling. diff --git a/Tools/brew-install b/Tools/brew-install deleted file mode 100755 index 39fe22bc2..000000000 --- a/Tools/brew-install +++ /dev/null @@ -1,25 +0,0 @@ -#!/bin/bash - -# Wrapper around 'brew install' emitting a message every minute if the command is still running. -# This is used on Travis to ensure the install isn't killed when there is no output over a long period (10 minutes). -# Usage: brew-install package, where package is the name of the package for brew to install. - -seconds=0 -minutes=0 -brew install "$@" & -while true; do - ps -p$! 2>& 1>/dev/null - if [ $? = 0 ]; then - if [ $seconds = 60 ]; then - let seconds=0 - let minutes=minutes+1 - echo "brew install $1 still running ($minutes min)" - fi - sleep 1 - let seconds=seconds+1 - else - break - fi -done -wait $! -exit $? diff --git a/Tools/travis-linux-install.sh b/Tools/travis-linux-install.sh deleted file mode 100755 index cb64d57d2..000000000 --- a/Tools/travis-linux-install.sh +++ /dev/null @@ -1,11 +0,0 @@ -#!/bin/bash - -# Install Linux packages where the version has been overridden in .travis.yml - -lsb_release -a -# find location of current script (only works in bash) -script_dir="$( dirname "${BASH_SOURCE[0]}")" - -# run generic script -RETRY=travis-retry -source "$script_dir"/CI-linux-install.sh diff --git a/Tools/travis-osx-install.sh b/Tools/travis-osx-install.sh deleted file mode 100755 index fc69c6654..000000000 --- a/Tools/travis-osx-install.sh +++ /dev/null @@ -1,41 +0,0 @@ -#!/bin/bash - -# Install MacOS packages where the version has been overridden in .travis.yml - -set -e # exit on failure (same as -o errexit) - -# Disable 'brew cleanup', just wastes Travis job run time -export HOMEBREW_NO_INSTALL_CLEANUP=1 - -sw_vers -travis_retry brew update -echo "Installed packages..." -travis_retry brew list --versions -# travis_retry brew install pcre # Travis Xcode-7.3 has pcre -# travis_retry brew install boost - -WITHLANG=$SWIGLANG - -case "$SWIGLANG" in - "csharp") - travis_retry brew install mono - ;; - "lua") - travis_retry brew install lua - ;; - "octave") - travis_retry Tools/brew-install octave - ;; - "perl5") - travis_retry Tools/brew-install perl - ;; - "python") - WITHLANG=$SWIGLANG$PY3 - ;; - "tcl") - travis_retry Tools/brew-install --cask tcl - ;; -esac - -# Workaround for https://github.com/travis-ci/travis-ci/issues/6522 -set +e # turn off exit on failure (same as +o errexit) From cf8788c411d8096104628dfd5901620b8ea3a315 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Tue, 11 Jan 2022 15:11:04 +0000 Subject: [PATCH 079/662] Update Python tests to not use flatstaticmethod access Use Python class staticmethod syntax to access C++ static member functions, such as Klass.memberfunction, instead of Klass_memberfunction. Examples and test-suite changes in preparation for issue #2137. --- Examples/python/import/runme.py | 8 +++---- Examples/python/import_template/runme.py | 8 +++---- Examples/test-suite/python/autodoc_runme.py | 22 ------------------- Examples/test-suite/python/contract_runme.py | 6 ++--- .../test-suite/python/default_args_runme.py | 2 +- .../python/director_abstract_runme.py | 2 +- .../test-suite/python/director_basic_runme.py | 8 +++---- .../python/director_nested_runme.py | 2 +- .../test-suite/python/kwargs_feature_runme.py | 8 +++---- .../python/li_boost_shared_ptr_runme.py | 2 +- .../test-suite/python/li_factory_runme.py | 4 ++-- .../python/li_std_auto_ptr_runme.py | 6 ++--- .../python/operator_overload_runme.py | 2 +- .../python/overload_simple_runme.py | 12 +++++----- .../python/overload_template_runme.py | 2 +- .../python_overload_simple_cast_runme.py | 12 +++++----- Examples/test-suite/python/refcount_runme.py | 6 ++--- .../python/return_const_value_runme.py | 4 ++-- .../python/template_static_runme.py | 2 +- .../python/typemap_out_optimal_runme.py | 2 +- .../test-suite/python/virtual_poly_runme.py | 4 ++-- Examples/test-suite/python/voidtest_runme.py | 2 +- 22 files changed, 52 insertions(+), 74 deletions(-) diff --git a/Examples/python/import/runme.py b/Examples/python/import/runme.py index afa21a2b3..7970dec26 100644 --- a/Examples/python/import/runme.py +++ b/Examples/python/import/runme.py @@ -84,14 +84,14 @@ x.B() print("\nTesting some dynamic casts\n") x = d.toBase() -y = foo.Foo_fromBase(x) +y = foo.Foo.fromBase(x) print(" Spam -> Base -> Foo : {} swig".format("bad" if y else "good")) -y = bar.Bar_fromBase(x) +y = bar.Bar.fromBase(x) print(" Spam -> Base -> Bar : {} swig".format("good" if y else "bad")) -y = spam.Spam_fromBase(x) +y = spam.Spam.fromBase(x) print(" Spam -> Base -> Spam : {} swig".format("good" if y else "bad")) -y = spam.Spam_fromBase(b) +y = spam.Spam.fromBase(b) print(" Foo -> Spam : {} swig".format("bad" if y else "good")) diff --git a/Examples/python/import_template/runme.py b/Examples/python/import_template/runme.py index b14f8d35e..74a918426 100644 --- a/Examples/python/import_template/runme.py +++ b/Examples/python/import_template/runme.py @@ -84,14 +84,14 @@ x.B() print("\nTesting some dynamic casts\n") x = d.toBase() -y = foo.intFoo_fromBase(x) +y = foo.intFoo.fromBase(x) print(" Spam -> Base -> Foo : {} swig".format("bad" if y else "good")) -y = bar.intBar_fromBase(x) +y = bar.intBar.fromBase(x) print(" Spam -> Base -> Bar : {} swig".format("good" if y else "bad")) -y = spam.intSpam_fromBase(x) +y = spam.intSpam.fromBase(x) print(" Spam -> Base -> Spam : {} swig".format("good" if y else "bad")) -y = spam.intSpam_fromBase(b) +y = spam.intSpam.fromBase(b) print(" Foo -> Spam : {} swig".format("bad" if y else "good")) diff --git a/Examples/test-suite/python/autodoc_runme.py b/Examples/test-suite/python/autodoc_runme.py index 7bc918644..960458584 100644 --- a/Examples/test-suite/python/autodoc_runme.py +++ b/Examples/test-suite/python/autodoc_runme.py @@ -65,14 +65,10 @@ check(inspect.getdoc(A.func0static), "func0static(e, arg2, hello, f=2) -> int") check(inspect.getdoc(_autodoc.A_func0static), "A_func0static(e, arg2, hello, f=2) -> int") -check(inspect.getdoc(A_func0static), - "A_func0static(e, arg2, hello, f=2) -> int") check(inspect.getdoc(A.func1static), "func1static(A e, short arg2, Tuple hello, double f=2) -> int") check(inspect.getdoc(_autodoc.A_func1static), "A_func1static(A e, short arg2, Tuple hello, double f=2) -> int") -check(inspect.getdoc(A_func1static), - "A_func1static(A e, short arg2, Tuple hello, double f=2) -> int") check(inspect.getdoc(A.func2static), "func2static(e, arg2, hello, f=2) -> int\n" "\n" @@ -91,15 +87,6 @@ check(inspect.getdoc(_autodoc.A_func2static), "arg2: short\n" "hello: int tuple[2]\n" "f: double") -check(inspect.getdoc(A_func2static), - "A_func2static(e, arg2, hello, f=2) -> int\n" - "\n" - "Parameters\n" - "----------\n" - "e: A *\n" - "arg2: short\n" - "hello: int tuple[2]\n" - "f: double") check(inspect.getdoc(A.func3static), "func3static(A e, short arg2, Tuple hello, double f=2) -> int\n" "\n" @@ -118,15 +105,6 @@ check(inspect.getdoc(_autodoc.A_func3static), "arg2: short\n" "hello: int tuple[2]\n" "f: double") -check(inspect.getdoc(A_func3static), - "A_func3static(A e, short arg2, Tuple hello, double f=2) -> int\n" - "\n" - "Parameters\n" - "----------\n" - "e: A *\n" - "arg2: short\n" - "hello: int tuple[2]\n" - "f: double") check(inspect.getdoc(A.variable_a), "variable_a" diff --git a/Examples/test-suite/python/contract_runme.py b/Examples/test-suite/python/contract_runme.py index b6bab3a09..3194b6ac7 100644 --- a/Examples/test-suite/python/contract_runme.py +++ b/Examples/test-suite/python/contract_runme.py @@ -58,15 +58,15 @@ try: except RuntimeError: pass -contract.Foo_stest_prepost(4, 0) +contract.Foo.stest_prepost(4, 0) try: - contract.Foo_stest_prepost(-4, 2) + contract.Foo.stest_prepost(-4, 2) raise Exception("Failed! Static method preassertion") except RuntimeError: pass try: - contract.Foo_stest_prepost(4, -10) + contract.Foo.stest_prepost(4, -10) raise Exception("Failed! Static method posteassertion") except RuntimeError: pass diff --git a/Examples/test-suite/python/default_args_runme.py b/Examples/test-suite/python/default_args_runme.py index 0ce47ab79..b8077cc28 100644 --- a/Examples/test-suite/python/default_args_runme.py +++ b/Examples/test-suite/python/default_args_runme.py @@ -12,7 +12,7 @@ def run(module_name): de.accelerate() de.accelerate(default_args.EnumClass.SLOW) - if default_args.Statics_staticMethod() != 60: + if default_args.Statics.staticMethod() != 60: raise RuntimeError if default_args.cfunc1(1) != 2: diff --git a/Examples/test-suite/python/director_abstract_runme.py b/Examples/test-suite/python/director_abstract_runme.py index c8c4b36dc..fbc54808e 100644 --- a/Examples/test-suite/python/director_abstract_runme.py +++ b/Examples/test-suite/python/director_abstract_runme.py @@ -37,7 +37,7 @@ class MyExample3(director_abstract.Example3_i): return b me1 = MyExample1() -if director_abstract.Example1_get_color(me1, 1, 2, 3) != 1: +if director_abstract.Example1.get_color(me1, 1, 2, 3) != 1: raise RuntimeError me2 = MyExample2(1, 2) diff --git a/Examples/test-suite/python/director_basic_runme.py b/Examples/test-suite/python/director_basic_runme.py index 79cd0e2eb..2d07c3ad5 100644 --- a/Examples/test-suite/python/director_basic_runme.py +++ b/Examples/test-suite/python/director_basic_runme.py @@ -44,8 +44,8 @@ b = director_basic.Bar(3) d = director_basic.MyClass() c = PyClass() -cc = director_basic.MyClass_get_self(c) -dd = director_basic.MyClass_get_self(d) +cc = director_basic.MyClass.get_self(c) +dd = director_basic.MyClass.get_self(d) bc = cc.cmethod(b) bd = dd.cmethod(b) @@ -86,8 +86,8 @@ for i in range(0, 100): pymult = PyMulti() -p1 = director_basic.Foo_get_self(pymult) -p2 = director_basic.MyClass_get_self(pymult) +p1 = director_basic.Foo.get_self(pymult) +p2 = director_basic.MyClass.get_self(pymult) p1.ping() p2.vmethod(bc) diff --git a/Examples/test-suite/python/director_nested_runme.py b/Examples/test-suite/python/director_nested_runme.py index b2c4b0d40..24216f9dd 100644 --- a/Examples/test-suite/python/director_nested_runme.py +++ b/Examples/test-suite/python/director_nested_runme.py @@ -54,7 +54,7 @@ class C(FooBar_int): pass cc = C() -c = FooBar_int_get_self(cc) +c = FooBar_int.get_self(cc) c.advance() if c.get_name() != "FooBar::get_name hello": diff --git a/Examples/test-suite/python/kwargs_feature_runme.py b/Examples/test-suite/python/kwargs_feature_runme.py index 387658ec3..d07525ffc 100644 --- a/Examples/test-suite/python/kwargs_feature_runme.py +++ b/Examples/test-suite/python/kwargs_feature_runme.py @@ -15,13 +15,13 @@ f = Foo(b=2, a=1) if f.foo(b=1, a=2) != 3: raise RuntimeError -if Foo_statfoo(b=2) != 3: +if Foo.statfoo(b=2) != 3: raise RuntimeError if f.efoo(b=2) != 3: raise RuntimeError -if Foo_sfoo(b=2) != 3: +if Foo.sfoo(b=2) != 3: raise RuntimeError @@ -31,13 +31,13 @@ b = BarInt(b=2, a=1) if b.bar(b=1, a=2) != 3: raise RuntimeError -if BarInt_statbar(b=2) != 3: +if BarInt.statbar(b=2) != 3: raise RuntimeError if b.ebar(b=2) != 3: raise RuntimeError -if BarInt_sbar(b=2) != 3: +if BarInt.sbar(b=2) != 3: raise RuntimeError diff --git a/Examples/test-suite/python/li_boost_shared_ptr_runme.py b/Examples/test-suite/python/li_boost_shared_ptr_runme.py index ecda7fdb1..2e241d590 100644 --- a/Examples/test-suite/python/li_boost_shared_ptr_runme.py +++ b/Examples/test-suite/python/li_boost_shared_ptr_runme.py @@ -20,7 +20,7 @@ class li_boost_shared_ptr_runme: self.runtest() # Expect 1 instance - the one global variable (GlobalValue) - if (li_boost_shared_ptr.Klass_getTotal_count() != 1): + if (li_boost_shared_ptr.Klass.getTotal_count() != 1): raise RuntimeError("Klass.total_count=%s" % li_boost_shared_ptr.Klass.getTotal_count()) diff --git a/Examples/test-suite/python/li_factory_runme.py b/Examples/test-suite/python/li_factory_runme.py index fb2c81e45..ce0e3caef 100644 --- a/Examples/test-suite/python/li_factory_runme.py +++ b/Examples/test-suite/python/li_factory_runme.py @@ -1,11 +1,11 @@ from li_factory import * -circle = Geometry_create(Geometry.CIRCLE) +circle = Geometry.create(Geometry.CIRCLE) r = circle.radius() if (r != 1.5): raise RuntimeError -point = Geometry_create(Geometry.POINT) +point = Geometry.create(Geometry.POINT) w = point.width() if (w != 1.0): raise RuntimeError 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 6d2479f87..d62224ff6 100644 --- a/Examples/test-suite/python/li_std_auto_ptr_runme.py +++ b/Examples/test-suite/python/li_std_auto_ptr_runme.py @@ -2,16 +2,16 @@ from li_std_auto_ptr import * k1 = makeKlassAutoPtr("first") k2 = makeKlassAutoPtr("second") -if Klass_getTotal_count() != 2: +if Klass.getTotal_count() != 2: raise "number of objects should be 2" del k1 -if Klass_getTotal_count() != 1: +if Klass.getTotal_count() != 1: raise "number of objects should be 1" if k2.getLabel() != "second": raise "wrong object label" del k2 -if Klass_getTotal_count() != 0: +if Klass.getTotal_count() != 0: raise "no objects should be left" diff --git a/Examples/test-suite/python/operator_overload_runme.py b/Examples/test-suite/python/operator_overload_runme.py index 31c49058e..cd565f619 100644 --- a/Examples/test-suite/python/operator_overload_runme.py +++ b/Examples/test-suite/python/operator_overload_runme.py @@ -1,7 +1,7 @@ from operator_overload import * # first check all the operators are implemented correctly from pure C++ code -Op_sanity_check() +Op.sanity_check() pop = Op(6)/Op(3) diff --git a/Examples/test-suite/python/overload_simple_runme.py b/Examples/test-suite/python/overload_simple_runme.py index 8ad813b86..56763828d 100644 --- a/Examples/test-suite/python/overload_simple_runme.py +++ b/Examples/test-suite/python/overload_simple_runme.py @@ -43,22 +43,22 @@ if s.foo(b) != "foo:Bar *": if s.foo(v) != "foo:void *": raise RuntimeError("Spam::foo(void *)") -if Spam_bar(3) != "bar:int": +if Spam.bar(3) != "bar:int": raise RuntimeError("Spam::bar(int)") -if Spam_bar(3.0) != "bar:double": +if Spam.bar(3.0) != "bar:double": raise RuntimeError("Spam::bar(double)") -if Spam_bar("hello") != "bar:char *": +if Spam.bar("hello") != "bar:char *": raise RuntimeError("Spam::bar(char *)") -if Spam_bar(f) != "bar:Foo *": +if Spam.bar(f) != "bar:Foo *": raise RuntimeError("Spam::bar(Foo *)") -if Spam_bar(b) != "bar:Bar *": +if Spam.bar(b) != "bar:Bar *": raise RuntimeError("Spam::bar(Bar *)") -if Spam_bar(v) != "bar:void *": +if Spam.bar(v) != "bar:void *": raise RuntimeError("Spam::bar(void *)") # Test constructors diff --git a/Examples/test-suite/python/overload_template_runme.py b/Examples/test-suite/python/overload_template_runme.py index a484d8f0e..8bd105add 100644 --- a/Examples/test-suite/python/overload_template_runme.py +++ b/Examples/test-suite/python/overload_template_runme.py @@ -140,6 +140,6 @@ if (nsoverload() != 1050): raise RuntimeError(("nsoverload(const char *)")) -A_foo(1) +A.foo(1) b = B() b.foo(1) diff --git a/Examples/test-suite/python/python_overload_simple_cast_runme.py b/Examples/test-suite/python/python_overload_simple_cast_runme.py index 7a0174af8..2aee5bb53 100644 --- a/Examples/test-suite/python/python_overload_simple_cast_runme.py +++ b/Examples/test-suite/python/python_overload_simple_cast_runme.py @@ -115,22 +115,22 @@ if s.foo(b) != "foo:Bar *": if s.foo(v) != "foo:void *": raise RuntimeError("Spam::foo(void *)") -if Spam_bar(3) != "bar:int": +if Spam.bar(3) != "bar:int": raise RuntimeError("Spam::bar(int)") -if Spam_bar(3.0) != "bar:double": +if Spam.bar(3.0) != "bar:double": raise RuntimeError("Spam::bar(double)") -if Spam_bar("hello") != "bar:char *": +if Spam.bar("hello") != "bar:char *": raise RuntimeError("Spam::bar(char *)") -if Spam_bar(f) != "bar:Foo *": +if Spam.bar(f) != "bar:Foo *": raise RuntimeError("Spam::bar(Foo *)") -if Spam_bar(b) != "bar:Bar *": +if Spam.bar(b) != "bar:Bar *": raise RuntimeError("Spam::bar(Bar *)") -if Spam_bar(v) != "bar:void *": +if Spam.bar(v) != "bar:void *": raise RuntimeError("Spam::bar(void *)") # Test constructors diff --git a/Examples/test-suite/python/refcount_runme.py b/Examples/test-suite/python/refcount_runme.py index 2cab6a77e..5bea25fa1 100644 --- a/Examples/test-suite/python/refcount_runme.py +++ b/Examples/test-suite/python/refcount_runme.py @@ -5,7 +5,7 @@ from refcount import * a = A3() b1 = B(a) -b2 = B_create(a) +b2 = B.create(a) if a.ref_count() != 3: @@ -13,7 +13,7 @@ if a.ref_count() != 3: rca = b2.get_rca() -b3 = B_create(rca) +b3 = B.create(rca) if a.ref_count() != 5: raise RuntimeError("Count = %d" % a.ref_count()) @@ -38,7 +38,7 @@ b5 = global_create(a) if b5.ref_count() != 1: raise RuntimeError -b6 = Factory_create(a) +b6 = Factory.create(a) if b6.ref_count() != 1: raise RuntimeError diff --git a/Examples/test-suite/python/return_const_value_runme.py b/Examples/test-suite/python/return_const_value_runme.py index 809eed97a..8cbac125c 100644 --- a/Examples/test-suite/python/return_const_value_runme.py +++ b/Examples/test-suite/python/return_const_value_runme.py @@ -1,10 +1,10 @@ import return_const_value import sys -p = return_const_value.Foo_ptr_getPtr() +p = return_const_value.Foo_ptr.getPtr() if (p.getVal() != 17): raise RuntimeError("Runtime test1 failed. p.getVal()={}".format(p.getVal())) -p = return_const_value.Foo_ptr_getConstPtr() +p = return_const_value.Foo_ptr.getConstPtr() if (p.getVal() != 17): raise RuntimeError("Runtime test2 failed. p.getVal()={}".format(p.getVal())) diff --git a/Examples/test-suite/python/template_static_runme.py b/Examples/test-suite/python/template_static_runme.py index c87a52439..84da28438 100644 --- a/Examples/test-suite/python/template_static_runme.py +++ b/Examples/test-suite/python/template_static_runme.py @@ -1,3 +1,3 @@ from template_static import * -Foo_bar_double(1) +Foo.bar_double(1) diff --git a/Examples/test-suite/python/typemap_out_optimal_runme.py b/Examples/test-suite/python/typemap_out_optimal_runme.py index c7a34308e..c325ece55 100644 --- a/Examples/test-suite/python/typemap_out_optimal_runme.py +++ b/Examples/test-suite/python/typemap_out_optimal_runme.py @@ -1,4 +1,4 @@ from typemap_out_optimal import * cvar.XX_debug = False -x = XX_create() +x = XX.create() diff --git a/Examples/test-suite/python/virtual_poly_runme.py b/Examples/test-suite/python/virtual_poly_runme.py index 0df6271ef..6708b6f99 100644 --- a/Examples/test-suite/python/virtual_poly_runme.py +++ b/Examples/test-suite/python/virtual_poly_runme.py @@ -29,10 +29,10 @@ if d.get() != dr.get(): # # 'narrowing' also works # -ddc = virtual_poly.NDouble_narrow(d.nnumber()) +ddc = virtual_poly.NDouble.narrow(d.nnumber()) if d.get() != ddc.get(): raise RuntimeError -dic = virtual_poly.NInt_narrow(i.nnumber()) +dic = virtual_poly.NInt.narrow(i.nnumber()) if i.get() != dic.get(): raise RuntimeError diff --git a/Examples/test-suite/python/voidtest_runme.py b/Examples/test-suite/python/voidtest_runme.py index b16cacf00..dd25b4c25 100644 --- a/Examples/test-suite/python/voidtest_runme.py +++ b/Examples/test-suite/python/voidtest_runme.py @@ -4,7 +4,7 @@ voidtest.globalfunc() f = voidtest.Foo() f.memberfunc() -voidtest.Foo_staticmemberfunc() +voidtest.Foo.staticmemberfunc() def fvoid(): From 627f7214dbe6d21487f1ce6800c6b433be92518e Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Tue, 11 Jan 2022 23:33:22 +0000 Subject: [PATCH 080/662] [Python] Add missing Python kwargs builtin support Accept keyword arguments accessing C++ static member functions when using -builtin and kwargs feature and Python class staticmethod syntax. The missing keyword argument support was only when using the class staticmethod syntax, not when using the flat static method syntax. --- CHANGES.current | 7 +++++++ Examples/test-suite/kwargs_feature.i | 1 + Examples/test-suite/python/kwargs_feature_runme.py | 3 +++ Source/Modules/python.cxx | 4 ++-- 4 files changed, 13 insertions(+), 2 deletions(-) diff --git a/CHANGES.current b/CHANGES.current index 6632f0126..a5a7b8c34 100644 --- a/CHANGES.current +++ b/CHANGES.current @@ -7,6 +7,13 @@ the issue number to the end of the URL: https://github.com/swig/swig/issues/ Version 4.1.0 (in progress) =========================== +2022-01-11: wsfulton + [Python] Accept keyword arguments accessing static member functions when + using -builtin and kwargs feature and Python class staticmethod syntax. + The missing keyword argument support was only when using the + class staticmethod syntax, such as Klass.memberfunction, and not when + using the flat static method syntax, such as Klass_memberfunction. + 2022-01-04: juierror [Go] #2045 Add support for std::array in std_array.i. diff --git a/Examples/test-suite/kwargs_feature.i b/Examples/test-suite/kwargs_feature.i index dd5b2638d..6db4d407b 100644 --- a/Examples/test-suite/kwargs_feature.i +++ b/Examples/test-suite/kwargs_feature.i @@ -27,6 +27,7 @@ virtual int foo(int a = 1, int b = 0) {return a + b; } static int statfoo(int a = 1, int b = 0) {return a + b; } + static int statfoo_onearg(int x = 10) {return x + x; } static Foo *create(int a = 1, int b = 0) { diff --git a/Examples/test-suite/python/kwargs_feature_runme.py b/Examples/test-suite/python/kwargs_feature_runme.py index d07525ffc..677c9ebd8 100644 --- a/Examples/test-suite/python/kwargs_feature_runme.py +++ b/Examples/test-suite/python/kwargs_feature_runme.py @@ -18,6 +18,9 @@ if f.foo(b=1, a=2) != 3: if Foo.statfoo(b=2) != 3: raise RuntimeError +if Foo.statfoo_onearg(x=4) != 8: + raise RuntimeError + if f.efoo(b=2) != 3: raise RuntimeError diff --git a/Source/Modules/python.cxx b/Source/Modules/python.cxx index 8682e6917..9046edcfb 100644 --- a/Source/Modules/python.cxx +++ b/Source/Modules/python.cxx @@ -4727,6 +4727,7 @@ public: Swig_restore(n); } + int kw = (check_kwargs(n) && !Getattr(n, "sym:overloaded")) ? 1 : 0; if (builtin && in_class) { if ((GetFlagAttr(n, "feature:extend") || checkAttribute(n, "access", "public")) && !Getattr(class_members, symname)) { @@ -4741,7 +4742,7 @@ public: else if (funpack && argcount == 1) Append(pyflags, "METH_O"); else - Append(pyflags, "METH_VARARGS"); + Append(pyflags, kw ? "METH_VARARGS|METH_KEYWORDS" : "METH_VARARGS"); // Cast via void(*)(void) to suppress GCC -Wcast-function-type warning. // Python should always call the function correctly, but the Python C // API requires us to store it in function pointer of a different type. @@ -4767,7 +4768,6 @@ public: String *staticfunc_name = NewString(fastproxy ? "_swig_new_static_method" : "staticmethod"); bool fast = (fastproxy && !have_addtofunc(n)) || Getattr(n, "feature:callback"); if (!fast || olddefs) { - int kw = (check_kwargs(n) && !Getattr(n, "sym:overloaded")) ? 1 : 0; String *parms = make_pyParmList(n, false, false, kw); String *callParms = make_pyParmList(n, false, true, kw); Printv(f_shadow, "\n", tab4, "@staticmethod", NIL); From 3aa302c08f609ad15a602b32a8c0124eb48861f9 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Fri, 14 Jan 2022 20:23:43 +0000 Subject: [PATCH 081/662] %callback and Python class access for C++ static member functions fixes Fix access to C++ static member functions using Python class staticmethod syntax, such as Klass.memberfunction instead of Klass_memberfunction, when using -fastproxy and -builtin in combination with %callback. The docstring containing the callback pointers were not being patched during module initialisation. --- CHANGES.current | 6 ++++++ Examples/test-suite/python/callback_runme.py | 13 +++++++----- Lib/python/pyinit.swg | 13 +++++------- Source/Modules/python.cxx | 21 ++++++++++++++++++-- 4 files changed, 38 insertions(+), 15 deletions(-) diff --git a/CHANGES.current b/CHANGES.current index a5a7b8c34..b6c21643b 100644 --- a/CHANGES.current +++ b/CHANGES.current @@ -7,6 +7,12 @@ the issue number to the end of the URL: https://github.com/swig/swig/issues/ Version 4.1.0 (in progress) =========================== +2022-01-14: wsfulton + [Python] Fix %callback and specifying the callback function as a + static member function using Python staticmethod syntax, such as + Klass.memberfunction instead of Klass_memberfunction when using + -builtin and -fastproxy. + 2022-01-11: wsfulton [Python] Accept keyword arguments accessing static member functions when using -builtin and kwargs feature and Python class staticmethod syntax. diff --git a/Examples/test-suite/python/callback_runme.py b/Examples/test-suite/python/callback_runme.py index de8a372f6..19f61c96b 100644 --- a/Examples/test-suite/python/callback_runme.py +++ b/Examples/test-suite/python/callback_runme.py @@ -1,10 +1,14 @@ import _callback from callback import * +# callbacks are implemented by modifying docstrings, useful for debugging: +# print("A_bar doc: {}".format(A_bar.__doc__)) +# print("A.bar doc: {}".format(A.bar.__doc__)) + if foo(2) != 2: raise RuntimeError -if A_bar(2) != 4: +if A.bar(2) != 4: raise RuntimeError if foobar(3, _callback.foo) != foo(3): @@ -13,13 +17,12 @@ if foobar(3, _callback.foo) != foo(3): if foobar(3, foo) != foo(3): raise RuntimeError -# Needs some more work for -builtin -# if foobar(3, A.bar) != A.bar(3): -# raise RuntimeError - if foobar(3, A_bar) != A_bar(3): raise RuntimeError +if foobar(3, A.bar) != A.bar(3): + raise RuntimeError + if foobar(3, foof) != foof(3): raise RuntimeError diff --git a/Lib/python/pyinit.swg b/Lib/python/pyinit.swg index dfd3940ec..b530fba15 100644 --- a/Lib/python/pyinit.swg +++ b/Lib/python/pyinit.swg @@ -58,15 +58,12 @@ SWIG_Python_InstallConstants(PyObject *d, swig_const_info constants[]) { } } -/* -----------------------------------------------------------------------------*/ -/* Fix SwigMethods to carry the callback ptrs when needed */ -/* -----------------------------------------------------------------------------*/ +/* ----------------------------------------------------------------------------- + * Patch %callback methods' docstrings to hold the callback ptrs + * -----------------------------------------------------------------------------*/ SWIGINTERN void -SWIG_Python_FixMethods(PyMethodDef *methods, - swig_const_info *const_table, - swig_type_info **types, - swig_type_info **types_initial) { +SWIG_Python_FixMethods(PyMethodDef *methods, const swig_const_info *const_table, swig_type_info **types, swig_type_info **types_initial) { size_t i; for (i = 0; methods[i].ml_name; ++i) { const char *c = methods[i].ml_doc; @@ -74,7 +71,7 @@ SWIG_Python_FixMethods(PyMethodDef *methods, c = strstr(c, "swig_ptr: "); if (c) { int j; - swig_const_info *ci = 0; + const swig_const_info *ci = 0; const char *name = c + 10; for (j = 0; const_table[j].type; ++j) { if (strncmp(const_table[j].name, name, diff --git a/Source/Modules/python.cxx b/Source/Modules/python.cxx index 9046edcfb..119a32364 100644 --- a/Source/Modules/python.cxx +++ b/Source/Modules/python.cxx @@ -73,8 +73,10 @@ static int py3 = 0; /* C++ Support + Shadow Classes */ -static int have_constructor; -static int have_repr; +static int have_constructor = 0; +static int have_repr = 0; +static bool have_builtin_static_member_method_callback = false; +static bool have_fast_proxy_static_member_method_callback = false; static String *real_classname; /* Thread Support */ @@ -815,6 +817,10 @@ public: Append(const_code, "{0, 0, 0, 0.0, 0, 0}};\n"); Printf(f_wrappers, "%s\n", const_code); + + if (have_fast_proxy_static_member_method_callback) + Printf(f_init, " SWIG_Python_FixMethods(SwigMethods_proxydocs, swig_const_table, swig_types, swig_type_initial);\n\n"); + initialize_threads(f_init); Printf(f_init, "#if PY_VERSION_HEX >= 0x03000000\n"); @@ -2478,6 +2484,7 @@ public: Printf(methods, "\"swig_ptr: %s\"", Getattr(n, "feature:callback:name")); if (fastproxy) { Printf(methods_proxydocs, "\"swig_ptr: %s\"", Getattr(n, "feature:callback:name")); + have_fast_proxy_static_member_method_callback = true; } } else { Append(methods, "NULL"); @@ -3935,6 +3942,10 @@ public: int funpack = fastunpack; static String *tp_new = NewString("PyType_GenericNew"); + if (have_builtin_static_member_method_callback) { + Printf(f_init, " SWIG_Python_FixMethods(SwigPyBuiltin_%s_methods, swig_const_table, swig_types, swig_type_initial);\n", mname); + } + Printv(f_init, " SwigPyBuiltin_SetMetaType(builtin_pytype, metatype);\n", NIL); // We can’t statically initialize a structure member with a function defined in another C module @@ -4365,6 +4376,7 @@ public: /* Create new strings for building up a wrapper function */ have_constructor = 0; have_repr = 0; + have_builtin_static_member_method_callback = false; class_name = Getattr(n, "sym:name"); real_classname = Getattr(n, "name"); @@ -4750,6 +4762,11 @@ public: String *ds = cdocstring(n, AUTODOC_STATICFUNC); Printf(builtin_methods, " { \"%s\", (PyCFunction)(void(*)(void))%s, %s, \"%s\" },\n", symname, wname, pyflags, ds); Delete(ds); + } else if (Getattr(n, "feature:callback")) { + String *ds = NewStringf("swig_ptr: %s", Getattr(n, "feature:callback:name")); + Printf(builtin_methods, " { \"%s\", (PyCFunction)(void(*)(void))%s, %s, \"%s\" },\n", symname, wname, pyflags, ds); + Delete(ds); + have_builtin_static_member_method_callback = true; } else { Printf(builtin_methods, " { \"%s\", (PyCFunction)(void(*)(void))%s, %s, \"\" },\n", symname, wname, pyflags); } From 2272d00c1a60ea6f3710e4d9dc17746b9df69780 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Fri, 14 Jan 2022 23:58:40 +0000 Subject: [PATCH 082/662] Add Python testcase for testing flatstaticmethod syntax For testing legacy flattened static method access for when issue #2137 is applied. --- Examples/test-suite/python/Makefile.in | 3 +- Examples/test-suite/python/callback_runme.py | 3 - .../python/python_flatstaticmethod_runme.py | 85 +++++++++++++++++++ Examples/test-suite/python_flatstaticmethod.i | 36 ++++++++ 4 files changed, 123 insertions(+), 4 deletions(-) create mode 100644 Examples/test-suite/python/python_flatstaticmethod_runme.py create mode 100644 Examples/test-suite/python_flatstaticmethod.i diff --git a/Examples/test-suite/python/Makefile.in b/Examples/test-suite/python/Makefile.in index 0bdbad51e..a5f2670d8 100644 --- a/Examples/test-suite/python/Makefile.in +++ b/Examples/test-suite/python/Makefile.in @@ -54,6 +54,7 @@ CPP_TEST_CASES += \ python_director \ python_docstring \ python_extranative \ + python_flatstaticmethod \ python_moduleimport \ python_overload_simple_cast \ python_pickle \ @@ -97,7 +98,7 @@ LIBS = -L. VALGRIND_OPT += --suppressions=pythonswig.supp # Custom tests - tests with additional commandline options -# none! +#python_flatstaticmethod.cpptest: SWIGOPT += -flatstaticmethod # Rules for the different types of tests %.cpptest: diff --git a/Examples/test-suite/python/callback_runme.py b/Examples/test-suite/python/callback_runme.py index 19f61c96b..dbf957cbb 100644 --- a/Examples/test-suite/python/callback_runme.py +++ b/Examples/test-suite/python/callback_runme.py @@ -17,9 +17,6 @@ if foobar(3, _callback.foo) != foo(3): if foobar(3, foo) != foo(3): raise RuntimeError -if foobar(3, A_bar) != A_bar(3): - raise RuntimeError - if foobar(3, A.bar) != A.bar(3): raise RuntimeError diff --git a/Examples/test-suite/python/python_flatstaticmethod_runme.py b/Examples/test-suite/python/python_flatstaticmethod_runme.py new file mode 100644 index 000000000..f34670013 --- /dev/null +++ b/Examples/test-suite/python/python_flatstaticmethod_runme.py @@ -0,0 +1,85 @@ +from python_flatstaticmethod import * +import inspect + +# This testcase tests C++ class static functions when using legacy "flattened" +# staticmethod access, A_bar, as well as the normal staticmethod access, A.bar. + + +def check(got, expected): + if got != expected: + raise RuntimeError("\ngot :{}\nwant:{}\n".format(got, expected)) + +if A_bar(2) != 4: + raise RuntimeError + +if A.bar(2) != 4: + raise RuntimeError + +# %callback +if foobar(3, A_bar) != A_bar(3): + raise RuntimeError + +if foobar(3, A.bar) != A_bar(3): + raise RuntimeError + +# kwargs +if A_pub() != 1: + raise RuntimeError + +if A_pub(b=2) != 3: + raise RuntimeError + +if A_pub(b=10,a=20) != 30: + raise RuntimeError + +if A.pub() != 1: + raise RuntimeError + +if A.pub(b=2) != 3: + raise RuntimeError + +if A.pub(b=10,a=20) != 30: + raise RuntimeError + +check(inspect.getdoc(A_func0static), + "A_func0static(e, arg2, hello, f=2) -> int") +check(inspect.getdoc(A_func1static), + "A_func1static(A e, short arg2, Tuple hello, double f=2) -> int") + +# overloaded static functions +if A_over(3) != "over:int": + raise RuntimeError("A::over(int)") + +if A_over(3.0) != "over:double": + raise RuntimeError("A::over(double)") + +if A_over("hello") != "over:char *": + raise RuntimeError("A::over(char *)") + +if A.over(3) != "over:int": + raise RuntimeError("A::over(int)") + +if A.over(3.0) != "over:double": + raise RuntimeError("A::over(double)") + +if A.over("hello") != "over:char *": + raise RuntimeError("A::over(char *)") + +# default args +if A_defargs() != 30: + raise RuntimeError + +if A_defargs(1) != 21: + raise RuntimeError + +if A_defargs(1, 2) != 3: + raise RuntimeError + +if A.defargs() != 30: + raise RuntimeError + +if A.defargs(1) != 21: + raise RuntimeError + +if A.defargs(1, 2) != 3: + raise RuntimeError diff --git a/Examples/test-suite/python_flatstaticmethod.i b/Examples/test-suite/python_flatstaticmethod.i new file mode 100644 index 000000000..c0de7d298 --- /dev/null +++ b/Examples/test-suite/python_flatstaticmethod.i @@ -0,0 +1,36 @@ +%module python_flatstaticmethod + +// This testcase tests C++ class static functions when using legacy "flattened" +// staticmethod access, A_bar, as well as the normal staticmethod access, A.bar. + +%callback(1) A::bar; +%feature("kwargs") A::pub; +%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]"; + +%inline %{ + struct A { + static int bar(int a) { + return 2*a; + } + static int pub(int a = 1, int b = 0) { + return a + b; + } + static int func0static(A *e, short, int c, int d, double f = 2) { return 0; } + static int func1static(A *e, short, int c, int d, double f = 2) { return 0; } + + static const char *over(int) { return "over:int"; } + static const char *over(double) { return "over:double"; } + static const char *over(char *) { return "over:char *"; } + + static int defargs(int xx = 10, int yy = 20) { return xx + yy; } + }; + + extern "C" int foobar(int a, int (*pf)(int a)) { + return pf(a); + } +%} + From 0fbf23a77be9859a587af2900b863aa5fdc5c788 Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Sun, 16 Jan 2022 12:35:41 +1300 Subject: [PATCH 083/662] Fix PHP docs formatting issue --- Doc/Manual/Php.html | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Doc/Manual/Php.html b/Doc/Manual/Php.html index 8f8ab39c4..813368ec3 100644 --- a/Doc/Manual/Php.html +++ b/Doc/Manual/Php.html @@ -746,7 +746,10 @@ class Ko { }; -would be executed in PHP as, +

    +would be executed in PHP as +

    +
     Ko::threats();
     
    From a5774a9d0f307f4c650c9999f53efc692ed95ddf Mon Sep 17 00:00:00 2001 From: Markus Friedrich Date: Sun, 16 Jan 2022 09:58:25 +0100 Subject: [PATCH 084/662] Fixed octave version check and enabled VPATH build for check-octave-operator example --- Examples/octave/operator/runme.m | 3 +++ Lib/octave/octrun.swg | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/Examples/octave/operator/runme.m b/Examples/octave/operator/runme.m index 4aad26064..d88dcff0b 100644 --- a/Examples/octave/operator/runme.m +++ b/Examples/octave/operator/runme.m @@ -3,6 +3,9 @@ if exist("crash_dumps_octave_core", "builtin") crash_dumps_octave_core(0); endif +scriptDir = fileparts(mfilename('fullpath')); +addpath(scriptDir); + # Operator overloading example swigexample diff --git a/Lib/octave/octrun.swg b/Lib/octave/octrun.swg index b8e80957b..d94056c8c 100644 --- a/Lib/octave/octrun.swg +++ b/Lib/octave/octrun.swg @@ -812,7 +812,7 @@ SWIGRUNTIME void swig_acquire_ownership_obj(void *vptr, int own); return as_value(); } -#if SWIG_OCTAVE_PREREQ(6,0,0) +#if SWIG_OCTAVE_PREREQ(4,4,0) virtual bool isobject() const { #else virtual bool is_object() const { From d0121bff6ec45a2bdffb2d6d2a1889d49038feb0 Mon Sep 17 00:00:00 2001 From: Markus Friedrich Date: Sun, 16 Jan 2022 22:13:09 +0100 Subject: [PATCH 085/662] Use a different assert in octave check 'module_path' for some octave version MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Octave >= 4.4 < 6 seem to handle the SWIG generated .oct files differently. Before the .oct file e.g. swigexample.oct is loaded exists('swigexample') returns 3 (name is a ‘.oct’ or ‘.mex’ file in Octave’s path.) After loading swigexample.oct exists('swigexample') returns 1 (name is a variable.) Whereas all other octave version return always 3. isglobal('swigexample') return always true. --- Examples/octave/module_load/runme.m | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/Examples/octave/module_load/runme.m b/Examples/octave/module_load/runme.m index beab1213b..b0c4dc275 100644 --- a/Examples/octave/module_load/runme.m +++ b/Examples/octave/module_load/runme.m @@ -19,7 +19,12 @@ clear all # load module in a function globally before base context clear all; function testme_1 - assert(exist("swigexample") == 3); + if compare_versions(version(), '4.4', '>=') && compare_versions(version(), '6', '<') + % in octave >= 4.4 < 6 'swigexample' is recognized as variable (1) instead of a .oct file (3) on the second call of 'swigexample' + assert(exist("swigexample") == 3 || exist("swigexample") == 1); + else + assert(exist("swigexample") == 3); + end swigexample; assert(isglobal("swigexample")); assert(cvar.ivar == ifunc); @@ -32,7 +37,12 @@ assert(isglobal("swigexample")); assert(cvar.ivar == ifunc); clear all function testme_2 - assert(exist("swigexample") == 3); + if compare_versions(version(), '4.4', '>=') && compare_versions(version(), '6', '<') + % in octave >= 4.4 < 6 'swigexample' is recognized as variable (1) instead of a .oct file (3) on the second call of 'swigexample' + assert(exist("swigexample") == 3 || exist("swigexample") == 1); + else + assert(exist("swigexample") == 3); + end swigexample; assert(isglobal("swigexample")); assert(cvar.ivar == ifunc); @@ -52,7 +62,12 @@ swigexample; assert(isglobal("swigexample")); assert(cvar.ivar == ifunc); function testme_3 - assert(exist("swigexample") == 3); + if compare_versions(version(), '4.4', '>=') && compare_versions(version(), '6', '<') + % in octave >= 4.4 < 6 'swigexample' is recognized as variable (1) instead of a .oct file (3) on the second call of 'swigexample' + assert(exist("swigexample") == 3 || exist("swigexample") == 1); + else + assert(exist("swigexample") == 3); + end swigexample; assert(isglobal("swigexample")); assert(cvar.ivar == ifunc); @@ -65,7 +80,12 @@ swigexample; assert(isglobal("swigexample")); assert(cvar.ivar == ifunc); function testme_4 - assert(exist("swigexample") == 3); + if compare_versions(version(), '4.4', '>=') && compare_versions(version(), '6', '<') + % in octave >= 4.4 < 6 'swigexample' is recognized as variable (1) instead of a .oct file (3) on the second call of 'swigexample' + assert(exist("swigexample") == 3 || exist("swigexample") == 1); + else + assert(exist("swigexample") == 3); + end swigexample; assert(isglobal("swigexample")); assert(cvar.ivar == ifunc); From 45c125593376adc5e4c8d0bcaa6e98905c9838c2 Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Tue, 18 Jan 2022 13:56:07 +1300 Subject: [PATCH 086/662] Fix missing HTML escaping in Octave docs --- Doc/Manual/Octave.html | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/Doc/Manual/Octave.html b/Doc/Manual/Octave.html index bdef5db7c..151957cff 100644 --- a/Doc/Manual/Octave.html +++ b/Doc/Manual/Octave.html @@ -570,13 +570,13 @@ __mul__ a * b __div__ a / b __pow__ a ^ b __ldiv__ a \ b -__lshift__ a << b -__rshift__ a >> b -__lt__ a < b -__le__ a <= b +__lshift__ a << b +__rshift__ a >> b +__lt__ a < b +__le__ a <= b __eq__ a == b -__ge__ a >= b -__gt__ a > b +__ge__ a >= b +__gt__ a > b __ne__ a != b __el_mul__ a .* b __el_div__ a ./ b @@ -598,16 +598,16 @@ On the C++ side, the default mappings are as follows: %rename(__mul__) *::operator*; %rename(__div__) *::operator/; %rename(__mod__) *::operator%; -%rename(__lshift__) *::operator<<; -%rename(__rshift__) *::operator>>; +%rename(__lshift__) *::operator<<; +%rename(__rshift__) *::operator>>; %rename(__el_and__) *::operator&&; %rename(__el_or__) *::operator||; %rename(__xor__) *::operator^; %rename(__invert__) *::operator~; -%rename(__lt__) *::operator<; -%rename(__le__) *::operator<=; -%rename(__gt__) *::operator>; -%rename(__ge__) *::operator>=; +%rename(__lt__) *::operator<; +%rename(__le__) *::operator<=; +%rename(__gt__) *::operator>; +%rename(__ge__) *::operator>=; %rename(__eq__) *::operator==; %rename(__ne__) *::operator!=; %rename(__not__) *::operator!; @@ -634,7 +634,7 @@ You can use it to define special behavior, like for example defining Octave oper %extend A { string __str__() { stringstream sout; - sout<<$self->value; + sout<<$self->value; return sout.str(); } } From c839066405d0700bdd17d7669eff623dab8fd928 Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Tue, 18 Jan 2022 14:51:55 +1300 Subject: [PATCH 087/662] [perl] Document explicitly not to use %OWNER directly See #1771 --- Doc/Manual/Perl5.html | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/Doc/Manual/Perl5.html b/Doc/Manual/Perl5.html index 85c2545cf..9f2e08ba4 100644 --- a/Doc/Manual/Perl5.html +++ b/Doc/Manual/Perl5.html @@ -2651,8 +2651,8 @@ constructors and destructors for the package and are always named "new" and "DESTROY". The constructor always returns a tied hash table. This hash table is used to access the member variables of a structure in addition to being able to invoke member functions. The -%OWNER and %BLESSEDMEMBERS hash tables are used -internally and described shortly. +%OWNER and %BLESSEDMEMBERS hash tables are +implementation details used internally and described shortly.

    @@ -2740,8 +2740,15 @@ to a C function that remembers the object, and then destroy the corresponding Perl object (this situation turns out to come up frequently when constructing objects like linked lists and trees). When C takes possession of an object, you can change Perl's ownership -by simply deleting the object from the %OWNER hash. This is -done using the DISOWN method. +by calling the DISOWN method (which will delete the object +from the internal %OWNER hash). +

    + +

    +The %OWNER hash is an implementation detail, discussed here +only to help clarify the operation of ACQUIRE and DISOWN. +You should not access %OWNER directly - the details of how it +works (and possibly even its existence) may chance in future SWIG versions.

    
    From c8645aab9ec227f5436bf8a061cc7a20f5a47717 Mon Sep 17 00:00:00 2001
    From: William S Fulton 
    Date: Sun, 16 Jan 2022 11:09:11 +0000
    Subject: [PATCH 088/662] Ensure GHA fails when testflags.py fails
    
    ---
     .github/workflows/ci.yml | 4 ++--
     1 file changed, 2 insertions(+), 2 deletions(-)
    
    diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
    index c4212a42c..1e8faff7d 100644
    --- a/.github/workflows/ci.yml
    +++ b/.github/workflows/ci.yml
    @@ -436,8 +436,8 @@ jobs:
                 esac
     
                 # Stricter compile flags for examples. Various headers and SWIG generated code prevents full use of -pedantic.
    -            cflags=$($GITHUB_WORKSPACE/Tools/testflags.py --language $SWIGLANG --cflags --std=$CSTD --compiler=$CC) && echo $cflags
    -            cxxflags=$($GITHUB_WORKSPACE/Tools/testflags.py --language $SWIGLANG --cxxflags --std=$CPPSTD --compiler=$CC) && echo $cxxflags
    +            cflags=$($GITHUB_WORKSPACE/Tools/testflags.py --language $SWIGLANG --cflags --std=$CSTD --compiler=$CC)
    +            cxxflags=$($GITHUB_WORKSPACE/Tools/testflags.py --language $SWIGLANG --cxxflags --std=$CPPSTD --compiler=$CC)
                 make check-$SWIGLANG-version
                 make check-$SWIGLANG-enabled
                 make $SWIGJOBS check-$SWIGLANG-examples CFLAGS="$cflags" CXXFLAGS="$cxxflags"
    
    From 8c608d646c611820ad58c85315f23b4499331de7 Mon Sep 17 00:00:00 2001
    From: William S Fulton 
    Date: Tue, 18 Jan 2022 20:14:38 +0000
    Subject: [PATCH 089/662] Fix Appveyor mingw builds - install autotools
    
    ---
     appveyor.yml | 2 +-
     1 file changed, 1 insertion(+), 1 deletion(-)
    
    diff --git a/appveyor.yml b/appveyor.yml
    index 07c4fac28..5eaa77b2f 100644
    --- a/appveyor.yml
    +++ b/appveyor.yml
    @@ -131,7 +131,7 @@ install:
     - if "%OSVARIANT%"=="" bash -c "which csc.exe"
     - if "%OSVARIANT%"=="" bash -c "csc.exe /? | head -n 1"
     - if "%OSVARIANT%"=="cygwin" %CYGWINSETUP% --quiet-mode --packages python2-devel,libpcre-devel,libboost-devel > cygwin-install.txt || bash -c "cat cygwin-install.txt"
    -- if "%OSVARIANT%"=="mingw" bash -c "pacman --noconfirm --sync mingw%MBITS%/mingw-w64-%MARCH%-pcre mingw%MBITS%/mingw-w64-%MARCH%-boost"
    +- if "%OSVARIANT%"=="mingw" bash -c "pacman --noconfirm --sync mingw%MBITS%/mingw-w64-%MARCH%-autotools mingw%MBITS%/mingw-w64-%MARCH%-pcre mingw%MBITS%/mingw-w64-%MARCH%-boost"
     - if not "%WITHLANG%"=="" set SWIGWITHLANG==%WITHLANG%
     - if not "%WITHLANG%"=="" where %WITHLANG%
     - bash -c "which $CC"
    
    From 748a9a5452568b90edba7162e5b9376d4837529d Mon Sep 17 00:00:00 2001
    From: Olly Betts 
    Date: Tue, 18 Jan 2022 15:36:37 +1300
    Subject: [PATCH 090/662] [perl] Require at least Perl 5.8.0
    
    As discussed and agreed in #1629, it's become hard to test with Perl
    5.6 or earlier, such old versions are no longer in active use, and
    4.1.0 is an appropriate time to make such a change.
    
    I've dropped the compatibility code that was obvious to me, but there's
    probably more that can be cleaned up now.
    ---
     CHANGES.current                               |  3 +
     Doc/Manual/Perl5.html                         |  9 ++-
     .../perl5/operator_overload_break_runme.pl    | 11 +---
     .../perl5/operator_overload_runme.pl          | 29 +++------
     .../test-suite/perl5/packageoption_runme.pl   |  9 ---
     Lib/perl5/perlhead.swg                        | 28 +--------
     Lib/perl5/perlinit.swg                        |  4 --
     Lib/perl5/perlrun.swg                         | 62 ++++---------------
     RELEASENOTES                                  |  1 +
     Source/Modules/perl5.cxx                      |  7 ---
     configure.ac                                  |  2 +-
     11 files changed, 34 insertions(+), 131 deletions(-)
    
    diff --git a/CHANGES.current b/CHANGES.current
    index b6c21643b..5aa435e15 100644
    --- a/CHANGES.current
    +++ b/CHANGES.current
    @@ -7,6 +7,9 @@ the issue number to the end of the URL: https://github.com/swig/swig/issues/
     Version 4.1.0 (in progress)
     ===========================
     
    +2022-01-18: olly
    +	    [Perl] #1629 Perl 5.8.0 is now the oldest version we aim to support.
    +
     2022-01-14: wsfulton
                 [Python] Fix %callback and specifying the callback function as a
                 static member function using Python staticmethod syntax, such as
    diff --git a/Doc/Manual/Perl5.html b/Doc/Manual/Perl5.html
    index 9f2e08ba4..03dcfe6bb 100644
    --- a/Doc/Manual/Perl5.html
    +++ b/Doc/Manual/Perl5.html
    @@ -91,10 +91,10 @@
     

    This chapter describes SWIG's support of Perl5. Although the Perl5 module is one of the earliest SWIG modules, it has continued to evolve -and has been improved greatly with the help of SWIG users. For the -best results, it is recommended that SWIG be used with Perl 5.8 or -later. We're no longer testing regularly with older versions, but -Perl 5.6 seems to mostly work, while older versions don't. +and has been improved greatly with the help of SWIG users. As of SWIG +4.1.0, the minimum version of Perl we aim to support is Perl 5.8.0. +We can no longer easily test with older versions, and they no longer +seem to be in active use.

    31.1 Overview

    @@ -680,7 +680,6 @@ files(s) field". installation under "Additional include directories".
  • Define the symbols WIN32 and MSWIN32 under preprocessor options. -If using the ActiveWare port, also define the symbol PERL_OBJECT. Note that all extensions to the ActiveWare port must be compiled with the C++ compiler since Perl has been encapsulated in a C++ class. diff --git a/Examples/test-suite/perl5/operator_overload_break_runme.pl b/Examples/test-suite/perl5/operator_overload_break_runme.pl index fd3fe3303..c692dfac7 100644 --- a/Examples/test-suite/perl5/operator_overload_break_runme.pl +++ b/Examples/test-suite/perl5/operator_overload_break_runme.pl @@ -4,15 +4,6 @@ use Test::More tests => 9; use operator_overload_break; -# Workaround for -# ok( not (expression) , "test description" ); -# does not working in older versions of Perl, eg 5.004_04 -sub ok_not ($;$) { - my($test, $name) = @_; - $test = not $test; - ok($test, $name); -} - pass("loaded"); my $op = operator_overload_break::Op->new(5); @@ -32,7 +23,7 @@ $op->{k} = 22; ok((10 == (32 - $op)), "reversed subtraction"); -ok_not((3 == $op), +ok(not(3 == $op), 'not equal'); $op->{k} = 3; diff --git a/Examples/test-suite/perl5/operator_overload_runme.pl b/Examples/test-suite/perl5/operator_overload_runme.pl index ba3f33a64..43a77a961 100644 --- a/Examples/test-suite/perl5/operator_overload_runme.pl +++ b/Examples/test-suite/perl5/operator_overload_runme.pl @@ -4,15 +4,6 @@ use Test::More tests => 39; use operator_overload; -# Workaround for -# ok( not (expression) , "test description" ); -# does not working in older versions of Perl, eg 5.004_04 -sub ok_not ($;$) { - my($test, $name) = @_; - $test = not $test; - ok($test, $name); -} - pass("loaded"); # first check all the operators are implemented correctly from pure C++ code @@ -30,7 +21,7 @@ isa_ok($op2, "operator_overload::Op"); $op->{i} = 5; $op2->{i} = 3; -ok_not(($op == $op2), "operator equal: not equal"); +ok(not($op == $op2), "operator equal: not equal"); $op->{i} = 3; ok(($op == $op2), "operator equal: equal"); @@ -42,7 +33,7 @@ $op2->{i} = 3; ok(($op != $op2), "operator not equal: not equal"); $op->{i} = 3; -ok_not(($op != $op2), "operator not equal: equal"); +ok(not($op != $op2), "operator not equal: equal"); # stringify operator $op->{i} = 3; @@ -99,16 +90,16 @@ is($op3->{i}, 2, "operator modulus"); $op->{i} = 8; $op2->{i} = 3; ok($op > $op2, "operator greater than"); -ok_not(($op2 > $op), "operator greater than"); +ok(not($op2 > $op), "operator greater than"); $op->{i} = 3; -ok_not(($op2 > $op), "operator greater than"); -ok_not(($op > $op2), "operator greater than"); +ok(not($op2 > $op), "operator greater than"); +ok(not($op > $op2), "operator greater than"); # greater than or equal operator $op->{i} = 8; $op2->{i} = 3; ok($op >= $op2, "operator greater than or equal"); -ok_not(($op2 >= $op), "operator greater than or equal"); +ok(not($op2 >= $op), "operator greater than or equal"); $op->{i} = 3; ok(($op2 >= $op), "operator greater than or equal"); ok(($op >= $op2), "operator greater than or equal"); @@ -117,16 +108,16 @@ ok(($op >= $op2), "operator greater than or equal"); $op2->{i} = 8; $op->{i} = 3; ok($op < $op2, "operator lesser than"); -ok_not(($op2 < $op), "operator lesser than"); +ok(not($op2 < $op), "operator lesser than"); $op2->{i} = 3; -ok_not(($op2 < $op), "operator lesser than"); -ok_not(($op < $op2), "operator lesser than"); +ok(not($op2 < $op), "operator lesser than"); +ok(not($op < $op2), "operator lesser than"); # less than or equal operator $op2->{i} = 8; $op->{i} = 3; ok($op <= $op2, "operator lesser than or equal"); -ok_not(($op2 <= $op), "operator lesser than or equal"); +ok(not($op2 <= $op), "operator lesser than or equal"); $op2->{i} = 3; ok(($op2 <= $op), "operator less than or equal"); ok(($op <= $op2), "operator less than or equal"); diff --git a/Examples/test-suite/perl5/packageoption_runme.pl b/Examples/test-suite/perl5/packageoption_runme.pl index d94a7a1fd..02e95f7a8 100644 --- a/Examples/test-suite/perl5/packageoption_runme.pl +++ b/Examples/test-suite/perl5/packageoption_runme.pl @@ -5,15 +5,6 @@ use Test::More tests => 4; BEGIN { use_ok('packageoption_a'); } BEGIN { use_ok('packageoption_b'); } -# Workaround for -# ok( not (expression) , "test description" ); -# does not working in older versions of Perl, eg 5.004_04 -sub ok_not ($;$) { - my($test, $name) = @_; - $test = not $test; - ok($test, $name); -} - my $a = CommonPackage::A->new(); isa_ok($a, 'CommonPackage::A'); diff --git a/Lib/perl5/perlhead.swg b/Lib/perl5/perlhead.swg index 5437af5a5..bb7c1741d 100644 --- a/Lib/perl5/perlhead.swg +++ b/Lib/perl5/perlhead.swg @@ -8,22 +8,9 @@ extern "C" { #include "perl.h" #include "XSUB.h" -/* Add in functionality missing in older versions of Perl. Much of this is based on Devel-PPPort on cpan. */ - -/* Add PERL_REVISION, PERL_VERSION, PERL_SUBVERSION if missing */ -#ifndef PERL_REVISION -# if !defined(__PATCHLEVEL_H_INCLUDED__) && !(defined(PATCHLEVEL) && defined(SUBVERSION)) -# define PERL_PATCHLEVEL_H_IMPLICIT -# include -# endif -# if !(defined(PERL_VERSION) || (defined(SUBVERSION) && defined(PATCHLEVEL))) -# include -# endif -# ifndef PERL_REVISION -# define PERL_REVISION (5) -# define PERL_VERSION PATCHLEVEL -# define PERL_SUBVERSION SUBVERSION -# endif +/* PERL_REVISION was added in Perl 5.6. */ +#if !defined PERL_REVISION || (PERL_REVISION-0 == 5 && PERL_VERSION-0 < 8) +# error SWIG requires Perl >= 5.8.0 #endif #if defined(WIN32) && defined(PERL_OBJECT) && !defined(PerlIO_exportFILE) @@ -38,15 +25,6 @@ extern "C" { # define SvUOK(sv) SvIOK_UV(sv) #endif -#if ((PERL_VERSION < 4) || ((PERL_VERSION == 4) && (PERL_SUBVERSION <= 5))) -# define PL_sv_undef sv_undef -# define PL_na na -# define PL_errgv errgv -# define PL_sv_no sv_no -# define PL_sv_yes sv_yes -# define PL_markstack_ptr markstack_ptr -#endif - #ifndef IVSIZE # ifdef LONGSIZE # define IVSIZE LONGSIZE diff --git a/Lib/perl5/perlinit.swg b/Lib/perl5/perlinit.swg index b49040d26..c26b93fad 100644 --- a/Lib/perl5/perlinit.swg +++ b/Lib/perl5/perlinit.swg @@ -4,15 +4,11 @@ #ifdef __cplusplus extern "C" #endif -#ifndef PERL_OBJECT #ifndef MULTIPLICITY SWIGEXPORT void SWIG_init (CV* cv); #else SWIGEXPORT void SWIG_init (pTHXo_ CV* cv); #endif -#else -SWIGEXPORT void SWIG_init (CV *cv, CPerlObj *); -#endif %} /* Module initialization function */ diff --git a/Lib/perl5/perlrun.swg b/Lib/perl5/perlrun.swg index b04002f5d..28703d1a6 100644 --- a/Lib/perl5/perlrun.swg +++ b/Lib/perl5/perlrun.swg @@ -6,13 +6,8 @@ * type checking. * ----------------------------------------------------------------------------- */ -#ifdef PERL_OBJECT -#define SWIG_PERL_OBJECT_DECL CPerlObj *SWIGUNUSEDPARM(pPerl), -#define SWIG_PERL_OBJECT_CALL pPerl, -#else #define SWIG_PERL_OBJECT_DECL #define SWIG_PERL_OBJECT_CALL -#endif /* Common SWIG API */ @@ -88,31 +83,11 @@ extern "C" { #endif /* Macro to call an XS function */ -#ifdef PERL_OBJECT -# define SWIG_CALLXS(_name) _name(cv,pPerl) -#else -# ifndef MULTIPLICITY -# define SWIG_CALLXS(_name) _name(cv) -# else -# define SWIG_CALLXS(_name) _name(PERL_GET_THX, cv) -# endif -#endif - -#ifdef PERL_OBJECT -#define MAGIC_PPERL CPerlObj *pPerl = (CPerlObj *) this; - -#ifdef __cplusplus -extern "C" { +#ifndef MULTIPLICITY +# define SWIG_CALLXS(_name) _name(cv) +#else +# define SWIG_CALLXS(_name) _name(PERL_GET_THX, cv) #endif -typedef int (CPerlObj::*SwigMagicFunc)(SV *, MAGIC *); -#ifdef __cplusplus -} -#endif - -#define SWIG_MAGIC(a,b) (SV *a, MAGIC *b) -#define SWIGCLASS_STATIC - -#else /* PERL_OBJECT */ #define MAGIC_PPERL #define SWIGCLASS_STATIC static SWIGUNUSED @@ -141,24 +116,14 @@ typedef int (*SwigMagicFunc)(struct interpreter *, SV *, MAGIC *); #endif #endif /* MULTIPLICITY */ -#endif /* PERL_OBJECT */ -# ifdef PERL_OBJECT -# define SWIG_croak_null() SWIG_Perl_croak_null(pPerl) -static void SWIGUNUSED SWIG_Perl_croak_null(CPerlObj *pPerl) -# else static void SWIGUNUSED SWIG_croak_null() -# endif { SV *err = get_sv("@", GV_ADD); -# if (PERL_VERSION < 6) - croak("%_", err); -# else if (sv_isobject(err)) croak(0); else croak("%s", SvPV_nolen(err)); -# endif } @@ -462,20 +427,15 @@ typedef struct { } swig_variable_info; /* Magic variable code */ -#ifndef PERL_OBJECT -# ifdef __cplusplus +#ifdef __cplusplus # define swig_create_magic(s,a,b,c) _swig_create_magic(s,const_cast(a),b,c) -# else -# define swig_create_magic(s,a,b,c) _swig_create_magic(s,(char*)(a),b,c) -# endif -# ifndef MULTIPLICITY -SWIGRUNTIME void _swig_create_magic(SV *sv, char *name, int (*set)(SV *, MAGIC *), int (*get)(SV *,MAGIC *)) -# else -SWIGRUNTIME void _swig_create_magic(SV *sv, char *name, int (*set)(struct interpreter*, SV *, MAGIC *), int (*get)(struct interpreter*, SV *,MAGIC *)) -# endif #else -# define swig_create_magic(s,a,b,c) _swig_create_magic(pPerl,s,a,b,c) -SWIGRUNTIME void _swig_create_magic(CPerlObj *pPerl, SV *sv, const char *name, int (CPerlObj::*set)(SV *, MAGIC *), int (CPerlObj::*get)(SV *, MAGIC *)) +# define swig_create_magic(s,a,b,c) _swig_create_magic(s,(char*)(a),b,c) +#endif +#ifndef MULTIPLICITY +SWIGRUNTIME void _swig_create_magic(SV *sv, char *name, int (*set)(SV *, MAGIC *), int (*get)(SV *,MAGIC *)) +#else +SWIGRUNTIME void _swig_create_magic(SV *sv, char *name, int (*set)(struct interpreter*, SV *, MAGIC *), int (*get)(struct interpreter*, SV *,MAGIC *)) #endif { MAGIC *mg; diff --git a/RELEASENOTES b/RELEASENOTES index c05ccc4ec..3a596dd46 100644 --- a/RELEASENOTES +++ b/RELEASENOTES @@ -10,6 +10,7 @@ published on the SWIG web site at http://swig.org/release.html. SWIG-4.1.0 summary: - Add PHP 8 support. - PHP wrapping is now done entirely via PHP's C API - no more .php wrapper. +- Perl 5.8.0 is now the oldest version SWIG supports. - GitHub Actions is now used instead of Travis CI for continuous integration. SWIG-4.0.2 summary: diff --git a/Source/Modules/perl5.cxx b/Source/Modules/perl5.cxx index e87f9f310..459d403bf 100644 --- a/Source/Modules/perl5.cxx +++ b/Source/Modules/perl5.cxx @@ -445,13 +445,7 @@ public: Printv(magic, "#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n", - "#ifdef PERL_OBJECT\n", - "#define MAGIC_CLASS _wrap_", underscore_module, "_var::\n", - "class _wrap_", underscore_module, "_var : public CPerlObj {\n", - "public:\n", - "#else\n", "#define MAGIC_CLASS\n", - "#endif\n", "SWIGCLASS_STATIC int swig_magic_readonly(pTHX_ SV *SWIGUNUSEDPARM(sv), MAGIC *SWIGUNUSEDPARM(mg)) {\n", tab4, "MAGIC_PPERL\n", tab4, "croak(\"Value is read-only.\");\n", tab4, "return 0;\n", "}\n", NIL); @@ -470,7 +464,6 @@ public: /* Dump out variable wrappers */ - Printv(magic, "\n\n#ifdef PERL_OBJECT\n", "};\n", "#endif\n", NIL); Printv(magic, "\n#ifdef __cplusplus\n}\n#endif\n", NIL); Printf(f_header, "%s\n", magic); diff --git a/configure.ac b/configure.ac index 8073bfdb3..ed836205f 100644 --- a/configure.ac +++ b/configure.ac @@ -983,7 +983,7 @@ else # First figure out what the name of Perl5 is if test "x$PERLBIN" = xyes; then -AC_CHECK_PROGS(PERL, perl perl5.6.1 perl5.6.0 perl5.004 perl5.003 perl5.002 perl5.001 perl5 perl) +AC_CHECK_PROGS(PERL, perl perl5) else PERL="$PERLBIN" fi From 76d5a9ec270a763c892ae28070e391cf99e0b7cd Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Tue, 18 Jan 2022 21:37:02 +0000 Subject: [PATCH 091/662] gcc-12 warning fix in test-case Closes #2145 --- Examples/test-suite/nested_class.i | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Examples/test-suite/nested_class.i b/Examples/test-suite/nested_class.i index b10c33949..c778a12cf 100644 --- a/Examples/test-suite/nested_class.i +++ b/Examples/test-suite/nested_class.i @@ -201,7 +201,7 @@ struct Outer { Integer xx; } MultipleInstanceAnonDerived1, MultipleInstanceAnonDerived2, *MultipleInstanceAnonDerived3, MultipleInstanceAnonDerived4[2]; -#if defined(__GNUC__) || defined(_MSC_VER) || defined(SWIG) +#if (defined(__GNUC__) && __GNUC__ < 12) || defined(_MSC_VER) || defined(SWIG) /* some compilers do not accept these */ struct : public InnerMultiple { Integer xx; From 1f1349741fbe34a1d4444d5158a34ae34b70bbb9 Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Thu, 20 Jan 2022 10:07:44 +1300 Subject: [PATCH 092/662] [php] Generate PHP type declarations We now automatically generate PHP type declarations for PHP >= 8.0. The generated code still compiles with PHP 7.x but without type declarations. --- Doc/Manual/Php.html | 73 ++++ Examples/test-suite/li_factory.i | 3 +- Examples/test-suite/php/argout_runme.php | 13 +- Examples/test-suite/php/li_factory_runme.php | 3 + Lib/php/factory.i | 2 +- Lib/php/php.swg | 135 +++--- Lib/php/phppointers.i | 36 +- Lib/php/phprun.swg | 21 + Lib/php/std_string.i | 10 +- Lib/php/typemaps.i | 20 +- Lib/php/utils.i | 6 +- Source/Modules/php.cxx | 410 ++++++++++++++----- 12 files changed, 536 insertions(+), 196 deletions(-) diff --git a/Doc/Manual/Php.html b/Doc/Manual/Php.html index 813368ec3..a887471f3 100644 --- a/Doc/Manual/Php.html +++ b/Doc/Manual/Php.html @@ -346,6 +346,79 @@ $c = bar(3.5); # Use default argument for 2nd parameter
  • +

    +SWIG generates PHP type declarations for function parameters and return +types for PHP 8 and later (we don't try to support PHP 7's more limited type +declarations and the generated wrappers compiled for PHP 7 will not have any +type declarations). +

    + +

    +You can control the generation of PHP type declarations using +the "php:type" %feature. This has three settings: +

    + +
      +
    • If unset or set to "0" then no type declarations are generated, e.g.: %feature("php:type", "0"); +

    • +
    • If set to "1" then type declarations are generated for both parameters and return types, e.g.: %feature("php:type", "1"); +

    • +
    • The default setting is "compat", which is the same as "1" except no + return type declarations are generated for virtual methods for which + directors are enabled. This provides better compatibility for PHP + subclasses of wrapped virtual methods in existing SWIG-generated bindings, e.g.: %feature("php:type", "compat"); +

    • +
    + +

    +If you have an existing PHP interface and are upgrading to SWIG >= 4.1.0 +then the default "compat" setting should work well. +

    + +

    +If you're writing a new set of bindings and only targetting PHP8 or newer +then enabling type declarations everywhere probably makes sense. It will +only actually make a difference if you enable directors and are wrapping C++ +classes with virtual methods, but doing it anyway means you won't forget to if +the code you are wrapping later evolves to have such classes and methods. +

    + +

    +The type declaration information will make the generated source code and +compiler extension module larger, so you might want to turn off type +declarations if keeping these small is important to you. If you find you +need to turn off type declarations to fix a problem, please let us know +via our github issue tracker. +

    + +

    +Note that being a SWIG feature this can be specified globally (like above) or +per class, per method, etc. See the %feature directives +section for full details of how to control at a fine-grained level. +

    + +

    +The PHP type information is specified via a "phptype" attribute on "in" and +"out" typemaps, and these have been added for all the typemaps we supply for +PHP. We don't currently support this for "argout" templates, but probably +will in a future version. +

    + +

    +If you have written custom SWIG typemaps for PHP and want to add PHP type +declarations, then the syntax is very like how you'd specify the type in +PHP code, e.g. %typemap(in, phptype="int|string|Foo") means the +typemap accepts a PHP int or string or an object of class Foo, +%typemap(in, phptype="?int") means a PHP int or NULL, etc. +As well as the standard PHP type declaration types, SWIG also understands the +special type "SWIGTYPE" as an entry in phptype, which means the PHP type +corresponding to the type that this typemap matched on - for a object this +will give you the PHP class for the object, and for a pointer to a non-class +type it will give you the name of the PHP class SWIG created for that +pointer type. +

    + - -

    -Caution: This chapter is under repair! -

    -

    This chapter describes SWIG's support of Python. SWIG is compatible with all recent Python versions (Python 2.7 and Python >= 3.2). If you @@ -967,7 +962,6 @@ swig -python -help -nortti Disable the use of the native C++ RTTI with directors -nothreads Disable thread support for the entire interface -olddefs Keep the old method definitions when using -fastproxy --py3 Generate code with Python 3 specific features and syntax -relativeimport Use relative Python imports -threads Add thread support for all the interface -O Enable the following optimization options: -fastdispatch -fastproxy -fvirtual @@ -6744,13 +6738,11 @@ to do this (remember you are now the Python importer) or use dynamic linking.

    SWIG is able to support Python 3.x. The wrapper code generated by -SWIG can be compiled with both Python 2.x or 3.x. Further more, by -passing the -py3 command line option to SWIG, wrapper code -with some Python 3 specific features can be generated (see below -subsections for details of these features). +SWIG can be compiled with both Python 2.x or 3.x. +

    -There is a list of known-to-be-broken features in Python 3: +The list of known-to-be-broken features around Python 3 are:

    • No more support for FILE* typemaps, because PyFile_AsFile has been dropped @@ -6875,7 +6867,7 @@ class V(object):

      Compatibility Note: SWIG-4.1.0 changed the way that function annotations are generated. -Prior versions required the -py3 option to generate function annotation support +Prior versions required the (now removed) -py3 option to generate function annotation support containing C/C++ types instead of supporting %feature("python:annotations", "c"). Variable annotations were also added in SWIG-4.1.0.

      diff --git a/Examples/Makefile.in b/Examples/Makefile.in index 5f56f71dc..1a27b32cd 100644 --- a/Examples/Makefile.in +++ b/Examples/Makefile.in @@ -329,13 +329,6 @@ else endif PYTHON_SO = @PYTHON_SO@ -# SWIG option for Python3 -ifneq (,$(PY2)) - SWIGOPTPY3 = -else - SWIGOPTPY3 = -py3 -endif - PYCODESTYLE = @PYCODESTYLE@ PYCODESTYLE_FLAGS = --ignore=E252,E30,E402,E501,E731,W291,W391 @@ -344,7 +337,7 @@ PYCODESTYLE_FLAGS = --ignore=E252,E30,E402,E501,E731,W291,W391 # ---------------------------------------------------------------- python: $(SRCDIR_SRCS) - $(SWIG) -python $(SWIGOPTPY3) $(SWIGOPT) -o $(ISRCS) $(INTERFACEPATH) + $(SWIG) -python $(SWIGOPT) -o $(ISRCS) $(INTERFACEPATH) $(CC) -c $(CCSHARED) $(CPPFLAGS) $(CFLAGS) $(ISRCS) $(SRCDIR_SRCS) $(INCLUDES) $(PYTHON_INCLUDE) $(LDSHARED) $(CFLAGS) $(LDFLAGS) $(OBJS) $(IOBJS) $(PYTHON_DLNK) $(LIBS) -o $(LIBPREFIX)_$(TARGET)$(PYTHON_SO) @@ -353,7 +346,7 @@ python: $(SRCDIR_SRCS) # ----------------------------------------------------------------- python_cpp: $(SRCDIR_SRCS) - $(SWIG) -python $(SWIGOPTPY3) -c++ $(SWIGOPT) -o $(ICXXSRCS) $(INTERFACEPATH) + $(SWIG) -python -c++ $(SWIGOPT) -o $(ICXXSRCS) $(INTERFACEPATH) $(CXX) -c $(CCSHARED) $(CPPFLAGS) $(CXXFLAGS) $(ICXXSRCS) $(SRCDIR_SRCS) $(SRCDIR_CXXSRCS) $(INCLUDES) $(PYTHON_INCLUDE) $(CXXSHARED) $(CXXFLAGS) $(LDFLAGS) $(OBJS) $(IOBJS) $(PYTHON_DLNK) $(LIBS) $(CPP_DLLIBS) -o $(LIBPREFIX)_$(TARGET)$(PYTHON_SO) @@ -369,12 +362,12 @@ TKINTER = PYTHON_LIBOPTS = $(PYTHON_LINK) @LIBS@ $(TKINTER) $(SYSLIBS) python_static: $(SRCDIR_SRCS) - $(SWIG) -python $(SWIGOPTPY3) -lembed.i $(SWIGOPT) -o $(ISRCS) $(INTERFACEPATH) + $(SWIG) -python -lembed.i $(SWIGOPT) -o $(ISRCS) $(INTERFACEPATH) $(CC) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) @LINKFORSHARED@ $(ISRCS) $(SRCDIR_SRCS) $(INCLUDES) \ $(PYTHON_INCLUDE) $(LIBS) -L$(PYTHON_LIB) $(PYTHON_LIBOPTS) -o $(TARGET) python_static_cpp: $(SRCDIR_SRCS) - $(SWIG) -python $(SWIGOPTPY3) -c++ -lembed.i $(SWIGOPT) -o $(ICXXSRCS) $(INTERFACEPATH) + $(SWIG) -python -c++ -lembed.i $(SWIGOPT) -o $(ICXXSRCS) $(INTERFACEPATH) $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(LDFLAGS) $(ICXXSRCS) $(SRCDIR_SRCS) $(SRCDIR_CXXSRCS) $(INCLUDES) \ $(PYTHON_INCLUDE) $(LIBS) -L$(PYTHON_LIB) $(PYTHON_LIBOPTS) -o $(TARGET) diff --git a/Examples/test-suite/python_annotations_c.i b/Examples/test-suite/python_annotations_c.i index 8ecf4c6b0..c023e4d07 100644 --- a/Examples/test-suite/python_annotations_c.i +++ b/Examples/test-suite/python_annotations_c.i @@ -1,7 +1,7 @@ %module python_annotations_c // Tests the C/C++ annotations that were automatically added by using -py3 before swig-4.1.0 -// In swig-4.1.0 and later, the feature below is needed as annotations are no longer generated with -py3 +// In swig-4.1.0 and later, the feature below is needed as the -py3 option was dropped %feature("python:annotations", "c") mymethod; %feature("python:annotations", "c") makeT; %feature("python:annotations", "c") global_ints; diff --git a/Source/Modules/python.cxx b/Source/Modules/python.cxx index 41569cb18..4a7b97751 100644 --- a/Source/Modules/python.cxx +++ b/Source/Modules/python.cxx @@ -69,8 +69,6 @@ static int no_header_file = 0; static int max_bases = 0; static int builtin_bases_needed = 0; -static int py3 = 0; - /* C++ Support + Shadow Classes */ static int have_constructor = 0; @@ -131,7 +129,6 @@ static const char *usage3 = "\ -nortti - Disable the use of the native C++ RTTI with directors\n\ -nothreads - Disable thread support for the entire interface\n\ -olddefs - Keep the old method definitions when using -fastproxy\n\ - -py3 - Generate code with Python 3 specific features and syntax\n\ -relativeimport - Use relative Python imports\n\ -threads - Add thread support for all the interface\n\ -O - Enable the following optimization options:\n\ @@ -396,10 +393,6 @@ public: fputs(usage1, stdout); fputs(usage2, stdout); fputs(usage3, stdout); - } else if (strcmp(argv[i], "-py3") == 0) { - py3 = 1; - Preprocessor_define("SWIGPYTHON_PY3", 0); - Swig_mark_arg(i); } else if (strcmp(argv[i], "-builtin") == 0) { builtin = 1; Preprocessor_define("SWIGPYTHON_BUILTIN", 0); @@ -415,7 +408,10 @@ public: strcmp(argv[i], "-modernargs") == 0 || strcmp(argv[i], "-noproxydel") == 0 || strcmp(argv[i], "-safecstrings") == 0) { - Printf(stderr, "Deprecated command line option: %s. This option is now always on.\n", argv[i]); + Printf(stderr, "Deprecated command line option: %s. Ignored, this option is now always on.\n", argv[i]); + Swig_mark_arg(i); + } else if (strcmp(argv[i], "-py3") == 0) { + Printf(stderr, "Deprecated command line option: %s. Ignored, this option is no longer supported.\n", argv[i]); Swig_mark_arg(i); } else if (strcmp(argv[i], "-aliasobj0") == 0 || strcmp(argv[i], "-buildnone") == 0 || @@ -443,7 +439,7 @@ public: strcmp(argv[i], "-oldrepr") == 0 || strcmp(argv[i], "-outputtuple") == 0 || strcmp(argv[i], "-proxydel") == 0) { - Printf(stderr, "Deprecated command line option: %s. This option is no longer supported.\n", argv[i]); + Printf(stderr, "Deprecated command line option: %s. This option is no longer available.\n", argv[i]); Swig_mark_arg(i); Exit(EXIT_FAILURE); } @@ -871,13 +867,8 @@ public: Printv(f_shadow_py, "\n", f_shadow_begin, "\n", NIL); Printv(f_shadow_py, "\nfrom sys import version_info as _swig_python_version_info\n", NULL); - if (py3) { - Printv(f_shadow_py, "if _swig_python_version_info < (3, 0):\n", NULL); - Printv(f_shadow_py, tab4, "raise RuntimeError(\"Python 3.x or later required\")\n\n", NULL); - } else { - Printv(f_shadow_py, "if _swig_python_version_info < (2, 7, 0):\n", NULL); - Printv(f_shadow_py, tab4, "raise RuntimeError(\"Python 2.7 or later required\")\n\n", NULL); - } + Printv(f_shadow_py, "if _swig_python_version_info < (2, 7, 0):\n", NULL); + Printv(f_shadow_py, tab4, "raise RuntimeError(\"Python 2.7 or later required\")\n\n", NULL); if (Len(f_shadow_after_begin) > 0) Printv(f_shadow_py, f_shadow_after_begin, "\n", NIL); From 469f694ae6f0d0532b0e382dc82e8da7bff7c2ca Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Thu, 24 Mar 2022 20:52:58 +0000 Subject: [PATCH 375/662] Fix using declaration in derived class bugs Problem when all the base class's overloaded methods were overridden in the derived class - fixes "multiply defined" errors. Linked lists of the overloaded methods were not set up correctly when handling the using declaration. Closes #2244 --- CHANGES.current | 5 +++ Examples/test-suite/using_member_scopes.i | 54 +++++++++++++++++++++++ Source/Modules/typepass.cxx | 51 ++++++++++----------- 3 files changed, 83 insertions(+), 27 deletions(-) diff --git a/CHANGES.current b/CHANGES.current index 1de8dccab..dbb4ec9a7 100644 --- a/CHANGES.current +++ b/CHANGES.current @@ -7,6 +7,11 @@ the issue number to the end of the URL: https://github.com/swig/swig/issues/ Version 4.1.0 (in progress) =========================== +2022-03-24: wsfulton + #2244 Fix using declaration in derived class bugs when all the base + class's overloaded methods were overridden in the derived class - + fixes "multiply defined" errors. + 2022-03-23: wsfulton [Python] #1779 The -py3 option is deprecated and now has no effect on the code generated. Use of this option results in a deprecated warning. diff --git a/Examples/test-suite/using_member_scopes.i b/Examples/test-suite/using_member_scopes.i index 354988a0b..3245c9cc7 100644 --- a/Examples/test-suite/using_member_scopes.i +++ b/Examples/test-suite/using_member_scopes.i @@ -29,3 +29,57 @@ typedef not working yet */ } %} + + +%inline %{ +// Test using declaration in various positions before and after overloaded methods +// Testing where the derived class overrides all the base class methods (and more) +namespace Bites +{ + struct Base + { + virtual ~Base() {} + virtual void grab() {} + virtual void grab(int i) {} + }; + struct Derived1 : public Base + { + using Base::grab; + virtual void grab() {} + virtual void grab(int i) {} + }; + struct Derived2 : public Base + { + using Base::grab; + virtual void grab() {} + virtual void grab(int i) {} + virtual void grab(int i, double d) {} + }; + struct Derived3 : public Base + { + virtual void grab() {} + using Base::grab; + virtual void grab(int i) {} + }; + struct Derived4 : public Base + { + virtual void grab() {} + using Base::grab; + virtual void grab(int i) {} + virtual void grab(int i, double d) {} + }; + struct Derived5 : public Base + { + virtual void grab() {} + virtual void grab(int i) {} + using Base::grab; + }; + struct Derived6 : public Base + { + virtual void grab() {} + virtual void grab(int i) {} + virtual void grab(int i, double d) {} + using Base::grab; + }; +} +%} diff --git a/Source/Modules/typepass.cxx b/Source/Modules/typepass.cxx index e1c3753ce..6f01ec0e8 100644 --- a/Source/Modules/typepass.cxx +++ b/Source/Modules/typepass.cxx @@ -1159,14 +1159,30 @@ class TypePass:private Dispatcher { * which is hacked. */ if (Getattr(n, "sym:overloaded")) { int cnt = 0; + Node *ps = Getattr(n, "sym:previousSibling"); + Node *ns = Getattr(n, "sym:nextSibling"); + Node *fc = firstChild(n); + Node *firstoverloaded = Getattr(n, "sym:overloaded"); #ifdef DEBUG_OVERLOADED - Node *debugnode = n; - show_overloaded(n); + show_overloaded(firstoverloaded); #endif - if (!firstChild(n)) { + + if (firstoverloaded == n) { + // This 'using' node we are cutting out was the first node in the overloaded list. + // Change the first node in the list + Delattr(firstoverloaded, "sym:overloaded"); + firstoverloaded = fc ? fc : ns; + + // Correct all the sibling overloaded methods (before adding in new methods) + Node *nnn = ns; + while (nnn) { + Setattr(nnn, "sym:overloaded", firstoverloaded); + nnn = Getattr(nnn, "sym:nextSibling"); + } + } + + if (!fc) { // Remove from overloaded list ('using' node does not actually end up adding in any methods) - Node *ps = Getattr(n, "sym:previousSibling"); - Node *ns = Getattr(n, "sym:nextSibling"); if (ps) { Setattr(ps, "sym:nextSibling", ns); } @@ -1174,24 +1190,8 @@ class TypePass:private Dispatcher { Setattr(ns, "sym:previousSibling", ps); } } else { - // The 'using' node results in methods being added in - slot in the these methods here - Node *ps = Getattr(n, "sym:previousSibling"); - Node *ns = Getattr(n, "sym:nextSibling"); - Node *fc = firstChild(n); + // The 'using' node results in methods being added in - slot in these methods here Node *pp = fc; - - Node *firstoverloaded = Getattr(n, "sym:overloaded"); - if (firstoverloaded == n) { - // This 'using' node we are cutting out was the first node in the overloaded list. - // Change the first node in the list to its first sibling - Delattr(firstoverloaded, "sym:overloaded"); - Node *nnn = Getattr(firstoverloaded, "sym:nextSibling"); - firstoverloaded = fc; - while (nnn) { - Setattr(nnn, "sym:overloaded", firstoverloaded); - nnn = Getattr(nnn, "sym:nextSibling"); - } - } while (pp) { Node *ppn = Getattr(pp, "sym:nextSibling"); Setattr(pp, "sym:overloaded", firstoverloaded); @@ -1209,18 +1209,15 @@ class TypePass:private Dispatcher { Setattr(ns, "sym:previousSibling", pp); Setattr(pp, "sym:nextSibling", ns); } -#ifdef DEBUG_OVERLOADED - debugnode = firstoverloaded; -#endif } Delattr(n, "sym:previousSibling"); Delattr(n, "sym:nextSibling"); Delattr(n, "sym:overloaded"); Delattr(n, "sym:overname"); + clean_overloaded(firstoverloaded); #ifdef DEBUG_OVERLOADED - show_overloaded(debugnode); + show_overloaded(firstoverloaded); #endif - clean_overloaded(n); // Needed? } Delete(n_decl_list); } From b737a64ec54ccdaf696b287e970d7aace6a9b81c Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Fri, 25 Mar 2022 19:09:17 +0000 Subject: [PATCH 376/662] Remove minimum Python version check The version checking was historically done to deal with different versions and importing the low-level Python module. Then it was used to try and help when using -py3. A minimum version check implies that the wrappers work with any version >= 2.7, which is not really correct. The correct thing to do is to check that the exact version used matches the one that the C layer was compiled against, which can only be left for the user to do, perhaps using %pythonbegin. Issue #1779 --- Source/Modules/python.cxx | 2 -- 1 file changed, 2 deletions(-) diff --git a/Source/Modules/python.cxx b/Source/Modules/python.cxx index 4a7b97751..964e7d425 100644 --- a/Source/Modules/python.cxx +++ b/Source/Modules/python.cxx @@ -867,8 +867,6 @@ public: Printv(f_shadow_py, "\n", f_shadow_begin, "\n", NIL); Printv(f_shadow_py, "\nfrom sys import version_info as _swig_python_version_info\n", NULL); - Printv(f_shadow_py, "if _swig_python_version_info < (2, 7, 0):\n", NULL); - Printv(f_shadow_py, tab4, "raise RuntimeError(\"Python 2.7 or later required\")\n\n", NULL); if (Len(f_shadow_after_begin) > 0) Printv(f_shadow_py, f_shadow_after_begin, "\n", NIL); From 1db04bf322eb8f954d9b048d68e2b9f89c92f8fb Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Fri, 25 Mar 2022 23:31:43 +0000 Subject: [PATCH 377/662] Improvements to the -debug command line options The debug command line options that display parse tree nodes (-debug-module, -debug-top, -debug-symtabs) now display previously hidden linked list pointers which are useful for debugging parse trees. Added new command line option -debug-quiet. This suppresses the display of most linked list pointers and symbol table pointers in the parse tree nodes. The keys in the parse tree node are now shown in alphabetical order. --- CHANGES.current | 10 + Doc/Manual/Extending.html | 408 ++++++++++++++++++---------------- Doc/Manual/SWIG.html | 12 +- Source/Modules/javascript.cxx | 5 - Source/Modules/main.cxx | 4 + Source/Modules/overload.cxx | 2 - Source/Modules/r.cxx | 2 - Source/Swig/swigtree.h | 1 + Source/Swig/tree.c | 48 +++- 9 files changed, 277 insertions(+), 215 deletions(-) diff --git a/CHANGES.current b/CHANGES.current index dbb4ec9a7..937f9f871 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-03-25: wsfulton + The debug command line options that display parse tree nodes + (-debug-module, -debug-top, -debug-symtabs) now display previously hidden + linked list pointers which are useful for debugging parse trees. + + Added new command line option -debug-quiet. This suppresses the display + of most linked list pointers and symbol table pointers in the parse tree nodes. + + The keys in the parse tree node are now shown in alphabetical order. + 2022-03-24: wsfulton #2244 Fix using declaration in derived class bugs when all the base class's overloaded methods were overridden in the derived class - diff --git a/Doc/Manual/Extending.html b/Doc/Manual/Extending.html index ad90d7b63..e70f30183 100644 --- a/Doc/Manual/Extending.html +++ b/Doc/Manual/Extending.html @@ -462,187 +462,220 @@ the stage being processed. There are a number of other parse tree display options, for example, swig -debug-module <n> will avoid displaying system parse information and only display the parse tree pertaining to the user's module at stage n of processing. +Adding the -debug-quiet option is recommended as it removes some noise which is not usually needed, +that is, the display of many linked list pointers and symbol table pointers.

      -$ swig -c++ -python -debug-module 4 example.i
      -      +++ include ----------------------------------------
      -      | name         - "example.i"
      +$ swig -c++ -python -debug-module 1 -debug-quiet example.i
      +debug-module stage 1
      ++++ module ----------------------------------------
      +| name         - "example"
      +| 
      ++++ insert ----------------------------------------
      +| code         - "\n#include \"example.h\"\n"
      +| 
      ++++ include ----------------------------------------
      +| name         - "example.h"
       
      -            +++ module ----------------------------------------
      -            | name         - "example"
      -            |
      -            +++ insert ----------------------------------------
      -            | code         - "\n#include \"example.h\"\n"
      -            |
      -            +++ include ----------------------------------------
      -            | name         - "example.h"
      +      +++ class ----------------------------------------
      +      | abstracts    - 0x7f4f15182930
      +      | allows_typedef - "1"
      +      | kind         - "class"
      +      | name         - "Shape"
      +      | sym:name     - "Shape"
       
      -                  +++ class ----------------------------------------
      -                  | abstract     - "1"
      -                  | sym:name     - "Shape"
      -                  | name         - "Shape"
      -                  | kind         - "class"
      -                  | symtab       - 0x40194140
      -                  | sym:symtab   - 0x40191078
      +            +++ access ----------------------------------------
      +            | kind         - "public"
      +            | 
      +            +++ constructor ----------------------------------------
      +            | access       - "public"
      +            | code         - "{\n    nshapes++;\n  }"
      +            | decl         - "f()."
      +            | feature:new  - "1"
      +            | ismember     - "1"
      +            | name         - "Shape"
      +            | sym:name     - "Shape"
      +            | 
      +            +++ destructor ----------------------------------------
      +            | access       - "public"
      +            | code         - "{\n    nshapes--;\n  }"
      +            | decl         - "f()."
      +            | ismember     - "1"
      +            | name         - "~Shape"
      +            | storage      - "virtual"
      +            | sym:name     - "~Shape"
      +            | 
      +            +++ cdecl ----------------------------------------
      +            | access       - "public"
      +            | decl         - ""
      +            | ismember     - "1"
      +            | kind         - "variable"
      +            | name         - "x"
      +            | sym:name     - "x"
      +            | type         - "double"
      +            | 
      +            +++ cdecl ----------------------------------------
      +            | access       - "public"
      +            | decl         - ""
      +            | ismember     - "1"
      +            | kind         - "variable"
      +            | name         - "y"
      +            | sym:name     - "y"
      +            | type         - "double"
      +            | 
      +            +++ cdecl ----------------------------------------
      +            | access       - "public"
      +            | decl         - "f(double,double)."
      +            | ismember     - "1"
      +            | kind         - "function"
      +            | name         - "move"
      +            | parms        - 'double dx,double dy'
      +            | sym:name     - "move"
      +            | type         - "void"
      +            | 
      +            +++ cdecl ----------------------------------------
      +            | abstract     - "1"
      +            | access       - "public"
      +            | decl         - "f()."
      +            | ismember     - "1"
      +            | kind         - "function"
      +            | name         - "area"
      +            | storage      - "virtual"
      +            | sym:name     - "area"
      +            | type         - "double"
      +            | value        - "0"
      +            | valuetype    - "int"
      +            | 
      +            +++ cdecl ----------------------------------------
      +            | abstract     - "1"
      +            | access       - "public"
      +            | decl         - "f()."
      +            | ismember     - "1"
      +            | kind         - "function"
      +            | name         - "perimeter"
      +            | storage      - "virtual"
      +            | sym:name     - "perimeter"
      +            | type         - "double"
      +            | value        - "0"
      +            | valuetype    - "int"
      +            | 
      +            +++ cdecl ----------------------------------------
      +            | access       - "public"
      +            | decl         - ""
      +            | ismember     - "1"
      +            | kind         - "variable"
      +            | name         - "nshapes"
      +            | storage      - "static"
      +            | sym:name     - "nshapes"
      +            | type         - "int"
      +            | 
      +      +++ class ----------------------------------------
      +      | allows_typedef - "1"
      +      | baselist     - 0x7f4f15182ad0
      +      | kind         - "class"
      +      | name         - "Circle"
      +      | privatebaselist - 0x7f4f15182b10
      +      | protectedbaselist - 0x7f4f15182af0
      +      | sym:name     - "Circle"
       
      -                        +++ access ----------------------------------------
      -                        | kind         - "public"
      -                        |
      -                        +++ constructor ----------------------------------------
      -                        | sym:name     - "Shape"
      -                        | name         - "Shape"
      -                        | decl         - "f()."
      -                        | code         - "{\n    nshapes++;\n  }"
      -                        | sym:symtab   - 0x40194140
      -                        |
      -                        +++ destructor ----------------------------------------
      -                        | sym:name     - "~Shape"
      -                        | name         - "~Shape"
      -                        | storage      - "virtual"
      -                        | code         - "{\n    nshapes--;\n  }"
      -                        | sym:symtab   - 0x40194140
      -                        |
      -                        +++ cdecl ----------------------------------------
      -                        | sym:name     - "x"
      -                        | name         - "x"
      -                        | decl         - ""
      -                        | type         - "double"
      -                        | sym:symtab   - 0x40194140
      -                        |
      -                        +++ cdecl ----------------------------------------
      -                        | sym:name     - "y"
      -                        | name         - "y"
      -                        | decl         - ""
      -                        | type         - "double"
      -                        | sym:symtab   - 0x40194140
      -                        |
      -                        +++ cdecl ----------------------------------------
      -                        | sym:name     - "move"
      -                        | name         - "move"
      -                        | decl         - "f(double, double)."
      -                        | parms        - double, double
      -                        | type         - "void"
      -                        | sym:symtab   - 0x40194140
      -                        |
      -                        +++ cdecl ----------------------------------------
      -                        | sym:name     - "area"
      -                        | name         - "area"
      -                        | decl         - "f(void)."
      -                        | parms        - void
      -                        | storage      - "virtual"
      -                        | value        - "0"
      -                        | type         - "double"
      -                        | sym:symtab   - 0x40194140
      -                        |
      -                        +++ cdecl ----------------------------------------
      -                        | sym:name     - "perimeter"
      -                        | name         - "perimeter"
      -                        | decl         - "f(void)."
      -                        | parms        - void
      -                        | storage      - "virtual"
      -                        | value        - "0"
      -                        | type         - "double"
      -                        | sym:symtab   - 0x40194140
      -                        |
      -                        +++ cdecl ----------------------------------------
      -                        | sym:name     - "nshapes"
      -                        | name         - "nshapes"
      -                        | decl         - ""
      -                        | storage      - "static"
      -                        | type         - "int"
      -                        | sym:symtab   - 0x40194140
      -                        |
      -                  +++ class ----------------------------------------
      -                  | sym:name     - "Circle"
      -                  | name         - "Circle"
      -                  | kind         - "class"
      -                  | bases        - 0x40194510
      -                  | symtab       - 0x40194538
      -                  | sym:symtab   - 0x40191078
      +            +++ access ----------------------------------------
      +            | kind         - "private"
      +            | 
      +            +++ cdecl ----------------------------------------
      +            | access       - "private"
      +            | decl         - ""
      +            | ismember     - "1"
      +            | kind         - "variable"
      +            | name         - "radius"
      +            | type         - "double"
      +            | 
      +            +++ access ----------------------------------------
      +            | kind         - "public"
      +            | 
      +            +++ constructor ----------------------------------------
      +            | access       - "public"
      +            | code         - "{ }"
      +            | decl         - "f(double)."
      +            | feature:new  - "1"
      +            | ismember     - "1"
      +            | name         - "Circle"
      +            | parms        - 'double r'
      +            | sym:name     - "Circle"
      +            | 
      +            +++ cdecl ----------------------------------------
      +            | access       - "public"
      +            | decl         - "f()."
      +            | ismember     - "1"
      +            | kind         - "function"
      +            | name         - "area"
      +            | storage      - "virtual"
      +            | sym:name     - "area"
      +            | type         - "double"
      +            | 
      +            +++ cdecl ----------------------------------------
      +            | access       - "public"
      +            | decl         - "f()."
      +            | ismember     - "1"
      +            | kind         - "function"
      +            | name         - "perimeter"
      +            | storage      - "virtual"
      +            | sym:name     - "perimeter"
      +            | type         - "double"
      +            | 
      +      +++ class ----------------------------------------
      +      | allows_typedef - "1"
      +      | baselist     - 0x7f4f15183830
      +      | kind         - "class"
      +      | name         - "Square"
      +      | privatebaselist - 0x7f4f15183870
      +      | protectedbaselist - 0x7f4f15183850
      +      | sym:name     - "Square"
       
      -                        +++ access ----------------------------------------
      -                        | kind         - "private"
      -                        |
      -                        +++ cdecl ----------------------------------------
      -                        | name         - "radius"
      -                        | decl         - ""
      -                        | type         - "double"
      -                        |
      -                        +++ access ----------------------------------------
      -                        | kind         - "public"
      -                        |
      -                        +++ constructor ----------------------------------------
      -                        | sym:name     - "Circle"
      -                        | name         - "Circle"
      -                        | parms        - double
      -                        | decl         - "f(double)."
      -                        | code         - "{ }"
      -                        | sym:symtab   - 0x40194538
      -                        |
      -                        +++ cdecl ----------------------------------------
      -                        | sym:name     - "area"
      -                        | name         - "area"
      -                        | decl         - "f(void)."
      -                        | parms        - void
      -                        | storage      - "virtual"
      -                        | type         - "double"
      -                        | sym:symtab   - 0x40194538
      -                        |
      -                        +++ cdecl ----------------------------------------
      -                        | sym:name     - "perimeter"
      -                        | name         - "perimeter"
      -                        | decl         - "f(void)."
      -                        | parms        - void
      -                        | storage      - "virtual"
      -                        | type         - "double"
      -                        | sym:symtab   - 0x40194538
      -                        |
      -                  +++ class ----------------------------------------
      -                  | sym:name     - "Square"
      -                  | name         - "Square"
      -                  | kind         - "class"
      -                  | bases        - 0x40194760
      -                  | symtab       - 0x40194788
      -                  | sym:symtab   - 0x40191078
      -
      -                        +++ access ----------------------------------------
      -                        | kind         - "private"
      -                        |
      -                        +++ cdecl ----------------------------------------
      -                        | name         - "width"
      -                        | decl         - ""
      -                        | type         - "double"
      -                        |
      -                        +++ access ----------------------------------------
      -                        | kind         - "public"
      -                        |
      -                        +++ constructor ----------------------------------------
      -                        | sym:name     - "Square"
      -                        | name         - "Square"
      -                        | parms        - double
      -                        | decl         - "f(double)."
      -                        | code         - "{ }"
      -                        | sym:symtab   - 0x40194788
      -                        |
      -                        +++ cdecl ----------------------------------------
      -                        | sym:name     - "area"
      -                        | name         - "area"
      -                        | decl         - "f(void)."
      -                        | parms        - void
      -                        | storage      - "virtual"
      -                        | type         - "double"
      -                        | sym:symtab   - 0x40194788
      -                        |
      -                        +++ cdecl ----------------------------------------
      -                        | sym:name     - "perimeter"
      -                        | name         - "perimeter"
      -                        | decl         - "f(void)."
      -                        | parms        - void
      -                        | storage      - "virtual"
      -                        | type         - "double"
      -                        | sym:symtab   - 0x40194788
      +            +++ access ----------------------------------------
      +            | kind         - "private"
      +            | 
      +            +++ cdecl ----------------------------------------
      +            | access       - "private"
      +            | decl         - ""
      +            | ismember     - "1"
      +            | kind         - "variable"
      +            | name         - "width"
      +            | type         - "double"
      +            | 
      +            +++ access ----------------------------------------
      +            | kind         - "public"
      +            | 
      +            +++ constructor ----------------------------------------
      +            | access       - "public"
      +            | code         - "{ }"
      +            | decl         - "f(double)."
      +            | feature:new  - "1"
      +            | ismember     - "1"
      +            | name         - "Square"
      +            | parms        - 'double w'
      +            | sym:name     - "Square"
      +            | 
      +            +++ cdecl ----------------------------------------
      +            | access       - "public"
      +            | decl         - "f()."
      +            | ismember     - "1"
      +            | kind         - "function"
      +            | name         - "area"
      +            | storage      - "virtual"
      +            | sym:name     - "area"
      +            | type         - "double"
      +            | 
      +            +++ cdecl ----------------------------------------
      +            | access       - "public"
      +            | decl         - "f()."
      +            | ismember     - "1"
      +            | kind         - "function"
      +            | name         - "perimeter"
      +            | storage      - "virtual"
      +            | sym:name     - "perimeter"
      +            | type         - "double"
       
      @@ -698,31 +731,28 @@ The parse tree can be viewed after the final stage of processing by running SWIG
      -$ swig -debug-top 4 example.i
      +$ swig -debug-top 1 -debug-quiet example.i
       ...
                   +++ cdecl ----------------------------------------
      -            | sym:name     - "foo_i"
      -            | name         - "foo"
                   | decl         - "f(int)."
      +            | name         - "foo"
                   | parms        - int
      +            | sym:name     - "foo_i"
                   | type         - "void"
      -            | sym:symtab   - 0x40165078
                   |
                   +++ cdecl ----------------------------------------
      -            | sym:name     - "foo_d"
      -            | name         - "foo"
                   | decl         - "f(double)."
      +            | name         - "foo"
                   | parms        - double
      +            | sym:name     - "foo_d"
                   | type         - "void"
      -            | sym:symtab   - 0x40165078
                   |
                   +++ cdecl ----------------------------------------
      -            | sym:name     - "foo"
      -            | name         - "foo"
                   | decl         - "f(p.Bar)."
      +            | name         - "foo"
                   | parms        - Bar *
      +            | sym:name     - "foo"
                   | type         - "void"
      -            | sym:symtab   - 0x40165078
       
      @@ -787,19 +817,18 @@ public: The behavior of %feature is very easy to describe--it simply attaches a new attribute to any parse tree node that matches the given prototype. When a feature is added, it shows up as an attribute in the feature: namespace. -You can see this when running with the -debug-top 4 option. For example: +You can see this when running with the -debug-top 4 -debug-quiet option. For example:

        +++ cdecl ----------------------------------------
      - | sym:name     - "getitem"
      - | name         - "getitem"
        | decl         - "f(int).p."
      - | parms        - int
      - | type         - "Object"
        | feature:except - "{\n    try {\n       $action\n    } catc..."
      - | sym:symtab   - 0x40168ac8
      + | name         - "getitem"
      + | parms        - int
      + | sym:name     - "getitem"
      + | type         - "Object"
        |
       
      @@ -3765,6 +3794,7 @@ There are various command line options which can aid debugging a SWIG interface -debug-symbols - Display target language symbols in the symbol tables -debug-csymbols - Display C symbols in the symbol tables -debug-lsymbols - Display target language layer symbols +-debug-quiet - Display less parse tree node debug info when using other -debug options -debug-tags - Display information about the tags found in the interface -debug-template - Display information for debugging templates -debug-top <n> - Display entire parse tree at stages 1-4, <n> is a csv list of stages diff --git a/Doc/Manual/SWIG.html b/Doc/Manual/SWIG.html index ea2e625ef..1d929ac71 100644 --- a/Doc/Manual/SWIG.html +++ b/Doc/Manual/SWIG.html @@ -155,6 +155,7 @@ General Options -debug-symbols - Display target language symbols in the symbol tables -debug-csymbols - Display C symbols in the symbol tables -debug-lsymbols - Display target language layer symbols + -debug-quiet - Display less parse tree node debug info when using other -debug options -debug-tags - Display information about the tags found in the interface -debug-template - Display information for debugging templates -debug-top <n> - Display entire parse tree at stages 1-4, <n> is a csv list of stages @@ -2186,18 +2187,19 @@ of the expression.

      For a comprehensive understanding of how the matching works, the internal parse tree needs to be examined using the -command line option: -debug-module 1. +command line option: -debug-module 1 -debug-quiet. A snippet of the resulting output might be:

      -            +++ destructor - 0x7fc10ea05af0 ----------------------------------------
      -            | name         - "~Shape"
      -            | ismember     - "1"
      -            | sym:name     - "~Shape"
      +            +++ destructor ----------------------------------------
                   | access       - "public"
      +            | decl         - "f()."
      +            | ismember     - "1"
      +            | name         - "~Shape"
                   | storage      - "virtual"
      +            | sym:name     - "~Shape"
       
      diff --git a/Source/Modules/javascript.cxx b/Source/Modules/javascript.cxx index 604b43743..b17c5e503 100644 --- a/Source/Modules/javascript.cxx +++ b/Source/Modules/javascript.cxx @@ -760,13 +760,10 @@ int JSEmitter::emitWrapperFunction(Node *n) { ret = emitSetter(n, is_member, is_static); } else if (is_getter) { ret = emitGetter(n, is_member, is_static); - } else { - Swig_print_node(n); } } else { Printf(stderr, "Warning: unsupported wrapper function type\n"); - Swig_print_node(n); ret = SWIG_ERROR; } } else { @@ -778,7 +775,6 @@ int JSEmitter::emitWrapperFunction(Node *n) { ret = emitDtor(n); } else { Printf(stderr, "Warning: unsupported wrapper function type"); - Swig_print_node(n); ret = SWIG_ERROR; } } @@ -1409,7 +1405,6 @@ int JSEmitter::switchNamespace(Node *n) { String *_nspace = lang->getNSpace(); if (!Equal(nspace, _nspace)) { Printf(stdout, "##### Custom vs Language::getNSpace(): %s | %s\n", nspace, _nspace); - Swig_print_node(n); } #endif diff --git a/Source/Modules/main.cxx b/Source/Modules/main.cxx index 239deabeb..f412a3eeb 100644 --- a/Source/Modules/main.cxx +++ b/Source/Modules/main.cxx @@ -74,6 +74,7 @@ static const char *usage1 = (const char *) "\ -debug-symbols - Display target language symbols in the symbol tables\n\ -debug-csymbols - Display C symbols in the symbol tables\n\ -debug-lsymbols - Display target language layer symbols\n\ + -debug-quiet - Display less parse tree node debug info when using other -debug options\n\ -debug-tags - Display information about the tags found in the interface\n\ -debug-template - Display information for debugging templates\n\ -debug-top - Display entire parse tree at stages 1-4, is a csv list of stages\n\ @@ -778,6 +779,9 @@ static void getoptions(int argc, char *argv[]) { } else if (strncmp(argv[i], "-w", 2) == 0) { Swig_mark_arg(i); Swig_warnfilter(argv[i] + 2, 1); + } else if (strcmp(argv[i], "-debug-quiet") == 0) { + Swig_print_quiet(1); + Swig_mark_arg(i); } else if (strcmp(argv[i], "-debug-symtabs") == 0) { dump_symtabs = 1; Swig_mark_arg(i); diff --git a/Source/Modules/overload.cxx b/Source/Modules/overload.cxx index 8a4ce48f7..034e0e76f 100644 --- a/Source/Modules/overload.cxx +++ b/Source/Modules/overload.cxx @@ -339,7 +339,6 @@ List *Swig_overload_rank(Node *n, bool script_lang_wrapping) { Setattr(nodes[i].n, "overload:ignore", "1"); Append(result, nodes[i].n); // Printf(stdout,"[ %d ] %d %s\n", i, nodes[i].implicitconv_function, ParmList_errorstr(nodes[i].parms)); - // Swig_print_node(nodes[i].n); if (i == nnodes-1 || nodes[i].argc != nodes[i+1].argc) { if (argc_changed_index+2 < nnodes && (nodes[argc_changed_index+1].argc == nodes[argc_changed_index+2].argc)) { // Add additional implicitconv functions in same order as already ranked. @@ -351,7 +350,6 @@ List *Swig_overload_rank(Node *n, bool script_lang_wrapping) { SetFlag(nodes[j].n, "implicitconvtypecheckoff"); Append(result, nodes[j].n); // Printf(stdout,"[ %d ] %d + %s\n", j, nodes[j].implicitconv_function, ParmList_errorstr(nodes[j].parms)); - // Swig_print_node(nodes[j].n); } } } diff --git a/Source/Modules/r.cxx b/Source/Modules/r.cxx index 9d9204c0f..541e7e622 100644 --- a/Source/Modules/r.cxx +++ b/Source/Modules/r.cxx @@ -1542,8 +1542,6 @@ List * R::Swig_overload_rank(Node *n, if (nodes[i].error) Setattr(nodes[i].n, "overload:ignore", "1"); Append(result,nodes[i].n); - // Printf(stdout,"[ %d ] %s\n", i, ParmList_errorstr(nodes[i].parms)); - // Swig_print_node(nodes[i].n); } } return result; diff --git a/Source/Swig/swigtree.h b/Source/Swig/swigtree.h index acd0e5e90..8f70a2cde 100644 --- a/Source/Swig/swigtree.h +++ b/Source/Swig/swigtree.h @@ -51,3 +51,4 @@ extern void Swig_restore(Node *node); extern void Swig_print_tags(File *obj, Node *root); extern void Swig_print_tree(Node *obj); extern void Swig_print_node(Node *obj); +extern int Swig_print_quiet(int quiet); diff --git a/Source/Swig/tree.c b/Source/Swig/tree.c index 5b0e9e1e9..e5d3467e5 100644 --- a/Source/Swig/tree.c +++ b/Source/Swig/tree.c @@ -16,6 +16,20 @@ #include #include +static int debug_quiet = 0; + +/* ----------------------------------------------------------------------------- + * Swig_print_quiet() + * + * Set quiet mode when printing a parse tree node + * ----------------------------------------------------------------------------- */ + +int Swig_print_quiet(int quiet) { + int previous_quiet = debug_quiet; + debug_quiet = quiet; + return previous_quiet; +} + /* ----------------------------------------------------------------------------- * Swig_print_tags() * @@ -68,31 +82,40 @@ void Swig_print_node(Node *obj) { Node *cobj; print_indent(0); - Printf(stdout, "+++ %s - %p ----------------------------------------\n", nodeType(obj), obj); - ki = First(obj); - while (ki.key) { - String *k = ki.key; - if ((Cmp(k, "nodeType") == 0) || (Cmp(k, "firstChild") == 0) || (Cmp(k, "lastChild") == 0) || - (Cmp(k, "parentNode") == 0) || (Cmp(k, "nextSibling") == 0) || (Cmp(k, "previousSibling") == 0) || (*(Char(k)) == '$')) { + if (debug_quiet) + Printf(stdout, "+++ %s ----------------------------------------\n", nodeType(obj)); + else + Printf(stdout, "+++ %s - %p ----------------------------------------\n", nodeType(obj), obj); + + List *keys = Keys(obj); + SortList(keys, 0); + ki = First(keys); + while (ki.item) { + String *k = ki.item; + DOH *value = Getattr(obj, k); + if (Equal(k, "nodeType") || (*(Char(k)) == '$')) { /* Do nothing */ - } else if (Cmp(k, "kwargs") == 0 || Cmp(k, "parms") == 0 || Cmp(k, "wrap:parms") == 0 || - Cmp(k, "pattern") == 0 || Cmp(k, "templateparms") == 0 || Cmp(k, "throws") == 0) { + } else if (debug_quiet && (Equal(k, "nodeType") || Equal(k, "firstChild") || Equal(k, "lastChild") || Equal(k, "parentNode") || Equal(k, "nextSibling") || + Equal(k, "previousSibling") || Equal(k, "symtab") || Equal(k, "csymtab") || Equal(k, "sym:symtab") || Equal(k, "sym:nextSibling") || + Equal(k, "sym:previousSibling") || Equal(k, "csym:nextSibling") || Equal(k, "csym:previousSibling"))) { + /* Do nothing */ + } else if (Equal(k, "kwargs") || Equal(k, "parms") || Equal(k, "wrap:parms") || Equal(k, "pattern") || Equal(k, "templateparms") || Equal(k, "throws")) { print_indent(2); /* Differentiate parameter lists by displaying within single quotes */ - Printf(stdout, "%-12s - \'%s\'\n", k, ParmList_str_defaultargs(Getattr(obj, k))); + Printf(stdout, "%-12s - \'%s\'\n", k, ParmList_str_defaultargs(value)); } else { DOH *o; const char *trunc = ""; print_indent(2); - if (DohIsString(Getattr(obj, k))) { - o = Str(Getattr(obj, k)); + if (DohIsString(value)) { + o = Str(value); if (Len(o) > 80) { trunc = "..."; } Printf(stdout, "%-12s - \"%(escape)-0.80s%s\"\n", k, o, trunc); Delete(o); } else { - Printf(stdout, "%-12s - %p\n", k, Getattr(obj, k)); + Printf(stdout, "%-12s - %p\n", k, value); } } ki = Next(ki); @@ -107,6 +130,7 @@ void Swig_print_node(Node *obj) { print_indent(1); Printf(stdout, "\n"); } + Delete(keys); } /* ----------------------------------------------------------------------------- From 51a7f27d1cb92d5caa81b6c6a58ecec830f3e753 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Fri, 25 Mar 2022 23:44:07 +0000 Subject: [PATCH 378/662] Minor fix to Swig_print_node --- Source/Swig/tree.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Swig/tree.c b/Source/Swig/tree.c index e5d3467e5..bc552988c 100644 --- a/Source/Swig/tree.c +++ b/Source/Swig/tree.c @@ -95,7 +95,7 @@ void Swig_print_node(Node *obj) { DOH *value = Getattr(obj, k); if (Equal(k, "nodeType") || (*(Char(k)) == '$')) { /* Do nothing */ - } else if (debug_quiet && (Equal(k, "nodeType") || Equal(k, "firstChild") || Equal(k, "lastChild") || Equal(k, "parentNode") || Equal(k, "nextSibling") || + } else if (debug_quiet && (Equal(k, "firstChild") || Equal(k, "lastChild") || Equal(k, "parentNode") || Equal(k, "nextSibling") || Equal(k, "previousSibling") || Equal(k, "symtab") || Equal(k, "csymtab") || Equal(k, "sym:symtab") || Equal(k, "sym:nextSibling") || Equal(k, "sym:previousSibling") || Equal(k, "csym:nextSibling") || Equal(k, "csym:previousSibling"))) { /* Do nothing */ From 5c68705a218afb6afd45498a9c0e096a56adab2d Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Sat, 26 Mar 2022 12:03:09 +0000 Subject: [PATCH 379/662] Comment broken part of using_member.i --- Examples/test-suite/using_member.i | 1 + 1 file changed, 1 insertion(+) diff --git a/Examples/test-suite/using_member.i b/Examples/test-suite/using_member.i index 6b4af2ea7..c80a83a50 100644 --- a/Examples/test-suite/using_member.i +++ b/Examples/test-suite/using_member.i @@ -46,6 +46,7 @@ namespace one { class BB : public two::three::AA { public: +// TODO: two::three::AA::great not introduced using two::three::AA::great; int great(bool) {return 2;} int jj() {return 3;} From 3ab288dfa48e34788da25cf0ec5b3bdd0e8d63f6 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Sat, 26 Mar 2022 15:06:13 +0000 Subject: [PATCH 380/662] Different capsule names for builtin changes entry --- CHANGES.current | 8 ++++++++ .../test-suite/python/python_runtime_data_runme.py | 12 ++++++++---- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/CHANGES.current b/CHANGES.current index 64e4c4402..56cb2c560 100644 --- a/CHANGES.current +++ b/CHANGES.current @@ -7,6 +7,14 @@ the issue number to the end of the URL: https://github.com/swig/swig/issues/ Version 4.1.0 (in progress) =========================== +2022-03-26: eltoder + [Python] #1684 Use different capsule names with and without -builtin + + Types generated with and without -builtin are not compatible. Mixing + them in a common type list leads to crashes. Avoid this by using + different capsule names: "type_pointer_capsule" without -builtin and + "type_pointer_capsule_builtin" with. + 2022-03-15: ianlancetaylor [Go] Don't convert arrays to pointers if there is a "gotype" typemap entry. diff --git a/Examples/test-suite/python/python_runtime_data_runme.py b/Examples/test-suite/python/python_runtime_data_runme.py index 341315ee3..063bf82d1 100644 --- a/Examples/test-suite/python/python_runtime_data_runme.py +++ b/Examples/test-suite/python/python_runtime_data_runme.py @@ -1,11 +1,15 @@ import python_runtime_data_builtin as builtin import python_runtime_data_nobuiltin as nobuiltin -assert builtin.is_python_builtin() -assert not nobuiltin.is_python_builtin() +def swig_assert(a): + if not a: + raise RuntimeError("Failed") + +swig_assert(builtin.is_python_builtin()) +swig_assert(not nobuiltin.is_python_builtin()) for i in range(1, 5): v1 = builtin.vectord([1.] * i) - assert len(v1) == i + swig_assert(len(v1) == i) v2 = nobuiltin.vectord([1.] * i) - assert len(v2) == i + swig_assert(len(v2) == i) From f2dd436a5b6c71d1c552a9238a33980f2f0bb529 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Sat, 26 Mar 2022 15:16:22 +0000 Subject: [PATCH 381/662] Rework swig_and_compile_multi_cpp makefile helper Seems less cryptic and more maintainable to me --- Examples/test-suite/common.mk | 14 ++++++++------ Examples/test-suite/python/Makefile.in | 5 ++++- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/Examples/test-suite/common.mk b/Examples/test-suite/common.mk index 85b27979d..ddbb75d22 100644 --- a/Examples/test-suite/common.mk +++ b/Examples/test-suite/common.mk @@ -831,6 +831,13 @@ endif partialcheck: $(MAKE) check CC=true CXX=true LDSHARED=true CXXSHARED=true RUNTOOL=true COMPILETOOL=true +swig_and_compile_cpp_helper = \ + $(MAKE) -f $(top_builddir)/$(EXAMPLES)/Makefile SRCDIR='$(SRCDIR)' CXXSRCS='$(CXXSRCS)' \ + SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \ + LIBS='$(LIBS)' INCLUDES='$(INCLUDES)' SWIGOPT=$(2) NOLINK=true \ + TARGET="$(TARGETPREFIX)$(1)$(TARGETSUFFIX)" INTERFACEDIR='$(INTERFACEDIR)' INTERFACE="$(1).i" \ + $(LANGUAGE)$(VARIANT)_cpp + swig_and_compile_cpp = \ $(MAKE) -f $(top_builddir)/$(EXAMPLES)/Makefile SRCDIR='$(SRCDIR)' CXXSRCS='$(CXXSRCS)' \ SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \ @@ -847,12 +854,7 @@ swig_and_compile_c = \ swig_and_compile_multi_cpp = \ for f in `cat $(top_srcdir)/$(EXAMPLES)/$(TEST_SUITE)/$*.list` ; do \ - swigopt=$$(name=SWIGOPT_$$f; eval echo \$$$$name); \ - $(MAKE) -f $(top_builddir)/$(EXAMPLES)/Makefile SRCDIR='$(SRCDIR)' CXXSRCS='$(CXXSRCS)' \ - SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \ - LIBS='$(LIBS)' INCLUDES='$(INCLUDES)' SWIGOPT="$${swigopt:-$(SWIGOPT)}" NOLINK=true \ - TARGET="$(TARGETPREFIX)$${f}$(TARGETSUFFIX)" INTERFACEDIR='$(INTERFACEDIR)' INTERFACE="$$f.i" \ - $(LANGUAGE)$(VARIANT)_cpp; \ + $(call swig_and_compile_cpp_helper,$${f},'$(SWIGOPT)'); \ done swig_and_compile_external = \ diff --git a/Examples/test-suite/python/Makefile.in b/Examples/test-suite/python/Makefile.in index 57106edd1..a85b2984a 100644 --- a/Examples/test-suite/python/Makefile.in +++ b/Examples/test-suite/python/Makefile.in @@ -105,9 +105,12 @@ VALGRIND_OPT += --suppressions=pythonswig.supp # Custom tests - tests with additional commandline options #python_flatstaticmethod.cpptest: SWIGOPT += -flatstaticmethod +# Make sure just python_runtime_data_builtin.i uses the -builtin option. Note: does not use python_runtime_data.list for all steps. python_runtime_data.multicpptest: override SWIG_FEATURES := $(filter-out -builtin,$(SWIG_FEATURES)) python_runtime_data.multicpptest: override SWIGOPT := $(filter-out -builtin,$(SWIGOPT)) -python_runtime_data.multicpptest: export SWIGOPT_python_runtime_data_builtin = $(SWIGOPT) -builtin +python_runtime_data.multicpptest: swig_and_compile_multi_cpp = \ + $(call swig_and_compile_cpp_helper,python_runtime_data_builtin,'$(SWIGOPT) -builtin') && \ + $(call swig_and_compile_cpp_helper,python_runtime_data_nobuiltin,'$(SWIGOPT)') # Rules for the different types of tests %.cpptest: From c5f209706ed411099ae128a49a9c1c987e789d0d Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Sun, 27 Mar 2022 11:27:58 +0100 Subject: [PATCH 382/662] Further makefile refactoring for multicpptests --- Examples/test-suite/common.mk | 2 ++ Examples/test-suite/go/Makefile.in | 48 +++++++----------------------- 2 files changed, 13 insertions(+), 37 deletions(-) diff --git a/Examples/test-suite/common.mk b/Examples/test-suite/common.mk index ddbb75d22..f887037d9 100644 --- a/Examples/test-suite/common.mk +++ b/Examples/test-suite/common.mk @@ -814,6 +814,8 @@ check-cpp: $(CPP_TEST_CASES:=.cpptest) check-cpp11: $(CPP11_TEST_CASES:=.cpptest) +check-multicpp: $(MULTI_CPP_TEST_CASES:=.multicpptest) + ifdef HAS_DOXYGEN check-doxygen: $(DOXYGEN_TEST_CASES:=.cpptest) endif diff --git a/Examples/test-suite/go/Makefile.in b/Examples/test-suite/go/Makefile.in index e905a1060..3f1bbea4e 100644 --- a/Examples/test-suite/go/Makefile.in +++ b/Examples/test-suite/go/Makefile.in @@ -43,17 +43,9 @@ INCLUDES = -I$(abs_top_srcdir)/$(EXAMPLES)/$(TEST_SUITE) %.multicpptest: $(setup) - mkdir -p gopath/$*/src 2>/dev/null || true - if ! test -d gopath/$*/src/swigtests; then \ - (cd gopath/$*/src && ln -s . swigtests); \ - fi + $(call go_multicpp_setup,$*) +for f in `cat $(top_srcdir)/$(EXAMPLES)/$(TEST_SUITE)/$*.list` ; do \ - $(MAKE) -f $(top_builddir)/$(EXAMPLES)/Makefile SRCDIR='$(SRCDIR)' CXXSRCS='$(CXXSRCS)' \ - SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \ - LIBS='$(LIBS)' INCLUDES='$(INCLUDES)' SWIGOPT='$(SWIGOPT)' NOLINK=true \ - TARGET="$(TARGETPREFIX)$${f}$(TARGETSUFFIX)" INTERFACEDIR='$(INTERFACEDIR)' INTERFACE="$$f.i" \ - GOMOD="$*" \ - $(LANGUAGE)$(VARIANT)_cpp; \ + $(call swig_and_compile_cpp_helper,$${f},'$(SWIGOPT)') GOMOD="$*"; \ done $(run_multi_testcase) @@ -61,28 +53,9 @@ li_windows.cpptest: # Does not work because go build won't build li_windows.go, # because file names with "windows" are only built on Windows. -multi_import.multicpptest: - $(setup) - mkdir -p gopath/multi_import/src 2>/dev/null || true - if ! test -d gopath/multi_import/src/swigtests; then \ - (cd gopath/multi_import/src && ln -s . swigtests); \ - fi - for f in multi_import_d multi_import_b multi_import_a; do \ - $(MAKE) -f $(top_builddir)/$(EXAMPLES)/Makefile SRCDIR='$(SRCDIR)' CXXSRCS='$(CXXSRCS)' \ - SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \ - LIBS='$(LIBS)' INCLUDES='$(INCLUDES)' SWIGOPT='$(SWIGOPT)' NOLINK=true \ - TARGET="$(TARGETPREFIX)$${f}$(TARGETSUFFIX)" INTERFACEDIR='$(INTERFACEDIR)' INTERFACE="$$f.i" \ - GOMOD="multi_import" \ - $(LANGUAGE)$(VARIANT)_cpp; \ - done - $(run_multi_testcase) - go_subdir_import.multicpptest: $(setup) - mkdir -p gopath/go_subdir_import/src 2>/dev/null || true - if ! test -d gopath/go_subdir_import/src/swigtests; then \ - (cd gopath/go_subdir_import/src && ln -s . swigtests); \ - fi + $(call go_multicpp_setup,go_subdir_import) mkdir -p testdir/go_subdir_import 2>/dev/null || true mkdir -p gopath/go_subdir_import/src/testdir/go_subdir_import 2>/dev/null || true $(MAKE) -f $(top_builddir)/$(EXAMPLES)/Makefile SRCDIR='$(SRCDIR)' CXXSRCS='$(CXXSRCS)' \ @@ -93,16 +66,17 @@ go_subdir_import.multicpptest: INTERFACE='testdir/go_subdir_import/go_subdir_import_b.i' \ GOMOD="go_subdir_import" \ $(LANGUAGE)$(VARIANT)_cpp; - for f in testdir/go_subdir_import/go_subdir_import_c go_subdir_import_a ; do \ - $(MAKE) -f $(top_builddir)/$(EXAMPLES)/Makefile SRCDIR='$(SRCDIR)' CXXSRCS='$(CXXSRCS)' \ - SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \ - LIBS='$(LIBS)' INCLUDES='$(INCLUDES)' SWIGOPT='$(SWIGOPT)' NOLINK=true \ - TARGET="$(TARGETPREFIX)$${f}$(TARGETSUFFIX)" INTERFACEDIR='$(INTERFACEDIR)' INTERFACE="$$f.i" \ - GOMOD="go_subdir_import" \ - $(LANGUAGE)$(VARIANT)_cpp; \ + +for f in testdir/go_subdir_import/go_subdir_import_c go_subdir_import_a ; do \ + $(call swig_and_compile_cpp_helper,$${f},'$(SWIGOPT)') GOMOD="go_subdir_import"; \ done $(run_multi_testcase) +go_multicpp_setup = \ + mkdir -p gopath/$*/src 2>/dev/null || true; \ + if ! test -d gopath/$*/src/swigtests; then \ + (cd gopath/$*/src && ln -s . swigtests); \ + fi + # Runs the testcase. run_testcase = \ if test -f $(SCRIPTDIR)/$(SCRIPTPREFIX)$*$(SCRIPTSUFFIX); then \ From ffe2f85417c0313b35387e266b539dd275f9cd6d Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Sun, 27 Mar 2022 12:44:19 +0100 Subject: [PATCH 383/662] go_multicpp_setup make function correction --- Examples/test-suite/go/Makefile.in | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Examples/test-suite/go/Makefile.in b/Examples/test-suite/go/Makefile.in index 3f1bbea4e..a0da7f180 100644 --- a/Examples/test-suite/go/Makefile.in +++ b/Examples/test-suite/go/Makefile.in @@ -43,7 +43,7 @@ INCLUDES = -I$(abs_top_srcdir)/$(EXAMPLES)/$(TEST_SUITE) %.multicpptest: $(setup) - $(call go_multicpp_setup,$*) + $(go_multicpp_setup) +for f in `cat $(top_srcdir)/$(EXAMPLES)/$(TEST_SUITE)/$*.list` ; do \ $(call swig_and_compile_cpp_helper,$${f},'$(SWIGOPT)') GOMOD="$*"; \ done @@ -55,7 +55,7 @@ li_windows.cpptest: go_subdir_import.multicpptest: $(setup) - $(call go_multicpp_setup,go_subdir_import) + $(go_multicpp_setup) mkdir -p testdir/go_subdir_import 2>/dev/null || true mkdir -p gopath/go_subdir_import/src/testdir/go_subdir_import 2>/dev/null || true $(MAKE) -f $(top_builddir)/$(EXAMPLES)/Makefile SRCDIR='$(SRCDIR)' CXXSRCS='$(CXXSRCS)' \ From a71c318b06232697bac8e8312316e70eac3e1f7e Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Sun, 27 Mar 2022 13:33:02 +0100 Subject: [PATCH 384/662] Stop testing two recently failing ocaml tests Problem here seems to be one also affecting other ocaml broken tests: 1. Enum value names should be using sym:name not name (ie %rename is broken for ocaml enum items) 2. directorin typemaps are not correct --- Examples/test-suite/ocaml/Makefile.in | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Examples/test-suite/ocaml/Makefile.in b/Examples/test-suite/ocaml/Makefile.in index 10b537e4c..e9253b920 100644 --- a/Examples/test-suite/ocaml/Makefile.in +++ b/Examples/test-suite/ocaml/Makefile.in @@ -25,10 +25,12 @@ director_enum \ director_primitives \ director_redefined \ director_string \ +director_using_member_scopes \ enum_thorough \ li_windows \ member_pointer_const \ preproc_constants \ +rename_camel \ smart_pointer_inherit \ FAILING_C_TESTS = \ From f44153069b86c8e195b9c0d33eb2d7dfa95859f9 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Sun, 27 Mar 2022 13:50:30 +0100 Subject: [PATCH 385/662] Ocaml test-suite 'passes' with c++11 testing now Test c++17 on Github Actions to try keep it passing when configure detects g++ can test c++17. --- .github/workflows/ci.yml | 1 + Examples/test-suite/cpp11_rvalue_reference2.i | 10 +++++----- Examples/test-suite/cpp11_template_explicit.i | 2 +- Examples/test-suite/cpp11_userdefined_literals.i | 4 ++-- Examples/test-suite/ocaml/Makefile.in | 2 ++ 5 files changed, 11 insertions(+), 8 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 88fd32328..731bcffae 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -296,6 +296,7 @@ jobs: - SWIGLANG: mzscheme continue-on-error: true - SWIGLANG: ocaml + CPPSTD: c++17 continue-on-error: true os: ubuntu-18.04 # ocaml-4.08 in ubuntu-20.04 not yet working # Run all of them, as opposed to aborting when one fails diff --git a/Examples/test-suite/cpp11_rvalue_reference2.i b/Examples/test-suite/cpp11_rvalue_reference2.i index a2a0020f5..a3af6daf8 100644 --- a/Examples/test-suite/cpp11_rvalue_reference2.i +++ b/Examples/test-suite/cpp11_rvalue_reference2.i @@ -20,10 +20,10 @@ static const bool PublicGlobalTrue = true; static const UserDef PublicUserDef = UserDef(); struct Thingy { typedef int Integer; - int val; + int valval; int &lvalref; int &&rvalref; - Thingy(int v, int &&rvalv) : val(v), lvalref(val), rvalref(std::move(rvalv)) {} + Thingy(int v, int &&rvalv) : valval(v), lvalref(valval), rvalref(std::move(rvalv)) {} void refIn(long &i) {} void rvalueIn(long &&i) {} short && rvalueInOut(short &&i) { return std::move(i); } @@ -31,10 +31,10 @@ struct Thingy { // test both primitive and user defined rvalue reference default arguments and compactdefaultargs void compactDefaultArgs(const bool &&b = (const bool &&)PublicGlobalTrue, const UserDef &&u = (const UserDef &&)PublicUserDef) {} void privateDefaultArgs(const bool &&b = (const bool &&)PrivateTrue) {} - operator int &&() { return std::move(val); } - Thingy(const Thingy& rhs) : val(rhs.val), lvalref(rhs.lvalref), rvalref(std::move(rhs.rvalref)) {} + operator int &&() { return std::move(valval); } + Thingy(const Thingy& rhs) : valval(rhs.valval), lvalref(rhs.lvalref), rvalref(std::move(rhs.rvalref)) {} Thingy& operator=(const Thingy& rhs) { - val = rhs.val; + valval = rhs.valval; lvalref = rhs.lvalref; rvalref = rhs.rvalref; return *this; diff --git a/Examples/test-suite/cpp11_template_explicit.i b/Examples/test-suite/cpp11_template_explicit.i index 630342862..950f1d265 100644 --- a/Examples/test-suite/cpp11_template_explicit.i +++ b/Examples/test-suite/cpp11_template_explicit.i @@ -12,7 +12,7 @@ template class Temper { public: - T val; + T valu; }; class A { diff --git a/Examples/test-suite/cpp11_userdefined_literals.i b/Examples/test-suite/cpp11_userdefined_literals.i index 43103cc8c..9284739cd 100644 --- a/Examples/test-suite/cpp11_userdefined_literals.i +++ b/Examples/test-suite/cpp11_userdefined_literals.i @@ -17,8 +17,8 @@ #include struct OutputType { - int val; - OutputType(int v) : val(v) {} + int valu; + OutputType(int v) : valu(v) {} }; // Raw literal diff --git a/Examples/test-suite/ocaml/Makefile.in b/Examples/test-suite/ocaml/Makefile.in index e9253b920..68fea58fc 100644 --- a/Examples/test-suite/ocaml/Makefile.in +++ b/Examples/test-suite/ocaml/Makefile.in @@ -17,6 +17,8 @@ FAILING_CPP_TESTS = \ allprotected \ apply_signed_char \ apply_strings \ +cpp11_director_enums \ +cpp11_strongly_typed_enumerations \ cpp_enum \ default_constructor \ director_binary_string \ From 282fdb17159cb6153d69ebba2c9b5a105b4c747d Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Sun, 27 Mar 2022 15:06:47 +0100 Subject: [PATCH 386/662] MzScheme 'passes' with c++11 testing now Test c++17 on Github Actions to try keep it passing when configure detects g++ can test c++17. --- .github/workflows/ci.yml | 1 + Examples/test-suite/common.mk | 1 + Examples/test-suite/mzscheme/Makefile.in | 5 +++++ 3 files changed, 7 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 731bcffae..65ec30886 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -294,6 +294,7 @@ jobs: GCC: 11 # Experimental languages (these are allowed to fail) - SWIGLANG: mzscheme + CPPSTD: c++17 continue-on-error: true - SWIGLANG: ocaml CPPSTD: c++17 diff --git a/Examples/test-suite/common.mk b/Examples/test-suite/common.mk index f887037d9..c9c9e373b 100644 --- a/Examples/test-suite/common.mk +++ b/Examples/test-suite/common.mk @@ -774,6 +774,7 @@ command_line_define.ctest: SWIGOPT += -DFOO # Allow modules to define temporarily failing tests. C_TEST_CASES := $(filter-out $(FAILING_C_TESTS),$(C_TEST_CASES)) CPP_TEST_CASES := $(filter-out $(FAILING_CPP_TESTS),$(CPP_TEST_CASES)) +CPP11_TEST_CASES := $(filter-out $(FAILING_CPP_TESTS),$(CPP11_TEST_CASES)) MULTI_CPP_TEST_CASES := $(filter-out $(FAILING_MULTI_CPP_TESTS),$(MULTI_CPP_TEST_CASES)) diff --git a/Examples/test-suite/mzscheme/Makefile.in b/Examples/test-suite/mzscheme/Makefile.in index 6a8ef74e4..e3fe17313 100644 --- a/Examples/test-suite/mzscheme/Makefile.in +++ b/Examples/test-suite/mzscheme/Makefile.in @@ -19,6 +19,11 @@ char_strings \ chartest \ class_scope_weird \ constant_pointers \ +cpp11_alternate_function_syntax \ +cpp11_director_enums \ +cpp11_ref_qualifiers \ +cpp11_rvalue_reference2 \ +cpp11_strongly_typed_enumerations \ cpp_basic \ cpp_enum \ curiously_recurring_template_pattern \ From cbd9bd6d71c4265f5347bd6a37bd9e3b5e7c896f Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Sun, 27 Mar 2022 16:43:30 +0100 Subject: [PATCH 387/662] Fix running make-cpp11 for ocaml --- Examples/test-suite/ocaml/Makefile.in | 1 + 1 file changed, 1 insertion(+) diff --git a/Examples/test-suite/ocaml/Makefile.in b/Examples/test-suite/ocaml/Makefile.in index 68fea58fc..995f7f49b 100644 --- a/Examples/test-suite/ocaml/Makefile.in +++ b/Examples/test-suite/ocaml/Makefile.in @@ -97,6 +97,7 @@ extra_objects: swig.cmi swig.cmo swigp4.cmi $(C_TEST_CASES:=.ctest): extra_objects $(CPP_TEST_CASES:=.cpptest): extra_objects +$(CPP11_TEST_CASES:=.cpptest): extra_objects $(MULTI_CPP_TEST_CASES:=.multicpptest): extra_objects # Clean From 27d6f5c2fef0abe43208cbb6a2f4f11e1e144881 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Sun, 27 Mar 2022 18:28:49 +0100 Subject: [PATCH 388/662] git commit -m "Fix test-suite's make clean to clean cpp11 testcases Always clean cpp11 tests even if --enable-cpp11-testing is not active May result in cpp11 tests being deleted twice though" ../ --- Examples/test-suite/common.mk | 1 + 1 file changed, 1 insertion(+) diff --git a/Examples/test-suite/common.mk b/Examples/test-suite/common.mk index c9c9e373b..96660c0d7 100644 --- a/Examples/test-suite/common.mk +++ b/Examples/test-suite/common.mk @@ -787,6 +787,7 @@ BROKEN_TEST_CASES = $(CPP_TEST_BROKEN:=.cpptest) \ $(C_TEST_BROKEN:=.ctest) ALL_CLEAN = $(CPP_TEST_CASES:=.clean) \ + $(CPP11_TEST_CASES:=.clean) \ $(C_TEST_CASES:=.clean) \ $(MULTI_CPP_TEST_CASES:=.clean) \ $(CPP_TEST_BROKEN:=.clean) \ From 5cc4591ae77416d8f8be23fa7d5a622eba5e8240 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Sun, 27 Mar 2022 19:34:20 +0100 Subject: [PATCH 389/662] Consistent cpp11 testing in test-suite Move HAVE_CXX11 into makefiles so that running test-suite from top level directory or in the language's test-suite directory is consistent. For example, running 'make check-java-test-suite' behaves the same as 'cd Examples/test-suite/java && make check'. --- Examples/test-suite/cffi/Makefile.in | 1 + Examples/test-suite/csharp/Makefile.in | 1 + Examples/test-suite/d/Makefile.in | 1 + Examples/test-suite/errors/Makefile.in | 1 + Examples/test-suite/go/Makefile.in | 1 + Examples/test-suite/guile/Makefile.in | 1 + Examples/test-suite/java/Makefile.in | 1 + Examples/test-suite/javascript/Makefile.in | 1 + Examples/test-suite/lua/Makefile.in | 1 + Examples/test-suite/mzscheme/Makefile.in | 1 + Examples/test-suite/ocaml/Makefile.in | 1 + Examples/test-suite/octave/Makefile.in | 1 + Examples/test-suite/perl5/Makefile.in | 1 + Examples/test-suite/php/Makefile.in | 1 + Examples/test-suite/python/Makefile.in | 1 + Examples/test-suite/r/Makefile.in | 1 + Examples/test-suite/ruby/Makefile.in | 1 + Examples/test-suite/scilab/Makefile.in | 1 + Examples/test-suite/tcl/Makefile.in | 1 + Makefile.in | 3 +-- 20 files changed, 20 insertions(+), 2 deletions(-) diff --git a/Examples/test-suite/cffi/Makefile.in b/Examples/test-suite/cffi/Makefile.in index b2e86e102..1ce64675a 100644 --- a/Examples/test-suite/cffi/Makefile.in +++ b/Examples/test-suite/cffi/Makefile.in @@ -6,6 +6,7 @@ LANGUAGE = cffi CFFI = @CFFIBIN@ SCRIPTSUFFIX = _runme.lisp +HAVE_CXX11 = @HAVE_CXX11@ srcdir = @srcdir@ top_srcdir = @top_srcdir@ top_builddir = @top_builddir@ diff --git a/Examples/test-suite/csharp/Makefile.in b/Examples/test-suite/csharp/Makefile.in index 02dcaafb0..74010c284 100644 --- a/Examples/test-suite/csharp/Makefile.in +++ b/Examples/test-suite/csharp/Makefile.in @@ -8,6 +8,7 @@ CSHARPCILINTERPRETER = @CSHARPCILINTERPRETER@ CSHARPCILINTERPRETER_FLAGS = @CSHARPCILINTERPRETER_FLAGS@ CSHARPCONVERTPATH = @top_srcdir@/@CSHARPCONVERTPATH@ +HAVE_CXX11 = @HAVE_CXX11@ srcdir = @srcdir@ top_srcdir = ../@top_srcdir@ top_builddir = ../@top_builddir@ diff --git a/Examples/test-suite/d/Makefile.in b/Examples/test-suite/d/Makefile.in index a20cfb4e3..e6b4e2d18 100644 --- a/Examples/test-suite/d/Makefile.in +++ b/Examples/test-suite/d/Makefile.in @@ -4,6 +4,7 @@ LANGUAGE = d +HAVE_CXX11 = @HAVE_CXX11@ srcdir = @srcdir@ top_srcdir = ../@top_srcdir@ top_builddir = ../@top_builddir@ diff --git a/Examples/test-suite/errors/Makefile.in b/Examples/test-suite/errors/Makefile.in index 7137a6862..97c7d5c76 100644 --- a/Examples/test-suite/errors/Makefile.in +++ b/Examples/test-suite/errors/Makefile.in @@ -16,6 +16,7 @@ LANGUAGE = errors ERROR_EXT = newerr +HAVE_CXX11 = @HAVE_CXX11@ srcdir = @srcdir@ top_srcdir = @top_srcdir@ top_builddir = @top_builddir@ diff --git a/Examples/test-suite/go/Makefile.in b/Examples/test-suite/go/Makefile.in index a0da7f180..67f96cf7e 100644 --- a/Examples/test-suite/go/Makefile.in +++ b/Examples/test-suite/go/Makefile.in @@ -12,6 +12,7 @@ SCRIPTSUFFIX = _runme.go SO = @SO@ +HAVE_CXX11 = @HAVE_CXX11@ srcdir = @srcdir@ top_srcdir = @top_srcdir@ top_builddir = @top_builddir@ diff --git a/Examples/test-suite/guile/Makefile.in b/Examples/test-suite/guile/Makefile.in index 55885fc29..1fda5dc9c 100644 --- a/Examples/test-suite/guile/Makefile.in +++ b/Examples/test-suite/guile/Makefile.in @@ -8,6 +8,7 @@ LANGUAGE = guile VARIANT = SCRIPTSUFFIX = _runme.scm +HAVE_CXX11 = @HAVE_CXX11@ srcdir = @srcdir@ top_srcdir = @top_srcdir@ top_builddir = @top_builddir@ diff --git a/Examples/test-suite/java/Makefile.in b/Examples/test-suite/java/Makefile.in index e2a3d2472..7a34f587b 100644 --- a/Examples/test-suite/java/Makefile.in +++ b/Examples/test-suite/java/Makefile.in @@ -11,6 +11,7 @@ JAVA_TOOLS_JAR = @JAVA_TOOLS_JAR@ SCRIPTSUFFIX = _runme.java SKIP_DOXYGEN_TEST_CASES = @JAVA_SKIP_DOXYGEN_TEST_CASES@ +HAVE_CXX11 = @HAVE_CXX11@ srcdir = @srcdir@ top_srcdir = ../@top_srcdir@ top_builddir = ../@top_builddir@ diff --git a/Examples/test-suite/javascript/Makefile.in b/Examples/test-suite/javascript/Makefile.in index 4f2d450e5..57b6eac75 100644 --- a/Examples/test-suite/javascript/Makefile.in +++ b/Examples/test-suite/javascript/Makefile.in @@ -9,6 +9,7 @@ SCRIPTSUFFIX = _runme.js OBJEXT = @OBJEXT@ SO = @SO@ +HAVE_CXX11 = @HAVE_CXX11@ srcdir = @srcdir@ top_srcdir = @top_srcdir@ top_builddir = @top_builddir@ diff --git a/Examples/test-suite/lua/Makefile.in b/Examples/test-suite/lua/Makefile.in index c0730466f..2d4100d1b 100644 --- a/Examples/test-suite/lua/Makefile.in +++ b/Examples/test-suite/lua/Makefile.in @@ -6,6 +6,7 @@ LANGUAGE = lua LUA = @LUABIN@ SCRIPTSUFFIX = _runme.lua +HAVE_CXX11 = @HAVE_CXX11@ srcdir = @srcdir@ top_srcdir = @top_srcdir@ top_builddir = @top_builddir@ diff --git a/Examples/test-suite/mzscheme/Makefile.in b/Examples/test-suite/mzscheme/Makefile.in index e3fe17313..93dbb4ba1 100644 --- a/Examples/test-suite/mzscheme/Makefile.in +++ b/Examples/test-suite/mzscheme/Makefile.in @@ -6,6 +6,7 @@ LANGUAGE = mzscheme MZSCHEME = mzscheme SCRIPTSUFFIX = _runme.scm +HAVE_CXX11 = @HAVE_CXX11@ srcdir = @srcdir@ top_srcdir = @top_srcdir@ top_builddir = @top_builddir@ diff --git a/Examples/test-suite/ocaml/Makefile.in b/Examples/test-suite/ocaml/Makefile.in index 995f7f49b..79e25efcf 100644 --- a/Examples/test-suite/ocaml/Makefile.in +++ b/Examples/test-suite/ocaml/Makefile.in @@ -9,6 +9,7 @@ OCAMLPP = -pp "camlp4o ./swigp4.cmo" VARIANT = _static SCRIPTSUFFIX = _runme.ml +HAVE_CXX11 = @HAVE_CXX11@ srcdir = @srcdir@ top_srcdir = @top_srcdir@ top_builddir = @top_builddir@ diff --git a/Examples/test-suite/octave/Makefile.in b/Examples/test-suite/octave/Makefile.in index 9602d85f5..81696b3ff 100644 --- a/Examples/test-suite/octave/Makefile.in +++ b/Examples/test-suite/octave/Makefile.in @@ -7,6 +7,7 @@ OCTAVE = @OCTAVE@ SCRIPTSUFFIX = _runme.m PCHSUPPORT = @PCHSUPPORT@ +HAVE_CXX11 = @HAVE_CXX11@ srcdir = @srcdir@ top_srcdir = @top_srcdir@ top_builddir = @top_builddir@ diff --git a/Examples/test-suite/perl5/Makefile.in b/Examples/test-suite/perl5/Makefile.in index 6388e5b32..3fb3ebac6 100644 --- a/Examples/test-suite/perl5/Makefile.in +++ b/Examples/test-suite/perl5/Makefile.in @@ -7,6 +7,7 @@ PERL = @PERL@ SCRIPTSUFFIX = _runme.pl TEST_RUNNER = $(srcdir)/run-perl-test.pl +HAVE_CXX11 = @HAVE_CXX11@ srcdir = @srcdir@ top_srcdir = @top_srcdir@ top_builddir = @top_builddir@ diff --git a/Examples/test-suite/php/Makefile.in b/Examples/test-suite/php/Makefile.in index a31eedbee..c460bff28 100644 --- a/Examples/test-suite/php/Makefile.in +++ b/Examples/test-suite/php/Makefile.in @@ -5,6 +5,7 @@ LANGUAGE = php SCRIPTSUFFIX = _runme.php +HAVE_CXX11 = @HAVE_CXX11@ srcdir = @srcdir@ top_srcdir = @top_srcdir@ top_builddir = @top_builddir@ diff --git a/Examples/test-suite/python/Makefile.in b/Examples/test-suite/python/Makefile.in index ccd5ca513..c061f903a 100644 --- a/Examples/test-suite/python/Makefile.in +++ b/Examples/test-suite/python/Makefile.in @@ -14,6 +14,7 @@ SCRIPTSUFFIX = _runme.py PYCODESTYLE = @PYCODESTYLE@ PYCODESTYLE_FLAGS = --ignore=E252,E30,E402,E501,E731,E741,W291,W391 +HAVE_CXX11 = @HAVE_CXX11@ srcdir = @srcdir@ top_srcdir = @top_srcdir@ top_builddir = @top_builddir@ diff --git a/Examples/test-suite/r/Makefile.in b/Examples/test-suite/r/Makefile.in index 33e9d90da..484dea375 100644 --- a/Examples/test-suite/r/Makefile.in +++ b/Examples/test-suite/r/Makefile.in @@ -8,6 +8,7 @@ WRAPSUFFIX = .R R_OPT = --quiet --no-save --no-restore RUNR = R CMD BATCH $(R_OPT) '--args $(SCRIPTDIR)' +HAVE_CXX11 = @HAVE_CXX11@ srcdir = @srcdir@ top_srcdir = @top_srcdir@ top_builddir = @top_builddir@ diff --git a/Examples/test-suite/ruby/Makefile.in b/Examples/test-suite/ruby/Makefile.in index f982eca1f..3b673bf71 100644 --- a/Examples/test-suite/ruby/Makefile.in +++ b/Examples/test-suite/ruby/Makefile.in @@ -6,6 +6,7 @@ LANGUAGE = ruby RUBY = @RUBY@ SCRIPTSUFFIX = _runme.rb +HAVE_CXX11 = @HAVE_CXX11@ srcdir = @srcdir@ top_srcdir = @top_srcdir@ top_builddir = @top_builddir@ diff --git a/Examples/test-suite/scilab/Makefile.in b/Examples/test-suite/scilab/Makefile.in index f873b8687..e1effcd64 100644 --- a/Examples/test-suite/scilab/Makefile.in +++ b/Examples/test-suite/scilab/Makefile.in @@ -7,6 +7,7 @@ SCILAB = @SCILAB@ SCILAB_OPT = @SCILABOPT@ SCRIPTSUFFIX = _runme.sci +HAVE_CXX11 = @HAVE_CXX11@ srcdir = @srcdir@ top_srcdir = ../@top_srcdir@ top_builddir = ../@top_builddir@ diff --git a/Examples/test-suite/tcl/Makefile.in b/Examples/test-suite/tcl/Makefile.in index 322e71914..84a7299f7 100644 --- a/Examples/test-suite/tcl/Makefile.in +++ b/Examples/test-suite/tcl/Makefile.in @@ -6,6 +6,7 @@ LANGUAGE = tcl TCLSH = tclsh SCRIPTSUFFIX = _runme.tcl +HAVE_CXX11 = @HAVE_CXX11@ srcdir = @srcdir@ top_srcdir = @top_srcdir@ top_builddir = @top_builddir@ diff --git a/Makefile.in b/Makefile.in index 6edfc240a..f4cb794d8 100644 --- a/Makefile.in +++ b/Makefile.in @@ -29,7 +29,6 @@ TARGET = $(TARGET_NOEXE)@EXEEXT@ SOURCE = Source CCACHE = CCache DOCS = Doc/Manual -HAVE_CXX11 = @HAVE_CXX11@ swig: libfiles source ccache @@ -249,7 +248,7 @@ check-%-test-suite: echo warning: cannot $(ACTION) $* test-suite "(no dir $$dir)";\ else \ echo $(ACTION)ing $* test-suite; \ - (cd $$dir && $(MAKE) $(FLAGS) $(ACTION) HAVE_CXX11=$(HAVE_CXX11)) \ + (cd $$dir && $(MAKE) $(FLAGS) $(ACTION)) \ || passed=false; \ fi; \ test $$passed = true From 2ded25d138ba51152087aebde9ab5c2d685519fc Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Mon, 28 Mar 2022 09:15:57 +0100 Subject: [PATCH 390/662] Fixes for ISO C89 --- Source/CParse/cscanner.c | 3 ++- Source/Swig/naming.c | 2 +- Source/Swig/tree.c | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/Source/CParse/cscanner.c b/Source/CParse/cscanner.c index 85d350cdc..a658f5a6f 100644 --- a/Source/CParse/cscanner.c +++ b/Source/CParse/cscanner.c @@ -955,6 +955,7 @@ int yylex(void) { } else { /* SWIG directives */ + String *stext = 0; if (strcmp(yytext, "%module") == 0) return (MODULE); if (strcmp(yytext, "%insert") == 0) @@ -1041,7 +1042,7 @@ int yylex(void) { * the operator. */ cparse_unknown_directive = NewString(yytext); - String *stext = NewString(yytext + 1); + stext = NewString(yytext + 1); Seek(stext,0,SEEK_SET); Setfile(stext,cparse_file); Setline(stext,cparse_line); diff --git a/Source/Swig/naming.c b/Source/Swig/naming.c index 1599941b7..4d07d5b2f 100644 --- a/Source/Swig/naming.c +++ b/Source/Swig/naming.c @@ -1101,6 +1101,7 @@ static int name_regexmatch_value(Node *n, String *pattern, String *s) { int errornum; size_t errpos; int rc; + pcre2_match_data *match_data = 0; compiled_pat = pcre2_compile((PCRE2_SPTR8)Char(pattern), PCRE2_ZERO_TERMINATED, 0, &errornum, &errpos, NULL); if (!compiled_pat) { @@ -1111,7 +1112,6 @@ static int name_regexmatch_value(Node *n, String *pattern, String *s) { Exit(EXIT_FAILURE); } - pcre2_match_data *match_data = 0; match_data = pcre2_match_data_create_from_pattern (compiled_pat, NULL); rc = pcre2_match(compiled_pat, (PCRE2_SPTR8)Char(s), PCRE2_ZERO_TERMINATED, 0, 0, match_data, 0); pcre2_code_free(compiled_pat); diff --git a/Source/Swig/tree.c b/Source/Swig/tree.c index bc552988c..7033bbefb 100644 --- a/Source/Swig/tree.c +++ b/Source/Swig/tree.c @@ -80,6 +80,7 @@ static void print_indent(int l) { void Swig_print_node(Node *obj) { Iterator ki; Node *cobj; + List *keys = Keys(obj); print_indent(0); if (debug_quiet) @@ -87,7 +88,6 @@ void Swig_print_node(Node *obj) { else Printf(stdout, "+++ %s - %p ----------------------------------------\n", nodeType(obj), obj); - List *keys = Keys(obj); SortList(keys, 0); ki = First(keys); while (ki.item) { From e1e4e4df285bfdb2de3de49cf2409783de4ae79a Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Mon, 28 Mar 2022 09:16:46 +0100 Subject: [PATCH 391/662] Add rvalue reference typemaps for D --- Lib/d/dswigtype.swg | 43 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/Lib/d/dswigtype.swg b/Lib/d/dswigtype.swg index f0d604b6f..1d97cb089 100644 --- a/Lib/d/dswigtype.swg +++ b/Lib/d/dswigtype.swg @@ -20,6 +20,10 @@ %typemap(imtype) SWIGTYPE & "void*" %typemap(dtype, nativepointer="$dtype") SWIGTYPE & "$dclassname" +%typemap(ctype) SWIGTYPE && "void *" +%typemap(imtype) SWIGTYPE && "void*" +%typemap(dtype, nativepointer="$dtype") SWIGTYPE && "$dclassname" + %typemap(ctype) SWIGTYPE *const& "void *" %typemap(imtype) SWIGTYPE *const& "void*" %typemap(dtype) SWIGTYPE *const& "$*dclassname" @@ -28,6 +32,7 @@ SWIGTYPE, SWIGTYPE *, SWIGTYPE &, + SWIGTYPE &&, SWIGTYPE [], SWIGTYPE *const& "" @@ -148,6 +153,43 @@ } +/* + * Rvalue reference conversion typemaps. + */ + +%typemap(in, canthrow=1) SWIGTYPE && %{ $1 = ($1_ltype)$input; + if (!$1) { + SWIG_DSetPendingException(SWIG_DIllegalArgumentException, "$1_type type is null"); + return $null; + } %} +%typemap(out) SWIGTYPE && "$result = (void *)$1;" + +%typemap(directorin) SWIGTYPE && + "$input = ($1_ltype) &$1;" +%typemap(directorout, warning=SWIGWARN_TYPEMAP_DIRECTOROUT_PTR_MSG) SWIGTYPE && +%{ if (!$input) { + SWIG_DSetPendingException(SWIG_DIllegalArgumentException, "Unexpected null return for type $1_type"); + return $null; + } + $result = ($1_ltype)$input; %} + +%typemap(ddirectorin, + nativepointer="cast($dtype)$winput" +) SWIGTYPE && "new $dclassname($winput, false)" +%typemap(ddirectorout, + nativepointer="cast(void*)$dcall" +) SWIGTYPE && "$dclassname.swigGetCPtr($dcall)" + +%typemap(din, + nativepointer="cast(void*)$dinput" +) SWIGTYPE && "$dclassname.swigGetCPtr($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 + return ret; +} + + /* * Array conversion typemaps. */ @@ -164,6 +206,7 @@ // Treat references to arrays like references to a single element. %apply SWIGTYPE & { SWIGTYPE ((&)[ANY]) } +%apply SWIGTYPE && { SWIGTYPE ((&&)[ANY]) } /* From 8be06d0e8c09b17338fef7585886444718c64d2c Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Mon, 28 Mar 2022 09:21:46 +0100 Subject: [PATCH 392/662] Correct MzScheme and OCaml GHA testing --- .github/workflows/ci.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 65ec30886..48c3d0459 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -295,9 +295,11 @@ jobs: # Experimental languages (these are allowed to fail) - SWIGLANG: mzscheme CPPSTD: c++17 + GCC: 11 continue-on-error: true - SWIGLANG: ocaml CPPSTD: c++17 + GCC: 11 continue-on-error: true os: ubuntu-18.04 # ocaml-4.08 in ubuntu-20.04 not yet working # Run all of them, as opposed to aborting when one fails From 0b157406638dc0a37b01a9f498577a2a72e9108c Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Mon, 28 Mar 2022 19:30:47 +0100 Subject: [PATCH 393/662] Fix warning in D test-suite --- .../test-suite/csharp/multiple_inheritance_overload_runme.cs | 4 ++-- .../test-suite/java/multiple_inheritance_overload_runme.java | 4 ++-- Examples/test-suite/multiple_inheritance_overload.i | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Examples/test-suite/csharp/multiple_inheritance_overload_runme.cs b/Examples/test-suite/csharp/multiple_inheritance_overload_runme.cs index 4036722a9..24a284931 100644 --- a/Examples/test-suite/csharp/multiple_inheritance_overload_runme.cs +++ b/Examples/test-suite/csharp/multiple_inheritance_overload_runme.cs @@ -29,7 +29,7 @@ public class multiple_inheritance_overload_runme { check(d1.AnotherMethod(i) != 0, "d1.AnotherMethod failed"); - Base db1 = BaseSwigImpl.inout(d1); + Base db1 = BaseSwigImpl.in_out(d1); check(db1.Method(i) != 0, "db1.Method failed"); check(db1.MethodForRenaming(i) != 0, "db1.MethodForRenaming failed"); check(db1.MethodForRenamingConst(i) != 1, "db1.MethodForRenamingConst failed"); @@ -47,7 +47,7 @@ public class multiple_inheritance_overload_runme { check(m1.AnotherMethod(i) != 0, "m1.AnotherMethod failed"); - Base mb2 = BaseSwigImpl.inout(m1); + Base mb2 = BaseSwigImpl.in_out(m1); check(mb2.Method(i) != 0, "mb2.Method failed"); check(mb2.MethodForRenaming(i) != 0, "mb2.MethodForRenaming failed"); check(mb2.MethodForRenamingConst(i) != 1, "mb2.MethodForRenamingConst failed"); diff --git a/Examples/test-suite/java/multiple_inheritance_overload_runme.java b/Examples/test-suite/java/multiple_inheritance_overload_runme.java index d2cc3ed71..e516e7738 100644 --- a/Examples/test-suite/java/multiple_inheritance_overload_runme.java +++ b/Examples/test-suite/java/multiple_inheritance_overload_runme.java @@ -36,7 +36,7 @@ public class multiple_inheritance_overload_runme { check(d1.AnotherMethod(i) != 0, "d1.AnotherMethod failed"); - Base db1 = BaseSwigImpl.inout(d1); + Base db1 = BaseSwigImpl.in_out(d1); check(db1.Method(i) != 0, "db1.Method failed"); check(db1.MethodForRenaming(i) != 0, "db1.MethodForRenaming failed"); check(db1.MethodForRenamingConst(i) != 1, "db1.MethodForRenamingConst failed"); @@ -54,7 +54,7 @@ public class multiple_inheritance_overload_runme { check(m1.AnotherMethod(i) != 0, "m1.AnotherMethod failed"); - Base mb2 = BaseSwigImpl.inout(m1); + Base mb2 = BaseSwigImpl.in_out(m1); check(mb2.Method(i) != 0, "mb2.Method failed"); check(mb2.MethodForRenaming(i) != 0, "mb2.MethodForRenaming failed"); check(mb2.MethodForRenamingConst(i) != 1, "mb2.MethodForRenamingConst failed"); diff --git a/Examples/test-suite/multiple_inheritance_overload.i b/Examples/test-suite/multiple_inheritance_overload.i index 77f5a9ad4..237ebd6f1 100644 --- a/Examples/test-suite/multiple_inheritance_overload.i +++ b/Examples/test-suite/multiple_inheritance_overload.i @@ -47,7 +47,7 @@ public: virtual int SimilarOverloadedMethod(Integer i) { return 0; } virtual int SimilarOverloadedMethod(unsigned short i) { return 1; } virtual ~Base() {} - static Base *inout(Base *p) { return p; } + static Base *in_out(Base *p) { return p; } }; class Derived : public Base, public AnotherSpace::AnotherBase From 4c074415498ff47cf79cf05215f1803d4c79177d Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Tue, 29 Mar 2022 09:01:18 +0100 Subject: [PATCH 394/662] GHA: MzScheme go back to c++98 testing MzScheme headers have a problem when using -Werror that the test-suite uses: /usr/include/racket/sconfig.h:126:43: error: invalid suffix on literal; C++11 requires a space between literal and string macro [-Werror=literal-suffix] 126 | # define SCHEME_PLATFORM_LIBRARY_SUBPATH "x86_64-"SPLS_LINUX --- .github/workflows/ci.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 48c3d0459..2f9d128b7 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -294,8 +294,6 @@ jobs: GCC: 11 # Experimental languages (these are allowed to fail) - SWIGLANG: mzscheme - CPPSTD: c++17 - GCC: 11 continue-on-error: true - SWIGLANG: ocaml CPPSTD: c++17 From ef3f25ab1c03d37802d9c228a5dab2946b549a3b Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Fri, 1 Apr 2022 11:24:15 +1300 Subject: [PATCH 395/662] Remove -browse command line option MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This option was undocumented. If used it quietly did nothing unless you'd installed the SWILL library before building SWIG, but SWILL is no longer maintained and hasn't seen a release since 2008-04-10. It's clear nobody has used this functionality for some time as the code to support it in SWIG isn't actually valid ISO C++: Modules/browser.cxx: In member function ‘void Browser::show_attributes(Node*)’: Modules/browser.cxx:57:23: warning: ISO C++ forbids converting a string constant to ‘char*’ [-Wwrite-strings] 57 | char *trunc = ""; | ^~ Modules/browser.cxx:61:21: warning: ISO C++ forbids converting a string constant to ‘char*’ [-Wwrite-strings] 61 | trunc = "..."; | ^~~~~ Closes #2251 --- CHANGES.current | 3 + Source/Makefile.am | 6 +- Source/Modules/browser.cxx | 421 ------------------------------------- Source/Modules/main.cxx | 7 - Source/Modules/swigmod.h | 8 +- configure.ac | 4 - 6 files changed, 7 insertions(+), 442 deletions(-) delete mode 100644 Source/Modules/browser.cxx diff --git a/CHANGES.current b/CHANGES.current index 7ce58028d..99581a84b 100644 --- a/CHANGES.current +++ b/CHANGES.current @@ -7,6 +7,9 @@ the issue number to the end of the URL: https://github.com/swig/swig/issues/ Version 4.1.0 (in progress) =========================== +2022-04-01: olly + Remove undocumented and non-functional -browse command line option. + 2022-03-26: eltoder [Python] #1684 Use different capsule names with and without -builtin diff --git a/Source/Makefile.am b/Source/Makefile.am index 5cfb88839..095c5d4ea 100644 --- a/Source/Makefile.am +++ b/Source/Makefile.am @@ -6,8 +6,6 @@ AUTOMAKE_OPTIONS = foreign nostdinc subdir-objects 1.7.2 SOURCE_DIR=$(top_srcdir)/Source BUILD_SOURCE_DIR=$(top_builddir)/Source -SWIG_CXX_DEFS = @SWILL@ - AM_CPPFLAGS = -I$(BUILD_SOURCE_DIR)/Include \ -I$(BUILD_SOURCE_DIR)/CParse \ -I$(SOURCE_DIR)/Include \ @@ -18,7 +16,7 @@ AM_CPPFLAGS = -I$(BUILD_SOURCE_DIR)/Include \ -I$(SOURCE_DIR)/Swig \ -I$(SOURCE_DIR)/Modules -AM_CXXFLAGS = $(SWIG_CXX_DEFS) +AM_CXXFLAGS = AM_YFLAGS = -d @@ -46,7 +44,6 @@ eswig_SOURCES = CParse/cscanner.c \ Doxygen/pydoc.cxx \ Doxygen/pydoc.h \ Modules/allocate.cxx \ - Modules/browser.cxx \ Modules/contract.cxx \ Modules/csharp.cxx \ Modules/d.cxx \ @@ -98,7 +95,6 @@ eswig_SOURCES = CParse/cscanner.c \ Swig/wrapfunc.c bin_PROGRAMS = eswig -eswig_LDADD = @SWIGLIBS@ # Override the link stage to avoid using Libtool CXXLINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ diff --git a/Source/Modules/browser.cxx b/Source/Modules/browser.cxx deleted file mode 100644 index 217b40a7e..000000000 --- a/Source/Modules/browser.cxx +++ /dev/null @@ -1,421 +0,0 @@ -/* ----------------------------------------------------------------------------- - * This file is part of SWIG, which is licensed as a whole under version 3 - * (or any later version) of the GNU General Public License. Some additional - * terms also apply to certain portions of SWIG. The full details of the SWIG - * license and copyrights can be found in the LICENSE and COPYRIGHT files - * included with the SWIG source code as distributed by the SWIG developers - * and at http://www.swig.org/legal.html. - * - * browser.cxx - * - * A web-base parse tree browser using SWILL. This is an optional - * feature that's normally disabled. - * ----------------------------------------------------------------------------- */ - -#include "swigmod.h" - -#ifdef SWIG_SWILL -extern "C" { -#include "swill.h" -} static FILE *out = 0; -static Node *view_top = 0; - -class Browser:public Dispatcher { - void show_checkbox(Node *t, Node *n) { - int v = 0; - if (Getmeta(n, "visible")) { - v = 1; - } - if (v) { - Printf(out, "[-] ", n, t, n, n); - } else { - Printf(out, "[+] ", n, t, n, n); - } - } - void show_attributes(Node *obj) { - if (!Getmeta(obj, "visible")) - return; - String *os = NewString(""); - String *k; - Iterator ki; - ki = First(obj); - while (ki.key) { - k = ki.key; - if ((Cmp(k, "nodeType") == 0) || (Cmp(k, "firstChild") == 0) || (Cmp(k, "lastChild") == 0) || - (Cmp(k, "parentNode") == 0) || (Cmp(k, "nextSibling") == 0) || (Cmp(k, "previousSibling") == 0) || (*(Char(k)) == '$')) { - /* Do nothing */ - } else if (Cmp(k, "parms") == 0) { - String *o = NewString(""); - Printf(o, "%s", ParmList_protostr(Getattr(obj, k))); - Replaceall(o, "&", "&"); - Replaceall(o, "<", "<"); - Replaceall(o, ">", ">"); - Printf(os, "? %-12s - %s\n", Getattr(obj, k), k, o); - Delete(o); - } else { - DOH *o; - char *trunc = ""; - if (DohIsString(Getattr(obj, k))) { - o = Str(Getattr(obj, k)); - if (Len(o) > 70) { - trunc = "..."; - } - Replaceall(o, "&", "&"); - Replaceall(o, "<", "<"); - Printf(os, "? %-12s - \"%(escape)-0.70s%s\"\n", Getattr(obj, k), k, o, trunc); - Delete(o); - } else { - Printf(os, "? %-12s - %p\n", Getattr(obj, k), k, Getattr(obj, k)); - } - } - ki = Next(ki); - } - Printf(out, "
      \n%s
      \n", Char(os)); - Delete(os); - } - -public: - virtual int emit_one(Node *n) { - char *tag = Char(nodeType(n)); - char *file = Char(Getfile(n)); - int line = Getline(n); - char *name = GetChar(n, "name"); - - show_checkbox(view_top, n); - Printf(out, "%s", n, tag); - if (name) { - Printf(out, " (%s)", name); - } - Printf(out, ". %s:%d\n", file, line); - Printf(out, "
      "); - Dispatcher::emit_one(n); - return SWIG_OK; - } - virtual int emit_children(Node *n) { - if (Getmeta(n, "visible")) { - Printf(out, "
      \n"); - Dispatcher::emit_children(n); - Printf(out, "
      \n"); - } - return SWIG_OK; - } - virtual int defaultHandler(Node *n) { - show_attributes(n); - return SWIG_OK; - } - virtual int top(Node *n) { - show_attributes(n); - emit_children(n); - return SWIG_OK; - } - virtual int includeDirective(Node *n) { - show_attributes(n); - emit_children(n); - return SWIG_OK; - } - virtual int importDirective(Node *n) { - show_attributes(n); - emit_children(n); - return SWIG_OK; - } - - virtual int extendDirective(Node *n) { - show_attributes(n); - emit_children(n); - return SWIG_OK; - } - virtual int classDeclaration(Node *n) { - show_attributes(n); - emit_children(n); - return SWIG_OK; - } - - virtual int templateDeclaration(Node *n) { - show_attributes(n); - emit_children(n); - return SWIG_OK; - } - - virtual int lambdaDeclaration(Node *n) { - show_attributes(n); - emit_children(n); - return SWIG_OK; - } - - virtual int enumDeclaration(Node *n) { - show_attributes(n); - emit_children(n); - return SWIG_OK; - } - virtual int typemapDirective(Node *n) { - show_attributes(n); - emit_children(n); - return SWIG_OK; - } - virtual int namespaceDeclaration(Node *n) { - show_attributes(n); - emit_children(n); - return SWIG_OK; - } - virtual int usingDeclaration(Node *n) { - show_attributes(n); - emit_children(n); - return SWIG_OK; - } - -}; - -static int browser_exit = 0; -static Node *tree_top = 0; -static Browser *browse = 0; - -/* ---------------------------------------------------------------------- - * exit_handler() - Force the browser to exit - * ---------------------------------------------------------------------- */ - -void exit_handler(FILE *f) { - browser_exit = 1; - Printf(f, "Terminated.\n"); -} - -/* ---------------------------------------------------------------------- - * node_handler() - Generate information about a specific node - * ---------------------------------------------------------------------- */ - -static void display(FILE *f, Node *n) { - /* Print standard HTML header */ - - Printf(f, "SWIG-%s\n", Swig_package_version()); - Printf(f, "SWIG-%s
      \n", Swig_package_version()); - Printf(f, "[ Exit ]"); - Printf(f, " [ Top ]", tree_top); - if (n != tree_top) { - Printf(f, " [ Up ]", parentNode(n)); - } - Printf(f, " [ Symbols ]"); - Printf(f, "

      \n"); - - out = f; - - browse->emit_one(n); - - /* Print standard footer */ - Printf(f, "


      \n"); - -} - -void node_handler(FILE *f) { - Node *n = 0; - if (!swill_getargs("p(node)", &n)) { - n = tree_top; - } - view_top = n; - display(f, n); -} - - -/* ---------------------------------------------------------------------- - * hide_handler() - Hide a node - * ---------------------------------------------------------------------- */ - -void hide_handler(FILE *f) { - Node *n = 0; - if (!swill_getargs("p(hn)", &n)) { - n = 0; - } - if (n) { - Delmeta(n, "visible"); - } - node_handler(f); -} - -void show_handler(FILE *f) { - Node *n = 0; - if (!swill_getargs("p(hn)", &n)) { - n = 0; - } - if (n) { - Setmeta(n, "visible", "1"); - } - node_handler(f); -} - -void raw_data(FILE *out, Node *obj) { - if (!obj) - return; - if (DohIsMapping(obj)) { - String *k; - Iterator ki; - String *os = NewString(""); - Printf(os, "Hash {\n"); - ki = First(obj); - while (ki.key) { - k = ki.key; - DOH *o; - const char *trunc = ""; - if (DohIsString(Getattr(obj, k))) { - o = Str(Getattr(obj, k)); - if (Len(o) > 70) { - trunc = "..."; - } - Replaceall(o, "<", "<"); - Printf(os, " ? %-12s - \"%(escape)-0.70s%s\"\n", Getattr(obj, k), k, o, trunc); - Delete(o); - } else { - Printf(os, " ? %-12s - %p\n", Getattr(obj, k), k, Getattr(obj, k)); - } - ki = Next(ki); - } - Printf(os, "}\n"); - Printf(out, "
      \n%s
      \n", Char(os)); - Delete(os); - } else if (DohIsString(obj)) { - String *o = Str(obj); - Replaceall(o, "<", "<"); - Printf(out, "
      \n%s
      \n", Char(o)); - Delete(o); - } else if (DohIsSequence(obj)) { - int i; - String *os = NewString(""); - Printf(os, "List [\n"); - for (i = 0; i < Len(obj); i++) { - DOH *o = Getitem(obj, i); - const char *trunc = ""; - if (DohIsString(o)) { - String *s = Str(o); - if (Len(s) > 70) { - trunc = "..."; - } - Replaceall(o, "<", "<"); - Printf(os, " ? [%d] - \"%(escape)-0.70s%s\"\n", o, i, s, trunc); - Delete(s); - } else { - Printf(os, " ? [%d] - %p\n", o, i, o); - } - } - Printf(os, "\n]\n"); - Printf(out, "
      \n%s
      \n", Char(os)); - Delete(os); - } -} - -void data_handler(FILE *f) { - DOH *n = 0; - if (!swill_getargs("p(n)", &n)) { - n = 0; - } - Printf(f, "SWIG-%s\n", Swig_package_version()); - Printf(f, "SWIG-%s
      \n", Swig_package_version()); - Printf(f, "[ Exit ]"); - Printf(f, " [ Top ]", tree_top); - Printf(f, "

      \n"); - if (n) { - raw_data(f, n); - } - /* Print standard footer */ - Printf(f, "


      \n"); -} - -void symbol_handler(FILE *f) { - Symtab *sym; - char *name = 0; - - Printf(f, "SWIG-%s\n", Swig_package_version()); - Printf(f, "SWIG-%s
      \n", Swig_package_version()); - Printf(f, "[ Exit ]"); - Printf(f, " [ Top ]", tree_top); - Printf(f, " [ Symbols ]"); - Printf(f, "

      \n"); - - if (!swill_getargs("p(sym)|s(name)", &sym, &name)) { - sym = Swig_symbol_getscope(""); - name = 0; - } - if (!sym) { - Printf(f, "No symbol table specified!\n"); - return; - } - { - String *q = Swig_symbol_qualifiedscopename(sym); - if (!Len(q)) { - Printf(f, "Symbol table: :: (global)
      \n"); - } else { - Printf(f, "Symbol table: %s
      \n", q); - } - Delete(q); - } - - fprintf(f, "

      \n"); - fprintf(f, "Symbol lookup:
      \n"); - fprintf(f, "\n", sym); - fprintf(f, "Submit : \n"); - fprintf(f, "
      "); - - if (name) { - Node *n = Swig_symbol_clookup(name, sym); - Printf(f, "Symbol '%s':\n", name); - Printf(f, "
      \n"); - if (!n) { - Printf(f, "Not defined!\n"); - } else { - raw_data(f, n); - } - Printf(f, "
      \n"); - } - - Printf(f, "

      Nested scopes
      \n"); - Printf(f, "

      \n");
      -  {
      -    Hash *h;
      -    h = firstChild(sym);
      -    while (h) {
      -      Printf(f, "%s\n", h, Getattr(h, "name"));
      -      h = nextSibling(h);
      -    }
      -  }
      -  Printf(f, "
      \n"); - - Printf(f, "

      Symbol table contents
      \n"); - raw_data(f, Getattr(sym, "symtab")); - Printf(f, "


      \n"); - -} -#endif - -void Swig_browser(Node *top, int port) { -#ifdef SWIG_SWILL - int sport; - browser_exit = 0; - - /* Initialize the server */ - sport = swill_init(port); - if (sport < 0) { - Printf(stderr, "Couldn't open socket on port %d. Sorry.\n", port); - return; - } - browse = new Browser(); - Setmeta(top, "visible", "1"); - tree_top = top; - - Printf(stderr, "SWIG: Tree browser listening on port %d\n", sport); - - swill_handle("exit.html", exit_handler, 0); - swill_handle("index.html", node_handler, 0); - swill_handle("hide.html", hide_handler, 0); - swill_handle("show.html", show_handler, 0); - swill_handle("data.html", data_handler, 0); - swill_handle("symbol.html", symbol_handler, 0); - swill_netscape("index.html"); - - while (!browser_exit) { - swill_serve(); - } - Printf(stderr, "Browser terminated.\n"); - swill_close(); - delete browse; - return; -#else - (void) top; - (void) port; -#endif -} diff --git a/Source/Modules/main.cxx b/Source/Modules/main.cxx index f412a3eeb..9344a7299 100644 --- a/Source/Modules/main.cxx +++ b/Source/Modules/main.cxx @@ -194,7 +194,6 @@ static int dump_tags = 0; static int dump_module = 0; static int dump_top = 0; static int dump_xml = 0; -static int browse = 0; static int dump_typedef = 0; static int dump_classes = 0; static int werror = 0; @@ -850,9 +849,6 @@ static void getoptions(int argc, char *argv[]) { } else if (strcmp(argv[i], "-nocontract") == 0) { Swig_mark_arg(i); Swig_contract_mode_set(0); - } else if (strcmp(argv[i], "-browse") == 0) { - browse = 1; - Swig_mark_arg(i); } else if ((strcmp(argv[i], "-debug-typedef") == 0) || (strcmp(argv[i], "-dump_typedef") == 0)) { dump_typedef = 1; Swig_mark_arg(i); @@ -1335,9 +1331,6 @@ int SWIG_main(int argc, char *argv[], const TargetLanguageModule *tlm) { lang->top(top); - if (browse) { - Swig_browser(top, 0); - } Delete(infile_filename); Delete(basename); } diff --git a/Source/Modules/swigmod.h b/Source/Modules/swigmod.h index 3661a2b61..de6ee48ef 100644 --- a/Source/Modules/swigmod.h +++ b/Source/Modules/swigmod.h @@ -430,16 +430,14 @@ extern "C" { void Swig_print_with_location(DOH *object, int count = -1); } +void Swig_default_allocators(Node *n); +void Swig_process_types(Node *n); + /* Contracts */ void Swig_contracts(Node *n); void Swig_contract_mode_set(int flag); int Swig_contract_mode_get(); -/* Browser */ -void Swig_browser(Node *n, int); -void Swig_default_allocators(Node *n); -void Swig_process_types(Node *n); - /* Nested classes */ void Swig_nested_process_classes(Node *n); void Swig_nested_name_unnamed_c_structs(Node *n); diff --git a/configure.ac b/configure.ac index feda58891..2afaf2275 100644 --- a/configure.ac +++ b/configure.ac @@ -460,10 +460,6 @@ AC_SEARCH_LIBS(t_open, nsl) # SVR4 AC_SEARCH_LIBS(gethostbyname, inet) # Sequent AC_SEARCH_LIBS(socket, socket) # SVR4 sockets -AC_CHECK_LIB(swill, swill_init, [SWIGLIBS="-lswill $LIBS" SWILL="-DSWIG_SWILL"]) -AC_SUBST(SWIGLIBS) -AC_SUBST(SWILL) - # check for --with-libm=... AC_SUBST(LIBM) LIBM=-lm From 471df4823b977525e304a137fb87255239737f5d Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Mon, 4 Apr 2022 08:59:36 +1200 Subject: [PATCH 396/662] Don't call skip_decl() on "Syntax error in input(3)" This is a useless left-over from long ago (2007) when we didn't exit right away after reporting this error. --- Source/CParse/parser.y | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/Source/CParse/parser.y b/Source/CParse/parser.y index 7a5ef42c5..b6ded8381 100644 --- a/Source/CParse/parser.y +++ b/Source/CParse/parser.y @@ -4670,9 +4670,7 @@ cpp_members : cpp_member cpp_members { | include_directive { $$ = $1; } | empty { $$ = 0;} | error { - int start_line = cparse_line; - skip_decl(); - Swig_error(cparse_file,start_line,"Syntax error in input(3).\n"); + Swig_error(cparse_file,cparse_line,"Syntax error in input(3).\n"); Exit(EXIT_FAILURE); } cpp_members { $$ = $3; From 322574722bc2d1a2b951f736c4ce840bd921580b Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Wed, 30 Mar 2022 20:16:28 +0100 Subject: [PATCH 397/662] Testcase warning fix for c# old versions of MSVC --- Examples/test-suite/cpp_typedef.i | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Examples/test-suite/cpp_typedef.i b/Examples/test-suite/cpp_typedef.i index d77485c77..8578988e9 100644 --- a/Examples/test-suite/cpp_typedef.i +++ b/Examples/test-suite/cpp_typedef.i @@ -3,7 +3,7 @@ %module cpp_typedef %{ -#if defined(_MSC_VER) +#if defined(_MSC_VER) && _MSC_VER >= 1900 #pragma warning( disable : 5208) // warning C5208: unnamed class used in typedef name cannot declare members other than non-static data members, member enumerations, or member classes #endif From e8c1bda0b5f3ed940797a01cf6988a298ab69bf8 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Sat, 2 Apr 2022 18:57:11 +0100 Subject: [PATCH 398/662] D compiler detection enhancements Detect LLVM D compiler ldmd2 or ldc2. Show D version. Note that dmd does not have an explicit command line option to show version. --- Examples/Makefile.in | 3 +-- configure.ac | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/Examples/Makefile.in b/Examples/Makefile.in index 1a27b32cd..d7b9a5bcf 100644 --- a/Examples/Makefile.in +++ b/Examples/Makefile.in @@ -1626,8 +1626,7 @@ d_run: # ----------------------------------------------------------------- d_version: - # Needs improvement! - echo D version guess - $(D_VERSION) + ($(DCOMPILER) --version 2> /dev/null || $(DCOMPILER)) | head -n 3 # ----------------------------------------------------------------- # Clean the D examples diff --git a/configure.ac b/configure.ac index 2afaf2275..360b2f440 100644 --- a/configure.ac +++ b/configure.ac @@ -2568,7 +2568,7 @@ _ACEOF fi if test -z "$D2COMPILERBIN" ; then - AC_CHECK_PROGS(D2COMPILER, dmd gdmd) + AC_CHECK_PROGS(D2COMPILER, dmd gdmd ldmd2 ldc2) if test -n "$D2COMPILER" ; then AC_MSG_CHECKING(whether the D2 compiler works) From b35ebc81a97bfdf813020215b1f9086690fd5c10 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Wed, 6 Apr 2022 08:08:14 +0100 Subject: [PATCH 399/662] Doxygen comments take precedence over the autodoc feature. If a "docstring" feature is present it will still override a Doxygen comment. If the "autodoc" feature is also present, the combined "autodoc" and "docstring" will override the Doxygen comment. If no "docstring" is present then the "autodoc" feature will not be generated when there is a Doxygen comment. This way the "autodoc" feature can be specified and used to provide documentation for 'missing' Doxygen comments. Closes #1635 --- CHANGES.current | 14 ++++ Doc/Manual/Contents.html | 1 + Doc/Manual/Python.html | 24 +++++++ Examples/test-suite/common.mk | 1 + .../test-suite/doxygen_autodoc_docstring.i | 66 +++++++++++++++++++ .../python/doxygen_autodoc_docstring_runme.py | 44 +++++++++++++ Source/Modules/python.cxx | 47 ++++++------- 7 files changed, 175 insertions(+), 22 deletions(-) create mode 100644 Examples/test-suite/doxygen_autodoc_docstring.i create mode 100644 Examples/test-suite/python/doxygen_autodoc_docstring_runme.py diff --git a/CHANGES.current b/CHANGES.current index 99581a84b..690a12938 100644 --- a/CHANGES.current +++ b/CHANGES.current @@ -7,6 +7,20 @@ the issue number to the end of the URL: https://github.com/swig/swig/issues/ Version 4.1.0 (in progress) =========================== +2022-04-06: wsfulton + [Python] #1635 The "autodoc" feature no longer overrides Doxygen comments + in the generated docstring. + + If a "docstring" feature is present it will still override a Doxygen comment. + If the "autodoc" feature is also present, the combined "autodoc" and "docstring" + will override the Doxygen comment. If no "docstring" is present then the + "autodoc" feature will not be generated when there is a Doxygen comment. + + This way the "autodoc" feature can be specified and used to provide documentation + for 'missing' Doxygen comments. + + *** POTENTIAL INCOMPATIBILITY *** + 2022-04-01: olly Remove undocumented and non-functional -browse command line option. diff --git a/Doc/Manual/Contents.html b/Doc/Manual/Contents.html index 6b33b99db..57ef77087 100644 --- a/Doc/Manual/Contents.html +++ b/Doc/Manual/Contents.html @@ -1464,6 +1464,7 @@
    • %feature("autodoc", "docstring")
  • %feature("docstring") +
  • Doxygen comments
  • Python Packages
      diff --git a/Doc/Manual/Python.html b/Doc/Manual/Python.html index e2c9c8630..ce6ed2877 100644 --- a/Doc/Manual/Python.html +++ b/Doc/Manual/Python.html @@ -114,6 +114,7 @@
    • %feature("autodoc", "docstring")
  • %feature("docstring") +
  • Doxygen comments
  • Python Packages
      @@ -152,6 +153,7 @@ +

      This chapter describes SWIG's support of Python. SWIG is compatible with all recent Python versions (Python 2.7 and Python >= 3.2). If you @@ -5898,6 +5900,28 @@ with more than one line. +

      33.10.4 Doxygen comments

      + + +

      +Please see the separate Doxygen chapter for information +on making use of C++ Doxygen comments and translating them into Python docstring comments. +

      + +

      +Note that when generating docstrings and Doxygen comments have also been turned on, +the docstring feature will take precedence over a Doxygen comment. +If the autodoc feature is also turned on, then it will be +used in conjunction with the docstring feature. +However, if there is no docstring feature present and there is a Doxygen comment, then the autodoc docstring will not be generated. The Doxygen comment alone will be used. +

      + +

      +This way, if the autodoc feature is specified globally it will fill in any missing +Doxygen documentation comments. +Doxygen comments can be overridden by using the docstring feature. +

      +

      33.11 Python Packages

      diff --git a/Examples/test-suite/common.mk b/Examples/test-suite/common.mk index 96660c0d7..57e663878 100644 --- a/Examples/test-suite/common.mk +++ b/Examples/test-suite/common.mk @@ -638,6 +638,7 @@ endif ifdef HAS_DOXYGEN DOXYGEN_TEST_CASES += \ doxygen_alias \ + doxygen_autodoc_docstring \ doxygen_basic_notranslate \ doxygen_basic_translate \ doxygen_basic_translate_style2 \ diff --git a/Examples/test-suite/doxygen_autodoc_docstring.i b/Examples/test-suite/doxygen_autodoc_docstring.i new file mode 100644 index 000000000..7dcaa56f5 --- /dev/null +++ b/Examples/test-suite/doxygen_autodoc_docstring.i @@ -0,0 +1,66 @@ +%module doxygen_autodoc_docstring + +%feature("autodoc", 1); + +%feature("docstring") ClassWithDocString "Class doc from docstring"; +%feature("docstring") functionWithDocString "Function doc from docstring"; +%feature("docstring") ClassWithDocStringAndDoxygenComment "Class doc from docstring overriding doxycomment"; +%feature("docstring") functionWithDocStringAndDoxygenComment "Function doc from docstring overriding doxycomment"; + +%inline %{ +class ClassWithoutDoxygenComment {}; + +void functionWithoutDoxygenComment(int number) {} + +/** + * Class doxygen comment + */ +class ClassWithDoxygenComment {}; + +/** + * Function doxygen comment + */ +void functionWithDoxygenComment(int number) {} + +class ClassWithDocString {}; + +void functionWithDocString(int number) {} + +/** + * Class doxygen comment + */ +class ClassWithDocStringAndDoxygenComment {}; + +/** + * Function doxygen comment + */ +void functionWithDocStringAndDoxygenComment(int number) {} +%} + + +%feature("autodoc", ""); // clear autodoc + +%feature("docstring") ClassWithDocStringAndDoxygenCommentNoAutodoc "Class doc from docstring overriding doxycomment (no autodoc)"; +%feature("docstring") functionWithDocStringAndDoxygenCommentNoAutodoc "Function doc from docstring overriding doxycomment (no autodoc)"; + +%inline %{ +/** + * Class doxygen comment + */ +class ClassWithDocStringAndDoxygenCommentNoAutodoc {}; + +/** + * Function doxygen comment + */ +void functionWithDocStringAndDoxygenCommentNoAutodoc(int number) {} + +/** + * Class doxygen comment 2 + */ +class ClassWithDoxygenComment2 {}; + +/** + * Function doxygen comment 2 + */ +void functionWithDoxygenComment2(int number) {} +%} diff --git a/Examples/test-suite/python/doxygen_autodoc_docstring_runme.py b/Examples/test-suite/python/doxygen_autodoc_docstring_runme.py new file mode 100644 index 000000000..7dac428cb --- /dev/null +++ b/Examples/test-suite/python/doxygen_autodoc_docstring_runme.py @@ -0,0 +1,44 @@ +from doxygen_autodoc_docstring import * +import inspect +import string +import os +import sys +import comment_verifier + +# documentation from autogenerated 'feature:autodoc' +comment_verifier.check(inspect.getdoc(ClassWithoutDoxygenComment), + "Proxy of C++ ClassWithoutDoxygenComment class.") +comment_verifier.check(inspect.getdoc(functionWithoutDoxygenComment), + "functionWithoutDoxygenComment(int number)") + +# documentation from doxygen comments +comment_verifier.check(inspect.getdoc(ClassWithDoxygenComment), + "Class doxygen comment") +comment_verifier.check(inspect.getdoc(functionWithDoxygenComment), + "Function doxygen comment") + +# documentation from 'feature:docstring' +comment_verifier.check(inspect.getdoc(ClassWithDocString), + "Class doc from docstring") +comment_verifier.check(inspect.getdoc(functionWithDocString), + "functionWithDocString(int number)\n" + "Function doc from docstring") + +# documentation from 'feature:docstring' + autodoc (overriding doxycomment) +comment_verifier.check(inspect.getdoc(ClassWithDocStringAndDoxygenComment), + "Class doc from docstring overriding doxycomment") +comment_verifier.check(inspect.getdoc(functionWithDocStringAndDoxygenComment), + "functionWithDocStringAndDoxygenComment(int number)\n" + "Function doc from docstring overriding doxycomment") + +# documentation from 'feature:docstring' (overriding doxycomment) +comment_verifier.check(inspect.getdoc(ClassWithDocStringAndDoxygenCommentNoAutodoc), + "Class doc from docstring overriding doxycomment (no autodoc)") +comment_verifier.check(inspect.getdoc(functionWithDocStringAndDoxygenCommentNoAutodoc), + "Function doc from docstring overriding doxycomment (no autodoc)") + +# documentation from doxygen comments (2) no autodoc feature present +comment_verifier.check(inspect.getdoc(ClassWithDoxygenComment2), + "Class doxygen comment 2") +comment_verifier.check(inspect.getdoc(functionWithDoxygenComment2), + "Function doxygen comment 2") diff --git a/Source/Modules/python.cxx b/Source/Modules/python.cxx index b2e67ff10..915e3f97f 100644 --- a/Source/Modules/python.cxx +++ b/Source/Modules/python.cxx @@ -1492,16 +1492,18 @@ public: /* ------------------------------------------------------------ * build_combined_docstring() * - * Build the full docstring which may be a combination of the - * explicit docstring and autodoc string or, if none of them - * is specified, obtained by translating Doxygen comment to - * Python. + * Build the full docstring: + * Use the docstring if there is one present otherwise + * use the Doxygen comment if there is one present. + * Ignore autodoc if there is a Doxygen comment, otherwise + * create the autodoc string and append to any docstring. * * Return new string to be deleted by caller (never NIL but * may be empty if there is no docstring). * ------------------------------------------------------------ */ String *build_combined_docstring(Node *n, autodoc_t ad_type, const String *indent = "", bool low_level = false) { + bool add_autodoc = true; String *docstr = Getattr(n, "feature:docstring"); if (docstr) { // Simplify the code below by just ignoring empty docstrings. @@ -1519,26 +1521,10 @@ public: } } - if (Getattr(n, "feature:autodoc") && !GetFlag(n, "feature:noautodoc")) { - String *autodoc = make_autodoc(n, ad_type, low_level); - if (autodoc && Len(autodoc) > 0) { - if (docstr) { - Append(autodoc, "\n"); - Append(autodoc, docstr); - } - - String *tmp = autodoc; - autodoc = docstr; - docstr = tmp; - } - - Delete(autodoc); - } - if (!docstr) { - if (doxygen) { + if (doxygen && doxygenTranslator->hasDocumentation(n)) { docstr = Getattr(n, "python:docstring"); - if (!docstr && doxygenTranslator->hasDocumentation(n)) { + if (!docstr) { docstr = doxygenTranslator->getDocumentation(n, 0); // Avoid rebuilding it again the next time: notice that we can't do @@ -1554,9 +1540,26 @@ public: // the cached object! docstr = Copy(docstr); } + add_autodoc = false; } } + if (add_autodoc && Getattr(n, "feature:autodoc") && !GetFlag(n, "feature:noautodoc")) { + String *autodoc = make_autodoc(n, ad_type, low_level); + if (autodoc && Len(autodoc) > 0) { + if (docstr) { + Append(autodoc, "\n"); + Append(autodoc, docstr); + } + + String *tmp = autodoc; + autodoc = docstr; + docstr = tmp; + } + + Delete(autodoc); + } + if (!docstr) docstr = NewString(""); From dba941120db4b573fd49eb3fb61287635173da2f Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Wed, 6 Apr 2022 19:39:24 +0100 Subject: [PATCH 400/662] Enable C++11 testing by default, Appveyor testing scaled back ./configure now enables C++11 and later C++ standards testing by default (when running: 'make check'). The options to control this testing are the same: ./configure --enable-cpp11-testing ./configure --disable-cpp11-testing But the former is now the default and the latter can be used to turn off C++11 and later C++ standards testing. Reduce the number of tests on Appveyor by only running 32-bit (x86) using latest Visual Studio (2022). Drop 32-bit Cygwin and MinGW testing. Add C# and Java testing on VS2022 and drop Java testing on older Visual Studio. This reduces the really long run times on Appveyor, however, VS2022 is somewhat slower than older compilers. --- .github/workflows/ci.yml | 3 ++- CHANGES.current | 12 ++++++++++++ appveyor.yml | 26 +++++++++++++++++++++----- configure.ac | 18 ++++++++++-------- 4 files changed, 45 insertions(+), 14 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2f9d128b7..f6fb3ec7a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -392,7 +392,8 @@ jobs: esac echo CSTD="$CSTD" >> $GITHUB_ENV fi - if test -n "$CPPSTD"; then CONFIGOPTS+=(--enable-cpp11-testing "CXXFLAGS=-std=$CPPSTD $CXXFLAGS"); fi + if test -z "$CPPSTD"; then CONFIGOPTS+=("--disable-cpp11-testing"); fi + if test -n "$CPPSTD"; then CONFIGOPTS+=("CXXFLAGS=-std=$CPPSTD $CXXFLAGS"); fi if test -n "$CSTD"; then CONFIGOPTS+=("CFLAGS=-std=$CSTD $CFLAGS"); fi if test -n "$SWIGLANG"; then CONFIGOPTS+=(--without-alllang --with-$WITHLANG); fi echo "${CONFIGOPTS[@]}" diff --git a/CHANGES.current b/CHANGES.current index 690a12938..b406611dc 100644 --- a/CHANGES.current +++ b/CHANGES.current @@ -7,6 +7,18 @@ the issue number to the end of the URL: https://github.com/swig/swig/issues/ Version 4.1.0 (in progress) =========================== +2022-04-06: wsfulton + ./configure now enables C++11 and later C++ standards testing by default (when + running: 'make check'). + + The options to control this testing are the same: + + ./configure --enable-cpp11-testing + ./configure --disable-cpp11-testing + + But the former is now the default and the latter can be used to turn off C++11 and + later C++ standards testing. + 2022-04-06: wsfulton [Python] #1635 The "autodoc" feature no longer overrides Doxygen comments in the generated docstring. diff --git a/appveyor.yml b/appveyor.yml index 314cd3333..3a25ed199 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,5 +1,4 @@ platform: -- x86 - x64 skip_commits: @@ -18,8 +17,6 @@ environment: VSVER: 12 - SWIGLANG: csharp VSVER: 14 - - SWIGLANG: java - VSVER: 14 - SWIGLANG: python VSVER: 14 VER: 27 @@ -34,10 +31,29 @@ environment: VSVER: 16 VER: 39 APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019 + - SWIGLANG: csharp + VSVER: 17 + APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2022 + - SWIGLANG: csharp + VSVER: 17 + Platform: x86 + APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2022 + - SWIGLANG: java + VSVER: 17 + APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2022 + - SWIGLANG: java + VSVER: 17 + Platform: x86 + APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2022 - SWIGLANG: python VSVER: 17 VER: 310 APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2022 + - SWIGLANG: python + VSVER: 17 + VER: 310 + Platform: x86 + APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2022 - SWIGLANG: python OSVARIANT: cygwin APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2022 @@ -160,8 +176,8 @@ build_script: - if "%BUILDSYSTEM%"=="cmake" cmake --version && cmake -G "Visual Studio 14 2015%VSARCH%" -DCMAKE_INSTALL_PREFIX="%CD:\=/%/install2" -DCMAKE_C_FLAGS="/WX /DPCRE2_STATIC" -DCMAKE_CXX_FLAGS="/WX /DPCRE2_STATIC" -DPCRE2_INCLUDE_DIR=%PCRE_ROOT%/include -DPCRE2_LIBRARY=%PCRE_ROOT%/lib/pcre2-8-static.lib -DBISON_EXECUTABLE=C:/cygwin/bin/bison.exe . && cmake --build . --config Release --target install && ctest --output-on-failure -V -C Release && appveyor exit - if "%OSVARIANT%"=="" bash -c "exec 0 Date: Wed, 6 Apr 2022 20:51:37 +0100 Subject: [PATCH 401/662] Temporarily disable doxygen_autodoc_docstring_runme.py --- Examples/test-suite/python/doxygen_autodoc_docstring_runme.py | 1 + 1 file changed, 1 insertion(+) diff --git a/Examples/test-suite/python/doxygen_autodoc_docstring_runme.py b/Examples/test-suite/python/doxygen_autodoc_docstring_runme.py index 7dac428cb..bd6afe731 100644 --- a/Examples/test-suite/python/doxygen_autodoc_docstring_runme.py +++ b/Examples/test-suite/python/doxygen_autodoc_docstring_runme.py @@ -5,6 +5,7 @@ import os import sys import comment_verifier +exit(0) # temporarily skip runtime test until builtin is fixed # documentation from autogenerated 'feature:autodoc' comment_verifier.check(inspect.getdoc(ClassWithoutDoxygenComment), "Proxy of C++ ClassWithoutDoxygenComment class.") From da07af7fe20b7ec80f88bd44d9331e7ed82083af Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Wed, 6 Apr 2022 22:33:17 +0100 Subject: [PATCH 402/662] doxygen_autodoc_docstring test fix for Python builtin --- Examples/test-suite/doxygen_autodoc_docstring.i | 9 +++++++++ .../test-suite/python/doxygen_autodoc_docstring_runme.py | 3 +-- Examples/test-suite/python_builtin.i | 1 - 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/Examples/test-suite/doxygen_autodoc_docstring.i b/Examples/test-suite/doxygen_autodoc_docstring.i index 7dcaa56f5..e590d7f94 100644 --- a/Examples/test-suite/doxygen_autodoc_docstring.i +++ b/Examples/test-suite/doxygen_autodoc_docstring.i @@ -64,3 +64,12 @@ class ClassWithDoxygenComment2 {}; */ void functionWithDoxygenComment2(int number) {} %} + +%inline %{ +#ifdef SWIGPYTHON_BUILTIN +bool is_python_builtin() { return true; } +#else +bool is_python_builtin() { return false; } +#endif +%} + diff --git a/Examples/test-suite/python/doxygen_autodoc_docstring_runme.py b/Examples/test-suite/python/doxygen_autodoc_docstring_runme.py index bd6afe731..9780516b9 100644 --- a/Examples/test-suite/python/doxygen_autodoc_docstring_runme.py +++ b/Examples/test-suite/python/doxygen_autodoc_docstring_runme.py @@ -5,10 +5,9 @@ import os import sys import comment_verifier -exit(0) # temporarily skip runtime test until builtin is fixed # documentation from autogenerated 'feature:autodoc' comment_verifier.check(inspect.getdoc(ClassWithoutDoxygenComment), - "Proxy of C++ ClassWithoutDoxygenComment class.") + "::ClassWithoutDoxygenComment" if is_python_builtin() else "Proxy of C++ ClassWithoutDoxygenComment class.") comment_verifier.check(inspect.getdoc(functionWithoutDoxygenComment), "functionWithoutDoxygenComment(int number)") diff --git a/Examples/test-suite/python_builtin.i b/Examples/test-suite/python_builtin.i index 994c625e8..754526dad 100644 --- a/Examples/test-suite/python_builtin.i +++ b/Examples/test-suite/python_builtin.i @@ -244,4 +244,3 @@ public: } }; %} - From a5be4a10b5b22f35aa6fccd52e181ceb3d9fda03 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Wed, 6 Apr 2022 22:48:33 +0100 Subject: [PATCH 403/662] Slight performance improvement for %pythonnondynamic Setting this is much more likely than thisown --- Source/Modules/python.cxx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Source/Modules/python.cxx b/Source/Modules/python.cxx index 915e3f97f..69984ae5e 100644 --- a/Source/Modules/python.cxx +++ b/Source/Modules/python.cxx @@ -737,10 +737,10 @@ public: tab4, tab4, "if name in (\"this\", \"thisown\"):\n", tab4, tab4, tab4, "set(self, name, value)\n", #else - tab4, tab4, "if name == \"thisown\":\n", - tab4, tab4, tab4, "self.this.own(value)\n", - tab4, tab4, "elif name == \"this\":\n", + tab4, tab4, "if name == \"this\":\n", tab4, tab4, tab4, "set(self, name, value)\n", + tab4, tab4, "elif name == \"thisown\":\n", + tab4, tab4, tab4, "self.this.own(value)\n", #endif tab4, tab4, "elif hasattr(self, name) and isinstance(getattr(type(self), name), property):\n", tab4, tab4, tab4, "set(self, name, value)\n", From 9c67a2c007be56aa5b9892e854ea141396645df9 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Wed, 6 Apr 2022 22:58:17 +0100 Subject: [PATCH 404/662] Remove legacy USE_THISOWN conditional compilation Seems to be a left over from 'thisown' partial removal in 985adc13fba238405028361a8d8e35e8b1b1008c --- Source/Modules/python.cxx | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/Source/Modules/python.cxx b/Source/Modules/python.cxx index 69984ae5e..7e369b76c 100644 --- a/Source/Modules/python.cxx +++ b/Source/Modules/python.cxx @@ -733,15 +733,10 @@ public: Printv(f_shadow, "\n", "def _swig_setattr_nondynamic_instance_variable(set):\n", tab4, "def set_instance_attr(self, name, value):\n", -#ifdef USE_THISOWN - tab4, tab4, "if name in (\"this\", \"thisown\"):\n", - tab4, tab4, tab4, "set(self, name, value)\n", -#else tab4, tab4, "if name == \"this\":\n", tab4, tab4, tab4, "set(self, name, value)\n", tab4, tab4, "elif name == \"thisown\":\n", tab4, tab4, tab4, "self.this.own(value)\n", -#endif tab4, tab4, "elif hasattr(self, name) and isinstance(getattr(type(self), name), property):\n", tab4, tab4, tab4, "set(self, name, value)\n", tab4, tab4, "else:\n", @@ -3903,11 +3898,7 @@ public: String *symname = Getattr(n, "sym:name"); String *mrename = Swig_name_disown(NSPACE_TODO, symname); //Getattr(n, "name")); Printv(f_shadow, tab4, "def __disown__(self):\n", NIL); -#ifdef USE_THISOWN - Printv(f_shadow, tab8, "self.thisown = 0\n", NIL); -#else Printv(f_shadow, tab8, "self.this.disown()\n", NIL); -#endif Printv(f_shadow, tab8, module, ".", mrename, "(self)\n", NIL); Printv(f_shadow, tab8, "return weakref.proxy(self)\n", NIL); Delete(mrename); @@ -4969,9 +4960,6 @@ public: if (have_pythonprepend(n)) Printv(f_shadow_stubs, indent_pythoncode(pythonprepend(n), tab4, Getfile(n), Getline(n), "%pythonprepend or %feature(\"pythonprepend\")"), "\n", NIL); Printv(f_shadow_stubs, tab4, "val = ", funcCall(subfunc, callParms), "\n", NIL); -#ifdef USE_THISOWN - Printv(f_shadow_stubs, tab4, "val.thisown = 1\n", NIL); -#endif if (have_pythonappend(n)) Printv(f_shadow_stubs, indent_pythoncode(pythonappend(n), tab4, Getfile(n), Getline(n), "%pythonappend or %feature(\"pythonappend\")"), "\n", NIL); Printv(f_shadow_stubs, tab4, "return val\n", NIL); @@ -5027,12 +5015,6 @@ public: Printv(f_shadow, tab8, docstring(n, AUTODOC_DTOR, tab8), "\n", NIL); if (have_pythonprepend(n)) Printv(f_shadow, indent_pythoncode(pythonprepend(n), tab8, Getfile(n), Getline(n), "%pythonprepend or %feature(\"pythonprepend\")"), "\n", NIL); -#ifdef USE_THISOWN - Printv(f_shadow, tab8, "try:\n", NIL); - Printv(f_shadow, tab8, tab4, "if self.thisown:", module, ".", Swig_name_destroy(NSPACE_TODO, symname), "(self)\n", NIL); - Printv(f_shadow, tab8, "except __builtin__.Exception: pass\n", NIL); -#else -#endif if (have_pythonappend(n)) Printv(f_shadow, indent_pythoncode(pythonappend(n), tab8, Getfile(n), Getline(n), "%pythonappend or %feature(\"pythonappend\")"), "\n", NIL); Printv(f_shadow, tab8, "pass\n", NIL); From a12fc916e4070958f95e492351e0702192128ca3 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Wed, 6 Apr 2022 23:06:48 +0100 Subject: [PATCH 405/662] Remove unused functions in Python builtin mode --- Source/Modules/python.cxx | 91 ++++++++++++++++++++------------------- 1 file changed, 47 insertions(+), 44 deletions(-) diff --git a/Source/Modules/python.cxx b/Source/Modules/python.cxx index 7e369b76c..5b7f535ce 100644 --- a/Source/Modules/python.cxx +++ b/Source/Modules/python.cxx @@ -712,9 +712,11 @@ public: Printv(default_import_code, tab4, "from ", module, " import *\n", NULL); } - /* Need builtins to qualify names like Exception that might also be - defined in this module (try both Python 3 and Python 2 names) */ - Printv(f_shadow, "try:\n", tab4, "import builtins as __builtin__\n", "except ImportError:\n", tab4, "import __builtin__\n", NULL); + if (!builtin) { + /* Need builtins to qualify names like Exception that might also be + defined in this module (try both Python 3 and Python 2 names) */ + Printv(f_shadow, "try:\n", tab4, "import builtins as __builtin__\n", "except ImportError:\n", tab4, "import __builtin__\n", NULL); + } if (!builtin && fastproxy) { Printf(f_shadow, "\n"); @@ -722,53 +724,54 @@ public: Printf(f_shadow, "_swig_new_static_method = %s.SWIG_PyStaticMethod_New\n", module); } - Printv(f_shadow, "\n", - "def _swig_repr(self):\n", - tab4, "try:\n", - tab4, tab4, "strthis = \"proxy of \" + self.this.__repr__()\n", - tab4, "except __builtin__.Exception:\n", - tab4, tab4, "strthis = \"\"\n", - tab4, "return \"<%s.%s; %s >\" % (self.__class__.__module__, self.__class__.__name__, strthis,)\n\n", NIL); + if (!builtin) { + Printv(f_shadow, "\n", + "def _swig_repr(self):\n", + tab4, "try:\n", + tab4, tab4, "strthis = \"proxy of \" + self.this.__repr__()\n", + tab4, "except __builtin__.Exception:\n", + tab4, tab4, "strthis = \"\"\n", + tab4, "return \"<%s.%s; %s >\" % (self.__class__.__module__, self.__class__.__name__, strthis,)\n\n", NIL); - Printv(f_shadow, "\n", - "def _swig_setattr_nondynamic_instance_variable(set):\n", - tab4, "def set_instance_attr(self, name, value):\n", - tab4, tab4, "if name == \"this\":\n", - tab4, tab4, tab4, "set(self, name, value)\n", - tab4, tab4, "elif name == \"thisown\":\n", - tab4, tab4, tab4, "self.this.own(value)\n", - tab4, tab4, "elif hasattr(self, name) and isinstance(getattr(type(self), name), property):\n", - tab4, tab4, tab4, "set(self, name, value)\n", - tab4, tab4, "else:\n", - tab4, tab4, tab4, "raise AttributeError(\"You cannot add instance attributes to %s\" % self)\n", - tab4, "return set_instance_attr\n\n", NIL); + Printv(f_shadow, "\n", + "def _swig_setattr_nondynamic_instance_variable(set):\n", + tab4, "def set_instance_attr(self, name, value):\n", + tab4, tab4, "if name == \"this\":\n", + tab4, tab4, tab4, "set(self, name, value)\n", + tab4, tab4, "elif name == \"thisown\":\n", + tab4, tab4, tab4, "self.this.own(value)\n", + tab4, tab4, "elif hasattr(self, name) and isinstance(getattr(type(self), name), property):\n", + tab4, tab4, tab4, "set(self, name, value)\n", + tab4, tab4, "else:\n", + tab4, tab4, tab4, "raise AttributeError(\"You cannot add instance attributes to %s\" % self)\n", + tab4, "return set_instance_attr\n\n", NIL); - Printv(f_shadow, "\n", - "def _swig_setattr_nondynamic_class_variable(set):\n", - tab4, "def set_class_attr(cls, name, value):\n", - tab4, tab4, "if hasattr(cls, name) and not isinstance(getattr(cls, name), property):\n", - tab4, tab4, tab4, "set(cls, name, value)\n", - tab4, tab4, "else:\n", - tab4, tab4, tab4, "raise AttributeError(\"You cannot add class attributes to %s\" % cls)\n", - tab4, "return set_class_attr\n\n", NIL); + Printv(f_shadow, "\n", + "def _swig_setattr_nondynamic_class_variable(set):\n", + tab4, "def set_class_attr(cls, name, value):\n", + tab4, tab4, "if hasattr(cls, name) and not isinstance(getattr(cls, name), property):\n", + tab4, tab4, tab4, "set(cls, name, value)\n", + tab4, tab4, "else:\n", + tab4, tab4, tab4, "raise AttributeError(\"You cannot add class attributes to %s\" % cls)\n", + tab4, "return set_class_attr\n\n", NIL); - Printv(f_shadow, "\n", - "def _swig_add_metaclass(metaclass):\n", - tab4, "\"\"\"Class decorator for adding a metaclass to a SWIG wrapped class - a slimmed down version of six.add_metaclass\"\"\"\n", - tab4, "def wrapper(cls):\n", - tab4, tab4, "return metaclass(cls.__name__, cls.__bases__, cls.__dict__.copy())\n", - tab4, "return wrapper\n\n", NIL); + Printv(f_shadow, "\n", + "def _swig_add_metaclass(metaclass):\n", + tab4, "\"\"\"Class decorator for adding a metaclass to a SWIG wrapped class - a slimmed down version of six.add_metaclass\"\"\"\n", + tab4, "def wrapper(cls):\n", + tab4, tab4, "return metaclass(cls.__name__, cls.__bases__, cls.__dict__.copy())\n", + tab4, "return wrapper\n\n", NIL); - Printv(f_shadow, "\n", - "class _SwigNonDynamicMeta(type):\n", - tab4, "\"\"\"Meta class to enforce nondynamic attributes (no new attributes) for a class\"\"\"\n", - tab4, "__setattr__ = _swig_setattr_nondynamic_class_variable(type.__setattr__)\n", - "\n", NIL); + Printv(f_shadow, "\n", + "class _SwigNonDynamicMeta(type):\n", + tab4, "\"\"\"Meta class to enforce nondynamic attributes (no new attributes) for a class\"\"\"\n", + tab4, "__setattr__ = _swig_setattr_nondynamic_class_variable(type.__setattr__)\n", + "\n", NIL); - Printv(f_shadow, "\n", NIL); + Printv(f_shadow, "\n", NIL); - if (directorsEnabled()) { - Printv(f_shadow, "import weakref\n\n", NIL); + if (directorsEnabled()) + Printv(f_shadow, "import weakref\n\n", NIL); } } // Include some information in the code From fe0af80933807ef7f6aed02981e601876850fd11 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Wed, 6 Apr 2022 23:49:59 +0100 Subject: [PATCH 406/662] Remove some unnecessary empty lines from generated .py file --- Source/Modules/python.cxx | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/Source/Modules/python.cxx b/Source/Modules/python.cxx index 5b7f535ce..c97bc4610 100644 --- a/Source/Modules/python.cxx +++ b/Source/Modules/python.cxx @@ -876,8 +876,10 @@ public: Printv(f_shadow_py, default_import_code, NIL); } - Printv(f_shadow_py, "\n", f_shadow, "\n", NIL); - Printv(f_shadow_py, f_shadow_stubs, "\n", NIL); + if (Len(f_shadow) > 0) + Printv(f_shadow_py, "\n", f_shadow, "\n", NIL); + if (Len(f_shadow_stubs) > 0) + Printv(f_shadow_py, f_shadow_stubs, "\n", NIL); Delete(f_shadow_py); } @@ -2635,7 +2637,7 @@ public: add_method(symname, wname, 0, p); /* Create a shadow for this function (if enabled and not in a member function) */ - if (!builtin && shadow && (!(shadow & PYSHADOW_MEMBER)) && use_static_method) { + if (!builtin && shadow && !(shadow & PYSHADOW_MEMBER) && use_static_method) { emitFunctionShadowHelper(n, in_class ? f_shadow_stubs : f_shadow, symname, 0); } DelWrapper(f); @@ -3309,9 +3311,10 @@ public: add_method(iname, wname, allow_kwargs, n, funpack, num_required, num_arguments); /* Create a shadow for this function (if enabled and not in a member function) */ - if (!builtin && shadow && (!(shadow & PYSHADOW_MEMBER)) && use_static_method) { + if (!builtin && shadow && !(shadow & PYSHADOW_MEMBER) && use_static_method) { emitFunctionShadowHelper(n, in_class ? f_shadow_stubs : f_shadow, iname, allow_kwargs); } + } else { if (!Getattr(n, "sym:nextSibling")) { dispatchFunction(n, linkage, funpack, builtin_self, builtin_ctor, director_class, use_static_method); @@ -3470,7 +3473,7 @@ public: if (builtin) Printf(f_init, "\t SwigPyBuiltin_AddPublicSymbol(public_interface, \"%s\");\n", global_name); have_globals = 1; - if (!builtin && (shadow) && (!(shadow & PYSHADOW_MEMBER))) { + if (!builtin && shadow && !(shadow & PYSHADOW_MEMBER)) { Printf(f_shadow_stubs, "%s = %s.%s\n", global_name, module, global_name); } } @@ -3628,7 +3631,7 @@ public: if ((tm = Swig_typemap_lookup("constcode", n, name, 0))) { Replaceall(tm, "$value", value); - if (needs_swigconstant(n) && !builtin && (shadow) && (!(shadow & PYSHADOW_MEMBER)) && (!in_class || !Getattr(n, "feature:python:callback"))) { + if (needs_swigconstant(n) && !builtin && shadow && !(shadow & PYSHADOW_MEMBER) && (!in_class || !Getattr(n, "feature:python:callback"))) { // Generate `*_swigconstant()` method which registers the new constant. // // *_swigconstant methods are required for constants of class type. @@ -3666,7 +3669,7 @@ public: return SWIG_NOWRAP; } - if (!builtin && (shadow) && (!(shadow & PYSHADOW_MEMBER))) { + if (!builtin && shadow && !(shadow & PYSHADOW_MEMBER)) { String *f_s; if (!in_class) { f_s = f_shadow; @@ -4617,7 +4620,8 @@ public: } shadow_indent = 0; - Printf(f_shadow_file, "%s\n", f_shadow_stubs); + if (Len(f_shadow_stubs) > 0) + Printf(f_shadow_file, "%s\n", f_shadow_stubs); Clear(f_shadow_stubs); } From 779d5cf57ade9de944d8feece9f5101668e2245f Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Wed, 6 Apr 2022 09:57:54 +1200 Subject: [PATCH 407/662] Remove bogus parser grammar rule for unary && This appears to have been accidentally added in d8cc75946b236f08f9561a82867997e1021f96ab as part of the changes to support C++11 rvalue references, presumably to match the existing correct rule for unary &. There is a non-standard GCC extension for taking the address of a label using unary &&: https://gcc.gnu.org/onlinedocs/gcc/Labels-as-Values.html However this extension only works in an expression in a function body, and SWIG doesn't parse the contents of function bodies so this grammar rule isn't even providing any useful support for this extension. --- Source/CParse/parser.y | 4 ---- 1 file changed, 4 deletions(-) diff --git a/Source/CParse/parser.y b/Source/CParse/parser.y index b6ded8381..9ecb65ba1 100644 --- a/Source/CParse/parser.y +++ b/Source/CParse/parser.y @@ -6743,10 +6743,6 @@ valexpr : exprsimple { $$ = $1; } $$ = $2; $$.val = NewStringf("&%s",$2.val); } - | LAND expr { - $$ = $2; - $$.val = NewStringf("&&%s",$2.val); - } | STAR expr { $$ = $2; $$.val = NewStringf("*%s",$2.val); From 1aeaa2a64424e5ffa3797063e23591854a7a5399 Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Thu, 7 Apr 2022 12:05:54 +1200 Subject: [PATCH 408/662] Recognise and ignore Doxygen group commands @{ and @} Fixes #1750 --- CHANGES.current | 3 +++ Examples/test-suite/doxygen_parsing.i | 9 +++++++++ .../test-suite/java/doxygen_parsing_runme.java | 8 ++++++++ Source/Doxygen/doxycommands.h | 2 ++ Source/Doxygen/doxyparser.h | 2 +- Source/Modules/python.cxx | 14 ++++++++++---- 6 files changed, 33 insertions(+), 5 deletions(-) diff --git a/CHANGES.current b/CHANGES.current index b406611dc..d41a4c235 100644 --- a/CHANGES.current +++ b/CHANGES.current @@ -7,6 +7,9 @@ the issue number to the end of the URL: https://github.com/swig/swig/issues/ Version 4.1.0 (in progress) =========================== +2022-04-07: olly + #1750 SWIG now recognises and ignores Doxygen group commands `@{` and `@}`. + 2022-04-06: wsfulton ./configure now enables C++11 and later C++ standards testing by default (when running: 'make check'). diff --git a/Examples/test-suite/doxygen_parsing.i b/Examples/test-suite/doxygen_parsing.i index 3a559053d..9df0097ec 100644 --- a/Examples/test-suite/doxygen_parsing.i +++ b/Examples/test-suite/doxygen_parsing.i @@ -133,6 +133,15 @@ struct SomeAnotherStruct } }; +struct Foo1750 +{ + /// @name Group name + /// @{ + int a; + /// @} + int b; +}; + #ifdef SWIGPYTHON_BUILTIN bool is_python_builtin() { return true; } #else diff --git a/Examples/test-suite/java/doxygen_parsing_runme.java b/Examples/test-suite/java/doxygen_parsing_runme.java index 29e524f78..2c76001db 100644 --- a/Examples/test-suite/java/doxygen_parsing_runme.java +++ b/Examples/test-suite/java/doxygen_parsing_runme.java @@ -132,6 +132,14 @@ public class doxygen_parsing_runme { wantedComments.put("doxygen_parsing.doxygen_parsingConstants.CONSTANT_VALUE", "The constant comment \n" + ""); + wantedComments.put("doxygen_parsing.Foo1750.getA()", + ""); + wantedComments.put("doxygen_parsing.Foo1750.getB()", + ""); + wantedComments.put("doxygen_parsing.Foo1750.setA(int)", + ""); + wantedComments.put("doxygen_parsing.Foo1750.setB(int)", + ""); // and ask the parser to check comments for us System.exit(CommentParser.check(wantedComments)); diff --git a/Source/Doxygen/doxycommands.h b/Source/Doxygen/doxycommands.h index b5d65af65..939b56917 100644 --- a/Source/Doxygen/doxycommands.h +++ b/Source/Doxygen/doxycommands.h @@ -44,6 +44,8 @@ const int sectionIndicatorsSize = sizeof(sectionIndicators) / sizeof(*sectionInd const char *simpleCommands[] = { // the first line are escaped chars, except \~, which is a language ID command. "n", "$", "@", "\\", "&", "~", "<", ">", "#", "%", "\"", ".", "::", + // Member groups, which we currently ignore. + "{", "}", "endcond", "callgraph", "callergraph", "showinitializer", "hideinitializer", "internal", "nosubgrouping", "public", "publicsection", "private", "privatesection", diff --git a/Source/Doxygen/doxyparser.h b/Source/Doxygen/doxyparser.h index e692729ce..7a7d5c4f2 100644 --- a/Source/Doxygen/doxyparser.h +++ b/Source/Doxygen/doxyparser.h @@ -238,7 +238,7 @@ private: * Method for Adding a Simple Command * Format: @command * Plain commands, such as newline etc, they contain no other data - * \n \\ \@ \& \$ \# \< \> \% + * \n \\ \@ \& \$ \# \< \> \% \{ \} */ void addSimpleCommand(const std::string &theCommand, DoxygenEntityList &doxyList); /* diff --git a/Source/Modules/python.cxx b/Source/Modules/python.cxx index c97bc4610..cd87984dc 100644 --- a/Source/Modules/python.cxx +++ b/Source/Modules/python.cxx @@ -5053,8 +5053,11 @@ public: Printv(f_shadow, tab4, symname, variable_annotation, " = property(", module, ".", getname, NIL); if (assignable) Printv(f_shadow, ", ", module, ".", setname, NIL); - if (have_docstring(n)) - Printv(f_shadow, ", doc=", docstring(n, AUTODOC_VAR, tab4), NIL); + if (have_docstring(n)) { + String *s = docstring(n, AUTODOC_VAR, tab4); + if (Len(s)) + Printv(f_shadow, ", doc=", s, NIL); + } Printv(f_shadow, ")\n", NIL); Delete(variable_annotation); Delete(mname); @@ -5121,8 +5124,11 @@ public: Printv(f_shadow, tab4, symname, " = property(", module, ".", getname, NIL); if (assignable) Printv(f_shadow, ", ", module, ".", setname, NIL); - if (have_docstring(n)) - Printv(f_shadow, ", doc=", docstring(n, AUTODOC_VAR, tab4), NIL); + if (have_docstring(n)) { + String *s = docstring(n, AUTODOC_VAR, tab4); + if (Len(s)) + Printv(f_shadow, ", doc=", s, NIL); + } Printv(f_shadow, ")\n", NIL); } String *getter = Getattr(n, "pybuiltin:getter"); From c8bec185541a5839a2a1728d3d83a180d4cd93ad Mon Sep 17 00:00:00 2001 From: luz paz Date: Sun, 10 Apr 2022 11:49:43 -0400 Subject: [PATCH 409/662] Fix various typos Found via `codespell -q 3 -L ans,anumber,ba,bae,chello,clos,cmo,coo,dout,fo,funktion,goin,inout,methid,nd,nin,nnumber,object,objekt,od,ois,packag,parm,parms,pres,statics,strack,struc,tempdate,te,thru,uint,upto,writen` --- Examples/python/import_packages/from_init1/runme.py | 2 +- Examples/python/import_packages/from_init2/runme.py | 2 +- Examples/python/import_packages/from_init3/runme.py | 2 +- Examples/python/import_packages/namespace_pkg/nonpkg.py | 2 +- Examples/python/import_packages/namespace_pkg/normal.py | 2 +- Examples/python/import_packages/namespace_pkg/nstest.py | 2 +- Examples/python/import_packages/namespace_pkg/split.py | 2 +- Examples/python/import_packages/namespace_pkg/zipsplit.py | 2 +- Examples/python/import_packages/relativeimport1/runme.py | 2 +- Examples/python/import_packages/relativeimport2/runme.py | 2 +- Examples/python/import_packages/relativeimport3/runme.py | 2 +- Examples/python/import_packages/same_modnames1/runme.py | 2 +- Examples/python/import_packages/same_modnames2/runme.py | 2 +- Examples/python/import_packages/split_modules/vanilla/runme.py | 2 +- .../python/import_packages/split_modules/vanilla_split/runme.py | 2 +- Examples/ruby/exceptproxy/example.i | 2 +- Examples/test-suite/php/director_extend_runme.php | 2 +- Source/CParse/parser.y | 2 +- Source/Modules/r.cxx | 2 +- 19 files changed, 19 insertions(+), 19 deletions(-) diff --git a/Examples/python/import_packages/from_init1/runme.py b/Examples/python/import_packages/from_init1/runme.py index c76716f16..1ed8898e4 100644 --- a/Examples/python/import_packages/from_init1/runme.py +++ b/Examples/python/import_packages/from_init1/runme.py @@ -4,7 +4,7 @@ import sys def run_except_on_windows(commandline, env=None): if os.name != "nt" and sys.platform != "cygwin": - # Strange failures on windows/cygin/mingw + # Strange failures on windows/cygwin/mingw subprocess.check_call(commandline, env=env, shell=True) print((" Finished running: " + commandline)) diff --git a/Examples/python/import_packages/from_init2/runme.py b/Examples/python/import_packages/from_init2/runme.py index c9c46a4da..100c97b9e 100644 --- a/Examples/python/import_packages/from_init2/runme.py +++ b/Examples/python/import_packages/from_init2/runme.py @@ -4,7 +4,7 @@ import sys def run_except_on_windows(commandline, env=None): if os.name != "nt" and sys.platform != "cygwin": - # Strange failures on windows/cygin/mingw + # Strange failures on windows/cygwin/mingw subprocess.check_call(commandline, env=env, shell=True) print((" Finished running: " + commandline)) diff --git a/Examples/python/import_packages/from_init3/runme.py b/Examples/python/import_packages/from_init3/runme.py index c9c46a4da..100c97b9e 100644 --- a/Examples/python/import_packages/from_init3/runme.py +++ b/Examples/python/import_packages/from_init3/runme.py @@ -4,7 +4,7 @@ import sys def run_except_on_windows(commandline, env=None): if os.name != "nt" and sys.platform != "cygwin": - # Strange failures on windows/cygin/mingw + # Strange failures on windows/cygwin/mingw subprocess.check_call(commandline, env=env, shell=True) print((" Finished running: " + commandline)) diff --git a/Examples/python/import_packages/namespace_pkg/nonpkg.py b/Examples/python/import_packages/namespace_pkg/nonpkg.py index 52be74db4..e87289089 100644 --- a/Examples/python/import_packages/namespace_pkg/nonpkg.py +++ b/Examples/python/import_packages/namespace_pkg/nonpkg.py @@ -4,7 +4,7 @@ import sys def run_except_on_windows(commandline, env=None): if os.name != "nt" and sys.platform != "cygwin": - # Strange failures on windows/cygin/mingw + # Strange failures on windows/cygwin/mingw subprocess.check_call(commandline, env=env, shell=True) print(" Finished running: " + commandline) diff --git a/Examples/python/import_packages/namespace_pkg/normal.py b/Examples/python/import_packages/namespace_pkg/normal.py index 0eb8f517c..f8fb025ad 100644 --- a/Examples/python/import_packages/namespace_pkg/normal.py +++ b/Examples/python/import_packages/namespace_pkg/normal.py @@ -4,7 +4,7 @@ import sys def run_except_on_windows(commandline, env=None): if os.name != "nt" and sys.platform != "cygwin": - # Strange failures on windows/cygin/mingw + # Strange failures on windows/cygwin/mingw subprocess.check_call(commandline, env=env, shell=True) print(" Finished running: " + commandline) diff --git a/Examples/python/import_packages/namespace_pkg/nstest.py b/Examples/python/import_packages/namespace_pkg/nstest.py index 4d618a6ad..0cd2a997d 100644 --- a/Examples/python/import_packages/namespace_pkg/nstest.py +++ b/Examples/python/import_packages/namespace_pkg/nstest.py @@ -6,7 +6,7 @@ import zipfile def run_except_on_windows(commandline, env=None): if os.name != "nt" and sys.platform != "cygwin": - # Strange failures on windows/cygin/mingw + # Strange failures on windows/cygwin/mingw subprocess.check_call(commandline, env=env, shell=True) print(" Finished running: " + commandline) diff --git a/Examples/python/import_packages/namespace_pkg/split.py b/Examples/python/import_packages/namespace_pkg/split.py index 9d786dc07..ed259b618 100644 --- a/Examples/python/import_packages/namespace_pkg/split.py +++ b/Examples/python/import_packages/namespace_pkg/split.py @@ -4,7 +4,7 @@ import sys def run_except_on_windows(commandline, env=None): if os.name != "nt" and sys.platform != "cygwin": - # Strange failures on windows/cygin/mingw + # Strange failures on windows/cygwin/mingw subprocess.check_call(commandline, env=env, shell=True) print(" Finished running: " + commandline) diff --git a/Examples/python/import_packages/namespace_pkg/zipsplit.py b/Examples/python/import_packages/namespace_pkg/zipsplit.py index 30434f9c0..474f2c742 100644 --- a/Examples/python/import_packages/namespace_pkg/zipsplit.py +++ b/Examples/python/import_packages/namespace_pkg/zipsplit.py @@ -4,7 +4,7 @@ import sys def run_except_on_windows(commandline, env=None): if os.name != "nt" and sys.platform != "cygwin": - # Strange failures on windows/cygin/mingw + # Strange failures on windows/cygwin/mingw subprocess.check_call(commandline, env=env, shell=True) print(" Finished running: " + commandline) diff --git a/Examples/python/import_packages/relativeimport1/runme.py b/Examples/python/import_packages/relativeimport1/runme.py index 3073cb5a7..ff8ca0427 100644 --- a/Examples/python/import_packages/relativeimport1/runme.py +++ b/Examples/python/import_packages/relativeimport1/runme.py @@ -4,7 +4,7 @@ import sys def run_except_on_windows(commandline, env=None): if os.name != "nt" and sys.platform != "cygwin": - # Strange failures on windows/cygin/mingw + # Strange failures on windows/cygwin/mingw subprocess.check_call(commandline, env=env, shell=True) print((" Finished running: " + commandline)) diff --git a/Examples/python/import_packages/relativeimport2/runme.py b/Examples/python/import_packages/relativeimport2/runme.py index 9ab8d9471..35c57e10b 100644 --- a/Examples/python/import_packages/relativeimport2/runme.py +++ b/Examples/python/import_packages/relativeimport2/runme.py @@ -4,7 +4,7 @@ import sys def run_except_on_windows(commandline, env=None): if os.name != "nt" and sys.platform != "cygwin": - # Strange failures on windows/cygin/mingw + # Strange failures on windows/cygwin/mingw subprocess.check_call(commandline, env=env, shell=True) print((" Finished running: " + commandline)) diff --git a/Examples/python/import_packages/relativeimport3/runme.py b/Examples/python/import_packages/relativeimport3/runme.py index 3073cb5a7..ff8ca0427 100644 --- a/Examples/python/import_packages/relativeimport3/runme.py +++ b/Examples/python/import_packages/relativeimport3/runme.py @@ -4,7 +4,7 @@ import sys def run_except_on_windows(commandline, env=None): if os.name != "nt" and sys.platform != "cygwin": - # Strange failures on windows/cygin/mingw + # Strange failures on windows/cygwin/mingw subprocess.check_call(commandline, env=env, shell=True) print((" Finished running: " + commandline)) diff --git a/Examples/python/import_packages/same_modnames1/runme.py b/Examples/python/import_packages/same_modnames1/runme.py index 05846ed9d..41d84aa3d 100644 --- a/Examples/python/import_packages/same_modnames1/runme.py +++ b/Examples/python/import_packages/same_modnames1/runme.py @@ -4,7 +4,7 @@ import sys def run_except_on_windows(commandline, env=None): if os.name != "nt" and sys.platform != "cygwin": - # Strange failures on windows/cygin/mingw + # Strange failures on windows/cygwin/mingw subprocess.check_call(commandline, env=env, shell=True) print((" Finished running: " + commandline)) diff --git a/Examples/python/import_packages/same_modnames2/runme.py b/Examples/python/import_packages/same_modnames2/runme.py index 190dadc77..48c209b86 100644 --- a/Examples/python/import_packages/same_modnames2/runme.py +++ b/Examples/python/import_packages/same_modnames2/runme.py @@ -4,7 +4,7 @@ import sys def run_except_on_windows(commandline, env=None): if os.name != "nt" and sys.platform != "cygwin": - # Strange failures on windows/cygin/mingw + # Strange failures on windows/cygwin/mingw subprocess.check_call(commandline, env=env, shell=True) print((" Finished running: " + commandline)) diff --git a/Examples/python/import_packages/split_modules/vanilla/runme.py b/Examples/python/import_packages/split_modules/vanilla/runme.py index 0f7b8806b..723eb3aaa 100644 --- a/Examples/python/import_packages/split_modules/vanilla/runme.py +++ b/Examples/python/import_packages/split_modules/vanilla/runme.py @@ -4,7 +4,7 @@ import sys def run_except_on_windows(commandline, env=None): if os.name != "nt" and sys.platform != "cygwin": - # Strange failures on windows/cygin/mingw + # Strange failures on windows/cygwin/mingw subprocess.check_call(commandline, env=env, shell=True) print((" Finished running: " + commandline)) diff --git a/Examples/python/import_packages/split_modules/vanilla_split/runme.py b/Examples/python/import_packages/split_modules/vanilla_split/runme.py index 0f7b8806b..723eb3aaa 100644 --- a/Examples/python/import_packages/split_modules/vanilla_split/runme.py +++ b/Examples/python/import_packages/split_modules/vanilla_split/runme.py @@ -4,7 +4,7 @@ import sys def run_except_on_windows(commandline, env=None): if os.name != "nt" and sys.platform != "cygwin": - # Strange failures on windows/cygin/mingw + # Strange failures on windows/cygwin/mingw subprocess.check_call(commandline, env=env, shell=True) print((" Finished running: " + commandline)) diff --git a/Examples/ruby/exceptproxy/example.i b/Examples/ruby/exceptproxy/example.i index ad0c23acb..3a3077f8a 100644 --- a/Examples/ruby/exceptproxy/example.i +++ b/Examples/ruby/exceptproxy/example.i @@ -16,7 +16,7 @@ /* The EmptyError doesn't appear in a throw declaration, and hence we need to tell SWIG that the dequeue method throws it. This can - now be done via the %catchs feature. */ + now be done via the %catches feature. */ %catches(FullError) *::enqueue; %catches(EmptyError) *::dequeue(); diff --git a/Examples/test-suite/php/director_extend_runme.php b/Examples/test-suite/php/director_extend_runme.php index 418985476..3c6dd6b1d 100644 --- a/Examples/test-suite/php/director_extend_runme.php +++ b/Examples/test-suite/php/director_extend_runme.php @@ -17,6 +17,6 @@ class MyObject extends SpObject{ $m = new MyObject(); check::equal($m->dummy(), 666, "1st call"); -check::equal($m->dummy(), 666, "2st call"); // Locked system +check::equal($m->dummy(), 666, "2nd call"); // Locked system check::done(); diff --git a/Source/CParse/parser.y b/Source/CParse/parser.y index 9ecb65ba1..1ae3a59db 100644 --- a/Source/CParse/parser.y +++ b/Source/CParse/parser.y @@ -25,7 +25,7 @@ %{ #define yylex yylex -/* doh.h uses #pragma GCC posion with GCC to prevent direct calls to certain +/* doh.h uses #pragma GCC poison with GCC to prevent direct calls to certain * standard C library functions being introduced, but those cause errors due * to checks like `#if defined YYMALLOC || defined malloc` in the bison * template code. We can't easily arrange to include headers after that diff --git a/Source/Modules/r.cxx b/Source/Modules/r.cxx index 541e7e622..536ee1243 100644 --- a/Source/Modules/r.cxx +++ b/Source/Modules/r.cxx @@ -940,7 +940,7 @@ int R::OutputClassMethodsTable(File *) { * The entries are indexed by _set and * _get. Each entry is a List *. - * out - the stram where the code is to be written. This is the S + * out - the stream where the code is to be written. This is the S * code stream as we generate only S code here. * --------------------------------------------------------------*/ From 962f0900018ecb10287b327d261e424fa5ccb755 Mon Sep 17 00:00:00 2001 From: Robin Stocker Date: Mon, 11 Apr 2022 11:44:39 +1000 Subject: [PATCH 410/662] Fix Ruby 3.2 warning "undefining the allocator of T_DATA class swig_runtime_data" Ruby 3.2 (still in development) started warning about this, see https://bugs.ruby-lang.org/issues/18007. Note that the extension docs mention it in https://ruby-doc.org/core-3.1.1/doc/extension_rdoc.html#label-C+struct+to+Ruby+object: > The klass argument is the class for the object. The klass should > derive from `rb_cObject`, and the allocator must be set by calling > `rb_define_alloc_func` or `rb_undef_alloc_func`. So in this case we call `rb_undef_alloc_func` to fix the warning. Verified that this works in robinst/taglib-ruby#115. Fixes #2257. --- Lib/ruby/rubyrun.swg | 1 + 1 file changed, 1 insertion(+) diff --git a/Lib/ruby/rubyrun.swg b/Lib/ruby/rubyrun.swg index 7c94c4e12..e4c23bde5 100644 --- a/Lib/ruby/rubyrun.swg +++ b/Lib/ruby/rubyrun.swg @@ -413,6 +413,7 @@ SWIG_Ruby_SetModule(swig_module_info *pointer) { /* register a new class */ VALUE cl = rb_define_class("swig_runtime_data", rb_cObject); + rb_undef_alloc_func(cl); /* create and store the structure pointer to a global variable */ swig_runtime_data_type_pointer = Data_Wrap_Struct(cl, 0, 0, pointer); rb_define_readonly_variable("$swig_runtime_data_type_pointer" SWIG_RUNTIME_VERSION SWIG_TYPE_TABLE_NAME, &swig_runtime_data_type_pointer); From 822e51009ee03dcf3720112c68d98368bcf13200 Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Tue, 12 Apr 2022 08:35:11 +1200 Subject: [PATCH 411/662] Add CHANGES entry for #2257/#2258 --- CHANGES.current | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGES.current b/CHANGES.current index d41a4c235..234e730c3 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-04-11: robinst + #2257 Fix new Ruby 3.2 warning "undefining the allocator of T_DATA + class swig_runtime_data". + 2022-04-07: olly #1750 SWIG now recognises and ignores Doxygen group commands `@{` and `@}`. From 6043554c38edc30cbe27ba632462f55fb702bb87 Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Wed, 13 Apr 2022 11:14:29 +1200 Subject: [PATCH 412/662] configure.ac: Add missing shell quoting Fixes "./configure[4896]: test: argument expected" on stderr. --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 3ea50e9c1..0d86e9ca9 100644 --- a/configure.ac +++ b/configure.ac @@ -59,7 +59,7 @@ dnl To make configuring easier, check for a locally built PCRE using the Tools/p if test x"${with_pcre}" = xyes ; then AC_MSG_CHECKING([whether to use local PCRE2]) local_pcre_config=no - if test -z $PCRE2_CONFIG; then + if test -z "$PCRE2_CONFIG"; then if test -f `pwd`/pcre/pcre-swig-install/bin/pcre2-config; then PCRE2_CONFIG=`pwd`/pcre/pcre-swig-install/bin/pcre2-config local_pcre_config=$PCRE2_CONFIG From fb4c69b4b02c1b3fac28624c16e684ae77de91fc Mon Sep 17 00:00:00 2001 From: Corey Minyard Date: Fri, 18 Mar 2022 21:40:11 -0500 Subject: [PATCH 413/662] [Go] Add missing newlines for goin typemaps In some cases the \n was missing from goin directives in some places. Without this change, you will get } swig_r = (int)(C.... in the output in some cases, and that won't compile in Go, it will error with: ../gensio/gensio.go:1508:3: expected ';', found swig_r It only did this on director callbacks with godirectorin, and only if the virtual function wasn't assigned to zero. So the following will fail: class callbacks { public: virtual bool call1(int v, const char * const *strarray); virtual ~callbacks() = default; }; but the following won't: class callbacks { public: virtual bool call1(int v, const char * const *strarray) = 0; virtual ~callbacks() = default; }; Add "\n" to the proper places to fix this. --- Source/Modules/go.cxx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Source/Modules/go.cxx b/Source/Modules/go.cxx index 071d39ec7..d828b00aa 100644 --- a/Source/Modules/go.cxx +++ b/Source/Modules/go.cxx @@ -3518,7 +3518,7 @@ private: goin = Copy(goin); Replaceall(goin, "$input", ln); Replaceall(goin, "$result", ivar); - Printv(f_go_wrappers, goin, NULL); + Printv(f_go_wrappers, goin, "\n", NULL); Delete(goin); } @@ -3772,7 +3772,7 @@ private: goin = Copy(goin); Replaceall(goin, "$input", ln); Replaceall(goin, "$result", ivar); - Printv(f_go_wrappers, goin, NULL); + Printv(f_go_wrappers, goin, "\n", NULL); Delete(goin); } From 546763ffbc333b98808802fff0d601d018763d0c Mon Sep 17 00:00:00 2001 From: Corey Minyard Date: Sun, 20 Mar 2022 15:04:27 -0500 Subject: [PATCH 414/662] [Go] Add an example for goin and godirectorin Shows how to use a go directory for passing an NULL terminated argv type array. This also exercises the bug in the previous commit. That's why the call1 function isn't assigned to zero, that the only case where that bug happens. Signed-off-by: Corey Minyard --- Examples/go/check.list | 1 + Examples/go/goin/Makefile | 18 ++++++ Examples/go/goin/example.i | 106 ++++++++++++++++++++++++++++++++++++ Examples/go/goin/index.html | 26 +++++++++ Examples/go/goin/runme.go | 38 +++++++++++++ Examples/go/index.html | 1 + 6 files changed, 190 insertions(+) create mode 100644 Examples/go/goin/Makefile create mode 100644 Examples/go/goin/example.i create mode 100644 Examples/go/goin/index.html create mode 100644 Examples/go/goin/runme.go diff --git a/Examples/go/check.list b/Examples/go/check.list index b3f34b306..6046c8310 100644 --- a/Examples/go/check.list +++ b/Examples/go/check.list @@ -12,3 +12,4 @@ reference simple template variables +goin diff --git a/Examples/go/goin/Makefile b/Examples/go/goin/Makefile new file mode 100644 index 000000000..f79b083cb --- /dev/null +++ b/Examples/go/goin/Makefile @@ -0,0 +1,18 @@ +TOP = ../.. +SWIGEXE = $(TOP)/../swig +SWIG_LIB_DIR = $(TOP)/../$(TOP_BUILDDIR_TO_TOP_SRCDIR)Lib +CXXSRCS = +TARGET = example +INTERFACE = example.i +SWIGOPT = + +check: build + $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' CXXSRCS='$(CXXSRCS)' TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' go_run + +build: + $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' CXXSRCS='$(CXXSRCS)' \ + SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \ + SWIGOPT='$(SWIGOPT)' TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' go_cpp + +clean: + $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' INTERFACE='$(INTERFACE)' go_clean diff --git a/Examples/go/goin/example.i b/Examples/go/goin/example.i new file mode 100644 index 000000000..1d8289af8 --- /dev/null +++ b/Examples/go/goin/example.i @@ -0,0 +1,106 @@ + +%module(directors="1") example + +%inline %{ +// Helper functions for converting string arrays +#include +void *alloc_ptr_array(unsigned int len) +{ + return calloc(len, sizeof(void *)); +} +void set_ptr_array(void *ain, unsigned int pos, void *val) +{ + void **a = (void **) ain; + a[pos] = val; +} +void *get_ptr_array(void *ain, unsigned int pos) +{ + void **a = (void **) ain; + return a[pos]; +} +void free_ptr_array(void *ain) +{ + void **a = (void **) ain; + unsigned int i; + + if (!a) + return; + for (i = 0; a[i]; i++) { + free(a[i]); + } + free(a); +} +char *uintptr_to_string(void *in) +{ + return (char *) in; +} +void *string_to_uintptr(char *in) +{ + return strdup(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(goin) (const char * const *) { + if $input == nil || len($input) == 0 { + $result = 0 + } else { + $result = Alloc_ptr_array(uint(len($input) + 1)) + defer func() { + Free_ptr_array($result) + }() + var i uint + for i = 0; i < uint(len($input)); i++ { + Set_ptr_array($result, i, String_to_uintptr($input[i])) + } + } +} +%typemap(in) (const char * const *) { + $1 = (char **) $input; +} +%typemap(godirectorin) (const char * const *) { + if ($input == 0) { + $result = nil + } else { + var i uint + for i = 0; ; i++ { + var v uintptr = Get_ptr_array($input, i) + if v == 0 { + break + } + } + if i == 0 { + $result = nil + } else { + $result = make([]string, i) + for i = 0; ; i++ { + var v uintptr = Get_ptr_array($input, i) + if v == 0 { + break + } + $result[i] = Uintptr_to_string(v) + } + } + } +} + +%feature("director") callbacks; + +%inline %{ + class callbacks { + public: + virtual bool call1(int v, const char * const *strarray); + virtual ~callbacks() {} + }; + + bool check1(callbacks *c, int v, const char * const *strarray) { + return c->call1(v, strarray); + } + + bool callbacks::call1(int v, const char * const *strarray) { + return false; + } +%} diff --git a/Examples/go/goin/index.html b/Examples/go/goin/index.html new file mode 100644 index 000000000..852b068da --- /dev/null +++ b/Examples/go/goin/index.html @@ -0,0 +1,26 @@ + + +SWIG:Examples:go:going + + + + + +SWIG/Examples/go/goin/ +
      + +

      Example of using goin and godirectorin

      + +

      +This example converts between a Go []string and a "const char * const *" +in C/C++. It does this for a director and for a normal call. + +

      +

      + +
      + + diff --git a/Examples/go/goin/runme.go b/Examples/go/goin/runme.go new file mode 100644 index 000000000..dfc7b0936 --- /dev/null +++ b/Examples/go/goin/runme.go @@ -0,0 +1,38 @@ +package main + +import ( + "fmt" + "swigtests/example" +) + +type mycallbacks struct { + example.Callbacks +} + +var tststrs = []string{ "A", "BCD", "EFGH" } +var tstint int = 5 + +func (v *mycallbacks) Call1(val int, strarray []string) bool { + var rv bool = true + + for i, s := range strarray { + fmt.Printf("%d: %s\n", i, s) + if s != tststrs[i] { + fmt.Printf(" ***Mismatch, expected %s\n", tststrs[i]) + rv = false + } + } + if val != tstint { + rv = false + } + return rv +} + +func main() { + cbs := &mycallbacks{} + cbs.Callbacks = example.NewDirectorCallbacks(cbs) + worked := example.Check1(cbs, tstint, tststrs) + if !worked { + panic("Data mismatch") + } +} diff --git a/Examples/go/index.html b/Examples/go/index.html index 467f4ecb7..370424c54 100644 --- a/Examples/go/index.html +++ b/Examples/go/index.html @@ -24,6 +24,7 @@ certain C declarations are turned into constants.
    • callback. C++ callbacks using directors.
    • extend. Polymorphism using directors.
    • director. Example how to utilize the director feature. +
    • director. Example how to use goin and godirectorin.

    Compilation Issues

    From 3cc67d42f39b816e04d4d31fa624923c094a6ff0 Mon Sep 17 00:00:00 2001 From: Corey Minyard Date: Mon, 18 Apr 2022 19:53:59 -0500 Subject: [PATCH 415/662] [Go] Add a test for godirectorin with const char ** This exercises a bug that was found with this fairly complex mapping, it wasn't putting newlines in the proper place. A previous commit added the newlines, this makes sure it doesn't happen again. Signed-off-by: Corey Minyard --- .../test-suite/go/go_director_inout_runme.go | 11 ++ Examples/test-suite/go_director_inout.i | 102 +++++++++++++++++- 2 files changed, 112 insertions(+), 1 deletion(-) diff --git a/Examples/test-suite/go/go_director_inout_runme.go b/Examples/test-suite/go/go_director_inout_runme.go index f2be9d30b..55f32dfc3 100644 --- a/Examples/test-suite/go/go_director_inout_runme.go +++ b/Examples/test-suite/go/go_director_inout_runme.go @@ -34,6 +34,15 @@ func (p *GoMyClass) S3(s *string) { *s = "R3" } +func (p *GoMyClass) S4(s []string) { + if s[0] != "T1" { + panic(s) + } + if s[1] != "T2" { + panic(s) + } +} + func main() { a := wrap.NewDirectorMyClass(&GoMyClass{}) m := map[string]interface{}{ @@ -56,6 +65,8 @@ func main() { panic(str) } + a.CallS4([]string{ "T1", "T2" }) + a = wrap.NewDirectorMyClass(nil) s = a.Adjust(m) if s.Str != `{"first":"second"}` { diff --git a/Examples/test-suite/go_director_inout.i b/Examples/test-suite/go_director_inout.i index 38059ea40..b12e5da52 100644 --- a/Examples/test-suite/go_director_inout.i +++ b/Examples/test-suite/go_director_inout.i @@ -120,6 +120,92 @@ type GoRetStruct struct { $1.assign(tmp->p, tmp->p + tmp->n); } +%inline %{ +// Helper functions for converting string arrays +#include +void *alloc_ptr_array(unsigned int len) +{ + return calloc(len, sizeof(void *)); +} +void set_ptr_array(void *ain, unsigned int pos, void *val) +{ + void **a = (void **) ain; + a[pos] = val; +} +void *get_ptr_array(void *ain, unsigned int pos) +{ + void **a = (void **) ain; + return a[pos]; +} +void free_ptr_array(void *ain) +{ + void **a = (void **) ain; + unsigned int i; + + if (!a) + return; + for (i = 0; a[i]; i++) { + free(a[i]); + } + free(a); +} +char *uintptr_to_string(void *in) +{ + return (char *) in; +} +void *string_to_uintptr(char *in) +{ + return strdup(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(goin) (const char * const *) { + if $input == nil || len($input) == 0 { + $result = 0 + } else { + $result = Alloc_ptr_array(uint(len($input) + 1)) + defer func() { + Free_ptr_array($result) + }() + var i uint + for i = 0; i < uint(len($input)); i++ { + Set_ptr_array($result, i, String_to_uintptr($input[i])) + } + } +} +%typemap(in) (const char * const *) { + $1 = (char **) $input; +} +%typemap(godirectorin) (const char * const *) { + if ($input == 0) { + $result = nil + } else { + var i uint + for i = 0; ; i++ { + var v uintptr = Get_ptr_array($input, i) + if v == 0 { + break + } + } + if i == 0 { + $result = nil + } else { + $result = make([]string, i) + for i = 0; ; i++ { + var v uintptr = Get_ptr_array($input, i) + if v == 0 { + break + } + $result[i] = Uintptr_to_string(v) + } + } + } +} + %feature("director") MyClass; %inline @@ -134,9 +220,23 @@ class MyClass { return r; } - virtual void S1(std::string s) = 0; + void CallS4(const char * const *strarray); + virtual void S1(std::string s); virtual void S2(std::string& s) = 0; virtual void S3(std::string* s) = 0; + virtual void S4(const char * const *strarray); }; +void MyClass::S1(std::string s) { + throw "Base S1 called!"; +} + +void MyClass::S4(const char * const *strarray) { + throw "Base S4 called!"; +} + +void MyClass::CallS4(const char * const *strarray) { + this->S4(strarray); +} + %} From 537669ba3dc97e0e6033160c9a736b63d0f9427f Mon Sep 17 00:00:00 2001 From: Corey Minyard Date: Wed, 20 Apr 2022 17:54:15 -0500 Subject: [PATCH 416/662] CHANGES.current: Add an entry for the godirectorin bug Document what was fixed in the previous few changes. Signed-off-by: Corey Minyard --- CHANGES.current | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/CHANGES.current b/CHANGES.current index 234e730c3..0c6db7c90 100644 --- a/CHANGES.current +++ b/CHANGES.current @@ -7,6 +7,17 @@ the issue number to the end of the URL: https://github.com/swig/swig/issues/ Version 4.1.0 (in progress) =========================== +2022-04-20: cminyard + Fix an issue where newlines were not properly generated + for godirectorin typemaps. If you have a virtual function + not assigned to zero, in some cases it won't generate a + newline and you will see errors: + example.go:1508:3: expected ';', found swig_r + when compiling the go code. + + Also add an example of using goin and godirectorin and add + a test for this situation. + 2022-04-11: robinst #2257 Fix new Ruby 3.2 warning "undefining the allocator of T_DATA class swig_runtime_data". From f5934b099b6db3e5bde9f2745a7e58d4768b8e88 Mon Sep 17 00:00:00 2001 From: Kris Thielemans Date: Thu, 21 Apr 2022 12:28:54 +0100 Subject: [PATCH 417/662] [Python] Replace tp_print with tp_vectorcall_offset slot for Python 3.8 The tp_print slot is no longer supported and replaced with tp_vectorcall_offset. The (printfunc) cast that we used caused problems on PyPy. Fixes #2262 --- Lib/python/builtin.swg | 12 ++++++++++-- Lib/python/pyrun.swg | 18 +++++++++++++++--- Source/Modules/python.cxx | 4 ++++ 3 files changed, 29 insertions(+), 5 deletions(-) diff --git a/Lib/python/builtin.swg b/Lib/python/builtin.swg index ec092233d..5da8d6ae3 100644 --- a/Lib/python/builtin.swg +++ b/Lib/python/builtin.swg @@ -211,7 +211,11 @@ SwigPyStaticVar_Type(void) { sizeof(PyGetSetDescrObject), /* tp_basicsize */ 0, /* tp_itemsize */ (destructor)SwigPyStaticVar_dealloc, /* tp_dealloc */ - 0, /* tp_print */ +#if PY_VERSION_HEX < 0x030800b4 + (printfunc)0, /*tp_print*/ +#else + (Py_ssize_t)0, /*tp_vectorcall_offset*/ +#endif 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_compare */ @@ -295,7 +299,11 @@ SwigPyObjectType(void) { PyType_Type.tp_basicsize, /* tp_basicsize */ 0, /* tp_itemsize */ 0, /* tp_dealloc */ - 0, /* tp_print */ +#if PY_VERSION_HEX < 0x030800b4 + (printfunc)0, /*tp_print*/ +#else + (Py_ssize_t)0, /*tp_vectorcall_offset*/ +#endif 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_compare */ diff --git a/Lib/python/pyrun.swg b/Lib/python/pyrun.swg index 081bb2cde..935885934 100644 --- a/Lib/python/pyrun.swg +++ b/Lib/python/pyrun.swg @@ -348,7 +348,11 @@ swig_varlink_type(void) { sizeof(swig_varlinkobject), /* tp_basicsize */ 0, /* tp_itemsize */ (destructor) swig_varlink_dealloc, /* tp_dealloc */ - 0, /* tp_print */ +#if PY_VERSION_HEX < 0x030800b4 + (printfunc)0, /*tp_print*/ +#else + (Py_ssize_t)0, /*tp_vectorcall_offset*/ +#endif (getattrfunc) swig_varlink_getattr, /* tp_getattr */ (setattrfunc) swig_varlink_setattr, /* tp_setattr */ 0, /* tp_compare */ @@ -914,7 +918,11 @@ SwigPyObject_TypeOnce(void) { sizeof(SwigPyObject), /* tp_basicsize */ 0, /* tp_itemsize */ (destructor)SwigPyObject_dealloc, /* tp_dealloc */ - 0, /* tp_print */ +#if PY_VERSION_HEX < 0x030800b4 + (printfunc)0, /*tp_print*/ +#else + (Py_ssize_t)0, /*tp_vectorcall_offset*/ +#endif (getattrfunc)0, /* tp_getattr */ (setattrfunc)0, /* tp_setattr */ #if PY_VERSION_HEX >= 0x03000000 @@ -1090,7 +1098,11 @@ SwigPyPacked_TypeOnce(void) { sizeof(SwigPyPacked), /* tp_basicsize */ 0, /* tp_itemsize */ (destructor)SwigPyPacked_dealloc, /* tp_dealloc */ - 0, /* tp_print */ +#if PY_VERSION_HEX < 0x030800b4 + (printfunc)0, /*tp_print*/ +#else + (Py_ssize_t)0, /*tp_vectorcall_offset*/ +#endif (getattrfunc)0, /* tp_getattr */ (setattrfunc)0, /* tp_setattr */ #if PY_VERSION_HEX>=0x03000000 diff --git a/Source/Modules/python.cxx b/Source/Modules/python.cxx index cd87984dc..7161c8e7d 100644 --- a/Source/Modules/python.cxx +++ b/Source/Modules/python.cxx @@ -4145,7 +4145,11 @@ public: printSlot(f, getSlot(n, "feature:python:tp_basicsize", tp_basicsize), "tp_basicsize"); printSlot(f, getSlot(n, "feature:python:tp_itemsize"), "tp_itemsize"); printSlot(f, getSlot(n, "feature:python:tp_dealloc", tp_dealloc_bad), "tp_dealloc", "destructor"); + Printv(f, "#if PY_VERSION_HEX < 0x030800b4\n", NIL); printSlot(f, getSlot(n, "feature:python:tp_print"), "tp_print", "printfunc"); + Printv(f, "#else\n", NIL); + printSlot(f, getSlot(n, "feature:python:tp_vectorcall_offset"), "tp_vectorcall_offset", "Py_ssize_t"); + Printv(f, "#endif\n", NIL); printSlot(f, getSlot(n, "feature:python:tp_getattr"), "tp_getattr", "getattrfunc"); printSlot(f, getSlot(n, "feature:python:tp_setattr"), "tp_setattr", "setattrfunc"); Printv(f, "#if PY_VERSION_HEX >= 0x03000000\n", NIL); From 8dc4e3a8cb063778255b03e02c246c8c641f6a43 Mon Sep 17 00:00:00 2001 From: Kris Thielemans Date: Thu, 28 Apr 2022 08:00:42 +0100 Subject: [PATCH 418/662] fix white-space --- Lib/python/builtin.swg | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Lib/python/builtin.swg b/Lib/python/builtin.swg index 5da8d6ae3..9dccd7e20 100644 --- a/Lib/python/builtin.swg +++ b/Lib/python/builtin.swg @@ -212,9 +212,9 @@ SwigPyStaticVar_Type(void) { 0, /* tp_itemsize */ (destructor)SwigPyStaticVar_dealloc, /* tp_dealloc */ #if PY_VERSION_HEX < 0x030800b4 - (printfunc)0, /*tp_print*/ + (printfunc)0, /* tp_print */ #else - (Py_ssize_t)0, /*tp_vectorcall_offset*/ + (Py_ssize_t)0, /* tp_vectorcall_offset */ #endif 0, /* tp_getattr */ 0, /* tp_setattr */ @@ -300,9 +300,9 @@ SwigPyObjectType(void) { 0, /* tp_itemsize */ 0, /* tp_dealloc */ #if PY_VERSION_HEX < 0x030800b4 - (printfunc)0, /*tp_print*/ + (printfunc)0, /* tp_print */ #else - (Py_ssize_t)0, /*tp_vectorcall_offset*/ + (Py_ssize_t)0, /* tp_vectorcall_offset */ #endif 0, /* tp_getattr */ 0, /* tp_setattr */ From ed42422d1c80deae1a6971cbb722f41123a4120d Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Fri, 29 Apr 2022 18:13:21 +0100 Subject: [PATCH 419/662] Add support for wchar_t * and std::wstring Unicode strings on Linux Initial contributions for Linux provided in issue #1233, modified to work on both Windows and Linux. Dual support is possible by detecting the sizeof wchar_t which is different on each of these systems. --- CHANGES.current | 3 + .../test-suite/csharp/li_std_wstring_runme.cs | 70 +++++-- Examples/test-suite/li_std_wstring.h | 5 + Examples/test-suite/li_std_wstring.i | 65 +++++- Lib/csharp/std_wstring.i | 40 +++- Lib/csharp/wchar.i | 188 ++++++++++++++++-- Lib/swigwarnings.swg | 1 + Source/Include/swigwarn.h | 1 + 8 files changed, 327 insertions(+), 46 deletions(-) create mode 100644 Examples/test-suite/li_std_wstring.h diff --git a/CHANGES.current b/CHANGES.current index 0c6db7c90..cfa0af2db 100644 --- a/CHANGES.current +++ b/CHANGES.current @@ -18,6 +18,9 @@ Version 4.1.0 (in progress) Also add an example of using goin and godirectorin and add a test for this situation. +2022-04-29: jason-daly, JerryJoyce, wsfulton + [C#] #1233 Add wchar_t * and std::wstring Unicode string support on Linux. + 2022-04-11: robinst #2257 Fix new Ruby 3.2 warning "undefining the allocator of T_DATA class swig_runtime_data". diff --git a/Examples/test-suite/csharp/li_std_wstring_runme.cs b/Examples/test-suite/csharp/li_std_wstring_runme.cs index d2927287f..059688a75 100644 --- a/Examples/test-suite/csharp/li_std_wstring_runme.cs +++ b/Examples/test-suite/csharp/li_std_wstring_runme.cs @@ -1,3 +1,6 @@ +// This file has a BOM for UTF-8 +// Notes for displaying UTF-8 properly in Windows: https://stackoverflow.com/questions/49476326/displaying-unicode-in-powershell + using System; using li_std_wstringNamespace; @@ -5,17 +8,38 @@ public class runme { static private void check_equal(char a, char b) { - if (a != b) - throw new Exception("char failed '" + a + "' != '" + b + "'"); + if (a != b) + throw new Exception("char failed '" + a + "' != '" + b + "'"); + } + + static private void display_bytes(string s) + { + Console.Write("["); + if (s != null) + { + foreach (char x in s) + { + int n = Convert.ToInt32(x); + Console.Write(n.ToString("X") + " "); + } + } + else + Console.Write("null"); + Console.WriteLine("]"); } static private void check_equal(string a, string b) { - if (a != b) - throw new Exception("string failed '" + a + "' != '" + b + "'"); + if (li_std_wstring.debug) { + Console.WriteLine("check_equal {0} {1}", a, b); + display_bytes(a); + display_bytes(b); + } + if (a != b) + throw new Exception("string failed '" + a + "' != '" + b + "'"); } - static void Main() + static void Main() { char h = 'h'; check_equal(li_std_wstring.test_wcvalue(h), h); @@ -30,6 +54,8 @@ public class runme li_std_wstring.test_pointer(null); li_std_wstring.test_const_pointer(null); + check_equal(li_std_wstring.test_ccvalue(null), null); + try { li_std_wstring.test_value(null); throw new Exception("NULL check failed"); @@ -37,8 +63,8 @@ public class runme } try { - li_std_wstring.test_reference(null); - throw new Exception("NULL check failed"); + li_std_wstring.test_reference(null); + throw new Exception("NULL check failed"); } catch (ArgumentNullException e) { if (!e.Message.Contains("type is null")) throw new Exception("Missing text " + e); @@ -54,13 +80,24 @@ public class runme x = "hello"; check_equal(li_std_wstring.test_const_reference(x), x); - /* Postpone, tricky, std::wstring portability problem. + /* Tricky, std::wstring portability problem. * std::wstring is 2 bytes on Windows, 4 bytes on Linux, LPWSTR is 2 bytes. - * .NET marshalling should work on Windows but not Linux. - string s = "abc"; - if (!li_std_wstring.test_equal_abc(s)) - throw new Exception("Not equal " + s); - */ + */ + string ss = "abc"; + if (!li_std_wstring.test_equal_abc(ss)) + throw new Exception("Not equal " + ss); + + ss = "JP: 日本語"; + if (!li_std_wstring.test_equal_jp(ss)) + throw new Exception("Not equal " + ss); + + ss = "DE: Kröpeliner Straße"; + if (!li_std_wstring.test_equal_de(ss)) + throw new Exception("Not equal " + ss); + + ss = "RU: Война и мир"; + if (!li_std_wstring.test_equal_ru(ss)) + throw new Exception("Not equal " + ss); try { li_std_wstring.test_throw(); @@ -81,15 +118,22 @@ public class runme check_equal(s.wchar_t_member, h); s.wchar_t_ptr_member = x; check_equal(s.wchar_t_ptr_member, "abc"); + s.wchar_t_ptr_member = ss; + check_equal(s.wchar_t_ptr_member, ss); { // Unicode strings + // Strings below are UTF8 in this file, but .NET holds them internally as UTF16 + // DE: https://www.utf8-chartable.de/ + // RU: https://www.utf8-chartable.de/unicode-utf8-table.pl?start=1024 string[] test_strings = { "JP: 日本語", "DE: Kröpeliner Straße" , "RU: Война и мир", "EN: War and Peace" }; foreach (string expected in test_strings) { + if (li_std_wstring.debug) + Console.WriteLine("expected (C#): " + expected); string received = li_std_wstring.test_value(expected); check_equal(received, expected); } diff --git a/Examples/test-suite/li_std_wstring.h b/Examples/test-suite/li_std_wstring.h new file mode 100644 index 000000000..a16b7cd30 --- /dev/null +++ b/Examples/test-suite/li_std_wstring.h @@ -0,0 +1,5 @@ +// This file has a BOM set to UTF-8, which is one way for Visual C++ to correctly interpet these strings +// Alternatively, the /utf-8 command line option could be used +#define JP_WSTRING L"JP: 日本語" +#define DE_WSTRING L"DE: Kröpeliner Straße" +#define RU_WSTRING L"RU: Война и мир" \ No newline at end of file diff --git a/Examples/test-suite/li_std_wstring.i b/Examples/test-suite/li_std_wstring.i index a790ca7e0..1f5ddb458 100644 --- a/Examples/test-suite/li_std_wstring.i +++ b/Examples/test-suite/li_std_wstring.i @@ -3,44 +3,71 @@ // The languages below are yet to provide std_wstring.i #if !(defined(SWIGD) || defined(SWIGGO) || defined(SWIGGUILE) || defined(SWIGJAVASCRIPT) || defined(SWIGLUA) || defined(SWIGMZSCHEME) || defined(SWIGOCAML) || defined(SWIGOCTAVE) || defined(SWIGPERL) || defined(SWIGPHP) || defined(SWIGR) || defined(SWIGSCILAB)) +%warnfilter(SWIGWARN_TYPEMAP_WCHARLEAK_MSG) wchar_t_const_ptr_member; // Setting a const wchar_t * variable may leak memory. + %include + // throw is invalid in C++17 and later, only SWIG to use it #define TESTCASE_THROW1(T1) throw(T1) %{ #define TESTCASE_THROW1(T1) %} +%{ +// Unicode strings are stored in li_std_wstring.h file which has the BOM appropriately set, primarily for Visual C++ to correctly interpret the wide strings +#include "li_std_wstring.h" +%} + %inline %{ #include +#include + +bool debug = false; + +void show_wstring_bytes(const std::wstring &s) { + unsigned char *p = (unsigned char *)s.data(); + size_t len = s.size()*sizeof(wchar_t); + std::wcout << L"s: " << /*s <<*/ L"["; + for (size_t i = 0; i %} +%fragment("Swig_csharp_UTF16ToWString", "header") %{ +/* For converting from .NET UTF16 (2 byte unicode) strings. wchar_t is 2 bytes on Windows, 4 bytes on Linux. */ +static std::wstring Swig_csharp_UTF16ToWString(const wchar_t *str) { + if (sizeof(wchar_t) == 2) { + return std::wstring(str); + } else { + const unsigned short *pBegin((const unsigned short *)(str)); + const unsigned short *ptr(pBegin); + + while (*ptr != 0) + ++ptr; + + std::wstring result; + result.reserve(ptr - pBegin); + while(pBegin != ptr) + result.push_back(*pBegin++); + + return result; + } +} +%} + namespace std { %naturalvar wstring; @@ -31,22 +53,22 @@ class wstring; %typemap(csdirectorin) wstring "$iminput" %typemap(csdirectorout) wstring "$cscall" -%typemap(in, canthrow=1) wstring +%typemap(in, canthrow=1, fragment="Swig_csharp_UTF16ToWString") wstring %{ if (!$input) { SWIG_CSharpSetPendingExceptionArgument(SWIG_CSharpArgumentNullException, "null wstring", 0); return $null; } - $1.assign($input); %} -%typemap(out) wstring %{ $result = SWIG_csharp_wstring_callback($1.c_str()); %} + $1 = Swig_csharp_UTF16ToWString($input); %} +%typemap(out) wstring %{ $result = SWIG_csharp_wstring_with_length_callback($1.c_str(), (int)$1.size()); %} -%typemap(directorout, canthrow=1) wstring +%typemap(directorout, canthrow=1) wstring %{ if (!$input) { SWIG_CSharpSetPendingExceptionArgument(SWIG_CSharpArgumentNullException, "null wstring", 0); return $null; } $result.assign($input); %} -%typemap(directorin) wstring %{ $input = SWIG_csharp_wstring_callback($1.c_str()); %} +%typemap(directorin) wstring %{ $input = SWIG_csharp_wstring_with_length_callback($1.c_str(), (int)$1.size()); %} %typemap(csin) wstring "$csinput" %typemap(csout, excode=SWIGEXCODE) wstring { @@ -72,14 +94,14 @@ class wstring; %typemap(csdirectorin) const wstring & "$iminput" %typemap(csdirectorout) const wstring & "$cscall" -%typemap(in, canthrow=1) const wstring & +%typemap(in, canthrow=1, fragment="Swig_csharp_UTF16ToWString") const wstring & %{ if (!$input) { SWIG_CSharpSetPendingExceptionArgument(SWIG_CSharpArgumentNullException, "null wstring", 0); return $null; } - std::wstring $1_str($input); + std::wstring $1_str(Swig_csharp_UTF16ToWString($input)); $1 = &$1_str; %} -%typemap(out) const wstring & %{ $result = SWIG_csharp_wstring_callback($1->c_str()); %} +%typemap(out) const wstring & %{ $result = SWIG_csharp_wstring_with_length_callback($1->c_str(), (int)$1->size()); %} %typemap(csin) const wstring & "$csinput" %typemap(csout, excode=SWIGEXCODE) const wstring & { @@ -97,7 +119,7 @@ class wstring; $1_str = $input; $result = &$1_str; %} -%typemap(directorin) const wstring & %{ $input = SWIG_csharp_wstring_callback($1.c_str()); %} +%typemap(directorin) const wstring & %{ $input = SWIG_csharp_wstring_with_length_callback($1.c_str(), (int)$1->size()); %} %typemap(csvarin, excode=SWIGEXCODE2) const wstring & %{ set { diff --git a/Lib/csharp/wchar.i b/Lib/csharp/wchar.i index 1ece767da..14879c80c 100644 --- a/Lib/csharp/wchar.i +++ b/Lib/csharp/wchar.i @@ -11,28 +11,49 @@ #if !defined(SWIG_CSHARP_NO_WSTRING_HELPER) #if !defined(SWIG_CSHARP_WSTRING_HELPER_) #define SWIG_CSHARP_WSTRING_HELPER_ + +%fragment(""); // TODO: %fragment("") const wchar_t * { + if ($input && sizeof(wchar_t) == 2) { + $1 = ($1_type) (new wchar_t[wcslen((const wchar_t *)$input)+1]); + wcscpy((wchar_t *)$1, (const wchar_t *)$input); + } else { + $1 = $input; + $input = 0; + } +} +%typemap(globalin,fragment="") wchar_t * { + delete [] $1; + if ($input && sizeof(wchar_t) == 2) { + $1 = ($1_type) (new wchar_t[wcslen((const wchar_t *)$input)+1]); + wcscpy((wchar_t *)$1, (const wchar_t *)$input); + } else { + $1 = $input; + $input = 0; + } +} +%typemap(globalin,warning=SWIGWARN_TYPEMAP_WCHARLEAK_MSG,fragment="") const wchar_t * { + if ($input && sizeof(wchar_t) == 2) { + $1 = ($1_type) (new wchar_t[wcslen((const wchar_t *)$input)+1]); + wcscpy((wchar_t *)$1, (const wchar_t *)$input); + } else { + $1 = $input; + $input = 0; + } +} +#else +%typemap(memberin,fragment="") wchar_t * { + free($1); + if ($input && sizeof(wchar_t) == 2) { + $1 = ($1_type) malloc(wcslen((const wchar_t *)$input)+1); + wcscpy((wchar_t *)$1, (const wchar_t *)$input); + } else { + $1 = $input; + $input = 0; + } +} +%typemap(memberin,warning=SWIGWARN_TYPEMAP_WCHARLEAK_MSG,fragment="") const wchar_t * { + if ($input && sizeof(wchar_t) == 2) { + $1 = ($1_type) malloc(wcslen((const wchar_t *)$input)+1); + wcscpy((wchar_t *)$1, (const wchar_t *)$input); + } else { + $1 = $input; + $input = 0; + } +} +%typemap(globalin,fragment="") wchar_t * { + free($1); + if ($input && sizeof(wchar_t) == 2) { + $1 = ($1_type) malloc(wcslen((const wchar_t *)$input)+1); + wcscpy((wchar_t *)$1, (const wchar_t *)$input); + } else { + $1 = $input; + $input = 0; + } +} +%typemap(globalin,warning=SWIGWARN_TYPEMAP_WCHARLEAK_MSG,fragment="") const wchar_t * { + if ($input && sizeof(wchar_t) == 2) { + $1 = ($1_type) malloc(wcslen((const wchar_t *)$input)+1); + wcscpy((wchar_t *)$1, (const wchar_t *)$input); + } else { + $1 = $input; + $input = 0; + } +} + +#endif diff --git a/Lib/swigwarnings.swg b/Lib/swigwarnings.swg index 34c98fbda..3f9ddcb58 100644 --- a/Lib/swigwarnings.swg +++ b/Lib/swigwarnings.swg @@ -52,6 +52,7 @@ %define SWIGWARN_TYPEMAP_CHARLEAK_MSG "451:Setting a const char * variable may leak memory." %enddef %define SWIGWARN_TYPEMAP_SWIGTYPELEAK_MSG "454:Setting a pointer/reference variable may leak memory." %enddef +%define SWIGWARN_TYPEMAP_WCHARLEAK_MSG "455:Setting a const wchar_t * variable may leak memory." %enddef %define SWIGWARN_TYPEMAP_THREAD_UNSAFE_MSG "470:Thread/reentrant unsafe wrapping, consider returning by value instead." %enddef %define SWIGWARN_TYPEMAP_DIRECTOROUT_PTR_MSG "473:Returning a pointer or reference in a director method is not recommended." %enddef %define SWIGWARN_TYPEMAP_INITIALIZER_LIST_MSG "476:Initialization using std::initializer_list." %enddef diff --git a/Source/Include/swigwarn.h b/Source/Include/swigwarn.h index 267b69c90..8755f2ab5 100644 --- a/Source/Include/swigwarn.h +++ b/Source/Include/swigwarn.h @@ -163,6 +163,7 @@ #define WARN_TYPEMAP_SWIGTYPE 452 /* No longer issued */ #define WARN_TYPEMAP_APPLY_UNDEF 453 #define WARN_TYPEMAP_SWIGTYPELEAK 454 +#define WARN_TYPEMAP_WCHARLEAK 455 #define WARN_TYPEMAP_IN_UNDEF 460 #define WARN_TYPEMAP_OUT_UNDEF 461 From 0fbd6cc364910a352ee01a90196f647b32076ef1 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Tue, 26 Apr 2022 21:27:15 +0100 Subject: [PATCH 420/662] wchar_t C# marshalling tweak Use more appropriate unsigned short (2 byte type) pointer for C# ctype instead of wchar_t pointer --- Lib/csharp/std_wstring.i | 14 ++++++++------ Lib/csharp/wchar.i | 13 +++++++------ 2 files changed, 15 insertions(+), 12 deletions(-) diff --git a/Lib/csharp/std_wstring.i b/Lib/csharp/std_wstring.i index 8b38dd44c..e8b81bea7 100644 --- a/Lib/csharp/std_wstring.i +++ b/Lib/csharp/std_wstring.i @@ -2,7 +2,9 @@ * std_wstring.i * * Typemaps for std::wstring and const std::wstring& - * These are mapped to a C# String and are passed around by value. + * std::wstring is mapped to a C# Unicode string (UTF16) and is passed around by value. + * std::wstring support includes wchar_t as a 2 byte type (Windows) and a 4 byte type + * (most Unix systems). * * To use non-const std::wstring references use the following %apply. Note * that they are passed by value. @@ -17,11 +19,11 @@ %fragment("Swig_csharp_UTF16ToWString", "header") %{ /* For converting from .NET UTF16 (2 byte unicode) strings. wchar_t is 2 bytes on Windows, 4 bytes on Linux. */ -static std::wstring Swig_csharp_UTF16ToWString(const wchar_t *str) { +static std::wstring Swig_csharp_UTF16ToWString(const unsigned short *str) { if (sizeof(wchar_t) == 2) { - return std::wstring(str); + return std::wstring((wchar_t *)str); } else { - const unsigned short *pBegin((const unsigned short *)(str)); + const unsigned short *pBegin(str); const unsigned short *ptr(pBegin); while (*ptr != 0) @@ -44,7 +46,7 @@ namespace std { class wstring; // wstring -%typemap(ctype, out="void *") wstring "wchar_t *" +%typemap(ctype, out="void *") wstring "unsigned short *" %typemap(imtype, inattributes="[global::System.Runtime.InteropServices.MarshalAs(global::System.Runtime.InteropServices.UnmanagedType.LPWStr)]", outattributes="[return: global::System.Runtime.InteropServices.MarshalAs(global::System.Runtime.InteropServices.UnmanagedType.LPWStr)]" @@ -84,7 +86,7 @@ class wstring; return $null; %} // const wstring & -%typemap(ctype, out="void *") const wstring & "wchar_t *" +%typemap(ctype, out="void *") const wstring & "unsigned short *" %typemap(imtype, inattributes="[global::System.Runtime.InteropServices.MarshalAs(global::System.Runtime.InteropServices.UnmanagedType.LPWStr)]", outattributes="[return: global::System.Runtime.InteropServices.MarshalAs(global::System.Runtime.InteropServices.UnmanagedType.LPWStr)]" diff --git a/Lib/csharp/wchar.i b/Lib/csharp/wchar.i index 14879c80c..c6720eb04 100644 --- a/Lib/csharp/wchar.i +++ b/Lib/csharp/wchar.i @@ -2,10 +2,11 @@ * wchar.i * * Typemaps for the wchar_t type - * These are mapped to a C# String and are passed around by value. + * wchar_t * is mapped to a C# Unicode string (UTF16) and is passed around by value. + * wchar_t * support includes wchar_t as a 2 byte type (Windows) and a 4 byte type + * (most Unix systems). * * Support code for wide strings can be turned off by defining SWIG_CSHARP_NO_WSTRING_HELPER - * * ----------------------------------------------------------------------------- */ #if !defined(SWIG_CSHARP_NO_WSTRING_HELPER) @@ -101,14 +102,14 @@ SWIGEXPORT void SWIGSTDCALL SWIGRegisterWStringCallback_$module(SWIG_CSharpWStri %fragment("Swig_csharp_UTF16ToWCharPtr", "header") %{ /* For converting from .NET UTF16 (2 byte unicode) strings. wchar_t is 2 bytes on Windows, 4 bytes on Linux. */ -static wchar_t * Swig_csharp_UTF16ToWCharPtr(const wchar_t *str) { +static wchar_t * Swig_csharp_UTF16ToWCharPtr(const unsigned short *str) { if (sizeof(wchar_t) == 2) { return (wchar_t *)str; } else { wchar_t *result = 0; if (str) { - const unsigned short *pBegin((const unsigned short *)(str)); + const unsigned short *pBegin(str); const unsigned short *pEnd(pBegin); wchar_t *ptr = 0; @@ -142,7 +143,7 @@ static void Swig_csharp_UTF16ToWCharPtrFree(wchar_t *str) { } %} -%typemap(ctype, out="void *") wchar_t * "wchar_t *" +%typemap(ctype, out="void *") wchar_t * "unsigned short *" %typemap(imtype, inattributes="[global::System.Runtime.InteropServices.MarshalAs(global::System.Runtime.InteropServices.UnmanagedType.LPWStr)]", outattributes="[return: global::System.Runtime.InteropServices.MarshalAs(global::System.Runtime.InteropServices.UnmanagedType.LPWStr)]" @@ -167,7 +168,7 @@ static void Swig_csharp_UTF16ToWCharPtrFree(wchar_t *str) { %typemap(in, fragment="Swig_csharp_UTF16ToWCharPtr") wchar_t * %{ $1 = Swig_csharp_UTF16ToWCharPtr($input); %} -%typemap(out) wchar_t * %{ $result = $1 ? SWIG_csharp_wstring_callback((wchar_t *)$1) : 0; %} +%typemap(out) wchar_t * %{ $result = $1 ? SWIG_csharp_wstring_callback($1) : 0; %} %typemap(freearg, fragment="Swig_csharp_UTF16ToWCharPtrFree") wchar_t * %{ Swig_csharp_UTF16ToWCharPtrFree($1); %} From 79a9389355f4e42ca9866617bf22e1ccaf5547bb Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Wed, 27 Apr 2022 18:41:24 +0100 Subject: [PATCH 421/662] Add support for throwing wstring exceptions Throw an ApplicationException for std::wstring and wchar_t * strings --- .../test-suite/csharp/li_std_wstring_runme.cs | 18 +++++ Examples/test-suite/li_std_wstring.i | 18 ++++- Lib/csharp/std_wstring.i | 6 +- Lib/csharp/wchar.i | 71 ++++++++++++++++++- 4 files changed, 106 insertions(+), 7 deletions(-) diff --git a/Examples/test-suite/csharp/li_std_wstring_runme.cs b/Examples/test-suite/csharp/li_std_wstring_runme.cs index 059688a75..21c225e5f 100644 --- a/Examples/test-suite/csharp/li_std_wstring_runme.cs +++ b/Examples/test-suite/csharp/li_std_wstring_runme.cs @@ -105,6 +105,24 @@ public class runme check_equal(e.Message, "throwing test_throw"); } + try { + li_std_wstring.test_throw_jp(); + } catch (Exception e) { + check_equal(e.Message, "JP: 日本語"); + } + + try { + li_std_wstring.test_throw_ref_jp(); + } catch (Exception e) { + check_equal(e.Message, "JP: 日本語"); + } + + try { + li_std_wstring.test_throw_wchar_t_ptr(); + } catch (Exception e) { + check_equal(e.Message, "JP: 日本語"); + } + x = "abc\0def"; // Unlike other languages, embedded NULL in std::string not supported // check_equal(li_std_wstring.test_value(x), x); diff --git a/Examples/test-suite/li_std_wstring.i b/Examples/test-suite/li_std_wstring.i index 1f5ddb458..43031679a 100644 --- a/Examples/test-suite/li_std_wstring.i +++ b/Examples/test-suite/li_std_wstring.i @@ -103,9 +103,23 @@ bool test_equal_ru(const std::wstring &s) { return test_equal(RU_WSTRING, s); } -void test_throw() TESTCASE_THROW1(std::wstring){ +void test_throw() TESTCASE_THROW1(std::wstring) { static std::wstring x = L"throwing test_throw"; - + throw x; +} + +void test_throw_wchar_t_ptr() TESTCASE_THROW1(std::wstring) { + static std::wstring x = JP_WSTRING; + throw x; +} + +void test_throw_jp() TESTCASE_THROW1(std::wstring) { + static std::wstring x = JP_WSTRING; + throw x; +} + +void test_throw_ref_jp() TESTCASE_THROW1(const std::wstring&) { + static std::wstring x = JP_WSTRING; throw x; } diff --git a/Lib/csharp/std_wstring.i b/Lib/csharp/std_wstring.i index e8b81bea7..6d2d52722 100644 --- a/Lib/csharp/std_wstring.i +++ b/Lib/csharp/std_wstring.i @@ -81,8 +81,7 @@ class wstring; %typemap(typecheck) wstring = wchar_t *; %typemap(throws, canthrow=1) wstring -%{ std::string message($1.begin(), $1.end()); - SWIG_CSharpSetPendingException(SWIG_CSharpApplicationException, message.c_str()); +%{ SWIG_csharp_ApplicationException_callback($1.c_str(), (int)$1.size()); return $null; %} // const wstring & @@ -136,8 +135,7 @@ class wstring; %typemap(typecheck) const wstring & = wchar_t *; %typemap(throws, canthrow=1) const wstring & -%{ std::string message($1.begin(), $1.end()); - SWIG_CSharpSetPendingException(SWIG_CSharpApplicationException, message.c_str()); +%{ SWIG_csharp_ApplicationException_callback($1.c_str(), (int)$1.size()); return $null; %} } diff --git a/Lib/csharp/wchar.i b/Lib/csharp/wchar.i index c6720eb04..d0f1fe0f6 100644 --- a/Lib/csharp/wchar.i +++ b/Lib/csharp/wchar.i @@ -39,7 +39,7 @@ static void * SWIG_csharp_wstring_callback(const wchar_t *s) { [global::System.Runtime.InteropServices.DllImport("$dllimport", EntryPoint="SWIGRegisterWStringCallback_$module")] public static extern void SWIGRegisterWStringCallback_$module(SWIGWStringDelegate wstringUTF16Delegate, SWIGWStringDelegate wstringUTF32Delegate); - static string CreateWStringFromUTF16([global::System.Runtime.InteropServices.MarshalAs(global::System.Runtime.InteropServices.UnmanagedType.LPWStr)]global::System.IntPtr cString, int length) { + public static string CreateWStringFromUTF16([global::System.Runtime.InteropServices.MarshalAs(global::System.Runtime.InteropServices.UnmanagedType.LPWStr)]global::System.IntPtr cString, int length) { return global::System.Runtime.InteropServices.Marshal.PtrToStringUni(cString, length); } @@ -72,6 +72,71 @@ SWIGEXPORT void SWIGSTDCALL SWIGRegisterWStringCallback_$module(SWIG_CSharpWStri #endif // SWIG_CSHARP_WSTRING_HELPER_ #endif // SWIG_CSHARP_NO_WSTRING_HELPER +#if !defined(SWIG_CSHARP_NO_WSTRING_EXCEPTION_HELPER) +#if !defined(SWIG_CSHARP_WSTRING_EXCEPTION_HELPER_) +#define SWIG_CSHARP_WSTRING_EXCEPTION_HELPER_ + +%insert(runtime) %{ +/* Callback for returning strings to C# without leaking memory */ +typedef void (SWIGSTDCALL* SWIG_CSharpWStringExceptionHelperCallback)(const wchar_t *, int length); +static SWIG_CSharpWStringExceptionHelperCallback SWIG_csharp_ApplicationException_callback = NULL; +%} + +%pragma(csharp) imclasscode=%{ + protected class SWIGWStringExceptionHelper { + + [return: global::System.Runtime.InteropServices.MarshalAs(global::System.Runtime.InteropServices.UnmanagedType.LPWStr)] + public delegate void SWIGWStringExceptionDelegate(global::System.IntPtr message, int length); + static SWIGWStringExceptionDelegate applicationExceptionUTF16Delegate = new SWIGWStringExceptionDelegate(SetPendingApplicationExceptionUTF16); + static SWIGWStringExceptionDelegate applicationExceptionUTF32Delegate = new SWIGWStringExceptionDelegate(SetPendingApplicationExceptionUTF32); + + [global::System.Runtime.InteropServices.DllImport("$dllimport", EntryPoint="SWIGRegisterWStringExceptionCallback_$module")] + public static extern void SWIGRegisterWStringExceptionCallback_$module(SWIGWStringExceptionDelegate applicationExceptionUTF16Delegate, SWIGWStringExceptionDelegate applicationExceptionUTF32Delegate); + + static string CreateWStringFromUTF16([global::System.Runtime.InteropServices.MarshalAs(global::System.Runtime.InteropServices.UnmanagedType.LPWStr)]global::System.IntPtr cString, int length) { + return global::System.Runtime.InteropServices.Marshal.PtrToStringUni(cString, length); + } + + public static string CreateWStringFromUTF32([global::System.Runtime.InteropServices.MarshalAs(global::System.Runtime.InteropServices.UnmanagedType.LPWStr)]global::System.IntPtr cString, int length) { + if (length == 0) + return string.Empty; + + byte[] buffer = new byte[length * 4]; + global::System.Runtime.InteropServices.Marshal.Copy(cString, buffer, 0, buffer.Length); + byte[] utf8buffer = global::System.Text.Encoding.Convert(global::System.Text.Encoding.UTF32, global::System.Text.Encoding.UTF8, buffer); + return global::System.Text.Encoding.Default.GetString(utf8buffer); + } + + static void SetPendingApplicationExceptionUTF16([global::System.Runtime.InteropServices.MarshalAs(global::System.Runtime.InteropServices.UnmanagedType.LPWStr)]global::System.IntPtr cString, int length) { + string message = SWIGWStringHelper.CreateWStringFromUTF16(cString, length); + SWIGPendingException.Set(new global::System.ApplicationException(message, SWIGPendingException.Retrieve())); + } + + static void SetPendingApplicationExceptionUTF32([global::System.Runtime.InteropServices.MarshalAs(global::System.Runtime.InteropServices.UnmanagedType.LPWStr)]global::System.IntPtr cString, int length) { + string message = SWIGWStringHelper.CreateWStringFromUTF32(cString, length); + SWIGPendingException.Set(new global::System.ApplicationException(message, SWIGPendingException.Retrieve())); + } + + static SWIGWStringExceptionHelper() { + SWIGRegisterWStringExceptionCallback_$module(applicationExceptionUTF16Delegate, applicationExceptionUTF32Delegate); + } + } + + static protected SWIGWStringExceptionHelper swigWStringExceptionHelper = new SWIGWStringExceptionHelper(); +%} + +%insert(runtime) %{ +#ifdef __cplusplus +extern "C" +#endif +SWIGEXPORT void SWIGSTDCALL SWIGRegisterWStringExceptionCallback_$module(SWIG_CSharpWStringExceptionHelperCallback callback_utf16, SWIG_CSharpWStringExceptionHelperCallback callback_utf32) { + SWIG_csharp_ApplicationException_callback = sizeof(wchar_t) == 2 ? callback_utf16 : callback_utf32; +} +%} + +#endif // SWIG_CSHARP_WSTRING_EXCEPTION_HELPER_ +#endif // SWIG_CSHARP_NO_WSTRING_EXCEPTION_HELPER + // wchar_t %typemap(ctype) wchar_t "wchar_t" @@ -175,6 +240,10 @@ static void Swig_csharp_UTF16ToWCharPtrFree(wchar_t *str) { %typemap(typecheck) wchar_t * = char *; +%typemap(throws, canthrow=1, fragment="") wchar_t * +%{ SWIG_csharp_ApplicationException_callback($1, (int)wcslen($1)); + return $null; %} + /* Default typemap for handling wchar_t * members (based on char * in swig.swg) */ From fc6269a3cad26acbb62f7eff8b3a218433fc5554 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Mon, 2 May 2022 21:25:58 +0100 Subject: [PATCH 422/662] GHA changes octave-6.4 has disappeared - stop testing it. ruby-2.6 allow to fail (for li_std_set), see issue #2115. --- .github/workflows/ci.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f6fb3ec7a..4a62868c2 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -96,7 +96,6 @@ jobs: - SWIGLANG: octave CPPSTD: c++11 - SWIGLANG: octave - VER: '6.4' CPPSTD: c++11 - SWIGLANG: perl5 - SWIGLANG: php @@ -300,6 +299,9 @@ jobs: GCC: 11 continue-on-error: true os: ubuntu-18.04 # ocaml-4.08 in ubuntu-20.04 not yet working + # Currently broken + - SWIGLANG: ruby + VER: '2.6' # Run all of them, as opposed to aborting when one fails fail-fast: false From 5b7447b20e9cbef3889a7e87d560c3f6a611ada6 Mon Sep 17 00:00:00 2001 From: tartanpaint <35690467+tartanpaint@users.noreply.github.com> Date: Tue, 21 Jan 2020 15:27:25 +0000 Subject: [PATCH 423/662] Fix marshalling of std::wstring parameters in directors std::wstring parameters on SWIG directors were being truncated to a single character due to marshalling inconsistencies. This patch applies the same MarshalAs(UnmanagedType.LPWStr) attribute to director delegate methods and allows std::wstrings to be successfully received in the C# code via director calls. --- Lib/csharp/std_wstring.i | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/Lib/csharp/std_wstring.i b/Lib/csharp/std_wstring.i index 6d2d52722..87c9a9f15 100644 --- a/Lib/csharp/std_wstring.i +++ b/Lib/csharp/std_wstring.i @@ -49,7 +49,9 @@ class wstring; %typemap(ctype, out="void *") wstring "unsigned short *" %typemap(imtype, inattributes="[global::System.Runtime.InteropServices.MarshalAs(global::System.Runtime.InteropServices.UnmanagedType.LPWStr)]", - outattributes="[return: global::System.Runtime.InteropServices.MarshalAs(global::System.Runtime.InteropServices.UnmanagedType.LPWStr)]" + outattributes="[return: global::System.Runtime.InteropServices.MarshalAs(global::System.Runtime.InteropServices.UnmanagedType.LPWStr)]", +         directorinattributes="[global::System.Runtime.InteropServices.MarshalAs(global::System.Runtime.InteropServices.UnmanagedType.LPWStr)]", +         directoroutattributes="[return: global::System.Runtime.InteropServices.MarshalAs(global::System.Runtime.InteropServices.UnmanagedType.LPWStr)]" ) wstring "string" %typemap(cstype) wstring "string" %typemap(csdirectorin) wstring "$iminput" @@ -88,7 +90,9 @@ class wstring; %typemap(ctype, out="void *") const wstring & "unsigned short *" %typemap(imtype, inattributes="[global::System.Runtime.InteropServices.MarshalAs(global::System.Runtime.InteropServices.UnmanagedType.LPWStr)]", - outattributes="[return: global::System.Runtime.InteropServices.MarshalAs(global::System.Runtime.InteropServices.UnmanagedType.LPWStr)]" + outattributes="[return: global::System.Runtime.InteropServices.MarshalAs(global::System.Runtime.InteropServices.UnmanagedType.LPWStr)]", +         directorinattributes="[global::System.Runtime.InteropServices.MarshalAs(global::System.Runtime.InteropServices.UnmanagedType.LPWStr)]", +         directoroutattributes="[return: global::System.Runtime.InteropServices.MarshalAs(global::System.Runtime.InteropServices.UnmanagedType.LPWStr)]" ) const wstring & "string" %typemap(cstype) const wstring & "string" From 3377b63dad9d5f35cc711966a11f427b79a056e7 Mon Sep 17 00:00:00 2001 From: tartanpaint <35690467+tartanpaint@users.noreply.github.com> Date: Wed, 22 Jan 2020 14:41:57 +0000 Subject: [PATCH 424/662] Fix line endings --- Lib/csharp/std_wstring.i | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Lib/csharp/std_wstring.i b/Lib/csharp/std_wstring.i index 87c9a9f15..d45471014 100644 --- a/Lib/csharp/std_wstring.i +++ b/Lib/csharp/std_wstring.i @@ -50,8 +50,8 @@ class wstring; %typemap(imtype, inattributes="[global::System.Runtime.InteropServices.MarshalAs(global::System.Runtime.InteropServices.UnmanagedType.LPWStr)]", outattributes="[return: global::System.Runtime.InteropServices.MarshalAs(global::System.Runtime.InteropServices.UnmanagedType.LPWStr)]", -         directorinattributes="[global::System.Runtime.InteropServices.MarshalAs(global::System.Runtime.InteropServices.UnmanagedType.LPWStr)]", -         directoroutattributes="[return: global::System.Runtime.InteropServices.MarshalAs(global::System.Runtime.InteropServices.UnmanagedType.LPWStr)]" + directorinattributes="[global::System.Runtime.InteropServices.MarshalAs(global::System.Runtime.InteropServices.UnmanagedType.LPWStr)]", + directoroutattributes="[return: global::System.Runtime.InteropServices.MarshalAs(global::System.Runtime.InteropServices.UnmanagedType.LPWStr)]" ) wstring "string" %typemap(cstype) wstring "string" %typemap(csdirectorin) wstring "$iminput" @@ -91,8 +91,8 @@ class wstring; %typemap(imtype, inattributes="[global::System.Runtime.InteropServices.MarshalAs(global::System.Runtime.InteropServices.UnmanagedType.LPWStr)]", outattributes="[return: global::System.Runtime.InteropServices.MarshalAs(global::System.Runtime.InteropServices.UnmanagedType.LPWStr)]", -         directorinattributes="[global::System.Runtime.InteropServices.MarshalAs(global::System.Runtime.InteropServices.UnmanagedType.LPWStr)]", -         directoroutattributes="[return: global::System.Runtime.InteropServices.MarshalAs(global::System.Runtime.InteropServices.UnmanagedType.LPWStr)]" + directorinattributes="[global::System.Runtime.InteropServices.MarshalAs(global::System.Runtime.InteropServices.UnmanagedType.LPWStr)]", + directoroutattributes="[return: global::System.Runtime.InteropServices.MarshalAs(global::System.Runtime.InteropServices.UnmanagedType.LPWStr)]" ) const wstring & "string" %typemap(cstype) const wstring & "string" From 9fd59650cf57c963311c18a779aacd949553520f Mon Sep 17 00:00:00 2001 From: tartanpaint <35690467+tartanpaint@users.noreply.github.com> Date: Wed, 29 Jan 2020 09:00:59 +0000 Subject: [PATCH 425/662] Apply C# test updates for directors with std::wstring supplied by wsfulton --- Examples/test-suite/csharp/Makefile.in | 1 + .../csharp/director_wstring_runme.cs | 41 +++++++++++++++++++ Examples/test-suite/director_wstring.i | 6 +++ 3 files changed, 48 insertions(+) create mode 100644 Examples/test-suite/csharp/director_wstring_runme.cs diff --git a/Examples/test-suite/csharp/Makefile.in b/Examples/test-suite/csharp/Makefile.in index 74010c284..600c5953d 100644 --- a/Examples/test-suite/csharp/Makefile.in +++ b/Examples/test-suite/csharp/Makefile.in @@ -25,6 +25,7 @@ CPP_TEST_CASES = \ csharp_namespace_system_collision \ csharp_prepost \ csharp_typemaps \ + director_wstring \ enum_thorough_simple \ enum_thorough_typesafe \ exception_partial_info \ diff --git a/Examples/test-suite/csharp/director_wstring_runme.cs b/Examples/test-suite/csharp/director_wstring_runme.cs new file mode 100644 index 000000000..6f97dcb50 --- /dev/null +++ b/Examples/test-suite/csharp/director_wstring_runme.cs @@ -0,0 +1,41 @@ +using System; +using director_wstringNamespace; + +public class runme +{ + static void Main() + { + runme r = new runme(); + r.run(); + } + + void run() + { + director_wstring_B b = new director_wstring_B("hello"); + + b.get(0); + if (b.get_first() != "hello world!") + throw new ApplicationException("Incorrect get_first:" + b.get_first()); + + b.call_process_func(); + + if (b.smem != "hello") + throw new ApplicationException("Incorrect smem:" + b.smem); + } +} + +class director_wstring_B : A +{ + public String smem; + public director_wstring_B(String first) : base(first) + { + } + public override String get_first() + { + return base.get_first() + " world!"; + } + public override void process_text(String s) + { + this.smem = s; + } +} \ No newline at end of file diff --git a/Examples/test-suite/director_wstring.i b/Examples/test-suite/director_wstring.i index 17761ea59..73900ccf6 100644 --- a/Examples/test-suite/director_wstring.i +++ b/Examples/test-suite/director_wstring.i @@ -40,9 +40,15 @@ struct A std::vector m_strings; +#if !defined(SWIGCSHARP) virtual void process_text(const wchar_t *text) { } +#else + virtual void process_text(const std::wstring& text) + { + } +#endif virtual std::wstring multiple_params_val(const std::wstring& p1, const std::wstring& p2, std::wstring p3, std::wstring p4) const { return get_first(); } From 751d443046ac5954ea64a169e6444363b65a8e80 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Wed, 4 May 2022 09:28:21 +0100 Subject: [PATCH 426/662] C# std::wstring director support Updates for #1706 --- .../csharp/director_wstring_runme.cs | 21 +++++++++++++++++-- Examples/test-suite/director_wstring.i | 13 ++++++------ Lib/csharp/std_wstring.i | 6 +++--- 3 files changed, 29 insertions(+), 11 deletions(-) diff --git a/Examples/test-suite/csharp/director_wstring_runme.cs b/Examples/test-suite/csharp/director_wstring_runme.cs index 6f97dcb50..fcb6e7afa 100644 --- a/Examples/test-suite/csharp/director_wstring_runme.cs +++ b/Examples/test-suite/csharp/director_wstring_runme.cs @@ -17,10 +17,19 @@ public class runme if (b.get_first() != "hello world!") throw new ApplicationException("Incorrect get_first:" + b.get_first()); + /* b.call_process_func(); - if (b.smem != "hello") throw new ApplicationException("Incorrect smem:" + b.smem); + */ + + b.call_process_wstring_func(); + if (b.smem != "hello (wstring)") + throw new ApplicationException("Incorrect smem:" + b.smem); + + b.call_process_wstring_ref_func(); + if (b.smem != "hello (wstring ref)") + throw new ApplicationException("Incorrect smem:" + b.smem); } } @@ -38,4 +47,12 @@ class director_wstring_B : A { this.smem = s; } -} \ No newline at end of file + public override void process_wstring_text(String s) + { + this.smem = s + " (wstring)"; + } + public override void process_wstring_ref_text(String s) + { + this.smem = s + " (wstring ref)"; + } +} diff --git a/Examples/test-suite/director_wstring.i b/Examples/test-suite/director_wstring.i index 73900ccf6..10dd032d0 100644 --- a/Examples/test-suite/director_wstring.i +++ b/Examples/test-suite/director_wstring.i @@ -41,13 +41,12 @@ struct A #if !defined(SWIGCSHARP) - virtual void process_text(const wchar_t *text) - { - } + virtual void process_text(const wchar_t *text) {} #else - virtual void process_text(const std::wstring& text) - { - } +// temp until wchar_t* fixed + virtual void process_text(std::wstring text) {} + virtual void process_wstring_text(std::wstring text) {} + virtual void process_wstring_ref_text(const std::wstring& text) {} #endif virtual std::wstring multiple_params_val(const std::wstring& p1, const std::wstring& p2, std::wstring p3, std::wstring p4) const @@ -57,6 +56,8 @@ struct A { return get_first(); } void call_process_func() { process_text(L"hello"); } + void call_process_wstring_func() { process_wstring_text(L"hello"); } + void call_process_wstring_ref_func() { process_wstring_ref_text(L"hello"); } }; %} diff --git a/Lib/csharp/std_wstring.i b/Lib/csharp/std_wstring.i index d45471014..1d10ca808 100644 --- a/Lib/csharp/std_wstring.i +++ b/Lib/csharp/std_wstring.i @@ -70,7 +70,7 @@ class wstring; SWIG_CSharpSetPendingExceptionArgument(SWIG_CSharpArgumentNullException, "null wstring", 0); return $null; } - $result.assign($input); %} + $result = Swig_csharp_UTF16ToWString($input); %} %typemap(directorin) wstring %{ $input = SWIG_csharp_wstring_with_length_callback($1.c_str(), (int)$1.size()); %} @@ -121,10 +121,10 @@ class wstring; } /* possible thread/reentrant code problem */ static std::wstring $1_str; - $1_str = $input; + $1_str = Swig_csharp_UTF16ToWString($input); $result = &$1_str; %} -%typemap(directorin) const wstring & %{ $input = SWIG_csharp_wstring_with_length_callback($1.c_str(), (int)$1->size()); %} +%typemap(directorin) const wstring & %{ $input = SWIG_csharp_wstring_with_length_callback($1.c_str(), (int)$1.size()); %} %typemap(csvarin, excode=SWIGEXCODE2) const wstring & %{ set { From bb39235c9ce53b8587a929c7e0f98beda2891be3 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Wed, 4 May 2022 19:33:47 +0100 Subject: [PATCH 427/662] Add C# wchar_t * director typemaps More Python std::wstring directors Python testing --- CHANGES.current | 3 +++ .../test-suite/csharp/director_wstring_runme.cs | 2 -- Examples/test-suite/director_wstring.i | 6 +----- .../test-suite/python/director_wstring_runme.py | 16 ++++++++++++++++ Lib/csharp/wchar.i | 11 ++++++++++- 5 files changed, 30 insertions(+), 8 deletions(-) diff --git a/CHANGES.current b/CHANGES.current index cfa0af2db..f14dc24ad 100644 --- a/CHANGES.current +++ b/CHANGES.current @@ -7,6 +7,9 @@ the issue number to the end of the URL: https://github.com/swig/swig/issues/ Version 4.1.0 (in progress) =========================== +2022-05-04: wsfulton + [C#] Add C# wchar_t * director typemaps + 2022-04-20: cminyard Fix an issue where newlines were not properly generated for godirectorin typemaps. If you have a virtual function diff --git a/Examples/test-suite/csharp/director_wstring_runme.cs b/Examples/test-suite/csharp/director_wstring_runme.cs index fcb6e7afa..7258e7f94 100644 --- a/Examples/test-suite/csharp/director_wstring_runme.cs +++ b/Examples/test-suite/csharp/director_wstring_runme.cs @@ -17,11 +17,9 @@ public class runme if (b.get_first() != "hello world!") throw new ApplicationException("Incorrect get_first:" + b.get_first()); - /* b.call_process_func(); if (b.smem != "hello") throw new ApplicationException("Incorrect smem:" + b.smem); - */ b.call_process_wstring_func(); if (b.smem != "hello (wstring)") diff --git a/Examples/test-suite/director_wstring.i b/Examples/test-suite/director_wstring.i index 10dd032d0..02df9d64c 100644 --- a/Examples/test-suite/director_wstring.i +++ b/Examples/test-suite/director_wstring.i @@ -39,15 +39,11 @@ struct A std::vector m_strings; + virtual const wchar_t * wchar_out() { return L"ciao"; } -#if !defined(SWIGCSHARP) virtual void process_text(const wchar_t *text) {} -#else -// temp until wchar_t* fixed - virtual void process_text(std::wstring text) {} virtual void process_wstring_text(std::wstring text) {} virtual void process_wstring_ref_text(const std::wstring& text) {} -#endif virtual std::wstring multiple_params_val(const std::wstring& p1, const std::wstring& p2, std::wstring p3, std::wstring p4) const { return get_first(); } diff --git a/Examples/test-suite/python/director_wstring_runme.py b/Examples/test-suite/python/director_wstring_runme.py index 5facc1f1d..659cf1854 100644 --- a/Examples/test-suite/python/director_wstring_runme.py +++ b/Examples/test-suite/python/director_wstring_runme.py @@ -12,6 +12,12 @@ class B(A): def process_text(self, s): self.smem = s + def process_wstring_text(self, s): + self.smem = s + " (wstring)" + + def process_wstring_ref_text(self, s): + self.smem = s + " (wstring ref)" + b = B("hello") @@ -24,3 +30,13 @@ b.call_process_func() if b.smem != "hello": raise RuntimeError("smem: {}".format(smem)) + +b.call_process_wstring_func() + +if b.smem != "hello (wstring)": + raise RuntimeError("smem: {}".format(smem)) + +b.call_process_wstring_ref_func() + +if b.smem != "hello (wstring ref)": + raise RuntimeError("smem: {}".format(smem)) diff --git a/Lib/csharp/wchar.i b/Lib/csharp/wchar.i index d0f1fe0f6..2ada4df75 100644 --- a/Lib/csharp/wchar.i +++ b/Lib/csharp/wchar.i @@ -211,9 +211,13 @@ static void Swig_csharp_UTF16ToWCharPtrFree(wchar_t *str) { %typemap(ctype, out="void *") wchar_t * "unsigned short *" %typemap(imtype, inattributes="[global::System.Runtime.InteropServices.MarshalAs(global::System.Runtime.InteropServices.UnmanagedType.LPWStr)]", - outattributes="[return: global::System.Runtime.InteropServices.MarshalAs(global::System.Runtime.InteropServices.UnmanagedType.LPWStr)]" + outattributes="[return: global::System.Runtime.InteropServices.MarshalAs(global::System.Runtime.InteropServices.UnmanagedType.LPWStr)]", + directorinattributes="[global::System.Runtime.InteropServices.MarshalAs(global::System.Runtime.InteropServices.UnmanagedType.LPWStr)]", + directoroutattributes="[return: global::System.Runtime.InteropServices.MarshalAs(global::System.Runtime.InteropServices.UnmanagedType.LPWStr)]" ) wchar_t * "string" %typemap(cstype) wchar_t * "string" +%typemap(csdirectorin) wchar_t * "$iminput" +%typemap(csdirectorout) wchar_t * "$cscall" %typemap(csin) wchar_t * "$csinput" %typemap(csout, excode=SWIGEXCODE) wchar_t * { @@ -238,6 +242,11 @@ static void Swig_csharp_UTF16ToWCharPtrFree(wchar_t *str) { %typemap(freearg, fragment="Swig_csharp_UTF16ToWCharPtrFree") wchar_t * %{ Swig_csharp_UTF16ToWCharPtrFree($1); %} +%typemap(directorout, warning=SWIGWARN_TYPEMAP_DIRECTOROUT_PTR_MSG) wchar_t * +%{ $result = Swig_csharp_UTF16ToWCharPtr($input); %} + +%typemap(directorin) wchar_t * %{ $input = SWIG_csharp_wstring_with_length_callback($1, (int)wcslen($1)); %} + %typemap(typecheck) wchar_t * = char *; %typemap(throws, canthrow=1, fragment="") wchar_t * From fe2cdb1d90023a899161233ca83a5d58fd6d6dc3 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Wed, 4 May 2022 21:40:15 +0100 Subject: [PATCH 428/662] Add python 3.2 as allowed to fail Seems broken atm --- .github/workflows/ci.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4a62868c2..5cf11718e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -302,6 +302,11 @@ jobs: # Currently broken - SWIGLANG: ruby VER: '2.6' + continue-on-error: true + - SWIGLANG: python + VER: '3.2' + os: ubuntu-18.04 # Python < 3.5 not available for 20.04. + continue-on-error: true # Run all of them, as opposed to aborting when one fails fail-fast: false From a3b49ef75ef1bbb9881ab593d34c00f174dcaeda Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Thu, 5 May 2022 08:42:02 +0100 Subject: [PATCH 429/662] GHA: continue-on-error corrections --- .github/workflows/ci.yml | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5cf11718e..a03ca7459 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -116,6 +116,7 @@ jobs: - SWIGLANG: python VER: '3.2' os: ubuntu-18.04 # Python < 3.5 not available for 20.04. + continue-on-error: true # broken packages problem - SWIGLANG: python VER: '3.3' os: ubuntu-18.04 # Python < 3.5 not available for 20.04. @@ -166,6 +167,7 @@ jobs: VER: '2.5' - SWIGLANG: ruby VER: '2.6' + continue-on-error: true # Sometimes fails, see https://github.com/swig/swig/issues/2115 - SWIGLANG: ruby VER: '2.7' - SWIGLANG: ruby @@ -299,14 +301,6 @@ jobs: GCC: 11 continue-on-error: true os: ubuntu-18.04 # ocaml-4.08 in ubuntu-20.04 not yet working - # Currently broken - - SWIGLANG: ruby - VER: '2.6' - continue-on-error: true - - SWIGLANG: python - VER: '3.2' - os: ubuntu-18.04 # Python < 3.5 not available for 20.04. - continue-on-error: true # Run all of them, as opposed to aborting when one fails fail-fast: false From f029beffe8e86b1b6e8f27b8dcc0514b99fa8bac Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Fri, 6 May 2022 08:06:26 +0100 Subject: [PATCH 430/662] Ruby li_std_set test failure workaround Prevent GC from collecting "hello" string in testcase as workaround to prevent GC occasionally causing segfault. Issue #2115 --- .github/workflows/ci.yml | 1 - Examples/test-suite/ruby/li_std_set_runme.rb | 8 ++++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a03ca7459..60791155c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -167,7 +167,6 @@ jobs: VER: '2.5' - SWIGLANG: ruby VER: '2.6' - continue-on-error: true # Sometimes fails, see https://github.com/swig/swig/issues/2115 - SWIGLANG: ruby VER: '2.7' - SWIGLANG: ruby diff --git a/Examples/test-suite/ruby/li_std_set_runme.rb b/Examples/test-suite/ruby/li_std_set_runme.rb index efc163bee..455a1706e 100644 --- a/Examples/test-suite/ruby/li_std_set_runme.rb +++ b/Examples/test-suite/ruby/li_std_set_runme.rb @@ -56,11 +56,15 @@ m.value == 'c' s = LanguageSet.new s.insert([1,2]) s.insert(1) -s.insert("hello") +# There is a reference count issue that needs fixing, see https://github.com/swig/swig/issues/2115 +# Workaround is to create hello variable containing a string and use it instead of just "hello" +hello = "hello" +s.insert(hello) #s.to_a == [1,[1,2],'hello'] # sort order: s.sort {|a,b| a.hash <=> b.hash} # Test above is flawed as LanguageSet sorts by each element's hash, so the order will change from one invocation to the next. Sort a conversion to array instead. +GC.start sa = s.to_a.sort { |x, y| x.to_s <=> y.to_s } -sa == [1,[1,2],'hello'] +sa == [1,[1,2],hello] EOF From f3ee3f2b126999bfc290733cbde84ab3d92e4e7f Mon Sep 17 00:00:00 2001 From: Konrad Eisele Date: Mon, 26 Mar 2012 11:36:00 +0000 Subject: [PATCH 431/662] Add argcargv.i to Lua Found in https://stackoverflow.com/questions/9860362/swig-lua-call-mint-argv-char-argc --- Lib/lua/argcargv.i | 58 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 Lib/lua/argcargv.i diff --git a/Lib/lua/argcargv.i b/Lib/lua/argcargv.i new file mode 100644 index 000000000..670ce4a80 --- /dev/null +++ b/Lib/lua/argcargv.i @@ -0,0 +1,58 @@ +/* ------------------------------------------------------------ + * --- Argc & Argv --- + * ------------------------------------------------------------ + * + * Use it as follow: + * + * %apply (int ARGC, char **ARGV) { (size_t argc, const char **argv) } + * extern int mainApp(size_t argc, const char **argv); + * + * then in the lua: + * + * args = { "arg0", "arg1" } + * mainApp(args); + * + * ------------------------------------------------------------ */ + +%{ +SWIGINTERN int SWIG_argv_size(lua_State* L, int index) { + int n=0; + while(1){ + lua_rawgeti(L,index,n+1); + if (lua_isnil(L,-1)) + break; + ++n; + lua_pop(L,1); + } + lua_pop(L,1); + return n; +} +%} + +%typemap(in) (int ARGC, char **ARGV) { + if (lua_istable(L,$input)) { + int i, size = SWIG_argv_size(L,$input); + $1 = ($1_ltype) size; + $2 = (char **) malloc((size+1)*sizeof(char *)); + for (i = 0; i < size; i++) { + lua_rawgeti(L,$input,i+1); + if (lua_isnil(L,-1)) + break; + $2[i] = (char *)lua_tostring(L, -1); + lua_pop(L,1); + } + $2[i]=NULL; + } else { + $1 = 0; $2 = 0; + lua_pushstring(L,"Expecting argv array"); + lua_error(L); + } +} + +%typemap(typecheck, precedence=SWIG_TYPECHECK_STRING_ARRAY) (int ARGC, char **ARGV) { + $1 = lua_istable(L,$input); +} + +%typemap(freearg) (int ARGC, char **ARGV) { + free((char *) $2); +} From 72f7b829353cd2cd2bba2116cf6d961972d8d58a Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Fri, 6 May 2022 18:44:02 +0100 Subject: [PATCH 432/662] Correct warning message for wchar_t * typemaps Use separate warning for char * and wchar_t * typemaps SWIGWARN_TYPEMAP_CHARLEAK_MSG and SWIGWARN_TYPEMAP_WCHARLEAK_MSG --- Lib/javascript/jsc/javascriptstrings.swg | 2 ++ Lib/typemaps/string.swg | 1 + Lib/typemaps/strings.swg | 13 ++++++++++--- Lib/typemaps/wstring.swg | 1 + 4 files changed, 14 insertions(+), 3 deletions(-) diff --git a/Lib/javascript/jsc/javascriptstrings.swg b/Lib/javascript/jsc/javascriptstrings.swg index 55c8e4b98..5c8081a82 100644 --- a/Lib/javascript/jsc/javascriptstrings.swg +++ b/Lib/javascript/jsc/javascriptstrings.swg @@ -75,6 +75,7 @@ SWIG_JSC_FromCharPtrAndSize(JSContextRef context, const char* carray, size_t siz } %define %_typemap2_string(StringCode, CharCode, + WarningLeakMsg, Char, CharName, SWIG_AsCharPtrAndSize, SWIG_FromCharPtrAndSize, @@ -166,6 +167,7 @@ SWIG_AsVal_dec(Char)(SWIG_Object obj, Char *val) %_typemap_string(StringCode, Char, + WarningLeakMsg, SWIG_AsCharPtrAndSize, SWIG_FromCharPtrAndSize, SWIG_CharPtrLen, diff --git a/Lib/typemaps/string.swg b/Lib/typemaps/string.swg index 4b7072365..72f4aa5b5 100644 --- a/Lib/typemaps/string.swg +++ b/Lib/typemaps/string.swg @@ -30,6 +30,7 @@ SWIG_strnlen(const char* s, size_t maxlen) %include %typemaps_string(%checkcode(STRING), %checkcode(CHAR), + SWIGWARN_TYPEMAP_CHARLEAK_MSG, char, Char, SWIG_AsCharPtrAndSize, SWIG_FromCharPtrAndSize, strlen, SWIG_strnlen, "", CHAR_MIN, CHAR_MAX) diff --git a/Lib/typemaps/strings.swg b/Lib/typemaps/strings.swg index 87e97dd74..e8ed401b0 100644 --- a/Lib/typemaps/strings.swg +++ b/Lib/typemaps/strings.swg @@ -19,6 +19,7 @@ %define %_typemap_string(StringCode, Char, + WarningLeakMsg, SWIG_AsCharPtrAndSize, SWIG_FromCharPtrAndSize, SWIG_CharPtrLen, @@ -86,7 +87,7 @@ } } -%typemap(varin,fragment=#SWIG_AsCharPtrAndSize,warning=SWIGWARN_TYPEMAP_CHARLEAK_MSG) const Char * { +%typemap(varin,fragment=#SWIG_AsCharPtrAndSize,warning=WarningLeakMsg) const Char * { Char *cptr = 0; size_t csize = 0; int alloc = SWIG_NEWOBJ; int res = SWIG_AsCharPtrAndSize($input, &cptr, &csize, &alloc); if (!SWIG_IsOK(res)) { @@ -117,7 +118,7 @@ } } -%typemap(memberin,noblock=1,warning=SWIGWARN_TYPEMAP_CHARLEAK_MSG) const Char * { +%typemap(memberin,noblock=1,warning=WarningLeakMsg) const Char * { if ($input) { size_t size = SWIG_CharPtrLen(%reinterpret_cast(%reinterpret_cast($input, const Char *), const Char *)) + 1; $1 = ($1_type)SWIG_NewCopyCharArray($input, size, Char); @@ -138,7 +139,7 @@ } } -%typemap(globalin,noblock=1,warning=SWIGWARN_TYPEMAP_CHARLEAK_MSG) const Char * { +%typemap(globalin,noblock=1,warning=WarningLeakMsg) const Char * { if ($input) { size_t size = SWIG_CharPtrLen($input) + 1; $1 = ($1_type)SWIG_NewCopyCharArray($input, size, Char); @@ -501,6 +502,7 @@ #ifndef %_typemap2_string %define %_typemap2_string(StringCode, CharCode, + WarningLeakMsg, Char, CharName, SWIG_AsCharPtrAndSize, SWIG_FromCharPtrAndSize, @@ -591,6 +593,7 @@ SWIG_AsVal_dec(Char)(SWIG_Object obj, Char *val) %_typemap_string(StringCode, Char, + WarningLeakMsg, SWIG_AsCharPtrAndSize, SWIG_FromCharPtrAndSize, SWIG_CharPtrLen, @@ -609,6 +612,7 @@ SWIG_AsVal_dec(Char)(SWIG_Object obj, Char *val) * ------------------------------------------------------------ */ %define %typemaps_string(StringCode, CharCode, + WarningLeakMsg, Char, CharName, SWIG_AsCharPtrAndSize, SWIG_FromCharPtrAndSize, @@ -616,6 +620,7 @@ SWIG_AsVal_dec(Char)(SWIG_Object obj, Char *val) SWIG_CharBufLen, FragLimits, CHAR_MIN, CHAR_MAX) %_typemap2_string(StringCode, CharCode, + WarningLeakMsg, Char, CharName, SWIG_AsCharPtrAndSize, SWIG_FromCharPtrAndSize, @@ -631,6 +636,7 @@ SWIG_AsVal_dec(Char)(SWIG_Object obj, Char *val) * ------------------------------------------------------------ */ %define %typemaps_string_alloc(StringCode, CharCode, + WarningLeakMsg, Char, CharName, SWIG_AsCharPtrAndSize, SWIG_FromCharPtrAndSize, @@ -640,6 +646,7 @@ SWIG_AsVal_dec(Char)(SWIG_Object obj, Char *val) SWIG_DeleteCharArray, FragLimits, CHAR_MIN, CHAR_MAX) %_typemap2_string(StringCode, CharCode, + WarningLeakMsg, Char, CharName, SWIG_AsCharPtrAndSize, SWIG_FromCharPtrAndSize, diff --git a/Lib/typemaps/wstring.swg b/Lib/typemaps/wstring.swg index cd409d1ce..d99c0bb38 100644 --- a/Lib/typemaps/wstring.swg +++ b/Lib/typemaps/wstring.swg @@ -31,6 +31,7 @@ SWIG_wcsnlen(const wchar_t* s, size_t maxlen) %include %typemaps_string(%checkcode(UNISTRING), %checkcode(UNICHAR), + SWIGWARN_TYPEMAP_WCHARLEAK_MSG, wchar_t, WChar, SWIG_AsWCharPtrAndSize, SWIG_FromWCharPtrAndSize, wcslen, SWIG_wcsnlen, "", WCHAR_MIN, WCHAR_MAX) From 464d548d7173d964b028941400b7e6a740fb7f94 Mon Sep 17 00:00:00 2001 From: Erez Geva Date: Fri, 6 May 2022 20:36:57 +0200 Subject: [PATCH 433/662] Add argcargv.i to more languages: Perl 5, Tcl, PHP Signed-off-by: Erez Geva --- Lib/perl5/argcargv.i | 31 +++++++++++++++++++++++++++++++ Lib/php/argcargv.i | 40 ++++++++++++++++++++++++++++++++++++++++ Lib/tcl/argcargv.i | 28 ++++++++++++++++++++++++++++ 3 files changed, 99 insertions(+) create mode 100644 Lib/perl5/argcargv.i create mode 100644 Lib/php/argcargv.i create mode 100644 Lib/tcl/argcargv.i diff --git a/Lib/perl5/argcargv.i b/Lib/perl5/argcargv.i new file mode 100644 index 000000000..de7b626e0 --- /dev/null +++ b/Lib/perl5/argcargv.i @@ -0,0 +1,31 @@ +/* ------------------------------------------------------------ + * --- Argc & Argv --- + * ------------------------------------------------------------ */ + +%typemap(default) (int ARGC, char **ARGV) { + $1 = 0; $2 = NULL; +} + +%typemap(in) (int ARGC, char **ARGV) { + int i; + I32 len; + AV *av = (AV *)SvRV($input); + if (SvTYPE(av) != SVt_PVAV) { + SWIG_croak("in method '$symname', Expecting reference to argv array"); + goto fail; + } + len = av_len(av) + 1; + $1 = ($1_ltype) len; + $2 = (char **) malloc((len+1)*sizeof(char *)); + for (i = 0; i < len; i++) { + SV **tv = av_fetch(av, i, 0); + $2[i] = SvPV_nolen(*tv); + } + $2[i] = NULL; +} + +%typemap(freearg) (int ARGC, char **ARGV) { + if ($2 != NULL) { + free((void *)$2); + } +} diff --git a/Lib/php/argcargv.i b/Lib/php/argcargv.i new file mode 100644 index 000000000..14b0cf2c9 --- /dev/null +++ b/Lib/php/argcargv.i @@ -0,0 +1,40 @@ +/* ------------------------------------------------------------ + * --- Argc & Argv --- + * ------------------------------------------------------------ */ + +%typemap(default) (int ARGC, char **ARGV) { + $1 = 0; $2 = NULL; +} + +%typemap(in) (int ARGC, char **ARGV) { + int len, i; + zval *val; + zend_array *ar; + if (Z_TYPE($input) != IS_ARRAY) { + SWIG_PHP_Error(E_ERROR, "Type error in '$symname'. Expected array"); + goto fail; + } + ar = Z_ARR($input); + len = zend_array_count(ar); + $1 = ($1_ltype) len; + $2 = (char **) malloc((len+1)*sizeof(char *)); + i = 0; + ZEND_HASH_FOREACH_VAL(ar, val) { + if (Z_TYPE(*val) != IS_STRING) { + SWIG_PHP_Error(E_ERROR, "Array must use strings only, in '$symname'."); + goto fail; + } + if (i == len) { + SWIG_PHP_Error(E_ERROR, "Array is bigger than zend report in '$symname'."); + goto fail; + } + $2[i++] = Z_STRVAL(*val); + } ZEND_HASH_FOREACH_END(); + $2[i] = NULL; +} + +%typemap(freearg) (int ARGC, char **ARGV) { + if ($2 != NULL) { + free((void *)$2); + } +} diff --git a/Lib/tcl/argcargv.i b/Lib/tcl/argcargv.i new file mode 100644 index 000000000..e43f2e657 --- /dev/null +++ b/Lib/tcl/argcargv.i @@ -0,0 +1,28 @@ +/* ------------------------------------------------------------ + * --- Argc & Argv --- + * ------------------------------------------------------------ */ + +%typemap(default) (int ARGC, char **ARGV) { + $1 = 0; $2 = NULL; +} + +%typemap(in) (int ARGC, char **ARGV) { + int i, nitems; + Tcl_Obj **listobjv; + if (Tcl_ListObjGetElements(interp, $input, &nitems, &listobjv) == TCL_ERROR) { + SWIG_exception_fail(SWIG_ValueError, "in method '$symname', Expecting list of argv"); + goto fail; + } + $1 = ($1_ltype) nitems; + $2 = (char **) malloc((nitems+1)*sizeof(char *)); + for (i = 0; i < nitems; i++) { + $2[i] = Tcl_GetStringFromObj(listobjv[i], NULL); + } + $2[i] = NULL; +} + +%typemap(freearg) (int ARGC, char **ARGV) { + if ($2 != NULL) { + free((void *)$2); + } +} From 72bb68d556e306b2faa54db7769f518e039f34f4 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Sat, 7 May 2022 06:22:25 +0100 Subject: [PATCH 434/662] Visual C++ warning fix in Python < 3.2 builtin wrappers Fixes: warning C4311: 'type cast': pointer truncation from 'void *' to 'long' warning C4302: 'type cast': truncation from 'void *' to 'long' --- Lib/python/builtin.swg | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Lib/python/builtin.swg b/Lib/python/builtin.swg index 9dccd7e20..f31fccf1e 100644 --- a/Lib/python/builtin.swg +++ b/Lib/python/builtin.swg @@ -6,7 +6,11 @@ SWIGINTERN Py_hash_t SwigPyObject_hash(PyObject *obj) { SwigPyObject *sobj = (SwigPyObject *)obj; void *ptr = sobj->ptr; +#if PY_VERSION_HEX < 0x03020000 + return (Py_hash_t)(Py_ssize_t)ptr; +#else return (Py_hash_t)ptr; +#endif } SWIGINTERN Py_hash_t From fd846be18bdaa7dda8f24e01aa24f73568a23a23 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Sat, 7 May 2022 07:09:44 +0100 Subject: [PATCH 435/662] Remove some usage of strdup To fix visual c++ warning: warning C4996: 'strdup': The POSIX name for this item is deprecated. --- Doc/Manual/Varargs.html | 8 ++++++-- Examples/python/multimap/example.i | 8 +++++--- Examples/test-suite/python_varargs_typemap.i | 14 +++++++++----- 3 files changed, 20 insertions(+), 10 deletions(-) diff --git a/Doc/Manual/Varargs.html b/Doc/Manual/Varargs.html index 620f2e5a0..80e391e49 100644 --- a/Doc/Manual/Varargs.html +++ b/Doc/Manual/Varargs.html @@ -512,7 +512,7 @@ like this:
     %typemap(in) (...)(char *vargs[10]) {
       int i;
    -  int argc;
    +  Py_ssize_t argc;
       for (i = 0; i < 10; i++) vargs[i] = 0;
       argc = PyTuple_Size(varargs);
       if (argc > 10) {
    @@ -523,6 +523,7 @@ like this:
         PyObject *pyobj = PyTuple_GetItem(varargs, i);
         char *str = 0;
     %#if PY_VERSION_HEX>=0x03000000
    +    const char *strtmp = 0;
         PyObject *pystr;
         if (!PyUnicode_Check(pyobj)) {
           PyErr_SetString(PyExc_ValueError, "Expected a string");
    @@ -532,7 +533,10 @@ like this:
         if (!pystr) {
           SWIG_fail;
         }
    -    str = strdup(PyBytes_AsString(pystr));
    +    strtmp = PyBytes_AsString(pystr);
    +    str = (char *)malloc(strlen(strtmp) + 1);
    +    if (str)
    +      strcpy(str, strtmp);
         Py_DECREF(pystr);
     %#else  
         if (!PyString_Check(pyobj)) {
    diff --git a/Examples/python/multimap/example.i b/Examples/python/multimap/example.i
    index 3ff5d52c0..7087d426b 100644
    --- a/Examples/python/multimap/example.i
    +++ b/Examples/python/multimap/example.i
    @@ -39,12 +39,14 @@ extern int    gcd(int x, int y);
     %#if PY_VERSION_HEX >= 0x03000000
         {
           PyObject *utf8str = PyUnicode_AsUTF8String(s);
    -      const char *cstr;
    +      const char *strtmp = 0;
           if (!utf8str) {
             SWIG_fail;
           }
    -      cstr = PyBytes_AsString(utf8str);
    -      $2[i] = strdup(cstr);
    +      strtmp = PyBytes_AsString(utf8str);
    +      $2[i] = (char *)malloc(strlen(strtmp) + 1);
    +      if ($2[i])
    +        strcpy($2[i], strtmp);
           Py_DECREF(utf8str);
         }
     %#else
    diff --git a/Examples/test-suite/python_varargs_typemap.i b/Examples/test-suite/python_varargs_typemap.i
    index d809bf1fa..65ce72f43 100644
    --- a/Examples/test-suite/python_varargs_typemap.i
    +++ b/Examples/test-suite/python_varargs_typemap.i
    @@ -17,21 +17,25 @@
         PyObject *pyobj = PyTuple_GetItem(varargs, i);
         char *str = 0;
     %#if PY_VERSION_HEX>=0x03000000
    +    const char *strtmp = 0;
         PyObject *pystr;
         if (!PyUnicode_Check(pyobj)) {
    -       PyErr_SetString(PyExc_ValueError, "Expected a string");
    -       SWIG_fail;
    +      PyErr_SetString(PyExc_ValueError, "Expected a string");
    +      SWIG_fail;
         }
         pystr = PyUnicode_AsUTF8String(pyobj);
         if (!pystr) {
           SWIG_fail;
         }
    -    str = strdup(PyBytes_AsString(pystr));
    +    strtmp = PyBytes_AsString(pystr);
    +    str = (char *)malloc(strlen(strtmp) + 1);
    +    if (str)
    +      strcpy(str, strtmp);
         Py_DECREF(pystr);
     %#else  
         if (!PyString_Check(pyobj)) {
    -       PyErr_SetString(PyExc_ValueError, "Expected a string");
    -       SWIG_fail;
    +      PyErr_SetString(PyExc_ValueError, "Expected a string");
    +      SWIG_fail;
         }
         str = PyString_AsString(pyobj);
     %#endif
    
    From a598abe23d9c52686992a60e3608395e3c1689fc Mon Sep 17 00:00:00 2001
    From: William S Fulton 
    Date: Sat, 7 May 2022 08:16:48 +0100
    Subject: [PATCH 436/662] Java wstring throws typemap improvements
    
    Unicode still not working, but works now for ASCII charset.
    ---
     Lib/java/std_wstring.i | 18 ++++++++++++------
     1 file changed, 12 insertions(+), 6 deletions(-)
    
    diff --git a/Lib/java/std_wstring.i b/Lib/java/std_wstring.i
    index 3e462256a..efa9e63b8 100644
    --- a/Lib/java/std_wstring.i
    +++ b/Lib/java/std_wstring.i
    @@ -88,9 +88,12 @@ class wstring;
     //%typemap(typecheck) wstring = wchar_t *;
     
     %typemap(throws) wstring
    -%{ std::string message($1.begin(), $1.end());
    -   SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, message.c_str());
    -   return $null; %}
    +%{std::string message($1.size(), '\0');
    +  for (size_t i = 0; i < $1.size(); ++i) {
    +    message[i] = (char)$1[i];
    +  }
    +  SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, message.c_str());
    +  return $null; %}
     
     // const wstring &
     %typemap(jni) const wstring & "jstring"
    @@ -166,9 +169,12 @@ class wstring;
     //%typemap(typecheck) const wstring & = wchar_t *;
     
     %typemap(throws) const wstring &
    -%{ std::string message($1.begin(), $1.end());
    -   SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, message.c_str());
    -   return $null; %}
    +%{std::string message($1.size(), '\0');
    +  for (size_t i = 0; i < $1.size(); ++i) {
    +    message[i] = (char)$1[i];
    +  }
    +  SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, message.c_str());
    +  return $null; %}
     
     }
     
    
    From 15d69ec2704cf331b7e6cab006924ecbd8b1ea23 Mon Sep 17 00:00:00 2001
    From: William S Fulton 
    Date: Sat, 7 May 2022 08:17:48 +0100
    Subject: [PATCH 437/662] Add runme.class file to Java test-suite clean
    
    ---
     Examples/test-suite/java/Makefile.in | 1 +
     1 file changed, 1 insertion(+)
    
    diff --git a/Examples/test-suite/java/Makefile.in b/Examples/test-suite/java/Makefile.in
    index 7a34f587b..43695ce69 100644
    --- a/Examples/test-suite/java/Makefile.in
    +++ b/Examples/test-suite/java/Makefile.in
    @@ -133,6 +133,7 @@ run_testcase = \
     	@if [ -d $(JAVA_PACKAGE) ]; then \
     	  rm -rf $(JAVA_PACKAGE); \
     	fi
    +	@rm -f $*_runme.class
     
     clean:
     	@rm -f *.class hs_err*.log
    
    From 06cd77834c4d4d91e30c6c8e08e363f89c64e5c5 Mon Sep 17 00:00:00 2001
    From: William S Fulton 
    Date: Sat, 7 May 2022 08:38:35 +0100
    Subject: [PATCH 438/662] Add PyPy fix to changes file
    
    ---
     CHANGES.current | 4 ++++
     1 file changed, 4 insertions(+)
    
    diff --git a/CHANGES.current b/CHANGES.current
    index f14dc24ad..a8975a03f 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-05-07: KrisThielemans
    +            [Python] Fix "too many initializers for 'PyHeapTypeObject'" errors
    +            using PyPy 3.8 and later.
    +
     2022-05-04: wsfulton
                 [C#] Add C# wchar_t * director typemaps
     
    
    From 69dba70319ec9dbcdb65171f71f76c6f1f60cf79 Mon Sep 17 00:00:00 2001
    From: William S Fulton 
    Date: Sat, 7 May 2022 09:34:53 +0100
    Subject: [PATCH 439/662] Visual C++ warning fix
    
    ---
     Source/Modules/interface.cxx | 2 +-
     1 file changed, 1 insertion(+), 1 deletion(-)
    
    diff --git a/Source/Modules/interface.cxx b/Source/Modules/interface.cxx
    index 76734dca1..c0c059019 100644
    --- a/Source/Modules/interface.cxx
    +++ b/Source/Modules/interface.cxx
    @@ -148,7 +148,7 @@ void Swig_interface_propagate_methods(Node *n) {
         process_interface_name(n);
         collect_interface_base_classes(n);
         List *methods = collect_interface_methods(n);
    -    bool is_interface = GetFlag(n, "feature:interface");
    +    bool is_interface = GetFlag(n, "feature:interface") ? true : false;
         for (Iterator mi = First(methods); mi.item; mi = Next(mi)) {
           if (!is_interface && GetFlag(mi.item, "abstract"))
     	continue;
    
    From 6939d91e4c6ea1f205574b85190a70b9c0db7bee Mon Sep 17 00:00:00 2001
    From: William S Fulton 
    Date: Sat, 7 May 2022 09:36:26 +0100
    Subject: [PATCH 440/662] Header file tidyup
    
    Fix Visual C++ warning in scilab.cxx:
      warning C4996: 'strtok': This function or variable may be unsafe.
    ---
     Source/Modules/csharp.cxx   | 2 +-
     Source/Modules/guile.cxx    | 1 -
     Source/Modules/java.cxx     | 2 +-
     Source/Modules/mzscheme.cxx | 1 -
     Source/Modules/ocaml.cxx    | 1 -
     Source/Modules/php.cxx      | 1 -
     Source/Modules/python.cxx   | 5 ++---
     Source/Modules/scilab.cxx   | 2 +-
     Source/Modules/utils.cxx    | 2 +-
     9 files changed, 6 insertions(+), 11 deletions(-)
    
    diff --git a/Source/Modules/csharp.cxx b/Source/Modules/csharp.cxx
    index 7f19070ee..d393ad1d6 100644
    --- a/Source/Modules/csharp.cxx
    +++ b/Source/Modules/csharp.cxx
    @@ -12,8 +12,8 @@
      * ----------------------------------------------------------------------------- */
     
     #include "swigmod.h"
    -#include 		// for INT_MAX
     #include "cparse.h"
    +#include 		// for INT_MAX
     #include 
     
     /* Hash type used for upcalls from C/C++ */
    diff --git a/Source/Modules/guile.cxx b/Source/Modules/guile.cxx
    index c30bf06f0..c70896af8 100644
    --- a/Source/Modules/guile.cxx
    +++ b/Source/Modules/guile.cxx
    @@ -12,7 +12,6 @@
      * ----------------------------------------------------------------------------- */
     
     #include "swigmod.h"
    -
     #include 
     
     // Note string broken in half for compilers that can't handle long strings
    diff --git a/Source/Modules/java.cxx b/Source/Modules/java.cxx
    index ae1e0fc2c..558231cf8 100644
    --- a/Source/Modules/java.cxx
    +++ b/Source/Modules/java.cxx
    @@ -12,8 +12,8 @@
      * ----------------------------------------------------------------------------- */
     
     #include "swigmod.h"
    -#include 		// for INT_MAX
     #include "cparse.h"
    +#include 		// for INT_MAX
     #include 
     #include "javadoc.h"
     
    diff --git a/Source/Modules/mzscheme.cxx b/Source/Modules/mzscheme.cxx
    index 8080b93c0..64b699336 100644
    --- a/Source/Modules/mzscheme.cxx
    +++ b/Source/Modules/mzscheme.cxx
    @@ -12,7 +12,6 @@
      * ----------------------------------------------------------------------------- */
     
     #include "swigmod.h"
    -
     #include 
     
     static const char *usage = "\
    diff --git a/Source/Modules/ocaml.cxx b/Source/Modules/ocaml.cxx
    index 6e45309e8..97bb8cc17 100644
    --- a/Source/Modules/ocaml.cxx
    +++ b/Source/Modules/ocaml.cxx
    @@ -12,7 +12,6 @@
      * ----------------------------------------------------------------------------- */
     
     #include "swigmod.h"
    -
     #include 
     
     static const char *usage = "\
    diff --git a/Source/Modules/php.cxx b/Source/Modules/php.cxx
    index 8d937e9b2..d61f6e428 100644
    --- a/Source/Modules/php.cxx
    +++ b/Source/Modules/php.cxx
    @@ -13,7 +13,6 @@
      */
     
     #include "swigmod.h"
    -
     #include 
     #include 
     
    diff --git a/Source/Modules/python.cxx b/Source/Modules/python.cxx
    index 7161c8e7d..9aac91601 100644
    --- a/Source/Modules/python.cxx
    +++ b/Source/Modules/python.cxx
    @@ -12,13 +12,12 @@
      * ----------------------------------------------------------------------------- */
     
     #include "swigmod.h"
    -#include 
     #include "cparse.h"
    +#include 
     #include 
     #include 
    -#include "pydoc.h"
    -
     #include 
    +#include "pydoc.h"
     
     #define PYSHADOW_MEMBER  0x2
     #define WARN_PYTHON_MULTIPLE_INH 405
    diff --git a/Source/Modules/scilab.cxx b/Source/Modules/scilab.cxx
    index 1731b218c..8c5536486 100644
    --- a/Source/Modules/scilab.cxx
    +++ b/Source/Modules/scilab.cxx
    @@ -11,9 +11,9 @@
      * Scilab language module for SWIG.
      * --------------------------------------------------------------------------*/
     
    +#include "swigmod.h"
     #include 
     #include 
    -#include "swigmod.h"
     
     static const int SCILAB_IDENTIFIER_NAME_CHAR_MAX = 24;
     
    diff --git a/Source/Modules/utils.cxx b/Source/Modules/utils.cxx
    index 2964ed3a6..0c1f87d19 100644
    --- a/Source/Modules/utils.cxx
    +++ b/Source/Modules/utils.cxx
    @@ -11,7 +11,7 @@
      * Various utility functions.
      * ----------------------------------------------------------------------------- */
     
    -#include 
    +#include "swigmod.h"
     
     int is_public(Node *n) {
       String *access = Getattr(n, "access");
    
    From ca6a73277b7f48ce4cf9d30d7bff7813f3685684 Mon Sep 17 00:00:00 2001
    From: Heinrich Schuchardt 
    Date: Mon, 9 May 2022 19:53:20 +0200
    Subject: [PATCH 441/662] Python: define PY_SSIZE_T_CLEAN
    
    It is recommended to always define PY_SSIZE_T_CLEAN before including
    Python.h. Cf. https://docs.python.org/3/c-api/intro.html
    
    This avoids errors like:
    
        SystemError: PY_SSIZE_T_CLEAN macro must be defined for '#' formats
    
    Signed-off-by: Heinrich Schuchardt 
    ---
     Lib/python/embed.i       | 4 +++-
     Lib/python/pyruntime.swg | 3 +++
     2 files changed, 6 insertions(+), 1 deletion(-)
    
    diff --git a/Lib/python/embed.i b/Lib/python/embed.i
    index efd048789..95225e2de 100644
    --- a/Lib/python/embed.i
    +++ b/Lib/python/embed.i
    @@ -29,7 +29,9 @@ As far as I know, this module is C++ safe.
     #endif
     
     %wrapper %{
    -
    +#ifndef PY_SSIZE_T_CLEAN
    +#define PY_SSIZE_T_CLEAN
    +#endif
     #include 
     
     #ifdef __cplusplus
    diff --git a/Lib/python/pyruntime.swg b/Lib/python/pyruntime.swg
    index 843fa6ce1..9b516ebaa 100644
    --- a/Lib/python/pyruntime.swg
    +++ b/Lib/python/pyruntime.swg
    @@ -11,6 +11,9 @@
     # include 
     #endif
     
    +#ifndef PY_SSIZE_T_CLEAN
    +#define PY_SSIZE_T_CLEAN
    +#endif
     #if defined(_DEBUG) && defined(SWIG_PYTHON_INTERPRETER_NO_DEBUG)
     /* Use debug wrappers with the Python release dll */
     # undef _DEBUG
    
    From 5851eb09a2f6f8cfa3fe6946782900b40ec12842 Mon Sep 17 00:00:00 2001
    From: Erez Geva 
    Date: Tue, 10 May 2022 20:13:55 +0200
    Subject: [PATCH 442/662] Add Lua test for argcargv.i
    
    Signed-off-by: Erez Geva 
    ---
     .../test-suite/lua/argcargvtest_runme.lua     | 26 +++++++++++++++++++
     1 file changed, 26 insertions(+)
     create mode 100644 Examples/test-suite/lua/argcargvtest_runme.lua
    
    diff --git a/Examples/test-suite/lua/argcargvtest_runme.lua b/Examples/test-suite/lua/argcargvtest_runme.lua
    new file mode 100644
    index 000000000..7f213665d
    --- /dev/null
    +++ b/Examples/test-suite/lua/argcargvtest_runme.lua
    @@ -0,0 +1,26 @@
    +require("import")	-- the import fn
    +import("argcargvtest")	-- import lib
    +v = argcargvtest
    +
    +-- 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})
    +
    +largs = {"hi", "hola", "hello"}
    +assert(v.mainc(largs) == 3, "bad main typemap")
    +
    +targs = {"hi", "hola"}
    +assert(v.mainv(targs, 1) == "hola", "bad main typemap")
    +
    +targs = {"hi", "hola"}
    +assert(v.mainv(targs, 1) == "hola", "bad main typemap")
    +
    +errorVal = 0
    +function try()
    +    mainv("hello", 1)
    +    errorVal = 1
    +end
    +assert(not pcall(try) and errorVal == 0, "bad main typemap")
    +
    +v.initializeApp(largs)
    
    From b88fe498cab92e18ad0a7b12e5ca9a49d4ac4ec0 Mon Sep 17 00:00:00 2001
    From: Erez Geva 
    Date: Wed, 11 May 2022 01:10:12 +0200
    Subject: [PATCH 443/662] Fix argcargv.i in Perl5, Tcl, PHP Add missing type
     map for type check. Add testing of argcargv.i for Perl5, Tcl, PHP and Ruby.
    
    Signed-off-by: Erez Geva 
    ---
     .../test-suite/perl5/argcargvtest_runme.pl    | 20 ++++++++++++
     .../test-suite/php/argcargvtest_runme.php     | 29 +++++++++++++++++
     .../test-suite/ruby/argcargvtest_runme.rb     | 32 +++++++++++++++++++
     .../test-suite/tcl/argcargvtest_runme.tcl     | 28 ++++++++++++++++
     Lib/perl5/argcargv.i                          |  5 +++
     Lib/php/argcargv.i                            |  4 +++
     Lib/tcl/argcargv.i                            |  5 +++
     7 files changed, 123 insertions(+)
     create mode 100644 Examples/test-suite/perl5/argcargvtest_runme.pl
     create mode 100644 Examples/test-suite/php/argcargvtest_runme.php
     create mode 100644 Examples/test-suite/ruby/argcargvtest_runme.rb
     create mode 100644 Examples/test-suite/tcl/argcargvtest_runme.tcl
    
    diff --git a/Examples/test-suite/perl5/argcargvtest_runme.pl b/Examples/test-suite/perl5/argcargvtest_runme.pl
    new file mode 100644
    index 000000000..c4157ebf4
    --- /dev/null
    +++ b/Examples/test-suite/perl5/argcargvtest_runme.pl
    @@ -0,0 +1,20 @@
    +use strict;
    +use warnings;
    +use Test::More tests => 8;
    +BEGIN { use_ok('argcargvtest') }
    +require_ok('argcargvtest');
    +
    +my $largs = ["hi", "hola", "hello"];
    +is(argcargvtest::mainc($largs), 3, "test main typemap 1");
    +
    +my $targs = ["hi", "hola"];
    +is(argcargvtest::mainv($targs, 1), "hola", "test main typemap 2");
    +
    +my $errorVal = 0;
    +my $ret = eval qq(argcargvtest::mainv("hello", 1); \$errorVal = 1;);
    +is($ret, undef, "test main typemap 3");
    +is($errorVal, 0, "test main typemap 4");
    +
    +is(argcargvtest::initializeApp($largs), undef, "test main typemap 5");
    +
    +ok(1, "done");
    diff --git a/Examples/test-suite/php/argcargvtest_runme.php b/Examples/test-suite/php/argcargvtest_runme.php
    new file mode 100644
    index 000000000..4a675d0ed
    --- /dev/null
    +++ b/Examples/test-suite/php/argcargvtest_runme.php
    @@ -0,0 +1,29 @@
    + e
    +    $ret = 1
    +end
    +
    +if $error == 1 or $ret != 1
    +    raise RuntimeError, "bad main typemap"
    +end
    +
    +initializeApp($largs)
    diff --git a/Examples/test-suite/tcl/argcargvtest_runme.tcl b/Examples/test-suite/tcl/argcargvtest_runme.tcl
    new file mode 100644
    index 000000000..14c0e92cb
    --- /dev/null
    +++ b/Examples/test-suite/tcl/argcargvtest_runme.tcl
    @@ -0,0 +1,28 @@
    +if [ catch { load ./argcargvtest[info sharedlibextension] argcargvtest} err_msg ] {
    +	puts stderr "Could not load shared object:\n$err_msg"
    +}
    +
    +set largs {hi hola hello}
    +if {[mainc $largs] != 3} {
    +     puts stderr "bad main typemap"
    +     exit 1
    +}
    +
    +set targs {hi hola}
    +if {[mainv $targs 1] != "hola"} {
    +     puts stderr "bad main typemap"
    +     exit 1
    +}
    +
    +set targs " hi hola "
    +if {[mainv $targs 1] != "hola"} {
    +     puts stderr "bad main typemap"
    +     exit 1
    +}
    +
    +if { ! [ catch { mainv("hello", 1) } ] } {
    +    puts stderr "bad main typemap"
    +    exit 1
    +}
    +
    +initializeApp $largs
    diff --git a/Lib/perl5/argcargv.i b/Lib/perl5/argcargv.i
    index de7b626e0..5c3968e37 100644
    --- a/Lib/perl5/argcargv.i
    +++ b/Lib/perl5/argcargv.i
    @@ -24,6 +24,11 @@
       $2[i] = NULL;
     }
     
    +%typemap(typecheck, precedence=SWIG_TYPECHECK_STRING_ARRAY) (int ARGC, char **ARGV) {
    +  AV *av = (AV *)SvRV($input);
    +  $1 = SvTYPE(av) == SVt_PVAV;
    +}
    +
     %typemap(freearg) (int ARGC, char **ARGV) {
       if ($2 != NULL) {
         free((void *)$2);
    diff --git a/Lib/php/argcargv.i b/Lib/php/argcargv.i
    index 14b0cf2c9..15a86a942 100644
    --- a/Lib/php/argcargv.i
    +++ b/Lib/php/argcargv.i
    @@ -33,6 +33,10 @@
       $2[i] = NULL;
     }
     
    +%typemap(typecheck, precedence=SWIG_TYPECHECK_STRING_ARRAY) (int ARGC, char **ARGV) {
    +  $1 = Z_TYPE($input) == IS_ARRAY;
    +}
    +
     %typemap(freearg) (int ARGC, char **ARGV) {
       if ($2 != NULL) {
         free((void *)$2);
    diff --git a/Lib/tcl/argcargv.i b/Lib/tcl/argcargv.i
    index e43f2e657..bcc3dc8a9 100644
    --- a/Lib/tcl/argcargv.i
    +++ b/Lib/tcl/argcargv.i
    @@ -21,6 +21,11 @@
       $2[i] = NULL;
     }
     
    +%typemap(typecheck, precedence=SWIG_TYPECHECK_STRING_ARRAY) (int ARGC, char **ARGV) {
    +  int len;
    +  $1 = Tcl_ListObjLength(interp, $input, &len) == TCL_OK;
    +}
    +
     %typemap(freearg) (int ARGC, char **ARGV) {
       if ($2 != NULL) {
         free((void *)$2);
    
    From 0307d0732c7c7c682d2b5542475f6171d287f7a2 Mon Sep 17 00:00:00 2001
    From: William S Fulton 
    Date: Sun, 15 May 2022 18:21:59 +0100
    Subject: [PATCH 444/662] Typemaps for (int ARGC, char **ARGV) fixup
    
    The default typemap should not be in this library file - this is for
    users to add in if they want C default argument support.
    ---
     Examples/test-suite/argcargvtest.i | 2 ++
     Lib/perl5/argcargv.i               | 4 ----
     Lib/php/argcargv.i                 | 4 ----
     Lib/tcl/argcargv.i                 | 4 ----
     4 files changed, 2 insertions(+), 12 deletions(-)
    
    diff --git a/Examples/test-suite/argcargvtest.i b/Examples/test-suite/argcargvtest.i
    index ed5aa0985..d87ce6871 100644
    --- a/Examples/test-suite/argcargvtest.i
    +++ b/Examples/test-suite/argcargvtest.i
    @@ -1,8 +1,10 @@
     %module argcargvtest
     
    +#if !defined(SWIGCSHARP) && !defined(SWIGD) && !defined(SWIGGO) && !defined(SWIGGUILE) && !defined(SWIGJAVA) && !defined(SWIGJAVASCRIPT) && !defined(SWIGMZSCHEME) && !defined(SWIGOCTAVE) && !defined(SWIGR) && !defined(SWIGSCILAB)
     %include 
     
     %apply (int ARGC, char **ARGV) { (size_t argc, const char **argv) }
    +#endif
     
     %inline %{
     
    diff --git a/Lib/perl5/argcargv.i b/Lib/perl5/argcargv.i
    index 5c3968e37..7ab7b66b7 100644
    --- a/Lib/perl5/argcargv.i
    +++ b/Lib/perl5/argcargv.i
    @@ -2,10 +2,6 @@
      * --- Argc & Argv ---
      * ------------------------------------------------------------ */
     
    -%typemap(default) (int ARGC, char **ARGV) {
    -  $1 = 0; $2 = NULL;
    -}
    -
     %typemap(in) (int ARGC, char **ARGV) {
       int i;
       I32 len;
    diff --git a/Lib/php/argcargv.i b/Lib/php/argcargv.i
    index 15a86a942..e5625c2ca 100644
    --- a/Lib/php/argcargv.i
    +++ b/Lib/php/argcargv.i
    @@ -2,10 +2,6 @@
      * --- Argc & Argv ---
      * ------------------------------------------------------------ */
     
    -%typemap(default) (int ARGC, char **ARGV) {
    -  $1 = 0; $2 = NULL;
    -}
    -
     %typemap(in) (int ARGC, char **ARGV) {
       int len, i;
       zval *val;
    diff --git a/Lib/tcl/argcargv.i b/Lib/tcl/argcargv.i
    index bcc3dc8a9..0fb1c8af9 100644
    --- a/Lib/tcl/argcargv.i
    +++ b/Lib/tcl/argcargv.i
    @@ -2,10 +2,6 @@
      * --- Argc & Argv ---
      * ------------------------------------------------------------ */
     
    -%typemap(default) (int ARGC, char **ARGV) {
    -  $1 = 0; $2 = NULL;
    -}
    -
     %typemap(in) (int ARGC, char **ARGV) {
       int i, nitems;
       Tcl_Obj **listobjv;
    
    From e4cdf9d98fe0cfc271192b9702cca1d9bcbe4549 Mon Sep 17 00:00:00 2001
    From: William S Fulton 
    Date: Sun, 15 May 2022 18:32:53 +0100
    Subject: [PATCH 445/662] argcargv.i cosmetic updates
    
    ---
     Lib/lua/argcargv.i    | 25 ++++++++++++-------------
     Lib/perl5/argcargv.i  |  2 +-
     Lib/php/argcargv.i    |  2 +-
     Lib/python/argcargv.i | 13 +++++--------
     Lib/ruby/argcargv.i   | 13 +++++--------
     Lib/tcl/argcargv.i    |  2 +-
     6 files changed, 25 insertions(+), 32 deletions(-)
    
    diff --git a/Lib/lua/argcargv.i b/Lib/lua/argcargv.i
    index 670ce4a80..376d346d8 100644
    --- a/Lib/lua/argcargv.i
    +++ b/Lib/lua/argcargv.i
    @@ -1,17 +1,16 @@
     /* ------------------------------------------------------------
    - * --- Argc & Argv ---
    - * ------------------------------------------------------------
    - *
    - *  Use it as follow:
    - *
    - *    %apply (int ARGC, char **ARGV) { (size_t argc, const char **argv) }
    - *    extern int mainApp(size_t argc, const char **argv);
    - *
    - *  then in the lua:
    - *
    - *    args = { "arg0", "arg1" }
    - *    mainApp(args);
    - *
    + * SWIG library containing argc and argv multi-argument typemaps
    +
    +   Use it as follows:
    +
    +     %apply (int ARGC, char **ARGV) { (size_t argc, const char **argv) }
    +     extern int mainApp(size_t argc, const char **argv);
    +
    +   then from lua:
    +
    +     args = { "arg0", "arg1" }
    +     mainApp(args);
    +
      * ------------------------------------------------------------ */
     
     %{
    diff --git a/Lib/perl5/argcargv.i b/Lib/perl5/argcargv.i
    index 7ab7b66b7..48a6047b8 100644
    --- a/Lib/perl5/argcargv.i
    +++ b/Lib/perl5/argcargv.i
    @@ -1,5 +1,5 @@
     /* ------------------------------------------------------------
    - * --- Argc & Argv ---
    + * SWIG library containing argc and argv multi-argument typemaps
      * ------------------------------------------------------------ */
     
     %typemap(in) (int ARGC, char **ARGV) {
    diff --git a/Lib/php/argcargv.i b/Lib/php/argcargv.i
    index e5625c2ca..e0093c214 100644
    --- a/Lib/php/argcargv.i
    +++ b/Lib/php/argcargv.i
    @@ -1,5 +1,5 @@
     /* ------------------------------------------------------------
    - * --- Argc & Argv ---
    + * SWIG library containing argc and argv multi-argument typemaps
      * ------------------------------------------------------------ */
     
     %typemap(in) (int ARGC, char **ARGV) {
    diff --git a/Lib/python/argcargv.i b/Lib/python/argcargv.i
    index 717fe7334..419803a81 100644
    --- a/Lib/python/argcargv.i
    +++ b/Lib/python/argcargv.i
    @@ -1,13 +1,10 @@
     /* ------------------------------------------------------------
    - * --- Argc & Argv ---
    + * SWIG library containing argc and argv multi-argument typemaps
      * ------------------------------------------------------------ */
     
     %fragment("SWIG_AsArgcArgv","header",fragment="SWIG_AsCharPtrAndSize") {
     SWIGINTERN int
    -SWIG_AsArgcArgv(PyObject *input,
    -		swig_type_info *ppchar_info,
    -		size_t *argc, char ***argv, int *owner)
    -{  
    +SWIG_AsArgcArgv(PyObject *input, swig_type_info *ppchar_info, size_t *argc, char ***argv, int *owner) {
       void *vptr;
       int res = SWIG_ConvertPtr(input, &vptr, ppchar_info, 0);
       if (!SWIG_IsOK(res)) {
    @@ -51,7 +48,7 @@ SWIG_AsArgcArgv(PyObject *input,
       } else {
         /* seems dangerous, but the user asked for it... */
         size_t i = 0;
    -    if (argv) { while (*argv[i] != 0) ++i;}    
    +    if (argv) { while (*argv[i] != 0) ++i;}
         if (argc) *argc = i;
         if (owner) *owner = 0;
         return SWIG_OK;
    @@ -66,10 +63,10 @@ SWIG_AsArgcArgv(PyObject *input,
     
     %typemap(in,noblock=0,fragment="SWIG_AsArgcArgv") (int ARGC, char **ARGV) (int res,char **argv = 0, size_t argc = 0, int owner= 0) {
       res = SWIG_AsArgcArgv($input, $descriptor(char**), &argc, &argv, &owner);
    -  if (!SWIG_IsOK(res)) { 
    +  if (!SWIG_IsOK(res)) {
         $1 = 0; $2 = 0;
         %argument_fail(SWIG_TypeError, "int ARGC, char **ARGV", $symname, $argnum);
    -  } else {  
    +  } else {
         $1 = %static_cast(argc,$1_ltype);
         $2 = %static_cast(argv, $2_ltype);
       }
    diff --git a/Lib/ruby/argcargv.i b/Lib/ruby/argcargv.i
    index fc0bc406a..330221a05 100644
    --- a/Lib/ruby/argcargv.i
    +++ b/Lib/ruby/argcargv.i
    @@ -1,21 +1,18 @@
     /* ------------------------------------------------------------
    - * --- Argc & Argv ---
    - * ------------------------------------------------------------ */
    - 
    -/* ------------------------------------------------------------
    + * SWIG library containing argc and argv multi-argument typemaps
     
    -   Use it as follow:
    +   Use it as follows:
     
          %apply (int ARGC, char **ARGV) { (size_t argc, const char **argv) }
     
          %inline %{
     
    -     int mainApp(size_t argc, const char **argv) 
    +     int mainApp(size_t argc, const char **argv)
          {
            return argc;
          }
     
    -   then in the ruby side:
    +   then from ruby:
     
          args = ["asdf", "asdf2"]
          mainApp(args);
    @@ -31,7 +28,7 @@
         VALUE *ptr = RARRAY_PTR($input);
         for (i=0; i < size; i++, ptr++) {
           $2[i]= StringValuePtr(*ptr);
    -    }    
    +    }
         $2[i]=NULL;
       } else {
         $1 = 0; $2 = 0;
    diff --git a/Lib/tcl/argcargv.i b/Lib/tcl/argcargv.i
    index 0fb1c8af9..bbe149ef0 100644
    --- a/Lib/tcl/argcargv.i
    +++ b/Lib/tcl/argcargv.i
    @@ -1,5 +1,5 @@
     /* ------------------------------------------------------------
    - * --- Argc & Argv ---
    + * SWIG library containing argc and argv multi-argument typemaps
      * ------------------------------------------------------------ */
     
     %typemap(in) (int ARGC, char **ARGV) {
    
    From 6860e2bc03dc2a46de0989dc938bffe63eb0694b Mon Sep 17 00:00:00 2001
    From: William S Fulton 
    Date: Sun, 15 May 2022 19:12:39 +0100
    Subject: [PATCH 446/662] Document argc argv library
    
    ---
     CHANGES.current          |  6 +++++
     Doc/Manual/Contents.html |  1 +
     Doc/Manual/Library.html  | 50 ++++++++++++++++++++++++++++++++++++----
     Lib/lua/argcargv.i       |  2 +-
     Lib/ruby/argcargv.i      |  7 +++---
     5 files changed, 57 insertions(+), 9 deletions(-)
    
    diff --git a/CHANGES.current b/CHANGES.current
    index f14dc24ad..3818bdf0b 100644
    --- a/CHANGES.current
    +++ b/CHANGES.current
    @@ -7,6 +7,12 @@ the issue number to the end of the URL: https://github.com/swig/swig/issues/
     Version 4.1.0 (in progress)
     ===========================
     
    +2022-05-15: erezgeva, eiselekd
    +            [Lua, Perl, PHP, Tcl] #2275 #2276 Add argcargv.i library containing
    +            (int ARGC, char **ARGV) multi-argument typemaps.
    +
    +            Document this library in Typemaps.html.
    +
     2022-05-04: wsfulton
                 [C#] Add C# wchar_t * director typemaps
     
    diff --git a/Doc/Manual/Contents.html b/Doc/Manual/Contents.html
    index 57ef77087..dfa9f6101 100644
    --- a/Doc/Manual/Contents.html
    +++ b/Doc/Manual/Contents.html
    @@ -419,6 +419,7 @@
     
  • The %include directive and library search path
  • C arrays and pointers
      +
    • argcargv.i
    • cpointer.i
    • carrays.i
    • cmalloc.i diff --git a/Doc/Manual/Library.html b/Doc/Manual/Library.html index 0efb8fb0f..3ecfc3a39 100644 --- a/Doc/Manual/Library.html +++ b/Doc/Manual/Library.html @@ -14,6 +14,7 @@
    • The %include directive and library search path
    • C arrays and pointers
        +
      • argcargv.i
      • cpointer.i
      • carrays.i
      • cmalloc.i @@ -115,7 +116,48 @@ pointers as class-like objects. Since these functions provide direct access to memory, their use is potentially unsafe and you should exercise caution.

        -

        12.2.1 cpointer.i

        +

        12.2.1 argcargv.i

        + + +

        +The argcargv.i library is a simple library providing multi-argument typemaps for handling C +argc argv command line argument C string arrays. +The argc parameter contains the argument count and argv contains the argument vector array. +

        + +

        +This library provides the following multi-argument typemap: +

        + +

        +(int ARGC, char **ARGV) +

        + +

        +Apply this multi-argument typemap to your use case, for example: +

        + +
        +
        +%apply (int ARGC, char **ARGV) { (size_t argc, const char **argv) }
        +
        +int mainApp(size_t argc, const char **argv);
        +
        +
        + +

        +then from Ruby: +

        + +
        +
        +$args = ["myarg1", "myarg2"]
        +mainApp(args);
        +
        +
        + + +

        12.2.2 cpointer.i

        @@ -331,7 +373,7 @@ In this example, the function int_to_uint() would be used to cast type Note: When working with simple pointers, typemaps can often be used to provide more seamless operation.

        -

        12.2.2 carrays.i

        +

        12.2.3 carrays.i

        @@ -510,7 +552,7 @@ used with types of char or char *. SWIG's default handling of these types is to handle them as character strings and the two macros do not do enough to change this.

        -

        12.2.3 cmalloc.i

        +

        12.2.4 cmalloc.i

        @@ -671,7 +713,7 @@ Now, in a script:

  • -

    12.2.4 cdata.i

    +

    12.2.5 cdata.i

    diff --git a/Lib/lua/argcargv.i b/Lib/lua/argcargv.i index 376d346d8..94cc8ed42 100644 --- a/Lib/lua/argcargv.i +++ b/Lib/lua/argcargv.i @@ -9,7 +9,7 @@ then from lua: args = { "arg0", "arg1" } - mainApp(args); + mainApp(args) * ------------------------------------------------------------ */ diff --git a/Lib/ruby/argcargv.i b/Lib/ruby/argcargv.i index 330221a05..24df9c94a 100644 --- a/Lib/ruby/argcargv.i +++ b/Lib/ruby/argcargv.i @@ -7,15 +7,14 @@ %inline %{ - int mainApp(size_t argc, const char **argv) - { + int mainApp(size_t argc, const char **argv) { return argc; } then from ruby: - args = ["asdf", "asdf2"] - mainApp(args); + $args = ["asdf", "asdf2"] + mainApp(args) * ------------------------------------------------------------ */ From 35ec8ca210b1db7c32a58decd219d4ec652a4cdb Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Sun, 15 May 2022 19:49:59 +0100 Subject: [PATCH 447/662] Add argcargv test case to test-suite --- Examples/test-suite/common.mk | 1 + .../test-suite/octave/argcargvtest_runme.m | 29 ------------------- Examples/test-suite/python/Makefile.in | 1 - 3 files changed, 1 insertion(+), 30 deletions(-) delete mode 100644 Examples/test-suite/octave/argcargvtest_runme.m diff --git a/Examples/test-suite/common.mk b/Examples/test-suite/common.mk index 57e663878..69f38113f 100644 --- a/Examples/test-suite/common.mk +++ b/Examples/test-suite/common.mk @@ -117,6 +117,7 @@ CPP_TEST_CASES += \ anonymous_bitfield \ apply_signed_char \ apply_strings \ + argcargvtest \ argout \ array_member \ array_typedef_memberin \ diff --git a/Examples/test-suite/octave/argcargvtest_runme.m b/Examples/test-suite/octave/argcargvtest_runme.m deleted file mode 100644 index f246dd9db..000000000 --- a/Examples/test-suite/octave/argcargvtest_runme.m +++ /dev/null @@ -1,29 +0,0 @@ -argcargvtest - -largs={'hi','hola','hello'}; -if (mainc(largs) != 3) - error("bad main typemap"); -endif - -targs={'hi','hola'}; -if (mainv(targs,1) != 'hola') - error("bad main typemap"); -endif - -targs={'hi', 'hola'}; -if (mainv(targs,1) != 'hola') - error("bad main typemap"); -endif - -try - error_flag = 0; - mainv('hello',1); - error_flag = 1; -catch -end_try_catch -if (error_flag) - error("bad main typemap") -endif - - -initializeApp(largs); diff --git a/Examples/test-suite/python/Makefile.in b/Examples/test-suite/python/Makefile.in index c061f903a..ddcd4afe9 100644 --- a/Examples/test-suite/python/Makefile.in +++ b/Examples/test-suite/python/Makefile.in @@ -20,7 +20,6 @@ top_srcdir = @top_srcdir@ top_builddir = @top_builddir@ CPP_TEST_CASES += \ - argcargvtest \ callback \ complextest \ director_stl \ From 96337b266ccba153c9278f63186d8aff74662a55 Mon Sep 17 00:00:00 2001 From: Xavier Delacour Date: Sat, 1 Mar 2008 23:35:44 +0000 Subject: [PATCH 448/662] Octave argcargvtest --- .../test-suite/octave/argcargvtest_runme.m | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 Examples/test-suite/octave/argcargvtest_runme.m diff --git a/Examples/test-suite/octave/argcargvtest_runme.m b/Examples/test-suite/octave/argcargvtest_runme.m new file mode 100644 index 000000000..f246dd9db --- /dev/null +++ b/Examples/test-suite/octave/argcargvtest_runme.m @@ -0,0 +1,29 @@ +argcargvtest + +largs={'hi','hola','hello'}; +if (mainc(largs) != 3) + error("bad main typemap"); +endif + +targs={'hi','hola'}; +if (mainv(targs,1) != 'hola') + error("bad main typemap"); +endif + +targs={'hi', 'hola'}; +if (mainv(targs,1) != 'hola') + error("bad main typemap"); +endif + +try + error_flag = 0; + mainv('hello',1); + error_flag = 1; +catch +end_try_catch +if (error_flag) + error("bad main typemap") +endif + + +initializeApp(largs); From 34221f223aef65896eb0e631a0fd2f608d98fa4e Mon Sep 17 00:00:00 2001 From: Erez Geva Date: Sat, 21 May 2022 20:47:50 +0200 Subject: [PATCH 449/662] Add Octave argcargv.i Signed-off-by: Erez Geva --- Examples/test-suite/argcargvtest.i | 2 +- Lib/octave/argcargv.i | 33 ++++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 1 deletion(-) create mode 100644 Lib/octave/argcargv.i diff --git a/Examples/test-suite/argcargvtest.i b/Examples/test-suite/argcargvtest.i index d87ce6871..3ba79d860 100644 --- a/Examples/test-suite/argcargvtest.i +++ b/Examples/test-suite/argcargvtest.i @@ -1,6 +1,6 @@ %module argcargvtest -#if !defined(SWIGCSHARP) && !defined(SWIGD) && !defined(SWIGGO) && !defined(SWIGGUILE) && !defined(SWIGJAVA) && !defined(SWIGJAVASCRIPT) && !defined(SWIGMZSCHEME) && !defined(SWIGOCTAVE) && !defined(SWIGR) && !defined(SWIGSCILAB) +#if !defined(SWIGCSHARP) && !defined(SWIGD) && !defined(SWIGGO) && !defined(SWIGGUILE) && !defined(SWIGJAVA) && !defined(SWIGJAVASCRIPT) && !defined(SWIGMZSCHEME) && !defined(SWIGR) && !defined(SWIGSCILAB) %include %apply (int ARGC, char **ARGV) { (size_t argc, const char **argv) } diff --git a/Lib/octave/argcargv.i b/Lib/octave/argcargv.i new file mode 100644 index 000000000..3da37a9a5 --- /dev/null +++ b/Lib/octave/argcargv.i @@ -0,0 +1,33 @@ +/* ------------------------------------------------------------ + * SWIG library containing argc and argv multi-argument typemaps + * ------------------------------------------------------------ */ + +%typemap(in) (int ARGC, char **ARGV) { + if ($input.is_scalar_type()) { + $1 = 0; $2 = NULL; + %argument_fail(SWIG_TypeError, "'int ARGC, char **ARGV' is not a list", $symname, $argnum); + } + octave_value_list list = $input.list_value(); + int i, len = list.length(); + $1 = ($1_ltype) len; + $2 = (char **) malloc((len+1)*sizeof(char *)); + for (i = 0; i < len; i++) { + if(!list(i).is_string()) { + $1 = 0; + %argument_fail(SWIG_TypeError, "'int ARGC, char **ARGV' use a non-string", $symname, $argnum); + } + $2[i] = (char *)list(i).string_value().c_str(); + } + $2[i] = NULL; +} + +%typemap(typecheck, precedence=SWIG_TYPECHECK_STRING_ARRAY) (int ARGC, char **ARGV) { + const octave_value& ov = $input; + $1 = !ov.is_scalar_type(); +} + +%typemap(freearg) (int ARGC, char **ARGV) { + if ($2 != NULL) { + free((void *)$2); + } +} From c359f57442ce5dbdd373442855fe1992a7e0b764 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Mon, 23 May 2022 08:50:38 +0100 Subject: [PATCH 450/662] Better Octave typecheck for argc argv typemaps --- Lib/octave/argcargv.i | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/Lib/octave/argcargv.i b/Lib/octave/argcargv.i index 3da37a9a5..8d455e586 100644 --- a/Lib/octave/argcargv.i +++ b/Lib/octave/argcargv.i @@ -4,15 +4,15 @@ %typemap(in) (int ARGC, char **ARGV) { if ($input.is_scalar_type()) { - $1 = 0; $2 = NULL; - %argument_fail(SWIG_TypeError, "'int ARGC, char **ARGV' is not a list", $symname, $argnum); + $1 = 0; $2 = NULL; + %argument_fail(SWIG_TypeError, "'int ARGC, char **ARGV' is not a list", $symname, $argnum); } octave_value_list list = $input.list_value(); int i, len = list.length(); $1 = ($1_ltype) len; $2 = (char **) malloc((len+1)*sizeof(char *)); for (i = 0; i < len; i++) { - if(!list(i).is_string()) { + if (!list(i).is_string()) { $1 = 0; %argument_fail(SWIG_TypeError, "'int ARGC, char **ARGV' use a non-string", $symname, $argnum); } @@ -22,8 +22,19 @@ } %typemap(typecheck, precedence=SWIG_TYPECHECK_STRING_ARRAY) (int ARGC, char **ARGV) { + $1 = 0; const octave_value& ov = $input; - $1 = !ov.is_scalar_type(); + if (!ov.is_scalar_type()) { + octave_value_list list = ov.list_value(); + int i, len = list.length(); + $1 = 1; + for (i = 0; i < len; i++) { + if (!list(i).is_string()) { + $1 = 0; + break; + } + } + } } %typemap(freearg) (int ARGC, char **ARGV) { From d5d58918661312857b3cd5985d9b46463cad21cc Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Mon, 23 May 2022 08:54:40 +0100 Subject: [PATCH 451/662] Remove ocaml from argcargv testing --- Examples/test-suite/argcargvtest.i | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Examples/test-suite/argcargvtest.i b/Examples/test-suite/argcargvtest.i index 3ba79d860..5711441d9 100644 --- a/Examples/test-suite/argcargvtest.i +++ b/Examples/test-suite/argcargvtest.i @@ -1,6 +1,6 @@ %module argcargvtest -#if !defined(SWIGCSHARP) && !defined(SWIGD) && !defined(SWIGGO) && !defined(SWIGGUILE) && !defined(SWIGJAVA) && !defined(SWIGJAVASCRIPT) && !defined(SWIGMZSCHEME) && !defined(SWIGR) && !defined(SWIGSCILAB) +#if !defined(SWIGCSHARP) && !defined(SWIGD) && !defined(SWIGGO) && !defined(SWIGGUILE) && !defined(SWIGJAVA) && !defined(SWIGJAVASCRIPT) && !defined(SWIGMZSCHEME) && !defined(SWIGOCAML) && !defined(SWIGR) && !defined(SWIGSCILAB) %include %apply (int ARGC, char **ARGV) { (size_t argc, const char **argv) } From 1ad77e8c9b955dfbf4c7b48890dcf49278b1e422 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Mon, 23 May 2022 08:59:13 +0100 Subject: [PATCH 452/662] Add octave argc argv to readme file --- CHANGES.current | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGES.current b/CHANGES.current index 32ccc4fc9..4a3bd7d98 100644 --- a/CHANGES.current +++ b/CHANGES.current @@ -8,7 +8,7 @@ Version 4.1.0 (in progress) =========================== 2022-05-15: erezgeva, eiselekd - [Lua, Perl, PHP, Tcl] #2275 #2276 Add argcargv.i library containing + [Lua, Perl, Octave, PHP, Tcl] #2275 #2276 #2283 Add argcargv.i library containing (int ARGC, char **ARGV) multi-argument typemaps. Document this library in Typemaps.html. From b58c554cdee28b1c79ad8a097da63751a237faee Mon Sep 17 00:00:00 2001 From: Joachim Kuebart Date: Fri, 13 Aug 2021 17:26:57 +0200 Subject: [PATCH 453/662] Java: Option to detach from the JVM in the thread destructor. --- CHANGES.current | 10 ++++++++++ Lib/java/director.swg | 28 +++++++++++++++++++++++++++- 2 files changed, 37 insertions(+), 1 deletion(-) diff --git a/CHANGES.current b/CHANGES.current index 4a3bd7d98..9d804f53b 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-05-23: jkuebart + [Java] On some versions of Android, specifically Android 6, + detaching the current thread from the JVM after every invocation + causes a memory leak. + + Offer SWIG_JAVA_DETACH_ON_THREAD_END to configure a behaviour + where the JVM is only detached in the thread destructor. + + See https://developer.android.com/training/articles/perf-jni#threads. + 2022-05-15: erezgeva, eiselekd [Lua, Perl, Octave, PHP, Tcl] #2275 #2276 #2283 Add argcargv.i library containing (int ARGC, char **ARGV) multi-argument typemaps. diff --git a/Lib/java/director.swg b/Lib/java/director.swg index e911a3da7..f7c4f2d8a 100644 --- a/Lib/java/director.swg +++ b/Lib/java/director.swg @@ -51,6 +51,22 @@ SWIGINTERN int Swig::GetThreadName(char *name, size_t len) { #endif +#if defined(SWIG_JAVA_DETACH_ON_THREAD_END) +#include +namespace { + + void detach(void* jvm) { + static_cast(jvm)->DetachCurrentThread(); + } + + pthread_key_t detachKey; + void makeDetachKey() { + pthread_key_create(&detachKey, detach); + } + +} +#endif + namespace Swig { /* Java object wrapper */ @@ -201,9 +217,19 @@ namespace Swig { #else director_->swig_jvm_->AttachCurrentThread(jenv, &args); #endif + +#if defined(SWIG_JAVA_DETACH_ON_THREAD_END) + // At least on Android 6, detaching after every call causes a memory leak. + // Instead, register a thread desructor and detach only when the thread ends. + // See https://developer.android.com/training/articles/perf-jni#threads + static pthread_once_t once = PTHREAD_ONCE_INIT; + + pthread_once(&once, makeDetachKey); + pthread_setspecific(detachKey, director->swig_jvm_); +#endif } ~JNIEnvWrapper() { -#if !defined(SWIG_JAVA_NO_DETACH_CURRENT_THREAD) +#if !defined(SWIG_JAVA_DETACH_ON_THREAD_END) && !defined(SWIG_JAVA_NO_DETACH_CURRENT_THREAD) // Some JVMs, eg jdk-1.4.2 and lower on Solaris have a bug and crash with the DetachCurrentThread call. // However, without this call, the JVM hangs on exit when the thread was not created by the JVM and creates a memory leak. if (env_status == JNI_EDETACHED) From 36dc81808bc5c5e98ad78142b60a4268125a378e Mon Sep 17 00:00:00 2001 From: Joachim Kuebart Date: Tue, 24 May 2022 14:34:09 +0200 Subject: [PATCH 454/662] Java: Move auxiliary methods into JObjectWrapper. --- Lib/java/director.swg | 33 +++++++++++++++++++-------------- 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/Lib/java/director.swg b/Lib/java/director.swg index f7c4f2d8a..70f4c561c 100644 --- a/Lib/java/director.swg +++ b/Lib/java/director.swg @@ -53,18 +53,6 @@ SWIGINTERN int Swig::GetThreadName(char *name, size_t len) { #if defined(SWIG_JAVA_DETACH_ON_THREAD_END) #include -namespace { - - void detach(void* jvm) { - static_cast(jvm)->DetachCurrentThread(); - } - - pthread_key_t detachKey; - void makeDetachKey() { - pthread_key_create(&detachKey, detach); - } - -} #endif namespace Swig { @@ -149,6 +137,19 @@ namespace Swig { } } +#if defined(SWIG_JAVA_DETACH_ON_THREAD_END) + static void detach(void* jvm) { + static_cast(jvm)->DetachCurrentThread(); + } + + static void makeDetachKey() { + pthread_key_create(&detach_key_, detach); + } + + /* thread-local key to register a destructor */ + static pthread_key_t detach_key_; +#endif + private: /* pointer to Java object */ jobject jthis_; @@ -156,6 +157,10 @@ namespace Swig { bool weak_global_; }; +#if defined(SWIG_JAVA_DETACH_ON_THREAD_END) + pthread_key_t JObjectWrapper::detach_key_; +#endif + /* Local JNI reference deleter */ class LocalRefGuard { JNIEnv *jenv_; @@ -224,8 +229,8 @@ namespace Swig { // See https://developer.android.com/training/articles/perf-jni#threads static pthread_once_t once = PTHREAD_ONCE_INIT; - pthread_once(&once, makeDetachKey); - pthread_setspecific(detachKey, director->swig_jvm_); + pthread_once(&once, JObjectWrapper::makeDetachKey); + pthread_setspecific(JObjectWrapper::detach_key_, director->swig_jvm_); #endif } ~JNIEnvWrapper() { From 34a27359ae44b4f694c1c7ff4c33f18094526ba9 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Thu, 26 May 2022 08:44:51 +0100 Subject: [PATCH 455/662] Final tidy up for improved C# SwigDerviedClassHasMethod implementation --- CHANGES.current | 4 ++++ Examples/test-suite/csharp/director_basic_runme.cs | 2 +- Examples/test-suite/director_basic.i | 5 +++-- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/CHANGES.current b/CHANGES.current index 4a3bd7d98..e2f9d9ff0 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-05-26: rokups + [C#] #1323 Modify SwigDerivedClassHasMethod for a more efficient director + implementation when calling virtual methods that are not overidden. + 2022-05-15: erezgeva, eiselekd [Lua, Perl, Octave, PHP, Tcl] #2275 #2276 #2283 Add argcargv.i library containing (int ARGC, char **ARGV) multi-argument typemaps. diff --git a/Examples/test-suite/csharp/director_basic_runme.cs b/Examples/test-suite/csharp/director_basic_runme.cs index de299b145..a81f27ef3 100644 --- a/Examples/test-suite/csharp/director_basic_runme.cs +++ b/Examples/test-suite/csharp/director_basic_runme.cs @@ -50,7 +50,7 @@ public class runme myNewBar.x = 10; // Low level implementation check -// my.testSwigDerivedClassHasMethod(); + my.testSwigDerivedClassHasMethod(); // These should not call the C# implementations as they are not overridden int v; diff --git a/Examples/test-suite/director_basic.i b/Examples/test-suite/director_basic.i index 23d910324..abb1a3d13 100644 --- a/Examples/test-suite/director_basic.i +++ b/Examples/test-suite/director_basic.i @@ -71,11 +71,12 @@ %} %typemap(cscode) MyClass %{ + // low level implementation check for checking MyOverriddenClass public void testSwigDerivedClassHasMethod() { if (SwigDerivedClassHasMethod("nonVirtual", swigMethodTypes3)) - throw new global::System.Exception("non-overriding non-virtual method would be when connecting director"); + throw new global::System.Exception("SwigDerivedClassHasMethod failed checking a non-overriding non-virtual method (nonVirtual)"); if (SwigDerivedClassHasMethod("nonOverride", swigMethodTypes4)) - throw new global::System.Exception("non-overriding virtual method would be when connecting director"); + throw new global::System.Exception("SwigDerivedClassHasMethod failed checking a non-overriding method (nonOverride)"); } %} From abc8e0bb277f7a54ff4ee209845dde910d267819 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Fri, 27 May 2022 18:58:04 +0100 Subject: [PATCH 456/662] Define PY_SSIZE_T_CLEAN macro before #include "Python.h" as recommended in Python 3.7 and later. Issue #2277 --- CHANGES.current | 11 +++++++++++ Lib/python/embed.i | 2 +- Lib/python/pyruntime.swg | 2 +- 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/CHANGES.current b/CHANGES.current index a8975a03f..a950b930f 100644 --- a/CHANGES.current +++ b/CHANGES.current @@ -7,6 +7,17 @@ the issue number to the end of the URL: https://github.com/swig/swig/issues/ Version 4.1.0 (in progress) =========================== +2022-05-27: xypron + [Python] #2277 Define PY_SSIZE_T_CLEAN macro before #include "Python.h" as + recommended in Python 3.7 and later. + + To avoid this macro definition, add the following to your interface file so + that SWIG_NO_PY_SSIZE_T_CLEAN is defined at the beginning of the C++ wrappers: + + %begin %{ + #define SWIG_NO_PY_SSIZE_T_CLEAN + %} + 2022-05-07: KrisThielemans [Python] Fix "too many initializers for 'PyHeapTypeObject'" errors using PyPy 3.8 and later. diff --git a/Lib/python/embed.i b/Lib/python/embed.i index 95225e2de..34cb9b92a 100644 --- a/Lib/python/embed.i +++ b/Lib/python/embed.i @@ -29,7 +29,7 @@ As far as I know, this module is C++ safe. #endif %wrapper %{ -#ifndef PY_SSIZE_T_CLEAN +#ifndef SWIG_NO_PY_SSIZE_T_CLEAN #define PY_SSIZE_T_CLEAN #endif #include diff --git a/Lib/python/pyruntime.swg b/Lib/python/pyruntime.swg index 9b516ebaa..b1033dfbc 100644 --- a/Lib/python/pyruntime.swg +++ b/Lib/python/pyruntime.swg @@ -11,7 +11,7 @@ # include #endif -#ifndef PY_SSIZE_T_CLEAN +#ifndef SWIG_NO_PY_SSIZE_T_CLEAN #define PY_SSIZE_T_CLEAN #endif #if defined(_DEBUG) && defined(SWIG_PYTHON_INTERPRETER_NO_DEBUG) From 8e3f0fd793afc17d293ee9533030b05e43548661 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Fri, 27 May 2022 20:01:57 +0100 Subject: [PATCH 457/662] Suppress -Wregister gcc warnings in Python.h MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Such as: /usr/include/python2.7/unicodeobject.h:534:24: warning: ISO C++17 does not allow ‘register’ storage class specifier [-Wregister] Closes #2227 --- Lib/python/embed.i | 12 ++++++++++++ Lib/python/pyruntime.swg | 12 ++++++++++++ 2 files changed, 24 insertions(+) diff --git a/Lib/python/embed.i b/Lib/python/embed.i index 34cb9b92a..505dd9b57 100644 --- a/Lib/python/embed.i +++ b/Lib/python/embed.i @@ -32,8 +32,20 @@ As far as I know, this module is C++ safe. #ifndef SWIG_NO_PY_SSIZE_T_CLEAN #define PY_SSIZE_T_CLEAN #endif + +#if __GNUC__ >= 7 +#pragma GCC diagnostic push +#if defined(__cplusplus) && __cplusplus >=201703L +#pragma GCC diagnostic ignored "-Wregister" /* For python-2.7 headers that use register */ +#endif +#endif + #include +#if __GNUC__ >= 7 +#pragma GCC diagnostic pop +#endif + #ifdef __cplusplus extern "C" #endif diff --git a/Lib/python/pyruntime.swg b/Lib/python/pyruntime.swg index b1033dfbc..74669a74f 100644 --- a/Lib/python/pyruntime.swg +++ b/Lib/python/pyruntime.swg @@ -14,6 +14,14 @@ #ifndef SWIG_NO_PY_SSIZE_T_CLEAN #define PY_SSIZE_T_CLEAN #endif + +#if __GNUC__ >= 7 +#pragma GCC diagnostic push +#if defined(__cplusplus) && __cplusplus >=201703L +#pragma GCC diagnostic ignored "-Wregister" /* For python-2.7 headers that use register */ +#endif +#endif + #if defined(_DEBUG) && defined(SWIG_PYTHON_INTERPRETER_NO_DEBUG) /* Use debug wrappers with the Python release dll */ # undef _DEBUG @@ -22,6 +30,10 @@ #else # include #endif + +#if __GNUC__ >= 7 +#pragma GCC diagnostic pop +#endif %} %insert(runtime) "swigrun.swg"; /* SWIG API */ From aef97a57833410ca521360437b78d315029bfabc Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Sat, 28 May 2022 10:22:34 +0100 Subject: [PATCH 458/662] Cosmetic tidyup in SWIG_JAVA_DETACH_ON_THREAD_END code --- Lib/java/director.swg | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Lib/java/director.swg b/Lib/java/director.swg index 70f4c561c..536513557 100644 --- a/Lib/java/director.swg +++ b/Lib/java/director.swg @@ -138,11 +138,11 @@ namespace Swig { } #if defined(SWIG_JAVA_DETACH_ON_THREAD_END) - static void detach(void* jvm) { - static_cast(jvm)->DetachCurrentThread(); + static void detach(void *jvm) { + static_cast(jvm)->DetachCurrentThread(); } - static void makeDetachKey() { + static void make_detach_key() { pthread_key_create(&detach_key_, detach); } @@ -229,7 +229,7 @@ namespace Swig { // See https://developer.android.com/training/articles/perf-jni#threads static pthread_once_t once = PTHREAD_ONCE_INIT; - pthread_once(&once, JObjectWrapper::makeDetachKey); + pthread_once(&once, JObjectWrapper::make_detach_key); pthread_setspecific(JObjectWrapper::detach_key_, director->swig_jvm_); #endif } From 62e0685df61bd636cb101eb58a27e0e14074b0c2 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Mon, 30 May 2022 19:00:04 +0100 Subject: [PATCH 459/662] Test and document imfuncname special variable expansion --- CHANGES.current | 4 ++++ Doc/Manual/Java.html | 3 ++- .../java/java_typemaps_proxy_runme.java | 9 +++++++++ Examples/test-suite/java_typemaps_proxy.i | 17 +++++++++++++++++ 4 files changed, 32 insertions(+), 1 deletion(-) diff --git a/CHANGES.current b/CHANGES.current index 46c567a02..95114d3f6 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-05-30: LindleyF + [Java] #2042 Add new special variable expansion: $imfuncname. + Expands to the function name called in the intermediary class. + 2022-02-02: olly [Ruby] https://sourceforge.net/p/swig/bugs/1136/ Fix remove of prefix from method name to only remove it at the start. diff --git a/Doc/Manual/Java.html b/Doc/Manual/Java.html index 03e3c9124..4a4b1750f 100644 --- a/Doc/Manual/Java.html +++ b/Doc/Manual/Java.html @@ -6441,7 +6441,8 @@ unless the jniclassname attribute is specified in the

    diff --git a/Examples/test-suite/java/java_typemaps_proxy_runme.java b/Examples/test-suite/java/java_typemaps_proxy_runme.java index 67a083114..0caeb1c65 100644 --- a/Examples/test-suite/java/java_typemaps_proxy_runme.java +++ b/Examples/test-suite/java/java_typemaps_proxy_runme.java @@ -76,6 +76,15 @@ public class java_typemaps_proxy_runme { java_typemaps_proxyJNI.Without_member_method(nullPtr, nullPtr); java_typemaps_proxyJNI.delete_Without(nullPtr); java_typemaps_proxyJNI.global_method_without(nullPtr); + + // $imfuncname substitution + ProxyA pa = new ProxyA(); + if (pa.imfuncname_test() != 123) + throw new RuntimeException("imfuncname_test is not 123"); + if (ProxyA.imfuncname_static_test() != 234) + throw new RuntimeException("imfuncname_test is not 234"); + if (java_typemaps_proxy.imfuncname_global_test() != 345) + throw new RuntimeException("imfuncname_test is not 345"); } } diff --git a/Examples/test-suite/java_typemaps_proxy.i b/Examples/test-suite/java_typemaps_proxy.i index 3e9b18335..b20dd385b 100644 --- a/Examples/test-suite/java_typemaps_proxy.i +++ b/Examples/test-suite/java_typemaps_proxy.i @@ -127,3 +127,20 @@ void global_method_constwithout(const ConstWithout *p) {} %} +// $imfuncname substitution +%typemap(javaout) int imfuncname_test { + return $moduleJNI.$imfuncname(swigCPtr, this) + 123; + } +%typemap(javaout) int imfuncname_static_test { + return $moduleJNI.$imfuncname() + 234; + } +%typemap(javaout) int imfuncname_global_test { + return $moduleJNI.$imfuncname() + 345; + } +%inline %{ +struct ProxyA { + int imfuncname_test() { return 0; } + static int imfuncname_static_test() { return 0; } +}; +int imfuncname_global_test() { return 0; } +%} From 954f29b032dfc0ef04e4b0ef0871b04a30068b6b Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Mon, 30 May 2022 19:43:04 +0100 Subject: [PATCH 460/662] Add special variable imfuncname expansion for C# and D Same functionality as Java --- CHANGES.current | 4 ++ Doc/Manual/CSharp.html | 6 +++ Doc/Manual/D.html | 6 +++ .../csharp/csharp_typemaps_runme.cs | 16 ++++++++ Examples/test-suite/csharp_typemaps.i | 39 +++++++++++++++++++ Source/Modules/csharp.cxx | 6 +++ Source/Modules/d.cxx | 2 + 7 files changed, 79 insertions(+) diff --git a/CHANGES.current b/CHANGES.current index 95114d3f6..5e496424c 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-05-30: wsfulton + [C#, D] Add new special variable expansion: $imfuncname. + Expands to the function name called in the intermediary class. + 2022-05-30: LindleyF [Java] #2042 Add new special variable expansion: $imfuncname. Expands to the function name called in the intermediary class. diff --git a/Doc/Manual/CSharp.html b/Doc/Manual/CSharp.html index fe8f7c4bd..405868b5c 100644 --- a/Doc/Manual/CSharp.html +++ b/Doc/Manual/CSharp.html @@ -550,6 +550,12 @@ This special variable expands to the intermediary class name. For C# this is usu unless the imclassname attribute is specified in the %module directive.

    +

    +$imfuncname
    +This special variable expands to the name of the function in the intermediary class that will be used in $imcall. +Like, $imcall, this special variable is only expanded in the "csout", "csvarin" and "csvarout" typemaps. +

    +

    The directory Examples/csharp has a number of simple examples. Visual Studio .NET 2003 solution and project files are available for compiling with the Microsoft .NET C# diff --git a/Doc/Manual/D.html b/Doc/Manual/D.html index f9f2d53ca..99ee027a1 100644 --- a/Doc/Manual/D.html +++ b/Doc/Manual/D.html @@ -267,6 +267,12 @@ SomeClass bar() { +

    $imfuncname
    +

    +This special variable expands to the name of the function in the intermediary class that will be used in $imcall. +Like, $imcall, this special variable is only expanded in the "dout" typemap. +

    +
    $importtype(SomeDType)

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

    diff --git a/Examples/test-suite/csharp/csharp_typemaps_runme.cs b/Examples/test-suite/csharp/csharp_typemaps_runme.cs index 846644f09..a9119a0c3 100644 --- a/Examples/test-suite/csharp/csharp_typemaps_runme.cs +++ b/Examples/test-suite/csharp/csharp_typemaps_runme.cs @@ -107,6 +107,22 @@ public class TestThread { Console.Error.WriteLine("Test failed (thread " + threadId + "): " + e.Message); Failed = true; } + + // $imfuncname substitution + ProxyA pa = new ProxyA(); + if (pa.imfuncname_test() != 123) + throw new ApplicationException("imfuncname_test is not 123"); + if (ProxyA.imfuncname_static_test() != 234) + throw new ApplicationException("imfuncname_test is not 234"); + if (csharp_typemaps.imfuncname_global_test() != 345) + throw new ApplicationException("imfuncname_test is not 345"); + + pa.variab = 1000; + if (pa.variab != 1000 + 111 + 222) + throw new ApplicationException("pa.variab is not 1333"); + csharp_typemaps.global_variab = 1000; + if (csharp_typemaps.global_variab != 1000 + 333 + 444) + throw new ApplicationException("csharp_typemaps.variab is not 1777"); } } diff --git a/Examples/test-suite/csharp_typemaps.i b/Examples/test-suite/csharp_typemaps.i index dc5b40c02..a73f01c44 100644 --- a/Examples/test-suite/csharp_typemaps.i +++ b/Examples/test-suite/csharp_typemaps.i @@ -136,3 +136,42 @@ namespace Glob { bool MVar::svar = false; %} +// $imfuncname substitution +%typemap(csout) int imfuncname_test { + return $modulePINVOKE.$imfuncname(swigCPtr) + 123; + } +%typemap(csout) int imfuncname_static_test { + return $modulePINVOKE.$imfuncname() + 234; + } +%typemap(csout) int imfuncname_global_test { + return $modulePINVOKE.$imfuncname() + 345; + } + +%typemap(csvarout, excode=SWIGEXCODE2) int variab %{ + get { + int ret = $modulePINVOKE.$imfuncname(swigCPtr) + 222;$excode + return ret; + } %} +%typemap(csvarin, excode=SWIGEXCODE2) int variab %{ + set { + $modulePINVOKE.$imfuncname(swigCPtr, value + 111);$excode + } %} + +%typemap(csvarout, excode=SWIGEXCODE2) int global_variab %{ + get { + int ret = $modulePINVOKE.$imfuncname() + 333;$excode + return ret; + } %} +%typemap(csvarin, excode=SWIGEXCODE2) int global_variab %{ + set { + $modulePINVOKE.$imfuncname(value + 444);$excode + } %} +%inline %{ +struct ProxyA { + int imfuncname_test() { return 0; } + static int imfuncname_static_test() { return 0; } + int variab; +}; +int imfuncname_global_test() { return 0; } +int global_variab; +%} diff --git a/Source/Modules/csharp.cxx b/Source/Modules/csharp.cxx index edb79e13e..f2f48d707 100644 --- a/Source/Modules/csharp.cxx +++ b/Source/Modules/csharp.cxx @@ -2572,6 +2572,7 @@ public: } else { Replaceall(imcall, "$imfuncname", intermediary_function_name); } + Replaceall(tm, "$imfuncname", intermediary_function_name); Replaceall(tm, "$imcall", imcall); } else { Swig_warning(WARN_CSHARP_TYPEMAP_CSOUT_UNDEF, input_file, line_number, "No csout typemap defined for %s\n", SwigType_str(t, 0)); @@ -2615,6 +2616,7 @@ public: if ((tm = Swig_typemap_lookup("csvarin", variable_parm, "", 0))) { substituteClassname(cvariable_type, tm); Replaceall(tm, "$csinput", "value"); + Replaceall(tm, "$imfuncname", intermediary_function_name); Replaceall(tm, "$imcall", imcall); excodeSubstitute(n, tm, "csvarin", variable_parm); Printf(proxy_class_code, "%s", tm); @@ -2629,6 +2631,7 @@ public: else Replaceall(tm, "$owner", "false"); substituteClassname(t, tm); + Replaceall(tm, "$imfuncname", intermediary_function_name); Replaceall(tm, "$imcall", imcall); excodeSubstitute(n, tm, "csvarout", n); Printf(proxy_class_code, "%s", tm); @@ -3141,6 +3144,7 @@ public: else Replaceall(tm, "$owner", "false"); substituteClassname(t, tm); + Replaceall(tm, "$imfuncname", overloaded_name); Replaceall(tm, "$imcall", imcall); } else { Swig_warning(WARN_CSHARP_TYPEMAP_CSOUT_UNDEF, input_file, line_number, "No csout typemap defined for %s\n", SwigType_str(t, 0)); @@ -3179,6 +3183,7 @@ public: if ((tm = Getattr(p, "tmap:csvarin"))) { substituteClassname(pt, tm); Replaceall(tm, "$csinput", "value"); + Replaceall(tm, "$imfuncname", overloaded_name); Replaceall(tm, "$imcall", imcall); excodeSubstitute(n, tm, "csvarin", p); Printf(module_class_code, "%s", tm); @@ -3193,6 +3198,7 @@ public: else Replaceall(tm, "$owner", "false"); substituteClassname(t, tm); + Replaceall(tm, "$imfuncname", overloaded_name); Replaceall(tm, "$imcall", imcall); excodeSubstitute(n, tm, "csvarout", n); Printf(module_class_code, "%s", tm); diff --git a/Source/Modules/d.cxx b/Source/Modules/d.cxx index b7283eac2..9d716f433 100644 --- a/Source/Modules/d.cxx +++ b/Source/Modules/d.cxx @@ -2898,6 +2898,7 @@ private: } else { Replaceall(imcall, "$imfuncname", intermediary_function_name); } + Replaceall(tm, "$imfuncname", intermediary_function_name); Replaceall(tm, "$imcall", imcall); } else { Swig_warning(WARN_D_TYPEMAP_DOUT_UNDEF, input_file, line_number, @@ -3100,6 +3101,7 @@ private: else Replaceall(tm, "$owner", "false"); replaceClassname(tm, t); + Replaceall(tm, "$imfuncname", overloaded_name); Replaceall(tm, "$imcall", imcall); } else { Swig_warning(WARN_D_TYPEMAP_DOUT_UNDEF, input_file, line_number, From 5afc8138427080f0fc9973afd645d1b2bdf5f3d8 Mon Sep 17 00:00:00 2001 From: Seth R Johnson Date: Thu, 2 Jun 2022 18:29:56 -0400 Subject: [PATCH 461/662] Fix whitespace and memory leak --- Source/Swig/typemap.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/Source/Swig/typemap.c b/Source/Swig/typemap.c index 8e2657583..c66b93ee6 100644 --- a/Source/Swig/typemap.c +++ b/Source/Swig/typemap.c @@ -537,24 +537,24 @@ int Swig_typemap_apply(ParmList *src, ParmList *dest) { Replace(nkey, "tmap:", "", DOH_REPLACE_ANY); Setattr(deferred_add, nkey, sm1); } - Delete(nkey); } + Delete(nkey); } } /* After assembling the key/item pairs, add the resulting typemaps */ for (ki = First(deferred_add); ki.key; ki = Next(ki)) { - Hash *sm1 = ki.item; - String *src_str = ParmList_str_multibrackets(src); - String *dest_str = ParmList_str_multibrackets(dest); - String *source_directive = NewStringf("apply %s { %s }", src_str, dest_str); + Hash *sm1 = ki.item; + String *src_str = ParmList_str_multibrackets(src); + String *dest_str = ParmList_str_multibrackets(dest); + String *source_directive = NewStringf("apply %s { %s }", src_str, dest_str); - typemap_register(ki.key, dest, Getattr(sm1, "code"), Getattr(sm1, "locals"), Getattr(sm1, "kwargs"), source_directive); + typemap_register(ki.key, dest, Getattr(sm1, "code"), Getattr(sm1, "locals"), Getattr(sm1, "kwargs"), source_directive); - Delete(source_directive); - Delete(dest_str); - Delete(src_str); - } + Delete(source_directive); + Delete(dest_str); + Delete(src_str); + } Delete(deferred_add); } Delete(ssig); From 28036e5a16028a13aa2715274ca1425408438d17 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Wed, 1 Jun 2022 22:11:18 +0100 Subject: [PATCH 462/662] Documentation for attribute support in $typemap. --- CHANGES.current | 19 +++++++++++++++++++ Doc/Manual/Contents.html | 1 + Doc/Manual/Typemaps.html | 36 ++++++++++++++++++++++++++++++++---- 3 files changed, 52 insertions(+), 4 deletions(-) diff --git a/CHANGES.current b/CHANGES.current index 68f7daa54..35b0f7ee2 100644 --- a/CHANGES.current +++ b/CHANGES.current @@ -7,6 +7,25 @@ the issue number to the end of the URL: https://github.com/swig/swig/issues/ Version 4.1.0 (in progress) =========================== +2022-06-04: sethrj + Enhance $typemap to support typemap attributes. + + $typemap(method:attribute, typepattern) + + For example: + + %typemap(cstype, out="object") XClass "XClass" + %typemap(cscode) BarClass %{ + $typemap(cstype:out, XClass) bar() { + return null; + } + + which expands to + + object bar() { + return null; + } + 2022-05-30: wsfulton [C#, D] Add new special variable expansion: $imfuncname. Expands to the function name called in the intermediary class. diff --git a/Doc/Manual/Contents.html b/Doc/Manual/Contents.html index dfa9f6101..6f48360fd 100644 --- a/Doc/Manual/Contents.html +++ b/Doc/Manual/Contents.html @@ -524,6 +524,7 @@
  • Special variables and typemap attributes
  • Special variables combined with special variable macros diff --git a/Doc/Manual/Typemaps.html b/Doc/Manual/Typemaps.html index 614c446e7..28f9d51ad 100644 --- a/Doc/Manual/Typemaps.html +++ b/Doc/Manual/Typemaps.html @@ -48,6 +48,7 @@
  • Special variables and typemap attributes
  • Special variables combined with special variable macros @@ -2457,13 +2458,40 @@ The result is the following expansion +

    14.4.4.3 $typemap(method:attribute, typepattern)

    + +

    -The first argument, the typemap method, can look up the attribute of a -typemap by appending a colon and the keyword. For example, -$typemap(directorin:descriptor, $type) would be replaced by "D" if type is a double. +An enhanced version of $typemap provides access to typemap attributes by +appending a colon and the attribute name after the method name. In the example below, +"cstype" is the typemap method and "out" is the typemap attribute.

    + +
    +
    +%typemap(cstype, out="object") XClass "XClass"
    +%typemap(cscode) BarClass %{
    +  $typemap(cstype:out, XClass) bar()
    +  {
    +    return null;
    +  }
    +
    +

    -New in SWIG 4.1. +which expands to +

    +
    +
    +  object bar()
    +  {
    +    return null;
    +  }
    +
    +
    + +

    +Compatibility note: Support for typemap attributes in $typemap +was introduced in SWIG-4.1.0.

    14.4.5 Special variables and typemap attributes

    From 6254de05efbb7e8969b0507ebc84b675a35d93ee Mon Sep 17 00:00:00 2001 From: Seth R Johnson Date: Fri, 3 Jun 2022 06:50:25 -0400 Subject: [PATCH 463/662] Avoid emitting locals duiring keyword typemap lookup --- Source/Swig/typemap.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Source/Swig/typemap.c b/Source/Swig/typemap.c index c66b93ee6..2f9c06000 100644 --- a/Source/Swig/typemap.c +++ b/Source/Swig/typemap.c @@ -2101,8 +2101,9 @@ static void replace_embedded_typemap(String *s, ParmList *parm_sublist, Wrapper } found_colon = Strchr(tmap_method, ':'); if (found_colon) { + /* Substitute from a keyword argument to a typemap. Avoid emitting local variables from the attached typemap by passing NULL for the file. */ String *temp_tmap_method = NewStringWithSize(Char(tmap_method), found_colon - Char(tmap_method)); - Swig_typemap_attach_parms(temp_tmap_method, to_match_parms, f); + Swig_typemap_attach_parms(temp_tmap_method, to_match_parms, NULL); Delete(temp_tmap_method); } else { Swig_typemap_attach_parms(tmap_method, to_match_parms, f); From a1b45a8333621c671bef178929c2b1c4f6950069 Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Wed, 8 Jun 2022 13:00:53 +1200 Subject: [PATCH 464/662] [php] Add runme.php for two more testcases --- .../php/director_exception_catches_runme.php | 26 +++++++++++++++++++ .../php/director_exception_nothrow_runme.php | 23 ++++++++++++++++ 2 files changed, 49 insertions(+) create mode 100644 Examples/test-suite/php/director_exception_catches_runme.php create mode 100644 Examples/test-suite/php/director_exception_nothrow_runme.php diff --git a/Examples/test-suite/php/director_exception_catches_runme.php b/Examples/test-suite/php/director_exception_catches_runme.php new file mode 100644 index 000000000..51c5663d5 --- /dev/null +++ b/Examples/test-suite/php/director_exception_catches_runme.php @@ -0,0 +1,26 @@ +getMessage(), "Testing exception thrown in description()", "Unexpected exception message: ".$e->getMessage()); +} + +check::done(); diff --git a/Examples/test-suite/php/director_exception_nothrow_runme.php b/Examples/test-suite/php/director_exception_nothrow_runme.php new file mode 100644 index 000000000..2bc4a0c4a --- /dev/null +++ b/Examples/test-suite/php/director_exception_nothrow_runme.php @@ -0,0 +1,23 @@ +pang(), "MyBar::pang()", "MyBar::pang() not called as expected"); +$b = new Bar(); +check::equal($b->pang(), "Bar::pang()", "Bar::pang() not called as expected"); + +check::done(); From 97a109ecc9bc6f6cd8575b052d753ad78c2b96bd Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Wed, 8 Jun 2022 17:41:00 +1200 Subject: [PATCH 465/662] WIP: Refactor pararent class tracking --- Source/Modules/php.cxx | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/Source/Modules/php.cxx b/Source/Modules/php.cxx index d61f6e428..72a2508f1 100644 --- a/Source/Modules/php.cxx +++ b/Source/Modules/php.cxx @@ -63,6 +63,7 @@ static String *pragma_phpinfo; static String *pragma_version; static String *class_name = NULL; +static String *base_class = NULL; static String *destructor_action = NULL; static String *magic_set = NULL; static String *magic_get = NULL; @@ -923,9 +924,10 @@ public: return n && Getattr(n, "classtype") != NULL; } - void generate_magic_property_methods(Node *class_node, String *base_class) { - if (Equal(base_class, "Exception") || !is_class_wrapped(base_class)) { - base_class = NULL; + void generate_magic_property_methods(Node *class_node) { + String *swig_base = base_class; + if (Equal(swig_base, "Exception") || !is_class_wrapped(swig_base)) { + swig_base = NULL; } static bool generated_magic_arginfo = false; @@ -976,8 +978,8 @@ public: "}\n", NIL); } Printf(f->code, "} else {\n"); - if (base_class) { - Printf(f->code, "PHP_MN(%s%s___set)(INTERNAL_FUNCTION_PARAM_PASSTHRU);\n}\n", prefix, base_class); + if (swig_base) { + Printf(f->code, "PHP_MN(%s%s___set)(INTERNAL_FUNCTION_PARAM_PASSTHRU);\n}\n", prefix, swig_base); } else { Printf(f->code, "add_property_zval_ex(ZEND_THIS, ZSTR_VAL(arg2), ZSTR_LEN(arg2), &args[1]);\n}\n"); } @@ -1008,8 +1010,8 @@ public: Printf(f->code, "\nelse if (strcmp(ZSTR_VAL(arg2),\"thisown\") == 0) {\n"); Printf(f->code, "if(arg->newobject) {\nRETVAL_LONG(1);\n}\nelse {\nRETVAL_LONG(0);\n}\n}\n\n"); Printf(f->code, "else {\n"); - if (base_class) { - Printf(f->code, "PHP_MN(%s%s___get)(INTERNAL_FUNCTION_PARAM_PASSTHRU);\n}\n", prefix, base_class); + if (swig_base) { + Printf(f->code, "PHP_MN(%s%s___get)(INTERNAL_FUNCTION_PARAM_PASSTHRU);\n}\n", prefix, swig_base); } else { // __get is only called if the property isn't set on the zend_object. Printf(f->code, "RETVAL_NULL();\n}\n"); @@ -1041,8 +1043,8 @@ public: Append(f->code, magic_isset); } Printf(f->code, "else {\n"); - if (base_class) { - Printf(f->code, "PHP_MN(%s%s___isset)(INTERNAL_FUNCTION_PARAM_PASSTHRU);\n}\n", prefix, base_class); + if (swig_base) { + Printf(f->code, "PHP_MN(%s%s___isset)(INTERNAL_FUNCTION_PARAM_PASSTHRU);\n}\n", prefix, swig_base); } else { // __isset is only called if the property isn't set on the zend_object. Printf(f->code, "RETVAL_FALSE;\n}\n"); @@ -1586,9 +1588,9 @@ public: virtual int classHandler(Node *n) { String *symname = Getattr(n, "sym:name"); - String *base_class = NULL; class_name = symname; + base_class = NULL; destructor_action = NULL; Printf(all_cs_entry, "static const zend_function_entry class_%s_functions[] = {\n", class_name); @@ -1799,10 +1801,11 @@ public: Printf(s_oinit, "#endif\n"); Printf(s_oinit, "\n"); - generate_magic_property_methods(n, base_class); + generate_magic_property_methods(n); Printf(all_cs_entry, " ZEND_FE_END\n};\n\n"); class_name = NULL; + base_class = NULL; return SWIG_OK; } From d7ed1a8b97cb0c4e3c27167a85d165990f15ca31 Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Thu, 9 Jun 2022 09:06:12 +1200 Subject: [PATCH 466/662] [php] Eliminate sprintf to temp buffer to create ZVAL Use zend_strpprintf() which handles this more cleanly without risk of buffer overflow and without a fixed length limit. --- Lib/php/php.swg | 16 ++++------------ Lib/php/typemaps.i | 24 ++++++------------------ Source/Modules/php.cxx | 4 +--- 3 files changed, 11 insertions(+), 33 deletions(-) diff --git a/Lib/php/php.swg b/Lib/php/php.swg index bf388a75a..ffcffde70 100644 --- a/Lib/php/php.swg +++ b/Lib/php/php.swg @@ -240,9 +240,7 @@ if ((long long)LONG_MIN <= $1 && $1 <= (long long)LONG_MAX) { RETVAL_LONG((long)($1)); } else { - char temp[256]; - sprintf(temp, "%lld", (long long)$1); - RETVAL_STRING(temp); + RETVAL_NEW_STR(zend_strpprintf(0, "%lld", (long long)$1)); } %} %typemap(out, phptype="int|string") unsigned long long @@ -250,9 +248,7 @@ if ($1 <= (unsigned long long)LONG_MAX) { RETVAL_LONG((long)($1)); } else { - char temp[256]; - sprintf(temp, "%llu", (unsigned long long)$1); - RETVAL_STRING(temp); + RETVAL_NEW_STR(zend_strpprintf(0, "%llu", (unsigned long long)$1)); } %} @@ -286,9 +282,7 @@ if ((long long)LONG_MIN <= *$1 && *$1 <= (long long)LONG_MAX) { RETVAL_LONG((long)(*$1)); } else { - char temp[256]; - sprintf(temp, "%lld", (long long)(*$1)); - RETVAL_STRING(temp); + RETVAL_NEW_STR(zend_strpprintf(0, "%lld", (long long)(*$1))); } %} %typemap(out, phptype="int|string") const unsigned long long & @@ -296,9 +290,7 @@ if (*$1 <= (unsigned long long)LONG_MAX) { RETVAL_LONG((long)(*$1)); } else { - char temp[256]; - sprintf(temp, "%llu", (unsigned long long)(*$1)); - RETVAL_STRING(temp); + RETVAL_NEW_STR(zend_strpprintf(0, "%llu", (unsigned long long)(*$1))); } %} diff --git a/Lib/php/typemaps.i b/Lib/php/typemaps.i index 321b1202c..2f7819097 100644 --- a/Lib/php/typemaps.i +++ b/Lib/php/typemaps.i @@ -122,9 +122,7 @@ INT_TYPEMAP(long long); if ((long long)LONG_MIN <= temp$argnum && temp$argnum <= (long long)LONG_MAX) { ZVAL_LONG(&o, (long)temp$argnum); } else { - char temp[256]; - sprintf(temp, "%lld", (long long)temp$argnum); - ZVAL_STRING(&o, temp); + ZVAL_NEW_STR(&o, zend_strpprintf(0, "%lld", (long long)temp$argnum)); } t_output_helper($result, &o); } @@ -138,9 +136,7 @@ INT_TYPEMAP(long long); if ((long long)LONG_MIN <= lvalue$argnum && lvalue$argnum <= (long long)LONG_MAX) { ZVAL_LONG(&$arg, (long)temp$argnum); } else { - char temp[256]; - sprintf(temp, "%lld", (long long)lvalue$argnum); - ZVAL_STRING(&$arg, temp); + ZVAL_NEW_STR(&$arg, zend_strpprintf(0, "%lld", (long long)lvalue$argnum)); } %} %typemap(argout) long long &OUTPUT @@ -148,9 +144,7 @@ INT_TYPEMAP(long long); if ((long long)LONG_MIN <= *arg$argnum && *arg$argnum <= (long long)LONG_MAX) { ZVAL_LONG($result, (long)(*arg$argnum)); } else { - char temp[256]; - sprintf(temp, "%lld", (long long)(*arg$argnum)); - ZVAL_STRING($result, temp); + ZVAL_NEW_STR($result, zend_strpprintf(0, "%lld", (long long)(*arg$argnum))); } %} @@ -161,9 +155,7 @@ INT_TYPEMAP(unsigned long long); if (temp$argnum <= (unsigned long long)LONG_MAX) { ZVAL_LONG(&o, temp$argnum); } else { - char temp[256]; - sprintf(temp, "%llu", (unsigned long long)temp$argnum); - ZVAL_STRING(&o, temp); + ZVAL_NEW_STR(&o, zend_strpprintf(0, "%llu", (unsigned long long)temp$argnum)); } t_output_helper($result, &o); } @@ -177,9 +169,7 @@ INT_TYPEMAP(unsigned long long); if (lvalue$argnum <= (unsigned long long)LONG_MAX) { ZVAL_LONG($arg, (long)(lvalue$argnum)); } else { - char temp[256]; - sprintf(temp, "%llu", (unsigned long long)lvalue$argnum); - ZVAL_STRING((*$arg), temp); + ZVAL_NEW_STR((*$arg), zend_strpprintf(0, "%llu", (unsigned long long)lvalue$argnum)); } %} %typemap(argout) unsigned long long &OUTPUT @@ -187,9 +177,7 @@ INT_TYPEMAP(unsigned long long); if (*arg$argnum <= (unsigned long long)LONG_MAX) { ZVAL_LONG($result, (long)(*arg$argnum)); } else { - char temp[256]; - sprintf(temp, "%llu", (unsigned long long)(*arg$argnum)); - ZVAL_STRING($result, temp); + ZVAL_NEW_STR($result, zend_strpprintf(0, "%llu", (unsigned long long)(*arg$argnum))); } %} diff --git a/Source/Modules/php.cxx b/Source/Modules/php.cxx index 72a2508f1..56152712d 100644 --- a/Source/Modules/php.cxx +++ b/Source/Modules/php.cxx @@ -151,14 +151,12 @@ static void SwigPHP_emit_pointer_type_registrations() { Printf(s_wrappers, "static int swig_ptr_cast_object(zend_object *zobj, zval *retval, int type) {\n"); Append(s_wrappers, "#endif\n"); Printf(s_wrappers, " if (type == IS_STRING) {\n"); - Printf(s_wrappers, " char buf[80];\n"); Append(s_wrappers, "#if PHP_MAJOR_VERSION < 8\n"); Printf(s_wrappers, " swig_object_wrapper *obj = SWIG_Z_FETCH_OBJ_P(z);\n"); Append(s_wrappers, "#else\n"); Printf(s_wrappers, " swig_object_wrapper *obj = swig_php_fetch_object(zobj);\n"); Append(s_wrappers, "#endif\n"); - Printv(s_wrappers, " sprintf(buf, \"SWIGPointer(%p,owned=%d)\", obj->ptr, obj->newobject);\n", NIL); - Printf(s_wrappers, " ZVAL_STRING(retval, buf);\n"); + Printv(s_wrappers, " ZVAL_NEW_STR(retval, zend_strpprintf(0, \"SWIGPointer(%p,owned=%d)\", obj->ptr, obj->newobject));\n", NIL); Printf(s_wrappers, " return SUCCESS;\n"); Printf(s_wrappers, " }\n"); Printf(s_wrappers, " return FAILURE;\n"); From a8994d418648372d0fb3dda579783d154ae6ec9d Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Thu, 9 Jun 2022 12:49:30 +1200 Subject: [PATCH 467/662] Rename zend_types to be clearer It's actually tracking pointer types which aren't wrapped as classes. --- Source/Modules/php.cxx | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/Source/Modules/php.cxx b/Source/Modules/php.cxx index 56152712d..7b4d823fa 100644 --- a/Source/Modules/php.cxx +++ b/Source/Modules/php.cxx @@ -102,7 +102,7 @@ static String *swig_wrapped_interface_ce() { static Hash *arginfo_used; /* Track non-class pointer types we need to to wrap */ -static Hash *zend_types = 0; +static Hash *raw_pointer_types = 0; static int shadow = 1; @@ -124,10 +124,10 @@ extern "C" { } static void SwigPHP_emit_pointer_type_registrations() { - if (!zend_types) + if (!raw_pointer_types) return; - Iterator ki = First(zend_types); + Iterator ki = First(raw_pointer_types); if (!ki.key) return; @@ -2381,9 +2381,9 @@ void PHPTypes::process_phptype(Node *n, int key, const String_or_char *attribute // fails at runtime and the error isn't very helpful). We could // check the condition // - // zend_types && Getattr(zend_types, SwigType_manglestr(type)) + // raw_pointer_types && Getattr(raw_pointer_types, SwigType_manglestr(type)) // - // except that zend_types may not have been fully filled in when + // except that raw_pointer_types may not have been fully filled in when // we are called. Append(merge_list, NewStringf("SWIG\\%s", SwigType_manglestr(type))); } @@ -2402,10 +2402,10 @@ extern "C" { static void typetrace(const SwigType *ty, String *mangled, String *clientdata) { if (maininstance->classLookup(ty) == NULL) { // a non-class pointer - if (!zend_types) { - zend_types = NewHash(); + if (!raw_pointer_types) { + raw_pointer_types = NewHash(); } - Setattr(zend_types, mangled, mangled); + Setattr(raw_pointer_types, mangled, mangled); } if (r_prevtracefunc) (*r_prevtracefunc) (ty, mangled, clientdata); From a277748870199ccdc63b852369fcd07625bf0c20 Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Thu, 9 Jun 2022 14:39:51 +1200 Subject: [PATCH 468/662] Fix PHP parameter type declarations compatibility Ensure PHP parameter type declarations are compatible with those for the same method in any classes we inherit from. See #2151 --- .../test-suite/php/director_classes_runme.php | 79 +++++++++++++ Source/Modules/php.cxx | 111 ++++++++++++------ 2 files changed, 156 insertions(+), 34 deletions(-) create mode 100644 Examples/test-suite/php/director_classes_runme.php diff --git a/Examples/test-suite/php/director_classes_runme.php b/Examples/test-suite/php/director_classes_runme.php new file mode 100644 index 000000000..6a1d8a557 --- /dev/null +++ b/Examples/test-suite/php/director_classes_runme.php @@ -0,0 +1,79 @@ +set($base); + $dh = new DoubleHolder(444.555); + check::equal($caller->ValCall($dh)->val, $dh->val, "$bname.Val"); + check::equal($caller->RefCall($dh)->val, $dh->val, "$bname.Ref"); + check::equal($caller->PtrCall($dh)->val, $dh->val, "$bname.Ptr"); + check::equal($caller->ConstPtrRefCall($dh)->val, $dh->val, "$bname.ConstPtrRef"); + check::equal($caller->FullyOverloadedCall(1), + "${bname}::FullyOverloaded(int)", + "$bname.FullyOverloaded(int)"); + check::equal($caller->FullyOverloadedCall(false), + "${bname}::FullyOverloaded(bool)", + "$bname.FullyOverloaded(bool)"); + // This next one is TODO for Perl with PerlDerived. + check::equal($caller->SemiOverloadedCall(-678), + "${bname}::SemiOverloaded(int)", + "$bname.SemiOverloaded(int)"); + check::equal($caller->SemiOverloadedCall(false), + "Base::SemiOverloaded(bool)", + "$bname.SemiOverloaded(bool)"); + check::equal($caller->DefaultParmsCall(10, 2.2), + "${bname}::DefaultParms(int, double)", + "$bname.DefaultParms(int, double)"); + check::equal($caller->DefaultParmsCall(10), + "${bname}::DefaultParms(int)", + "$bname.DefaultParms(int)"); + $caller->reset(); +} + +check::done(); diff --git a/Source/Modules/php.cxx b/Source/Modules/php.cxx index 7b4d823fa..71e196b1e 100644 --- a/Source/Modules/php.cxx +++ b/Source/Modules/php.cxx @@ -185,10 +185,27 @@ static void SwigPHP_emit_pointer_type_registrations() { } } +static Hash *create_php_type_flags() { + Hash *h = NewHash(); + Setattr(h, "array", "MAY_BE_ARRAY"); + Setattr(h, "bool", "MAY_BE_BOOL"); + Setattr(h, "callable", "MAY_BE_CALLABLE"); + Setattr(h, "float", "MAY_BE_DOUBLE"); + Setattr(h, "int", "MAY_BE_LONG"); + Setattr(h, "iterable", "MAY_BE_ITERABLE"); + Setattr(h, "mixed", "MAY_BE_MIXED"); + Setattr(h, "null", "MAY_BE_NULL"); + Setattr(h, "object", "MAY_BE_OBJECT"); + Setattr(h, "resource", "MAY_BE_RESOURCE"); + Setattr(h, "string", "MAY_BE_STRING"); + Setattr(h, "void", "MAY_BE_VOID"); + return h; +} + +static Hash *php_type_flags = create_php_type_flags(); + // Class encapsulating the machinery to add PHP type declarations. class PHPTypes { - Hash *phptypes; - // List with an entry for each parameter and one for the return type. // // We assemble the types in here before emitting them so for an overloaded @@ -201,26 +218,14 @@ class PHPTypes { List *byref; public: - PHPTypes() : phptypes(NewHash()), merged_types(NULL), byref(NULL) { - Setattr(phptypes, "array", "MAY_BE_ARRAY"); - Setattr(phptypes, "bool", "MAY_BE_BOOL"); - Setattr(phptypes, "callable", "MAY_BE_CALLABLE"); - Setattr(phptypes, "float", "MAY_BE_DOUBLE"); - Setattr(phptypes, "int", "MAY_BE_LONG"); - Setattr(phptypes, "iterable", "MAY_BE_ITERABLE"); - Setattr(phptypes, "mixed", "MAY_BE_MIXED"); - Setattr(phptypes, "null", "MAY_BE_NULL"); - Setattr(phptypes, "object", "MAY_BE_OBJECT"); - Setattr(phptypes, "resource", "MAY_BE_RESOURCE"); - Setattr(phptypes, "string", "MAY_BE_STRING"); - Setattr(phptypes, "void", "MAY_BE_VOID"); - } + PHPTypes() : merged_types(NewList()), byref(NULL) { } - void reset() { + PHPTypes(const PHPTypes *o) + : merged_types(Copy(o->merged_types)), byref(Copy(o->byref)) { } + + ~PHPTypes() { Delete(merged_types); - merged_types = NewList(); Delete(byref); - byref = NULL; } // key is 0 for return type, or >= 1 for parameters numbered from 1 @@ -238,7 +243,7 @@ public: // Skip duplicates when merging. continue; } - String *c = Getattr(phptypes, i.item); + String *c = Getattr(php_type_flags, i.item); if (c) { if (Len(result) > 0) Append(result, "|"); Append(result, c); @@ -272,9 +277,18 @@ public: } }; -class PHP : public Language { - PHPTypes phptypes; +static PHPTypes *phptypes = NULL; +// Track if the current phptypes is for a non-class function. +static PHPTypes *non_class_phptypes = NULL; + +// class + ":" + method -> PHPTypes* +static Hash *all_phptypes = NewHash(); + +// php_class_name -> php_parent_class_name +static Hash *php_parent_class = NewHash(); + +class PHP : public Language { public: PHP() { director_language = 1; @@ -728,7 +742,7 @@ public: // it inherits from is directed, which is what we care about here. // Using (!is_member_director(n)) would get it wrong for testcase // director_frob. - out_phptype = phptypes.get_phptype(0, out_phpclasses); + out_phptype = phptypes->get_phptype(0, out_phpclasses); } } @@ -763,17 +777,17 @@ public: String *phpclasses = NewStringEmpty(); String *phptype = NULL; if (GetFlag(n, "feature:php:type")) { - phptype = phptypes.get_phptype(param_count, phpclasses); + phptype = phptypes->get_phptype(param_count, phpclasses); } int byref; if (!dispatch) { byref = GetFlag(p, "tmap:in:byref"); - if (byref) phptypes.set_byref(param_count); + if (byref) phptypes->set_byref(param_count); } else { // If any overload takes a particular parameter by reference then the // dispatch function also needs to take that parameter by reference. - byref = phptypes.get_byref(param_count); + byref = phptypes->get_byref(param_count); } // FIXME: Should we be doing byref for return value as well? @@ -1141,12 +1155,6 @@ public: return SWIG_ERROR; } - if (!Getattr(n, "sym:previousSibling")) { - // First function of an overloaded group or a function which isn't part - // of a group so reset the phptype information. - phptypes.reset(); - } - if (constructor) { wname = NewString("__construct"); } else if (wrapperType == membervar) { @@ -1197,6 +1205,40 @@ public: return SWIG_OK; } + if (!Getattr(n, "sym:previousSibling")) { + // First function of an overloaded group or a function which isn't part + // of a group so reset the phptype information. + if (non_class_phptypes) { + delete non_class_phptypes; + non_class_phptypes = NULL; + } + phptypes = NULL; + + if (class_name) { + // See if there's a parent class which implements this method, and if + // so copy the PHPTypes of that method as a starting point as we need + // to be compatible with it (whether it is virtual or not). + String *parent = class_name; + while ((parent = Getattr(php_parent_class, parent)) != NULL) { + String *key = NewStringf("%s:%s", parent, wname); + PHPTypes *p = (PHPTypes*)GetVoid(all_phptypes, key); + Delete(key); + if (p) { + phptypes = new PHPTypes(p); + break; + } + } + } + if (!phptypes) { + phptypes = new PHPTypes(); + } + if (class_name) { + SetVoid(all_phptypes, NewStringf("%s:%s", class_name, wname), phptypes); + } else { + non_class_phptypes = phptypes; + } + } + f = NewWrapper(); if (static_getter) { @@ -1313,7 +1355,7 @@ public: continue; } - phptypes.process_phptype(p, i + 1, "tmap:in:phptype"); + phptypes->process_phptype(p, i + 1, "tmap:in:phptype"); String *source = NewStringf("args[%d]", i); Replaceall(tm, "$input", source); @@ -1399,7 +1441,7 @@ public: } emit_return_variable(n, d, f); - phptypes.process_phptype(n, 0, "tmap:out:phptype"); + phptypes->process_phptype(n, 0, "tmap:out:phptype"); if (outarg) { Printv(f->code, outarg, NIL); @@ -1643,6 +1685,7 @@ public: Printf(s_oinit, " SWIG_Php_ce_%s = zend_register_internal_class_ex(&internal_ce, zend_ce_exception);\n", class_name); } else if (is_class_wrapped(base_class)) { Printf(s_oinit, " SWIG_Php_ce_%s = zend_register_internal_class_ex(&internal_ce, SWIG_Php_ce_%s);\n", class_name, base_class); + Setattr(php_parent_class, class_name, base_class); } else { Printf(s_oinit, " SWIG_Php_ce_%s = zend_register_internal_class(&internal_ce);\n", class_name); } From d43d62cd7abac737bb5e8d73afa319ba579030e0 Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Thu, 9 Jun 2022 17:55:09 +1200 Subject: [PATCH 469/662] Revert "Fix PHP parameter type declarations compatibility" I missed that this change breaks cpp_static, which seems to be to do with handling the combined getter and setter we emit for static member variables. Reverting while I figure out how to handle that. This reverts commit a277748870199ccdc63b852369fcd07625bf0c20. --- .../test-suite/php/director_classes_runme.php | 79 ------------- Source/Modules/php.cxx | 111 ++++++------------ 2 files changed, 34 insertions(+), 156 deletions(-) delete mode 100644 Examples/test-suite/php/director_classes_runme.php diff --git a/Examples/test-suite/php/director_classes_runme.php b/Examples/test-suite/php/director_classes_runme.php deleted file mode 100644 index 6a1d8a557..000000000 --- a/Examples/test-suite/php/director_classes_runme.php +++ /dev/null @@ -1,79 +0,0 @@ -set($base); - $dh = new DoubleHolder(444.555); - check::equal($caller->ValCall($dh)->val, $dh->val, "$bname.Val"); - check::equal($caller->RefCall($dh)->val, $dh->val, "$bname.Ref"); - check::equal($caller->PtrCall($dh)->val, $dh->val, "$bname.Ptr"); - check::equal($caller->ConstPtrRefCall($dh)->val, $dh->val, "$bname.ConstPtrRef"); - check::equal($caller->FullyOverloadedCall(1), - "${bname}::FullyOverloaded(int)", - "$bname.FullyOverloaded(int)"); - check::equal($caller->FullyOverloadedCall(false), - "${bname}::FullyOverloaded(bool)", - "$bname.FullyOverloaded(bool)"); - // This next one is TODO for Perl with PerlDerived. - check::equal($caller->SemiOverloadedCall(-678), - "${bname}::SemiOverloaded(int)", - "$bname.SemiOverloaded(int)"); - check::equal($caller->SemiOverloadedCall(false), - "Base::SemiOverloaded(bool)", - "$bname.SemiOverloaded(bool)"); - check::equal($caller->DefaultParmsCall(10, 2.2), - "${bname}::DefaultParms(int, double)", - "$bname.DefaultParms(int, double)"); - check::equal($caller->DefaultParmsCall(10), - "${bname}::DefaultParms(int)", - "$bname.DefaultParms(int)"); - $caller->reset(); -} - -check::done(); diff --git a/Source/Modules/php.cxx b/Source/Modules/php.cxx index 71e196b1e..7b4d823fa 100644 --- a/Source/Modules/php.cxx +++ b/Source/Modules/php.cxx @@ -185,27 +185,10 @@ static void SwigPHP_emit_pointer_type_registrations() { } } -static Hash *create_php_type_flags() { - Hash *h = NewHash(); - Setattr(h, "array", "MAY_BE_ARRAY"); - Setattr(h, "bool", "MAY_BE_BOOL"); - Setattr(h, "callable", "MAY_BE_CALLABLE"); - Setattr(h, "float", "MAY_BE_DOUBLE"); - Setattr(h, "int", "MAY_BE_LONG"); - Setattr(h, "iterable", "MAY_BE_ITERABLE"); - Setattr(h, "mixed", "MAY_BE_MIXED"); - Setattr(h, "null", "MAY_BE_NULL"); - Setattr(h, "object", "MAY_BE_OBJECT"); - Setattr(h, "resource", "MAY_BE_RESOURCE"); - Setattr(h, "string", "MAY_BE_STRING"); - Setattr(h, "void", "MAY_BE_VOID"); - return h; -} - -static Hash *php_type_flags = create_php_type_flags(); - // Class encapsulating the machinery to add PHP type declarations. class PHPTypes { + Hash *phptypes; + // List with an entry for each parameter and one for the return type. // // We assemble the types in here before emitting them so for an overloaded @@ -218,14 +201,26 @@ class PHPTypes { List *byref; public: - PHPTypes() : merged_types(NewList()), byref(NULL) { } + PHPTypes() : phptypes(NewHash()), merged_types(NULL), byref(NULL) { + Setattr(phptypes, "array", "MAY_BE_ARRAY"); + Setattr(phptypes, "bool", "MAY_BE_BOOL"); + Setattr(phptypes, "callable", "MAY_BE_CALLABLE"); + Setattr(phptypes, "float", "MAY_BE_DOUBLE"); + Setattr(phptypes, "int", "MAY_BE_LONG"); + Setattr(phptypes, "iterable", "MAY_BE_ITERABLE"); + Setattr(phptypes, "mixed", "MAY_BE_MIXED"); + Setattr(phptypes, "null", "MAY_BE_NULL"); + Setattr(phptypes, "object", "MAY_BE_OBJECT"); + Setattr(phptypes, "resource", "MAY_BE_RESOURCE"); + Setattr(phptypes, "string", "MAY_BE_STRING"); + Setattr(phptypes, "void", "MAY_BE_VOID"); + } - PHPTypes(const PHPTypes *o) - : merged_types(Copy(o->merged_types)), byref(Copy(o->byref)) { } - - ~PHPTypes() { + void reset() { Delete(merged_types); + merged_types = NewList(); Delete(byref); + byref = NULL; } // key is 0 for return type, or >= 1 for parameters numbered from 1 @@ -243,7 +238,7 @@ public: // Skip duplicates when merging. continue; } - String *c = Getattr(php_type_flags, i.item); + String *c = Getattr(phptypes, i.item); if (c) { if (Len(result) > 0) Append(result, "|"); Append(result, c); @@ -277,18 +272,9 @@ public: } }; -static PHPTypes *phptypes = NULL; - -// Track if the current phptypes is for a non-class function. -static PHPTypes *non_class_phptypes = NULL; - -// class + ":" + method -> PHPTypes* -static Hash *all_phptypes = NewHash(); - -// php_class_name -> php_parent_class_name -static Hash *php_parent_class = NewHash(); - class PHP : public Language { + PHPTypes phptypes; + public: PHP() { director_language = 1; @@ -742,7 +728,7 @@ public: // it inherits from is directed, which is what we care about here. // Using (!is_member_director(n)) would get it wrong for testcase // director_frob. - out_phptype = phptypes->get_phptype(0, out_phpclasses); + out_phptype = phptypes.get_phptype(0, out_phpclasses); } } @@ -777,17 +763,17 @@ public: String *phpclasses = NewStringEmpty(); String *phptype = NULL; if (GetFlag(n, "feature:php:type")) { - phptype = phptypes->get_phptype(param_count, phpclasses); + phptype = phptypes.get_phptype(param_count, phpclasses); } int byref; if (!dispatch) { byref = GetFlag(p, "tmap:in:byref"); - if (byref) phptypes->set_byref(param_count); + if (byref) phptypes.set_byref(param_count); } else { // If any overload takes a particular parameter by reference then the // dispatch function also needs to take that parameter by reference. - byref = phptypes->get_byref(param_count); + byref = phptypes.get_byref(param_count); } // FIXME: Should we be doing byref for return value as well? @@ -1155,6 +1141,12 @@ public: return SWIG_ERROR; } + if (!Getattr(n, "sym:previousSibling")) { + // First function of an overloaded group or a function which isn't part + // of a group so reset the phptype information. + phptypes.reset(); + } + if (constructor) { wname = NewString("__construct"); } else if (wrapperType == membervar) { @@ -1205,40 +1197,6 @@ public: return SWIG_OK; } - if (!Getattr(n, "sym:previousSibling")) { - // First function of an overloaded group or a function which isn't part - // of a group so reset the phptype information. - if (non_class_phptypes) { - delete non_class_phptypes; - non_class_phptypes = NULL; - } - phptypes = NULL; - - if (class_name) { - // See if there's a parent class which implements this method, and if - // so copy the PHPTypes of that method as a starting point as we need - // to be compatible with it (whether it is virtual or not). - String *parent = class_name; - while ((parent = Getattr(php_parent_class, parent)) != NULL) { - String *key = NewStringf("%s:%s", parent, wname); - PHPTypes *p = (PHPTypes*)GetVoid(all_phptypes, key); - Delete(key); - if (p) { - phptypes = new PHPTypes(p); - break; - } - } - } - if (!phptypes) { - phptypes = new PHPTypes(); - } - if (class_name) { - SetVoid(all_phptypes, NewStringf("%s:%s", class_name, wname), phptypes); - } else { - non_class_phptypes = phptypes; - } - } - f = NewWrapper(); if (static_getter) { @@ -1355,7 +1313,7 @@ public: continue; } - phptypes->process_phptype(p, i + 1, "tmap:in:phptype"); + phptypes.process_phptype(p, i + 1, "tmap:in:phptype"); String *source = NewStringf("args[%d]", i); Replaceall(tm, "$input", source); @@ -1441,7 +1399,7 @@ public: } emit_return_variable(n, d, f); - phptypes->process_phptype(n, 0, "tmap:out:phptype"); + phptypes.process_phptype(n, 0, "tmap:out:phptype"); if (outarg) { Printv(f->code, outarg, NIL); @@ -1685,7 +1643,6 @@ public: Printf(s_oinit, " SWIG_Php_ce_%s = zend_register_internal_class_ex(&internal_ce, zend_ce_exception);\n", class_name); } else if (is_class_wrapped(base_class)) { Printf(s_oinit, " SWIG_Php_ce_%s = zend_register_internal_class_ex(&internal_ce, SWIG_Php_ce_%s);\n", class_name, base_class); - Setattr(php_parent_class, class_name, base_class); } else { Printf(s_oinit, " SWIG_Php_ce_%s = zend_register_internal_class(&internal_ce);\n", class_name); } From 2de2efb0bbbd982c22db41d184404357e7b5009c Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Thu, 9 Jun 2022 14:39:51 +1200 Subject: [PATCH 470/662] Fix PHP parameter type declarations compatibility Ensure PHP parameter type declarations are compatible with those for the same method in any classes we inherit from. See #2151 --- .../test-suite/php/director_classes_runme.php | 79 ++++++++++++ Source/Modules/php.cxx | 113 ++++++++++++------ 2 files changed, 157 insertions(+), 35 deletions(-) create mode 100644 Examples/test-suite/php/director_classes_runme.php diff --git a/Examples/test-suite/php/director_classes_runme.php b/Examples/test-suite/php/director_classes_runme.php new file mode 100644 index 000000000..6a1d8a557 --- /dev/null +++ b/Examples/test-suite/php/director_classes_runme.php @@ -0,0 +1,79 @@ +set($base); + $dh = new DoubleHolder(444.555); + check::equal($caller->ValCall($dh)->val, $dh->val, "$bname.Val"); + check::equal($caller->RefCall($dh)->val, $dh->val, "$bname.Ref"); + check::equal($caller->PtrCall($dh)->val, $dh->val, "$bname.Ptr"); + check::equal($caller->ConstPtrRefCall($dh)->val, $dh->val, "$bname.ConstPtrRef"); + check::equal($caller->FullyOverloadedCall(1), + "${bname}::FullyOverloaded(int)", + "$bname.FullyOverloaded(int)"); + check::equal($caller->FullyOverloadedCall(false), + "${bname}::FullyOverloaded(bool)", + "$bname.FullyOverloaded(bool)"); + // This next one is TODO for Perl with PerlDerived. + check::equal($caller->SemiOverloadedCall(-678), + "${bname}::SemiOverloaded(int)", + "$bname.SemiOverloaded(int)"); + check::equal($caller->SemiOverloadedCall(false), + "Base::SemiOverloaded(bool)", + "$bname.SemiOverloaded(bool)"); + check::equal($caller->DefaultParmsCall(10, 2.2), + "${bname}::DefaultParms(int, double)", + "$bname.DefaultParms(int, double)"); + check::equal($caller->DefaultParmsCall(10), + "${bname}::DefaultParms(int)", + "$bname.DefaultParms(int)"); + $caller->reset(); +} + +check::done(); diff --git a/Source/Modules/php.cxx b/Source/Modules/php.cxx index 7b4d823fa..bbdd95249 100644 --- a/Source/Modules/php.cxx +++ b/Source/Modules/php.cxx @@ -185,10 +185,27 @@ static void SwigPHP_emit_pointer_type_registrations() { } } +static Hash *create_php_type_flags() { + Hash *h = NewHash(); + Setattr(h, "array", "MAY_BE_ARRAY"); + Setattr(h, "bool", "MAY_BE_BOOL"); + Setattr(h, "callable", "MAY_BE_CALLABLE"); + Setattr(h, "float", "MAY_BE_DOUBLE"); + Setattr(h, "int", "MAY_BE_LONG"); + Setattr(h, "iterable", "MAY_BE_ITERABLE"); + Setattr(h, "mixed", "MAY_BE_MIXED"); + Setattr(h, "null", "MAY_BE_NULL"); + Setattr(h, "object", "MAY_BE_OBJECT"); + Setattr(h, "resource", "MAY_BE_RESOURCE"); + Setattr(h, "string", "MAY_BE_STRING"); + Setattr(h, "void", "MAY_BE_VOID"); + return h; +} + +static Hash *php_type_flags = create_php_type_flags(); + // Class encapsulating the machinery to add PHP type declarations. class PHPTypes { - Hash *phptypes; - // List with an entry for each parameter and one for the return type. // // We assemble the types in here before emitting them so for an overloaded @@ -201,26 +218,14 @@ class PHPTypes { List *byref; public: - PHPTypes() : phptypes(NewHash()), merged_types(NULL), byref(NULL) { - Setattr(phptypes, "array", "MAY_BE_ARRAY"); - Setattr(phptypes, "bool", "MAY_BE_BOOL"); - Setattr(phptypes, "callable", "MAY_BE_CALLABLE"); - Setattr(phptypes, "float", "MAY_BE_DOUBLE"); - Setattr(phptypes, "int", "MAY_BE_LONG"); - Setattr(phptypes, "iterable", "MAY_BE_ITERABLE"); - Setattr(phptypes, "mixed", "MAY_BE_MIXED"); - Setattr(phptypes, "null", "MAY_BE_NULL"); - Setattr(phptypes, "object", "MAY_BE_OBJECT"); - Setattr(phptypes, "resource", "MAY_BE_RESOURCE"); - Setattr(phptypes, "string", "MAY_BE_STRING"); - Setattr(phptypes, "void", "MAY_BE_VOID"); - } + PHPTypes() : merged_types(NewList()), byref(NULL) { } - void reset() { + PHPTypes(const PHPTypes *o) + : merged_types(Copy(o->merged_types)), byref(Copy(o->byref)) { } + + ~PHPTypes() { Delete(merged_types); - merged_types = NewList(); Delete(byref); - byref = NULL; } // key is 0 for return type, or >= 1 for parameters numbered from 1 @@ -238,7 +243,7 @@ public: // Skip duplicates when merging. continue; } - String *c = Getattr(phptypes, i.item); + String *c = Getattr(php_type_flags, i.item); if (c) { if (Len(result) > 0) Append(result, "|"); Append(result, c); @@ -272,9 +277,18 @@ public: } }; -class PHP : public Language { - PHPTypes phptypes; +static PHPTypes *phptypes = NULL; +// Track if the current phptypes is for a non-class function. +static PHPTypes *non_class_phptypes = NULL; + +// class + ":" + method -> PHPTypes* +static Hash *all_phptypes = NewHash(); + +// php_class_name -> php_parent_class_name +static Hash *php_parent_class = NewHash(); + +class PHP : public Language { public: PHP() { director_language = 1; @@ -728,7 +742,7 @@ public: // it inherits from is directed, which is what we care about here. // Using (!is_member_director(n)) would get it wrong for testcase // director_frob. - out_phptype = phptypes.get_phptype(0, out_phpclasses); + out_phptype = phptypes->get_phptype(0, out_phpclasses); } } @@ -763,17 +777,17 @@ public: String *phpclasses = NewStringEmpty(); String *phptype = NULL; if (GetFlag(n, "feature:php:type")) { - phptype = phptypes.get_phptype(param_count, phpclasses); + phptype = phptypes->get_phptype(param_count, phpclasses); } int byref; if (!dispatch) { byref = GetFlag(p, "tmap:in:byref"); - if (byref) phptypes.set_byref(param_count); + if (byref) phptypes->set_byref(param_count); } else { // If any overload takes a particular parameter by reference then the // dispatch function also needs to take that parameter by reference. - byref = phptypes.get_byref(param_count); + byref = phptypes->get_byref(param_count); } // FIXME: Should we be doing byref for return value as well? @@ -1141,12 +1155,6 @@ public: return SWIG_ERROR; } - if (!Getattr(n, "sym:previousSibling")) { - // First function of an overloaded group or a function which isn't part - // of a group so reset the phptype information. - phptypes.reset(); - } - if (constructor) { wname = NewString("__construct"); } else if (wrapperType == membervar) { @@ -1197,6 +1205,40 @@ public: return SWIG_OK; } + if (!Getattr(n, "sym:previousSibling") && !static_getter) { + // First function of an overloaded group or a function which isn't part + // of a group so reset the phptype information. + if (non_class_phptypes) { + delete non_class_phptypes; + non_class_phptypes = NULL; + } + phptypes = NULL; + + if (class_name) { + // See if there's a parent class which implements this method, and if + // so copy the PHPTypes of that method as a starting point as we need + // to be compatible with it (whether it is virtual or not). + String *parent = class_name; + while ((parent = Getattr(php_parent_class, parent)) != NULL) { + String *key = NewStringf("%s:%s", parent, wname); + PHPTypes *p = (PHPTypes*)GetVoid(all_phptypes, key); + Delete(key); + if (p) { + phptypes = new PHPTypes(p); + break; + } + } + } + if (!phptypes) { + phptypes = new PHPTypes(); + } + if (class_name) { + SetVoid(all_phptypes, NewStringf("%s:%s", class_name, wname), phptypes); + } else { + non_class_phptypes = phptypes; + } + } + f = NewWrapper(); if (static_getter) { @@ -1313,7 +1355,7 @@ public: continue; } - phptypes.process_phptype(p, i + 1, "tmap:in:phptype"); + phptypes->process_phptype(p, i + 1, "tmap:in:phptype"); String *source = NewStringf("args[%d]", i); Replaceall(tm, "$input", source); @@ -1399,7 +1441,7 @@ public: } emit_return_variable(n, d, f); - phptypes.process_phptype(n, 0, "tmap:out:phptype"); + phptypes->process_phptype(n, 0, "tmap:out:phptype"); if (outarg) { Printv(f->code, outarg, NIL); @@ -1450,7 +1492,7 @@ public: dispatchFunction(n, constructor); } } else { - if (!static_getter) { + if (!static_setter) { create_command(class_name, wname, n, false, modes); } } @@ -1643,6 +1685,7 @@ public: Printf(s_oinit, " SWIG_Php_ce_%s = zend_register_internal_class_ex(&internal_ce, zend_ce_exception);\n", class_name); } else if (is_class_wrapped(base_class)) { Printf(s_oinit, " SWIG_Php_ce_%s = zend_register_internal_class_ex(&internal_ce, SWIG_Php_ce_%s);\n", class_name, base_class); + Setattr(php_parent_class, class_name, base_class); } else { Printf(s_oinit, " SWIG_Php_ce_%s = zend_register_internal_class(&internal_ce);\n", class_name); } From 14df91f8a0e47ce403593b6571c5fa935d1be3cf Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Fri, 10 Jun 2022 12:01:23 +1200 Subject: [PATCH 471/662] Fix new director_classes_runme.php for PHP7 --- .../test-suite/php/director_classes_runme.php | 75 +++++++++++++------ 1 file changed, 53 insertions(+), 22 deletions(-) diff --git a/Examples/test-suite/php/director_classes_runme.php b/Examples/test-suite/php/director_classes_runme.php index 6a1d8a557..0901107f7 100644 --- a/Examples/test-suite/php/director_classes_runme.php +++ b/Examples/test-suite/php/director_classes_runme.php @@ -8,30 +8,61 @@ check::classes(array('director_classes', 'Base', 'BaseClass', 'Caller', 'Derived // New vars check::globals(array('PrintDebug')); -class PHPDerived extends Base { - function Val(DoubleHolder $x) { return $x; } - function Ref(DoubleHolder $x) { return $x; } - function Ptr(?DoubleHolder $x) { var_dump($x); return $x; } - function ConstPtrRef(?DoubleHolder $x) { return $x; } - function FullyOverloaded($x) { - $rv = parent::FullyOverloaded($x); - $rv = preg_replace('/Base/', 'PHPDerived', $rv); - return $rv; - } - function SemiOverloaded($x) { - # this is going to be awkward because we can't really - # semi-overload in PHP, but we can sort of fake it. - if (!is_int($x)) { - return parent::SemiOverloaded($x); +if (PHP_MAJOR_VERSION < 8) { + // Without type declarations since we don't generate them for PHP < 8 + // and we need to be compatible with method declarations in Base. + class PHPDerived extends Base { + function Val($x) { return $x; } + function Ref($x) { return $x; } + function Ptr($x) { var_dump($x); return $x; } + function ConstPtrRef($x) { return $x; } + function FullyOverloaded($x) { + $rv = parent::FullyOverloaded($x); + $rv = preg_replace('/Base/', 'PHPDerived', $rv); + return $rv; + } + function SemiOverloaded($x) { + # this is going to be awkward because we can't really + # semi-overload in PHP, but we can sort of fake it. + if (!is_int($x)) { + return parent::SemiOverloaded($x); + } + $rv = parent::SemiOverloaded($x); + $rv = preg_replace('/Base/', 'PHPDerived', $rv); + return $rv; + } + function DefaultParms($x, $y = 1.1) { + $rv = parent::DefaultParms($x, $y); + $rv = preg_replace('/Base/', 'PHPDerived', $rv); + return $rv; } - $rv = parent::SemiOverloaded($x); - $rv = preg_replace('/Base/', 'PHPDerived', $rv); - return $rv; } - function DefaultParms(int $x, float $y = 1.1) { - $rv = parent::DefaultParms($x, $y); - $rv = preg_replace('/Base/', 'PHPDerived', $rv); - return $rv; +} else { + class PHPDerived extends Base { + function Val(DoubleHolder $x) { return $x; } + function Ref(DoubleHolder $x) { return $x; } + function Ptr(?DoubleHolder $x) { var_dump($x); return $x; } + function ConstPtrRef(?DoubleHolder $x) { return $x; } + function FullyOverloaded($x) { + $rv = parent::FullyOverloaded($x); + $rv = preg_replace('/Base/', 'PHPDerived', $rv); + return $rv; + } + function SemiOverloaded($x) { + # this is going to be awkward because we can't really + # semi-overload in PHP, but we can sort of fake it. + if (!is_int($x)) { + return parent::SemiOverloaded($x); + } + $rv = parent::SemiOverloaded($x); + $rv = preg_replace('/Base/', 'PHPDerived', $rv); + return $rv; + } + function DefaultParms(int $x, float $y = 1.1) { + $rv = parent::DefaultParms($x, $y); + $rv = preg_replace('/Base/', 'PHPDerived', $rv); + return $rv; + } } } From b7f82d78e924d24aa79b27bbdba51c88c7f596ca Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Fri, 10 Jun 2022 13:38:00 +1200 Subject: [PATCH 472/662] Fix director_classes_runme.php for PHP 7.0 PHP 7.0 fails to parse `?` before a parameter type (meaning Nullable in newer versions), so just omit these parameter type declarations in the testcase until we drop PHP 7.0 support. Also drop some `var_dump($x);` left over from debugging this testcase. --- Examples/test-suite/php/director_classes_runme.php | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/Examples/test-suite/php/director_classes_runme.php b/Examples/test-suite/php/director_classes_runme.php index 0901107f7..f50544024 100644 --- a/Examples/test-suite/php/director_classes_runme.php +++ b/Examples/test-suite/php/director_classes_runme.php @@ -14,7 +14,7 @@ if (PHP_MAJOR_VERSION < 8) { class PHPDerived extends Base { function Val($x) { return $x; } function Ref($x) { return $x; } - function Ptr($x) { var_dump($x); return $x; } + function Ptr($x) { return $x; } function ConstPtrRef($x) { return $x; } function FullyOverloaded($x) { $rv = parent::FullyOverloaded($x); @@ -41,8 +41,12 @@ if (PHP_MAJOR_VERSION < 8) { class PHPDerived extends Base { function Val(DoubleHolder $x) { return $x; } function Ref(DoubleHolder $x) { return $x; } - function Ptr(?DoubleHolder $x) { var_dump($x); return $x; } - function ConstPtrRef(?DoubleHolder $x) { return $x; } + // PHP 7.0 fails to parse the `?` - revert once we drop 7.0 support: + // function Ptr(?DoubleHolder $x) { return $x; } + function Ptr($x) { return $x; } + // PHP 7.0 fails to parse the `?` - revert once we drop 7.0 support: + // function ConstPtrRef(?DoubleHolder $x) { return $x; } + function ConstPtrRef($x) { return $x; } function FullyOverloaded($x) { $rv = parent::FullyOverloaded($x); $rv = preg_replace('/Base/', 'PHPDerived', $rv); From 2df27036b71ef1fbb3b6a701450fa3e06a18381b Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Thu, 9 Jun 2022 17:42:21 +1200 Subject: [PATCH 473/662] [php] Skip directorout typemap if PHP exception pending Otherwise can end up with a second PHP exception if the directorout typemap doesn't accept PHP Null. `SWIG_fail` in this case results in us returning to PHP which then propagates the pending exception. This commit fixes a failure in smoketest.php in Xapian's PHP bindings, but I've not managed to come up with a reproducer which works for SWIG's testsuite. --- Source/Modules/php.cxx | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/Source/Modules/php.cxx b/Source/Modules/php.cxx index bbdd95249..faf4fe070 100644 --- a/Source/Modules/php.cxx +++ b/Source/Modules/php.cxx @@ -2249,11 +2249,13 @@ public: if (tm) tm = Copy(tm); } - if ((tm) && Len(tm) && (Strcmp(tm, "1") != 0)) { - Replaceall(tm, "$error", "EG(exception)"); - Printv(w->code, Str(tm), "\n", NIL); + if (!tm || Len(tm) == 0 || Equal(tm, "1")) { + // Skip marshalling the return value as there isn't one. + tm = NewString("if ($error) SWIG_fail;"); } - Append(w->code, "}\n"); + + Replaceall(tm, "$error", "EG(exception)"); + Printv(w->code, Str(tm), "\n}\n{\n", NIL); Delete(tm); /* marshal return value from PHP to C/C++ type */ @@ -2301,6 +2303,8 @@ public: } } + Append(w->code, "}\n"); + Delete(cleanup); Delete(outarg); } From c95df57976f0d64392565b1ce06496a7fc12f9fe Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Sun, 12 Jun 2022 09:22:27 +1200 Subject: [PATCH 474/662] [php] Fix missing parameter type declarations In some cases of overloaded functions the parameter type information was missing for some or all parameters. See #2151 --- .../test-suite/php/default_args_runme.php | 141 ++++++++++++++++++ Source/Modules/php.cxx | 41 ++--- 2 files changed, 154 insertions(+), 28 deletions(-) create mode 100644 Examples/test-suite/php/default_args_runme.php diff --git a/Examples/test-suite/php/default_args_runme.php b/Examples/test-suite/php/default_args_runme.php new file mode 100644 index 000000000..944426e29 --- /dev/null +++ b/Examples/test-suite/php/default_args_runme.php @@ -0,0 +1,141 @@ +blah(), true, "EnumClass::blah() default arguments don't work"); + +$de = new DerivedEnumClass(); +$de->accelerate(); +$de->accelerate(EnumClass::SLOW); + +check::equal(Statics::staticMethod(), 60, "Statics::staticMethod()"); + +check::equal(cfunc1(1), 2.0, "cfunc1(1)"); + +check::equal(cfunc2(1), 3.0, "cfunc2(1)"); + +check::equal(cfunc3(1), 4.0, "cfunc3(1)"); + +$f = new Foo(); + +$f->newname(); +$f->newname(1); +$f->defaulted1(); +$f->defaulted2(); + +check::equal($f->double_if_void_ptr_is_null(2, Null), 4, "\$f->double_if_void_ptr_is_null(2, Null)"); + +check::equal($f->double_if_void_ptr_is_null(3), 6, "\$f->double_if_void_ptr_is_null(3)"); + +check::equal($f->double_if_void_ptr_is_null(4, Null), 8, "\$f->double_if_void_ptr_is_null(4, Null)"); + +check::equal($f->double_if_void_ptr_is_null(5, Null), 10, "\$f->double_if_void_ptr_is_null(5, Null)"); + +check::equal($f->double_if_void_ptr_is_null(6, Null), 12, "\$f->double_if_void_ptr_is_null(6, Null)"); + +check::equal($f->double_if_void_ptr_is_null(7), 14, "\$f->double_if_void_ptr_is_null(7)"); + +try { + $f = new Foo(1); + check::fail("Foo::Foo ignore is not working"); +} catch (ArgumentCountError $e) { +} + +try { + $f = new Foo(1, 2); + check::fail("Foo::Foo ignore is not working"); +} catch (ArgumentCountError $e) { +} + +try { + $f = new Foo(1, 2, 3); + check::fail("Foo::Foo ignore is not working"); +} catch (ArgumentCountError $e) { +} + +try { + $m = $f->meth(1); + check::fail("Foo::meth ignore is not working"); +} catch (Error $e) { +} + +try { + $m = $f->meth(1, 2); + check::fail("Foo::meth ignore is not working"); +} catch (Error $e) { +} + +try { + $m = $f->meth(1, 2, 3); + check::fail("Foo::meth ignore is not working"); +} catch (Error $e) { +} + +check::equal(Klass::inc(100, new Klass(22))->val, 122, "Klass::inc failed"); + +check::equal(klass::inc(100)->val, 99, "klass::inc failed"); + +check::equal(klass::inc()->val, 0, "klass::inc failed"); + +$tricky = new TrickyInPython(); +check::equal($tricky->value_m1(10), -1, "trickyvalue_m1 failed"); +check::equal($tricky->value_m1(10, 10), 10, "trickyvalue_m1 failed"); +check::equal($tricky->value_0xabcdef(10), 0xabcdef, "trickyvalue_0xabcdef failed"); +check::equal($tricky->value_0644(10), 420, "trickyvalue_0644 failed"); +check::equal($tricky->value_perm(10), 420, "trickyvalue_perm failed"); +check::equal($tricky->value_m01(10), -1, "trickyvalue_m01 failed"); +check::equal($tricky->booltest2(), True, "booltest2 failed"); + +check::equal($tricky->max_32bit_int1(), 0x7FFFFFFF, "max_32bit_int1 failed"); +check::equal($tricky->min_32bit_int1(), -2147483648, "min_32bit_int1 failed"); +check::equal($tricky->max_32bit_int2(), 0x7FFFFFFF, "max_32bit_int2 failed"); + +$tricky->too_big_32bit_int1(); +$tricky->too_small_32bit_int1(); +$tricky->too_big_32bit_int2(); +$tricky->too_small_32bit_int2(); + +seek(); +seek(10); + +check::equal(booltest(), True, "booltest failed"); + +check::equal(slightly_off_square(10), 102, "slightly_off_square(10)"); + +check::equal(slightly_off_square(), 291, "slightly_off_square()"); + +check::equal(chartest1(), "x", "chartest1()"); + +check::equal(chartest2(), "\0", "chartest2()"); + +check::equal(chartest3(), "\1", "chartest3()"); + +check::equal(chartest4(), "\n", "chartest4()"); + +check::equal(chartest5(), "B", "chartest5()"); + +check::equal(chartest6(), "C", "chartest6()"); + +if (PHP_MAJOR_VERSION >= 8) { + // Regression test for bug in initial implementation of PHP type declarations. + $p = (new ReflectionMethod('TrickyInPython', 'value_m1'))->getParameters(); + // empty array in buggy version + check::equal(count($p), 2, "Expected 2 parameters"); + check::equal((string)$p[0]->getType(), 'int', "Expected int parameter"); + check::equal((string)$p[1]->getType(), 'int', "Expected int parameter"); + + $p = (new ReflectionMethod('EnumClass', 'blah'))->getParameters(); + // empty array in buggy version + check::equal(count($p), 2, "Expected 2 parameters"); + check::equal((string)$p[0]->getType(), 'int', "Expected int parameter"); + check::equal((string)$p[1]->getType(), 'int', "Expected int parameter"); +} + +check::done(); diff --git a/Source/Modules/php.cxx b/Source/Modules/php.cxx index faf4fe070..d0c337a6a 100644 --- a/Source/Modules/php.cxx +++ b/Source/Modules/php.cxx @@ -13,6 +13,7 @@ */ #include "swigmod.h" +#include #include #include @@ -269,12 +270,19 @@ public: while (Len(byref) <= key) { Append(byref, None); } + // If any overload takes a particular parameter by reference then the + // dispatch function also needs to take that parameter by reference so + // we can just set unconditionally here. Setitem(byref, key, ""); // Just needs to be something != None. } int get_byref(int key) const { return byref && key < Len(byref) && Getitem(byref, key) != None; } + + int size() const { + return std::max(Len(merged_types), Len(byref)); + } }; static PHPTypes *phptypes = NULL; @@ -759,36 +767,12 @@ public: Printf(arginfo_code, "ZEND_BEGIN_ARG_INFO_EX(swig_arginfo_###, 0, 0, %d)\n", num_required); } - if (Getattr(n, "defaultargs")) { - // Include parameters with default values in the arginfo. - l = Getattr(Getattr(n, "defaultargs"), "parms"); - } - int param_count = 0; - for (Parm *p = l; p; p = Getattr(p, "tmap:in:next")) { - String *tmap_in_numinputs = Getattr(p, "tmap:in:numinputs"); - // tmap:in:numinputs is unset for varargs, which we don't count here. - if (!tmap_in_numinputs || Equal(tmap_in_numinputs, "0")) { - /* Ignored parameter */ - continue; - } - - ++param_count; - + int phptypes_size = phptypes->size(); + for (int param_count = 1; param_count < phptypes_size; ++param_count) { String *phpclasses = NewStringEmpty(); - String *phptype = NULL; - if (GetFlag(n, "feature:php:type")) { - phptype = phptypes->get_phptype(param_count, phpclasses); - } + String *phptype = phptypes->get_phptype(param_count, phpclasses); - int byref; - if (!dispatch) { - byref = GetFlag(p, "tmap:in:byref"); - if (byref) phptypes->set_byref(param_count); - } else { - // If any overload takes a particular parameter by reference then the - // dispatch function also needs to take that parameter by reference. - byref = phptypes->get_byref(param_count); - } + int byref = phptypes->get_byref(param_count); // FIXME: Should we be doing byref for return value as well? @@ -1356,6 +1340,7 @@ public: } phptypes->process_phptype(p, i + 1, "tmap:in:phptype"); + if (GetFlag(p, "tmap:in:byref")) phptypes->set_byref(i + 1); String *source = NewStringf("args[%d]", i); Replaceall(tm, "$input", source); From 3a84a4dd96d320cbbaa9d51bf5ebea94dc0ef6fb Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Sun, 12 Jun 2022 10:19:15 +1200 Subject: [PATCH 475/662] [php] Fix new default_args_runme.php for PHP < 7.3 --- .../test-suite/php/default_args_runme.php | 34 ++++++++++++------- 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/Examples/test-suite/php/default_args_runme.php b/Examples/test-suite/php/default_args_runme.php index 944426e29..3e3f2f31a 100644 --- a/Examples/test-suite/php/default_args_runme.php +++ b/Examples/test-suite/php/default_args_runme.php @@ -42,39 +42,49 @@ check::equal($f->double_if_void_ptr_is_null(6, Null), 12, "\$f->double_if_void_p check::equal($f->double_if_void_ptr_is_null(7), 14, "\$f->double_if_void_ptr_is_null(7)"); +# For the testcases below PHP < 7.3 emits an error, while newer versions throw +# an exception. We handle the older versions by suppressing the error with `@`, +# then checking for the created object being Null if the PHP version is < 7.3. + try { - $f = new Foo(1); - check::fail("Foo::Foo ignore is not working"); + @$f = new Foo(1); + if (!(PHP_MAJOR_VERSION == 7 && PHP_MINOR_VERSION < 3 && $f === null)) + check::fail("Foo::Foo ignore is not working"); } catch (ArgumentCountError $e) { } try { - $f = new Foo(1, 2); - check::fail("Foo::Foo ignore is not working"); + @$f = new Foo(1, 2); + if (!(PHP_MAJOR_VERSION == 7 && PHP_MINOR_VERSION < 3 && $f === null)) + check::fail("Foo::Foo ignore is not working"); } catch (ArgumentCountError $e) { } try { - $f = new Foo(1, 2, 3); - check::fail("Foo::Foo ignore is not working"); + @$f = new Foo(1, 2, 3); + if (!(PHP_MAJOR_VERSION == 7 && PHP_MINOR_VERSION < 3 && $f === null)) + check::fail("Foo::Foo ignore is not working"); } catch (ArgumentCountError $e) { } try { - $m = $f->meth(1); - check::fail("Foo::meth ignore is not working"); + @$m = $f->meth(1); + if (!(PHP_MAJOR_VERSION == 7 && PHP_MINOR_VERSION < 3 && $f === null)) + check::fail("Foo::meth ignore is not working"); } catch (Error $e) { } try { - $m = $f->meth(1, 2); - check::fail("Foo::meth ignore is not working"); + @$m = $f->meth(1, 2); + if (!(PHP_MAJOR_VERSION == 7 && PHP_MINOR_VERSION < 3 && $f === null)) + check::fail("Foo::meth ignore is not working"); } catch (Error $e) { } try { - $m = $f->meth(1, 2, 3); - check::fail("Foo::meth ignore is not working"); + @$m = $f->meth(1, 2, 3); + if (!(PHP_MAJOR_VERSION == 7 && PHP_MINOR_VERSION < 3 && $f === null)) + check::fail("Foo::meth ignore is not working"); } catch (Error $e) { } From cdcb8cc9eef34001110bd9d5ebc636ca8975c747 Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Sun, 12 Jun 2022 15:02:26 +1200 Subject: [PATCH 476/662] [php] Try again to fix default_args_runme.php for PHP7 --- .../test-suite/php/default_args_runme.php | 38 ++++++++++--------- 1 file changed, 20 insertions(+), 18 deletions(-) diff --git a/Examples/test-suite/php/default_args_runme.php b/Examples/test-suite/php/default_args_runme.php index 3e3f2f31a..0ace7e45a 100644 --- a/Examples/test-suite/php/default_args_runme.php +++ b/Examples/test-suite/php/default_args_runme.php @@ -46,48 +46,50 @@ check::equal($f->double_if_void_ptr_is_null(7), 14, "\$f->double_if_void_ptr_is_ # an exception. We handle the older versions by suppressing the error with `@`, # then checking for the created object being Null if the PHP version is < 7.3. +if (PHP_MAJOR_VERSION == 7) { + $old_error_handler = set_error_handler(function($n,$s,$f,$l){throw preg_match('/^Wrong parameter count/', $s) ? new ArgumentCountError($s) : new Error($s);}); +} + try { - @$f = new Foo(1); - if (!(PHP_MAJOR_VERSION == 7 && PHP_MINOR_VERSION < 3 && $f === null)) - check::fail("Foo::Foo ignore is not working"); + $f = new Foo(1); + check::fail("Foo::Foo ignore is not working"); } catch (ArgumentCountError $e) { } try { - @$f = new Foo(1, 2); - if (!(PHP_MAJOR_VERSION == 7 && PHP_MINOR_VERSION < 3 && $f === null)) - check::fail("Foo::Foo ignore is not working"); + $f = new Foo(1, 2); + check::fail("Foo::Foo ignore is not working"); } catch (ArgumentCountError $e) { } try { - @$f = new Foo(1, 2, 3); - if (!(PHP_MAJOR_VERSION == 7 && PHP_MINOR_VERSION < 3 && $f === null)) - check::fail("Foo::Foo ignore is not working"); + $f = new Foo(1, 2, 3); + check::fail("Foo::Foo ignore is not working"); } catch (ArgumentCountError $e) { } try { - @$m = $f->meth(1); - if (!(PHP_MAJOR_VERSION == 7 && PHP_MINOR_VERSION < 3 && $f === null)) - check::fail("Foo::meth ignore is not working"); + $m = $f->meth(1); + check::fail("Foo::meth ignore is not working"); } catch (Error $e) { } try { - @$m = $f->meth(1, 2); - if (!(PHP_MAJOR_VERSION == 7 && PHP_MINOR_VERSION < 3 && $f === null)) - check::fail("Foo::meth ignore is not working"); + $m = $f->meth(1, 2); + check::fail("Foo::meth ignore is not working"); } catch (Error $e) { } try { - @$m = $f->meth(1, 2, 3); - if (!(PHP_MAJOR_VERSION == 7 && PHP_MINOR_VERSION < 3 && $f === null)) - check::fail("Foo::meth ignore is not working"); + $m = $f->meth(1, 2, 3); + check::fail("Foo::meth ignore is not working"); } catch (Error $e) { } +if (PHP_MAJOR_VERSION == 7) { + set_error_handler($old_error_handler); +} + check::equal(Klass::inc(100, new Klass(22))->val, 122, "Klass::inc failed"); check::equal(klass::inc(100)->val, 99, "klass::inc failed"); From b41fede82715b216a97be825c87dd08dc92ef98e Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Sun, 12 Jun 2022 15:27:49 +1200 Subject: [PATCH 477/662] [php] Fix default_args_runme.php for PHP7.0 --- Examples/test-suite/php/default_args_runme.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Examples/test-suite/php/default_args_runme.php b/Examples/test-suite/php/default_args_runme.php index 0ace7e45a..cd0ec8127 100644 --- a/Examples/test-suite/php/default_args_runme.php +++ b/Examples/test-suite/php/default_args_runme.php @@ -47,6 +47,10 @@ check::equal($f->double_if_void_ptr_is_null(7), 14, "\$f->double_if_void_ptr_is_ # then checking for the created object being Null if the PHP version is < 7.3. if (PHP_MAJOR_VERSION == 7) { + if (PHP_MINOR_VERSION == 0) { + # ArgumentCountError was added in PHP 7.1. + class ArgumentCountError extends Error {} + } $old_error_handler = set_error_handler(function($n,$s,$f,$l){throw preg_match('/^Wrong parameter count/', $s) ? new ArgumentCountError($s) : new Error($s);}); } From 9cdf46e8c8c45bc6d1035fefa7639194e73a075a Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Sun, 12 Jun 2022 10:12:02 +1200 Subject: [PATCH 478/662] [php] Adjust #required params for subclass methods If the same method name is implemented in a parent class then the subclass can't have more required parameters than that or else we get a compatibility error when the module is loaded. The testsuite wasn't catching this problem because it was no longer trying to load the modules for testcases without _runme.php, because the mechanism to do that relied on there being a generated .php wrapper, which we no longer have by default. Fix that to provide a regression test for this fix. See #2151 --- Examples/Makefile.in | 2 +- Examples/test-suite/php/Makefile.in | 12 +++++----- .../php/director_abstract_runme.php | 6 ++--- .../test-suite/php/director_stl_runme.php | 2 +- Source/Modules/php.cxx | 22 +++++++++++++++---- 5 files changed, 29 insertions(+), 15 deletions(-) diff --git a/Examples/Makefile.in b/Examples/Makefile.in index d7b9a5bcf..532152e80 100644 --- a/Examples/Makefile.in +++ b/Examples/Makefile.in @@ -1071,7 +1071,7 @@ php_cpp: $(SRCDIR_SRCS) # ----------------------------------------------------------------- php_run: - $(RUNTOOL) $(PHP) -n -d extension_dir=. -d extension=$(PHP_EXTENSION) -d display_errors=stderr -r 'set_error_handler(function($$n,$$s,$$f,$$l){if($$f!==Null){print$$f;if($$l!==Null)print":$$l";print": ";}print"$$s\n";exit(1);});include($$argv[1]);' $(PHP_SCRIPT) $(RUNPIPE) + $(RUNTOOL) $(PHP) -n -d extension_dir=. -d extension=$(PHP_EXTENSION) -d display_errors=stderr -r 'set_error_handler(function($$n,$$s,$$f,$$l){if($$f!==Null){print$$f;if($$l!==Null)print":$$l";print": ";}print"$$s\n";exit(1);});if(strlen($$argv[1]))include($$argv[1]);' '$(PHP_SCRIPT)' $(RUNPIPE) # ----------------------------------------------------------------- # Version display diff --git a/Examples/test-suite/php/Makefile.in b/Examples/test-suite/php/Makefile.in index c460bff28..6a2a4590b 100644 --- a/Examples/test-suite/php/Makefile.in +++ b/Examples/test-suite/php/Makefile.in @@ -68,18 +68,18 @@ missingtests: missingcpptests missingctests @echo ' $(MULTI_CPP_TEST_CASES) '|grep -F -v ' $* ' >/dev/null ||\ $(MAKE) $*.multicpptest -# Runs the testcase. Tries to run testcase_runme.php, and if that's not -# found, runs testcase.php, except for multicpptests. +# Runs the testcase. Tries to run testcase_runme.php, and if that's not found, +# at least test that the module loads without errors, except for multicpptests. run_testcase = \ if [ -f $(SCRIPTDIR)/$(SCRIPTPREFIX)$*$(SCRIPTSUFFIX) ]; then \ $(MAKE) -f $(top_builddir)/$(EXAMPLES)/Makefile PHP_EXTENSION=$(TARGETPREFIX)$*@PHP_SO@ PHP_SCRIPT=$(SCRIPTDIR)/$(SCRIPTPREFIX)$*$(SCRIPTSUFFIX) RUNTOOL='$(RUNTOOL)' php_run; \ - elif [ -f $(SCRIPTDIR)/$(SCRIPTPREFIX)$*.php -a ! -f $(top_srcdir)/$(EXAMPLES)/$(TEST_SUITE)/$*.list ]; then \ - $(MAKE) -f $(top_builddir)/$(EXAMPLES)/Makefile PHP_EXTENSION=$(TARGETPREFIX)$*@PHP_SO@ PHP_SCRIPT=$(SCRIPTDIR)/$(SCRIPTPREFIX)$*.php RUNTOOL='$(RUNTOOL)' php_run; \ + elif [ ! -f $(top_srcdir)/$(EXAMPLES)/$(TEST_SUITE)/$*.list ]; then \ + $(MAKE) -f $(top_builddir)/$(EXAMPLES)/Makefile PHP_EXTENSION=$(TARGETPREFIX)$*@PHP_SO@ PHP_SCRIPT= RUNTOOL='$(RUNTOOL)' php_run; \ fi -# Clean: remove the generated .php file +# Clean: remove the generated PHP-specific files %.clean: - @rm -f $*.php php_$*.h + @rm -f php_$*.h clean: $(MAKE) -f $(top_builddir)/$(EXAMPLES)/Makefile SRCDIR='$(SRCDIR)' php_clean diff --git a/Examples/test-suite/php/director_abstract_runme.php b/Examples/test-suite/php/director_abstract_runme.php index bb424f9ea..2d9799f2f 100644 --- a/Examples/test-suite/php/director_abstract_runme.php +++ b/Examples/test-suite/php/director_abstract_runme.php @@ -22,19 +22,19 @@ check::equal($a->ping(), "MyFoo::ping()", "MyFoo::ping failed"); check::equal($a->pong(), "Foo::pong();MyFoo::ping()", "MyFoo::pong failed"); class MyExample1 extends Example1 { - function Color($r, $g, $b) { + function Color($r, $g = NULL, $b = NULL) { return $r; } } class MyExample2 extends Example1 { - function Color($r, $g, $b) { + function Color($r, $g = NULL, $b = NULL) { return $g; } } class MyExample3 extends Example1 { - function Color($r, $g, $b) { + function Color($r, $g = NULL, $b = NULL) { return $b; } } diff --git a/Examples/test-suite/php/director_stl_runme.php b/Examples/test-suite/php/director_stl_runme.php index 654251a30..031a87ae7 100644 --- a/Examples/test-suite/php/director_stl_runme.php +++ b/Examples/test-suite/php/director_stl_runme.php @@ -26,7 +26,7 @@ class MyFoo extends Foo { return $v; } - function vsecond($v1, $v2) { + function vsecond($v1, $v2 = NULL) { return $v2; } } diff --git a/Source/Modules/php.cxx b/Source/Modules/php.cxx index d0c337a6a..c424572f1 100644 --- a/Source/Modules/php.cxx +++ b/Source/Modules/php.cxx @@ -218,17 +218,31 @@ class PHPTypes { // the dispatch function. If NULL, no parameters are passed by reference. List *byref; + // Used to clamp the required number of parameters in the arginfo to be + // compatible with any parent class version of the method. + int required_clamp; + public: - PHPTypes() : merged_types(NewList()), byref(NULL) { } + PHPTypes(int num_required) + : merged_types(NewList()), + byref(NULL), + required_clamp(num_required) { } PHPTypes(const PHPTypes *o) - : merged_types(Copy(o->merged_types)), byref(Copy(o->byref)) { } + : merged_types(Copy(o->merged_types)), + byref(Copy(o->byref)), + required_clamp(o->required_clamp) { } ~PHPTypes() { Delete(merged_types); Delete(byref); } + int adjust_num_required(int num_required) { + required_clamp = std::min(num_required, required_clamp); + return required_clamp; + } + // key is 0 for return type, or >= 1 for parameters numbered from 1 void process_phptype(Node *n, int key, const String_or_char *attribute_name); @@ -712,7 +726,7 @@ public: } } - int num_required = emit_num_required(l); + int num_required = phptypes->adjust_num_required(emit_num_required(l)); // We want to only emit each different arginfo once, as that reduces the // size of both the generated source code and the compiled extension @@ -1214,7 +1228,7 @@ public: } } if (!phptypes) { - phptypes = new PHPTypes(); + phptypes = new PHPTypes(emit_num_required(l)); } if (class_name) { SetVoid(all_phptypes, NewStringf("%s:%s", class_name, wname), phptypes); From 9b096e65612347d8497bca39eb54f003570e8130 Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Tue, 14 Jun 2022 17:40:12 +1200 Subject: [PATCH 479/662] WIP --- Examples/test-suite/php/Makefile.in | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Examples/test-suite/php/Makefile.in b/Examples/test-suite/php/Makefile.in index 6a2a4590b..9e34ccc3d 100644 --- a/Examples/test-suite/php/Makefile.in +++ b/Examples/test-suite/php/Makefile.in @@ -26,6 +26,13 @@ C_TEST_CASES += \ li_cdata_carrays \ multivalue \ +# These fail with PHP8 currently. Aiming to fix before 4.1 release. See #2181. +FAILING_CPP_TESTS = \ + director_redefined \ + director_using_member_scopes \ + using_composition \ + using_extend \ + include $(srcdir)/../common.mk # Overridden variables here From 088dc6e8707b45872c687c980349ece6866c0bfd Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Wed, 15 Jun 2022 08:45:29 +0100 Subject: [PATCH 480/662] Add move assignment operator to SwigValueWrapper Closes #2039 --- CHANGES.current | 4 + Examples/test-suite/common.mk | 1 + .../test-suite/cpp11_move_only_valuewrapper.i | 239 ++++++++++++++++++ .../cpp11_move_only_valuewrapper_runme.cs | 25 ++ Lib/swig.swg | 4 + 5 files changed, 273 insertions(+) create mode 100644 Examples/test-suite/cpp11_move_only_valuewrapper.i create mode 100644 Examples/test-suite/csharp/cpp11_move_only_valuewrapper_runme.cs diff --git a/CHANGES.current b/CHANGES.current index 35b0f7ee2..1e06bd85b 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-06-15: wsfulton + #2039 Add move assignment operator to SwigValueWrapper used by the + valuewrapper feature. + 2022-06-04: sethrj Enhance $typemap to support typemap attributes. diff --git a/Examples/test-suite/common.mk b/Examples/test-suite/common.mk index 69f38113f..003138010 100644 --- a/Examples/test-suite/common.mk +++ b/Examples/test-suite/common.mk @@ -597,6 +597,7 @@ CPP11_TEST_CASES += \ cpp11_initializer_list \ cpp11_initializer_list_extend \ cpp11_lambda_functions \ + cpp11_move_only_valuewrapper \ cpp11_noexcept \ cpp11_null_pointer_constant \ cpp11_raw_string_literals \ diff --git a/Examples/test-suite/cpp11_move_only_valuewrapper.i b/Examples/test-suite/cpp11_move_only_valuewrapper.i new file mode 100644 index 000000000..fb9f5dc31 --- /dev/null +++ b/Examples/test-suite/cpp11_move_only_valuewrapper.i @@ -0,0 +1,239 @@ +%module cpp11_move_only_valuewrapper + +/* + * This test case checks SwigValueWrapper and move assignment. + * Although not necessary, the test case was developed testing with C++98 compatibility for comparing improvements. + * C++11 and later is of course required for the move assignment support. + * C++98 is not actually necesary now as the test-suite only runs this test with compilers that support C++11 and later. +*/ + +%{ +#include +#include +using std::cout; +using std::endl; + +#if __cplusplus >= 201103L +#include +#else +namespace std { + // just something that will compile and vaguely work for when c++11 is not supported + template class unique_ptr { + T *ptr; + public: + unique_ptr(T *ptr = 0) : ptr(ptr) {} + unique_ptr(const unique_ptr &a) : ptr(a.ptr) { /*please look away*/ const_cast(a).ptr = 0;} + ~unique_ptr() { delete ptr; } + unique_ptr& operator=(const unique_ptr &a) { + if (&a != this) { + delete ptr; + ptr = a.ptr; + /*please look away*/ const_cast(a).ptr = 0; + } + return *this; + } + }; +} +#endif +%} + +%include + +%valuewrapper XXX; +%ignore XXX::operator=; +%catches(std::string) XXX::check_counts; + +%inline %{ +bool debug = false; +struct XXX { + XXX(int i = 0) { if (debug) cout << "XXX(" << i << ")" << " " << this << endl; normal_constructor_count++; } + XXX(const XXX &other) { if (debug) cout << "XXX(const XXX &)" << " " << this << " " << &other << endl; copy_constructor_count++;} + XXX & operator=(const XXX &other) { if (debug) cout << "operator=(const XXX &)" << " " << this << " " << &other << endl; copy_assignment_count++; return *this; } +#if defined(__cplusplus) && __cplusplus >= 201103L + XXX(XXX &&other) noexcept { if (debug) cout << "XXX(XXX &&)" << " " << this << endl; move_constructor_count++; } + XXX & operator=(XXX &&other) noexcept { if (debug) cout << "operator=(XXX &&)" << " " << this << endl; move_assignment_count++; return *this; } +#endif + ~XXX() { if (debug) cout << "~XXX()" << " " << this << endl; destructor_count++; } + static int normal_constructor_count; + static int copy_constructor_count; + static int copy_assignment_count; + static int move_constructor_count; + static int move_assignment_count; + static int destructor_count; + static void reset_counts() { + XXX::normal_constructor_count = 0; + XXX::copy_constructor_count = 0; + XXX::copy_assignment_count = 0; + XXX::move_constructor_count = 0; + XXX::move_assignment_count = 0; + XXX::destructor_count = 0; + } + // Check against expected counts of constructor, assignment operators etc. + // Not observed during development, but compiler optimisation could change the expected values. + // Throws exception if not correct (use %catches to catch them) + static void check_counts( + int normal_constructor_count, + int copy_constructor_count, + int copy_assignment_count, + int move_constructor_count, + int move_assignment_count, + int destructor_count) { + bool match = ( + normal_constructor_count == XXX::normal_constructor_count && + copy_constructor_count == XXX::copy_constructor_count && + copy_assignment_count == XXX::copy_assignment_count && + move_constructor_count == XXX::move_constructor_count && + move_assignment_count == XXX::move_assignment_count && + destructor_count == XXX::destructor_count); + if (!match) { + std::stringstream ss; + ss << "check_counts failed" << std::endl << + XXX::normal_constructor_count << " " << + XXX::copy_constructor_count << " " << + XXX::copy_assignment_count << " " << + XXX::move_constructor_count << " " << + XXX::move_assignment_count << " " << + XXX::destructor_count << " " << + " (actual)" << std::endl << + normal_constructor_count << " " << + copy_constructor_count << " " << + copy_assignment_count << " " << + move_constructor_count << " " << + move_assignment_count << " " << + destructor_count << " " << + " (expected)" << std::endl; + throw ss.str(); + } + } +}; + +int XXX::normal_constructor_count = 0; +int XXX::copy_constructor_count = 0; +int XXX::copy_assignment_count = 0; +int XXX::move_constructor_count = 0; +int XXX::move_assignment_count = 0; +int XXX::destructor_count = 0; +bool has_cplusplus11() { +#if __cplusplus >= 201103L + return true; +#else + return false; +#endif +} +%} + +#if defined(SWIGCSHARP) +%typemap(out) std::unique_ptr %{ + if (debug) cout << "out start" << endl; +#if __cplusplus >= 201103L + $result = new std::unique_ptr(std::move(static_cast&>($1))); +#else + $result = new std::unique_ptr((const std::unique_ptr &)$1); +#endif + if (debug) cout << "out done" << endl; +%} + +std::unique_ptr makeUniqueXXX(); +void cleanup(std::unique_ptr* p); +#endif + +%{ +std::unique_ptr makeUniqueXXX() { + if (debug) cout << "makeUniqueXXX()" << endl; + return std::unique_ptr(new XXX(11)); +} +void cleanup(std::unique_ptr* p) { + delete p; +} +%} + +%inline %{ +XXX createXXX() { + if (debug) cout << "createXXX()" << endl; + return XXX(111); +} +%} + + +%catches(std::string) test1; +%catches(std::string) test2; +%catches(std::string) test3; +%catches(std::string) test4; +%catches(std::string) test5; +%catches(std::string) test6; + +%inline %{ +// 'unit tests' for SwigValueWrapper +void test1() { + XXX::reset_counts(); + { + SwigValueWrapper x; + x = XXX(); + } +#if __cplusplus >= 201103L + XXX::check_counts(1, 0, 0, 1, 0, 2); // was same as < c++11 counts below before move assignment operator added to SwigValueWrapper +#else + XXX::check_counts(1, 1, 0, 0, 0, 2); +#endif +} +void test2() { + XXX::reset_counts(); + { + SwigValueWrapper x; + x = XXX(); + x = XXX(); + } +#if __cplusplus >= 201103L + XXX::check_counts(2, 0, 0, 2, 0, 4); +#else + XXX::check_counts(2, 2, 0, 0, 0, 4); +#endif +} +void test3() { + XXX::reset_counts(); + { + SwigValueWrapper x; + XXX a(999); +#if __cplusplus >= 201103L + x = std::move(a); +#endif + } +#if __cplusplus >= 201103L + XXX::check_counts(1, 0, 0, 1, 0, 2); +#endif +} +void test4() { + XXX::reset_counts(); + { + SwigValueWrapper > x; + x = std::unique_ptr(new XXX(444)); + } + XXX::check_counts(1, 0, 0, 0, 0, 1); +} +void test5() { +#if __cplusplus >= 201103L + XXX::reset_counts(); + { + SwigValueWrapper > x; + x = std::unique_ptr(new XXX(550)); + std::unique_ptr x2(new XXX(555)); + x = std::move(x2); + } + XXX::check_counts(2, 0, 0, 0, 0, 2); +#endif +} +void test6() { +#if __cplusplus >= 201103L + XXX::reset_counts(); + { + // emulates how std::unique_ptr typemaps could be wrapped with SwigValueWrapper + void *ptr = 0; + SwigValueWrapper > x; // SWIG generated if std::unique_ptr<> definition not parsed + x = makeUniqueXXX(); // SWIG generated code wrapping function returning std::unique_ptr + ptr = new std::unique_ptr(std::move((std::unique_ptr&)x)); // 'out' typemap (move std::unique_ptr from stack to the heap), note non-const cast std::unique_tr& + delete (std::unique_ptr *)ptr; // Final cleanup (user needs to call this) + } + XXX::check_counts(1, 0, 0, 0, 0, 1); +#endif +} +%} diff --git a/Examples/test-suite/csharp/cpp11_move_only_valuewrapper_runme.cs b/Examples/test-suite/csharp/cpp11_move_only_valuewrapper_runme.cs new file mode 100644 index 000000000..69f788699 --- /dev/null +++ b/Examples/test-suite/csharp/cpp11_move_only_valuewrapper_runme.cs @@ -0,0 +1,25 @@ +using System; +using cpp11_move_only_valuewrapperNamespace; + +public class cpp11_move_only_valuewrapper_runme { + + public static void Main() { + XXX.reset_counts(); + using (XXX xxx = cpp11_move_only_valuewrapper.createXXX()) { + } + if (cpp11_move_only_valuewrapper.has_cplusplus11()) + XXX.check_counts(1, 1, 0, 1, 0, 3); // Was (1, 2, 0, 0, 0, 3) before SwigValueWrapper::operator=(T &&) was added. + cpp11_move_only_valuewrapper.test1(); + cpp11_move_only_valuewrapper.test2(); + cpp11_move_only_valuewrapper.test3(); + cpp11_move_only_valuewrapper.test4(); + cpp11_move_only_valuewrapper.test5(); + cpp11_move_only_valuewrapper.test6(); + + // C# only test (SwigValueWrapper and custom typemaps for std::unique_ptr) + SWIGTYPE_p_std__unique_ptrT_XXX_t ptr = cpp11_move_only_valuewrapper.makeUniqueXXX(); + cpp11_move_only_valuewrapper.cleanup(ptr); + + } + +} diff --git a/Lib/swig.swg b/Lib/swig.swg index 223d46482..9978ae9b7 100644 --- a/Lib/swig.swg +++ b/Lib/swig.swg @@ -663,6 +663,7 @@ namespace std { #ifdef __cplusplus %insert("runtime") %{ #ifdef __cplusplus +#include /* SwigValueWrapper is described in swig.swg */ template class SwigValueWrapper { struct SwigMovePointer { @@ -676,6 +677,9 @@ template class SwigValueWrapper { public: SwigValueWrapper() : pointer(0) { } SwigValueWrapper& operator=(const T& t) { SwigMovePointer tmp(new T(t)); pointer = tmp; return *this; } +#if __cplusplus >= 201103L + SwigValueWrapper& operator=(T&& t) { SwigMovePointer tmp(new T(std::move(t))); pointer = tmp; return *this; } +#endif operator T&() const { return *pointer.ptr; } T *operator&() { return pointer.ptr; } };%} From 4dd285fad736c014224ef2ad25b85e17f3dce1f9 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Thu, 16 Jun 2022 07:47:44 +0100 Subject: [PATCH 481/662] Cosmetic rename SwigMovePointer -> SwigSmartPointer This smart pointer doesn't really offer move semantics as is commonly understood in C++11, so rename accordingly. --- Lib/swig.swg | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/Lib/swig.swg b/Lib/swig.swg index 9978ae9b7..f6ba3a69f 100644 --- a/Lib/swig.swg +++ b/Lib/swig.swg @@ -653,8 +653,8 @@ namespace std { * arg1 = Vector(1,2,3); // Assignment from a value * * The class offers a strong guarantee of exception safety. - * With regards to the implementation, the private SwigMovePointer nested class is - * a simple smart pointer with move semantics, much like std::auto_ptr. + * With regards to the implementation, the private SwigSmartPointer nested class is + * a simple smart pointer providing exception safety, much like std::auto_ptr. * * This wrapping technique was suggested by William Fulton and is henceforth * known as the "Fulton Transform" :-). @@ -666,19 +666,19 @@ namespace std { #include /* SwigValueWrapper is described in swig.swg */ template class SwigValueWrapper { - struct SwigMovePointer { + struct SwigSmartPointer { T *ptr; - SwigMovePointer(T *p) : ptr(p) { } - ~SwigMovePointer() { delete ptr; } - SwigMovePointer& operator=(SwigMovePointer& rhs) { T* oldptr = ptr; ptr = 0; delete oldptr; ptr = rhs.ptr; rhs.ptr = 0; return *this; } + SwigSmartPointer(T *p) : ptr(p) { } + ~SwigSmartPointer() { delete ptr; } + SwigSmartPointer& operator=(SwigSmartPointer& rhs) { T* oldptr = ptr; ptr = 0; delete oldptr; ptr = rhs.ptr; rhs.ptr = 0; return *this; } } pointer; SwigValueWrapper& operator=(const SwigValueWrapper& rhs); SwigValueWrapper(const SwigValueWrapper& rhs); public: SwigValueWrapper() : pointer(0) { } - SwigValueWrapper& operator=(const T& t) { SwigMovePointer tmp(new T(t)); pointer = tmp; return *this; } + SwigValueWrapper& operator=(const T& t) { SwigSmartPointer tmp(new T(t)); pointer = tmp; return *this; } #if __cplusplus >= 201103L - SwigValueWrapper& operator=(T&& t) { SwigMovePointer tmp(new T(std::move(t))); pointer = tmp; return *this; } + SwigValueWrapper& operator=(T&& t) { SwigSmartPointer tmp(new T(std::move(t))); pointer = tmp; return *this; } #endif operator T&() const { return *pointer.ptr; } T *operator&() { return pointer.ptr; } From 6c4010e4421fbb1be76e89f4edba2d7db532c1cb Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Thu, 30 Jun 2022 12:36:45 +1200 Subject: [PATCH 482/662] Resolve -Wstrict-prototypes warnings with clang-15 warning: a function declaration without a prototype is deprecated in all versions of C [-Wstrict-prototypes] --- Source/CParse/cparse.h | 2 +- Source/CParse/cscanner.c | 10 +++++----- Source/CParse/parser.y | 6 +++--- Source/CParse/templ.c | 2 +- Source/DOH/file.c | 4 ++-- Source/DOH/memory.c | 4 ++-- Source/Preprocessor/cpp.c | 4 ++-- Source/Preprocessor/expr.c | 6 +++--- Source/Swig/include.c | 4 ++-- Source/Swig/misc.c | 2 +- Source/Swig/naming.c | 8 ++++---- Source/Swig/parms.c | 2 +- Source/Swig/swigfile.h | 2 +- Source/Swig/typemap.c | 4 ++-- Source/Swig/typesys.c | 8 ++++---- 15 files changed, 34 insertions(+), 34 deletions(-) diff --git a/Source/CParse/cparse.h b/Source/CParse/cparse.h index c67ffeaba..0d9ca4b9d 100644 --- a/Source/CParse/cparse.h +++ b/Source/CParse/cparse.h @@ -43,7 +43,7 @@ extern "C" { extern void scanner_clear_rename(void); extern void scanner_set_location(String *file, int line); extern void scanner_set_main_input_file(String *file); - extern String *scanner_get_main_input_file(); + extern String *scanner_get_main_input_file(void); extern void Swig_cparse_follow_locators(int); extern void start_inline(char *, int); extern String *scanner_ccode; diff --git a/Source/CParse/cscanner.c b/Source/CParse/cscanner.c index a658f5a6f..155c7c81b 100644 --- a/Source/CParse/cscanner.c +++ b/Source/CParse/cscanner.c @@ -123,7 +123,7 @@ void Swig_cparse_cplusplusout(int v) { * Initialize buffers * ------------------------------------------------------------------------- */ -void scanner_init() { +void scanner_init(void) { scan = NewScanner(); Scanner_idstart(scan,"%"); scan_init = 1; @@ -528,11 +528,11 @@ void scanner_set_location(String *file, int line) { Scanner_set_location(scan,file,line-1); } -void scanner_check_typedef() { +void scanner_check_typedef(void) { check_typedef = 1; } -void scanner_ignore_typedef() { +void scanner_ignore_typedef(void) { check_typedef = 0; } @@ -540,7 +540,7 @@ void scanner_last_id(int x) { last_id = x; } -void scanner_clear_rename() { +void scanner_clear_rename(void) { rename_active = 0; } @@ -554,7 +554,7 @@ void scanner_set_main_input_file(String *file) { main_input_file = file; } -String *scanner_get_main_input_file() { +String *scanner_get_main_input_file(void) { return main_input_file; } diff --git a/Source/CParse/parser.y b/Source/CParse/parser.y index 1ae3a59db..ddb9634b2 100644 --- a/Source/CParse/parser.y +++ b/Source/CParse/parser.y @@ -50,7 +50,7 @@ * Externals * ----------------------------------------------------------------------------- */ -int yyparse(); +int yyparse(void); /* NEW Variables */ @@ -349,7 +349,7 @@ static String *make_name(Node *n, String *name,SwigType *decl) { } /* Generate an unnamed identifier */ -static String *make_unnamed() { +static String *make_unnamed(void) { unnamed++; return NewStringf("$unnamed%d$",unnamed); } @@ -874,7 +874,7 @@ static void add_typedef_name(Node *n, Node *declnode, String *oldName, Symtab *c /* If the class name is qualified. We need to create or lookup namespace entries */ -static Symtab *set_scope_to_global() { +static Symtab *set_scope_to_global(void) { Symtab *symtab = Swig_symbol_global_scope(); Swig_symbol_setscope(symtab); return symtab; diff --git a/Source/CParse/templ.c b/Source/CParse/templ.c index f8c926d37..44a606299 100644 --- a/Source/CParse/templ.c +++ b/Source/CParse/templ.c @@ -19,7 +19,7 @@ static int template_debug = 0; const char *baselists[3]; -void SwigType_template_init() { +void SwigType_template_init(void) { baselists[0] = "baselist"; baselists[1] = "protectedbaselist"; baselists[2] = "privatebaselist"; diff --git a/Source/DOH/file.c b/Source/DOH/file.c index bf8055177..8ec8bd6ae 100644 --- a/Source/DOH/file.c +++ b/Source/DOH/file.c @@ -35,7 +35,7 @@ typedef struct { * reference count of the underlying DOH objects. * ----------------------------------------------------------------------------- */ -static DOHList *open_files_list_instance() { +static DOHList *open_files_list_instance(void) { static DOHList *all_open_files = 0; if (!all_open_files) all_open_files = DohNewList(); @@ -73,7 +73,7 @@ static void open_files_list_remove(DohFile *f) { * Close all opened files, to be called on program termination * ----------------------------------------------------------------------------- */ -void DohCloseAllOpenFiles() { +void DohCloseAllOpenFiles(void) { int i; DOHList *all_open_files = open_files_list_instance(); for (i = 0; i < DohLen(all_open_files); i++) { diff --git a/Source/DOH/memory.c b/Source/DOH/memory.c index 88ed0f959..d461ce392 100644 --- a/Source/DOH/memory.c +++ b/Source/DOH/memory.c @@ -48,7 +48,7 @@ static int pools_initialized = 0; * CreatePool() - Create a new memory pool * ---------------------------------------------------------------------- */ -static void CreatePool() { +static void CreatePool(void) { Pool *p = 0; p = (Pool *) DohMalloc(sizeof(Pool)); p->ptr = (DohBase *) DohCalloc(PoolSize, sizeof(DohBase)); @@ -65,7 +65,7 @@ static void CreatePool() { * InitPools() - Initialize the memory allocator * ---------------------------------------------------------------------- */ -static void InitPools() { +static void InitPools(void) { if (pools_initialized) return; CreatePool(); /* Create initial pool */ diff --git a/Source/Preprocessor/cpp.c b/Source/Preprocessor/cpp.c index 34ace2d77..14fa1aa01 100644 --- a/Source/Preprocessor/cpp.c +++ b/Source/Preprocessor/cpp.c @@ -1356,14 +1356,14 @@ static void add_chunk(DOH *ns, DOH *chunk, int allow) { push/pop_imported(): helper functions for defining and undefining SWIGIMPORTED (when %importing a file). */ -static void push_imported() { +static void push_imported(void) { if (imported_depth == 0) { Preprocessor_define("SWIGIMPORTED 1", 0); } ++imported_depth; } -static void pop_imported() { +static void pop_imported(void) { --imported_depth; if (imported_depth == 0) { Preprocessor_undef("SWIGIMPORTED"); diff --git a/Source/Preprocessor/expr.c b/Source/Preprocessor/expr.c index e5c768765..52e467b6c 100644 --- a/Source/Preprocessor/expr.c +++ b/Source/Preprocessor/expr.c @@ -52,7 +52,7 @@ static int expr_init = 0; /* Initialization flag */ static const char *errmsg = 0; /* Parsing error */ /* Initialize the precedence table for various operators. Low values have higher precedence */ -static void init_precedence() { +static void init_precedence(void) { prec[SWIG_TOKEN_NOT] = 10; prec[OP_UMINUS] = 10; prec[OP_UPLUS] = 10; @@ -85,7 +85,7 @@ static void init_precedence() { /* Reduce a single operator on the stack */ /* return 0 on failure, 1 on success */ -static int reduce_op() { +static int reduce_op(void) { long op_token = stack[sp - 1].value; assert(sp > 0); assert(stack[sp - 1].op == EXPR_OP); @@ -474,6 +474,6 @@ extra_rparen: * Return error message set by the evaluator (if any) * ----------------------------------------------------------------------------- */ -const char *Preprocessor_expr_error() { +const char *Preprocessor_expr_error(void) { return errmsg; } diff --git a/Source/Swig/include.c b/Source/Swig/include.c index 94df338f0..ca43dbd65 100644 --- a/Source/Swig/include.c +++ b/Source/Swig/include.c @@ -145,7 +145,7 @@ static List *Swig_search_path_any(int syspath) { return slist; } -List *Swig_search_path() { +List *Swig_search_path(void) { return Swig_search_path_any(0); } @@ -376,6 +376,6 @@ String *Swig_file_dirname(const_String_or_char_ptr filename) { /* * Swig_file_debug() */ -void Swig_file_debug_set() { +void Swig_file_debug_set(void) { file_debug = 1; } diff --git a/Source/Swig/misc.c b/Source/Swig/misc.c index 0519b57c9..55306b1da 100644 --- a/Source/Swig/misc.c +++ b/Source/Swig/misc.c @@ -1497,7 +1497,7 @@ int Swig_is_generated_overload(Node *n) { * Initialize the SWIG core * ----------------------------------------------------------------------------- */ -void Swig_init() { +void Swig_init(void) { /* Set some useful string encoding methods */ DohEncoding("escape", Swig_string_escape); DohEncoding("hexescape", Swig_string_hexescape); diff --git a/Source/Swig/naming.c b/Source/Swig/naming.c index 4d07d5b2f..0673429ad 100644 --- a/Source/Swig/naming.c +++ b/Source/Swig/naming.c @@ -744,28 +744,28 @@ void Swig_feature_set(Hash *features, const_String_or_char_ptr name, SwigType *d * ----------------------------------------------------------------------------- */ static Hash *namewarn_hash = 0; -static Hash *name_namewarn_hash() { +static Hash *name_namewarn_hash(void) { if (!namewarn_hash) namewarn_hash = NewHash(); return namewarn_hash; } static Hash *rename_hash = 0; -static Hash *name_rename_hash() { +static Hash *name_rename_hash(void) { if (!rename_hash) rename_hash = NewHash(); return rename_hash; } static List *namewarn_list = 0; -static List *name_namewarn_list() { +static List *name_namewarn_list(void) { if (!namewarn_list) namewarn_list = NewList(); return namewarn_list; } static List *rename_list = 0; -static List *name_rename_list() { +static List *name_rename_list(void) { if (!rename_list) rename_list = NewList(); return rename_list; diff --git a/Source/Swig/parms.c b/Source/Swig/parms.c index 3e832c361..f89ad6356 100644 --- a/Source/Swig/parms.c +++ b/Source/Swig/parms.c @@ -149,7 +149,7 @@ int ParmList_len(ParmList *p) { * get_empty_type() * ---------------------------------------------------------------------- */ -static SwigType *get_empty_type() { +static SwigType *get_empty_type(void) { return NewStringEmpty(); } diff --git a/Source/Swig/swigfile.h b/Source/Swig/swigfile.h index f12b33081..0583b3792 100644 --- a/Source/Swig/swigfile.h +++ b/Source/Swig/swigfile.h @@ -30,7 +30,7 @@ extern String *Swig_file_extension(const_String_or_char_ptr filename); extern String *Swig_file_basename(const_String_or_char_ptr filename); extern String *Swig_file_filename(const_String_or_char_ptr filename); extern String *Swig_file_dirname(const_String_or_char_ptr filename); -extern void Swig_file_debug_set(); +extern void Swig_file_debug_set(void); /* Delimiter used in accessing files and directories */ diff --git a/Source/Swig/typemap.c b/Source/Swig/typemap.c index 2f9c06000..126d88026 100644 --- a/Source/Swig/typemap.c +++ b/Source/Swig/typemap.c @@ -151,7 +151,7 @@ static void set_typemap(const SwigType *type, Hash **tmhash) { * Initialize the typemap system * ----------------------------------------------------------------------------- */ -void Swig_typemap_init() { +void Swig_typemap_init(void) { typemaps = NewHash(); } @@ -2170,7 +2170,7 @@ static void replace_embedded_typemap(String *s, ParmList *parm_sublist, Wrapper * Display all typemaps * ----------------------------------------------------------------------------- */ -void Swig_typemap_debug() { +void Swig_typemap_debug(void) { int nesting_level = 2; Printf(stdout, "---[ typemaps ]--------------------------------------------------------------\n"); Swig_print(typemaps, nesting_level); diff --git a/Source/Swig/typesys.c b/Source/Swig/typesys.c index d6d6bcc88..710688a0f 100644 --- a/Source/Swig/typesys.c +++ b/Source/Swig/typesys.c @@ -180,7 +180,7 @@ int Swig_value_wrapper_mode(int mode) { } -static void flush_cache() { +static void flush_cache(void) { typedef_resolve_cache = 0; typedef_all_cache = 0; typedef_qualified_cache = 0; @@ -188,7 +188,7 @@ static void flush_cache() { /* Initialize the scoping system */ -void SwigType_typesystem_init() { +void SwigType_typesystem_init(void) { if (global_scope) Delete(global_scope); if (scopes) @@ -407,7 +407,7 @@ void SwigType_using_scope(Typetab *scope) { * table for the scope that was popped off. * ----------------------------------------------------------------------------- */ -Typetab *SwigType_pop_scope() { +Typetab *SwigType_pop_scope(void) { Typetab *t, *old = current_scope; t = Getattr(current_scope, "parent"); if (!t) @@ -2093,7 +2093,7 @@ static int SwigType_compare_mangled(const DOH *a, const DOH *b) { * Returns the sorted list of mangled type names that should be exported into the * wrapper file. * ----------------------------------------------------------------------------- */ -List *SwigType_get_sorted_mangled_list() { +List *SwigType_get_sorted_mangled_list(void) { List *l = Keys(r_mangled); SortList(l, SwigType_compare_mangled); return l; From f5e2d044df193f3aa2340eca9ee47d5f125982fc Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Thu, 30 Jun 2022 12:50:53 +1200 Subject: [PATCH 483/662] Remove set but not used variables Highlighted by clang-15 warnings such as: warning: variable 'index' set but not used [-Wunused-but-set-variable] --- Source/Modules/directors.cxx | 2 -- Source/Modules/lua.cxx | 2 -- Source/Modules/ocaml.cxx | 7 ------- Source/Modules/octave.cxx | 2 -- Source/Modules/php.cxx | 7 ------- Source/Modules/tcl8.cxx | 1 + 6 files changed, 1 insertion(+), 20 deletions(-) diff --git a/Source/Modules/directors.cxx b/Source/Modules/directors.cxx index 196974792..4ca8b25e5 100644 --- a/Source/Modules/directors.cxx +++ b/Source/Modules/directors.cxx @@ -97,7 +97,6 @@ String *Swig_director_declaration(Node *n) { String *Swig_method_call(const_String_or_char_ptr name, ParmList *parms) { String *func; - int i = 0; int comma = 0; Parm *p = parms; SwigType *pt; @@ -115,7 +114,6 @@ String *Swig_method_call(const_String_or_char_ptr name, ParmList *parms) { pname = Getattr(p, "name"); Printf(func, "%s", pname); comma = 1; - i++; } p = nextSibling(p); } diff --git a/Source/Modules/lua.cxx b/Source/Modules/lua.cxx index 18cf8a346..5265aa5c1 100644 --- a/Source/Modules/lua.cxx +++ b/Source/Modules/lua.cxx @@ -1418,7 +1418,6 @@ public: List *baselist = Getattr(n, "bases"); if (baselist && Len(baselist)) { Iterator b; - int index = 0; b = First(baselist); while (b.item) { String *bname = Getattr(b.item, "name"); @@ -1431,7 +1430,6 @@ public: Printf(base_class_names, "\"%s *\",", SwigType_namestr(bname)); b = Next(b); - index++; } } // First, print class static part diff --git a/Source/Modules/ocaml.cxx b/Source/Modules/ocaml.cxx index 97bb8cc17..84f16aa99 100644 --- a/Source/Modules/ocaml.cxx +++ b/Source/Modules/ocaml.cxx @@ -1486,10 +1486,6 @@ public: int i; char source[256]; - int outputs = 0; - if (!is_void) - outputs++; - /* build argument list and type conversion string */ for (i = 0, idx = 0, p = l; i < num_arguments; i++) { @@ -1497,9 +1493,6 @@ public: p = Getattr(p, "tmap:ignore:next"); } - if (Getattr(p, "tmap:directorargout") != 0) - outputs++; - String *pname = Getattr(p, "name"); String *ptype = Getattr(p, "type"); diff --git a/Source/Modules/octave.cxx b/Source/Modules/octave.cxx index 9e5bd17a1..e6c55fb0b 100644 --- a/Source/Modules/octave.cxx +++ b/Source/Modules/octave.cxx @@ -1003,7 +1003,6 @@ public: List *baselist = Getattr(n, "bases"); if (baselist && Len(baselist)) { Iterator b; - int index = 0; b = First(baselist); while (b.item) { String *bname = Getattr(b.item, "name"); @@ -1016,7 +1015,6 @@ public: Printf(base_class_names, "\"%s\",", bname_mangled); Printf(base_class, "0,"); b = Next(b); - index++; Delete(bname_mangled); } } diff --git a/Source/Modules/php.cxx b/Source/Modules/php.cxx index c424572f1..67f7f1f19 100644 --- a/Source/Modules/php.cxx +++ b/Source/Modules/php.cxx @@ -2167,10 +2167,6 @@ public: Parm *p; - int outputs = 0; - if (!is_void) - outputs++; - /* build argument list and type conversion string */ idx = 0; p = l; @@ -2180,9 +2176,6 @@ public: continue; } - if (Getattr(p, "tmap:directorargout") != 0) - outputs++; - String *pname = Getattr(p, "name"); String *ptype = Getattr(p, "type"); diff --git a/Source/Modules/tcl8.cxx b/Source/Modules/tcl8.cxx index 641dfc866..72908d8ed 100644 --- a/Source/Modules/tcl8.cxx +++ b/Source/Modules/tcl8.cxx @@ -825,6 +825,7 @@ public: //Printf(f_init,"/* Register base : %s */\n", bmangle); //Printf(f_init,"swig_%s_bases[%d] = (swig_class *) SWIG_TypeQuery(\"%s *\")->clientdata;\n", mangled_classname, index, SwigType_namestr(bname)); + (void)index; b = Next(b); index++; Putc(',', base_class); From a0fed47163b566fbaae19aa0e7805bd59fd446e9 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Tue, 21 Jun 2022 14:56:17 +0100 Subject: [PATCH 484/662] Remove duplicate typemaps --- Lib/cffi/cffi.swg | 9 --------- 1 file changed, 9 deletions(-) diff --git a/Lib/cffi/cffi.swg b/Lib/cffi/cffi.swg index f7294956f..690081032 100644 --- a/Lib/cffi/cffi.swg +++ b/Lib/cffi/cffi.swg @@ -201,15 +201,6 @@ ;;;SWIG wrapper code ends here %} -#ifdef __cplusplus -%typemap(out) SWIGTYPE "$result = new $1_type($1);"; -#else -%typemap(out) SWIGTYPE { - $result = ($&1_ltype) malloc(sizeof($1_type)); - memmove($result, &$1, sizeof($1_type)); -} -#endif - ////////////////////////////////////////////////////////////// /* name conversion for overloaded operators. */ From 6ccef6dae1dee6d569642d49f449c40e8d432627 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Fri, 24 Jun 2022 21:24:24 +0100 Subject: [PATCH 485/662] Ocaml clean fixes --- Examples/test-suite/ocaml/Makefile.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Examples/test-suite/ocaml/Makefile.in b/Examples/test-suite/ocaml/Makefile.in index 79e25efcf..9b0c32b0f 100644 --- a/Examples/test-suite/ocaml/Makefile.in +++ b/Examples/test-suite/ocaml/Makefile.in @@ -103,7 +103,7 @@ $(MULTI_CPP_TEST_CASES:=.multicpptest): extra_objects # Clean %.clean: - @rm -f $*.ml $*.mli $*_runme; + @rm -f $*_wrap.* $*.cmo $*.cmi $*.ml $*.mli $*_runme; @if test $(srcdir) != .; then rm -f $(ml_runme); fi clean: From bf36bf7d8aa8d130f30d0cbb2c260966f96bc108 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Wed, 22 Jun 2022 12:52:06 +0100 Subject: [PATCH 486/662] Movable and move-only types supported in "out" typemaps. Enhance SWIGTYPE "out" typemaps to use std::move when copying objects, thereby making use of move semantics when wrapping a function returning by value if the returned type supports move semantics. Wrapping functions that return move only types 'by value' now work out the box without having to provide custom typemaps. The implementation removed all casts in the "out" typemaps to allow the compiler to appropriately choose calling a move constructor, where possible, otherwise a copy constructor. The implementation alsoand required modifying SwigValueWrapper to change a cast operator from: SwigValueWrapper::operator T&() const; to #if __cplusplus >=201103L SwigValueWrapper::operator T&&() const; #else SwigValueWrapper::operator T&() const; #endif This is not backwards compatible for C++11 and later when using the valuewrapper feature if a cast is explicitly being made in user supplied "out" typemaps. Suggested change in custom "out" typemaps for C++11 and later code: 1. Try remove the cast altogether to let the compiler use an appropriate implicit cast. 2. Change the cast, for example, from static_cast to static_cast, using the __cplusplus macro if all versions of C++ need to be supported. Issue #999 Closes #1044 More about the commit: Added some missing "varout" typemaps for Ocaml which was falling back to use "out" typemaps as they were missing. Ruby std::set fix for SwigValueWrapper C++11 changes. --- CHANGES.current | 33 +++++ Doc/Manual/CPlusPlus11.html | 79 +++++++++++ Doc/Manual/Contents.html | 3 + Doc/Manual/SWIGPlus.html | 24 ++-- Doc/Manual/Typemaps.html | 10 +- Examples/test-suite/common.mk | 1 + Examples/test-suite/cpp11_move_only.i | 52 +++++++ Examples/test-suite/cpp11_move_only_helper.i | 71 ++++++++++ .../test-suite/cpp11_move_only_valuewrapper.i | 129 +++++------------- .../csharp/cpp11_move_only_runme.cs | 23 ++++ .../cpp11_move_only_valuewrapper_runme.cs | 16 ++- .../csharp/typemap_out_optimal_runme.cs | 8 +- .../d/typemap_out_optimal_runme.1.d | 1 + .../d/typemap_out_optimal_runme.2.d | 1 + .../go/typemap_out_optimal_runme.go | 1 + .../java/cpp11_move_only_runme.java | 39 ++++++ .../cpp11_move_only_valuewrapper_runme.java | 44 ++++++ .../java/typemap_out_optimal_runme.java | 10 +- .../python/cpp11_move_only_runme.py | 17 +++ .../python/typemap_out_optimal_runme.py | 3 + Examples/test-suite/typemap_out_optimal.i | 13 +- Lib/cffi/cffi.swg | 3 +- Lib/csharp/csharp.swg | 2 +- Lib/d/dswigtype.swg | 2 +- Lib/guile/typemaps.i | 5 +- Lib/java/java.swg | 2 +- Lib/lua/luatypemaps.swg | 2 +- Lib/mzscheme/typemaps.i | 2 +- Lib/ocaml/ocaml.swg | 10 +- Lib/ocaml/std_string.i | 9 ++ Lib/php/php.swg | 2 +- Lib/ruby/std_set.i | 7 +- Lib/swig.swg | 6 +- Lib/typemaps/swigtype.swg | 16 ++- 34 files changed, 508 insertions(+), 138 deletions(-) create mode 100644 Examples/test-suite/cpp11_move_only.i create mode 100644 Examples/test-suite/cpp11_move_only_helper.i create mode 100644 Examples/test-suite/csharp/cpp11_move_only_runme.cs create mode 100644 Examples/test-suite/java/cpp11_move_only_runme.java create mode 100644 Examples/test-suite/java/cpp11_move_only_valuewrapper_runme.java create mode 100644 Examples/test-suite/python/cpp11_move_only_runme.py diff --git a/CHANGES.current b/CHANGES.current index 1e06bd85b..6584e1781 100644 --- a/CHANGES.current +++ b/CHANGES.current @@ -7,6 +7,39 @@ the issue number to the end of the URL: https://github.com/swig/swig/issues/ Version 4.1.0 (in progress) =========================== +2022-06-29: wsfulton + #999 #1044 Enhance SWIGTYPE "out" typemaps to use std::move when copying + objects, thereby making use of move semantics when wrapping a function returning + by value if the returned type supports move semantics. + + Wrapping functions that return move only types 'by value' now work out the box + without having to provide custom typemaps. + + The implementation removed all casts in the "out" typemaps to allow the compiler to + appropriately choose calling a move constructor, where possible, otherwise a copy + constructor. The implementation alsoand required modifying SwigValueWrapper to + change a cast operator from: + + SwigValueWrapper::operator T&() const; + + to + + #if __cplusplus >=201103L + SwigValueWrapper::operator T&&() const; + #else + SwigValueWrapper::operator T&() const; + #endif + + This is not backwards compatible for C++11 and later when using the valuewrapper feature + if a cast is explicitly being made in user supplied "out" typemaps. Suggested change + in custom "out" typemaps for C++11 and later code: + + 1. Try remove the cast altogether to let the compiler use an appropriate implicit cast. + 2. Change the cast, for example, from static_cast to static_cast, using the + __cplusplus macro if all versions of C++ need to be supported. + + *** POTENTIAL INCOMPATIBILITY *** + 2022-06-15: wsfulton #2039 Add move assignment operator to SwigValueWrapper used by the valuewrapper feature. diff --git a/Doc/Manual/CPlusPlus11.html b/Doc/Manual/CPlusPlus11.html index 86a35bfaa..b98713961 100644 --- a/Doc/Manual/CPlusPlus11.html +++ b/Doc/Manual/CPlusPlus11.html @@ -15,6 +15,9 @@
  • Core language changes
    • Rvalue reference and move semantics +
    • Generalized constant expressions
    • Extern template
    • Initializer lists @@ -123,6 +126,82 @@ example.i:18: Warning 503: Can't wrap 'operator =' unless renamed to a valid ide +

      7.2.1.1 Movable and move-only types

      + + +

      +SWIG has traditionally relied on wrapped C++ types to be copy constructible or copy assignable, either via an explicit or implicit copy constructor and copy assignment operator. +Prior to C++11, a function could not return nor take a type by value that was not copyable. +In C++11 this is no longer the case. A type can also be movable if it has has a move constructor and a move assignment operator. +A move-only type is movable but not copyable; it has both the copy constructor and copy assignment operator deleted. +Movable types can appear in function signatures for passing 'by value' and in C++11 the object can then be moved rather than copied. +

      + +

      +SWIG has been enhanced with support for both copyable and/or movable types but this is currently just for function return values. +

      + +

      +The support for function return values is generically implemented in the "out" SWIGTYPE typemap which supports any type, including copyable, movable and move-only types. +The typemap code is very simple and written so that the compiler will call the move constructor if possible, +otherwise the copy constructor: +

      + +
      +%typemap(out) SWIGTYPE %{
      +  $result = new $1_ltype($1);
      +%}
      +
      + +

      +The above typemap is for C# and when used to wrap a move-only type such as: +

      + +
      +struct MoveOnly {
      +  int  val;
      +  MoveOnly(): val(0)  {}
      +
      +  MoveOnly(const MoveOnly &) = delete;
      +  MoveOnly(MoveOnly &&) = default;
      +
      +  MoveOnly & operator=(const MoveOnly &) = delete;
      +  MoveOnly & operator=(MoveOnly &&) = default;
      +
      +  static MoveOnly create() { return MoveOnly(); }
      +};
      +
      + +

      +will generate wrapper code for the create factory method: +

      + +
      +SWIGEXPORT void * SWIGSTDCALL CSharp_MoveOnly_create() {
      +  void * jresult ;
      +  SwigValueWrapper< MoveOnly > result;
      +
      +  result = MoveOnly::create();
      +  jresult = new MoveOnly(result);
      +  return jresult;
      +}
      +
      + +

      +SwigValueWrapper is covered in Pass and return by value. +Note that the generated code could be optimised further using the "optimal" attribute in the "out" typemap. +

      + +

      +There is currently only partial support for move-only types as +support for move-only types used as a parameter in a function, that are passed 'by value', is not yet available. +

      + +

      +Compatibility note: +SWIG-4.1.0 introduced support for taking advantage of types with move semantics and wrapping functions that return movable or move-only types 'by value'. +

      +

      7.2.2 Generalized constant expressions

      diff --git a/Doc/Manual/Contents.html b/Doc/Manual/Contents.html index 6f48360fd..ef87cf78d 100644 --- a/Doc/Manual/Contents.html +++ b/Doc/Manual/Contents.html @@ -297,6 +297,9 @@
    • Core language changes
      • Rvalue reference and move semantics +
      • Generalized constant expressions
      • Extern template
      • Initializer lists diff --git a/Doc/Manual/SWIGPlus.html b/Doc/Manual/SWIGPlus.html index 4cefdc365..820c5088b 100644 --- a/Doc/Manual/SWIGPlus.html +++ b/Doc/Manual/SWIGPlus.html @@ -584,7 +584,7 @@ automatically generate a wrapper for one.
      • If a C++ class does not declare an explicit copy constructor, SWIG will -automatically generate a wrapper for one if the %copyctor is used. +automatically generate a wrapper for one if %copyctor is used.
      • @@ -1352,16 +1352,19 @@ following:
         Vector *wrap_cross_product(Vector *a, Vector *b) {
        -  Vector x = *a;
        -  Vector y = *b;
        -  Vector r = cross_product(x, y);
        +  Vector x;
        +  Vector y;
        +  Vector r;
        +  x = *a;
        +  y = *b;
        +  r = cross_product(x, y);
           return new Vector(r);
         }

        -In order for the wrapper code to compile, Vector must define a copy constructor and a -default constructor. +In order for the wrapper code to compile, Vector must define a default constructor, copy assignment operator (and/or a move assignment operator for C++11 and later). +The Movable and move-only types section should be read regarding C++11 move semantics and return by value.

        @@ -1374,9 +1377,12 @@ called the "Fulton Transform". This produces a wrapper that looks like this:

         Vector cross_product(Vector *a, Vector *b) {
        -  SwigValueWrapper<Vector> x = *a;
        -  SwigValueWrapper<Vector> y = *b;
        -  SwigValueWrapper<Vector> r = cross_product(x, y);
        +  SwigValueWrapper<Vector> x;
        +  SwigValueWrapper<Vector> y;
        +  SwigValueWrapper<Vector> r;
        +  x = *a;
        +  y = *b;
        +  r = cross_product(x, y);
           return new Vector(r);
         }
         
        diff --git a/Doc/Manual/Typemaps.html b/Doc/Manual/Typemaps.html index 28f9d51ad..24a68b1ba 100644 --- a/Doc/Manual/Typemaps.html +++ b/Doc/Manual/Typemaps.html @@ -3364,7 +3364,7 @@ Consider running the following code through SWIG:
         %typemap(out) SWIGTYPE %{
        -  $result = new $1_ltype((const $1_ltype &)$1);
        +  $result = new $1_ltype($1);
         %}
         
         %inline %{
        @@ -3414,7 +3414,7 @@ If the typemap code is kept the same and just the "optimal" attribute specified
         
         %typemap(out, optimal="1") SWIGTYPE %{
        -  $result = new $1_ltype((const $1_ltype &)$1);
        +  $result = new $1_ltype($1);
         %}
         
        @@ -3441,7 +3441,7 @@ SWIGEXPORT void * SWIGSTDCALL CSharp_XX_create() { void * jresult ; XX result; result = XX::create(); - jresult = new XX((const XX &)result); + jresult = new XX(result); return jresult; } @@ -3456,7 +3456,7 @@ With the "optimal" attribute, the code is:
         SWIGEXPORT void * SWIGSTDCALL CSharp_XX_create() {
           void * jresult ;
        -  jresult = new XX((const XX &)XX::create());
        +  jresult = new XX(XX::create());
           return jresult;
         }
         
        @@ -3513,7 +3513,7 @@ It should be clear that the above code cannot be used as the argument to the cop

        -Secondly, if the typemaps uses $1 more than once, then multiple calls to the wrapped function +Secondly, if the typemap uses $1 more than once, then multiple calls to the wrapped function will be made. Obviously that is not very optimal. In fact SWIG attempts to detect this and will issue a warning something like:

        diff --git a/Examples/test-suite/common.mk b/Examples/test-suite/common.mk index 003138010..a640febc1 100644 --- a/Examples/test-suite/common.mk +++ b/Examples/test-suite/common.mk @@ -597,6 +597,7 @@ CPP11_TEST_CASES += \ cpp11_initializer_list \ cpp11_initializer_list_extend \ cpp11_lambda_functions \ + cpp11_move_only \ cpp11_move_only_valuewrapper \ cpp11_noexcept \ cpp11_null_pointer_constant \ diff --git a/Examples/test-suite/cpp11_move_only.i b/Examples/test-suite/cpp11_move_only.i new file mode 100644 index 000000000..7c91933c4 --- /dev/null +++ b/Examples/test-suite/cpp11_move_only.i @@ -0,0 +1,52 @@ +%module cpp11_move_only + +#if defined(SWIGD) +%rename(trace) debug; +#endif + +%include "cpp11_move_only_helper.i" + +%ignore MoveOnly::operator=; +//%valuewrapper MoveOnly; // SWIG sets %valuewrapper by default for move-only types + +%inline %{ +#include +using namespace std; + +bool debug = false; + +struct MoveOnly { + MoveOnly(int i = 0) { if (debug) cout << "MoveOnly(" << i << ")" << " " << this << endl; Counter::normal_constructor++; } + + MoveOnly(const MoveOnly &other) = delete; + MoveOnly & operator=(const MoveOnly &other) = delete; + + MoveOnly(MoveOnly &&other) noexcept { if (debug) cout << "MoveOnly(MoveOnly &&)" << " " << this << endl; Counter::move_constructor++; } + MoveOnly & operator=(MoveOnly &&other) noexcept { if (debug) cout << "operator=(MoveOnly &&)" << " " << this << endl; Counter::move_assignment++; return *this; } + ~MoveOnly() { if (debug) cout << "~MoveOnly()" << " " << this << endl; Counter::destructor++; } + + static MoveOnly create() { return MoveOnly(111); } + // static const MoveOnly createConst() { return MoveOnly(111); } // not supported by default +}; +%} + +%ignore MovableCopyable::operator=; +%ignore MovableCopyable::MovableCopyable(MovableCopyable &&); +// %valuewrapper MovableCopyable; // SWIG does not use valuewrapper by default for copyable types with a default constructor + +%inline %{ +// Movable and Copyable +struct MovableCopyable { + MovableCopyable(int i = 0) { if (debug) cout << "MovableCopyable(" << i << ")" << " " << this << endl; Counter::normal_constructor++; } + + MovableCopyable(const MovableCopyable &other) { if (debug) cout << "MovableCopyable(const MovableCopyable &)" << " " << this << " " << &other << endl; Counter::copy_constructor++;} + MovableCopyable & operator=(const MovableCopyable &other) { if (debug) cout << "operator=(const MovableCopyable &)" << " " << this << " " << &other << endl; Counter::copy_assignment++; return *this; } + + MovableCopyable(MovableCopyable &&other) noexcept { if (debug) cout << "MovableCopyable(MovableCopyable &&)" << " " << this << endl; Counter::move_constructor++; } + MovableCopyable & operator=(MovableCopyable &&other) noexcept { if (debug) cout << "operator=(MovableCopyable &&)" << " " << this << endl; Counter::move_assignment++; return *this; } + ~MovableCopyable() { if (debug) cout << "~MovableCopyable()" << " " << this << endl; Counter::destructor++; } + + static MovableCopyable create() { return MovableCopyable(111); } + static const MovableCopyable createConst() { return MovableCopyable(111); } +}; +%} diff --git a/Examples/test-suite/cpp11_move_only_helper.i b/Examples/test-suite/cpp11_move_only_helper.i new file mode 100644 index 000000000..89fc1509b --- /dev/null +++ b/Examples/test-suite/cpp11_move_only_helper.i @@ -0,0 +1,71 @@ +// Helper interface for cpp11_move_only.i and others + +%include +%catches(std::string) Counter::check_counts; + +%inline %{ +#include +using namespace std; + + +struct Counter { + static int normal_constructor; + static int copy_constructor; + static int copy_assignment; + static int move_constructor; + static int move_assignment; + static int destructor; + static void reset_counts() { + normal_constructor = 0; + copy_constructor = 0; + copy_assignment = 0; + move_constructor = 0; + move_assignment = 0; + destructor = 0; + } + // Check against expected counts of constructor, assignment operators etc. + // Not observed during development, but compiler optimisation could change the expected values. + // Throws exception if not correct (use %catches to catch them) + static void check_counts( + int normal_constructor, + int copy_constructor, + int copy_assignment, + int move_constructor, + int move_assignment, + int destructor) { + bool match = ( + normal_constructor == Counter::normal_constructor && + copy_constructor == Counter::copy_constructor && + copy_assignment == Counter::copy_assignment && + move_constructor == Counter::move_constructor && + move_assignment == Counter::move_assignment && + destructor == Counter::destructor); + if (!match) { + std::stringstream ss; + ss << "check_counts failed" << std::endl << + Counter::normal_constructor << " " << + Counter::copy_constructor << " " << + Counter::copy_assignment << " " << + Counter::move_constructor << " " << + Counter::move_assignment << " " << + Counter::destructor << " " << + " (actual)" << std::endl << + normal_constructor << " " << + copy_constructor << " " << + copy_assignment << " " << + move_constructor << " " << + move_assignment << " " << + destructor << " " << + " (expected)" << std::endl; + throw ss.str(); + } + } +}; + +int Counter::normal_constructor = 0; +int Counter::copy_constructor = 0; +int Counter::copy_assignment = 0; +int Counter::move_constructor = 0; +int Counter::move_assignment = 0; +int Counter::destructor = 0; +%} diff --git a/Examples/test-suite/cpp11_move_only_valuewrapper.i b/Examples/test-suite/cpp11_move_only_valuewrapper.i index fb9f5dc31..bde95f014 100644 --- a/Examples/test-suite/cpp11_move_only_valuewrapper.i +++ b/Examples/test-suite/cpp11_move_only_valuewrapper.i @@ -37,82 +37,28 @@ namespace std { #endif %} -%include +#if defined(SWIGD) +%rename(trace) debug; +#endif + +%include "cpp11_move_only_helper.i" %valuewrapper XXX; %ignore XXX::operator=; -%catches(std::string) XXX::check_counts; %inline %{ bool debug = false; struct XXX { - XXX(int i = 0) { if (debug) cout << "XXX(" << i << ")" << " " << this << endl; normal_constructor_count++; } - XXX(const XXX &other) { if (debug) cout << "XXX(const XXX &)" << " " << this << " " << &other << endl; copy_constructor_count++;} - XXX & operator=(const XXX &other) { if (debug) cout << "operator=(const XXX &)" << " " << this << " " << &other << endl; copy_assignment_count++; return *this; } + XXX(int i = 0) { if (debug) cout << "XXX(" << i << ")" << " " << this << endl; Counter::normal_constructor++; } + XXX(const XXX &other) { if (debug) cout << "XXX(const XXX &)" << " " << this << " " << &other << endl; Counter::copy_constructor++;} + XXX & operator=(const XXX &other) { if (debug) cout << "operator=(const XXX &)" << " " << this << " " << &other << endl; Counter::copy_assignment++; return *this; } #if defined(__cplusplus) && __cplusplus >= 201103L - XXX(XXX &&other) noexcept { if (debug) cout << "XXX(XXX &&)" << " " << this << endl; move_constructor_count++; } - XXX & operator=(XXX &&other) noexcept { if (debug) cout << "operator=(XXX &&)" << " " << this << endl; move_assignment_count++; return *this; } + XXX(XXX &&other) noexcept { if (debug) cout << "XXX(XXX &&)" << " " << this << endl; Counter::move_constructor++; } + XXX & operator=(XXX &&other) noexcept { if (debug) cout << "operator=(XXX &&)" << " " << this << endl; Counter::move_assignment++; return *this; } #endif - ~XXX() { if (debug) cout << "~XXX()" << " " << this << endl; destructor_count++; } - static int normal_constructor_count; - static int copy_constructor_count; - static int copy_assignment_count; - static int move_constructor_count; - static int move_assignment_count; - static int destructor_count; - static void reset_counts() { - XXX::normal_constructor_count = 0; - XXX::copy_constructor_count = 0; - XXX::copy_assignment_count = 0; - XXX::move_constructor_count = 0; - XXX::move_assignment_count = 0; - XXX::destructor_count = 0; - } - // Check against expected counts of constructor, assignment operators etc. - // Not observed during development, but compiler optimisation could change the expected values. - // Throws exception if not correct (use %catches to catch them) - static void check_counts( - int normal_constructor_count, - int copy_constructor_count, - int copy_assignment_count, - int move_constructor_count, - int move_assignment_count, - int destructor_count) { - bool match = ( - normal_constructor_count == XXX::normal_constructor_count && - copy_constructor_count == XXX::copy_constructor_count && - copy_assignment_count == XXX::copy_assignment_count && - move_constructor_count == XXX::move_constructor_count && - move_assignment_count == XXX::move_assignment_count && - destructor_count == XXX::destructor_count); - if (!match) { - std::stringstream ss; - ss << "check_counts failed" << std::endl << - XXX::normal_constructor_count << " " << - XXX::copy_constructor_count << " " << - XXX::copy_assignment_count << " " << - XXX::move_constructor_count << " " << - XXX::move_assignment_count << " " << - XXX::destructor_count << " " << - " (actual)" << std::endl << - normal_constructor_count << " " << - copy_constructor_count << " " << - copy_assignment_count << " " << - move_constructor_count << " " << - move_assignment_count << " " << - destructor_count << " " << - " (expected)" << std::endl; - throw ss.str(); - } - } + ~XXX() { if (debug) cout << "~XXX()" << " " << this << endl; Counter::destructor++; } }; -int XXX::normal_constructor_count = 0; -int XXX::copy_constructor_count = 0; -int XXX::copy_assignment_count = 0; -int XXX::move_constructor_count = 0; -int XXX::move_assignment_count = 0; -int XXX::destructor_count = 0; bool has_cplusplus11() { #if __cplusplus >= 201103L return true; @@ -122,20 +68,8 @@ bool has_cplusplus11() { } %} -#if defined(SWIGCSHARP) -%typemap(out) std::unique_ptr %{ - if (debug) cout << "out start" << endl; -#if __cplusplus >= 201103L - $result = new std::unique_ptr(std::move(static_cast&>($1))); -#else - $result = new std::unique_ptr((const std::unique_ptr &)$1); -#endif - if (debug) cout << "out done" << endl; -%} - std::unique_ptr makeUniqueXXX(); void cleanup(std::unique_ptr* p); -#endif %{ std::unique_ptr makeUniqueXXX() { @@ -145,6 +79,7 @@ std::unique_ptr makeUniqueXXX() { void cleanup(std::unique_ptr* p) { delete p; } +typedef XXX UUU; %} %inline %{ @@ -152,6 +87,16 @@ XXX createXXX() { if (debug) cout << "createXXX()" << endl; return XXX(111); } +XXX createXXX2() { + if (debug) cout << "createXXX2()" << endl; + return XXX(222); +} +UUU createUnknownType() { + if (debug) cout << "createXXX2()" << endl; + return XXX(222); +} +struct YYY {}; +void inputByValue(UUU uuu, XXX xxx, YYY yyy) {} %} @@ -165,32 +110,32 @@ XXX createXXX() { %inline %{ // 'unit tests' for SwigValueWrapper void test1() { - XXX::reset_counts(); + Counter::reset_counts(); { SwigValueWrapper x; x = XXX(); } #if __cplusplus >= 201103L - XXX::check_counts(1, 0, 0, 1, 0, 2); // was same as < c++11 counts below before move assignment operator added to SwigValueWrapper + Counter::check_counts(1, 0, 0, 1, 0, 2); // was same as < c++11 counts below before move assignment operator added to SwigValueWrapper #else - XXX::check_counts(1, 1, 0, 0, 0, 2); + Counter::check_counts(1, 1, 0, 0, 0, 2); #endif } void test2() { - XXX::reset_counts(); + Counter::reset_counts(); { SwigValueWrapper x; x = XXX(); x = XXX(); } #if __cplusplus >= 201103L - XXX::check_counts(2, 0, 0, 2, 0, 4); + Counter::check_counts(2, 0, 0, 2, 0, 4); #else - XXX::check_counts(2, 2, 0, 0, 0, 4); + Counter::check_counts(2, 2, 0, 0, 0, 4); #endif } void test3() { - XXX::reset_counts(); + Counter::reset_counts(); { SwigValueWrapper x; XXX a(999); @@ -199,41 +144,41 @@ void test3() { #endif } #if __cplusplus >= 201103L - XXX::check_counts(1, 0, 0, 1, 0, 2); + Counter::check_counts(1, 0, 0, 1, 0, 2); #endif } void test4() { - XXX::reset_counts(); + Counter::reset_counts(); { SwigValueWrapper > x; x = std::unique_ptr(new XXX(444)); } - XXX::check_counts(1, 0, 0, 0, 0, 1); + Counter::check_counts(1, 0, 0, 0, 0, 1); } void test5() { #if __cplusplus >= 201103L - XXX::reset_counts(); + Counter::reset_counts(); { SwigValueWrapper > x; x = std::unique_ptr(new XXX(550)); std::unique_ptr x2(new XXX(555)); x = std::move(x2); } - XXX::check_counts(2, 0, 0, 0, 0, 2); + Counter::check_counts(2, 0, 0, 0, 0, 2); #endif } void test6() { #if __cplusplus >= 201103L - XXX::reset_counts(); + Counter::reset_counts(); { // emulates how std::unique_ptr typemaps could be wrapped with SwigValueWrapper void *ptr = 0; SwigValueWrapper > x; // SWIG generated if std::unique_ptr<> definition not parsed x = makeUniqueXXX(); // SWIG generated code wrapping function returning std::unique_ptr - ptr = new std::unique_ptr(std::move((std::unique_ptr&)x)); // 'out' typemap (move std::unique_ptr from stack to the heap), note non-const cast std::unique_tr& + ptr = new std::unique_ptr(x); // 'out' typemap (move std::unique_ptr from stack to the heap) delete (std::unique_ptr *)ptr; // Final cleanup (user needs to call this) } - XXX::check_counts(1, 0, 0, 0, 0, 1); + Counter::check_counts(1, 0, 0, 0, 0, 1); #endif } %} diff --git a/Examples/test-suite/csharp/cpp11_move_only_runme.cs b/Examples/test-suite/csharp/cpp11_move_only_runme.cs new file mode 100644 index 000000000..57cb7aa18 --- /dev/null +++ b/Examples/test-suite/csharp/cpp11_move_only_runme.cs @@ -0,0 +1,23 @@ +using System; +using cpp11_move_onlyNamespace; + +public class cpp11_move_only_runme { + + public static void Main() { + Counter.reset_counts(); + using (MoveOnly mo = MoveOnly.create()) { + } + Counter.check_counts(1, 0, 0, 2, 0, 3); + + Counter.reset_counts(); + using (MovableCopyable mo = MovableCopyable.create()) { + } + Counter.check_counts(2, 1, 0, 0, 1, 3); + + // Move semantics not used + Counter.reset_counts(); + using (MovableCopyable mo = MovableCopyable.createConst()) { + } + Counter.check_counts(2, 1, 1, 0, 0, 3); + } +} diff --git a/Examples/test-suite/csharp/cpp11_move_only_valuewrapper_runme.cs b/Examples/test-suite/csharp/cpp11_move_only_valuewrapper_runme.cs index 69f788699..d6a42a3f7 100644 --- a/Examples/test-suite/csharp/cpp11_move_only_valuewrapper_runme.cs +++ b/Examples/test-suite/csharp/cpp11_move_only_valuewrapper_runme.cs @@ -4,11 +4,18 @@ using cpp11_move_only_valuewrapperNamespace; public class cpp11_move_only_valuewrapper_runme { public static void Main() { - XXX.reset_counts(); + Counter.reset_counts(); using (XXX xxx = cpp11_move_only_valuewrapper.createXXX()) { } if (cpp11_move_only_valuewrapper.has_cplusplus11()) - XXX.check_counts(1, 1, 0, 1, 0, 3); // Was (1, 2, 0, 0, 0, 3) before SwigValueWrapper::operator=(T &&) was added. + // Was (1, 2, 0, 0, 0, 3) before SwigValueWrapper::operator=(T &&) was added. + // Was (1, 1, 0, 1, 0, 3) before SwigValueWrapper::operator T&&() was added with new "out" typemaps + Counter.check_counts(1, 0, 0, 2, 0, 3); + Counter.reset_counts(); + using (XXX xxx = cpp11_move_only_valuewrapper.createXXX2()) { + } + if (cpp11_move_only_valuewrapper.has_cplusplus11()) + Counter.check_counts(1, 0, 0, 2, 0, 3); cpp11_move_only_valuewrapper.test1(); cpp11_move_only_valuewrapper.test2(); cpp11_move_only_valuewrapper.test3(); @@ -16,10 +23,11 @@ public class cpp11_move_only_valuewrapper_runme { cpp11_move_only_valuewrapper.test5(); cpp11_move_only_valuewrapper.test6(); - // C# only test (SwigValueWrapper and custom typemaps for std::unique_ptr) + // Tests SwigValueWrapper, std::unique_ptr (SWIG not parsing a type that is move-only) + Counter.reset_counts(); SWIGTYPE_p_std__unique_ptrT_XXX_t ptr = cpp11_move_only_valuewrapper.makeUniqueXXX(); cpp11_move_only_valuewrapper.cleanup(ptr); - + Counter.check_counts(1, 0, 0, 0, 0, 1); } } diff --git a/Examples/test-suite/csharp/typemap_out_optimal_runme.cs b/Examples/test-suite/csharp/typemap_out_optimal_runme.cs index 5bc1d14be..0d697498a 100644 --- a/Examples/test-suite/csharp/typemap_out_optimal_runme.cs +++ b/Examples/test-suite/csharp/typemap_out_optimal_runme.cs @@ -3,10 +3,14 @@ using typemap_out_optimalNamespace; public class typemap_out_optimal_runme { - public static XX x = null; public static void Main() { XX.debug = false; - x = XX.create(); + if (XX.debug) + Console.WriteLine("calling create()"); + using (XX x = XX.create()) { } + if (XX.debug) + Console.WriteLine("calling createConst()"); + using (XX x = XX.createConst()) { } } } diff --git a/Examples/test-suite/d/typemap_out_optimal_runme.1.d b/Examples/test-suite/d/typemap_out_optimal_runme.1.d index 16aab3cff..1267197e2 100644 --- a/Examples/test-suite/d/typemap_out_optimal_runme.1.d +++ b/Examples/test-suite/d/typemap_out_optimal_runme.1.d @@ -6,4 +6,5 @@ void main() { XX x; XX.trace = false; x = XX.create(); + x = XX.createConst(); } diff --git a/Examples/test-suite/d/typemap_out_optimal_runme.2.d b/Examples/test-suite/d/typemap_out_optimal_runme.2.d index 16aab3cff..1267197e2 100644 --- a/Examples/test-suite/d/typemap_out_optimal_runme.2.d +++ b/Examples/test-suite/d/typemap_out_optimal_runme.2.d @@ -6,4 +6,5 @@ void main() { XX x; XX.trace = false; x = XX.create(); + x = XX.createConst(); } diff --git a/Examples/test-suite/go/typemap_out_optimal_runme.go b/Examples/test-suite/go/typemap_out_optimal_runme.go index 0cccd97a6..0467ce293 100644 --- a/Examples/test-suite/go/typemap_out_optimal_runme.go +++ b/Examples/test-suite/go/typemap_out_optimal_runme.go @@ -5,4 +5,5 @@ import . "swigtests/typemap_out_optimal" func main() { SetXXDebug(false) _ = XXCreate() + _ = XXCreateConst() } diff --git a/Examples/test-suite/java/cpp11_move_only_runme.java b/Examples/test-suite/java/cpp11_move_only_runme.java new file mode 100644 index 000000000..b652634e5 --- /dev/null +++ b/Examples/test-suite/java/cpp11_move_only_runme.java @@ -0,0 +1,39 @@ + +import cpp11_move_only.*; + +public class cpp11_move_only_runme { + + static { + try { + System.loadLibrary("cpp11_move_only"); + } 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); + } + } + + public static void main(String argv[]) { + + { + Counter.reset_counts(); + MoveOnly mo = MoveOnly.create(); + mo.delete(); + Counter.check_counts(1, 0, 0, 2, 0, 3); + } + + { + Counter.reset_counts(); + MovableCopyable mo = MovableCopyable.create(); + mo.delete(); + Counter.check_counts(2, 1, 0, 0, 1, 3); + } + + // Move semantics not used + { + Counter.reset_counts(); + MovableCopyable mo = MovableCopyable.createConst(); + mo.delete(); + Counter.check_counts(2, 1, 1, 0, 0, 3); + } + } +} diff --git a/Examples/test-suite/java/cpp11_move_only_valuewrapper_runme.java b/Examples/test-suite/java/cpp11_move_only_valuewrapper_runme.java new file mode 100644 index 000000000..c857a7b81 --- /dev/null +++ b/Examples/test-suite/java/cpp11_move_only_valuewrapper_runme.java @@ -0,0 +1,44 @@ +import cpp11_move_only_valuewrapper.*; + +public class cpp11_move_only_valuewrapper_runme { + + static { + try { + System.loadLibrary("cpp11_move_only_valuewrapper"); + } 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); + } + } + + public static void main(String argv[]) { + Counter.reset_counts(); + { + XXX xxx = cpp11_move_only_valuewrapper.createXXX(); + xxx.delete(); + } + if (cpp11_move_only_valuewrapper.has_cplusplus11()) + // Was (1, 2, 0, 0, 0, 3) before SwigValueWrapper::operator=(T &&) was added. + // Was (1, 1, 0, 1, 0, 3) before SwigValueWrapper::operator T&&() was added with new "out" typemaps + Counter.check_counts(1, 0, 0, 2, 0, 3); + Counter.reset_counts(); + { + XXX xxx = cpp11_move_only_valuewrapper.createXXX2(); + xxx.delete(); + } + if (cpp11_move_only_valuewrapper.has_cplusplus11()) + Counter.check_counts(1, 0, 0, 2, 0, 3); + cpp11_move_only_valuewrapper.test1(); + cpp11_move_only_valuewrapper.test2(); + cpp11_move_only_valuewrapper.test3(); + cpp11_move_only_valuewrapper.test4(); + cpp11_move_only_valuewrapper.test5(); + cpp11_move_only_valuewrapper.test6(); + + // Tests SwigValueWrapper, std::unique_ptr (SWIG not parsing a type that is move-only) + Counter.reset_counts(); + SWIGTYPE_p_std__unique_ptrT_XXX_t ptr = cpp11_move_only_valuewrapper.makeUniqueXXX(); + cpp11_move_only_valuewrapper.cleanup(ptr); + Counter.check_counts(1, 0, 0, 0, 0, 1); + } +} diff --git a/Examples/test-suite/java/typemap_out_optimal_runme.java b/Examples/test-suite/java/typemap_out_optimal_runme.java index 8a87f0c4b..b48e5d697 100644 --- a/Examples/test-suite/java/typemap_out_optimal_runme.java +++ b/Examples/test-suite/java/typemap_out_optimal_runme.java @@ -12,10 +12,16 @@ public class typemap_out_optimal_runme { } } - public static XX x = null; public static void main(String argv[]) { XX.setDebug(false); - x = XX.create(); + { + XX x = XX.create(); + x.delete(); + } + { + XX x = XX.createConst(); + x.delete(); + } } } diff --git a/Examples/test-suite/python/cpp11_move_only_runme.py b/Examples/test-suite/python/cpp11_move_only_runme.py new file mode 100644 index 000000000..1c3183327 --- /dev/null +++ b/Examples/test-suite/python/cpp11_move_only_runme.py @@ -0,0 +1,17 @@ +from cpp11_move_only import * + +Counter.reset_counts() +mo = MoveOnly.create() +del mo +Counter.check_counts(1, 0, 0, 2, 0, 3) + +Counter.reset_counts() +mo = MovableCopyable.create() +del mo +Counter.check_counts(2, 1, 0, 0, 1, 3) + +# Move semantics not used +Counter.reset_counts() +mo = MovableCopyable.createConst() +del mo +Counter.check_counts(2, 1, 1, 0, 0, 3) diff --git a/Examples/test-suite/python/typemap_out_optimal_runme.py b/Examples/test-suite/python/typemap_out_optimal_runme.py index c325ece55..beed46bfc 100644 --- a/Examples/test-suite/python/typemap_out_optimal_runme.py +++ b/Examples/test-suite/python/typemap_out_optimal_runme.py @@ -2,3 +2,6 @@ from typemap_out_optimal import * cvar.XX_debug = False x = XX.create() +del x +x = XX.createConst() +del x diff --git a/Examples/test-suite/typemap_out_optimal.i b/Examples/test-suite/typemap_out_optimal.i index d707ed2d5..11f1db80f 100644 --- a/Examples/test-suite/typemap_out_optimal.i +++ b/Examples/test-suite/typemap_out_optimal.i @@ -4,15 +4,15 @@ // Just the following languages tested #if defined (SWIGCSHARP) || defined (SWIGD) %typemap(out, optimal="1") SWIGTYPE %{ - $result = new $1_ltype((const $1_ltype &)$1); + $result = new $1_ltype($1); %} #elif defined (SWIGJAVA) %typemap(out, optimal="1") SWIGTYPE %{ - *($&1_ltype*)&$result = new $1_ltype((const $1_ltype &)$1); + *($&1_ltype*)&$result = new $1_ltype($1); %} #elif defined (SWIGUTL) %typemap(out,noblock="1", optimal="1") SWIGTYPE { - %set_output(SWIG_NewPointerObj(%new_copy($1, $ltype), $&descriptor, SWIG_POINTER_OWN | %newpointer_flags)); + %set_output(SWIG_NewPointerObj(new $1_ltype($1), $&descriptor, SWIG_POINTER_OWN | %newpointer_flags)); } #endif @@ -32,9 +32,14 @@ struct XX { XX(const XX &other) { if (debug) cout << "XX(const XX &)" << endl; } XX& operator =(const XX &other) { if (debug) cout << "operator=(const XX &)" << endl; return *this; } ~XX() { if (debug) cout << "~XX()" << endl; } - static XX create() { + +// Note: best observed RVO for C#, Java and Python with g++-6 to g++-10 (just one constructor and one destructor call) + static XX create() { return XX(123); } + static const XX createConst() { + return XX(456); + } static bool debug; }; bool XX::debug = true; diff --git a/Lib/cffi/cffi.swg b/Lib/cffi/cffi.swg index 690081032..205bf7900 100644 --- a/Lib/cffi/cffi.swg +++ b/Lib/cffi/cffi.swg @@ -90,7 +90,8 @@ enum SWIGTYPE, SWIGTYPE *, SWIGTYPE[ANY], SWIGTYPE &, SWIGTYPE && "$result = $1;"; #ifdef __cplusplus -%typemap(out) SWIGTYPE "$result = new $1_type($1);"; +%typemap(out) SWIGTYPE +%{ $result = new $1_ltype($1); %} #else %typemap(out) SWIGTYPE { $result = ($&1_ltype) malloc(sizeof($1_type)); diff --git a/Lib/csharp/csharp.swg b/Lib/csharp/csharp.swg index 0e180f576..d4bcd3c80 100644 --- a/Lib/csharp/csharp.swg +++ b/Lib/csharp/csharp.swg @@ -399,7 +399,7 @@ SWIGINTERN const char * SWIG_UnpackData(const char *c, void *ptr, size_t sz) { %typemap(out) SWIGTYPE #ifdef __cplusplus -%{ $result = new $1_ltype((const $1_ltype &)$1); %} +%{ $result = new $1_ltype($1); %} #else { $&1_ltype $1ptr = ($&1_ltype) malloc(sizeof($1_ltype)); diff --git a/Lib/d/dswigtype.swg b/Lib/d/dswigtype.swg index 1d97cb089..535e8d576 100644 --- a/Lib/d/dswigtype.swg +++ b/Lib/d/dswigtype.swg @@ -52,7 +52,7 @@ %typemap(out) SWIGTYPE #ifdef __cplusplus -%{ $result = new $1_ltype((const $1_ltype &)$1); %} +%{ $result = new $1_ltype($1); %} #else { $&1_ltype $1ptr = ($&1_ltype) malloc(sizeof($1_ltype)); diff --git a/Lib/guile/typemaps.i b/Lib/guile/typemaps.i index f4d3a0118..4ad1aefa8 100644 --- a/Lib/guile/typemaps.i +++ b/Lib/guile/typemaps.i @@ -130,7 +130,7 @@ #ifdef __cplusplus { $&1_ltype resultptr; - resultptr = new $1_ltype((const $1_ltype &) $1); + resultptr = new $1_ltype($1); $result = SWIG_NewPointerObj (resultptr, $&1_descriptor, 1); } #else @@ -145,8 +145,7 @@ %typemap(varout) SWIGTYPE #ifdef __cplusplus { - $&1_ltype resultptr; - resultptr = new $1_ltype((const $1_ltype&) $1); + $&1_ltype resultptr = ($&1_ltype)&$1; $result = SWIG_NewPointerObj (resultptr, $&1_descriptor, 0); } #else diff --git a/Lib/java/java.swg b/Lib/java/java.swg index 8f95f3a3b..7967c1882 100644 --- a/Lib/java/java.swg +++ b/Lib/java/java.swg @@ -665,7 +665,7 @@ Swig::LocalRefGuard $1_refguard(jenv, $input); } %typemap(out) SWIGTYPE #ifdef __cplusplus -%{ *($&1_ltype*)&$result = new $1_ltype((const $1_ltype &)$1); %} +%{ *($&1_ltype*)&$result = new $1_ltype($1); %} #else { $&1_ltype $1ptr = ($&1_ltype) malloc(sizeof($1_ltype)); diff --git a/Lib/lua/luatypemaps.swg b/Lib/lua/luatypemaps.swg index f8e12846b..97ecef41e 100644 --- a/Lib/lua/luatypemaps.swg +++ b/Lib/lua/luatypemaps.swg @@ -217,7 +217,7 @@ $1=($1_ltype)&temp;%} #ifdef __cplusplus %typemap(out) SWIGTYPE { - $&1_ltype resultptr = new $1_ltype((const $1_ltype &) $1); + $&1_ltype resultptr = new $1_ltype($1); SWIG_NewPointerObj(L,(void *) resultptr,$&1_descriptor,1); SWIG_arg++; } #else diff --git a/Lib/mzscheme/typemaps.i b/Lib/mzscheme/typemaps.i index 09bda2cca..059dd06ff 100644 --- a/Lib/mzscheme/typemaps.i +++ b/Lib/mzscheme/typemaps.i @@ -127,7 +127,7 @@ #ifdef __cplusplus { $&1_ltype resultptr; - resultptr = new $1_ltype(($1_ltype &) $1); + resultptr = new $1_ltype($1); $result = SWIG_NewPointerObj (resultptr, $&1_descriptor, 1); } #else diff --git a/Lib/ocaml/ocaml.swg b/Lib/ocaml/ocaml.swg index afb01daea..0c190bbc4 100644 --- a/Lib/ocaml/ocaml.swg +++ b/Lib/ocaml/ocaml.swg @@ -93,10 +93,14 @@ $1 = *(($&1_ltype) caml_ptr_val($input,$&1_descriptor)) ; } +%typemap(varout) SWIGTYPE { + $result = SWIG_Ocaml_ptr_to_val("create_$ntype_from_ptr", (void *)&$1, $&1_descriptor); +} + #ifdef __cplusplus %typemap(out) SWIGTYPE { - $&1_ltype temp = new $ltype((const $1_ltype &) $1); + $&1_ltype temp = new $1_ltype($1); $result = SWIG_Ocaml_ptr_to_val("create_$ntype_from_ptr", (void *)temp, $&1_descriptor); } @@ -110,6 +114,10 @@ #endif +%typemap(varout) SWIGTYPE * { + $result = SWIG_Ocaml_ptr_to_val("create_$ntype_from_ptr", (void *)$1, $1_descriptor); +} + %typemap(directorin) SWIGTYPE { $<ype temp = new $ltype((const $ltype &)$1); swig_result = SWIG_Ocaml_ptr_to_val("create_$ltype_from_ptr", (void *)temp, $&1_descriptor); diff --git a/Lib/ocaml/std_string.i b/Lib/ocaml/std_string.i index 712c3bb73..a8881a16c 100644 --- a/Lib/ocaml/std_string.i +++ b/Lib/ocaml/std_string.i @@ -83,9 +83,18 @@ class wstring; $result = caml_val_string_len($1.c_str(),$1.size()); } +%typemap(varout) string { + $result = caml_val_string_len($1.c_str(),$1.size()); +} + %typemap(out) string * { $result = caml_val_string_len((*$1).c_str(),(*$1).size()); } + +%typemap(varout) string * { + $result = caml_val_string_len((*$1).c_str(),(*$1).size()); +} + %typemap(typecheck) string, const string & = char *; } diff --git a/Lib/php/php.swg b/Lib/php/php.swg index ffcffde70..7d6d5f29d 100644 --- a/Lib/php/php.swg +++ b/Lib/php/php.swg @@ -443,7 +443,7 @@ %typemap(out, phptype="SWIGTYPE") SWIGTYPE { #ifdef __cplusplus - $&1_ltype resultobj = new $1_ltype((const $1_ltype &) $1); + $&1_ltype resultobj = new $1_ltype($1); #else $&1_ltype resultobj = ($&1_ltype) malloc(sizeof($1_type)); memcpy(resultobj, &$1, sizeof($1_type)); diff --git a/Lib/ruby/std_set.i b/Lib/ruby/std_set.i index e38702ef5..1b425c6b5 100644 --- a/Lib/ruby/std_set.i +++ b/Lib/ruby/std_set.i @@ -180,17 +180,14 @@ // Redefine std::set iterator/reverse_iterator typemap %typemap(out,noblock=1) iterator, reverse_iterator { - $result = SWIG_NewPointerObj(swig::make_set_nonconst_iterator(%static_cast($1,const $type &), - self), - swig::Iterator::descriptor(),SWIG_POINTER_OWN); + $result = SWIG_NewPointerObj((swig::make_set_nonconst_iterator<$type>($1, self)), swig::Iterator::descriptor(), SWIG_POINTER_OWN); } // Redefine std::set std::pair typemap %typemap(out,noblock=1,fragment="RubyPairBoolOutputIterator") std::pair { $result = rb_ary_new2(2); - rb_ary_push($result, SWIG_NewPointerObj(swig::make_set_nonconst_iterator(%static_cast($1,$type &).first), - swig::Iterator::descriptor(),SWIG_POINTER_OWN)); + rb_ary_push($result, SWIG_NewPointerObj((swig::make_set_nonconst_iterator($1.first)), swig::Iterator::descriptor(), SWIG_POINTER_OWN)); rb_ary_push($result, SWIG_From(bool)(%static_cast($1,const $type &).second)); } diff --git a/Lib/swig.swg b/Lib/swig.swg index f6ba3a69f..188c47e03 100644 --- a/Lib/swig.swg +++ b/Lib/swig.swg @@ -677,10 +677,12 @@ template class SwigValueWrapper { public: SwigValueWrapper() : pointer(0) { } SwigValueWrapper& operator=(const T& t) { SwigSmartPointer tmp(new T(t)); pointer = tmp; return *this; } -#if __cplusplus >= 201103L +#if __cplusplus >=201103L SwigValueWrapper& operator=(T&& t) { SwigSmartPointer tmp(new T(std::move(t))); pointer = tmp; return *this; } -#endif + operator T&&() const { return std::move(*pointer.ptr); } +#else operator T&() const { return *pointer.ptr; } +#endif T *operator&() { return pointer.ptr; } };%} diff --git a/Lib/typemaps/swigtype.swg b/Lib/typemaps/swigtype.swg index 402313ebf..6973e3a10 100644 --- a/Lib/typemaps/swigtype.swg +++ b/Lib/typemaps/swigtype.swg @@ -146,9 +146,15 @@ } /* Return by value */ +#ifdef __cplusplus %typemap(out, noblock=1) SWIGTYPE { - %set_output(SWIG_NewPointerObj(%new_copy($1, $ltype), $&descriptor, SWIG_POINTER_OWN | %newpointer_flags)); + %set_output(SWIG_NewPointerObj((new $1_ltype($1)), $&descriptor, SWIG_POINTER_OWN | %newpointer_flags)); } +#else +%typemap(out, noblock=1) SWIGTYPE { + %set_output(SWIG_NewPointerObj(%new_copy($1, $1_ltype), $&descriptor, SWIG_POINTER_OWN | %newpointer_flags)); +} +#endif /* ----------------------------------------------------------------------------- * --- Variable input --- @@ -534,7 +540,7 @@ * ------------------------------------------------------------ */ %typemap(throws,noblock=1) SWIGTYPE { - %raise(SWIG_NewPointerObj(%new_copy($1, $ltype),$&descriptor,SWIG_POINTER_OWN), "$type", $&descriptor); + %raise(SWIG_NewPointerObj(%new_copy($1, $1_ltype),$&descriptor,SWIG_POINTER_OWN), "$type", $&descriptor); } %typemap(throws,noblock=1) SWIGTYPE * { @@ -703,9 +709,15 @@ /* INSTANCE typemap */ +#ifdef __cplusplus +%typemap(out,noblock=1) SWIGTYPE INSTANCE { + %set_output(SWIG_NewInstanceObj((new $1_ltype($1)), $&1_descriptor, SWIG_POINTER_OWN | %newinstance_flags)); +} +#else %typemap(out,noblock=1) SWIGTYPE INSTANCE { %set_output(SWIG_NewInstanceObj(%new_copy($1, $1_ltype), $&1_descriptor, SWIG_POINTER_OWN | %newinstance_flags)); } +#endif %typemap(out,noblock=1) SWIGTYPE *INSTANCE, SWIGTYPE &INSTANCE, SWIGTYPE INSTANCE[] { %set_output(SWIG_NewInstanceObj(%as_voidptr($1), $1_descriptor, $owner | %newinstance_flags)); From 7cab5accef810642e500194debecedfcad940deb Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Wed, 29 Jun 2022 22:46:03 +0100 Subject: [PATCH 487/662] SwigValueWrapper::operator& should always have been const --- Lib/swig.swg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib/swig.swg b/Lib/swig.swg index 188c47e03..416d40982 100644 --- a/Lib/swig.swg +++ b/Lib/swig.swg @@ -683,7 +683,7 @@ public: #else operator T&() const { return *pointer.ptr; } #endif - T *operator&() { return pointer.ptr; } + T *operator&() const { return pointer.ptr; } };%} /* From 1993b334a6583aaec1ce28000c3b3a1ae0406d5d Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Thu, 30 Jun 2022 17:28:25 +0100 Subject: [PATCH 488/662] Generate swiglabels code earlier on in runtime code Since the recent inclusion of , the warning suppressions in swiglabels.swg stopped working as they appear after this include file. In particular, The _MSC_VER warnings were not working. --- Lib/swig.swg | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/Lib/swig.swg b/Lib/swig.swg index 416d40982..ca7586457 100644 --- a/Lib/swig.swg +++ b/Lib/swig.swg @@ -602,6 +602,10 @@ namespace std { * Runtime code * ----------------------------------------------------------------------------- */ + +%insert("runtime") "swiglabels.swg" + + /* The SwigValueWrapper class */ /* @@ -703,8 +707,3 @@ template T SwigValueInit() { %} #endif -/* The swiglabels */ - -%insert("runtime") "swiglabels.swg" - - From 299880e6a658934d39ae3b53159a3b61f1051c16 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Sat, 2 Jul 2022 16:06:32 +0100 Subject: [PATCH 489/662] Add std::unique support Simple copy of current auto_ptr support (just suppport for functions returning std::unique_ptr). Closes #1722 --- CHANGES.current | 10 ++ Doc/Manual/CPlusPlus11.html | 6 +- Doc/Manual/Contents.html | 1 + Doc/Manual/Library.html | 117 ++++++++++++++++-- Examples/test-suite/common.mk | 1 + Examples/test-suite/cpp11_std_unique_ptr.i | 53 ++++++++ .../csharp/cpp11_std_unique_ptr_runme.cs | 64 ++++++++++ .../java/cpp11_std_unique_ptr_runme.java | 68 ++++++++++ .../python/cpp11_std_unique_ptr_runme.py | 17 +++ .../ruby/cpp11_std_unique_ptr_runme.rb | 27 ++++ Lib/csharp/std_unique_ptr.i | 27 ++++ Lib/java/std_unique_ptr.i | 29 +++++ Lib/python/std_unique_ptr.i | 19 +++ Lib/ruby/std_unique_ptr.i | 19 +++ 14 files changed, 443 insertions(+), 15 deletions(-) create mode 100644 Examples/test-suite/cpp11_std_unique_ptr.i create mode 100644 Examples/test-suite/csharp/cpp11_std_unique_ptr_runme.cs create mode 100644 Examples/test-suite/java/cpp11_std_unique_ptr_runme.java create mode 100644 Examples/test-suite/python/cpp11_std_unique_ptr_runme.py create mode 100644 Examples/test-suite/ruby/cpp11_std_unique_ptr_runme.rb create mode 100644 Lib/csharp/std_unique_ptr.i create mode 100644 Lib/java/std_unique_ptr.i create mode 100644 Lib/python/std_unique_ptr.i create mode 100644 Lib/ruby/std_unique_ptr.i diff --git a/CHANGES.current b/CHANGES.current index 6584e1781..57dd6c765 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-07-02: wsfulton + #1722 [C#, Java, Python, Ruby] Add std::unique_ptr support. Ported from std::auto_ptr. + Use the %unique_ptr(T) macro as follows for usage std::unique_ptr. For example, for + a class called Klass: + + %include "std_unique_ptr.i" + %unique_ptr(Klass) + + Support is currently limited to only returning a std::unique_ptr from a function. + 2022-06-29: wsfulton #999 #1044 Enhance SWIGTYPE "out" typemaps to use std::move when copying objects, thereby making use of move semantics when wrapping a function returning diff --git a/Doc/Manual/CPlusPlus11.html b/Doc/Manual/CPlusPlus11.html index b98713961..52764eeef 100644 --- a/Doc/Manual/CPlusPlus11.html +++ b/Doc/Manual/CPlusPlus11.html @@ -1236,8 +1236,10 @@ While SWIG could provide wrappers for the new C++11 regular expressions classes,

        SWIG provides special smart pointer handling for std::shared_ptr in the same way it has support for boost::shared_ptr. -Please see the shared_ptr smart pointer library section. -There is no special smart pointer handling available for std::weak_ptr and std::unique_ptr yet. +Please see the shared_ptr smart pointer +and unique_ptr smart pointer library sections. +There is no special smart pointer handling available for std::weak_ptr. +

        7.3.6 Extensible random number facility

        diff --git a/Doc/Manual/Contents.html b/Doc/Manual/Contents.html index ef87cf78d..39d83bd14 100644 --- a/Doc/Manual/Contents.html +++ b/Doc/Manual/Contents.html @@ -448,6 +448,7 @@
      • shared_ptr and templates
      • shared_ptr and directors
      +
    • unique_ptr smart pointer
    • auto_ptr smart pointer
  • Utility Libraries diff --git a/Doc/Manual/Library.html b/Doc/Manual/Library.html index 3ecfc3a39..b18ecc957 100644 --- a/Doc/Manual/Library.html +++ b/Doc/Manual/Library.html @@ -40,6 +40,7 @@
  • shared_ptr and templates
  • shared_ptr and directors +
  • unique_ptr smart pointer
  • auto_ptr smart pointer
  • Utility Libraries @@ -2040,38 +2041,45 @@ The SWIG code below shows the required ordering: The languages that support shared_ptr also have support for using shared_ptr with directors.

    - -

    12.4.5 auto_ptr smart pointer

    +

    12.4.5 unique_ptr smart pointer

    -While std::auto_ptr is deprecated in C++11, some existing code may -still be using it, so SWIG provides limited support for this class: -std_auto_ptr.i defines the typemaps which apply to the functions -returning objects of this type. Any other use of std_auto_ptr.i is not -directly supported. +The std_unique_ptr.i library file provides SWIG's unique_ptr support. +It defines typemaps and a macro, %unique_ptr(T), to use for handling +std::unique_ptr<T> for a type T. +The type T must be non-primitive. +This macro should be used before any code declaring or using type T. +Ordering requirements for using this smart pointer macro are the same as the +equivalent %shared_ptr(T) macro covered in the previous section.

    -A typical example of use would be +Note that the support provided is limited to returning this smart pointer from a function. +Any other use of std::auto_ptr is not directly provided yet. +

    + +

    +Example usage would be

    -%include <std_auto_ptr.i>
    +%include <std_unique_ptr.i>
     
    -%auto_ptr(Klass)
    +%unique_ptr(Klass)
     %inline %{
    +#include <memory>
     class Klass {
     public:
       // Factory function creating objects of this class:
    -  static std::auto_ptr<Klass> Create(int value) {
    -    return std::auto_ptr<Klass>(new Klass(value));
    +  static std::unique_ptr<Klass> Create(int value) {
    +    return std::unique_ptr<Klass>(new Klass(value));
       }
     
       int getValue() const { return m_value; }
     
     private:
    -  DerivedIntValue(int value) : m_value(value) {}
    +  Klass(int value) : m_value(value) {}
       int m_value;
     };
     %}
    @@ -2090,6 +2098,89 @@ int value = k.getValue();
     
    +

    +The implementation simply calls std::unique_ptr::release() to obtain +the underlying raw pointer. The pointer is then used to create a target language +proxy class in the same way that SWIG handles a C++ function returning a class by value. +The target language proxy class then owns the memory pointed to by the raw pointer +and memory handling is identical to normal SWIG proxy class handling of the underlying C++ memory. +Note that an object returned by value is first copied/moved from the stack onto the heap in order to obtain +a raw pointer on the heap, whereas the underlying raw pointer in std::unique_ptr already points to an object the heap. +

    + +

    +Note that the implementation is quite different to the std::shared_ptr smart pointer, +where the proxy class manages the underlying C++ memory as a pointer to a shared_ptr instead of a plain raw pointer. +

    + +

    12.4.6 auto_ptr smart pointer

    + + +

    +While std::auto_ptr is deprecated in C++11, some existing code may +still be using it, so SWIG provides limited support for this class by some target languages. +

    + +

    +The std_auto_ptr.i library file provides SWIG's auto_ptr support. +It defines typemaps and a macro, %auto_ptr(T), to use for handling +std::auto_ptr<T> for a type T. +The type T must be non-primitive. +This macro should be used before any code declaring or using type T. +Ordering requirements for using this smart pointer macro are the same as the +equivalent %shared_ptr(T) and %unique_ptr macros covered in +the previous two sections. +

    + +

    +Note that the support provided is limited to returning this smart pointer from a function. +Any other use of std::auto_ptr is not directly provided. +

    + +

    +Example usage would be +

    +
    +
    +%include <std_auto_ptr.i>
    +
    +%auto_ptr(Klass)
    +%inline %{
    +#include <memory>
    +class Klass {
    +public:
    +  // Factory function creating objects of this class:
    +  static std::auto_ptr<Klass> Create(int value) {
    +    return std::auto_ptr<Klass>(new Klass(value));
    +  }
    +
    +  int getValue() const { return m_value; }
    +
    +private:
    +  Klass(int value) : m_value(value) {}
    +  int m_value;
    +};
    +%}
    +
    +
    + +

    +The returned objects can be used naturally from the target language, e.g. from +C#: +

    + +
    +
    +Klass k = Klass.Create(17);
    +int value = k.getValue();
    +
    +
    + +

    +The implementation simply calls std::auto_ptr::release() to obtain the underlying raw pointer. +That is, it works the same way covered in the previous section for std::unique_ptr. +

    +

    12.5 Utility Libraries

    diff --git a/Examples/test-suite/common.mk b/Examples/test-suite/common.mk index a640febc1..bf0e52f02 100644 --- a/Examples/test-suite/common.mk +++ b/Examples/test-suite/common.mk @@ -612,6 +612,7 @@ CPP11_TEST_CASES += \ cpp11_sizeof_object \ cpp11_static_assert \ cpp11_std_array \ + cpp11_std_unique_ptr \ cpp11_strongly_typed_enumerations \ cpp11_thread_local \ cpp11_template_double_brackets \ diff --git a/Examples/test-suite/cpp11_std_unique_ptr.i b/Examples/test-suite/cpp11_std_unique_ptr.i new file mode 100644 index 000000000..518d9be6e --- /dev/null +++ b/Examples/test-suite/cpp11_std_unique_ptr.i @@ -0,0 +1,53 @@ +%module cpp11_std_unique_ptr + +#if defined(SWIGCSHARP) || defined(SWIGJAVA) || defined(SWIGPYTHON) || defined(SWIGRUBY) + +%include "std_unique_ptr.i" + +%unique_ptr(Klass) + +%inline %{ +#include +#include +#include "swig_examples_lock.h" + +class Klass { +public: + explicit Klass(const char* label) : + m_label(label) + { + SwigExamples::Lock lock(critical_section); + total_count++; + } + + const char* getLabel() const { return m_label.c_str(); } + + ~Klass() + { + SwigExamples::Lock lock(critical_section); + total_count--; + } + + static int getTotal_count() { return total_count; } + +private: + static SwigExamples::CriticalSection critical_section; + static int total_count; + + std::string m_label; +}; + +SwigExamples::CriticalSection Klass::critical_section; +int Klass::total_count = 0; + +%} + +%inline %{ + +std::unique_ptr makeKlassUniquePtr(const char* label) { + return std::unique_ptr(new Klass(label)); +} + +%} + +#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 new file mode 100644 index 000000000..db5c8cff0 --- /dev/null +++ b/Examples/test-suite/csharp/cpp11_std_unique_ptr_runme.cs @@ -0,0 +1,64 @@ +using System; +using cpp11_std_unique_ptrNamespace; + +public class cpp11_std_unique_ptr_runme { + private static void WaitForGC() + { + System.GC.Collect(); + System.GC.WaitForPendingFinalizers(); + System.Threading.Thread.Sleep(10); + } + + public static void Main() + { + Klass k1 = cpp11_std_unique_ptr.makeKlassUniquePtr("first"); + if (k1.getLabel() != "first") + throw new Exception("wrong object label"); + + Klass k2 = cpp11_std_unique_ptr.makeKlassUniquePtr("second"); + if (Klass.getTotal_count() != 2) + throw new Exception("number of objects should be 2"); + + using (Klass k3 = cpp11_std_unique_ptr.makeKlassUniquePtr("second")) { + if (Klass.getTotal_count() != 3) + throw new Exception("number of objects should be 3"); + } + if (Klass.getTotal_count() != 2) + throw new Exception("number of objects should be 2"); + + k1 = null; + { + int countdown = 500; + int expectedCount = 1; + while (true) { + WaitForGC(); + if (--countdown == 0) + break; + if (Klass.getTotal_count() == expectedCount) + break; + }; + int actualCount = Klass.getTotal_count(); + if (actualCount != expectedCount) + Console.Error.WriteLine("Expected count: " + expectedCount + " Actual count: " + actualCount); // Finalizers are not guaranteed to be run and sometimes they just don't + } + + if (k2.getLabel() != "second") + throw new Exception("wrong object label"); + + k2 = null; + { + int countdown = 500; + int expectedCount = 0; + while (true) { + WaitForGC(); + if (--countdown == 0) + break; + if (Klass.getTotal_count() == expectedCount) + break; + } + int actualCount = Klass.getTotal_count(); + if (actualCount != expectedCount) + Console.Error.WriteLine("Expected count: " + expectedCount + " Actual count: " + actualCount); // Finalizers are not guaranteed to be run and sometimes they just don't + } + } +} diff --git a/Examples/test-suite/java/cpp11_std_unique_ptr_runme.java b/Examples/test-suite/java/cpp11_std_unique_ptr_runme.java new file mode 100644 index 000000000..a734b0e5e --- /dev/null +++ b/Examples/test-suite/java/cpp11_std_unique_ptr_runme.java @@ -0,0 +1,68 @@ +import cpp11_std_unique_ptr.*; + +public class cpp11_std_unique_ptr_runme { + static { + try { + System.loadLibrary("cpp11_std_unique_ptr"); + } 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); + } + } + + private static void WaitForGC() + { + System.gc(); + System.runFinalization(); + try { + java.lang.Thread.sleep(10); + } catch (java.lang.InterruptedException e) { + } + } + + public static void main(String argv[]) throws Throwable + { + Klass k1 = cpp11_std_unique_ptr.makeKlassUniquePtr("first"); + if (!k1.getLabel().equals("first")) + throw new RuntimeException("wrong object label"); + + Klass k2 = cpp11_std_unique_ptr.makeKlassUniquePtr("second"); + if (Klass.getTotal_count() != 2) + throw new RuntimeException("number of objects should be 2"); + + k1 = null; + { + int countdown = 500; + int expectedCount = 1; + while (true) { + WaitForGC(); + if (--countdown == 0) + break; + if (Klass.getTotal_count() == expectedCount) + break; + } + int actualCount = Klass.getTotal_count(); + if (actualCount != expectedCount) + System.err.println("GC failed to run (cpp11_std_unique_ptr 1). Expected count: " + expectedCount + " Actual count: " + actualCount); // Finalizers are not guaranteed to be run and sometimes they just don't + } + + if (!k2.getLabel().equals("second")) + throw new RuntimeException("wrong object label"); + + k2 = null; + { + int countdown = 500; + int expectedCount = 0; + while (true) { + WaitForGC(); + if (--countdown == 0) + break; + if (Klass.getTotal_count() == expectedCount) + break; + }; + int actualCount = Klass.getTotal_count(); + if (actualCount != expectedCount) + System.err.println("GC failed to run (cpp11_std_unique_ptr 2). Expected count: " + expectedCount + " Actual count: " + actualCount); // Finalizers are not guaranteed to be run and sometimes they just don't + } + } +} diff --git a/Examples/test-suite/python/cpp11_std_unique_ptr_runme.py b/Examples/test-suite/python/cpp11_std_unique_ptr_runme.py new file mode 100644 index 000000000..a84efcd5f --- /dev/null +++ b/Examples/test-suite/python/cpp11_std_unique_ptr_runme.py @@ -0,0 +1,17 @@ +from cpp11_std_unique_ptr import * + +k1 = makeKlassUniquePtr("first") +k2 = makeKlassUniquePtr("second") +if Klass.getTotal_count() != 2: + raise "number of objects should be 2" + +del k1 +if Klass.getTotal_count() != 1: + raise "number of objects should be 1" + +if k2.getLabel() != "second": + raise "wrong object label" + +del k2 +if Klass.getTotal_count() != 0: + raise "no objects should be left" diff --git a/Examples/test-suite/ruby/cpp11_std_unique_ptr_runme.rb b/Examples/test-suite/ruby/cpp11_std_unique_ptr_runme.rb new file mode 100644 index 000000000..cfc03fe2a --- /dev/null +++ b/Examples/test-suite/ruby/cpp11_std_unique_ptr_runme.rb @@ -0,0 +1,27 @@ +#!/usr/bin/env ruby + +require 'swig_assert' + +require 'cpp11_std_unique_ptr' + +def gc_check(expected_count) +# GC.start(full_mark: true, immediate_sweep: true) + GC.start +# GC is not reliably run, skip check +# swig_assert_equal_simple(expected_count, Cpp11_std_unique_ptr::Klass::getTotal_count()) +end + +k1 = Cpp11_std_unique_ptr::makeKlassUniquePtr("first") +k2 = Cpp11_std_unique_ptr::makeKlassUniquePtr("second") +swig_assert_equal_simple(2, Cpp11_std_unique_ptr::Klass::getTotal_count()) + +gc_check(2) +k1 = nil +gc_check(1) + +swig_assert_equal_simple(k2.getLabel(), "second") +gc_check(1) + +k2 = nil +gc_check(0) + diff --git a/Lib/csharp/std_unique_ptr.i b/Lib/csharp/std_unique_ptr.i new file mode 100644 index 000000000..b2716756a --- /dev/null +++ b/Lib/csharp/std_unique_ptr.i @@ -0,0 +1,27 @@ +/* ----------------------------------------------------------------------------- + * std_unique_ptr.i + * + * The typemaps here allow handling functions returning std::unique_ptr<>, + * which is the most common use of this type. If you have functions taking it + * as parameter, these typemaps can't be used for them and you need to do + * something else (e.g. use shared_ptr<> which SWIG supports fully). + * ----------------------------------------------------------------------------- */ + +%define %unique_ptr(TYPE) +%typemap (ctype) std::unique_ptr< TYPE > "void *" +%typemap (imtype, out="System.IntPtr") std::unique_ptr< TYPE > "HandleRef" +%typemap (cstype) std::unique_ptr< TYPE > "$typemap(cstype, TYPE)" +%typemap (out) std::unique_ptr< TYPE > %{ + $result = (void *)$1.release(); +%} +%typemap(csout, excode=SWIGEXCODE) std::unique_ptr< TYPE > { + System.IntPtr cPtr = $imcall; + $typemap(cstype, TYPE) ret = (cPtr == System.IntPtr.Zero) ? null : new $typemap(cstype, TYPE)(cPtr, true);$excode + return ret; + } +%template() std::unique_ptr< TYPE >; +%enddef + +namespace std { + template class unique_ptr {}; +} diff --git a/Lib/java/std_unique_ptr.i b/Lib/java/std_unique_ptr.i new file mode 100644 index 000000000..665d913ae --- /dev/null +++ b/Lib/java/std_unique_ptr.i @@ -0,0 +1,29 @@ +/* ----------------------------------------------------------------------------- + * std_unique_ptr.i + * + * The typemaps here allow handling functions returning std::unique_ptr<>, + * which is the most common use of this type. If you have functions taking it + * as parameter, these typemaps can't be used for them and you need to do + * something else (e.g. use shared_ptr<> which SWIG supports fully). + * ----------------------------------------------------------------------------- */ + +%define %unique_ptr(TYPE) +%typemap (jni) std::unique_ptr< TYPE > "jlong" +%typemap (jtype) std::unique_ptr< TYPE > "long" +%typemap (jstype) std::unique_ptr< TYPE > "$typemap(jstype, TYPE)" + +%typemap (out) std::unique_ptr< TYPE > %{ + jlong lpp = 0; + *(TYPE **) &lpp = $1.release(); + $result = lpp; +%} +%typemap(javaout) std::unique_ptr< TYPE > { + long cPtr = $jnicall; + return (cPtr == 0) ? null : new $typemap(jstype, TYPE)(cPtr, true); + } +%template() std::unique_ptr< TYPE >; +%enddef + +namespace std { + template class unique_ptr {}; +} diff --git a/Lib/python/std_unique_ptr.i b/Lib/python/std_unique_ptr.i new file mode 100644 index 000000000..331817f76 --- /dev/null +++ b/Lib/python/std_unique_ptr.i @@ -0,0 +1,19 @@ +/* ----------------------------------------------------------------------------- + * std_unique_ptr.i + * + * The typemaps here allow handling functions returning std::unique_ptr<>, + * which is the most common use of this type. If you have functions taking it + * as parameter, these typemaps can't be used for them and you need to do + * something else (e.g. use shared_ptr<> which SWIG supports fully). + * ----------------------------------------------------------------------------- */ + +%define %unique_ptr(TYPE) +%typemap (out) std::unique_ptr< TYPE > %{ + %set_output(SWIG_NewPointerObj($1.release(), $descriptor(TYPE *), SWIG_POINTER_OWN | %newpointer_flags)); +%} +%template() std::unique_ptr< TYPE >; +%enddef + +namespace std { + template class unique_ptr {}; +} diff --git a/Lib/ruby/std_unique_ptr.i b/Lib/ruby/std_unique_ptr.i new file mode 100644 index 000000000..163c7c2d1 --- /dev/null +++ b/Lib/ruby/std_unique_ptr.i @@ -0,0 +1,19 @@ +/* ----------------------------------------------------------------------------- + * std_unique_ptr.i + * + * The typemaps here allow handling functions returning std::unique_ptr<>, + * which is the most common use of this type. If you have functions taking it + * as parameter, these typemaps can't be used for them and you need to do + * something else (e.g. use shared_ptr<> which SWIG supports fully). + * ----------------------------------------------------------------------------- */ + +%define %unique_ptr(TYPE) +%typemap (out) std::unique_ptr< TYPE > %{ + %set_output(SWIG_NewPointerObj($1.release(), $descriptor(TYPE *), SWIG_POINTER_OWN | %newpointer_flags)); +%} +%template() std::unique_ptr< TYPE >; +%enddef + +namespace std { + template class unique_ptr {}; +} From 980e21a3bf371ee8dbeb8276a5d61861e749fa7b Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Sat, 2 Jul 2022 16:12:16 +0100 Subject: [PATCH 490/662] Cosmetic changes to auto_ptr library files --- Lib/csharp/std_auto_ptr.i | 26 ++++++++++++++------------ Lib/java/std_auto_ptr.i | 28 +++++++++++++++------------- Lib/python/std_auto_ptr.i | 18 ++++++++++-------- Lib/ruby/std_auto_ptr.i | 18 ++++++++++-------- 4 files changed, 49 insertions(+), 41 deletions(-) diff --git a/Lib/csharp/std_auto_ptr.i b/Lib/csharp/std_auto_ptr.i index 1d91c9872..068d3a9d1 100644 --- a/Lib/csharp/std_auto_ptr.i +++ b/Lib/csharp/std_auto_ptr.i @@ -1,23 +1,25 @@ -/* - The typemaps here allow handling functions returning std::auto_ptr<>, - which is the most common use of this type. If you have functions taking it - as parameter, these typemaps can't be used for them and you need to do - something else (e.g. use shared_ptr<> which SWIG supports fully). - */ +/* ----------------------------------------------------------------------------- + * std_auto_ptr.i + * + * The typemaps here allow handling functions returning std::auto_ptr<>, + * which is the most common use of this type. If you have functions taking it + * as parameter, these typemaps can't be used for them and you need to do + * something else (e.g. use shared_ptr<> which SWIG supports fully). + * ----------------------------------------------------------------------------- */ %define %auto_ptr(TYPE) -%typemap (ctype) std::auto_ptr "void *" -%typemap (imtype, out="System.IntPtr") std::auto_ptr "HandleRef" -%typemap (cstype) std::auto_ptr "$typemap(cstype, TYPE)" -%typemap (out) std::auto_ptr %{ +%typemap (ctype) std::auto_ptr< TYPE > "void *" +%typemap (imtype, out="System.IntPtr") std::auto_ptr< TYPE > "HandleRef" +%typemap (cstype) std::auto_ptr< TYPE > "$typemap(cstype, TYPE)" +%typemap (out) std::auto_ptr< TYPE > %{ $result = (void *)$1.release(); %} -%typemap(csout, excode=SWIGEXCODE) std::auto_ptr { +%typemap(csout, excode=SWIGEXCODE) std::auto_ptr< TYPE > { System.IntPtr cPtr = $imcall; $typemap(cstype, TYPE) ret = (cPtr == System.IntPtr.Zero) ? null : new $typemap(cstype, TYPE)(cPtr, true);$excode return ret; } -%template() std::auto_ptr; +%template() std::auto_ptr< TYPE >; %enddef namespace std { diff --git a/Lib/java/std_auto_ptr.i b/Lib/java/std_auto_ptr.i index 69ac2841f..0eb5fe155 100644 --- a/Lib/java/std_auto_ptr.i +++ b/Lib/java/std_auto_ptr.i @@ -1,25 +1,27 @@ -/* - The typemaps here allow handling functions returning std::auto_ptr<>, - which is the most common use of this type. If you have functions taking it - as parameter, these typemaps can't be used for them and you need to do - something else (e.g. use shared_ptr<> which SWIG supports fully). - */ +/* ----------------------------------------------------------------------------- + * std_auto_ptr.i + * + * The typemaps here allow handling functions returning std::auto_ptr<>, + * which is the most common use of this type. If you have functions taking it + * as parameter, these typemaps can't be used for them and you need to do + * something else (e.g. use shared_ptr<> which SWIG supports fully). + * ----------------------------------------------------------------------------- */ %define %auto_ptr(TYPE) -%typemap (jni) std::auto_ptr "jlong" -%typemap (jtype) std::auto_ptr "long" -%typemap (jstype) std::auto_ptr "$typemap(jstype, TYPE)" +%typemap (jni) std::auto_ptr< TYPE > "jlong" +%typemap (jtype) std::auto_ptr< TYPE > "long" +%typemap (jstype) std::auto_ptr< TYPE > "$typemap(jstype, TYPE)" -%typemap (out) std::auto_ptr %{ +%typemap (out) std::auto_ptr< TYPE > %{ jlong lpp = 0; - *(TYPE**) &lpp = $1.release(); + *(TYPE **) &lpp = $1.release(); $result = lpp; %} -%typemap(javaout) std::auto_ptr { +%typemap(javaout) std::auto_ptr< TYPE > { long cPtr = $jnicall; return (cPtr == 0) ? null : new $typemap(jstype, TYPE)(cPtr, true); } -%template() std::auto_ptr; +%template() std::auto_ptr< TYPE >; %enddef namespace std { diff --git a/Lib/python/std_auto_ptr.i b/Lib/python/std_auto_ptr.i index c94006a68..fb044f851 100644 --- a/Lib/python/std_auto_ptr.i +++ b/Lib/python/std_auto_ptr.i @@ -1,15 +1,17 @@ -/* - The typemaps here allow handling functions returning std::auto_ptr<>, - which is the most common use of this type. If you have functions taking it - as parameter, these typemaps can't be used for them and you need to do - something else (e.g. use shared_ptr<> which SWIG supports fully). - */ +/* ----------------------------------------------------------------------------- + * std_auto_ptr.i + * + * The typemaps here allow handling functions returning std::auto_ptr<>, + * which is the most common use of this type. If you have functions taking it + * as parameter, these typemaps can't be used for them and you need to do + * something else (e.g. use shared_ptr<> which SWIG supports fully). + * ----------------------------------------------------------------------------- */ %define %auto_ptr(TYPE) -%typemap (out) std::auto_ptr %{ +%typemap (out) std::auto_ptr< TYPE > %{ %set_output(SWIG_NewPointerObj($1.release(), $descriptor(TYPE *), SWIG_POINTER_OWN | %newpointer_flags)); %} -%template() std::auto_ptr; +%template() std::auto_ptr< TYPE >; %enddef namespace std { diff --git a/Lib/ruby/std_auto_ptr.i b/Lib/ruby/std_auto_ptr.i index eab8ec53d..ecaea2b0f 100644 --- a/Lib/ruby/std_auto_ptr.i +++ b/Lib/ruby/std_auto_ptr.i @@ -1,15 +1,17 @@ -/* - The typemaps here allow handling functions returning std::auto_ptr<>, - which is the most common use of this type. If you have functions taking it - as parameter, these typemaps can't be used for them and you need to do - something else (e.g. use shared_ptr<> which SWIG supports fully). - */ +/* ----------------------------------------------------------------------------- + * std_auto_ptr.i + * + * The typemaps here allow handling functions returning std::auto_ptr<>, + * which is the most common use of this type. If you have functions taking it + * as parameter, these typemaps can't be used for them and you need to do + * something else (e.g. use shared_ptr<> which SWIG supports fully). + * ----------------------------------------------------------------------------- */ %define %auto_ptr(TYPE) -%typemap (out) std::auto_ptr %{ +%typemap (out) std::auto_ptr< TYPE > %{ %set_output(SWIG_NewPointerObj($1.release(), $descriptor(TYPE *), SWIG_POINTER_OWN | %newpointer_flags)); %} -%template() std::auto_ptr; +%template() std::auto_ptr< TYPE >; %enddef namespace std { From e75095e6c56ac45aba7aaafb4c732e1f1c675591 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Sun, 3 Jul 2022 13:35:08 +0100 Subject: [PATCH 491/662] Add OCaml throws typemaps for std::string --- Lib/ocaml/std_string.i | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Lib/ocaml/std_string.i b/Lib/ocaml/std_string.i index a8881a16c..2564cfb38 100644 --- a/Lib/ocaml/std_string.i +++ b/Lib/ocaml/std_string.i @@ -96,6 +96,9 @@ class wstring; } %typemap(typecheck) string, const string & = char *; + +%typemap(throws) string, const string & "SWIG_OCamlThrowException(SWIG_OCamlRuntimeException, $1.c_str());" + } #ifdef ENABLE_CHARPTR_ARRAY From 71cd6a38fe539a89dc2ee159c6d54017fd4e90a0 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Sun, 3 Jul 2022 13:58:26 +0100 Subject: [PATCH 492/662] Performance optimisation for directors for classes passed by value The directorin typemaps in the director methods now use std::move on the input parameter when copying the object from the stack to the heap prior to the callback into the target language, thereby taking advantage of move semantics if available. --- CHANGES.current | 6 +++ .../csharp/director_pass_by_value_runme.cs | 2 + Examples/test-suite/director_pass_by_value.i | 41 +++++++++++++++++-- .../java/director_pass_by_value_runme.java | 2 + .../ocaml/director_pass_by_value_runme.ml | 3 ++ .../php/director_pass_by_value_runme.php | 3 ++ .../python/director_pass_by_value_runme.py | 2 + Lib/csharp/boost_shared_ptr.i | 2 +- Lib/csharp/csharp.swg | 2 +- Lib/d/boost_shared_ptr.i | 2 +- Lib/d/dswigtype.swg | 2 +- Lib/go/go.swg | 2 +- Lib/java/boost_shared_ptr.i | 2 +- Lib/java/java.swg | 2 +- Lib/java/swiginterface.i | 2 +- Lib/ocaml/ocaml.swg | 2 +- Lib/octave/boost_shared_ptr.i | 2 +- Lib/php/php.swg | 2 +- Lib/python/boost_shared_ptr.i | 2 +- Lib/r/boost_shared_ptr.i | 2 +- Lib/ruby/boost_shared_ptr.i | 2 +- Lib/scilab/boost_shared_ptr.i | 2 +- Lib/swig.swg | 9 ++++ Lib/typemaps/swigtype.swg | 2 +- 24 files changed, 80 insertions(+), 20 deletions(-) diff --git a/CHANGES.current b/CHANGES.current index 57dd6c765..9adfa8ad0 100644 --- a/CHANGES.current +++ b/CHANGES.current @@ -7,6 +7,12 @@ the issue number to the end of the URL: https://github.com/swig/swig/issues/ Version 4.1.0 (in progress) =========================== +2022-07-03: wsfulton + Performane optimisation for directors for classes passed by value. The directorin + typemaps in the director methods now use std::move on the input parameter when + copying the object from the stack to the heap prior to the callback into the target + language, thereby taking advantage of move semantics if available. + 2022-07-02: wsfulton #1722 [C#, Java, Python, Ruby] Add std::unique_ptr support. Ported from std::auto_ptr. Use the %unique_ptr(T) macro as follows for usage std::unique_ptr. For example, for diff --git a/Examples/test-suite/csharp/director_pass_by_value_runme.cs b/Examples/test-suite/csharp/director_pass_by_value_runme.cs index ba6371590..1f64f6d7e 100644 --- a/Examples/test-suite/csharp/director_pass_by_value_runme.cs +++ b/Examples/test-suite/csharp/director_pass_by_value_runme.cs @@ -28,6 +28,8 @@ public class runme break; }; } + if (director_pass_by_value.has_cplusplus11()) + Counter.check_counts(1, 0, 0, 1, 0, 1); // check move constructor called and just one destructor // bug was the passByVal 'global' object was destroyed after the call to virtualMethod had finished. int ret = runme.passByVal.getVal(); if (ret != 0x12345678) diff --git a/Examples/test-suite/director_pass_by_value.i b/Examples/test-suite/director_pass_by_value.i index 31d8ce2d2..5e31c9d3b 100644 --- a/Examples/test-suite/director_pass_by_value.i +++ b/Examples/test-suite/director_pass_by_value.i @@ -1,14 +1,38 @@ %module(directors="1") director_pass_by_value + +#if defined(SWIGD) +%rename(trace) debug; +#endif + %director DirectorPassByValueAbstractBase; +%include "cpp11_move_only_helper.i" + +%ignore PassedByValue::operator=; +%ignore PassedByValue::PassedByValue(PassedByValue &&); + %inline %{ -class PassedByValue { - int val; -public: - PassedByValue() { val = 0x12345678; } +#include +using namespace std; +int debug = false; +struct PassedByValue { + PassedByValue(int v = 0x12345678) { val = v; if (debug) cout << "PassedByValue(0x" << hex << val << ")" << " " << this << endl; Counter::normal_constructor++; } + + PassedByValue(const PassedByValue &other) { val = other.val; if (debug) cout << "PassedByValue(const PassedByValue &)" << " " << this << " " << &other << endl; Counter::copy_constructor++;} + PassedByValue & operator=(const PassedByValue &other) { val = other.val; if (debug) cout << "operator=(const PassedByValue &)" << " " << this << " " << &other << endl; Counter::copy_assignment++; return *this; } + +#if __cplusplus >= 201103L + PassedByValue(PassedByValue &&other) noexcept { val = other.val; if (debug) cout << "PassedByValue(PassedByValue &&)" << " " << this << endl; Counter::move_constructor++; } + PassedByValue & operator=(PassedByValue &&other) noexcept { val = other.val; if (debug) cout << "operator=(PassedByValue &&)" << " " << this << endl; Counter::move_assignment++; return *this; } + ~PassedByValue() { if (debug) cout << "~PassedByValue()" << " " << this << endl; Counter::destructor++; } +#endif + int getVal() { return val; } +private: + int val; }; + int doSomething(int x) { int yy[256]; yy[0] =0x9876; @@ -18,6 +42,7 @@ int doSomething(int x) { class DirectorPassByValueAbstractBase { public: virtual void virtualMethod(PassedByValue pbv) = 0; + virtual void virtualConstMethod(const PassedByValue pbv) {} virtual ~DirectorPassByValueAbstractBase () {} }; @@ -27,4 +52,12 @@ public: f.virtualMethod(PassedByValue()); } }; + +bool has_cplusplus11() { +#if __cplusplus >= 201103L + return true; +#else + return false; +#endif +} %} diff --git a/Examples/test-suite/java/director_pass_by_value_runme.java b/Examples/test-suite/java/director_pass_by_value_runme.java index 24ded2ccf..1d34c3b55 100644 --- a/Examples/test-suite/java/director_pass_by_value_runme.java +++ b/Examples/test-suite/java/director_pass_by_value_runme.java @@ -32,6 +32,8 @@ public class director_pass_by_value_runme { break; }; } + if (director_pass_by_value.has_cplusplus11()) + Counter.check_counts(1, 0, 0, 1, 0, 1); // check move constructor called and just one destructor // bug was the passByVal 'global' object was destroyed after the call to virtualMethod had finished. int ret = director_pass_by_value_runme.passByVal.getVal(); if (ret != 0x12345678) diff --git a/Examples/test-suite/ocaml/director_pass_by_value_runme.ml b/Examples/test-suite/ocaml/director_pass_by_value_runme.ml index af862f189..ce2137fbe 100644 --- a/Examples/test-suite/ocaml/director_pass_by_value_runme.ml +++ b/Examples/test-suite/ocaml/director_pass_by_value_runme.ml @@ -14,10 +14,13 @@ let d = (director_pass_by_value_Derived) '() +let cpp11 = _has_cplusplus11 '() as bool + let _ = let caller = new_Caller '() in assert (caller -> call_virtualMethod (d) = C_void); assert (Array.length !passByVal = 1); +(* TODO: only run if cpp11... let _ = _Counter_check_counts (C_list [C_int 0; C_int 0; C_int 0; C_int 1; C_int 0; C_int 1]) in*) (* check move constructor called and just one destructor *) let a = List.hd (fnhelper (!passByVal.(0))) in assert (a -> getVal () as int = 0x12345678); assert (a -> "~" () = C_void); diff --git a/Examples/test-suite/php/director_pass_by_value_runme.php b/Examples/test-suite/php/director_pass_by_value_runme.php index d3763292f..b8f1bb9f9 100644 --- a/Examples/test-suite/php/director_pass_by_value_runme.php +++ b/Examples/test-suite/php/director_pass_by_value_runme.php @@ -14,6 +14,9 @@ class director_pass_by_value_Derived extends DirectorPassByValueAbstractBase { # bug was the passByVal global object was destroyed after the call to virtualMethod had finished. $caller = new Caller(); $caller->call_virtualMethod(new director_pass_by_value_Derived()); +if (has_cplusplus11()) { + Counter::check_counts(1, 0, 0, 1, 0, 1); # check move constructor called and just one destructor +} $ret = $passByVal->getVal(); if ($ret != 0x12345678) { check::fail("Bad return value, got " . dechex($ret)); diff --git a/Examples/test-suite/python/director_pass_by_value_runme.py b/Examples/test-suite/python/director_pass_by_value_runme.py index 7744db962..9dbd64ad6 100644 --- a/Examples/test-suite/python/director_pass_by_value_runme.py +++ b/Examples/test-suite/python/director_pass_by_value_runme.py @@ -8,6 +8,8 @@ class director_pass_by_value_Derived(director_pass_by_value.DirectorPassByValueA # bug was the passByVal global object was destroyed after the call to virtualMethod had finished. director_pass_by_value.Caller().call_virtualMethod(director_pass_by_value_Derived()) +if director_pass_by_value.has_cplusplus11(): + director_pass_by_value.Counter.check_counts(1, 0, 0, 1, 0, 1) # check move constructor called and just one destructor ret = passByVal.getVal(); if ret != 0x12345678: raise RuntimeError("Bad return value, got " + hex(ret)) diff --git a/Lib/csharp/boost_shared_ptr.i b/Lib/csharp/boost_shared_ptr.i index 508c0ec14..2bbb6e277 100644 --- a/Lib/csharp/boost_shared_ptr.i +++ b/Lib/csharp/boost_shared_ptr.i @@ -32,7 +32,7 @@ %{ $result = new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >(new $1_ltype(($1_ltype &)$1)); %} %typemap(directorin) CONST TYPE -%{ $input = new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > (new $1_ltype((const $1_ltype &)$1)); %} +%{ $input = new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > (new $1_ltype(SWIG_STD_MOVE($1))); %} %typemap(directorout) CONST TYPE %{ if (!$input) { diff --git a/Lib/csharp/csharp.swg b/Lib/csharp/csharp.swg index d4bcd3c80..94e0458a6 100644 --- a/Lib/csharp/csharp.swg +++ b/Lib/csharp/csharp.swg @@ -409,7 +409,7 @@ SWIGINTERN const char * SWIG_UnpackData(const char *c, void *ptr, size_t sz) { #endif %typemap(directorin) SWIGTYPE -%{ $input = (void *)new $1_ltype((const $1_ltype &)$1); %} +%{ $input = (void *)new $1_ltype(SWIG_STD_MOVE($1)); %} %typemap(csdirectorin) SWIGTYPE "new $&csclassname($iminput, true)" %typemap(csdirectorout) SWIGTYPE "$&csclassname.getCPtr($cscall).Handle" diff --git a/Lib/d/boost_shared_ptr.i b/Lib/d/boost_shared_ptr.i index 4a220a589..1018bd1f2 100644 --- a/Lib/d/boost_shared_ptr.i +++ b/Lib/d/boost_shared_ptr.i @@ -26,7 +26,7 @@ %{ $result = new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >(new $1_ltype(($1_ltype &)$1)); %} %typemap(directorin) CONST TYPE -%{ $input = new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > (new $1_ltype((const $1_ltype &)$1)); %} +%{ $input = new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > (new $1_ltype(SWIG_STD_MOVE($1))); %} %typemap(directorout) CONST TYPE %{ if (!$input) { diff --git a/Lib/d/dswigtype.swg b/Lib/d/dswigtype.swg index 535e8d576..3fb7f6a01 100644 --- a/Lib/d/dswigtype.swg +++ b/Lib/d/dswigtype.swg @@ -62,7 +62,7 @@ #endif %typemap(directorin) SWIGTYPE - "$input = (void *)new $1_ltype((const $1_ltype &)$1);" + "$input = (void *)new $1_ltype(SWIG_STD_MOVE($1));" %typemap(directorout) SWIGTYPE %{ if (!$input) { SWIG_DSetPendingException(SWIG_DIllegalArgumentException, "Unexpected null return for type $1_type"); diff --git a/Lib/go/go.swg b/Lib/go/go.swg index 6e415d2c1..bb7a471cc 100644 --- a/Lib/go/go.swg +++ b/Lib/go/go.swg @@ -625,7 +625,7 @@ %typemap(goout) SWIGTYPE "" %typemap(directorin) SWIGTYPE -%{ $input = new $1_ltype((const $1_ltype &)$1); %} +%{ $input = new $1_ltype(SWIG_STD_MOVE($1)); %} %typemap(godirectorin) SWIGTYPE "" diff --git a/Lib/java/boost_shared_ptr.i b/Lib/java/boost_shared_ptr.i index 325a6832d..adf9c203e 100644 --- a/Lib/java/boost_shared_ptr.i +++ b/Lib/java/boost_shared_ptr.i @@ -33,7 +33,7 @@ %typemap(directorin,descriptor="L$packagepath/$&javaclassname;") CONST TYPE %{ $input = 0; - *((SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > **)&$input) = new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > (new $1_ltype((const $1_ltype &)$1)); %} + *((SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > **)&$input) = new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > (new $1_ltype(SWIG_STD_MOVE($1))); %} %typemap(directorout) CONST TYPE %{ if (!$input) { diff --git a/Lib/java/java.swg b/Lib/java/java.swg index 7967c1882..23744aeb3 100644 --- a/Lib/java/java.swg +++ b/Lib/java/java.swg @@ -676,7 +676,7 @@ Swig::LocalRefGuard $1_refguard(jenv, $input); } %typemap(directorin,descriptor="L$packagepath/$&javaclassname;") SWIGTYPE %{ $input = 0; - *(($&1_ltype*)&$input) = new $1_ltype((const $1_ltype &)$1); %} + *(($&1_ltype*)&$input) = new $1_ltype(SWIG_STD_MOVE($1)); %} %typemap(javadirectorin) SWIGTYPE "new $&javaclassname($jniinput, true)" %typemap(javadirectorout) SWIGTYPE "$&javaclassname.getCPtr($javacall)" diff --git a/Lib/java/swiginterface.i b/Lib/java/swiginterface.i index 0a0f7806a..c3ca97d36 100644 --- a/Lib/java/swiginterface.i +++ b/Lib/java/swiginterface.i @@ -40,7 +40,7 @@ %typemap(javadirectorout) CTYPE *const& "$javacall.$*interfacename_GetInterfaceCPtr()" %typemap(directorin,descriptor="L$packagepath/$&javainterfacename;") CTYPE %{ $input = 0; - *(($&1_ltype*)&$input) = new $1_ltype((const $1_ltype &)$1); %} + *(($&1_ltype*)&$input) = new $1_ltype(SWIG_STD_MOVE($1)); %} %typemap(directorin,descriptor="L$packagepath/$javainterfacename;") CTYPE *, CTYPE [] %{ *(($&1_ltype)&$input) = ($1_ltype) $1; %} %typemap(directorin,descriptor="L$packagepath/$javainterfacename;") CTYPE & diff --git a/Lib/ocaml/ocaml.swg b/Lib/ocaml/ocaml.swg index 0c190bbc4..ef0a64c90 100644 --- a/Lib/ocaml/ocaml.swg +++ b/Lib/ocaml/ocaml.swg @@ -119,7 +119,7 @@ } %typemap(directorin) SWIGTYPE { - $<ype temp = new $ltype((const $ltype &)$1); + $<ype temp = new $1_ltype(SWIG_STD_MOVE($1)); swig_result = SWIG_Ocaml_ptr_to_val("create_$ltype_from_ptr", (void *)temp, $&1_descriptor); args = caml_list_append(args, swig_result); } diff --git a/Lib/octave/boost_shared_ptr.i b/Lib/octave/boost_shared_ptr.i index 668bf4354..a1427b74d 100644 --- a/Lib/octave/boost_shared_ptr.i +++ b/Lib/octave/boost_shared_ptr.i @@ -59,7 +59,7 @@ } %typemap(directorin,noblock=1) CONST TYPE (SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *smartarg = 0) %{ - smartarg = new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >(new $1_ltype(($1_ltype &)$1)); + smartarg = new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >(new $1_ltype(SWIG_STD_MOVE($1))); $input = SWIG_NewPointerObj(%as_voidptr(smartarg), $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), SWIG_POINTER_OWN | %newpointer_flags); %} %typemap(directorout,noblock=1) CONST TYPE (void *swig_argp, int swig_res = 0) { diff --git a/Lib/php/php.swg b/Lib/php/php.swg index 7d6d5f29d..c2442d24b 100644 --- a/Lib/php/php.swg +++ b/Lib/php/php.swg @@ -454,7 +454,7 @@ %typemap(directorin) SWIGTYPE %{ ZVAL_UNDEF($input); - SWIG_SetPointerZval($input, SWIG_as_voidptr(new $1_ltype((const $1_ltype &)$1)), $&1_descriptor, 1); + SWIG_SetPointerZval($input, SWIG_as_voidptr(new $1_ltype(SWIG_STD_MOVE($1))), $&1_descriptor, 1); %} %typemap(out, phptype="void") void ""; diff --git a/Lib/python/boost_shared_ptr.i b/Lib/python/boost_shared_ptr.i index 709e7811d..ab9962ac8 100644 --- a/Lib/python/boost_shared_ptr.i +++ b/Lib/python/boost_shared_ptr.i @@ -63,7 +63,7 @@ } %typemap(directorin,noblock=1) CONST TYPE (SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *smartarg = 0) %{ - smartarg = new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >(new $1_ltype(($1_ltype &)$1)); + smartarg = new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >(new $1_ltype(SWIG_STD_MOVE($1))); $input = SWIG_NewPointerObj(%as_voidptr(smartarg), $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), SWIG_POINTER_OWN | %newpointer_flags); %} %typemap(directorout,noblock=1) CONST TYPE (void *swig_argp, int swig_res = 0) { diff --git a/Lib/r/boost_shared_ptr.i b/Lib/r/boost_shared_ptr.i index 668bf4354..a1427b74d 100644 --- a/Lib/r/boost_shared_ptr.i +++ b/Lib/r/boost_shared_ptr.i @@ -59,7 +59,7 @@ } %typemap(directorin,noblock=1) CONST TYPE (SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *smartarg = 0) %{ - smartarg = new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >(new $1_ltype(($1_ltype &)$1)); + smartarg = new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >(new $1_ltype(SWIG_STD_MOVE($1))); $input = SWIG_NewPointerObj(%as_voidptr(smartarg), $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), SWIG_POINTER_OWN | %newpointer_flags); %} %typemap(directorout,noblock=1) CONST TYPE (void *swig_argp, int swig_res = 0) { diff --git a/Lib/ruby/boost_shared_ptr.i b/Lib/ruby/boost_shared_ptr.i index 9676bf9d8..fe3ea8cde 100644 --- a/Lib/ruby/boost_shared_ptr.i +++ b/Lib/ruby/boost_shared_ptr.i @@ -59,7 +59,7 @@ } %typemap(directorin,noblock=1) CONST TYPE (SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *smartarg = 0) %{ - smartarg = new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >(new $1_ltype(($1_ltype &)$1)); + smartarg = new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >(new $1_ltype(SWIG_STD_MOVE($1))); $input = SWIG_NewPointerObj(%as_voidptr(smartarg), $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), SWIG_POINTER_OWN | %newpointer_flags); %} %typemap(directorout,noblock=1) CONST TYPE (void *swig_argp, int swig_res = 0) { diff --git a/Lib/scilab/boost_shared_ptr.i b/Lib/scilab/boost_shared_ptr.i index 668bf4354..a1427b74d 100644 --- a/Lib/scilab/boost_shared_ptr.i +++ b/Lib/scilab/boost_shared_ptr.i @@ -59,7 +59,7 @@ } %typemap(directorin,noblock=1) CONST TYPE (SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *smartarg = 0) %{ - smartarg = new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >(new $1_ltype(($1_ltype &)$1)); + smartarg = new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >(new $1_ltype(SWIG_STD_MOVE($1))); $input = SWIG_NewPointerObj(%as_voidptr(smartarg), $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), SWIG_POINTER_OWN | %newpointer_flags); %} %typemap(directorout,noblock=1) CONST TYPE (void *swig_argp, int swig_res = 0) { diff --git a/Lib/swig.swg b/Lib/swig.swg index ca7586457..c9b301426 100644 --- a/Lib/swig.swg +++ b/Lib/swig.swg @@ -703,6 +703,15 @@ public: template T SwigValueInit() { return T(); } +%} + +%insert("runtime") %{ +#if __cplusplus >=201103L +# define SWIG_STD_MOVE(OBJ) std::move(OBJ) +#else +# define SWIG_STD_MOVE(OBJ) OBJ +#endif + #endif %} #endif diff --git a/Lib/typemaps/swigtype.swg b/Lib/typemaps/swigtype.swg index 6973e3a10..52fac3252 100644 --- a/Lib/typemaps/swigtype.swg +++ b/Lib/typemaps/swigtype.swg @@ -417,7 +417,7 @@ /* directorin */ %typemap(directorin,noblock=1) SWIGTYPE { - $input = SWIG_NewPointerObj(%as_voidptr(new $1_ltype((const $1_ltype &)$1)), $&descriptor, SWIG_POINTER_OWN | %newpointer_flags); + $input = SWIG_NewPointerObj(%as_voidptr(new $1_ltype(SWIG_STD_MOVE($1))), $&descriptor, SWIG_POINTER_OWN | %newpointer_flags); } %typemap(directorin,noblock=1) SWIGTYPE * { From 319442a8c4fe9d3bb3ce1f4a6fa45e4da2e7f88e Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Mon, 4 Jul 2022 08:40:04 +0100 Subject: [PATCH 493/662] More move semantics improvements More removal of casts in the out typemaps when copying objects to enable C++ compilers to possibly make use of move semantics. --- Lib/csharp/boost_intrusive_ptr.i | 4 ++-- Lib/csharp/boost_shared_ptr.i | 4 ++-- Lib/d/boost_shared_ptr.i | 4 ++-- Lib/java/boost_intrusive_ptr.i | 4 ++-- Lib/java/boost_shared_ptr.i | 2 +- Lib/lua/lua.swg | 2 +- Lib/mzscheme/typemaps.i | 2 +- Lib/octave/boost_shared_ptr.i | 4 ++-- Lib/php/utils.i | 2 +- Lib/python/boost_shared_ptr.i | 4 ++-- Lib/r/boost_shared_ptr.i | 4 ++-- Lib/ruby/boost_shared_ptr.i | 4 ++-- Lib/scilab/boost_shared_ptr.i | 4 ++-- 13 files changed, 22 insertions(+), 22 deletions(-) diff --git a/Lib/csharp/boost_intrusive_ptr.i b/Lib/csharp/boost_intrusive_ptr.i index fa3f53a20..355a910cf 100644 --- a/Lib/csharp/boost_intrusive_ptr.i +++ b/Lib/csharp/boost_intrusive_ptr.i @@ -32,7 +32,7 @@ %} %typemap(out, fragment="SWIG_intrusive_deleter") CONST TYPE %{ //plain value(out) - $1_ltype* resultp = new $1_ltype(($1_ltype &)$1); + $1_ltype* resultp = new $1_ltype($1); intrusive_ptr_add_ref(resultp); *(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > **)&$result = new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >(resultp, SWIG_intrusive_deleter< CONST TYPE >()); %} @@ -372,7 +372,7 @@ } $1 = *argp; %} %typemap(out) CONST TYPE -%{ *(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > **)&$result = new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >(new $1_ltype(($1_ltype &)$1)); %} +%{ *(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > **)&$result = new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >(new $1_ltype($1)); %} // plain pointer %typemap(in) CONST TYPE * (SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *smartarg = 0) %{ diff --git a/Lib/csharp/boost_shared_ptr.i b/Lib/csharp/boost_shared_ptr.i index 2bbb6e277..d47fab558 100644 --- a/Lib/csharp/boost_shared_ptr.i +++ b/Lib/csharp/boost_shared_ptr.i @@ -29,7 +29,7 @@ } $1 = *argp; %} %typemap(out) CONST TYPE -%{ $result = new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >(new $1_ltype(($1_ltype &)$1)); %} +%{ $result = new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >(new $1_ltype($1)); %} %typemap(directorin) CONST TYPE %{ $input = new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > (new $1_ltype(SWIG_STD_MOVE($1))); %} @@ -122,7 +122,7 @@ %typemap(in) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > * ($*1_ltype tempnull) %{ $1 = $input ? ($1_ltype)$input : &tempnull; %} %typemap(out, fragment="SWIG_null_deleter") SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > * -%{ $result = ($1 && *$1) ? new $*1_ltype(*($1_ltype)$1) : 0; +%{ $result = ($1 && *$1) ? new $*1_ltype(*$1) : 0; if ($owner) delete $1; %} %typemap(directorin) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > * diff --git a/Lib/d/boost_shared_ptr.i b/Lib/d/boost_shared_ptr.i index 1018bd1f2..6d85c5aef 100644 --- a/Lib/d/boost_shared_ptr.i +++ b/Lib/d/boost_shared_ptr.i @@ -23,7 +23,7 @@ } $1 = *argp; %} %typemap(out) CONST TYPE -%{ $result = new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >(new $1_ltype(($1_ltype &)$1)); %} +%{ $result = new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >(new $1_ltype($1)); %} %typemap(directorin) CONST TYPE %{ $input = new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > (new $1_ltype(SWIG_STD_MOVE($1))); %} @@ -116,7 +116,7 @@ %typemap(in) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > * ($*1_ltype tempnull) %{ $1 = $input ? ($1_ltype)$input : &tempnull; %} %typemap(out, fragment="SWIG_null_deleter") SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > * -%{ $result = ($1 && *$1) ? new $*1_ltype(*($1_ltype)$1) : 0; +%{ $result = ($1 && *$1) ? new $*1_ltype(*$1) : 0; if ($owner) delete $1; %} %typemap(directorin) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > * diff --git a/Lib/java/boost_intrusive_ptr.i b/Lib/java/boost_intrusive_ptr.i index 3bc80b467..072a31e8c 100644 --- a/Lib/java/boost_intrusive_ptr.i +++ b/Lib/java/boost_intrusive_ptr.i @@ -33,7 +33,7 @@ %} %typemap(out, fragment="SWIG_intrusive_deleter") CONST TYPE %{ //plain value(out) - $1_ltype* resultp = new $1_ltype(($1_ltype &)$1); + $1_ltype* resultp = new $1_ltype($1); intrusive_ptr_add_ref(resultp); *(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > **)&$result = new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >(resultp, SWIG_intrusive_deleter< CONST TYPE >()); %} @@ -342,7 +342,7 @@ } $1 = *argp; %} %typemap(out) CONST TYPE -%{ *(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > **)&$result = new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >(new $1_ltype(($1_ltype &)$1)); %} +%{ *(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > **)&$result = new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >(new $1_ltype($1)); %} // plain pointer %typemap(in) CONST TYPE * (SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *smartarg = 0) %{ diff --git a/Lib/java/boost_shared_ptr.i b/Lib/java/boost_shared_ptr.i index adf9c203e..ce00162da 100644 --- a/Lib/java/boost_shared_ptr.i +++ b/Lib/java/boost_shared_ptr.i @@ -29,7 +29,7 @@ } $1 = *argp; %} %typemap(out) CONST TYPE -%{ *(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > **)&$result = new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >(new $1_ltype(($1_ltype &)$1)); %} +%{ *(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > **)&$result = new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >(new $1_ltype($1)); %} %typemap(directorin,descriptor="L$packagepath/$&javaclassname;") CONST TYPE %{ $input = 0; diff --git a/Lib/lua/lua.swg b/Lib/lua/lua.swg index 5144f601d..12c635d77 100644 --- a/Lib/lua/lua.swg +++ b/Lib/lua/lua.swg @@ -213,7 +213,7 @@ SWIG_fail;%} // %apply SWIGTYPE EXCEPTION_BY_VAL {FooBar}; // %apply SWIGTYPE& EXCEPTION_BY_VAL {FooBar&}; // note: need & twice %typemap(throws) SWIGTYPE EXCEPTION_BY_VAL -%{SWIG_NewPointerObj(L,(void *)new $1_ltype(($1_ltype &) $1),$&1_descriptor,1); +%{SWIG_NewPointerObj(L,(void *)new $1_ltype($1),$&1_descriptor,1); SWIG_fail;%} // similar for object reference diff --git a/Lib/mzscheme/typemaps.i b/Lib/mzscheme/typemaps.i index 059dd06ff..0fc947d58 100644 --- a/Lib/mzscheme/typemaps.i +++ b/Lib/mzscheme/typemaps.i @@ -143,7 +143,7 @@ #ifdef __cplusplus { $&1_ltype resultptr; - resultptr = new $1_ltype(($1_ltype &) $1); + resultptr = new $1_ltype($1); $result = SWIG_NewPointerObj (resultptr, $&1_descriptor, 0); } #else diff --git a/Lib/octave/boost_shared_ptr.i b/Lib/octave/boost_shared_ptr.i index a1427b74d..87c89b5f9 100644 --- a/Lib/octave/boost_shared_ptr.i +++ b/Lib/octave/boost_shared_ptr.i @@ -35,7 +35,7 @@ } } %typemap(out) CONST TYPE { - SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *smartresult = new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >(new $1_ltype(($1_ltype &)$1)); + SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *smartresult = new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >(new $1_ltype($1)); %set_output(SWIG_NewPointerObj(%as_voidptr(smartresult), $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), SWIG_POINTER_OWN)); } @@ -54,7 +54,7 @@ } } %typemap(varout) CONST TYPE { - SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *smartresult = new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >(new $1_ltype(($1_ltype &)$1)); + SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *smartresult = new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >(new $1_ltype($1)); %set_varoutput(SWIG_NewPointerObj(%as_voidptr(smartresult), $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), SWIG_POINTER_OWN)); } diff --git a/Lib/php/utils.i b/Lib/php/utils.i index 1343495e0..33db942a9 100644 --- a/Lib/php/utils.i +++ b/Lib/php/utils.i @@ -81,7 +81,7 @@ %{ $*1_ltype swig_val; CONVERT_IN(swig_val, $*1_ltype, *$input); - $1_ltype temp = new $*1_ltype(($*1_ltype)swig_val); + $1_ltype temp = new $*1_ltype(swig_val); swig_acquire_ownership(temp); $result = temp; %} diff --git a/Lib/python/boost_shared_ptr.i b/Lib/python/boost_shared_ptr.i index ab9962ac8..bfd8787c0 100644 --- a/Lib/python/boost_shared_ptr.i +++ b/Lib/python/boost_shared_ptr.i @@ -39,7 +39,7 @@ } } %typemap(out) CONST TYPE { - SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *smartresult = new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >(new $1_ltype(($1_ltype &)$1)); + SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *smartresult = new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >(new $1_ltype($1)); %set_output(SWIG_NewPointerObj(%as_voidptr(smartresult), $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), SWIG_POINTER_OWN)); } @@ -58,7 +58,7 @@ } } %typemap(varout) CONST TYPE { - SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *smartresult = new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >(new $1_ltype(($1_ltype &)$1)); + SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *smartresult = new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >(new $1_ltype($1)); %set_varoutput(SWIG_NewPointerObj(%as_voidptr(smartresult), $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), SWIG_POINTER_OWN)); } diff --git a/Lib/r/boost_shared_ptr.i b/Lib/r/boost_shared_ptr.i index a1427b74d..87c89b5f9 100644 --- a/Lib/r/boost_shared_ptr.i +++ b/Lib/r/boost_shared_ptr.i @@ -35,7 +35,7 @@ } } %typemap(out) CONST TYPE { - SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *smartresult = new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >(new $1_ltype(($1_ltype &)$1)); + SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *smartresult = new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >(new $1_ltype($1)); %set_output(SWIG_NewPointerObj(%as_voidptr(smartresult), $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), SWIG_POINTER_OWN)); } @@ -54,7 +54,7 @@ } } %typemap(varout) CONST TYPE { - SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *smartresult = new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >(new $1_ltype(($1_ltype &)$1)); + SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *smartresult = new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >(new $1_ltype($1)); %set_varoutput(SWIG_NewPointerObj(%as_voidptr(smartresult), $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), SWIG_POINTER_OWN)); } diff --git a/Lib/ruby/boost_shared_ptr.i b/Lib/ruby/boost_shared_ptr.i index fe3ea8cde..70deae4f2 100644 --- a/Lib/ruby/boost_shared_ptr.i +++ b/Lib/ruby/boost_shared_ptr.i @@ -35,7 +35,7 @@ } } %typemap(out) CONST TYPE { - SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *smartresult = new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >(new $1_ltype(($1_ltype &)$1)); + SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *smartresult = new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >(new $1_ltype($1)); %set_output(SWIG_NewPointerObj(%as_voidptr(smartresult), $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), SWIG_POINTER_OWN)); } @@ -54,7 +54,7 @@ } } %typemap(varout) CONST TYPE { - SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *smartresult = new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >(new $1_ltype(($1_ltype &)$1)); + SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *smartresult = new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >(new $1_ltype($1)); %set_varoutput(SWIG_NewPointerObj(%as_voidptr(smartresult), $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), SWIG_POINTER_OWN)); } diff --git a/Lib/scilab/boost_shared_ptr.i b/Lib/scilab/boost_shared_ptr.i index a1427b74d..87c89b5f9 100644 --- a/Lib/scilab/boost_shared_ptr.i +++ b/Lib/scilab/boost_shared_ptr.i @@ -35,7 +35,7 @@ } } %typemap(out) CONST TYPE { - SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *smartresult = new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >(new $1_ltype(($1_ltype &)$1)); + SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *smartresult = new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >(new $1_ltype($1)); %set_output(SWIG_NewPointerObj(%as_voidptr(smartresult), $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), SWIG_POINTER_OWN)); } @@ -54,7 +54,7 @@ } } %typemap(varout) CONST TYPE { - SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *smartresult = new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >(new $1_ltype(($1_ltype &)$1)); + SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *smartresult = new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >(new $1_ltype($1)); %set_varoutput(SWIG_NewPointerObj(%as_voidptr(smartresult), $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), SWIG_POINTER_OWN)); } From 5e06e0931edee5d102ef45fa74ed805368cb22dd Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Mon, 4 Jul 2022 09:52:31 +0100 Subject: [PATCH 494/662] Remove Tcl SWIGTYPE CLASS typemap Odd typemap cleanup - this typemap can't be used - SWIG_new_copy does not exist --- Lib/tcl/tcltypemaps.swg | 5 ----- 1 file changed, 5 deletions(-) diff --git a/Lib/tcl/tcltypemaps.swg b/Lib/tcl/tcltypemaps.swg index ad31bcfc9..66cce47ec 100644 --- a/Lib/tcl/tcltypemaps.swg +++ b/Lib/tcl/tcltypemaps.swg @@ -77,11 +77,6 @@ #endif -%typemap(throws,noblock=1) SWIGTYPE CLASS { - SWIG_set_result(SWIG_NewInstanceObj(%as_voidptr(SWIG_new_copy($1, $1_ltype)), $&1_descriptor, 1)); - SWIG_fail; -} - %typemap(out) SWIGTYPE = SWIGTYPE INSTANCE; %typemap(out) SWIGTYPE * = SWIGTYPE *INSTANCE; %typemap(out) SWIGTYPE *const = SWIGTYPE *; From e1173cac26be86bd1b1caf6e5266435fe90a5250 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Tue, 5 Jul 2022 10:53:08 +0100 Subject: [PATCH 495/662] Tcl std_vector.i functions not static Closes #2305 --- Lib/tcl/std_vector.i | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Lib/tcl/std_vector.i b/Lib/tcl/std_vector.i index 144788be5..a74bf3a1b 100644 --- a/Lib/tcl/std_vector.i +++ b/Lib/tcl/std_vector.i @@ -34,11 +34,11 @@ %{ #include -Tcl_Obj* SwigString_FromString(const std::string &s) { +SWIGINTERN Tcl_Obj* SwigString_FromString(const std::string &s) { return Tcl_NewStringObj(s.data(), (int)s.length()); } -int Tcl_GetBoolFromObj(Tcl_Interp *interp, Tcl_Obj *o, bool *val) { +SWIGINTERN int Tcl_GetBoolFromObj(Tcl_Interp *interp, Tcl_Obj *o, bool *val) { int v; int res = Tcl_GetBooleanFromObj(interp, o, &v); if (res == TCL_OK) { @@ -47,7 +47,7 @@ int Tcl_GetBoolFromObj(Tcl_Interp *interp, Tcl_Obj *o, bool *val) { return res; } -int SwigString_AsString(Tcl_Interp *interp, Tcl_Obj *o, std::string *val) { +SWIGINTERN int SwigString_AsString(Tcl_Interp *interp, Tcl_Obj *o, std::string *val) { int len; const char* temp = Tcl_GetStringFromObj(o, &len); (void)interp; From 87cbf8c3410cdde9356875f2652ea5927b3543f4 Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Tue, 5 Jul 2022 17:00:21 -0700 Subject: [PATCH 496/662] [Go] #2245 Handle NULL pointers for string* conversions. Rearrange generation of director methods and rename receiver argument from p to swig_p. Fixes #2245 --- CHANGES.current | 5 + .../test-suite/go/go_director_inout_runme.go | 3 + Examples/test-suite/go_director_inout.i | 9 + Lib/go/std_string.i | 29 +- Source/Modules/go.cxx | 310 +++++++++--------- 5 files changed, 194 insertions(+), 162 deletions(-) diff --git a/CHANGES.current b/CHANGES.current index 9adfa8ad0..3a10743e5 100644 --- a/CHANGES.current +++ b/CHANGES.current @@ -7,6 +7,11 @@ the issue number to the end of the URL: https://github.com/swig/swig/issues/ Version 4.1.0 (in progress) =========================== +2022-07-05: ianlancetaylor + [Go] #2245 Handle NULL pointers for string* conversions. + Rearrange generation of director methods and rename + receiver argument from p to swig_p. + 2022-07-03: wsfulton Performane optimisation for directors for classes passed by value. The directorin typemaps in the director methods now use std::move on the input parameter when diff --git a/Examples/test-suite/go/go_director_inout_runme.go b/Examples/test-suite/go/go_director_inout_runme.go index 55f32dfc3..6b68543a2 100644 --- a/Examples/test-suite/go/go_director_inout_runme.go +++ b/Examples/test-suite/go/go_director_inout_runme.go @@ -67,6 +67,9 @@ func main() { a.CallS4([]string{ "T1", "T2" }) + a.S5(&str) + a.S5(nil) + a = wrap.NewDirectorMyClass(nil) s = a.Adjust(m) if s.Str != `{"first":"second"}` { diff --git a/Examples/test-suite/go_director_inout.i b/Examples/test-suite/go_director_inout.i index b12e5da52..c11b963f5 100644 --- a/Examples/test-suite/go_director_inout.i +++ b/Examples/test-suite/go_director_inout.i @@ -225,6 +225,7 @@ class MyClass { virtual void S2(std::string& s) = 0; virtual void S3(std::string* s) = 0; virtual void S4(const char * const *strarray); + virtual int S5(const std::string* s); }; void MyClass::S1(std::string s) { @@ -239,4 +240,12 @@ void MyClass::CallS4(const char * const *strarray) { this->S4(strarray); } +int MyClass::S5(const std::string* s) { + if (s) { + return (*s)[0]; + } else { + return 0; + } +} + %} diff --git a/Lib/go/std_string.i b/Lib/go/std_string.i index c362f5c5e..3abf04cae 100644 --- a/Lib/go/std_string.i +++ b/Lib/go/std_string.i @@ -93,17 +93,22 @@ class string; %typemap(in) string * (string temp) %{ - temp.assign($input->p, $input->n); - $1 = &temp; + if ($input) { + temp.assign($input->p, $input->n); + $1 = &temp; + } else + $1 = 0; %} %typemap(godirectorout) string * %{ - { + if $input != nil { p := Swig_malloc(len(*$input)) s := (*[1<<30]byte)(unsafe.Pointer(p))[:len(*$input)] copy(s, *$input) $result = (*string)(unsafe.Pointer(&s)) + } else { + $result = nil } %} @@ -125,17 +130,27 @@ class string; %typemap(directorin,fragment="AllocateString") string * (_gostring_ temp) %{ - temp = Swig_AllocateString($1->data(), $1->length()); - $input = &temp; + if ($1) { + temp = Swig_AllocateString($1->data(), $1->length()); + $input = &temp; + } else + $input = 0; %} %typemap(godirectorin,fragment="CopyString") string * %{ *$result = swigCopyString(*$input); %} %typemap(argout,fragment="AllocateString") string * -%{ *$input = Swig_AllocateString($1->data(), $1->length()); %} +%{ + if ($1) + *$input = Swig_AllocateString($1->data(), $1->length()); +%} %typemap(goargout,fragment="CopyString") string * -%{ *$input = swigCopyString(*$1) %} +%{ + if $input != nil { + *$1 = swigCopyString(*$input) + } +%} } diff --git a/Source/Modules/go.cxx b/Source/Modules/go.cxx index d828b00aa..1692e905a 100644 --- a/Source/Modules/go.cxx +++ b/Source/Modules/go.cxx @@ -3580,11 +3580,162 @@ private: Printv(f_go_wrappers, "}\n\n", NULL); - // Define a method in the C++ director class that the C++ upcall - // function can call. This permits an upcall to a protected - // method. - if (!GetFlag(n, "abstract")) { + // Define a function that uses the Go director type that other + // methods in the Go type can call to get parent methods. + + Printv(f_go_wrappers, "func Director", cn, go_with_over_name, "(swig_p ", cn, NULL); + + p = parms; + for (int i = 0; i < parm_count; ++i) { + p = getParm(p); + Printv(f_go_wrappers, ", ", Getattr(p, "lname"), " ", NULL); + String *tm = goType(p, Getattr(p, "type")); + Printv(f_go_wrappers, tm, NULL); + Delete(tm); + p = nextParm(p); + } + + Printv(f_go_wrappers, ")", NULL); + + if (SwigType_type(result) != T_VOID) { + String *tm = goType(n, result); + Printv(f_go_wrappers, " ", tm, NULL); + Delete(tm); + } + + Printv(f_go_wrappers, " {\n", NULL); + + String *ret_type = NULL; + bool memcpy_ret = false; + String *wt = NULL; + String *goout = NULL; + if (SwigType_type(result) != T_VOID) { + ret_type = goImType(n, result); + Printv(f_go_wrappers, "\tvar swig_r ", ret_type, "\n", NULL); + goout = goTypemapLookup("goout", n, "swig_r"); + + bool c_struct_type; + Delete(cgoTypeForGoValue(n, result, &c_struct_type)); + if (c_struct_type) { + memcpy_ret = true; + } + } + + String *call = NewString(""); + + Printv(call, "\t", NULL); + if (SwigType_type(result) != T_VOID) { + if (memcpy_ret) { + Printv(call, "swig_r_p := ", NULL); + } else { + Printv(call, "swig_r = (", ret_type, ")(", NULL); + } + if (goTypeIsInterface(n, result)) { + wt = goWrapperType(n, result, true); + Printv(call, "(", wt, ")(", NULL); + } + } + + Printv(call, "C.", upcall_wname, "(C.uintptr_t(swig_p.(*", + director_struct_name, ").", go_type_name, ")", NULL); + + p = parms; + for (int i = 0; i < parm_count; ++i) { + Printv(call, ", ", NULL); + p = getParm(p); + SwigType *pt = Getattr(p, "type"); + + String *ivar = NewStringf("_swig_i_%d", i); + + String *ln = Copy(Getattr(p, "lname")); + + String *goin = goGetattr(p, "tmap:goin"); + if (goin == NULL) { + Printv(f_go_wrappers, "\t", ivar, " := ", NULL); + bool need_close = false; + if (goTypeIsInterface(p, pt)) { + Printv(f_go_wrappers, "getSwigcptr(", NULL); + need_close = true; + } + Printv(f_go_wrappers, ln, NULL); + if (need_close) { + Printv(f_go_wrappers, ")", NULL); + } + Printv(f_go_wrappers, "\n", NULL); + } else { + String *itm = goImType(p, pt); + Printv(f_go_wrappers, "\tvar ", ivar, " ", itm, "\n", NULL); + goin = Copy(goin); + Replaceall(goin, "$input", ln); + Replaceall(goin, "$result", ivar); + Printv(f_go_wrappers, goin, "\n", NULL); + Delete(goin); + } + + Setattr(p, "emit:goinput", ivar); + + bool c_struct_type; + String *ct = cgoTypeForGoValue(p, pt, &c_struct_type); + if (c_struct_type) { + Printv(call, "*(*C.", ct, ")(unsafe.Pointer(&", ivar, "))", NULL); + } else { + Printv(call, "C.", ct, "(", ivar, ")", NULL); + } + + Delete(ln); + + p = nextParm(p); + } + + Printv(call, ")", NULL); + + if (wt) { + // Close the type conversion to the wrapper type. + Printv(call, ")", NULL); + } + if (SwigType_type(result) != T_VOID && !memcpy_ret) { + // Close the type conversion of the return value. + Printv(call, ")", NULL); + } + + Printv(call, "\n", NULL); + + Printv(f_go_wrappers, call, NULL); + Delete(call); + + if (memcpy_ret) { + Printv(f_go_wrappers, "\tswig_r = *(*", ret_type, ")(unsafe.Pointer(&swig_r_p))\n", NULL); + } + + goargout(parms); + + if (SwigType_type(result) != T_VOID) { + if (goout == NULL) { + Printv(f_go_wrappers, "\treturn swig_r\n", NULL); + } else { + String *tm = goType(n, result); + Printv(f_go_wrappers, "\tvar swig_r_1 ", tm, "\n", NULL); + Replaceall(goout, "$input", "swig_r"); + Replaceall(goout, "$result", "swig_r_1"); + Printv(f_go_wrappers, goout, "\n", NULL); + Printv(f_go_wrappers, "\treturn swig_r_1\n", NULL); + } + } + + Printv(f_go_wrappers, "}\n\n", NULL); + + if (ret_type) { + Delete(ret_type); + } + if (wt) { + Delete(wt); + } + + // Define a method in the C++ director class that the C++ + // upcall function can call. This permits an upcall to a + // protected method. + String *upcall_method_name = NewString("_swig_upcall_"); Append(upcall_method_name, name); if (overname) { @@ -3683,157 +3834,6 @@ private: Swig_restore(n); Delete(upcall_method_name); - - // Define a function that uses the Go director type that other - // methods in the Go type can call to get parent methods. - - Printv(f_go_wrappers, "func Director", cn, go_with_over_name, "(p ", cn, NULL); - - p = parms; - for (int i = 0; i < parm_count; ++i) { - p = getParm(p); - Printv(f_go_wrappers, ", ", Getattr(p, "lname"), " ", NULL); - String *tm = goType(p, Getattr(p, "type")); - Printv(f_go_wrappers, tm, NULL); - Delete(tm); - p = nextParm(p); - } - - Printv(f_go_wrappers, ")", NULL); - - if (SwigType_type(result) != T_VOID) { - String *tm = goType(n, result); - Printv(f_go_wrappers, " ", tm, NULL); - Delete(tm); - } - - Printv(f_go_wrappers, " {\n", NULL); - - String *ret_type = NULL; - bool memcpy_ret = false; - String *wt = NULL; - String *goout = NULL; - if (SwigType_type(result) != T_VOID) { - ret_type = goImType(n, result); - Printv(f_go_wrappers, "\tvar swig_r ", ret_type, "\n", NULL); - goout = goTypemapLookup("goout", n, "swig_r"); - - bool c_struct_type; - Delete(cgoTypeForGoValue(n, result, &c_struct_type)); - if (c_struct_type) { - memcpy_ret = true; - } - } - - String *call = NewString(""); - - Printv(call, "\t", NULL); - if (SwigType_type(result) != T_VOID) { - if (memcpy_ret) { - Printv(call, "swig_r_p := ", NULL); - } else { - Printv(call, "swig_r = (", ret_type, ")(", NULL); - } - if (goTypeIsInterface(n, result)) { - wt = goWrapperType(n, result, true); - Printv(call, "(", wt, ")(", NULL); - } - } - - Printv(call, "C.", upcall_wname, "(C.uintptr_t(p.(*", - director_struct_name, ").", go_type_name, ")", NULL); - - p = parms; - for (int i = 0; i < parm_count; ++i) { - Printv(call, ", ", NULL); - p = getParm(p); - SwigType *pt = Getattr(p, "type"); - - String *ivar = NewStringf("_swig_i_%d", i); - - String *ln = Copy(Getattr(p, "lname")); - - String *goin = goGetattr(p, "tmap:goin"); - if (goin == NULL) { - Printv(f_go_wrappers, "\t", ivar, " := ", NULL); - bool need_close = false; - if (goTypeIsInterface(p, pt)) { - Printv(f_go_wrappers, "getSwigcptr(", NULL); - need_close = true; - } - Printv(f_go_wrappers, ln, NULL); - if (need_close) { - Printv(f_go_wrappers, ")", NULL); - } - Printv(f_go_wrappers, "\n", NULL); - } else { - String *itm = goImType(p, pt); - Printv(f_go_wrappers, "\tvar ", ivar, " ", itm, "\n", NULL); - goin = Copy(goin); - Replaceall(goin, "$input", ln); - Replaceall(goin, "$result", ivar); - Printv(f_go_wrappers, goin, "\n", NULL); - Delete(goin); - } - - Setattr(p, "emit:goinput", ivar); - - bool c_struct_type; - String *ct = cgoTypeForGoValue(p, pt, &c_struct_type); - if (c_struct_type) { - Printv(call, "*(*C.", ct, ")(unsafe.Pointer(&", ivar, "))", NULL); - } else { - Printv(call, "C.", ct, "(", ivar, ")", NULL); - } - - Delete(ln); - - p = nextParm(p); - } - - Printv(call, ")", NULL); - - if (wt) { - // Close the type conversion to the wrapper type. - Printv(call, ")", NULL); - } - if (SwigType_type(result) != T_VOID && !memcpy_ret) { - // Close the type conversion of the return value. - Printv(call, ")", NULL); - } - - Printv(call, "\n", NULL); - - Printv(f_go_wrappers, call, NULL); - Delete(call); - - if (memcpy_ret) { - Printv(f_go_wrappers, "\tswig_r = *(*", ret_type, ")(unsafe.Pointer(&swig_r_p))\n", NULL); - } - - goargout(parms); - - if (SwigType_type(result) != T_VOID) { - if (goout == NULL) { - Printv(f_go_wrappers, "\treturn swig_r\n", NULL); - } else { - String *tm = goType(n, result); - Printv(f_go_wrappers, "\tvar swig_r_1 ", tm, "\n", NULL); - Replaceall(goout, "$input", "swig_r"); - Replaceall(goout, "$result", "swig_r_1"); - Printv(f_go_wrappers, goout, "\n", NULL); - Printv(f_go_wrappers, "\treturn swig_r_1\n", NULL); - } - } - - Printv(f_go_wrappers, "}\n\n", NULL); - - if (ret_type) { - Delete(ret_type); - } - if (wt) { - Delete(wt); - } } // The Go function which invokes the method. This is called by From 8987259959ef8bb87efcd0e88d5eecaf6473f46b Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Fri, 1 Jul 2022 15:38:19 +1200 Subject: [PATCH 497/662] Fix ticket reference in comment --- Examples/test-suite/php/Makefile.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Examples/test-suite/php/Makefile.in b/Examples/test-suite/php/Makefile.in index 9e34ccc3d..ae3dd0aa1 100644 --- a/Examples/test-suite/php/Makefile.in +++ b/Examples/test-suite/php/Makefile.in @@ -26,7 +26,7 @@ C_TEST_CASES += \ li_cdata_carrays \ multivalue \ -# These fail with PHP8 currently. Aiming to fix before 4.1 release. See #2181. +# These fail with PHP8 currently. Aiming to fix before 4.1 release. See #2151. FAILING_CPP_TESTS = \ director_redefined \ director_using_member_scopes \ From 5a96a39aa48fe35fa0bd0b92f5fb5615447ea6e8 Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Thu, 7 Jul 2022 11:50:00 +1200 Subject: [PATCH 498/662] Adjust the DOH string hash function The one we're currently using only considers the last five characters plus the least significant bit of the last-but-sixth character, which unsurprisingly generates a lot of many-way collisions. This change seems to give about a 4% reduction in wallclock time for processing li_std_list_wrap.i from the testsuite for Python. The hash collision rate for this example drops from 39% to 0! Closes #2303 --- Source/DOH/string.c | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/Source/DOH/string.c b/Source/DOH/string.c index 543c3e3f8..8f321508e 100644 --- a/Source/DOH/string.c +++ b/Source/DOH/string.c @@ -180,19 +180,27 @@ static int String_hash(DOH *so) { if (s->hashkey >= 0) { return s->hashkey; } else { - char *c = s->str; + /* We use the djb2 hash function: https://theartincode.stanis.me/008-djb2/ + * + * One difference is we use initial seed 0. It seems the usual seed value + * is intended to help spread out hash values, which is beneficial if + * linear probing is used but DOH Hash uses a chain of buckets instead, and + * grouped hash values are probably more cache friendly. In tests using + * 0 seems slightly faster anyway. + */ + const char *c = s->str; unsigned int len = s->len > 50 ? 50 : s->len; unsigned int h = 0; unsigned int mlen = len >> 2; unsigned int i = mlen; for (; i; --i) { - h = (h << 5) + *(c++); - h = (h << 5) + *(c++); - h = (h << 5) + *(c++); - h = (h << 5) + *(c++); + h = h + (h << 5) + *(c++); + h = h + (h << 5) + *(c++); + h = h + (h << 5) + *(c++); + h = h + (h << 5) + *(c++); } for (i = len - (mlen << 2); i; --i) { - h = (h << 5) + *(c++); + h = h + (h << 5) + *(c++); } h &= 0x7fffffff; s->hashkey = (int)h; From d3759a9b36be36af5a7e01bf5853143dece4980f Mon Sep 17 00:00:00 2001 From: Julien Marrec Date: Fri, 8 Jul 2022 15:23:05 +1200 Subject: [PATCH 499/662] Avoid parse errors for C++ attributes Just ignore anything in between [[ and ]] in the scanner, which is better that failing with a parse error. Fixes #1158 Fixes #2286 --- Examples/test-suite/common.mk | 1 + .../test-suite/cpp11_attribute_specifiers.i | 41 +++++++++++++++++++ Source/CParse/cscanner.c | 12 ++++++ Source/CParse/parser.y | 1 + Source/Swig/scanner.c | 33 +++++++++++++-- Source/Swig/swigscan.h | 2 + 6 files changed, 86 insertions(+), 4 deletions(-) create mode 100644 Examples/test-suite/cpp11_attribute_specifiers.i diff --git a/Examples/test-suite/common.mk b/Examples/test-suite/common.mk index bf0e52f02..c654807d7 100644 --- a/Examples/test-suite/common.mk +++ b/Examples/test-suite/common.mk @@ -583,6 +583,7 @@ CPP11_TEST_CASES += \ cpp11_alias_nested_template_scoping \ cpp11_alignment \ cpp11_alternate_function_syntax \ + cpp11_attribute_specifiers \ cpp11_constexpr \ cpp11_decltype \ cpp11_default_delete \ diff --git a/Examples/test-suite/cpp11_attribute_specifiers.i b/Examples/test-suite/cpp11_attribute_specifiers.i new file mode 100644 index 000000000..aa6de312e --- /dev/null +++ b/Examples/test-suite/cpp11_attribute_specifiers.i @@ -0,0 +1,41 @@ +%module cpp11_attribute_specifiers + +%inline %{ + +#if defined(__GNUC__) +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" // We're using a deprecated attribute here... +#pragma GCC diagnostic ignored "-Wattributes" // likely is C++20 +#pragma GCC diagnostic ignored "-Wunused-variable" // We are using an unused variable on purpose here +#pragma GCC diagnostic ignored "-Wunused-parameter" // We are using an unused param on purpose here +#endif + +#if defined(__clang__) +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" +#pragma clang diagnostic ignored "-Wattributes" +#pragma clang diagnostic ignored "-Wunused-variable" +#pragma clang diagnostic ignored "-Wunused-parameter" +#endif + + +[[noreturn]] void noReturn() { throw; } +[[nodiscard]] bool noDiscard() { return true; } +[[nodiscard, deprecated("This has been replaced")]] bool noDiscardDeprecated() { return true; } +void maybeUnused1([[maybe_unused]] bool b) { } +bool maybeUnused2(bool a, [[maybe_unused]] bool b) { return a; } + +[[deprecated, nodiscard]] bool likely([[maybe_unused]] bool a, bool b) { + [[maybe_unused]] bool c = b; + if (b) [[likely]] { + return true; + } else [[unlikely]] { + if(a) { + return true; + } + } + return false; +} + +struct [[nodiscard]] S { }; + +%} diff --git a/Source/CParse/cscanner.c b/Source/CParse/cscanner.c index 155c7c81b..75f100d1c 100644 --- a/Source/CParse/cscanner.c +++ b/Source/CParse/cscanner.c @@ -354,6 +354,18 @@ static int yylook(void) { case SWIG_TOKEN_ELLIPSIS: return ELLIPSIS; + case SWIG_TOKEN_LLBRACKET: + do { + tok = Scanner_token(scan); + } while ((tok != SWIG_TOKEN_RRBRACKET) && (tok > 0)); + if (tok <= 0) { + Swig_error(cparse_file, cparse_line, "Unbalanced double brackets, missing closing (']]'). Reached end of input.\n"); + } + break; + + case SWIG_TOKEN_RRBRACKET: + return RRBRACKET; + /* Look for multi-character sequences */ case SWIG_TOKEN_RSTRING: diff --git a/Source/CParse/parser.y b/Source/CParse/parser.y index ddb9634b2..010df3c1c 100644 --- a/Source/CParse/parser.y +++ b/Source/CParse/parser.y @@ -1613,6 +1613,7 @@ static String *add_qualifier_to_declarator(SwigType *type, SwigType *qualifier) %token TYPE_INT TYPE_UNSIGNED TYPE_SHORT TYPE_LONG TYPE_FLOAT TYPE_DOUBLE TYPE_CHAR TYPE_WCHAR TYPE_VOID TYPE_SIGNED TYPE_BOOL TYPE_COMPLEX TYPE_TYPEDEF TYPE_RAW TYPE_NON_ISO_INT8 TYPE_NON_ISO_INT16 TYPE_NON_ISO_INT32 TYPE_NON_ISO_INT64 %token LPAREN RPAREN COMMA SEMI EXTERN INIT LBRACE RBRACE PERIOD ELLIPSIS %token CONST_QUAL VOLATILE REGISTER STRUCT UNION EQUAL SIZEOF MODULE LBRACKET RBRACKET +%token LLBRACKET RRBRACKET /* C++11 Attribute specifier sequence */ %token BEGINFILE ENDOFFILE %token ILLEGAL CONSTANT %token NAME RENAME NAMEWARN EXTEND PRAGMA FEATURE VARARGS diff --git a/Source/Swig/scanner.c b/Source/Swig/scanner.c index 65f534a79..b03a07a5b 100644 --- a/Source/Swig/scanner.c +++ b/Source/Swig/scanner.c @@ -596,10 +596,6 @@ static int look(Scanner *s) { state = 3; else if (c == '\\') return SWIG_TOKEN_BACKSLASH; - else if (c == '[') - return SWIG_TOKEN_LBRACKET; - else if (c == ']') - return SWIG_TOKEN_RBRACKET; else if (c == '@') return SWIG_TOKEN_AT; else if (c == '$') @@ -637,6 +633,10 @@ static int look(Scanner *s) { else if (c == '.') state = 100; /* Maybe a number, maybe ellipsis, just a period */ + else if (c == '[') + state = 102; /* Maybe a bracket or a double bracket */ + else if (c == ']') + state = 103; /* Maybe a bracket or a double bracket */ else if (isdigit(c)) state = 8; /* A numerical value */ else @@ -1358,6 +1358,31 @@ static int look(Scanner *s) { } break; + /* A left bracket or a double left bracket */ + case 102: + + if ((c = nextchar(s)) == 0) { + return SWIG_TOKEN_LBRACKET; + } else if (c == '[') { + return SWIG_TOKEN_LLBRACKET; + } else { + retract(s, 1); + return SWIG_TOKEN_LBRACKET; + } + break; + + /* a right bracket or a double right bracket */ + case 103: + if ((c = nextchar(s)) == 0) { + return SWIG_TOKEN_RBRACKET; + } else if (c == ']') { + return SWIG_TOKEN_RRBRACKET; + } else { + retract(s, 1); + return SWIG_TOKEN_RBRACKET; + } + break; + case 200: /* PLUS, PLUSPLUS, PLUSEQUAL */ if ((c = nextchar(s)) == 0) return SWIG_TOKEN_PLUS; diff --git a/Source/Swig/swigscan.h b/Source/Swig/swigscan.h index 4f66de8a2..526413a14 100644 --- a/Source/Swig/swigscan.h +++ b/Source/Swig/swigscan.h @@ -71,6 +71,8 @@ extern void Scanner_locator(Scanner *, String *loc); #define SWIG_TOKEN_WSTRING 33 /* L"str" */ #define SWIG_TOKEN_WCHAR 34 /* L'c' */ #define SWIG_TOKEN_ELLIPSIS 35 /* ... */ +#define SWIG_TOKEN_LLBRACKET 36 /* [[ */ +#define SWIG_TOKEN_RRBRACKET 37 /* ]] */ #define SWIG_TOKEN_ILLEGAL 99 #define SWIG_TOKEN_ERROR -1 From 5ddcbac56b1e1d5716ace67412c82ba6ed55ec98 Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Fri, 8 Jul 2022 15:33:01 +1200 Subject: [PATCH 500/662] Test [[ and ]] in string literal are preserved Suggested by wsfulton in #1158 --- Examples/test-suite/cpp11_attribute_specifiers.i | 2 ++ .../php/cpp11_attribute_specifiers_runme.php | 14 ++++++++++++++ 2 files changed, 16 insertions(+) create mode 100644 Examples/test-suite/php/cpp11_attribute_specifiers_runme.php diff --git a/Examples/test-suite/cpp11_attribute_specifiers.i b/Examples/test-suite/cpp11_attribute_specifiers.i index aa6de312e..0d49b8615 100644 --- a/Examples/test-suite/cpp11_attribute_specifiers.i +++ b/Examples/test-suite/cpp11_attribute_specifiers.i @@ -38,4 +38,6 @@ bool maybeUnused2(bool a, [[maybe_unused]] bool b) { return a; } struct [[nodiscard]] S { }; +const char *test_string_literal() { return "Test [[ and ]] in string literal"; } + %} diff --git a/Examples/test-suite/php/cpp11_attribute_specifiers_runme.php b/Examples/test-suite/php/cpp11_attribute_specifiers_runme.php new file mode 100644 index 000000000..2336b319a --- /dev/null +++ b/Examples/test-suite/php/cpp11_attribute_specifiers_runme.php @@ -0,0 +1,14 @@ + Date: Fri, 8 Jul 2022 15:50:51 +1200 Subject: [PATCH 501/662] Turn an unmatched ]] back into two ] Needed to handle e.g. `a[a[0]]`. SWIG's parser doesn't seem to handle that currently though. See #2286. --- Examples/test-suite/cpp11_attribute_specifiers.i | 7 +++++++ Source/CParse/cscanner.c | 4 +++- Source/CParse/parser.y | 1 - 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/Examples/test-suite/cpp11_attribute_specifiers.i b/Examples/test-suite/cpp11_attribute_specifiers.i index 0d49b8615..063e431e0 100644 --- a/Examples/test-suite/cpp11_attribute_specifiers.i +++ b/Examples/test-suite/cpp11_attribute_specifiers.i @@ -40,4 +40,11 @@ struct [[nodiscard]] S { }; const char *test_string_literal() { return "Test [[ and ]] in string literal"; } +#if 0 +// Check that SWIG doesn't choke on ]] when it's not part of an attribute. +// FIXME: SWIG's parser doesn't handle this case currently. +int *a; +int b = a[a[0]]; +#endif + %} diff --git a/Source/CParse/cscanner.c b/Source/CParse/cscanner.c index 75f100d1c..558a9c6cf 100644 --- a/Source/CParse/cscanner.c +++ b/Source/CParse/cscanner.c @@ -364,7 +364,9 @@ static int yylook(void) { break; case SWIG_TOKEN_RRBRACKET: - return RRBRACKET; + /* Turn an unmatched ]] back into two ] - e.g. `a[a[0]]` */ + scanner_next_token(RBRACKET); + return RBRACKET; /* Look for multi-character sequences */ diff --git a/Source/CParse/parser.y b/Source/CParse/parser.y index 010df3c1c..ddb9634b2 100644 --- a/Source/CParse/parser.y +++ b/Source/CParse/parser.y @@ -1613,7 +1613,6 @@ static String *add_qualifier_to_declarator(SwigType *type, SwigType *qualifier) %token TYPE_INT TYPE_UNSIGNED TYPE_SHORT TYPE_LONG TYPE_FLOAT TYPE_DOUBLE TYPE_CHAR TYPE_WCHAR TYPE_VOID TYPE_SIGNED TYPE_BOOL TYPE_COMPLEX TYPE_TYPEDEF TYPE_RAW TYPE_NON_ISO_INT8 TYPE_NON_ISO_INT16 TYPE_NON_ISO_INT32 TYPE_NON_ISO_INT64 %token LPAREN RPAREN COMMA SEMI EXTERN INIT LBRACE RBRACE PERIOD ELLIPSIS %token CONST_QUAL VOLATILE REGISTER STRUCT UNION EQUAL SIZEOF MODULE LBRACKET RBRACKET -%token LLBRACKET RRBRACKET /* C++11 Attribute specifier sequence */ %token BEGINFILE ENDOFFILE %token ILLEGAL CONSTANT %token NAME RENAME NAMEWARN EXTEND PRAGMA FEATURE VARARGS From a5380ed1c52e015c3a8c000306c0704a26260708 Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Fri, 8 Jul 2022 15:57:29 +1200 Subject: [PATCH 502/662] Update docs for C++ attribute support --- CHANGES.current | 5 +++++ Doc/Manual/CPlusPlus11.html | 4 +++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGES.current b/CHANGES.current index 3a10743e5..c78242886 100644 --- a/CHANGES.current +++ b/CHANGES.current @@ -7,6 +7,11 @@ the issue number to the end of the URL: https://github.com/swig/swig/issues/ Version 4.1.0 (in progress) =========================== +2022-07-07: jmarrec + #1158 #2286 Add basic support for C++11 attributes. These are now + crudely ignored by SWIG's parser's tokeniser, which is better that + failing with a parse error. + 2022-07-05: ianlancetaylor [Go] #2245 Handle NULL pointers for string* conversions. Rearrange generation of director methods and rename diff --git a/Doc/Manual/CPlusPlus11.html b/Doc/Manual/CPlusPlus11.html index 52764eeef..7618b6dbe 100644 --- a/Doc/Manual/CPlusPlus11.html +++ b/Doc/Manual/CPlusPlus11.html @@ -1089,7 +1089,9 @@ Use the preprocessor to work around this for now:

    -Attributes such as those shown below, are not yet supported and will give a syntax error. +Attributes such as those shown below, are supported since SWIG 4.1.0 but are +currently crudely ignored by the parser's tokeniser so they have no effect on +SWIG's code generation.

    
    From 655da94f360a1e19a8cf72768b2525780fbf29f5 Mon Sep 17 00:00:00 2001
    From: Olly Betts 
    Date: Fri, 8 Jul 2022 16:13:33 +1200
    Subject: [PATCH 503/662] CHANGES.current: Fix some typos
    
    ---
     CHANGES.current | 6 +++---
     1 file changed, 3 insertions(+), 3 deletions(-)
    
    diff --git a/CHANGES.current b/CHANGES.current
    index c78242886..2614bf6d7 100644
    --- a/CHANGES.current
    +++ b/CHANGES.current
    @@ -18,7 +18,7 @@ Version 4.1.0 (in progress)
     	    receiver argument from p to swig_p.
     
     2022-07-03: wsfulton
    -            Performane optimisation for directors for classes passed by value. The directorin
    +            Performance optimisation for directors for classes passed by value. The directorin
                 typemaps in the director methods now use std::move on the input parameter when
                 copying the object from the stack to the heap prior to the callback into the target
                 language, thereby taking advantage of move semantics if available.
    @@ -43,7 +43,7 @@ Version 4.1.0 (in progress)
     
                 The implementation removed all casts in the "out" typemaps to allow the compiler to
                 appropriately choose calling a move constructor, where possible, otherwise a copy
    -            constructor. The implementation alsoand required modifying SwigValueWrapper to
    +            constructor. The implementation also required modifying SwigValueWrapper to
                 change a cast operator from:
     
                   SwigValueWrapper::operator T&() const;
    @@ -120,7 +120,7 @@ Version 4.1.0 (in progress)
     
     2022-05-26: rokups
                 [C#] #1323 Modify SwigDerivedClassHasMethod for a more efficient director
    -            implementation when calling virtual methods that are not overidden.
    +            implementation when calling virtual methods that are not overridden.
     
     2022-05-15: erezgeva, eiselekd
                 [Lua, Perl, Octave, PHP, Tcl] #2275 #2276 #2283 Add argcargv.i library containing
    
    From 22a4355f340e9a844d5e5d8d0528d767c4808ebb Mon Sep 17 00:00:00 2001
    From: Olly Betts 
    Date: Fri, 8 Jul 2022 16:34:19 +1200
    Subject: [PATCH 504/662] [xml] Move to "Experimental" target language status
    
    The XML target language support is not in good shape and is likely to be
    removed unless somebody steps up to bring it up to the expected standard
    (it fails to even meet the criteria for "Experimental" currently).
    
    Closes #2213
    ---
     CHANGES.current             | 6 ++++++
     Doc/Manual/SWIG.html        | 2 +-
     Examples/xml/Makefile.in    | 4 +++-
     RELEASENOTES                | 1 +
     Source/Modules/swigmain.cxx | 2 +-
     5 files changed, 12 insertions(+), 3 deletions(-)
    
    diff --git a/CHANGES.current b/CHANGES.current
    index 2614bf6d7..f5ffd91e2 100644
    --- a/CHANGES.current
    +++ b/CHANGES.current
    @@ -7,6 +7,12 @@ the issue number to the end of the URL: https://github.com/swig/swig/issues/
     Version 4.1.0 (in progress)
     ===========================
     
    +2022-07-07: olly
    +	    [xml] #2213 XML has been moved to "Experimental" target language
    +	    status. It's not in good shape and is likely to be removed unless
    +	    somebody steps up to bring it up to the expected standard (it fails
    +	    to even meet the criteria for "Experimental" currently).
    +
     2022-07-07: jmarrec
     	    #1158 #2286 Add basic support for C++11 attributes.  These are now
     	    crudely ignored by SWIG's parser's tokeniser, which is better that
    diff --git a/Doc/Manual/SWIG.html b/Doc/Manual/SWIG.html
    index 1d929ac71..8d8f7bd45 100644
    --- a/Doc/Manual/SWIG.html
    +++ b/Doc/Manual/SWIG.html
    @@ -134,11 +134,11 @@ Supported Target Language Options
          -ruby           - Generate Ruby wrappers
          -scilab         - Generate Scilab wrappers
          -tcl8           - Generate Tcl 8 wrappers
    -     -xml            - Generate XML wrappers
     
     Experimental Target Language Options
          -mzscheme       - Generate MzScheme/Racket wrappers
          -ocaml          - Generate OCaml wrappers
    +     -xml            - Generate XML wrappers
     
     General Options
          -addextern      - Add extra extern declarations
    diff --git a/Examples/xml/Makefile.in b/Examples/xml/Makefile.in
    index 44894b8ea..eaabe0ac5 100644
    --- a/Examples/xml/Makefile.in
    +++ b/Examples/xml/Makefile.in
    @@ -5,9 +5,11 @@ top_srcdir	= @top_srcdir@
     top_builddir	= @top_builddir@
     
     SWIGEXE         = $(top_builddir)/swig
    +# Suppress "experimental target language" warning
    +SWIGOPT         = -w524
     SWIG_LIB_DIR    = $(top_srcdir)/Lib
     SWIG_LIB_SET    = @SWIG_LIB_SET@
    -SWIGINVOKE      = $(SWIG_LIB_SET) $(SWIGTOOL) $(SWIGEXE)
    +SWIGINVOKE      = $(SWIG_LIB_SET) $(SWIGTOOL) $(SWIGEXE) $(SWIGOPT)
     
     cleanup		= tail +2 \
     		  | sed -e 's/ident="ID[0-9A-F]*"//g' \
    diff --git a/RELEASENOTES b/RELEASENOTES
    index 1fedffc8a..2fad03096 100644
    --- a/RELEASENOTES
    +++ b/RELEASENOTES
    @@ -14,6 +14,7 @@ SWIG-4.1.0 summary:
     - Common cases of `<` and `>` comparisons in constant expressions are now
       supported.
     - GitHub Actions is now used instead of Travis CI for continuous integration.
    +- The "XML" target language has been reclassified as "Experimental".
     
     SWIG-4.0.2 summary:
     - A few fixes around doxygen comment handling.
    diff --git a/Source/Modules/swigmain.cxx b/Source/Modules/swigmain.cxx
    index 45dffbe85..7cb2c2398 100644
    --- a/Source/Modules/swigmain.cxx
    +++ b/Source/Modules/swigmain.cxx
    @@ -80,7 +80,7 @@ static TargetLanguageModule modules[] = {
       {"-tcl", swig_tcl, NULL, Supported},
       {"-tcl8", swig_tcl, "Tcl 8", Supported},
       {"-uffi", NULL, "Common Lisp / UFFI", Disabled},
    -  {"-xml", swig_xml, "XML", Supported},
    +  {"-xml", swig_xml, "XML", Experimental},
       {NULL, NULL, NULL, Disabled}
     };
     
    
    From 1ece69cafd417b2936347686df8482a26eadb90e Mon Sep 17 00:00:00 2001
    From: William S Fulton 
    Date: Fri, 8 Jul 2022 08:01:55 +0100
    Subject: [PATCH 505/662] Test copy constructor and assignment operator calls
     for movable types
    
    This is the current state of play where the copy constructor and copy
    assignment operators are called, even for movable types passed as
    function parameters.
    ---
     Examples/test-suite/cpp11_move_only.i               |  4 ++++
     Examples/test-suite/csharp/cpp11_move_only_runme.cs | 11 +++++++++++
     Examples/test-suite/java/cpp11_move_only_runme.java | 12 ++++++++++++
     Examples/test-suite/python/cpp11_move_only_runme.py | 10 ++++++++++
     4 files changed, 37 insertions(+)
    
    diff --git a/Examples/test-suite/cpp11_move_only.i b/Examples/test-suite/cpp11_move_only.i
    index 7c91933c4..f97d7090e 100644
    --- a/Examples/test-suite/cpp11_move_only.i
    +++ b/Examples/test-suite/cpp11_move_only.i
    @@ -27,6 +27,8 @@ struct MoveOnly {
     
       static MoveOnly create() { return MoveOnly(111); }
       // static const MoveOnly createConst() { return MoveOnly(111); } // not supported by default
    +
    +  // static void take(MoveOnly mo) { if (debug) cout << "take(MoveOnly)" << " " << &mo << endl; }
     };
     %}
     
    @@ -48,5 +50,7 @@ struct MovableCopyable {
     
       static MovableCopyable create() { return MovableCopyable(111); }
       static const MovableCopyable createConst() { return MovableCopyable(111); }
    +
    +  static void take(MovableCopyable mc) { if (debug) cout << "take(MovableCopyable)" << " " << &mc << endl; }
     };
     %}
    diff --git a/Examples/test-suite/csharp/cpp11_move_only_runme.cs b/Examples/test-suite/csharp/cpp11_move_only_runme.cs
    index 57cb7aa18..4bd291109 100644
    --- a/Examples/test-suite/csharp/cpp11_move_only_runme.cs
    +++ b/Examples/test-suite/csharp/cpp11_move_only_runme.cs
    @@ -4,6 +4,8 @@ using cpp11_move_onlyNamespace;
     public class cpp11_move_only_runme {
     
       public static void Main() {
    +
    +    // Output
         Counter.reset_counts();
         using (MoveOnly mo = MoveOnly.create()) {
         }
    @@ -19,5 +21,14 @@ public class cpp11_move_only_runme {
         using (MovableCopyable mo = MovableCopyable.createConst()) {
         }
         Counter.check_counts(2, 1, 1, 0, 0, 3);
    +
    +    // Input
    +    Counter.reset_counts();
    +    using (MovableCopyable mo = new MovableCopyable(222)) {
    +      Counter.check_counts(1, 0, 0, 0, 0, 0);
    +      MovableCopyable.take(mo);
    +      Counter.check_counts(2, 1, 1, 0, 0, 2);
    +    }
    +    Counter.check_counts(2, 1, 1, 0, 0, 3);
       }
     }
    diff --git a/Examples/test-suite/java/cpp11_move_only_runme.java b/Examples/test-suite/java/cpp11_move_only_runme.java
    index b652634e5..e1d7cf180 100644
    --- a/Examples/test-suite/java/cpp11_move_only_runme.java
    +++ b/Examples/test-suite/java/cpp11_move_only_runme.java
    @@ -14,6 +14,7 @@ public class cpp11_move_only_runme {
     
       public static void main(String argv[]) {
     
    +    // Output
         {
           Counter.reset_counts();
           MoveOnly mo = MoveOnly.create();
    @@ -35,5 +36,16 @@ public class cpp11_move_only_runme {
           mo.delete();
           Counter.check_counts(2, 1, 1, 0, 0, 3);
         }
    +
    +    // Input
    +    {
    +      Counter.reset_counts();
    +      MovableCopyable mo = new MovableCopyable(222);
    +      Counter.check_counts(1, 0, 0, 0, 0, 0);
    +      MovableCopyable.take(mo);
    +      Counter.check_counts(2, 1, 1, 0, 0, 2);
    +      mo.delete();
    +      Counter.check_counts(2, 1, 1, 0, 0, 3);
    +    }
       }
     }
    diff --git a/Examples/test-suite/python/cpp11_move_only_runme.py b/Examples/test-suite/python/cpp11_move_only_runme.py
    index 1c3183327..1e1defcdc 100644
    --- a/Examples/test-suite/python/cpp11_move_only_runme.py
    +++ b/Examples/test-suite/python/cpp11_move_only_runme.py
    @@ -1,5 +1,6 @@
     from cpp11_move_only import *
     
    +# Output
     Counter.reset_counts()
     mo = MoveOnly.create()
     del mo
    @@ -15,3 +16,12 @@ Counter.reset_counts()
     mo = MovableCopyable.createConst()
     del mo
     Counter.check_counts(2, 1, 1, 0, 0, 3)
    +
    +# Input
    +Counter.reset_counts()
    +mo = MovableCopyable(222)
    +Counter.check_counts(1, 0, 0, 0, 0, 0)
    +MovableCopyable.take(mo)
    +Counter.check_counts(2, 1, 1, 0, 0, 2)
    +del mo
    +Counter.check_counts(2, 1, 1, 0, 0, 3)
    
    From e777b054d583aaf2ed445a263208c6ef21bc05ac Mon Sep 17 00:00:00 2001
    From: William S Fulton 
    Date: Fri, 8 Jul 2022 08:34:45 +0100
    Subject: [PATCH 506/662] Performance optimisation for parameters passed by
     value that are C++11 movable.
    
    The C++ wrappers create a temporary variable for a parameter to be passed to a
    function. This is initially default constructed and then copy assigned from the
    instance being passed in from the target language. This is unchanged, however,
    when the temporary variable is passed to wrapped function, it is now done using
    std::move. If the type is move constructible, the move constructor will be used
    instead of the copy constructor.
    
    Note that the implementation calls std::move for all user-defined types
    (non-primitive types passed by value), this excludes anything passed by pointer,
    reference and arrays. It does also include any type that has not been
    defined/parsed by SWIG, that is, unknown types. std::move is called via the
    SWIG_STD_MOVE macro which only calls std::move for C++11 and later code.
    ---
     CHANGES.current                                     | 11 ++++++++++-
     Examples/test-suite/csharp/cpp11_move_only_runme.cs |  4 ++--
     Examples/test-suite/java/cpp11_move_only_runme.java |  4 ++--
     Examples/test-suite/python/cpp11_move_only_runme.py |  4 ++--
     Source/Swig/cwrap.c                                 | 10 +++++++---
     5 files changed, 23 insertions(+), 10 deletions(-)
    
    diff --git a/CHANGES.current b/CHANGES.current
    index 9adfa8ad0..d00f53bc2 100644
    --- a/CHANGES.current
    +++ b/CHANGES.current
    @@ -7,8 +7,17 @@ the issue number to the end of the URL: https://github.com/swig/swig/issues/
     Version 4.1.0 (in progress)
     ===========================
     
    +2022-07-08: wsfulton
    +            Performance optimisation for parameters passed by value that are C++11 movable.
    +            The C++ wrappers create a temporary variable for a parameter to be passed to a
    +            function. This is initially default constructed and then copy assigned from the
    +            instance being passed in from the target language. This is unchanged, however,
    +            when the temporary variable is passed to wrapped function, it is now done using
    +            std::move. If the type is move constructible, the move constructor will be used
    +            instead of the copy constructor.
    +
     2022-07-03: wsfulton
    -            Performane optimisation for directors for classes passed by value. The directorin
    +            Performance optimisation for directors for classes passed by value. The directorin
                 typemaps in the director methods now use std::move on the input parameter when
                 copying the object from the stack to the heap prior to the callback into the target
                 language, thereby taking advantage of move semantics if available.
    diff --git a/Examples/test-suite/csharp/cpp11_move_only_runme.cs b/Examples/test-suite/csharp/cpp11_move_only_runme.cs
    index 4bd291109..f2d1c4cb5 100644
    --- a/Examples/test-suite/csharp/cpp11_move_only_runme.cs
    +++ b/Examples/test-suite/csharp/cpp11_move_only_runme.cs
    @@ -27,8 +27,8 @@ public class cpp11_move_only_runme {
         using (MovableCopyable mo = new MovableCopyable(222)) {
           Counter.check_counts(1, 0, 0, 0, 0, 0);
           MovableCopyable.take(mo);
    -      Counter.check_counts(2, 1, 1, 0, 0, 2);
    +      Counter.check_counts(2, 0, 1, 1, 0, 2);
         }
    -    Counter.check_counts(2, 1, 1, 0, 0, 3);
    +    Counter.check_counts(2, 0, 1, 1, 0, 3);
       }
     }
    diff --git a/Examples/test-suite/java/cpp11_move_only_runme.java b/Examples/test-suite/java/cpp11_move_only_runme.java
    index e1d7cf180..8f0f2acef 100644
    --- a/Examples/test-suite/java/cpp11_move_only_runme.java
    +++ b/Examples/test-suite/java/cpp11_move_only_runme.java
    @@ -43,9 +43,9 @@ public class cpp11_move_only_runme {
           MovableCopyable mo = new MovableCopyable(222);
           Counter.check_counts(1, 0, 0, 0, 0, 0);
           MovableCopyable.take(mo);
    -      Counter.check_counts(2, 1, 1, 0, 0, 2);
    +      Counter.check_counts(2, 0, 1, 1, 0, 2);
           mo.delete();
    -      Counter.check_counts(2, 1, 1, 0, 0, 3);
    +      Counter.check_counts(2, 0, 1, 1, 0, 3);
         }
       }
     }
    diff --git a/Examples/test-suite/python/cpp11_move_only_runme.py b/Examples/test-suite/python/cpp11_move_only_runme.py
    index 1e1defcdc..9727f3fcc 100644
    --- a/Examples/test-suite/python/cpp11_move_only_runme.py
    +++ b/Examples/test-suite/python/cpp11_move_only_runme.py
    @@ -22,6 +22,6 @@ Counter.reset_counts()
     mo = MovableCopyable(222)
     Counter.check_counts(1, 0, 0, 0, 0, 0)
     MovableCopyable.take(mo)
    -Counter.check_counts(2, 1, 1, 0, 0, 2)
    +Counter.check_counts(2, 0, 1, 1, 0, 2)
     del mo
    -Counter.check_counts(2, 1, 1, 0, 0, 3)
    +Counter.check_counts(2, 0, 1, 1, 0, 3)
    diff --git a/Source/Swig/cwrap.c b/Source/Swig/cwrap.c
    index ebe9fa702..36e69332c 100644
    --- a/Source/Swig/cwrap.c
    +++ b/Source/Swig/cwrap.c
    @@ -427,10 +427,14 @@ String *Swig_cfunction_call(const_String_or_char_ptr name, ParmList *parms) {
           String *rcaststr = SwigType_rcaststr(rpt, pname);
     
           if (comma) {
    -	Printv(func, ",", rcaststr, NIL);
    -      } else {
    -	Append(func, rcaststr);
    +	Append(func, ",");
           }
    +
    +      if (cparse_cplusplus && SwigType_type(rpt) == T_USER)
    +	Printv(func, "SWIG_STD_MOVE(", rcaststr, ")", NIL);
    +      else
    +	Printv(func, rcaststr, NIL);
    +
           Delete(rpt);
           Delete(pname);
           Delete(rcaststr);
    
    From adb85d3d050958051aa88f01f51b71b8632096be Mon Sep 17 00:00:00 2001
    From: Erez Geva 
    Date: Mon, 4 Jul 2022 02:14:21 +0200
    Subject: [PATCH 507/662] Add std::unique_ptr to Perl5.
    
    Signed-off-by: Erez Geva 
    ---
     Examples/test-suite/cpp11_std_unique_ptr.i    |  2 +-
     .../perl5/cpp11_std_unique_ptr_runme.pl       | 17 +++++++++++++++++
     Lib/perl5/std_unique_ptr.i                    | 19 +++++++++++++++++++
     3 files changed, 37 insertions(+), 1 deletion(-)
     create mode 100644 Examples/test-suite/perl5/cpp11_std_unique_ptr_runme.pl
     create mode 100644 Lib/perl5/std_unique_ptr.i
    
    diff --git a/Examples/test-suite/cpp11_std_unique_ptr.i b/Examples/test-suite/cpp11_std_unique_ptr.i
    index 518d9be6e..9bd65b97f 100644
    --- a/Examples/test-suite/cpp11_std_unique_ptr.i
    +++ b/Examples/test-suite/cpp11_std_unique_ptr.i
    @@ -1,6 +1,6 @@
     %module cpp11_std_unique_ptr
     
    -#if defined(SWIGCSHARP) || defined(SWIGJAVA) || defined(SWIGPYTHON) || defined(SWIGRUBY)
    +#if defined(SWIGCSHARP) || defined(SWIGJAVA) || defined(SWIGPYTHON) || defined(SWIGRUBY) || defined(SWIGPERL)
     
     %include "std_unique_ptr.i"
     
    diff --git a/Examples/test-suite/perl5/cpp11_std_unique_ptr_runme.pl b/Examples/test-suite/perl5/cpp11_std_unique_ptr_runme.pl
    new file mode 100644
    index 000000000..ce64bbf00
    --- /dev/null
    +++ b/Examples/test-suite/perl5/cpp11_std_unique_ptr_runme.pl
    @@ -0,0 +1,17 @@
    +use strict;
    +use warnings;
    +use Test::More tests => 6;
    +BEGIN { use_ok('cpp11_std_unique_ptr') }
    +require_ok('cpp11_std_unique_ptr');
    +
    +my $k1 = cpp11_std_unique_ptr::makeKlassUniquePtr("first");
    +my $k2 = cpp11_std_unique_ptr::makeKlassUniquePtr("second");
    +is(cpp11_std_unique_ptr::Klass::getTotal_count, 2, "have 2 pointers");
    +
    +undef $k1;
    +is(cpp11_std_unique_ptr::Klass::getTotal_count, 1, "left 1 pointer");
    +
    +is($k2->getLabel, "second", "proper label");
    +
    +undef $k2;
    +is(cpp11_std_unique_ptr::Klass::getTotal_count, 0, "remove all pointers");
    diff --git a/Lib/perl5/std_unique_ptr.i b/Lib/perl5/std_unique_ptr.i
    new file mode 100644
    index 000000000..163c7c2d1
    --- /dev/null
    +++ b/Lib/perl5/std_unique_ptr.i
    @@ -0,0 +1,19 @@
    +/* -----------------------------------------------------------------------------
    + * std_unique_ptr.i
    + *
    + * The typemaps here allow handling functions returning std::unique_ptr<>,
    + * which is the most common use of this type. If you have functions taking it
    + * as parameter, these typemaps can't be used for them and you need to do
    + * something else (e.g. use shared_ptr<> which SWIG supports fully).
    + * ----------------------------------------------------------------------------- */
    +
    +%define %unique_ptr(TYPE)
    +%typemap (out) std::unique_ptr< TYPE > %{
    +   %set_output(SWIG_NewPointerObj($1.release(), $descriptor(TYPE *), SWIG_POINTER_OWN | %newpointer_flags));
    +%}
    +%template() std::unique_ptr< TYPE >;
    +%enddef
    +
    +namespace std {
    +   template  class unique_ptr {};
    +}
    
    From 29354ed19da2266395312b973195e7a9bd9a8461 Mon Sep 17 00:00:00 2001
    From: Olly Betts 
    Date: Mon, 11 Jul 2022 13:20:25 +1200
    Subject: [PATCH 508/662] Update comment in PHP testcase
    
    The PHP7 workaround we currently use has evolved a bit since this
    comment was written.
    ---
     Examples/test-suite/php/default_args_runme.php | 7 ++++---
     1 file changed, 4 insertions(+), 3 deletions(-)
    
    diff --git a/Examples/test-suite/php/default_args_runme.php b/Examples/test-suite/php/default_args_runme.php
    index cd0ec8127..c793b08af 100644
    --- a/Examples/test-suite/php/default_args_runme.php
    +++ b/Examples/test-suite/php/default_args_runme.php
    @@ -42,9 +42,10 @@ check::equal($f->double_if_void_ptr_is_null(6, Null), 12, "\$f->double_if_void_p
     
     check::equal($f->double_if_void_ptr_is_null(7), 14, "\$f->double_if_void_ptr_is_null(7)");
     
    -# For the testcases below PHP < 7.3 emits an error, while newer versions throw
    -# an exception.  We handle the older versions by suppressing the error with `@`,
    -# then checking for the created object being Null if the PHP version is < 7.3.
    +# For the testcases below, PHP 7 emits an error, while PHP 8 throws an
    +# exception.  To simplify the testcases we install an error handler function
    +# for PHP7 which throws an ArgumentCountError exception (which we have to
    +# define ourselves for PHP 7.0).
     
     if (PHP_MAJOR_VERSION == 7) {
       if (PHP_MINOR_VERSION == 0) {
    
    From cf9422b4d985faee722643c8b8ccda954d10063e Mon Sep 17 00:00:00 2001
    From: Olly Betts 
    Date: Mon, 11 Jul 2022 15:32:43 +1200
    Subject: [PATCH 509/662] [php] Stop setting unused php:proxy attribute
    
    This is no longer used since we changed how classes are wrapped.
    ---
     Source/Modules/php.cxx | 5 -----
     1 file changed, 5 deletions(-)
    
    diff --git a/Source/Modules/php.cxx b/Source/Modules/php.cxx
    index 67f7f1f19..7c7735a65 100644
    --- a/Source/Modules/php.cxx
    +++ b/Source/Modules/php.cxx
    @@ -1613,11 +1613,6 @@ public:
        * ------------------------------------------------------------ */
     
       virtual int classDeclaration(Node *n) {
    -    if (!Getattr(n, "feature:onlychildren")) {
    -      String *symname = Getattr(n, "sym:name");
    -      Setattr(n, "php:proxy", symname);
    -    }
    -
         return Language::classDeclaration(n);
       }
     
    
    From 63c681a5139050b0e44fd9a7cf79bd5eee538916 Mon Sep 17 00:00:00 2001
    From: Olly Betts 
    Date: Mon, 11 Jul 2022 15:37:53 +1200
    Subject: [PATCH 510/662] TODO: Remove nested typemaps since now supported
    
    ---
     TODO | 74 ------------------------------------------------------------
     1 file changed, 74 deletions(-)
    
    diff --git a/TODO b/TODO
    index 1fcc992ac..2182ef86a 100644
    --- a/TODO
    +++ b/TODO
    @@ -26,80 +26,6 @@ defer  ready to go.  The primary obstacle lies in the target language
            This is one of the last remaining "hard" problems in the SWIG
            core, but it is important that we solve it.
     
    -***    "Nested" typemaps. The basic idea is similar to allowing one to 
    -       use $descriptor(T) for any T, rather than just $descriptor
    -       for the type currently being typemapped.
    -
    -       In short (ha!), given a previously defined typemap:
    -
    -       %typemap(in) Foo {
    -           // whatever it takes to initialize $1 from $input
    -       }
    -
    -       it would be possible to inline its code inside another typemap. 
    -       While the syntax is still to be defined, the use would be
    -       along the lines of:
    -
    -       template  class vector {
    -           %typemap(in) vector {
    -               ...
    -               for (int i=0; i $typemap(in, input=x) 
    -	      	    ( int FIRST = foo, double SECOND = bar );
    -
    -	  The advantage of this syntax would be that the formal
    -	  arguments (int FIRST, double SECOND) are close to the
    -	  actual arguments (foo, bar).
    -
    -	Comment by beazley
    -
    -               $typemap(in, input=x) int = foo;
    -
    -        is a little bit hard to parse in terms of variable substitution.
    -        I'm considering something like this:
    -
    -               $typemap(in,1=int foo, input=x)
    -
    -       Note: This is partially implemented in the new Unified Typemap
    -       Library(python,tcl,ruby and perl) via %fragments and the
    -       SWIG_From/SWIG_AsVal methdos.
    -
     ***    Implement $fail special variable substitution in wrappers. Used
            to properly transfer control out of a wrapper function while
            reclaiming resources.
    
    From c25d0d707ac368c7db408fa76d91409d72f185e4 Mon Sep 17 00:00:00 2001
    From: Olly Betts 
    Date: Mon, 11 Jul 2022 16:38:29 +1200
    Subject: [PATCH 511/662] Minor PHP documentation improvements
    
    ---
     Doc/Manual/Php.html | 12 +++++-------
     1 file changed, 5 insertions(+), 7 deletions(-)
    
    diff --git a/Doc/Manual/Php.html b/Doc/Manual/Php.html
    index 419e87b50..51ef01c51 100644
    --- a/Doc/Manual/Php.html
    +++ b/Doc/Manual/Php.html
    @@ -307,11 +307,10 @@ functions.
     

    -SWIG honors the %immutable modifier by not generating code -for the _set method. This provides read-only access to the -variable from the php script. Attempting to access the _set -method will result in a php fatal error because the function is -undefined. +SWIG honors the %immutable modifier by not generating a +_set method (so attempting to call it will give a PHP fatal +error). A _get method is still generated so this provides read-only +access to the variable from the PHP script.

    @@ -700,8 +699,7 @@ Member variables and methods are accessed using the -> operator.

    The -noproxy option flattens the object structure and -generates collections of named functions (these are the functions -which the PHP class wrappers call). The above example results +generates collections of named functions. The above example results in the following PHP functions:

    From 65032006842f34d43e9c1c893e84e0489e309485 Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Mon, 11 Jul 2022 17:15:34 +1200 Subject: [PATCH 512/662] php: Encapsulate arginfo generation Encapsulate the code to generate arginfo in the PHPTypes class. By itself this should result in no functional changes, but it's a step towards being able to delay arginfo generation which I think is necessary to address the incompatible overridden method problem discussed in #2151. --- Source/Modules/php.cxx | 291 +++++++++++++++++++++-------------------- 1 file changed, 147 insertions(+), 144 deletions(-) diff --git a/Source/Modules/php.cxx b/Source/Modules/php.cxx index 7c7735a65..f79a60a45 100644 --- a/Source/Modules/php.cxx +++ b/Source/Modules/php.cxx @@ -220,32 +220,16 @@ class PHPTypes { // Used to clamp the required number of parameters in the arginfo to be // compatible with any parent class version of the method. - int required_clamp; + int num_required; -public: - PHPTypes(int num_required) - : merged_types(NewList()), - byref(NULL), - required_clamp(num_required) { } - - PHPTypes(const PHPTypes *o) - : merged_types(Copy(o->merged_types)), - byref(Copy(o->byref)), - required_clamp(o->required_clamp) { } - - ~PHPTypes() { - Delete(merged_types); - Delete(byref); + int get_byref(int key) const { + return byref && key < Len(byref) && Getitem(byref, key) != None; } - int adjust_num_required(int num_required) { - required_clamp = std::min(num_required, required_clamp); - return required_clamp; + int size() const { + return std::max(Len(merged_types), Len(byref)); } - // key is 0 for return type, or >= 1 for parameters numbered from 1 - void process_phptype(Node *n, int key, const String_or_char *attribute_name); - String *get_phptype(int key, String *classtypes) { Clear(classtypes); DOH *types = Getitem(merged_types, key); @@ -277,6 +261,29 @@ public: return result; } +public: + PHPTypes(int num_required_) + : merged_types(NewList()), + byref(NULL), + num_required(num_required_) { } + + PHPTypes(const PHPTypes *o) + : merged_types(Copy(o->merged_types)), + byref(Copy(o->byref)), + num_required(o->num_required) { } + + ~PHPTypes() { + Delete(merged_types); + Delete(byref); + } + + void adjust_num_required(int num_required_) { + num_required = std::min(num_required, num_required_); + } + + // key is 0 for return type, or >= 1 for parameters numbered from 1 + void process_phptype(Node *n, int key, const String_or_char *attribute_name); + void set_byref(int key) { if (!byref) { byref = NewList(); @@ -290,12 +297,124 @@ public: Setitem(byref, key, ""); // Just needs to be something != None. } - int get_byref(int key) const { - return byref && key < Len(byref) && Getitem(byref, key) != None; - } + void emit_arginfo(String *fname, String *cname, Node *n, String *modes, bool dispatch) { + // We want to only emit each different arginfo once, as that reduces the + // size of both the generated source code and the compiled extension + // module. The parameters at this level are just named arg1, arg2, etc + // so the arginfo will be the same for any function with the same number + // of parameters and (if present) PHP type declarations for parameters and + // return type. + // + // We generate the arginfo we want (taking care to normalise, e.g. the + // lists of types are unique and in sorted order), then use the + // arginfo_used Hash to see if we've already generated it. - int size() const { - return std::max(Len(merged_types), Len(byref)); + // Don't add a return type declaration for a constructor (because there + // is no return type as far as PHP is concerned). + String *out_phptype = NULL; + String *out_phpclasses = NewStringEmpty(); + if (!Equal(fname, "__construct")) { + String *php_type_flag = GetFlagAttr(n, "feature:php:type"); + if (Equal(php_type_flag, "1") || + (php_type_flag && !Getattr(n, "directorNode"))) { + // We provide a simple way to generate PHP return type declarations + // except for directed methods. The point of directors is to allow + // subclassing in the target language, and if the wrapped method has + // a return type declaration then an overriding method in user code + // needs to have a compatible declaration. + // + // The upshot of this is that enabling return type declarations for + // existing bindings would break compatibility with user code written + // for an older version. For parameters however the situation is + // different because if the parent class declares types for parameters + // a subclass overriding the function will be compatible whether it + // declares them or not. + // + // directorNode being present seems to indicate if this method or one + // it inherits from is directed, which is what we care about here. + // Using (!is_member_director(n)) would get it wrong for testcase + // director_frob. + out_phptype = get_phptype(0, out_phpclasses); + } + } + + // ### in arginfo_code will be replaced with the id once that is known. + String *arginfo_code = NewStringEmpty(); + if (out_phptype) { + if (Len(out_phpclasses)) { + Replace(out_phpclasses, "\\", "\\\\", DOH_REPLACE_ANY); + Printf(arginfo_code, "ZEND_BEGIN_ARG_WITH_RETURN_OBJ_TYPE_MASK_EX(swig_arginfo_###, 0, %d, %s, %s)\n", num_required, out_phpclasses, out_phptype); + } else { + Printf(arginfo_code, "ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(swig_arginfo_###, 0, %d, %s)\n", num_required, out_phptype); + } + } else { + Printf(arginfo_code, "ZEND_BEGIN_ARG_INFO_EX(swig_arginfo_###, 0, 0, %d)\n", num_required); + } + + int phptypes_size = size(); + for (int param_count = 1; param_count < phptypes_size; ++param_count) { + String *phpclasses = NewStringEmpty(); + String *phptype = get_phptype(param_count, phpclasses); + + int byref = get_byref(param_count); + + // FIXME: Should we be doing byref for return value as well? + + if (phptype) { + if (Len(phpclasses)) { + // We need to double any backslashes (which are PHP namespace + // separators) in the PHP class names as they get turned into + // C strings by the ZEND_ARG_OBJ_TYPE_MASK macro. + Replace(phpclasses, "\\", "\\\\", DOH_REPLACE_ANY); + Printf(arginfo_code, " ZEND_ARG_OBJ_TYPE_MASK(%d,arg%d,%s,%s,NULL)\n", byref, param_count, phpclasses, phptype); + } else { + Printf(arginfo_code, " ZEND_ARG_TYPE_MASK(%d,arg%d,%s,NULL)\n", byref, param_count, phptype); + } + } else { + Printf(arginfo_code, " ZEND_ARG_INFO(%d,arg%d)\n", byref, param_count); + } + } + Printf(arginfo_code, "ZEND_END_ARG_INFO()\n"); + + String *arginfo_id_new = Getattr(n, "sym:name"); + String *arginfo_id = Getattr(arginfo_used, arginfo_code); + if (arginfo_id) { + Printf(s_arginfo, "#define swig_arginfo_%s swig_arginfo_%s\n", arginfo_id_new, arginfo_id); + } else { + // Not had this arginfo before. + Setattr(arginfo_used, arginfo_code, arginfo_id_new); + arginfo_code = Copy(arginfo_code); + Replace(arginfo_code, "###", arginfo_id_new, DOH_REPLACE_FIRST); + Append(s_arginfo, arginfo_code); + } + Delete(arginfo_code); + arginfo_code = NULL; + + String *s = cs_entry; + if (!s) s = s_entry; + if (cname && Cmp(Getattr(n, "storage"), "friend") != 0) { + Printf(all_cs_entry, " PHP_ME(%s%s,%s,swig_arginfo_%s,%s)\n", prefix, cname, fname, arginfo_id_new, modes); + } else { + if (dispatch) { + if (wrap_nonclass_global) { + Printf(s, " ZEND_NAMED_FE(%(lower)s,%s,swig_arginfo_%s)\n", Getattr(n, "sym:name"), fname, arginfo_id_new); + } + + if (wrap_nonclass_fake_class) { + (void)fake_class_name(); + Printf(fake_cs_entry, " ZEND_NAMED_ME(%(lower)s,%s,swig_arginfo_%s,ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)\n", Getattr(n, "sym:name"), fname, arginfo_id_new); + } + } else { + if (wrap_nonclass_global) { + Printf(s, " PHP_FE(%s,swig_arginfo_%s)\n", fname, arginfo_id_new); + } + + if (wrap_nonclass_fake_class) { + String *fake_class = fake_class_name(); + Printf(fake_cs_entry, " PHP_ME(%s,%s,swig_arginfo_%s,ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)\n", fake_class, fname, arginfo_id_new); + } + } + } } }; @@ -726,125 +845,9 @@ public: } } - int num_required = phptypes->adjust_num_required(emit_num_required(l)); + phptypes->adjust_num_required(emit_num_required(l)); - // We want to only emit each different arginfo once, as that reduces the - // size of both the generated source code and the compiled extension - // module. The parameters at this level are just named arg1, arg2, etc - // so the arginfo will be the same for any function with the same number - // of parameters and (if present) PHP type declarations for parameters and - // return type. - // - // We generate the arginfo we want (taking care to normalise, e.g. the - // lists of types are unique and in sorted order), then use the - // arginfo_used Hash to see if we've already generated it. - - // Don't add a return type declaration for a constructor (because there - // is no return type as far as PHP is concerned). - String *out_phptype = NULL; - String *out_phpclasses = NewStringEmpty(); - if (!Equal(fname, "__construct")) { - String *php_type_flag = GetFlagAttr(n, "feature:php:type"); - if (Equal(php_type_flag, "1") || - (php_type_flag && !Getattr(n, "directorNode"))) { - // We provide a simple way to generate PHP return type declarations - // except for directed methods. The point of directors is to allow - // subclassing in the target language, and if the wrapped method has - // a return type declaration then an overriding method in user code - // needs to have a compatible declaration. - // - // The upshot of this is that enabling return type declarations for - // existing bindings would break compatibility with user code written - // for an older version. For parameters however the situation is - // different because if the parent class declares types for parameters - // a subclass overriding the function will be compatible whether it - // declares them or not. - // - // directorNode being present seems to indicate if this method or one - // it inherits from is directed, which is what we care about here. - // Using (!is_member_director(n)) would get it wrong for testcase - // director_frob. - out_phptype = phptypes->get_phptype(0, out_phpclasses); - } - } - - // ### in arginfo_code will be replaced with the id once that is known. - String *arginfo_code = NewStringEmpty(); - if (out_phptype) { - if (Len(out_phpclasses)) { - Replace(out_phpclasses, "\\", "\\\\", DOH_REPLACE_ANY); - Printf(arginfo_code, "ZEND_BEGIN_ARG_WITH_RETURN_OBJ_TYPE_MASK_EX(swig_arginfo_###, 0, %d, %s, %s)\n", num_required, out_phpclasses, out_phptype); - } else { - Printf(arginfo_code, "ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(swig_arginfo_###, 0, %d, %s)\n", num_required, out_phptype); - } - } else { - Printf(arginfo_code, "ZEND_BEGIN_ARG_INFO_EX(swig_arginfo_###, 0, 0, %d)\n", num_required); - } - - int phptypes_size = phptypes->size(); - for (int param_count = 1; param_count < phptypes_size; ++param_count) { - String *phpclasses = NewStringEmpty(); - String *phptype = phptypes->get_phptype(param_count, phpclasses); - - int byref = phptypes->get_byref(param_count); - - // FIXME: Should we be doing byref for return value as well? - - if (phptype) { - if (Len(phpclasses)) { - // We need to double any backslashes (which are PHP namespace - // separators) in the PHP class names as they get turned into - // C strings by the ZEND_ARG_OBJ_TYPE_MASK macro. - Replace(phpclasses, "\\", "\\\\", DOH_REPLACE_ANY); - Printf(arginfo_code, " ZEND_ARG_OBJ_TYPE_MASK(%d,arg%d,%s,%s,NULL)\n", byref, param_count, phpclasses, phptype); - } else { - Printf(arginfo_code, " ZEND_ARG_TYPE_MASK(%d,arg%d,%s,NULL)\n", byref, param_count, phptype); - } - } else { - Printf(arginfo_code, " ZEND_ARG_INFO(%d,arg%d)\n", byref, param_count); - } - } - Printf(arginfo_code, "ZEND_END_ARG_INFO()\n"); - - String *arginfo_id_new = Getattr(n, "sym:name"); - String *arginfo_id = Getattr(arginfo_used, arginfo_code); - if (arginfo_id) { - Printf(s_arginfo, "#define swig_arginfo_%s swig_arginfo_%s\n", arginfo_id_new, arginfo_id); - } else { - // Not had this arginfo before. - Setattr(arginfo_used, arginfo_code, arginfo_id_new); - arginfo_code = Copy(arginfo_code); - Replace(arginfo_code, "###", arginfo_id_new, DOH_REPLACE_FIRST); - Append(s_arginfo, arginfo_code); - } - Delete(arginfo_code); - arginfo_code = NULL; - - String *s = cs_entry; - if (!s) s = s_entry; - if (cname && Cmp(Getattr(n, "storage"), "friend") != 0) { - Printf(all_cs_entry, " PHP_ME(%s%s,%s,swig_arginfo_%s,%s)\n", prefix, cname, fname, arginfo_id_new, modes); - } else { - if (dispatch) { - if (wrap_nonclass_global) { - Printf(s, " ZEND_NAMED_FE(%(lower)s,%s,swig_arginfo_%s)\n", Getattr(n, "sym:name"), fname, arginfo_id_new); - } - - if (wrap_nonclass_fake_class) { - (void)fake_class_name(); - Printf(fake_cs_entry, " ZEND_NAMED_ME(%(lower)s,%s,swig_arginfo_%s,ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)\n", Getattr(n, "sym:name"), fname, arginfo_id_new); - } - } else { - if (wrap_nonclass_global) { - Printf(s, " PHP_FE(%s,swig_arginfo_%s)\n", fname, arginfo_id_new); - } - - if (wrap_nonclass_fake_class) { - String *fake_class = fake_class_name(); - Printf(fake_cs_entry, " PHP_ME(%s,%s,swig_arginfo_%s,ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)\n", fake_class, fname, arginfo_id_new); - } - } - } + phptypes->emit_arginfo(fname, cname, n, modes, dispatch); } /* ------------------------------------------------------------ From 7cf91c12dc8507a4f254c288e3d53c6cc373792c Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Mon, 11 Jul 2022 17:38:34 +1200 Subject: [PATCH 513/662] php: Move ME and FE generation back out of PHPTypes It's more natural to leave it where it was, and will work better when we delay the arginfo generation. --- Source/Modules/php.cxx | 57 +++++++++++++++++++++--------------------- 1 file changed, 29 insertions(+), 28 deletions(-) diff --git a/Source/Modules/php.cxx b/Source/Modules/php.cxx index f79a60a45..69558e2e2 100644 --- a/Source/Modules/php.cxx +++ b/Source/Modules/php.cxx @@ -297,7 +297,7 @@ public: Setitem(byref, key, ""); // Just needs to be something != None. } - void emit_arginfo(String *fname, String *cname, Node *n, String *modes, bool dispatch) { + void emit_arginfo(String *fname, Node *n) { // We want to only emit each different arginfo once, as that reduces the // size of both the generated source code and the compiled extension // module. The parameters at this level are just named arg1, arg2, etc @@ -389,32 +389,6 @@ public: } Delete(arginfo_code); arginfo_code = NULL; - - String *s = cs_entry; - if (!s) s = s_entry; - if (cname && Cmp(Getattr(n, "storage"), "friend") != 0) { - Printf(all_cs_entry, " PHP_ME(%s%s,%s,swig_arginfo_%s,%s)\n", prefix, cname, fname, arginfo_id_new, modes); - } else { - if (dispatch) { - if (wrap_nonclass_global) { - Printf(s, " ZEND_NAMED_FE(%(lower)s,%s,swig_arginfo_%s)\n", Getattr(n, "sym:name"), fname, arginfo_id_new); - } - - if (wrap_nonclass_fake_class) { - (void)fake_class_name(); - Printf(fake_cs_entry, " ZEND_NAMED_ME(%(lower)s,%s,swig_arginfo_%s,ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)\n", Getattr(n, "sym:name"), fname, arginfo_id_new); - } - } else { - if (wrap_nonclass_global) { - Printf(s, " PHP_FE(%s,swig_arginfo_%s)\n", fname, arginfo_id_new); - } - - if (wrap_nonclass_fake_class) { - String *fake_class = fake_class_name(); - Printf(fake_cs_entry, " PHP_ME(%s,%s,swig_arginfo_%s,ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)\n", fake_class, fname, arginfo_id_new); - } - } - } } }; @@ -847,7 +821,34 @@ public: phptypes->adjust_num_required(emit_num_required(l)); - phptypes->emit_arginfo(fname, cname, n, modes, dispatch); + phptypes->emit_arginfo(fname, n); + + String *arginfo_id_new = Getattr(n, "sym:name"); + String *s = cs_entry; + if (!s) s = s_entry; + if (cname && Cmp(Getattr(n, "storage"), "friend") != 0) { + Printf(all_cs_entry, " PHP_ME(%s%s,%s,swig_arginfo_%s,%s)\n", prefix, cname, fname, arginfo_id_new, modes); + } else { + if (dispatch) { + if (wrap_nonclass_global) { + Printf(s, " ZEND_NAMED_FE(%(lower)s,%s,swig_arginfo_%s)\n", Getattr(n, "sym:name"), fname, arginfo_id_new); + } + + if (wrap_nonclass_fake_class) { + (void)fake_class_name(); + Printf(fake_cs_entry, " ZEND_NAMED_ME(%(lower)s,%s,swig_arginfo_%s,ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)\n", Getattr(n, "sym:name"), fname, arginfo_id_new); + } + } else { + if (wrap_nonclass_global) { + Printf(s, " PHP_FE(%s,swig_arginfo_%s)\n", fname, arginfo_id_new); + } + + if (wrap_nonclass_fake_class) { + String *fake_class = fake_class_name(); + Printf(fake_cs_entry, " PHP_ME(%s,%s,swig_arginfo_%s,ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)\n", fake_class, fname, arginfo_id_new); + } + } + } } /* ------------------------------------------------------------ From 216c7f72cf6c7fa27578fc1104cbe8021f8a892e Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Tue, 12 Jul 2022 10:51:32 +1200 Subject: [PATCH 514/662] Revert "Adjust the DOH string hash function" Changing the hash function breaks some testcases. It seems there's a latent bug here (I suspect something somewhere in SWIG depends on the hash iteration order), but I didn't see where and we can't really have CI continuing to fail. See #2303. This reverts commit 5a96a39aa48fe35fa0bd0b92f5fb5615447ea6e8. --- Source/DOH/string.c | 20 ++++++-------------- 1 file changed, 6 insertions(+), 14 deletions(-) diff --git a/Source/DOH/string.c b/Source/DOH/string.c index 8f321508e..543c3e3f8 100644 --- a/Source/DOH/string.c +++ b/Source/DOH/string.c @@ -180,27 +180,19 @@ static int String_hash(DOH *so) { if (s->hashkey >= 0) { return s->hashkey; } else { - /* We use the djb2 hash function: https://theartincode.stanis.me/008-djb2/ - * - * One difference is we use initial seed 0. It seems the usual seed value - * is intended to help spread out hash values, which is beneficial if - * linear probing is used but DOH Hash uses a chain of buckets instead, and - * grouped hash values are probably more cache friendly. In tests using - * 0 seems slightly faster anyway. - */ - const char *c = s->str; + char *c = s->str; unsigned int len = s->len > 50 ? 50 : s->len; unsigned int h = 0; unsigned int mlen = len >> 2; unsigned int i = mlen; for (; i; --i) { - h = h + (h << 5) + *(c++); - h = h + (h << 5) + *(c++); - h = h + (h << 5) + *(c++); - h = h + (h << 5) + *(c++); + h = (h << 5) + *(c++); + h = (h << 5) + *(c++); + h = (h << 5) + *(c++); + h = (h << 5) + *(c++); } for (i = len - (mlen << 2); i; --i) { - h = h + (h << 5) + *(c++); + h = (h << 5) + *(c++); } h &= 0x7fffffff; s->hashkey = (int)h; From 2bba78f7571f414e7d673073e72041b03145ea69 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Tue, 12 Jul 2022 09:41:56 +0100 Subject: [PATCH 515/662] Add std::auto_ptr support for Perl based on std::unique_ptr --- CHANGES.current | 6 ++++++ Examples/test-suite/li_std_auto_ptr.i | 2 +- .../test-suite/perl5/li_std_auto_ptr_runme.pl | 17 +++++++++++++++++ Lib/perl5/std_auto_ptr.i | 19 +++++++++++++++++++ 4 files changed, 43 insertions(+), 1 deletion(-) create mode 100644 Examples/test-suite/perl5/li_std_auto_ptr_runme.pl create mode 100644 Lib/perl5/std_auto_ptr.i diff --git a/CHANGES.current b/CHANGES.current index f5ffd91e2..41824f3fa 100644 --- a/CHANGES.current +++ b/CHANGES.current @@ -7,6 +7,12 @@ the issue number to the end of the URL: https://github.com/swig/swig/issues/ Version 4.1.0 (in progress) =========================== +2022-07-12: wsfulton + [Perl] Add std::auto_ptr support in std_auto_ptr.i library file. + +2022-07-12: erezgeva + [Perl] Add std::unique_ptr support in std_unique_ptr.i library file. + 2022-07-07: olly [xml] #2213 XML has been moved to "Experimental" target language status. It's not in good shape and is likely to be removed unless diff --git a/Examples/test-suite/li_std_auto_ptr.i b/Examples/test-suite/li_std_auto_ptr.i index d83732af0..edfe2ccf5 100644 --- a/Examples/test-suite/li_std_auto_ptr.i +++ b/Examples/test-suite/li_std_auto_ptr.i @@ -12,7 +12,7 @@ #endif %} -#if defined(SWIGCSHARP) || defined(SWIGJAVA) || defined(SWIGPYTHON) || defined(SWIGRUBY) +#if defined(SWIGCSHARP) || defined(SWIGJAVA) || defined(SWIGPYTHON) || defined(SWIGRUBY) || defined(SWIGPERL) %include "std_auto_ptr.i" diff --git a/Examples/test-suite/perl5/li_std_auto_ptr_runme.pl b/Examples/test-suite/perl5/li_std_auto_ptr_runme.pl new file mode 100644 index 000000000..52cb23ac5 --- /dev/null +++ b/Examples/test-suite/perl5/li_std_auto_ptr_runme.pl @@ -0,0 +1,17 @@ +use strict; +use warnings; +use Test::More tests => 6; +BEGIN { use_ok('li_std_auto_ptr') } +require_ok('li_std_auto_ptr'); + +my $k1 = li_std_auto_ptr::makeKlassAutoPtr("first"); +my $k2 = li_std_auto_ptr::makeKlassAutoPtr("second"); +is(li_std_auto_ptr::Klass::getTotal_count, 2, "have 2 pointers"); + +undef $k1; +is(li_std_auto_ptr::Klass::getTotal_count, 1, "left 1 pointer"); + +is($k2->getLabel, "second", "proper label"); + +undef $k2; +is(li_std_auto_ptr::Klass::getTotal_count, 0, "remove all pointers"); diff --git a/Lib/perl5/std_auto_ptr.i b/Lib/perl5/std_auto_ptr.i new file mode 100644 index 000000000..ecaea2b0f --- /dev/null +++ b/Lib/perl5/std_auto_ptr.i @@ -0,0 +1,19 @@ +/* ----------------------------------------------------------------------------- + * std_auto_ptr.i + * + * The typemaps here allow handling functions returning std::auto_ptr<>, + * which is the most common use of this type. If you have functions taking it + * as parameter, these typemaps can't be used for them and you need to do + * something else (e.g. use shared_ptr<> which SWIG supports fully). + * ----------------------------------------------------------------------------- */ + +%define %auto_ptr(TYPE) +%typemap (out) std::auto_ptr< TYPE > %{ + %set_output(SWIG_NewPointerObj($1.release(), $descriptor(TYPE *), SWIG_POINTER_OWN | %newpointer_flags)); +%} +%template() std::auto_ptr< TYPE >; +%enddef + +namespace std { + template class auto_ptr {}; +} From cfc3888cba4375fd3a3a3f97365cafd1c62c9c54 Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Wed, 13 Jul 2022 14:21:02 +1200 Subject: [PATCH 516/662] [php] Emit arginfo after all the code Another step in preparation for a fix for the incompatible overridden method problem discussed in #2151. --- Source/Modules/php.cxx | 194 ++++++++++++++++++++++++----------------- 1 file changed, 115 insertions(+), 79 deletions(-) diff --git a/Source/Modules/php.cxx b/Source/Modules/php.cxx index 69558e2e2..7656e5472 100644 --- a/Source/Modules/php.cxx +++ b/Source/Modules/php.cxx @@ -218,6 +218,15 @@ class PHPTypes { // the dispatch function. If NULL, no parameters are passed by reference. List *byref; + // The id string used in the name of the arginfo for this object. + String *arginfo_id; + + // The feature:php:type value: 0, 1 or -1 for "compatibility". + int php_type_flag; + + // Does the node for this have directorNode set? + bool has_director_node; + // Used to clamp the required number of parameters in the arginfo to be // compatible with any parent class version of the method. int num_required; @@ -261,24 +270,51 @@ class PHPTypes { return result; } + void init(Node *n) { + String *php_type_feature = Getattr(n, "feature:php:type"); + php_type_flag = 0; + if (php_type_feature != NULL) { + if (Equal(php_type_feature, "1")) { + php_type_flag = 1; + } else if (!Equal(php_type_feature, "0")) { + php_type_flag = -1; + } + } + arginfo_id = Copy(Getattr(n, "sym:name")); + has_director_node = (Getattr(n, "directorNode") != NULL); + } + public: - PHPTypes(int num_required_) + PHPTypes(Node *n, int num_required_) : merged_types(NewList()), byref(NULL), - num_required(num_required_) { } + num_required(num_required_) { + init(n); + } - PHPTypes(const PHPTypes *o) + PHPTypes(Node *n, const PHPTypes *o) : merged_types(Copy(o->merged_types)), byref(Copy(o->byref)), - num_required(o->num_required) { } + num_required(o->num_required) { + init(n); + } ~PHPTypes() { Delete(merged_types); Delete(byref); } - void adjust_num_required(int num_required_) { + void adjust(int num_required_, bool php_constructor) { num_required = std::min(num_required, num_required_); + if (php_constructor) { + // Don't add a return type declaration for a PHP __construct method + // (because there it has no return type as far as PHP is concerned). + php_type_flag = 0; + } + } + + String *get_arginfo_id() const { + return arginfo_id; } // key is 0 for return type, or >= 1 for parameters numbered from 1 @@ -297,7 +333,7 @@ public: Setitem(byref, key, ""); // Just needs to be something != None. } - void emit_arginfo(String *fname, Node *n) { + void emit_arginfo() { // We want to only emit each different arginfo once, as that reduces the // size of both the generated source code and the compiled extension // module. The parameters at this level are just named arg1, arg2, etc @@ -308,34 +344,27 @@ public: // We generate the arginfo we want (taking care to normalise, e.g. the // lists of types are unique and in sorted order), then use the // arginfo_used Hash to see if we've already generated it. - - // Don't add a return type declaration for a constructor (because there - // is no return type as far as PHP is concerned). String *out_phptype = NULL; String *out_phpclasses = NewStringEmpty(); - if (!Equal(fname, "__construct")) { - String *php_type_flag = GetFlagAttr(n, "feature:php:type"); - if (Equal(php_type_flag, "1") || - (php_type_flag && !Getattr(n, "directorNode"))) { - // We provide a simple way to generate PHP return type declarations - // except for directed methods. The point of directors is to allow - // subclassing in the target language, and if the wrapped method has - // a return type declaration then an overriding method in user code - // needs to have a compatible declaration. - // - // The upshot of this is that enabling return type declarations for - // existing bindings would break compatibility with user code written - // for an older version. For parameters however the situation is - // different because if the parent class declares types for parameters - // a subclass overriding the function will be compatible whether it - // declares them or not. - // - // directorNode being present seems to indicate if this method or one - // it inherits from is directed, which is what we care about here. - // Using (!is_member_director(n)) would get it wrong for testcase - // director_frob. - out_phptype = get_phptype(0, out_phpclasses); - } + if (php_type_flag > 0 || (php_type_flag && !has_director_node)) { + // We provide a simple way to generate PHP return type declarations + // except for directed methods. The point of directors is to allow + // subclassing in the target language, and if the wrapped method has + // a return type declaration then an overriding method in user code + // needs to have a compatible declaration. + // + // The upshot of this is that enabling return type declarations for + // existing bindings would break compatibility with user code written + // for an older version. For parameters however the situation is + // different because if the parent class declares types for parameters + // a subclass overriding the function will be compatible whether it + // declares them or not. + // + // directorNode being present seems to indicate if this method or one + // it inherits from is directed, which is what we care about here. + // Using (!is_member_director(n)) would get it wrong for testcase + // director_frob. + out_phptype = get_phptype(0, out_phpclasses); } // ### in arginfo_code will be replaced with the id once that is known. @@ -376,15 +405,14 @@ public: } Printf(arginfo_code, "ZEND_END_ARG_INFO()\n"); - String *arginfo_id_new = Getattr(n, "sym:name"); - String *arginfo_id = Getattr(arginfo_used, arginfo_code); - if (arginfo_id) { - Printf(s_arginfo, "#define swig_arginfo_%s swig_arginfo_%s\n", arginfo_id_new, arginfo_id); + String *arginfo_id_same = Getattr(arginfo_used, arginfo_code); + if (arginfo_id_same) { + Printf(s_arginfo, "#define swig_arginfo_%s swig_arginfo_%s\n", arginfo_id, arginfo_id_same); } else { // Not had this arginfo before. - Setattr(arginfo_used, arginfo_code, arginfo_id_new); + Setattr(arginfo_used, arginfo_code, arginfo_id); arginfo_code = Copy(arginfo_code); - Replace(arginfo_code, "###", arginfo_id_new, DOH_REPLACE_FIRST); + Replace(arginfo_code, "###", arginfo_id, DOH_REPLACE_FIRST); Append(s_arginfo, arginfo_code); } Delete(arginfo_code); @@ -394,10 +422,8 @@ public: static PHPTypes *phptypes = NULL; -// Track if the current phptypes is for a non-class function. -static PHPTypes *non_class_phptypes = NULL; - -// class + ":" + method -> PHPTypes* +// php_class + ":" + php_method -> PHPTypes* +// ":" + php_function -> PHPTypes* static Hash *all_phptypes = NewHash(); // php_class_name -> php_parent_class_name @@ -599,6 +625,12 @@ public: /* Emit all of the code */ Language::top(n); + /* Emit all the arginfo */ + for (Iterator ki = First(all_phptypes); ki.key; ki = Next(ki)) { + PHPTypes *p = (PHPTypes*)Data(ki.item); + p->emit_arginfo(); + } + SwigPHP_emit_pointer_type_registrations(); Dump(s_creation, s_header); Delete(s_creation); @@ -808,7 +840,7 @@ public: wrapperType != staticmembervar && !Equal(fname, "__construct")) { // Skip the first entry in the parameter list which is the this pointer. - l = Getattr(l, "tmap:in:next"); + if (l) l = Getattr(l, "tmap:in:next"); // FIXME: does this throw the phptype key value off? } } else { @@ -819,33 +851,31 @@ public: } } - phptypes->adjust_num_required(emit_num_required(l)); + phptypes->adjust(emit_num_required(l), Equal(fname, "__construct")); - phptypes->emit_arginfo(fname, n); - - String *arginfo_id_new = Getattr(n, "sym:name"); + String *arginfo_id = phptypes->get_arginfo_id(); String *s = cs_entry; if (!s) s = s_entry; if (cname && Cmp(Getattr(n, "storage"), "friend") != 0) { - Printf(all_cs_entry, " PHP_ME(%s%s,%s,swig_arginfo_%s,%s)\n", prefix, cname, fname, arginfo_id_new, modes); + Printf(all_cs_entry, " PHP_ME(%s%s,%s,swig_arginfo_%s,%s)\n", prefix, cname, fname, arginfo_id, modes); } else { if (dispatch) { if (wrap_nonclass_global) { - Printf(s, " ZEND_NAMED_FE(%(lower)s,%s,swig_arginfo_%s)\n", Getattr(n, "sym:name"), fname, arginfo_id_new); + Printf(s, " ZEND_NAMED_FE(%(lower)s,%s,swig_arginfo_%s)\n", Getattr(n, "sym:name"), fname, arginfo_id); } if (wrap_nonclass_fake_class) { (void)fake_class_name(); - Printf(fake_cs_entry, " ZEND_NAMED_ME(%(lower)s,%s,swig_arginfo_%s,ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)\n", Getattr(n, "sym:name"), fname, arginfo_id_new); + Printf(fake_cs_entry, " ZEND_NAMED_ME(%(lower)s,%s,swig_arginfo_%s,ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)\n", Getattr(n, "sym:name"), fname, arginfo_id); } } else { if (wrap_nonclass_global) { - Printf(s, " PHP_FE(%s,swig_arginfo_%s)\n", fname, arginfo_id_new); + Printf(s, " PHP_FE(%s,swig_arginfo_%s)\n", fname, arginfo_id); } if (wrap_nonclass_fake_class) { String *fake_class = fake_class_name(); - Printf(fake_cs_entry, " PHP_ME(%s,%s,swig_arginfo_%s,ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)\n", fake_class, fname, arginfo_id_new); + Printf(fake_cs_entry, " PHP_ME(%s,%s,swig_arginfo_%s,ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)\n", fake_class, fname, arginfo_id); } } } @@ -870,8 +900,8 @@ public: bool constructorRenameOverload = false; if (constructor) { - // Renamed constructor - turn into static factory method - if (Cmp(class_name, Getattr(n, "constructorHandler:sym:name")) != 0) { + if (!Equal(class_name, Getattr(n, "constructorHandler:sym:name"))) { + // Renamed constructor - turn into static factory method constructorRenameOverload = true; wname = Copy(Getattr(n, "constructorHandler:sym:name")); } else { @@ -1158,7 +1188,12 @@ public: } if (constructor) { - wname = NewString("__construct"); + if (!Equal(class_name, Getattr(n, "constructorHandler:sym:name"))) { + // Renamed constructor - turn into static factory method + wname = Copy(Getattr(n, "constructorHandler:sym:name")); + } else { + wname = NewString("__construct"); + } } else if (wrapperType == membervar) { wname = Copy(Getattr(n, "membervariableHandler:sym:name")); if (is_setter_method(n)) { @@ -1210,34 +1245,35 @@ public: if (!Getattr(n, "sym:previousSibling") && !static_getter) { // First function of an overloaded group or a function which isn't part // of a group so reset the phptype information. - if (non_class_phptypes) { - delete non_class_phptypes; - non_class_phptypes = NULL; - } phptypes = NULL; - if (class_name) { - // See if there's a parent class which implements this method, and if - // so copy the PHPTypes of that method as a starting point as we need - // to be compatible with it (whether it is virtual or not). - String *parent = class_name; - while ((parent = Getattr(php_parent_class, parent)) != NULL) { - String *key = NewStringf("%s:%s", parent, wname); - PHPTypes *p = (PHPTypes*)GetVoid(all_phptypes, key); - Delete(key); - if (p) { - phptypes = new PHPTypes(p); - break; + String *key = NewStringf("%s:%s", class_name, wname); + PHPTypes *p = (PHPTypes*)GetVoid(all_phptypes, key); + if (p) { + // We already have an entry - this happens when overloads are created + // by %extend, for instance. + phptypes = p; + Delete(key); + } else { + if (class_name) { + // See if there's a parent class which implements this method, and if + // so copy the PHPTypes of that method as a starting point as we need + // to be compatible with it (whether it is virtual or not). + String *parent = class_name; + while ((parent = Getattr(php_parent_class, parent)) != NULL) { + String *k = NewStringf("%s:%s", parent, wname); + PHPTypes *p = (PHPTypes*)GetVoid(all_phptypes, k); + Delete(key); + if (p) { + phptypes = new PHPTypes(n, p); + break; + } } } - } - if (!phptypes) { - phptypes = new PHPTypes(emit_num_required(l)); - } - if (class_name) { - SetVoid(all_phptypes, NewStringf("%s:%s", class_name, wname), phptypes); - } else { - non_class_phptypes = phptypes; + if (!phptypes) { + phptypes = new PHPTypes(n, emit_num_required(l)); + } + SetVoid(all_phptypes, key, phptypes); } } From 732af1d7b80aed9dddbab8c8c42bfa1f94c45fb6 Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Wed, 13 Jul 2022 15:15:56 +1200 Subject: [PATCH 517/662] Tweak testcase comments --- Examples/test-suite/equality.i | 3 +-- Examples/test-suite/operator_overload.i | 4 ++-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/Examples/test-suite/equality.i b/Examples/test-suite/equality.i index cdabc4892..344cb9f8c 100644 --- a/Examples/test-suite/equality.i +++ b/Examples/test-suite/equality.i @@ -57,8 +57,7 @@ inline bool operator==( const EqualOpWrong& first, const EqualOpWrong& second ) %} /* - in order to wrapper this correctly - we need to extend the class + in order to wrap this correctly we need to extend the class to make the friends & non members part of the class */ %extend EqualOpDefined { diff --git a/Examples/test-suite/operator_overload.i b/Examples/test-suite/operator_overload.i index af884e5b4..ce3454fd9 100644 --- a/Examples/test-suite/operator_overload.i +++ b/Examples/test-suite/operator_overload.i @@ -69,6 +69,7 @@ see bottom for a set of possible tests #endif #ifdef SWIGPHP +// "And" and "Or" can't be used as function names in PHP. %rename(AndOperator) operator &&; %rename(OrOperator) operator ||; #endif @@ -174,8 +175,7 @@ inline bool operator>=(const Op& a,const Op& b){return a.i>=b.i;} Op operator-(const Op& a,const Op& b){return Op(a.i-b.i);} %} -// in order to wrapper this correctly -// we need to extend the class +// in order to wrap this correctly we need to extend the class // to make the friends & non members part of the class %extend Op{ Op operator &&(const Op& b){return Op($self->i&&b.i);} From 6c083b208c172725a118022407bda3b3e8c5654a Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Wed, 13 Jul 2022 15:18:39 +1200 Subject: [PATCH 518/662] [php] Reenable 3 testcases which now pass See #2151 --- Examples/test-suite/php/Makefile.in | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/Examples/test-suite/php/Makefile.in b/Examples/test-suite/php/Makefile.in index ae3dd0aa1..9e6aca3b3 100644 --- a/Examples/test-suite/php/Makefile.in +++ b/Examples/test-suite/php/Makefile.in @@ -28,10 +28,7 @@ C_TEST_CASES += \ # These fail with PHP8 currently. Aiming to fix before 4.1 release. See #2151. FAILING_CPP_TESTS = \ - director_redefined \ - director_using_member_scopes \ - using_composition \ - using_extend \ + director_redefined include $(srcdir)/../common.mk From 1f925867f4ae3f4b97184066526ffec6d470b346 Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Wed, 13 Jul 2022 15:33:41 +1200 Subject: [PATCH 519/662] [ci] Drop duplicate octave build This was created by fc6269a3cad26acbb62f7eff8b3a218433fc5554 which converted the non-functioning Octave 6.4 into a duplicate of the other Octave build instead of dropping it completely. --- .github/workflows/ci.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 60791155c..ac63a863e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -95,8 +95,6 @@ jobs: VER: '5.3' - SWIGLANG: octave CPPSTD: c++11 - - SWIGLANG: octave - CPPSTD: c++11 - SWIGLANG: perl5 - SWIGLANG: php VER: '7.0' From 64fa88c0eb03ac37983d93a024ff375ff268361d Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Wed, 13 Jul 2022 16:01:59 +1200 Subject: [PATCH 520/662] [php] Omit incompatible return type declaraction Under %feature("php:type", "compat") we don't generate return type declaration for virtual methods if directors are enabled for that class. However if a base class of the class has a method of the same name which isn't directed this was still getting a return type declaration which caused PHP to give an error when it tried to load the module. Now we detect this situation and suppress the base class method's return type declaration too. Re-enable testcase director_redefined which now works again (it was failing under PHP8 due to this issue). See #2151 --- Examples/test-suite/php/Makefile.in | 4 ---- Source/Modules/php.cxx | 33 ++++++++++++++++++++--------- 2 files changed, 23 insertions(+), 14 deletions(-) diff --git a/Examples/test-suite/php/Makefile.in b/Examples/test-suite/php/Makefile.in index 9e6aca3b3..6a2a4590b 100644 --- a/Examples/test-suite/php/Makefile.in +++ b/Examples/test-suite/php/Makefile.in @@ -26,10 +26,6 @@ C_TEST_CASES += \ li_cdata_carrays \ multivalue \ -# These fail with PHP8 currently. Aiming to fix before 4.1 release. See #2151. -FAILING_CPP_TESTS = \ - director_redefined - include $(srcdir)/../common.mk # Overridden variables here diff --git a/Source/Modules/php.cxx b/Source/Modules/php.cxx index 7656e5472..72f9baa1b 100644 --- a/Source/Modules/php.cxx +++ b/Source/Modules/php.cxx @@ -205,6 +205,17 @@ static Hash *create_php_type_flags() { static Hash *php_type_flags = create_php_type_flags(); +// php_class + ":" + php_method -> PHPTypes* +// ":" + php_function -> PHPTypes* +static Hash *all_phptypes = NewHash(); + +// php_class_name -> php_parent_class_name +static Hash *php_parent_class = NewHash(); + +// Track if a method is directed in a descendent class. +// php_class + ":" + php_method -> boolean (using SetFlag()/GetFlag()). +static Hash *has_directed_descendent = NewHash(); + // Class encapsulating the machinery to add PHP type declarations. class PHPTypes { // List with an entry for each parameter and one for the return type. @@ -333,7 +344,7 @@ public: Setitem(byref, key, ""); // Just needs to be something != None. } - void emit_arginfo() { + void emit_arginfo(String *key) { // We want to only emit each different arginfo once, as that reduces the // size of both the generated source code and the compiled extension // module. The parameters at this level are just named arg1, arg2, etc @@ -346,7 +357,9 @@ public: // arginfo_used Hash to see if we've already generated it. String *out_phptype = NULL; String *out_phpclasses = NewStringEmpty(); - if (php_type_flag > 0 || (php_type_flag && !has_director_node)) { + if (php_type_flag && + (php_type_flag > 0 || !has_director_node) && + !GetFlag(has_directed_descendent, key)) { // We provide a simple way to generate PHP return type declarations // except for directed methods. The point of directors is to allow // subclassing in the target language, and if the wrapped method has @@ -422,13 +435,6 @@ public: static PHPTypes *phptypes = NULL; -// php_class + ":" + php_method -> PHPTypes* -// ":" + php_function -> PHPTypes* -static Hash *all_phptypes = NewHash(); - -// php_class_name -> php_parent_class_name -static Hash *php_parent_class = NewHash(); - class PHP : public Language { public: PHP() { @@ -628,7 +634,7 @@ public: /* Emit all the arginfo */ for (Iterator ki = First(all_phptypes); ki.key; ki = Next(ki)) { PHPTypes *p = (PHPTypes*)Data(ki.item); - p->emit_arginfo(); + p->emit_arginfo(ki.key); } SwigPHP_emit_pointer_type_registrations(); @@ -1421,6 +1427,13 @@ public: Append(f->code, "director = SWIG_DIRECTOR_CAST(arg1);\n"); Wrapper_add_local(f, "upcall", "bool upcall = false"); Printf(f->code, "upcall = (director && (director->swig_get_self()==Z_OBJ_P(ZEND_THIS)));\n"); + + String *parent = class_name; + while ((parent = Getattr(php_parent_class, parent)) != NULL) { + // Mark this method name as having a directed descendent for all + // classes we're derived from. + SetFlag(has_directed_descendent, NewStringf("%s:%s", parent, wname)); + } } Swig_director_emit_dynamic_cast(n, f); From 6b361bf05004181a118235df37c6c9bac099022a Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Fri, 8 Jul 2022 18:04:20 +0100 Subject: [PATCH 521/662] Add Java support for std::unique for input parameters. This works by transferring ownership of the underlying C++ memory from the target language proxy class to an instance of the unique_ptr which is passed to the wrapped function via std::move. The proxy class has a new swigRelease() method which sets the underlying C++ pointer for the proxy class to null, so working in much the same way as std::unique_ptr::release(). Any attempt at using the proxy class will be the same as if the delete() function has been called on the proxy class. That is, using a C++ null pointer, when a non-null pointer is usually expected. This commit relies on the previous commit that uses std::move on the temporary variable used for the wrapped function's input parameter as std::unique_ptr is not copyable, it has move-only semantics. --- Examples/test-suite/cpp11_std_unique_ptr.i | 21 +++++++++++- .../java/cpp11_std_unique_ptr_runme.java | 34 +++++++++++++++++++ Examples/test-suite/java_throws.i | 15 ++++++++ Lib/java/std_unique_ptr.i | 23 +++++++++++++ Source/Modules/java.cxx | 2 ++ 5 files changed, 94 insertions(+), 1 deletion(-) diff --git a/Examples/test-suite/cpp11_std_unique_ptr.i b/Examples/test-suite/cpp11_std_unique_ptr.i index 9bd65b97f..fd0e8e942 100644 --- a/Examples/test-suite/cpp11_std_unique_ptr.i +++ b/Examples/test-suite/cpp11_std_unique_ptr.i @@ -2,6 +2,7 @@ #if defined(SWIGCSHARP) || defined(SWIGJAVA) || defined(SWIGPYTHON) || defined(SWIGRUBY) || defined(SWIGPERL) +%include "std_string.i" %include "std_unique_ptr.i" %unique_ptr(Klass) @@ -22,7 +23,7 @@ public: const char* getLabel() const { return m_label.c_str(); } - ~Klass() + virtual ~Klass() { SwigExamples::Lock lock(critical_section); total_count--; @@ -44,6 +45,24 @@ int Klass::total_count = 0; %inline %{ +// Virtual inheritance used as this usually results in different values for Klass* and KlassInheritance* +// for testing class inheritance and unique_ptr +struct KlassInheritance : virtual Klass { + KlassInheritance(const char* label) : Klass(label) { + // std::cout << "ptrs.... " << std::hex << (Klass*)this << " " << (KlassInheritance*)this << std::endl; + } +}; + +#if defined(SWIGJAVA) +std::string takeKlassUniquePtr(std::unique_ptr k) { + return std::string(k->getLabel()); +} +#endif + +bool is_nullptr(Klass *p) { + return p == nullptr; +} + std::unique_ptr makeKlassUniquePtr(const char* label) { return std::unique_ptr(new Klass(label)); } 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 a734b0e5e..3f2b15f44 100644 --- a/Examples/test-suite/java/cpp11_std_unique_ptr_runme.java +++ b/Examples/test-suite/java/cpp11_std_unique_ptr_runme.java @@ -20,8 +20,42 @@ public class cpp11_std_unique_ptr_runme { } } + private static void checkCount(int expected_count) { + int actual_count = Klass.getTotal_count(); + if (actual_count != expected_count) + throw new RuntimeException("Counts incorrect, expected:" + expected_count + " actual:" + actual_count); + } + public static void main(String argv[]) throws Throwable { + // unique_ptr as input + { + Klass kin = new Klass("KlassInput"); + checkCount(1); + String s = cpp11_std_unique_ptr.takeKlassUniquePtr(kin); + checkCount(0); + if (!s.equals("KlassInput")) + throw new RuntimeException("Incorrect string: " + s); + if (!cpp11_std_unique_ptr.is_nullptr(kin)) + throw new RuntimeException("is_nullptr failed"); + kin.delete(); // Should not fail, even though already deleted + checkCount(0); + } + + { + KlassInheritance kini = new KlassInheritance("KlassInheritanceInput"); + checkCount(1); + String s = cpp11_std_unique_ptr.takeKlassUniquePtr(kini); + checkCount(0); + if (!s.equals("KlassInheritanceInput")) + throw new RuntimeException("Incorrect string: " + s); + if (!cpp11_std_unique_ptr.is_nullptr(kini)) + throw new RuntimeException("is_nullptr failed"); + kini.delete(); // Should not fail, even though already deleted + checkCount(0); + } + + // unique_ptr as output Klass k1 = cpp11_std_unique_ptr.makeKlassUniquePtr("first"); if (!k1.getLabel().equals("first")) throw new RuntimeException("wrong object label"); diff --git a/Examples/test-suite/java_throws.i b/Examples/test-suite/java_throws.i index 6cd47b448..940f2c192 100644 --- a/Examples/test-suite/java_throws.i +++ b/Examples/test-suite/java_throws.i @@ -192,6 +192,21 @@ try { } } %} +%typemap(javarelease) SWIGTYPE %{ + protected static long swigRelease($javaclassname obj) { + long ptr = 0; + if (obj != null) { + ptr = obj.swigCPtr; + obj.swigCMemOwn = false; + try { + obj.delete(); + } catch (MyException e) { + throw new RuntimeException(e); + } + } + return ptr; + } +%} %inline %{ struct NoExceptTest { diff --git a/Lib/java/std_unique_ptr.i b/Lib/java/std_unique_ptr.i index 665d913ae..7a647f616 100644 --- a/Lib/java/std_unique_ptr.i +++ b/Lib/java/std_unique_ptr.i @@ -8,19 +8,42 @@ * ----------------------------------------------------------------------------- */ %define %unique_ptr(TYPE) + %typemap (jni) std::unique_ptr< TYPE > "jlong" %typemap (jtype) std::unique_ptr< TYPE > "long" %typemap (jstype) std::unique_ptr< TYPE > "$typemap(jstype, TYPE)" +%typemap(in) std::unique_ptr< TYPE > (TYPE *unique_temp) +%{ unique_temp = *(TYPE **)&$input; + $1.reset(unique_temp); %} + +%typemap(javain) std::unique_ptr< TYPE > "$typemap(jstype, TYPE).swigRelease($javainput)" + %typemap (out) std::unique_ptr< TYPE > %{ jlong lpp = 0; *(TYPE **) &lpp = $1.release(); $result = lpp; %} + %typemap(javaout) std::unique_ptr< TYPE > { long cPtr = $jnicall; return (cPtr == 0) ? null : new $typemap(jstype, TYPE)(cPtr, true); } + +%typemap(javarelease) TYPE %{ + protected static long swigRelease($javaclassname obj) { + long ptr = 0; + if (obj != null) { + if (!obj.swigCMemOwn) + throw new RuntimeException("Cannot release ownership as memory is not owned"); + ptr = obj.swigCPtr; + obj.swigCMemOwn = false; + obj.delete(); + } + return ptr; + } +%} + %template() std::unique_ptr< TYPE >; %enddef diff --git a/Source/Modules/java.cxx b/Source/Modules/java.cxx index ea7e4607a..cf39fc80b 100644 --- a/Source/Modules/java.cxx +++ b/Source/Modules/java.cxx @@ -2025,6 +2025,8 @@ public: typemapLookup(n, "javabody", typemap_lookup_type, WARN_JAVA_TYPEMAP_JAVABODY_UNDEF), // main body of class NIL); + Printv(proxy_class_def, typemapLookup(n, "javarelease", typemap_lookup_type, WARN_NONE), NIL); + // C++ destructor is wrapped by the delete method // Note that the method name is specified in a typemap attribute called methodname String *destruct = NewString(""); From bf761998ed481821997e7c65f5d3e6acdf2eaf03 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Sun, 10 Jul 2022 19:08:32 +0100 Subject: [PATCH 522/662] SWIGTYPE && input typemaps now assume object has been moved Change these typemaps to assume that after a function call, the parameter has been moved. The parameter's proxy class that owns the C++ object thus has the underlying pointer set to null so the object cannot be used again and the object is deleted. Scrap new javarelease typemap and move contents into javabody typemap. --- Examples/test-suite/common.mk | 1 + .../cpp11_rvalue_reference_move_input.i | 41 +++++++++++++ ...p11_rvalue_reference_move_input_runme.java | 60 +++++++++++++++++++ Examples/test-suite/java_throws.i | 18 +++++- Lib/java/java.swg | 32 +++++++++- Lib/java/std_unique_ptr.i | 14 ----- Source/Modules/java.cxx | 2 - 7 files changed, 150 insertions(+), 18 deletions(-) create mode 100644 Examples/test-suite/cpp11_rvalue_reference_move_input.i create mode 100644 Examples/test-suite/java/cpp11_rvalue_reference_move_input_runme.java diff --git a/Examples/test-suite/common.mk b/Examples/test-suite/common.mk index c654807d7..b4633e3f6 100644 --- a/Examples/test-suite/common.mk +++ b/Examples/test-suite/common.mk @@ -610,6 +610,7 @@ CPP11_TEST_CASES += \ cpp11_rvalue_reference \ cpp11_rvalue_reference2 \ cpp11_rvalue_reference3 \ + cpp11_rvalue_reference_move_input \ cpp11_sizeof_object \ cpp11_static_assert \ cpp11_std_array \ diff --git a/Examples/test-suite/cpp11_rvalue_reference_move_input.i b/Examples/test-suite/cpp11_rvalue_reference_move_input.i new file mode 100644 index 000000000..03abd7322 --- /dev/null +++ b/Examples/test-suite/cpp11_rvalue_reference_move_input.i @@ -0,0 +1,41 @@ +%module cpp11_rvalue_reference_move_input + +// Testcase for testing rvalue reference input typemaps which assume the object is moved during a function call + +#if defined(SWIGD) +%rename(trace) debug; +#endif + +%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 debug = false; + +class MovableCopyable { +public: + MovableCopyable(int i = 0) { if (debug) cout << "MovableCopyable(" << i << ")" << " " << this << endl; Counter::normal_constructor++; } + + MovableCopyable(const MovableCopyable &other) { if (debug) cout << "MovableCopyable(const MovableCopyable &)" << " " << this << " " << &other << endl; Counter::copy_constructor++;} + MovableCopyable & operator=(const MovableCopyable &other) { if (debug) cout << "operator=(const MovableCopyable &)" << " " << this << " " << &other << endl; Counter::copy_assignment++; return *this; } + + MovableCopyable(MovableCopyable &&other) noexcept { if (debug) cout << "MovableCopyable(MovableCopyable &&)" << " " << this << endl; Counter::move_constructor++; } + MovableCopyable & operator=(MovableCopyable &&other) noexcept { if (debug) cout << "operator=(MovableCopyable &&)" << " " << this << endl; Counter::move_assignment++; return *this; } + ~MovableCopyable() { if (debug) 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/java/cpp11_rvalue_reference_move_input_runme.java b/Examples/test-suite/java/cpp11_rvalue_reference_move_input_runme.java new file mode 100644 index 000000000..dfc09f217 --- /dev/null +++ b/Examples/test-suite/java/cpp11_rvalue_reference_move_input_runme.java @@ -0,0 +1,60 @@ + +import cpp11_rvalue_reference_move_input.*; + +public class cpp11_rvalue_reference_move_input_runme { + + static { + try { + System.loadLibrary("cpp11_rvalue_reference_move_input"); + } 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); + } + } + + public static void main(String argv[]) { + + { + 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 RuntimeException("is_nullptr failed"); + mo.delete(); + 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 RuntimeException("is_nullptr failed"); + 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 = 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 RuntimeException("is_nullptr failed"); + mo222.delete(); + Counter.check_counts(2, 0, 0, 0, 1, 1); + mo111.delete(); + Counter.check_counts(2, 0, 0, 0, 1, 2); + } + } +} diff --git a/Examples/test-suite/java_throws.i b/Examples/test-suite/java_throws.i index 940f2c192..7c3b6f328 100644 --- a/Examples/test-suite/java_throws.i +++ b/Examples/test-suite/java_throws.i @@ -192,10 +192,25 @@ try { } } %} -%typemap(javarelease) SWIGTYPE %{ + +%typemap(javabody) SWIGTYPE %{ + private transient long swigCPtr; + protected transient boolean swigCMemOwn; + + protected $javaclassname(long cPtr, boolean cMemoryOwn) { + swigCMemOwn = cMemoryOwn; + swigCPtr = cPtr; + } + + protected static long getCPtr($javaclassname obj) { + return (obj == null) ? 0 : obj.swigCPtr; + } + protected static long swigRelease($javaclassname obj) { long ptr = 0; if (obj != null) { + if (!obj.swigCMemOwn) + throw new RuntimeException("Cannot release ownership as memory is not owned"); ptr = obj.swigCPtr; obj.swigCMemOwn = false; try { @@ -208,6 +223,7 @@ try { } %} + %inline %{ struct NoExceptTest { unsigned int noExceptionPlease() { return 123; } diff --git a/Lib/java/java.swg b/Lib/java/java.swg index 23744aeb3..19198b7b4 100644 --- a/Lib/java/java.swg +++ b/Lib/java/java.swg @@ -700,6 +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(out) SWIGTYPE * %{ *($&1_ltype)&$result = $1; %} %typemap(out, fragment="SWIG_PackData", noblock=1) SWIGTYPE (CLASS::*) { @@ -1101,7 +1102,8 @@ Swig::LocalRefGuard $1_refguard(jenv, $input); } jobjectArray "$javainput" %typemap(javain) SWIGTYPE "$&javaclassname.getCPtr($javainput)" -%typemap(javain) SWIGTYPE *, SWIGTYPE &, SWIGTYPE &&, SWIGTYPE [] "$javaclassname.getCPtr($javainput)" +%typemap(javain) SWIGTYPE *, SWIGTYPE &, SWIGTYPE [] "$javaclassname.getCPtr($javainput)" +%typemap(javain) SWIGTYPE && "$javaclassname.swigRelease($javainput)" %typemap(javain) SWIGTYPE (CLASS::*) "$javaclassname.getCMemberPtr($javainput)" /* The javaout typemap is used for converting function return types from the return type @@ -1216,6 +1218,18 @@ Swig::LocalRefGuard $1_refguard(jenv, $input); } CPTR_VISIBILITY static long getCPtr($javaclassname obj) { return (obj == null) ? 0 : obj.swigCPtr; } + + CPTR_VISIBILITY static long swigRelease($javaclassname obj) { + long ptr = 0; + if (obj != null) { + if (!obj.swigCMemOwn) + throw new RuntimeException("Cannot release ownership as memory is not owned"); + ptr = obj.swigCPtr; + obj.swigCMemOwn = false; + obj.delete(); + } + return ptr; + } %} // Derived proxy classes @@ -1230,6 +1244,18 @@ Swig::LocalRefGuard $1_refguard(jenv, $input); } CPTR_VISIBILITY static long getCPtr($javaclassname obj) { return (obj == null) ? 0 : obj.swigCPtr; } + + CPTR_VISIBILITY static long swigRelease($javaclassname obj) { + long ptr = 0; + if (obj != null) { + if (!obj.swigCMemOwn) + throw new RuntimeException("Cannot release ownership as memory is not owned"); + ptr = obj.swigCPtr; + obj.swigCMemOwn = false; + obj.delete(); + } + return ptr; + } %} %enddef @@ -1249,6 +1275,10 @@ Swig::LocalRefGuard $1_refguard(jenv, $input); } CPTR_VISIBILITY static long getCPtr($javaclassname obj) { return (obj == null) ? 0 : obj.swigCPtr; } + + CPTR_VISIBILITY static long swigRelease($javaclassname obj) { + return (obj == null) ? 0 : obj.swigCPtr; + } %} %typemap(javabody) TYPE (CLASS::*) %{ diff --git a/Lib/java/std_unique_ptr.i b/Lib/java/std_unique_ptr.i index 7a647f616..5f4a0c5a2 100644 --- a/Lib/java/std_unique_ptr.i +++ b/Lib/java/std_unique_ptr.i @@ -30,20 +30,6 @@ return (cPtr == 0) ? null : new $typemap(jstype, TYPE)(cPtr, true); } -%typemap(javarelease) TYPE %{ - protected static long swigRelease($javaclassname obj) { - long ptr = 0; - if (obj != null) { - if (!obj.swigCMemOwn) - throw new RuntimeException("Cannot release ownership as memory is not owned"); - ptr = obj.swigCPtr; - obj.swigCMemOwn = false; - obj.delete(); - } - return ptr; - } -%} - %template() std::unique_ptr< TYPE >; %enddef diff --git a/Source/Modules/java.cxx b/Source/Modules/java.cxx index cf39fc80b..ea7e4607a 100644 --- a/Source/Modules/java.cxx +++ b/Source/Modules/java.cxx @@ -2025,8 +2025,6 @@ public: typemapLookup(n, "javabody", typemap_lookup_type, WARN_JAVA_TYPEMAP_JAVABODY_UNDEF), // main body of class NIL); - Printv(proxy_class_def, typemapLookup(n, "javarelease", typemap_lookup_type, WARN_NONE), NIL); - // C++ destructor is wrapped by the delete method // Note that the method name is specified in a typemap attribute called methodname String *destruct = NewString(""); From 1bf15210ef5f86e588cc8a08ff5b1206637feb03 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Sat, 16 Jul 2022 23:02:21 +0100 Subject: [PATCH 523/662] Java unique_ptr enhance test for double release --- .../java/cpp11_std_unique_ptr_runme.java | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) 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 3f2b15f44..4ac72d720 100644 --- a/Examples/test-suite/java/cpp11_std_unique_ptr_runme.java +++ b/Examples/test-suite/java/cpp11_std_unique_ptr_runme.java @@ -42,6 +42,27 @@ public class cpp11_std_unique_ptr_runme { checkCount(0); } + { + Klass kin = new Klass("KlassInput"); + checkCount(1); + String s = cpp11_std_unique_ptr.takeKlassUniquePtr(kin); + checkCount(0); + if (!s.equals("KlassInput")) + throw new RuntimeException("Incorrect string: " + s); + if (!cpp11_std_unique_ptr.is_nullptr(kin)) + throw new RuntimeException("is_nullptr failed"); + boolean exception_thrown = false; + try { + cpp11_std_unique_ptr.takeKlassUniquePtr(kin); + } catch (RuntimeException e) { + exception_thrown = true; + } + if (!exception_thrown) + throw new RuntimeException("double usage of takeKlassUniquePtr should have been an error"); + kin.delete(); // Should not fail, even though already deleted + checkCount(0); + } + { KlassInheritance kini = new KlassInheritance("KlassInheritanceInput"); checkCount(1); From 8bd9eb3f16621ae900b974845806b12262884466 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Sun, 17 Jul 2022 12:46:16 +0100 Subject: [PATCH 524/662] Java unique_ptr test ownership enhancement to test Make sure the object is owned before releasing ownership and passing ownership to unique_ptr instance. --- Examples/test-suite/cpp11_std_unique_ptr.i | 4 ++++ .../java/cpp11_std_unique_ptr_runme.java | 15 +++++++++++++++ 2 files changed, 19 insertions(+) diff --git a/Examples/test-suite/cpp11_std_unique_ptr.i b/Examples/test-suite/cpp11_std_unique_ptr.i index fd0e8e942..c96047f64 100644 --- a/Examples/test-suite/cpp11_std_unique_ptr.i +++ b/Examples/test-suite/cpp11_std_unique_ptr.i @@ -63,6 +63,10 @@ bool is_nullptr(Klass *p) { return p == nullptr; } +Klass *get_not_owned_ptr(Klass *p) { + return p; +} + std::unique_ptr makeKlassUniquePtr(const char* label) { return std::unique_ptr(new Klass(label)); } 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 4ac72d720..14c117206 100644 --- a/Examples/test-suite/java/cpp11_std_unique_ptr_runme.java +++ b/Examples/test-suite/java/cpp11_std_unique_ptr_runme.java @@ -63,6 +63,21 @@ public class cpp11_std_unique_ptr_runme { checkCount(0); } + { + Klass kin = new Klass("KlassInput"); + boolean exception_thrown = false; + try { + Klass notowned = cpp11_std_unique_ptr.get_not_owned_ptr(kin); + cpp11_std_unique_ptr.takeKlassUniquePtr(notowned); + } catch (RuntimeException e) { + exception_thrown = true; + } + if (!exception_thrown) + throw new RuntimeException("Should have thrown 'Cannot release ownership as memory is not owned' error"); + kin.delete(); + checkCount(0); + } + { KlassInheritance kini = new KlassInheritance("KlassInheritanceInput"); checkCount(1); From c737bd57131c02eed9573d13f30662397890ba0b Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Fri, 15 Jul 2022 17:41:58 +0100 Subject: [PATCH 525/662] Add C# support std::unique_ptr inputs Based on Java implementation. --- Examples/test-suite/cpp11_std_unique_ptr.i | 2 +- .../csharp/cpp11_std_unique_ptr_runme.cs | 63 +++++++++++++++++++ Lib/csharp/csharp.swg | 30 +++++++++ Lib/csharp/std_auto_ptr.i | 2 +- Lib/csharp/std_unique_ptr.i | 10 ++- 5 files changed, 103 insertions(+), 4 deletions(-) diff --git a/Examples/test-suite/cpp11_std_unique_ptr.i b/Examples/test-suite/cpp11_std_unique_ptr.i index c96047f64..5ef49456c 100644 --- a/Examples/test-suite/cpp11_std_unique_ptr.i +++ b/Examples/test-suite/cpp11_std_unique_ptr.i @@ -53,7 +53,7 @@ struct KlassInheritance : virtual Klass { } }; -#if defined(SWIGJAVA) +#if defined(SWIGJAVA) || defined (SWIGCSHARP) std::string takeKlassUniquePtr(std::unique_ptr k) { return std::string(k->getLabel()); } 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 db5c8cff0..5b730aa05 100644 --- a/Examples/test-suite/csharp/cpp11_std_unique_ptr_runme.cs +++ b/Examples/test-suite/csharp/cpp11_std_unique_ptr_runme.cs @@ -9,8 +9,71 @@ public class cpp11_std_unique_ptr_runme { System.Threading.Thread.Sleep(10); } + private static void checkCount(int expected_count) + { + int actual_count = Klass.getTotal_count(); + if (actual_count != expected_count) + throw new ApplicationException("Counts incorrect, expected:" + expected_count + " actual:" + actual_count); + } + public static void Main() { + // unique_ptr as input + using (Klass kin = new Klass("KlassInput")) { + checkCount(1); + string s = cpp11_std_unique_ptr.takeKlassUniquePtr(kin); + checkCount(0); + if (s != "KlassInput") + throw new ApplicationException("Incorrect string: " + s); + if (!cpp11_std_unique_ptr.is_nullptr(kin)) + throw new ApplicationException("is_nullptr failed"); + } // Dispose should not fail, even though already deleted + checkCount(0); + + using (Klass kin = new Klass("KlassInput")) { + checkCount(1); + string s = cpp11_std_unique_ptr.takeKlassUniquePtr(kin); + checkCount(0); + if (s != "KlassInput") + throw new ApplicationException("Incorrect string: " + s); + if (!cpp11_std_unique_ptr.is_nullptr(kin)) + throw new ApplicationException("is_nullptr failed"); + bool exception_thrown = false; + try { + cpp11_std_unique_ptr.takeKlassUniquePtr(kin); + } catch (ApplicationException) { + exception_thrown = true; + } + if (!exception_thrown) + throw new ApplicationException("double usage of takeKlassUniquePtr should have been an error"); + } // Dispose should not fail, even though already deleted + checkCount(0); + + using (Klass kin = new Klass("KlassInput")) { + bool exception_thrown = false; + try { + Klass notowned = cpp11_std_unique_ptr.get_not_owned_ptr(kin); + cpp11_std_unique_ptr.takeKlassUniquePtr(notowned); + } catch (ApplicationException) { + exception_thrown = true; + } + if (!exception_thrown) + throw new ApplicationException("Should have thrown 'Cannot release ownership as memory is not owned' error"); + } + checkCount(0); + + using (KlassInheritance kini = new KlassInheritance("KlassInheritanceInput")) { + checkCount(1); + string s = cpp11_std_unique_ptr.takeKlassUniquePtr(kini); + checkCount(0); + if (s != "KlassInheritanceInput") + throw new ApplicationException("Incorrect string: " + s); + if (!cpp11_std_unique_ptr.is_nullptr(kini)) + throw new ApplicationException("is_nullptr failed"); + } // Dispose should not fail, even though already deleted + checkCount(0); + + // unique_ptr as output Klass k1 = cpp11_std_unique_ptr.makeKlassUniquePtr("first"); if (k1.getLabel() != "first") throw new Exception("wrong object label"); diff --git a/Lib/csharp/csharp.swg b/Lib/csharp/csharp.swg index 94e0458a6..60ab388f3 100644 --- a/Lib/csharp/csharp.swg +++ b/Lib/csharp/csharp.swg @@ -913,6 +913,19 @@ SWIGINTERN const char * SWIG_UnpackData(const char *c, void *ptr, size_t sz) { CPTR_VISIBILITY static global::System.Runtime.InteropServices.HandleRef getCPtr($csclassname obj) { return (obj == null) ? new global::System.Runtime.InteropServices.HandleRef(null, global::System.IntPtr.Zero) : obj.swigCPtr; } + + CPTR_VISIBILITY static global::System.Runtime.InteropServices.HandleRef swigRelease($csclassname obj) { + if (obj != null) { + if (!obj.swigCMemOwn) + throw new global::System.ApplicationException("Cannot release ownership as memory is not owned"); + global::System.Runtime.InteropServices.HandleRef ptr = obj.swigCPtr; + obj.swigCMemOwn = false; + obj.Dispose(); + return ptr; + } else { + return new global::System.Runtime.InteropServices.HandleRef(null, global::System.IntPtr.Zero); + } + } %} // Derived proxy classes @@ -926,6 +939,19 @@ SWIGINTERN const char * SWIG_UnpackData(const char *c, void *ptr, size_t sz) { CPTR_VISIBILITY static global::System.Runtime.InteropServices.HandleRef getCPtr($csclassname obj) { return (obj == null) ? new global::System.Runtime.InteropServices.HandleRef(null, global::System.IntPtr.Zero) : obj.swigCPtr; } + + CPTR_VISIBILITY static global::System.Runtime.InteropServices.HandleRef swigRelease($csclassname obj) { + if (obj != null) { + if (!obj.swigCMemOwn) + throw new global::System.ApplicationException("Cannot release ownership as memory is not owned"); + global::System.Runtime.InteropServices.HandleRef ptr = obj.swigCPtr; + obj.swigCMemOwn = false; + obj.Dispose(); + return ptr; + } else { + return new global::System.Runtime.InteropServices.HandleRef(null, global::System.IntPtr.Zero); + } + } %} %enddef @@ -945,6 +971,10 @@ SWIGINTERN const char * SWIG_UnpackData(const char *c, void *ptr, size_t sz) { CPTR_VISIBILITY static global::System.Runtime.InteropServices.HandleRef getCPtr($csclassname obj) { return (obj == null) ? new global::System.Runtime.InteropServices.HandleRef(null, global::System.IntPtr.Zero) : obj.swigCPtr; } + + CPTR_VISIBILITY static global::System.Runtime.InteropServices.HandleRef swigRelease($csclassname obj) { + return (obj == null) ? new global::System.Runtime.InteropServices.HandleRef(null, global::System.IntPtr.Zero) : obj.swigCPtr; + } %} %typemap(csbody) TYPE (CLASS::*) %{ diff --git a/Lib/csharp/std_auto_ptr.i b/Lib/csharp/std_auto_ptr.i index 068d3a9d1..b1ec3d569 100644 --- a/Lib/csharp/std_auto_ptr.i +++ b/Lib/csharp/std_auto_ptr.i @@ -9,7 +9,7 @@ %define %auto_ptr(TYPE) %typemap (ctype) std::auto_ptr< TYPE > "void *" -%typemap (imtype, out="System.IntPtr") std::auto_ptr< TYPE > "HandleRef" +%typemap (imtype, out="System.IntPtr") std::auto_ptr< TYPE > "global::System.Runtime.InteropServices.HandleRef" %typemap (cstype) std::auto_ptr< TYPE > "$typemap(cstype, TYPE)" %typemap (out) std::auto_ptr< TYPE > %{ $result = (void *)$1.release(); diff --git a/Lib/csharp/std_unique_ptr.i b/Lib/csharp/std_unique_ptr.i index b2716756a..ba13fce4e 100644 --- a/Lib/csharp/std_unique_ptr.i +++ b/Lib/csharp/std_unique_ptr.i @@ -9,8 +9,14 @@ %define %unique_ptr(TYPE) %typemap (ctype) std::unique_ptr< TYPE > "void *" -%typemap (imtype, out="System.IntPtr") std::unique_ptr< TYPE > "HandleRef" +%typemap (imtype, out="System.IntPtr") std::unique_ptr< TYPE > "global::System.Runtime.InteropServices.HandleRef" %typemap (cstype) std::unique_ptr< TYPE > "$typemap(cstype, TYPE)" + +%typemap(in) std::unique_ptr< TYPE > +%{ $1.reset((TYPE *)$input); %} + +%typemap(csin) std::unique_ptr< TYPE > "$typemap(cstype, TYPE).swigRelease($csinput)" + %typemap (out) std::unique_ptr< TYPE > %{ $result = (void *)$1.release(); %} @@ -23,5 +29,5 @@ %enddef namespace std { - template class unique_ptr {}; + template class unique_ptr {}; } From c3c061cac8fbae8c65caefe462a3bd879fc6f547 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Sat, 16 Jul 2022 13:14:40 +0100 Subject: [PATCH 526/662] Add Python support for std::unique_ptr inputs Equivalent to Java/C# implementation. --- Examples/test-suite/cpp11_std_unique_ptr.i | 2 +- .../python/cpp11_std_unique_ptr_runme.py | 65 +++++++++++++++++++ Lib/python/pyrun.swg | 17 +++-- Lib/python/std_unique_ptr.i | 13 ++++ Lib/swigerrors.swg | 3 +- Lib/swigrun.swg | 10 ++- Lib/typemaps/exception.swg | 1 + Lib/typemaps/swigtypemaps.swg | 1 + 8 files changed, 103 insertions(+), 9 deletions(-) diff --git a/Examples/test-suite/cpp11_std_unique_ptr.i b/Examples/test-suite/cpp11_std_unique_ptr.i index 5ef49456c..804a4a27d 100644 --- a/Examples/test-suite/cpp11_std_unique_ptr.i +++ b/Examples/test-suite/cpp11_std_unique_ptr.i @@ -53,7 +53,7 @@ struct KlassInheritance : virtual Klass { } }; -#if defined(SWIGJAVA) || defined (SWIGCSHARP) +#if defined(SWIGJAVA) || defined (SWIGCSHARP) || defined(SWIGPYTHON) std::string takeKlassUniquePtr(std::unique_ptr k) { return std::string(k->getLabel()); } 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 a84efcd5f..d102ebcd8 100644 --- a/Examples/test-suite/python/cpp11_std_unique_ptr_runme.py +++ b/Examples/test-suite/python/cpp11_std_unique_ptr_runme.py @@ -1,5 +1,70 @@ from cpp11_std_unique_ptr import * +def checkCount(expected_count): + actual_count = Klass.getTotal_count() + if (actual_count != expected_count): + raise RuntimeError("Counts incorrect, expected:" + expected_count + " actual:" + actual_count) + +# unique_ptr as input +kin = Klass("KlassInput") +checkCount(1) +s = takeKlassUniquePtr(kin) +checkCount(0) +if kin.thisown: + raise RuntimeError("thisown should be false") +if s != "KlassInput": + raise RuntimeError("Incorrect string: " + s) +if not is_nullptr(kin): + raise RuntimeError("is_nullptr failed") +del kin # Should not fail, even though already deleted +checkCount(0) + +kin = Klass("KlassInput") +checkCount(1) +s = takeKlassUniquePtr(kin) +checkCount(0) +if kin.thisown: + raise RuntimeError("thisown should be false") +if s != "KlassInput": + raise RuntimeError("Incorrect string: " + s) +if not is_nullptr(kin): + raise RuntimeError("is_nullptr failed") +exception_thrown = False +try: + s = takeKlassUniquePtr(kin) +except RuntimeError as e: + exception_thrown = True +if not exception_thrown: + raise RuntimeError("double usage of takeKlassUniquePtr should have been an error") +del kin # Should not fail, even though already deleted +checkCount(0) + +kin = Klass("KlassInput") +exception_thrown = False +try: + notowned = get_not_owned_ptr(kin) + takeKlassUniquePtr(notowned) +except RuntimeError as e: + exception_thrown = True +if not exception_thrown: + raise RuntimeError("Should have thrown 'Cannot release ownership as memory is not owned' error") +del kin +checkCount(0) + +kini = KlassInheritance("KlassInheritanceInput") +checkCount(1) +s = takeKlassUniquePtr(kini) +checkCount(0) +if kini.thisown: + raise RuntimeError("thisown should be false") +if s != "KlassInheritanceInput": + raise RuntimeError("Incorrect string: " + s) +if not is_nullptr(kini): + raise RuntimeError("is_nullptr failed") +del kini # Should not fail, even though already deleted +checkCount(0) + +# unique_ptr as output k1 = makeKlassUniquePtr("first") k2 = makeKlassUniquePtr("second") if Klass.getTotal_count() != 2: diff --git a/Lib/python/pyrun.swg b/Lib/python/pyrun.swg index 935885934..ec6e3d5a8 100644 --- a/Lib/python/pyrun.swg +++ b/Lib/python/pyrun.swg @@ -1357,12 +1357,19 @@ SWIG_Python_ConvertPtrAndOwn(PyObject *obj, void **ptr, swig_type_info *ty, int } } if (sobj) { - if (own) - *own = *own | sobj->own; - if (flags & SWIG_POINTER_DISOWN) { - sobj->own = 0; + if (((flags & SWIG_POINTER_RELEASE) == SWIG_POINTER_RELEASE) && !sobj->own) { + res = SWIG_ERROR_RELEASE_NOT_OWNED; + } else { + if (own) + *own = *own | sobj->own; + if (flags & SWIG_POINTER_DISOWN) { + sobj->own = 0; + } + if (flags & SWIG_POINTER_CLEAR) { + sobj->ptr = 0; + } + res = SWIG_OK; } - res = SWIG_OK; } else { if (implicit_conv) { SwigPyClientData *data = ty ? (SwigPyClientData *) ty->clientdata : 0; diff --git a/Lib/python/std_unique_ptr.i b/Lib/python/std_unique_ptr.i index 331817f76..bec8bf968 100644 --- a/Lib/python/std_unique_ptr.i +++ b/Lib/python/std_unique_ptr.i @@ -8,9 +8,22 @@ * ----------------------------------------------------------------------------- */ %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 | %convertptr_flags); + if (!SWIG_IsOK(res)) { + if (res == SWIG_ERROR_RELEASE_NOT_OWNED) { + %releasenotowned_fail(res, "TYPE *", $symname, $argnum); + } else { + %argument_fail(res, "TYPE *", $symname, $argnum); + } + } + $1.reset((TYPE *)argp); +} + %typemap (out) std::unique_ptr< TYPE > %{ %set_output(SWIG_NewPointerObj($1.release(), $descriptor(TYPE *), SWIG_POINTER_OWN | %newpointer_flags)); %} + %template() std::unique_ptr< TYPE >; %enddef diff --git a/Lib/swigerrors.swg b/Lib/swigerrors.swg index 1a6d20366..4d5a8e473 100644 --- a/Lib/swigerrors.swg +++ b/Lib/swigerrors.swg @@ -1,4 +1,4 @@ -/* Errors in SWIG */ +/* SWIG Errors applicable to all language modules, values are reserved from -1 to -99 */ #define SWIG_UnknownError -1 #define SWIG_IOError -2 #define SWIG_RuntimeError -3 @@ -13,4 +13,3 @@ #define SWIG_MemoryError -12 #define SWIG_NullReferenceError -13 - diff --git a/Lib/swigrun.swg b/Lib/swigrun.swg index de0db2dc3..9ec98ccf2 100644 --- a/Lib/swigrun.swg +++ b/Lib/swigrun.swg @@ -44,6 +44,8 @@ #define SWIG_POINTER_DISOWN 0x1 #define SWIG_CAST_NEW_MEMORY 0x2 #define SWIG_POINTER_NO_NULL 0x4 +#define SWIG_POINTER_CLEAR 0x8 +#define SWIG_POINTER_RELEASE (SWIG_POINTER_CLEAR | SWIG_POINTER_DISOWN) /* Flags for new pointer objects */ #define SWIG_POINTER_OWN 0x1 @@ -129,7 +131,13 @@ */ #define SWIG_OK (0) +/* Runtime errors are < 0 */ #define SWIG_ERROR (-1) +/* Errors in range -1 to -99 are in swigerrors.swg (errors for all languages including those not using the runtime) */ +/* Errors in range -100 to -199 are language specific errors defined in *errors.swg */ +/* Errors < -200 are generic runtime specific errors */ +#define SWIG_ERROR_RELEASE_NOT_OWNED (-200) + #define SWIG_IsOK(r) (r >= 0) #define SWIG_ArgError(r) ((r != SWIG_ERROR) ? r : SWIG_TypeError) @@ -144,7 +152,7 @@ #define SWIG_OLDOBJ (SWIG_OK) #define SWIG_NEWOBJ (SWIG_OK | SWIG_NEWOBJMASK) #define SWIG_TMPOBJ (SWIG_OK | SWIG_TMPOBJMASK) -/* Check, add and del mask methods */ +/* Check, add and del object mask methods */ #define SWIG_AddNewMask(r) (SWIG_IsOK(r) ? (r | SWIG_NEWOBJMASK) : r) #define SWIG_DelNewMask(r) (SWIG_IsOK(r) ? (r & ~SWIG_NEWOBJMASK) : r) #define SWIG_IsNewObj(r) (SWIG_IsOK(r) && (r & SWIG_NEWOBJMASK)) diff --git a/Lib/typemaps/exception.swg b/Lib/typemaps/exception.swg index e48294c3f..aece8326f 100644 --- a/Lib/typemaps/exception.swg +++ b/Lib/typemaps/exception.swg @@ -19,6 +19,7 @@ #endif #define %varnullref_fmt(_type,_name) %nullref_fmt() %varfail_fmt(_type, _name) #define %outnullref_fmt(_type) %nullref_fmt() %outfail_fmt(_type) +#define %releasenotownedfail_fmt(_type,_name,_argn) "in method '" `_name` "', cannot release ownership as memory is not owned for argument " `_argn`" of type '" `_type`"'" /* setting an error */ #define %error(code,msg...) SWIG_Error(code, msg) diff --git a/Lib/typemaps/swigtypemaps.swg b/Lib/typemaps/swigtypemaps.swg index 4e5bb2b04..733e5acd0 100644 --- a/Lib/typemaps/swigtypemaps.swg +++ b/Lib/typemaps/swigtypemaps.swg @@ -140,6 +140,7 @@ #define %argument_nullref(type, name, argn) SWIG_exception_fail(SWIG_ValueError, %argnullref_fmt(type, name, argn)) #define %variable_fail(code, type, name) SWIG_exception_fail(%default_code(code), %varfail_fmt(type, name)) #define %variable_nullref(type, name) SWIG_exception_fail(SWIG_ValueError, %varnullref_fmt(type, name)) +#define %releasenotowned_fail(code, type, name, argn) SWIG_exception_fail(%default_code(code), %releasenotownedfail_fmt(type, name, argn)) #if defined(SWIG_DIRECTOR_TYPEMAPS) #define %dirout_fail(code, type) SWIG_DirOutFail(%default_code(code), %outfail_fmt(type)) From f99a2e6f6432423cc64c3e45756519637df08e27 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Sun, 17 Jul 2022 14:27:33 +0100 Subject: [PATCH 527/662] Add Ruby support for std::unique_ptr inputs Equivalent to Java/C#/Python implementations. --- Examples/test-suite/cpp11_std_unique_ptr.i | 2 - .../ruby/cpp11_std_unique_ptr_runme.rb | 91 +++++++++++++++++++ Lib/ruby/rubyrun.swg | 11 ++- Lib/ruby/std_unique_ptr.i | 13 +++ 4 files changed, 114 insertions(+), 3 deletions(-) diff --git a/Examples/test-suite/cpp11_std_unique_ptr.i b/Examples/test-suite/cpp11_std_unique_ptr.i index 804a4a27d..ec7505974 100644 --- a/Examples/test-suite/cpp11_std_unique_ptr.i +++ b/Examples/test-suite/cpp11_std_unique_ptr.i @@ -53,11 +53,9 @@ struct KlassInheritance : virtual Klass { } }; -#if defined(SWIGJAVA) || defined (SWIGCSHARP) || defined(SWIGPYTHON) std::string takeKlassUniquePtr(std::unique_ptr k) { return std::string(k->getLabel()); } -#endif bool is_nullptr(Klass *p) { return p == nullptr; 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 cfc03fe2a..ed9138bcd 100644 --- a/Examples/test-suite/ruby/cpp11_std_unique_ptr_runme.rb +++ b/Examples/test-suite/ruby/cpp11_std_unique_ptr_runme.rb @@ -11,6 +11,97 @@ def gc_check(expected_count) # swig_assert_equal_simple(expected_count, Cpp11_std_unique_ptr::Klass::getTotal_count()) end +def checkCount(expected_count) + actual_count = Cpp11_std_unique_ptr::Klass.getTotal_count() + if (actual_count != expected_count) + raise RuntimeError, "Counts incorrect, expected:" + expected_count + " actual:" + actual_count + end +end + + +# unique_ptr as input +kin = Cpp11_std_unique_ptr::Klass.new("KlassInput") +checkCount(1) +s = Cpp11_std_unique_ptr.takeKlassUniquePtr(kin) +checkCount(0) +if (s != "KlassInput") + raise RuntimeError, "Incorrect string: " + s +end +exception_thrown = false +begin + Cpp11_std_unique_ptr.is_nullptr(kin) +rescue ObjectPreviouslyDeleted + exception_thrown = true +end +if (!exception_thrown) + raise RuntimeError, "is_nullptr failed to throw" +end +kin = nil +checkCount(0) + +kin = Cpp11_std_unique_ptr::Klass.new("KlassInput") +checkCount(1) +s = Cpp11_std_unique_ptr.takeKlassUniquePtr(kin) +checkCount(0) +if (s != "KlassInput") + raise RuntimeError, "Incorrect string: " + s +end +exception_thrown = false +begin + Cpp11_std_unique_ptr.is_nullptr(kin) +rescue ObjectPreviouslyDeleted + exception_thrown = true +end +if (!exception_thrown) + raise RuntimeError, "is_nullptr failed to throw" +end +exception_thrown = false +begin + Cpp11_std_unique_ptr.takeKlassUniquePtr(kin) +rescue RuntimeError => e + # puts e.message + exception_thrown = true +end +if (!exception_thrown) + raise RuntimeError, "double usage of takeKlassUniquePtr should have been an error" +end +kin = nil +checkCount(0) + +kin = Cpp11_std_unique_ptr::Klass.new("KlassInput") +exception_thrown = false +begin + notowned = Cpp11_std_unique_ptr::get_not_owned_ptr(kin) + Cpp11_std_unique_ptr::takeKlassUniquePtr(notowned) +rescue RuntimeError + exception_thrown = true +end +if (!exception_thrown) + raise RuntimeError, "Should have thrown 'Cannot release ownership as memory is not owned' error" +end +Cpp11_std_unique_ptr.takeKlassUniquePtr(kin) # Ensure object is deleted (can't rely on GC) +checkCount(0) + +kini = Cpp11_std_unique_ptr::KlassInheritance.new("KlassInheritanceInput") +checkCount(1) +s = Cpp11_std_unique_ptr.takeKlassUniquePtr(kini) +checkCount(0) +if (s != "KlassInheritanceInput") + raise RuntimeError, "Incorrect string: " + s +end +exception_thrown = false +begin + Cpp11_std_unique_ptr.is_nullptr(kini) +rescue ObjectPreviouslyDeleted + exception_thrown = true +end +if (!exception_thrown) + raise RuntimeError, "is_nullptr failed to throw" +end +kini = nil +checkCount(0) + +# unique_ptr as output k1 = Cpp11_std_unique_ptr::makeKlassUniquePtr("first") k2 = Cpp11_std_unique_ptr::makeKlassUniquePtr("second") swig_assert_equal_simple(2, Cpp11_std_unique_ptr::Klass::getTotal_count()) diff --git a/Lib/ruby/rubyrun.swg b/Lib/ruby/rubyrun.swg index e4c23bde5..6cac4626a 100644 --- a/Lib/ruby/rubyrun.swg +++ b/Lib/ruby/rubyrun.swg @@ -281,6 +281,11 @@ SWIG_Ruby_ConvertPtrAndOwn(VALUE obj, void **ptr, swig_type_info *ty, int flags, own->own = 0; } + if (((flags & SWIG_POINTER_RELEASE) == SWIG_POINTER_RELEASE)) { + if (!RDATA(obj)->dfree) + return SWIG_ERROR_RELEASE_NOT_OWNED; + } + /* Check to see if the input object is giving up ownership of the underlying C struct or C++ object. If so then we need to reset the destructor since the Ruby object no @@ -292,7 +297,7 @@ SWIG_Ruby_ConvertPtrAndOwn(VALUE obj, void **ptr, swig_type_info *ty, int flags, swig_class *sklass = (swig_class *) ty->clientdata; track = sklass->trackObjects; } - + if (track) { /* We are tracking objects for this class. Thus we change the destructor * to SWIG_RubyRemoveTracking. This allows us to @@ -306,6 +311,10 @@ SWIG_Ruby_ConvertPtrAndOwn(VALUE obj, void **ptr, swig_type_info *ty, int flags, } } + if (flags & SWIG_POINTER_CLEAR) { + DATA_PTR(obj) = 0; + } + /* Do type-checking if type info was provided */ if (ty) { if (ty->clientdata) { diff --git a/Lib/ruby/std_unique_ptr.i b/Lib/ruby/std_unique_ptr.i index 163c7c2d1..a0128ba78 100644 --- a/Lib/ruby/std_unique_ptr.i +++ b/Lib/ruby/std_unique_ptr.i @@ -8,9 +8,22 @@ * ----------------------------------------------------------------------------- */ %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 | %convertptr_flags); + if (!SWIG_IsOK(res)) { + if (res == SWIG_ERROR_RELEASE_NOT_OWNED) { + %releasenotowned_fail(res, "TYPE *", $symname, $argnum); + } else { + %argument_fail(res, "TYPE *", $symname, $argnum); + } + } + $1.reset((TYPE *)argp); +} + %typemap (out) std::unique_ptr< TYPE > %{ %set_output(SWIG_NewPointerObj($1.release(), $descriptor(TYPE *), SWIG_POINTER_OWN | %newpointer_flags)); %} + %template() std::unique_ptr< TYPE >; %enddef From 50fc600e8cb128e8e1d4be3d07107b9f8df5edc2 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Sun, 17 Jul 2022 20:23:52 +0100 Subject: [PATCH 528/662] Add Perl support for std::unique_ptr inputs Equivalent to Java/C#/Python/Ruby implementations. --- .../perl5/cpp11_std_unique_ptr_runme.pl | 60 ++++++++++++++++++- Lib/perl5/perlrun.swg | 17 +++++- Lib/perl5/std_unique_ptr.i | 13 ++++ 3 files changed, 87 insertions(+), 3 deletions(-) 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 ce64bbf00..a42580aca 100644 --- a/Examples/test-suite/perl5/cpp11_std_unique_ptr_runme.pl +++ b/Examples/test-suite/perl5/cpp11_std_unique_ptr_runme.pl @@ -1,9 +1,67 @@ use strict; use warnings; -use Test::More tests => 6; +use Test::More tests => 24; BEGIN { use_ok('cpp11_std_unique_ptr') } require_ok('cpp11_std_unique_ptr'); +# adapted from ../java/cpp11_std_unique_ptr_runme.java + +sub checkCount { + my($expected_count) = @_; + my $actual_count = cpp11_std_unique_ptr::Klass::getTotal_count(); + is($actual_count, $expected_count, "Counts incorrect, expected: $expected_count actual: $actual_count"); +} + +# unique_ptr as input +{ + my $kin = new cpp11_std_unique_ptr::Klass("KlassInput"); + checkCount(1); + my $s = cpp11_std_unique_ptr::takeKlassUniquePtr($kin); + checkCount(0); + is($s, "KlassInput", "Incorrect string: $s"); + is(cpp11_std_unique_ptr::is_nullptr($kin), 1, "is_nullptr check"); + undef $kin; # Should not fail, even though already deleted + checkCount(0); +} + +{ + my $kin = new cpp11_std_unique_ptr::Klass("KlassInput"); + checkCount(1); + my $s = cpp11_std_unique_ptr::takeKlassUniquePtr($kin); + checkCount(0); + is($s, "KlassInput", "Incorrect string: $s"); + is(cpp11_std_unique_ptr::is_nullptr($kin), 1, "is_nullptr check"); + eval { + cpp11_std_unique_ptr::takeKlassUniquePtr($kin); + }; + like($@, qr/\bcannot release ownership as memory is not owned\b/, "double usage of takeKlassUniquePtr should be an error"); + undef $kin; # Should not fail, even though already deleted + checkCount(0); +} + +{ + my $kin = new cpp11_std_unique_ptr::Klass("KlassInput"); + eval { + my $notowned = cpp11_std_unique_ptr::get_not_owned_ptr($kin); + cpp11_std_unique_ptr::takeKlassUniquePtr($notowned); + }; + like($@, qr/\bcannot release ownership as memory is not owned\b/, "double usage of takeKlassUniquePtr should be an error"); + undef $kin; + checkCount(0); +} + +{ + my $kini = new cpp11_std_unique_ptr::KlassInheritance("KlassInheritanceInput"); + checkCount(1); + my $s = cpp11_std_unique_ptr::takeKlassUniquePtr($kini); + checkCount(0); + is($s, "KlassInheritanceInput", "Incorrect string: $s"); + is(cpp11_std_unique_ptr::is_nullptr($kini), 1, "is_nullptr failed"); + undef $kini; # Should not fail, even though already deleted + checkCount(0); +} + +# unique_ptr as output my $k1 = cpp11_std_unique_ptr::makeKlassUniquePtr("first"); my $k2 = cpp11_std_unique_ptr::makeKlassUniquePtr("second"); is(cpp11_std_unique_ptr::Klass::getTotal_count, 2, "have 2 pointers"); diff --git a/Lib/perl5/perlrun.swg b/Lib/perl5/perlrun.swg index 28703d1a6..71f19cbf8 100644 --- a/Lib/perl5/perlrun.swg +++ b/Lib/perl5/perlrun.swg @@ -210,6 +210,7 @@ SWIG_Perl_ConvertPtrAndOwn(SWIG_MAYBE_PERL_OBJECT SV *sv, void **ptr, swig_type_ swig_cast_info *tc; void *voidptr = (void *)0; SV *tsv = 0; + int check_owned_pointer_release = (flags & SWIG_POINTER_RELEASE) == SWIG_POINTER_RELEASE; if (own) *own = 0; @@ -286,13 +287,14 @@ SWIG_Perl_ConvertPtrAndOwn(SWIG_MAYBE_PERL_OBJECT SV *sv, void **ptr, swig_type_ /* * DISOWN implementation: we need a perl guru to check this one. */ - if (tsv && (flags & SWIG_POINTER_DISOWN)) { + if (tsv && ((flags & SWIG_POINTER_DISOWN) || check_owned_pointer_release)) { /* * almost copy paste code from below SWIG_POINTER_OWN setting */ SV *obj = sv; HV *stash = SvSTASH(SvRV(obj)); GV *gv = *(GV**)hv_fetch(stash, "OWNER", 5, TRUE); + int owned = 0; if (isGV(gv)) { HV *hv = GvHVn(gv); /* @@ -300,10 +302,21 @@ SWIG_Perl_ConvertPtrAndOwn(SWIG_MAYBE_PERL_OBJECT SV *sv, void **ptr, swig_type_ * Hence, to remove ownership, we delete the entry. */ if (hv_exists_ent(hv, obj, 0)) { - hv_delete_ent(hv, obj, 0, 0); + owned = 1; + if (flags & SWIG_POINTER_DISOWN) { + hv_delete_ent(hv, obj, 0, 0); + } } } + if (check_owned_pointer_release && !owned) { + return SWIG_ERROR_RELEASE_NOT_OWNED; + } } + + if (tsv && (flags & SWIG_POINTER_CLEAR)) { + SvIV_set(tsv, 0); + } + return SWIG_OK; } diff --git a/Lib/perl5/std_unique_ptr.i b/Lib/perl5/std_unique_ptr.i index 163c7c2d1..a0128ba78 100644 --- a/Lib/perl5/std_unique_ptr.i +++ b/Lib/perl5/std_unique_ptr.i @@ -8,9 +8,22 @@ * ----------------------------------------------------------------------------- */ %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 | %convertptr_flags); + if (!SWIG_IsOK(res)) { + if (res == SWIG_ERROR_RELEASE_NOT_OWNED) { + %releasenotowned_fail(res, "TYPE *", $symname, $argnum); + } else { + %argument_fail(res, "TYPE *", $symname, $argnum); + } + } + $1.reset((TYPE *)argp); +} + %typemap (out) std::unique_ptr< TYPE > %{ %set_output(SWIG_NewPointerObj($1.release(), $descriptor(TYPE *), SWIG_POINTER_OWN | %newpointer_flags)); %} + %template() std::unique_ptr< TYPE >; %enddef From 5dd5e80a84a9c7b0941f55e21c8ac53c7529f5fd Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Sun, 17 Jul 2022 20:44:20 +0100 Subject: [PATCH 529/662] Cosmetic formatting and doc updates in std_unique_ptr.i files --- Lib/csharp/std_unique_ptr.i | 23 +++++++++++++---------- Lib/java/std_unique_ptr.i | 25 +++++++++++++------------ Lib/perl5/std_unique_ptr.i | 13 +++++++------ Lib/python/std_unique_ptr.i | 15 ++++++++------- Lib/ruby/std_unique_ptr.i | 13 +++++++------ 5 files changed, 48 insertions(+), 41 deletions(-) diff --git a/Lib/csharp/std_unique_ptr.i b/Lib/csharp/std_unique_ptr.i index ba13fce4e..2233cdc06 100644 --- a/Lib/csharp/std_unique_ptr.i +++ b/Lib/csharp/std_unique_ptr.i @@ -1,10 +1,11 @@ /* ----------------------------------------------------------------------------- * std_unique_ptr.i * - * The typemaps here allow handling functions returning std::unique_ptr<>, - * which is the most common use of this type. If you have functions taking it - * as parameter, these typemaps can't be used for them and you need to do - * something else (e.g. use shared_ptr<> which SWIG supports fully). + * SWIG library file for handling std::unique_ptr. + * Memory ownership is passed from the std::unique_ptr C++ layer to the proxy + * class when returning a std::unique_ptr from a function. + * Memory ownership is passed from the proxy class to the std::unique_ptr in the + * C++ layer when passed as a parameter to a wrapped function. * ----------------------------------------------------------------------------- */ %define %unique_ptr(TYPE) @@ -18,16 +19,18 @@ %typemap(csin) std::unique_ptr< TYPE > "$typemap(cstype, TYPE).swigRelease($csinput)" %typemap (out) std::unique_ptr< TYPE > %{ - $result = (void *)$1.release(); + $result = (void *)$1.release(); %} + %typemap(csout, excode=SWIGEXCODE) std::unique_ptr< TYPE > { - System.IntPtr cPtr = $imcall; - $typemap(cstype, TYPE) ret = (cPtr == System.IntPtr.Zero) ? null : new $typemap(cstype, TYPE)(cPtr, true);$excode - return ret; - } + System.IntPtr cPtr = $imcall; + $typemap(cstype, TYPE) ret = (cPtr == System.IntPtr.Zero) ? null : new $typemap(cstype, TYPE)(cPtr, true);$excode + return ret; + } + %template() std::unique_ptr< TYPE >; %enddef namespace std { template class unique_ptr {}; -} +} diff --git a/Lib/java/std_unique_ptr.i b/Lib/java/std_unique_ptr.i index 5f4a0c5a2..e1e5a2622 100644 --- a/Lib/java/std_unique_ptr.i +++ b/Lib/java/std_unique_ptr.i @@ -1,10 +1,11 @@ /* ----------------------------------------------------------------------------- * std_unique_ptr.i * - * The typemaps here allow handling functions returning std::unique_ptr<>, - * which is the most common use of this type. If you have functions taking it - * as parameter, these typemaps can't be used for them and you need to do - * something else (e.g. use shared_ptr<> which SWIG supports fully). + * SWIG library file for handling std::unique_ptr. + * Memory ownership is passed from the std::unique_ptr C++ layer to the proxy + * class when returning a std::unique_ptr from a function. + * Memory ownership is passed from the proxy class to the std::unique_ptr in the + * C++ layer when passed as a parameter to a wrapped function. * ----------------------------------------------------------------------------- */ %define %unique_ptr(TYPE) @@ -20,19 +21,19 @@ %typemap(javain) std::unique_ptr< TYPE > "$typemap(jstype, TYPE).swigRelease($javainput)" %typemap (out) std::unique_ptr< TYPE > %{ - jlong lpp = 0; - *(TYPE **) &lpp = $1.release(); - $result = lpp; + jlong lpp = 0; + *(TYPE **) &lpp = $1.release(); + $result = lpp; %} %typemap(javaout) std::unique_ptr< TYPE > { - long cPtr = $jnicall; - return (cPtr == 0) ? null : new $typemap(jstype, TYPE)(cPtr, true); - } + long cPtr = $jnicall; + return (cPtr == 0) ? null : new $typemap(jstype, TYPE)(cPtr, true); + } %template() std::unique_ptr< TYPE >; %enddef namespace std { - template class unique_ptr {}; -} + template class unique_ptr {}; +} diff --git a/Lib/perl5/std_unique_ptr.i b/Lib/perl5/std_unique_ptr.i index a0128ba78..1a7ec06fa 100644 --- a/Lib/perl5/std_unique_ptr.i +++ b/Lib/perl5/std_unique_ptr.i @@ -1,10 +1,11 @@ /* ----------------------------------------------------------------------------- * std_unique_ptr.i * - * The typemaps here allow handling functions returning std::unique_ptr<>, - * which is the most common use of this type. If you have functions taking it - * as parameter, these typemaps can't be used for them and you need to do - * something else (e.g. use shared_ptr<> which SWIG supports fully). + * SWIG library file for handling std::unique_ptr. + * Memory ownership is passed from the std::unique_ptr C++ layer to the proxy + * class when returning a std::unique_ptr from a function. + * Memory ownership is passed from the proxy class to the std::unique_ptr in the + * C++ layer when passed as a parameter to a wrapped function. * ----------------------------------------------------------------------------- */ %define %unique_ptr(TYPE) @@ -21,12 +22,12 @@ } %typemap (out) std::unique_ptr< TYPE > %{ - %set_output(SWIG_NewPointerObj($1.release(), $descriptor(TYPE *), SWIG_POINTER_OWN | %newpointer_flags)); + %set_output(SWIG_NewPointerObj($1.release(), $descriptor(TYPE *), SWIG_POINTER_OWN | %newpointer_flags)); %} %template() std::unique_ptr< TYPE >; %enddef namespace std { - template class unique_ptr {}; + template class unique_ptr {}; } diff --git a/Lib/python/std_unique_ptr.i b/Lib/python/std_unique_ptr.i index bec8bf968..1a7ec06fa 100644 --- a/Lib/python/std_unique_ptr.i +++ b/Lib/python/std_unique_ptr.i @@ -1,10 +1,11 @@ /* ----------------------------------------------------------------------------- * std_unique_ptr.i * - * The typemaps here allow handling functions returning std::unique_ptr<>, - * which is the most common use of this type. If you have functions taking it - * as parameter, these typemaps can't be used for them and you need to do - * something else (e.g. use shared_ptr<> which SWIG supports fully). + * SWIG library file for handling std::unique_ptr. + * Memory ownership is passed from the std::unique_ptr C++ layer to the proxy + * class when returning a std::unique_ptr from a function. + * Memory ownership is passed from the proxy class to the std::unique_ptr in the + * C++ layer when passed as a parameter to a wrapped function. * ----------------------------------------------------------------------------- */ %define %unique_ptr(TYPE) @@ -21,12 +22,12 @@ } %typemap (out) std::unique_ptr< TYPE > %{ - %set_output(SWIG_NewPointerObj($1.release(), $descriptor(TYPE *), SWIG_POINTER_OWN | %newpointer_flags)); + %set_output(SWIG_NewPointerObj($1.release(), $descriptor(TYPE *), SWIG_POINTER_OWN | %newpointer_flags)); %} %template() std::unique_ptr< TYPE >; %enddef namespace std { - template class unique_ptr {}; -} + template class unique_ptr {}; +} diff --git a/Lib/ruby/std_unique_ptr.i b/Lib/ruby/std_unique_ptr.i index a0128ba78..1a7ec06fa 100644 --- a/Lib/ruby/std_unique_ptr.i +++ b/Lib/ruby/std_unique_ptr.i @@ -1,10 +1,11 @@ /* ----------------------------------------------------------------------------- * std_unique_ptr.i * - * The typemaps here allow handling functions returning std::unique_ptr<>, - * which is the most common use of this type. If you have functions taking it - * as parameter, these typemaps can't be used for them and you need to do - * something else (e.g. use shared_ptr<> which SWIG supports fully). + * SWIG library file for handling std::unique_ptr. + * Memory ownership is passed from the std::unique_ptr C++ layer to the proxy + * class when returning a std::unique_ptr from a function. + * Memory ownership is passed from the proxy class to the std::unique_ptr in the + * C++ layer when passed as a parameter to a wrapped function. * ----------------------------------------------------------------------------- */ %define %unique_ptr(TYPE) @@ -21,12 +22,12 @@ } %typemap (out) std::unique_ptr< TYPE > %{ - %set_output(SWIG_NewPointerObj($1.release(), $descriptor(TYPE *), SWIG_POINTER_OWN | %newpointer_flags)); + %set_output(SWIG_NewPointerObj($1.release(), $descriptor(TYPE *), SWIG_POINTER_OWN | %newpointer_flags)); %} %template() std::unique_ptr< TYPE >; %enddef namespace std { - template class unique_ptr {}; + template class unique_ptr {}; } From dd0c8632bf05765f30c99e74203e99b1d281478c Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Mon, 18 Jul 2022 18:38:49 +1200 Subject: [PATCH 530/662] Set PYTHON*DYNAMICLINKING for AIX Changes based on supplied patch, but reworked version not tested as I don't have access to AIX and the submitter hasn't responded in 18 months. Fixes #1920 --- configure.ac | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/configure.ac b/configure.ac index 0d86e9ca9..188b2397f 100644 --- a/configure.ac +++ b/configure.ac @@ -779,6 +779,9 @@ else PYTHONDYNAMICLINKING="-L$PYLIB $PYLINK" DEFS="-DUSE_DL_IMPORT $DEFS" ;; + *-*-aix*) + PYTHONDYNAMICLINKING="-L$PYLIB $PYLINK" + ;; *)PYTHONDYNAMICLINKING="";; esac fi @@ -954,6 +957,9 @@ else PYTHON3DYNAMICLINKING="-L$PY3LIB $PY3LINK" DEFS="-DUSE_DL_IMPORT $DEFS" ;; + *-*-aix*) + PYTHON3DYNAMICLINKING="-L$PY3LIB $PY3LINK" + ;; *)PYTHON3DYNAMICLINKING="";; esac From db5e37a1d7b80304a9c9875b01cfd585070a288a Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Mon, 18 Jul 2022 08:32:26 +0100 Subject: [PATCH 531/662] Add support for std::auto_ptr inputs Ported from std::unique, behaviour is identical with regard to memory ownership/handling --- .../csharp/li_std_auto_ptr_runme.cs | 63 +++++++++++++ .../java/li_std_auto_ptr_runme.java | 70 ++++++++++++++ Examples/test-suite/li_std_auto_ptr.i | 30 +++++- .../test-suite/perl5/li_std_auto_ptr_runme.pl | 60 +++++++++++- .../python/li_std_auto_ptr_runme.py | 65 +++++++++++++ .../test-suite/ruby/li_std_auto_ptr_runme.rb | 91 +++++++++++++++++++ Lib/csharp/std_auto_ptr.i | 31 ++++--- Lib/java/std_auto_ptr.i | 34 ++++--- Lib/perl5/std_auto_ptr.i | 26 ++++-- Lib/python/std_auto_ptr.i | 28 ++++-- Lib/ruby/std_auto_ptr.i | 26 ++++-- 11 files changed, 477 insertions(+), 47 deletions(-) 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 863b86701..b804e7ead 100644 --- a/Examples/test-suite/csharp/li_std_auto_ptr_runme.cs +++ b/Examples/test-suite/csharp/li_std_auto_ptr_runme.cs @@ -9,8 +9,71 @@ public class li_std_auto_ptr_runme { System.Threading.Thread.Sleep(10); } + private static void checkCount(int expected_count) + { + int actual_count = Klass.getTotal_count(); + if (actual_count != expected_count) + throw new ApplicationException("Counts incorrect, expected:" + expected_count + " actual:" + actual_count); + } + public static void Main() { + // auto_ptr as input + using (Klass kin = new Klass("KlassInput")) { + checkCount(1); + string s = li_std_auto_ptr.takeKlassAutoPtr(kin); + checkCount(0); + if (s != "KlassInput") + throw new ApplicationException("Incorrect string: " + s); + if (!li_std_auto_ptr.is_nullptr(kin)) + throw new ApplicationException("is_nullptr failed"); + } // Dispose should not fail, even though already deleted + checkCount(0); + + using (Klass kin = new Klass("KlassInput")) { + checkCount(1); + string s = li_std_auto_ptr.takeKlassAutoPtr(kin); + checkCount(0); + if (s != "KlassInput") + throw new ApplicationException("Incorrect string: " + s); + if (!li_std_auto_ptr.is_nullptr(kin)) + throw new ApplicationException("is_nullptr failed"); + bool exception_thrown = false; + try { + li_std_auto_ptr.takeKlassAutoPtr(kin); + } catch (ApplicationException) { + exception_thrown = true; + } + if (!exception_thrown) + throw new ApplicationException("double usage of takeKlassAutoPtr should have been an error"); + } // Dispose should not fail, even though already deleted + checkCount(0); + + using (Klass kin = new Klass("KlassInput")) { + bool exception_thrown = false; + try { + Klass notowned = li_std_auto_ptr.get_not_owned_ptr(kin); + li_std_auto_ptr.takeKlassAutoPtr(notowned); + } catch (ApplicationException) { + exception_thrown = true; + } + if (!exception_thrown) + throw new ApplicationException("Should have thrown 'Cannot release ownership as memory is not owned' error"); + } + checkCount(0); + + using (KlassInheritance kini = new KlassInheritance("KlassInheritanceInput")) { + checkCount(1); + string s = li_std_auto_ptr.takeKlassAutoPtr(kini); + checkCount(0); + if (s != "KlassInheritanceInput") + throw new ApplicationException("Incorrect string: " + s); + if (!li_std_auto_ptr.is_nullptr(kini)) + throw new ApplicationException("is_nullptr failed"); + } // Dispose should not fail, even though already deleted + checkCount(0); + + // auto_ptr as output Klass k1 = li_std_auto_ptr.makeKlassAutoPtr("first"); if (k1.getLabel() != "first") throw new Exception("wrong object label"); 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 50ed113a4..40957e974 100644 --- a/Examples/test-suite/java/li_std_auto_ptr_runme.java +++ b/Examples/test-suite/java/li_std_auto_ptr_runme.java @@ -20,8 +20,78 @@ public class li_std_auto_ptr_runme { } } + private static void checkCount(int expected_count) { + int actual_count = Klass.getTotal_count(); + if (actual_count != expected_count) + throw new RuntimeException("Counts incorrect, expected:" + expected_count + " actual:" + actual_count); + } + public static void main(String argv[]) throws Throwable { + // auto_ptr as input + { + Klass kin = new Klass("KlassInput"); + checkCount(1); + String s = li_std_auto_ptr.takeKlassAutoPtr(kin); + checkCount(0); + if (!s.equals("KlassInput")) + throw new RuntimeException("Incorrect string: " + s); + if (!li_std_auto_ptr.is_nullptr(kin)) + throw new RuntimeException("is_nullptr failed"); + kin.delete(); // Should not fail, even though already deleted + checkCount(0); + } + + { + Klass kin = new Klass("KlassInput"); + checkCount(1); + String s = li_std_auto_ptr.takeKlassAutoPtr(kin); + checkCount(0); + if (!s.equals("KlassInput")) + throw new RuntimeException("Incorrect string: " + s); + if (!li_std_auto_ptr.is_nullptr(kin)) + throw new RuntimeException("is_nullptr failed"); + boolean exception_thrown = false; + try { + li_std_auto_ptr.takeKlassAutoPtr(kin); + } catch (RuntimeException e) { + exception_thrown = true; + } + if (!exception_thrown) + throw new RuntimeException("double usage of takeKlassAutoPtr should have been an error"); + kin.delete(); // Should not fail, even though already deleted + checkCount(0); + } + + { + Klass kin = new Klass("KlassInput"); + boolean exception_thrown = false; + try { + Klass notowned = li_std_auto_ptr.get_not_owned_ptr(kin); + li_std_auto_ptr.takeKlassAutoPtr(notowned); + } catch (RuntimeException e) { + exception_thrown = true; + } + if (!exception_thrown) + throw new RuntimeException("Should have thrown 'Cannot release ownership as memory is not owned' error"); + kin.delete(); + checkCount(0); + } + + { + KlassInheritance kini = new KlassInheritance("KlassInheritanceInput"); + checkCount(1); + String s = li_std_auto_ptr.takeKlassAutoPtr(kini); + checkCount(0); + if (!s.equals("KlassInheritanceInput")) + throw new RuntimeException("Incorrect string: " + s); + if (!li_std_auto_ptr.is_nullptr(kini)) + throw new RuntimeException("is_nullptr failed"); + kini.delete(); // Should not fail, even though already deleted + checkCount(0); + } + + // auto_ptr as output Klass k1 = li_std_auto_ptr.makeKlassAutoPtr("first"); if (!k1.getLabel().equals("first")) throw new RuntimeException("wrong object label"); diff --git a/Examples/test-suite/li_std_auto_ptr.i b/Examples/test-suite/li_std_auto_ptr.i index edfe2ccf5..02c8235f2 100644 --- a/Examples/test-suite/li_std_auto_ptr.i +++ b/Examples/test-suite/li_std_auto_ptr.i @@ -14,6 +14,7 @@ #if defined(SWIGCSHARP) || defined(SWIGJAVA) || defined(SWIGPYTHON) || defined(SWIGRUBY) || defined(SWIGPERL) +%include "std_string.i" %include "std_auto_ptr.i" %auto_ptr(Klass) @@ -27,10 +28,13 @@ namespace std { template class auto_ptr { T *ptr; public: - auto_ptr(T *ptr = 0) : ptr(ptr) {} + explicit auto_ptr(T *p = 0) : ptr(p) {} auto_ptr(auto_ptr&& a) : ptr(a.ptr) { a.ptr = 0;} ~auto_ptr() { delete ptr; } T *release() { T *p = ptr; ptr = 0; return p; } + void reset(T *p = 0) { delete ptr; ptr = p; } + T &operator*() const { return *ptr; } + T *operator->() const { return ptr; } auto_ptr& operator=(auto_ptr&& a) { if (&a != this) { delete ptr; ptr = a.ptr; a.ptr = 0; } return *this; } }; } @@ -53,7 +57,7 @@ public: const char* getLabel() const { return m_label.c_str(); } - ~Klass() + virtual ~Klass() { SwigExamples::Lock lock(critical_section); total_count--; @@ -73,10 +77,28 @@ int Klass::total_count = 0; %} -%template(KlassAutoPtr) std::auto_ptr; - %inline %{ +// Virtual inheritance used as this usually results in different values for Klass* and KlassInheritance* +// for testing class inheritance and auto_ptr +struct KlassInheritance : virtual Klass { + KlassInheritance(const char* label) : Klass(label) { + // std::cout << "ptrs.... " << std::hex << (Klass*)this << " " << (KlassInheritance*)this << std::endl; + } +}; + +std::string takeKlassAutoPtr(std::auto_ptr k) { + return std::string(k->getLabel()); +} + +bool is_nullptr(Klass *p) { + return p == 0; +} + +Klass *get_not_owned_ptr(Klass *p) { + return p; +} + std::auto_ptr makeKlassAutoPtr(const char* label) { return std::auto_ptr(new Klass(label)); } 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 52cb23ac5..8a33f4562 100644 --- a/Examples/test-suite/perl5/li_std_auto_ptr_runme.pl +++ b/Examples/test-suite/perl5/li_std_auto_ptr_runme.pl @@ -1,9 +1,67 @@ use strict; use warnings; -use Test::More tests => 6; +use Test::More tests => 24; BEGIN { use_ok('li_std_auto_ptr') } require_ok('li_std_auto_ptr'); +# adapted from ../java/li_std_auto_ptr_runme.java + +sub checkCount { + my($expected_count) = @_; + my $actual_count = li_std_auto_ptr::Klass::getTotal_count(); + is($actual_count, $expected_count, "Counts incorrect, expected: $expected_count actual: $actual_count"); +} + +# auto_ptr as input +{ + my $kin = new li_std_auto_ptr::Klass("KlassInput"); + checkCount(1); + my $s = li_std_auto_ptr::takeKlassAutoPtr($kin); + checkCount(0); + is($s, "KlassInput", "Incorrect string: $s"); + is(li_std_auto_ptr::is_nullptr($kin), 1, "is_nullptr check"); + undef $kin; # Should not fail, even though already deleted + checkCount(0); +} + +{ + my $kin = new li_std_auto_ptr::Klass("KlassInput"); + checkCount(1); + my $s = li_std_auto_ptr::takeKlassAutoPtr($kin); + checkCount(0); + is($s, "KlassInput", "Incorrect string: $s"); + is(li_std_auto_ptr::is_nullptr($kin), 1, "is_nullptr check"); + eval { + li_std_auto_ptr::takeKlassAutoPtr($kin); + }; + like($@, qr/\bcannot release ownership as memory is not owned\b/, "double usage of takeKlassAutoPtr should be an error"); + undef $kin; # Should not fail, even though already deleted + checkCount(0); +} + +{ + my $kin = new li_std_auto_ptr::Klass("KlassInput"); + eval { + my $notowned = li_std_auto_ptr::get_not_owned_ptr($kin); + li_std_auto_ptr::takeKlassAutoPtr($notowned); + }; + like($@, qr/\bcannot release ownership as memory is not owned\b/, "double usage of takeKlassAutoPtr should be an error"); + undef $kin; + checkCount(0); +} + +{ + my $kini = new li_std_auto_ptr::KlassInheritance("KlassInheritanceInput"); + checkCount(1); + my $s = li_std_auto_ptr::takeKlassAutoPtr($kini); + checkCount(0); + is($s, "KlassInheritanceInput", "Incorrect string: $s"); + is(li_std_auto_ptr::is_nullptr($kini), 1, "is_nullptr failed"); + undef $kini; # Should not fail, even though already deleted + checkCount(0); +} + +# auto_ptr as output my $k1 = li_std_auto_ptr::makeKlassAutoPtr("first"); my $k2 = li_std_auto_ptr::makeKlassAutoPtr("second"); is(li_std_auto_ptr::Klass::getTotal_count, 2, "have 2 pointers"); 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 d62224ff6..3f1d392ea 100644 --- a/Examples/test-suite/python/li_std_auto_ptr_runme.py +++ b/Examples/test-suite/python/li_std_auto_ptr_runme.py @@ -1,5 +1,70 @@ from li_std_auto_ptr import * +def checkCount(expected_count): + actual_count = Klass.getTotal_count() + if (actual_count != expected_count): + raise RuntimeError("Counts incorrect, expected:" + expected_count + " actual:" + actual_count) + +# auto_ptr as input +kin = Klass("KlassInput") +checkCount(1) +s = takeKlassAutoPtr(kin) +checkCount(0) +if kin.thisown: + raise RuntimeError("thisown should be false") +if s != "KlassInput": + raise RuntimeError("Incorrect string: " + s) +if not is_nullptr(kin): + raise RuntimeError("is_nullptr failed") +del kin # Should not fail, even though already deleted +checkCount(0) + +kin = Klass("KlassInput") +checkCount(1) +s = takeKlassAutoPtr(kin) +checkCount(0) +if kin.thisown: + raise RuntimeError("thisown should be false") +if s != "KlassInput": + raise RuntimeError("Incorrect string: " + s) +if not is_nullptr(kin): + raise RuntimeError("is_nullptr failed") +exception_thrown = False +try: + s = takeKlassAutoPtr(kin) +except RuntimeError as e: + exception_thrown = True +if not exception_thrown: + raise RuntimeError("double usage of takeKlassAutoPtr should have been an error") +del kin # Should not fail, even though already deleted +checkCount(0) + +kin = Klass("KlassInput") +exception_thrown = False +try: + notowned = get_not_owned_ptr(kin) + takeKlassAutoPtr(notowned) +except RuntimeError as e: + exception_thrown = True +if not exception_thrown: + raise RuntimeError("Should have thrown 'Cannot release ownership as memory is not owned' error") +del kin +checkCount(0) + +kini = KlassInheritance("KlassInheritanceInput") +checkCount(1) +s = takeKlassAutoPtr(kini) +checkCount(0) +if kini.thisown: + raise RuntimeError("thisown should be false") +if s != "KlassInheritanceInput": + raise RuntimeError("Incorrect string: " + s) +if not is_nullptr(kini): + raise RuntimeError("is_nullptr failed") +del kini # Should not fail, even though already deleted +checkCount(0) + +# auto_ptr as output k1 = makeKlassAutoPtr("first") k2 = makeKlassAutoPtr("second") if Klass.getTotal_count() != 2: 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 cec48a58c..14e0bd9d4 100644 --- a/Examples/test-suite/ruby/li_std_auto_ptr_runme.rb +++ b/Examples/test-suite/ruby/li_std_auto_ptr_runme.rb @@ -11,6 +11,97 @@ def gc_check(expected_count) # swig_assert_equal_simple(expected_count, Li_std_auto_ptr::Klass::getTotal_count()) end +def checkCount(expected_count) + actual_count = Li_std_auto_ptr::Klass.getTotal_count() + if (actual_count != expected_count) + raise RuntimeError, "Counts incorrect, expected:" + expected_count + " actual:" + actual_count + end +end + + +# auto_ptr as input +kin = Li_std_auto_ptr::Klass.new("KlassInput") +checkCount(1) +s = Li_std_auto_ptr.takeKlassAutoPtr(kin) +checkCount(0) +if (s != "KlassInput") + raise RuntimeError, "Incorrect string: " + s +end +exception_thrown = false +begin + Li_std_auto_ptr.is_nullptr(kin) +rescue ObjectPreviouslyDeleted + exception_thrown = true +end +if (!exception_thrown) + raise RuntimeError, "is_nullptr failed to throw" +end +kin = nil +checkCount(0) + +kin = Li_std_auto_ptr::Klass.new("KlassInput") +checkCount(1) +s = Li_std_auto_ptr.takeKlassAutoPtr(kin) +checkCount(0) +if (s != "KlassInput") + raise RuntimeError, "Incorrect string: " + s +end +exception_thrown = false +begin + Li_std_auto_ptr.is_nullptr(kin) +rescue ObjectPreviouslyDeleted + exception_thrown = true +end +if (!exception_thrown) + raise RuntimeError, "is_nullptr failed to throw" +end +exception_thrown = false +begin + Li_std_auto_ptr.takeKlassAutoPtr(kin) +rescue RuntimeError => e + # puts e.message + exception_thrown = true +end +if (!exception_thrown) + raise RuntimeError, "double usage of takeKlassAutoPtr should have been an error" +end +kin = nil +checkCount(0) + +kin = Li_std_auto_ptr::Klass.new("KlassInput") +exception_thrown = false +begin + notowned = Li_std_auto_ptr::get_not_owned_ptr(kin) + Li_std_auto_ptr::takeKlassAutoPtr(notowned) +rescue RuntimeError + exception_thrown = true +end +if (!exception_thrown) + raise RuntimeError, "Should have thrown 'Cannot release ownership as memory is not owned' error" +end +Li_std_auto_ptr.takeKlassAutoPtr(kin) # Ensure object is deleted (can't rely on GC) +checkCount(0) + +kini = Li_std_auto_ptr::KlassInheritance.new("KlassInheritanceInput") +checkCount(1) +s = Li_std_auto_ptr.takeKlassAutoPtr(kini) +checkCount(0) +if (s != "KlassInheritanceInput") + raise RuntimeError, "Incorrect string: " + s +end +exception_thrown = false +begin + Li_std_auto_ptr.is_nullptr(kini) +rescue ObjectPreviouslyDeleted + exception_thrown = true +end +if (!exception_thrown) + raise RuntimeError, "is_nullptr failed to throw" +end +kini = nil +checkCount(0) + +# auto_ptr as output k1 = Li_std_auto_ptr::makeKlassAutoPtr("first") k2 = Li_std_auto_ptr::makeKlassAutoPtr("second") swig_assert_equal_simple(2, Li_std_auto_ptr::Klass::getTotal_count()) diff --git a/Lib/csharp/std_auto_ptr.i b/Lib/csharp/std_auto_ptr.i index b1ec3d569..78d7eaf4c 100644 --- a/Lib/csharp/std_auto_ptr.i +++ b/Lib/csharp/std_auto_ptr.i @@ -1,27 +1,36 @@ /* ----------------------------------------------------------------------------- * std_auto_ptr.i * - * The typemaps here allow handling functions returning std::auto_ptr<>, - * which is the most common use of this type. If you have functions taking it - * as parameter, these typemaps can't be used for them and you need to do - * something else (e.g. use shared_ptr<> which SWIG supports fully). + * SWIG library file for handling std::auto_ptr. + * Memory ownership is passed from the std::auto_ptr C++ layer to the proxy + * class when returning a std::auto_ptr from a function. + * Memory ownership is passed from the proxy class to the std::auto_ptr in the + * C++ layer when passed as a parameter to a wrapped function. * ----------------------------------------------------------------------------- */ %define %auto_ptr(TYPE) %typemap (ctype) std::auto_ptr< TYPE > "void *" %typemap (imtype, out="System.IntPtr") std::auto_ptr< TYPE > "global::System.Runtime.InteropServices.HandleRef" %typemap (cstype) std::auto_ptr< TYPE > "$typemap(cstype, TYPE)" + +%typemap(in) std::auto_ptr< TYPE > +%{ $1.reset((TYPE *)$input); %} + +%typemap(csin) std::auto_ptr< TYPE > "$typemap(cstype, TYPE).swigRelease($csinput)" + %typemap (out) std::auto_ptr< TYPE > %{ - $result = (void *)$1.release(); + $result = (void *)$1.release(); %} + %typemap(csout, excode=SWIGEXCODE) std::auto_ptr< TYPE > { - System.IntPtr cPtr = $imcall; - $typemap(cstype, TYPE) ret = (cPtr == System.IntPtr.Zero) ? null : new $typemap(cstype, TYPE)(cPtr, true);$excode - return ret; - } + System.IntPtr cPtr = $imcall; + $typemap(cstype, TYPE) ret = (cPtr == System.IntPtr.Zero) ? null : new $typemap(cstype, TYPE)(cPtr, true);$excode + return ret; + } + %template() std::auto_ptr< TYPE >; %enddef namespace std { - template class auto_ptr {}; -} + template class auto_ptr {}; +} diff --git a/Lib/java/std_auto_ptr.i b/Lib/java/std_auto_ptr.i index 0eb5fe155..6d65f0451 100644 --- a/Lib/java/std_auto_ptr.i +++ b/Lib/java/std_auto_ptr.i @@ -1,29 +1,39 @@ /* ----------------------------------------------------------------------------- * std_auto_ptr.i * - * The typemaps here allow handling functions returning std::auto_ptr<>, - * which is the most common use of this type. If you have functions taking it - * as parameter, these typemaps can't be used for them and you need to do - * something else (e.g. use shared_ptr<> which SWIG supports fully). + * SWIG library file for handling std::auto_ptr. + * Memory ownership is passed from the std::auto_ptr C++ layer to the proxy + * class when returning a std::auto_ptr from a function. + * Memory ownership is passed from the proxy class to the std::auto_ptr in the + * C++ layer when passed as a parameter to a wrapped function. * ----------------------------------------------------------------------------- */ %define %auto_ptr(TYPE) + %typemap (jni) std::auto_ptr< TYPE > "jlong" %typemap (jtype) std::auto_ptr< TYPE > "long" %typemap (jstype) std::auto_ptr< TYPE > "$typemap(jstype, TYPE)" +%typemap(in) std::auto_ptr< TYPE > (TYPE *auto_temp) +%{ auto_temp = *(TYPE **)&$input; + $1.reset(auto_temp); %} + +%typemap(javain) std::auto_ptr< TYPE > "$typemap(jstype, TYPE).swigRelease($javainput)" + %typemap (out) std::auto_ptr< TYPE > %{ - jlong lpp = 0; - *(TYPE **) &lpp = $1.release(); - $result = lpp; + jlong lpp = 0; + *(TYPE **) &lpp = $1.release(); + $result = lpp; %} + %typemap(javaout) std::auto_ptr< TYPE > { - long cPtr = $jnicall; - return (cPtr == 0) ? null : new $typemap(jstype, TYPE)(cPtr, true); - } + long cPtr = $jnicall; + return (cPtr == 0) ? null : new $typemap(jstype, TYPE)(cPtr, true); + } + %template() std::auto_ptr< TYPE >; %enddef namespace std { - template class auto_ptr {}; -} + template class auto_ptr {}; +} diff --git a/Lib/perl5/std_auto_ptr.i b/Lib/perl5/std_auto_ptr.i index ecaea2b0f..d062886e4 100644 --- a/Lib/perl5/std_auto_ptr.i +++ b/Lib/perl5/std_auto_ptr.i @@ -1,19 +1,33 @@ /* ----------------------------------------------------------------------------- * std_auto_ptr.i * - * The typemaps here allow handling functions returning std::auto_ptr<>, - * which is the most common use of this type. If you have functions taking it - * as parameter, these typemaps can't be used for them and you need to do - * something else (e.g. use shared_ptr<> which SWIG supports fully). + * SWIG library file for handling std::auto_ptr. + * Memory ownership is passed from the std::auto_ptr C++ layer to the proxy + * class when returning a std::auto_ptr from a function. + * Memory ownership is passed from the proxy class to the std::auto_ptr in the + * C++ layer when passed as a parameter to a wrapped function. * ----------------------------------------------------------------------------- */ %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 | %convertptr_flags); + if (!SWIG_IsOK(res)) { + if (res == SWIG_ERROR_RELEASE_NOT_OWNED) { + %releasenotowned_fail(res, "TYPE *", $symname, $argnum); + } else { + %argument_fail(res, "TYPE *", $symname, $argnum); + } + } + $1.reset((TYPE *)argp); +} + %typemap (out) std::auto_ptr< TYPE > %{ - %set_output(SWIG_NewPointerObj($1.release(), $descriptor(TYPE *), SWIG_POINTER_OWN | %newpointer_flags)); + %set_output(SWIG_NewPointerObj($1.release(), $descriptor(TYPE *), SWIG_POINTER_OWN | %newpointer_flags)); %} + %template() std::auto_ptr< TYPE >; %enddef namespace std { - template class auto_ptr {}; + template class auto_ptr {}; } diff --git a/Lib/python/std_auto_ptr.i b/Lib/python/std_auto_ptr.i index fb044f851..d062886e4 100644 --- a/Lib/python/std_auto_ptr.i +++ b/Lib/python/std_auto_ptr.i @@ -1,19 +1,33 @@ /* ----------------------------------------------------------------------------- * std_auto_ptr.i * - * The typemaps here allow handling functions returning std::auto_ptr<>, - * which is the most common use of this type. If you have functions taking it - * as parameter, these typemaps can't be used for them and you need to do - * something else (e.g. use shared_ptr<> which SWIG supports fully). + * SWIG library file for handling std::auto_ptr. + * Memory ownership is passed from the std::auto_ptr C++ layer to the proxy + * class when returning a std::auto_ptr from a function. + * Memory ownership is passed from the proxy class to the std::auto_ptr in the + * C++ layer when passed as a parameter to a wrapped function. * ----------------------------------------------------------------------------- */ %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 | %convertptr_flags); + if (!SWIG_IsOK(res)) { + if (res == SWIG_ERROR_RELEASE_NOT_OWNED) { + %releasenotowned_fail(res, "TYPE *", $symname, $argnum); + } else { + %argument_fail(res, "TYPE *", $symname, $argnum); + } + } + $1.reset((TYPE *)argp); +} + %typemap (out) std::auto_ptr< TYPE > %{ - %set_output(SWIG_NewPointerObj($1.release(), $descriptor(TYPE *), SWIG_POINTER_OWN | %newpointer_flags)); + %set_output(SWIG_NewPointerObj($1.release(), $descriptor(TYPE *), SWIG_POINTER_OWN | %newpointer_flags)); %} + %template() std::auto_ptr< TYPE >; %enddef namespace std { - template class auto_ptr {}; -} + template class auto_ptr {}; +} diff --git a/Lib/ruby/std_auto_ptr.i b/Lib/ruby/std_auto_ptr.i index ecaea2b0f..d062886e4 100644 --- a/Lib/ruby/std_auto_ptr.i +++ b/Lib/ruby/std_auto_ptr.i @@ -1,19 +1,33 @@ /* ----------------------------------------------------------------------------- * std_auto_ptr.i * - * The typemaps here allow handling functions returning std::auto_ptr<>, - * which is the most common use of this type. If you have functions taking it - * as parameter, these typemaps can't be used for them and you need to do - * something else (e.g. use shared_ptr<> which SWIG supports fully). + * SWIG library file for handling std::auto_ptr. + * Memory ownership is passed from the std::auto_ptr C++ layer to the proxy + * class when returning a std::auto_ptr from a function. + * Memory ownership is passed from the proxy class to the std::auto_ptr in the + * C++ layer when passed as a parameter to a wrapped function. * ----------------------------------------------------------------------------- */ %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 | %convertptr_flags); + if (!SWIG_IsOK(res)) { + if (res == SWIG_ERROR_RELEASE_NOT_OWNED) { + %releasenotowned_fail(res, "TYPE *", $symname, $argnum); + } else { + %argument_fail(res, "TYPE *", $symname, $argnum); + } + } + $1.reset((TYPE *)argp); +} + %typemap (out) std::auto_ptr< TYPE > %{ - %set_output(SWIG_NewPointerObj($1.release(), $descriptor(TYPE *), SWIG_POINTER_OWN | %newpointer_flags)); + %set_output(SWIG_NewPointerObj($1.release(), $descriptor(TYPE *), SWIG_POINTER_OWN | %newpointer_flags)); %} + %template() std::auto_ptr< TYPE >; %enddef namespace std { - template class auto_ptr {}; + template class auto_ptr {}; } From 892557e799f37f168fd91e3c220a1061d6889458 Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Tue, 19 Jul 2022 08:14:07 +1200 Subject: [PATCH 532/662] Improve #include guard macros Avoid using reserved identifiers such as `_DOHINT_H` (fixes #1989), fix cases where the name doesn't match the filename, and make the naming more consistent and less likely to collide with include guards in other headers. --- Doc/Manual/Preprocessor.html | 6 +++--- Examples/javascript/nspace/example.h | 4 ++-- Examples/lua/nspace/example.h | 4 ++-- Examples/ruby/free_function/example.h | 6 +++--- Examples/ruby/mark_function/example.h | 6 +++--- Examples/test-suite/refcount.h | 6 +++--- Examples/test-suite/template_typedef_cplx2.h | 6 +++--- Lib/allkw.swg | 6 +++--- Lib/octave/octheaders.hpp | 6 +++--- Source/CParse/cparse.h | 4 ++-- Source/DOH/doh.h | 6 +++--- Source/DOH/dohint.h | 6 +++--- Source/Doxygen/doxyentity.h | 4 ++-- Source/Doxygen/doxyparser.h | 4 ++-- Source/Doxygen/doxytranslator.h | 4 ++-- Source/Doxygen/javadoc.h | 4 ++-- Source/Doxygen/pydoc.h | 4 ++-- Source/Include/swigwarn.h | 4 ++-- Source/Modules/swigmod.h | 4 ++-- Source/Preprocessor/preprocessor.h | 4 ++-- Source/Swig/swig.h | 4 ++-- 21 files changed, 51 insertions(+), 51 deletions(-) diff --git a/Doc/Manual/Preprocessor.html b/Doc/Manual/Preprocessor.html index c5043aaed..0d5cc6300 100644 --- a/Doc/Manual/Preprocessor.html +++ b/Doc/Manual/Preprocessor.html @@ -189,15 +189,15 @@ is also used to try and detect constants. Therefore, if you have something like
    -#ifndef _FOO_H 1
    -#define _FOO_H 1
    +#ifndef FOO_H 1
    +#define FOO_H 1
     ...
     #endif
     

    -you may get some extra constants such as _FOO_H showing up in the scripting interface. +you may get some extra constants such as FOO_H showing up in the scripting interface.

    diff --git a/Examples/javascript/nspace/example.h b/Examples/javascript/nspace/example.h index 53066980a..b2e46e95c 100644 --- a/Examples/javascript/nspace/example.h +++ b/Examples/javascript/nspace/example.h @@ -1,5 +1,5 @@ -#ifndef _example_guardian_ -#define _example_guardian_ +#ifndef EXAMPLE_H +#define EXAMPLE_H int module_function() { return 7; } int module_variable = 9; diff --git a/Examples/lua/nspace/example.h b/Examples/lua/nspace/example.h index 53066980a..b2e46e95c 100644 --- a/Examples/lua/nspace/example.h +++ b/Examples/lua/nspace/example.h @@ -1,5 +1,5 @@ -#ifndef _example_guardian_ -#define _example_guardian_ +#ifndef EXAMPLE_H +#define EXAMPLE_H int module_function() { return 7; } int module_variable = 9; diff --git a/Examples/ruby/free_function/example.h b/Examples/ruby/free_function/example.h index 933bb3645..c709cdec1 100644 --- a/Examples/ruby/free_function/example.h +++ b/Examples/ruby/free_function/example.h @@ -1,5 +1,5 @@ -#ifndef _EXAMPLE_H_ -#define _EXAMPLE_H_ +#ifndef EXAMPLE_H +#define EXAMPLE_H #include #include @@ -46,4 +46,4 @@ public: Animal* get_animal(size_t i) const; }; -#endif /*_EXAMPLE_H_*/ +#endif /* EXAMPLE_H */ diff --git a/Examples/ruby/mark_function/example.h b/Examples/ruby/mark_function/example.h index 933bb3645..c709cdec1 100644 --- a/Examples/ruby/mark_function/example.h +++ b/Examples/ruby/mark_function/example.h @@ -1,5 +1,5 @@ -#ifndef _EXAMPLE_H_ -#define _EXAMPLE_H_ +#ifndef EXAMPLE_H +#define EXAMPLE_H #include #include @@ -46,4 +46,4 @@ public: Animal* get_animal(size_t i) const; }; -#endif /*_EXAMPLE_H_*/ +#endif /* EXAMPLE_H */ diff --git a/Examples/test-suite/refcount.h b/Examples/test-suite/refcount.h index 7d07e7242..f3ebbf2ec 100644 --- a/Examples/test-suite/refcount.h +++ b/Examples/test-suite/refcount.h @@ -1,5 +1,5 @@ -#ifndef TEST_SUITE_REFCOUNT_H__ -#define TEST_SUITE_REFCOUNT_H__ +#ifndef TEST_SUITE_REFCOUNT_H +#define TEST_SUITE_REFCOUNT_H struct RCObjBase { /*! @@ -195,4 +195,4 @@ RCPtr& RCPtr::operator=(const RCPtr& rhs) -#endif //TEST_SUITE_REFCOUNT_H__ +#endif // TEST_SUITE_REFCOUNT_H diff --git a/Examples/test-suite/template_typedef_cplx2.h b/Examples/test-suite/template_typedef_cplx2.h index a6ee3c673..a23c319c1 100644 --- a/Examples/test-suite/template_typedef_cplx2.h +++ b/Examples/test-suite/template_typedef_cplx2.h @@ -1,5 +1,5 @@ -#ifndef ___typedef_import_h__ -#define ___typedef_import_h__ +#ifndef TEMPLATE_TYPEDEF_CPLX2_H +#define TEMPLATE_TYPEDEF_CPLX2_H #ifdef SWIG %module template_typedef_cplx2; @@ -174,4 +174,4 @@ namespace vfncs { #endif -#endif //___template_typedef_h__ +#endif // TEMPLATE_TYPEDEF_CPLX2_H diff --git a/Lib/allkw.swg b/Lib/allkw.swg index 2d3cf6ea9..5e4cb8308 100644 --- a/Lib/allkw.swg +++ b/Lib/allkw.swg @@ -1,5 +1,5 @@ -#ifndef __Lib_allkw_swg__ -#define __Lib_allkw_swg__ +#ifndef SWIG_INCLUDED_LIB_ALLKW_SWG +#define SWIG_INCLUDED_LIB_ALLKW_SWG /* @@ -30,4 +30,4 @@ %include -#endif //__Lib_allkw_swg__ +#endif // SWIG_INCLUDED_LIB_ALLKW_SWG diff --git a/Lib/octave/octheaders.hpp b/Lib/octave/octheaders.hpp index abf6428e7..26e5564d4 100644 --- a/Lib/octave/octheaders.hpp +++ b/Lib/octave/octheaders.hpp @@ -9,8 +9,8 @@ // g++ -c -include octheaders.hpp ... // -#if !defined(_SWIG_OCTAVE_OCTHEADERS_HPP) -#define _SWIG_OCTAVE_OCTHEADERS_HPP +#if !defined(SWIG_OCTAVE_OCTHEADERS_HPP) +#define SWIG_OCTAVE_OCTHEADERS_HPP // Required C++ headers #include @@ -127,4 +127,4 @@ #include #endif -#endif // !defined(_SWIG_OCTAVE_OCTHEADERS_HPP) +#endif // !defined(SWIG_OCTAVE_OCTHEADERS_HPP) diff --git a/Source/CParse/cparse.h b/Source/CParse/cparse.h index 0d9ca4b9d..ca8127741 100644 --- a/Source/CParse/cparse.h +++ b/Source/CParse/cparse.h @@ -11,8 +11,8 @@ * SWIG parser module. * ----------------------------------------------------------------------------- */ -#ifndef SWIG_CPARSE_H_ -#define SWIG_CPARSE_H_ +#ifndef SWIG_CPARSE_H +#define SWIG_CPARSE_H #include "swig.h" #include "swigwarn.h" diff --git a/Source/DOH/doh.h b/Source/DOH/doh.h index af6b99664..7631e4ed4 100644 --- a/Source/DOH/doh.h +++ b/Source/DOH/doh.h @@ -11,8 +11,8 @@ * This file describes of the externally visible functions in DOH. * ----------------------------------------------------------------------------- */ -#ifndef _DOH_H -#define _DOH_H +#ifndef SWIG_DOH_H +#define SWIG_DOH_H #ifndef MACSWIG #include "swigconfig.h" @@ -503,4 +503,4 @@ extern void DohMemoryDebug(void); # pragma GCC poison abort exit #endif -#endif /* DOH_H */ +#endif /* SWIG_DOH_H */ diff --git a/Source/DOH/dohint.h b/Source/DOH/dohint.h index 87def9d3d..a1974ff76 100644 --- a/Source/DOH/dohint.h +++ b/Source/DOH/dohint.h @@ -11,8 +11,8 @@ * This file describes internally managed objects. * ----------------------------------------------------------------------------- */ -#ifndef _DOHINT_H -#define _DOHINT_H +#ifndef SWIG_DOHINT_H +#define SWIG_DOHINT_H #include "doh.h" @@ -128,4 +128,4 @@ typedef struct { extern DOH *DohObjMalloc(DohObjInfo *type, void *data); /* Allocate a DOH object */ extern void DohObjFree(DOH *ptr); /* Free a DOH object */ -#endif /* DOHINT_H */ +#endif /* SWIG_DOHINT_H */ diff --git a/Source/Doxygen/doxyentity.h b/Source/Doxygen/doxyentity.h index 93737e604..c18a59b53 100644 --- a/Source/Doxygen/doxyentity.h +++ b/Source/Doxygen/doxyentity.h @@ -11,8 +11,8 @@ * Part of the Doxygen comment translation module of SWIG. * ----------------------------------------------------------------------------- */ -#ifndef DOXYGENENTITY_H_ -#define DOXYGENENTITY_H_ +#ifndef SWIG_DOXYENTITY_H +#define SWIG_DOXYENTITY_H #include #include diff --git a/Source/Doxygen/doxyparser.h b/Source/Doxygen/doxyparser.h index 7a7d5c4f2..c099f23dd 100644 --- a/Source/Doxygen/doxyparser.h +++ b/Source/Doxygen/doxyparser.h @@ -9,8 +9,8 @@ * doxyparser.h * ----------------------------------------------------------------------------- */ -#ifndef DOXYGENPARSER_H_ -#define DOXYGENPARSER_H_ +#ifndef SWIG_DOXYPARSER_H +#define SWIG_DOXYPARSER_H #include #include #include diff --git a/Source/Doxygen/doxytranslator.h b/Source/Doxygen/doxytranslator.h index a72a31df6..eb527fc6f 100644 --- a/Source/Doxygen/doxytranslator.h +++ b/Source/Doxygen/doxytranslator.h @@ -12,8 +12,8 @@ * systems. * ----------------------------------------------------------------------------- */ -#ifndef DOXYGENTRANSLATOR_H_ -#define DOXYGENTRANSLATOR_H_ +#ifndef SWIG_DOXYTRANSLATOR_H +#define SWIG_DOXYTRANSLATOR_H #include "swig.h" #include "doxyentity.h" diff --git a/Source/Doxygen/javadoc.h b/Source/Doxygen/javadoc.h index 6feff5295..6459f05a3 100644 --- a/Source/Doxygen/javadoc.h +++ b/Source/Doxygen/javadoc.h @@ -11,8 +11,8 @@ * Module to return documentation for nodes formatted for JavaDoc * ----------------------------------------------------------------------------- */ -#ifndef JAVADOCCONVERTER_H_ -#define JAVADOCCONVERTER_H_ +#ifndef SWIG_JAVADOC_H +#define SWIG_JAVADOC_H #include "doxytranslator.h" #include diff --git a/Source/Doxygen/pydoc.h b/Source/Doxygen/pydoc.h index 19885276f..8b35d5b62 100644 --- a/Source/Doxygen/pydoc.h +++ b/Source/Doxygen/pydoc.h @@ -11,8 +11,8 @@ * Module to return documentation for nodes formatted for PyDoc * ----------------------------------------------------------------------------- */ -#ifndef PYDOCCONVERTER_H_ -#define PYDOCCONVERTER_H_ +#ifndef SWIG_PYDOC_H +#define SWIG_PYDOC_H #include #include diff --git a/Source/Include/swigwarn.h b/Source/Include/swigwarn.h index 8755f2ab5..f37cb0ef2 100644 --- a/Source/Include/swigwarn.h +++ b/Source/Include/swigwarn.h @@ -22,8 +22,8 @@ * This file is used as the input for generating Lib/swigwarn.swg. * ----------------------------------------------------------------------------- */ -#ifndef SWIGWARN_H_ -#define SWIGWARN_H_ +#ifndef SWIG_SWIGWARN_H +#define SWIG_SWIGWARN_H #define WARN_NONE 0 diff --git a/Source/Modules/swigmod.h b/Source/Modules/swigmod.h index de6ee48ef..c36b49bdf 100644 --- a/Source/Modules/swigmod.h +++ b/Source/Modules/swigmod.h @@ -11,8 +11,8 @@ * Main header file for SWIG modules. * ----------------------------------------------------------------------------- */ -#ifndef SWIG_SWIGMOD_H_ -#define SWIG_SWIGMOD_H_ +#ifndef SWIG_SWIGMOD_H +#define SWIG_SWIGMOD_H #include "swig.h" #include "preprocessor.h" diff --git a/Source/Preprocessor/preprocessor.h b/Source/Preprocessor/preprocessor.h index 4c24f48d0..e0fb8194c 100644 --- a/Source/Preprocessor/preprocessor.h +++ b/Source/Preprocessor/preprocessor.h @@ -11,8 +11,8 @@ * SWIG preprocessor module. * ----------------------------------------------------------------------------- */ -#ifndef SWIG_PREPROCESSOR_H_ -#define SWIG_PREPROCESSOR_H_ +#ifndef SWIG_PREPROCESSOR_H +#define SWIG_PREPROCESSOR_H #include "swigwarn.h" diff --git a/Source/Swig/swig.h b/Source/Swig/swig.h index e9689afd9..bf1ca33d5 100644 --- a/Source/Swig/swig.h +++ b/Source/Swig/swig.h @@ -11,8 +11,8 @@ * Header file for the SWIG core. * ----------------------------------------------------------------------------- */ -#ifndef SWIGCORE_H_ -#define SWIGCORE_H_ +#ifndef SWIG_SWIG_H +#define SWIG_SWIG_H #ifndef MACSWIG #include "swigconfig.h" From 6b4d5fe3f0846d698e10475b6e656896979548bd Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Tue, 19 Jul 2022 08:20:32 +1200 Subject: [PATCH 533/662] Remove remaining code to support macos9 This OS has been unsupported for over 20 years. We stopped providing macswig builds more than 20 years ago too: https://sourceforge.net/projects/swig/files/macswig/ The required SIOUX library doesn't seem to be available anywhere now either. Closes #2323 --- CHANGES.current | 4 + Lib/tcl/mactkinit.c | 233 ------------------------------------ Lib/tcl/tclsh.i | 22 +--- Lib/tcl/wish.i | 33 +---- Source/DOH/doh.h | 2 - Source/Modules/swigmain.cxx | 10 -- Source/Swig/include.c | 4 - Source/Swig/misc.c | 2 +- Source/Swig/swig.h | 2 - Source/Swig/swigfile.h | 4 +- 10 files changed, 9 insertions(+), 307 deletions(-) delete mode 100644 Lib/tcl/mactkinit.c diff --git a/CHANGES.current b/CHANGES.current index e312abaaa..645776f5c 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-07-19: olly + Remove remaining support code for classic macos, which has not been + supported by Apple for over 20 years now. + 2022-07-12: wsfulton Performance optimisation for parameters passed by value that are C++11 movable. The C++ wrappers create a temporary variable for a parameter to be passed to a diff --git a/Lib/tcl/mactkinit.c b/Lib/tcl/mactkinit.c deleted file mode 100644 index 18f1f0203..000000000 --- a/Lib/tcl/mactkinit.c +++ /dev/null @@ -1,233 +0,0 @@ -/* ----------------------------------------------------------------------------- - * mactkinit.c - * - * This is a support file needed to build a new version of Wish. - * Normally, this capability is found in TkAppInit.c, but this creates - * tons of namespace problems for many applications. - * ----------------------------------------------------------------------------- */ - -#include -#include -#include -#include -#include -#include - -#include "tk.h" -#include "tkInt.h" -#include "tkMacInt.h" - -typedef int (*TclMacConvertEventPtr) _ANSI_ARGS_((EventRecord *eventPtr)); -Tcl_Interp *gStdoutInterp = NULL; - -void TclMacSetEventProc _ANSI_ARGS_((TclMacConvertEventPtr procPtr)); -int TkMacConvertEvent _ANSI_ARGS_((EventRecord *eventPtr)); - -/* - * Prototypes for functions the ANSI library needs to link against. - */ -short InstallConsole _ANSI_ARGS_((short fd)); -void RemoveConsole _ANSI_ARGS_((void)); -long WriteCharsToConsole _ANSI_ARGS_((char *buff, long n)); -long ReadCharsFromConsole _ANSI_ARGS_((char *buff, long n)); -char * __ttyname _ANSI_ARGS_((long fildes)); -short SIOUXHandleOneEvent _ANSI_ARGS_((EventRecord *event)); - -/* - * Forward declarations for procedures defined later in this file: - */ - -/* - *---------------------------------------------------------------------- - * - * MacintoshInit -- - * - * This procedure calls Mac specific initialization calls. Most of - * these calls must be made as soon as possible in the startup - * process. - * - * Results: - * Returns TCL_OK if everything went fine. If it didn't the - * application should probably fail. - * - * Side effects: - * Inits the application. - * - *---------------------------------------------------------------------- - */ - -int -MacintoshInit() -{ - int i; - long result, mask = 0x0700; /* mask = system 7.x */ - - /* - * Tk needs us to set the qd pointer it uses. This is needed - * so Tk doesn't have to assume the availiblity of the qd global - * variable. Which in turn allows Tk to be used in code resources. - */ - tcl_macQdPtr = &qd; - - InitGraf(&tcl_macQdPtr->thePort); - InitFonts(); - InitWindows(); - InitMenus(); - InitDialogs((long) NULL); - InitCursor(); - - /* - * Make sure we are running on system 7 or higher - */ - - if ((NGetTrapAddress(_Gestalt, ToolTrap) == - NGetTrapAddress(_Unimplemented, ToolTrap)) - || (((Gestalt(gestaltSystemVersion, &result) != noErr) - || (mask != (result & mask))))) { - panic("Tcl/Tk requires System 7 or higher."); - } - - /* - * Make sure we have color quick draw - * (this means we can't run on 68000 macs) - */ - - if (((Gestalt(gestaltQuickdrawVersion, &result) != noErr) - || (result < gestalt32BitQD13))) { - panic("Tk requires Color QuickDraw."); - } - - - FlushEvents(everyEvent, 0); - SetEventMask(everyEvent); - - /* - * Set up stack & heap sizes - */ - /* TODO: stack size - size = StackSpace(); - SetAppLimit(GetAppLimit() - 8192); - */ - MaxApplZone(); - for (i = 0; i < 4; i++) { - (void) MoreMasters(); - } - - TclMacSetEventProc(TkMacConvertEvent); - TkConsoleCreate(); - - return TCL_OK; -} - -/* - *---------------------------------------------------------------------- - * - * SetupMainInterp -- - * - * This procedure calls initialization routines require a Tcl - * interp as an argument. This call effectively makes the passed - * interpreter the "main" interpreter for the application. - * - * Results: - * Returns TCL_OK if everything went fine. If it didn't the - * application should probably fail. - * - * Side effects: - * More initialization. - * - *---------------------------------------------------------------------- - */ - -int -SetupMainInterp( - Tcl_Interp *interp) -{ - /* - * Initialize the console only if we are running as an interactive - * application. - */ - - TkMacInitAppleEvents(interp); - TkMacInitMenus(interp); - - if (strcmp(Tcl_GetVar(interp, "tcl_interactive", TCL_GLOBAL_ONLY), "1") - == 0) { - if (TkConsoleInit(interp) == TCL_ERROR) { - goto error; - } - } - - /* - * Attach the global interpreter to tk's expected global console - */ - - gStdoutInterp = interp; - - return TCL_OK; - -error: - panic(interp->result); - return TCL_ERROR; -} - -/* - *---------------------------------------------------------------------- - * - * InstallConsole, RemoveConsole, etc. -- - * - * The following functions provide the UI for the console package. - * Users wishing to replace SIOUX with their own console package - * need only provide the four functions below in a library. - * - * Results: - * See SIOUX documentation for details. - * - * Side effects: - * See SIOUX documentation for details. - * - *---------------------------------------------------------------------- - */ - -short -InstallConsole(short fd) -{ -#pragma unused (fd) - - return 0; -} - -void -RemoveConsole(void) -{ -} - -long -WriteCharsToConsole(char *buffer, long n) -{ - TkConsolePrint(gStdoutInterp, TCL_STDOUT, buffer, n); - return n; -} - -long -ReadCharsFromConsole(char *buffer, long n) -{ - return 0; -} - -extern char * -__ttyname(long fildes) -{ - static char *devicename = "null device"; - - if (fildes >= 0 && fildes <= 2) { - return (devicename); - } - - return (0L); -} - -short -SIOUXHandleOneEvent(EventRecord *event) -{ - return 0; -} diff --git a/Lib/tcl/tclsh.i b/Lib/tcl/tclsh.i index a119b93ac..21dc35af3 100644 --- a/Lib/tcl/tclsh.i +++ b/Lib/tcl/tclsh.i @@ -33,10 +33,6 @@ char *SWIG_RcFileName = "~/.myapprc"; #endif -#ifdef MAC_TCL -extern int MacintoshInit _ANSI_ARGS_((void)); -#endif - int Tcl_AppInit(Tcl_Interp *interp){ if (Tcl_Init(interp) == TCL_ERROR) @@ -47,27 +43,11 @@ int Tcl_AppInit(Tcl_Interp *interp){ if (SWIG_init(interp) == TCL_ERROR) return TCL_ERROR; Tcl_SetVar(interp, (char *) "tcl_rcFileName",SWIG_RcFileName,TCL_GLOBAL_ONLY); -#ifdef SWIG_RcRsrcName - Tcl_SetVar(interp, (char *) "tcl_rcRsrcName",SWIG_RcRsrcName,TCL_GLOBAL); -#endif - + return TCL_OK; } int main(int argc, char **argv) { -#ifdef MAC_TCL - char *newArgv[2]; - - if (MacintoshInit() != TCL_OK) { - Tcl_Exit(1); - } - - argc = 1; - newArgv[0] = "tclsh"; - newArgv[1] = NULL; - argv = newArgv; -#endif - Tcl_Main(argc, argv, Tcl_AppInit); return(0); diff --git a/Lib/tcl/wish.i b/Lib/tcl/wish.i index bfd2c5fa9..42902850d 100644 --- a/Lib/tcl/wish.i +++ b/Lib/tcl/wish.i @@ -35,11 +35,6 @@ as follows (this should be included in a code-block) : char *SWIG_RcFileName = "~/.wishrc"; #endif -#ifdef MAC_TCL -extern int MacintoshInit _ANSI_ARGS_((void)); -extern int SetupMainInterp _ANSI_ARGS_((Tcl_Interp *interp)); -#endif - /* *---------------------------------------------------------------------- * @@ -61,10 +56,9 @@ extern int SetupMainInterp _ANSI_ARGS_((Tcl_Interp *interp)); int Tcl_AppInit(Tcl_Interp *interp) { -#ifndef MAC_TCL Tk_Window main; main = Tk_MainWindow(interp); -#endif + /* * Call the init procedures for included packages. Each call should * look like this: @@ -93,10 +87,6 @@ int Tcl_AppInit(Tcl_Interp *interp) return TCL_ERROR; } -#ifdef MAC_TCL - SetupMainInterp(interp); -#endif - /* * Specify a user-specific startup file to invoke if the application * is run interactively. Typically the startup file is "~/.apprc" @@ -104,31 +94,12 @@ int Tcl_AppInit(Tcl_Interp *interp) * then no user-specific startup file will be run under any conditions. */ - Tcl_SetVar(interp, (char *) "tcl_rcFileName",SWIG_RcFileName,TCL_GLOBAL_ONLY); - -/* For Macintosh might also want this */ - -#ifdef MAC_TCL -#ifdef SWIG_RcRsrcName - Tcl_SetVar(interp, (char *) "tcl_rcRsrcName",SWIG_RcRsrcName,TCL_GLOBAL_ONLY); -#endif -#endif + Tcl_SetVar(interp, (char *) "tcl_rcFileName",SWIG_RcFileName,TCL_GLOBAL_ONLY); return TCL_OK; } #if TK_MAJOR_VERSION >= 4 int main(int argc, char **argv) { - -#ifdef MAC_TCL - char *newArgv[2]; - if (MacintoshInit() != TCL_OK) { - Tcl_Exit(1); - } - argc = 1; - newArgv[0] = "Wish"; - newArgv[1] = NULL; - argv = newArgv; -#endif Tk_Main(argc, argv, Tcl_AppInit); return(0); } diff --git a/Source/DOH/doh.h b/Source/DOH/doh.h index 7631e4ed4..4ee0dfffa 100644 --- a/Source/DOH/doh.h +++ b/Source/DOH/doh.h @@ -14,9 +14,7 @@ #ifndef SWIG_DOH_H #define SWIG_DOH_H -#ifndef MACSWIG #include "swigconfig.h" -#endif #include #include diff --git a/Source/Modules/swigmain.cxx b/Source/Modules/swigmain.cxx index 7cb2c2398..6c8852adb 100644 --- a/Source/Modules/swigmain.cxx +++ b/Source/Modules/swigmain.cxx @@ -84,11 +84,6 @@ static TargetLanguageModule modules[] = { {NULL, NULL, NULL, Disabled} }; -#ifdef MACSWIG -#include -#include -#endif - //----------------------------------------------------------------- // main() // @@ -222,11 +217,6 @@ int main(int margc, char **margv) { SWIG_merge_envopt(getenv("SWIG_FEATURES"), margc, margv, &argc, &argv); merge_options_files(&argc, &argv); -#ifdef MACSWIG - SIOUXSettings.asktosaveonclose = false; - argc = ccommand(&argv); -#endif - Swig_init_args(argc, argv); /* Get options */ diff --git a/Source/Swig/include.c b/Source/Swig/include.c index ca43dbd65..a474d0458 100644 --- a/Source/Swig/include.c +++ b/Source/Swig/include.c @@ -110,11 +110,7 @@ static List *Swig_search_path_any(int syspath) { assert(slist); filename = NewStringEmpty(); assert(filename); -#ifdef MACSWIG - Printf(filename, "%s", SWIG_FILE_DELIMITER); -#else Printf(filename, ".%s", SWIG_FILE_DELIMITER); -#endif Append(slist, filename); Delete(filename); diff --git a/Source/Swig/misc.c b/Source/Swig/misc.c index 55306b1da..da7d1d0e3 100644 --- a/Source/Swig/misc.c +++ b/Source/Swig/misc.c @@ -218,7 +218,7 @@ void Swig_filename_correct(String *filename) { if (fname[0] == '/' && fname[1] == '/') network_path = 1; } -#if defined(_WIN32) || defined(MACSWIG) +#if defined(_WIN32) /* accept Unix path separator on non-Unix systems */ Replaceall(filename, "/", SWIG_FILE_DELIMITER); #endif diff --git a/Source/Swig/swig.h b/Source/Swig/swig.h index bf1ca33d5..b27e26330 100644 --- a/Source/Swig/swig.h +++ b/Source/Swig/swig.h @@ -14,9 +14,7 @@ #ifndef SWIG_SWIG_H #define SWIG_SWIG_H -#ifndef MACSWIG #include "swigconfig.h" -#endif #include #include diff --git a/Source/Swig/swigfile.h b/Source/Swig/swigfile.h index 0583b3792..653ada2f7 100644 --- a/Source/Swig/swigfile.h +++ b/Source/Swig/swigfile.h @@ -34,9 +34,7 @@ extern void Swig_file_debug_set(void); /* Delimiter used in accessing files and directories */ -#if defined(MACSWIG) -# define SWIG_FILE_DELIMITER ":" -#elif defined(_WIN32) +#if defined(_WIN32) # define SWIG_FILE_DELIMITER "\\" #else # define SWIG_FILE_DELIMITER "/" From a55d40dbb5eee8f0c1b360d27820d50463dbe8aa Mon Sep 17 00:00:00 2001 From: Julien Schueller Date: Mon, 18 Jul 2022 11:01:31 +0200 Subject: [PATCH 534/662] Drop support for Python 3.2 Closes #2314 --- .github/workflows/ci.yml | 4 ---- Lib/python/pyrun.swg | 4 ++-- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ac63a863e..69871b7d5 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -111,10 +111,6 @@ jobs: VER: '8.1' - SWIGLANG: python PY2: 2 - - SWIGLANG: python - VER: '3.2' - os: ubuntu-18.04 # Python < 3.5 not available for 20.04. - continue-on-error: true # broken packages problem - SWIGLANG: python VER: '3.3' os: ubuntu-18.04 # Python < 3.5 not available for 20.04. diff --git a/Lib/python/pyrun.swg b/Lib/python/pyrun.swg index 935885934..baaac8795 100644 --- a/Lib/python/pyrun.swg +++ b/Lib/python/pyrun.swg @@ -11,8 +11,8 @@ # error "This version of SWIG only supports Python >= 2.7" #endif -#if PY_VERSION_HEX >= 0x03000000 && PY_VERSION_HEX < 0x03020000 -# error "This version of SWIG only supports Python 3 >= 3.2" +#if PY_VERSION_HEX >= 0x03000000 && PY_VERSION_HEX < 0x03030000 +# error "This version of SWIG only supports Python 3 >= 3.3" #endif /* Common SWIG API */ From 0b9d4eff09a9d12435e9688842662994ec2b154d Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Tue, 19 Jul 2022 13:20:07 +1200 Subject: [PATCH 535/662] Update everything for dropping Python 3.2 support --- CHANGES.current | 3 +++ Doc/Manual/Python.html | 5 ++-- .../import_packages/module_is_init/runme.py | 8 ------ Lib/python/pyerrors.swg | 1 - Lib/python/pyhead.swg | 25 +++---------------- Lib/python/pyrun.swg | 2 -- RELEASENOTES | 1 + 7 files changed, 9 insertions(+), 36 deletions(-) diff --git a/CHANGES.current b/CHANGES.current index 645776f5c..977fea758 100644 --- a/CHANGES.current +++ b/CHANGES.current @@ -7,6 +7,9 @@ the issue number to the end of the URL: https://github.com/swig/swig/issues/ Version 4.1.0 (in progress) =========================== +2022-07-19: jschueller + [Python] #2314 Drop support for Python 3.2. + 2022-07-19: olly Remove remaining support code for classic macos, which has not been supported by Apple for over 20 years now. diff --git a/Doc/Manual/Python.html b/Doc/Manual/Python.html index ce6ed2877..0496299eb 100644 --- a/Doc/Manual/Python.html +++ b/Doc/Manual/Python.html @@ -156,9 +156,8 @@

    This chapter describes SWIG's support of Python. SWIG is compatible -with all recent Python versions (Python 2.7 and Python >= 3.2). If you -still need to generate bindings which work with older versions of Python, -you'll have to use SWIG 3.0.x. +with all recent Python versions (Python 2.7 and Python >= 3.3). SWIG 4.0.x +supported Python 3.2. SWIG 3.0.x supported older Python 2.x and 3.x.

    diff --git a/Examples/python/import_packages/module_is_init/runme.py b/Examples/python/import_packages/module_is_init/runme.py index c4806cdf8..42d48995e 100644 --- a/Examples/python/import_packages/module_is_init/runme.py +++ b/Examples/python/import_packages/module_is_init/runme.py @@ -5,14 +5,6 @@ import sys testname = os.path.basename(os.path.dirname(os.path.abspath(__file__))) print("Testing " + testname + " - module renamed as __init__.py") -if sys.version_info >= (3, 0, 0) and sys.version_info < (3, 3, 0): - print(" Not importing as Python version is >= 3.0 and < 3.3") - # Package detection does not work in these versions. - # Can be fixed by using this in the interface file: - # %module(moduleimport="from . import $module") foo # without -builtin - # %module(moduleimport="from .$module import *") foo # with -builtin - sys.exit(0) - import pkg1 print(" Finished importing pkg1") diff --git a/Lib/python/pyerrors.swg b/Lib/python/pyerrors.swg index 2628de8e6..10b694cde 100644 --- a/Lib/python/pyerrors.swg +++ b/Lib/python/pyerrors.swg @@ -64,7 +64,6 @@ SWIG_Python_AddErrorMsg(const char* mesg) PyErr_Format(type, "%s %s", tmp, mesg); else PyErr_Format(type, "%s", mesg); - SWIG_Python_str_DelForPy3(tmp); Py_DECREF(old_str); Py_DECREF(value); } else { diff --git a/Lib/python/pyhead.swg b/Lib/python/pyhead.swg index d3730a8fa..6f37160bb 100644 --- a/Lib/python/pyhead.swg +++ b/Lib/python/pyhead.swg @@ -30,38 +30,19 @@ #endif -/* Warning: This function will allocate a new string in Python 3, - * so please call SWIG_Python_str_DelForPy3(x) to free the space. - */ SWIGINTERN char* SWIG_Python_str_AsChar(PyObject *str) { #if PY_VERSION_HEX >= 0x03030000 return (char *)PyUnicode_AsUTF8(str); -#elif PY_VERSION_HEX >= 0x03000000 - char *newstr = 0; - str = PyUnicode_AsUTF8String(str); - if (str) { - char *cstr; - Py_ssize_t len; - if (PyBytes_AsStringAndSize(str, &cstr, &len) != -1) { - newstr = (char *) malloc(len+1); - if (newstr) - memcpy(newstr, cstr, len+1); - } - Py_XDECREF(str); - } - return newstr; #else return PyString_AsString(str); #endif } -#if PY_VERSION_HEX >= 0x03030000 || PY_VERSION_HEX < 0x03000000 -# define SWIG_Python_str_DelForPy3(x) -#else -# define SWIG_Python_str_DelForPy3(x) free( (void*) (x) ) -#endif +/* Was useful for Python 3.0.x-3.2.x - now provided only for compatibility + * with any uses in user interface files. */ +#define SWIG_Python_str_DelForPy3(x) SWIGINTERN PyObject* diff --git a/Lib/python/pyrun.swg b/Lib/python/pyrun.swg index baaac8795..a74843bf1 100644 --- a/Lib/python/pyrun.swg +++ b/Lib/python/pyrun.swg @@ -1758,7 +1758,6 @@ SWIG_Python_AddErrMesg(const char* mesg, int infront) } else { PyErr_Format(type, "%s %s", errmesg, mesg); } - SWIG_Python_str_DelForPy3(tmp); Py_DECREF(old_str); } return 1; @@ -1810,7 +1809,6 @@ SWIG_Python_TypeError(const char *type, PyObject *obj) if (cstr) { PyErr_Format(PyExc_TypeError, "a '%s' is expected, '%s(%s)' is received", type, otype, cstr); - SWIG_Python_str_DelForPy3(cstr); } else { PyErr_Format(PyExc_TypeError, "a '%s' is expected, '%s' is received", type, otype); diff --git a/RELEASENOTES b/RELEASENOTES index 2fad03096..33f7e4c45 100644 --- a/RELEASENOTES +++ b/RELEASENOTES @@ -11,6 +11,7 @@ SWIG-4.1.0 summary: - Add PHP 8 support. - PHP wrapping is now done entirely via PHP's C API - no more .php wrapper. - Perl 5.8.0 is now the oldest version SWIG supports. +- Python 3.3 is now the oldest Python 3 version SWIG supports. - Common cases of `<` and `>` comparisons in constant expressions are now supported. - GitHub Actions is now used instead of Travis CI for continuous integration. From 1b63af0f2c3d28bbaaa8856d7046b0b22c898609 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Tue, 19 Jul 2022 08:57:47 +0100 Subject: [PATCH 536/662] std::unique_ptr std::auto_ptr tidyup Add docs on additional support Additional testing for invalid usage for parameter inputs --- CHANGES.current | 8 ++ Doc/Manual/Library.html | 73 ++++++++++++++++--- .../csharp/cpp11_std_unique_ptr_runme.cs | 14 ++-- .../csharp/li_std_auto_ptr_runme.cs | 14 ++-- .../java/cpp11_std_unique_ptr_runme.java | 4 + .../java/li_std_auto_ptr_runme.java | 4 + .../python/cpp11_std_unique_ptr_runme.py | 2 + .../python/li_std_auto_ptr_runme.py | 2 + .../ruby/cpp11_std_unique_ptr_runme.rb | 5 +- .../test-suite/ruby/li_std_auto_ptr_runme.rb | 3 + 10 files changed, 107 insertions(+), 22 deletions(-) diff --git a/CHANGES.current b/CHANGES.current index e312abaaa..3ed3a94a5 100644 --- a/CHANGES.current +++ b/CHANGES.current @@ -7,6 +7,14 @@ the issue number to the end of the URL: https://github.com/swig/swig/issues/ Version 4.1.0 (in progress) =========================== +2022-07-19: wsfulton + #692 [C#, Java, Perl, Python, Ruby] std::unique_ptr and std::auto_ptr typemaps + provided for inputs types in std_unique_ptr.i and std_auto_ptr.i. + + Now these smart pointers can be used as input parameters to functions. A proxy + class instance transfers memory ownership of the underlying C++ object from the + proxy class to a smart pointer instance passed to the wrapped function. + 2022-07-12: wsfulton Performance optimisation for parameters passed by value that are C++11 movable. The C++ wrappers create a temporary variable for a parameter to be passed to a diff --git a/Doc/Manual/Library.html b/Doc/Manual/Library.html index b18ecc957..7dc649c16 100644 --- a/Doc/Manual/Library.html +++ b/Doc/Manual/Library.html @@ -2055,13 +2055,9 @@ equivalent %shared_ptr(T) macro covered in the previous section.

    -Note that the support provided is limited to returning this smart pointer from a function. -Any other use of std::auto_ptr is not directly provided yet. +Example usage of a std::unique_ptr being returned from a function is shown below.

    -

    -Example usage would be -

     %include <std_unique_ptr.i>
    @@ -2113,12 +2109,67 @@ Note that the implementation is quite different to the std::shared_ptr
     where the proxy class manages the underlying C++ memory as a pointer to a shared_ptr instead of a plain raw pointer.
     

    +

    +A possibly less common usage of this smart pointer is as a parameter to a function. +When used like this it indicates that memory usage of the object pointed to by the underlying pointer +is transferred to the function being called. +The code that SWIG generates assumes this happens. +First, it is assumed that a proxy class already owns the underlying C++ object and is used to pass the object to the C++ function being called. +Second, the ownership is transferred from the proxy class to the C++ function being called and +lifetime is then controlled by the function. +Finally, it is assumed the lifetime of the object may not last beyond returning from the C++ function +and hence the proxy class can no longer be used. +

    + +

    +Consider expanding the example above with a function that takes a std::unique_ptr as follows: +

    + +
    +
    +void take(std::unique_ptr);
    +
    +
    + +

    +and use from C#: +

    + +
    +
    +Klass k = Klass.Create(17); // create an instance of Klass any way you like
    +int value = k.getValue();   // ok
    +example.take(k);            // memory ownership passes from C# layer to C++ layer
    +int v = k.getValue();       // don't do this - invalid use of k
    +
    +
    + +

    +Attempts to use k after the ownership has been passed into the take function +should not be attempted. +The implementation sets the proxy class to an invalid state by setting the class's underlying +C++ pointer to null after the return from the take function. +Subsequent use of an invalid proxy class instance is very much dependent on the implementation +in the target language and ranges from a segfault to giving a nice error. +Consider implementing additional checks via the 'check' typemap. +

    + +

    +Attempts to pass ownership from a proxy class to a std::unique parameter more than once will result +in a "Cannot release ownership as memory is not owned" exception. For example, if example.take(k) in the example above is called twice. +

    + +

    +Compatibility note: Support for std::unique_ptr was added in SWIG-4.1.0. +

    +

    12.4.6 auto_ptr smart pointer

    While std::auto_ptr is deprecated in C++11, some existing code may -still be using it, so SWIG provides limited support for this class by some target languages. +still be using it. SWIG provides support for this class which is nearly identical +to std::unique_ptr.

    @@ -2133,13 +2184,9 @@ the previous two sections.

    -Note that the support provided is limited to returning this smart pointer from a function. -Any other use of std::auto_ptr is not directly provided. +Example usage of a std::auto_ptr being returned from a function is shown below.

    -

    -Example usage would be -

     %include <std_auto_ptr.i>
    @@ -2181,6 +2228,10 @@ The implementation simply calls std::auto_ptr::release() to obtain the
     That is, it works the same way covered in the previous section for std::unique_ptr.
     

    +

    +Input parameters also work the same way as std::unique_ptr covered in the previous section. +

    +

    12.5 Utility Libraries

    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 5b730aa05..09c6ec0af 100644 --- a/Examples/test-suite/csharp/cpp11_std_unique_ptr_runme.cs +++ b/Examples/test-suite/csharp/cpp11_std_unique_ptr_runme.cs @@ -41,7 +41,9 @@ public class cpp11_std_unique_ptr_runme { bool exception_thrown = false; try { cpp11_std_unique_ptr.takeKlassUniquePtr(kin); - } catch (ApplicationException) { + } 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) @@ -52,10 +54,12 @@ public class cpp11_std_unique_ptr_runme { using (Klass kin = new Klass("KlassInput")) { bool exception_thrown = false; try { - Klass notowned = cpp11_std_unique_ptr.get_not_owned_ptr(kin); - cpp11_std_unique_ptr.takeKlassUniquePtr(notowned); - } catch (ApplicationException) { - exception_thrown = true; + Klass notowned = cpp11_std_unique_ptr.get_not_owned_ptr(kin); + cpp11_std_unique_ptr.takeKlassUniquePtr(notowned); + } 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"); 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 b804e7ead..b5ff1fd29 100644 --- a/Examples/test-suite/csharp/li_std_auto_ptr_runme.cs +++ b/Examples/test-suite/csharp/li_std_auto_ptr_runme.cs @@ -41,7 +41,9 @@ public class li_std_auto_ptr_runme { bool exception_thrown = false; try { li_std_auto_ptr.takeKlassAutoPtr(kin); - } catch (ApplicationException) { + } 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) @@ -52,10 +54,12 @@ public class li_std_auto_ptr_runme { using (Klass kin = new Klass("KlassInput")) { bool exception_thrown = false; try { - Klass notowned = li_std_auto_ptr.get_not_owned_ptr(kin); - li_std_auto_ptr.takeKlassAutoPtr(notowned); - } catch (ApplicationException) { - exception_thrown = true; + Klass notowned = li_std_auto_ptr.get_not_owned_ptr(kin); + li_std_auto_ptr.takeKlassAutoPtr(notowned); + } 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"); 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 14c117206..36a9c03fc 100644 --- a/Examples/test-suite/java/cpp11_std_unique_ptr_runme.java +++ b/Examples/test-suite/java/cpp11_std_unique_ptr_runme.java @@ -55,6 +55,8 @@ public class cpp11_std_unique_ptr_runme { try { cpp11_std_unique_ptr.takeKlassUniquePtr(kin); } 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) @@ -70,6 +72,8 @@ public class cpp11_std_unique_ptr_runme { Klass notowned = cpp11_std_unique_ptr.get_not_owned_ptr(kin); cpp11_std_unique_ptr.takeKlassUniquePtr(notowned); } 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) 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 40957e974..daec84dc0 100644 --- a/Examples/test-suite/java/li_std_auto_ptr_runme.java +++ b/Examples/test-suite/java/li_std_auto_ptr_runme.java @@ -55,6 +55,8 @@ public class li_std_auto_ptr_runme { try { li_std_auto_ptr.takeKlassAutoPtr(kin); } 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) @@ -70,6 +72,8 @@ public class li_std_auto_ptr_runme { Klass notowned = li_std_auto_ptr.get_not_owned_ptr(kin); li_std_auto_ptr.takeKlassAutoPtr(notowned); } 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) 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 d102ebcd8..d317754b4 100644 --- a/Examples/test-suite/python/cpp11_std_unique_ptr_runme.py +++ b/Examples/test-suite/python/cpp11_std_unique_ptr_runme.py @@ -33,6 +33,8 @@ exception_thrown = False try: s = takeKlassUniquePtr(kin) except RuntimeError as e: + if "cannot release ownership as memory is not owned" not in str(e): + raise RuntimeError("incorrect exception message"); exception_thrown = True if not exception_thrown: raise RuntimeError("double usage of takeKlassUniquePtr should have been an error") 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 3f1d392ea..c1df7eb76 100644 --- a/Examples/test-suite/python/li_std_auto_ptr_runme.py +++ b/Examples/test-suite/python/li_std_auto_ptr_runme.py @@ -33,6 +33,8 @@ exception_thrown = False try: s = takeKlassAutoPtr(kin) except RuntimeError as e: + if "cannot release ownership as memory is not owned" not in str(e): + raise RuntimeError("incorrect exception message"); exception_thrown = True if not exception_thrown: raise RuntimeError("double usage of takeKlassAutoPtr should have been an error") 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 ed9138bcd..83bac5f1b 100644 --- a/Examples/test-suite/ruby/cpp11_std_unique_ptr_runme.rb +++ b/Examples/test-suite/ruby/cpp11_std_unique_ptr_runme.rb @@ -73,7 +73,10 @@ exception_thrown = false begin notowned = Cpp11_std_unique_ptr::get_not_owned_ptr(kin) Cpp11_std_unique_ptr::takeKlassUniquePtr(notowned) -rescue RuntimeError +rescue RuntimeError => e + if (!e.to_s.include? "cannot release ownership as memory is not owned") + raise RuntimeError, "incorrect exception message" + end exception_thrown = true end if (!exception_thrown) 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 14e0bd9d4..6562d8d84 100644 --- a/Examples/test-suite/ruby/li_std_auto_ptr_runme.rb +++ b/Examples/test-suite/ruby/li_std_auto_ptr_runme.rb @@ -74,6 +74,9 @@ begin notowned = Li_std_auto_ptr::get_not_owned_ptr(kin) Li_std_auto_ptr::takeKlassAutoPtr(notowned) rescue RuntimeError + if (!e.to_s.include? "cannot release ownership as memory is not owned") + raise RuntimeError, "incorrect exception message" + end exception_thrown = true end if (!exception_thrown) From 8a03c7d5553256333f0e0b91d41eb55c964f297f Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Wed, 20 Jul 2022 13:00:54 +1200 Subject: [PATCH 537/662] Remove nonsensical comment A testcase can't be a copy of itself. Seems to have been accidentally added in 50fec047596dc540f1a22b8456329b171e0c0b9b. --- Examples/test-suite/multiple_inheritance_abstract.i | 1 - 1 file changed, 1 deletion(-) diff --git a/Examples/test-suite/multiple_inheritance_abstract.i b/Examples/test-suite/multiple_inheritance_abstract.i index 34813a068..aea330d39 100644 --- a/Examples/test-suite/multiple_inheritance_abstract.i +++ b/Examples/test-suite/multiple_inheritance_abstract.i @@ -1,4 +1,3 @@ -// This is a copy of the multiple_inheritance_abstract test %module(ruby_minherit="1") multiple_inheritance_abstract %warnfilter(SWIGWARN_D_MULTIPLE_INHERITANCE, From e23d912b49a91704131bf43915e82f25bbbe942c Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Wed, 20 Jul 2022 13:17:25 +1200 Subject: [PATCH 538/662] [python] Fix inheriting from multiple director classes Fix mishandling of a Python class inheriting from multiple SWIG-wrapped director classes. Fixes #422 Fixes https://sourceforge.net/p/swig/bugs/1379/ --- CHANGES.current | 4 ++ .../director_multiple_inheritance.i | 71 +++++++++++++++++++ .../director_multiple_inheritance_runme.py | 36 ++++++++++ Lib/python/pyrun.swg | 1 + 4 files changed, 112 insertions(+) create mode 100644 Examples/test-suite/director_multiple_inheritance.i create mode 100644 Examples/test-suite/python/director_multiple_inheritance_runme.py diff --git a/CHANGES.current b/CHANGES.current index 72833c7a2..39157d37f 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-07-20: jicks, Ingener74, olly + #422 [Python] Fix mishandling of a Python class inheriting from + multiple SWIG-wrapped director classes. + 2022-07-19: wsfulton #692 [C#, Java, Perl, Python, Ruby] std::unique_ptr and std::auto_ptr typemaps provided for inputs types in std_unique_ptr.i and std_auto_ptr.i. diff --git a/Examples/test-suite/director_multiple_inheritance.i b/Examples/test-suite/director_multiple_inheritance.i new file mode 100644 index 000000000..ff50cfeba --- /dev/null +++ b/Examples/test-suite/director_multiple_inheritance.i @@ -0,0 +1,71 @@ +//%module(ruby_minherit="1") multiple_inheritance +%module(directors="1") director_multiple_inheritance + +%feature("director") A; +%feature("director") B; +%feature("director") C; +%feature("director") D; + +%inline %{ + +class A { +public: + virtual ~A() { } + virtual int testA(); +}; + +class B: virtual public A { +public: + virtual ~B() { } + virtual int testB(); +}; + +class C: virtual public A { +public: + virtual ~C() { } + virtual int testC(); +}; + +class D: virtual public A { +public: + virtual ~D() { } + virtual int testD(); +}; + +class E { +public: + virtual ~E() { } + virtual int testE(B*); +}; + +class F { +public: + virtual ~F() { } + virtual int testF(C*); +}; + +class T { +public: + virtual ~T() { } + virtual int testT(D*); +}; + +%} + +%{ + +int A::testA() { return 1; } + +int B::testB() { return 2; } + +int C::testC() { return 3; } + +int D::testD() { return 4; } + +int E::testE(B*) { return 5; } + +int F::testF(C*) { return 6; } + +int T::testT(D*) { return 20; } + +%} diff --git a/Examples/test-suite/python/director_multiple_inheritance_runme.py b/Examples/test-suite/python/director_multiple_inheritance_runme.py new file mode 100644 index 000000000..8c8ea0bf6 --- /dev/null +++ b/Examples/test-suite/python/director_multiple_inheritance_runme.py @@ -0,0 +1,36 @@ +import director_multiple_inheritance as st + +class TestBCD(st.B, st.C, st.D): + def __init__(self): + st.B.__init__(self) + st.C.__init__(self) + st.D.__init__(self) + +class TestBDC(st.B, st.C, st.D): + def __init__(self): + st.B.__init__(self) + st.D.__init__(self) + st.C.__init__(self) + +class TestCBD(st.B, st.C, st.D): + def __init__(self): + st.C.__init__(self) + st.B.__init__(self) + st.D.__init__(self) + +def dotest(test): + e = st.E() + if e.testE(test) != 5: + raise RuntimeError(e.testE(test)) + + f = st.F() + if f.testF(test) != 6: + raise RuntimeError(f.testF(test)) + + t = st.T() + if t.testT(test) != 20: + raise RuntimeError(t.testT(test)) + +dotest(TestBCD()) +dotest(TestCBD()) +dotest(TestBDC()) diff --git a/Lib/python/pyrun.swg b/Lib/python/pyrun.swg index 36a20c422..a1ac95baf 100644 --- a/Lib/python/pyrun.swg +++ b/Lib/python/pyrun.swg @@ -792,6 +792,7 @@ SwigPyObject_append(PyObject* v, PyObject* next) PyErr_SetString(PyExc_TypeError, "Attempt to append a non SwigPyObject"); return NULL; } + ((SwigPyObject *)next)->next = sobj->next; sobj->next = next; Py_INCREF(next); return SWIG_Py_Void(); From ccccd6fc1f42a7707e0887e26431b927937c466d Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Wed, 20 Jul 2022 15:06:56 +1200 Subject: [PATCH 539/662] Add director_multiple_inheritance to CPP_TEST_CASES --- Examples/test-suite/common.mk | 1 + 1 file changed, 1 insertion(+) diff --git a/Examples/test-suite/common.mk b/Examples/test-suite/common.mk index b4633e3f6..32444688d 100644 --- a/Examples/test-suite/common.mk +++ b/Examples/test-suite/common.mk @@ -200,6 +200,7 @@ CPP_TEST_CASES += \ director_frob \ director_ignore \ director_keywords \ + director_multiple_inheritance \ director_namespace_clash \ director_nested \ director_nspace \ From 7592722e39a7595d20d2d81a5bc1f9eb91f2e35b Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Wed, 20 Jul 2022 19:46:08 +0100 Subject: [PATCH 540/662] Order of interfaces generated for %interface macros Ensure the order of interfaces generated in proxy interfaces for the %interface family of macros is the same as that parsed from the bases in C++. --- CHANGES.current | 4 ++++ .../multiple_inheritance_interfaces_runme.java | 10 +++++----- Source/Modules/csharp.cxx | 10 ++++------ Source/Modules/interface.cxx | 14 ++++++-------- Source/Modules/java.cxx | 10 ++++------ 5 files changed, 23 insertions(+), 25 deletions(-) diff --git a/CHANGES.current b/CHANGES.current index 39157d37f..1f0dd3807 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-07-20: wsfulton + [C#, Java] Ensure the order of interfaces generated in proxy interfaces for the + %interface family of macros is the same as that parsed from the bases in C++. + 2022-07-20: jicks, Ingener74, olly #422 [Python] Fix mishandling of a Python class inheriting from multiple SWIG-wrapped director classes. diff --git a/Examples/test-suite/java/multiple_inheritance_interfaces_runme.java b/Examples/test-suite/java/multiple_inheritance_interfaces_runme.java index 35a872c1c..df3e217fd 100644 --- a/Examples/test-suite/java/multiple_inheritance_interfaces_runme.java +++ b/Examples/test-suite/java/multiple_inheritance_interfaces_runme.java @@ -46,17 +46,17 @@ public class multiple_inheritance_interfaces_runme { checkBaseAndInterfaces(IC.class, true, "", new String[] {"IA", "IB"}); checkBaseAndInterfaces(A.class, false, "", new String[] {"IA"}); checkBaseAndInterfaces(B.class, false, "", new String[] {"IB"}); - checkBaseAndInterfaces(C.class, false, "", new String[] {"IA", "IB", "IC"}); - checkBaseAndInterfaces(D.class, false, "", new String[] {"IA", "IB", "IC"}); + checkBaseAndInterfaces(C.class, false, "", new String[] {"IC", "IA", "IB"}); + checkBaseAndInterfaces(D.class, false, "", new String[] {"IC", "IA", "IB"}); checkBaseAndInterfaces(E.class, false, "D", new String[] {}); checkBaseAndInterfaces(IJ.class, true, "", new String[] {}); checkBaseAndInterfaces(IK.class, true, "", new String[] {"IJ"}); checkBaseAndInterfaces(IL.class, true, "", new String[] {"IK"}); checkBaseAndInterfaces(J.class, false, "", new String[] {"IJ"}); - checkBaseAndInterfaces(K.class, false, "", new String[] {"IJ", "IK"}); - checkBaseAndInterfaces(L.class, false, "", new String[] {"IJ", "IK", "IL"}); - checkBaseAndInterfaces(M.class, false, "", new String[] {"IJ", "IK", "IL"}); + checkBaseAndInterfaces(K.class, false, "", new String[] {"IK", "IJ"}); + checkBaseAndInterfaces(L.class, false, "", new String[] {"IL", "IK", "IJ"}); + checkBaseAndInterfaces(M.class, false, "", new String[] {"IL", "IK", "IJ"}); checkBaseAndInterfaces(P.class, false, "", new String[] {}); checkBaseAndInterfaces(IQ.class, true, "", new String[] {}); diff --git a/Source/Modules/csharp.cxx b/Source/Modules/csharp.cxx index 294f7c20f..554c2ce56 100644 --- a/Source/Modules/csharp.cxx +++ b/Source/Modules/csharp.cxx @@ -1699,10 +1699,9 @@ public: * addInterfaceNameAndUpcasts() * ----------------------------------------------------------------------------- */ - void addInterfaceNameAndUpcasts(SwigType *smart, String *interface_list, String *interface_upcasts, Hash *base_list, SwigType *c_classname) { - List *keys = Keys(base_list); - for (Iterator it = First(keys); it.item; it = Next(it)) { - Node *base = Getattr(base_list, it.item); + void addInterfaceNameAndUpcasts(SwigType *smart, String *interface_list, String *interface_upcasts, List *base_list, SwigType *c_classname) { + for (Iterator it = First(base_list); it.item; it = Next(it)) { + Node *base = it.item; SwigType *c_baseclassname = Getattr(base, "name"); String *interface_name = Getattr(base, "interface:name"); if (Len(interface_list)) @@ -1729,7 +1728,6 @@ public: Delete(cptr_method_name); Delete(interface_code); } - Delete(keys); } /* ----------------------------------------------------------------------------- @@ -1825,7 +1823,7 @@ public: } } } - Hash *interface_bases = Getattr(n, "interface:bases"); + List *interface_bases = Getattr(n, "interface:bases"); if (interface_bases) addInterfaceNameAndUpcasts(smart, interface_list, interface_upcasts, interface_bases, c_classname); diff --git a/Source/Modules/interface.cxx b/Source/Modules/interface.cxx index c0c059019..f6a57eefb 100644 --- a/Source/Modules/interface.cxx +++ b/Source/Modules/interface.cxx @@ -29,10 +29,9 @@ static bool interface_feature_enabled = false; static List *collect_interface_methods(Node *n) { List *methods = NewList(); - if (Hash *bases = Getattr(n, "interface:bases")) { - List *keys = Keys(bases); - for (Iterator base = First(keys); base.item; base = Next(base)) { - Node *cls = Getattr(bases, base.item); + if (List *bases = Getattr(n, "interface:bases")) { + for (Iterator base = First(bases); base.item; base = Next(base)) { + Node *cls = base.item; if (cls == n) continue; for (Node *child = firstChild(cls); child; child = nextSibling(child)) { @@ -55,7 +54,6 @@ static List *collect_interface_methods(Node *n) { } } } - Delete(keys); } return methods; } @@ -64,11 +62,11 @@ static List *collect_interface_methods(Node *n) { * collect_interface_bases * ----------------------------------------------------------------------------- */ -static void collect_interface_bases(Hash *bases, Node *n) { +static void collect_interface_bases(List *bases, Node *n) { if (GetFlag(n, "feature:interface")) { String *name = Getattr(n, "interface:name"); if (!Getattr(bases, name)) - Setattr(bases, name, n); + Append(bases, n); } if (List *baselist = Getattr(n, "bases")) { @@ -106,7 +104,7 @@ static void collect_interface_base_classes(Node *n) { } } - Hash *interface_bases = NewHash(); + List *interface_bases = NewList(); collect_interface_bases(interface_bases, n); if (Len(interface_bases) == 0) Delete(interface_bases); diff --git a/Source/Modules/java.cxx b/Source/Modules/java.cxx index ea7e4607a..3396a1a6e 100644 --- a/Source/Modules/java.cxx +++ b/Source/Modules/java.cxx @@ -1840,10 +1840,9 @@ public: * addInterfaceNameAndUpcasts() * ----------------------------------------------------------------------------- */ - void addInterfaceNameAndUpcasts(SwigType *smart, String *interface_list, String *interface_upcasts, Hash *base_list, SwigType *c_classname) { - List *keys = Keys(base_list); - for (Iterator it = First(keys); it.item; it = Next(it)) { - Node *base = Getattr(base_list, it.item); + void addInterfaceNameAndUpcasts(SwigType *smart, String *interface_list, String *interface_upcasts, List *base_list, SwigType *c_classname) { + for (Iterator it = First(base_list); it.item; it = Next(it)) { + Node *base = it.item; SwigType *c_baseclassname = Getattr(base, "name"); String *interface_name = Getattr(base, "interface:name"); if (Len(interface_list)) @@ -1870,7 +1869,6 @@ public: Delete(cptr_method_name); Delete(interface_code); } - Delete(keys); } /* ----------------------------------------------------------------------------- @@ -1976,7 +1974,7 @@ public: } } - Hash *interface_bases = Getattr(n, "interface:bases"); + List *interface_bases = Getattr(n, "interface:bases"); if (interface_bases) addInterfaceNameAndUpcasts(smart, interface_list, interface_upcasts, interface_bases, c_classname); From eaf311a650c104e40aad356863e965f0b2969b35 Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Fri, 22 Jul 2022 17:37:32 +1200 Subject: [PATCH 541/662] [php] Make $message optional in testsuite helpers Also report the filename and line in the testcase where a check function which fails was called from. --- Examples/test-suite/php/tests.php | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/Examples/test-suite/php/tests.php b/Examples/test-suite/php/tests.php index d092b5317..8561ef826 100644 --- a/Examples/test-suite/php/tests.php +++ b/Examples/test-suite/php/tests.php @@ -168,26 +168,35 @@ class check { return TRUE; } - static function equal($a,$b,$message) { - if (! ($a===$b)) return check::fail($message . ": '$a'!=='$b'"); + static function equal($a,$b,$message=null) { + if (! ($a===$b)) return check::fail_($message, "'$a'!=='$b'"); return TRUE; } - static function equivalent($a,$b,$message) { - if (! ($a==$b)) return check::fail($message . ": '$a'!='$b'"); + static function equivalent($a,$b,$message=null) { + if (! ($a==$b)) return check::fail_($message, "'$a'!='$b'"); return TRUE; } - static function isnull($a,$message) { + static function isnull($a,$message=null) { return check::equal($a,NULL,$message); } - static function fail($pattern) { + private static function fail_($message, $pattern) { + $bt = debug_backtrace(0); + $bt = $bt[array_key_last($bt)-1]; + print("{$bt['file']}:{$bt['line']}: Failed on: "); + if ($message !== NULL) print("$message: "); $args=func_get_args(); - print("Failed on: ".call_user_func_array("sprintf",$args)."\n"); + array_shift($args); + print(call_user_func_array("sprintf",$args)."\n"); exit(1); } + static function fail($pattern) { + fail_(null, $pattern); + } + static function warn($pattern) { $args=func_get_args(); if (self::$_werror) self::fail($pattern); From 2aa979b7a03694e4f7346a4e63604298ba30d4b0 Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Fri, 22 Jul 2022 17:40:40 +1200 Subject: [PATCH 542/662] [php] Add friends_runme.php --- Examples/test-suite/php/friends_runme.php | 37 +++++++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 Examples/test-suite/php/friends_runme.php diff --git a/Examples/test-suite/php/friends_runme.php b/Examples/test-suite/php/friends_runme.php new file mode 100644 index 000000000..f0ef5df58 --- /dev/null +++ b/Examples/test-suite/php/friends_runme.php @@ -0,0 +1,37 @@ + Date: Fri, 22 Jul 2022 17:44:45 +1200 Subject: [PATCH 543/662] Fix friends_runme.* Most of these test D_d twice when they really should be testing D_d once and D_i once (the variable name is `di` and the values assigned are integers). This was wrong in the initial version for Python in 708021a809a566a410ec0e6bf5c63029392315e1 and it looks like subsequent additions for other languages have just copied that mistake. --- Examples/test-suite/csharp/friends_runme.cs | 2 +- Examples/test-suite/go/friends_runme.go | 8 ++++---- Examples/test-suite/java/friends_runme.java | 2 +- Examples/test-suite/octave/friends_runme.m | 2 +- Examples/test-suite/python/friends_runme.py | 2 +- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Examples/test-suite/csharp/friends_runme.cs b/Examples/test-suite/csharp/friends_runme.cs index ae3ffb64f..9dfd9ba09 100644 --- a/Examples/test-suite/csharp/friends_runme.cs +++ b/Examples/test-suite/csharp/friends_runme.cs @@ -22,7 +22,7 @@ public class friends_runme { if (friends.mix(a,b) != 5) throw new Exception("failed"); - D_d di = new D_d(2); + D_i di = new D_i(2); D_d dd = new D_d(3.3); // incredible template overloading working just fine diff --git a/Examples/test-suite/go/friends_runme.go b/Examples/test-suite/go/friends_runme.go index b6b9e93f3..f7836ad2f 100644 --- a/Examples/test-suite/go/friends_runme.go +++ b/Examples/test-suite/go/friends_runme.go @@ -27,21 +27,21 @@ func main() { panic(0) } - di := friends.NewD_d(2) + di := friends.NewD_i(2) dd := friends.NewD_d(3.3) // incredible template overloading working just fine - if friends.Get_val1(di).(float64) != 2 { + if friends.Get_val1(di).(int) != 2 { panic(0) } if friends.Get_val1(dd).(float64) != 3.3 { panic(0) } - friends.Set(di, 4.0) + friends.Set(di, 4) friends.Set(dd, 1.3) - if friends.Get_val1(di).(float64) != 4 { + if friends.Get_val1(di).(int) != 4 { panic(0) } if friends.Get_val1(dd).(float64) != 1.3 { diff --git a/Examples/test-suite/java/friends_runme.java b/Examples/test-suite/java/friends_runme.java index 2dced9efa..ebec103c1 100644 --- a/Examples/test-suite/java/friends_runme.java +++ b/Examples/test-suite/java/friends_runme.java @@ -32,7 +32,7 @@ public class friends_runme { if (friends.mix(a,b) != 5) throw new RuntimeException("failed"); - D_d di = new D_d(2); + D_i di = new D_i(2); D_d dd = new D_d(3.3); // incredible template overloading working just fine diff --git a/Examples/test-suite/octave/friends_runme.m b/Examples/test-suite/octave/friends_runme.m index 50a5b20ef..163f05b8d 100644 --- a/Examples/test-suite/octave/friends_runme.m +++ b/Examples/test-suite/octave/friends_runme.m @@ -29,7 +29,7 @@ if (friends.mix(a,b) != 5) error("failed"); endif -di = friends.D_d(2); +di = friends.D_i(2); dd = friends.D_d(3.3); # incredible template overloading working just fine diff --git a/Examples/test-suite/python/friends_runme.py b/Examples/test-suite/python/friends_runme.py index 2d377fdd1..7c7bbabfe 100644 --- a/Examples/test-suite/python/friends_runme.py +++ b/Examples/test-suite/python/friends_runme.py @@ -19,7 +19,7 @@ b = friends.B(3) if friends.mix(a, b) != 5: raise RuntimeError -di = friends.D_d(2) +di = friends.D_i(2) dd = friends.D_d(3.3) # incredible template overloading working just fine From 5a4baece4f0809f19c72059b8f825fe02fe0cfd8 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Sun, 24 Jul 2022 10:57:36 +0100 Subject: [PATCH 544/662] Remove redundant check for NULL in char * typemaps No need to check for NULL before calling delete/free. Anyone using typemaps_string_alloc with custom allocators and deallocators need to ensure the custom allocators behave in the same way as the standard deallocators in this respect. --- Lib/typemaps/strings.swg | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Lib/typemaps/strings.swg b/Lib/typemaps/strings.swg index e8ed401b0..5dd57b93d 100644 --- a/Lib/typemaps/strings.swg +++ b/Lib/typemaps/strings.swg @@ -79,7 +79,7 @@ if (!SWIG_IsOK(res)) { %variable_fail(res,"$type","$name"); } - if ($1) SWIG_DeleteCharArray($1); + SWIG_DeleteCharArray($1); if (alloc == SWIG_NEWOBJ) { $1 = cptr; } else { @@ -109,7 +109,7 @@ /* memberin */ %typemap(memberin,noblock=1) Char * { - if ($1) SWIG_DeleteCharArray($1); + SWIG_DeleteCharArray($1); if ($input) { size_t size = SWIG_CharPtrLen(%reinterpret_cast($input, const Char *)) + 1; $1 = ($1_type)SWIG_NewCopyCharArray(%reinterpret_cast($input, const Char *), size, Char); @@ -130,7 +130,7 @@ /* globalin */ %typemap(globalin,noblock=1) Char * { - if ($1) SWIG_DeleteCharArray($1); + SWIG_DeleteCharArray($1); if ($input) { size_t size = SWIG_CharPtrLen(%reinterpret_cast(%reinterpret_cast($input, const Char *), const Char *)) + 1; $1 = ($1_type)SWIG_NewCopyCharArray($input, size, Char); From de5ce08a7d519b3f8d70a98fdee51819dfd6b5d3 Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Tue, 26 Jul 2022 12:35:58 +1200 Subject: [PATCH 545/662] Fix operator precedence in preprocessor expressions --- CHANGES.current | 3 +++ Examples/test-suite/common.mk | 1 + Examples/test-suite/preproc_expr.i | 34 ++++++++++++++++++++++++++++++ Source/Preprocessor/expr.c | 20 +++++++++--------- 4 files changed, 48 insertions(+), 10 deletions(-) create mode 100644 Examples/test-suite/preproc_expr.i diff --git a/CHANGES.current b/CHANGES.current index 1f0dd3807..15769cbdf 100644 --- a/CHANGES.current +++ b/CHANGES.current @@ -7,6 +7,9 @@ the issue number to the end of the URL: https://github.com/swig/swig/issues/ Version 4.1.0 (in progress) =========================== +2022-07-26: olly + Fix incorrect operator precedence in preprocessor expressions. + 2022-07-20: wsfulton [C#, Java] Ensure the order of interfaces generated in proxy interfaces for the %interface family of macros is the same as that parsed from the bases in C++. diff --git a/Examples/test-suite/common.mk b/Examples/test-suite/common.mk index 32444688d..7626872cd 100644 --- a/Examples/test-suite/common.mk +++ b/Examples/test-suite/common.mk @@ -746,6 +746,7 @@ C_TEST_CASES += \ preproc \ preproc_constants_c \ preproc_defined \ + preproc_expr \ preproc_gcc_output \ preproc_include \ preproc_line_file \ diff --git a/Examples/test-suite/preproc_expr.i b/Examples/test-suite/preproc_expr.i new file mode 100644 index 000000000..a24f7715c --- /dev/null +++ b/Examples/test-suite/preproc_expr.i @@ -0,0 +1,34 @@ +%module preproc_expr + +// Check expressions which suffered from incorrect operator precedence prior +// to SWIG 4.1.0. + +%inline %{ +// `!` should have higher precedence than binary `+`. +#if !0 + 1 +#else +# error Bad preprocessor expression operator precedence +#endif + +// `!=` should have higher precedence than bitwise and. +#if 1 & 2 != 0 +#else +# error Bad preprocessor expression operator precedence +#endif + +// `==` should have higher precedence than bitwise or. +#if (2 | 1 == 3) != 2 +# error Bad preprocessor expression operator precedence +#endif + +// `!=` should have higher precedence than bitwise xor. +#if 1 ^ 2 != 4 +# error Bad preprocessor expression operator precedence +#endif + +// `<` should have higher precedence than '=='. +#if 2 == 2 < 2 +# error Bad preprocessor expression operator precedence +#endif + +%} diff --git a/Source/Preprocessor/expr.c b/Source/Preprocessor/expr.c index 52e467b6c..b2efba57e 100644 --- a/Source/Preprocessor/expr.c +++ b/Source/Preprocessor/expr.c @@ -54,6 +54,7 @@ static const char *errmsg = 0; /* Parsing error */ /* Initialize the precedence table for various operators. Low values have higher precedence */ static void init_precedence(void) { prec[SWIG_TOKEN_NOT] = 10; + prec[SWIG_TOKEN_LNOT] = 10; prec[OP_UMINUS] = 10; prec[OP_UPLUS] = 10; prec[SWIG_TOKEN_STAR] = 20; @@ -63,16 +64,15 @@ static void init_precedence(void) { prec[SWIG_TOKEN_MINUS] = 30; prec[SWIG_TOKEN_LSHIFT] = 40; prec[SWIG_TOKEN_RSHIFT] = 40; - prec[SWIG_TOKEN_AND] = 50; - prec[SWIG_TOKEN_XOR] = 60; - prec[SWIG_TOKEN_OR] = 70; - prec[SWIG_TOKEN_EQUALTO] = 80; - prec[SWIG_TOKEN_NOTEQUAL] = 80; - prec[SWIG_TOKEN_LESSTHAN] = 80; - prec[SWIG_TOKEN_GREATERTHAN] = 80; - prec[SWIG_TOKEN_LTEQUAL] = 80; - prec[SWIG_TOKEN_GTEQUAL] = 80; - prec[SWIG_TOKEN_LNOT] = 90; + prec[SWIG_TOKEN_LESSTHAN] = 50; + prec[SWIG_TOKEN_GREATERTHAN] = 50; + prec[SWIG_TOKEN_LTEQUAL] = 50; + prec[SWIG_TOKEN_GTEQUAL] = 50; + prec[SWIG_TOKEN_EQUALTO] = 60; + prec[SWIG_TOKEN_NOTEQUAL] = 60; + prec[SWIG_TOKEN_AND] = 70; + prec[SWIG_TOKEN_XOR] = 80; + prec[SWIG_TOKEN_OR] = 90; prec[SWIG_TOKEN_LAND] = 100; prec[SWIG_TOKEN_LOR] = 110; expr_init = 1; From 8038cd7ac34d49490f63686317efc0300ddd3e4b Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Mon, 25 Jul 2022 16:40:16 +1200 Subject: [PATCH 546/662] Fix C++20 compatibility in testcases --- Examples/test-suite/cpp11_raw_string_literals.i | 9 +++++---- Examples/test-suite/cpp11_userdefined_literals.i | 3 +++ Examples/test-suite/cpp17_u8_char_literals.i | 3 ++- Examples/test-suite/template_construct.i | 6 ++++++ Examples/test-suite/valuewrapper_opaque.i | 2 +- 5 files changed, 17 insertions(+), 6 deletions(-) diff --git a/Examples/test-suite/cpp11_raw_string_literals.i b/Examples/test-suite/cpp11_raw_string_literals.i index 813374928..fb861377e 100644 --- a/Examples/test-suite/cpp11_raw_string_literals.i +++ b/Examples/test-suite/cpp11_raw_string_literals.i @@ -1,7 +1,7 @@ /* This module tests whether SWIG correctly parses: - - ordinary strings (char_t) + - ordinary strings (char) - L wide strings (wchar_t) - - u8 unicode8 strings (char_t) + - u8 unicode8 strings (char / char8_t since C++20) - u unicode16 strings (char16_t) - U unicode32 strings (char32_t) @@ -49,7 +49,8 @@ struct URStruct { // New string literals wstring aa = L"Wide string"; -const char *bb = u8"UTF-8 string"; +// u8"" is const char8_t[N] in C++20; const char[N] from C++11 until then. +const char *bb = reinterpret_cast(u8"UTF-8 string"); const char16_t *cc = u"UTF-16 string"; const char32_t *dd = U"UTF-32 string"; // New char literals @@ -62,7 +63,7 @@ char32_t char32_t_char = U'b'; const char *xx = ")I'm an \"ascii\" \\ string."; const char *ee = R"XXX()I'm an "ascii" \ string.)XXX"; wstring ff = LR"XXX(I'm a "raw wide" \ string.)XXX"; -const char *gg = u8R"XXX(I'm a "raw UTF-8" \ string.)XXX"; +const char *gg = reinterpret_cast(u8R"XXX(I'm a "raw UTF-8" \ string.)XXX"); const char16_t *hh = uR"XXX(I'm a "raw UTF-16" \ string.)XXX"; const char32_t *ii = UR"XXX(I'm a "raw UTF-32" \ string.)XXX"; %} diff --git a/Examples/test-suite/cpp11_userdefined_literals.i b/Examples/test-suite/cpp11_userdefined_literals.i index 9284739cd..37dc6c5ff 100644 --- a/Examples/test-suite/cpp11_userdefined_literals.i +++ b/Examples/test-suite/cpp11_userdefined_literals.i @@ -30,6 +30,9 @@ OutputType operator "" _mySuffixFloat(long double) { return OutputType(30); } // Cooked string literals OutputType operator "" _mySuffix1(const char * string_values, size_t num_chars) { return OutputType(100); } +#ifdef __cpp_lib_char8_t // For C++20 +OutputType operator "" _mySuffix1(const char8_t * string_values, size_t num_chars) { return OutputType(100); } +#endif OutputType operator "" _mySuffix2(const wchar_t * string_values, size_t num_chars) { return OutputType(200); } OutputType operator "" _mySuffix3(const char16_t * string_values, size_t num_chars) { return OutputType(300); } OutputType operator "" _mySuffix4(const char32_t * string_values, size_t num_chars) { return OutputType(400); } diff --git a/Examples/test-suite/cpp17_u8_char_literals.i b/Examples/test-suite/cpp17_u8_char_literals.i index 1aae1b231..16f0498ec 100644 --- a/Examples/test-suite/cpp17_u8_char_literals.i +++ b/Examples/test-suite/cpp17_u8_char_literals.i @@ -8,7 +8,8 @@ #endif %} -// UTF-8 character literals will (apparently) have type char8_t in C++20. +// UTF-8 character literals are type `char` in C++17 but `char8_t` in C++20, +// but the latter can be assigned to `char`. char a = u8'a'; char u = u8'u'; char u8 = u8'8'; diff --git a/Examples/test-suite/template_construct.i b/Examples/test-suite/template_construct.i index a6e8c3c33..ac418f8e5 100644 --- a/Examples/test-suite/template_construct.i +++ b/Examples/test-suite/template_construct.i @@ -7,7 +7,13 @@ template class Foo { T y; public: +#ifdef SWIG Foo(T x) : y(x) { } +#else + // Modern compilers reject this, so feed the compiler the corrected + // version. + Foo(T x) : y(x) { } +#endif }; %} diff --git a/Examples/test-suite/valuewrapper_opaque.i b/Examples/test-suite/valuewrapper_opaque.i index bc7ba8683..962bd2f81 100644 --- a/Examples/test-suite/valuewrapper_opaque.i +++ b/Examples/test-suite/valuewrapper_opaque.i @@ -14,7 +14,7 @@ class C; %{ template class TemplateClass { public: -TemplateClass(T a) {} +TemplateClass(T a) {} }; struct B From b5ad734fdfab6ebe3b5363863ab48352c57e1353 Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Mon, 25 Jul 2022 13:45:47 +1200 Subject: [PATCH 547/662] Update AX_CXX_COMPILE_STDCXX to upstream serial 14 Only functional change is the addition of C++20 support. --- Tools/config/m4_ax_cxx_compile_stdcxx.m4 | 51 ++++++++++++++++++++++-- 1 file changed, 47 insertions(+), 4 deletions(-) diff --git a/Tools/config/m4_ax_cxx_compile_stdcxx.m4 b/Tools/config/m4_ax_cxx_compile_stdcxx.m4 index 9413da624..51a35054d 100644 --- a/Tools/config/m4_ax_cxx_compile_stdcxx.m4 +++ b/Tools/config/m4_ax_cxx_compile_stdcxx.m4 @@ -10,8 +10,8 @@ # # Check for baseline language coverage in the compiler for the specified # version of the C++ standard. If necessary, add switches to CXX and -# CXXCPP to enable support. VERSION may be '11' (for the C++11 standard) -# or '14' (for the C++14 standard). +# CXXCPP to enable support. VERSION may be '11', '14', '17', or '20' for +# the respective C++ standard version. # # The second argument, if specified, indicates whether you insist on an # extended mode (e.g. -std=gnu++11) or a strict conformance mode (e.g. @@ -36,13 +36,14 @@ # Copyright (c) 2016, 2018 Krzesimir Nowak # Copyright (c) 2019 Enji Cooper # Copyright (c) 2020 Jason Merrill +# Copyright (c) 2021 Jörn Heusipp # # Copying and distribution of this file, with or without modification, are # permitted in any medium without royalty provided the copyright notice # and this notice are preserved. This file is offered as-is, without any # warranty. -#serial 12 +#serial 14 dnl This macro is based on the code from the AX_CXX_COMPILE_STDCXX_11 macro dnl (serial version number 13). @@ -51,6 +52,7 @@ AC_DEFUN([AX_CXX_COMPILE_STDCXX], [dnl m4_if([$1], [11], [ax_cxx_compile_alternatives="11 0x"], [$1], [14], [ax_cxx_compile_alternatives="14 1y"], [$1], [17], [ax_cxx_compile_alternatives="17 1z"], + [$1], [20], [ax_cxx_compile_alternatives="20"], [m4_fatal([invalid first argument `$1' to AX_CXX_COMPILE_STDCXX])])dnl m4_if([$2], [], [], [$2], [ext], [], @@ -151,7 +153,6 @@ m4_define([_AX_CXX_COMPILE_STDCXX_testbody_11], _AX_CXX_COMPILE_STDCXX_testbody_new_in_11 ) - dnl Test body for checking C++14 support m4_define([_AX_CXX_COMPILE_STDCXX_testbody_14], @@ -159,12 +160,24 @@ m4_define([_AX_CXX_COMPILE_STDCXX_testbody_14], _AX_CXX_COMPILE_STDCXX_testbody_new_in_14 ) +dnl Test body for checking C++17 support + m4_define([_AX_CXX_COMPILE_STDCXX_testbody_17], _AX_CXX_COMPILE_STDCXX_testbody_new_in_11 _AX_CXX_COMPILE_STDCXX_testbody_new_in_14 _AX_CXX_COMPILE_STDCXX_testbody_new_in_17 ) +dnl Test body for checking C++20 support + +m4_define([_AX_CXX_COMPILE_STDCXX_testbody_20], + _AX_CXX_COMPILE_STDCXX_testbody_new_in_11 + _AX_CXX_COMPILE_STDCXX_testbody_new_in_14 + _AX_CXX_COMPILE_STDCXX_testbody_new_in_17 + _AX_CXX_COMPILE_STDCXX_testbody_new_in_20 +) + + dnl Tests for new features in C++11 m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_11], [[ @@ -960,3 +973,33 @@ namespace cxx17 #endif // __cplusplus < 201703L ]]) + + +dnl Tests for new features in C++20 + +m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_20], [[ + +#ifndef __cplusplus + +#error "This is not a C++ compiler" + +#elif __cplusplus < 202002L + +#error "This is not a C++20 compiler" + +#else + +#include + +namespace cxx20 +{ + +// As C++20 supports feature test macros in the standard, there is no +// immediate need to actually test for feature availability on the +// Autoconf side. + +} // namespace cxx20 + +#endif // __cplusplus < 202002L + +]]) From 07f0b732ba71eca1dee15ed495c2bb61ec38d0dc Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Mon, 25 Jul 2022 14:07:12 +1200 Subject: [PATCH 548/662] Add machinery for C++14, C++17 and C++20 testing Support running testcases conditional on the compiler supporting a each language version, like we already handle C++11. Currently no testcases are actually run in this way for these newer language versions. --- Examples/test-suite/cffi/Makefile.in | 3 ++ Examples/test-suite/common.mk | 47 +++++++++++++++++++++- Examples/test-suite/csharp/Makefile.in | 3 ++ Examples/test-suite/d/Makefile.in | 3 ++ Examples/test-suite/errors/Makefile.in | 3 ++ Examples/test-suite/go/Makefile.in | 3 ++ Examples/test-suite/guile/Makefile.in | 3 ++ Examples/test-suite/java/Makefile.in | 3 ++ Examples/test-suite/javascript/Makefile.in | 3 ++ Examples/test-suite/lua/Makefile.in | 3 ++ Examples/test-suite/mzscheme/Makefile.in | 3 ++ Examples/test-suite/ocaml/Makefile.in | 3 ++ Examples/test-suite/octave/Makefile.in | 3 ++ Examples/test-suite/perl5/Makefile.in | 3 ++ Examples/test-suite/php/Makefile.in | 3 ++ Examples/test-suite/python/Makefile.in | 3 ++ Examples/test-suite/r/Makefile.in | 3 ++ Examples/test-suite/ruby/Makefile.in | 3 ++ Examples/test-suite/scilab/Makefile.in | 3 ++ Examples/test-suite/tcl/Makefile.in | 3 ++ configure.ac | 45 ++++++++++++++------- 21 files changed, 133 insertions(+), 16 deletions(-) diff --git a/Examples/test-suite/cffi/Makefile.in b/Examples/test-suite/cffi/Makefile.in index 1ce64675a..e27b2c85d 100644 --- a/Examples/test-suite/cffi/Makefile.in +++ b/Examples/test-suite/cffi/Makefile.in @@ -7,6 +7,9 @@ CFFI = @CFFIBIN@ SCRIPTSUFFIX = _runme.lisp HAVE_CXX11 = @HAVE_CXX11@ +HAVE_CXX14 = @HAVE_CXX14@ +HAVE_CXX17 = @HAVE_CXX17@ +HAVE_CXX20 = @HAVE_CXX20@ srcdir = @srcdir@ top_srcdir = @top_srcdir@ top_builddir = @top_builddir@ diff --git a/Examples/test-suite/common.mk b/Examples/test-suite/common.mk index 32444688d..0952ee8c1 100644 --- a/Examples/test-suite/common.mk +++ b/Examples/test-suite/common.mk @@ -91,7 +91,10 @@ CPP_TEST_BROKEN += \ template_default_pointer \ template_private_assignment \ template_expr \ - $(CPP11_TEST_BROKEN) + $(CPP11_TEST_BROKEN) \ + $(CPP14_TEST_BROKEN) \ + $(CPP17_TEST_BROKEN) \ + $(CPP20_TEST_BROKEN) # Broken C test cases. (Can be run individually using: make testcase.ctest) @@ -632,6 +635,24 @@ CPP11_TEST_BROKEN = \ # cpp11_variadic_templates \ # Broken for some languages (such as Java) # cpp11_reference_wrapper \ # No typemaps +# C++14 test cases. +CPP14_TEST_CASES += \ + +# Broken C++14 test cases. +CPP14_TEST_BROKEN = \ + +# C++17 test cases. +CPP17_TEST_CASES += \ + +# Broken C++17 test cases. +CPP17_TEST_BROKEN = \ + +# C++20 test cases. +CPP20_TEST_CASES += \ + +# Broken C++20 test cases. +CPP20_TEST_BROKEN = \ + # Doxygen support test cases: can only be used with languages supporting # Doxygen comment translation (currently Python and Java) and only if not # disabled by configure via SKIP_DOXYGEN_TEST_CASES. @@ -699,6 +720,18 @@ ifeq (1,$(HAVE_CXX11)) CPP_TEST_CASES += $(CPP11_TEST_CASES) endif +ifeq (1,$(HAVE_CXX14)) +CPP_TEST_CASES += $(CPP14_TEST_CASES) +endif + +ifeq (1,$(HAVE_CXX17)) +CPP_TEST_CASES += $(CPP17_TEST_CASES) +endif + +ifeq (1,$(HAVE_CXX20)) +CPP_TEST_CASES += $(CPP20_TEST_CASES) +endif + # C test cases. (Can be run individually using: make testcase.ctest) C_TEST_CASES += \ arrays \ @@ -783,6 +816,9 @@ command_line_define.ctest: SWIGOPT += -DFOO C_TEST_CASES := $(filter-out $(FAILING_C_TESTS),$(C_TEST_CASES)) CPP_TEST_CASES := $(filter-out $(FAILING_CPP_TESTS),$(CPP_TEST_CASES)) CPP11_TEST_CASES := $(filter-out $(FAILING_CPP_TESTS),$(CPP11_TEST_CASES)) +CPP14_TEST_CASES := $(filter-out $(FAILING_CPP_TESTS),$(CPP14_TEST_CASES)) +CPP17_TEST_CASES := $(filter-out $(FAILING_CPP_TESTS),$(CPP17_TEST_CASES)) +CPP20_TEST_CASES := $(filter-out $(FAILING_CPP_TESTS),$(CPP20_TEST_CASES)) MULTI_CPP_TEST_CASES := $(filter-out $(FAILING_MULTI_CPP_TESTS),$(MULTI_CPP_TEST_CASES)) @@ -796,6 +832,9 @@ BROKEN_TEST_CASES = $(CPP_TEST_BROKEN:=.cpptest) \ ALL_CLEAN = $(CPP_TEST_CASES:=.clean) \ $(CPP11_TEST_CASES:=.clean) \ + $(CPP14_TEST_CASES:=.clean) \ + $(CPP17_TEST_CASES:=.clean) \ + $(CPP20_TEST_CASES:=.clean) \ $(C_TEST_CASES:=.clean) \ $(MULTI_CPP_TEST_CASES:=.clean) \ $(CPP_TEST_BROKEN:=.clean) \ @@ -824,6 +863,12 @@ check-cpp: $(CPP_TEST_CASES:=.cpptest) check-cpp11: $(CPP11_TEST_CASES:=.cpptest) +check-cpp14: $(CPP14_TEST_CASES:=.cpptest) + +check-cpp17: $(CPP17_TEST_CASES:=.cpptest) + +check-cpp20: $(CPP20_TEST_CASES:=.cpptest) + check-multicpp: $(MULTI_CPP_TEST_CASES:=.multicpptest) ifdef HAS_DOXYGEN diff --git a/Examples/test-suite/csharp/Makefile.in b/Examples/test-suite/csharp/Makefile.in index 600c5953d..0d2664681 100644 --- a/Examples/test-suite/csharp/Makefile.in +++ b/Examples/test-suite/csharp/Makefile.in @@ -9,6 +9,9 @@ CSHARPCILINTERPRETER_FLAGS = @CSHARPCILINTERPRETER_FLAGS@ CSHARPCONVERTPATH = @top_srcdir@/@CSHARPCONVERTPATH@ HAVE_CXX11 = @HAVE_CXX11@ +HAVE_CXX14 = @HAVE_CXX14@ +HAVE_CXX17 = @HAVE_CXX17@ +HAVE_CXX20 = @HAVE_CXX20@ srcdir = @srcdir@ top_srcdir = ../@top_srcdir@ top_builddir = ../@top_builddir@ diff --git a/Examples/test-suite/d/Makefile.in b/Examples/test-suite/d/Makefile.in index e6b4e2d18..d6486845c 100644 --- a/Examples/test-suite/d/Makefile.in +++ b/Examples/test-suite/d/Makefile.in @@ -5,6 +5,9 @@ LANGUAGE = d HAVE_CXX11 = @HAVE_CXX11@ +HAVE_CXX14 = @HAVE_CXX14@ +HAVE_CXX17 = @HAVE_CXX17@ +HAVE_CXX20 = @HAVE_CXX20@ srcdir = @srcdir@ top_srcdir = ../@top_srcdir@ top_builddir = ../@top_builddir@ diff --git a/Examples/test-suite/errors/Makefile.in b/Examples/test-suite/errors/Makefile.in index 97c7d5c76..347bf3858 100644 --- a/Examples/test-suite/errors/Makefile.in +++ b/Examples/test-suite/errors/Makefile.in @@ -17,6 +17,9 @@ LANGUAGE = errors ERROR_EXT = newerr HAVE_CXX11 = @HAVE_CXX11@ +HAVE_CXX14 = @HAVE_CXX14@ +HAVE_CXX17 = @HAVE_CXX17@ +HAVE_CXX20 = @HAVE_CXX20@ srcdir = @srcdir@ top_srcdir = @top_srcdir@ top_builddir = @top_builddir@ diff --git a/Examples/test-suite/go/Makefile.in b/Examples/test-suite/go/Makefile.in index 67f96cf7e..d4c27c7b5 100644 --- a/Examples/test-suite/go/Makefile.in +++ b/Examples/test-suite/go/Makefile.in @@ -13,6 +13,9 @@ SCRIPTSUFFIX = _runme.go SO = @SO@ HAVE_CXX11 = @HAVE_CXX11@ +HAVE_CXX14 = @HAVE_CXX14@ +HAVE_CXX17 = @HAVE_CXX17@ +HAVE_CXX20 = @HAVE_CXX20@ srcdir = @srcdir@ top_srcdir = @top_srcdir@ top_builddir = @top_builddir@ diff --git a/Examples/test-suite/guile/Makefile.in b/Examples/test-suite/guile/Makefile.in index 1fda5dc9c..2efa6adbe 100644 --- a/Examples/test-suite/guile/Makefile.in +++ b/Examples/test-suite/guile/Makefile.in @@ -9,6 +9,9 @@ VARIANT = SCRIPTSUFFIX = _runme.scm HAVE_CXX11 = @HAVE_CXX11@ +HAVE_CXX14 = @HAVE_CXX14@ +HAVE_CXX17 = @HAVE_CXX17@ +HAVE_CXX20 = @HAVE_CXX20@ srcdir = @srcdir@ top_srcdir = @top_srcdir@ top_builddir = @top_builddir@ diff --git a/Examples/test-suite/java/Makefile.in b/Examples/test-suite/java/Makefile.in index 43695ce69..00ebb100b 100644 --- a/Examples/test-suite/java/Makefile.in +++ b/Examples/test-suite/java/Makefile.in @@ -12,6 +12,9 @@ SCRIPTSUFFIX = _runme.java SKIP_DOXYGEN_TEST_CASES = @JAVA_SKIP_DOXYGEN_TEST_CASES@ HAVE_CXX11 = @HAVE_CXX11@ +HAVE_CXX14 = @HAVE_CXX14@ +HAVE_CXX17 = @HAVE_CXX17@ +HAVE_CXX20 = @HAVE_CXX20@ srcdir = @srcdir@ top_srcdir = ../@top_srcdir@ top_builddir = ../@top_builddir@ diff --git a/Examples/test-suite/javascript/Makefile.in b/Examples/test-suite/javascript/Makefile.in index 57b6eac75..61cc5ff3d 100644 --- a/Examples/test-suite/javascript/Makefile.in +++ b/Examples/test-suite/javascript/Makefile.in @@ -10,6 +10,9 @@ OBJEXT = @OBJEXT@ SO = @SO@ HAVE_CXX11 = @HAVE_CXX11@ +HAVE_CXX14 = @HAVE_CXX14@ +HAVE_CXX17 = @HAVE_CXX17@ +HAVE_CXX20 = @HAVE_CXX20@ srcdir = @srcdir@ top_srcdir = @top_srcdir@ top_builddir = @top_builddir@ diff --git a/Examples/test-suite/lua/Makefile.in b/Examples/test-suite/lua/Makefile.in index 2d4100d1b..af6735101 100644 --- a/Examples/test-suite/lua/Makefile.in +++ b/Examples/test-suite/lua/Makefile.in @@ -7,6 +7,9 @@ LUA = @LUABIN@ SCRIPTSUFFIX = _runme.lua HAVE_CXX11 = @HAVE_CXX11@ +HAVE_CXX14 = @HAVE_CXX14@ +HAVE_CXX17 = @HAVE_CXX17@ +HAVE_CXX20 = @HAVE_CXX20@ srcdir = @srcdir@ top_srcdir = @top_srcdir@ top_builddir = @top_builddir@ diff --git a/Examples/test-suite/mzscheme/Makefile.in b/Examples/test-suite/mzscheme/Makefile.in index 93dbb4ba1..212379ca8 100644 --- a/Examples/test-suite/mzscheme/Makefile.in +++ b/Examples/test-suite/mzscheme/Makefile.in @@ -7,6 +7,9 @@ MZSCHEME = mzscheme SCRIPTSUFFIX = _runme.scm HAVE_CXX11 = @HAVE_CXX11@ +HAVE_CXX14 = @HAVE_CXX14@ +HAVE_CXX17 = @HAVE_CXX17@ +HAVE_CXX20 = @HAVE_CXX20@ srcdir = @srcdir@ top_srcdir = @top_srcdir@ top_builddir = @top_builddir@ diff --git a/Examples/test-suite/ocaml/Makefile.in b/Examples/test-suite/ocaml/Makefile.in index 9b0c32b0f..ffd62049d 100644 --- a/Examples/test-suite/ocaml/Makefile.in +++ b/Examples/test-suite/ocaml/Makefile.in @@ -10,6 +10,9 @@ VARIANT = _static SCRIPTSUFFIX = _runme.ml HAVE_CXX11 = @HAVE_CXX11@ +HAVE_CXX14 = @HAVE_CXX14@ +HAVE_CXX17 = @HAVE_CXX17@ +HAVE_CXX20 = @HAVE_CXX20@ srcdir = @srcdir@ top_srcdir = @top_srcdir@ top_builddir = @top_builddir@ diff --git a/Examples/test-suite/octave/Makefile.in b/Examples/test-suite/octave/Makefile.in index 81696b3ff..5a092f5e3 100644 --- a/Examples/test-suite/octave/Makefile.in +++ b/Examples/test-suite/octave/Makefile.in @@ -8,6 +8,9 @@ SCRIPTSUFFIX = _runme.m PCHSUPPORT = @PCHSUPPORT@ HAVE_CXX11 = @HAVE_CXX11@ +HAVE_CXX14 = @HAVE_CXX14@ +HAVE_CXX17 = @HAVE_CXX17@ +HAVE_CXX20 = @HAVE_CXX20@ srcdir = @srcdir@ top_srcdir = @top_srcdir@ top_builddir = @top_builddir@ diff --git a/Examples/test-suite/perl5/Makefile.in b/Examples/test-suite/perl5/Makefile.in index 3fb3ebac6..688b985ac 100644 --- a/Examples/test-suite/perl5/Makefile.in +++ b/Examples/test-suite/perl5/Makefile.in @@ -8,6 +8,9 @@ SCRIPTSUFFIX = _runme.pl TEST_RUNNER = $(srcdir)/run-perl-test.pl HAVE_CXX11 = @HAVE_CXX11@ +HAVE_CXX14 = @HAVE_CXX14@ +HAVE_CXX17 = @HAVE_CXX17@ +HAVE_CXX20 = @HAVE_CXX20@ srcdir = @srcdir@ top_srcdir = @top_srcdir@ top_builddir = @top_builddir@ diff --git a/Examples/test-suite/php/Makefile.in b/Examples/test-suite/php/Makefile.in index 6a2a4590b..c918581bf 100644 --- a/Examples/test-suite/php/Makefile.in +++ b/Examples/test-suite/php/Makefile.in @@ -6,6 +6,9 @@ LANGUAGE = php SCRIPTSUFFIX = _runme.php HAVE_CXX11 = @HAVE_CXX11@ +HAVE_CXX14 = @HAVE_CXX14@ +HAVE_CXX17 = @HAVE_CXX17@ +HAVE_CXX20 = @HAVE_CXX20@ srcdir = @srcdir@ top_srcdir = @top_srcdir@ top_builddir = @top_builddir@ diff --git a/Examples/test-suite/python/Makefile.in b/Examples/test-suite/python/Makefile.in index ddcd4afe9..baa89859a 100644 --- a/Examples/test-suite/python/Makefile.in +++ b/Examples/test-suite/python/Makefile.in @@ -15,6 +15,9 @@ PYCODESTYLE = @PYCODESTYLE@ PYCODESTYLE_FLAGS = --ignore=E252,E30,E402,E501,E731,E741,W291,W391 HAVE_CXX11 = @HAVE_CXX11@ +HAVE_CXX14 = @HAVE_CXX14@ +HAVE_CXX17 = @HAVE_CXX17@ +HAVE_CXX20 = @HAVE_CXX20@ srcdir = @srcdir@ top_srcdir = @top_srcdir@ top_builddir = @top_builddir@ diff --git a/Examples/test-suite/r/Makefile.in b/Examples/test-suite/r/Makefile.in index 484dea375..78cc4bb53 100644 --- a/Examples/test-suite/r/Makefile.in +++ b/Examples/test-suite/r/Makefile.in @@ -9,6 +9,9 @@ R_OPT = --quiet --no-save --no-restore RUNR = R CMD BATCH $(R_OPT) '--args $(SCRIPTDIR)' HAVE_CXX11 = @HAVE_CXX11@ +HAVE_CXX14 = @HAVE_CXX14@ +HAVE_CXX17 = @HAVE_CXX17@ +HAVE_CXX20 = @HAVE_CXX20@ srcdir = @srcdir@ top_srcdir = @top_srcdir@ top_builddir = @top_builddir@ diff --git a/Examples/test-suite/ruby/Makefile.in b/Examples/test-suite/ruby/Makefile.in index 3b673bf71..09ff02842 100644 --- a/Examples/test-suite/ruby/Makefile.in +++ b/Examples/test-suite/ruby/Makefile.in @@ -7,6 +7,9 @@ RUBY = @RUBY@ SCRIPTSUFFIX = _runme.rb HAVE_CXX11 = @HAVE_CXX11@ +HAVE_CXX14 = @HAVE_CXX14@ +HAVE_CXX17 = @HAVE_CXX17@ +HAVE_CXX20 = @HAVE_CXX20@ srcdir = @srcdir@ top_srcdir = @top_srcdir@ top_builddir = @top_builddir@ diff --git a/Examples/test-suite/scilab/Makefile.in b/Examples/test-suite/scilab/Makefile.in index e1effcd64..cf36794e3 100644 --- a/Examples/test-suite/scilab/Makefile.in +++ b/Examples/test-suite/scilab/Makefile.in @@ -8,6 +8,9 @@ SCILAB_OPT = @SCILABOPT@ SCRIPTSUFFIX = _runme.sci HAVE_CXX11 = @HAVE_CXX11@ +HAVE_CXX14 = @HAVE_CXX14@ +HAVE_CXX17 = @HAVE_CXX17@ +HAVE_CXX20 = @HAVE_CXX20@ srcdir = @srcdir@ top_srcdir = ../@top_srcdir@ top_builddir = ../@top_builddir@ diff --git a/Examples/test-suite/tcl/Makefile.in b/Examples/test-suite/tcl/Makefile.in index 84a7299f7..db8eaa874 100644 --- a/Examples/test-suite/tcl/Makefile.in +++ b/Examples/test-suite/tcl/Makefile.in @@ -7,6 +7,9 @@ TCLSH = tclsh SCRIPTSUFFIX = _runme.tcl HAVE_CXX11 = @HAVE_CXX11@ +HAVE_CXX14 = @HAVE_CXX14@ +HAVE_CXX17 = @HAVE_CXX17@ +HAVE_CXX20 = @HAVE_CXX20@ srcdir = @srcdir@ top_srcdir = @top_srcdir@ top_builddir = @top_builddir@ diff --git a/configure.ac b/configure.ac index 188b2397f..4a7c76c79 100644 --- a/configure.ac +++ b/configure.ac @@ -304,40 +304,52 @@ if test x"$enable_cpp11_testing" = xyes; then CXX_SAVED=$CXX CXXCPP_SAVED=$CXXCPP - # Test for c++17 + # Test for c++20 CXXCPP=" " - AX_CXX_COMPILE_STDCXX(17, [noext], [optional]) - AC_MSG_CHECKING([whether C++11 to C++17 testing is enabled]) - if test "$HAVE_CXX17" = "1"; then + AX_CXX_COMPILE_STDCXX(20, [noext], [optional]) + AC_MSG_CHECKING([whether C++11 to C++20 testing is enabled]) + if test "$HAVE_CXX20" = "1"; then AC_MSG_RESULT([yes]) PLATCXXFLAGS="$CXXCPP $PLATCXXFLAGS" + HAVE_CXX17="1" HAVE_CXX14="1" HAVE_CXX11="1" else - AC_MSG_RESULT([no]) - - # Test for c++14 + # Test for c++17 CXXCPP=" " - CXX=$CXX_SAVED - AX_CXX_COMPILE_STDCXX(14, [noext], [optional]) - AC_MSG_CHECKING([whether C++11 to C++14 testing is enabled]) - if test "$HAVE_CXX14" = "1"; then + AX_CXX_COMPILE_STDCXX(17, [noext], [optional]) + AC_MSG_CHECKING([whether C++11 to C++17 testing is enabled]) + if test "$HAVE_CXX17" = "1"; then AC_MSG_RESULT([yes]) PLATCXXFLAGS="$CXXCPP $PLATCXXFLAGS" + HAVE_CXX14="1" HAVE_CXX11="1" else AC_MSG_RESULT([no]) - # Test for c++11 + # Test for c++14 CXXCPP=" " CXX=$CXX_SAVED - AX_CXX_COMPILE_STDCXX(11, [noext], [optional]) - AC_MSG_CHECKING([whether C++11 testing is enabled]) - if test "$HAVE_CXX11" = "1"; then + AX_CXX_COMPILE_STDCXX(14, [noext], [optional]) + AC_MSG_CHECKING([whether C++11 to C++14 testing is enabled]) + if test "$HAVE_CXX14" = "1"; then AC_MSG_RESULT([yes]) PLATCXXFLAGS="$CXXCPP $PLATCXXFLAGS" + HAVE_CXX11="1" else AC_MSG_RESULT([no]) + + # Test for c++11 + CXXCPP=" " + CXX=$CXX_SAVED + AX_CXX_COMPILE_STDCXX(11, [noext], [optional]) + AC_MSG_CHECKING([whether C++11 testing is enabled]) + if test "$HAVE_CXX11" = "1"; then + AC_MSG_RESULT([yes]) + PLATCXXFLAGS="$CXXCPP $PLATCXXFLAGS" + else + AC_MSG_RESULT([no]) + fi fi fi fi @@ -346,6 +358,9 @@ if test x"$enable_cpp11_testing" = xyes; then CXXCPP=$CXXCPP_SAVED fi AC_SUBST(HAVE_CXX11) +AC_SUBST(HAVE_CXX14) +AC_SUBST(HAVE_CXX17) +AC_SUBST(HAVE_CXX20) # On darwin 10.7,10.8,10.9 using clang++, need to ensure using # libc++ for tests and examples to run under mono. May affect From 3140acd748fb9473ef5c1bfc6dbdc94c89e018d1 Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Mon, 25 Jul 2022 16:45:27 +1200 Subject: [PATCH 549/662] Run C++14 and C++17 tests with appropriate compiler Previously these testcases had C++98 fallback versions of the testcase code to feed to the compiler if it didn't set __cplusplus to a value which indicated support for the required C++ version, as well as the C++14 or C++17 code which was fed to SWIG, and also to the compiler if it was new enough. This approach allowed some testing of such features with an older compiler, but it complicates the testcases and not all new C++ features can be tested in this way (indeed some of the existing testcases don't fully exercise the feature being tested currently). C++14 and C++17 support are also much more widespread than they were 3.5 years ago when this approach was first implemented, so it makes more sense to switch C++14 and C++17 testcases to require a suitable compiler, like how C++11 testing always has. --- Examples/test-suite/common.mk | 10 +- .../cpp14_binary_integer_literals.i | 24 +--- .../test-suite/cpp17_hex_floating_literals.i | 32 +---- Examples/test-suite/cpp17_nested_namespaces.i | 118 ------------------ Examples/test-suite/cpp17_u8_char_literals.i | 20 +-- 5 files changed, 8 insertions(+), 196 deletions(-) diff --git a/Examples/test-suite/common.mk b/Examples/test-suite/common.mk index 0952ee8c1..785f1aa53 100644 --- a/Examples/test-suite/common.mk +++ b/Examples/test-suite/common.mk @@ -168,11 +168,6 @@ CPP_TEST_CASES += \ cpp_parameters \ cpp_static \ cpp_typedef \ - cpp14_binary_integer_literals \ - cpp17_hex_floating_literals \ - cpp17_nested_namespaces \ - cpp17_nspace_nested_namespaces \ - cpp17_u8_char_literals \ curiously_recurring_template_pattern \ default_args \ default_arg_expressions \ @@ -637,12 +632,17 @@ CPP11_TEST_BROKEN = \ # C++14 test cases. CPP14_TEST_CASES += \ + cpp14_binary_integer_literals \ # Broken C++14 test cases. CPP14_TEST_BROKEN = \ # C++17 test cases. CPP17_TEST_CASES += \ + cpp17_hex_floating_literals \ + cpp17_nested_namespaces \ + cpp17_nspace_nested_namespaces \ + cpp17_u8_char_literals \ # Broken C++17 test cases. CPP17_TEST_BROKEN = \ diff --git a/Examples/test-suite/cpp14_binary_integer_literals.i b/Examples/test-suite/cpp14_binary_integer_literals.i index 9c696b5a5..5e736be64 100644 --- a/Examples/test-suite/cpp14_binary_integer_literals.i +++ b/Examples/test-suite/cpp14_binary_integer_literals.i @@ -1,31 +1,9 @@ %module cpp14_binary_integer_literals -// Tests are designed so that code compiles with C++98 compilers - -%{ -#if __cplusplus >= 201402L -#define CPP14 1 -#endif -%} - +%inline %{ int b1 = 0b1; int b2 = 0b10; long b3 = 0b11l; unsigned long b4 = 0b100ul; unsigned long b5 = 0B101UL; - -%{ -#if defined(CPP14) -int b1 = 0b1; -int b2 = 0b10; -long b3 = 0b11l; -unsigned long b4 = 0b100ul; -unsigned long b5 = 0B101UL; -#else -int b1 = 1; -int b2 = 2; -long b3 = 3; -unsigned long b4 = 4; -unsigned long b5 = 5; -#endif %} diff --git a/Examples/test-suite/cpp17_hex_floating_literals.i b/Examples/test-suite/cpp17_hex_floating_literals.i index dfc1dc0cf..dd8e09936 100644 --- a/Examples/test-suite/cpp17_hex_floating_literals.i +++ b/Examples/test-suite/cpp17_hex_floating_literals.i @@ -1,13 +1,6 @@ %module cpp17_hex_floating_literals -// Tests are designed so that code compiles with C++98 compilers - -%{ -#if __cplusplus >= 201703L -#define CPP17 1 -#endif -%} - +%inline %{ double f1 = 0x.0p1; double f2 = 0x0.p1; double f3 = 0x0.0p-1; @@ -17,27 +10,4 @@ double f6 = 0x0.10P+10; double f7 = 0xb2F.p2; float f8 = 0x1234AP1F; float f9 = 0x45A1.D1A2p+10f; - -%{ -#if defined(CPP17) -double f1 = 0x.0p1; -double f2 = 0x0.p1; -double f3 = 0x0.0p-1; -double f4 = 0xf.p-1; -double f5 = 0xA.0p1; -double f6 = 0x0.10P+10; -double f7 = 0xb2F.p2; -float f8 = 0x1234AP1F; -float f9 = 0x45A1.D1A2p+10f; -#else -double f1 = 0.; -double f2 = 0.; -double f3 = 0.; -double f4 = 7.5; -double f5 = 20.; -double f6 = 64.; -double f7 = 11452.; -float f8 = 149140.f; -float f9 = 18253638.f; -#endif %} diff --git a/Examples/test-suite/cpp17_nested_namespaces.i b/Examples/test-suite/cpp17_nested_namespaces.i index b9ec9bd5a..fcbf24c9a 100644 --- a/Examples/test-suite/cpp17_nested_namespaces.i +++ b/Examples/test-suite/cpp17_nested_namespaces.i @@ -1,13 +1,5 @@ %module cpp17_nested_namespaces // Tests c++17 style nested namespaces -// Tests are designed so that code compiles with C++98 compilers - -#define CPP17 1 -%{ -#if __cplusplus >= 201703L -#define CPP17 1 -#endif -%} %inline %{ // Tests with namespaces already defined using C++98 style (non-nested) namespaces @@ -21,20 +13,10 @@ namespace A1 { }; } } -#if defined(CPP17) namespace A1::B1 { -#else -namespace A1 { - namespace B1 { -#endif A1Struct createA1Struct() { return ::A1::A1Struct(); } B1Struct createB1Struct() { return ::A1::B1::B1Struct(); } -#if !defined(CPP17) - } } -#else -} -#endif namespace A1 { namespace B1 { @@ -46,154 +28,54 @@ namespace A1 { } } -#if defined(CPP17) namespace A1::B1::C1 { -#else -namespace A1 { - namespace B1 { - namespace C1 { -#endif C1Struct createC1Struct() { return ::A1::B1::C1::C1Struct(); } -#if !defined(CPP17) - } - } } -#else -} -#endif %} %inline %{ // Tests with namespaces already defined using C++17 style (nested) namespaces -#if defined(CPP17) namespace A2::B2 { -#else -namespace A2 { - namespace B2 { -#endif struct B2Struct { void B2Method() {} }; -#if !defined(CPP17) - } } -#else -} -#endif -#if defined(CPP17) namespace A2::B2 { -#else -namespace A2 { - namespace B2 { -#endif B2Struct createB2Struct() { return ::A2::B2::B2Struct(); } -#if !defined(CPP17) - } } -#else -} -#endif -#if defined(CPP17) namespace A2::B2::C2 { -#else -namespace A2 { - namespace B2 { - namespace C2 { -#endif struct C2Struct { void C2Method() {} }; -#if !defined(CPP17) - } - } } -#else -} -#endif -#if defined(CPP17) namespace A2::B2::C2 { -#else -namespace A2 { - namespace B2 { - namespace C2 { -#endif C2Struct createC2Struct() { return ::A2::B2::C2::C2Struct(); } -#if !defined(CPP17) - } - } } -#else -} -#endif %} %inline %{ // Tests with namespaces already defined using C++17 style (nested) namespaces to 3 levels -#if defined(CPP17) namespace A3::B3::C3 { -#else -namespace A3 { - namespace B3 { - namespace C3 { -#endif struct C3Struct { void C3Method() {} }; -#if !defined(CPP17) - } - } } -#else -} -#endif -#if defined(CPP17) namespace A3::B3::C3 { -#else -namespace A3 { - namespace B3 { - namespace C3 { -#endif C3Struct createC3Struct() { return ::A3::B3::C3::C3Struct(); } -#if !defined(CPP17) - } - } } -#else -} -#endif -#if defined(CPP17) namespace A3::B3 { -#else -namespace A3 { - namespace B3 { -#endif struct B3Struct { void B3Method() {} }; -#if !defined(CPP17) - } } -#else -} -#endif -#if defined(CPP17) namespace A3::B3 { -#else -namespace A3 { - namespace B3 { -#endif B3Struct createB3Struct() { return ::A3::B3::B3Struct(); } -#if !defined(CPP17) - } } -#else -} -#endif %} diff --git a/Examples/test-suite/cpp17_u8_char_literals.i b/Examples/test-suite/cpp17_u8_char_literals.i index 16f0498ec..e2e8e0d31 100644 --- a/Examples/test-suite/cpp17_u8_char_literals.i +++ b/Examples/test-suite/cpp17_u8_char_literals.i @@ -1,27 +1,9 @@ %module cpp17_u8_char_literals -// Tests are designed so that code compiles with C++98 compilers - -%{ -#if __cplusplus >= 201703L -#define CPP17 1 -#endif -%} - // UTF-8 character literals are type `char` in C++17 but `char8_t` in C++20, // but the latter can be assigned to `char`. +%inline %{ char a = u8'a'; char u = u8'u'; char u8 = u8'8'; - -%{ -#if defined(CPP17) -char a = u8'a'; -char u = u8'u'; -char u8 = u8'8'; -#else -char a = 'a'; -char u = 'u'; -char u8 = '8'; -#endif %} From 1bfe88eeda08d04f33e98281d9f59a5aacb1f42f Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Mon, 25 Jul 2022 18:13:59 +1200 Subject: [PATCH 550/662] Support binary integer literals in the preprocessor --- CHANGES.current | 3 +++ Examples/test-suite/cpp14_binary_integer_literals.i | 4 ++++ Source/Preprocessor/expr.c | 7 ++++++- 3 files changed, 13 insertions(+), 1 deletion(-) diff --git a/CHANGES.current b/CHANGES.current index 1f0dd3807..b0488780c 100644 --- a/CHANGES.current +++ b/CHANGES.current @@ -7,6 +7,9 @@ the issue number to the end of the URL: https://github.com/swig/swig/issues/ Version 4.1.0 (in progress) =========================== +2022-07-25: olly + Support for C++14 binary integer literals in preprocessor expressions. + 2022-07-20: wsfulton [C#, Java] Ensure the order of interfaces generated in proxy interfaces for the %interface family of macros is the same as that parsed from the bases in C++. diff --git a/Examples/test-suite/cpp14_binary_integer_literals.i b/Examples/test-suite/cpp14_binary_integer_literals.i index 5e736be64..54e070032 100644 --- a/Examples/test-suite/cpp14_binary_integer_literals.i +++ b/Examples/test-suite/cpp14_binary_integer_literals.i @@ -1,5 +1,9 @@ %module cpp14_binary_integer_literals +#if 0b100 < 4 +# error binary constant in preprocessor expression failed +#endif + %inline %{ int b1 = 0b1; int b2 = 0b10; diff --git a/Source/Preprocessor/expr.c b/Source/Preprocessor/expr.c index 52e467b6c..15bf99657 100644 --- a/Source/Preprocessor/expr.c +++ b/Source/Preprocessor/expr.c @@ -318,7 +318,12 @@ int Preprocessor_expr(DOH *s, int *error) { if ((token == SWIG_TOKEN_INT) || (token == SWIG_TOKEN_UINT) || (token == SWIG_TOKEN_LONG) || (token == SWIG_TOKEN_ULONG)) { /* A number. Reduce EXPR_TOP to an EXPR_VALUE */ char *c = Char(Scanner_text(scan)); - stack[sp].value = (long) strtol(c, 0, 0); + if (c[0] == '0' && (c[1] == 'b' || c[1] == 'B')) { + // strtol() doesn't handle binary constants. + stack[sp].value = (long) strtol(c + 2, 0, 2); + } else { + stack[sp].value = (long) strtol(c, 0, 0); + } stack[sp].svalue = 0; stack[sp].op = EXPR_VALUE; } else if ((token == SWIG_TOKEN_MINUS) || (token == SWIG_TOKEN_PLUS) || (token == SWIG_TOKEN_LNOT) || (token == SWIG_TOKEN_NOT)) { From c759da250fa7c57dd559d8d7dbae3b9e6d9a625f Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Mon, 25 Jul 2022 18:17:04 +1200 Subject: [PATCH 551/662] Add tests for binary integer literal constants --- Examples/test-suite/cpp14_binary_integer_literals.i | 4 ++++ .../python/cpp14_binary_integer_literals_runme.py | 9 +++++++++ 2 files changed, 13 insertions(+) diff --git a/Examples/test-suite/cpp14_binary_integer_literals.i b/Examples/test-suite/cpp14_binary_integer_literals.i index 54e070032..0cabb1c74 100644 --- a/Examples/test-suite/cpp14_binary_integer_literals.i +++ b/Examples/test-suite/cpp14_binary_integer_literals.i @@ -10,4 +10,8 @@ int b2 = 0b10; long b3 = 0b11l; unsigned long b4 = 0b100ul; unsigned long b5 = 0B101UL; +#define b6 0b110 +const int b7 = 0b111; %} + +%constant int b8 = 0b1000; diff --git a/Examples/test-suite/python/cpp14_binary_integer_literals_runme.py b/Examples/test-suite/python/cpp14_binary_integer_literals_runme.py index 8274ec6b5..ee308aa39 100644 --- a/Examples/test-suite/python/cpp14_binary_integer_literals_runme.py +++ b/Examples/test-suite/python/cpp14_binary_integer_literals_runme.py @@ -14,3 +14,12 @@ if cvar.b4 != 4: if cvar.b5 != 5: raise RuntimeError + +if b6 != 6: + raise RuntimeError + +if b7 != 7: + raise RuntimeError + +if b8 != 8: + raise RuntimeError From 9d3fb41eef3897ce2942beedf8ca546646f22293 Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Tue, 26 Jul 2022 10:11:50 +1200 Subject: [PATCH 552/662] Fix MSVC error in cpp_typedef.i MSVC in C++20 mode complains: error C7626: unnamed class used in typedef name cannot declare members other than non-static data members, member enumerations, or member classes The struct member in question isn't actually used by the testcase, so just remove it. --- Examples/test-suite/cpp_typedef.i | 1 - 1 file changed, 1 deletion(-) diff --git a/Examples/test-suite/cpp_typedef.i b/Examples/test-suite/cpp_typedef.i index 8578988e9..140df34ae 100644 --- a/Examples/test-suite/cpp_typedef.i +++ b/Examples/test-suite/cpp_typedef.i @@ -30,7 +30,6 @@ public: // Test that the correct types are used for typedef struct declarations typedef struct { int something; - void m() {} } UnnamedStruct; typedef struct NamedStruct { From 4a15f3934d2a55835b7cc63320ac071a4bc6032d Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Tue, 26 Jul 2022 10:24:48 +1200 Subject: [PATCH 553/662] Fix MSVC error in nested_class.i MSVC now fails with: error C4596: 'foo': illegal qualified name in member declaration Such redundant qualification is invalid. Compilers used to be permissive here (so it's useful for SWIG to handle it), but compilers increasingly complain about it so adjust the testcase to show the compiler a valid version, and only test the redundant qualification with SWIG. --- Examples/test-suite/nested_class.i | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/Examples/test-suite/nested_class.i b/Examples/test-suite/nested_class.i index c778a12cf..cb9f27b31 100644 --- a/Examples/test-suite/nested_class.i +++ b/Examples/test-suite/nested_class.i @@ -133,8 +133,13 @@ struct Outer { Integer x; } InnerClass4Typedef; -#ifdef _MSC_VER - int Outer::foo(){ return 1; } // should correctly ignore qualification here (#508) +#ifdef SWIG + // SWIG should ignore the redundant qualification here (#508)... + int Outer::foo(){ return 1; } +#else + // ..but that redundant qualification is actually invalid and many compilers + // now reject it with an error, so feed a valid version to the compiler. + int foo(){ return 1; } #endif typedef struct { From 4f44d0a1eae1736af6cc7efb0c791e204663efee Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Tue, 26 Jul 2022 10:30:19 +1200 Subject: [PATCH 554/662] Attempt to fix cpp11_result_of for MSVC MSVC fails with: cpp11_result_of_wrap.cxx(3211): error C2672: 'test_result_impl': no matching overloaded function found cpp11_result_of_wrap.cxx(3211): error C2893: Failed to specialize function template 'std::result_of::type test_result_impl(Fun,Arg)' cpp11_result_of_wrap.cxx(3150): note: see declaration of 'test_result_impl' cpp11_result_of_wrap.cxx(3211): note: With the following template arguments: cpp11_result_of_wrap.cxx(3211): note: 'Fun=double (__cdecl *)(double)' cpp11_result_of_wrap.cxx(3211): note: 'Arg=int' Try making the second parameter double to match the template. --- Examples/test-suite/cpp11_result_of.i | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Examples/test-suite/cpp11_result_of.i b/Examples/test-suite/cpp11_result_of.i index 44e7299b0..f37705415 100644 --- a/Examples/test-suite/cpp11_result_of.i +++ b/Examples/test-suite/cpp11_result_of.i @@ -55,10 +55,10 @@ std::result_of< fn_ptr(double) >::type test_result_alternative1(double(*fun)(dou #include void cpp_testing() { - std::cout << "result: " << test_result_impl(square, 3) << std::endl; - std::cout << "result: " << test_result_impl(square, 4) << std::endl; - std::cout << "result: " << test_result_impl< fn_ptr, double >(square, 5) << std::endl; - std::cout << "result: " << test_result_alternative1(square, 6) << std::endl; + std::cout << "result: " << test_result_impl(square, 3.0) << std::endl; + std::cout << "result: " << test_result_impl(square, 4.0) << std::endl; + std::cout << "result: " << test_result_impl< fn_ptr, double >(square, 5.0) << std::endl; + std::cout << "result: " << test_result_alternative1(square, 6.0) << std::endl; } %} From 06d375cdab63842b223ea5b9091ad0336144e899 Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Tue, 26 Jul 2022 14:59:42 +1200 Subject: [PATCH 555/662] [Tcl] Fix handling of long long on 32-bit platforms Fixes https://sourceforge.net/p/swig/bugs/977/ reported by Vera and Kjell Wooding. Closes #2331 --- CHANGES.current | 6 +++++ Doc/Manual/Tcl.html | 6 ++--- Examples/test-suite/tcl/integers_runme.tcl | 24 +++++++++++++++++++ Lib/tcl/tclprimtypes.swg | 27 ++++------------------ 4 files changed, 38 insertions(+), 25 deletions(-) create mode 100644 Examples/test-suite/tcl/integers_runme.tcl diff --git a/CHANGES.current b/CHANGES.current index 15769cbdf..89bceac9e 100644 --- a/CHANGES.current +++ b/CHANGES.current @@ -7,6 +7,12 @@ the issue number to the end of the URL: https://github.com/swig/swig/issues/ Version 4.1.0 (in progress) =========================== +2022-07-26: olly + [Tcl] https://sourceforge.net/p/swig/bugs/977/ + Fix handling of long long on 32-bit platforms. This fix raises + SWIG's minimum supported Tcl version to 8.4.0 (which was released + just under 20 years ago). + 2022-07-26: olly Fix incorrect operator precedence in preprocessor expressions. diff --git a/Doc/Manual/Tcl.html b/Doc/Manual/Tcl.html index bab5a8c1c..c271a2ee6 100644 --- a/Doc/Manual/Tcl.html +++ b/Doc/Manual/Tcl.html @@ -79,9 +79,9 @@

    -This chapter discusses SWIG's support of Tcl. SWIG currently requires -Tcl 8.0 or a later release. Earlier releases of SWIG supported Tcl 7.x, but -this is no longer supported. +This chapter discusses SWIG's support of Tcl. Since SWIG 4.1.0, Tcl 8.4 or a +later release is required. Prior to that earlier Tcl 8.x releases were also +supported.

    37.1 Preliminaries

    diff --git a/Examples/test-suite/tcl/integers_runme.tcl b/Examples/test-suite/tcl/integers_runme.tcl new file mode 100644 index 000000000..c04dd1e9e --- /dev/null +++ b/Examples/test-suite/tcl/integers_runme.tcl @@ -0,0 +1,24 @@ +if [ catch { load ./integers[info sharedlibextension] integers} err_msg ] { + puts stderr "Could not load shared object:\n$err_msg" +} + +set val 3902408827 +if {[signed_long_identity $val] != $val} { + puts stderr "Runtime test 1 failed" + exit 1 +} + +if {[unsigned_long_identity $val] != $val} { + puts stderr "Runtime test 2 failed" + exit 1 +} + +if {[signed_long_long_identity $val] != $val} { + puts stderr "Runtime test 3 failed" + exit 1 +} + +if {[unsigned_long_long_identity $val] != $val} { + puts stderr "Runtime test 4 failed" + exit 1 +} diff --git a/Lib/tcl/tclprimtypes.swg b/Lib/tcl/tclprimtypes.swg index 3b6d04f59..febbffb73 100644 --- a/Lib/tcl/tclprimtypes.swg +++ b/Lib/tcl/tclprimtypes.swg @@ -136,30 +136,13 @@ SWIG_From_dec(long long)(long long value) SWIGINTERN int SWIG_AsVal_dec(long long)(Tcl_Obj *obj, long long *val) { - long v; - if (Tcl_GetLongFromObj(0,obj, &v) == TCL_OK) { + Tcl_WideInt v; + if (Tcl_GetWideIntFromObj(0, obj, &v) == TCL_OK) { + if (sizeof(v) > sizeof(*val) && (v < LLONG_MIN || v > LLONG_MAX)) { + return SWIG_OverflowError; + } if (val) *val = v; return SWIG_OK; - } else { - int len = 0; - const char *nptr = Tcl_GetStringFromObj(obj, &len); - if (nptr && len > 0) { - char *endptr; - long long v; - errno = 0; - v = strtoll(nptr, &endptr,0); - if (nptr[0] == '\0' || *endptr != '\0') - return SWIG_TypeError; - if ((v == LLONG_MAX || v == LLONG_MIN) && errno == ERANGE) { - errno = 0; - return SWIG_OverflowError; - } else { - if (*endptr == '\0') { - if (val) *val = v; - return SWIG_OK; - } - } - } } return SWIG_TypeError; } From a80e7485658adeaf66f300a00eafe205f19da48a Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Wed, 27 Jul 2022 08:47:53 +1200 Subject: [PATCH 556/662] [php] Add missing qualification in test suite helper This would cause an error due to failing to find the function to call if certain testcase checks failed. Bug introduced in eaf311a650c104e40aad356863e965f0b2969b35 --- Examples/test-suite/php/tests.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Examples/test-suite/php/tests.php b/Examples/test-suite/php/tests.php index 8561ef826..92e554741 100644 --- a/Examples/test-suite/php/tests.php +++ b/Examples/test-suite/php/tests.php @@ -194,7 +194,7 @@ class check { } static function fail($pattern) { - fail_(null, $pattern); + check::fail_(null, $pattern); } static function warn($pattern) { From b57248cc1a0afd442f05bb3ccaa3ea021221c358 Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Wed, 27 Jul 2022 08:49:15 +1200 Subject: [PATCH 557/662] [php] Add parentheses around $value when casting In some cases $value can be an expression without parentheses around it, and we want to cast the result of the whole expression. --- Lib/php/const.i | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Lib/php/const.i b/Lib/php/const.i index 6e83ffe88..33060dc04 100644 --- a/Lib/php/const.i +++ b/Lib/php/const.i @@ -12,11 +12,11 @@ unsigned char, signed char, enum SWIGTYPE %{ - zend_declare_class_constant_long(SWIG_Php_ce_$class, "$const_name", sizeof("$const_name") - 1, ($1_type)$value); + zend_declare_class_constant_long(SWIG_Php_ce_$class, "$const_name", sizeof("$const_name") - 1, ($1_type)($value)); %} %typemap(classconsttab) bool %{ - zend_declare_class_constant_bool(SWIG_Php_ce_$class, "$const_name", sizeof("$const_name") - 1, ($1_type)$value); + zend_declare_class_constant_bool(SWIG_Php_ce_$class, "$const_name", sizeof("$const_name") - 1, ($1_type)($value)); %} %typemap(classconsttab) float, @@ -48,7 +48,7 @@ { zval z; ZVAL_UNDEF(&z); - SWIG_SetPointerZval(&z, (void*)$value, $1_descriptor, 0); + SWIG_SetPointerZval(&z, (void*)($value), $1_descriptor, 0); zval_copy_ctor(&z); zend_declare_class_constant(SWIG_Php_ce_$class, "$const_name", sizeof("$const_name") - 1, &z); } @@ -65,10 +65,10 @@ unsigned char, signed char, enum SWIGTYPE - "SWIG_LONG_CONSTANT($symname, ($1_type)$value);"; + "SWIG_LONG_CONSTANT($symname, ($1_type)($value));"; %typemap(consttab) bool - "SWIG_BOOL_CONSTANT($symname, ($1_type)$value);"; + "SWIG_BOOL_CONSTANT($symname, ($1_type)($value));"; %typemap(consttab) float, double @@ -92,7 +92,7 @@ SWIGTYPE [] { zend_constant c; ZVAL_UNDEF(&c.value); - SWIG_SetPointerZval(&c.value, (void*)$value, $1_descriptor, 0); + SWIG_SetPointerZval(&c.value, (void*)($value), $1_descriptor, 0); zval_copy_ctor(&c.value); c.name = zend_string_init("$symname", sizeof("$symname") - 1, 0); SWIG_ZEND_CONSTANT_SET_FLAGS(&c, CONST_CS, module_number); From 36310c04e5c3706d8a9d8c1346f403f2b12d3f56 Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Wed, 27 Jul 2022 08:52:33 +1200 Subject: [PATCH 558/662] Add comments to clarify how #define gets wrapped It took me a while to fully get my head around this, and I'd like to help out future developers. --- CHANGES.current | 3 +++ Source/CParse/parser.y | 3 +++ Source/Preprocessor/expr.c | 5 +++++ 3 files changed, 11 insertions(+) diff --git a/CHANGES.current b/CHANGES.current index 3e076d60f..38c0b7011 100644 --- a/CHANGES.current +++ b/CHANGES.current @@ -7,6 +7,9 @@ the issue number to the end of the URL: https://github.com/swig/swig/issues/ Version 4.1.0 (in progress) =========================== +2022-07-27: ZackerySpytz, olly + #1622 Add support for the C++20 spaceship operator (<=>). + 2022-07-26: olly [Tcl] https://sourceforge.net/p/swig/bugs/977/ Fix handling of long long on 32-bit platforms. This fix raises diff --git a/Source/CParse/parser.y b/Source/CParse/parser.y index ddb9634b2..1a5d4a201 100644 --- a/Source/CParse/parser.y +++ b/Source/CParse/parser.y @@ -1951,6 +1951,9 @@ clear_directive : CLEAR tm_list SEMI { /* ------------------------------------------------------------ %constant name = value; %constant type name = value; + + Note: Source/Preprocessor/cpp.c injects `%constant X = Y;` for + each `#define X Y` so that's handled here too. ------------------------------------------------------------ */ constant_directive : CONSTANT identifier EQUAL definetype SEMI { diff --git a/Source/Preprocessor/expr.c b/Source/Preprocessor/expr.c index 24cbb7603..b03060939 100644 --- a/Source/Preprocessor/expr.c +++ b/Source/Preprocessor/expr.c @@ -10,6 +10,11 @@ * * Integer arithmetic expression evaluator used to handle expressions * encountered during preprocessing. + * + * Note that this is used for expressions in `#if` and the like, but not + * for expressions in `#define` which SWIG wraps as constants - for those + * we inject a `%constant` directive which is handled by the parser in + * `Source/CParse/parser.y`. * ----------------------------------------------------------------------------- */ #include "swig.h" From cb887ed2d477a2ebc2b14aa5d5ec063e5ce9309f Mon Sep 17 00:00:00 2001 From: Zackery Spytz Date: Tue, 3 Sep 2019 16:48:24 -0600 Subject: [PATCH 559/662] Add support for the <=> operator (C++20) --- Lib/swigwarnings.swg | 1 + Source/CParse/cscanner.c | 2 ++ Source/CParse/parser.y | 8 ++++++-- Source/Include/swigwarn.h | 1 + Source/Swig/scanner.c | 14 ++++++++++++-- Source/Swig/swigscan.h | 1 + 6 files changed, 23 insertions(+), 4 deletions(-) diff --git a/Lib/swigwarnings.swg b/Lib/swigwarnings.swg index 3f9ddcb58..63ae4c65a 100644 --- a/Lib/swigwarnings.swg +++ b/Lib/swigwarnings.swg @@ -108,6 +108,7 @@ %define SWIGWARN_IGNORE_OPERATOR_NEWARR_MSG "394:operator new[] ignored" %enddef %define SWIGWARN_IGNORE_OPERATOR_DELARR_MSG "395:operator delete[] ignored" %enddef %define SWIGWARN_IGNORE_OPERATOR_REF_MSG "396:operator*() ignored" %enddef +%define SWIGWARN_IGNORE_OPERATOR_LTEQUALGT_MSG "397:operator<=> ignored" %enddef #define %ignoreoperator(Oper) %ignorewarn(SWIGWARN_IGNORE_OPERATOR_##Oper##_MSG) diff --git a/Source/CParse/cscanner.c b/Source/CParse/cscanner.c index 558a9c6cf..db0e6df27 100644 --- a/Source/CParse/cscanner.c +++ b/Source/CParse/cscanner.c @@ -331,6 +331,8 @@ static int yylook(void) { return COLON; case SWIG_TOKEN_DCOLONSTAR: return DSTAR; + case SWIG_TOKEN_LTEQUALGT: + return LESSEQUALGREATER; case SWIG_TOKEN_DCOLON: { diff --git a/Source/CParse/parser.y b/Source/CParse/parser.y index 1a5d4a201..e2d37dae0 100644 --- a/Source/CParse/parser.y +++ b/Source/CParse/parser.y @@ -1626,7 +1626,7 @@ static String *add_qualifier_to_declarator(SwigType *type, SwigType *qualifier) %token TYPEMAP EXCEPT ECHO APPLY CLEAR SWIGTEMPLATE FRAGMENT %token WARN %token LESSTHAN GREATERTHAN DELETE_KW DEFAULT -%token LESSTHANOREQUALTO GREATERTHANOREQUALTO EQUALTO NOTEQUALTO +%token LESSTHANOREQUALTO GREATERTHANOREQUALTO EQUALTO NOTEQUALTO LESSEQUALGREATER %token ARROW %token QUESTIONMARK %token TYPES PARMS @@ -1647,7 +1647,7 @@ static String *add_qualifier_to_declarator(SwigType *type, SwigType *qualifier) %left XOR %left AND %left EQUALTO NOTEQUALTO -%left GREATERTHAN LESSTHAN GREATERTHANOREQUALTO LESSTHANOREQUALTO +%left GREATERTHAN LESSTHAN GREATERTHANOREQUALTO LESSTHANOREQUALTO LESSEQUALGREATER %left LSHIFT RSHIFT %left PLUS MINUS %left STAR SLASH MODULO @@ -6844,6 +6844,10 @@ exprcompound : expr PLUS expr { $$.val = NewStringf("%s <= %s", COMPOUND_EXPR_VAL($1), COMPOUND_EXPR_VAL($3)); $$.type = cparse_cplusplus ? T_BOOL : T_INT; } + | expr LESSEQUALGREATER expr { + $$.val = NewStringf("%s <=> %s", COMPOUND_EXPR_VAL($1), COMPOUND_EXPR_VAL($3)); + $$.type = T_BOOL; + } | expr QUESTIONMARK expr COLON expr %prec QUESTIONMARK { $$.val = NewStringf("%s?%s:%s", COMPOUND_EXPR_VAL($1), COMPOUND_EXPR_VAL($3), COMPOUND_EXPR_VAL($5)); /* This may not be exactly right, but is probably good enough diff --git a/Source/Include/swigwarn.h b/Source/Include/swigwarn.h index f37cb0ef2..89df97a88 100644 --- a/Source/Include/swigwarn.h +++ b/Source/Include/swigwarn.h @@ -147,6 +147,7 @@ #define WARN_IGNORE_OPERATOR_NEWARR 394 /* new [] */ #define WARN_IGNORE_OPERATOR_DELARR 395 /* delete [] */ #define WARN_IGNORE_OPERATOR_REF 396 /* operator *() */ +#define WARN_IGNORE_OPERATOR_LTEQUALGT 397 /* <=> */ /* please leave 350-399 free for WARN_IGNORE_OPERATOR_* */ diff --git a/Source/Swig/scanner.c b/Source/Swig/scanner.c index b03a07a5b..961da8343 100644 --- a/Source/Swig/scanner.c +++ b/Source/Swig/scanner.c @@ -893,8 +893,18 @@ static int look(Scanner *s) { } if (c == '<') state = 240; - else if (c == '=') - return SWIG_TOKEN_LTEQUAL; + else if (c == '=') { + if ((c = nextchar(s)) == 0) { + brackets_increment(s); + return SWIG_TOKEN_LTEQUAL; + } else if (c == '>') { /* Spaceship operator */ + return SWIG_TOKEN_LTEQUALGT; + } else { + retract(s, 1); + brackets_increment(s); + return SWIG_TOKEN_LTEQUAL; + } + } else { retract(s, 1); brackets_increment(s); diff --git a/Source/Swig/swigscan.h b/Source/Swig/swigscan.h index 526413a14..0476e8587 100644 --- a/Source/Swig/swigscan.h +++ b/Source/Swig/swigscan.h @@ -116,3 +116,4 @@ extern void Scanner_locator(Scanner *, String *loc); #define SWIG_TOKEN_MODEQUAL 134 /* %= */ #define SWIG_TOKEN_ARROW 135 /* -> */ #define SWIG_TOKEN_ARROWSTAR 136 /* ->* */ +#define SWIG_TOKEN_LTEQUALGT 137 /* <=> */ From 02b4bd8eca73c6de0bb56f866f19fc30c63b7ba9 Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Wed, 9 Mar 2022 10:08:17 +1300 Subject: [PATCH 560/662] Fix spaceship operator bugs, document, add tests Remove some erroneously added brackets_increment() calls. Reject <=> in preprocessor expressions with a clear error message (it seems it isn't supported here - clang and gcc don't at least). The type returned by `<=>` is not `bool`. We pretend it's `int` for now, which should work for how it's likely to be used in constant expressions. Fixes #1622 --- Doc/Devel/scanner.html | 1 + Doc/Manual/CPlusPlus20.html | 15 ++++++++++ Examples/test-suite/common.mk | 1 + .../test-suite/cpp20_spaceship_operator.i | 28 +++++++++++++++++++ .../test-suite/errors/pp_expressions_bad.i | 4 +++ .../errors/pp_expressions_bad.stderr | 2 ++ .../php/cpp20_spaceship_operator_runme.php | 23 +++++++++++++++ Source/CParse/parser.y | 12 ++++++-- Source/Preprocessor/expr.c | 7 +++++ Source/Swig/scanner.c | 5 +--- 10 files changed, 91 insertions(+), 7 deletions(-) create mode 100644 Examples/test-suite/cpp20_spaceship_operator.i create mode 100644 Examples/test-suite/php/cpp20_spaceship_operator_runme.php diff --git a/Doc/Devel/scanner.html b/Doc/Devel/scanner.html index 65ef1d8e9..d620c3d98 100644 --- a/Doc/Devel/scanner.html +++ b/Doc/Devel/scanner.html @@ -204,6 +204,7 @@ SWIG_TOKEN_LESSTHAN < SWIG_TOKEN_GREATERTHAN > SWIG_TOKEN_LTEQUAL <= SWIG_TOKEN_GTEQUAL >= +SWIG_TOKEN_LTEQUALGT <=> SWIG_TOKEN_NOT ~ SWIG_TOKEN_LNOT ! SWIG_TOKEN_LBRACKET [ diff --git a/Doc/Manual/CPlusPlus20.html b/Doc/Manual/CPlusPlus20.html index 0a8b0027f..8db84bfd5 100644 --- a/Doc/Manual/CPlusPlus20.html +++ b/Doc/Manual/CPlusPlus20.html @@ -34,6 +34,21 @@ Work has only just begun on adding C++20 support.

    10.2 Core language changes

    +

    10.2.1 Spaceship operator

    + +

    +SWIG supports the spaceship operator <=> in constant +expressions. To simplifying handling the return value is currently +treated as an integer rather than std::strong_ordering, etc. +In practice we think that should do the right thing in most cases. +

    + +

    +SWIG also recognises operator<=> which can be wrapped +if renamed. There's not currently any default renaming for the operator +or attempts to automatically map it to a three-way comparison operator +in any target languages that have one. +

    10.3 Standard library changes

    diff --git a/Examples/test-suite/common.mk b/Examples/test-suite/common.mk index c1b339c54..838ea5d2a 100644 --- a/Examples/test-suite/common.mk +++ b/Examples/test-suite/common.mk @@ -649,6 +649,7 @@ CPP17_TEST_BROKEN = \ # C++20 test cases. CPP20_TEST_CASES += \ + cpp20_spaceship_operator \ # Broken C++20 test cases. CPP20_TEST_BROKEN = \ diff --git a/Examples/test-suite/cpp20_spaceship_operator.i b/Examples/test-suite/cpp20_spaceship_operator.i new file mode 100644 index 000000000..ddece13a0 --- /dev/null +++ b/Examples/test-suite/cpp20_spaceship_operator.i @@ -0,0 +1,28 @@ +%module cpp20_spaceship_operator + +%rename(spaceship) operator<=>; + +%inline %{ +#include + +int v = (-1 <=> 1 > 0) ? 7 : 42; + +// We use !(a >= b) here due to limited support for (a < b) in SWIG's parser. +#define ALIEN !(0 <=> 1 >= 0) + +const int SPACE = 3 <=> 3 == 0; + +struct A { + int v; + + explicit A(int v_) : v(v_) { } +}; + +int operator<=>(const A& a, const A& b) { + return a.v - b.v; +} + +int f(int v = (-1 <=> 1 > 0) ? 7 : 42) { return v; } +%} + +%constant int COMET = (4 <=> 2 > 0); diff --git a/Examples/test-suite/errors/pp_expressions_bad.i b/Examples/test-suite/errors/pp_expressions_bad.i index 445ed7949..3fa49ba4a 100644 --- a/Examples/test-suite/errors/pp_expressions_bad.i +++ b/Examples/test-suite/errors/pp_expressions_bad.i @@ -66,3 +66,7 @@ /* Unary + was a no-op and so this didn't give an error in SWIG < 4.1.0. */ #if "1" == +"1" #endif + +/* Spaceship operator doesn't seem to be allowed in preprocessor expressions. */ +#if (4 <=> 2) < 0 +#endif diff --git a/Examples/test-suite/errors/pp_expressions_bad.stderr b/Examples/test-suite/errors/pp_expressions_bad.stderr index 37f846c03..12eb42e04 100644 --- a/Examples/test-suite/errors/pp_expressions_bad.stderr +++ b/Examples/test-suite/errors/pp_expressions_bad.stderr @@ -31,3 +31,5 @@ pp_expressions_bad.i:64: Warning 202: Could not evaluate expression '"1" == ~"1" pp_expressions_bad.i:64: Warning 202: Syntax error: attempt to apply unary operator to string pp_expressions_bad.i:67: Warning 202: Could not evaluate expression '"1" == +"1"' pp_expressions_bad.i:67: Warning 202: Syntax error: attempt to apply unary operator to string +pp_expressions_bad.i:71: Warning 202: Could not evaluate expression '(4 <=> 2) < 0' +pp_expressions_bad.i:71: Warning 202: Spaceship operator (<=>) not allowed in preprocessor expression diff --git a/Examples/test-suite/php/cpp20_spaceship_operator_runme.php b/Examples/test-suite/php/cpp20_spaceship_operator_runme.php new file mode 100644 index 000000000..00484f742 --- /dev/null +++ b/Examples/test-suite/php/cpp20_spaceship_operator_runme.php @@ -0,0 +1,23 @@ + 0, true); + +check::equal(f(), 42); + +check::done(); diff --git a/Source/CParse/parser.y b/Source/CParse/parser.y index e2d37dae0..be5159a62 100644 --- a/Source/CParse/parser.y +++ b/Source/CParse/parser.y @@ -1647,7 +1647,8 @@ static String *add_qualifier_to_declarator(SwigType *type, SwigType *qualifier) %left XOR %left AND %left EQUALTO NOTEQUALTO -%left GREATERTHAN LESSTHAN GREATERTHANOREQUALTO LESSTHANOREQUALTO LESSEQUALGREATER +%left GREATERTHAN LESSTHAN GREATERTHANOREQUALTO LESSTHANOREQUALTO +%left LESSEQUALGREATER %left LSHIFT RSHIFT %left PLUS MINUS %left STAR SLASH MODULO @@ -6844,9 +6845,14 @@ exprcompound : expr PLUS expr { $$.val = NewStringf("%s <= %s", COMPOUND_EXPR_VAL($1), COMPOUND_EXPR_VAL($3)); $$.type = cparse_cplusplus ? T_BOOL : T_INT; } - | expr LESSEQUALGREATER expr { + | expr LESSEQUALGREATER expr { $$.val = NewStringf("%s <=> %s", COMPOUND_EXPR_VAL($1), COMPOUND_EXPR_VAL($3)); - $$.type = T_BOOL; + // Really `<=>` returns one of `std::strong_ordering`, + // `std::partial_ordering` or `std::weak_ordering`, but we + // fake it by treating the return value as `int`. The main + // thing to do with the return value in this context is to + // compare it with 0, for which `int` does the job. + $$.type = T_INT; } | expr QUESTIONMARK expr COLON expr %prec QUESTIONMARK { $$.val = NewStringf("%s?%s:%s", COMPOUND_EXPR_VAL($1), COMPOUND_EXPR_VAL($3), COMPOUND_EXPR_VAL($5)); diff --git a/Source/Preprocessor/expr.c b/Source/Preprocessor/expr.c index b03060939..557e0e752 100644 --- a/Source/Preprocessor/expr.c +++ b/Source/Preprocessor/expr.c @@ -445,6 +445,8 @@ int Preprocessor_expr(DOH *s, int *error) { stack[sp - 1].svalue = stack[sp].svalue; sp--; break; + case SWIG_TOKEN_LTEQUALGT: + goto spaceship_not_allowed; default: goto syntax_error_expected_operator; break; @@ -476,6 +478,11 @@ extra_rparen: errmsg = "Extra \')\'"; *error = 1; return 0; + +spaceship_not_allowed: + errmsg = "Spaceship operator (<=>) not allowed in preprocessor expression"; + *error = 1; + return 0; } /* ----------------------------------------------------------------------------- diff --git a/Source/Swig/scanner.c b/Source/Swig/scanner.c index 961da8343..4ac3e6c3c 100644 --- a/Source/Swig/scanner.c +++ b/Source/Swig/scanner.c @@ -895,17 +895,14 @@ static int look(Scanner *s) { state = 240; else if (c == '=') { if ((c = nextchar(s)) == 0) { - brackets_increment(s); return SWIG_TOKEN_LTEQUAL; } else if (c == '>') { /* Spaceship operator */ return SWIG_TOKEN_LTEQUALGT; } else { retract(s, 1); - brackets_increment(s); return SWIG_TOKEN_LTEQUAL; } - } - else { + } else { retract(s, 1); brackets_increment(s); return SWIG_TOKEN_LESSTHAN; From 61928bd882f3b53ebd88862bc9bb40f2bb33ca0d Mon Sep 17 00:00:00 2001 From: Zackery Spytz Date: Sat, 7 Dec 2019 21:08:11 -0700 Subject: [PATCH 561/662] Add support for C++20 "templated" lambdas Such as `auto lambda = [](std::vector t){};` --- Source/CParse/parser.y | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/Source/CParse/parser.y b/Source/CParse/parser.y index be5159a62..a8456826b 100644 --- a/Source/CParse/parser.y +++ b/Source/CParse/parser.y @@ -1713,7 +1713,7 @@ static String *add_qualifier_to_declarator(SwigType *type, SwigType *qualifier) %type type_specifier primitive_type_list ; %type fname stringtype; %type featattr; -%type lambda_introducer lambda_body; +%type lambda_introducer lambda_body lambda_template; %type lambda_tail; %type virt_specifier_seq virt_specifier_seq_opt; @@ -3420,17 +3420,17 @@ cpp_alternate_rettype : primitive_type { $$ = $1; } auto myFunc = [](int x, int y) throw() -> int { return x+y; }; auto six = [](int x, int y) { return x+y; }(4, 2); ------------------------------------------------------------ */ -cpp_lambda_decl : storage_class AUTO idcolon EQUAL lambda_introducer LPAREN parms RPAREN cpp_const lambda_body lambda_tail { +cpp_lambda_decl : storage_class AUTO idcolon EQUAL lambda_introducer lambda_template LPAREN parms RPAREN cpp_const lambda_body lambda_tail { $$ = new_node("lambda"); Setattr($$,"name",$3); add_symbols($$); } - | storage_class AUTO idcolon EQUAL lambda_introducer LPAREN parms RPAREN cpp_const ARROW type lambda_body lambda_tail { + | storage_class AUTO idcolon EQUAL lambda_introducer lambda_template LPAREN parms RPAREN cpp_const ARROW type lambda_body lambda_tail { $$ = new_node("lambda"); Setattr($$,"name",$3); add_symbols($$); } - | storage_class AUTO idcolon EQUAL lambda_introducer lambda_body lambda_tail { + | storage_class AUTO idcolon EQUAL lambda_introducer lambda_template lambda_body lambda_tail { $$ = new_node("lambda"); Setattr($$,"name",$3); add_symbols($$); @@ -3442,7 +3442,12 @@ lambda_introducer : LBRACKET { $$ = 0; } ; - +lambda_template : LESSTHAN { + skip_balanced('<','>'); + $$ = 0; + } + | empty { $$ = 0; } + ; lambda_body : LBRACE { skip_balanced('{','}'); $$ = 0; From e31de2aebba03425915dd9f399c60e9ec85a8ef4 Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Wed, 27 Jul 2022 09:30:30 +1200 Subject: [PATCH 562/662] Tidy up indentation --- Source/CParse/parser.y | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/Source/CParse/parser.y b/Source/CParse/parser.y index a8456826b..816264de6 100644 --- a/Source/CParse/parser.y +++ b/Source/CParse/parser.y @@ -3442,12 +3442,14 @@ lambda_introducer : LBRACKET { $$ = 0; } ; + lambda_template : LESSTHAN { skip_balanced('<','>'); $$ = 0; - } - | empty { $$ = 0; } - ; + } + | empty { $$ = 0; } + ; + lambda_body : LBRACE { skip_balanced('{','}'); $$ = 0; From 88f227b5da97bd30ab165a000530bb7468f96424 Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Wed, 27 Jul 2022 09:30:39 +1200 Subject: [PATCH 563/662] Add testcase --- Examples/test-suite/common.mk | 1 + Examples/test-suite/cpp20_lambda_template.i | 12 ++++++++++++ 2 files changed, 13 insertions(+) create mode 100644 Examples/test-suite/cpp20_lambda_template.i diff --git a/Examples/test-suite/common.mk b/Examples/test-suite/common.mk index 838ea5d2a..6ca3aef22 100644 --- a/Examples/test-suite/common.mk +++ b/Examples/test-suite/common.mk @@ -649,6 +649,7 @@ CPP17_TEST_BROKEN = \ # C++20 test cases. CPP20_TEST_CASES += \ + cpp20_lambda_template \ cpp20_spaceship_operator \ # Broken C++20 test cases. diff --git a/Examples/test-suite/cpp20_lambda_template.i b/Examples/test-suite/cpp20_lambda_template.i new file mode 100644 index 000000000..948364f42 --- /dev/null +++ b/Examples/test-suite/cpp20_lambda_template.i @@ -0,0 +1,12 @@ +%module cpp20_lambda_template + +// We just want to test that SWIG doesn't choke parsing this so suppress: +// Warning 340: Lambda expressions and closures are not fully supported yet. +%warnfilter(WARN_CPP11_LAMBDA); + +%include + +%inline %{ +#include +auto templated_lambda = [](std::vector t){}; +%} From 8182740b8e6f89c276d19b767853f89b74a3c569 Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Wed, 27 Jul 2022 09:34:16 +1200 Subject: [PATCH 564/662] Add documentation --- CHANGES.current | 3 +++ Doc/Manual/CPlusPlus20.html | 8 ++++++++ 2 files changed, 11 insertions(+) diff --git a/CHANGES.current b/CHANGES.current index 38c0b7011..fbf85ba3e 100644 --- a/CHANGES.current +++ b/CHANGES.current @@ -7,6 +7,9 @@ the issue number to the end of the URL: https://github.com/swig/swig/issues/ Version 4.1.0 (in progress) =========================== +2022-07-27: ZackerySpytz, olly + #1678 Support parsing C++20 templated lambdas. + 2022-07-27: ZackerySpytz, olly #1622 Add support for the C++20 spaceship operator (<=>). diff --git a/Doc/Manual/CPlusPlus20.html b/Doc/Manual/CPlusPlus20.html index 8db84bfd5..0f29a03b8 100644 --- a/Doc/Manual/CPlusPlus20.html +++ b/Doc/Manual/CPlusPlus20.html @@ -50,6 +50,14 @@ or attempts to automatically map it to a three-way comparison operator in any target languages that have one.

    +

    10.2.2 Lambda templates

    + +

    +SWIG should parse lambda templates, but +like + non-templated lambdas they aren't currently wrapped. +

    +

    10.3 Standard library changes

    From 2227dc9e53dfe7aa236523058de139b5b3d5b6cc Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Wed, 27 Jul 2022 10:29:33 +1200 Subject: [PATCH 565/662] Fix handling of array whose size contains << Fixes https://sourceforge.net/p/swig/bugs/983/ --- CHANGES.current | 4 ++++ Examples/test-suite/arrays.i | 4 ++++ Examples/test-suite/php/arrays_runme.php | 2 +- Source/Swig/typesys.c | 4 +++- 4 files changed, 12 insertions(+), 2 deletions(-) diff --git a/CHANGES.current b/CHANGES.current index fbf85ba3e..f754f3362 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-07-27: olly + https://sourceforge.net/p/swig/bugs/983/ + Fix handling of array whose size contains a left shift operator (<<). + 2022-07-27: ZackerySpytz, olly #1678 Support parsing C++20 templated lambdas. diff --git a/Examples/test-suite/arrays.i b/Examples/test-suite/arrays.i index 07162aa90..764fe8679 100644 --- a/Examples/test-suite/arrays.i +++ b/Examples/test-suite/arrays.i @@ -73,4 +73,8 @@ typedef struct { cartPosition_t p; } CartPoseData_t; +/* Test left shift in array size doesn't trigger "Bad template type" error. + * Regression test for https://sourceforge.net/p/swig/bugs/983/ */ +int array_shifted_size[(1<<2)]; + %} diff --git a/Examples/test-suite/php/arrays_runme.php b/Examples/test-suite/php/arrays_runme.php index eb06fbfd8..1d9e44d76 100644 --- a/Examples/test-suite/php/arrays_runme.php +++ b/Examples/test-suite/php/arrays_runme.php @@ -4,7 +4,7 @@ require "tests.php"; check::functions(array('fn_taking_arrays','newintpointer','setintfrompointer','getintfrompointer','array_pointer_func')); check::classes(array('arrays','SimpleStruct','ArrayStruct','CartPoseData_t')); -check::globals(array()); +check::globals(array('array_shifted_size')); $ss=new simplestruct(); check::classname('simplestruct',$ss); diff --git a/Source/Swig/typesys.c b/Source/Swig/typesys.c index 710688a0f..464b89f28 100644 --- a/Source/Swig/typesys.c +++ b/Source/Swig/typesys.c @@ -1702,7 +1702,9 @@ void SwigType_remember_clientdata(const SwigType *t, const_String_or_char_ptr cl if (t) { char *ct = Char(t); - if (strchr(ct, '<') && !(strstr(ct, "<("))) { + const char *lt = strchr(ct, '<'); + /* Allow for `<<` operator in constant expression for array size. */ + if (lt && lt[1] != '(' && lt[1] != '<') { Printf(stdout, "Bad template type passed to SwigType_remember: %s\n", t); assert(0); } From 0ff9a0959ab0fc537c7db53fb94efb7534b45925 Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Wed, 27 Jul 2022 12:25:27 +1200 Subject: [PATCH 566/662] Modify fix for << in array size The previous fix broke testcase arrays for Go. --- Lib/swiglabels.swg | 5 +++++ Source/CParse/parser.y | 6 +++++- Source/Swig/typesys.c | 4 +--- 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/Lib/swiglabels.swg b/Lib/swiglabels.swg index b3855665e..43b2f6edc 100644 --- a/Lib/swiglabels.swg +++ b/Lib/swiglabels.swg @@ -121,3 +121,8 @@ #ifdef __INTEL_COMPILER # pragma warning disable 592 #endif + +/* We replace `<<` with `SWIG_LSHIFT` in constant expressions to avoid + * confusing SWIG's type system into thinking there's a template. + */ +#define SWIG_LSHIFT << diff --git a/Source/CParse/parser.y b/Source/CParse/parser.y index 816264de6..ce0602f3b 100644 --- a/Source/CParse/parser.y +++ b/Source/CParse/parser.y @@ -6803,7 +6803,11 @@ exprcompound : expr PLUS expr { $$.type = promote($1.type,$3.type); } | expr LSHIFT expr { - $$.val = NewStringf("%s << %s",COMPOUND_EXPR_VAL($1),COMPOUND_EXPR_VAL($3)); + /* To avoid confusing SWIG's type system, we replace `<<` with + * `SWIG_LSHIFT` here, then define the latter as a macro in + * the generated wrapper file. + */ + $$.val = NewStringf("%s SWIG_LSHIFT %s",COMPOUND_EXPR_VAL($1),COMPOUND_EXPR_VAL($3)); $$.type = promote_type($1.type); } | expr RSHIFT expr { diff --git a/Source/Swig/typesys.c b/Source/Swig/typesys.c index 464b89f28..710688a0f 100644 --- a/Source/Swig/typesys.c +++ b/Source/Swig/typesys.c @@ -1702,9 +1702,7 @@ void SwigType_remember_clientdata(const SwigType *t, const_String_or_char_ptr cl if (t) { char *ct = Char(t); - const char *lt = strchr(ct, '<'); - /* Allow for `<<` operator in constant expression for array size. */ - if (lt && lt[1] != '(' && lt[1] != '<') { + if (strchr(ct, '<') && !(strstr(ct, "<("))) { Printf(stdout, "Bad template type passed to SwigType_remember: %s\n", t); assert(0); } From 6e931b03992b5c024be34e108d0281670680a6e7 Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Wed, 27 Jul 2022 13:45:03 +1200 Subject: [PATCH 567/662] Revert "Fix handling of array whose size contains <<" This reverts commit 2227dc9e53dfe7aa236523058de139b5b3d5b6cc. --- CHANGES.current | 4 ---- Examples/test-suite/arrays.i | 4 ---- Examples/test-suite/php/arrays_runme.php | 2 +- 3 files changed, 1 insertion(+), 9 deletions(-) diff --git a/CHANGES.current b/CHANGES.current index f754f3362..fbf85ba3e 100644 --- a/CHANGES.current +++ b/CHANGES.current @@ -7,10 +7,6 @@ the issue number to the end of the URL: https://github.com/swig/swig/issues/ Version 4.1.0 (in progress) =========================== -2022-07-27: olly - https://sourceforge.net/p/swig/bugs/983/ - Fix handling of array whose size contains a left shift operator (<<). - 2022-07-27: ZackerySpytz, olly #1678 Support parsing C++20 templated lambdas. diff --git a/Examples/test-suite/arrays.i b/Examples/test-suite/arrays.i index 764fe8679..07162aa90 100644 --- a/Examples/test-suite/arrays.i +++ b/Examples/test-suite/arrays.i @@ -73,8 +73,4 @@ typedef struct { cartPosition_t p; } CartPoseData_t; -/* Test left shift in array size doesn't trigger "Bad template type" error. - * Regression test for https://sourceforge.net/p/swig/bugs/983/ */ -int array_shifted_size[(1<<2)]; - %} diff --git a/Examples/test-suite/php/arrays_runme.php b/Examples/test-suite/php/arrays_runme.php index 1d9e44d76..eb06fbfd8 100644 --- a/Examples/test-suite/php/arrays_runme.php +++ b/Examples/test-suite/php/arrays_runme.php @@ -4,7 +4,7 @@ require "tests.php"; check::functions(array('fn_taking_arrays','newintpointer','setintfrompointer','getintfrompointer','array_pointer_func')); check::classes(array('arrays','SimpleStruct','ArrayStruct','CartPoseData_t')); -check::globals(array('array_shifted_size')); +check::globals(array()); $ss=new simplestruct(); check::classname('simplestruct',$ss); From 54ddefe4103d9adc7b64adf2ab2dab3fe13a400d Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Wed, 27 Jul 2022 13:45:08 +1200 Subject: [PATCH 568/662] Revert "Modify fix for << in array size" This reverts commit 0ff9a0959ab0fc537c7db53fb94efb7534b45925. The modified fix breaks Java and C#, where C constant expressions get used in the generated target language code in some cases. Revert this fix for now. --- Lib/swiglabels.swg | 5 ----- Source/CParse/parser.y | 6 +----- Source/Swig/typesys.c | 4 +++- 3 files changed, 4 insertions(+), 11 deletions(-) diff --git a/Lib/swiglabels.swg b/Lib/swiglabels.swg index 43b2f6edc..b3855665e 100644 --- a/Lib/swiglabels.swg +++ b/Lib/swiglabels.swg @@ -121,8 +121,3 @@ #ifdef __INTEL_COMPILER # pragma warning disable 592 #endif - -/* We replace `<<` with `SWIG_LSHIFT` in constant expressions to avoid - * confusing SWIG's type system into thinking there's a template. - */ -#define SWIG_LSHIFT << diff --git a/Source/CParse/parser.y b/Source/CParse/parser.y index ce0602f3b..816264de6 100644 --- a/Source/CParse/parser.y +++ b/Source/CParse/parser.y @@ -6803,11 +6803,7 @@ exprcompound : expr PLUS expr { $$.type = promote($1.type,$3.type); } | expr LSHIFT expr { - /* To avoid confusing SWIG's type system, we replace `<<` with - * `SWIG_LSHIFT` here, then define the latter as a macro in - * the generated wrapper file. - */ - $$.val = NewStringf("%s SWIG_LSHIFT %s",COMPOUND_EXPR_VAL($1),COMPOUND_EXPR_VAL($3)); + $$.val = NewStringf("%s << %s",COMPOUND_EXPR_VAL($1),COMPOUND_EXPR_VAL($3)); $$.type = promote_type($1.type); } | expr RSHIFT expr { diff --git a/Source/Swig/typesys.c b/Source/Swig/typesys.c index 710688a0f..464b89f28 100644 --- a/Source/Swig/typesys.c +++ b/Source/Swig/typesys.c @@ -1702,7 +1702,9 @@ void SwigType_remember_clientdata(const SwigType *t, const_String_or_char_ptr cl if (t) { char *ct = Char(t); - if (strchr(ct, '<') && !(strstr(ct, "<("))) { + const char *lt = strchr(ct, '<'); + /* Allow for `<<` operator in constant expression for array size. */ + if (lt && lt[1] != '(' && lt[1] != '<') { Printf(stdout, "Bad template type passed to SwigType_remember: %s\n", t); assert(0); } From 100d4d5350663118f7827e7b7156e9982f21d414 Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Wed, 27 Jul 2022 13:32:20 +1200 Subject: [PATCH 569/662] Only recognise spaceship operator for C++ I don't think any valid C program can contain `<=>` in a tokenisable context, but it's more helpful to fail with a syntax error at SWIG parse time and not potentially generate C code trying to use `<=>` in an expression which then fails at compile time. --- Examples/test-suite/errors/c_spaceship.i | 3 +++ Examples/test-suite/errors/c_spaceship.stderr | 1 + Source/Swig/scanner.c | 2 +- 3 files changed, 5 insertions(+), 1 deletion(-) create mode 100644 Examples/test-suite/errors/c_spaceship.i create mode 100644 Examples/test-suite/errors/c_spaceship.stderr diff --git a/Examples/test-suite/errors/c_spaceship.i b/Examples/test-suite/errors/c_spaceship.i new file mode 100644 index 000000000..9be490c54 --- /dev/null +++ b/Examples/test-suite/errors/c_spaceship.i @@ -0,0 +1,3 @@ +%module xxx + +int a[(1<=>2>1)]; diff --git a/Examples/test-suite/errors/c_spaceship.stderr b/Examples/test-suite/errors/c_spaceship.stderr new file mode 100644 index 000000000..bc18d45ed --- /dev/null +++ b/Examples/test-suite/errors/c_spaceship.stderr @@ -0,0 +1 @@ +c_spaceship.i:3: Error: Syntax error in input(1). diff --git a/Source/Swig/scanner.c b/Source/Swig/scanner.c index 4ac3e6c3c..423040185 100644 --- a/Source/Swig/scanner.c +++ b/Source/Swig/scanner.c @@ -896,7 +896,7 @@ static int look(Scanner *s) { else if (c == '=') { if ((c = nextchar(s)) == 0) { return SWIG_TOKEN_LTEQUAL; - } else if (c == '>') { /* Spaceship operator */ + } else if (c == '>' && cparse_cplusplus) { /* Spaceship operator */ return SWIG_TOKEN_LTEQUALGT; } else { retract(s, 1); From 346ede21c39da1e1f15d0366cb747f2dd56307cc Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Wed, 27 Jul 2022 18:17:31 +1200 Subject: [PATCH 570/662] Fix spaceship preproc tests for previous change --- Examples/test-suite/errors/cpp_pp_expressions_bad.i | 6 ++++++ Examples/test-suite/errors/cpp_pp_expressions_bad.stderr | 2 ++ Examples/test-suite/errors/pp_expressions_bad.i | 4 +++- Examples/test-suite/errors/pp_expressions_bad.stderr | 4 ++-- 4 files changed, 13 insertions(+), 3 deletions(-) create mode 100644 Examples/test-suite/errors/cpp_pp_expressions_bad.i create mode 100644 Examples/test-suite/errors/cpp_pp_expressions_bad.stderr diff --git a/Examples/test-suite/errors/cpp_pp_expressions_bad.i b/Examples/test-suite/errors/cpp_pp_expressions_bad.i new file mode 100644 index 000000000..c95b9bfc4 --- /dev/null +++ b/Examples/test-suite/errors/cpp_pp_expressions_bad.i @@ -0,0 +1,6 @@ +%module xxx +/* Note: needs -Wextra to see these warnings */ + +/* Spaceship operator doesn't seem to be allowed in preprocessor expressions. */ +#if (4 <=> 2) < 0 +#endif diff --git a/Examples/test-suite/errors/cpp_pp_expressions_bad.stderr b/Examples/test-suite/errors/cpp_pp_expressions_bad.stderr new file mode 100644 index 000000000..d95d416f5 --- /dev/null +++ b/Examples/test-suite/errors/cpp_pp_expressions_bad.stderr @@ -0,0 +1,2 @@ +cpp_pp_expressions_bad.i:5: Warning 202: Could not evaluate expression '(4 <=> 2) < 0' +cpp_pp_expressions_bad.i:5: Warning 202: Spaceship operator (<=>) not allowed in preprocessor expression diff --git a/Examples/test-suite/errors/pp_expressions_bad.i b/Examples/test-suite/errors/pp_expressions_bad.i index 3fa49ba4a..0e67c78f8 100644 --- a/Examples/test-suite/errors/pp_expressions_bad.i +++ b/Examples/test-suite/errors/pp_expressions_bad.i @@ -67,6 +67,8 @@ #if "1" == +"1" #endif -/* Spaceship operator doesn't seem to be allowed in preprocessor expressions. */ +/* Spaceship operator doesn't seem to be allowed in preprocessor expressions, + * and isn't valid in C at all. + */ #if (4 <=> 2) < 0 #endif diff --git a/Examples/test-suite/errors/pp_expressions_bad.stderr b/Examples/test-suite/errors/pp_expressions_bad.stderr index 12eb42e04..e8d187cb5 100644 --- a/Examples/test-suite/errors/pp_expressions_bad.stderr +++ b/Examples/test-suite/errors/pp_expressions_bad.stderr @@ -31,5 +31,5 @@ pp_expressions_bad.i:64: Warning 202: Could not evaluate expression '"1" == ~"1" pp_expressions_bad.i:64: Warning 202: Syntax error: attempt to apply unary operator to string pp_expressions_bad.i:67: Warning 202: Could not evaluate expression '"1" == +"1"' pp_expressions_bad.i:67: Warning 202: Syntax error: attempt to apply unary operator to string -pp_expressions_bad.i:71: Warning 202: Could not evaluate expression '(4 <=> 2) < 0' -pp_expressions_bad.i:71: Warning 202: Spaceship operator (<=>) not allowed in preprocessor expression +pp_expressions_bad.i:73: Warning 202: Could not evaluate expression '(4 <=> 2) < 0' +pp_expressions_bad.i:73: Warning 202: Syntax error From 848cb3f95ec6f5f77f8ee28773d197d7035a8454 Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Thu, 28 Jul 2022 07:06:00 +1200 Subject: [PATCH 571/662] Document lack of separate ISO C tag namespace This is a long-standing limitation, but only seems to have been reported once back in 2004. Nobody's cared enough to address it in 18 years, but we can at least document it in the manual rather than only in a source code comment in Source/Swig/symbol.c. Addresses https://sourceforge.net/p/swig/bugs/429/ --- Doc/Manual/SWIG.html | 42 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 40 insertions(+), 2 deletions(-) diff --git a/Doc/Manual/SWIG.html b/Doc/Manual/SWIG.html index 8d8f7bd45..b7021c468 100644 --- a/Doc/Manual/SWIG.html +++ b/Doc/Manual/SWIG.html @@ -2528,6 +2528,45 @@ This section describes the behavior of SWIG when processing ISO C structures and handle C++ are described in the next section.

    +

    +ISO C has a separate tag name space in which the names of structures, +unions and enumerated types are put, which is separate from the +name space for ordinary identifiers (function names, object names, +typedef names, enumeration constants). For example, this is valid +ISO C because Foo the struct tag and Foo the function +name are in different name spaces: +

    + +
    +struct Foo {
    +  int bar;
    +};
    +
    +int Foo(void) { return 42; }
    +
    + +

    +SWIG doesn't currently implement this separate tag name space and +for the above example you'll get: +

    + +
    +foo.i:5: Warning 302: Identifier 'Foo' redefined (ignored),
    +foo.i:1: Warning 302: previous definition of 'Foo'.
    +
    + +

    +In practice this rarely actually causes problems, particular because +SWIG has special handling for typedef so cases such as this +work: +

    + +
    +typedef struct Foo {
    +  int bar;
    +} Foo;
    +
    +

    If SWIG encounters the definition of a structure or union, it creates a set of accessor functions. Although SWIG does not need @@ -2539,8 +2578,7 @@ to an individual member. For example, the declaration :

     struct Vector {
       double x, y, z;
    -}
    -
    +};
     

    From 8cc3d04a354450d51f5f50b98789d912befb557a Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Thu, 28 Jul 2022 10:23:54 +1200 Subject: [PATCH 572/662] [perl] Note in -help that -proxy is on by default --- Source/Modules/perl5.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Modules/perl5.cxx b/Source/Modules/perl5.cxx index 1f6476b6b..db47d1804 100644 --- a/Source/Modules/perl5.cxx +++ b/Source/Modules/perl5.cxx @@ -21,7 +21,7 @@ Perl 5 Options (available with -perl5)\n\ -const - Wrap constants as constants and not variables (implies -proxy)\n\ -nopm - Do not generate the .pm file\n\ -noproxy - Don't create proxy classes\n\ - -proxy - Create proxy classes\n\ + -proxy - Create proxy classes (enabled by default)\n\ -static - Omit code related to dynamic loading\n\ \n"; From 64d72483c606c3c463e857de39473b4f5f725438 Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Thu, 28 Jul 2022 14:30:43 +1200 Subject: [PATCH 573/662] Clean up Tcl version docs and handling We require 8.4 now which simplifies things a bit. --- Doc/Manual/Tcl.html | 25 +++++++++++++++---------- Examples/Makefile.in | 2 +- Lib/tcl/Makefile.in | 2 +- Lib/tcl/tclinit.swg | 5 ++--- 4 files changed, 19 insertions(+), 15 deletions(-) diff --git a/Doc/Manual/Tcl.html b/Doc/Manual/Tcl.html index c271a2ee6..ab3346c70 100644 --- a/Doc/Manual/Tcl.html +++ b/Doc/Manual/Tcl.html @@ -3137,9 +3137,8 @@ For example:

    -Tcl 7.4 introduced the idea of an extension package. By default, SWIG -generates all of the code necessary to create a package. To set the package version, -simply use the -pkgversion option. For example: +SWIG generates all of the code necessary to create a Tcl extension package. +To set the package version use the -pkgversion option. For example:

    @@ -3150,7 +3149,7 @@ simply use the -pkgversion option. For example:

    After building the SWIG generated module, you need to execute -the "pkg_mkIndex" command inside tclsh. For example : +the pkg_mkIndex command inside tclsh. For example :

    @@ -3430,7 +3429,7 @@ interesting things.
     
     

    For background information about the Tcl Stubs feature, see -http://www.tcl.tk/doc/howto/stubs.html. +https://www.tcl.tk/doc/howto/stubs.html.

    @@ -3440,11 +3439,17 @@ feature if compiled with -DUSE_TCL_STUBS.

    As of SWIG 1.3.40, the generated C/C++ wrapper will use the Tk Stubs -feature if compiled with -DUSE_TK_STUBS. Also, you can override -the minimum version to support which is passed to Tcl_InitStubs() -and Tk_InitStubs() with -DSWIG_TCL_STUBS_VERSION="8.3" -or the version being compiled with using --DSWIG_TCL_STUBS_VERSION=TCL_VERSION. +feature if compiled with -DUSE_TK_STUBS. +

    + +

    +By default SWIG sets the minimum Tcl version to support to the 8.4 +as that's the minimum Tcl version we aim to support (since SWIG 4.1.0; before +this SWIG set it to 8.1, which was the first Tcl version with the stubs +mechanism). This minimum version is passed to Tcl_InitStubs() and +Tk_InitStubs(). You can override with a specific version using +-DSWIG_TCL_STUBS_VERSION="8.5" or set it to the Tcl version being +compiled with using -DSWIG_TCL_STUBS_VERSION=TCL_VERSION.

    diff --git a/Examples/Makefile.in b/Examples/Makefile.in index 532152e80..03b33430c 100644 --- a/Examples/Makefile.in +++ b/Examples/Makefile.in @@ -191,7 +191,7 @@ tcl: $(SRCDIR_SRCS) $(TCLLDSHARED) $(CFLAGS) $(LDFLAGS) $(OBJS) $(IOBJS) $(TCL_DLNK) $(LIBS) -o $(LIBPREFIX)$(TARGET)$(TCL_SO) $(TCL_LINK) # ----------------------------------------------------------- -# Build a Tcl7.5 dynamic loadable module for C++ +# Build a Tcl dynamic loadable module for C++ # ----------------------------------------------------------- tcl_cpp: $(SRCDIR_SRCS) diff --git a/Lib/tcl/Makefile.in b/Lib/tcl/Makefile.in index 13d7d4653..019091c98 100644 --- a/Lib/tcl/Makefile.in +++ b/Lib/tcl/Makefile.in @@ -45,7 +45,7 @@ LIBS = # SWIGCC = Compiler used to compile the wrapper file SWIG = $(exec_prefix)/bin/swig -SWIGOPT = -tcl # use -tcl8 for Tcl 8.0 +SWIGOPT = -tcl SWIGCC = $(CC) # SWIG Library files. Uncomment if rebuilding tclsh diff --git a/Lib/tcl/tclinit.swg b/Lib/tcl/tclinit.swg index 3140bdcdb..cf14de881 100644 --- a/Lib/tcl/tclinit.swg +++ b/Lib/tcl/tclinit.swg @@ -24,7 +24,7 @@ SWIGEXPORT int SWIG_init(Tcl_Interp *); /* Compatibility version for TCL stubs */ #ifndef SWIG_TCL_STUBS_VERSION -#define SWIG_TCL_STUBS_VERSION "8.1" +#define SWIG_TCL_STUBS_VERSION "8.4" #endif %} @@ -100,8 +100,7 @@ SWIGEXPORT int SWIG_init(Tcl_Interp *interp) { size_t i; if (interp == 0) return TCL_ERROR; #ifdef USE_TCL_STUBS - /* (char*) cast is required to avoid compiler warning/error for Tcl < 8.4. */ - if (Tcl_InitStubs(interp, (char*)SWIG_TCL_STUBS_VERSION, 0) == NULL) { + if (Tcl_InitStubs(interp, SWIG_TCL_STUBS_VERSION, 0) == NULL) { return TCL_ERROR; } #endif From 379d5b67424d9077d2642e03a4e2250c58d45309 Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Fri, 29 Jul 2022 16:28:10 +1200 Subject: [PATCH 574/662] Fix warning suppression in cpp20_lambda_template --- Examples/test-suite/cpp20_lambda_template.i | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Examples/test-suite/cpp20_lambda_template.i b/Examples/test-suite/cpp20_lambda_template.i index 948364f42..5672bd1b7 100644 --- a/Examples/test-suite/cpp20_lambda_template.i +++ b/Examples/test-suite/cpp20_lambda_template.i @@ -2,7 +2,7 @@ // We just want to test that SWIG doesn't choke parsing this so suppress: // Warning 340: Lambda expressions and closures are not fully supported yet. -%warnfilter(WARN_CPP11_LAMBDA); +%warnfilter(SWIGWARN_CPP11_LAMBDA); %include From dce42543774e050d969f95fb1161c3d71386abe7 Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Sat, 23 Jul 2022 14:51:10 +1200 Subject: [PATCH 575/662] [php] Fix handling of friend functions We were incorrectly considering them as methods of the class they are a friend of for the purposes of calculate PHP type declarations. --- Source/Modules/php.cxx | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/Source/Modules/php.cxx b/Source/Modules/php.cxx index 72f9baa1b..964456c08 100644 --- a/Source/Modules/php.cxx +++ b/Source/Modules/php.cxx @@ -1253,7 +1253,13 @@ public: // of a group so reset the phptype information. phptypes = NULL; - String *key = NewStringf("%s:%s", class_name, wname); + String *key; + if (class_name && !Equal(Getattr(n, "storage"), "friend")) { + key = NewStringf("%s:%s", class_name, wname); + } else { + key = NewStringf(":%s", wname); + } + PHPTypes *p = (PHPTypes*)GetVoid(all_phptypes, key); if (p) { // We already have an entry - this happens when overloads are created @@ -1428,11 +1434,13 @@ public: Wrapper_add_local(f, "upcall", "bool upcall = false"); Printf(f->code, "upcall = (director && (director->swig_get_self()==Z_OBJ_P(ZEND_THIS)));\n"); - String *parent = class_name; - while ((parent = Getattr(php_parent_class, parent)) != NULL) { - // Mark this method name as having a directed descendent for all - // classes we're derived from. - SetFlag(has_directed_descendent, NewStringf("%s:%s", parent, wname)); + if (class_name && !Equal(Getattr(n, "storage"), "friend")) { + String *parent = class_name; + while ((parent = Getattr(php_parent_class, parent)) != NULL) { + // Mark this method name as having a directed descendent for all + // classes we're derived from. + SetFlag(has_directed_descendent, NewStringf("%s:%s", parent, wname)); + } } } From 26fbf9990122ac7cdb1cdb2c7873144779d989c6 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Sat, 30 Jul 2022 16:05:35 +0100 Subject: [PATCH 576/662] Add Tcl support for std::unique_ptr and std::auto_ptr Equivalent to Ruby/Python implementations. --- CHANGES.current | 4 + Examples/test-suite/cpp11_std_unique_ptr.i | 2 +- Examples/test-suite/li_std_auto_ptr.i | 2 +- .../tcl/cpp11_std_unique_ptr_runme.tcl | 140 ++++++++++++++++++ .../test-suite/tcl/li_std_auto_ptr_runme.tcl | 111 ++++++++++++++ Lib/tcl/std_auto_ptr.i | 33 +++++ Lib/tcl/std_unique_ptr.i | 33 +++++ Lib/tcl/tclrun.swg | 51 +++++-- 8 files changed, 364 insertions(+), 12 deletions(-) create mode 100644 Examples/test-suite/tcl/cpp11_std_unique_ptr_runme.tcl create mode 100644 Examples/test-suite/tcl/li_std_auto_ptr_runme.tcl create mode 100644 Lib/tcl/std_auto_ptr.i create mode 100644 Lib/tcl/std_unique_ptr.i diff --git a/CHANGES.current b/CHANGES.current index fbf85ba3e..1ec7a6435 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-07-30: wsfulton + [Tcl] Add support for std::unique_ptr in std_unique_ptr.i. + Add support for std::auto_ptr in std_auto_ptr.i. + 2022-07-27: ZackerySpytz, olly #1678 Support parsing C++20 templated lambdas. diff --git a/Examples/test-suite/cpp11_std_unique_ptr.i b/Examples/test-suite/cpp11_std_unique_ptr.i index ec7505974..2dcdbca45 100644 --- a/Examples/test-suite/cpp11_std_unique_ptr.i +++ b/Examples/test-suite/cpp11_std_unique_ptr.i @@ -1,6 +1,6 @@ %module cpp11_std_unique_ptr -#if defined(SWIGCSHARP) || defined(SWIGJAVA) || defined(SWIGPYTHON) || defined(SWIGRUBY) || defined(SWIGPERL) +#if defined(SWIGCSHARP) || defined(SWIGJAVA) || defined(SWIGPYTHON) || defined(SWIGRUBY) || defined(SWIGPERL) || defined(SWIGTCL) %include "std_string.i" %include "std_unique_ptr.i" diff --git a/Examples/test-suite/li_std_auto_ptr.i b/Examples/test-suite/li_std_auto_ptr.i index 02c8235f2..68dbf0ffa 100644 --- a/Examples/test-suite/li_std_auto_ptr.i +++ b/Examples/test-suite/li_std_auto_ptr.i @@ -12,7 +12,7 @@ #endif %} -#if defined(SWIGCSHARP) || defined(SWIGJAVA) || defined(SWIGPYTHON) || defined(SWIGRUBY) || defined(SWIGPERL) +#if defined(SWIGCSHARP) || defined(SWIGJAVA) || defined(SWIGPYTHON) || defined(SWIGRUBY) || defined(SWIGPERL) || defined(SWIGTCL) %include "std_string.i" %include "std_auto_ptr.i" diff --git a/Examples/test-suite/tcl/cpp11_std_unique_ptr_runme.tcl b/Examples/test-suite/tcl/cpp11_std_unique_ptr_runme.tcl new file mode 100644 index 000000000..d5864b874 --- /dev/null +++ b/Examples/test-suite/tcl/cpp11_std_unique_ptr_runme.tcl @@ -0,0 +1,140 @@ + +if [ catch { load ./cpp11_std_unique_ptr[info sharedlibextension] cpp11_std_unique_ptr} err_msg ] { + puts stderr "Could not load shared object:\n$err_msg" +} + + +proc checkCount {expected_count} { + set actual_count [Klass_getTotal_count] + if {$actual_count != $expected_count} { + error "Counts incorrect, expected: $expected_count actual: $actual_count" + } +} + +################################# Tcl pointer recycling bug start +# +# ### Possibly related to premature object deletion problem mentioned in newobject1_runme.tcl. ### +# +# While this won't be repeatable on all machines, the following caused the underlying C++ +# pointer value for k1 to be reused for k4. +# +# If the C/C++ memory allocator uses the same pointer value again, then a command name that +# contains a pointer encoding, such as, _b09b1148bd550000_p_Klass (not a variable name) will be +# re-used in SWIG_Tcl_NewInstanceObj. The command should have disappeared from the Tcl side when +# the object was deleted, but there is some sort of bug preventing this from happening in this +# scenario as follows: +# +# Below creates a struct via the call to Tcl_CreateObjCommand in +# SWIG_Tcl_NewInstanceObj (creates a command name with a pointer encoding such as +# _50fb3608ce550000_p_Klass) which also makes a second call to Tcl_CreateObjCommand in +# SWIG_Tcl_ObjectConstructor (creates a command name with the name k1). +Klass k1 "one" +# Line below calls Tcl_DeleteCommandFromToken but is only called for the command created in the +# second call (k1) and not the first call to Tcl_CreateObjCommand. +k1 -delete +set k2 [makeKlassUniquePtr "two"] +set k3 [makeKlassUniquePtr "three"] +$k2 -delete +# If the memory allocator uses the same pointer value, then SWIG_Tcl_NewInstanceObj will find +# the undeleted command _50fb3608ce550000_p_Klass and re-use it. This command should surely +# have been deleted !?? +set k4 [makeKlassUniquePtr "four"] +$k3 -delete +$k4 -delete +checkCount 0 +################################# Tcl pointer recycling bug end + + +# unique_ptr as input +Klass kin "KlassInput" +checkCount 1 +set s [takeKlassUniquePtr kin] +checkCount 0 +if {[kin cget -thisown]} { + error "thisown should be false" +} +if {$s != "KlassInput"} { + error "Incorrect string: $s" +} +if {![is_nullptr kin]} { + error "is_nullptr failed" +} +kin -delete # Should not fail, even though already deleted +checkCount 0 + +Klass kin "KlassInput" +checkCount 1 +set s [takeKlassUniquePtr kin] +checkCount 0 +if {[kin cget -thisown]} { + error "thisown should be false" +} +if {$s != "KlassInput"} { + error "Incorrect string: $s" +} +if {![is_nullptr kin]} { + error "is_nullptr failed" +} +set exception_thrown 0 +if [ catch { set s [takeKlassUniquePtr kin] } 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 "double usage of takeKlassUniquePtr should have been an error" +} +kin -delete # Should not fail, even though already deleted +checkCount 0 + +Klass kin "KlassInput" +set exception_thrown 0 +if [ catch { + set notowned [get_not_owned_ptr kin] + takeKlassUniquePtr notowned +} ] { + set exception_thrown 1 +} +if {!$exception_thrown} { + error "Should have thrown 'Cannot release ownership as memory is not owned' error" +} +kin -delete +checkCount 0 + +KlassInheritance kini "KlassInheritanceInput" +checkCount 1 +set s [takeKlassUniquePtr kini] +checkCount 0 +if {[kini cget -thisown]} { + error "thisown should be false" +} +if {$s != "KlassInheritanceInput"} { + error "Incorrect string: $s" +} +if {![is_nullptr kini]} { + error "is_nullptr failed" +} +kini -delete # Should not fail, even though already deleted +checkCount 0 + +# unique_ptr as output +set k1 [makeKlassUniquePtr "first"] +set k2 [makeKlassUniquePtr "second"] +if {[Klass_getTotal_count] != 2} { + error "number of objects should be 2" +} + +$k1 -delete +if {[Klass_getTotal_count] != 1} { + error "number of objects should be 1" +} + +if {[$k2 getLabel] != "second"} { + error "wrong object label" +} + +$k2 -delete +if {[Klass_getTotal_count] != 0} { + error "no objects should be left" +} diff --git a/Examples/test-suite/tcl/li_std_auto_ptr_runme.tcl b/Examples/test-suite/tcl/li_std_auto_ptr_runme.tcl new file mode 100644 index 000000000..f9ab30ad4 --- /dev/null +++ b/Examples/test-suite/tcl/li_std_auto_ptr_runme.tcl @@ -0,0 +1,111 @@ + +if [ catch { load ./li_std_auto_ptr[info sharedlibextension] li_std_auto_ptr} err_msg ] { + puts stderr "Could not load shared object:\n$err_msg" +} + + +proc checkCount {expected_count} { + set actual_count [Klass_getTotal_count] + if {$actual_count != $expected_count} { + error "Counts incorrect, expected: $expected_count actual: $actual_count" + } +} + +################################# Tcl pointer recycling bug start +# Not copied from cpp11_std_unique_ptr_runme.tcl +################################# Tcl pointer recycling bug end + + +# auto_ptr as input +Klass kin "KlassInput" +checkCount 1 +set s [takeKlassAutoPtr kin] +checkCount 0 +if {[kin cget -thisown]} { + error "thisown should be false" +} +if {$s != "KlassInput"} { + error "Incorrect string: $s" +} +if {![is_nullptr kin]} { + error "is_nullptr failed" +} +kin -delete # Should not fail, even though already deleted +checkCount 0 + +Klass kin "KlassInput" +checkCount 1 +set s [takeKlassAutoPtr kin] +checkCount 0 +if {[kin cget -thisown]} { + error "thisown should be false" +} +if {$s != "KlassInput"} { + error "Incorrect string: $s" +} +if {![is_nullptr kin]} { + error "is_nullptr failed" +} +set exception_thrown 0 +if [ catch { set s [takeKlassAutoPtr kin] } 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 "double usage of takeKlassAutoPtr should have been an error" +} +kin -delete # Should not fail, even though already deleted +checkCount 0 + +Klass kin "KlassInput" +set exception_thrown 0 +if [ catch { + set notowned [get_not_owned_ptr kin] + takeKlassAutoPtr notowned +} ] { + set exception_thrown 1 +} +if {!$exception_thrown} { + error "Should have thrown 'Cannot release ownership as memory is not owned' error" +} +kin -delete +checkCount 0 + +KlassInheritance kini "KlassInheritanceInput" +checkCount 1 +set s [takeKlassAutoPtr kini] +checkCount 0 +if {[kini cget -thisown]} { + error "thisown should be false" +} +if {$s != "KlassInheritanceInput"} { + error "Incorrect string: $s" +} +if {![is_nullptr kini]} { + error "is_nullptr failed" +} +kini -delete # Should not fail, even though already deleted +checkCount 0 + +# auto_ptr as output +set k1 [makeKlassAutoPtr "first"] +set k2 [makeKlassAutoPtr "second"] +if {[Klass_getTotal_count] != 2} { + error "number of objects should be 2" +} + +$k1 -delete +if {[Klass_getTotal_count] != 1} { + error "number of objects should be 1" +} + +if {[$k2 getLabel] != "second"} { + error "wrong object label" +} + +$k2 -delete +if {[Klass_getTotal_count] != 0} { + error "no objects should be left" +} diff --git a/Lib/tcl/std_auto_ptr.i b/Lib/tcl/std_auto_ptr.i new file mode 100644 index 000000000..3030a1bdf --- /dev/null +++ b/Lib/tcl/std_auto_ptr.i @@ -0,0 +1,33 @@ +/* ----------------------------------------------------------------------------- + * std_auto_ptr.i + * + * SWIG library file for handling std::auto_ptr. + * Memory ownership is passed from the std::auto_ptr C++ layer to the proxy + * class when returning a std::auto_ptr from a function. + * Memory ownership is passed from the proxy class to the std::auto_ptr in the + * C++ layer when passed as a parameter to a wrapped function. + * ----------------------------------------------------------------------------- */ + +%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 | %convertptr_flags); + if (!SWIG_IsOK(res)) { + if (res == SWIG_ERROR_RELEASE_NOT_OWNED) { + %releasenotowned_fail(res, "TYPE *", $symname, $argnum); + } else { + %argument_fail(res, "TYPE *", $symname, $argnum); + } + } + $1.reset((TYPE *)argp); +} + +%typemap (out) std::auto_ptr< TYPE > %{ + Tcl_SetObjResult(interp, SWIG_NewInstanceObj($1.release(), $descriptor(TYPE *), SWIG_POINTER_OWN)); +%} + +%template() std::auto_ptr< TYPE >; +%enddef + +namespace std { + template class auto_ptr {}; +} diff --git a/Lib/tcl/std_unique_ptr.i b/Lib/tcl/std_unique_ptr.i new file mode 100644 index 000000000..704055676 --- /dev/null +++ b/Lib/tcl/std_unique_ptr.i @@ -0,0 +1,33 @@ +/* ----------------------------------------------------------------------------- + * std_unique_ptr.i + * + * SWIG library file for handling std::unique_ptr. + * Memory ownership is passed from the std::unique_ptr C++ layer to the proxy + * class when returning a std::unique_ptr from a function. + * Memory ownership is passed from the proxy class to the std::unique_ptr in the + * C++ layer when passed as a parameter to a wrapped function. + * ----------------------------------------------------------------------------- */ + +%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 | %convertptr_flags); + if (!SWIG_IsOK(res)) { + if (res == SWIG_ERROR_RELEASE_NOT_OWNED) { + %releasenotowned_fail(res, "TYPE *", $symname, $argnum); + } else { + %argument_fail(res, "TYPE *", $symname, $argnum); + } + } + $1.reset((TYPE *)argp); +} + +%typemap (out) std::unique_ptr< TYPE > %{ + Tcl_SetObjResult(interp, SWIG_NewInstanceObj($1.release(), $descriptor(TYPE *), SWIG_POINTER_OWN)); +%} + +%template() std::unique_ptr< TYPE >; +%enddef + +namespace std { + template class unique_ptr {}; +} diff --git a/Lib/tcl/tclrun.swg b/Lib/tcl/tclrun.swg index 938ec9854..e8136051f 100644 --- a/Lib/tcl/tclrun.swg +++ b/Lib/tcl/tclrun.swg @@ -122,6 +122,7 @@ SWIG_Tcl_Disown(void *ptr) { SWIGRUNTIME int SWIG_Tcl_ConvertPtrFromString(Tcl_Interp *interp, const char *c, void **ptr, swig_type_info *ty, int flags) { swig_cast_info *tc; + const char *cmd_name; /* Pointer values must start with leading underscore */ while (*c != '_') { *ptr = (void *) 0; @@ -157,23 +158,42 @@ SWIG_Tcl_ConvertPtrFromString(Tcl_Interp *interp, const char *c, void **ptr, swi c = Tcl_GetStringFromObj(Tcl_GetObjResult(interp), NULL); } + cmd_name = c; c++; c = SWIG_UnpackData(c,ptr,sizeof(void *)); + if (ty) { tc = c ? SWIG_TypeCheck(c,ty) : 0; - if (!tc) { + if (tc) { + Tcl_CmdInfo info; + if (Tcl_GetCommandInfo(interp, cmd_name, &info)) { + swig_instance *inst = (swig_instance *)info.objClientData; + if (!inst->thisvalue) { + *ptr = 0; + } + assert(inst->thisvalue == *ptr); + if (((flags & SWIG_POINTER_RELEASE) == SWIG_POINTER_RELEASE) && !SWIG_Thisown(inst->thisvalue)) { + return SWIG_ERROR_RELEASE_NOT_OWNED; + } else { + if (flags & SWIG_POINTER_DISOWN) { + SWIG_Disown((void *) *ptr); + } + if (flags & SWIG_POINTER_CLEAR) { + inst->thisvalue = 0; + } + { + int newmemory = 0; + *ptr = SWIG_TypeCast(tc,(void *) *ptr,&newmemory); + assert(!newmemory); /* newmemory handling not yet implemented */ + } + } + } + } else { return SWIG_ERROR; } - if (flags & SWIG_POINTER_DISOWN) { - SWIG_Disown((void *) *ptr); - } - { - int newmemory = 0; - *ptr = SWIG_TypeCast(tc,(void *) *ptr,&newmemory); - assert(!newmemory); /* newmemory handling not yet implemented */ - } } + return SWIG_OK; } @@ -490,9 +510,11 @@ SWIG_Tcl_NewInstanceObj(Tcl_Interp *interp, void *thisvalue, swig_type_info *typ /* Check to see if this pointer belongs to a class or not */ if (thisvalue && (type->clientdata) && (interp)) { Tcl_CmdInfo ci; + int has_command; char *name; name = Tcl_GetStringFromObj(robj,NULL); - if (!Tcl_GetCommandInfo(interp,name, &ci) || (flags)) { + has_command = Tcl_GetCommandInfo(interp, name, &ci); + if (!has_command || flags) { swig_instance *newinst = (swig_instance *) malloc(sizeof(swig_instance)); newinst->thisptr = Tcl_DuplicateObj(robj); Tcl_IncrRefCount(newinst->thisptr); @@ -503,6 +525,15 @@ SWIG_Tcl_NewInstanceObj(Tcl_Interp *interp, void *thisvalue, swig_type_info *typ if (flags) { SWIG_Acquire(thisvalue); } + } else { + swig_instance *inst = (swig_instance *)ci.objClientData; + /* Restore thisvalue as SWIG_POINTER_CLEAR may have been used to set it to zero. + Occurs when the C pointer is re-used by the memory allocator and the command has + been created and not destroyed - bug?? - see cpp11_std_unique_ptr_runme.tcl test. */ + if (inst->thisvalue != thisvalue) { + assert(inst->thisvalue == 0); + inst->thisvalue = thisvalue; + } } } return robj; From d93a8c2db86cbb323fb3106f03079f2c4e330984 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Sat, 30 Jul 2022 17:41:13 +0100 Subject: [PATCH 577/662] Minor editing of C++20 docs --- Doc/Manual/CPlusPlus20.html | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Doc/Manual/CPlusPlus20.html b/Doc/Manual/CPlusPlus20.html index 0f29a03b8..e92ca3a76 100644 --- a/Doc/Manual/CPlusPlus20.html +++ b/Doc/Manual/CPlusPlus20.html @@ -38,24 +38,24 @@ Work has only just begun on adding C++20 support.

    SWIG supports the spaceship operator <=> in constant -expressions. To simplifying handling the return value is currently +expressions. To simplify handling of the return value type, it is currently treated as an integer rather than std::strong_ordering, etc. In practice we think that should do the right thing in most cases.

    SWIG also recognises operator<=> which can be wrapped -if renamed. There's not currently any default renaming for the operator -or attempts to automatically map it to a three-way comparison operator -in any target languages that have one. +if renamed. There is not currently any default renaming for the operator +or any attempt to automatically map it to a three-way comparison operator +in any of the target languages.

    10.2.2 Lambda templates

    -SWIG should parse lambda templates, but -like - non-templated lambdas they aren't currently wrapped. +SWIG should parse lambda templates, but like + +non-templated lambdas they aren't currently wrapped.

    10.3 Standard library changes

    From 3bc754da10c5cac64f237ed890ade983c3c34f3d Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Sat, 30 Jul 2022 17:42:26 +0100 Subject: [PATCH 578/662] html corrections --- Doc/Manual/CPlusPlus20.html | 7 +++++++ Doc/Manual/Contents.html | 4 ++++ Doc/Manual/Library.html | 2 +- 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/Doc/Manual/CPlusPlus20.html b/Doc/Manual/CPlusPlus20.html index e92ca3a76..a289d776f 100644 --- a/Doc/Manual/CPlusPlus20.html +++ b/Doc/Manual/CPlusPlus20.html @@ -13,6 +13,10 @@
    @@ -34,8 +38,10 @@ Work has only just begun on adding C++20 support.

    10.2 Core language changes

    +

    10.2.1 Spaceship operator

    +

    SWIG supports the spaceship operator <=> in constant expressions. To simplify handling of the return value type, it is currently @@ -52,6 +58,7 @@ in any of the target languages.

    10.2.2 Lambda templates

    +

    SWIG should parse lambda templates, but like diff --git a/Doc/Manual/Contents.html b/Doc/Manual/Contents.html index 39d83bd14..3d8494184 100644 --- a/Doc/Manual/Contents.html +++ b/Doc/Manual/Contents.html @@ -386,6 +386,10 @@

    diff --git a/Doc/Manual/Library.html b/Doc/Manual/Library.html index 7dc649c16..f308c31f1 100644 --- a/Doc/Manual/Library.html +++ b/Doc/Manual/Library.html @@ -2127,7 +2127,7 @@ Consider expanding the example above with a function that takes a std::uniqu
    -void take(std::unique_ptr);
    +void take(std::unique_ptr<Klass>);
     
    From c1bfda210f9bb8989f211f306c24d4021b32f3ad Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Sun, 31 Jul 2022 00:42:08 +0100 Subject: [PATCH 579/662] Fix configure messages when C++20 is not available --- configure.ac | 2 ++ 1 file changed, 2 insertions(+) diff --git a/configure.ac b/configure.ac index 4a7c76c79..fd2438dec 100644 --- a/configure.ac +++ b/configure.ac @@ -315,6 +315,8 @@ if test x"$enable_cpp11_testing" = xyes; then HAVE_CXX14="1" HAVE_CXX11="1" else + AC_MSG_RESULT([no]) + # Test for c++17 CXXCPP=" " AX_CXX_COMPILE_STDCXX(17, [noext], [optional]) From 4a8447d503a01755ec2833601ce64e49923fe4dd Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Sat, 30 Jul 2022 18:58:03 +0100 Subject: [PATCH 580/662] Add c++-20 testing on experimental GHA Ubuntu 22.04 --- .github/workflows/ci.yml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 69871b7d5..6932556e4 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -41,6 +41,9 @@ jobs: GCC: 10 - SWIGLANG: "" GCC: 11 + - SWIGLANG: "" + GCC: 12 + os: ubuntu-22.04 - SWIGLANG: "" compiler: clang - SWIGLANG: csharp @@ -286,6 +289,12 @@ jobs: - SWIGLANG: tcl CPPSTD: c++17 GCC: 11 + # c++20 testing (using gcc12) + # ubuntu-22.04 is currently experimental on Github Actions, so limit to just one language for now + - SWIGLANG: python + CPPSTD: c++20 + GCC: 12 + os: ubuntu-22.04 # Experimental languages (these are allowed to fail) - SWIGLANG: mzscheme continue-on-error: true From eb8346b958d8ce7239c06577179f4899e42210fd Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Sat, 30 Jul 2022 18:58:43 +0100 Subject: [PATCH 581/662] Convert cpp20_spaceship_operator php test to python --- .../python/cpp20_spaceship_operator_runme.py | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 Examples/test-suite/python/cpp20_spaceship_operator_runme.py diff --git a/Examples/test-suite/python/cpp20_spaceship_operator_runme.py b/Examples/test-suite/python/cpp20_spaceship_operator_runme.py new file mode 100644 index 000000000..7adce6db2 --- /dev/null +++ b/Examples/test-suite/python/cpp20_spaceship_operator_runme.py @@ -0,0 +1,19 @@ +from cpp20_spaceship_operator import * + +def check_equal(a, b): + if a != b: + raise RuntimeError("{} is not equal to {}".format(a, b)) + +# check_equal(ALIEN, true) +check_equal(SPACE, 1) +check_equal(COMET, 1) +check_equal(cvar.v, 42) + +x = A(1) +y = A(2) + +check_equal(spaceship(x, y) < 0, True) +check_equal(spaceship(x, x), 0) +check_equal(spaceship(y, x) > 0, True) + +check_equal(f(), 42) From db854dcef4c0761593bbac9ab10b16a1199ef0f6 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Sat, 30 Jul 2022 19:45:53 +0100 Subject: [PATCH 582/662] GHA: Python is already installed --- Tools/CI-linux-install.sh | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Tools/CI-linux-install.sh b/Tools/CI-linux-install.sh index b88df193c..525121e8c 100644 --- a/Tools/CI-linux-install.sh +++ b/Tools/CI-linux-install.sh @@ -12,8 +12,7 @@ else fi $RETRY sudo apt-get -qq install libboost-dev libpcre3-dev -# testflags.py needs python -$RETRY sudo apt-get install -qq python +# Note: testflags.py needs python, but python is pre-installed WITHLANG=$SWIGLANG From 590de1642e21efc2e4d83774110e0e0fcb09dfbb Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Sat, 30 Jul 2022 21:16:10 +0100 Subject: [PATCH 583/662] MS_WIN64 no longer needed on Appveyor MinGW for Python Not sure why - 64bit must be default now. Fixes Appveyor and Python C++20 tests as the -std=c++20 flags were not being passed to the compiler. --- appveyor.yml | 3 --- 1 file changed, 3 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index 3a25ed199..152336be4 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -138,9 +138,6 @@ install: $env:MSYSTEM="MINGW$env:MBITS" # This is important for msys2 $env:CC="gcc" $env:CXX="g++" - if ($env:MBITS -eq "64" -and $env:SWIGLANG -eq "python") { - $env:CHECK_OPTIONS2="CFLAGS+=-DMS_WIN64 CXXFLAGS+=-DMS_WIN64" - } } - if "%OSVARIANT%"=="" bash -c "cd /usr/bin && curl --retry 15 -s -L https://github.com/swig/cccl/archive/cccl-1.2.tar.gz | tar -xz --strip 1 cccl-cccl-1.2/cccl" - if "%OSVARIANT%"=="" call "%VCVARSBAT%" %VCVARSARG% From 675c94c5758b56ce29c782d2319d1893702640a8 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Sat, 30 Jul 2022 21:35:05 +0100 Subject: [PATCH 584/662] Add in EXTRA_CFLAGS and EXTRA_CXXFLAGS for more flexible test-suite testing --- Examples/Makefile.in | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Examples/Makefile.in b/Examples/Makefile.in index 03b33430c..a3bda6fd7 100644 --- a/Examples/Makefile.in +++ b/Examples/Makefile.in @@ -46,8 +46,8 @@ TARGET = CC = @CC@ CXX = @CXX@ CPPFLAGS = $(SRCDIR_INCLUDE) -CFLAGS = @PLATCFLAGS@ -CXXFLAGS = @BOOST_CPPFLAGS@ @PLATCXXFLAGS@ +CFLAGS = @PLATCFLAGS@ $(EXTRA_CFLAGS) +CXXFLAGS = @BOOST_CPPFLAGS@ @PLATCXXFLAGS@ $(EXTRA_CXXFLAGS) LDFLAGS = prefix = @prefix@ exec_prefix= @exec_prefix@ From ffbde7a13206a592dc26f3e9e36ce35289e7baee Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Sat, 30 Jul 2022 23:21:21 +0100 Subject: [PATCH 585/662] Fixes for deprecated std::basic_string::reserve() --- CHANGES.current | 17 +++++++++++++++++ .../python/li_std_string_extra_runme.py | 5 +++++ Lib/std/std_basic_string.i | 11 ++++++++++- 3 files changed, 32 insertions(+), 1 deletion(-) diff --git a/CHANGES.current b/CHANGES.current index 1ec7a6435..7e7232383 100644 --- a/CHANGES.current +++ b/CHANGES.current @@ -7,6 +7,23 @@ the issue number to the end of the URL: https://github.com/swig/swig/issues/ Version 4.1.0 (in progress) =========================== +2022-07-30: wsfulton + C++20 has deprecated std::basic_string<>::reserve() and the C++11 method + std::basic_string<>::shrink_to_fit() is a replacement that can be used. + std_string.i and std_wstring.i provided wrappers for reserve with the following + template instantiations: + + %template(string) std::basic_string; + %template(wstring) std::basic_string; + + The reserve method is no longer wrapped, however the shrink_to_fit() method + can be used as an alternative from the target language (the generated wrappers + call reserve() instead if C++<=20). + + Note that std::basic_string<>::reserve(size_t n) is still wrapped unchanged. + + *** POTENTIAL INCOMPATIBILITY *** + 2022-07-30: wsfulton [Tcl] 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/python/li_std_string_extra_runme.py b/Examples/test-suite/python/li_std_string_extra_runme.py index 96c64163d..71620e7fb 100644 --- a/Examples/test-suite/python/li_std_string_extra_runme.py +++ b/Examples/test-suite/python/li_std_string_extra_runme.py @@ -15,6 +15,11 @@ if li_std_string_extra.test_value(x) != x: if li_std_string_extra.test_const_reference(x) != x: raise RuntimeError("bad string mapping") +s = li_std_string_extra.string("1234567890") +size = s.size() +if size != 10: + raise "Incorrect size" +s.shrink_to_fit() s = li_std_string_extra.string("he") #s += "ll" diff --git a/Lib/std/std_basic_string.i b/Lib/std/std_basic_string.i index fb7afc1e6..e95cb4765 100644 --- a/Lib/std/std_basic_string.i +++ b/Lib/std/std_basic_string.i @@ -55,7 +55,16 @@ namespace std { size_type capacity() const; - void reserve(size_type __res_arg = 0); + void reserve(size_type __res_arg); + %extend { + void shrink_to_fit() { + %#if __cplusplus >= 202002L + self->shrink_to_fit(); + %#else + self->reserve(); + %#endif + } + } // Modifiers: From ea3570ddb10f043b70b788d3b0b630e31d0b170d Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Sat, 30 Jul 2022 23:27:30 +0100 Subject: [PATCH 586/662] -Wvolatile gcc warning fix for C++20 --- Examples/test-suite/typemap_array_qualifiers.i | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Examples/test-suite/typemap_array_qualifiers.i b/Examples/test-suite/typemap_array_qualifiers.i index c3965ced2..f7cce3c86 100644 --- a/Examples/test-suite/typemap_array_qualifiers.i +++ b/Examples/test-suite/typemap_array_qualifiers.i @@ -26,6 +26,12 @@ } %enddef +%{ +#if __cplusplus >= 202002L +#define volatile +#endif +%} + %inline %{ typedef struct { int a; From 4e234c760450b4ab27ed35e68e05fe6f9092c177 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Sat, 30 Jul 2022 23:43:49 +0100 Subject: [PATCH 587/662] Suppress Visual C++ deprecated warnings --- Examples/test-suite/cpp11_attribute_specifiers.i | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Examples/test-suite/cpp11_attribute_specifiers.i b/Examples/test-suite/cpp11_attribute_specifiers.i index 063e431e0..b822d2ae9 100644 --- a/Examples/test-suite/cpp11_attribute_specifiers.i +++ b/Examples/test-suite/cpp11_attribute_specifiers.i @@ -17,6 +17,10 @@ #pragma clang diagnostic ignored "-Wunused-parameter" #endif +#if defined(_MSC_VER) +#pragma warning(disable : 4996) // For the deprecated attributes in this testcase +#endif + [[noreturn]] void noReturn() { throw; } [[nodiscard]] bool noDiscard() { return true; } From 3fa8e1f38fd53ceb58659949623f184b5971b9d4 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Sat, 30 Jul 2022 23:57:26 +0100 Subject: [PATCH 588/662] Visual C++ warning fix conversion from '__int64' to 'long', possible loss of data --- Source/Swig/typemap.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Swig/typemap.c b/Source/Swig/typemap.c index 126d88026..d6f48814d 100644 --- a/Source/Swig/typemap.c +++ b/Source/Swig/typemap.c @@ -2102,7 +2102,7 @@ static void replace_embedded_typemap(String *s, ParmList *parm_sublist, Wrapper found_colon = Strchr(tmap_method, ':'); if (found_colon) { /* Substitute from a keyword argument to a typemap. Avoid emitting local variables from the attached typemap by passing NULL for the file. */ - String *temp_tmap_method = NewStringWithSize(Char(tmap_method), found_colon - Char(tmap_method)); + String *temp_tmap_method = NewStringWithSize(Char(tmap_method), (int)(found_colon - Char(tmap_method))); Swig_typemap_attach_parms(temp_tmap_method, to_match_parms, NULL); Delete(temp_tmap_method); } else { From 842ae379aafe189ff83bed07579f6f56cb1c6771 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Sun, 31 Jul 2022 08:32:40 +0100 Subject: [PATCH 589/662] GHA: Fix for pycodestyle check in examples E275 missing whitespace after keyword For pycodestyle 2.9.0 released on 30 July 2022. --- Examples/python/import_packages/split_modules/vanilla/runme.py | 2 +- .../python/import_packages/split_modules/vanilla_split/runme.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Examples/python/import_packages/split_modules/vanilla/runme.py b/Examples/python/import_packages/split_modules/vanilla/runme.py index 723eb3aaa..963adca79 100644 --- a/Examples/python/import_packages/split_modules/vanilla/runme.py +++ b/Examples/python/import_packages/split_modules/vanilla/runme.py @@ -15,7 +15,7 @@ import pkg1.foo print(" Finished importing pkg1.foo") -if not(pkg1.foo.count() == 3): +if not pkg1.foo.count() == 3: raise RuntimeError("test failed") commandline = sys.executable + " -m pkg1.foo" diff --git a/Examples/python/import_packages/split_modules/vanilla_split/runme.py b/Examples/python/import_packages/split_modules/vanilla_split/runme.py index 723eb3aaa..963adca79 100644 --- a/Examples/python/import_packages/split_modules/vanilla_split/runme.py +++ b/Examples/python/import_packages/split_modules/vanilla_split/runme.py @@ -15,7 +15,7 @@ import pkg1.foo print(" Finished importing pkg1.foo") -if not(pkg1.foo.count() == 3): +if not pkg1.foo.count() == 3: raise RuntimeError("test failed") commandline = sys.executable + " -m pkg1.foo" From ae4642d4bb9cb94f4ee89bd6e9673c87f52af06e Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Sun, 31 Jul 2022 09:08:40 +0100 Subject: [PATCH 590/662] GHA: Test C17 with C++20 --- .github/workflows/ci.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6932556e4..3be9b3a1d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -392,6 +392,7 @@ jobs: c++11) export CSTD=c11 ;; c++14) export CSTD=c11 ;; c++17) export CSTD=c17 ;; + c++20) export CSTD=c20 ;; esac echo CSTD="$CSTD" >> $GITHUB_ENV fi From d9fd09aa21f4578bd0232c9b5e477bfba4d3029b Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Sun, 31 Jul 2022 14:32:04 +0100 Subject: [PATCH 591/662] Suppress Ruby.h gcc warnings --- Lib/ruby/rubyhead.swg | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/Lib/ruby/rubyhead.swg b/Lib/ruby/rubyhead.swg index bf4e36248..06c430bf6 100644 --- a/Lib/ruby/rubyhead.swg +++ b/Lib/ruby/rubyhead.swg @@ -1,5 +1,20 @@ +#if __GNUC__ >= 7 +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wregister" +#if __GNUC__ >= 10 +#pragma GCC diagnostic ignored "-Wvolatile" +#if __GNUC__ >= 11 +#pragma GCC diagnostic ignored "-Wdeprecated-enum-enum-conversion" +#endif +#endif +#endif + #include +#if __GNUC__ >= 7 +#pragma GCC diagnostic pop +#endif + /* Ruby 1.9.1 has a "memoisation optimisation" when compiling with GCC which * breaks using rb_intern as an lvalue, as SWIG does. We work around this * issue for now by disabling this. From ac8864bc59449e61e1f6ee08321bd2647f34c538 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Sun, 31 Jul 2022 16:15:00 +0100 Subject: [PATCH 592/662] ruby --- Lib/ruby/rubyhead.swg | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Lib/ruby/rubyhead.swg b/Lib/ruby/rubyhead.swg index 06c430bf6..e4d9e2147 100644 --- a/Lib/ruby/rubyhead.swg +++ b/Lib/ruby/rubyhead.swg @@ -1,5 +1,6 @@ #if __GNUC__ >= 7 #pragma GCC diagnostic push +#if defined(__cplusplus) #pragma GCC diagnostic ignored "-Wregister" #if __GNUC__ >= 10 #pragma GCC diagnostic ignored "-Wvolatile" @@ -8,6 +9,7 @@ #endif #endif #endif +#endif #include From e0ed4cc62d6aae3801df0adc2f877b729e6cdc88 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Sun, 31 Jul 2022 16:18:08 +0100 Subject: [PATCH 593/662] Suppress -Wvolatile gcc warnings in Guile wrappers for C++20 --- Lib/guile/guile_scm_run.swg | 6 ++++++ Lib/guile/swigrun.i | 2 -- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/Lib/guile/guile_scm_run.swg b/Lib/guile/guile_scm_run.swg index 2e96184b1..84444e33e 100644 --- a/Lib/guile/guile_scm_run.swg +++ b/Lib/guile/guile_scm_run.swg @@ -2,6 +2,12 @@ * guile_scm_run.swg * ----------------------------------------------------------------------------- */ +#if __GNUC__ >= 10 +#if defined(__cplusplus) +#pragma GCC diagnostic ignored "-Wvolatile" /* For 'volatile SCM *' in at least Guile 3.0 and earlier */ +#endif +#endif + #include #include #include diff --git a/Lib/guile/swigrun.i b/Lib/guile/swigrun.i index 4b9ea2c79..e4573eb3b 100644 --- a/Lib/guile/swigrun.i +++ b/Lib/guile/swigrun.i @@ -4,8 +4,6 @@ #ifdef SWIGGUILE_SCM -/* Hook the runtime module initialization - into the shared initialization function SWIG_Guile_Init. */ %runtime %{ /* Hook the runtime module initialization into the shared initialization function SWIG_Guile_Init. */ From 89f57708e9511f9e3ba7d69d3605cc5c942c7f94 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Sun, 31 Jul 2022 16:45:31 +0100 Subject: [PATCH 594/662] Suppress -Wvolatile gcc warnings in Perl headers for C++20 Seen in Perl 5.34 and earlier --- Lib/perl5/perlhead.swg | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/Lib/perl5/perlhead.swg b/Lib/perl5/perlhead.swg index bb7c1741d..773adee92 100644 --- a/Lib/perl5/perlhead.swg +++ b/Lib/perl5/perlhead.swg @@ -4,10 +4,21 @@ #include extern "C" { #endif + +#if __GNUC__ >= 10 +#if defined(__cplusplus) +#pragma GCC diagnostic ignored "-Wvolatile" +#endif +#endif + #include "EXTERN.h" #include "perl.h" #include "XSUB.h" +#if __GNUC__ >= 10 +#pragma GCC diagnostic pop +#endif + /* PERL_REVISION was added in Perl 5.6. */ #if !defined PERL_REVISION || (PERL_REVISION-0 == 5 && PERL_VERSION-0 < 8) # error SWIG requires Perl >= 5.8.0 From 54e7bb606e93207c497876a4a5c7e8e10b0224e9 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Sun, 31 Jul 2022 22:23:39 +0100 Subject: [PATCH 595/662] Correct c17 testing with C++20 --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3be9b3a1d..51cef6a20 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -392,7 +392,7 @@ jobs: c++11) export CSTD=c11 ;; c++14) export CSTD=c11 ;; c++17) export CSTD=c17 ;; - c++20) export CSTD=c20 ;; + c++20) export CSTD=c17 ;; esac echo CSTD="$CSTD" >> $GITHUB_ENV fi From 1d56bc6b856d2ddd4c647ff6a4ced5e8526e858b Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Mon, 1 Aug 2022 07:51:04 +0100 Subject: [PATCH 596/662] Add initialisers for additional members in PyHeapTypeObject (builtin mode) for Python-3.11 - _ht_tpname, _spec_cache. --- CHANGES.current | 4 ++++ Lib/python/builtin.swg | 2 +- Source/Modules/python.cxx | 11 +++++++++++ 3 files changed, 16 insertions(+), 1 deletion(-) diff --git a/CHANGES.current b/CHANGES.current index 7e7232383..616d973c9 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-01: wsfulton + [Python] Add initialisers for additional members in PyHeapTypeObject + (builtin mode) for Python-3.11 - _ht_tpname, _spec_cache. + 2022-07-30: wsfulton C++20 has deprecated std::basic_string<>::reserve() and the C++11 method std::basic_string<>::shrink_to_fit() is a replacement that can be used. diff --git a/Lib/python/builtin.swg b/Lib/python/builtin.swg index f31fccf1e..5cff6835f 100644 --- a/Lib/python/builtin.swg +++ b/Lib/python/builtin.swg @@ -426,7 +426,7 @@ SwigPyBuiltin_ThisClosure (PyObject *self, void *SWIGUNUSEDPARM(closure)) { SWIGINTERN void SwigPyBuiltin_SetMetaType (PyTypeObject *type, PyTypeObject *metatype) { -#if PY_VERSION_HEX >= 0x030900A4 +#if PY_VERSION_HEX >= 0x030900a4 Py_SET_TYPE(type, metatype); #else Py_TYPE(type) = metatype; diff --git a/Source/Modules/python.cxx b/Source/Modules/python.cxx index 9aac91601..2d2ac4f5f 100644 --- a/Source/Modules/python.cxx +++ b/Source/Modules/python.cxx @@ -4348,9 +4348,20 @@ public: printSlot(f, getSlot(n, "feature:python:ht_cached_keys"), "ht_cached_keys"); Printv(f, "#endif\n", NIL); + // PyObject *ht_module; Printv(f, "#if PY_VERSION_HEX >= 0x03090000\n", NIL); printSlot(f, getSlot(n, "feature:python:ht_module"), "ht_module", "PyObject *"); Printv(f, "#endif\n", NIL); + + // char *_ht_tpname; + Printv(f, "#if PY_VERSION_HEX >= 0x030b0000\n", NIL); + printSlot(f, getSlot(n, "feature:python:_ht_tpname"), "_ht_tpname", "char *"); + + // struct _specialization_cache _spec_cache; + Printf(f, " {\n"); + printSlot(f, getSlot(n, "feature:python:getitem"), "getitem", "PyObject *"); + Printf(f, " }\n"); + Printv(f, "#endif\n", NIL); Printf(f, "};\n\n"); String *clientdata = NewString(""); From 1730e4126e4283d3fd42cc4cd4710eec1919b3f5 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Mon, 1 Aug 2022 08:30:28 +0100 Subject: [PATCH 597/662] GHA: Start testing python-3.11 --- .github/workflows/ci.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 51cef6a20..427c5c381 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -132,6 +132,8 @@ jobs: VER: '3.9' - SWIGLANG: python VER: '3.10' + - SWIGLANG: python + VER: '3.11' - SWIGLANG: python PY2: 2 SWIG_FEATURES: -builtin From 2ccc9bd0607664ff1b86b65be4c797eeb69fcc00 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Mon, 1 Aug 2022 23:49:14 +0100 Subject: [PATCH 598/662] Add Octave support for std::unique_ptr and std::auto_ptr Equivalent to Ruby/Python implementations. --- CHANGES.current | 4 + Examples/test-suite/cpp11_std_unique_ptr.i | 2 +- Examples/test-suite/li_std_auto_ptr.i | 15 ++- .../octave/cpp11_std_unique_ptr_runme.m | 109 ++++++++++++++++++ .../test-suite/octave/li_std_auto_ptr_runme.m | 108 +++++++++++++++++ Lib/octave/octrun.swg | 57 ++++++--- Lib/octave/std_auto_ptr.i | 33 ++++++ Lib/octave/std_unique_ptr.i | 33 ++++++ 8 files changed, 341 insertions(+), 20 deletions(-) create mode 100644 Examples/test-suite/octave/cpp11_std_unique_ptr_runme.m create mode 100644 Examples/test-suite/octave/li_std_auto_ptr_runme.m create mode 100644 Lib/octave/std_auto_ptr.i create mode 100644 Lib/octave/std_unique_ptr.i diff --git a/CHANGES.current b/CHANGES.current index 616d973c9..d05cf04ca 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-02: wsfulton + [Octave] Add support for std::unique_ptr in std_unique_ptr.i. + Add support for std::auto_ptr in std_auto_ptr.i. + 2022-08-01: wsfulton [Python] Add initialisers for additional members in PyHeapTypeObject (builtin mode) for Python-3.11 - _ht_tpname, _spec_cache. diff --git a/Examples/test-suite/cpp11_std_unique_ptr.i b/Examples/test-suite/cpp11_std_unique_ptr.i index 2dcdbca45..745c7e918 100644 --- a/Examples/test-suite/cpp11_std_unique_ptr.i +++ b/Examples/test-suite/cpp11_std_unique_ptr.i @@ -1,6 +1,6 @@ %module cpp11_std_unique_ptr -#if defined(SWIGCSHARP) || defined(SWIGJAVA) || defined(SWIGPYTHON) || defined(SWIGRUBY) || defined(SWIGPERL) || defined(SWIGTCL) +#if defined(SWIGCSHARP) || defined(SWIGJAVA) || defined(SWIGPYTHON) || defined(SWIGRUBY) || defined(SWIGPERL) || defined(SWIGTCL) || defined(SWIGOCTAVE) %include "std_string.i" %include "std_unique_ptr.i" diff --git a/Examples/test-suite/li_std_auto_ptr.i b/Examples/test-suite/li_std_auto_ptr.i index 68dbf0ffa..e2a908423 100644 --- a/Examples/test-suite/li_std_auto_ptr.i +++ b/Examples/test-suite/li_std_auto_ptr.i @@ -12,17 +12,28 @@ #endif %} -#if defined(SWIGCSHARP) || defined(SWIGJAVA) || defined(SWIGPYTHON) || defined(SWIGRUBY) || defined(SWIGPERL) || defined(SWIGTCL) +#if defined(SWIGCSHARP) || defined(SWIGJAVA) || defined(SWIGPYTHON) || defined(SWIGRUBY) || defined(SWIGPERL) || defined(SWIGTCL) || defined(SWIGOCTAVE) %include "std_string.i" %include "std_auto_ptr.i" %auto_ptr(Klass) +%inline %{ +void show_cplusplus_version() { + printf("__cplusplus %d\n", (int)__cplusplus); +} +%} + %{ #if __cplusplus < 201703L #include #else + +// If has already been include (Octave does) then unfortunately gcc incorrectly still provides +// std::auto_ptr when _GLIBCXX_USE_DEPRECATED is defined by the compiler configuration/OS/who knows what!! +#include // Now need to include it in case _GLIBCXX_USE_DEPRECATED is defined and has not been included, argh +#if !defined(_GLIBCXX_USE_DEPRECATED) // Simple std::auto_ptr implementation for testing after its removal in C++17 namespace std { template class auto_ptr { @@ -40,6 +51,8 @@ namespace std { } #endif +#endif + #include #include "swig_examples_lock.h" %} diff --git a/Examples/test-suite/octave/cpp11_std_unique_ptr_runme.m b/Examples/test-suite/octave/cpp11_std_unique_ptr_runme.m new file mode 100644 index 000000000..3da93e338 --- /dev/null +++ b/Examples/test-suite/octave/cpp11_std_unique_ptr_runme.m @@ -0,0 +1,109 @@ +# do not dump Octave core +if exist("crash_dumps_octave_core", "builtin") + crash_dumps_octave_core(0); +endif + +cpp11_std_unique_ptr + +function checkCount(expected_count) + actual_count = Klass_getTotal_count(); + if (actual_count != expected_count) + error("Counts incorrect, expected:%d actual:%d", expected_count, actual_count); + endif +end + + +# unique_ptr as input +kin = Klass("KlassInput"); +checkCount(1); +s = takeKlassUniquePtr(kin); +checkCount(0); +if (!strcmp(s, "KlassInput")) + error("Incorrect string: %s", s); +endif +if (!is_nullptr(kin)) + error("is_nullptr failed"); +endif +clear kin; # Should not fail, even though already deleted +checkCount(0); + +kin = Klass("KlassInput"); +checkCount(1); +s = takeKlassUniquePtr(kin); +checkCount(0); +if (!strcmp(s, "KlassInput")) + error("Incorrect string: %s", s); +endif +if (!is_nullptr(kin)) + error("is_nullptr failed"); +endif +exception_thrown = false; +try + takeKlassUniquePtr(kin); +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("double usage of takeKlassUniquePtr should have been an error"); +endif +clear kin; # Should not fail, even though already deleted +checkCount(0); + +kin = Klass("KlassInput"); +exception_thrown = false; +try + notowned = get_not_owned_ptr(kin); + takeKlassUniquePtr(notowned); +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 +clear kin; +checkCount(0); + +kini = KlassInheritance("KlassInheritanceInput"); +checkCount(1); +s = takeKlassUniquePtr(kini); +checkCount(0); +if (!strcmp(s, "KlassInheritanceInput")) + error("Incorrect string: %s", s); +endif +if (!is_nullptr(kini)) + error("is_nullptr failed"); +endif +clear kini; # Should not fail, even though already deleted +checkCount(0); + + +# unique_ptr as output +k1 = makeKlassUniquePtr("first"); +if (!strcmp(k1.getLabel(), "first")) + error("wrong object label"); +endif + +k2 = makeKlassUniquePtr("second"); +if (Klass_getTotal_count() != 2) + error("number of objects should be 2"); +endif + +clear k1; +if (Klass.getTotal_count() != 1) + error("number of objects should be 1"); +endif + +if (!strcmp(k2.getLabel(), "second")) + error("wrong object label"); +endif + +clear k2; +if (Klass.getTotal_count() != 0) + error("no objects should be left"); +endif diff --git a/Examples/test-suite/octave/li_std_auto_ptr_runme.m b/Examples/test-suite/octave/li_std_auto_ptr_runme.m new file mode 100644 index 000000000..c1e655db5 --- /dev/null +++ b/Examples/test-suite/octave/li_std_auto_ptr_runme.m @@ -0,0 +1,108 @@ +# do not dump Octave core +if exist("crash_dumps_octave_core", "builtin") + crash_dumps_octave_core(0); +endif + +li_std_auto_ptr + +function checkCount(expected_count) + actual_count = Klass_getTotal_count(); + if (actual_count != expected_count) + error("Counts incorrect, expected:%d actual:%d", expected_count, actual_count); + endif +end + +# auto_ptr as input +kin = Klass("KlassInput"); +checkCount(1); +s = takeKlassAutoPtr(kin); +checkCount(0); +if (!strcmp(s, "KlassInput")) + error("Incorrect string: %s", s); +endif +if (!is_nullptr(kin)) + error("is_nullptr failed"); +endif +clear kin; # Should not fail, even though already deleted +checkCount(0); + +kin = Klass("KlassInput"); +checkCount(1); +s = takeKlassAutoPtr(kin); +checkCount(0); +if (!strcmp(s, "KlassInput")) + error("Incorrect string: %s", s); +endif +if (!is_nullptr(kin)) + error("is_nullptr failed"); +endif +exception_thrown = false; +try + takeKlassAutoPtr(kin); +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("double usage of takeKlassAutoPtr should have been an error"); +endif +clear kin; # Should not fail, even though already deleted +checkCount(0); + +kin = Klass("KlassInput"); +exception_thrown = false; +try + notowned = get_not_owned_ptr(kin); + takeKlassAutoPtr(notowned); +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 +clear kin; +checkCount(0); + +kini = KlassInheritance("KlassInheritanceInput"); +checkCount(1); +s = takeKlassAutoPtr(kini); +checkCount(0); +if (!strcmp(s, "KlassInheritanceInput")) + error("Incorrect string: %s", s); +endif +if (!is_nullptr(kini)) + error("is_nullptr failed"); +endif +clear kini; # Should not fail, even though already deleted +checkCount(0); + + +# auto_ptr as output +k1 = makeKlassAutoPtr("first"); +if (!strcmp(k1.getLabel(), "first")) + error("wrong object label"); +endif + +k2 = makeKlassAutoPtr("second"); +if (Klass_getTotal_count() != 2) + error("number of objects should be 2"); +endif + +clear k1; +if (Klass.getTotal_count() != 1) + error("number of objects should be 1"); +endif + +if (!strcmp(k2.getLabel(), "second")) + error("wrong object label"); +endif + +clear k2; +if (Klass.getTotal_count() != 0) + error("no objects should be left"); +endif diff --git a/Lib/octave/octrun.swg b/Lib/octave/octrun.swg index d94056c8c..71a907f9b 100644 --- a/Lib/octave/octrun.swg +++ b/Lib/octave/octrun.swg @@ -232,7 +232,7 @@ SWIGRUNTIME void swig_acquire_ownership_obj(void *vptr, int own); const swig_type_info *construct_type; // type of special type object std::vector < type_ptr_pair > types; // our c++ base classes - int own; // whether we call c++ destructors when we die + int thisown; // whether we call c++ destructors when we die typedef std::pair < const swig_octave_member *, octave_value > member_value_pair; typedef std::map < std::string, member_value_pair > member_map; @@ -412,7 +412,7 @@ SWIGRUNTIME void swig_acquire_ownership_obj(void *vptr, int own); octave_swig_type(void *_ptr = 0, const swig_type_info *_type = 0, int _own = 0, bool _always_static = false) - : module(0), construct_type(_ptr ? 0 : _type), own(_own), + : module(0), construct_type(_ptr ? 0 : _type), thisown(_own), always_static(_always_static) { if (_type || _ptr) types.push_back(std::make_pair(_type, _ptr)); @@ -426,7 +426,7 @@ SWIGRUNTIME void swig_acquire_ownership_obj(void *vptr, int own); } ~octave_swig_type() { - if (own) { + if (thisown) { ++count; for (unsigned int j = 0; j < types.size(); ++j) { if (!types[j].first || !types[j].first->clientdata) @@ -559,7 +559,7 @@ SWIGRUNTIME void swig_acquire_ownership_obj(void *vptr, int own); } void merge(octave_swig_type &rhs) { - rhs.own = 0; + rhs.thisown = 0; for (unsigned int j = 0; j < rhs.types.size(); ++j) { assert(!rhs.types[j].second.destroyed); #ifdef SWIG_DIRECTORS @@ -582,35 +582,56 @@ SWIGRUNTIME void swig_acquire_ownership_obj(void *vptr, int own); swig_member_const_iterator swig_members_begin() { return members.begin(); } swig_member_const_iterator swig_members_end() { return members.end(); } - int cast(void **vptr, swig_type_info *type, int *_own, int flags) { + int cast(void **vptr, swig_type_info *type, int *own, int flags) { int res = SWIG_ERROR; - if (_own) - *_own = own; - if (flags &SWIG_POINTER_DISOWN) - own = 0; + int clear_pointer = 0; + + if (own) + *own = 0; + if (((flags & SWIG_POINTER_RELEASE) == SWIG_POINTER_RELEASE) && !thisown) { + return SWIG_ERROR_RELEASE_NOT_OWNED; + } else { + if (own) + *own = *own | thisown; + if (flags & SWIG_POINTER_DISOWN) { + thisown = 0; + } + if (flags & SWIG_POINTER_CLEAR) { + clear_pointer = 1; + } + } + if (!type && types.size()) { - if(vptr) + if (vptr) { *vptr = types[0].second.ptr; + if (clear_pointer) + types[0].second.ptr = 0; + } return SWIG_OK; } for (unsigned int j = 0; j < types.size(); ++j) if (type == types[j].first) { - if(vptr) + if (vptr) { *vptr = types[j].second.ptr; + if (clear_pointer) + types[j].second.ptr = 0; + } return SWIG_OK; } for (unsigned int j = 0; j < types.size(); ++j) { swig_cast_info *tc = SWIG_TypeCheck(types[j].first->name, type); if (!tc) continue; - if(vptr) { + if (vptr) { int newmemory = 0; *vptr = SWIG_TypeCast(tc, types[j].second.ptr, &newmemory); - if (newmemory == SWIG_CAST_NEW_MEMORY) { - assert(_own); /* badly formed typemap which will lead to a memory leak - it must set and use own to delete *ptr */ - if (_own) - *_own = *_own | SWIG_CAST_NEW_MEMORY; - } + if (newmemory == SWIG_CAST_NEW_MEMORY) { + assert(own); /* badly formed typemap which will lead to a memory leak - it must set and use own to delete *ptr */ + if (own) + *own = *own | SWIG_CAST_NEW_MEMORY; + } + if (clear_pointer) + types[j].second.ptr = 0; } res = SWIG_OK; break; @@ -619,7 +640,7 @@ SWIGRUNTIME void swig_acquire_ownership_obj(void *vptr, int own); } bool is_owned() const { - return own; + return thisown; } #ifdef SWIG_DIRECTORS diff --git a/Lib/octave/std_auto_ptr.i b/Lib/octave/std_auto_ptr.i new file mode 100644 index 000000000..d062886e4 --- /dev/null +++ b/Lib/octave/std_auto_ptr.i @@ -0,0 +1,33 @@ +/* ----------------------------------------------------------------------------- + * std_auto_ptr.i + * + * SWIG library file for handling std::auto_ptr. + * Memory ownership is passed from the std::auto_ptr C++ layer to the proxy + * class when returning a std::auto_ptr from a function. + * Memory ownership is passed from the proxy class to the std::auto_ptr in the + * C++ layer when passed as a parameter to a wrapped function. + * ----------------------------------------------------------------------------- */ + +%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 | %convertptr_flags); + if (!SWIG_IsOK(res)) { + if (res == SWIG_ERROR_RELEASE_NOT_OWNED) { + %releasenotowned_fail(res, "TYPE *", $symname, $argnum); + } else { + %argument_fail(res, "TYPE *", $symname, $argnum); + } + } + $1.reset((TYPE *)argp); +} + +%typemap (out) std::auto_ptr< TYPE > %{ + %set_output(SWIG_NewPointerObj($1.release(), $descriptor(TYPE *), SWIG_POINTER_OWN | %newpointer_flags)); +%} + +%template() std::auto_ptr< TYPE >; +%enddef + +namespace std { + template class auto_ptr {}; +} diff --git a/Lib/octave/std_unique_ptr.i b/Lib/octave/std_unique_ptr.i new file mode 100644 index 000000000..1a7ec06fa --- /dev/null +++ b/Lib/octave/std_unique_ptr.i @@ -0,0 +1,33 @@ +/* ----------------------------------------------------------------------------- + * std_unique_ptr.i + * + * SWIG library file for handling std::unique_ptr. + * Memory ownership is passed from the std::unique_ptr C++ layer to the proxy + * class when returning a std::unique_ptr from a function. + * Memory ownership is passed from the proxy class to the std::unique_ptr in the + * C++ layer when passed as a parameter to a wrapped function. + * ----------------------------------------------------------------------------- */ + +%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 | %convertptr_flags); + if (!SWIG_IsOK(res)) { + if (res == SWIG_ERROR_RELEASE_NOT_OWNED) { + %releasenotowned_fail(res, "TYPE *", $symname, $argnum); + } else { + %argument_fail(res, "TYPE *", $symname, $argnum); + } + } + $1.reset((TYPE *)argp); +} + +%typemap (out) std::unique_ptr< TYPE > %{ + %set_output(SWIG_NewPointerObj($1.release(), $descriptor(TYPE *), SWIG_POINTER_OWN | %newpointer_flags)); +%} + +%template() std::unique_ptr< TYPE >; +%enddef + +namespace std { + template class unique_ptr {}; +} From 239ffe4b5b098d78de2be84d5fe9297b91b135c5 Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Wed, 16 Mar 2022 17:55:33 +1300 Subject: [PATCH 599/662] [ci] Add testing for guile 2.2 and 3.0 --- .github/workflows/ci.yml | 4 ++++ Tools/CI-linux-install.sh | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 427c5c381..2166d9879 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -67,6 +67,10 @@ jobs: - SWIGLANG: go VER: '1.17' - SWIGLANG: guile + - SWIGLANG: guile + VER: '2.2' + - SWIGLANG: guile + VER: '3.0' - SWIGLANG: java - SWIGLANG: javascript ENGINE: node diff --git a/Tools/CI-linux-install.sh b/Tools/CI-linux-install.sh index 525121e8c..ea811f506 100644 --- a/Tools/CI-linux-install.sh +++ b/Tools/CI-linux-install.sh @@ -62,7 +62,7 @@ case "$SWIGLANG" in esac ;; "guile") - $RETRY sudo apt-get -qq install guile-2.0-dev + $RETRY sudo apt-get -qq install guile-${VER:-2.0}-dev ;; "lua") if [[ -z "$VER" ]]; then From 336de2f745fec4e1979d24e9d7991dbf05fa90fb Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Wed, 16 Mar 2022 18:04:44 +1300 Subject: [PATCH 600/662] [guile] Stop using deprecated aliases The replacements should all work with Guile 1.8.0, which is the oldest version we still aim to support. Fixes #1624 --- .../guile/guile_ext_test_external.cxx | 2 +- Lib/guile/guile_scm_run.swg | 18 +++++++++--------- Lib/guile/typemaps.i | 2 +- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/Examples/test-suite/guile/guile_ext_test_external.cxx b/Examples/test-suite/guile/guile_ext_test_external.cxx index c4f906a97..2729537bd 100644 --- a/Examples/test-suite/guile/guile_ext_test_external.cxx +++ b/Examples/test-suite/guile/guile_ext_test_external.cxx @@ -19,6 +19,6 @@ SCM test_create() SCM test_is_pointer(SCM val) { #define FUNC_NAME "test-is-pointer" - return SCM_BOOL(SWIG_IsPointer(val)); + return scm_from_bool(SWIG_IsPointer(val)); #undef FUNC_NAME } diff --git a/Lib/guile/guile_scm_run.swg b/Lib/guile/guile_scm_run.swg index 84444e33e..3752d3c8a 100644 --- a/Lib/guile/guile_scm_run.swg +++ b/Lib/guile/guile_scm_run.swg @@ -131,7 +131,7 @@ SWIG_Guile_NewPointerObj(void *ptr, swig_type_info *type, int owner) else SCM_NEWSMOB2(smob, swig_tag, ptr, (void *) type); - if (!cdata || SCM_NULLP(cdata->goops_class) || swig_make_func == SCM_EOL ) { + if (!cdata || scm_is_null(cdata->goops_class) || swig_make_func == SCM_EOL ) { return smob; } else { /* the scm_make() C function only handles the creation of gf, @@ -151,7 +151,7 @@ SWIGINTERN unsigned long SWIG_Guile_PointerAddress(SCM object) { SCM smob = SWIG_Guile_GetSmob(object); - if (SCM_NULLP(smob)) return 0; + if (scm_is_null(smob)) return 0; else if (SCM_SMOB_PREDICATE(swig_tag, smob) || SCM_SMOB_PREDICATE(swig_collectable_tag, smob) || SCM_SMOB_PREDICATE(swig_destroyed_tag, smob)) { @@ -164,7 +164,7 @@ SWIGINTERN swig_type_info * SWIG_Guile_PointerType(SCM object) { SCM smob = SWIG_Guile_GetSmob(object); - if (SCM_NULLP(smob)) return NULL; + if (scm_is_null(smob)) return NULL; else if (SCM_SMOB_PREDICATE(swig_tag, smob) || SCM_SMOB_PREDICATE(swig_collectable_tag, smob) || SCM_SMOB_PREDICATE(swig_destroyed_tag, smob)) { @@ -192,7 +192,7 @@ SWIG_Guile_ConvertPtr(SCM s, void **result, swig_type_info *type, int flags) swig_type_info *from; SCM smob = SWIG_Guile_GetSmob(s); - if (SCM_NULLP(smob)) { + if (scm_is_null(smob)) { *result = NULL; return (flags & SWIG_POINTER_NO_NULL) ? SWIG_NullReferenceError : SWIG_OK; #if SCM_MAJOR_VERSION >= 2 @@ -258,7 +258,7 @@ SWIGINTERN void SWIG_Guile_MarkPointerNoncollectable(SCM s) { SCM smob = SWIG_Guile_GetSmob(s); - if (!SCM_NULLP(smob)) { + if (!scm_is_null(smob)) { if (SWIG_Guile_IsValidSmob(smob)) { SCM_SET_CELL_TYPE(smob, swig_tag); } @@ -271,7 +271,7 @@ SWIGINTERN void SWIG_Guile_MarkPointerDestroyed(SCM s) { SCM smob = SWIG_Guile_GetSmob(s); - if (!SCM_NULLP(smob)) { + if (!scm_is_null(smob)) { if (SWIG_Guile_IsValidSmob(smob)) { SCM_SET_CELL_TYPE(smob, swig_destroyed_tag); } @@ -492,20 +492,20 @@ SWIG_Guile_GetArgs (SCM *dest, SCM rest, int i; int num_args_passed = 0; for (i = 0; i Date: Wed, 16 Mar 2022 18:03:14 +1300 Subject: [PATCH 601/662] [guile] Update supported guile versions in docs Document that Guile 2.2.x and 3.0.x work. Document that Guile 1.8.x is believed to still work, but that we're no longer able to easily test this. --- Doc/Manual/Guile.html | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/Doc/Manual/Guile.html b/Doc/Manual/Guile.html index f72a4287b..5a95f3b7d 100644 --- a/Doc/Manual/Guile.html +++ b/Doc/Manual/Guile.html @@ -52,9 +52,10 @@ This section details guile-specific support in SWIG.

    -SWIG works with Guile versions 1.8.x and 2.0.x. Support for version -1.6.x has been dropped. The last version of SWIG that still works with -Guile version 1.6.x is SWIG 2.0.9. +SWIG is known to work with Guile versions 2.0.x, 2.2.x and 3.0.x. We believe +it still works with 1.8.x, but we're no longer able to easily test this. +Support for version 1.6.x has been dropped. The last version of SWIG that still +works with Guile version 1.6.x is SWIG 2.0.9.

    Note that starting with guile 2.0, the guile sources can be compiled for From fe17296eb4f80bb03d8d419e88098be958ee8c15 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Wed, 3 Aug 2022 20:19:38 +0100 Subject: [PATCH 602/662] Add Javascript support for std::unique_ptr and std::auto_ptr Equivalent to Ruby/Python implementations. --- CHANGES.current | 4 + Examples/test-suite/cpp11_std_unique_ptr.i | 2 +- .../javascript/cpp11_std_unique_ptr_runme.js | 101 ++++++++++++++++++ .../javascript/li_std_auto_ptr_runme.js | 101 ++++++++++++++++++ Examples/test-suite/li_std_auto_ptr.i | 2 +- Lib/javascript/jsc/javascriptrun.swg | 11 +- Lib/javascript/jsc/std_auto_ptr.i | 33 ++++++ Lib/javascript/jsc/std_unique_ptr.i | 33 ++++++ Lib/javascript/v8/javascriptrun.swg | 11 +- Lib/javascript/v8/std_auto_ptr.i | 33 ++++++ Lib/javascript/v8/std_unique_ptr.i | 33 ++++++ 11 files changed, 358 insertions(+), 6 deletions(-) create mode 100644 Examples/test-suite/javascript/cpp11_std_unique_ptr_runme.js create mode 100644 Examples/test-suite/javascript/li_std_auto_ptr_runme.js create mode 100644 Lib/javascript/jsc/std_auto_ptr.i create mode 100644 Lib/javascript/jsc/std_unique_ptr.i create mode 100644 Lib/javascript/v8/std_auto_ptr.i create mode 100644 Lib/javascript/v8/std_unique_ptr.i diff --git a/CHANGES.current b/CHANGES.current index d05cf04ca..c50691bac 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-03: wsfulton + [Javascript] Add support for std::unique_ptr in std_unique_ptr.i. + Add support for std::auto_ptr in std_auto_ptr.i. + 2022-08-02: wsfulton [Octave] 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/cpp11_std_unique_ptr.i b/Examples/test-suite/cpp11_std_unique_ptr.i index 745c7e918..9475890d8 100644 --- a/Examples/test-suite/cpp11_std_unique_ptr.i +++ b/Examples/test-suite/cpp11_std_unique_ptr.i @@ -1,6 +1,6 @@ %module cpp11_std_unique_ptr -#if defined(SWIGCSHARP) || defined(SWIGJAVA) || defined(SWIGPYTHON) || defined(SWIGRUBY) || defined(SWIGPERL) || defined(SWIGTCL) || defined(SWIGOCTAVE) +#if defined(SWIGCSHARP) || defined(SWIGJAVA) || defined(SWIGPYTHON) || defined(SWIGRUBY) || defined(SWIGPERL) || defined(SWIGTCL) || defined(SWIGOCTAVE) || defined(SWIGJAVASCRIPT) %include "std_string.i" %include "std_unique_ptr.i" diff --git a/Examples/test-suite/javascript/cpp11_std_unique_ptr_runme.js b/Examples/test-suite/javascript/cpp11_std_unique_ptr_runme.js new file mode 100644 index 000000000..e29217f5f --- /dev/null +++ b/Examples/test-suite/javascript/cpp11_std_unique_ptr_runme.js @@ -0,0 +1,101 @@ +var cpp11_std_unique_ptr = require("cpp11_std_unique_ptr"); + +var checkCount = function(expected_count) { + actual_count = cpp11_std_unique_ptr.Klass.getTotal_count(); + if (actual_count != expected_count) + throw new Error("Counts incorrect, expected:" + expected_count + " actual:" + actual_count); +} + +// unique_ptr as input +{ + kin = new cpp11_std_unique_ptr.Klass("KlassInput"); + checkCount(1); + s = cpp11_std_unique_ptr.takeKlassUniquePtr(kin); + checkCount(0); + if (s !== "KlassInput") + throw new Error("Incorrect string: " + s); + if (!cpp11_std_unique_ptr.is_nullptr(kin)) + throw new Error("is_nullptr failed"); + delete kin; // Should not fail, even though already deleted + checkCount(0); +} + +{ + kin = new cpp11_std_unique_ptr.Klass("KlassInput"); + checkCount(1); + s = cpp11_std_unique_ptr.takeKlassUniquePtr(kin); + checkCount(0); + if (s !== "KlassInput") + throw new Error("Incorrect string: " + s); + if (!cpp11_std_unique_ptr.is_nullptr(kin)) + throw new Error("is_nullptr failed"); + exception_thrown = false; + try { + cpp11_std_unique_ptr.takeKlassUniquePtr(kin); + } 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("double usage of takeKlassUniquePtr should have been an error"); + delete kin; // Should not fail, even though already deleted + checkCount(0); +} + +{ + kin = new cpp11_std_unique_ptr.Klass("KlassInput"); + exception_thrown = false; + notowned = cpp11_std_unique_ptr.get_not_owned_ptr(kin); + try { + cpp11_std_unique_ptr.takeKlassUniquePtr(notowned); + } 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"); + checkCount(1); + // delete kin; + // Above not deleting the C++ object(node v12) - can't reliably control GC + cpp11_std_unique_ptr.takeKlassUniquePtr(kin); + checkCount(0); +} + +{ + kini = new cpp11_std_unique_ptr.KlassInheritance("KlassInheritanceInput"); + checkCount(1); + s = cpp11_std_unique_ptr.takeKlassUniquePtr(kini); + checkCount(0); + if (s !== "KlassInheritanceInput") + throw new Error("Incorrect string: " + s); + if (!cpp11_std_unique_ptr.is_nullptr(kini)) + throw new Error("is_nullptr failed"); + delete kini; // Should not fail, even though already deleted + checkCount(0); +} + +// unique_ptr as output +k1 = cpp11_std_unique_ptr.makeKlassUniquePtr("first"); +if (k1.getLabel() !== "first") + throw new Error("wrong object label"); + +k2 = cpp11_std_unique_ptr.makeKlassUniquePtr("second"); +if (cpp11_std_unique_ptr.Klass.getTotal_count() != 2) + throw new Error("number of objects should be 2"); + +// delete k1; +// Above not deleting the C++ object(node v12), not sure why, use below as workaround +cpp11_std_unique_ptr.takeKlassUniquePtr(k1); +if (cpp11_std_unique_ptr.Klass.getTotal_count() != 1) + throw new Error("number of objects should be 1"); + +if (k2.getLabel() !== "second") + throw new Error("wrong object label"); + +// delete k2; +// Above not deleting the C++ object(node v12) - can't reliably control GC +cpp11_std_unique_ptr.takeKlassUniquePtr(k2); +if (cpp11_std_unique_ptr.Klass.getTotal_count() != 0) + throw new Error("no objects should be left"); diff --git a/Examples/test-suite/javascript/li_std_auto_ptr_runme.js b/Examples/test-suite/javascript/li_std_auto_ptr_runme.js new file mode 100644 index 000000000..5cb2007f8 --- /dev/null +++ b/Examples/test-suite/javascript/li_std_auto_ptr_runme.js @@ -0,0 +1,101 @@ +var li_std_auto_ptr = require("li_std_auto_ptr"); + +var checkCount = function(expected_count) { + actual_count = li_std_auto_ptr.Klass.getTotal_count(); + if (actual_count != expected_count) + throw new Error("Counts incorrect, expected:" + expected_count + " actual:" + actual_count); +} + +// auto_ptr as input +{ + kin = new li_std_auto_ptr.Klass("KlassInput"); + checkCount(1); + s = li_std_auto_ptr.takeKlassAutoPtr(kin); + checkCount(0); + if (s !== "KlassInput") + throw new Error("Incorrect string: " + s); + if (!li_std_auto_ptr.is_nullptr(kin)) + throw new Error("is_nullptr failed"); + delete kin; // Should not fail, even though already deleted + checkCount(0); +} + +{ + kin = new li_std_auto_ptr.Klass("KlassInput"); + checkCount(1); + s = li_std_auto_ptr.takeKlassAutoPtr(kin); + checkCount(0); + if (s !== "KlassInput") + throw new Error("Incorrect string: " + s); + if (!li_std_auto_ptr.is_nullptr(kin)) + throw new Error("is_nullptr failed"); + exception_thrown = false; + try { + li_std_auto_ptr.takeKlassAutoPtr(kin); + } 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("double usage of takeKlassAutoPtr should have been an error"); + delete kin; // Should not fail, even though already deleted + checkCount(0); +} + +{ + kin = new li_std_auto_ptr.Klass("KlassInput"); + exception_thrown = false; + notowned = li_std_auto_ptr.get_not_owned_ptr(kin); + try { + li_std_auto_ptr.takeKlassAutoPtr(notowned); + } 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"); + checkCount(1); + // delete kin; + // Above not deleting the C++ object(node v12) - can't reliably control GC + li_std_auto_ptr.takeKlassAutoPtr(kin); + checkCount(0); +} + +{ + kini = new li_std_auto_ptr.KlassInheritance("KlassInheritanceInput"); + checkCount(1); + s = li_std_auto_ptr.takeKlassAutoPtr(kini); + checkCount(0); + if (s !== "KlassInheritanceInput") + throw new Error("Incorrect string: " + s); + if (!li_std_auto_ptr.is_nullptr(kini)) + throw new Error("is_nullptr failed"); + delete kini; // Should not fail, even though already deleted + checkCount(0); +} + +// auto_ptr as output +k1 = li_std_auto_ptr.makeKlassAutoPtr("first"); +if (k1.getLabel() !== "first") + throw new Error("wrong object label"); + +k2 = li_std_auto_ptr.makeKlassAutoPtr("second"); +if (li_std_auto_ptr.Klass.getTotal_count() != 2) + throw new Error("number of objects should be 2"); + +// delete k1; +// Above not deleting the C++ object(node v12), not sure why, use below as workaround +li_std_auto_ptr.takeKlassAutoPtr(k1); +if (li_std_auto_ptr.Klass.getTotal_count() != 1) + throw new Error("number of objects should be 1"); + +if (k2.getLabel() !== "second") + throw new Error("wrong object label"); + +// 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.Klass.getTotal_count() != 0) + throw new Error("no objects should be left"); diff --git a/Examples/test-suite/li_std_auto_ptr.i b/Examples/test-suite/li_std_auto_ptr.i index e2a908423..06591a971 100644 --- a/Examples/test-suite/li_std_auto_ptr.i +++ b/Examples/test-suite/li_std_auto_ptr.i @@ -12,7 +12,7 @@ #endif %} -#if defined(SWIGCSHARP) || defined(SWIGJAVA) || defined(SWIGPYTHON) || defined(SWIGRUBY) || defined(SWIGPERL) || defined(SWIGTCL) || defined(SWIGOCTAVE) +#if defined(SWIGCSHARP) || defined(SWIGJAVA) || defined(SWIGPYTHON) || defined(SWIGRUBY) || defined(SWIGPERL) || defined(SWIGTCL) || defined(SWIGOCTAVE) || defined(SWIGJAVASCRIPT) %include "std_string.i" %include "std_auto_ptr.i" diff --git a/Lib/javascript/jsc/javascriptrun.swg b/Lib/javascript/jsc/javascriptrun.swg index 20e747872..2ffb533f4 100644 --- a/Lib/javascript/jsc/javascriptrun.swg +++ b/Lib/javascript/jsc/javascriptrun.swg @@ -135,8 +135,15 @@ SWIGRUNTIME int SWIG_JSC_ConvertInstancePtr(JSContextRef context, JSObjectRef ob } } - if (flags & SWIG_POINTER_DISOWN) { - cdata->swigCMemOwn = false; + if (((flags & SWIG_POINTER_RELEASE) == SWIG_POINTER_RELEASE) && !cdata->swigCMemOwn) { + return SWIG_ERROR_RELEASE_NOT_OWNED; + } else { + if (flags & SWIG_POINTER_DISOWN) { + cdata->swigCMemOwn = false; + } + if (flags & SWIG_POINTER_CLEAR) { + cdata->swigCObject = 0; + } } return SWIG_OK; diff --git a/Lib/javascript/jsc/std_auto_ptr.i b/Lib/javascript/jsc/std_auto_ptr.i new file mode 100644 index 000000000..d062886e4 --- /dev/null +++ b/Lib/javascript/jsc/std_auto_ptr.i @@ -0,0 +1,33 @@ +/* ----------------------------------------------------------------------------- + * std_auto_ptr.i + * + * SWIG library file for handling std::auto_ptr. + * Memory ownership is passed from the std::auto_ptr C++ layer to the proxy + * class when returning a std::auto_ptr from a function. + * Memory ownership is passed from the proxy class to the std::auto_ptr in the + * C++ layer when passed as a parameter to a wrapped function. + * ----------------------------------------------------------------------------- */ + +%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 | %convertptr_flags); + if (!SWIG_IsOK(res)) { + if (res == SWIG_ERROR_RELEASE_NOT_OWNED) { + %releasenotowned_fail(res, "TYPE *", $symname, $argnum); + } else { + %argument_fail(res, "TYPE *", $symname, $argnum); + } + } + $1.reset((TYPE *)argp); +} + +%typemap (out) std::auto_ptr< TYPE > %{ + %set_output(SWIG_NewPointerObj($1.release(), $descriptor(TYPE *), SWIG_POINTER_OWN | %newpointer_flags)); +%} + +%template() std::auto_ptr< TYPE >; +%enddef + +namespace std { + template class auto_ptr {}; +} diff --git a/Lib/javascript/jsc/std_unique_ptr.i b/Lib/javascript/jsc/std_unique_ptr.i new file mode 100644 index 000000000..1a7ec06fa --- /dev/null +++ b/Lib/javascript/jsc/std_unique_ptr.i @@ -0,0 +1,33 @@ +/* ----------------------------------------------------------------------------- + * std_unique_ptr.i + * + * SWIG library file for handling std::unique_ptr. + * Memory ownership is passed from the std::unique_ptr C++ layer to the proxy + * class when returning a std::unique_ptr from a function. + * Memory ownership is passed from the proxy class to the std::unique_ptr in the + * C++ layer when passed as a parameter to a wrapped function. + * ----------------------------------------------------------------------------- */ + +%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 | %convertptr_flags); + if (!SWIG_IsOK(res)) { + if (res == SWIG_ERROR_RELEASE_NOT_OWNED) { + %releasenotowned_fail(res, "TYPE *", $symname, $argnum); + } else { + %argument_fail(res, "TYPE *", $symname, $argnum); + } + } + $1.reset((TYPE *)argp); +} + +%typemap (out) std::unique_ptr< TYPE > %{ + %set_output(SWIG_NewPointerObj($1.release(), $descriptor(TYPE *), SWIG_POINTER_OWN | %newpointer_flags)); +%} + +%template() std::unique_ptr< TYPE >; +%enddef + +namespace std { + template class unique_ptr {}; +} diff --git a/Lib/javascript/v8/javascriptrun.swg b/Lib/javascript/v8/javascriptrun.swg index 7e50a8b84..6d3d4e82e 100644 --- a/Lib/javascript/v8/javascriptrun.swg +++ b/Lib/javascript/v8/javascriptrun.swg @@ -194,8 +194,15 @@ SWIGRUNTIME int SWIG_V8_ConvertInstancePtr(SWIGV8_OBJECT objRef, void **ptr, swi *ptr = cdata->swigCObject; } - if(flags & SWIG_POINTER_DISOWN) { - cdata->swigCMemOwn = false; + if (((flags & SWIG_POINTER_RELEASE) == SWIG_POINTER_RELEASE) && !cdata->swigCMemOwn) { + return SWIG_ERROR_RELEASE_NOT_OWNED; + } else { + if (flags & SWIG_POINTER_DISOWN) { + cdata->swigCMemOwn = false; + } + if (flags & SWIG_POINTER_CLEAR) { + cdata->swigCObject = 0; + } } return SWIG_OK; } diff --git a/Lib/javascript/v8/std_auto_ptr.i b/Lib/javascript/v8/std_auto_ptr.i new file mode 100644 index 000000000..d062886e4 --- /dev/null +++ b/Lib/javascript/v8/std_auto_ptr.i @@ -0,0 +1,33 @@ +/* ----------------------------------------------------------------------------- + * std_auto_ptr.i + * + * SWIG library file for handling std::auto_ptr. + * Memory ownership is passed from the std::auto_ptr C++ layer to the proxy + * class when returning a std::auto_ptr from a function. + * Memory ownership is passed from the proxy class to the std::auto_ptr in the + * C++ layer when passed as a parameter to a wrapped function. + * ----------------------------------------------------------------------------- */ + +%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 | %convertptr_flags); + if (!SWIG_IsOK(res)) { + if (res == SWIG_ERROR_RELEASE_NOT_OWNED) { + %releasenotowned_fail(res, "TYPE *", $symname, $argnum); + } else { + %argument_fail(res, "TYPE *", $symname, $argnum); + } + } + $1.reset((TYPE *)argp); +} + +%typemap (out) std::auto_ptr< TYPE > %{ + %set_output(SWIG_NewPointerObj($1.release(), $descriptor(TYPE *), SWIG_POINTER_OWN | %newpointer_flags)); +%} + +%template() std::auto_ptr< TYPE >; +%enddef + +namespace std { + template class auto_ptr {}; +} diff --git a/Lib/javascript/v8/std_unique_ptr.i b/Lib/javascript/v8/std_unique_ptr.i new file mode 100644 index 000000000..1a7ec06fa --- /dev/null +++ b/Lib/javascript/v8/std_unique_ptr.i @@ -0,0 +1,33 @@ +/* ----------------------------------------------------------------------------- + * std_unique_ptr.i + * + * SWIG library file for handling std::unique_ptr. + * Memory ownership is passed from the std::unique_ptr C++ layer to the proxy + * class when returning a std::unique_ptr from a function. + * Memory ownership is passed from the proxy class to the std::unique_ptr in the + * C++ layer when passed as a parameter to a wrapped function. + * ----------------------------------------------------------------------------- */ + +%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 | %convertptr_flags); + if (!SWIG_IsOK(res)) { + if (res == SWIG_ERROR_RELEASE_NOT_OWNED) { + %releasenotowned_fail(res, "TYPE *", $symname, $argnum); + } else { + %argument_fail(res, "TYPE *", $symname, $argnum); + } + } + $1.reset((TYPE *)argp); +} + +%typemap (out) std::unique_ptr< TYPE > %{ + %set_output(SWIG_NewPointerObj($1.release(), $descriptor(TYPE *), SWIG_POINTER_OWN | %newpointer_flags)); +%} + +%template() std::unique_ptr< TYPE >; +%enddef + +namespace std { + template class unique_ptr {}; +} From a741c7dbcf107013c37c14032367720ee9c9d3c6 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Wed, 3 Aug 2022 20:32:58 +0100 Subject: [PATCH 603/662] auto_ptr and unique_ptr test tweaks --- Examples/test-suite/csharp/cpp11_std_unique_ptr_runme.cs | 3 ++- Examples/test-suite/csharp/li_std_auto_ptr_runme.cs | 3 ++- Examples/test-suite/java/cpp11_std_unique_ptr_runme.java | 3 ++- Examples/test-suite/java/li_std_auto_ptr_runme.java | 3 ++- Examples/test-suite/octave/cpp11_std_unique_ptr_runme.m | 3 ++- Examples/test-suite/octave/li_std_auto_ptr_runme.m | 3 ++- Examples/test-suite/perl5/cpp11_std_unique_ptr_runme.pl | 5 +++-- Examples/test-suite/perl5/li_std_auto_ptr_runme.pl | 5 +++-- Examples/test-suite/python/cpp11_std_unique_ptr_runme.py | 3 ++- Examples/test-suite/python/li_std_auto_ptr_runme.py | 3 ++- Examples/test-suite/ruby/cpp11_std_unique_ptr_runme.rb | 3 ++- Examples/test-suite/ruby/li_std_auto_ptr_runme.rb | 3 ++- Examples/test-suite/tcl/cpp11_std_unique_ptr_runme.tcl | 3 ++- Examples/test-suite/tcl/li_std_auto_ptr_runme.tcl | 3 ++- 14 files changed, 30 insertions(+), 16 deletions(-) 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 09c6ec0af..9382cb83a 100644 --- a/Examples/test-suite/csharp/cpp11_std_unique_ptr_runme.cs +++ b/Examples/test-suite/csharp/cpp11_std_unique_ptr_runme.cs @@ -53,8 +53,8 @@ public class cpp11_std_unique_ptr_runme { using (Klass kin = new Klass("KlassInput")) { bool exception_thrown = false; + Klass notowned = cpp11_std_unique_ptr.get_not_owned_ptr(kin); try { - Klass notowned = cpp11_std_unique_ptr.get_not_owned_ptr(kin); cpp11_std_unique_ptr.takeKlassUniquePtr(notowned); } catch (ApplicationException e) { if (!e.Message.Contains("Cannot release ownership as memory is not owned")) @@ -63,6 +63,7 @@ public class cpp11_std_unique_ptr_runme { } if (!exception_thrown) throw new ApplicationException("Should have thrown 'Cannot release ownership as memory is not owned' error"); + checkCount(1); } checkCount(0); 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 b5ff1fd29..491fa3652 100644 --- a/Examples/test-suite/csharp/li_std_auto_ptr_runme.cs +++ b/Examples/test-suite/csharp/li_std_auto_ptr_runme.cs @@ -53,8 +53,8 @@ public class li_std_auto_ptr_runme { using (Klass kin = new Klass("KlassInput")) { bool exception_thrown = false; + Klass notowned = li_std_auto_ptr.get_not_owned_ptr(kin); try { - Klass notowned = li_std_auto_ptr.get_not_owned_ptr(kin); li_std_auto_ptr.takeKlassAutoPtr(notowned); } catch (ApplicationException e) { if (!e.Message.Contains("Cannot release ownership as memory is not owned")) @@ -63,6 +63,7 @@ public class li_std_auto_ptr_runme { } if (!exception_thrown) throw new ApplicationException("Should have thrown 'Cannot release ownership as memory is not owned' error"); + checkCount(1); } checkCount(0); 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 36a9c03fc..7d6e708ad 100644 --- a/Examples/test-suite/java/cpp11_std_unique_ptr_runme.java +++ b/Examples/test-suite/java/cpp11_std_unique_ptr_runme.java @@ -68,8 +68,8 @@ public class cpp11_std_unique_ptr_runme { { Klass kin = new Klass("KlassInput"); boolean exception_thrown = false; + Klass notowned = cpp11_std_unique_ptr.get_not_owned_ptr(kin); try { - Klass notowned = cpp11_std_unique_ptr.get_not_owned_ptr(kin); cpp11_std_unique_ptr.takeKlassUniquePtr(notowned); } catch (RuntimeException e) { if (!e.getMessage().contains("Cannot release ownership as memory is not owned")) @@ -78,6 +78,7 @@ public class cpp11_std_unique_ptr_runme { } if (!exception_thrown) throw new RuntimeException("Should have thrown 'Cannot release ownership as memory is not owned' error"); + checkCount(1); kin.delete(); checkCount(0); } 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 daec84dc0..58f1ea9c3 100644 --- a/Examples/test-suite/java/li_std_auto_ptr_runme.java +++ b/Examples/test-suite/java/li_std_auto_ptr_runme.java @@ -68,8 +68,8 @@ public class li_std_auto_ptr_runme { { Klass kin = new Klass("KlassInput"); boolean exception_thrown = false; + Klass notowned = li_std_auto_ptr.get_not_owned_ptr(kin); try { - Klass notowned = li_std_auto_ptr.get_not_owned_ptr(kin); li_std_auto_ptr.takeKlassAutoPtr(notowned); } catch (RuntimeException e) { if (!e.getMessage().contains("Cannot release ownership as memory is not owned")) @@ -78,6 +78,7 @@ public class li_std_auto_ptr_runme { } if (!exception_thrown) throw new RuntimeException("Should have thrown 'Cannot release ownership as memory is not owned' error"); + checkCount(1); kin.delete(); checkCount(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 3da93e338..82c93836b 100644 --- a/Examples/test-suite/octave/cpp11_std_unique_ptr_runme.m +++ b/Examples/test-suite/octave/cpp11_std_unique_ptr_runme.m @@ -54,8 +54,8 @@ checkCount(0); kin = Klass("KlassInput"); exception_thrown = false; +notowned = get_not_owned_ptr(kin); try - notowned = get_not_owned_ptr(kin); takeKlassUniquePtr(notowned); catch e if (isempty(strfind(e.message, "cannot release ownership as memory is not owned"))) @@ -66,6 +66,7 @@ end_try_catch if (!exception_thrown) error("Should have thrown 'Cannot release ownership as memory is not owned' error"); endif +checkCount(1); clear kin; checkCount(0); 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 c1e655db5..51898e0bd 100644 --- a/Examples/test-suite/octave/li_std_auto_ptr_runme.m +++ b/Examples/test-suite/octave/li_std_auto_ptr_runme.m @@ -53,8 +53,8 @@ checkCount(0); kin = Klass("KlassInput"); exception_thrown = false; +notowned = get_not_owned_ptr(kin); try - notowned = get_not_owned_ptr(kin); takeKlassAutoPtr(notowned); catch e if (isempty(strfind(e.message, "cannot release ownership as memory is not owned"))) @@ -65,6 +65,7 @@ end_try_catch if (!exception_thrown) error("Should have thrown 'Cannot release ownership as memory is not owned' error"); endif +checkCount(1); clear kin; checkCount(0); 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 a42580aca..0202b0fda 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 => 24; +use Test::More tests => 25; BEGIN { use_ok('cpp11_std_unique_ptr') } require_ok('cpp11_std_unique_ptr'); @@ -41,11 +41,12 @@ sub checkCount { { my $kin = new cpp11_std_unique_ptr::Klass("KlassInput"); + my $notowned = cpp11_std_unique_ptr::get_not_owned_ptr($kin); eval { - my $notowned = cpp11_std_unique_ptr::get_not_owned_ptr($kin); cpp11_std_unique_ptr::takeKlassUniquePtr($notowned); }; like($@, qr/\bcannot release ownership as memory is not owned\b/, "double usage of takeKlassUniquePtr should be an error"); + checkCount(1); undef $kin; checkCount(0); } 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 8a33f4562..232ebf6d0 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 => 24; +use Test::More tests => 25; BEGIN { use_ok('li_std_auto_ptr') } require_ok('li_std_auto_ptr'); @@ -41,11 +41,12 @@ sub checkCount { { my $kin = new li_std_auto_ptr::Klass("KlassInput"); + my $notowned = li_std_auto_ptr::get_not_owned_ptr($kin); eval { - my $notowned = li_std_auto_ptr::get_not_owned_ptr($kin); li_std_auto_ptr::takeKlassAutoPtr($notowned); }; like($@, qr/\bcannot release ownership as memory is not owned\b/, "double usage of takeKlassAutoPtr should be an error"); + checkCount(1); undef $kin; checkCount(0); } 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 d317754b4..ba2a486bc 100644 --- a/Examples/test-suite/python/cpp11_std_unique_ptr_runme.py +++ b/Examples/test-suite/python/cpp11_std_unique_ptr_runme.py @@ -43,13 +43,14 @@ checkCount(0) kin = Klass("KlassInput") exception_thrown = False +notowned = get_not_owned_ptr(kin) try: - notowned = get_not_owned_ptr(kin) takeKlassUniquePtr(notowned) except RuntimeError as e: exception_thrown = True if not exception_thrown: raise RuntimeError("Should have thrown 'Cannot release ownership as memory is not owned' error") +checkCount(1) del kin checkCount(0) 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 c1df7eb76..fe377b6c4 100644 --- a/Examples/test-suite/python/li_std_auto_ptr_runme.py +++ b/Examples/test-suite/python/li_std_auto_ptr_runme.py @@ -43,13 +43,14 @@ checkCount(0) kin = Klass("KlassInput") exception_thrown = False +notowned = get_not_owned_ptr(kin) try: - notowned = get_not_owned_ptr(kin) takeKlassAutoPtr(notowned) except RuntimeError as e: exception_thrown = True if not exception_thrown: raise RuntimeError("Should have thrown 'Cannot release ownership as memory is not owned' error") +checkCount(1) del kin checkCount(0) 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 83bac5f1b..4f2ccb3d9 100644 --- a/Examples/test-suite/ruby/cpp11_std_unique_ptr_runme.rb +++ b/Examples/test-suite/ruby/cpp11_std_unique_ptr_runme.rb @@ -70,8 +70,8 @@ checkCount(0) kin = Cpp11_std_unique_ptr::Klass.new("KlassInput") exception_thrown = false +notowned = Cpp11_std_unique_ptr::get_not_owned_ptr(kin) begin - notowned = Cpp11_std_unique_ptr::get_not_owned_ptr(kin) Cpp11_std_unique_ptr::takeKlassUniquePtr(notowned) rescue RuntimeError => e if (!e.to_s.include? "cannot release ownership as memory is not owned") @@ -82,6 +82,7 @@ end if (!exception_thrown) raise RuntimeError, "Should have thrown 'Cannot release ownership as memory is not owned' error" end +checkCount(1) Cpp11_std_unique_ptr.takeKlassUniquePtr(kin) # Ensure object is deleted (can't rely on GC) checkCount(0) 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 6562d8d84..ffd33ad34 100644 --- a/Examples/test-suite/ruby/li_std_auto_ptr_runme.rb +++ b/Examples/test-suite/ruby/li_std_auto_ptr_runme.rb @@ -70,8 +70,8 @@ checkCount(0) kin = Li_std_auto_ptr::Klass.new("KlassInput") exception_thrown = false +notowned = Li_std_auto_ptr::get_not_owned_ptr(kin) begin - notowned = Li_std_auto_ptr::get_not_owned_ptr(kin) Li_std_auto_ptr::takeKlassAutoPtr(notowned) rescue RuntimeError if (!e.to_s.include? "cannot release ownership as memory is not owned") @@ -82,6 +82,7 @@ end if (!exception_thrown) raise RuntimeError, "Should have thrown 'Cannot release ownership as memory is not owned' error" end +checkCount(1) Li_std_auto_ptr.takeKlassAutoPtr(kin) # Ensure object is deleted (can't rely on GC) checkCount(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 d5864b874..636757d48 100644 --- a/Examples/test-suite/tcl/cpp11_std_unique_ptr_runme.tcl +++ b/Examples/test-suite/tcl/cpp11_std_unique_ptr_runme.tcl @@ -90,8 +90,8 @@ checkCount 0 Klass kin "KlassInput" set exception_thrown 0 +set notowned [get_not_owned_ptr kin] if [ catch { - set notowned [get_not_owned_ptr kin] takeKlassUniquePtr notowned } ] { set exception_thrown 1 @@ -99,6 +99,7 @@ if [ catch { if {!$exception_thrown} { error "Should have thrown 'Cannot release ownership as memory is not owned' error" } +checkCount 1 kin -delete checkCount 0 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 f9ab30ad4..7c32187be 100644 --- a/Examples/test-suite/tcl/li_std_auto_ptr_runme.tcl +++ b/Examples/test-suite/tcl/li_std_auto_ptr_runme.tcl @@ -61,8 +61,8 @@ checkCount 0 Klass kin "KlassInput" set exception_thrown 0 +set notowned [get_not_owned_ptr kin] if [ catch { - set notowned [get_not_owned_ptr kin] takeKlassAutoPtr notowned } ] { set exception_thrown 1 @@ -70,6 +70,7 @@ if [ catch { if {!$exception_thrown} { error "Should have thrown 'Cannot release ownership as memory is not owned' error" } +checkCount 1 kin -delete checkCount 0 From 662b88b605bd686f843296e372a5309555f2e88e Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Wed, 3 Aug 2022 23:07:02 +0100 Subject: [PATCH 604/662] JavaScript Webkit testing and detection changes Add testing for javascriptcoregtk-4.1. Simplify configure detection of JSC, relying only only pkg-config. Add javascriptcoregtk-4.1 tests to GHA. --- .github/workflows/ci.yml | 5 ++ Tools/CI-linux-install.sh | 2 +- configure.ac | 103 +++++++++++++++++--------------------- 3 files changed, 53 insertions(+), 57 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2166d9879..a7c89728e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -97,6 +97,11 @@ jobs: CPPSTD: c++14 - SWIGLANG: javascript ENGINE: jsc + VER: '4.0' + - SWIGLANG: javascript + ENGINE: jsc + VER: '4.1' + os: ubuntu-22.04 - SWIGLANG: lua - SWIGLANG: lua VER: '5.3' diff --git a/Tools/CI-linux-install.sh b/Tools/CI-linux-install.sh index ea811f506..fb3e57de9 100644 --- a/Tools/CI-linux-install.sh +++ b/Tools/CI-linux-install.sh @@ -54,7 +54,7 @@ case "$SWIGLANG" in fi ;; "jsc") - $RETRY sudo apt-get install -qq libjavascriptcoregtk-4.0-dev + $RETRY sudo apt-get install -qq libjavascriptcoregtk-${VER}-dev ;; "v8") $RETRY sudo apt-get install -qq libv8-dev diff --git a/configure.ac b/configure.ac index fd2438dec..242124205 100644 --- a/configure.ac +++ b/configure.ac @@ -1640,69 +1640,60 @@ else fi #---------------------------------------------------------------- - # Look for JavascriptCore (Webkit) settings (JSCOREINCDIR, JSCOREDYNAMICLINKING) + # Look for JavaScriptCore (Webkit) settings #---------------------------------------------------------------- # check for include files - AC_MSG_CHECKING(for JavaScriptCore/JavaScript.h) - AC_ARG_WITH(jscoreinc, [ --with-jscoreinc=path Set location of Javascript include directory], [JSCOREINCDIR="$withval"], [JSCOREINCDIR=]) - - JSCOREVERSION= - - if test -z "$JSCOREINCDIR"; then - JSCOREINCDIR="/usr/include/ /usr/local/include/" - - # Add in default directory for JavaScriptCore headers for Linux and Mac OS X - case $host in - *-*-linux*) - JSCOREINCDIR="/usr/include/webkit-1.0/ /usr/include/webkitgtk-1.0/ /usr/local/include/webkit-1.0/JavaScriptCore/ $JSCOREINCDIR" - ;; - *-*-darwin*) - JSCOREINCDIR="/System/Library/Frameworks/JavaScriptCore.framework/Headers/ $JSCOREINCDIR" - ;; - *) - ;; - esac - fi - - for d in $JSCOREINCDIR ; do - if test -r "$d/JavaScriptCore/JavaScript.h" || test -r "$d/JavaScript.h" ; then - AC_MSG_RESULT($d) - JSCOREINCDIR=$d - JSCOREINC=-I\"$d\" - break - fi - done - - if test "$JSCOREINC" = "" ; then - AC_MSG_RESULT(not found) - fi - + AC_ARG_WITH(jscoreinc, [ --with-jscoreinc=path Set location of JavaScriptCore/Webkit include directory], [JSCOREINCDIR="$withval"], [JSCOREINCDIR=]) # check for JavaScriptCore/Webkit libraries AC_ARG_WITH(jscorelib,[ --with-jscorelib=path Set location of the JavaScriptCore/Webkit library directory],[JSCORELIB="-L$withval"], [JSCORELIB=]) - if test -z "$JSCORELIB" -a -n "$PKG_CONFIG "; then - AC_MSG_CHECKING(for JavaScriptCore/Webkit library) - if $PKG_CONFIG javascriptcoregtk-4.0 2>/dev/null ; then - JSCORELIB=`$PKG_CONFIG --libs javascriptcoregtk-4.0` - JSCOREINC=`$PKG_CONFIG --cflags-only-I javascriptcoregtk-4.0` - JSCOREVERSION=`$PKG_CONFIG --modversion javascriptcoregtk-4.0` - elif $PKG_CONFIG javascriptcoregtk-3.0 2>/dev/null ; then - JSCORELIB=`$PKG_CONFIG --libs javascriptcoregtk-3.0` - JSCOREINC=`$PKG_CONFIG --cflags-only-I javascriptcoregtk-3.0` - JSCOREVERSION=`$PKG_CONFIG --modversion javascriptcoregtk-3.0` - elif $PKG_CONFIG javascriptcoregtk-1.0 2>/dev/null ; then - JSCORELIB=`$PKG_CONFIG --libs javascriptcoregtk-1.0` - JSCOREVERSION=`$PKG_CONFIG --modversion javascriptcoregtk-1.0` - fi - if test -z "$JSCORELIB"; then - AC_MSG_RESULT(not found) - JSCENABLED= - else - AC_MSG_RESULT([$JSCORELIB]) - JSCOREDYNAMICLINKING="$JSCORELIB" - JSCENABLED=1 + JSCOREVERSION= + + if test -z "$JSCOREINCDIR" -a -n "$JSCORELIB"; then + AC_MSG_ERROR([Either both or none of --with-jcoreinc --with-jscorelib should be specified]) + elif test -n "$JSCOREINCDIR" -a -z "$JSCORELIB"; then + AC_MSG_ERROR([Either both or none of --with-jcoreinc --with-jscorelib should be specified]) + elif test -z "$JSCOREINCDIR" -a -z "$JSCORELIB"; then + if test -z "$JSCORELIB" -a -n "$PKG_CONFIG "; then + AC_MSG_CHECKING(for JavaScriptCore/Webkit) + if $PKG_CONFIG javascriptcoregtk-4.1 2>/dev/null ; then + JSCORELIB=`$PKG_CONFIG --libs javascriptcoregtk-4.1` + JSCOREINC=`$PKG_CONFIG --cflags-only-I javascriptcoregtk-4.1` + JSCOREVERSION=`$PKG_CONFIG --modversion javascriptcoregtk-4.1` + elif $PKG_CONFIG javascriptcoregtk-4.0 2>/dev/null ; then + JSCORELIB=`$PKG_CONFIG --libs javascriptcoregtk-4.0` + JSCOREINC=`$PKG_CONFIG --cflags-only-I javascriptcoregtk-4.0` + JSCOREVERSION=`$PKG_CONFIG --modversion javascriptcoregtk-4.0` + elif $PKG_CONFIG javascriptcoregtk-3.0 2>/dev/null ; then + JSCORELIB=`$PKG_CONFIG --libs javascriptcoregtk-3.0` + JSCOREINC=`$PKG_CONFIG --cflags-only-I javascriptcoregtk-3.0` + JSCOREVERSION=`$PKG_CONFIG --modversion javascriptcoregtk-3.0` + elif $PKG_CONFIG javascriptcoregtk-1.0 2>/dev/null ; then + JSCORELIB=`$PKG_CONFIG --libs javascriptcoregtk-1.0` + JSCOREVERSION=`$PKG_CONFIG --modversion javascriptcoregtk-1.0` + fi + if test -z "$JSCORELIB"; then + AC_MSG_RESULT(not found) + JSCENABLED= + else + AC_MSG_RESULT([version $JSCOREVERSION]) + AC_MSG_CHECKING(for JavaScriptCore/Webkit include flags) + AC_MSG_RESULT([$JSCOREINC]) + AC_MSG_CHECKING(for JavaScriptCore/Webkit link flags) + AC_MSG_RESULT([$JSCORELIB]) + JSCOREDYNAMICLINKING="$JSCORELIB" + JSCENABLED=1 + fi fi + else + AC_MSG_CHECKING(for JavaScriptCore/Webkit include flags) + JSCOREINC=-I\"$JSCOREINCDIR\" + AC_MSG_RESULT([$JSCOREINC]) + AC_MSG_CHECKING(for JavaScriptCore/Webkit link flags) + AC_MSG_RESULT([$JSCORELIB]) + JSCOREDYNAMICLINKING="$JSCORELIB" + JSCENABLED=1 fi #---------------------------------------------------------------- From 7a3e79cfc651291b64143a28370e0c12f557ed2c Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Wed, 3 Aug 2022 23:32:22 +0100 Subject: [PATCH 605/662] JSC version display tweaks --- Examples/Makefile.in | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Examples/Makefile.in b/Examples/Makefile.in index a3bda6fd7..fc33ead8b 100644 --- a/Examples/Makefile.in +++ b/Examples/Makefile.in @@ -737,9 +737,9 @@ ifeq (node, $(ENGINE)) endif ifeq (jsc, $(ENGINE)) @if [ "@JSCOREVERSION@" != "" ]; then \ - echo "@JSCOREVERSION@"; \ + echo "JavaScriptCore: @JSCOREVERSION@"; \ else \ - echo "Unknown JavascriptCore version."; \ + echo "Unknown JavaScriptCore version."; \ fi endif ifeq (v8, $(ENGINE)) From d13763892ea996d8c0cba086f28374e787ef1854 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Wed, 3 Aug 2022 23:43:50 +0100 Subject: [PATCH 606/662] GHA: Test newer JavaScriptCore with c++11 --- .github/workflows/ci.yml | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a7c89728e..7dce53ae1 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -98,10 +98,6 @@ jobs: - SWIGLANG: javascript ENGINE: jsc VER: '4.0' - - SWIGLANG: javascript - ENGINE: jsc - VER: '4.1' - os: ubuntu-22.04 - SWIGLANG: lua - SWIGLANG: lua VER: '5.3' @@ -197,6 +193,11 @@ jobs: CPPSTD: c++11 - SWIGLANG: java CPPSTD: c++11 + - SWIGLANG: javascript + ENGINE: jsc + VER: '4.1' + os: ubuntu-22.04 + CPPSTD: c++11 - SWIGLANG: javascript ENGINE: node VER: '14' From 15a9ce36f8aef92d9aaa926b194afd2f8a6e64f4 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Thu, 4 Aug 2022 07:51:20 +0100 Subject: [PATCH 607/662] ISO C comments fix --- Source/CParse/parser.y | 10 +++++----- Source/Preprocessor/expr.c | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Source/CParse/parser.y b/Source/CParse/parser.y index 816264de6..d9c00809b 100644 --- a/Source/CParse/parser.y +++ b/Source/CParse/parser.y @@ -6854,11 +6854,11 @@ exprcompound : expr PLUS expr { } | expr LESSEQUALGREATER expr { $$.val = NewStringf("%s <=> %s", COMPOUND_EXPR_VAL($1), COMPOUND_EXPR_VAL($3)); - // Really `<=>` returns one of `std::strong_ordering`, - // `std::partial_ordering` or `std::weak_ordering`, but we - // fake it by treating the return value as `int`. The main - // thing to do with the return value in this context is to - // compare it with 0, for which `int` does the job. + /* Really `<=>` returns one of `std::strong_ordering`, + * `std::partial_ordering` or `std::weak_ordering`, but we + * fake it by treating the return value as `int`. The main + * thing to do with the return value in this context is to + * compare it with 0, for which `int` does the job. */ $$.type = T_INT; } | expr QUESTIONMARK expr COLON expr %prec QUESTIONMARK { diff --git a/Source/Preprocessor/expr.c b/Source/Preprocessor/expr.c index 557e0e752..2fc1eafeb 100644 --- a/Source/Preprocessor/expr.c +++ b/Source/Preprocessor/expr.c @@ -324,7 +324,7 @@ int Preprocessor_expr(DOH *s, int *error) { /* A number. Reduce EXPR_TOP to an EXPR_VALUE */ char *c = Char(Scanner_text(scan)); if (c[0] == '0' && (c[1] == 'b' || c[1] == 'B')) { - // strtol() doesn't handle binary constants. + /* strtol() doesn't handle binary constants */ stack[sp].value = (long) strtol(c + 2, 0, 2); } else { stack[sp].value = (long) strtol(c, 0, 0); From c16d25d9d668718df7eb4b6a8c41573704d06063 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Thu, 4 Aug 2022 09:03:32 +0100 Subject: [PATCH 608/662] Update docs regarding 'modern' c++ standards testing --- Doc/Manual/Extending.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Doc/Manual/Extending.html b/Doc/Manual/Extending.html index e70f30183..cbb78bef8 100644 --- a/Doc/Manual/Extending.html +++ b/Doc/Manual/Extending.html @@ -3622,7 +3622,7 @@ A target language is given the 'Supported' status when

  • It passes all of the main SWIG test-suite. The main test-suite is defined by the tests in the C_TEST_CASES, CPP_TEST_CASES and MULTI_CPP_TEST_CASES lists in Examples/test-suite/common.mk. - The tests in CPP11_TEST_CASES will also be required in the near future. + All the newer C++ standard tests need to work and are grouped together, such as CPP11_TEST_CASES for C++11. These more 'modern' C++ standards are only tested though if the compiler is detected as supporting the given standard.
  • The test-suite must also include at least twenty wide-ranging runtime tests. From e3cb10487b8a2e379e08550884f2c5ddef69858b Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Thu, 4 Aug 2022 09:03:52 +0100 Subject: [PATCH 609/662] Switch node 17 testing to node 18 --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7dce53ae1..a7bfd5b0b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -93,7 +93,7 @@ jobs: CPPSTD: c++11 - SWIGLANG: javascript ENGINE: node - VER: '17' + VER: '18' CPPSTD: c++14 - SWIGLANG: javascript ENGINE: jsc @@ -270,7 +270,7 @@ jobs: GCC: 11 - SWIGLANG: javascript ENGINE: node - VER: '17' + VER: '18' CPPSTD: c++17 GCC: 11 - SWIGLANG: lua From c496bc9d7b8e90f5c16656bda82a487a202819ec Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Thu, 4 Aug 2022 11:32:24 +1200 Subject: [PATCH 610/662] cpp20_spaceship_operator_runme.py: Check ALIEN value --- Examples/test-suite/python/cpp20_spaceship_operator_runme.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Examples/test-suite/python/cpp20_spaceship_operator_runme.py b/Examples/test-suite/python/cpp20_spaceship_operator_runme.py index 7adce6db2..f13fd48f6 100644 --- a/Examples/test-suite/python/cpp20_spaceship_operator_runme.py +++ b/Examples/test-suite/python/cpp20_spaceship_operator_runme.py @@ -4,7 +4,7 @@ def check_equal(a, b): if a != b: raise RuntimeError("{} is not equal to {}".format(a, b)) -# check_equal(ALIEN, true) +check_equal(ALIEN, 1) check_equal(SPACE, 1) check_equal(COMET, 1) check_equal(cvar.v, 42) From 6bf2138fa0e90c56e3cfe920a7bcede79cc2c677 Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Fri, 5 Aug 2022 10:21:20 +1200 Subject: [PATCH 611/662] [guile] Update status of Guile 1.8.0 support See #1624 --- Doc/Manual/Guile.html | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Doc/Manual/Guile.html b/Doc/Manual/Guile.html index 5a95f3b7d..7f607f804 100644 --- a/Doc/Manual/Guile.html +++ b/Doc/Manual/Guile.html @@ -52,16 +52,16 @@ This section details guile-specific support in SWIG.

    -SWIG is known to work with Guile versions 2.0.x, 2.2.x and 3.0.x. We believe -it still works with 1.8.x, but we're no longer able to easily test this. -Support for version 1.6.x has been dropped. The last version of SWIG that still -works with Guile version 1.6.x is SWIG 2.0.9. +SWIG is known to work with Guile versions 2.0.x, 2.2.x and 3.0.x (these are +all tested via CI). SWIG probably still works with Guile 1.8.x but we're no +longer able to regularly test this either in CI or by hand. Support for Guile +1.6.x has been dropped (SWIG 2.0.9 was the last version of SWIG to support it).

    Note that starting with guile 2.0, the guile sources can be compiled for improved performance. This is currently not tested with swig so your mileage may vary. To be safe set environment variable -GUILE_AUTO_COMPILE to 0 when using swig generated guile code. +GUILE_AUTO_COMPILE to 0 when using swig generated guile code.

    26.2 Meaning of "Module"

    From 5a379d317bee504f0e33ab1e9fb345a37bb7676a Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Fri, 5 Aug 2022 19:07:48 +0100 Subject: [PATCH 612/662] Add Tcl support for std::unique_ptr and std::auto_ptr Equivalent to C#/Java implementations. --- CHANGES.current | 4 + Examples/test-suite/cpp11_std_unique_ptr.i | 2 +- .../d/cpp11_std_unique_ptr_runme.1.d | 101 ++++++++++++++++++ .../d/cpp11_std_unique_ptr_runme.2.d | 101 ++++++++++++++++++ .../test-suite/d/li_std_auto_ptr_runme.1.d | 101 ++++++++++++++++++ .../test-suite/d/li_std_auto_ptr_runme.2.d | 101 ++++++++++++++++++ Examples/test-suite/li_std_auto_ptr.i | 2 +- Lib/d/dclassgen.swg | 32 +++++- Lib/d/std_auto_ptr.i | 40 +++++++ Lib/d/std_unique_ptr.i | 40 +++++++ 10 files changed, 521 insertions(+), 3 deletions(-) create mode 100644 Examples/test-suite/d/cpp11_std_unique_ptr_runme.1.d create mode 100644 Examples/test-suite/d/cpp11_std_unique_ptr_runme.2.d create mode 100644 Examples/test-suite/d/li_std_auto_ptr_runme.1.d create mode 100644 Examples/test-suite/d/li_std_auto_ptr_runme.2.d create mode 100644 Lib/d/std_auto_ptr.i create mode 100644 Lib/d/std_unique_ptr.i diff --git a/CHANGES.current b/CHANGES.current index c50691bac..2fed37737 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-05: wsfulton + [D] Add support for std::unique_ptr in std_unique_ptr.i. + Add support for std::auto_ptr in std_auto_ptr.i. + 2022-08-03: wsfulton [Javascript] 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/cpp11_std_unique_ptr.i b/Examples/test-suite/cpp11_std_unique_ptr.i index 9475890d8..49c85d6aa 100644 --- a/Examples/test-suite/cpp11_std_unique_ptr.i +++ b/Examples/test-suite/cpp11_std_unique_ptr.i @@ -1,6 +1,6 @@ %module cpp11_std_unique_ptr -#if defined(SWIGCSHARP) || defined(SWIGJAVA) || defined(SWIGPYTHON) || defined(SWIGRUBY) || defined(SWIGPERL) || defined(SWIGTCL) || defined(SWIGOCTAVE) || defined(SWIGJAVASCRIPT) +#if defined(SWIGCSHARP) || defined(SWIGJAVA) || defined(SWIGPYTHON) || defined(SWIGRUBY) || defined(SWIGPERL) || defined(SWIGTCL) || defined(SWIGOCTAVE) || defined(SWIGJAVASCRIPT) || defined(SWIGD) %include "std_string.i" %include "std_unique_ptr.i" 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 new file mode 100644 index 000000000..7730f255f --- /dev/null +++ b/Examples/test-suite/d/cpp11_std_unique_ptr_runme.1.d @@ -0,0 +1,101 @@ +module cpp11_std_unique_ptr_runme; + +import cpp11_std_unique_ptr.cpp11_std_unique_ptr; +import cpp11_std_unique_ptr.Klass; +import cpp11_std_unique_ptr.KlassInheritance; +import std.conv; +import std.algorithm; + +void checkCount(int expected_count) { + int actual_count = Klass.getTotal_count(); + if (actual_count != expected_count) + throw new Exception("Counts incorrect, expected:" ~ to!string(expected_count) ~ " actual:" ~ to!string(actual_count)); +} + +void main() { + // unique_ptr as input + { + scope Klass kin = new Klass("KlassInput"); + checkCount(1); + string s = takeKlassUniquePtr(kin); + checkCount(0); + if (s != "KlassInput") + throw new Exception("Incorrect string: " ~ s); + if (!is_nullptr(kin)) + throw new Exception("is_nullptr failed"); + } // dispose should not fail, even though already deleted + checkCount(0); + + { + scope Klass kin = new Klass("KlassInput"); + checkCount(1); + string s = takeKlassUniquePtr(kin); + checkCount(0); + if (s != "KlassInput") + throw new Exception("Incorrect string: " ~ s); + if (!is_nullptr(kin)) + throw new Exception("is_nullptr failed"); + bool exception_thrown = false; + try { + takeKlassUniquePtr(kin); + } 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("double usage of takeKlassUniquePtr should have been an error"); + } // dispose should not fail, even though already deleted + checkCount(0); + + { + scope Klass kin = new Klass("KlassInput"); + bool exception_thrown = false; + Klass notowned = get_not_owned_ptr(kin); + try { + takeKlassUniquePtr(notowned); + } 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"); + checkCount(1); + } + checkCount(0); + + /* + { + scope KlassInheritance kini = new KlassInheritance("KlassInheritanceInput"); + checkCount(1); + string s = takeKlassUniquePtr(kini); + checkCount(0); + if (s != "KlassInheritanceInput") + throw new Exception("Incorrect string: " ~ s); + if (!is_nullptr(kini)) + throw new Exception("is_nullptr failed"); + } // dispose should not fail, even though already deleted + checkCount(0); + */ + + // unique_ptr as output + Klass k1 = makeKlassUniquePtr("first"); + if (k1.getLabel() != "first") + throw new Exception("wrong object label"); + + Klass k2 = makeKlassUniquePtr("second"); + if (Klass.getTotal_count() != 2) + throw new Exception("number of objects should be 2"); + + k1.dispose(); + if (Klass.getTotal_count() != 1) + throw new Exception("number of objects should be 1"); + + if (k2.getLabel() != "second") + throw new Exception("wrong object label"); + + k2.dispose(); + if (Klass.getTotal_count() != 0) + throw new Exception("no objects should be left"); +} 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 new file mode 100644 index 000000000..7730f255f --- /dev/null +++ b/Examples/test-suite/d/cpp11_std_unique_ptr_runme.2.d @@ -0,0 +1,101 @@ +module cpp11_std_unique_ptr_runme; + +import cpp11_std_unique_ptr.cpp11_std_unique_ptr; +import cpp11_std_unique_ptr.Klass; +import cpp11_std_unique_ptr.KlassInheritance; +import std.conv; +import std.algorithm; + +void checkCount(int expected_count) { + int actual_count = Klass.getTotal_count(); + if (actual_count != expected_count) + throw new Exception("Counts incorrect, expected:" ~ to!string(expected_count) ~ " actual:" ~ to!string(actual_count)); +} + +void main() { + // unique_ptr as input + { + scope Klass kin = new Klass("KlassInput"); + checkCount(1); + string s = takeKlassUniquePtr(kin); + checkCount(0); + if (s != "KlassInput") + throw new Exception("Incorrect string: " ~ s); + if (!is_nullptr(kin)) + throw new Exception("is_nullptr failed"); + } // dispose should not fail, even though already deleted + checkCount(0); + + { + scope Klass kin = new Klass("KlassInput"); + checkCount(1); + string s = takeKlassUniquePtr(kin); + checkCount(0); + if (s != "KlassInput") + throw new Exception("Incorrect string: " ~ s); + if (!is_nullptr(kin)) + throw new Exception("is_nullptr failed"); + bool exception_thrown = false; + try { + takeKlassUniquePtr(kin); + } 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("double usage of takeKlassUniquePtr should have been an error"); + } // dispose should not fail, even though already deleted + checkCount(0); + + { + scope Klass kin = new Klass("KlassInput"); + bool exception_thrown = false; + Klass notowned = get_not_owned_ptr(kin); + try { + takeKlassUniquePtr(notowned); + } 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"); + checkCount(1); + } + checkCount(0); + + /* + { + scope KlassInheritance kini = new KlassInheritance("KlassInheritanceInput"); + checkCount(1); + string s = takeKlassUniquePtr(kini); + checkCount(0); + if (s != "KlassInheritanceInput") + throw new Exception("Incorrect string: " ~ s); + if (!is_nullptr(kini)) + throw new Exception("is_nullptr failed"); + } // dispose should not fail, even though already deleted + checkCount(0); + */ + + // unique_ptr as output + Klass k1 = makeKlassUniquePtr("first"); + if (k1.getLabel() != "first") + throw new Exception("wrong object label"); + + Klass k2 = makeKlassUniquePtr("second"); + if (Klass.getTotal_count() != 2) + throw new Exception("number of objects should be 2"); + + k1.dispose(); + if (Klass.getTotal_count() != 1) + throw new Exception("number of objects should be 1"); + + if (k2.getLabel() != "second") + throw new Exception("wrong object label"); + + k2.dispose(); + if (Klass.getTotal_count() != 0) + throw new Exception("no objects should be left"); +} 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 new file mode 100644 index 000000000..76c81ffc8 --- /dev/null +++ b/Examples/test-suite/d/li_std_auto_ptr_runme.1.d @@ -0,0 +1,101 @@ +module li_std_auto_ptr_runme; + +import li_std_auto_ptr.li_std_auto_ptr; +import li_std_auto_ptr.Klass; +import li_std_auto_ptr.KlassInheritance; +import std.conv; +import std.algorithm; + +void checkCount(int expected_count) { + int actual_count = Klass.getTotal_count(); + if (actual_count != expected_count) + throw new Exception("Counts incorrect, expected:" ~ to!string(expected_count) ~ " actual:" ~ to!string(actual_count)); +} + +void main() { + // auto_ptr as input + { + scope Klass kin = new Klass("KlassInput"); + checkCount(1); + string s = takeKlassAutoPtr(kin); + checkCount(0); + if (s != "KlassInput") + throw new Exception("Incorrect string: " ~ s); + if (!is_nullptr(kin)) + throw new Exception("is_nullptr failed"); + } // dispose should not fail, even though already deleted + checkCount(0); + + { + scope Klass kin = new Klass("KlassInput"); + checkCount(1); + string s = takeKlassAutoPtr(kin); + checkCount(0); + if (s != "KlassInput") + throw new Exception("Incorrect string: " ~ s); + if (!is_nullptr(kin)) + throw new Exception("is_nullptr failed"); + bool exception_thrown = false; + try { + takeKlassAutoPtr(kin); + } 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("double usage of takeKlassAutoPtr should have been an error"); + } // dispose should not fail, even though already deleted + checkCount(0); + + { + scope Klass kin = new Klass("KlassInput"); + bool exception_thrown = false; + Klass notowned = get_not_owned_ptr(kin); + try { + takeKlassAutoPtr(notowned); + } 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"); + checkCount(1); + } + checkCount(0); + + /* + { + scope KlassInheritance kini = new KlassInheritance("KlassInheritanceInput"); + checkCount(1); + string s = takeKlassAutoPtr(kini); + checkCount(0); + if (s != "KlassInheritanceInput") + throw new Exception("Incorrect string: " ~ s); + if (!is_nullptr(kini)) + throw new Exception("is_nullptr failed"); + } // dispose should not fail, even though already deleted + checkCount(0); + */ + + // auto_ptr as output + Klass k1 = makeKlassAutoPtr("first"); + if (k1.getLabel() != "first") + throw new Exception("wrong object label"); + + Klass k2 = makeKlassAutoPtr("second"); + if (Klass.getTotal_count() != 2) + throw new Exception("number of objects should be 2"); + + k1.dispose(); + if (Klass.getTotal_count() != 1) + throw new Exception("number of objects should be 1"); + + if (k2.getLabel() != "second") + throw new Exception("wrong object label"); + + k2.dispose(); + if (Klass.getTotal_count() != 0) + throw new Exception("no objects should be left"); +} 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 new file mode 100644 index 000000000..76c81ffc8 --- /dev/null +++ b/Examples/test-suite/d/li_std_auto_ptr_runme.2.d @@ -0,0 +1,101 @@ +module li_std_auto_ptr_runme; + +import li_std_auto_ptr.li_std_auto_ptr; +import li_std_auto_ptr.Klass; +import li_std_auto_ptr.KlassInheritance; +import std.conv; +import std.algorithm; + +void checkCount(int expected_count) { + int actual_count = Klass.getTotal_count(); + if (actual_count != expected_count) + throw new Exception("Counts incorrect, expected:" ~ to!string(expected_count) ~ " actual:" ~ to!string(actual_count)); +} + +void main() { + // auto_ptr as input + { + scope Klass kin = new Klass("KlassInput"); + checkCount(1); + string s = takeKlassAutoPtr(kin); + checkCount(0); + if (s != "KlassInput") + throw new Exception("Incorrect string: " ~ s); + if (!is_nullptr(kin)) + throw new Exception("is_nullptr failed"); + } // dispose should not fail, even though already deleted + checkCount(0); + + { + scope Klass kin = new Klass("KlassInput"); + checkCount(1); + string s = takeKlassAutoPtr(kin); + checkCount(0); + if (s != "KlassInput") + throw new Exception("Incorrect string: " ~ s); + if (!is_nullptr(kin)) + throw new Exception("is_nullptr failed"); + bool exception_thrown = false; + try { + takeKlassAutoPtr(kin); + } 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("double usage of takeKlassAutoPtr should have been an error"); + } // dispose should not fail, even though already deleted + checkCount(0); + + { + scope Klass kin = new Klass("KlassInput"); + bool exception_thrown = false; + Klass notowned = get_not_owned_ptr(kin); + try { + takeKlassAutoPtr(notowned); + } 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"); + checkCount(1); + } + checkCount(0); + + /* + { + scope KlassInheritance kini = new KlassInheritance("KlassInheritanceInput"); + checkCount(1); + string s = takeKlassAutoPtr(kini); + checkCount(0); + if (s != "KlassInheritanceInput") + throw new Exception("Incorrect string: " ~ s); + if (!is_nullptr(kini)) + throw new Exception("is_nullptr failed"); + } // dispose should not fail, even though already deleted + checkCount(0); + */ + + // auto_ptr as output + Klass k1 = makeKlassAutoPtr("first"); + if (k1.getLabel() != "first") + throw new Exception("wrong object label"); + + Klass k2 = makeKlassAutoPtr("second"); + if (Klass.getTotal_count() != 2) + throw new Exception("number of objects should be 2"); + + k1.dispose(); + if (Klass.getTotal_count() != 1) + throw new Exception("number of objects should be 1"); + + if (k2.getLabel() != "second") + throw new Exception("wrong object label"); + + k2.dispose(); + if (Klass.getTotal_count() != 0) + throw new Exception("no objects should be left"); +} diff --git a/Examples/test-suite/li_std_auto_ptr.i b/Examples/test-suite/li_std_auto_ptr.i index 06591a971..afa4782c3 100644 --- a/Examples/test-suite/li_std_auto_ptr.i +++ b/Examples/test-suite/li_std_auto_ptr.i @@ -12,7 +12,7 @@ #endif %} -#if defined(SWIGCSHARP) || defined(SWIGJAVA) || defined(SWIGPYTHON) || defined(SWIGRUBY) || defined(SWIGPERL) || defined(SWIGTCL) || defined(SWIGOCTAVE) || defined(SWIGJAVASCRIPT) +#if defined(SWIGCSHARP) || defined(SWIGJAVA) || defined(SWIGPYTHON) || defined(SWIGRUBY) || defined(SWIGPERL) || defined(SWIGTCL) || defined(SWIGOCTAVE) || defined(SWIGJAVASCRIPT) || defined(SWIGD) %include "std_string.i" %include "std_auto_ptr.i" diff --git a/Lib/d/dclassgen.swg b/Lib/d/dclassgen.swg index 84fa03a0b..e4ff8d5f5 100644 --- a/Lib/d/dclassgen.swg +++ b/Lib/d/dclassgen.swg @@ -76,6 +76,19 @@ public static void* swigGetCPtr(typeof(this) obj) { return (obj is null) ? null : obj.swigCPtr; } +public static void* swigRelease(typeof(this) obj) { + if (obj !is null) { + if (!obj.swigCMemOwn) + throw new Exception("Cannot release ownership as memory is not owned"); + void* ptr = obj.swigCPtr; + obj.swigCMemOwn = false; + obj.dispose(); + return ptr; + } else { + return null; + } +} + mixin $imdmodule.SwigOperatorDefinitions; %} @@ -92,6 +105,19 @@ public static void* swigGetCPtr(typeof(this) obj) { return (obj is null) ? null : obj.swigCPtr; } +public static void* swigRelease(typeof(this) obj) { + if (obj !is null) { + if (!obj.swigCMemOwn) + throw new Exception("Cannot release ownership as memory is not owned"); + void* ptr = obj.swigCPtr; + obj.swigCMemOwn = false; + obj.dispose(); + return ptr; + } else { + return null; + } +} + mixin $imdmodule.SwigOperatorDefinitions; %} @@ -100,7 +126,7 @@ mixin $imdmodule.SwigOperatorDefinitions; * Type wrapper classes. */ -%typemap(dbody) SWIGTYPE *, SWIGTYPE &, SWIGTYPE [] %{ +%typemap(dbody) SWIGTYPE *, SWIGTYPE &, SWIGTYPE &&, SWIGTYPE [] %{ private void* swigCPtr; public this(void* cObject, bool futureUse) { @@ -115,6 +141,10 @@ public static void* swigGetCPtr(typeof(this) obj) { return (obj is null) ? null : obj.swigCPtr; } +public static void* swigRelease(typeof(this) obj) { + return (obj is null) ? null : obj.swigCPtr; +} + mixin $imdmodule.SwigOperatorDefinitions; %} diff --git a/Lib/d/std_auto_ptr.i b/Lib/d/std_auto_ptr.i new file mode 100644 index 000000000..e04a18061 --- /dev/null +++ b/Lib/d/std_auto_ptr.i @@ -0,0 +1,40 @@ +/* ----------------------------------------------------------------------------- + * std_auto_ptr.i + * + * SWIG library file for handling std::auto_ptr. + * Memory ownership is passed from the std::auto_ptr C++ layer to the proxy + * class when returning a std::auto_ptr from a function. + * Memory ownership is passed from the proxy class to the std::auto_ptr in the + * C++ layer when passed as a parameter to a wrapped function. + * ----------------------------------------------------------------------------- */ + +%define %auto_ptr(TYPE) +%typemap (ctype) std::auto_ptr< TYPE > "void *" +%typemap (imtype) std::auto_ptr< TYPE > "void*" +%typemap (dtype) std::auto_ptr< TYPE > "$typemap(dtype, TYPE)" + +%typemap(in) std::auto_ptr< TYPE > +%{ $1.reset((TYPE *)$input); %} + +%typemap(din, + nativepointer="cast(void*)$dinput" +) std::auto_ptr< TYPE > "$typemap(dtype, TYPE).swigRelease($dinput)" + +%typemap (out) std::auto_ptr< TYPE > %{ + $result = (void *)$1.release(); +%} + +%typemap(dout, excode=SWIGEXCODE, + nativepointer="{\n auto ret = cast($dtype)$imcall;$excode\n return ret;\n}" +) std::auto_ptr< TYPE > { + void* cPtr = $imcall; + $typemap(dtype, TYPE) ret = (cPtr is null) ? null : new $typemap(dtype, TYPE)(cPtr, true);$excode + return ret; +} + +%template() std::auto_ptr< TYPE >; +%enddef + +namespace std { + template class auto_ptr {}; +} diff --git a/Lib/d/std_unique_ptr.i b/Lib/d/std_unique_ptr.i new file mode 100644 index 000000000..8a06ba066 --- /dev/null +++ b/Lib/d/std_unique_ptr.i @@ -0,0 +1,40 @@ +/* ----------------------------------------------------------------------------- + * std_unique_ptr.i + * + * SWIG library file for handling std::unique_ptr. + * Memory ownership is passed from the std::unique_ptr C++ layer to the proxy + * class when returning a std::unique_ptr from a function. + * Memory ownership is passed from the proxy class to the std::unique_ptr in the + * C++ layer when passed as a parameter to a wrapped function. + * ----------------------------------------------------------------------------- */ + +%define %unique_ptr(TYPE) +%typemap (ctype) std::unique_ptr< TYPE > "void *" +%typemap (imtype) std::unique_ptr< TYPE > "void*" +%typemap (dtype) std::unique_ptr< TYPE > "$typemap(dtype, TYPE)" + +%typemap(in) std::unique_ptr< TYPE > +%{ $1.reset((TYPE *)$input); %} + +%typemap(din, + nativepointer="cast(void*)$dinput" +) std::unique_ptr< TYPE > "$typemap(dtype, TYPE).swigRelease($dinput)" + +%typemap (out) std::unique_ptr< TYPE > %{ + $result = (void *)$1.release(); +%} + +%typemap(dout, excode=SWIGEXCODE, + nativepointer="{\n auto ret = cast($dtype)$imcall;$excode\n return ret;\n}" +) std::unique_ptr< TYPE > { + void* cPtr = $imcall; + $typemap(dtype, TYPE) ret = (cPtr is null) ? null : new $typemap(dtype, TYPE)(cPtr, true);$excode + return ret; +} + +%template() std::unique_ptr< TYPE >; +%enddef + +namespace std { + template class unique_ptr {}; +} From 910fd1e3cf973888fb3e0e84646edff7410657ab Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Fri, 5 Aug 2022 19:36:54 +0100 Subject: [PATCH 613/662] [D] Fix occasional undefined behaviour with inheritance hierarchies Particularly when using virtual inheritance as the pointers weren't correctly upcast from derived class to base class when stored in the base's proxy class. Fixes commented out test code in cpp11_std_unique_ptr_runme and li_std_auto_ptr_runme D tests. --- CHANGES.current | 5 +++++ Examples/test-suite/cpp11_std_unique_ptr.i | 13 ++++++++++++- .../test-suite/d/cpp11_std_unique_ptr_runme.1.d | 12 ++++++++++-- .../test-suite/d/cpp11_std_unique_ptr_runme.2.d | 12 ++++++++++-- Examples/test-suite/d/li_std_auto_ptr_runme.1.d | 12 ++++++++++-- Examples/test-suite/d/li_std_auto_ptr_runme.2.d | 13 +++++++++++-- Examples/test-suite/li_std_auto_ptr.i | 16 ++++++++++++++-- Source/Modules/d.cxx | 2 +- 8 files changed, 73 insertions(+), 12 deletions(-) diff --git a/CHANGES.current b/CHANGES.current index 2fed37737..bb16fef2d 100644 --- a/CHANGES.current +++ b/CHANGES.current @@ -7,6 +7,11 @@ the issue number to the end of the URL: https://github.com/swig/swig/issues/ Version 4.1.0 (in progress) =========================== +2022-08-05: wsfulton + [D] Fix occasional undefined behaviour with inheritance hierarchies, particularly + when using virtual inheritance as the pointers weren't correctly upcast from derived + class to base class when stored in the base's proxy class. + 2022-08-05: wsfulton [D] 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/cpp11_std_unique_ptr.i b/Examples/test-suite/cpp11_std_unique_ptr.i index 49c85d6aa..0549a7b45 100644 --- a/Examples/test-suite/cpp11_std_unique_ptr.i +++ b/Examples/test-suite/cpp11_std_unique_ptr.i @@ -10,6 +10,7 @@ %inline %{ #include #include +//#include #include "swig_examples_lock.h" class Klass { @@ -53,8 +54,18 @@ struct KlassInheritance : virtual Klass { } }; +std::string useKlassRawPtr(Klass* k) { +// std::cout << "useKlassRawPtr " << std::hex << (Klass*)k << std::endl; + std::string s(k->getLabel()); +// std::cout << "useKlassRawPtr string: " << s << std::endl; + return s; +} + std::string takeKlassUniquePtr(std::unique_ptr k) { - return std::string(k->getLabel()); +// std::cout << "takeKlassUniquePtr " << std::hex << (Klass*)k.get() << std::endl; + std::string s(k->getLabel()); +// std::cout << "takeKlassUniquePtr string: " << s << std::endl; + return s; } bool is_nullptr(Klass *p) { 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 7730f255f..5aee10727 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 @@ -13,6 +13,16 @@ void checkCount(int expected_count) { } void main() { + // Test raw pointer handling involving virtual inheritance + { + scope KlassInheritance kini = new KlassInheritance("KlassInheritanceInput"); + checkCount(1); + string s = useKlassRawPtr(kini); + if (s != "KlassInheritanceInput") + throw new Exception("Incorrect string: " ~ s); + } + checkCount(0); + // unique_ptr as input { scope Klass kin = new Klass("KlassInput"); @@ -65,7 +75,6 @@ void main() { } checkCount(0); - /* { scope KlassInheritance kini = new KlassInheritance("KlassInheritanceInput"); checkCount(1); @@ -77,7 +86,6 @@ void main() { throw new Exception("is_nullptr failed"); } // dispose should not fail, even though already deleted checkCount(0); - */ // unique_ptr as output Klass k1 = makeKlassUniquePtr("first"); 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 7730f255f..5aee10727 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 @@ -13,6 +13,16 @@ void checkCount(int expected_count) { } void main() { + // Test raw pointer handling involving virtual inheritance + { + scope KlassInheritance kini = new KlassInheritance("KlassInheritanceInput"); + checkCount(1); + string s = useKlassRawPtr(kini); + if (s != "KlassInheritanceInput") + throw new Exception("Incorrect string: " ~ s); + } + checkCount(0); + // unique_ptr as input { scope Klass kin = new Klass("KlassInput"); @@ -65,7 +75,6 @@ void main() { } checkCount(0); - /* { scope KlassInheritance kini = new KlassInheritance("KlassInheritanceInput"); checkCount(1); @@ -77,7 +86,6 @@ void main() { throw new Exception("is_nullptr failed"); } // dispose should not fail, even though already deleted checkCount(0); - */ // unique_ptr as output Klass k1 = makeKlassUniquePtr("first"); 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 76c81ffc8..3b51ba3ce 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 @@ -13,6 +13,16 @@ void checkCount(int expected_count) { } void main() { + // Test raw pointer handling involving virtual inheritance + { + scope KlassInheritance kini = new KlassInheritance("KlassInheritanceInput"); + checkCount(1); + string s = useKlassRawPtr(kini); + if (s != "KlassInheritanceInput") + throw new Exception("Incorrect string: " ~ s); + } + checkCount(0); + // auto_ptr as input { scope Klass kin = new Klass("KlassInput"); @@ -65,7 +75,6 @@ void main() { } checkCount(0); - /* { scope KlassInheritance kini = new KlassInheritance("KlassInheritanceInput"); checkCount(1); @@ -77,7 +86,6 @@ void main() { throw new Exception("is_nullptr failed"); } // dispose should not fail, even though already deleted checkCount(0); - */ // auto_ptr as output Klass k1 = makeKlassAutoPtr("first"); 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 76c81ffc8..38efa3d7d 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 @@ -13,6 +13,17 @@ void checkCount(int expected_count) { } void main() { + // Test raw pointer handling involving virtual inheritance + { + scope KlassInheritance kini = new KlassInheritance("KlassInheritanceInput"); + checkCount(1); + string s = useKlassRawPtr(kini); + checkCount(1); + if (s != "KlassInheritanceInput") + throw new Exception("Incorrect string: " ~ s); + } + checkCount(0); + // auto_ptr as input { scope Klass kin = new Klass("KlassInput"); @@ -65,7 +76,6 @@ void main() { } checkCount(0); - /* { scope KlassInheritance kini = new KlassInheritance("KlassInheritanceInput"); checkCount(1); @@ -77,7 +87,6 @@ void main() { throw new Exception("is_nullptr failed"); } // dispose should not fail, even though already deleted checkCount(0); - */ // auto_ptr as output Klass k1 = makeKlassAutoPtr("first"); diff --git a/Examples/test-suite/li_std_auto_ptr.i b/Examples/test-suite/li_std_auto_ptr.i index afa4782c3..5f3b7724f 100644 --- a/Examples/test-suite/li_std_auto_ptr.i +++ b/Examples/test-suite/li_std_auto_ptr.i @@ -15,6 +15,7 @@ #if defined(SWIGCSHARP) || defined(SWIGJAVA) || defined(SWIGPYTHON) || defined(SWIGRUBY) || defined(SWIGPERL) || defined(SWIGTCL) || defined(SWIGOCTAVE) || defined(SWIGJAVASCRIPT) || defined(SWIGD) %include "std_string.i" +//#include %include "std_auto_ptr.i" %auto_ptr(Klass) @@ -100,10 +101,21 @@ struct KlassInheritance : virtual Klass { } }; -std::string takeKlassAutoPtr(std::auto_ptr k) { - return std::string(k->getLabel()); +std::string useKlassRawPtr(Klass* k) { +// std::cout << "useKlassRawPtr " << std::hex << (Klass*)k << std::endl; + std::string s(k->getLabel()); +// std::cout << "useKlassRawPtr string: " << s << std::endl; + return s; } +std::string takeKlassAutoPtr(std::auto_ptr k) { +// std::cout << "takeKlassAutoPtr " << std::hex << (Klass*)k.get() << std::endl; + std::string s(k->getLabel()); +// std::cout << "takeKlassAutoPtr string: " << s << std::endl; + return s; +} + + bool is_nullptr(Klass *p) { return p == 0; } diff --git a/Source/Modules/d.cxx b/Source/Modules/d.cxx index ff32dbf0b..c1f68da07 100644 --- a/Source/Modules/d.cxx +++ b/Source/Modules/d.cxx @@ -3402,7 +3402,7 @@ private: } else { Printv(upcasts_code, "SWIGEXPORT ", baseclassname, " * ", upcast_wrapper_name, - "(", baseclassname, " *objectRef) {\n", + "(", classname, " *objectRef) {\n", " return (", baseclassname, " *)objectRef;\n" "}\n", "\n", NIL); From d4b1152d4b0a1be78e3ac7cab3d640f610ec2f39 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Fri, 5 Aug 2022 20:36:29 +0100 Subject: [PATCH 614/662] Add raw pointer handling test for virtual inheritance This is a test added for D in previous commit, now expanded to all target languages. Tidy up counting object instances. --- .../csharp/cpp11_std_unique_ptr_runme.cs | 52 ++++++------------- .../csharp/li_std_auto_ptr_runme.cs | 50 ++++++------------ .../d/cpp11_std_unique_ptr_runme.1.d | 9 ++-- .../d/cpp11_std_unique_ptr_runme.2.d | 9 ++-- .../test-suite/d/li_std_auto_ptr_runme.1.d | 9 ++-- .../test-suite/d/li_std_auto_ptr_runme.2.d | 10 ++-- .../java/cpp11_std_unique_ptr_runme.java | 46 ++++++---------- .../java/li_std_auto_ptr_runme.java | 46 ++++++---------- .../javascript/cpp11_std_unique_ptr_runme.js | 25 ++++++--- .../javascript/li_std_auto_ptr_runme.js | 25 ++++++--- .../octave/cpp11_std_unique_ptr_runme.m | 22 ++++---- .../test-suite/octave/li_std_auto_ptr_runme.m | 23 ++++---- .../perl5/cpp11_std_unique_ptr_runme.pl | 19 +++++-- .../test-suite/perl5/li_std_auto_ptr_runme.pl | 19 +++++-- .../python/cpp11_std_unique_ptr_runme.py | 19 ++++--- .../python/li_std_auto_ptr_runme.py | 19 ++++--- .../ruby/cpp11_std_unique_ptr_runme.rb | 10 ++++ .../test-suite/ruby/li_std_auto_ptr_runme.rb | 10 ++++ .../tcl/cpp11_std_unique_ptr_runme.tcl | 19 +++---- .../test-suite/tcl/li_std_auto_ptr_runme.tcl | 19 +++---- 20 files changed, 236 insertions(+), 224 deletions(-) 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 9382cb83a..b24b5c204 100644 --- a/Examples/test-suite/csharp/cpp11_std_unique_ptr_runme.cs +++ b/Examples/test-suite/csharp/cpp11_std_unique_ptr_runme.cs @@ -18,6 +18,15 @@ public class cpp11_std_unique_ptr_runme { public static void Main() { + // Test raw pointer handling involving virtual inheritance + using (KlassInheritance kini = new KlassInheritance("KlassInheritanceInput")) { + checkCount(1); + string s = cpp11_std_unique_ptr.useKlassRawPtr(kini); + if (s != "KlassInheritanceInput") + throw new ApplicationException("Incorrect string: " + s); + } + checkCount(0); + // unique_ptr as input using (Klass kin = new Klass("KlassInput")) { checkCount(1); @@ -63,7 +72,7 @@ public class cpp11_std_unique_ptr_runme { } if (!exception_thrown) throw new ApplicationException("Should have thrown 'Cannot release ownership as memory is not owned' error"); - checkCount(1); + checkCount(1); } checkCount(0); @@ -84,49 +93,22 @@ public class cpp11_std_unique_ptr_runme { throw new Exception("wrong object label"); Klass k2 = cpp11_std_unique_ptr.makeKlassUniquePtr("second"); - if (Klass.getTotal_count() != 2) - throw new Exception("number of objects should be 2"); + checkCount(2); using (Klass k3 = cpp11_std_unique_ptr.makeKlassUniquePtr("second")) { - if (Klass.getTotal_count() != 3) - throw new Exception("number of objects should be 3"); + checkCount(3); } - if (Klass.getTotal_count() != 2) - throw new Exception("number of objects should be 2"); + checkCount(2); + k1.Dispose(); k1 = null; - { - int countdown = 500; - int expectedCount = 1; - while (true) { - WaitForGC(); - if (--countdown == 0) - break; - if (Klass.getTotal_count() == expectedCount) - break; - }; - int actualCount = Klass.getTotal_count(); - if (actualCount != expectedCount) - Console.Error.WriteLine("Expected count: " + expectedCount + " Actual count: " + actualCount); // Finalizers are not guaranteed to be run and sometimes they just don't - } + checkCount(1); if (k2.getLabel() != "second") throw new Exception("wrong object label"); + k2.Dispose(); k2 = null; - { - int countdown = 500; - int expectedCount = 0; - while (true) { - WaitForGC(); - if (--countdown == 0) - break; - if (Klass.getTotal_count() == expectedCount) - break; - } - int actualCount = Klass.getTotal_count(); - if (actualCount != expectedCount) - Console.Error.WriteLine("Expected count: " + expectedCount + " Actual count: " + actualCount); // Finalizers are not guaranteed to be run and sometimes they just don't - } + checkCount(0); } } 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 491fa3652..ebbb23c69 100644 --- a/Examples/test-suite/csharp/li_std_auto_ptr_runme.cs +++ b/Examples/test-suite/csharp/li_std_auto_ptr_runme.cs @@ -18,6 +18,15 @@ public class li_std_auto_ptr_runme { public static void Main() { + // Test raw pointer handling involving virtual inheritance + using (KlassInheritance kini = new KlassInheritance("KlassInheritanceInput")) { + checkCount(1); + string s = li_std_auto_ptr.useKlassRawPtr(kini); + if (s != "KlassInheritanceInput") + throw new ApplicationException("Incorrect string: " + s); + } + checkCount(0); + // auto_ptr as input using (Klass kin = new Klass("KlassInput")) { checkCount(1); @@ -84,49 +93,22 @@ public class li_std_auto_ptr_runme { throw new Exception("wrong object label"); Klass k2 = li_std_auto_ptr.makeKlassAutoPtr("second"); - if (Klass.getTotal_count() != 2) - throw new Exception("number of objects should be 2"); + checkCount(2); using (Klass k3 = li_std_auto_ptr.makeKlassAutoPtr("second")) { - if (Klass.getTotal_count() != 3) - throw new Exception("number of objects should be 3"); + checkCount(3); } - if (Klass.getTotal_count() != 2) - throw new Exception("number of objects should be 2"); + checkCount(2); + k1.Dispose(); k1 = null; - { - int countdown = 500; - int expectedCount = 1; - while (true) { - WaitForGC(); - if (--countdown == 0) - break; - if (Klass.getTotal_count() == expectedCount) - break; - }; - int actualCount = Klass.getTotal_count(); - if (actualCount != expectedCount) - Console.Error.WriteLine("Expected count: " + expectedCount + " Actual count: " + actualCount); // Finalizers are not guaranteed to be run and sometimes they just don't - } + checkCount(1); if (k2.getLabel() != "second") throw new Exception("wrong object label"); + k2.Dispose(); k2 = null; - { - int countdown = 500; - int expectedCount = 0; - while (true) { - WaitForGC(); - if (--countdown == 0) - break; - if (Klass.getTotal_count() == expectedCount) - break; - } - int actualCount = Klass.getTotal_count(); - if (actualCount != expectedCount) - Console.Error.WriteLine("Expected count: " + expectedCount + " Actual count: " + actualCount); // Finalizers are not guaranteed to be run and sometimes they just don't - } + checkCount(0); } } 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 5aee10727..ec89a0d28 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 @@ -93,17 +93,14 @@ void main() { throw new Exception("wrong object label"); Klass k2 = makeKlassUniquePtr("second"); - if (Klass.getTotal_count() != 2) - throw new Exception("number of objects should be 2"); + checkCount(2); k1.dispose(); - if (Klass.getTotal_count() != 1) - throw new Exception("number of objects should be 1"); + checkCount(1); if (k2.getLabel() != "second") throw new Exception("wrong object label"); k2.dispose(); - if (Klass.getTotal_count() != 0) - throw new Exception("no objects should be left"); + checkCount(0); } 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 5aee10727..ec89a0d28 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 @@ -93,17 +93,14 @@ void main() { throw new Exception("wrong object label"); Klass k2 = makeKlassUniquePtr("second"); - if (Klass.getTotal_count() != 2) - throw new Exception("number of objects should be 2"); + checkCount(2); k1.dispose(); - if (Klass.getTotal_count() != 1) - throw new Exception("number of objects should be 1"); + checkCount(1); if (k2.getLabel() != "second") throw new Exception("wrong object label"); k2.dispose(); - if (Klass.getTotal_count() != 0) - throw new Exception("no objects should be left"); + checkCount(0); } 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 3b51ba3ce..382f37e48 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 @@ -93,17 +93,14 @@ void main() { throw new Exception("wrong object label"); Klass k2 = makeKlassAutoPtr("second"); - if (Klass.getTotal_count() != 2) - throw new Exception("number of objects should be 2"); + checkCount(2); k1.dispose(); - if (Klass.getTotal_count() != 1) - throw new Exception("number of objects should be 1"); + checkCount(1); if (k2.getLabel() != "second") throw new Exception("wrong object label"); k2.dispose(); - if (Klass.getTotal_count() != 0) - throw new Exception("no objects should be left"); + checkCount(0); } 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 38efa3d7d..382f37e48 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 @@ -18,7 +18,6 @@ void main() { scope KlassInheritance kini = new KlassInheritance("KlassInheritanceInput"); checkCount(1); string s = useKlassRawPtr(kini); - checkCount(1); if (s != "KlassInheritanceInput") throw new Exception("Incorrect string: " ~ s); } @@ -94,17 +93,14 @@ void main() { throw new Exception("wrong object label"); Klass k2 = makeKlassAutoPtr("second"); - if (Klass.getTotal_count() != 2) - throw new Exception("number of objects should be 2"); + checkCount(2); k1.dispose(); - if (Klass.getTotal_count() != 1) - throw new Exception("number of objects should be 1"); + checkCount(1); if (k2.getLabel() != "second") throw new Exception("wrong object label"); k2.dispose(); - if (Klass.getTotal_count() != 0) - throw new Exception("no objects should be left"); + checkCount(0); } 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 7d6e708ad..7fec2e0cd 100644 --- a/Examples/test-suite/java/cpp11_std_unique_ptr_runme.java +++ b/Examples/test-suite/java/cpp11_std_unique_ptr_runme.java @@ -28,6 +28,17 @@ public class cpp11_std_unique_ptr_runme { public static void main(String argv[]) throws Throwable { + // Test raw pointer handling involving virtual inheritance + { + KlassInheritance kini = new KlassInheritance("KlassInheritanceInput"); + checkCount(1); + String s = cpp11_std_unique_ptr.useKlassRawPtr(kini); + if (!s.equals("KlassInheritanceInput")) + throw new RuntimeException("Incorrect string: " + s); + kini.delete(); + checkCount(0); + } + // unique_ptr as input { Klass kin = new Klass("KlassInput"); @@ -102,42 +113,17 @@ public class cpp11_std_unique_ptr_runme { throw new RuntimeException("wrong object label"); Klass k2 = cpp11_std_unique_ptr.makeKlassUniquePtr("second"); - if (Klass.getTotal_count() != 2) - throw new RuntimeException("number of objects should be 2"); + checkCount(2); + k1.delete(); k1 = null; - { - int countdown = 500; - int expectedCount = 1; - while (true) { - WaitForGC(); - if (--countdown == 0) - break; - if (Klass.getTotal_count() == expectedCount) - break; - } - int actualCount = Klass.getTotal_count(); - if (actualCount != expectedCount) - System.err.println("GC failed to run (cpp11_std_unique_ptr 1). Expected count: " + expectedCount + " Actual count: " + actualCount); // Finalizers are not guaranteed to be run and sometimes they just don't - } + checkCount(1); if (!k2.getLabel().equals("second")) throw new RuntimeException("wrong object label"); + k2.delete(); k2 = null; - { - int countdown = 500; - int expectedCount = 0; - while (true) { - WaitForGC(); - if (--countdown == 0) - break; - if (Klass.getTotal_count() == expectedCount) - break; - }; - int actualCount = Klass.getTotal_count(); - if (actualCount != expectedCount) - System.err.println("GC failed to run (cpp11_std_unique_ptr 2). Expected count: " + expectedCount + " Actual count: " + actualCount); // Finalizers are not guaranteed to be run and sometimes they just don't - } + checkCount(0); } } 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 58f1ea9c3..594908bbd 100644 --- a/Examples/test-suite/java/li_std_auto_ptr_runme.java +++ b/Examples/test-suite/java/li_std_auto_ptr_runme.java @@ -28,6 +28,17 @@ public class li_std_auto_ptr_runme { public static void main(String argv[]) throws Throwable { + // Test raw pointer handling involving virtual inheritance + { + KlassInheritance kini = new KlassInheritance("KlassInheritanceInput"); + checkCount(1); + String s = li_std_auto_ptr.useKlassRawPtr(kini); + if (!s.equals("KlassInheritanceInput")) + throw new RuntimeException("Incorrect string: " + s); + kini.delete(); + checkCount(0); + } + // auto_ptr as input { Klass kin = new Klass("KlassInput"); @@ -102,42 +113,17 @@ public class li_std_auto_ptr_runme { throw new RuntimeException("wrong object label"); Klass k2 = li_std_auto_ptr.makeKlassAutoPtr("second"); - if (Klass.getTotal_count() != 2) - throw new RuntimeException("number of objects should be 2"); + checkCount(2); + k1.delete(); k1 = null; - { - int countdown = 500; - int expectedCount = 1; - while (true) { - WaitForGC(); - if (--countdown == 0) - break; - if (Klass.getTotal_count() == expectedCount) - break; - } - int actualCount = Klass.getTotal_count(); - if (actualCount != expectedCount) - System.err.println("GC failed to run (li_std_auto_ptr 1). Expected count: " + expectedCount + " Actual count: " + actualCount); // Finalizers are not guaranteed to be run and sometimes they just don't - } + checkCount(1); if (!k2.getLabel().equals("second")) throw new RuntimeException("wrong object label"); + k2.delete(); k2 = null; - { - int countdown = 500; - int expectedCount = 0; - while (true) { - WaitForGC(); - if (--countdown == 0) - break; - if (Klass.getTotal_count() == expectedCount) - break; - }; - int actualCount = Klass.getTotal_count(); - if (actualCount != expectedCount) - System.err.println("GC failed to run (li_std_auto_ptr 2). Expected count: " + expectedCount + " Actual count: " + actualCount); // Finalizers are not guaranteed to be run and sometimes they just don't - } + checkCount(0); } } 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 e29217f5f..567af2c29 100644 --- a/Examples/test-suite/javascript/cpp11_std_unique_ptr_runme.js +++ b/Examples/test-suite/javascript/cpp11_std_unique_ptr_runme.js @@ -6,6 +6,20 @@ var checkCount = function(expected_count) { throw new Error("Counts incorrect, expected:" + expected_count + " actual:" + actual_count); } +// Test raw pointer handling involving virtual inheritance +{ + kini = new cpp11_std_unique_ptr.KlassInheritance("KlassInheritanceInput"); + checkCount(1); + s = cpp11_std_unique_ptr.useKlassRawPtr(kini); + if (s !== "KlassInheritanceInput") + throw new Error("Incorrect string: " + s); + // delete kini; + // Above not deleting the C++ object(node v12) - can't reliably control GC + cpp11_std_unique_ptr.takeKlassUniquePtr(kini); + checkCount(0); +} + + // unique_ptr as input { kin = new cpp11_std_unique_ptr.Klass("KlassInput"); @@ -82,14 +96,12 @@ if (k1.getLabel() !== "first") throw new Error("wrong object label"); k2 = cpp11_std_unique_ptr.makeKlassUniquePtr("second"); -if (cpp11_std_unique_ptr.Klass.getTotal_count() != 2) - throw new Error("number of objects should be 2"); +checkCount(2); // delete k1; -// Above not deleting the C++ object(node v12), not sure why, use below as workaround +// Above not deleting the C++ object(node v12) - can't reliably control GC cpp11_std_unique_ptr.takeKlassUniquePtr(k1); -if (cpp11_std_unique_ptr.Klass.getTotal_count() != 1) - throw new Error("number of objects should be 1"); +checkCount(1); if (k2.getLabel() !== "second") throw new Error("wrong object label"); @@ -97,5 +109,4 @@ if (k2.getLabel() !== "second") // delete k2; // Above not deleting the C++ object(node v12) - can't reliably control GC cpp11_std_unique_ptr.takeKlassUniquePtr(k2); -if (cpp11_std_unique_ptr.Klass.getTotal_count() != 0) - throw new Error("no objects should be left"); +checkCount(0); 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 5cb2007f8..66eecffda 100644 --- a/Examples/test-suite/javascript/li_std_auto_ptr_runme.js +++ b/Examples/test-suite/javascript/li_std_auto_ptr_runme.js @@ -6,6 +6,20 @@ var checkCount = function(expected_count) { throw new Error("Counts incorrect, expected:" + expected_count + " actual:" + actual_count); } +// Test raw pointer handling involving virtual inheritance +{ + kini = new li_std_auto_ptr.KlassInheritance("KlassInheritanceInput"); + checkCount(1); + s = li_std_auto_ptr.useKlassRawPtr(kini); + if (s !== "KlassInheritanceInput") + throw new Error("Incorrect string: " + s); + // delete kini; + // Above not deleting the C++ object(node v12) - can't reliably control GC + li_std_auto_ptr.takeKlassAutoPtr(kini); + checkCount(0); +} + + // auto_ptr as input { kin = new li_std_auto_ptr.Klass("KlassInput"); @@ -82,14 +96,12 @@ if (k1.getLabel() !== "first") throw new Error("wrong object label"); k2 = li_std_auto_ptr.makeKlassAutoPtr("second"); -if (li_std_auto_ptr.Klass.getTotal_count() != 2) - throw new Error("number of objects should be 2"); +checkCount(2); // delete k1; -// Above not deleting the C++ object(node v12), not sure why, use below as workaround +// Above not deleting the C++ object(node v12) - can't reliably control GC li_std_auto_ptr.takeKlassAutoPtr(k1); -if (li_std_auto_ptr.Klass.getTotal_count() != 1) - throw new Error("number of objects should be 1"); +checkCount(1); if (k2.getLabel() !== "second") throw new Error("wrong object label"); @@ -97,5 +109,4 @@ 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.Klass.getTotal_count() != 0) - throw new Error("no objects should be left"); +checkCount(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 82c93836b..4b1851901 100644 --- a/Examples/test-suite/octave/cpp11_std_unique_ptr_runme.m +++ b/Examples/test-suite/octave/cpp11_std_unique_ptr_runme.m @@ -12,6 +12,16 @@ function checkCount(expected_count) endif end +# Test raw pointer handling involving virtual inheritance +kini = KlassInheritance("KlassInheritanceInput"); +checkCount(1); +s = takeKlassUniquePtr(kini); +if (!strcmp(s, "KlassInheritanceInput")) + error("Incorrect string: %s", s); +endif +clear kini; +checkCount(0); + # unique_ptr as input kin = Klass("KlassInput"); @@ -91,20 +101,14 @@ if (!strcmp(k1.getLabel(), "first")) endif k2 = makeKlassUniquePtr("second"); -if (Klass_getTotal_count() != 2) - error("number of objects should be 2"); -endif +checkCount(2); clear k1; -if (Klass.getTotal_count() != 1) - error("number of objects should be 1"); -endif +checkCount(1); if (!strcmp(k2.getLabel(), "second")) error("wrong object label"); endif clear k2; -if (Klass.getTotal_count() != 0) - error("no objects should be left"); -endif +checkCount(0); 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 51898e0bd..db2fdaf5a 100644 --- a/Examples/test-suite/octave/li_std_auto_ptr_runme.m +++ b/Examples/test-suite/octave/li_std_auto_ptr_runme.m @@ -12,6 +12,17 @@ function checkCount(expected_count) endif end +# Test raw pointer handling involving virtual inheritance +kini = KlassInheritance("KlassInheritanceInput"); +checkCount(1); +s = takeKlassAutoPtr(kini); +if (!strcmp(s, "KlassInheritanceInput")) + error("Incorrect string: %s", s); +endif +clear kini; +checkCount(0); + + # auto_ptr as input kin = Klass("KlassInput"); checkCount(1); @@ -90,20 +101,14 @@ if (!strcmp(k1.getLabel(), "first")) endif k2 = makeKlassAutoPtr("second"); -if (Klass_getTotal_count() != 2) - error("number of objects should be 2"); -endif +checkCount(2); clear k1; -if (Klass.getTotal_count() != 1) - error("number of objects should be 1"); -endif +checkCount(1); if (!strcmp(k2.getLabel(), "second")) error("wrong object label"); endif clear k2; -if (Klass.getTotal_count() != 0) - error("no objects should be left"); -endif +checkCount(0); 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 0202b0fda..9a55c08ec 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 => 25; +use Test::More tests => 28; BEGIN { use_ok('cpp11_std_unique_ptr') } require_ok('cpp11_std_unique_ptr'); @@ -12,6 +12,17 @@ sub checkCount { is($actual_count, $expected_count, "Counts incorrect, expected: $expected_count actual: $actual_count"); } +# Test raw pointer handling involving virtual inheritance +{ + my $kini = new cpp11_std_unique_ptr::KlassInheritance("KlassInheritanceInput"); + checkCount(1); + my $s = cpp11_std_unique_ptr::takeKlassUniquePtr($kini); + is($s, "KlassInheritanceInput", "Incorrect string: $s"); + undef $kini; + checkCount(0); +} + + # unique_ptr as input { my $kin = new cpp11_std_unique_ptr::Klass("KlassInput"); @@ -65,12 +76,12 @@ sub checkCount { # unique_ptr as output my $k1 = cpp11_std_unique_ptr::makeKlassUniquePtr("first"); my $k2 = cpp11_std_unique_ptr::makeKlassUniquePtr("second"); -is(cpp11_std_unique_ptr::Klass::getTotal_count, 2, "have 2 pointers"); +checkCount(2); undef $k1; -is(cpp11_std_unique_ptr::Klass::getTotal_count, 1, "left 1 pointer"); +checkCount(1); is($k2->getLabel, "second", "proper label"); undef $k2; -is(cpp11_std_unique_ptr::Klass::getTotal_count, 0, "remove all pointers"); +checkCount(0); 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 232ebf6d0..5d367e683 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 => 25; +use Test::More tests => 28; BEGIN { use_ok('li_std_auto_ptr') } require_ok('li_std_auto_ptr'); @@ -12,6 +12,17 @@ sub checkCount { is($actual_count, $expected_count, "Counts incorrect, expected: $expected_count actual: $actual_count"); } +# Test raw pointer handling involving virtual inheritance +{ + my $kini = new li_std_auto_ptr::KlassInheritance("KlassInheritanceInput"); + checkCount(1); + my $s = li_std_auto_ptr::takeKlassAutoPtr($kini); + is($s, "KlassInheritanceInput", "Incorrect string: $s"); + undef $kini; + checkCount(0); +} + + # auto_ptr as input { my $kin = new li_std_auto_ptr::Klass("KlassInput"); @@ -65,12 +76,12 @@ sub checkCount { # auto_ptr as output my $k1 = li_std_auto_ptr::makeKlassAutoPtr("first"); my $k2 = li_std_auto_ptr::makeKlassAutoPtr("second"); -is(li_std_auto_ptr::Klass::getTotal_count, 2, "have 2 pointers"); +checkCount(2); undef $k1; -is(li_std_auto_ptr::Klass::getTotal_count, 1, "left 1 pointer"); +checkCount(1); is($k2->getLabel, "second", "proper label"); undef $k2; -is(li_std_auto_ptr::Klass::getTotal_count, 0, "remove all pointers"); +checkCount(0); 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 ba2a486bc..92dbc1c30 100644 --- a/Examples/test-suite/python/cpp11_std_unique_ptr_runme.py +++ b/Examples/test-suite/python/cpp11_std_unique_ptr_runme.py @@ -5,6 +5,16 @@ def checkCount(expected_count): if (actual_count != expected_count): raise RuntimeError("Counts incorrect, expected:" + expected_count + " actual:" + actual_count) +# Test raw pointer handling involving virtual inheritance +kini = KlassInheritance("KlassInheritanceInput") +checkCount(1) +s = takeKlassUniquePtr(kini) +if s != "KlassInheritanceInput": + raise RuntimeError("Incorrect string: " + s) +del kini +checkCount(0) + + # unique_ptr as input kin = Klass("KlassInput") checkCount(1) @@ -70,16 +80,13 @@ checkCount(0) # unique_ptr as output k1 = makeKlassUniquePtr("first") k2 = makeKlassUniquePtr("second") -if Klass.getTotal_count() != 2: - raise "number of objects should be 2" +checkCount(2) del k1 -if Klass.getTotal_count() != 1: - raise "number of objects should be 1" +checkCount(1) if k2.getLabel() != "second": raise "wrong object label" del k2 -if Klass.getTotal_count() != 0: - raise "no objects should be left" +checkCount(0) 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 fe377b6c4..881c59bfe 100644 --- a/Examples/test-suite/python/li_std_auto_ptr_runme.py +++ b/Examples/test-suite/python/li_std_auto_ptr_runme.py @@ -5,6 +5,16 @@ def checkCount(expected_count): if (actual_count != expected_count): raise RuntimeError("Counts incorrect, expected:" + expected_count + " actual:" + actual_count) +# Test raw pointer handling involving virtual inheritance +kini = KlassInheritance("KlassInheritanceInput") +checkCount(1) +s = takeKlassAutoPtr(kini) +if s != "KlassInheritanceInput": + raise RuntimeError("Incorrect string: " + s) +del kini +checkCount(0) + + # auto_ptr as input kin = Klass("KlassInput") checkCount(1) @@ -70,16 +80,13 @@ checkCount(0) # auto_ptr as output k1 = makeKlassAutoPtr("first") k2 = makeKlassAutoPtr("second") -if Klass.getTotal_count() != 2: - raise "number of objects should be 2" +checkCount(2) del k1 -if Klass.getTotal_count() != 1: - raise "number of objects should be 1" +checkCount(1) if k2.getLabel() != "second": raise "wrong object label" del k2 -if Klass.getTotal_count() != 0: - raise "no objects should be left" +checkCount(0) 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 4f2ccb3d9..af4374b77 100644 --- a/Examples/test-suite/ruby/cpp11_std_unique_ptr_runme.rb +++ b/Examples/test-suite/ruby/cpp11_std_unique_ptr_runme.rb @@ -18,6 +18,16 @@ def checkCount(expected_count) end end +# Test raw pointer handling involving virtual inheritance +kini = Cpp11_std_unique_ptr::KlassInheritance.new("KlassInheritanceInput") +checkCount(1) +s = Cpp11_std_unique_ptr.takeKlassUniquePtr(kini) +if (s != "KlassInheritanceInput") + raise RuntimeError, "Incorrect string: " + s +end +kini = nil +checkCount(0) + # unique_ptr as input kin = Cpp11_std_unique_ptr::Klass.new("KlassInput") 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 ffd33ad34..ba74b12a7 100644 --- a/Examples/test-suite/ruby/li_std_auto_ptr_runme.rb +++ b/Examples/test-suite/ruby/li_std_auto_ptr_runme.rb @@ -18,6 +18,16 @@ def checkCount(expected_count) end end +# Test raw pointer handling involving virtual inheritance +kini = Li_std_auto_ptr::KlassInheritance.new("KlassInheritanceInput") +checkCount(1) +s = Li_std_auto_ptr.takeKlassAutoPtr(kini) +if (s != "KlassInheritanceInput") + raise RuntimeError, "Incorrect string: " + s +end +kini = nil +checkCount(0) + # auto_ptr as input kin = Li_std_auto_ptr::Klass.new("KlassInput") 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 636757d48..2b71799e7 100644 --- a/Examples/test-suite/tcl/cpp11_std_unique_ptr_runme.tcl +++ b/Examples/test-suite/tcl/cpp11_std_unique_ptr_runme.tcl @@ -44,6 +44,13 @@ $k4 -delete checkCount 0 ################################# Tcl pointer recycling bug end +# Test raw pointer handling involving virtual inheritance +KlassInheritance kini "KlassInheritanceInput" +checkCount 1 +set s [takeKlassUniquePtr kini] +kini -delete +checkCount 0 + # unique_ptr as input Klass kin "KlassInput" @@ -122,20 +129,14 @@ checkCount 0 # unique_ptr as output set k1 [makeKlassUniquePtr "first"] set k2 [makeKlassUniquePtr "second"] -if {[Klass_getTotal_count] != 2} { - error "number of objects should be 2" -} +checkCount 2 $k1 -delete -if {[Klass_getTotal_count] != 1} { - error "number of objects should be 1" -} +checkCount 1 if {[$k2 getLabel] != "second"} { error "wrong object label" } $k2 -delete -if {[Klass_getTotal_count] != 0} { - error "no objects should be left" -} +checkCount 0 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 7c32187be..e9a41aabd 100644 --- a/Examples/test-suite/tcl/li_std_auto_ptr_runme.tcl +++ b/Examples/test-suite/tcl/li_std_auto_ptr_runme.tcl @@ -15,6 +15,13 @@ proc checkCount {expected_count} { # Not copied from cpp11_std_unique_ptr_runme.tcl ################################# Tcl pointer recycling bug end +# Test raw pointer handling involving virtual inheritance +KlassInheritance kini "KlassInheritanceInput" +checkCount 1 +set s [takeKlassAutoPtr kini] +kini -delete +checkCount 0 + # auto_ptr as input Klass kin "KlassInput" @@ -93,20 +100,14 @@ checkCount 0 # auto_ptr as output set k1 [makeKlassAutoPtr "first"] set k2 [makeKlassAutoPtr "second"] -if {[Klass_getTotal_count] != 2} { - error "number of objects should be 2" -} +checkCount 2 $k1 -delete -if {[Klass_getTotal_count] != 1} { - error "number of objects should be 1" -} +checkCount 1 if {[$k2 getLabel] != "second"} { error "wrong object label" } $k2 -delete -if {[Klass_getTotal_count] != 0} { - error "no objects should be left" -} +checkCount 0 From fa9c7a719789f94ba14858182c2a512c8a3ba3aa Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Sat, 6 Aug 2022 18:34:26 +0100 Subject: [PATCH 615/662] Add PHP support for std::unique_ptr and std::auto_ptr Equivalent to Python/Ruby implementations. --- Examples/test-suite/cpp11_std_unique_ptr.i | 6 +- Examples/test-suite/li_std_auto_ptr.i | 2 +- .../php/cpp11_std_unique_ptr_runme.php | 88 +++++++++++++++++++ .../test-suite/php/li_std_auto_ptr_runme.php | 88 +++++++++++++++++++ Lib/php/phprun.swg | 16 +++- Lib/php/std_auto_ptr.i | 35 ++++++++ Lib/php/std_unique_ptr.i | 35 ++++++++ 7 files changed, 265 insertions(+), 5 deletions(-) create mode 100644 Examples/test-suite/php/cpp11_std_unique_ptr_runme.php create mode 100644 Examples/test-suite/php/li_std_auto_ptr_runme.php create mode 100644 Lib/php/std_auto_ptr.i create mode 100644 Lib/php/std_unique_ptr.i diff --git a/Examples/test-suite/cpp11_std_unique_ptr.i b/Examples/test-suite/cpp11_std_unique_ptr.i index 0549a7b45..285eedf5a 100644 --- a/Examples/test-suite/cpp11_std_unique_ptr.i +++ b/Examples/test-suite/cpp11_std_unique_ptr.i @@ -1,6 +1,6 @@ %module cpp11_std_unique_ptr -#if defined(SWIGCSHARP) || defined(SWIGJAVA) || defined(SWIGPYTHON) || defined(SWIGRUBY) || defined(SWIGPERL) || defined(SWIGTCL) || defined(SWIGOCTAVE) || defined(SWIGJAVASCRIPT) || defined(SWIGD) +#if defined(SWIGCSHARP) || defined(SWIGJAVA) || defined(SWIGPYTHON) || defined(SWIGRUBY) || defined(SWIGPERL) || defined(SWIGTCL) || defined(SWIGOCTAVE) || defined(SWIGJAVASCRIPT) || defined(SWIGD) || defined(SWIGPHP) %include "std_string.i" %include "std_unique_ptr.i" @@ -68,6 +68,10 @@ std::string takeKlassUniquePtr(std::unique_ptr k) { return s; } +Klass *make_null() { + return nullptr; +} + bool is_nullptr(Klass *p) { return p == nullptr; } diff --git a/Examples/test-suite/li_std_auto_ptr.i b/Examples/test-suite/li_std_auto_ptr.i index 5f3b7724f..49615e0b5 100644 --- a/Examples/test-suite/li_std_auto_ptr.i +++ b/Examples/test-suite/li_std_auto_ptr.i @@ -12,7 +12,7 @@ #endif %} -#if defined(SWIGCSHARP) || defined(SWIGJAVA) || defined(SWIGPYTHON) || defined(SWIGRUBY) || defined(SWIGPERL) || defined(SWIGTCL) || defined(SWIGOCTAVE) || defined(SWIGJAVASCRIPT) || defined(SWIGD) +#if defined(SWIGCSHARP) || defined(SWIGJAVA) || defined(SWIGPYTHON) || defined(SWIGRUBY) || defined(SWIGPERL) || defined(SWIGTCL) || defined(SWIGOCTAVE) || defined(SWIGJAVASCRIPT) || defined(SWIGD) || (SWIGPHP) %include "std_string.i" //#include diff --git a/Examples/test-suite/php/cpp11_std_unique_ptr_runme.php b/Examples/test-suite/php/cpp11_std_unique_ptr_runme.php new file mode 100644 index 000000000..5820592de --- /dev/null +++ b/Examples/test-suite/php/cpp11_std_unique_ptr_runme.php @@ -0,0 +1,88 @@ +getMessage(), "Cannot release ownership as memory is not owned for argument 1 of type 'Klass *' of takeKlassUniquePtr", "Unexpected exception: {$e->getMessage()}"); +} +$kin = NULL; # Should not fail, even though already deleted +checkCount(0); + +$kin = new Klass("KlassInput"); +$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()}"); +} +checkCount(1); +$kin = NULL; +checkCount(0); + +$kini = new KlassInheritance("KlassInheritanceInput"); +checkCount(1); +$s = takeKlassUniquePtr($kini); +checkCount(0); +check::equal($s, "KlassInheritanceInput", "Incorrect string: $s"); +try { + is_nullptr($kini); + check::fail("is_nullptr check"); +} catch (TypeError $e) { +} + +$kini = NULL; # Should not fail, even though already deleted +checkCount(0); + +# unique_ptr as output +$k1 = makeKlassUniquePtr("first"); +$k2 = makeKlassUniquePtr("second"); +checkCount(2); + +$k1 = NULL; +checkCount(1); + +check::equal($k2->getLabel(), "second", "proper label"); + +$k2 = NULL; +checkCount(0); + +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 new file mode 100644 index 000000000..c4992c1fe --- /dev/null +++ b/Examples/test-suite/php/li_std_auto_ptr_runme.php @@ -0,0 +1,88 @@ +getMessage(), "Cannot release ownership as memory is not owned for argument 1 of type 'Klass *' of takeKlassAutoPtr", "Unexpected exception: {$e->getMessage()}"); +} +$kin = NULL; # Should not fail, even though already deleted +checkCount(0); + +$kin = new Klass("KlassInput"); +$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()}"); +} +checkCount(1); +$kin = NULL; +checkCount(0); + +$kini = new KlassInheritance("KlassInheritanceInput"); +checkCount(1); +$s = takeKlassAutoPtr($kini); +checkCount(0); +check::equal($s, "KlassInheritanceInput", "Incorrect string: $s"); +try { + is_nullptr($kini); + check::fail("is_nullptr check"); +} catch (TypeError $e) { +} + +$kini = NULL; # Should not fail, even though already deleted +checkCount(0); + +# auto_ptr as output +$k1 = makeKlassAutoPtr("first"); +$k2 = makeKlassAutoPtr("second"); +checkCount(2); + +$k1 = NULL; +checkCount(1); + +check::equal($k2->getLabel(), "second", "proper label"); + +$k2 = NULL; +checkCount(0); + +check::done(); diff --git a/Lib/php/phprun.swg b/Lib/php/phprun.swg index a49683197..a81baf001 100644 --- a/Lib/php/phprun.swg +++ b/Lib/php/phprun.swg @@ -208,10 +208,20 @@ SWIG_ConvertPtrAndOwn(zval *z, void **ptr, swig_type_info *ty, int flags, swig_o *ptr = NULL; } } - if (*ptr == NULL) return SWIG_ERROR; - if (flags & SWIG_POINTER_DISOWN) { - value->newobject = 0; + + if (((flags & SWIG_POINTER_RELEASE) == SWIG_POINTER_RELEASE) && !value->newobject) { + return SWIG_ERROR_RELEASE_NOT_OWNED; + } else { + if (*ptr == NULL) + return SWIG_ERROR; /* should be SWIG_NullReferenceError?? */ + if (flags & SWIG_POINTER_DISOWN) { + value->newobject = 0; + } + if (flags & SWIG_POINTER_CLEAR) { + value->ptr = 0; + } } + return SWIG_OK; } case IS_NULL: diff --git a/Lib/php/std_auto_ptr.i b/Lib/php/std_auto_ptr.i new file mode 100644 index 000000000..7df497e60 --- /dev/null +++ b/Lib/php/std_auto_ptr.i @@ -0,0 +1,35 @@ +/* ----------------------------------------------------------------------------- + * std_auto_ptr.i + * + * SWIG library file for handling std::auto_ptr. + * Memory ownership is passed from the std::auto_ptr C++ layer to the proxy + * class when returning a std::auto_ptr from a function. + * Memory ownership is passed from the proxy class to the std::auto_ptr in the + * C++ layer when passed as a parameter to a wrapped function. + * ----------------------------------------------------------------------------- */ + +%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); + 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"); + return; + } else { + zend_type_error("Expected TYPE * for argument $argnum of $symname"); + return; + } + } + $1.reset((TYPE *)argp); +} + +%typemap (out) std::auto_ptr< TYPE > %{ + SWIG_SetPointerZval($result, (void *)$1.release(), $descriptor(TYPE *), SWIG_POINTER_OWN); +%} + +%template() std::auto_ptr< TYPE >; +%enddef + +namespace std { + template class auto_ptr {}; +} diff --git a/Lib/php/std_unique_ptr.i b/Lib/php/std_unique_ptr.i new file mode 100644 index 000000000..591f580cb --- /dev/null +++ b/Lib/php/std_unique_ptr.i @@ -0,0 +1,35 @@ +/* ----------------------------------------------------------------------------- + * std_unique_ptr.i + * + * SWIG library file for handling std::unique_ptr. + * Memory ownership is passed from the std::unique_ptr C++ layer to the proxy + * class when returning a std::unique_ptr from a function. + * Memory ownership is passed from the proxy class to the std::unique_ptr in the + * C++ layer when passed as a parameter to a wrapped function. + * ----------------------------------------------------------------------------- */ + +%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); + 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"); + return; + } else { + zend_type_error("Expected TYPE * for argument $argnum of $symname"); + return; + } + } + $1.reset((TYPE *)argp); +} + +%typemap (out) std::unique_ptr< TYPE > %{ + SWIG_SetPointerZval($result, (void *)$1.release(), $descriptor(TYPE *), SWIG_POINTER_OWN); +%} + +%template() std::unique_ptr< TYPE >; +%enddef + +namespace std { + template class unique_ptr {}; +} From 6436c9408a08559372789d01731184a13762d4f7 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Sun, 7 Aug 2022 08:12:49 +0100 Subject: [PATCH 616/662] GHA: Add ruby-3.1 testing --- .github/workflows/ci.yml | 3 +++ Tools/CI-linux-install.sh | 16 ++++++++++------ 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a7bfd5b0b..700fcc12e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -176,6 +176,9 @@ jobs: - SWIGLANG: ruby VER: '3.0' CPPSTD: c++11 + - SWIGLANG: ruby + VER: '3.1' + CPPSTD: c++11 - SWIGLANG: scilab VER: '5.5.2' - SWIGLANG: scilab diff --git a/Tools/CI-linux-install.sh b/Tools/CI-linux-install.sh index fb3e57de9..456f5bc42 100644 --- a/Tools/CI-linux-install.sh +++ b/Tools/CI-linux-install.sh @@ -131,12 +131,16 @@ case "$SWIGLANG" in source $HOME/.rvm/scripts/rvm set -x fi - if [[ "$VER" == "2.7" || "$VER" == "3.0" ]]; then - # Ruby 2.7+ support is currently only rvm master (30 Dec 2019) - $RETRY rvm get master - rvm reload - rvm list known - fi + case "$VER" in + 2.7 | 3.0 | 3.1 ) + # Ruby 2.7+ support is currently only rvm master (30 Dec 2019) + set +x + $RETRY rvm get master + rvm reload + rvm list known + set -x + ;; + esac if [[ "$VER" ]]; then $RETRY rvm install $VER fi From 1f2338bf41341306a6c523753edd257f30f0f353 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Thu, 11 Aug 2022 07:20:04 +0100 Subject: [PATCH 617/662] Typo fix in Go.html --- Doc/Manual/Go.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Doc/Manual/Go.html b/Doc/Manual/Go.html index 5501010cf..f4ef1fe57 100644 --- a/Doc/Manual/Go.html +++ b/Doc/Manual/Go.html @@ -1424,7 +1424,7 @@ default as described above. An intermediate Go type used by the "goin", "goout", "godirectorin", and "godirectorout" typemaps. If this typemap is not defined for a -C/C++ type, the gotype typemape will be used. This is useful when +C/C++ type, the gotype typemap will be used. This is useful when gotype is best converted to C/C++ using Go code. From 63632f80fb815aef2577aaa495fdbe369c880ab2 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Thu, 11 Aug 2022 18:44:36 +0100 Subject: [PATCH 618/662] Correct raw pointer handling test for virtual inheritance --- Examples/test-suite/octave/cpp11_std_unique_ptr_runme.m | 2 +- Examples/test-suite/octave/li_std_auto_ptr_runme.m | 2 +- Examples/test-suite/perl5/cpp11_std_unique_ptr_runme.pl | 2 +- Examples/test-suite/perl5/li_std_auto_ptr_runme.pl | 2 +- Examples/test-suite/php/cpp11_std_unique_ptr_runme.php | 2 +- Examples/test-suite/php/li_std_auto_ptr_runme.php | 2 +- Examples/test-suite/python/cpp11_std_unique_ptr_runme.py | 2 +- Examples/test-suite/python/li_std_auto_ptr_runme.py | 2 +- Examples/test-suite/ruby/cpp11_std_unique_ptr_runme.rb | 5 +++-- Examples/test-suite/ruby/li_std_auto_ptr_runme.rb | 5 +++-- Examples/test-suite/tcl/cpp11_std_unique_ptr_runme.tcl | 2 +- Examples/test-suite/tcl/li_std_auto_ptr_runme.tcl | 2 +- 12 files changed, 16 insertions(+), 14 deletions(-) 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 4b1851901..7d1c0e41a 100644 --- a/Examples/test-suite/octave/cpp11_std_unique_ptr_runme.m +++ b/Examples/test-suite/octave/cpp11_std_unique_ptr_runme.m @@ -15,7 +15,7 @@ end # Test raw pointer handling involving virtual inheritance kini = KlassInheritance("KlassInheritanceInput"); checkCount(1); -s = takeKlassUniquePtr(kini); +s = useKlassRawPtr(kini); if (!strcmp(s, "KlassInheritanceInput")) error("Incorrect string: %s", s); endif 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 db2fdaf5a..832d75faf 100644 --- a/Examples/test-suite/octave/li_std_auto_ptr_runme.m +++ b/Examples/test-suite/octave/li_std_auto_ptr_runme.m @@ -15,7 +15,7 @@ end # Test raw pointer handling involving virtual inheritance kini = KlassInheritance("KlassInheritanceInput"); checkCount(1); -s = takeKlassAutoPtr(kini); +s = useKlassRawPtr(kini); if (!strcmp(s, "KlassInheritanceInput")) error("Incorrect string: %s", s); endif 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 9a55c08ec..3e3e7f4b1 100644 --- a/Examples/test-suite/perl5/cpp11_std_unique_ptr_runme.pl +++ b/Examples/test-suite/perl5/cpp11_std_unique_ptr_runme.pl @@ -16,7 +16,7 @@ sub checkCount { { my $kini = new cpp11_std_unique_ptr::KlassInheritance("KlassInheritanceInput"); checkCount(1); - my $s = cpp11_std_unique_ptr::takeKlassUniquePtr($kini); + my $s = cpp11_std_unique_ptr::useKlassRawPtr($kini); is($s, "KlassInheritanceInput", "Incorrect string: $s"); undef $kini; checkCount(0); 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 5d367e683..cc71d9128 100644 --- a/Examples/test-suite/perl5/li_std_auto_ptr_runme.pl +++ b/Examples/test-suite/perl5/li_std_auto_ptr_runme.pl @@ -16,7 +16,7 @@ sub checkCount { { my $kini = new li_std_auto_ptr::KlassInheritance("KlassInheritanceInput"); checkCount(1); - my $s = li_std_auto_ptr::takeKlassAutoPtr($kini); + my $s = li_std_auto_ptr::useKlassRawPtr($kini); is($s, "KlassInheritanceInput", "Incorrect string: $s"); undef $kini; checkCount(0); 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 5820592de..b02fdaa33 100644 --- a/Examples/test-suite/php/cpp11_std_unique_ptr_runme.php +++ b/Examples/test-suite/php/cpp11_std_unique_ptr_runme.php @@ -10,7 +10,7 @@ function checkCount($expected_count) { # Test raw pointer handling involving virtual inheritance $kini = new KlassInheritance("KlassInheritanceInput"); checkCount(1); -$s = takeKlassUniquePtr($kini); +$s = useKlassRawPtr($kini); check::equal($s, "KlassInheritanceInput", "Incorrect string: $s"); $kini = 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 c4992c1fe..cba5f2109 100644 --- a/Examples/test-suite/php/li_std_auto_ptr_runme.php +++ b/Examples/test-suite/php/li_std_auto_ptr_runme.php @@ -10,7 +10,7 @@ function checkCount($expected_count) { # Test raw pointer handling involving virtual inheritance $kini = new KlassInheritance("KlassInheritanceInput"); checkCount(1); -$s = takeKlassAutoPtr($kini); +$s = useKlassRawPtr($kini); check::equal($s, "KlassInheritanceInput", "Incorrect string: $s"); $kini = NULL; checkCount(0); 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 92dbc1c30..e822ddf09 100644 --- a/Examples/test-suite/python/cpp11_std_unique_ptr_runme.py +++ b/Examples/test-suite/python/cpp11_std_unique_ptr_runme.py @@ -8,7 +8,7 @@ def checkCount(expected_count): # Test raw pointer handling involving virtual inheritance kini = KlassInheritance("KlassInheritanceInput") checkCount(1) -s = takeKlassUniquePtr(kini) +s = useKlassRawPtr(kini) if s != "KlassInheritanceInput": raise RuntimeError("Incorrect string: " + s) del kini 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 881c59bfe..9c68f3e52 100644 --- a/Examples/test-suite/python/li_std_auto_ptr_runme.py +++ b/Examples/test-suite/python/li_std_auto_ptr_runme.py @@ -8,7 +8,7 @@ def checkCount(expected_count): # Test raw pointer handling involving virtual inheritance kini = KlassInheritance("KlassInheritanceInput") checkCount(1) -s = takeKlassAutoPtr(kini) +s = useKlassRawPtr(kini) if s != "KlassInheritanceInput": raise RuntimeError("Incorrect string: " + s) del kini 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 af4374b77..c623b45c5 100644 --- a/Examples/test-suite/ruby/cpp11_std_unique_ptr_runme.rb +++ b/Examples/test-suite/ruby/cpp11_std_unique_ptr_runme.rb @@ -21,11 +21,12 @@ end # Test raw pointer handling involving virtual inheritance kini = Cpp11_std_unique_ptr::KlassInheritance.new("KlassInheritanceInput") checkCount(1) -s = Cpp11_std_unique_ptr.takeKlassUniquePtr(kini) +s = Cpp11_std_unique_ptr.useKlassRawPtr(kini) if (s != "KlassInheritanceInput") raise RuntimeError, "Incorrect string: " + s end -kini = nil +# kini = nil +Cpp11_std_unique_ptr.takeKlassUniquePtr(kini) # Ensure object is deleted (can't rely on GC) checkCount(0) 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 ba74b12a7..6780763c0 100644 --- a/Examples/test-suite/ruby/li_std_auto_ptr_runme.rb +++ b/Examples/test-suite/ruby/li_std_auto_ptr_runme.rb @@ -21,11 +21,12 @@ end # Test raw pointer handling involving virtual inheritance kini = Li_std_auto_ptr::KlassInheritance.new("KlassInheritanceInput") checkCount(1) -s = Li_std_auto_ptr.takeKlassAutoPtr(kini) +s = Li_std_auto_ptr.useKlassRawPtr(kini) if (s != "KlassInheritanceInput") raise RuntimeError, "Incorrect string: " + s end -kini = nil +# kini = nil +Li_std_auto_ptr.takeKlassAutoPtr(kini) # Ensure object is deleted (can't rely on GC) checkCount(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 2b71799e7..380985f4e 100644 --- a/Examples/test-suite/tcl/cpp11_std_unique_ptr_runme.tcl +++ b/Examples/test-suite/tcl/cpp11_std_unique_ptr_runme.tcl @@ -47,7 +47,7 @@ checkCount 0 # Test raw pointer handling involving virtual inheritance KlassInheritance kini "KlassInheritanceInput" checkCount 1 -set s [takeKlassUniquePtr kini] +set s [useKlassRawPtr kini] kini -delete checkCount 0 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 e9a41aabd..f88be1aed 100644 --- a/Examples/test-suite/tcl/li_std_auto_ptr_runme.tcl +++ b/Examples/test-suite/tcl/li_std_auto_ptr_runme.tcl @@ -18,7 +18,7 @@ proc checkCount {expected_count} { # Test raw pointer handling involving virtual inheritance KlassInheritance kini "KlassInheritanceInput" checkCount 1 -set s [takeKlassAutoPtr kini] +set s [useKlassRawPtr kini] kini -delete checkCount 0 From 41fddf61ec6aa253b6a531ef33dd78fef5925e4a Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Thu, 11 Aug 2022 21:37:16 +0100 Subject: [PATCH 619/662] Add Lua support for std::unique_ptr and std::auto_ptr Equivalent to Python/Ruby implementations. --- CHANGES.current | 4 + Examples/test-suite/cpp11_std_unique_ptr.i | 2 +- Examples/test-suite/li_std_auto_ptr.i | 2 +- .../test-suite/lua/li_std_auto_ptr_runme.lua | 93 +++++++++++++++++++ Lib/lua/luarun.swg | 30 ++++-- Lib/lua/std_auto_ptr.i | 33 +++++++ Lib/lua/std_unique_ptr.i | 33 +++++++ 7 files changed, 186 insertions(+), 11 deletions(-) create mode 100644 Examples/test-suite/lua/li_std_auto_ptr_runme.lua create mode 100644 Lib/lua/std_auto_ptr.i create mode 100644 Lib/lua/std_unique_ptr.i diff --git a/CHANGES.current b/CHANGES.current index bb16fef2d..8554c5a2d 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-11: wsfulton + [Lua] Add support for std::unique_ptr in std_unique_ptr.i. + Add support for std::auto_ptr in std_auto_ptr.i. + 2022-08-05: wsfulton [D] Fix occasional undefined behaviour with inheritance hierarchies, particularly when using virtual inheritance as the pointers weren't correctly upcast from derived diff --git a/Examples/test-suite/cpp11_std_unique_ptr.i b/Examples/test-suite/cpp11_std_unique_ptr.i index 285eedf5a..2defdd445 100644 --- a/Examples/test-suite/cpp11_std_unique_ptr.i +++ b/Examples/test-suite/cpp11_std_unique_ptr.i @@ -1,6 +1,6 @@ %module cpp11_std_unique_ptr -#if defined(SWIGCSHARP) || defined(SWIGJAVA) || defined(SWIGPYTHON) || defined(SWIGRUBY) || defined(SWIGPERL) || defined(SWIGTCL) || defined(SWIGOCTAVE) || defined(SWIGJAVASCRIPT) || defined(SWIGD) || defined(SWIGPHP) +#if !(defined(SWIGGO) || defined(SWIGOCAML) || defined(SWIGMZSCHEME) || defined(SWIGR) || defined(SWIGSCILAB)) %include "std_string.i" %include "std_unique_ptr.i" diff --git a/Examples/test-suite/li_std_auto_ptr.i b/Examples/test-suite/li_std_auto_ptr.i index 49615e0b5..ee007c777 100644 --- a/Examples/test-suite/li_std_auto_ptr.i +++ b/Examples/test-suite/li_std_auto_ptr.i @@ -12,7 +12,7 @@ #endif %} -#if defined(SWIGCSHARP) || defined(SWIGJAVA) || defined(SWIGPYTHON) || defined(SWIGRUBY) || defined(SWIGPERL) || defined(SWIGTCL) || defined(SWIGOCTAVE) || defined(SWIGJAVASCRIPT) || defined(SWIGD) || (SWIGPHP) +#if !(defined(SWIGGO) || defined(SWIGOCAML) || defined(SWIGMZSCHEME) || defined(SWIGR) || defined(SWIGSCILAB)) %include "std_string.i" //#include diff --git a/Examples/test-suite/lua/li_std_auto_ptr_runme.lua b/Examples/test-suite/lua/li_std_auto_ptr_runme.lua new file mode 100644 index 000000000..f677a6e4e --- /dev/null +++ b/Examples/test-suite/lua/li_std_auto_ptr_runme.lua @@ -0,0 +1,93 @@ +require("import") -- the import fn +import("li_std_auto_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 = li_std_auto_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 = li_std_auto_ptr.KlassInheritance("KlassInheritanceInput") +checkCount(1) +s = li_std_auto_ptr.useKlassRawPtr(kini) +if not (s == "KlassInheritanceInput") then + error("Incorrect string: "..s) +end +kini = nil +checkCount(0) + +-- auto_ptr as input +kin = li_std_auto_ptr.Klass("KlassInput") +checkCount(1) +s = li_std_auto_ptr.takeKlassAutoPtr(kin) +checkCount(0) +if not (s == "KlassInput") then + error("Incorrect string: "..s) +end +if not (li_std_auto_ptr.is_nullptr(kin)) then + error("is_nullptr failed") +end +kin = nil -- Should not fail, even though already deleted +checkCount(0) + +kin = li_std_auto_ptr.Klass("KlassInput") +checkCount(1) +s = li_std_auto_ptr.takeKlassAutoPtr(kin) +checkCount(0) +if not (s == "KlassInput") then + error("Incorrect string: "..s) +end +if not (li_std_auto_ptr.is_nullptr(kin)) then + error("is_nullptr failed") +end +s, msg = pcall(function() li_std_auto_ptr.takeKlassAutoPtr(kin) end) +assert(s == false and msg == "Cannot release ownership as memory is not owned for argument 1 of type 'Klass *' in takeKlassAutoPtr") + +kin = nil -- Should not fail, even though already deleted +checkCount(0) + +kin = li_std_auto_ptr.Klass("KlassInput") +notowned = li_std_auto_ptr.get_not_owned_ptr(kin) +s, msg = pcall(function() li_std_auto_ptr.takeKlassAutoPtr(notowned) end) +assert(s == false and msg == "Cannot release ownership as memory is not owned for argument 1 of type 'Klass *' in takeKlassAutoPtr") +checkCount(1) +kin = nil +checkCount(0) + +kini = li_std_auto_ptr.KlassInheritance("KlassInheritanceInput") +checkCount(1) +s = li_std_auto_ptr.takeKlassAutoPtr(kini) +checkCount(0) +if not (s == "KlassInheritanceInput") then + error("Incorrect string: "..s) +end +if not (li_std_auto_ptr.is_nullptr(kini)) then + error("is_nullptr failed") +end +kini = nil -- Should not fail, even though already deleted +checkCount(0) + +-- auto_ptr as output +k1 = li_std_auto_ptr.makeKlassAutoPtr("first") +k2 = li_std_auto_ptr.makeKlassAutoPtr("second") +checkCount(2) + +k1 = nil +checkCount(1) + +if not (k2:getLabel() == "second") then + error("wrong object label") +end + +k2 = nil +checkCount(0) diff --git a/Lib/lua/luarun.swg b/Lib/lua/luarun.swg index 572da4703..909a5229c 100644 --- a/Lib/lua/luarun.swg +++ b/Lib/lua/luarun.swg @@ -1757,6 +1757,7 @@ SWIGRUNTIME void SWIG_Lua_NewPointerObj(lua_State *L,void *ptr,swig_type_info *t (if possible) */ SWIGRUNTIME int SWIG_Lua_ConvertPtr(lua_State *L,int index,void **ptr,swig_type_info *type,int flags) { + int ret = SWIG_ERROR; swig_lua_userdata *usr; swig_cast_info *cast; /* special case: lua nil => NULL pointer */ @@ -1773,25 +1774,36 @@ SWIGRUNTIME int SWIG_Lua_ConvertPtr(lua_State *L,int index,void **ptr,swig_type usr=(swig_lua_userdata*)lua_touserdata(L,index); /* get data */ if (usr) { + if (((flags & SWIG_POINTER_RELEASE) == SWIG_POINTER_RELEASE) && !usr->own) + { + return SWIG_ERROR_RELEASE_NOT_OWNED; + } if (flags & SWIG_POINTER_DISOWN) /* must disown the object */ { - usr->own=0; + usr->own = 0; } if (!type) /* special cast void*, no casting fn */ { *ptr=usr->ptr; - return SWIG_OK; /* ok */ + ret = SWIG_OK; } - cast=SWIG_TypeCheckStruct(usr->type,type); /* performs normal type checking */ - if (cast) + else { - int newmemory = 0; - *ptr=SWIG_TypeCast(cast,usr->ptr,&newmemory); - assert(!newmemory); /* newmemory handling not yet implemented */ - return SWIG_OK; /* ok */ + cast=SWIG_TypeCheckStruct(usr->type,type); /* performs normal type checking */ + if (cast) + { + int newmemory = 0; + *ptr=SWIG_TypeCast(cast,usr->ptr,&newmemory); + assert(!newmemory); /* newmemory handling not yet implemented */ + ret = SWIG_OK; + } + } + if ((ret == SWIG_OK) && (flags & SWIG_POINTER_CLEAR)) + { + usr->ptr = 0; } } - return SWIG_ERROR; /* error */ + return ret; } SWIGRUNTIME void* SWIG_Lua_MustGetPtr(lua_State *L,int index,swig_type_info *type,int flags, diff --git a/Lib/lua/std_auto_ptr.i b/Lib/lua/std_auto_ptr.i new file mode 100644 index 000000000..b0978963b --- /dev/null +++ b/Lib/lua/std_auto_ptr.i @@ -0,0 +1,33 @@ +/* ----------------------------------------------------------------------------- + * std_auto_ptr.i + * + * SWIG library file for handling std::auto_ptr. + * Memory ownership is passed from the std::auto_ptr C++ layer to the proxy + * class when returning a std::auto_ptr from a function. + * Memory ownership is passed from the proxy class to the std::auto_ptr in the + * C++ layer when passed as a parameter to a wrapped function. + * ----------------------------------------------------------------------------- */ + +%define %auto_ptr(TYPE) +%typemap(in, checkfn="lua_isuserdata", 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) { + lua_pushfstring(L, "Cannot release ownership as memory is not owned for argument $argnum of type 'TYPE *' in $symname"); SWIG_fail; + } else { + SWIG_fail_ptr("$symname", $argnum, $descriptor(TYPE *)); + } + } + $1.reset((TYPE *)argp); +} + +%typemap (out) std::auto_ptr< TYPE > %{ + SWIG_NewPointerObj(L, $1.release(), $descriptor(TYPE *), SWIG_POINTER_OWN); SWIG_arg++; +%} + +%template() std::auto_ptr< TYPE >; +%enddef + +namespace std { + template class auto_ptr {}; +} diff --git a/Lib/lua/std_unique_ptr.i b/Lib/lua/std_unique_ptr.i new file mode 100644 index 000000000..de84b2497 --- /dev/null +++ b/Lib/lua/std_unique_ptr.i @@ -0,0 +1,33 @@ +/* ----------------------------------------------------------------------------- + * std_unique_ptr.i + * + * SWIG library file for handling std::unique_ptr. + * Memory ownership is passed from the std::unique_ptr C++ layer to the proxy + * class when returning a std::unique_ptr from a function. + * Memory ownership is passed from the proxy class to the std::unique_ptr in the + * C++ layer when passed as a parameter to a wrapped function. + * ----------------------------------------------------------------------------- */ + +%define %unique_ptr(TYPE) +%typemap(in, checkfn="lua_isuserdata", 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) { + lua_pushfstring(L, "Cannot release ownership as memory is not owned for argument $argnum of type 'TYPE *' in $symname"); SWIG_fail; + } else { + SWIG_fail_ptr("$symname", $argnum, $descriptor(TYPE *)); + } + } + $1.reset((TYPE *)argp); +} + +%typemap (out) std::unique_ptr< TYPE > %{ + SWIG_NewPointerObj(L, $1.release(), $descriptor(TYPE *), SWIG_POINTER_OWN); SWIG_arg++; +%} + +%template() std::unique_ptr< TYPE >; +%enddef + +namespace std { + template class unique_ptr {}; +} From b34092c5171b204ec5554261d66da9c8f1d64072 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Thu, 11 Aug 2022 22:08:10 +0100 Subject: [PATCH 620/662] Add -pthread to lua testing Required to fix linker errors in li_std_auto_ptr and cpp11_std_unique_ptr test cases --- configure.ac | 1 + 1 file changed, 1 insertion(+) diff --git a/configure.ac b/configure.ac index 242124205..b3b1a8e48 100644 --- a/configure.ac +++ b/configure.ac @@ -2430,6 +2430,7 @@ if test "$LUABIN"; then if test "$LUA_VERSION" = "5.0"; then LUALINK="$LUALINK -llualib" fi + LUALINK="$LUALINK -pthread" LIBS=$lua_save_LIBS # restore LIBS fi From 3a0721bfbcab3250b05f0deb01a7362dcac002a7 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Thu, 11 Aug 2022 22:12:19 +0100 Subject: [PATCH 621/662] Remove inadvertent guile testing of auto_ptr and unique_ptr --- Examples/test-suite/cpp11_std_unique_ptr.i | 2 +- Examples/test-suite/li_std_auto_ptr.i | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Examples/test-suite/cpp11_std_unique_ptr.i b/Examples/test-suite/cpp11_std_unique_ptr.i index 2defdd445..1bd7a8b58 100644 --- a/Examples/test-suite/cpp11_std_unique_ptr.i +++ b/Examples/test-suite/cpp11_std_unique_ptr.i @@ -1,6 +1,6 @@ %module cpp11_std_unique_ptr -#if !(defined(SWIGGO) || defined(SWIGOCAML) || defined(SWIGMZSCHEME) || defined(SWIGR) || defined(SWIGSCILAB)) +#if !(defined(SWIGGO) || defined(SWIGGUILE) || defined(SWIGOCAML) || defined(SWIGMZSCHEME) || defined(SWIGR) || defined(SWIGSCILAB)) %include "std_string.i" %include "std_unique_ptr.i" diff --git a/Examples/test-suite/li_std_auto_ptr.i b/Examples/test-suite/li_std_auto_ptr.i index ee007c777..af6249e17 100644 --- a/Examples/test-suite/li_std_auto_ptr.i +++ b/Examples/test-suite/li_std_auto_ptr.i @@ -12,7 +12,7 @@ #endif %} -#if !(defined(SWIGGO) || defined(SWIGOCAML) || defined(SWIGMZSCHEME) || defined(SWIGR) || defined(SWIGSCILAB)) +#if !(defined(SWIGGO) || defined(SWIGGUILE) || defined(SWIGOCAML) || defined(SWIGMZSCHEME) || defined(SWIGR) || defined(SWIGSCILAB)) %include "std_string.i" //#include From 23ce0655a61eef61e15b7fc78b81393a362c7981 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Fri, 12 Aug 2022 23:50:54 +0100 Subject: [PATCH 622/662] Add Guile support for std::unique_ptr and std::auto_ptr Equivalent to Python/Ruby implementations. --- CHANGES.current | 4 + Examples/test-suite/cpp11_std_unique_ptr.i | 2 +- .../guile/cpp11_std_unique_ptr_runme.scm | 3 + .../guile/li_std_auto_ptr_runme.scm | 3 + Examples/test-suite/li_std_auto_ptr.i | 2 +- .../schemerunme/cpp11_std_unique_ptr.scm | 75 +++++++++++++++++++ .../schemerunme/li_std_auto_ptr.scm | 75 +++++++++++++++++++ Lib/guile/guile_scm_run.swg | 25 +++++-- Lib/guile/std_auto_ptr.i | 33 ++++++++ Lib/guile/std_unique_ptr.i | 33 ++++++++ 10 files changed, 248 insertions(+), 7 deletions(-) create mode 100644 Examples/test-suite/guile/cpp11_std_unique_ptr_runme.scm create mode 100644 Examples/test-suite/guile/li_std_auto_ptr_runme.scm create mode 100644 Examples/test-suite/schemerunme/cpp11_std_unique_ptr.scm create mode 100644 Examples/test-suite/schemerunme/li_std_auto_ptr.scm create mode 100644 Lib/guile/std_auto_ptr.i create mode 100644 Lib/guile/std_unique_ptr.i diff --git a/CHANGES.current b/CHANGES.current index 8554c5a2d..ad4b4aea4 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-13: wsfulton + [Guile] Add support for std::unique_ptr in std_unique_ptr.i. + Add support for std::auto_ptr in std_auto_ptr.i. + 2022-08-11: wsfulton [Lua] 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/cpp11_std_unique_ptr.i b/Examples/test-suite/cpp11_std_unique_ptr.i index 1bd7a8b58..2defdd445 100644 --- a/Examples/test-suite/cpp11_std_unique_ptr.i +++ b/Examples/test-suite/cpp11_std_unique_ptr.i @@ -1,6 +1,6 @@ %module cpp11_std_unique_ptr -#if !(defined(SWIGGO) || defined(SWIGGUILE) || defined(SWIGOCAML) || defined(SWIGMZSCHEME) || defined(SWIGR) || defined(SWIGSCILAB)) +#if !(defined(SWIGGO) || defined(SWIGOCAML) || defined(SWIGMZSCHEME) || defined(SWIGR) || defined(SWIGSCILAB)) %include "std_string.i" %include "std_unique_ptr.i" diff --git a/Examples/test-suite/guile/cpp11_std_unique_ptr_runme.scm b/Examples/test-suite/guile/cpp11_std_unique_ptr_runme.scm new file mode 100644 index 000000000..9ba124a5e --- /dev/null +++ b/Examples/test-suite/guile/cpp11_std_unique_ptr_runme.scm @@ -0,0 +1,3 @@ +(dynamic-call "scm_init_cpp11_std_unique_ptr_module" (dynamic-link "./libcpp11_std_unique_ptr")) +(load "testsuite.scm") +(load "../schemerunme/cpp11_std_unique_ptr.scm") diff --git a/Examples/test-suite/guile/li_std_auto_ptr_runme.scm b/Examples/test-suite/guile/li_std_auto_ptr_runme.scm new file mode 100644 index 000000000..04d3d6597 --- /dev/null +++ b/Examples/test-suite/guile/li_std_auto_ptr_runme.scm @@ -0,0 +1,3 @@ +(dynamic-call "scm_init_li_std_auto_ptr_module" (dynamic-link "./libli_std_auto_ptr")) +(load "testsuite.scm") +(load "../schemerunme/li_std_auto_ptr.scm") diff --git a/Examples/test-suite/li_std_auto_ptr.i b/Examples/test-suite/li_std_auto_ptr.i index af6249e17..ee007c777 100644 --- a/Examples/test-suite/li_std_auto_ptr.i +++ b/Examples/test-suite/li_std_auto_ptr.i @@ -12,7 +12,7 @@ #endif %} -#if !(defined(SWIGGO) || defined(SWIGGUILE) || defined(SWIGOCAML) || defined(SWIGMZSCHEME) || defined(SWIGR) || defined(SWIGSCILAB)) +#if !(defined(SWIGGO) || defined(SWIGOCAML) || defined(SWIGMZSCHEME) || defined(SWIGR) || defined(SWIGSCILAB)) %include "std_string.i" //#include diff --git a/Examples/test-suite/schemerunme/cpp11_std_unique_ptr.scm b/Examples/test-suite/schemerunme/cpp11_std_unique_ptr.scm new file mode 100644 index 000000000..1a32d08d1 --- /dev/null +++ b/Examples/test-suite/schemerunme/cpp11_std_unique_ptr.scm @@ -0,0 +1,75 @@ +(define checkCount + (lambda (expected-count) + (define actual-count (Klass-getTotal-count)) + (if (not (= actual-count expected-count)) (error "Counts incorrect, expected:" expected-count " actual:" actual-count)))) + +; Test raw pointer handling involving virtual inheritance +(define kini (new-KlassInheritance "KlassInheritanceInput")) +(checkCount 1) +(define s (useKlassRawPtr kini)) +(if (not (string=? s "KlassInheritanceInput")) + (error "Incorrect string: " s)) +(delete-Klass kini) +(checkCount 0) + +; unique_ptr as input +(define kin (new-Klass "KlassInput")) +(checkCount 1) +(define s (takeKlassUniquePtr kin)) +(checkCount 0) +(if (not (string=? s "KlassInput")) + (error "Incorrect string: " s)) +(if (not (is-nullptr kin)) + (error "is_nullptr failed")) +(delete-Klass kin) ; Should not fail, even though already deleted +(checkCount 0) + +(define kin (new-Klass "KlassInput")) +(checkCount 1) +(define s (takeKlassUniquePtr kin)) +(checkCount 0) +(if (not (string=? s "KlassInput")) + (error "Incorrect string: " s)) +(if (not (is-nullptr kin)) + (error "is_nullptr failed")) +(expect-throw 'misc-error + (takeKlassUniquePtr kin)) +; TODO: check the exception message +(delete-Klass kin) ; Should not fail, even though already deleted +(checkCount 0) + +(define kin (new-Klass "KlassInput")) +(define notowned (get-not-owned-ptr kin)) +(expect-throw 'misc-error + (takeKlassUniquePtr notowned)) +; TODO: check the exception message +(checkCount 1) +(delete-Klass kin) +(checkCount 0) + +(define kini (new-KlassInheritance "KlassInheritanceInput")) +(checkCount 1) +(define s (takeKlassUniquePtr kini)) +(checkCount 0) +(if (not (string=? s "KlassInheritanceInput")) + (error "Incorrect string: " s)) +(if (not (is-nullptr kini)) + (error "is_nullptr failed")) +(delete-Klass kini) ; Should not fail, even though already deleted +(checkCount 0) + +; unique_ptr as output +(define k1 (makeKlassUniquePtr "first")) +(define k2 (makeKlassUniquePtr "second")) +(checkCount 2) + +(delete-Klass k1) +(checkCount 1) + +(if (not (string=? (Klass-getLabel k2) "second")) + (error "wrong object label" )) + +(delete-Klass k2) +(checkCount 0) + +(exit 0) diff --git a/Examples/test-suite/schemerunme/li_std_auto_ptr.scm b/Examples/test-suite/schemerunme/li_std_auto_ptr.scm new file mode 100644 index 000000000..b3cf088b9 --- /dev/null +++ b/Examples/test-suite/schemerunme/li_std_auto_ptr.scm @@ -0,0 +1,75 @@ +(define checkCount + (lambda (expected-count) + (define actual-count (Klass-getTotal-count)) + (if (not (= actual-count expected-count)) (error "Counts incorrect, expected:" expected-count " actual:" actual-count)))) + +; Test raw pointer handling involving virtual inheritance +(define kini (new-KlassInheritance "KlassInheritanceInput")) +(checkCount 1) +(define s (useKlassRawPtr kini)) +(if (not (string=? s "KlassInheritanceInput")) + (error "Incorrect string: " s)) +(delete-Klass kini) +(checkCount 0) + +; auto_ptr as input +(define kin (new-Klass "KlassInput")) +(checkCount 1) +(define s (takeKlassAutoPtr kin)) +(checkCount 0) +(if (not (string=? s "KlassInput")) + (error "Incorrect string: " s)) +(if (not (is-nullptr kin)) + (error "is_nullptr failed")) +(delete-Klass kin) ; Should not fail, even though already deleted +(checkCount 0) + +(define kin (new-Klass "KlassInput")) +(checkCount 1) +(define s (takeKlassAutoPtr kin)) +(checkCount 0) +(if (not (string=? s "KlassInput")) + (error "Incorrect string: " s)) +(if (not (is-nullptr kin)) + (error "is_nullptr failed")) +(expect-throw 'misc-error + (takeKlassAutoPtr kin)) +; TODO: check the exception message +(delete-Klass kin) ; Should not fail, even though already deleted +(checkCount 0) + +(define kin (new-Klass "KlassInput")) +(define notowned (get-not-owned-ptr kin)) +(expect-throw 'misc-error + (takeKlassAutoPtr notowned)) +; TODO: check the exception message +(checkCount 1) +(delete-Klass kin) +(checkCount 0) + +(define kini (new-KlassInheritance "KlassInheritanceInput")) +(checkCount 1) +(define s (takeKlassAutoPtr kini)) +(checkCount 0) +(if (not (string=? s "KlassInheritanceInput")) + (error "Incorrect string: " s)) +(if (not (is-nullptr kini)) + (error "is_nullptr failed")) +(delete-Klass kini) ; Should not fail, even though already deleted +(checkCount 0) + +; auto_ptr as output +(define k1 (makeKlassAutoPtr "first")) +(define k2 (makeKlassAutoPtr "second")) +(checkCount 2) + +(delete-Klass k1) +(checkCount 1) + +(if (not (string=? (Klass-getLabel k2) "second")) + (error "wrong object label" )) + +(delete-Klass k2) +(checkCount 0) + +(exit 0) diff --git a/Lib/guile/guile_scm_run.swg b/Lib/guile/guile_scm_run.swg index 3752d3c8a..44e2db225 100644 --- a/Lib/guile/guile_scm_run.swg +++ b/Lib/guile/guile_scm_run.swg @@ -118,6 +118,8 @@ static SCM swig_symbol = SCM_EOL; ( !scm_is_null(x) && SCM_INSTANCEP(x) && scm_is_true(scm_slot_exists_p(x, swig_symbol)) \ ? scm_slot_ref(x, swig_symbol) : (x) ) +SWIGINTERN void SWIG_Guile_MarkPointerNoncollectable(SCM s); + SWIGINTERN SCM SWIG_Guile_NewPointerObj(void *ptr, swig_type_info *type, int owner) { @@ -191,6 +193,7 @@ SWIG_Guile_ConvertPtr(SCM s, void **result, swig_type_info *type, int flags) swig_cast_info *cast; swig_type_info *from; SCM smob = SWIG_Guile_GetSmob(s); + int ret = SWIG_ERROR; if (scm_is_null(smob)) { *result = NULL; @@ -203,22 +206,34 @@ SWIG_Guile_ConvertPtr(SCM s, void **result, swig_type_info *type, int flags) } else if (SWIG_Guile_IsValidSmob(smob)) { from = (swig_type_info *) SCM_CELL_WORD_2(smob); if (!from) return SWIG_ERROR; + + if ((flags & SWIG_POINTER_RELEASE) == SWIG_POINTER_RELEASE) { + if ((SCM_CELL_TYPE(smob) == swig_collectable_tag && SCM_CELL_WORD_1(smob) == 0) || SCM_CELL_TYPE(smob) == swig_tag) { + return SWIG_ERROR_RELEASE_NOT_OWNED; + } + } + if (type) { cast = SWIG_TypeCheckStruct(from, type); if (cast) { int newmemory = 0; *result = SWIG_TypeCast(cast, (void *) SCM_CELL_WORD_1(smob), &newmemory); assert(!newmemory); /* newmemory handling not yet implemented */ - return SWIG_OK; - } else { - return SWIG_ERROR; + ret = SWIG_OK; } } else { *result = (void *) SCM_CELL_WORD_1(smob); - return SWIG_OK; + ret = SWIG_OK; + } + + if (flags & SWIG_POINTER_DISOWN) { + SWIG_Guile_MarkPointerNoncollectable(smob); + } + if (flags & SWIG_POINTER_CLEAR) { + SCM_SET_CELL_WORD_1(smob, 0); } } - return SWIG_ERROR; + return ret; } SWIGINTERNINLINE void * diff --git a/Lib/guile/std_auto_ptr.i b/Lib/guile/std_auto_ptr.i new file mode 100644 index 000000000..1b1253a16 --- /dev/null +++ b/Lib/guile/std_auto_ptr.i @@ -0,0 +1,33 @@ +/* ----------------------------------------------------------------------------- + * std_auto_ptr.i + * + * SWIG library file for handling std::auto_ptr. + * Memory ownership is passed from the std::auto_ptr C++ layer to the proxy + * class when returning a std::auto_ptr from a function. + * Memory ownership is passed from the proxy class to the std::auto_ptr in the + * C++ layer when passed as a parameter to a wrapped function. + * ----------------------------------------------------------------------------- */ + +%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); + if (!SWIG_IsOK(res)) { + if (res == SWIG_ERROR_RELEASE_NOT_OWNED) { + scm_misc_error(FUNC_NAME, "Cannot release ownership as memory is not owned for argument $argnum of type 'TYPE *'", SCM_EOL); + } else { + %argument_fail(res, "TYPE *", $symname, $argnum); + } + } + $1.reset((TYPE *)argp); +} + +%typemap (out) std::auto_ptr< TYPE > %{ + %set_output(SWIG_NewPointerObj($1.release(), $descriptor(TYPE *), SWIG_POINTER_OWN)); +%} + +%template() std::auto_ptr< TYPE >; +%enddef + +namespace std { + template class auto_ptr {}; +} diff --git a/Lib/guile/std_unique_ptr.i b/Lib/guile/std_unique_ptr.i new file mode 100644 index 000000000..5fc4dc490 --- /dev/null +++ b/Lib/guile/std_unique_ptr.i @@ -0,0 +1,33 @@ +/* ----------------------------------------------------------------------------- + * std_unique_ptr.i + * + * SWIG library file for handling std::unique_ptr. + * Memory ownership is passed from the std::unique_ptr C++ layer to the proxy + * class when returning a std::unique_ptr from a function. + * Memory ownership is passed from the proxy class to the std::unique_ptr in the + * C++ layer when passed as a parameter to a wrapped function. + * ----------------------------------------------------------------------------- */ + +%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); + if (!SWIG_IsOK(res)) { + if (res == SWIG_ERROR_RELEASE_NOT_OWNED) { + scm_misc_error(FUNC_NAME, "Cannot release ownership as memory is not owned for argument $argnum of type 'TYPE *'", SCM_EOL); + } else { + %argument_fail(res, "TYPE *", $symname, $argnum); + } + } + $1.reset((TYPE *)argp); +} + +%typemap (out) std::unique_ptr< TYPE > %{ + %set_output(SWIG_NewPointerObj($1.release(), $descriptor(TYPE *), SWIG_POINTER_OWN)); +%} + +%template() std::unique_ptr< TYPE >; +%enddef + +namespace std { + template class unique_ptr {}; +} From 748bad3db2734ca415ce594492c3ecf912990380 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Mon, 15 Aug 2022 19:56:31 +0100 Subject: [PATCH 623/662] Add guile test for %newobject --- Examples/test-suite/guile/newobject1_runme.scm | 3 +++ Examples/test-suite/schemerunme/newobject1.scm | 16 ++++++++++++++++ 2 files changed, 19 insertions(+) create mode 100644 Examples/test-suite/guile/newobject1_runme.scm create mode 100644 Examples/test-suite/schemerunme/newobject1.scm diff --git a/Examples/test-suite/guile/newobject1_runme.scm b/Examples/test-suite/guile/newobject1_runme.scm new file mode 100644 index 000000000..21f6d8618 --- /dev/null +++ b/Examples/test-suite/guile/newobject1_runme.scm @@ -0,0 +1,3 @@ +(dynamic-call "scm_init_newobject1_module" (dynamic-link "./libnewobject1")) +(load "../schemerunme/newobject1.scm") + diff --git a/Examples/test-suite/schemerunme/newobject1.scm b/Examples/test-suite/schemerunme/newobject1.scm new file mode 100644 index 000000000..fa0ace6de --- /dev/null +++ b/Examples/test-suite/schemerunme/newobject1.scm @@ -0,0 +1,16 @@ +(define-macro (check test) + `(if (not ,test) (error "Error in test" ',test))) + +(define foo1 (Foo-makeFoo)) +(check (= (Foo-fooCount) 1)) + +(define foo2 (Foo-makeMore foo1)) +(check (= (Foo-fooCount) 2)) + +(delete-Foo foo1) +(check (= (Foo-fooCount) 1)) + +(delete-Foo foo2) +(check (= (Foo-fooCount) 0)) + +(exit 0) From c9f5a85e45e9eaf79d67f94ecf0108b279784b20 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Wed, 17 Aug 2022 08:16:47 +0100 Subject: [PATCH 624/662] Add Racket test for %newobject Uses common mzscheme test, but corrections for Racket error: if: bad syntax (must have an "else" expression) --- Examples/test-suite/mzscheme/newobject1_runme.scm | 5 +++++ Examples/test-suite/schemerunme/newobject1.scm | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) create mode 100644 Examples/test-suite/mzscheme/newobject1_runme.scm diff --git a/Examples/test-suite/mzscheme/newobject1_runme.scm b/Examples/test-suite/mzscheme/newobject1_runme.scm new file mode 100644 index 000000000..a7c55d2b0 --- /dev/null +++ b/Examples/test-suite/mzscheme/newobject1_runme.scm @@ -0,0 +1,5 @@ +(load-extension "newobject1.so") + +(require (lib "defmacro.ss")) + +(load "../schemerunme/newobject1.scm") diff --git a/Examples/test-suite/schemerunme/newobject1.scm b/Examples/test-suite/schemerunme/newobject1.scm index fa0ace6de..7779d89a2 100644 --- a/Examples/test-suite/schemerunme/newobject1.scm +++ b/Examples/test-suite/schemerunme/newobject1.scm @@ -1,5 +1,5 @@ (define-macro (check test) - `(if (not ,test) (error "Error in test" ',test))) + `(unless ,test (error "Error in test" ',test))) (define foo1 (Foo-makeFoo)) (check (= (Foo-fooCount) 1)) From 5b16e4fbd39b6c089e2b5e573e5516765fee92fb Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Thu, 18 Aug 2022 21:31:20 +0100 Subject: [PATCH 625/662] Guile cpp11_std_unique_ptr testcase tweaks for use from Racket --- .../schemerunme/cpp11_std_unique_ptr.scm | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/Examples/test-suite/schemerunme/cpp11_std_unique_ptr.scm b/Examples/test-suite/schemerunme/cpp11_std_unique_ptr.scm index 1a32d08d1..97ecaaf54 100644 --- a/Examples/test-suite/schemerunme/cpp11_std_unique_ptr.scm +++ b/Examples/test-suite/schemerunme/cpp11_std_unique_ptr.scm @@ -1,13 +1,13 @@ (define checkCount (lambda (expected-count) (define actual-count (Klass-getTotal-count)) - (if (not (= actual-count expected-count)) (error "Counts incorrect, expected:" expected-count " actual:" actual-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)) -(if (not (string=? s "KlassInheritanceInput")) +(unless (string=? s "KlassInheritanceInput") (error "Incorrect string: " s)) (delete-Klass kini) (checkCount 0) @@ -17,9 +17,9 @@ (checkCount 1) (define s (takeKlassUniquePtr kin)) (checkCount 0) -(if (not (string=? s "KlassInput")) +(unless (string=? s "KlassInput") (error "Incorrect string: " s)) -(if (not (is-nullptr kin)) +(unless (is-nullptr kin) (error "is_nullptr failed")) (delete-Klass kin) ; Should not fail, even though already deleted (checkCount 0) @@ -28,9 +28,9 @@ (checkCount 1) (define s (takeKlassUniquePtr kin)) (checkCount 0) -(if (not (string=? s "KlassInput")) +(unless (string=? s "KlassInput") (error "Incorrect string: " s)) -(if (not (is-nullptr kin)) +(unless (is-nullptr kin) (error "is_nullptr failed")) (expect-throw 'misc-error (takeKlassUniquePtr kin)) @@ -51,9 +51,9 @@ (checkCount 1) (define s (takeKlassUniquePtr kini)) (checkCount 0) -(if (not (string=? s "KlassInheritanceInput")) +(unless (string=? s "KlassInheritanceInput") (error "Incorrect string: " s)) -(if (not (is-nullptr kini)) +(unless (is-nullptr kini) (error "is_nullptr failed")) (delete-Klass kini) ; Should not fail, even though already deleted (checkCount 0) @@ -66,7 +66,7 @@ (delete-Klass k1) (checkCount 1) -(if (not (string=? (Klass-getLabel k2) "second")) +(unless (string=? (Klass-getLabel k2) "second") (error "wrong object label" )) (delete-Klass k2) From 63143e8773086954207a14cf82fd7a35d673fb56 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Thu, 18 Aug 2022 21:42:25 +0100 Subject: [PATCH 626/662] Guile testing - call gc instead of explicitly calling the destructor --- .../schemerunme/cpp11_std_unique_ptr.scm | 14 +++++++------- Examples/test-suite/schemerunme/newobject1.scm | 6 ++++-- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/Examples/test-suite/schemerunme/cpp11_std_unique_ptr.scm b/Examples/test-suite/schemerunme/cpp11_std_unique_ptr.scm index 97ecaaf54..49184005a 100644 --- a/Examples/test-suite/schemerunme/cpp11_std_unique_ptr.scm +++ b/Examples/test-suite/schemerunme/cpp11_std_unique_ptr.scm @@ -9,7 +9,7 @@ (define s (useKlassRawPtr kini)) (unless (string=? s "KlassInheritanceInput") (error "Incorrect string: " s)) -(delete-Klass kini) +(set! kini '()) (gc) (checkCount 0) ; unique_ptr as input @@ -21,7 +21,7 @@ (error "Incorrect string: " s)) (unless (is-nullptr kin) (error "is_nullptr failed")) -(delete-Klass kin) ; Should not fail, even though already deleted +(set! kini '()) (gc) ; Should not fail, even though already deleted (checkCount 0) (define kin (new-Klass "KlassInput")) @@ -35,7 +35,7 @@ (expect-throw 'misc-error (takeKlassUniquePtr kin)) ; TODO: check the exception message -(delete-Klass kin) ; Should not fail, even though already deleted +(set! kin '()) (gc) ; Should not fail, even though already deleted (checkCount 0) (define kin (new-Klass "KlassInput")) @@ -44,7 +44,7 @@ (takeKlassUniquePtr notowned)) ; TODO: check the exception message (checkCount 1) -(delete-Klass kin) +(set! kin '()) (gc) (checkCount 0) (define kini (new-KlassInheritance "KlassInheritanceInput")) @@ -55,7 +55,7 @@ (error "Incorrect string: " s)) (unless (is-nullptr kini) (error "is_nullptr failed")) -(delete-Klass kini) ; Should not fail, even though already deleted +(set! kini '()) (gc) ; Should not fail, even though already deleted (checkCount 0) ; unique_ptr as output @@ -63,13 +63,13 @@ (define k2 (makeKlassUniquePtr "second")) (checkCount 2) -(delete-Klass k1) +(set! k1 '()) (gc) (checkCount 1) (unless (string=? (Klass-getLabel k2) "second") (error "wrong object label" )) -(delete-Klass k2) +(set! k2 '()) (gc) (checkCount 0) (exit 0) diff --git a/Examples/test-suite/schemerunme/newobject1.scm b/Examples/test-suite/schemerunme/newobject1.scm index 7779d89a2..9d9d43a18 100644 --- a/Examples/test-suite/schemerunme/newobject1.scm +++ b/Examples/test-suite/schemerunme/newobject1.scm @@ -7,10 +7,12 @@ (define foo2 (Foo-makeMore foo1)) (check (= (Foo-fooCount) 2)) -(delete-Foo foo1) +(set! foo1 '()) +(gc) (check (= (Foo-fooCount) 1)) -(delete-Foo foo2) +(set! foo2 '()) +(gc) (check (= (Foo-fooCount) 0)) (exit 0) From 5365149ae4eaa84ee813c96efc2e3aa4ded77acb Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Thu, 18 Aug 2022 22:37:59 +0100 Subject: [PATCH 627/662] Guile testing - call gc instead of explicitly calling the destructor - Guile li_std_auto_ptr testcase tweaks intended for use from Racket --- .../schemerunme/li_std_auto_ptr.scm | 32 +++++++++---------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/Examples/test-suite/schemerunme/li_std_auto_ptr.scm b/Examples/test-suite/schemerunme/li_std_auto_ptr.scm index b3cf088b9..f23a00c41 100644 --- a/Examples/test-suite/schemerunme/li_std_auto_ptr.scm +++ b/Examples/test-suite/schemerunme/li_std_auto_ptr.scm @@ -1,15 +1,15 @@ (define checkCount (lambda (expected-count) (define actual-count (Klass-getTotal-count)) - (if (not (= actual-count expected-count)) (error "Counts incorrect, expected:" expected-count " actual:" actual-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)) -(if (not (string=? s "KlassInheritanceInput")) +(unless (string=? s "KlassInheritanceInput") (error "Incorrect string: " s)) -(delete-Klass kini) +(set! kini '()) (gc) (checkCount 0) ; auto_ptr as input @@ -17,25 +17,25 @@ (checkCount 1) (define s (takeKlassAutoPtr kin)) (checkCount 0) -(if (not (string=? s "KlassInput")) +(unless (string=? s "KlassInput") (error "Incorrect string: " s)) -(if (not (is-nullptr kin)) +(unless (is-nullptr kin) (error "is_nullptr failed")) -(delete-Klass kin) ; Should not fail, even though already deleted +(set! kini '()) (gc) ; Should not fail, even though already deleted (checkCount 0) (define kin (new-Klass "KlassInput")) (checkCount 1) (define s (takeKlassAutoPtr kin)) (checkCount 0) -(if (not (string=? s "KlassInput")) +(unless (string=? s "KlassInput") (error "Incorrect string: " s)) -(if (not (is-nullptr kin)) +(unless (is-nullptr kin) (error "is_nullptr failed")) (expect-throw 'misc-error (takeKlassAutoPtr kin)) ; TODO: check the exception message -(delete-Klass kin) ; Should not fail, even though already deleted +(set! kin '()) (gc) ; Should not fail, even though already deleted (checkCount 0) (define kin (new-Klass "KlassInput")) @@ -44,18 +44,18 @@ (takeKlassAutoPtr notowned)) ; TODO: check the exception message (checkCount 1) -(delete-Klass kin) +(set! kin '()) (gc) (checkCount 0) (define kini (new-KlassInheritance "KlassInheritanceInput")) (checkCount 1) (define s (takeKlassAutoPtr kini)) (checkCount 0) -(if (not (string=? s "KlassInheritanceInput")) +(unless (string=? s "KlassInheritanceInput") (error "Incorrect string: " s)) -(if (not (is-nullptr kini)) +(unless (is-nullptr kini) (error "is_nullptr failed")) -(delete-Klass kini) ; Should not fail, even though already deleted +(set! kini '()) (gc) ; Should not fail, even though already deleted (checkCount 0) ; auto_ptr as output @@ -63,13 +63,13 @@ (define k2 (makeKlassAutoPtr "second")) (checkCount 2) -(delete-Klass k1) +(set! k1 '()) (gc) (checkCount 1) -(if (not (string=? (Klass-getLabel k2) "second")) +(unless (string=? (Klass-getLabel k2) "second") (error "wrong object label" )) -(delete-Klass k2) +(set! k2 '()) (gc) (checkCount 0) (exit 0) From 48c644ea6eb9f817b88f2813ed05f88a8c8be034 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Thu, 18 Aug 2022 22:41:40 +0100 Subject: [PATCH 628/662] Add Racket support for std::unique_ptr and std::auto_ptr Equivalent to Guile implementation. Slight tweak to proxy ownership was required by adding in the own member to swig_mz_proxy. --- CHANGES.current | 4 + Examples/test-suite/cpp11_std_unique_ptr.i | 2 +- Examples/test-suite/li_std_auto_ptr.i | 2 +- .../mzscheme/li_std_auto_ptr_runme.scm | 91 +++++++++++++++++++ .../test-suite/mzscheme/newobject1_runme.scm | 4 + Lib/mzscheme/mzrun.swg | 28 ++++-- Lib/mzscheme/std_auto_ptr.i | 36 ++++++++ Lib/mzscheme/std_unique_ptr.i | 36 ++++++++ Lib/mzscheme/typemaps.i | 7 +- 9 files changed, 201 insertions(+), 9 deletions(-) create mode 100644 Examples/test-suite/mzscheme/li_std_auto_ptr_runme.scm create mode 100644 Lib/mzscheme/std_auto_ptr.i create mode 100644 Lib/mzscheme/std_unique_ptr.i diff --git a/CHANGES.current b/CHANGES.current index ad4b4aea4..edba0d6ec 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-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. + 2022-08-13: wsfulton [Guile] 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/cpp11_std_unique_ptr.i b/Examples/test-suite/cpp11_std_unique_ptr.i index 2defdd445..414557507 100644 --- a/Examples/test-suite/cpp11_std_unique_ptr.i +++ b/Examples/test-suite/cpp11_std_unique_ptr.i @@ -1,6 +1,6 @@ %module cpp11_std_unique_ptr -#if !(defined(SWIGGO) || defined(SWIGOCAML) || defined(SWIGMZSCHEME) || defined(SWIGR) || defined(SWIGSCILAB)) +#if !(defined(SWIGGO) || defined(SWIGOCAML) || defined(SWIGR) || defined(SWIGSCILAB)) %include "std_string.i" %include "std_unique_ptr.i" diff --git a/Examples/test-suite/li_std_auto_ptr.i b/Examples/test-suite/li_std_auto_ptr.i index ee007c777..c02397c08 100644 --- a/Examples/test-suite/li_std_auto_ptr.i +++ b/Examples/test-suite/li_std_auto_ptr.i @@ -12,7 +12,7 @@ #endif %} -#if !(defined(SWIGGO) || defined(SWIGOCAML) || defined(SWIGMZSCHEME) || defined(SWIGR) || defined(SWIGSCILAB)) +#if !(defined(SWIGGO) || defined(SWIGOCAML) || defined(SWIGR) || defined(SWIGSCILAB)) %include "std_string.i" //#include diff --git a/Examples/test-suite/mzscheme/li_std_auto_ptr_runme.scm b/Examples/test-suite/mzscheme/li_std_auto_ptr_runme.scm new file mode 100644 index 000000000..6335d4eb8 --- /dev/null +++ b/Examples/test-suite/mzscheme/li_std_auto_ptr_runme.scm @@ -0,0 +1,91 @@ +(load-extension "li_std_auto_ptr.so") +(require (lib "defmacro.ss")) + +; Copied from ../schemerunme/li_std_auto_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) + +; auto_ptr as input +(define kin (new-Klass "KlassInput")) +(checkCount 1) +(define s (takeKlassAutoPtr 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 (takeKlassAutoPtr 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)))]) + (takeKlassAutoPtr kin)) +(unless (string=? exception_thrown "takeKlassAutoPtr: 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)))]) + (takeKlassAutoPtr notowned)) +(unless (string=? exception_thrown "takeKlassAutoPtr: 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 (takeKlassAutoPtr 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) + +; auto_ptr as output +(define k1 (makeKlassAutoPtr "first")) +(define k2 (makeKlassAutoPtr "second")) +(checkCount 2) + +(set! k1 '()) (gc) +(checkCount 1) + +(unless (string=? (Klass-getLabel k2) "second") + (error "wrong object label" )) + +(set! k2 '()) (gc) +(checkCount 0) + +(exit 0) diff --git a/Examples/test-suite/mzscheme/newobject1_runme.scm b/Examples/test-suite/mzscheme/newobject1_runme.scm index a7c55d2b0..c2d7a9809 100644 --- a/Examples/test-suite/mzscheme/newobject1_runme.scm +++ b/Examples/test-suite/mzscheme/newobject1_runme.scm @@ -2,4 +2,8 @@ (require (lib "defmacro.ss")) +; Define an equivalent to Guile's gc procedure +(define-macro (gc) + `(collect-garbage 'major)) + (load "../schemerunme/newobject1.scm") diff --git a/Lib/mzscheme/mzrun.swg b/Lib/mzscheme/mzrun.swg index 279073113..fed660dfb 100644 --- a/Lib/mzscheme/mzrun.swg +++ b/Lib/mzscheme/mzrun.swg @@ -125,6 +125,7 @@ struct swig_mz_proxy { Scheme_Type mztype; swig_type_info *type; void *object; + int own; }; static Scheme_Type swig_type; @@ -135,7 +136,7 @@ mz_free_swig(void *p, void *data) { if (SCHEME_NULLP((Scheme_Object*)p) || SCHEME_TYPE((Scheme_Object*)p) != swig_type) return; if (proxy->type) { - if (proxy->type->clientdata) { + if (proxy->type->clientdata && proxy->own) { ((Scheme_Prim *)proxy->type->clientdata)(1, (Scheme_Object **)&proxy); } } @@ -148,7 +149,8 @@ SWIG_MzScheme_NewPointerObj(void *ptr, swig_type_info *type, int owner) { new_proxy->mztype = swig_type; new_proxy->type = type; new_proxy->object = ptr; - if (owner) { + 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; @@ -157,28 +159,42 @@ SWIG_MzScheme_NewPointerObj(void *ptr, swig_type_info *type, int owner) { static int SWIG_MzScheme_ConvertPtr(Scheme_Object *s, void **result, swig_type_info *type, int flags) { swig_cast_info *cast; + int ret = SWIG_ERROR; if (SCHEME_NULLP(s)) { *result = NULL; return (flags & SWIG_POINTER_NO_NULL) ? SWIG_NullReferenceError : SWIG_OK; } else if (SCHEME_TYPE(s) == swig_type) { struct swig_mz_proxy *proxy = (struct swig_mz_proxy *) s; + + if ((flags & SWIG_POINTER_RELEASE) == SWIG_POINTER_RELEASE && !proxy->own) { + return SWIG_ERROR_RELEASE_NOT_OWNED; + } + if (type) { cast = SWIG_TypeCheckStruct(proxy->type, type); if (cast) { int newmemory = 0; *result = SWIG_TypeCast(cast, proxy->object, &newmemory); assert(!newmemory); /* newmemory handling not yet implemented */ - return 0; + ret = SWIG_OK; } else { - return 1; + return SWIG_ERROR; } } else { *result = proxy->object; - return 0; + ret = SWIG_OK; + } + + if (flags & SWIG_POINTER_DISOWN) { + scheme_subtract_finalizer(proxy, mz_free_swig, NULL); + proxy->own = 0; + } + if (flags & SWIG_POINTER_CLEAR) { + proxy->object = 0; } } - return 1; + return ret; } static SWIGINLINE void * diff --git a/Lib/mzscheme/std_auto_ptr.i b/Lib/mzscheme/std_auto_ptr.i new file mode 100644 index 000000000..a903d0063 --- /dev/null +++ b/Lib/mzscheme/std_auto_ptr.i @@ -0,0 +1,36 @@ +/* ----------------------------------------------------------------------------- + * std_auto_ptr.i + * + * SWIG library file for handling std::auto_ptr. + * Memory ownership is passed from the std::auto_ptr C++ layer to the proxy + * class when returning a std::auto_ptr from a function. + * Memory ownership is passed from the proxy class to the std::auto_ptr in the + * 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); + 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 'TYPE *'"); + } else { + %argument_fail(res, "TYPE *", $symname, $argnum); + } + } + $1.reset((TYPE *)argp); +} + +%typemap (out) std::auto_ptr< TYPE > %{ + %set_output(SWIG_NewPointerObj($1.release(), $descriptor(TYPE *), SWIG_POINTER_OWN)); +%} + +%template() std::auto_ptr< TYPE >; +%enddef + +namespace std { + template class auto_ptr {}; +} diff --git a/Lib/mzscheme/std_unique_ptr.i b/Lib/mzscheme/std_unique_ptr.i new file mode 100644 index 000000000..35386a783 --- /dev/null +++ b/Lib/mzscheme/std_unique_ptr.i @@ -0,0 +1,36 @@ +/* ----------------------------------------------------------------------------- + * std_unique_ptr.i + * + * SWIG library file for handling std::unique_ptr. + * Memory ownership is passed from the std::unique_ptr C++ layer to the proxy + * class when returning a std::unique_ptr from a function. + * Memory ownership is passed from the proxy class to the std::unique_ptr in the + * 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); + 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 'TYPE *'"); + } else { + %argument_fail(res, "TYPE *", $symname, $argnum); + } + } + $1.reset((TYPE *)argp); +} + +%typemap (out) std::unique_ptr< TYPE > %{ + %set_output(SWIG_NewPointerObj($1.release(), $descriptor(TYPE *), SWIG_POINTER_OWN)); +%} + +%template() std::unique_ptr< TYPE >; +%enddef + +namespace std { + template class unique_ptr {}; +} diff --git a/Lib/mzscheme/typemaps.i b/Lib/mzscheme/typemaps.i index 0fc947d58..ebd0f28da 100644 --- a/Lib/mzscheme/typemaps.i +++ b/Lib/mzscheme/typemaps.i @@ -2,6 +2,12 @@ * typemaps.i * ----------------------------------------------------------------------------- */ +#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 %as_voidptr(ptr) (void*)(ptr) + + /* The MzScheme module handles all types uniformly via typemaps. Here are the definitions. */ @@ -291,7 +297,6 @@ REF_MAP(double, SCHEME_REALP, scheme_real_to_double, // $2 = ($2_ltype) temp; //} - /* ------------------------------------------------------------ * Typechecking rules * ------------------------------------------------------------ */ From 0ba11023acfc80689ccb58efa91eaf55c2d60e3b Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Sat, 20 Aug 2022 15:09:23 +0100 Subject: [PATCH 629/662] Rename debug in testcases to trace To remove D specific keyword rename --- Examples/test-suite/cpp11_move_only.i | 30 ++++++++----------- .../test-suite/cpp11_move_only_valuewrapper.i | 26 +++++++--------- .../cpp11_rvalue_reference_move_input.i | 18 +++++------ .../test-suite/csharp/li_std_wstring_runme.cs | 4 +-- .../csharp/typemap_out_optimal_runme.cs | 6 ++-- Examples/test-suite/director_pass_by_value.i | 18 +++++------ .../go/typemap_out_optimal_runme.go | 2 +- .../java/typemap_out_optimal_runme.java | 2 +- Examples/test-suite/li_std_wstring.i | 6 ++-- .../test-suite/python/python_pickle_runme.py | 4 +-- .../python/typemap_out_optimal_runme.py | 2 +- Examples/test-suite/python_pickle.i | 6 ++-- Examples/test-suite/typemap_out_optimal.i | 18 +++++------ 13 files changed, 61 insertions(+), 81 deletions(-) diff --git a/Examples/test-suite/cpp11_move_only.i b/Examples/test-suite/cpp11_move_only.i index f97d7090e..732bc49db 100644 --- a/Examples/test-suite/cpp11_move_only.i +++ b/Examples/test-suite/cpp11_move_only.i @@ -1,9 +1,5 @@ %module cpp11_move_only -#if defined(SWIGD) -%rename(trace) debug; -#endif - %include "cpp11_move_only_helper.i" %ignore MoveOnly::operator=; @@ -13,22 +9,22 @@ #include using namespace std; -bool debug = false; +bool trace = false; struct MoveOnly { - MoveOnly(int i = 0) { if (debug) cout << "MoveOnly(" << i << ")" << " " << this << endl; Counter::normal_constructor++; } + MoveOnly(int i = 0) { if (trace) cout << "MoveOnly(" << i << ")" << " " << this << endl; Counter::normal_constructor++; } MoveOnly(const MoveOnly &other) = delete; MoveOnly & operator=(const MoveOnly &other) = delete; - MoveOnly(MoveOnly &&other) noexcept { if (debug) cout << "MoveOnly(MoveOnly &&)" << " " << this << endl; Counter::move_constructor++; } - MoveOnly & operator=(MoveOnly &&other) noexcept { if (debug) cout << "operator=(MoveOnly &&)" << " " << this << endl; Counter::move_assignment++; return *this; } - ~MoveOnly() { if (debug) cout << "~MoveOnly()" << " " << this << endl; Counter::destructor++; } + MoveOnly(MoveOnly &&other) noexcept { if (trace) cout << "MoveOnly(MoveOnly &&)" << " " << this << endl; Counter::move_constructor++; } + MoveOnly & operator=(MoveOnly &&other) noexcept { if (trace) cout << "operator=(MoveOnly &&)" << " " << this << endl; Counter::move_assignment++; return *this; } + ~MoveOnly() { if (trace) cout << "~MoveOnly()" << " " << this << endl; Counter::destructor++; } static MoveOnly create() { return MoveOnly(111); } // static const MoveOnly createConst() { return MoveOnly(111); } // not supported by default - // static void take(MoveOnly mo) { if (debug) cout << "take(MoveOnly)" << " " << &mo << endl; } + // static void take(MoveOnly mo) { if (trace) cout << "take(MoveOnly)" << " " << &mo << endl; } }; %} @@ -39,18 +35,18 @@ struct MoveOnly { %inline %{ // Movable and Copyable struct MovableCopyable { - MovableCopyable(int i = 0) { if (debug) cout << "MovableCopyable(" << i << ")" << " " << this << endl; Counter::normal_constructor++; } + MovableCopyable(int i = 0) { if (trace) cout << "MovableCopyable(" << i << ")" << " " << this << endl; Counter::normal_constructor++; } - MovableCopyable(const MovableCopyable &other) { if (debug) cout << "MovableCopyable(const MovableCopyable &)" << " " << this << " " << &other << endl; Counter::copy_constructor++;} - MovableCopyable & operator=(const MovableCopyable &other) { if (debug) cout << "operator=(const MovableCopyable &)" << " " << this << " " << &other << endl; Counter::copy_assignment++; return *this; } + 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 (debug) cout << "MovableCopyable(MovableCopyable &&)" << " " << this << endl; Counter::move_constructor++; } - MovableCopyable & operator=(MovableCopyable &&other) noexcept { if (debug) cout << "operator=(MovableCopyable &&)" << " " << this << endl; Counter::move_assignment++; return *this; } - ~MovableCopyable() { if (debug) cout << "~MovableCopyable()" << " " << this << endl; Counter::destructor++; } + 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 MovableCopyable create() { return MovableCopyable(111); } static const MovableCopyable createConst() { return MovableCopyable(111); } - static void take(MovableCopyable mc) { if (debug) cout << "take(MovableCopyable)" << " " << &mc << endl; } + static void take(MovableCopyable mc) { if (trace) cout << "take(MovableCopyable)" << " " << &mc << endl; } }; %} diff --git a/Examples/test-suite/cpp11_move_only_valuewrapper.i b/Examples/test-suite/cpp11_move_only_valuewrapper.i index bde95f014..a4194ea86 100644 --- a/Examples/test-suite/cpp11_move_only_valuewrapper.i +++ b/Examples/test-suite/cpp11_move_only_valuewrapper.i @@ -37,26 +37,22 @@ namespace std { #endif %} -#if defined(SWIGD) -%rename(trace) debug; -#endif - %include "cpp11_move_only_helper.i" %valuewrapper XXX; %ignore XXX::operator=; %inline %{ -bool debug = false; +bool trace = false; struct XXX { - XXX(int i = 0) { if (debug) cout << "XXX(" << i << ")" << " " << this << endl; Counter::normal_constructor++; } - XXX(const XXX &other) { if (debug) cout << "XXX(const XXX &)" << " " << this << " " << &other << endl; Counter::copy_constructor++;} - XXX & operator=(const XXX &other) { if (debug) cout << "operator=(const XXX &)" << " " << this << " " << &other << endl; Counter::copy_assignment++; return *this; } + XXX(int i = 0) { if (trace) cout << "XXX(" << i << ")" << " " << this << endl; Counter::normal_constructor++; } + XXX(const XXX &other) { if (trace) cout << "XXX(const XXX &)" << " " << this << " " << &other << endl; Counter::copy_constructor++;} + XXX & operator=(const XXX &other) { if (trace) cout << "operator=(const XXX &)" << " " << this << " " << &other << endl; Counter::copy_assignment++; return *this; } #if defined(__cplusplus) && __cplusplus >= 201103L - XXX(XXX &&other) noexcept { if (debug) cout << "XXX(XXX &&)" << " " << this << endl; Counter::move_constructor++; } - XXX & operator=(XXX &&other) noexcept { if (debug) cout << "operator=(XXX &&)" << " " << this << endl; Counter::move_assignment++; return *this; } + XXX(XXX &&other) noexcept { if (trace) cout << "XXX(XXX &&)" << " " << this << endl; Counter::move_constructor++; } + XXX & operator=(XXX &&other) noexcept { if (trace) cout << "operator=(XXX &&)" << " " << this << endl; Counter::move_assignment++; return *this; } #endif - ~XXX() { if (debug) cout << "~XXX()" << " " << this << endl; Counter::destructor++; } + ~XXX() { if (trace) cout << "~XXX()" << " " << this << endl; Counter::destructor++; } }; bool has_cplusplus11() { @@ -73,7 +69,7 @@ void cleanup(std::unique_ptr* p); %{ std::unique_ptr makeUniqueXXX() { - if (debug) cout << "makeUniqueXXX()" << endl; + if (trace) cout << "makeUniqueXXX()" << endl; return std::unique_ptr(new XXX(11)); } void cleanup(std::unique_ptr* p) { @@ -84,15 +80,15 @@ typedef XXX UUU; %inline %{ XXX createXXX() { - if (debug) cout << "createXXX()" << endl; + if (trace) cout << "createXXX()" << endl; return XXX(111); } XXX createXXX2() { - if (debug) cout << "createXXX2()" << endl; + if (trace) cout << "createXXX2()" << endl; return XXX(222); } UUU createUnknownType() { - if (debug) cout << "createXXX2()" << endl; + if (trace) cout << "createXXX2()" << endl; return XXX(222); } struct YYY {}; diff --git a/Examples/test-suite/cpp11_rvalue_reference_move_input.i b/Examples/test-suite/cpp11_rvalue_reference_move_input.i index 03abd7322..69b4fd858 100644 --- a/Examples/test-suite/cpp11_rvalue_reference_move_input.i +++ b/Examples/test-suite/cpp11_rvalue_reference_move_input.i @@ -2,10 +2,6 @@ // Testcase for testing rvalue reference input typemaps which assume the object is moved during a function call -#if defined(SWIGD) -%rename(trace) debug; -#endif - %include "cpp11_move_only_helper.i" %rename(MoveAssign) MovableCopyable::operator=(MovableCopyable &&); @@ -16,18 +12,18 @@ #include using namespace std; -bool debug = false; +bool trace = false; class MovableCopyable { public: - MovableCopyable(int i = 0) { if (debug) cout << "MovableCopyable(" << i << ")" << " " << this << endl; Counter::normal_constructor++; } + MovableCopyable(int i = 0) { if (trace) cout << "MovableCopyable(" << i << ")" << " " << this << endl; Counter::normal_constructor++; } - MovableCopyable(const MovableCopyable &other) { if (debug) cout << "MovableCopyable(const MovableCopyable &)" << " " << this << " " << &other << endl; Counter::copy_constructor++;} - MovableCopyable & operator=(const MovableCopyable &other) { if (debug) cout << "operator=(const MovableCopyable &)" << " " << this << " " << &other << endl; Counter::copy_assignment++; return *this; } + 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 (debug) cout << "MovableCopyable(MovableCopyable &&)" << " " << this << endl; Counter::move_constructor++; } - MovableCopyable & operator=(MovableCopyable &&other) noexcept { if (debug) cout << "operator=(MovableCopyable &&)" << " " << this << endl; Counter::move_assignment++; return *this; } - ~MovableCopyable() { if (debug) cout << "~MovableCopyable()" << " " << this << endl; Counter::destructor++; } + 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); diff --git a/Examples/test-suite/csharp/li_std_wstring_runme.cs b/Examples/test-suite/csharp/li_std_wstring_runme.cs index 21c225e5f..d2be3d1ff 100644 --- a/Examples/test-suite/csharp/li_std_wstring_runme.cs +++ b/Examples/test-suite/csharp/li_std_wstring_runme.cs @@ -30,7 +30,7 @@ public class runme static private void check_equal(string a, string b) { - if (li_std_wstring.debug) { + if (li_std_wstring.trace) { Console.WriteLine("check_equal {0} {1}", a, b); display_bytes(a); display_bytes(b); @@ -150,7 +150,7 @@ public class runme foreach (string expected in test_strings) { - if (li_std_wstring.debug) + if (li_std_wstring.trace) Console.WriteLine("expected (C#): " + expected); string received = li_std_wstring.test_value(expected); check_equal(received, expected); diff --git a/Examples/test-suite/csharp/typemap_out_optimal_runme.cs b/Examples/test-suite/csharp/typemap_out_optimal_runme.cs index 0d697498a..0d4254eef 100644 --- a/Examples/test-suite/csharp/typemap_out_optimal_runme.cs +++ b/Examples/test-suite/csharp/typemap_out_optimal_runme.cs @@ -4,11 +4,11 @@ using typemap_out_optimalNamespace; public class typemap_out_optimal_runme { public static void Main() { - XX.debug = false; - if (XX.debug) + XX.trace = false; + if (XX.trace) Console.WriteLine("calling create()"); using (XX x = XX.create()) { } - if (XX.debug) + if (XX.trace) Console.WriteLine("calling createConst()"); using (XX x = XX.createConst()) { } } diff --git a/Examples/test-suite/director_pass_by_value.i b/Examples/test-suite/director_pass_by_value.i index 5e31c9d3b..6eb62f035 100644 --- a/Examples/test-suite/director_pass_by_value.i +++ b/Examples/test-suite/director_pass_by_value.i @@ -1,9 +1,5 @@ %module(directors="1") director_pass_by_value -#if defined(SWIGD) -%rename(trace) debug; -#endif - %director DirectorPassByValueAbstractBase; %include "cpp11_move_only_helper.i" @@ -14,17 +10,17 @@ %inline %{ #include using namespace std; -int debug = false; +int trace = false; struct PassedByValue { - PassedByValue(int v = 0x12345678) { val = v; if (debug) cout << "PassedByValue(0x" << hex << val << ")" << " " << this << endl; Counter::normal_constructor++; } + PassedByValue(int v = 0x12345678) { val = v; if (trace) cout << "PassedByValue(0x" << hex << val << ")" << " " << this << endl; Counter::normal_constructor++; } - PassedByValue(const PassedByValue &other) { val = other.val; if (debug) cout << "PassedByValue(const PassedByValue &)" << " " << this << " " << &other << endl; Counter::copy_constructor++;} - PassedByValue & operator=(const PassedByValue &other) { val = other.val; if (debug) cout << "operator=(const PassedByValue &)" << " " << this << " " << &other << endl; Counter::copy_assignment++; return *this; } + PassedByValue(const PassedByValue &other) { val = other.val; if (trace) cout << "PassedByValue(const PassedByValue &)" << " " << this << " " << &other << endl; Counter::copy_constructor++;} + PassedByValue & operator=(const PassedByValue &other) { val = other.val; if (trace) cout << "operator=(const PassedByValue &)" << " " << this << " " << &other << endl; Counter::copy_assignment++; return *this; } #if __cplusplus >= 201103L - PassedByValue(PassedByValue &&other) noexcept { val = other.val; if (debug) cout << "PassedByValue(PassedByValue &&)" << " " << this << endl; Counter::move_constructor++; } - PassedByValue & operator=(PassedByValue &&other) noexcept { val = other.val; if (debug) cout << "operator=(PassedByValue &&)" << " " << this << endl; Counter::move_assignment++; return *this; } - ~PassedByValue() { if (debug) cout << "~PassedByValue()" << " " << this << endl; Counter::destructor++; } + PassedByValue(PassedByValue &&other) noexcept { val = other.val; if (trace) cout << "PassedByValue(PassedByValue &&)" << " " << this << endl; Counter::move_constructor++; } + PassedByValue & operator=(PassedByValue &&other) noexcept { val = other.val; if (trace) cout << "operator=(PassedByValue &&)" << " " << this << endl; Counter::move_assignment++; return *this; } + ~PassedByValue() { if (trace) cout << "~PassedByValue()" << " " << this << endl; Counter::destructor++; } #endif int getVal() { return val; } diff --git a/Examples/test-suite/go/typemap_out_optimal_runme.go b/Examples/test-suite/go/typemap_out_optimal_runme.go index 0467ce293..646aa8ece 100644 --- a/Examples/test-suite/go/typemap_out_optimal_runme.go +++ b/Examples/test-suite/go/typemap_out_optimal_runme.go @@ -3,7 +3,7 @@ package main import . "swigtests/typemap_out_optimal" func main() { - SetXXDebug(false) + SetXXTrace(false) _ = XXCreate() _ = XXCreateConst() } diff --git a/Examples/test-suite/java/typemap_out_optimal_runme.java b/Examples/test-suite/java/typemap_out_optimal_runme.java index b48e5d697..254b0c6b6 100644 --- a/Examples/test-suite/java/typemap_out_optimal_runme.java +++ b/Examples/test-suite/java/typemap_out_optimal_runme.java @@ -13,7 +13,7 @@ public class typemap_out_optimal_runme { } public static void main(String argv[]) { - XX.setDebug(false); + XX.setTrace(false); { XX x = XX.create(); x.delete(); diff --git a/Examples/test-suite/li_std_wstring.i b/Examples/test-suite/li_std_wstring.i index 43031679a..88f80beb4 100644 --- a/Examples/test-suite/li_std_wstring.i +++ b/Examples/test-suite/li_std_wstring.i @@ -23,7 +23,7 @@ #include #include -bool debug = false; +bool trace = false; void show_wstring_bytes(const std::wstring &s) { unsigned char *p = (unsigned char *)s.data(); @@ -59,7 +59,7 @@ wchar_t* test_wchar_overload(wchar_t *x) { } std::wstring test_value(std::wstring x) { - if (debug) { + if (trace) { std::wcout << "received(C++): " /*<< x */<< std::endl; show_wstring_bytes(x); } @@ -80,7 +80,7 @@ void test_reference(std::wstring &x) { } bool test_equal(const wchar_t *wcs, const std::wstring& s) { - if (debug) { + if (trace) { show_wstring_bytes(wcs); show_wstring_bytes(s); } diff --git a/Examples/test-suite/python/python_pickle_runme.py b/Examples/test-suite/python/python_pickle_runme.py index cbe425fa2..7cb07ef59 100644 --- a/Examples/test-suite/python/python_pickle_runme.py +++ b/Examples/test-suite/python/python_pickle_runme.py @@ -8,13 +8,13 @@ def check(p): if msg != "hi there": raise RuntimeError("Bad, got: " + msg) -python_pickle.cvar.debug = False +python_pickle.cvar.trace = False p = python_pickle.PickleMe("hi there") check(p) r = p.__reduce__() -if python_pickle.cvar.debug: +if python_pickle.cvar.trace: print("__reduce__ returned: {}".format(r)) pickle_string = pickle.dumps(p) newp = pickle.loads(pickle_string) diff --git a/Examples/test-suite/python/typemap_out_optimal_runme.py b/Examples/test-suite/python/typemap_out_optimal_runme.py index beed46bfc..6f6cc5490 100644 --- a/Examples/test-suite/python/typemap_out_optimal_runme.py +++ b/Examples/test-suite/python/typemap_out_optimal_runme.py @@ -1,6 +1,6 @@ from typemap_out_optimal import * -cvar.XX_debug = False +cvar.XX_trace = False x = XX.create() del x x = XX.createConst() diff --git a/Examples/test-suite/python_pickle.i b/Examples/test-suite/python_pickle.i index fbb3d05a8..10be972a0 100644 --- a/Examples/test-suite/python_pickle.i +++ b/Examples/test-suite/python_pickle.i @@ -14,7 +14,7 @@ def __reduce__(self): #else // Equivalent to Python code above PyObject *__reduce__() { - if (debug) + if (trace) std::cout << "In C++ __reduce__" << std::endl; PyObject *args = PyTuple_New(1); PyTuple_SetItem(args, 0, SWIG_From_std_string(self->msg)); @@ -39,12 +39,12 @@ def __reduce__(self): %inline %{ #include -bool debug = false; +bool trace = false; struct PickleMe { std::string msg; PickleMe(const std::string& msg) : msg(msg) { - if (debug) + if (trace) std::cout << "In C++ constructor " << " [" << msg << "]" << std::endl; } }; diff --git a/Examples/test-suite/typemap_out_optimal.i b/Examples/test-suite/typemap_out_optimal.i index 11f1db80f..46809d117 100644 --- a/Examples/test-suite/typemap_out_optimal.i +++ b/Examples/test-suite/typemap_out_optimal.i @@ -18,20 +18,16 @@ %ignore XX::operator=; -#ifdef SWIGD -%rename(trace) XX::debug; -#endif - %inline %{ #include using namespace std; struct XX { - XX() { if (debug) cout << "XX()" << endl; } - XX(int i) { if (debug) cout << "XX(" << i << ")" << endl; } - XX(const XX &other) { if (debug) cout << "XX(const XX &)" << endl; } - XX& operator =(const XX &other) { if (debug) cout << "operator=(const XX &)" << endl; return *this; } - ~XX() { if (debug) cout << "~XX()" << endl; } + XX() { if (trace) cout << "XX()" << endl; } + XX(int i) { if (trace) cout << "XX(" << i << ")" << endl; } + XX(const XX &other) { if (trace) cout << "XX(const XX &)" << endl; } + XX& operator =(const XX &other) { if (trace) cout << "operator=(const XX &)" << endl; return *this; } + ~XX() { if (trace) cout << "~XX()" << endl; } // Note: best observed RVO for C#, Java and Python with g++-6 to g++-10 (just one constructor and one destructor call) static XX create() { @@ -40,8 +36,8 @@ struct XX { static const XX createConst() { return XX(456); } - static bool debug; + static bool trace; }; -bool XX::debug = true; +bool XX::trace = true; %} From ec965840ce3fa59a9f09e9d09fefacaa617b54d5 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Sat, 20 Aug 2022 15:23:15 +0100 Subject: [PATCH 630/662] 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 631/662] 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 632/662] 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 633/662] 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 634/662] 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 635/662] 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 636/662] 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 637/662] 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 638/662] 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 891367d7921852e51118149fbb94332c261643d8 Mon Sep 17 00:00:00 2001 From: Alex <93376818+sashashura@users.noreply.github.com> Date: Fri, 2 Sep 2022 17:07:45 +0100 Subject: [PATCH 639/662] Update ci.yml Signed-off-by: sashashura <93376818+sashashura@users.noreply.github.com> --- .github/workflows/ci.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 700fcc12e..6fd1ff8b9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -13,6 +13,9 @@ on: - 'Doc/**' - 'appveyor.yml' +permissions: + contents: read + jobs: build: From 4c58bb558f3e4cd4a4870c6bb4a4a9af2e7ba5e0 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Fri, 2 Sep 2022 19:17:38 +0100 Subject: [PATCH 640/662] 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 2a0abbb7f6ddab87463d7c9bc97917238e25784b Mon Sep 17 00:00:00 2001 From: Clinton Stimpson Date: Fri, 2 Sep 2022 14:29:49 -0600 Subject: [PATCH 641/662] Python: Use PyType_Modified() instead of modifying flags. Closes #2345 Also supported with Py_LIMITED_API --- Lib/python/pyrun.swg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib/python/pyrun.swg b/Lib/python/pyrun.swg index a1ac95baf..0dcbc1ce5 100644 --- a/Lib/python/pyrun.swg +++ b/Lib/python/pyrun.swg @@ -1515,7 +1515,7 @@ SWIG_Python_NewShadowInstance(SwigPyClientData *data, PyObject *swig_this) Py_DECREF(inst); inst = 0; } else { - Py_TYPE(inst)->tp_flags &= ~Py_TPFLAGS_VALID_VERSION_TAG; + PyType_Modified(Py_TYPE(inst)); } } } From de13a0020b11c7bc20da3c3cba9c8b211a869d73 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Sat, 3 Sep 2022 05:37:13 +0100 Subject: [PATCH 642/662] 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 643/662] 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 644/662] 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 645/662] 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 646/662] 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 e683168018558f4e73dc26629c4bbec224d23438 Mon Sep 17 00:00:00 2001 From: Clinton Stimpson Date: Tue, 30 Aug 2022 14:33:15 -0600 Subject: [PATCH 647/662] Use PyObject instead of PySliceObject throughout with Python 3.2+ This supports use of the Py_LIMITED_API. --- Lib/python/pycontainer.swg | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/Lib/python/pycontainer.swg b/Lib/python/pycontainer.swg index 2ddf4c375..d6fdff087 100644 --- a/Lib/python/pycontainer.swg +++ b/Lib/python/pycontainer.swg @@ -15,9 +15,9 @@ #include #if PY_VERSION_HEX >= 0x03020000 -# define SWIGPY_SLICE_ARG(obj) ((PyObject*) (obj)) +# define SWIGPY_SLICEOBJECT PyObject #else -# define SWIGPY_SLICE_ARG(obj) ((PySliceObject*) (obj)) +# define SWIGPY_SLICEOBJECT PySliceObject #endif %} @@ -781,7 +781,7 @@ namespace swig #if 1 %newobject __getslice__; #endif - %newobject __getitem__(PySliceObject *slice); + %newobject __getitem__(SWIGPY_SLICEOBJECT *slice); #if defined(SWIGPYTHON_BUILTIN) %feature("python:slot", "nb_nonzero", functype="inquiry") __nonzero__; @@ -829,13 +829,13 @@ namespace swig %extend { /* typemap for slice object support */ - %typemap(in) PySliceObject* { + %typemap(in) SWIGPY_SLICEOBJECT* { if (!PySlice_Check($input)) { %argument_fail(SWIG_TypeError, "$type", $symname, $argnum); } - $1 = (PySliceObject *) $input; + $1 = (SWIGPY_SLICEOBJECT *) $input; } - %typemap(typecheck,precedence=SWIG_TYPECHECK_POINTER) PySliceObject* { + %typemap(typecheck,precedence=SWIG_TYPECHECK_POINTER) SWIGPY_SLICEOBJECT* { $1 = PySlice_Check($input); } @@ -865,49 +865,49 @@ namespace swig /* Overloaded methods for Python 3 compatibility * (Also useful in Python 2.x) */ - Sequence* __getitem__(PySliceObject *slice) throw (std::out_of_range, std::invalid_argument) { + Sequence* __getitem__(SWIGPY_SLICEOBJECT *slice) throw (std::out_of_range, std::invalid_argument) { Py_ssize_t i, j, step; if( !PySlice_Check(slice) ) { SWIG_Error(SWIG_TypeError, "Slice object expected."); return NULL; } - PySlice_GetIndices(SWIGPY_SLICE_ARG(slice), (Py_ssize_t)self->size(), &i, &j, &step); + PySlice_GetIndices(slice, (Py_ssize_t)self->size(), &i, &j, &step); Sequence::difference_type id = i; Sequence::difference_type jd = j; return swig::getslice(self, id, jd, step); } - void __setitem__(PySliceObject *slice, const Sequence& v) throw (std::out_of_range, std::invalid_argument) { + void __setitem__(SWIGPY_SLICEOBJECT *slice, const Sequence& v) throw (std::out_of_range, std::invalid_argument) { Py_ssize_t i, j, step; if( !PySlice_Check(slice) ) { SWIG_Error(SWIG_TypeError, "Slice object expected."); return; } - PySlice_GetIndices(SWIGPY_SLICE_ARG(slice), (Py_ssize_t)self->size(), &i, &j, &step); + PySlice_GetIndices(slice, (Py_ssize_t)self->size(), &i, &j, &step); Sequence::difference_type id = i; Sequence::difference_type jd = j; swig::setslice(self, id, jd, step, v); } - void __setitem__(PySliceObject *slice) throw (std::out_of_range, std::invalid_argument) { + void __setitem__(SWIGPY_SLICEOBJECT *slice) throw (std::out_of_range, std::invalid_argument) { Py_ssize_t i, j, step; if( !PySlice_Check(slice) ) { SWIG_Error(SWIG_TypeError, "Slice object expected."); return; } - PySlice_GetIndices(SWIGPY_SLICE_ARG(slice), (Py_ssize_t)self->size(), &i, &j, &step); + PySlice_GetIndices(slice, (Py_ssize_t)self->size(), &i, &j, &step); Sequence::difference_type id = i; Sequence::difference_type jd = j; swig::delslice(self, id, jd, step); } - void __delitem__(PySliceObject *slice) throw (std::out_of_range, std::invalid_argument) { + void __delitem__(SWIGPY_SLICEOBJECT *slice) throw (std::out_of_range, std::invalid_argument) { Py_ssize_t i, j, step; if( !PySlice_Check(slice) ) { SWIG_Error(SWIG_TypeError, "Slice object expected."); return; } - PySlice_GetIndices(SWIGPY_SLICE_ARG(slice), (Py_ssize_t)self->size(), &i, &j, &step); + PySlice_GetIndices(slice, (Py_ssize_t)self->size(), &i, &j, &step); Sequence::difference_type id = i; Sequence::difference_type jd = j; swig::delslice(self, id, jd, step); From 2212af3f4f0906d84ef3aecf4812622af5f3ec7e Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Thu, 8 Sep 2022 08:46:32 +0100 Subject: [PATCH 648/662] 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 From 0a0743f25cc0bbb395d03a27ac62887c8cbee5cf Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Fri, 9 Sep 2022 08:44:39 +0100 Subject: [PATCH 649/662] Temporarily remove Octave concatenation test broken in octave-7.2.0 --- Examples/octave/operator/runme.m | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/Examples/octave/operator/runme.m b/Examples/octave/operator/runme.m index d88dcff0b..41c2c14a7 100644 --- a/Examples/octave/operator/runme.m +++ b/Examples/octave/operator/runme.m @@ -46,6 +46,7 @@ if swig_octave_prereq(3,8,0) printf("exp(a) = %s\n", disp(exp(a))); endif -# concatenation operator -g = [a, b, c]; -printf("g = %s\n",disp(g)); +# concatenation operator, note: calls @swig_ref/horzcat.m +# g = [a, b, c]; +# printf("g = %s\n",disp(g)); +# Above temporarily removed as broken in octave-7.2.0, see https://github.com/swig/swig/issues/2353 From 26c0a0c152bdb3dfa700c65244ad08406588fd65 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Fri, 9 Sep 2022 19:01:54 +0100 Subject: [PATCH 650/662] CHANGES file tweaks --- CHANGES.current | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/CHANGES.current b/CHANGES.current index 1d99fd0fc..d931cce06 100644 --- a/CHANGES.current +++ b/CHANGES.current @@ -17,6 +17,8 @@ Version 4.1.0 (in progress) so that the (moved from, but still valid) C++ object cannot be used again and the the object is additionally deleted. + *** POTENTIAL INCOMPATIBILITY *** + 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 @@ -122,11 +124,11 @@ Version 4.1.0 (in progress) supported by Apple for over 20 years now. 2022-07-12: wsfulton - Performance optimisation for parameters passed by value that are C++11 movable. + #999 Performance optimisation for parameters passed by value that are C++11 movable. The C++ wrappers create a temporary variable for a parameter to be passed to a function. This is initially default constructed and then copy assigned from the instance being passed in from the target language. This is unchanged, however, - when the temporary variable is passed to wrapped function, it is now done using + when the temporary variable is passed to the wrapped function, it is now done using std::move. If the type is move constructible, the move constructor will be used instead of the copy constructor. @@ -153,7 +155,7 @@ Version 4.1.0 (in progress) receiver argument from p to swig_p. 2022-07-03: wsfulton - Performance optimisation for directors for classes passed by value. The directorin + #999 Performance optimisation for directors for classes passed by value. The directorin typemaps in the director methods now use std::move on the input parameter when copying the object from the stack to the heap prior to the callback into the target language, thereby taking advantage of move semantics if available. From dcb2544a439d446cf8fd309bec252b0616181328 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Fri, 9 Sep 2022 05:55:54 +0100 Subject: [PATCH 651/662] Visual C++ debug builds linking to Python release builds Only use the corecrt.h workaround for #2090 when using SWIG_PYTHON_INTERPRETER_NO_DEBUG as the problem seems to only occur when undefining _DEBUG. Also extend workaround for Visual Studio 2019 version 16.10 and 16.11 as per #2174 (_MSC_VER=1929). --- Lib/python/pyruntime.swg | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/Lib/python/pyruntime.swg b/Lib/python/pyruntime.swg index 74669a74f..eabc829c0 100644 --- a/Lib/python/pyruntime.swg +++ b/Lib/python/pyruntime.swg @@ -4,13 +4,6 @@ # include #endif -#if defined(_MSC_VER) && _MSC_VER >= 1930 -/* Workaround what seems to be a bug in the Python headers with MSVC 2022. - * https://github.com/swig/swig/issues/2090 - */ -# include -#endif - #ifndef SWIG_NO_PY_SSIZE_T_CLEAN #define PY_SSIZE_T_CLEAN #endif @@ -24,6 +17,14 @@ #if defined(_DEBUG) && defined(SWIG_PYTHON_INTERPRETER_NO_DEBUG) /* Use debug wrappers with the Python release dll */ + +#if defined(_MSC_VER) && _MSC_VER >= 1929 +/* Workaround what seems to be a bug in the Python headers with MSVC 2022. + * https://github.com/swig/swig/issues/2090 + */ +# include +#endif + # undef _DEBUG # include # define _DEBUG 1 From 0c2d0fea0fa882cc92ba40635ef09524deea4eea Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Fri, 9 Sep 2022 07:49:48 +0100 Subject: [PATCH 652/662] Move SwigValueWrapper to header section Recent change to SwigValueWrapper required the header. Included headers should be after the include of the language specific header files (which go into the earlier runtime section). Testcase required -Winit-list-lifetime warning suppression change for Perl which somehow lost the warning suppression when put into the %begin section. --- Examples/test-suite/cpp11_initializer_list.i | 2 +- Lib/swig.swg | 9 ++++----- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/Examples/test-suite/cpp11_initializer_list.i b/Examples/test-suite/cpp11_initializer_list.i index b309576c1..c1646248c 100644 --- a/Examples/test-suite/cpp11_initializer_list.i +++ b/Examples/test-suite/cpp11_initializer_list.i @@ -10,7 +10,7 @@ $1 = {"Ab", "Fab"}; %} -%begin %{ +%runtime %{ #if __GNUC__ >= 9 /* warning: ‘new’ of initializer_list does not extend the lifetime of the underlying array [-Winit-list-lifetime] */ /* incorrect warning for C::C(std::initializer_list) */ diff --git a/Lib/swig.swg b/Lib/swig.swg index 9148c9153..6cac0e377 100644 --- a/Lib/swig.swg +++ b/Lib/swig.swg @@ -665,7 +665,9 @@ namespace std { */ #ifdef __cplusplus -%insert("runtime") %{ +// Placed in the header section to ensure the language specific header files are +// the first included headers and not +%insert("header") %{ #ifdef __cplusplus #include /* SwigValueWrapper is described in swig.swg */ @@ -688,7 +690,7 @@ public: operator T&() const { return *pointer.ptr; } #endif T *operator&() const { return pointer.ptr; } -};%} +}; /* * SwigValueInit() is a generic initialisation solution as the following approach: @@ -699,13 +701,10 @@ public: * * unsigned int c_result = unsigned int(); */ -%insert("runtime") %{ template T SwigValueInit() { return T(); } -%} -%insert("runtime") %{ #if __cplusplus >=201103L # define SWIG_STD_MOVE(OBJ) std::move(OBJ) #else From c09020853d8f6feddd003ebdb8b8a424b3c142ed Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Fri, 9 Sep 2022 22:15:07 +0100 Subject: [PATCH 653/662] Update comments re _DEBUG redefinition before including Python.h --- Lib/python/pyruntime.swg | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/Lib/python/pyruntime.swg b/Lib/python/pyruntime.swg index eabc829c0..aa2ecfe08 100644 --- a/Lib/python/pyruntime.swg +++ b/Lib/python/pyruntime.swg @@ -19,9 +19,8 @@ /* Use debug wrappers with the Python release dll */ #if defined(_MSC_VER) && _MSC_VER >= 1929 -/* Workaround what seems to be a bug in the Python headers with MSVC 2022. - * https://github.com/swig/swig/issues/2090 - */ +/* Workaround compilation errors when redefining _DEBUG in MSVC 2019 version 16.10 and later + * See https://github.com/swig/swig/issues/2090 */ # include #endif From ad1688055dea4f07cd4023d5e0301d97f7759151 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Fri, 9 Sep 2022 22:53:07 +0100 Subject: [PATCH 654/662] Correct TCL integers testcase for 32-bit platforms --- Examples/test-suite/tcl/integers_runme.tcl | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Examples/test-suite/tcl/integers_runme.tcl b/Examples/test-suite/tcl/integers_runme.tcl index c04dd1e9e..261c4c289 100644 --- a/Examples/test-suite/tcl/integers_runme.tcl +++ b/Examples/test-suite/tcl/integers_runme.tcl @@ -2,12 +2,14 @@ if [ catch { load ./integers[info sharedlibextension] integers} err_msg ] { puts stderr "Could not load shared object:\n$err_msg" } -set val 3902408827 +# 32-bit long max +set val 2147483647 if {[signed_long_identity $val] != $val} { puts stderr "Runtime test 1 failed" exit 1 } +set val 3902408827 if {[unsigned_long_identity $val] != $val} { puts stderr "Runtime test 2 failed" exit 1 From 7eb54a38b1af7837b85e42f85c169d8a421575e2 Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Wed, 14 Sep 2022 10:11:36 +1200 Subject: [PATCH 655/662] Note workaround for -DFOO change Code relying on FOO being defined as empty needs to change, but can just use -DFOO= instead and remain compatible with older SWIG. Fixes #2363 --- CHANGES.current | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGES.current b/CHANGES.current index d931cce06..cd985e863 100644 --- a/CHANGES.current +++ b/CHANGES.current @@ -657,6 +657,12 @@ Version 4.1.0 (in progress) consistency with C/C++ compiler preprocessors. Previously SWIG set FOO to an empty value. + Existing invocations of SWIG with `-DFOO` where the empty value + matters can be updated to `-DFOO=` which should work with both + old and new releases of SWIG. + + *** POTENTIAL INCOMPATIBILITY *** + 2022-02-06: sethrj #2194 Classes that are non-assignable due to const data or const reference members are now automatically detected. From adc2fa966451074052276dab79e5549cd8694fe2 Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Wed, 14 Sep 2022 11:30:28 +1200 Subject: [PATCH 656/662] Fix default_args_runme.php for 32-bit platforms On 32-bit platforms -2147483648 is a PHP float (rather than PHP int on 64-bit platforms) so only check equivalence rather than strict equality. Fixes #2360 --- Examples/test-suite/php/default_args_runme.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Examples/test-suite/php/default_args_runme.php b/Examples/test-suite/php/default_args_runme.php index c793b08af..59350644f 100644 --- a/Examples/test-suite/php/default_args_runme.php +++ b/Examples/test-suite/php/default_args_runme.php @@ -111,7 +111,10 @@ check::equal($tricky->value_m01(10), -1, "trickyvalue_m01 failed"); check::equal($tricky->booltest2(), True, "booltest2 failed"); check::equal($tricky->max_32bit_int1(), 0x7FFFFFFF, "max_32bit_int1 failed"); -check::equal($tricky->min_32bit_int1(), -2147483648, "min_32bit_int1 failed"); +// On 32-bit platforms -2147483648 is a PHP float (rather than +// PHP int on 64-bit platforms) so only check equivalence rather +// than strict equality. +check::equivalent($tricky->min_32bit_int1(), -2147483648, "min_32bit_int1 failed"); check::equal($tricky->max_32bit_int2(), 0x7FFFFFFF, "max_32bit_int2 failed"); $tricky->too_big_32bit_int1(); From de65875955b236ee2644014e41bdeb1d574acc93 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Fri, 16 Sep 2022 08:02:51 +0100 Subject: [PATCH 657/662] .gitignore for Lua examples --- .gitignore | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/.gitignore b/.gitignore index b51da0fdf..4fee29d54 100644 --- a/.gitignore +++ b/.gitignore @@ -160,6 +160,14 @@ Examples/java/doxygen/javadocs Examples/test-suite/javascript/*/ *.gyp +# Lua +Examples/lua/dual/dual +Examples/lua/dual/swigluarun.h +Examples/lua/embed/embed +Examples/lua/embed2/embed2 +Examples/lua/embed3/embed3 +Examples/lua/embed3/swigluarun.h + # OCaml Examples/test-suite/ocaml/*.ml* Examples/test-suite/ocaml/*.cm* From dad7c93ca0a923e7d2671347cee711d180dd0338 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Fri, 16 Sep 2022 08:36:25 +0100 Subject: [PATCH 658/662] Provide SWIGTYPE MOVE typemaps in swigmove.i For implementing full move semantics when passing parameters by value. Based on SWIGTYPE && and std::unique_ptr typemaps which implement move semantics. Added for all languages, but untested for: Go, Ocaml, R, Scilab (and unlikely to be fully functional for same reasons as for std::unique_ptr support). Issue #999 --- CHANGES.current | 4 + Doc/Manual/CPlusPlus11.html | 194 +++++++++++++++++- Doc/Manual/Contents.html | 2 +- Examples/test-suite/common.mk | 5 +- Examples/test-suite/cpp11_move_only.i | 23 ++- Examples/test-suite/cpp11_move_typemaps.i | 12 ++ .../csharp/cpp11_move_typemaps_runme.cs | 37 ++++ .../d/cpp11_move_typemaps_runme.1.d | 42 ++++ .../d/cpp11_move_typemaps_runme.2.d | 42 ++++ .../guile/cpp11_move_typemaps_runme.scm | 3 + .../java/cpp11_move_typemaps_runme.java | 51 +++++ .../javascript/cpp11_move_typemaps_runme.js | 30 +++ .../lua/cpp11_move_typemaps_runme.lua | 28 +++ .../mzscheme/cpp11_move_typemaps_runme.scm | 35 ++++ .../octave/cpp11_move_typemaps_runme.m | 37 ++++ .../perl5/cpp11_move_typemaps_runme.pl | 34 +++ .../php/cpp11_move_typemaps_runme.php | 32 +++ .../python/cpp11_move_typemaps_runme.py | 29 +++ .../ruby/cpp11_move_typemaps_runme.rb | 36 ++++ .../schemerunme/cpp11_move_typemaps.scm | 23 +++ .../tcl/cpp11_move_typemaps_runme.tcl | 35 ++++ Lib/csharp/swigmove.i | 16 ++ Lib/d/swigmove.i | 16 ++ Lib/go/swigmove.i | 15 ++ Lib/guile/swigmove.i | 19 ++ Lib/java/swigmove.i | 16 ++ Lib/javascript/jsc/swigmove.i | 1 + Lib/javascript/v8/swigmove.i | 1 + Lib/lua/swigmove.i | 18 ++ Lib/mzscheme/swigmove.i | 19 ++ Lib/ocaml/swigmove.i | 11 + Lib/octave/swigmove.i | 1 + Lib/perl5/swigmove.i | 1 + Lib/php/swigmove.i | 24 +++ Lib/python/swigmove.i | 1 + Lib/r/swigmove.i | 1 + Lib/ruby/swigmove.i | 1 + Lib/scilab/swigmove.i | 1 + Lib/swig.swg | 12 ++ Lib/tcl/swigmove.i | 1 + Lib/typemaps/swigmove.swg | 19 ++ 41 files changed, 909 insertions(+), 19 deletions(-) create mode 100644 Examples/test-suite/cpp11_move_typemaps.i create mode 100644 Examples/test-suite/csharp/cpp11_move_typemaps_runme.cs create mode 100644 Examples/test-suite/d/cpp11_move_typemaps_runme.1.d create mode 100644 Examples/test-suite/d/cpp11_move_typemaps_runme.2.d create mode 100644 Examples/test-suite/guile/cpp11_move_typemaps_runme.scm create mode 100644 Examples/test-suite/java/cpp11_move_typemaps_runme.java create mode 100644 Examples/test-suite/javascript/cpp11_move_typemaps_runme.js create mode 100644 Examples/test-suite/lua/cpp11_move_typemaps_runme.lua create mode 100644 Examples/test-suite/mzscheme/cpp11_move_typemaps_runme.scm create mode 100644 Examples/test-suite/octave/cpp11_move_typemaps_runme.m create mode 100644 Examples/test-suite/perl5/cpp11_move_typemaps_runme.pl create mode 100644 Examples/test-suite/php/cpp11_move_typemaps_runme.php create mode 100644 Examples/test-suite/python/cpp11_move_typemaps_runme.py create mode 100644 Examples/test-suite/ruby/cpp11_move_typemaps_runme.rb create mode 100644 Examples/test-suite/schemerunme/cpp11_move_typemaps.scm create mode 100644 Examples/test-suite/tcl/cpp11_move_typemaps_runme.tcl create mode 100644 Lib/csharp/swigmove.i create mode 100644 Lib/d/swigmove.i create mode 100644 Lib/go/swigmove.i create mode 100644 Lib/guile/swigmove.i create mode 100644 Lib/java/swigmove.i create mode 100644 Lib/javascript/jsc/swigmove.i create mode 100644 Lib/javascript/v8/swigmove.i create mode 100644 Lib/lua/swigmove.i create mode 100644 Lib/mzscheme/swigmove.i create mode 100644 Lib/ocaml/swigmove.i create mode 100644 Lib/octave/swigmove.i create mode 100644 Lib/perl5/swigmove.i create mode 100644 Lib/php/swigmove.i create mode 100644 Lib/python/swigmove.i create mode 100644 Lib/r/swigmove.i create mode 100644 Lib/ruby/swigmove.i create mode 100644 Lib/scilab/swigmove.i create mode 100644 Lib/tcl/swigmove.i create mode 100644 Lib/typemaps/swigmove.swg diff --git a/CHANGES.current b/CHANGES.current index cd985e863..d18afadd1 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-09-16: wsfulton + #999 Provide SWIGTYPE MOVE typemaps in swigmove.i for implementing full + move semantics when passing parameters by value. + 2022-08-31: wsfulton #999 Improve move semantics when using rvalue references. The SWIGTYPE && input typemaps now assume the object has been moved. diff --git a/Doc/Manual/CPlusPlus11.html b/Doc/Manual/CPlusPlus11.html index ba60fd3f8..861b80048 100644 --- a/Doc/Manual/CPlusPlus11.html +++ b/Doc/Manual/CPlusPlus11.html @@ -18,7 +18,7 @@
    • Generalized constant expressions
    • Extern template @@ -240,7 +240,7 @@ Another alternative would be to modify the output rvalue reference typemap to al Fortunately you're highly unlikely to have to solve any of these issues!

      -

      7.2.1.3 Movable and move-only types

      +

      7.2.1.3 Movable and move-only types by value

      @@ -252,7 +252,10 @@ Movable types can appear in function signatures for passing 'by value' and in C+

      -SWIG has been enhanced with support for both copyable and/or movable types but this is currently just for function return values. +SWIG has support for both copyable and/or movable types. +Support for move semantics is quite seamless when returning by value from a function. +Support for move semantics is less so and may require some customisation when passing by value to a function. +First let's consider returning by value from a function.

      @@ -283,6 +286,7 @@ struct MoveOnly { MoveOnly & operator=(MoveOnly &&) = default; static MoveOnly create() { return MoveOnly(); } + static void take(MoveOnly mo); };

    @@ -303,17 +307,193 @@ SWIGEXPORT void * SWIGSTDCALL CSharp_MoveOnly_create() {

    SwigValueWrapper is covered in Pass and return by value. -Note that the generated code could be optimised further using the "optimal" attribute in the "out" typemap. +Note that the generated code could be optimised further using the "optimal" attribute +in the "out" typemap, so if the above typemap is customised as follows (note that this is C# specific): +

    + +
    +%typemap(out, optimal="1") MoveOnly %{
    +  $result = new $1_ltype($1);
    +%}
    +
    + +

    +then the generated code will result in the object being optimally moved: +

    + +
    +SWIGEXPORT void * SWIGSTDCALL CSharp_MoveOnly_create() {
    +  void * jresult ;
    +  jresult = new MoveOnly(MoveOnly::create());
    +  return jresult;
    +}
    +
    + +

    +Now let's consider passing by value. +We'll consider three cases; namely types that are: +

    + +
      +
    1. Copyable and not movable - CopyOnly.
    2. +
    3. Copyable and movable - MovableCopyable.
    4. +
    5. Movable and not copyable - MoveOnly.
    6. +
    + +

    +and for clarification, define these two additional types as follows: +

    + +
    +struct CopyOnly {
    +  int  val;
    +  CopyOnly(): val(0)  {}
    +
    +  CopyOnly(const CopyOnly &) = default;
    +  CopyOnly & operator=(const CopyOnly &) = default;
    +
    +  static CopyOnly create() { return CopyOnly(); }
    +  static void take(CopyOnly co);
    +};
    +
    +struct MovableCopyable {
    +  int  val;
    +  MovableCopyable(): val(0)  {}
    +
    +  MovableCopyable(const MovableCopyable &) = default;
    +  MovableCopyable(MovableCopyable &&) = default;
    +  MovableCopyable & operator=(const MovableCopyable &) = default;
    +  MovableCopyable & operator=(MovableCopyable &&) = default;
    +
    +  static MovableCopyable create() { return MovableCopyable(); }
    +  static void take(MovableCopyable mc);
    +};
    +
    + +

    +The generated code is shown below for CopyOnly::take (with additional comments for when constructors and assignment operators are called). +While the code shown is C# specific, the generated constructor and/or assignment operator calls are ultimately the same for all target languages. +

    + +
    +SWIGEXPORT void SWIGSTDCALL CSharp_CopyOnly_take(void * jarg1) {
    +  CopyOnly arg1 ; // (a) Default constructor
    +  CopyOnly *argp1 ;
    +  
    +  argp1 = (CopyOnly *)jarg1; 
    +  if (!argp1) {
    +    SWIG_CSharpSetPendingExceptionArgument(SWIG_CSharpArgumentNullException, "Attempt to dereference null CopyOnly", 0);
    +    return ;
    +  }
    +  arg1 = *argp1; // (b) Copy assignment
    +  CopyOnly::take(SWIG_STD_MOVE(arg1)); // (c) Copy constructor
    +}
    +
    + +

    +Note that SWIG_STD_MOVE is a macro defined as shown below to use std::move which is only available from C++11 onwards: +

    + +
    +#if __cplusplus >=201103L
    +# define SWIG_STD_MOVE(OBJ) std::move(OBJ)
    +#else
    +# define SWIG_STD_MOVE(OBJ) OBJ
    +#endif
    +
    + +

    +Also note: (c) Copy constructor. +Yes, when passing by value the copy constructor is called for all versions of C++, even C++11 and later even though std::move is specified. +It's a C++ language feature for types that don't have move semantics!

    -There is currently only partial support for move-only types as -support for move-only types used as a parameter in a function, that are passed 'by value', is not yet available. +The generated code for MovableCopyable::take is the same as for CopyOnly::take, however, the C++ compiler will choose the move constructor this time where commented (c) Move constructor:

    +
    +SWIGEXPORT void SWIGSTDCALL CSharp_MovableCopyable_take(void * jarg1) {
    +  MovableCopyable arg1 ; // (a) Default constructor
    +  MovableCopyable *argp1 ;
    +  
    +  argp1 = (MovableCopyable *)jarg1; 
    +  if (!argp1) {
    +    SWIG_CSharpSetPendingExceptionArgument(SWIG_CSharpArgumentNullException, "Attempt to dereference null MovableCopyable", 0);
    +    return ;
    +  }
    +  arg1 = *argp1; // (b) Copy assignment
    +  MovableCopyable::take(SWIG_STD_MOVE(arg1)); // (c) Move constructor
    +}
    +
    + +

    +There are two optimisation opportunities available. +

    +
      +
    1. Remove the default constructor call with the %feature("valuewrapper") covered in Pass and return by value and replace it with SwigValueWrapper. +
    2. +
    3. Apply the SWIGTYPE MOVE typemaps which are designed specifically to implement full move semantics when passing parameters by value. + They replace the copy assignment with a call to SwigValueWrapper::reset, which works much like std::unique_ptr::reset. + These typemaps could alternatively have replaced the copy assignment with a move assignment, but this is not maximally optimal. +
    4. +
    +

    +Simply add the following before the MovableCopyable::take method is parsed: +

    + +
    +%valuewrapper MovableCopyable;
    +%include <swigmove.i>
    +%apply SWIGTYPE MOVE { MovableCopyable }
    +
    + +

    +will result in this optimal code where just one move constructor is invoked: +

    + +
    +SWIGEXPORT void SWIGSTDCALL CSharp_MovableCopyable_take(void * jarg1) {
    +  SwigValueWrapper< MovableCopyable > arg1 ; // (a) No constructors invoked
    +  MovableCopyable *argp1 ;
    +  
    +  argp1 = (MovableCopyable *)jarg1;
    +  if (!argp1) {
    +    SWIG_CSharpSetPendingExceptionArgument(SWIG_CSharpArgumentNullException, "Attempt to dereference null MovableCopyable", 0);
    +    return ;
    +  }
    +  SwigValueWrapper< MovableCopyable >::reset(arg1, argp1);  // (b) No constructor or assignment operator invoked
    +  MovableCopyable::take(SWIG_STD_MOVE(arg1)); // (c) Move constructor
    +}
    +
    + +

    +Note that SwigValueWrapper will call the destructor for the pointer passed to it in the reset function. +This pointer is the underlying C++ object that the proxy class owns. +The details aren't shown, but the 'csin' typemap also generates C# code to ensure that the proxy class releases ownership of the object. +Please see the 'SWIGTYPE MOVE' typemaps in the swigmove.i file provided for each target language. +Therefore full move semantics are implemented; ownership is moved from the proxy class into the C++ layer and the net effect +is the same as using an rvalue reference parameter discussed earlier. +

    + +

    +Lastly, let's consider the MoveOnly::take function defined earlier. +By default the generated code fails to compile as MoveOnly does not have a copy assignment operator. +SWIG is not designed to select a different typemap automatically for move-only types and the user +must apply the SWIGTYPE MOVE typemaps to ensure that only move-only semantics are used. +However, SWIG is able to automatically use %feature("valuewrapper") for move-only +types so it is not necessary to explicitly use this feature. +So in this move-only case, simply add the following before MoveOnly::take is parsed, which results in the same optimal code shown above for MovableCopyable: +

    + +
    +%include <swigmove.i>
    +%apply SWIGTYPE MOVE { MoveOnly }
    +
    +

    Compatibility note: -SWIG-4.1.0 introduced support for taking advantage of types with move semantics and wrapping functions that return movable or move-only types 'by value'. +SWIG-4.1.0 introduced support for taking advantage of types with move semantics and making it possible to easily use move only types.

    diff --git a/Doc/Manual/Contents.html b/Doc/Manual/Contents.html index 2fdabafa6..d3106bf09 100644 --- a/Doc/Manual/Contents.html +++ b/Doc/Manual/Contents.html @@ -300,7 +300,7 @@
  • Generalized constant expressions
  • Extern template diff --git a/Examples/test-suite/common.mk b/Examples/test-suite/common.mk index 950f62d98..4df120943 100644 --- a/Examples/test-suite/common.mk +++ b/Examples/test-suite/common.mk @@ -597,8 +597,9 @@ CPP11_TEST_CASES += \ cpp11_initializer_list \ cpp11_initializer_list_extend \ cpp11_lambda_functions \ - cpp11_move_only \ - cpp11_move_only_valuewrapper \ + cpp11_move_only \ + cpp11_move_typemaps \ + cpp11_move_only_valuewrapper \ cpp11_noexcept \ cpp11_null_pointer_constant \ cpp11_raw_string_literals \ diff --git a/Examples/test-suite/cpp11_move_only.i b/Examples/test-suite/cpp11_move_only.i index 732bc49db..28aaf05e5 100644 --- a/Examples/test-suite/cpp11_move_only.i +++ b/Examples/test-suite/cpp11_move_only.i @@ -12,19 +12,23 @@ using namespace std; bool trace = false; struct MoveOnly { - MoveOnly(int i = 0) { if (trace) cout << "MoveOnly(" << i << ")" << " " << this << endl; Counter::normal_constructor++; } + int val; + MoveOnly(int i = 0) : val(i) { if (trace) cout << "MoveOnly(" << i << ")" << " " << this << endl; Counter::normal_constructor++; } MoveOnly(const MoveOnly &other) = delete; MoveOnly & operator=(const MoveOnly &other) = delete; - MoveOnly(MoveOnly &&other) noexcept { if (trace) cout << "MoveOnly(MoveOnly &&)" << " " << this << endl; Counter::move_constructor++; } - MoveOnly & operator=(MoveOnly &&other) noexcept { if (trace) cout << "operator=(MoveOnly &&)" << " " << this << endl; Counter::move_assignment++; return *this; } + MoveOnly(MoveOnly &&other) noexcept : val(std::move(other.val)) { if (trace) cout << "MoveOnly(MoveOnly &&)" << " " << this << endl; Counter::move_constructor++; } + MoveOnly & operator=(MoveOnly &&other) noexcept { if (trace) cout << "operator=(MoveOnly &&)" << " " << this << endl; Counter::move_assignment++; if (this != &other) { val = std::move(other.val); } return *this; } ~MoveOnly() { if (trace) cout << "~MoveOnly()" << " " << this << endl; Counter::destructor++; } static MoveOnly create() { return MoveOnly(111); } // static const MoveOnly createConst() { return MoveOnly(111); } // not supported by default - // static void take(MoveOnly mo) { if (trace) cout << "take(MoveOnly)" << " " << &mo << endl; } + // compile error by default, see cpp11_move_typemaps.i + #if defined(WRAP_TAKE_METHOD) + static void take(MoveOnly mo) { if (trace) cout << "take(MoveOnly)" << " " << &mo << endl; } + #endif }; %} @@ -35,13 +39,14 @@ struct MoveOnly { %inline %{ // Movable and Copyable struct MovableCopyable { - MovableCopyable(int i = 0) { if (trace) cout << "MovableCopyable(" << i << ")" << " " << this << endl; Counter::normal_constructor++; } + int val; + MovableCopyable(int i = 0) : val(i) { 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(const MovableCopyable &other) : val(other.val) { 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++; if (this != &other) { val = other.val; } 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(MovableCopyable &&other) noexcept : val(std::move(other.val)) { 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++; if (this != &other) { val = std::move(other.val); } return *this; } ~MovableCopyable() { if (trace) cout << "~MovableCopyable()" << " " << this << endl; Counter::destructor++; } static MovableCopyable create() { return MovableCopyable(111); } diff --git a/Examples/test-suite/cpp11_move_typemaps.i b/Examples/test-suite/cpp11_move_typemaps.i new file mode 100644 index 000000000..706780ad4 --- /dev/null +++ b/Examples/test-suite/cpp11_move_typemaps.i @@ -0,0 +1,12 @@ +%module cpp11_move_typemaps + +%include +%apply SWIGTYPE MOVE { MoveOnly mo } +%valuewrapper MovableCopyable; +%apply SWIGTYPE MOVE { MovableCopyable mc } + +%inline %{ +#define WRAP_TAKE_METHOD +%} + +%include "cpp11_move_only.i" diff --git a/Examples/test-suite/csharp/cpp11_move_typemaps_runme.cs b/Examples/test-suite/csharp/cpp11_move_typemaps_runme.cs new file mode 100644 index 000000000..96849c4d3 --- /dev/null +++ b/Examples/test-suite/csharp/cpp11_move_typemaps_runme.cs @@ -0,0 +1,37 @@ +using System; +using cpp11_move_typemapsNamespace; + +public class cpp11_move_typemaps_runme { + + public static void Main() { + Counter.reset_counts(); + using (MoveOnly mo = new MoveOnly(111)) { + Counter.check_counts(1, 0, 0, 0, 0, 0); + MoveOnly.take(mo); + Counter.check_counts(1, 0, 0, 1, 0, 2); + } + Counter.check_counts(1, 0, 0, 1, 0, 2); + + Counter.reset_counts(); + using (MovableCopyable mo = new MovableCopyable(111)) { + Counter.check_counts(1, 0, 0, 0, 0, 0); + MovableCopyable.take(mo); + Counter.check_counts(1, 0, 0, 1, 0, 2); + } + Counter.check_counts(1, 0, 0, 1, 0, 2); + + using (MoveOnly mo = new MoveOnly(222)) { + MoveOnly.take(mo); + bool exception_thrown = false; + try { + MoveOnly.take(mo); + } 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("double usage of take should have been an error"); + } + } +} diff --git a/Examples/test-suite/d/cpp11_move_typemaps_runme.1.d b/Examples/test-suite/d/cpp11_move_typemaps_runme.1.d new file mode 100644 index 000000000..29561cde3 --- /dev/null +++ b/Examples/test-suite/d/cpp11_move_typemaps_runme.1.d @@ -0,0 +1,42 @@ +module cpp11_move_typemaps_runme; + +import cpp11_move_typemaps.Counter; +import cpp11_move_typemaps.MoveOnly; +import cpp11_move_typemaps.MovableCopyable; +import std.conv; +import std.algorithm; + +void main() { + { + Counter.reset_counts(); + scope MoveOnly mo = new MoveOnly(111); + Counter.check_counts(1, 0, 0, 0, 0, 0); + MoveOnly.take(mo); + Counter.check_counts(1, 0, 0, 1, 0, 2); + } + Counter.check_counts(1, 0, 0, 1, 0, 2); + + { + Counter.reset_counts(); + scope MovableCopyable mo = new MovableCopyable(111); + Counter.check_counts(1, 0, 0, 0, 0, 0); + MovableCopyable.take(mo); + Counter.check_counts(1, 0, 0, 1, 0, 2); + } + Counter.check_counts(1, 0, 0, 1, 0, 2); + + { + scope MoveOnly mo = new MoveOnly(222); + MoveOnly.take(mo); + bool exception_thrown = false; + try { + MoveOnly.take(mo); + } 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("double usage of take should have been an error"); + } +} diff --git a/Examples/test-suite/d/cpp11_move_typemaps_runme.2.d b/Examples/test-suite/d/cpp11_move_typemaps_runme.2.d new file mode 100644 index 000000000..29561cde3 --- /dev/null +++ b/Examples/test-suite/d/cpp11_move_typemaps_runme.2.d @@ -0,0 +1,42 @@ +module cpp11_move_typemaps_runme; + +import cpp11_move_typemaps.Counter; +import cpp11_move_typemaps.MoveOnly; +import cpp11_move_typemaps.MovableCopyable; +import std.conv; +import std.algorithm; + +void main() { + { + Counter.reset_counts(); + scope MoveOnly mo = new MoveOnly(111); + Counter.check_counts(1, 0, 0, 0, 0, 0); + MoveOnly.take(mo); + Counter.check_counts(1, 0, 0, 1, 0, 2); + } + Counter.check_counts(1, 0, 0, 1, 0, 2); + + { + Counter.reset_counts(); + scope MovableCopyable mo = new MovableCopyable(111); + Counter.check_counts(1, 0, 0, 0, 0, 0); + MovableCopyable.take(mo); + Counter.check_counts(1, 0, 0, 1, 0, 2); + } + Counter.check_counts(1, 0, 0, 1, 0, 2); + + { + scope MoveOnly mo = new MoveOnly(222); + MoveOnly.take(mo); + bool exception_thrown = false; + try { + MoveOnly.take(mo); + } 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("double usage of take should have been an error"); + } +} diff --git a/Examples/test-suite/guile/cpp11_move_typemaps_runme.scm b/Examples/test-suite/guile/cpp11_move_typemaps_runme.scm new file mode 100644 index 000000000..43f78e6e4 --- /dev/null +++ b/Examples/test-suite/guile/cpp11_move_typemaps_runme.scm @@ -0,0 +1,3 @@ +(dynamic-call "scm_init_cpp11_move_typemaps_module" (dynamic-link "./libcpp11_move_typemaps")) +(load "testsuite.scm") +(load "../schemerunme/cpp11_move_typemaps.scm") diff --git a/Examples/test-suite/java/cpp11_move_typemaps_runme.java b/Examples/test-suite/java/cpp11_move_typemaps_runme.java new file mode 100644 index 000000000..1b5fd2e6c --- /dev/null +++ b/Examples/test-suite/java/cpp11_move_typemaps_runme.java @@ -0,0 +1,51 @@ + +import cpp11_move_typemaps.*; + +public class cpp11_move_typemaps_runme { + + static { + try { + System.loadLibrary("cpp11_move_typemaps"); + } 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); + } + } + + public static void main(String argv[]) { + { + Counter.reset_counts(); + MoveOnly mo = new MoveOnly(111); + Counter.check_counts(1, 0, 0, 0, 0, 0); + MoveOnly.take(mo); + Counter.check_counts(1, 0, 0, 1, 0, 2); + mo.delete(); + } + Counter.check_counts(1, 0, 0, 1, 0, 2); + + { + Counter.reset_counts(); + MovableCopyable mo = new MovableCopyable(111); + Counter.check_counts(1, 0, 0, 0, 0, 0); + MovableCopyable.take(mo); + Counter.check_counts(1, 0, 0, 1, 0, 2); + mo.delete(); + } + Counter.check_counts(1, 0, 0, 1, 0, 2); + + { + MoveOnly mo = new MoveOnly(222); + MoveOnly.take(mo); + boolean exception_thrown = false; + try { + MoveOnly.take(mo); + } 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("double usage of take should have been an error"); + } + } +} diff --git a/Examples/test-suite/javascript/cpp11_move_typemaps_runme.js b/Examples/test-suite/javascript/cpp11_move_typemaps_runme.js new file mode 100644 index 000000000..1e888cb9c --- /dev/null +++ b/Examples/test-suite/javascript/cpp11_move_typemaps_runme.js @@ -0,0 +1,30 @@ +var cpp11_move_typemaps = require("cpp11_move_typemaps"); + +cpp11_move_typemaps.Counter.reset_counts(); +mo = new cpp11_move_typemaps.MoveOnly(111); +cpp11_move_typemaps.Counter.check_counts(1, 0, 0, 0, 0, 0); +cpp11_move_typemaps.MoveOnly.take(mo); +cpp11_move_typemaps.Counter.check_counts(1, 0, 0, 1, 0, 2); +delete mo; +cpp11_move_typemaps.Counter.check_counts(1, 0, 0, 1, 0, 2); + +cpp11_move_typemaps.Counter.reset_counts(); +mo = new cpp11_move_typemaps.MovableCopyable(111); +cpp11_move_typemaps.Counter.check_counts(1, 0, 0, 0, 0, 0); +cpp11_move_typemaps.MovableCopyable.take(mo); +cpp11_move_typemaps.Counter.check_counts(1, 0, 0, 1, 0, 2); +delete mo; +cpp11_move_typemaps.Counter.check_counts(1, 0, 0, 1, 0, 2); + +mo = new cpp11_move_typemaps.MoveOnly(222); +cpp11_move_typemaps.MoveOnly.take(mo); +exception_thrown = false; +try { + cpp11_move_typemaps.MoveOnly.take(mo); +} 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("double usage of take should have been an error"); diff --git a/Examples/test-suite/lua/cpp11_move_typemaps_runme.lua b/Examples/test-suite/lua/cpp11_move_typemaps_runme.lua new file mode 100644 index 000000000..d8947b757 --- /dev/null +++ b/Examples/test-suite/lua/cpp11_move_typemaps_runme.lua @@ -0,0 +1,28 @@ +require("import") -- the import fn +import("cpp11_move_typemaps") -- 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}) + +cpp11_move_typemaps.Counter.reset_counts() +mo = cpp11_move_typemaps.MoveOnly(111) +cpp11_move_typemaps.Counter.check_counts(1, 0, 0, 0, 0, 0) +cpp11_move_typemaps.MoveOnly.take(mo) +cpp11_move_typemaps.Counter.check_counts(1, 0, 0, 1, 0, 2) +mo = nil +cpp11_move_typemaps.Counter.check_counts(1, 0, 0, 1, 0, 2) + +cpp11_move_typemaps.Counter.reset_counts() +mo = cpp11_move_typemaps.MovableCopyable(111) +cpp11_move_typemaps.Counter.check_counts(1, 0, 0, 0, 0, 0) +cpp11_move_typemaps.MovableCopyable.take(mo) +cpp11_move_typemaps.Counter.check_counts(1, 0, 0, 1, 0, 2) +mo = nil +cpp11_move_typemaps.Counter.check_counts(1, 0, 0, 1, 0, 2) + +mo = cpp11_move_typemaps.MoveOnly(222) +cpp11_move_typemaps.MoveOnly.take(mo) +s, msg = pcall(function() cpp11_move_typemaps.MoveOnly.take(mo) end) +assert(s == false and msg:find("Cannot release ownership as memory is not owned", 1, true)) diff --git a/Examples/test-suite/mzscheme/cpp11_move_typemaps_runme.scm b/Examples/test-suite/mzscheme/cpp11_move_typemaps_runme.scm new file mode 100644 index 000000000..910cb3938 --- /dev/null +++ b/Examples/test-suite/mzscheme/cpp11_move_typemaps_runme.scm @@ -0,0 +1,35 @@ +(load-extension "cpp11_move_typemaps.so") +(require (lib "defmacro.ss")) + +; Copied from ../schemerunme/cpp11_move_typemaps.scm and modified for exceptions + +; Define an equivalent to Guile's gc procedure +(define-macro (gc) + `(collect-garbage 'major)) + +(Counter-reset-counts) +(define mo (new-MoveOnly 111)) +(Counter-check-counts 1 0 0 0 0 0) +(MoveOnly-take mo) +(Counter-check-counts 1 0 0 1 0 2) +(delete-MoveOnly mo) +(Counter-check-counts 1 0 0 1 0 2) + +(Counter-reset-counts) +(define mo (new-MovableCopyable 111)) +(Counter-check-counts 1 0 0 0 0 0) +(MovableCopyable-take mo) +(Counter-check-counts 1 0 0 1 0 2) +(delete-MovableCopyable mo) +(Counter-check-counts 1 0 0 1 0 2) + +(define mo (new-MoveOnly 222)) +(MoveOnly-take mo) +(define exception_thrown "no exception thrown for mo") +(with-handlers ([exn:fail? (lambda (exn) + (set! exception_thrown (exn-message exn)))]) + (MoveOnly-take mo)) +(unless (string-contains? exception_thrown "cannot release ownership as memory is not owned") + (error "Wrong or no exception thrown: " exception_thrown)) + +(exit 0) diff --git a/Examples/test-suite/octave/cpp11_move_typemaps_runme.m b/Examples/test-suite/octave/cpp11_move_typemaps_runme.m new file mode 100644 index 000000000..c0532565b --- /dev/null +++ b/Examples/test-suite/octave/cpp11_move_typemaps_runme.m @@ -0,0 +1,37 @@ +# do not dump Octave core +if exist("crash_dumps_octave_core", "builtin") + crash_dumps_octave_core(0); +endif + +cpp11_move_typemaps + +Counter.reset_counts(); +mo = MoveOnly(111); +Counter_check_counts(1, 0, 0, 0, 0, 0); +MoveOnly.take(mo); +Counter_check_counts(1, 0, 0, 1, 0, 2); +clear mo; +Counter_check_counts(1, 0, 0, 1, 0, 2); + +Counter.reset_counts(); +mo = MovableCopyable(111); +Counter_check_counts(1, 0, 0, 0, 0, 0); +MovableCopyable.take(mo); +Counter_check_counts(1, 0, 0, 1, 0, 2); +clear mo; +Counter_check_counts(1, 0, 0, 1, 0, 2); + +mo = MoveOnly(222); +MoveOnly.take(mo); +exception_thrown = false; +try + MoveOnly.take(mo); +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("double usage of take should have been an error"); +endif diff --git a/Examples/test-suite/perl5/cpp11_move_typemaps_runme.pl b/Examples/test-suite/perl5/cpp11_move_typemaps_runme.pl new file mode 100644 index 000000000..aae3e4dcb --- /dev/null +++ b/Examples/test-suite/perl5/cpp11_move_typemaps_runme.pl @@ -0,0 +1,34 @@ +use strict; +use warnings; +use Test::More tests => 3; +BEGIN { use_ok('cpp11_move_typemaps') } +require_ok('cpp11_move_typemaps'); + +{ + cpp11_move_typemaps::Counter::reset_counts(); + my $mo = new cpp11_move_typemaps::MoveOnly(111); + cpp11_move_typemaps::Counter::check_counts(1, 0, 0, 0, 0, 0); + cpp11_move_typemaps::MoveOnly::take($mo); + cpp11_move_typemaps::Counter::check_counts(1, 0, 0, 1, 0, 2); + undef $mo; +} +cpp11_move_typemaps::Counter::check_counts(1, 0, 0, 1, 0, 2); + +{ + cpp11_move_typemaps::Counter::reset_counts(); + my $mo = new cpp11_move_typemaps::MovableCopyable(111); + cpp11_move_typemaps::Counter::check_counts(1, 0, 0, 0, 0, 0); + cpp11_move_typemaps::MovableCopyable::take($mo); + cpp11_move_typemaps::Counter::check_counts(1, 0, 0, 1, 0, 2); + undef $mo; +} +cpp11_move_typemaps::Counter::check_counts(1, 0, 0, 1, 0, 2); + +{ + my $mo = new cpp11_move_typemaps::MoveOnly(222); + cpp11_move_typemaps::MoveOnly::take($mo); + eval { + cpp11_move_typemaps::MoveOnly::take($mo); + }; + like($@, qr/\bcannot release ownership as memory is not owned\b/, "double usage of takeKlassUniquePtr should be an error"); +} diff --git a/Examples/test-suite/php/cpp11_move_typemaps_runme.php b/Examples/test-suite/php/cpp11_move_typemaps_runme.php new file mode 100644 index 000000000..2d4b5e090 --- /dev/null +++ b/Examples/test-suite/php/cpp11_move_typemaps_runme.php @@ -0,0 +1,32 @@ +getMessage(), "Cannot release ownership as memory is not owned", "incorrect exception message: {$e->getMessage()}"); + $exception_thrown = true; +} +check::equal($exception_thrown, true, "double usage of takeKlassUniquePtr should have been an error"); + +check::done(); diff --git a/Examples/test-suite/python/cpp11_move_typemaps_runme.py b/Examples/test-suite/python/cpp11_move_typemaps_runme.py new file mode 100644 index 000000000..e4cf06c53 --- /dev/null +++ b/Examples/test-suite/python/cpp11_move_typemaps_runme.py @@ -0,0 +1,29 @@ +from cpp11_move_typemaps import * + +Counter.reset_counts() +mo = MoveOnly(111) +Counter.check_counts(1, 0, 0, 0, 0, 0) +MoveOnly.take(mo) +Counter.check_counts(1, 0, 0, 1, 0, 2) +del mo +Counter.check_counts(1, 0, 0, 1, 0, 2) + +Counter.reset_counts() +mo = MovableCopyable(111) +Counter.check_counts(1, 0, 0, 0, 0, 0) +MovableCopyable.take(mo) +Counter.check_counts(1, 0, 0, 1, 0, 2) +del mo +Counter.check_counts(1, 0, 0, 1, 0, 2) + +mo = MoveOnly(222) +MoveOnly.take(mo) +exception_thrown = False +try: + MoveOnly.take(mo) +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") diff --git a/Examples/test-suite/ruby/cpp11_move_typemaps_runme.rb b/Examples/test-suite/ruby/cpp11_move_typemaps_runme.rb new file mode 100644 index 000000000..d2c9fe3df --- /dev/null +++ b/Examples/test-suite/ruby/cpp11_move_typemaps_runme.rb @@ -0,0 +1,36 @@ +#!/usr/bin/env ruby + +require 'swig_assert' + +require 'cpp11_move_typemaps' + +Cpp11_move_typemaps::Counter.reset_counts() +mo = Cpp11_move_typemaps::MoveOnly.new(111) +Cpp11_move_typemaps::Counter.check_counts(1, 0, 0, 0, 0, 0) +Cpp11_move_typemaps::MoveOnly.take(mo) +Cpp11_move_typemaps::Counter.check_counts(1, 0, 0, 1, 0, 2) +mo = nil +Cpp11_move_typemaps::Counter.check_counts(1, 0, 0, 1, 0, 2) + +Cpp11_move_typemaps::Counter.reset_counts() +mo = Cpp11_move_typemaps::MovableCopyable.new(111) +Cpp11_move_typemaps::Counter.check_counts(1, 0, 0, 0, 0, 0) +Cpp11_move_typemaps::MovableCopyable.take(mo) +Cpp11_move_typemaps::Counter.check_counts(1, 0, 0, 1, 0, 2) +mo = nil +Cpp11_move_typemaps::Counter.check_counts(1, 0, 0, 1, 0, 2) + +mo = Cpp11_move_typemaps::MoveOnly.new(222) +Cpp11_move_typemaps::MoveOnly.take(mo) +exception_thrown = false +begin + Cpp11_move_typemaps::MoveOnly.take(mo) +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 diff --git a/Examples/test-suite/schemerunme/cpp11_move_typemaps.scm b/Examples/test-suite/schemerunme/cpp11_move_typemaps.scm new file mode 100644 index 000000000..0a8b85a58 --- /dev/null +++ b/Examples/test-suite/schemerunme/cpp11_move_typemaps.scm @@ -0,0 +1,23 @@ +(Counter-reset-counts) +(define mo (new-MoveOnly 111)) +(Counter-check-counts 1 0 0 0 0 0) +(MoveOnly-take mo) +(Counter-check-counts 1 0 0 1 0 2) +(delete-MoveOnly mo) +(Counter-check-counts 1 0 0 1 0 2) + +(Counter-reset-counts) +(define mo (new-MovableCopyable 111)) +(Counter-check-counts 1 0 0 0 0 0) +(MovableCopyable-take mo) +(Counter-check-counts 1 0 0 1 0 2) +(delete-MovableCopyable mo) +(Counter-check-counts 1 0 0 1 0 2) + +(define mo (new-MoveOnly 222)) +(MoveOnly-take mo) +(expect-throw 'misc-error + (MoveOnly-take mo)) +; TODO: check the exception message + +(exit 0) diff --git a/Examples/test-suite/tcl/cpp11_move_typemaps_runme.tcl b/Examples/test-suite/tcl/cpp11_move_typemaps_runme.tcl new file mode 100644 index 000000000..48f860101 --- /dev/null +++ b/Examples/test-suite/tcl/cpp11_move_typemaps_runme.tcl @@ -0,0 +1,35 @@ + +if [ catch { load ./cpp11_move_typemaps[info sharedlibextension] cpp11_move_typemaps} err_msg ] { + puts stderr "Could not load shared object:\n$err_msg" +} + +Counter_reset_counts +MoveOnly mo 111 +Counter_check_counts 1 0 0 0 0 0 +MoveOnly_take mo +Counter_check_counts 1 0 0 1 0 2 +mo -delete +Counter_check_counts 1 0 0 1 0 2 + +Counter_reset_counts +MovableCopyable mo 111 +Counter_check_counts 1 0 0 0 0 0 +MovableCopyable_take mo +Counter_check_counts 1 0 0 1 0 2 +mo -delete +Counter_check_counts 1 0 0 1 0 2 + +MoveOnly mo 222 +MoveOnly_take mo +set exception_thrown 0 +if [ catch { + MoveOnly_take mo +} 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" +} diff --git a/Lib/csharp/swigmove.i b/Lib/csharp/swigmove.i new file mode 100644 index 000000000..2f21bd6f7 --- /dev/null +++ b/Lib/csharp/swigmove.i @@ -0,0 +1,16 @@ +/* ----------------------------------------------------------------------------- + * swigmove.i + * + * Input typemaps library for implementing full move semantics when passing + * parameters by value. + * ----------------------------------------------------------------------------- */ + +%typemap(in, canthrow=1, fragment="") SWIGTYPE MOVE ($&1_type argp) +%{ argp = ($&1_ltype)$input; + if (!argp) { + SWIG_CSharpSetPendingExceptionArgument(SWIG_CSharpArgumentNullException, "Attempt to dereference null $1_type", 0); + return $null; + } + SwigValueWrapper< $1_ltype >::reset($1, argp); %} + +%typemap(csin) SWIGTYPE MOVE "$&csclassname.swigRelease($csinput)" diff --git a/Lib/d/swigmove.i b/Lib/d/swigmove.i new file mode 100644 index 000000000..e2eb83406 --- /dev/null +++ b/Lib/d/swigmove.i @@ -0,0 +1,16 @@ +/* ----------------------------------------------------------------------------- + * swigmove.i + * + * Input typemaps library for implementing full move semantics when passing + * parameters by value. + * ----------------------------------------------------------------------------- */ + +%typemap(in, canthrow=1) SWIGTYPE MOVE ($&1_type argp) +%{ argp = ($&1_ltype)$input; + if (!argp) { + SWIG_DSetPendingException(SWIG_DIllegalArgumentException, "Attempt to dereference null $1_type"); + return $null; + } + SwigValueWrapper< $1_ltype >::reset($1, argp); %} + +%typemap(din) SWIGTYPE MOVE "$dclassname.swigRelease($dinput)" diff --git a/Lib/go/swigmove.i b/Lib/go/swigmove.i new file mode 100644 index 000000000..e1984b6ea --- /dev/null +++ b/Lib/go/swigmove.i @@ -0,0 +1,15 @@ +/* ----------------------------------------------------------------------------- + * swigmove.i + * + * Input typemaps library for implementing full move semantics when passing + * parameters by value. + * ----------------------------------------------------------------------------- */ + +%typemap(in) SWIGTYPE MOVE ($&1_type argp) +%{ + argp = ($&1_ltype)$input; + if (argp == NULL) { + _swig_gopanic("Attempt to dereference null $1_type"); + } + SwigValueWrapper< $1_ltype >::reset($1, argp); +%} diff --git a/Lib/guile/swigmove.i b/Lib/guile/swigmove.i new file mode 100644 index 000000000..87ab91ead --- /dev/null +++ b/Lib/guile/swigmove.i @@ -0,0 +1,19 @@ +/* ----------------------------------------------------------------------------- + * swigmove.i + * + * Input typemaps library for implementing full move semantics when passing + * parameters by value. + * ----------------------------------------------------------------------------- */ + +%typemap(in, noblock=1) SWIGTYPE MOVE (void *argp = 0, int res = 0) { + res = SWIG_ConvertPtr($input, &argp, $&1_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); } + SwigValueWrapper< $1_ltype >::reset($1, ($&1_type)argp); +} diff --git a/Lib/java/swigmove.i b/Lib/java/swigmove.i new file mode 100644 index 000000000..671b988af --- /dev/null +++ b/Lib/java/swigmove.i @@ -0,0 +1,16 @@ +/* ----------------------------------------------------------------------------- + * swigmove.i + * + * Input typemaps library for implementing full move semantics when passing + * parameters by value. + * ----------------------------------------------------------------------------- */ + +%typemap(in) SWIGTYPE MOVE ($&1_type argp) +%{ argp = *($&1_ltype*)&$input; + if (!argp) { + SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "Attempt to dereference null $1_type"); + return $null; + } + SwigValueWrapper< $1_ltype >::reset($1, argp); %} + +%typemap(javain) SWIGTYPE MOVE "$&javaclassname.swigRelease($javainput)" diff --git a/Lib/javascript/jsc/swigmove.i b/Lib/javascript/jsc/swigmove.i new file mode 100644 index 000000000..62ecca768 --- /dev/null +++ b/Lib/javascript/jsc/swigmove.i @@ -0,0 +1 @@ +%include diff --git a/Lib/javascript/v8/swigmove.i b/Lib/javascript/v8/swigmove.i new file mode 100644 index 000000000..62ecca768 --- /dev/null +++ b/Lib/javascript/v8/swigmove.i @@ -0,0 +1 @@ +%include diff --git a/Lib/lua/swigmove.i b/Lib/lua/swigmove.i new file mode 100644 index 000000000..d130e797a --- /dev/null +++ b/Lib/lua/swigmove.i @@ -0,0 +1,18 @@ +/* ----------------------------------------------------------------------------- + * swigmove.i + * + * Input typemaps library for implementing full move semantics when passing + * parameters by value. + * ----------------------------------------------------------------------------- */ + +%typemap(in, checkfn="lua_isuserdata", noblock=1) SWIGTYPE MOVE (void *argp = 0, int res = 0) { + res = SWIG_ConvertPtr(L, $input, &argp, $&1_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, $&1_descriptor); + } + } + SwigValueWrapper< $1_ltype >::reset($1, ($&1_type)argp); +} diff --git a/Lib/mzscheme/swigmove.i b/Lib/mzscheme/swigmove.i new file mode 100644 index 000000000..bbfcdcb16 --- /dev/null +++ b/Lib/mzscheme/swigmove.i @@ -0,0 +1,19 @@ +/* ----------------------------------------------------------------------------- + * swigmove.i + * + * Input typemaps library for implementing full move semantics when passing + * parameters by value. + * ----------------------------------------------------------------------------- */ + +%typemap(in, noblock=1) SWIGTYPE MOVE (void *argp = 0, int res = 0) { + res = SWIG_ConvertPtr($input, &argp, $&1_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)"); + SwigValueWrapper< $1_ltype >::reset($1, ($&1_type)argp); +} diff --git a/Lib/ocaml/swigmove.i b/Lib/ocaml/swigmove.i new file mode 100644 index 000000000..32f9903bd --- /dev/null +++ b/Lib/ocaml/swigmove.i @@ -0,0 +1,11 @@ +/* ----------------------------------------------------------------------------- + * swigmove.i + * + * Input typemaps library for implementing full move semantics when passing + * parameters by value. + * ----------------------------------------------------------------------------- */ + +%typemap(in, noblock=1) SWIGTYPE MOVE (void *argp = 0) { + argp1 = ($&1_ltype) caml_ptr_val($input,$&1_descriptor); + SwigValueWrapper< $1_ltype >::reset($1, ($&1_type)argp); +} diff --git a/Lib/octave/swigmove.i b/Lib/octave/swigmove.i new file mode 100644 index 000000000..62ecca768 --- /dev/null +++ b/Lib/octave/swigmove.i @@ -0,0 +1 @@ +%include diff --git a/Lib/perl5/swigmove.i b/Lib/perl5/swigmove.i new file mode 100644 index 000000000..62ecca768 --- /dev/null +++ b/Lib/perl5/swigmove.i @@ -0,0 +1 @@ +%include diff --git a/Lib/php/swigmove.i b/Lib/php/swigmove.i new file mode 100644 index 000000000..b16a3c544 --- /dev/null +++ b/Lib/php/swigmove.i @@ -0,0 +1,24 @@ +/* ----------------------------------------------------------------------------- + * swigmove.i + * + * Input typemaps library for implementing full move semantics when passing + * parameters by value. + * ----------------------------------------------------------------------------- */ + +%typemap(in, noblock=1) SWIGTYPE MOVE (void *argp = 0, int res = 0) { + res = SWIG_ConvertPtr(&$input, &argp, $&1_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; + } + SwigValueWrapper< $1_ltype >::reset($1, ($&1_type)argp); +} diff --git a/Lib/python/swigmove.i b/Lib/python/swigmove.i new file mode 100644 index 000000000..62ecca768 --- /dev/null +++ b/Lib/python/swigmove.i @@ -0,0 +1 @@ +%include diff --git a/Lib/r/swigmove.i b/Lib/r/swigmove.i new file mode 100644 index 000000000..62ecca768 --- /dev/null +++ b/Lib/r/swigmove.i @@ -0,0 +1 @@ +%include diff --git a/Lib/ruby/swigmove.i b/Lib/ruby/swigmove.i new file mode 100644 index 000000000..62ecca768 --- /dev/null +++ b/Lib/ruby/swigmove.i @@ -0,0 +1 @@ +%include diff --git a/Lib/scilab/swigmove.i b/Lib/scilab/swigmove.i new file mode 100644 index 000000000..62ecca768 --- /dev/null +++ b/Lib/scilab/swigmove.i @@ -0,0 +1 @@ +%include diff --git a/Lib/swig.swg b/Lib/swig.swg index 6cac0e377..9f9d53349 100644 --- a/Lib/swig.swg +++ b/Lib/swig.swg @@ -656,6 +656,16 @@ namespace std { * arg1 = *inarg1; // Assignment from a pointer * arg1 = Vector(1,2,3); // Assignment from a value * + * SwigValueWrapper is a drop in replacement to modify normal value semantics by + * using the heap instead of the stack to copy/move the underlying object it is + * managing. Smart pointers also manage an underlying object on the heap, so + * SwigValueWrapper has characteristics of a smart pointer. The reset function + * is specific smart pointer functionality, but cannot be a non-static member as + * when SWIG modifies typemap code it assumes non-static member function calls + * are routed to the underlying object, changing for example $1.f() to (&x)->f(). + * The reset function was added as an optimisation to avoid some copying/moving + * and to take ownership of an object already created on the heap. + * * The class offers a strong guarantee of exception safety. * With regards to the implementation, the private SwigSmartPointer nested class is * a simple smart pointer providing exception safety, much like std::auto_ptr. @@ -677,6 +687,7 @@ template class SwigValueWrapper { SwigSmartPointer(T *p) : ptr(p) { } ~SwigSmartPointer() { delete ptr; } SwigSmartPointer& operator=(SwigSmartPointer& rhs) { T* oldptr = ptr; ptr = 0; delete oldptr; ptr = rhs.ptr; rhs.ptr = 0; return *this; } + void reset(T *p) { T* oldptr = ptr; ptr = 0; delete oldptr; ptr = p; } } pointer; SwigValueWrapper& operator=(const SwigValueWrapper& rhs); SwigValueWrapper(const SwigValueWrapper& rhs); @@ -690,6 +701,7 @@ public: operator T&() const { return *pointer.ptr; } #endif T *operator&() const { return pointer.ptr; } + static void reset(SwigValueWrapper& t, T *p) { t.pointer.reset(p); } }; /* diff --git a/Lib/tcl/swigmove.i b/Lib/tcl/swigmove.i new file mode 100644 index 000000000..62ecca768 --- /dev/null +++ b/Lib/tcl/swigmove.i @@ -0,0 +1 @@ +%include diff --git a/Lib/typemaps/swigmove.swg b/Lib/typemaps/swigmove.swg new file mode 100644 index 000000000..b0a296850 --- /dev/null +++ b/Lib/typemaps/swigmove.swg @@ -0,0 +1,19 @@ +/* ----------------------------------------------------------------------------- + * swigmove.swg + * + * Input typemaps library for implementing full move semantics when passing + * parameters by value. + * ----------------------------------------------------------------------------- */ + +%typemap(in, noblock=1) SWIGTYPE MOVE (void *argp = 0, int res = 0) { + res = SWIG_ConvertPtr($input, &argp, $&1_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); } + SwigValueWrapper< $1_ltype >::reset($1, ($&1_type)argp); +} From c5610fd4b3ff948a0220368f92dd842ef877b3f0 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Fri, 16 Sep 2022 18:52:52 +0100 Subject: [PATCH 659/662] Guile - Add error checking to SWIGTYPE and SWIGTYPE & in typemaps To prevent seg faults when passing #nil to these parameter types. --- CHANGES.current | 4 ++++ Lib/guile/typemaps.i | 10 ++++++++-- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/CHANGES.current b/CHANGES.current index d18afadd1..dd808d37f 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-09-17: wsfulton + [Guile] Add error checking to SWIGTYPE and SWIGTYPE & in typemaps to prevent + seg faults when passing #nil to these parameter types. + 2022-09-16: wsfulton #999 Provide SWIGTYPE MOVE typemaps in swigmove.i for implementing full move semantics when passing parameters by value. diff --git a/Lib/guile/typemaps.i b/Lib/guile/typemaps.i index 37dfaee64..45a2208f2 100644 --- a/Lib/guile/typemaps.i +++ b/Lib/guile/typemaps.i @@ -14,9 +14,14 @@ /* Pointers */ -%typemap(in) SWIGTYPE *, SWIGTYPE &, SWIGTYPE [] { +%typemap(in) SWIGTYPE *, SWIGTYPE [] { $1 = ($1_ltype)SWIG_MustGetPtr($input, $descriptor, $argnum, 0); } +%typemap(in) SWIGTYPE & ($1_ltype argp) { + argp = ($1_ltype)SWIG_MustGetPtr($input, $descriptor, $argnum, 0); + if (!argp) { %argument_nullref("$1_type", $symname, $argnum); } + $1 = argp; +} %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)) { @@ -136,8 +141,9 @@ /* Pass-by-value */ -%typemap(in) SWIGTYPE($&1_ltype argp) { +%typemap(in) SWIGTYPE ($&1_ltype argp) { argp = ($&1_ltype)SWIG_MustGetPtr($input, $&1_descriptor, $argnum, 0); + if (!argp) { %argument_nullref("$1_type", $symname, $argnum); } $1 = *argp; } From f0af17b3244d98109a62e3fda5ab6e5fc458283d Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Fri, 16 Sep 2022 19:13:02 +0100 Subject: [PATCH 660/662] Correct error handling in Guile pointer conversion --- Lib/guile/guile_scm_run.swg | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Lib/guile/guile_scm_run.swg b/Lib/guile/guile_scm_run.swg index 44e2db225..689a1060f 100644 --- a/Lib/guile/guile_scm_run.swg +++ b/Lib/guile/guile_scm_run.swg @@ -220,6 +220,8 @@ SWIG_Guile_ConvertPtr(SCM s, void **result, swig_type_info *type, int flags) *result = SWIG_TypeCast(cast, (void *) SCM_CELL_WORD_1(smob), &newmemory); assert(!newmemory); /* newmemory handling not yet implemented */ ret = SWIG_OK; + } else { + return SWIG_ERROR; } } else { *result = (void *) SCM_CELL_WORD_1(smob); From e97181ebc07a4755c1ab3e6f08eef12a3f9de07e Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Sat, 17 Sep 2022 10:23:51 +0100 Subject: [PATCH 661/662] Add missing typecheck typemaps for std::auto_ptr and std::unique_ptr To fix overloading when using these types. --- CHANGES.current | 4 ++++ Examples/test-suite/cpp11_std_unique_ptr.i | 14 ++++++++++++++ .../csharp/cpp11_std_unique_ptr_runme.cs | 9 +++++++++ .../test-suite/csharp/li_std_auto_ptr_runme.cs | 9 +++++++++ .../test-suite/d/cpp11_std_unique_ptr_runme.1.d | 9 +++++++++ .../test-suite/d/cpp11_std_unique_ptr_runme.2.d | 9 +++++++++ Examples/test-suite/d/li_std_auto_ptr_runme.1.d | 9 +++++++++ Examples/test-suite/d/li_std_auto_ptr_runme.2.d | 9 +++++++++ .../java/cpp11_std_unique_ptr_runme.java | 9 +++++++++ .../test-suite/java/li_std_auto_ptr_runme.java | 9 +++++++++ .../javascript/cpp11_std_unique_ptr_runme.js | 9 +++++++++ .../test-suite/javascript/li_std_auto_ptr_runme.js | 9 +++++++++ Examples/test-suite/li_std_auto_ptr.i | 14 ++++++++++++++ .../test-suite/lua/cpp11_std_unique_ptr_runme.lua | 12 ++++++++++++ Examples/test-suite/lua/li_std_auto_ptr_runme.lua | 12 ++++++++++++ .../mzscheme/cpp11_std_unique_ptr_runme.scm | 9 +++++++++ .../test-suite/mzscheme/li_std_auto_ptr_runme.scm | 9 +++++++++ .../test-suite/octave/cpp11_std_unique_ptr_runme.m | 12 ++++++++++++ Examples/test-suite/octave/li_std_auto_ptr_runme.m | 12 ++++++++++++ .../test-suite/perl5/cpp11_std_unique_ptr_runme.pl | 8 +++++++- Examples/test-suite/perl5/li_std_auto_ptr_runme.pl | 8 +++++++- .../test-suite/php/cpp11_std_unique_ptr_runme.php | 6 ++++++ Examples/test-suite/php/li_std_auto_ptr_runme.php | 6 ++++++ .../python/cpp11_std_unique_ptr_runme.py | 9 +++++++++ .../test-suite/python/li_std_auto_ptr_runme.py | 9 +++++++++ .../test-suite/ruby/cpp11_std_unique_ptr_runme.rb | 12 ++++++++++++ Examples/test-suite/ruby/li_std_auto_ptr_runme.rb | 12 ++++++++++++ .../schemerunme/cpp11_std_unique_ptr.scm | 9 +++++++++ .../test-suite/schemerunme/li_std_auto_ptr.scm | 9 +++++++++ .../test-suite/tcl/cpp11_std_unique_ptr_runme.tcl | 12 ++++++++++++ Examples/test-suite/tcl/li_std_auto_ptr_runme.tcl | 12 ++++++++++++ Lib/csharp/std_auto_ptr.i | 2 ++ Lib/csharp/std_unique_ptr.i | 2 ++ Lib/d/std_auto_ptr.i | 2 ++ Lib/d/std_unique_ptr.i | 2 ++ Lib/guile/std_auto_ptr.i | 6 ++++++ Lib/guile/std_unique_ptr.i | 6 ++++++ Lib/java/std_auto_ptr.i | 2 ++ Lib/java/std_unique_ptr.i | 2 ++ Lib/javascript/jsc/std_auto_ptr.i | 6 ++++++ Lib/javascript/jsc/std_unique_ptr.i | 6 ++++++ Lib/javascript/v8/std_auto_ptr.i | 6 ++++++ Lib/javascript/v8/std_unique_ptr.i | 6 ++++++ Lib/lua/std_auto_ptr.i | 6 ++++++ Lib/lua/std_unique_ptr.i | 6 ++++++ Lib/mzscheme/std_auto_ptr.i | 6 ++++++ Lib/mzscheme/std_unique_ptr.i | 6 ++++++ Lib/octave/std_auto_ptr.i | 6 ++++++ Lib/octave/std_unique_ptr.i | 6 ++++++ Lib/perl5/std_auto_ptr.i | 6 ++++++ Lib/perl5/std_unique_ptr.i | 6 ++++++ Lib/php/std_auto_ptr.i | 6 ++++++ Lib/php/std_unique_ptr.i | 6 ++++++ Lib/python/std_auto_ptr.i | 6 ++++++ Lib/python/std_unique_ptr.i | 6 ++++++ Lib/ruby/std_auto_ptr.i | 6 ++++++ Lib/ruby/std_unique_ptr.i | 6 ++++++ Lib/tcl/std_auto_ptr.i | 6 ++++++ Lib/tcl/std_unique_ptr.i | 6 ++++++ 59 files changed, 442 insertions(+), 2 deletions(-) diff --git a/CHANGES.current b/CHANGES.current index dd808d37f..6fe039d30 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-09-17: wsfulton + Add missing typecheck typemaps for std::auto_ptr and std::unique_ptr to + fix overloading when using these types. + 2022-09-17: wsfulton [Guile] Add error checking to SWIGTYPE and SWIGTYPE & in typemaps to prevent seg faults when passing #nil to these parameter types. diff --git a/Examples/test-suite/cpp11_std_unique_ptr.i b/Examples/test-suite/cpp11_std_unique_ptr.i index f1ff84aae..f360d8cf3 100644 --- a/Examples/test-suite/cpp11_std_unique_ptr.i +++ b/Examples/test-suite/cpp11_std_unique_ptr.i @@ -2,6 +2,8 @@ #if !(defined(SWIGGO) || defined(SWIGOCAML) || defined(SWIGR) || defined(SWIGSCILAB)) +%warnfilter(509, 516) overloadTest(Klass); + %include "std_string.i" %include "std_unique_ptr.i" @@ -88,6 +90,18 @@ std::unique_ptr makeNullUniquePtr() { return std::unique_ptr(); } +int overloadTest() { + return 0; +} + +int overloadTest(std::unique_ptr kover) { + return 1; +} + +int overloadTest(Klass k) { + return 2; +} + %} #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 04fafae42..7d905e08b 100644 --- a/Examples/test-suite/csharp/cpp11_std_unique_ptr_runme.cs +++ b/Examples/test-suite/csharp/cpp11_std_unique_ptr_runme.cs @@ -91,6 +91,15 @@ public class cpp11_std_unique_ptr_runme { cpp11_std_unique_ptr.takeKlassUniquePtr(cpp11_std_unique_ptr.make_null()); checkCount(0); + // overloaded parameters + if (cpp11_std_unique_ptr.overloadTest() != 0) + throw new ApplicationException("overloadTest failed"); + if (cpp11_std_unique_ptr.overloadTest(null) != 1) + throw new ApplicationException("overloadTest failed"); + if (cpp11_std_unique_ptr.overloadTest(new Klass("over")) != 1) + throw new ApplicationException("overloadTest failed"); + checkCount(0); + // unique_ptr as output Klass k1 = cpp11_std_unique_ptr.makeKlassUniquePtr("first"); 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 a11b57fec..bc5c77608 100644 --- a/Examples/test-suite/csharp/li_std_auto_ptr_runme.cs +++ b/Examples/test-suite/csharp/li_std_auto_ptr_runme.cs @@ -91,6 +91,15 @@ public class li_std_auto_ptr_runme { li_std_auto_ptr.takeKlassAutoPtr(li_std_auto_ptr.make_null()); checkCount(0); + // overloaded parameters + if (li_std_auto_ptr.overloadTest() != 0) + throw new ApplicationException("overloadTest failed"); + if (li_std_auto_ptr.overloadTest(null) != 1) + throw new ApplicationException("overloadTest failed"); + if (li_std_auto_ptr.overloadTest(new Klass("over")) != 1) + throw new ApplicationException("overloadTest failed"); + checkCount(0); + // auto_ptr as output Klass k1 = li_std_auto_ptr.makeKlassAutoPtr("first"); 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 b83392a85..b8e466414 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 @@ -91,6 +91,15 @@ void main() { takeKlassUniquePtr(make_null()); checkCount(0); + // overloaded parameters + if (overloadTest() != 0) + throw new Exception("overloadTest failed"); + if (overloadTest(null) != 1) + throw new Exception("overloadTest failed"); + if (overloadTest(new Klass("over")) != 1) + throw new Exception("overloadTest failed"); + checkCount(0); + // unique_ptr as output Klass k1 = makeKlassUniquePtr("first"); 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 b83392a85..b8e466414 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 @@ -91,6 +91,15 @@ void main() { takeKlassUniquePtr(make_null()); checkCount(0); + // overloaded parameters + if (overloadTest() != 0) + throw new Exception("overloadTest failed"); + if (overloadTest(null) != 1) + throw new Exception("overloadTest failed"); + if (overloadTest(new Klass("over")) != 1) + throw new Exception("overloadTest failed"); + checkCount(0); + // unique_ptr as output Klass k1 = makeKlassUniquePtr("first"); 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 3ad86dc61..86fac68b5 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 @@ -91,6 +91,15 @@ void main() { takeKlassAutoPtr(make_null()); checkCount(0); + // overloaded parameters + if (overloadTest() != 0) + throw new Exception("overloadTest failed"); + if (overloadTest(null) != 1) + throw new Exception("overloadTest failed"); + if (overloadTest(new Klass("over")) != 1) + throw new Exception("overloadTest failed"); + checkCount(0); + // auto_ptr as output Klass k1 = makeKlassAutoPtr("first"); 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 3ad86dc61..86fac68b5 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 @@ -91,6 +91,15 @@ void main() { takeKlassAutoPtr(make_null()); checkCount(0); + // overloaded parameters + if (overloadTest() != 0) + throw new Exception("overloadTest failed"); + if (overloadTest(null) != 1) + throw new Exception("overloadTest failed"); + if (overloadTest(new Klass("over")) != 1) + throw new Exception("overloadTest failed"); + checkCount(0); + // auto_ptr as output Klass k1 = makeKlassAutoPtr("first"); 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 6a8b9b8f2..f90ef7041 100644 --- a/Examples/test-suite/java/cpp11_std_unique_ptr_runme.java +++ b/Examples/test-suite/java/cpp11_std_unique_ptr_runme.java @@ -111,6 +111,15 @@ public class cpp11_std_unique_ptr_runme { cpp11_std_unique_ptr.takeKlassUniquePtr(cpp11_std_unique_ptr.make_null()); checkCount(0); + // overloaded parameters + if (cpp11_std_unique_ptr.overloadTest() != 0) + throw new RuntimeException("overloadTest failed"); + if (cpp11_std_unique_ptr.overloadTest(null) != 1) + throw new RuntimeException("overloadTest failed"); + if (cpp11_std_unique_ptr.overloadTest(new Klass("over")) != 1) + throw new RuntimeException("overloadTest failed"); + checkCount(0); + // unique_ptr as output Klass k1 = cpp11_std_unique_ptr.makeKlassUniquePtr("first"); 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 fd13b9215..24e353ddc 100644 --- a/Examples/test-suite/java/li_std_auto_ptr_runme.java +++ b/Examples/test-suite/java/li_std_auto_ptr_runme.java @@ -111,6 +111,15 @@ public class li_std_auto_ptr_runme { li_std_auto_ptr.takeKlassAutoPtr(li_std_auto_ptr.make_null()); checkCount(0); + // overloaded parameters + if (li_std_auto_ptr.overloadTest() != 0) + throw new RuntimeException("overloadTest failed"); + if (li_std_auto_ptr.overloadTest(null) != 1) + throw new RuntimeException("overloadTest failed"); + if (li_std_auto_ptr.overloadTest(new Klass("over")) != 1) + throw new RuntimeException("overloadTest failed"); + checkCount(0); + // auto_ptr as output Klass k1 = li_std_auto_ptr.makeKlassAutoPtr("first"); 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 8f358a4a7..9e7d87971 100644 --- a/Examples/test-suite/javascript/cpp11_std_unique_ptr_runme.js +++ b/Examples/test-suite/javascript/cpp11_std_unique_ptr_runme.js @@ -94,6 +94,15 @@ cpp11_std_unique_ptr.takeKlassUniquePtr(null); cpp11_std_unique_ptr.takeKlassUniquePtr(cpp11_std_unique_ptr.make_null()); checkCount(0); +// overloaded parameters +if (cpp11_std_unique_ptr.overloadTest() != 0) + throw new RuntimeException("overloadTest failed"); +if (cpp11_std_unique_ptr.overloadTest(null) != 1) + throw new RuntimeException("overloadTest failed"); +if (cpp11_std_unique_ptr.overloadTest(new cpp11_std_unique_ptr.Klass("over")) != 1) + throw new RuntimeException("overloadTest failed"); +checkCount(0); + // unique_ptr as output k1 = cpp11_std_unique_ptr.makeKlassUniquePtr("first"); 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 abe659878..715b9aca2 100644 --- a/Examples/test-suite/javascript/li_std_auto_ptr_runme.js +++ b/Examples/test-suite/javascript/li_std_auto_ptr_runme.js @@ -94,6 +94,15 @@ li_std_auto_ptr.takeKlassAutoPtr(null); li_std_auto_ptr.takeKlassAutoPtr(li_std_auto_ptr.make_null()); checkCount(0); +// overloaded parameters +if (li_std_auto_ptr.overloadTest() != 0) + throw new RuntimeException("overloadTest failed"); +if (li_std_auto_ptr.overloadTest(null) != 1) + throw new RuntimeException("overloadTest failed"); +if (li_std_auto_ptr.overloadTest(new li_std_auto_ptr.Klass("over")) != 1) + throw new RuntimeException("overloadTest failed"); +checkCount(0); + // auto_ptr as output k1 = li_std_auto_ptr.makeKlassAutoPtr("first"); diff --git a/Examples/test-suite/li_std_auto_ptr.i b/Examples/test-suite/li_std_auto_ptr.i index 6de33f6cf..18df51368 100644 --- a/Examples/test-suite/li_std_auto_ptr.i +++ b/Examples/test-suite/li_std_auto_ptr.i @@ -14,6 +14,8 @@ #if !(defined(SWIGGO) || defined(SWIGOCAML) || defined(SWIGR) || defined(SWIGSCILAB)) +%warnfilter(509, 516) overloadTest(Klass); + %include "std_string.i" //#include %include "std_auto_ptr.i" @@ -136,6 +138,18 @@ std::auto_ptr makeNullAutoPtr() { return std::auto_ptr(); } +int overloadTest() { + return 0; +} + +int overloadTest(std::auto_ptr kover) { + return 1; +} + +int overloadTest(Klass k) { + return 2; +} + %} #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 index e22a09728..88d453e19 100644 --- a/Examples/test-suite/lua/cpp11_std_unique_ptr_runme.lua +++ b/Examples/test-suite/lua/cpp11_std_unique_ptr_runme.lua @@ -81,6 +81,18 @@ cpp11_std_unique_ptr.takeKlassUniquePtr(nil); cpp11_std_unique_ptr.takeKlassUniquePtr(cpp11_std_unique_ptr.make_null()); checkCount(0); +-- overloaded parameters +if not (cpp11_std_unique_ptr.overloadTest() == 0) then + error("overloadTest failed") +end +if not (cpp11_std_unique_ptr.overloadTest(nil) == 1) then + error("overloadTest failed") +end +if not (cpp11_std_unique_ptr.overloadTest(cpp11_std_unique_ptr.Klass("over")) == 1) then + error("overloadTest failed") +end +checkCount(0) + -- unique_ptr as output k1 = cpp11_std_unique_ptr.makeKlassUniquePtr("first") 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 d605af692..118a62f01 100644 --- a/Examples/test-suite/lua/li_std_auto_ptr_runme.lua +++ b/Examples/test-suite/lua/li_std_auto_ptr_runme.lua @@ -81,6 +81,18 @@ li_std_auto_ptr.takeKlassAutoPtr(nil); li_std_auto_ptr.takeKlassAutoPtr(li_std_auto_ptr.make_null()); checkCount(0); +-- overloaded parameters +if not (li_std_auto_ptr.overloadTest() == 0) then + error("overloadTest failed") +end +if not (li_std_auto_ptr.overloadTest(nil) == 1) then + error("overloadTest failed") +end +if not (li_std_auto_ptr.overloadTest(li_std_auto_ptr.Klass("over")) == 1) then + error("overloadTest failed") +end +checkCount(0) + -- auto_ptr as output k1 = li_std_auto_ptr.makeKlassAutoPtr("first") diff --git a/Examples/test-suite/mzscheme/cpp11_std_unique_ptr_runme.scm b/Examples/test-suite/mzscheme/cpp11_std_unique_ptr_runme.scm index 5996586af..cd0e18038 100644 --- a/Examples/test-suite/mzscheme/cpp11_std_unique_ptr_runme.scm +++ b/Examples/test-suite/mzscheme/cpp11_std_unique_ptr_runme.scm @@ -79,6 +79,15 @@ (takeKlassUniquePtr (make-null)) (checkCount 0) +; overloaded parameters +(unless (= (overloadTest) 0) + (error "overloadTest failed")) +(unless (= (overloadTest null) 1) + (error "overloadTest failed")) +(unless (= (overloadTest (new-Klass "over")) 1) + (error "overloadTest failed")) +(checkCount 0) + ; unique_ptr as output (define k1 (makeKlassUniquePtr "first")) 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 f52829163..c6c43dba0 100644 --- a/Examples/test-suite/mzscheme/li_std_auto_ptr_runme.scm +++ b/Examples/test-suite/mzscheme/li_std_auto_ptr_runme.scm @@ -79,6 +79,15 @@ (takeKlassAutoPtr (make-null)) (checkCount 0) +; overloaded parameters +(unless (= (overloadTest) 0) + (error "overloadTest failed")) +(unless (= (overloadTest null) 1) + (error "overloadTest failed")) +(unless (= (overloadTest (new-Klass "over")) 1) + (error "overloadTest failed")) +(checkCount 0) + ; auto_ptr as output (define k1 (makeKlassAutoPtr "first")) 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 fd72a522b..dbd461711 100644 --- a/Examples/test-suite/octave/cpp11_std_unique_ptr_runme.m +++ b/Examples/test-suite/octave/cpp11_std_unique_ptr_runme.m @@ -100,6 +100,18 @@ takeKlassUniquePtr(null); takeKlassUniquePtr(null_ptr); checkCount(0); +# overloaded parameters +if (overloadTest() != 0) + error("overloadTest failed"); +endif +if (overloadTest(null) != 1) + error("overloadTest failed"); +endif +if (overloadTest(Klass("over")) != 1) + error("overloadTest failed"); +endif +checkCount(0); + # unique_ptr as output k1 = makeKlassUniquePtr("first"); 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 c8d00afbd..9f0dd16cd 100644 --- a/Examples/test-suite/octave/li_std_auto_ptr_runme.m +++ b/Examples/test-suite/octave/li_std_auto_ptr_runme.m @@ -100,6 +100,18 @@ takeKlassAutoPtr(null); takeKlassAutoPtr(null_ptr); checkCount(0); +# overloaded parameters +if (overloadTest() != 0) + error("overloadTest failed"); +endif +if (overloadTest(null) != 1) + error("overloadTest failed"); +endif +if (overloadTest(Klass("over")) != 1) + error("overloadTest failed"); +endif +checkCount(0); + # auto_ptr as output k1 = makeKlassAutoPtr("first"); 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 793ba733f..d61964bec 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 => 30; +use Test::More tests => 34; BEGIN { use_ok('cpp11_std_unique_ptr') } require_ok('cpp11_std_unique_ptr'); @@ -77,6 +77,12 @@ cpp11_std_unique_ptr::takeKlassUniquePtr(undef); cpp11_std_unique_ptr::takeKlassUniquePtr(cpp11_std_unique_ptr::make_null()); checkCount(0); +# overloaded parameters +is(cpp11_std_unique_ptr::overloadTest(), 0, "overloadTest failed"); +is(cpp11_std_unique_ptr::overloadTest(undef), 1, "overloadTest failed"); +is(cpp11_std_unique_ptr::overloadTest(new cpp11_std_unique_ptr::Klass("over")), 1, "overloadTest failed"); +checkCount(0); + # unique_ptr as output my $k1 = cpp11_std_unique_ptr::makeKlassUniquePtr("first"); 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 cd68ddedf..bfcd38651 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 => 30; +use Test::More tests => 34; BEGIN { use_ok('li_std_auto_ptr') } require_ok('li_std_auto_ptr'); @@ -77,6 +77,12 @@ li_std_auto_ptr::takeKlassAutoPtr(undef); li_std_auto_ptr::takeKlassAutoPtr(li_std_auto_ptr::make_null()); checkCount(0); +# overloaded parameters +is(li_std_auto_ptr::overloadTest(), 0, "overloadTest failed"); +is(li_std_auto_ptr::overloadTest(undef), 1, "overloadTest failed"); +is(li_std_auto_ptr::overloadTest(new li_std_auto_ptr::Klass("over")), 1, "overloadTest failed"); +checkCount(0); + # auto_ptr as output my $k1 = li_std_auto_ptr::makeKlassAutoPtr("first"); 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 77b3f375a..425f6535f 100644 --- a/Examples/test-suite/php/cpp11_std_unique_ptr_runme.php +++ b/Examples/test-suite/php/cpp11_std_unique_ptr_runme.php @@ -83,6 +83,12 @@ takeKlassUniquePtr(NULL); takeKlassUniquePtr(make_null()); checkCount(0); +# overloaded parameters +check::equal(overloadTest(), 0, "overloadTest failed"); +check::equal(overloadTest(NULL), 1, "overloadTest failed"); +check::equal(overloadTest(new Klass("over")), 1, "overloadTest failed"); +checkCount(0); + # unique_ptr as output $k1 = makeKlassUniquePtr("first"); 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 caf604a3c..7ebcf97b1 100644 --- a/Examples/test-suite/php/li_std_auto_ptr_runme.php +++ b/Examples/test-suite/php/li_std_auto_ptr_runme.php @@ -83,6 +83,12 @@ takeKlassAutoPtr(NULL); takeKlassAutoPtr(make_null()); checkCount(0); +# overloaded parameters +check::equal(overloadTest(), 0, "overloadTest failed"); +check::equal(overloadTest(NULL), 1, "overloadTest failed"); +check::equal(overloadTest(new Klass("over")), 1, "overloadTest failed"); +checkCount(0); + # auto_ptr as output $k1 = makeKlassAutoPtr("first"); 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 ac3f52c23..9548fc28a 100644 --- a/Examples/test-suite/python/cpp11_std_unique_ptr_runme.py +++ b/Examples/test-suite/python/cpp11_std_unique_ptr_runme.py @@ -81,6 +81,15 @@ takeKlassUniquePtr(None) takeKlassUniquePtr(make_null()) checkCount(0) +# overloaded parameters +if overloadTest() != 0: + raise RuntimeError("overloadTest failed") +if overloadTest(None) != 1: + raise RuntimeError("overloadTest failed") +if overloadTest(Klass("over")) != 1: + raise RuntimeError("overloadTest failed") +checkCount(0); + # unique_ptr as output k1 = makeKlassUniquePtr("first") 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 c3c5424c6..dd8893f40 100644 --- a/Examples/test-suite/python/li_std_auto_ptr_runme.py +++ b/Examples/test-suite/python/li_std_auto_ptr_runme.py @@ -81,6 +81,15 @@ takeKlassAutoPtr(None) takeKlassAutoPtr(make_null()) checkCount(0) +# overloaded parameters +if overloadTest() != 0: + raise RuntimeError("overloadTest failed") +if overloadTest(None) != 1: + raise RuntimeError("overloadTest failed") +if overloadTest(Klass("over")) != 1: + raise RuntimeError("overloadTest failed") +checkCount(0); + # auto_ptr as output k1 = makeKlassAutoPtr("first") 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 fd43920b7..59e9691be 100644 --- a/Examples/test-suite/ruby/cpp11_std_unique_ptr_runme.rb +++ b/Examples/test-suite/ruby/cpp11_std_unique_ptr_runme.rb @@ -120,6 +120,18 @@ Cpp11_std_unique_ptr::takeKlassUniquePtr(nil) Cpp11_std_unique_ptr::takeKlassUniquePtr(Cpp11_std_unique_ptr::make_null()) checkCount(0) +# overloaded parameters +if (Cpp11_std_unique_ptr::overloadTest() != 0) + raise RuntimeError, "overloadTest failed" +end +if (Cpp11_std_unique_ptr::overloadTest(nil) != 1) + raise RuntimeError, "overloadTest failed" +end +if (Cpp11_std_unique_ptr::overloadTest(Cpp11_std_unique_ptr::Klass.new("over")) != 1) + raise RuntimeError, "overloadTest failed" +end +checkCount(0); + # unique_ptr as output k1 = Cpp11_std_unique_ptr::makeKlassUniquePtr("first") 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 a6aa09be2..48276a888 100644 --- a/Examples/test-suite/ruby/li_std_auto_ptr_runme.rb +++ b/Examples/test-suite/ruby/li_std_auto_ptr_runme.rb @@ -120,6 +120,18 @@ Li_std_auto_ptr::takeKlassAutoPtr(nil) Li_std_auto_ptr::takeKlassAutoPtr(Li_std_auto_ptr::make_null()) checkCount(0) +# overloaded parameters +if (Li_std_auto_ptr::overloadTest() != 0) + raise RuntimeError, "overloadTest failed" +end +if (Li_std_auto_ptr::overloadTest(nil) != 1) + raise RuntimeError, "overloadTest failed" +end +if (Li_std_auto_ptr::overloadTest(Li_std_auto_ptr::Klass.new("over")) != 1) + raise RuntimeError, "overloadTest failed" +end +checkCount(0); + # auto_ptr as output k1 = Li_std_auto_ptr::makeKlassAutoPtr("first") diff --git a/Examples/test-suite/schemerunme/cpp11_std_unique_ptr.scm b/Examples/test-suite/schemerunme/cpp11_std_unique_ptr.scm index b181ffcf3..5e6d0dfcc 100644 --- a/Examples/test-suite/schemerunme/cpp11_std_unique_ptr.scm +++ b/Examples/test-suite/schemerunme/cpp11_std_unique_ptr.scm @@ -65,6 +65,15 @@ (takeKlassUniquePtr (make-null)) (checkCount 0) +; overloaded parameters +(unless (= (overloadTest) 0) + (error "overloadTest failed")) +(unless (= (overloadTest nullnil) 1) + (error "overloadTest failed")) +(unless (= (overloadTest (new-Klass "over")) 1) + (error "overloadTest failed")) +(checkCount 0) + ; unique_ptr as output (define k1 (makeKlassUniquePtr "first")) diff --git a/Examples/test-suite/schemerunme/li_std_auto_ptr.scm b/Examples/test-suite/schemerunme/li_std_auto_ptr.scm index cad0c8b80..3ccd83fdb 100644 --- a/Examples/test-suite/schemerunme/li_std_auto_ptr.scm +++ b/Examples/test-suite/schemerunme/li_std_auto_ptr.scm @@ -65,6 +65,15 @@ (takeKlassAutoPtr (make-null)) (checkCount 0) +; overloaded parameters +(unless (= (overloadTest) 0) + (error "overloadTest failed")) +(unless (= (overloadTest nullnil) 1) + (error "overloadTest failed")) +(unless (= (overloadTest (new-Klass "over")) 1) + (error "overloadTest failed")) +(checkCount 0) + ; auto_ptr as output (define k1 (makeKlassAutoPtr "first")) 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 d61ffb78a..9e641df7e 100644 --- a/Examples/test-suite/tcl/cpp11_std_unique_ptr_runme.tcl +++ b/Examples/test-suite/tcl/cpp11_std_unique_ptr_runme.tcl @@ -130,6 +130,18 @@ takeKlassUniquePtr "NULL" takeKlassUniquePtr [make_null] checkCount 0 +# overloaded parameters +if {[overloadTest] != 0} { + error "overloadTest failed" +} +if {[overloadTest "NULL"] != 1} { + error "overloadTest failed" +} +if {[overloadTest [Klass k "over"]] != 1} { + error "overloadTest failed" +} +checkCount 0 + # unique_ptr as output set k1 [makeKlassUniquePtr "first"] 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 d7c019026..502a758dc 100644 --- a/Examples/test-suite/tcl/li_std_auto_ptr_runme.tcl +++ b/Examples/test-suite/tcl/li_std_auto_ptr_runme.tcl @@ -101,6 +101,18 @@ takeKlassAutoPtr "NULL" takeKlassAutoPtr [make_null] checkCount 0 +# overloaded parameters +if {[overloadTest] != 0} { + error "overloadTest failed" +} +if {[overloadTest "NULL"] != 1} { + error "overloadTest failed" +} +if {[overloadTest [Klass k "over"]] != 1} { + error "overloadTest failed" +} +checkCount 0 + # auto_ptr as output set k1 [makeKlassAutoPtr "first"] diff --git a/Lib/csharp/std_auto_ptr.i b/Lib/csharp/std_auto_ptr.i index 78d7eaf4c..da15df3e9 100644 --- a/Lib/csharp/std_auto_ptr.i +++ b/Lib/csharp/std_auto_ptr.i @@ -28,6 +28,8 @@ return ret; } +%typemap(typecheck, precedence=SWIG_TYPECHECK_POINTER, equivalent="TYPE *") std::auto_ptr< TYPE > "" + %template() std::auto_ptr< TYPE >; %enddef diff --git a/Lib/csharp/std_unique_ptr.i b/Lib/csharp/std_unique_ptr.i index 2233cdc06..0a4caafbc 100644 --- a/Lib/csharp/std_unique_ptr.i +++ b/Lib/csharp/std_unique_ptr.i @@ -28,6 +28,8 @@ return ret; } +%typemap(typecheck, precedence=SWIG_TYPECHECK_POINTER, equivalent="TYPE *") std::unique_ptr< TYPE > "" + %template() std::unique_ptr< TYPE >; %enddef diff --git a/Lib/d/std_auto_ptr.i b/Lib/d/std_auto_ptr.i index e04a18061..500b6115a 100644 --- a/Lib/d/std_auto_ptr.i +++ b/Lib/d/std_auto_ptr.i @@ -32,6 +32,8 @@ return ret; } +%typemap(typecheck, precedence=SWIG_TYPECHECK_POINTER, equivalent="TYPE *") std::auto_ptr< TYPE > "" + %template() std::auto_ptr< TYPE >; %enddef diff --git a/Lib/d/std_unique_ptr.i b/Lib/d/std_unique_ptr.i index 8a06ba066..9317a7e0e 100644 --- a/Lib/d/std_unique_ptr.i +++ b/Lib/d/std_unique_ptr.i @@ -32,6 +32,8 @@ return ret; } +%typemap(typecheck, precedence=SWIG_TYPECHECK_POINTER, equivalent="TYPE *") std::unique_ptr< TYPE > "" + %template() std::unique_ptr< TYPE >; %enddef diff --git a/Lib/guile/std_auto_ptr.i b/Lib/guile/std_auto_ptr.i index 1b1253a16..59d5c0ed8 100644 --- a/Lib/guile/std_auto_ptr.i +++ b/Lib/guile/std_auto_ptr.i @@ -25,6 +25,12 @@ %set_output(SWIG_NewPointerObj($1.release(), $descriptor(TYPE *), SWIG_POINTER_OWN)); %} +%typemap(typecheck, precedence=SWIG_TYPECHECK_POINTER, equivalent="TYPE *", noblock=1) std::auto_ptr< TYPE > { + void *vptr = 0; + int res = SWIG_ConvertPtr($input, &vptr, $descriptor(TYPE *), 0); + $1 = SWIG_CheckState(res); +} + %template() std::auto_ptr< TYPE >; %enddef diff --git a/Lib/guile/std_unique_ptr.i b/Lib/guile/std_unique_ptr.i index 5fc4dc490..6f907e90c 100644 --- a/Lib/guile/std_unique_ptr.i +++ b/Lib/guile/std_unique_ptr.i @@ -25,6 +25,12 @@ %set_output(SWIG_NewPointerObj($1.release(), $descriptor(TYPE *), SWIG_POINTER_OWN)); %} +%typemap(typecheck, precedence=SWIG_TYPECHECK_POINTER, equivalent="TYPE *", noblock=1) std::unique_ptr< TYPE > { + void *vptr = 0; + int res = SWIG_ConvertPtr($input, &vptr, $descriptor(TYPE *), 0); + $1 = SWIG_CheckState(res); +} + %template() std::unique_ptr< TYPE >; %enddef diff --git a/Lib/java/std_auto_ptr.i b/Lib/java/std_auto_ptr.i index 6d65f0451..aee9b4828 100644 --- a/Lib/java/std_auto_ptr.i +++ b/Lib/java/std_auto_ptr.i @@ -31,6 +31,8 @@ return (cPtr == 0) ? null : new $typemap(jstype, TYPE)(cPtr, true); } +%typemap(typecheck, precedence=SWIG_TYPECHECK_POINTER, equivalent="TYPE *") std::auto_ptr< TYPE > "" + %template() std::auto_ptr< TYPE >; %enddef diff --git a/Lib/java/std_unique_ptr.i b/Lib/java/std_unique_ptr.i index e1e5a2622..838ca495a 100644 --- a/Lib/java/std_unique_ptr.i +++ b/Lib/java/std_unique_ptr.i @@ -31,6 +31,8 @@ return (cPtr == 0) ? null : new $typemap(jstype, TYPE)(cPtr, true); } +%typemap(typecheck, precedence=SWIG_TYPECHECK_POINTER, equivalent="TYPE *") std::unique_ptr< TYPE > "" + %template() std::unique_ptr< TYPE >; %enddef diff --git a/Lib/javascript/jsc/std_auto_ptr.i b/Lib/javascript/jsc/std_auto_ptr.i index d062886e4..3d7ae8ba1 100644 --- a/Lib/javascript/jsc/std_auto_ptr.i +++ b/Lib/javascript/jsc/std_auto_ptr.i @@ -25,6 +25,12 @@ %set_output(SWIG_NewPointerObj($1.release(), $descriptor(TYPE *), SWIG_POINTER_OWN | %newpointer_flags)); %} +%typemap(typecheck, precedence=SWIG_TYPECHECK_POINTER, equivalent="TYPE *", noblock=1) std::auto_ptr< TYPE > { + void *vptr = 0; + int res = SWIG_ConvertPtr($input, &vptr, $descriptor(TYPE *), 0); + $1 = SWIG_CheckState(res); +} + %template() std::auto_ptr< TYPE >; %enddef diff --git a/Lib/javascript/jsc/std_unique_ptr.i b/Lib/javascript/jsc/std_unique_ptr.i index 1a7ec06fa..f988714df 100644 --- a/Lib/javascript/jsc/std_unique_ptr.i +++ b/Lib/javascript/jsc/std_unique_ptr.i @@ -25,6 +25,12 @@ %set_output(SWIG_NewPointerObj($1.release(), $descriptor(TYPE *), SWIG_POINTER_OWN | %newpointer_flags)); %} +%typemap(typecheck, precedence=SWIG_TYPECHECK_POINTER, equivalent="TYPE *", noblock=1) std::unique_ptr< TYPE > { + void *vptr = 0; + int res = SWIG_ConvertPtr($input, &vptr, $descriptor(TYPE *), 0); + $1 = SWIG_CheckState(res); +} + %template() std::unique_ptr< TYPE >; %enddef diff --git a/Lib/javascript/v8/std_auto_ptr.i b/Lib/javascript/v8/std_auto_ptr.i index d062886e4..3d7ae8ba1 100644 --- a/Lib/javascript/v8/std_auto_ptr.i +++ b/Lib/javascript/v8/std_auto_ptr.i @@ -25,6 +25,12 @@ %set_output(SWIG_NewPointerObj($1.release(), $descriptor(TYPE *), SWIG_POINTER_OWN | %newpointer_flags)); %} +%typemap(typecheck, precedence=SWIG_TYPECHECK_POINTER, equivalent="TYPE *", noblock=1) std::auto_ptr< TYPE > { + void *vptr = 0; + int res = SWIG_ConvertPtr($input, &vptr, $descriptor(TYPE *), 0); + $1 = SWIG_CheckState(res); +} + %template() std::auto_ptr< TYPE >; %enddef diff --git a/Lib/javascript/v8/std_unique_ptr.i b/Lib/javascript/v8/std_unique_ptr.i index 1a7ec06fa..f988714df 100644 --- a/Lib/javascript/v8/std_unique_ptr.i +++ b/Lib/javascript/v8/std_unique_ptr.i @@ -25,6 +25,12 @@ %set_output(SWIG_NewPointerObj($1.release(), $descriptor(TYPE *), SWIG_POINTER_OWN | %newpointer_flags)); %} +%typemap(typecheck, precedence=SWIG_TYPECHECK_POINTER, equivalent="TYPE *", noblock=1) std::unique_ptr< TYPE > { + void *vptr = 0; + int res = SWIG_ConvertPtr($input, &vptr, $descriptor(TYPE *), 0); + $1 = SWIG_CheckState(res); +} + %template() std::unique_ptr< TYPE >; %enddef diff --git a/Lib/lua/std_auto_ptr.i b/Lib/lua/std_auto_ptr.i index 3952d6dd6..b3b71d0f2 100644 --- a/Lib/lua/std_auto_ptr.i +++ b/Lib/lua/std_auto_ptr.i @@ -25,6 +25,12 @@ SWIG_NewPointerObj(L, $1.release(), $descriptor(TYPE *), SWIG_POINTER_OWN); SWIG_arg++; %} +%typemap(typecheck, precedence=SWIG_TYPECHECK_POINTER, equivalent="TYPE *", noblock=1) std::auto_ptr< TYPE > { + void *vptr = 0; + int res = SWIG_ConvertPtr(L, $input, &vptr, $descriptor(TYPE *), 0); + $1 = SWIG_CheckState(res); +} + %template() std::auto_ptr< TYPE >; %enddef diff --git a/Lib/lua/std_unique_ptr.i b/Lib/lua/std_unique_ptr.i index 4c1c1fde5..ad08f3b0e 100644 --- a/Lib/lua/std_unique_ptr.i +++ b/Lib/lua/std_unique_ptr.i @@ -25,6 +25,12 @@ SWIG_NewPointerObj(L, $1.release(), $descriptor(TYPE *), SWIG_POINTER_OWN); SWIG_arg++; %} +%typemap(typecheck, precedence=SWIG_TYPECHECK_POINTER, equivalent="TYPE *", noblock=1) std::unique_ptr< TYPE > { + void *vptr = 0; + int res = SWIG_ConvertPtr(L, $input, &vptr, $descriptor(TYPE *), 0); + $1 = SWIG_CheckState(res); +} + %template() std::unique_ptr< TYPE >; %enddef diff --git a/Lib/mzscheme/std_auto_ptr.i b/Lib/mzscheme/std_auto_ptr.i index dd55230b3..c61bc8b26 100644 --- a/Lib/mzscheme/std_auto_ptr.i +++ b/Lib/mzscheme/std_auto_ptr.i @@ -25,6 +25,12 @@ %set_output(SWIG_NewPointerObj($1.release(), $descriptor(TYPE *), SWIG_POINTER_OWN)); %} +%typemap(typecheck, precedence=SWIG_TYPECHECK_POINTER, equivalent="TYPE *", noblock=1) std::auto_ptr< TYPE > { + void *vptr = 0; + int res = SWIG_ConvertPtr($input, &vptr, $descriptor(TYPE *), 0); + $1 = SWIG_CheckState(res); +} + %template() std::auto_ptr< TYPE >; %enddef diff --git a/Lib/mzscheme/std_unique_ptr.i b/Lib/mzscheme/std_unique_ptr.i index af602c342..53cf46694 100644 --- a/Lib/mzscheme/std_unique_ptr.i +++ b/Lib/mzscheme/std_unique_ptr.i @@ -25,6 +25,12 @@ %set_output(SWIG_NewPointerObj($1.release(), $descriptor(TYPE *), SWIG_POINTER_OWN)); %} +%typemap(typecheck, precedence=SWIG_TYPECHECK_POINTER, equivalent="TYPE *", noblock=1) std::unique_ptr< TYPE > { + void *vptr = 0; + int res = SWIG_ConvertPtr($input, &vptr, $descriptor(TYPE *), 0); + $1 = SWIG_CheckState(res); +} + %template() std::unique_ptr< TYPE >; %enddef diff --git a/Lib/octave/std_auto_ptr.i b/Lib/octave/std_auto_ptr.i index d062886e4..3d7ae8ba1 100644 --- a/Lib/octave/std_auto_ptr.i +++ b/Lib/octave/std_auto_ptr.i @@ -25,6 +25,12 @@ %set_output(SWIG_NewPointerObj($1.release(), $descriptor(TYPE *), SWIG_POINTER_OWN | %newpointer_flags)); %} +%typemap(typecheck, precedence=SWIG_TYPECHECK_POINTER, equivalent="TYPE *", noblock=1) std::auto_ptr< TYPE > { + void *vptr = 0; + int res = SWIG_ConvertPtr($input, &vptr, $descriptor(TYPE *), 0); + $1 = SWIG_CheckState(res); +} + %template() std::auto_ptr< TYPE >; %enddef diff --git a/Lib/octave/std_unique_ptr.i b/Lib/octave/std_unique_ptr.i index 1a7ec06fa..f988714df 100644 --- a/Lib/octave/std_unique_ptr.i +++ b/Lib/octave/std_unique_ptr.i @@ -25,6 +25,12 @@ %set_output(SWIG_NewPointerObj($1.release(), $descriptor(TYPE *), SWIG_POINTER_OWN | %newpointer_flags)); %} +%typemap(typecheck, precedence=SWIG_TYPECHECK_POINTER, equivalent="TYPE *", noblock=1) std::unique_ptr< TYPE > { + void *vptr = 0; + int res = SWIG_ConvertPtr($input, &vptr, $descriptor(TYPE *), 0); + $1 = SWIG_CheckState(res); +} + %template() std::unique_ptr< TYPE >; %enddef diff --git a/Lib/perl5/std_auto_ptr.i b/Lib/perl5/std_auto_ptr.i index d062886e4..3d7ae8ba1 100644 --- a/Lib/perl5/std_auto_ptr.i +++ b/Lib/perl5/std_auto_ptr.i @@ -25,6 +25,12 @@ %set_output(SWIG_NewPointerObj($1.release(), $descriptor(TYPE *), SWIG_POINTER_OWN | %newpointer_flags)); %} +%typemap(typecheck, precedence=SWIG_TYPECHECK_POINTER, equivalent="TYPE *", noblock=1) std::auto_ptr< TYPE > { + void *vptr = 0; + int res = SWIG_ConvertPtr($input, &vptr, $descriptor(TYPE *), 0); + $1 = SWIG_CheckState(res); +} + %template() std::auto_ptr< TYPE >; %enddef diff --git a/Lib/perl5/std_unique_ptr.i b/Lib/perl5/std_unique_ptr.i index 1a7ec06fa..f988714df 100644 --- a/Lib/perl5/std_unique_ptr.i +++ b/Lib/perl5/std_unique_ptr.i @@ -25,6 +25,12 @@ %set_output(SWIG_NewPointerObj($1.release(), $descriptor(TYPE *), SWIG_POINTER_OWN | %newpointer_flags)); %} +%typemap(typecheck, precedence=SWIG_TYPECHECK_POINTER, equivalent="TYPE *", noblock=1) std::unique_ptr< TYPE > { + void *vptr = 0; + int res = SWIG_ConvertPtr($input, &vptr, $descriptor(TYPE *), 0); + $1 = SWIG_CheckState(res); +} + %template() std::unique_ptr< TYPE >; %enddef diff --git a/Lib/php/std_auto_ptr.i b/Lib/php/std_auto_ptr.i index bd07dbdb5..284091657 100644 --- a/Lib/php/std_auto_ptr.i +++ b/Lib/php/std_auto_ptr.i @@ -27,6 +27,12 @@ SWIG_SetPointerZval($result, (void *)$1.release(), $descriptor(TYPE *), SWIG_POINTER_OWN); %} +%typemap(typecheck, precedence=SWIG_TYPECHECK_POINTER, equivalent="TYPE *", noblock=1) std::auto_ptr< TYPE > { + void *vptr = 0; + int res = SWIG_ConvertPtr(&$input, &vptr, $descriptor(TYPE *), 0); + $1 = SWIG_CheckState(res); +} + %template() std::auto_ptr< TYPE >; %enddef diff --git a/Lib/php/std_unique_ptr.i b/Lib/php/std_unique_ptr.i index 168273663..1bf31595e 100644 --- a/Lib/php/std_unique_ptr.i +++ b/Lib/php/std_unique_ptr.i @@ -27,6 +27,12 @@ SWIG_SetPointerZval($result, (void *)$1.release(), $descriptor(TYPE *), SWIG_POINTER_OWN); %} +%typemap(typecheck, precedence=SWIG_TYPECHECK_POINTER, equivalent="TYPE *", noblock=1) std::unique_ptr< TYPE > { + void *vptr = 0; + int res = SWIG_ConvertPtr(&$input, &vptr, $descriptor(TYPE *), 0); + $1 = SWIG_CheckState(res); +} + %template() std::unique_ptr< TYPE >; %enddef diff --git a/Lib/python/std_auto_ptr.i b/Lib/python/std_auto_ptr.i index d062886e4..3d7ae8ba1 100644 --- a/Lib/python/std_auto_ptr.i +++ b/Lib/python/std_auto_ptr.i @@ -25,6 +25,12 @@ %set_output(SWIG_NewPointerObj($1.release(), $descriptor(TYPE *), SWIG_POINTER_OWN | %newpointer_flags)); %} +%typemap(typecheck, precedence=SWIG_TYPECHECK_POINTER, equivalent="TYPE *", noblock=1) std::auto_ptr< TYPE > { + void *vptr = 0; + int res = SWIG_ConvertPtr($input, &vptr, $descriptor(TYPE *), 0); + $1 = SWIG_CheckState(res); +} + %template() std::auto_ptr< TYPE >; %enddef diff --git a/Lib/python/std_unique_ptr.i b/Lib/python/std_unique_ptr.i index 1a7ec06fa..f988714df 100644 --- a/Lib/python/std_unique_ptr.i +++ b/Lib/python/std_unique_ptr.i @@ -25,6 +25,12 @@ %set_output(SWIG_NewPointerObj($1.release(), $descriptor(TYPE *), SWIG_POINTER_OWN | %newpointer_flags)); %} +%typemap(typecheck, precedence=SWIG_TYPECHECK_POINTER, equivalent="TYPE *", noblock=1) std::unique_ptr< TYPE > { + void *vptr = 0; + int res = SWIG_ConvertPtr($input, &vptr, $descriptor(TYPE *), 0); + $1 = SWIG_CheckState(res); +} + %template() std::unique_ptr< TYPE >; %enddef diff --git a/Lib/ruby/std_auto_ptr.i b/Lib/ruby/std_auto_ptr.i index d062886e4..3d7ae8ba1 100644 --- a/Lib/ruby/std_auto_ptr.i +++ b/Lib/ruby/std_auto_ptr.i @@ -25,6 +25,12 @@ %set_output(SWIG_NewPointerObj($1.release(), $descriptor(TYPE *), SWIG_POINTER_OWN | %newpointer_flags)); %} +%typemap(typecheck, precedence=SWIG_TYPECHECK_POINTER, equivalent="TYPE *", noblock=1) std::auto_ptr< TYPE > { + void *vptr = 0; + int res = SWIG_ConvertPtr($input, &vptr, $descriptor(TYPE *), 0); + $1 = SWIG_CheckState(res); +} + %template() std::auto_ptr< TYPE >; %enddef diff --git a/Lib/ruby/std_unique_ptr.i b/Lib/ruby/std_unique_ptr.i index 1a7ec06fa..f988714df 100644 --- a/Lib/ruby/std_unique_ptr.i +++ b/Lib/ruby/std_unique_ptr.i @@ -25,6 +25,12 @@ %set_output(SWIG_NewPointerObj($1.release(), $descriptor(TYPE *), SWIG_POINTER_OWN | %newpointer_flags)); %} +%typemap(typecheck, precedence=SWIG_TYPECHECK_POINTER, equivalent="TYPE *", noblock=1) std::unique_ptr< TYPE > { + void *vptr = 0; + int res = SWIG_ConvertPtr($input, &vptr, $descriptor(TYPE *), 0); + $1 = SWIG_CheckState(res); +} + %template() std::unique_ptr< TYPE >; %enddef diff --git a/Lib/tcl/std_auto_ptr.i b/Lib/tcl/std_auto_ptr.i index 3030a1bdf..b24809af7 100644 --- a/Lib/tcl/std_auto_ptr.i +++ b/Lib/tcl/std_auto_ptr.i @@ -25,6 +25,12 @@ Tcl_SetObjResult(interp, SWIG_NewInstanceObj($1.release(), $descriptor(TYPE *), SWIG_POINTER_OWN)); %} +%typemap(typecheck, precedence=SWIG_TYPECHECK_POINTER, equivalent="TYPE *", noblock=1) std::auto_ptr< TYPE > { + void *vptr = 0; + int res = SWIG_ConvertPtr($input, &vptr, $descriptor(TYPE *), 0); + $1 = SWIG_CheckState(res); +} + %template() std::auto_ptr< TYPE >; %enddef diff --git a/Lib/tcl/std_unique_ptr.i b/Lib/tcl/std_unique_ptr.i index 704055676..0ea324cda 100644 --- a/Lib/tcl/std_unique_ptr.i +++ b/Lib/tcl/std_unique_ptr.i @@ -25,6 +25,12 @@ Tcl_SetObjResult(interp, SWIG_NewInstanceObj($1.release(), $descriptor(TYPE *), SWIG_POINTER_OWN)); %} +%typemap(typecheck, precedence=SWIG_TYPECHECK_POINTER, equivalent="TYPE *", noblock=1) std::unique_ptr< TYPE > { + void *vptr = 0; + int res = SWIG_ConvertPtr($input, &vptr, $descriptor(TYPE *), 0); + $1 = SWIG_CheckState(res); +} + %template() std::unique_ptr< TYPE >; %enddef From 3caf2857428860fd2147b261f9eb53e9d79d2985 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Sat, 17 Sep 2022 14:27:51 +0200 Subject: [PATCH 662/662] Make method wrappers suffix optional and disabled by default Unfortunately the changes of 26bf86322 (Use SWIG-specific for non-overloaded synthesized functions too, 2021-11-09) did break some existing code bases using SWIG as they hardcoded the old wrapper function names. So turn this off by default and add a global variable allowing to enable this, which can be done for a specific language only. This is ugly but, unfortunately, there is no way to use the Language object from the C function Swig_MethodToFunction(), so the only alternative would be to add another parameter to it, but it already has 6 of them, so it wouldn't really be that much better. See #2366, #2368, #2370. --- Source/Modules/lang.cxx | 3 ++- Source/Modules/main.cxx | 1 + Source/Swig/cwrap.c | 8 +++++--- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/Source/Modules/lang.cxx b/Source/Modules/lang.cxx index eb61752b8..343b8007f 100644 --- a/Source/Modules/lang.cxx +++ b/Source/Modules/lang.cxx @@ -77,6 +77,7 @@ static Hash *classhash; extern int GenerateDefault; extern int ForceExtern; extern int AddExtern; +extern int UseWrapperSuffix; /* import modes */ @@ -1324,7 +1325,7 @@ int Language::staticmemberfunctionHandler(Node *n) { // See Swig_MethodToFunction() for the explanation of this code. if (Getattr(n, "sym:overloaded")) { Append(cname, Getattr(defaultargs ? defaultargs : n, "sym:overname")); - } else { + } else if (UseWrapperSuffix) { Append(cname, "__SWIG"); } diff --git a/Source/Modules/main.cxx b/Source/Modules/main.cxx index 9344a7299..aaf3948ea 100644 --- a/Source/Modules/main.cxx +++ b/Source/Modules/main.cxx @@ -37,6 +37,7 @@ int Verbose = 0; int AddExtern = 0; int NoExcept = 0; int SwigRuntime = 0; // 0 = no option, 1 = -runtime, 2 = -noruntime +int UseWrapperSuffix = 0; // If 1, append suffix to non-overloaded functions too. /* Suppress warning messages for private inheritance, preprocessor evaluation etc... WARN_PP_EVALUATION 202 diff --git a/Source/Swig/cwrap.c b/Source/Swig/cwrap.c index 36e69332c..3b20f4e4f 100644 --- a/Source/Swig/cwrap.c +++ b/Source/Swig/cwrap.c @@ -15,6 +15,8 @@ #include "swig.h" #include "cparse.h" +extern int UseWrapperSuffix; // from main.cxx + static const char *cresult_variable_name = "result"; static Parm *nonvoid_parms(Parm *p) { @@ -1083,13 +1085,13 @@ int Swig_MethodToFunction(Node *n, const_String_or_char_ptr nspace, String *clas in C. But when not using the suffix used for overloaded functions, we still need to ensure that the - wrapper name doesn't conflict with any wrapper functions, so make it sufficiently unique by - appending a suffix similar to the one used for overloaded functions to it. + wrapper name doesn't conflict with any wrapper functions for some languages, so optionally make + it sufficiently unique by appending a suffix similar to the one used for overloaded functions to it. */ if (code) { if (Getattr(n, "sym:overloaded")) { Append(mangled, Getattr(defaultargs ? defaultargs : n, "sym:overname")); - } else { + } else if (UseWrapperSuffix) { Append(mangled, "__SWIG"); } }