From ce7f269f9cd797368b1908a64dea5c4de5d0999b Mon Sep 17 00:00:00 2001 From: Asi Bross Date: Sun, 10 May 2015 11:56:59 +0300 Subject: [PATCH 001/455] Missing smart pointer handling in Java director extra methods implementation. Added proper smart pointer casting to the generated *change_ownership method. Fixing issue #370. --- Source/Modules/java.cxx | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/Source/Modules/java.cxx b/Source/Modules/java.cxx index 8fbdb13e4..6911076a1 100644 --- a/Source/Modules/java.cxx +++ b/Source/Modules/java.cxx @@ -3521,9 +3521,20 @@ public: Printf(code_wrap->def, "SWIGEXPORT void JNICALL Java_%s%s_%s(JNIEnv *jenv, jclass jcls, jobject jself, jlong objarg, jboolean jtake_or_release) {\n", jnipackage, jni_imclass_name, changeown_jnimethod_name); - Printf(code_wrap->code, " %s *obj = *((%s **)&objarg);\n", norm_name, norm_name); - Printf(code_wrap->code, " %s *director = dynamic_cast<%s *>(obj);\n", dirClassName, dirClassName); - Printf(code_wrap->code, " (void)jcls;\n"); + + if (Len(smartptr)) { + Printf(code_wrap->code, " %s *obj = *((%s **)&objarg);\n", smartptr, smartptr); + Printf(code_wrap->code, " (void)jcls;\n"); + Printf(code_wrap->code, " // Keep a local instance of the smart pointer around while we are using the raw pointer\n"); + Printf(code_wrap->code, " // Avoids using smart pointer specific API.\n"); + Printf(code_wrap->code, " %s *director = dynamic_cast<%s *>(obj->operator->());\n", dirClassName, dirClassName); + } + else { + Printf(code_wrap->code, " %s *obj = *((%s **)&objarg);\n", norm_name, norm_name); + Printf(code_wrap->code, " (void)jcls;\n"); + Printf(code_wrap->code, " %s *director = dynamic_cast<%s *>(obj);\n", dirClassName, dirClassName); + } + Printf(code_wrap->code, " if (director) {\n"); Printf(code_wrap->code, " director->swig_java_change_ownership(jenv, jself, jtake_or_release ? true : false);\n"); Printf(code_wrap->code, " }\n"); From dcf8d13f816cbacc8cbd8dca6143b2b28fba7513 Mon Sep 17 00:00:00 2001 From: Frederick Parotat Date: Sat, 27 Jun 2015 01:33:18 +0200 Subject: [PATCH 002/455] [C#] static_cast for native directors Replaced dynamic_cast with static_cast. In the case of directors it seems dynamic_cast is not necessary, yet demands compilation of the generated native wrapper code with RTTI flag (which can impact an application's performance). --- Source/Modules/csharp.cxx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Source/Modules/csharp.cxx b/Source/Modules/csharp.cxx index 9193cd34b..831545c93 100644 --- a/Source/Modules/csharp.cxx +++ b/Source/Modules/csharp.cxx @@ -2044,7 +2044,7 @@ public: Printf(dcast_wrap->code, " Swig::Director *director = (Swig::Director *) 0;\n"); Printf(dcast_wrap->code, " jobject jresult = (jobject) 0;\n"); Printf(dcast_wrap->code, " %s *obj = *((%s **)&jCPtrBase);\n", norm_name, norm_name); - Printf(dcast_wrap->code, " if (obj) director = dynamic_cast(obj);\n"); + Printf(dcast_wrap->code, " if (obj) director = static_cast(obj);\n"); Printf(dcast_wrap->code, " if (director) jresult = director->swig_get_self(jenv);\n"); Printf(dcast_wrap->code, " return jresult;\n"); Printf(dcast_wrap->code, "}\n"); @@ -3473,11 +3473,11 @@ public: Printf(code_wrap->code, " %s *obj = (%s *)objarg;\n", smartptr, smartptr); Printf(code_wrap->code, " // Keep a local instance of the smart pointer around while we are using the raw pointer\n"); Printf(code_wrap->code, " // Avoids using smart pointer specific API.\n"); - Printf(code_wrap->code, " %s *director = dynamic_cast<%s *>(obj->operator->());\n", dirClassName, dirClassName); + Printf(code_wrap->code, " %s *director = static_cast<%s *>(obj->operator->());\n", dirClassName, dirClassName); } else { Printf(code_wrap->code, " %s *obj = (%s *)objarg;\n", norm_name, norm_name); - Printf(code_wrap->code, " %s *director = dynamic_cast<%s *>(obj);\n", dirClassName, dirClassName); + Printf(code_wrap->code, " %s *director = static_cast<%s *>(obj);\n", dirClassName, dirClassName); } // TODO: if statement not needed?? - Java too From 6a4467721bd732820d95b9b7da237adc78c7a5c8 Mon Sep 17 00:00:00 2001 From: Alan Woodland Date: Sat, 7 May 2016 22:44:28 +0100 Subject: [PATCH 003/455] - added std_list.i implemenatation that extends Java's AbstractSequentialList base class - added autobox.i that provides supporting typemaps for generics in containers --- Lib/java/autobox.i | 12 ++++ Lib/java/std_list.i | 168 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 180 insertions(+) create mode 100644 Lib/java/autobox.i create mode 100644 Lib/java/std_list.i diff --git a/Lib/java/autobox.i b/Lib/java/autobox.i new file mode 100644 index 000000000..0146faa76 --- /dev/null +++ b/Lib/java/autobox.i @@ -0,0 +1,12 @@ +// Java typemaps for autoboxing in return types of generics +%define AUTOBOX(CTYPE, JTYPE) +%typemap(autobox) CTYPE, const CTYPE&, CTYPE& "JTYPE" +%enddef +AUTOBOX(double, Double) +AUTOBOX(float, Float) +AUTOBOX(boolean, Boolean) +AUTOBOX(signed char, Byte) +AUTOBOX(short, Short) +AUTOBOX(int, Integer) +AUTOBOX(long, Long) +AUTOBOX(SWIGTYPE, $typemap(jstype,$1_basetype)) diff --git a/Lib/java/std_list.i b/Lib/java/std_list.i new file mode 100644 index 000000000..0fd24dd51 --- /dev/null +++ b/Lib/java/std_list.i @@ -0,0 +1,168 @@ +%include +%include + +%{ +#include +#include +%} + +namespace std { + template class list { + public: + // This typedef is a weird hack to make stuff work + typedef std::list::iterator iterator; + typedef size_t size_type; + typedef T value_type; + typedef T& reference; + + void assign(size_type n, const value_type &val); + + bool empty() const; + + list(size_type n, const value_type &value=value_type()); + list(const list &o); + list(); + ~list(); + + size_type max_size () const; + + void pop_back(); + void pop_front(); + void push_back(const value_type &x); + void push_front(const value_type &x); + void remove(const T &v); + + // Possible bug: jint != size_type + jint size () const; + void sort(); + +%javamethodmodifiers "private"; + // Only for helping implement listIterator + iterator begin(); + iterator insert(iterator pos, const value_type &v); + + %extend { + static void set(iterator pos, const value_type& v) { + *pos = v; + } + + jint previous_index(const iterator& pos) const { + return pos == self->begin() ? -1 : std::distance(self->begin(), static_cast::const_iterator>(pos)); + } + + jint next_index(const iterator& pos) const { + return pos == self->end() ? self->size() : std::distance(self->begin(), static_cast::const_iterator>(pos)); + } + + static iterator next(iterator pos) { + return ++pos; + } + + static iterator previous(iterator pos) { + return --pos; + } + + static value_type deref(const iterator& pos) { + return *pos; + } + + static void advance(iterator& pos, jint index) { + std::advance(pos, index); + } + + bool has_next(const iterator& pos) const { + return pos != $self->end(); + } + } +%javamethodmodifiers "public"; + }; +} + +%typemap(javaimports) std::list %{ + import java.util.AbstractSequentialList; + import java.util.ListIterator; + import java.util.NoSuchElementException; + import java.util.Collection; +%} + +%typemap(javabase) std::list "AbstractSequentialList<$typemap(autobox,$1_basetype::value_type)>" + +#define JAVA_VALUE_TYPE $typemap(autobox,$1_basetype::value_type) +#define JAVA_ITERATOR_TYPE $typemap(jstype, $1_basetype::iterator) + +%typemap(javacode,noblock=1) std::list { + public $javaclassname(Collection c) { + this(); + ListIterator it = listIterator(0); + for (Object o: c) { + it.add((JAVA_VALUE_TYPE)o); + } + } + + public ListIterator listIterator(int index) { + return new ListIterator() { + private JAVA_ITERATOR_TYPE pos; + private JAVA_ITERATOR_TYPE last; + + private ListIterator init(int index) { + pos = $javaclassname.this.begin(); + $javaclassname.advance(pos, index); + return this; + } + + public void add(JAVA_VALUE_TYPE v) { + // Technically we can invalidate last here, but this makes more sense + last=$javaclassname.this.insert(pos, v); + } + + public void set(JAVA_VALUE_TYPE v) { + if (null==last) { + throw new IllegalStateException(); + } + $javaclassname.set(last, v); + } + + public void remove() { + if (null==last) { + throw new IllegalStateException(); + } + $javaclassname.this.remove(last); + last=null; + } + + public int previousIndex() { + return $javaclassname.this.previous_index(pos); + } + + public int nextIndex() { + return $javaclassname.this.next_index(pos); + } + + public JAVA_VALUE_TYPE previous() { + if (previousIndex() < 0) { + throw new NoSuchElementException(); + } + last = pos; + pos = $javaclassname.previous(pos); + return $javaclassname.deref(last); + } + + public JAVA_VALUE_TYPE next() { + if (!hasNext()) { + throw new NoSuchElementException(); + } + last = pos; + pos = $javaclassname.next(pos); + return $javaclassname.deref(last); + } + + public boolean hasPrevious() { + return previousIndex() != -1; + } + + public boolean hasNext() { + return $javaclassname.this.has_next(pos); + } + }.init(index); + } +} From b0de71857e5684dc9119a380edc1d83a19fc5f9c Mon Sep 17 00:00:00 2001 From: Alan Woodland Date: Mon, 16 May 2016 20:39:34 +0100 Subject: [PATCH 004/455] Don't expose remove() method from std::list to avoid confusing it with Java's remove() in List --- Lib/java/std_list.i | 1 - 1 file changed, 1 deletion(-) diff --git a/Lib/java/std_list.i b/Lib/java/std_list.i index 0fd24dd51..b717bbfc2 100644 --- a/Lib/java/std_list.i +++ b/Lib/java/std_list.i @@ -30,7 +30,6 @@ namespace std { void pop_front(); void push_back(const value_type &x); void push_front(const value_type &x); - void remove(const T &v); // Possible bug: jint != size_type jint size () const; From 0094e3c90df80267d03a049ad7a48ce3fe866c17 Mon Sep 17 00:00:00 2001 From: Alan Woodland Date: Mon, 16 May 2016 20:49:51 +0100 Subject: [PATCH 005/455] Target each method specificly for setting modifiers --- Lib/java/std_list.i | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/Lib/java/std_list.i b/Lib/java/std_list.i index b717bbfc2..f49b11826 100644 --- a/Lib/java/std_list.i +++ b/Lib/java/std_list.i @@ -6,6 +6,17 @@ #include %} +%javamethodmodifiers std::list::begin "private"; +%javamethodmodifiers std::list::insert "private"; +%javamethodmodifiers std::list::set "private"; +%javamethodmodifiers std::list::previous_index "private"; +%javamethodmodifiers std::list::next_index "private"; +%javamethodmodifiers std::list::previous "private"; +%javamethodmodifiers std::list::next "private"; +%javamethodmodifiers std::list::deref "private"; +%javamethodmodifiers std::list::advance "private"; +%javamethodmodifiers std::list::has_next "private"; + namespace std { template class list { public: @@ -35,7 +46,6 @@ namespace std { jint size () const; void sort(); -%javamethodmodifiers "private"; // Only for helping implement listIterator iterator begin(); iterator insert(iterator pos, const value_type &v); @@ -73,7 +83,6 @@ namespace std { return pos != $self->end(); } } -%javamethodmodifiers "public"; }; } From a2b092ab7e2b00a1090651b6ec9f21fa2b4bfb9d Mon Sep 17 00:00:00 2001 From: Alan Woodland Date: Mon, 16 May 2016 21:24:11 +0100 Subject: [PATCH 006/455] Don't expose sort() to avoid adding dependencies on all std::list users --- Lib/java/std_list.i | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Lib/java/std_list.i b/Lib/java/std_list.i index f49b11826..932980d67 100644 --- a/Lib/java/std_list.i +++ b/Lib/java/std_list.i @@ -44,7 +44,9 @@ namespace std { // Possible bug: jint != size_type jint size () const; - void sort(); + + // Although sort() is nice it makes operator<() mandatory which it probably shouldn't be + //void sort(); // Only for helping implement listIterator iterator begin(); From 131f5e5a0d78825523eb215f12a24e8219973fa0 Mon Sep 17 00:00:00 2001 From: Alan Woodland Date: Mon, 16 May 2016 21:25:08 +0100 Subject: [PATCH 007/455] Expose more types from li_std_list.i --- Examples/test-suite/li_std_list.i | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Examples/test-suite/li_std_list.i b/Examples/test-suite/li_std_list.i index bae475eea..cdf028a50 100644 --- a/Examples/test-suite/li_std_list.i +++ b/Examples/test-suite/li_std_list.i @@ -42,5 +42,7 @@ struct Struct { }; %} - +%template(StructList) std::list; +%template(StructPtrList) std::list; +%template(StructConstPtrList) std::list; From 65483965aba5b9e26a10a1e7c916f749058113c4 Mon Sep 17 00:00:00 2001 From: Alan Woodland Date: Mon, 16 May 2016 21:25:47 +0100 Subject: [PATCH 008/455] Base _runme.java for li_std_list off li_std_vector_runme.java --- .../test-suite/java/li_std_list_runme.java | 35 +++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 Examples/test-suite/java/li_std_list_runme.java diff --git a/Examples/test-suite/java/li_std_list_runme.java b/Examples/test-suite/java/li_std_list_runme.java new file mode 100644 index 000000000..de53a9fa6 --- /dev/null +++ b/Examples/test-suite/java/li_std_list_runme.java @@ -0,0 +1,35 @@ +import li_std_list.*; + +public class li_std_list_runme { + + static { + try { + System.loadLibrary("li_std_list"); + } 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[]) throws Throwable + { + IntList v1 = new IntList(); + DoubleList v2 = new DoubleList(); + + v1.add(123); + if (v1.get(0) != 123) throw new RuntimeException("v1 test failed"); + + StructList v4 = new StructList(); + StructPtrList v5 = new StructPtrList(); + StructConstPtrList v6 = new StructConstPtrList(); + + v4.add(new Struct(12)); + v5.add(new Struct(34)); + v6.add(new Struct(56)); + + Struct s = null; + if (v4.get(0).getNum() != 12) throw new RuntimeException("v4 test failed"); + if (v5.get(0).getNum() != 34) throw new RuntimeException("v5 test failed"); + if (v6.get(0).getNum() != 56) throw new RuntimeException("v6 test failed"); + } +} From d217a68908a8c7f5555a56325ba22e92a2bd7e7a Mon Sep 17 00:00:00 2001 From: Alan Woodland Date: Mon, 16 May 2016 21:29:22 +0100 Subject: [PATCH 009/455] added more comments in a few places --- Lib/java/std_list.i | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Lib/java/std_list.i b/Lib/java/std_list.i index 932980d67..35f0ecac8 100644 --- a/Lib/java/std_list.i +++ b/Lib/java/std_list.i @@ -104,6 +104,7 @@ namespace std { public $javaclassname(Collection c) { this(); ListIterator it = listIterator(0); + // We should special case the "copy constructor" here to avoid lots of cross-language calls for (Object o: c) { it.add((JAVA_VALUE_TYPE)o); } @@ -167,6 +168,7 @@ namespace std { } public boolean hasPrevious() { + // This call to previousIndex() will be much slower than the hasNext() implementation, but it's simpler like this with C++ forward iterators return previousIndex() != -1; } From a3821245eb47d88e995e9598a57f493b4e744a2b Mon Sep 17 00:00:00 2001 From: Alan Woodland Date: Mon, 16 May 2016 21:49:45 +0100 Subject: [PATCH 010/455] Added li_std_list to the Java test-suit makefile --- 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 e69964352..b5e8c65f0 100644 --- a/Examples/test-suite/java/Makefile.in +++ b/Examples/test-suite/java/Makefile.in @@ -39,6 +39,7 @@ CPP_TEST_CASES = \ java_throws \ java_typemaps_proxy \ java_typemaps_typewrapper \ + li_std_list \ # li_boost_intrusive_ptr CPP11_TEST_CASES = \ From 4a149f66fdc12e34b33c7189f51082ca9b9af709 Mon Sep 17 00:00:00 2001 From: Alan Woodland Date: Mon, 16 May 2016 22:00:37 +0100 Subject: [PATCH 011/455] Added enum to li_std_list tests --- Examples/test-suite/li_std_list.i | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Examples/test-suite/li_std_list.i b/Examples/test-suite/li_std_list.i index cdf028a50..54b4cdfea 100644 --- a/Examples/test-suite/li_std_list.i +++ b/Examples/test-suite/li_std_list.i @@ -40,9 +40,17 @@ struct Struct { Struct(double d) : num(d) {} // bool operator==(const Struct &other) { return (num == other.num); } }; + +enum Fruit { + APPLE, + BANANNA, + PEAR, + KIWI, +}; %} %template(StructList) std::list; %template(StructPtrList) std::list; %template(StructConstPtrList) std::list; +%template(FruitList) std::list; From b09fce84a40c0c806eac3a2de58d97ae69b167ce Mon Sep 17 00:00:00 2001 From: Alan Woodland Date: Mon, 16 May 2016 22:01:30 +0100 Subject: [PATCH 012/455] just use a forward declaration for C++ iterator types to fix enum errors --- Lib/java/std_list.i | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Lib/java/std_list.i b/Lib/java/std_list.i index 35f0ecac8..0dde17371 100644 --- a/Lib/java/std_list.i +++ b/Lib/java/std_list.i @@ -20,8 +20,7 @@ namespace std { template class list { public: - // This typedef is a weird hack to make stuff work - typedef std::list::iterator iterator; + struct iterator; typedef size_t size_type; typedef T value_type; typedef T& reference; From 9ade17cc5011e09adc4f863618ac324b42854abb Mon Sep 17 00:00:00 2001 From: Alan Woodland Date: Tue, 24 May 2016 22:03:53 +0100 Subject: [PATCH 013/455] Drop non-const reference from autobox typemap macro to be consistent. --- Lib/java/autobox.i | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib/java/autobox.i b/Lib/java/autobox.i index 0146faa76..aae197ad8 100644 --- a/Lib/java/autobox.i +++ b/Lib/java/autobox.i @@ -1,6 +1,6 @@ // Java typemaps for autoboxing in return types of generics %define AUTOBOX(CTYPE, JTYPE) -%typemap(autobox) CTYPE, const CTYPE&, CTYPE& "JTYPE" +%typemap(autobox) CTYPE, const CTYPE& "JTYPE" %enddef AUTOBOX(double, Double) AUTOBOX(float, Float) From e561a78205643973318cbbfef5c2376968e9176d Mon Sep 17 00:00:00 2001 From: Alan Woodland Date: Tue, 24 May 2016 22:28:59 +0100 Subject: [PATCH 014/455] Added a best case workaround for std::list::size_type vs jint problem. There's a bit of commentry added around it too for clarity. --- Lib/java/std_list.i | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/Lib/java/std_list.i b/Lib/java/std_list.i index 0dde17371..959fdf25d 100644 --- a/Lib/java/std_list.i +++ b/Lib/java/std_list.i @@ -1,5 +1,5 @@ +%include %include -%include %{ #include @@ -17,6 +17,18 @@ %javamethodmodifiers std::list::advance "private"; %javamethodmodifiers std::list::has_next "private"; +/* + To conform to Java Collection interface we must return int from size(). + Unfortunately that loses precision from the integer types commonly used in + C++ implementations. Since we can't overload on return values the best + workaround here is to expose the real C++ size() return value to Java as a + long under a different name. We can then wrap that with a Java specific + size() implementation that at least checks and fails gracefully in the case + where we have a collection with > 2^31-1 items rather than failing + mysteriously. The wrapper implementaiton is in the javacode typemap later. +*/ +%rename(realSize) std::list::size; + namespace std { template class list { public: @@ -41,8 +53,7 @@ namespace std { void push_back(const value_type &x); void push_front(const value_type &x); - // Possible bug: jint != size_type - jint size () const; + size_type size() const; // Although sort() is nice it makes operator<() mandatory which it probably shouldn't be //void sort(); @@ -109,6 +120,14 @@ namespace std { } } + public int size() { + final long val = realSize(); + if (val > Integer.MAX_VALUE) { + throw new IndexOutOfBoundsException("Size of Collection $javaclassname is not representable as int"); + } + return (int)val; + } + public ListIterator listIterator(int index) { return new ListIterator() { private JAVA_ITERATOR_TYPE pos; From c78a005a294cf919b3fe1c8949d9935e92b71375 Mon Sep 17 00:00:00 2001 From: Alan Woodland Date: Tue, 31 May 2016 14:51:37 +0100 Subject: [PATCH 015/455] Removed typedef from li_std_list test as it's not expected to work properly in templated code --- Examples/test-suite/li_std_list.i | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/Examples/test-suite/li_std_list.i b/Examples/test-suite/li_std_list.i index 54b4cdfea..3a2d761ff 100644 --- a/Examples/test-suite/li_std_list.i +++ b/Examples/test-suite/li_std_list.i @@ -14,12 +14,8 @@ namespace std { %template(DoubleList) std::list; -%inline %{ -typedef float Real; -%} - namespace std { - %template(RealList) list; + %template(RealList) list; } %inline %{ @@ -53,4 +49,4 @@ enum Fruit { %template(StructPtrList) std::list; %template(StructConstPtrList) std::list; -%template(FruitList) std::list; +%template(FruitList) std::list; From 583fdce790a00ae4cec5fb1cd55f3dfc6d916dc5 Mon Sep 17 00:00:00 2001 From: Alan Woodland Date: Tue, 31 May 2016 20:22:39 +0100 Subject: [PATCH 016/455] Moving iterator functionality into nested Java class now. --- Lib/java/std_list.i | 66 +++++++++++++++++++++++++-------------------- 1 file changed, 37 insertions(+), 29 deletions(-) diff --git a/Lib/java/std_list.i b/Lib/java/std_list.i index 959fdf25d..1e126e35e 100644 --- a/Lib/java/std_list.i +++ b/Lib/java/std_list.i @@ -29,13 +29,41 @@ */ %rename(realSize) std::list::size; +%nodefaultctor std::list::iterator; + namespace std { template class list { public: - struct iterator; typedef size_t size_type; typedef T value_type; typedef T& reference; + struct iterator { + %extend { + void set_unchecked(const value_type& v) { + **$self = v; + } + + iterator next_unchecked() const { + std::list::iterator ret=*$self; + ++ret; + return ret; + } + + iterator previous_unchecked() const { + std::list::iterator ret=*$self; + --ret; + return ret; + } + + value_type deref_unchecked() const { + return **$self; + } + + void advance_unchecked(jint index) { + std::advance(*$self, index); + } + } + }; void assign(size_type n, const value_type &val); @@ -58,15 +86,11 @@ namespace std { // Although sort() is nice it makes operator<() mandatory which it probably shouldn't be //void sort(); - // Only for helping implement listIterator iterator begin(); + iterator end(); iterator insert(iterator pos, const value_type &v); %extend { - static void set(iterator pos, const value_type& v) { - *pos = v; - } - jint previous_index(const iterator& pos) const { return pos == self->begin() ? -1 : std::distance(self->begin(), static_cast::const_iterator>(pos)); } @@ -75,22 +99,6 @@ namespace std { return pos == self->end() ? self->size() : std::distance(self->begin(), static_cast::const_iterator>(pos)); } - static iterator next(iterator pos) { - return ++pos; - } - - static iterator previous(iterator pos) { - return --pos; - } - - static value_type deref(const iterator& pos) { - return *pos; - } - - static void advance(iterator& pos, jint index) { - std::advance(pos, index); - } - bool has_next(const iterator& pos) const { return pos != $self->end(); } @@ -108,7 +116,7 @@ namespace std { %typemap(javabase) std::list "AbstractSequentialList<$typemap(autobox,$1_basetype::value_type)>" #define JAVA_VALUE_TYPE $typemap(autobox,$1_basetype::value_type) -#define JAVA_ITERATOR_TYPE $typemap(jstype, $1_basetype::iterator) +#define JAVA_ITERATOR_TYPE iterator %typemap(javacode,noblock=1) std::list { public $javaclassname(Collection c) { @@ -135,7 +143,7 @@ namespace std { private ListIterator init(int index) { pos = $javaclassname.this.begin(); - $javaclassname.advance(pos, index); + pos.advance_unchecked(index); return this; } @@ -148,7 +156,7 @@ namespace std { if (null==last) { throw new IllegalStateException(); } - $javaclassname.set(last, v); + last.set_unchecked(v); } public void remove() { @@ -172,8 +180,8 @@ namespace std { throw new NoSuchElementException(); } last = pos; - pos = $javaclassname.previous(pos); - return $javaclassname.deref(last); + pos = pos.previous_unchecked(); + return last.deref_unchecked(); } public JAVA_VALUE_TYPE next() { @@ -181,8 +189,8 @@ namespace std { throw new NoSuchElementException(); } last = pos; - pos = $javaclassname.next(pos); - return $javaclassname.deref(last); + pos = pos.next_unchecked(); + return last.deref_unchecked(); } public boolean hasPrevious() { From 1f4a8e62314d42200447ee30ebf63b829cf7b462 Mon Sep 17 00:00:00 2001 From: Alan Woodland Date: Tue, 31 May 2016 20:27:16 +0100 Subject: [PATCH 017/455] Java style fix: iterator->Iterator --- Lib/java/std_list.i | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Lib/java/std_list.i b/Lib/java/std_list.i index 1e126e35e..cc14d7353 100644 --- a/Lib/java/std_list.i +++ b/Lib/java/std_list.i @@ -29,6 +29,9 @@ */ %rename(realSize) std::list::size; +// Match Java style better: +%rename(Iterator) std::list::iterator; + %nodefaultctor std::list::iterator; namespace std { @@ -116,7 +119,7 @@ namespace std { %typemap(javabase) std::list "AbstractSequentialList<$typemap(autobox,$1_basetype::value_type)>" #define JAVA_VALUE_TYPE $typemap(autobox,$1_basetype::value_type) -#define JAVA_ITERATOR_TYPE iterator +#define JAVA_ITERATOR_TYPE Iterator %typemap(javacode,noblock=1) std::list { public $javaclassname(Collection c) { From 00ac1f38e590618e72a5ba3a46cd732b17123db2 Mon Sep 17 00:00:00 2001 From: Alan Woodland Date: Tue, 31 May 2016 20:50:29 +0100 Subject: [PATCH 018/455] Comment on consideration of making iterator non-static. --- Lib/java/std_list.i | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/Lib/java/std_list.i b/Lib/java/std_list.i index cc14d7353..dbce830c2 100644 --- a/Lib/java/std_list.i +++ b/Lib/java/std_list.i @@ -40,6 +40,16 @@ namespace std { typedef size_t size_type; typedef T value_type; typedef T& reference; + + /* + * We'd actually be better off having the nested class *not* be static in the wrapper + * output, but this doesn't actually remove the $static from the nested class still. + * (This would allow us to somewhat simplify the implementation of the ListIterator + * interface and give "natural" semantics to Java users of the C++ iterator) + */ + //%typemap(javaclassmodifiers) iterator "public class" + //%typemap(javainterfaces) iterator "ListIterator<$typemap(autobox,$1_basetype::value_type)>" + struct iterator { %extend { void set_unchecked(const value_type& v) { From 5eb46d5f9f106c8367f65ff499d19a6af6c438af Mon Sep 17 00:00:00 2001 From: Alan Woodland Date: Tue, 31 May 2016 20:52:58 +0100 Subject: [PATCH 019/455] Be consistent in semantics of %extend on std::list::iterator --- Lib/java/std_list.i | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/Lib/java/std_list.i b/Lib/java/std_list.i index dbce830c2..330bff854 100644 --- a/Lib/java/std_list.i +++ b/Lib/java/std_list.i @@ -72,8 +72,10 @@ namespace std { return **$self; } - void advance_unchecked(jint index) { - std::advance(*$self, index); + iterator advance_unchecked(jint index) const { + std::list::iterator ret=*$self; + std::advance(ret, index); + return ret; } } }; @@ -156,7 +158,7 @@ namespace std { private ListIterator init(int index) { pos = $javaclassname.this.begin(); - pos.advance_unchecked(index); + pos = pos.advance_unchecked(index); return this; } From c5a724f1bb1bfbcf4c0b68a9e85e62d476501dd2 Mon Sep 17 00:00:00 2001 From: Alan Woodland Date: Tue, 31 May 2016 21:34:48 +0100 Subject: [PATCH 020/455] Made the conversion from long->int for size_type mapping onto Java interfaces cleaner. --- Lib/java/std_list.i | 37 +++++++++++++++++++++---------------- 1 file changed, 21 insertions(+), 16 deletions(-) diff --git a/Lib/java/std_list.i b/Lib/java/std_list.i index 330bff854..ac786910a 100644 --- a/Lib/java/std_list.i +++ b/Lib/java/std_list.i @@ -22,12 +22,24 @@ Unfortunately that loses precision from the integer types commonly used in C++ implementations. Since we can't overload on return values the best workaround here is to expose the real C++ size() return value to Java as a - long under a different name. We can then wrap that with a Java specific - size() implementation that at least checks and fails gracefully in the case - where we have a collection with > 2^31-1 items rather than failing - mysteriously. The wrapper implementaiton is in the javacode typemap later. + long and use the javaout typemap to validate. We can then at least fails + gracefully in the case where we have a collection with > 2^31-1 items rather + than failing mysteriously. + + The use of SWIG_list_size_type here allows us to selectively %apply this to + only the cases where we have to conform to the Java interface requirement, + without interfering with other size_type usage. The intention is that + SWIG_list_size_type is both reserved and unique. (Perhaps it could live in + std_common.i later on?) */ -%rename(realSize) std::list::size; +%typemap(jstype) SWIG_list_size_type "int"; +%typemap(javaout) SWIG_list_size_type { + final long result = $jnicall; + if (result > Integer.MAX_VALUE) { + throw new IndexOutOfBoundsException("Size of Collection is not representable as int"); + } + return (int)result; +} // Match Java style better: %rename(Iterator) std::list::iterator; @@ -40,6 +52,7 @@ namespace std { typedef size_t size_type; typedef T value_type; typedef T& reference; + %apply SWIG_list_size_type { size_type next_index, size_type previous_index, size_type size }; /* * We'd actually be better off having the nested class *not* be static in the wrapper @@ -72,7 +85,7 @@ namespace std { return **$self; } - iterator advance_unchecked(jint index) const { + iterator advance_unchecked(const size_type index) const { std::list::iterator ret=*$self; std::advance(ret, index); return ret; @@ -106,11 +119,11 @@ namespace std { iterator insert(iterator pos, const value_type &v); %extend { - jint previous_index(const iterator& pos) const { + size_type previous_index(const iterator& pos) const { return pos == self->begin() ? -1 : std::distance(self->begin(), static_cast::const_iterator>(pos)); } - jint next_index(const iterator& pos) const { + size_type next_index(const iterator& pos) const { return pos == self->end() ? self->size() : std::distance(self->begin(), static_cast::const_iterator>(pos)); } @@ -143,14 +156,6 @@ namespace std { } } - public int size() { - final long val = realSize(); - if (val > Integer.MAX_VALUE) { - throw new IndexOutOfBoundsException("Size of Collection $javaclassname is not representable as int"); - } - return (int)val; - } - public ListIterator listIterator(int index) { return new ListIterator() { private JAVA_ITERATOR_TYPE pos; From 3908817fc39625fb76b49c9f96d9e535f6450d8e Mon Sep 17 00:00:00 2001 From: Alan Woodland Date: Tue, 31 May 2016 22:11:15 +0100 Subject: [PATCH 021/455] Document autobox.i --- Lib/java/autobox.i | 60 +++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 59 insertions(+), 1 deletion(-) diff --git a/Lib/java/autobox.i b/Lib/java/autobox.i index aae197ad8..9fe6b995c 100644 --- a/Lib/java/autobox.i +++ b/Lib/java/autobox.i @@ -1,4 +1,62 @@ -// Java typemaps for autoboxing in return types of generics +/* + Java typemaps for autoboxing in return types of generics. + + Java generics let you define interfaces, e.g. Collection which operate on any homogenous + collection of Objects, with compile time type checking. For example Collection can + only store String objects and the compiler helps enforce that. + + Unfortunately Java treats primitive types as a special case. They're not first class objects, + so in order to have a collection of ints we have to actually maintain a Collection. + For each primitive type in Java (boolean, byte, short, int, long, float, double) there + exists a corresponding "proper" Object type in java.lang.*. + + Although these proper Objects include a constructor and a xValue() method that allow for + explicit conversion between primitives and the corresponding Object type if programmers + were required to explicitly perform this conversion every time it would rapidly become + tedious for no real benefits. To address this the language designers introduced the + concepts of "autoboxing" and a corresponding unboxing which can happen implicitly. Thus it + becomes legal to write: + + Collection c = new ArrayList(); + double d1 = 0; + c.add(d1); // 1: void add(Double); + double d2 = c.iterator().next(); // 2: Double next(); + + The conversions required to allow lines commented 1: and 2: to compile are inserted + implicitly. + + When it comes to wrapping primitives from C or C++ code to Java SWIG by default take the path + most expected. This means that double in C++ is represented by double in Java etc. as expected. + Normally this behaviour is ideal, however when it comes to wrapping C++ templates which are + being mapped onto implementations of Java interfaces this behaviour is unhelpful because it + is a syntax error in Java to claim to implement Collection instead of + Collection. + + So to transparently allow a C++ template when wrapped to Java to accept template type + parameters of primitive, struct, enum etc. fluidly from the user perspective we need to support + the same mapping, outside of the normal default. + + This autobox typemap exists to solve exactly that problem. With it we can map primitives onto + the corresponding java.lang.* type, whilst mapping all other types onto type that they would + usually map onto. (That is to say it falls back to simply be the result of the jstype typemap + for all non-primitive types). + + So for example if a given container template in exists in C++: + + template + struct ExampleContainer { + typedef T value_type; + // ..... + }; + + When wrapped in Java we'd like it to implement the Collection interface correctly, even for + primitives. With these autobox typemaps we can now simply write the following for example: + + %typemap(javabase) ExampleContainer "Collection<$typemap(autobox,$1_basetype::value_type)>" + + Which does exactly the right thing for both primitive and non-primitive types. + +*/ %define AUTOBOX(CTYPE, JTYPE) %typemap(autobox) CTYPE, const CTYPE& "JTYPE" %enddef From 7c4109c7018dedb5e165b66de36f0dd137322b13 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Mon, 28 Nov 2016 21:32:00 +0100 Subject: [PATCH 022/455] Add helper macro to avoid duplication in Java vector typemaps No real changes yet, just use a C#-like macro in Java std::vector<> typemaps too to avoid having to repeat almost exactly the same class declaration for the general case and for the bool specialization. --- Lib/java/std_vector.i | 49 +++++++++++-------------------------------- 1 file changed, 12 insertions(+), 37 deletions(-) diff --git a/Lib/java/std_vector.i b/Lib/java/std_vector.i index 971b426a1..eea87885d 100644 --- a/Lib/java/std_vector.i +++ b/Lib/java/std_vector.i @@ -9,13 +9,11 @@ #include %} -namespace std { - - template class vector { - public: +%define SWIG_STD_VECTOR_MINIMUM_INTERNAL(CTYPE, CREF_TYPE) + public: typedef size_t size_type; - typedef T value_type; - typedef const value_type& const_reference; + typedef CTYPE value_type; + typedef CREF_TYPE const_reference; vector(); vector(size_type n); size_type size() const; @@ -27,7 +25,7 @@ namespace std { %rename(add) push_back; void push_back(const value_type& x); %extend { - const_reference get(int i) throw (std::out_of_range) { + CREF_TYPE get(int i) throw (std::out_of_range) { int size = int(self->size()); if (i>=0 && i class vector { + SWIG_STD_VECTOR_MINIMUM_INTERNAL(T, const T&) }; // bool specialization template<> class vector { - public: - typedef size_t size_type; - typedef bool value_type; - typedef bool const_reference; - vector(); - vector(size_type n); - size_type size() const; - size_type capacity() const; - void reserve(size_type n); - %rename(isEmpty) empty; - bool empty() const; - void clear(); - %rename(add) push_back; - void push_back(const value_type& x); - %extend { - bool get(int i) throw (std::out_of_range) { - int size = int(self->size()); - if (i>=0 && isize()); - if (i>=0 && i Date: Mon, 28 Nov 2016 22:38:38 +0100 Subject: [PATCH 023/455] Make std::vector<> wrappers conform to List interface in Java Derive the class wrapping std::vector<> in Java from java.util.AbstractList<>. This makes it possible to use it with various algorithms working with Java collections and, maybe even more importantly, makes it possible to iterate over the wrapped vectors using for-each loops. This commit is based on the original patch by Volker Diels-Grabsch from https://sourceforge.net/p/swig/patches/278/ --- CHANGES.current | 4 + .../test-suite/java/li_std_vector_runme.java | 14 ++- Lib/java/java.swg | 17 ++++ Lib/java/std_vector.i | 98 +++++++++++++++++-- 4 files changed, 126 insertions(+), 7 deletions(-) diff --git a/CHANGES.current b/CHANGES.current index 14f6fb4cb..c68167775 100644 --- a/CHANGES.current +++ b/CHANGES.current @@ -5,6 +5,10 @@ See the RELEASENOTES file for a summary of changes in each release. Version 3.0.11 (in progress) ============================ +2016-11-28: Volker Diels-Grabsch, vadz + [Java] Implement java.util.List<> for std::vector. This notably allows to + iterate over wrapped vectors in a natural way. + 2016-11-28: wsfulton Fix %rename override of wildcard %rename for templates. For example: diff --git a/Examples/test-suite/java/li_std_vector_runme.java b/Examples/test-suite/java/li_std_vector_runme.java index b422655a4..3238f9dd8 100644 --- a/Examples/test-suite/java/li_std_vector_runme.java +++ b/Examples/test-suite/java/li_std_vector_runme.java @@ -19,6 +19,9 @@ public class li_std_vector_runme { v1.add(123); if (v1.get(0) != 123) throw new RuntimeException("v1 test failed"); + for (int n : v1) { + if (n != 123) throw new RuntimeException("v1 loop test failed"); + } StructVector v4 = li_std_vector.vecstruct(new StructVector()); StructPtrVector v5 = li_std_vector.vecstructptr(new StructPtrVector()); @@ -28,9 +31,18 @@ public class li_std_vector_runme { v5.add(new Struct(34)); v6.add(new Struct(56)); - Struct s = null; if (v4.get(0).getNum() != 12) throw new RuntimeException("v4 test failed"); if (v5.get(0).getNum() != 34) throw new RuntimeException("v5 test failed"); if (v6.get(0).getNum() != 56) throw new RuntimeException("v6 test failed"); + + for (Struct s : v4) { + if (s.getNum() != 12) throw new RuntimeException("v4 loop test failed"); + } + for (Struct s : v5) { + if (s.getNum() != 34) throw new RuntimeException("v5 loop test failed"); + } + for (Struct s : v6) { + if (s.getNum() != 56) throw new RuntimeException("v6 loop test failed"); + } } } diff --git a/Lib/java/java.swg b/Lib/java/java.swg index f1227d0ad..225de5935 100644 --- a/Lib/java/java.swg +++ b/Lib/java/java.swg @@ -103,9 +103,25 @@ SWIGINTERN const char * SWIG_UnpackData(const char *c, void *ptr, size_t sz) { %typemap(jstype) double, const double & "double" %typemap(jstype) void "void" +%typemap(jboxtype) bool "Boolean" +%typemap(jboxtype) char "Character" +%typemap(jboxtype) signed char "Byte" +%typemap(jboxtype) unsigned char "Short" +%typemap(jboxtype) short "Short" +%typemap(jboxtype) unsigned short "Integer" +%typemap(jboxtype) int "Integer" +%typemap(jboxtype) unsigned int "Long" +%typemap(jboxtype) long "Integer" +%typemap(jboxtype) unsigned long "Long" +%typemap(jboxtype) long long "Long" +%typemap(jboxtype) unsigned long long "java.math.BigInteger" +%typemap(jboxtype) float "Float" +%typemap(jboxtype) double "Double" + %typemap(jni) char *, char *&, char[ANY], char[] "jstring" %typemap(jtype) char *, char *&, char[ANY], char[] "String" %typemap(jstype) char *, char *&, char[ANY], char[] "String" +%typemap(jboxtype) char *, char *&, char[ANY], char[] "String" /* JNI types */ %typemap(jni) jboolean "jboolean" @@ -172,6 +188,7 @@ SWIGINTERN const char * SWIG_UnpackData(const char *c, void *ptr, size_t sz) { %typemap(jni) SWIGTYPE "jlong" %typemap(jtype) SWIGTYPE "long" %typemap(jstype) SWIGTYPE "$&javaclassname" +%typemap(jboxtype) SWIGTYPE "$typemap(jstype, $1_type)" %typemap(jni) SWIGTYPE [] "jlong" %typemap(jtype) SWIGTYPE [] "long" diff --git a/Lib/java/std_vector.i b/Lib/java/std_vector.i index eea87885d..6c745aa23 100644 --- a/Lib/java/std_vector.i +++ b/Lib/java/std_vector.i @@ -10,38 +10,124 @@ %} %define SWIG_STD_VECTOR_MINIMUM_INTERNAL(CTYPE, CREF_TYPE) +%typemap(javabase) std::vector "java.util.AbstractList<$typemap(jboxtype, CTYPE)>" +%typemap(javainterfaces) std::vector "java.util.RandomAccess" +%typemap(javacode) std::vector %{ + public $javaclassname($typemap(jstype, CTYPE)[] initialElements) { + this(); + for ($typemap(jstype, CTYPE) element : initialElements) { + add(element); + } + } + + public $javaclassname(Iterable<$typemap(jboxtype, CTYPE)> initialElements) { + this(); + for ($typemap(jstype, CTYPE) element : initialElements) { + add(element); + } + } + + public $typemap(jboxtype, CTYPE) get(int index) { + return doGet(index); + } + + public $typemap(jboxtype, CTYPE) set(int index, $typemap(jboxtype, CTYPE) e) { + return doSet(index, e); + } + + public boolean add($typemap(jboxtype, CTYPE) e) { + modCount++; + doAdd(e); + return true; + } + + public void add(int index, $typemap(jboxtype, CTYPE) e) { + modCount++; + doAdd(index, e); + } + + public $typemap(jboxtype, CTYPE) remove(int index) { + modCount++; + return doRemove(index); + } + + protected void removeRange(int fromIndex, int toIndex) { + modCount++; + doRemoveRange(fromIndex, toIndex); + } +%} + public: typedef size_t size_type; typedef CTYPE value_type; typedef CREF_TYPE const_reference; vector(); vector(size_type n); - size_type size() const; + // Note that it returns int, and not size_type, for compatibility with + // the signature of size() in Java interface. + int size() const; size_type capacity() const; void reserve(size_type n); %rename(isEmpty) empty; bool empty() const; void clear(); - %rename(add) push_back; - void push_back(const value_type& x); %extend { - CREF_TYPE get(int i) throw (std::out_of_range) { + void doAdd(const value_type& value) { + self->push_back(value); + } + + void doAdd(int index, const value_type& value) throw (std::out_of_range) { + const int size = int(self->size()); + if (0 <= index && index <= size) { + self->insert(self->begin() + index, value); + } else { + throw std::out_of_range("vector index out of range"); + } + } + value_type doRemove(int index) throw (std::out_of_range) { + const int size = int(self->size()); + if (0 <= index && index < size) { + CTYPE const old_value = (*self)[index]; + self->erase(self->begin() + index); + return old_value; + } else { + throw std::out_of_range("vector index out of range"); + } + } + CREF_TYPE doGet(int i) throw (std::out_of_range) { int size = int(self->size()); if (i>=0 && isize()); - if (i>=0 && i=0 && isize()); + if (0 <= fromIndex && fromIndex <= toIndex && toIndex <= size) { + self->erase(self->begin() + fromIndex, self->begin() + toIndex); + } else { + throw std::out_of_range("vector index out of range"); + } + } } %enddef +%javamethodmodifiers std::vector::doAdd "private"; +%javamethodmodifiers std::vector::doGet "private"; +%javamethodmodifiers std::vector::doSet "private"; +%javamethodmodifiers std::vector::doRemove "private"; +%javamethodmodifiers std::vector::doRemoveRange "private"; + namespace std { template class vector { From eba70ed16f7cd6d678633d8fc98562548672933d Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Tue, 29 Nov 2016 00:20:24 +0100 Subject: [PATCH 024/455] Add runtime checks for vector size in Java It doesn't seem to be possible to have a Java collection with more than 2^31-1 items, but it is perfectly possible to have an std::vector with more elements than that in C++, so add runtime checks verifying that we don't lose count of elements in the Java wrappers. --- Lib/java/std_vector.i | 42 ++++++++++++++++++++++++++++++++++-------- 1 file changed, 34 insertions(+), 8 deletions(-) diff --git a/Lib/java/std_vector.i b/Lib/java/std_vector.i index 6c745aa23..fee33f8c2 100644 --- a/Lib/java/std_vector.i +++ b/Lib/java/std_vector.i @@ -7,6 +7,27 @@ %{ #include #include +#include + +// C++ allows to have up to 2^64-1 items in a vector on 64 bit machines and +// 2^32-1 even on 32 bit ones, but in Java size() must return a value of type +// "int" which is limited to signed 32 bit values, i.e. 2^31-1, and there +// doesn't seem to be any way to represent bigger vectors there. +// +// The only thing we can do is to at least detect such situation and throw an +// exception instead of silently returning the wrong size in this case and we +// use this helper to convert size_t values to int, instead of just casting +// them, in order to achieve this. +namespace { +int size_as_int(std::size_t sz) { + if (sz > static_cast(INT_MAX)) { + throw std::out_of_range("vector size is too big to be representable as int"); + } + + return static_cast(sz); +} +} // anonymous namespace + %} %define SWIG_STD_VECTOR_MINIMUM_INTERNAL(CTYPE, CREF_TYPE) @@ -55,6 +76,10 @@ modCount++; doRemoveRange(fromIndex, toIndex); } + + public int size() { + return doSize(); + } %} public: @@ -63,21 +88,22 @@ typedef CREF_TYPE const_reference; vector(); vector(size_type n); - // Note that it returns int, and not size_type, for compatibility with - // the signature of size() in Java interface. - int size() const; size_type capacity() const; void reserve(size_type n); %rename(isEmpty) empty; bool empty() const; void clear(); %extend { + int doSize() const { + return size_as_int(self->size()); + } + void doAdd(const value_type& value) { self->push_back(value); } void doAdd(int index, const value_type& value) throw (std::out_of_range) { - const int size = int(self->size()); + const int size = size_as_int(self->size()); if (0 <= index && index <= size) { self->insert(self->begin() + index, value); } else { @@ -85,7 +111,7 @@ } } value_type doRemove(int index) throw (std::out_of_range) { - const int size = int(self->size()); + const int size = size_as_int(self->size()); if (0 <= index && index < size) { CTYPE const old_value = (*self)[index]; self->erase(self->begin() + index); @@ -95,14 +121,14 @@ } } CREF_TYPE doGet(int i) throw (std::out_of_range) { - int size = int(self->size()); + const int size = size_as_int(self->size()); if (i>=0 && isize()); + const int size = size_as_int(self->size()); if (i>=0 && isize()); + const int size = size_as_int(self->size()); if (0 <= fromIndex && fromIndex <= toIndex && toIndex <= size) { self->erase(self->begin() + fromIndex, self->begin() + toIndex); } else { From db8bc1c9c7a02d36e9f69db6a4331d8296567fde Mon Sep 17 00:00:00 2001 From: Takashi Tamura Date: Mon, 30 Jan 2017 11:54:46 +0900 Subject: [PATCH 025/455] [python] fix std unordered containers --- Lib/python/pycontainer.swg | 14 ++--- Lib/python/pyiterators.swg | 97 +++++++++++++++++++++++++++++ Lib/python/std_map.i | 2 +- Lib/python/std_set.i | 2 +- Lib/python/std_unordered_map.i | 56 +++++------------ Lib/python/std_unordered_multimap.i | 2 +- Lib/python/std_unordered_multiset.i | 2 +- Lib/python/std_unordered_set.i | 2 +- 8 files changed, 126 insertions(+), 51 deletions(-) diff --git a/Lib/python/pycontainer.swg b/Lib/python/pycontainer.swg index d40b0baa8..b8489ed4b 100644 --- a/Lib/python/pycontainer.swg +++ b/Lib/python/pycontainer.swg @@ -654,7 +654,7 @@ namespace swig } } -%define %swig_sequence_iterator(Sequence...) +%define %swig_sequence_iterator(Make_output_iterator_func,Sequence...) #if defined(SWIG_EXPORT_ITERATOR_METHODS) class iterator; class reverse_iterator; @@ -663,15 +663,15 @@ namespace swig %typemap(out,noblock=1,fragment="SwigPySequence_Cont") iterator, reverse_iterator, const_iterator, const_reverse_iterator { - $result = SWIG_NewPointerObj(swig::make_output_iterator(%static_cast($1,const $type &)), + $result = SWIG_NewPointerObj(Make_output_iterator_func(%static_cast($1,const $type &)), swig::SwigPyIterator::descriptor(),SWIG_POINTER_OWN); } %typemap(out,noblock=1,fragment="SwigPySequence_Cont") std::pair, std::pair { $result = PyTuple_New(2); - PyTuple_SetItem($result,0,SWIG_NewPointerObj(swig::make_output_iterator(%static_cast($1,const $type &).first), + PyTuple_SetItem($result,0,SWIG_NewPointerObj(Make_output_iterator_func(%static_cast($1,const $type &).first), swig::SwigPyIterator::descriptor(),SWIG_POINTER_OWN)); - PyTuple_SetItem($result,1,SWIG_NewPointerObj(swig::make_output_iterator(%static_cast($1,const $type &).second), + PyTuple_SetItem($result,1,SWIG_NewPointerObj(Make_output_iterator_func(%static_cast($1,const $type &).second), swig::SwigPyIterator::descriptor(),SWIG_POINTER_OWN)); } @@ -680,7 +680,7 @@ namespace swig %typemap(out,noblock=1,fragment="SwigPyPairBoolOutputIterator") std::pair, std::pair { $result = PyTuple_New(2); - PyTuple_SetItem($result,0,SWIG_NewPointerObj(swig::make_output_iterator(%static_cast($1,const $type &).first), + PyTuple_SetItem($result,0,SWIG_NewPointerObj(Make_output_iterator_func(%static_cast($1,const $type &).first), swig::SwigPyIterator::descriptor(),SWIG_POINTER_OWN)); PyTuple_SetItem($result,1,SWIG_From(bool)(%static_cast($1,const $type &).second)); } @@ -715,7 +715,7 @@ namespace swig %newobject iterator(PyObject **PYTHON_SELF); %extend { swig::SwigPyIterator* iterator(PyObject **PYTHON_SELF) { - return swig::make_output_iterator(self->begin(), self->begin(), self->end(), *PYTHON_SELF); + return Make_output_iterator_func(self->begin(), self->begin(), self->end(), *PYTHON_SELF); } #if defined(SWIGPYTHON_BUILTIN) @@ -764,7 +764,7 @@ namespace swig %define %swig_sequence_methods_common(Sequence...) - %swig_sequence_iterator(%arg(Sequence)) +%swig_sequence_iterator(swig::make_output_iterator,%arg(Sequence)) %swig_container_methods(%arg(Sequence)) %fragment("SwigPySequence_Base"); diff --git a/Lib/python/pyiterators.swg b/Lib/python/pyiterators.swg index 8fbb31226..5bc47a228 100644 --- a/Lib/python/pyiterators.swg +++ b/Lib/python/pyiterators.swg @@ -195,6 +195,42 @@ namespace swig { } }; + template::value_type, + typename FromOper = from_oper > + class SwigPyForwardIteratorOpen_T : public SwigPyIterator_T + { + public: + FromOper from; + typedef OutIterator out_iterator; + typedef ValueType value_type; + typedef SwigPyIterator_T base; + typedef SwigPyForwardIteratorOpen_T self_type; + + SwigPyForwardIteratorOpen_T(out_iterator curr, PyObject *seq) + : SwigPyIterator_T(curr, seq) + { + } + + PyObject *value() const { + return from(static_cast(*(base::current))); + } + + SwigPyIterator *copy() const + { + return new self_type(*this); + } + + SwigPyIterator *incr(size_t n = 1) + { + while (n--) { + ++base::current; + } + return this; + } + + }; + template::value_type, typename FromOper = from_oper > @@ -237,6 +273,52 @@ namespace swig { return this; } }; + template::value_type, + typename FromOper = from_oper > + class SwigPyForwardIteratorClosed_T : public SwigPyIterator_T + { + public: + FromOper from; + typedef OutIterator out_iterator; + typedef ValueType value_type; + typedef SwigPyIterator_T base; + typedef SwigPyForwardIteratorClosed_T self_type; + + SwigPyForwardIteratorClosed_T(out_iterator curr, out_iterator first, out_iterator last, PyObject *seq) + : SwigPyIterator_T(curr, seq), begin(first), end(last) + { + } + + PyObject *value() const { + if (base::current == end) { + throw stop_iteration(); + } else { + return from(static_cast(*(base::current))); + } + } + + SwigPyIterator *copy() const + { + return new self_type(*this); + } + + SwigPyIterator *incr(size_t n = 1) + { + while (n--) { + if (base::current == end) { + throw stop_iteration(); + } else { + ++base::current; + } + } + return this; + } + + private: + out_iterator begin; + out_iterator end; + }; template::value_type, @@ -297,6 +379,14 @@ namespace swig { out_iterator end; }; + + template + inline SwigPyIterator* + make_output_forward_iterator(const OutIter& current, const OutIter& begin,const OutIter& end, PyObject *seq = 0) + { + return new SwigPyForwardIteratorClosed_T(current, begin, end, seq); + } + template inline SwigPyIterator* make_output_iterator(const OutIter& current, const OutIter& begin,const OutIter& end, PyObject *seq = 0) @@ -304,6 +394,13 @@ namespace swig { return new SwigPyIteratorClosed_T(current, begin, end, seq); } + template + inline SwigPyIterator* + make_output_forward_iterator(const OutIter& current, PyObject *seq = 0) + { + return new SwigPyForwardIteratorOpen_T(current, seq); + } + template inline SwigPyIterator* make_output_iterator(const OutIter& current, PyObject *seq = 0) diff --git a/Lib/python/std_map.i b/Lib/python/std_map.i index f61f79c44..0e37d065e 100644 --- a/Lib/python/std_map.i +++ b/Lib/python/std_map.i @@ -149,7 +149,7 @@ } %define %swig_map_common(Map...) - %swig_sequence_iterator(Map); + %swig_sequence_iterator(swig::make_output_iterator,Map); %swig_container_methods(Map) #if defined(SWIGPYTHON_BUILTIN) diff --git a/Lib/python/std_set.i b/Lib/python/std_set.i index 53f97e475..9820cbb3c 100644 --- a/Lib/python/std_set.i +++ b/Lib/python/std_set.i @@ -33,7 +33,7 @@ %} %define %swig_set_methods(set...) - %swig_sequence_iterator(set); + %swig_sequence_iterator(swig::make_output_iterator,set); %swig_container_methods(set); %extend { diff --git a/Lib/python/std_unordered_map.i b/Lib/python/std_unordered_map.i index 894840c6c..2af261185 100644 --- a/Lib/python/std_unordered_map.i +++ b/Lib/python/std_unordered_map.i @@ -2,7 +2,7 @@ Unordered Maps */ -%fragment("StdMapTraits","header",fragment="StdSequenceTraits") +%fragment("StdUnorderedMapTraits","header",fragment="StdSequenceTraits") { namespace swig { template @@ -74,33 +74,11 @@ } }; - template - struct from_key_oper - { - typedef const ValueType& argument_type; - typedef PyObject *result_type; - result_type operator()(argument_type v) const - { - return swig::from(v.first); - } - }; - - template - struct from_value_oper - { - typedef const ValueType& argument_type; - typedef PyObject *result_type; - result_type operator()(argument_type v) const - { - return swig::from(v.second); - } - }; - template - struct SwigPyMapIterator_T : SwigPyIteratorClosed_T + struct SwigPyMapForwardIterator_T : SwigPyForwardIteratorClosed_T { - SwigPyMapIterator_T(OutIterator curr, OutIterator first, OutIterator last, PyObject *seq) - : SwigPyIteratorClosed_T(curr, first, last, seq) + SwigPyMapForwardIterator_T(OutIterator curr, OutIterator first, OutIterator last, PyObject *seq) + : SwigPyForwardIteratorClosed_T(curr, first, last, seq) { } }; @@ -108,27 +86,27 @@ template > - struct SwigPyMapKeyIterator_T : SwigPyMapIterator_T + struct SwigPyMapKeyForwardIterator_T : SwigPyMapForwardIterator_T { - SwigPyMapKeyIterator_T(OutIterator curr, OutIterator first, OutIterator last, PyObject *seq) - : SwigPyMapIterator_T(curr, first, last, seq) + SwigPyMapKeyForwardIterator_T(OutIterator curr, OutIterator first, OutIterator last, PyObject *seq) + : SwigPyMapForwardIterator_T(curr, first, last, seq) { } }; template inline SwigPyIterator* - make_output_key_iterator(const OutIter& current, const OutIter& begin, const OutIter& end, PyObject *seq = 0) + make_output_key_forward_iterator(const OutIter& current, const OutIter& begin, const OutIter& end, PyObject *seq = 0) { - return new SwigPyMapKeyIterator_T(current, begin, end, seq); + return new SwigPyMapKeyForwardIterator_T(current, begin, end, seq); } template > - struct SwigPyMapValueITerator_T : SwigPyMapIterator_T + struct SwigPyMapValueForwardIterator_T : SwigPyMapForwardIterator_T { - SwigPyMapValueITerator_T(OutIterator curr, OutIterator first, OutIterator last, PyObject *seq) - : SwigPyMapIterator_T(curr, first, last, seq) + SwigPyMapValueForwardIterator_T(OutIterator curr, OutIterator first, OutIterator last, PyObject *seq) + : SwigPyMapForwardIterator_T(curr, first, last, seq) { } }; @@ -136,15 +114,15 @@ template inline SwigPyIterator* - make_output_value_iterator(const OutIter& current, const OutIter& begin, const OutIter& end, PyObject *seq = 0) + make_output_value_forward_iterator(const OutIter& current, const OutIter& begin, const OutIter& end, PyObject *seq = 0) { - return new SwigPyMapValueITerator_T(current, begin, end, seq); + return new SwigPyMapValueForwardIterator_T(current, begin, end, seq); } } } %define %swig_unordered_map_common(Map...) - %swig_sequence_iterator(Map); + %swig_sequence_iterator(swig::make_output_forward_iterator,Map); %swig_container_methods(Map) %extend { @@ -227,12 +205,12 @@ %newobject key_iterator(PyObject **PYTHON_SELF); swig::SwigPyIterator* key_iterator(PyObject **PYTHON_SELF) { - return swig::make_output_key_iterator(self->begin(), self->begin(), self->end(), *PYTHON_SELF); + return swig::make_output_key_forward_iterator(self->begin(), self->begin(), self->end(), *PYTHON_SELF); } %newobject value_iterator(PyObject **PYTHON_SELF); swig::SwigPyIterator* value_iterator(PyObject **PYTHON_SELF) { - return swig::make_output_value_iterator(self->begin(), self->begin(), self->end(), *PYTHON_SELF); + return swig::make_output_value_forward_iterator(self->begin(), self->begin(), self->end(), *PYTHON_SELF); } %pythoncode %{def __iter__(self): diff --git a/Lib/python/std_unordered_multimap.i b/Lib/python/std_unordered_multimap.i index 2410aa52b..f46a94b16 100644 --- a/Lib/python/std_unordered_multimap.i +++ b/Lib/python/std_unordered_multimap.i @@ -74,7 +74,7 @@ } %define %swig_unordered_multimap_methods(Type...) - %swig_map_common(Type); + %swig_unordered_map_common(Type); %extend { void __setitem__(const key_type& key, const mapped_type& x) throw (std::out_of_range) { self->insert(Type::value_type(key,x)); diff --git a/Lib/python/std_unordered_multiset.i b/Lib/python/std_unordered_multiset.i index 0d9f3d9c6..d90a97bdc 100644 --- a/Lib/python/std_unordered_multiset.i +++ b/Lib/python/std_unordered_multiset.i @@ -41,7 +41,7 @@ } %} -#define %swig_unordered_multiset_methods(Set...) %swig_set_methods(Set) +#define %swig_unordered_multiset_methods(Set...) %swig_unordered_set_methods(Set) diff --git a/Lib/python/std_unordered_set.i b/Lib/python/std_unordered_set.i index 855a28da5..4db24f74b 100644 --- a/Lib/python/std_unordered_set.i +++ b/Lib/python/std_unordered_set.i @@ -40,7 +40,7 @@ %} %define %swig_unordered_set_methods(unordered_set...) - %swig_sequence_iterator(unordered_set); + %swig_sequence_iterator(swig::make_output_forward_iterator,unordered_set); %swig_container_methods(unordered_set); %extend { From 9c6d5dc53c2fa90718753daa2aeeecf0ea769da0 Mon Sep 17 00:00:00 2001 From: Takashi Tamura Date: Mon, 30 Jan 2017 16:37:33 +0900 Subject: [PATCH 026/455] [python] make SwigPyIteratorClosed_T and SwigPyIteratorOpen_T inherit from forward iterator classes. --- Lib/python/pyiterators.swg | 62 ++++++-------------------------------- 1 file changed, 9 insertions(+), 53 deletions(-) diff --git a/Lib/python/pyiterators.swg b/Lib/python/pyiterators.swg index 5bc47a228..cb15e35cd 100644 --- a/Lib/python/pyiterators.swg +++ b/Lib/python/pyiterators.swg @@ -234,7 +234,7 @@ namespace swig { template::value_type, typename FromOper = from_oper > - class SwigPyIteratorOpen_T : public SwigPyIterator_T + class SwigPyIteratorOpen_T : public SwigPyForwardIteratorOpen_T { public: FromOper from; @@ -244,26 +244,9 @@ namespace swig { typedef SwigPyIteratorOpen_T self_type; SwigPyIteratorOpen_T(out_iterator curr, PyObject *seq) - : SwigPyIterator_T(curr, seq) + : SwigPyForwardIteratorOpen_T(curr, seq) { } - - PyObject *value() const { - return from(static_cast(*(base::current))); - } - - SwigPyIterator *copy() const - { - return new self_type(*this); - } - - SwigPyIterator *incr(size_t n = 1) - { - while (n--) { - ++base::current; - } - return this; - } SwigPyIterator *decr(size_t n = 1) { @@ -273,6 +256,7 @@ namespace swig { return this; } }; + template::value_type, typename FromOper = from_oper > @@ -315,7 +299,7 @@ namespace swig { return this; } - private: + protected: out_iterator begin; out_iterator end; }; @@ -323,49 +307,25 @@ namespace swig { template::value_type, typename FromOper = from_oper > - class SwigPyIteratorClosed_T : public SwigPyIterator_T + class SwigPyIteratorClosed_T : public SwigPyForwardIteratorClosed_T { public: FromOper from; typedef OutIterator out_iterator; typedef ValueType value_type; - typedef SwigPyIterator_T base; + typedef SwigPyIterator_T base; + typedef SwigPyForwardIteratorClosed_T base0; typedef SwigPyIteratorClosed_T self_type; SwigPyIteratorClosed_T(out_iterator curr, out_iterator first, out_iterator last, PyObject *seq) - : SwigPyIterator_T(curr, seq), begin(first), end(last) + : SwigPyForwardIteratorClosed_T(curr, first, last, seq) { } - - PyObject *value() const { - if (base::current == end) { - throw stop_iteration(); - } else { - return from(static_cast(*(base::current))); - } - } - - SwigPyIterator *copy() const - { - return new self_type(*this); - } - - SwigPyIterator *incr(size_t n = 1) - { - while (n--) { - if (base::current == end) { - throw stop_iteration(); - } else { - ++base::current; - } - } - return this; - } SwigPyIterator *decr(size_t n = 1) { while (n--) { - if (base::current == begin) { + if (base::current == base0::begin) { throw stop_iteration(); } else { --base::current; @@ -373,10 +333,6 @@ namespace swig { } return this; } - - private: - out_iterator begin; - out_iterator end; }; From 3174e1488c6b906222993afaa7ce84e93bbd2ee5 Mon Sep 17 00:00:00 2001 From: Takashi Tamura Date: Tue, 31 Jan 2017 16:21:39 +0900 Subject: [PATCH 027/455] [python] add %swig_sequence_iterator_with_making_function and make %swig_sequence_iterator forward to it. add %swig_sequence_forward_iterator too. --- Lib/python/pycontainer.swg | 22 +++++++++++++++------- Lib/python/std_map.i | 2 +- Lib/python/std_set.i | 2 +- Lib/python/std_unordered_map.i | 2 +- Lib/python/std_unordered_set.i | 2 +- 5 files changed, 19 insertions(+), 11 deletions(-) diff --git a/Lib/python/pycontainer.swg b/Lib/python/pycontainer.swg index b8489ed4b..287bb14b6 100644 --- a/Lib/python/pycontainer.swg +++ b/Lib/python/pycontainer.swg @@ -654,7 +654,15 @@ namespace swig } } -%define %swig_sequence_iterator(Make_output_iterator_func,Sequence...) +%define %swig_sequence_iterator(Sequence...) + %swig_sequence_iterator_with_making_function(swig::make_output_iterator,Sequence...) +%enddef + +%define %swig_sequence_forward_iterator(Sequence...) + %swig_sequence_iterator_with_making_function(swig::make_output_forward_iterator,Sequence...) +%enddef + +%define %swig_sequence_iterator_with_making_function(Make_output_iterator,Sequence...) #if defined(SWIG_EXPORT_ITERATOR_METHODS) class iterator; class reverse_iterator; @@ -663,15 +671,15 @@ namespace swig %typemap(out,noblock=1,fragment="SwigPySequence_Cont") iterator, reverse_iterator, const_iterator, const_reverse_iterator { - $result = SWIG_NewPointerObj(Make_output_iterator_func(%static_cast($1,const $type &)), + $result = SWIG_NewPointerObj(Make_output_iterator(%static_cast($1,const $type &)), swig::SwigPyIterator::descriptor(),SWIG_POINTER_OWN); } %typemap(out,noblock=1,fragment="SwigPySequence_Cont") std::pair, std::pair { $result = PyTuple_New(2); - PyTuple_SetItem($result,0,SWIG_NewPointerObj(Make_output_iterator_func(%static_cast($1,const $type &).first), + PyTuple_SetItem($result,0,SWIG_NewPointerObj(Make_output_iterator(%static_cast($1,const $type &).first), swig::SwigPyIterator::descriptor(),SWIG_POINTER_OWN)); - PyTuple_SetItem($result,1,SWIG_NewPointerObj(Make_output_iterator_func(%static_cast($1,const $type &).second), + PyTuple_SetItem($result,1,SWIG_NewPointerObj(Make_output_iterator(%static_cast($1,const $type &).second), swig::SwigPyIterator::descriptor(),SWIG_POINTER_OWN)); } @@ -680,7 +688,7 @@ namespace swig %typemap(out,noblock=1,fragment="SwigPyPairBoolOutputIterator") std::pair, std::pair { $result = PyTuple_New(2); - PyTuple_SetItem($result,0,SWIG_NewPointerObj(Make_output_iterator_func(%static_cast($1,const $type &).first), + PyTuple_SetItem($result,0,SWIG_NewPointerObj(Make_output_iterator(%static_cast($1,const $type &).first), swig::SwigPyIterator::descriptor(),SWIG_POINTER_OWN)); PyTuple_SetItem($result,1,SWIG_From(bool)(%static_cast($1,const $type &).second)); } @@ -715,7 +723,7 @@ namespace swig %newobject iterator(PyObject **PYTHON_SELF); %extend { swig::SwigPyIterator* iterator(PyObject **PYTHON_SELF) { - return Make_output_iterator_func(self->begin(), self->begin(), self->end(), *PYTHON_SELF); + return Make_output_iterator(self->begin(), self->begin(), self->end(), *PYTHON_SELF); } #if defined(SWIGPYTHON_BUILTIN) @@ -764,7 +772,7 @@ namespace swig %define %swig_sequence_methods_common(Sequence...) -%swig_sequence_iterator(swig::make_output_iterator,%arg(Sequence)) + %swig_sequence_iterator(%arg(Sequence)) %swig_container_methods(%arg(Sequence)) %fragment("SwigPySequence_Base"); diff --git a/Lib/python/std_map.i b/Lib/python/std_map.i index 0e37d065e..f61f79c44 100644 --- a/Lib/python/std_map.i +++ b/Lib/python/std_map.i @@ -149,7 +149,7 @@ } %define %swig_map_common(Map...) - %swig_sequence_iterator(swig::make_output_iterator,Map); + %swig_sequence_iterator(Map); %swig_container_methods(Map) #if defined(SWIGPYTHON_BUILTIN) diff --git a/Lib/python/std_set.i b/Lib/python/std_set.i index 9820cbb3c..53f97e475 100644 --- a/Lib/python/std_set.i +++ b/Lib/python/std_set.i @@ -33,7 +33,7 @@ %} %define %swig_set_methods(set...) - %swig_sequence_iterator(swig::make_output_iterator,set); + %swig_sequence_iterator(set); %swig_container_methods(set); %extend { diff --git a/Lib/python/std_unordered_map.i b/Lib/python/std_unordered_map.i index 2af261185..8ab4b1447 100644 --- a/Lib/python/std_unordered_map.i +++ b/Lib/python/std_unordered_map.i @@ -122,7 +122,7 @@ } %define %swig_unordered_map_common(Map...) - %swig_sequence_iterator(swig::make_output_forward_iterator,Map); + %swig_sequence_forward_iterator(Map); %swig_container_methods(Map) %extend { diff --git a/Lib/python/std_unordered_set.i b/Lib/python/std_unordered_set.i index 4db24f74b..6c646509c 100644 --- a/Lib/python/std_unordered_set.i +++ b/Lib/python/std_unordered_set.i @@ -40,7 +40,7 @@ %} %define %swig_unordered_set_methods(unordered_set...) - %swig_sequence_iterator(swig::make_output_forward_iterator,unordered_set); + %swig_sequence_forward_iterator(unordered_set); %swig_container_methods(unordered_set); %extend { From 904bc2ad52fce9da3489febb89263bf1ce245360 Mon Sep 17 00:00:00 2001 From: Takashi Tamura Date: Sat, 18 Feb 2017 16:27:23 +0900 Subject: [PATCH 028/455] [ruby] fix support for std::wstring. --- Lib/ruby/rubywstrings.swg | 69 ++++++++++++++------------------------- Lib/ruby/std_wstring.i | 14 ++++++++ 2 files changed, 39 insertions(+), 44 deletions(-) diff --git a/Lib/ruby/rubywstrings.swg b/Lib/ruby/rubywstrings.swg index b6dd937a5..b0c9b98c6 100644 --- a/Lib/ruby/rubywstrings.swg +++ b/Lib/ruby/rubywstrings.swg @@ -15,38 +15,17 @@ SWIGINTERN int SWIG_AsWCharPtrAndSize(VALUE obj, wchar_t **cptr, size_t *psize, int *alloc) { - return SWIG_AsCharPtrAndSize( obj, (char**)cptr, psize, alloc); -// VALUE tmp = 0; -// bool ok = false; -// if ( TYPE(obj) == T_STRING ) { -// if (cptr) { -// obj = tmp = SWIG_Unicode_FromObject(obj); -// ok = true; -// } -// } -// if (ok) { -// Py_ssize_t len = PyUnicode_GetSize(obj); -// rb_notimplement(); -// if (cptr) { -// *cptr = %new_array(len + 1, wchar_t); -// SWIG_Unicode_AsWideChar((PyUnicodeObject *)obj, *cptr, len); -// (*cptr)[len] = 0; -// } -// if (psize) *psize = (size_t) len + 1; -// if (alloc) *alloc = cptr ? SWIG_NEWOBJ : 0; -// return SWIG_OK; -// } else { -// swig_type_info* pwchar_descriptor = SWIG_pwchar_descriptor(); -// if (pwchar_descriptor) { -// void * vptr = 0; -// if (SWIG_ConvertPtr(obj, &vptr, pwchar_descriptor, 0) == SWIG_OK) { -// if (cptr) *cptr = (wchar_t *)vptr; -// if (psize) *psize = vptr ? (wcslen((wchar_t *)vptr) + 1) : 0; -// return SWIG_OK; -// } -// } -// } -// return SWIG_TypeError; + VALUE tmp; + *alloc = SWIG_NEWOBJ; + if(sizeof(wchar_t) == 4) { + tmp = rb_str_conv_enc(obj, rb_enc_get(obj), rb_to_encoding(rb_str_new_cstr("UTF-32")) ); + } else if (sizeof(wchar_t) == 2) { + tmp = rb_str_conv_enc(obj, rb_enc_get(obj), rb_to_encoding(rb_str_new_cstr("UTF-16")) ); + } else { + rb_raise(rb_eRuntimeError, "unsupported wchar_t size"); + } + return SWIG_AsCharPtrAndSize( tmp, (char**)cptr, psize, alloc); + } } @@ -54,18 +33,20 @@ SWIG_AsWCharPtrAndSize(VALUE obj, wchar_t **cptr, size_t *psize, int *alloc) SWIGINTERNINLINE VALUE SWIG_FromWCharPtrAndSize(const wchar_t * carray, size_t size) { - return SWIG_FromCharPtrAndSize( (const char*)carray, size); -// if (carray) { -// if (size > INT_MAX) { -// swig_type_info* pwchar_descriptor = SWIG_pwchar_descriptor(); -// return pwchar_descriptor ? -// SWIG_NewPointerObj(%const_cast(carray,wchar_t *), pwchar_descriptor, 0) : Qnil; -// } else { -// return SWIG_Unicode_FromWideChar(carray, %numeric_cast(size,int)); -// } -// } else { -// return Qnil; -// } + VALUE ret = SWIG_FromCharPtrAndSize( (const char*)carray, size); + rb_encoding* enc = rb_default_internal_encoding(); + if(sizeof(wchar_t) == 4) { + rb_enc_associate(ret, rb_to_encoding(rb_str_new_cstr("UTF-32"))); + } else if (sizeof(wchar_t) == 2) { + rb_enc_associate(ret, rb_to_encoding(rb_str_new_cstr("UTF-16"))); + } else { + rb_raise(rb_eRuntimeError, "unsupported wchar_t size"); + } + + if( !enc ) { + enc = rb_to_encoding(rb_str_new_cstr("UTF-8")); + } + return rb_str_conv_enc(ret, rb_enc_get(ret), enc ); } } diff --git a/Lib/ruby/std_wstring.i b/Lib/ruby/std_wstring.i index 5ca77c0c8..4ee47bb26 100644 --- a/Lib/ruby/std_wstring.i +++ b/Lib/ruby/std_wstring.i @@ -1,3 +1,17 @@ +%{ +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef HAVE_RUBY_ENCODING_H +#include "ruby/encoding.h" +#endif + +#ifdef __cplusplus +} +#endif +%} + %include %include From bfe720457641b5cf38676a00a8164324d455b612 Mon Sep 17 00:00:00 2001 From: Takashi Tamura Date: Sat, 18 Feb 2017 17:54:03 +0900 Subject: [PATCH 029/455] [ruby] add a few tests for std::wstring --- Examples/test-suite/ruby/Makefile.in | 1 + .../test-suite/ruby/li_std_wstring_runme.rb | 22 +++++++++++++++++++ Lib/ruby/std_basic_string.i | 4 ++++ 3 files changed, 27 insertions(+) create mode 100644 Examples/test-suite/ruby/li_std_wstring_runme.rb diff --git a/Examples/test-suite/ruby/Makefile.in b/Examples/test-suite/ruby/Makefile.in index a127860b0..cb47b1c35 100644 --- a/Examples/test-suite/ruby/Makefile.in +++ b/Examples/test-suite/ruby/Makefile.in @@ -19,6 +19,7 @@ CPP_TEST_CASES = \ li_std_queue \ li_std_set \ li_std_stack \ + li_std_wstring \ primitive_types \ ruby_keywords \ ruby_minherit_shared_ptr \ diff --git a/Examples/test-suite/ruby/li_std_wstring_runme.rb b/Examples/test-suite/ruby/li_std_wstring_runme.rb new file mode 100644 index 000000000..eafb81f70 --- /dev/null +++ b/Examples/test-suite/ruby/li_std_wstring_runme.rb @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +require 'swig_assert' +require 'li_std_wstring' + +x = "h" + +swig_assert_equal("Li_std_wstring.test_value(x)", "x", binding) + + +x = "abc" + +swig_assert_equal("Li_std_wstring.test_value(x)", "x", binding) + +x = "hello" + +swig_assert_equal("Li_std_wstring.test_const_reference(x)", "x", binding) + +a = Li_std_wstring::A.new(x) + +swig_assert_equal("Li_std_wstring.test_value(a)", "x", binding) + +swig_assert_equal("Li_std_wstring.test_value(x)", "x", binding) diff --git a/Lib/ruby/std_basic_string.i b/Lib/ruby/std_basic_string.i index 1351177fc..a51333793 100644 --- a/Lib/ruby/std_basic_string.i +++ b/Lib/ruby/std_basic_string.i @@ -55,6 +55,10 @@ SWIGINTERNINLINE VALUE #if !defined(SWIG_STD_WSTRING) +%traits_swigtype(std::basic_string); +%fragment(SWIG_Traits_frag(std::basic_string)); + + %fragment(SWIG_AsPtr_frag(std::basic_string),"header", fragment="SWIG_AsWCharPtrAndSize") { SWIGINTERN int From 5722d81a09bb3380d99539e84f6a5ce429df189c Mon Sep 17 00:00:00 2001 From: Takashi Tamura Date: Sun, 19 Feb 2017 15:57:34 +0900 Subject: [PATCH 030/455] [ruby] use WCHAR_MAX to determine the encoding of std::wstring. --- Lib/ruby/rubywstrings.swg | 32 +++++++------------------------- Lib/ruby/std_wstring.i | 25 +++++++++++++++++++++++++ 2 files changed, 32 insertions(+), 25 deletions(-) diff --git a/Lib/ruby/rubywstrings.swg b/Lib/ruby/rubywstrings.swg index b0c9b98c6..afdeb1277 100644 --- a/Lib/ruby/rubywstrings.swg +++ b/Lib/ruby/rubywstrings.swg @@ -1,13 +1,6 @@ /* ----------------------------------------------------------------------------- * rubywstrings.swg * - * Currently, Ruby does not support Unicode or WChar properly, so these - * are still treated as char arrays for now. - * There are other libraries available that add support to this in - * ruby including WString, FXString, etc. - * ----------------------------------------------------------------------------- */ - -/* ------------------------------------------------------------ * utility methods for wchar_t strings * ------------------------------------------------------------ */ @@ -15,17 +8,11 @@ SWIGINTERN int SWIG_AsWCharPtrAndSize(VALUE obj, wchar_t **cptr, size_t *psize, int *alloc) { - VALUE tmp; + VALUE tmp = rb_str_conv_enc(obj, rb_enc_get(obj), + rb_to_encoding(rb_str_new_cstr( SWIG_RUBY_WSTRING_ENCODING )) ); *alloc = SWIG_NEWOBJ; - if(sizeof(wchar_t) == 4) { - tmp = rb_str_conv_enc(obj, rb_enc_get(obj), rb_to_encoding(rb_str_new_cstr("UTF-32")) ); - } else if (sizeof(wchar_t) == 2) { - tmp = rb_str_conv_enc(obj, rb_enc_get(obj), rb_to_encoding(rb_str_new_cstr("UTF-16")) ); - } else { - rb_raise(rb_eRuntimeError, "unsupported wchar_t size"); - } - return SWIG_AsCharPtrAndSize( tmp, (char**)cptr, psize, alloc); + return SWIG_AsCharPtrAndSize(tmp, (char**)cptr, psize, alloc); } } @@ -35,18 +22,13 @@ SWIG_FromWCharPtrAndSize(const wchar_t * carray, size_t size) { VALUE ret = SWIG_FromCharPtrAndSize( (const char*)carray, size); rb_encoding* enc = rb_default_internal_encoding(); - if(sizeof(wchar_t) == 4) { - rb_enc_associate(ret, rb_to_encoding(rb_str_new_cstr("UTF-32"))); - } else if (sizeof(wchar_t) == 2) { - rb_enc_associate(ret, rb_to_encoding(rb_str_new_cstr("UTF-16"))); - } else { - rb_raise(rb_eRuntimeError, "unsupported wchar_t size"); - } + + rb_enc_associate(ret, rb_to_encoding(rb_str_new_cstr( SWIG_RUBY_WSTRING_ENCODING )) ); if( !enc ) { - enc = rb_to_encoding(rb_str_new_cstr("UTF-8")); + enc = rb_to_encoding(rb_str_new_cstr( SWIG_RUBY_INTERNAL_ENCODING )); } - return rb_str_conv_enc(ret, rb_enc_get(ret), enc ); + return rb_str_conv_enc(ret, rb_enc_get(ret), enc); } } diff --git a/Lib/ruby/std_wstring.i b/Lib/ruby/std_wstring.i index 4ee47bb26..b99a71945 100644 --- a/Lib/ruby/std_wstring.i +++ b/Lib/ruby/std_wstring.i @@ -7,6 +7,31 @@ extern "C" { #include "ruby/encoding.h" #endif +/** + * The internal encoding of std::wstring is defined based on + * the size of wchar_t. If it is not appropriate for your library, + * SWIG_RUBY_WSTRING_ENCODING must be given when compiling. + */ +#ifndef SWIG_RUBY_WSTRING_ENCODING + +#if WCHAR_MAX == 0x7fff || WCHAR_MAX == 0xffff +#define SWIG_RUBY_WSTRING_ENCODING "UTF-16" +#elif WCHAR_MAX == 0x7fffffff || WCHAR_MAX == 0xffffffff +#define SWIG_RUBY_WSTRING_ENCODING "UTF-32" +#else +#error unsupported wchar_t size. SWIG_RUBY_WSTRING_ENCODING must be given. +#endif + +#endif + +/** + * If Encoding.default_internal is nil, this encoding will be used + * when coverting from std::wstring to String object in Ruby. + */ +#ifndef SWIG_RUBY_INTERNAL_ENCODING +#define SWIG_RUBY_INTERNAL_ENCODING "UTF-8" +#endif + #ifdef __cplusplus } #endif From 4009da3588e9beb81fa9dfc02697da757edb4ce8 Mon Sep 17 00:00:00 2001 From: Takashi Tamura Date: Mon, 20 Feb 2017 17:00:52 +0900 Subject: [PATCH 031/455] [ruby] * rewrite SWIG_AsWCharPtrAndSize and SWIG_FromWCharPtrAndSize * use UTF-32LE and UTF-16LE to avoid BOM * add tests --- Examples/test-suite/li_std_wstring.i | 4 ++ .../test-suite/ruby/li_std_wstring_runme.rb | 39 ++++++++++++------ Lib/ruby/rubywstrings.swg | 41 ++++++++++++++----- Lib/ruby/std_wstring.i | 4 +- 4 files changed, 64 insertions(+), 24 deletions(-) diff --git a/Examples/test-suite/li_std_wstring.i b/Examples/test-suite/li_std_wstring.i index 3c2d6f183..fe1166be3 100644 --- a/Examples/test-suite/li_std_wstring.i +++ b/Examples/test-suite/li_std_wstring.i @@ -78,6 +78,10 @@ std::wstring& test_reference_out() { return x; } +bool test_equal_abc(const std::wstring &s) { + return L"abc" == s; +} + #if defined(_MSC_VER) #pragma warning(disable: 4290) // C++ exception specification ignored except to indicate a function is not __declspec(nothrow) #endif diff --git a/Examples/test-suite/ruby/li_std_wstring_runme.rb b/Examples/test-suite/ruby/li_std_wstring_runme.rb index eafb81f70..4e32fced9 100644 --- a/Examples/test-suite/ruby/li_std_wstring_runme.rb +++ b/Examples/test-suite/ruby/li_std_wstring_runme.rb @@ -2,21 +2,36 @@ require 'swig_assert' require 'li_std_wstring' -x = "h" - -swig_assert_equal("Li_std_wstring.test_value(x)", "x", binding) - - x = "abc" +swig_assert_equal("Li_std_wstring.test_wchar_overload(x)", "x", binding) +swig_assert_equal("Li_std_wstring.test_ccvalue(x)", "x", binding) +swig_assert_equal("Li_std_wstring.test_value(Li_std_wstring::Wstring.new(x))", "x", binding) +swig_assert_equal("Li_std_wstring.test_wchar_overload()", "nil", binding) + +swig_assert_equal("Li_std_wstring.test_pointer(Li_std_wstring::Wstring.new(x))", "nil", binding) +swig_assert_equal("Li_std_wstring.test_const_pointer(Li_std_wstring::Wstring.new(x))", "nil", binding) +swig_assert_equal("Li_std_wstring.test_const_pointer(Li_std_wstring::Wstring.new(x))", "nil", binding) +swig_assert_equal("Li_std_wstring.test_reference(Li_std_wstring::Wstring.new(x))", "nil", binding) + +x = "y" swig_assert_equal("Li_std_wstring.test_value(x)", "x", binding) - -x = "hello" - -swig_assert_equal("Li_std_wstring.test_const_reference(x)", "x", binding) - a = Li_std_wstring::A.new(x) - swig_assert_equal("Li_std_wstring.test_value(a)", "x", binding) -swig_assert_equal("Li_std_wstring.test_value(x)", "x", binding) +x = "hello" +swig_assert_equal("Li_std_wstring.test_const_reference(x)", "x", binding) + + +swig_assert_equal("Li_std_wstring.test_pointer_out", "'x'", binding) +swig_assert_equal("Li_std_wstring.test_const_pointer_out", "'x'", binding) +swig_assert_equal("Li_std_wstring.test_reference_out()", "'x'", binding) + +s = "abc" +swig_assert("Li_std_wstring.test_equal_abc(s)", binding) + +begin + Li_std_wstring.test_throw +rescue RuntimeError => e + swig_assert_equal("e.message", "'x'", binding) +end diff --git a/Lib/ruby/rubywstrings.swg b/Lib/ruby/rubywstrings.swg index afdeb1277..043f213bc 100644 --- a/Lib/ruby/rubywstrings.swg +++ b/Lib/ruby/rubywstrings.swg @@ -8,11 +8,28 @@ SWIGINTERN int SWIG_AsWCharPtrAndSize(VALUE obj, wchar_t **cptr, size_t *psize, int *alloc) { - VALUE tmp = rb_str_conv_enc(obj, rb_enc_get(obj), - rb_to_encoding(rb_str_new_cstr( SWIG_RUBY_WSTRING_ENCODING )) ); - *alloc = SWIG_NEWOBJ; - return SWIG_AsCharPtrAndSize(tmp, (char**)cptr, psize, alloc); + if (TYPE(obj) == T_STRING) { + VALUE tmp = rb_str_conv_enc(obj, rb_enc_get(obj), + rb_to_encoding(rb_str_new_cstr( SWIG_RUBY_WSTRING_ENCODING )) ); + wchar_t* cstr = (wchar_t*) StringValuePtr(tmp); + size_t size = RSTRING_LEN(tmp) / sizeof(wchar_t) + 1; + + if( RSTRING_LEN(tmp) % sizeof(wchar_t) != 0 ) { + rb_raise(rb_eRuntimeError, + "The length of the byte sequence of converted string is not a multiplier of sizeof(wchar_t). Invalid byte sequence is given. Or invalid SWIG_RUBY_WSTRING_ENCODING is given when compiling this binding."); + } + if (cptr && alloc) { + *alloc = SWIG_NEWOBJ; + *cptr = %new_array(size, wchar_t); + memmove(*cptr, cstr, RSTRING_LEN(tmp)); + } + if(psize) *psize = size; + + return SWIG_OK; + } else { + return SWIG_TypeError; + } } } @@ -20,15 +37,19 @@ SWIG_AsWCharPtrAndSize(VALUE obj, wchar_t **cptr, size_t *psize, int *alloc) SWIGINTERNINLINE VALUE SWIG_FromWCharPtrAndSize(const wchar_t * carray, size_t size) { - VALUE ret = SWIG_FromCharPtrAndSize( (const char*)carray, size); - rb_encoding* enc = rb_default_internal_encoding(); + if (carray && size <= LONG_MAX) { + VALUE ret = rb_str_new( (const char*)carray, %numeric_cast(size*sizeof(wchar_t),long) ); + rb_encoding* new_enc = rb_default_internal_encoding(); - rb_enc_associate(ret, rb_to_encoding(rb_str_new_cstr( SWIG_RUBY_WSTRING_ENCODING )) ); + rb_enc_associate(ret, rb_to_encoding(rb_str_new_cstr( SWIG_RUBY_WSTRING_ENCODING )) ); - if( !enc ) { - enc = rb_to_encoding(rb_str_new_cstr( SWIG_RUBY_INTERNAL_ENCODING )); + if( !new_enc ) { + new_enc = rb_to_encoding(rb_str_new_cstr( SWIG_RUBY_INTERNAL_ENCODING )); + } + return rb_str_conv_enc(ret, rb_enc_get(ret), new_enc); + } else { + return Qnil; } - return rb_str_conv_enc(ret, rb_enc_get(ret), enc); } } diff --git a/Lib/ruby/std_wstring.i b/Lib/ruby/std_wstring.i index b99a71945..d41aa064b 100644 --- a/Lib/ruby/std_wstring.i +++ b/Lib/ruby/std_wstring.i @@ -15,9 +15,9 @@ extern "C" { #ifndef SWIG_RUBY_WSTRING_ENCODING #if WCHAR_MAX == 0x7fff || WCHAR_MAX == 0xffff -#define SWIG_RUBY_WSTRING_ENCODING "UTF-16" +#define SWIG_RUBY_WSTRING_ENCODING "UTF-16LE" #elif WCHAR_MAX == 0x7fffffff || WCHAR_MAX == 0xffffffff -#define SWIG_RUBY_WSTRING_ENCODING "UTF-32" +#define SWIG_RUBY_WSTRING_ENCODING "UTF-32LE" #else #error unsupported wchar_t size. SWIG_RUBY_WSTRING_ENCODING must be given. #endif From 89695255e63c8051266c2fd291400288aafad6ac Mon Sep 17 00:00:00 2001 From: Takashi Tamura Date: Mon, 20 Feb 2017 17:49:17 +0900 Subject: [PATCH 032/455] [ruby] add std::wstring tests for string including a null terminator. --- Examples/test-suite/ruby/li_std_wstring_runme.rb | 5 +++++ Lib/ruby/std_wstring.i | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/Examples/test-suite/ruby/li_std_wstring_runme.rb b/Examples/test-suite/ruby/li_std_wstring_runme.rb index 4e32fced9..0cf38ae4b 100644 --- a/Examples/test-suite/ruby/li_std_wstring_runme.rb +++ b/Examples/test-suite/ruby/li_std_wstring_runme.rb @@ -35,3 +35,8 @@ begin rescue RuntimeError => e swig_assert_equal("e.message", "'x'", binding) end + +x = "abc\0def" +swig_assert_equal("Li_std_wstring.test_value(x)", "x", binding) +swig_assert_equal("Li_std_wstring.test_ccvalue(x)", '"abc"', binding) +swig_assert_equal("Li_std_wstring.test_wchar_overload(x)", '"abc"', binding) diff --git a/Lib/ruby/std_wstring.i b/Lib/ruby/std_wstring.i index d41aa064b..943b4f770 100644 --- a/Lib/ruby/std_wstring.i +++ b/Lib/ruby/std_wstring.i @@ -26,7 +26,7 @@ extern "C" { /** * If Encoding.default_internal is nil, this encoding will be used - * when coverting from std::wstring to String object in Ruby. + * when converting from std::wstring to String object in Ruby. */ #ifndef SWIG_RUBY_INTERNAL_ENCODING #define SWIG_RUBY_INTERNAL_ENCODING "UTF-8" From e7eece9bcded750f51518e3356da2120eb4c05fd Mon Sep 17 00:00:00 2001 From: Takashi Tamura Date: Tue, 21 Feb 2017 17:33:10 +0900 Subject: [PATCH 033/455] [ruby] * use static variable to avoid creating stirngs every time. * fix possible overflow. --- Lib/ruby/rubywstrings.swg | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/Lib/ruby/rubywstrings.swg b/Lib/ruby/rubywstrings.swg index 043f213bc..54724b268 100644 --- a/Lib/ruby/rubywstrings.swg +++ b/Lib/ruby/rubywstrings.swg @@ -8,23 +8,23 @@ SWIGINTERN int SWIG_AsWCharPtrAndSize(VALUE obj, wchar_t **cptr, size_t *psize, int *alloc) { + static rb_encoding* wstr_enc = rb_to_encoding(rb_str_new_cstr( SWIG_RUBY_WSTRING_ENCODING )); if (TYPE(obj) == T_STRING) { - VALUE tmp = rb_str_conv_enc(obj, rb_enc_get(obj), - rb_to_encoding(rb_str_new_cstr( SWIG_RUBY_WSTRING_ENCODING )) ); - wchar_t* cstr = (wchar_t*) StringValuePtr(tmp); - size_t size = RSTRING_LEN(tmp) / sizeof(wchar_t) + 1; + VALUE rstr = rb_str_conv_enc(obj, rb_enc_get(obj), wstr_enc); + wchar_t* cstr = (wchar_t*) StringValuePtr(rstr); + size_t size = RSTRING_LEN(rstr) / sizeof(wchar_t) + 1; - if( RSTRING_LEN(tmp) % sizeof(wchar_t) != 0 ) { + if ( RSTRING_LEN(rstr) % sizeof(wchar_t) != 0 ) { rb_raise(rb_eRuntimeError, "The length of the byte sequence of converted string is not a multiplier of sizeof(wchar_t). Invalid byte sequence is given. Or invalid SWIG_RUBY_WSTRING_ENCODING is given when compiling this binding."); } if (cptr && alloc) { *alloc = SWIG_NEWOBJ; *cptr = %new_array(size, wchar_t); - memmove(*cptr, cstr, RSTRING_LEN(tmp)); + memmove(*cptr, cstr, RSTRING_LEN(rstr)); } - if(psize) *psize = size; + if (psize) *psize = size; return SWIG_OK; } else { @@ -37,16 +37,18 @@ SWIG_AsWCharPtrAndSize(VALUE obj, wchar_t **cptr, size_t *psize, int *alloc) SWIGINTERNINLINE VALUE SWIG_FromWCharPtrAndSize(const wchar_t * carray, size_t size) { - if (carray && size <= LONG_MAX) { - VALUE ret = rb_str_new( (const char*)carray, %numeric_cast(size*sizeof(wchar_t),long) ); + static rb_encoding* wstr_enc = rb_to_encoding(rb_str_new_cstr( SWIG_RUBY_WSTRING_ENCODING )); + static rb_encoding* rb_enc = rb_to_encoding(rb_str_new_cstr( SWIG_RUBY_INTERNAL_ENCODING )); + + if (carray && size <= LONG_MAX/sizeof(wchar_t)) { + VALUE rstr = rb_str_new( (const char*)carray, %numeric_cast(size*sizeof(wchar_t),long) ); rb_encoding* new_enc = rb_default_internal_encoding(); - rb_enc_associate(ret, rb_to_encoding(rb_str_new_cstr( SWIG_RUBY_WSTRING_ENCODING )) ); - - if( !new_enc ) { - new_enc = rb_to_encoding(rb_str_new_cstr( SWIG_RUBY_INTERNAL_ENCODING )); + rb_enc_associate(rstr, wstr_enc); + if ( !new_enc ) { + new_enc = rb_enc; } - return rb_str_conv_enc(ret, rb_enc_get(ret), new_enc); + return rb_str_conv_enc(rstr, wstr_enc, new_enc); } else { return Qnil; } From 04a7c4f8b87a77758b9350ffc7c193cbcdcf229d Mon Sep 17 00:00:00 2001 From: Takashi Tamura Date: Wed, 22 Feb 2017 12:25:27 +0900 Subject: [PATCH 034/455] [ruby] should initialize static variables inside %init{}, in which it will not be excuted concurrently by multiple threads. --- Lib/ruby/rubywstrings.swg | 6 +++--- Lib/ruby/std_wstring.i | 8 ++++++++ 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/Lib/ruby/rubywstrings.swg b/Lib/ruby/rubywstrings.swg index 54724b268..93d0da21d 100644 --- a/Lib/ruby/rubywstrings.swg +++ b/Lib/ruby/rubywstrings.swg @@ -8,7 +8,7 @@ SWIGINTERN int SWIG_AsWCharPtrAndSize(VALUE obj, wchar_t **cptr, size_t *psize, int *alloc) { - static rb_encoding* wstr_enc = rb_to_encoding(rb_str_new_cstr( SWIG_RUBY_WSTRING_ENCODING )); + rb_encoding* wstr_enc = swig_ruby_wstring_encoding; if (TYPE(obj) == T_STRING) { VALUE rstr = rb_str_conv_enc(obj, rb_enc_get(obj), wstr_enc); @@ -37,8 +37,8 @@ SWIG_AsWCharPtrAndSize(VALUE obj, wchar_t **cptr, size_t *psize, int *alloc) SWIGINTERNINLINE VALUE SWIG_FromWCharPtrAndSize(const wchar_t * carray, size_t size) { - static rb_encoding* wstr_enc = rb_to_encoding(rb_str_new_cstr( SWIG_RUBY_WSTRING_ENCODING )); - static rb_encoding* rb_enc = rb_to_encoding(rb_str_new_cstr( SWIG_RUBY_INTERNAL_ENCODING )); + rb_encoding* wstr_enc = swig_ruby_wstring_encoding; + rb_encoding* rb_enc = swig_ruby_internal_encoding; if (carray && size <= LONG_MAX/sizeof(wchar_t)) { VALUE rstr = rb_str_new( (const char*)carray, %numeric_cast(size*sizeof(wchar_t),long) ); diff --git a/Lib/ruby/std_wstring.i b/Lib/ruby/std_wstring.i index 943b4f770..38149e4ed 100644 --- a/Lib/ruby/std_wstring.i +++ b/Lib/ruby/std_wstring.i @@ -32,11 +32,19 @@ extern "C" { #define SWIG_RUBY_INTERNAL_ENCODING "UTF-8" #endif +static rb_encoding *swig_ruby_wstring_encoding; +static rb_encoding *swig_ruby_internal_encoding; + #ifdef __cplusplus } #endif %} +%init{ + swig_ruby_wstring_encoding = rb_enc_find( SWIG_RUBY_WSTRING_ENCODING ); + swig_ruby_internal_encoding = rb_enc_find( SWIG_RUBY_INTERNAL_ENCODING ); +} + %include %include From 4f31f5d0a387774377f3090765770d8bf33531f8 Mon Sep 17 00:00:00 2001 From: Takashi Tamura Date: Thu, 23 Feb 2017 21:08:04 +0900 Subject: [PATCH 035/455] [ruby] use %fragment to clarify the dependency of code. --- Lib/ruby/rubywstrings.swg | 4 ++-- Lib/ruby/std_wstring.i | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Lib/ruby/rubywstrings.swg b/Lib/ruby/rubywstrings.swg index 93d0da21d..7da6f4bf2 100644 --- a/Lib/ruby/rubywstrings.swg +++ b/Lib/ruby/rubywstrings.swg @@ -4,7 +4,7 @@ * utility methods for wchar_t strings * ------------------------------------------------------------ */ -%fragment("SWIG_AsWCharPtrAndSize","header",fragment="",fragment="SWIG_pwchar_descriptor",fragment="SWIG_AsCharPtrAndSize") { +%fragment("SWIG_AsWCharPtrAndSize","header",fragment="",fragment="SWIG_pwchar_descriptor",fragment="SWIG_AsCharPtrAndSize",fragment="SWIG_ruby_wstring_encoding_init") { SWIGINTERN int SWIG_AsWCharPtrAndSize(VALUE obj, wchar_t **cptr, size_t *psize, int *alloc) { @@ -33,7 +33,7 @@ SWIG_AsWCharPtrAndSize(VALUE obj, wchar_t **cptr, size_t *psize, int *alloc) } } -%fragment("SWIG_FromWCharPtrAndSize","header",fragment="",fragment="SWIG_pwchar_descriptor",fragment="SWIG_FromCharPtrAndSize") { +%fragment("SWIG_FromWCharPtrAndSize","header",fragment="",fragment="SWIG_pwchar_descriptor",fragment="SWIG_FromCharPtrAndSize",fragment="SWIG_ruby_wstring_encoding_init") { SWIGINTERNINLINE VALUE SWIG_FromWCharPtrAndSize(const wchar_t * carray, size_t size) { diff --git a/Lib/ruby/std_wstring.i b/Lib/ruby/std_wstring.i index 38149e4ed..f2487077b 100644 --- a/Lib/ruby/std_wstring.i +++ b/Lib/ruby/std_wstring.i @@ -40,7 +40,7 @@ static rb_encoding *swig_ruby_internal_encoding; #endif %} -%init{ +%fragment("SWIG_ruby_wstring_encoding_init", "init") { swig_ruby_wstring_encoding = rb_enc_find( SWIG_RUBY_WSTRING_ENCODING ); swig_ruby_internal_encoding = rb_enc_find( SWIG_RUBY_INTERNAL_ENCODING ); } From b8d383cb4a5edd9dd4feb4fa528fefca2a2a3c1f Mon Sep 17 00:00:00 2001 From: Takashi Tamura Date: Sat, 25 Feb 2017 15:44:49 +0900 Subject: [PATCH 036/455] [ruby] add simple assertions. --- Examples/test-suite/ruby/swig_assert.rb | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/Examples/test-suite/ruby/swig_assert.rb b/Examples/test-suite/ruby/swig_assert.rb index 69a1a0207..2d5d1f406 100644 --- a/Examples/test-suite/ruby/swig_assert.rb +++ b/Examples/test-suite/ruby/swig_assert.rb @@ -15,6 +15,21 @@ class SwigRubyError < RuntimeError end +# +# simple assertions. strings are not needed as arguments. +# +def simple_assert_equal(a, b) + unless a == b + raise SwigRubyError.new("\n#{a} expected but was \n#{b}") + end +end + +def simple_assert(a) + unless a + raise SwigRubyError.new("assertion falied.") + end +end + # # Asserts whether a and b are equal. # From 50e495c453a3d5beb8f3f1fcf2d3e0ba0e883575 Mon Sep 17 00:00:00 2001 From: Takashi Tamura Date: Wed, 1 Mar 2017 16:08:45 +0900 Subject: [PATCH 037/455] [ruby] use template specialization for swig::asptr,asval functions on std:shared_ptr. --- Lib/ruby/rubystdcommon.swg | 75 +++++++++++++++++++++++++++++++++++++- 1 file changed, 74 insertions(+), 1 deletion(-) diff --git a/Lib/ruby/rubystdcommon.swg b/Lib/ruby/rubystdcommon.swg index f72745b56..9a72ef489 100644 --- a/Lib/ruby/rubystdcommon.swg +++ b/Lib/ruby/rubystdcommon.swg @@ -198,6 +198,79 @@ namespace swig { inline bool check(VALUE obj) { return traits_check::category>::check(obj); } -} + + template + struct traits_asptr > { + static int asptr(VALUE obj, std::shared_ptr **val) { + std::shared_ptr *p=0; + swig_type_info *descriptor = type_info >(); + swig_ruby_owntype newmem = {0, 0}; + int res = descriptor ? SWIG_ConvertPtrAndOwn(obj, (void **)&p, descriptor, 0, &newmem) : SWIG_ERROR; + if (SWIG_IsOK(res) && p) { + if (val && *val) **val = *p; + if (newmem.own & SWIG_CAST_NEW_MEMORY) delete p; + return SWIG_OK; + } else { + return SWIG_ERROR; + } + } + }; + + template + struct traits_asval > { + static int asval(VALUE obj, std::shared_ptr *val) { + if (val) { + std::shared_ptr ret; + std::shared_ptr *p=&ret; + int res = traits_asptr >::asptr(obj, &p); + if (!SWIG_IsOK(res)) return res; + if (val) *val = ret; + return SWIG_OK; + } else { + return traits_asptr >::asptr(obj, (std::shared_ptr **)(0)); + } + } + }; + + template + struct traits_asval*> { + static int asval(VALUE obj, std::shared_ptr **val) { + if (val && *val) { + typedef typename noconst_traits >::noconst_type noconst_type; + noconst_type ret; + noconst_type *p = &ret; + int res = traits_asptr::asptr(obj, &p); + if (SWIG_IsOK(res)) { + **(const_cast(val)) = ret; + } + return res; + } else { + return traits_asptr >::asptr(obj, (std::shared_ptr **)(0)); + } + } + }; + + template + struct traits_as, pointer_category> { + static std::shared_ptr as(VALUE obj, bool throw_error) { + std::shared_ptr ret; + std::shared_ptr *v = &ret; + int res = (obj ? traits_asptr >::asptr(obj, &v) : SWIG_ERROR); + if (SWIG_IsOK(res)) { + return ret; + } else { + // Uninitialized return value, no Type() constructor required. + if (throw_error) throw std::invalid_argument("bad type"); + VALUE lastErr = rb_gv_get("$!"); + if (lastErr == Qnil) { + SWIG_Error(SWIG_TypeError, swig::type_name >()); + } + static std::shared_ptr *v_def = (std::shared_ptr*) malloc(sizeof(std::shared_ptr)); + memset(v_def,0,sizeof(std::shared_ptr)); + return *v_def; + } + } + }; } +} From a84ea749b3ae630212fc2928be6697e34b22faed Mon Sep 17 00:00:00 2001 From: Takashi Tamura Date: Wed, 1 Mar 2017 21:32:03 +0900 Subject: [PATCH 038/455] [ruby] add tests for upcasting std::shared_ptr within std containers. --- Examples/test-suite/cpp11_shared_ptr_upcast.i | 97 +++++++++++++++++++ Examples/test-suite/ruby/Makefile.in | 1 + .../ruby/cpp11_shared_ptr_upcast_runme.rb | 12 +++ 3 files changed, 110 insertions(+) create mode 100644 Examples/test-suite/cpp11_shared_ptr_upcast.i create mode 100644 Examples/test-suite/ruby/cpp11_shared_ptr_upcast_runme.rb diff --git a/Examples/test-suite/cpp11_shared_ptr_upcast.i b/Examples/test-suite/cpp11_shared_ptr_upcast.i new file mode 100644 index 000000000..637563d53 --- /dev/null +++ b/Examples/test-suite/cpp11_shared_ptr_upcast.i @@ -0,0 +1,97 @@ +%module cpp11_shared_ptr_upcast + +%{ +#include +#include +#include +#include +#include +#include +%} + +%include std_vector.i +%include std_map.i +%include std_shared_ptr.i + +%{ + +class Base { +public: + Base() : m(-1) {} + Base(int i) : m(i) {} + int get_m() { return m; } + int m; +}; + +class Derived : public Base { +public: + Derived() : n(-2) {} + Derived(int i) : n(i) {} + int get_n() { return n; } + int n; +}; + + typedef std::shared_ptr BasePtr; + typedef std::shared_ptr DerivedPtr; + + int derived_num(DerivedPtr v) { + return (*v).get_n(); + } + + int derived_num(std::vector v) { + return (*v[0]).get_n(); + } + + int derived_num(std::map v) { + return (*v[0]).get_n(); + } + + int base_num(BasePtr v) { + return (*v).get_m(); + } + + int base_num(std::vector v) { + return (*v[0]).get_m(); + } + + int base_num(std::map v) { + return (*v[0]).get_m(); + } + +%} + + +%shared_ptr(Base); +%shared_ptr(Derived); + +%template(BaseList) std::vector >; +%template(DerivedList) std::vector >; + +%template(BaseMap) std::map >; +%template(DerivedMap) std::map >; + +class Base { +public: + Base(); + int get_m(); + int m; +}; + +class Derived : public Base { +public: + Derived(); + Derived(int i); + int get_n(); + int n; +}; + +typedef std::shared_ptr BasePtr; +typedef std::shared_ptr DerivedPtr; + +int derived_num(DerivedPtr); +int derived_num(std::vector > v); +int derived_num(std::map v); +int base_num(BasePtr); +int base_num(std::vector > v); +int base_num(std::map v); + diff --git a/Examples/test-suite/ruby/Makefile.in b/Examples/test-suite/ruby/Makefile.in index a127860b0..a560aa0f9 100644 --- a/Examples/test-suite/ruby/Makefile.in +++ b/Examples/test-suite/ruby/Makefile.in @@ -31,6 +31,7 @@ CPP_TEST_CASES = \ CPP11_TEST_CASES = \ cpp11_hash_tables \ + cpp11_shared_ptr_upcast C_TEST_CASES += \ li_cstring \ diff --git a/Examples/test-suite/ruby/cpp11_shared_ptr_upcast_runme.rb b/Examples/test-suite/ruby/cpp11_shared_ptr_upcast_runme.rb new file mode 100644 index 000000000..188f9ccbf --- /dev/null +++ b/Examples/test-suite/ruby/cpp11_shared_ptr_upcast_runme.rb @@ -0,0 +1,12 @@ +require 'swig_assert' +require 'cpp11_shared_ptr_upcast' + + +include Cpp11_shared_ptr_upcast + +simple_assert_equal( 7, derived_num(Derived.new(7)) ) +simple_assert_equal( 7, derived_num([Derived.new(7)]) ) +simple_assert_equal( 7, derived_num({0 => Derived.new(7)}) ) +simple_assert_equal(-1, base_num(Derived.new(7)) ) +simple_assert_equal(-1, base_num([Derived.new(7)]) ) +simple_assert_equal(-1, base_num({0 => Derived.new(7)}) ) From a784ace983b49346d973553987e3574cba0eeeaa Mon Sep 17 00:00:00 2001 From: Takashi Tamura Date: Thu, 2 Mar 2017 09:47:46 +0900 Subject: [PATCH 039/455] [ruby] move template specialization to std_shared_ptr.i. --- Lib/ruby/rubystdcommon.swg | 77 ++-------------------------------- Lib/ruby/std_shared_ptr.i | 85 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 88 insertions(+), 74 deletions(-) diff --git a/Lib/ruby/rubystdcommon.swg b/Lib/ruby/rubystdcommon.swg index 9a72ef489..2f7c03c0b 100644 --- a/Lib/ruby/rubystdcommon.swg +++ b/Lib/ruby/rubystdcommon.swg @@ -7,6 +7,8 @@ %fragment("StdTraits","header",fragment="StdTraitsCommon") { +%#define SWIG_RUBYSTDCOMMON + namespace swig { /* Traits that provides the from method @@ -198,79 +200,6 @@ namespace swig { inline bool check(VALUE obj) { return traits_check::category>::check(obj); } - - template - struct traits_asptr > { - static int asptr(VALUE obj, std::shared_ptr **val) { - std::shared_ptr *p=0; - swig_type_info *descriptor = type_info >(); - swig_ruby_owntype newmem = {0, 0}; - int res = descriptor ? SWIG_ConvertPtrAndOwn(obj, (void **)&p, descriptor, 0, &newmem) : SWIG_ERROR; - if (SWIG_IsOK(res) && p) { - if (val && *val) **val = *p; - if (newmem.own & SWIG_CAST_NEW_MEMORY) delete p; - return SWIG_OK; - } else { - return SWIG_ERROR; - } - } - }; - - template - struct traits_asval > { - static int asval(VALUE obj, std::shared_ptr *val) { - if (val) { - std::shared_ptr ret; - std::shared_ptr *p=&ret; - int res = traits_asptr >::asptr(obj, &p); - if (!SWIG_IsOK(res)) return res; - if (val) *val = ret; - return SWIG_OK; - } else { - return traits_asptr >::asptr(obj, (std::shared_ptr **)(0)); - } - } - }; - - template - struct traits_asval*> { - static int asval(VALUE obj, std::shared_ptr **val) { - if (val && *val) { - typedef typename noconst_traits >::noconst_type noconst_type; - noconst_type ret; - noconst_type *p = &ret; - int res = traits_asptr::asptr(obj, &p); - if (SWIG_IsOK(res)) { - **(const_cast(val)) = ret; - } - return res; - } else { - return traits_asptr >::asptr(obj, (std::shared_ptr **)(0)); - } - } - }; - - template - struct traits_as, pointer_category> { - static std::shared_ptr as(VALUE obj, bool throw_error) { - std::shared_ptr ret; - std::shared_ptr *v = &ret; - int res = (obj ? traits_asptr >::asptr(obj, &v) : SWIG_ERROR); - if (SWIG_IsOK(res)) { - return ret; - } else { - // Uninitialized return value, no Type() constructor required. - if (throw_error) throw std::invalid_argument("bad type"); - VALUE lastErr = rb_gv_get("$!"); - if (lastErr == Qnil) { - SWIG_Error(SWIG_TypeError, swig::type_name >()); - } - static std::shared_ptr *v_def = (std::shared_ptr*) malloc(sizeof(std::shared_ptr)); - memset(v_def,0,sizeof(std::shared_ptr)); - return *v_def; - } - } - }; +} } -} diff --git a/Lib/ruby/std_shared_ptr.i b/Lib/ruby/std_shared_ptr.i index df873679c..4192c87cb 100644 --- a/Lib/ruby/std_shared_ptr.i +++ b/Lib/ruby/std_shared_ptr.i @@ -1,2 +1,87 @@ #define SWIG_SHARED_PTR_NAMESPACE std %include + + + /* + * We want to put the folloing code after the fragment "StdTraits" at rubystdcommon.swg. + * This code is needed if and only if "StdTraits" and this std_shared_ptr.i are included at the same time. + * They don't always require each other. So specifying the dependecy by using %fragment does not work. + */ +%wrapper %{ +#ifdef SWIG_RUBYSTDCOMMON +namespace swig { + template + struct traits_asptr > { + static int asptr(VALUE obj, std::shared_ptr **val) { + std::shared_ptr *p=0; + swig_type_info *descriptor = type_info >(); + swig_ruby_owntype newmem = {0, 0}; + int res = descriptor ? SWIG_ConvertPtrAndOwn(obj, (void **)&p, descriptor, 0, &newmem) : SWIG_ERROR; + if (SWIG_IsOK(res) && p) { + if (val && *val) **val = *p; + if (newmem.own & SWIG_CAST_NEW_MEMORY) delete p; + return SWIG_OK; + } else { + return SWIG_ERROR; + } + } + }; + + template + struct traits_asval > { + static int asval(VALUE obj, std::shared_ptr *val) { + if (val) { + std::shared_ptr ret; + std::shared_ptr *p=&ret; + int res = traits_asptr >::asptr(obj, &p); + if (!SWIG_IsOK(res)) return res; + if (val) *val = ret; + return SWIG_OK; + } else { + return traits_asptr >::asptr(obj, (std::shared_ptr **)(0)); + } + } + }; + + template + struct traits_asval*> { + static int asval(VALUE obj, std::shared_ptr **val) { + if (val && *val) { + typedef typename noconst_traits >::noconst_type noconst_type; + noconst_type ret; + noconst_type *p = &ret; + int res = traits_asptr::asptr(obj, &p); + if (SWIG_IsOK(res)) { + **(const_cast(val)) = ret; + } + return res; + } else { + return traits_asptr >::asptr(obj, (std::shared_ptr **)(0)); + } + } + }; + + template + struct traits_as, pointer_category> { + static std::shared_ptr as(VALUE obj, bool throw_error) { + std::shared_ptr ret; + std::shared_ptr *v = &ret; + int res = (obj ? traits_asptr >::asptr(obj, &v) : SWIG_ERROR); + if (SWIG_IsOK(res)) { + return ret; + } else { + // Uninitialized return value, no Type() constructor required. + if (throw_error) throw std::invalid_argument("bad type"); + VALUE lastErr = rb_gv_get("$!"); + if (lastErr == Qnil) { + SWIG_Error(SWIG_TypeError, swig::type_name >()); + } + static std::shared_ptr *v_def = (std::shared_ptr*) malloc(sizeof(std::shared_ptr)); + memset(v_def,0,sizeof(std::shared_ptr)); + return *v_def; + } + } + }; + } +#endif +%} From 806f49bf5809a73ffb5478cbac0a247a0c679dd2 Mon Sep 17 00:00:00 2001 From: Takashi Tamura Date: Thu, 2 Mar 2017 11:55:09 +0900 Subject: [PATCH 040/455] [ruby] edit comments [skip ci] --- Lib/ruby/std_shared_ptr.i | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/Lib/ruby/std_shared_ptr.i b/Lib/ruby/std_shared_ptr.i index 4192c87cb..02a225b6e 100644 --- a/Lib/ruby/std_shared_ptr.i +++ b/Lib/ruby/std_shared_ptr.i @@ -3,9 +3,10 @@ /* - * We want to put the folloing code after the fragment "StdTraits" at rubystdcommon.swg. - * This code is needed if and only if "StdTraits" and this std_shared_ptr.i are included at the same time. - * They don't always require each other. So specifying the dependecy by using %fragment does not work. + * We want to put the following code after the fragment "StdTraits" at rubystdcommon.swg. + * This code is needed if and only if the fragment and this std_shared_ptr.i are included at the same time. + * They don't always require each other. The order of including them is not predetermined either. + * So specifying the dependecy by using %fragment does not work. */ %wrapper %{ #ifdef SWIG_RUBYSTDCOMMON From f96c2ad73d2e4d6ec81941fd5f4b405c7f8828f3 Mon Sep 17 00:00:00 2001 From: Takashi Tamura Date: Fri, 3 Mar 2017 12:50:23 +0900 Subject: [PATCH 041/455] [ruby] For swig::from, use template specialization to convert shared_ptr to shared_ptr. --- Examples/test-suite/cpp11_shared_ptr_const.i | 47 +++++++++++++++++++ Examples/test-suite/ruby/Makefile.in | 1 + .../ruby/cpp11_shared_ptr_const_runme.rb | 7 +++ Lib/ruby/rubystdcommon.swg | 2 + Lib/ruby/std_shared_ptr.i | 15 ++++++ 5 files changed, 72 insertions(+) create mode 100644 Examples/test-suite/cpp11_shared_ptr_const.i create mode 100644 Examples/test-suite/ruby/cpp11_shared_ptr_const_runme.rb diff --git a/Examples/test-suite/cpp11_shared_ptr_const.i b/Examples/test-suite/cpp11_shared_ptr_const.i new file mode 100644 index 000000000..ef6e7ad2c --- /dev/null +++ b/Examples/test-suite/cpp11_shared_ptr_const.i @@ -0,0 +1,47 @@ +%module cpp11_shared_ptr_const + +%{ + +#include +#include + +class Foo +{ +public: + Foo(int i) : m(i) {} + int get_m() { return m;} + int m; +}; + +std::vector > foo_vec() { + std::vector > result; + result.push_back( std::shared_ptr(new Foo(7)) ); + return result; +} + +std::vector > const_foo_vec() { + std::vector > result; + result.push_back( std::shared_ptr(new Foo(7)) ); + return result; +} + +%} + +%include +%include + +%shared_ptr(Foo); + +%template (FooVector) std::vector >; +%template (FooConstVector) std::vector >; + +std::vector > foo_vec() const; +std::vector > const_foo_vec() const; + +class Foo +{ +public: + Foo(int i); + int get_m(); + int m; +}; diff --git a/Examples/test-suite/ruby/Makefile.in b/Examples/test-suite/ruby/Makefile.in index a127860b0..0fde9a2ff 100644 --- a/Examples/test-suite/ruby/Makefile.in +++ b/Examples/test-suite/ruby/Makefile.in @@ -31,6 +31,7 @@ CPP_TEST_CASES = \ CPP11_TEST_CASES = \ cpp11_hash_tables \ + cpp11_shared_ptr_const C_TEST_CASES += \ li_cstring \ diff --git a/Examples/test-suite/ruby/cpp11_shared_ptr_const_runme.rb b/Examples/test-suite/ruby/cpp11_shared_ptr_const_runme.rb new file mode 100644 index 000000000..a881ed056 --- /dev/null +++ b/Examples/test-suite/ruby/cpp11_shared_ptr_const_runme.rb @@ -0,0 +1,7 @@ +require "swig_assert" +require "cpp11_shared_ptr_const" + +include Cpp11_shared_ptr_const + +simple_assert_equal(7, foo_vec()[0].get_m ) +simple_assert_equal(7, const_foo_vec()[0].get_m ) diff --git a/Lib/ruby/rubystdcommon.swg b/Lib/ruby/rubystdcommon.swg index f72745b56..2f7c03c0b 100644 --- a/Lib/ruby/rubystdcommon.swg +++ b/Lib/ruby/rubystdcommon.swg @@ -7,6 +7,8 @@ %fragment("StdTraits","header",fragment="StdTraitsCommon") { +%#define SWIG_RUBYSTDCOMMON + namespace swig { /* Traits that provides the from method diff --git a/Lib/ruby/std_shared_ptr.i b/Lib/ruby/std_shared_ptr.i index df873679c..1d4235ab8 100644 --- a/Lib/ruby/std_shared_ptr.i +++ b/Lib/ruby/std_shared_ptr.i @@ -1,2 +1,17 @@ #define SWIG_SHARED_PTR_NAMESPACE std %include + + +%wrapper %{ +#ifdef SWIG_RUBYSTDCOMMON +namespace swig { + template + struct traits_from > { + static VALUE from(const std::shared_ptr& val) { + std::shared_ptr p = std::const_pointer_cast(val); + return swig::from(p); + } + }; +}; +#endif +%} From b91e03d39ab3d45915d5cb8ddf4b9431ab264aa6 Mon Sep 17 00:00:00 2001 From: Takashi Tamura Date: Fri, 3 Mar 2017 16:58:51 +0900 Subject: [PATCH 042/455] [ruby] add tests for shared_ptr of const Type. --- Examples/test-suite/cpp11_shared_ptr_const.i | 22 ++++++++++++++----- .../ruby/cpp11_shared_ptr_const_runme.rb | 6 +++-- 2 files changed, 20 insertions(+), 8 deletions(-) diff --git a/Examples/test-suite/cpp11_shared_ptr_const.i b/Examples/test-suite/cpp11_shared_ptr_const.i index ef6e7ad2c..1989e3261 100644 --- a/Examples/test-suite/cpp11_shared_ptr_const.i +++ b/Examples/test-suite/cpp11_shared_ptr_const.i @@ -13,15 +13,23 @@ public: int m; }; -std::vector > foo_vec() { +std::shared_ptr foo(Foo v) { + return std::shared_ptr(new Foo(v)); +} + +std::shared_ptr const_foo(Foo v) { + return std::shared_ptr(new Foo(v)); +} + +std::vector > foo_vec(Foo v) { std::vector > result; - result.push_back( std::shared_ptr(new Foo(7)) ); + result.push_back( std::shared_ptr(new Foo(v)) ); return result; } -std::vector > const_foo_vec() { +std::vector > const_foo_vec(Foo v) { std::vector > result; - result.push_back( std::shared_ptr(new Foo(7)) ); + result.push_back( std::shared_ptr(new Foo(v)) ); return result; } @@ -35,8 +43,10 @@ std::vector > const_foo_vec() { %template (FooVector) std::vector >; %template (FooConstVector) std::vector >; -std::vector > foo_vec() const; -std::vector > const_foo_vec() const; +std::shared_ptr foo(Foo v); +std::shared_ptr const_foo(Foo v); +std::vector > foo_vec(Foo v) const; +std::vector > const_foo_vec(Foo v) const; class Foo { diff --git a/Examples/test-suite/ruby/cpp11_shared_ptr_const_runme.rb b/Examples/test-suite/ruby/cpp11_shared_ptr_const_runme.rb index a881ed056..db56252da 100644 --- a/Examples/test-suite/ruby/cpp11_shared_ptr_const_runme.rb +++ b/Examples/test-suite/ruby/cpp11_shared_ptr_const_runme.rb @@ -3,5 +3,7 @@ require "cpp11_shared_ptr_const" include Cpp11_shared_ptr_const -simple_assert_equal(7, foo_vec()[0].get_m ) -simple_assert_equal(7, const_foo_vec()[0].get_m ) +simple_assert_equal(1, foo( Foo.new(1) ).get_m ) +simple_assert_equal(7, const_foo( Foo.new(7) ).get_m ) +simple_assert_equal(7, foo_vec( Foo.new(7) )[0].get_m ) +simple_assert_equal(8, const_foo_vec( Foo.new(8) )[0].get_m ) From cb1f89cb6860afd30f2f2bff8e5f03feedb8644d Mon Sep 17 00:00:00 2001 From: Takashi Tamura Date: Tue, 7 Mar 2017 11:43:01 +0900 Subject: [PATCH 043/455] [ruby] must not do a null check for VALUE. --- Lib/ruby/std_shared_ptr.i | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Lib/ruby/std_shared_ptr.i b/Lib/ruby/std_shared_ptr.i index 02a225b6e..d3f67bab4 100644 --- a/Lib/ruby/std_shared_ptr.i +++ b/Lib/ruby/std_shared_ptr.i @@ -67,9 +67,9 @@ namespace swig { static std::shared_ptr as(VALUE obj, bool throw_error) { std::shared_ptr ret; std::shared_ptr *v = &ret; - int res = (obj ? traits_asptr >::asptr(obj, &v) : SWIG_ERROR); + int res = traits_asptr >::asptr(obj, &v); if (SWIG_IsOK(res)) { - return ret; + return ret; } else { // Uninitialized return value, no Type() constructor required. if (throw_error) throw std::invalid_argument("bad type"); @@ -82,7 +82,7 @@ namespace swig { return *v_def; } } - }; + }; } #endif %} From b32854bc592c82d1401ed749f6ca7fff686180ef Mon Sep 17 00:00:00 2001 From: Takashi Tamura Date: Wed, 29 Mar 2017 19:11:44 +0900 Subject: [PATCH 044/455] use forward declaration to treat the dependency of fragments --- Examples/test-suite/cpp11_shared_ptr_upcast.i | 6 ++--- Lib/ruby/rubystdcommon.swg | 5 ++-- Lib/ruby/rubystdcommon_forward.swg | 14 ++++++++++ Lib/ruby/std_shared_ptr.i | 26 ++++++++++++------- 4 files changed, 35 insertions(+), 16 deletions(-) create mode 100644 Lib/ruby/rubystdcommon_forward.swg diff --git a/Examples/test-suite/cpp11_shared_ptr_upcast.i b/Examples/test-suite/cpp11_shared_ptr_upcast.i index 637563d53..22bc55594 100644 --- a/Examples/test-suite/cpp11_shared_ptr_upcast.i +++ b/Examples/test-suite/cpp11_shared_ptr_upcast.i @@ -9,9 +9,9 @@ #include %} -%include std_vector.i -%include std_map.i -%include std_shared_ptr.i +%include +%include +%include %{ diff --git a/Lib/ruby/rubystdcommon.swg b/Lib/ruby/rubystdcommon.swg index 2f7c03c0b..d1d366cf0 100644 --- a/Lib/ruby/rubystdcommon.swg +++ b/Lib/ruby/rubystdcommon.swg @@ -3,12 +3,11 @@ * The Ruby classes, for C++ * ------------------------------------------------------------ */ %include +%include -%fragment("StdTraits","header",fragment="StdTraitsCommon") +%fragment("StdTraits","header",fragment="StdTraitsCommon",fragment="StdTraitsForwardDeclaration") { -%#define SWIG_RUBYSTDCOMMON - namespace swig { /* Traits that provides the from method diff --git a/Lib/ruby/rubystdcommon_forward.swg b/Lib/ruby/rubystdcommon_forward.swg new file mode 100644 index 000000000..27bcb9960 --- /dev/null +++ b/Lib/ruby/rubystdcommon_forward.swg @@ -0,0 +1,14 @@ +%fragment("StdTraitsForwardDeclaration","header") +{ +namespace swig { + template struct traits_asptr; + template struct traits_asval; + struct pointer_category; + template struct traits_as; + template struct traits_from; + template struct noconst_traits; + template swig_type_info* type_info(); + template const char* type_name(); + template VALUE from(const Type& val); +} +} diff --git a/Lib/ruby/std_shared_ptr.i b/Lib/ruby/std_shared_ptr.i index 0610d590d..5d56b8750 100644 --- a/Lib/ruby/std_shared_ptr.i +++ b/Lib/ruby/std_shared_ptr.i @@ -1,16 +1,15 @@ #define SWIG_SHARED_PTR_NAMESPACE std %include +%include - /* - * We want to put the following code after the fragment "StdTraits" at rubystdcommon.swg. - * This code is needed if and only if the fragment and this std_shared_ptr.i are included at the same time. - * They don't always require each other. The order of including them is not predetermined either. - * So specifying the dependecy by using %fragment does not work. - */ -%wrapper %{ -#ifdef SWIG_RUBYSTDCOMMON +%fragment("StdSharedPtrTraits","header",fragment="StdTraitsForwardDeclaration") +{ namespace swig { + /* + template specialization for functions defined in rubystdcommon.swg. + here we should treat smart pointers in a way different from the way we treat raw pointers. + */ template struct traits_asptr > { static int asptr(VALUE obj, std::shared_ptr **val) { @@ -84,6 +83,11 @@ namespace swig { } }; + /* + we have to remove the const qualifier to work around a BUG + SWIG_TypeQuery("std::shared_ptr") == NULL, + which is caused by %template treating const qualifiers not properly. + */ template struct traits_from > { static VALUE from(const std::shared_ptr& val) { @@ -92,5 +96,7 @@ namespace swig { } }; } -#endif -%} +} + +//force the fragment. +%fragment("StdSharedPtrTraits"); From d56c8ef9ffcf96acbe7e9cc69eefd11e81488ada Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Fri, 31 Mar 2017 07:32:04 +0100 Subject: [PATCH 045/455] Rename new Ruby assert functions used in test-suite --- Examples/test-suite/ruby/swig_assert.rb | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/Examples/test-suite/ruby/swig_assert.rb b/Examples/test-suite/ruby/swig_assert.rb index 2d5d1f406..5b3f9b5ce 100644 --- a/Examples/test-suite/ruby/swig_assert.rb +++ b/Examples/test-suite/ruby/swig_assert.rb @@ -1,12 +1,7 @@ #!/usr/bin/env ruby # -# A simple function to create useful asserts +# Useful assert functions # -# -# -# -# - # # Exception raised when some swig binding test fails @@ -16,15 +11,15 @@ end # -# simple assertions. strings are not needed as arguments. +# Simple assertions. Strings are not needed as arguments. # -def simple_assert_equal(a, b) +def swig_assert_equal_simple(a, b) unless a == b raise SwigRubyError.new("\n#{a} expected but was \n#{b}") end end -def simple_assert(a) +def swig_assert_simple(a) unless a raise SwigRubyError.new("assertion falied.") end From e66d8125aae043fc9a3b145116339ea5066ebf4c Mon Sep 17 00:00:00 2001 From: Joe LeVeque Date: Fri, 31 Mar 2017 01:45:26 -0700 Subject: [PATCH 046/455] [Lua] Fix compiler warnings --- Lib/lua/luarun.swg | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Lib/lua/luarun.swg b/Lib/lua/luarun.swg index 660dbbf86..3510d04d7 100644 --- a/Lib/lua/luarun.swg +++ b/Lib/lua/luarun.swg @@ -1860,7 +1860,7 @@ SWIG_Lua_InstallConstants(lua_State *L, swig_lua_const_info constants[]) { switch(constants[i].type) { case SWIG_LUA_INT: lua_pushstring(L,constants[i].name); - lua_pushinteger(L,(lua_Number)constants[i].lvalue); + lua_pushinteger(L,(lua_Integer)constants[i].lvalue); lua_rawset(L,-3); break; case SWIG_LUA_FLOAT: @@ -1871,7 +1871,7 @@ SWIG_Lua_InstallConstants(lua_State *L, swig_lua_const_info constants[]) { case SWIG_LUA_CHAR: lua_pushstring(L,constants[i].name); { - char c = constants[i].lvalue; + char c = (char)constants[i].lvalue; lua_pushlstring(L,&c,1); } lua_rawset(L,-3); From 07d81cc1e9f912a4710b12d1ddb35f84e05710b0 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Fri, 17 Mar 2017 23:00:56 +0100 Subject: [PATCH 047/455] Use new unified Mono mcs compiler if available under Unix Do not prefer the old .NET 2 gmcs compiler, which was used even if the newer .NET 4 mcs was available. This is recommended by Mono project, see http://www.mono-project.com/docs/about-mono/languages/csharp/, and the .NET 1 original mcs is nowhere to be found nowadays. --- configure.ac | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/configure.ac b/configure.ac index 4d9355cd0..7c0c916f3 100644 --- a/configure.ac +++ b/configure.ac @@ -2267,14 +2267,14 @@ else if test -z "$CSHARPCOMPILERBIN" ; then case $host in *-*-cygwin* | *-*-mingw*) - # prefer Mono gmcs (.NET 2.0) over mcs (.NET 1.1) - note mcs-1.2.3 has major pinvoke bug - AC_CHECK_PROGS(CSHARPCOMPILER, csc mono-csc gmcs mcs cscc) + # prefer unified Mono mcs compiler (not to be confused with the ancient .NET 1 mcs) over older/alternative names. + AC_CHECK_PROGS(CSHARPCOMPILER, csc mcs mono-csc gmcs cscc) if test -n "$CSHARPCOMPILER" && test "$CSHARPCOMPILER" = "csc" ; then AC_MSG_CHECKING(whether csc is the Microsoft CSharp compiler) csc 2>/dev/null | grep "C#" > /dev/null || CSHARPCOMPILER="" if test -z "$CSHARPCOMPILER" ; then AC_MSG_RESULT(no) - AC_CHECK_PROGS(CSHARPCOMPILER, mono-csc gmcs mcs cscc) + AC_CHECK_PROGS(CSHARPCOMPILER, mcs mono-csc gmcs cscc) else AC_MSG_RESULT(yes) fi From aa047c43f73d155f920871e23e7d9e909563e017 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Fri, 17 Mar 2017 18:45:27 +0100 Subject: [PATCH 048/455] Add support for std::complex<> to C# Create Lib/csharp/complex.i with simplest possible typemaps mapping std::complex<> to System.Numerics.Complex. --- CHANGES.current | 3 ++ Examples/test-suite/csharp/Makefile.in | 2 + .../test-suite/csharp/complextest_runme.cs | 28 ++++++++++++ Lib/csharp/complex.i | 44 +++++++++++++++++++ 4 files changed, 77 insertions(+) create mode 100644 Examples/test-suite/csharp/complextest_runme.cs create mode 100644 Lib/csharp/complex.i diff --git a/CHANGES.current b/CHANGES.current index 93b3cc5c4..73740bf0c 100644 --- a/CHANGES.current +++ b/CHANGES.current @@ -15,6 +15,9 @@ Version 3.0.13 (in progress) [Ruby] Fix #939 - Wrapping std::vector fix due to incorrect null checks on VALUE obj. +2017-03-17: vadz + [C#] Add support for std::complex + 2017-03-17: wsfulton [Go] Fix handling of typedef'd function pointers and typedef'd member function pointers such as: diff --git a/Examples/test-suite/csharp/Makefile.in b/Examples/test-suite/csharp/Makefile.in index 0c799c7d9..292854a9f 100644 --- a/Examples/test-suite/csharp/Makefile.in +++ b/Examples/test-suite/csharp/Makefile.in @@ -13,6 +13,7 @@ top_srcdir = ../@top_srcdir@ top_builddir = ../@top_builddir@ CPP_TEST_CASES = \ + complextest \ csharp_attributes \ csharp_swig2_compatibility \ csharp_exceptions \ @@ -40,6 +41,7 @@ CSHARPFLAGSSPECIAL = # Custom tests - tests with additional commandline options intermediary_classname.cpptest: SWIGOPT += -dllimport intermediary_classname +complextest.cpptest: CSHARPFLAGSSPECIAL = -r:System.Numerics.dll csharp_lib_arrays.cpptest: CSHARPFLAGSSPECIAL = -unsafe csharp_swig2_compatibility.cpptest: SWIGOPT += -DSWIG2_CSHARP diff --git a/Examples/test-suite/csharp/complextest_runme.cs b/Examples/test-suite/csharp/complextest_runme.cs new file mode 100644 index 000000000..781909f25 --- /dev/null +++ b/Examples/test-suite/csharp/complextest_runme.cs @@ -0,0 +1,28 @@ +// This is the complex runtime testcase. It checks that the C++ std::complex type works. +// It requires .NET 4.0 as the previous versions didn't have System.Numerics.Complex type. + +using System; +using System.Numerics; + +using complextestNamespace; + +public class complextest_runme { + + public static void Main() { + var a = new Complex(-1, 2); + if ( complextest.Conj(a) != Complex.Conjugate(a) ) + throw new Exception("std::complex test failed"); + + if ( complextest.Conjf(a) != Complex.Conjugate(a) ) + throw new Exception("std::complex test failed"); + + var vec = new VectorStdCplx(); + vec.Add(new Complex(1, 2)); + vec.Add(new Complex(2, 3)); + vec.Add(new Complex(4, 3)); + vec.Add(new Complex(1, 0)); + + if ( complextest.Copy_h(vec).Count != 2 ) + throw new Exception("vector test failed"); + } +} diff --git a/Lib/csharp/complex.i b/Lib/csharp/complex.i new file mode 100644 index 000000000..045b65d43 --- /dev/null +++ b/Lib/csharp/complex.i @@ -0,0 +1,44 @@ +#ifndef __cplusplus +#error C# module only supports complex in C++ mode. +#endif + +%{ +#include +%} + +namespace std { + +// An extremely simplified subset of std::complex<> which contains just the +// methods we need. +template +class complex +{ +public: + complex(T re, T im); + + T real() const; + T imag() const; +}; + +} // namespace std + +%define swig_complex_typemaps(T) +%typemap(cstype) std::complex, const std::complex& "System.Numerics.Complex" + +// The casts in "pre" are needed in order to allow creating std::complex +// from System.Numerics.Complex, which always uses doubles. It relies on the +// fact that the name of the C++ and C# float/double types are the same. +%typemap(csin, + pre=" var cpp$csinput = new Complex_" #T "((" #T ")$csinput.Real, (" #T ")$csinput.Imaginary);" + ) std::complex, const std::complex& "Complex_" #T ".getCPtr(cpp$csinput)" + +%typemap(csout, excode=SWIGEXCODE) std::complex, const std::complex& { + Complex_##T cppret = new Complex_##T($imcall, $owner);$excode + return new System.Numerics.Complex(cppret.real(), cppret.imag()); + } + +%template(Complex_##T) std::complex; +%enddef + +swig_complex_typemaps(double) +swig_complex_typemaps(float) From ec565f74cf64f1c916d47d7e8fdcb7197b1b26e7 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Sat, 1 Apr 2017 23:48:33 +0200 Subject: [PATCH 049/455] Extend C# complex support to member variables of this type Define csvar{in,out} typemaps needed to support properties of complex type and apply the existing cstype and csin ones to them as well. Add unit test verifying that this works as expected in C# and, also, in Python, even though no changes were needed there. --- Examples/test-suite/complextest.i | 5 +++++ .../test-suite/csharp/complextest_runme.cs | 6 ++++++ .../test-suite/python/complextest_runme.py | 6 ++++++ Lib/csharp/complex.i | 18 ++++++++++++++++-- 4 files changed, 33 insertions(+), 2 deletions(-) diff --git a/Examples/test-suite/complextest.i b/Examples/test-suite/complextest.i index 64c751a82..6e82e8915 100644 --- a/Examples/test-suite/complextest.i +++ b/Examples/test-suite/complextest.i @@ -34,6 +34,11 @@ return b; } #endif + + struct ComplexPair + { + std::complex z1, z2; + }; } diff --git a/Examples/test-suite/csharp/complextest_runme.cs b/Examples/test-suite/csharp/complextest_runme.cs index 781909f25..2b7e4cc84 100644 --- a/Examples/test-suite/csharp/complextest_runme.cs +++ b/Examples/test-suite/csharp/complextest_runme.cs @@ -24,5 +24,11 @@ public class complextest_runme { if ( complextest.Copy_h(vec).Count != 2 ) throw new Exception("vector test failed"); + + var p = new ComplexPair(); + p.z1 = new Complex(0, 1); + p.z2 = new Complex(0, -1); + if ( Complex.Conjugate(p.z2) != p.z1 ) + throw new Exception("vector test failed"); } } diff --git a/Examples/test-suite/python/complextest_runme.py b/Examples/test-suite/python/complextest_runme.py index 7dd7f5a3b..a55e6098b 100644 --- a/Examples/test-suite/python/complextest_runme.py +++ b/Examples/test-suite/python/complextest_runme.py @@ -15,3 +15,9 @@ try: complextest.Copy_h(v) except: pass + +p = complextest.ComplexPair() +p.z1 = complex(0, 1) +p.z2 = complex(0, -1) +if complextest.Conj(p.z2) != p.z1: + raise RuntimeError, "bad complex mapping" diff --git a/Lib/csharp/complex.i b/Lib/csharp/complex.i index 045b65d43..21c84adbb 100644 --- a/Lib/csharp/complex.i +++ b/Lib/csharp/complex.i @@ -23,20 +23,34 @@ public: } // namespace std %define swig_complex_typemaps(T) -%typemap(cstype) std::complex, const std::complex& "System.Numerics.Complex" +%typemap(cstype) std::complex, std::complex*, const std::complex& "System.Numerics.Complex" // The casts in "pre" are needed in order to allow creating std::complex // from System.Numerics.Complex, which always uses doubles. It relies on the // fact that the name of the C++ and C# float/double types are the same. %typemap(csin, pre=" var cpp$csinput = new Complex_" #T "((" #T ")$csinput.Real, (" #T ")$csinput.Imaginary);" - ) std::complex, const std::complex& "Complex_" #T ".getCPtr(cpp$csinput)" + ) std::complex, std::complex*, const std::complex& "Complex_" #T ".getCPtr(cpp$csinput)" %typemap(csout, excode=SWIGEXCODE) std::complex, const std::complex& { Complex_##T cppret = new Complex_##T($imcall, $owner);$excode return new System.Numerics.Complex(cppret.real(), cppret.imag()); } +%typemap(csvarin, excode=SWIGEXCODE2) std::complex* %{ + set { + var cppvalue = new Complex_##T((T)value.Real, (T)value.Imaginary); + $imcall;$excode + } + %} + +%typemap(csvarout, excode=SWIGEXCODE2) std::complex* %{ + get { + var cppret = new Complex_##T($imcall, $owner);$excode + return new System.Numerics.Complex(cppret.real(), cppret.imag()); + } + %} + %template(Complex_##T) std::complex; %enddef From bd233408e8ec192b342dc02e014906affab9e08f Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Fri, 7 Apr 2017 07:34:58 +0100 Subject: [PATCH 050/455] Add shared_ptr non-overloaded upcast tests --- Examples/test-suite/cpp11_shared_ptr_upcast.i | 75 +++++++++++++------ .../ruby/cpp11_shared_ptr_upcast_runme.rb | 11 +++ 2 files changed, 65 insertions(+), 21 deletions(-) diff --git a/Examples/test-suite/cpp11_shared_ptr_upcast.i b/Examples/test-suite/cpp11_shared_ptr_upcast.i index 22bc55594..9f65eb7e1 100644 --- a/Examples/test-suite/cpp11_shared_ptr_upcast.i +++ b/Examples/test-suite/cpp11_shared_ptr_upcast.i @@ -31,33 +31,58 @@ public: int n; }; - typedef std::shared_ptr BasePtr; - typedef std::shared_ptr DerivedPtr; +typedef std::shared_ptr BasePtr; +typedef std::shared_ptr DerivedPtr; - int derived_num(DerivedPtr v) { - return (*v).get_n(); - } +// non-overloaded +int derived_num1(DerivedPtr v) { + return (*v).get_n(); +} - int derived_num(std::vector v) { - return (*v[0]).get_n(); - } +int derived_num2(std::vector v) { + return (*v[0]).get_n(); +} - int derived_num(std::map v) { - return (*v[0]).get_n(); - } +int derived_num3(std::map v) { + return (*v[0]).get_n(); +} - int base_num(BasePtr v) { - return (*v).get_m(); - } +int base_num1(BasePtr v) { + return (*v).get_m(); +} - int base_num(std::vector v) { - return (*v[0]).get_m(); - } +int base_num2(std::vector v) { + return (*v[0]).get_m(); +} - int base_num(std::map v) { - return (*v[0]).get_m(); - } +int base_num3(std::map v) { + return (*v[0]).get_m(); +} +// overloaded +int derived_num(DerivedPtr v) { + return derived_num1(v); +} + +int derived_num(std::vector v) { + return derived_num2(v); +} + +int derived_num(std::map v) { + return derived_num3(v); +} + +int base_num(BasePtr v) { + return base_num1(v); +} + +int base_num(std::vector v) { + return base_num2(v); +} + +int base_num(std::map v) { + return base_num3(v); +} %} @@ -88,10 +113,18 @@ public: typedef std::shared_ptr BasePtr; typedef std::shared_ptr DerivedPtr; +// non-overloaded +int derived_num1(DerivedPtr); +int derived_num2(std::vector > v); +int derived_num3(std::map v); +int base_num1(BasePtr); +int base_num2(std::vector > v); +int base_num3(std::map v); + +// overloaded int derived_num(DerivedPtr); int derived_num(std::vector > v); int derived_num(std::map v); int base_num(BasePtr); int base_num(std::vector > v); int base_num(std::map v); - diff --git a/Examples/test-suite/ruby/cpp11_shared_ptr_upcast_runme.rb b/Examples/test-suite/ruby/cpp11_shared_ptr_upcast_runme.rb index 188f9ccbf..ef83ab367 100644 --- a/Examples/test-suite/ruby/cpp11_shared_ptr_upcast_runme.rb +++ b/Examples/test-suite/ruby/cpp11_shared_ptr_upcast_runme.rb @@ -4,9 +4,20 @@ require 'cpp11_shared_ptr_upcast' include Cpp11_shared_ptr_upcast +# non-overloaded +simple_assert_equal( 7, derived_num1(Derived.new(7)) ) +simple_assert_equal( 7, derived_num2([Derived.new(7)]) ) +simple_assert_equal( 7, derived_num3({0 => Derived.new(7)}) ) + +simple_assert_equal(-1, base_num1(Derived.new(7)) ) +simple_assert_equal(-1, base_num2([Derived.new(7)]) ) +simple_assert_equal(-1, base_num3({0 => Derived.new(7)}) ) + +# overloaded simple_assert_equal( 7, derived_num(Derived.new(7)) ) simple_assert_equal( 7, derived_num([Derived.new(7)]) ) simple_assert_equal( 7, derived_num({0 => Derived.new(7)}) ) + simple_assert_equal(-1, base_num(Derived.new(7)) ) simple_assert_equal(-1, base_num([Derived.new(7)]) ) simple_assert_equal(-1, base_num({0 => Derived.new(7)}) ) From 83a389d3fbccbd588f3a649c4a736feeae617341 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Wed, 12 Apr 2017 19:08:23 +0100 Subject: [PATCH 051/455] Add support for pointers to shared_ptr and null shared_ptr in Ruby containers Upcasting of pointers to shared_ptr would need some more fundamental changes, but not done yet ... pointers to shared_ptr are not common. --- Examples/test-suite/cpp11_shared_ptr_upcast.i | 70 +++++++++++++-- .../ruby/cpp11_shared_ptr_upcast_runme.rb | 37 ++++++++ Lib/ruby/std_shared_ptr.i | 85 +++++++++++++------ 3 files changed, 160 insertions(+), 32 deletions(-) diff --git a/Examples/test-suite/cpp11_shared_ptr_upcast.i b/Examples/test-suite/cpp11_shared_ptr_upcast.i index 9f65eb7e1..3427829d9 100644 --- a/Examples/test-suite/cpp11_shared_ptr_upcast.i +++ b/Examples/test-suite/cpp11_shared_ptr_upcast.i @@ -36,27 +36,27 @@ typedef std::shared_ptr DerivedPtr; // non-overloaded int derived_num1(DerivedPtr v) { - return (*v).get_n(); + return v == nullptr ? 999 : (*v).get_n(); } int derived_num2(std::vector v) { - return (*v[0]).get_n(); + return v[0] == nullptr ? 999 : (*v[0]).get_n(); } int derived_num3(std::map v) { - return (*v[0]).get_n(); + return v[0] == nullptr ? 999 : (*v[0]).get_n(); } int base_num1(BasePtr v) { - return (*v).get_m(); + return v == nullptr ? 999 : (*v).get_m(); } int base_num2(std::vector v) { - return (*v[0]).get_m(); + return v[0] == nullptr ? 999 : (*v[0]).get_m(); } int base_num3(std::map v) { - return (*v[0]).get_m(); + return v[0] == nullptr ? 999 : (*v[0]).get_m(); } // overloaded @@ -128,3 +128,61 @@ int derived_num(std::map v); int base_num(BasePtr); int base_num(std::vector > v); int base_num(std::map v); + +// ptr to shared_ptr +%shared_ptr(Base2); +%shared_ptr(Derived2) + +%inline %{ +class Base2 { +public: + Base2() : m(-1) {} + Base2(int i) : m(i) {} + int get_m() { return m; } + int m; +}; + + +class Derived2 : public Base2 { +public: + Derived2() : n(0) {} + Derived2(int i) : n(i) {} + int get_n_2() { return n; } + int n; +}; +%} + +%template(Base2List) std::vector * >; +%template(Base2Map) std::map * >; + +%template(Derived2List) std::vector * >; +%template(Derived2Map) std::map * >; + +%inline %{ +typedef std::shared_ptr * Derived2Ptr; +typedef std::shared_ptr * Base2Ptr; + +int base2_num1(Base2Ptr v) { + return v == nullptr ? 999 : *v == nullptr ? 888 : (*v)->get_m(); +} + +int base2_num2(std::vector v) { + return v[0] == nullptr ? 999 : *v[0] == nullptr ? 888 : (*v[0])->get_m(); +} + +int base2_num3(std::map v) { + return v[0] == nullptr ? 999 : *v[0] == nullptr ? 888 : (*v[0])->get_m(); +} + +int derived2_num1(Derived2Ptr v) { + return v == nullptr ? 999 : *v == nullptr ? 888 : (*v)->get_n_2(); +} + +int derived2_num2(std::vector v) { + return v[0] == nullptr ? 999 : *v[0] == nullptr ? 888 : (*v[0])->get_n_2(); +} + +int derived2_num3(std::map v) { + return v[0] == nullptr ? 999 : *v[0] == nullptr ? 888 : (*v[0])->get_n_2(); +} +%} diff --git a/Examples/test-suite/ruby/cpp11_shared_ptr_upcast_runme.rb b/Examples/test-suite/ruby/cpp11_shared_ptr_upcast_runme.rb index ef83ab367..864be1382 100644 --- a/Examples/test-suite/ruby/cpp11_shared_ptr_upcast_runme.rb +++ b/Examples/test-suite/ruby/cpp11_shared_ptr_upcast_runme.rb @@ -13,6 +13,14 @@ simple_assert_equal(-1, base_num1(Derived.new(7)) ) simple_assert_equal(-1, base_num2([Derived.new(7)]) ) simple_assert_equal(-1, base_num3({0 => Derived.new(7)}) ) +simple_assert_equal( 999, derived_num1(nil) ) +simple_assert_equal( 999, derived_num2([nil]) ) +simple_assert_equal( 999, derived_num3({0 => nil}) ) + +simple_assert_equal( 999, base_num1(nil) ) +simple_assert_equal( 999, base_num2([nil]) ) +simple_assert_equal( 999, base_num3({0 => nil}) ) + # overloaded simple_assert_equal( 7, derived_num(Derived.new(7)) ) simple_assert_equal( 7, derived_num([Derived.new(7)]) ) @@ -21,3 +29,32 @@ simple_assert_equal( 7, derived_num({0 => Derived.new(7)}) ) simple_assert_equal(-1, base_num(Derived.new(7)) ) simple_assert_equal(-1, base_num([Derived.new(7)]) ) simple_assert_equal(-1, base_num({0 => Derived.new(7)}) ) + +# ptr to shared_ptr +simple_assert_equal( 7, derived2_num1(Derived2.new(7)) ) +simple_assert_equal( 7, derived2_num2([Derived2.new(7)]) ) +simple_assert_equal( 7, derived2_num3({0 => Derived2.new(7)}) ) + +simple_assert_equal( -1, base2_num1(Derived2.new(7)) ) + +begin + # Upcast for pointers to shared_ptr in this generic framework has not been implemented + simple_assert_equal( -1, base2_num2([Derived2.new(7)]) ) + raise RuntimeError, "Failed to catch TypeError" +rescue TypeError +end +begin + # Upcast for pointers to shared_ptr in this generic framework has not been implemented + simple_assert_equal( -1, base2_num3({0 => Derived2.new(7)}) ) + raise RuntimeError, "Failed to catch TypeError" +rescue TypeError +end + +simple_assert_equal( 888, derived2_num1(nil) ) +simple_assert_equal( 999, derived2_num2([nil]) ) # although 888 would be more consistent +simple_assert_equal( 999, derived2_num3({0 => nil}) ) # although 888 would be more consistent + +simple_assert_equal( 888, base2_num1(nil) ) +simple_assert_equal( 999, base2_num2([nil]) ) # although 888 would be more consistent +simple_assert_equal( 999, base2_num3({0 => nil}) ) # although 888 would be more consistent + diff --git a/Lib/ruby/std_shared_ptr.i b/Lib/ruby/std_shared_ptr.i index 5d56b8750..4e0798d56 100644 --- a/Lib/ruby/std_shared_ptr.i +++ b/Lib/ruby/std_shared_ptr.i @@ -7,23 +7,32 @@ { namespace swig { /* - template specialization for functions defined in rubystdcommon.swg. - here we should treat smart pointers in a way different from the way we treat raw pointers. + Template specialization for functions defined in rubystdcommon.swg. Special handling for shared_ptr + is required as, shared_ptr * is used rather than the usual T *, see shared_ptr.i. */ template struct traits_asptr > { static int asptr(VALUE obj, std::shared_ptr **val) { - std::shared_ptr *p=0; + std::shared_ptr *p = 0; swig_type_info *descriptor = type_info >(); swig_ruby_owntype newmem = {0, 0}; int res = descriptor ? SWIG_ConvertPtrAndOwn(obj, (void **)&p, descriptor, 0, &newmem) : SWIG_ERROR; - if (SWIG_IsOK(res) && p) { - if (val && *val) **val = *p; - if (newmem.own & SWIG_CAST_NEW_MEMORY) delete p; - return SWIG_OK; - } else { - return SWIG_ERROR; + if (SWIG_IsOK(res)) { + if (val) { + if (*val) { + **val = p ? *p : std::shared_ptr(); + } else { + *val = p; + if (newmem.own & SWIG_CAST_NEW_MEMORY) { + // Upcast for pointers to shared_ptr in this generic framework has not been implemented + res = SWIG_ERROR; + } + } + } + if (newmem.own & SWIG_CAST_NEW_MEMORY) + delete p; } + return res; } }; @@ -31,12 +40,13 @@ namespace swig { struct traits_asval > { static int asval(VALUE obj, std::shared_ptr *val) { if (val) { - std::shared_ptr ret; - std::shared_ptr *p=&ret; + std::shared_ptr ret; + std::shared_ptr *p = &ret; int res = traits_asptr >::asptr(obj, &p); - if (!SWIG_IsOK(res)) return res; - if (val) *val = ret; - return SWIG_OK; + if (!SWIG_IsOK(res)) + return res; + *val = ret; + return SWIG_OK; } else { return traits_asptr >::asptr(obj, (std::shared_ptr **)(0)); } @@ -44,17 +54,24 @@ namespace swig { }; template - struct traits_asval*> { + struct traits_asval *> { static int asval(VALUE obj, std::shared_ptr **val) { - if (val && *val) { - typedef typename noconst_traits >::noconst_type noconst_type; - noconst_type ret; - noconst_type *p = &ret; - int res = traits_asptr::asptr(obj, &p); - if (SWIG_IsOK(res)) { - **(const_cast(val)) = ret; + if (val) { + typedef typename noconst_traits >::noconst_type noconst_type; + if (*val) { + noconst_type ret; + noconst_type *p = &ret; + int res = traits_asptr::asptr(obj, &p); + if (SWIG_IsOK(res)) + **(const_cast(val)) = ret; + return res; + } else { + noconst_type *p = 0; + int res = traits_asptr::asptr(obj, &p); + if (SWIG_IsOK(res)) + *val = p; + return res; } - return res; } else { return traits_asptr >::asptr(obj, (std::shared_ptr **)(0)); } @@ -73,16 +90,32 @@ namespace swig { // Uninitialized return value, no Type() constructor required. if (throw_error) throw std::invalid_argument("bad type"); VALUE lastErr = rb_gv_get("$!"); - if (lastErr == Qnil) { + if (lastErr == Qnil) SWIG_Error(SWIG_TypeError, swig::type_name >()); - } - static std::shared_ptr *v_def = (std::shared_ptr*) malloc(sizeof(std::shared_ptr)); + static std::shared_ptr *v_def = (std::shared_ptr *) malloc(sizeof(std::shared_ptr)); memset(v_def,0,sizeof(std::shared_ptr)); return *v_def; } } }; + template + struct traits_as *, pointer_category> { + static std::shared_ptr * as(VALUE obj, bool throw_error) { + std::shared_ptr *p = 0; + int res = traits_asptr >::asptr(obj, &p); + if (SWIG_IsOK(res)) { + return p; + } else { + if (throw_error) throw std::invalid_argument("bad type"); + VALUE lastErr = rb_gv_get("$!"); + if (lastErr == Qnil) + SWIG_Error(SWIG_TypeError, swig::type_name *>()); + return 0; + } + } + }; + /* we have to remove the const qualifier to work around a BUG SWIG_TypeQuery("std::shared_ptr") == NULL, From 1a6f8d1e4b350a8245bf3c355c76825bf7bfaaf8 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Thu, 13 Apr 2017 07:04:07 +0100 Subject: [PATCH 052/455] Ruby shared_ptr on error code improvement in traits_as::as --- Lib/ruby/std_shared_ptr.i | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/Lib/ruby/std_shared_ptr.i b/Lib/ruby/std_shared_ptr.i index 4e0798d56..983ffde49 100644 --- a/Lib/ruby/std_shared_ptr.i +++ b/Lib/ruby/std_shared_ptr.i @@ -87,14 +87,11 @@ namespace swig { if (SWIG_IsOK(res)) { return ret; } else { - // Uninitialized return value, no Type() constructor required. if (throw_error) throw std::invalid_argument("bad type"); VALUE lastErr = rb_gv_get("$!"); if (lastErr == Qnil) SWIG_Error(SWIG_TypeError, swig::type_name >()); - static std::shared_ptr *v_def = (std::shared_ptr *) malloc(sizeof(std::shared_ptr)); - memset(v_def,0,sizeof(std::shared_ptr)); - return *v_def; + return std::shared_ptr(); } } }; From 485efd511f52aa0a8446ad58f60455ceaf788966 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Fri, 14 Apr 2017 19:23:31 +0200 Subject: [PATCH 053/455] Add std_complex.i for C# too For consistency with the other modules (Python, Ruby and JS), allow including directly when using C# too instead of including which only works in C++ mode (i.e. when using std::complex) anyhow with C# for now. --- Lib/csharp/complex.i | 59 ++-------------------------------------- Lib/csharp/std_complex.i | 54 ++++++++++++++++++++++++++++++++++++ 2 files changed, 57 insertions(+), 56 deletions(-) create mode 100644 Lib/csharp/std_complex.i diff --git a/Lib/csharp/complex.i b/Lib/csharp/complex.i index 21c84adbb..4a6f91cdf 100644 --- a/Lib/csharp/complex.i +++ b/Lib/csharp/complex.i @@ -1,58 +1,5 @@ -#ifndef __cplusplus +#ifdef __cplusplus +%include +#else #error C# module only supports complex in C++ mode. #endif - -%{ -#include -%} - -namespace std { - -// An extremely simplified subset of std::complex<> which contains just the -// methods we need. -template -class complex -{ -public: - complex(T re, T im); - - T real() const; - T imag() const; -}; - -} // namespace std - -%define swig_complex_typemaps(T) -%typemap(cstype) std::complex, std::complex*, const std::complex& "System.Numerics.Complex" - -// The casts in "pre" are needed in order to allow creating std::complex -// from System.Numerics.Complex, which always uses doubles. It relies on the -// fact that the name of the C++ and C# float/double types are the same. -%typemap(csin, - pre=" var cpp$csinput = new Complex_" #T "((" #T ")$csinput.Real, (" #T ")$csinput.Imaginary);" - ) std::complex, std::complex*, const std::complex& "Complex_" #T ".getCPtr(cpp$csinput)" - -%typemap(csout, excode=SWIGEXCODE) std::complex, const std::complex& { - Complex_##T cppret = new Complex_##T($imcall, $owner);$excode - return new System.Numerics.Complex(cppret.real(), cppret.imag()); - } - -%typemap(csvarin, excode=SWIGEXCODE2) std::complex* %{ - set { - var cppvalue = new Complex_##T((T)value.Real, (T)value.Imaginary); - $imcall;$excode - } - %} - -%typemap(csvarout, excode=SWIGEXCODE2) std::complex* %{ - get { - var cppret = new Complex_##T($imcall, $owner);$excode - return new System.Numerics.Complex(cppret.real(), cppret.imag()); - } - %} - -%template(Complex_##T) std::complex; -%enddef - -swig_complex_typemaps(double) -swig_complex_typemaps(float) diff --git a/Lib/csharp/std_complex.i b/Lib/csharp/std_complex.i new file mode 100644 index 000000000..d7cf7e6d3 --- /dev/null +++ b/Lib/csharp/std_complex.i @@ -0,0 +1,54 @@ +%{ +#include +%} + +namespace std { + +// An extremely simplified subset of std::complex<> which contains just the +// methods we need. +template +class complex +{ +public: + complex(T re, T im); + + T real() const; + T imag() const; +}; + +} // namespace std + +%define swig_complex_typemaps(T) +%typemap(cstype) std::complex, std::complex*, const std::complex& "System.Numerics.Complex" + +// The casts in "pre" are needed in order to allow creating std::complex +// from System.Numerics.Complex, which always uses doubles. It relies on the +// fact that the name of the C++ and C# float/double types are the same. +%typemap(csin, + pre=" var cpp$csinput = new Complex_" #T "((" #T ")$csinput.Real, (" #T ")$csinput.Imaginary);" + ) std::complex, std::complex*, const std::complex& "Complex_" #T ".getCPtr(cpp$csinput)" + +%typemap(csout, excode=SWIGEXCODE) std::complex, const std::complex& { + Complex_##T cppret = new Complex_##T($imcall, $owner);$excode + return new System.Numerics.Complex(cppret.real(), cppret.imag()); + } + +%typemap(csvarin, excode=SWIGEXCODE2) std::complex* %{ + set { + var cppvalue = new Complex_##T((T)value.Real, (T)value.Imaginary); + $imcall;$excode + } + %} + +%typemap(csvarout, excode=SWIGEXCODE2) std::complex* %{ + get { + var cppret = new Complex_##T($imcall, $owner);$excode + return new System.Numerics.Complex(cppret.real(), cppret.imag()); + } + %} + +%template(Complex_##T) std::complex; +%enddef + +swig_complex_typemaps(double) +swig_complex_typemaps(float) From 95aa3d9389fd691b182921c0ebce88b8eb821b13 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Sat, 15 Apr 2017 20:18:24 +0200 Subject: [PATCH 054/455] Also apply csvar{in,out} typemaps to std::complex references This is needed to handle the artificial complex-valued properties created using %naturalvar correctly. --- Lib/csharp/std_complex.i | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Lib/csharp/std_complex.i b/Lib/csharp/std_complex.i index d7cf7e6d3..4c627d72f 100644 --- a/Lib/csharp/std_complex.i +++ b/Lib/csharp/std_complex.i @@ -33,14 +33,14 @@ public: return new System.Numerics.Complex(cppret.real(), cppret.imag()); } -%typemap(csvarin, excode=SWIGEXCODE2) std::complex* %{ +%typemap(csvarin, excode=SWIGEXCODE2) std::complex*, const std::complex& %{ set { var cppvalue = new Complex_##T((T)value.Real, (T)value.Imaginary); $imcall;$excode } %} -%typemap(csvarout, excode=SWIGEXCODE2) std::complex* %{ +%typemap(csvarout, excode=SWIGEXCODE2) std::complex*, const std::complex& %{ get { var cppret = new Complex_##T($imcall, $owner);$excode return new System.Numerics.Complex(cppret.real(), cppret.imag()); From 03f229b3141703bbcec27e404c0c14f9391884e8 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Sat, 15 Apr 2017 20:28:30 +0200 Subject: [PATCH 055/455] Allow avoiding generation of unwanted std::complex typemaps In many cases, only one of std::complex and std::complex is used, so while we continue to define typemaps for both by default, for compatibility with the other modules, add a possibility to avoid generating the code for the unwanted specialization by predefining the corresponding SWIG_NO_STD_COMPLEX_$TYPE before including this file. --- Lib/csharp/std_complex.i | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Lib/csharp/std_complex.i b/Lib/csharp/std_complex.i index 4c627d72f..b5bdec60d 100644 --- a/Lib/csharp/std_complex.i +++ b/Lib/csharp/std_complex.i @@ -50,5 +50,13 @@ public: %template(Complex_##T) std::complex; %enddef +// By default, typemaps for both std::complex and std::complex +// are defined, but one of them can be disabled by predefining the +// corresponding symbol before including this file. +#ifndef SWIG_NO_STD_COMPLEX_DOUBLE swig_complex_typemaps(double) +#endif + +#ifndef SWIG_NO_STD_COMPLEX_FLOAT swig_complex_typemaps(float) +#endif From 7a343a196bc74dad5acce107d2c709974b7535d9 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Thu, 20 Apr 2017 07:33:15 +0100 Subject: [PATCH 056/455] Correct ordering of declarations in testcase --- Examples/test-suite/cpp11_shared_ptr_const.i | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Examples/test-suite/cpp11_shared_ptr_const.i b/Examples/test-suite/cpp11_shared_ptr_const.i index 1989e3261..0d1acdac0 100644 --- a/Examples/test-suite/cpp11_shared_ptr_const.i +++ b/Examples/test-suite/cpp11_shared_ptr_const.i @@ -43,11 +43,6 @@ std::vector > const_foo_vec(Foo v) { %template (FooVector) std::vector >; %template (FooConstVector) std::vector >; -std::shared_ptr foo(Foo v); -std::shared_ptr const_foo(Foo v); -std::vector > foo_vec(Foo v) const; -std::vector > const_foo_vec(Foo v) const; - class Foo { public: @@ -55,3 +50,8 @@ public: int get_m(); int m; }; +std::shared_ptr foo(Foo v); +std::shared_ptr const_foo(Foo v); +std::vector > foo_vec(Foo v) const; +std::vector > const_foo_vec(Foo v) const; + From 660147043da845998e9066d7116aaf3f525b56e5 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Thu, 20 Apr 2017 07:49:03 +0100 Subject: [PATCH 057/455] Correct comment about const removal for shared_ptr --- Lib/ruby/std_shared_ptr.i | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/Lib/ruby/std_shared_ptr.i b/Lib/ruby/std_shared_ptr.i index 983ffde49..f6c0a15ac 100644 --- a/Lib/ruby/std_shared_ptr.i +++ b/Lib/ruby/std_shared_ptr.i @@ -114,9 +114,8 @@ namespace swig { }; /* - we have to remove the const qualifier to work around a BUG - SWIG_TypeQuery("std::shared_ptr") == NULL, - which is caused by %template treating const qualifiers not properly. + The descriptors in the shared_ptr typemaps remove the const qualifier for the SWIG type system. + Remove const likewise here, otherwise SWIG_TypeQuery("std::shared_ptr") will return NULL. */ template struct traits_from > { @@ -128,5 +127,4 @@ namespace swig { } } -//force the fragment. %fragment("StdSharedPtrTraits"); From 6398614c9278db40d41dca630a672bcb39835276 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Thu, 20 Apr 2017 07:57:48 +0100 Subject: [PATCH 058/455] Update ruby tests for change in swig_assert_equal_simple name --- .../ruby/cpp11_shared_ptr_const_runme.rb | 8 +-- .../ruby/cpp11_shared_ptr_upcast_runme.rb | 60 +++++++++---------- 2 files changed, 34 insertions(+), 34 deletions(-) diff --git a/Examples/test-suite/ruby/cpp11_shared_ptr_const_runme.rb b/Examples/test-suite/ruby/cpp11_shared_ptr_const_runme.rb index db56252da..149aa0898 100644 --- a/Examples/test-suite/ruby/cpp11_shared_ptr_const_runme.rb +++ b/Examples/test-suite/ruby/cpp11_shared_ptr_const_runme.rb @@ -3,7 +3,7 @@ require "cpp11_shared_ptr_const" include Cpp11_shared_ptr_const -simple_assert_equal(1, foo( Foo.new(1) ).get_m ) -simple_assert_equal(7, const_foo( Foo.new(7) ).get_m ) -simple_assert_equal(7, foo_vec( Foo.new(7) )[0].get_m ) -simple_assert_equal(8, const_foo_vec( Foo.new(8) )[0].get_m ) +swig_assert_equal_simple(1, foo( Foo.new(1) ).get_m ) +swig_assert_equal_simple(7, const_foo( Foo.new(7) ).get_m ) +swig_assert_equal_simple(7, foo_vec( Foo.new(7) )[0].get_m ) +swig_assert_equal_simple(8, const_foo_vec( Foo.new(8) )[0].get_m ) diff --git a/Examples/test-suite/ruby/cpp11_shared_ptr_upcast_runme.rb b/Examples/test-suite/ruby/cpp11_shared_ptr_upcast_runme.rb index 864be1382..000b9b6a9 100644 --- a/Examples/test-suite/ruby/cpp11_shared_ptr_upcast_runme.rb +++ b/Examples/test-suite/ruby/cpp11_shared_ptr_upcast_runme.rb @@ -5,56 +5,56 @@ require 'cpp11_shared_ptr_upcast' include Cpp11_shared_ptr_upcast # non-overloaded -simple_assert_equal( 7, derived_num1(Derived.new(7)) ) -simple_assert_equal( 7, derived_num2([Derived.new(7)]) ) -simple_assert_equal( 7, derived_num3({0 => Derived.new(7)}) ) +swig_assert_equal_simple( 7, derived_num1(Derived.new(7)) ) +swig_assert_equal_simple( 7, derived_num2([Derived.new(7)]) ) +swig_assert_equal_simple( 7, derived_num3({0 => Derived.new(7)}) ) -simple_assert_equal(-1, base_num1(Derived.new(7)) ) -simple_assert_equal(-1, base_num2([Derived.new(7)]) ) -simple_assert_equal(-1, base_num3({0 => Derived.new(7)}) ) +swig_assert_equal_simple(-1, base_num1(Derived.new(7)) ) +swig_assert_equal_simple(-1, base_num2([Derived.new(7)]) ) +swig_assert_equal_simple(-1, base_num3({0 => Derived.new(7)}) ) -simple_assert_equal( 999, derived_num1(nil) ) -simple_assert_equal( 999, derived_num2([nil]) ) -simple_assert_equal( 999, derived_num3({0 => nil}) ) +swig_assert_equal_simple( 999, derived_num1(nil) ) +swig_assert_equal_simple( 999, derived_num2([nil]) ) +swig_assert_equal_simple( 999, derived_num3({0 => nil}) ) -simple_assert_equal( 999, base_num1(nil) ) -simple_assert_equal( 999, base_num2([nil]) ) -simple_assert_equal( 999, base_num3({0 => nil}) ) +swig_assert_equal_simple( 999, base_num1(nil) ) +swig_assert_equal_simple( 999, base_num2([nil]) ) +swig_assert_equal_simple( 999, base_num3({0 => nil}) ) # overloaded -simple_assert_equal( 7, derived_num(Derived.new(7)) ) -simple_assert_equal( 7, derived_num([Derived.new(7)]) ) -simple_assert_equal( 7, derived_num({0 => Derived.new(7)}) ) +swig_assert_equal_simple( 7, derived_num(Derived.new(7)) ) +swig_assert_equal_simple( 7, derived_num([Derived.new(7)]) ) +swig_assert_equal_simple( 7, derived_num({0 => Derived.new(7)}) ) -simple_assert_equal(-1, base_num(Derived.new(7)) ) -simple_assert_equal(-1, base_num([Derived.new(7)]) ) -simple_assert_equal(-1, base_num({0 => Derived.new(7)}) ) +swig_assert_equal_simple(-1, base_num(Derived.new(7)) ) +swig_assert_equal_simple(-1, base_num([Derived.new(7)]) ) +swig_assert_equal_simple(-1, base_num({0 => Derived.new(7)}) ) # ptr to shared_ptr -simple_assert_equal( 7, derived2_num1(Derived2.new(7)) ) -simple_assert_equal( 7, derived2_num2([Derived2.new(7)]) ) -simple_assert_equal( 7, derived2_num3({0 => Derived2.new(7)}) ) +swig_assert_equal_simple( 7, derived2_num1(Derived2.new(7)) ) +swig_assert_equal_simple( 7, derived2_num2([Derived2.new(7)]) ) +swig_assert_equal_simple( 7, derived2_num3({0 => Derived2.new(7)}) ) -simple_assert_equal( -1, base2_num1(Derived2.new(7)) ) +swig_assert_equal_simple( -1, base2_num1(Derived2.new(7)) ) begin # Upcast for pointers to shared_ptr in this generic framework has not been implemented - simple_assert_equal( -1, base2_num2([Derived2.new(7)]) ) + swig_assert_equal_simple( -1, base2_num2([Derived2.new(7)]) ) raise RuntimeError, "Failed to catch TypeError" rescue TypeError end begin # Upcast for pointers to shared_ptr in this generic framework has not been implemented - simple_assert_equal( -1, base2_num3({0 => Derived2.new(7)}) ) + swig_assert_equal_simple( -1, base2_num3({0 => Derived2.new(7)}) ) raise RuntimeError, "Failed to catch TypeError" rescue TypeError end -simple_assert_equal( 888, derived2_num1(nil) ) -simple_assert_equal( 999, derived2_num2([nil]) ) # although 888 would be more consistent -simple_assert_equal( 999, derived2_num3({0 => nil}) ) # although 888 would be more consistent +swig_assert_equal_simple( 888, derived2_num1(nil) ) +swig_assert_equal_simple( 999, derived2_num2([nil]) ) # although 888 would be more consistent +swig_assert_equal_simple( 999, derived2_num3({0 => nil}) ) # although 888 would be more consistent -simple_assert_equal( 888, base2_num1(nil) ) -simple_assert_equal( 999, base2_num2([nil]) ) # although 888 would be more consistent -simple_assert_equal( 999, base2_num3({0 => nil}) ) # although 888 would be more consistent +swig_assert_equal_simple( 888, base2_num1(nil) ) +swig_assert_equal_simple( 999, base2_num2([nil]) ) # although 888 would be more consistent +swig_assert_equal_simple( 999, base2_num3({0 => nil}) ) # although 888 would be more consistent From 79620b10a993f3d735a29ff6f16552e43fb8f533 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Thu, 20 Apr 2017 08:16:50 +0100 Subject: [PATCH 059/455] Add changes entry for enhanced Ruby shared_ptr in containers support --- CHANGES.current | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGES.current b/CHANGES.current index 2d5e841ea..9ea6662cc 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 3.0.13 (in progress) ============================ +2017-04-20: tamuratak + [Ruby] #930, #937 - Fix containers of std::shared_ptr. + Upcasting, const types (eg vector>) and NULL/nullptr support added. + 2017-04-12: smarchetto [Scilab] New parameter targetversion to specify the Scilab target version (5, 6, ..) for code generation With Scilab 6 target specified, identifier names truncation is disabled (no longer necessary) From 661c3fc55472439803ff3b3742ad7c83228d2fb3 Mon Sep 17 00:00:00 2001 From: Takashi Tamura Date: Thu, 13 Apr 2017 15:43:25 +0900 Subject: [PATCH 060/455] [ruby] treat null shared_ptr in std containers properly. --- Lib/ruby/rubystdcommon_forward.swg | 3 ++- Lib/ruby/std_shared_ptr.i | 11 +++++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/Lib/ruby/rubystdcommon_forward.swg b/Lib/ruby/rubystdcommon_forward.swg index 27bcb9960..4120b38e4 100644 --- a/Lib/ruby/rubystdcommon_forward.swg +++ b/Lib/ruby/rubystdcommon_forward.swg @@ -5,7 +5,8 @@ namespace swig { template struct traits_asval; struct pointer_category; template struct traits_as; - template struct traits_from; + template struct traits_from; + template struct traits_from_ptr; template struct noconst_traits; template swig_type_info* type_info(); template const char* type_name(); diff --git a/Lib/ruby/std_shared_ptr.i b/Lib/ruby/std_shared_ptr.i index f6c0a15ac..f2b05ef36 100644 --- a/Lib/ruby/std_shared_ptr.i +++ b/Lib/ruby/std_shared_ptr.i @@ -113,6 +113,17 @@ namespace swig { } }; + template + struct traits_from_ptr > { + static VALUE from(std::shared_ptr *val, int owner = 0) { + if (val && *val) { + return SWIG_NewPointerObj(val, type_info >(), owner); + } else { + return Qnil; + } + } + }; + /* The descriptors in the shared_ptr typemaps remove the const qualifier for the SWIG type system. Remove const likewise here, otherwise SWIG_TypeQuery("std::shared_ptr") will return NULL. From 0c3298073b0502dd0eda43b1a998937a0f00d057 Mon Sep 17 00:00:00 2001 From: Takashi Tamura Date: Sun, 16 Apr 2017 16:35:15 +0900 Subject: [PATCH 061/455] [ruby] add a test for null shared_ptr in containers. --- .../cpp11_shared_ptr_nullptr_in_containers.i | 48 +++++++++++++++++++ ..._shared_ptr_nullptr_in_containers_runme.rb | 15 ++++++ 2 files changed, 63 insertions(+) create mode 100644 Examples/test-suite/cpp11_shared_ptr_nullptr_in_containers.i create mode 100644 Examples/test-suite/ruby/cpp11_shared_ptr_nullptr_in_containers_runme.rb diff --git a/Examples/test-suite/cpp11_shared_ptr_nullptr_in_containers.i b/Examples/test-suite/cpp11_shared_ptr_nullptr_in_containers.i new file mode 100644 index 000000000..3050add7e --- /dev/null +++ b/Examples/test-suite/cpp11_shared_ptr_nullptr_in_containers.i @@ -0,0 +1,48 @@ +%module cpp11_shared_ptr_nullptr_in_containers + +%{ +#include +#include +%} + +%include +%include + +%shared_ptr(C) + +%inline %{ + +class C { +public: + C() : m(-1) {} + C(int i) : m(i) {} + int get_m() { return m; } + int m; +}; + +%} + +%template() std::vector >; + +%inline %{ + + std::vector > ret_vec_c_shared_ptr() { + std::vector > ret(3); + ret[0] = std::shared_ptr(new C(0)); + ret[2] = std::shared_ptr(new C(2)); + return ret; + } + + std::vector > ret_arg_vec(const std::vector >& v) { + return v; + } + + bool is_last_null(const std::vector >& v) { + if( *v.end() ) { + return false; + } else { + return true; + } + } + +%} diff --git a/Examples/test-suite/ruby/cpp11_shared_ptr_nullptr_in_containers_runme.rb b/Examples/test-suite/ruby/cpp11_shared_ptr_nullptr_in_containers_runme.rb new file mode 100644 index 000000000..46d499427 --- /dev/null +++ b/Examples/test-suite/ruby/cpp11_shared_ptr_nullptr_in_containers_runme.rb @@ -0,0 +1,15 @@ +require "cpp11_shared_ptr_nullptr_in_containers" + +include Cpp11_shared_ptr_nullptr_in_containers + +a = ret_vec_c_shared_ptr() +raise unless a[0].get_m == 0 +raise unless a[1] == nil +raise unless a[2].get_m == 2 + +a = ret_arg_vec([C.new(7), nil, C.new(9)]) +raise unless a[0].get_m == 7 +raise unless a[1] == nil +raise unless a[2].get_m == 9 + +raise unless is_last_null([C.new(7), C.new(8), nil]) From 042d8289fd2beb27a909b8f0f7787a353ad34fb3 Mon Sep 17 00:00:00 2001 From: Takashi Tamura Date: Mon, 17 Apr 2017 12:28:49 +0900 Subject: [PATCH 062/455] [ruby] enable a test for null shared_ptr in containers. --- Examples/test-suite/ruby/Makefile.in | 1 + 1 file changed, 1 insertion(+) diff --git a/Examples/test-suite/ruby/Makefile.in b/Examples/test-suite/ruby/Makefile.in index 27e9f5e18..8ed73efb0 100644 --- a/Examples/test-suite/ruby/Makefile.in +++ b/Examples/test-suite/ruby/Makefile.in @@ -33,6 +33,7 @@ CPP_TEST_CASES = \ CPP11_TEST_CASES = \ cpp11_hash_tables \ cpp11_shared_ptr_upcast \ + cpp11_shared_ptr_nullptr_in_containers \ cpp11_shared_ptr_const C_TEST_CASES += \ From cc4e3aec52ecedb1240ae56f92fdf70b64e1380c Mon Sep 17 00:00:00 2001 From: Takashi Tamura Date: Thu, 20 Apr 2017 13:59:44 +0900 Subject: [PATCH 063/455] [ruby] use std::vector::back() method. --- Examples/test-suite/cpp11_shared_ptr_nullptr_in_containers.i | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Examples/test-suite/cpp11_shared_ptr_nullptr_in_containers.i b/Examples/test-suite/cpp11_shared_ptr_nullptr_in_containers.i index 3050add7e..46e2501d7 100644 --- a/Examples/test-suite/cpp11_shared_ptr_nullptr_in_containers.i +++ b/Examples/test-suite/cpp11_shared_ptr_nullptr_in_containers.i @@ -3,6 +3,8 @@ %{ #include #include + +class C; %} %include @@ -38,7 +40,7 @@ public: } bool is_last_null(const std::vector >& v) { - if( *v.end() ) { + if( v.back() ) { return false; } else { return true; From 34ba3b9ed96b864de0ddd8768394252e43aa7ead Mon Sep 17 00:00:00 2001 From: Takashi Tamura Date: Thu, 20 Apr 2017 14:20:33 +0900 Subject: [PATCH 064/455] [ruby] add a test. --- .../ruby/cpp11_shared_ptr_nullptr_in_containers_runme.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/Examples/test-suite/ruby/cpp11_shared_ptr_nullptr_in_containers_runme.rb b/Examples/test-suite/ruby/cpp11_shared_ptr_nullptr_in_containers_runme.rb index 46d499427..9d8b3c050 100644 --- a/Examples/test-suite/ruby/cpp11_shared_ptr_nullptr_in_containers_runme.rb +++ b/Examples/test-suite/ruby/cpp11_shared_ptr_nullptr_in_containers_runme.rb @@ -13,3 +13,4 @@ raise unless a[1] == nil raise unless a[2].get_m == 9 raise unless is_last_null([C.new(7), C.new(8), nil]) +raise if is_last_null([C.new(7), C.new(8)]) From 1c968b3695b234ec94cf7fbdb9902ecd519d2edf Mon Sep 17 00:00:00 2001 From: Takashi Tamura Date: Mon, 10 Apr 2017 18:53:46 +0900 Subject: [PATCH 065/455] add a test for shared_ptr with director --- .../test-suite/cpp11_shared_ptr_director.i | 23 ++++++++++++++++++ .../ruby/cpp11_shared_ptr_director_runme.rb | 24 +++++++++++++++++++ 2 files changed, 47 insertions(+) create mode 100644 Examples/test-suite/cpp11_shared_ptr_director.i create mode 100644 Examples/test-suite/ruby/cpp11_shared_ptr_director_runme.rb diff --git a/Examples/test-suite/cpp11_shared_ptr_director.i b/Examples/test-suite/cpp11_shared_ptr_director.i new file mode 100644 index 000000000..a8907de2c --- /dev/null +++ b/Examples/test-suite/cpp11_shared_ptr_director.i @@ -0,0 +1,23 @@ +%module(directors="1") "cpp11_shared_ptr_director" + +%{ +#include +%} + +%include "std_shared_ptr.i"; +%shared_ptr(Created); +%feature("director") Creator; + +%inline %{ +struct Created {}; + +struct Creator { + Creator() {}; + virtual std::shared_ptr create() = 0; + virtual ~Creator() {} +}; + +void crash(Creator* creator) { + std::shared_ptr ptr = creator->create(); +} +%} diff --git a/Examples/test-suite/ruby/cpp11_shared_ptr_director_runme.rb b/Examples/test-suite/ruby/cpp11_shared_ptr_director_runme.rb new file mode 100644 index 000000000..17e7512f3 --- /dev/null +++ b/Examples/test-suite/ruby/cpp11_shared_ptr_director_runme.rb @@ -0,0 +1,24 @@ +require 'cpp11_shared_ptr_director' + +include Cpp11_shared_ptr_director + +class Derived < Creator + + def initialize(flag) + @return_none = flag + super() + end + + def create + if @return_none + nil + else + Created.new + end + end + +end + +crash(Derived.new(false)) +crash(Derived.new(true)) + From b3c2b1c51ca703177082479874d3ac533d529de0 Mon Sep 17 00:00:00 2001 From: Takashi Tamura Date: Mon, 10 Apr 2017 23:26:18 +0900 Subject: [PATCH 066/455] [ruby] add %typemap(directorout) for shared_ptr. --- Examples/test-suite/cpp11_shared_ptr_director.i | 13 +++++++++++-- .../ruby/cpp11_shared_ptr_director_runme.rb | 4 ++-- Lib/ruby/boost_shared_ptr.i | 12 ++++++++++++ 3 files changed, 25 insertions(+), 4 deletions(-) diff --git a/Examples/test-suite/cpp11_shared_ptr_director.i b/Examples/test-suite/cpp11_shared_ptr_director.i index a8907de2c..23e649af3 100644 --- a/Examples/test-suite/cpp11_shared_ptr_director.i +++ b/Examples/test-suite/cpp11_shared_ptr_director.i @@ -9,7 +9,10 @@ %feature("director") Creator; %inline %{ -struct Created {}; +struct Created { + Created() {}; + int get_m() { return 1; }; +}; struct Creator { Creator() {}; @@ -17,7 +20,13 @@ struct Creator { virtual ~Creator() {} }; -void crash(Creator* creator) { +int crash(Creator* creator) { std::shared_ptr ptr = creator->create(); + if (ptr) { + return ptr->get_m(); + } else { + return -1; + } } + %} diff --git a/Examples/test-suite/ruby/cpp11_shared_ptr_director_runme.rb b/Examples/test-suite/ruby/cpp11_shared_ptr_director_runme.rb index 17e7512f3..208e72603 100644 --- a/Examples/test-suite/ruby/cpp11_shared_ptr_director_runme.rb +++ b/Examples/test-suite/ruby/cpp11_shared_ptr_director_runme.rb @@ -19,6 +19,6 @@ class Derived < Creator end -crash(Derived.new(false)) -crash(Derived.new(true)) +p crash(Derived.new(false)) +p crash(Derived.new(true)) diff --git a/Lib/ruby/boost_shared_ptr.i b/Lib/ruby/boost_shared_ptr.i index 938074d81..356e87452 100644 --- a/Lib/ruby/boost_shared_ptr.i +++ b/Lib/ruby/boost_shared_ptr.i @@ -197,6 +197,18 @@ %set_output(SWIG_NewPointerObj(%as_voidptr(smartresult), $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), SWIG_POINTER_OWN)); } +%typemap(directorout) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > (void * swig_argp, int swig_res = 0) { + if (NIL_P($input)) { + $result = $ltype(); + } else { + swig_res = SWIG_ConvertPtr($input,&swig_argp,$&descriptor, %convertptr_flags); + if (!SWIG_IsOK(swig_res)) { + %dirout_fail(swig_res,"$type"); + } + $result = *(%reinterpret_cast(swig_argp, $<ype)); + } +} + %typemap(varin) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > { swig_ruby_owntype newmem = {0, 0}; void *argp = 0; From 17b4e0c66ec262381832950cc381e1a22ed6ffaa Mon Sep 17 00:00:00 2001 From: Takashi Tamura Date: Tue, 11 Apr 2017 18:41:14 +0900 Subject: [PATCH 067/455] [ruby] add %typemap(directorin) and %typemap(directorout) for shared_ptr. --- .../test-suite/cpp11_shared_ptr_director.i | 48 ++++++++--- .../ruby/cpp11_shared_ptr_director_runme.rb | 34 ++++++-- Lib/ruby/boost_shared_ptr.i | 80 ++++++++++++++++--- 3 files changed, 133 insertions(+), 29 deletions(-) diff --git a/Examples/test-suite/cpp11_shared_ptr_director.i b/Examples/test-suite/cpp11_shared_ptr_director.i index 23e649af3..bb23a1de7 100644 --- a/Examples/test-suite/cpp11_shared_ptr_director.i +++ b/Examples/test-suite/cpp11_shared_ptr_director.i @@ -5,23 +5,29 @@ %} %include "std_shared_ptr.i"; -%shared_ptr(Created); -%feature("director") Creator; +%shared_ptr(C); +%feature("director") Base; %inline %{ -struct Created { - Created() {}; - int get_m() { return 1; }; +struct C { + C() : m(1) {}; + C(int n) : m(n) {}; + int get_m() { return m; }; + int m; }; -struct Creator { - Creator() {}; - virtual std::shared_ptr create() = 0; - virtual ~Creator() {} +struct Base { + Base() {}; + virtual std::shared_ptr ret_c_shared_ptr() = 0; + virtual C ret_c_by_value() = 0; + virtual int take_c_by_value(C c) = 0; + virtual int take_c_shared_ptr_by_value(std::shared_ptr c) = 0; + virtual int take_c_shared_ptr_by_ref(std::shared_ptr& c) = 0; + virtual ~Base() {} }; -int crash(Creator* creator) { - std::shared_ptr ptr = creator->create(); +int call_ret_c_shared_ptr(Base* b) { + std::shared_ptr ptr = b->ret_c_shared_ptr(); if (ptr) { return ptr->get_m(); } else { @@ -29,4 +35,24 @@ int crash(Creator* creator) { } } +int call_ret_c_by_value(Base* b) { + C c = b->ret_c_by_value(); + return c.get_m(); +} + +int call_take_c_by_value(Base* b) { + C c(5); + return b->take_c_by_value(c); +} + +int call_take_c_shared_ptr_by_value(Base* b) { + std::shared_ptr ptr(new C(6)); + return b->take_c_shared_ptr_by_value(ptr); +} + +int call_take_c_shared_ptr_by_ref(Base* b) { + std::shared_ptr ptr(new C(7)); + return b->take_c_shared_ptr_by_ref(ptr); +} + %} diff --git a/Examples/test-suite/ruby/cpp11_shared_ptr_director_runme.rb b/Examples/test-suite/ruby/cpp11_shared_ptr_director_runme.rb index 208e72603..c2aefaa3d 100644 --- a/Examples/test-suite/ruby/cpp11_shared_ptr_director_runme.rb +++ b/Examples/test-suite/ruby/cpp11_shared_ptr_director_runme.rb @@ -2,23 +2,47 @@ require 'cpp11_shared_ptr_director' include Cpp11_shared_ptr_director -class Derived < Creator +class Derived < Base def initialize(flag) @return_none = flag super() end - def create + def ret_c_shared_ptr if @return_none nil else - Created.new + C.new end end + def ret_c_by_value + C.new + end + + def take_c_by_value(c) + c.get_m + end + + def take_c_shared_ptr_by_value(c) + c.get_m + end + + def take_c_shared_ptr_by_ref(c) + c.get_m + end + end -p crash(Derived.new(false)) -p crash(Derived.new(true)) +a = Derived.new(false) +b = Derived.new(true) + +raise unless call_ret_c_shared_ptr(a) == 1 +raise unless call_ret_c_shared_ptr(b) == -1 +raise unless call_ret_c_by_value(a) == 1 + +raise unless call_take_c_by_value(a) == 5 +raise unless call_take_c_shared_ptr_by_value(a) == 6 +raise unless call_take_c_shared_ptr_by_ref(a) == 7 diff --git a/Lib/ruby/boost_shared_ptr.i b/Lib/ruby/boost_shared_ptr.i index 356e87452..ef65fcb25 100644 --- a/Lib/ruby/boost_shared_ptr.i +++ b/Lib/ruby/boost_shared_ptr.i @@ -24,7 +24,9 @@ // Typemap customisations... +// // plain value +// %typemap(in) CONST TYPE (void *argp, int res = 0) { swig_ruby_owntype newmem = {0, 0}; res = SWIG_ConvertPtrAndOwn($input, &argp, $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), %convertptr_flags, &newmem); @@ -62,8 +64,28 @@ %set_varoutput(SWIG_NewPointerObj(%as_voidptr(smartresult), $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), SWIG_POINTER_OWN)); } +%typemap(directorout,noblock=1) CONST TYPE (void *argp, int res = 0) { + swig_ruby_owntype newmem = {0, 0}; + res = SWIG_ConvertPtrAndOwn($input, &argp, $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), %convertptr_flags, &newmem); + if (!SWIG_IsOK(res)) { + %dirout_fail(res, "$type"); + } + if (!argp) { + %dirout_nullref("$type"); + } else { + $result = *(%reinterpret_cast(argp, SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *)->get()); + if (newmem.own & SWIG_CAST_NEW_MEMORY) delete %reinterpret_cast(argp, SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *); + } +} +%typemap(directorin,noblock=1) 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)); + $input = SWIG_NewPointerObj(%as_voidptr(smartresult), $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), SWIG_POINTER_OWN | %newpointer_flags); +} + +// // plain pointer // Note: $disown not implemented by default as it will lead to a memory leak of the shared_ptr instance +// %typemap(in) CONST TYPE * (void *argp = 0, int res = 0, SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > tempshared, SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *smartarg = 0) { swig_ruby_owntype newmem = {0, 0}; res = SWIG_ConvertPtrAndOwn($input, &argp, $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), SHARED_PTR_DISOWN | %convertptr_flags, &newmem); @@ -79,7 +101,6 @@ $1 = %const_cast((smartarg ? smartarg->get() : 0), $1_ltype); } } - %typemap(out, fragment="SWIG_null_deleter_python") CONST TYPE * { SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *smartresult = $1 ? new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >($1 SWIG_NO_NULL_DELETER_$owner) : 0; %set_output(SWIG_NewPointerObj(%as_voidptr(smartresult), $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), $owner | SWIG_POINTER_OWN)); @@ -108,7 +129,16 @@ %set_varoutput(SWIG_NewPointerObj(%as_voidptr(smartresult), $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), SWIG_POINTER_OWN)); } +%typemap(directorin,noblock=1) CONST TYPE * %{ +#error "directorin typemap for plain pointer not implemented" +%} +%typemap(directorout,noblock=1) CONST TYPE * %{ +#error "directorout typemap for plain pointer not implemented" +%} + +// // plain reference +// %typemap(in) CONST TYPE & (void *argp = 0, int res = 0, SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > tempshared) { swig_ruby_owntype newmem = {0, 0}; res = SWIG_ConvertPtrAndOwn($input, &argp, $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), %convertptr_flags, &newmem); @@ -153,8 +183,17 @@ %set_varoutput(SWIG_NewPointerObj(%as_voidptr(smartresult), $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), SWIG_POINTER_OWN)); } +%typemap(directorin,noblock=1) CONST TYPE & %{ +#error "directorin typemap for plain reference not implemented" +%} +%typemap(directorout,noblock=1) CONST TYPE & %{ +#error "directorout typemap for plain reference not implemented" +%} + +// // plain pointer by reference // Note: $disown not implemented by default as it will lead to a memory leak of the shared_ptr instance +// %typemap(in) TYPE *CONST& (void *argp = 0, int res = 0, $*1_ltype temp = 0, SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > tempshared) { swig_ruby_owntype newmem = {0, 0}; res = SWIG_ConvertPtrAndOwn($input, &argp, $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), SHARED_PTR_DISOWN | %convertptr_flags, &newmem); @@ -182,7 +221,16 @@ #error "varout typemap not implemented" %} +%typemap(directorin,noblock=1) TYPE *CONST& %{ +#error "directorin typemap for plain pointer by reference not implemented" +%} +%typemap(directorout,noblock=1) TYPE *CONST& %{ +#error "directorout typemap for plain pointer by reference not implemented" +%} + +// // shared_ptr by value +// %typemap(in) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > (void *argp, int res = 0) { swig_ruby_owntype newmem = {0, 0}; res = SWIG_ConvertPtrAndOwn($input, &argp, $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), %convertptr_flags, &newmem); @@ -197,18 +245,6 @@ %set_output(SWIG_NewPointerObj(%as_voidptr(smartresult), $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), SWIG_POINTER_OWN)); } -%typemap(directorout) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > (void * swig_argp, int swig_res = 0) { - if (NIL_P($input)) { - $result = $ltype(); - } else { - swig_res = SWIG_ConvertPtr($input,&swig_argp,$&descriptor, %convertptr_flags); - if (!SWIG_IsOK(swig_res)) { - %dirout_fail(swig_res,"$type"); - } - $result = *(%reinterpret_cast(swig_argp, $<ype)); - } -} - %typemap(varin) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > { swig_ruby_owntype newmem = {0, 0}; void *argp = 0; @@ -224,7 +260,21 @@ %set_varoutput(SWIG_NewPointerObj(%as_voidptr(smartresult), $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), SWIG_POINTER_OWN)); } +%typemap(directorout,noblock=1) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > (void * swig_argp, int swig_res = 0) { + if (NIL_P($input)) { + $result = $ltype(); + } else { + swig_res = SWIG_ConvertPtr($input,&swig_argp,$&descriptor, %convertptr_flags); + if (!SWIG_IsOK(swig_res)) { + %dirout_fail(swig_res,"$type"); + } + $result = *(%reinterpret_cast(swig_argp, $<ype)); + } +} + +// // shared_ptr by reference +// %typemap(in) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > & (void *argp, int res = 0, $*1_ltype tempshared) { swig_ruby_owntype newmem = {0, 0}; res = SWIG_ConvertPtrAndOwn($input, &argp, $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), %convertptr_flags, &newmem); @@ -251,7 +301,9 @@ #error "varout typemap not implemented" %} +// // shared_ptr by pointer +// %typemap(in) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > * (void *argp, int res = 0, $*1_ltype tempshared) { swig_ruby_owntype newmem = {0, 0}; res = SWIG_ConvertPtrAndOwn($input, &argp, $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), %convertptr_flags, &newmem); @@ -279,7 +331,9 @@ #error "varout typemap not implemented" %} +// // shared_ptr by pointer reference +// %typemap(in) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *& (void *argp, int res = 0, SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > tempshared, $*1_ltype temp = 0) { swig_ruby_owntype newmem = {0, 0}; res = SWIG_ConvertPtrAndOwn($input, &argp, $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), %convertptr_flags, &newmem); From 0f94b936e82201f56cc6d4a24cd3645640ddeaf9 Mon Sep 17 00:00:00 2001 From: Takashi Tamura Date: Tue, 11 Apr 2017 18:51:32 +0900 Subject: [PATCH 068/455] [ruby] enable a test, cpp11_shared_ptr_director. --- Examples/test-suite/ruby/Makefile.in | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Examples/test-suite/ruby/Makefile.in b/Examples/test-suite/ruby/Makefile.in index 27e9f5e18..33f42a7fc 100644 --- a/Examples/test-suite/ruby/Makefile.in +++ b/Examples/test-suite/ruby/Makefile.in @@ -33,7 +33,8 @@ CPP_TEST_CASES = \ CPP11_TEST_CASES = \ cpp11_hash_tables \ cpp11_shared_ptr_upcast \ - cpp11_shared_ptr_const + cpp11_shared_ptr_const \ + cpp11_shared_ptr_director C_TEST_CASES += \ li_cstring \ From 0020fc97b02d6ec7d58e211d1a652f68d6bc7f51 Mon Sep 17 00:00:00 2001 From: Takashi Tamura Date: Wed, 12 Apr 2017 12:20:05 +0900 Subject: [PATCH 069/455] [ruby] add %typemap(directorin) for shared_ptr. --- .../test-suite/cpp11_shared_ptr_director.i | 32 +++++++++++++++ .../ruby/cpp11_shared_ptr_director_runme.rb | 41 ++++++++++++++++--- Lib/ruby/boost_shared_ptr.i | 26 +++++++++++- 3 files changed, 93 insertions(+), 6 deletions(-) diff --git a/Examples/test-suite/cpp11_shared_ptr_director.i b/Examples/test-suite/cpp11_shared_ptr_director.i index bb23a1de7..0f0554134 100644 --- a/Examples/test-suite/cpp11_shared_ptr_director.i +++ b/Examples/test-suite/cpp11_shared_ptr_director.i @@ -23,6 +23,8 @@ struct Base { virtual int take_c_by_value(C c) = 0; virtual int take_c_shared_ptr_by_value(std::shared_ptr c) = 0; virtual int take_c_shared_ptr_by_ref(std::shared_ptr& c) = 0; + virtual int take_c_shared_ptr_by_pointer(std::shared_ptr* c) = 0; + virtual int take_c_shared_ptr_by_pointer_ref(std::shared_ptr*const&c) = 0; virtual ~Base() {} }; @@ -50,9 +52,39 @@ int call_take_c_shared_ptr_by_value(Base* b) { return b->take_c_shared_ptr_by_value(ptr); } +int call_take_c_shared_ptr_by_value_with_null(Base* b) { + std::shared_ptr ptr; + return b->take_c_shared_ptr_by_value(ptr); +} + int call_take_c_shared_ptr_by_ref(Base* b) { std::shared_ptr ptr(new C(7)); return b->take_c_shared_ptr_by_ref(ptr); } +int call_take_c_shared_ptr_by_ref_with_null(Base* b) { + std::shared_ptr ptr; + return b->take_c_shared_ptr_by_ref(ptr); +} + +int call_take_c_shared_ptr_by_pointer(Base* b) { + std::shared_ptr ptr(new C(8)); + return b->take_c_shared_ptr_by_pointer(&ptr); +} + +int call_take_c_shared_ptr_by_pointer_with_null(Base* b) { + std::shared_ptr ptr; + return b->take_c_shared_ptr_by_pointer(&ptr); +} + +int call_take_c_shared_ptr_by_pointer_ref(Base* b) { + auto ptr = new std::shared_ptr(new C(9)); + return b->take_c_shared_ptr_by_pointer_ref(ptr); +} + +int call_take_c_shared_ptr_by_pointer_ref_with_null(Base* b) { + auto ptr = new std::shared_ptr(); + return b->take_c_shared_ptr_by_pointer_ref(ptr); +} + %} diff --git a/Examples/test-suite/ruby/cpp11_shared_ptr_director_runme.rb b/Examples/test-suite/ruby/cpp11_shared_ptr_director_runme.rb index c2aefaa3d..51b338aef 100644 --- a/Examples/test-suite/ruby/cpp11_shared_ptr_director_runme.rb +++ b/Examples/test-suite/ruby/cpp11_shared_ptr_director_runme.rb @@ -26,11 +26,35 @@ class Derived < Base end def take_c_shared_ptr_by_value(c) - c.get_m + if c + c.get_m + else + -2 + end end def take_c_shared_ptr_by_ref(c) - c.get_m + if c + c.get_m + else + -3 + end + end + + def take_c_shared_ptr_by_pointer(c) + if c + c.get_m + else + -4 + end + end + + def take_c_shared_ptr_by_pointer_ref(c) + if c + c.get_m + else + -5 + end end end @@ -42,7 +66,14 @@ raise unless call_ret_c_shared_ptr(a) == 1 raise unless call_ret_c_shared_ptr(b) == -1 raise unless call_ret_c_by_value(a) == 1 -raise unless call_take_c_by_value(a) == 5 -raise unless call_take_c_shared_ptr_by_value(a) == 6 -raise unless call_take_c_shared_ptr_by_ref(a) == 7 +raise unless call_take_c_by_value(a) == 5 +raise unless call_take_c_shared_ptr_by_value(a) == 6 +raise unless call_take_c_shared_ptr_by_ref(a) == 7 +raise unless call_take_c_shared_ptr_by_pointer(a) == 8 +raise unless call_take_c_shared_ptr_by_pointer_ref(a) == 9 + +raise unless call_take_c_shared_ptr_by_value_with_null(a) == -2 +raise unless call_take_c_shared_ptr_by_ref_with_null(a) == -3 +raise unless call_take_c_shared_ptr_by_pointer_with_null(a) == -4 +raise unless call_take_c_shared_ptr_by_pointer_ref_with_null(a) == -5 diff --git a/Lib/ruby/boost_shared_ptr.i b/Lib/ruby/boost_shared_ptr.i index ef65fcb25..0350f41d9 100644 --- a/Lib/ruby/boost_shared_ptr.i +++ b/Lib/ruby/boost_shared_ptr.i @@ -260,11 +260,19 @@ %set_varoutput(SWIG_NewPointerObj(%as_voidptr(smartresult), $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), SWIG_POINTER_OWN)); } +%typemap(directorin,noblock=1) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > { + if ($1) { + SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *smartresult = new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >($1); + $input = SWIG_NewPointerObj(%as_voidptr(smartresult), $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), SWIG_POINTER_OWN | %newpointer_flags); + } else { + $input = Qnil; + } +} %typemap(directorout,noblock=1) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > (void * swig_argp, int swig_res = 0) { if (NIL_P($input)) { $result = $ltype(); } else { - swig_res = SWIG_ConvertPtr($input,&swig_argp,$&descriptor, %convertptr_flags); + swig_res = SWIG_ConvertPtr($input, &swig_argp, $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), %convertptr_flags); if (!SWIG_IsOK(swig_res)) { %dirout_fail(swig_res,"$type"); } @@ -301,6 +309,14 @@ #error "varout typemap not implemented" %} +%typemap(directorin,noblock=1) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > & { + if ($1) { + $input = SWIG_NewPointerObj(%as_voidptr(&$1), $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), %newpointer_flags); + } else { + $input = Qnil; + } +} + // // shared_ptr by pointer // @@ -331,6 +347,14 @@ #error "varout typemap not implemented" %} +%typemap(directorin,noblock=1) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *, SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *const& { + if ($1 && *$1) { + $input = SWIG_NewPointerObj(%as_voidptr($1), $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), %newpointer_flags); + } else { + $input = Qnil; + } +} + // // shared_ptr by pointer reference // From b4377488f775464ddbb324128941c7182233f13c Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Thu, 20 Apr 2017 18:51:45 +0100 Subject: [PATCH 070/455] Add assert for invalid NULL type parameter when calling SWIG_Ruby_NewPointerObj. Closes #935 --- CHANGES.current | 3 +++ Lib/ruby/rubyrun.swg | 9 +++++---- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/CHANGES.current b/CHANGES.current index 9ea6662cc..e31a71ab9 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 3.0.13 (in progress) ============================ +2017-04-20: wsfulton + [Ruby] #586, #935 Add assert for invalid NULL type parameter when calling SWIG_Ruby_NewPointerObj. + 2017-04-20: tamuratak [Ruby] #930, #937 - Fix containers of std::shared_ptr. Upcasting, const types (eg vector>) and NULL/nullptr support added. diff --git a/Lib/ruby/rubyrun.swg b/Lib/ruby/rubyrun.swg index 94618db4e..4628aedc3 100644 --- a/Lib/ruby/rubyrun.swg +++ b/Lib/ruby/rubyrun.swg @@ -171,10 +171,11 @@ SWIG_Ruby_NewPointerObj(void *ptr, swig_type_info *type, int flags) swig_class *sklass; VALUE klass; VALUE obj; - + if (!ptr) return Qnil; - + + assert(type); if (type->clientdata) { sklass = (swig_class *) type->clientdata; @@ -182,7 +183,7 @@ SWIG_Ruby_NewPointerObj(void *ptr, swig_type_info *type, int flags) track = sklass->trackObjects; if (track) { obj = SWIG_RubyInstanceFor(ptr); - + /* Check the object's type and make sure it has the correct type. It might not in cases where methods do things like downcast methods. */ @@ -214,7 +215,7 @@ SWIG_Ruby_NewPointerObj(void *ptr, swig_type_info *type, int flags) obj = Data_Wrap_Struct(klass, 0, 0, ptr); } rb_iv_set(obj, "@__swigtype__", rb_str_new2(type->name)); - + return obj; } From ab1e9f5bd9dba792f6fa197299f303f089663e79 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Thu, 20 Apr 2017 19:20:35 +0100 Subject: [PATCH 071/455] Consistent whitespace amongst all the shared_ptr and intrusive_ptr typemaps [skip ci] --- Lib/csharp/boost_shared_ptr.i | 16 +++---- Lib/java/boost_intrusive_ptr.i | 80 +++++++++++++++++----------------- Lib/java/boost_shared_ptr.i | 18 ++++---- Lib/octave/boost_shared_ptr.i | 22 +++++----- Lib/python/boost_shared_ptr.i | 23 +++++----- Lib/r/boost_shared_ptr.i | 22 +++++----- Lib/scilab/boost_shared_ptr.i | 22 +++++----- 7 files changed, 101 insertions(+), 102 deletions(-) diff --git a/Lib/csharp/boost_shared_ptr.i b/Lib/csharp/boost_shared_ptr.i index 2b65bf20d..8d65d7953 100644 --- a/Lib/csharp/boost_shared_ptr.i +++ b/Lib/csharp/boost_shared_ptr.i @@ -14,7 +14,7 @@ %naturalvar SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >; // destructor mods -%feature("unref") TYPE +%feature("unref") TYPE //"if (debug_shared) { cout << \"deleting use_count: \" << (*smartarg1).use_count() << \" [\" << (boost::get_deleter(*smartarg1) ? std::string(\"CANNOT BE DETERMINED SAFELY\") : ( (*smartarg1).get() ? (*smartarg1)->getValue() : std::string(\"NULL PTR\") )) << \"]\" << endl << flush; }\n" "(void)arg1; delete smartarg1;" @@ -28,7 +28,7 @@ return $null; } $1 = *argp; %} -%typemap(out) CONST TYPE +%typemap(out) CONST TYPE %{ $result = new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >(new $1_ltype(($1_ltype &)$1)); %} // plain pointer @@ -66,7 +66,7 @@ %typemap(in, canthrow=1) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > & ($*1_ltype tempnull) %{ $1 = $input ? ($1_ltype)$input : &tempnull; %} %typemap(out) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > & -%{ $result = *$1 ? new $*1_ltype(*$1) : 0; %} +%{ $result = *$1 ? new $*1_ltype(*$1) : 0; %} // shared_ptr by pointer %typemap(in) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > * ($*1_ltype tempnull) @@ -80,7 +80,7 @@ %{ temp = $input ? *($1_ltype)&$input : &tempnull; $1 = &temp; %} %typemap(out) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *& -%{ *($1_ltype)&$result = (*$1 && **$1) ? new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >(**$1) : 0; %} +%{ *($1_ltype)&$result = (*$1 && **$1) ? new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >(**$1) : 0; %} // various missing typemaps - If ever used (unlikely) ensure compilation error rather than runtime bug %typemap(in) CONST TYPE[], CONST TYPE[ANY], CONST TYPE (CLASS::*) %{ @@ -91,20 +91,20 @@ %} -%typemap (ctype) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >, +%typemap (ctype) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >, SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > &, SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *, SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *& "void *" -%typemap (imtype, out="global::System.IntPtr") SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >, +%typemap (imtype, out="global::System.IntPtr") SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >, SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > &, SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *, SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *& "global::System.Runtime.InteropServices.HandleRef" -%typemap (cstype) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >, +%typemap (cstype) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >, SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > &, SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *, SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *& "$typemap(cstype, TYPE)" -%typemap(csin) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >, +%typemap(csin) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >, SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > &, SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *, SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *& "$typemap(cstype, TYPE).getCPtr($csinput)" diff --git a/Lib/java/boost_intrusive_ptr.i b/Lib/java/boost_intrusive_ptr.i index a484a3b6c..48e530c63 100644 --- a/Lib/java/boost_intrusive_ptr.i +++ b/Lib/java/boost_intrusive_ptr.i @@ -29,26 +29,26 @@ SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "Attempt to dereference null $1_type"); return $null; } - $1 = *argp; + $1 = *argp; %} -%typemap(out, fragment="SWIG_intrusive_deleter") CONST TYPE %{ +%typemap(out, fragment="SWIG_intrusive_deleter") CONST TYPE %{ //plain value(out) $1_ltype* resultp = new $1_ltype(($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 >()); + *(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > **)&$result = new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >(resultp, SWIG_intrusive_deleter< CONST TYPE >()); %} %typemap(in) CONST TYPE * (SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *smartarg = 0) %{ // plain pointer smartarg = *(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > **)&$input; - $1 = (TYPE *)(smartarg ? smartarg->get() : 0); + $1 = (TYPE *)(smartarg ? smartarg->get() : 0); %} %typemap(out, fragment="SWIG_intrusive_deleter,SWIG_null_deleter") CONST TYPE * %{ //plain pointer(out) #if ($owner) if ($1) { intrusive_ptr_add_ref($1); - *(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > **)&$result = new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >($1, SWIG_intrusive_deleter< CONST TYPE >()); + *(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > **)&$result = new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >($1, SWIG_intrusive_deleter< CONST TYPE >()); } else { *(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > **)&$result = 0; } @@ -63,70 +63,70 @@ if(!$1) { SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "$1_type reference is null"); return $null; - } + } %} -%typemap(out, fragment="SWIG_intrusive_deleter,SWIG_null_deleter") CONST TYPE & %{ +%typemap(out, fragment="SWIG_intrusive_deleter,SWIG_null_deleter") CONST TYPE & %{ //plain reference(out) #if ($owner) if ($1) { intrusive_ptr_add_ref($1); - *(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > **)&$result = new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >($1, SWIG_intrusive_deleter< CONST TYPE >()); + *(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > **)&$result = new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >($1, SWIG_intrusive_deleter< CONST TYPE >()); } else { *(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > **)&$result = 0; - } + } #else *(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > **)&$result = $1 ? new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >($1 SWIG_NO_NULL_DELETER_0) : 0; #endif %} -%typemap(in) TYPE *CONST& ($*1_ltype temp = 0, SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *smartarg = 0) %{ +%typemap(in) TYPE *CONST& ($*1_ltype temp = 0, SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *smartarg = 0) %{ // plain pointer by reference temp = ($*1_ltype)((*(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > **)&$input) ? (*(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > **)&$input)->get() : 0); - $1 = &temp; + $1 = &temp; %} -%typemap(out, fragment="SWIG_intrusive_deleter,SWIG_null_deleter") TYPE *CONST& %{ +%typemap(out, fragment="SWIG_intrusive_deleter,SWIG_null_deleter") TYPE *CONST& %{ // plain pointer by reference(out) #if ($owner) if (*$1) { intrusive_ptr_add_ref(*$1); - *(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > **)&$result = new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >(*$1, SWIG_intrusive_deleter< CONST TYPE >()); + *(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > **)&$result = new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >(*$1, SWIG_intrusive_deleter< CONST TYPE >()); } else { *(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > **)&$result = 0; - } + } #else *(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > **)&$result = new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >(*$1 SWIG_NO_NULL_DELETER_0); #endif %} -%typemap(in) SWIG_INTRUSIVE_PTR_QNAMESPACE::intrusive_ptr< CONST TYPE > ($&1_type argp, SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > * smartarg) %{ +%typemap(in) SWIG_INTRUSIVE_PTR_QNAMESPACE::intrusive_ptr< CONST TYPE > ($&1_type argp, SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > * smartarg) %{ // intrusive_ptr by value smartarg = *(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >**)&$input; if (smartarg) { - $1 = SWIG_INTRUSIVE_PTR_QNAMESPACE::intrusive_ptr< CONST TYPE >(smartarg->get(), true); + $1 = SWIG_INTRUSIVE_PTR_QNAMESPACE::intrusive_ptr< CONST TYPE >(smartarg->get(), true); } %} -%typemap(out, fragment="SWIG_intrusive_deleter") SWIG_INTRUSIVE_PTR_QNAMESPACE::intrusive_ptr< CONST TYPE > %{ +%typemap(out, fragment="SWIG_intrusive_deleter") SWIG_INTRUSIVE_PTR_QNAMESPACE::intrusive_ptr< CONST TYPE > %{ if ($1) { intrusive_ptr_add_ref(result.get()); *(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > **)&$result = new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >(result.get(), SWIG_intrusive_deleter< CONST TYPE >()); } else { - *(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > **)&$result = 0; + *(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > **)&$result = 0; } %} %typemap(in) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > swigSharedPtrUpcast ($&1_type smartarg) %{ // shared_ptr by value - smartarg = *($&1_ltype*)&$input; - if (smartarg) $1 = *smartarg; + smartarg = *($&1_ltype*)&$input; + if (smartarg) $1 = *smartarg; %} -%typemap(out) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > ANY_TYPE_SWIGSharedPtrUpcast %{ - *($&1_ltype*)&$result = $1 ? new $1_ltype($1) : 0; +%typemap(out) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > ANY_TYPE_SWIGSharedPtrUpcast %{ + *($&1_ltype*)&$result = $1 ? new $1_ltype($1) : 0; %} -%typemap(in) SWIG_INTRUSIVE_PTR_QNAMESPACE::intrusive_ptr< CONST TYPE > & ($*1_ltype tempnull, $*1_ltype temp, SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > * smartarg) %{ +%typemap(in) SWIG_INTRUSIVE_PTR_QNAMESPACE::intrusive_ptr< CONST TYPE > & ($*1_ltype tempnull, $*1_ltype temp, SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > * smartarg) %{ // intrusive_ptr by reference if ( $input ) { - smartarg = *(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >**)&$input; + smartarg = *(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >**)&$input; temp = SWIG_INTRUSIVE_PTR_QNAMESPACE::intrusive_ptr< CONST TYPE >(smartarg->get(), true); $1 = &temp; } else { @@ -140,21 +140,21 @@ $1 = *temp; } %} -%typemap(out, fragment="SWIG_intrusive_deleter") SWIG_INTRUSIVE_PTR_QNAMESPACE::intrusive_ptr< CONST TYPE > & %{ +%typemap(out, fragment="SWIG_intrusive_deleter") SWIG_INTRUSIVE_PTR_QNAMESPACE::intrusive_ptr< CONST TYPE > & %{ if (*$1) { intrusive_ptr_add_ref($1->get()); *(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > **)&$result = new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >($1->get(), SWIG_intrusive_deleter< CONST TYPE >()); } else { *(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > **)&$result = 0; } -%} +%} -%typemap(in) SWIG_INTRUSIVE_PTR_QNAMESPACE::intrusive_ptr< CONST TYPE > * ($*1_ltype tempnull, $*1_ltype temp, SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > * smartarg) %{ +%typemap(in) SWIG_INTRUSIVE_PTR_QNAMESPACE::intrusive_ptr< CONST TYPE > * ($*1_ltype tempnull, $*1_ltype temp, SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > * smartarg) %{ // intrusive_ptr by pointer if ( $input ) { - smartarg = *(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >**)&$input; + smartarg = *(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >**)&$input; temp = SWIG_INTRUSIVE_PTR_QNAMESPACE::intrusive_ptr< CONST TYPE >(smartarg->get(), true); - $1 = &temp; + $1 = &temp; } else { $1 = &tempnull; } @@ -163,17 +163,17 @@ delete $1; if ($self) $1 = new SWIG_INTRUSIVE_PTR_QNAMESPACE::intrusive_ptr< CONST TYPE >(*$input); %} -%typemap(out, fragment="SWIG_intrusive_deleter") SWIG_INTRUSIVE_PTR_QNAMESPACE::intrusive_ptr< CONST TYPE > * %{ +%typemap(out, fragment="SWIG_intrusive_deleter") SWIG_INTRUSIVE_PTR_QNAMESPACE::intrusive_ptr< CONST TYPE > * %{ if ($1 && *$1) { intrusive_ptr_add_ref($1->get()); *(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > **)&$result = new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >($1->get(), SWIG_intrusive_deleter< CONST TYPE >()); } else { *(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > **)&$result = 0; } - if ($owner) delete $1; + if ($owner) delete $1; %} -%typemap(in) SWIG_INTRUSIVE_PTR_QNAMESPACE::intrusive_ptr< CONST TYPE > *& (SWIG_INTRUSIVE_PTR_QNAMESPACE::intrusive_ptr< CONST TYPE > temp, $*1_ltype tempp = 0, SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > * smartarg) %{ +%typemap(in) SWIG_INTRUSIVE_PTR_QNAMESPACE::intrusive_ptr< CONST TYPE > *& (SWIG_INTRUSIVE_PTR_QNAMESPACE::intrusive_ptr< CONST TYPE > temp, $*1_ltype tempp = 0, SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > * smartarg) %{ // intrusive_ptr by pointer reference smartarg = *(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >**)&$input; if ($input) { @@ -185,14 +185,14 @@ %typemap(memberin) SWIG_INTRUSIVE_PTR_QNAMESPACE::intrusive_ptr< CONST TYPE > *& %{ if ($self) $1 = *$input; %} -%typemap(out, fragment="SWIG_intrusive_deleter") SWIG_INTRUSIVE_PTR_QNAMESPACE::intrusive_ptr< CONST TYPE > *& %{ +%typemap(out, fragment="SWIG_intrusive_deleter") SWIG_INTRUSIVE_PTR_QNAMESPACE::intrusive_ptr< CONST TYPE > *& %{ if (*$1 && **$1) { intrusive_ptr_add_ref((*$1)->get()); *(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > **)&$result = new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >((*$1)->get(), SWIG_intrusive_deleter< CONST TYPE >()); } else { *(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > **)&$result = 0; } -%} +%} // various missing typemaps - If ever used (unlikely) ensure compilation error rather than runtime bug %typemap(in) CONST TYPE[], CONST TYPE[ANY], CONST TYPE (CLASS::*) %{ @@ -208,7 +208,7 @@ SWIG_INTRUSIVE_PTR_QNAMESPACE::intrusive_ptr< CONST TYPE > &, SWIG_INTRUSIVE_PTR_QNAMESPACE::intrusive_ptr< CONST TYPE > *, SWIG_INTRUSIVE_PTR_QNAMESPACE::intrusive_ptr< CONST TYPE > *& "jlong" -%typemap (jtype) SWIG_INTRUSIVE_PTR_QNAMESPACE::intrusive_ptr< CONST TYPE >, +%typemap (jtype) SWIG_INTRUSIVE_PTR_QNAMESPACE::intrusive_ptr< CONST TYPE >, SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >, SWIG_INTRUSIVE_PTR_QNAMESPACE::intrusive_ptr< CONST TYPE > &, SWIG_INTRUSIVE_PTR_QNAMESPACE::intrusive_ptr< CONST TYPE > *, @@ -341,7 +341,7 @@ return $null; } $1 = *argp; %} -%typemap(out) CONST TYPE +%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)); %} // plain pointer @@ -371,11 +371,11 @@ %typemap(in) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > swigSharedPtrUpcast ($&1_type smartarg) %{ // shared_ptr by value - smartarg = *($&1_ltype*)&$input; - if (smartarg) $1 = *smartarg; + smartarg = *($&1_ltype*)&$input; + if (smartarg) $1 = *smartarg; %} -%typemap(out) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > ANY_TYPE_SWIGSharedPtrUpcast %{ - *($&1_ltype*)&$result = $1 ? new $1_ltype($1) : 0; +%typemap(out) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > ANY_TYPE_SWIGSharedPtrUpcast %{ + *($&1_ltype*)&$result = $1 ? new $1_ltype($1) : 0; %} // various missing typemaps - If ever used (unlikely) ensure compilation error rather than runtime bug diff --git a/Lib/java/boost_shared_ptr.i b/Lib/java/boost_shared_ptr.i index 5ed16aa32..33da61bf8 100644 --- a/Lib/java/boost_shared_ptr.i +++ b/Lib/java/boost_shared_ptr.i @@ -14,7 +14,7 @@ %naturalvar SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >; // destructor wrapper customisation -%feature("unref") TYPE +%feature("unref") TYPE //"if (debug_shared) { cout << \"deleting use_count: \" << (*smartarg1).use_count() << \" [\" << (boost::get_deleter(*smartarg1) ? std::string(\"CANNOT BE DETERMINED SAFELY\") : ( (*smartarg1).get() ? (*smartarg1)->getValue() : std::string(\"NULL PTR\") )) << \"]\" << endl << flush; }\n" "(void)arg1; delete smartarg1;" @@ -28,7 +28,7 @@ return $null; } $1 = *argp; %} -%typemap(out) CONST TYPE +%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)); %} // plain pointer @@ -58,7 +58,7 @@ // shared_ptr by value %typemap(in) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > ($&1_type argp) -%{ argp = *($&1_ltype*)&$input; +%{ argp = *($&1_ltype*)&$input; if (argp) $1 = *argp; %} %typemap(out) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > %{ *($&1_ltype*)&$result = $1 ? new $1_ltype($1) : 0; %} @@ -67,7 +67,7 @@ %typemap(in) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > & ($*1_ltype tempnull) %{ $1 = $input ? *($&1_ltype)&$input : &tempnull; %} %typemap(out) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > & -%{ *($&1_ltype)&$result = *$1 ? new $*1_ltype(*$1) : 0; %} +%{ *($&1_ltype)&$result = *$1 ? new $*1_ltype(*$1) : 0; %} // shared_ptr by pointer %typemap(in) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > * ($*1_ltype tempnull) @@ -81,7 +81,7 @@ %{ temp = $input ? *($1_ltype)&$input : &tempnull; $1 = &temp; %} %typemap(out) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *& -%{ *($1_ltype)&$result = (*$1 && **$1) ? new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >(**$1) : 0; %} +%{ *($1_ltype)&$result = (*$1 && **$1) ? new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >(**$1) : 0; %} // various missing typemaps - If ever used (unlikely) ensure compilation error rather than runtime bug %typemap(in) CONST TYPE[], CONST TYPE[ANY], CONST TYPE (CLASS::*) %{ @@ -92,20 +92,20 @@ %} -%typemap (jni) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >, +%typemap (jni) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >, SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > &, SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *, SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *& "jlong" -%typemap (jtype) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >, +%typemap (jtype) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >, SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > &, SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *, SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *& "long" -%typemap (jstype) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >, +%typemap (jstype) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >, SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > &, SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *, SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *& "$typemap(jstype, TYPE)" -%typemap(javain) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >, +%typemap(javain) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >, SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > &, SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *, SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *& "$typemap(jstype, TYPE).getCPtr($javainput)" diff --git a/Lib/octave/boost_shared_ptr.i b/Lib/octave/boost_shared_ptr.i index e91862057..4ef646831 100644 --- a/Lib/octave/boost_shared_ptr.i +++ b/Lib/octave/boost_shared_ptr.i @@ -8,7 +8,7 @@ %naturalvar SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >; // destructor wrapper customisation -%feature("unref") TYPE +%feature("unref") TYPE //"if (debug_shared) { cout << \"deleting use_count: \" << (*smartarg1).use_count() << \" [\" << (boost::get_deleter(*smartarg1) ? std::string(\"CANNOT BE DETERMINED SAFELY\") : ( (*smartarg1).get() ? (*smartarg1)->getValue() : std::string(\"NULL PTR\") )) << \"]\" << endl << flush; }\n" "(void)arg1; delete smartarg1;" @@ -19,7 +19,7 @@ int newmem = 0; res = SWIG_ConvertPtrAndOwn($input, &argp, $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), %convertptr_flags, &newmem); if (!SWIG_IsOK(res)) { - %argument_fail(res, "$type", $symname, $argnum); + %argument_fail(res, "$type", $symname, $argnum); } if (!argp) { %argument_nullref("$type", $symname, $argnum); @@ -58,7 +58,7 @@ int newmem = 0; res = SWIG_ConvertPtrAndOwn($input, &argp, $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), %convertptr_flags, &newmem); if (!SWIG_IsOK(res)) { - %argument_fail(res, "$type", $symname, $argnum); + %argument_fail(res, "$type", $symname, $argnum); } if (newmem & SWIG_CAST_NEW_MEMORY) { tempshared = *%reinterpret_cast(argp, SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *); @@ -102,7 +102,7 @@ int newmem = 0; res = SWIG_ConvertPtrAndOwn($input, &argp, $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), %convertptr_flags, &newmem); if (!SWIG_IsOK(res)) { - %argument_fail(res, "$type", $symname, $argnum); + %argument_fail(res, "$type", $symname, $argnum); } if (!argp) { %argument_nullref("$type", $symname, $argnum); } if (newmem & SWIG_CAST_NEW_MEMORY) { @@ -148,7 +148,7 @@ int newmem = 0; res = SWIG_ConvertPtrAndOwn($input, &argp, $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), %convertptr_flags, &newmem); if (!SWIG_IsOK(res)) { - %argument_fail(res, "$type", $symname, $argnum); + %argument_fail(res, "$type", $symname, $argnum); } if (newmem & SWIG_CAST_NEW_MEMORY) { tempshared = *%reinterpret_cast(argp, SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *); @@ -176,7 +176,7 @@ int newmem = 0; res = SWIG_ConvertPtrAndOwn($input, &argp, $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), %convertptr_flags, &newmem); if (!SWIG_IsOK(res)) { - %argument_fail(res, "$type", $symname, $argnum); + %argument_fail(res, "$type", $symname, $argnum); } if (argp) $1 = *(%reinterpret_cast(argp, $<ype)); if (newmem & SWIG_CAST_NEW_MEMORY) delete %reinterpret_cast(argp, $<ype); @@ -206,7 +206,7 @@ int newmem = 0; res = SWIG_ConvertPtrAndOwn($input, &argp, $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), %convertptr_flags, &newmem); if (!SWIG_IsOK(res)) { - %argument_fail(res, "$type", $symname, $argnum); + %argument_fail(res, "$type", $symname, $argnum); } if (newmem & SWIG_CAST_NEW_MEMORY) { if (argp) tempshared = *%reinterpret_cast(argp, $ltype); @@ -233,7 +233,7 @@ int newmem = 0; res = SWIG_ConvertPtrAndOwn($input, &argp, $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), %convertptr_flags, &newmem); if (!SWIG_IsOK(res)) { - %argument_fail(res, "$type", $symname, $argnum); + %argument_fail(res, "$type", $symname, $argnum); } if (newmem & SWIG_CAST_NEW_MEMORY) { if (argp) tempshared = *%reinterpret_cast(argp, $ltype); @@ -261,7 +261,7 @@ int newmem = 0; res = SWIG_ConvertPtrAndOwn($input, &argp, $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), %convertptr_flags, &newmem); if (!SWIG_IsOK(res)) { - %argument_fail(res, "$type", $symname, $argnum); + %argument_fail(res, "$type", $symname, $argnum); } if (argp) tempshared = *%reinterpret_cast(argp, $*ltype); if (newmem & SWIG_CAST_NEW_MEMORY) delete %reinterpret_cast(argp, $*ltype); @@ -281,9 +281,9 @@ %} // Typecheck typemaps -// Note: SWIG_ConvertPtr with void ** parameter set to 0 instead of using SWIG_ConvertPtrAndOwn, so that the casting +// Note: SWIG_ConvertPtr with void ** parameter set to 0 instead of using SWIG_ConvertPtrAndOwn, so that the casting // function is not called thereby avoiding a possible smart pointer copy constructor call when casting up the inheritance chain. -%typemap(typecheck,precedence=SWIG_TYPECHECK_POINTER,noblock=1) +%typemap(typecheck,precedence=SWIG_TYPECHECK_POINTER,noblock=1) TYPE CONST, TYPE CONST &, TYPE CONST *, diff --git a/Lib/python/boost_shared_ptr.i b/Lib/python/boost_shared_ptr.i index 40a1ae1ef..be5604cbe 100644 --- a/Lib/python/boost_shared_ptr.i +++ b/Lib/python/boost_shared_ptr.i @@ -18,7 +18,7 @@ %naturalvar SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >; // destructor wrapper customisation -%feature("unref") TYPE +%feature("unref") TYPE //"if (debug_shared) { cout << \"deleting use_count: \" << (*smartarg1).use_count() << \" [\" << (boost::get_deleter(*smartarg1) ? std::string(\"CANNOT BE DETERMINED SAFELY\") : ( (*smartarg1).get() ? (*smartarg1)->getValue() : std::string(\"NULL PTR\") )) << \"]\" << endl << flush; }\n" "(void)arg1; delete smartarg1;" @@ -29,7 +29,7 @@ int newmem = 0; res = SWIG_ConvertPtrAndOwn($input, &argp, $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), %convertptr_flags, &newmem); if (!SWIG_IsOK(res)) { - %argument_fail(res, "$type", $symname, $argnum); + %argument_fail(res, "$type", $symname, $argnum); } if (!argp) { %argument_nullref("$type", $symname, $argnum); @@ -68,7 +68,7 @@ int newmem = 0; res = SWIG_ConvertPtrAndOwn($input, &argp, $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), SHARED_PTR_DISOWN | %convertptr_flags, &newmem); if (!SWIG_IsOK(res)) { - %argument_fail(res, "$type", $symname, $argnum); + %argument_fail(res, "$type", $symname, $argnum); } if (newmem & SWIG_CAST_NEW_MEMORY) { tempshared = *%reinterpret_cast(argp, SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *); @@ -113,7 +113,7 @@ int newmem = 0; res = SWIG_ConvertPtrAndOwn($input, &argp, $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), %convertptr_flags, &newmem); if (!SWIG_IsOK(res)) { - %argument_fail(res, "$type", $symname, $argnum); + %argument_fail(res, "$type", $symname, $argnum); } if (!argp) { %argument_nullref("$type", $symname, $argnum); } if (newmem & SWIG_CAST_NEW_MEMORY) { @@ -159,7 +159,7 @@ int newmem = 0; res = SWIG_ConvertPtrAndOwn($input, &argp, $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), SHARED_PTR_DISOWN | %convertptr_flags, &newmem); if (!SWIG_IsOK(res)) { - %argument_fail(res, "$type", $symname, $argnum); + %argument_fail(res, "$type", $symname, $argnum); } if (newmem & SWIG_CAST_NEW_MEMORY) { tempshared = *%reinterpret_cast(argp, SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *); @@ -187,7 +187,7 @@ int newmem = 0; res = SWIG_ConvertPtrAndOwn($input, &argp, $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), %convertptr_flags, &newmem); if (!SWIG_IsOK(res)) { - %argument_fail(res, "$type", $symname, $argnum); + %argument_fail(res, "$type", $symname, $argnum); } if (argp) $1 = *(%reinterpret_cast(argp, $<ype)); if (newmem & SWIG_CAST_NEW_MEMORY) delete %reinterpret_cast(argp, $<ype); @@ -217,7 +217,7 @@ int newmem = 0; res = SWIG_ConvertPtrAndOwn($input, &argp, $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), %convertptr_flags, &newmem); if (!SWIG_IsOK(res)) { - %argument_fail(res, "$type", $symname, $argnum); + %argument_fail(res, "$type", $symname, $argnum); } if (newmem & SWIG_CAST_NEW_MEMORY) { if (argp) tempshared = *%reinterpret_cast(argp, $ltype); @@ -244,7 +244,7 @@ int newmem = 0; res = SWIG_ConvertPtrAndOwn($input, &argp, $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), %convertptr_flags, &newmem); if (!SWIG_IsOK(res)) { - %argument_fail(res, "$type", $symname, $argnum); + %argument_fail(res, "$type", $symname, $argnum); } if (newmem & SWIG_CAST_NEW_MEMORY) { if (argp) tempshared = *%reinterpret_cast(argp, $ltype); @@ -272,7 +272,7 @@ int newmem = 0; res = SWIG_ConvertPtrAndOwn($input, &argp, $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), %convertptr_flags, &newmem); if (!SWIG_IsOK(res)) { - %argument_fail(res, "$type", $symname, $argnum); + %argument_fail(res, "$type", $symname, $argnum); } if (argp) tempshared = *%reinterpret_cast(argp, $*ltype); if (newmem & SWIG_CAST_NEW_MEMORY) delete %reinterpret_cast(argp, $*ltype); @@ -292,9 +292,9 @@ %} // Typecheck typemaps -// Note: SWIG_ConvertPtr with void ** parameter set to 0 instead of using SWIG_ConvertPtrAndOwn, so that the casting +// Note: SWIG_ConvertPtr with void ** parameter set to 0 instead of using SWIG_ConvertPtrAndOwn, so that the casting // function is not called thereby avoiding a possible smart pointer copy constructor call when casting up the inheritance chain. -%typemap(typecheck,precedence=SWIG_TYPECHECK_POINTER,noblock=1) +%typemap(typecheck,precedence=SWIG_TYPECHECK_POINTER,noblock=1) TYPE CONST, TYPE CONST &, TYPE CONST *, @@ -321,4 +321,3 @@ %enddef - diff --git a/Lib/r/boost_shared_ptr.i b/Lib/r/boost_shared_ptr.i index 8ef8d2ef2..4a56d7cba 100644 --- a/Lib/r/boost_shared_ptr.i +++ b/Lib/r/boost_shared_ptr.i @@ -8,7 +8,7 @@ %naturalvar SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >; // destructor wrapper customisation -%feature("unref") TYPE +%feature("unref") TYPE //"if (debug_shared) { cout << \"deleting use_count: \" << (*smartarg1).use_count() << \" [\" << (boost::get_deleter(*smartarg1) ? std::string(\"CANNOT BE DETERMINED SAFELY\") : ( (*smartarg1).get() ? (*smartarg1)->getValue() : std::string(\"NULL PTR\") )) << \"]\" << endl << flush; }\n" "(void)arg1; delete smartarg1;" @@ -19,7 +19,7 @@ int newmem = 0; res = SWIG_ConvertPtrAndOwn($input, &argp, $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), %convertptr_flags, &newmem); if (!SWIG_IsOK(res)) { - %argument_fail(res, "$type", $symname, $argnum); + %argument_fail(res, "$type", $symname, $argnum); } if (!argp) { %argument_nullref("$type", $symname, $argnum); @@ -56,7 +56,7 @@ int newmem = 0; res = SWIG_ConvertPtrAndOwn($input, &argp, $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), %convertptr_flags, &newmem); if (!SWIG_IsOK(res)) { - %argument_fail(res, "$type", $symname, $argnum); + %argument_fail(res, "$type", $symname, $argnum); } if (newmem & SWIG_CAST_NEW_MEMORY) { tempshared = *%reinterpret_cast(argp, SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *); @@ -100,7 +100,7 @@ int newmem = 0; res = SWIG_ConvertPtrAndOwn($input, &argp, $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), %convertptr_flags, &newmem); if (!SWIG_IsOK(res)) { - %argument_fail(res, "$type", $symname, $argnum); + %argument_fail(res, "$type", $symname, $argnum); } if (!argp) { %argument_nullref("$type", $symname, $argnum); } if (newmem & SWIG_CAST_NEW_MEMORY) { @@ -146,7 +146,7 @@ int newmem = 0; res = SWIG_ConvertPtrAndOwn($input, &argp, $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), %convertptr_flags, &newmem); if (!SWIG_IsOK(res)) { - %argument_fail(res, "$type", $symname, $argnum); + %argument_fail(res, "$type", $symname, $argnum); } if (newmem & SWIG_CAST_NEW_MEMORY) { tempshared = *%reinterpret_cast(argp, SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *); @@ -174,7 +174,7 @@ int newmem = 0; res = SWIG_ConvertPtrAndOwn($input, &argp, $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), %convertptr_flags, &newmem); if (!SWIG_IsOK(res)) { - %argument_fail(res, "$type", $symname, $argnum); + %argument_fail(res, "$type", $symname, $argnum); } if (argp) $1 = *(%reinterpret_cast(argp, $<ype)); if (newmem & SWIG_CAST_NEW_MEMORY) delete %reinterpret_cast(argp, $<ype); @@ -204,7 +204,7 @@ int newmem = 0; res = SWIG_ConvertPtrAndOwn($input, &argp, $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), %convertptr_flags, &newmem); if (!SWIG_IsOK(res)) { - %argument_fail(res, "$type", $symname, $argnum); + %argument_fail(res, "$type", $symname, $argnum); } if (newmem & SWIG_CAST_NEW_MEMORY) { if (argp) tempshared = *%reinterpret_cast(argp, $ltype); @@ -231,7 +231,7 @@ int newmem = 0; res = SWIG_ConvertPtrAndOwn($input, &argp, $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), %convertptr_flags, &newmem); if (!SWIG_IsOK(res)) { - %argument_fail(res, "$type", $symname, $argnum); + %argument_fail(res, "$type", $symname, $argnum); } if (newmem & SWIG_CAST_NEW_MEMORY) { if (argp) tempshared = *%reinterpret_cast(argp, $ltype); @@ -259,7 +259,7 @@ int newmem = 0; res = SWIG_ConvertPtrAndOwn($input, &argp, $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), %convertptr_flags, &newmem); if (!SWIG_IsOK(res)) { - %argument_fail(res, "$type", $symname, $argnum); + %argument_fail(res, "$type", $symname, $argnum); } if (argp) tempshared = *%reinterpret_cast(argp, $*ltype); if (newmem & SWIG_CAST_NEW_MEMORY) delete %reinterpret_cast(argp, $*ltype); @@ -279,9 +279,9 @@ %} // Typecheck typemaps -// Note: SWIG_ConvertPtr with void ** parameter set to 0 instead of using SWIG_ConvertPtrAndOwn, so that the casting +// Note: SWIG_ConvertPtr with void ** parameter set to 0 instead of using SWIG_ConvertPtrAndOwn, so that the casting // function is not called thereby avoiding a possible smart pointer copy constructor call when casting up the inheritance chain. -%typemap(typecheck,precedence=SWIG_TYPECHECK_POINTER,noblock=1) +%typemap(typecheck,precedence=SWIG_TYPECHECK_POINTER,noblock=1) TYPE CONST, TYPE CONST &, TYPE CONST *, diff --git a/Lib/scilab/boost_shared_ptr.i b/Lib/scilab/boost_shared_ptr.i index b90422a66..d595b4861 100644 --- a/Lib/scilab/boost_shared_ptr.i +++ b/Lib/scilab/boost_shared_ptr.i @@ -14,7 +14,7 @@ %naturalvar SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >; // destructor wrapper customisation -%feature("unref") TYPE +%feature("unref") TYPE //"if (debug_shared) { cout << \"deleting use_count: \" << (*smartarg1).use_count() << \" [\" << (boost::get_deleter(*smartarg1) ? std::string(\"CANNOT BE DETERMINED SAFELY\") : ( (*smartarg1).get() ? (*smartarg1)->getValue() : std::string(\"NULL PTR\") )) << \"]\" << endl << flush; }\n" "(void)arg1; delete smartarg1;" @@ -25,7 +25,7 @@ int newmem = 0; res = SWIG_ConvertPtrAndOwn($input, &argp, $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), %convertptr_flags, &newmem); if (!SWIG_IsOK(res)) { - %argument_fail(res, "$type", $symname, $argnum); + %argument_fail(res, "$type", $symname, $argnum); } if (!argp) { %argument_nullref("$type", $symname, $argnum); @@ -64,7 +64,7 @@ int newmem = 0; res = SWIG_ConvertPtrAndOwn($input, &argp, $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), SHARED_PTR_DISOWN | %convertptr_flags, &newmem); if (!SWIG_IsOK(res)) { - %argument_fail(res, "$type", $symname, $argnum); + %argument_fail(res, "$type", $symname, $argnum); } if (newmem & SWIG_CAST_NEW_MEMORY) { tempshared = *%reinterpret_cast(argp, SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *); @@ -109,7 +109,7 @@ int newmem = 0; res = SWIG_ConvertPtrAndOwn($input, &argp, $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), %convertptr_flags, &newmem); if (!SWIG_IsOK(res)) { - %argument_fail(res, "$type", $symname, $argnum); + %argument_fail(res, "$type", $symname, $argnum); } if (!argp) { %argument_nullref("$type", $symname, $argnum); } if (newmem & SWIG_CAST_NEW_MEMORY) { @@ -155,7 +155,7 @@ int newmem = 0; res = SWIG_ConvertPtrAndOwn($input, &argp, $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), SHARED_PTR_DISOWN | %convertptr_flags, &newmem); if (!SWIG_IsOK(res)) { - %argument_fail(res, "$type", $symname, $argnum); + %argument_fail(res, "$type", $symname, $argnum); } if (newmem & SWIG_CAST_NEW_MEMORY) { tempshared = *%reinterpret_cast(argp, SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *); @@ -183,7 +183,7 @@ int newmem = 0; res = SWIG_ConvertPtrAndOwn($input, &argp, $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), %convertptr_flags, &newmem); if (!SWIG_IsOK(res)) { - %argument_fail(res, "$type", $symname, $argnum); + %argument_fail(res, "$type", $symname, $argnum); } if (argp) $1 = *(%reinterpret_cast(argp, $<ype)); if (newmem & SWIG_CAST_NEW_MEMORY) delete %reinterpret_cast(argp, $<ype); @@ -213,7 +213,7 @@ int newmem = 0; res = SWIG_ConvertPtrAndOwn($input, &argp, $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), %convertptr_flags, &newmem); if (!SWIG_IsOK(res)) { - %argument_fail(res, "$type", $symname, $argnum); + %argument_fail(res, "$type", $symname, $argnum); } if (newmem & SWIG_CAST_NEW_MEMORY) { if (argp) tempshared = *%reinterpret_cast(argp, $ltype); @@ -240,7 +240,7 @@ int newmem = 0; res = SWIG_ConvertPtrAndOwn($input, &argp, $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), %convertptr_flags, &newmem); if (!SWIG_IsOK(res)) { - %argument_fail(res, "$type", $symname, $argnum); + %argument_fail(res, "$type", $symname, $argnum); } if (newmem & SWIG_CAST_NEW_MEMORY) { if (argp) tempshared = *%reinterpret_cast(argp, $ltype); @@ -268,7 +268,7 @@ int newmem = 0; res = SWIG_ConvertPtrAndOwn($input, &argp, $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), %convertptr_flags, &newmem); if (!SWIG_IsOK(res)) { - %argument_fail(res, "$type", $symname, $argnum); + %argument_fail(res, "$type", $symname, $argnum); } if (argp) tempshared = *%reinterpret_cast(argp, $*ltype); if (newmem & SWIG_CAST_NEW_MEMORY) delete %reinterpret_cast(argp, $*ltype); @@ -288,9 +288,9 @@ %} // Typecheck typemaps -// Note: SWIG_ConvertPtr with void ** parameter set to 0 instead of using SWIG_ConvertPtrAndOwn, so that the casting +// Note: SWIG_ConvertPtr with void ** parameter set to 0 instead of using SWIG_ConvertPtrAndOwn, so that the casting // function is not called thereby avoiding a possible smart pointer copy constructor call when casting up the inheritance chain. -%typemap(typecheck,precedence=SWIG_TYPECHECK_POINTER,noblock=1) +%typemap(typecheck,precedence=SWIG_TYPECHECK_POINTER,noblock=1) TYPE CONST, TYPE CONST &, TYPE CONST *, From 6672338cc0d74c68c6738c53ba7de06a83b1efaa Mon Sep 17 00:00:00 2001 From: Takashi Tamura Date: Fri, 21 Apr 2017 22:44:38 +0900 Subject: [PATCH 072/455] [ruby] delete unnecessary changes. --- Lib/ruby/boost_shared_ptr.i | 17 +---------------- 1 file changed, 1 insertion(+), 16 deletions(-) diff --git a/Lib/ruby/boost_shared_ptr.i b/Lib/ruby/boost_shared_ptr.i index 0350f41d9..02e2f999f 100644 --- a/Lib/ruby/boost_shared_ptr.i +++ b/Lib/ruby/boost_shared_ptr.i @@ -24,9 +24,7 @@ // Typemap customisations... -// // plain value -// %typemap(in) CONST TYPE (void *argp, int res = 0) { swig_ruby_owntype newmem = {0, 0}; res = SWIG_ConvertPtrAndOwn($input, &argp, $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), %convertptr_flags, &newmem); @@ -82,10 +80,8 @@ $input = SWIG_NewPointerObj(%as_voidptr(smartresult), $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), SWIG_POINTER_OWN | %newpointer_flags); } -// // plain pointer // Note: $disown not implemented by default as it will lead to a memory leak of the shared_ptr instance -// %typemap(in) CONST TYPE * (void *argp = 0, int res = 0, SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > tempshared, SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *smartarg = 0) { swig_ruby_owntype newmem = {0, 0}; res = SWIG_ConvertPtrAndOwn($input, &argp, $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), SHARED_PTR_DISOWN | %convertptr_flags, &newmem); @@ -101,6 +97,7 @@ $1 = %const_cast((smartarg ? smartarg->get() : 0), $1_ltype); } } + %typemap(out, fragment="SWIG_null_deleter_python") CONST TYPE * { SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *smartresult = $1 ? new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >($1 SWIG_NO_NULL_DELETER_$owner) : 0; %set_output(SWIG_NewPointerObj(%as_voidptr(smartresult), $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), $owner | SWIG_POINTER_OWN)); @@ -136,9 +133,7 @@ #error "directorout typemap for plain pointer not implemented" %} -// // plain reference -// %typemap(in) CONST TYPE & (void *argp = 0, int res = 0, SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > tempshared) { swig_ruby_owntype newmem = {0, 0}; res = SWIG_ConvertPtrAndOwn($input, &argp, $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), %convertptr_flags, &newmem); @@ -190,10 +185,8 @@ #error "directorout typemap for plain reference not implemented" %} -// // plain pointer by reference // Note: $disown not implemented by default as it will lead to a memory leak of the shared_ptr instance -// %typemap(in) TYPE *CONST& (void *argp = 0, int res = 0, $*1_ltype temp = 0, SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > tempshared) { swig_ruby_owntype newmem = {0, 0}; res = SWIG_ConvertPtrAndOwn($input, &argp, $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), SHARED_PTR_DISOWN | %convertptr_flags, &newmem); @@ -228,9 +221,7 @@ #error "directorout typemap for plain pointer by reference not implemented" %} -// // shared_ptr by value -// %typemap(in) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > (void *argp, int res = 0) { swig_ruby_owntype newmem = {0, 0}; res = SWIG_ConvertPtrAndOwn($input, &argp, $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), %convertptr_flags, &newmem); @@ -280,9 +271,7 @@ } } -// // shared_ptr by reference -// %typemap(in) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > & (void *argp, int res = 0, $*1_ltype tempshared) { swig_ruby_owntype newmem = {0, 0}; res = SWIG_ConvertPtrAndOwn($input, &argp, $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), %convertptr_flags, &newmem); @@ -317,9 +306,7 @@ } } -// // shared_ptr by pointer -// %typemap(in) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > * (void *argp, int res = 0, $*1_ltype tempshared) { swig_ruby_owntype newmem = {0, 0}; res = SWIG_ConvertPtrAndOwn($input, &argp, $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), %convertptr_flags, &newmem); @@ -355,9 +342,7 @@ } } -// // shared_ptr by pointer reference -// %typemap(in) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *& (void *argp, int res = 0, SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > tempshared, $*1_ltype temp = 0) { swig_ruby_owntype newmem = {0, 0}; res = SWIG_ConvertPtrAndOwn($input, &argp, $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), %convertptr_flags, &newmem); From 31459d0cc070c294e6f7465ef68b262c634bbdbd Mon Sep 17 00:00:00 2001 From: Takashi Tamura Date: Fri, 21 Apr 2017 22:56:13 +0900 Subject: [PATCH 073/455] [ruby] use boost/shared_ptr and boost_shared_ptr.i. not use auto. --- .../test-suite/cpp11_shared_ptr_director.i | 32 +++++++++---------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/Examples/test-suite/cpp11_shared_ptr_director.i b/Examples/test-suite/cpp11_shared_ptr_director.i index 0f0554134..0a8a2494f 100644 --- a/Examples/test-suite/cpp11_shared_ptr_director.i +++ b/Examples/test-suite/cpp11_shared_ptr_director.i @@ -1,10 +1,10 @@ %module(directors="1") "cpp11_shared_ptr_director" %{ -#include +#include %} -%include "std_shared_ptr.i"; +%include "boost_shared_ptr.i"; %shared_ptr(C); %feature("director") Base; @@ -18,18 +18,18 @@ struct C { struct Base { Base() {}; - virtual std::shared_ptr ret_c_shared_ptr() = 0; + virtual boost::shared_ptr ret_c_shared_ptr() = 0; virtual C ret_c_by_value() = 0; virtual int take_c_by_value(C c) = 0; - virtual int take_c_shared_ptr_by_value(std::shared_ptr c) = 0; - virtual int take_c_shared_ptr_by_ref(std::shared_ptr& c) = 0; - virtual int take_c_shared_ptr_by_pointer(std::shared_ptr* c) = 0; - virtual int take_c_shared_ptr_by_pointer_ref(std::shared_ptr*const&c) = 0; + virtual int take_c_shared_ptr_by_value(boost::shared_ptr c) = 0; + virtual int take_c_shared_ptr_by_ref(boost::shared_ptr& c) = 0; + virtual int take_c_shared_ptr_by_pointer(boost::shared_ptr* c) = 0; + virtual int take_c_shared_ptr_by_pointer_ref(boost::shared_ptr*const&c) = 0; virtual ~Base() {} }; int call_ret_c_shared_ptr(Base* b) { - std::shared_ptr ptr = b->ret_c_shared_ptr(); + boost::shared_ptr ptr = b->ret_c_shared_ptr(); if (ptr) { return ptr->get_m(); } else { @@ -48,42 +48,42 @@ int call_take_c_by_value(Base* b) { } int call_take_c_shared_ptr_by_value(Base* b) { - std::shared_ptr ptr(new C(6)); + boost::shared_ptr ptr(new C(6)); return b->take_c_shared_ptr_by_value(ptr); } int call_take_c_shared_ptr_by_value_with_null(Base* b) { - std::shared_ptr ptr; + boost::shared_ptr ptr; return b->take_c_shared_ptr_by_value(ptr); } int call_take_c_shared_ptr_by_ref(Base* b) { - std::shared_ptr ptr(new C(7)); + boost::shared_ptr ptr(new C(7)); return b->take_c_shared_ptr_by_ref(ptr); } int call_take_c_shared_ptr_by_ref_with_null(Base* b) { - std::shared_ptr ptr; + boost::shared_ptr ptr; return b->take_c_shared_ptr_by_ref(ptr); } int call_take_c_shared_ptr_by_pointer(Base* b) { - std::shared_ptr ptr(new C(8)); + boost::shared_ptr ptr(new C(8)); return b->take_c_shared_ptr_by_pointer(&ptr); } int call_take_c_shared_ptr_by_pointer_with_null(Base* b) { - std::shared_ptr ptr; + boost::shared_ptr ptr; return b->take_c_shared_ptr_by_pointer(&ptr); } int call_take_c_shared_ptr_by_pointer_ref(Base* b) { - auto ptr = new std::shared_ptr(new C(9)); + boost::shared_ptr *ptr = new boost::shared_ptr(new C(9)); return b->take_c_shared_ptr_by_pointer_ref(ptr); } int call_take_c_shared_ptr_by_pointer_ref_with_null(Base* b) { - auto ptr = new std::shared_ptr(); + boost::shared_ptr *ptr = new boost::shared_ptr(); return b->take_c_shared_ptr_by_pointer_ref(ptr); } From 093cf8d60f0622f66bfbddca75167d9160801502 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Fri, 21 Apr 2017 19:28:08 +0100 Subject: [PATCH 074/455] Rename shared_ptr testcase --- CHANGES.current | 3 +++ ...1_shared_ptr_director.i => li_boost_shared_ptr_director.i} | 2 +- Examples/test-suite/ruby/Makefile.in | 2 +- ...irector_runme.rb => li_boost_shared_ptr_director_runme.rb} | 4 ++-- 4 files changed, 7 insertions(+), 4 deletions(-) rename Examples/test-suite/{cpp11_shared_ptr_director.i => li_boost_shared_ptr_director.i} (97%) rename Examples/test-suite/ruby/{cpp11_shared_ptr_director_runme.rb => li_boost_shared_ptr_director_runme.rb} (94%) diff --git a/CHANGES.current b/CHANGES.current index 9ea6662cc..e859072bd 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 3.0.13 (in progress) ============================ +2017-04-21: tamuratak + [Ruby] #964 - Add shared_ptr director typemaps. + 2017-04-20: tamuratak [Ruby] #930, #937 - Fix containers of std::shared_ptr. Upcasting, const types (eg vector>) and NULL/nullptr support added. diff --git a/Examples/test-suite/cpp11_shared_ptr_director.i b/Examples/test-suite/li_boost_shared_ptr_director.i similarity index 97% rename from Examples/test-suite/cpp11_shared_ptr_director.i rename to Examples/test-suite/li_boost_shared_ptr_director.i index 0a8a2494f..4acfa1a5d 100644 --- a/Examples/test-suite/cpp11_shared_ptr_director.i +++ b/Examples/test-suite/li_boost_shared_ptr_director.i @@ -1,4 +1,4 @@ -%module(directors="1") "cpp11_shared_ptr_director" +%module(directors="1") "li_boost_shared_ptr_director" %{ #include diff --git a/Examples/test-suite/ruby/Makefile.in b/Examples/test-suite/ruby/Makefile.in index 33f42a7fc..cc2ba1ed2 100644 --- a/Examples/test-suite/ruby/Makefile.in +++ b/Examples/test-suite/ruby/Makefile.in @@ -11,6 +11,7 @@ top_srcdir = @top_srcdir@ top_builddir = @top_builddir@ CPP_TEST_CASES = \ + li_boost_shared_ptr_director \ li_cstring \ li_factory \ li_std_functors \ @@ -34,7 +35,6 @@ CPP11_TEST_CASES = \ cpp11_hash_tables \ cpp11_shared_ptr_upcast \ cpp11_shared_ptr_const \ - cpp11_shared_ptr_director C_TEST_CASES += \ li_cstring \ diff --git a/Examples/test-suite/ruby/cpp11_shared_ptr_director_runme.rb b/Examples/test-suite/ruby/li_boost_shared_ptr_director_runme.rb similarity index 94% rename from Examples/test-suite/ruby/cpp11_shared_ptr_director_runme.rb rename to Examples/test-suite/ruby/li_boost_shared_ptr_director_runme.rb index 51b338aef..0f7f14b46 100644 --- a/Examples/test-suite/ruby/cpp11_shared_ptr_director_runme.rb +++ b/Examples/test-suite/ruby/li_boost_shared_ptr_director_runme.rb @@ -1,6 +1,6 @@ -require 'cpp11_shared_ptr_director' +require 'li_boost_shared_ptr_director' -include Cpp11_shared_ptr_director +include Li_boost_shared_ptr_director class Derived < Base From 28f7d61986e6afb2a5d52fec6a8b79cee6237a25 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Fri, 21 Apr 2017 19:36:09 +0100 Subject: [PATCH 075/455] Bump version to 4.0.0 --- ANNOUNCE | 8 ++++---- CHANGES.current | 4 ++-- Doc/Manual/Sections.html | 2 +- README | 2 +- configure.ac | 2 +- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/ANNOUNCE b/ANNOUNCE index e0bd4d0f9..109cf9216 100644 --- a/ANNOUNCE +++ b/ANNOUNCE @@ -1,8 +1,8 @@ -*** ANNOUNCE: SWIG 3.0.13 (in progress) *** +*** ANNOUNCE: SWIG 4.0.0 (in progress) *** http://www.swig.org -We're pleased to announce SWIG-3.0.13, the latest SWIG release. +We're pleased to announce SWIG-4.0.0, the latest SWIG release. What is SWIG? ============= @@ -27,11 +27,11 @@ Availability ============ The release is available for download on Sourceforge at - http://prdownloads.sourceforge.net/swig/swig-3.0.13.tar.gz + http://prdownloads.sourceforge.net/swig/swig-4.0.0.tar.gz A Windows version is also available at - http://prdownloads.sourceforge.net/swig/swigwin-3.0.13.zip + http://prdownloads.sourceforge.net/swig/swigwin-4.0.0.zip Please report problems with this release to the swig-devel mailing list, details at http://www.swig.org/mail.html. diff --git a/CHANGES.current b/CHANGES.current index 46b32f24a..f01a29b96 100644 --- a/CHANGES.current +++ b/CHANGES.current @@ -4,8 +4,8 @@ See the RELEASENOTES file for a summary of changes in each release. Issue # numbers mentioned below can be found on Github. For more details, add the issue number to the end of the URL: https://github.com/swig/swig/issues/ -Version 3.0.13 (in progress) -============================ +Version 4.0.0 (in progress) +=========================== 2017-04-21: tamuratak [Ruby] #964 - Add shared_ptr director typemaps. diff --git a/Doc/Manual/Sections.html b/Doc/Manual/Sections.html index bdf590ac9..739170745 100644 --- a/Doc/Manual/Sections.html +++ b/Doc/Manual/Sections.html @@ -8,7 +8,7 @@

SWIG-3.0 Documentation

-Last update : SWIG-3.0.13 (in progress) +Last update : SWIG-4.0.0 (in progress)

Sections

diff --git a/README b/README index 5510e0ec3..649602048 100644 --- a/README +++ b/README @@ -1,6 +1,6 @@ SWIG (Simplified Wrapper and Interface Generator) -Version: 3.0.13 (in progress) +Version: 4.0.0 (in progress) Tagline: SWIG is a compiler that integrates C and C++ with languages including Perl, Python, Tcl, Ruby, PHP, Java, C#, D, Go, Lua, diff --git a/configure.ac b/configure.ac index 4d9355cd0..7234a1fd4 100644 --- a/configure.ac +++ b/configure.ac @@ -2,7 +2,7 @@ dnl Process this file with autoconf to produce a configure script. dnl The macros which aren't shipped with the autotools are stored in the dnl Tools/config directory in .m4 files. -AC_INIT([swig],[3.0.13],[http://www.swig.org]) +AC_INIT([swig],[4.0.0],[http://www.swig.org]) dnl NB: When this requirement is increased to 2.60 or later, AC_PROG_SED dnl definition below can be removed From 43c3ca37678ed421f13d93a0394c32e9ce741576 Mon Sep 17 00:00:00 2001 From: Takashi Tamura Date: Sat, 18 Feb 2017 21:30:17 +0900 Subject: [PATCH 076/455] [ruby] clarify dependency of fragments for unordered_set containers. --- Lib/ruby/std_unordered_multiset.i | 2 +- Lib/ruby/std_unordered_set.i | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Lib/ruby/std_unordered_multiset.i b/Lib/ruby/std_unordered_multiset.i index 29fa73a98..181aa212d 100644 --- a/Lib/ruby/std_unordered_multiset.i +++ b/Lib/ruby/std_unordered_multiset.i @@ -4,7 +4,7 @@ %include -%fragment("StdUnorderedMultisetTraits","header",fragment="StdSequenceTraits") +%fragment("StdUnorderedMultisetTraits","header",fragment="StdUnorderedSetTraits") %{ namespace swig { template diff --git a/Lib/ruby/std_unordered_set.i b/Lib/ruby/std_unordered_set.i index 5279bbed5..3d4494351 100644 --- a/Lib/ruby/std_unordered_set.i +++ b/Lib/ruby/std_unordered_set.i @@ -4,7 +4,7 @@ %include -%fragment("StdUnorderedSetTraits","header",fragment="",fragment="StdSequenceTraits") +%fragment("StdUnorderedSetTraits","header",fragment="",fragment="StdSetTraits") %{ namespace swig { template From 70740c51d0323c874e898f1cf438cacb0ab496ab Mon Sep 17 00:00:00 2001 From: Takashi Tamura Date: Sat, 22 Apr 2017 16:32:52 +0900 Subject: [PATCH 077/455] [ruby] add simple tests for std unordered containers. --- Examples/test-suite/cpp11_std_unordered_map.i | 5 +++++ Examples/test-suite/cpp11_std_unordered_multimap.i | 7 +++++++ Examples/test-suite/cpp11_std_unordered_multiset.i | 5 +++++ Examples/test-suite/cpp11_std_unordered_set.i | 5 +++++ Examples/test-suite/ruby/Makefile.in | 4 ++++ 5 files changed, 26 insertions(+) create mode 100644 Examples/test-suite/cpp11_std_unordered_map.i create mode 100644 Examples/test-suite/cpp11_std_unordered_multimap.i create mode 100644 Examples/test-suite/cpp11_std_unordered_multiset.i create mode 100644 Examples/test-suite/cpp11_std_unordered_set.i diff --git a/Examples/test-suite/cpp11_std_unordered_map.i b/Examples/test-suite/cpp11_std_unordered_map.i new file mode 100644 index 000000000..56c4a5248 --- /dev/null +++ b/Examples/test-suite/cpp11_std_unordered_map.i @@ -0,0 +1,5 @@ +%module cpp11_std_unordered_map + +%include + +%template(UnorderedMapIntInt) std::unordered_map; diff --git a/Examples/test-suite/cpp11_std_unordered_multimap.i b/Examples/test-suite/cpp11_std_unordered_multimap.i new file mode 100644 index 000000000..8556b26b5 --- /dev/null +++ b/Examples/test-suite/cpp11_std_unordered_multimap.i @@ -0,0 +1,7 @@ +%module cpp11_std_unordered_multimap + +%include +%include + +%template(PairIntInt) std::pair; +%template(UnorderedMultiMapIntInt) std::unordered_multimap; diff --git a/Examples/test-suite/cpp11_std_unordered_multiset.i b/Examples/test-suite/cpp11_std_unordered_multiset.i new file mode 100644 index 000000000..c9907425e --- /dev/null +++ b/Examples/test-suite/cpp11_std_unordered_multiset.i @@ -0,0 +1,5 @@ +%module cpp11_std_unordered_multiset + +%include + +%template(UnorderedMultiSetInt) std::unordered_multiset; diff --git a/Examples/test-suite/cpp11_std_unordered_set.i b/Examples/test-suite/cpp11_std_unordered_set.i new file mode 100644 index 000000000..f5652cb88 --- /dev/null +++ b/Examples/test-suite/cpp11_std_unordered_set.i @@ -0,0 +1,5 @@ +%module cpp11_std_unordered_set + +%include + +%template(UnorderedSetInt) std::unordered_set; diff --git a/Examples/test-suite/ruby/Makefile.in b/Examples/test-suite/ruby/Makefile.in index cc2ba1ed2..0a0e82fc0 100644 --- a/Examples/test-suite/ruby/Makefile.in +++ b/Examples/test-suite/ruby/Makefile.in @@ -35,6 +35,10 @@ CPP11_TEST_CASES = \ cpp11_hash_tables \ cpp11_shared_ptr_upcast \ cpp11_shared_ptr_const \ + cpp11_std_unordered_map \ + cpp11_std_unordered_multimap \ + cpp11_std_unordered_set \ + cpp11_std_unordered_multiset C_TEST_CASES += \ li_cstring \ From db11e82896753bc1c3c8ba78c6a402587c5f6921 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Mon, 24 Apr 2017 20:45:01 +0100 Subject: [PATCH 078/455] Makefile cosmetics --- Examples/test-suite/ruby/Makefile.in | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Examples/test-suite/ruby/Makefile.in b/Examples/test-suite/ruby/Makefile.in index f04e3a425..a34e55f71 100644 --- a/Examples/test-suite/ruby/Makefile.in +++ b/Examples/test-suite/ruby/Makefile.in @@ -27,9 +27,9 @@ CPP_TEST_CASES = \ ruby_naming \ ruby_track_objects \ ruby_track_objects_directors \ - std_containers -# ruby_li_std_speed -# stl_new + std_containers \ +# ruby_li_std_speed \ +# stl_new \ CPP11_TEST_CASES = \ cpp11_hash_tables \ From 7b9d94db2e0db0b3eb7c30edd17fea5bb1926c76 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Tue, 25 Apr 2017 07:29:54 +0100 Subject: [PATCH 079/455] Fix Lua warning for missing (SWIGTYPE CLASS::*) typemaps for C wrappers --- Lib/lua/luatypemaps.swg | 2 -- 1 file changed, 2 deletions(-) diff --git a/Lib/lua/luatypemaps.swg b/Lib/lua/luatypemaps.swg index c2dfcae41..4c68d1d1d 100644 --- a/Lib/lua/luatypemaps.swg +++ b/Lib/lua/luatypemaps.swg @@ -235,7 +235,6 @@ $1=($1_ltype)&temp;%} // so the standard wrapping cannot be done // nor can you cast a member function pointer to a void* (obviously) // therefore a special wrapping functions SWIG_ConvertMember() & SWIG_NewMemberObj() were written -#ifdef __cplusplus %typemap(in,checkfn="lua_isuserdata") SWIGTYPE (CLASS::*) %{ if (!SWIG_IsOK(SWIG_ConvertMember(L,$input,(void*)(&$1),sizeof($type),$descriptor))) @@ -246,7 +245,6 @@ $1=($1_ltype)&temp;%} %{ SWIG_NewMemberObj(L,(void*)(&$1),sizeof($type),$descriptor); SWIG_arg++; %} -#endif // void (must be empty without the SWIG_arg++) From 34dee11d1d70e614b95eb19463a36d627d1b5c00 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Tue, 25 Apr 2017 07:34:54 +0100 Subject: [PATCH 080/455] Add changes file entry for Lua warning fix --- CHANGES.current | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGES.current b/CHANGES.current index f01a29b96..5f1a67771 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.0.0 (in progress) =========================== +2017-04-25: jleveque + [Lua] #959 - Fix Visual Studio C4244 conversion warnings in Lua wrappers. + 2017-04-21: tamuratak [Ruby] #964 - Add shared_ptr director typemaps. From 7ad8ac92c0d6b9034303dedd1c2d0319dbd549d8 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Tue, 25 Apr 2017 18:06:57 +0100 Subject: [PATCH 081/455] Test c++11 unordered containers in Python --- Examples/test-suite/python/Makefile.in | 7 ++- .../python/cpp11_hash_tables_runme.py | 51 +++++++++++++++++++ 2 files changed, 56 insertions(+), 2 deletions(-) create mode 100644 Examples/test-suite/python/cpp11_hash_tables_runme.py diff --git a/Examples/test-suite/python/Makefile.in b/Examples/test-suite/python/Makefile.in index 6d073a101..b6da00aa5 100644 --- a/Examples/test-suite/python/Makefile.in +++ b/Examples/test-suite/python/Makefile.in @@ -73,18 +73,21 @@ CPP_TEST_CASES += \ simutry \ std_containers \ swigobject \ - template_matrix + template_matrix \ # li_std_carray # director_profile # python_pybuf +CPP11_TEST_CASES = \ + cpp11_hash_tables \ + C_TEST_CASES += \ file_test \ li_cstring \ li_cwstring \ python_nondynamic \ - python_varargs_typemap + python_varargs_typemap \ # # This test only works with modern C compilers diff --git a/Examples/test-suite/python/cpp11_hash_tables_runme.py b/Examples/test-suite/python/cpp11_hash_tables_runme.py new file mode 100644 index 000000000..39388fd20 --- /dev/null +++ b/Examples/test-suite/python/cpp11_hash_tables_runme.py @@ -0,0 +1,51 @@ +import cpp11_hash_tables + +def swig_assert_equal(a, b): + if a != b: + raise RuntimeError(str(a) + " != " + str(b)) + +for x in [cpp11_hash_tables.MapIntInt({1:7}), + cpp11_hash_tables.MultiMapIntInt({1:7}), + cpp11_hash_tables.UnorderedMapIntInt({1:7}), + cpp11_hash_tables.UnorderedMultiMapIntInt({1:7})]: + + swig_assert_equal([(k, v) for k, v in x.iteritems()], [(1, 7)]) + + swig_assert_equal(x[1], 7) + swig_assert_equal(2 in x, False) + x[2] = 9 + swig_assert_equal(x[2], 9) + del x[2] + swig_assert_equal(2 in x, False) + swig_assert_equal(x.empty(), False) + del x[1] + swig_assert_equal(x.empty(), True) + swig_assert_equal(1 in x, False) + +for x in [cpp11_hash_tables.MultiMapIntInt({1:7}), + cpp11_hash_tables.UnorderedMultiMapIntInt({1:7})]: + x[1] = 9 + swig_assert_equal(sorted([v for k, v in x.iteritems()]), [7, 9]) +# Is this broken?... +# swig_assert_equal(sorted([v for v in x[1]]), [7, 9]) + +for x in [cpp11_hash_tables.SetInt([1]), + cpp11_hash_tables.MultiSetInt([1]), + cpp11_hash_tables.UnorderedSetInt([1]), + cpp11_hash_tables.UnorderedMultiSetInt([1])]: + + swig_assert_equal([e for e in x], [1]) + + swig_assert_equal(1 in x, True) + swig_assert_equal(2 in x, False) + x.append(2) + swig_assert_equal(2 in x, True) + x.erase(2) + swig_assert_equal(x.empty(), False) + x.erase(1) + swig_assert_equal(x.empty(), True) + +for x in [cpp11_hash_tables.MultiSetInt([1]), + cpp11_hash_tables.UnorderedMultiSetInt([1])]: + x.append(1) + swig_assert_equal(x.count(1), 2) From 624ec3e1b7dd8908b37ee86bce6f60423c915bc5 Mon Sep 17 00:00:00 2001 From: Philip Herron Date: Tue, 25 Apr 2017 07:09:18 +0100 Subject: [PATCH 082/455] Fix bug with comments inline in macros - commit fixes #974 --- Source/Preprocessor/cpp.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/Source/Preprocessor/cpp.c b/Source/Preprocessor/cpp.c index 12d27c316..491eb8a96 100644 --- a/Source/Preprocessor/cpp.c +++ b/Source/Preprocessor/cpp.c @@ -607,6 +607,23 @@ static List *find_args(String *s, int ismacro, String *macro_name) { skip_tochar(s, '\'', str); c = Getc(s); continue; + } else if (c == '/') { + /* Ensure comments are ignored by eating up the characters */ + c = Getc(s); + if (c == '*') { + while ((c = Getc(s)) != EOF) { + if (c == '*') { + c = Getc(s); + if (c == '/' || c == EOF) + break; + } + } + c = Getc(s); + continue; + } + /* ensure char is available in the stream as this was not a comment*/ + Ungetc(c, s); + c = '/'; } if ((c == ',') && (level == 0)) break; From 956495dd47d3f1eec5da67befbf76b3ec79b5489 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Thu, 27 Apr 2017 19:45:19 +0100 Subject: [PATCH 083/455] Add testcase for macros with commas in comment --- CHANGES.current | 3 +++ Examples/test-suite/preproc.i | 17 +++++++++++++++++ Examples/test-suite/python/preproc_runme.py | 3 +++ 3 files changed, 23 insertions(+) diff --git a/CHANGES.current b/CHANGES.current index f01a29b96..1513eb33a 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.0.0 (in progress) =========================== +2017-04-27: redbrain + Issue #974, Patch #976 - Fix preprocessor handling of macros with commas in a comment. + 2017-04-21: tamuratak [Ruby] #964 - Add shared_ptr director typemaps. diff --git a/Examples/test-suite/preproc.i b/Examples/test-suite/preproc.i index f236bfdff..8ed8c1a09 100644 --- a/Examples/test-suite/preproc.i +++ b/Examples/test-suite/preproc.i @@ -370,3 +370,20 @@ int methodX(int x); int methodX(int x) { return x+100; } %} +// Comma in macro - Github issue #974 +%inline %{ +#define __attribute__(x) +#define TCX_PACKED(d) d __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; +%} + diff --git a/Examples/test-suite/python/preproc_runme.py b/Examples/test-suite/python/preproc_runme.py index 99a6d0307..071362bc3 100644 --- a/Examples/test-suite/python/preproc_runme.py +++ b/Examples/test-suite/python/preproc_runme.py @@ -14,3 +14,6 @@ if 2 * preproc.one != preproc.two: if preproc.methodX(99) != 199: raise RuntimeError + +t1 = preproc.tcxMessageTest() +t2 = preproc.tcxMessageBug() From b4efa7b16e4a8cdb28a28ccecb9e77179673665e Mon Sep 17 00:00:00 2001 From: Christophe Duvernois Date: Thu, 27 Apr 2017 23:35:05 +0200 Subject: [PATCH 084/455] #526 : propagate c++11 noexcept to director classes test case --- Examples/test-suite/common.mk | 1 + Examples/test-suite/cpp11_directors.i | 20 ++++++++++++++++++++ 2 files changed, 21 insertions(+) create mode 100644 Examples/test-suite/cpp11_directors.i diff --git a/Examples/test-suite/common.mk b/Examples/test-suite/common.mk index f9fe04383..18c00e750 100644 --- a/Examples/test-suite/common.mk +++ b/Examples/test-suite/common.mk @@ -543,6 +543,7 @@ CPP11_TEST_CASES += \ cpp11_default_delete \ cpp11_delegating_constructors \ cpp11_director_enums \ + cpp11_directors \ cpp11_explicit_conversion_operators \ cpp11_final_override \ cpp11_function_objects \ diff --git a/Examples/test-suite/cpp11_directors.i b/Examples/test-suite/cpp11_directors.i new file mode 100644 index 000000000..4462c1d52 --- /dev/null +++ b/Examples/test-suite/cpp11_directors.i @@ -0,0 +1,20 @@ +%module(directors="1") cpp11_directors +%feature("director"); + +%{ + +class Foo { + public: + virtual ~Foo() noexcept {} + virtual int ping() noexcept = 0; + virtual int pong() noexcept = 0; +}; + +%} + +class Foo { + public: + virtual ~Foo() noexcept {} + virtual int ping() noexcept = 0; + virtual int pong() noexcept = 0; +}; \ No newline at end of file From 4777a0ad3c28a11ce11141aa8ff83457d5e0caf8 Mon Sep 17 00:00:00 2001 From: Christophe Duvernois Date: Tue, 25 Apr 2017 15:53:25 +0200 Subject: [PATCH 085/455] #526 : propagate c++11 noexcept to director classes --- Source/Modules/csharp.cxx | 9 ++++++++- Source/Modules/d.cxx | 9 ++++++++- Source/Modules/java.cxx | 9 ++++++++- Source/Modules/octave.cxx | 4 ++++ Source/Modules/perl5.cxx | 9 ++++++++- Source/Modules/php.cxx | 4 ++++ Source/Modules/python.cxx | 5 ++++- Source/Modules/ruby.cxx | 4 ++++ 8 files changed, 48 insertions(+), 5 deletions(-) diff --git a/Source/Modules/csharp.cxx b/Source/Modules/csharp.cxx index 423c5a451..154fadac5 100644 --- a/Source/Modules/csharp.cxx +++ b/Source/Modules/csharp.cxx @@ -4102,6 +4102,10 @@ public: Delete(target); // Add any exception specifications to the methods in the director class + if (Getattr(n, "noexcept")) { + Append(w->def, " noexcept"); + Append(declaration, " noexcept"); + } ParmList *throw_parm_list = NULL; if ((throw_parm_list = Getattr(n, "throws")) || Getattr(n, "throw")) { int gencomma = 0; @@ -4419,7 +4423,10 @@ public: String *dirclassname = directorClassName(current_class); Wrapper *w = NewWrapper(); - if (Getattr(n, "throw")) { + if (Getattr(n, "noexcept")) { + Printf(f_directors_h, " virtual ~%s() noexcept;\n", dirclassname); + Printf(w->def, "%s::~%s() noexcept {\n", dirclassname, dirclassname); + } else if (Getattr(n, "throw")) { Printf(f_directors_h, " virtual ~%s() throw ();\n", dirclassname); Printf(w->def, "%s::~%s() throw () {\n", dirclassname, dirclassname); } else { diff --git a/Source/Modules/d.cxx b/Source/Modules/d.cxx index de7afdab1..05ca6c636 100644 --- a/Source/Modules/d.cxx +++ b/Source/Modules/d.cxx @@ -2217,6 +2217,10 @@ public: Delete(target); // Add any exception specifications to the methods in the director class + if (Getattr(n, "noexcept")) { + Append(w->def, " noexcept"); + Append(declaration, " noexcept"); + } ParmList *throw_parm_list = NULL; if ((throw_parm_list = Getattr(n, "throws")) || Getattr(n, "throw")) { int gencomma = 0; @@ -2483,7 +2487,10 @@ public: String *dirclassname = directorClassName(current_class); Wrapper *w = NewWrapper(); - if (Getattr(n, "throw")) { + if (Getattr(n, "noexcept")) { + Printf(f_directors_h, " virtual ~%s() noexcept;\n", dirclassname); + Printf(w->def, "%s::~%s() noexcept {\n", dirclassname, dirclassname); + } else if (Getattr(n, "throw")) { Printf(f_directors_h, " virtual ~%s() throw ();\n", dirclassname); Printf(w->def, "%s::~%s() throw () {\n", dirclassname, dirclassname); } else { diff --git a/Source/Modules/java.cxx b/Source/Modules/java.cxx index 946962447..b380565b5 100644 --- a/Source/Modules/java.cxx +++ b/Source/Modules/java.cxx @@ -4293,6 +4293,10 @@ public: } } + if (Getattr(n, "noexcept")) { + Append(w->def, " noexcept"); + Append(declaration, " noexcept"); + } if ((throw_parm_list = Getattr(n, "throws")) || Getattr(n, "throw")) { int gencomma = 0; @@ -4671,7 +4675,10 @@ public: String *dirClassName = directorClassName(current_class); Wrapper *w = NewWrapper(); - if (Getattr(n, "throw")) { + if (Getattr(n, "noexcept")) { + Printf(f_directors_h, " virtual ~%s() noexcept;\n", dirClassName); + Printf(w->def, "%s::~%s() noexcept {\n", dirClassName, dirClassName); + } else if (Getattr(n, "throw")) { Printf(f_directors_h, " virtual ~%s() throw ();\n", dirClassName); Printf(w->def, "%s::~%s() throw () {\n", dirClassName, dirClassName); } else { diff --git a/Source/Modules/octave.cxx b/Source/Modules/octave.cxx index b977609a8..0130cedd8 100644 --- a/Source/Modules/octave.cxx +++ b/Source/Modules/octave.cxx @@ -1321,6 +1321,10 @@ public: Delete(target); // Get any exception classes in the throws typemap + if (Getattr(n, "noexcept")) { + Append(w->def, " noexcept"); + Append(declaration, " noexcept"); + } ParmList *throw_parm_list = 0; if ((throw_parm_list = Getattr(n, "throws")) || Getattr(n, "throw")) { diff --git a/Source/Modules/perl5.cxx b/Source/Modules/perl5.cxx index 406568b16..a7c7fa9ff 100644 --- a/Source/Modules/perl5.cxx +++ b/Source/Modules/perl5.cxx @@ -2090,6 +2090,10 @@ public: Delete(target); // Get any exception classes in the throws typemap + if (Getattr(n, "noexcept")) { + Append(w->def, " noexcept"); + Append(declaration, " noexcept"); + } ParmList *throw_parm_list = 0; if ((throw_parm_list = Getattr(n, "throws")) || Getattr(n, "throw")) { @@ -2486,7 +2490,10 @@ public: Delete(mangle); Delete(ptype); - if (Getattr(n, "throw")) { + if (Getattr(n, "noexcept")) { + Printf(f_directors_h, " virtual ~%s() noexcept;\n", DirectorClassName); + Printf(f_directors, "%s::~%s() noexcept {%s}\n\n", DirectorClassName, DirectorClassName, body); + } else if (Getattr(n, "throw")) { Printf(f_directors_h, " virtual ~%s() throw ();\n", DirectorClassName); Printf(f_directors, "%s::~%s() throw () {%s}\n\n", DirectorClassName, DirectorClassName, body); } else { diff --git a/Source/Modules/php.cxx b/Source/Modules/php.cxx index 295039ba1..f0e3ae2df 100644 --- a/Source/Modules/php.cxx +++ b/Source/Modules/php.cxx @@ -2530,6 +2530,10 @@ done: Delete(target); // Get any exception classes in the throws typemap + if (Getattr(n, "noexcept")) { + Append(w->def, " noexcept"); + Append(declaration, " noexcept"); + } ParmList *throw_parm_list = 0; if ((throw_parm_list = Getattr(n, "throws")) || Getattr(n, "throw")) { diff --git a/Source/Modules/python.cxx b/Source/Modules/python.cxx index 5e058e773..8dcabb578 100644 --- a/Source/Modules/python.cxx +++ b/Source/Modules/python.cxx @@ -5366,8 +5366,11 @@ int PYTHON::classDirectorMethod(Node *n, Node *parent, String *super) { Delete(target); // Get any exception classes in the throws typemap + if (Getattr(n, "noexcept")) { + Append(w->def, " noexcept"); + Append(declaration, " noexcept"); + } ParmList *throw_parm_list = 0; - if ((throw_parm_list = Getattr(n, "throws")) || Getattr(n, "throw")) { Parm *p; int gencomma = 0; diff --git a/Source/Modules/ruby.cxx b/Source/Modules/ruby.cxx index b9ac11546..07c5797f8 100644 --- a/Source/Modules/ruby.cxx +++ b/Source/Modules/ruby.cxx @@ -3112,6 +3112,10 @@ public: Delete(target); // Get any exception classes in the throws typemap + if (Getattr(n, "noexcept")) { + Append(w->def, " noexcept"); + Append(declaration, " noexcept"); + } ParmList *throw_parm_list = 0; if ((throw_parm_list = Getattr(n, "throws")) || Getattr(n, "throw")) { From e13eaaae2118309af479333ab97244e8c28b5fd0 Mon Sep 17 00:00:00 2001 From: Christophe Duvernois Date: Fri, 28 Apr 2017 11:45:02 +0200 Subject: [PATCH 086/455] java : noexcept method can't raise Swig::DirectorException --- Source/Modules/java.cxx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Source/Modules/java.cxx b/Source/Modules/java.cxx index b380565b5..b814c1576 100644 --- a/Source/Modules/java.cxx +++ b/Source/Modules/java.cxx @@ -4375,9 +4375,11 @@ public: Printf(w->code, "jenv->%s(Swig::jclass_%s, Swig::director_method_ids[%s], %s);\n", methop, imclass_name, methid, jupcall_args); + if (!Getattr(n, "noexcept")) { // Generate code to handle any Java exception thrown by director delegation directorExceptHandler(n, catches_list ? catches_list : throw_parm_list, w); - + } + if (!is_void) { String *jresult_str = NewString("jresult"); String *result_str = NewString("c_result"); From 9dcf10138e5053d50a37a7837dc86e58d6b96dae Mon Sep 17 00:00:00 2001 From: Christophe Duvernois Date: Fri, 28 Apr 2017 11:45:36 +0200 Subject: [PATCH 087/455] csharp : noexcept method can't raise Swig::DirectorPureVirtualException --- Source/Modules/csharp.cxx | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/Source/Modules/csharp.cxx b/Source/Modules/csharp.cxx index 154fadac5..a8792f7ea 100644 --- a/Source/Modules/csharp.cxx +++ b/Source/Modules/csharp.cxx @@ -403,6 +403,7 @@ public: if (directorsEnabled()) { Printf(f_runtime, "#define SWIG_DIRECTORS\n"); + Printf(f_runtime, "#include \n"); /* Emit initial director header and director code: */ Swig_banner(f_directors_h); @@ -3935,7 +3936,12 @@ public: } Delete(super_call); } else { - Printf(w->code, " throw Swig::DirectorPureVirtualException(\"%s::%s\");\n", SwigType_namestr(c_classname), SwigType_namestr(name)); + if (Getattr(n, "noexcept")) { + Printf(w->code, " //can't throw exception here\n"); + Printf(w->code, " assert(0 && \"swig DirectorPureVirtualException %s::%s\");", SwigType_namestr(c_classname), SwigType_namestr(name)); + } else { + Printf(w->code, " throw Swig::DirectorPureVirtualException(\"%s::%s\");\n", SwigType_namestr(c_classname), SwigType_namestr(name)); + } } if (!ignored_method) From 3adf88e9ef236ff2795bd1b69b240b6fd35e895b Mon Sep 17 00:00:00 2001 From: Nihal Date: Sun, 7 May 2017 17:49:02 +0530 Subject: [PATCH 088/455] Refactor to generate init section before the code. Prerequisite to address issue #360, feature request of adding extension version. This change has been taken from Sources/Modules/php.cxx - PHP7 Backend. --- Source/Modules/php5.cxx | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/Source/Modules/php5.cxx b/Source/Modules/php5.cxx index bf3ce4fa4..e31b81ecb 100644 --- a/Source/Modules/php5.cxx +++ b/Source/Modules/php5.cxx @@ -294,7 +294,7 @@ public: f_runtime = NewStringEmpty(); /* sections of the output file */ - s_init = NewString("/* init section */\n"); + s_init = NewStringEmpty(); r_init = NewString("/* rinit section */\n"); s_shutdown = NewString("/* shutdown section */\n"); r_shutdown = NewString("/* rshutdown section */\n"); @@ -528,7 +528,14 @@ public: Printf(s_entry, "/* Every non-class user visible function must have an entry here */\n"); Printf(s_entry, "static zend_function_entry %s_functions[] = {\n", module); + /* Emit all of the code */ + Language::top(n); + + SwigPHP_emit_resource_registrations(); + /* start the init section */ + String * s_init_old = s_init; + s_init = NewString("/* init section */\n"); Append(s_init, "#if ZEND_MODULE_API_NO <= 20090626\n"); Append(s_init, "#undef ZEND_MODULE_BUILD_ID\n"); Append(s_init, "#define ZEND_MODULE_BUILD_ID (char*)\"API\" ZEND_TOSTR(ZEND_MODULE_API_NO) ZEND_BUILD_TS ZEND_BUILD_DEBUG ZEND_BUILD_SYSTEM ZEND_BUILD_EXTRA\n"); @@ -562,11 +569,9 @@ public: * things are being called in the wrong order */ Printf(s_init, "#define SWIG_php_minit PHP_MINIT_FUNCTION(%s)\n", module); + Printv(s_init, s_init_old, NIL); + Delete(s_init_old); - /* Emit all of the code */ - Language::top(n); - - SwigPHP_emit_resource_registrations(); // Printv(s_init,s_resourcetypes,NIL); /* We need this after all classes written out by ::top */ Printf(s_oinit, "CG(active_class_entry) = NULL;\n"); From eb9e72f3b259b299c966f5f02bf724ea82a2c126 Mon Sep 17 00:00:00 2001 From: Nihal Date: Mon, 8 May 2017 11:43:38 +0530 Subject: [PATCH 089/455] Add new pragma to specify version to PHP5 and PHP7 extensions. See issue #360, feature request to have version in php5 and php7 extensions. --- Source/Modules/php.cxx | 12 +++++++++++- Source/Modules/php5.cxx | 12 +++++++++++- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/Source/Modules/php.cxx b/Source/Modules/php.cxx index 295039ba1..4bc0eecd3 100644 --- a/Source/Modules/php.cxx +++ b/Source/Modules/php.cxx @@ -96,6 +96,7 @@ static String *all_cs_entry; static String *pragma_incl; static String *pragma_code; static String *pragma_phpinfo; +static String *pragma_version; static String *s_oowrappers; static String *s_fakeoowrappers; static String *s_phpclasses; @@ -359,6 +360,7 @@ public: /* sub-sections of the php file */ pragma_code = NewStringEmpty(); pragma_incl = NewStringEmpty(); + pragma_version = NULL; /* Initialize the rest of the module */ @@ -515,7 +517,11 @@ public: } else { Printf(s_init, " NULL, /* No MINFO code */\n"); } - Printf(s_init, " NO_VERSION_YET,\n"); + if (Len(pragma_version) > 0) { + Printf(s_init, " \"%s\",\n", pragma_version); + } else { + 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); @@ -2007,6 +2013,10 @@ done: if (value) { Printf(pragma_phpinfo, "%s\n", value); } + } else if (Strcmp(type, "version") == 0) { + if (value) { + pragma_version = value; + } } else { Swig_warning(WARN_PHP_UNKNOWN_PRAGMA, input_file, line_number, "Unrecognized pragma <%s>.\n", type); } diff --git a/Source/Modules/php5.cxx b/Source/Modules/php5.cxx index e31b81ecb..7726a2f6c 100644 --- a/Source/Modules/php5.cxx +++ b/Source/Modules/php5.cxx @@ -96,6 +96,7 @@ static String *all_cs_entry; static String *pragma_incl; static String *pragma_code; static String *pragma_phpinfo; +static String *pragma_version; static String *s_oowrappers; static String *s_fakeoowrappers; static String *s_phpclasses; @@ -391,6 +392,7 @@ public: /* sub-sections of the php file */ pragma_code = NewStringEmpty(); pragma_incl = NewStringEmpty(); + pragma_version = NULL; /* Initialize the rest of the module */ @@ -549,7 +551,11 @@ public: Printf(s_init, " PHP_RINIT(%s),\n", module); Printf(s_init, " PHP_RSHUTDOWN(%s),\n", module); Printf(s_init, " PHP_MINFO(%s),\n", module); - Printf(s_init, " NO_VERSION_YET,\n"); + if (Len(pragma_version) > 0) { + Printf(s_init, " \"%s\",\n", pragma_version); + } else { + 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); @@ -1993,6 +1999,10 @@ done: if (value) { Printf(pragma_phpinfo, "%s\n", value); } + } else if (Strcmp(type, "version") == 0) { + if (value) { + pragma_version = value; + } } else { Swig_warning(WARN_PHP_UNKNOWN_PRAGMA, input_file, line_number, "Unrecognized pragma <%s>.\n", type); } From 7f72398eb690a143fb928068cb61dfaa23c22d7a Mon Sep 17 00:00:00 2001 From: Nihal Date: Mon, 8 May 2017 12:02:18 +0530 Subject: [PATCH 090/455] Add tests for PHP pragma version to both PHP5 and PHP7. Pragma version to specify version of PHP5 and PHP7 extensions. See issue #360. --- Examples/test-suite/php/Makefile.in | 1 + Examples/test-suite/php/php_pragma_runme.php | 12 ++++++++++++ Examples/test-suite/php5/Makefile.in | 1 + Examples/test-suite/php5/php_pragma_runme.php | 12 ++++++++++++ Examples/test-suite/php_pragma.i | 6 ++++++ 5 files changed, 32 insertions(+) create mode 100644 Examples/test-suite/php/php_pragma_runme.php create mode 100644 Examples/test-suite/php5/php_pragma_runme.php create mode 100644 Examples/test-suite/php_pragma.i diff --git a/Examples/test-suite/php/Makefile.in b/Examples/test-suite/php/Makefile.in index c554e2b17..64f0d1f9d 100644 --- a/Examples/test-suite/php/Makefile.in +++ b/Examples/test-suite/php/Makefile.in @@ -14,6 +14,7 @@ CPP_TEST_CASES += \ li_factory \ php_iterator \ php_namewarn_rename \ + php_pragma \ include $(srcdir)/../common.mk diff --git a/Examples/test-suite/php/php_pragma_runme.php b/Examples/test-suite/php/php_pragma_runme.php new file mode 100644 index 000000000..ae92f6818 --- /dev/null +++ b/Examples/test-suite/php/php_pragma_runme.php @@ -0,0 +1,12 @@ +getVersion(),"1.5==version(php_pragma)"); + +check::done(); + +?> + diff --git a/Examples/test-suite/php5/Makefile.in b/Examples/test-suite/php5/Makefile.in index 391ca2c53..179ce59d6 100644 --- a/Examples/test-suite/php5/Makefile.in +++ b/Examples/test-suite/php5/Makefile.in @@ -14,6 +14,7 @@ CPP_TEST_CASES += \ li_factory \ php_iterator \ php_namewarn_rename \ + php_pragma \ include $(srcdir)/../common.mk diff --git a/Examples/test-suite/php5/php_pragma_runme.php b/Examples/test-suite/php5/php_pragma_runme.php new file mode 100644 index 000000000..ae92f6818 --- /dev/null +++ b/Examples/test-suite/php5/php_pragma_runme.php @@ -0,0 +1,12 @@ +getVersion(),"1.5==version(php_pragma)"); + +check::done(); + +?> + diff --git a/Examples/test-suite/php_pragma.i b/Examples/test-suite/php_pragma.i new file mode 100644 index 000000000..4d14f1357 --- /dev/null +++ b/Examples/test-suite/php_pragma.i @@ -0,0 +1,6 @@ +// Test pragma of php - pragma version. + +%module php_pragma + +%pragma(php) version= "1.5" + From 21108781a7d5ccdece63513bab1028e4c6034ef5 Mon Sep 17 00:00:00 2001 From: Nihal Date: Mon, 8 May 2017 12:02:53 +0530 Subject: [PATCH 091/455] Add documentation and examples for php version pragma. Pragma version to specify versions for PHP5 and PHP7 extensions. See issue #360. --- Doc/Manual/Php.html | 9 +++++++++ Examples/php/pragmas/example.i | 1 + Examples/php/pragmas/runme.php | 1 + Examples/php5/pragmas/example.i | 1 + Examples/php5/pragmas/runme.php | 1 + 5 files changed, 13 insertions(+) diff --git a/Doc/Manual/Php.html b/Doc/Manual/Php.html index 52bedf87f..7d3d33ac1 100644 --- a/Doc/Manual/Php.html +++ b/Doc/Manual/Php.html @@ -820,6 +820,15 @@ Results in the following in "example.php" echo "example.php execution\n"; +

+The version pragma can be used to add version to generated PHP extension module. The version is inserted in the zend_module_entry block. +

+ +
+%module example
+%pragma(php) version="1.5"
+
+

The include pragma is a short cut to add include statements to the example.php file. diff --git a/Examples/php/pragmas/example.i b/Examples/php/pragmas/example.i index c7e8bf303..f9307a663 100644 --- a/Examples/php/pragmas/example.i +++ b/Examples/php/pragmas/example.i @@ -27,5 +27,6 @@ # This code is inserted into example.php echo \"this was php code\\n\"; " +%pragma(php) version="1.5" %pragma(php) phpinfo="php_info_print_table_start();" diff --git a/Examples/php/pragmas/runme.php b/Examples/php/pragmas/runme.php index 538548b6f..b99cf37a4 100644 --- a/Examples/php/pragmas/runme.php +++ b/Examples/php/pragmas/runme.php @@ -2,4 +2,5 @@ require "example.php"; +echo "Version - " . ((new ReflectionExtension('example'))->getVersion()); ?> diff --git a/Examples/php5/pragmas/example.i b/Examples/php5/pragmas/example.i index c7e8bf303..f9307a663 100644 --- a/Examples/php5/pragmas/example.i +++ b/Examples/php5/pragmas/example.i @@ -27,5 +27,6 @@ # This code is inserted into example.php echo \"this was php code\\n\"; " +%pragma(php) version="1.5" %pragma(php) phpinfo="php_info_print_table_start();" diff --git a/Examples/php5/pragmas/runme.php b/Examples/php5/pragmas/runme.php index 538548b6f..b99cf37a4 100644 --- a/Examples/php5/pragmas/runme.php +++ b/Examples/php5/pragmas/runme.php @@ -2,4 +2,5 @@ require "example.php"; +echo "Version - " . ((new ReflectionExtension('example'))->getVersion()); ?> From e8e56f74ca5b12ca335c6db7319fbc1e0fc1b387 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Fri, 12 May 2017 07:41:40 +0100 Subject: [PATCH 092/455] Fix thread race in director_thread test --- Examples/test-suite/director_thread.i | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/Examples/test-suite/director_thread.i b/Examples/test-suite/director_thread.i index 2732eb907..fa55540a0 100644 --- a/Examples/test-suite/director_thread.i +++ b/Examples/test-suite/director_thread.i @@ -17,7 +17,7 @@ #include #endif -#include +#include class Foo; extern "C" { @@ -28,8 +28,17 @@ extern "C" { void* working(void* t); pthread_t thread; #endif + static int thread_terminate = 0; - + static SwigExamples::CriticalSection critical_section; + int get_thread_terminate() { + SwigExamples::Lock lock(critical_section); + return thread_terminate; + } + void set_thread_terminate(int value) { + SwigExamples::Lock lock(critical_section); + thread_terminate = value; + } } %} @@ -55,7 +64,7 @@ extern "C" { } void stop() { - thread_terminate = 1; + set_thread_terminate(1); %#ifdef _WIN32 /*TODO(bhy) what to do for win32? */ %#else @@ -87,7 +96,7 @@ extern "C" { #endif { Foo* f = static_cast(t); - while ( ! thread_terminate ) { + while (!get_thread_terminate()) { MilliSecondSleep(50); f->do_foo(); } From be5d046f7dc1c761e0308e1c75f6286cd76cdff4 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Fri, 12 May 2017 08:20:01 +0100 Subject: [PATCH 093/455] director_thread testcase improvements - Add missing threading constructs to director_thread test for Windows - pthreads tidy up --- Examples/test-suite/director_thread.i | 28 ++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/Examples/test-suite/director_thread.i b/Examples/test-suite/director_thread.i index fa55540a0..699ccf5c4 100644 --- a/Examples/test-suite/director_thread.i +++ b/Examples/test-suite/director_thread.i @@ -11,6 +11,7 @@ #ifdef _WIN32 #include #include +#include #else #include #include @@ -22,11 +23,11 @@ class Foo; extern "C" { #ifdef _WIN32 - unsigned int __stdcall working(void* t); - unsigned int thread_id(0); + static unsigned int __stdcall working(void* t); + static HANDLE thread_handle = 0; #else void* working(void* t); - pthread_t thread; + static pthread_t thread; #endif static int thread_terminate = 0; @@ -66,7 +67,8 @@ extern "C" { void stop() { set_thread_terminate(1); %#ifdef _WIN32 - /*TODO(bhy) what to do for win32? */ + WaitForSingleObject(thread_handle, INFINITE); + CloseHandle(thread_handle); %#else pthread_join(thread, NULL); %#endif @@ -74,9 +76,18 @@ extern "C" { void run() { %#ifdef _WIN32 - _beginthreadex(NULL,0,working,this,0,&thread_id); + int thread_id = 0; + thread_handle = (HANDLE)_beginthreadex(NULL,0,working,this,0,&thread_id); + if (thread_handle == 0) { + fprintf(stderr, "_beginthreadex failed in run()\n"); + assert(0); + } %#else - pthread_create(&thread,NULL,working,this); + int create = pthread_create(&thread,NULL,working,this); + if (create != 0) { + fprintf(stderr, "pthread_create failed in run()\n"); + assert(0); + } %#endif MilliSecondSleep(500); } @@ -100,11 +111,6 @@ extern "C" { MilliSecondSleep(50); f->do_foo(); } -#ifdef _WIN32 - /* TODO(bhy) what's the corresponding of pthread_exit in win32? */ -#else - pthread_exit(0); -#endif return 0; } } From e05412088fd5e4b8dc2c7354abe0aa4f86665574 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Fri, 12 May 2017 19:41:31 +0100 Subject: [PATCH 094/455] director_thread testcase fix --- Examples/test-suite/director_thread.i | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Examples/test-suite/director_thread.i b/Examples/test-suite/director_thread.i index 699ccf5c4..260bce774 100644 --- a/Examples/test-suite/director_thread.i +++ b/Examples/test-suite/director_thread.i @@ -18,7 +18,8 @@ #include #endif -#include +#include +#include "swig_examples_lock.h" class Foo; extern "C" { @@ -76,7 +77,7 @@ extern "C" { void run() { %#ifdef _WIN32 - int thread_id = 0; + unsigned int thread_id = 0; thread_handle = (HANDLE)_beginthreadex(NULL,0,working,this,0,&thread_id); if (thread_handle == 0) { fprintf(stderr, "_beginthreadex failed in run()\n"); From e429a891c9bff73f5d549b51b3f6fe81e6767040 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Sat, 13 May 2017 16:16:17 +0100 Subject: [PATCH 095/455] Revert "csharp : noexcept method can't raise Swig::DirectorPureVirtualException" This reverts commit 9dcf10138e5053d50a37a7837dc86e58d6b96dae. --- Source/Modules/csharp.cxx | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/Source/Modules/csharp.cxx b/Source/Modules/csharp.cxx index a8792f7ea..154fadac5 100644 --- a/Source/Modules/csharp.cxx +++ b/Source/Modules/csharp.cxx @@ -403,7 +403,6 @@ public: if (directorsEnabled()) { Printf(f_runtime, "#define SWIG_DIRECTORS\n"); - Printf(f_runtime, "#include \n"); /* Emit initial director header and director code: */ Swig_banner(f_directors_h); @@ -3936,12 +3935,7 @@ public: } Delete(super_call); } else { - if (Getattr(n, "noexcept")) { - Printf(w->code, " //can't throw exception here\n"); - Printf(w->code, " assert(0 && \"swig DirectorPureVirtualException %s::%s\");", SwigType_namestr(c_classname), SwigType_namestr(name)); - } else { - Printf(w->code, " throw Swig::DirectorPureVirtualException(\"%s::%s\");\n", SwigType_namestr(c_classname), SwigType_namestr(name)); - } + Printf(w->code, " throw Swig::DirectorPureVirtualException(\"%s::%s\");\n", SwigType_namestr(c_classname), SwigType_namestr(name)); } if (!ignored_method) From cedfbfbee87cefe5b402ef2360719bd86accb99e Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Sat, 13 May 2017 16:16:29 +0100 Subject: [PATCH 096/455] Revert "java : noexcept method can't raise Swig::DirectorException" This reverts commit e13eaaae2118309af479333ab97244e8c28b5fd0. --- Source/Modules/java.cxx | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/Source/Modules/java.cxx b/Source/Modules/java.cxx index b814c1576..b380565b5 100644 --- a/Source/Modules/java.cxx +++ b/Source/Modules/java.cxx @@ -4375,11 +4375,9 @@ public: Printf(w->code, "jenv->%s(Swig::jclass_%s, Swig::director_method_ids[%s], %s);\n", methop, imclass_name, methid, jupcall_args); - if (!Getattr(n, "noexcept")) { // Generate code to handle any Java exception thrown by director delegation directorExceptHandler(n, catches_list ? catches_list : throw_parm_list, w); - } - + if (!is_void) { String *jresult_str = NewString("jresult"); String *result_str = NewString("c_result"); From 971404485f559bf8dcdcf12d74411f63e439d5b5 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Sat, 13 May 2017 16:59:36 +0100 Subject: [PATCH 097/455] php5: propagate c++11 noexcept to director classes --- Source/Modules/php5.cxx | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Source/Modules/php5.cxx b/Source/Modules/php5.cxx index bf3ce4fa4..188f287d5 100644 --- a/Source/Modules/php5.cxx +++ b/Source/Modules/php5.cxx @@ -2525,6 +2525,10 @@ done: Delete(target); // Get any exception classes in the throws typemap + if (Getattr(n, "noexcept")) { + Append(w->def, " noexcept"); + Append(declaration, " noexcept"); + } ParmList *throw_parm_list = 0; if ((throw_parm_list = Getattr(n, "throws")) || Getattr(n, "throw")) { From 07ab80b49e0b51931a7e309b8c62b72a459efe64 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Sat, 13 May 2017 17:01:15 +0100 Subject: [PATCH 098/455] Add raise methods for throwing c++ exceptions in C#, Java, D The director c++ exceptions are thrown in a helper method instead of in the director overloaded method. This circumvents compiler warnings about throwing exceptions when the method has an exception specification or noexcept. If the exception is thrown, abort will still be called! In Java, the "director:noexcept" typemap can be used to do something else. This typemap should be ported to the other languages too. --- Doc/Manual/Java.html | 16 ++++++++++++++-- Lib/csharp/director.swg | 4 ++++ Lib/d/director.swg | 4 ++++ Lib/java/director.swg | 4 ++++ Source/Modules/csharp.cxx | 2 +- Source/Modules/d.cxx | 2 +- Source/Modules/java.cxx | 2 +- 7 files changed, 29 insertions(+), 5 deletions(-) diff --git a/Doc/Manual/Java.html b/Doc/Manual/Java.html index bd259e60d..c77724bf2 100644 --- a/Doc/Manual/Java.html +++ b/Doc/Manual/Java.html @@ -3923,12 +3923,24 @@ is used in the feature code. Consider the following, which also happens to be th if ($error) { jenv->ExceptionClear(); $directorthrowshandlers - throw Swig::DirectorException(jenv, $error); + Swig::DirectorException::raise(jenv, $error); } %} +

+where Swig::DirectorException::raise is a helper method in the DirectorException class to throw a C++ exception (implemented in director.swg): +

+ +
+
+    static void raise(JNIEnv *jenv, jthrowable throwable) {
+      throw DirectorException(jenv, throwable);
+    }
+
+
+

The code generated using the director:except feature replaces the $directorthrowshandlers special variable with the code in the "directorthrows" typemaps, for each and every exception defined for the method. @@ -3963,7 +3975,7 @@ if (swigerror) { throw std::out_of_range(Swig::JavaExceptionMessage(jenv, swigerror).message()); } - throw Swig::DirectorException(jenv, swigerror); + Swig::DirectorException::raise(jenv, swigerror); } diff --git a/Lib/csharp/director.swg b/Lib/csharp/director.swg index 3438f2bf0..5d2ab5d9b 100644 --- a/Lib/csharp/director.swg +++ b/Lib/csharp/director.swg @@ -41,6 +41,10 @@ namespace Swig { public: DirectorPureVirtualException(const char *msg) : DirectorException(std::string("Attempt to invoke pure virtual method ") + msg) { } + + static void raise(const char *msg) { + throw DirectorPureVirtualException(msg); + } }; } diff --git a/Lib/d/director.swg b/Lib/d/director.swg index a7d9c7688..02da0e0ac 100644 --- a/Lib/d/director.swg +++ b/Lib/d/director.swg @@ -40,6 +40,10 @@ namespace Swig { public: DirectorPureVirtualException(const char *msg) : DirectorException(std::string("Attempted to invoke pure virtual method ") + msg) { } + + static void raise(const char *msg) { + throw DirectorPureVirtualException(msg); + } }; } diff --git a/Lib/java/director.swg b/Lib/java/director.swg index 355e62d67..abde72286 100644 --- a/Lib/java/director.swg +++ b/Lib/java/director.swg @@ -356,6 +356,10 @@ namespace Swig { } } + static void raise(JNIEnv *jenv, jthrowable throwable) { + throw DirectorException(jenv, throwable); + } + private: static char *copypath(const char *srcmsg) { char *target = copystr(srcmsg); diff --git a/Source/Modules/csharp.cxx b/Source/Modules/csharp.cxx index 154fadac5..c41a212e4 100644 --- a/Source/Modules/csharp.cxx +++ b/Source/Modules/csharp.cxx @@ -3935,7 +3935,7 @@ public: } Delete(super_call); } else { - Printf(w->code, " throw Swig::DirectorPureVirtualException(\"%s::%s\");\n", SwigType_namestr(c_classname), SwigType_namestr(name)); + Printf(w->code, "Swig::DirectorPureVirtualException::raise(\"%s::%s\");\n", SwigType_namestr(c_classname), SwigType_namestr(name)); } if (!ignored_method) diff --git a/Source/Modules/d.cxx b/Source/Modules/d.cxx index 05ca6c636..36216b75e 100644 --- a/Source/Modules/d.cxx +++ b/Source/Modules/d.cxx @@ -2077,7 +2077,7 @@ public: } Delete(super_call); } else { - Printf(w->code, " throw Swig::DirectorPureVirtualException(\"%s::%s\");\n", SwigType_namestr(c_classname), SwigType_namestr(name)); + Printf(w->code, "Swig::DirectorPureVirtualException::raise(\"%s::%s\");\n", SwigType_namestr(c_classname), SwigType_namestr(name)); } if (!ignored_method) diff --git a/Source/Modules/java.cxx b/Source/Modules/java.cxx index b380565b5..e53cf1576 100644 --- a/Source/Modules/java.cxx +++ b/Source/Modules/java.cxx @@ -4490,7 +4490,7 @@ public: Printf(directorexcept, "jthrowable $error = jenv->ExceptionOccurred();\n"); Printf(directorexcept, "if ($error) {\n"); Printf(directorexcept, " jenv->ExceptionClear();$directorthrowshandlers\n"); - Printf(directorexcept, " throw Swig::DirectorException(jenv, $error);\n"); + Printf(directorexcept, " Swig::DirectorException::raise(jenv, $error);\n"); Printf(directorexcept, "}\n"); } else { directorexcept = Copy(directorexcept); From 1416a158f04733cc638bfbba1b260a9a790e5942 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Sat, 13 May 2017 17:33:07 +0100 Subject: [PATCH 099/455] changes file entry for noexcept on director methods --- CHANGES.current | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGES.current b/CHANGES.current index 7e579f911..d6104c02c 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.0.0 (in progress) =========================== +2017-05-13: yag00 + Patch #975 - Add support for noexcept on director methods. + 2017-04-27: redbrain Issue #974, Patch #976 - Fix preprocessor handling of macros with commas in a comment. From 731f175d21c04aab3ec7ca074595280ca5a9529f Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Sat, 13 May 2017 17:46:01 +0100 Subject: [PATCH 100/455] propagate c++11 noexcept to director classes for Go --- Source/Modules/go.cxx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Source/Modules/go.cxx b/Source/Modules/go.cxx index 4927326f2..bcae168f0 100644 --- a/Source/Modules/go.cxx +++ b/Source/Modules/go.cxx @@ -5492,6 +5492,8 @@ private: *--------------------------------------------------------------------*/ String *buildThrow(Node *n) { + if (Getattr(n, "noexcept")) + return NewString("noexcept"); ParmList *throw_parm_list = Getattr(n, "throws"); if (!throw_parm_list && !Getattr(n, "throw")) return NULL; From ace88b45a0ba98248e77883e3d1045f9deb5e1cc Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Sat, 13 May 2017 18:15:55 +0100 Subject: [PATCH 101/455] Expand c++11 and c++14 Travis testing Add testing for Go, Perl, PHP, Tcl --- .travis.yml | 32 +++++++++++++++++++ .../test-suite/cpp11_raw_string_literals.i | 2 ++ 2 files changed, 34 insertions(+) diff --git a/.travis.yml b/.travis.yml index dce67cee7..d147114b0 100644 --- a/.travis.yml +++ b/.travis.yml @@ -224,10 +224,22 @@ matrix: env: SWIGLANG=csharp SWIG_CC=gcc-5 SWIG_CXX=g++-5 CPP11=1 sudo: required dist: trusty + - os: linux + env: SWIGLANG=go SWIG_CC=gcc-5 SWIG_CXX=g++-5 CPP11=1 + sudo: required + dist: trusty - os: linux env: SWIGLANG=java SWIG_CC=gcc-5 SWIG_CXX=g++-5 CPP11=1 sudo: required dist: trusty + - os: linux + env: SWIGLANG=perl5 SWIG_CC=gcc-5 SWIG_CXX=g++-5 CPP11=1 + sudo: required + dist: trusty + - os: linux + env: SWIGLANG=php VER=7.1 SWIG_CC=gcc-5 SWIG_CXX=g++-5 CPP11=1 + sudo: required + dist: trusty - os: linux env: SWIGLANG=python SWIG_CC=gcc-5 SWIG_CXX=g++-5 CPP11=1 sudo: required @@ -236,14 +248,30 @@ matrix: env: SWIGLANG=ruby SWIG_CC=gcc-5 SWIG_CXX=g++-5 CPP11=1 sudo: required dist: trusty + - os: linux + env: SWIGLANG=tcl SWIG_CC=gcc-5 SWIG_CXX=g++-5 CPP11=1 + sudo: required + dist: trusty - os: linux env: SWIGLANG=csharp SWIG_CC=gcc-6 SWIG_CXX=g++-6 CPP14=1 sudo: required dist: trusty + - os: linux + env: SWIGLANG=go SWIG_CC=gcc-6 SWIG_CXX=g++-6 CPP14=1 + sudo: required + dist: trusty - os: linux env: SWIGLANG=java SWIG_CC=gcc-6 SWIG_CXX=g++-6 CPP14=1 sudo: required dist: trusty + - os: linux + env: SWIGLANG=perl5 SWIG_CC=gcc-6 SWIG_CXX=g++-6 CPP14=1 + sudo: required + dist: trusty + - os: linux + env: SWIGLANG=php VER=7.1 SWIG_CC=gcc-6 SWIG_CXX=g++-6 CPP14=1 + sudo: required + dist: trusty - os: linux env: SWIGLANG=python SWIG_CC=gcc-6 SWIG_CXX=g++-6 CPP14=1 sudo: required @@ -252,6 +280,10 @@ matrix: env: SWIGLANG=ruby SWIG_CC=gcc-6 SWIG_CXX=g++-6 CPP14=1 sudo: required dist: trusty + - os: linux + env: SWIGLANG=tcl SWIG_CC=gcc-6 SWIG_CXX=g++-6 CPP14=1 + sudo: required + dist: trusty - compiler: gcc os: osx env: SWIGLANG= diff --git a/Examples/test-suite/cpp11_raw_string_literals.i b/Examples/test-suite/cpp11_raw_string_literals.i index 6fd13a0d0..1dea90e0c 100644 --- a/Examples/test-suite/cpp11_raw_string_literals.i +++ b/Examples/test-suite/cpp11_raw_string_literals.i @@ -17,7 +17,9 @@ %warnfilter(SWIGWARN_TYPEMAP_SWIGTYPELEAK_MSG) hh; %warnfilter(SWIGWARN_TYPEMAP_SWIGTYPELEAK_MSG) ii; +#if defined(SWIGTCL) || defined(SWIGCSHARP) || defined(SWIGOCTAVE) || defined(SWIGRUBY) || defined(SWIGPYTHON) || defined(SWIGJAVA) %include +#endif %inline %{ #include From ebd37155a81fd0c9504522e43cbdaf38312a132c Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Sat, 13 May 2017 22:40:59 +0100 Subject: [PATCH 102/455] Fix potential use of uninitialized variables in directors --- Source/Modules/go.cxx | 14 +++++++++++++- Source/Modules/ocaml.cxx | 16 +++++++++++++--- Source/Modules/octave.cxx | 18 +++++++++++++----- Source/Modules/perl5.cxx | 18 ++++++++++++++---- Source/Modules/php.cxx | 12 ++++++++++-- Source/Modules/php5.cxx | 12 ++++++++++-- Source/Modules/python.cxx | 12 ++++++++++-- Source/Modules/ruby.cxx | 16 +++++++++++++--- 8 files changed, 96 insertions(+), 22 deletions(-) diff --git a/Source/Modules/go.cxx b/Source/Modules/go.cxx index bcae168f0..1512834f9 100644 --- a/Source/Modules/go.cxx +++ b/Source/Modules/go.cxx @@ -5058,7 +5058,19 @@ private: Printv(w->def, " {\n", NULL); if (SwigType_type(result) != T_VOID) { - Wrapper_add_local(w, "c_result", SwigType_lstr(result, "c_result")); + if (!SwigType_isclass(result)) { + if (!(SwigType_ispointer(result) || SwigType_isreference(result))) { + String *construct_result = NewStringf("= SwigValueInit< %s >()", SwigType_lstr(result, 0)); + Wrapper_add_localv(w, "c_result", SwigType_lstr(result, "c_result"), construct_result, NIL); + Delete(construct_result); + } else { + Wrapper_add_localv(w, "c_result", SwigType_lstr(result, "c_result"), "= 0", NIL); + } + } else { + String *cres = SwigType_lstr(result, "c_result"); + Printf(w->code, "%s;\n", cres); + Delete(cres); + } } if (!is_ignored) { diff --git a/Source/Modules/ocaml.cxx b/Source/Modules/ocaml.cxx index 73dd14f96..15a13f5ec 100644 --- a/Source/Modules/ocaml.cxx +++ b/Source/Modules/ocaml.cxx @@ -1429,9 +1429,19 @@ public: * if the return value is a reference or const reference, a specialized typemap must * handle it, including declaration of c_result ($result). */ - if (!is_void) { - if (!(ignored_method && !pure_virtual)) { - Wrapper_add_localv(w, "c_result", SwigType_lstr(returntype, "c_result"), NIL); + if (!is_void && (!ignored_method || pure_virtual)) { + if (!SwigType_isclass(returntype)) { + if (!(SwigType_ispointer(returntype) || SwigType_isreference(returntype))) { + String *construct_result = NewStringf("= SwigValueInit< %s >()", SwigType_lstr(returntype, 0)); + Wrapper_add_localv(w, "c_result", SwigType_lstr(returntype, "c_result"), construct_result, NIL); + Delete(construct_result); + } else { + Wrapper_add_localv(w, "c_result", SwigType_lstr(returntype, "c_result"), "= 0", NIL); + } + } else { + String *cres = SwigType_lstr(returntype, "c_result"); + Printf(w->code, "%s;\n", cres); + Delete(cres); } } diff --git a/Source/Modules/octave.cxx b/Source/Modules/octave.cxx index 0130cedd8..e64a0779f 100644 --- a/Source/Modules/octave.cxx +++ b/Source/Modules/octave.cxx @@ -1359,11 +1359,19 @@ public: // 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). - if (!is_void) { - if (!(ignored_method && !pure_virtual)) { - String *cres = SwigType_lstr(returntype, "c_result"); - Printf(w->code, "%s;\n", cres); - Delete(cres); + if (!is_void && (!ignored_method || pure_virtual)) { + if (!SwigType_isclass(returntype)) { + if (!(SwigType_ispointer(returntype) || SwigType_isreference(returntype))) { + String *construct_result = NewStringf("= SwigValueInit< %s >()", SwigType_lstr(returntype, 0)); + Wrapper_add_localv(w, "c_result", SwigType_lstr(returntype, "c_result"), construct_result, NIL); + Delete(construct_result); + } else { + Wrapper_add_localv(w, "c_result", SwigType_lstr(returntype, "c_result"), "= 0", NIL); + } + } else { + String *cres = SwigType_lstr(returntype, "c_result"); + Printf(w->code, "%s;\n", cres); + Delete(cres); } } diff --git a/Source/Modules/perl5.cxx b/Source/Modules/perl5.cxx index a7c7fa9ff..e46761028 100644 --- a/Source/Modules/perl5.cxx +++ b/Source/Modules/perl5.cxx @@ -2130,10 +2130,20 @@ public: * handle it, including declaration of c_result ($result). */ if (!is_void) { - if (!(ignored_method && !pure_virtual)) { - String *cres = SwigType_lstr(returntype, "c_result"); - Printf(w->code, "%s;\n", cres); - Delete(cres); + if (!ignored_method || pure_virtual) { + if (!SwigType_isclass(returntype)) { + if (!(SwigType_ispointer(returntype) || SwigType_isreference(returntype))) { + String *construct_result = NewStringf("= SwigValueInit< %s >()", SwigType_lstr(returntype, 0)); + Wrapper_add_localv(w, "c_result", SwigType_lstr(returntype, "c_result"), construct_result, NIL); + Delete(construct_result); + } else { + Wrapper_add_localv(w, "c_result", SwigType_lstr(returntype, "c_result"), "= 0", NIL); + } + } else { + String *cres = SwigType_lstr(returntype, "c_result"); + Printf(w->code, "%s;\n", cres); + Delete(cres); + } } if (!ignored_method) { String *pres = NewStringf("SV *%s", Swig_cresult_name()); diff --git a/Source/Modules/php.cxx b/Source/Modules/php.cxx index f0e3ae2df..e6fbf47d7 100644 --- a/Source/Modules/php.cxx +++ b/Source/Modules/php.cxx @@ -2569,8 +2569,16 @@ done: * if the return value is a reference or const reference, a specialized typemap must * handle it, including declaration of c_result ($result). */ - if (!is_void) { - if (!(ignored_method && !pure_virtual)) { + if (!is_void && (!ignored_method || pure_virtual)) { + if (!SwigType_isclass(returntype)) { + if (!(SwigType_ispointer(returntype) || SwigType_isreference(returntype))) { + String *construct_result = NewStringf("= SwigValueInit< %s >()", SwigType_lstr(returntype, 0)); + Wrapper_add_localv(w, "c_result", SwigType_lstr(returntype, "c_result"), construct_result, NIL); + Delete(construct_result); + } else { + Wrapper_add_localv(w, "c_result", SwigType_lstr(returntype, "c_result"), "= 0", NIL); + } + } else { String *cres = SwigType_lstr(returntype, "c_result"); Printf(w->code, "%s;\n", cres); Delete(cres); diff --git a/Source/Modules/php5.cxx b/Source/Modules/php5.cxx index 188f287d5..59d928c21 100644 --- a/Source/Modules/php5.cxx +++ b/Source/Modules/php5.cxx @@ -2566,8 +2566,16 @@ done: * if the return value is a reference or const reference, a specialized typemap must * handle it, including declaration of c_result ($result). */ - if (!is_void) { - if (!(ignored_method && !pure_virtual)) { + if (!is_void && (!ignored_method || pure_virtual)) { + if (!SwigType_isclass(returntype)) { + if (!(SwigType_ispointer(returntype) || SwigType_isreference(returntype))) { + String *construct_result = NewStringf("= SwigValueInit< %s >()", SwigType_lstr(returntype, 0)); + Wrapper_add_localv(w, "c_result", SwigType_lstr(returntype, "c_result"), construct_result, NIL); + Delete(construct_result); + } else { + Wrapper_add_localv(w, "c_result", SwigType_lstr(returntype, "c_result"), "= 0", NIL); + } + } else { String *cres = SwigType_lstr(returntype, "c_result"); Printf(w->code, "%s;\n", cres); Delete(cres); diff --git a/Source/Modules/python.cxx b/Source/Modules/python.cxx index 8dcabb578..2248ba920 100644 --- a/Source/Modules/python.cxx +++ b/Source/Modules/python.cxx @@ -5404,8 +5404,16 @@ int PYTHON::classDirectorMethod(Node *n, Node *parent, String *super) { * if the return value is a reference or const reference, a specialized typemap must * handle it, including declaration of c_result ($result). */ - if (!is_void) { - if (!(ignored_method && !pure_virtual)) { + if (!is_void && (!ignored_method || pure_virtual)) { + if (!SwigType_isclass(returntype)) { + if (!(SwigType_ispointer(returntype) || SwigType_isreference(returntype))) { + String *construct_result = NewStringf("= SwigValueInit< %s >()", SwigType_lstr(returntype, 0)); + Wrapper_add_localv(w, "c_result", SwigType_lstr(returntype, "c_result"), construct_result, NIL); + Delete(construct_result); + } else { + Wrapper_add_localv(w, "c_result", SwigType_lstr(returntype, "c_result"), "= 0", NIL); + } + } else { String *cres = SwigType_lstr(returntype, "c_result"); Printf(w->code, "%s;\n", cres); Delete(cres); diff --git a/Source/Modules/ruby.cxx b/Source/Modules/ruby.cxx index 07c5797f8..25988d6fb 100644 --- a/Source/Modules/ruby.cxx +++ b/Source/Modules/ruby.cxx @@ -3154,9 +3154,19 @@ public: * if the return value is a reference or const reference, a specialized typemap must * handle it, including declaration of c_result ($result). */ - if (!is_void) { - if (!(ignored_method && !pure_virtual)) { - Wrapper_add_localv(w, "c_result", SwigType_lstr(returntype, "c_result"), NIL); + if (!is_void && (!ignored_method || pure_virtual)) { + if (!SwigType_isclass(returntype)) { + if (!(SwigType_ispointer(returntype) || SwigType_isreference(returntype))) { + String *construct_result = NewStringf("= SwigValueInit< %s >()", SwigType_lstr(returntype, 0)); + Wrapper_add_localv(w, "c_result", SwigType_lstr(returntype, "c_result"), construct_result, NIL); + Delete(construct_result); + } else { + Wrapper_add_localv(w, "c_result", SwigType_lstr(returntype, "c_result"), "= 0", NIL); + } + } else { + String *cres = SwigType_lstr(returntype, "c_result"); + Printf(w->code, "%s;\n", cres); + Delete(cres); } } From 320df846074e2ca24384d0e85b7f439eebc63cc0 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Sat, 13 May 2017 23:17:02 +0100 Subject: [PATCH 103/455] Add missing return for pure virtual director wrappers for D and C# --- Source/Modules/csharp.cxx | 6 +++++- Source/Modules/d.cxx | 6 +++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/Source/Modules/csharp.cxx b/Source/Modules/csharp.cxx index c41a212e4..89c47186e 100644 --- a/Source/Modules/csharp.cxx +++ b/Source/Modules/csharp.cxx @@ -3826,7 +3826,7 @@ public: qualified_return = SwigType_rcaststr(returntype, "c_result"); - if (!is_void && !ignored_method) { + if (!is_void && (!ignored_method || pure_virtual)) { if (!SwigType_isclass(returntype)) { if (!(SwigType_ispointer(returntype) || SwigType_isreference(returntype))) { String *construct_result = NewStringf("= SwigValueInit< %s >()", SwigType_lstr(returntype, 0)); @@ -3936,6 +3936,10 @@ public: Delete(super_call); } else { Printf(w->code, "Swig::DirectorPureVirtualException::raise(\"%s::%s\");\n", SwigType_namestr(c_classname), SwigType_namestr(name)); + if (!is_void) + Printf(w->code, "return %s;", qualified_return); + else if (!ignored_method) + Printf(w->code, "return;\n"); } if (!ignored_method) diff --git a/Source/Modules/d.cxx b/Source/Modules/d.cxx index 36216b75e..dd0fc371f 100644 --- a/Source/Modules/d.cxx +++ b/Source/Modules/d.cxx @@ -1975,7 +1975,7 @@ public: qualified_return = SwigType_rcaststr(returntype, "c_result"); - if (!is_void && !ignored_method) { + if (!is_void && (!ignored_method || pure_virtual)) { if (!SwigType_isclass(returntype)) { if (!(SwigType_ispointer(returntype) || SwigType_isreference(returntype))) { String *construct_result = NewStringf("= SwigValueInit< %s >()", SwigType_lstr(returntype, 0)); @@ -2078,6 +2078,10 @@ public: Delete(super_call); } else { Printf(w->code, "Swig::DirectorPureVirtualException::raise(\"%s::%s\");\n", SwigType_namestr(c_classname), SwigType_namestr(name)); + if (!is_void) + Printf(w->code, "return %s;", qualified_return); + else if (!ignored_method) + Printf(w->code, "return;\n"); } if (!ignored_method) From d02302bd48927def5bb69de2645383968f849c46 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Sat, 13 May 2017 23:18:12 +0100 Subject: [PATCH 104/455] Remove php and perl5 C++11 and C++14 testing on Travis The language headers are not C++11 compatible --- .travis.yml | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/.travis.yml b/.travis.yml index d147114b0..fd70c9160 100644 --- a/.travis.yml +++ b/.travis.yml @@ -232,14 +232,6 @@ matrix: env: SWIGLANG=java SWIG_CC=gcc-5 SWIG_CXX=g++-5 CPP11=1 sudo: required dist: trusty - - os: linux - env: SWIGLANG=perl5 SWIG_CC=gcc-5 SWIG_CXX=g++-5 CPP11=1 - sudo: required - dist: trusty - - os: linux - env: SWIGLANG=php VER=7.1 SWIG_CC=gcc-5 SWIG_CXX=g++-5 CPP11=1 - sudo: required - dist: trusty - os: linux env: SWIGLANG=python SWIG_CC=gcc-5 SWIG_CXX=g++-5 CPP11=1 sudo: required @@ -264,14 +256,6 @@ matrix: env: SWIGLANG=java SWIG_CC=gcc-6 SWIG_CXX=g++-6 CPP14=1 sudo: required dist: trusty - - os: linux - env: SWIGLANG=perl5 SWIG_CC=gcc-6 SWIG_CXX=g++-6 CPP14=1 - sudo: required - dist: trusty - - os: linux - env: SWIGLANG=php VER=7.1 SWIG_CC=gcc-6 SWIG_CXX=g++-6 CPP14=1 - sudo: required - dist: trusty - os: linux env: SWIGLANG=python SWIG_CC=gcc-6 SWIG_CXX=g++-6 CPP14=1 sudo: required From a271043555cdb94759ca12026ca530e782048f0b Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Sun, 14 May 2017 00:39:08 +0100 Subject: [PATCH 105/455] Fix warnings in Java OUTPUT and INOUT typemaps --- Examples/test-suite/java_director_typemaps.i | 2 +- Lib/java/typemaps.i | 36 +++++++++++++++++--- 2 files changed, 33 insertions(+), 5 deletions(-) diff --git a/Examples/test-suite/java_director_typemaps.i b/Examples/test-suite/java_director_typemaps.i index 8d86c59a4..e7bc9a659 100644 --- a/Examples/test-suite/java_director_typemaps.i +++ b/Examples/test-suite/java_director_typemaps.i @@ -185,7 +185,7 @@ public: void etest() { bool boolarg_inout = false; - signed char signed_chararg_inout = 150; + signed char signed_chararg_inout = 111; unsigned char unsigned_chararg_inout = 150; short shortarg_inout = 150; diff --git a/Lib/java/typemaps.i b/Lib/java/typemaps.i index 4170915b3..1785d97ce 100644 --- a/Lib/java/typemaps.i +++ b/Lib/java/typemaps.i @@ -220,14 +220,14 @@ There are no char *OUTPUT typemaps, however you can apply the signed char * type { JNITYPE $1_jvalue; JCALL4(Get##JAVATYPE##ArrayRegion, jenv, $input, 0, 1, &$1_jvalue); - $result = $1_jvalue; + $result = ($*1_ltype)$1_jvalue; } %typemap(directorargout, noblock=1) TYPE *OUTPUT { JNITYPE $1_jvalue; JCALL4(Get##JAVATYPE##ArrayRegion, jenv, $input, 0, 1, &$1_jvalue); - *$result = $1_jvalue; + *$result = ($*1_ltype)$1_jvalue; } %typemap(typecheck) TYPE *OUTPUT = TYPECHECKTYPE; @@ -264,6 +264,21 @@ OUTPUT_TYPEMAP(double, jdouble, double, Double, "[D", jdoubleArray); $1 = &temp; } +%typemap(directorargout, noblock=1) bool &OUTPUT +{ + jboolean $1_jvalue; + JCALL4(GetBooleanArrayRegion, jenv, $input, 0, 1, &$1_jvalue); + $result = $1_jvalue ? true : false; +} + +%typemap(directorargout, noblock=1) bool *OUTPUT +{ + jboolean $1_jvalue; + JCALL4(GetBooleanArrayRegion, jenv, $input, 0, 1, &$1_jvalue); + *$result = $1_jvalue ? true : false; +} + + /* Convert to BigInteger - byte array holds number in 2's complement big endian format */ /* Use first element in BigInteger array for output */ /* Overrides the typemap in the OUTPUT_TYPEMAP macro */ @@ -386,13 +401,13 @@ There are no char *INOUT typemaps, however you can apply the signed char * typem %typemap(directorargout, noblock=1) TYPE &INOUT { JCALL4(Get##JAVATYPE##ArrayRegion, jenv, $input, 0, 1, &$1_jvalue); - $result = $1_jvalue; + $result = ($*1_ltype)$1_jvalue; } %typemap(directorargout, noblock=1) TYPE *INOUT { JCALL4(Get##JAVATYPE##ArrayRegion, jenv, $input, 0, 1, &$1_jvalue); - *$result = $1_jvalue; + *$result = ($*1_ltype)$1_jvalue; } %typemap(typecheck) TYPE *INOUT = TYPECHECKTYPE; @@ -436,6 +451,19 @@ INOUT_TYPEMAP(double, jdouble, double, Double, "[D", jdoubleArray); JCALL3(ReleaseBooleanArrayElements, jenv, $input , (jboolean *)jbtemp$argnum, 0); } +%typemap(directorargout, noblock=1) bool &INOUT +{ + JCALL4(GetBooleanArrayRegion, jenv, $input, 0, 1, &$1_jvalue); + $result = $1_jvalue ? true : false; +} + +%typemap(directorargout, noblock=1) bool *INOUT +{ + JCALL4(GetBooleanArrayRegion, jenv, $input, 0, 1, &$1_jvalue); + *$result = $1_jvalue ? true : false; +} + + /* Override the typemap in the INOUT_TYPEMAP macro for unsigned long long */ %typemap(in) unsigned long long *INOUT ($*1_ltype temp), unsigned long long &INOUT ($*1_ltype temp) { jobject bigint; From 6a3910690bef10fe45d780ad2ba22d393e55d425 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Sun, 14 May 2017 01:07:14 +0100 Subject: [PATCH 106/455] director_exception testcase warning fixes Fixes: 'function assumed not to throw an exception but does' --- Examples/test-suite/director_exception.i | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Examples/test-suite/director_exception.i b/Examples/test-suite/director_exception.i index 0f87fb4ba..1ce14dedf 100644 --- a/Examples/test-suite/director_exception.i +++ b/Examples/test-suite/director_exception.i @@ -35,9 +35,9 @@ class DirectorMethodException: public Swig::DirectorException {}; #ifdef SWIGPHP %feature("director:except") { - if ($error == FAILURE) { - throw Swig::DirectorMethodException(); - } + if ($error == FAILURE) { + Swig::DirectorMethodException::raise("$symname"); + } } %exception { @@ -50,9 +50,9 @@ class DirectorMethodException: public Swig::DirectorException {}; #ifdef SWIGPYTHON %feature("director:except") { - if ($error != NULL) { - throw Swig::DirectorMethodException(); - } + if ($error != NULL) { + Swig::DirectorMethodException::raise("$symname"); + } } %exception { @@ -88,7 +88,7 @@ class DirectorMethodException: public Swig::DirectorException {}; #ifdef SWIGRUBY %feature("director:except") { - throw Swig::DirectorMethodException($error); + Swig::DirectorMethodException::raise($error); } %exception { From 37d90ca3ec5a6edd1c0a83fa9f7ccce66682a5a3 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Mon, 15 May 2017 07:47:22 +0100 Subject: [PATCH 107/455] Appveyor testing- install python-devel package Needed for newer versions of cygwin on Appveyor in order to run Python tests --- appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index ea01db0f8..74b1c045d 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -79,7 +79,7 @@ install: - if "%OSVARIANT%"=="" bash -c "cl.exe /? 2>&1 | head -n 1" - if "%OSVARIANT%"=="" bash -c "which csc.exe" - if "%OSVARIANT%"=="" bash -c "csc.exe /? | head -n 1" -- if "%OSVARIANT%"=="cygwin" %CYGWINSETUP% --quiet-mode --packages libpcre-devel,libboost-devel > cygwin-install.txt || bash -c "cat cygwin-install.txt" +- if "%OSVARIANT%"=="cygwin" %CYGWINSETUP% --quiet-mode --packages python-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" - bash -c "which $CC" - bash -c "which $CXX" From 8f1ae7a8761a239b265ffae905e20f277f3b4283 Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Tue, 16 May 2017 17:51:45 +1200 Subject: [PATCH 108/455] Add CHANGES.current entry for #970 --- CHANGES.current | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGES.current b/CHANGES.current index d6104c02c..aaa2e7c1f 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.0.0 (in progress) =========================== +2017-05-16: nihal95 + [PHP] Add %pragma version directive to allow the version of the + extension to be set. Patch #970, fixes #360. + 2017-05-13: yag00 Patch #975 - Add support for noexcept on director methods. From bb758d7810c833e18b95c7500753e0de2e7c8bfd Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Fri, 19 May 2017 06:58:54 +0100 Subject: [PATCH 109/455] Use %naturalvar for C# std::complex wrappers --- Lib/csharp/std_complex.i | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/Lib/csharp/std_complex.i b/Lib/csharp/std_complex.i index b5bdec60d..323b97a59 100644 --- a/Lib/csharp/std_complex.i +++ b/Lib/csharp/std_complex.i @@ -4,6 +4,8 @@ namespace std { +%naturalvar complex; + // An extremely simplified subset of std::complex<> which contains just the // methods we need. template @@ -19,28 +21,28 @@ public: } // namespace std %define swig_complex_typemaps(T) -%typemap(cstype) std::complex, std::complex*, const std::complex& "System.Numerics.Complex" +%typemap(cstype) std::complex, const std::complex& "System.Numerics.Complex" // The casts in "pre" are needed in order to allow creating std::complex // from System.Numerics.Complex, which always uses doubles. It relies on the // fact that the name of the C++ and C# float/double types are the same. %typemap(csin, pre=" var cpp$csinput = new Complex_" #T "((" #T ")$csinput.Real, (" #T ")$csinput.Imaginary);" - ) std::complex, std::complex*, const std::complex& "Complex_" #T ".getCPtr(cpp$csinput)" + ) std::complex, const std::complex& "Complex_" #T ".getCPtr(cpp$csinput)" %typemap(csout, excode=SWIGEXCODE) std::complex, const std::complex& { Complex_##T cppret = new Complex_##T($imcall, $owner);$excode return new System.Numerics.Complex(cppret.real(), cppret.imag()); } -%typemap(csvarin, excode=SWIGEXCODE2) std::complex*, const std::complex& %{ +%typemap(csvarin, excode=SWIGEXCODE2) const std::complex& %{ set { var cppvalue = new Complex_##T((T)value.Real, (T)value.Imaginary); $imcall;$excode } %} -%typemap(csvarout, excode=SWIGEXCODE2) std::complex*, const std::complex& %{ +%typemap(csvarout, excode=SWIGEXCODE2) const std::complex& %{ get { var cppret = new Complex_##T($imcall, $owner);$excode return new System.Numerics.Complex(cppret.real(), cppret.imag()); From 8c13ee2411aa8d3d822897f831b4c497cddc2cd7 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Fri, 19 May 2017 07:10:43 +0100 Subject: [PATCH 110/455] C# std::complex wrappers SwigValueWrapper fix Fix std::complex constructor declaration to stop SwigValueWrapper from being generated --- Lib/csharp/std_complex.i | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib/csharp/std_complex.i b/Lib/csharp/std_complex.i index 323b97a59..ac30e1692 100644 --- a/Lib/csharp/std_complex.i +++ b/Lib/csharp/std_complex.i @@ -12,7 +12,7 @@ template class complex { public: - complex(T re, T im); + complex(T re = T(), T im = T()); T real() const; T imag() const; From e11e1c4cb8fc9be7f46160ba52cdad8acc433ea7 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Fri, 19 May 2017 08:15:01 +0100 Subject: [PATCH 111/455] C# std::complex wrappers marshalling by value Change the wrapping to marshall directly to the .net System.Numerics.Complex type instead of using an intermediate std::complex .net type. --- Lib/csharp/std_complex.i | 57 ++++++++++++++++++++++++---------------- 1 file changed, 35 insertions(+), 22 deletions(-) diff --git a/Lib/csharp/std_complex.i b/Lib/csharp/std_complex.i index ac30e1692..0f5b6b921 100644 --- a/Lib/csharp/std_complex.i +++ b/Lib/csharp/std_complex.i @@ -2,54 +2,67 @@ #include %} +%fragment("SwigSystemNumericsComplex", "header") { +// Identical to the layout of System.Numerics.Complex, but does assume that it is +// LayoutKind.Sequential on the managed side +struct SwigSystemNumericsComplex { + double real; + double imag; + SwigSystemNumericsComplex(double r = 0.0, double i = 0.0) : real(r), imag(i) {} +}; +} + namespace std { %naturalvar complex; -// An extremely simplified subset of std::complex<> which contains just the -// methods we need. template class complex { public: complex(T re = T(), T im = T()); - - T real() const; - T imag() const; }; -} // namespace std +} %define swig_complex_typemaps(T) -%typemap(cstype) std::complex, const std::complex& "System.Numerics.Complex" +%typemap(ctype, fragment="SwigSystemNumericsComplex") std::complex, const std::complex & "SwigSystemNumericsComplex" +%typemap(imtype) std::complex, const std::complex & "System.Numerics.Complex" +%typemap(cstype) std::complex, const std::complex & "System.Numerics.Complex" -// The casts in "pre" are needed in order to allow creating std::complex -// from System.Numerics.Complex, which always uses doubles. It relies on the -// fact that the name of the C++ and C# float/double types are the same. -%typemap(csin, - pre=" var cpp$csinput = new Complex_" #T "((" #T ")$csinput.Real, (" #T ")$csinput.Imaginary);" - ) std::complex, const std::complex& "Complex_" #T ".getCPtr(cpp$csinput)" +%typemap(in) std::complex($*1_ltype temp), const std::complex &($*1_ltype temp) +%{temp = std::complex< double >($input.real, $input.imag); + $1 = &temp;%} -%typemap(csout, excode=SWIGEXCODE) std::complex, const std::complex& { - Complex_##T cppret = new Complex_##T($imcall, $owner);$excode - return new System.Numerics.Complex(cppret.real(), cppret.imag()); +%typemap(out) std::complex +%{$result = SwigSystemNumericsComplex($1.real(), $1.imag());%} + +%typemap(out) const std::complex & +%{$result = SwigSystemNumericsComplex($1->real(), $1->imag());%} + +%typemap(cstype) std::complex, const std::complex & "System.Numerics.Complex" + +%typemap(csin) std::complex, const std::complex & "$csinput" + +%typemap(csout, excode=SWIGEXCODE) std::complex, const std::complex & { + System.Numerics.Complex ret = $imcall;$excode + return ret; } -%typemap(csvarin, excode=SWIGEXCODE2) const std::complex& %{ +%typemap(csvarin, excode=SWIGEXCODE2) const std::complex & %{ set { - var cppvalue = new Complex_##T((T)value.Real, (T)value.Imaginary); $imcall;$excode } %} -%typemap(csvarout, excode=SWIGEXCODE2) const std::complex& %{ +%typemap(csvarout, excode=SWIGEXCODE2) const std::complex & %{ get { - var cppret = new Complex_##T($imcall, $owner);$excode - return new System.Numerics.Complex(cppret.real(), cppret.imag()); + System.Numerics.Complex ret = $imcall;$excode + return ret; } %} -%template(Complex_##T) std::complex; +%template() std::complex; %enddef // By default, typemaps for both std::complex and std::complex From 57ec5ec056b3e0b806a3e46d822354486cd94f78 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Fri, 19 May 2017 19:52:39 +0100 Subject: [PATCH 112/455] Fix linkage problems in C# std::complex wrappers Fix warnings and subsequent exception trying to use wrappers: Warning C4190: 'CSharp_complextestNamespace_VectorStdCplx_getitemcopy' has C-linkage specified, but returns UDT 'SwigSystemNumericsComplex' which is incompatible with C Rename swig_complex_typemaps macro to SWIG_COMPLEX_TYPEMAPS --- Lib/csharp/std_complex.i | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/Lib/csharp/std_complex.i b/Lib/csharp/std_complex.i index 0f5b6b921..960a4b9b4 100644 --- a/Lib/csharp/std_complex.i +++ b/Lib/csharp/std_complex.i @@ -3,15 +3,23 @@ %} %fragment("SwigSystemNumericsComplex", "header") { +extern "C" { // Identical to the layout of System.Numerics.Complex, but does assume that it is // LayoutKind.Sequential on the managed side struct SwigSystemNumericsComplex { double real; double imag; - SwigSystemNumericsComplex(double r = 0.0, double i = 0.0) : real(r), imag(i) {} }; } +SWIGINTERN SwigSystemNumericsComplex SwigCreateSystemNumericsComplex(double real, double imag) { + SwigSystemNumericsComplex cpx; + cpx.real = real; + cpx.imag = imag; + return cpx; +} +} + namespace std { %naturalvar complex; @@ -25,7 +33,7 @@ public: } -%define swig_complex_typemaps(T) +%define SWIG_COMPLEX_TYPEMAPS(T) %typemap(ctype, fragment="SwigSystemNumericsComplex") std::complex, const std::complex & "SwigSystemNumericsComplex" %typemap(imtype) std::complex, const std::complex & "System.Numerics.Complex" %typemap(cstype) std::complex, const std::complex & "System.Numerics.Complex" @@ -34,11 +42,11 @@ public: %{temp = std::complex< double >($input.real, $input.imag); $1 = &temp;%} -%typemap(out) std::complex -%{$result = SwigSystemNumericsComplex($1.real(), $1.imag());%} +%typemap(out, null="SwigCreateSystemNumericsComplex(0.0, 0.0)") std::complex +%{$result = SwigCreateSystemNumericsComplex($1.real(), $1.imag());%} -%typemap(out) const std::complex & -%{$result = SwigSystemNumericsComplex($1->real(), $1->imag());%} +%typemap(out, null="SwigCreateSystemNumericsComplex(0.0, 0.0)") const std::complex & +%{$result = SwigCreateSystemNumericsComplex($1->real(), $1->imag());%} %typemap(cstype) std::complex, const std::complex & "System.Numerics.Complex" @@ -69,9 +77,9 @@ public: // are defined, but one of them can be disabled by predefining the // corresponding symbol before including this file. #ifndef SWIG_NO_STD_COMPLEX_DOUBLE -swig_complex_typemaps(double) +SWIG_COMPLEX_TYPEMAPS(double) #endif #ifndef SWIG_NO_STD_COMPLEX_FLOAT -swig_complex_typemaps(float) +SWIG_COMPLEX_TYPEMAPS(float) #endif From fb941315c1247696b69b9188104d73afca285a08 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Fri, 19 May 2017 20:24:49 +0100 Subject: [PATCH 113/455] Add header to std_complex.i --- Lib/csharp/std_complex.i | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Lib/csharp/std_complex.i b/Lib/csharp/std_complex.i index 960a4b9b4..e69d17067 100644 --- a/Lib/csharp/std_complex.i +++ b/Lib/csharp/std_complex.i @@ -1,3 +1,10 @@ +/* ----------------------------------------------------------------------------- + * std_complex.i + * + * Typemaps for handling std::complex and std::complex as a .NET + * System.Numerics.Complex type. Requires .NET 4 minimum. + * ----------------------------------------------------------------------------- */ + %{ #include %} From ed54cc904c4f85eaf1ceb18278c02049784218de Mon Sep 17 00:00:00 2001 From: Julien Schueller Date: Fri, 19 May 2017 17:16:08 +0200 Subject: [PATCH 114/455] Fix E731: do not assign a lambda expression https://www.python.org/dev/peps/pep-0008/#programming-recommendations --- Source/Modules/python.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Modules/python.cxx b/Source/Modules/python.cxx index 2248ba920..40a2d0f40 100644 --- a/Source/Modules/python.cxx +++ b/Source/Modules/python.cxx @@ -5033,7 +5033,7 @@ public: Printv(f_shadow, tab4, "__swig_destroy__ = ", module, ".", Swig_name_destroy(NSPACE_TODO, symname), "\n", NIL); if (!have_pythonprepend(n) && !have_pythonappend(n)) { if (proxydel) { - Printv(f_shadow, tab4, "__del__ = lambda self: None\n", NIL); + Printv(f_shadow, tab4, "def __del__(self):\n", tab8, "return None\n", NIL); } return SWIG_OK; } From 10172161bfc6728ea5719f30657ddbfed0e06bfa Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Sat, 20 May 2017 15:38:38 +0100 Subject: [PATCH 115/455] Update STL library documentation --- Doc/Manual/Library.html | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/Doc/Manual/Library.html b/Doc/Manual/Library.html index 4bad9a03e..a800c2d73 100644 --- a/Doc/Manual/Library.html +++ b/Doc/Manual/Library.html @@ -1385,16 +1385,24 @@ The following table shows which C++ classes are supported and the equivalent SWI SWIG Interface library file + std::array (C++11) array std_array.i std::auto_ptr memory std_auto_ptr.i + std::complex complex std_complex.i std::deque deque std_deque.i std::list list std_list.i std::map map std_map.i + std::multimap (C++11) multimap std_multimap.i + std::multiset (C++11) multiset std_multiset.i std::pair utility std_pair.i std::set set std_set.i std::string string std_string.i + std::unordered_map (C++11) unordered_map std_unordered_map.i + std::unordered_multimap (C++11) unordered_multimap std_unordered_multimap.i + std::unordered_multiset (C++11) unordered_multiset std_unordered_multiset.i + std::unordered_set (C++11) unordered_set std_unordered_set.i std::vector vector std_vector.i - std::array array (C++11) std_array.i - std::shared_ptr shared_ptr (C++11) std_shared_ptr.i + std::wstring wstring std_wstring.i + std::shared_ptr (C++11) shared_ptr std_shared_ptr.i From 3e47ed56144c536a4cfc8b8d5be8185cb724e1c3 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Sat, 20 May 2017 15:54:27 +0100 Subject: [PATCH 116/455] changes file update --- CHANGES.current | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/CHANGES.current b/CHANGES.current index 04dc7313f..c85c15335 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.0.0 (in progress) =========================== +2017-05-20: jschueller + [Python] #991 Fix E731 PEP8 warning: do not assign a lambda expression + 2017-05-16: nihal95 [PHP] Add %pragma version directive to allow the version of the extension to be set. Patch #970, fixes #360. @@ -43,7 +46,7 @@ Version 4.0.0 (in progress) on VALUE obj. 2017-03-17: vadz - [C#] Add support for std::complex + [C#] #947 Add support for std::complex 2017-03-17: wsfulton [Go] Fix handling of typedef'd function pointers and typedef'd member function pointers From 81ba06e59eda4a14b29695f4d2ecbbd377b6f051 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Sat, 20 May 2017 23:57:15 +0100 Subject: [PATCH 117/455] Fix Python negative unsigned default values Closes #993 --- CHANGES.current | 4 ++++ Examples/test-suite/default_args.i | 3 +++ Examples/test-suite/python/default_args_runme.py | 2 ++ Source/Modules/python.cxx | 2 ++ 4 files changed, 11 insertions(+) diff --git a/CHANGES.current b/CHANGES.current index c85c15335..8a3bb9ce7 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.0.0 (in progress) =========================== +2017-05-21: wsfulton + [Python] #993 Fix handling of default -ve unsigned values, such as: + void f(unsigned = -1U); + 2017-05-20: jschueller [Python] #991 Fix E731 PEP8 warning: do not assign a lambda expression diff --git a/Examples/test-suite/default_args.i b/Examples/test-suite/default_args.i index 39b499cf4..8828bfe04 100644 --- a/Examples/test-suite/default_args.i +++ b/Examples/test-suite/default_args.i @@ -156,6 +156,9 @@ int double_if_handle_is_null(int n, MyHandle h = 0) { return h ? n : 2*n; } int double_if_dbl_ptr_is_null(int n, double* null_by_default) { return null_by_default ? n : 2*n; } + + void defaulted1(unsigned offset = -1U) {} // minus unsigned! + void defaulted2(int offset = -1U) {} // minus unsigned! }; int Foo::bar = 1; int Foo::spam = 2; diff --git a/Examples/test-suite/python/default_args_runme.py b/Examples/test-suite/python/default_args_runme.py index 9d275e4a1..b7c4cb508 100644 --- a/Examples/test-suite/python/default_args_runme.py +++ b/Examples/test-suite/python/default_args_runme.py @@ -32,6 +32,8 @@ def run(module_name): f.newname() f.newname(1) + f.defaulted1() + f.defaulted2() if f.double_if_void_ptr_is_null(2, None) != 4: raise RuntimeError diff --git a/Source/Modules/python.cxx b/Source/Modules/python.cxx index 40a2d0f40..cf81827cb 100644 --- a/Source/Modules/python.cxx +++ b/Source/Modules/python.cxx @@ -2115,6 +2115,8 @@ public: case 'u': case 'U': + if (value < 0) + fail = true; break; default: From b90a8d7444360abbc338875eb69b52cfb2972b5a Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Sun, 21 May 2017 17:28:13 +0100 Subject: [PATCH 118/455] Remove unnecessary dynamic_cast in C#/D/Java directors Also revert the removal of dynamic_cast in the csdowncast feature. --- CHANGES.current | 4 ++++ Source/Modules/csharp.cxx | 10 +++------- Source/Modules/d.cxx | 6 ++---- Source/Modules/java.cxx | 14 +++++--------- 4 files changed, 14 insertions(+), 20 deletions(-) diff --git a/CHANGES.current b/CHANGES.current index 8a3bb9ce7..70439b221 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.0.0 (in progress) =========================== +2017-05-21: Sghirate + [Java, C#, D] #449 Remove unnecessary use of dynamic_cast in directors to enable + non-RTTI compilation. + 2017-05-21: wsfulton [Python] #993 Fix handling of default -ve unsigned values, such as: void f(unsigned = -1U); diff --git a/Source/Modules/csharp.cxx b/Source/Modules/csharp.cxx index bbc1b8ac6..fc682365c 100644 --- a/Source/Modules/csharp.cxx +++ b/Source/Modules/csharp.cxx @@ -2225,7 +2225,7 @@ public: Printf(dcast_wrap->code, " Swig::Director *director = (Swig::Director *) 0;\n"); Printf(dcast_wrap->code, " jobject jresult = (jobject) 0;\n"); Printf(dcast_wrap->code, " %s *obj = *((%s **)&jCPtrBase);\n", norm_name, norm_name); - Printf(dcast_wrap->code, " if (obj) director = static_cast(obj);\n"); + Printf(dcast_wrap->code, " if (obj) director = dynamic_cast(obj);\n"); Printf(dcast_wrap->code, " if (director) jresult = director->swig_get_self(jenv);\n"); Printf(dcast_wrap->code, " return jresult;\n"); Printf(dcast_wrap->code, "}\n"); @@ -3735,15 +3735,12 @@ public: Printf(code_wrap->code, " // Keep a local instance of the smart pointer around while we are using the raw pointer\n"); Printf(code_wrap->code, " // Avoids using smart pointer specific API.\n"); Printf(code_wrap->code, " %s *director = static_cast<%s *>(obj->operator->());\n", dirClassName, dirClassName); - } - else { + } else { Printf(code_wrap->code, " %s *obj = (%s *)objarg;\n", norm_name, norm_name); Printf(code_wrap->code, " %s *director = static_cast<%s *>(obj);\n", dirClassName, dirClassName); } - // TODO: if statement not needed?? - Java too - Printf(code_wrap->code, " if (director) {\n"); - Printf(code_wrap->code, " director->swig_connect_director("); + Printf(code_wrap->code, " director->swig_connect_director("); for (int i = first_class_dmethod; i < curr_class_dmethod; ++i) { UpcallData *udata = Getitem(dmethods_seq, i); @@ -3760,7 +3757,6 @@ public: Printf(code_wrap->def, ") {\n"); Printf(code_wrap->code, ");\n"); Printf(imclass_class_code, ");\n"); - Printf(code_wrap->code, " }\n"); Printf(code_wrap->code, "}\n"); Wrapper_print(code_wrap, f_wrappers); diff --git a/Source/Modules/d.cxx b/Source/Modules/d.cxx index dd0fc371f..9a64543c3 100644 --- a/Source/Modules/d.cxx +++ b/Source/Modules/d.cxx @@ -3567,10 +3567,9 @@ private: Printf(code_wrap->def, "SWIGEXPORT void D_%s(void *objarg, void *dobj", connect_name); Printf(code_wrap->code, " %s *obj = (%s *)objarg;\n", norm_name, norm_name); - Printf(code_wrap->code, " %s *director = dynamic_cast<%s *>(obj);\n", dirClassName, dirClassName); + Printf(code_wrap->code, " %s *director = static_cast<%s *>(obj);\n", dirClassName, dirClassName); - Printf(code_wrap->code, " if (director) {\n"); - Printf(code_wrap->code, " director->swig_connect_director(dobj"); + Printf(code_wrap->code, " director->swig_connect_director(dobj"); for (int i = first_class_dmethod; i < curr_class_dmethod; ++i) { UpcallData *udata = Getitem(dmethods_seq, i); @@ -3584,7 +3583,6 @@ private: Printf(code_wrap->def, ") {\n"); Printf(code_wrap->code, ");\n"); Printf(im_dmodule_code, ") %s;\n", connect_name); - Printf(code_wrap->code, " }\n"); Printf(code_wrap->code, "}\n"); Wrapper_print(code_wrap, f_wrappers); diff --git a/Source/Modules/java.cxx b/Source/Modules/java.cxx index e53cf1576..75fe61c2b 100644 --- a/Source/Modules/java.cxx +++ b/Source/Modules/java.cxx @@ -3760,18 +3760,16 @@ public: Printf(code_wrap->code, " (void)jcls;\n"); Printf(code_wrap->code, " // Keep a local instance of the smart pointer around while we are using the raw pointer\n"); Printf(code_wrap->code, " // Avoids using smart pointer specific API.\n"); - Printf(code_wrap->code, " %s *director = dynamic_cast<%s *>(obj->operator->());\n", dirClassName, dirClassName); + Printf(code_wrap->code, " %s *director = static_cast<%s *>(obj->operator->());\n", dirClassName, dirClassName); } else { Printf(code_wrap->code, " %s *obj = *((%s **)&objarg);\n", norm_name, norm_name); Printf(code_wrap->code, " (void)jcls;\n"); - Printf(code_wrap->code, " %s *director = dynamic_cast<%s *>(obj);\n", dirClassName, dirClassName); + Printf(code_wrap->code, " %s *director = static_cast<%s *>(obj);\n", dirClassName, dirClassName); } - Printf(code_wrap->code, " if (director) {\n"); - Printf(code_wrap->code, " director->swig_connect_director(jenv, jself, jenv->GetObjectClass(jself), " + Printf(code_wrap->code, " director->swig_connect_director(jenv, jself, jenv->GetObjectClass(jself), " "(jswig_mem_own == JNI_TRUE), (jweak_global == JNI_TRUE));\n"); - Printf(code_wrap->code, " }\n"); Printf(code_wrap->code, "}\n"); Wrapper_print(code_wrap, f_wrappers); @@ -3791,11 +3789,9 @@ public: "SWIGEXPORT void JNICALL Java_%s%s_%s(JNIEnv *jenv, jclass jcls, jobject jself, jlong objarg, jboolean jtake_or_release) {\n", jnipackage, jni_imclass_name, changeown_jnimethod_name); Printf(code_wrap->code, " %s *obj = *((%s **)&objarg);\n", norm_name, norm_name); - Printf(code_wrap->code, " %s *director = dynamic_cast<%s *>(obj);\n", dirClassName, dirClassName); + Printf(code_wrap->code, " %s *director = static_cast<%s *>(obj);\n", dirClassName, dirClassName); Printf(code_wrap->code, " (void)jcls;\n"); - Printf(code_wrap->code, " if (director) {\n"); - Printf(code_wrap->code, " director->swig_java_change_ownership(jenv, jself, jtake_or_release ? true : false);\n"); - Printf(code_wrap->code, " }\n"); + Printf(code_wrap->code, " director->swig_java_change_ownership(jenv, jself, jtake_or_release ? true : false);\n"); Printf(code_wrap->code, "}\n"); Wrapper_print(code_wrap, f_wrappers); From 05badeb1a4f5f743aa525d2e262c670bd745f544 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Sun, 21 May 2017 17:38:38 +0100 Subject: [PATCH 119/455] Remove undocumented features used in directors The jsdowncast and csdowncast features are not documented and I think these are a relic of something that was never finished. --- Source/Modules/csharp.cxx | 31 ------------------------------- Source/Modules/java.cxx | 33 --------------------------------- 2 files changed, 64 deletions(-) diff --git a/Source/Modules/csharp.cxx b/Source/Modules/csharp.cxx index fc682365c..7b1fca071 100644 --- a/Source/Modules/csharp.cxx +++ b/Source/Modules/csharp.cxx @@ -2207,37 +2207,6 @@ public: --nesting_depth; } - /* Output the downcast method, if necessary. Note: There's no other really - good place to put this code, since Abstract Base Classes (ABCs) can and should have - downcasts, making the constructorHandler() a bad place (because ABCs don't get to - have constructors emitted.) */ - if (GetFlag(n, "feature:csdowncast")) { - String *downcast_method = Swig_name_member(getNSpace(), proxy_class_name, "SWIGDowncast"); - String *wname = Swig_name_wrapper(downcast_method); - - String *norm_name = SwigType_namestr(Getattr(n, "name")); - - Printf(imclass_class_code, " public final static native %s %s(long cPtrBase, boolean cMemoryOwn);\n", proxy_class_name, downcast_method); - - Wrapper *dcast_wrap = NewWrapper(); - - Printf(dcast_wrap->def, "SWIGEXPORT jobject SWIGSTDCALL %s(JNIEnv *jenv, jclass jcls, jlong jCPtrBase, jboolean cMemoryOwn) {", wname); - Printf(dcast_wrap->code, " Swig::Director *director = (Swig::Director *) 0;\n"); - Printf(dcast_wrap->code, " jobject jresult = (jobject) 0;\n"); - Printf(dcast_wrap->code, " %s *obj = *((%s **)&jCPtrBase);\n", norm_name, norm_name); - Printf(dcast_wrap->code, " if (obj) director = dynamic_cast(obj);\n"); - Printf(dcast_wrap->code, " if (director) jresult = director->swig_get_self(jenv);\n"); - Printf(dcast_wrap->code, " return jresult;\n"); - Printf(dcast_wrap->code, "}\n"); - - Wrapper_print(dcast_wrap, f_wrappers); - DelWrapper(dcast_wrap); - - Delete(norm_name); - Delete(wname); - Delete(downcast_method); - } - if (f_interface) { Printv(f_interface, interface_class_code, "}\n", NIL); addCloseNamespace(nspace, f_interface); diff --git a/Source/Modules/java.cxx b/Source/Modules/java.cxx index 75fe61c2b..bd6e005d2 100644 --- a/Source/Modules/java.cxx +++ b/Source/Modules/java.cxx @@ -2272,39 +2272,6 @@ public: --nesting_depth; } - /* Output the downcast method, if necessary. Note: There's no other really - good place to put this code, since Abstract Base Classes (ABCs) can and should have - downcasts, making the constructorHandler() a bad place (because ABCs don't get to - have constructors emitted.) */ - if (GetFlag(n, "feature:javadowncast")) { - String *downcast_method = Swig_name_member(getNSpace(), getClassPrefix(), "SWIGDowncast"); - String *jniname = makeValidJniName(downcast_method); - String *wname = Swig_name_wrapper(jniname); - - String *norm_name = SwigType_namestr(Getattr(n, "name")); - - Printf(imclass_class_code, " public final static native %s %s(long cPtrBase, boolean cMemoryOwn);\n", proxy_class_name, downcast_method); - - Wrapper *dcast_wrap = NewWrapper(); - - Printf(dcast_wrap->def, "SWIGEXPORT jobject JNICALL %s(JNIEnv *jenv, jclass jcls, jlong jCPtrBase, jboolean cMemoryOwn) {", wname); - Printf(dcast_wrap->code, " Swig::Director *director = (Swig::Director *) 0;\n"); - Printf(dcast_wrap->code, " jobject jresult = (jobject) 0;\n"); - Printf(dcast_wrap->code, " %s *obj = *((%s **)&jCPtrBase);\n", norm_name, norm_name); - Printf(dcast_wrap->code, " if (obj) director = dynamic_cast(obj);\n"); - Printf(dcast_wrap->code, " if (director) jresult = director->swig_get_self(jenv);\n"); - Printf(dcast_wrap->code, " return jresult;\n"); - Printf(dcast_wrap->code, "}\n"); - - Wrapper_print(dcast_wrap, f_wrappers); - DelWrapper(dcast_wrap); - - Delete(norm_name); - Delete(wname); - Delete(jniname); - Delete(downcast_method); - } - if (f_interface) { Printv(f_interface, interface_class_code, "}\n", NIL); Delete(f_interface); From 98e67539ddbebc7461b2ece58149ac123e7a4835 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Mon, 22 May 2017 19:15:39 +0100 Subject: [PATCH 120/455] Director testcase cosmetic fixes --- .../test-suite/li_boost_shared_ptr_director.i | 8 ++--- Lib/java/boost_shared_ptr.i | 29 +++++++++++++++++++ Lib/java/java.swg | 2 +- 3 files changed, 34 insertions(+), 5 deletions(-) diff --git a/Examples/test-suite/li_boost_shared_ptr_director.i b/Examples/test-suite/li_boost_shared_ptr_director.i index 4acfa1a5d..8f36bf31c 100644 --- a/Examples/test-suite/li_boost_shared_ptr_director.i +++ b/Examples/test-suite/li_boost_shared_ptr_director.i @@ -10,14 +10,14 @@ %inline %{ struct C { - C() : m(1) {}; - C(int n) : m(n) {}; - int get_m() { return m; }; + C() : m(1) {} + C(int n) : m(n) {} + int get_m() { return m; } int m; }; struct Base { - Base() {}; + Base() {} virtual boost::shared_ptr ret_c_shared_ptr() = 0; virtual C ret_c_by_value() = 0; virtual int take_c_by_value(C c) = 0; diff --git a/Lib/java/boost_shared_ptr.i b/Lib/java/boost_shared_ptr.i index 33da61bf8..699a8a0a0 100644 --- a/Lib/java/boost_shared_ptr.i +++ b/Lib/java/boost_shared_ptr.i @@ -156,6 +156,10 @@ CPTR_VISIBILITY static long getCPtr($javaclassname obj) { return (obj == null) ? 0 : obj.swigCPtr; } + + CPTR_VISIBILITY void swigSetCMemOwn(boolean own) { + swigCMemOwn = own; + } %} // Derived proxy classes @@ -172,6 +176,11 @@ CPTR_VISIBILITY static long getCPtr($javaclassname obj) { return (obj == null) ? 0 : obj.swigCPtr; } + + CPTR_VISIBILITY void swigSetCMemOwn(boolean own) { + swigCMemOwnDerived = own; + super.swigSetCMemOwn(own); + } %} %typemap(javadestruct, methodname="delete", methodmodifiers="public synchronized") TYPE { @@ -195,6 +204,26 @@ super.delete(); } +%typemap(directordisconnect, methodname="swigDirectorDisconnect") TYPE %{ + protected void $methodname() { + swigSetCMemOwn(false); + $jnicall; + } +%} + +%typemap(directorowner_release, methodname="swigReleaseOwnership") TYPE %{ + public void $methodname() { + swigSetCMemOwn(false); + $jnicall; + } +%} + +%typemap(directorowner_take, methodname="swigTakeOwnership") TYPE %{ + public void $methodname() { + swigSetCMemOwn(true); + $jnicall; + } +%} %template() SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >; %enddef diff --git a/Lib/java/java.swg b/Lib/java/java.swg index 2ca426675..60ab7b049 100644 --- a/Lib/java/java.swg +++ b/Lib/java/java.swg @@ -1260,7 +1260,7 @@ SWIG_JAVABODY_TYPEWRAPPER(protected, protected, protected, SWIGTYPE) */ %define SWIG_PROXY_CONSTRUCTOR(OWNERSHIP, WEAKREF, TYPENAME...) -%typemap(javaconstruct,directorconnect="\n $imclassname.$javaclazznamedirector_connect(this, swigCPtr, swigCMemOwn, WEAKREF);") TYPENAME { +%typemap(javaconstruct,directorconnect="\n $imclassname.$javaclazznamedirector_connect(this, swigCPtr, OWNERSHIP, WEAKREF);") TYPENAME { this($imcall, OWNERSHIP);$directorconnect } %enddef From 41db45beff36a8f1391f3fa4be0ae6337df04dea Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Mon, 22 May 2017 19:33:20 +0100 Subject: [PATCH 121/455] director runtime test for java --- .../li_boost_shared_ptr_director_runme.java | 60 +++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 Examples/test-suite/java/li_boost_shared_ptr_director_runme.java diff --git a/Examples/test-suite/java/li_boost_shared_ptr_director_runme.java b/Examples/test-suite/java/li_boost_shared_ptr_director_runme.java new file mode 100644 index 000000000..904eab387 --- /dev/null +++ b/Examples/test-suite/java/li_boost_shared_ptr_director_runme.java @@ -0,0 +1,60 @@ +public class li_boost_shared_ptr_runme { + + static { + try { + System.loadLibrary("li_boost_shared_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 check(String got, String expected) { + if (!got.equals(expected)) + throw new RuntimeException("Failed, got: " + got + " expected: " + expected); + } + + public static void main(String argv[]) { + li_boost_shared_ptr_director_Derived a = li_boost_shared_ptr_director_Derived.new(false); + li_boost_shared_ptr_director_Derived b = li_boost_shared_ptr_director_Derived.new(true); + + check(call_ret_c_shared_ptr(a) == 1); + check(call_ret_c_shared_ptr(b) == -1); + check(call_ret_c_by_value(a) == 1); + + check(call_take_c_by_value(a) == 5); + check(call_take_c_shared_ptr_by_value(a) == 6); + check(call_take_c_shared_ptr_by_ref(a) == 7); + check(call_take_c_shared_ptr_by_pointer(a) == 8); + check(call_take_c_shared_ptr_by_pointer_ref(a) == 9); + + check(call_take_c_shared_ptr_by_value_with_null(a) == -2); + check(call_take_c_shared_ptr_by_ref_with_null(a) == -3); + check(call_take_c_shared_ptr_by_pointer_with_null(a) == -4); + check(call_take_c_shared_ptr_by_pointer_ref_with_null(a) == -5); + + } +} + +class li_boost_shared_ptr_director_Derived extends li_boost_shared_ptr_director.Base { + + @Override + public String ping() { + return "li_boost_shared_ptr_director_MyBarFoo.ping()"; + } + + @Override + public String pong() { + return "li_boost_shared_ptr_director_MyBarFoo.pong();" + ping(); + } + + @Override + public String upcall(li_boost_shared_ptr_director.FooBar fooBarPtr) { + return "override;" + fooBarPtr.FooBarDo(); + } + + @Override + public li_boost_shared_ptr_director.Foo makeFoo() { + return new li_boost_shared_ptr_director.Foo(); + } +} From 4bf607589f821092f45742ef85b58b4818b60ab4 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Tue, 23 May 2017 20:56:15 +0100 Subject: [PATCH 122/455] Fix Java shared_ptr and directors for derived classes java compilation error. For shared_ptr proxy proxy classes, add a protected method swigSetCMemOwn for modifying the swigCMemOwn and swigCMemOwnDerived member variables which are used by various other methods for controlling memory ownership. Closes #230 Closes #759 --- CHANGES.current | 8 +++ Examples/test-suite/director_smartptr.i | 8 ++- .../java/director_smartptr_runme.java | 29 +++++++++ .../li_boost_shared_ptr_director_runme.java | 60 +++++++++++++++++++ .../test-suite/li_boost_shared_ptr_director.i | 8 +-- Lib/java/boost_shared_ptr.i | 29 +++++++++ Lib/java/java.swg | 2 +- 7 files changed, 138 insertions(+), 6 deletions(-) create mode 100644 Examples/test-suite/java/li_boost_shared_ptr_director_runme.java diff --git a/CHANGES.current b/CHANGES.current index 70439b221..cd91b3607 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.0.0 (in progress) =========================== +2017-05-23: wsfulton + [Java] #230 #759 Fix Java shared_ptr and directors for derived classes java compilation + error. + + For shared_ptr proxy proxy classes, add a protected method swigSetCMemOwn for modifying + the swigCMemOwn and swigCMemOwnDerived member variables which are used by various other + methods for controlling memory ownership. + 2017-05-21: Sghirate [Java, C#, D] #449 Remove unnecessary use of dynamic_cast in directors to enable non-RTTI compilation. diff --git a/Examples/test-suite/director_smartptr.i b/Examples/test-suite/director_smartptr.i index 9d0be80f0..d016af17e 100644 --- a/Examples/test-suite/director_smartptr.i +++ b/Examples/test-suite/director_smartptr.i @@ -44,7 +44,6 @@ public: %include %shared_ptr(Foo) - %feature("director") Foo; class FooBar { @@ -72,5 +71,12 @@ public: static Foo* get_self(Foo *self_); }; +%shared_ptr(FooDerived) +%feature("director") FooDerived; + +%inline %{ +struct FooDerived : Foo { +}; +%} #endif diff --git a/Examples/test-suite/java/director_smartptr_runme.java b/Examples/test-suite/java/director_smartptr_runme.java index 710ece710..ba2bfc8c4 100644 --- a/Examples/test-suite/java/director_smartptr_runme.java +++ b/Examples/test-suite/java/director_smartptr_runme.java @@ -33,6 +33,12 @@ public class director_smartptr_runme { director_smartptr.Foo myFoo2 = new director_smartptr.Foo().makeFoo(); check(myFoo2.pong(), "Foo::pong();Foo::ping()"); check(director_smartptr.Foo.callPong(myFoo2), "Foo::pong();Foo::ping()"); + + director_smartptr.FooDerived myBarFooDerived = new director_smartptr_MyBarFooDerived(); + check(myBarFooDerived.ping(), "director_smartptr_MyBarFooDerived.ping()"); + check(director_smartptr.FooDerived.callPong(myBarFooDerived), "director_smartptr_MyBarFooDerived.pong();director_smartptr_MyBarFooDerived.ping()"); + check(director_smartptr.FooDerived.callUpcall(myBarFooDerived, fooBar), "overrideDerived;Bar::Foo2::Foo2Bar()"); + } } @@ -58,3 +64,26 @@ class director_smartptr_MyBarFoo extends director_smartptr.Foo { return new director_smartptr.Foo(); } } + +class director_smartptr_MyBarFooDerived extends director_smartptr.FooDerived { + + @Override + public String ping() { + return "director_smartptr_MyBarFooDerived.ping()"; + } + + @Override + public String pong() { + return "director_smartptr_MyBarFooDerived.pong();" + ping(); + } + + @Override + public String upcall(director_smartptr.FooBar fooBarPtr) { + return "overrideDerived;" + fooBarPtr.FooBarDo(); + } + + @Override + public director_smartptr.Foo makeFoo() { + return new director_smartptr.Foo(); + } +} diff --git a/Examples/test-suite/java/li_boost_shared_ptr_director_runme.java b/Examples/test-suite/java/li_boost_shared_ptr_director_runme.java new file mode 100644 index 000000000..904eab387 --- /dev/null +++ b/Examples/test-suite/java/li_boost_shared_ptr_director_runme.java @@ -0,0 +1,60 @@ +public class li_boost_shared_ptr_runme { + + static { + try { + System.loadLibrary("li_boost_shared_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 check(String got, String expected) { + if (!got.equals(expected)) + throw new RuntimeException("Failed, got: " + got + " expected: " + expected); + } + + public static void main(String argv[]) { + li_boost_shared_ptr_director_Derived a = li_boost_shared_ptr_director_Derived.new(false); + li_boost_shared_ptr_director_Derived b = li_boost_shared_ptr_director_Derived.new(true); + + check(call_ret_c_shared_ptr(a) == 1); + check(call_ret_c_shared_ptr(b) == -1); + check(call_ret_c_by_value(a) == 1); + + check(call_take_c_by_value(a) == 5); + check(call_take_c_shared_ptr_by_value(a) == 6); + check(call_take_c_shared_ptr_by_ref(a) == 7); + check(call_take_c_shared_ptr_by_pointer(a) == 8); + check(call_take_c_shared_ptr_by_pointer_ref(a) == 9); + + check(call_take_c_shared_ptr_by_value_with_null(a) == -2); + check(call_take_c_shared_ptr_by_ref_with_null(a) == -3); + check(call_take_c_shared_ptr_by_pointer_with_null(a) == -4); + check(call_take_c_shared_ptr_by_pointer_ref_with_null(a) == -5); + + } +} + +class li_boost_shared_ptr_director_Derived extends li_boost_shared_ptr_director.Base { + + @Override + public String ping() { + return "li_boost_shared_ptr_director_MyBarFoo.ping()"; + } + + @Override + public String pong() { + return "li_boost_shared_ptr_director_MyBarFoo.pong();" + ping(); + } + + @Override + public String upcall(li_boost_shared_ptr_director.FooBar fooBarPtr) { + return "override;" + fooBarPtr.FooBarDo(); + } + + @Override + public li_boost_shared_ptr_director.Foo makeFoo() { + return new li_boost_shared_ptr_director.Foo(); + } +} diff --git a/Examples/test-suite/li_boost_shared_ptr_director.i b/Examples/test-suite/li_boost_shared_ptr_director.i index 4acfa1a5d..8f36bf31c 100644 --- a/Examples/test-suite/li_boost_shared_ptr_director.i +++ b/Examples/test-suite/li_boost_shared_ptr_director.i @@ -10,14 +10,14 @@ %inline %{ struct C { - C() : m(1) {}; - C(int n) : m(n) {}; - int get_m() { return m; }; + C() : m(1) {} + C(int n) : m(n) {} + int get_m() { return m; } int m; }; struct Base { - Base() {}; + Base() {} virtual boost::shared_ptr ret_c_shared_ptr() = 0; virtual C ret_c_by_value() = 0; virtual int take_c_by_value(C c) = 0; diff --git a/Lib/java/boost_shared_ptr.i b/Lib/java/boost_shared_ptr.i index 33da61bf8..699a8a0a0 100644 --- a/Lib/java/boost_shared_ptr.i +++ b/Lib/java/boost_shared_ptr.i @@ -156,6 +156,10 @@ CPTR_VISIBILITY static long getCPtr($javaclassname obj) { return (obj == null) ? 0 : obj.swigCPtr; } + + CPTR_VISIBILITY void swigSetCMemOwn(boolean own) { + swigCMemOwn = own; + } %} // Derived proxy classes @@ -172,6 +176,11 @@ CPTR_VISIBILITY static long getCPtr($javaclassname obj) { return (obj == null) ? 0 : obj.swigCPtr; } + + CPTR_VISIBILITY void swigSetCMemOwn(boolean own) { + swigCMemOwnDerived = own; + super.swigSetCMemOwn(own); + } %} %typemap(javadestruct, methodname="delete", methodmodifiers="public synchronized") TYPE { @@ -195,6 +204,26 @@ super.delete(); } +%typemap(directordisconnect, methodname="swigDirectorDisconnect") TYPE %{ + protected void $methodname() { + swigSetCMemOwn(false); + $jnicall; + } +%} + +%typemap(directorowner_release, methodname="swigReleaseOwnership") TYPE %{ + public void $methodname() { + swigSetCMemOwn(false); + $jnicall; + } +%} + +%typemap(directorowner_take, methodname="swigTakeOwnership") TYPE %{ + public void $methodname() { + swigSetCMemOwn(true); + $jnicall; + } +%} %template() SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >; %enddef diff --git a/Lib/java/java.swg b/Lib/java/java.swg index 2ca426675..60ab7b049 100644 --- a/Lib/java/java.swg +++ b/Lib/java/java.swg @@ -1260,7 +1260,7 @@ SWIG_JAVABODY_TYPEWRAPPER(protected, protected, protected, SWIGTYPE) */ %define SWIG_PROXY_CONSTRUCTOR(OWNERSHIP, WEAKREF, TYPENAME...) -%typemap(javaconstruct,directorconnect="\n $imclassname.$javaclazznamedirector_connect(this, swigCPtr, swigCMemOwn, WEAKREF);") TYPENAME { +%typemap(javaconstruct,directorconnect="\n $imclassname.$javaclazznamedirector_connect(this, swigCPtr, OWNERSHIP, WEAKREF);") TYPENAME { this($imcall, OWNERSHIP);$directorconnect } %enddef From 241460eddc2165cea0d30626ccca363b373ee115 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Tue, 23 May 2017 21:32:44 +0100 Subject: [PATCH 123/455] director_smartptr runtime tests enhancement Add same changes from previous commit to additional languages --- .../csharp/director_smartptr_runme.cs | 29 +++++++++++++++++++ .../python/director_smartptr_runme.py | 19 ++++++++++++ .../ruby/director_smartptr_runme.rb | 24 +++++++++++++++ 3 files changed, 72 insertions(+) diff --git a/Examples/test-suite/csharp/director_smartptr_runme.cs b/Examples/test-suite/csharp/director_smartptr_runme.cs index 559dff7a0..33037a1da 100644 --- a/Examples/test-suite/csharp/director_smartptr_runme.cs +++ b/Examples/test-suite/csharp/director_smartptr_runme.cs @@ -26,6 +26,29 @@ public class runme } } + private class director_smartptr_MyBarFooDerived : FooDerived + { + public override string ping() + { + return "director_smartptr_MyBarFooDerived.ping()"; + } + + public override string pong() + { + return "director_smartptr_MyBarFooDerived.pong();" + ping(); + } + + public override string upcall(FooBar fooBarPtr) + { + return "overrideDerived;" + fooBarPtr.FooBarDo(); + } + + public override Foo makeFoo() + { + return new Foo(); + } + } + private static void check(string got, string expected) { if (got != expected) @@ -49,5 +72,11 @@ public class runme Foo myFoo2 = new Foo().makeFoo(); check(myFoo2.pong(), "Foo::pong();Foo::ping()"); check(Foo.callPong(myFoo2), "Foo::pong();Foo::ping()"); + + FooDerived myBarFooDerived = new director_smartptr_MyBarFooDerived(); + check(myBarFooDerived.ping(), "director_smartptr_MyBarFooDerived.ping()"); + check(FooDerived.callPong(myBarFooDerived), "director_smartptr_MyBarFooDerived.pong();director_smartptr_MyBarFooDerived.ping()"); + check(FooDerived.callUpcall(myBarFooDerived, fooBar), "overrideDerived;Bar::Foo2::Foo2Bar()"); + } } diff --git a/Examples/test-suite/python/director_smartptr_runme.py b/Examples/test-suite/python/director_smartptr_runme.py index c8bab9d7a..23e22d0fb 100644 --- a/Examples/test-suite/python/director_smartptr_runme.py +++ b/Examples/test-suite/python/director_smartptr_runme.py @@ -15,6 +15,20 @@ class director_smartptr_MyBarFoo(Foo): def makeFoo(self): return Foo() +class director_smartptr_MyBarFooDerived(FooDerived): + + def ping(self): + return "director_smartptr_MyBarFooDerived.ping()" + + def pong(self): + return "director_smartptr_MyBarFooDerived.pong();" + self.ping() + + def upcall(self, fooBarPtr): + return "overrideDerived;" + fooBarPtr.FooBarDo() + + def makeFoo(self): + return Foo() + def check(got, expected): if (got != expected): raise RuntimeError, "Failed, got: " + got + " expected: " + expected @@ -35,3 +49,8 @@ myFoo2 = Foo().makeFoo() check(myFoo2.pong(), "Foo::pong();Foo::ping()") check(Foo.callPong(myFoo2), "Foo::pong();Foo::ping()") check(myFoo2.upcall(FooBar()), "Bar::Foo2::Foo2Bar()") + +myBarFooDerived = director_smartptr_MyBarFooDerived() +check(myBarFooDerived.ping(), "director_smartptr_MyBarFooDerived.ping()") +check(FooDerived.callPong(myBarFooDerived), "director_smartptr_MyBarFooDerived.pong();director_smartptr_MyBarFooDerived.ping()") +check(FooDerived.callUpcall(myBarFooDerived, fooBar), "overrideDerived;Bar::Foo2::Foo2Bar()") diff --git a/Examples/test-suite/ruby/director_smartptr_runme.rb b/Examples/test-suite/ruby/director_smartptr_runme.rb index 8b4bd3d6d..46ef8b1b5 100644 --- a/Examples/test-suite/ruby/director_smartptr_runme.rb +++ b/Examples/test-suite/ruby/director_smartptr_runme.rb @@ -30,6 +30,25 @@ class Director_smartptr_MyBarFoo < Foo end end +class Director_smartptr_MyBarFooDerived < FooDerived + + def ping() + return "director_smartptr_MyBarFooDerived.ping()" + end + + def pong() + return "director_smartptr_MyBarFooDerived.pong();" + ping() + end + + def upcall(fooBarPtr) + return "overrideDerived;" + fooBarPtr.FooBarDo() + end + + def makeFoo() + return Foo.new() + end +end + def check(got, expected) if (got != expected) raise RuntimeError, "Failed, got: #{got} expected: #{expected}" @@ -52,3 +71,8 @@ myFoo2 = Foo.new().makeFoo() check(myFoo2.pong(), "Foo::pong();Foo::ping()") check(Foo.callPong(myFoo2), "Foo::pong();Foo::ping()") check(myFoo2.upcall(FooBar.new()), "Bar::Foo2::Foo2Bar()") + +myBarFooDerived = Director_smartptr_MyBarFooDerived.new() +check(myBarFooDerived.ping(), "director_smartptr_MyBarFooDerived.ping()") +check(FooDerived.callPong(myBarFooDerived), "director_smartptr_MyBarFooDerived.pong();director_smartptr_MyBarFooDerived.ping()") +check(FooDerived.callUpcall(myBarFooDerived, fooBar), "overrideDerived;Bar::Foo2::Foo2Bar()") From a4d01cddebf8568116bad93a2ffb783cd925c783 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Thu, 25 May 2017 20:35:18 +0100 Subject: [PATCH 124/455] Missing smart pointer handling in Java director extra methods - Add CHANGES file entry - Add testcase --- CHANGES.current | 4 ++++ Examples/test-suite/java/director_smartptr_runme.java | 7 +++++++ 2 files changed, 11 insertions(+) diff --git a/CHANGES.current b/CHANGES.current index cd91b3607..78eb605a4 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.0.0 (in progress) =========================== +2017-05-25: asibross + [Java] #370 #417 Missing smart pointer handling in Java director extra methods + swigReleaseOwnership() and swigTakeOwnership(). + 2017-05-23: wsfulton [Java] #230 #759 Fix Java shared_ptr and directors for derived classes java compilation error. diff --git a/Examples/test-suite/java/director_smartptr_runme.java b/Examples/test-suite/java/director_smartptr_runme.java index ba2bfc8c4..53d68f995 100644 --- a/Examples/test-suite/java/director_smartptr_runme.java +++ b/Examples/test-suite/java/director_smartptr_runme.java @@ -39,6 +39,13 @@ public class director_smartptr_runme { check(director_smartptr.FooDerived.callPong(myBarFooDerived), "director_smartptr_MyBarFooDerived.pong();director_smartptr_MyBarFooDerived.ping()"); check(director_smartptr.FooDerived.callUpcall(myBarFooDerived, fooBar), "overrideDerived;Bar::Foo2::Foo2Bar()"); + director_smartptr.Foo myFoo3 = myBarFoo.makeFoo(); + myFoo3.swigReleaseOwnership(); + myFoo3.swigTakeOwnership(); + director_smartptr.FooDerived myBarFooDerived2 = new director_smartptr_MyBarFooDerived(); + myBarFooDerived2.swigReleaseOwnership(); + myBarFooDerived2.swigTakeOwnership(); + } } From 0bafadea5a2852fc88809ee2c5dbdfeb04eabbf1 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Fri, 26 May 2017 18:55:52 +0100 Subject: [PATCH 125/455] Fix potential STL std::vector wrappers <: digraphs problems. --- Lib/java/std_vector.i | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Lib/java/std_vector.i b/Lib/java/std_vector.i index fee33f8c2..6d4f75010 100644 --- a/Lib/java/std_vector.i +++ b/Lib/java/std_vector.i @@ -31,9 +31,9 @@ int size_as_int(std::size_t sz) { %} %define SWIG_STD_VECTOR_MINIMUM_INTERNAL(CTYPE, CREF_TYPE) -%typemap(javabase) std::vector "java.util.AbstractList<$typemap(jboxtype, CTYPE)>" -%typemap(javainterfaces) std::vector "java.util.RandomAccess" -%typemap(javacode) std::vector %{ +%typemap(javabase) std::vector< CTYPE > "java.util.AbstractList<$typemap(jboxtype, CTYPE)>" +%typemap(javainterfaces) std::vector< CTYPE > "java.util.RandomAccess" +%typemap(javacode) std::vector< CTYPE > %{ public $javaclassname($typemap(jstype, CTYPE)[] initialElements) { this(); for ($typemap(jstype, CTYPE) element : initialElements) { From b51f32a915df51be552f9b906953d788af150906 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Fri, 26 May 2017 21:48:40 +0100 Subject: [PATCH 126/455] Java std::vector tweaks - Replace javacode typemap with %proxycode to make this typemap available to users - Make doSize private. --- Lib/java/std_vector.i | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Lib/java/std_vector.i b/Lib/java/std_vector.i index 6d4f75010..9e0b2455d 100644 --- a/Lib/java/std_vector.i +++ b/Lib/java/std_vector.i @@ -33,7 +33,7 @@ int size_as_int(std::size_t sz) { %define SWIG_STD_VECTOR_MINIMUM_INTERNAL(CTYPE, CREF_TYPE) %typemap(javabase) std::vector< CTYPE > "java.util.AbstractList<$typemap(jboxtype, CTYPE)>" %typemap(javainterfaces) std::vector< CTYPE > "java.util.RandomAccess" -%typemap(javacode) std::vector< CTYPE > %{ +%proxycode %{ public $javaclassname($typemap(jstype, CTYPE)[] initialElements) { this(); for ($typemap(jstype, CTYPE) element : initialElements) { @@ -110,6 +110,7 @@ int size_as_int(std::size_t sz) { throw std::out_of_range("vector index out of range"); } } + value_type doRemove(int index) throw (std::out_of_range) { const int size = size_as_int(self->size()); if (0 <= index && index < size) { @@ -120,6 +121,7 @@ int size_as_int(std::size_t sz) { throw std::out_of_range("vector index out of range"); } } + CREF_TYPE doGet(int i) throw (std::out_of_range) { const int size = size_as_int(self->size()); if (i>=0 && isize()); if (i>=0 && isize()); if (0 <= fromIndex && fromIndex <= toIndex && toIndex <= size) { @@ -148,6 +152,7 @@ int size_as_int(std::size_t sz) { } %enddef +%javamethodmodifiers std::vector::doSize "private"; %javamethodmodifiers std::vector::doAdd "private"; %javamethodmodifiers std::vector::doGet "private"; %javamethodmodifiers std::vector::doSet "private"; From fdca8e9829d4c68e0747a09ee0b57f79fbb38e0c Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Fri, 26 May 2017 22:36:23 +0100 Subject: [PATCH 127/455] Better variable naming consistency in STL containers --- Lib/csharp/std_array.i | 6 +++--- Lib/csharp/std_map.i | 4 ++-- Lib/csharp/std_vector.i | 4 ++-- Lib/d/std_vector.i | 8 ++++---- Lib/java/std_array.i | 4 ++-- Lib/java/std_vector.i | 4 ++-- 6 files changed, 15 insertions(+), 15 deletions(-) diff --git a/Lib/csharp/std_array.i b/Lib/csharp/std_array.i index 61bb510de..e7d392b85 100644 --- a/Lib/csharp/std_array.i +++ b/Lib/csharp/std_array.i @@ -174,7 +174,7 @@ bool empty() const; %rename(Fill) fill; - void fill(const value_type& val); + void fill(const value_type& value); %rename(Swap) swap; void swap(array& other); @@ -192,9 +192,9 @@ else throw std::out_of_range("index"); } - void setitem(int index, const_reference val) throw (std::out_of_range) { + void setitem(int index, const_reference value) throw (std::out_of_range) { if (index>=0 && index<(int)$self->size()) - (*$self)[index] = val; + (*$self)[index] = value; else throw std::out_of_range("index"); } diff --git a/Lib/csharp/std_map.i b/Lib/csharp/std_map.i index 90a865079..59b0a84f0 100644 --- a/Lib/csharp/std_map.i +++ b/Lib/csharp/std_map.i @@ -239,11 +239,11 @@ return iter != $self->end(); } - void Add(const key_type& key, const mapped_type& val) throw (std::out_of_range) { + void Add(const key_type& key, const mapped_type& value) throw (std::out_of_range) { std::map< K, T, C >::iterator iter = $self->find(key); if (iter != $self->end()) throw std::out_of_range("key already exists"); - $self->insert(std::pair< K, T >(key, val)); + $self->insert(std::pair< K, T >(key, value)); } bool Remove(const key_type& key) { diff --git a/Lib/csharp/std_vector.i b/Lib/csharp/std_vector.i index b0485eba6..52a865e67 100644 --- a/Lib/csharp/std_vector.i +++ b/Lib/csharp/std_vector.i @@ -231,9 +231,9 @@ else throw std::out_of_range("index"); } - void setitem(int index, CTYPE const& val) throw (std::out_of_range) { + void setitem(int index, CTYPE const& value) throw (std::out_of_range) { if (index>=0 && index<(int)$self->size()) - (*$self)[index] = val; + (*$self)[index] = value; else throw std::out_of_range("index"); } diff --git a/Lib/d/std_vector.i b/Lib/d/std_vector.i index 56f7188c7..c67057180 100644 --- a/Lib/d/std_vector.i +++ b/Lib/d/std_vector.i @@ -165,11 +165,11 @@ public void capacity(size_t value) { // generation issue when using const pointers as vector elements (like // std::vector< const int* >). %extend { - void setElement(size_type index, CTYPE const& val) throw (std::out_of_range) { + void setElement(size_type index, CTYPE const& value) throw (std::out_of_range) { if ((index < 0) || ($self->size() <= index)) { throw std::out_of_range("Tried to set value of element with invalid index."); } - (*$self)[index] = val; + (*$self)[index] = value; } } @@ -517,11 +517,11 @@ int opApply(int delegate(ref size_t index, ref $typemap(dtype, CTYPE) value) dg) // generation issue when using const pointers as vector elements (like // std::vector< const int* >). %extend { - void setElement(size_type index, CTYPE const& val) throw (std::out_of_range) { + void setElement(size_type index, CTYPE const& value) throw (std::out_of_range) { if ((index < 0) || ($self->size() <= index)) { throw std::out_of_range("Tried to set value of element with invalid index."); } - (*$self)[index] = val; + (*$self)[index] = value; } } diff --git a/Lib/java/std_array.i b/Lib/java/std_array.i index cbacfe673..f75857e21 100644 --- a/Lib/java/std_array.i +++ b/Lib/java/std_array.i @@ -29,10 +29,10 @@ namespace std { else throw std::out_of_range("array index out of range"); } - void set(int i, const value_type& val) throw (std::out_of_range) { + void set(int i, const value_type& value) throw (std::out_of_range) { int size = int(self->size()); if (i>=0 && isize()); if (i>=0 && i Date: Tue, 30 May 2017 14:40:22 +0200 Subject: [PATCH 128/455] fix Scilab 6.0.0 linking issue --- Source/Modules/scilab.cxx | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Source/Modules/scilab.cxx b/Source/Modules/scilab.cxx index b3abc009e..4fea0ce36 100644 --- a/Source/Modules/scilab.cxx +++ b/Source/Modules/scilab.cxx @@ -1027,8 +1027,14 @@ public: Printf(gatewayHeader, "\n"); gatewayHeaderV6 = NewString(""); + Printf(gatewayHeaderV6, "#ifdef __cplusplus\n"); + Printf(gatewayHeaderV6, "extern \"C\" {\n"); + Printf(gatewayHeaderV6, "#endif\n"); Printf(gatewayHeaderV6, "#include \"c_gateway_prototype.h\"\n"); Printf(gatewayHeaderV6, "#include \"addfunction.h\"\n"); + Printf(gatewayHeaderV6, "#ifdef __cplusplus\n"); + Printf(gatewayHeaderV6, "}\n"); + Printf(gatewayHeaderV6, "#endif\n"); Printf(gatewayHeaderV6, "\n"); Printf(gatewayHeaderV6, "#define MODULE_NAME L\"%s\"\n", gatewayLibraryName); Printf(gatewayHeaderV6, "#ifdef __cplusplus\n"); From 84106490451daf19b0b5b3ac12daf627228321f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20DAVID?= Date: Tue, 30 May 2017 15:30:59 +0200 Subject: [PATCH 129/455] update changes referencing issue --- CHANGES.current | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGES.current b/CHANGES.current index 78eb605a4..7c82b8b89 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.0.0 (in progress) =========================== +2017-05-30: davidcl + [Scilab] #994 Undefined symbol error when loading in Scilab 6 + 2017-05-25: asibross [Java] #370 #417 Missing smart pointer handling in Java director extra methods swigReleaseOwnership() and swigTakeOwnership(). From 32e7074d9b288f08e638afeea6b49c829d9cd200 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Fri, 26 May 2017 22:50:36 +0100 Subject: [PATCH 130/455] Whitespace fixes in STL wrappers --- Lib/csharp/std_map.i | 20 +++--- Lib/csharp/std_vector.i | 10 +-- Lib/d/std_map.i | 71 ++++++++++---------- Lib/java/std_map.i | 73 ++++++++++----------- Lib/java/std_vector.i | 140 ++++++++++++++++++++-------------------- 5 files changed, 154 insertions(+), 160 deletions(-) diff --git a/Lib/csharp/std_map.i b/Lib/csharp/std_map.i index 59b0a84f0..9d07bc830 100644 --- a/Lib/csharp/std_map.i +++ b/Lib/csharp/std_map.i @@ -4,14 +4,14 @@ * SWIG typemaps for std::map< K, T, C > * * The C# wrapper is made to look and feel like a C# System.Collections.Generic.IDictionary<>. - * + * * Using this wrapper is fairly simple. For example, to create a map from integers to doubles use: * * %include * %template(MapIntDouble) std::map * * Notes: - * 1) IEnumerable<> is implemented in the proxy class which is useful for using LINQ with + * 1) IEnumerable<> is implemented in the proxy class which is useful for using LINQ with * C++ std::map wrappers. * * Warning: heavy macro usage in this file. Use swig -E to get a sane view on the real file contents! @@ -55,8 +55,8 @@ } public bool IsReadOnly { - get { - return false; + get { + return false; } } @@ -84,7 +84,7 @@ return vals; } } - + public void Add(global::System.Collections.Generic.KeyValuePair<$typemap(cstype, K), $typemap(cstype, T)> item) { Add(item.Key, item.Value); } @@ -143,7 +143,7 @@ /// whenever the collection is modified. This has been done for changes in the size of the /// collection but not when one of the elements of the collection is modified as it is a bit /// tricky to detect unmanaged code that modifies the collection under our feet. - public sealed class $csclassnameEnumerator : global::System.Collections.IEnumerator, + public sealed class $csclassnameEnumerator : global::System.Collections.IEnumerator, global::System.Collections.Generic.IEnumerator> { private $csclassname collectionRef; @@ -206,7 +206,7 @@ currentObject = null; } } - + %} public: @@ -251,7 +251,7 @@ if (iter != $self->end()) { $self->erase(iter); return true; - } + } return false; } @@ -285,12 +285,12 @@ %csmethodmodifiers std::map::destroy_iterator "private" // Default implementation -namespace std { +namespace std { template > class map { SWIG_STD_MAP_INTERNAL(K, T, C) }; } - + // Legacy macros (deprecated) %define specialize_std_map_on_key(K,CHECK,CONVERT_FROM,CONVERT_TO) diff --git a/Lib/csharp/std_vector.i b/Lib/csharp/std_vector.i index 52a865e67..0d1476f7f 100644 --- a/Lib/csharp/std_vector.i +++ b/Lib/csharp/std_vector.i @@ -5,9 +5,9 @@ * C# implementation * The C# wrapper is made to look and feel like a C# System.Collections.Generic.List<> collection. * - * Note that IEnumerable<> is implemented in the proxy class which is useful for using LINQ with + * Note that IEnumerable<> is implemented in the proxy class which is useful for using LINQ with * C++ std::vector wrappers. The IList<> interface is also implemented to provide enhanced functionality - * whenever we are confident that the required C++ operator== is available. This is the case for when + * whenever we are confident that the required C++ operator== is available. This is the case for when * T is a primitive type or a pointer. If T does define an operator==, then use the SWIG_STD_VECTOR_ENHANCED * macro to obtain this enhanced functionality, for example: * @@ -33,14 +33,14 @@ this.Add(element); } } - + public $csclassname(global::System.Collections.Generic.IEnumerable<$typemap(cstype, CTYPE)> c) : this() { if (c == null) throw new global::System.ArgumentNullException("c"); foreach ($typemap(cstype, CTYPE) element in c) { this.Add(element); } - } + } public bool IsFixedSize { get { @@ -332,7 +332,7 @@ std::vector< CTYPE >::iterator it = std::find($self->begin(), $self->end(), value); if (it != $self->end()) { $self->erase(it); - return true; + return true; } return false; } diff --git a/Lib/d/std_map.i b/Lib/d/std_map.i index 0e8574b8a..d2ba04118 100644 --- a/Lib/d/std_map.i +++ b/Lib/d/std_map.i @@ -16,44 +16,41 @@ #include %} -// exported class - namespace std { - template class map { - // add typemaps here - public: - typedef size_t size_type; - typedef ptrdiff_t difference_type; - typedef K key_type; - typedef T mapped_type; - map(); - map(const map &); + template class map { + public: + typedef size_t size_type; + typedef ptrdiff_t difference_type; + typedef K key_type; + typedef T mapped_type; + map(); + map(const map &); - unsigned int size() const; - bool empty() const; - void clear(); - %extend { - const T& get(const K& key) throw (std::out_of_range) { - std::map::iterator i = self->find(key); - if (i != self->end()) - return i->second; - else - throw std::out_of_range("key not found"); - } - void set(const K& key, const T& x) { - (*self)[key] = x; - } - void del(const K& key) throw (std::out_of_range) { - std::map::iterator i = self->find(key); - if (i != self->end()) - self->erase(i); - else - throw std::out_of_range("key not found"); - } - bool has_key(const K& key) { - std::map::iterator i = self->find(key); - return i != self->end(); - } + unsigned int size() const; + bool empty() const; + void clear(); + %extend { + const T& get(const K& key) throw (std::out_of_range) { + std::map::iterator i = self->find(key); + if (i != self->end()) + return i->second; + else + throw std::out_of_range("key not found"); } - }; + void set(const K& key, const T& x) { + (*self)[key] = x; + } + void del(const K& key) throw (std::out_of_range) { + std::map::iterator i = self->find(key); + if (i != self->end()) + self->erase(i); + else + throw std::out_of_range("key not found"); + } + bool has_key(const K& key) { + std::map::iterator i = self->find(key); + return i != self->end(); + } + } + }; } diff --git a/Lib/java/std_map.i b/Lib/java/std_map.i index e7812f38a..2405571fa 100644 --- a/Lib/java/std_map.i +++ b/Lib/java/std_map.i @@ -16,47 +16,44 @@ #include %} -// exported class - namespace std { - template class map { - // add typemaps here - public: - typedef size_t size_type; - typedef ptrdiff_t difference_type; - typedef K key_type; - typedef T mapped_type; - map(); - map(const map &); - - unsigned int size() const; - bool empty() const; - void clear(); - %extend { - const T& get(const K& key) throw (std::out_of_range) { - std::map::iterator i = self->find(key); - if (i != self->end()) - return i->second; - else - throw std::out_of_range("key not found"); - } - void set(const K& key, const T& x) { - (*self)[key] = x; - } - void del(const K& key) throw (std::out_of_range) { - std::map::iterator i = self->find(key); - if (i != self->end()) - self->erase(i); - else - throw std::out_of_range("key not found"); - } - bool has_key(const K& key) { - std::map::iterator i = self->find(key); - return i != self->end(); - } + template class map { + public: + typedef size_t size_type; + typedef ptrdiff_t difference_type; + typedef K key_type; + typedef T mapped_type; + map(); + map(const map &); + + unsigned int size() const; + bool empty() const; + void clear(); + %extend { + const T& get(const K& key) throw (std::out_of_range) { + std::map::iterator i = self->find(key); + if (i != self->end()) + return i->second; + else + throw std::out_of_range("key not found"); } - }; + void set(const K& key, const T& x) { + (*self)[key] = x; + } + void del(const K& key) throw (std::out_of_range) { + std::map::iterator i = self->find(key); + if (i != self->end()) + self->erase(i); + else + throw std::out_of_range("key not found"); + } + bool has_key(const K& key) { + std::map::iterator i = self->find(key); + return i != self->end(); + } + } + }; // Legacy macros (deprecated) %define specialize_std_map_on_key(K,CHECK,CONVERT_FROM,CONVERT_TO) diff --git a/Lib/java/std_vector.i b/Lib/java/std_vector.i index 3a76ec891..99fbd3e9a 100644 --- a/Lib/java/std_vector.i +++ b/Lib/java/std_vector.i @@ -20,11 +20,11 @@ // them, in order to achieve this. namespace { int size_as_int(std::size_t sz) { - if (sz > static_cast(INT_MAX)) { - throw std::out_of_range("vector size is too big to be representable as int"); - } + if (sz > static_cast(INT_MAX)) { + throw std::out_of_range("vector size is too big to be representable as int"); + } - return static_cast(sz); + return static_cast(sz); } } // anonymous namespace @@ -82,74 +82,74 @@ int size_as_int(std::size_t sz) { } %} - public: - typedef size_t size_type; - typedef CTYPE value_type; - typedef CREF_TYPE const_reference; - vector(); - vector(size_type n); - size_type capacity() const; - void reserve(size_type n); - %rename(isEmpty) empty; - bool empty() const; - void clear(); - %extend { - int doSize() const { - return size_as_int(self->size()); - } + public: + typedef size_t size_type; + typedef CTYPE value_type; + typedef CREF_TYPE const_reference; + vector(); + vector(size_type n); + size_type capacity() const; + void reserve(size_type n); + %rename(isEmpty) empty; + bool empty() const; + void clear(); + %extend { + int doSize() const { + return size_as_int(self->size()); + } - void doAdd(const value_type& value) { - self->push_back(value); - } + void doAdd(const value_type& value) { + self->push_back(value); + } - void doAdd(int index, const value_type& value) throw (std::out_of_range) { - const int size = size_as_int(self->size()); - if (0 <= index && index <= size) { - self->insert(self->begin() + index, value); - } else { - throw std::out_of_range("vector index out of range"); - } - } - - value_type doRemove(int index) throw (std::out_of_range) { - const int size = size_as_int(self->size()); - if (0 <= index && index < size) { - CTYPE const old_value = (*self)[index]; - self->erase(self->begin() + index); - return old_value; - } else { - throw std::out_of_range("vector index out of range"); - } - } - - CREF_TYPE doGet(int i) throw (std::out_of_range) { - const int size = size_as_int(self->size()); - if (i>=0 && isize()); - if (i>=0 && isize()); - if (0 <= fromIndex && fromIndex <= toIndex && toIndex <= size) { - self->erase(self->begin() + fromIndex, self->begin() + toIndex); - } else { - throw std::out_of_range("vector index out of range"); - } - } + void doAdd(int index, const value_type& value) throw (std::out_of_range) { + const int size = size_as_int(self->size()); + if (0 <= index && index <= size) { + self->insert(self->begin() + index, value); + } else { + throw std::out_of_range("vector index out of range"); } + } + + value_type doRemove(int index) throw (std::out_of_range) { + const int size = size_as_int(self->size()); + if (0 <= index && index < size) { + CTYPE const old_value = (*self)[index]; + self->erase(self->begin() + index); + return old_value; + } else { + throw std::out_of_range("vector index out of range"); + } + } + + CREF_TYPE doGet(int i) throw (std::out_of_range) { + const int size = size_as_int(self->size()); + if (i>=0 && isize()); + if (i>=0 && isize()); + if (0 <= fromIndex && fromIndex <= toIndex && toIndex <= size) { + self->erase(self->begin() + fromIndex, self->begin() + toIndex); + } else { + throw std::out_of_range("vector index out of range"); + } + } + } %enddef %javamethodmodifiers std::vector::doSize "private"; @@ -160,7 +160,7 @@ int size_as_int(std::size_t sz) { %javamethodmodifiers std::vector::doRemoveRange "private"; namespace std { - + template class vector { SWIG_STD_VECTOR_MINIMUM_INTERNAL(T, const T&) }; From 9f55985a6cf86540d86799b174df607375e2c5c5 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Fri, 2 Jun 2017 18:39:02 +0100 Subject: [PATCH 131/455] Remove unused code --- Source/Modules/lang.cxx | 1 - 1 file changed, 1 deletion(-) diff --git a/Source/Modules/lang.cxx b/Source/Modules/lang.cxx index 4dc39e069..69ca07772 100644 --- a/Source/Modules/lang.cxx +++ b/Source/Modules/lang.cxx @@ -81,7 +81,6 @@ extern int AddExtern; /* import modes */ #define IMPORT_MODE 1 -#define IMPORT_MODULE 2 /* ---------------------------------------------------------------------- * Dispatcher::emit_one() From 857a62425c7726d937ca4276a1c19e7280da3135 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Sat, 3 Jun 2017 13:47:26 +0100 Subject: [PATCH 132/455] Formatting fixes in Lisp docs --- Doc/Manual/Lisp.html | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/Doc/Manual/Lisp.html b/Doc/Manual/Lisp.html index ba42f735c..7bf8562c5 100644 --- a/Doc/Manual/Lisp.html +++ b/Doc/Manual/Lisp.html @@ -122,9 +122,12 @@ swig -cffi -help

27.2.2 Generating CFFI bindings

+

+ As we mentioned earlier the ideal way to use SWIG is to use interface files. To illustrate the use of it, let's assume that we have a file named test.h with the following C code: +

 #define y 5
@@ -155,7 +158,10 @@ void lispsort_double (int n, double * array);
 enum color { RED, BLUE, GREEN};
 
+

Corresponding to this we will write a simple interface file: +

+
 %module test
 
@@ -163,7 +169,9 @@ Corresponding to this we will write a simple interface file:
 
 
+

The generated SWIG Code will be: +

 ;;;SWIG wrapper code starts here
@@ -430,8 +438,10 @@ Also, while parsing the C++ file and generating C wrapper code SWIG
 %include "target/header.h"
 
 
+

Various features which were available for C headers can also be used here. The target header which we are going to use here is: +

 namespace OpenDemo {
   class Test
@@ -478,8 +488,10 @@ namespace OpenDemo {
 %include "test.cpp"
 
+

SWIG generates 3 files, the first one is a C wrap which we don't show, the second is the plain CFFI wrapper which is as shown below: +

 (cffi:defcfun ("_wrap_Test_x_set" Test_x_set) :void
   (self :pointer)
@@ -528,11 +540,13 @@ SWIG generates 3 files, the first one is a C wrap which we don't show,
 (cffi:defcfun ("_wrap_RandomUnitVectorOnXZPlane" RandomUnitVectorOnXZPlane) :pointer)
 
+

The output is pretty good but it fails in disambiguating overloaded functions such as the constructor, in this case. One way of resolving this problem is to make the interface use the rename directiv, but hopefully there are better solutions. In addition SWIG also generates, a CLOS file +


From 57a89f987dd5736f9f55f23eb4b3708e07d0f676 Mon Sep 17 00:00:00 2001
From: William S Fulton 
Date: Sat, 3 Jun 2017 16:18:41 +0100
Subject: [PATCH 133/455] Fix %import and %fragment forced inclusion to not
 generate code.

---
 CHANGES.current                          | 22 ++++++
 Doc/Manual/Typemaps.html                 | 91 ++++++++++++++++++++++--
 Examples/test-suite/common.mk            |  1 +
 Examples/test-suite/import_fragments.i   | 18 +++++
 Examples/test-suite/import_fragments_a.i | 45 ++++++++++++
 Examples/test-suite/import_fragments_b.i |  9 +++
 Source/Modules/javascript.cxx            |  4 +-
 Source/Modules/lang.cxx                  |  3 +-
 8 files changed, 186 insertions(+), 7 deletions(-)
 create mode 100644 Examples/test-suite/import_fragments.i
 create mode 100644 Examples/test-suite/import_fragments_a.i
 create mode 100644 Examples/test-suite/import_fragments_b.i

diff --git a/CHANGES.current b/CHANGES.current
index 65c32605d..f96beecbd 100644
--- a/CHANGES.current
+++ b/CHANGES.current
@@ -7,6 +7,28 @@ the issue number to the end of the URL: https://github.com/swig/swig/issues/
 Version 4.0.0 (in progress)
 ===========================
 
+2017-06-03: wsfulton
+            Fix %import on a file containing a file scope %fragment forced inclusion to not
+            generate the fragment contents as %import should not result in code being generated.
+            The behaviour is now the same as importing code insertion blocks.
+            Wrapping FileC.i in the following example will result in no generated code, whereas
+            previously "#include " was generated:
+
+              // FileA.i
+              %fragment("", "header") %{
+                #include 
+              %}
+
+              %{
+                #include 
+              %}
+              %fragment("");
+
+              // FileC.i
+              %import "FileA.i"
+
+            *** POTENTIAL INCOMPATIBILITY ***
+
 2017-05-26: Volker Diels-Grabsch, vadz
             [Java] Implement java.util.List<> for std::vector. This notably allows to
             iterate over wrapped vectors in a natural way.
diff --git a/Doc/Manual/Typemaps.html b/Doc/Manual/Typemaps.html
index a3a3e09cb..f274c9293 100644
--- a/Doc/Manual/Typemaps.html
+++ b/Doc/Manual/Typemaps.html
@@ -3904,9 +3904,9 @@ A fragment can use one or more additional fragments, for example:
 
 
-%fragment("<limits.h>", "header") {
-  %#include <limits.h>
-}
+%fragment("<limits.h>", "header") %{
+  #include <limits.h>
+%}
 
 
 %fragment("AsMyClass", "header", fragment="<limits.h>") {
@@ -3989,8 +3989,91 @@ Finally, you can force the inclusion of a fragment at any point in the generated
 

-which is very useful inside a template class, for example. +which, for example, is very useful inside a template class. +Another useful case is when using %extend inside a class +where the additional code in the %extend block depends on the contents of the fragment.

+ +
+
+%fragment("<limits.h>", "header") %{
+  #include <limits.h>
+%}
+
+struct X {
+  ...
+  %extend {
+    %fragment("<limits.h>");
+    bool check(short val) {
+      if (val < SHRT_MIN /*defined in <limits.h>*/) {
+        return true;
+      } else {
+        return false;
+      }
+    }
+  }
+};
+
+
+ + +

+Forced inclusion of fragments can be used as a replacement for code insertion block, ensuring the +code block is only generated once. +Consider the contents of FileA.i below which first uses a code insertion block and then a forced fragment inclusion to generate code: +

+

+
+// FileA.i
+%{
+  #include <stdio.h>
+%}
+%fragment("<limits.h>");
+
+
+ +

+and another file including the above: +

+ +
+
+// FileB.i
+%include "FileA.i"
+
+
+ +

+The resulting code in the wrappers for FileB.i is: +

+ +
+
+  #include <stdio.h>
+
+  #include <limits.h>
+
+
+ +

+A note of caution must be mentioned when using %fragment forced inclusion or code insertion blocks with %import. +If %import is used instead: +

+ +

+
+// FileC.i
+%import "FileA.i"
+
+
+ +

+then nothing is generated in the resulting code in the wrappers for FileC.i. +This is because %import is for collecting type information and does not result in any code +being generated, see File Imports. +

+ +

diff --git a/Examples/test-suite/common.mk b/Examples/test-suite/common.mk index 18c00e750..f68451f87 100644 --- a/Examples/test-suite/common.mk +++ b/Examples/test-suite/common.mk @@ -246,6 +246,7 @@ CPP_TEST_CASES += \ global_vars \ grouping \ ignore_parameter \ + import_fragments \ import_nomodule \ inherit \ inherit_member \ diff --git a/Examples/test-suite/import_fragments.i b/Examples/test-suite/import_fragments.i new file mode 100644 index 000000000..26b87cdb2 --- /dev/null +++ b/Examples/test-suite/import_fragments.i @@ -0,0 +1,18 @@ +%module import_fragments + +// Check %fragments forced inclusion does not result in code generation when using %import +%import "import_fragments_a.i" + +%{ +template +struct TemplateA4 {}; +%} + +%template(TemplateA4Int) TemplateA4; + +%inline %{ +int getImport4() { + // Requires the ImportA4 fragment to be generated in order to compile + return ImportA4; +} +%} diff --git a/Examples/test-suite/import_fragments_a.i b/Examples/test-suite/import_fragments_a.i new file mode 100644 index 000000000..7478a1e86 --- /dev/null +++ b/Examples/test-suite/import_fragments_a.i @@ -0,0 +1,45 @@ +%module import_fragments_a + +%fragment("ImportA1", "header") %{ +ImportA1_this_will_not_compile; +%} +%fragment("ImportA2", "header") %{ +ImportA2_this_will_not_compile; +%} +%fragment("ImportA3", "header") %{ +ImportA3_this_will_not_compile; +%} +%fragment("ImportA4", "header") %{ +static int ImportA4 = 99; +%} +%fragment("ImportA5", "header") %{ +ImportA5_this_will_not_compile; +%} + +%fragment("ImportA1"); + +%{ +Import_will_not_compile; +%} + +struct StructA { + %fragment("ImportA2"); +}; + +template +struct TemplateA3 { + %fragment("ImportA3"); +}; + +template +struct TemplateA4 { + %fragment("ImportA4"); +}; + +template +struct TemplateA5 { + %fragment("ImportA5"); +}; +%template(TemplateA5Double) TemplateA5; + +%include "import_fragments_b.i" diff --git a/Examples/test-suite/import_fragments_b.i b/Examples/test-suite/import_fragments_b.i new file mode 100644 index 000000000..615db4796 --- /dev/null +++ b/Examples/test-suite/import_fragments_b.i @@ -0,0 +1,9 @@ +%module import_fragments_b + +%fragment("ImportB", "header") %{ +ImportB_this_will_not_compile; +%} + +%fragment("ImportB"); + + diff --git a/Source/Modules/javascript.cxx b/Source/Modules/javascript.cxx index 4e7a7912f..490ee7fd3 100644 --- a/Source/Modules/javascript.cxx +++ b/Source/Modules/javascript.cxx @@ -462,10 +462,10 @@ int JAVASCRIPT::fragmentDirective(Node *n) { // and register them at the emitter. String *section = Getattr(n, "section"); - if (Equal(section, "templates")) { + if (Equal(section, "templates") && !ImportMode) { emitter->registerTemplate(Getattr(n, "value"), Getattr(n, "code")); } else { - Swig_fragment_register(n); + return Language::fragmentDirective(n); } return SWIG_OK; diff --git a/Source/Modules/lang.cxx b/Source/Modules/lang.cxx index 69ca07772..11874ef0a 100644 --- a/Source/Modules/lang.cxx +++ b/Source/Modules/lang.cxx @@ -624,7 +624,8 @@ int Language::constantDirective(Node *n) { * ---------------------------------------------------------------------- */ int Language::fragmentDirective(Node *n) { - Swig_fragment_register(n); + if (!(Getattr(n, "emitonly") && ImportMode)) + Swig_fragment_register(n); return SWIG_OK; } From be63f73e33fa0624e28652f117ee68c1648762cc Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Sat, 3 Jun 2017 17:15:44 +0100 Subject: [PATCH 134/455] Fix c++ compiler warnings in c++11 testcases --- .../test-suite/cpp11_alternate_function_syntax.i | 1 + Examples/test-suite/cpp11_constexpr.i | 10 ++++++++-- Examples/test-suite/cpp11_final_override.i | 1 + Examples/test-suite/cpp11_noexcept.i | 2 +- Examples/test-suite/cpp11_rvalue_reference2.i | 11 ++++++----- Examples/test-suite/cpp11_rvalue_reference3.i | 16 ++++++++++++++-- 6 files changed, 31 insertions(+), 10 deletions(-) diff --git a/Examples/test-suite/cpp11_alternate_function_syntax.i b/Examples/test-suite/cpp11_alternate_function_syntax.i index 3e47bbafe..b3ecabc8c 100644 --- a/Examples/test-suite/cpp11_alternate_function_syntax.i +++ b/Examples/test-suite/cpp11_alternate_function_syntax.i @@ -13,6 +13,7 @@ struct SomeStruct { auto addAlternateMemberPtrConstParm(int x, int (SomeStruct::*mp)(int, int) const) const -> int; virtual auto addFinal(int x, int y) const noexcept -> int final { return x + y; } + virtual ~SomeStruct() = default; }; int SomeStruct::addNormal(int x, int y) { return x + y; } diff --git a/Examples/test-suite/cpp11_constexpr.i b/Examples/test-suite/cpp11_constexpr.i index d91107cc6..ef08a49c3 100644 --- a/Examples/test-suite/cpp11_constexpr.i +++ b/Examples/test-suite/cpp11_constexpr.i @@ -3,11 +3,17 @@ */ %module cpp11_constexpr + %inline %{ +#ifdef SWIG +#define CONST const +#else +#define CONST +#endif constexpr int AAA = 10; constexpr const int BBB = 20; constexpr int CCC() { return 30; } -constexpr const int DDD() { return 40; } +constexpr CONST int DDD() { return 40; } constexpr int XXX() { return 10; } constexpr int YYY = XXX() + 100; @@ -17,7 +23,7 @@ struct ConstExpressions { static constexpr int KKK = 200; static const int LLL = 300; constexpr int MMM() { return 400; } - constexpr const int NNN() { return 500; } + constexpr CONST int NNN() { return 500; } // Regression tests for support added in SWIG 3.0.4: static constexpr const int JJJ1 = 101; constexpr static int KKK1 = 201; diff --git a/Examples/test-suite/cpp11_final_override.i b/Examples/test-suite/cpp11_final_override.i index a5baeaa36..7abf50123 100644 --- a/Examples/test-suite/cpp11_final_override.i +++ b/Examples/test-suite/cpp11_final_override.i @@ -82,6 +82,7 @@ struct Destructors4 : Base { struct FinalOverrideMethods { virtual void final() {} virtual void override(int) {} + virtual ~FinalOverrideMethods() = default; }; struct FinalOverrideVariables { int final; diff --git a/Examples/test-suite/cpp11_noexcept.i b/Examples/test-suite/cpp11_noexcept.i index 2fa6e8985..a77eb046f 100644 --- a/Examples/test-suite/cpp11_noexcept.i +++ b/Examples/test-suite/cpp11_noexcept.i @@ -18,7 +18,7 @@ struct NoExceptClass { NoExceptClass(const NoExceptClass&) noexcept {} NoExceptClass(NoExceptClass&&) noexcept {} NoExceptClass& operator=(const NoExceptClass&) noexcept { return *this; } - ~NoExceptClass() noexcept {} + virtual ~NoExceptClass() noexcept {} void noex0() noexcept {} void noex1() noexcept(sizeof(int) == 4) {} diff --git a/Examples/test-suite/cpp11_rvalue_reference2.i b/Examples/test-suite/cpp11_rvalue_reference2.i index 6718a3941..d532e29f3 100644 --- a/Examples/test-suite/cpp11_rvalue_reference2.i +++ b/Examples/test-suite/cpp11_rvalue_reference2.i @@ -23,7 +23,7 @@ struct Thingy { int val; int &lvalref; int &&rvalref; - Thingy(int v) : val(v), lvalref(val), rvalref(22) {} + Thingy(int v, int &&rvalv) : val(v), lvalref(val), rvalref(std::move(rvalv)) {} void refIn(long &i) {} void rvalueIn(long &&i) {} short && rvalueInOut(short &&i) { return std::move(i); } @@ -32,7 +32,7 @@ struct Thingy { 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(0); } - Thingy(const Thingy& rhs) : val(rhs.val), lvalref(rhs.lvalref), rvalref(copy_int(rhs.rvalref)) {} + Thingy(const Thingy& rhs) : val(rhs.val), lvalref(rhs.lvalref), rvalref(std::move(rhs.rvalref)) {} Thingy& operator=(const Thingy& rhs) { val = rhs.val; lvalref = rhs.lvalref; @@ -41,17 +41,18 @@ struct Thingy { } private: static const bool PrivateTrue; - int copy_int(int& i) { return i; } Thingy(); }; const bool Thingy::PrivateTrue = true; short && globalRvalueInOut(short &&i) { return std::move(i); } -Thingy &&globalrrval = Thingy(55); +int glob = 123; + +Thingy &&globalrrval = Thingy(55, std::move(glob)); short && func(short &&i) { return std::move(i); } -Thingy getit() { return Thingy(22); } +Thingy getit() { return Thingy(22, std::move(glob)); } void rvalrefFunction1(int &&v = (int &&)5) {} void rvalrefFunctionBYVAL(short (Thingy::*memFunc)(short)) {} diff --git a/Examples/test-suite/cpp11_rvalue_reference3.i b/Examples/test-suite/cpp11_rvalue_reference3.i index c65309945..6dfe4c098 100644 --- a/Examples/test-suite/cpp11_rvalue_reference3.i +++ b/Examples/test-suite/cpp11_rvalue_reference3.i @@ -31,7 +31,13 @@ struct Containing { Thing *const&& member_rvalue_ref_ptr3 = 0; Thing const*const &&member_rvalue_ref_ptr4 = 0; - Containing() : member_rvalue_ref(Thing()) {} + Containing(Thing&&r, Thing*&& r1, Thing const*&& r2, Thing *const&& r3, Thing const*const && r4) : + member_rvalue_ref(std::move(r)), + member_rvalue_ref_ptr1(std::move(r1)), + member_rvalue_ref_ptr2(std::move(r2)), + member_rvalue_ref_ptr3(std::move(r3)), + member_rvalue_ref_ptr4(std::move(r4)) + {} }; %} @@ -62,6 +68,12 @@ struct IntContaining { int *const&& member_rvalue_ref_ptr3 = 0; int const*const &&member_rvalue_ref_ptr4 = 0; - IntContaining() : member_rvalue_ref(55) {} + IntContaining(int&& r, int*&& r1, int const*&& r2, int *const&& r3, int const*const && r4) : + member_rvalue_ref(std::move(r)), + member_rvalue_ref_ptr1(std::move(r1)), + member_rvalue_ref_ptr2(std::move(r2)), + member_rvalue_ref_ptr3(std::move(r3)), + member_rvalue_ref_ptr4(std::move(r4)) + {} }; %} From 5eb9f735daee254b227b728da16e68e4d83b0843 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Mon, 5 Jun 2017 18:49:54 +0100 Subject: [PATCH 135/455] Add generic approach in fragments for converting size_t to Java int --- Lib/java/java.swg | 8 ++++++ Lib/java/std_vector.i | 65 ++++++++++++++++++------------------------- 2 files changed, 35 insertions(+), 38 deletions(-) diff --git a/Lib/java/java.swg b/Lib/java/java.swg index 2ffb57196..e0ddcba02 100644 --- a/Lib/java/java.swg +++ b/Lib/java/java.swg @@ -54,6 +54,14 @@ SWIGINTERN const char * SWIG_UnpackData(const char *c, void *ptr, size_t sz) { } } +%fragment("SWIG_JavaIntFromSize_t", "header") { +/* Check for overflow converting to Java int (always signed 32-bit) from (unsigned variable-bit) size_t */ +SWIGINTERN jint SWIG_JavaIntFromSize_t(size_t size) { + static const jint JINT_MAX = 0x7FFFFFFF; + return (size > (size_t)JINT_MAX) ? -1 : (jint)size; +} +} + /* Primitive types */ %typemap(jni) bool, const bool & "jboolean" %typemap(jni) char, const char & "jchar" diff --git a/Lib/java/std_vector.i b/Lib/java/std_vector.i index 99fbd3e9a..4f5afe6db 100644 --- a/Lib/java/std_vector.i +++ b/Lib/java/std_vector.i @@ -7,29 +7,17 @@ %{ #include #include -#include - -// C++ allows to have up to 2^64-1 items in a vector on 64 bit machines and -// 2^32-1 even on 32 bit ones, but in Java size() must return a value of type -// "int" which is limited to signed 32 bit values, i.e. 2^31-1, and there -// doesn't seem to be any way to represent bigger vectors there. -// -// The only thing we can do is to at least detect such situation and throw an -// exception instead of silently returning the wrong size in this case and we -// use this helper to convert size_t values to int, instead of just casting -// them, in order to achieve this. -namespace { -int size_as_int(std::size_t sz) { - if (sz > static_cast(INT_MAX)) { - throw std::out_of_range("vector size is too big to be representable as int"); - } - - return static_cast(sz); -} -} // anonymous namespace - %} +%fragment("SWIG_VectorSize", "header", fragment="SWIG_JavaIntFromSize_t") { +SWIGINTERN jint SWIG_VectorSize(size_t size) { + jint sz = SWIG_JavaIntFromSize_t(size); + if (sz == -1) + throw std::out_of_range("vector size is too large to fit into a Java int"); + return sz; +} +} + %define SWIG_STD_VECTOR_MINIMUM_INTERNAL(CTYPE, CREF_TYPE) %typemap(javabase) std::vector< CTYPE > "java.util.AbstractList<$typemap(jboxtype, CTYPE)>" %typemap(javainterfaces) std::vector< CTYPE > "java.util.RandomAccess" @@ -94,16 +82,17 @@ int size_as_int(std::size_t sz) { bool empty() const; void clear(); %extend { - int doSize() const { - return size_as_int(self->size()); + %fragment("SWIG_VectorSize"); + jint doSize() const throw (std::out_of_range) { + return SWIG_VectorSize(self->size()); } void doAdd(const value_type& value) { self->push_back(value); } - void doAdd(int index, const value_type& value) throw (std::out_of_range) { - const int size = size_as_int(self->size()); + void doAdd(jint index, const value_type& value) throw (std::out_of_range) { + const jint size = SWIG_VectorSize(self->size()); if (0 <= index && index <= size) { self->insert(self->begin() + index, value); } else { @@ -111,8 +100,8 @@ int size_as_int(std::size_t sz) { } } - value_type doRemove(int index) throw (std::out_of_range) { - const int size = size_as_int(self->size()); + value_type doRemove(jint index) throw (std::out_of_range) { + const jint size = SWIG_VectorSize(self->size()); if (0 <= index && index < size) { CTYPE const old_value = (*self)[index]; self->erase(self->begin() + index); @@ -122,27 +111,27 @@ int size_as_int(std::size_t sz) { } } - CREF_TYPE doGet(int i) throw (std::out_of_range) { - const int size = size_as_int(self->size()); - if (i>=0 && isize()); + if (index >= 0 && index < size) + return (*self)[index]; else throw std::out_of_range("vector index out of range"); } - value_type doSet(int i, const value_type& value) throw (std::out_of_range) { - const int size = size_as_int(self->size()); - if (i>=0 && isize()); + if (index >= 0 && index < size) { + CTYPE const old_value = (*self)[index]; + (*self)[index] = value; return old_value; } else throw std::out_of_range("vector index out of range"); } - void doRemoveRange(int fromIndex, int toIndex) throw (std::out_of_range) { - const int size = size_as_int(self->size()); + void doRemoveRange(jint fromIndex, jint toIndex) throw (std::out_of_range) { + const jint size = SWIG_VectorSize(self->size()); if (0 <= fromIndex && fromIndex <= toIndex && toIndex <= size) { self->erase(self->begin() + fromIndex, self->begin() + toIndex); } else { From 30b7424f8ea663986aeed8694edabce6c2b41181 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Mon, 5 Jun 2017 19:15:32 +0100 Subject: [PATCH 136/455] Java std_vector runtime test From Volker Diels-Grabsch in SF patch https://sourceforge.net/p/swig/patches/278/ --- .../test-suite/java/li_std_vector_runme.java | 71 ++++++++++++++++++- 1 file changed, 68 insertions(+), 3 deletions(-) diff --git a/Examples/test-suite/java/li_std_vector_runme.java b/Examples/test-suite/java/li_std_vector_runme.java index b422655a4..21f35c269 100644 --- a/Examples/test-suite/java/li_std_vector_runme.java +++ b/Examples/test-suite/java/li_std_vector_runme.java @@ -4,7 +4,7 @@ public class li_std_vector_runme { static { try { - System.loadLibrary("li_std_vector"); + System.loadLibrary("li_std_vector"); } 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); @@ -17,8 +17,30 @@ public class li_std_vector_runme { IntPtrVector v2 = li_std_vector.vecintptr(new IntPtrVector()); IntConstPtrVector v3 = li_std_vector.vecintconstptr(new IntConstPtrVector()); - v1.add(123); - if (v1.get(0) != 123) throw new RuntimeException("v1 test failed"); + if (!v1.isEmpty()) throw new RuntimeException("v1 test (1) failed"); + if (v1.size() != 0) throw new RuntimeException("v1 test (2) failed"); + if (!v1.add(123)) throw new RuntimeException("v1 test (3) failed"); + if (v1.size() != 1) throw new RuntimeException("v1 test (4) failed"); + if (v1.isEmpty()) throw new RuntimeException("v1 test (5) failed"); + if (v1.set(0, 456) != 123) throw new RuntimeException("v1 test (6) failed"); + if (v1.size() != 1) throw new RuntimeException("v1 test (7) failed"); + if (v1.get(0) != 456) throw new RuntimeException("v1 test (8) failed"); + + java.util.Iterator v1_iterator = v1.iterator(); + if (!v1_iterator.hasNext()) throw new RuntimeException("v1 test (9) failed"); + if (v1_iterator.next() != 456) throw new RuntimeException("v1 test (10) failed"); + if (v1_iterator.hasNext()) throw new RuntimeException("v1 test (11) failed"); + try { + v1_iterator.next(); + throw new RuntimeException("v1 test (12) failed"); + } catch (java.util.NoSuchElementException e) { + } + + if (v1.remove(new Integer(123))) throw new RuntimeException("v1 test (13) failed"); + if (!v1.remove(new Integer(456))) throw new RuntimeException("v1 test (14) failed"); + if (!v1.isEmpty()) throw new RuntimeException("v1 test (15) failed"); + if (v1.size() != 0) throw new RuntimeException("v1 test (16) failed"); + if (v1.remove(new Integer(456))) throw new RuntimeException("v1 test (17) failed"); StructVector v4 = li_std_vector.vecstruct(new StructVector()); StructPtrVector v5 = li_std_vector.vecstructptr(new StructPtrVector()); @@ -32,5 +54,48 @@ public class li_std_vector_runme { if (v4.get(0).getNum() != 12) throw new RuntimeException("v4 test failed"); if (v5.get(0).getNum() != 34) throw new RuntimeException("v5 test failed"); if (v6.get(0).getNum() != 56) throw new RuntimeException("v6 test failed"); + + StructVector v7 = li_std_vector.vecstruct(new StructVector()); + v7.add(new Struct(1)); + v7.add(new Struct(23)); + v7.add(new Struct(456)); + v7.add(new Struct(7890)); + if (v7.size() != 4) throw new RuntimeException("v7 test (1) failed"); + { + double[] a7 = {1, 23, 456, 7890}; + int i7 = 0; + for (Struct s7 : v7) { + if (s7.getNum() != a7[i7]) throw new RuntimeException("v7 test (2) failed"); + i7++; + } + if (i7 != a7.length) throw new RuntimeException("v7 test (3) failed"); + } + if (v7.remove(2).getNum() != 456) throw new RuntimeException("v7 test (4) failed"); + { + double[] a7 = {1, 23, 7890}; + int i7 = 0; + for (Struct s7 : v7) { + if (s7.getNum() != a7[i7]) throw new RuntimeException("v7 test (5) failed"); + i7++; + } + if (i7 != a7.length) throw new RuntimeException("v7 test (6) failed"); + } + v7.add(1, new Struct(123)); + { + double[] a7 = {1, 123, 23, 7890}; + int i7 = 0; + for (Struct s7 : v7) { + if (s7.getNum() != a7[i7]) throw new RuntimeException("v7 test (7) failed"); + i7++; + } + if (i7 != a7.length) throw new RuntimeException("v7 test (8) failed"); + } + + BoolVector v8 = new BoolVector(); + if (!v8.add(true)) throw new RuntimeException("v8 test (1) failed");; + if (v8.get(0) != true) throw new RuntimeException("v8 test (2) failed");; + if (v8.set(0, false) != true) throw new RuntimeException("v8 test (3) failed");; + if (v8.set(0, false) != false) throw new RuntimeException("v8 test (4) failed");; + if (v8.size() != 1) throw new RuntimeException("v8 test (5) failed");; } } From bc7c80b8628a973d41aa8ebccd01773f76c75eb0 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Mon, 5 Jun 2017 19:33:45 +0100 Subject: [PATCH 137/455] More Java vector runtime tests --- Examples/test-suite/java/li_std_vector_runme.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Examples/test-suite/java/li_std_vector_runme.java b/Examples/test-suite/java/li_std_vector_runme.java index 1a1e3614e..60776bbf1 100644 --- a/Examples/test-suite/java/li_std_vector_runme.java +++ b/Examples/test-suite/java/li_std_vector_runme.java @@ -110,5 +110,12 @@ public class li_std_vector_runme { if (v8.set(0, false) != true) throw new RuntimeException("v8 test (3) failed");; if (v8.set(0, false) != false) throw new RuntimeException("v8 test (4) failed");; if (v8.size() != 1) throw new RuntimeException("v8 test (5) failed");; + + java.util.ArrayList bl = new java.util.ArrayList(java.util.Arrays.asList(true, false, true, false)); + BoolVector bv = new BoolVector(java.util.Arrays.asList(true, false, true, false)); + BoolVector bv2 = new BoolVector(bl); + java.util.ArrayList bl2 = new java.util.ArrayList(bv); + boolean bbb1 = bv.get(0); + Boolean bbb2 = bv.get(0); } } From e1a667bd52dd938bbb0d8ac4633668ecd6ee214e Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Mon, 5 Jun 2017 19:44:16 +0100 Subject: [PATCH 138/455] minor update to the changes file --- CHANGES.current | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/CHANGES.current b/CHANGES.current index f96beecbd..c0481b7af 100644 --- a/CHANGES.current +++ b/CHANGES.current @@ -30,8 +30,8 @@ Version 4.0.0 (in progress) *** POTENTIAL INCOMPATIBILITY *** 2017-05-26: Volker Diels-Grabsch, vadz - [Java] Implement java.util.List<> for std::vector. This notably allows to - iterate over wrapped vectors in a natural way. + [Java] #842 Extend from java.util.AbstractList<> and implement java.util.RandomAccess for + std::vector wrappers. This notably allows to iterate over wrapped vectors in a natural way. 2017-05-25: asibross [Java] #370 #417 Missing smart pointer handling in Java director extra methods @@ -83,10 +83,6 @@ Version 4.0.0 (in progress) [Scilab] New parameter targetversion to specify the Scilab target version (5, 6, ..) for code generation With Scilab 6 target specified, identifier names truncation is disabled (no longer necessary) -2017-02-29: tamuratak - [Ruby] #917 - Add Enumerable module to all container class wrappers. It was missing - for std::list, std::multiset, std::unordered_multiset and std::unordered_map. - 2017-03-24: tamuratak [Ruby] Fix #939 - Wrapping std::vector fix due to incorrect null checks on VALUE obj. @@ -118,6 +114,10 @@ Version 4.0.0 (in progress) auto sum1(int x, int y) const -> int { return x + y; } auto sum2(int x, int y) noexcept -> int { return x + y; } +2017-02-29: tamuratak + [Ruby] #917 - Add Enumerable module to all container class wrappers. It was missing + for std::list, std::multiset, std::unordered_multiset and std::unordered_map. + 2017-02-27: assambar [C++11] Extend parser to support throw specifier in combination with override and/or final. From 10e73a5bfbaf696a751fc8f83bd79dddfec9cf0c Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Mon, 5 Jun 2017 20:47:49 +0100 Subject: [PATCH 139/455] Java jboxtype typemap documentation and tidy up --- Doc/Manual/Java.html | 11 +++++++++++ Lib/java/java.swg | 29 ++++++++++++++--------------- 2 files changed, 25 insertions(+), 15 deletions(-) diff --git a/Doc/Manual/Java.html b/Doc/Manual/Java.html index c77724bf2..e0178465c 100644 --- a/Doc/Manual/Java.html +++ b/Doc/Manual/Java.html @@ -5693,6 +5693,17 @@ The most important of these implement the mapping of C/C++ types to Java types: In other words the typemap provides the conversion from the native method call return type. + +jboxtype +Java boxed type. + These are Java code typemaps to provide the Java boxed type, such as, Integer for C type int. + As autoboxing is only relevant to the Java primitive types, these are only provided for the + C types that map to Java primitive types. + This typemap is usually only used by C++ STL container wrappers that are wrapped by Java generic + types as the boxed type must be used instead of the unboxed/primitive type when declaring a Java generic type. + + + javadirectorin Conversion from jtype to jstype for director methods. diff --git a/Lib/java/java.swg b/Lib/java/java.swg index e0ddcba02..b49826ba0 100644 --- a/Lib/java/java.swg +++ b/Lib/java/java.swg @@ -111,25 +111,24 @@ SWIGINTERN jint SWIG_JavaIntFromSize_t(size_t size) { %typemap(jstype) double, const double & "double" %typemap(jstype) void "void" -%typemap(jboxtype) bool "Boolean" -%typemap(jboxtype) char "Character" -%typemap(jboxtype) signed char "Byte" -%typemap(jboxtype) unsigned char "Short" -%typemap(jboxtype) short "Short" -%typemap(jboxtype) unsigned short "Integer" -%typemap(jboxtype) int "Integer" -%typemap(jboxtype) unsigned int "Long" -%typemap(jboxtype) long "Integer" -%typemap(jboxtype) unsigned long "Long" -%typemap(jboxtype) long long "Long" -%typemap(jboxtype) unsigned long long "java.math.BigInteger" -%typemap(jboxtype) float "Float" -%typemap(jboxtype) double "Double" +%typemap(jboxtype) bool, const bool & "Boolean" +%typemap(jboxtype) char, const char & "Character" +%typemap(jboxtype) signed char, const signed char & "Byte" +%typemap(jboxtype) unsigned char, const unsigned char & "Short" +%typemap(jboxtype) short, const short & "Short" +%typemap(jboxtype) unsigned short, const unsigned short & "Integer" +%typemap(jboxtype) int, const int & "Integer" +%typemap(jboxtype) unsigned int, const unsigned int & "Long" +%typemap(jboxtype) long, const long & "Integer" +%typemap(jboxtype) unsigned long, const unsigned long & "Long" +%typemap(jboxtype) long long, const long long & "Long" +%typemap(jboxtype) unsigned long long, const unsigned long long & "java.math.BigInteger" +%typemap(jboxtype) float, const float & "Float" +%typemap(jboxtype) double, const double & "Double" %typemap(jni) char *, char *&, char[ANY], char[] "jstring" %typemap(jtype) char *, char *&, char[ANY], char[] "String" %typemap(jstype) char *, char *&, char[ANY], char[] "String" -%typemap(jboxtype) char *, char *&, char[ANY], char[] "String" /* JNI types */ %typemap(jni) jboolean "jboolean" From 0083d451db637a625069ef340ff87f336585bf0b Mon Sep 17 00:00:00 2001 From: Alan Woodland Date: Mon, 5 Jun 2017 21:57:23 +0100 Subject: [PATCH 140/455] Switched from autobox to jboxtype per #842 --- Lib/java/autobox.i | 70 --------------------------------------------- Lib/java/std_list.i | 7 ++--- 2 files changed, 3 insertions(+), 74 deletions(-) delete mode 100644 Lib/java/autobox.i diff --git a/Lib/java/autobox.i b/Lib/java/autobox.i deleted file mode 100644 index 9fe6b995c..000000000 --- a/Lib/java/autobox.i +++ /dev/null @@ -1,70 +0,0 @@ -/* - Java typemaps for autoboxing in return types of generics. - - Java generics let you define interfaces, e.g. Collection which operate on any homogenous - collection of Objects, with compile time type checking. For example Collection can - only store String objects and the compiler helps enforce that. - - Unfortunately Java treats primitive types as a special case. They're not first class objects, - so in order to have a collection of ints we have to actually maintain a Collection. - For each primitive type in Java (boolean, byte, short, int, long, float, double) there - exists a corresponding "proper" Object type in java.lang.*. - - Although these proper Objects include a constructor and a xValue() method that allow for - explicit conversion between primitives and the corresponding Object type if programmers - were required to explicitly perform this conversion every time it would rapidly become - tedious for no real benefits. To address this the language designers introduced the - concepts of "autoboxing" and a corresponding unboxing which can happen implicitly. Thus it - becomes legal to write: - - Collection c = new ArrayList(); - double d1 = 0; - c.add(d1); // 1: void add(Double); - double d2 = c.iterator().next(); // 2: Double next(); - - The conversions required to allow lines commented 1: and 2: to compile are inserted - implicitly. - - When it comes to wrapping primitives from C or C++ code to Java SWIG by default take the path - most expected. This means that double in C++ is represented by double in Java etc. as expected. - Normally this behaviour is ideal, however when it comes to wrapping C++ templates which are - being mapped onto implementations of Java interfaces this behaviour is unhelpful because it - is a syntax error in Java to claim to implement Collection instead of - Collection. - - So to transparently allow a C++ template when wrapped to Java to accept template type - parameters of primitive, struct, enum etc. fluidly from the user perspective we need to support - the same mapping, outside of the normal default. - - This autobox typemap exists to solve exactly that problem. With it we can map primitives onto - the corresponding java.lang.* type, whilst mapping all other types onto type that they would - usually map onto. (That is to say it falls back to simply be the result of the jstype typemap - for all non-primitive types). - - So for example if a given container template in exists in C++: - - template - struct ExampleContainer { - typedef T value_type; - // ..... - }; - - When wrapped in Java we'd like it to implement the Collection interface correctly, even for - primitives. With these autobox typemaps we can now simply write the following for example: - - %typemap(javabase) ExampleContainer "Collection<$typemap(autobox,$1_basetype::value_type)>" - - Which does exactly the right thing for both primitive and non-primitive types. - -*/ -%define AUTOBOX(CTYPE, JTYPE) -%typemap(autobox) CTYPE, const CTYPE& "JTYPE" -%enddef -AUTOBOX(double, Double) -AUTOBOX(float, Float) -AUTOBOX(boolean, Boolean) -AUTOBOX(signed char, Byte) -AUTOBOX(short, Short) -AUTOBOX(int, Integer) -AUTOBOX(long, Long) -AUTOBOX(SWIGTYPE, $typemap(jstype,$1_basetype)) diff --git a/Lib/java/std_list.i b/Lib/java/std_list.i index ac786910a..804223efd 100644 --- a/Lib/java/std_list.i +++ b/Lib/java/std_list.i @@ -1,5 +1,4 @@ %include -%include %{ #include @@ -61,7 +60,7 @@ namespace std { * interface and give "natural" semantics to Java users of the C++ iterator) */ //%typemap(javaclassmodifiers) iterator "public class" - //%typemap(javainterfaces) iterator "ListIterator<$typemap(autobox,$1_basetype::value_type)>" + //%typemap(javainterfaces) iterator "ListIterator<$typemap(jboxtype,$1_basetype::value_type)>" struct iterator { %extend { @@ -141,9 +140,9 @@ namespace std { import java.util.Collection; %} -%typemap(javabase) std::list "AbstractSequentialList<$typemap(autobox,$1_basetype::value_type)>" +%typemap(javabase) std::list "AbstractSequentialList<$typemap(jboxtype,$1_basetype::value_type)>" -#define JAVA_VALUE_TYPE $typemap(autobox,$1_basetype::value_type) +#define JAVA_VALUE_TYPE $typemap(jboxtype,$1_basetype::value_type) #define JAVA_ITERATOR_TYPE Iterator %typemap(javacode,noblock=1) std::list { From 0695cb72cb9727ea8ffbe7a41674f91a8f389a3c Mon Sep 17 00:00:00 2001 From: Alan Woodland Date: Mon, 5 Jun 2017 22:09:41 +0100 Subject: [PATCH 141/455] re-enabled li_std_list test --- Examples/test-suite/common.mk | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Examples/test-suite/common.mk b/Examples/test-suite/common.mk index f68451f87..11b1446e0 100644 --- a/Examples/test-suite/common.mk +++ b/Examples/test-suite/common.mk @@ -600,8 +600,8 @@ CPP_STD_TEST_CASES += \ smart_pointer_inherit \ template_typedef_fnc \ template_type_namespace \ - template_opaque -# li_std_list + template_opaque \ + li_std_list ifndef SKIP_CPP_STD_CASES From 00b0c5b8ea91493378bdc2e7c8fb6588c7d8e795 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Tue, 6 Jun 2017 06:59:23 +0100 Subject: [PATCH 142/455] Testcase fix for name clash in tcl headers --- Examples/test-suite/cpp11_constexpr.i | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Examples/test-suite/cpp11_constexpr.i b/Examples/test-suite/cpp11_constexpr.i index ef08a49c3..755efb0e0 100644 --- a/Examples/test-suite/cpp11_constexpr.i +++ b/Examples/test-suite/cpp11_constexpr.i @@ -6,14 +6,14 @@ %inline %{ #ifdef SWIG -#define CONST const +#define SWIGTESTCONST const #else -#define CONST +#define SWIGTESTCONST #endif constexpr int AAA = 10; constexpr const int BBB = 20; constexpr int CCC() { return 30; } -constexpr CONST int DDD() { return 40; } +constexpr SWIGTESTCONST int DDD() { return 40; } constexpr int XXX() { return 10; } constexpr int YYY = XXX() + 100; @@ -23,7 +23,7 @@ struct ConstExpressions { static constexpr int KKK = 200; static const int LLL = 300; constexpr int MMM() { return 400; } - constexpr CONST int NNN() { return 500; } + constexpr SWIGTESTCONST int NNN() { return 500; } // Regression tests for support added in SWIG 3.0.4: static constexpr const int JJJ1 = 101; constexpr static int KKK1 = 201; From b08d6ddbad85c1c38cbec8c53e1c5adb10be0f67 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Tue, 6 Jun 2017 07:14:18 +0100 Subject: [PATCH 143/455] Temporarily disable failing tests --- Examples/test-suite/go/Makefile.in | 3 +++ Examples/test-suite/scilab/Makefile.in | 3 +++ 2 files changed, 6 insertions(+) diff --git a/Examples/test-suite/go/Makefile.in b/Examples/test-suite/go/Makefile.in index b7be554d7..385f91002 100644 --- a/Examples/test-suite/go/Makefile.in +++ b/Examples/test-suite/go/Makefile.in @@ -38,6 +38,9 @@ CPP_TEST_CASES = \ MULTI_CPP_TEST_CASES = \ go_subdir_import +FAILING_CPP_TESTS = \ + import_fragments \ + include $(srcdir)/../common.mk INCLUDES = -I$(abs_top_srcdir)/$(EXAMPLES)/$(TEST_SUITE) diff --git a/Examples/test-suite/scilab/Makefile.in b/Examples/test-suite/scilab/Makefile.in index 483ed2439..ee0c19f6a 100644 --- a/Examples/test-suite/scilab/Makefile.in +++ b/Examples/test-suite/scilab/Makefile.in @@ -27,6 +27,9 @@ CPP_STD_TEST_CASES += \ li_std_container_typemaps \ li_std_string_extra \ +FAILING_MULTI_CPP_TESTS = \ + import_stl \ + include $(srcdir)/../common.mk # Overriden variables From 5d5fd5b1224bfba952328e1b2dcd09bea269456b Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Tue, 6 Jun 2017 19:56:59 +0100 Subject: [PATCH 144/455] Fix scilab fragment dependency problem in STL headers import_stl test now working again --- Examples/test-suite/scilab/Makefile.in | 3 --- Lib/scilab/scicontainer.swg | 7 ++++--- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/Examples/test-suite/scilab/Makefile.in b/Examples/test-suite/scilab/Makefile.in index ee0c19f6a..483ed2439 100644 --- a/Examples/test-suite/scilab/Makefile.in +++ b/Examples/test-suite/scilab/Makefile.in @@ -27,9 +27,6 @@ CPP_STD_TEST_CASES += \ li_std_container_typemaps \ li_std_string_extra \ -FAILING_MULTI_CPP_TESTS = \ - import_stl \ - include $(srcdir)/../common.mk # Overriden variables diff --git a/Lib/scilab/scicontainer.swg b/Lib/scilab/scicontainer.swg index 2cc44b8e5..f6078690b 100644 --- a/Lib/scilab/scicontainer.swg +++ b/Lib/scilab/scicontainer.swg @@ -42,7 +42,9 @@ %fragment("SciSequence_Cont", "header", fragment="StdTraits", - fragment="SwigSciIterator_T") + fragment="SwigSciIterator_T", + fragment=SWIG_Traits_Sequence_frag(ptr), + fragment=SWIG_Traits_SequenceItem_frag(ptr)) { namespace swig { @@ -334,8 +336,7 @@ namespace swig %fragment("StdSequenceTraits","header", fragment="StdTraits", - fragment="SciSequence_Cont", - fragment=SWIG_Traits_SequenceItem_frag(ptr)) + fragment="SciSequence_Cont") { namespace swig { template From 8855ef2b482c09da9255079b0fac92d08c8308fb Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Tue, 13 Jun 2017 17:32:37 +1200 Subject: [PATCH 145/455] [Perl] Fix testsuite to work without . in @INC "." was removed from @INC in Perl 5.26 for security reasons, and has also been removed from older versions in some distros. Fixes https://github.com/swig/swig/issues/997 reported by lfam. --- CHANGES.current | 6 ++++++ Examples/Makefile.in | 2 +- Examples/test-suite/perl5/run-perl-test.pl | 2 +- 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/CHANGES.current b/CHANGES.current index ac620c96b..6b379a94b 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.0.0 (in progress) =========================== +2017-06-13: olly + [Perl] Fix testsuite to work without . in @INC - it was removed in + Perl 5.26 for security reasons, and has also been removed from + older versions in some distros. Fixes + https://github.com/swig/swig/issues/997 reported by lfam. + 2017-06-03: wsfulton Fix %import on a file containing a file scope %fragment forced inclusion to not generate the fragment contents as %import should not result in code being generated. diff --git a/Examples/Makefile.in b/Examples/Makefile.in index 7682b565f..8a88fb5ea 100644 --- a/Examples/Makefile.in +++ b/Examples/Makefile.in @@ -282,7 +282,7 @@ perl5_static_cpp: $(SRCDIR_SRCS) # ----------------------------------------------------------------- perl5_run: - $(RUNTOOL) $(PERL) $(PERL5_SCRIPT) $(RUNPIPE) + $(RUNTOOL) $(PERL) -I. $(PERL5_SCRIPT) $(RUNPIPE) # ----------------------------------------------------------------- # Version display diff --git a/Examples/test-suite/perl5/run-perl-test.pl b/Examples/test-suite/perl5/run-perl-test.pl index 106bf002b..5ea4e5115 100644 --- a/Examples/test-suite/perl5/run-perl-test.pl +++ b/Examples/test-suite/perl5/run-perl-test.pl @@ -7,7 +7,7 @@ use strict; my $command = shift @ARGV; -my $output = `$^X $command 2>&1`; +my $output = `$^X -I. $command 2>&1`; die "SWIG Perl test failed: \n\n$output\n" if $?; From 82969b07557bd7212b20373841406d4489dc5d78 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Tue, 13 Jun 2017 19:02:59 +0100 Subject: [PATCH 146/455] Fix warning in generated code - traits_asptr. Visual Studio 2015 debug builds: error C4703: potentially uninitialized local pointer variable 'p' used --- Lib/octave/octstdcommon.swg | 2 +- Lib/python/pystdcommon.swg | 2 +- Lib/r/rstdcommon.swg | 2 +- Lib/ruby/rubystdcommon.swg | 2 +- Lib/scilab/scistdcommon.swg | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Lib/octave/octstdcommon.swg b/Lib/octave/octstdcommon.swg index 799d369a7..b3b3d0048 100644 --- a/Lib/octave/octstdcommon.swg +++ b/Lib/octave/octstdcommon.swg @@ -41,7 +41,7 @@ namespace swig { template struct traits_asptr { static int asptr(const octave_value& obj, Type **val) { - Type *p; + Type *p = 0; swig_type_info *descriptor = type_info(); int res = descriptor ? SWIG_ConvertPtr(obj, (void **)&p, descriptor, 0) : SWIG_ERROR; if (SWIG_IsOK(res)) { diff --git a/Lib/python/pystdcommon.swg b/Lib/python/pystdcommon.swg index 8372426a0..93ee34bc7 100644 --- a/Lib/python/pystdcommon.swg +++ b/Lib/python/pystdcommon.swg @@ -45,7 +45,7 @@ namespace swig { template struct traits_asptr { static int asptr(PyObject *obj, Type **val) { - Type *p; + Type *p = 0; swig_type_info *descriptor = type_info(); int res = descriptor ? SWIG_ConvertPtr(obj, (void **)&p, descriptor, 0) : SWIG_ERROR; if (SWIG_IsOK(res)) { diff --git a/Lib/r/rstdcommon.swg b/Lib/r/rstdcommon.swg index e6c873a07..557dac71b 100644 --- a/Lib/r/rstdcommon.swg +++ b/Lib/r/rstdcommon.swg @@ -39,7 +39,7 @@ namespace swig { template struct traits_asptr { static int asptr(SWIG_Object obj, Type **val) { - Type *p; + Type *p = 0; swig_type_info *descriptor = type_info(); int res = descriptor ? SWIG_ConvertPtr(obj, (void **)&p, descriptor, 0) : SWIG_ERROR; if (SWIG_IsOK(res)) { diff --git a/Lib/ruby/rubystdcommon.swg b/Lib/ruby/rubystdcommon.swg index 5cbdb430d..c34dacefb 100644 --- a/Lib/ruby/rubystdcommon.swg +++ b/Lib/ruby/rubystdcommon.swg @@ -53,7 +53,7 @@ namespace swig { template struct traits_asptr { static int asptr(VALUE obj, Type **val) { - Type *p; + Type *p = 0; swig_type_info *descriptor = type_info(); int res = descriptor ? SWIG_ConvertPtr(obj, (void **)&p, descriptor, 0) : SWIG_ERROR; if (SWIG_IsOK(res)) { diff --git a/Lib/scilab/scistdcommon.swg b/Lib/scilab/scistdcommon.swg index 63f3ca164..975e93a7b 100644 --- a/Lib/scilab/scistdcommon.swg +++ b/Lib/scilab/scistdcommon.swg @@ -41,7 +41,7 @@ namespace swig { template struct traits_asptr { static int asptr(const SwigSciObject& obj, Type **val) { - Type *p; + Type *p = 0; swig_type_info *descriptor = type_info(); int res = descriptor ? SWIG_ConvertPtr(obj, (void **)&p, descriptor, 0) : SWIG_ERROR; if (SWIG_IsOK(res)) { From 5b0611dbcd65399a5167db7aa1d2424220d072f6 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Tue, 13 Jun 2017 19:36:35 +0100 Subject: [PATCH 147/455] Fix compiler flags used during R testing CFLAGS and CXXFLAGS were not being passed properly when compiling wrappers. --- Examples/Makefile.in | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Examples/Makefile.in b/Examples/Makefile.in index 8a88fb5ea..e29a7608a 100644 --- a/Examples/Makefile.in +++ b/Examples/Makefile.in @@ -1693,7 +1693,7 @@ r: $(SRCDIR_SRCS) ifneq ($(SRCDIR_SRCS),) $(CC) -g -c $(CPPFLAGS) $(CFLAGS) $(R_CFLAGS) $(SRCDIR_SRCS) $(INCLUDES) endif - +( PKG_CPPFLAGS="$(CPPFLAGS) $(INCLUDES)" $(COMPILETOOL) $(R) CMD SHLIB -o $(LIBPREFIX)$(TARGET)$(SO) $(ISRCS) $(OBJS) > /dev/null ) + +( PKG_CPPFLAGS="$(CPPFLAGS) $(INCLUDES)" PKG_CFLAGS="$(CFLAGS)" $(COMPILETOOL) $(R) CMD SHLIB -o $(LIBPREFIX)$(TARGET)$(SO) $(ISRCS) $(OBJS) > /dev/null ) # ---------------------------------------------------------------- # Build a R dynamically loadable module (C++) @@ -1703,7 +1703,7 @@ r_cpp: $(SRCDIR_CXXSRCS) ifneq ($(SRCDIR_CXXSRCS),) $(CXX) -g -c $(CPPFLAGS) $(CXXFLAGS) $(R_CFLAGS) $(SRCDIR_CXXSRCS) $(INCLUDES) endif - +( PKG_CPPFLAGS="$(CPPFLAGS) $(INCLUDES)" $(COMPILETOOL) $(R) CMD SHLIB -o $(LIBPREFIX)$(TARGET)$(SO) $(RCXXSRCS) $(OBJS) > /dev/null ) + +( PKG_CPPFLAGS="$(CPPFLAGS) $(INCLUDES)" PKG_CXXFLAGS="$(CXXFLAGS)" $(COMPILETOOL) $(R) CMD SHLIB -o $(LIBPREFIX)$(TARGET)$(SO) $(RCXXSRCS) $(OBJS) > /dev/null ) # ----------------------------------------------------------------- # Run R example From 6a7cd97fe9f3186b1105bd063fb2eb117dd3c87d Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Fri, 16 Jun 2017 07:02:07 +0100 Subject: [PATCH 148/455] Fix R function pointer wrappers containing lvalue and rvalue reference parameters --- CHANGES.current | 3 ++ Examples/test-suite/cpp11_rvalue_reference2.i | 9 +++--- Examples/test-suite/funcptr_cpp.i | 2 ++ Source/Modules/r.cxx | 31 ++++++++++++------- 4 files changed, 30 insertions(+), 15 deletions(-) diff --git a/CHANGES.current b/CHANGES.current index 6b379a94b..7c879fb28 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.0.0 (in progress) =========================== +2017-06-16: wsfulton + [R] Fix wrapping function pointers containing rvalue and lvalue reference parameters. + 2017-06-13: olly [Perl] Fix testsuite to work without . in @INC - it was removed in Perl 5.26 for security reasons, and has also been removed from diff --git a/Examples/test-suite/cpp11_rvalue_reference2.i b/Examples/test-suite/cpp11_rvalue_reference2.i index d532e29f3..dd6c98d0b 100644 --- a/Examples/test-suite/cpp11_rvalue_reference2.i +++ b/Examples/test-suite/cpp11_rvalue_reference2.i @@ -55,10 +55,11 @@ short && func(short &&i) { return std::move(i); } Thingy getit() { return Thingy(22, std::move(glob)); } void rvalrefFunction1(int &&v = (int &&)5) {} -void rvalrefFunctionBYVAL(short (Thingy::*memFunc)(short)) {} -void rvalrefFunctionLVALUE(short &(Thingy::*memFunc)(short &)) {} -void rvalrefFunction2(short && (Thingy::*memFunc)(short &&)) {} -void rvalrefFunction3(short && (*memFunc)(short &&)) {} +void rvalrefFunctionBYVAL(short (Thingy::*fptr)(short)) {} +void rvalrefFunctionPTR(short * (*fptr)(short *)) {} +void rvalrefFunctionLVALUE(short & (Thingy::*fptr)(short &)) {} +void rvalrefFunction2(short && (Thingy::*fptr)(short &&)) {} +void rvalrefFunction3(short && (*fptr)(short &&)) {} template struct RemoveReference { typedef T type; diff --git a/Examples/test-suite/funcptr_cpp.i b/Examples/test-suite/funcptr_cpp.i index b63749dc1..8e05d308d 100644 --- a/Examples/test-suite/funcptr_cpp.i +++ b/Examples/test-suite/funcptr_cpp.i @@ -15,6 +15,8 @@ int & addByReference(const int &a, int b) { static int val; val = a+b; return va int call1(int (*d)(const int &, int), int a, int b) { return d(a, b); } int call2(int * (*d)(const int &, int), int a, int b) { return *d(a, b); } int call3(int & (*d)(const int &, int), int a, int b) { return d(a, b); } +int call4(int & (*d)(int &, int *), int a, int b) { return d(a, &b); } +int call5(int & (*d)(int &, int const * const), int a, int b) { return d(a, &b); } %} %constant int (*ADD_BY_VALUE)(const int &, int) = addByValue; diff --git a/Source/Modules/r.cxx b/Source/Modules/r.cxx index 74130aac3..1c8533064 100644 --- a/Source/Modules/r.cxx +++ b/Source/Modules/r.cxx @@ -573,7 +573,7 @@ String * R::createFunctionPointerHandler(SwigType *t, Node *n, int *numArgs) { String *lname; if (!arg && Cmp(Getattr(p, "type"), "void")) { - lname = NewStringf("s_arg%d", i+1); + lname = NewStringf("arg%d", i+1); Setattr(p, "name", lname); } else lname = arg; @@ -616,19 +616,25 @@ String * R::createFunctionPointerHandler(SwigType *t, Node *n, int *numArgs) { for(i = 0; p; i++) { SwigType *tt = Getattr(p, "type"); SwigType *name = Getattr(p, "name"); + SwigType *swig_parm_name = NewStringf("swigarg_%s", name); String *tm = Getattr(p, "tmap:out"); - Printf(f->def, "%s %s", SwigType_str(tt, 0), name); - if(tm) { - Replaceall(tm, "$1", name); - if (SwigType_isreference(tt)) { - String *tmp = NewString(""); - Append(tmp, "*"); - Append(tmp, name); - Replaceall(tm, tmp, name); + bool isVoidParm = Strcmp(tt, "void") == 0; + if (isVoidParm) + Printf(f->def, "%s", SwigType_str(tt, 0)); + else + Printf(f->def, "%s %s", SwigType_str(tt, 0), swig_parm_name); + if (tm) { + String *lstr = SwigType_lstr(tt, 0); + if (SwigType_isreference(tt) || SwigType_isrvalue_reference(tt)) { + Printf(f->code, "%s = (%s) &%s;\n", Getattr(p, "lname"), lstr, swig_parm_name); + } else if (!isVoidParm) { + Printf(f->code, "%s = (%s) %s;\n", Getattr(p, "lname"), lstr, swig_parm_name); } + Replaceall(tm, "$1", name); Replaceall(tm, "$result", "r_tmp"); replaceRClass(tm, Getattr(p,"type")); Replaceall(tm,"$owner", "R_SWIG_EXTERNAL"); + Delete(lstr); } Printf(setExprElements, "%s\n", tm); @@ -697,10 +703,13 @@ String * R::createFunctionPointerHandler(SwigType *t, Node *n, int *numArgs) { Printv(f->code, "R_SWIG_popCallbackFunctionData(1);\n", NIL); Printv(f->code, "\n", UnProtectWrapupCode, NIL); - if (SwigType_isreference(rettype)) { + if (SwigType_isreference(rettype)) { Printv(f->code, "return *", Swig_cresult_name(), ";\n", NIL); - } else if(!isVoidType) + } else if (SwigType_isrvalue_reference(rettype)) { + Printv(f->code, "return std::move(*", Swig_cresult_name(), ");\n", NIL); + } else if (!isVoidType) { Printv(f->code, "return ", Swig_cresult_name(), ";\n", NIL); + } Printv(f->code, "\n}\n", NIL); Replaceall(f->code, "SWIG_exception_fail", "SWIG_exception_noreturn"); From b2e494f018edb2b358f39eaee2e925620f61a81a Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Fri, 16 Jun 2017 07:38:26 +0100 Subject: [PATCH 149/455] Add R to c++11 and c++14 Travis testing --- .travis.yml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/.travis.yml b/.travis.yml index fd70c9160..5f09c87ec 100644 --- a/.travis.yml +++ b/.travis.yml @@ -236,6 +236,10 @@ matrix: env: SWIGLANG=python SWIG_CC=gcc-5 SWIG_CXX=g++-5 CPP11=1 sudo: required dist: trusty + - os: linux + env: SWIGLANG=r SWIG_CC=gcc-5 SWIG_CXX=g++-5 CPP11=1 + sudo: required + dist: trusty - os: linux env: SWIGLANG=ruby SWIG_CC=gcc-5 SWIG_CXX=g++-5 CPP11=1 sudo: required @@ -260,6 +264,10 @@ matrix: env: SWIGLANG=python SWIG_CC=gcc-6 SWIG_CXX=g++-6 CPP14=1 sudo: required dist: trusty + - os: linux + env: SWIGLANG=r SWIG_CC=gcc-6 SWIG_CXX=g++-6 CPP14=1 + sudo: required + dist: trusty - os: linux env: SWIGLANG=ruby SWIG_CC=gcc-6 SWIG_CXX=g++-6 CPP14=1 sudo: required From 67190cbb2e61e7d13d063e4fba81ee9ff13aa971 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Fri, 16 Jun 2017 09:04:36 +0100 Subject: [PATCH 150/455] Add import_fragment test back in to Go test-suite --- Examples/test-suite/go/Makefile.in | 3 --- Examples/test-suite/import_fragments_a.i | 3 +++ 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Examples/test-suite/go/Makefile.in b/Examples/test-suite/go/Makefile.in index 385f91002..b7be554d7 100644 --- a/Examples/test-suite/go/Makefile.in +++ b/Examples/test-suite/go/Makefile.in @@ -38,9 +38,6 @@ CPP_TEST_CASES = \ MULTI_CPP_TEST_CASES = \ go_subdir_import -FAILING_CPP_TESTS = \ - import_fragments \ - include $(srcdir)/../common.mk INCLUDES = -I$(abs_top_srcdir)/$(EXAMPLES)/$(TEST_SUITE) diff --git a/Examples/test-suite/import_fragments_a.i b/Examples/test-suite/import_fragments_a.i index 7478a1e86..1babea95f 100644 --- a/Examples/test-suite/import_fragments_a.i +++ b/Examples/test-suite/import_fragments_a.i @@ -1,4 +1,7 @@ +#if !defined(SWIGGO) +// Prevent Go from generating a Go module import - this test is not set up as true multiple modules %module import_fragments_a +#endif %fragment("ImportA1", "header") %{ ImportA1_this_will_not_compile; From 95e8643d7077548392ce1bcccd9d1a4d961383ba Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Fri, 16 Jun 2017 19:13:58 +0100 Subject: [PATCH 151/455] Rename func to funk in tests to avoid Go keyword problems --- Examples/test-suite/cpp11_default_delete.i | 8 ++++---- Examples/test-suite/cpp11_rvalue_reference2.i | 2 +- Examples/test-suite/cpp11_type_aliasing.i | 2 +- .../java/java_director_assumeoverride_runme.java | 2 +- Examples/test-suite/java_director_assumeoverride.i | 4 ++-- Examples/test-suite/javascript/null_pointer_runme.js | 2 +- Examples/test-suite/name_warnings.i | 4 +--- Examples/test-suite/null_pointer.i | 4 +--- Examples/test-suite/octave/null_pointer_runme.m | 2 +- Examples/test-suite/octave/octave_cell_deref_runme.m | 4 ++-- Examples/test-suite/octave_cell_deref.i | 2 +- Examples/test-suite/python/python_append_runme.py | 2 +- Examples/test-suite/python_append.i | 6 +++--- Examples/test-suite/scilab/null_pointer_runme.sci | 2 +- Examples/test-suite/simutry.i | 6 +++--- Examples/test-suite/tcl/null_pointer_runme.tcl | 2 +- 16 files changed, 25 insertions(+), 29 deletions(-) diff --git a/Examples/test-suite/cpp11_default_delete.i b/Examples/test-suite/cpp11_default_delete.i index 79c02cddc..b5e84ed51 100644 --- a/Examples/test-suite/cpp11_default_delete.i +++ b/Examples/test-suite/cpp11_default_delete.i @@ -17,20 +17,20 @@ public: }; struct A1 { - void func(int i) {} + void funk(int i) {} A1() = default; ~A1() = default; - void func(double i) = delete; /* Don't cast double to int. Compiler returns an error */ + void funk(double i) = delete; /* Don't cast double to int. Compiler returns an error */ private: A1(const A1&); }; A1::A1(const A1&) = default; struct A2 { - void func(int i) {} + void funk(int i) {} virtual void fff(int) = delete; virtual ~A2() = default; - template void func(T) = delete; + template void funk(T) = delete; }; struct trivial { diff --git a/Examples/test-suite/cpp11_rvalue_reference2.i b/Examples/test-suite/cpp11_rvalue_reference2.i index dd6c98d0b..9aaf4accb 100644 --- a/Examples/test-suite/cpp11_rvalue_reference2.i +++ b/Examples/test-suite/cpp11_rvalue_reference2.i @@ -51,7 +51,7 @@ int glob = 123; Thingy &&globalrrval = Thingy(55, std::move(glob)); -short && func(short &&i) { return std::move(i); } +short && funk(short &&i) { return std::move(i); } Thingy getit() { return Thingy(22, std::move(glob)); } void rvalrefFunction1(int &&v = (int &&)5) {} diff --git a/Examples/test-suite/cpp11_type_aliasing.i b/Examples/test-suite/cpp11_type_aliasing.i index 2f6ea3aa7..abc1642c4 100644 --- a/Examples/test-suite/cpp11_type_aliasing.i +++ b/Examples/test-suite/cpp11_type_aliasing.i @@ -108,5 +108,5 @@ PairSubclass::data_t plus1(PairSubclass::const_ref_data_t x) { return x + 1; } using callback_t = int(*)(int); callback_t get_callback() { return mult2; } -int call(callback_t func, int param) { return func(param); } +int call(callback_t funk, int param) { return funk(param); } %} diff --git a/Examples/test-suite/java/java_director_assumeoverride_runme.java b/Examples/test-suite/java/java_director_assumeoverride_runme.java index e876a79c9..6c4d6918e 100644 --- a/Examples/test-suite/java/java_director_assumeoverride_runme.java +++ b/Examples/test-suite/java/java_director_assumeoverride_runme.java @@ -18,7 +18,7 @@ public class java_director_assumeoverride_runme { public static void main(String argv[]) { OverrideMe overrideMe = new MyOverrideMe(); - // MyOverrideMe doesn't actually override func(), but because assumeoverride + // MyOverrideMe doesn't actually override funk(), but because assumeoverride // was set to true, the C++ side will believe it was overridden. if (!java_director_assumeoverride.isFuncOverridden(overrideMe)) { throw new RuntimeException ( "isFuncOverridden()" ); diff --git a/Examples/test-suite/java_director_assumeoverride.i b/Examples/test-suite/java_director_assumeoverride.i index cddebb4d7..f0eb37049 100644 --- a/Examples/test-suite/java_director_assumeoverride.i +++ b/Examples/test-suite/java_director_assumeoverride.i @@ -4,7 +4,7 @@ class OverrideMe { public: virtual ~OverrideMe() {} - virtual void func() {}; + virtual void funk() {}; }; #include "java_director_assumeoverride_wrap.h" @@ -23,7 +23,7 @@ bool isFuncOverridden(OverrideMe* f) { class OverrideMe { public: virtual ~OverrideMe(); - virtual void func(); + virtual void funk(); }; bool isFuncOverridden(OverrideMe* f); diff --git a/Examples/test-suite/javascript/null_pointer_runme.js b/Examples/test-suite/javascript/null_pointer_runme.js index 7c0d61244..8a9b61186 100644 --- a/Examples/test-suite/javascript/null_pointer_runme.js +++ b/Examples/test-suite/javascript/null_pointer_runme.js @@ -1,6 +1,6 @@ var null_pointer = require("null_pointer"); -if (!null_pointer.func(null)) { +if (!null_pointer.funk(null)) { throw new Error("Javascript 'null' should be converted into NULL."); } diff --git a/Examples/test-suite/name_warnings.i b/Examples/test-suite/name_warnings.i index 3455c03bf..0b62ec5d7 100644 --- a/Examples/test-suite/name_warnings.i +++ b/Examples/test-suite/name_warnings.i @@ -40,9 +40,7 @@ namespace std #endif virtual ~A() {} -#ifndef SWIGGO // func is a keyword in Go. - virtual int func() = 0; -#endif + virtual int funk() = 0; private: typedef complex False; }; diff --git a/Examples/test-suite/null_pointer.i b/Examples/test-suite/null_pointer.i index 0da827f99..f40d6929f 100644 --- a/Examples/test-suite/null_pointer.i +++ b/Examples/test-suite/null_pointer.i @@ -1,11 +1,9 @@ %module null_pointer -%warnfilter(SWIGWARN_PARSE_KEYWORD) func; // 'func' is a Go keyword, renamed as 'Xfunc' - %inline { struct A {}; - bool func(A* a) { + bool funk(A* a) { return !a; } diff --git a/Examples/test-suite/octave/null_pointer_runme.m b/Examples/test-suite/octave/null_pointer_runme.m index 9d55d8be2..72362f451 100644 --- a/Examples/test-suite/octave/null_pointer_runme.m +++ b/Examples/test-suite/octave/null_pointer_runme.m @@ -5,4 +5,4 @@ endif null_pointer; -assert(func([])); +assert(funk([])); diff --git a/Examples/test-suite/octave/octave_cell_deref_runme.m b/Examples/test-suite/octave/octave_cell_deref_runme.m index d00d17282..0a45999d3 100644 --- a/Examples/test-suite/octave/octave_cell_deref_runme.m +++ b/Examples/test-suite/octave/octave_cell_deref_runme.m @@ -5,8 +5,8 @@ endif octave_cell_deref; -assert(func("hello")); -assert(func({"hello"})); +assert(funk("hello")); +assert(funk({"hello"})); c = func2(); assert(strcmp(c{1}, "hello")); diff --git a/Examples/test-suite/octave_cell_deref.i b/Examples/test-suite/octave_cell_deref.i index 2e92ec4de..272ba7c99 100644 --- a/Examples/test-suite/octave_cell_deref.i +++ b/Examples/test-suite/octave_cell_deref.i @@ -1,7 +1,7 @@ %module octave_cell_deref %inline { - bool func(const char* s) { + bool funk(const char* s) { return !strcmp("hello",s); } diff --git a/Examples/test-suite/python/python_append_runme.py b/Examples/test-suite/python/python_append_runme.py index 6675f3509..ce5514dff 100644 --- a/Examples/test-suite/python/python_append_runme.py +++ b/Examples/test-suite/python/python_append_runme.py @@ -9,7 +9,7 @@ if is_python_builtin(): exit(0) t = Test() -t.func() +t.funk() if is_new_style_class(Test): t.static_func() else: diff --git a/Examples/test-suite/python_append.i b/Examples/test-suite/python_append.i index 2a71b5784..049494319 100644 --- a/Examples/test-suite/python_append.i +++ b/Examples/test-suite/python_append.i @@ -17,11 +17,11 @@ def clearstaticpath(): staticfuncpath = None %} -%pythonappend Test::func %{ +%pythonappend Test::funk %{ funcpath = os.path.dirname(funcpath) %} -%pythonprepend Test::func %{ +%pythonprepend Test::funk %{ global funcpath funcpath = mypath %} @@ -46,7 +46,7 @@ import os.path class Test { public: static void static_func() {}; - void func() {}; + void funk() {}; }; #ifdef SWIGPYTHON_BUILTIN diff --git a/Examples/test-suite/scilab/null_pointer_runme.sci b/Examples/test-suite/scilab/null_pointer_runme.sci index 2c693d259..dab59acf8 100644 --- a/Examples/test-suite/scilab/null_pointer_runme.sci +++ b/Examples/test-suite/scilab/null_pointer_runme.sci @@ -2,6 +2,6 @@ exec("swigtest.start", -1); p = getnull(); checkequal(SWIG_this(p), 0, "SWIG_this(p)"); -checkequal(func(p), %T, "func(p)"); +checkequal(funk(p), %T, "funk(p)"); exec("swigtest.quit", -1); diff --git a/Examples/test-suite/simutry.i b/Examples/test-suite/simutry.i index addea14db..ad45da425 100644 --- a/Examples/test-suite/simutry.i +++ b/Examples/test-suite/simutry.i @@ -23,7 +23,7 @@ namespace simuPOP { } - virtual int func() const + virtual int funk() const { return m_pop.m_a; } }; @@ -32,7 +32,7 @@ namespace simuPOP struct DerivedOperator: public Operator { DerivedOperator(int a):Operator(a){} - virtual int func() const + virtual int funk() const { return 2*this->m_pop.m_a; } }; @@ -90,7 +90,7 @@ namespace simuPOP void test( const std::vector< Operator*>& para) { for( size_t i =0; i < para.size(); ++i) - para[i]->func(); + para[i]->funk(); } } } diff --git a/Examples/test-suite/tcl/null_pointer_runme.tcl b/Examples/test-suite/tcl/null_pointer_runme.tcl index be99c7166..7ed87c153 100644 --- a/Examples/test-suite/tcl/null_pointer_runme.tcl +++ b/Examples/test-suite/tcl/null_pointer_runme.tcl @@ -3,7 +3,7 @@ if [ catch { load ./null_pointer[info sharedlibextension] null_pointer} err_msg } set a [A] -if {[func $a] != 0} { +if {[funk $a] != 0} { puts stderr "null_pointer test 1 failed" exit 1 } From 11aa71b93919213bf3952ecf08ff1a5496bb1f83 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Fri, 16 Jun 2017 19:20:50 +0100 Subject: [PATCH 152/455] Make sure warning and error messages are not split up They could be split up by other processes writing to stdout at the same time. --- CHANGES.current | 4 ++++ Source/Swig/error.c | 19 +++++++++++++------ 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/CHANGES.current b/CHANGES.current index 7c879fb28..65180f4e0 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.0.0 (in progress) =========================== +2017-06-16: wsfulton + Make sure warning and error messages are not split up by other processes writing to + stdout at the same time. + 2017-06-16: wsfulton [R] Fix wrapping function pointers containing rvalue and lvalue reference parameters. diff --git a/Source/Swig/error.c b/Source/Swig/error.c index 2c93cfb21..1dde06652 100644 --- a/Source/Swig/error.c +++ b/Source/Swig/error.c @@ -106,13 +106,16 @@ void Swig_warning(int wnum, const_String_or_char_ptr filename, int line, const c } if (warnall || wrn) { String *formatted_filename = format_filename(filename); + String *full_message = NewString(""); if (wnum) { - Printf(stderr, wrn_wnum_fmt, formatted_filename, line, wnum); + Printf(full_message, wrn_wnum_fmt, formatted_filename, line, wnum); } else { - Printf(stderr, wrn_nnum_fmt, formatted_filename, line); + Printf(full_message, wrn_nnum_fmt, formatted_filename, line); } - Printf(stderr, "%s", msg); + Printf(full_message, "%s", msg); + Printv(stderr, full_message, NIL); nwarning++; + Delete(full_message); Delete(formatted_filename); } Delete(out); @@ -128,6 +131,7 @@ void Swig_warning(int wnum, const_String_or_char_ptr filename, int line, const c void Swig_error(const_String_or_char_ptr filename, int line, const char *fmt, ...) { va_list ap; String *formatted_filename = NULL; + String *full_message = NULL; if (silence) return; @@ -136,14 +140,17 @@ void Swig_error(const_String_or_char_ptr filename, int line, const char *fmt, .. va_start(ap, fmt); formatted_filename = format_filename(filename); + full_message = NewString(""); if (line > 0) { - Printf(stderr, err_line_fmt, formatted_filename, line); + Printf(full_message, err_line_fmt, formatted_filename, line); } else { - Printf(stderr, err_eof_fmt, formatted_filename); + Printf(full_message, err_eof_fmt, formatted_filename); } - vPrintf(stderr, fmt, ap); + vPrintf(full_message, fmt, ap); + Printv(stderr, full_message, NIL); va_end(ap); nerrors++; + Delete(full_message); Delete(formatted_filename); } From 5679bce94fdc586c8a239ccc9368d3390c6d1444 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Fri, 16 Jun 2017 20:36:52 +0100 Subject: [PATCH 153/455] Revert "Add R to c++11 and c++14 Travis testing" This reverts commit b2e494f018edb2b358f39eaee2e925620f61a81a. --- .travis.yml | 8 -------- 1 file changed, 8 deletions(-) diff --git a/.travis.yml b/.travis.yml index 5f09c87ec..fd70c9160 100644 --- a/.travis.yml +++ b/.travis.yml @@ -236,10 +236,6 @@ matrix: env: SWIGLANG=python SWIG_CC=gcc-5 SWIG_CXX=g++-5 CPP11=1 sudo: required dist: trusty - - os: linux - env: SWIGLANG=r SWIG_CC=gcc-5 SWIG_CXX=g++-5 CPP11=1 - sudo: required - dist: trusty - os: linux env: SWIGLANG=ruby SWIG_CC=gcc-5 SWIG_CXX=g++-5 CPP11=1 sudo: required @@ -264,10 +260,6 @@ matrix: env: SWIGLANG=python SWIG_CC=gcc-6 SWIG_CXX=g++-6 CPP14=1 sudo: required dist: trusty - - os: linux - env: SWIGLANG=r SWIG_CC=gcc-6 SWIG_CXX=g++-6 CPP14=1 - sudo: required - dist: trusty - os: linux env: SWIGLANG=ruby SWIG_CC=gcc-6 SWIG_CXX=g++-6 CPP14=1 sudo: required From 5386bf2a2484c0db5d8dcb9c050e480b30f2d28e Mon Sep 17 00:00:00 2001 From: Fabrice Benhamouda Date: Thu, 15 Jun 2017 17:18:52 -0400 Subject: [PATCH 154/455] fix swig/swig#600 and fix swig/swig#955 --- Examples/go/callback/gocallback.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Examples/go/callback/gocallback.go b/Examples/go/callback/gocallback.go index 20fd0627a..881f505e0 100644 --- a/Examples/go/callback/gocallback.go +++ b/Examples/go/callback/gocallback.go @@ -36,6 +36,6 @@ func DeleteGoCallback(p GoCallback) { p.deleteCallback() } -func (p *goCallback) Run() { +func (p *overwrittenMethodsOnCallback) Run() { fmt.Println("GoCallback.Run") } From d5d4f180217d38897b44ecbcd892dafe4a129a93 Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Sat, 17 Jun 2017 11:41:24 +1200 Subject: [PATCH 155/455] [Go] Fix Go callback example Fixes github #600, #955, #1000 --- CHANGES.current | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGES.current b/CHANGES.current index 65180f4e0..584fa6cb8 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.0.0 (in progress) =========================== +2017-06-17: fabrice102 + [Go] Fix Go callback example. Fixes github #600, #955, #1000. + 2017-06-16: wsfulton Make sure warning and error messages are not split up by other processes writing to stdout at the same time. From f12d14d1be51e21f39ff806175d6ff2eb7210f90 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Sat, 17 Jun 2017 10:32:26 +0100 Subject: [PATCH 156/455] Turn on C++11 Travis testing for R R tests use 'R CMD SHLIB' to compile the wrappers and there is no easy way to change the compiler this tool uses. --- .travis.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.travis.yml b/.travis.yml index fd70c9160..709bc4989 100644 --- a/.travis.yml +++ b/.travis.yml @@ -236,6 +236,10 @@ matrix: env: SWIGLANG=python SWIG_CC=gcc-5 SWIG_CXX=g++-5 CPP11=1 sudo: required dist: trusty + - os: linux + env: SWIGLANG=r CPP11=1 # Note: making 'R CMD SHLIB' use a different compiler is non-trivial + sudo: required + dist: trusty - os: linux env: SWIGLANG=ruby SWIG_CC=gcc-5 SWIG_CXX=g++-5 CPP11=1 sudo: required From 9d9acba737aa1dd2a35e725c57a52c5b667ce453 Mon Sep 17 00:00:00 2001 From: FUTATSUKI Yasuhito Date: Mon, 19 Jun 2017 15:37:29 +0900 Subject: [PATCH 157/455] Apply patch to configure with 2to3 rename for 3.0.12 --- Examples/Makefile.in | 2 +- Examples/test-suite/python/Makefile.in | 2 +- configure.ac | 5 +++++ 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/Examples/Makefile.in b/Examples/Makefile.in index e29a7608a..6d4260d13 100644 --- a/Examples/Makefile.in +++ b/Examples/Makefile.in @@ -386,7 +386,7 @@ else PYSCRIPT = $(RUNME)3.py endif -PY2TO3 = 2to3 `2to3 -l | grep -v -E "Available|import$$" | awk '{print "-f "$$0}'` +PY2TO3 = @PY2TO3PROG@ `@PY2TO3PROG@ -l | grep -v -E "Available|import$$" | awk '{print "-f "$$0}'` python_run: $(PYSCRIPT) ifneq (,$(PEP8)) diff --git a/Examples/test-suite/python/Makefile.in b/Examples/test-suite/python/Makefile.in index b6da00aa5..f62a31826 100644 --- a/Examples/test-suite/python/Makefile.in +++ b/Examples/test-suite/python/Makefile.in @@ -16,7 +16,7 @@ PEP8_FLAGS = --ignore=E30,E402,E501,E731,W291,W391 #*_runme.py for Python 2.x, *_runme3.py for Python 3.x PY2SCRIPTSUFFIX = _runme.py PY3SCRIPTSUFFIX = _runme3.py -PY2TO3 = 2to3 -x import +PY2TO3 = @PY2TO3PROG@ -x import ifeq (,$(PY3)) SCRIPTSUFFIX = $(PY2SCRIPTSUFFIX) diff --git a/configure.ac b/configure.ac index 25ea0a243..130882c16 100644 --- a/configure.ac +++ b/configure.ac @@ -902,6 +902,11 @@ if test -n "$PYINCLUDE" || test -n "$PY3INCLUDE" ; then AC_MSG_RESULT($pep8_version) fi fi +AC_ARG_WITH(2to3, AS_HELP_STRING([--with-2to3], [alternate 2to3 executable]) +AS_HELP_STRING([--with-2to3=path], [Specify 2to3 utility path]),[ PY2TO3="$withval"], [PY2TO3="2to3"]) +if [ ! -z "$PYTHON3" ] ; then + AC_CHECK_PROGS(PY2TO3PROG, $PY2TO3) +fi #---------------------------------------------------------------- # Look for Perl5 From a706aa146c92298339d48100a1236909aecee265 Mon Sep 17 00:00:00 2001 From: FUTATSUKI YASUHITO Date: Mon, 19 Jun 2017 18:34:38 +0900 Subject: [PATCH 158/455] CCache: take care of program prefix/suffix on configure --- CCache/Makefile.in | 43 ++++++++++++++++++++++--------------------- CCache/ccache.h | 2 -- CCache/configure.ac | 14 ++++++++++++++ CCache/test.sh | 7 ++++++- 4 files changed, 42 insertions(+), 24 deletions(-) diff --git a/CCache/Makefile.in b/CCache/Makefile.in index 67fd3f363..845b9c6ef 100644 --- a/CCache/Makefile.in +++ b/CCache/Makefile.in @@ -8,6 +8,7 @@ bindir=@bindir@ mandir=@mandir@ INSTALLCMD=@INSTALL@ PACKAGE_NAME=@PACKAGE_NAME@ +MYNAME=@MYNAME@ # Soft link test can be skipped on systems that don't support soft linking NOSOFTLINKSTEST= @@ -25,46 +26,46 @@ OBJS= ccache.o mdfour.o hash.o execute.o util.o args.o stats.o \ cleanup.o snprintf.o unify.o HEADERS = ccache.h mdfour.h -all: $(PACKAGE_NAME)$(EXEEXT) +all: $(MYNAME)$(EXEEXT) # Regenerate Makefile if Makefile.in or config.status have changed. Makefile: $(srcdir)/Makefile.in ./config.status $(SHELL) ./config.status # Note that HTML documentation is actually generated and used from the main SWIG documentation Makefile -docs: $(srcdir)/$(PACKAGE_NAME).1 $(srcdir)/web/ccache-man.html +docs: $(srcdir)/$(MYNAME).1 $(srcdir)/web/$(MYNAME)-man.html -$(PACKAGE_NAME)$(EXEEXT): $(OBJS) $(HEADERS) +$(MYNAME)$(EXEEXT): $(OBJS) $(HEADERS) $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(OBJS) $(LIBS) -$(srcdir)/$(PACKAGE_NAME).1: $(srcdir)/ccache.yo - -yodl2man -o $(srcdir)/$(PACKAGE_NAME).1 $(srcdir)/ccache.yo +$(srcdir)/$(MYNAME).1: $(srcdir)/ccache.yo + -yodl2man -o $(srcdir)/$(MYNAME).1 $(srcdir)/ccache.yo -$(srcdir)/web/ccache-man.html: $(srcdir)/ccache.yo - yodl2html -o $(srcdir)/web/ccache-man.html $(srcdir)/ccache.yo +$(srcdir)/web/$(MYNAME)-man.html: $(srcdir)/ccache.yo + yodl2html -o $(srcdir)/web/$(MYNMAE)-man.html $(srcdir)/ccache.yo -install: $(PACKAGE_NAME)$(EXEEXT) - @echo "Installing $(PACKAGE_NAME)" - @echo "Installing $(DESTDIR)${bindir}/`echo $(PACKAGE_NAME) | sed '$(transform)'`$(EXEEXT)" +install: $(MYNAME)$(EXEEXT) + @echo "Installing $(MYNAME)" + @echo "Installing $(DESTDIR)${bindir}/$(MYNAME)$(EXEEXT)" ${INSTALLCMD} -d $(DESTDIR)${bindir} - ${INSTALLCMD} -m 755 $(PACKAGE_NAME)$(EXEEXT) $(DESTDIR)${bindir}/`echo $(PACKAGE_NAME) | sed '$(transform)'`$(EXEEXT) + ${INSTALLCMD} -m 755 $(MYNAME)$(EXEEXT) $(DESTDIR)${bindir}/$(MYNAME)$(EXEEXT) -install-docs: $(srcdir)/$(PACKAGE_NAME).1 - @echo "Installing $(DESTDIR)${mandir}/man1/`echo $(PACKAGE_NAME) | sed '$(transform)'`.1" +install-docs: $(srcdir)/$(MYNAME).1 + @echo "Installing $(DESTDIR)${mandir}/man1/$(MYNAME).1" ${INSTALLCMD} -d $(DESTDIR)${mandir}/man1 - ${INSTALLCMD} -m 644 $(srcdir)/$(PACKAGE_NAME).1 $(DESTDIR)${mandir}/man1/`echo $(PACKAGE_NAME) | sed '$(transform)'`.1 + ${INSTALLCMD} -m 644 $(srcdir)/$(MYNAME).1 $(DESTDIR)${mandir}/man1/$(MYNAME).1 -uninstall: $(PACKAGE_NAME)$(EXEEXT) - rm -f $(DESTDIR)${bindir}/`echo $(PACKAGE_NAME) | sed '$(transform)'`$(EXEEXT) +uninstall: $(MYNAME)$(EXEEXT) + rm -f $(DESTDIR)${bindir}/$(MYNAME)$(EXEEXT) -uninstall-docs: $(srcdir)/$(PACKAGE_NAME).1 - rm -f $(DESTDIR)${mandir}/man1/`echo $(PACKAGE_NAME) | sed '$(transform)'`.1 +uninstall-docs: $(srcdir)/$(MYNAME).1 + rm -f $(DESTDIR)${mandir}/man1/$(MYNAME).1 clean: - /bin/rm -f $(OBJS) *~ $(PACKAGE_NAME)$(EXEEXT) + /bin/rm -f $(OBJS) *~ $(MYNAME)$(EXEEXT) test: test.sh - SWIG_LIB='$(SWIG_LIB)' PATH=../..:$$PATH SWIG='$(SWIG)' CC='$(CC)' NOSOFTLINKSTEST='$(NOSOFTLINKSTEST)' $(srcdir)/test.sh + SWIG_LIB='$(SWIG_LIB)' PATH=../..:$$PATH SWIG='$(SWIG)' CC='$(CC)' NOSOFTLINKSTEST='$(NOSOFTLINKSTEST)' CCACHE='../$(MYNAME)' $(srcdir)/test.sh check: test @@ -73,7 +74,7 @@ distclean: clean /bin/rm -rf autom4te.cache maintainer-clean: distclean - /bin/rm -f $(srcdir)/$(PACKAGE_NAME).1 $(srcdir)/web/ccache-man.html + /bin/rm -f $(srcdir)/$(MYNAME).1 $(srcdir)/web/$(MYNAME)-man.html # FIXME: To fix this, test.sh needs to be able to take ccache from the diff --git a/CCache/ccache.h b/CCache/ccache.h index a79d88322..99a63483b 100644 --- a/CCache/ccache.h +++ b/CCache/ccache.h @@ -51,8 +51,6 @@ #define STATUS_FATAL 4 #define STATUS_NOCACHE 5 -#define MYNAME PACKAGE_NAME - #define LIMIT_MULTIPLE 0.8 /* default maximum cache size */ diff --git a/CCache/configure.ac b/CCache/configure.ac index dfbf86dbc..d5f0c38c2 100644 --- a/CCache/configure.ac +++ b/CCache/configure.ac @@ -14,6 +14,20 @@ AC_PROG_CPP AC_PROG_INSTALL AC_ARG_PROGRAM # for program_transform_name +AC_SUBST(MYNAME) +if test "x$program_prefix" != "xNONE" -a "x$program_prefix" != "x" +then + MYNAME="$program_prefix$PACKAGE_NAME" +else + MYNAME="$PACKAGE_NAME" +fi +if test "x$program_suffix" != "xNONE" -a "x$program_suffix" != "x" +then + MYNAME="$MYNAME$program_suffix" +fi + +AC_DEFINE_UNQUOTED(MYNAME, "$MYNAME", [Define my program name]) + AC_DEFINE([_GNU_SOURCE], 1, [Define _GNU_SOURCE so that we get all necessary prototypes]) diff --git a/CCache/test.sh b/CCache/test.sh index 438e782cd..7e69149ff 100755 --- a/CCache/test.sh +++ b/CCache/test.sh @@ -20,7 +20,12 @@ fi PATH="`echo $PATH | \ sed -e 's!:/usr\(/local\)*/lib\([0-9]\)*/ccache\(/\)*!!g'`" -CCACHE=../ccache-swig +if test -n "$CCACHE"; then + CCACHE="$CCACHE" +else + CCACHE=../ccache-swig +fi + TESTDIR=test.$$ test_failed() { From 93895f5a5101ba77e599f25ed241d60a85de290d Mon Sep 17 00:00:00 2001 From: FUTATSUKI YASUHITO Date: Tue, 20 Jun 2017 01:33:10 +0900 Subject: [PATCH 159/455] Add header file in CCache for _WIN32 environment --- CCache/Makefile.in | 2 +- CCache/ccache.h | 2 +- CCache/config_w32.h.in | 3 +++ CCache/configure.ac | 1 + 4 files changed, 6 insertions(+), 2 deletions(-) create mode 100644 CCache/config_w32.h.in diff --git a/CCache/Makefile.in b/CCache/Makefile.in index 845b9c6ef..a718c8985 100644 --- a/CCache/Makefile.in +++ b/CCache/Makefile.in @@ -70,7 +70,7 @@ test: test.sh check: test distclean: clean - /bin/rm -f Makefile config.h config.sub config.log build-stamp config.status ccache_swig_config.h + /bin/rm -f Makefile config.h config.sub config.log build-stamp config.status ccache_swig_config.h config_win32.h /bin/rm -rf autom4te.cache maintainer-clean: distclean diff --git a/CCache/ccache.h b/CCache/ccache.h index 99a63483b..f1c7f3eef 100644 --- a/CCache/ccache.h +++ b/CCache/ccache.h @@ -6,7 +6,7 @@ #include "config.h" #else #include -#define PACKAGE_NAME "ccache-swig.exe" +#include "config_w32.h" #endif #include diff --git a/CCache/config_w32.h.in b/CCache/config_w32.h.in new file mode 100644 index 000000000..35b1c5571 --- /dev/null +++ b/CCache/config_w32.h.in @@ -0,0 +1,3 @@ +#if !defined(MYNAME) +#define MYNAME "@MYNAME@@EXEEXT@" +#endif diff --git a/CCache/configure.ac b/CCache/configure.ac index d5f0c38c2..84d8fe835 100644 --- a/CCache/configure.ac +++ b/CCache/configure.ac @@ -7,6 +7,7 @@ AC_CONFIG_SRCDIR([ccache.h]) AC_MSG_NOTICE([Configuring ccache]) AC_CONFIG_HEADER(config.h) +AC_CONFIG_FILES([config_w32.h]) dnl Checks for programs. AC_PROG_CC From 529906f181249e5def19f7a9d0f6e48b7c3d101b Mon Sep 17 00:00:00 2001 From: FUTATSUKI YASUHITO Date: Tue, 20 Jun 2017 01:47:07 +0900 Subject: [PATCH 160/455] Embed fixed string '.exe' to CCache/config_win32.h even if EXEEXT is empty. --- CCache/config_w32.h.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CCache/config_w32.h.in b/CCache/config_w32.h.in index 35b1c5571..74094b4bd 100644 --- a/CCache/config_w32.h.in +++ b/CCache/config_w32.h.in @@ -1,3 +1,3 @@ #if !defined(MYNAME) -#define MYNAME "@MYNAME@@EXEEXT@" +#define MYNAME "@MYNAME@.exe" #endif From 687cf9c9c1b886ef4a828b2c29610183e9fef26d Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Mon, 19 Jun 2017 19:12:23 +0100 Subject: [PATCH 161/455] Add missing %python:maybecall to operator overloads. This ensures NotImplemented is returned on error so that the Python interpreter will handle the operators correctly instead of throwing an exception. NotImplemented was not being returned for non-builtin wrappers when the operator overload did not have a function overload. See PEP 207 and https://docs.python.org/3/library/constants.html#NotImplemented Mentioned in SF patch #303 and SF bug #1208. --- CHANGES.current | 21 +++++++ Doc/Manual/Python.html | 8 +++ .../python/python_richcompare_runme.py | 56 +++++++++++++++++++ Source/Modules/python.cxx | 19 +++++-- 4 files changed, 98 insertions(+), 6 deletions(-) diff --git a/CHANGES.current b/CHANGES.current index 584fa6cb8..f9177f1a6 100644 --- a/CHANGES.current +++ b/CHANGES.current @@ -7,6 +7,27 @@ the issue number to the end of the URL: https://github.com/swig/swig/issues/ Version 4.0.0 (in progress) =========================== +2017-06-19: wsfulton + [Python] Fix handling of rich comparisons when wrapping overloaded operators: + + operator< operator<= operator> operator>= operator== operator!= + + Previously a TypeError was always thrown if the type was not correct. NotImplemented + is now returned from these wrapped functions if the type being compared with is + not correct. The subsequent behaviour varies between different versions of Python + and the comparison function being used, but is now consistent with normal Python + behaviour. For example, for the first 4 operator overloads above, a TypeError + 'unorderable types' is thrown in Python 3, but Python 2 will return True or False. + NotImplemented should be returned when the comparison cannot be done, see PEP 207 and + https://docs.python.org/3/library/constants.html#NotImplemented + + Note that the bug was only present when overloaded operators did not also have a + function overload. + + Fixes SF bug #1208 (3441262) and SF patch #303. + + *** POTENTIAL INCOMPATIBILITY *** + 2017-06-17: fabrice102 [Go] Fix Go callback example. Fixes github #600, #955, #1000. diff --git a/Doc/Manual/Python.html b/Doc/Manual/Python.html index 9b3afbdd9..1b73c08b7 100644 --- a/Doc/Manual/Python.html +++ b/Doc/Manual/Python.html @@ -1894,6 +1894,14 @@ Also, be aware that certain operators don't map cleanly to Python. For instance overloaded assignment operators don't map to Python semantics and will be ignored.

+

+Operator overloading is implemented in the pyopers.swg library file. +In particular overloaded operators are marked with the python:maybecall feature, also known as %pythonmaybecall. +This feature forces SWIG to generate code that return an instance of Python's NotImplemented +instead of raising an exception when the comparison fails, that is, on any kind of error. +This follows the guidelines in PEP 207 - Rich Comparisons and NotImplemented Python constant. +

+

36.3.12 C++ namespaces

diff --git a/Examples/test-suite/python/python_richcompare_runme.py b/Examples/test-suite/python/python_richcompare_runme.py index a68da2f98..f7c7a673b 100644 --- a/Examples/test-suite/python/python_richcompare_runme.py +++ b/Examples/test-suite/python/python_richcompare_runme.py @@ -1,4 +1,12 @@ import python_richcompare +import sys + +def check_unorderable_types(exception): + if str(exception).find("unorderable types") == -1: + raise RuntimeError("A TypeError 'unorderable types' exception was expected"), None, sys.exc_info()[2] + +def is_new_style_class(cls): + return hasattr(cls, "__class__") base1 = python_richcompare.BaseClass(1) base2 = python_richcompare.BaseClass(2) @@ -65,6 +73,18 @@ if (b1 == a1): raise RuntimeError( "Comparing equivalent instances of different subclasses, == returned True") +# Check comparison to other objects +#------------------------------------------------------------------------------- +if (base1 == 42) : + raise RuntimeError("Comparing class to incompatible type, == returned True") +if not (base1 != 42) : + raise RuntimeError("Comparing class to incompatible type, != returned False") + +if (a1 == 42) : + raise RuntimeError("Comparing class (with overloaded operator ==) to incompatible type, == returned True") +if not (a1 != 42) : + raise RuntimeError("Comparing class (with overloaded operator ==) to incompatible type, != returned False") + # Check inequalities #------------------------------------------------------------------------- @@ -80,6 +100,42 @@ if not (a2 >= b2): if not (a2 <= b2): raise RuntimeError("operator<= failed") +# Check inequalities to other objects +#------------------------------------------------------------------------------- +if is_new_style_class(python_richcompare.BaseClass): + # Skip testing -classic option + if sys.version_info[0:2] < (3, 0): + if (base1 < 42): + raise RuntimeError("Comparing class to incompatible type, < returned True") + if (base1 <= 42): + raise RuntimeError("Comparing class to incompatible type, <= returned True") + if not (base1 > 42): + raise RuntimeError("Comparing class to incompatible type, > returned False") + if not (base1 >= 42): + raise RuntimeError("Comparing class to incompatible type, >= returned False") + else: + # Python 3 throws: TypeError: unorderable types + try: + res = base1 < 42 + raise RuntimeError("Failed to throw") + except TypeError,e: + check_unorderable_types(e) + try: + res = base1 <= 42 + raise RuntimeError("Failed to throw") + except TypeError,e: + check_unorderable_types(e) + try: + res = base1 > 42 + raise RuntimeError("Failed to throw") + except TypeError,e: + check_unorderable_types(e) + try: + res = base1 >= 42 + raise RuntimeError("Failed to throw") + except TypeError,e: + check_unorderable_types(e) + # Check inequalities used for ordering #------------------------------------------------------------------------- diff --git a/Source/Modules/python.cxx b/Source/Modules/python.cxx index cf81827cb..802c36cc7 100644 --- a/Source/Modules/python.cxx +++ b/Source/Modules/python.cxx @@ -2573,8 +2573,8 @@ public: if (GetFlag(n, "feature:python:maybecall")) { Append(f->code, "fail:\n"); - Append(f->code, "Py_INCREF(Py_NotImplemented);\n"); - Append(f->code, "return Py_NotImplemented;\n"); + Append(f->code, " Py_INCREF(Py_NotImplemented);\n"); + Append(f->code, " return Py_NotImplemented;\n"); } else { Node *sibl = n; while (Getattr(sibl, "sym:previousSibling")) @@ -2586,7 +2586,7 @@ public: Delete(fulldecl); } while ((sibl = Getattr(sibl, "sym:nextSibling"))); Append(f->code, "fail:\n"); - Printf(f->code, "SWIG_SetErrorMsg(PyExc_NotImplementedError," + Printf(f->code, " SWIG_SetErrorMsg(PyExc_NotImplementedError," "\"Wrong number or type of arguments for overloaded function '%s'.\\n\"" "\n\" Possible C/C++ prototypes are:\\n\"%s);\n", symname, protoTypes); Printf(f->code, "return %s;\n", builtin_ctor ? "-1" : "0"); Delete(protoTypes); @@ -3211,10 +3211,17 @@ public: if (need_cleanup) { Printv(f->code, cleanup, NIL); } - if (builtin_ctor) + if (builtin_ctor) { Printv(f->code, " return -1;\n", NIL); - else - Printv(f->code, " return NULL;\n", NIL); + } else { + if (GetFlag(n, "feature:python:maybecall")) { + Append(f->code, " PyErr_Clear();\n"); + Append(f->code, " Py_INCREF(Py_NotImplemented);\n"); + Append(f->code, " return Py_NotImplemented;\n"); + } else { + Printv(f->code, " return NULL;\n", NIL); + } + } if (funpack) { From 4ab2aff0a10aec829177f6db05b5ab09094aa596 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Mon, 19 Jun 2017 19:43:51 +0100 Subject: [PATCH 162/455] Fix Python unordered_map and ordered_map compilation error when using -builtin --- Lib/python/std_unordered_map.i | 2 +- Lib/python/std_unordered_multimap.i | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Lib/python/std_unordered_map.i b/Lib/python/std_unordered_map.i index 8ab4b1447..6bd34077b 100644 --- a/Lib/python/std_unordered_map.i +++ b/Lib/python/std_unordered_map.i @@ -53,7 +53,7 @@ static PyObject *from(const unordered_map_type& unordered_map) { swig_type_info *desc = swig::type_info(); if (desc && desc->clientdata) { - return SWIG_NewPointerObj(new unordered_map_type(unordered_map), desc, SWIG_POINTER_OWN); + return SWIG_InternalNewPointerObj(new unordered_map_type(unordered_map), desc, SWIG_POINTER_OWN); } else { size_type size = unordered_map.size(); Py_ssize_t pysize = (size <= (size_type) INT_MAX) ? (Py_ssize_t) size : -1; diff --git a/Lib/python/std_unordered_multimap.i b/Lib/python/std_unordered_multimap.i index f46a94b16..312b29e61 100644 --- a/Lib/python/std_unordered_multimap.i +++ b/Lib/python/std_unordered_multimap.i @@ -50,7 +50,7 @@ static PyObject *from(const unordered_multimap_type& unordered_multimap) { swig_type_info *desc = swig::type_info(); if (desc && desc->clientdata) { - return SWIG_NewPointerObj(new unordered_multimap_type(unordered_multimap), desc, SWIG_POINTER_OWN); + return SWIG_InternalNewPointerObj(new unordered_multimap_type(unordered_multimap), desc, SWIG_POINTER_OWN); } else { size_type size = unordered_multimap.size(); Py_ssize_t pysize = (size <= (size_type) INT_MAX) ? (Py_ssize_t) size : -1; From b56d7c0539e398ec74d4e354f36beaaa2c758514 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Mon, 19 Jun 2017 20:32:32 +0100 Subject: [PATCH 163/455] Python builtin C++11 STL fixes Compilation fixes for std::multimap, std::unordered_map and std::unordered_multimap. --- Lib/python/std_multimap.i | 10 ++++++++++ Lib/python/std_unordered_map.i | 10 ++++++++++ Lib/python/std_unordered_multimap.i | 10 ++++++++++ 3 files changed, 30 insertions(+) diff --git a/Lib/python/std_multimap.i b/Lib/python/std_multimap.i index 3209fb0f8..21c84b009 100644 --- a/Lib/python/std_multimap.i +++ b/Lib/python/std_multimap.i @@ -68,7 +68,17 @@ %define %swig_multimap_methods(Type...) %swig_map_common(Type); + +#if defined(SWIGPYTHON_BUILTIN) + %feature("python:slot", "mp_ass_subscript", functype="objobjargproc") __setitem__; +#endif + %extend { + // This will be called through the mp_ass_subscript slot to delete an entry. + void __setitem__(const key_type& key) { + self->erase(key); + } + void __setitem__(const key_type& key, const mapped_type& x) throw (std::out_of_range) { self->insert(Type::value_type(key,x)); } diff --git a/Lib/python/std_unordered_map.i b/Lib/python/std_unordered_map.i index 6bd34077b..53f6aa283 100644 --- a/Lib/python/std_unordered_map.i +++ b/Lib/python/std_unordered_map.i @@ -226,7 +226,17 @@ %define %swig_unordered_map_methods(Map...) %swig_unordered_map_common(Map) + +#if defined(SWIGPYTHON_BUILTIN) + %feature("python:slot", "mp_ass_subscript", functype="objobjargproc") __setitem__; +#endif + %extend { + // This will be called through the mp_ass_subscript slot to delete an entry. + void __setitem__(const key_type& key) { + self->erase(key); + } + void __setitem__(const key_type& key, const mapped_type& x) throw (std::out_of_range) { (*self)[key] = x; } diff --git a/Lib/python/std_unordered_multimap.i b/Lib/python/std_unordered_multimap.i index 312b29e61..4dbc2a4dd 100644 --- a/Lib/python/std_unordered_multimap.i +++ b/Lib/python/std_unordered_multimap.i @@ -75,7 +75,17 @@ %define %swig_unordered_multimap_methods(Type...) %swig_unordered_map_common(Type); + +#if defined(SWIGPYTHON_BUILTIN) + %feature("python:slot", "mp_ass_subscript", functype="objobjargproc") __setitem__; +#endif + %extend { + // This will be called through the mp_ass_subscript slot to delete an entry. + void __setitem__(const key_type& key) { + self->erase(key); + } + void __setitem__(const key_type& key, const mapped_type& x) throw (std::out_of_range) { self->insert(Type::value_type(key,x)); } From e0c0017839eddfac297458c5d5f3e547027b856e Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Mon, 19 Jun 2017 20:33:32 +0100 Subject: [PATCH 164/455] Remove failing runtime tests for now using Python 2 and -builtin --- Examples/test-suite/python/cpp11_hash_tables_runme.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/Examples/test-suite/python/cpp11_hash_tables_runme.py b/Examples/test-suite/python/cpp11_hash_tables_runme.py index 39388fd20..d8c63208a 100644 --- a/Examples/test-suite/python/cpp11_hash_tables_runme.py +++ b/Examples/test-suite/python/cpp11_hash_tables_runme.py @@ -6,8 +6,10 @@ def swig_assert_equal(a, b): for x in [cpp11_hash_tables.MapIntInt({1:7}), cpp11_hash_tables.MultiMapIntInt({1:7}), - cpp11_hash_tables.UnorderedMapIntInt({1:7}), - cpp11_hash_tables.UnorderedMultiMapIntInt({1:7})]: +# TODO: fix for -builtin +# cpp11_hash_tables.UnorderedMapIntInt({1:7}), +# cpp11_hash_tables.UnorderedMultiMapIntInt({1:7}) + ]: swig_assert_equal([(k, v) for k, v in x.iteritems()], [(1, 7)]) @@ -25,7 +27,8 @@ for x in [cpp11_hash_tables.MapIntInt({1:7}), for x in [cpp11_hash_tables.MultiMapIntInt({1:7}), cpp11_hash_tables.UnorderedMultiMapIntInt({1:7})]: x[1] = 9 - swig_assert_equal(sorted([v for k, v in x.iteritems()]), [7, 9]) +# TODO: fix for -builtin +# swig_assert_equal(sorted([v for k, v in x.iteritems()]), [7, 9]) # Is this broken?... # swig_assert_equal(sorted([v for v in x[1]]), [7, 9]) From 057b1dc02884f408d6a6e9943d619aaead575a87 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Mon, 19 Jun 2017 20:37:09 +0100 Subject: [PATCH 165/455] Add Travis Python 2, C++11 and -builtin testing --- .travis.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.travis.yml b/.travis.yml index 709bc4989..57f20eef6 100644 --- a/.travis.yml +++ b/.travis.yml @@ -165,6 +165,10 @@ matrix: env: SWIGLANG=python SWIG_FEATURES=-builtin sudo: required dist: trusty + - os: linux + env: SWIGLANG=python SWIG_FEATURES=-builtin SWIG_CC=gcc-5 SWIG_CXX=g++-5 CPP11=1 + sudo: required + dist: trusty - compiler: gcc os: linux env: SWIGLANG=python SWIG_FEATURES=-builtin PY3=3 VER=3.4 From 36b61dd0f27da90465b2b67ae5a136d2ff61274b Mon Sep 17 00:00:00 2001 From: FUTATSUKI YASUHITO Date: Tue, 20 Jun 2017 07:57:54 +0900 Subject: [PATCH 166/455] fix typo --- CCache/Makefile.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CCache/Makefile.in b/CCache/Makefile.in index a718c8985..3e4609101 100644 --- a/CCache/Makefile.in +++ b/CCache/Makefile.in @@ -70,7 +70,7 @@ test: test.sh check: test distclean: clean - /bin/rm -f Makefile config.h config.sub config.log build-stamp config.status ccache_swig_config.h config_win32.h + /bin/rm -f Makefile config.h config.sub config.log build-stamp config.status ccache_swig_config.h config_w32.h /bin/rm -rf autom4te.cache maintainer-clean: distclean From 1d1d0de2d0ef53949fabcb68a7c42fd6d837e288 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Tue, 20 Jun 2017 00:02:00 +0100 Subject: [PATCH 167/455] Fix python_richcompare test for Python 3.6 --- Examples/test-suite/python/python_richcompare_runme.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Examples/test-suite/python/python_richcompare_runme.py b/Examples/test-suite/python/python_richcompare_runme.py index f7c7a673b..247660301 100644 --- a/Examples/test-suite/python/python_richcompare_runme.py +++ b/Examples/test-suite/python/python_richcompare_runme.py @@ -2,8 +2,9 @@ import python_richcompare import sys def check_unorderable_types(exception): - if str(exception).find("unorderable types") == -1: - raise RuntimeError("A TypeError 'unorderable types' exception was expected"), None, sys.exc_info()[2] +# if str(exception).find("unorderable types") == -1: +# raise RuntimeError("A TypeError 'unorderable types' exception was expected"), None, sys.exc_info()[2] + pass # Exception message seems to vary from one version of Python to another def is_new_style_class(cls): return hasattr(cls, "__class__") From ff53789dc90e61415b94fb82c9cd8bb9a08ac078 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Tue, 20 Jun 2017 07:00:22 +0100 Subject: [PATCH 168/455] Suppress warning in testcase --- Examples/test-suite/default_args.i | 1 + 1 file changed, 1 insertion(+) diff --git a/Examples/test-suite/default_args.i b/Examples/test-suite/default_args.i index 8828bfe04..7959caa33 100644 --- a/Examples/test-suite/default_args.i +++ b/Examples/test-suite/default_args.i @@ -5,6 +5,7 @@ %{ #if defined(_MSC_VER) #pragma warning(disable: 4290) // C++ exception specification ignored except to indicate a function is not __declspec(nothrow) + #pragma warning(disable: 4146) // unary minus operator applied to unsigned type, result still unsigned #endif #if __GNUC__ >= 7 #pragma GCC diagnostic push From 339b62516027a98ff97749c27440a6f9f3927173 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Wed, 21 Jun 2017 00:05:56 +0100 Subject: [PATCH 169/455] Add changes file entry for Ruby std::wstring support --- CHANGES.current | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGES.current b/CHANGES.current index f9177f1a6..65cf8d127 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.0.0 (in progress) =========================== +2017-06-21: tamuratak + [Ruby] #911 - Add std::wstring support. + 2017-06-19: wsfulton [Python] Fix handling of rich comparisons when wrapping overloaded operators: From 7be53b769237bf8f818b3f426b03655c2d3b1a1f Mon Sep 17 00:00:00 2001 From: FUTATSUKI YASUHITO Date: Wed, 21 Jun 2017 08:07:08 +0900 Subject: [PATCH 170/455] Apply changes requested for this pull request --- CCache/Makefile.in | 46 ++++++++++++++++++++-------------------- CCache/ccache.h | 4 +++- CCache/config_w32.h.in | 3 --- CCache/config_win32.h.in | 3 +++ CCache/configure.ac | 12 +++++------ 5 files changed, 35 insertions(+), 33 deletions(-) delete mode 100644 CCache/config_w32.h.in create mode 100644 CCache/config_win32.h.in diff --git a/CCache/Makefile.in b/CCache/Makefile.in index 3e4609101..1a6feb40f 100644 --- a/CCache/Makefile.in +++ b/CCache/Makefile.in @@ -8,7 +8,7 @@ bindir=@bindir@ mandir=@mandir@ INSTALLCMD=@INSTALL@ PACKAGE_NAME=@PACKAGE_NAME@ -MYNAME=@MYNAME@ +PROGRAM_NAME=@PROGRAM_NAME@ # Soft link test can be skipped on systems that don't support soft linking NOSOFTLINKSTEST= @@ -26,55 +26,55 @@ OBJS= ccache.o mdfour.o hash.o execute.o util.o args.o stats.o \ cleanup.o snprintf.o unify.o HEADERS = ccache.h mdfour.h -all: $(MYNAME)$(EXEEXT) +all: $(PROGRAM_NAME)$(EXEEXT) # Regenerate Makefile if Makefile.in or config.status have changed. Makefile: $(srcdir)/Makefile.in ./config.status $(SHELL) ./config.status # Note that HTML documentation is actually generated and used from the main SWIG documentation Makefile -docs: $(srcdir)/$(MYNAME).1 $(srcdir)/web/$(MYNAME)-man.html +docs: $(srcdir)/$(PROGRAM_NAME).1 $(srcdir)/web/$(PROGRAM_NAME)-man.html -$(MYNAME)$(EXEEXT): $(OBJS) $(HEADERS) +$(PROGRAM_NAME)$(EXEEXT): $(OBJS) $(HEADERS) $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(OBJS) $(LIBS) -$(srcdir)/$(MYNAME).1: $(srcdir)/ccache.yo - -yodl2man -o $(srcdir)/$(MYNAME).1 $(srcdir)/ccache.yo +$(srcdir)/$(PROGRAM_NAME).1: $(srcdir)/ccache.yo + -yodl2man -o $(srcdir)/$(PROGRAM_NAME).1 $(srcdir)/ccache.yo -$(srcdir)/web/$(MYNAME)-man.html: $(srcdir)/ccache.yo - yodl2html -o $(srcdir)/web/$(MYNMAE)-man.html $(srcdir)/ccache.yo +$(srcdir)/web/$(PROGRAM_NAME)-man.html: $(srcdir)/ccache.yo + yodl2html -o $(srcdir)/web/$(PROGRAM_NAME)-man.html $(srcdir)/ccache.yo -install: $(MYNAME)$(EXEEXT) - @echo "Installing $(MYNAME)" - @echo "Installing $(DESTDIR)${bindir}/$(MYNAME)$(EXEEXT)" +install: $(PROGRAM_NAME)$(EXEEXT) + @echo "Installing $(PROGRAM_NAME)" + @echo "Installing $(DESTDIR)${bindir}/$(PROGRAM_NAME)$(EXEEXT)" ${INSTALLCMD} -d $(DESTDIR)${bindir} - ${INSTALLCMD} -m 755 $(MYNAME)$(EXEEXT) $(DESTDIR)${bindir}/$(MYNAME)$(EXEEXT) + ${INSTALLCMD} -m 755 $(PROGRAM_NAME)$(EXEEXT) $(DESTDIR)${bindir}/$(PROGRAM_NAME)$(EXEEXT) -install-docs: $(srcdir)/$(MYNAME).1 - @echo "Installing $(DESTDIR)${mandir}/man1/$(MYNAME).1" +install-docs: $(srcdir)/$(PROGRAM_NAME).1 + @echo "Installing $(DESTDIR)${mandir}/man1/$(PROGRAM_NAME).1" ${INSTALLCMD} -d $(DESTDIR)${mandir}/man1 - ${INSTALLCMD} -m 644 $(srcdir)/$(MYNAME).1 $(DESTDIR)${mandir}/man1/$(MYNAME).1 + ${INSTALLCMD} -m 644 $(srcdir)/$(PROGRAM_NAME).1 $(DESTDIR)${mandir}/man1/$(PROGRAM_NAME).1 -uninstall: $(MYNAME)$(EXEEXT) - rm -f $(DESTDIR)${bindir}/$(MYNAME)$(EXEEXT) +uninstall: $(PROGRAM_NAME)$(EXEEXT) + rm -f $(DESTDIR)${bindir}/$(PROGRAM_NAME)$(EXEEXT) -uninstall-docs: $(srcdir)/$(MYNAME).1 - rm -f $(DESTDIR)${mandir}/man1/$(MYNAME).1 +uninstall-docs: $(srcdir)/$(PROGRAM_NAME).1 + rm -f $(DESTDIR)${mandir}/man1/$(PROGRAM_NAME).1 clean: - /bin/rm -f $(OBJS) *~ $(MYNAME)$(EXEEXT) + /bin/rm -f $(OBJS) *~ $(PROGRAM_NAME)$(EXEEXT) test: test.sh - SWIG_LIB='$(SWIG_LIB)' PATH=../..:$$PATH SWIG='$(SWIG)' CC='$(CC)' NOSOFTLINKSTEST='$(NOSOFTLINKSTEST)' CCACHE='../$(MYNAME)' $(srcdir)/test.sh + SWIG_LIB='$(SWIG_LIB)' PATH=../..:$$PATH SWIG='$(SWIG)' CC='$(CC)' NOSOFTLINKSTEST='$(NOSOFTLINKSTEST)' CCACHE='../$(PROGRAM_NAME)' $(srcdir)/test.sh check: test distclean: clean - /bin/rm -f Makefile config.h config.sub config.log build-stamp config.status ccache_swig_config.h config_w32.h + /bin/rm -f Makefile config.h config.sub config.log build-stamp config.status ccache_swig_config.h config_win32.h /bin/rm -rf autom4te.cache maintainer-clean: distclean - /bin/rm -f $(srcdir)/$(MYNAME).1 $(srcdir)/web/$(MYNAME)-man.html + /bin/rm -f $(srcdir)/$(PROGRAM_NAME).1 $(srcdir)/web/$(PROGRAM_NAME)-man.html # FIXME: To fix this, test.sh needs to be able to take ccache from the diff --git a/CCache/ccache.h b/CCache/ccache.h index f1c7f3eef..25e786496 100644 --- a/CCache/ccache.h +++ b/CCache/ccache.h @@ -6,7 +6,7 @@ #include "config.h" #else #include -#include "config_w32.h" +#include "config_win32.h" #endif #include @@ -51,6 +51,8 @@ #define STATUS_FATAL 4 #define STATUS_NOCACHE 5 +#define MYNAME PROGRAM_NAME + #define LIMIT_MULTIPLE 0.8 /* default maximum cache size */ diff --git a/CCache/config_w32.h.in b/CCache/config_w32.h.in deleted file mode 100644 index 74094b4bd..000000000 --- a/CCache/config_w32.h.in +++ /dev/null @@ -1,3 +0,0 @@ -#if !defined(MYNAME) -#define MYNAME "@MYNAME@.exe" -#endif diff --git a/CCache/config_win32.h.in b/CCache/config_win32.h.in new file mode 100644 index 000000000..2d5ab97e3 --- /dev/null +++ b/CCache/config_win32.h.in @@ -0,0 +1,3 @@ +#if !defined(PROGRAM_NAME) +#define PROGRAM_NAME "@PROGRAM_NAME@.exe" +#endif diff --git a/CCache/configure.ac b/CCache/configure.ac index 84d8fe835..e1c761860 100644 --- a/CCache/configure.ac +++ b/CCache/configure.ac @@ -7,7 +7,7 @@ AC_CONFIG_SRCDIR([ccache.h]) AC_MSG_NOTICE([Configuring ccache]) AC_CONFIG_HEADER(config.h) -AC_CONFIG_FILES([config_w32.h]) +AC_CONFIG_FILES([config_win32.h]) dnl Checks for programs. AC_PROG_CC @@ -15,19 +15,19 @@ AC_PROG_CPP AC_PROG_INSTALL AC_ARG_PROGRAM # for program_transform_name -AC_SUBST(MYNAME) +AC_SUBST(PROGRAM_NAME) if test "x$program_prefix" != "xNONE" -a "x$program_prefix" != "x" then - MYNAME="$program_prefix$PACKAGE_NAME" + PROGRAM_NAME="$program_prefix$PACKAGE_NAME" else - MYNAME="$PACKAGE_NAME" + PROGRAM_NAME="$PACKAGE_NAME" fi if test "x$program_suffix" != "xNONE" -a "x$program_suffix" != "x" then - MYNAME="$MYNAME$program_suffix" + PROGRAM_NAME="$PROGRAM_NAME$program_suffix" fi -AC_DEFINE_UNQUOTED(MYNAME, "$MYNAME", [Define my program name]) +AC_DEFINE_UNQUOTED(PROGRAM_NAME, "$PROGRAM_NAME", [Define my program name]) AC_DEFINE([_GNU_SOURCE], 1, [Define _GNU_SOURCE so that we get all necessary prototypes]) From 2a47918a3f8d4a50acea604b2f6355d79104496b Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Wed, 21 Jun 2017 15:35:35 +0100 Subject: [PATCH 171/455] Add changes entry for ccache-swig configure fix --- CHANGES.current | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGES.current b/CHANGES.current index 65cf8d127..d06fba638 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.0.0 (in progress) =========================== +2017-06-21: futatuki + #1004 - Fix ccache-swig executable name to respect configure's --program-prefix and + --program-suffix values if used. + 2017-06-21: tamuratak [Ruby] #911 - Add std::wstring support. From fa416e4d4092331d6d77129adfe9c5d202903f2f Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Wed, 21 Jun 2017 15:51:52 +0100 Subject: [PATCH 172/455] li_std_list testcase not working for most languages --- Examples/test-suite/common.mk | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/Examples/test-suite/common.mk b/Examples/test-suite/common.mk index 11b1446e0..146ada2c6 100644 --- a/Examples/test-suite/common.mk +++ b/Examples/test-suite/common.mk @@ -99,7 +99,7 @@ CPP_TEST_BROKEN += \ # Broken C test cases. (Can be run individually using: make testcase.ctest) C_TEST_BROKEN += \ - tag_no_clash_with_variable + tag_no_clash_with_variable \ # C++ test cases. (Can be run individually using: make testcase.cpptest) CPP_TEST_CASES += \ @@ -533,7 +533,7 @@ CPP_TEST_CASES += \ virtual_vs_nonvirtual_base \ voidtest \ wallkw \ - wrapmacro + wrapmacro \ # C++11 test cases. CPP11_TEST_CASES += \ @@ -601,8 +601,6 @@ CPP_STD_TEST_CASES += \ template_typedef_fnc \ template_type_namespace \ template_opaque \ - li_std_list - ifndef SKIP_CPP_STD_CASES CPP_TEST_CASES += ${CPP_STD_TEST_CASES} @@ -666,7 +664,7 @@ C_TEST_CASES += \ typedef_struct \ typemap_subst \ union_parameter \ - unions + unions \ # Multi-module C++ test cases . (Can be run individually using make testcase.multicpptest) @@ -677,7 +675,7 @@ MULTI_CPP_TEST_CASES += \ packageoption \ mod \ template_typedef_import \ - multi_import + multi_import \ # Custom tests - tests with additional commandline options wallkw.cpptest: SWIGOPT += -Wallkw From dd25f5b722499aa1ec9220ce5b70142c869d6b26 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Thu, 22 Jun 2017 11:47:56 +0100 Subject: [PATCH 173/455] Java std::list rework to be consistent with std::vector wrappers --- Lib/java/std_list.i | 274 +++++++++++++++++++++----------------------- 1 file changed, 128 insertions(+), 146 deletions(-) diff --git a/Lib/java/std_list.i b/Lib/java/std_list.i index 804223efd..70bb6e20a 100644 --- a/Lib/java/std_list.i +++ b/Lib/java/std_list.i @@ -2,56 +2,134 @@ %{ #include -#include +#include %} +%fragment("SWIG_ListSize", "header", fragment="SWIG_JavaIntFromSize_t") { +SWIGINTERN jint SWIG_ListSize(size_t size) { + jint sz = SWIG_JavaIntFromSize_t(size); + if (sz == -1) + throw std::out_of_range("list size is too large to fit into a Java int"); + return sz; +} +} + %javamethodmodifiers std::list::begin "private"; %javamethodmodifiers std::list::insert "private"; %javamethodmodifiers std::list::set "private"; -%javamethodmodifiers std::list::previous_index "private"; -%javamethodmodifiers std::list::next_index "private"; %javamethodmodifiers std::list::previous "private"; %javamethodmodifiers std::list::next "private"; %javamethodmodifiers std::list::deref "private"; %javamethodmodifiers std::list::advance "private"; -%javamethodmodifiers std::list::has_next "private"; - -/* - To conform to Java Collection interface we must return int from size(). - Unfortunately that loses precision from the integer types commonly used in - C++ implementations. Since we can't overload on return values the best - workaround here is to expose the real C++ size() return value to Java as a - long and use the javaout typemap to validate. We can then at least fails - gracefully in the case where we have a collection with > 2^31-1 items rather - than failing mysteriously. - - The use of SWIG_list_size_type here allows us to selectively %apply this to - only the cases where we have to conform to the Java interface requirement, - without interfering with other size_type usage. The intention is that - SWIG_list_size_type is both reserved and unique. (Perhaps it could live in - std_common.i later on?) -*/ -%typemap(jstype) SWIG_list_size_type "int"; -%typemap(javaout) SWIG_list_size_type { - final long result = $jnicall; - if (result > Integer.MAX_VALUE) { - throw new IndexOutOfBoundsException("Size of Collection is not representable as int"); - } - return (int)result; -} +%javamethodmodifiers std::list::doSize "private"; +%javamethodmodifiers std::list::doPreviousIndex "private"; +%javamethodmodifiers std::list::doNextIndex "private"; +%javamethodmodifiers std::list::doHasNext "private"; // Match Java style better: %rename(Iterator) std::list::iterator; %nodefaultctor std::list::iterator; +%typemap(javaimports) std::list %{ + import java.util.AbstractSequentialList; + import java.util.ListIterator; + import java.util.NoSuchElementException; + import java.util.Collection; +%} + +%typemap(javabase) std::list "AbstractSequentialList<$typemap(jboxtype, $1_basetype::value_type)>" + namespace std { template class list { + +%proxycode %{ + public $javaclassname(Collection c) { + this(); + ListIterator<$typemap(jboxtype, T)> it = listIterator(0); + // Special case the "copy constructor" here to avoid lots of cross-language calls + for (Object o : c) { + it.add(($typemap(jboxtype, T))o); + } + } + + public int size() { + return doSize(); + } + + public ListIterator<$typemap(jboxtype, T)> listIterator(int index) { + return new ListIterator<$typemap(jboxtype, T)>() { + private Iterator pos; + private Iterator last; + + private ListIterator<$typemap(jboxtype, T)> init(int index) { + pos = $javaclassname.this.begin(); + pos = pos.advance_unchecked(index); + return this; + } + + public void add($typemap(jboxtype, T) v) { + // Technically we can invalidate last here, but this makes more sense + last = $javaclassname.this.insert(pos, v); + } + + public void set($typemap(jboxtype, T) v) { + if (null == last) { + throw new IllegalStateException(); + } + last.set_unchecked(v); + } + + public void remove() { + if (null == last) { + throw new IllegalStateException(); + } + $javaclassname.this.remove(last); + last = null; + } + + public int previousIndex() { + return $javaclassname.this.doPreviousIndex(pos); + } + + public int nextIndex() { + return $javaclassname.this.doNextIndex(pos); + } + + public $typemap(jboxtype, T) previous() { + if (previousIndex() < 0) { + throw new NoSuchElementException(); + } + last = pos; + pos = pos.previous_unchecked(); + return last.deref_unchecked(); + } + + public $typemap(jboxtype, T) next() { + if (!hasNext()) { + throw new NoSuchElementException(); + } + last = pos; + pos = pos.next_unchecked(); + return last.deref_unchecked(); + } + + public boolean hasPrevious() { + // This call to previousIndex() will be much slower than the hasNext() implementation, but it's simpler like this with C++ forward iterators + return previousIndex() != -1; + } + + public boolean hasNext() { + return $javaclassname.this.doHasNext(pos); + } + }.init(index); + } +%} + public: typedef size_t size_type; typedef T value_type; - typedef T& reference; - %apply SWIG_list_size_type { size_type next_index, size_type previous_index, size_type size }; + typedef T &reference; /* * We'd actually be better off having the nested class *not* be static in the wrapper @@ -60,22 +138,22 @@ namespace std { * interface and give "natural" semantics to Java users of the C++ iterator) */ //%typemap(javaclassmodifiers) iterator "public class" - //%typemap(javainterfaces) iterator "ListIterator<$typemap(jboxtype,$1_basetype::value_type)>" + //%typemap(javainterfaces) iterator "ListIterator<$typemap(jboxtype, $1_basetype::value_type)>" struct iterator { %extend { - void set_unchecked(const value_type& v) { + void set_unchecked(const value_type &v) { **$self = v; } iterator next_unchecked() const { - std::list::iterator ret=*$self; + std::list::iterator ret = *$self; ++ret; return ret; } iterator previous_unchecked() const { - std::list::iterator ret=*$self; + std::list::iterator ret = *$self; --ret; return ret; } @@ -85,141 +163,45 @@ namespace std { } iterator advance_unchecked(const size_type index) const { - std::list::iterator ret=*$self; + std::list::iterator ret = *$self; std::advance(ret, index); return ret; } } }; - void assign(size_type n, const value_type &val); - - bool empty() const; - - list(size_type n, const value_type &value=value_type()); - list(const list &o); list(); + list(size_type n, const value_type &value = value_type()); + list(const list &o); ~list(); - - size_type max_size () const; - + void assign(size_type n, const value_type &val); + bool empty() const; + size_type max_size() const; void pop_back(); void pop_front(); void push_back(const value_type &x); void push_front(const value_type &x); - - size_type size() const; - - // Although sort() is nice it makes operator<() mandatory which it probably shouldn't be - //void sort(); - iterator begin(); iterator end(); iterator insert(iterator pos, const value_type &v); %extend { - size_type previous_index(const iterator& pos) const { - return pos == self->begin() ? -1 : std::distance(self->begin(), static_cast::const_iterator>(pos)); + %fragment("SWIG_ListSize"); + jint doSize() const throw (std::out_of_range) { + return SWIG_ListSize(self->size()); } - size_type next_index(const iterator& pos) const { - return pos == self->end() ? self->size() : std::distance(self->begin(), static_cast::const_iterator>(pos)); + jint doPreviousIndex(const iterator &pos) const { + return pos == self->begin() ? -1 : SWIG_ListSize(std::distance(self->begin(), static_cast::const_iterator>(pos))); } - bool has_next(const iterator& pos) const { + jint doNextIndex(const iterator &pos) const { + return pos == self->end() ? self->size() : SWIG_ListSize(std::distance(self->begin(), static_cast::const_iterator>(pos))); + } + + bool doHasNext(const iterator &pos) const { return pos != $self->end(); } } }; } - -%typemap(javaimports) std::list %{ - import java.util.AbstractSequentialList; - import java.util.ListIterator; - import java.util.NoSuchElementException; - import java.util.Collection; -%} - -%typemap(javabase) std::list "AbstractSequentialList<$typemap(jboxtype,$1_basetype::value_type)>" - -#define JAVA_VALUE_TYPE $typemap(jboxtype,$1_basetype::value_type) -#define JAVA_ITERATOR_TYPE Iterator - -%typemap(javacode,noblock=1) std::list { - public $javaclassname(Collection c) { - this(); - ListIterator it = listIterator(0); - // We should special case the "copy constructor" here to avoid lots of cross-language calls - for (Object o: c) { - it.add((JAVA_VALUE_TYPE)o); - } - } - - public ListIterator listIterator(int index) { - return new ListIterator() { - private JAVA_ITERATOR_TYPE pos; - private JAVA_ITERATOR_TYPE last; - - private ListIterator init(int index) { - pos = $javaclassname.this.begin(); - pos = pos.advance_unchecked(index); - return this; - } - - public void add(JAVA_VALUE_TYPE v) { - // Technically we can invalidate last here, but this makes more sense - last=$javaclassname.this.insert(pos, v); - } - - public void set(JAVA_VALUE_TYPE v) { - if (null==last) { - throw new IllegalStateException(); - } - last.set_unchecked(v); - } - - public void remove() { - if (null==last) { - throw new IllegalStateException(); - } - $javaclassname.this.remove(last); - last=null; - } - - public int previousIndex() { - return $javaclassname.this.previous_index(pos); - } - - public int nextIndex() { - return $javaclassname.this.next_index(pos); - } - - public JAVA_VALUE_TYPE previous() { - if (previousIndex() < 0) { - throw new NoSuchElementException(); - } - last = pos; - pos = pos.previous_unchecked(); - return last.deref_unchecked(); - } - - public JAVA_VALUE_TYPE next() { - if (!hasNext()) { - throw new NoSuchElementException(); - } - last = pos; - pos = pos.next_unchecked(); - return last.deref_unchecked(); - } - - public boolean hasPrevious() { - // This call to previousIndex() will be much slower than the hasNext() implementation, but it's simpler like this with C++ forward iterators - return previousIndex() != -1; - } - - public boolean hasNext() { - return $javaclassname.this.has_next(pos); - } - }.init(index); - } -} From 02a00db9f5a765daeb7e663a783340edbe2bf51e Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Thu, 22 Jun 2017 20:30:11 +0100 Subject: [PATCH 174/455] Remove redundant code --- Lib/java/std_list.i | 5 ----- 1 file changed, 5 deletions(-) diff --git a/Lib/java/std_list.i b/Lib/java/std_list.i index 70bb6e20a..070f6a606 100644 --- a/Lib/java/std_list.i +++ b/Lib/java/std_list.i @@ -16,11 +16,6 @@ SWIGINTERN jint SWIG_ListSize(size_t size) { %javamethodmodifiers std::list::begin "private"; %javamethodmodifiers std::list::insert "private"; -%javamethodmodifiers std::list::set "private"; -%javamethodmodifiers std::list::previous "private"; -%javamethodmodifiers std::list::next "private"; -%javamethodmodifiers std::list::deref "private"; -%javamethodmodifiers std::list::advance "private"; %javamethodmodifiers std::list::doSize "private"; %javamethodmodifiers std::list::doPreviousIndex "private"; %javamethodmodifiers std::list::doNextIndex "private"; From 7b7f921ccb9e1e4de193f073d07af87445ecb393 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Thu, 22 Jun 2017 20:38:19 +0100 Subject: [PATCH 175/455] cosmetics --- Lib/java/std_list.i | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib/java/std_list.i b/Lib/java/std_list.i index 070f6a606..f9986b11e 100644 --- a/Lib/java/std_list.i +++ b/Lib/java/std_list.i @@ -157,7 +157,7 @@ namespace std { return **$self; } - iterator advance_unchecked(const size_type index) const { + iterator advance_unchecked(size_type index) const { std::list::iterator ret = *$self; std::advance(ret, index); return ret; From 430376e1159eb578537de7c88b1dc9264d4128a8 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Thu, 22 Jun 2017 21:49:58 +0100 Subject: [PATCH 176/455] Java std::list - fully qualifiy Java class name to avoid potential name ambiguity --- Lib/java/std_list.i | 25 +++++++++---------------- 1 file changed, 9 insertions(+), 16 deletions(-) diff --git a/Lib/java/std_list.i b/Lib/java/std_list.i index f9986b11e..c6f074417 100644 --- a/Lib/java/std_list.i +++ b/Lib/java/std_list.i @@ -26,22 +26,15 @@ SWIGINTERN jint SWIG_ListSize(size_t size) { %nodefaultctor std::list::iterator; -%typemap(javaimports) std::list %{ - import java.util.AbstractSequentialList; - import java.util.ListIterator; - import java.util.NoSuchElementException; - import java.util.Collection; -%} - -%typemap(javabase) std::list "AbstractSequentialList<$typemap(jboxtype, $1_basetype::value_type)>" +%typemap(javabase) std::list "java.util.AbstractSequentialList<$typemap(jboxtype, $1_basetype::value_type)>" namespace std { template class list { %proxycode %{ - public $javaclassname(Collection c) { + public $javaclassname(java.util.Collection c) { this(); - ListIterator<$typemap(jboxtype, T)> it = listIterator(0); + java.util.ListIterator<$typemap(jboxtype, T)> it = listIterator(0); // Special case the "copy constructor" here to avoid lots of cross-language calls for (Object o : c) { it.add(($typemap(jboxtype, T))o); @@ -52,12 +45,12 @@ namespace std { return doSize(); } - public ListIterator<$typemap(jboxtype, T)> listIterator(int index) { - return new ListIterator<$typemap(jboxtype, T)>() { + public java.util.ListIterator<$typemap(jboxtype, T)> listIterator(int index) { + return new java.util.ListIterator<$typemap(jboxtype, T)>() { private Iterator pos; private Iterator last; - private ListIterator<$typemap(jboxtype, T)> init(int index) { + private java.util.ListIterator<$typemap(jboxtype, T)> init(int index) { pos = $javaclassname.this.begin(); pos = pos.advance_unchecked(index); return this; @@ -93,7 +86,7 @@ namespace std { public $typemap(jboxtype, T) previous() { if (previousIndex() < 0) { - throw new NoSuchElementException(); + throw new java.util.NoSuchElementException(); } last = pos; pos = pos.previous_unchecked(); @@ -102,7 +95,7 @@ namespace std { public $typemap(jboxtype, T) next() { if (!hasNext()) { - throw new NoSuchElementException(); + throw new java.util.NoSuchElementException(); } last = pos; pos = pos.next_unchecked(); @@ -133,7 +126,7 @@ namespace std { * interface and give "natural" semantics to Java users of the C++ iterator) */ //%typemap(javaclassmodifiers) iterator "public class" - //%typemap(javainterfaces) iterator "ListIterator<$typemap(jboxtype, $1_basetype::value_type)>" + //%typemap(javainterfaces) iterator "java.util.ListIterator<$typemap(jboxtype, $1_basetype::value_type)>" struct iterator { %extend { From 109a60add684e1991285c35b024b53a076f45737 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Thu, 22 Jun 2017 22:17:59 +0100 Subject: [PATCH 177/455] javabase typemap improvement for std::list --- Lib/java/std_list.i | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Lib/java/std_list.i b/Lib/java/std_list.i index c6f074417..38742632e 100644 --- a/Lib/java/std_list.i +++ b/Lib/java/std_list.i @@ -26,11 +26,10 @@ SWIGINTERN jint SWIG_ListSize(size_t size) { %nodefaultctor std::list::iterator; -%typemap(javabase) std::list "java.util.AbstractSequentialList<$typemap(jboxtype, $1_basetype::value_type)>" - namespace std { template class list { +%typemap(javabase) std::list< T > "java.util.AbstractSequentialList<$typemap(jboxtype, T)>" %proxycode %{ public $javaclassname(java.util.Collection c) { this(); From 80ffb169c173537c08355e75d4ade4462b38c015 Mon Sep 17 00:00:00 2001 From: Michael Thon Date: Tue, 7 Jun 2016 02:12:12 +0200 Subject: [PATCH 178/455] [Python] fix and improve default argument handling 1. Fix negative octals. Currently not handled correctly by `-py3` (unusual case, but incorrect). 2. Fix arguments of type "octal + something" (e.g. `0640 | 04`). Currently drops everything after the first octal. Nasty! 3. Fix bool arguments "0 + something" (e.g. `0 | 1`) are always "False" (unusual case, but incorrect). 4. Remove special handling of "TRUE" and "FALSE" from `convertValue` since there's no reason these have to match "true" and "false". 5. Remove the Python 2 vs. Python 3 distinction based on the `-py3` flag. Now the same python code is produced for default arguments for Python 2 and Python 3. For this, octal default arguments, e.g. 0644, are now wrapped as `int('644', 8)`. This is required, as Python 2 and Python 3 have incompatible syntax for octal literals. Fixes #707 --- CHANGES.current | 21 +++ Examples/test-suite/default_args.i | 14 +- .../test-suite/python/default_args_runme.py | 36 +++- Source/Modules/python.cxx | 163 ++++++++---------- 4 files changed, 129 insertions(+), 105 deletions(-) diff --git a/CHANGES.current b/CHANGES.current index f9177f1a6..d3c025363 100644 --- a/CHANGES.current +++ b/CHANGES.current @@ -7,6 +7,27 @@ the issue number to the end of the URL: https://github.com/swig/swig/issues/ Version 4.0.0 (in progress) =========================== +2017-06-23: m7thon + [Python] fix and improve default argument handling: + + 1. Fix negative octals. Currently not handled correctly by `-py3` + (unusual case, but incorrect). + 2. Fix arguments of type "octal + something" (e.g. `0640 | 04`). + Currently drops everything after the first octal. Nasty! + 3. Fix bool arguments "0 + something" (e.g. `0 | 1`) are always + "False" (unusual case, but incorrect). + 4. Remove special handling of "TRUE" and "FALSE" from + `convertValue` since there's no reason these have to match + "true" and "false". + 5. Remove the Python 2 vs. Python 3 distinction based on the + `-py3` flag. Now the same python code is produced for default + arguments for Python 2 and Python 3. For this, octal default + arguments, e.g. 0644, are now wrapped as `int('644', 8)`. This + is required, as Python 2 and Python 3 have incompatible syntax + for octal literals. + + Fixes #707 + 2017-06-19: wsfulton [Python] Fix handling of rich comparisons when wrapping overloaded operators: diff --git a/Examples/test-suite/default_args.i b/Examples/test-suite/default_args.i index 8828bfe04..28e64d40e 100644 --- a/Examples/test-suite/default_args.i +++ b/Examples/test-suite/default_args.i @@ -18,14 +18,20 @@ #include // All kinds of numbers: hex, octal (which pose special problems to Python), negative... - void trickyvalue1(int first, int pos = -1) {} - void trickyvalue2(int first, unsigned rgb = 0xabcdef) {} - void trickyvalue3(int first, int mode = 0644) {} + + class TrickyInPython { + public: + int value_m1(int first, int pos = -1) { return pos; } + unsigned value_0xabcdef(int first, unsigned rgb = 0xabcdef) { return rgb; } + int value_0644(int first, int mode = 0644) { return mode; } + int value_perm(int first, int mode = 0640 | 0004) { return mode; } + int value_m01(int first, int val = -01) { return val; } + bool booltest2(bool x = 0 | 1) { return x; } + }; void doublevalue1(int first, double num = 0.0e-1) {} void doublevalue2(int first, double num = -0.0E2) {} - // Long long arguments are not handled at Python level currently but still work. void seek(long long offset = 0LL) {} void seek2(unsigned long long offset = 0ULL) {} void seek3(long offset = 0L) {} diff --git a/Examples/test-suite/python/default_args_runme.py b/Examples/test-suite/python/default_args_runme.py index b7c4cb508..ddaf2cd4f 100644 --- a/Examples/test-suite/python/default_args_runme.py +++ b/Examples/test-suite/python/default_args_runme.py @@ -115,15 +115,39 @@ def run(module_name): if Klass_inc().val != 0: raise RuntimeError("Klass::inc failed") - default_args.trickyvalue1(10) - default_args.trickyvalue1(10, 10) - default_args.trickyvalue2(10) - default_args.trickyvalue2(10, 10) - default_args.trickyvalue3(10) - default_args.trickyvalue3(10, 10) + tricky_failure = False + tricky = default_args.TrickyInPython() + if tricky.value_m1(10) != -1: + print "trickyvalue_m1 failed" + tricky_failure = True + if tricky.value_m1(10, 10) != 10: + print "trickyvalue_m1 failed" + tricky_failure = True + if tricky.value_0xabcdef(10) != 0xabcdef: + print "trickyvalue_0xabcdef failed" + tricky_failure = True + if tricky.value_0644(10) != 420: + print "trickyvalue_0644 failed" + tricky_failure = True + if tricky.value_perm(10) != 420: + print "trickyvalue_perm failed" + tricky_failure = True + if tricky.value_m01(10) != -1: + print "trickyvalue_m01 failed" + tricky_failure = True + if not tricky.booltest2(): + print "booltest2 failed" + tricky_failure = True + + if tricky_failure: + raise RuntimeError + default_args.seek() default_args.seek(10) + if not default_args.booltest(): + raise RuntimeError("booltest failed") + if default_args.slightly_off_square(10) != 102: raise RuntimeError diff --git a/Source/Modules/python.cxx b/Source/Modules/python.cxx index 802c36cc7..a55c8ab09 100644 --- a/Source/Modules/python.cxx +++ b/Source/Modules/python.cxx @@ -2030,6 +2030,66 @@ public: return doc; } + /* ------------------------------------------------------------ + * convertIntegerValue() + * + * Check if string v is an integer and can be represented in + * Python. If so, return an appropriate Python representation, + * otherwise (or if we are unsure), return NIL. + * ------------------------------------------------------------ */ + String *convertIntegerValue(String *v, SwigType *resolved_type) { + const char *const s = Char(v); + char *end; + String *result = NIL; + + // Check if this is an integer number in any base. + long value = strtol(s, &end, 0); + if (errno == ERANGE || end == s) + return NIL; + if (*end != '\0') { + // If there is a suffix after the number, we can safely ignore any + // combination of "l" and "u", but not anything else. + for (char *p = end; *p != '\0'; ++p) { + switch (*p) { + case 'l': + case 'L': + case 'u': + case 'U': + break; + default: + return NIL; + } + } + } + // So now we are certain that we are indeed dealing with an integer + // that has a representation as long given by value. + + if (Cmp(resolved_type, "bool") == 0) + // Allow integers as the default value for a bool parameter. + return NewString(value ? "True" : "False"); + + if (value == 0) + return NewString(SwigType_ispointer(resolved_type) ? "None" : "0"); + + // v may still be octal or hexadecimal: + const char *p = s; + if (*p == '+' || *p == '-') + ++p; + if (*p == '0' && *(p+1) != 'x' && *(p+1) != 'X') { + // This must have been an octal number. This is the only case we + // cannot use in Python directly, since Python 2 and 3 use non- + // compatible representations. + result = NewString(*s == '-' ? "int('-" : "int('"); + String *octal_string = NewStringWithSize(p, (int) (end - p)); + Append(result, octal_string); + Append(result, "', 8)"); + Delete(octal_string); + return result; + } + result = *end == '\0' ? v : NewStringWithSize(s, (int) (end - s)); + return result; + } + /* ------------------------------------------------------------ * convertDoubleValue() * @@ -2078,111 +2138,24 @@ public: * convertValue() * * Check if string v can be a Python value literal or a - * constant. Return NIL if it isn't. + * constant. Return an equivalent Python representation, + * or NIL if it isn't, or we are unsure. * ------------------------------------------------------------ */ String *convertValue(String *v, SwigType *type) { const char *const s = Char(v); - char *end; String *result = NIL; - bool fail = false; - SwigType *resolved_type = 0; + SwigType *resolved_type = SwigType_typedef_resolve_all(type); - // Check if this is a number in any base. - long value = strtol(s, &end, 0); - (void) value; - if (end != s) { - if (errno == ERANGE) { - // There was an overflow, we could try representing the value as Python - // long integer literal, but for now don't bother with it. - fail = true; - } else { - if (*end != '\0') { - // If there is a suffix after the number, we can safely ignore any - // combination of "l" and "u", but not anything else (again, stuff like - // "LL" could be handled, but we don't bother to do it currently). - bool seen_long = false; - for (char * p = end; *p != '\0'; ++p) { - switch (*p) { - case 'l': - case 'L': - // Bail out on "LL". - if (seen_long) { - fail = true; - break; - } - seen_long = true; - break; - - case 'u': - case 'U': - if (value < 0) - fail = true; - break; - - default: - // Except that our suffix could actually be the fractional part of - // a floating point number, so we still have to check for this. - result = convertDoubleValue(v); - } - } - } - - if (!fail) { - // Allow integers as the default value for a bool parameter. - resolved_type = SwigType_typedef_resolve_all(type); - if (Cmp(resolved_type, "bool") == 0) { - result = NewString(value ? "True" : "False"); - } else { - // Deal with the values starting with 0 first as they can be octal or - // hexadecimal numbers or even pointers. - if (s[0] == '0') { - if (Len(v) == 1) { - // This is just a lone 0, but it needs to be represented differently - // in Python depending on whether it's a zero or a null pointer. - if (SwigType_ispointer(resolved_type)) - result = NewString("None"); - else - result = v; - } else if (s[1] == 'x' || s[1] == 'X') { - // This must have been a hex number, we can use it directly in Python, - // so nothing to do here. - } else { - // This must have been an octal number, we have to change its prefix - // to be "0o" in Python 3 only (and as long as we still support Python - // 2.5, this can't be done unconditionally). - if (py3) { - if (end - s > 1) { - result = NewString("0o"); - Append(result, NewStringWithSize(s + 1, (int)(end - s - 1))); - } - } - } - } - - // Avoid unnecessary string allocation in the common case when we don't - // need to remove any suffix. - if (!result) - result = *end == '\0' ? v : NewStringWithSize(s, (int)(end - s)); - } - } - } - } - - // Check if this is a floating point number (notice that it wasn't - // necessarily parsed as a long above, consider e.g. ".123"). - if (!fail && !result) { + result = convertIntegerValue(v, resolved_type); + if (!result) { result = convertDoubleValue(v); if (!result) { - if (Strcmp(v, "true") == 0 || Strcmp(v, "TRUE") == 0) + if (Strcmp(v, "true") == 0) result = NewString("True"); - else if (Strcmp(v, "false") == 0 || Strcmp(v, "FALSE") == 0) + else if (Strcmp(v, "false") == 0) result = NewString("False"); - else if (Strcmp(v, "NULL") == 0 || Strcmp(v, "nullptr") == 0) { - if (!resolved_type) - resolved_type = SwigType_typedef_resolve_all(type); + else if (Strcmp(v, "NULL") == 0 || Strcmp(v, "nullptr") == 0) result = SwigType_ispointer(resolved_type) ? NewString("None") : NewString("0"); - } - // This could also be an enum type, default value of which could be // representable in Python if it doesn't include any scope (which could, // but currently is not, translated). From 2425c8d6d896dfb4eacb1b5877a5fa6274fde8d8 Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Fri, 23 Jun 2017 14:54:50 +1200 Subject: [PATCH 179/455] Don't handle cases like -1U as Python constants --- Source/Modules/python.cxx | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/Source/Modules/python.cxx b/Source/Modules/python.cxx index a55c8ab09..73706f240 100644 --- a/Source/Modules/python.cxx +++ b/Source/Modules/python.cxx @@ -2047,14 +2047,18 @@ public: if (errno == ERANGE || end == s) return NIL; if (*end != '\0') { - // If there is a suffix after the number, we can safely ignore any - // combination of "l" and "u", but not anything else. + // If there is a suffix after the number, we can safely ignore "l" + // and (provided the number is unsigned) "u", and also combinations of + // these, but not anything else. for (char *p = end; *p != '\0'; ++p) { switch (*p) { case 'l': case 'L': + break; case 'u': case 'U': + if (value < 0) + return NIL; break; default: return NIL; From a2267a815288076e31e27e4397d78e6f2c1b0627 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Fri, 23 Jun 2017 14:19:12 +0100 Subject: [PATCH 180/455] Memory leak fixes in Python default argument handling --- Source/Modules/python.cxx | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/Source/Modules/python.cxx b/Source/Modules/python.cxx index 73706f240..581064046 100644 --- a/Source/Modules/python.cxx +++ b/Source/Modules/python.cxx @@ -1874,6 +1874,7 @@ public: String *new_value = convertValue(value, Getattr(p, "type")); if (new_value) Printf(doc, "=%s", new_value); + Delete(new_value); } Delete(type_str); Delete(made_name); @@ -2090,7 +2091,7 @@ public: Delete(octal_string); return result; } - result = *end == '\0' ? v : NewStringWithSize(s, (int) (end - s)); + result = *end == '\0' ? Copy(v) : NewStringWithSize(s, (int) (end - s)); return result; } @@ -2132,7 +2133,7 @@ public: // Avoid unnecessary string allocation in the common case when we don't // need to remove any suffix. - return *end == '\0' ? v : NewStringWithSize(s, (int)(end - s)); + return *end == '\0' ? Copy(v) : NewStringWithSize(s, (int)(end - s)); } return NIL; @@ -2167,7 +2168,7 @@ public: Node *lookup = Swig_symbol_clookup(v, 0); if (lookup) { if (Cmp(Getattr(lookup, "nodeType"), "enumitem") == 0) - result = Getattr(lookup, "sym:name"); + result = Copy(Getattr(lookup, "sym:name")); } } } @@ -2214,10 +2215,12 @@ public: if (Getattr(p, "tmap:default")) return false; - if (String *value = Getattr(p, "value")) { - String *type = Getattr(p, "type"); - if (!convertValue(value, type)) + String *value = Getattr(p, "value"); + if (value) { + String *convertedValue = convertValue(value, Getattr(p, "type")); + if (!convertedValue) return false; + Delete(convertedValue); } } From 005ff93dbdabb9ce0708d74588c36b04aff1e658 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Fri, 23 Jun 2017 14:38:26 +0100 Subject: [PATCH 181/455] Fix construction from dict for std::multimap std::unordered_multimap (Python 3) --- Lib/python/std_multimap.i | 6 +++++- Lib/python/std_unordered_multimap.i | 6 +++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/Lib/python/std_multimap.i b/Lib/python/std_multimap.i index 21c84b009..f78a5277c 100644 --- a/Lib/python/std_multimap.i +++ b/Lib/python/std_multimap.i @@ -23,7 +23,11 @@ int res = SWIG_ERROR; if (PyDict_Check(obj)) { SwigVar_PyObject items = PyObject_CallMethod(obj,(char *)"items",NULL); - return traits_asptr_stdseq, std::pair >::asptr(items, val); +%#if PY_VERSION_HEX >= 0x03000000 + /* In Python 3.x the ".items()" method returns a dict_items object */ + items = PySequence_Fast(items, ".items() didn't return a sequence!"); +%#endif + res = traits_asptr_stdseq, std::pair >::asptr(items, val); } else { multimap_type *p; swig_type_info *descriptor = swig::type_info(); diff --git a/Lib/python/std_unordered_multimap.i b/Lib/python/std_unordered_multimap.i index 4dbc2a4dd..6d7def900 100644 --- a/Lib/python/std_unordered_multimap.i +++ b/Lib/python/std_unordered_multimap.i @@ -30,7 +30,11 @@ int res = SWIG_ERROR; if (PyDict_Check(obj)) { SwigVar_PyObject items = PyObject_CallMethod(obj,(char *)"items",NULL); - return traits_asptr_stdseq, std::pair >::asptr(items, val); +%#if PY_VERSION_HEX >= 0x03000000 + /* In Python 3.x the ".items()" method returns a dict_items object */ + items = PySequence_Fast(items, ".items() didn't return a sequence!"); +%#endif + res = traits_asptr_stdseq, std::pair >::asptr(items, val); } else { unordered_multimap_type *p; swig_type_info *descriptor = swig::type_info(); From c6bff3731e59cb820bfaddae4d205a689bcde343 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Fri, 23 Jun 2017 14:51:25 +0100 Subject: [PATCH 182/455] Add Python 3 C++11 Travis testing --- .travis.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.travis.yml b/.travis.yml index 57f20eef6..e2a47e6f1 100644 --- a/.travis.yml +++ b/.travis.yml @@ -169,6 +169,10 @@ matrix: env: SWIGLANG=python SWIG_FEATURES=-builtin SWIG_CC=gcc-5 SWIG_CXX=g++-5 CPP11=1 sudo: required dist: trusty + - os: linux + env: SWIGLANG=python SWIG_FEATURES=-builtin SWIG_CC=gcc-5 SWIG_CXX=g++-5 CPP11=1 PY3=3 VER=3.5 + sudo: required + dist: trusty - compiler: gcc os: linux env: SWIGLANG=python SWIG_FEATURES=-builtin PY3=3 VER=3.4 From 990c5973657bbf25d50d65fc3d40d8bf3b4df0a9 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Fri, 23 Jun 2017 15:26:53 +0100 Subject: [PATCH 183/455] Wrap std::list::empty as isEmpty in Java --- Examples/test-suite/java/li_std_list_runme.java | 7 ++++++- Lib/java/std_list.i | 1 + 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/Examples/test-suite/java/li_std_list_runme.java b/Examples/test-suite/java/li_std_list_runme.java index de53a9fa6..c3c666c51 100644 --- a/Examples/test-suite/java/li_std_list_runme.java +++ b/Examples/test-suite/java/li_std_list_runme.java @@ -16,7 +16,12 @@ public class li_std_list_runme { IntList v1 = new IntList(); DoubleList v2 = new DoubleList(); - v1.add(123); + if (!v1.isEmpty()) throw new RuntimeException("v1 test (1) failed"); + if (v1.size() != 0) throw new RuntimeException("v1 test (2) failed"); + if (!v1.add(123)) throw new RuntimeException("v1 test (3) failed"); + if (v1.size() != 1) throw new RuntimeException("v1 test (4) failed"); + if (v1.isEmpty()) throw new RuntimeException("v1 test (5) failed"); + if (v1.get(0) != 123) throw new RuntimeException("v1 test failed"); StructList v4 = new StructList(); diff --git a/Lib/java/std_list.i b/Lib/java/std_list.i index 38742632e..8714be0f4 100644 --- a/Lib/java/std_list.i +++ b/Lib/java/std_list.i @@ -162,6 +162,7 @@ namespace std { list(const list &o); ~list(); void assign(size_type n, const value_type &val); + %rename(isEmpty) empty; bool empty() const; size_type max_size() const; void pop_back(); From 428b332e6845093abc68a1f704db714beaa86cf8 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Fri, 23 Jun 2017 15:35:10 +0100 Subject: [PATCH 184/455] Improve Java std::list std::vector runtime tests and wrap std::list::clear --- .../test-suite/java/li_std_list_runme.java | 13 +++++++++++ .../test-suite/java/li_std_vector_runme.java | 22 +++++++++++++------ Lib/java/std_list.i | 1 + 3 files changed, 29 insertions(+), 7 deletions(-) diff --git a/Examples/test-suite/java/li_std_list_runme.java b/Examples/test-suite/java/li_std_list_runme.java index c3c666c51..05be034ff 100644 --- a/Examples/test-suite/java/li_std_list_runme.java +++ b/Examples/test-suite/java/li_std_list_runme.java @@ -22,7 +22,20 @@ public class li_std_list_runme { if (v1.size() != 1) throw new RuntimeException("v1 test (4) failed"); if (v1.isEmpty()) throw new RuntimeException("v1 test (5) failed"); + int sum = 0; + for (int n : v1) { + if (n != 123) throw new RuntimeException("v1 loop test failed"); + sum += n; + } + if (sum != 123) throw new RuntimeException("v1 sum test failed"); if (v1.get(0) != 123) throw new RuntimeException("v1 test failed"); + v1.clear(); + if (!v1.isEmpty()) throw new RuntimeException("v1 test clear failed"); + v1.add(123); + + if (v1.set(0, 456) != 123) throw new RuntimeException("v1 test (6) failed"); + if (v1.size() != 1) throw new RuntimeException("v1 test (7) failed"); + if (v1.get(0) != 456) throw new RuntimeException("v1 test (8) failed"); StructList v4 = new StructList(); StructPtrList v5 = new StructPtrList(); diff --git a/Examples/test-suite/java/li_std_vector_runme.java b/Examples/test-suite/java/li_std_vector_runme.java index 60776bbf1..56a2e4359 100644 --- a/Examples/test-suite/java/li_std_vector_runme.java +++ b/Examples/test-suite/java/li_std_vector_runme.java @@ -17,15 +17,23 @@ public class li_std_vector_runme { IntPtrVector v2 = li_std_vector.vecintptr(new IntPtrVector()); IntConstPtrVector v3 = li_std_vector.vecintconstptr(new IntConstPtrVector()); - for (int n : v1) { - if (n != 123) throw new RuntimeException("v1 loop test failed"); - } - if (!v1.isEmpty()) throw new RuntimeException("v1 test (1) failed"); if (v1.size() != 0) throw new RuntimeException("v1 test (2) failed"); if (!v1.add(123)) throw new RuntimeException("v1 test (3) failed"); if (v1.size() != 1) throw new RuntimeException("v1 test (4) failed"); if (v1.isEmpty()) throw new RuntimeException("v1 test (5) failed"); + + int sum = 0; + for (int n : v1) { + if (n != 123) throw new RuntimeException("v1 loop test failed"); + sum += n; + } + if (sum != 123) throw new RuntimeException("v1 sum test failed"); + if (v1.get(0) != 123) throw new RuntimeException("v1 test failed"); + v1.clear(); + if (!v1.isEmpty()) throw new RuntimeException("v1 test clear failed"); + v1.add(123); + if (v1.set(0, 456) != 123) throw new RuntimeException("v1 test (6) failed"); if (v1.size() != 1) throw new RuntimeException("v1 test (7) failed"); if (v1.get(0) != 456) throw new RuntimeException("v1 test (8) failed"); @@ -59,13 +67,13 @@ public class li_std_vector_runme { if (v6.get(0).getNum() != 56) throw new RuntimeException("v6 test failed"); for (Struct s : v4) { - if (s.getNum() != 12) throw new RuntimeException("v4 loop test failed"); + if (s.getNum() != 12) throw new RuntimeException("v4 loop test failed"); } for (Struct s : v5) { - if (s.getNum() != 34) throw new RuntimeException("v5 loop test failed"); + if (s.getNum() != 34) throw new RuntimeException("v5 loop test failed"); } for (Struct s : v6) { - if (s.getNum() != 56) throw new RuntimeException("v6 loop test failed"); + if (s.getNum() != 56) throw new RuntimeException("v6 loop test failed"); } StructVector v7 = li_std_vector.vecstruct(new StructVector()); diff --git a/Lib/java/std_list.i b/Lib/java/std_list.i index 8714be0f4..ab824e512 100644 --- a/Lib/java/std_list.i +++ b/Lib/java/std_list.i @@ -164,6 +164,7 @@ namespace std { void assign(size_type n, const value_type &val); %rename(isEmpty) empty; bool empty() const; + void clear(); size_type max_size() const; void pop_back(); void pop_front(); From 2d99027935a95d6b02bb6904bdbea1eff52c6f4d Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Fri, 23 Jun 2017 16:17:00 +0100 Subject: [PATCH 185/455] Fix removing elements from std::list Java wrapper Add missing remove method on Java side (without it elements aren't removed). --- Examples/test-suite/java/li_std_list_runme.java | 16 ++++++++++++++++ Lib/java/std_list.i | 2 ++ 2 files changed, 18 insertions(+) diff --git a/Examples/test-suite/java/li_std_list_runme.java b/Examples/test-suite/java/li_std_list_runme.java index 05be034ff..ca40db2f2 100644 --- a/Examples/test-suite/java/li_std_list_runme.java +++ b/Examples/test-suite/java/li_std_list_runme.java @@ -37,6 +37,22 @@ public class li_std_list_runme { if (v1.size() != 1) throw new RuntimeException("v1 test (7) failed"); if (v1.get(0) != 456) throw new RuntimeException("v1 test (8) failed"); + java.util.Iterator v1_iterator = v1.iterator(); + if (!v1_iterator.hasNext()) throw new RuntimeException("v1 test (9) failed"); + if (v1_iterator.next() != 456) throw new RuntimeException("v1 test (10) failed"); + if (v1_iterator.hasNext()) throw new RuntimeException("v1 test (11) failed"); + try { + v1_iterator.next(); + throw new RuntimeException("v1 test (12) failed"); + } catch (java.util.NoSuchElementException e) { + } + + if (v1.remove(new Integer(123))) throw new RuntimeException("v1 test (13) failed"); + if (!v1.remove(new Integer(456))) throw new RuntimeException("v1 test (14) failed"); + if (!v1.isEmpty()) throw new RuntimeException("v1 test (15) failed"); + if (v1.size() != 0) throw new RuntimeException("v1 test (16) failed"); + if (v1.remove(new Integer(456))) throw new RuntimeException("v1 test (17) failed"); + StructList v4 = new StructList(); StructPtrList v5 = new StructPtrList(); StructConstPtrList v6 = new StructConstPtrList(); diff --git a/Lib/java/std_list.i b/Lib/java/std_list.i index ab824e512..0eca5a970 100644 --- a/Lib/java/std_list.i +++ b/Lib/java/std_list.i @@ -165,6 +165,8 @@ namespace std { %rename(isEmpty) empty; bool empty() const; void clear(); + %rename(remove) erase; + iterator erase(iterator pos); size_type max_size() const; void pop_back(); void pop_front(); From b40b9aee83f25796aa64a2288a351ed55302e1ba Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Fri, 23 Jun 2017 20:10:26 +0100 Subject: [PATCH 186/455] Modify std::list declarations to match the C++ standard --- Lib/java/std_list.i | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/Lib/java/std_list.i b/Lib/java/std_list.i index 0eca5a970..0ce26ad0f 100644 --- a/Lib/java/std_list.i +++ b/Lib/java/std_list.i @@ -125,11 +125,11 @@ namespace std { * interface and give "natural" semantics to Java users of the C++ iterator) */ //%typemap(javaclassmodifiers) iterator "public class" - //%typemap(javainterfaces) iterator "java.util.ListIterator<$typemap(jboxtype, $1_basetype::value_type)>" + //%typemap(javainterfaces) iterator "java.util.ListIterator<$typemap(jboxtype, T)>" struct iterator { %extend { - void set_unchecked(const value_type &v) { + void set_unchecked(const T &v) { **$self = v; } @@ -145,7 +145,7 @@ namespace std { return ret; } - value_type deref_unchecked() const { + T deref_unchecked() const { return **$self; } @@ -158,10 +158,10 @@ namespace std { }; list(); - list(size_type n, const value_type &value = value_type()); - list(const list &o); + list(size_type n, const T &value = T()); + list(const list &other); ~list(); - void assign(size_type n, const value_type &val); + void assign(size_type n, const T &value); %rename(isEmpty) empty; bool empty() const; void clear(); @@ -170,11 +170,11 @@ namespace std { size_type max_size() const; void pop_back(); void pop_front(); - void push_back(const value_type &x); - void push_front(const value_type &x); + void push_back(const T &value); + void push_front(const T &value); iterator begin(); iterator end(); - iterator insert(iterator pos, const value_type &v); + iterator insert(iterator pos, const T &value); %extend { %fragment("SWIG_ListSize"); From c2f622c73c27fa370c6d643512b6d8591f0929f2 Mon Sep 17 00:00:00 2001 From: FUTATSUKI Yasuhito Date: Sat, 24 Jun 2017 21:41:59 +0900 Subject: [PATCH 187/455] Fix make *clean issue in CCache subdir --- CCache/Makefile.in | 36 ++++++++++++++++++------------------ CCache/test.sh | 4 ++++ 2 files changed, 22 insertions(+), 18 deletions(-) diff --git a/CCache/Makefile.in b/CCache/Makefile.in index 1a6feb40f..f3b25a5f5 100644 --- a/CCache/Makefile.in +++ b/CCache/Makefile.in @@ -26,46 +26,46 @@ OBJS= ccache.o mdfour.o hash.o execute.o util.o args.o stats.o \ cleanup.o snprintf.o unify.o HEADERS = ccache.h mdfour.h -all: $(PROGRAM_NAME)$(EXEEXT) +all: $(PACKAGE_NAME)$(EXEEXT) # Regenerate Makefile if Makefile.in or config.status have changed. Makefile: $(srcdir)/Makefile.in ./config.status $(SHELL) ./config.status # Note that HTML documentation is actually generated and used from the main SWIG documentation Makefile -docs: $(srcdir)/$(PROGRAM_NAME).1 $(srcdir)/web/$(PROGRAM_NAME)-man.html +docs: $(srcdir)/$(PACKAGE_NAME).1 $(srcdir)/web/$(PACKAGE_NAME)-man.html -$(PROGRAM_NAME)$(EXEEXT): $(OBJS) $(HEADERS) +$(PACKAGE_NAME)$(EXEEXT): $(OBJS) $(HEADERS) $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(OBJS) $(LIBS) -$(srcdir)/$(PROGRAM_NAME).1: $(srcdir)/ccache.yo - -yodl2man -o $(srcdir)/$(PROGRAM_NAME).1 $(srcdir)/ccache.yo +$(srcdir)/$(PACKAGE_NAME).1: $(srcdir)/ccache.yo + -yodl2man -o $(srcdir)/$(PACKAGE_NAME).1 $(srcdir)/ccache.yo -$(srcdir)/web/$(PROGRAM_NAME)-man.html: $(srcdir)/ccache.yo - yodl2html -o $(srcdir)/web/$(PROGRAM_NAME)-man.html $(srcdir)/ccache.yo +$(srcdir)/web/$(PACKAGE_NAME)-man.html: $(srcdir)/ccache.yo + yodl2html -o $(srcdir)/web/$(PACKAGE_NAME)-man.html $(srcdir)/ccache.yo -install: $(PROGRAM_NAME)$(EXEEXT) - @echo "Installing $(PROGRAM_NAME)" +install: $(PACKAGE_NAME)$(EXEEXT) + @echo "Installing $(PACKAGE_NAME)" @echo "Installing $(DESTDIR)${bindir}/$(PROGRAM_NAME)$(EXEEXT)" ${INSTALLCMD} -d $(DESTDIR)${bindir} - ${INSTALLCMD} -m 755 $(PROGRAM_NAME)$(EXEEXT) $(DESTDIR)${bindir}/$(PROGRAM_NAME)$(EXEEXT) + ${INSTALLCMD} -m 755 $(PACKAGE_NAME)$(EXEEXT) $(DESTDIR)${bindir}/$(PROGRAM_NAME)$(EXEEXT) -install-docs: $(srcdir)/$(PROGRAM_NAME).1 +install-docs: $(srcdir)/$(PACKAGE_NAME).1 @echo "Installing $(DESTDIR)${mandir}/man1/$(PROGRAM_NAME).1" ${INSTALLCMD} -d $(DESTDIR)${mandir}/man1 - ${INSTALLCMD} -m 644 $(srcdir)/$(PROGRAM_NAME).1 $(DESTDIR)${mandir}/man1/$(PROGRAM_NAME).1 + ${INSTALLCMD} -m 644 $(srcdir)/$(PACKAGE_NAME).1 $(DESTDIR)${mandir}/man1/$(PROGRAM_NAME).1 -uninstall: $(PROGRAM_NAME)$(EXEEXT) +uninstall: $(PACKAGE_NAME)$(EXEEXT) rm -f $(DESTDIR)${bindir}/$(PROGRAM_NAME)$(EXEEXT) -uninstall-docs: $(srcdir)/$(PROGRAM_NAME).1 - rm -f $(DESTDIR)${mandir}/man1/$(PROGRAM_NAME).1 +uninstall-docs: $(srcdir)/$(PACKAGE_NAME).1 + rm -f $(DESTDIR)${mandir}/man1/$(PACKAGE_NAME).1 clean: - /bin/rm -f $(OBJS) *~ $(PROGRAM_NAME)$(EXEEXT) + /bin/rm -f $(OBJS) *~ $(PACKAGE_NAME)$(EXEEXT) test: test.sh - SWIG_LIB='$(SWIG_LIB)' PATH=../..:$$PATH SWIG='$(SWIG)' CC='$(CC)' NOSOFTLINKSTEST='$(NOSOFTLINKSTEST)' CCACHE='../$(PROGRAM_NAME)' $(srcdir)/test.sh + SWIG_LIB='$(SWIG_LIB)' PATH=../..:$$PATH SWIG='$(SWIG)' CC='$(CC)' NOSOFTLINKSTEST='$(NOSOFTLINKSTEST)' CCACHE='../$(PACKAGE_NAME)' CCACHE_PROG=$(PROGRAM_NAME) $(srcdir)/test.sh check: test @@ -74,7 +74,7 @@ distclean: clean /bin/rm -rf autom4te.cache maintainer-clean: distclean - /bin/rm -f $(srcdir)/$(PROGRAM_NAME).1 $(srcdir)/web/$(PROGRAM_NAME)-man.html + /bin/rm -f $(srcdir)/$(PACKAGE_NAME).1 $(srcdir)/web/$(PACKAGE_NAME)-man.html # FIXME: To fix this, test.sh needs to be able to take ccache from the diff --git a/CCache/test.sh b/CCache/test.sh index 7e69149ff..5b6f92a35 100755 --- a/CCache/test.sh +++ b/CCache/test.sh @@ -411,6 +411,10 @@ swigtests() { # main program rm -rf $TESTDIR mkdir $TESTDIR +if test -n "$CCACHE_PROG"; then + ln -s $CCACHE $TESTDIR/$CCACHE_PROG + CCACHE=./$CCACHE_PROG +fi cd $TESTDIR || exit 1 unset CCACHE_DIR From ea55c5bba0596676668b23877e256a510a60807a Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Sat, 24 Jun 2017 14:21:34 +0100 Subject: [PATCH 188/455] Java std::vector std::list enhancements - Add missing vector copy constructor - Add constructor to initialize the containers. Note that Java's equivalent constructor for ArrayList just sets the capacity, whereas the wrappers behave like the C++ constructor and set the size. I've done this mainly because there has been a vector(size_type) constructor in the Java wrappers for many years, so best to keep this unchanged. --- .../test-suite/java/li_std_list_runme.java | 67 ++++++++++++++++++- .../test-suite/java/li_std_vector_runme.java | 6 ++ Examples/test-suite/li_std_list.i | 24 ++++--- Lib/java/std_list.i | 15 ++++- Lib/java/std_vector.i | 14 +++- 5 files changed, 114 insertions(+), 12 deletions(-) diff --git a/Examples/test-suite/java/li_std_list_runme.java b/Examples/test-suite/java/li_std_list_runme.java index ca40db2f2..f0e48804b 100644 --- a/Examples/test-suite/java/li_std_list_runme.java +++ b/Examples/test-suite/java/li_std_list_runme.java @@ -53,6 +53,12 @@ public class li_std_list_runme { if (v1.size() != 0) throw new RuntimeException("v1 test (16) failed"); if (v1.remove(new Integer(456))) throw new RuntimeException("v1 test (17) failed"); + if (new IntList(3).size() != 3) throw new RuntimeException("constructor initial size test failed"); + for (int n : new IntList(10, 999)) + if (n != 999) throw new RuntimeException("constructor initialization with value failed"); + for (int n : new IntList(new IntList(10, 999))) + if (n != 999) throw new RuntimeException("copy constructor initialization with value failed"); + StructList v4 = new StructList(); StructPtrList v5 = new StructPtrList(); StructConstPtrList v6 = new StructConstPtrList(); @@ -61,9 +67,68 @@ public class li_std_list_runme { v5.add(new Struct(34)); v6.add(new Struct(56)); - Struct s = null; if (v4.get(0).getNum() != 12) throw new RuntimeException("v4 test failed"); if (v5.get(0).getNum() != 34) throw new RuntimeException("v5 test failed"); if (v6.get(0).getNum() != 56) throw new RuntimeException("v6 test failed"); + + for (Struct s : v4) { + if (s.getNum() != 12) throw new RuntimeException("v4 loop test failed"); + } + for (Struct s : v5) { + if (s.getNum() != 34) throw new RuntimeException("v5 loop test failed"); + } + for (Struct s : v6) { + if (s.getNum() != 56) throw new RuntimeException("v6 loop test failed"); + } + + StructList v7 = li_std_list.CopyContainerStruct(new StructList()); + v7.add(new Struct(1)); + v7.add(new Struct(23)); + v7.add(new Struct(456)); + v7.add(new Struct(7890)); + if (v7.size() != 4) throw new RuntimeException("v7 test (1) failed"); + { + double[] a7 = {1, 23, 456, 7890}; + int i7 = 0; + for (Struct s7 : v7) { + if (s7.getNum() != a7[i7]) throw new RuntimeException("v7 test (2) failed"); + i7++; + } + if (i7 != a7.length) throw new RuntimeException("v7 test (3) failed"); + } + if (v7.remove(2).getNum() != 456) throw new RuntimeException("v7 test (4) failed"); + { + double[] a7 = {1, 23, 7890}; + int i7 = 0; + for (Struct s7 : v7) { + if (s7.getNum() != a7[i7]) throw new RuntimeException("v7 test (5) failed"); + i7++; + } + if (i7 != a7.length) throw new RuntimeException("v7 test (6) failed"); + } + v7.add(1, new Struct(123)); + { + double[] a7 = {1, 123, 23, 7890}; + int i7 = 0; + for (Struct s7 : v7) { + if (s7.getNum() != a7[i7]) throw new RuntimeException("v7 test (7) failed"); + i7++; + } + if (i7 != a7.length) throw new RuntimeException("v7 test (8) failed"); + } + + BoolList v8 = new BoolList(); + if (!v8.add(true)) throw new RuntimeException("v8 test (1) failed");; + if (v8.get(0) != true) throw new RuntimeException("v8 test (2) failed");; + if (v8.set(0, false) != true) throw new RuntimeException("v8 test (3) failed");; + if (v8.set(0, false) != false) throw new RuntimeException("v8 test (4) failed");; + if (v8.size() != 1) throw new RuntimeException("v8 test (5) failed");; + + java.util.ArrayList bl = new java.util.ArrayList(java.util.Arrays.asList(true, false, true, false)); + BoolList bv = new BoolList(java.util.Arrays.asList(true, false, true, false)); + BoolList bv2 = new BoolList(bl); + java.util.ArrayList bl2 = new java.util.ArrayList(bv); + boolean bbb1 = bv.get(0); + Boolean bbb2 = bv.get(0); } } diff --git a/Examples/test-suite/java/li_std_vector_runme.java b/Examples/test-suite/java/li_std_vector_runme.java index 56a2e4359..b63df0210 100644 --- a/Examples/test-suite/java/li_std_vector_runme.java +++ b/Examples/test-suite/java/li_std_vector_runme.java @@ -54,6 +54,12 @@ public class li_std_vector_runme { if (v1.size() != 0) throw new RuntimeException("v1 test (16) failed"); if (v1.remove(new Integer(456))) throw new RuntimeException("v1 test (17) failed"); + if (new IntVector(3).size() != 3) throw new RuntimeException("constructor initial size test failed"); + for (int n : new IntVector(10, 999)) + if (n != 999) throw new RuntimeException("constructor initialization with value failed"); + for (int n : new IntVector(new IntVector(10, 999))) + if (n != 999) throw new RuntimeException("copy constructor initialization with value failed"); + StructVector v4 = li_std_vector.vecstruct(new StructVector()); StructPtrVector v5 = li_std_vector.vecstructptr(new StructPtrVector()); StructConstPtrVector v6 = li_std_vector.vecstructconstptr(new StructConstPtrVector()); diff --git a/Examples/test-suite/li_std_list.i b/Examples/test-suite/li_std_list.i index 3a2d761ff..d1ec4e7e4 100644 --- a/Examples/test-suite/li_std_list.i +++ b/Examples/test-suite/li_std_list.i @@ -1,6 +1,7 @@ %module li_std_list %include "std_list.i" +%include "std_string.i" %{ #include @@ -8,15 +9,18 @@ #include %} -namespace std { - %template(IntList) list; -} - +%template(BoolList) std::list; +%template(CharList) std::list; +%template(ShortList) std::list; +%template(IntList) std::list; +%template(LongList) std::list; +%template(UCharList) std::list; +%template(UIntList) std::list; +%template(UShortList) std::list; +%template(ULongList) std::list; +%template(FloatList) std::list; %template(DoubleList) std::list; - -namespace std { - %template(RealList) list; -} +%template(StringList) std::list; %inline %{ @@ -37,6 +41,10 @@ struct Struct { // bool operator==(const Struct &other) { return (num == other.num); } }; +const std::list & CopyContainerStruct(const std::list & container) { return container; } +const std::list & CopyContainerStructPtr(const std::list & container) { return container; } +const std::list & CopyContainerStructConstPtr(const std::list & container) { return container; } + enum Fruit { APPLE, BANANNA, diff --git a/Lib/java/std_list.i b/Lib/java/std_list.i index 0ce26ad0f..619afbb1d 100644 --- a/Lib/java/std_list.i +++ b/Lib/java/std_list.i @@ -29,7 +29,7 @@ SWIGINTERN jint SWIG_ListSize(size_t size) { namespace std { template class list { -%typemap(javabase) std::list< T > "java.util.AbstractSequentialList<$typemap(jboxtype, T)>" +%typemap(javabase) std::list "java.util.AbstractSequentialList<$typemap(jboxtype, T)>" %proxycode %{ public $javaclassname(java.util.Collection c) { this(); @@ -158,7 +158,6 @@ namespace std { }; list(); - list(size_type n, const T &value = T()); list(const list &other); ~list(); void assign(size_type n, const T &value); @@ -178,6 +177,18 @@ namespace std { %extend { %fragment("SWIG_ListSize"); + list(jint count) { + if (count < 0) + throw std::out_of_range("list count must be positive"); + return new std::list(static_cast::size_type>(count)); + } + + list(jint count, const T &value) { + if (count < 0) + throw std::out_of_range("list count must be positive"); + return new std::list(static_cast::size_type>(count), value); + } + jint doSize() const throw (std::out_of_range) { return SWIG_ListSize(self->size()); } diff --git a/Lib/java/std_vector.i b/Lib/java/std_vector.i index 4f5afe6db..2f6f07096 100644 --- a/Lib/java/std_vector.i +++ b/Lib/java/std_vector.i @@ -75,7 +75,7 @@ SWIGINTERN jint SWIG_VectorSize(size_t size) { typedef CTYPE value_type; typedef CREF_TYPE const_reference; vector(); - vector(size_type n); + vector(const vector &other); size_type capacity() const; void reserve(size_type n); %rename(isEmpty) empty; @@ -83,6 +83,18 @@ SWIGINTERN jint SWIG_VectorSize(size_t size) { void clear(); %extend { %fragment("SWIG_VectorSize"); + vector(jint count) { + if (count < 0) + throw std::out_of_range("vector count must be positive"); + return new std::vector< CTYPE >(static_cast::size_type>(count)); + } + + vector(jint count, const CTYPE &value) { + if (count < 0) + throw std::out_of_range("vector count must be positive"); + return new std::vector< CTYPE >(static_cast::size_type>(count), value); + } + jint doSize() const throw (std::out_of_range) { return SWIG_VectorSize(self->size()); } From b4b193d7de84a7bab5e45c1f6a16b941a5b44178 Mon Sep 17 00:00:00 2001 From: FUTATSUKI Yasuhito Date: Sat, 24 Jun 2017 22:32:27 +0900 Subject: [PATCH 189/455] Add explicit dependency on header files generated by configure script --- CCache/Makefile.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CCache/Makefile.in b/CCache/Makefile.in index f3b25a5f5..d36e7d0ac 100644 --- a/CCache/Makefile.in +++ b/CCache/Makefile.in @@ -24,7 +24,7 @@ transform = @program_transform_name@ LIBS= @LIBS@ OBJS= ccache.o mdfour.o hash.o execute.o util.o args.o stats.o \ cleanup.o snprintf.o unify.o -HEADERS = ccache.h mdfour.h +HEADERS = ccache.h mdfour.h config.h config_win32.h all: $(PACKAGE_NAME)$(EXEEXT) From a8e948e96de007cb4c7b8f69242dd5cb2310c1bf Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Sat, 24 Jun 2017 22:53:11 +0100 Subject: [PATCH 190/455] Java std::vector std::list: add missing exception handling --- Lib/java/std_list.i | 8 ++++---- Lib/java/std_vector.i | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Lib/java/std_list.i b/Lib/java/std_list.i index 619afbb1d..05c5683fa 100644 --- a/Lib/java/std_list.i +++ b/Lib/java/std_list.i @@ -177,13 +177,13 @@ namespace std { %extend { %fragment("SWIG_ListSize"); - list(jint count) { + list(jint count) throw (std::out_of_range) { if (count < 0) throw std::out_of_range("list count must be positive"); return new std::list(static_cast::size_type>(count)); } - list(jint count, const T &value) { + list(jint count, const T &value) throw (std::out_of_range) { if (count < 0) throw std::out_of_range("list count must be positive"); return new std::list(static_cast::size_type>(count), value); @@ -193,11 +193,11 @@ namespace std { return SWIG_ListSize(self->size()); } - jint doPreviousIndex(const iterator &pos) const { + jint doPreviousIndex(const iterator &pos) const throw (std::out_of_range) { return pos == self->begin() ? -1 : SWIG_ListSize(std::distance(self->begin(), static_cast::const_iterator>(pos))); } - jint doNextIndex(const iterator &pos) const { + jint doNextIndex(const iterator &pos) const throw (std::out_of_range) { return pos == self->end() ? self->size() : SWIG_ListSize(std::distance(self->begin(), static_cast::const_iterator>(pos))); } diff --git a/Lib/java/std_vector.i b/Lib/java/std_vector.i index 2f6f07096..774b6c911 100644 --- a/Lib/java/std_vector.i +++ b/Lib/java/std_vector.i @@ -83,13 +83,13 @@ SWIGINTERN jint SWIG_VectorSize(size_t size) { void clear(); %extend { %fragment("SWIG_VectorSize"); - vector(jint count) { + vector(jint count) throw (std::out_of_range) { if (count < 0) throw std::out_of_range("vector count must be positive"); return new std::vector< CTYPE >(static_cast::size_type>(count)); } - vector(jint count, const CTYPE &value) { + vector(jint count, const CTYPE &value) throw (std::out_of_range) { if (count < 0) throw std::out_of_range("vector count must be positive"); return new std::vector< CTYPE >(static_cast::size_type>(count), value); From c686045f552f3b157b20fe86fc3c4b5611c6becb Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Sat, 24 Jun 2017 23:33:31 +0100 Subject: [PATCH 191/455] More efficient add implementation for Java std::list The default implementation in AbstractSequentialList calls add(size(), e) and size() might be expensive. --- Examples/test-suite/java/li_std_list_runme.java | 8 ++++++++ Examples/test-suite/java/li_std_vector_runme.java | 8 ++++++++ Lib/java/std_list.i | 6 ++++++ 3 files changed, 22 insertions(+) diff --git a/Examples/test-suite/java/li_std_list_runme.java b/Examples/test-suite/java/li_std_list_runme.java index f0e48804b..0af9fbc48 100644 --- a/Examples/test-suite/java/li_std_list_runme.java +++ b/Examples/test-suite/java/li_std_list_runme.java @@ -130,5 +130,13 @@ public class li_std_list_runme { java.util.ArrayList bl2 = new java.util.ArrayList(bv); boolean bbb1 = bv.get(0); Boolean bbb2 = bv.get(0); + + IntList v9 = new IntList(java.util.Arrays.asList(10, 20, 30, 40)); + v9.add(50); + v9.add(60); + v9.add(70); + if (v9.size() != 7) throw new RuntimeException("v9 test (1) failed"); + if (!v9.remove(new Integer(60))) throw new RuntimeException("v9 test (2) failed"); + if (v9.size() != 6) throw new RuntimeException("v9 test (3) failed"); } } diff --git a/Examples/test-suite/java/li_std_vector_runme.java b/Examples/test-suite/java/li_std_vector_runme.java index b63df0210..4d28b30de 100644 --- a/Examples/test-suite/java/li_std_vector_runme.java +++ b/Examples/test-suite/java/li_std_vector_runme.java @@ -131,5 +131,13 @@ public class li_std_vector_runme { java.util.ArrayList bl2 = new java.util.ArrayList(bv); boolean bbb1 = bv.get(0); Boolean bbb2 = bv.get(0); + + IntVector v9 = new IntVector(java.util.Arrays.asList(10, 20, 30, 40)); + v9.add(50); + v9.add(60); + v9.add(70); + if (v9.size() != 7) throw new RuntimeException("v9 test (1) failed"); + if (!v9.remove(new Integer(60))) throw new RuntimeException("v9 test (2) failed"); + if (v9.size() != 6) throw new RuntimeException("v9 test (3) failed"); } } diff --git a/Lib/java/std_list.i b/Lib/java/std_list.i index 05c5683fa..d98fde731 100644 --- a/Lib/java/std_list.i +++ b/Lib/java/std_list.i @@ -14,6 +14,7 @@ SWIGINTERN jint SWIG_ListSize(size_t size) { } } +%javamethodmodifiers std::list::push_back "private"; %javamethodmodifiers std::list::begin "private"; %javamethodmodifiers std::list::insert "private"; %javamethodmodifiers std::list::doSize "private"; @@ -44,6 +45,11 @@ namespace std { return doSize(); } + public boolean add($typemap(jboxtype, T) value) { + push_back(value); + return true; + } + public java.util.ListIterator<$typemap(jboxtype, T)> listIterator(int index) { return new java.util.ListIterator<$typemap(jboxtype, T)>() { private Iterator pos; From ecebbdd0df3748e376c4e160346d9429493b669b Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Sun, 25 Jun 2017 00:10:06 +0100 Subject: [PATCH 192/455] Additional add/remove methods added to Java std::list wrappers Add functions similar to java.util.LinkedList: addFirst addLast removeFirst removeLast --- Examples/test-suite/java/li_std_list_runme.java | 10 ++++++++++ Lib/java/std_list.i | 7 +++++-- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/Examples/test-suite/java/li_std_list_runme.java b/Examples/test-suite/java/li_std_list_runme.java index 0af9fbc48..e0d97b893 100644 --- a/Examples/test-suite/java/li_std_list_runme.java +++ b/Examples/test-suite/java/li_std_list_runme.java @@ -138,5 +138,15 @@ public class li_std_list_runme { if (v9.size() != 7) throw new RuntimeException("v9 test (1) failed"); if (!v9.remove(new Integer(60))) throw new RuntimeException("v9 test (2) failed"); if (v9.size() != 6) throw new RuntimeException("v9 test (3) failed"); + v9.addFirst(-10); + v9.addLast(80); + if (v9.size() != 8) throw new RuntimeException("v9 test (4) failed"); + if (v9.get(0) != -10) throw new RuntimeException("v9 test (5) failed");; + if (v9.get(v9.size()-1) != 80) throw new RuntimeException("v9 test (6) failed");; + v9.removeFirst(); + if (v9.get(0) != 10) throw new RuntimeException("v9 test (7) failed");; + v9.removeLast(); + if (v9.size() != 6) throw new RuntimeException("v9 test (8) failed"); + if (v9.get(v9.size()-1) != 70) throw new RuntimeException("v9 test (9) failed");; } } diff --git a/Lib/java/std_list.i b/Lib/java/std_list.i index d98fde731..86024a903 100644 --- a/Lib/java/std_list.i +++ b/Lib/java/std_list.i @@ -14,7 +14,6 @@ SWIGINTERN jint SWIG_ListSize(size_t size) { } } -%javamethodmodifiers std::list::push_back "private"; %javamethodmodifiers std::list::begin "private"; %javamethodmodifiers std::list::insert "private"; %javamethodmodifiers std::list::doSize "private"; @@ -46,7 +45,7 @@ namespace std { } public boolean add($typemap(jboxtype, T) value) { - push_back(value); + addLast(value); return true; } @@ -173,9 +172,13 @@ namespace std { %rename(remove) erase; iterator erase(iterator pos); size_type max_size() const; + %rename(removeLast) pop_back; void pop_back(); + %rename(removeFirst) pop_front; void pop_front(); + %rename(addLast) push_back; void push_back(const T &value); + %rename(addFirst) push_front; void push_front(const T &value); iterator begin(); iterator end(); From 74fa7d00e27abeeedd86f1292456eca5fbb04f86 Mon Sep 17 00:00:00 2001 From: Nihal Date: Sat, 24 Jun 2017 13:43:55 +0530 Subject: [PATCH 193/455] Fix indentation in PHP7 and PHP5 variables example --- Examples/php/variables/runme.php | 4 ++-- Examples/php5/variables/runme.php | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Examples/php/variables/runme.php b/Examples/php/variables/runme.php index bbfeb610b..14f27f389 100644 --- a/Examples/php/variables/runme.php +++ b/Examples/php/variables/runme.php @@ -26,10 +26,10 @@ echo "pt = ".pt_get(), point_print(pt_get()) , "\n"; /* Try to set the values of some global variables */ -$a = "42.14"; + $a = "42.14"; ivar_set($a); -echo "a = $a\n"; + echo "a = $a\n"; svar_set(-31000); lvar_set(65537); uivar_set(123456); diff --git a/Examples/php5/variables/runme.php b/Examples/php5/variables/runme.php index bbfeb610b..14f27f389 100644 --- a/Examples/php5/variables/runme.php +++ b/Examples/php5/variables/runme.php @@ -26,10 +26,10 @@ echo "pt = ".pt_get(), point_print(pt_get()) , "\n"; /* Try to set the values of some global variables */ -$a = "42.14"; + $a = "42.14"; ivar_set($a); -echo "a = $a\n"; + echo "a = $a\n"; svar_set(-31000); lvar_set(65537); uivar_set(123456); From 6daed2cea10d51c41e363d734921f944e75028b1 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Mon, 26 Jun 2017 12:28:02 +0100 Subject: [PATCH 194/455] Remove Java std::list::assign This doesn't exist in equivalent Java containers. If we put it back, the full set of overloaded assign wrappers ought to be added. --- Lib/java/std_list.i | 1 - 1 file changed, 1 deletion(-) diff --git a/Lib/java/std_list.i b/Lib/java/std_list.i index 86024a903..a634de382 100644 --- a/Lib/java/std_list.i +++ b/Lib/java/std_list.i @@ -165,7 +165,6 @@ namespace std { list(); list(const list &other); ~list(); - void assign(size_type n, const T &value); %rename(isEmpty) empty; bool empty() const; void clear(); From 3af40e74231b5c7f79f00b7e01e9f906dc60e2ae Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Mon, 26 Jun 2017 12:46:22 +0100 Subject: [PATCH 195/455] Handle length_error exceptions in Java std::vector::reserve --- Lib/java/std_vector.i | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib/java/std_vector.i b/Lib/java/std_vector.i index 774b6c911..d22896390 100644 --- a/Lib/java/std_vector.i +++ b/Lib/java/std_vector.i @@ -77,7 +77,7 @@ SWIGINTERN jint SWIG_VectorSize(size_t size) { vector(); vector(const vector &other); size_type capacity() const; - void reserve(size_type n); + void reserve(size_type n) throw (std::length_error); %rename(isEmpty) empty; bool empty() const; void clear(); From 90d2ba884c92ce799c8e8c7b4684e778f7b77ec2 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Mon, 26 Jun 2017 13:42:19 +0100 Subject: [PATCH 196/455] Java std::list std::vector - test addAll and subList --- Examples/test-suite/java/li_std_list_runme.java | 10 ++++++++++ Examples/test-suite/java/li_std_vector_runme.java | 10 ++++++++++ 2 files changed, 20 insertions(+) diff --git a/Examples/test-suite/java/li_std_list_runme.java b/Examples/test-suite/java/li_std_list_runme.java index e0d97b893..ea2227faf 100644 --- a/Examples/test-suite/java/li_std_list_runme.java +++ b/Examples/test-suite/java/li_std_list_runme.java @@ -148,5 +148,15 @@ public class li_std_list_runme { v9.removeLast(); if (v9.size() != 6) throw new RuntimeException("v9 test (8) failed"); if (v9.get(v9.size()-1) != 70) throw new RuntimeException("v9 test (9) failed");; + + IntList v10 = new IntList(java.util.Arrays.asList(10, 20, 30, 40, 50)); + v10.subList(1, 4).clear(); // Recommended way to call protected method removeRange(1,3) + if (v10.size() != 2) throw new RuntimeException("v10 test (1) failed"); + if (v10.get(0) != 10) throw new RuntimeException("v10 test (2) failed"); + if (v10.get(1) != 50) throw new RuntimeException("v10 test (3) failed"); + v10.addAll(1, java.util.Arrays.asList(22, 33)); + if (v10.size() != 4) throw new RuntimeException("v10 test (4) failed"); + if (v10.get(1) != 22) throw new RuntimeException("v10 test (5) failed"); + if (v10.get(2) != 33) throw new RuntimeException("v10 test (6) failed"); } } diff --git a/Examples/test-suite/java/li_std_vector_runme.java b/Examples/test-suite/java/li_std_vector_runme.java index 4d28b30de..5371a2ba2 100644 --- a/Examples/test-suite/java/li_std_vector_runme.java +++ b/Examples/test-suite/java/li_std_vector_runme.java @@ -139,5 +139,15 @@ public class li_std_vector_runme { if (v9.size() != 7) throw new RuntimeException("v9 test (1) failed"); if (!v9.remove(new Integer(60))) throw new RuntimeException("v9 test (2) failed"); if (v9.size() != 6) throw new RuntimeException("v9 test (3) failed"); + + IntVector v10 = new IntVector(java.util.Arrays.asList(10, 20, 30, 40, 50)); + v10.subList(1, 4).clear(); // Recommended way to call protected method removeRange(1,3) + if (v10.size() != 2) throw new RuntimeException("v10 test (1) failed"); + if (v10.get(0) != 10) throw new RuntimeException("v10 test (2) failed"); + if (v10.get(1) != 50) throw new RuntimeException("v10 test (3) failed"); + v10.addAll(1, java.util.Arrays.asList(22, 33)); + if (v10.size() != 4) throw new RuntimeException("v10 test (4) failed"); + if (v10.get(1) != 22) throw new RuntimeException("v10 test (5) failed"); + if (v10.get(2) != 33) throw new RuntimeException("v10 test (6) failed"); } } From d92faa7f7fc94067155ecab4d2ce4610ddc3fa0f Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Mon, 26 Jun 2017 13:43:57 +0100 Subject: [PATCH 197/455] Remove Java std::list::max_size Not in any Java equivalent containers nor std::vector wrapper. --- Lib/java/std_list.i | 1 - 1 file changed, 1 deletion(-) diff --git a/Lib/java/std_list.i b/Lib/java/std_list.i index a634de382..d937bcfe3 100644 --- a/Lib/java/std_list.i +++ b/Lib/java/std_list.i @@ -170,7 +170,6 @@ namespace std { void clear(); %rename(remove) erase; iterator erase(iterator pos); - size_type max_size() const; %rename(removeLast) pop_back; void pop_back(); %rename(removeFirst) pop_front; From d04eb8874251f029a50699736dc2889f777c526e Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Mon, 26 Jun 2017 13:53:49 +0100 Subject: [PATCH 198/455] Consistent destructor declarations --- Lib/java/std_list.i | 1 - 1 file changed, 1 deletion(-) diff --git a/Lib/java/std_list.i b/Lib/java/std_list.i index d937bcfe3..766fb184c 100644 --- a/Lib/java/std_list.i +++ b/Lib/java/std_list.i @@ -164,7 +164,6 @@ namespace std { list(); list(const list &other); - ~list(); %rename(isEmpty) empty; bool empty() const; void clear(); From f4aa8b33218beab0ea4022a1aa77cac4e73b9c16 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Mon, 26 Jun 2017 15:28:43 +0100 Subject: [PATCH 199/455] Add missing typedefs to Java std::vector --- Lib/java/std_vector.i | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Lib/java/std_vector.i b/Lib/java/std_vector.i index d22896390..c7fd73b37 100644 --- a/Lib/java/std_vector.i +++ b/Lib/java/std_vector.i @@ -72,8 +72,13 @@ SWIGINTERN jint SWIG_VectorSize(size_t size) { public: typedef size_t size_type; + typedef ptrdiff_t difference_type; typedef CTYPE value_type; + typedef CTYPE &reference; typedef CREF_TYPE const_reference; + typedef CTYPE *pointer; + typedef CTYPE const *const_pointer; + vector(); vector(const vector &other); size_type capacity() const; From 717ef91b902323e9e6aefbade4b7c967dff140f4 Mon Sep 17 00:00:00 2001 From: Nihal Date: Mon, 26 Jun 2017 11:21:52 +0530 Subject: [PATCH 200/455] Remove -noproxy support in the Examples of PHP7 --- Examples/php/enum/Makefile | 2 +- Examples/php/enum/runme.php | 20 ++++++++++---------- Examples/php/value/Makefile | 2 +- Examples/php/value/runme.php | 18 +++++++++--------- 4 files changed, 21 insertions(+), 21 deletions(-) diff --git a/Examples/php/enum/Makefile b/Examples/php/enum/Makefile index 4483f781e..063a0645f 100644 --- a/Examples/php/enum/Makefile +++ b/Examples/php/enum/Makefile @@ -5,7 +5,7 @@ CXXSRCS = example.cxx TARGET = example INTERFACE = example.i LIBS = -SWIGOPT = -noproxy +SWIGOPT = check: build $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' php_run diff --git a/Examples/php/enum/runme.php b/Examples/php/enum/runme.php index 55b0bc4c3..813476645 100644 --- a/Examples/php/enum/runme.php +++ b/Examples/php/enum/runme.php @@ -11,22 +11,22 @@ print " BLUE =" . BLUE; print " GREEN =" . GREEN; print "\n*** Foo::speed ***"; -print " Foo_IMPULSE =" . Foo_IMPULSE; -print " Foo_WARP =" . Foo_WARP; -print " Foo_LUDICROUS =" . Foo_LUDICROUS; +print " Foo::IMPULSE =" . Foo::IMPULSE; +print " Foo::WARP =" . Foo::WARP; +print " Foo::LUDICROUS =" . Foo::LUDICROUS; print "\nTesting use of enums with functions\n"; -enum_test(RED, Foo_IMPULSE); -enum_test(BLUE, Foo_WARP); -enum_test(GREEN, Foo_LUDICROUS); +enum_test(RED, Foo::IMPULSE); +enum_test(BLUE, Foo::WARP); +enum_test(GREEN, Foo::LUDICROUS); enum_test(1234,5678); print "\nTesting use of enum with class method\n"; -$f = new_Foo(); +$f = new Foo(); -Foo_enum_test($f,Foo_IMPULSE); -Foo_enum_test($f,Foo_WARP); -Foo_enum_test($f,Foo_LUDICROUS); +$f->enum_test(Foo::IMPULSE); +$f->enum_test(Foo::WARP); +$f->enum_test(Foo::LUDICROUS); ?> diff --git a/Examples/php/value/Makefile b/Examples/php/value/Makefile index 28fc3a127..47e5ed9f9 100644 --- a/Examples/php/value/Makefile +++ b/Examples/php/value/Makefile @@ -5,7 +5,7 @@ SRCS = example.c TARGET = example INTERFACE = example.i LIBS = -SWIGOPT = -noproxy +SWIGOPT = check: build $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' php_run diff --git a/Examples/php/value/runme.php b/Examples/php/value/runme.php index 49115376c..569c87cf5 100644 --- a/Examples/php/value/runme.php +++ b/Examples/php/value/runme.php @@ -3,15 +3,15 @@ require "example.php"; - $v = new_vector(); - vector_x_set($v,1.0); - vector_y_set($v,2.0); - vector_z_set($v,3.0); + $v = new Vector(); + $v->x = 1.0; + $v->y = 2.0; + $v->z = 3.0; - $w = new_vector(); - vector_x_set($w,10.0); - vector_y_set($w,11.0); - vector_z_set($w,12.0); + $w = new Vector(); + $w->x = 10.0; + $w->y = 11.0; + $w->z = 12.0; echo "I just created the following vector\n"; vector_print($v); @@ -25,7 +25,7 @@ echo "\nNow I'm going to add the vectors together\n"; - $r = new_vector(); + $r = new Vector(); vector_add($v, $w, $r); vector_print($r); From 52f9ef7bfce7e42fa6764382da6bf4e24fdf4c72 Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Tue, 27 Jun 2017 16:37:18 +1200 Subject: [PATCH 201/455] Add entry for previous commit --- CHANGES.current | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGES.current b/CHANGES.current index b07e3eb7b..7373f7c97 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.0.0 (in progress) =========================== +2017-06-27: nihaln + [PHP] Update the enum and value examples to use the OO wrappers + rather than the flat functions produced with -noproxy. There's + not been a good reason to use -noproxy for since PHP5 OO wrapping + was fixed back in 2005. + 2017-06-23: m7thon [Python] fix and improve default argument handling: From 251d25346dada6fe14cc0dd0aaa45e8fa653ded0 Mon Sep 17 00:00:00 2001 From: Nihal Date: Tue, 27 Jun 2017 10:37:07 +0530 Subject: [PATCH 202/455] Fix OUTPUT Typemap not having return statement bug in PHP wrapper. --- CHANGES.current | 4 ++++ Source/Modules/php.cxx | 2 +- Source/Modules/php5.cxx | 2 +- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/CHANGES.current b/CHANGES.current index 7373f7c97..9662acb28 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.0.0 (in progress) =========================== +2017-06-27: nihaln + [PHP] Update the OUTPUT Typemap to add return statement to the + PHP Wrapper. + 2017-06-27: nihaln [PHP] Update the enum and value examples to use the OO wrappers rather than the flat functions produced with -noproxy. There's diff --git a/Source/Modules/php.cxx b/Source/Modules/php.cxx index 0ab792863..061dc0c22 100644 --- a/Source/Modules/php.cxx +++ b/Source/Modules/php.cxx @@ -1841,7 +1841,7 @@ public: Delete(wrapobj); } } else { - if (non_void_return) { + if (non_void_return || hasargout) { Printf(output, "\t\treturn %s;\n", invoke); } else if (Cmp(invoke, "$r") != 0) { Printf(output, "\t\t%s;\n", invoke); diff --git a/Source/Modules/php5.cxx b/Source/Modules/php5.cxx index bf5664c3c..2fa76493e 100644 --- a/Source/Modules/php5.cxx +++ b/Source/Modules/php5.cxx @@ -1827,7 +1827,7 @@ public: Delete(wrapobj); } } else { - if (non_void_return) { + if (non_void_return || hasargout) { Printf(output, "\t\treturn %s;\n", invoke); } else if (Cmp(invoke, "$r") != 0) { Printf(output, "\t\t%s;\n", invoke); From fccf5c29b481bc55766daebc0b79a2c0e2b1ff42 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Thu, 29 Jun 2017 15:34:05 +0100 Subject: [PATCH 203/455] Minor correction in C# std::list doNextIndex --- Lib/java/std_list.i | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib/java/std_list.i b/Lib/java/std_list.i index 766fb184c..e511ea006 100644 --- a/Lib/java/std_list.i +++ b/Lib/java/std_list.i @@ -204,7 +204,7 @@ namespace std { } jint doNextIndex(const iterator &pos) const throw (std::out_of_range) { - return pos == self->end() ? self->size() : SWIG_ListSize(std::distance(self->begin(), static_cast::const_iterator>(pos))); + return pos == self->end() ? SWIG_ListSize(self->size()) : SWIG_ListSize(std::distance(self->begin(), static_cast::const_iterator>(pos))); } bool doHasNext(const iterator &pos) const { From 44cd658a53e457c363a72b11aba6ec52677f4f82 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Thu, 29 Jun 2017 19:32:34 +0100 Subject: [PATCH 204/455] Add in missing Java std::list listIterator index range checking --- .../test-suite/java/li_std_list_runme.java | 18 ++++++++++++++++++ .../test-suite/java/li_std_vector_runme.java | 18 ++++++++++++++++++ Lib/java/std_list.i | 2 ++ 3 files changed, 38 insertions(+) diff --git a/Examples/test-suite/java/li_std_list_runme.java b/Examples/test-suite/java/li_std_list_runme.java index ea2227faf..e45b8968b 100644 --- a/Examples/test-suite/java/li_std_list_runme.java +++ b/Examples/test-suite/java/li_std_list_runme.java @@ -158,5 +158,23 @@ public class li_std_list_runme { if (v10.size() != 4) throw new RuntimeException("v10 test (4) failed"); if (v10.get(1) != 22) throw new RuntimeException("v10 test (5) failed"); if (v10.get(2) != 33) throw new RuntimeException("v10 test (6) failed"); + + v10.add(v10.size(), 55); + if (v10.size() != 5) throw new RuntimeException("v10 test (7) failed"); + if (v10.get(4) != 55) throw new RuntimeException("v10 test (8) failed"); + + IntList v11 = new IntList(java.util.Arrays.asList(11, 22, 33, 44)); + v11.listIterator(0); + v11.listIterator(v11.size()); + try { + v11.listIterator(v11.size() + 1); + throw new RuntimeException("v11 test (1) failed"); + } catch (IndexOutOfBoundsException e) { + } + try { + v11.listIterator(-1); + throw new RuntimeException("v11 test (2) failed"); + } catch (IndexOutOfBoundsException e) { + } } } diff --git a/Examples/test-suite/java/li_std_vector_runme.java b/Examples/test-suite/java/li_std_vector_runme.java index 5371a2ba2..d23bbe7cd 100644 --- a/Examples/test-suite/java/li_std_vector_runme.java +++ b/Examples/test-suite/java/li_std_vector_runme.java @@ -149,5 +149,23 @@ public class li_std_vector_runme { if (v10.size() != 4) throw new RuntimeException("v10 test (4) failed"); if (v10.get(1) != 22) throw new RuntimeException("v10 test (5) failed"); if (v10.get(2) != 33) throw new RuntimeException("v10 test (6) failed"); + + v10.add(v10.size(), 55); + if (v10.size() != 5) throw new RuntimeException("v10 test (7) failed"); + if (v10.get(4) != 55) throw new RuntimeException("v10 test (8) failed"); + + IntVector v11 = new IntVector(java.util.Arrays.asList(11, 22, 33, 44)); + v11.listIterator(0); + v11.listIterator(v11.size()); + try { + v11.listIterator(v11.size() + 1); + throw new RuntimeException("v11 test (1) failed"); + } catch (IndexOutOfBoundsException e) { + } + try { + v11.listIterator(-1); + throw new RuntimeException("v11 test (2) failed"); + } catch (IndexOutOfBoundsException e) { + } } } diff --git a/Lib/java/std_list.i b/Lib/java/std_list.i index e511ea006..af6ac075f 100644 --- a/Lib/java/std_list.i +++ b/Lib/java/std_list.i @@ -55,6 +55,8 @@ namespace std { private Iterator last; private java.util.ListIterator<$typemap(jboxtype, T)> init(int index) { + if (index < 0 || index > $javaclassname.this.size()) + throw new IndexOutOfBoundsException("Index: " + index); pos = $javaclassname.this.begin(); pos = pos.advance_unchecked(index); return this; From 0b390a5473eb36b931046c19c677c3a3545920d6 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Thu, 29 Jun 2017 19:59:19 +0100 Subject: [PATCH 205/455] Fix Java container tests for change in vector constructor declaration --- Examples/test-suite/constructor_copy.i | 8 +++++++- Examples/test-suite/ignore_template_constructor.i | 8 +++++++- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/Examples/test-suite/constructor_copy.i b/Examples/test-suite/constructor_copy.i index 7dcd05e8b..222c12f32 100644 --- a/Examples/test-suite/constructor_copy.i +++ b/Examples/test-suite/constructor_copy.i @@ -73,12 +73,18 @@ public: %include "std_vector.i" -#if defined(SWIGJAVA) || defined(SWIGCSHARP) || defined(SWIGPYTHON) || defined(SWIGR) || defined(SWIGOCTAVE) || defined(SWIGRUBY) || defined(SWIGJAVASCRIPT) || defined(SWIGSCILAB) +#if defined(SWIGCSHARP) || defined(SWIGPYTHON) || defined(SWIGR) || defined(SWIGOCTAVE) || defined(SWIGRUBY) || defined(SWIGJAVASCRIPT) || defined(SWIGSCILAB) #define SWIG_GOOD_VECTOR %ignore std::vector::vector(size_type); %ignore std::vector::resize(size_type); #endif +#if defined(SWIGJAVA) +#define SWIG_GOOD_VECTOR +%ignore std::vector::vector(jint); +%ignore std::vector::resize(jint); +#endif + #if defined(SWIGTCL) || defined(SWIGPERL) #define SWIG_GOOD_VECTOR /* here, for languages with bad declaration */ diff --git a/Examples/test-suite/ignore_template_constructor.i b/Examples/test-suite/ignore_template_constructor.i index 31a5505fb..bdffbec3e 100644 --- a/Examples/test-suite/ignore_template_constructor.i +++ b/Examples/test-suite/ignore_template_constructor.i @@ -1,12 +1,18 @@ %module ignore_template_constructor %include std_vector.i -#if defined(SWIGJAVA) || defined(SWIGCSHARP) || defined(SWIGPYTHON) || defined(SWIGPERL) || defined(SWIGRUBY) +#if defined(SWIGCSHARP) || defined(SWIGPYTHON) || defined(SWIGPERL) || defined(SWIGRUBY) #define SWIG_GOOD_VECTOR %ignore std::vector::vector(size_type); %ignore std::vector::resize(size_type); #endif +#if defined(SWIGJAVA) +#define SWIG_GOOD_VECTOR +%ignore std::vector::vector(jint); +%ignore std::vector::resize(jint); +#endif + #if defined(SWIGTCL) || defined(SWIGPERL) #define SWIG_GOOD_VECTOR /* here, for languages with bad declaration */ From abe53e39a9f3602a65a9b6b5dea0c74a12d7e1c9 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Thu, 29 Jun 2017 20:19:59 +0100 Subject: [PATCH 206/455] Java std::vector minor improvement --- Lib/java/std_vector.i | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Lib/java/std_vector.i b/Lib/java/std_vector.i index c7fd73b37..f35376965 100644 --- a/Lib/java/std_vector.i +++ b/Lib/java/std_vector.i @@ -109,7 +109,7 @@ SWIGINTERN jint SWIG_VectorSize(size_t size) { } void doAdd(jint index, const value_type& value) throw (std::out_of_range) { - const jint size = SWIG_VectorSize(self->size()); + const jint size = static_cast::size_type>(self->size()); if (0 <= index && index <= size) { self->insert(self->begin() + index, value); } else { @@ -118,7 +118,7 @@ SWIGINTERN jint SWIG_VectorSize(size_t size) { } value_type doRemove(jint index) throw (std::out_of_range) { - const jint size = SWIG_VectorSize(self->size()); + const jint size = static_cast::size_type>(self->size()); if (0 <= index && index < size) { CTYPE const old_value = (*self)[index]; self->erase(self->begin() + index); @@ -129,7 +129,7 @@ SWIGINTERN jint SWIG_VectorSize(size_t size) { } CREF_TYPE doGet(jint index) throw (std::out_of_range) { - const jint size = SWIG_VectorSize(self->size()); + const jint size = static_cast::size_type>(self->size()); if (index >= 0 && index < size) return (*self)[index]; else @@ -137,7 +137,7 @@ SWIGINTERN jint SWIG_VectorSize(size_t size) { } value_type doSet(jint index, const value_type& value) throw (std::out_of_range) { - const jint size = SWIG_VectorSize(self->size()); + const jint size = static_cast::size_type>(self->size()); if (index >= 0 && index < size) { CTYPE const old_value = (*self)[index]; (*self)[index] = value; @@ -148,7 +148,7 @@ SWIGINTERN jint SWIG_VectorSize(size_t size) { } void doRemoveRange(jint fromIndex, jint toIndex) throw (std::out_of_range) { - const jint size = SWIG_VectorSize(self->size()); + const jint size = static_cast::size_type>(self->size()); if (0 <= fromIndex && fromIndex <= toIndex && toIndex <= size) { self->erase(self->begin() + fromIndex, self->begin() + toIndex); } else { From 74345c92e47938a75817eff5ba48dc9d3ce2a281 Mon Sep 17 00:00:00 2001 From: Mike Romberg Date: Sat, 1 Jul 2017 17:38:48 -0600 Subject: [PATCH 207/455] supress clang warning about vtable ptr overwrite. Use calloc to zero memory just once. Document memory leak. --- Lib/python/pystdcommon.swg | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Lib/python/pystdcommon.swg b/Lib/python/pystdcommon.swg index 93ee34bc7..45f27375e 100644 --- a/Lib/python/pystdcommon.swg +++ b/Lib/python/pystdcommon.swg @@ -135,12 +135,11 @@ namespace swig { } } else { // Uninitialized return value, no Type() constructor required. - static Type *v_def = (Type*) malloc(sizeof(Type)); + static Type *v_def = (Type*) calloc(1, sizeof(Type)); // memory leak? if (!PyErr_Occurred()) { %type_error(swig::type_name()); } if (throw_error) throw std::invalid_argument("bad type"); - memset(v_def,0,sizeof(Type)); return *v_def; } } From 6c0885ff677139a0c3c9719dd9fae7eac4f0167f Mon Sep 17 00:00:00 2001 From: Mike Romberg Date: Sat, 1 Jul 2017 17:58:59 -0600 Subject: [PATCH 208/455] Use the Type() ctor and avoid: - clang warning about memset overwrite of vtable - memory leak - Undefined behavior in Type copy/move operations and dtor. --- Lib/python/pystdcommon.swg | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/Lib/python/pystdcommon.swg b/Lib/python/pystdcommon.swg index 45f27375e..70746a58e 100644 --- a/Lib/python/pystdcommon.swg +++ b/Lib/python/pystdcommon.swg @@ -134,13 +134,12 @@ namespace swig { return *v; } } else { - // Uninitialized return value, no Type() constructor required. - static Type *v_def = (Type*) calloc(1, sizeof(Type)); // memory leak? + static Type v_def; if (!PyErr_Occurred()) { %type_error(swig::type_name()); } if (throw_error) throw std::invalid_argument("bad type"); - return *v_def; + return v_def; } } }; From bfaafde020dc7e38d3a147b0fdbd79adaf68df96 Mon Sep 17 00:00:00 2001 From: Mike Romberg Date: Mon, 3 Jul 2017 12:25:04 -0600 Subject: [PATCH 209/455] traits_as::as() ignores throw_error and always throws. --- Lib/python/pystdcommon.swg | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/Lib/python/pystdcommon.swg b/Lib/python/pystdcommon.swg index 70746a58e..c8ce2c8e6 100644 --- a/Lib/python/pystdcommon.swg +++ b/Lib/python/pystdcommon.swg @@ -122,7 +122,7 @@ namespace swig { template struct traits_as { - static Type as(PyObject *obj, bool throw_error) { + static Type as(PyObject *obj, bool /* throw_error */) { Type *v = 0; int res = (obj ? traits_asptr::asptr(obj, &v) : SWIG_ERROR); if (SWIG_IsOK(res) && v) { @@ -134,12 +134,10 @@ namespace swig { return *v; } } else { - static Type v_def; if (!PyErr_Occurred()) { %type_error(swig::type_name()); } - if (throw_error) throw std::invalid_argument("bad type"); - return v_def; + throw std::invalid_argument("bad type"); } } }; From b229d92f9bfbefb6d11c3b92d590ead1ce93dc4a Mon Sep 17 00:00:00 2001 From: Mike Romberg Date: Mon, 3 Jul 2017 12:49:30 -0600 Subject: [PATCH 210/455] remove bool from as() (it now always throws). catch std::invalid_argument (what is expected) instread of std::exception. --- Lib/python/pycontainer.swg | 4 ++-- Lib/python/pystdcommon.swg | 15 +++++++-------- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/Lib/python/pycontainer.swg b/Lib/python/pycontainer.swg index 1687aca42..36557d75e 100644 --- a/Lib/python/pycontainer.swg +++ b/Lib/python/pycontainer.swg @@ -434,8 +434,8 @@ namespace swig { swig::SwigVar_PyObject item = PySequence_GetItem(_seq, _index); try { - return swig::as(item, true); - } catch (std::exception& e) { + return swig::as(item); + } catch (const std::invalid_argument& e) { char msg[1024]; sprintf(msg, "in sequence element %d ", (int)_index); if (!PyErr_Occurred()) { diff --git a/Lib/python/pystdcommon.swg b/Lib/python/pystdcommon.swg index c8ce2c8e6..0242e4d35 100644 --- a/Lib/python/pystdcommon.swg +++ b/Lib/python/pystdcommon.swg @@ -107,14 +107,14 @@ namespace swig { template struct traits_as { - static Type as(PyObject *obj, bool throw_error) { + static Type as(PyObject *obj) { Type v; int res = asval(obj, &v); if (!obj || !SWIG_IsOK(res)) { if (!PyErr_Occurred()) { ::%type_error(swig::type_name()); } - if (throw_error) throw std::invalid_argument("bad type"); + throw std::invalid_argument("bad type"); } return v; } @@ -122,7 +122,7 @@ namespace swig { template struct traits_as { - static Type as(PyObject *obj, bool /* throw_error */) { + static Type as(PyObject *obj) { Type *v = 0; int res = (obj ? traits_asptr::asptr(obj, &v) : SWIG_ERROR); if (SWIG_IsOK(res) && v) { @@ -144,7 +144,7 @@ namespace swig { template struct traits_as { - static Type* as(PyObject *obj, bool throw_error) { + static Type* as(PyObject *obj) { Type *v = 0; int res = (obj ? traits_asptr::asptr(obj, &v) : SWIG_ERROR); if (SWIG_IsOK(res)) { @@ -153,15 +153,14 @@ namespace swig { if (!PyErr_Occurred()) { %type_error(swig::type_name()); } - if (throw_error) throw std::invalid_argument("bad type"); - return 0; + throw std::invalid_argument("bad type"); } } }; template - inline Type as(PyObject *obj, bool te = false) { - return traits_as::category>::as(obj, te); + inline Type as(PyObject *obj) { + return traits_as::category>::as(obj); } template From dd26e8a01423e9e6c7e3660558df34f22b4a0506 Mon Sep 17 00:00:00 2001 From: Mike Romberg Date: Mon, 3 Jul 2017 15:35:24 -0600 Subject: [PATCH 211/455] as() now always throws and never creates an invalid object with memset() --- Lib/ruby/rubycontainer.swg | 12 ++++++------ Lib/ruby/rubystdcommon.swg | 21 ++++++++------------- 2 files changed, 14 insertions(+), 19 deletions(-) diff --git a/Lib/ruby/rubycontainer.swg b/Lib/ruby/rubycontainer.swg index 4f1c6f55e..4d0163f51 100644 --- a/Lib/ruby/rubycontainer.swg +++ b/Lib/ruby/rubycontainer.swg @@ -183,8 +183,8 @@ namespace swig { VALUE item = rb_ary_entry(_seq, _index ); try { - return swig::as(item, true); - } catch (std::exception& e) { + return swig::as(item); + } catch (const std::invalid_argument& e) { char msg[1024]; sprintf(msg, "in sequence element %d ", _index); VALUE lastErr = rb_gv_get("$!"); @@ -926,7 +926,7 @@ namespace swig VALUE elem = argv[0]; int idx = 0; try { - Sequence::value_type val = swig::as( elem, true ); + Sequence::value_type val = swig::as( elem ); if ( i >= len ) { $self->resize(i-1, val); return $self; @@ -943,7 +943,7 @@ namespace swig } } - catch( std::invalid_argument ) + catch( const std::invalid_argument & ) { rb_raise( rb_eArgError, "%s", Ruby_Format_TypeError( "", @@ -967,10 +967,10 @@ namespace swig Sequence::iterator start = $self->begin(); VALUE elem = argv[idx]; try { - Sequence::value_type val = swig::as( elem, true ); + Sequence::value_type val = swig::as( elem ); $self->insert( start, val ); } - catch( std::invalid_argument ) + catch( const std::invalid_argument & ) { rb_raise( rb_eArgError, "%s", Ruby_Format_TypeError( "", diff --git a/Lib/ruby/rubystdcommon.swg b/Lib/ruby/rubystdcommon.swg index c34dacefb..99dd7f81e 100644 --- a/Lib/ruby/rubystdcommon.swg +++ b/Lib/ruby/rubystdcommon.swg @@ -115,15 +115,15 @@ namespace swig { template struct traits_as { - static Type as(VALUE obj, bool throw_error) { + static Type as(VALUE obj) { Type v; int res = asval(obj, &v); if (!SWIG_IsOK(res)) { - if (throw_error) throw std::invalid_argument("bad type"); VALUE lastErr = rb_gv_get("$!"); if (lastErr == Qnil) { %type_error(swig::type_name()); } + throw std::invalid_argument("bad type"); } return v; } @@ -131,7 +131,7 @@ namespace swig { template struct traits_as { - static Type as(VALUE obj, bool throw_error) { + static Type as(VALUE obj) { Type *v = 0; int res = traits_asptr::asptr(obj, &v); if (SWIG_IsOK(res) && v) { @@ -143,40 +143,35 @@ namespace swig { return *v; } } else { - // Uninitialized return value, no Type() constructor required. - if (throw_error) throw std::invalid_argument("bad type"); VALUE lastErr = rb_gv_get("$!"); if (lastErr == Qnil) { %type_error(swig::type_name()); } - static Type *v_def = (Type*) malloc(sizeof(Type)); - memset(v_def,0,sizeof(Type)); - return *v_def; + throw std::invalid_argument("bad type"); } } }; template struct traits_as { - static Type* as(VALUE obj, bool throw_error) { + static Type* as(VALUE obj) { Type *v = 0; int res = traits_asptr::asptr(obj, &v); if (SWIG_IsOK(res)) { return v; } else { - if (throw_error) throw std::invalid_argument("bad type"); VALUE lastErr = rb_gv_get("$!"); if (lastErr == Qnil) { %type_error(swig::type_name()); } - return 0; + throw std::invalid_argument("bad type"); } } }; template - inline Type as(VALUE obj, bool te = false) { - return traits_as< Type, typename traits< Type >::category >::as(obj, te); + inline Type as(VALUE obj) { + return traits_as< Type, typename traits< Type >::category >::as(obj); } template From a67eff0ae908a81dfea913d51265833f039abba5 Mon Sep 17 00:00:00 2001 From: Mike Romberg Date: Mon, 3 Jul 2017 20:55:40 -0600 Subject: [PATCH 212/455] remove bool from shared_ptr as well. --- Lib/ruby/std_shared_ptr.i | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Lib/ruby/std_shared_ptr.i b/Lib/ruby/std_shared_ptr.i index f2b05ef36..9742230cc 100644 --- a/Lib/ruby/std_shared_ptr.i +++ b/Lib/ruby/std_shared_ptr.i @@ -80,35 +80,35 @@ namespace swig { template struct traits_as, pointer_category> { - static std::shared_ptr as(VALUE obj, bool throw_error) { + static std::shared_ptr as(VALUE obj) { std::shared_ptr ret; std::shared_ptr *v = &ret; int res = traits_asptr >::asptr(obj, &v); if (SWIG_IsOK(res)) { return ret; } else { - if (throw_error) throw std::invalid_argument("bad type"); + VALUE lastErr = rb_gv_get("$!"); if (lastErr == Qnil) SWIG_Error(SWIG_TypeError, swig::type_name >()); - return std::shared_ptr(); + throw std::invalid_argument("bad type"); } } }; template struct traits_as *, pointer_category> { - static std::shared_ptr * as(VALUE obj, bool throw_error) { + static std::shared_ptr * as(VALUE obj) { std::shared_ptr *p = 0; int res = traits_asptr >::asptr(obj, &p); if (SWIG_IsOK(res)) { return p; } else { - if (throw_error) throw std::invalid_argument("bad type"); + VALUE lastErr = rb_gv_get("$!"); if (lastErr == Qnil) SWIG_Error(SWIG_TypeError, swig::type_name *>()); - return 0; + throw std::invalid_argument("bad type"); } } }; From 7be6c10d4ab474b7ba952fbf0490cfec10e8519c Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Fri, 7 Jul 2017 19:35:44 +0100 Subject: [PATCH 213/455] Fix display of documented template types when using the autodoc feature for Python. --- CHANGES.current | 17 +++++++++++++++++ Examples/test-suite/autodoc.i | 9 ++++++++- Examples/test-suite/python/autodoc_runme.py | 6 ++++++ Source/Modules/python.cxx | 8 ++++---- 4 files changed, 35 insertions(+), 5 deletions(-) diff --git a/CHANGES.current b/CHANGES.current index 9662acb28..0232208b7 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.0.0 (in progress) =========================== +2017-07-07: wsfulton + [Python] Fix display of documented template types when using the autodoc + feature. For example when wrapping: + + %feature("autodoc"); + template struct T {}; + %template(TInteger) T; + + the generated documentation contains: + """Proxy of C++ T< int > class.""" + instead of: + """Proxy of C++ T<(int)> class.""" + and + """__init__(TInteger self) -> TInteger""" + instead of + """__init__(T<(int)> self) -> TInteger""" + 2017-06-27: nihaln [PHP] Update the OUTPUT Typemap to add return statement to the PHP Wrapper. diff --git a/Examples/test-suite/autodoc.i b/Examples/test-suite/autodoc.i index a2d9f5b4e..97c05d791 100644 --- a/Examples/test-suite/autodoc.i +++ b/Examples/test-suite/autodoc.i @@ -133,6 +133,14 @@ typedef int Integer; void banana(S *a, const struct tagS *b, int c, Integer d) {} %} +// Check docs for a template type +%inline %{ +template struct T { + T inout(T t) { return t; } +}; +%} +%template(TInteger) T; + %inline %{ #ifdef SWIGPYTHON_BUILTIN bool is_python_builtin() { return true; } @@ -140,4 +148,3 @@ bool is_python_builtin() { return true; } bool is_python_builtin() { return false; } #endif %} - diff --git a/Examples/test-suite/python/autodoc_runme.py b/Examples/test-suite/python/autodoc_runme.py index af04c8c0e..bf2fa621d 100644 --- a/Examples/test-suite/python/autodoc_runme.py +++ b/Examples/test-suite/python/autodoc_runme.py @@ -365,3 +365,9 @@ check(func_output.__doc__, "func_output() -> int") check(func_inout.__doc__, "func_inout(int * INOUT) -> int") check(func_cb.__doc__, "func_cb(int c, int d) -> int") check(banana.__doc__, "banana(S a, S b, int c, Integer d)") + +check(TInteger.__doc__, "Proxy of C++ T< int > class.", "::T< int >") +check(TInteger.__init__.__doc__, "__init__(TInteger self) -> TInteger", None, skip) +check(TInteger.inout.__doc__, + "inout(TInteger self, TInteger t) -> TInteger", + "inout(TInteger t) -> TInteger") diff --git a/Source/Modules/python.cxx b/Source/Modules/python.cxx index 581064046..64905bc21 100644 --- a/Source/Modules/python.cxx +++ b/Source/Modules/python.cxx @@ -1960,9 +1960,9 @@ public: Delete(rname); } else { if (CPlusPlus) { - Printf(doc, "Proxy of C++ %s class.", real_classname); + Printf(doc, "Proxy of C++ %s class.", SwigType_namestr(real_classname)); } else { - Printf(doc, "Proxy of C %s struct.", real_classname); + Printf(doc, "Proxy of C %s struct.", SwigType_namestr(real_classname)); } } } @@ -1973,7 +1973,7 @@ public: String *paramList = make_autodocParmList(n, showTypes); Printf(doc, "__init__("); if (showTypes) - Printf(doc, "%s ", getClassName()); + Printf(doc, "%s ", class_name); if (Len(paramList)) Printf(doc, "self, %s) -> %s", paramList, class_name); else @@ -1984,7 +1984,7 @@ public: case AUTODOC_DTOR: if (showTypes) - Printf(doc, "__del__(%s self)", getClassName()); + Printf(doc, "__del__(%s self)", class_name); else Printf(doc, "__del__(self)"); break; From 20b72b78b4c96b521f41bf7c4d7fda7d632c1f29 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Sat, 15 Jul 2017 13:17:50 +0100 Subject: [PATCH 214/455] Fix CCache documentation build and uninstall --- .gitignore | 3 +++ CCache/Makefile.in | 10 +++++----- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/.gitignore b/.gitignore index e94087e29..d2e6b841f 100644 --- a/.gitignore +++ b/.gitignore @@ -66,6 +66,7 @@ CCache/ccache_swig_config.h CCache/config.h CCache/config.log CCache/config.status +CCache/config_win32.h Examples/Makefile Examples/d/example.mk Examples/guile/Makefile @@ -85,6 +86,8 @@ swig.spec # Build Artifacts .dirstamp CCache/ccache-swig +CCache/ccache-swig.1 +CCache/web/ccache-swig-man.html Lib/swigwarn.swg Source/CParse/parser.c Source/CParse/parser.h diff --git a/CCache/Makefile.in b/CCache/Makefile.in index d36e7d0ac..d1bb8c526 100644 --- a/CCache/Makefile.in +++ b/CCache/Makefile.in @@ -18,9 +18,6 @@ SWIG=swig SWIG_LIB=../$(srcdir)/../Lib EXEEXT=@EXEEXT@ -# Use standard autoconf approach to transform executable name using --program-prefix and --program-suffix -transform = @program_transform_name@ - LIBS= @LIBS@ OBJS= ccache.o mdfour.o hash.o execute.o util.o args.o stats.o \ cleanup.o snprintf.o unify.o @@ -59,11 +56,14 @@ uninstall: $(PACKAGE_NAME)$(EXEEXT) rm -f $(DESTDIR)${bindir}/$(PROGRAM_NAME)$(EXEEXT) uninstall-docs: $(srcdir)/$(PACKAGE_NAME).1 - rm -f $(DESTDIR)${mandir}/man1/$(PACKAGE_NAME).1 + rm -f $(DESTDIR)${mandir}/man1/$(PROGRAM_NAME).1 -clean: +clean: clean-docs /bin/rm -f $(OBJS) *~ $(PACKAGE_NAME)$(EXEEXT) +clean-docs: + rm -f $(srcdir)/$(PACKAGE_NAME).1 $(srcdir)/web/$(PACKAGE_NAME)-man.html + test: test.sh SWIG_LIB='$(SWIG_LIB)' PATH=../..:$$PATH SWIG='$(SWIG)' CC='$(CC)' NOSOFTLINKSTEST='$(NOSOFTLINKSTEST)' CCACHE='../$(PACKAGE_NAME)' CCACHE_PROG=$(PROGRAM_NAME) $(srcdir)/test.sh From 06c275935bffeaec91ebf37e17f7ce3dbe6ccf6c Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Tue, 18 Jul 2017 07:17:03 +0100 Subject: [PATCH 215/455] Add readme info for Java container wrappers --- CHANGES.current | 5 +++++ Lib/java/std_list.i | 8 ++++++++ Lib/java/std_vector.i | 5 +++++ 3 files changed, 18 insertions(+) diff --git a/CHANGES.current b/CHANGES.current index 0232208b7..531295c1e 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.0.0 (in progress) =========================== +2017-07-17: fflexo + [Java] #674 Add std_list.i to add support for std::list containers. The Java proxy + extends java.util.AbstractSequentialList and makes the C++ std::list container look + and feel much like a java.util.LinkedList from Java. + 2017-07-07: wsfulton [Python] Fix display of documented template types when using the autodoc feature. For example when wrapping: diff --git a/Lib/java/std_list.i b/Lib/java/std_list.i index af6ac075f..595db8919 100644 --- a/Lib/java/std_list.i +++ b/Lib/java/std_list.i @@ -1,3 +1,11 @@ +/* ----------------------------------------------------------------------------- + * std_list.i + * + * SWIG typemaps for std::list. + * The Java proxy class extends java.util.AbstractSequentialList. The std::list + * container looks and feels much like a java.util.LinkedList from Java. + * ----------------------------------------------------------------------------- */ + %include %{ diff --git a/Lib/java/std_vector.i b/Lib/java/std_vector.i index f35376965..57368c81a 100644 --- a/Lib/java/std_vector.i +++ b/Lib/java/std_vector.i @@ -1,5 +1,10 @@ /* ----------------------------------------------------------------------------- * std_vector.i + * + * SWIG typemaps for std::vector. + * The Java proxy class extends java.util.AbstractList and implements + * java.util.RandomAccess. The std::vector container looks and feels much like a + * java.util.ArrayList from Java. * ----------------------------------------------------------------------------- */ %include From a2e3cc0709364630dfde7fe65ca13752aa35ce70 Mon Sep 17 00:00:00 2001 From: Mike Romberg Date: Thu, 20 Jul 2017 13:07:59 -0600 Subject: [PATCH 216/455] as() no longer uses memset and always throws. --- Lib/r/rstdcommon.swg | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/Lib/r/rstdcommon.swg b/Lib/r/rstdcommon.swg index 557dac71b..5f41fd144 100644 --- a/Lib/r/rstdcommon.swg +++ b/Lib/r/rstdcommon.swg @@ -101,12 +101,11 @@ namespace swig { template struct traits_as { - static Type as(SWIG_Object obj, bool throw_error) { + static Type as(SWIG_Object obj) { Type v; int res = asval(obj, &v); if (!obj || !SWIG_IsOK(res)) { - if (throw_error) - throw std::invalid_argument("bad type"); + throw std::invalid_argument("bad type"); } return v; } @@ -114,7 +113,7 @@ namespace swig { template struct traits_as { - static Type as(SWIG_Object obj, bool throw_error) { + static Type as(SWIG_Object obj) { Type *v = 0; int res = (obj ? traits_asptr::asptr(obj, &v) : SWIG_ERROR); if (SWIG_IsOK(res) && v) { @@ -126,12 +125,7 @@ namespace swig { return *v; } } else { - // Uninitialized return value, no Type() constructor required. - static Type *v_def = (Type*) malloc(sizeof(Type)); - if (throw_error) throw std::invalid_argument("bad type"); - memset(v_def,0,sizeof(Type)); - return *v_def; } } }; @@ -152,8 +146,8 @@ namespace swig { }; template - inline Type as(SWIG_Object obj, bool te = false) { - return traits_as::category>::as(obj, te); + inline Type as(SWIG_Object obj) { + return traits_as::category>::as(obj); } template From b27a58b5b85698db763452bd7cb14f07338e13f6 Mon Sep 17 00:00:00 2001 From: Mike Romberg Date: Thu, 20 Jul 2017 14:28:02 -0600 Subject: [PATCH 217/455] as() no longer memsets and always throws. --- Lib/octave/octcontainer.swg | 4 ++-- Lib/octave/octstdcommon.swg | 21 ++++++++------------- 2 files changed, 10 insertions(+), 15 deletions(-) diff --git a/Lib/octave/octcontainer.swg b/Lib/octave/octcontainer.swg index 771edbde0..9b6520739 100644 --- a/Lib/octave/octcontainer.swg +++ b/Lib/octave/octcontainer.swg @@ -202,8 +202,8 @@ namespace swig // swig::SwigVar_PyObject item = OctSequence_GetItem(_seq, _index); octave_value item; // * todo try { - return swig::as(item, true); - } catch (std::exception& e) { + return swig::as(item); + } catch (const std::exception& e) { char msg[1024]; sprintf(msg, "in sequence element %d ", _index); if (!Octave_Error_Occurred()) { diff --git a/Lib/octave/octstdcommon.swg b/Lib/octave/octstdcommon.swg index b3b3d0048..80b2154d9 100644 --- a/Lib/octave/octstdcommon.swg +++ b/Lib/octave/octstdcommon.swg @@ -103,14 +103,14 @@ namespace swig { template struct traits_as { - static Type as(const octave_value& obj, bool throw_error) { + static Type as(const octave_value& obj) { Type v; int res = asval(obj, &v); if (!obj.is_defined() || !SWIG_IsOK(res)) { if (!Octave_Error_Occurred()) { %type_error(swig::type_name()); } - if (throw_error) throw std::invalid_argument("bad type"); + throw std::invalid_argument("bad type"); } return v; } @@ -118,7 +118,7 @@ namespace swig { template struct traits_as { - static Type as(const octave_value& obj, bool throw_error) { + static Type as(const octave_value& obj) { Type *v = 0; int res = traits_asptr::asptr(obj, &v); if (SWIG_IsOK(res) && v) { @@ -130,21 +130,17 @@ namespace swig { return *v; } } else { - // Uninitialized return value, no Type() constructor required. - static Type *v_def = (Type*) malloc(sizeof(Type)); if (!Octave_Error_Occurred()) { %type_error(swig::type_name()); } - if (throw_error) throw std::invalid_argument("bad type"); - memset(v_def,0,sizeof(Type)); - return *v_def; + throw std::invalid_argument("bad type"); } } }; template struct traits_as { - static Type* as(const octave_value& obj, bool throw_error) { + static Type* as(const octave_value& obj) { Type *v = 0; int res = traits_asptr::asptr(obj, &v); if (SWIG_IsOK(res)) { @@ -153,15 +149,14 @@ namespace swig { if (!Octave_Error_Occurred()) { %type_error(swig::type_name()); } - if (throw_error) throw std::invalid_argument("bad type"); - return 0; + throw std::invalid_argument("bad type"); } } }; template - inline Type as(const octave_value& obj, bool te = false) { - return traits_as::category>::as(obj, te); + inline Type as(const octave_value& obj) { + return traits_as::category>::as(obj); } template From c3ba9506bfb041f6f153f079cb8f0192b2aa6d6d Mon Sep 17 00:00:00 2001 From: Mike Romberg Date: Thu, 20 Jul 2017 14:48:51 -0600 Subject: [PATCH 218/455] as() no longer uses memset and always throws. --- Lib/scilab/scistdcommon.swg | 31 +++++++++++-------------------- 1 file changed, 11 insertions(+), 20 deletions(-) diff --git a/Lib/scilab/scistdcommon.swg b/Lib/scilab/scistdcommon.swg index 975e93a7b..b08fc0307 100644 --- a/Lib/scilab/scistdcommon.swg +++ b/Lib/scilab/scistdcommon.swg @@ -104,23 +104,21 @@ namespace swig { template struct traits_as { - static Type as(const SwigSciObject& obj, bool throw_error) { + static Type as(const SwigSciObject& obj) { Type v; int res = asval(obj, &v); if (SWIG_IsOK(res)) { return v; } else { - %type_error(swig::type_name()); - if (throw_error) - throw std::invalid_argument("bad type"); - return res; + %type_error(swig::type_name()); + throw std::invalid_argument("bad type"); } } }; template struct traits_as { - static Type as(const SwigSciObject& obj, bool throw_error) { + static Type as(const SwigSciObject& obj) { Type *v = 0; int res = traits_asptr::asptr(obj, &v); if (SWIG_IsOK(res) && v) { @@ -132,36 +130,29 @@ namespace swig { return *v; } } else { - // Uninitialized return value, no Type() constructor required. - static Type *v_def = (Type*) malloc(sizeof(Type)); - %type_error(swig::type_name()); - if (throw_error) - throw std::invalid_argument("bad type"); - memset(v_def,0,sizeof(Type)); - return *v_def; + %type_error(swig::type_name()); + throw std::invalid_argument("bad type"); } } }; template struct traits_as { - static Type* as(const SwigSciObject& obj, bool throw_error) { + static Type* as(const SwigSciObject& obj) { Type *v = 0; int res = traits_asptr::asptr(obj, &v); if (SWIG_IsOK(res)) { return v; } else { - %type_error(swig::type_name()); - if (throw_error) - throw std::invalid_argument("bad type"); - return SWIG_OK; + %type_error(swig::type_name()); + throw std::invalid_argument("bad type"); } } }; template - inline Type as(const SwigSciObject& obj, bool te = false) { - return traits_as::category>::as(obj, te); + inline Type as(const SwigSciObject& obj) { + return traits_as::category>::as(obj); } template From 46f7217c507f5599777041e346b23a3c3475d015 Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Fri, 28 Jul 2017 09:37:41 +1200 Subject: [PATCH 219/455] Remove random statement glued onto comment line And also copy-and-paste duplicate. --- Examples/octave/extend/runme.m | 2 +- Examples/python/extend/runme.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Examples/octave/extend/runme.m b/Examples/octave/extend/runme.m index bc73184a8..c88a7c151 100644 --- a/Examples/octave/extend/runme.m +++ b/Examples/octave/extend/runme.m @@ -14,7 +14,7 @@ CEO=@(name) subclass(swigexample.Manager(name),'getPosition',@(self) "CEO"); # Create an instance of our employee extension class, CEO. The calls to # getName() and getPosition() are standard, the call to getTitle() uses -# the director wrappers to call CEO.getPosition. e = CEO("Alice") +# the director wrappers to call CEO.getPosition. e = CEO("Alice"); printf("%s is a %s\n",e.getName(),e.getPosition()); diff --git a/Examples/python/extend/runme.py b/Examples/python/extend/runme.py index 2bb38fadc..e97358b99 100644 --- a/Examples/python/extend/runme.py +++ b/Examples/python/extend/runme.py @@ -18,7 +18,7 @@ class CEO(example.Manager): # Create an instance of our employee extension class, CEO. The calls to # getName() and getPosition() are standard, the call to getTitle() uses -# the director wrappers to call CEO.getPosition. e = CEO("Alice") +# the director wrappers to call CEO.getPosition. e = CEO("Alice") print e.getName(), "is a", e.getPosition() From a92137a708baa1e3378364c1f5cbc0e031e97bed Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Fri, 4 Aug 2017 14:09:30 +1200 Subject: [PATCH 220/455] [C++11] Allow static_assert at the top level And disallow it right after template). Fixes https://github.com/swig/swig/issues/1031 reported by Artem V L. --- CHANGES.current | 5 +++++ Doc/Manual/CPlusPlus11.html | 3 ++- Examples/test-suite/cpp11_static_assert.i | 14 ++++++++++++-- Source/CParse/parser.y | 10 +++++----- 4 files changed, 24 insertions(+), 8 deletions(-) diff --git a/CHANGES.current b/CHANGES.current index 531295c1e..c957a6e6c 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.0.0 (in progress) =========================== +2017-08-05: olly + [C++11] Allow static_assert at the top level (and disallow it right + after template). Fixes https://github.com/swig/swig/issues/1031 + reported by Artem V L. + 2017-07-17: fflexo [Java] #674 Add std_list.i to add support for std::list containers. The Java proxy extends java.util.AbstractSequentialList and makes the C++ std::list container look diff --git a/Doc/Manual/CPlusPlus11.html b/Doc/Manual/CPlusPlus11.html index d3494455b..e4dff6543 100644 --- a/Doc/Manual/CPlusPlus11.html +++ b/Doc/Manual/CPlusPlus11.html @@ -877,7 +877,8 @@ so in this case it is entirely possible to pass an int instead of a double to -SWIG correctly parses the new static_assert declarations. +SWIG correctly parses the new static_assert declarations (though 3.0.12 and earlier +had a bug which meant this wasn't accepted at file scope). This is a C++ compile time directive so there isn't anything useful that SWIG can do with it.

diff --git a/Examples/test-suite/cpp11_static_assert.i b/Examples/test-suite/cpp11_static_assert.i index 8d616f96c..1533d4210 100644 --- a/Examples/test-suite/cpp11_static_assert.i +++ b/Examples/test-suite/cpp11_static_assert.i @@ -1,12 +1,22 @@ -/* This test case checks whether SWIG correctly parses and ignores the - keywords "static_assert()" inside the class or struct. +/* This test case checks whether SWIG correctly parses and ignores + "static_assert()" in various places. */ %module cpp11_static_assert %inline %{ +static_assert(sizeof(int) >= 2, "What? int size is invalid!"); + +namespace dummy { +// C++17 allows the message to be omitted, so check that works too. +static_assert(sizeof(int) >= sizeof(short)); +} + template struct Check1 { static_assert(sizeof(int) <= sizeof(T), "not big enough"); + Check1() { + static_assert(true); + } }; template diff --git a/Source/CParse/parser.y b/Source/CParse/parser.y index 69dce5534..db5ff9f97 100644 --- a/Source/CParse/parser.y +++ b/Source/CParse/parser.y @@ -2991,6 +2991,9 @@ c_declaration : c_decl { SetFlag($$,"aliastemplate"); add_symbols($$); } + | cpp_static_assert { + $$ = $1; + } ; /* ------------------------------------------------------------ @@ -4209,9 +4212,6 @@ cpp_temp_possible: c_decl { | cpp_constructor_decl { $$ = $1; } - | cpp_static_assert { - $$ = $1; - } | cpp_template_decl { $$ = 0; } @@ -4469,7 +4469,6 @@ cpp_member : c_declaration { $$ = $1; } default_arguments($$); } | cpp_destructor_decl { $$ = $1; } - | cpp_static_assert { $$ = $1; } | cpp_protection_decl { $$ = $1; } | cpp_swig_directive { $$ = $1; } | cpp_conversion_operator { $$ = $1; } @@ -4673,7 +4672,8 @@ cpp_catch_decl : CATCH LPAREN parms RPAREN LBRACE { } ; -/* static_assert(bool, const char*); */ +/* static_assert(bool, const char*); (C++11) + * static_assert(bool); (C++17) */ cpp_static_assert : STATIC_ASSERT LPAREN { skip_balanced('(',')'); $$ = 0; From 6303a099aa91d37d3d023b55f6cbc2500aa64b22 Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Fri, 4 Aug 2017 17:01:35 +1200 Subject: [PATCH 221/455] Fix previous commit to compile with older compilers Not all "C++11" compilers will also support C++17. --- Examples/test-suite/cpp11_static_assert.i | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/Examples/test-suite/cpp11_static_assert.i b/Examples/test-suite/cpp11_static_assert.i index 1533d4210..7ca452d85 100644 --- a/Examples/test-suite/cpp11_static_assert.i +++ b/Examples/test-suite/cpp11_static_assert.i @@ -8,14 +8,24 @@ static_assert(sizeof(int) >= 2, "What? int size is invalid!"); namespace dummy { // C++17 allows the message to be omitted, so check that works too. +// But only show the C++17 version to SWIG, as the compiler may +// lack C++17 support. +#ifdef SWIG static_assert(sizeof(int) >= sizeof(short)); +#else +static_assert(sizeof(int) >= sizeof(short), "blah"); +#endif } template struct Check1 { static_assert(sizeof(int) <= sizeof(T), "not big enough"); Check1() { +#ifdef SWIG static_assert(true); +#else + static_assert(true, "true"); +#endif } }; From 74a4cc878629781bf63899ee4a5eff04b03b0027 Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Wed, 9 Aug 2017 11:37:03 +1200 Subject: [PATCH 222/455] [php] Fix reported descriptor in typemap error message The affected typemap is %typemap(in) SWIGTYPE *DISOWN, where the error message was referring to $&1_descriptor but the descriptor actually used by the typemap is $1_descriptor. --- Lib/php/php.swg | 2 +- Lib/php5/php.swg | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Lib/php/php.swg b/Lib/php/php.swg index 0ac46e006..83f76217a 100644 --- a/Lib/php/php.swg +++ b/Lib/php/php.swg @@ -134,7 +134,7 @@ %typemap(in) SWIGTYPE *DISOWN %{ if (SWIG_ConvertPtr(&$input, (void **) &$1, $1_descriptor, SWIG_POINTER_DISOWN ) < 0) { - SWIG_PHP_Error(E_ERROR, "Type error in argument $argnum of $symname. Expected $&1_descriptor"); + SWIG_PHP_Error(E_ERROR, "Type error in argument $argnum of $symname. Expected $1_descriptor"); } %} diff --git a/Lib/php5/php.swg b/Lib/php5/php.swg index 40854ea61..6f8470ff9 100644 --- a/Lib/php5/php.swg +++ b/Lib/php5/php.swg @@ -134,7 +134,7 @@ %typemap(in) SWIGTYPE *DISOWN { if(SWIG_ConvertPtr(*$input, (void **) &$1, $1_descriptor, SWIG_POINTER_DISOWN ) < 0) { - SWIG_PHP_Error(E_ERROR, "Type error in argument $argnum of $symname. Expected $&1_descriptor"); + SWIG_PHP_Error(E_ERROR, "Type error in argument $argnum of $symname. Expected $1_descriptor"); } } From 90f9117e10172722c03dcfde74b35ddd93d6072d Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Sun, 13 Aug 2017 18:04:33 +1200 Subject: [PATCH 223/455] Fix various comment and documentation typos --- CHANGES | 2 +- Doc/Manual/Allegrocl.html | 2 +- Doc/Manual/Android.html | 2 +- Doc/Manual/CCache.html | 2 +- Doc/Manual/CSharp.html | 2 +- Doc/Manual/D.html | 2 +- Doc/Manual/Extending.html | 4 ++-- Doc/Manual/Java.html | 2 +- Doc/Manual/Php.html | 2 +- Doc/Manual/Python.html | 2 +- Doc/Manual/SWIGPlus.html | 2 +- Doc/Manual/Scilab.html | 8 ++++---- Examples/javascript/enum/runme.js | 2 +- Examples/test-suite/README | 2 +- Examples/test-suite/csharp/li_std_map_runme.cs | 2 +- Examples/test-suite/director_extend.i | 2 +- Examples/test-suite/perl5/README | 2 +- Lib/d/dswigtype.swg | 2 +- Lib/lua/luarun.swg | 4 ++-- Lib/perl5/perlrun.swg | 2 +- Lib/python/pyrun.swg | 4 ++-- Lib/r/rrun.swg | 2 +- Lib/r/srun.swg | 2 +- Lib/ruby/rubyrun.swg | 2 +- Lib/scilab/scitypemaps.swg | 2 +- Lib/tcl/tclrun.swg | 2 +- Source/Modules/go.cxx | 2 +- Source/Modules/lang.cxx | 6 +++--- Source/Modules/lua.cxx | 4 ++-- Source/Modules/r.cxx | 2 +- Source/Modules/utils.cxx | 2 +- Source/Swig/cwrap.c | 2 +- Source/Swig/symbol.c | 2 +- configure.ac | 2 +- 34 files changed, 43 insertions(+), 43 deletions(-) diff --git a/CHANGES b/CHANGES index 836bf4b9c..8376c0b36 100644 --- a/CHANGES +++ b/CHANGES @@ -21116,7 +21116,7 @@ Version 1.3.7 (September 3, 2001) typedef __name vector; %enddef - An a specific instantiation is created in exactly the same way: + A specific instantiation is created in exactly the same way: %template(intvec) vector; diff --git a/Doc/Manual/Allegrocl.html b/Doc/Manual/Allegrocl.html index ddb6fba55..c4d898130 100644 --- a/Doc/Manual/Allegrocl.html +++ b/Doc/Manual/Allegrocl.html @@ -155,7 +155,7 @@ SWIG directives. SWIG can be furnished with a header file, but an interface can also be generated without library headers by supplying a simple text file--called the interface file, which is typically named with a .i extension--containing any foreign declarations of -identifiers you wish to use. The most common approach is to use a an +identifiers you wish to use. The most common approach is to use an interface file with directives to parse the needed headers. A straight parse of library headers will result in usable code, but SWIG directives provides much freedom in how a user might tailor the diff --git a/Doc/Manual/Android.html b/Doc/Manual/Android.html index b295b5e04..726314228 100644 --- a/Doc/Manual/Android.html +++ b/Doc/Manual/Android.html @@ -409,7 +409,7 @@ All the steps required to compile and use a simple hierarchy of classes for shap

First create an Android project called SwigClass in a subdirectory called class. -The steps below create and build a the JNI C++ app. +The steps below create and build the JNI C++ app. Adjust the --target id as mentioned earlier in the Examples introduction.

diff --git a/Doc/Manual/CCache.html b/Doc/Manual/CCache.html index d23b0cb2f..521184ff0 100644 --- a/Doc/Manual/CCache.html +++ b/Doc/Manual/CCache.html @@ -411,7 +411,7 @@ following conditions need to be met:

-ccache was inspired by the compilercache shell script script written +ccache was inspired by the compilercache shell script written by Erik Thiele and I would like to thank him for an excellent piece of work. See http://www.erikyyy.de/compilercache/ diff --git a/Doc/Manual/CSharp.html b/Doc/Manual/CSharp.html index 5be63a340..4eb855022 100644 --- a/Doc/Manual/CSharp.html +++ b/Doc/Manual/CSharp.html @@ -1772,7 +1772,7 @@ should pass the call on to CSharpDefaults.DefaultMethod(int)using the C

-When using multiple modules it is is possible to compile each SWIG generated wrapper +When using multiple modules it is possible to compile each SWIG generated wrapper into a different assembly. However, by default the generated code may not compile if generated classes in one assembly use generated classes in another assembly. diff --git a/Doc/Manual/D.html b/Doc/Manual/D.html index 45b57e18b..1a317a005 100644 --- a/Doc/Manual/D.html +++ b/Doc/Manual/D.html @@ -280,7 +280,7 @@ class SomeClass : AnInterface, AnotherInterface { ... }

-

For this to work, AnInterface and AnotherInterface have to be in scope. If SWIG is not in split proxy mode, this is already the case, but it it is, they have to be added to the import list via the dimports typemap. Additionally, the import statement depends on the package SWIG is configured to emit the modules to.

+

For this to work, AnInterface and AnotherInterface have to be in scope. If SWIG is not in split proxy mode, this is already the case, but if it is, they have to be added to the import list via the dimports typemap. Additionally, the import statement depends on the package SWIG is configured to emit the modules to.

The $importtype macro helps you to elegantly solve this problem:

 %typemap(dimports) RemoteMpe %{
diff --git a/Doc/Manual/Extending.html b/Doc/Manual/Extending.html
index bf70b69ac..358d02706 100644
--- a/Doc/Manual/Extending.html
+++ b/Doc/Manual/Extending.html
@@ -1576,7 +1576,7 @@ return the node for the first class member.
 
 
Returns the last child node. You might use this if you wanted to append a new -node to the of a class. +node to the children of a class.

@@ -3164,7 +3164,7 @@ these kinds of problems.

Examples/Makefile.in -
Nothing special here; see comments at top the of this file +
Nothing special here; see comments at the top of this file and look to the existing languages for examples.
Examples/qux99/check.list diff --git a/Doc/Manual/Java.html b/Doc/Manual/Java.html index e0178465c..fad2fc3d4 100644 --- a/Doc/Manual/Java.html +++ b/Doc/Manual/Java.html @@ -4105,7 +4105,7 @@ the exception specification or %catches feature.

Note that the "directorthrows" typemaps are important -only if it is important for the the exceptions passed through the C++ +only if it is important for the exceptions passed through the C++ layer to be mapped to distinct C++ exceptions. If director methods are being called by C++ code that is itself wrapped in a SWIG generated Java wrapper and access is always through this wrapper, diff --git a/Doc/Manual/Php.html b/Doc/Manual/Php.html index 7d3d33ac1..4e17db316 100644 --- a/Doc/Manual/Php.html +++ b/Doc/Manual/Php.html @@ -163,7 +163,7 @@ If the module is in PHP's default extension directory, you can omit the path.

For some SAPIs (for example, the CLI SAPI) you can instead use the dl() function to load -an extension at run time, by adding a like like this to the start of each +an extension at run time, by adding a line like this to the start of each PHP script which uses your extension:

diff --git a/Doc/Manual/Python.html b/Doc/Manual/Python.html index 1b73c08b7..9b9e51455 100644 --- a/Doc/Manual/Python.html +++ b/Doc/Manual/Python.html @@ -6046,7 +6046,7 @@ zipimporter requires python-3.5.1 or newer to work with subpackages.

When SWIG creates wrappers from an interface file, say foo.i, two Python modules are -created. There is a pure Python module module (foo.py) and C/C++ code which is +created. There is a pure Python module (foo.py) and C/C++ code which is built and linked into a dynamically (or statically) loaded low-level module _foo (see the Preliminaries section for details). So, the interface file really defines two Python modules. How these two modules are loaded is diff --git a/Doc/Manual/SWIGPlus.html b/Doc/Manual/SWIGPlus.html index 3e7860b9b..0667623bc 100644 --- a/Doc/Manual/SWIGPlus.html +++ b/Doc/Manual/SWIGPlus.html @@ -2779,7 +2779,7 @@ into two methods such that additional logic can be packed into the operations; C this[type key] { get { ... } set { ... }}, Python uses __getitem__ and __setitem__, etc. In C++ if the return type of operator[] is a reference and the method is const, it is often indicative of the setter, -and and the getter is usually a const function return an object by value. +and the getter is usually a const function return an object by value. In the absence of any hard and fast rules and the fact that there may be multiple index operators, it is up to the user to choose the getter and setter to use by using %rename as shown earlier.

diff --git a/Doc/Manual/Scilab.html b/Doc/Manual/Scilab.html index 14e03ff18..44c570b9b 100644 --- a/Doc/Manual/Scilab.html +++ b/Doc/Manual/Scilab.html @@ -1136,7 +1136,7 @@ But we can use either use the get_perimeter() function of the parent cl As explained in 6.15 SWIG provides support for overloaded functions and constructors.

-

As SWIG knows pointer types, the overloading works also with pointer types, here is is an example with a function magnify overloaded for the previous classes Shape and Circle: +

As SWIG knows pointer types, the overloading works also with pointer types, here is an example with a function magnify overloaded for the previous classes Shape and Circle:

@@ -1620,11 +1620,11 @@ void printArray(int values[], int len) {
 
 
 

-There are no specific typemaps for pointer-to-pointers, they are are mapped as pointers in Scilab. +There are no specific typemaps for pointer-to-pointers, they are mapped as pointers in Scilab.

-Pointer-to-pointers are sometimes used to implement matrices in C. The following is a an example of this: +Pointer-to-pointers are sometimes used to implement matrices in C. The following is an example of this:

@@ -2062,7 +2062,7 @@ In this mode, the following SWIG options may be used to setup the build: Let's give an example how to build a module example, composed of two sources, and using a library dependency:

    -
  • the sources are baa1.c and baa2.c (and are stored in in the current directory)
  • +
  • the sources are baa1.c and baa2.c (and are stored in the current directory)
  • the library is libfoo in /opt/foo (headers stored in /opt/foo/include, and shared library in /opt/foo/lib)
diff --git a/Examples/javascript/enum/runme.js b/Examples/javascript/enum/runme.js index 851d43c4b..f3264889c 100644 --- a/Examples/javascript/enum/runme.js +++ b/Examples/javascript/enum/runme.js @@ -30,5 +30,5 @@ f.enum_test(example.Foo.LUDICROUS); // enum value BLUE of enum color is accessed as property of cconst console.log("example.BLUE= " + example.BLUE); -// enum value LUDICROUS of enum Foo::speed is accessed as as property of cconst +// enum value LUDICROUS of enum Foo::speed is accessed as property of cconst console.log("example.speed.LUDICROUS= " + example.Foo.LUDICROUS); diff --git a/Examples/test-suite/README b/Examples/test-suite/README index aac7636c6..3b7cea477 100644 --- a/Examples/test-suite/README +++ b/Examples/test-suite/README @@ -47,6 +47,6 @@ testdir/README file. Further Documentation --------------------- -There is documentation about the test-suite and how to use use it in +There is documentation about the test-suite and how to use it in the SWIG documentation - Doc/Manual/Extending.html#Extending_test_suite. diff --git a/Examples/test-suite/csharp/li_std_map_runme.cs b/Examples/test-suite/csharp/li_std_map_runme.cs index 0fe1ab5cd..b21c81e4e 100644 --- a/Examples/test-suite/csharp/li_std_map_runme.cs +++ b/Examples/test-suite/csharp/li_std_map_runme.cs @@ -18,7 +18,7 @@ public class li_std_map_runme { public static void Main() { - // Set up an int int map + // Set up an string to int map StringIntMap simap = new StringIntMap(); for (int i = 0; i < collectionSize; i++) { diff --git a/Examples/test-suite/director_extend.i b/Examples/test-suite/director_extend.i index cec930a42..60a9d4cf0 100644 --- a/Examples/test-suite/director_extend.i +++ b/Examples/test-suite/director_extend.i @@ -25,7 +25,7 @@ namespace Swig { size_t ExceptionMethod() { // Check positioning of director code in wrapper file -// Below is what we really want to test, but director exceptions vary too much across across all languages +// Below is what we really want to test, but director exceptions vary too much across all languages // throw Swig::DirectorException("DirectorException was not in scope!!"); // Instead check definition of Director class as that is defined in the same place as DirectorException (director.swg) size_t size = sizeof(Swig::Director); diff --git a/Examples/test-suite/perl5/README b/Examples/test-suite/perl5/README index 804dec8e8..f15c07849 100644 --- a/Examples/test-suite/perl5/README +++ b/Examples/test-suite/perl5/README @@ -6,7 +6,7 @@ Test::More Support == Test::More is a standard perl test harness tool. -Support was added for for using Test::More in 1.3.28. +Support was added for using Test::More in 1.3.28. If adding a new test to this suite, please use Test::More. There are a few legacy test cases which do not use Test::More and these ought to be converted: diff --git a/Lib/d/dswigtype.swg b/Lib/d/dswigtype.swg index f91d6dfe6..5043741d5 100644 --- a/Lib/d/dswigtype.swg +++ b/Lib/d/dswigtype.swg @@ -162,7 +162,7 @@ return ret; } -// Treat references to arrays like like references to a single element. +// Treat references to arrays like references to a single element. %apply SWIGTYPE & { SWIGTYPE ((&)[ANY]) } diff --git a/Lib/lua/luarun.swg b/Lib/lua/luarun.swg index 3510d04d7..514336029 100644 --- a/Lib/lua/luarun.swg +++ b/Lib/lua/luarun.swg @@ -180,7 +180,7 @@ typedef struct swig_elua_entry { * -------------------------------------------------------------------------- */ /* Push the string STR on the Lua stack, like lua_pushstring, but - prefixed with the the location of the innermost Lua call-point + prefixed with the location of the innermost Lua call-point (as formated by luaL_where). */ SWIGRUNTIME void SWIG_Lua_pusherrstring (lua_State *L, const char *str) @@ -191,7 +191,7 @@ SWIG_Lua_pusherrstring (lua_State *L, const char *str) } /* Push a formatted string generated from FMT and following args on - the Lua stack, like lua_pushfstring, but prefixed with the the + the Lua stack, like lua_pushfstring, but prefixed with the location of the innermost Lua call-point (as formated by luaL_where). */ SWIGRUNTIME void SWIG_Lua_pushferrstring (lua_State *L, const char *fmt, ...) diff --git a/Lib/perl5/perlrun.swg b/Lib/perl5/perlrun.swg index d1865de0a..cc4ba446a 100644 --- a/Lib/perl5/perlrun.swg +++ b/Lib/perl5/perlrun.swg @@ -392,7 +392,7 @@ SWIG_Perl_NewPackedObj(SWIG_MAYBE_PERL_OBJECT void *ptr, int sz, swig_type_info return result; } -/* Convert a packed value value */ +/* Convert a packed pointer value */ SWIGRUNTIME int SWIG_Perl_ConvertPacked(SWIG_MAYBE_PERL_OBJECT SV *obj, void *ptr, int sz, swig_type_info *ty) { swig_cast_info *tc; diff --git a/Lib/python/pyrun.swg b/Lib/python/pyrun.swg index 939a69204..efc476613 100644 --- a/Lib/python/pyrun.swg +++ b/Lib/python/pyrun.swg @@ -538,7 +538,7 @@ SwigPyObject_dealloc(PyObject *v) PyObject *res; /* PyObject_CallFunction() has the potential to silently drop - the active active exception. In cases of unnamed temporary + the active exception. In cases of unnamed temporary variable or where we just finished iterating over a generator StopIteration will be active right now, and this needs to remain true upon return from SwigPyObject_dealloc. So save @@ -1308,7 +1308,7 @@ SWIG_Python_ConvertFunctionPtr(PyObject *obj, void **ptr, swig_type_info *ty) { } } -/* Convert a packed value value */ +/* Convert a packed pointer value */ SWIGRUNTIME int SWIG_Python_ConvertPacked(PyObject *obj, void *ptr, size_t sz, swig_type_info *ty) { diff --git a/Lib/r/rrun.swg b/Lib/r/rrun.swg index 81f6461d2..63b7ecc70 100644 --- a/Lib/r/rrun.swg +++ b/Lib/r/rrun.swg @@ -350,7 +350,7 @@ SWIG_R_NewPackedObj(void *ptr, size_t sz, swig_type_info *type) { return ptr ? RSwigPacked_New((void *) ptr, sz, type) : R_NilValue; } -/* Convert a packed value value */ +/* Convert a packed pointer value */ SWIGRUNTIME int SWIG_R_ConvertPacked(SEXP obj, void *ptr, size_t sz, swig_type_info *ty) { diff --git a/Lib/r/srun.swg b/Lib/r/srun.swg index 2045ab94e..d07218a77 100644 --- a/Lib/r/srun.swg +++ b/Lib/r/srun.swg @@ -7,7 +7,7 @@ # This could be provided as a separate run-time library but this -# approach allows the code to to be included directly into the +# approach allows the code to be included directly into the # generated bindings and so removes the need to have and install an # additional library. We may however end up with multiple copies of # this and some confusion at run-time as to which class to use. This diff --git a/Lib/ruby/rubyrun.swg b/Lib/ruby/rubyrun.swg index 4628aedc3..1afc5c1d0 100644 --- a/Lib/ruby/rubyrun.swg +++ b/Lib/ruby/rubyrun.swg @@ -363,7 +363,7 @@ SWIG_Ruby_NewPackedObj(void *ptr, int sz, swig_type_info *type) { return rb_str_new2(result); } -/* Convert a packed value value */ +/* Convert a packed pointer value */ SWIGRUNTIME int SWIG_Ruby_ConvertPacked(VALUE obj, void *ptr, int sz, swig_type_info *ty) { swig_cast_info *tc; diff --git a/Lib/scilab/scitypemaps.swg b/Lib/scilab/scitypemaps.swg index 4cf0da3f1..682d18c44 100644 --- a/Lib/scilab/scitypemaps.swg +++ b/Lib/scilab/scitypemaps.swg @@ -7,7 +7,7 @@ #define SWIG_Object int #define %append_output(obj) if (!SWIG_IsOK(SWIG_Scilab_SetOutput(pvApiCtx, obj))) return SWIG_ERROR -#define %set_constant(name, obj) if (!SWIG_IsOK(SWIG_Scilab_SetOutput(pvApiCtx, obj))) return SWIG_ERROR // Name is managed by the the function name +#define %set_constant(name, obj) if (!SWIG_IsOK(SWIG_Scilab_SetOutput(pvApiCtx, obj))) return SWIG_ERROR // Name is managed by the function name #define %raise(obj, type, desc) SWIG_Scilab_Raise(obj, type, desc) #define %set_output(obj) if (!SWIG_IsOK(SWIG_Scilab_SetOutput(pvApiCtx, obj))) return SWIG_ERROR #define %set_varoutput(obj) if (!SWIG_IsOK(SWIG_Scilab_SetOutput(pvApiCtx, obj))) return SWIG_ERROR diff --git a/Lib/tcl/tclrun.swg b/Lib/tcl/tclrun.swg index f671ba240..408ddac3d 100644 --- a/Lib/tcl/tclrun.swg +++ b/Lib/tcl/tclrun.swg @@ -199,7 +199,7 @@ SWIG_Tcl_PointerTypeFromString(char *c) { return c; } -/* Convert a packed value value */ +/* Convert a packed pointer value */ SWIGRUNTIME int SWIG_Tcl_ConvertPacked(Tcl_Interp *SWIGUNUSEDPARM(interp) , Tcl_Obj *obj, void *ptr, int sz, swig_type_info *ty) { swig_cast_info *tc; diff --git a/Source/Modules/go.cxx b/Source/Modules/go.cxx index 1512834f9..916030437 100644 --- a/Source/Modules/go.cxx +++ b/Source/Modules/go.cxx @@ -990,7 +990,7 @@ private: * overname: The overload string for overloaded function. * wname: The SWIG wrapped name--the name of the C function. * base: A list of the names of base classes, in the case where this - * is is a vritual method not defined in the current class. + * is a virtual method not defined in the current class. * parms: The parameters. * result: The result type. * is_static: Whether this is a static method or member. diff --git a/Source/Modules/lang.cxx b/Source/Modules/lang.cxx index 11874ef0a..1e4a6bdb6 100644 --- a/Source/Modules/lang.cxx +++ b/Source/Modules/lang.cxx @@ -1949,7 +1949,7 @@ int Language::unrollVirtualMethods(Node *n, Node *parent, List *vm, int default_ generation of 'empty' director classes. But this has to be done outside the previous 'for' - an the recursive loop!. + and the recursive loop!. */ if (n == parent) { int len = Len(vm); @@ -2078,7 +2078,7 @@ int Language::classDirectorConstructors(Node *n) { needed, since there is a public constructor already defined. (scottm) This code is needed here to make the director_abstract + - test generate compilable code (Example2 in director_abastract.i). + test generate compilable code (Example2 in director_abstract.i). (mmatus) This is very strange, since swig compiled with gcc3.2.3 doesn't need it here.... @@ -3308,7 +3308,7 @@ Node *Language::classLookup(const SwigType *s) const { } if (n) { /* Found a match. Look at the prefix. We only allow - the cases where where we want a proxy class for the particular type */ + the cases where we want a proxy class for the particular type */ bool acceptable_prefix = (Len(prefix) == 0) || // simple type (pass by value) (Strcmp(prefix, "p.") == 0) || // pointer diff --git a/Source/Modules/lua.cxx b/Source/Modules/lua.cxx index 80ea47f3f..08de34976 100644 --- a/Source/Modules/lua.cxx +++ b/Source/Modules/lua.cxx @@ -1755,7 +1755,7 @@ public: * * This is to convert the string of Lua code into a proper string, which can then be * emitted into the C/C++ code. - * Basically is is a lot of search & replacing of odd sequences + * Basically it is a lot of search & replacing of odd sequences * ---------------------------------------------------------------------------- */ void escapeCode(String *str) { @@ -1770,7 +1770,7 @@ public: /* ----------------------------------------------------------------------------- * rawGetCArraysHash(String *name) * - * A small helper to hide impelementation of how CArrays hashes are stored + * A small helper to hide implementation of how CArrays hashes are stored * ---------------------------------------------------------------------------- */ Hash *rawGetCArraysHash(const_String_or_char_ptr name) { diff --git a/Source/Modules/r.cxx b/Source/Modules/r.cxx index 1c8533064..6a326206f 100644 --- a/Source/Modules/r.cxx +++ b/Source/Modules/r.cxx @@ -718,7 +718,7 @@ String * R::createFunctionPointerHandler(SwigType *t, Node *n, int *numArgs) { function that handles the scoerceout. We need to check if any of the argument types have an entry in that map. If none do, the ignore and call the function straight. - Otherwise, generate the a marshalling function. + Otherwise, generate a marshalling function. Need to be able to find it in S. Or use an entirely generic one that evaluates the expressions. Handle errors in the evaluation of the function by restoring diff --git a/Source/Modules/utils.cxx b/Source/Modules/utils.cxx index a91ebe098..2964ed3a6 100644 --- a/Source/Modules/utils.cxx +++ b/Source/Modules/utils.cxx @@ -59,7 +59,7 @@ int is_non_virtual_protected_access(Node *n) { // When vtable is empty, the director class does not get emitted, so a check for an empty vtable should be done. // However, vtable is set in Language and so is not yet set when methods in Typepass call clean_overloaded() // which calls is_non_virtual_protected_access. So commented out below. - // Moving the director vtable creation into into Typepass should solve this problem. + // Moving the director vtable creation into Typepass should solve this problem. if (is_member_director_helper(parentNode, n) /* && Getattr(parentNode, "vtable")*/) result = 1; } diff --git a/Source/Swig/cwrap.c b/Source/Swig/cwrap.c index 9da4e0829..4c3135e3a 100644 --- a/Source/Swig/cwrap.c +++ b/Source/Swig/cwrap.c @@ -277,7 +277,7 @@ int Swig_cargs(Wrapper *w, ParmList *p) { SwigType_del_rvalue_reference(tvalue); tycode = SwigType_type(tvalue); if (tycode != T_USER) { - /* plain primitive type, we copy the the def value */ + /* plain primitive type, we copy the def value */ String *lstr = SwigType_lstr(tvalue, defname); defvalue = NewStringf("%s = %s", lstr, qvalue); Delete(lstr); diff --git a/Source/Swig/symbol.c b/Source/Swig/symbol.c index c548a0670..965a84472 100644 --- a/Source/Swig/symbol.c +++ b/Source/Swig/symbol.c @@ -599,7 +599,7 @@ void Swig_symbol_cadd(const_String_or_char_ptr name, Node *n) { Setattr(ccurrent, name, n); } - /* Multiple entries in the C symbol table. We append to to the symbol table */ + /* Multiple entries in the C symbol table. We append to the symbol table */ if (append) { Node *fn, *pn = 0; cn = Getattr(ccurrent, name); diff --git a/configure.ac b/configure.ac index 25ea0a243..ddf7a7dd7 100644 --- a/configure.ac +++ b/configure.ac @@ -280,7 +280,7 @@ fi AC_MSG_RESULT($RPATH) # LINKFORSHARED are the flags passed to the $(CC) command that links -# the a few executables -- this is only needed for a few systems +# a few executables -- this is only needed for a few systems AC_MSG_CHECKING(LINKFORSHARED) if test -z "$LINKFORSHARED" From 2165f27f5d77d38399f7f83e6a7fb41a12c77690 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Wed, 2 Aug 2017 22:55:23 +0100 Subject: [PATCH 224/455] Fix incorrectly shown warning for empty template instantiation used as a base class. --- CHANGES.current | 8 ++++++ Examples/test-suite/common.mk | 1 + Examples/test-suite/template_empty_inherit.i | 30 ++++++++++++++++++++ Source/Modules/typepass.cxx | 12 +++++--- 4 files changed, 47 insertions(+), 4 deletions(-) create mode 100644 Examples/test-suite/template_empty_inherit.i diff --git a/CHANGES.current b/CHANGES.current index c957a6e6c..808bd1798 100644 --- a/CHANGES.current +++ b/CHANGES.current @@ -12,6 +12,14 @@ Version 4.0.0 (in progress) after template). Fixes https://github.com/swig/swig/issues/1031 reported by Artem V L. +2017-08-02: wsfulton + Fix incorrectly shown warning when an empty template instantiation was used on a + class used as a base class and that base class was explicitly ignored with %ignore. + Example of the warning which will no longer appear: + + Warning 401: Base class 'Functor< int,int >' has no name as it is an empty + template instantiated with '%template()'. Ignored. + 2017-07-17: fflexo [Java] #674 Add std_list.i to add support for std::list containers. The Java proxy extends java.util.AbstractSequentialList and makes the C++ std::list container look diff --git a/Examples/test-suite/common.mk b/Examples/test-suite/common.mk index 146ada2c6..b7ea38f10 100644 --- a/Examples/test-suite/common.mk +++ b/Examples/test-suite/common.mk @@ -418,6 +418,7 @@ CPP_TEST_CASES += \ template_default_inherit \ template_default_qualify \ template_default_vw \ + template_empty_inherit \ template_enum \ template_enum_ns_inherit \ template_enum_typedef \ diff --git a/Examples/test-suite/template_empty_inherit.i b/Examples/test-suite/template_empty_inherit.i new file mode 100644 index 000000000..3032f8171 --- /dev/null +++ b/Examples/test-suite/template_empty_inherit.i @@ -0,0 +1,30 @@ +%module template_empty_inherit + +%inline %{ +template struct Functor { + virtual Result operator()(Arg x) const = 0; +}; +%} + +// Bug fix - %ignore was resulting in this warning: +// Warning 401: Base class 'Functor< int,int >' has no name as it is an empty template instantiated with '%template()'. Ignored. +%ignore Functor; +%template() Functor; + +%inline %{ +#include +struct SquareFunctor : Functor { + int operator()(int v) const { return v*v; } +}; +%} + +%include +%template(VectorInt) std::vector; + +%inline %{ +std::vector squares(const std::vector& vi) { + std::vector result; + std::transform(vi.begin(), vi.end(), std::back_inserter(result), SquareFunctor()); + return result; +} +%} diff --git a/Source/Modules/typepass.cxx b/Source/Modules/typepass.cxx index bf8028c29..281c96ad0 100644 --- a/Source/Modules/typepass.cxx +++ b/Source/Modules/typepass.cxx @@ -187,8 +187,10 @@ class TypePass:private Dispatcher { ilist = alist = NewList(); Append(ilist, bcls); } else { - Swig_warning(WARN_TYPE_UNDEFINED_CLASS, Getfile(bname), Getline(bname), "Base class '%s' has no name as it is an empty template instantiated with '%%template()'. Ignored.\n", SwigType_namestr(bname)); - Swig_warning(WARN_TYPE_UNDEFINED_CLASS, Getfile(bcls), Getline(bcls), "The %%template directive must be written before '%s' is used as a base class and be declared with a name.\n", SwigType_namestr(bname)); + if (!GetFlag(bcls, "feature:ignore")) { + Swig_warning(WARN_TYPE_UNDEFINED_CLASS, Getfile(bname), Getline(bname), "Base class '%s' has no name as it is an empty template instantiated with '%%template()'. Ignored.\n", SwigType_namestr(bname)); + Swig_warning(WARN_TYPE_UNDEFINED_CLASS, Getfile(bcls), Getline(bcls), "The %%template directive must be written before '%s' is used as a base class and be declared with a name.\n", SwigType_namestr(bname)); + } } } break; @@ -209,8 +211,10 @@ class TypePass:private Dispatcher { ilist = alist = NewList(); Append(ilist, bcls); } else { - Swig_warning(WARN_TYPE_UNDEFINED_CLASS, Getfile(bname), Getline(bname), "Base class '%s' has no name as it is an empty template instantiated with '%%template()'. Ignored.\n", SwigType_namestr(bname)); - Swig_warning(WARN_TYPE_UNDEFINED_CLASS, Getfile(bcls), Getline(bcls), "The %%template directive must be written before '%s' is used as a base class and be declared with a name.\n", SwigType_namestr(bname)); + if (!GetFlag(bcls, "feature:ignore")) { + Swig_warning(WARN_TYPE_UNDEFINED_CLASS, Getfile(bname), Getline(bname), "Base class '%s' has no name as it is an empty template instantiated with '%%template()'. Ignored.\n", SwigType_namestr(bname)); + Swig_warning(WARN_TYPE_UNDEFINED_CLASS, Getfile(bcls), Getline(bcls), "The %%template directive must be written before '%s' is used as a base class and be declared with a name.\n", SwigType_namestr(bname)); + } } } else { Swig_warning(WARN_TYPE_UNDEFINED_CLASS, Getfile(bname), Getline(bname), "Base class '%s' undefined.\n", SwigType_namestr(bname)); From aedc3c3eafe416c58467abcc68c498d6b7fd1d27 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Wed, 9 Aug 2017 21:15:23 +0100 Subject: [PATCH 225/455] Replace assert in Python import examples with code that always runs. --- Examples/python/import_packages/namespace_pkg/nonpkg.py | 3 ++- Examples/python/import_packages/namespace_pkg/normal.py | 3 ++- Examples/python/import_packages/namespace_pkg/split.py | 3 ++- Examples/python/import_packages/namespace_pkg/zipsplit.py | 3 ++- Examples/python/import_packages/split_modules/vanilla/runme.py | 3 ++- .../import_packages/split_modules/vanilla_split/runme.py | 3 ++- 6 files changed, 12 insertions(+), 6 deletions(-) diff --git a/Examples/python/import_packages/namespace_pkg/nonpkg.py b/Examples/python/import_packages/namespace_pkg/nonpkg.py index acf0aedbd..dc910b846 100644 --- a/Examples/python/import_packages/namespace_pkg/nonpkg.py +++ b/Examples/python/import_packages/namespace_pkg/nonpkg.py @@ -2,4 +2,5 @@ import robin -assert(robin.run() == "AWAY!") +if not(robin.run() == "AWAY!"): + raise RuntimeError("test failed") diff --git a/Examples/python/import_packages/namespace_pkg/normal.py b/Examples/python/import_packages/namespace_pkg/normal.py index fc26c0216..231d4cccd 100644 --- a/Examples/python/import_packages/namespace_pkg/normal.py +++ b/Examples/python/import_packages/namespace_pkg/normal.py @@ -4,4 +4,5 @@ sys.path.insert(0, 'path1') from brave import robin -assert(robin.run() == "AWAY!") +if not(robin.run() == "AWAY!"): + raise RuntimeError("test failed") diff --git a/Examples/python/import_packages/namespace_pkg/split.py b/Examples/python/import_packages/namespace_pkg/split.py index 1b66c2d49..88d17d5fe 100644 --- a/Examples/python/import_packages/namespace_pkg/split.py +++ b/Examples/python/import_packages/namespace_pkg/split.py @@ -6,4 +6,5 @@ sys.path.insert(0, 'path3') from brave import robin -assert(robin.run() == "AWAY!") +if not(robin.run() == "AWAY!"): + raise RuntimeError("test failed") diff --git a/Examples/python/import_packages/namespace_pkg/zipsplit.py b/Examples/python/import_packages/namespace_pkg/zipsplit.py index 9e35559e3..b027b11c1 100644 --- a/Examples/python/import_packages/namespace_pkg/zipsplit.py +++ b/Examples/python/import_packages/namespace_pkg/zipsplit.py @@ -6,4 +6,5 @@ sys.path.insert(0, 'path3') from brave import robin -assert(robin.run() == "AWAY!") +if not(robin.run() == "AWAY!"): + raise RuntimeError("test failed") diff --git a/Examples/python/import_packages/split_modules/vanilla/runme.py b/Examples/python/import_packages/split_modules/vanilla/runme.py index a188364f1..4c46ef200 100644 --- a/Examples/python/import_packages/split_modules/vanilla/runme.py +++ b/Examples/python/import_packages/split_modules/vanilla/runme.py @@ -7,4 +7,5 @@ import pkg1.foo print " Finished importing pkg1.foo" -assert(pkg1.foo.count() == 3) +if not(pkg1.foo.count() == 3): + raise RuntimeError("test failed") 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 a188364f1..4c46ef200 100644 --- a/Examples/python/import_packages/split_modules/vanilla_split/runme.py +++ b/Examples/python/import_packages/split_modules/vanilla_split/runme.py @@ -7,4 +7,5 @@ import pkg1.foo print " Finished importing pkg1.foo" -assert(pkg1.foo.count() == 3) +if not(pkg1.foo.count() == 3): + raise RuntimeError("test failed") From b2660e7100b0f499635a58206e0b1a9152f3ffb2 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Mon, 14 Aug 2017 07:46:56 +0100 Subject: [PATCH 226/455] Fix template_empty_inherit testcase - To be standards compliant - Wrap operator() for all target languages --- Examples/test-suite/template_empty_inherit.i | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Examples/test-suite/template_empty_inherit.i b/Examples/test-suite/template_empty_inherit.i index 3032f8171..308a01fda 100644 --- a/Examples/test-suite/template_empty_inherit.i +++ b/Examples/test-suite/template_empty_inherit.i @@ -1,5 +1,7 @@ %module template_empty_inherit +%rename(FunctorOperator) operator(); + %inline %{ template struct Functor { virtual Result operator()(Arg x) const = 0; @@ -13,6 +15,7 @@ template struct Functor { %inline %{ #include +#include struct SquareFunctor : Functor { int operator()(int v) const { return v*v; } }; From aa2932f4090022ee9989d092bc05487622ba212d Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Mon, 17 Jul 2017 07:23:23 +0100 Subject: [PATCH 227/455] Typemap change for templates For templates only, the template parameters are fully resolved when handling typemaps. Without this, it is too hard to have decent rules to apply typemaps when parameter types are typedef'd and template parameters have default values. Fixes %clear for typedefs in templates, eg: %typemap("in") XXX::Long "..." template typename struct XXX { typedef long Long; }; %clear XXX::Long; as the typemap was previously incorrectly stored as a typemap for long instead of XXX::Long. --- .../python/typemap_template_typedef_runme.py | 32 +++++++++ .../test-suite/typemap_template_typedef.i | 66 +++++++++++++++++++ Source/Swig/typemap.c | 36 +++++++++- 3 files changed, 132 insertions(+), 2 deletions(-) create mode 100644 Examples/test-suite/python/typemap_template_typedef_runme.py create mode 100644 Examples/test-suite/typemap_template_typedef.i diff --git a/Examples/test-suite/python/typemap_template_typedef_runme.py b/Examples/test-suite/python/typemap_template_typedef_runme.py new file mode 100644 index 000000000..a2458367e --- /dev/null +++ b/Examples/test-suite/python/typemap_template_typedef_runme.py @@ -0,0 +1,32 @@ +from typemap_template_typedef import * + +def check(got, expected): + if got != expected: + raise RuntimeError("got: " + str(got) + " expected: " + str(expected)) + +x = XXXInt() + +check(x.aa1(0), 0) +check(x.aa2(0), 55) +check(x.aa3(0), 0) +check(aa1(0), 0) +check(aa2(0), 0) + +check(x.bb1(0), 0) +check(x.bb2(0), 66) +check(x.bb3(0), 0) +check(bb1(0), 0) +check(bb2(0), 0) + +check(x.cc1(0), 0) +check(x.cc2(0), 77) +check(x.cc3(0), 77) +check(cc1(0), 0) +check(cc2(0), 0) + +check(x.dd1(0), 0) +check(x.dd2(0), 88) +check(x.dd3(0), 0) +check(dd1(0), 0) +check(dd2(0), 0) + diff --git a/Examples/test-suite/typemap_template_typedef.i b/Examples/test-suite/typemap_template_typedef.i new file mode 100644 index 000000000..c84416ef9 --- /dev/null +++ b/Examples/test-suite/typemap_template_typedef.i @@ -0,0 +1,66 @@ +%module typemap_template_typedef +//%module("templatereduce") typemap_template_typedef + +%typemap(in) int TMAP55 %{ $1 = 55; /* int TMAP55 typemap */ %} +%typemap(in) int TMAP66 %{ $1 = 66; /* int TMAP66 typemap */ %} +%typemap(in) int TMAP77 %{ $1 = 77; /* int TMAP77 typemap */ %} +%typemap(in) int TMAP88 %{ $1 = 88; /* int TMAP88 typemap */ %} + +%apply int TMAP77 { XXX::Long cc } + +%inline %{ +typedef int Integer; + +template struct XXX { +#ifdef SWIG +// In swig-3.0.12 'Long aa' was actually stored as 'long aa' in typemap table instead of 'XXX::Long aa' +%apply int TMAP55 { Long aa } +%apply int TMAP66 { XXX::Long bb } +%apply int TMAP88 { XXX::Long dd } +#endif + typedef long Long; + long aa1(long aa) { return aa; } + long aa2(Long aa) { return aa; } + long bb1(long bb) { return bb; } + long bb2(Long bb) { return bb; } + long cc1(long cc) { return cc; } + long cc2(Long cc) { return cc; } + long dd1(long dd) { return dd; } + long dd2(Long dd) { return dd; } +#ifdef SWIG +%clear Long aa; +%clear XXX::Long bb; +%clear XXX::Long dd; +#endif + long aa3(Long aa) { return aa; } + long bb3(Long bb) { return bb; } + long cc3(Long cc) { return cc; } + long dd3(Long dd) { return dd; } +}; +%} + +%template(XXXInt) XXX; + +%clear XXX::Long cc; + +%inline %{ + long aa1(XXX::Long aa) { return aa; } + long aa2(long aa) { return aa; } + long bb1(XXX::Long bb) { return bb; } + long bb2(long bb) { return bb; } + long cc1(XXX::Long cc) { return cc; } + long cc2(long cc) { return cc; } + long dd1(XXX::Long dd) { return dd; } + long dd2(long dd) { return dd; } +%} + +%inline %{ +typedef Integer INTEGER; +template struct YYY { + void meff(T1 t1, T2 t2) {} +}; +%} +%template(YYYIntInt) YYY; +%inline %{ + void whyohwhy(YYY yy) {} +%} diff --git a/Source/Swig/typemap.c b/Source/Swig/typemap.c index 8970c719d..c0f5397c1 100644 --- a/Source/Swig/typemap.c +++ b/Source/Swig/typemap.c @@ -61,13 +61,44 @@ static void replace_embedded_typemap(String *s, ParmList *parm_sublist, Wrapper static Hash *typemaps; +/* ----------------------------------------------------------------------------- + * typemap_identifier_fix() + * + * Create a type that can be used as a hash key lookup independent of the various + * ways a template parameter list can be defined. This is achieved by fully + * resolving the template parameters. + * + * This is a copy and modification of feature_identifier_fix in parser.y. + * ----------------------------------------------------------------------------- */ + +static SwigType *typemap_identifier_fix(const SwigType *s) { + String *tp = SwigType_istemplate_templateprefix(s); + if (tp) { + String *ts, *ta, *tq, *tr; + ts = SwigType_templatesuffix(s); + ta = SwigType_templateargs(s); + tq = Swig_symbol_type_qualify(ta, 0); + tr = SwigType_typedef_resolve_all(ta); + Append(tp,tr); + Append(tp,ts); + Delete(ts); + Delete(ta); + Delete(tq); + Delete(tr); + return tp; + } else { + return NewString(s); + } +} + static Hash *get_typemap(const SwigType *type) { Hash *tm = 0; SwigType *dtype = 0; SwigType *hashtype; if (SwigType_istemplate(type)) { - String *ty = Swig_symbol_template_deftype(type, 0); + SwigType *rty = typemap_identifier_fix(type); + String *ty = Swig_symbol_template_deftype(rty, 0); dtype = Swig_symbol_type_qualify(ty, 0); type = dtype; Delete(ty); @@ -88,7 +119,7 @@ static void set_typemap(const SwigType *type, Hash **tmhash) { Hash *new_tm = 0; assert(*tmhash == 0); if (SwigType_istemplate(type)) { - SwigType *rty = SwigType_typedef_resolve_all(type); + SwigType *rty = typemap_identifier_fix(type); String *ty = Swig_symbol_template_deftype(rty, 0); String *tyq = Swig_symbol_type_qualify(ty, 0); hashtype = SwigType_remove_global_scope_prefix(tyq); @@ -733,6 +764,7 @@ static Hash *typemap_search(const_String_or_char_ptr tmap_method, SwigType *type SwigType *oldctype = ctype; ctype = SwigType_typedef_resolve(ctype_unstripped); Delete(oldctype); + Delete(ctype_unstripped); ctype_unstripped = Copy(ctype); } } From 26e14c4f189c0f269047c9a40d137293ecf9a983 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Sat, 22 Jul 2017 13:17:23 +0100 Subject: [PATCH 228/455] Fix scope lookup for template parameters containing unary scope operators Fixes cases like: namespace Alloc { template struct Rebind { typedef int Integer; }; } %template(RebindBucket) Alloc::Rebind< Bucket >; OR %template(RebindBucket) Alloc::Rebind< ::Bucket >; Alloc::Rebind< Bucket >::Integer Bucket1() { return 1; } Alloc::Rebind< ::Bucket >::Integer Bucket2() { return 2; } Alloc::Rebind<::template TemplateBucket>::Integer Bucket3() { return 3; }; --- Examples/test-suite/common.mk | 1 + .../java/cpp11_template_typedefs_runme.java | 19 +++ ...emplate_parameters_global_scope_runme.java | 75 ++++++++++ .../template_parameters_global_scope.i | 133 ++++++++++++++++++ Source/Swig/typesys.c | 38 ++++- 5 files changed, 260 insertions(+), 6 deletions(-) create mode 100644 Examples/test-suite/java/cpp11_template_typedefs_runme.java create mode 100644 Examples/test-suite/java/template_parameters_global_scope_runme.java create mode 100644 Examples/test-suite/template_parameters_global_scope.i diff --git a/Examples/test-suite/common.mk b/Examples/test-suite/common.mk index 146ada2c6..ab341e7a1 100644 --- a/Examples/test-suite/common.mk +++ b/Examples/test-suite/common.mk @@ -444,6 +444,7 @@ CPP_TEST_CASES += \ template_ns_enum2 \ template_ns_inherit \ template_ns_scope \ + template_parameters_global_scope \ template_partial_arg \ template_partial_specialization \ template_partial_specialization_typedef \ diff --git a/Examples/test-suite/java/cpp11_template_typedefs_runme.java b/Examples/test-suite/java/cpp11_template_typedefs_runme.java new file mode 100644 index 000000000..473e7cf07 --- /dev/null +++ b/Examples/test-suite/java/cpp11_template_typedefs_runme.java @@ -0,0 +1,19 @@ +import cpp11_template_typedefs.*; + +public class cpp11_template_typedefs_runme { + + static { + try { + System.loadLibrary("cpp11_template_typedefs"); + } 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[]) { + int alloc1 = cpp11_template_typedefs.get_bucket_allocator1(); + int alloc2 = cpp11_template_typedefs.get_bucket_allocator2(); + } +} + diff --git a/Examples/test-suite/java/template_parameters_global_scope_runme.java b/Examples/test-suite/java/template_parameters_global_scope_runme.java new file mode 100644 index 000000000..a536fe476 --- /dev/null +++ b/Examples/test-suite/java/template_parameters_global_scope_runme.java @@ -0,0 +1,75 @@ +import template_parameters_global_scope.*; + +public class template_parameters_global_scope_runme { + + static { + try { + System.loadLibrary("template_parameters_global_scope"); + } 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[]) { + + int alloc = 0; + + // Check 1 + alloc = template_parameters_global_scope.Bucket1(); + alloc = template_parameters_global_scope.Bucket2(); + alloc = template_parameters_global_scope.Bucket3(); + alloc = template_parameters_global_scope.Bucket4(); + alloc = template_parameters_global_scope.Bucket5(); + alloc = template_parameters_global_scope.Bucket6(); + + // Check 2 + alloc = template_parameters_global_scope.Spade1(); + alloc = template_parameters_global_scope.Spade2(); + alloc = template_parameters_global_scope.Spade3(); + alloc = template_parameters_global_scope.Spade4(); + alloc = template_parameters_global_scope.Spade5(); + alloc = template_parameters_global_scope.Spade6(); + + // Check 3 + alloc = template_parameters_global_scope.Ball1(); + alloc = template_parameters_global_scope.Ball2(); + alloc = template_parameters_global_scope.Ball3(); + alloc = template_parameters_global_scope.Ball4(); + alloc = template_parameters_global_scope.Ball5(); + alloc = template_parameters_global_scope.Ball6(); + + // Check 4 + alloc = template_parameters_global_scope.Bat1(); + alloc = template_parameters_global_scope.Bat2(); + alloc = template_parameters_global_scope.Bat3(); + alloc = template_parameters_global_scope.Bat4(); + alloc = template_parameters_global_scope.Bat5(); + alloc = template_parameters_global_scope.Bat6(); + + // Check 5 + alloc = template_parameters_global_scope.Chair1(); + alloc = template_parameters_global_scope.Chair2(); + alloc = template_parameters_global_scope.Chair3(); + alloc = template_parameters_global_scope.Chair4(); + alloc = template_parameters_global_scope.Chair5(); + alloc = template_parameters_global_scope.Chair6(); + + // Check 6 + alloc = template_parameters_global_scope.Table1(); + alloc = template_parameters_global_scope.Table2(); + alloc = template_parameters_global_scope.Table3(); + alloc = template_parameters_global_scope.Table4(); + alloc = template_parameters_global_scope.Table5(); + alloc = template_parameters_global_scope.Table6(); + + /* + alloc = template_parameters_global_scope.rejig1(); + alloc = template_parameters_global_scope.rejig2(); + alloc = template_parameters_global_scope.rejig3(); + alloc = template_parameters_global_scope.rejig4(); + alloc = template_parameters_global_scope.rejig5(); + alloc = template_parameters_global_scope.rejig6(); + */ + } +} diff --git a/Examples/test-suite/template_parameters_global_scope.i b/Examples/test-suite/template_parameters_global_scope.i new file mode 100644 index 000000000..4c14ba4a3 --- /dev/null +++ b/Examples/test-suite/template_parameters_global_scope.i @@ -0,0 +1,133 @@ +%module template_parameters_global_scope + +%inline %{ +namespace Alloc { + template struct Rebind { + typedef int Integer; + }; +} +%} + +%inline %{ +struct Bucket {}; +typedef Bucket TDBucket; +typedef ::Bucket TDGlobalBucket; +%} + +// Check 1: %template no unary scope operator +%template(RebindBucket) Alloc::Rebind< Bucket >; + +%inline %{ +Alloc::Rebind< Bucket >::Integer Bucket1() { return 1; } +Alloc::Rebind< ::Bucket >::Integer Bucket2() { return 2; } +Alloc::Rebind< TDBucket >::Integer Bucket3() { return 3; } +Alloc::Rebind< ::TDBucket >::Integer Bucket4() { return 4; } +Alloc::Rebind< TDGlobalBucket >::Integer Bucket5() { return 5; } +Alloc::Rebind< ::TDGlobalBucket >::Integer Bucket6() { return 6; } +%} + +// Check 2: %template with unary scope operator +%inline %{ +struct Spade {}; +typedef Spade TDSpade; +typedef ::Spade TDGlobalSpade; +%} +%template(RebindSpade) Alloc::Rebind< ::Spade >; + +%inline %{ +Alloc::Rebind< Spade >::Integer Spade1() { return 1; } +Alloc::Rebind< ::Spade >::Integer Spade2() { return 2; } +Alloc::Rebind< TDSpade >::Integer Spade3() { return 3; } +Alloc::Rebind< ::TDSpade >::Integer Spade4() { return 4; } +Alloc::Rebind< TDGlobalSpade >::Integer Spade5() { return 5; } +Alloc::Rebind< ::TDGlobalSpade >::Integer Spade6() { return 6; } +%} + +// Check 3: %template typedef no unary scope operator +%inline %{ +struct Ball {}; +typedef Ball TDBall; +typedef ::Ball TDGlobalBall; +%} +%template(RebindBall) Alloc::Rebind< TDBall >; + +%inline %{ +Alloc::Rebind< Ball >::Integer Ball1() { return 1; } +Alloc::Rebind< ::Ball >::Integer Ball2() { return 2; } +Alloc::Rebind< TDBall >::Integer Ball3() { return 3; } +Alloc::Rebind< ::TDBall >::Integer Ball4() { return 4; } +Alloc::Rebind< TDGlobalBall >::Integer Ball5() { return 5; } +Alloc::Rebind< ::TDGlobalBall >::Integer Ball6() { return 6; } +%} + +// Check 4: %template typedef with unary scope operator +%inline %{ +struct Bat {}; +typedef Bat TDBat; +typedef ::Bat TDGlobalBat; +%} +%template(RebindBat) Alloc::Rebind< ::TDBat >; + +%inline %{ +Alloc::Rebind< Bat >::Integer Bat1() { return 1; } +Alloc::Rebind< ::Bat >::Integer Bat2() { return 2; } +Alloc::Rebind< TDBat >::Integer Bat3() { return 3; } +Alloc::Rebind< ::TDBat >::Integer Bat4() { return 4; } +Alloc::Rebind< TDGlobalBat >::Integer Bat5() { return 5; } +Alloc::Rebind< ::TDGlobalBat >::Integer Bat6() { return 6; } +%} + +// Check 5: %template double typedef no unary scope operator +%inline %{ +struct Chair {}; +typedef Chair TDChair; +typedef ::Chair TDGlobalChair; +%} +%template(RebindChair) Alloc::Rebind< TDGlobalChair >; + +%inline %{ +Alloc::Rebind< Chair >::Integer Chair1() { return 1; } +Alloc::Rebind< ::Chair >::Integer Chair2() { return 2; } +Alloc::Rebind< TDChair >::Integer Chair3() { return 3; } +Alloc::Rebind< ::TDChair >::Integer Chair4() { return 4; } +Alloc::Rebind< TDGlobalChair >::Integer Chair5() { return 5; } +Alloc::Rebind< ::TDGlobalChair >::Integer Chair6() { return 6; } +%} + +// Check 6: %template double typedef with unary scope operator +%inline %{ +struct Table {}; +typedef Table TDTable; +typedef ::Table TDGlobalTable; +%} +%template(RebindTable) Alloc::Rebind< ::TDGlobalTable >; + +%inline %{ +Alloc::Rebind< Table >::Integer Table1() { return 1; } +Alloc::Rebind< ::Table >::Integer Table2() { return 2; } +Alloc::Rebind< TDTable >::Integer Table3() { return 3; } +Alloc::Rebind< ::TDTable >::Integer Table4() { return 4; } +Alloc::Rebind< TDGlobalTable >::Integer Table5() { return 5; } +Alloc::Rebind< ::TDGlobalTable >::Integer Table6() { return 6; } +%} + +#if 0 +%inline %{ +namespace Alloc { + template struct Rejig { + typedef int Integer; + }; +} +%} + +%template(RejigSpade) Alloc::Rejig<::Spade>; + +%inline %{ +Alloc::Rejig<>::Integer rejig1() { return 1; } +Alloc::Rejig< ::Spade >::Integer rejig2() { return 2; } +Alloc::Rejig< ::TDSpade >::Integer rejig3() { return 3; } +Alloc::Rejig< ::TDSpade >::Integer rejig4() { return 4; } +Alloc::Rejig< TDGlobalSpade >::Integer rejig5() { return 5; } +Alloc::Rejig< ::TDGlobalSpade >::Integer rejig6() { return 6; } +%} +#endif diff --git a/Source/Swig/typesys.c b/Source/Swig/typesys.c index e11fc781a..40155591c 100644 --- a/Source/Swig/typesys.c +++ b/Source/Swig/typesys.c @@ -248,10 +248,26 @@ void SwigType_new_scope(const_String_or_char_ptr name) { ttab = NewHash(); Setattr(s, "typetab", ttab); - /* Build fully qualified name and */ + /* Build fully qualified name */ qname = SwigType_scope_name(s); +#if 1 + { + /* TODO: only do with templates? What happens with non-templates with code below? */ + String *stripped_qname; + stripped_qname = SwigType_remove_global_scope_prefix(qname); + /* Use fully qualified name for hash key without unary scope prefix, qname may contain unary scope */ + Setattr(scopes, stripped_qname, s); + Setattr(s, "qname", qname); + /* + Printf(stdout, "SwigType_new_scope stripped %s %s\n", qname, stripped_qname); + */ + Delete(stripped_qname); + } +#else + Printf(stdout, "SwigType_new_scope %s\n", qname); Setattr(scopes, qname, s); Setattr(s, "qname", qname); +#endif Delete(qname); current_scope = s; @@ -418,12 +434,14 @@ static Typetab *SwigType_find_scope(Typetab *s, const SwigType *nameprefix) { Typetab *s_orig = s; String *nnameprefix = 0; static int check_parent = 1; + int is_template = 0; if (Getmark(s)) return 0; Setmark(s, 1); - if (SwigType_istemplate(nameprefix)) { + is_template = SwigType_istemplate(nameprefix); + if (is_template) { nnameprefix = SwigType_typedef_resolve_all(nameprefix); nameprefix = nnameprefix; } @@ -437,10 +455,12 @@ static Typetab *SwigType_find_scope(Typetab *s, const SwigType *nameprefix) { } else { full = NewString(nameprefix); } - if (Getattr(scopes, full)) { - s = Getattr(scopes, full); - } else { - s = 0; + s = Getattr(scopes, full); + if (!s && is_template) { + /* try look up scope with all the unary scope operators within the template parameter list removed */ + SwigType *full_stripped = SwigType_remove_global_scope_prefix(full); + s = Getattr(scopes, full_stripped); + Delete(full_stripped); } Delete(full); if (s) { @@ -911,6 +931,9 @@ SwigType *SwigType_typedef_resolve_all(const SwigType *t) { return Copy(r); } +#ifdef SWIG_DEBUG + Printf(stdout, "SwigType_typedef_resolve_all start ... %s\n", t); +#endif /* Recursively resolve the typedef */ r = NewString(t); while ((n = SwigType_typedef_resolve(r))) { @@ -931,6 +954,9 @@ SwigType *SwigType_typedef_resolve_all(const SwigType *t) { Delete(key); Delete(rr); } +#ifdef SWIG_DEBUG + Printf(stdout, "SwigType_typedef_resolve_all end === %s => %s\n", t, r); +#endif return r; } From 8bf3a342c2293d7c621076d26a6245bf5bbbbcb6 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Wed, 26 Jul 2017 18:54:54 +0100 Subject: [PATCH 229/455] Minor code optimisation in template_parameters_resolve --- Source/Swig/typesys.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/Source/Swig/typesys.c b/Source/Swig/typesys.c index 40155591c..3bb776a2c 100644 --- a/Source/Swig/typesys.c +++ b/Source/Swig/typesys.c @@ -594,14 +594,15 @@ static String *template_parameters_resolve(const String *base) { if ((i + 1) < sz) Append(type, ","); } - Append(type, ")>"); - Append(type, suffix); - Delete(suffix); - Delete(tparms); - if (!rep) { + if (rep) { + Append(type, ")>"); + Append(type, suffix); + } else { Delete(type); type = 0; } + Delete(suffix); + Delete(tparms); return type; } From 2681bbad366b8dfc1ed9aa599dcb14ed8684733d Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Wed, 26 Jul 2017 19:48:46 +0100 Subject: [PATCH 230/455] Improve description of template_parameters_resolve --- Source/Swig/typesys.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/Source/Swig/typesys.c b/Source/Swig/typesys.c index 3bb776a2c..2fb514d5e 100644 --- a/Source/Swig/typesys.c +++ b/Source/Swig/typesys.c @@ -561,8 +561,11 @@ static SwigType *_typedef_resolve(Typetab *s, String *base, int look_parent) { /* ----------------------------------------------------------------------------- * template_parameters_resolve() * - * For use with templates only. The template parameters are resolved. If none - * of the parameters can be resolved, zero is returned. + * For use with templates only. Attempts to resolve one template parameter. + * + * If one of the template parameters can be resolved, the type is returned with + * just the one parameter resolved and the remaining parameters left as is. + * If none of the template parameters can be resolved, zero is returned. * ----------------------------------------------------------------------------- */ static String *template_parameters_resolve(const String *base) { From 8753f9652ccc91f0aa080efff15207a4fa33c8ec Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Sun, 30 Jul 2017 13:09:02 +0100 Subject: [PATCH 231/455] Namespace documentation minor corrections --- Doc/Manual/SWIGPlus.html | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Doc/Manual/SWIGPlus.html b/Doc/Manual/SWIGPlus.html index 3e7860b9b..b22f1c279 100644 --- a/Doc/Manual/SWIGPlus.html +++ b/Doc/Manual/SWIGPlus.html @@ -3915,6 +3915,8 @@ then SWIG simply creates three wrapper functions bar(), spam(), and blah() in the target language. SWIG does not prepend the names with a namespace prefix nor are the functions packaged in any kind of nested scope. +Note that the default handling of flattening all the namespace scopes in the target language +can be changed via the nspace feature.

@@ -4203,9 +4205,7 @@ namespace foo {

Note: The flattening of namespaces is only intended to serve as a basic namespace implementation. -None of the target language modules are currently programmed -with any namespace awareness. In the future, language modules may or may not provide -more advanced namespace support. +More advanced handling of namespaces is discussed next.

6.19.1 The nspace feature for namespaces

From 7ee76f93f99e01c9fb5de0bd91ab16178519f18c Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Sun, 30 Jul 2017 13:41:45 +0100 Subject: [PATCH 232/455] More consistent formatting of examples in documentation --- Doc/Manual/Java.html | 4 +-- Doc/Manual/Lua.html | 18 ++++++------ Doc/Manual/Perl5.html | 6 ++-- Doc/Manual/Php.html | 6 ++-- Doc/Manual/Python.html | 37 ++++++++++++------------ Doc/Manual/SWIG.html | 20 ++++++------- Doc/Manual/SWIGPlus.html | 62 ++++++++++++++++++++-------------------- Doc/Manual/Scilab.html | 26 ++++++++--------- Doc/Manual/Tcl.html | 16 +++++------ 9 files changed, 96 insertions(+), 99 deletions(-) diff --git a/Doc/Manual/Java.html b/Doc/Manual/Java.html index e0178465c..e21440ee9 100644 --- a/Doc/Manual/Java.html +++ b/Doc/Manual/Java.html @@ -5278,7 +5278,7 @@ void * operator new(size_t t) { throw bad_alloc(); pJalloc->ref = 0; return static_cast<void *>( - static_cast<char *>(static_cast<void *>(pJalloc)) + sizeof(Jalloc)); + static_cast<char *>(static_cast<void *>(pJalloc)) + sizeof(Jalloc)); } } @@ -7240,7 +7240,7 @@ public class runme { example.print_args(animals); String args[] = example.get_args(); for (int i=0; i<args.length; i++) - System.out.println(i + ":" + args[i]); + System.out.println(i + ":" + args[i]); } }
diff --git a/Doc/Manual/Lua.html b/Doc/Manual/Lua.html index c94fe31dc..c5c944225 100644 --- a/Doc/Manual/Lua.html +++ b/Doc/Manual/Lua.html @@ -1008,11 +1008,10 @@ The following operators cannot be overloaded (mainly because they are not suppor

SWIG also accepts the __str__() member function which converts an object to a string. This function should return a const char*, preferably to static memory. This will be used for the print() and tostring() functions in Lua. Assuming the complex class has a function

-
const char* __str__()
-{
-        static char buffer[255];
-        sprintf(buffer, "Complex(%g, %g)", this->re(), this->im());
-        return buffer;
+
const char* __str__() {
+  static char buffer[255];
+  sprintf(buffer, "Complex(%g, %g)", this->re(), this->im());
+  return buffer;
 }
 

@@ -1031,11 +1030,10 @@ Complex(10, 12)

It is also possible to overload the operator[], but currently this cannot be automatically performed. To overload the operator[] you need to provide two functions, __getitem__() and __setitem__()

-
class Complex
-{
-        //....
-        double __getitem__(int i)const; // i is the index, returns the data
-        void __setitem__(int i, double d); // i is the index, d is the data
+
class Complex {
+  //....
+  double __getitem__(int i)const; // i is the index, returns the data
+  void __setitem__(int i, double d); // i is the index, d is the data
 };
 

diff --git a/Doc/Manual/Perl5.html b/Doc/Manual/Perl5.html index 96e9f7517..03f2c7048 100644 --- a/Doc/Manual/Perl5.html +++ b/Doc/Manual/Perl5.html @@ -3279,9 +3279,9 @@ suffice in most cases:

 %feature("director:except") {
-    if ($error != NULL) {
-        throw Swig::DirectorMethodException();
-    }
+  if ($error != NULL) {
+    throw Swig::DirectorMethodException();
+  }
 }
 
diff --git a/Doc/Manual/Php.html b/Doc/Manual/Php.html index 7d3d33ac1..c4ba2e3f8 100644 --- a/Doc/Manual/Php.html +++ b/Doc/Manual/Php.html @@ -1175,9 +1175,9 @@ should suffice in most cases:
 %feature("director:except") {
-    if ($error == FAILURE) {
-        throw Swig::DirectorMethodException();
-    }
+  if ($error == FAILURE) {
+    throw Swig::DirectorMethodException();
+  }
 }
 
diff --git a/Doc/Manual/Python.html b/Doc/Manual/Python.html index 1b73c08b7..169151d47 100644 --- a/Doc/Manual/Python.html +++ b/Doc/Manual/Python.html @@ -226,16 +226,15 @@ resulting C file should be built as a python extension, inserting the module #include "example.h" int fact(int n) { - if (n < 0){ /* This should probably return an error, but this is simpler */ - return 0; - } - if (n == 0) { - return 1; - } - else { - /* testing for overflow would be a good idea here */ - return n * fact(n-1); - } + if (n < 0) { /* This should probably return an error, but this is simpler */ + return 0; + } + if (n == 0) { + return 1; + } else { + /* testing for overflow would be a good idea here */ + return n * fact(n-1); + } }
@@ -3133,9 +3132,9 @@ suffice in most cases:
 %feature("director:except") {
-    if ($error != NULL) {
-        throw Swig::DirectorMethodException();
-    }
+  if ($error != NULL) {
+    throw Swig::DirectorMethodException();
+  }
 }
 
@@ -4142,11 +4141,11 @@ Sometimes a C function expects an array to be passed as a pointer. For example,
 int sumitems(int *first, int nitems) {
-    int i, sum = 0;
-    for (i = 0; i < nitems; i++) {
-        sum += first[i];
-    }
-    return sum;
+  int i, sum = 0;
+  for (i = 0; i < nitems; i++) {
+    sum += first[i];
+  }
+  return sum;
 }
 
@@ -6526,7 +6525,7 @@ string that cannot be completely decoded as UTF-8: %inline %{ const char* non_utf8_c_str(void) { - return "h\xe9llo w\xc3\xb6rld"; + return "h\xe9llo w\xc3\xb6rld"; } %} diff --git a/Doc/Manual/SWIG.html b/Doc/Manual/SWIG.html index e5b441fbb..b1cb1b4dd 100644 --- a/Doc/Manual/SWIG.html +++ b/Doc/Manual/SWIG.html @@ -1266,12 +1266,12 @@ pointers. As a result, SWIG creates a wrapper like this:
 Vector *wrap_cross_product(Vector *v1, Vector *v2) {
-        Vector x = *v1;
-        Vector y = *v2;
-        Vector *result;
-        result = (Vector *) malloc(sizeof(Vector));
-        *(result) = cross(x, y);
-        return result;
+  Vector x = *v1;
+  Vector y = *v2;
+  Vector *result;
+  result = (Vector *) malloc(sizeof(Vector));
+  *(result) = cross(x, y);
+  return result;
 }
 
@@ -1280,10 +1280,10 @@ or if SWIG was run with the -c++ option:

 Vector *wrap_cross(Vector *v1, Vector *v2) {
-        Vector x = *v1;
-        Vector y = *v2;
-        Vector *result = new Vector(cross(x, y)); // Uses default copy constructor
-        return result;
+  Vector x = *v1;
+  Vector y = *v2;
+  Vector *result = new Vector(cross(x, y)); // Uses default copy constructor
+  return result;
 }
 
diff --git a/Doc/Manual/SWIGPlus.html b/Doc/Manual/SWIGPlus.html index b22f1c279..5841c7d43 100644 --- a/Doc/Manual/SWIGPlus.html +++ b/Doc/Manual/SWIGPlus.html @@ -2958,29 +2958,29 @@ To illustrate, consider the following template definition:
 template<class T> class List {
 private:
-    T *data;
-    int nitems;
-    int maxitems;
+  T *data;
+  int nitems;
+  int maxitems;
 public:
-    List(int max) {
-      data = new T [max];
-      nitems = 0;
-      maxitems = max;
-    }
-    ~List() {
-      delete [] data;
-    };
-    void append(T obj) {
-      if (nitems < maxitems) {
-        data[nitems++] = obj;
-      }
-    }
-    int length() {
-      return nitems;
-    }
-    T get(int n) {
-      return data[n];
+  List(int max) {
+    data = new T [max];
+    nitems = 0;
+    maxitems = max;
+  }
+  ~List() {
+    delete [] data;
+  };
+  void append(T obj) {
+    if (nitems < maxitems) {
+      data[nitems++] = obj;
     }
+  }
+  int length() {
+    return nitems;
+  }
+  T get(int n) {
+    return data[n];
+  }
 };
 
@@ -3704,10 +3704,10 @@ template <class T> class OuterTemplateClass {}; // Don't forget to use %feature("flatnested") for OuterClass::InnerStruct and // OuterClass::InnerClass if the target language doesn't support nested classes. class OuterClass { - public: - // Forward declarations: - struct InnerStruct; - class InnerClass; + public: + // Forward declarations: + struct InnerStruct; + class InnerClass; }; struct OuterClass::InnerStruct {}; @@ -4533,13 +4533,13 @@ around some other class. For example:
 // Smart-pointer class
 template<class T> class SmartPtr {
-    T *pointee;
+  T *pointee;
 public:
-    SmartPtr(T *p) : pointee(p) { ... }
-    T *operator->() {
-        return pointee;
-    }
-    ...
+  SmartPtr(T *p) : pointee(p) { ... }
+  T *operator->() {
+    return pointee;
+  }
+  ...
 };
 
 // Ordinary class
diff --git a/Doc/Manual/Scilab.html b/Doc/Manual/Scilab.html
index 14e03ff18..aef06e302 100644
--- a/Doc/Manual/Scilab.html
+++ b/Doc/Manual/Scilab.html
@@ -121,15 +121,15 @@ In this example we bind from C a function and a global variable into Scilab. The
 double Foo = 3.0;
 
 int fact(int n) {
-    if (n < 0) {
-        return 0;
-    }
-    else if (n == 0) {
-        return 1;
-    }
-    else {
-        return n * fact(n-1);
-    }
+  if (n < 0) {
+    return 0;
+  }
+  else if (n == 0) {
+    return 1;
+  }
+  else {
+    return n * fact(n-1);
+  }
 }
 %}
 
@@ -896,8 +896,8 @@ Let's see it on an example of a struct with two members: %inline %{ typedef struct { - int x; - int arr[4]; + int x; + int arr[4]; } Foo; %} @@ -1143,11 +1143,11 @@ As explained in 6.15 SWI %module example void magnify(Square *square, double factor) { - square->size *= factor; + square->size *= factor; }; void magnify(Circle *circle, double factor) { - square->radius *= factor; + square->radius *= factor; };
diff --git a/Doc/Manual/Tcl.html b/Doc/Manual/Tcl.html index 38d4103e0..31408b312 100644 --- a/Doc/Manual/Tcl.html +++ b/Doc/Manual/Tcl.html @@ -3215,28 +3215,28 @@ helper functions to access arrays : %inline %{ double *new_double(int size) { - return (double *) malloc(size*sizeof(double)); + return (double *) malloc(size*sizeof(double)); } void delete_double(double *a) { - free(a); + free(a); } double get_double(double *a, int index) { - return a[index]; + return a[index]; } void set_double(double *a, int index, double val) { - a[index] = val; + a[index] = val; } int *new_int(int size) { - return (int *) malloc(size*sizeof(int)); + return (int *) malloc(size*sizeof(int)); } void delete_int(int *a) { - free(a); + free(a); } int get_int(int *a, int index) { - return a[index]; + return a[index]; } int set_int(int *a, int index, int val) { - a[index] = val; + a[index] = val; } %} From 8052211ac586e691c75bde7814803add8fe1b32f Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Sun, 30 Jul 2017 13:56:47 +0100 Subject: [PATCH 233/455] More consistent formatting of examples in documentation --- Doc/Manual/CSharp.html | 40 ++++++++++++------------ Doc/Manual/Customization.html | 2 +- Doc/Manual/Extending.html | 58 +++++++++++++++++------------------ Doc/Manual/Java.html | 22 ++++++------- Doc/Manual/Perl5.html | 5 ++- Doc/Manual/SWIGPlus.html | 26 ++++++++-------- 6 files changed, 76 insertions(+), 77 deletions(-) diff --git a/Doc/Manual/CSharp.html b/Doc/Manual/CSharp.html index 5be63a340..d618f5a08 100644 --- a/Doc/Manual/CSharp.html +++ b/Doc/Manual/CSharp.html @@ -997,9 +997,9 @@ When the following C# code is executed:
 public class runme {
-    static void Main() {
-      example.positivesonly(-1);
-    }
+  static void Main() {
+    example.positivesonly(-1);
+  }
 }
 
@@ -1846,12 +1846,12 @@ and the following usage from C# after running the code through SWIG:
-      Wheel wheel = new Bike(10).getWheel();
-      Console.WriteLine("wheel size: " + wheel.size);
-      // Simulate a garbage collection
-      global::System.GC.Collect();
-      global::System.GC.WaitForPendingFinalizers();
-      global::System.Console.WriteLine("wheel size: " + wheel.size);
+  Wheel wheel = new Bike(10).getWheel();
+  Console.WriteLine("wheel size: " + wheel.size);
+  // Simulate a garbage collection
+  global::System.GC.Collect();
+  global::System.GC.WaitForPendingFinalizers();
+  global::System.Console.WriteLine("wheel size: " + wheel.size);
 
@@ -1980,9 +1980,9 @@ and more or less equivalent usage from C#
-      Container container = new Container();
-      Element element = new Element(20);
-      container.setElement(element);
+  Container container = new Container();
+  Element element = new Element(20);
+  container.setElement(element);
 
@@ -1993,14 +1993,14 @@ In order to understand why, consider a garbage collection occuring...
-      Container container = new Container();
-      Element element = new Element(20);
-      container.setElement(element);
-      Console.WriteLine("element.value: " + container.getElement().value);
-      // Simulate a garbage collection
-      global::System.GC.Collect();
-      global::System.GC.WaitForPendingFinalizers();
-      global::System.Console.WriteLine("element.value: " + container.getElement().value);
+  Container container = new Container();
+  Element element = new Element(20);
+  container.setElement(element);
+  Console.WriteLine("element.value: " + container.getElement().value);
+  // Simulate a garbage collection
+  global::System.GC.Collect();
+  global::System.GC.WaitForPendingFinalizers();
+  global::System.Console.WriteLine("element.value: " + container.getElement().value);
 
diff --git a/Doc/Manual/Customization.html b/Doc/Manual/Customization.html index 0e5fb2869..e5040fc9b 100644 --- a/Doc/Manual/Customization.html +++ b/Doc/Manual/Customization.html @@ -516,7 +516,7 @@ The special variables are often used in situations where method calls are logged $action } catch (MemoryError) { - croak("Out of memory in $decl"); + croak("Out of memory in $decl"); } } void log(const char *message); diff --git a/Doc/Manual/Extending.html b/Doc/Manual/Extending.html index bf70b69ac..c225d9554 100644 --- a/Doc/Manual/Extending.html +++ b/Doc/Manual/Extending.html @@ -2592,36 +2592,36 @@ command line options, simply use code similar to this:
 void Language::main(int argc, char *argv[]) {
   for (int i = 1; i < argc; i++) {
-      if (argv[i]) {
-          if (strcmp(argv[i], "-interface") == 0) {
-            if (argv[i+1]) {
-              interface = NewString(argv[i+1]);
-              Swig_mark_arg(i);
-              Swig_mark_arg(i+1);
-              i++;
-            } else {
-              Swig_arg_error();
-            }
-          } else if (strcmp(argv[i], "-globals") == 0) {
-            if (argv[i+1]) {
-              global_name = NewString(argv[i+1]);
-              Swig_mark_arg(i);
-              Swig_mark_arg(i+1);
-              i++;
-            } else {
-              Swig_arg_error();
-            }
-          } else if ((strcmp(argv[i], "-proxy") == 0)) {
-            proxy_flag = 1;
-            Swig_mark_arg(i);
-          } else if (strcmp(argv[i], "-keyword") == 0) {
-            use_kw = 1;
-            Swig_mark_arg(i);
-          } else if (strcmp(argv[i], "-help") == 0) {
-            fputs(usage, stderr);
-          }
-          ...
+    if (argv[i]) {
+      if (strcmp(argv[i], "-interface") == 0) {
+        if (argv[i+1]) {
+          interface = NewString(argv[i+1]);
+          Swig_mark_arg(i);
+          Swig_mark_arg(i+1);
+          i++;
+        } else {
+          Swig_arg_error();
+        }
+      } else if (strcmp(argv[i], "-globals") == 0) {
+        if (argv[i+1]) {
+          global_name = NewString(argv[i+1]);
+          Swig_mark_arg(i);
+          Swig_mark_arg(i+1);
+          i++;
+        } else {
+          Swig_arg_error();
+        }
+      } else if ((strcmp(argv[i], "-proxy") == 0)) {
+        proxy_flag = 1;
+        Swig_mark_arg(i);
+      } else if (strcmp(argv[i], "-keyword") == 0) {
+        use_kw = 1;
+        Swig_mark_arg(i);
+      } else if (strcmp(argv[i], "-help") == 0) {
+        fputs(usage, stderr);
       }
+      ...
+    }
   }
 }
 
diff --git a/Doc/Manual/Java.html b/Doc/Manual/Java.html index e21440ee9..928adce67 100644 --- a/Doc/Manual/Java.html +++ b/Doc/Manual/Java.html @@ -3935,9 +3935,9 @@ where Swig::DirectorException::raise is a helper method in the Director
-    static void raise(JNIEnv *jenv, jthrowable throwable) {
-      throw DirectorException(jenv, throwable);
-    }
+  static void raise(JNIEnv *jenv, jthrowable throwable) {
+    throw DirectorException(jenv, throwable);
+  }
 
@@ -4335,16 +4335,16 @@ struct Vector { %extend Vector { char *toString() { - static char tmp[1024]; - sprintf(tmp, "Vector(%g, %g, %g)", $self->x, $self->y, $self->z); - return tmp; + static char tmp[1024]; + sprintf(tmp, "Vector(%g, %g, %g)", $self->x, $self->y, $self->z); + return tmp; } Vector(double x, double y, double z) { - Vector *v = (Vector *) malloc(sizeof(Vector)); - v->x = x; - v->y = y; - v->z = z; - return v; + Vector *v = (Vector *) malloc(sizeof(Vector)); + v->x = x; + v->y = y; + v->z = z; + return v; } };
diff --git a/Doc/Manual/Perl5.html b/Doc/Manual/Perl5.html index 03f2c7048..5e9a9e33e 100644 --- a/Doc/Manual/Perl5.html +++ b/Doc/Manual/Perl5.html @@ -1633,9 +1633,8 @@ class DoubleArray { void setitem(int i, double val) { if ((i >= 0) && (i < n)) ptr[i] = val; - else { + else throw RangeError(); - } } };
@@ -2985,7 +2984,7 @@ sub set_transform for (my $j = 0; $j < 4, $j++) { mat44_set($a, $i, $j, $x->[i][j]) - } + } } example.set_transform($im, $a); free_mat44($a); diff --git a/Doc/Manual/SWIGPlus.html b/Doc/Manual/SWIGPlus.html index 5841c7d43..3d8263e37 100644 --- a/Doc/Manual/SWIGPlus.html +++ b/Doc/Manual/SWIGPlus.html @@ -346,8 +346,8 @@ public: class Spam { public: - Foo *value; - ... + Foo *value; + ... }; @@ -726,7 +726,7 @@ public: class Grok : public Bar { public: - Grok(); // Not wrapped. No implementation of abstract spam(). + Grok(); // Not wrapped. No implementation of abstract spam(). }; @@ -4915,19 +4915,19 @@ base classes. For example:
 class Foo {
 public:
-      int  blah(int x);
+  int  blah(int x);
 };
 
 class Bar {
 public:
-      double blah(double x);
+  double blah(double x);
 };
 
 class FooBar : public Foo, public Bar {
 public:
-      using Foo::blah;  
-      using Bar::blah;
-      char *blah(const char *x);
+  using Foo::blah;
+  using Bar::blah;
+  char *blah(const char *x);
 };
 
@@ -5008,14 +5008,14 @@ correctly, you can always change the interface to the following: class FooBar : public Foo, public Bar { public: #ifndef SWIG - using Foo::blah; - using Bar::blah; + using Foo::blah; + using Bar::blah; #else - int blah(int x); // explicitly tell SWIG about other declarations - double blah(double x); + int blah(int x); // explicitly tell SWIG about other declarations + double blah(double x); #endif - char *blah(const char *x); + char *blah(const char *x); }; From ba45861b462e91e266456f510036768c2aa55be5 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Sun, 30 Jul 2017 16:49:21 +0100 Subject: [PATCH 234/455] More consistent formatting of examples in documentation --- Doc/Manual/Go.html | 4 +- Doc/Manual/SWIG.html | 16 ++--- Doc/Manual/SWIGPlus.html | 148 +++++++++++++++++++-------------------- 3 files changed, 84 insertions(+), 84 deletions(-) diff --git a/Doc/Manual/Go.html b/Doc/Manual/Go.html index f25e9850b..820921bd5 100644 --- a/Doc/Manual/Go.html +++ b/Doc/Manual/Go.html @@ -639,12 +639,12 @@ public: virtual ~FooBarAbstract() {}; std::string FooBar() { - return this->Foo() + ", " + this->Bar(); + return this->Foo() + ", " + this->Bar(); }; protected: virtual std::string Foo() { - return "Foo"; + return "Foo"; }; virtual std::string Bar() = 0; diff --git a/Doc/Manual/SWIG.html b/Doc/Manual/SWIG.html index b1cb1b4dd..cff4e7dc2 100644 --- a/Doc/Manual/SWIG.html +++ b/Doc/Manual/SWIG.html @@ -1043,14 +1043,14 @@ expect :

 # Copy a file 
 def filecopy(source, target):
-  f1 = fopen(source, "r")
-  f2 = fopen(target, "w")
-  buffer = malloc(8192)
-  nbytes = fread(buffer, 8192, 1, f1)
-  while (nbytes > 0):
-    fwrite(buffer, 8192, 1, f2)
-          nbytes = fread(buffer, 8192, 1, f1)
-  free(buffer)
+    f1 = fopen(source, "r")
+    f2 = fopen(target, "w")
+    buffer = malloc(8192)
+    nbytes = fread(buffer, 8192, 1, f1)
+    while (nbytes > 0):
+        fwrite(buffer, 8192, 1, f2)
+            nbytes = fread(buffer, 8192, 1, f1)
+    free(buffer)
 

diff --git a/Doc/Manual/SWIGPlus.html b/Doc/Manual/SWIGPlus.html index 3d8263e37..87fe30fa8 100644 --- a/Doc/Manual/SWIGPlus.html +++ b/Doc/Manual/SWIGPlus.html @@ -777,9 +777,9 @@ the normal constructor function. For example, if you have this:

 class List {
 public:
-    List();    
-    List(const List &);      // Copy constructor
-    ...
+  List();    
+  List(const List &);      // Copy constructor
+  ...
 };
 
@@ -803,7 +803,7 @@ through a special function like this:
 List *copy_List(List *f) {
-    return new List(*f);
+  return new List(*f);
 }
 
@@ -832,7 +832,7 @@ However, copy constructor wrappers can be generated if using the copyctor
@@ -851,9 +851,9 @@ could be wrapped, but they had to be renamed. For example:
 class Foo {
 public:
-    Foo();
+  Foo();
   %name(CopyFoo) Foo(const Foo &);
-    ...
+  ...
 };
 
@@ -969,8 +969,8 @@ not primitive types, such as classes. For instance, if you had another class lik
 class Foo {
 public:
-    List items;
-    ...
+  List items;
+  ...
 
@@ -982,10 +982,10 @@ For example:
 List *Foo_items_get(Foo *self) {
-    return &self->items;
+  return &self->items;
 }
 void Foo_items_set(Foo *self, List *value) {
-    self->items = *value;
+  self->items = *value;
 }
 
@@ -1007,10 +1007,10 @@ It is the naturalvar feature and can be used to effectively change the way acces
 const List &Foo_items_get(Foo *self) {
-    return self->items;
+  return self->items;
 }
 void Foo_items_set(Foo *self, const List &value) {
-    self->items = value;
+  self->items = value;
 }
 
@@ -1105,7 +1105,7 @@ SWIG will wrap all types of functions that have default arguments. For example m
 class Foo {
 public:
-    void bar(int x, int y = 3, int z = 4);
+  void bar(int x, int y = 3, int z = 4);
 };
 
@@ -1120,9 +1120,9 @@ Thus for the example above, it is as if we had instead given the following to SW
 class Foo {
 public:
-    void bar(int x, int y, int z);
-    void bar(int x, int y);
-    void bar(int x);
+  void bar(int x, int y, int z);
+  void bar(int x, int y);
+  void bar(int x);
 };
 
@@ -1158,7 +1158,7 @@ can be re-activated by using the compactdefaultargs %feature("compactdefaultargs") Foo::bar; class Foo { public: - void bar(int x, int y = 3, int z = 4); + void bar(int x, int y = 3, int z = 4); }; @@ -1485,8 +1485,8 @@ class A; %feature("valuewrapper") B; struct B { - B(); - // .... + B(); + // .... }; @@ -3000,15 +3000,15 @@ provide an expanded version of the class directly like this: %rename(intList) List<int>; // Rename to a suitable identifier class List<int> { private: - int *data; - int nitems; - int maxitems; + int *data; + int nitems; + int maxitems; public: - List(int max); - ~List(); - void append(int obj); - int length(); - int get(int n); + List(int max); + ~List(); + void append(int obj); + int length(); + int get(int n); }; @@ -3244,15 +3244,15 @@ a class like this,
 template<> class List<int> {
 private:
-    int *data;
-    int nitems;
-    int maxitems;
+  int *data;
+  int nitems;
+  int maxitems;
 public:
-    List(int max);
-    ~List();
-    void append(int obj);
-    int length();
-    int get(int n);
+  List(int max);
+  ~List();
+  void append(int obj);
+  int length();
+  int get(int n);
 };
 
@@ -3275,15 +3275,15 @@ code defines a template that is applied when the template argument is a pointer.
 template<class T> class List<T*> {
 private:
-    T *data;
-    int nitems;
-    int maxitems;
+  T *data;
+  int nitems;
+  int maxitems;
 public:
-    List(int max);
-    ~List();
-    void append(int obj);
-    int length();
-    T get(int n);
+  List(int max);
+  ~List();
+  void append(int obj);
+  int length();
+  T get(int n);
 };
 
@@ -3587,11 +3587,11 @@ It is also possible to separate these declarations from the template class. For ... template<class T> class List { - ... - public: - List() { } - T get(int index); - ... + ... + public: + List() { } + T get(int index); + ... }; @@ -3609,9 +3609,9 @@ additional methods to a specific instantiation. For example: %template(intList) List<int>; %extend List<int> { - void blah() { - printf("Hey, I'm an List<int>!\n"); - } + void blah() { + printf("Hey, I'm an List<int>!\n"); + } }; @@ -3698,7 +3698,7 @@ template <class T> class OuterTemplateClass {}; // OuterTemplateClass<OuterClass::InnerStruct> and thus the template needs // to be expanded with %template before the OuterClass declaration. %template(OuterTemplateClass_OuterClass__InnerStruct) - OuterTemplateClass<OuterClass::InnerStruct> + OuterTemplateClass<OuterClass::InnerStruct> // Don't forget to use %feature("flatnested") for OuterClass::InnerStruct and @@ -3736,7 +3736,7 @@ introduced a new class name. This name could then be used with other directives
 %template(vectori) vector<int>;
 %extend vectori {
-    void somemethod() { }
+  void somemethod() { }
 };
 
@@ -3750,7 +3750,7 @@ as the class name. For example:
 %template(vectori) vector<int>;
 %extend vector<int> {
-    void somemethod() { }
+  void somemethod() { }
 };
 
@@ -4011,7 +4011,7 @@ in a different namespace. For example:
 namespace foo {
-    template<typename T> T max(T a, T b) { return a > b ? a : b; }
+  template<typename T> T max(T a, T b) { return a > b ? a : b; }
 }
 
 using foo::max;
@@ -4020,8 +4020,8 @@ using foo::max;
 %template(maxfloat) foo::max<float>;    // Okay (qualified name).
 
 namespace bar {
-    using namespace foo;
-    %template(maxdouble)  max<double>;    // Okay.
+  using namespace foo;
+  %template(maxdouble)  max<double>;    // Okay.
 }
 
@@ -4445,10 +4445,10 @@ struct Error4 : EBase { }; class Foo { public: - ... - void bar(); - void blah() throw(Error1, Error2, Error3, Error4); - ... + ... + void bar(); + void blah() throw(Error1, Error2, Error3, Error4); + ... }; @@ -4545,8 +4545,8 @@ public: // Ordinary class class Foo_Impl { public: - int x; - virtual void bar(); + int x; + virtual void bar(); ... }; @@ -4555,13 +4555,13 @@ typedef SmartPtr<Foo_Impl> Foo; // Create smart pointer Foo Foo make_Foo() { - return SmartPtr<Foo_Impl>(new Foo_Impl()); + return SmartPtr<Foo_Impl>(new Foo_Impl()); } // Do something with smart pointer Foo void do_something(Foo f) { - printf("x = %d\n", f->x); - f->bar(); + printf("x = %d\n", f->x); + f->bar(); } // Call the wrapped smart pointer proxy class in the target language 'Foo' @@ -4660,13 +4660,13 @@ example, if you have this code

 class Foo {
 public:
-    int x;
+  int x;
 };
 
 class Bar {
 public:
-    int x;       
-    Foo *operator->();
+  int x;       
+  Foo *operator->();
 };
 
@@ -4970,14 +4970,14 @@ you wrap this code in Python, the module works just like you would expect:
 class Foo {
 protected:
-    int x;
-    int blah(int x);
+  int x;
+  int blah(int x);
 };
 
 class Bar : public Foo {
 public:
-    using Foo::x;       // Make x public
-    using Foo::blah;    // Make blah public
+  using Foo::x;       // Make x public
+  using Foo::blah;    // Make blah public
 };
 
From c454f2ce2f91e0f458121033ffa349c283eeeb30 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Sun, 30 Jul 2017 17:02:47 +0100 Subject: [PATCH 235/455] Documentation corrections to use targetlang formatting --- Doc/Manual/Library.html | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Doc/Manual/Library.html b/Doc/Manual/Library.html index a800c2d73..f41799bf0 100644 --- a/Doc/Manual/Library.html +++ b/Doc/Manual/Library.html @@ -411,7 +411,7 @@ void print_array(double x[10]); Now, in a scripting language, you might write this:

-
+
 a = new_doubleArray(10)             # Create an array
 for i in range(0, 10):
@@ -475,7 +475,7 @@ void print_array(double x[10]);
 Allows you to do this:
 

-
+
 import example
 c = example.doubleArray(10)  # Create double[10]
@@ -801,7 +801,7 @@ target language.  In other words, if you were using a language like Tcl,
 and you wrote this,
 

-
+
 % foo Hello
 
@@ -852,7 +852,7 @@ size_t parity(char *str, size_t len, size_t initial); Now, in the target language, you can use binary string data like this:

-
+
 >>> s = "H\x00\x15eg\x09\x20"
 >>> parity(s, 0)

From 04131a988f49286fde74fb9d74c5c4bd1ade8454 Mon Sep 17 00:00:00 2001
From: William S Fulton 
Date: Sun, 30 Jul 2017 17:18:55 +0100
Subject: [PATCH 236/455] More consistent formatting of examples in
 documentation

---
 Doc/Manual/CSharp.html   |   2 +-
 Doc/Manual/Perl5.html    | 114 ++++++++++++++++++-------------------
 Doc/Manual/Php.html      |  18 +++---
 Doc/Manual/Pike.html     |   4 +-
 Doc/Manual/Python.html   | 119 ++++++++++++++++++++-------------------
 Doc/Manual/SWIG.html     |  16 +++---
 Doc/Manual/SWIGPlus.html |   2 +-
 Doc/Manual/Tcl.html      |  46 +++++++--------
 8 files changed, 161 insertions(+), 160 deletions(-)

diff --git a/Doc/Manual/CSharp.html b/Doc/Manual/CSharp.html
index d618f5a08..bb3524ac5 100644
--- a/Doc/Manual/CSharp.html
+++ b/Doc/Manual/CSharp.html
@@ -677,7 +677,7 @@ As a result, we get the following method in the module class:
 
 public static void myArrayCopy(int[] sourceArray, int[] targetArray, int nitems) {
-    examplePINVOKE.myArrayCopy(sourceArray, targetArray, nitems);
+  examplePINVOKE.myArrayCopy(sourceArray, targetArray, nitems);
 }
 
diff --git a/Doc/Manual/Perl5.html b/Doc/Manual/Perl5.html index 5e9a9e33e..8ea43ad6b 100644 --- a/Doc/Manual/Perl5.html +++ b/Doc/Manual/Perl5.html @@ -949,7 +949,7 @@ Foo *BarToFoo(Bar *b) { } Foo *IncrFoo(Foo *f, int i) { - return f+i; + return f+i; } %}
@@ -1057,7 +1057,7 @@ produces a single accessor function like this:
 int *Foo_x_get(Foo *self) {
-    return self->x;
+  return self->x;
 };
 
@@ -1092,11 +1092,11 @@ generates accessor functions such as this:
 Foo *Bar_f_get(Bar *b) {
-    return &b->f;
+  return &b->f;
 }
 
 void Bar_f_set(Bar *b, Foo *val) {
-    b->f = *val;
+  b->f = *val;
 }
 
@@ -1887,9 +1887,9 @@ like this:
 %typemap(out) int {
-    $result = sv_newmortal();
-    set_setiv($result, (IV) $1);
-    argvi++;
+  $result = sv_newmortal();
+  set_setiv($result, (IV) $1);
+  argvi++;
 }
 
@@ -2312,8 +2312,8 @@ Consider the following data structure:
 #define SIZE  8
 typedef struct {
-    int   values[SIZE];
-    ...
+  int   values[SIZE];
+  ...
 } Foo;
 
 
@@ -2327,10 +2327,10 @@ To make the member writable, a "memberin" typemap can be used.
 %typemap(memberin) int [SIZE] {
-    int i;
-    for (i = 0; i < SIZE; i++) {
-        $1[i] = $input[i];
-    }
+  int i;
+  for (i = 0; i < SIZE; i++) {
+    $1[i] = $input[i];
+  }
 }
 
 
@@ -2599,48 +2599,48 @@ package example::Vector; %BLESSEDMEMBERS = (); sub new () { - my $self = shift; - my @args = @_; - $self = vectorc::new_Vector(@args); - return undef if (!defined($self)); - bless $self, "example::Vector"; - $OWNER{$self} = 1; - my %retval; - tie %retval, "example::Vector", $self; - return bless \%retval, "Vector"; + my $self = shift; + my @args = @_; + $self = vectorc::new_Vector(@args); + return undef if (!defined($self)); + bless $self, "example::Vector"; + $OWNER{$self} = 1; + my %retval; + tie %retval, "example::Vector", $self; + return bless \%retval, "Vector"; } sub DESTROY { - return unless $_[0]->isa('HASH'); - my $self = tied(%{$_[0]}); - delete $ITERATORS{$self}; - if (exists $OWNER{$self}) { - examplec::delete_Vector($self)); - delete $OWNER{$self}; - } + return unless $_[0]->isa('HASH'); + my $self = tied(%{$_[0]}); + delete $ITERATORS{$self}; + if (exists $OWNER{$self}) { + examplec::delete_Vector($self)); + delete $OWNER{$self}; + } } sub FETCH { - my ($self, $field) = @_; - my $member_func = "vectorc::Vector_${field}_get"; - my $val = &$member_func($self); - if (exists $BLESSEDMEMBERS{$field}) { - return undef if (!defined($val)); - my %retval; - tie %retval, $BLESSEDMEMBERS{$field}, $val; - return bless \%retval, $BLESSEDMEMBERS{$field}; - } - return $val; + my ($self, $field) = @_; + my $member_func = "vectorc::Vector_${field}_get"; + my $val = &$member_func($self); + if (exists $BLESSEDMEMBERS{$field}) { + return undef if (!defined($val)); + my %retval; + tie %retval, $BLESSEDMEMBERS{$field}, $val; + return bless \%retval, $BLESSEDMEMBERS{$field}; + } + return $val; } sub STORE { - my ($self, $field, $newval) = @_; - my $member_func = "vectorc::Vector_${field}_set"; - if (exists $BLESSEDMEMBERS{$field}) { - &$member_func($self, tied(%{$newval})); - } else { - &$member_func($self, $newval); - } + my ($self, $field, $newval) = @_; + my $member_func = "vectorc::Vector_${field}_set"; + if (exists $BLESSEDMEMBERS{$field}) { + &$member_func($self, tied(%{$newval})); + } else { + &$member_func($self, $newval); + } }
@@ -2841,11 +2841,11 @@ this:
 sub dot_product {
-    my @args = @_;
-    $args[0] = tied(%{$args[0]});         # Get the real pointer values
-    $args[1] = tied(%{$args[1]});
-    my $result = vectorc::dot_product(@args);
-    return $result;
+  my @args = @_;
+  $args[0] = tied(%{$args[0]});         # Get the real pointer values
+  $args[1] = tied(%{$args[1]});
+  my $result = vectorc::dot_product(@args);
+  return $result;
 }
 
@@ -3103,14 +3103,14 @@ the methods one() and two() (but not three()): %feature("director") Foo; class Foo { public: - Foo(int foo); - virtual void one(); - virtual void two(); + Foo(int foo); + virtual void one(); + virtual void two(); }; class Bar: public Foo { public: - virtual void three(); + virtual void three(); };
@@ -3304,8 +3304,8 @@ suitable exception handler:
 %exception {
-    try { $action }
-    catch (Swig::DirectorException &e) { SWIG_fail; }
+  try { $action }
+  catch (Swig::DirectorException &e) { SWIG_fail; }
 }
 
diff --git a/Doc/Manual/Php.html b/Doc/Manual/Php.html index c4ba2e3f8..4fda4cc69 100644 --- a/Doc/Manual/Php.html +++ b/Doc/Manual/Php.html @@ -986,14 +986,14 @@ the methods one() and two() (but not three()): %feature("director") Foo; class Foo { public: - Foo(int foo); - virtual void one(); - virtual void two(); + Foo(int foo); + virtual void one(); + virtual void two(); }; class Bar: public Foo { public: - virtual void three(); + virtual void three(); };
@@ -1125,12 +1125,12 @@ Here is an example:
 class Foo {
 public:
-    ...
+  ...
 };
 class FooContainer {
 public:
-    void addFoo(Foo *);
-    ...
+  void addFoo(Foo *);
+  ...
 };
 
@@ -1204,8 +1204,8 @@ suitable exception handler:
 %exception {
-    try { $action }
-    catch (Swig::DirectorException &e) { SWIG_fail; }
+  try { $action }
+  catch (Swig::DirectorException &e) { SWIG_fail; }
 }
 
diff --git a/Doc/Manual/Pike.html b/Doc/Manual/Pike.html index 22ab4e2a2..a8bc0d415 100644 --- a/Doc/Manual/Pike.html +++ b/Doc/Manual/Pike.html @@ -230,8 +230,8 @@ For example, given this C++ class declaration: class Shape { public: - static void print(); - static int nshapes; + static void print(); + static int nshapes; }; diff --git a/Doc/Manual/Python.html b/Doc/Manual/Python.html index 169151d47..e294db86d 100644 --- a/Doc/Manual/Python.html +++ b/Doc/Manual/Python.html @@ -1275,7 +1275,7 @@ Foo *BarToFoo(Bar *b) { } Foo *IncrFoo(Foo *f, int i) { - return f+i; + return f+i; } %} @@ -1385,7 +1385,7 @@ example, consider this:
 struct Bar {
-    int  x[16];
+  int  x[16];
 };
 
@@ -1715,9 +1715,9 @@ Similarly, if you have a class like this,
 class Foo {
 public:
-    Foo();
-    Foo(const Foo &);
-    ...
+  Foo();
+  Foo(const Foo &);
+  ...
 };
 
@@ -1950,11 +1950,11 @@ For example: %rename(Bar_spam) Bar::spam; namespace Foo { - int spam(); + int spam(); } namespace Bar { - int spam(); + int spam(); } @@ -2165,9 +2165,9 @@ have a class like this
 class Foo {
 public:
-    int x;
-    int spam(int);
-    ...
+  int x;
+  int spam(int);
+  ...
 
@@ -2178,19 +2178,19 @@ then SWIG transforms it into a set of low-level procedural wrappers. For example
 Foo *new_Foo() {
-    return new Foo();
+  return new Foo();
 }
 void delete_Foo(Foo *f) {
-    delete f;
+  delete f;
 }
 int Foo_x_get(Foo *f) {
-    return f->x;
+  return f->x;
 }
 void Foo_x_set(Foo *f, int value) {
-    f->x = value;
+  f->x = value;
 }
 int Foo_spam(Foo *f, int arg1) {
-    return f->spam(arg1);
+  return f->spam(arg1);
 }
 
@@ -2309,10 +2309,10 @@ please refer to the python documentation:

 typedef struct {
-    PyObject_HEAD
-    PyObject *dict;
-    PyObject *args;
-    PyObject *message;
+  PyObject_HEAD
+  PyObject *dict;
+  PyObject *args;
+  PyObject *message;
 } PyBaseExceptionObject;
 
@@ -2322,12 +2322,12 @@ typedef struct {
 typedef struct {
-    PyObject_HEAD
-    void *ptr;
-    swig_type_info *ty;
-    int own;
-    PyObject *next;
-    PyObject *dict;
+  PyObject_HEAD
+  void *ptr;
+  swig_type_info *ty;
+  int own;
+  PyObject *next;
+  PyObject *dict;
 } SwigPyObject;
 
@@ -2338,13 +2338,13 @@ typedef struct {
 class MyException {
 public:
-    MyException (const char *msg_);
-    ~MyException ();
+  MyException (const char *msg_);
+  ~MyException ();
 
-    const char *what () const;
+  const char *what () const;
 
 private:
-    char *msg;
+  char *msg;
 };
 
@@ -2371,9 +2371,9 @@ strings, you can define an 'operator+ (const char*)' method :

 class MyString {
 public:
-    MyString (const char *init);
-    MyString operator+ (const char *other) const;
-    ...
+  MyString (const char *init);
+  MyString operator+ (const char *other) const;
+  ...
 };
 
@@ -2472,11 +2472,12 @@ slot entries. For example, suppose you have this class:
 class Twit {
 public:
-    Twit operator+ (const Twit& twit) const;
+  Twit operator+ (const Twit& twit) const;
 
-    // Forward to operator+
-    Twit add (const Twit& twit) const
-    { return *this + twit; }
+  // Forward to operator+
+  Twit add (const Twit& twit) const {
+    return *this + twit;
+  }
 };
 
@@ -2635,8 +2636,8 @@ ownership of the result. For example:
 class Foo {
 public:
-    Foo();
-    Foo bar();
+  Foo();
+  Foo bar();
 };
 
@@ -2665,9 +2666,9 @@ they came from. Therefore, the ownership is set to zero. For example:
 class Foo {
 public:
-    ...
-    Foo *spam();
-    ...
+  ...
+  Foo *spam();
+  ...
 };
 
@@ -2706,8 +2707,8 @@ or global variable. For example, consider this interface: %module example struct Foo { - int value; - Foo *next; + int value; + Foo *next; }; Foo *head = 0; @@ -2938,15 +2939,15 @@ the methods one() and two() (but not three()): %feature("director") Foo; class Foo { public: - Foo(int foo); - virtual ~Foo(); - virtual void one(); - virtual void two(); + Foo(int foo); + virtual ~Foo(); + virtual void one(); + virtual void two(); }; class Bar: public Foo { public: - virtual void three(); + virtual void three(); }; @@ -3090,8 +3091,8 @@ public: }; class FooContainer { public: - void addFoo(Foo *); - ... + void addFoo(Foo *); + ... }; @@ -3161,8 +3162,8 @@ suitable exception handler:
 %exception {
-    try { $action }
-    catch (Swig::DirectorException &e) { SWIG_fail; }
+  try { $action }
+  catch (Swig::DirectorException &e) { SWIG_fail; }
 }
 
@@ -3239,7 +3240,7 @@ references, such as
 class Foo {
 …
-    virtual const int& bar();
+  virtual const int& bar();
 …
 };
 
@@ -3257,7 +3258,7 @@ types, wherever possible, for example
 class Foo {
 …
-    virtual int bar();
+  virtual int bar();
 …
 };
 
@@ -3510,7 +3511,7 @@ def bar(*args): class Foo { public: - int bar(int x); + int bar(int x); }; @@ -3547,7 +3548,7 @@ proxy, just before the return statement. class Foo { public: - int bar(int x); + int bar(int x); }; @@ -3576,7 +3577,7 @@ SWIG version 1.3.28 you can use the directive forms class Foo { public: - int bar(int x); + int bar(int x); }; @@ -3605,8 +3606,8 @@ as it will then get attached to all the overloaded C++ methods. For example: class Foo { public: - int bar(int x); - int bar(); + int bar(int x); + int bar(); }; diff --git a/Doc/Manual/SWIG.html b/Doc/Manual/SWIG.html index cff4e7dc2..a43ff94b5 100644 --- a/Doc/Manual/SWIG.html +++ b/Doc/Manual/SWIG.html @@ -1236,9 +1236,9 @@ creating a wrapper equivalent to the following:
 double wrap_dot_product(Vector *a, Vector *b) {
-    Vector x = *a;
-    Vector y = *b;
-    return dot_product(x, y);
+  Vector x = *a;
+  Vector y = *b;
+  return dot_product(x, y);
 }
 
@@ -2368,10 +2368,10 @@ defined in the interface. For example:
 struct Vector *new_Vector() {
-    return (Vector *) calloc(1, sizeof(struct Vector));
+  return (Vector *) calloc(1, sizeof(struct Vector));
 }
 void delete_Vector(struct Vector *obj) {
-    free(obj);
+  free(obj);
 }
 
@@ -2602,10 +2602,10 @@ like this:
 WORD Foo_w_get(Foo *f) {
-    return f->w;
+  return f->w;
 }
 void Foo_w_set(FOO *f, WORD value) {
-    f->w = value;
+  f->w = value;
 }
 
@@ -2896,7 +2896,7 @@ instead of a method. To do this, you might write some code like this:
 // Add a new attribute to Vector
 %extend Vector {
-    const double magnitude;
+  const double magnitude;
 }
 // Now supply the implementation of the Vector_magnitude_get function
 %{
diff --git a/Doc/Manual/SWIGPlus.html b/Doc/Manual/SWIGPlus.html
index 87fe30fa8..da4f54603 100644
--- a/Doc/Manual/SWIGPlus.html
+++ b/Doc/Manual/SWIGPlus.html
@@ -4042,7 +4042,7 @@ namespace foo {
   typedef int Integer;
   class bar {
     public:
-      ...
+    ...
   };
 }
 
diff --git a/Doc/Manual/Tcl.html b/Doc/Manual/Tcl.html
index 31408b312..41cb78661 100644
--- a/Doc/Manual/Tcl.html
+++ b/Doc/Manual/Tcl.html
@@ -958,7 +958,7 @@ Foo *BarToFoo(Bar *b) {
 }
 
 Foo *IncrFoo(Foo *f, int i) {
-    return f+i;
+  return f+i;
 }
 %}
 
@@ -1054,7 +1054,7 @@ example, consider this:
 struct Bar {
-    int  x[16];
+  int  x[16];
 };
 
@@ -1456,9 +1456,9 @@ Similarly, if you have a class like this,
 class Foo {
 public:
-    Foo();
-    Foo(const Foo &);
-    ...
+  Foo();
+  Foo(const Foo &);
+  ...
 };
 
@@ -1693,11 +1693,11 @@ For example: %rename(Bar_spam) Bar::spam; namespace Foo { - int spam(); + int spam(); } namespace Bar { - int spam(); + int spam(); } @@ -1886,19 +1886,19 @@ then SWIG transforms it into a set of low-level procedural wrappers. For example
 Foo *new_Foo() {
-    return new Foo();
+  return new Foo();
 }
 void delete_Foo(Foo *f) {
-    delete f;
+  delete f;
 }
 int Foo_x_get(Foo *f) {
-    return f->x;
+  return f->x;
 }
 void Foo_x_set(Foo *f, int value) {
-    f->x = value;
+  f->x = value;
 }
 int Foo_spam(Foo *f, int arg1) {
-    return f->spam(arg1);
+  return f->spam(arg1);
 }
 
@@ -1945,8 +1945,8 @@ ownership of the result. For example:
 class Foo {
 public:
-    Foo();
-    Foo bar();
+  Foo();
+  Foo bar();
 };
 
@@ -1975,9 +1975,9 @@ they came from. Therefore, the ownership is set to zero. For example:
 class Foo {
 public:
-    ...
-    Foo *spam();
-    ...
+  ...
+  Foo *spam();
+  ...
 };
 
@@ -2011,8 +2011,8 @@ or global variable. For example, consider this interface: %module example struct Foo { - int value; - Foo *next; + int value; + Foo *next; }; Foo *head = 0; @@ -2465,9 +2465,9 @@ you might define a typemap like this: %module example %typemap(in) int { - if (Tcl_GetIntFromObj(interp, $input, &$1) == TCL_ERROR) - return TCL_ERROR; - printf("Received an integer : %d\n", $1); + if (Tcl_GetIntFromObj(interp, $input, &$1) == TCL_ERROR) + return TCL_ERROR; + printf("Received an integer : %d\n", $1); } %inline %{ extern int fact(int n); @@ -2585,7 +2585,7 @@ like this:
 %typemap(out) int {
-    Tcl_SetObjResult(interp, Tcl_NewIntObj($1));
+  Tcl_SetObjResult(interp, Tcl_NewIntObj($1));
 }
 
From 5779aa8d7966ae4ce983a822a0dc56014e3c295a Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Sun, 30 Jul 2017 17:22:40 +0100 Subject: [PATCH 237/455] More consistent formatting of examples in documentation --- Doc/Manual/Python.html | 8 ++++---- Doc/Manual/SWIG.html | 2 +- Doc/Manual/SWIGPlus.html | 12 ++++++------ Doc/Manual/Varargs.html | 4 ++-- 4 files changed, 13 insertions(+), 13 deletions(-) diff --git a/Doc/Manual/Python.html b/Doc/Manual/Python.html index e294db86d..b43ca1949 100644 --- a/Doc/Manual/Python.html +++ b/Doc/Manual/Python.html @@ -2565,9 +2565,9 @@ the function callback in the tp_hash slot for the builtin type for MyClass
 static PyHeapTypeObject SwigPyBuiltin__MyClass_type = {
-    ...
-    (hashfunc) myHashFunc,       /* tp_hash */
-    ...
+  ...
+  (hashfunc) myHashFunc,       /* tp_hash */
+  ...
 
@@ -3087,7 +3087,7 @@ references. Here is an example:
 class Foo {
 public:
-    ...
+  ...
 };
 class FooContainer {
 public:
diff --git a/Doc/Manual/SWIG.html b/Doc/Manual/SWIG.html
index a43ff94b5..c05ed456c 100644
--- a/Doc/Manual/SWIG.html
+++ b/Doc/Manual/SWIG.html
@@ -389,7 +389,7 @@ For example
 /* bar not wrapped unless foo has been defined and 
    the declaration of bar within foo has already been parsed */
 int foo::bar(int) {
-    ... whatever ...
+  ... whatever ...
 }
 
diff --git a/Doc/Manual/SWIGPlus.html b/Doc/Manual/SWIGPlus.html index da4f54603..d0a8f2c9c 100644 --- a/Doc/Manual/SWIGPlus.html +++ b/Doc/Manual/SWIGPlus.html @@ -706,7 +706,7 @@ class Foo { protected: Foo(); // Not wrapped. public: - ... + ... }; @@ -1278,7 +1278,7 @@ equivalent to one generated for the following declaration
 class Foo {
 public:
-    ...
+  ...
 };
 
 void blah(Foo *f);    
@@ -4381,9 +4381,9 @@ class Error { };
 
 class Foo {
 public:
-    ...
-    void blah() throw(Error);
-    ...
+  ...
+  void blah() throw(Error);
+  ...
 };
 
@@ -4547,7 +4547,7 @@ class Foo_Impl { public: int x; virtual void bar(); - ... + ... }; // Smart-pointer wrapper diff --git a/Doc/Manual/Varargs.html b/Doc/Manual/Varargs.html index fb58ee39a..eba816382 100644 --- a/Doc/Manual/Varargs.html +++ b/Doc/Manual/Varargs.html @@ -423,8 +423,8 @@ Variable length arguments may be used in typemap specifications. For example:
 %typemap(in) (...) {
-    // Get variable length arguments (somehow)
-    ...
+  // Get variable length arguments (somehow)
+  ...
 }
 
 %typemap(in) (const char *fmt, ...) {

From 97ae9d66bc7b8cd1fe78680c1253a222c5864c55 Mon Sep 17 00:00:00 2001
From: William S Fulton 
Date: Tue, 8 Aug 2017 19:40:39 +0100
Subject: [PATCH 238/455] Template documentation tweaks

Add subsections to the template documentation
Rewrite some of the template introduction
---
 Doc/Manual/Contents.html |   9 ++
 Doc/Manual/SWIGPlus.html | 227 +++++++++++++++++++++++----------------
 2 files changed, 146 insertions(+), 90 deletions(-)

diff --git a/Doc/Manual/Contents.html b/Doc/Manual/Contents.html
index 56afca857..67f0c3965 100644
--- a/Doc/Manual/Contents.html
+++ b/Doc/Manual/Contents.html
@@ -246,6 +246,15 @@
 
  • Wrapping overloaded operators
  • Class extension
  • Templates +
  • Namespaces
    • The nspace feature for namespaces diff --git a/Doc/Manual/SWIGPlus.html b/Doc/Manual/SWIGPlus.html index d0a8f2c9c..7cc0d5387 100644 --- a/Doc/Manual/SWIGPlus.html +++ b/Doc/Manual/SWIGPlus.html @@ -49,6 +49,15 @@
    • Wrapping overloaded operators
    • Class extension
    • Templates +
    • Namespaces
      • The nspace feature for namespaces @@ -2936,23 +2945,24 @@ as vector<int>. The wrapper for foo() will accept either variant.

        +

        6.18.1 The %template directive

        + +

        -Starting with SWIG-1.3.7, simple C++ template declarations can also be -wrapped. SWIG-1.3.12 greatly expands upon the earlier implementation. Before discussing this any further, there are a few things -you need to know about template wrapping. First, a bare C++ template +There are a couple of important points about template wrapping. +First, a bare C++ template does not define any sort of runnable object-code for which SWIG can normally create a wrapper. Therefore, in order to wrap a template, you need to give SWIG information about a particular template -instantiation (e.g., vector<int>, +instantiation (e.g., vector<int>, array<double>, etc.). Second, an instantiation name such as vector<int> is generally not a valid identifier name in most target languages. Thus, you will need to give the -template instantiation a more suitable name such as intvector -when creating a wrapper. +template instantiation a more suitable name such as intvector.

        -To illustrate, consider the following template definition: +To illustrate, consider the following class template definition:

        @@ -2985,14 +2995,26 @@ public:
         

        -By itself, this template declaration is useless--SWIG simply ignores it -because it doesn't know how to generate any code until unless a definition of +By itself, this class template is useless--SWIG simply ignores it +because it doesn't know how to generate any code unless a definition of T is provided. +The %template directive is required to instantiate the template for use in a target language. +The directive requires an identifier name for use in the target language plus the template for instantiation. +The example below instantiates List<int> for use as a class named intList:

        +
        +
        +%template(intList) List<int>;
        +
        +
        +

        -One way to create wrappers for a specific template instantiation is to simply -provide an expanded version of the class directly like this: +The instantiation expands the template code as a C++ compiler would do and then makes it available +under the given identifier name. +Essentially it is the same as wrapping the following concept code where +the class template definition has T expanded to int +(note that this is not entirely valid syntax):

        @@ -3014,28 +3036,6 @@ public:
        -

        -The %rename directive is needed to give the template class an appropriate identifier -name in the target language (most languages would not recognize C++ template syntax as a valid -class name). The rest of the code is the same as what would appear in a normal -class definition. -

        - -

        -Since manual expansion of templates gets old in a hurry, the %template directive can -be used to create instantiations of a template class. Semantically, %template is -simply a shortcut---it expands template code in exactly the same way as shown above. Here -are some examples: -

        - -
        -
        -/* Instantiate a few different versions of the template */
        -%template(intList) List<int>;
        -%template(doubleList) List<double>;
        -
        -
        -

        The argument to %template() is the name of the instantiation in the target language. The name you choose should not conflict with @@ -3053,7 +3053,67 @@ typedef List<int> intList; // OK

  • -SWIG can also generate wrappers for function templates using a similar technique. +The %template directive +must always appear after the definition of the template to be expanded, so the following will work: +

    + +
    +
    +template<class T> class List { ... };
    +%template(intList) List<int>;
    +
    +
    + +

    +but if %template is used before the template definition, such as: +

    + +
    +
    +%template(intList) List<int>;
    +template<class T> class List { ... };
    +
    +
    + +

    +SWIG will generate an error: +

    + +
    +
    +example.i:3: Error: Template 'List' undefined.
    +
    +
    + +

    +Since the type system knows how to handle typedef, it is +generally not necessary to instantiate different versions of a template +for typenames that are equivalent. For instance, consider this code: +

    + +
    +
    +%template(intList) List<int>;
    +typedef int Integer;
    +...
    +void foo(List<Integer> *x);
    +
    +
    + +

    +In this case, List<Integer> is exactly the same type as +List<int>. Any use of List<Integer> is mapped back to the +instantiation of List<int> created earlier. Therefore, it is +not necessary to instantiate a new class for the type Integer (doing so is +redundant and will simply result in code bloat). +

    + +

    6.18.2 Function templates

    + + +

    +SWIG can also generate wrappers for function templates using a similar technique +to that shown above for class templates. For example:

    @@ -3073,6 +3133,28 @@ In this case, maxint and maxdouble become unique names for spe instantiations of the function.

    +

    +SWIG even supports overloaded templated functions. As usual the %template directive +is used to wrap templated functions. For example: +

    + +
    +
    +template<class T> void foo(T x) { };
    +template<class T> void foo(T x, T y) { };
    +
    +%template(foo) foo<int>;
    +
    +
    + +

    +This will generate two overloaded wrapper methods, the first will take a single integer as an argument +and the second will take two integer arguments. +

    + +

    6.18.3 Default template arguments

    + +

    The number of arguments supplied to %template should match that in the original template definition. Template default arguments are supported. For example: @@ -3110,28 +3192,8 @@ instantiation only once in order to reduce the potential for code bloat.

    -

    -Since the type system knows how to handle typedef, it is -generally not necessary to instantiate different versions of a template -for typenames that are equivalent. For instance, consider this code: -

    +

    6.18.4 Template base classes

    -
    -
    -%template(intList) vector<int>;
    -typedef int Integer;
    -...
    -void foo(vector<Integer> *x);
    -
    -
    - -

    -In this case, vector<Integer> is exactly the same type as -vector<int>. Any use of Vector<Integer> is mapped back to the -instantiation of vector<int> created earlier. Therefore, it is -not necessary to instantiate a new class for the type Integer (doing so is -redundant and will simply result in code bloat). -

    When a template is instantiated using %template, information @@ -3158,13 +3220,13 @@ nothing is known about List<int>, you will get a warning message

    -example.h:42: Warning 401. Nothing known about class 'List<int >'. Ignored. 
    -example.h:42: Warning 401. Maybe you forgot to instantiate 'List<int >' using %template. 
    +example.h:42: Warning 401. Nothing known about class 'List< int >'. Ignored. 
    +example.h:42: Warning 401. Maybe you forgot to instantiate 'List< int >' using %template. 
     

    -If a template class inherits from another template class, you need to +If a class template inherits from another class template, you need to make sure that base classes are instantiated before derived classes. For example:

    @@ -3235,6 +3297,9 @@ TEMPLATE_WRAP(PairStringInt, std::pair<string, int>) Note the use of a vararg macro for the type T. If this wasn't used, the comma in the templated type in the last example would not be possible.

    +

    6.18.5 Template specialization

    + +

    The SWIG template mechanism does support specialization. For instance, if you define a class like this, @@ -3281,7 +3346,7 @@ private: public: List(int max); ~List(); - void append(int obj); + void append(T obj); int length(); T get(int n); }; @@ -3322,10 +3387,13 @@ SWIG implements template argument deduction so that the following partial specia +

    6.18.6 Member templates

    + +

    -Member function templates are supported. The underlying principle is the same +Member templates are supported. The underlying principle is the same as for normal templates--SWIG can't create a wrapper unless you provide -more information about types. For example, a class with a member template might +more information about types. For example, a class with a member function template might look like this:

    @@ -3399,11 +3467,6 @@ methods to the Foo class.

    -

    -Note: because of the way that templates are handled, the %template directive -must always appear after the definition of the template to be expanded. -

    -

    Now, if your target language supports overloading, you can even try

    @@ -3424,7 +3487,7 @@ depending on the argument type.

    When used with members, the %template directive may be placed in another -template class. Here is a slightly perverse example: +class template. Here is a slightly perverse example:

    @@ -3475,7 +3538,7 @@ template<class T1, class T2> struct pair {

    This declaration is perfectly acceptable to SWIG, but the constructor template will be ignored unless you explicitly expand it. To do that, you could expand a few versions of the constructor -in the template class itself. For example: +in the class template itself. For example:

    @@ -3536,6 +3599,9 @@ constructor, that will dispatch the proper call depending on the argument type.

    +

    6.18.7 More on templates

    + +

    If all of this isn't quite enough and you really want to make someone's head explode, SWIG directives such as @@ -3568,7 +3634,7 @@ instantiation.

    -It is also possible to separate these declarations from the template class. For example: +It is also possible to separate these declarations from the class template. For example:

    @@ -3616,25 +3682,6 @@ additional methods to a specific instantiation. For example:
    -

    -SWIG even supports overloaded templated functions. As usual the %template directive -is used to wrap templated functions. For example: -

    - -
    -
    -template<class T> void foo(T x) { };
    -template<class T> void foo(T x, T y) { };
    -
    -%template(foo) foo<int>;
    -
    -
    - -

    -This will generate two overloaded wrapper methods, the first will take a single integer as an argument -and the second will take two integer arguments. -

    -

    It is even possible to extend a class via %extend with template methods, for example:

    @@ -3694,7 +3741,7 @@ For example:
     template <class T> class OuterTemplateClass {};
     
    -// The nested class OuterClass::InnerClass inherits from the template class
    +// The nested class OuterClass::InnerClass inherits from the class template
     // OuterTemplateClass<OuterClass::InnerStruct> and thus the template needs
     // to be expanded with %template before the OuterClass declaration.
     %template(OuterTemplateClass_OuterClass__InnerStruct)
    @@ -4524,7 +4571,7 @@ for member pointers.
     

    In some C++ programs, objects are often encapsulated by smart-pointers or proxy classes. This is sometimes done to implement automatic memory management (reference counting) or -persistence. Typically a smart-pointer is defined by a template class where +persistence. Typically a smart-pointer is defined by a class template where the -> operator has been overloaded. This class is then wrapped around some other class. For example:

    From 959e6272082e416303d80d7326430d1fd0b4c432 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Wed, 9 Aug 2017 00:06:24 +0100 Subject: [PATCH 239/455] %template scope enforcement and class definition fixes The scoping rules around %template have been specified and enforced. The %template directive for a class template is the equivalent to an explicit instantiation of a C++ class template. The scope for a valid %template instantiation is now the same as the scope required for a valid explicit instantiation of a C++ template. A definition of the template for the explicit instantiation must be in scope where the instantiation is declared and must not be enclosed within a different namespace. For example, a few %template and explicit instantiations of std::vector are shown below: // valid namespace std { %template(vin) vector; template class vector; } // valid using namespace std; %template(vin) vector; template class vector; // valid using std::vector; %template(vin) vector; template class vector; // ill-formed namespace unrelated { using std::vector; %template(vin) vector; template class vector; } // ill-formed namespace unrelated { using namespace std; %template(vin) vector; template class vector; } // ill-formed namespace unrelated { namespace std { %template(vin) vector; template class vector; } } // ill-formed namespace unrelated { %template(vin) std::vector; template class std::vector; } When the scope is incorrect, an error now occurs such as: cpp_template_scope.i:34: Error: 'vector' resolves to 'std::vector' and was incorrectly instantiated in scope 'unrelated' instead of within scope 'std'. Previously SWIG accepted the ill-formed examples above but this led to numerous subtle template scope problems especially in the presence of using declarations and using directives as well as with %feature and %typemap. Actually, a valid instantiation is one which conforms to the C++03 standard as C++11 made a change to disallow using declarations and using directives to find a template. // valid C++03, ill-formed C++11 using std::vector; template class vector; Similar fixes for defining classes using forward class references have also been put in place. For example: namespace Space1 { struct A; } namespace Space2 { struct Space1::A { void x(); } } will now error out with: cpp_class_definition.i:5: Error: 'Space1::A' resolves to 'Space1::A' and was incorrectly instantiated in scope 'Space2' instead of within scope 'Space1'. --- Doc/Manual/Contents.html | 1 + Doc/Manual/SWIGPlus.html | 108 ++++++++++- Examples/test-suite/class_scope_namespace.i | 153 ++++++++++++++++ Examples/test-suite/common.mk | 1 + .../test-suite/errors/cpp_class_definition.i | 26 +++ .../errors/cpp_class_definition.stderr | 1 + .../errors/cpp_namespace_template_bad.i | 40 +++++ .../errors/cpp_namespace_template_bad.stderr | 9 + .../errors/cpp_nested_template.stderr | 2 + .../test-suite/errors/cpp_template_scope.i | 57 ++++++ .../errors/cpp_template_scope.stderr | 11 ++ .../java/class_scope_namespace_runme.java | 59 ++++++ .../java/namespace_template_runme.java | 32 ++++ Examples/test-suite/namespace_template.i | 40 ++--- .../test-suite/smart_pointer_namespace2.i | 13 +- .../test-suite/template_nested_typemaps.i | 33 ++-- .../template_partial_specialization.i | 4 +- .../template_partial_specialization_typedef.i | 4 +- Source/CParse/parser.y | 170 ++++++++++++------ Source/Swig/misc.c | 38 +++- Source/Swig/swig.h | 1 + 21 files changed, 689 insertions(+), 114 deletions(-) create mode 100644 Examples/test-suite/class_scope_namespace.i create mode 100644 Examples/test-suite/errors/cpp_class_definition.i create mode 100644 Examples/test-suite/errors/cpp_class_definition.stderr create mode 100644 Examples/test-suite/errors/cpp_namespace_template_bad.i create mode 100644 Examples/test-suite/errors/cpp_namespace_template_bad.stderr create mode 100644 Examples/test-suite/errors/cpp_template_scope.i create mode 100644 Examples/test-suite/errors/cpp_template_scope.stderr create mode 100644 Examples/test-suite/java/class_scope_namespace_runme.java create mode 100644 Examples/test-suite/java/namespace_template_runme.java diff --git a/Doc/Manual/Contents.html b/Doc/Manual/Contents.html index 67f0c3965..3d9f6fd3b 100644 --- a/Doc/Manual/Contents.html +++ b/Doc/Manual/Contents.html @@ -253,6 +253,7 @@
  • Template base classes
  • Template specialization
  • Member templates +
  • Scoping and templates
  • More on templates
  • Namespaces diff --git a/Doc/Manual/SWIGPlus.html b/Doc/Manual/SWIGPlus.html index 7cc0d5387..13c81588d 100644 --- a/Doc/Manual/SWIGPlus.html +++ b/Doc/Manual/SWIGPlus.html @@ -56,6 +56,7 @@
  • Template base classes
  • Template specialization
  • Member templates +
  • Scoping and templates
  • More on templates
  • Namespaces @@ -3599,7 +3600,108 @@ constructor, that will dispatch the proper call depending on the argument type.

    -

    6.18.7 More on templates

    +

    6.18.7 Scoping and templates

    + + +

    +The %template directive for a class template is the equivalent to an explicit instantiation +of a C++ class template. The scope for a valid %template instantiation is the same +as the scope required for a valid explicit instantiation of a C++ template. +A definition of the template for the explicit instantiation must be in scope +where the instantiation is declared and must not be enclosed within a different namespace. +

    + +

    +For example, a few %template instantiations and C++ explicit instantiations are shown below: +

    + +
    +
    +namespace N {
    +  template<typename T> class C {};
    +}
    +
    +// valid
    +%template(cin) N::C<int>;
    +template class N::C<int>;
    +
    +// valid
    +namespace N {
    +  %template(cin) C<int>;
    +  template class C<int>;
    +}
    +
    +// valid
    +using namespace N;
    +%template(cin) C<int>;
    +template class C<int>;
    +
    +// valid
    +using N::C;
    +%template(cin) C<int>;
    +template class C<int>;
    +
    +// ill-formed
    +namespace unrelated {
    +  using N::C;
    +  %template(cin) C<int>;
    +  template class C<int>;
    +}
    +
    +// ill-formed
    +namespace unrelated {
    +  using namespace N;
    +  %template(cin) C<int>;
    +  template class C<int>;
    +}
    +
    +// ill-formed
    +namespace unrelated {
    +  namespace N {
    +    %template(cin) C<int>;
    +    template class C<int>;
    +  }
    +}
    +
    +// ill-formed
    +namespace unrelated {
    +  %template(cin) N::C<int>;
    +  template class N::C<int>;
    +}
    +
    +
    + +

    +When the scope is incorrect, such as for the ill-formed examples above, an error occurs: +

    + +
    +
    +cpp_template_scope.i:34: Error: 'C' resolves to 'N::C' and was incorrectly instantiated
    +in scope 'unrelated' instead of within scope 'N'.
    +
    +
    + +

    +A note for the C++ standard geeks out there; a valid instantiation is one which conforms to +the C++03 standard as C++11 made a change to disallow using declarations and using directives to find a template. +

    + +
    +
    +// valid C++03, ill-formed C++11
    +using N::C;
    +template class C<int>;
    +
    +
    + +

    +Compatibility Note: Versions prior to SWIG-4.0.0 did not error out with incorrectly scoped +%template declarations, but this led to numerous subtle template scope problems. +

    + + +

    6.18.8 More on templates

    @@ -4348,9 +4450,9 @@ In the example below, the generic template type is used to rename to bbb

    -%rename(bbb) Space::ABC::aaa(T t);                  // will match but with lower precedence than ccc
    +%rename(bbb) Space::ABC::aaa(T t);                     // will match but with lower precedence than ccc
     %rename(ccc) Space::ABC<Space::XYZ>::aaa(Space::XYZ t);// will match but with higher precedence
    -                                                             // than bbb
    +                                                       // than bbb
     
     namespace Space {
       class XYZ {};
    diff --git a/Examples/test-suite/class_scope_namespace.i b/Examples/test-suite/class_scope_namespace.i
    new file mode 100644
    index 000000000..08a9f01dc
    --- /dev/null
    +++ b/Examples/test-suite/class_scope_namespace.i
    @@ -0,0 +1,153 @@
    +// Test a mix of forward class declarations, class definitions, using declarations and using directives.
    +
    +%module class_scope_namespace
    +
    +%warnfilter(SWIGWARN_PARSE_NAMED_NESTED_CLASS) H::HH;
    +%warnfilter(SWIGWARN_PARSE_NAMED_NESTED_CLASS) Space8::I::II;
    +
    +%inline %{
    +struct A;
    +namespace Space1 {
    +  namespace SubSpace1 {
    +    struct A {
    +      void aa(Space1::SubSpace1::A, SubSpace1::A, A) {}
    +    };
    +    void aaa(Space1::SubSpace1::A, SubSpace1::A, A) {}
    +  }
    +}
    +
    +namespace Space2 {
    +  struct B;
    +}
    +using Space2::B;
    +struct B {
    +  void bb(Space2::B, B) {}
    +};
    +void bbb(Space2::B, B) {}
    +
    +namespace Space3 {
    +  namespace SubSpace3 {
    +    struct C;
    +    struct D;
    +  }
    +}
    +struct C;
    +struct D;
    +namespace Space3 {
    +  struct C;
    +  struct SubSpace3::C {
    +    void cc(Space3::SubSpace3::C, SubSpace3::C) {}
    +  };
    +  using SubSpace3::D;
    +  struct SubSpace3::D {
    +    void dd(Space3::SubSpace3::D, SubSpace3::D, D) {}
    +  };
    +  void ccc(Space3::SubSpace3::C, SubSpace3::C) {}
    +  void ddd(Space3::SubSpace3::D, SubSpace3::D, D) {}
    +}
    +
    +namespace Space4 {
    +  namespace SubSpace4 {
    +    struct E;
    +  }
    +}
    +using namespace Space4;
    +using SubSpace4::E;
    +// Was added to incorrect namespace in swig-3.0.12
    +struct SubSpace4::E {
    +  void ee(Space4::SubSpace4::E, SubSpace4::E, E) {}
    +};
    +void eee(Space4::SubSpace4::E, SubSpace4::E, E) {}
    +
    +namespace Space5 {
    +  namespace SubSpace5 {
    +    namespace SubSubSpace5 {
    +      struct F;
    +    }
    +  }
    +}
    +namespace Space5 {
    +  using namespace SubSpace5;
    +  using SubSubSpace5::F;
    +  // Was added to incorrect namespace in swig-3.0.12
    +  struct SubSubSpace5::F {
    +    void ff(Space5::SubSpace5::SubSubSpace5::F, SubSpace5::SubSubSpace5::F, SubSubSpace5::F, F) {}
    +  };
    +// needs fixing
    +  void fff(Space5::SubSpace5::SubSubSpace5::F, SubSpace5::SubSubSpace5::F, /*SubSubSpace5::F,*/ F) {}
    +}
    +
    +namespace Space6 {
    +  struct G;
    +  namespace SubSpace6 {
    +    struct G;
    +  }
    +}
    +namespace Space6 {
    +  struct SubSpace6::G {
    +    void gg(Space6::SubSpace6::G, SubSpace6::G) {}
    +  };
    +  void ggg(Space6::SubSpace6::G, SubSpace6::G) {}
    +}
    +
    +struct HH;
    +struct H {
    +  struct HH {
    +    void hh(H::HH) {}
    +  };
    +};
    +void hhh(H::HH) {}
    +
    +namespace Space8 {
    +  struct II;
    +  struct I {
    +    struct II {
    +      void ii(Space8::I::II, I::II) {}
    +    };
    +  };
    +  void iii(Space8::I::II, I::II) {}
    +}
    +
    +struct J;
    +namespace Space9 {
    +  namespace SubSpace9 {
    +    struct J {
    +      void jj(Space9::SubSpace9::J, SubSpace9::J, J) {}
    +    };
    +    void jjj(Space9::SubSpace9::J, SubSpace9::J, J) {}
    +  }
    +}
    +
    +namespace Space10 {
    +  struct K;
    +}
    +namespace Space10 {
    +  namespace SubSpace10 {
    +    struct K {
    +      void kk(Space10::SubSpace10::K, SubSpace10::K, K) {}
    +    };
    +    void kkk(Space10::SubSpace10::K, SubSpace10::K, K) {}
    +  }
    +}
    +
    +namespace OtherSpace {
    +  struct L;
    +  struct M;
    +}
    +using OtherSpace::L;
    +namespace Space11 {
    +  using OtherSpace::M;
    +  namespace SubSpace11 {
    +    struct L {
    +      void ll(Space11::SubSpace11::L, SubSpace11::L, L) {}
    +    };
    +    void lll(Space11::SubSpace11::L, SubSpace11::L, L) {}
    +    struct M {
    +      void mm(Space11::SubSpace11::M, SubSpace11::M, M) {}
    +    };
    +    void mmm(Space11::SubSpace11::M, SubSpace11::M, M) {}
    +  }
    +}
    +
    +%}
    +
    diff --git a/Examples/test-suite/common.mk b/Examples/test-suite/common.mk
    index ab341e7a1..0c896825f 100644
    --- a/Examples/test-suite/common.mk
    +++ b/Examples/test-suite/common.mk
    @@ -136,6 +136,7 @@ CPP_TEST_CASES += \
     	char_binary \
     	char_strings \
     	chartest \
    +	class_scope_namespace \
     	class_forward \
     	class_ignore \
     	class_scope_weird \
    diff --git a/Examples/test-suite/errors/cpp_class_definition.i b/Examples/test-suite/errors/cpp_class_definition.i
    new file mode 100644
    index 000000000..8381e75cc
    --- /dev/null
    +++ b/Examples/test-suite/errors/cpp_class_definition.i
    @@ -0,0 +1,26 @@
    +%module xxx
    +
    +// This should error but doesn't
    +#if 0
    +namespace OtherSpace {
    +  struct L;
    +}
    +namespace Space11 {
    +  namespace SubSpace11 {
    +    using OtherSpace::L;
    +    struct L {
    +      void ll();
    +    };
    +  }
    +}
    +#endif
    +
    +namespace Space1 {
    +  struct A;
    +}
    +namespace Space2 {
    +  struct Space1::A {
    +    void x();
    +  };
    +}
    +
    diff --git a/Examples/test-suite/errors/cpp_class_definition.stderr b/Examples/test-suite/errors/cpp_class_definition.stderr
    new file mode 100644
    index 000000000..2c4102842
    --- /dev/null
    +++ b/Examples/test-suite/errors/cpp_class_definition.stderr
    @@ -0,0 +1 @@
    +cpp_class_definition.i:22: Error: 'Space1::A' resolves to 'Space1::A' and was incorrectly instantiated in scope 'Space2' instead of within scope 'Space1'.
    diff --git a/Examples/test-suite/errors/cpp_namespace_template_bad.i b/Examples/test-suite/errors/cpp_namespace_template_bad.i
    new file mode 100644
    index 000000000..5c42d6dcb
    --- /dev/null
    +++ b/Examples/test-suite/errors/cpp_namespace_template_bad.i
    @@ -0,0 +1,40 @@
    +%module namespace_template
    +
    +namespace test {
    +  template T max(T a, T b) { return (a > b) ? a : b; }
    +  template class vector { 
    +  public:
    +    vector() { }
    +    ~vector() { }
    +  }; 
    +}
    +
    +namespace test2 {
    +  using namespace test;
    +  %template(maxshort) max;
    +  %template(vectorshort) vector;
    +}
    +
    +namespace test3 {
    +  using test::max;
    +  using test::vector;
    +  %template(maxlong) max;
    +  %template(vectorlong) vector;
    +}
    +
    +namespace test4 {
    +  using namespace test;
    +  typedef int Integer;
    +}
    +
    +namespace test4 {
    +  %template(maxInteger) max;
    +  %template(vectorInteger) vector;
    +}
    +
    +using namespace test;
    +namespace test5 {
    +  %template(maxdouble) max;
    +  %template(vectordouble) vector;
    +}
    +
    diff --git a/Examples/test-suite/errors/cpp_namespace_template_bad.stderr b/Examples/test-suite/errors/cpp_namespace_template_bad.stderr
    new file mode 100644
    index 000000000..5965d529c
    --- /dev/null
    +++ b/Examples/test-suite/errors/cpp_namespace_template_bad.stderr
    @@ -0,0 +1,9 @@
    +cpp_namespace_template_bad.i:14: Error: 'max' resolves to 'test::max' and was incorrectly instantiated in scope 'test2' instead of within scope 'test'.
    +cpp_namespace_template_bad.i:15: Error: 'vector' resolves to 'test::vector' and was incorrectly instantiated in scope 'test2' instead of within scope 'test'.
    +cpp_namespace_template_bad.i:21: Error: 'max' resolves to 'test::max' and was incorrectly instantiated in scope 'test3' instead of within scope 'test'.
    +cpp_namespace_template_bad.i:22: Error: 'vector' resolves to 'test::vector' and was incorrectly instantiated in scope 'test3' instead of within scope 'test'.
    +cpp_namespace_template_bad.i:31: Error: 'max' resolves to 'test::max' and was incorrectly instantiated in scope 'test4' instead of within scope 'test'.
    +cpp_namespace_template_bad.i:32: Error: 'vector' resolves to 'test::vector' and was incorrectly instantiated in scope 'test4' instead of within scope 'test'.
    +cpp_namespace_template_bad.i:37: Error: 'max' resolves to 'test::max' and was incorrectly instantiated in scope 'test5' instead of within scope 'test'.
    +cpp_namespace_template_bad.i:37: Error: Template 'max' undefined.
    +cpp_namespace_template_bad.i:38: Error: 'vector' resolves to 'test::vector' and was incorrectly instantiated in scope 'test5' instead of within scope 'test'.
    diff --git a/Examples/test-suite/errors/cpp_nested_template.stderr b/Examples/test-suite/errors/cpp_nested_template.stderr
    index 9e46cff74..363a260f6 100644
    --- a/Examples/test-suite/errors/cpp_nested_template.stderr
    +++ b/Examples/test-suite/errors/cpp_nested_template.stderr
    @@ -1,2 +1,4 @@
    +cpp_nested_template.i:9: Error: 'Temply' resolves to '::Temply' and was incorrectly instantiated in scope 'A' instead of within scope ''.
     cpp_nested_template.i:9: Warning 324: Named nested template instantiations not supported. Processing as if no name was given to %template().
    +cpp_nested_template.i:18: Error: 'Temply' resolves to '::Temply' and was incorrectly instantiated in scope 'B' instead of within scope ''.
     cpp_nested_template.i:18: Warning 324: Named nested template instantiations not supported. Processing as if no name was given to %template().
    diff --git a/Examples/test-suite/errors/cpp_template_scope.i b/Examples/test-suite/errors/cpp_template_scope.i
    new file mode 100644
    index 000000000..ec0f0a577
    --- /dev/null
    +++ b/Examples/test-suite/errors/cpp_template_scope.i
    @@ -0,0 +1,57 @@
    +%module xxx
    +
    +namespace std {
    +  template class vector {};
    +}
    +
    +struct S1 {};
    +struct S2 {};
    +struct S3 {};
    +struct S4 {};
    +struct S5 {};
    +struct S6 {};
    +struct S7 {};
    +
    +// valid
    +namespace std {
    +  %template(vi1) vector;
    +  template class vector;
    +}
    +
    +// valid
    +using namespace std;
    +%template(vi2) vector;
    +template class vector;
    +
    +// valid
    +using std::vector;
    +%template(vi3) vector;
    +template class vector;
    +
    +// ill-formed
    +namespace unrelated {
    +  using std::vector;
    +  %template(vi4) vector;
    +  template class vector;
    +}
    +
    +// ill-formed
    +namespace unrelated {
    +  using namespace std;
    +  %template(vi5) vector;
    +  template class vector;
    +}
    +
    +// ill-formed
    +namespace unrelated {
    +  namespace std {
    +    %template(vi6) vector;
    +    template class vector;
    +  }
    +}
    +
    +// ill-formed
    +namespace unrelated {
    +  %template(vi7) std::vector;
    +  template class std::vector;
    +}
    diff --git a/Examples/test-suite/errors/cpp_template_scope.stderr b/Examples/test-suite/errors/cpp_template_scope.stderr
    new file mode 100644
    index 000000000..e47630268
    --- /dev/null
    +++ b/Examples/test-suite/errors/cpp_template_scope.stderr
    @@ -0,0 +1,11 @@
    +cpp_template_scope.i:18: Warning 320: Explicit template instantiation ignored.
    +cpp_template_scope.i:24: Warning 320: Explicit template instantiation ignored.
    +cpp_template_scope.i:29: Warning 320: Explicit template instantiation ignored.
    +cpp_template_scope.i:34: Error: 'vector' resolves to 'std::vector' and was incorrectly instantiated in scope 'unrelated' instead of within scope 'std'.
    +cpp_template_scope.i:35: Warning 320: Explicit template instantiation ignored.
    +cpp_template_scope.i:41: Error: 'vector' resolves to 'std::vector' and was incorrectly instantiated in scope 'unrelated' instead of within scope 'std'.
    +cpp_template_scope.i:42: Warning 320: Explicit template instantiation ignored.
    +cpp_template_scope.i:48: Error: 'vector' resolves to 'std::vector' and was incorrectly instantiated in scope 'unrelated::std' instead of within scope 'std'.
    +cpp_template_scope.i:49: Warning 320: Explicit template instantiation ignored.
    +cpp_template_scope.i:55: Error: 'std::vector' resolves to 'std::vector' and was incorrectly instantiated in scope 'unrelated' instead of within scope 'std'.
    +cpp_template_scope.i:56: Warning 320: Explicit template instantiation ignored.
    diff --git a/Examples/test-suite/java/class_scope_namespace_runme.java b/Examples/test-suite/java/class_scope_namespace_runme.java
    new file mode 100644
    index 000000000..e80779413
    --- /dev/null
    +++ b/Examples/test-suite/java/class_scope_namespace_runme.java
    @@ -0,0 +1,59 @@
    +
    +import class_scope_namespace.*;
    +
    +public class class_scope_namespace_runme {
    +
    +  static {
    +    try {
    +      System.loadLibrary("class_scope_namespace");
    +    } 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[]) 
    +  {
    +    A a = new A();
    +    B b = new B();
    +    C c = new C();
    +    D d = new D();
    +    E e = new E();
    +    F f = new F();
    +    G g = new G();
    +    H.HH h = new H.HH();
    +    I.II i = new I.II();
    +    J j = new J();
    +    K k = new K();
    +    L l = new L();
    +    M m = new M();
    +
    +    a.aa(a, a, a);
    +    b.bb(b, b);
    +    c.cc(c, c);
    +    d.dd(d, d, d);
    +    e.ee(e, e, e);
    +    f.ff(f, f, f, f);
    +    g.gg(g, g);
    +    h.hh(h);
    +    i.ii(i, i);
    +    j.jj(j, j, j);
    +    k.kk(k, k, k);
    +    l.ll(l, l, l);
    +    m.mm(m, m, m);
    +
    +    class_scope_namespace.aaa(a, a, a);
    +    class_scope_namespace.bbb(b, b);
    +    class_scope_namespace.ccc(c, c);
    +    class_scope_namespace.ddd(d, d, d);
    +    class_scope_namespace.eee(e, e, e);
    +    class_scope_namespace.fff(f, f, f);
    +    class_scope_namespace.ggg(g, g);
    +    class_scope_namespace.hhh(h);
    +    class_scope_namespace.iii(i, i);
    +    class_scope_namespace.jjj(j, j, j);
    +    class_scope_namespace.kkk(k, k, k);
    +    class_scope_namespace.lll(l, l, l);
    +    class_scope_namespace.mmm(m, m, m);
    +  }
    +}
    diff --git a/Examples/test-suite/java/namespace_template_runme.java b/Examples/test-suite/java/namespace_template_runme.java
    new file mode 100644
    index 000000000..c0c7ba135
    --- /dev/null
    +++ b/Examples/test-suite/java/namespace_template_runme.java
    @@ -0,0 +1,32 @@
    +
    +import namespace_template.*;
    +
    +public class namespace_template_runme {
    +
    +  static {
    +    try {
    +      System.loadLibrary("namespace_template");
    +    } 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[]) {
    +    vectorchar vc = new vectorchar();
    +    vectorshort vs = new vectorshort();
    +    vectorint vi = new vectorint();
    +    vectorlong vl = new vectorlong();
    +
    +    vc.blah((char)10);
    +    vs.blah((short)10);
    +    vi.blah(10);
    +    vl.blah(10);
    +
    +    vc.vectoruse(vc, vc);
    +    vs.vectoruse(vs, vs);
    +    vi.vectoruse(vi, vi);
    +    vl.vectoruse(vl, vl);
    +  }
    +}
    +
    diff --git a/Examples/test-suite/namespace_template.i b/Examples/test-suite/namespace_template.i
    index a36abb19b..8a4b6dca9 100644
    --- a/Examples/test-suite/namespace_template.i
    +++ b/Examples/test-suite/namespace_template.i
    @@ -2,10 +2,10 @@
     
     %module namespace_template
     
    -%warnfilter(SWIGWARN_RUBY_WRONG_NAME) vector;            /* Ruby, wrong class name */
    -%warnfilter(SWIGWARN_RUBY_WRONG_NAME) test2::vector;   /* Ruby, wrong class name */
    -%warnfilter(SWIGWARN_RUBY_WRONG_NAME) test3::vector;    /* Ruby, wrong class name */
    -%warnfilter(SWIGWARN_RUBY_WRONG_NAME) vector; /* Ruby, wrong class name */
    +%warnfilter(SWIGWARN_RUBY_WRONG_NAME) test::vector;        /* Ruby, wrong class name */
    +%warnfilter(SWIGWARN_RUBY_WRONG_NAME) test::vector;      /* Ruby, wrong class name */
    +%warnfilter(SWIGWARN_RUBY_WRONG_NAME) test::vector;       /* Ruby, wrong class name */
    +%warnfilter(SWIGWARN_RUBY_WRONG_NAME) test::vector; /* Ruby, wrong class name */
     
     %{
     #ifdef max
    @@ -23,20 +23,9 @@ namespace test {
                char * blah(T x) {
                   return (char *) "vector::blah";
                }
    +           void vectoruse(vector a, test::vector b) {}
        }; 
     }
    -
    -namespace test2 {
    -   using namespace test;
    -}
    -
    -namespace test3 {
    -   using test::max;
    -   using test::vector;
    -}
    -
    -using namespace test2;
    -namespace T4 = test;
     %}
     
     namespace test {
    @@ -48,6 +37,7 @@ namespace test {
                char * blah(T x) {
                   return (char *) "vector::blah";
                }
    +           void vectoruse(vector a, test::vector b) {}
        }; 
     }
     
    @@ -55,30 +45,26 @@ using namespace test;
     %template(maxint) max;
     %template(vectorint) vector;
     
    -namespace test2 {
    -   using namespace test;
    +namespace test {
        %template(maxshort) max;
        %template(vectorshort) vector;
     }
     
    -namespace test3 {
    -   using test::max;
    -   using test::vector;
    +namespace test {
        %template(maxlong) max;
        %template(vectorlong) vector;
     }
     
     %inline %{
     
    -namespace test4 {
    -   using namespace test;
    -   typedef int Integer;
    +namespace test {
    +   typedef char Char;
     }
     
     %}
     
    -namespace test4 {
    -   %template(maxInteger) max;
    -   %template(vectorInteger) vector;
    +namespace test {
    +   %template(maxchar) max;
    +   %template(vectorchar) vector;
     }
     
    diff --git a/Examples/test-suite/smart_pointer_namespace2.i b/Examples/test-suite/smart_pointer_namespace2.i
    index 882799862..e78364c25 100644
    --- a/Examples/test-suite/smart_pointer_namespace2.i
    +++ b/Examples/test-suite/smart_pointer_namespace2.i
    @@ -49,11 +49,6 @@ namespace one
         };
     }
     
    -%define PTR_DEF(o)
    -typedef one::Ptr o ## _ptr;
    -%template(o ## _ptr) one::Ptr;
    -%enddef
    -
     namespace one
     {
         class Obj1
    @@ -63,7 +58,8 @@ namespace one
             void donothing() {}
         };
     
    -    PTR_DEF(Obj1)
    +    typedef one::Ptr Obj1_ptr;
    +    %template(Obj1_ptr) one::Ptr;
     }
     
     namespace two
    @@ -75,6 +71,9 @@ namespace two
             void donothing() {}
         };
     
    -    PTR_DEF(Obj2)
    +    typedef one::Ptr Obj2_ptr;
     }
     
    +using two::Obj2;
    +%template(Obj2_ptr) one::Ptr;
    +
    diff --git a/Examples/test-suite/template_nested_typemaps.i b/Examples/test-suite/template_nested_typemaps.i
    index 54f5bc503..577a88e14 100644
    --- a/Examples/test-suite/template_nested_typemaps.i
    +++ b/Examples/test-suite/template_nested_typemaps.i
    @@ -1,25 +1,30 @@
    -#pragma SWIG nowarn=SWIGWARN_PARSE_NESTED_TEMPLATE
    -
     %module template_nested_typemaps
     
    -// Testing that the typemaps invoked within a class via %template are picked up by appropriate methods
    +#pragma SWIG nowarn=SWIGWARN_PARSE_NAMED_NESTED_CLASS
     
    -template  struct Typemap {
    -  %typemap(in) T {
    -    $1 = -99;
    -  }
    -};
    -template <> struct Typemap { // Note explicit specialization
    -  %typemap(in) short {
    -    $1 = -77;
    -  }
    -};
    +// Testing that the typemaps invoked within a class via %template are picked up by appropriate methods
    +// Only for languages that support nested classes
     
     %inline %{
     int globalInt1(int s) { return s; }
     short globalShort1(short s) { return s; }
     
     template  struct Breeze {
    +  template  struct Typemap {
    +#ifdef SWIG
    +    %typemap(in) TMT {
    +      $1 = -99;
    +    }
    +#endif
    +  };
    +  template  struct TypemapShort {
    +#ifdef SWIG
    +    %typemap(in) short {
    +      $1 = -77;
    +    }
    +#endif
    +  };
    +
       int methodInt1(int s) { return s; }
     #if defined(SWIG)
       %template() Typemap;
    @@ -29,7 +34,7 @@ template  struct Breeze {
     
       short methodShort1(short s) { return s; }
     #if defined(SWIG)
    -  %template(TypemapShort) Typemap; // should issue warning SWIGWARN_PARSE_NESTED_TEMPLATE
    +  %template() TypemapShort;
     #endif
       short methodShort2(short s) { return s; } // should pick up the typemap within Typemap
     };
    diff --git a/Examples/test-suite/template_partial_specialization.i b/Examples/test-suite/template_partial_specialization.i
    index 8781fbbda..a7afd3000 100644
    --- a/Examples/test-suite/template_partial_specialization.i
    +++ b/Examples/test-suite/template_partial_specialization.i
    @@ -32,7 +32,7 @@ namespace One {
     %template(H) One::OneParm;
     
     // %template scope explicit specializations
    -namespace ONE {
    +namespace One {
       %template(I) One::OneParm;
       %template(J) ::One::OneParm;
     }
    @@ -42,7 +42,7 @@ namespace One {
     }
     
     // %template scope partial specializations
    -namespace ONE {
    +namespace One {
       %template(BB) One::OneParm;
       %template(BBB) ::One::OneParm;
     }
    diff --git a/Examples/test-suite/template_partial_specialization_typedef.i b/Examples/test-suite/template_partial_specialization_typedef.i
    index 6fdbf99aa..9c00efc98 100644
    --- a/Examples/test-suite/template_partial_specialization_typedef.i
    +++ b/Examples/test-suite/template_partial_specialization_typedef.i
    @@ -59,7 +59,7 @@ namespace One {
     %template(H) One::OneParm;
     
     // %template scope explicit specializations
    -namespace ONE {
    +namespace One {
       %template(I) One::OneParm;
       %template(J) ::One::OneParm;
     }
    @@ -69,7 +69,7 @@ namespace One {
     }
     
     // %template scope partial specializations
    -namespace ONE {
    +namespace One {
       %template(BB) One::OneParm;
       %template(BBB) ::One::OneParm;
     }
    diff --git a/Source/CParse/parser.y b/Source/CParse/parser.y
    index 69dce5534..30408e73b 100644
    --- a/Source/CParse/parser.y
    +++ b/Source/CParse/parser.y
    @@ -209,7 +209,7 @@ static String *yyrename = 0;
     
     /* Forward renaming operator */
     
    -static String *resolve_create_node_scope(String *cname);
    +static String *resolve_create_node_scope(String *cname, int is_class_definition);
     
     
     Hash *Swig_cparse_features(void) {
    @@ -815,32 +815,53 @@ static String *remove_block(Node *kw, const String *inputcode) {
       return modified_code;
     }
     
    -
    +/*
    +#define RESOLVE_DEBUG 1
    +*/
     static Node *nscope = 0;
     static Node *nscope_inner = 0;
     
     /* Remove the scope prefix from cname and return the base name without the prefix.
      * The scopes required for the symbol name are resolved and/or created, if required.
      * For example AA::BB::CC as input returns CC and creates the namespace AA then inner 
    - * namespace BB in the current scope. If cname is found to already exist as a weak symbol
    - * (forward reference) then the scope might be changed to match, such as when a symbol match 
    - * is made via a using reference. */
    -static String *resolve_create_node_scope(String *cname) {
    + * namespace BB in the current scope. */
    +static String *resolve_create_node_scope(String *cname, int is_class_definition) {
       Symtab *gscope = 0;
       Node *cname_node = 0;
    -  int skip_lookup = 0;
    +  String *last = Swig_scopename_last(cname);
       nscope = 0;
       nscope_inner = 0;  
     
    -  if (Strncmp(cname,"::",2) == 0)
    -    skip_lookup = 1;
    -
    -  cname_node = skip_lookup ? 0 : Swig_symbol_clookup_no_inherit(cname, 0);
    +  if (Strncmp(cname,"::" ,2) != 0) {
    +    if (is_class_definition) {
    +      /* Only lookup symbols which are in scope via a using declaration but not via a using directive.
    +         For example find y via 'using x::y' but not y via a 'using namespace x'. */
    +      cname_node = Swig_symbol_clookup_no_inherit(cname, 0);
    +      if (!cname_node) {
    +	Node *full_lookup_node = Swig_symbol_clookup(cname, 0);
    +	if (full_lookup_node) {
    +	 /* This finds a symbol brought into scope via both a using directive and a using declaration. */
    +	  Node *last_node = Swig_symbol_clookup_no_inherit(last, 0);
    +	  if (last_node == full_lookup_node)
    +	    cname_node = last_node;
    +	}
    +      }
    +    } else {
    +      /* For %template, the template needs to be in scope via any means. */
    +      cname_node = Swig_symbol_clookup(cname, 0);
    +    }
    +  }
    +#if RESOLVE_DEBUG
    +  if (!cname_node)
    +    Printf(stdout, "symbol does not yet exist (%d): [%s]\n", is_class_definition, cname);
    +  else
    +    Printf(stdout, "symbol does exist (%d): [%s]\n", is_class_definition, cname);
    +#endif
     
       if (cname_node) {
         /* The symbol has been defined already or is in another scope.
    -       If it is a weak symbol, it needs replacing and if it was brought into the current scope
    -       via a using declaration, the scope needs adjusting appropriately for the new symbol.
    +       If it is a weak symbol, it needs replacing and if it was brought into the current scope,
    +       the scope needs adjusting appropriately for the new symbol.
            Similarly for defined templates. */
         Symtab *symtab = Getattr(cname_node, "sym:symtab");
         Node *sym_weak = Getattr(cname_node, "sym:weak");
    @@ -848,48 +869,92 @@ static String *resolve_create_node_scope(String *cname) {
           /* Check if the scope is the current scope */
           String *current_scopename = Swig_symbol_qualifiedscopename(0);
           String *found_scopename = Swig_symbol_qualifiedscopename(symtab);
    -      int len;
           if (!current_scopename)
     	current_scopename = NewString("");
           if (!found_scopename)
     	found_scopename = NewString("");
    -      len = Len(current_scopename);
    -      if ((len > 0) && (Strncmp(current_scopename, found_scopename, len) == 0)) {
    -	if (Len(found_scopename) > len + 2) {
    -	  /* A matching weak symbol was found in non-global scope, some scope adjustment may be required */
    -	  String *new_cname = NewString(Char(found_scopename) + len + 2); /* skip over "::" prefix */
    -	  String *base = Swig_scopename_last(cname);
    -	  Printf(new_cname, "::%s", base);
    -	  cname = new_cname;
    -	  Delete(base);
    -	} else {
    -	  /* A matching weak symbol was found in the same non-global local scope, no scope adjustment required */
    -	  assert(len == Len(found_scopename));
    +
    +      {
    +	int fail = 1;
    +	List *current_scopes = Swig_scopename_tolist(current_scopename);
    +	List *found_scopes = Swig_scopename_tolist(found_scopename);
    +        Iterator cit = First(current_scopes);
    +	Iterator fit = First(found_scopes);
    +#if RESOLVE_DEBUG
    +Printf(stdout, "comparing current: [%s] found: [%s]\n", current_scopename, found_scopename);
    +#endif
    +	for (; fit.item && cit.item; fit = Next(fit), cit = Next(cit)) {
    +	  String *current = cit.item;
    +	  String *found = fit.item;
    +#if RESOLVE_DEBUG
    +	  Printf(stdout, "  looping %s %s\n", current, found);
    +#endif
    +	  if (Strcmp(current, found) != 0)
    +	    break;
     	}
    -      } else {
    -	String *base = Swig_scopename_last(cname);
    -	if (Len(found_scopename) > 0) {
    -	  /* A matching weak symbol was found in a different scope to the local scope - probably via a using declaration */
    -	  cname = NewStringf("%s::%s", found_scopename, base);
    +
    +	if (!cit.item) {
    +	  String *subscope = NewString("");
    +	  for (; fit.item; fit = Next(fit)) {
    +	    if (Len(subscope) > 0)
    +	      Append(subscope, "::");
    +	    Append(subscope, fit.item);
    +	  }
    +	  if (Len(subscope) > 0)
    +	    cname = NewStringf("%s::%s", subscope, last);
    +	  else
    +	    cname = Copy(last);
    +#if RESOLVE_DEBUG
    +	  Printf(stdout, "subscope to create: [%s] cname: [%s]\n", subscope, cname);
    +#endif
    +	  fail = 0;
    +	  Delete(subscope);
     	} else {
    -	  /* Either:
    -	      1) A matching weak symbol was found in a different scope to the local scope - this is actually a
    -	      symbol with the same name in a different scope which we don't want, so no adjustment required.
    -	      2) A matching weak symbol was found in the global scope - no adjustment required.
    -	  */
    -	  cname = Copy(base);
    +	  if (is_class_definition) {
    +	    if (!fit.item) {
    +	      /* It is valid to define a new class with the same name as one forward declared in a parent scope */
    +	      fail = 0;
    +	    } else if (Swig_scopename_check(cname)) {
    +	      /* Classes defined with scope qualifiers must have a matching forward declaration in matching scope */
    +	      fail = 1;
    +	    } else {
    +	      /* This may let through some invalid cases */
    +	      fail = 0;
    +	    }
    +#if RESOLVE_DEBUG
    +	    Printf(stdout, "scope for class definition, fail: %d\n", fail);
    +#endif
    +	  } else {
    +#if RESOLVE_DEBUG
    +	    Printf(stdout, "no matching base scope for template\n");
    +#endif
    +	    fail = 1;
    +	  }
    +	}
    +
    +	Delete(found_scopes);
    +	Delete(current_scopes);
    +
    +	if (fail) {
    +	  String *cname_resolved = NewStringf("%s::%s", found_scopename, last);
    +	  Swig_error(cparse_file, cparse_line, "'%s' resolves to '%s' and was incorrectly instantiated in scope '%s' instead of within scope '%s'.\n", cname, cname_resolved, current_scopename, found_scopename);
    +	  cname = Copy(last);
    +	  Delete(cname_resolved);
     	}
    -	Delete(base);
           }
    +
           Delete(current_scopename);
           Delete(found_scopename);
         }
    +  } else if (!is_class_definition) {
    +    /* A template instantiation requires a template to be found in scope... fail here too?
    +    Swig_error(cparse_file, cparse_line, "No template found to instantiate '%s' with %%template.\n", cname);
    +     */
       }
     
       if (Swig_scopename_check(cname)) {
         Node   *ns;
         String *prefix = Swig_scopename_prefix(cname);
    -    String *base = Swig_scopename_last(cname);
         if (prefix && (Strncmp(prefix,"::",2) == 0)) {
     /* I don't think we can use :: global scope to declare classes and hence neither %template. - consider reporting error instead - wsfulton. */
           /* Use the global scope */
    @@ -899,6 +964,7 @@ static String *resolve_create_node_scope(String *cname) {
           gscope = set_scope_to_global();
         }
         if (Len(prefix) == 0) {
    +      String *base = Copy(last);
           /* Use the global scope, but we need to add a 'global' namespace.  */
           if (!gscope) gscope = set_scope_to_global();
           /* note that this namespace is not the "unnamed" one,
    @@ -907,6 +973,7 @@ static String *resolve_create_node_scope(String *cname) {
           nscope = new_node("namespace");
           Setattr(nscope,"symtab", gscope);;
           nscope_inner = nscope;
    +      Delete(last);
           return base;
         }
         /* Try to locate the scope */
    @@ -924,7 +991,7 @@ static String *resolve_create_node_scope(String *cname) {
     	String *nname = Swig_symbol_qualifiedscopename(nstab);
     	if (tname && (Strcmp(tname,nname) == 0)) {
     	  ns = 0;
    -	  cname = base;
    +	  cname = Copy(last);
     	}
     	Delete(tname);
     	Delete(nname);
    @@ -932,19 +999,10 @@ static String *resolve_create_node_scope(String *cname) {
           if (ns) {
     	/* we will try to create a new node using the namespaces we
     	   can find in the scope name */
    -	List *scopes;
    +	List *scopes = Swig_scopename_tolist(prefix);
     	String *sname;
     	Iterator si;
    -	String *name = NewString(prefix);
    -	scopes = NewList();
    -	while (name) {
    -	  String *base = Swig_scopename_last(name);
    -	  String *tprefix = Swig_scopename_prefix(name);
    -	  Insert(scopes,0,base);
    -	  Delete(base);
    -	  Delete(name);
    -	  name = tprefix;
    -	}
    +
     	for (si = First(scopes); si.item; si = Next(si)) {
     	  Node *ns1,*ns2;
     	  sname = si.item;
    @@ -990,12 +1048,13 @@ static String *resolve_create_node_scope(String *cname) {
     	  nscope_inner = ns2;
     	  if (!nscope) nscope = ns2;
     	}
    -	cname = base;
    +	cname = Copy(last);
     	Delete(scopes);
           }
         }
         Delete(prefix);
       }
    +  Delete(last);
     
       return cname;
     }
    @@ -2631,9 +2690,8 @@ template_directive: SWIGTEMPLATE LPAREN idstringopt RPAREN idcolonnt LESSTHAN va
     		  tscope = Swig_symbol_current();          /* Get the current scope */
     
     		  /* If the class name is qualified, we need to create or lookup namespace entries */
    -		  if (!inclass) {
    -		    $5 = resolve_create_node_scope($5);
    -		  }
    +		  $5 = resolve_create_node_scope($5, 0);
    +
     		  if (nscope_inner && Strcmp(nodeType(nscope_inner), "class") == 0) {
     		    outer_class	= nscope_inner;
     		  }
    @@ -3520,7 +3578,7 @@ cpp_class_decl  : storage_class cpptype idcolon inherit LBRACE {
     		   Setattr($$,"prev_symtab",Swig_symbol_current());
     		  
     		   /* If the class name is qualified.  We need to create or lookup namespace/scope entries */
    -		   scope = resolve_create_node_scope($3);
    +		   scope = resolve_create_node_scope($3, 1);
     		   /* save nscope_inner to the class - it may be overwritten in nested classes*/
     		   Setattr($$, "nested:innerscope", nscope_inner);
     		   Setattr($$, "nested:nscope", nscope);
    diff --git a/Source/Swig/misc.c b/Source/Swig/misc.c
    index cfa0c68b3..f80fb678f 100644
    --- a/Source/Swig/misc.c
    +++ b/Source/Swig/misc.c
    @@ -823,10 +823,11 @@ String *Swig_string_emangle(String *s) {
     
     
     /* -----------------------------------------------------------------------------
    - * Swig_scopename_prefix()
    + * Swig_scopename_split()
      *
    - * Take a qualified name like "A::B::C" and return the scope name.
    - * In this case, "A::B".   Returns NULL if there is no base.
    + * Take a qualified name like "A::B::C" and splits off the last name.
    + * In this case, returns "C" as last and "A::B" as prefix.
    + * Always returns non NULL for last, but prefix may be NULL if there is no prefix.
      * ----------------------------------------------------------------------------- */
     
     void Swig_scopename_split(const String *s, String **rprefix, String **rlast) {
    @@ -882,6 +883,12 @@ void Swig_scopename_split(const String *s, String **rprefix, String **rlast) {
       }
     }
     
    +/* -----------------------------------------------------------------------------
    + * Swig_scopename_prefix()
    + *
    + * Take a qualified name like "A::B::C" and return the scope name.
    + * In this case, "A::B".   Returns NULL if there is no base.
    + * ----------------------------------------------------------------------------- */
     
     String *Swig_scopename_prefix(const String *s) {
       char *tmp = Char(s);
    @@ -1067,6 +1074,31 @@ String *Swig_scopename_suffix(const String *s) {
       }
     }
     
    +/* -----------------------------------------------------------------------------
    + * Swig_scopename_tolist()
    + *
    + * Take a qualified scope name like "A::B::C" and convert it to a list.
    + * In this case, return a list of 3 elements "A", "B", "C".
    + * Returns an empty list if the input is empty.
    + * ----------------------------------------------------------------------------- */
    +
    +List *Swig_scopename_tolist(const String *s) {
    +  List *scopes = NewList();
    +  String *name = Len(s) == 0 ? 0 : NewString(s);
    +
    +  while (name) {
    +    String *last = 0;
    +    String *prefix = 0;
    +    Swig_scopename_split(name, &prefix, &last);
    +    Insert(scopes, 0, last);
    +    Delete(last);
    +    Delete(name);
    +    name = prefix;
    +  }
    +  Delete(name);
    +  return scopes;
    +}
    +
     /* -----------------------------------------------------------------------------
      * Swig_scopename_check()
      *
    diff --git a/Source/Swig/swig.h b/Source/Swig/swig.h
    index f25f0993e..0bcd53a66 100644
    --- a/Source/Swig/swig.h
    +++ b/Source/Swig/swig.h
    @@ -326,6 +326,7 @@ extern int        ParmList_is_compactdefargs(ParmList *p);
       extern String *Swig_scopename_last(const String *s);
       extern String *Swig_scopename_first(const String *s);
       extern String *Swig_scopename_suffix(const String *s);
    +  extern List *Swig_scopename_tolist(const String *s);
       extern int Swig_scopename_check(const String *s);
       extern String *Swig_string_lower(String *s);
       extern String *Swig_string_upper(String *s);
    
    From 1434449041eee60fb13dfe9a0ddea6be88fc88df Mon Sep 17 00:00:00 2001
    From: William S Fulton 
    Date: Wed, 9 Aug 2017 09:15:50 +0100
    Subject: [PATCH 240/455] Testcase fix for nameclash in php
    
    ---
     .../test-suite/template_parameters_global_scope.i    | 12 ++++++------
     1 file changed, 6 insertions(+), 6 deletions(-)
    
    diff --git a/Examples/test-suite/template_parameters_global_scope.i b/Examples/test-suite/template_parameters_global_scope.i
    index 4c14ba4a3..a828187b5 100644
    --- a/Examples/test-suite/template_parameters_global_scope.i
    +++ b/Examples/test-suite/template_parameters_global_scope.i
    @@ -9,17 +9,17 @@ namespace Alloc {
     %}
     
     %inline %{
    -struct Bucket {};
    -typedef Bucket TDBucket;
    -typedef ::Bucket TDGlobalBucket;
    +struct Bucket_ {};
    +typedef Bucket_ TDBucket;
    +typedef ::Bucket_ TDGlobalBucket;
     %}
     
     // Check 1: %template no unary scope operator
    -%template(RebindBucket) Alloc::Rebind< Bucket >;
    +%template(RebindBucket) Alloc::Rebind< Bucket_ >;
     
     %inline %{
    -Alloc::Rebind< Bucket >::Integer Bucket1() { return 1; }
    -Alloc::Rebind< ::Bucket >::Integer Bucket2() { return 2; }
    +Alloc::Rebind< Bucket_ >::Integer Bucket1() { return 1; }
    +Alloc::Rebind< ::Bucket_ >::Integer Bucket2() { return 2; }
     Alloc::Rebind< TDBucket >::Integer Bucket3() { return 3; }
     Alloc::Rebind< ::TDBucket >::Integer Bucket4() { return 4; }
     Alloc::Rebind< TDGlobalBucket >::Integer Bucket5() { return 5; }
    
    From 8bf81b8718ba413f66a9dc41e06a50f113e68edd Mon Sep 17 00:00:00 2001
    From: William S Fulton 
    Date: Wed, 9 Aug 2017 20:54:32 +0100
    Subject: [PATCH 241/455] More docs on %template
    
    ---
     Doc/Manual/SWIGPlus.html | 14 ++++++++++++++
     1 file changed, 14 insertions(+)
    
    diff --git a/Doc/Manual/SWIGPlus.html b/Doc/Manual/SWIGPlus.html
    index 13c81588d..28e0e839f 100644
    --- a/Doc/Manual/SWIGPlus.html
    +++ b/Doc/Manual/SWIGPlus.html
    @@ -3109,6 +3109,20 @@ not necessary to instantiate a new class for the type Integer (doing so
     redundant and will simply result in code bloat).
     

    +

    +The template provide to %template for instantiation must be the actual template and not a typedef to a template. +

    + +
    +
    +typedef List<int> ListOfInt;
    +
    +%template(intList) List<int>; // ok
    +%template(intList) ListOfInt; // illegal - Syntax error
    +
    +
    + +

    6.18.2 Function templates

    From bf98c5304faed50fa0c1f09228c55f21fcb06691 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Sat, 12 Aug 2017 10:11:38 +0100 Subject: [PATCH 242/455] Fix type lookup in the presence of using directives and using declarations Fix some cases of type lookup failure via a combination of both using directives and using declarations resulting in C++ code that did not compile as the generated type was not fully qualified for use in the global namespace. Example below: namespace Space5 { namespace SubSpace5 { namespace SubSubSpace5 { struct F {}; } } using namespace SubSpace5; using SubSubSpace5::F; void func(SubSubSpace5::F f); } --- Examples/test-suite/class_scope_namespace.i | 3 +- Examples/test-suite/common.mk | 1 + .../java/class_scope_namespace_runme.java | 2 +- .../java/namespace_chase_runme.java | 26 +++++ Examples/test-suite/namespace_chase.i | 36 +++++++ Source/Swig/typesys.c | 101 +++++++++++++----- 6 files changed, 139 insertions(+), 30 deletions(-) create mode 100644 Examples/test-suite/java/namespace_chase_runme.java create mode 100644 Examples/test-suite/namespace_chase.i diff --git a/Examples/test-suite/class_scope_namespace.i b/Examples/test-suite/class_scope_namespace.i index 08a9f01dc..372727f3c 100644 --- a/Examples/test-suite/class_scope_namespace.i +++ b/Examples/test-suite/class_scope_namespace.i @@ -73,8 +73,7 @@ namespace Space5 { struct SubSubSpace5::F { void ff(Space5::SubSpace5::SubSubSpace5::F, SubSpace5::SubSubSpace5::F, SubSubSpace5::F, F) {} }; -// needs fixing - void fff(Space5::SubSpace5::SubSubSpace5::F, SubSpace5::SubSubSpace5::F, /*SubSubSpace5::F,*/ F) {} + void fff(Space5::SubSpace5::SubSubSpace5::F, SubSpace5::SubSubSpace5::F, SubSubSpace5::F, F) {} } namespace Space6 { diff --git a/Examples/test-suite/common.mk b/Examples/test-suite/common.mk index 0c896825f..ce6544279 100644 --- a/Examples/test-suite/common.mk +++ b/Examples/test-suite/common.mk @@ -292,6 +292,7 @@ CPP_TEST_CASES += \ multiple_inheritance_shared_ptr \ name_cxx \ name_warnings \ + namespace_chase \ namespace_class \ namespace_enum \ namespace_extend \ diff --git a/Examples/test-suite/java/class_scope_namespace_runme.java b/Examples/test-suite/java/class_scope_namespace_runme.java index e80779413..9d74a6ca6 100644 --- a/Examples/test-suite/java/class_scope_namespace_runme.java +++ b/Examples/test-suite/java/class_scope_namespace_runme.java @@ -47,7 +47,7 @@ public class class_scope_namespace_runme { class_scope_namespace.ccc(c, c); class_scope_namespace.ddd(d, d, d); class_scope_namespace.eee(e, e, e); - class_scope_namespace.fff(f, f, f); + class_scope_namespace.fff(f, f, f, f); class_scope_namespace.ggg(g, g); class_scope_namespace.hhh(h); class_scope_namespace.iii(i, i); diff --git a/Examples/test-suite/java/namespace_chase_runme.java b/Examples/test-suite/java/namespace_chase_runme.java new file mode 100644 index 000000000..9b4898bd0 --- /dev/null +++ b/Examples/test-suite/java/namespace_chase_runme.java @@ -0,0 +1,26 @@ + +import namespace_chase.*; + +public class namespace_chase_runme { + + static { + try { + System.loadLibrary("namespace_chase"); + } 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[]) + { + Struct1A s1a = new Struct1A(); + Struct1B s1b = new Struct1B(); + Struct1C s1c = new Struct1C(); + + namespace_chase.sss3a(s1a, s1b, s1c); + namespace_chase.sss3b(s1a, s1b, s1c); + // needs fixing +// namespace_chase.sss3c(s1a, s1b, s1c); + } +} diff --git a/Examples/test-suite/namespace_chase.i b/Examples/test-suite/namespace_chase.i new file mode 100644 index 000000000..5e3921d0d --- /dev/null +++ b/Examples/test-suite/namespace_chase.i @@ -0,0 +1,36 @@ +%module namespace_chase + +%inline %{ + namespace Space1A { + struct Struct1A {}; + namespace Space1B { + struct Struct1B {}; + namespace Space1C { + struct Struct1C {}; + } + } + } + namespace Space2A { + using namespace Space1A; + namespace Space2B { + using namespace Space1B; + namespace Space2C { + using namespace Space1C; + } + } + } + namespace Space3 { + using namespace Space2A; + void sss3a(Space1A::Struct1A, Space1A::Space1B::Struct1B, Space1A::Space1B::Space1C::Struct1C) {} + void sss3b(Struct1A, Space1B::Struct1B, Space1B::Space1C::Struct1C) {} + // To fix: the last two parameters below fail and result in SWIGTYPE_ types instead of proxy classes + void sss3c(Space2A::Struct1A, Space2A::Space1B::Struct1B, Space2A::Space1B::Space1C::Struct1C) {} + } + namespace Space4 { + using namespace Space2A; + using namespace Space2A::Space2B; + using namespace Space2A::Space2B::Space2C; + void sss4a(Struct1A, Struct1B, Space2C::Struct1C) {} + void sss4b(Struct1A, Struct1B, Struct1C) {} + } +%} diff --git a/Source/Swig/typesys.c b/Source/Swig/typesys.c index 2fb514d5e..e460b422a 100644 --- a/Source/Swig/typesys.c +++ b/Source/Swig/typesys.c @@ -53,8 +53,7 @@ * typedef A B; * typedef B *C; * - * typetab is built as follows: - * + * typetab in scope '' contains: * "A" : "int" * "B" : "A" * "C" : "p.B" @@ -67,31 +66,76 @@ * ---> a(40).p.p.A (B --> A) * ---> a(40).p.p.int (A --> int) * + * + * Using declarations are stored in the "typetab" hash table. For example, + * + * namespace NN { + * struct SS {}; + * } + * namespace N { + * struct S {}; + * using NN::SS; + * } + * using N::S; + * + * typetab in scope '' contains: + * "S" : "N::S" + * + * and typetab in scope 'N' contains: + * "SS" : "NN::SS" + * "S" : "S" + * + * * For inheritance, SWIG tries to resolve types back to the base class. For instance, if * you have this: * - * class Foo { - * public: - * typedef int Integer; - * }; + * class Foo { + * public: + * typedef int Integer; + * }; + * struct Bar : public Foo { + * void blah(Integer x); + * }; * - * class Bar : public Foo { - * void blah(Integer x); - * }; + * In this case typetab in scope '' contains: + * "Foo" : "Foo" + * "Bar" : "Bar" + * and scope 'Foo' contains: + * "Integer" : "int" + * and scope 'Bar' inherits from 'Foo' but is empty (observe that blah is not a scope or typedef) * * The argument type of Bar::blah will be set to Foo::Integer. * + * + * The scope-inheritance mechanism is used to manage C++ using directives. + * + * namespace XX { + * class CC {}; + * } + * namespace X { + * class C {}; + * using namespace XX; + * } + * using namespace X; + * + * typetab in scope '' inherits from 'X' + * typetab in scope 'X' inherits from 'XX' and contains: + * "C" : "C" + * typetab in scope 'XX' contains: + * "CC" : "CC" + * + * * The scope-inheritance mechanism is used to manage C++ namespace aliases. * For example, if you have this: * - * namespace Foo { - * typedef int Integer; - * } + * namespace Foo { + * typedef int Integer; + * } * - * namespace F = Foo; + * namespace F = Foo; * - * In this case, "F::" is defined as a scope that "inherits" from Foo. Internally, - * "F::" will merely be an empty scope that refers to Foo. SWIG will never + * In this case, F is defined as a scope that "inherits" from Foo. Internally, + * F will merely be an empty scope that points to Foo. SWIG will never * place new type information into a namespace alias---attempts to do so * will generate a warning message (in the parser) and will place information into * Foo instead. @@ -968,8 +1012,17 @@ SwigType *SwigType_typedef_resolve_all(const SwigType *t) { /* ----------------------------------------------------------------------------- * SwigType_typedef_qualified() * - * Given a type declaration, this function tries to fully qualify it according to - * typedef scope rules. + * Given a type declaration, this function tries to fully qualify it so that the + * resulting type can be used in the global scope. The type name is resolved in + * the current scope. + * + * It provides a fully qualified name, not necessarily a fully expanded name. + * When a using declaration or using directive is found the type may not be fully + * expanded, but it will be resolved and fully qualified for use in the global scope. + * + * This function is for looking up scopes to qualify a type. It does not resolve + * C typedefs, it just qualifies them. See SwigType_typedef_resolve for resolving. + * * If the unary scope operator (::) is used as a prefix to the type to denote global * scope, it is left in place. * ----------------------------------------------------------------------------- */ @@ -1030,20 +1083,14 @@ SwigType *SwigType_typedef_qualified(const SwigType *t) { out of the current scope */ Typetab *cs = current_scope; - while (cs) { - String *qs = SwigType_scope_name(cs); - if (Len(qs)) { - Append(qs, "::"); - } - Append(qs, e); - if (Getattr(scopes, qs)) { + if (cs) { + Typetab *found_scope = SwigType_find_scope(cs, e); + if (found_scope) { + String *qs = SwigType_scope_name(found_scope); Clear(e); Append(e, qs); Delete(qs); - break; } - Delete(qs); - cs = Getattr(cs, "parent"); } } } From 96e99416d76c3e0201a7b60417a0c24f845ba5b8 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Tue, 15 Aug 2017 22:38:03 +0100 Subject: [PATCH 243/455] Add using declarations to templates into typedef table. Fixes #1051. Using declarations to templates were missing in SWIG's internal typedef tables. This led to a few problems, such as, templates that did not instantiate and generated C++ code that did not compile as SWIG did not know what scope the template was in. This happened mostly when a using declaration was used on a template type in a completely unrelated namespace. --- Examples/test-suite/common.mk | 1 + ...rective_and_declaration_forward_runme.java | 10 ++--- ...emplate_using_directive_typedef_runme.java | 31 +++++++++++++ .../template_using_directive_typedef_runme.py | 15 +++++++ Source/Modules/typepass.cxx | 3 -- Source/Swig/typesys.c | 45 +++++++++++++++---- 6 files changed, 89 insertions(+), 16 deletions(-) create mode 100644 Examples/test-suite/java/template_using_directive_typedef_runme.java create mode 100644 Examples/test-suite/python/template_using_directive_typedef_runme.py diff --git a/Examples/test-suite/common.mk b/Examples/test-suite/common.mk index ce6544279..e5e60a330 100644 --- a/Examples/test-suite/common.mk +++ b/Examples/test-suite/common.mk @@ -436,6 +436,7 @@ CPP_TEST_CASES += \ template_methods \ template_namespace_forward_declaration \ template_using_directive_and_declaration_forward \ + template_using_directive_typedef \ template_nested \ template_nested_typemaps \ template_ns \ diff --git a/Examples/test-suite/java/template_using_directive_and_declaration_forward_runme.java b/Examples/test-suite/java/template_using_directive_and_declaration_forward_runme.java index 080945e02..3aab5fa8f 100644 --- a/Examples/test-suite/java/template_using_directive_and_declaration_forward_runme.java +++ b/Examples/test-suite/java/template_using_directive_and_declaration_forward_runme.java @@ -19,32 +19,32 @@ public class template_using_directive_and_declaration_forward_runme { template_using_directive_and_declaration_forward.useit1b(new Thing1Int()); template_using_directive_and_declaration_forward.useit1c(new Thing1Int()); -//BROKEN template_using_directive_and_declaration_forward.useit2(new Thing2Int()); + template_using_directive_and_declaration_forward.useit2(new Thing2Int()); template_using_directive_and_declaration_forward.useit2a(new Thing2Int()); template_using_directive_and_declaration_forward.useit2b(new Thing2Int()); template_using_directive_and_declaration_forward.useit2c(new Thing2Int()); template_using_directive_and_declaration_forward.useit2d(new Thing2Int()); -//BROKEN template_using_directive_and_declaration_forward.useit3(new Thing3Int()); + template_using_directive_and_declaration_forward.useit3(new Thing3Int()); template_using_directive_and_declaration_forward.useit3a(new Thing3Int()); template_using_directive_and_declaration_forward.useit3b(new Thing3Int()); template_using_directive_and_declaration_forward.useit3c(new Thing3Int()); template_using_directive_and_declaration_forward.useit3d(new Thing3Int()); -//BROKEN template_using_directive_and_declaration_forward.useit4(new Thing4Int()); + template_using_directive_and_declaration_forward.useit4(new Thing4Int()); template_using_directive_and_declaration_forward.useit4a(new Thing4Int()); template_using_directive_and_declaration_forward.useit4b(new Thing4Int()); template_using_directive_and_declaration_forward.useit4c(new Thing4Int()); template_using_directive_and_declaration_forward.useit4d(new Thing4Int()); -//BROKEN template_using_directive_and_declaration_forward.useit5(new Thing5Int()); + template_using_directive_and_declaration_forward.useit5(new Thing5Int()); template_using_directive_and_declaration_forward.useit5a(new Thing5Int()); template_using_directive_and_declaration_forward.useit5b(new Thing5Int()); template_using_directive_and_declaration_forward.useit5c(new Thing5Int()); template_using_directive_and_declaration_forward.useit5d(new Thing5Int()); -//BROKEN template_using_directive_and_declaration_forward.useit7(new Thing7Int()); + template_using_directive_and_declaration_forward.useit7(new Thing7Int()); template_using_directive_and_declaration_forward.useit7a(new Thing7Int()); template_using_directive_and_declaration_forward.useit7b(new Thing7Int()); template_using_directive_and_declaration_forward.useit7c(new Thing7Int()); diff --git a/Examples/test-suite/java/template_using_directive_typedef_runme.java b/Examples/test-suite/java/template_using_directive_typedef_runme.java new file mode 100644 index 000000000..bec077399 --- /dev/null +++ b/Examples/test-suite/java/template_using_directive_typedef_runme.java @@ -0,0 +1,31 @@ + +import template_using_directive_typedef.*; + +public class template_using_directive_typedef_runme { + + static { + try { + System.loadLibrary("template_using_directive_typedef"); + } 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[]) { + Vector_Obj vo = new Vector_Obj(); + + Holder h = new Holder(); + h.holder_use1(vo, vo, vo); + h.holder_use2(vo, vo, vo); + h.holder_use3(vo, vo, vo); + + template_using_directive_typedef.tns_holder_use(vo, vo); + template_using_directive_typedef.tns_use(vo, vo, vo); + template_using_directive_typedef.global_holder_use(vo); + template_using_directive_typedef.global_use(vo, vo, vo); + template_using_directive_typedef.ns1_holder_use(vo); + template_using_directive_typedef.ns2_holder_use(vo, vo, vo, vo); + } +} + diff --git a/Examples/test-suite/python/template_using_directive_typedef_runme.py b/Examples/test-suite/python/template_using_directive_typedef_runme.py new file mode 100644 index 000000000..363a3b754 --- /dev/null +++ b/Examples/test-suite/python/template_using_directive_typedef_runme.py @@ -0,0 +1,15 @@ +import template_using_directive_typedef + +vo = template_using_directive_typedef.Vector_Obj(); + +h = template_using_directive_typedef.Holder(); +h.holder_use1(vo, vo, vo); +h.holder_use2(vo, vo, vo); +h.holder_use3(vo, vo, vo); + +template_using_directive_typedef.tns_holder_use(vo, vo); +template_using_directive_typedef.tns_use(vo, vo, vo); +template_using_directive_typedef.global_holder_use(vo); +template_using_directive_typedef.global_use(vo, vo, vo); +template_using_directive_typedef.ns1_holder_use(vo); +template_using_directive_typedef.ns2_holder_use(vo, vo, vo, vo); diff --git a/Source/Modules/typepass.cxx b/Source/Modules/typepass.cxx index bf8028c29..43ada4d4b 100644 --- a/Source/Modules/typepass.cxx +++ b/Source/Modules/typepass.cxx @@ -1199,10 +1199,7 @@ class TypePass:private Dispatcher { } else if (Strcmp(ntype, "enum") == 0) { SwigType_typedef_using(Getattr(n, "uname")); } else if (Strcmp(ntype, "template") == 0) { - /* - Printf(stdout, "usingDeclaration template %s --- %s\n", Getattr(n, "name"), Getattr(n, "uname")); SwigType_typedef_using(Getattr(n, "uname")); - */ } } } diff --git a/Source/Swig/typesys.c b/Source/Swig/typesys.c index e460b422a..409e28f35 100644 --- a/Source/Swig/typesys.c +++ b/Source/Swig/typesys.c @@ -42,10 +42,15 @@ * "name" - Scope name * "qname" - Fully qualified typename * "typetab" - Type table containing typenames and typedef information + * For a given key in the typetab table, the value is a fully + * qualified name if not pointing to itself. * "symtab" - Hash table of symbols defined in a scope * "inherit" - List of inherited scopes * "parent" - Parent scope * + * The contents of these tables can be viewed for debugging using the -debug-typedef + * option which calls SwigType_print_scope(). + * * Typedef information is stored in the "typetab" hash table. For example, * if you have these declarations: * @@ -210,6 +215,7 @@ void SwigType_typesystem_init() { * ----------------------------------------------------------------------------- */ int SwigType_typedef(const SwigType *type, const_String_or_char_ptr name) { + /* Printf(stdout, "typedef %s %s\n", type, name); */ if (Getattr(current_typetab, name)) return -1; /* Already defined */ if (Strcmp(type, name) == 0) { /* Can't typedef a name to itself */ @@ -660,6 +666,17 @@ static SwigType *typedef_resolve(Typetab *s, String *base) { /* ----------------------------------------------------------------------------- * SwigType_typedef_resolve() + * + * Given a type declaration, this function looks to reduce/resolve the type via a + * typedef (including via C++ using declarations). + * + * If it is able to find a typedef, the resolved type is returned. If no typedef + * is found NULL is returned. The type name is resolved in the current scope. + * The type returned is not always fully qualified for the global scope, it is + * valid for use in the current scope. If the current scope is global scope, a + * fully qualified type should be returned. + * + * Some additional notes are in Doc/Manual/Extending.html. * ----------------------------------------------------------------------------- */ /* #define SWIG_DEBUG */ @@ -786,6 +803,25 @@ SwigType *SwigType_typedef_resolve(const SwigType *t) { } } + if (!type && SwigType_istemplate(base)) { + String *tprefix = SwigType_templateprefix(base); + String *rtprefix = SwigType_typedef_resolve(tprefix); + /* We're looking for a using declaration on the template prefix to resolve the template prefix + * in another scope. Using declaration do not have template parameters. */ + if (rtprefix && !SwigType_istemplate(rtprefix)) { + String *tsuffix = SwigType_templatesuffix(base); + String *targs = SwigType_templateargs(base); + type = NewString(rtprefix); + newtype = 1; + Append(type, targs); + Append(type, tsuffix); + Delete(targs); + Delete(tsuffix); + Delete(rtprefix); + } + Delete(tprefix); + } + if (type && (Equal(base, type))) { if (newtype) Delete(type); @@ -1106,10 +1142,6 @@ SwigType *SwigType_typedef_qualified(const SwigType *t) { Parm *p; List *parms; ty = Swig_symbol_template_deftype(e, current_symtab); - /* - String *dt = Swig_symbol_template_deftype(e, current_symtab); - ty = Swig_symbol_type_qualify(dt, 0); - */ e = ty; parms = SwigType_parmlist(e); tprefix = SwigType_templateprefix(e); @@ -1176,9 +1208,6 @@ SwigType *SwigType_typedef_qualified(const SwigType *t) { Delete(tprefix); Delete(qprefix); Delete(parms); - /* - Delete(dt); - */ } Append(result, e); Delete(ty); @@ -1258,7 +1287,7 @@ int SwigType_typedef_using(const_String_or_char_ptr name) { String *defined_name = 0; - /* Printf(stdout,"using %s\n", name); */ + /* Printf(stdout, "using %s\n", name); */ if (!Swig_scopename_check(name)) return -1; /* Not properly qualified */ From 09af283371edab461a4ddd0df147ce86e8547c04 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Tue, 15 Aug 2017 23:12:55 +0100 Subject: [PATCH 244/455] Test a few %template errors --- Examples/test-suite/errors/cpp_invalid_template.i | 9 +++++++++ Examples/test-suite/errors/cpp_invalid_template.stderr | 3 +++ 2 files changed, 12 insertions(+) create mode 100644 Examples/test-suite/errors/cpp_invalid_template.i create mode 100644 Examples/test-suite/errors/cpp_invalid_template.stderr diff --git a/Examples/test-suite/errors/cpp_invalid_template.i b/Examples/test-suite/errors/cpp_invalid_template.i new file mode 100644 index 000000000..ea0d7beac --- /dev/null +++ b/Examples/test-suite/errors/cpp_invalid_template.i @@ -0,0 +1,9 @@ +%module cpp_invalid_scope + +%template(abc) SSS::AAA; + +namespace UUU { + struct JJJ; +} + +%template(xxx) UUU::JJJ; diff --git a/Examples/test-suite/errors/cpp_invalid_template.stderr b/Examples/test-suite/errors/cpp_invalid_template.stderr new file mode 100644 index 000000000..f6bfaaf7d --- /dev/null +++ b/Examples/test-suite/errors/cpp_invalid_template.stderr @@ -0,0 +1,3 @@ +cpp_invalid_template.i:3: Error: Undefined scope 'SSS' +cpp_invalid_template.i:3: Error: Template 'SSS::AAA' undefined. +cpp_invalid_template.i:9: Error: 'JJJ' is not defined as a template. (classforward) From 902a141540a14c96f19c448dd0d18fb79413d47d Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Wed, 16 Aug 2017 07:56:28 +0100 Subject: [PATCH 245/455] Fix testcase failure on Node Javascript --- Examples/test-suite/preproc.i | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Examples/test-suite/preproc.i b/Examples/test-suite/preproc.i index 8ed8c1a09..8d9c5176f 100644 --- a/Examples/test-suite/preproc.i +++ b/Examples/test-suite/preproc.i @@ -372,8 +372,9 @@ int methodX(int x) { return x+100; } // Comma in macro - Github issue #974 %inline %{ -#define __attribute__(x) -#define TCX_PACKED(d) d __attribute__ ((__packed__)) +#define swig__attribute__(x) +#define TCX_PACKED(d) d swig__attribute__ ((__packed__)) + TCX_PACKED (typedef struct tcxMessageTestImpl { From 8813343920e8d92e287377485848aad132eae880 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Wed, 16 Aug 2017 07:57:30 +0100 Subject: [PATCH 246/455] Remove stray blank line print in php test --- Examples/test-suite/php5/php_pragma_runme.php | 1 - 1 file changed, 1 deletion(-) diff --git a/Examples/test-suite/php5/php_pragma_runme.php b/Examples/test-suite/php5/php_pragma_runme.php index ae92f6818..c76cfc9b5 100644 --- a/Examples/test-suite/php5/php_pragma_runme.php +++ b/Examples/test-suite/php5/php_pragma_runme.php @@ -9,4 +9,3 @@ check::equal('1.5',(new ReflectionExtension('php_pragma'))->getVersion(),"1.5==v check::done(); ?> - From 1132bc334b399e20f420b4abdd00eb2c20463887 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Wed, 16 Aug 2017 22:05:26 +0100 Subject: [PATCH 247/455] Add recent template and scope fixes into changes file --- CHANGES.current | 155 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 155 insertions(+) diff --git a/CHANGES.current b/CHANGES.current index 808bd1798..4e3aebafd 100644 --- a/CHANGES.current +++ b/CHANGES.current @@ -7,6 +7,161 @@ the issue number to the end of the URL: https://github.com/swig/swig/issues/ Version 4.0.0 (in progress) =========================== +2017-08-16: wsfulton + Fix #1051. Add using declarations to templates into typedef table. + + Using declarations to templates were missing in SWIG's internal typedef tables. + This led to a few problems, such as, templates that did not instantiate and generated + C++ code that did not compile as SWIG did not know what scope the template was + in. This happened mostly when a using declaration was used on a template type in a + completely unrelated namespace. + +2017-08-16: wsfulton + Fix type lookup in the presence of using directives and using declarations. + + Fix some cases of type lookup failure via a combination of both using directives and + using declarations resulting in C++ code that did not compile as the generated type was + not fully qualified for use in the global namespace. Example below: + + namespace Space5 { + namespace SubSpace5 { + namespace SubSubSpace5 { + struct F {}; + } + } + using namespace SubSpace5; + using SubSubSpace5::F; + void func(SubSubSpace5::F f); + } + +2017-08-16: wsfulton + %template scope enforcement and class definition fixes. + + The scoping rules around %template have been specified and enforced. + The %template directive for a class template is the equivalent to an + explicit instantiation of a C++ class template. The scope for a valid + %template instantiation is now the same as the scope required for a + valid explicit instantiation of a C++ template. A definition of the + template for the explicit instantiation must be in scope where the + instantiation is declared and must not be enclosed within a different + namespace. + + For example, a few %template and C++ explicit instantiations of std::vector + are shown below: + + // valid + namespace std { + %template(vin) vector; + template class vector; + } + + // valid + using namespace std; + %template(vin) vector; + template class vector; + + // valid + using std::vector; + %template(vin) vector; + template class vector; + + // ill-formed + namespace unrelated { + using std::vector; + %template(vin) vector; + template class vector; + } + + // ill-formed + namespace unrelated { + using namespace std; + %template(vin) vector; + template class vector; + } + + // ill-formed + namespace unrelated { + namespace std { + %template(vin) vector; + template class vector; + } + } + + // ill-formed + namespace unrelated { + %template(vin) std::vector; + template class std::vector; + } + + When the scope is incorrect, an error now occurs such as: + + cpp_template_scope.i:34: Error: 'vector' resolves to 'std::vector' and + was incorrectly instantiated in scope 'unrelated' instead of within scope 'std'. + + Previously SWIG accepted the ill-formed examples above but this led to + numerous subtle template scope problems especially in the presence of + using declarations and using directives as well as with %feature and %typemap. + + Actually, a valid instantiation is one which conforms to the C++03 + standard as C++11 made a change to disallow using declarations and + using directives to find a template. + + // valid C++03, ill-formed C++11 + using std::vector; + template class vector; + + Similar fixes for defining classes using forward class references have + also been put in place. For example: + + namespace Space1 { + struct A; + } + namespace Space2 { + struct Space1::A { + void x(); + } + } + + will now error out with: + + cpp_class_definition.i:5: Error: 'Space1::A' resolves to 'Space1::A' and + was incorrectly instantiated in scope 'Space2' instead of within scope 'Space1'. + +2017-08-16: wsfulton + Fix scope lookup for template parameters containing unary scope operators. + + Fixes cases like: + + namespace Alloc { + template struct Rebind { + typedef int Integer; + }; + } + %template(RebindBucket) Alloc::Rebind< Bucket >; + OR + %template(RebindBucket) Alloc::Rebind< ::Bucket >; + + Alloc::Rebind< Bucket >::Integer Bucket1(); + Alloc::Rebind< ::Bucket >::Integer Bucket2(); + Alloc::Rebind<::template TemplateBucket>::Integer Bucket3(); + +2017-08-16: wsfulton + For templates only, the template parameters are fully resolved when + handling typemaps. Without this, it is too hard to have decent rules + to apply typemaps when parameter types are typedef'd and template + parameters have default values. + + Fixes %clear for typedefs in templates, eg: + + %typemap("in") XXX::Long "..." + template typename struct XXX { + typedef long Long; + }; + %clear XXX::Long; + + as the typemap was previously incorrectly stored as a typemap for long + instead of XXX::Long. + 2017-08-05: olly [C++11] Allow static_assert at the top level (and disallow it right after template). Fixes https://github.com/swig/swig/issues/1031 From 9f454234b1e15e421c51c20b42cb1d78a66800ea Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Wed, 16 Aug 2017 22:15:17 +0100 Subject: [PATCH 248/455] Add missing template_using_directive_typedef.i test file --- .../template_using_directive_typedef.i | 44 +++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 Examples/test-suite/template_using_directive_typedef.i diff --git a/Examples/test-suite/template_using_directive_typedef.i b/Examples/test-suite/template_using_directive_typedef.i new file mode 100644 index 000000000..1c8bcb9dd --- /dev/null +++ b/Examples/test-suite/template_using_directive_typedef.i @@ -0,0 +1,44 @@ +%module template_using_directive_typedef + +%inline %{ +namespace space { + template class Vector {}; + class VectorClass {}; +} +struct Obj {}; +%} + +%template(Vector_Obj) space::Vector; + +%inline %{ +namespace tns { + using space::Vector; // template using directives were not being added into the typedef table + using space::VectorClass; + typedef Vector NSVec; +} +%} + +%inline %{ +namespace tns { + struct Holder { +// using Vec = Vector; + typedef Vector Vec; + typedef VectorClass VecClass; + Vec items; + void holder_use1(space::Vector, tns::NSVec, tns::Vector) {} + void holder_use2(space::Vector, NSVec, Vector) {} + void holder_use3(tns::Holder::Vec, Holder::Vec, Vec) {} + }; + void tns_holder_use(tns::Holder::Vec, Holder::Vec) {} + void tns_use(space::Vector, NSVec, tns::NSVec) {} +} +void global_holder_use(tns::Holder::Vec) {} +void global_use(space::Vector, tns::NSVec, tns::Vector) {} +namespace ns1 { + void ns1_holder_use(tns::Holder::Vec) {} +} +namespace ns2 { + using namespace tns; + void ns2_holder_use(tns::Holder::Vec, Holder::Vec, NSVec, Vector) {} +} +%} From 11d105080399f5089dbf24f4acc61d388c5f90a8 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Wed, 16 Aug 2017 22:18:29 +0100 Subject: [PATCH 249/455] Correct issue numbers in changes file --- CHANGES.current | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGES.current b/CHANGES.current index 4e3aebafd..0629dfbb6 100644 --- a/CHANGES.current +++ b/CHANGES.current @@ -8,7 +8,7 @@ Version 4.0.0 (in progress) =========================== 2017-08-16: wsfulton - Fix #1051. Add using declarations to templates into typedef table. + Fix #1063. Add using declarations to templates into typedef table. Using declarations to templates were missing in SWIG's internal typedef tables. This led to a few problems, such as, templates that did not instantiate and generated @@ -35,7 +35,7 @@ Version 4.0.0 (in progress) } 2017-08-16: wsfulton - %template scope enforcement and class definition fixes. + Issue #1051. %template scope enforcement and class definition fixes. The scoping rules around %template have been specified and enforced. The %template directive for a class template is the equivalent to an From dd3d04a2f2f2a05d5fc3bedac0a177e7caf6d1bd Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Thu, 17 Aug 2017 10:28:41 +0100 Subject: [PATCH 250/455] Fix testcase for clang --- Examples/test-suite/class_scope_namespace.i | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Examples/test-suite/class_scope_namespace.i b/Examples/test-suite/class_scope_namespace.i index 372727f3c..730c076aa 100644 --- a/Examples/test-suite/class_scope_namespace.i +++ b/Examples/test-suite/class_scope_namespace.i @@ -20,9 +20,17 @@ namespace Space2 { struct B; } using Space2::B; +#ifdef __clang__ +namespace Space2 { + struct B { + void bb(Space2::B, B) {} + }; +} +#else struct B { void bb(Space2::B, B) {} }; +#endif void bbb(Space2::B, B) {} namespace Space3 { From 9e19fe7868d6d901c45329873ba02f09a7942542 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Sat, 19 Aug 2017 01:02:34 +0100 Subject: [PATCH 251/455] C++11 ref-qualifier support added Fixes #1059 Methods with rvalue ref-qualifiers are ignored by default as it is not possible to have an rvalue temporary from the target language (which is needed to call the rvalue ref-qualified method). A warning 405 is shown mentioning the ignored rvalue ref-qualifier method which can be seen with the -Wextra option. cpp_refqualifier.i:15: Warning 405: Method with rvalue ref-qualifier ignored h() const &&. Usually rvalue and lvalue ref-qualifier overloaded methods are written - the lvalue method will then be wrapped. --- Examples/test-suite/common.mk | 1 + Examples/test-suite/cpp11_ref_qualifiers.i | 16 ++++ Examples/test-suite/errors/cpp_refqualifier.i | 18 +++++ .../test-suite/errors/cpp_refqualifier.stderr | 6 ++ .../java/cpp11_ref_qualifiers_runme.java | 22 ++++++ .../python/cpp11_ref_qualifiers_runme.py | 6 ++ Source/CParse/parser.y | 74 ++++++++++++++++--- Source/Include/swigwarn.h | 1 + Source/Modules/main.cxx | 15 ++-- Source/Swig/naming.c | 4 + 10 files changed, 145 insertions(+), 18 deletions(-) create mode 100644 Examples/test-suite/cpp11_ref_qualifiers.i create mode 100644 Examples/test-suite/errors/cpp_refqualifier.i create mode 100644 Examples/test-suite/errors/cpp_refqualifier.stderr create mode 100644 Examples/test-suite/java/cpp11_ref_qualifiers_runme.java create mode 100644 Examples/test-suite/python/cpp11_ref_qualifiers_runme.py diff --git a/Examples/test-suite/common.mk b/Examples/test-suite/common.mk index e3448dcbc..b47b6e33b 100644 --- a/Examples/test-suite/common.mk +++ b/Examples/test-suite/common.mk @@ -561,6 +561,7 @@ CPP11_TEST_CASES += \ cpp11_noexcept \ cpp11_null_pointer_constant \ cpp11_raw_string_literals \ + cpp11_ref_qualifiers \ cpp11_result_of \ cpp11_rvalue_reference \ cpp11_rvalue_reference2 \ diff --git a/Examples/test-suite/cpp11_ref_qualifiers.i b/Examples/test-suite/cpp11_ref_qualifiers.i new file mode 100644 index 000000000..fa1d68d0e --- /dev/null +++ b/Examples/test-suite/cpp11_ref_qualifiers.i @@ -0,0 +1,16 @@ +%module cpp11_ref_qualifiers + +%inline %{ +class Host { +public: + void h1() & {} + void h2() const & {} + void h3() && {} + void h4() const && {} + + void h() & {} + void h() const & {} + void h() && {} + void h() const && {} +}; +%} diff --git a/Examples/test-suite/errors/cpp_refqualifier.i b/Examples/test-suite/errors/cpp_refqualifier.i new file mode 100644 index 000000000..1cbcd936d --- /dev/null +++ b/Examples/test-suite/errors/cpp_refqualifier.i @@ -0,0 +1,18 @@ +%module cpp_refqualifier + +%ignore Host::h_ignored; + +class Host { +public: + void h1() &; + void h2() const &; + void h3() &&; + void h4() const &&; + + void h() &; + void h() const &; + void h() &&; + void h() const &&; + + void h_ignored() &&; +}; diff --git a/Examples/test-suite/errors/cpp_refqualifier.stderr b/Examples/test-suite/errors/cpp_refqualifier.stderr new file mode 100644 index 000000000..866d9b530 --- /dev/null +++ b/Examples/test-suite/errors/cpp_refqualifier.stderr @@ -0,0 +1,6 @@ +cpp_refqualifier.i:9: Warning 405: Method with rvalue ref-qualifier ignored h3() &&. +cpp_refqualifier.i:10: Warning 405: Method with rvalue ref-qualifier ignored h4() const &&. +cpp_refqualifier.i:14: Warning 405: Method with rvalue ref-qualifier ignored h() &&. +cpp_refqualifier.i:15: Warning 405: Method with rvalue ref-qualifier ignored h() const &&. +cpp_refqualifier.i:13: Warning 512: Overloaded method Host::h() const & ignored, +cpp_refqualifier.i:12: Warning 512: using non-const method Host::h() & instead. diff --git a/Examples/test-suite/java/cpp11_ref_qualifiers_runme.java b/Examples/test-suite/java/cpp11_ref_qualifiers_runme.java new file mode 100644 index 000000000..49afe8039 --- /dev/null +++ b/Examples/test-suite/java/cpp11_ref_qualifiers_runme.java @@ -0,0 +1,22 @@ + +import cpp11_ref_qualifiers.*; + +public class cpp11_ref_qualifiers_runme { + + static { + try { + System.loadLibrary("cpp11_ref_qualifiers"); + } 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[]) { + Host h = new Host(); + h.h1(); + h.h2(); + h.h(); + } +} + diff --git a/Examples/test-suite/python/cpp11_ref_qualifiers_runme.py b/Examples/test-suite/python/cpp11_ref_qualifiers_runme.py new file mode 100644 index 000000000..24ce1d2bf --- /dev/null +++ b/Examples/test-suite/python/cpp11_ref_qualifiers_runme.py @@ -0,0 +1,6 @@ +import cpp11_ref_qualifiers + +h = cpp11_ref_qualifiers.Host() +h.h1() +h.h2() +h.h() diff --git a/Source/CParse/parser.y b/Source/CParse/parser.y index a4167b12d..9a101b1d2 100644 --- a/Source/CParse/parser.y +++ b/Source/CParse/parser.y @@ -485,6 +485,16 @@ static void add_symbols(Node *n) { SetFlag(n,"deleted"); SetFlag(n,"feature:ignore"); } + { + String *refqualifier = Getattr(n, "refqualifier"); + if (Equal(refqualifier, "&&") && strncmp(Char(symname), "$ignore", 7) != 0) { + SWIG_WARN_NODE_BEGIN(n); + Swig_warning(WARN_TYPE_RVALUE_REF_QUALIFIER_IGNORED, Getfile(n), Getline(n), + "Method with rvalue ref-qualifier ignored %s.\n", Swig_name_decl(n)); + SWIG_WARN_NODE_END(n); + SetFlag(n, "feature:ignore"); + } + } } if (only_csymbol || GetFlag(n,"feature:ignore") || strncmp(Char(symname),"$ignore",7) == 0) { /* Only add to C symbol table and continue */ @@ -1451,6 +1461,7 @@ static String *add_qualifier_to_declarator(SwigType *type, SwigType *qualifier) String *rawval; int type; String *qualifier; + String *refqualifier; String *bitfield; Parm *throws; String *throwf; @@ -1560,7 +1571,7 @@ static String *add_qualifier_to_declarator(SwigType *type, SwigType *qualifier) /* Misc */ %type identifier; -%type initializer cpp_const exception_specification; +%type initializer cpp_const exception_specification cv_ref_qualifier; %type storage_class extern_string; %type parms ptail rawparms varargs_parms ; %type templateparameters templateparameterstail; @@ -1576,7 +1587,8 @@ static String *add_qualifier_to_declarator(SwigType *type, SwigType *qualifier) %type expr exprnum exprcompound valexpr; %type ename ; %type less_valparms_greater; -%type type_qualifier ; +%type type_qualifier; +%type ref_qualifier; %type type_qualifier_raw; %type idstring idstringopt; %type pragma_lang; @@ -3063,6 +3075,7 @@ c_decl : storage_class type declarator initializer c_decl_tail { $$ = new_node("cdecl"); if ($4.qualifier) decl = add_qualifier_to_declarator($3.type, $4.qualifier); + Setattr($$,"refqualifier",$4.refqualifier); Setattr($$,"type",$2); Setattr($$,"storage",$1); Setattr($$,"name",$3.id); @@ -3136,6 +3149,7 @@ c_decl : storage_class type declarator initializer c_decl_tail { | storage_class AUTO declarator cpp_const ARROW cpp_alternate_rettype initializer c_decl_tail { $$ = new_node("cdecl"); if ($4.qualifier) SwigType_push($3.type, $4.qualifier); + Setattr($$,"refqualifier",$4.refqualifier); Setattr($$,"type",$6); Setattr($$,"storage",$1); Setattr($$,"name",$3.id); @@ -3198,6 +3212,7 @@ c_decl_tail : SEMI { | COMMA declarator initializer c_decl_tail { $$ = new_node("cdecl"); if ($3.qualifier) SwigType_push($2.type,$3.qualifier); + Setattr($$,"refqualifier",$3.refqualifier); Setattr($$,"name",$2.id); Setattr($$,"decl",$2.type); Setattr($$,"parms",$2.parms); @@ -3236,13 +3251,15 @@ c_decl_tail : SEMI { initializer : def_args { $$ = $1; $$.qualifier = 0; + $$.refqualifier = 0; $$.throws = 0; $$.throwf = 0; $$.nexcept = 0; } - | type_qualifier def_args { + | cv_ref_qualifier def_args { $$ = $2; - $$.qualifier = $1; + $$.qualifier = $1.qualifier; + $$.refqualifier = $1.refqualifier; $$.throws = 0; $$.throwf = 0; $$.nexcept = 0; @@ -3250,13 +3267,15 @@ initializer : def_args { | exception_specification def_args { $$ = $2; $$.qualifier = 0; + $$.refqualifier = 0; $$.throws = $1.throws; $$.throwf = $1.throwf; $$.nexcept = $1.nexcept; } - | type_qualifier exception_specification def_args { + | cv_ref_qualifier exception_specification def_args { $$ = $3; - $$.qualifier = $1; + $$.qualifier = $1.qualifier; + $$.refqualifier = $1.refqualifier; $$.throws = $2.throws; $$.throwf = $2.throwf; $$.nexcept = $2.nexcept; @@ -4809,6 +4828,7 @@ cpp_vend : cpp_const SEMI { Clear(scanner_ccode); $$.val = 0; $$.qualifier = $1.qualifier; + $$.refqualifier = 0; $$.bitfield = 0; $$.throws = $1.throws; $$.throwf = $1.throwf; @@ -4818,6 +4838,7 @@ cpp_vend : cpp_const SEMI { Clear(scanner_ccode); $$.val = $3.val; $$.qualifier = $1.qualifier; + $$.refqualifier = 0; $$.bitfield = 0; $$.throws = $1.throws; $$.throwf = $1.throwf; @@ -4827,6 +4848,7 @@ cpp_vend : cpp_const SEMI { skip_balanced('{','}'); $$.val = 0; $$.qualifier = $1.qualifier; + $$.refqualifier = 0; $$.bitfield = 0; $$.throws = $1.throws; $$.throwf = $1.throwf; @@ -5828,6 +5850,29 @@ pointer : STAR type_qualifier pointer { } ; +/* cv-qualifier plus C++11 ref-qualifier for non-static member functions */ +cv_ref_qualifier : type_qualifier { + $$.qualifier = $1; + $$.refqualifier = 0; + } + | type_qualifier ref_qualifier { + $$.qualifier = $1; + $$.refqualifier = $2; + } + | ref_qualifier { + $$.qualifier = 0; + $$.refqualifier = $1; + } + ; + +ref_qualifier : AND { + $$ = NewString("&"); + } + | LAND { + $$ = NewString("&&"); + } + ; + type_qualifier : type_qualifier_raw { $$ = NewStringEmpty(); if ($1) SwigType_add_qualifier($$,$1); @@ -6049,6 +6094,7 @@ definetype : { /* scanner_check_typedef(); */ } expr { $$.rawval = NewStringf("%s", $$.val); } $$.qualifier = 0; + $$.refqualifier = 0; $$.bitfield = 0; $$.throws = 0; $$.throwf = 0; @@ -6074,6 +6120,7 @@ deleted_definition : DELETE_KW { $$.rawval = 0; $$.type = T_STRING; $$.qualifier = 0; + $$.refqualifier = 0; $$.bitfield = 0; $$.throws = 0; $$.throwf = 0; @@ -6087,6 +6134,7 @@ explicit_default : DEFAULT { $$.rawval = 0; $$.type = T_STRING; $$.qualifier = 0; + $$.refqualifier = 0; $$.bitfield = 0; $$.throws = 0; $$.throwf = 0; @@ -6616,25 +6664,29 @@ exception_specification : THROW LPAREN parms RPAREN { } ; -cpp_const : type_qualifier { +cpp_const : cv_ref_qualifier { $$.throws = 0; $$.throwf = 0; $$.nexcept = 0; - $$.qualifier = $1; + $$.qualifier = $1.qualifier; + $$.refqualifier = $1.refqualifier; } | exception_specification { $$ = $1; $$.qualifier = 0; + $$.refqualifier = 0; } - | type_qualifier exception_specification { + | cv_ref_qualifier exception_specification { $$ = $2; - $$.qualifier = $1; + $$.qualifier = $1.qualifier; + $$.refqualifier = $1.refqualifier; } | empty { $$.throws = 0; $$.throwf = 0; $$.nexcept = 0; - $$.qualifier = 0; + $$.qualifier = 0; + $$.refqualifier = 0; } ; diff --git a/Source/Include/swigwarn.h b/Source/Include/swigwarn.h index 0b4c7eeb5..dd32aef3a 100644 --- a/Source/Include/swigwarn.h +++ b/Source/Include/swigwarn.h @@ -153,6 +153,7 @@ #define WARN_TYPE_INCOMPLETE 402 #define WARN_TYPE_ABSTRACT 403 #define WARN_TYPE_REDEFINED 404 +#define WARN_TYPE_RVALUE_REF_QUALIFIER_IGNORED 405 #define WARN_TYPEMAP_SOURCETARGET 450 #define WARN_TYPEMAP_CHARLEAK 451 diff --git a/Source/Modules/main.cxx b/Source/Modules/main.cxx index 12b83b2e4..9822b6af7 100644 --- a/Source/Modules/main.cxx +++ b/Source/Modules/main.cxx @@ -38,14 +38,15 @@ int NoExcept = 0; int SwigRuntime = 0; // 0 = no option, 1 = -runtime, 2 = -noruntime /* Suppress warning messages for private inheritance, preprocessor evaluation etc... - WARN_PP_EVALUATION 202 - WARN_PARSE_PRIVATE_INHERIT 309 - WARN_TYPE_ABSTRACT 403 - WARN_LANG_OVERLOAD_CONST 512 - WARN_PARSE_BUILTIN_NAME 321 - WARN_PARSE_REDUNDANT 322 + WARN_PP_EVALUATION 202 + WARN_PARSE_PRIVATE_INHERIT 309 + WARN_PARSE_BUILTIN_NAME 321 + WARN_PARSE_REDUNDANT 322 + WARN_TYPE_ABSTRACT 403 + WARN_TYPE_RVALUE_REF_QUALIFIER_IGNORED 405 + WARN_LANG_OVERLOAD_CONST 512 */ -#define EXTRA_WARNINGS "202,309,403,512,321,322" +#define EXTRA_WARNINGS "202,309,403,405,512,321,322" extern "C" { extern String *ModuleName; diff --git a/Source/Swig/naming.c b/Source/Swig/naming.c index ce1dbe806..69b9e2190 100644 --- a/Source/Swig/naming.c +++ b/Source/Swig/naming.c @@ -1681,6 +1681,7 @@ String *Swig_name_str(Node *n) { * "MyNameSpace::MyTemplate::~MyTemplate()" * "MyNameSpace::ABC::ABC(int,double)" * "MyNameSpace::ABC::constmethod(int) const" + * "MyNameSpace::ABC::refqualifiermethod(int) const &" * "MyNameSpace::ABC::variablename" * * ----------------------------------------------------------------------------- */ @@ -1688,6 +1689,7 @@ String *Swig_name_str(Node *n) { String *Swig_name_decl(Node *n) { String *qname; String *decl; + String *refqualifier = Getattr(n, "refqualifier"); qname = Swig_name_str(n); @@ -1695,6 +1697,8 @@ String *Swig_name_decl(Node *n) { decl = NewStringf("%s", qname); else decl = NewStringf("%s(%s)%s", qname, ParmList_errorstr(Getattr(n, "parms")), SwigType_isconst(Getattr(n, "decl")) ? " const" : ""); + if (refqualifier) + Printv(decl, " ", refqualifier, NIL); Delete(qname); From 685ee6cdc46bd4833851e0a55f535e9cfd18a978 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Sat, 19 Aug 2017 09:38:19 +0100 Subject: [PATCH 252/455] Use normal SWIG encodings for ref-qualifiers --- Source/CParse/parser.y | 8 +++++--- Source/Swig/naming.c | 7 +++++-- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/Source/CParse/parser.y b/Source/CParse/parser.y index 9a101b1d2..80ec8611e 100644 --- a/Source/CParse/parser.y +++ b/Source/CParse/parser.y @@ -487,7 +487,7 @@ static void add_symbols(Node *n) { } { String *refqualifier = Getattr(n, "refqualifier"); - if (Equal(refqualifier, "&&") && strncmp(Char(symname), "$ignore", 7) != 0) { + if (SwigType_isrvalue_reference(refqualifier) && strncmp(Char(symname), "$ignore", 7) != 0) { SWIG_WARN_NODE_BEGIN(n); Swig_warning(WARN_TYPE_RVALUE_REF_QUALIFIER_IGNORED, Getfile(n), Getline(n), "Method with rvalue ref-qualifier ignored %s.\n", Swig_name_decl(n)); @@ -5866,10 +5866,12 @@ cv_ref_qualifier : type_qualifier { ; ref_qualifier : AND { - $$ = NewString("&"); + $$ = NewStringEmpty(); + SwigType_add_reference($$); } | LAND { - $$ = NewString("&&"); + $$ = NewStringEmpty(); + SwigType_add_rvalue_reference($$); } ; diff --git a/Source/Swig/naming.c b/Source/Swig/naming.c index 69b9e2190..4fa32538f 100644 --- a/Source/Swig/naming.c +++ b/Source/Swig/naming.c @@ -1697,8 +1697,11 @@ String *Swig_name_decl(Node *n) { decl = NewStringf("%s", qname); else decl = NewStringf("%s(%s)%s", qname, ParmList_errorstr(Getattr(n, "parms")), SwigType_isconst(Getattr(n, "decl")) ? " const" : ""); - if (refqualifier) - Printv(decl, " ", refqualifier, NIL); + if (refqualifier) { + String *rq = SwigType_str(refqualifier, 0); + Printv(decl, " ", rq, NIL); + Delete(rq); + } Delete(qname); From 665b09ffc99109d2c0939a2965d460508e55ec13 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Mon, 21 Aug 2017 18:34:51 +0100 Subject: [PATCH 253/455] Fix seg fault with %interface and using declarations --- Source/Modules/interface.cxx | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/Source/Modules/interface.cxx b/Source/Modules/interface.cxx index f6d4c955b..fee6cd7da 100644 --- a/Source/Modules/interface.cxx +++ b/Source/Modules/interface.cxx @@ -151,12 +151,14 @@ void Swig_interface_propagate_methods(Node *n) { for (Node *child = firstChild(n); child; child = nextSibling(child)) { if (Getattr(child, "interface:owner")) break; // at the end of the list are newly appended methods - if (checkAttribute(child, "name", name)) { - String *decl = SwigType_typedef_resolve_all(Getattr(child, "decl")); - identically_overloaded_method = Strcmp(decl, this_decl_resolved) == 0; - Delete(decl); - if (identically_overloaded_method) - break; + if (Cmp(nodeType(child), "cdecl") == 0) { + if (checkAttribute(child, "name", name)) { + String *decl = SwigType_typedef_resolve_all(Getattr(child, "decl")); + identically_overloaded_method = Strcmp(decl, this_decl_resolved) == 0; + Delete(decl); + if (identically_overloaded_method) + break; + } } } } From fbada9959c8412fd13ca858bca1918e3d5c33359 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Sun, 27 Aug 2017 11:11:32 +0100 Subject: [PATCH 254/455] Fix types when calling PyTuple_New Replace int with Py_ssize_t to fix warnings on Windows when using -O and/or -builtin. --- Lib/python/builtin.swg | 4 ++-- Source/Modules/python.cxx | 7 ++++--- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/Lib/python/builtin.swg b/Lib/python/builtin.swg index 4fd19471a..99903a9b5 100644 --- a/Lib/python/builtin.swg +++ b/Lib/python/builtin.swg @@ -393,10 +393,10 @@ SwigPyStaticVar_new_getset(PyTypeObject *type, PyGetSetDef *getset) { SWIGINTERN void SwigPyBuiltin_InitBases (PyTypeObject *type, PyTypeObject **bases) { - int base_count = 0; + Py_ssize_t base_count = 0; PyTypeObject **b; PyObject *tuple; - int i; + Py_ssize_t i; if (!bases[0]) { bases[0] = SwigPyObject_type(); diff --git a/Source/Modules/python.cxx b/Source/Modules/python.cxx index 64905bc21..9039f07ca 100644 --- a/Source/Modules/python.cxx +++ b/Source/Modules/python.cxx @@ -2927,9 +2927,9 @@ public: Clear(f->def); if (overname) { if (noargs) { - Printv(f->def, linkage, wrap_return, wname, "(PyObject *", self_param, ", int nobjs, PyObject **SWIGUNUSEDPARM(swig_obj)) {", NIL); + Printv(f->def, linkage, wrap_return, wname, "(PyObject *", self_param, ", Py_ssize_t nobjs, PyObject **SWIGUNUSEDPARM(swig_obj)) {", NIL); } else { - Printv(f->def, linkage, wrap_return, wname, "(PyObject *", self_param, ", int nobjs, PyObject **swig_obj) {", NIL); + Printv(f->def, linkage, wrap_return, wname, "(PyObject *", self_param, ", Py_ssize_t nobjs, PyObject **swig_obj) {", NIL); } Printf(parse_args, "if ((nobjs < %d) || (nobjs > %d)) SWIG_fail;\n", num_required, num_arguments); } else { @@ -3238,7 +3238,8 @@ public: DelWrapper(f); f = NewWrapper(); if (funpack) { - Printv(f->def, linkage, wrap_return, wname, "(PyObject *", self_param, ", int nobjs, PyObject **swig_obj) {", NIL); + // Note: funpack is currently always false for varargs + Printv(f->def, linkage, wrap_return, wname, "(PyObject *", self_param, ", Py_ssize_t nobjs, PyObject **swig_obj) {", NIL); } else { Printv(f->def, linkage, wrap_return, wname, "(PyObject *", self_param, ", PyObject *args) {", NIL); } From 175ab4e720266727f371e7f33381f2c6fecc5297 Mon Sep 17 00:00:00 2001 From: Jesse Rusak Date: Tue, 29 Aug 2017 11:00:23 -0400 Subject: [PATCH 255/455] Avoid possible GC issues in Java example code This prevents the previously-set element value from being collected before or during the call to setElement. Since C++ could still have a reference to during that time, it could lead to misbehavior. --- Doc/Manual/Java.html | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/Doc/Manual/Java.html b/Doc/Manual/Java.html index 85757d1cb..fd57fda25 100644 --- a/Doc/Manual/Java.html +++ b/Doc/Manual/Java.html @@ -8165,13 +8165,10 @@ public class Container { // Ensure that the GC doesn't collect any Element set from Java // as the underlying C++ class stores a shallow copy private Element elementReference; - private long getCPtrAndAddReference(Element element) { - elementReference = element; - return Element.getCPtr(element); - } public void setElement(Element e) { - exampleJNI.Container_setElement(swigCPtr, this, getCPtrAndAddReference(e), e); + exampleJNI.Container_setElement(swigCPtr, this, Element.getCPtr(e), e); + elementReference = e; } }
    @@ -8179,22 +8176,20 @@ public class Container {

    The following typemaps will generate the desired code. -The 'javain' typemap matches the input parameter type for the setElement method. +The 'javain' typemap matches the input parameter type for the setElement method and allows adding code after the call. The 'javacode' typemap simply adds in the specified code into the Java proxy class.

    -%typemap(javain) Element *e "getCPtrAndAddReference($javainput)"
    +%typemap(javain, 
    +         post="elementReference = $javainput;\n"
    +         ) Element *e "Element.getCPtr($javainput)"
     
     %typemap(javacode) Container %{
       // Ensure that the GC doesn't collect any element set from Java
       // as the underlying C++ class stores a shallow copy
       private Element elementReference;
    -  private long getCPtrAndAddReference(Element element) {
    -    elementReference = element;
    -    return Element.getCPtr(element);
    -  }
     %}
     
    From eeab1529016f34e6f2f8e6e95f8cb465d73d4d6a Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Sun, 20 Aug 2017 23:09:04 +0100 Subject: [PATCH 256/455] Fix support for member const function pointer variables Was not generating code that compiled when the variable was not a simple member pointer, for example, a const reference member pointer: short (Funcs::* const& cc7)(bool) const = cc1; --- Examples/test-suite/member_funcptr_galore.i | 22 +++++++++++- Source/CParse/parser.y | 39 +++++++++++++++------ Source/Swig/stype.c | 6 +++- Source/Swig/typeobj.c | 2 +- 4 files changed, 55 insertions(+), 14 deletions(-) diff --git a/Examples/test-suite/member_funcptr_galore.i b/Examples/test-suite/member_funcptr_galore.i index 27d7a386a..01857ff1a 100644 --- a/Examples/test-suite/member_funcptr_galore.i +++ b/Examples/test-suite/member_funcptr_galore.i @@ -6,6 +6,12 @@ %warnfilter(SWIGWARN_TYPEMAP_SWIGTYPELEAK_MSG) pp3; %warnfilter(SWIGWARN_TYPEMAP_SWIGTYPELEAK_MSG) pp5; +%warnfilter(SWIGWARN_TYPEMAP_SWIGTYPELEAK_MSG) ccextra2; +%warnfilter(SWIGWARN_TYPEMAP_SWIGTYPELEAK_MSG) ccextra3; +%warnfilter(SWIGWARN_TYPEMAP_SWIGTYPELEAK_MSG) cc2; +%warnfilter(SWIGWARN_TYPEMAP_SWIGTYPELEAK_MSG) cc3; +%warnfilter(SWIGWARN_TYPEMAP_SWIGTYPELEAK_MSG) cc5; + %{ #if defined(__SUNPRO_CC) #pragma error_messages (off, badargtype2w) /* Formal argument ... is being passed extern "C" ... */ @@ -191,7 +197,7 @@ int MemberFuncPtrs::qqq5(short (Funcs::* & qq5)(bool)) const { return 0; } int MemberFuncPtrs::qqq6(short (Funcs::* const qq6)(bool)) const { return 0; } int MemberFuncPtrs::qqq7(short (Funcs::* const& qq7)(bool)) const { return 0; } -// member function pointer variables +// member non-const function pointer variables short (Funcs::* pp1)(bool) = &Funcs::FF; short (Funcs::* const * extra2)(bool) = &pp1; @@ -204,4 +210,18 @@ short (Funcs::* *const& pp4)(bool) = extra4; short (Funcs::* & pp5)(bool) = pp1; short (Funcs::* const pp6)(bool) = &Funcs::FF; short (Funcs::* const& pp7)(bool) = pp1; + +// member const function pointer variables +short (Funcs::* cc1)(bool) const = &Funcs::CC; + +short (Funcs::* const * ccextra2)(bool) const = &cc1; +short (Funcs::* * ccextra3)(bool) const = &cc1; +short (Funcs::* *const ccextra4)(bool) const = &cc1; + +short (Funcs::* const *& cc2)(bool) const = ccextra2; +short (Funcs::* *& cc3)(bool) const = ccextra3; +short (Funcs::* *const& cc4)(bool) const = ccextra4; +short (Funcs::* & cc5)(bool) const = cc1; +short (Funcs::* const cc6)(bool) const = &Funcs::CC; +short (Funcs::* const& cc7)(bool) const = cc1; %} diff --git a/Source/CParse/parser.y b/Source/CParse/parser.y index 80ec8611e..bc12997be 100644 --- a/Source/CParse/parser.y +++ b/Source/CParse/parser.y @@ -1432,22 +1432,39 @@ static void mark_nodes_as_extend(Node *n) { static String *add_qualifier_to_declarator(SwigType *type, SwigType *qualifier) { int is_pointer_to_member_function = 0; String *decl = Copy(type); + String *poppedtype = NewString(""); assert(qualifier); - if (SwigType_ismemberpointer(decl)) { - String *memberptr = SwigType_pop(decl); - if (SwigType_isfunction(decl)) { - assert(!SwigType_isqualifier(decl)); - SwigType_push(decl, qualifier); - SwigType_push(decl, memberptr); - is_pointer_to_member_function = 1; + + while (decl) { + if (SwigType_ismemberpointer(decl)) { + String *memberptr = SwigType_pop(decl); + if (SwigType_isfunction(decl)) { + is_pointer_to_member_function = 1; + SwigType_push(decl, qualifier); + SwigType_push(decl, memberptr); + Insert(decl, 0, poppedtype); + Delete(memberptr); + break; + } else { + Append(poppedtype, memberptr); + } + Delete(memberptr); } else { - Delete(decl); - decl = Copy(type); + String *popped = SwigType_pop(decl); + if (!popped) + break; + Append(poppedtype, popped); + Delete(popped); } - Delete(memberptr); } - if (!is_pointer_to_member_function) + + if (!is_pointer_to_member_function) { + Delete(decl); + decl = Copy(type); SwigType_push(decl, qualifier); + } + + Delete(poppedtype); return decl; } diff --git a/Source/Swig/stype.c b/Source/Swig/stype.c index 829005cd9..5cfa3e890 100644 --- a/Source/Swig/stype.c +++ b/Source/Swig/stype.c @@ -670,6 +670,7 @@ SwigType *SwigType_ltype(const SwigType *s) { int nelements, i; int firstarray = 1; int notypeconv = 0; + int memberpointer = 0; result = NewStringEmpty(); tc = Copy(s); @@ -707,13 +708,16 @@ SwigType *SwigType_ltype(const SwigType *s) { notypeconv = 1; } if (SwigType_isqualifier(element)) { - /* Do nothing. Ignore */ + if (memberpointer) + Append(result, element); + /* otherwise ignore */ } else if (SwigType_ispointer(element)) { Append(result, element); firstarray = 0; } else if (SwigType_ismemberpointer(element)) { Append(result, element); firstarray = 0; + memberpointer = 1; } else if (SwigType_isreference(element)) { if (notypeconv) { Append(result, element); diff --git a/Source/Swig/typeobj.c b/Source/Swig/typeobj.c index b2832b6a9..5240927ef 100644 --- a/Source/Swig/typeobj.c +++ b/Source/Swig/typeobj.c @@ -48,7 +48,7 @@ * 'a(n).' = Array of size n [n] * 'f(..,..).' = Function with arguments (args) * 'q(str).' = Qualifier (such as const or volatile) (const, volatile) - * 'm(qual).' = Pointer to member (qual::*) + * 'm(cls).' = Pointer to member (cls::*) * * The complete type representation for varargs is: * 'v(...)' From 1cf599bccb100f3bcda42f5f507ea32f99cd5f89 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Wed, 23 Aug 2017 09:07:12 +0100 Subject: [PATCH 257/455] Improve ref-qualifier implementation Internally, handle function ref-qualifiers in the function decl type string. Needed for a whole host of things to work like %feature and %rename. Add %feature %rename and %ignore testing for ref-qualifiers. --- Examples/test-suite/cpp11_ref_qualifiers.i | 82 ++++++++++++++++--- Examples/test-suite/errors/cpp_refqualifier.i | 4 + .../test-suite/errors/cpp_refqualifier.stderr | 12 +-- .../java/cpp11_ref_qualifiers_runme.java | 25 ++++++ .../python/cpp11_ref_qualifiers_runme.py | 31 +++++++ Source/CParse/parser.y | 20 +++-- Source/Modules/overload.cxx | 18 +++- Source/Swig/naming.c | 23 ++++-- Source/Swig/stype.c | 20 +++-- Source/Swig/swig.h | 1 + Source/Swig/typeobj.c | 81 ++++++++++++++++-- 11 files changed, 265 insertions(+), 52 deletions(-) diff --git a/Examples/test-suite/cpp11_ref_qualifiers.i b/Examples/test-suite/cpp11_ref_qualifiers.i index fa1d68d0e..2115843a3 100644 --- a/Examples/test-suite/cpp11_ref_qualifiers.i +++ b/Examples/test-suite/cpp11_ref_qualifiers.i @@ -1,16 +1,76 @@ %module cpp11_ref_qualifiers -%inline %{ -class Host { -public: - void h1() & {} - void h2() const & {} - void h3() && {} - void h4() const && {} +%include - void h() & {} - void h() const & {} - void h() && {} - void h() const && {} +%ignore Host::h() const &; + +// Basic testing +%inline %{ +using std::string; +class Host { + string s; +public: + string h1() & { return string(); } + string h2() const & { return string(); } + string h3() && { return std::move(string()); } + string h4() const && { return std::move(string()); } + string h5() const { return string(); } + string h6() volatile const & { return string(); } + string h7() const volatile & { return string(); } + string h8() volatile const && { return std::move(string()); } + string h9() const volatile && { return std::move(string()); } + + string h() & { return string(); } + string h() const & { return string(); } + string h() && { return std::move(string()); } + string h() const && { return std::move(string()); } +}; +%} + +// %feature testing +%feature("except") F1() & %{ result = "F1"; %} +%feature("except") F2 %{ result = "F2"; %} +%feature("except") F3 %{ result = "F3"; %} +%feature("except") F3() %{ _should_not_be_used_ %} + +%feature("except") C1(int i) const & %{ result = "C1"; %} +%feature("except") C2 %{ result = "C2"; %} +%feature("except") C3 %{ result = "C3"; %} +%feature("except") C3(int i) %{ _should_not_be_used_ %} + +%inline %{ +struct Features { + string F1() & { return string(); } + string F2() & { return string(); } + string F3() & { return string(); } + + string C1(int i) const & { return string(); } + string C2(int i) const & { return string(); } + string C3(int i) const & { return string(); } +}; +%} + +// %rename testing +%rename(RR1) R1; +%rename(RR2) R2() &; +%rename(RR3) R3; +%rename(RR3Bad) R3(); + +%rename(SS1) S1; +%rename(SS2) S2(int i) const &; +%rename(SS3) S3; +%rename(SS3Bad) S3(int i); +%rename(SS3BadConst) S3(int i) const; +%rename(SS3BadLValue) S3(int i) &; + +%inline %{ +struct Renames { + string R1() & { return string(); } + string R2() & { return string(); } + string R3() & { return string(); } + + string S1(int i) const & { return string(); } + string S2(int i) const & { return string(); } + string S3(int i) const & { return string(); } }; %} diff --git a/Examples/test-suite/errors/cpp_refqualifier.i b/Examples/test-suite/errors/cpp_refqualifier.i index 1cbcd936d..438aacd93 100644 --- a/Examples/test-suite/errors/cpp_refqualifier.i +++ b/Examples/test-suite/errors/cpp_refqualifier.i @@ -1,6 +1,8 @@ %module cpp_refqualifier %ignore Host::h_ignored; +%ignore Host::i_ignored() &&; +%ignore Host::j_ignored() const &&; class Host { public: @@ -15,4 +17,6 @@ public: void h() const &&; void h_ignored() &&; + void i_ignored() &&; + void j_ignored() const &&; }; diff --git a/Examples/test-suite/errors/cpp_refqualifier.stderr b/Examples/test-suite/errors/cpp_refqualifier.stderr index 866d9b530..ea2cd220a 100644 --- a/Examples/test-suite/errors/cpp_refqualifier.stderr +++ b/Examples/test-suite/errors/cpp_refqualifier.stderr @@ -1,6 +1,6 @@ -cpp_refqualifier.i:9: Warning 405: Method with rvalue ref-qualifier ignored h3() &&. -cpp_refqualifier.i:10: Warning 405: Method with rvalue ref-qualifier ignored h4() const &&. -cpp_refqualifier.i:14: Warning 405: Method with rvalue ref-qualifier ignored h() &&. -cpp_refqualifier.i:15: Warning 405: Method with rvalue ref-qualifier ignored h() const &&. -cpp_refqualifier.i:13: Warning 512: Overloaded method Host::h() const & ignored, -cpp_refqualifier.i:12: Warning 512: using non-const method Host::h() & instead. +cpp_refqualifier.i:11: Warning 405: Method with rvalue ref-qualifier h3() && ignored. +cpp_refqualifier.i:12: Warning 405: Method with rvalue ref-qualifier h4() const && ignored. +cpp_refqualifier.i:16: Warning 405: Method with rvalue ref-qualifier h() && ignored. +cpp_refqualifier.i:17: Warning 405: Method with rvalue ref-qualifier h() const && ignored. +cpp_refqualifier.i:15: Warning 512: Overloaded method Host::h() const & ignored, +cpp_refqualifier.i:14: Warning 512: using non-const method Host::h() & instead. diff --git a/Examples/test-suite/java/cpp11_ref_qualifiers_runme.java b/Examples/test-suite/java/cpp11_ref_qualifiers_runme.java index 49afe8039..bbe6be8e3 100644 --- a/Examples/test-suite/java/cpp11_ref_qualifiers_runme.java +++ b/Examples/test-suite/java/cpp11_ref_qualifiers_runme.java @@ -14,9 +14,34 @@ public class cpp11_ref_qualifiers_runme { public static void main(String argv[]) { Host h = new Host(); + + // Basic testing h.h1(); h.h2(); + h.h6(); + h.h7(); + h.h(); + + // %feature testing + Features f = new Features(); + if (!f.F1().equals("F1")) throw new RuntimeException("Fail"); + if (!f.F2().equals("F2")) throw new RuntimeException("Fail"); + if (!f.F3().equals("F3")) throw new RuntimeException("Fail"); + + if (!f.C1(0).equals("C1")) throw new RuntimeException("Fail"); + if (!f.C2(0).equals("C2")) throw new RuntimeException("Fail"); + if (!f.C3(0).equals("C3")) throw new RuntimeException("Fail"); + + // %rename testing + Renames r = new Renames(); + r.RR1(); + r.RR2(); + r.RR3(); + + r.SS1(0); + r.SS2(0); + r.SS3(0); } } diff --git a/Examples/test-suite/python/cpp11_ref_qualifiers_runme.py b/Examples/test-suite/python/cpp11_ref_qualifiers_runme.py index 24ce1d2bf..47c474218 100644 --- a/Examples/test-suite/python/cpp11_ref_qualifiers_runme.py +++ b/Examples/test-suite/python/cpp11_ref_qualifiers_runme.py @@ -1,6 +1,37 @@ import cpp11_ref_qualifiers h = cpp11_ref_qualifiers.Host() + +# Basic testing h.h1() h.h2() +h.h6() +h.h7() + h.h() + +# %feature testing +f = cpp11_ref_qualifiers.Features() +if f.F1() != "F1": + raise RuntimeException("Fail") +if f.F2() != "F2": + raise RuntimeException("Fail") +if f.F3() != "F3": + raise RuntimeException("Fail") + +if f.C1(0) != "C1": + raise RuntimeException("Fail") +if f.C2(0) != "C2": + raise RuntimeException("Fail") +if f.C3(0) != "C3": + raise RuntimeException("Fail") + +# %rename testing +r = cpp11_ref_qualifiers.Renames() +r.RR1() +r.RR2() +r.RR3() + +r.SS1(0) +r.SS2(0) +r.SS3(0) diff --git a/Source/CParse/parser.y b/Source/CParse/parser.y index bc12997be..ccb09e3eb 100644 --- a/Source/CParse/parser.y +++ b/Source/CParse/parser.y @@ -487,16 +487,16 @@ static void add_symbols(Node *n) { } { String *refqualifier = Getattr(n, "refqualifier"); - if (SwigType_isrvalue_reference(refqualifier) && strncmp(Char(symname), "$ignore", 7) != 0) { + if (SwigType_isrvalue_reference(refqualifier) && Strcmp(symname, "$ignore") != 0) { SWIG_WARN_NODE_BEGIN(n); Swig_warning(WARN_TYPE_RVALUE_REF_QUALIFIER_IGNORED, Getfile(n), Getline(n), - "Method with rvalue ref-qualifier ignored %s.\n", Swig_name_decl(n)); + "Method with rvalue ref-qualifier %s ignored.\n", Swig_name_decl(n)); SWIG_WARN_NODE_END(n); SetFlag(n, "feature:ignore"); } } } - if (only_csymbol || GetFlag(n,"feature:ignore") || strncmp(Char(symname),"$ignore",7) == 0) { + if (only_csymbol || GetFlag(n, "feature:ignore") || Strncmp(symname, "$ignore", 7) == 0) { /* Only add to C symbol table and continue */ Swig_symbol_add(0, n); if (!only_csymbol && !GetFlag(n, "feature:ignore")) { @@ -1421,10 +1421,12 @@ static void mark_nodes_as_extend(Node *n) { } /* ----------------------------------------------------------------------------- - * add_qualifier_to_declarator + * add_qualifier_to_declarator() * + * Normally the qualifier is pushed on to the front of the type. * Adding a qualifier to a pointer to member function is a special case. * For example : typedef double (Cls::*pmf)(void) const; + * The qualifier is : q(const). * The declarator is : m(Cls).f(void). * We need : m(Cls).q(const).f(void). * ----------------------------------------------------------------------------- */ @@ -5870,15 +5872,17 @@ pointer : STAR type_qualifier pointer { /* cv-qualifier plus C++11 ref-qualifier for non-static member functions */ cv_ref_qualifier : type_qualifier { $$.qualifier = $1; - $$.refqualifier = 0; + $$.refqualifier = 0; } | type_qualifier ref_qualifier { $$.qualifier = $1; - $$.refqualifier = $2; + $$.refqualifier = $2; + SwigType_push($$.qualifier, $2); } | ref_qualifier { - $$.qualifier = 0; - $$.refqualifier = $1; + $$.qualifier = NewStringEmpty(); + $$.refqualifier = $1; + SwigType_push($$.qualifier, $1); } ; diff --git a/Source/Modules/overload.cxx b/Source/Modules/overload.cxx index 330294efd..81d1bb000 100644 --- a/Source/Modules/overload.cxx +++ b/Source/Modules/overload.cxx @@ -231,9 +231,21 @@ List *Swig_overload_rank(Node *n, bool script_lang_wrapping) { } if (!differ) { /* See if declarations differ by const only */ - String *d1 = Getattr(nodes[i].n, "decl"); - String *d2 = Getattr(nodes[j].n, "decl"); - if (d1 && d2) { + String *decl1 = Getattr(nodes[i].n, "decl"); + String *decl2 = Getattr(nodes[j].n, "decl"); + if (decl1 && decl2) { + /* Remove ref-qualifiers. Note that rvalue ref-qualifiers are already ignored and + * it is illegal to overload a function with and without ref-qualifiers. So with + * all the combinations of ref-qualifiers and cv-qualifiers, we just detect + * the cv-qualifier (const) overloading. */ + String *d1 = Copy(decl1); + String *d2 = Copy(decl2); + if (SwigType_isreference(d1) || SwigType_isrvalue_reference(d1)) { + Delete(SwigType_pop(d1)); + } + if (SwigType_isreference(d2) || SwigType_isrvalue_reference(d2)) { + Delete(SwigType_pop(d2)); + } String *dq1 = Copy(d1); String *dq2 = Copy(d2); if (SwigType_isconst(d1)) { diff --git a/Source/Swig/naming.c b/Source/Swig/naming.c index 4fa32538f..d12770125 100644 --- a/Source/Swig/naming.c +++ b/Source/Swig/naming.c @@ -1689,18 +1689,23 @@ String *Swig_name_str(Node *n) { String *Swig_name_decl(Node *n) { String *qname; String *decl; - String *refqualifier = Getattr(n, "refqualifier"); qname = Swig_name_str(n); + decl = NewStringf("%s", qname); - if (checkAttribute(n, "kind", "variable")) - decl = NewStringf("%s", qname); - else - decl = NewStringf("%s(%s)%s", qname, ParmList_errorstr(Getattr(n, "parms")), SwigType_isconst(Getattr(n, "decl")) ? " const" : ""); - if (refqualifier) { - String *rq = SwigType_str(refqualifier, 0); - Printv(decl, " ", rq, NIL); - Delete(rq); + if (!checkAttribute(n, "kind", "variable")) { + String *d = Getattr(n, "decl"); + Printv(decl, "(", ParmList_errorstr(Getattr(n, "parms")), ")", NIL); + if (SwigType_isfunction(d)) { + SwigType *decl_temp = Copy(d); + SwigType *qualifiers = SwigType_pop_function_qualifiers(decl_temp); + if (qualifiers) { + String *qualifiers_string = SwigType_str(qualifiers, 0); + Printv(decl, " ", qualifiers_string, NIL); + Delete(qualifiers_string); + } + Delete(decl_temp); + } } Delete(qname); diff --git a/Source/Swig/stype.c b/Source/Swig/stype.c index 5cfa3e890..4b745b335 100644 --- a/Source/Swig/stype.c +++ b/Source/Swig/stype.c @@ -44,7 +44,7 @@ * 'z.' = Rvalue reference (&&) * 'a(n).' = Array of size n [n] * 'f(..,..).' = Function with arguments (args) - * 'q(str).' = Qualifier (such as const or volatile) (const, volatile) + * 'q(str).' = Qualifier, such as const or volatile (cv-qualifier) * 'm(cls).' = Pointer to member (cls::*) * * The encoding follows the order that you might describe a type in words. @@ -64,11 +64,19 @@ * * More examples: * - * String Encoding C++ Example - * --------------- ----------- - * p.f(bool).q(const).long const long (*)(bool) - * m(Funcs).q(const).f(bool).long long (Funcs::*)(bool) const - * r.q(const).m(Funcs).f(int).long long (Funcs::*const &)(int) + * String Encoding C++ Example + * --------------- ----------- + * p.f(bool).r.q(const).long const long & (*)(bool) + * m(Funcs).q(const).f(bool).long long (Funcs::*)(bool) const + * r.q(const).m(Funcs).f(int).long long (Funcs::*const &)(int) + * m(Funcs).z.q(const).f(bool).long long (Funcs::*)(bool) const && + * + * Function decl examples: + * + * f(bool). long a(bool); + * r.f(bool). long b(bool) &; + * z.f(bool). long c(bool) &&; + * z.q(const).f(bool). long d(bool) const &&; * * For the most part, this module tries to minimize the use of special * characters (*, [, <, etc...) in its type encoding. One reason for this diff --git a/Source/Swig/swig.h b/Source/Swig/swig.h index 0bcd53a66..7452c374c 100644 --- a/Source/Swig/swig.h +++ b/Source/Swig/swig.h @@ -136,6 +136,7 @@ extern "C" { extern SwigType *SwigType_add_function(SwigType *t, ParmList *parms); extern SwigType *SwigType_add_template(SwigType *t, ParmList *parms); extern SwigType *SwigType_pop_function(SwigType *t); + extern SwigType *SwigType_pop_function_qualifiers(SwigType *t); extern ParmList *SwigType_function_parms(const SwigType *t, Node *file_line_node); extern List *SwigType_split(const SwigType *t); extern String *SwigType_pop(SwigType *t); diff --git a/Source/Swig/typeobj.c b/Source/Swig/typeobj.c index 5240927ef..7a0626c29 100644 --- a/Source/Swig/typeobj.c +++ b/Source/Swig/typeobj.c @@ -43,11 +43,11 @@ * All type constructors are denoted by a trailing '.': * * 'p.' = Pointer (*) - * 'r.' = Reference (&) - * 'z.' = Rvalue reference (&&) + * 'r.' = Reference or ref-qualifier (&) + * 'z.' = Rvalue reference or ref-qualifier (&&) * 'a(n).' = Array of size n [n] * 'f(..,..).' = Function with arguments (args) - * 'q(str).' = Qualifier (such as const or volatile) (const, volatile) + * 'q(str).' = Qualifier, such as const or volatile (cv-qualifier) * 'm(cls).' = Pointer to member (cls::*) * * The complete type representation for varargs is: @@ -183,9 +183,10 @@ SwigType *SwigType_del_element(SwigType *t) { * SwigType_pop() * * Pop one type element off the type. - * Example: t in: q(const).p.Integer - * t out: p.Integer - * result: q(const). + * For example: + * t in: q(const).p.Integer + * t out: p.Integer + * result: q(const). * ----------------------------------------------------------------------------- */ SwigType *SwigType_pop(SwigType *t) { @@ -771,7 +772,6 @@ SwigType *SwigType_array_type(const SwigType *ty) { * Functions * * SwigType_add_function() - * SwigType_del_function() * SwigType_isfunction() * SwigType_pop_function() * @@ -795,14 +795,36 @@ SwigType *SwigType_add_function(SwigType *t, ParmList *parms) { return t; } +/* ----------------------------------------------------------------------------- + * SwigType_pop_function() + * + * Pop and return the function from the input type leaving the function's return + * type, if any. + * For example: + * t in: q(const).f().p. + * t out: p. + * result: q(const).f(). + * ----------------------------------------------------------------------------- */ + SwigType *SwigType_pop_function(SwigType *t) { SwigType *f = 0; SwigType *g = 0; char *c = Char(t); - if (strncmp(c, "q(", 2) == 0) { + if (strncmp(c, "r.", 2) == 0 || strncmp(c, "z.", 2) == 0) { + /* Remove ref-qualifier */ f = SwigType_pop(t); c = Char(t); } + if (strncmp(c, "q(", 2) == 0) { + /* Remove cv-qualifier */ + String *qual = SwigType_pop(t); + if (f) { + SwigType_push(qual, f); + Delete(f); + } + f = qual; + c = Char(t); + } if (strncmp(c, "f(", 2)) { printf("Fatal error. SwigType_pop_function applied to non-function.\n"); abort(); @@ -814,14 +836,55 @@ SwigType *SwigType_pop_function(SwigType *t) { return g; } +/* ----------------------------------------------------------------------------- + * SwigType_pop_function_qualifiers() + * + * Pop and return the function qualifiers from the input type leaving the rest of + * function declaration. Returns NULL if no qualifiers. + * For example: + * t in: r.q(const).f().p. + * t out: f().p. + * result: r.q(const) + * ----------------------------------------------------------------------------- */ + +SwigType *SwigType_pop_function_qualifiers(SwigType *t) { + SwigType *qualifiers = 0; + char *c = Char(t); + if (strncmp(c, "r.", 2) == 0 || strncmp(c, "z.", 2) == 0) { + /* Remove ref-qualifier */ + String *qual = SwigType_pop(t); + qualifiers = qual; + c = Char(t); + } + if (strncmp(c, "q(", 2) == 0) { + /* Remove cv-qualifier */ + String *qual = SwigType_pop(t); + if (qualifiers) { + SwigType_push(qual, qualifiers); + Delete(qualifiers); + } + qualifiers = qual; + c = Char(t); + } + assert(strncmp(c, "f(", 2) == 0); + + return qualifiers; +} + int SwigType_isfunction(const SwigType *t) { char *c; if (!t) { return 0; } c = Char(t); + if (strncmp(c, "r.", 2) == 0 || strncmp(c, "z.", 2) == 0) { + /* Might be a function with a ref-qualifier, skip over */ + c += 2; + if (!*c) + return 0; + } if (strncmp(c, "q(", 2) == 0) { - /* Might be a 'const' function. Try to skip over the 'const' */ + /* Might be a function with a cv-qualifier, skip over */ c = strchr(c, '.'); if (c) c++; From 8a40327aa8f75af9d5c68bfee1125be4544f2865 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Fri, 25 Aug 2017 19:08:09 +0100 Subject: [PATCH 258/455] Add unignore for rvalue ref-qualifiers Use std::move on this pointer as the default approach to supporting rvalue ref-qualifiers if a user really wants to wrap. std::move requires headers so add swigfragments.swg for all languages to use common fragments. Just header file fragments for now. --- Examples/test-suite/common.mk | 1 + .../cpp11_ref_qualifiers_rvalue_unignore.i | 15 ++++ Examples/test-suite/errors/cpp_refqualifier.i | 8 +- ..._ref_qualifiers_rvalue_unignore_runme.java | 20 +++++ ...11_ref_qualifiers_rvalue_unignore_runme.py | 4 + Lib/swig.swg | 4 +- Lib/swigfragments.swg | 86 +++++++++++++++++++ Lib/typemaps/fragments.swg | 69 --------------- Source/CParse/parser.y | 7 +- Source/Swig/cwrap.c | 9 ++ 10 files changed, 149 insertions(+), 74 deletions(-) create mode 100644 Examples/test-suite/cpp11_ref_qualifiers_rvalue_unignore.i create mode 100644 Examples/test-suite/java/cpp11_ref_qualifiers_rvalue_unignore_runme.java create mode 100644 Examples/test-suite/python/cpp11_ref_qualifiers_rvalue_unignore_runme.py create mode 100644 Lib/swigfragments.swg diff --git a/Examples/test-suite/common.mk b/Examples/test-suite/common.mk index b47b6e33b..0d0a32c8c 100644 --- a/Examples/test-suite/common.mk +++ b/Examples/test-suite/common.mk @@ -562,6 +562,7 @@ CPP11_TEST_CASES += \ cpp11_null_pointer_constant \ cpp11_raw_string_literals \ cpp11_ref_qualifiers \ + cpp11_ref_qualifiers_rvalue_unignore \ cpp11_result_of \ cpp11_rvalue_reference \ cpp11_rvalue_reference2 \ diff --git a/Examples/test-suite/cpp11_ref_qualifiers_rvalue_unignore.i b/Examples/test-suite/cpp11_ref_qualifiers_rvalue_unignore.i new file mode 100644 index 000000000..2f5fadfc6 --- /dev/null +++ b/Examples/test-suite/cpp11_ref_qualifiers_rvalue_unignore.i @@ -0,0 +1,15 @@ +%module cpp11_ref_qualifiers_rvalue_unignore + +// This is a minimal test that does not include any C++ headers to make sure the required +// header is generated from a fragment for the generated std::move call + +// m1 and m2 are ignored by default, unignore them +%feature("ignore", "0") RefQualifier::m1() &&; +%feature("ignore", "0") RefQualifier::m2() const &&; + +%inline %{ +struct RefQualifier { + void m1() && {} + void m2() const && {} +}; +%} diff --git a/Examples/test-suite/errors/cpp_refqualifier.i b/Examples/test-suite/errors/cpp_refqualifier.i index 438aacd93..afd6632fc 100644 --- a/Examples/test-suite/errors/cpp_refqualifier.i +++ b/Examples/test-suite/errors/cpp_refqualifier.i @@ -18,5 +18,11 @@ public: void h_ignored() &&; void i_ignored() &&; - void j_ignored() const &&; + void i_ignored() &&; +}; + +%feature("ignore", "0") Unignore::k_unignored() const &&; + +struct Unignore { + void k_unignored() const &&; }; diff --git a/Examples/test-suite/java/cpp11_ref_qualifiers_rvalue_unignore_runme.java b/Examples/test-suite/java/cpp11_ref_qualifiers_rvalue_unignore_runme.java new file mode 100644 index 000000000..bbbe6f788 --- /dev/null +++ b/Examples/test-suite/java/cpp11_ref_qualifiers_rvalue_unignore_runme.java @@ -0,0 +1,20 @@ + +import cpp11_ref_qualifiers_rvalue_unignore.*; + +public class cpp11_ref_qualifiers_rvalue_unignore_runme { + + static { + try { + System.loadLibrary("cpp11_ref_qualifiers_rvalue_unignore"); + } 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[]) { + new RefQualifier().m1(); + new RefQualifier().m2(); + } +} + diff --git a/Examples/test-suite/python/cpp11_ref_qualifiers_rvalue_unignore_runme.py b/Examples/test-suite/python/cpp11_ref_qualifiers_rvalue_unignore_runme.py new file mode 100644 index 000000000..6352c79c2 --- /dev/null +++ b/Examples/test-suite/python/cpp11_ref_qualifiers_rvalue_unignore_runme.py @@ -0,0 +1,4 @@ +import cpp11_ref_qualifiers_rvalue_unignore + +cpp11_ref_qualifiers_rvalue_unignore.RefQualifier().m1() +cpp11_ref_qualifiers_rvalue_unignore.RefQualifier().m2() diff --git a/Lib/swig.swg b/Lib/swig.swg index 6f48f0d20..6dc215dcf 100644 --- a/Lib/swig.swg +++ b/Lib/swig.swg @@ -309,11 +309,13 @@ static int NAME(TYPE x) { %define %$classname %$ismember,"match$parentNode$name" %enddef %define %$isnested "match$nested"="1" %enddef + /* ----------------------------------------------------------------------------- - * Include all the warnings labels and macros + * Common includes for warning labels, macros, fragments etc * ----------------------------------------------------------------------------- */ %include +%include /* ----------------------------------------------------------------------------- * Overloading support diff --git a/Lib/swigfragments.swg b/Lib/swigfragments.swg new file mode 100644 index 000000000..63bb6c8f4 --- /dev/null +++ b/Lib/swigfragments.swg @@ -0,0 +1,86 @@ +/* ----------------------------------------------------------------------------- + * swigfragments.swg + * + * Common fragments + * ----------------------------------------------------------------------------- */ + +/* ----------------------------------------------------------------------------- + * Fragments for C header files + * ----------------------------------------------------------------------------- */ + +%fragment("", "header") %{ +#include +%} + +/* Default compiler options for gcc allow long_long but not LLONG_MAX. + * Define SWIG_NO_LLONG_MAX if this added limits support is not wanted. */ +%fragment("", "header") %{ +#include +#if !defined(SWIG_NO_LLONG_MAX) +# if !defined(LLONG_MAX) && defined(__GNUC__) && defined (__LONG_LONG_MAX__) +# define LLONG_MAX __LONG_LONG_MAX__ +# define LLONG_MIN (-LLONG_MAX - 1LL) +# define ULLONG_MAX (LLONG_MAX * 2ULL + 1ULL) +# endif +#endif +%} + +%fragment("", "header") %{ +#include +%} + +%fragment("", "header") %{ +#include +%} + +%fragment("", "header") %{ +#include +#if defined(_MSC_VER) || defined(__BORLANDC__) || defined(_WATCOM) +# ifndef snprintf +# define snprintf _snprintf +# endif +#endif +%} + +%fragment("", "header") %{ +#include +#ifdef _MSC_VER +# ifndef strtoull +# define strtoull _strtoui64 +# endif +# ifndef strtoll +# define strtoll _strtoi64 +# endif +#endif +%} + +%fragment("", "header") %{ +#include +#include +#ifndef WCHAR_MIN +# define WCHAR_MIN 0 +#endif +#ifndef WCHAR_MAX +# define WCHAR_MAX 65535 +#endif +%} + +/* ----------------------------------------------------------------------------- + * Fragments for C++ header files + * ----------------------------------------------------------------------------- */ + +%fragment("", "header") %{ +#include +%} + +%fragment("", "header") %{ +#include +%} + +%fragment("", "header") %{ +#include +%} + +%fragment("", "header") %{ +#include +%} diff --git a/Lib/typemaps/fragments.swg b/Lib/typemaps/fragments.swg index 3f33ca98d..aaf948c05 100644 --- a/Lib/typemaps/fragments.swg +++ b/Lib/typemaps/fragments.swg @@ -96,75 +96,6 @@ * common fragments * ------------------------------------------------------------ */ -/* Default compiler options for gcc allow long_long but not LLONG_MAX. - * Define SWIG_NO_LLONG_MAX if this added limits support is not wanted. */ -%fragment("","header") %{ -#include -#if !defined(SWIG_NO_LLONG_MAX) -# if !defined(LLONG_MAX) && defined(__GNUC__) && defined (__LONG_LONG_MAX__) -# define LLONG_MAX __LONG_LONG_MAX__ -# define LLONG_MIN (-LLONG_MAX - 1LL) -# define ULLONG_MAX (LLONG_MAX * 2ULL + 1ULL) -# endif -#endif -%} - -%fragment("","header") %{ -#include -%} - -%fragment("","header") %{ -#include -#include -#ifndef WCHAR_MIN -# define WCHAR_MIN 0 -#endif -#ifndef WCHAR_MAX -# define WCHAR_MAX 65535 -#endif -%} - -%fragment("","header") %{ -#include -%} - -%fragment("","header") %{ -#include -#if defined(_MSC_VER) || defined(__BORLANDC__) || defined(_WATCOM) -# ifndef snprintf -# define snprintf _snprintf -# endif -#endif -%} - -%fragment("","header") %{ -#include -#ifdef _MSC_VER -# ifndef strtoull -# define strtoull _strtoui64 -# endif -# ifndef strtoll -# define strtoll _strtoi64 -# endif -#endif -%} - -%fragment("", "header") %{ -#include -%} - -%fragment("", "header") %{ -#include -%} - -%fragment("", "header") %{ -#include -%} - -%fragment("", "header") %{ -#include -%} - %fragment("SWIG_isfinite","header",fragment=",") %{ /* Getting isfinite working pre C99 across multiple platforms is non-trivial. Users can provide SWIG_isfinite on older platforms. */ #ifndef SWIG_isfinite diff --git a/Source/CParse/parser.y b/Source/CParse/parser.y index ccb09e3eb..3e0fd3282 100644 --- a/Source/CParse/parser.y +++ b/Source/CParse/parser.y @@ -485,9 +485,10 @@ static void add_symbols(Node *n) { SetFlag(n,"deleted"); SetFlag(n,"feature:ignore"); } - { - String *refqualifier = Getattr(n, "refqualifier"); - if (SwigType_isrvalue_reference(refqualifier) && Strcmp(symname, "$ignore") != 0) { + if (SwigType_isrvalue_reference(Getattr(n, "refqualifier"))) { + /* Ignore rvalue ref-qualifiers by default + * Use Getattr instead of GetFlag to handle explicit ignore and explicit not ignore */ + if (!(Getattr(n, "feature:ignore") || Strncmp(symname, "$ignore", 7) == 0)) { SWIG_WARN_NODE_BEGIN(n); Swig_warning(WARN_TYPE_RVALUE_REF_QUALIFIER_IGNORED, Getfile(n), Getline(n), "Method with rvalue ref-qualifier %s ignored.\n", Swig_name_decl(n)); diff --git a/Source/Swig/cwrap.c b/Source/Swig/cwrap.c index 4c3135e3a..d6e5e0cdc 100644 --- a/Source/Swig/cwrap.c +++ b/Source/Swig/cwrap.c @@ -1024,6 +1024,15 @@ int Swig_MethodToFunction(Node *n, const_String_or_char_ptr nspace, String *clas } } + if (!self && SwigType_isrvalue_reference(Getattr(n, "refqualifier"))) { + String *memory_header = NewString(""); + Setfile(memory_header, Getfile(n)); + Setline(memory_header, Getline(n)); + Swig_fragment_emit(memory_header); + self = NewString("std::move(*this)."); + Delete(memory_header); + } + call = Swig_cmethod_call(explicitcall_name ? explicitcall_name : name, p, self, explicit_qualifier, director_type); cres = Swig_cresult(Getattr(n, "type"), Swig_cresult_name(), call); From 330ef362f483fc999b6f4045ab85c0897c361352 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Fri, 25 Aug 2017 22:52:56 +0100 Subject: [PATCH 259/455] Add docs for C++11 ref-qualifiers --- CHANGES.current | 23 +++++++++ Doc/Manual/CPlusPlus11.html | 100 ++++++++++++++++++++++++++++++++++++ Doc/Manual/Contents.html | 1 + Doc/Manual/SWIGPlus.html | 28 ++++++++-- Doc/Manual/Typemaps.html | 4 +- 5 files changed, 150 insertions(+), 6 deletions(-) diff --git a/CHANGES.current b/CHANGES.current index 0629dfbb6..79c7df479 100644 --- a/CHANGES.current +++ b/CHANGES.current @@ -7,6 +7,29 @@ the issue number to the end of the URL: https://github.com/swig/swig/issues/ Version 4.0.0 (in progress) =========================== +2017-08-25: wsfulton + Issue #1059. Add support for C++11 ref-qualifiers on non-static member functions. + Members with lvalue ref-qualifiers such as: + + struct RQ { + void m1(int x) &; + void m2(int x) const &; + }; + + are wrapped like any other member function. Member functions with rvalue ref-qualifiers + are ignored by default, such as: + + struct RQ { + void m3(int x) &&; + void m4(int x) const &&; + }; + + example.i:7: Warning 405: Method with rvalue ref-qualifier m3(int) && ignored. + example.i:8: Warning 405: Method with rvalue ref-qualifier m4(int) const && ignored. + + These can be unignored and exposed to the target language, see further documentation in + CPlusPlus11.html. + 2017-08-16: wsfulton Fix #1063. Add using declarations to templates into typedef table. diff --git a/Doc/Manual/CPlusPlus11.html b/Doc/Manual/CPlusPlus11.html index e4dff6543..f9281bd56 100644 --- a/Doc/Manual/CPlusPlus11.html +++ b/Doc/Manual/CPlusPlus11.html @@ -42,6 +42,7 @@
  • Exception specifications and noexcept
  • Control and query object alignment
  • Attributes +
  • Methods with ref-qualifiers
  • Standard library changes
      @@ -971,6 +972,104 @@ int [[attr1]] i [[attr2, attr3]]; [[noreturn, nothrow]] void f [[noreturn]] ();
  • + +

    7.2.29 Methods with ref-qualifiers

    + + +

    +C++11 non-static member functions can be declared with ref-qualifiers. +Member functions declared with a & lvalue ref-qualifiers are wrapped like any other function without ref-qualifiers. +Member functions declared with a && rvalue ref-qualifiers are ignored by default +as they are unlikely to be required from non-C++ languages where the concept of rvalue-ness +for the implied *this pointer does not apply. +The warning is hidden by default, but can be displayed as described in the section on Enabling extra warnings. +

    + +

    +Consider: +

    + +
    +struct RQ {
    +  void m1(int x) &;
    +  void m2(int x) &&;
    +};
    +
    + +

    +The only wrapped method will be the lvalue ref-qualified method m1 +and if SWIG is run with the -Wextra command-line option, the following warning will be issued indicating m2 is not wrapped: +

    + +
    +
    +example.i:7: Warning 405: Method with rvalue ref-qualifier m2(int) && ignored.
    +
    +
    + +

    +If you unignore the method as follows, wrappers for m2 will be generated: +

    + +
    +%feature("ignore", "0") RQ::m2(int x) &&;
    +struct RQ {
    +  void m1(int x) &;
    +  void m2(int x) &&;
    +};
    +
    + +

    +Inspection of the generated C++ code, will show that std::move is used on the instance +of the RQ * class: +

    + +
    +  RQ *arg1 = (RQ *) 0 ;
    +  int arg2 ;
    +
    +  arg1 = ...marshalled from target language...
    +  arg2 = ...marshalled from target language...
    +
    +  std::move(*arg1).m2(arg2);
    +
    + +

    +This will compile but when run, the move effects may not be what you want. +As stated earlier, rvalue ref-qualifiers aren't really applicable outside the world of C++. +However, if you really know what you are doing, full control over the call to the method is +possible via the low-level "action" feature. +This feature completely replaces the call to the underlying function, that is, the last line in the snippet of code above. +

    + +
    +%feature("ignore", "0") RQ::m2(int x) &&;
    +%feature("action") RQ::m2(int x) && %{
    +  RQ().m2(arg2);
    +%}
    +struct RQ {
    +  void m1(int x) &;
    +  void m2(int x) &&;
    +};
    +
    + +

    +resulting in: +

    + +
    +  RQ *arg1 = (RQ *) 0 ;
    +  int arg2 ;
    +
    +  arg1 = ...marshalled from target language...
    +  arg2 = ...marshalled from target language...
    +
    +  RQ().m2(arg2);
    +
    + +

    +Compatibility note: SWIG-4.0.0 was the first version to support ref-qualifiers. +

    7.3 Standard library changes

    @@ -1177,5 +1276,6 @@ Phew, that is a lot of hard work to get a callback working. You could just go with the more attractive option of just using double as the return type in the function declaration instead of result_of!

    + diff --git a/Doc/Manual/Contents.html b/Doc/Manual/Contents.html index 3d9f6fd3b..b879eaa04 100644 --- a/Doc/Manual/Contents.html +++ b/Doc/Manual/Contents.html @@ -310,6 +310,7 @@
  • Exception specifications and noexcept
  • Control and query object alignment
  • Attributes +
  • Methods with ref-qualifiers
  • Standard library changes
      diff --git a/Doc/Manual/SWIGPlus.html b/Doc/Manual/SWIGPlus.html index 57da73d31..f64de15e3 100644 --- a/Doc/Manual/SWIGPlus.html +++ b/Doc/Manual/SWIGPlus.html @@ -2409,8 +2409,8 @@ the first renaming rule found on a depth-first traversal of the class hierarchy is used. -
    • The name matching rules strictly follow member qualification rules. -For example, if you have a class like this:

      +
    • The name matching rules strictly follow member qualifier rules. +For example, if you have a class and member with a member that is const qualified like this:

      @@ -2434,7 +2434,7 @@ the declaration
       

      -will not apply as there is no unqualified member bar(). The following will apply as +will not apply as there is no unqualified member bar(). The following will apply the rename as the qualifier matches correctly:

      @@ -2444,6 +2444,26 @@ the qualifier matches correctly:
  • +

    +Similarly for combinations of cv-qualifiers and ref-qualifiers, all the qualifiers must be specified to match correctly: +

    + +
    +
    +%rename(name) Jam::bar();          // will not match
    +%rename(name) Jam::bar() &;        // will not match
    +%rename(name) Jam::bar() const;    // will not match
    +%rename(name) Jam::bar() const &;  // ok, will match
    +
    +class Jam {
    +public:
    +  ...
    +  void bar() const &;
    +  ...
    +};
    +
    +
    +

    An often overlooked C++ feature is that classes can define two different overloaded members that differ only in their qualifiers, like this: @@ -2476,7 +2496,7 @@ For example we can give them separate names in the target language:

    Similarly, if you merely wanted to ignore one of the declarations, use %ignore -with the full qualification. For example, the following directive +with the full qualifier. For example, the following directive would tell SWIG to ignore the const version of bar() above:

    diff --git a/Doc/Manual/Typemaps.html b/Doc/Manual/Typemaps.html index f274c9293..eeabdd89a 100644 --- a/Doc/Manual/Typemaps.html +++ b/Doc/Manual/Typemaps.html @@ -4021,7 +4021,7 @@ struct X { Forced inclusion of fragments can be used as a replacement for code insertion block, ensuring the code block is only generated once. Consider the contents of FileA.i below which first uses a code insertion block and then a forced fragment inclusion to generate code: -

    +

     // FileA.i
    @@ -4058,7 +4058,7 @@ The resulting code in the wrappers for FileB.i is:
     

    A note of caution must be mentioned when using %fragment forced inclusion or code insertion blocks with %import. If %import is used instead: -

    +

    
    From c9d425604c58a9c862b562ffffd260f6647b08c2 Mon Sep 17 00:00:00 2001
    From: William S Fulton 
    Date: Sat, 26 Aug 2017 14:00:44 +0100
    Subject: [PATCH 260/455] Re-organise parser grammar for declarator and
     initializer rules
    
    Step 1 to make these closer to the definitions used in the standard.
    The initializer rule should not include qualifiers and exception specification.
    
    - split cpp_const into add qualifiers_exception_specification and empty rules
    - simplify initializer to use new qualifiers_exception_specification rule
    ---
     Source/CParse/parser.y | 37 +++++++++++++------------------------
     1 file changed, 13 insertions(+), 24 deletions(-)
    
    diff --git a/Source/CParse/parser.y b/Source/CParse/parser.y
    index 3e0fd3282..4c73b8a25 100644
    --- a/Source/CParse/parser.y
    +++ b/Source/CParse/parser.y
    @@ -1591,7 +1591,7 @@ static String *add_qualifier_to_declarator(SwigType *type, SwigType *qualifier)
     
     /* Misc */
     %type        identifier;
    -%type     initializer cpp_const exception_specification cv_ref_qualifier;
    +%type     initializer cpp_const exception_specification cv_ref_qualifier qualifiers_exception_specification;
     %type        storage_class extern_string;
     %type        parms  ptail rawparms varargs_parms ;
     %type        templateparameters templateparameterstail;
    @@ -3268,38 +3268,22 @@ c_decl_tail    : SEMI {
                    }
                   ;
     
    -initializer   : def_args { 
    -                   $$ = $1; 
    +initializer   : def_args {
    +                   $$ = $1;
                        $$.qualifier = 0;
                        $$.refqualifier = 0;
     		   $$.throws = 0;
     		   $$.throwf = 0;
     		   $$.nexcept = 0;
                   }
    -              | cv_ref_qualifier def_args {
    -                   $$ = $2; 
    -		   $$.qualifier = $1.qualifier;
    -		   $$.refqualifier = $1.refqualifier;
    -		   $$.throws = 0;
    -		   $$.throwf = 0;
    -		   $$.nexcept = 0;
    -	      }
    -              | exception_specification def_args { 
    -		   $$ = $2; 
    -                   $$.qualifier = 0;
    -                   $$.refqualifier = 0;
    +              | qualifiers_exception_specification def_args {
    +                   $$ = $2;
    +                   $$.qualifier = $1.qualifier;
    +                   $$.refqualifier = $1.refqualifier;
     		   $$.throws = $1.throws;
     		   $$.throwf = $1.throwf;
     		   $$.nexcept = $1.nexcept;
                   }
    -              | cv_ref_qualifier exception_specification def_args {
    -                   $$ = $3; 
    -                   $$.qualifier = $1.qualifier;
    -		   $$.refqualifier = $1.refqualifier;
    -		   $$.throws = $2.throws;
    -		   $$.throwf = $2.throwf;
    -		   $$.nexcept = $2.nexcept;
    -              }
                   ;
     
     cpp_alternate_rettype : primitive_type { $$ = $1; }
    @@ -6688,7 +6672,7 @@ exception_specification : THROW LPAREN parms RPAREN {
     	       }
     	       ;	
     
    -cpp_const      : cv_ref_qualifier {
    +qualifiers_exception_specification : cv_ref_qualifier {
                         $$.throws = 0;
                         $$.throwf = 0;
                         $$.nexcept = 0;
    @@ -6705,6 +6689,11 @@ cpp_const      : cv_ref_qualifier {
                         $$.qualifier = $1.qualifier;
                         $$.refqualifier = $1.refqualifier;
                    }
    +               ;
    +
    +cpp_const      : qualifiers_exception_specification {
    +                    $$ = $1;
    +               }
                    | empty { 
                         $$.throws = 0;
                         $$.throwf = 0;
    
    From 8227c02267b1bc54e88c714251e2052260810650 Mon Sep 17 00:00:00 2001
    From: William S Fulton 
    Date: Sat, 26 Aug 2017 23:23:54 +0100
    Subject: [PATCH 261/455] Re-organise parser grammar for initializer rules
    
    Simply split initializer into const_cpp and initializer
    ---
     Source/CParse/parser.y | 73 +++++++++++++++++-------------------------
     1 file changed, 30 insertions(+), 43 deletions(-)
    
    diff --git a/Source/CParse/parser.y b/Source/CParse/parser.y
    index 4c73b8a25..b999a3796 100644
    --- a/Source/CParse/parser.y
    +++ b/Source/CParse/parser.y
    @@ -3090,7 +3090,7 @@ c_declaration   : c_decl {
        A C global declaration of some kind (may be variable, function, typedef, etc.)
        ------------------------------------------------------------ */
     
    -c_decl  : storage_class type declarator initializer c_decl_tail {
    +c_decl  : storage_class type declarator cpp_const initializer c_decl_tail {
     	      String *decl = $3.type;
                   $$ = new_node("cdecl");
     	      if ($4.qualifier)
    @@ -3101,26 +3101,26 @@ c_decl  : storage_class type declarator initializer c_decl_tail {
     	      Setattr($$,"name",$3.id);
     	      Setattr($$,"decl",decl);
     	      Setattr($$,"parms",$3.parms);
    -	      Setattr($$,"value",$4.val);
    +	      Setattr($$,"value",$5.val);
     	      Setattr($$,"throws",$4.throws);
     	      Setattr($$,"throw",$4.throwf);
     	      Setattr($$,"noexcept",$4.nexcept);
    -	      if ($4.val && $4.type) {
    +	      if ($5.val && $5.type) {
     		/* store initializer type as it might be different to the declared type */
    -		SwigType *valuetype = NewSwigType($4.type);
    +		SwigType *valuetype = NewSwigType($5.type);
     		if (Len(valuetype) > 0)
     		  Setattr($$,"valuetype",valuetype);
     		else
     		  Delete(valuetype);
     	      }
    -	      if (!$5) {
    +	      if (!$6) {
     		if (Len(scanner_ccode)) {
     		  String *code = Copy(scanner_ccode);
     		  Setattr($$,"code",code);
     		  Delete(code);
     		}
     	      } else {
    -		Node *n = $5;
    +		Node *n = $6;
     		/* Inherit attributes */
     		while (n) {
     		  String *type = Copy($2);
    @@ -3130,8 +3130,8 @@ c_decl  : storage_class type declarator initializer c_decl_tail {
     		  Delete(type);
     		}
     	      }
    -	      if ($4.bitfield) {
    -		Setattr($$,"bitfield", $4.bitfield);
    +	      if ($5.bitfield) {
    +		Setattr($$,"bitfield", $5.bitfield);
     	      }
     
     	      if ($3.id) {
    @@ -3146,18 +3146,18 @@ c_decl  : storage_class type declarator initializer c_decl_tail {
     		      String *lstr = Swig_scopename_last($3.id);
     		      Setattr($$, "name", lstr);
     		      Delete(lstr);
    -		      set_nextSibling($$, $5);
    +		      set_nextSibling($$, $6);
     		    } else {
     		      Delete($$);
    -		      $$ = $5;
    +		      $$ = $6;
     		    }
     		    Delete(p);
     		  } else {
     		    Delete($$);
    -		    $$ = $5;
    +		    $$ = $6;
     		  }
     		} else {
    -		  set_nextSibling($$, $5);
    +		  set_nextSibling($$, $6);
     		}
     	      } else {
     		Swig_error(cparse_file, cparse_line, "Missing symbol name for global declaration\n");
    @@ -3166,7 +3166,7 @@ c_decl  : storage_class type declarator initializer c_decl_tail {
                }
                /* Alternate function syntax introduced in C++11:
                   auto funcName(int x, int y) -> int; */
    -           | storage_class AUTO declarator cpp_const ARROW cpp_alternate_rettype initializer c_decl_tail {
    +           | storage_class AUTO declarator cpp_const ARROW cpp_alternate_rettype cpp_const initializer c_decl_tail {
                   $$ = new_node("cdecl");
     	      if ($4.qualifier) SwigType_push($3.type, $4.qualifier);
     	      Setattr($$,"refqualifier",$4.refqualifier);
    @@ -3179,14 +3179,14 @@ c_decl  : storage_class type declarator initializer c_decl_tail {
     	      Setattr($$,"throws",$4.throws);
     	      Setattr($$,"throw",$4.throwf);
     	      Setattr($$,"noexcept",$4.nexcept);
    -	      if (!$8) {
    +	      if (!$9) {
     		if (Len(scanner_ccode)) {
     		  String *code = Copy(scanner_ccode);
     		  Setattr($$,"code",code);
     		  Delete(code);
     		}
     	      } else {
    -		Node *n = $8;
    +		Node *n = $9;
     		while (n) {
     		  String *type = Copy($6);
     		  Setattr(n,"type",type);
    @@ -3207,18 +3207,18 @@ c_decl  : storage_class type declarator initializer c_decl_tail {
     		    String *lstr = Swig_scopename_last($3.id);
     		    Setattr($$,"name",lstr);
     		    Delete(lstr);
    -		    set_nextSibling($$, $8);
    +		    set_nextSibling($$, $9);
     		  } else {
     		    Delete($$);
    -		    $$ = $8;
    +		    $$ = $9;
     		  }
     		  Delete(p);
     		} else {
     		  Delete($$);
    -		  $$ = $8;
    +		  $$ = $9;
     		}
     	      } else {
    -		set_nextSibling($$, $8);
    +		set_nextSibling($$, $9);
     	      }
                }
                ;
    @@ -3229,28 +3229,28 @@ c_decl_tail    : SEMI {
                        $$ = 0;
                        Clear(scanner_ccode); 
                    }
    -               | COMMA declarator initializer c_decl_tail {
    +               | COMMA declarator cpp_const initializer c_decl_tail {
     		 $$ = new_node("cdecl");
     		 if ($3.qualifier) SwigType_push($2.type,$3.qualifier);
     		 Setattr($$,"refqualifier",$3.refqualifier);
     		 Setattr($$,"name",$2.id);
     		 Setattr($$,"decl",$2.type);
     		 Setattr($$,"parms",$2.parms);
    -		 Setattr($$,"value",$3.val);
    +		 Setattr($$,"value",$4.val);
     		 Setattr($$,"throws",$3.throws);
     		 Setattr($$,"throw",$3.throwf);
     		 Setattr($$,"noexcept",$3.nexcept);
    -		 if ($3.bitfield) {
    -		   Setattr($$,"bitfield", $3.bitfield);
    +		 if ($4.bitfield) {
    +		   Setattr($$,"bitfield", $4.bitfield);
     		 }
    -		 if (!$4) {
    +		 if (!$5) {
     		   if (Len(scanner_ccode)) {
     		     String *code = Copy(scanner_ccode);
     		     Setattr($$,"code",code);
     		     Delete(code);
     		   }
     		 } else {
    -		   set_nextSibling($$,$4);
    +		   set_nextSibling($$, $5);
     		 }
     	       }
                    | LBRACE { 
    @@ -3270,19 +3270,6 @@ c_decl_tail    : SEMI {
     
     initializer   : def_args {
                        $$ = $1;
    -                   $$.qualifier = 0;
    -                   $$.refqualifier = 0;
    -		   $$.throws = 0;
    -		   $$.throwf = 0;
    -		   $$.nexcept = 0;
    -              }
    -              | qualifiers_exception_specification def_args {
    -                   $$ = $2;
    -                   $$.qualifier = $1.qualifier;
    -                   $$.refqualifier = $1.refqualifier;
    -		   $$.throws = $1.throws;
    -		   $$.throwf = $1.throwf;
    -		   $$.nexcept = $1.nexcept;
                   }
                   ;
     
    @@ -3425,7 +3412,7 @@ c_enum_decl :  storage_class c_enum_key ename c_enum_inherit LBRACE enumlist RBR
     		    Namespaceprefix = Swig_symbol_qualifiedscopename(0);
     		  }
                    }
    -	       | storage_class c_enum_key ename c_enum_inherit LBRACE enumlist RBRACE declarator initializer c_decl_tail {
    +	       | storage_class c_enum_key ename c_enum_inherit LBRACE enumlist RBRACE declarator cpp_const initializer c_decl_tail {
     		 Node *n;
     		 SwigType *ty = 0;
     		 String   *unnamed = 0;
    @@ -3472,8 +3459,8 @@ c_enum_decl :  storage_class c_enum_key ename c_enum_inherit LBRACE enumlist RBR
     		   SetFlag(n,"unnamedinstance");
     		   Delete(cty);
                      }
    -		 if ($10) {
    -		   Node *p = $10;
    +		 if ($11) {
    +		   Node *p = $11;
     		   set_nextSibling(n,p);
     		   while (p) {
     		     SwigType *cty = Copy(ty);
    @@ -3981,12 +3968,12 @@ cpp_class_decl  : storage_class cpptype idcolon inherit LBRACE {
                  ;
     
     cpp_opt_declarators :  SEMI { $$ = 0; }
    -                    |  declarator initializer c_decl_tail {
    +                    |  declarator cpp_const initializer c_decl_tail {
                             $$ = new_node("cdecl");
                             Setattr($$,"name",$1.id);
                             Setattr($$,"decl",$1.type);
                             Setattr($$,"parms",$1.parms);
    -			set_nextSibling($$,$3);
    +			set_nextSibling($$, $4);
                         }
                         ;
     /* ------------------------------------------------------------
    
    From 0e50ef30b1aef7e11e3e6e42948593001666961a Mon Sep 17 00:00:00 2001
    From: William S Fulton 
    Date: Sat, 26 Aug 2017 23:39:34 +0100
    Subject: [PATCH 262/455] Alternate function syntax parsing improvement
    
    This was incorrectly accepting qualifiers and exception specifications
    in the wrong place.
    ---
     Source/CParse/parser.y | 12 ++++++++++--
     1 file changed, 10 insertions(+), 2 deletions(-)
    
    diff --git a/Source/CParse/parser.y b/Source/CParse/parser.y
    index b999a3796..f9dc6b32f 100644
    --- a/Source/CParse/parser.y
    +++ b/Source/CParse/parser.y
    @@ -1629,7 +1629,7 @@ static String *add_qualifier_to_declarator(SwigType *type, SwigType *qualifier)
     %type      lambda_introducer lambda_body;
     %type        lambda_tail;
     %type      optional_constant_directive;
    -%type       virt_specifier_seq;
    +%type       virt_specifier_seq virt_specifier_seq_opt;
     
     %%
     
    @@ -3166,7 +3166,7 @@ c_decl  : storage_class type declarator cpp_const initializer c_decl_tail {
                }
                /* Alternate function syntax introduced in C++11:
                   auto funcName(int x, int y) -> int; */
    -           | storage_class AUTO declarator cpp_const ARROW cpp_alternate_rettype cpp_const initializer c_decl_tail {
    +           | storage_class AUTO declarator cpp_const ARROW cpp_alternate_rettype virt_specifier_seq_opt initializer c_decl_tail {
                   $$ = new_node("cdecl");
     	      if ($4.qualifier) SwigType_push($3.type, $4.qualifier);
     	      Setattr($$,"refqualifier",$4.refqualifier);
    @@ -6627,6 +6627,14 @@ virt_specifier_seq : OVERRIDE {
     	       }
                    ;
     
    +virt_specifier_seq_opt : virt_specifier_seq {
    +                   $$ = 0;
    +               }
    +               | empty {
    +                   $$ = 0;
    +               }
    +               ;
    +
     exception_specification : THROW LPAREN parms RPAREN {
                         $$.throws = $3;
                         $$.throwf = NewString("1");
    
    From 950edc1c000daf15846eeb878111354ee3c293d7 Mon Sep 17 00:00:00 2001
    From: William S Fulton 
    Date: Tue, 29 Aug 2017 21:11:26 +0100
    Subject: [PATCH 263/455] Add support for conversion operators with
     ref-qualifiers
    
    ---
     Examples/test-suite/cpp11_ref_qualifiers.i        | 15 +++++++++++++++
     .../java/cpp11_ref_qualifiers_runme.java          |  9 +++++++++
     .../python/cpp11_ref_qualifiers_runme.py          |  8 ++++++++
     Source/CParse/parser.y                            | 11 ++++++++---
     4 files changed, 40 insertions(+), 3 deletions(-)
    
    diff --git a/Examples/test-suite/cpp11_ref_qualifiers.i b/Examples/test-suite/cpp11_ref_qualifiers.i
    index 2115843a3..7e9f0e170 100644
    --- a/Examples/test-suite/cpp11_ref_qualifiers.i
    +++ b/Examples/test-suite/cpp11_ref_qualifiers.i
    @@ -74,3 +74,18 @@ struct Renames {
       string S3(int i) const & { return string(); }
     };
     %}
    +
    +// Conversion operators
    +%rename(StringConvertCopy) operator string() &;
    +%rename(StringConvertMove) operator string() &&;
    +%feature("ignore", "0") operator string() &&; // unignore as it is ignored by default
    +
    +%inline %{
    +struct ConversionOperators {
    +  virtual operator string() & { return string(); }
    +  virtual operator string() && { return std::move(string()); }
    +};
    +struct ConversionOperators2 {
    +  virtual operator string() && { return std::move(string()); }
    +};
    +%}
    diff --git a/Examples/test-suite/java/cpp11_ref_qualifiers_runme.java b/Examples/test-suite/java/cpp11_ref_qualifiers_runme.java
    index bbe6be8e3..4755f8d1f 100644
    --- a/Examples/test-suite/java/cpp11_ref_qualifiers_runme.java
    +++ b/Examples/test-suite/java/cpp11_ref_qualifiers_runme.java
    @@ -42,6 +42,15 @@ public class cpp11_ref_qualifiers_runme {
         r.SS1(0);
         r.SS2(0);
         r.SS3(0);
    +
    +    // Conversion operators
    +    String s = null;
    +    ConversionOperators co = new ConversionOperators();
    +    s = co.StringConvertCopy();
    +    s = co.StringConvertMove();
    +
    +    ConversionOperators2 co2 = new ConversionOperators2();
    +    s = co2.StringConvertMove();
       }
     }
     
    diff --git a/Examples/test-suite/python/cpp11_ref_qualifiers_runme.py b/Examples/test-suite/python/cpp11_ref_qualifiers_runme.py
    index 47c474218..d3aa98c47 100644
    --- a/Examples/test-suite/python/cpp11_ref_qualifiers_runme.py
    +++ b/Examples/test-suite/python/cpp11_ref_qualifiers_runme.py
    @@ -35,3 +35,11 @@ r.RR3()
     r.SS1(0)
     r.SS2(0)
     r.SS3(0)
    +
    +# Conversion operators
    +co = cpp11_ref_qualifiers.ConversionOperators()
    +s = co.StringConvertCopy()
    +s = co.StringConvertMove()
    +
    +co2 = cpp11_ref_qualifiers.ConversionOperators2()
    +s = co2.StringConvertMove()
    diff --git a/Source/CParse/parser.y b/Source/CParse/parser.y
    index f9dc6b32f..a982ce011 100644
    --- a/Source/CParse/parser.y
    +++ b/Source/CParse/parser.y
    @@ -4656,6 +4656,7 @@ cpp_conversion_operator : storage_class CONVERSIONOPERATOR type pointer LPAREN p
     		 if ($8.qualifier) {
     		   SwigType_push($4,$8.qualifier);
     		 }
    +		 Setattr($$,"refqualifier",$8.refqualifier);
     		 Setattr($$,"decl",$4);
     		 Setattr($$,"parms",$6);
     		 Setattr($$,"conversion_operator","1");
    @@ -4673,6 +4674,7 @@ cpp_conversion_operator : storage_class CONVERSIONOPERATOR type pointer LPAREN p
     		 if ($8.qualifier) {
     		   SwigType_push(decl,$8.qualifier);
     		 }
    +		 Setattr($$,"refqualifier",$8.refqualifier);
     		 Setattr($$,"decl",decl);
     		 Setattr($$,"parms",$6);
     		 Setattr($$,"conversion_operator","1");
    @@ -4690,6 +4692,7 @@ cpp_conversion_operator : storage_class CONVERSIONOPERATOR type pointer LPAREN p
     		 if ($8.qualifier) {
     		   SwigType_push(decl,$8.qualifier);
     		 }
    +		 Setattr($$,"refqualifier",$8.refqualifier);
     		 Setattr($$,"decl",decl);
     		 Setattr($$,"parms",$6);
     		 Setattr($$,"conversion_operator","1");
    @@ -4709,6 +4712,7 @@ cpp_conversion_operator : storage_class CONVERSIONOPERATOR type pointer LPAREN p
     		 if ($9.qualifier) {
     		   SwigType_push(decl,$9.qualifier);
     		 }
    +		 Setattr($$,"refqualifier",$9.refqualifier);
     		 Setattr($$,"decl",decl);
     		 Setattr($$,"parms",$7);
     		 Setattr($$,"conversion_operator","1");
    @@ -4725,6 +4729,7 @@ cpp_conversion_operator : storage_class CONVERSIONOPERATOR type pointer LPAREN p
     		if ($7.qualifier) {
     		  SwigType_push(t,$7.qualifier);
     		}
    +		 Setattr($$,"refqualifier",$7.refqualifier);
     		Setattr($$,"decl",t);
     		Setattr($$,"parms",$5);
     		Setattr($$,"conversion_operator","1");
    @@ -4819,7 +4824,7 @@ cpp_vend       : cpp_const SEMI {
                          Clear(scanner_ccode);
                          $$.val = 0;
                          $$.qualifier = $1.qualifier;
    -                     $$.refqualifier = 0;
    +                     $$.refqualifier = $1.refqualifier;
                          $$.bitfield = 0;
                          $$.throws = $1.throws;
                          $$.throwf = $1.throwf;
    @@ -4829,7 +4834,7 @@ cpp_vend       : cpp_const SEMI {
                          Clear(scanner_ccode);
                          $$.val = $3.val;
                          $$.qualifier = $1.qualifier;
    -                     $$.refqualifier = 0;
    +                     $$.refqualifier = $1.refqualifier;
                          $$.bitfield = 0;
                          $$.throws = $1.throws; 
                          $$.throwf = $1.throwf; 
    @@ -4839,7 +4844,7 @@ cpp_vend       : cpp_const SEMI {
                          skip_balanced('{','}');
                          $$.val = 0;
                          $$.qualifier = $1.qualifier;
    -                     $$.refqualifier = 0;
    +                     $$.refqualifier = $1.refqualifier;
                          $$.bitfield = 0;
                          $$.throws = $1.throws; 
                          $$.throwf = $1.throwf; 
    
    From 7e4717320b73dd68f00a5709f2ec346ec53b7cc2 Mon Sep 17 00:00:00 2001
    From: William S Fulton 
    Date: Wed, 30 Aug 2017 06:57:51 +0100
    Subject: [PATCH 264/455] Add error for constructors, destructors, static
     methods declared with qualifiers
    
    SWIG parses a superset of valid C++ declarations. These ill-formed declarations
    were previously successfully parsed but now result an error message.
    ---
     .../errors/cpp_invalid_qualifiers.i           | 43 +++++++++++++++++++
     .../errors/cpp_invalid_qualifiers.stderr      | 20 +++++++++
     Source/CParse/parser.y                        | 26 ++++++++++-
     3 files changed, 88 insertions(+), 1 deletion(-)
     create mode 100644 Examples/test-suite/errors/cpp_invalid_qualifiers.i
     create mode 100644 Examples/test-suite/errors/cpp_invalid_qualifiers.stderr
    
    diff --git a/Examples/test-suite/errors/cpp_invalid_qualifiers.i b/Examples/test-suite/errors/cpp_invalid_qualifiers.i
    new file mode 100644
    index 000000000..fd3b36332
    --- /dev/null
    +++ b/Examples/test-suite/errors/cpp_invalid_qualifiers.i
    @@ -0,0 +1,43 @@
    +%module cpp_invalid_qualifiers
    +
    +// Constructors, destructors and static methods cannot have qualifiers
    +struct A {
    +  ~A() const;
    +};
    +struct B {
    +  virtual ~B() const;
    +};
    +struct C {
    +  ~C() &;
    +};
    +struct D {
    +  virtual ~D() &;
    +};
    +struct E {
    +  ~E() &&;
    +};
    +struct F {
    +  virtual ~F() &&;
    +};
    +
    +struct J {
    +  J() const;
    +  J(int) const;
    +};
    +struct K {
    +  K() &;
    +  K(int) &;
    +};
    +struct L {
    +  L() &&;
    +  L(int) &&;
    +};
    +
    +struct M {
    +  static void m1() const;
    +  static void m2() &;
    +  thread_local static void m3() &&;
    +  static auto m4() const -> int;
    +  static auto m5() & -> int;
    +  static auto m6() && -> int;
    +};
    diff --git a/Examples/test-suite/errors/cpp_invalid_qualifiers.stderr b/Examples/test-suite/errors/cpp_invalid_qualifiers.stderr
    new file mode 100644
    index 000000000..7b3e442eb
    --- /dev/null
    +++ b/Examples/test-suite/errors/cpp_invalid_qualifiers.stderr
    @@ -0,0 +1,20 @@
    +cpp_invalid_qualifiers.i:5: Error: Destructor ~A() const cannot have a qualifier.
    +cpp_invalid_qualifiers.i:8: Error: Destructor ~B() const cannot have a qualifier.
    +cpp_invalid_qualifiers.i:11: Error: Destructor ~C() & cannot have a qualifier.
    +cpp_invalid_qualifiers.i:14: Error: Destructor ~D() & cannot have a qualifier.
    +cpp_invalid_qualifiers.i:17: Error: Destructor ~E() && cannot have a qualifier.
    +cpp_invalid_qualifiers.i:20: Error: Destructor ~F() && cannot have a qualifier.
    +cpp_invalid_qualifiers.i:24: Error: Constructor cannot have a qualifier.
    +cpp_invalid_qualifiers.i:25: Error: Constructor cannot have a qualifier.
    +cpp_invalid_qualifiers.i:28: Error: Constructor cannot have a qualifier.
    +cpp_invalid_qualifiers.i:29: Error: Constructor cannot have a qualifier.
    +cpp_invalid_qualifiers.i:32: Error: Constructor cannot have a qualifier.
    +cpp_invalid_qualifiers.i:33: Error: Constructor cannot have a qualifier.
    +cpp_invalid_qualifiers.i:37: Error: Static function m1() const cannot have a qualifier.
    +cpp_invalid_qualifiers.i:38: Error: Static function m2() & cannot have a qualifier.
    +cpp_invalid_qualifiers.i:39: Error: Static function m3() && cannot have a qualifier.
    +cpp_invalid_qualifiers.i:39: Warning 405: Method with rvalue ref-qualifier m3() && ignored.
    +cpp_invalid_qualifiers.i:40: Error: Static function m4() const cannot have a qualifier.
    +cpp_invalid_qualifiers.i:41: Error: Static function m5() & cannot have a qualifier.
    +cpp_invalid_qualifiers.i:42: Error: Static function m6() && cannot have a qualifier.
    +cpp_invalid_qualifiers.i:42: Warning 405: Method with rvalue ref-qualifier m6() && ignored.
    diff --git a/Source/CParse/parser.y b/Source/CParse/parser.y
    index a982ce011..f88eb5f60 100644
    --- a/Source/CParse/parser.y
    +++ b/Source/CParse/parser.y
    @@ -3163,6 +3163,9 @@ c_decl  : storage_class type declarator cpp_const initializer c_decl_tail {
     		Swig_error(cparse_file, cparse_line, "Missing symbol name for global declaration\n");
     		$$ = 0;
     	      }
    +
    +	      if ($4.qualifier && $1 && Strstr($1, "static"))
    +		Swig_error(cparse_file, cparse_line, "Static function %s cannot have a qualifier.\n", Swig_name_decl($$));
                }
                /* Alternate function syntax introduced in C++11:
                   auto funcName(int x, int y) -> int; */
    @@ -3220,6 +3223,9 @@ c_decl  : storage_class type declarator cpp_const initializer c_decl_tail {
     	      } else {
     		set_nextSibling($$, $9);
     	      }
    +
    +	      if ($4.qualifier && $1 && Strstr($1, "static"))
    +		Swig_error(cparse_file, cparse_line, "Static function %s cannot have a qualifier.\n", Swig_name_decl($$));
                }
                ;
     
    @@ -4610,6 +4616,8 @@ cpp_destructor_decl : NOT idtemplate LPAREN parms RPAREN cpp_end {
     	       Setattr($$,"noexcept",$6.nexcept);
     	       if ($6.val)
     	         Setattr($$,"value",$6.val);
    +	       if ($6.qualifier)
    +		 Swig_error(cparse_file, cparse_line, "Destructor %s %s cannot have a qualifier.\n", Swig_name_decl($$), SwigType_str($6.qualifier, 0));
     	       add_symbols($$);
     	      }
     
    @@ -4639,7 +4647,8 @@ cpp_destructor_decl : NOT idtemplate LPAREN parms RPAREN cpp_end {
     		  Setattr($$,"decl",decl);
     		  Delete(decl);
     		}
    -
    +		if ($7.qualifier)
    +		  Swig_error(cparse_file, cparse_line, "Destructor %s %s cannot have a qualifier.\n", Swig_name_decl($$), SwigType_str($7.qualifier, 0));
     		add_symbols($$);
     	      }
                   ;
    @@ -4800,6 +4809,9 @@ cpp_swig_directive: pragma_directive { $$ = $1; }
     cpp_end        : cpp_const SEMI {
     	            Clear(scanner_ccode);
     		    $$.val = 0;
    +		    $$.qualifier = $1.qualifier;
    +		    $$.refqualifier = $1.refqualifier;
    +		    $$.bitfield = 0;
     		    $$.throws = $1.throws;
     		    $$.throwf = $1.throwf;
     		    $$.nexcept = $1.nexcept;
    @@ -4807,6 +4819,9 @@ cpp_end        : cpp_const SEMI {
                    | cpp_const EQUAL default_delete SEMI {
     	            Clear(scanner_ccode);
     		    $$.val = $3.val;
    +		    $$.qualifier = $1.qualifier;
    +		    $$.refqualifier = $1.refqualifier;
    +		    $$.bitfield = 0;
     		    $$.throws = $1.throws;
     		    $$.throwf = $1.throwf;
     		    $$.nexcept = $1.nexcept;
    @@ -4814,6 +4829,9 @@ cpp_end        : cpp_const SEMI {
                    | cpp_const LBRACE { 
     		    skip_balanced('{','}'); 
     		    $$.val = 0;
    +		    $$.qualifier = $1.qualifier;
    +		    $$.refqualifier = $1.refqualifier;
    +		    $$.bitfield = 0;
     		    $$.throws = $1.throws;
     		    $$.throwf = $1.throwf;
     		    $$.nexcept = $1.nexcept;
    @@ -6710,6 +6728,8 @@ ctor_end       : cpp_const ctor_initializer SEMI {
     		    $$.throws = $1.throws;
     		    $$.throwf = $1.throwf;
     		    $$.nexcept = $1.nexcept;
    +                    if ($1.qualifier)
    +                      Swig_error(cparse_file, cparse_line, "Constructor cannot have a qualifier.\n");
                    }
                    | cpp_const ctor_initializer LBRACE { 
                         skip_balanced('{','}'); 
    @@ -6718,6 +6738,8 @@ ctor_end       : cpp_const ctor_initializer SEMI {
                         $$.throws = $1.throws;
                         $$.throwf = $1.throwf;
                         $$.nexcept = $1.nexcept;
    +                    if ($1.qualifier)
    +                      Swig_error(cparse_file, cparse_line, "Constructor cannot have a qualifier.\n");
                    }
                    | LPAREN parms RPAREN SEMI { 
                         Clear(scanner_ccode); 
    @@ -6750,6 +6772,8 @@ ctor_end       : cpp_const ctor_initializer SEMI {
                         $$.throws = $1.throws;
                         $$.throwf = $1.throwf;
                         $$.nexcept = $1.nexcept;
    +                    if ($1.qualifier)
    +                      Swig_error(cparse_file, cparse_line, "Constructor cannot have a qualifier.\n");
                    }
                    ;
     
    
    From 61c24e9cd1fab8bbcdd937e515f0749b02cfd7fb Mon Sep 17 00:00:00 2001
    From: Frank Schlimbach 
    Date: Thu, 12 Jan 2017 06:50:25 -0600
    Subject: [PATCH 265/455] - allowing R package names with containing dosts
     ('.') - allowing mulitple get accessors in R
    
    ---
     Source/Modules/r.cxx | 16 +++++++++++-----
     1 file changed, 11 insertions(+), 5 deletions(-)
    
    diff --git a/Source/Modules/r.cxx b/Source/Modules/r.cxx
    index 6a326206f..70d6ca327 100644
    --- a/Source/Modules/r.cxx
    +++ b/Source/Modules/r.cxx
    @@ -1045,10 +1045,6 @@ int R::OutputMemberReferenceMethod(String *className, int isSet,
       bool has_prev = false;
       for(j = 0; j < numMems; j+=3) {
         String *item = Getitem(el, j);
    -    if (Getattr(itemList, item)) 
    -      continue;
    -    Setattr(itemList, item, "1");
    -    
         String *dup = Getitem(el, j + 1);
         char *ptr = Char(dup);
         ptr = &ptr[Len(dup) - 3];
    @@ -1056,6 +1052,10 @@ int R::OutputMemberReferenceMethod(String *className, int isSet,
         if (!strcmp(ptr, "get"))
           varaccessor++;
     
    +    if (Getattr(itemList, item))
    +      continue;
    +    Setattr(itemList, item, "1");
    +
         String *pitem;
         if (!Strcmp(item, "operator ()")) {
           pitem = NewString("call");
    @@ -2270,7 +2270,13 @@ int R::outputRegistrationRoutines(File *out) {
       if(!noInitializationCode) {
         if (inCPlusMode)
           Printv(out, "extern \"C\" ", NIL);
    -    Printf(out, "SWIGEXPORT void R_init_%s(DllInfo *dll) {\n", Rpackage);
    +    { /* R allows pckage names to have '.' in the name, which is not allowed in C++ var names
    +         we simply replace all occurrences of '.' with '_' to construct the var name */
    +      String * Rpackage_sane = Copy(Rpackage);
    +      Replace(Rpackage_sane, ".", "_", DOH_REPLACE_ANY);
    +      Printf(out, "SWIGEXPORT void R_init_%s(DllInfo *dll) {\n", Rpackage_sane);
    +      Delete(Rpackage_sane);
    +    }
         Printf(out, "%sR_registerRoutines(dll, NULL, CallEntries, NULL, NULL);\n", tab4);
         if(Len(s_init_routine)) {
           Printf(out, "\n%s\n", s_init_routine);
    
    From d4989aa7fc89b56bd9e89380eec3f320eedddad0 Mon Sep 17 00:00:00 2001
    From: Frank Schlimbach 
    Date: Fri, 13 Jan 2017 10:51:29 -0600
    Subject: [PATCH 266/455] fixing smart-pointer and NAMESPACE support
    
    ---
     Source/Modules/r.cxx | 26 ++++++++++++++++++++++----
     1 file changed, 22 insertions(+), 4 deletions(-)
    
    diff --git a/Source/Modules/r.cxx b/Source/Modules/r.cxx
    index 70d6ca327..b7b09545a 100644
    --- a/Source/Modules/r.cxx
    +++ b/Source/Modules/r.cxx
    @@ -12,6 +12,7 @@
      * ----------------------------------------------------------------------------- */
     
     #include "swigmod.h"
    +#include "cparse.h"
     
     static const double DEFAULT_NUMBER = .0000123456712312312323;
     
    @@ -908,7 +909,7 @@ int R::DumpCode(Node *n) {
         writeListByLine(namespaceFunctions, ns);
         Printf(ns, ")\n");
         Printf(ns, "\nexportMethods(\n");
    -    writeListByLine(namespaceFunctions, ns, 1);
    +    writeListByLine(namespaceMethods, ns, 1);
         Printf(ns, ")\n");
         Delete(ns);
         Delete(s_namespace);
    @@ -1826,8 +1827,16 @@ int R::functionWrapper(Node *n) {
       Printf(sfun->def, "# Start of %s\n", iname);         
       Printv(sfun->def, "\n`", sfname, "` = function(", NIL);
     
    -  if(outputNamespaceInfo) //XXX Need to be a little more discriminating
    -    addNamespaceFunction(iname);
    +  if(outputNamespaceInfo) {//XXX Need to be a little more discriminating
    +      if (constructor) {
    +          String *niname = Copy(iname);
    +          Replace(niname, "new_", "", DOH_REPLACE_FIRST);
    +          addNamespaceFunction(niname);
    +          Delete(niname);
    +      } else {
    +          addNamespaceFunction(iname);
    +      }
    +  }
     
       Swig_typemap_attach_parms("scoercein", l, f);
       Swig_typemap_attach_parms("scoerceout", l, f);
    @@ -2328,8 +2337,17 @@ void R::registerClass(Node *n) {
     
         Printf(s_classes, "setClass('%s', contains = %s)\n", sname, base);
         Delete(base);
    +    String *smartptr = Getattr(n, "feature:smartptr");
    +    if (smartptr) {
    +        SwigType *spt = Swig_cparse_type(smartptr);
    +        String *smart = SwigType_typedef_resolve_all(spt);
    +        String *smart_rname = SwigType_manglestr(smart);
    +        Printf(s_classes, "setClass('_p%s', contains = c('%s'))\n", smart_rname, sname);
    +        Delete(spt);
    +        Delete(smart);
    +        Delete(smart_rname);
    +    }
       }
    -  
     }
     
     int R::classDeclaration(Node *n) {
    
    From e6a1a7dbd111421c9d0dbffa3817a6f2907d8ccf Mon Sep 17 00:00:00 2001
    From: Frank Schlimbach 
    Date: Tue, 24 Jan 2017 11:29:28 -0600
    Subject: [PATCH 267/455] constructors now returning smart pointers (if class
     declared as such)
    
    ---
     Source/Modules/r.cxx | 9 +++++++++
     1 file changed, 9 insertions(+)
    
    diff --git a/Source/Modules/r.cxx b/Source/Modules/r.cxx
    index b7b09545a..ccba6c794 100644
    --- a/Source/Modules/r.cxx
    +++ b/Source/Modules/r.cxx
    @@ -2137,6 +2137,15 @@ int R::functionWrapper(Node *n) {
       if ((tm = Swig_typemap_lookup("scoerceout", n, Swig_cresult_name(), sfun))) {
         Replaceall(tm,"$source","ans");
         Replaceall(tm,"$result","ans");
    +    if (constructor) {
    +        Node * parent = Getattr(n, "parentNode");
    +        String * smartname = Getattr(parent, "feature:smartptr");
    +        if (smartname) {
    +            smartname = getRClassName(smartname, 1, 1);
    +            Replaceall(tm, "$R_class", smartname);
    +            Delete(smartname);
    +        }
    +    }
         replaceRClass(tm, Getattr(n, "type"));
         Chop(tm);
       }
    
    From 1df744e0c35ade8b6622b561e6c815457ecd76d7 Mon Sep 17 00:00:00 2001
    From: Frank Schlimbach 
    Date: Wed, 25 Jan 2017 10:57:26 -0600
    Subject: [PATCH 268/455] smart-pointer classes deriving from parent
     smart-pointers white-space cleanup
    
    ---
     Source/Modules/r.cxx | 791 ++++++++++++++++++++++---------------------
     1 file changed, 397 insertions(+), 394 deletions(-)
    
    diff --git a/Source/Modules/r.cxx b/Source/Modules/r.cxx
    index ccba6c794..ac78b13d9 100644
    --- a/Source/Modules/r.cxx
    +++ b/Source/Modules/r.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
    @@ -33,15 +33,15 @@ static String * getRTypeName(SwigType *t, int *outCount = NULL) {
       List *els = SwigType_split(t);
       int count = 0;
       int i;
    -  
    -  if(Strncmp(b, "struct ", 7) == 0) 
    +
    +  if(Strncmp(b, "struct ", 7) == 0)
         Replace(b, "struct ", "", DOH_REPLACE_FIRST);
    -  
    +
       /* Printf(stdout, " %s,base = %s\n", t, b);
    -     for(i = 0; i < Len(els); i++) 
    +     for(i = 0; i < Len(els); i++)
          Printf(stdout, "%d) %s, ", i, Getitem(els,i));
          Printf(stdout, "\n"); */
    -  
    +
       for(i = 0; i < Len(els); i++) {
         String *el = Getitem(els, i);
         if(Strcmp(el, "p.") == 0 || Strncmp(el, "a(", 2) == 0) {
    @@ -51,18 +51,18 @@ static String * getRTypeName(SwigType *t, int *outCount = NULL) {
       }
       if(outCount)
         *outCount = count;
    -  
    +
       String *tmp = NewString("");
       char *retName = Char(SwigType_manglestr(t));
       Insert(tmp, 0, retName);
       return tmp;
    -  
    +
       /*
    -  if(count)
    +    if(count)
         return(b);
    -  
    -  Delete(b);
    -  return(NewString(""));
    +
    +    Delete(b);
    +    return(NewString(""));
       */
     }
     
    @@ -81,7 +81,7 @@ static String *getRClassName(String *retType, int /*addRef*/ = 1, int upRef=0) {
       } else{
         Insert(tmp, 0, retName);
       }
    -  
    +
       return tmp;
     /*
     #if 1
    @@ -90,33 +90,33 @@ static String *getRClassName(String *retType, int /*addRef*/ = 1, int upRef=0) {
       if(!l || n == 0) {
     #ifdef R_SWIG_VERBOSE
         if (debugMode)
    -      Printf(stdout, "SwigType_split return an empty list for %s\n", 
    -	     retType);
    +      Printf(stdout, "SwigType_split return an empty list for %s\n",
    +             retType);
     #endif
         return(tmp);
       }
    -  
    -  
    +
    +
       String *el = Getitem(l, n-1);
       char *ptr = Char(el);
       if(strncmp(ptr, "struct ", 7) == 0)
         ptr += 7;
    -  
    +
       Printf(tmp, "%s", ptr);
    -  
    +
       if(addRef) {
         for(int i = 0; i < n; i++) {
    -      if(Strcmp(Getitem(l, i), "p.") == 0 || 
    -	 Strncmp(Getitem(l, i), "a(", 2) == 0)
    -	Printf(tmp, "Ref");
    +      if(Strcmp(Getitem(l, i), "p.") == 0 ||
    +         Strncmp(Getitem(l, i), "a(", 2) == 0)
    +        Printf(tmp, "Ref");
         }
       }
    -  
    +
     #else
       char *retName = Char(SwigType_manglestr(retType));
       if(!retName)
         return(tmp);
    -  
    +
       if(addRef) {
         while(retName && strlen(retName) > 1 && strncmp(retName, "_p", 2) == 0)  {
           retName += 2;
    @@ -127,7 +127,7 @@ static String *getRClassName(String *retType, int /*addRef*/ = 1, int upRef=0) {
         retName ++;
       Insert(tmp, 0, retName);
     #endif
    -  
    +
       return tmp;
     */
     }
    @@ -140,7 +140,7 @@ static String *getRClassName(String *retType, int /*addRef*/ = 1, int upRef=0) {
     
     static String * getRClassNameCopyStruct(String *retType, int addRef) {
       String *tmp = NewString("");
    -  
    +
     #if 1
       List *l = SwigType_split(retType);
       int n = Len(l);
    @@ -150,36 +150,36 @@ static String * getRClassNameCopyStruct(String *retType, int addRef) {
     #endif
         return(tmp);
       }
    -  
    -  
    +
    +
       String *el = Getitem(l, n-1);
       char *ptr = Char(el);
       if(strncmp(ptr, "struct ", 7) == 0)
         ptr += 7;
    -  
    +
       Printf(tmp, "%s", ptr);
    -  
    +
       if(addRef) {
         for(int i = 0; i < n; i++) {
    -      if(Strcmp(Getitem(l, i), "p.") == 0 || 
    +      if(Strcmp(Getitem(l, i), "p.") == 0 ||
     	 Strncmp(Getitem(l, i), "a(", 2) == 0)
     	Printf(tmp, "Ref");
         }
       }
    -  
    +
     #else
       char *retName = Char(SwigType_manglestr(retType));
       if(!retName)
         return(tmp);
    -  
    +
       if(addRef) {
    -    while(retName && strlen(retName) > 1 && 
    +    while(retName && strlen(retName) > 1 &&
     	  strncmp(retName, "_p", 2) == 0)  {
           retName += 2;
           Printf(tmp, "Ref");
         }
       }
    -  
    +
       if(retName[0] == '_')
         retName ++;
       Insert(tmp, 0, retName);
    @@ -198,10 +198,10 @@ static String * getRClassNameCopyStruct(String *retType, int addRef) {
     
     static void writeListByLine(List *l, File *out, bool quote = 0) {
       int i, n = Len(l);
    -  for(i = 0; i < n; i++) 
    -    Printf(out, "%s%s%s%s%s\n", tab8, 
    -	   quote ? "\"" :"",  
    -	   Getitem(l, i), 
    +  for(i = 0; i < n; i++)
    +    Printf(out, "%s%s%s%s%s\n", tab8,
    +	   quote ? "\"" :"",
    +	   Getitem(l, i),
     	   quote ? "\"" :"", i < n-1 ? "," : "");
     }
     
    @@ -212,14 +212,14 @@ R Options (available with -r)\n\
          -cppcast         - Enable C++ casting operators (default) \n\
          -debug           - Output debug\n\
          -dll       - Name of the DLL (without the .dll or .so suffix).\n\
    -                        Default is the module name.\n\
    +	                Default is the module name.\n\
          -gc              - Aggressive garbage collection\n\
          -memoryprof      - Add memory profile\n\
          -namespace       - Output NAMESPACE file\n\
          -no-init-code    - Turn off the generation of the R_init_ code\n\
    -                        (registration information still generated)\n\
    +	                (registration information still generated)\n\
          -package   - Package name for the PACKAGE argument of the R .Call()\n\
    -                        invocations. Default is the module name.\n\
    +	                invocations. Default is the module name.\n\
     ";
     
     
    @@ -279,7 +279,7 @@ public:
       void registerClass(Node *n);
       void main(int argc, char *argv[]);
       int top(Node *n);
    -  
    +
       void dispatchFunction(Node *n);
       int functionWrapper(Node *n);
       int constantWrapper(Node *n);
    @@ -292,52 +292,52 @@ public:
     
       int typedefHandler(Node *n);
       static List *Swig_overload_rank(Node *n,
    -			   bool script_lang_wrapping);
    +	                          bool script_lang_wrapping);
     
       int memberfunctionHandler(Node *n) {
         if (debugMode)
    -      Printf(stdout, " %s %s\n", 
    +      Printf(stdout, " %s %s\n",
     	     Getattr(n, "name"),
     	     Getattr(n, "type"));
         member_name = Getattr(n, "sym:name");
         processing_class_member_function = 1;
    -    int status = Language::memberfunctionHandler(n);    
    +    int status = Language::memberfunctionHandler(n);
         processing_class_member_function = 0;
         return status;
       }
     
    -  /* Grab the name of the current class being processed so that we can 
    +  /* Grab the name of the current class being processed so that we can
          deal with members of that class. */
       int classHandler(Node *n){
    -    if(!ClassMemberTable) 
    +    if(!ClassMemberTable)
           ClassMemberTable = NewHash();
    -    
    +
         class_name = Getattr(n, "name");
         int status = Language::classHandler(n);
    -    
    +
         class_name = NULL;
         return status;
       }
     
       // Not used:
       String *runtimeCode();
    -  
    +
     protected:
       int addRegistrationRoutine(String *rname, int nargs);
       int outputRegistrationRoutines(File *out);
    -  
    +
       int outputCommandLineArguments(File *out);
    -  int generateCopyRoutines(Node *n); 
    +  int generateCopyRoutines(Node *n);
       int DumpCode(Node *n);
    -  
    +
       int OutputMemberReferenceMethod(String *className, int isSet, List *el, File *out);
       int OutputArrayMethod(String *className, List *el, File *out);
       int OutputClassMemberTable(Hash *tb, File *out);
       int OutputClassMethodsTable(File *out);
       int OutputClassAccessInfo(Hash *tb, File *out);
    -  
    +
       int defineArrayAccessors(SwigType *type);
    -  
    +
       void addNamespaceFunction(String *name) {
         if(!namespaceFunctions)
           namespaceFunctions = NewList();
    @@ -349,41 +349,41 @@ protected:
           namespaceMethods = NewList();
         Append(namespaceMethods, name);
       }
    -  
    +
       String* processType(SwigType *t, Node *n, int *nargs = NULL);
       String *createFunctionPointerHandler(SwigType *t, Node *n, int *nargs);
       int addFunctionPointerProxy(String *name, Node *n, SwigType *t, String *s_paramTypes) {
         /*XXX Do we need to put the t in there to get the return type later. */
    -    if(!functionPointerProxyTable) 
    +    if(!functionPointerProxyTable)
           functionPointerProxyTable = NewHash();
    -    
    +
         Setattr(functionPointerProxyTable, name, n);
    -    
    +
         Setattr(SClassDefs, name, name);
    -    Printv(s_classes, "setClass('", 
    +    Printv(s_classes, "setClass('",
     	   name,
    -	   "',\n", tab8, 
    +	   "',\n", tab8,
     	   "prototype = list(parameterTypes = c(", s_paramTypes, "),\n",
     	   tab8, tab8, tab8,
    -	   "returnType = '", SwigType_manglestr(t), "'),\n", tab8, 
    +	   "returnType = '", SwigType_manglestr(t), "'),\n", tab8,
     	   "contains = 'CRoutinePointer')\n\n##\n", NIL);
    -    
    +
         return SWIG_OK;
       }
    -  
     
    -  void addSMethodInfo(String *name, 
    +
    +  void addSMethodInfo(String *name,
     		      String *argType, int nargs);
    -  // Simple initialization such as constant strings that can be reused. 
    -  void init(); 
    -  
    -  
    -  void addAccessor(String *memberName, Wrapper *f, 
    +  // Simple initialization such as constant strings that can be reused.
    +  void init();
    +
    +
    +  void addAccessor(String *memberName, Wrapper *f,
     		   String *name, int isSet = -1);
    -  
    +
       static int getFunctionPointerNumArgs(Node *n, SwigType *tt);
     
    -protected: 
    +protected:
       bool copyStruct;
       bool memoryProfile;
       bool aggressiveGc;
    @@ -401,49 +401,49 @@ protected:
       String *s_init;
       String *s_init_routine;
       String *s_namespace;
    -  
    -  // State variables that carry information across calls to functionWrapper() 
    -  // from  member accessors and class declarations. 
    +
    +  // State variables that carry information across calls to functionWrapper()
    +  // from  member accessors and class declarations.
       String *opaqueClassDeclaration;
       int processing_variable;
       int processing_member_access_function;
       String *member_name;
       String *class_name;
    -  
    -  
    +
    +
       int processing_class_member_function;
       List *class_member_functions;
       List *class_member_set_functions;
    -  
    +
       /* */
       Hash *ClassMemberTable;
       Hash *ClassMethodsTable;
       Hash *SClassDefs;
       Hash *SMethodInfo;
    -  
    -  // Information about routines that are generated and to be registered with 
    -  // R for dynamic lookup. 
    +
    +  // Information about routines that are generated and to be registered with
    +  // R for dynamic lookup.
       Hash *registrationTable;
       Hash *functionPointerProxyTable;
    -  
    +
       List *namespaceFunctions;
       List *namespaceMethods;
       List *namespaceClasses; // Probably can do this from ClassMemberTable.
    -  
    -  
    -  // Store a copy of the command line. 
    -  // Need only keep a string that has it formatted. 
    +
    +
    +  // Store a copy of the command line.
    +  // Need only keep a string that has it formatted.
       char **Argv;
       int    Argc;
       bool inCPlusMode;
    -  
    +
       // State variables that we remember from the command line settings
       // potentially that govern the code we generate.
       String *DllName;
       String *Rpackage;
       bool    noInitializationCode;
       bool    outputNamespaceInfo;
    -  
    +
       String *UnProtectWrapupCode;
     
       // Static members
    @@ -509,7 +509,7 @@ int R::getFunctionPointerNumArgs(Node *n, SwigType *tt) {
     
     void R::addSMethodInfo(String *name, String *argType, int nargs) {
       (void) argType;
    -  
    +
       if(!SMethodInfo)
         SMethodInfo = NewHash();
       if (debugMode)
    @@ -532,20 +532,20 @@ void R::addSMethodInfo(String *name, String *argType, int nargs) {
         Setattr(tb, "max", str);
       }
     }
    - 
    +
     /*
    -Returns the name of the new routine.
    +  Returns the name of the new routine.
     */
     String * R::createFunctionPointerHandler(SwigType *t, Node *n, int *numArgs) {
       String *funName = SwigType_manglestr(t);
    -  
    +
       /* See if we have already processed this one. */
       if(functionPointerProxyTable && Getattr(functionPointerProxyTable, funName))
         return funName;
    -  
    +
       if (debugMode)
         Printf(stdout, " Defining %s\n",  t);
    -  
    +
       SwigType *rettype = Copy(Getattr(n, "type"));
       SwigType *funcparams = SwigType_functionpointer_decompose(rettype);
       String *rtype = SwigType_str(rettype, 0);
    @@ -559,13 +559,13 @@ String * R::createFunctionPointerHandler(SwigType *t, Node *n, int *numArgs) {
         Printf(stdout, "Type: %s\n", t);
         Printf(stdout, "Return type: %s\n", SwigType_base(t));
       }
    -  
    +
       bool isVoidType = Strcmp(rettype, "void") == 0;
       if (debugMode)
         Printf(stdout, "%s is void ? %s  (%s)\n", funName, isVoidType ? "yes" : "no", rettype);
    -  
    +
       Wrapper *f = NewWrapper();
    -  
    +
       /* Go through argument list, attach lnames for arguments */
       int i = 0;
       Parm *p = parms;
    @@ -581,7 +581,7 @@ String * R::createFunctionPointerHandler(SwigType *t, Node *n, int *numArgs) {
     
         Setattr(p, "lname", lname);
       }
    -  
    +
       Swig_typemap_attach_parms("out", parms, f);
       Swig_typemap_attach_parms("scoerceout", parms, f);
       Swig_typemap_attach_parms("scheck", parms, f);
    @@ -590,7 +590,7 @@ String * R::createFunctionPointerHandler(SwigType *t, Node *n, int *numArgs) {
     
       emit_parameter_variables(parms, f);
       emit_return_variable(n, rettype, f);
    -//  emit_attach_parmmaps(parms,f);
    +  //  emit_attach_parmmaps(parms,f);
     
       /*  Using weird name and struct to avoid potential conflicts. */
       Wrapper_add_local(f, "r_swig_cb_data", "RCallbackFunctionData *r_swig_cb_data = R_SWIG_getCallbackFunctionData()");
    @@ -610,9 +610,9 @@ String * R::createFunctionPointerHandler(SwigType *t, Node *n, int *numArgs) {
         *numArgs = nargs;
         if (debugMode)
           Printf(stdout, "Setting number of parameters to %d\n", *numArgs);
    -  } 
    +  }
       String *setExprElements = NewString("");
    -  
    +
       String *s_paramTypes = NewString("");
       for(i = 0; p; i++) {
         SwigType *tt = Getattr(p, "type");
    @@ -641,35 +641,35 @@ String * R::createFunctionPointerHandler(SwigType *t, Node *n, int *numArgs) {
         Printf(setExprElements, "%s\n", tm);
         Printf(setExprElements, "SETCAR(r_swig_cb_data->el, %s);\n", "r_tmp");
         Printf(setExprElements, "r_swig_cb_data->el = CDR(r_swig_cb_data->el);\n\n");
    -    
    +
         Printf(s_paramTypes, "'%s'", SwigType_manglestr(tt));
    -    
    -    
    +
    +
         p = nextSibling(p);
         if(p) {
           Printf(f->def, ", ");
           Printf(s_paramTypes, ", ");
         }
       }
    -  
    +
       Printf(f->def,  ") {\n");
    -  
    +
       Printf(f->code, "Rf_protect(%s->expr = Rf_allocVector(LANGSXP, %d));\n", lvar, nargs + 1);
       Printf(f->code, "r_nprotect++;\n");
       Printf(f->code, "r_swig_cb_data->el = r_swig_cb_data->expr;\n\n");
    -  
    +
       Printf(f->code, "SETCAR(r_swig_cb_data->el, r_swig_cb_data->fun);\n");
       Printf(f->code, "r_swig_cb_data->el = CDR(r_swig_cb_data->el);\n\n");
    -  
    +
       Printf(f->code, "%s\n\n", setExprElements);
    -  
    -  Printv(f->code, "r_swig_cb_data->retValue = R_tryEval(", 
    +
    +  Printv(f->code, "r_swig_cb_data->retValue = R_tryEval(",
     	 "r_swig_cb_data->expr,",
     	 " R_GlobalEnv,",
     	 " &r_swig_cb_data->errorOccurred",
    -	 ");\n", 
    +	 ");\n",
     	 NIL);
    -  
    +
       Printv(f->code, "\n",
     	 "if(r_swig_cb_data->errorOccurred) {\n",
     	 "R_SWIG_popCallbackFunctionData(1);\n",
    @@ -678,11 +678,11 @@ String * R::createFunctionPointerHandler(SwigType *t, Node *n, int *numArgs) {
     	 ")\");\n",
     	 "}\n",
     	 NIL);
    -   
    -   
    -   
    +
    +
    +
       if(!isVoidType) {
    -    /* Need to deal with the return type of the function pointer, not the function pointer itself. 
    +    /* Need to deal with the return type of the function pointer, not the function pointer itself.
            So build a new node that has the relevant pieces.
            XXX  Have to be a little more clever so that we can deal with struct A * - the * is getting lost.
            Is this still true? If so, will a SwigType_push() solve things?
    @@ -700,7 +700,7 @@ String * R::createFunctionPointerHandler(SwigType *t, Node *n, int *numArgs) {
         }
         Delete(bbase);
       }
    -  
    +
       Printv(f->code, "R_SWIG_popCallbackFunctionData(1);\n", NIL);
       Printv(f->code, "\n", UnProtectWrapupCode, NIL);
     
    @@ -711,40 +711,40 @@ String * R::createFunctionPointerHandler(SwigType *t, Node *n, int *numArgs) {
       } else if (!isVoidType) {
         Printv(f->code,  "return ", Swig_cresult_name(), ";\n", NIL);
       }
    -  
    +
       Printv(f->code, "\n}\n", NIL);
       Replaceall(f->code, "SWIG_exception_fail", "SWIG_exception_noreturn");
    -  
    +
       /* To coerce correctly in S, we really want to have an extra/intermediate
    -     function that handles the scoerceout. 
    +     function that handles the scoerceout.
          We need to check if any of the argument types have an entry in
          that map. If none do, the ignore and call the function straight.
          Otherwise, generate a marshalling function.
          Need to be able to find it in S. Or use an entirely generic one
          that evaluates the expressions.
          Handle errors in the evaluation of the function by restoring
    -     the stack, if there is one in use for this function (i.e. no 
    +     the stack, if there is one in use for this function (i.e. no
          userData).
       */
    -  
    +
       Wrapper_print(f, f_wrapper);
    -  
    +
       addFunctionPointerProxy(funName, n, t, s_paramTypes);
       Delete(s_paramTypes);
       Delete(rtype);
       Delete(rettype);
       Delete(funcparams);
       DelWrapper(f);
    -  
    +
       return funName;
     }
     
     void R::init() {
    -  UnProtectWrapupCode =  
    +  UnProtectWrapupCode =
         NewStringf("%s", "vmaxset(r_vmax);\nif(r_nprotect)  Rf_unprotect(r_nprotect);\n\n");
    -  
    +
       SClassDefs = NewHash();
    -  
    +
       sfile = NewString("");
       f_init = NewString("");
       s_header = NewString("");
    @@ -771,13 +771,13 @@ int R::cDeclaration(Node *n) {
     
     /**
        Method from Language that is called to start the entire
    -   processing off, i.e. the generation of the code. 
    +   processing off, i.e. the generation of the code.
        It is called after the input has been read and parsed.
        Here we open the output streams and generate the code.
     ***/
     int R::top(Node *n) {
       String *module = Getattr(n, "name");
    -  if(!Rpackage) 
    +  if(!Rpackage)
         Rpackage = Copy(module);
       if(!DllName)
         DllName = Copy(module);
    @@ -805,7 +805,7 @@ int R::top(Node *n) {
     
       Printf(f_runtime, "\n\n#ifndef SWIGR\n#define SWIGR\n#endif\n\n");
     
    -  
    +
       Swig_banner_target_lang(s_init, "#");
       outputCommandLineArguments(s_init);
     
    @@ -856,27 +856,27 @@ int R::top(Node *n) {
     ****************************************************/
     int R::DumpCode(Node *n) {
       String *output_filename = NewString("");
    -  
    -  
    +
    +
       /* The name of the file in which we will generate the S code. */
       Printf(output_filename, "%s%s.R", SWIG_output_directory(), Rpackage);
    -  
    +
     #ifdef R_SWIG_VERBOSE
       Printf(stdout, "Writing S code to %s\n", output_filename);
     #endif
    -  
    +
       File *scode = NewFile(output_filename, "w", SWIG_output_files());
       if (!scode) {
         FileErrorDisplay(output_filename);
         SWIG_exit(EXIT_FAILURE);
       }
       Delete(output_filename);
    -  
    -  
    +
    +
       Printf(scode, "%s\n\n", s_init);
       Printf(scode, "%s\n\n", s_classes);
       Printf(scode, "%s\n", sfile);
    -  
    +
       Delete(scode);
       String *outfile = Getattr(n,"outfile");
       File *runtime = NewFile(outfile,"w", SWIG_output_files());
    @@ -884,7 +884,7 @@ int R::DumpCode(Node *n) {
         FileErrorDisplay(outfile);
         SWIG_exit(EXIT_FAILURE);
       }
    -  
    +
       Printf(runtime, "%s", f_begin);
       Printf(runtime, "%s\n", f_runtime);
       Printf(runtime, "%s\n", s_header);
    @@ -902,7 +902,7 @@ int R::DumpCode(Node *n) {
           SWIG_exit(EXIT_FAILURE);
         }
         Delete(output_filename);
    -   
    +
         Printf(ns, "%s\n", s_namespace);
     
         Printf(ns, "\nexport(\n");
    @@ -921,7 +921,7 @@ int R::DumpCode(Node *n) {
     
     
     /*
    -  We may need to do more.... so this is left as a 
    +  We may need to do more.... so this is left as a
       stub for the moment.
     */
     int R::OutputClassAccessInfo(Hash *tb, File *out) {
    @@ -933,15 +933,15 @@ int R::OutputClassAccessInfo(Hash *tb, File *out) {
     /************************************************************************
       Currently this just writes the information collected about the
       different methods of the C++ classes that have been processed
    -  to the console. 
    +  to the console.
       This will be used later to define S4 generics and methods.
     **************************************************************************/
     int R::OutputClassMethodsTable(File *) {
       Hash *tb = ClassMethodsTable;
    -  
    +
       if(!tb)
         return SWIG_OK;
    -  
    +
       List *keys = Keys(tb);
       String *key;
       int i, n = Len(keys);
    @@ -965,35 +965,36 @@ int R::OutputClassMethodsTable(File *) {
     
     
     /*
    -  Iterate over the _set and <>_get 
    +  Iterate over the _set and <>_get
       elements and generate the $ and $<- functions
       that provide constrained access to the member
       fields in these elements.
     
       tb - a hash table that is built up in functionWrapper
       as we process each membervalueHandler.
    -  The entries are indexed by _set and 
    +  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
       code stream as we generate only S code here..
     */
     int R::OutputClassMemberTable(Hash *tb, File *out) {
       List *keys = Keys(tb), *el;
    -  
    +
       String *key;
       int i, n = Len(keys);
       /* Loop over all the  _set and _get entries in the table. */
       /* This function checks for names ending in _set - perhaps it should */
       /* use attributes of some other form, as it potentially clashes with */
       /* methods ending in _set */
    +
       if(n && outputNamespaceInfo) {
         Printf(s_namespace, "exportClasses(");
       }
       for(i = 0; i < n; i++) {
         key = Getitem(keys, i);
         el = Getattr(tb, key);
    -    
    +
         String *className = Getitem(el, 0);
         char *ptr = Char(key);
         int klen = Len(key);
    @@ -1003,42 +1004,42 @@ int R::OutputClassMemberTable(Hash *tb, File *out) {
           isSet = strcmp(ptr, "_set") == 0;
         }
     
    -    //        OutputArrayMethod(className, el, out);        
    +    //        OutputArrayMethod(className, el, out);  
         OutputMemberReferenceMethod(className, isSet, el, out);
    -    
    -    if(outputNamespaceInfo) 
    +
    +    if(outputNamespaceInfo)
           Printf(s_namespace, "\"%s\"%s", className, i < n-1 ? "," : "");
       }
    -  if(n && outputNamespaceInfo) { 
    +  if(n && outputNamespaceInfo) {
         Printf(s_namespace, ")\n");
       }
    -  
    +
       return n;
     }
     
     /*******************************************************************
    - Write the methods for $ or $<- for accessing a member field in an 
    + Write the methods for $ or $<- for accessing a member field in an
      struct or union (or class).
      className - the name of the struct or union (e.g. Bar for struct Bar)
    - isSet - a logical value indicating whether the method is for 
    -           modifying ($<-) or accessing ($) the member field.
    + isSet - a logical value indicating whether the method is for
    +	   modifying ($<-) or accessing ($) the member field.
      el - a list of length  2 * # accessible member elements  + 1.
    -      The first element is the name of the class. 
    +      The first element is the name of the class.
           The other pairs are  member name and the name of the R function to access it.
      out - the stream where we write the code.
     ********************************************************************/
    -int R::OutputMemberReferenceMethod(String *className, int isSet, 
    +int R::OutputMemberReferenceMethod(String *className, int isSet,
     				   List *el, File *out) {
       int numMems = Len(el), j;
       int varaccessor = 0;
    -  if (numMems == 0) 
    +  if (numMems == 0)
         return SWIG_OK;
    -  
    +
       Wrapper *f = NewWrapper(), *attr = NewWrapper();
    -  
    +
       Printf(f->def, "function(x, name%s)", isSet ? ", value" : "");
       Printf(attr->def, "function(x, i, j, ...%s)", isSet ? ", value" : "");
    -  
    +
       Printf(f->code, "{\n");
       Printf(f->code, "%saccessorFuns = list(", tab8);
     
    @@ -1049,7 +1050,7 @@ int R::OutputMemberReferenceMethod(String *className, int isSet,
         String *dup = Getitem(el, j + 1);
         char *ptr = Char(dup);
         ptr = &ptr[Len(dup) - 3];
    -    
    +
         if (!strcmp(ptr, "get"))
           varaccessor++;
     
    @@ -1069,7 +1070,7 @@ int R::OutputMemberReferenceMethod(String *className, int isSet,
         } else {
           pitem = Copy(item);
         }
    -    if (has_prev) 
    +    if (has_prev)
           Printf(f->code, ", ");
         Printf(f->code, "'%s' = %s", pitem, dup);
         has_prev = true;
    @@ -1077,7 +1078,7 @@ int R::OutputMemberReferenceMethod(String *className, int isSet,
       }
       Delete(itemList);
       Printf(f->code, ");\n");
    -  
    +
       if (!isSet && varaccessor > 0) {
         Printf(f->code, "%svaccessors = c(", tab8);
         int first = 1;
    @@ -1086,7 +1087,7 @@ int R::OutputMemberReferenceMethod(String *className, int isSet,
           String *dup = Getitem(el, j + 1);
           char *ptr = Char(dup);
           ptr = &ptr[Len(dup) - 3];
    -      
    +
           if (!strcmp(ptr, "get")) {
     	Printf(f->code, "%s'%s'", first ? "" : ", ", item);
     	first = 0;
    @@ -1094,15 +1095,15 @@ int R::OutputMemberReferenceMethod(String *className, int isSet,
         }
         Printf(f->code, ");\n");
       }
    -  
    -  
    +
    +
       /*    Printv(f->code, tab8,
     	"idx = pmatch(name, names(accessorFuns))\n",
     	tab8,
     	"if(is.na(idx)) {\n",
    -	tab8, tab4, 
    +	tab8, tab4,
     	"stop(\"No ", (isSet ? "modifiable" : "accessible"), " field named \", name, \" in ", className,
    -	": fields are \", paste(names(accessorFuns), sep = \", \")", 
    +	": fields are \", paste(names(accessorFuns), sep = \", \")",
     	")", "\n}\n", NIL); */
       Printv(f->code, ";", tab8,
     	 "idx = pmatch(name, names(accessorFuns));\n",
    @@ -1124,67 +1125,67 @@ int R::OutputMemberReferenceMethod(String *className, int isSet,
         }
       }
       Printf(f->code, "}\n");
    -  
    -  
    +
    +
       Printf(out, "# Start of accessor method for %s\n", className);
       Printf(out, "setMethod('$%s', '_p%s', ",
    -	 isSet ? "<-" : "", 
    -	 getRClassName(className)); 
    +	 isSet ? "<-" : "",
    +	 getRClassName(className));
       Wrapper_print(f, out);
       Printf(out, ");\n");
    -  
    +
       if(isSet) {
    -    Printf(out, "setMethod('[[<-', c('_p%s', 'character'),", 
    -	   getRClassName(className)); 
    +    Printf(out, "setMethod('[[<-', c('_p%s', 'character'),",
    +	   getRClassName(className));
         Insert(f->code, 2, "name = i;\n");
         Printf(attr->code, "%s", f->code);
         Wrapper_print(attr, out);
         Printf(out, ");\n");
       }
    -  
    +
       DelWrapper(attr);
       DelWrapper(f);
    -  
    +
       Printf(out, "# end of accessor method for %s\n", className);
    -  
    +
       return SWIG_OK;
     }
     
     /*******************************************************************
    - Write the methods for [ or [<- for accessing a member field in an 
    + Write the methods for [ or [<- for accessing a member field in an
      struct or union (or class).
      className - the name of the struct or union (e.g. Bar for struct Bar)
      el - a list of length  2 * # accessible member elements  + 1.
    -      The first element is the name of the class. 
    +      The first element is the name of the class.
           The other pairs are  member name and the name of the R function to access it.
      out - the stream where we write the code.
     ********************************************************************/
     int R::OutputArrayMethod(String *className, List *el, File *out) {
       int numMems = Len(el), j;
    -  
    +
       if(!el || numMems == 0)
         return(0);
    -  
    +
       Printf(out, "# start of array methods for %s\n", className);
       for(j = 0; j < numMems; j+=3) {
         String *item = Getitem(el, j);
         String *dup = Getitem(el, j + 1);
         if (!Strcmp(item, "__getitem__")) {
    -      Printf(out, 
    -	     "setMethod('[', '_p%s', function(x, i, j, ..., drop =TRUE) ", 
    +      Printf(out,
    +	     "setMethod('[', '_p%s', function(x, i, j, ..., drop =TRUE) ",
     	     getRClassName(className));
           Printf(out, "  sapply(i, function (n)  %s(x, as.integer(n-1))))\n\n", dup);
         }
         if (!Strcmp(item, "__setitem__")) {
    -      Printf(out, "setMethod('[<-', '_p%s', function(x, i, j, ..., value)", 
    +      Printf(out, "setMethod('[<-', '_p%s', function(x, i, j, ..., value)",
     	     getRClassName(className));
           Printf(out, "  sapply(1:length(i), function(n) %s(x, as.integer(i[n]-1), value[n])))\n\n", dup);
         }
    -    
    +
       }
    -  
    +
       Printf(out, "# end of array methods for %s\n", className);
    -  
    +
       return SWIG_OK;
     }
     
    @@ -1200,9 +1201,9 @@ int R::enumDeclaration(Node *n) {
     
       String *name = Getattr(n, "name");
       String *tdname = Getattr(n, "tdname");
    -  
    +
       /* Using name if tdname is empty. */
    -  
    +
       if(Len(tdname) == 0)
         tdname = name;
     
    @@ -1211,40 +1212,40 @@ int R::enumDeclaration(Node *n) {
         Language::enumDeclaration(n);
         return SWIG_OK;
       }
    -  
    +
       String *mangled_tdname = SwigType_manglestr(tdname);
       String *scode = NewString("");
    -  
    -  Printv(scode, "defineEnumeration('", mangled_tdname, "'", 
    +
    +  Printv(scode, "defineEnumeration('", mangled_tdname, "'",
     	 ",\n",  tab8, tab8, tab4, ".values = c(\n", NIL);
    -  
    +
       Node *c;
       int value = -1; // First number is zero
       for (c = firstChild(n); c; c = nextSibling(c)) {
         //      const char *tag = Char(nodeType(c));
    -    //      if (Strcmp(tag,"cdecl") == 0) {        
    +    //      if (Strcmp(tag,"cdecl") == 0) {
         name = Getattr(c, "name");
         String *val = Getattr(c, "enumvalue");
         if(val && Char(val)) {
           int inval = (int) getNumber(val);
    -      if(inval == DEFAULT_NUMBER) 
    +      if(inval == DEFAULT_NUMBER)
     	value++;
    -      else 
    +      else
     	value = inval;
         } else
           value++;
    -    
    +
         Printf(scode, "%s%s%s'%s' = %d%s\n", tab8, tab8, tab8, name, value,
     	   nextSibling(c) ? ", " : "");
         //      }
       }
    -  
    +
       Printv(scode, "))", NIL);
       Printf(sfile, "%s\n", scode);
    -  
    +
       Delete(scode);
       Delete(mangled_tdname);
    -  
    +
       return SWIG_OK;
     }
     
    @@ -1253,27 +1254,27 @@ int R::enumDeclaration(Node *n) {
     **************************************************************/
     int R::variableWrapper(Node *n) {
       String *name = Getattr(n, "sym:name");
    -  
    +
       processing_variable = 1;
       Language::variableWrapper(n); // Force the emission of the _set and _get function wrappers.
       processing_variable = 0;
    -  
    -  
    +
    +
       SwigType *ty = Getattr(n, "type");
       int addCopyParam = addCopyParameter(ty);
    -  
    +
       //XXX
       processType(ty, n);
    -  
    +
       if(!SwigType_isconst(ty)) {
         Wrapper *f = NewWrapper();
    -    Printf(f->def, "%s = \nfunction(value%s)\n{\n", 
    +    Printf(f->def, "%s = \nfunction(value%s)\n{\n",
     	   name, addCopyParam ? ", .copy = FALSE" : "");
    -    Printv(f->code, "if(missing(value)) {\n", 
    +    Printv(f->code, "if(missing(value)) {\n",
     	   name, "_get(", addCopyParam ? ".copy" : "", ")\n}", NIL);
    -    Printv(f->code, " else {\n", 
    +    Printv(f->code, " else {\n",
     	   name, "_set(value)\n}\n}", NIL);
    -    
    +
         Wrapper_print(f, sfile);
         DelWrapper(f);
       } else {
    @@ -1284,7 +1285,7 @@ int R::variableWrapper(Node *n) {
     }
     
     
    -void R::addAccessor(String *memberName, Wrapper *wrapper, String *name, 
    +void R::addAccessor(String *memberName, Wrapper *wrapper, String *name,
     		    int isSet) {
       if(isSet < 0) {
         int n = Len(name);
    @@ -1293,9 +1294,9 @@ void R::addAccessor(String *memberName, Wrapper *wrapper, String *name,
           isSet = Strcmp(NewString(&ptr[n-4]), "_set") == 0;
         }
       }
    -  
    +
       List *l = isSet ? class_member_set_functions : class_member_functions;
    -  
    +
       if(!l) {
         l = NewList();
         if(isSet)
    @@ -1303,10 +1304,10 @@ void R::addAccessor(String *memberName, Wrapper *wrapper, String *name,
         else
           class_member_functions = l;
       }
    -  
    +
       Append(l, memberName);
       Append(l, name);
    -  
    +
       String *tmp = NewString("");
       Wrapper_print(wrapper, tmp);
       Append(l, tmp);
    @@ -1325,8 +1326,8 @@ struct Overloaded {
     };
     
     
    -List * R::Swig_overload_rank(Node *n, 
    -				 bool script_lang_wrapping) {
    +List * R::Swig_overload_rank(Node *n,
    +	                     bool script_lang_wrapping) {
       Overloaded  nodes[MAX_OVERLOAD];
       int         nnodes = 0;
       Node *o = Getattr(n,"sym:overloaded");
    @@ -1357,7 +1358,7 @@ List * R::Swig_overload_rank(Node *n,
         }
         c = Getattr(c,"sym:nextSibling");
       }
    -  
    +
       /* Sort the declarations by required argument count */
       {
         int i,j;
    @@ -1444,7 +1445,7 @@ List * R::Swig_overload_rank(Node *n,
     	      }
     
     	      /* Need subtype check here.  If t2 is a subtype of t1, then we need to change the
    -                 order */
    +	         order */
     
     	      if (SwigType_issubtype(t2,t1)) {
     		Overloaded t = nodes[i];
    @@ -1560,7 +1561,7 @@ List * R::Swig_overload_rank(Node *n,
         int i;
         for (i = 0; i < nnodes; i++) {
           if (nodes[i].error)
    -        Setattr(nodes[i].n, "overload:ignore", "1");
    +	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);
    @@ -1573,7 +1574,7 @@ void R::dispatchFunction(Node *n) {
       Wrapper *f = NewWrapper();
       String *symname = Getattr(n, "sym:name");
       String *nodeType = Getattr(n, "nodeType");
    -  bool constructor = (!Cmp(nodeType, "constructor")); 
    +  bool constructor = (!Cmp(nodeType, "constructor"));
     
       String *sfname = NewString(symname);
     
    @@ -1587,7 +1588,7 @@ void R::dispatchFunction(Node *n) {
       }
       List *dispatch = Swig_overload_rank(n, true);
       int   nfunc = Len(dispatch);
    -  Printv(f->code, 
    +  Printv(f->code,
     	 "argtypes <- mapply(class, list(...));\n",
     	 "argv <- list(...);\n",
     	 "argc <- length(argtypes);\n", NIL );
    @@ -1600,7 +1601,7 @@ void R::dispatchFunction(Node *n) {
         Parm *pi = Getattr(ni,"wrap:parms");
         int num_arguments = emit_num_arguments(pi);
     
    -    String *overname = Getattr(ni,"sym:overname");      
    +    String *overname = Getattr(ni,"sym:overname");
         if (cur_args != num_arguments) {
           if (cur_args != -1) {
     	Printv(f->code, "} else ", NIL);
    @@ -1649,29 +1650,29 @@ void R::dispatchFunction(Node *n) {
     	if (tm) {
     	  if (Strcmp(tm,"numeric")==0) {
     	    Printf(f->code, "%sis.numeric(argv[[%d]])",
    -		j == 0 ? "" : " && ",
    -		j+1);
    +	           j == 0 ? "" : " && ",
    +	           j+1);
     	  }
     	  else if (Strcmp(tm,"integer")==0) {
     	    Printf(f->code, "%s(is.integer(argv[[%d]]) || is.numeric(argv[[%d]]))",
    -		j == 0 ? "" : " && ",
    -		j+1, j+1);
    +	           j == 0 ? "" : " && ",
    +	           j+1, j+1);
     	  }
     	  else if (Strcmp(tm,"character")==0) {
     	    Printf(f->code, "%sis.character(argv[[%d]])",
    -		j == 0 ? "" : " && ",
    -		j+1);
    +	           j == 0 ? "" : " && ",
    +	           j+1);
     	  }
     	  else {
     	    Printf(f->code, "%sextends(argtypes[%d], '%s')",
    -		j == 0 ? "" : " && ",
    -		j+1,
    -		tm);
    +	           j == 0 ? "" : " && ",
    +	           j+1,
    +	           tm);
     	  }
     	}
     	if (!SwigType_ispointer(Getattr(p, "type"))) {
     	  Printf(f->code, " && length(argv[[%d]]) == 1",
    -	      j+1);
    +	         j+1);
     	}
     	p = Getattr(p, "tmap:in:next");
           }
    @@ -1699,40 +1700,40 @@ void R::dispatchFunction(Node *n) {
     int R::functionWrapper(Node *n) {
       String *fname = Getattr(n, "name");
       String *iname = Getattr(n, "sym:name");
    -  String *type = Getattr(n, "type"); 
    -  
    +  String *type = Getattr(n, "type");
    +
       if (debugMode) {
    -    Printf(stdout, 
    +    Printf(stdout,
     	   " %s %s %s\n", fname, iname, type);
       }
       String *overname = 0;
       String *nodeType = Getattr(n, "nodeType");
    -  bool constructor = (!Cmp(nodeType, "constructor")); 
    -  bool destructor = (!Cmp(nodeType, "destructor")); 
    -  
    +  bool constructor = (!Cmp(nodeType, "constructor"));
    +  bool destructor = (!Cmp(nodeType, "destructor"));
    +
       String *sfname = NewString(iname);
    -  
    +
       if (constructor)
         Replace(sfname, "new_", "", DOH_REPLACE_FIRST);
    -  
    +
       if (Getattr(n,"sym:overloaded")) {
    -    overname = Getattr(n,"sym:overname");      
    +    overname = Getattr(n,"sym:overname");
         Append(sfname, overname);
       }
    -  
    -  if (debugMode) 
    -    Printf(stdout, 
    +
    +  if (debugMode)
    +    Printf(stdout,
     	   " processing parameters\n");
    -  
    -  
    +
    +
       ParmList *l = Getattr(n, "parms");
       Parm *p;
       String *tm;
    -  
    +
       p = l;
       while(p) {
         SwigType *resultType = Getattr(p, "type");
    -    if (expandTypedef(resultType) && 
    +    if (expandTypedef(resultType) &&
     	SwigType_istypedef(resultType)) {
           SwigType *resolved =
     	SwigType_typedef_resolve_all(resultType);
    @@ -1741,43 +1742,43 @@ int R::functionWrapper(Node *n) {
           }
         }
         p = nextSibling(p);
    -  } 
    +  }
     
    -  String *unresolved_return_type = 
    +  String *unresolved_return_type =
         Copy(type);
       if (expandTypedef(type) &&
           SwigType_istypedef(type)) {
    -    SwigType *resolved = 
    +    SwigType *resolved =
           SwigType_typedef_resolve_all(type);
         if (expandTypedef(resolved)) {
           type = Copy(resolved);
           Setattr(n, "type", type);
         }
       }
    -  if (debugMode) 
    +  if (debugMode)
         Printf(stdout, " unresolved_return_type %s\n",
     	   unresolved_return_type);
       if(processing_member_access_function) {
         if (debugMode)
    -      Printf(stdout, " '%s' '%s' '%s' '%s'\n", 
    +      Printf(stdout, " '%s' '%s' '%s' '%s'\n",
     	     fname, iname, member_name, class_name);
    -    
    +
         if(opaqueClassDeclaration)
           return SWIG_OK;
    -      
    -      
    -    /* Add the name of this member to a list for this class_name. 
    +
    +
    +    /* Add the name of this member to a list for this class_name.
            We will dump all these at the end. */
    -    
    +
         int n = Len(iname);
         char *ptr = Char(iname);
         bool isSet(0);
         if (n > 4) isSet = Strcmp(NewString(&ptr[n-4]), "_set") == 0;
    -    
    -    
    +
    +
         String *tmp = NewString("");
         Printf(tmp, "%s_%s", class_name, isSet ? "set" : "get");
    -    
    +
         List *memList = Getattr(ClassMemberTable, tmp);
         if(!memList) {
           memList = NewList();
    @@ -1788,29 +1789,29 @@ int R::functionWrapper(Node *n) {
         Append(memList, member_name);
         Append(memList, iname);
       }
    -  
    +
       int i;
       int nargs;
    -  
    +
       String *wname = Swig_name_wrapper(iname);
       Replace(wname, "_wrap", "R_swig", DOH_REPLACE_FIRST);
    -  if(overname) 
    +  if(overname)
         Append(wname, overname);
       Setattr(n,"wrap:name", wname);
     
       Wrapper *f = NewWrapper();
       Wrapper *sfun = NewWrapper();
    -  
    +
       int isVoidReturnType = (Strcmp(type, "void") == 0);
    -  // Need to use the unresolved return type since 
    -  // typedef resolution removes the const which causes a 
    +  // Need to use the unresolved return type since
    +  // typedef resolution removes the const which causes a
       // mismatch with the function action
       emit_return_variable(n, unresolved_return_type, f);
     
       SwigType *rtype = Getattr(n, "type");
       int addCopyParam = 0;
     
    -  if(!isVoidReturnType) 
    +  if(!isVoidReturnType)
         addCopyParam = addCopyParameter(rtype);
     
     
    @@ -1819,23 +1820,23 @@ int R::functionWrapper(Node *n) {
     
       //    if(addCopyParam)
       if (debugMode)
    -    Printf(stdout, "Adding a .copy argument to %s for %s = %s\n", 
    +    Printf(stdout, "Adding a .copy argument to %s for %s = %s\n",
     	   iname, type, addCopyParam ? "yes" : "no");
     
       Printv(f->def, "SWIGEXPORT SEXP\n", wname, " ( ", NIL);
     
    -  Printf(sfun->def, "# Start of %s\n", iname);         
    +  Printf(sfun->def, "# Start of %s\n", iname);
       Printv(sfun->def, "\n`", sfname, "` = function(", NIL);
     
       if(outputNamespaceInfo) {//XXX Need to be a little more discriminating
    -      if (constructor) {
    -          String *niname = Copy(iname);
    -          Replace(niname, "new_", "", DOH_REPLACE_FIRST);
    -          addNamespaceFunction(niname);
    -          Delete(niname);
    -      } else {
    -          addNamespaceFunction(iname);
    -      }
    +    if (constructor) {
    +      String *niname = Copy(iname);
    +      Replace(niname, "new_", "", DOH_REPLACE_FIRST);
    +      addNamespaceFunction(niname);
    +      Delete(niname);
    +    } else {
    +      addNamespaceFunction(iname);
    +    }
       }
     
       Swig_typemap_attach_parms("scoercein", l, f);
    @@ -1898,7 +1899,7 @@ int R::functionWrapper(Node *n) {
           name = Copy(name);
           Insert(name, 0, "s_");
         }
    -      
    +
         if(processing_variable) {
           name = Copy(name);
           Insert(name, 0, "s_");
    @@ -1923,7 +1924,7 @@ int R::functionWrapper(Node *n) {
     
     	String *snargs = NewStringf("%d", nargs);
     	Printv(sfun->code, "if(is.function(", name, ")) {", "\n",
    -	       "assert('...' %in% names(formals(", name, 
    +	       "assert('...' %in% names(formals(", name,
     	       ")) || length(formals(", name, ")) >= ", snargs, ");\n} ", NIL);
     	Delete(snargs);
     
    @@ -1978,11 +1979,11 @@ int R::functionWrapper(Node *n) {
     
     
           Printf(f->code,"%s\n",tm);
    -      if(funcptr_name) 
    -	Printf(f->code, "} else {\n%s = %s;\nR_SWIG_pushCallbackFunctionData(%s, NULL);\n}\n", 
    +      if(funcptr_name)
    +	Printf(f->code, "} else {\n%s = %s;\nR_SWIG_pushCallbackFunctionData(%s, NULL);\n}\n",
     	       lname, funcptr_name, name);
           Printv(f->def, inFirstArg ? "" : ", ", "SEXP ", name, NIL);
    -      if (Len(name) != 0) 
    +      if (Len(name) != 0)
     	inFirstArg = false;
           p = Getattr(p,"tmap:in:next");
     
    @@ -1999,7 +2000,7 @@ int R::functionWrapper(Node *n) {
         Printf(s_inputMap, "%s%s='%s'", inFirstType ? "" : ", ", name, tm);
         inFirstType = false;
     
    -    if(funcptr_name) 
    +    if(funcptr_name)
           Delete(funcptr_name);
       } /* end of looping over parameters. */
     
    @@ -2050,9 +2051,9 @@ int R::functionWrapper(Node *n) {
       String *actioncode = emit_action(n);
     
       /* Deal with the explicit return value. */
    -  if ((tm = Swig_typemap_lookup_out("out", n, Swig_cresult_name(), f, actioncode))) { 
    +  if ((tm = Swig_typemap_lookup_out("out", n, Swig_cresult_name(), f, actioncode))) {
         SwigType *retType = Getattr(n, "type");
    -    //Printf(stdout, "Return Value for %s, array? %s\n", retType, SwigType_isarray(retType) ? "yes" : "no");     
    +    //Printf(stdout, "Return Value for %s, array? %s\n", retType, SwigType_isarray(retType) ? "yes" : "no");
         /*      if(SwigType_isarray(retType)) {
     	    defineArrayAccessors(retType);
     	    } */
    @@ -2073,11 +2074,11 @@ int R::functionWrapper(Node *n) {
           Printf(f->code, "if(LOGICAL(s_swig_copy)[0]) {\n");
           Printf(f->code, "/* Deal with returning a reference. */\nr_ans = R_NilValue;\n");
           Printf(f->code, "}\n else {\n");
    -    } 
    +    }
     #endif
         Printf(f->code, "%s\n", tm);
     #if 0
    -    if(addCopyParam) 
    +    if(addCopyParam)
           Printf(f->code, "}\n"); /* end of if(s_swig_copy) ... else { ... } */
     #endif
     
    @@ -2094,8 +2095,8 @@ int R::functionWrapper(Node *n) {
         if(!isVoidReturnType)
           Printf(tmp, "Rf_protect(r_ans);\n");
     
    -    Printf(tmp, "Rf_protect(R_OutputValues = Rf_allocVector(VECSXP,%d));\nr_nprotect += %d;\n", 
    -	   numOutArgs + !isVoidReturnType, 
    +    Printf(tmp, "Rf_protect(R_OutputValues = Rf_allocVector(VECSXP,%d));\nr_nprotect += %d;\n",
    +	   numOutArgs + !isVoidReturnType,
     	   isVoidReturnType ? 1 : 2);
     
         if(!isVoidReturnType)
    @@ -2103,7 +2104,7 @@ int R::functionWrapper(Node *n) {
         Printf(tmp, "r_ans = R_OutputValues;\n");
     
         Insert(outargs, 0, tmp);
    -    Delete(tmp); 
    +    Delete(tmp);
     
     
     
    @@ -2138,30 +2139,30 @@ int R::functionWrapper(Node *n) {
         Replaceall(tm,"$source","ans");
         Replaceall(tm,"$result","ans");
         if (constructor) {
    -        Node * parent = Getattr(n, "parentNode");
    -        String * smartname = Getattr(parent, "feature:smartptr");
    -        if (smartname) {
    -            smartname = getRClassName(smartname, 1, 1);
    -            Replaceall(tm, "$R_class", smartname);
    -            Delete(smartname);
    -        }
    +      Node * parent = Getattr(n, "parentNode");
    +      String * smartname = Getattr(parent, "feature:smartptr");
    +      if (smartname) {
    +	smartname = getRClassName(smartname, 1, 1);
    +	Replaceall(tm, "$R_class", smartname);
    +	Delete(smartname);
    +      }
         }
         replaceRClass(tm, Getattr(n, "type"));
         Chop(tm);
       }
     
     
    -  Printv(sfun->code, ";", (Len(tm) ? "ans = " : ""), ".Call('", wname, 
    +  Printv(sfun->code, ";", (Len(tm) ? "ans = " : ""), ".Call('", wname,
     	 "', ", sargs, "PACKAGE='", Rpackage, "');\n", NIL);
       if(Len(tm))
         {
    -      Printf(sfun->code, "%s\n\n", tm); 
    +      Printf(sfun->code, "%s\n\n", tm);
           if (constructor)
    -	{ 
    +	{
     	  String *finalizer = NewString(iname);
     	  Replace(finalizer, "new_", "", DOH_REPLACE_FIRST);
     	  Printf(sfun->code, "reg.finalizer(ans@ref, delete_%s)\n", finalizer);
    -	}                                                                      
    +	}
           Printf(sfun->code, "ans\n");
         }
     
    @@ -2182,17 +2183,17 @@ int R::functionWrapper(Node *n) {
       if(tm) {
         SwigType *retType = Getattr(n, "type");
         replaceRClass(tm, retType);
    -  }  
    -    
    -  Printv(sfile, "attr(`", sfname, "`, 'returnType') = '", 
    -	 isVoidReturnType ? "void" : (tm ? tm : ""), 
    -	 "'\n", NIL); 
    -    
    +  }
    +
    +  Printv(sfile, "attr(`", sfname, "`, 'returnType') = '",
    +	 isVoidReturnType ? "void" : (tm ? tm : ""),
    +	 "'\n", NIL);
    +
       if(nargs > 0)
         Printv(sfile, "attr(`", sfname, "`, \"inputTypes\") = c(",
     	   s_inputTypes, ")\n", NIL);
    -  Printv(sfile, "class(`", sfname, "`) = c(\"SWIGFunction\", class('", 
    -	 sfname, "'))\n\n", NIL); 
    +  Printv(sfile, "class(`", sfname, "`) = c(\"SWIGFunction\", class('",
    +	 sfname, "'))\n\n", NIL);
     
       if (memoryProfile) {
         Printv(sfile, "memory.profile()\n", NIL);
    @@ -2205,8 +2206,8 @@ int R::functionWrapper(Node *n) {
     
     
     
    -  /* If we are dealing with a method in an C++ class, then 
    -     add the name of the R function and its definition. 
    +  /* If we are dealing with a method in an C++ class, then
    +     add the name of the R function and its definition.
          XXX need to figure out how to store the Wrapper if possible in the hash/list.
          Would like to be able to do this so that we can potentially insert
       */
    @@ -2240,21 +2241,21 @@ int R::constantWrapper(Node *n) {
     }
     
     /*****************************************************
    - Add the specified routine name to the collection of 
    + Add the specified routine name to the collection of
      generated routines that are called from R functions.
    - This is used to register the routines with R for 
    + This is used to register the routines with R for
      resolving symbols.
     
      rname - the name of the routine
    - nargs - the number of arguments it expects. 
    + nargs - the number of arguments it expects.
     ******************************************************/
     int R::addRegistrationRoutine(String *rname, int nargs) {
    -  if(!registrationTable) 
    +  if(!registrationTable)
         registrationTable = NewHash();
     
    -  String *el = 
    +  String *el =
         NewStringf("{\"%s\", (DL_FUNC) &%s, %d}", rname, rname, nargs);
    -  
    +
       Setattr(registrationTable, rname, el);
     
       return SWIG_OK;
    @@ -2267,17 +2268,17 @@ int R::addRegistrationRoutine(String *rname, int nargs) {
     ******************************************************/
     int R::outputRegistrationRoutines(File *out) {
       int i, n;
    -  if(!registrationTable) 
    +  if(!registrationTable)
         return(0);
    -  if(inCPlusMode) 
    +  if(inCPlusMode)
         Printf(out, "#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n");
     
       Printf(out, "#include \n\n");
    -  if(inCPlusMode) 
    +  if(inCPlusMode)
         Printf(out, "#ifdef __cplusplus\n}\n#endif\n\n");
     
       Printf(out, "SWIGINTERN R_CallMethodDef CallEntries[] = {\n");
    -    
    +
       List *keys = Keys(registrationTable);
       n = Len(keys);
       for(i = 0; i < n; i++)
    @@ -2289,7 +2290,7 @@ int R::outputRegistrationRoutines(File *out) {
         if (inCPlusMode)
           Printv(out, "extern \"C\" ", NIL);
         { /* R allows pckage names to have '.' in the name, which is not allowed in C++ var names
    -         we simply replace all occurrences of '.' with '_' to construct the var name */
    +	 we simply replace all occurrences of '.' with '_' to construct the var name */
           String * Rpackage_sane = Copy(Rpackage);
           Replace(Rpackage_sane, ".", "_", DOH_REPLACE_ANY);
           Printf(out, "SWIGEXPORT void R_init_%s(DllInfo *dll) {\n", Rpackage_sane);
    @@ -2310,14 +2311,14 @@ int R::outputRegistrationRoutines(File *out) {
     /****************************************************************************
       Process a struct, union or class declaration in the source code,
       or an anonymous typedef struct
    - 
    +
     *****************************************************************************/
    -//XXX What do we need to do here - 
    +//XXX What do we need to do here -
     // Define an S4 class to refer to this.
     
     void R::registerClass(Node *n) {
    -  String *name = Getattr(n, "name");    
    -  String *kind = Getattr(n, "kind");    
    +  String *name = Getattr(n, "name");
    +  String *kind = Getattr(n, "kind");
     
       if (debugMode)
         Swig_print_node(n);
    @@ -2333,42 +2334,57 @@ void R::registerClass(Node *n) {
     	Printf(base, "c(");
     	for(int i = 0; i < Len(l); i++) {
     	  registerClass(Getitem(l, i));
    -	  Printf(base, "'_p%s'%s", 
    -		 SwigType_manglestr(Getattr(Getitem(l, i), "name")), 
    -		 i < Len(l)-1 ? ", " : "");                
    +	  Printf(base, "'_p%s'%s",
    +		 SwigType_manglestr(Getattr(Getitem(l, i), "name")),
    +		 i < Len(l)-1 ? ", " : "");
     	}
     	Printf(base, ")");
           } else {
     	base = NewString("'C++Reference'");
           }
    -    } else 
    +    } else
           base = NewString("'ExternalReference'");
     
         Printf(s_classes, "setClass('%s', contains = %s)\n", sname, base);
         Delete(base);
         String *smartptr = Getattr(n, "feature:smartptr");
         if (smartptr) {
    -        SwigType *spt = Swig_cparse_type(smartptr);
    -        String *smart = SwigType_typedef_resolve_all(spt);
    -        String *smart_rname = SwigType_manglestr(smart);
    -        Printf(s_classes, "setClass('_p%s', contains = c('%s'))\n", smart_rname, sname);
    -        Delete(spt);
    -        Delete(smart);
    -        Delete(smart_rname);
    +      List *l = Getattr(n, "bases");
    +      SwigType *spt = Swig_cparse_type(smartptr);
    +      String *smart = SwigType_typedef_resolve_all(spt);
    +      String *smart_rname = SwigType_manglestr(smart);
    +      Printf(s_classes, "setClass('_p%s', contains = c('%s'", smart_rname, sname);
    +      Delete(spt);
    +      Delete(smart);
    +      Delete(smart_rname);
    +      for(int i = 0; i < Len(l); i++) {
    +	Node * b = Getitem(l, i);
    +	smartptr = Getattr(b, "feature:smartptr");
    +	if (smartptr) {
    +	  spt = Swig_cparse_type(smartptr);
    +	  smart = SwigType_typedef_resolve_all(spt);
    +	  smart_rname = SwigType_manglestr(smart);
    +	  Printf(s_classes, ", '_p%s'", smart_rname);
    +	  Delete(spt);
    +	  Delete(smart);
    +	  Delete(smart_rname);
    +	}
    +      }
    +      Printf(s_classes, "))\n");
         }
       }
     }
     
     int R::classDeclaration(Node *n) {
     
    -  String *name = Getattr(n, "name");    
    -  String *kind = Getattr(n, "kind");    
    +  String *name = Getattr(n, "name");
    +  String *kind = Getattr(n, "kind");
     
       if (debugMode)
         Swig_print_node(n);
       registerClass(n);
     
    -    
    +
       /* If we have a typedef union { ... } U, then we never get to see the typedef
          via a regular call to typedefHandler. Instead, */
       if(Getattr(n, "unnamed") && Getattr(n, "storage") && Strcmp(Getattr(n, "storage"), "typedef") == 0
    @@ -2388,7 +2404,7 @@ int R::classDeclaration(Node *n) {
       opaqueClassDeclaration = NULL;
     
     
    -  // OutputArrayMethod(name, class_member_functions, sfile);        
    +  // OutputArrayMethod(name, class_member_functions, sfile);
       if (class_member_functions)
         OutputMemberReferenceMethod(name, 0, class_member_functions, sfile);
       if (class_member_set_functions)
    @@ -2410,7 +2426,7 @@ int R::classDeclaration(Node *n) {
       }
       if(!opaque && !Strcmp(kind, "struct") && copyStruct) {
     
    -    String *def = 
    +    String *def =
           NewStringf("setClass(\"%s\",\n%srepresentation(\n", name, tab4);
         bool firstItem = true;
     
    @@ -2419,7 +2435,7 @@ int R::classDeclaration(Node *n) {
           String *tp;
     
           elName = Getattr(c, "name");
    - 
    +
           String *elKind = Getattr(c, "kind");
           if (!Equal(elKind, "variable")) {
     	c = nextSibling(c);
    @@ -2449,12 +2465,12 @@ int R::classDeclaration(Node *n) {
     
           if (!firstItem) {
     	Printf(def, ",\n");
    -      } 
    -      //	    else 
    +      }
    +      //	    else
           //XXX How can we tell if this is already done.
           //	      SwigType_push(elType, elDecl);
    -	    
    -	    
    +	
    +	
           // returns ""  tp = processType(elType, c, NULL);
           //	    Printf(stdout, " elType %p\n", elType);
           //	    tp = getRClassNameCopyStruct(Getattr(c, "type"), 1);
    @@ -2493,7 +2509,7 @@ int R::classDeclaration(Node *n) {
     int R::generateCopyRoutines(Node *n) {
       Wrapper *copyToR = NewWrapper();
       Wrapper *copyToC = NewWrapper();
    -  
    +
       String *name = Getattr(n, "name");
       String *tdname = Getattr(n, "tdname");
       String *kind = Getattr(n, "kind");
    @@ -2510,9 +2526,9 @@ int R::generateCopyRoutines(Node *n) {
       if (debugMode)
         Printf(stdout, "generateCopyRoutines:  name = %s, %s\n", name, type);
     
    -  Printf(copyToR->def, "CopyToR%s = function(value, obj = new(\"%s\"))\n{\n", 
    +  Printf(copyToR->def, "CopyToR%s = function(value, obj = new(\"%s\"))\n{\n",
     	 mangledName, name);
    -  Printf(copyToC->def, "CopyToC%s = function(value, obj)\n{\n", 
    +  Printf(copyToC->def, "CopyToC%s = function(value, obj)\n{\n",
     	 mangledName);
     
       Node *c = firstChild(n);
    @@ -2548,22 +2564,22 @@ int R::generateCopyRoutines(Node *n) {
       }
       Printf(copyToR->code, "obj;\n}\n\n");
       String *rclassName = getRClassNameCopyStruct(type, 0); // without the Ref.
    -  Printf(sfile, "# Start definition of copy functions & methods for %s\n", rclassName);  
    -  
    +  Printf(sfile, "# Start definition of copy functions & methods for %s\n", rclassName);
    +
       Wrapper_print(copyToR, sfile);
       Printf(copyToC->code, "obj\n}\n\n");
       Wrapper_print(copyToC, sfile);
    -  
    -  
    -  Printf(sfile, "# Start definition of copy methods for %s\n", rclassName);  
    -  Printf(sfile, "setMethod('copyToR', '_p_%s', CopyToR%s);\n", rclassName, 
    +
    +
    +  Printf(sfile, "# Start definition of copy methods for %s\n", rclassName);
    +  Printf(sfile, "setMethod('copyToR', '_p_%s', CopyToR%s);\n", rclassName,
     	 mangledName);
    -  Printf(sfile, "setMethod('copyToC', '%s', CopyToC%s);\n\n", rclassName, 
    +  Printf(sfile, "setMethod('copyToC', '%s', CopyToC%s);\n\n", rclassName,
     	 mangledName);
    -  
    -  Printf(sfile, "# End definition of copy methods for %s\n", rclassName);  
    -  Printf(sfile, "# End definition of copy functions & methods for %s\n", rclassName);  
    -      
    +
    +  Printf(sfile, "# End definition of copy methods for %s\n", rclassName);
    +  Printf(sfile, "# End definition of copy functions & methods for %s\n", rclassName);
    +
       String *m = NewStringf("%sCopyToR", name);
       addNamespaceMethod(m);
       char *tt = Char(m);  tt[Len(m)-1] = 'C';
    @@ -2580,9 +2596,9 @@ int R::generateCopyRoutines(Node *n) {
     
     
     /*****
    -      Called when there is a typedef to be invoked. 
    +      Called when there is a typedef to be invoked.
     
    -      XXX Needs to be enhanced or split to handle the case where we have a 
    +      XXX Needs to be enhanced or split to handle the case where we have a
           typedef within a classDeclaration emission because the struct/union/etc.
           is anonymous.
     ******/
    @@ -2600,7 +2616,7 @@ int R::typedefHandler(Node *n) {
         trueName += 7;
         if (debugMode)
           Printf(stdout, " Defining S class %s\n", trueName);
    -    Printf(s_classes, "setClass('_p%s', contains = 'ExternalReference')\n", 
    +    Printf(s_classes, "setClass('_p%s', contains = 'ExternalReference')\n",
     	   SwigType_manglestr(name));
       }
     
    @@ -2612,7 +2628,7 @@ int R::typedefHandler(Node *n) {
     /*********************
       Called when processing a field in a "class", i.e. struct, union or
       actual class.  We set a state variable so that we can correctly
    -  interpret the resulting functionWrapper() call and understand that 
    +  interpret the resulting functionWrapper() call and understand that
       it is for a field element.
     **********************/
     int R::membervariableHandler(Node *n) {
    @@ -2621,7 +2637,7 @@ int R::membervariableHandler(Node *n) {
       processing_member_access_function = 1;
       member_name = Getattr(n,"sym:name");
       if (debugMode)
    -    Printf(stdout, " name = %s, sym:name = %s\n", 
    +    Printf(stdout, " name = %s, sym:name = %s\n",
     	   Getattr(n, "name"), member_name);
     
       int status(Language::membervariableHandler(n));
    @@ -2650,7 +2666,7 @@ String * R::runtimeCode() {
     
     
     /**
    -   Called when SWIG wants to initialize this 
    +   Called when SWIG wants to initialize this
        We initialize anythin we want here.
        Most importantly, tell SWIG where to find the files (e.g. r.swg) for this module.
        Use Swig_mark_arg() to tell SWIG that it is understood and not to throw an error.
    @@ -2672,7 +2688,7 @@ void R::main(int argc, char *argv[]) {
       this->Argc = argc;
       this->Argv = argv;
     
    -  allow_overloading();// can we support this?    
    +  allow_overloading();// can we support this?
     
       for(int i = 0; i < argc; i++) {
         if(strcmp(argv[i], "-package") == 0) {
    @@ -2761,9 +2777,9 @@ int R::outputCommandLineArguments(File *out)
     
     
     
    -/* How SWIG instantiates an object from this module. 
    +/* How SWIG instantiates an object from this module.
        See swigmain.cxx */
    -extern "C" 
    +extern "C"
     Language *swig_r(void) {
       return new R();
     }
    @@ -2782,11 +2798,11 @@ String * R::processType(SwigType *t, Node *n, int *nargs) {
       SwigType *tmp = Getattr(n, "tdname");
       if (debugMode)
         Printf(stdout, "processType %s (tdname = %s)\n", Getattr(n, "name"), tmp);
    -  
    +
       SwigType *td = t;
       if (expandTypedef(t) &&
           SwigType_istypedef(t)) {
    -    SwigType *resolved = 
    +    SwigType *resolved =
           SwigType_typedef_resolve_all(t);
         if (expandTypedef(resolved)) {
           td = Copy(resolved);
    @@ -2800,10 +2816,10 @@ String * R::processType(SwigType *t, Node *n, int *nargs) {
           if (debugMode)
     	Printf(stdout, " Defining class %s\n",  b);
     
    -      Printf(s_classes, "setClass('%s', contains = 'ExternalReference')\n", b);       
    +      Printf(s_classes, "setClass('%s', contains = 'ExternalReference')\n", b);
           Setattr(SClassDefs, b, b);
         }
    -     
    +
       }
     
     
    @@ -2812,9 +2828,9 @@ String * R::processType(SwigType *t, Node *n, int *nargs) {
     
       if(SwigType_isfunctionpointer(t)) {
         if (debugMode)
    -      Printf(stdout, 
    +      Printf(stdout,
     	     " Defining pointer handler %s\n",  t);
    -       
    +
         String *tmp = createFunctionPointerHandler(t, n, nargs);
         return tmp;
       }
    @@ -2826,17 +2842,4 @@ String * R::processType(SwigType *t, Node *n, int *nargs) {
         return NULL;
     }
     
    -
    -
    -
    -
    -
    -
    -
    -
     /*************************************************************************************/
    -
    -
    -
    -
    -
    
    From 711ae145418b6048234653d0fbba38020fb89333 Mon Sep 17 00:00:00 2001
    From: "Lamarre, Mathieu" 
    Date: Thu, 31 Aug 2017 09:43:07 -0400
    Subject: [PATCH 269/455] Define _DEBUG to 1 to do exactly like /LDd, /MDd or
     /MTd compiler options
    
    ---
     Lib/python/pyruntime.swg | 2 +-
     1 file changed, 1 insertion(+), 1 deletion(-)
    
    diff --git a/Lib/python/pyruntime.swg b/Lib/python/pyruntime.swg
    index fad97be9f..26d3081a0 100644
    --- a/Lib/python/pyruntime.swg
    +++ b/Lib/python/pyruntime.swg
    @@ -3,7 +3,7 @@
     /* Use debug wrappers with the Python release dll */
     # undef _DEBUG
     # include 
    -# define _DEBUG
    +# define _DEBUG 1
     #else
     # include 
     #endif
    
    From eb68e4375dccfb337fad0896b4a5510c5515b3ad Mon Sep 17 00:00:00 2001
    From: William S Fulton 
    Date: Tue, 5 Sep 2017 18:44:00 +0100
    Subject: [PATCH 270/455] Add support for member function pointers with
     ref-qualifiers
    
    ---
     Examples/test-suite/cpp11_ref_qualifiers.i  | 117 ++++++++++++++++++++
     Examples/test-suite/member_funcptr_galore.i |   2 +-
     Source/CParse/parser.y                      |  13 ++-
     Source/Swig/stype.c                         | 108 +++++++++++-------
     4 files changed, 195 insertions(+), 45 deletions(-)
    
    diff --git a/Examples/test-suite/cpp11_ref_qualifiers.i b/Examples/test-suite/cpp11_ref_qualifiers.i
    index 7e9f0e170..781e52f23 100644
    --- a/Examples/test-suite/cpp11_ref_qualifiers.i
    +++ b/Examples/test-suite/cpp11_ref_qualifiers.i
    @@ -1,5 +1,11 @@
     %module cpp11_ref_qualifiers
     
    +%warnfilter(SWIGWARN_TYPEMAP_SWIGTYPELEAK_MSG) ccextra2;
    +%warnfilter(SWIGWARN_TYPEMAP_SWIGTYPELEAK_MSG) ccextra3;
    +%warnfilter(SWIGWARN_TYPEMAP_SWIGTYPELEAK_MSG) cc2;
    +%warnfilter(SWIGWARN_TYPEMAP_SWIGTYPELEAK_MSG) cc3;
    +%warnfilter(SWIGWARN_TYPEMAP_SWIGTYPELEAK_MSG) cc5;
    +
     %include 
     
     %ignore Host::h() const &;
    @@ -89,3 +95,114 @@ struct ConversionOperators2 {
       virtual operator string() && { return std::move(string()); }
     };
     %}
    +
    +%inline %{
    +struct Funcs {
    +  short FF(bool) { return 0; }
    +  short CC(bool) const & { return 0; }
    +};
    +
    +class MemberFuncPtrs
    +{
    +public:
    +  // member ref-qualified function pointers, unnamed parameters
    +  int aaa1(short (Funcs::*)(bool) &) const;
    +  int aaa2(short (Funcs::* const *&)(bool) &) const;
    +  int aaa3(short (Funcs::* *&)(bool) &) const;
    +  int aaa4(short (Funcs::* *const&)(bool) &) const;
    +  int aaa5(short (Funcs::* &)(bool) &) const;
    +  int aaa6(short (Funcs::* const)(bool) &) const;
    +  int aaa7(short (Funcs::* const&)(bool) &) const;
    +
    +  // member cv-qualified and ref-qualified function pointers, unnamed parameters
    +  int bbb1(short (Funcs::*)(bool) const &) const;
    +  int bbb2(short (Funcs::* const *&)(bool) const &) const;
    +  int bbb3(short (Funcs::* *&)(bool) const &) const;
    +  int bbb4(short (Funcs::* *const&)(bool) const &) const;
    +  int bbb5(short (Funcs::* &)(bool) const &) const;
    +  int bbb6(short (Funcs::* const)(bool) const &) const;
    +  int bbb7(short (Funcs::* const&)(bool) const &) const;
    +
    +  // member ref-qualified function pointers, named parameters
    +  int qqq1(short (Funcs::* qq1)(bool) &) const;
    +  int qqq2(short (Funcs::* const *& qq2)(bool) &) const;
    +  int qqq3(short (Funcs::* *& qq3)(bool) &) const;
    +  int qqq4(short (Funcs::* *const& qq4)(bool) &) const;
    +  int qqq5(short (Funcs::* & qq5)(bool) &) const;
    +  int qqq6(short (Funcs::* const qq6)(bool) &) const;
    +  int qqq7(short (Funcs::* const& qq7)(bool) &) const;
    +
    +  // member cv-qualified and ref-qualified function pointers, named parameters
    +  int rrr1(short (Funcs::* rr1)(bool) const &) const;
    +  int rrr2(short (Funcs::* const *& rr2)(bool) const &) const;
    +  int rrr3(short (Funcs::* *& rr3)(bool) const &) const;
    +  int rrr4(short (Funcs::* *const& rr4)(bool) const &) const;
    +  int rrr5(short (Funcs::* & rr5)(bool) const &) const;
    +  int rrr6(short (Funcs::* const rr6)(bool) const &) const;
    +  int rrr7(short (Funcs::* const& rr7)(bool) const &) const;
    +};
    +
    +// member ref-qualified function pointers, unnamed parameters
    +int MemberFuncPtrs::aaa1(short (Funcs::*)(bool) &) const { return 0; }
    +int MemberFuncPtrs::aaa2(short (Funcs::* const *&)(bool) &) const { return 0; }
    +int MemberFuncPtrs::aaa3(short (Funcs::* *&)(bool) &) const { return 0; }
    +int MemberFuncPtrs::aaa4(short (Funcs::* *const&)(bool) &) const { return 0; }
    +int MemberFuncPtrs::aaa5(short (Funcs::* &)(bool) &) const { return 0; }
    +int MemberFuncPtrs::aaa6(short (Funcs::* const)(bool) &) const { return 0; }
    +int MemberFuncPtrs::aaa7(short (Funcs::* const&)(bool) &) const { return 0; }
    +
    +// member cv-qualified and ref-qualified function pointers, unnamed parameters
    +int MemberFuncPtrs::bbb1(short (Funcs::*)(bool) const &) const { return 0; }
    +int MemberFuncPtrs::bbb2(short (Funcs::* const *&)(bool) const &) const { return 0; }
    +int MemberFuncPtrs::bbb3(short (Funcs::* *&)(bool) const &) const { return 0; }
    +int MemberFuncPtrs::bbb4(short (Funcs::* *const&)(bool) const &) const { return 0; }
    +int MemberFuncPtrs::bbb5(short (Funcs::* &)(bool) const &) const { return 0; }
    +int MemberFuncPtrs::bbb6(short (Funcs::* const)(bool) const &) const { return 0; }
    +int MemberFuncPtrs::bbb7(short (Funcs::* const&)(bool) const &) const { return 0; }
    +
    +// member ref-qualified function pointers, named parameters
    +int MemberFuncPtrs::qqq1(short (Funcs::* qq1)(bool) &) const { return 0; }
    +int MemberFuncPtrs::qqq2(short (Funcs::* const *& qq2)(bool) &) const { return 0; }
    +int MemberFuncPtrs::qqq3(short (Funcs::* *& qq3)(bool) &) const { return 0; }
    +int MemberFuncPtrs::qqq4(short (Funcs::* *const& qq4)(bool) &) const { return 0; }
    +int MemberFuncPtrs::qqq5(short (Funcs::* & qq5)(bool) &) const { return 0; }
    +int MemberFuncPtrs::qqq6(short (Funcs::* const qq6)(bool) &) const { return 0; }
    +int MemberFuncPtrs::qqq7(short (Funcs::* const& qq7)(bool) &) const { return 0; }
    +
    +// member cv-qualified and ref-qualified function pointers, named parameters
    +int MemberFuncPtrs::rrr1(short (Funcs::* rr1)(bool) const &) const { return 0; }
    +int MemberFuncPtrs::rrr2(short (Funcs::* const *& rr2)(bool) const &) const { return 0; }
    +int MemberFuncPtrs::rrr3(short (Funcs::* *& rr3)(bool) const &) const { return 0; }
    +int MemberFuncPtrs::rrr4(short (Funcs::* *const& rr4)(bool) const &) const { return 0; }
    +int MemberFuncPtrs::rrr5(short (Funcs::* & rr5)(bool) const &) const { return 0; }
    +int MemberFuncPtrs::rrr6(short (Funcs::* const rr6)(bool) const &) const { return 0; }
    +int MemberFuncPtrs::rrr7(short (Funcs::* const& rr7)(bool) const &) const { return 0; }
    +
    +// member cv-qualified and ref-qualified pointer variables
    +short (Funcs::* cc1)(bool) const & = &Funcs::CC;
    +
    +short (Funcs::* const * ccextra2)(bool) const & = &cc1;
    +short (Funcs::* * ccextra3)(bool) const & = &cc1;
    +short (Funcs::* *const ccextra4)(bool) const & = &cc1;
    +
    +short (Funcs::* const *& cc2)(bool) const & = ccextra2;
    +short (Funcs::* *& cc3)(bool) const & = ccextra3;
    +short (Funcs::* *const& cc4)(bool) const & = ccextra4;
    +short (Funcs::* & cc5)(bool) const & = cc1;
    +short (Funcs::* const cc6)(bool) const & = &Funcs::CC;
    +short (Funcs::* const& cc7)(bool) const & = cc1;
    +%}
    +
    +%inline %{
    +
    +struct Funktions {
    +  int addByValue(const int &a, int b) const & { return a+b; }
    +  int * addByPointer(const int &a, int b) const & { static int val; val = a+b; return &val; }
    +  int & addByReference(const int &a, int b) const & { static int val; val = a+b; return val; }
    +};
    +
    +int call1(int (Funktions::*d)(const int &, int) const &, int a, int b) { Funktions f; return (f.*d)(a, b); }
    +//int call2(int * (Funktions::*d)(const int &, int) const &, int a, int b) { Funktions f; return *(f.*d)(a, b); }
    +//int call3(int & (Funktions::*d)(const int &, int) const &, int a, int b) { Funktions f; return (f.*d)(a, b); }
    +%}
    +%constant int (Funktions::*ADD_BY_VALUE)(const int &, int) const & = &Funktions::addByValue;
    diff --git a/Examples/test-suite/member_funcptr_galore.i b/Examples/test-suite/member_funcptr_galore.i
    index 01857ff1a..27c2f02a7 100644
    --- a/Examples/test-suite/member_funcptr_galore.i
    +++ b/Examples/test-suite/member_funcptr_galore.i
    @@ -161,7 +161,7 @@ public:
         int qqq7(short (Funcs::* const& qq7)(bool)) const;
     };
     
    -    // member const function pointers, unnamed parameters
    +// member const function pointers, unnamed parameters
     int MemberFuncPtrs::aaa1(short (Funcs::* )(bool) const) const { return 0; }
     int MemberFuncPtrs::aaa2(short (Funcs::* const *&)(bool) const) const { return 0; }
     int MemberFuncPtrs::aaa3(short (Funcs::* *& )(bool) const) const { return 0; }
    diff --git a/Source/CParse/parser.y b/Source/CParse/parser.y
    index f88eb5f60..9cf6f00c6 100644
    --- a/Source/CParse/parser.y
    +++ b/Source/CParse/parser.y
    @@ -1897,10 +1897,10 @@ constant_directive :  CONSTANT identifier EQUAL definetype SEMI {
                    }
     	       /* Member const function pointers . eg.
     	         %constant short (Funcs::*pmf)(bool) const = &Funcs::F; */
    -	       | CONSTANT type direct_declarator LPAREN parms RPAREN CONST_QUAL def_args SEMI {
    +	       | CONSTANT type direct_declarator LPAREN parms RPAREN cv_ref_qualifier def_args SEMI {
     		 if (($8.type != T_ERROR) && ($8.type != T_SYMBOL)) {
     		   SwigType_add_function($2, $5);
    -		   SwigType_add_qualifier($2, "const");
    +		   SwigType_push($2, $7.qualifier);
     		   SwigType_push($2, $3.type);
     		   /* Sneaky callback function trick */
     		   if (SwigType_isfunction($2)) {
    @@ -5118,12 +5118,13 @@ parameter_declarator : declarator def_args {
                 }
     	    /* Member const function pointer parameters. eg.
     	      int f(short (Funcs::*parm)(bool) const); */
    -	    | direct_declarator LPAREN parms RPAREN CONST_QUAL {
    +	    | direct_declarator LPAREN parms RPAREN cv_ref_qualifier {
     	      SwigType *t;
     	      $$ = $1;
     	      t = NewStringEmpty();
     	      SwigType_add_function(t,$3);
    -	      SwigType_add_qualifier(t, "const");
    +	      if ($5.qualifier)
    +	        SwigType_push(t, $5.qualifier);
     	      if (!$$.have_parms) {
     		$$.parms = $3;
     		$$.have_parms = 1;
    @@ -5812,12 +5813,12 @@ direct_abstract_declarator : direct_abstract_declarator LBRACKET RBRACKET {
     		      $$.have_parms = 1;
     		    }
     		  }
    -                  | direct_abstract_declarator LPAREN parms RPAREN type_qualifier {
    +                  | direct_abstract_declarator LPAREN parms RPAREN cv_ref_qualifier {
     		    SwigType *t;
                         $$ = $1;
     		    t = NewStringEmpty();
                         SwigType_add_function(t,$3);
    -		    SwigType_push(t, $5);
    +		    SwigType_push(t, $5.qualifier);
     		    if (!$$.type) {
     		      $$.type = t;
     		    } else {
    diff --git a/Source/Swig/stype.c b/Source/Swig/stype.c
    index 4b745b335..346731996 100644
    --- a/Source/Swig/stype.c
    +++ b/Source/Swig/stype.c
    @@ -544,10 +544,9 @@ String *SwigType_str(const SwigType *s, const_String_or_char_ptr id) {
       String *element = 0;
       String *nextelement;
       String *forwardelement;
    -  String *member_const_function_element = 0;
    +  SwigType *member_function_qualifiers = 0;
       List *elements;
       int nelements, i;
    -  int member_const_function = 0;
     
       if (id) {
         /* stringify the id expanding templates, for example when the id is a fully qualified templated class name */
    @@ -578,14 +577,12 @@ String *SwigType_str(const SwigType *s, const_String_or_char_ptr id) {
           forwardelement = 0;
         }
         if (SwigType_isqualifier(element)) {
    -      if (!member_const_function) {
    +      if (!member_function_qualifiers) {
     	DOH *q = 0;
     	q = SwigType_parm(element);
     	Insert(result, 0, " ");
     	Insert(result, 0, q);
     	Delete(q);
    -      } else {
    -        member_const_function = 0;
           }
         } else if (SwigType_ispointer(element)) {
           Insert(result, 0, "*");
    @@ -602,19 +599,27 @@ String *SwigType_str(const SwigType *s, const_String_or_char_ptr id) {
     	Insert(result, 0, "(");
     	Append(result, ")");
           }
    -      if (SwigType_isqualifier(nextelement)) {
    -	member_const_function_element = nextelement;
    -	member_const_function = 1;
    +      {
    +	String *next3elements = NewStringEmpty();
    +	int j;
    +	for (j = i + 1; j < i + 4 && j < nelements; j++) {
    +	  Append(next3elements, Getitem(elements, j));
    +	}
    +	if (SwigType_isfunction(next3elements))
    +	  member_function_qualifiers = SwigType_pop_function_qualifiers(next3elements);
    +	Delete(next3elements);
           }
           Delete(q);
         } else if (SwigType_isreference(element)) {
    -      Insert(result, 0, "&");
    +      if (!member_function_qualifiers)
    +	Insert(result, 0, "&");
           if ((forwardelement) && ((SwigType_isfunction(forwardelement) || (SwigType_isarray(forwardelement))))) {
     	Insert(result, 0, "(");
     	Append(result, ")");
           }
         } else if (SwigType_isrvalue_reference(element)) {
    -      Insert(result, 0, "&&");
    +      if (!member_function_qualifiers)
    +	Insert(result, 0, "&&");
           if ((nextelement) && ((SwigType_isfunction(nextelement) || (SwigType_isarray(nextelement))))) {
     	Insert(result, 0, "(");
     	Append(result, ")");
    @@ -639,12 +644,13 @@ String *SwigType_str(const SwigType *s, const_String_or_char_ptr id) {
     	  Append(result, ",");
           }
           Append(result, ")");
    -      if (member_const_function_element) {
    -	String *p = SwigType_str(member_const_function_element, 0);
    +      if (member_function_qualifiers) {
    +	String *p = SwigType_str(member_function_qualifiers, 0);
     	Append(result, " ");
     	Append(result, p);
     	Delete(p);
    -	member_const_function_element = 0;
    +	Delete(member_function_qualifiers);
    +	member_function_qualifiers = 0;
           }
           Delete(parms);
         } else {
    @@ -678,7 +684,7 @@ SwigType *SwigType_ltype(const SwigType *s) {
       int nelements, i;
       int firstarray = 1;
       int notypeconv = 0;
    -  int memberpointer = 0;
    +  int ignore_member_function_qualifiers = 0;
     
       result = NewStringEmpty();
       tc = Copy(s);
    @@ -705,6 +711,7 @@ SwigType *SwigType_ltype(const SwigType *s) {
           tc = td;
         }
       }
    +
       elements = SwigType_split(tc);
       nelements = Len(elements);
     
    @@ -714,18 +721,34 @@ SwigType *SwigType_ltype(const SwigType *s) {
         /* when we see a function, we need to preserve the following types */
         if (SwigType_isfunction(element)) {
           notypeconv = 1;
    +      ignore_member_function_qualifiers = 0;
         }
    -    if (SwigType_isqualifier(element)) {
    -      if (memberpointer)
    -	Append(result, element);
    -      /* otherwise ignore */
    +    if (ignore_member_function_qualifiers) {
    +      /* cv-qualifiers and ref-qualifiers up until the f() element have already been added */
    +    } else if (SwigType_isqualifier(element)) {
    +      /* swallow cv-qualifiers */
         } else if (SwigType_ispointer(element)) {
           Append(result, element);
           firstarray = 0;
         } else if (SwigType_ismemberpointer(element)) {
           Append(result, element);
    +      {
    +	String *next3elements = NewStringEmpty();
    +	int j;
    +	for (j = i + 1; j < i + 4 && j < nelements; j++) {
    +	  Append(next3elements, Getitem(elements, j));
    +	}
    +	if (SwigType_isfunction(next3elements)) {
    +	  SwigType *member_function_qualifiers = SwigType_pop_function_qualifiers(next3elements);
    +	  /* compilers won't let us cast from a member function without qualifiers to one with qualifiers, so the qualifiers are kept in the ltype */
    +	  if (member_function_qualifiers)
    +	    Append(result, member_function_qualifiers);
    +	  Delete(member_function_qualifiers);
    +	  ignore_member_function_qualifiers = 1;
    +	}
    +	Delete(next3elements);
    +      }
           firstarray = 0;
    -      memberpointer = 1;
         } else if (SwigType_isreference(element)) {
           if (notypeconv) {
     	Append(result, element);
    @@ -764,13 +787,14 @@ SwigType *SwigType_ltype(const SwigType *s) {
     }
     
     /* -----------------------------------------------------------------------------
    - * SwigType_lstr(DOH *s, DOH *id)
    + * SwigType_lstr()
      *
      * Produces a type-string that is suitable as a lvalue in an expression.
      * That is, a type that can be freely assigned a value without violating
      * any C assignment rules.
      *
      *      -   Qualifiers such as 'const' and 'volatile' are stripped.
    + *          Except for member function cv-qualifiers and ref-qualifiers.
      *      -   Arrays are converted into a *single* pointer (i.e.,
      *          double [][] becomes double *).
      *      -   References are converted into a pointer.
    @@ -800,7 +824,7 @@ String *SwigType_rcaststr(const SwigType *s, const_String_or_char_ptr name) {
       String *element = 0;
       String *nextelement;
       String *forwardelement;
    -  String *member_const_function_element = 0;
    +  String *member_function_qualifiers = 0;
       SwigType *td, *tc = 0;
       const SwigType *rs;
       List *elements;
    @@ -809,7 +833,6 @@ String *SwigType_rcaststr(const SwigType *s, const_String_or_char_ptr name) {
       int firstarray = 1;
       int isreference = 0;
       int isfunction = 0;
    -  int member_const_function = 0;
     
       result = NewStringEmpty();
     
    @@ -858,15 +881,13 @@ String *SwigType_rcaststr(const SwigType *s, const_String_or_char_ptr name) {
           forwardelement = 0;
         }
         if (SwigType_isqualifier(element)) {
    -      if (!member_const_function) {
    +      if (!member_function_qualifiers) {
     	DOH *q = 0;
     	q = SwigType_parm(element);
     	Insert(result, 0, " ");
     	Insert(result, 0, q);
     	Delete(q);
     	clear = 0;
    -      } else {
    -        member_const_function = 0;
           }
         } else if (SwigType_ispointer(element)) {
           Insert(result, 0, "*");
    @@ -880,32 +901,42 @@ String *SwigType_rcaststr(const SwigType *s, const_String_or_char_ptr name) {
           Insert(result, 0, "::*");
           q = SwigType_parm(element);
           Insert(result, 0, q);
    -      Delete(q);
           if ((forwardelement) && ((SwigType_isfunction(forwardelement) || (SwigType_isarray(forwardelement))))) {
     	Insert(result, 0, "(");
     	Append(result, ")");
           }
    -      if (SwigType_isqualifier(nextelement)) {
    -	member_const_function_element = nextelement;
    -	member_const_function = 1;
    +      {
    +	String *next3elements = NewStringEmpty();
    +	int j;
    +	for (j = i + 1; j < i + 4 && j < nelements; j++) {
    +	  Append(next3elements, Getitem(elements, j));
    +	}
    +	if (SwigType_isfunction(next3elements))
    +	  member_function_qualifiers = SwigType_pop_function_qualifiers(next3elements);
    +	Delete(next3elements);
           }
           firstarray = 0;
    +      Delete(q);
         } else if (SwigType_isreference(element)) {
    -      Insert(result, 0, "&");
    +      if (!member_function_qualifiers) {
    +	Insert(result, 0, "&");
    +	if (!isfunction)
    +	  isreference = 1;
    +      }
           if ((forwardelement) && ((SwigType_isfunction(forwardelement) || (SwigType_isarray(forwardelement))))) {
     	Insert(result, 0, "(");
     	Append(result, ")");
           }
    -      if (!isfunction)
    -	isreference = 1;
         } else if (SwigType_isrvalue_reference(element)) {
    -      Insert(result, 0, "&&");
    +      if (!member_function_qualifiers) {
    +	Insert(result, 0, "&&");
    +	if (!isfunction)
    +	  isreference = 1;
    +      }
           if ((forwardelement) && ((SwigType_isfunction(forwardelement) || (SwigType_isarray(forwardelement))))) {
     	Insert(result, 0, "(");
     	Append(result, ")");
           }
    -      if (!isfunction)
    -	isreference = 1;
           clear = 0;
         } else if (SwigType_isarray(element)) {
           DOH *size;
    @@ -935,12 +966,13 @@ String *SwigType_rcaststr(const SwigType *s, const_String_or_char_ptr name) {
           }
           Append(result, ")");
           Delete(parms);
    -      if (member_const_function_element) {
    -	String *p = SwigType_str(member_const_function_element, 0);
    +      if (member_function_qualifiers) {
    +	String *p = SwigType_str(member_function_qualifiers, 0);
     	Append(result, " ");
     	Append(result, p);
     	Delete(p);
    -	member_const_function_element = 0;
    +	Delete(member_function_qualifiers);
    +	member_function_qualifiers = 0;
     	clear = 0;
           }
           isfunction = 1;
    
    From 45c161dfcea94d5eaae65e753483a7c117506425 Mon Sep 17 00:00:00 2001
    From: William S Fulton 
    Date: Thu, 7 Sep 2017 06:58:01 +0100
    Subject: [PATCH 271/455] Fix wrapping of some member function pointer
     parameters
    
    Generated code did not compile if both cv-qualifiers and rvalue
    ref-qualifiers were present in the member function pointer.
    ---
     Examples/test-suite/cpp11_ref_qualifiers.i | 16 ++++++++++++++++
     Source/Swig/stype.c                        |  2 +-
     2 files changed, 17 insertions(+), 1 deletion(-)
    
    diff --git a/Examples/test-suite/cpp11_ref_qualifiers.i b/Examples/test-suite/cpp11_ref_qualifiers.i
    index 781e52f23..237234e9c 100644
    --- a/Examples/test-suite/cpp11_ref_qualifiers.i
    +++ b/Examples/test-suite/cpp11_ref_qualifiers.i
    @@ -114,6 +114,8 @@ public:
       int aaa6(short (Funcs::* const)(bool) &) const;
       int aaa7(short (Funcs::* const&)(bool) &) const;
     
    +  int aaa8(short (Funcs::* const&)(bool) &&) const;
    +
       // member cv-qualified and ref-qualified function pointers, unnamed parameters
       int bbb1(short (Funcs::*)(bool) const &) const;
       int bbb2(short (Funcs::* const *&)(bool) const &) const;
    @@ -123,6 +125,8 @@ public:
       int bbb6(short (Funcs::* const)(bool) const &) const;
       int bbb7(short (Funcs::* const&)(bool) const &) const;
     
    +  int bbb8(short (Funcs::*)(bool) const &&) const;
    +
       // member ref-qualified function pointers, named parameters
       int qqq1(short (Funcs::* qq1)(bool) &) const;
       int qqq2(short (Funcs::* const *& qq2)(bool) &) const;
    @@ -132,6 +136,8 @@ public:
       int qqq6(short (Funcs::* const qq6)(bool) &) const;
       int qqq7(short (Funcs::* const& qq7)(bool) &) const;
     
    +  int qqq8(short (Funcs::* const& qq8)(bool) &&) const;
    +
       // member cv-qualified and ref-qualified function pointers, named parameters
       int rrr1(short (Funcs::* rr1)(bool) const &) const;
       int rrr2(short (Funcs::* const *& rr2)(bool) const &) const;
    @@ -140,6 +146,8 @@ public:
       int rrr5(short (Funcs::* & rr5)(bool) const &) const;
       int rrr6(short (Funcs::* const rr6)(bool) const &) const;
       int rrr7(short (Funcs::* const& rr7)(bool) const &) const;
    +
    +  int rrr8(short (Funcs::* rr1)(bool) const &&) const;
     };
     
     // member ref-qualified function pointers, unnamed parameters
    @@ -151,6 +159,8 @@ int MemberFuncPtrs::aaa5(short (Funcs::* &)(bool) &) const { return 0; }
     int MemberFuncPtrs::aaa6(short (Funcs::* const)(bool) &) const { return 0; }
     int MemberFuncPtrs::aaa7(short (Funcs::* const&)(bool) &) const { return 0; }
     
    +int MemberFuncPtrs::aaa8(short (Funcs::* const&)(bool) &&) const { return 0; }
    +
     // member cv-qualified and ref-qualified function pointers, unnamed parameters
     int MemberFuncPtrs::bbb1(short (Funcs::*)(bool) const &) const { return 0; }
     int MemberFuncPtrs::bbb2(short (Funcs::* const *&)(bool) const &) const { return 0; }
    @@ -160,6 +170,8 @@ int MemberFuncPtrs::bbb5(short (Funcs::* &)(bool) const &) const { return 0; }
     int MemberFuncPtrs::bbb6(short (Funcs::* const)(bool) const &) const { return 0; }
     int MemberFuncPtrs::bbb7(short (Funcs::* const&)(bool) const &) const { return 0; }
     
    +int MemberFuncPtrs::bbb8(short (Funcs::*)(bool) const &&) const { return 0; }
    +
     // member ref-qualified function pointers, named parameters
     int MemberFuncPtrs::qqq1(short (Funcs::* qq1)(bool) &) const { return 0; }
     int MemberFuncPtrs::qqq2(short (Funcs::* const *& qq2)(bool) &) const { return 0; }
    @@ -169,6 +181,8 @@ int MemberFuncPtrs::qqq5(short (Funcs::* & qq5)(bool) &) const { return 0; }
     int MemberFuncPtrs::qqq6(short (Funcs::* const qq6)(bool) &) const { return 0; }
     int MemberFuncPtrs::qqq7(short (Funcs::* const& qq7)(bool) &) const { return 0; }
     
    +int MemberFuncPtrs::qqq8(short (Funcs::* const& qq8)(bool) &&) const { return 0; }
    +
     // member cv-qualified and ref-qualified function pointers, named parameters
     int MemberFuncPtrs::rrr1(short (Funcs::* rr1)(bool) const &) const { return 0; }
     int MemberFuncPtrs::rrr2(short (Funcs::* const *& rr2)(bool) const &) const { return 0; }
    @@ -178,6 +192,8 @@ int MemberFuncPtrs::rrr5(short (Funcs::* & rr5)(bool) const &) const { return 0;
     int MemberFuncPtrs::rrr6(short (Funcs::* const rr6)(bool) const &) const { return 0; }
     int MemberFuncPtrs::rrr7(short (Funcs::* const& rr7)(bool) const &) const { return 0; }
     
    +int MemberFuncPtrs::rrr8(short (Funcs::* rr1)(bool) const &&) const { return 0; }
    +
     // member cv-qualified and ref-qualified pointer variables
     short (Funcs::* cc1)(bool) const & = &Funcs::CC;
     
    diff --git a/Source/Swig/stype.c b/Source/Swig/stype.c
    index 346731996..364329d08 100644
    --- a/Source/Swig/stype.c
    +++ b/Source/Swig/stype.c
    @@ -620,7 +620,7 @@ String *SwigType_str(const SwigType *s, const_String_or_char_ptr id) {
         } else if (SwigType_isrvalue_reference(element)) {
           if (!member_function_qualifiers)
     	Insert(result, 0, "&&");
    -      if ((nextelement) && ((SwigType_isfunction(nextelement) || (SwigType_isarray(nextelement))))) {
    +      if ((forwardelement) && ((SwigType_isfunction(forwardelement) || (SwigType_isarray(forwardelement))))) {
     	Insert(result, 0, "(");
     	Append(result, ")");
           }
    
    From c4e280024fb1ed9881312dc997f36f6f3563f697 Mon Sep 17 00:00:00 2001
    From: William S Fulton 
    Date: Sat, 9 Sep 2017 23:46:14 +0100
    Subject: [PATCH 272/455] Add support for %typemap and member function pointers
     with qualifiers
    
    ---
     Examples/test-suite/common.mk                 |  1 +
     .../cpp11_ref_qualifiers_typemaps.i           | 74 +++++++++++++++++++
     .../cpp11_ref_qualifiers_typemaps_runme.java  | 39 ++++++++++
     Source/CParse/parser.y                        | 25 ++++++-
     4 files changed, 137 insertions(+), 2 deletions(-)
     create mode 100644 Examples/test-suite/cpp11_ref_qualifiers_typemaps.i
     create mode 100644 Examples/test-suite/java/cpp11_ref_qualifiers_typemaps_runme.java
    
    diff --git a/Examples/test-suite/common.mk b/Examples/test-suite/common.mk
    index 0d0a32c8c..4bd657c13 100644
    --- a/Examples/test-suite/common.mk
    +++ b/Examples/test-suite/common.mk
    @@ -563,6 +563,7 @@ CPP11_TEST_CASES += \
     	cpp11_raw_string_literals \
     	cpp11_ref_qualifiers \
     	cpp11_ref_qualifiers_rvalue_unignore \
    +	cpp11_ref_qualifiers_typemaps \
     	cpp11_result_of \
     	cpp11_rvalue_reference \
     	cpp11_rvalue_reference2 \
    diff --git a/Examples/test-suite/cpp11_ref_qualifiers_typemaps.i b/Examples/test-suite/cpp11_ref_qualifiers_typemaps.i
    new file mode 100644
    index 000000000..e9cce4bfb
    --- /dev/null
    +++ b/Examples/test-suite/cpp11_ref_qualifiers_typemaps.i
    @@ -0,0 +1,74 @@
    +%module cpp11_ref_qualifiers_typemaps
    +
    +%typemap(in) SWIGTYPE (CLASS::*) %{
    +  _this_will_fail_to_compile_if_used_
    +%}
    +
    +// typemaps to completely ignore the input parm and override it
    +%typemap(in) short (Funcs::*ff)(bool) const   %{ $1 = &Funcs::FF2; %}
    +%typemap(in) short (Funcs::*cc)(bool) &       %{ $1 = &Funcs::CC5; %}
    +%typemap(in) short (Funcs::*gg)(bool) const & %{ $1 = &Funcs::GG8; %}
    +%typemap(in) short (Funcs::*hh)(bool) &&      %{ $1 = &Funcs::HH11; %}
    +
    +%typemap(in) short (Funcs::*)(bool) const   %{ $1 = &Funcs::FF3; %}
    +%typemap(in) short (Funcs::*)(bool) &       %{ $1 = &Funcs::CC6; %}
    +%typemap(in) short (Funcs::*)(bool) const & %{ $1 = &Funcs::GG9; %}
    +%typemap(in) short (Funcs::*)(bool) &&      %{ $1 = &Funcs::HH12; %}
    +
    +%inline %{
    +struct Funcs {
    +  short FF1(bool) const { return 1; }
    +  short FF2(bool) const { return 2; }
    +  short FF3(bool) const { return 3; }
    +  short CC4(bool) & { return 4; }
    +  short CC5(bool) & { return 5; }
    +  short CC6(bool) & { return 6; }
    +  short GG7(bool) const & { return 7; }
    +  short GG8(bool) const & { return 8; }
    +  short GG9(bool) const & { return 9; }
    +  short HH10(bool) && { return 10; }
    +  short HH11(bool) && { return 11; }
    +  short HH12(bool) && { return 12; }
    +};
    +struct TypemapsNamedParms
    +{
    +  short fff(short (Funcs::*ff)(bool) const) {
    +    Funcs funcs;
    +    return (funcs.*ff)(true);
    +  }
    +  short ccc(short (Funcs::*cc)(bool) &) {
    +    Funcs funcs;
    +    return (funcs.*cc)(true);
    +  }
    +  short ggg(short (Funcs::*gg)(bool) const &) {
    +    Funcs funcs;
    +    return (funcs.*gg)(true);
    +  }
    +  short hhh(short (Funcs::*hh)(bool) &&) {
    +    return (Funcs().*hh)(true);
    +  }
    +};
    +struct TypemapsUnnamedParms
    +{
    +  short fff(short (Funcs::*f)(bool) const) {
    +    Funcs funcs;
    +    return (funcs.*f)(true);
    +  }
    +  short ccc(short (Funcs::*c)(bool) &) {
    +    Funcs funcs;
    +    return (funcs.*c)(true);
    +  }
    +  short ggg(short (Funcs::*g)(bool) const &) {
    +    Funcs funcs;
    +    return (funcs.*g)(true);
    +  }
    +  short hhh(short (Funcs::*h)(bool) &&) {
    +    return (Funcs().*h)(true);
    +  }
    +};
    +%}
    +
    +%constant short (Funcs::*FF1_MFP)(bool) const = &Funcs::FF1;
    +%constant short (Funcs::*CC4_MFP)(bool) & = &Funcs::CC4;
    +%constant short (Funcs::*GG7_MFP)(bool) const & = &Funcs::GG7;
    +%constant short (Funcs::*HH10_MFP)(bool) && = &Funcs::HH10;
    diff --git a/Examples/test-suite/java/cpp11_ref_qualifiers_typemaps_runme.java b/Examples/test-suite/java/cpp11_ref_qualifiers_typemaps_runme.java
    new file mode 100644
    index 000000000..8c6a21b15
    --- /dev/null
    +++ b/Examples/test-suite/java/cpp11_ref_qualifiers_typemaps_runme.java
    @@ -0,0 +1,39 @@
    +import cpp11_ref_qualifiers_typemaps.*;
    +
    +public class cpp11_ref_qualifiers_typemaps_runme {
    +  static {
    +    try {
    +      System.loadLibrary("cpp11_ref_qualifiers_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[]) 
    +  {
    +    {
    +      TypemapsNamedParms tm = new TypemapsNamedParms();
    +      if (tm.fff(cpp11_ref_qualifiers_typemaps.FF1_MFP) != 2)
    +        throw new RuntimeException("failed");
    +      if (tm.ccc(cpp11_ref_qualifiers_typemaps.CC4_MFP) != 5)
    +        throw new RuntimeException("failed");
    +      if (tm.ggg(cpp11_ref_qualifiers_typemaps.GG7_MFP) != 8)
    +        throw new RuntimeException("failed");
    +      if (tm.hhh(cpp11_ref_qualifiers_typemaps.HH10_MFP) != 11)
    +        throw new RuntimeException("failed");
    +    }
    +    {
    +      TypemapsUnnamedParms tm = new TypemapsUnnamedParms();
    +      if (tm.fff(cpp11_ref_qualifiers_typemaps.FF1_MFP) != 3)
    +        throw new RuntimeException("failed");
    +      if (tm.ccc(cpp11_ref_qualifiers_typemaps.CC4_MFP) != 6)
    +        throw new RuntimeException("failed");
    +      if (tm.ggg(cpp11_ref_qualifiers_typemaps.GG7_MFP) != 9)
    +        throw new RuntimeException("failed");
    +      if (tm.hhh(cpp11_ref_qualifiers_typemaps.HH10_MFP) != 12)
    +        throw new RuntimeException("failed");
    +    }
    +  }
    +}
    +
    diff --git a/Source/CParse/parser.y b/Source/CParse/parser.y
    index 9cf6f00c6..2e92cd01b 100644
    --- a/Source/CParse/parser.y
    +++ b/Source/CParse/parser.y
    @@ -1895,7 +1895,7 @@ constant_directive :  CONSTANT identifier EQUAL definetype SEMI {
     		   $$ = 0;
     		 }
                    }
    -	       /* Member const function pointers . eg.
    +	       /* Member function pointers with qualifiers. eg.
     	         %constant short (Funcs::*pmf)(bool) const = &Funcs::F; */
     	       | CONSTANT type direct_declarator LPAREN parms RPAREN cv_ref_qualifier def_args SEMI {
     		 if (($8.type != T_ERROR) && ($8.type != T_SYMBOL)) {
    @@ -5116,7 +5116,7 @@ parameter_declarator : declarator def_args {
                   $$.id = 0;
     	      $$.defarg = $1.rawval ? $1.rawval : $1.val;
                 }
    -	    /* Member const function pointer parameters. eg.
    +	    /* Member function pointers with qualifiers. eg.
     	      int f(short (Funcs::*parm)(bool) const); */
     	    | direct_declarator LPAREN parms RPAREN cv_ref_qualifier {
     	      SwigType *t;
    @@ -5174,6 +5174,27 @@ plain_declarator : declarator {
     		$$.parms = 0;
     	      }
                 }
    +	    /* Member function pointers with qualifiers. eg.
    +	      int f(short (Funcs::*parm)(bool) const) */
    +	    | direct_declarator LPAREN parms RPAREN cv_ref_qualifier {
    +	      SwigType *t;
    +	      $$ = $1;
    +	      t = NewStringEmpty();
    +	      SwigType_add_function(t, $3);
    +	      if ($5.qualifier)
    +	        SwigType_push(t, $5.qualifier);
    +	      if (!$$.have_parms) {
    +		$$.parms = $3;
    +		$$.have_parms = 1;
    +	      }
    +	      if (!$$.type) {
    +		$$.type = t;
    +	      } else {
    +		SwigType_push(t, $$.type);
    +		Delete($$.type);
    +		$$.type = t;
    +	      }
    +	    }
                 | empty {
        	      $$.type = 0;
                   $$.id = 0;
    
    From f38e525a24fbaff57357c026824bc2c89ab98376 Mon Sep 17 00:00:00 2001
    From: William S Fulton 
    Date: Sun, 10 Sep 2017 12:49:24 +0100
    Subject: [PATCH 273/455] Warnings in testcases fix
    
    ---
     Examples/test-suite/cpp11_ref_qualifiers.i   | 2 ++
     Examples/test-suite/template_empty_inherit.i | 1 +
     2 files changed, 3 insertions(+)
    
    diff --git a/Examples/test-suite/cpp11_ref_qualifiers.i b/Examples/test-suite/cpp11_ref_qualifiers.i
    index 237234e9c..e37136770 100644
    --- a/Examples/test-suite/cpp11_ref_qualifiers.i
    +++ b/Examples/test-suite/cpp11_ref_qualifiers.i
    @@ -90,9 +90,11 @@ struct Renames {
     struct ConversionOperators {
       virtual operator string() & { return string(); }
       virtual operator string() && { return std::move(string()); }
    +  virtual ~ConversionOperators() {}
     };
     struct ConversionOperators2 {
       virtual operator string() && { return std::move(string()); }
    +  virtual ~ConversionOperators2() {}
     };
     %}
     
    diff --git a/Examples/test-suite/template_empty_inherit.i b/Examples/test-suite/template_empty_inherit.i
    index 308a01fda..5677b8b1a 100644
    --- a/Examples/test-suite/template_empty_inherit.i
    +++ b/Examples/test-suite/template_empty_inherit.i
    @@ -5,6 +5,7 @@
     %inline %{
     template struct Functor {
       virtual Result operator()(Arg x) const = 0;
    +  virtual ~Functor() {}
     };
     %}
     
    
    From 0646db73c354de147ad01888a4db55d7f9c3877a Mon Sep 17 00:00:00 2001
    From: William S Fulton 
    Date: Sun, 10 Sep 2017 17:20:35 +0100
    Subject: [PATCH 274/455] Add _DEBUG set to 1 change into changes files
    
    ---
     CHANGES.current | 4 ++++
     1 file changed, 4 insertions(+)
    
    diff --git a/CHANGES.current b/CHANGES.current
    index 0629dfbb6..8e77d5bc0 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.0.0 (in progress)
     ===========================
     
    +2017-09-10: mlamarre
    +            [Python] Patch #1083. Define_DEBUG to 1 to do exactly like Visual Studio
    +            /LDd, /MDd or /MTd compiler options.
    +
     2017-08-16: wsfulton
                 Fix #1063. Add using declarations to templates into typedef table.
     
    
    From f18b45e677f90eef406152675b6abeae12567010 Mon Sep 17 00:00:00 2001
    From: William S Fulton 
    Date: Mon, 11 Sep 2017 08:16:57 +0100
    Subject: [PATCH 275/455] Travis workaround fix for pip install pep8 install
     fail
    
    Example failure:
    https://travis-ci.org/swig/swig/jobs/273885223#L557
    
    Error:
    IOError: [Errno 13] Permission denied: '/usr/local/lib/python2.7/dist-packages/pep8.pyc'
    ---
     .travis.yml | 1 +
     1 file changed, 1 insertion(+)
    
    diff --git a/.travis.yml b/.travis.yml
    index e2a47e6f1..99316f436 100644
    --- a/.travis.yml
    +++ b/.travis.yml
    @@ -1,4 +1,5 @@
     language: cpp
    +group: deprecated-2017Q3 # workaround for failing: pip install pep8
     matrix:
       include:
         - compiler: clang
    
    From d8556b011981e070d67acb1d68563cdc3ab9a00d Mon Sep 17 00:00:00 2001
    From: William S Fulton 
    Date: Mon, 11 Sep 2017 08:21:55 +0100
    Subject: [PATCH 276/455] Remove node testing from Travis
    
    Travis is now testing on Ubuntu Trusty by default instead of Ubuntu
    Precise. SWIG wrappers need some work for this environment.
    Travis build failure: https://travis-ci.org/swig/swig/jobs/273885208
    Issue #971
    ---
     .travis.yml | 6 +++---
     1 file changed, 3 insertions(+), 3 deletions(-)
    
    diff --git a/.travis.yml b/.travis.yml
    index 99316f436..5dc3ce44a 100644
    --- a/.travis.yml
    +++ b/.travis.yml
    @@ -53,9 +53,9 @@ matrix:
           env: SWIGLANG=java
           sudo: required
           dist: trusty
    -    - compiler: gcc
    -      os: linux
    -      env: SWIGLANG=javascript ENGINE=node
    +#    - compiler: gcc
    +#      os: linux
    +#      env: SWIGLANG=javascript ENGINE=node
         - compiler: gcc
           os: linux
           env: SWIGLANG=javascript ENGINE=jsc
    
    From 64bc67f57e47ec59fd13ecb97d3615f8fff70fe5 Mon Sep 17 00:00:00 2001
    From: William S Fulton 
    Date: Mon, 11 Sep 2017 08:27:18 +0100
    Subject: [PATCH 277/455] Remove all Ubuntu Precise testing on Travis
    
    This is going end of life on Travis.
    ---
     .travis.yml | 4 +---
     1 file changed, 1 insertion(+), 3 deletions(-)
    
    diff --git a/.travis.yml b/.travis.yml
    index 5dc3ce44a..05681a110 100644
    --- a/.travis.yml
    +++ b/.travis.yml
    @@ -7,9 +7,6 @@ matrix:
           env: SWIGLANG=
           sudo: required
           dist: trusty
    -    - compiler: gcc
    -      os: linux
    -      env: SWIGLANG=
         - compiler: gcc
           os: linux
           env: SWIGLANG=
    @@ -56,6 +53,7 @@ matrix:
     #    - compiler: gcc
     #      os: linux
     #      env: SWIGLANG=javascript ENGINE=node
    +#      dist: trusty
         - compiler: gcc
           os: linux
           env: SWIGLANG=javascript ENGINE=jsc
    
    From 0587edd5597e773b700c8f10c42bd0cc00ef39b9 Mon Sep 17 00:00:00 2001
    From: luav 
    Date: Mon, 11 Sep 2017 22:13:19 +0200
    Subject: [PATCH 278/455] Includes inside %inline block documented, see #1068
    
    ---
     Doc/Manual/SWIG.html | 6 +++++-
     1 file changed, 5 insertions(+), 1 deletion(-)
    
    diff --git a/Doc/Manual/SWIG.html b/Doc/Manual/SWIG.html
    index c05ed456c..f0c4837f1 100644
    --- a/Doc/Manual/SWIG.html
    +++ b/Doc/Manual/SWIG.html
    @@ -3293,7 +3293,6 @@ Vector *new_Vector() {
       return (Vector *) malloc(sizeof(Vector));
     }
     %}
    -
     

    @@ -3305,6 +3304,11 @@ declaration. Since the code inside an %inline %{ ... %} block is given to both the C compiler and SWIG, it is illegal to include any SWIG directives inside a %{ ... %} block.

    +

    +Note:Any #include directives are omitted inside the +%inline %{ ... %} block unless the -includeall command line +option is supplied.

    +

    5.6.4 Initialization blocks

    From f069d0a744ef9bf7b3e31a89877977e9153fc959 Mon Sep 17 00:00:00 2001 From: luav Date: Mon, 11 Sep 2017 22:55:13 +0200 Subject: [PATCH 279/455] %shared_ptr usage for the templates documented, see #1049 --- Doc/Manual/Library.html | 43 +++++++++++++++++++++++++++++++++++++++-- Doc/Manual/SWIG.html | 2 +- 2 files changed, 42 insertions(+), 3 deletions(-) diff --git a/Doc/Manual/Library.html b/Doc/Manual/Library.html index f41799bf0..40677cc9f 100644 --- a/Doc/Manual/Library.html +++ b/Doc/Manual/Library.html @@ -1728,6 +1728,10 @@ Any thrown STL exceptions will then be gracefully handled instead of causing a c

    9.4.4 shared_ptr smart pointer

    +

    +%shared_ptr Basics +

    +

    Some target languages have support for handling the shared_ptr reference counted smart pointer. This smart pointer is available in the standard C++11 library as std::shared_ptr. @@ -1822,7 +1826,11 @@ System.out.println(val1 + " " + val2);

    -This shared_ptr library works quite differently to SWIG's normal, but somewhat limited, +%shared_ptr and Inheritance +

    + +

    +The shared_ptr library works quite differently to SWIG's normal, but somewhat limited, smart pointer handling. The shared_ptr library does not generate extra wrappers, just for smart pointer handling, in addition to the proxy class. The normal proxy class including inheritance relationships is generated as usual. @@ -1900,7 +1908,7 @@ Adding the missing %shared_ptr macros will fix this:

    -%include "boost_shared_ptr.i"
    +%include <boost_shared_ptr.i>
     %shared_ptr(GrandParent);
     %shared_ptr(Parent);
     %shared_ptr(Child);
    @@ -1909,6 +1917,37 @@ Adding the missing %shared_ptr macros will fix this:
     
    +

    +%shared_ptr and Templates +

    + +

    +Only the single %shared_ptr declaration should be used for all specializations +of the template before the first template instantiation using the following notation: +%shared_ptr(TemplateName<>). For example: +

    + +
    +
    +%include <std_shared_ptr.i>
    +
    +%shared_ptr(Graph<>);  //!< Declaration of the transparent shared ptr for the Graph template
    +
    +%{
    +  #include "graph.hpp"  // Graph definition (inside the namespace gany)
    +  using namespace gany;
    +%}
    +
    +%include "graph.h"  // Graph declaration (inside the namespace gany)
    +using namespace gany;
    +
    +%template(SGraph) Graph<false>;  //!< Simple graph 
    +// Note: the Graph name is redefined in the following line from the template to the specialization (class)
    +%template(Graph) Graph<true>;  //!< Weighted graph
    +
    +
    + +

    Note: There is somewhat limited support for %shared_ptr and the director feature and the degrees of success varies among the different target languages. diff --git a/Doc/Manual/SWIG.html b/Doc/Manual/SWIG.html index f0c4837f1..965fae11c 100644 --- a/Doc/Manual/SWIG.html +++ b/Doc/Manual/SWIG.html @@ -3305,7 +3305,7 @@ is given to both the C compiler and SWIG, it is illegal to include any SWIG directives inside a %{ ... %} block.

    -Note:Any #include directives are omitted inside the +Note: Any #include directives are omitted inside the %inline %{ ... %} block unless the -includeall command line option is supplied.

    From 0c0384198a747748ba58c2dda43b0b425b54009b Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Mon, 11 Sep 2017 23:17:30 +0100 Subject: [PATCH 280/455] Fix testcase symbol name conflict FF1 is also defined in /usr/include/sys/termio.h on cygwin and used by Python.h. --- .../cpp11_ref_qualifiers_typemaps.i | 48 +++++++++---------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/Examples/test-suite/cpp11_ref_qualifiers_typemaps.i b/Examples/test-suite/cpp11_ref_qualifiers_typemaps.i index e9cce4bfb..0e1c3fe53 100644 --- a/Examples/test-suite/cpp11_ref_qualifiers_typemaps.i +++ b/Examples/test-suite/cpp11_ref_qualifiers_typemaps.i @@ -5,30 +5,30 @@ %} // typemaps to completely ignore the input parm and override it -%typemap(in) short (Funcs::*ff)(bool) const %{ $1 = &Funcs::FF2; %} -%typemap(in) short (Funcs::*cc)(bool) & %{ $1 = &Funcs::CC5; %} -%typemap(in) short (Funcs::*gg)(bool) const & %{ $1 = &Funcs::GG8; %} -%typemap(in) short (Funcs::*hh)(bool) && %{ $1 = &Funcs::HH11; %} +%typemap(in) short (Funcs::*ff)(bool) const %{ $1 = &Funcs::FFF2; %} +%typemap(in) short (Funcs::*cc)(bool) & %{ $1 = &Funcs::CCC5; %} +%typemap(in) short (Funcs::*gg)(bool) const & %{ $1 = &Funcs::GGG8; %} +%typemap(in) short (Funcs::*hh)(bool) && %{ $1 = &Funcs::HHH11; %} -%typemap(in) short (Funcs::*)(bool) const %{ $1 = &Funcs::FF3; %} -%typemap(in) short (Funcs::*)(bool) & %{ $1 = &Funcs::CC6; %} -%typemap(in) short (Funcs::*)(bool) const & %{ $1 = &Funcs::GG9; %} -%typemap(in) short (Funcs::*)(bool) && %{ $1 = &Funcs::HH12; %} +%typemap(in) short (Funcs::*)(bool) const %{ $1 = &Funcs::FFF3; %} +%typemap(in) short (Funcs::*)(bool) & %{ $1 = &Funcs::CCC6; %} +%typemap(in) short (Funcs::*)(bool) const & %{ $1 = &Funcs::GGG9; %} +%typemap(in) short (Funcs::*)(bool) && %{ $1 = &Funcs::HHH12; %} %inline %{ struct Funcs { - short FF1(bool) const { return 1; } - short FF2(bool) const { return 2; } - short FF3(bool) const { return 3; } - short CC4(bool) & { return 4; } - short CC5(bool) & { return 5; } - short CC6(bool) & { return 6; } - short GG7(bool) const & { return 7; } - short GG8(bool) const & { return 8; } - short GG9(bool) const & { return 9; } - short HH10(bool) && { return 10; } - short HH11(bool) && { return 11; } - short HH12(bool) && { return 12; } + short FFF1(bool) const { return 1; } + short FFF2(bool) const { return 2; } + short FFF3(bool) const { return 3; } + short CCC4(bool) & { return 4; } + short CCC5(bool) & { return 5; } + short CCC6(bool) & { return 6; } + short GGG7(bool) const & { return 7; } + short GGG8(bool) const & { return 8; } + short GGG9(bool) const & { return 9; } + short HHH10(bool) && { return 10; } + short HHH11(bool) && { return 11; } + short HHH12(bool) && { return 12; } }; struct TypemapsNamedParms { @@ -68,7 +68,7 @@ struct TypemapsUnnamedParms }; %} -%constant short (Funcs::*FF1_MFP)(bool) const = &Funcs::FF1; -%constant short (Funcs::*CC4_MFP)(bool) & = &Funcs::CC4; -%constant short (Funcs::*GG7_MFP)(bool) const & = &Funcs::GG7; -%constant short (Funcs::*HH10_MFP)(bool) && = &Funcs::HH10; +%constant short (Funcs::*FF1_MFP)(bool) const = &Funcs::FFF1; +%constant short (Funcs::*CC4_MFP)(bool) & = &Funcs::CCC4; +%constant short (Funcs::*GG7_MFP)(bool) const & = &Funcs::GGG7; +%constant short (Funcs::*HH10_MFP)(bool) && = &Funcs::HHH10; From 6077b808f737c1d05df158e31ce50f9189bf9506 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Mon, 11 Sep 2017 23:18:55 +0100 Subject: [PATCH 281/455] Remove code duplication of Swig_overload_rank Allegrocl and R versions were also out of date --- Source/Modules/allegrocl.cxx | 279 ----------------------------------- Source/Modules/r.cxx | 256 -------------------------------- 2 files changed, 535 deletions(-) diff --git a/Source/Modules/allegrocl.cxx b/Source/Modules/allegrocl.cxx index 77f1319c7..f32d34976 100644 --- a/Source/Modules/allegrocl.cxx +++ b/Source/Modules/allegrocl.cxx @@ -1685,285 +1685,6 @@ int ALLEGROCL::top(Node *n) { return SWIG_OK; } -/* very shamelessly 'borrowed' from overload.cxx, which - keeps the below Swig_overload_rank() code to itself. - We don't need a dispatch function in the C++ wrapper - code; we want it over on the lisp side. */ - -#define Swig_overload_rank Allegrocl_swig_overload_rank - -#define MAX_OVERLOAD 256 - -/* Overload "argc" and "argv" */ -// String *argv_template_string; -// String *argc_template_string; - -struct Overloaded { - Node *n; /* Node */ - int argc; /* Argument count */ - ParmList *parms; /* Parameters used for overload check */ - int error; /* Ambiguity error */ -}; - -/* ----------------------------------------------------------------------------- - * Swig_overload_rank() - * - * This function takes an overloaded declaration and creates a list that ranks - * all overloaded methods in an order that can be used to generate a dispatch - * function. - * Slight difference in the way this function is used by scripting languages and - * statically typed languages. The script languages call this method via - * Swig_overload_dispatch() - where wrappers for all overloaded methods are generated, - * however sometimes the code can never be executed. The non-scripting languages - * call this method via Swig_overload_check() for each overloaded method in order - * to determine whether or not the method should be wrapped. Note the slight - * difference when overloading methods that differ by const only. The - * scripting languages will ignore the const method, whereas the non-scripting - * languages ignore the first method parsed. - * ----------------------------------------------------------------------------- */ - -static List *Swig_overload_rank(Node *n, bool script_lang_wrapping) { - Overloaded nodes[MAX_OVERLOAD]; - int nnodes = 0; - Node *o = Getattr(n, "sym:overloaded"); - Node *c; - - if (!o) - return 0; - - c = o; - while (c) { - if (Getattr(c, "error")) { - c = Getattr(c, "sym:nextSibling"); - continue; - } - /* if (SmartPointer && Getattr(c,"cplus:staticbase")) { - c = Getattr(c,"sym:nextSibling"); - continue; - } */ - - /* Make a list of all the declarations (methods) that are overloaded with - * this one particular method name */ - if (Getattr(c, "wrap:name")) { - nodes[nnodes].n = c; - nodes[nnodes].parms = Getattr(c, "wrap:parms"); - nodes[nnodes].argc = emit_num_required(nodes[nnodes].parms); - nodes[nnodes].error = 0; - nnodes++; - } - c = Getattr(c, "sym:nextSibling"); - } - - /* Sort the declarations by required argument count */ - { - int i, j; - for (i = 0; i < nnodes; i++) { - for (j = i + 1; j < nnodes; j++) { - if (nodes[i].argc > nodes[j].argc) { - Overloaded t = nodes[i]; - nodes[i] = nodes[j]; - nodes[j] = t; - } - } - } - } - - /* Sort the declarations by argument types */ - { - int i, j; - for (i = 0; i < nnodes - 1; i++) { - if (nodes[i].argc == nodes[i + 1].argc) { - for (j = i + 1; (j < nnodes) && (nodes[j].argc == nodes[i].argc); j++) { - Parm *p1 = nodes[i].parms; - Parm *p2 = nodes[j].parms; - int differ = 0; - int num_checked = 0; - while (p1 && p2 && (num_checked < nodes[i].argc)) { - // Printf(stdout,"p1 = '%s', p2 = '%s'\n", Getattr(p1,"type"), Getattr(p2,"type")); - if (checkAttribute(p1, "tmap:in:numinputs", "0")) { - p1 = Getattr(p1, "tmap:in:next"); - continue; - } - if (checkAttribute(p2, "tmap:in:numinputs", "0")) { - p2 = Getattr(p2, "tmap:in:next"); - continue; - } - String *t1 = Getattr(p1, "tmap:typecheck:precedence"); - String *t2 = Getattr(p2, "tmap:typecheck:precedence"); - if ((!t1) && (!nodes[i].error)) { - Swig_warning(WARN_TYPEMAP_TYPECHECK, Getfile(nodes[i].n), Getline(nodes[i].n), - "Overloaded method %s not supported (incomplete type checking rule - no precedence level in typecheck typemap for '%s').\n", - Swig_name_decl(nodes[i].n), SwigType_str(Getattr(p1, "type"), 0)); - nodes[i].error = 1; - } else if ((!t2) && (!nodes[j].error)) { - Swig_warning(WARN_TYPEMAP_TYPECHECK, Getfile(nodes[j].n), Getline(nodes[j].n), - "Overloaded method %s not supported (incomplete type checking rule - no precedence level in typecheck typemap for '%s').\n", - Swig_name_decl(nodes[j].n), SwigType_str(Getattr(p2, "type"), 0)); - nodes[j].error = 1; - } - if (t1 && t2) { - int t1v, t2v; - t1v = atoi(Char(t1)); - t2v = atoi(Char(t2)); - differ = t1v - t2v; - } else if (!t1 && t2) - differ = 1; - else if (t1 && !t2) - differ = -1; - else if (!t1 && !t2) - differ = -1; - num_checked++; - if (differ > 0) { - Overloaded t = nodes[i]; - nodes[i] = nodes[j]; - nodes[j] = t; - break; - } else if ((differ == 0) && (Strcmp(t1, "0") == 0)) { - t1 = Getattr(p1, "ltype"); - if (!t1) { - t1 = SwigType_ltype(Getattr(p1, "type")); - if (Getattr(p1, "tmap:typecheck:SWIGTYPE")) { - SwigType_add_pointer(t1); - } - Setattr(p1, "ltype", t1); - } - t2 = Getattr(p2, "ltype"); - if (!t2) { - t2 = SwigType_ltype(Getattr(p2, "type")); - if (Getattr(p2, "tmap:typecheck:SWIGTYPE")) { - SwigType_add_pointer(t2); - } - Setattr(p2, "ltype", t2); - } - - /* Need subtype check here. If t2 is a subtype of t1, then we need to change the - order */ - - if (SwigType_issubtype(t2, t1)) { - Overloaded t = nodes[i]; - nodes[i] = nodes[j]; - nodes[j] = t; - } - - if (Strcmp(t1, t2) != 0) { - differ = 1; - break; - } - } else if (differ) { - break; - } - if (Getattr(p1, "tmap:in:next")) { - p1 = Getattr(p1, "tmap:in:next"); - } else { - p1 = nextSibling(p1); - } - if (Getattr(p2, "tmap:in:next")) { - p2 = Getattr(p2, "tmap:in:next"); - } else { - p2 = nextSibling(p2); - } - } - if (!differ) { - /* See if declarations differ by const only */ - String *d1 = Getattr(nodes[i].n, "decl"); - String *d2 = Getattr(nodes[j].n, "decl"); - if (d1 && d2) { - String *dq1 = Copy(d1); - String *dq2 = Copy(d2); - if (SwigType_isconst(d1)) { - Delete(SwigType_pop(dq1)); - } - if (SwigType_isconst(d2)) { - Delete(SwigType_pop(dq2)); - } - if (Strcmp(dq1, dq2) == 0) { - - if (SwigType_isconst(d1) && !SwigType_isconst(d2)) { - if (script_lang_wrapping) { - // Swap nodes so that the const method gets ignored (shadowed by the non-const method) - Overloaded t = nodes[i]; - nodes[i] = nodes[j]; - nodes[j] = t; - } - differ = 1; - if (!nodes[j].error) { - if (script_lang_wrapping) { - Swig_warning(WARN_LANG_OVERLOAD_CONST, Getfile(nodes[j].n), Getline(nodes[j].n), - "Overloaded method %s ignored,\n", Swig_name_decl(nodes[j].n)); - Swig_warning(WARN_LANG_OVERLOAD_CONST, Getfile(nodes[i].n), Getline(nodes[i].n), - "using non-const method %s instead.\n", Swig_name_decl(nodes[i].n)); - } else { - if (!Getattr(nodes[j].n, "overload:ignore")) { - Swig_warning(WARN_LANG_OVERLOAD_IGNORED, Getfile(nodes[j].n), Getline(nodes[j].n), - "Overloaded method %s ignored,\n", Swig_name_decl(nodes[j].n)); - Swig_warning(WARN_LANG_OVERLOAD_IGNORED, Getfile(nodes[i].n), Getline(nodes[i].n), - "using %s instead.\n", Swig_name_decl(nodes[i].n)); - } - } - } - nodes[j].error = 1; - } else if (!SwigType_isconst(d1) && SwigType_isconst(d2)) { - differ = 1; - if (!nodes[j].error) { - if (script_lang_wrapping) { - Swig_warning(WARN_LANG_OVERLOAD_CONST, Getfile(nodes[j].n), Getline(nodes[j].n), - "Overloaded method %s ignored,\n", Swig_name_decl(nodes[j].n)); - Swig_warning(WARN_LANG_OVERLOAD_CONST, Getfile(nodes[i].n), Getline(nodes[i].n), - "using non-const method %s instead.\n", Swig_name_decl(nodes[i].n)); - } else { - if (!Getattr(nodes[j].n, "overload:ignore")) { - Swig_warning(WARN_LANG_OVERLOAD_IGNORED, Getfile(nodes[j].n), Getline(nodes[j].n), - "Overloaded method %s ignored,\n", Swig_name_decl(nodes[j].n)); - Swig_warning(WARN_LANG_OVERLOAD_IGNORED, Getfile(nodes[i].n), Getline(nodes[i].n), - "using %s instead.\n", Swig_name_decl(nodes[i].n)); - } - } - } - nodes[j].error = 1; - } - } - Delete(dq1); - Delete(dq2); - } - } - if (!differ) { - if (!nodes[j].error) { - if (script_lang_wrapping) { - Swig_warning(WARN_LANG_OVERLOAD_SHADOW, Getfile(nodes[j].n), Getline(nodes[j].n), - "Overloaded method %s effectively ignored,\n", Swig_name_decl(nodes[j].n)); - Swig_warning(WARN_LANG_OVERLOAD_SHADOW, Getfile(nodes[i].n), Getline(nodes[i].n), - "as it is shadowed by %s.\n", Swig_name_decl(nodes[i].n)); - } else { - if (!Getattr(nodes[j].n, "overload:ignore")) { - Swig_warning(WARN_LANG_OVERLOAD_IGNORED, Getfile(nodes[j].n), Getline(nodes[j].n), - "Overloaded method %s ignored,\n", Swig_name_decl(nodes[j].n)); - Swig_warning(WARN_LANG_OVERLOAD_IGNORED, Getfile(nodes[i].n), Getline(nodes[i].n), - "using %s instead.\n", Swig_name_decl(nodes[i].n)); - } - } - nodes[j].error = 1; - } - } - } - } - } - } - List *result = NewList(); - { - int i; - for (i = 0; i < nnodes; i++) { - 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; -} - -/* end shameless borrowing */ - int any_varargs(ParmList *pl) { Parm *p; diff --git a/Source/Modules/r.cxx b/Source/Modules/r.cxx index 6a326206f..db94ec934 100644 --- a/Source/Modules/r.cxx +++ b/Source/Modules/r.cxx @@ -290,8 +290,6 @@ public: int membervariableHandler(Node *n); int typedefHandler(Node *n); - static List *Swig_overload_rank(Node *n, - bool script_lang_wrapping); int memberfunctionHandler(Node *n) { if (debugMode) @@ -1314,260 +1312,6 @@ void R::addAccessor(String *memberName, Wrapper *wrapper, String *name, Printf(stdout, "Adding accessor: %s (%s) => %s\n", memberName, name, tmp); } -#define MAX_OVERLOAD 256 - -struct Overloaded { - Node *n; /* Node */ - int argc; /* Argument count */ - ParmList *parms; /* Parameters used for overload check */ - int error; /* Ambiguity error */ -}; - - -List * R::Swig_overload_rank(Node *n, - bool script_lang_wrapping) { - Overloaded nodes[MAX_OVERLOAD]; - int nnodes = 0; - Node *o = Getattr(n,"sym:overloaded"); - - - if (!o) return 0; - - Node *c = o; - while (c) { - if (Getattr(c,"error")) { - c = Getattr(c,"sym:nextSibling"); - continue; - } - /* if (SmartPointer && Getattr(c,"cplus:staticbase")) { - c = Getattr(c,"sym:nextSibling"); - continue; - } */ - - /* Make a list of all the declarations (methods) that are overloaded with - * this one particular method name */ - - if (Getattr(c,"wrap:name")) { - nodes[nnodes].n = c; - nodes[nnodes].parms = Getattr(c,"wrap:parms"); - nodes[nnodes].argc = emit_num_required(nodes[nnodes].parms); - nodes[nnodes].error = 0; - nnodes++; - } - c = Getattr(c,"sym:nextSibling"); - } - - /* Sort the declarations by required argument count */ - { - int i,j; - for (i = 0; i < nnodes; i++) { - for (j = i+1; j < nnodes; j++) { - if (nodes[i].argc > nodes[j].argc) { - Overloaded t = nodes[i]; - nodes[i] = nodes[j]; - nodes[j] = t; - } - } - } - } - - /* Sort the declarations by argument types */ - { - int i,j; - for (i = 0; i < nnodes-1; i++) { - if (nodes[i].argc == nodes[i+1].argc) { - for (j = i+1; (j < nnodes) && (nodes[j].argc == nodes[i].argc); j++) { - Parm *p1 = nodes[i].parms; - Parm *p2 = nodes[j].parms; - int differ = 0; - int num_checked = 0; - while (p1 && p2 && (num_checked < nodes[i].argc)) { - if (debugMode) { - Printf(stdout,"p1 = '%s', p2 = '%s'\n", Getattr(p1,"type"), Getattr(p2,"type")); - } - if (checkAttribute(p1,"tmap:in:numinputs","0")) { - p1 = Getattr(p1,"tmap:in:next"); - continue; - } - if (checkAttribute(p2,"tmap:in:numinputs","0")) { - p2 = Getattr(p2,"tmap:in:next"); - continue; - } - String *t1 = Getattr(p1,"tmap:typecheck:precedence"); - String *t2 = Getattr(p2,"tmap:typecheck:precedence"); - if (debugMode) { - Printf(stdout,"t1 = '%s', t2 = '%s'\n", t1, t2); - } - if ((!t1) && (!nodes[i].error)) { - Swig_warning(WARN_TYPEMAP_TYPECHECK, Getfile(nodes[i].n), Getline(nodes[i].n), - "Overloaded method %s not supported (incomplete type checking rule - no precedence level in typecheck typemap for '%s').\n", - Swig_name_decl(nodes[i].n), SwigType_str(Getattr(p1, "type"), 0)); - nodes[i].error = 1; - } else if ((!t2) && (!nodes[j].error)) { - Swig_warning(WARN_TYPEMAP_TYPECHECK, Getfile(nodes[j].n), Getline(nodes[j].n), - "Overloaded method %s not supported (incomplete type checking rule - no precedence level in typecheck typemap for '%s').\n", - Swig_name_decl(nodes[j].n), SwigType_str(Getattr(p2, "type"), 0)); - nodes[j].error = 1; - } - if (t1 && t2) { - int t1v, t2v; - t1v = atoi(Char(t1)); - t2v = atoi(Char(t2)); - differ = t1v-t2v; - } - else if (!t1 && t2) differ = 1; - else if (t1 && !t2) differ = -1; - else if (!t1 && !t2) differ = -1; - num_checked++; - if (differ > 0) { - Overloaded t = nodes[i]; - nodes[i] = nodes[j]; - nodes[j] = t; - break; - } else if ((differ == 0) && (Strcmp(t1,"0") == 0)) { - t1 = Getattr(p1,"ltype"); - if (!t1) { - t1 = SwigType_ltype(Getattr(p1,"type")); - if (Getattr(p1,"tmap:typecheck:SWIGTYPE")) { - SwigType_add_pointer(t1); - } - Setattr(p1,"ltype",t1); - } - t2 = Getattr(p2,"ltype"); - if (!t2) { - t2 = SwigType_ltype(Getattr(p2,"type")); - if (Getattr(p2,"tmap:typecheck:SWIGTYPE")) { - SwigType_add_pointer(t2); - } - Setattr(p2,"ltype",t2); - } - - /* Need subtype check here. If t2 is a subtype of t1, then we need to change the - order */ - - if (SwigType_issubtype(t2,t1)) { - Overloaded t = nodes[i]; - nodes[i] = nodes[j]; - nodes[j] = t; - } - - if (Strcmp(t1,t2) != 0) { - differ = 1; - break; - } - } else if (differ) { - break; - } - if (Getattr(p1,"tmap:in:next")) { - p1 = Getattr(p1,"tmap:in:next"); - } else { - p1 = nextSibling(p1); - } - if (Getattr(p2,"tmap:in:next")) { - p2 = Getattr(p2,"tmap:in:next"); - } else { - p2 = nextSibling(p2); - } - } - if (!differ) { - /* See if declarations differ by const only */ - String *d1 = Getattr(nodes[i].n, "decl"); - String *d2 = Getattr(nodes[j].n, "decl"); - if (d1 && d2) { - String *dq1 = Copy(d1); - String *dq2 = Copy(d2); - if (SwigType_isconst(d1)) { - Delete(SwigType_pop(dq1)); - } - if (SwigType_isconst(d2)) { - Delete(SwigType_pop(dq2)); - } - if (Strcmp(dq1, dq2) == 0) { - - if (SwigType_isconst(d1) && !SwigType_isconst(d2)) { - if (script_lang_wrapping) { - // Swap nodes so that the const method gets ignored (shadowed by the non-const method) - Overloaded t = nodes[i]; - nodes[i] = nodes[j]; - nodes[j] = t; - } - differ = 1; - if (!nodes[j].error) { - if (script_lang_wrapping) { - Swig_warning(WARN_LANG_OVERLOAD_CONST, Getfile(nodes[j].n), Getline(nodes[j].n), - "Overloaded method %s ignored,\n", Swig_name_decl(nodes[j].n)); - Swig_warning(WARN_LANG_OVERLOAD_CONST, Getfile(nodes[i].n), Getline(nodes[i].n), - "using non-const method %s instead.\n", Swig_name_decl(nodes[i].n)); - } else { - if (!Getattr(nodes[j].n, "overload:ignore")) { - Swig_warning(WARN_LANG_OVERLOAD_IGNORED, Getfile(nodes[j].n), Getline(nodes[j].n), - "Overloaded method %s ignored,\n", Swig_name_decl(nodes[j].n)); - Swig_warning(WARN_LANG_OVERLOAD_IGNORED, Getfile(nodes[i].n), Getline(nodes[i].n), - "using %s instead.\n", Swig_name_decl(nodes[i].n)); - } - } - } - nodes[j].error = 1; - } else if (!SwigType_isconst(d1) && SwigType_isconst(d2)) { - differ = 1; - if (!nodes[j].error) { - if (script_lang_wrapping) { - Swig_warning(WARN_LANG_OVERLOAD_CONST, Getfile(nodes[j].n), Getline(nodes[j].n), - "Overloaded method %s ignored,\n", Swig_name_decl(nodes[j].n)); - Swig_warning(WARN_LANG_OVERLOAD_CONST, Getfile(nodes[i].n), Getline(nodes[i].n), - "using non-const method %s instead.\n", Swig_name_decl(nodes[i].n)); - } else { - if (!Getattr(nodes[j].n, "overload:ignore")) { - Swig_warning(WARN_LANG_OVERLOAD_IGNORED, Getfile(nodes[j].n), Getline(nodes[j].n), - "Overloaded method %s ignored,\n", Swig_name_decl(nodes[j].n)); - Swig_warning(WARN_LANG_OVERLOAD_IGNORED, Getfile(nodes[i].n), Getline(nodes[i].n), - "using %s instead.\n", Swig_name_decl(nodes[i].n)); - } - } - } - nodes[j].error = 1; - } - } - Delete(dq1); - Delete(dq2); - } - } - if (!differ) { - if (!nodes[j].error) { - if (script_lang_wrapping) { - Swig_warning(WARN_LANG_OVERLOAD_SHADOW, Getfile(nodes[j].n), Getline(nodes[j].n), - "Overloaded method %s effectively ignored,\n", Swig_name_decl(nodes[j].n)); - Swig_warning(WARN_LANG_OVERLOAD_SHADOW, Getfile(nodes[i].n), Getline(nodes[i].n), - "as it is shadowed by %s.\n", Swig_name_decl(nodes[i].n)); - } else { - if (!Getattr(nodes[j].n, "overload:ignore")) { - Swig_warning(WARN_LANG_OVERLOAD_IGNORED, Getfile(nodes[j].n), Getline(nodes[j].n), - "Overloaded method %s ignored,\n", Swig_name_decl(nodes[j].n)); - Swig_warning(WARN_LANG_OVERLOAD_IGNORED, Getfile(nodes[i].n), Getline(nodes[i].n), - "using %s instead.\n", Swig_name_decl(nodes[i].n)); - } - } - nodes[j].error = 1; - } - } - } - } - } - } - List *result = NewList(); - { - int i; - for (i = 0; i < nnodes; i++) { - 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; -} - void R::dispatchFunction(Node *n) { Wrapper *f = NewWrapper(); String *symname = Getattr(n, "sym:name"); From 73fe0fdc7e72311072235137d498864e15ccf2f2 Mon Sep 17 00:00:00 2001 From: luav Date: Tue, 12 Sep 2017 04:10:30 +0200 Subject: [PATCH 282/455] %rename for functions with default parameters explained, see #1087 --- Doc/Manual/SWIG.html | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/Doc/Manual/SWIG.html b/Doc/Manual/SWIG.html index 965fae11c..304377f29 100644 --- a/Doc/Manual/SWIG.html +++ b/Doc/Manual/SWIG.html @@ -1736,6 +1736,43 @@ already defined in the target scripting language. However, if you are careful about namespaces and your use of modules, you can usually avoid these problems.

    +

    +%rename directive respects function parameters and discriminates default parameters from non-default, +which is essential for some languages including Python. Be careful renaming functions having default parameters: +

    +
    +%rename(toFFVal) to_val(FileFormat, bool bin=false);
    +int to_val(FileFormat flag, bool bin=false)
    +{
    +  return 0;
    +}
    +
    +%rename(toDFVal) to_val(DirFormat, bool bin);
    +int to_val(DirFormat flag, bool bin=false)
    +{
    +  return 0;
    +}
    +
    +%rename(toLFVal) to_val(FolderFormat, bool bin);
    +int to_val(FolderFormat flag, bool bin=false)
    +{
    +  return 0;
    +}
    +
    + +

    +The SWIG generator yields the following warning for the last renaming:
    + +rename.i:36: Warning 509: Overloaded method to_val(FolderFormat) effectively ignored,
    +rename.i:26: Warning 509: as it is shadowed by to_val(DirFormat).
    +
    +The renaming performed for the int to_val(FolderFormat flag, bool bin), +but not for the int to_val(FolderFormat flag), where the second parameter bool bin +is omitted taking the default value false. See details about the default +parameters processing in the Default Arguments section. +

    + +

    Closely related to %rename is the %ignore directive. %ignore instructs SWIG to ignore declarations that match a given identifier. For example: From 065c06159ee51e5babce59b542b75c2467449eef Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Tue, 12 Sep 2017 07:48:25 +0100 Subject: [PATCH 283/455] Travis fix for pip install pep8 Fix for recent Travis image cleanup. Issue https://github.com/travis-ci/travis-ci/issues/8378 --- .travis.yml | 1 - Tools/travis-linux-install.sh | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 05681a110..5cf93628e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,5 +1,4 @@ language: cpp -group: deprecated-2017Q3 # workaround for failing: pip install pep8 matrix: include: - compiler: clang diff --git a/Tools/travis-linux-install.sh b/Tools/travis-linux-install.sh index 43bdb77bc..5e93d995f 100755 --- a/Tools/travis-linux-install.sh +++ b/Tools/travis-linux-install.sh @@ -88,7 +88,7 @@ case "$SWIGLANG" in travis_retry sudo apt-get -qq install php$VER-cli php$VER-dev ;; "python") - pip install pep8 + pip install --user pep8 if [[ "$PY3" ]]; then travis_retry sudo apt-get install -qq python3-dev fi From cac396eb56991651eea8613d773590857d4b3357 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Tue, 12 Sep 2017 08:32:49 +0100 Subject: [PATCH 284/455] Restore node testing on Travis (for Ubuntu Trusty) --- .travis.yml | 9 +++++---- Tools/travis-linux-install.sh | 5 +---- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/.travis.yml b/.travis.yml index 5cf93628e..a82b2bc47 100644 --- a/.travis.yml +++ b/.travis.yml @@ -49,10 +49,11 @@ matrix: env: SWIGLANG=java sudo: required dist: trusty -# - compiler: gcc -# os: linux -# env: SWIGLANG=javascript ENGINE=node -# dist: trusty + - compiler: gcc + os: linux + env: SWIGLANG=javascript ENGINE=node + sudo: required + dist: trusty - compiler: gcc os: linux env: SWIGLANG=javascript ENGINE=jsc diff --git a/Tools/travis-linux-install.sh b/Tools/travis-linux-install.sh index 5e93d995f..4a958dfb8 100755 --- a/Tools/travis-linux-install.sh +++ b/Tools/travis-linux-install.sh @@ -33,10 +33,7 @@ case "$SWIGLANG" in "javascript") case "$ENGINE" in "node") - travis_retry sudo add-apt-repository -y ppa:chris-lea/node.js - travis_retry sudo apt-get -qq update - travis_retry sudo apt-get install -qq nodejs rlwrap - travis_retry sudo npm install -g node-gyp + travis_retry sudo apt-get install -qq nodejs node-gyp ;; "jsc") travis_retry sudo apt-get install -qq libwebkitgtk-dev From b41fdba9ef483969f6641b94a75b14c0f12a5fde Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Tue, 12 Sep 2017 08:36:53 +0100 Subject: [PATCH 285/455] Cosmetic changes for Java std::array wrappers --- Lib/java/std_array.i | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Lib/java/std_array.i b/Lib/java/std_array.i index f75857e21..0944d932f 100644 --- a/Lib/java/std_array.i +++ b/Lib/java/std_array.i @@ -8,13 +8,13 @@ namespace std { template class array { public: - typedef T& reference; - typedef const T& const_reference; typedef size_t size_type; typedef ptrdiff_t difference_type; typedef T value_type; - typedef T* pointer; - typedef const T* const_pointer; + typedef T &reference; + typedef const T &const_reference; + typedef T *pointer; + typedef const T *const_pointer; array(); array(const array& other); size_type size() const; From 8a168795d35c5157474d046cf248118b905cf5ae Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Tue, 12 Sep 2017 08:47:10 +0100 Subject: [PATCH 286/455] Cosmetic formatting fixes in generated code for exception handlers --- Source/Modules/emit.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Modules/emit.cxx b/Source/Modules/emit.cxx index 7c2607fc8..813a30924 100644 --- a/Source/Modules/emit.cxx +++ b/Source/Modules/emit.cxx @@ -454,7 +454,7 @@ String *emit_action(Node *n) { if (catchlist) { int unknown_catch = 0; int has_varargs = 0; - Printf(eaction, "}\n"); + Printf(eaction, "} "); for (Parm *ep = catchlist; ep; ep = nextSibling(ep)) { String *em = Swig_typemap_lookup("throws", ep, "_e", 0); if (em) { From 2fee7c96cc86516671c24e5895619922122a11a8 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Fri, 28 Oct 2016 07:04:33 +0100 Subject: [PATCH 287/455] Remove C casts in PyTypeObject for Python builtin type declarations Choose compile time failures over runtime errors. This change highlighted a problem in the constructor wrappers for tp_init where the kwargs parameter was missing in the generated wrapper function. Leave casts in for 0 initialization. --- Source/Modules/python.cxx | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/Source/Modules/python.cxx b/Source/Modules/python.cxx index 9039f07ca..4e9053395 100644 --- a/Source/Modules/python.cxx +++ b/Source/Modules/python.cxx @@ -177,7 +177,7 @@ static String *getSlot(Node *n = NULL, const char *key = NULL, String *default_s static void printSlot(File *f, String *slotval, const char *slotname, const char *functype = NULL) { String *slotval_override = 0; - if (functype) + if (functype && Strcmp(slotval, "0") == 0) slotval = slotval_override = NewStringf("(%s) %s", functype, slotval); int len = Len(slotval); int fieldwidth = len > 41 ? (len > 61 ? 0 : 61 - len) : 41 - len; @@ -2501,7 +2501,8 @@ public: String *tmp = NewString(""); String *dispatch; - const char *dispatch_code = funpack ? "return %s(self, argc, argv);" : "return %s(self, args);"; + const char *dispatch_code = funpack ? "return %s(self, argc, argv);" : + (builtin_ctor ? "return %s(self, args, NULL);" : "return %s(self, args);"); if (castmode) { dispatch = Swig_overload_dispatch_cast(n, dispatch_code, &maxargs); @@ -2515,7 +2516,8 @@ public: String *symname = Getattr(n, "sym:name"); String *wname = Swig_name_wrapper(symname); - Printv(f->def, linkage, builtin_ctor ? "int " : "PyObject *", wname, "(PyObject *self, PyObject *args) {", NIL); + const char *builtin_kwargs = builtin_ctor ? ", PyObject *SWIGUNUSEDPARM(kwargs)" : ""; + Printv(f->def, linkage, builtin_ctor ? "int " : "PyObject *", wname, "(PyObject *self, PyObject *args", builtin_kwargs, ") {", NIL); Wrapper_add_local(f, "argc", "Py_ssize_t argc"); Printf(tmp, "PyObject *argv[%d] = {0}", maxargs + 1); @@ -2729,9 +2731,10 @@ public: Append(wname, overname); } + const char *builtin_kwargs = builtin_ctor ? ", PyObject *SWIGUNUSEDPARM(kwargs)" : ""; if (!allow_kwargs || overname) { if (!varargs) { - Printv(f->def, linkage, wrap_return, wname, "(PyObject *", self_param, ", PyObject *args) {", NIL); + Printv(f->def, linkage, wrap_return, wname, "(PyObject *", self_param, ", PyObject *args", builtin_kwargs, ") {", NIL); } else { Printv(f->def, linkage, wrap_return, wname, "__varargs__", "(PyObject *", self_param, ", PyObject *args, PyObject *varargs) {", NIL); } @@ -2933,11 +2936,7 @@ public: } Printf(parse_args, "if ((nobjs < %d) || (nobjs > %d)) SWIG_fail;\n", num_required, num_arguments); } else { - if (noargs) { - Printv(f->def, linkage, wrap_return, wname, "(PyObject *", self_param, ", PyObject *args) {", NIL); - } else { - Printv(f->def, linkage, wrap_return, wname, "(PyObject *", self_param, ", PyObject *args) {", NIL); - } + Printv(f->def, linkage, wrap_return, wname, "(PyObject *", self_param, ", PyObject *args", builtin_kwargs, ") {", NIL); if (onearg && !builtin_ctor) { Printf(parse_args, "if (!args) SWIG_fail;\n"); Append(parse_args, "swig_obj[0] = args;\n"); @@ -3241,7 +3240,7 @@ public: // Note: funpack is currently always false for varargs Printv(f->def, linkage, wrap_return, wname, "(PyObject *", self_param, ", Py_ssize_t nobjs, PyObject **swig_obj) {", NIL); } else { - Printv(f->def, linkage, wrap_return, wname, "(PyObject *", self_param, ", PyObject *args) {", NIL); + Printv(f->def, linkage, wrap_return, wname, "(PyObject *", self_param, ", PyObject *args", builtin_kwargs, ") {", NIL); } Wrapper_add_local(f, "resultobj", builtin_ctor ? "int resultobj" : "PyObject *resultobj"); Wrapper_add_local(f, "varargs", "PyObject *varargs"); @@ -3351,7 +3350,7 @@ public: closure_name = Copy(wrapper_name); } if (func_type) { - String *s = NewStringf("(%s) %s", func_type, closure_name); + String *s = NewStringf("%s", closure_name); Delete(closure_name); closure_name = s; } From 169738011c7ee2f12aaf5d5fcbabd18045f5c30b Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Thu, 14 Sep 2017 07:39:16 +0100 Subject: [PATCH 288/455] Update version number to 4.0 in docs --- Doc/Manual/Sections.html | 4 ++-- Doc/Manual/index.html | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Doc/Manual/Sections.html b/Doc/Manual/Sections.html index 739170745..c17f9e84e 100644 --- a/Doc/Manual/Sections.html +++ b/Doc/Manual/Sections.html @@ -1,11 +1,11 @@ -SWIG-3.0 Documentation +SWIG-4.0 Documentation -

    SWIG-3.0 Documentation

    +

    SWIG-4.0 Documentation

    Last update : SWIG-4.0.0 (in progress) diff --git a/Doc/Manual/index.html b/Doc/Manual/index.html index 26cc81ea1..e720e70d0 100644 --- a/Doc/Manual/index.html +++ b/Doc/Manual/index.html @@ -1,11 +1,11 @@ -SWIG-3.0 Documentation +SWIG-4.0 Documentation -

    SWIG-3.0 Documentation

    +

    SWIG-4.0 Documentation

    The SWIG documentation is available in one of the following formats.
      From ff52610dc58bec838d7298a9d9bd45d2770515b5 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Thu, 14 Sep 2017 07:49:06 +0100 Subject: [PATCH 289/455] Move C++ 'Default arguments' section in manual --- Doc/Manual/Contents.html | 2 +- Doc/Manual/SWIGPlus.html | 228 +++++++++++++++++++-------------------- 2 files changed, 115 insertions(+), 115 deletions(-) diff --git a/Doc/Manual/Contents.html b/Doc/Manual/Contents.html index b879eaa04..e3478ae91 100644 --- a/Doc/Manual/Contents.html +++ b/Doc/Manual/Contents.html @@ -228,7 +228,6 @@
    • Static members
    • Member data
    -
  • Default arguments
  • Protection
  • Enums and constants
  • Friends @@ -236,6 +235,7 @@
  • Pass and return by value
  • Inheritance
  • A brief discussion of multiple inheritance, pointers, and type checking +
  • Default arguments
  • Wrapping Overloaded Functions and Methods -
  • Default arguments
  • Protection
  • Enums and constants
  • Friends @@ -39,6 +38,7 @@
  • Pass and return by value
  • Inheritance
  • A brief discussion of multiple inheritance, pointers, and type checking +
  • Default arguments
  • Wrapping Overloaded Functions and Methods
    • Dispatch function generation @@ -1104,113 +1104,7 @@ a few problems related to structure wrapping and some of SWIG's customization features.

      -

      6.7 Default arguments

      - - -

      -SWIG will wrap all types of functions that have default arguments. For example member functions: -

      - -
      -
      -class Foo {
      -public:
      -  void bar(int x, int y = 3, int z = 4);
      -};
      -
      -
      - -

      -SWIG handles default arguments by generating an extra overloaded method for each defaulted argument. -SWIG is effectively handling methods with default arguments as if it was wrapping the equivalent overloaded methods. -Thus for the example above, it is as if we had instead given the following to SWIG: -

      - -
      -
      -class Foo {
      -public:
      -  void bar(int x, int y, int z);
      -  void bar(int x, int y);
      -  void bar(int x);
      -};
      -
      -
      - -

      -The wrappers produced are exactly the same as if the above code was instead fed into SWIG. -Details of this are covered later in the Wrapping Overloaded Functions and Methods section. -This approach allows SWIG to wrap all possible default arguments, but can be verbose. -For example if a method has ten default arguments, then eleven wrapper methods are generated. -

      - -

      -Please see the Features and default arguments -section for more information on using %feature with functions with default arguments. -The Ambiguity resolution and renaming section -also deals with using %rename and %ignore on methods with default arguments. -If you are writing your own typemaps for types used in methods with default arguments, you may also need to write a typecheck typemap. -See the Typemaps and overloading section for details or otherwise -use the compactdefaultargs feature flag as mentioned below. -

      - -

      -Compatibility note: Versions of SWIG prior to SWIG-1.3.23 wrapped default arguments slightly differently. -Instead a single wrapper method was generated and the default values were copied into the C++ wrappers -so that the method being wrapped was then called with all the arguments specified. -If the size of the wrappers are a concern then this approach to wrapping methods with default arguments -can be re-activated by using the compactdefaultargs -feature flag. -

      - -
      -
      -%feature("compactdefaultargs") Foo::bar;
      -class Foo {
      -public:
      -  void bar(int x, int y = 3, int z = 4);
      -};
      -
      -
      - - -

      -This is great for reducing the size of the wrappers, but the caveat is it does not work for the statically typed languages, -such as C# and Java, -which don't have optional arguments in the language, -Another restriction of this feature is that it cannot handle default arguments that are not public. -The following example illustrates this: -

      - -
      -
      -class Foo {
      -private:
      -  static const int spam;
      -public:
      -  void bar(int x, int y = spam);   // Won't work with %feature("compactdefaultargs") -
      -                                   // private default value
      -};
      -
      -
      - -

      -This produces uncompilable wrapper code because default values in C++ are -evaluated in the same scope as the member function whereas SWIG -evaluates them in the scope of a wrapper function (meaning that the -values have to be public). -

      - -

      -The compactdefaultargs feature is automatically turned on when wrapping C code with default arguments. -Some target languages will also automatically turn on this feature -if the keyword arguments feature (kwargs) is specified for either C or C++ functions, and the target language supports kwargs, -the compactdefaultargs feature is also automatically turned on. -Keyword arguments are a language feature of some scripting languages, for example Ruby and Python. -SWIG is unable to support kwargs when wrapping overloaded methods, so the default approach cannot be used. -

      - -

      6.8 Protection

      +

      6.7 Protection

      @@ -1230,7 +1124,7 @@ until you explicitly give a `public:' declaration (This is the same convention used by C++).

      -

      6.9 Enums and constants

      +

      6.8 Enums and constants

      @@ -1260,7 +1154,7 @@ Swig_STOUT = Swig::STOUT Members declared as const are wrapped as read-only members and do not create constants.

      -

      6.10 Friends

      +

      6.9 Friends

      @@ -1321,7 +1215,7 @@ namespace bar { and a wrapper for the method 'blah' will not be generated.

      -

      6.11 References and pointers

      +

      6.10 References and pointers

      @@ -1421,7 +1315,7 @@ templates and the STL. This was first added in SWIG-1.3.12.

      -

      6.12 Pass and return by value

      +

      6.11 Pass and return by value

      @@ -1525,7 +1419,7 @@ classes that don't define a default constructor. It is not used for C++ pointers or references.

      -

      6.13 Inheritance

      +

      6.12 Inheritance

      @@ -1711,7 +1605,7 @@ functions for virtual members that are already defined in a base class.

      -

      6.14 A brief discussion of multiple inheritance, pointers, and type checking

      +

      6.13 A brief discussion of multiple inheritance, pointers, and type checking

      @@ -1843,6 +1737,112 @@ int y = B_function((B *) pB); In practice, the pointer is held as an integral number in the target language proxy class.

      +

      6.14 Default arguments

      + + +

      +SWIG will wrap all types of functions that have default arguments. For example member functions: +

      + +
      +
      +class Foo {
      +public:
      +  void bar(int x, int y = 3, int z = 4);
      +};
      +
      +
      + +

      +SWIG handles default arguments by generating an extra overloaded method for each defaulted argument. +SWIG is effectively handling methods with default arguments as if it was wrapping the equivalent overloaded methods. +Thus for the example above, it is as if we had instead given the following to SWIG: +

      + +
      +
      +class Foo {
      +public:
      +  void bar(int x, int y, int z);
      +  void bar(int x, int y);
      +  void bar(int x);
      +};
      +
      +
      + +

      +The wrappers produced are exactly the same as if the above code was instead fed into SWIG. +Details of this are covered later in the Wrapping Overloaded Functions and Methods section. +This approach allows SWIG to wrap all possible default arguments, but can be verbose. +For example if a method has ten default arguments, then eleven wrapper methods are generated. +

      + +

      +Please see the Features and default arguments +section for more information on using %feature with functions with default arguments. +The Ambiguity resolution and renaming section +also deals with using %rename and %ignore on methods with default arguments. +If you are writing your own typemaps for types used in methods with default arguments, you may also need to write a typecheck typemap. +See the Typemaps and overloading section for details or otherwise +use the compactdefaultargs feature flag as mentioned below. +

      + +

      +Compatibility note: Versions of SWIG prior to SWIG-1.3.23 wrapped default arguments slightly differently. +Instead a single wrapper method was generated and the default values were copied into the C++ wrappers +so that the method being wrapped was then called with all the arguments specified. +If the size of the wrappers are a concern then this approach to wrapping methods with default arguments +can be re-activated by using the compactdefaultargs +feature flag. +

      + +
      +
      +%feature("compactdefaultargs") Foo::bar;
      +class Foo {
      +public:
      +  void bar(int x, int y = 3, int z = 4);
      +};
      +
      +
      + + +

      +This is great for reducing the size of the wrappers, but the caveat is it does not work for the statically typed languages, +such as C# and Java, +which don't have optional arguments in the language, +Another restriction of this feature is that it cannot handle default arguments that are not public. +The following example illustrates this: +

      + +
      +
      +class Foo {
      +private:
      +  static const int spam;
      +public:
      +  void bar(int x, int y = spam);   // Won't work with %feature("compactdefaultargs") -
      +                                   // private default value
      +};
      +
      +
      + +

      +This produces uncompilable wrapper code because default values in C++ are +evaluated in the same scope as the member function whereas SWIG +evaluates them in the scope of a wrapper function (meaning that the +values have to be public). +

      + +

      +The compactdefaultargs feature is automatically turned on when wrapping C code with default arguments. +Some target languages will also automatically turn on this feature +if the keyword arguments feature (kwargs) is specified for either C or C++ functions, and the target language supports kwargs, +the compactdefaultargs feature is also automatically turned on. +Keyword arguments are a language feature of some scripting languages, for example Ruby and Python. +SWIG is unable to support kwargs when wrapping overloaded methods, so the default approach cannot be used. +

      +

      6.15 Wrapping Overloaded Functions and Methods

      From d5d97a406927ebf6bd86ce2c4c7723e76fb8252b Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Thu, 14 Sep 2017 07:58:24 +0100 Subject: [PATCH 290/455] Overloaded methods section renamed slightly in docs --- Doc/Manual/Contents.html | 4 ++-- Doc/Manual/Php.html | 3 +-- Doc/Manual/SWIGPlus.html | 10 +++++----- Doc/Manual/Scilab.html | 2 +- 4 files changed, 9 insertions(+), 10 deletions(-) diff --git a/Doc/Manual/Contents.html b/Doc/Manual/Contents.html index e3478ae91..4211d8ab8 100644 --- a/Doc/Manual/Contents.html +++ b/Doc/Manual/Contents.html @@ -236,14 +236,14 @@
    • Inheritance
    • A brief discussion of multiple inheritance, pointers, and type checking
    • Default arguments -
    • Wrapping Overloaded Functions and Methods +
    • Overloaded functions and methods -
    • Wrapping overloaded operators +
    • Overloaded operators
    • Class extension
    • Templates
        diff --git a/Doc/Manual/Php.html b/Doc/Manual/Php.html index 9a1178abf..9fbfd75c0 100644 --- a/Doc/Manual/Php.html +++ b/Doc/Manual/Php.html @@ -390,8 +390,7 @@ Although PHP does not support overloading functions natively, swig will generate dispatch functions which will use %typecheck typemaps to allow overloading. This dispatch function's operation and precedence is described in Wrapping -Overloaded Functions and Methods. +href="SWIGPlus.html#SWIGPlus_overloaded_methods">Overloaded functions and methods.

         %module(directors="1") example
         
         %{
        -  #include <string>
           #include <stdexcept>
        +  #include <iostream>
         %}
         
        -// Define exceptions in header section using std::runtime_error
        -%define DEFINE_EXCEPTION(NAME)
        -%{
        -  namespace MyNS {
        -    struct NAME : public std::runtime_error { NAME(const std::string &what) : runtime_error(what) {} };
        +// Generic catch handler for all wrapped methods
        +%exception %{
        +  try {
        +    $action
        +  } catch (const std::exception &e) {
        +    std::cout << "Generic std::exception catch handler" << std::endl;
        +    jclass clazz = jenv->FindClass("java/lang/RuntimeException");
        +    jenv->ThrowNew(clazz, e.what()); 
        +    return $null;
           }
         %}
        -%enddef
         
        -// Expose C++ exceptions as Java Exceptions by changing the Java base class and providing a getMessage()
        -%define DECLARE_EXCEPTION(NAME)
        -%typemap(javabase) MyNS::NAME "java.lang.Exception";
        -%rename(getMessage) MyNS::NAME::what;
        +// Expose C++ exception as a Java Exception by changing the Java base class and providing a getMessage()
        +%typemap(javabase) MyNS::MyException "java.lang.RuntimeException";
        +%rename(getMessage) MyNS::MyException::whatsup;
        +
        +%inline %{
         namespace MyNS {
        -  struct NAME {
        -    NAME(const std::string& what);
        -    const char * what();
        +  class MyException {
        +    std::string msg;
        +  public:
        +    MyException(const char *msg) : msg(msg) {}
        +    const char * whatsup() const { return msg.c_str(); }
           };
         }
        -%enddef
        +%}
         
        -DEFINE_EXCEPTION(ExceptionA)
        -DEFINE_EXCEPTION(ExceptionB)
        -DEFINE_EXCEPTION(Unexpected)
        -
        -%typemap(directorthrows) MyNS::ExceptionA, MyNS::ExceptionB, MyNS::Unexpected %{
        -  if (Swig::ExceptionMatches(jenv, $error, "$packagepath/$javaclassname")) {
        +%typemap(directorthrows) MyNS::MyException %{
        +  if (Swig::ExceptionMatches(jenv, $error, "$packagepath/MyException")) {
        +    std::cout << "$1_type exception matched (directorthrows typemap)" << std::endl;
             throw $1_type(Swig::JavaExceptionMessage(jenv, $error).message());
           }
         %}
         
        -DECLARE_EXCEPTION(ExceptionA)
        -DECLARE_EXCEPTION(ExceptionB)
        -DECLARE_EXCEPTION(Unexpected)
        +%typemap(throws) MyNS::MyException %{
        +  std::cout << "$1_type caught (throws typemap)" << std::endl;
        +  jclass excep = jenv->FindClass("MyException");
        +  if (excep) {
        +    std::cout << "$1_type class found (throws typemap)" << std::endl;
        +    jenv->ThrowNew(excep, $1.whatsup());
        +  }
        +  return $null;
        +%}
         
        -%catches(MyNS::ExceptionA, MyNS::ExceptionB, MyNS::Unexpected) MyClass::meth2();
        +// These are the exceptions that the director method MyClass::dirmethod will have catch handlers for.
        +// Note that this is also a virtual method / director method and the C++ exceptions listed can be
        +// thrown after converting them from Java exceptions.
        +%catches(MyNS::MyException, Swig::DirectorException) MyClass::dirmethod;
        +
        +// These are the exceptions that call_dirmethod C++ wrapper will have catch handlers for.
        +// Note that this is not a virtual method, hence not a director method.
        +%catches(MyNS::MyException, Swig::DirectorException) call_dirmethod;
         
         %feature("director") MyClass;
         
        -%inline {
        -  class MyClass {
        -  public:
        -    virtual void meth1(int x) throw(MyNS::ExceptionA, MyNS::ExceptionB) = 0;
        -    virtual void meth2() = 0;   /* throws MyNS::ExceptionA, MyNS::ExceptionB, MyNS::Unexpected */
        -    virtual void meth3(float x) throw(MyNS::Unexpected) = 0;
        -    virtual ~MyClass() {}
        -  };
        -}
        -
        -
        - -

        -In this case the three different "directorthrows" typemaps will be used -to generate the three different exception handlers for -meth1, meth2 and meth3. The generated -handlers will have "if" blocks for each exception type, where the exception types are listed in either -the exception specification or %catches feature. -

        - -

        Note that the "directorthrows" typemaps are important -only if it is important for the exceptions passed through the C++ -layer need to be mapped to distinct C++ exceptions. If director methods -are being called by C++ code that is itself wrapped in a -SWIG generated Java wrapper and access is always through this wrapper, -the default Swig::DirectorException class provides enough information -to reconstruct the original exception. In this case removing the -$directorthrowshandlers special variable from the -default director:except feature and simply always -throwing a Swig::DirectorException will achieve the desired result. -Along with this a generic exception feature is added to convert any -caught Swig::DirectorExceptions back into the underlying -Java exceptions via the Swig::DirectorException::raiseJavaException method, -as demonstrated with %javaexception below: -

        - -
        -
        -%javaexception("Exception") MyClass::myMethod %{
        -  try {
        -    $action
        -  } catch (Swig::DirectorException &e) {
        -    // raise/throw the Java exception that originally caused the DirectorException
        -    e.raiseJavaException(jenv);
        -    return $null;
        +%feature("director:except") MyClass::dirmethod(int x) {
        +  jthrowable $error = jenv->ExceptionOccurred();
        +  if ($error) {
        +    std::cout << "Upcall finished, an exception was thrown in Java" << std::endl;
        +    $directorthrowshandlers
        +    std::cout << "Upcall finished, no exception conversion, throwing DirectorException" << std::endl;
        +    Swig::DirectorException::raise(jenv, $error);
           }
        +}
        +
        +%inline %{
        +class MyClass {
        +public:
        +  /** Throws either a std::out_of_range or MyException on error */
        +  virtual void dirmethod(int x) {
        +    if (x <= 0)
        +      throw std::out_of_range("MyClass::dirmethod index is out of range");
        +    else if (x == 1)
        +      throw MyNS::MyException("MyClass::dirmethod some problem!");
        +  }
        +  virtual ~MyClass() {}
        +  static void call_dirmethod(MyClass& c, int x) {
        +    return c.dirmethod(x);
        +  }
        +};
         %}
         

        -See the Exception handling with %exception and %javaexception -section for more on converting C++ exceptions to Java exceptions. +The generated code for the call_dirmethod wrapper contains the various exception handlers. +The outer exception handler is from the %exception directive and the others +are from the "throws" typemaps.

        +
        +
        +SWIGEXPORT void JNICALL Java_exampleJNI_MyClass_1call_1dirmethod(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_, jint jarg2) {
        +  ...
        +  try {
        +    try {
        +      MyClass::call_dirmethod(*arg1,arg2);
        +    } catch(MyNS::MyException &_e) {
        +      std::cout << "MyNS::MyException caught (throws typemap)" << std::endl;
        +      jclass excep = jenv->FindClass("MyException");
        +      if (excep) {
        +        std::cout << "MyNS::MyException class found (throws typemap)" << std::endl;
        +        jenv->ThrowNew(excep, (&_e)->whatsup());
        +      }
        +      return ;
        +      
        +    } catch(Swig::DirectorException &_e) {
        +      (&_e)->raiseJavaException(jenv);
        +      return ; 
        +    }
        +  } catch (const std::exception &e) {
        +    std::cout << "Generic std::exception catch handler" << std::endl;
        +    jclass clazz = jenv->FindClass("java/lang/RuntimeException");
        +    jenv->ThrowNew(clazz, e.what()); 
        +    return ;
        +  }
        +
        +
        + +

        +The director method calling up to Java contains the exception handling code from the "directorthrows" typemaps and director:except feature. +

        + +
        +
        +void SwigDirector_MyClass::dirmethod(int x) {
        +      ... [call up to Java using CallStaticVoidMethod]
        +      jthrowable swigerror = jenv->ExceptionOccurred();
        +      if (swigerror) {
        +        std::cout << "Upcall finished, an exception was thrown in Java" << std::endl;
        +        
        +        if (Swig::ExceptionMatches(jenv, swigerror, "MyException")) {
        +          std::cout << "MyNS::MyException exception matched (directorthrows typemap)" << std::endl;
        +          throw MyNS::MyException(Swig::JavaExceptionMessage(jenv, swigerror).message());
        +        }
        +        
        +        std::cout << "Upcall finished, no exception conversion, throwing DirectorException" << std::endl;
        +        Swig::DirectorException::raise(jenv, swigerror);
        +      }
        +
        +
        + +

        +Let's use the following Java class to override the director method. +

        + +
        +
        +class DerivedClass extends MyClass {
        +  @Override
        +  public void dirmethod(int x) {
        +    if (x < 0)
        +      throw new IndexOutOfBoundsException("Index is negative");
        +    else if (x == 0)
        +      throw new MyException("MyException: bad dirmethod");
        +  }
        +}
        +public class runme {
        +  public static void main(String argv[]) {
        +    System.loadLibrary("example");
        +    ... code snippets shown below ...
        +  }
        +}
        +
        +
        + +

        +Consider the output using the Java code in the four slightly different scenarios below. +

        + +

        +1. Non-director C++ class is used, thus, no upcall to a Java director method is made. +A std::out_of_range exception is thrown, which is derived from std::exception, +and hence caught by the generic exception handler in the call_dirmethod wrapper. +The Java code snippet and resulting output is: +

        + + +
        +
        +MyClass.call_dirmethod(new MyClass(), 0);
        +
        +
        + +
        +
        +Generic std::exception catch handler
        +Exception in thread "main" java.lang.RuntimeException: MyClass::dirmethod index is out of range
        +        at exampleJNI.MyClass_call_dirmethod(Native Method)
        +        at MyClass.call_dirmethod(MyClass.java:57)
        +        at runme.main(runme.java:14)
        +
        +
        + +

        +2. Non-director C++ class again but this time the MyNS::MyException class is thrown and caught: +

        + +
        +
        +MyClass.call_dirmethod(new MyClass(), 1);
        +
        +
        + +
        +
        +MyNS::MyException caught (throws typemap)
        +MyNS::MyException class found (throws typemap)
        +Exception in thread "main" MyException: MyClass::dirmethod some problem!
        +        at exampleJNI.MyClass_call_dirmethod(Native Method)
        +        at MyClass.call_dirmethod(MyClass.java:57)
        +        at runme.main(runme.java:15)
        +
        +
        + +

        +3. The DerivedClass director class is used so the upcall to Java occurs, but it throws +a Java MyException, which gets converted into a C++ MyNS::MyException, then caught and converted back +into a Java MyException: +

        + +
        +
        +MyClass.call_dirmethod(new DerivedClass(), 0);
        +
        +
        + +
        +
        +Upcall finished, an exception was thrown in Java
        +MyNS::MyException exception matched (directorthrows typemap)
        +MyNS::MyException caught (throws typemap)
        +MyNS::MyException class found (throws typemap)
        +Exception in thread "main" MyException: MyException: bad dirmethod
        +        at exampleJNI.MyClass_call_dirmethod(Native Method)
        +        at MyClass.call_dirmethod(MyClass.java:57)
        +        at runme.main(runme.java:16)
        +
        +
        + +

        +4. The director class is used again, but this time the director method throws a Java IndexOutOfBoundsException exception which is converted into a C++ Swig::DirectorException, thrown and caught again. +This time the original Java exception is extracted from the Swig::DirectorException and rethrown. +Note that this approach keeps the stack trace information of the original exception, so it has the exact location of where the IndexOutOfBoundsException exception was thrown. +This is arguably an improvement over the approach above that converts from a Java excepton to C++ exception and then back to a new Java exception, losing the location of the original exception. +

        + +
        +
        +MyClass.call_dirmethod(new DerivedClass(), -1);
        +
        +
        + +
        +
        +Upcall finished, an exception was thrown in Java
        +Upcall finished, no exception conversion, throwing DirectorException
        +Exception in thread "main" java.lang.IndexOutOfBoundsException: Index is negative
        +        at DerivedClass.dirmethod(runme.java:5)
        +        at exampleJNI.SwigDirector_MyClass_dirmethod(exampleJNI.java:23)
        +        at exampleJNI.MyClass_call_dirmethod(Native Method)
        +        at MyClass.call_dirmethod(MyClass.java:57)
        +        at runme.main(runme.java:17)
        +
        +
        +

        25.6 Accessing protected members

        diff --git a/Doc/Manual/SWIGPlus.html b/Doc/Manual/SWIGPlus.html index 144a24d0a..5eac55261 100644 --- a/Doc/Manual/SWIGPlus.html +++ b/Doc/Manual/SWIGPlus.html @@ -4630,7 +4630,7 @@ The next section details a way of simulating an exception specification or repla Exceptions are automatically handled for methods with an exception specification. Similar handling can be achieved for methods without exception specifications through the %catches feature. It is also possible to replace any declared exception specification using the %catches feature. -In fact, %catches uses the same "throws" typemaps that SWIG uses for exception specifications in handling exceptions. +In fact, %catches uses the same "throws" typemaps that SWIG uses for exception specifications in handling exceptions. The %catches feature must contain a list of possible types that can be thrown. For each type that is in the list, SWIG will generate a catch handler, in the same way that it would for types declared in the exception specification. Note that the list can also include the catch all specification "...". diff --git a/Doc/Manual/Typemaps.html b/Doc/Manual/Typemaps.html index 371d0debd..d0d8d7951 100644 --- a/Doc/Manual/Typemaps.html +++ b/Doc/Manual/Typemaps.html @@ -67,7 +67,7 @@
      • "memberin" typemap
      • "varin" typemap
      • "varout" typemap -
      • "throws" typemap +
      • "throws" typemap
    • Some typemap examples
        @@ -2884,11 +2884,11 @@ The "varout" typemap is used to convert a C/C++ object to an object in the targe language when reading a C/C++ global variable. This is implementation specific.

        -

        11.5.14 "throws" typemap

        +

        11.5.14 "throws" typemap

        -The "throws" typemap is only used when SWIG parses a C++ method with an exception specification or has the %catches feature attached to the method. +The "throws" typemap is only used when SWIG parses a C++ method with an exception specification or has the %catches feature attached to the method (see Exception handling with %catches). It provides a default mechanism for handling C++ methods that have declared the exceptions they will throw. The purpose of this typemap is to convert a C++ exception into an error or exception in the target language. It is slightly different to the other typemaps as it is based around the exception type rather than the type of a parameter or variable. @@ -2913,7 +2913,7 @@ For example:

        As can be seen from the resulting generated code below, SWIG generates an exception handler -with the catch block comprising the "throws" typemap content. +when wrapping the bar function with the catch block comprising the "throws" typemap content.

        From 901f8357b00f6de94a3ad9d70dd00722557b5430 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Wed, 29 Nov 2017 20:25:58 +0000 Subject: [PATCH 384/455] Replace DirectorException::raiseJavaException with DirectorException::throwException This is part of a plan to provide a common DirectorException api for throwing the target language exception raised during a director method call. --- Doc/Manual/Java.html | 4 ++-- Examples/test-suite/java_director_exception_feature.i | 7 ++++--- .../test-suite/java_director_exception_feature_nspace.i | 7 ++++--- Lib/java/director.swg | 7 ++++++- Lib/java/java.swg | 2 +- 5 files changed, 17 insertions(+), 10 deletions(-) diff --git a/Doc/Manual/Java.html b/Doc/Manual/Java.html index 2b6ec6ce0..3b6cb3a05 100644 --- a/Doc/Manual/Java.html +++ b/Doc/Manual/Java.html @@ -3992,7 +3992,7 @@ namespace Swig { // Reconstruct and raise/throw the Java Exception that caused the DirectorException // Note that any error in the JNI exception handling results in a Java RuntimeException - void raiseJavaException(JNIEnv *jenv) const; + void throwException(JNIEnv *jenv) const; // Create and throw the DirectorException static void raise(JNIEnv *jenv, jthrowable throwable) { @@ -4295,7 +4295,7 @@ SWIGEXPORT void JNICALL Java_exampleJNI_MyClass_1call_1dirmethod(JNIEnv *jenv, j return ; } catch(Swig::DirectorException &_e) { - (&_e)->raiseJavaException(jenv); + (&_e)->throwException(jenv); return ; } } catch (const std::exception &e) { diff --git a/Examples/test-suite/java_director_exception_feature.i b/Examples/test-suite/java_director_exception_feature.i index 0cd555875..b5b9c3938 100644 --- a/Examples/test-suite/java_director_exception_feature.i +++ b/Examples/test-suite/java_director_exception_feature.i @@ -132,9 +132,10 @@ %} %feature ("except",throws="Exception") MyNS::Bar::genericpong %{ - try { $action } - catch (Swig::DirectorException & direxcp) { - direxcp.raiseJavaException(jenv); // jenv always available in JNI code + try { + $action + } catch (Swig::DirectorException & direxcp) { + direxcp.throwException(jenv); // jenv always available in JNI code return $null; } %} diff --git a/Examples/test-suite/java_director_exception_feature_nspace.i b/Examples/test-suite/java_director_exception_feature_nspace.i index aa8c64cc9..9f542fd37 100644 --- a/Examples/test-suite/java_director_exception_feature_nspace.i +++ b/Examples/test-suite/java_director_exception_feature_nspace.i @@ -139,9 +139,10 @@ %} %feature ("except",throws="Exception") MyNS::Bar::genericpong %{ - try { $action } - catch (Swig::DirectorException & direxcp) { - direxcp.raiseJavaException(jenv); // jenv always available in JNI code + try { + $action + } catch (Swig::DirectorException & direxcp) { + direxcp.throwException(jenv); // jenv always available in JNI code return $null; } %} diff --git a/Lib/java/director.swg b/Lib/java/director.swg index 416361c27..2275976b8 100644 --- a/Lib/java/director.swg +++ b/Lib/java/director.swg @@ -339,7 +339,7 @@ namespace Swig { // Reconstruct and raise/throw the Java Exception that caused the DirectorException // Note that any error in the JNI exception handling results in a Java RuntimeException - void raiseJavaException(JNIEnv *jenv) const { + void throwException(JNIEnv *jenv) const { if (jenv) { if (jenv == jenv_ && throwable_) { // Throw original exception if not already pending @@ -371,6 +371,11 @@ namespace Swig { } } + // Deprecated - use throwException + void raiseJavaException(JNIEnv *jenv) const { + throwException(jenv); + } + // Create and throw the DirectorException static void raise(JNIEnv *jenv, jthrowable throwable) { throw DirectorException(jenv, throwable); diff --git a/Lib/java/java.swg b/Lib/java/java.swg index 184ee56aa..ae984313b 100644 --- a/Lib/java/java.swg +++ b/Lib/java/java.swg @@ -1053,7 +1053,7 @@ Swig::LocalRefGuard $1_refguard(jenv, $input); } /* For methods to raise/throw the original Java exception thrown in a director method */ %typemap(throws) Swig::DirectorException -%{ $1.raiseJavaException(jenv); +%{ $1.throwException(jenv); return $null; %} /* Java to C++ DirectorException should already be handled. Suppress warning and do nothing in the From bf21e80267dd0c7170a0cb8799562753ea1bef66 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Wed, 29 Nov 2017 20:30:40 +0000 Subject: [PATCH 385/455] Add recent Java director enhancements to the changes file --- CHANGES.current | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/CHANGES.current b/CHANGES.current index b1c35d46d..a8fec2709 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.0.0 (in progress) =========================== +2017-11-29: wsfulton + [Java] director exception handling improvements. + + When a director method throws an exception and it is caught by DirectorException + and passed back to Java using Swig::DirectorException::throwException, the Java + stack trace now contains the original source line that threw the exception. + + Deprecate Swig::DirectorException::raiseJavaException, please replace usage with + Swig::DirectorException::throwException. + 2017-10-26: wsfulton Add support for C++11 ref-qualifiers when using directors. From 7eff4e7c1d40b4f6666aa8b635f30d8f6771e88f Mon Sep 17 00:00:00 2001 From: Joshua Watt Date: Mon, 4 Dec 2017 09:23:06 -0600 Subject: [PATCH 386/455] Terminate options when passed via env var The C standard requires that argv be terminated with a NULL pointer (that is, argv[argc] == NULL). There are several places in the swig codebase that require this to check for missing arguments. However, SWIG_merge_envopt() was not keeping the NULL terminator, resulting in argument parsing failures (typically program aborts) when arguments were passed via the SWIG_FEATURES environment variable. --- Source/Modules/swigmain.cxx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Source/Modules/swigmain.cxx b/Source/Modules/swigmain.cxx index 397677fc5..b49fe909a 100644 --- a/Source/Modules/swigmain.cxx +++ b/Source/Modules/swigmain.cxx @@ -125,7 +125,7 @@ void SWIG_merge_envopt(const char *env, int oargc, char *oargv[], int *nargc, ch int argc = 1; int arge = oargc + 1024; - char **argv = (char **) malloc(sizeof(char *) * (arge)); + char **argv = (char **) malloc(sizeof(char *) * (arge + 1)); char *buffer = (char *) malloc(2048); char *b = buffer; char *be = b + 1023; @@ -147,6 +147,7 @@ void SWIG_merge_envopt(const char *env, int oargc, char *oargv[], int *nargc, ch for (int i = 1; (i < oargc) && (argc < arge); ++i, ++argc) { argv[argc] = oargv[i]; } + argv[argc] = NULL; *nargc = argc; *nargv = argv; From b0e29fbdf31bb94b11cb8a7cc830b4a76467afa3 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Mon, 4 Dec 2017 18:41:55 +0000 Subject: [PATCH 387/455] Add missing checks for failures in calls to PyUnicode_AsUTF8String. Previously a seg fault could occur when passing invalid UTF8 strings (low surrogates), eg passing u"\udcff" to the C layer (Python 3). --- CHANGES.current | 8 ++++++- Doc/Manual/Python.html | 22 ++++++++++++++++--- Doc/Manual/Varargs.html | 5 ++++- Examples/python/multimap/example.i | 12 +++++++++- .../python/unicode_strings_runme.py | 10 +++++++++ Examples/test-suite/python_varargs_typemap.i | 5 ++++- Examples/test-suite/unicode_strings.i | 2 ++ Lib/python/pyerrors.swg | 11 ++++++---- Lib/python/pyhead.swg | 16 ++++++++------ Lib/python/pyinit.swg | 4 ++-- Lib/python/pyrun.swg | 10 ++++++--- Lib/python/pystrings.swg | 12 ++++++++-- 12 files changed, 92 insertions(+), 25 deletions(-) diff --git a/CHANGES.current b/CHANGES.current index 5cab80172..06b958f18 100644 --- a/CHANGES.current +++ b/CHANGES.current @@ -6,8 +6,14 @@ the issue number to the end of the URL: https://github.com/swig/swig/issues/ Version 4.0.0 (in progress) =========================== + +2017-12-04: wsfulton + [Python] Add missing checks for failures in calls to PyUnicode_AsUTF8String. Previously a + seg fault could occur when passing invalid UTF8 strings (low surrogates), eg passing + u"\udcff" to the C layer (Python 3). + 2017-11-24: joequant - Fix github #1124 and return R_NilValue for null pointers + Fix #1124 and return R_NilValue for null pointers 2017-11-29: wsfulton [Java] director exception handling improvements. diff --git a/Doc/Manual/Python.html b/Doc/Manual/Python.html index 0c0023dea..27ce084bd 100644 --- a/Doc/Manual/Python.html +++ b/Doc/Manual/Python.html @@ -6521,14 +6521,16 @@ string that cannot be completely decoded as UTF-8:
         %module example
         
        -%include <std_string.i>
        -
         %inline %{
         
        -const char* non_utf8_c_str(void) {
        +const char * non_utf8_c_str(void) {
           return "h\xe9llo w\xc3\xb6rld";
         }
         
        +void instring(const char *s) {
        +  ...
        +}
        +
         %}
         
        @@ -6590,6 +6592,20 @@ For more details about the surrogateescape error handler, please see PEP 383.

        +

        +When Python 3 strings are passed to the C/C++ layer, they are expected to be valid UTF8 Unicode strings too. +For example, when the instring method above is wrapped and called, any invalid UTF8 Unicode code strings +will result in a TypeError because the attempted conversion fails: +

        + +
        +>>> example.instring('h\xe9llo')
        +>>> example.instring('h\udce9llo')
        +Traceback (most recent call last):
        +  File "<stdin>", line 1, in <module>
        +TypeError: in method 'instring', argument 1 of type 'char const *'
        +
        +

        In some cases, users may wish to instead handle all byte strings as bytes objects in Python 3. This can be accomplished by adding diff --git a/Doc/Manual/Varargs.html b/Doc/Manual/Varargs.html index eba816382..014a38cae 100644 --- a/Doc/Manual/Varargs.html +++ b/Doc/Manual/Varargs.html @@ -529,8 +529,11 @@ like this: SWIG_fail; } pystr = PyUnicode_AsUTF8String(pyobj); + if (!pystr) { + SWIG_fail; + } str = strdup(PyBytes_AsString(pystr)); - Py_XDECREF(pystr); + Py_DECREF(pystr); %#else if (!PyString_Check(pyobj)) { PyErr_SetString(PyExc_ValueError, "Expected a string"); diff --git a/Examples/python/multimap/example.i b/Examples/python/multimap/example.i index 66c0f74c6..3ff5d52c0 100644 --- a/Examples/python/multimap/example.i +++ b/Examples/python/multimap/example.i @@ -39,7 +39,11 @@ extern int gcd(int x, int y); %#if PY_VERSION_HEX >= 0x03000000 { PyObject *utf8str = PyUnicode_AsUTF8String(s); - const char *cstr = PyBytes_AsString(utf8str); + const char *cstr; + if (!utf8str) { + SWIG_fail; + } + cstr = PyBytes_AsString(utf8str); $2[i] = strdup(cstr); Py_DECREF(utf8str); } @@ -72,6 +76,9 @@ extern int gcdmain(int argc, char *argv[]); SWIG_fail; } utf8str = PyUnicode_AsUTF8String($input); + if (!utf8str) { + SWIG_fail; + } PyBytes_AsStringAndSize(utf8str, &cstr, &len); $1 = strncpy((char *)malloc(len+1), cstr, (size_t)len); $2 = (int)len; @@ -105,6 +112,9 @@ extern int count(char *bytes, int len, char c); char *cstr; Py_ssize_t len; PyObject *utf8str = PyUnicode_AsUTF8String($input); + if (!utf8str) { + SWIG_fail; + } PyBytes_AsStringAndSize(utf8str, &cstr, &len); $1 = strncpy((char *)malloc(len+1), cstr, (size_t)len); $2 = (int)len; diff --git a/Examples/test-suite/python/unicode_strings_runme.py b/Examples/test-suite/python/unicode_strings_runme.py index fa9c51437..39e93b0fc 100644 --- a/Examples/test-suite/python/unicode_strings_runme.py +++ b/Examples/test-suite/python/unicode_strings_runme.py @@ -25,3 +25,13 @@ if sys.version_info[0:2] < (3, 0): check(unicode_strings.charstring(unicode("hello4")), "hello4") unicode_strings.charstring(u"hell\xb05") unicode_strings.charstring(u"hell\u00f66") + +low_surrogate_string = u"\udcff" +try: + unicode_strings.instring(low_surrogate_string) + # Will succeed with Python 2 +except TypeError, e: + # Python 3 will fail the PyUnicode_AsUTF8String conversion resulting in a TypeError. + # The real error is actually: + # UnicodeEncodeError: 'utf-8' codec can't encode character '\udcff' in position 0: surrogates not allowed + pass diff --git a/Examples/test-suite/python_varargs_typemap.i b/Examples/test-suite/python_varargs_typemap.i index f05fb98eb..d809bf1fa 100644 --- a/Examples/test-suite/python_varargs_typemap.i +++ b/Examples/test-suite/python_varargs_typemap.i @@ -23,8 +23,11 @@ SWIG_fail; } pystr = PyUnicode_AsUTF8String(pyobj); + if (!pystr) { + SWIG_fail; + } str = strdup(PyBytes_AsString(pystr)); - Py_XDECREF(pystr); + Py_DECREF(pystr); %#else if (!PyString_Check(pyobj)) { PyErr_SetString(PyExc_ValueError, "Expected a string"); diff --git a/Examples/test-suite/unicode_strings.i b/Examples/test-suite/unicode_strings.i index 9be3748e6..e7266266e 100644 --- a/Examples/test-suite/unicode_strings.i +++ b/Examples/test-suite/unicode_strings.i @@ -20,4 +20,6 @@ char *charstring(char *s) { return s; } +void instring(const char *s) { +} %} diff --git a/Lib/python/pyerrors.swg b/Lib/python/pyerrors.swg index fe7313554..463afae15 100644 --- a/Lib/python/pyerrors.swg +++ b/Lib/python/pyerrors.swg @@ -53,14 +53,17 @@ SWIG_Python_AddErrorMsg(const char* mesg) PyObject *value = 0; PyObject *traceback = 0; - if (PyErr_Occurred()) PyErr_Fetch(&type, &value, &traceback); + if (PyErr_Occurred()) + PyErr_Fetch(&type, &value, &traceback); if (value) { - char *tmp; PyObject *old_str = PyObject_Str(value); + const char *tmp = SWIG_Python_str_AsChar(old_str); PyErr_Clear(); Py_XINCREF(type); - - PyErr_Format(type, "%s %s", tmp = SWIG_Python_str_AsChar(old_str), mesg); + if (tmp) + 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); diff --git a/Lib/python/pyhead.swg b/Lib/python/pyhead.swg index 55eb95a6d..2fa8b5b4c 100644 --- a/Lib/python/pyhead.swg +++ b/Lib/python/pyhead.swg @@ -38,14 +38,16 @@ SWIGINTERN char* SWIG_Python_str_AsChar(PyObject *str) { #if PY_VERSION_HEX >= 0x03000000 - char *cstr; - char *newstr; - Py_ssize_t len; + char *newstr = 0; str = PyUnicode_AsUTF8String(str); - PyBytes_AsStringAndSize(str, &cstr, &len); - newstr = (char *) malloc(len+1); - memcpy(newstr, cstr, len+1); - Py_XDECREF(str); + if (str) { + char *cstr; + Py_ssize_t len; + PyBytes_AsStringAndSize(str, &cstr, &len); + newstr = (char *) malloc(len+1); + memcpy(newstr, cstr, len+1); + Py_XDECREF(str); + } return newstr; #else return PyString_AsString(str); diff --git a/Lib/python/pyinit.swg b/Lib/python/pyinit.swg index fe45ac941..826f8411b 100644 --- a/Lib/python/pyinit.swg +++ b/Lib/python/pyinit.swg @@ -84,10 +84,10 @@ swig_varlink_str(swig_varlinkobject *v) { SWIGINTERN int swig_varlink_print(swig_varlinkobject *v, FILE *fp, int SWIGUNUSEDPARM(flags)) { - char *tmp; PyObject *str = swig_varlink_str(v); + const char *tmp = SWIG_Python_str_AsChar(str); fprintf(fp,"Swig global variables "); - fprintf(fp,"%s\n", tmp = SWIG_Python_str_AsChar(str)); + fprintf(fp,"%s\n", tmp ? tmp : "Invalid global variable"); SWIG_Python_str_DelForPy3(tmp); Py_DECREF(str); return 0; diff --git a/Lib/python/pyrun.swg b/Lib/python/pyrun.swg index efc476613..430d3af18 100644 --- a/Lib/python/pyrun.swg +++ b/Lib/python/pyrun.swg @@ -1672,14 +1672,16 @@ SWIG_Python_AddErrMesg(const char* mesg, int infront) PyObject *traceback = 0; PyErr_Fetch(&type, &value, &traceback); if (value) { - char *tmp; PyObject *old_str = PyObject_Str(value); + const char *tmp = SWIG_Python_str_AsChar(old_str); + if (!tmp) + tmp = "Invalid error message"; Py_XINCREF(type); PyErr_Clear(); if (infront) { - PyErr_Format(type, "%s %s", mesg, tmp = SWIG_Python_str_AsChar(old_str)); + PyErr_Format(type, "%s %s", mesg, tmp); } else { - PyErr_Format(type, "%s %s", tmp = SWIG_Python_str_AsChar(old_str), mesg); + PyErr_Format(type, "%s %s", tmp, mesg); } SWIG_Python_str_DelForPy3(tmp); Py_DECREF(old_str); @@ -1805,6 +1807,8 @@ SWIG_Python_NonDynamicSetAttr(PyObject *obj, PyObject *name, PyObject *value) { Py_INCREF(name); } else { encoded_name = PyUnicode_AsUTF8String(name); + if (!encoded_name) + return -1; } PyErr_Format(PyExc_AttributeError, "'%.100s' object has no attribute '%.200s'", tp->tp_name, PyString_AsString(encoded_name)); Py_DECREF(encoded_name); diff --git a/Lib/python/pystrings.swg b/Lib/python/pystrings.swg index fd37855eb..301e0f3e1 100644 --- a/Lib/python/pystrings.swg +++ b/Lib/python/pystrings.swg @@ -16,6 +16,7 @@ SWIG_AsCharPtrAndSize(PyObject *obj, char** cptr, size_t* psize, int *alloc) %#endif { char *cstr; Py_ssize_t len; + int ret = SWIG_OK; %#if PY_VERSION_HEX>=0x03000000 %#if !defined(SWIG_PYTHON_STRICT_BYTE_CHAR) if (!alloc && cptr) { @@ -26,7 +27,10 @@ SWIG_AsCharPtrAndSize(PyObject *obj, char** cptr, size_t* psize, int *alloc) return SWIG_RuntimeError; } obj = PyUnicode_AsUTF8String(obj); - if(alloc) *alloc = SWIG_NEWOBJ; + if (!obj) + return SWIG_TypeError; + if (alloc) + *alloc = SWIG_NEWOBJ; %#endif PyBytes_AsStringAndSize(obj, &cstr, &len); %#else @@ -64,6 +68,8 @@ SWIG_AsCharPtrAndSize(PyObject *obj, char** cptr, size_t* psize, int *alloc) %#endif %#else *cptr = SWIG_Python_str_AsChar(obj); + if (!*cptr) + ret = SWIG_TypeError; %#endif } } @@ -71,7 +77,7 @@ SWIG_AsCharPtrAndSize(PyObject *obj, char** cptr, size_t* psize, int *alloc) %#if PY_VERSION_HEX>=0x03000000 && !defined(SWIG_PYTHON_STRICT_BYTE_CHAR) Py_XDECREF(obj); %#endif - return SWIG_OK; + return ret; } else { %#if defined(SWIG_PYTHON_2_UNICODE) %#if defined(SWIG_PYTHON_STRICT_BYTE_CHAR) @@ -84,6 +90,8 @@ SWIG_AsCharPtrAndSize(PyObject *obj, char** cptr, size_t* psize, int *alloc) return SWIG_RuntimeError; } obj = PyUnicode_AsUTF8String(obj); + if (!obj) + return SWIG_TypeError; if (PyString_AsStringAndSize(obj, &cstr, &len) != -1) { if (cptr) { if (alloc) *alloc = SWIG_NEWOBJ; From 224bb9e0232a219b7cefd23472b592b39e277f46 Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Fri, 8 Dec 2017 15:50:14 +1300 Subject: [PATCH 388/455] [PHP] Use ZEND_MODULE_GLOBALS_ACCESSOR to access globals This should make the generated code work with PHP 7.2.0. --- CHANGES.current | 4 ++++ Source/Modules/php.cxx | 4 ++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/CHANGES.current b/CHANGES.current index 06b958f18..ce71dcac2 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.0.0 (in progress) =========================== +2017-12-08: olly + [PHP] Use ZEND_MODULE_GLOBALS_ACCESSOR to access globals - this + should make the generated code work with PHP 7.2.0. + 2017-12-04: wsfulton [Python] Add missing checks for failures in calls to PyUnicode_AsUTF8String. Previously a seg fault could occur when passing invalid UTF8 strings (low surrogates), eg passing diff --git a/Source/Modules/php.cxx b/Source/Modules/php.cxx index dcfe4e377..b32f3c63e 100644 --- a/Source/Modules/php.cxx +++ b/Source/Modules/php.cxx @@ -372,8 +372,8 @@ public: Printf(s_header, "int error_code;\n"); Printf(s_header, "ZEND_END_MODULE_GLOBALS(%s)\n", module); Printf(s_header, "ZEND_DECLARE_MODULE_GLOBALS(%s)\n", module); - Printf(s_header, "#define SWIG_ErrorMsg() (%s_globals.error_msg)\n", module); - Printf(s_header, "#define SWIG_ErrorCode() (%s_globals.error_code)\n", module); + Printf(s_header, "#define SWIG_ErrorMsg() ZEND_MODULE_GLOBALS_ACCESSOR(%s, error_msg)\n", module); + Printf(s_header, "#define SWIG_ErrorCode() ZEND_MODULE_GLOBALS_ACCESSOR(%s, error_code)\n", module); /* The following can't go in Lib/php/phprun.swg as it uses SWIG_ErrorMsg(), etc * which has to be dynamically generated as it depends on the module name. From e86c881a70333af96694dae4310f1ba48e71dd64 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Wed, 13 Dec 2017 20:47:05 +0000 Subject: [PATCH 389/455] Fix directorout typemaps which were causing undefined behaviour when returning pointers by reference. Closes #1167 --- CHANGES.current | 4 ++++ Lib/csharp/csharp.swg | 6 ++++-- Lib/d/dswigtype.swg | 4 +++- Lib/go/go.swg | 5 +++++ Lib/java/java.swg | 6 ++++-- Lib/typemaps/swigtype.swg | 6 ++++-- 6 files changed, 24 insertions(+), 7 deletions(-) diff --git a/CHANGES.current b/CHANGES.current index ce71dcac2..331806b8f 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.0.0 (in progress) =========================== +2017-12-13: wsfulton + Issue #1167 Fix directorout typemaps which were causing undefined behaviour when + returning pointers by reference. + 2017-12-08: olly [PHP] Use ZEND_MODULE_GLOBALS_ACCESSOR to access globals - this should make the generated code work with PHP 7.2.0. diff --git a/Lib/csharp/csharp.swg b/Lib/csharp/csharp.swg index 5b539332c..e1554dcb8 100644 --- a/Lib/csharp/csharp.swg +++ b/Lib/csharp/csharp.swg @@ -857,8 +857,10 @@ SWIGINTERN const char * SWIG_UnpackData(const char *c, void *ptr, size_t sz) { %{ $result = (void *)*$1; %} %typemap(directorin) SWIGTYPE *const& %{ $input = (void *) $1; %} -%typemap(directorout, warning=SWIGWARN_TYPEMAP_DIRECTOROUT_PTR_MSG) SWIGTYPE *const& -%{ $result = ($1_ltype)&$input; %} +%typemap(directorout, warning=SWIGWARN_TYPEMAP_THREAD_UNSAFE_MSG) SWIGTYPE *const& +%{ static $*1_ltype swig_temp; + swig_temp = ($*1_ltype)$input; + $result = &swig_temp; %} %typemap(csdirectorin) SWIGTYPE *const& "($iminput == global::System.IntPtr.Zero) ? null : new $*csclassname($iminput, false)" %typemap(csdirectorout) SWIGTYPE *const& "$*csclassname.getCPtr($cscall).Handle" diff --git a/Lib/d/dswigtype.swg b/Lib/d/dswigtype.swg index 19b700052..f0d604b6f 100644 --- a/Lib/d/dswigtype.swg +++ b/Lib/d/dswigtype.swg @@ -185,7 +185,9 @@ %typemap(directorin) SWIGTYPE *const& "$input = (void *) $1;" %typemap(directorout, warning=SWIGWARN_TYPEMAP_DIRECTOROUT_PTR_MSG) SWIGTYPE *const& - "$result = ($1_ltype)&$input;" +%{ static $*1_ltype swig_temp; + swig_temp = ($*1_ltype)$input; + $result = &swig_temp; %} %typemap(ddirectorin, nativepointer="cast($dtype)$winput" ) SWIGTYPE *const& "($winput is null) ? null : new $*dclassname($winput, false)" diff --git a/Lib/go/go.swg b/Lib/go/go.swg index 3e1fab2d9..c225ed9ad 100644 --- a/Lib/go/go.swg +++ b/Lib/go/go.swg @@ -380,6 +380,11 @@ %typemap(directorout) SWIGTYPE & %{ *($&1_ltype)&$result = $input; %} +%typemap(directorout, warning=SWIGWARN_TYPEMAP_DIRECTOROUT_PTR_MSG) SWIGTYPE *const& +%{ static $*1_ltype swig_temp; + swig_temp = *($1_ltype)&$input; + $result = &swig_temp; %} + %typemap(gotype) SWIGTYPE && %{$gotypename%} diff --git a/Lib/java/java.swg b/Lib/java/java.swg index ae984313b..19e597bd9 100644 --- a/Lib/java/java.swg +++ b/Lib/java/java.swg @@ -1183,8 +1183,10 @@ Swig::LocalRefGuard $1_refguard(jenv, $input); } %{ *($1_ltype)&$result = *$1; %} %typemap(directorin,descriptor="L$packagepath/$*javaclassname;") SWIGTYPE *const& %{ *(($1_ltype)&$input) = ($*1_ltype) $1; %} -%typemap(directorout, warning=SWIGWARN_TYPEMAP_DIRECTOROUT_PTR_MSG) SWIGTYPE *const& -%{ $result = ($1_ltype)&$input; %} +%typemap(directorout, warning=SWIGWARN_TYPEMAP_THREAD_UNSAFE_MSG) SWIGTYPE *const& +%{ static $*1_ltype swig_temp; + swig_temp = *($1_ltype)&$input; + $result = &swig_temp; %} %typemap(javadirectorin) SWIGTYPE *const& "($jniinput == 0) ? null : new $*javaclassname($jniinput, false)" %typemap(javadirectorout) SWIGTYPE *const& "$*javaclassname.getCPtr($javacall)" diff --git a/Lib/typemaps/swigtype.swg b/Lib/typemaps/swigtype.swg index be684211c..723dc08bb 100644 --- a/Lib/typemaps/swigtype.swg +++ b/Lib/typemaps/swigtype.swg @@ -431,6 +431,7 @@ } /* directorout */ + #if defined(__cplusplus) && defined(%implicitconv_flag) %typemap(directorout,noblock=1,implicitconv=1) SWIGTYPE (void * swig_argp, int swig_res = 0) { swig_res = SWIG_ConvertPtr($input,&swig_argp,$&descriptor, %convertptr_flags | %implicitconv_flag); @@ -471,8 +472,9 @@ if (!SWIG_IsOK(swig_res)) { %dirout_fail(swig_res,"$type"); } - $result = %reinterpret_cast(&swig_argp, $ltype); - swig_acquire_ownership_obj(%as_voidptr(*$result), own /* & TODO: SWIG_POINTER_OWN */); + $1_ltype swig_temp = new $*1_ltype(($*1_ltype)swig_argp); + swig_acquire_ownership(swig_temp); + $result = swig_temp; } %typemap(directorfree,noblock=1,match="directorout") SWIGTYPE *const& { if (director) { From 717b7866d4e438e1ae3483f796eb07f96e246fe6 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Thu, 14 Dec 2017 07:49:56 +0000 Subject: [PATCH 390/455] Perl - Add support for missing directorfree typemaps Related to issue #1167, to free up memory when returning reference types. SWIG_Perl_AcquirePtr still needs implementing. --- CHANGES.current | 3 +++ Lib/perl5/perlrun.swg | 9 +++++++++ Source/Modules/perl5.cxx | 9 +++++++++ 3 files changed, 21 insertions(+) diff --git a/CHANGES.current b/CHANGES.current index 331806b8f..1c361fbec 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.0.0 (in progress) =========================== +2017-12-13: wsfulton + [Perl] add missing support for directorfree typemaps. + 2017-12-13: wsfulton Issue #1167 Fix directorout typemaps which were causing undefined behaviour when returning pointers by reference. diff --git a/Lib/perl5/perlrun.swg b/Lib/perl5/perlrun.swg index cc4ba446a..02714c451 100644 --- a/Lib/perl5/perlrun.swg +++ b/Lib/perl5/perlrun.swg @@ -20,6 +20,7 @@ #define SWIG_ConvertPtr(obj, pp, type, flags) SWIG_Perl_ConvertPtr(SWIG_PERL_OBJECT_CALL obj, pp, type, flags) #define SWIG_ConvertPtrAndOwn(obj, pp, type, flags,own) SWIG_Perl_ConvertPtrAndOwn(SWIG_PERL_OBJECT_CALL obj, pp, type, flags, own) #define SWIG_NewPointerObj(p, type, flags) SWIG_Perl_NewPointerObj(SWIG_PERL_OBJECT_CALL p, type, flags) +#define SWIG_AcquirePtr(ptr, src) SWIG_Perl_AcquirePtr(ptr, src) #define swig_owntype int /* for raw packed data */ @@ -229,6 +230,14 @@ SWIG_TypeProxyCheck(const char *c, swig_type_info *ty) { return 0; } +/* Acquire a pointer value */ + +SWIGRUNTIME int +SWIG_Perl_AcquirePtr(SWIG_MAYBE_PERL_OBJECT SV *sv, int own) { + /* TODO */ + return 0; +} + /* Function for getting a pointer value */ SWIGRUNTIME int diff --git a/Source/Modules/perl5.cxx b/Source/Modules/perl5.cxx index d49da695f..3212a501b 100644 --- a/Source/Modules/perl5.cxx +++ b/Source/Modules/perl5.cxx @@ -900,6 +900,15 @@ public: Printf(f->code, "%s\n", tm); } + if (director_method) { + if ((tm = Swig_typemap_lookup("directorfree", n, Swig_cresult_name(), 0))) { + Replaceall(tm, "$input", Swig_cresult_name()); + Replaceall(tm, "$result", "ST(argvi)"); + Printf(f->code, "%s\n", tm); + Delete(tm); + } + } + Printv(f->code, "XSRETURN(argvi);\n", "fail:\n", cleanup, "SWIG_croak_null();\n" "}\n" "}\n", NIL); /* Add the dXSARGS last */ From 589b7237e90405259a319de576a19bd1ae5c14e6 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Thu, 14 Dec 2017 18:58:06 +0000 Subject: [PATCH 391/455] Tweak Perl's director method's $result variable generation. Use same code as other languages - no real change in output. --- Source/Modules/perl5.cxx | 35 +++++++++++++++++------------------ 1 file changed, 17 insertions(+), 18 deletions(-) diff --git a/Source/Modules/perl5.cxx b/Source/Modules/perl5.cxx index 3212a501b..be586b4db 100644 --- a/Source/Modules/perl5.cxx +++ b/Source/Modules/perl5.cxx @@ -2138,27 +2138,26 @@ public: * if the return value is a reference or const reference, a specialized typemap must * handle it, including declaration of c_result ($result). */ - if (!is_void) { - if (!ignored_method || pure_virtual) { - if (!SwigType_isclass(returntype)) { - if (!(SwigType_ispointer(returntype) || SwigType_isreference(returntype))) { - String *construct_result = NewStringf("= SwigValueInit< %s >()", SwigType_lstr(returntype, 0)); - Wrapper_add_localv(w, "c_result", SwigType_lstr(returntype, "c_result"), construct_result, NIL); - Delete(construct_result); - } else { - Wrapper_add_localv(w, "c_result", SwigType_lstr(returntype, "c_result"), "= 0", NIL); - } + if (!is_void && (!ignored_method || pure_virtual)) { + if (!SwigType_isclass(returntype)) { + if (!(SwigType_ispointer(returntype) || SwigType_isreference(returntype))) { + String *construct_result = NewStringf("= SwigValueInit< %s >()", SwigType_lstr(returntype, 0)); + Wrapper_add_localv(w, "c_result", SwigType_lstr(returntype, "c_result"), construct_result, NIL); + Delete(construct_result); } else { - String *cres = SwigType_lstr(returntype, "c_result"); - Printf(w->code, "%s;\n", cres); - Delete(cres); + Wrapper_add_localv(w, "c_result", SwigType_lstr(returntype, "c_result"), "= 0", NIL); } + } else { + String *cres = SwigType_lstr(returntype, "c_result"); + Printf(w->code, "%s;\n", cres); + Delete(cres); } - if (!ignored_method) { - String *pres = NewStringf("SV *%s", Swig_cresult_name()); - Wrapper_add_local(w, Swig_cresult_name(), pres); - Delete(pres); - } + } + + if (!is_void && !ignored_method) { + String *pres = NewStringf("SV *%s", Swig_cresult_name()); + Wrapper_add_local(w, Swig_cresult_name(), pres); + Delete(pres); } if (ignored_method) { From a4884e45e1aa10623d03d38eaae167ca6b6eb665 Mon Sep 17 00:00:00 2001 From: Cyrille Faucheux Date: Tue, 5 Dec 2017 21:52:47 +0100 Subject: [PATCH 392/455] Do not abort when unlinking non-data ruby objects Fixes issue #1168. Remove a call to abort() (introduced by commit 0e725b5d9bd534964ae606852453df46d04037ee) made when SWIG_RubyUnlinkObjects() is called on non T_DATA objects. It can happen when the destruction of T_DATA objects is deferred: the Ruby GC first turn them to T_ZOMBIE, then calls their free method (SWIG_RubyUnlinkObjects()). --- Examples/ruby/free_function/runme.rb | 6 +++++- Lib/ruby/rubytracking.swg | 13 +++++++------ 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/Examples/ruby/free_function/runme.rb b/Examples/ruby/free_function/runme.rb index a517ed454..cf405d4cc 100644 --- a/Examples/ruby/free_function/runme.rb +++ b/Examples/ruby/free_function/runme.rb @@ -39,7 +39,11 @@ GC.start # C++ object ok = false begin - puts tiger2.get_name + # Let's stress the GC a bit, a single pass might not be enough. + 10.times { + GC.start + puts tiger2.get_name + } rescue ObjectPreviouslyDeleted => error ok = true end diff --git a/Lib/ruby/rubytracking.swg b/Lib/ruby/rubytracking.swg index 8f9f01be8..b9fb249d8 100644 --- a/Lib/ruby/rubytracking.swg +++ b/Lib/ruby/rubytracking.swg @@ -1,7 +1,7 @@ /* ----------------------------------------------------------------------------- * rubytracking.swg * - * This file contains support for tracking mappings from + * This file contains support for tracking mappings from * Ruby objects to C++ objects. This functionality is needed * to implement mark functions for Ruby's mark and sweep * garbage collector. @@ -28,7 +28,7 @@ extern "C" { #endif /* Global hash table to store Trackings from C/C++ - structs to Ruby Objects. + structs to Ruby Objects. */ static st_table* swig_ruby_trackings = NULL; @@ -42,7 +42,7 @@ SWIGRUNTIME void SWIG_RubyInitializeTrackings(void) { /* Create a hash table to store Trackings from C++ objects to Ruby objects. */ - /* Try to see if some other .so has already created a + /* Try to see if some other .so has already created a tracking hash table, which we keep hidden in an instance var in the SWIG module. This is done to allow multiple DSOs to share the same @@ -101,13 +101,14 @@ SWIGRUNTIME void SWIG_RubyRemoveTracking(void* ptr) { /* This is a helper method that unlinks a Ruby object from its underlying C++ object. This is needed if the lifetime of the - Ruby object is longer than the C++ object */ + Ruby object is longer than the C++ object. */ SWIGRUNTIME void SWIG_RubyUnlinkObjects(void* ptr) { VALUE object = SWIG_RubyInstanceFor(ptr); if (object != Qnil) { - if (TYPE(object) != T_DATA) - abort(); + // object might have the T_ZOMBIE type, but that's just + // because the GC has flagged it as such for a deferred + // destruction. Until then, it's still a T_DATA object. DATA_PTR(object) = 0; } } From 6b2bcfed0b1c8b0ed87d92ce492651c2325e067b Mon Sep 17 00:00:00 2001 From: David Avedissian Date: Wed, 27 Dec 2017 16:31:16 +0000 Subject: [PATCH 393/455] Added test case for a forward declaration in a typedef with the same name --- Examples/test-suite/common.mk | 2 ++ .../typedef_classforward_same_name_runme.java | 22 +++++++++++++++++++ .../typedef_classforward_same_name.i | 9 ++++++++ 3 files changed, 33 insertions(+) create mode 100644 Examples/test-suite/java/typedef_classforward_same_name_runme.java create mode 100644 Examples/test-suite/typedef_classforward_same_name.i diff --git a/Examples/test-suite/common.mk b/Examples/test-suite/common.mk index db9b13433..7a2136639 100644 --- a/Examples/test-suite/common.mk +++ b/Examples/test-suite/common.mk @@ -490,6 +490,7 @@ CPP_TEST_CASES += \ throw_exception \ typedef_array_member \ typedef_class \ + typedef_classforward_same_name \ typedef_funcptr \ typedef_inherit \ typedef_mptr \ @@ -676,6 +677,7 @@ C_TEST_CASES += \ string_simple \ struct_rename \ struct_initialization \ + typedef_classforward_same_name \ typedef_struct \ typemap_subst \ union_parameter \ diff --git a/Examples/test-suite/java/typedef_classforward_same_name_runme.java b/Examples/test-suite/java/typedef_classforward_same_name_runme.java new file mode 100644 index 000000000..23a06b913 --- /dev/null +++ b/Examples/test-suite/java/typedef_classforward_same_name_runme.java @@ -0,0 +1,22 @@ + +import typedef_classforward_same_name.*; + +public class typedef_classforward_same_name_runme { + + static { + try { + System.loadLibrary("typedef_classforward_same_name"); + } 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[]) { + Foo foo = new Foo(); + foo.setX(5); + if (typedef_classforward_same_name.extract(foo) == 5) { + // All good! + } + } +} \ No newline at end of file diff --git a/Examples/test-suite/typedef_classforward_same_name.i b/Examples/test-suite/typedef_classforward_same_name.i new file mode 100644 index 000000000..15e29c693 --- /dev/null +++ b/Examples/test-suite/typedef_classforward_same_name.i @@ -0,0 +1,9 @@ +%module typedef_classforward_same_name + +%inline %{ +typedef struct Foo Foo; +struct Foo { + int x; +}; +int extract(Foo* foo) { return foo->x; } +%} \ No newline at end of file From 3617e22fda7b276d727c24452250e64871d4117c Mon Sep 17 00:00:00 2001 From: David Avedissian Date: Sun, 31 Dec 2017 00:23:51 +0000 Subject: [PATCH 394/455] Fixed 'typedef class Foo Foo;' edge case by iterating through linked list. Suggested fix by wsfulton --- CHANGES.current | 5 +++++ Source/Modules/lang.cxx | 8 ++++++++ 2 files changed, 13 insertions(+) diff --git a/CHANGES.current b/CHANGES.current index 1c361fbec..3b5bb3f85 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.0.0 (in progress) =========================== +2017-12-30: davedissian + Fixed a symbol lookup issue when encountering a typedef of a symbol from the tag + namespace to the global namespace when the names are identical, such as 'typedef + struct Foo Foo;'. + 2017-12-13: wsfulton [Perl] add missing support for directorfree typemaps. diff --git a/Source/Modules/lang.cxx b/Source/Modules/lang.cxx index 1e4a6bdb6..3464d2327 100644 --- a/Source/Modules/lang.cxx +++ b/Source/Modules/lang.cxx @@ -3296,6 +3296,14 @@ Node *Language::classLookup(const SwigType *s) const { break; if (Strcmp(nodeType(n), "class") == 0) break; + Node *sibling = n; + while (sibling) { + sibling = Getattr(sibling, "csym:nextSibling"); + if (sibling && Strcmp(nodeType(sibling), "class") == 0) + break; + } + if (sibling) + break; n = parentNode(n); if (!n) break; From d1e5f1e0c87fce759b9106ebca525036149668b0 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Sat, 30 Dec 2017 17:07:15 +0000 Subject: [PATCH 395/455] Switch to using pycodestyle instead of pep8 --- Tools/travis-linux-install.sh | 2 +- configure.ac | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Tools/travis-linux-install.sh b/Tools/travis-linux-install.sh index 5704c4c28..110bd8b70 100755 --- a/Tools/travis-linux-install.sh +++ b/Tools/travis-linux-install.sh @@ -89,7 +89,7 @@ case "$SWIGLANG" in travis_retry sudo apt-get -qq install php$VER-cli php$VER-dev ;; "python") - pip install --user pep8 + pip install --user pycodestyle if [[ "$PY3" ]]; then travis_retry sudo apt-get install -qq python3-dev fi diff --git a/configure.ac b/configure.ac index 85b24e701..cd5992d02 100644 --- a/configure.ac +++ b/configure.ac @@ -895,9 +895,9 @@ else fi if test -n "$PYINCLUDE" || test -n "$PY3INCLUDE" ; then - AC_CHECK_PROGS(PEP8, pep8) + AC_CHECK_PROGS(PEP8, pycodestyle) if test -n "$PEP8"; then - AC_MSG_CHECKING(pep8 version) + AC_MSG_CHECKING(pycodestyle version) pep8_version=`$PEP8 --version 2>/dev/null` AC_MSG_RESULT($pep8_version) fi From 0b0aed6842db720d72f197f7fccd4fb96e55f550 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Sat, 30 Dec 2017 21:19:38 +0000 Subject: [PATCH 396/455] Fix pycodestyle 'E722 do not use bare except' --- Examples/python/variables/runme.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Examples/python/variables/runme.py b/Examples/python/variables/runme.py index 3388a0eba..fba485aca 100644 --- a/Examples/python/variables/runme.py +++ b/Examples/python/variables/runme.py @@ -52,14 +52,14 @@ print " Tring to set 'path'" try: example.cvar.path = "Whoa!" print "Hey, what's going on?!?! This shouldn't work" -except: +except Exception: print "Good." print " Trying to set 'status'" try: example.cvar.status = 0 print "Hey, what's going on?!?! This shouldn't work" -except: +except Exception: print "Good." From aff36823df43b31a0ef35cc5e1c0ec0eccb244f1 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Sat, 30 Dec 2017 21:37:05 +0000 Subject: [PATCH 397/455] Complete switch from pep8 to pycodestyle for Python testing --- CHANGES.current | 4 ++++ Examples/Makefile.in | 8 ++++---- Examples/test-suite/python/Makefile.in | 10 +++++----- configure.ac | 8 ++++---- 4 files changed, 17 insertions(+), 13 deletions(-) diff --git a/CHANGES.current b/CHANGES.current index 1c361fbec..ac04b3b29 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.0.0 (in progress) =========================== +2017-12-30: wsfulton + [Python] Replace pep8 with pycodestyle for checking the Python code style when + running Python tests. + 2017-12-13: wsfulton [Perl] add missing support for directorfree typemaps. diff --git a/Examples/Makefile.in b/Examples/Makefile.in index e020a659a..81697c8b2 100644 --- a/Examples/Makefile.in +++ b/Examples/Makefile.in @@ -334,8 +334,8 @@ else SWIGOPTPY3 = -py3 endif -PEP8 = @PEP8@ -PEP8_FLAGS = --ignore=E402,E501,E30,W291,W391 +PYCODESTYLE = @PYCODESTYLE@ +PYCODESTYLE_FLAGS = --ignore=E402,E501,E30,W291,W391 # ---------------------------------------------------------------- # Build a C dynamically loadable module @@ -389,8 +389,8 @@ endif PY2TO3 = @PY2TO3@ `@PY2TO3@ -l | grep -v -E "Available|import$$" | awk '{print "-f "$$0}'` python_run: $(PYSCRIPT) -ifneq (,$(PEP8)) - $(COMPILETOOL) $(PEP8) $(PEP8_FLAGS) $(PYSCRIPT) +ifneq (,$(PYCODESTYLE)) + $(COMPILETOOL) $(PYCODESTYLE) $(PYCODESTYLE_FLAGS) $(PYSCRIPT) endif env PYTHONPATH=$$PWD $(RUNTOOL) $(PYTHON) $(PYSCRIPT) $(RUNPIPE) diff --git a/Examples/test-suite/python/Makefile.in b/Examples/test-suite/python/Makefile.in index 869426569..12844e311 100644 --- a/Examples/test-suite/python/Makefile.in +++ b/Examples/test-suite/python/Makefile.in @@ -10,8 +10,8 @@ endif LANGUAGE = python PYTHON = $(PYBIN) -PEP8 = @PEP8@ -PEP8_FLAGS = --ignore=E30,E402,E501,E731,W291,W391 +PYCODESTYLE = @PYCODESTYLE@ +PYCODESTYLE_FLAGS = --ignore=E30,E402,E501,E731,W291,W391 #*_runme.py for Python 2.x, *_runme3.py for Python 3.x PY2SCRIPTSUFFIX = _runme.py @@ -141,12 +141,12 @@ py_runme = $(SCRIPTPREFIX)$*$(SCRIPTSUFFIX) py2_runme = $(SCRIPTPREFIX)$*$(PY2SCRIPTSUFFIX) py3_runme = $(SCRIPTPREFIX)$*$(PY3SCRIPTSUFFIX) -ifneq (,$(PEP8)) -check_pep8 = $(COMPILETOOL) $(PEP8) $(PEP8_FLAGS) $(SCRIPTPREFIX)$*.py +ifneq (,$(PYCODESTYLE)) +check_pep8 = $(COMPILETOOL) $(PYCODESTYLE) $(PYCODESTYLE_FLAGS) $(SCRIPTPREFIX)$*.py check_pep8_multi_cpp = \ for f in `cat $(top_srcdir)/$(EXAMPLES)/$(TEST_SUITE)/$*.list` ; do \ - $(COMPILETOOL) $(PEP8) $(PEP8_FLAGS) $$f.py; \ + $(COMPILETOOL) $(PYCODESTYLE) $(PYCODESTYLE_FLAGS) $$f.py; \ done endif diff --git a/configure.ac b/configure.ac index cd5992d02..cfc338126 100644 --- a/configure.ac +++ b/configure.ac @@ -895,11 +895,11 @@ else fi if test -n "$PYINCLUDE" || test -n "$PY3INCLUDE" ; then - AC_CHECK_PROGS(PEP8, pycodestyle) - if test -n "$PEP8"; then + AC_CHECK_PROGS(PYCODESTYLE, pycodestyle) + if test -n "$PYCODESTYLE"; then AC_MSG_CHECKING(pycodestyle version) - pep8_version=`$PEP8 --version 2>/dev/null` - AC_MSG_RESULT($pep8_version) + pycodestyle_version=`$PYCODESTYLE --version 2>/dev/null` + AC_MSG_RESULT($pycodestyle_version) fi fi From 3c30dec661a9584c2b56eaf381533ac0816ff65a Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Sat, 30 Dec 2017 21:37:56 +0000 Subject: [PATCH 398/455] Remove php5 generated files inadvertently checked in --- Examples/test-suite/php5/newobject3.php | 93 ----------------------- Examples/test-suite/php5/php_newobject3.h | 36 --------- 2 files changed, 129 deletions(-) delete mode 100644 Examples/test-suite/php5/newobject3.php delete mode 100644 Examples/test-suite/php5/php_newobject3.h diff --git a/Examples/test-suite/php5/newobject3.php b/Examples/test-suite/php5/newobject3.php deleted file mode 100644 index 21e1769d7..000000000 --- a/Examples/test-suite/php5/newobject3.php +++ /dev/null @@ -1,93 +0,0 @@ -_cPtr,$value); - $this->_pData[$var] = $value; - } - - function __get($var) { - if ($var === 'thisown') return swig_newobject3_get_newobject($this->_cPtr); - return $this->_pData[$var]; - } - - function __isset($var) { - if ($var === 'thisown') return true; - return array_key_exists($var, $this->_pData); - } - - function __construct($res=null) { - if (is_resource($res) && get_resource_type($res) === '_p_Product') { - $this->_cPtr=$res; - return; - } - $this->_cPtr=new_Product(); - } -} - -class factory { - public $_cPtr=null; - protected $_pData=array(); - - function __set($var,$value) { - if ($var === 'thisown') return swig_newobject3_alter_newobject($this->_cPtr,$value); - $this->_pData[$var] = $value; - } - - function __get($var) { - if ($var === 'thisown') return swig_newobject3_get_newobject($this->_cPtr); - return $this->_pData[$var]; - } - - function __isset($var) { - if ($var === 'thisown') return true; - return array_key_exists($var, $this->_pData); - } - - function create($id_or_name,$type=0) { - $r=factory_create($this->_cPtr,$id_or_name,$type); - if (!is_resource($r)) return $r; - return new Product($r); - } - - function __construct($res=null) { - if (is_resource($res) && get_resource_type($res) === '_p_factory') { - $this->_cPtr=$res; - return; - } - $this->_cPtr=new_factory(); - } -} - - -?> diff --git a/Examples/test-suite/php5/php_newobject3.h b/Examples/test-suite/php5/php_newobject3.h deleted file mode 100644 index 6ff30705a..000000000 --- a/Examples/test-suite/php5/php_newobject3.h +++ /dev/null @@ -1,36 +0,0 @@ -/* ---------------------------------------------------------------------------- - * This file was automatically generated by SWIG (http://www.swig.org). - * Version 4.0.0 - * - * This file is not intended to be easily readable and contains a number of - * coding conventions designed to improve portability and efficiency. Do not make - * changes to this file unless you know what you are doing--modify the SWIG - * interface file instead. - * ----------------------------------------------------------------------------- */ - -#ifndef PHP_NEWOBJECT3_H -#define PHP_NEWOBJECT3_H - -extern zend_module_entry newobject3_module_entry; -#define phpext_newobject3_ptr &newobject3_module_entry - -#ifdef PHP_WIN32 -# define PHP_NEWOBJECT3_API __declspec(dllexport) -#else -# define PHP_NEWOBJECT3_API -#endif - -#ifdef ZTS -#include "TSRM.h" -#endif - -PHP_MINIT_FUNCTION(newobject3); -PHP_MSHUTDOWN_FUNCTION(newobject3); -PHP_RINIT_FUNCTION(newobject3); -PHP_RSHUTDOWN_FUNCTION(newobject3); -PHP_MINFO_FUNCTION(newobject3); - -ZEND_NAMED_FUNCTION(_wrap_new_Product); -ZEND_NAMED_FUNCTION(_wrap_factory_create); -ZEND_NAMED_FUNCTION(_wrap_new_factory); -#endif /* PHP_NEWOBJECT3_H */ From 0beec3cf7306d7b9d6fe771012bb9421877a9a82 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Sat, 30 Dec 2017 20:56:25 +0000 Subject: [PATCH 399/455] Travis testing: use new deadsnakes repository for testing various python versions See https://github.com/deadsnakes/issues/issues/53 --- Tools/travis-linux-install.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tools/travis-linux-install.sh b/Tools/travis-linux-install.sh index 110bd8b70..e8a5e4c9c 100755 --- a/Tools/travis-linux-install.sh +++ b/Tools/travis-linux-install.sh @@ -95,7 +95,7 @@ case "$SWIGLANG" in fi WITHLANG=$SWIGLANG$PY3 if [[ "$VER" ]]; then - travis_retry sudo add-apt-repository -y ppa:fkrull/deadsnakes + travis_retry sudo add-apt-repository -y ppa:deadsnakes/ppa travis_retry sudo apt-get -qq update travis_retry sudo apt-get -qq install python${VER}-dev WITHLANG=$SWIGLANG$PY3=$SWIGLANG$VER From ce6960de9261f08bb653400555254f7dc01ca663 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Sun, 31 Dec 2017 16:25:55 +0000 Subject: [PATCH 400/455] Add more runtime typedef_classforward_same_name runtime testing --- .../java/typedef_classforward_same_name_runme.java | 12 ++++++++---- .../python/typedef_classforward_same_name_runme.py | 11 +++++++++++ Examples/test-suite/typedef_classforward_same_name.i | 10 ++++++++-- 3 files changed, 27 insertions(+), 6 deletions(-) create mode 100644 Examples/test-suite/python/typedef_classforward_same_name_runme.py diff --git a/Examples/test-suite/java/typedef_classforward_same_name_runme.java b/Examples/test-suite/java/typedef_classforward_same_name_runme.java index 23a06b913..86e713d14 100644 --- a/Examples/test-suite/java/typedef_classforward_same_name_runme.java +++ b/Examples/test-suite/java/typedef_classforward_same_name_runme.java @@ -15,8 +15,12 @@ public class typedef_classforward_same_name_runme { public static void main(String argv[]) { Foo foo = new Foo(); foo.setX(5); - if (typedef_classforward_same_name.extract(foo) == 5) { - // All good! - } + if (typedef_classforward_same_name.extractFoo(foo) != 5) + throw new RuntimeException("unexpected value"); + + Boo boo = new Boo(); + boo.setX(5); + if (typedef_classforward_same_name.extractBoo(boo) != 5) + throw new RuntimeException("unexpected value"); } -} \ No newline at end of file +} diff --git a/Examples/test-suite/python/typedef_classforward_same_name_runme.py b/Examples/test-suite/python/typedef_classforward_same_name_runme.py new file mode 100644 index 000000000..61f45fbee --- /dev/null +++ b/Examples/test-suite/python/typedef_classforward_same_name_runme.py @@ -0,0 +1,11 @@ +from typedef_classforward_same_name import * + +foo = Foo() +foo.x = 5 +if extractFoo(foo) != 5: + raise RuntimeError("unexpected value") + +boo = Boo() +boo.x = 5 +if extractBoo(boo) != 5: + raise RuntimeError("unexpected value") diff --git a/Examples/test-suite/typedef_classforward_same_name.i b/Examples/test-suite/typedef_classforward_same_name.i index 15e29c693..ad2e456f8 100644 --- a/Examples/test-suite/typedef_classforward_same_name.i +++ b/Examples/test-suite/typedef_classforward_same_name.i @@ -5,5 +5,11 @@ typedef struct Foo Foo; struct Foo { int x; }; -int extract(Foo* foo) { return foo->x; } -%} \ No newline at end of file +int extractFoo(Foo* foo) { return foo->x; } + +struct Boo { + int x; +}; +typedef struct Boo Boo; +int extractBoo(Boo* boo) { return boo->x; } +%} From cd9b7c3c34def07db975a2b706e425afc6500adb Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Thu, 4 Jan 2018 07:00:26 +0000 Subject: [PATCH 401/455] std_basic_string.i fixes - Remove python code from octave's std_basic_string.i - Correctly return an error to fix error handling when using std::basic_string in overloaded methods - issue #1171. --- Examples/test-suite/li_std_string_extra.i | 8 ++ .../python/li_std_string_extra_runme.py | 18 +++++ Lib/octave/std_basic_string.i | 47 +++--------- Lib/python/std_basic_string.i | 74 ++++++++----------- Lib/ruby/std_basic_string.i | 60 ++++++--------- Lib/scilab/std_basic_string.i | 3 +- 6 files changed, 92 insertions(+), 118 deletions(-) diff --git a/Examples/test-suite/li_std_string_extra.i b/Examples/test-suite/li_std_string_extra.i index 6bef12ff4..1fc2225ca 100644 --- a/Examples/test-suite/li_std_string_extra.i +++ b/Examples/test-suite/li_std_string_extra.i @@ -49,6 +49,14 @@ std::basic_string,std::allocator > test_value_ return x; } +std::basic_string,std::allocator > test_value_basic_overload(std::basic_string,std::allocator > x) { + return x; +} + +std::basic_string,std::allocator > test_value_basic_overload(int) { + return "int"; +} + #ifdef SWIGPYTHON_BUILTIN bool is_python_builtin() { return true; } #else 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 b65f0774a..9835eaa81 100644 --- a/Examples/test-suite/python/li_std_string_extra_runme.py +++ b/Examples/test-suite/python/li_std_string_extra_runme.py @@ -87,6 +87,24 @@ if li_std_string_extra.test_value_basic2(x) != x: if li_std_string_extra.test_value_basic3(x) != x: raise RuntimeError, "bad string mapping" +if li_std_string_extra.test_value_basic_overload(x) != x: + raise RuntimeError, "bad overload string" + +if li_std_string_extra.test_value_basic_overload(123) != "int": + raise RuntimeError, "bad overload int" + +try: + li_std_string_extra.test_value_basic_overload([x]) + raise RuntimeError, "should throw NotImplementedError" +except NotImplementedError: + pass + +try: + li_std_string_extra.test_value_basic_overload([123]) + raise RuntimeError, "should throw NotImplementedError" +except NotImplementedError: + pass + # Global variables s = "initial string" if li_std_string_extra.cvar.GlobalString2 != "global string 2": diff --git a/Lib/octave/std_basic_string.i b/Lib/octave/std_basic_string.i index 19712e8d0..01a2c34a2 100644 --- a/Lib/octave/std_basic_string.i +++ b/Lib/octave/std_basic_string.i @@ -10,24 +10,20 @@ %fragment(SWIG_AsPtr_frag(std::basic_string),"header", fragment="SWIG_AsCharPtrAndSize") { SWIGINTERN int -SWIG_AsPtr(std::basic_string)(octave_value obj, std::string **val) -{ +SWIG_AsPtr(std::basic_string)(octave_value obj, std::string **val) { if (obj.is_string()) { if (val) *val = new std::string(obj.string_value()); return SWIG_NEWOBJ; } - if (val) - error("a string is expected"); - return 0; + return SWIG_ERROR; } } %fragment(SWIG_From_frag(std::basic_string),"header", fragment="SWIG_FromCharPtrAndSize") { SWIGINTERNINLINE octave_value - SWIG_From(std::basic_string)(const std::string& s) - { + SWIG_From(std::basic_string)(const std::string& s) { return SWIG_FromCharPtrAndSize(s.data(), s.size()); } } @@ -45,41 +41,20 @@ SWIGINTERNINLINE octave_value %fragment(SWIG_AsPtr_frag(std::basic_string),"header", fragment="SWIG_AsWCharPtrAndSize") { SWIGINTERN int - SWIG_AsPtr(std::basic_string)(PyObject* obj, std::wstring **val) - { - static swig_type_info* string_info = - SWIG_TypeQuery("std::basic_string *"); - std::wstring *vptr; - if (SWIG_ConvertPtr(obj, (void**)&vptr, string_info, 0) == SWIG_OK) { - if (val) *val = vptr; - return SWIG_OLDOBJ; - } else { - PyErr_Clear(); - wchar_t *buf = 0 ; size_t size = 0; int alloc = 0; - if (SWIG_AsWCharPtrAndSize(obj, &buf, &size, &alloc) == SWIG_OK) { - if (buf) { - if (val) *val = new std::wstring(buf, size - 1); - if (alloc == SWIG_NEWOBJ) %delete_array(buf); - return SWIG_NEWOBJ; - } - } else { - PyErr_Clear(); - } - if (val) { - SWIG_PYTHON_THREAD_BEGIN_BLOCK; - PyErr_SetString(PyExc_TypeError,"a wstring is expected"); - SWIG_PYTHON_THREAD_END_BLOCK; - } - return 0; - } +SWIG_AsPtr(std::basic_string)(octave_value obj, std::wstring **val) { + if (obj.is_string()) { + if (val) + *val = new std::wstring(obj.string_value()); + return SWIG_NEWOBJ; } + return SWIG_ERROR; +} } %fragment(SWIG_From_frag(std::basic_string),"header", fragment="SWIG_FromWCharPtrAndSize") { SWIGINTERNINLINE PyObject* - SWIG_From(std::basic_string)(const std::wstring& s) - { + SWIG_From(std::basic_string)(const std::wstring& s) { return SWIG_FromWCharPtrAndSize(s.data(), s.size()); } } diff --git a/Lib/python/std_basic_string.i b/Lib/python/std_basic_string.i index 7d3366db5..e3f524dbd 100644 --- a/Lib/python/std_basic_string.i +++ b/Lib/python/std_basic_string.i @@ -9,41 +9,34 @@ %fragment(SWIG_AsPtr_frag(std::basic_string),"header", fragment="SWIG_AsCharPtrAndSize") { SWIGINTERN int -SWIG_AsPtr(std::basic_string)(PyObject* obj, std::string **val) -{ - static swig_type_info* string_info = - SWIG_TypeQuery("std::basic_string *"); - std::string *vptr; - if (SWIG_ConvertPtr(obj, (void**)&vptr, string_info, 0) == SWIG_OK) { +SWIG_AsPtr(std::basic_string)(PyObject* obj, std::string **val) { + static swig_type_info* string_info = SWIG_TypeQuery("std::basic_string *"); + std::string *vptr; + if (SWIG_IsOK(SWIG_ConvertPtr(obj, (void**)&vptr, string_info, 0))) { if (val) *val = vptr; return SWIG_OLDOBJ; } else { PyErr_Clear(); char* buf = 0 ; size_t size = 0; int alloc = 0; - if (SWIG_AsCharPtrAndSize(obj, &buf, &size, &alloc) == SWIG_OK) { + if (SWIG_IsOK(SWIG_AsCharPtrAndSize(obj, &buf, &size, &alloc))) { if (buf) { if (val) *val = new std::string(buf, size - 1); if (alloc == SWIG_NEWOBJ) %delete_array(buf); return SWIG_NEWOBJ; + } else { + if (val) *val = 0; + return SWIG_OLDOBJ; } - } else { - PyErr_Clear(); - } - if (val) { - SWIG_PYTHON_THREAD_BEGIN_BLOCK; - PyErr_SetString(PyExc_TypeError,"a string is expected"); - SWIG_PYTHON_THREAD_END_BLOCK; } - return 0; + return SWIG_ERROR; } -} +} } %fragment(SWIG_From_frag(std::basic_string),"header", fragment="SWIG_FromCharPtrAndSize") { SWIGINTERNINLINE PyObject* - SWIG_From(std::basic_string)(const std::string& s) - { + SWIG_From(std::basic_string)(const std::string& s) { return SWIG_FromCharPtrAndSize(s.data(), s.size()); } } @@ -59,41 +52,34 @@ SWIGINTERNINLINE PyObject* %fragment(SWIG_AsPtr_frag(std::basic_string),"header", fragment="SWIG_AsWCharPtrAndSize") { SWIGINTERN int - SWIG_AsPtr(std::basic_string)(PyObject* obj, std::wstring **val) - { - static swig_type_info* string_info = - SWIG_TypeQuery("std::basic_string *"); - std::wstring *vptr; - if (SWIG_ConvertPtr(obj, (void**)&vptr, string_info, 0) == SWIG_OK) { - if (val) *val = vptr; - return SWIG_OLDOBJ; - } else { - PyErr_Clear(); - wchar_t *buf = 0 ; size_t size = 0; int alloc = 0; - if (SWIG_AsWCharPtrAndSize(obj, &buf, &size, &alloc) == SWIG_OK) { - if (buf) { - if (val) *val = new std::wstring(buf, size - 1); - if (alloc == SWIG_NEWOBJ) %delete_array(buf); - return SWIG_NEWOBJ; - } +SWIG_AsPtr(std::basic_string)(PyObject* obj, std::wstring **val) { + static swig_type_info* string_info = SWIG_TypeQuery("std::basic_string *"); + std::wstring *vptr; + if (SWIG_IsOK(SWIG_ConvertPtr(obj, (void**)&vptr, string_info, 0))) { + if (val) *val = vptr; + return SWIG_OLDOBJ; + } else { + PyErr_Clear(); + wchar_t *buf = 0 ; size_t size = 0; int alloc = 0; + if (SWIG_IsOK(SWIG_AsWCharPtrAndSize(obj, &buf, &size, &alloc))) { + if (buf) { + if (val) *val = new std::wstring(buf, size - 1); + if (alloc == SWIG_NEWOBJ) %delete_array(buf); + return SWIG_NEWOBJ; } else { - PyErr_Clear(); - } - if (val) { - SWIG_PYTHON_THREAD_BEGIN_BLOCK; - PyErr_SetString(PyExc_TypeError,"a wstring is expected"); - SWIG_PYTHON_THREAD_END_BLOCK; + if (val) *val = 0; + return SWIG_OLDOBJ; } - return 0; } + return SWIG_ERROR; } } +} %fragment(SWIG_From_frag(std::basic_string),"header", fragment="SWIG_FromWCharPtrAndSize") { SWIGINTERNINLINE PyObject* - SWIG_From(std::basic_string)(const std::wstring& s) - { + SWIG_From(std::basic_string)(const std::wstring& s) { return SWIG_FromWCharPtrAndSize(s.data(), s.size()); } } diff --git a/Lib/ruby/std_basic_string.i b/Lib/ruby/std_basic_string.i index 4435b220d..ba13ba764 100644 --- a/Lib/ruby/std_basic_string.i +++ b/Lib/ruby/std_basic_string.i @@ -13,36 +13,30 @@ %fragment(SWIG_AsPtr_frag(std::basic_string),"header", fragment="SWIG_AsCharPtrAndSize") { SWIGINTERN int -SWIG_AsPtr(std::basic_string)(VALUE obj, std::string **val) -{ - static swig_type_info* string_info = - SWIG_TypeQuery("std::basic_string *"); - std::string *vptr; - if (SWIG_ConvertPtr(obj, (void**)&vptr, string_info, 0) == SWIG_OK) { +SWIG_AsPtr(std::basic_string)(VALUE obj, std::string **val) { + static swig_type_info* string_info = SWIG_TypeQuery("std::basic_string *"); + std::string *vptr; + if (SWIG_IsOK(SWIG_ConvertPtr(obj, (void**)&vptr, string_info, 0))) { if (val) *val = vptr; return SWIG_OLDOBJ; } else { char* buf = 0 ; size_t size = 0; int alloc = 0; - if (SWIG_AsCharPtrAndSize(obj, &buf, &size, &alloc) == SWIG_OK) { + if (SWIG_IsOK(SWIG_AsCharPtrAndSize(obj, &buf, &size, &alloc))) { if (buf) { if (val) *val = new std::string(buf, size - 1); if (alloc == SWIG_NEWOBJ) %delete_array(buf); return SWIG_NEWOBJ; } } - if (val) { - rb_raise( rb_eTypeError, "a string is expected"); - } - return 0; + return SWIG_ERROR; } -} +} } %fragment(SWIG_From_frag(std::basic_string),"header", fragment="SWIG_FromCharPtrAndSize") { SWIGINTERNINLINE VALUE - SWIG_From(std::basic_string)(const std::string& s) - { + SWIG_From(std::basic_string)(const std::string& s) { return SWIG_FromCharPtrAndSize(s.data(), s.size()); } } @@ -65,36 +59,30 @@ SWIGINTERNINLINE VALUE %fragment(SWIG_AsPtr_frag(std::basic_string),"header", fragment="SWIG_AsWCharPtrAndSize") { SWIGINTERN int - SWIG_AsPtr(std::basic_string)(VALUE obj, std::wstring **val) - { - static swig_type_info* string_info = - SWIG_TypeQuery("std::basic_string *"); - std::wstring *vptr; - if (SWIG_ConvertPtr(obj, (void**)&vptr, string_info, 0) == SWIG_OK) { - if (val) *val = vptr; - return SWIG_OLDOBJ; - } else { - wchar_t *buf = 0 ; size_t size = 0; int alloc = 0; - if (SWIG_AsWCharPtrAndSize(obj, &buf, &size, &alloc) == SWIG_OK) { - if (buf) { - if (val) *val = new std::wstring(buf, size - 1); - if (alloc == SWIG_NEWOBJ) %delete_array(buf); - return SWIG_NEWOBJ; - } +SWIG_AsPtr(std::basic_string)(VALUE obj, std::wstring **val) { + static swig_type_info* string_info = SWIG_TypeQuery("std::basic_string *"); + std::wstring *vptr; + if (SWIG_IsOK(SWIG_ConvertPtr(obj, (void**)&vptr, string_info, 0))) { + if (val) *val = vptr; + return SWIG_OLDOBJ; + } else { + wchar_t *buf = 0 ; size_t size = 0; int alloc = 0; + if (SWIG_IsOK(SWIG_AsWCharPtrAndSize(obj, &buf, &size, &alloc))) { + if (buf) { + if (val) *val = new std::wstring(buf, size - 1); + if (alloc == SWIG_NEWOBJ) %delete_array(buf); + return SWIG_NEWOBJ; } - if (val) { - rb_raise( rb_eTypeError, "a string is expected"); - } - return 0; } + return SWIG_ERROR; } } +} %fragment(SWIG_From_frag(std::basic_string),"header", fragment="SWIG_FromWCharPtrAndSize") { SWIGINTERNINLINE VALUE - SWIG_From(std::basic_string)(const std::wstring& s) - { + SWIG_From(std::basic_string)(const std::wstring& s) { return SWIG_FromWCharPtrAndSize(s.data(), s.size()); } } diff --git a/Lib/scilab/std_basic_string.i b/Lib/scilab/std_basic_string.i index 43b660db6..b57353816 100644 --- a/Lib/scilab/std_basic_string.i +++ b/Lib/scilab/std_basic_string.i @@ -21,8 +21,7 @@ SWIG_AsPtr_dec(std::basic_string)(int _iVar, std::basic_string **_ps delete[] buf; } return SWIG_NEWOBJ; - } - else { + } else { if (_pstValue) { *_pstValue = NULL; } From ef378407d064142672ccb55cbff47723a14f162c Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Fri, 5 Jan 2018 07:58:25 +0000 Subject: [PATCH 402/455] Fix parsing of default argument expressions containing ->. --- CHANGES.current | 4 ++++ Examples/test-suite/common.mk | 1 + Source/CParse/parser.y | 30 ++++++++++++++++++++++++++++-- 3 files changed, 33 insertions(+), 2 deletions(-) diff --git a/CHANGES.current b/CHANGES.current index ac04b3b29..5e7fbbf6e 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.0.0 (in progress) =========================== +2018-01-05: wsfulton + Fix default arguments using expressions containing -> syntax error. Problem reported on + swig-user mailing list. + 2017-12-30: wsfulton [Python] Replace pep8 with pycodestyle for checking the Python code style when running Python tests. diff --git a/Examples/test-suite/common.mk b/Examples/test-suite/common.mk index db9b13433..d798a6853 100644 --- a/Examples/test-suite/common.mk +++ b/Examples/test-suite/common.mk @@ -164,6 +164,7 @@ CPP_TEST_CASES += \ cpp_typedef \ curiously_recurring_template_pattern \ default_args \ + default_arg_expressions \ default_arg_values \ default_constructor \ defvalue_constructor \ diff --git a/Source/CParse/parser.y b/Source/CParse/parser.y index 857cecd0e..0c8d95ecd 100644 --- a/Source/CParse/parser.y +++ b/Source/CParse/parser.y @@ -1604,7 +1604,7 @@ static String *add_qualifier_to_declarator(SwigType *type, SwigType *qualifier) %type type rawtype type_right anon_bitfield_type decltype ; %type base_list inherit raw_inherit; %type definetype def_args etype default_delete deleted_definition explicit_default; -%type expr exprnum exprcompound valexpr; +%type expr exprnum exprcompound valexpr exprmem; %type ename ; %type less_valparms_greater; %type type_qualifier; @@ -6266,7 +6266,33 @@ expr : valexpr { $$ = $1; } } ; -valexpr : exprnum { $$ = $1; } +/* simple member access expressions */ +exprmem : ID ARROW ID { + $$.val = NewStringf("%s->%s", $1, $3); + $$.type = 0; + } + | exprmem ARROW ID { + $$ = $1; + Printf($$.val, "->%s", $3); + } +/* This generates a shift-reduce + | ID PERIOD ID { + $$.val = NewStringf("%s.%s", $1, $3); + $$.type = 0; + } +*/ + | exprmem PERIOD ID { + $$ = $1; + Printf($$.val, ".%s", $3); + } + ; + +valexpr : exprnum { + $$ = $1; + } + | exprmem { + $$ = $1; + } | string { $$.val = $1; $$.type = T_STRING; From aef25cff0cd3fc1bbae1a8d26825fe5f80fce770 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Fri, 5 Jan 2018 18:31:48 +0000 Subject: [PATCH 403/455] Add missing default_arg_expressions.i testcase --- Examples/test-suite/default_arg_expressions.i | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 Examples/test-suite/default_arg_expressions.i diff --git a/Examples/test-suite/default_arg_expressions.i b/Examples/test-suite/default_arg_expressions.i new file mode 100644 index 000000000..ca2a27e33 --- /dev/null +++ b/Examples/test-suite/default_arg_expressions.i @@ -0,0 +1,30 @@ +%module default_arg_expressions + +%warnfilter(SWIGWARN_TYPEMAP_SWIGTYPELEAK_MSG) ptr; +%warnfilter(SWIGWARN_TYPEMAP_SWIGTYPELEAK_MSG) UsdGeomTokensPtr; +%immutable UsdGeomTokens; + +%inline %{ +struct Numbers { + int val; + int *ptr; + Numbers() : val(), ptr(&val) {} +}; +struct TfToken { + Numbers val; + Numbers *ptr; + TfToken() : val(), ptr(&val) {} +}; +struct Tokens { + const TfToken face; + const TfToken *pface; + Tokens() : face(), pface(&face) {} +}; +static Tokens UsdGeomTokens; +static Tokens *UsdGeomTokensPtr = &UsdGeomTokens; +void CreateMaterialBindSubset1(const Tokens &elementType = UsdGeomTokens) {} +void CreateMaterialBindSubset2(int num = UsdGeomTokensPtr->pface->val.val) {} +void CreateMaterialBindSubset3(int num = UsdGeomTokensPtr->pface->ptr->val) {} +void CreateMaterialBindSubset4(int num = UsdGeomTokensPtr->face.val.val) {} +//void CreateMaterialBindSubset5(int num = UsdGeomTokens.face.val.val) {} +%} From 830422a87b29bc47ad5167d52d56f281736ddaf6 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Mon, 1 Jan 2018 23:44:43 +0000 Subject: [PATCH 404/455] Fix Makefile and skip testing python-2.4 for import_packages test --- Examples/python/import_packages/Makefile | 10 +++++----- Examples/python/import_packages/from_init1/runme.py | 4 ++++ Examples/python/import_packages/from_init2/runme.py | 4 ++++ Examples/python/import_packages/from_init3/runme.py | 4 ++++ .../python/import_packages/relativeimport1/runme.py | 4 ++++ .../python/import_packages/relativeimport2/runme.py | 4 ++++ .../python/import_packages/relativeimport3/runme.py | 4 ++++ Examples/python/import_packages/split_modules/Makefile | 8 ++++---- 8 files changed, 33 insertions(+), 9 deletions(-) diff --git a/Examples/python/import_packages/Makefile b/Examples/python/import_packages/Makefile index f428d6f5c..a70c97e8b 100644 --- a/Examples/python/import_packages/Makefile +++ b/Examples/python/import_packages/Makefile @@ -18,22 +18,22 @@ import_packages_subdirs = \ check: build if test "x$(SRCDIR)" != x; then \ for file in `cd $(SRCDIR) && find . -type f -name "*.py"`; do \ - mkdir -p `dirname $$file`; \ + mkdir -p `dirname $$file` \ cp "${SRCDIR}$$file" "$$file" || exit 1; \ done; \ fi; \ for s in $(import_packages_subdirs); do \ - (cd $$s && $(MAKE) check); \ + (cd $$s && $(MAKE) check) || exit 1; \ done build: for s in $(import_packages_subdirs); do \ - (cd $$s && $(MAKE) SWIGOPT='$(SWIGOPT)' LIBS='$(LIBS)' build); \ + (cd $$s && $(MAKE) SWIGOPT='$(SWIGOPT)' LIBS='$(LIBS)' build) || exit 1; \ done static: for s in $(import_packages_subdirs); do \ - (cd $$s && $(MAKE) SWIGOPT='$(SWIGOPT)' LIBS='$(LIBS)' static); \ + (cd $$s && $(MAKE) SWIGOPT='$(SWIGOPT)' LIBS='$(LIBS)' static) || exit 1; \ done clean: @@ -44,5 +44,5 @@ clean: done; \ fi; \ for s in $(import_packages_subdirs); do \ - (cd $$s && $(MAKE) clean); \ + (cd $$s && $(MAKE) clean) || exit 1; \ done diff --git a/Examples/python/import_packages/from_init1/runme.py b/Examples/python/import_packages/from_init1/runme.py index dda397487..424e9ca44 100644 --- a/Examples/python/import_packages/from_init1/runme.py +++ b/Examples/python/import_packages/from_init1/runme.py @@ -5,6 +5,10 @@ import os.path testname = os.path.basename(os.path.dirname(os.path.abspath(__file__))) print "Testing " + testname + " - %module(package=...) + python 'import' in __init__.py" +if sys.version_info < (2, 5): + print " Skipping test as Python version is < 2.5 and does not support relative import syntax: 'from . import x'" + sys.exit(0) + if sys.version_info < (3, 0): import py2.pkg2 print " Finished importing py2.pkg2" diff --git a/Examples/python/import_packages/from_init2/runme.py b/Examples/python/import_packages/from_init2/runme.py index dda397487..424e9ca44 100644 --- a/Examples/python/import_packages/from_init2/runme.py +++ b/Examples/python/import_packages/from_init2/runme.py @@ -5,6 +5,10 @@ import os.path testname = os.path.basename(os.path.dirname(os.path.abspath(__file__))) print "Testing " + testname + " - %module(package=...) + python 'import' in __init__.py" +if sys.version_info < (2, 5): + print " Skipping test as Python version is < 2.5 and does not support relative import syntax: 'from . import x'" + sys.exit(0) + if sys.version_info < (3, 0): import py2.pkg2 print " Finished importing py2.pkg2" diff --git a/Examples/python/import_packages/from_init3/runme.py b/Examples/python/import_packages/from_init3/runme.py index dda397487..424e9ca44 100644 --- a/Examples/python/import_packages/from_init3/runme.py +++ b/Examples/python/import_packages/from_init3/runme.py @@ -5,6 +5,10 @@ import os.path testname = os.path.basename(os.path.dirname(os.path.abspath(__file__))) print "Testing " + testname + " - %module(package=...) + python 'import' in __init__.py" +if sys.version_info < (2, 5): + print " Skipping test as Python version is < 2.5 and does not support relative import syntax: 'from . import x'" + sys.exit(0) + if sys.version_info < (3, 0): import py2.pkg2 print " Finished importing py2.pkg2" diff --git a/Examples/python/import_packages/relativeimport1/runme.py b/Examples/python/import_packages/relativeimport1/runme.py index 997476b1d..5b1b5f45a 100644 --- a/Examples/python/import_packages/relativeimport1/runme.py +++ b/Examples/python/import_packages/relativeimport1/runme.py @@ -5,6 +5,10 @@ import os.path testname = os.path.basename(os.path.dirname(os.path.abspath(__file__))) print "Testing " + testname + " - %module(package=...) with -relativeimport" +if sys.version_info < (2, 5): + print " Skipping test as Python version is < 2.5 and does not support relative import syntax: 'from . import x'" + sys.exit(0) + if sys.version_info < (3, 0): import py2.pkg2.bar print " Finished importing py2.pkg2.bar" diff --git a/Examples/python/import_packages/relativeimport2/runme.py b/Examples/python/import_packages/relativeimport2/runme.py index 9789afc18..9d1a05ec8 100644 --- a/Examples/python/import_packages/relativeimport2/runme.py +++ b/Examples/python/import_packages/relativeimport2/runme.py @@ -5,6 +5,10 @@ import os.path testname = os.path.basename(os.path.dirname(os.path.abspath(__file__))) print "Testing " + testname + " - %module(package=...) + python 'import' in __init__.py" +if sys.version_info < (2, 5): + print " Skipping test as Python version is < 2.5 and does not support relative import syntax: 'from . import x'" + sys.exit(0) + if sys.version_info < (3, 0): import py2.pkg2.bar print " Finished importing py2.pkg2.bar" diff --git a/Examples/python/import_packages/relativeimport3/runme.py b/Examples/python/import_packages/relativeimport3/runme.py index 997476b1d..5b1b5f45a 100644 --- a/Examples/python/import_packages/relativeimport3/runme.py +++ b/Examples/python/import_packages/relativeimport3/runme.py @@ -5,6 +5,10 @@ import os.path testname = os.path.basename(os.path.dirname(os.path.abspath(__file__))) print "Testing " + testname + " - %module(package=...) with -relativeimport" +if sys.version_info < (2, 5): + print " Skipping test as Python version is < 2.5 and does not support relative import syntax: 'from . import x'" + sys.exit(0) + if sys.version_info < (3, 0): import py2.pkg2.bar print " Finished importing py2.pkg2.bar" diff --git a/Examples/python/import_packages/split_modules/Makefile b/Examples/python/import_packages/split_modules/Makefile index 65d635bb7..9eaaabd32 100644 --- a/Examples/python/import_packages/split_modules/Makefile +++ b/Examples/python/import_packages/split_modules/Makefile @@ -6,21 +6,21 @@ subdirs = vanilla vanilla_split check: build for s in $(subdirs); do \ - (cd $$s && $(MAKE) check); \ + (cd $$s && $(MAKE) check) || exit 1; \ done build: for s in $(subdirs); do \ - (cd $$s && $(MAKE) SWIGOPT='$(SWIGOPT)' LIBS='$(LIBS)' build); \ + (cd $$s && $(MAKE) SWIGOPT='$(SWIGOPT)' LIBS='$(LIBS)' build) || exit 1; \ done static: for s in $(subdirs); do \ - (cd $$s && $(MAKE) SWIGOPT='$(SWIGOPT)' LIBS='$(LIBS)' static); \ + (cd $$s && $(MAKE) SWIGOPT='$(SWIGOPT)' LIBS='$(LIBS)' static) || exit 1; \ done clean: $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' python_clean for s in $(subdirs); do \ - (cd $$s && $(MAKE) clean); \ + (cd $$s && $(MAKE) clean) || exit 1; \ done From b0c910ac96c56a11a140ec24fbf12c976d43ebff Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Sat, 6 Jan 2018 23:12:52 +0000 Subject: [PATCH 405/455] Fix out of source import_packages Makefile --- Examples/python/import_packages/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Examples/python/import_packages/Makefile b/Examples/python/import_packages/Makefile index a70c97e8b..e6c07fe75 100644 --- a/Examples/python/import_packages/Makefile +++ b/Examples/python/import_packages/Makefile @@ -18,7 +18,7 @@ import_packages_subdirs = \ check: build if test "x$(SRCDIR)" != x; then \ for file in `cd $(SRCDIR) && find . -type f -name "*.py"`; do \ - mkdir -p `dirname $$file` \ + mkdir -p `dirname $$file`; \ cp "${SRCDIR}$$file" "$$file" || exit 1; \ done; \ fi; \ From 3066f8950c0dacdadec2c0119d0d7042a8f7e221 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Sat, 6 Jan 2018 23:19:04 +0000 Subject: [PATCH 406/455] Minor tweaks in import_packages Makefile --- Examples/python/import_packages/Makefile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Examples/python/import_packages/Makefile b/Examples/python/import_packages/Makefile index e6c07fe75..2857866d4 100644 --- a/Examples/python/import_packages/Makefile +++ b/Examples/python/import_packages/Makefile @@ -12,7 +12,7 @@ import_packages_subdirs = \ relativeimport2 \ relativeimport3 \ split_modules \ - namespace_pkg + namespace_pkg \ check: build @@ -21,7 +21,7 @@ check: build mkdir -p `dirname $$file`; \ cp "${SRCDIR}$$file" "$$file" || exit 1; \ done; \ - fi; \ + fi for s in $(import_packages_subdirs); do \ (cd $$s && $(MAKE) check) || exit 1; \ done @@ -42,7 +42,7 @@ clean: for file in `cd $(SRCDIR) && find . -type f -name "*.py"`; do \ rm -f "$$file" || exit 1; \ done; \ - fi; \ + fi for s in $(import_packages_subdirs); do \ (cd $$s && $(MAKE) clean) || exit 1; \ done From 0d588d19ade9f1b8445aef8a1179c01a68f54715 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Sun, 7 Jan 2018 00:57:23 +0000 Subject: [PATCH 407/455] Fix out of source clean target in import_packages Makefile --- .../import_packages/split_modules/vanilla_split/Makefile | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Examples/python/import_packages/split_modules/vanilla_split/Makefile b/Examples/python/import_packages/split_modules/vanilla_split/Makefile index c322b5aec..5d1c3521c 100644 --- a/Examples/python/import_packages/split_modules/vanilla_split/Makefile +++ b/Examples/python/import_packages/split_modules/vanilla_split/Makefile @@ -19,4 +19,6 @@ static: clean: $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' TARGET='foo' python_clean - cd pkg1 && $(MAKE) -f $(TOP)/../Makefile SRCDIR='$(SRCDIR)' TARGET='foo' python_clean + if test -d pkg1; then \ + cd pkg1 && $(MAKE) -f $(TOP)/../Makefile SRCDIR='$(SRCDIR)' TARGET='foo' python_clean; \ + fi From 49af1907b82be03ee4848b415564bc1f1e26e6bd Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Fri, 12 Jan 2018 07:34:32 +0000 Subject: [PATCH 408/455] Add missing Java throws clause for interfaces when using the %interface family of macros. Fixes #1156. --- CHANGES.current | 4 ++++ .../test-suite/java/java_throws_runme.java | 22 +++++++++++++++++++ Examples/test-suite/java_throws.i | 17 ++++++++++++++ Source/Modules/java.cxx | 7 ++++-- 4 files changed, 48 insertions(+), 2 deletions(-) diff --git a/CHANGES.current b/CHANGES.current index f39960bc3..0aad216de 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.0.0 (in progress) =========================== +2018-01-12: wsfulton + [Java] Fix issue #1156. Add missing throws clause for interfaces when using the + %interface family of macros. + 2018-01-05: wsfulton Fix default arguments using expressions containing -> syntax error. Problem reported on swig-user mailing list. diff --git a/Examples/test-suite/java/java_throws_runme.java b/Examples/test-suite/java/java_throws_runme.java index 0365b69ed..16eab7cad 100644 --- a/Examples/test-suite/java/java_throws_runme.java +++ b/Examples/test-suite/java/java_throws_runme.java @@ -93,6 +93,28 @@ public class java_throws_runme { if (!pass) throw new RuntimeException("Test 6 failed"); + // Interface function + pass = false; + try { + InterfaceTestImpl iti = new InterfaceTestImpl(); + iti.imethod(true); + } + catch (MyException e) { pass = true; } + + if (!pass) + throw new RuntimeException("Test interface 1 failed"); + + pass = false; + try { + InterfaceTestImpl iti = new InterfaceTestImpl(); + iti.imethod(false); + pass = true; + } + catch (MyException e) { pass = false; } + + if (!pass) + throw new RuntimeException("Test interface 2 failed"); + // Global function pass = false; try { diff --git a/Examples/test-suite/java_throws.i b/Examples/test-suite/java_throws.i index c628a45e6..875bce0ff 100644 --- a/Examples/test-suite/java_throws.i +++ b/Examples/test-suite/java_throws.i @@ -135,6 +135,23 @@ JAVAEXCEPTION(FeatureTest::staticMethod) }; %} +%include +%interface_impl(InterfaceTest); +JAVAEXCEPTION(imethod) + +%inline %{ + struct InterfaceTest { + virtual void imethod(bool raise) = 0; + }; + + struct InterfaceTestImpl : InterfaceTest { + void imethod(bool raise) { + if (raise) + throw MyException("raise message"); + } + }; +%} + // Mixing except feature and typemaps when both generate a class for the throws clause %typemap(in, throws="ClassNotFoundException") int both { $1 = (int)$input; diff --git a/Source/Modules/java.cxx b/Source/Modules/java.cxx index f759aaf5d..d2b25426a 100644 --- a/Source/Modules/java.cxx +++ b/Source/Modules/java.cxx @@ -2544,8 +2544,6 @@ public: Printf(imcall, ")"); Printf(function_code, ")"); - if (is_interface) - Printf(interface_class_code, ");\n"); // Transform return type used in JNI function (in intermediary class) to type used in Java wrapper function (in proxy class) if ((tm = Swig_typemap_lookup("javaout", n, "", 0))) { @@ -2603,6 +2601,11 @@ public: Swig_warning(WARN_JAVA_TYPEMAP_JAVAOUT_UNDEF, input_file, line_number, "No javaout typemap defined for %s\n", SwigType_str(t, 0)); } + if (is_interface) { + Printf(interface_class_code, ")"); + generateThrowsClause(n, interface_class_code); + Printf(interface_class_code, ";\n"); + } generateThrowsClause(n, function_code); Printf(function_code, " %s\n\n", tm ? (const String *) tm : empty_string); Printv(proxy_class_code, function_code, NIL); From 368cd3b52c8a17dd829ac42481a1901b449f9a60 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Fri, 12 Jan 2018 18:26:47 +0000 Subject: [PATCH 409/455] Add ToArray test for C# std::vector wrapper --- CHANGES.current | 3 +++ Examples/test-suite/csharp/li_std_vector_runme.cs | 11 +++++++++++ Lib/csharp/std_vector.i | 2 +- 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/CHANGES.current b/CHANGES.current index 0aad216de..07ab418cb 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.0.0 (in progress) =========================== +2018-01-12: Liryna + [C#] Patch #1128. Add ToArray function to std::vector wrappers. + 2018-01-12: wsfulton [Java] Fix issue #1156. Add missing throws clause for interfaces when using the %interface family of macros. diff --git a/Examples/test-suite/csharp/li_std_vector_runme.cs b/Examples/test-suite/csharp/li_std_vector_runme.cs index 453faa6c1..0c6211ca5 100644 --- a/Examples/test-suite/csharp/li_std_vector_runme.cs +++ b/Examples/test-suite/csharp/li_std_vector_runme.cs @@ -177,6 +177,17 @@ public class li_std_vector_runme { if (doubleArray[i] != dvCopy[i]) throw new Exception("Copy constructor failed, index:" + i); } + if (dvCopy.Count != doubleArray.Length) + throw new Exception("Copy constructor lengths mismatch"); + + // ToArray test + double[] dvArray = dv.ToArray(); + for (int i=0; i Date: Tue, 28 Nov 2017 21:43:24 -0600 Subject: [PATCH 410/455] Add option file support Arguments may be passed using an option file prefixed with the '@' character. Processing of option files is the same as for the same feature in gcc. --- Source/Modules/main.cxx | 4 ++ Source/Modules/swigmain.cxx | 82 ++++++++++++++++++++++++++++++++++++- 2 files changed, 85 insertions(+), 1 deletion(-) diff --git a/Source/Modules/main.cxx b/Source/Modules/main.cxx index 9822b6af7..c7ae02625 100644 --- a/Source/Modules/main.cxx +++ b/Source/Modules/main.cxx @@ -159,6 +159,10 @@ is equivalent to: \n\ \n\ $ swig -Wall -python interface.i \n\ \n\ +Arguments may also be passed in a file, separated by whitespace. For example:\n\ +\n\ + $ echo \"-Wall -python interface.i\" > args.txt\n\ + $ swig @args.txt\n\ \n"; // Local variables diff --git a/Source/Modules/swigmain.cxx b/Source/Modules/swigmain.cxx index b49fe909a..f72525b6f 100644 --- a/Source/Modules/swigmain.cxx +++ b/Source/Modules/swigmain.cxx @@ -119,7 +119,8 @@ static swig_module modules[] = { void SWIG_merge_envopt(const char *env, int oargc, char *oargv[], int *nargc, char ***nargv) { if (!env) { *nargc = oargc; - *nargv = oargv; + *nargv = (char **)malloc(sizeof(char *) * (oargc + 1)); + memcpy(*nargv, oargv, sizeof(char *) * (oargc + 1)); return; } @@ -153,6 +154,84 @@ void SWIG_merge_envopt(const char *env, int oargc, char *oargv[], int *nargc, ch *nargv = argv; } +static void insert_option(int *argc, char ***argv, int index, char const *start, char const *end) { + int new_argc = *argc; + char **new_argv = *argv; + size_t option_len = end - start; + + // Preserve the NULL pointer at argv[argc] + new_argv = (char **)realloc(new_argv, (new_argc + 2) * sizeof(char *)); + memmove(&new_argv[index + 1], &new_argv[index], sizeof(char *) * (new_argc + 1 - index)); + new_argc++; + + new_argv[index] = (char *)malloc(option_len + 1); + memcpy(new_argv[index], start, option_len); + new_argv[index][option_len] = '\0'; + + *argc = new_argc; + *argv = new_argv; +} + +static void merge_options_files(int *argc, char ***argv) { + static const int BUFFER_SIZE = 4096; + char buffer[BUFFER_SIZE]; + int i; + int insert; + char **new_argv = *argv; + int new_argc = *argc; + FILE *f; + + i = 1; + while (i < new_argc) { + if (new_argv[i] && new_argv[i][0] == '@' && (f = fopen(&new_argv[i][1], "r"))) { + char c; + char *b; + char *be = &buffer[BUFFER_SIZE]; + int quote = 0; + bool escape = false; + + new_argc--; + memmove(&new_argv[i], &new_argv[i + 1], sizeof(char *) * (new_argc - i)); + insert = i; + b = buffer; + + while ((c = fgetc(f)) != EOF) { + if (escape) { + if (b != be) { + *b = c; + ++b; + } + escape = false; + } else if (c == '\\') { + escape = true; + } else if (!quote && (c == '\'' || c == '"')) { + quote = c; + } else if (quote && c == quote) { + quote = 0; + } else if (isspace(c) && !quote) { + if (b != buffer) { + insert_option(&new_argc, &new_argv, insert, buffer, b); + insert++; + + b = buffer; + } + } else if (b != be) { + *b = c; + ++b; + } + } + if (b != buffer) + insert_option(&new_argc, &new_argv, insert, buffer, b); + fclose(f); + } else { + ++i; + } + } + + *argv = new_argv; + *argc = new_argc; +} + int main(int margc, char **margv) { int i; Language *dl = 0; @@ -162,6 +241,7 @@ int main(int margc, char **margv) { char **argv; SWIG_merge_envopt(getenv("SWIG_FEATURES"), margc, margv, &argc, &argv); + merge_options_files(&argc, &argv); #ifdef MACSWIG SIOUXSettings.asktosaveonclose = false; From bc89aad59f4090bcd2b6cc1bb5f3acdbd56c5748 Mon Sep 17 00:00:00 2001 From: Joshua Watt Date: Wed, 29 Nov 2017 20:29:21 -0600 Subject: [PATCH 411/455] Add documentation for option files --- Doc/Manual/SWIG.html | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/Doc/Manual/SWIG.html b/Doc/Manual/SWIG.html index f6a62d55d..ffc373f24 100644 --- a/Doc/Manual/SWIG.html +++ b/Doc/Manual/SWIG.html @@ -163,6 +163,32 @@ can be obtained by typing swig -help or swig

        +

        +Arguments may also be passed in a command-line options file (also known as a +response file) which is useful if they exceed the system command line length +limit. To do this, put the arguments in a file, then provide the file name +prefixed with @ like so: +

        + +
        +swig @file
        +
        + +

        +The options read from the file are inserted in place of the file option. If the +file does not exist, or cannot be read, then the option will be treated +literally and not removed. +

        + +

        +Options in the file are separated by whitespace. A whitespace character may be +included in an option by surrounding the entire option in either single or +double quotes. Any character (including a backslash) may be included by +prefixing the character to be included with a backslash. The file may itself +contain additional @file options; any such options will be processed +recursively. +

        +

        5.1.1 Input format

        From af8d176c40b8d01b721fd04092155045478c855d Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Fri, 12 Jan 2018 23:10:02 +0000 Subject: [PATCH 412/455] java_throws testcase warning fix --- Examples/test-suite/java_throws.i | 1 + 1 file changed, 1 insertion(+) diff --git a/Examples/test-suite/java_throws.i b/Examples/test-suite/java_throws.i index 875bce0ff..bb5c6e48f 100644 --- a/Examples/test-suite/java_throws.i +++ b/Examples/test-suite/java_throws.i @@ -142,6 +142,7 @@ JAVAEXCEPTION(imethod) %inline %{ struct InterfaceTest { virtual void imethod(bool raise) = 0; + virtual ~InterfaceTest() {} }; struct InterfaceTestImpl : InterfaceTest { From ab5559f51ce55f31965cb54b060e8b8b0c65713b Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Sat, 13 Jan 2018 07:33:28 +0000 Subject: [PATCH 413/455] Fix out of bounds memory problems in handling simple macro arguments Fixes handling macro in swigmacros.swg: #define %arg(Arg...) Arg AddressSanitizer error running Python test-suite. --- Source/Preprocessor/cpp.c | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/Source/Preprocessor/cpp.c b/Source/Preprocessor/cpp.c index a8d386cea..df7458201 100644 --- a/Source/Preprocessor/cpp.c +++ b/Source/Preprocessor/cpp.c @@ -930,19 +930,21 @@ static String *expand_macro(String *name, List *args, String *line_file) { namelen = Len(aname); a = strstr(s, name); while (a) { - char ca = a[namelen + 1]; + char ca = a[namelen]; if (!isidchar((int) ca)) { /* Matched the entire vararg name, not just a prefix */ - t = a - 1; - if (*t == '\002') { - t--; - while (t >= s) { - if (isspace((int) *t)) - t--; - else if (*t == ',') { - *t = ' '; - } else - break; + if (a > s) { + t = a - 1; + if (*t == '\002') { + t--; + while (t >= s) { + if (isspace((int) *t)) + t--; + else if (*t == ',') { + *t = ' '; + } else + break; + } } } } From 9b0e06a8e8cffde10dc2ddc5f6bd41e4eb26b2ff Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Sat, 13 Jan 2018 07:57:30 +0000 Subject: [PATCH 414/455] Seg fault fix running uffi tests --- Source/Modules/uffi.cxx | 31 ++++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/Source/Modules/uffi.cxx b/Source/Modules/uffi.cxx index d56ed3b1f..10a53a561 100644 --- a/Source/Modules/uffi.cxx +++ b/Source/Modules/uffi.cxx @@ -363,23 +363,24 @@ int UFFI::classHandler(Node *n) { for (c = firstChild(n); c; c = nextSibling(c)) { SwigType *type = Getattr(c, "type"); SwigType *decl = Getattr(c, "decl"); - type = Copy(type); - SwigType_push(type, decl); - String *lisp_type; + if (type) { + type = Copy(type); + SwigType_push(type, decl); + String *lisp_type; - if (Strcmp(nodeType(c), "cdecl")) { - Printf(stderr, "Structure %s has a slot that we can't deal with.\n", name); - Printf(stderr, "nodeType: %s, name: %s, type: %s\n", nodeType(c), Getattr(c, "name"), Getattr(c, "type")); - SWIG_exit(EXIT_FAILURE); + if (Strcmp(nodeType(c), "cdecl")) { + Printf(stderr, "Structure %s has a slot that we can't deal with.\n", name); + Printf(stderr, "nodeType: %s, name: %s, type: %s\n", nodeType(c), Getattr(c, "name"), Getattr(c, "type")); + SWIG_exit(EXIT_FAILURE); + } + + /* Printf(stdout, "Converting %s in %s\n", type, name); */ + lisp_type = get_ffi_type(n, type, Getattr(c, "sym:name")); + + Printf(f_cl, " (#.(%s \"%s\" :type :slot) %s)\n", identifier_converter, Getattr(c, "sym:name"), lisp_type); + + Delete(lisp_type); } - - - /* Printf(stdout, "Converting %s in %s\n", type, name); */ - lisp_type = get_ffi_type(n, type, Getattr(c, "sym:name")); - - Printf(f_cl, " (#.(%s \"%s\" :type :slot) %s)\n", identifier_converter, Getattr(c, "sym:name"), lisp_type); - - Delete(lisp_type); } // Language::classHandler(n); From 07a30249f416ced2ae627e1a32c15d38cb403087 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Sun, 14 Jan 2018 19:36:09 +0000 Subject: [PATCH 415/455] Fix seg fault parsing invalid exponents Add error message when exponents are incomplete, for example 5e and 5.e --- CHANGES.current | 3 +++ .../test-suite/errors/cpp_invalid_exponents1.i | 4 ++++ .../errors/cpp_invalid_exponents1.stderr | 2 ++ .../test-suite/errors/cpp_invalid_exponents2.i | 4 ++++ .../errors/cpp_invalid_exponents2.stderr | 2 ++ Examples/test-suite/errors/pp_invalid_exponents.i | 7 +++++++ .../test-suite/errors/pp_invalid_exponents.stderr | 6 ++++++ Source/Swig/scanner.c | 14 ++++++++------ 8 files changed, 36 insertions(+), 6 deletions(-) create mode 100644 Examples/test-suite/errors/cpp_invalid_exponents1.i create mode 100644 Examples/test-suite/errors/cpp_invalid_exponents1.stderr create mode 100644 Examples/test-suite/errors/cpp_invalid_exponents2.i create mode 100644 Examples/test-suite/errors/cpp_invalid_exponents2.stderr create mode 100644 Examples/test-suite/errors/pp_invalid_exponents.i create mode 100644 Examples/test-suite/errors/pp_invalid_exponents.stderr diff --git a/CHANGES.current b/CHANGES.current index 07ab418cb..0618e9725 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.0.0 (in progress) =========================== +2018-01-14: wsfulton + Fix issue #1172. Seg fault parsing invalid exponents in the preprocessor. + 2018-01-12: Liryna [C#] Patch #1128. Add ToArray function to std::vector wrappers. diff --git a/Examples/test-suite/errors/cpp_invalid_exponents1.i b/Examples/test-suite/errors/cpp_invalid_exponents1.i new file mode 100644 index 000000000..1ff2c3603 --- /dev/null +++ b/Examples/test-suite/errors/cpp_invalid_exponents1.i @@ -0,0 +1,4 @@ +%module xxx + +void bad(double nn = 5e); + diff --git a/Examples/test-suite/errors/cpp_invalid_exponents1.stderr b/Examples/test-suite/errors/cpp_invalid_exponents1.stderr new file mode 100644 index 000000000..6096114be --- /dev/null +++ b/Examples/test-suite/errors/cpp_invalid_exponents1.stderr @@ -0,0 +1,2 @@ +cpp_invalid_exponents1.i:3: Error: Exponent does not have any digits +cpp_invalid_exponents1.i:3: Error: Syntax error in input(1). diff --git a/Examples/test-suite/errors/cpp_invalid_exponents2.i b/Examples/test-suite/errors/cpp_invalid_exponents2.i new file mode 100644 index 000000000..2e074872a --- /dev/null +++ b/Examples/test-suite/errors/cpp_invalid_exponents2.i @@ -0,0 +1,4 @@ +%module xxx + +void bad(double nn = 6.6e); + diff --git a/Examples/test-suite/errors/cpp_invalid_exponents2.stderr b/Examples/test-suite/errors/cpp_invalid_exponents2.stderr new file mode 100644 index 000000000..e7d1bf07d --- /dev/null +++ b/Examples/test-suite/errors/cpp_invalid_exponents2.stderr @@ -0,0 +1,2 @@ +cpp_invalid_exponents2.i:3: Error: Exponent does not have any digits +cpp_invalid_exponents2.i:3: Error: Syntax error in input(1). diff --git a/Examples/test-suite/errors/pp_invalid_exponents.i b/Examples/test-suite/errors/pp_invalid_exponents.i new file mode 100644 index 000000000..73dcdb145 --- /dev/null +++ b/Examples/test-suite/errors/pp_invalid_exponents.i @@ -0,0 +1,7 @@ +%module xxx + +#if 123e +#endif + +#if 456.e +#endif diff --git a/Examples/test-suite/errors/pp_invalid_exponents.stderr b/Examples/test-suite/errors/pp_invalid_exponents.stderr new file mode 100644 index 000000000..735a31ceb --- /dev/null +++ b/Examples/test-suite/errors/pp_invalid_exponents.stderr @@ -0,0 +1,6 @@ +:EOF: Error: Exponent does not have any digits +pp_invalid_exponents.i:3: Warning 202: Could not evaluate expression '123e' +pp_invalid_exponents.i:3: Warning 202: Error: 'Syntax error' +:EOF: Error: Exponent does not have any digits +pp_invalid_exponents.i:6: Warning 202: Could not evaluate expression '456.e' +pp_invalid_exponents.i:6: Warning 202: Error: 'Syntax error' diff --git a/Source/Swig/scanner.c b/Source/Swig/scanner.c index f62ddda01..af4a38adb 100644 --- a/Source/Swig/scanner.c +++ b/Source/Swig/scanner.c @@ -1118,27 +1118,29 @@ static int look(Scanner *s) { break; case 82: if ((c = nextchar(s)) == 0) { - retract(s, 1); - return SWIG_TOKEN_INT; + Swig_error(cparse_file, cparse_start_line, "Exponent does not have any digits\n"); + return SWIG_TOKEN_ERROR; } if ((isdigit(c)) || (c == '-') || (c == '+')) state = 86; else { retract(s, 2); - return (SWIG_TOKEN_INT); + Swig_error(cparse_file, cparse_start_line, "Exponent does not have any digits\n"); + return SWIG_TOKEN_ERROR; } break; case 820: /* Like case 82, but we've seen a decimal point. */ if ((c = nextchar(s)) == 0) { - retract(s, 1); - return SWIG_TOKEN_DOUBLE; + Swig_error(cparse_file, cparse_start_line, "Exponent does not have any digits\n"); + return SWIG_TOKEN_ERROR; } if ((isdigit(c)) || (c == '-') || (c == '+')) state = 86; else { retract(s, 2); - return (SWIG_TOKEN_DOUBLE); + Swig_error(cparse_file, cparse_start_line, "Exponent does not have any digits\n"); + return SWIG_TOKEN_ERROR; } break; case 83: From ea5b55ecf44091482fbc7d5484f61cc5efade4e1 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Mon, 15 Jan 2018 07:51:18 +0000 Subject: [PATCH 416/455] Fix floating point division by zero in preprocessor expressions. Closes #1183 --- CHANGES.current | 4 ++++ .../test-suite/errors/pp_expressions_bad.i | 13 +++++++++++++ .../errors/pp_expressions_bad.stderr | 8 ++++++++ Source/Preprocessor/expr.c | 18 ++++++++++++++---- 4 files changed, 39 insertions(+), 4 deletions(-) create mode 100644 Examples/test-suite/errors/pp_expressions_bad.i create mode 100644 Examples/test-suite/errors/pp_expressions_bad.stderr diff --git a/CHANGES.current b/CHANGES.current index 0618e9725..e2072fd33 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.0.0 (in progress) =========================== +2018-01-15: wsfulton + Fix issue #1183. Floating point exception evaluating preprocessor expressions + resulting in division by zero. + 2018-01-14: wsfulton Fix issue #1172. Seg fault parsing invalid exponents in the preprocessor. diff --git a/Examples/test-suite/errors/pp_expressions_bad.i b/Examples/test-suite/errors/pp_expressions_bad.i new file mode 100644 index 000000000..8f7b3abb3 --- /dev/null +++ b/Examples/test-suite/errors/pp_expressions_bad.i @@ -0,0 +1,13 @@ +%module xxx + +#define ZERO 0 + +#if 1%ZERO +#endif +#if 2/ZERO +#endif + +#if 1%(5-5) +#endif +#if 2/(55-55) +#endif diff --git a/Examples/test-suite/errors/pp_expressions_bad.stderr b/Examples/test-suite/errors/pp_expressions_bad.stderr new file mode 100644 index 000000000..4f7aec541 --- /dev/null +++ b/Examples/test-suite/errors/pp_expressions_bad.stderr @@ -0,0 +1,8 @@ +pp_expressions_bad.i:5: Warning 202: Could not evaluate expression '1%ZERO' +pp_expressions_bad.i:5: Warning 202: Error: 'Modulo by zero in expression' +pp_expressions_bad.i:7: Warning 202: Could not evaluate expression '2/ZERO' +pp_expressions_bad.i:7: Warning 202: Error: 'Division by zero in expression' +pp_expressions_bad.i:10: Warning 202: Could not evaluate expression '1%(5-5)' +pp_expressions_bad.i:10: Warning 202: Error: 'Modulo by zero in expression' +pp_expressions_bad.i:12: Warning 202: Could not evaluate expression '2/(55-55)' +pp_expressions_bad.i:12: Warning 202: Error: 'Division by zero in expression' diff --git a/Source/Preprocessor/expr.c b/Source/Preprocessor/expr.c index 6d22c8c5e..f6de7ef84 100644 --- a/Source/Preprocessor/expr.c +++ b/Source/Preprocessor/expr.c @@ -188,12 +188,22 @@ static int reduce_op() { sp--; break; case SWIG_TOKEN_SLASH: - stack[sp - 2].value = stack[sp - 2].value / stack[sp].value; - sp -= 2; + if (stack[sp].value != 0) { + stack[sp - 2].value = stack[sp - 2].value / stack[sp].value; + sp -= 2; + } else { + errmsg = "Division by zero in expression"; + return 0; + } break; case SWIG_TOKEN_PERCENT: - stack[sp - 2].value = stack[sp - 2].value % stack[sp].value; - sp -= 2; + if (stack[sp].value != 0) { + stack[sp - 2].value = stack[sp - 2].value % stack[sp].value; + sp -= 2; + } else { + errmsg = "Modulo by zero in expression"; + return 0; + } break; case SWIG_TOKEN_LSHIFT: stack[sp - 2].value = stack[sp - 2].value << stack[sp].value; From 532999f4f2cb55c5b5b46681f5dc9126ef6b44aa Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Mon, 15 Jan 2018 08:09:14 +0000 Subject: [PATCH 417/455] Improve error message when preprocessor expressions result in a floating point constant Instead of a syntax error, the error is now: Warning 202: Error: 'Floating point constant in preprocessor expression' --- .../test-suite/errors/pp_expressions_bad.i | 13 +++++++++++ .../errors/pp_expressions_bad.stderr | 22 ++++++++++++------- Source/Preprocessor/expr.c | 4 ++++ 3 files changed, 31 insertions(+), 8 deletions(-) diff --git a/Examples/test-suite/errors/pp_expressions_bad.i b/Examples/test-suite/errors/pp_expressions_bad.i index 8f7b3abb3..19d740942 100644 --- a/Examples/test-suite/errors/pp_expressions_bad.i +++ b/Examples/test-suite/errors/pp_expressions_bad.i @@ -1,5 +1,7 @@ %module xxx +/* Note: needs -Wextra to see these warnings */ +/* Divide by zero */ #define ZERO 0 #if 1%ZERO @@ -11,3 +13,14 @@ #endif #if 2/(55-55) #endif + +/* Floating point */ +#if 1.2 +#endif + +#if 2e3 +#endif + +#if 0 +#elif 8.8 +#endif diff --git a/Examples/test-suite/errors/pp_expressions_bad.stderr b/Examples/test-suite/errors/pp_expressions_bad.stderr index 4f7aec541..3e1112206 100644 --- a/Examples/test-suite/errors/pp_expressions_bad.stderr +++ b/Examples/test-suite/errors/pp_expressions_bad.stderr @@ -1,8 +1,14 @@ -pp_expressions_bad.i:5: Warning 202: Could not evaluate expression '1%ZERO' -pp_expressions_bad.i:5: Warning 202: Error: 'Modulo by zero in expression' -pp_expressions_bad.i:7: Warning 202: Could not evaluate expression '2/ZERO' -pp_expressions_bad.i:7: Warning 202: Error: 'Division by zero in expression' -pp_expressions_bad.i:10: Warning 202: Could not evaluate expression '1%(5-5)' -pp_expressions_bad.i:10: Warning 202: Error: 'Modulo by zero in expression' -pp_expressions_bad.i:12: Warning 202: Could not evaluate expression '2/(55-55)' -pp_expressions_bad.i:12: Warning 202: Error: 'Division by zero in expression' +pp_expressions_bad.i:7: Warning 202: Could not evaluate expression '1%ZERO' +pp_expressions_bad.i:7: Warning 202: Error: 'Modulo by zero in expression' +pp_expressions_bad.i:9: Warning 202: Could not evaluate expression '2/ZERO' +pp_expressions_bad.i:9: Warning 202: Error: 'Division by zero in expression' +pp_expressions_bad.i:12: Warning 202: Could not evaluate expression '1%(5-5)' +pp_expressions_bad.i:12: Warning 202: Error: 'Modulo by zero in expression' +pp_expressions_bad.i:14: Warning 202: Could not evaluate expression '2/(55-55)' +pp_expressions_bad.i:14: Warning 202: Error: 'Division by zero in expression' +pp_expressions_bad.i:18: Warning 202: Could not evaluate expression '1.2' +pp_expressions_bad.i:18: Warning 202: Error: 'Floating point constant in preprocessor expression' +pp_expressions_bad.i:21: Warning 202: Could not evaluate expression '2e3' +pp_expressions_bad.i:21: Warning 202: Error: 'Floating point constant in preprocessor expression' +pp_expressions_bad.i:25: Warning 202: Could not evaluate expression '8.8' +pp_expressions_bad.i:25: Warning 202: Error: 'Floating point constant in preprocessor expression' diff --git a/Source/Preprocessor/expr.c b/Source/Preprocessor/expr.c index f6de7ef84..a36588983 100644 --- a/Source/Preprocessor/expr.c +++ b/Source/Preprocessor/expr.c @@ -319,6 +319,10 @@ int Preprocessor_expr(DOH *s, int *error) { stack[sp].value = 0; stack[sp].svalue = 0; stack[sp].op = EXPR_VALUE; + } else if ((token == SWIG_TOKEN_FLOAT) || (token == SWIG_TOKEN_DOUBLE)) { + errmsg = "Floating point constant in preprocessor expression"; + *error = 1; + return 0; } else goto syntax_error; break; From 72964a1fafd2be8849ddd8f6cc6f5a8e04871c53 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Mon, 15 Jan 2018 19:57:10 +0000 Subject: [PATCH 418/455] Don't accept some invalid preprocessor code Whitespace or non-numeric characters are required after a preprocessor directive that requires an expression. --- CHANGES.current | 25 +++++++++++++++++++ .../test-suite/errors/pp_expressions_bad.i | 17 +++++++++++++ .../errors/pp_expressions_bad.stderr | 5 ++++ Source/Preprocessor/cpp.c | 2 +- 4 files changed, 48 insertions(+), 1 deletion(-) diff --git a/CHANGES.current b/CHANGES.current index e2072fd33..1db9cbca1 100644 --- a/CHANGES.current +++ b/CHANGES.current @@ -7,6 +7,31 @@ the issue number to the end of the URL: https://github.com/swig/swig/issues/ Version 4.0.0 (in progress) =========================== +2018-01-16: wsfulton + Expressions following a preprocessor directive must now be separated by whitespace + or non-numeric characters. This syntax change makes the SWIG preprocessor work like + the C preprocessor in this area. + + For example, the following code used be accepted as valid syntax: + #if1 + #define ABC 123 + #endif + + Now you get an error: + example.h:1: Error: Unknown SWIG preprocessor directive: if1 (if this is a block of + target language code, delimit it with %{ and %}) + example.h:3: Error: Extraneous #endif. + + The following is the correct syntax: + #if 1 + #define ABC 123 + #endif + + The following of course also works: + #if(1) + #define ABC 123 + #endif + 2018-01-15: wsfulton Fix issue #1183. Floating point exception evaluating preprocessor expressions resulting in division by zero. diff --git a/Examples/test-suite/errors/pp_expressions_bad.i b/Examples/test-suite/errors/pp_expressions_bad.i index 19d740942..454437f95 100644 --- a/Examples/test-suite/errors/pp_expressions_bad.i +++ b/Examples/test-suite/errors/pp_expressions_bad.i @@ -24,3 +24,20 @@ #if 0 #elif 8.8 #endif + +/* Missing whitespace after preproc directive */ +#if123 +#endif + +#if456e +#endif + +#if 0 +#warning This should not warn +#elif1 +#warning This should also not warn +#endif + +#if(1) +#warning Warning okay: #if(1) +#endif diff --git a/Examples/test-suite/errors/pp_expressions_bad.stderr b/Examples/test-suite/errors/pp_expressions_bad.stderr index 3e1112206..84104c6a8 100644 --- a/Examples/test-suite/errors/pp_expressions_bad.stderr +++ b/Examples/test-suite/errors/pp_expressions_bad.stderr @@ -12,3 +12,8 @@ pp_expressions_bad.i:21: Warning 202: Could not evaluate expression '2e3' pp_expressions_bad.i:21: Warning 202: Error: 'Floating point constant in preprocessor expression' pp_expressions_bad.i:25: Warning 202: Could not evaluate expression '8.8' pp_expressions_bad.i:25: Warning 202: Error: 'Floating point constant in preprocessor expression' +pp_expressions_bad.i:29: Error: Unknown SWIG preprocessor directive: if123 (if this is a block of target language code, delimit it with %{ and %}) +pp_expressions_bad.i:30: Error: Extraneous #endif. +pp_expressions_bad.i:32: Error: Unknown SWIG preprocessor directive: if456e (if this is a block of target language code, delimit it with %{ and %}) +pp_expressions_bad.i:33: Error: Extraneous #endif. +pp_expressions_bad.i:42: Warning 204: CPP #warning, "Warning okay: #if(1)". diff --git a/Source/Preprocessor/cpp.c b/Source/Preprocessor/cpp.c index df7458201..10018a787 100644 --- a/Source/Preprocessor/cpp.c +++ b/Source/Preprocessor/cpp.c @@ -1454,7 +1454,7 @@ String *Preprocessor_parse(String *s) { break; case 41: /* Build up the name of the preprocessor directive */ - if ((isspace(c) || (!isalpha(c)))) { + if ((isspace(c) || (!isidchar(c)))) { Clear(value); Clear(comment); if (c == '\n') { From 862501480efea950e33215cc49c1a20cb2af2958 Mon Sep 17 00:00:00 2001 From: Simon Marchetto Date: Tue, 30 Jan 2018 16:34:31 +0100 Subject: [PATCH 419/455] add type name argument in SWIG_ptr() function to cast from pointer adress to typed pointers --- CHANGES.current | 7 +++- Lib/scilab/scirun.swg | 85 +++++++++++++++++++++++++++++---------- Lib/scilab/sciruntime.swg | 6 ++- 3 files changed, 72 insertions(+), 26 deletions(-) diff --git a/CHANGES.current b/CHANGES.current index 1db9cbca1..5f0daee0b 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.0.0 (in progress) =========================== +2018-01-30: smarchetto + [Scilab] add type name argument in SWIG_ptr() function to cast from pointer adress to typed pointers + 2018-01-16: wsfulton Expressions following a preprocessor directive must now be separated by whitespace or non-numeric characters. This syntax change makes the SWIG preprocessor work like @@ -71,7 +74,7 @@ Version 4.0.0 (in progress) should make the generated code work with PHP 7.2.0. 2017-12-04: wsfulton - [Python] Add missing checks for failures in calls to PyUnicode_AsUTF8String. Previously a + [Python] Add missing checks for failures in calls to PyUnicode_AsUTF8String. Previously a seg fault could occur when passing invalid UTF8 strings (low surrogates), eg passing u"\udcff" to the C layer (Python 3). @@ -150,7 +153,7 @@ Version 4.0.0 (in progress) language as the C++ template name, for example, this is now possible: template struct X { ... }; - %template(X) X; + %template(X) X; 2017-09-23: wsfulton Issue #1098. Fix overloading of shared_ptr with underlying pointer types, eg: diff --git a/Lib/scilab/scirun.swg b/Lib/scilab/scirun.swg index 29f8096ef..a9e9d6351 100644 --- a/Lib/scilab/scirun.swg +++ b/Lib/scilab/scirun.swg @@ -446,36 +446,77 @@ int SWIG_this(SWIG_GatewayParameters) { extern "C" #endif int SWIG_ptr(SWIG_GatewayParameters) { - void *ptrValue = NULL; - double dValue = 0; - if (SwigScilabPtrToObject(pvApiCtx, 1, &ptrValue, NULL, 0, fname) == SWIG_OK) { - SWIG_Scilab_SetOutputPosition(1); - return SWIG_Scilab_SetOutput(pvApiCtx, - SwigScilabPtrFromObject(pvApiCtx, 1, ptrValue, NULL, 0, NULL)); - } - else { - int *piAddr; - SciErr sciErr = getVarAddressFromPosition(pvApiCtx, 1, &piAddr); - if(sciErr.iErr) { + if (SWIG_NbInputArgument(pvApiCtx) > 0) { + int *piAddrVar1 = NULL; + int iTypeVar1 = 0; + char *pstInputPtrTypeName = NULL; + char *pstOutputMListTypeName = NULL; + if (SWIG_NbInputArgument(pvApiCtx) > 2) { + int *piAddrVar2 = NULL; + int *piAddrVar3 = NULL; + SciErr sciErr = getVarAddressFromPosition(pvApiCtx, 2, &piAddrVar2); + if (sciErr.iErr) { + printError(&sciErr, 0); + return SWIG_ERROR; + } + if (getAllocatedSingleString(pvApiCtx, piAddrVar2, &pstInputPtrTypeName)) { + return SWIG_ERROR; + } + sciErr = getVarAddressFromPosition(pvApiCtx, 3, &piAddrVar3); + if (sciErr.iErr) { + printError(&sciErr, 0); + return SWIG_ERROR; + } + if (getAllocatedSingleString(pvApiCtx, piAddrVar3, &pstOutputMListTypeName)) { + return SWIG_ERROR; + } + } + + SciErr sciErr = getVarAddressFromPosition(pvApiCtx, 1, &piAddrVar1); + if (sciErr.iErr) { printError(&sciErr, 0); return SWIG_ERROR; } - if (getScalarDouble(pvApiCtx, piAddr, &dValue) == 0) { - if (dValue != (uintptr_t)dValue) { - Scierror(SCILAB_API_ARGUMENT_ERROR, _("%s: Incorrect value for input argument #%d: The double value cannot be converted to a pointer.\n"), fname, 1); - return SWIG_ValueError; + sciErr = getVarType(pvApiCtx, piAddrVar1, &iTypeVar1); + if (sciErr.iErr) { + printError(&sciErr, 0); + return SWIG_ERROR; + } + + if ((iTypeVar1 == sci_pointer) || (iTypeVar1 == sci_mlist)) { + void *ptrValue = NULL; + if (SwigScilabPtrToObject(pvApiCtx, 1, &ptrValue, SWIG_Scilab_TypeQuery(pstInputPtrTypeName), 0, (char *) "SWIG_ptr") == SWIG_OK) { + SWIG_Scilab_SetOutputPosition(1); + return SWIG_Scilab_SetOutput(pvApiCtx, + SwigScilabPtrFromObject(pvApiCtx, 1, ptrValue, SWIG_Scilab_TypeQuery(pstInputPtrTypeName), 0, pstOutputMListTypeName)); } - if ((dValue < 0) || (dValue > ULONG_MAX)) { - Scierror(SCILAB_API_ARGUMENT_ERROR, _("%s: Overflow error for input argument #%d: The double value cannot be converted to a pointer.\n"), fname, 1); - return SWIG_OverflowError; + } + else if (iTypeVar1 == sci_matrix) { + double dValue = 0; + if (getScalarDouble(pvApiCtx, piAddrVar1, &dValue) == 0) { + if (dValue != (uintptr_t)dValue) { + Scierror(SCILAB_API_ARGUMENT_ERROR, _("%s: Incorrect value for input argument #%d: The double value cannot be converted to a pointer.\n"), fname, 1); + return SWIG_ValueError; + } + if ((dValue < 0) || (dValue > ULONG_MAX)) { + Scierror(SCILAB_API_ARGUMENT_ERROR, _("%s: Overflow error for input argument #%d: The double value cannot be converted to a pointer.\n"), fname, 1); + return SWIG_OverflowError; + } + SWIG_Scilab_SetOutputPosition(1); + return SWIG_Scilab_SetOutput(pvApiCtx, + SwigScilabPtrFromObject(pvApiCtx, 1, (void *) (uintptr_t)dValue, SWIG_Scilab_TypeQuery(pstInputPtrTypeName), 0, pstOutputMListTypeName)); + } + else { + return SWIG_TypeError; } - SWIG_Scilab_SetOutputPosition(1); - return SWIG_Scilab_SetOutput(pvApiCtx, - SwigScilabPtrFromObject(pvApiCtx, 1, (void *) (uintptr_t)dValue, NULL, 0, NULL)); } else { - Scierror(SCILAB_API_ARGUMENT_ERROR, _("%s: Wrong type for input argument #%d: A pointer or a double expected.\n"), "SWIG_ptr", 1); + Scierror(SCILAB_API_ARGUMENT_ERROR, _("%s: Wrong type for input argument #%d: A mlist, pointer or a double expected.\n"), (char *) "SWIG_ptr", 1); return SWIG_TypeError; } } + else { + Scierror(SCILAB_API_ARGUMENT_ERROR, _("%s: A mlist, pointer, or a double expected.\n"), "SWIG_ptr", 1); + return SWIG_TypeError; + } } diff --git a/Lib/scilab/sciruntime.swg b/Lib/scilab/sciruntime.swg index 9abedfe3d..3de138e11 100644 --- a/Lib/scilab/sciruntime.swg +++ b/Lib/scilab/sciruntime.swg @@ -25,12 +25,14 @@ SWIG_Scilab_SetModule(swig_module_info *swig_module) { SWIGRUNTIME swig_type_info * SWIG_Scilab_TypeQuery(const char *name) { if (SWIG_Module_Initialized()) { - return SWIG_TypeQuery(name); + if (name) { + return SWIG_TypeQuery(name); + } } else { SWIG_Error(SWIG_RuntimeError, "the module is not initialized"); - return NULL; } + return NULL; } %} From 7a9ee39412bbb10d79d9cafb5f61a4fb5c00840e Mon Sep 17 00:00:00 2001 From: Simon Marchetto Date: Thu, 1 Feb 2018 10:09:35 +0100 Subject: [PATCH 420/455] [Scilab] fix compilation error --- Lib/scilab/scirun.swg | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Lib/scilab/scirun.swg b/Lib/scilab/scirun.swg index a9e9d6351..3b2a96520 100644 --- a/Lib/scilab/scirun.swg +++ b/Lib/scilab/scirun.swg @@ -447,6 +447,7 @@ extern "C" #endif int SWIG_ptr(SWIG_GatewayParameters) { if (SWIG_NbInputArgument(pvApiCtx) > 0) { + SciErr sciErr; int *piAddrVar1 = NULL; int iTypeVar1 = 0; char *pstInputPtrTypeName = NULL; @@ -454,7 +455,7 @@ int SWIG_ptr(SWIG_GatewayParameters) { if (SWIG_NbInputArgument(pvApiCtx) > 2) { int *piAddrVar2 = NULL; int *piAddrVar3 = NULL; - SciErr sciErr = getVarAddressFromPosition(pvApiCtx, 2, &piAddrVar2); + sciErr = getVarAddressFromPosition(pvApiCtx, 2, &piAddrVar2); if (sciErr.iErr) { printError(&sciErr, 0); return SWIG_ERROR; @@ -472,7 +473,7 @@ int SWIG_ptr(SWIG_GatewayParameters) { } } - SciErr sciErr = getVarAddressFromPosition(pvApiCtx, 1, &piAddrVar1); + sciErr = getVarAddressFromPosition(pvApiCtx, 1, &piAddrVar1); if (sciErr.iErr) { printError(&sciErr, 0); return SWIG_ERROR; From 164713536918485f31a888242a7a0df411d03ec9 Mon Sep 17 00:00:00 2001 From: Simon Marchetto Date: Thu, 1 Feb 2018 14:31:52 +0100 Subject: [PATCH 421/455] [scilab] fix compilation (checked with the additional compiler options) --- Lib/scilab/scirun.swg | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Lib/scilab/scirun.swg b/Lib/scilab/scirun.swg index 3b2a96520..961ac1c21 100644 --- a/Lib/scilab/scirun.swg +++ b/Lib/scilab/scirun.swg @@ -491,6 +491,9 @@ int SWIG_ptr(SWIG_GatewayParameters) { return SWIG_Scilab_SetOutput(pvApiCtx, SwigScilabPtrFromObject(pvApiCtx, 1, ptrValue, SWIG_Scilab_TypeQuery(pstInputPtrTypeName), 0, pstOutputMListTypeName)); } + else { + return SWIG_ERROR; + } } else if (iTypeVar1 == sci_matrix) { double dValue = 0; From 449ba627f5711ca9e65a4282cb734e7ac0187040 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Wed, 17 Jan 2018 22:13:03 +0000 Subject: [PATCH 422/455] Typo fix in SWIGPlus.html docs --- Doc/Manual/SWIGPlus.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Doc/Manual/SWIGPlus.html b/Doc/Manual/SWIGPlus.html index 5eac55261..310a7a951 100644 --- a/Doc/Manual/SWIGPlus.html +++ b/Doc/Manual/SWIGPlus.html @@ -3152,7 +3152,7 @@ redundant and will simply result in code bloat).

        -The template provide to %template for instantiation must be the actual template and not a typedef to a template. +The template provided to %template for instantiation must be the actual template and not a typedef to a template.

        From 7fbdd21b4999e5a064b77f99919f4f0c242899db Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Sun, 11 Feb 2018 11:12:24 +0000 Subject: [PATCH 423/455] Javascript - Fix compilation error wrapping std::complex via std_complex.i Closes #1187 --- CHANGES.current | 4 ++++ Lib/javascript/v8/javascriptcomplex.swg | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGES.current b/CHANGES.current index 5f0daee0b..79e7a3f8d 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.0.0 (in progress) =========================== +2018-02-11: wsfulton + [Javascript] #1187 Fix compilation error wrapping std::complex via + std_complex.i. + 2018-01-30: smarchetto [Scilab] add type name argument in SWIG_ptr() function to cast from pointer adress to typed pointers diff --git a/Lib/javascript/v8/javascriptcomplex.swg b/Lib/javascript/v8/javascriptcomplex.swg index 1c0107beb..d3b4aaffa 100644 --- a/Lib/javascript/v8/javascriptcomplex.swg +++ b/Lib/javascript/v8/javascriptcomplex.swg @@ -17,7 +17,7 @@ SWIG_From_dec(Type)(%ifcplusplus(const Type&, Type) c) { SWIGV8_HANDLESCOPE_ESC(); - v8::Local vals = SWIGV8_ARRAY_NEW(2); + v8::Local vals = SWIGV8_ARRAY_NEW(); vals->Set(0, SWIG_From(double)(Real(c))); vals->Set(1, SWIG_From(double)(Imag(c))); From e435f3b93b6fa52b7a9552a00b6aa3fd3a41f94f Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Sun, 18 Feb 2018 21:12:10 +0000 Subject: [PATCH 424/455] Document command-line options file support in changes file --- CHANGES.current | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/CHANGES.current b/CHANGES.current index 79e7a3f8d..7e3bd76f9 100644 --- a/CHANGES.current +++ b/CHANGES.current @@ -7,6 +7,15 @@ the issue number to the end of the URL: https://github.com/swig/swig/issues/ Version 4.0.0 (in progress) =========================== +2018-02-18: JPEWdev + Patch #1164 - Add support for a command-line options file, also sometimes + called a response file. This is useful if the command-line options exceed + the system command-line length limit. To use, put the command-line options + into a file, then provide the file name prefixed with @, for example using + a file called args.txt: + + swig @args.txt + 2018-02-11: wsfulton [Javascript] #1187 Fix compilation error wrapping std::complex via std_complex.i. From d4badb3e1dc32a5f60ceb8a2ed454d6694e57951 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Sat, 3 Mar 2018 14:31:03 +0000 Subject: [PATCH 425/455] Travis OSX Python 3 build fix for recent changes in brew --- Tools/travis-osx-install.sh | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Tools/travis-osx-install.sh b/Tools/travis-osx-install.sh index 42cc33bb2..6bfb2276a 100755 --- a/Tools/travis-osx-install.sh +++ b/Tools/travis-osx-install.sh @@ -23,8 +23,7 @@ case "$SWIGLANG" in "python") WITHLANG=$SWIGLANG$PY3 if [[ "$PY3" ]]; then - travis_retry brew install python3 - travis_retry brew list -v python3 + travis_retry brew upgrade python fi ;; esac From 30719feaf955135586fc96f61c067c9ccf09d507 Mon Sep 17 00:00:00 2001 From: Luca Longinotti Date: Thu, 30 Nov 2017 11:10:44 +0100 Subject: [PATCH 426/455] Fix handling of // comments inside macro arguments /* */ are already handled correctly. This completes the fix from commit 624ec3e1b7dd8908b37ee86bce6f60423c915bc5 related to swig/swig#974. --- Source/Preprocessor/cpp.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/Source/Preprocessor/cpp.c b/Source/Preprocessor/cpp.c index 10018a787..af1775007 100644 --- a/Source/Preprocessor/cpp.c +++ b/Source/Preprocessor/cpp.c @@ -610,6 +610,7 @@ static List *find_args(String *s, int ismacro, String *macro_name) { } else if (c == '/') { /* Ensure comments are ignored by eating up the characters */ c = Getc(s); + /* Handle / * ... * / type comments (multi-line) */ if (c == '*') { while ((c = Getc(s)) != EOF) { if (c == '*') { @@ -621,6 +622,16 @@ static List *find_args(String *s, int ismacro, String *macro_name) { c = Getc(s); continue; } + /* Handle // ... type comments (single-line) */ + if (c == '/') { + while ((c = Getc(s)) != EOF) { + if (c == '\n') { + break; + } + } + c = Getc(s); + continue; + } /* ensure char is available in the stream as this was not a comment*/ Ungetc(c, s); c = '/'; From d5e012f70f7626d3c381666d0112588be883fedf Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Wed, 7 Mar 2018 14:40:28 +1300 Subject: [PATCH 427/455] Add test coverage for // comment fix --- Examples/test-suite/preproc.i | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/Examples/test-suite/preproc.i b/Examples/test-suite/preproc.i index 1efc0dd98..6d6549be7 100644 --- a/Examples/test-suite/preproc.i +++ b/Examples/test-suite/preproc.i @@ -389,6 +389,20 @@ TCX_PACKED (typedef struct tcxMessageBugImpl { int mBid; /**< Bid price and size, check PresentMap if available in message */ }) tcxMessageBug; + + +TCX_PACKED (typedef struct tcxMessageTestImplSlashSlash +{ + int mHeader; ///< comment +}) tcxMessageTestSlashSlash; + + +TCX_PACKED (typedef struct tcxMessageBugImplSlashSlash +{ + int mBid; ///< Bid price and size, check PresentMap if available in message +}) tcxMessageBugSlashSlash; + + %} // Regression tests for https://github.com/swig/swig/pull/1111 From 538ce627750945262179606930850697e0317f6e Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Wed, 7 Mar 2018 14:48:44 +1300 Subject: [PATCH 428/455] Add CHANGES.current entry for previous fix --- CHANGES.current | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGES.current b/CHANGES.current index 7e3bd76f9..b3954a680 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.0.0 (in progress) =========================== +2018-03-07: llongi + Github PR #1166 - Fix preprocessor handling of macros with commas + in a // comment. + 2018-02-18: JPEWdev Patch #1164 - Add support for a command-line options file, also sometimes called a response file. This is useful if the command-line options exceed From ba3773e1be7dfc0580ff2edb8881e418b6877b2f Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Thu, 8 Mar 2018 06:10:08 +1300 Subject: [PATCH 429/455] preproc.i: Shorten classname for scilab Errors were: ../../../../../../Examples/test-suite/scilab/../preproc.i:400: Error: Wrapping functions names for member 'tcxMessageTestSlashSlash.mHeader' will exceed 24 characters, please rename the container of member 'tcxMessageTestSlashSlash'. ../../../../../../Examples/test-suite/scilab/../preproc.i:408: Error: Wrapping functions names for member 'tcxMessageBugSlashSlash.mBid' will exceed 24 characters, please rename the container of member 'tcxMessageBugSlashSlash'. --- Examples/test-suite/preproc.i | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Examples/test-suite/preproc.i b/Examples/test-suite/preproc.i index 6d6549be7..f666911fe 100644 --- a/Examples/test-suite/preproc.i +++ b/Examples/test-suite/preproc.i @@ -391,16 +391,16 @@ TCX_PACKED (typedef struct tcxMessageBugImpl }) tcxMessageBug; -TCX_PACKED (typedef struct tcxMessageTestImplSlashSlash +TCX_PACKED (typedef struct tcxMessageTestImpl2 { int mHeader; ///< comment -}) tcxMessageTestSlashSlash; +}) tcxMessageTest2; -TCX_PACKED (typedef struct tcxMessageBugImplSlashSlash +TCX_PACKED (typedef struct tcxMessageBugImpl2 { int mBid; ///< Bid price and size, check PresentMap if available in message -}) tcxMessageBugSlashSlash; +}) tcxMessageBug2; %} From 1915740af8c26720f366162c768c223bddb15c7c Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Thu, 8 Mar 2018 06:12:01 +1300 Subject: [PATCH 430/455] preproc.i: Also note URL for "// in macro" PR --- Examples/test-suite/preproc.i | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Examples/test-suite/preproc.i b/Examples/test-suite/preproc.i index f666911fe..3239798f7 100644 --- a/Examples/test-suite/preproc.i +++ b/Examples/test-suite/preproc.i @@ -373,7 +373,8 @@ int methodX(int x); int methodX(int x) { return x+100; } %} -// Comma in macro - Github issue #974 +// Comma in macro - https://github.com/swig/swig/issues/974 (for /* */) +// and https://github.com/swig/swig/pull/1166 (for //) %inline %{ #define swig__attribute__(x) #define TCX_PACKED(d) d swig__attribute__ ((__packed__)) From 60ee821bcaa9751b0dfeb4d9381b3263f592757e Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Tue, 13 Feb 2018 19:39:15 +0000 Subject: [PATCH 431/455] Correct C# warning for missing cstype typemap --- 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 9b28829ee..78d494fb7 100644 --- a/Source/Modules/csharp.cxx +++ b/Source/Modules/csharp.cxx @@ -1384,7 +1384,7 @@ public: // Wrap C/C++ enums with constant integers or use the typesafe enum pattern SwigType *typemap_lookup_type = parent_name ? parent_name : NewString("enum "); Setattr(n, "type", typemap_lookup_type); - const String *tm = typemapLookup(n, "cstype", typemap_lookup_type, WARN_CSHARP_TYPEMAP_CSTYPE_UNDEF); + const String *tm = typemapLookup(n, "cstype", typemap_lookup_type, WARN_CSHARP_TYPEMAP_CSWTYPE_UNDEF); String *return_type = Copy(tm); substituteClassname(typemap_lookup_type, return_type); From 3ce3ce0683dd3c6ac4482abacd0f3734e9b95a3d Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Tue, 13 Feb 2018 19:45:03 +0000 Subject: [PATCH 432/455] Add std_shared_ptr.i for Scilab and R as boost_shared_ptr.i is already available --- Lib/r/std_shared_ptr.i | 2 ++ Lib/scilab/std_shared_ptr.i | 2 ++ 2 files changed, 4 insertions(+) create mode 100644 Lib/r/std_shared_ptr.i create mode 100644 Lib/scilab/std_shared_ptr.i diff --git a/Lib/r/std_shared_ptr.i b/Lib/r/std_shared_ptr.i new file mode 100644 index 000000000..df873679c --- /dev/null +++ b/Lib/r/std_shared_ptr.i @@ -0,0 +1,2 @@ +#define SWIG_SHARED_PTR_NAMESPACE std +%include diff --git a/Lib/scilab/std_shared_ptr.i b/Lib/scilab/std_shared_ptr.i new file mode 100644 index 000000000..df873679c --- /dev/null +++ b/Lib/scilab/std_shared_ptr.i @@ -0,0 +1,2 @@ +#define SWIG_SHARED_PTR_NAMESPACE std +%include From b4f4ce4fd516f3fed319aaf0d9d8ec98a106de8b Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Fri, 9 Mar 2018 08:13:41 +0000 Subject: [PATCH 433/455] Fix Java swigReleaseOwnership() and swigTakeOwnership() regression Fixes segfault when using non-director classes. Restores a dynamic_cast which was previously removed. The dynamic_cast is not needed for the swig_connect_director call ... we'll have to find another solution for #449 for Java. Closes #1184 --- CHANGES.current | 4 ++ Examples/test-suite/common.mk | 1 + Examples/test-suite/director_ownership.i | 72 +++++++++++++++++++ .../java/director_ownership_runme.java | 42 +++++++++++ Source/Modules/java.cxx | 11 +-- 5 files changed, 125 insertions(+), 5 deletions(-) create mode 100644 Examples/test-suite/director_ownership.i create mode 100644 Examples/test-suite/java/director_ownership_runme.java diff --git a/CHANGES.current b/CHANGES.current index b3954a680..6dbfbe4a0 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.0.0 (in progress) =========================== +2018-03-09: fultonwi + [Java] #1184 Fix swigReleaseOwnership() and swigTakeOwnership() regression + for non-director classes. Restores a dynamic_cast which was previously removed. + 2018-03-07: llongi Github PR #1166 - Fix preprocessor handling of macros with commas in a // comment. diff --git a/Examples/test-suite/common.mk b/Examples/test-suite/common.mk index 3bcf67c8c..eaf8d38cf 100644 --- a/Examples/test-suite/common.mk +++ b/Examples/test-suite/common.mk @@ -194,6 +194,7 @@ CPP_TEST_CASES += \ director_nspace_director_name_collision \ director_overload \ director_overload2 \ + director_ownership \ director_pass_by_value \ director_primitives \ director_property \ diff --git a/Examples/test-suite/director_ownership.i b/Examples/test-suite/director_ownership.i new file mode 100644 index 000000000..3f8f1b512 --- /dev/null +++ b/Examples/test-suite/director_ownership.i @@ -0,0 +1,72 @@ +%module(directors="1") director_ownership + +// Github issue #1184 + +%include "std_string.i" + +%feature("director") example::ContentBase; +%feature("director") example::ContentDerived; + +%newobject example::make_content; + +%inline %{ +#include + +namespace example +{ + +class ContentBase +{ +public: + ContentBase() {} + virtual ~ContentBase() {} + virtual std::string get_name() const = 0; +}; + + +class ContentDerived: public ContentBase +{ +public: + ContentDerived():ContentBase() { m_name = "ContentDerived"; } + virtual ~ContentDerived() {} + virtual std::string get_name() const override { return m_name; } + +private: + std::string m_name; +}; + + +class Container +{ +public: + Container() { m_content = 0; } + ~Container() + { + clear_content(); + } + // the container takes the ownership of the content + void set_content(ContentBase* content) + { + clear_content(); + m_content = content; + } + ContentBase* get_content() { return m_content; } + +private: + void clear_content() + { + if(m_content) + { + delete m_content; + m_content = 0; + } + } + +private: + ContentBase* m_content; +}; + +static ContentBase* make_content() { return new ContentDerived(); } + +} // namespace example +%} diff --git a/Examples/test-suite/java/director_ownership_runme.java b/Examples/test-suite/java/director_ownership_runme.java new file mode 100644 index 000000000..c038f56a4 --- /dev/null +++ b/Examples/test-suite/java/director_ownership_runme.java @@ -0,0 +1,42 @@ +import director_ownership.*; + +public class director_ownership_runme { + + static { + try { + System.loadLibrary("director_ownership"); + } 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 set_content_and_release(Container container, ContentBase content) { + content.swigReleaseOwnership(); + container.set_content(content); + } + + public static void main(String argv[]) { + + Container container = new Container(); + + // make a content in java (cMemoryOwn true) + ContentBase content_java = new ContentDerived(); + + // make a content in c++ (cMemoryOwn true) + ContentBase content_cpp = director_ownership.make_content(); + + set_content_and_release(container, content_java); + if (!container.get_content().get_name().equals("ContentDerived")) + throw new RuntimeException("did not get ContentDerived"); + + // when swigReleaseOwnership() is called on content_cpp, swig tries a static_cast to director and calls the method + // director->swig_java_change_ownership. The content created in c++ native library is not a director, therefore a + // segfault may occur. + // With a check done using dynamic_cast this issue could be avoided. + set_content_and_release(container, content_cpp); + if (!container.get_content().get_name().equals("ContentDerived")) + throw new RuntimeException("did not get ContentDerived"); + } +} + diff --git a/Source/Modules/java.cxx b/Source/Modules/java.cxx index d2b25426a..0f4b13186 100644 --- a/Source/Modules/java.cxx +++ b/Source/Modules/java.cxx @@ -3763,15 +3763,16 @@ public: Printf(code_wrap->code, " %s *obj = *((%s **)&objarg);\n", smartptr, smartptr); Printf(code_wrap->code, " // Keep a local instance of the smart pointer around while we are using the raw pointer\n"); Printf(code_wrap->code, " // Avoids using smart pointer specific API.\n"); - Printf(code_wrap->code, " %s *director = static_cast<%s *>(obj->operator->());\n", dirClassName, dirClassName); - } - else { + Printf(code_wrap->code, " %s *director = dynamic_cast<%s *>(obj->operator->());\n", dirClassName, dirClassName); + } else { Printf(code_wrap->code, " %s *obj = *((%s **)&objarg);\n", norm_name, norm_name); - Printf(code_wrap->code, " %s *director = static_cast<%s *>(obj);\n", dirClassName, dirClassName); + Printf(code_wrap->code, " %s *director = dynamic_cast<%s *>(obj);\n", dirClassName, dirClassName); } Printf(code_wrap->code, " (void)jcls;\n"); - Printf(code_wrap->code, " director->swig_java_change_ownership(jenv, jself, jtake_or_release ? true : false);\n"); + Printf(code_wrap->code, " if (director) {\n"); + Printf(code_wrap->code, " director->swig_java_change_ownership(jenv, jself, jtake_or_release ? true : false);\n"); + Printf(code_wrap->code, " }\n"); Printf(code_wrap->code, "}\n"); Wrapper_print(code_wrap, f_wrappers); From 98ebd56942019eacca543a6469c89119c88a0359 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Fri, 9 Mar 2018 18:27:16 +0000 Subject: [PATCH 434/455] Remove c++11 override in testcase --- Examples/test-suite/director_ownership.i | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Examples/test-suite/director_ownership.i b/Examples/test-suite/director_ownership.i index 3f8f1b512..48e909758 100644 --- a/Examples/test-suite/director_ownership.i +++ b/Examples/test-suite/director_ownership.i @@ -29,7 +29,7 @@ class ContentDerived: public ContentBase public: ContentDerived():ContentBase() { m_name = "ContentDerived"; } virtual ~ContentDerived() {} - virtual std::string get_name() const override { return m_name; } + virtual std::string get_name() const { return m_name; } private: std::string m_name; From b5796019e042f10ad84d4c30c170fafe9415f768 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Wed, 21 Feb 2018 12:25:35 +0000 Subject: [PATCH 435/455] Remove deprecated autoconf macros AC_EXEEXT AC_OBJEXT are deprecated in the minimum autoconf version we use: 2.58. The compiler checking macros do the equivalent now. --- configure.ac | 2 -- 1 file changed, 2 deletions(-) diff --git a/configure.ac b/configure.ac index cfc338126..a40c6662d 100644 --- a/configure.ac +++ b/configure.ac @@ -28,8 +28,6 @@ AH_BOTTOM([ dnl Check for programs that a user requires to build SWIG AC_PROG_CC AC_PROG_CXX -AC_EXEEXT -AC_OBJEXT AM_PROG_CC_C_O # Needed for subdir-objects in AUTOMAKE_OPTIONS AC_COMPILE_WARNINGS # Increase warning levels From 9b44d1bb7e00301d67e20c3cca451feb2f6c2779 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Mon, 19 Mar 2018 23:58:20 +0000 Subject: [PATCH 436/455] Fix -Wimplicit-fallthrough gcc-7.3 warning --- CCache/snprintf.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CCache/snprintf.c b/CCache/snprintf.c index 32187c1a5..9bf8a817b 100644 --- a/CCache/snprintf.c +++ b/CCache/snprintf.c @@ -292,6 +292,7 @@ static size_t dopr(char *buffer, size_t maxlen, const char *format, va_list args break; case 'X': flags |= DP_F_UP; + /* FALLTHROUGH */ case 'x': flags |= DP_F_UNSIGNED; if (cflags == DP_C_SHORT) @@ -314,6 +315,7 @@ static size_t dopr(char *buffer, size_t maxlen, const char *format, va_list args break; case 'E': flags |= DP_F_UP; + /* FALLTHROUGH */ case 'e': if (cflags == DP_C_LDOUBLE) fvalue = va_arg (args, LDOUBLE); @@ -322,6 +324,7 @@ static size_t dopr(char *buffer, size_t maxlen, const char *format, va_list args break; case 'G': flags |= DP_F_UP; + /* FALLTHROUGH */ case 'g': if (cflags == DP_C_LDOUBLE) fvalue = va_arg (args, LDOUBLE); From 6fac581a2b9517b8058f978ea5442026f1340753 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Tue, 20 Mar 2018 07:44:00 +0000 Subject: [PATCH 437/455] Stop testing Python on Appveyor msys/mingw I can't get python2 nor python3 to work with recent platform changes at Appveyor. Just compile SWIG binary for now. --- appveyor.yml | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index 74b1c045d..e2f6a6b32 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -22,8 +22,7 @@ environment: PY3: 1 - SWIGLANG: python OSVARIANT: cygwin - - SWIGLANG: python - OSVARIANT: mingw + - OSVARIANT: mingw install: - date /T & time /T @@ -85,8 +84,6 @@ install: - bash -c "which $CXX" - bash -c "$CC --version | head -n 1" - bash -c "$CXX --version | head -n 1" -- bash -c "which python" -- bash -c "python -V" - bash -c "make --version | head -n 2" - pwd - echo MAKEJOBS=%MAKEJOBS% @@ -105,9 +102,9 @@ test_script: - .\swig.exe -version - if not "%OSVARIANT%"=="" CCache\ccache-swig -V - bash -c "file ./swig.exe" -- bash -c "make check-%SWIGLANG%-version" -- bash -c "time make -k check-%SWIGLANG%-examples %CHECK_OPTIONS%" -- bash -c "time make -k check-%SWIGLANG%-test-suite -j%MAKEJOBS% %CHECK_OPTIONS%" +- if not "%SWIGLANG%"=="" bash -c "make check-%SWIGLANG%-version %CHECK_OPTIONS%" +- if not "%SWIGLANG%"=="" bash -c "time make -k check-%SWIGLANG%-examples %CHECK_OPTIONS%" +- if not "%SWIGLANG%"=="" bash -c "time make -k check-%SWIGLANG%-test-suite -j%MAKEJOBS% %CHECK_OPTIONS%" # Do not build on tags (GitHub only) skip_tags: true From a1cea4f483144952989580f54e73f38f94b90562 Mon Sep 17 00:00:00 2001 From: Joel Anderson Date: Wed, 21 Mar 2018 19:12:54 -0400 Subject: [PATCH 438/455] Fix ruby %alias directive for native c functions Using the %alias directive on native C functions causes swig to segfault due to a dereference of klass (which is NULL for native C functions) in the defineAliases function of the Ruby module. This commit adds support for an alias of native C functions for both separate module as well as global functions, as well as three test cases for the %alias directive of the Ruby module. Fixes: mod.i %module ruby_alias %alias get_my_name "nickname,fullname"; %inline %{ const char *get_my_name(){ return "Chester Tester"; } %} $ swig -ruby mod.i Segmentation fault Signed-off-by: Joel Anderson --- Examples/test-suite/ruby/Makefile.in | 4 +++ .../ruby/ruby_alias_global_function_runme.rb | 20 ++++++++++++++ .../ruby/ruby_alias_method_runme.rb | 24 +++++++++++++++++ .../ruby/ruby_alias_module_function_runme.rb | 26 +++++++++++++++++++ .../test-suite/ruby_alias_global_function.i | 11 ++++++++ Examples/test-suite/ruby_alias_method.i | 26 +++++++++++++++++++ .../test-suite/ruby_alias_module_function.i | 11 ++++++++ Source/Modules/ruby.cxx | 8 +++++- 8 files changed, 129 insertions(+), 1 deletion(-) create mode 100644 Examples/test-suite/ruby/ruby_alias_global_function_runme.rb create mode 100644 Examples/test-suite/ruby/ruby_alias_method_runme.rb create mode 100644 Examples/test-suite/ruby/ruby_alias_module_function_runme.rb create mode 100644 Examples/test-suite/ruby_alias_global_function.i create mode 100644 Examples/test-suite/ruby_alias_method.i create mode 100644 Examples/test-suite/ruby_alias_module_function.i diff --git a/Examples/test-suite/ruby/Makefile.in b/Examples/test-suite/ruby/Makefile.in index 292244a9e..add65fe9f 100644 --- a/Examples/test-suite/ruby/Makefile.in +++ b/Examples/test-suite/ruby/Makefile.in @@ -22,6 +22,7 @@ CPP_TEST_CASES = \ li_std_stack \ li_std_wstring \ primitive_types \ + ruby_alias_method \ ruby_keywords \ ruby_minherit_shared_ptr \ ruby_naming \ @@ -44,6 +45,8 @@ CPP11_TEST_CASES = \ C_TEST_CASES += \ li_cstring \ + ruby_alias_global_function \ + ruby_alias_module_function \ ruby_manual_proxy \ include $(srcdir)/../common.mk @@ -52,6 +55,7 @@ include $(srcdir)/../common.mk SWIGOPT += -w801 -noautorename -features autodoc=4 # Custom tests - tests with additional commandline options +ruby_alias_global_function.ctest: SWIGOPT += -globalmodule ruby_naming.cpptest: SWIGOPT += -autorename # Rules for the different types of tests diff --git a/Examples/test-suite/ruby/ruby_alias_global_function_runme.rb b/Examples/test-suite/ruby/ruby_alias_global_function_runme.rb new file mode 100644 index 000000000..14e38e4cf --- /dev/null +++ b/Examples/test-suite/ruby/ruby_alias_global_function_runme.rb @@ -0,0 +1,20 @@ +#!/usr/bin/env ruby +# +# Runtime tests for ruby_alias_global_function.i +# + +require 'swig_assert' +require 'ruby_alias_global_function' + +expected_name = get_my_name + +swig_assert(fullname == expected_name, msg: "nickname not working as expected") +swig_assert(nickname == expected_name, msg: "fullname not working as expected") + +if method(:nickname).respond_to?(:original_name) + swig_assert_equal_simple(method(:nickname).original_name, :get_my_name) + swig_assert_equal_simple(method(:fullname).original_name, :get_my_name) +else + swig_assert(method(:nickname) == method(:get_my_name), msg: "nickname is not an alias of get_my_name") + swig_assert(method(:fullname) == method(:get_my_name), msg: "fullname is not an alias of get_my_name") +end diff --git a/Examples/test-suite/ruby/ruby_alias_method_runme.rb b/Examples/test-suite/ruby/ruby_alias_method_runme.rb new file mode 100644 index 000000000..c19101e63 --- /dev/null +++ b/Examples/test-suite/ruby/ruby_alias_method_runme.rb @@ -0,0 +1,24 @@ +#!/usr/bin/env ruby +# +# Runtime tests for ruby_alias_method.i +# + +require 'swig_assert' +require 'ruby_alias_method' + +include Ruby_alias_method + +expected_name = "Chester Tester" +syn = Synonym.new(expected_name) + +swig_assert(syn.getMyName() == expected_name, msg: "getMyName not working as expected") +swig_assert(syn.nickname() == expected_name, msg: "nickname not working as expected") +swig_assert(syn.fullname() == expected_name, msg: "fullname not working as expected") + +if syn.method(:nickname).respond_to?(:original_name) + swig_assert_equal_simple(syn.method(:nickname).original_name, :getMyName) + swig_assert_equal_simple(syn.method(:fullname).original_name, :getMyName) +else + swig_assert(syn.method(:nickname) == syn.method(:getMyName)) + swig_assert(syn.method(:fullname) == syn.method(:getMyName)) +end diff --git a/Examples/test-suite/ruby/ruby_alias_module_function_runme.rb b/Examples/test-suite/ruby/ruby_alias_module_function_runme.rb new file mode 100644 index 000000000..1f4205f1f --- /dev/null +++ b/Examples/test-suite/ruby/ruby_alias_module_function_runme.rb @@ -0,0 +1,26 @@ +#!/usr/bin/env ruby +# +# Runtime tests for ruby_alias_module_function.i +# + +require 'swig_assert' +require 'ruby_alias_module_function' + +include Ruby_alias_module_function + +expected_name = Ruby_alias_module_function.get_my_name + +swig_assert(Ruby_alias_module_function.nickname == expected_name, msg: "nickname returned a different result than get_my_name") +swig_assert(Ruby_alias_module_function.fullname == expected_name, msg: "fullname returned a different result than get_my_name") + +nickname_method = Ruby_alias_module_function.method(:nickname) +fullname_method = Ruby_alias_module_function.method(:fullname) + +if nickname_method.respond_to?(:original_name) + swig_assert_equal_simple(nickname_method.original_name, :get_my_name) + swig_assert_equal_simple(fullname_method.original_name, :get_my_name) +else + original_method = Ruby_alias_module_function.method(:get_my_name) + swig_assert(nickname_method == original_method, msg: "nickname is not an alias of get_my_name") + swig_assert(fullname_method == original_method, msg: "fullname is not an alias of get_my_name") +end diff --git a/Examples/test-suite/ruby_alias_global_function.i b/Examples/test-suite/ruby_alias_global_function.i new file mode 100644 index 000000000..bddb24959 --- /dev/null +++ b/Examples/test-suite/ruby_alias_global_function.i @@ -0,0 +1,11 @@ +%module ruby_alias_global_function + +%alias get_my_name "nickname,fullname"; + +%inline %{ + +const char *get_my_name(){ + return "Chester Tester"; +} + +%} diff --git a/Examples/test-suite/ruby_alias_method.i b/Examples/test-suite/ruby_alias_method.i new file mode 100644 index 000000000..9ddcfce5e --- /dev/null +++ b/Examples/test-suite/ruby_alias_method.i @@ -0,0 +1,26 @@ +%module ruby_alias_method +%include + +%alias Synonym::getMyName "nickname,fullname" + +%inline %{ + +class Synonym { +private: + std::string myName; + +public: + Synonym(std::string myName); + + std::string getMyName(); +}; + +Synonym::Synonym(std::string myName){ + this->myName = myName; +}; + +std::string Synonym::getMyName(){ + return this->myName; +}; + +%} diff --git a/Examples/test-suite/ruby_alias_module_function.i b/Examples/test-suite/ruby_alias_module_function.i new file mode 100644 index 000000000..900de5f1d --- /dev/null +++ b/Examples/test-suite/ruby_alias_module_function.i @@ -0,0 +1,11 @@ +%module ruby_alias_module_function + +%alias get_my_name "nickname,fullname"; + +%inline %{ + +const char *get_my_name(){ + return "Chester Tester"; +} + +%} diff --git a/Source/Modules/ruby.cxx b/Source/Modules/ruby.cxx index 69a849d16..78bd23a6e 100644 --- a/Source/Modules/ruby.cxx +++ b/Source/Modules/ruby.cxx @@ -1316,7 +1316,13 @@ public: Iterator alias = First(aliases); while (alias.item) { if (Len(alias.item) > 0) { - if (multipleInheritance) { + if (current == NO_CPP) { + if (useGlobalModule) { + Printv(f_init, tab4, "rb_define_alias(rb_cObject, \"", alias.item, "\", \"", iname, "\");\n", NIL); + } else { + Printv(f_init, tab4, "rb_define_alias(rb_singleton_class(", modvar, "), \"", alias.item, "\", \"", iname, "\");\n", NIL); + } + } else if (multipleInheritance) { Printv(klass->init, tab4, "rb_define_alias(", klass->mImpl, ", \"", alias.item, "\", \"", iname, "\");\n", NIL); } else { Printv(klass->init, tab4, "rb_define_alias(", klass->vname, ", \"", alias.item, "\", \"", iname, "\");\n", NIL); From 5f5ab92d5e9658ae0b120591176043049a002b52 Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Tue, 3 Apr 2018 17:44:51 +1200 Subject: [PATCH 439/455] Fix typo --- CHANGES.current | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGES.current b/CHANGES.current index 6dbfbe4a0..d923c2974 100644 --- a/CHANGES.current +++ b/CHANGES.current @@ -147,7 +147,7 @@ Version 4.0.0 (in progress) https://sourceforge.net/p/swig/bugs/826/ 2017-10-06: wsfulton - [Python] Issue #1108. Fix platorm inconsistency in Python default argument handling. + [Python] Issue #1108. Fix platform inconsistency in Python default argument handling. 32 bit and 64 bit compiled versions of SWIG generated different Python files when default arguments were outside the range of 32 bit signed integers. The default arguments specified in Python are now only those that are in the From 3bea8f6b7e0449946c12a0ce2c5aa893d6026883 Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Tue, 3 Apr 2018 18:01:58 +1200 Subject: [PATCH 440/455] [Ruby] Pass Qnil instead of NULL to rb_funcall() This silences GCC -Wconversion-null warning (on by default with recent GCC). --- CHANGES.current | 4 ++++ Doc/Manual/Ruby.html | 20 ++++++++++---------- Examples/ruby/hashargs/example.i | 4 ++-- Source/Modules/ruby.cxx | 2 +- 4 files changed, 17 insertions(+), 13 deletions(-) diff --git a/CHANGES.current b/CHANGES.current index d923c2974..84842a830 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.0.0 (in progress) =========================== +2018-04-03: olly + [Ruby] Fix to pass Qnil instead of NULL to rb_funcall(), which silences GCC + -Wconversion-null warning (on by default with recent GCC). + 2018-03-09: fultonwi [Java] #1184 Fix swigReleaseOwnership() and swigTakeOwnership() regression for non-director classes. Restores a dynamic_cast which was previously removed. diff --git a/Doc/Manual/Ruby.html b/Doc/Manual/Ruby.html index 04a4f1cee..433afd7ad 100644 --- a/Doc/Manual/Ruby.html +++ b/Doc/Manual/Ruby.html @@ -3704,7 +3704,7 @@ value:

        %typemap(in) (int nattributes, const char **names, const int *values)
           (VALUE keys_arr, int i, VALUE key, VALUE val) {
             Check_Type($input, T_HASH);
        -    $1 = NUM2INT(rb_funcall($input, rb_intern("size"), 0, NULL));
        +    $1 = NUM2INT(rb_funcall($input, rb_intern("size"), 0, Qnil));
         }
        @@ -3717,7 +3717,7 @@ the keys and values from the hash:

        %typemap(in) (int nattributes, const char **names, const int *values)
           (VALUE keys_arr, int i, VALUE key, VALUE val) {
             Check_Type($input, T_HASH);
        -    $1 = NUM2INT(rb_funcall($input, rb_intern("size"), 0, NULL));
        +    $1 = NUM2INT(rb_funcall($input, rb_intern("size"), 0, Qnil));
             $2 = NULL;
             $3 = NULL;
             if ($1 > 0) {
        @@ -3736,13 +3736,13 @@ of the keys) and then start looping over the elements in that array: 

        %typemap(in) (int nattributes, const char **names, const int *values)
           (VALUE keys_arr, int i, VALUE key, VALUE val) {
             Check_Type($input, T_HASH);
        -    $1 = NUM2INT(rb_funcall($input, rb_intern("size"), 0, NULL));
        +    $1 = NUM2INT(rb_funcall($input, rb_intern("size"), 0, Qnil));
             $2 = NULL;
             $3 = NULL;
             if ($1 > 0) {
               $2 = (char **) malloc($1*sizeof(char *));
               $3 = (int *) malloc($1*sizeof(int));
        -      keys_arr = rb_funcall($input, rb_intern("keys"), 0, NULL);
        +      keys_arr = rb_funcall($input, rb_intern("keys"), 0, Qnil);
               for (i = 0; i < $1; i++) {
               }
             }
        @@ -3758,13 +3758,13 @@ corresponding to that key in the hash: 

        %typemap(in) (int nattributes, const char **names, const int *values)
           (VALUE keys_arr, int i, VALUE key, VALUE val) {
             Check_Type($input, T_HASH);
        -    $1 = NUM2INT(rb_funcall($input, rb_intern("size"), 0, NULL));
        +    $1 = NUM2INT(rb_funcall($input, rb_intern("size"), 0, Qnil));
             $2 = NULL;
             $3 = NULL;
             if ($1 > 0) {
               $2 = (char **) malloc($1*sizeof(char *));
               $3 = (int *) malloc($1*sizeof(int));
        -      keys_arr = rb_funcall($input, rb_intern("keys"), 0, NULL);
        +      keys_arr = rb_funcall($input, rb_intern("keys"), 0, Qnil);
               for (i = 0; i < $1; i++) {
                 key = rb_ary_entry(keys_arr, i);
                 val = rb_hash_aref($input, key);
        @@ -3781,13 +3781,13 @@ value is a Fixnum: 

        %typemap(in) (int nattributes, const char **names, const int *values)
           (VALUE keys_arr, int i, VALUE key, VALUE val) {
             Check_Type($input, T_HASH);
        -    $1 = NUM2INT(rb_funcall($input, rb_intern("size"), 0, NULL));
        +    $1 = NUM2INT(rb_funcall($input, rb_intern("size"), 0, Qnil));
             $2 = NULL;
             $3 = NULL;
             if ($1 > 0) {
               $2 = (char **) malloc($1*sizeof(char *));
               $3 = (int *) malloc($1*sizeof(int));
        -      keys_arr = rb_funcall($input, rb_intern("keys"), 0, NULL);
        +      keys_arr = rb_funcall($input, rb_intern("keys"), 0, Qnil);
               for (i = 0; i < $1; i++) {
                 key = rb_ary_entry(keys_arr, i);
                 val = rb_hash_aref($input, key);
        @@ -3805,13 +3805,13 @@ equivalents and store them in our local C arrays: 

        %typemap(in) (int nattributes, const char **names, const int *values)
           (VALUE keys_arr, int i, VALUE key, VALUE val) {
           Check_Type($input, T_HASH);
        -  $1 = NUM2INT(rb_funcall($input, rb_intern("size"), 0, NULL));
        +  $1 = NUM2INT(rb_funcall($input, rb_intern("size"), 0, Qnil));
           $2 = NULL;
           $3 = NULL;
           if ($1 > 0) {
             $2 = (char **) malloc($1*sizeof(char *));
             $3 = (int *) malloc($1*sizeof(int));
        -    keys_arr = rb_funcall($input, rb_intern("keys"), 0, NULL);
        +    keys_arr = rb_funcall($input, rb_intern("keys"), 0, Qnil);
             for (i = 0; i < $1; i++) {
               key = rb_ary_entry(keys_arr, i);
               val = rb_hash_aref($input, key);
        diff --git a/Examples/ruby/hashargs/example.i b/Examples/ruby/hashargs/example.i
        index 10e209e5f..4c3f3070b 100644
        --- a/Examples/ruby/hashargs/example.i
        +++ b/Examples/ruby/hashargs/example.i
        @@ -2,13 +2,13 @@
         
         %typemap(in) (int nattributes, const char **names, const int *values) (VALUE keys_ary, int i, VALUE key, VALUE val) {
           Check_Type($input, T_HASH);
        -  $1 = NUM2INT(rb_funcall($input, rb_intern("size"), 0, NULL));
        +  $1 = NUM2INT(rb_funcall($input, rb_intern("size"), 0, Qnil));
           $2 = NULL;
           $3 = NULL;
           if ($1 > 0) {
             $2 = (char **) malloc($1*sizeof(char *));
             $3 = (int *) malloc($1*sizeof(int));
        -    keys_ary = rb_funcall($input, rb_intern("keys"), 0, NULL);
        +    keys_ary = rb_funcall($input, rb_intern("keys"), 0, Qnil);
             for (i = 0; i < $1; i++) {
               key = rb_ary_entry(keys_ary, i);
               val = rb_hash_aref($input, key);
        diff --git a/Source/Modules/ruby.cxx b/Source/Modules/ruby.cxx
        index 69a849d16..641604620 100644
        --- a/Source/Modules/ruby.cxx
        +++ b/Source/Modules/ruby.cxx
        @@ -3046,7 +3046,7 @@ public:
               if (argc > 0) {
         	Printf(w->code, "%s = rb_funcall(swig_get_self(), rb_intern(\"%s\"), %d%s);\n", Swig_cresult_name(), methodName, argc, args);
               } else {
        -	Printf(w->code, "%s = rb_funcall(swig_get_self(), rb_intern(\"%s\"), 0, NULL);\n", Swig_cresult_name(), methodName);
        +	Printf(w->code, "%s = rb_funcall(swig_get_self(), rb_intern(\"%s\"), 0, Qnil);\n", Swig_cresult_name(), methodName);
               }
               if ( initstack ) Printf(w->code, "SWIG_RELEASE_STACK;\n");
             }
        
        From 15a09ffbdc9e45f1f99da62391b797e0815f8706 Mon Sep 17 00:00:00 2001
        From: William S Fulton 
        Date: Sat, 7 Apr 2018 12:34:39 +0100
        Subject: [PATCH 441/455] Add changes entry for Ruby %alias fix for global
         functions
        
        ---
         CHANGES.current | 3 +++
         1 file changed, 3 insertions(+)
        
        diff --git a/CHANGES.current b/CHANGES.current
        index 84842a830..72764c694 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.0.0 (in progress)
         ===========================
         
        +2018-04-07: goatshriek
        +            [Ruby] #1213 Fix ruby %alias directive for global C/C++ functions.
        +
         2018-04-03: olly
         	    [Ruby] Fix to pass Qnil instead of NULL to rb_funcall(), which silences GCC
         	    -Wconversion-null warning (on by default with recent GCC).
        
        From cf8f99ba442c6cb0c658576c08522d455836633e Mon Sep 17 00:00:00 2001
        From: Ben Elliston 
        Date: Tue, 10 Apr 2018 10:07:47 +1000
        Subject: [PATCH 442/455] * Makefile.in (configfiles): Update URLs for latest
         configfiles.
        
        We haven't uploaded the latest version of these scripts to ftp.gnu.org
        in over 10 years. See ftp://ftp.gnu.org/pub/gnu/config/README. The
        best place to fetch them from is the Savannah git repository.
        ---
         Makefile.in | 4 ++--
         1 file changed, 2 insertions(+), 2 deletions(-)
        
        diff --git a/Makefile.in b/Makefile.in
        index c19e16a97..9f81598cd 100644
        --- a/Makefile.in
        +++ b/Makefile.in
        @@ -583,9 +583,9 @@ srcrpm:
         # version 1.10 for our case of not having a top level Makefile.am. Until then we
         # can fetch them manually and will have to commit them to Git.
         configfiles:
        -	wget ftp://ftp.gnu.org/pub/gnu/config/config.guess -O Tools/config/config.guess
        +	wget 'https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess' -O Tools/config/config.guess
         	chmod a+x Tools/config/config.guess
        -	wget ftp://ftp.gnu.org/pub/gnu/config/config.sub -O Tools/config/config.sub
        +	wget 'https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub' -O Tools/config/config.sub
         	chmod a+x Tools/config/config.sub
         
         # Regenerate Makefile if Makefile.in or config.status have changed.
        
        From 46ab0c252da9ab846265a60517ca462e5256cd24 Mon Sep 17 00:00:00 2001
        From: Geert Janssens 
        Date: Mon, 16 Apr 2018 19:52:29 +0200
        Subject: [PATCH 443/455] Fix off-by-one error
        
        The condition only applies to guile 1.8 and older so it should really
        have been '<2' all along. As we already have such a conditional block
        earlier up, merge the two together as well.
        ---
         Lib/guile/guile_scm_run.swg | 6 ++----
         1 file changed, 2 insertions(+), 4 deletions(-)
        
        diff --git a/Lib/guile/guile_scm_run.swg b/Lib/guile/guile_scm_run.swg
        index 1cc08b024..274f19715 100644
        --- a/Lib/guile/guile_scm_run.swg
        +++ b/Lib/guile/guile_scm_run.swg
        @@ -24,6 +24,8 @@ scm_module_variable (SCM module, SCM sym)
           return scm_sym2var (sym, scm_module_lookup_closure (module), SCM_BOOL_F);
         }
         
        +#define scm_to_utf8_string scm_to_locale_string
        +#define scm_from_utf8_string scm_from_locale_string
         #endif
         
         #if SCM_MAJOR_VERSION >= 2
        @@ -40,10 +42,6 @@ typedef struct swig_guile_clientdata {
           SCM goops_class;
         } swig_guile_clientdata;
         
        -#if SCM_MAJOR_VERSION <= 2
        -#define scm_to_utf8_string scm_to_locale_string
        -#define scm_from_utf8_string scm_from_locale_string
        -#endif
         #define SWIG_scm2str(s) \
           SWIG_Guile_scm2newstr(s, NULL)
         #define SWIG_str02scm(str) \
        
        From 209586c991c1a42df1e2cdb23f520fb18a79525c Mon Sep 17 00:00:00 2001
        From: Ivan Leonov 
        Date: Tue, 10 Apr 2018 14:22:15 +0300
        Subject: [PATCH 444/455] Fix typo in help --with-jscoreinc and
         --with-jscorelib
        
        ---
         configure.ac | 4 ++--
         1 file changed, 2 insertions(+), 2 deletions(-)
        
        diff --git a/configure.ac b/configure.ac
        index a40c6662d..7b5b54c65 100644
        --- a/configure.ac
        +++ b/configure.ac
        @@ -1492,7 +1492,7 @@ else
         
           # check for include files
           AC_MSG_CHECKING(for JavaScriptCore/JavaScript.h)
        -  AC_ARG_WITH(jscoreinc, [  --with-jscinc=path      Set location of Javascript include directory], [JSCOREINCDIR="$withval"], [JSCOREINCDIR=])
        +  AC_ARG_WITH(jscoreinc, [  --with-jscoreinc=path      Set location of Javascript include directory], [JSCOREINCDIR="$withval"], [JSCOREINCDIR=])
         
           JSCOREVERSION=
         
        @@ -1526,7 +1526,7 @@ else
           fi
         
           # check for JavaScriptCore/Webkit libraries
        -  AC_ARG_WITH(jscorelib,[  --with-jsclib=path      Set location of the JavaScriptCore/Webkit library directory],[JSCORELIB="-L$withval"], [JSCORELIB=])
        +  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 "$PKGCONFIG"; then
             AC_MSG_CHECKING(for JavaScriptCore/Webkit library)
        
        From 34ee191769e885fefa380d4e7c09c17f3d103ae6 Mon Sep 17 00:00:00 2001
        From: Ivan Leonov 
        Date: Tue, 10 Apr 2018 14:32:27 +0300
        Subject: [PATCH 445/455] Add if-no-present action for jsv8inc arg
        
        ---
         configure.ac | 2 +-
         1 file changed, 1 insertion(+), 1 deletion(-)
        
        diff --git a/configure.ac b/configure.ac
        index 7b5b54c65..833cb37bf 100644
        --- a/configure.ac
        +++ b/configure.ac
        @@ -1550,7 +1550,7 @@ else
         
           # check for include files
           AC_MSG_CHECKING(for V8 Javascript v8.h)
        -  AC_ARG_WITH(jsv8inc, [  --with-jsv8inc=path     Set location of Javascript v8 include directory], [JSV8INCDIR="$withval"])
        +  AC_ARG_WITH(jsv8inc, [  --with-jsv8inc=path     Set location of Javascript v8 include directory], [JSV8INCDIR="$withval"], [JSV8INCDIR=])
         
           # if not include dir is specified we try to find
           if test -z "$JSV8INCDIR"; then
        
        From 2ab3f4d744682d6512e216f57e0fb7cecea04169 Mon Sep 17 00:00:00 2001
        From: Olly Betts 
        Date: Wed, 18 Apr 2018 17:00:02 +1200
        Subject: [PATCH 446/455] [Python] Suppress new pycodestyle warning
        
        E252 missing whitespace around parameter equals
        ---
         CHANGES.current                        | 4 ++++
         Examples/Makefile.in                   | 2 +-
         Examples/test-suite/python/Makefile.in | 2 +-
         3 files changed, 6 insertions(+), 2 deletions(-)
        
        diff --git a/CHANGES.current b/CHANGES.current
        index 72764c694..f15c99e90 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.0.0 (in progress)
         ===========================
         
        +2018-04-18: olly
        +	    [Python] Suppress new pycodestyle warning:
        +	    E252 missing whitespace around parameter equals
        +
         2018-04-07: goatshriek
                     [Ruby] #1213 Fix ruby %alias directive for global C/C++ functions.
         
        diff --git a/Examples/Makefile.in b/Examples/Makefile.in
        index 81697c8b2..8218f5122 100644
        --- a/Examples/Makefile.in
        +++ b/Examples/Makefile.in
        @@ -335,7 +335,7 @@ else
         endif
         
         PYCODESTYLE       = @PYCODESTYLE@
        -PYCODESTYLE_FLAGS = --ignore=E402,E501,E30,W291,W391
        +PYCODESTYLE_FLAGS = --ignore=E252,E30,E402,E501,E731,W291,W391
         
         # ----------------------------------------------------------------
         # Build a C dynamically loadable module
        diff --git a/Examples/test-suite/python/Makefile.in b/Examples/test-suite/python/Makefile.in
        index 12844e311..e2aad7c8b 100644
        --- a/Examples/test-suite/python/Makefile.in
        +++ b/Examples/test-suite/python/Makefile.in
        @@ -11,7 +11,7 @@ endif
         LANGUAGE     = python
         PYTHON       = $(PYBIN)
         PYCODESTYLE       = @PYCODESTYLE@
        -PYCODESTYLE_FLAGS = --ignore=E30,E402,E501,E731,W291,W391
        +PYCODESTYLE_FLAGS = --ignore=E252,E30,E402,E501,E731,W291,W391
         
         #*_runme.py for Python 2.x, *_runme3.py for Python 3.x
         PY2SCRIPTSUFFIX = _runme.py
        
        From 5f6012039abb6ec9e9dfea801effa6b02fd102bc Mon Sep 17 00:00:00 2001
        From: Vsevolod Kvachev 
        Date: Thu, 19 Apr 2018 23:04:37 +0300
        Subject: [PATCH 447/455] Fix go version matching in configure for go1.10
        
        ---
         configure.ac | 10 +++++-----
         1 file changed, 5 insertions(+), 5 deletions(-)
        
        diff --git a/configure.ac b/configure.ac
        index 833cb37bf..ba1631743 100644
        --- a/configure.ac
        +++ b/configure.ac
        @@ -2584,7 +2584,7 @@ else
             GOVERSIONOPTION=version
             go_version=$($GO $GOVERSIONOPTION | sed -e 's/go version //')
             case "$go_version" in
        -    go1 | go1.[[01234]]*)
        +    go1 | go1.[[01234]] | go1.[[01234]].*)
               GOC=$(sh -c "$(go env) && echo \$GOCHAR")c
               ;;
             *)
        @@ -2593,7 +2593,7 @@ else
             esac
             AC_MSG_CHECKING([whether go version is too old])
             case $go_version in
        -    go1.1* | go1.0* | go1 )
        +    go1.1.* | go1.1 | go1.0 | go1.0.* | go1 )
               AC_MSG_RESULT([yes - minimum version is 1.2])
               GO=
               GOOPT="-intgosize 32"
        @@ -2611,13 +2611,13 @@ else
               ;;
             esac
             case $go_version in
        -    go1.0* | go1 | go1.1*)
        +    go1.0 | go1.0.* | go1 | go1.1 | go1.1.*)
               GOOPT="$GOOPT -use-shlib"
               ;;
        -    go1.2*)
        +    go1.2 | go1.2.*)
               GO12=true
               ;;
        -    go1.3* | go1.4*)
        +    go1.3 | go1.3.* | go1.4 | go1.4.*)
               GO13=true
               ;;
             *)
        
        From 0d2a6466549f34c74835943c979ee315feb3eda8 Mon Sep 17 00:00:00 2001
        From: Geert Janssens 
        Date: Wed, 18 Apr 2018 11:10:11 +0200
        Subject: [PATCH 448/455] guile - use more reliable method of finding guile
         executable based on guile-config
        
        This allows to only specify --with-guile-config=xyz to configure and it will pick up
        the correct guile executable in case more versions of guile are installed on the same
        system. For example on Fedora 27, I have
        /usr/bin/guile1.8
        /usr/bin/guile (which is guile 2.0)
        /usr/bin/guile2.2
        Without this patch the configure script would always pick /usr/bin/guile regardless of which
        guile-config I would specify (guile1.8-config, guile-config or guile-config2.2).
        With the patch guile2.2 is now correctly picked for guile-config2.2.
        Unfortunately it still won't work with guile 1.8 because that version can't provide the
        executable name via guile-config yet. In that case configure will fall back to the old
        behaviour. On my Fedora 27 system that would mean it would still pick the wrong
        executable. However this is not critical because that as well can be overridden by
        setting --with-guile=abc. I don't see an easy way to improve on this.
        ---
         configure.ac | 21 ++++++++++++++-------
         1 file changed, 14 insertions(+), 7 deletions(-)
        
        diff --git a/configure.ac b/configure.ac
        index 833cb37bf..664c0fa1a 100644
        --- a/configure.ac
        +++ b/configure.ac
        @@ -1704,13 +1704,20 @@ else
           fi
           if test -n "$GUILE_CONFIG" ; then
             if test x"$GUILE" = xyes; then
        -      AC_MSG_CHECKING([for guile bindir])
        -      guile_bindir="`$GUILE_CONFIG info bindir`"
        -      AC_MSG_RESULT([$guile_bindir])
        -      GUILE=$guile_bindir/guile
        -      if ! test -f "$GUILE" ; then
        -	GUILE=
        -        AC_PATH_PROG(GUILE, guile)
        +      AC_MSG_CHECKING([for guile executable])
        +      if $GUILE_CONFIG info guile > /dev/null 2>&1; then
        +        GUILE="`$GUILE_CONFIG info guile`"
        +        AC_MSG_RESULT([$GUILE])
        +      else
        +        AC_MSG_RESULT([not in guile-config, constructing path])
        +        AC_MSG_CHECKING([for guile bindir])
        +        guile_bindir="`$GUILE_CONFIG info bindir`"
        +        AC_MSG_RESULT([$guile_bindir])
        +        GUILE=$guile_bindir/guile
        +        if ! test -f "$GUILE" ; then
        +          GUILE=
        +          AC_PATH_PROG(GUILE, guile)
        +        fi
               fi
             fi
         
        
        From d1f7054b7e620deaf33e8f75eac73389a60141d9 Mon Sep 17 00:00:00 2001
        From: Geert Janssens 
        Date: Wed, 18 Apr 2018 11:46:56 +0200
        Subject: [PATCH 449/455] guile - replace obsolete scm_listify with scm_list_n
        
        scm_list_n is available in all guile versions supported by swig, while
        scm_listify no longer is in guile 2.2
        ---
         Lib/guile/guile_scm.swg |  4 ++--
         Lib/guile/typemaps.i    | 16 ++++++++--------
         2 files changed, 10 insertions(+), 10 deletions(-)
        
        diff --git a/Lib/guile/guile_scm.swg b/Lib/guile/guile_scm.swg
        index dfd5da271..37eef6f33 100644
        --- a/Lib/guile/guile_scm.swg
        +++ b/Lib/guile/guile_scm.swg
        @@ -26,10 +26,10 @@
             else {									\
               if (!gswig_list_p) {							\
         	      gswig_list_p = 1;							\
        -	      gswig_result = scm_listify(gswig_result, object, SCM_UNDEFINED);	\
        +	      gswig_result = scm_list_n(gswig_result, object, SCM_UNDEFINED);	\
               }									\
               else									\
        -            gswig_result = scm_append(scm_listify(gswig_result, scm_listify(object, SCM_UNDEFINED), SCM_UNDEFINED));		\
        +            gswig_result = scm_append(scm_list_n(gswig_result, scm_list_n(object, SCM_UNDEFINED), SCM_UNDEFINED));		\
             }
         
         %}
        diff --git a/Lib/guile/typemaps.i b/Lib/guile/typemaps.i
        index 0d130f523..f2926c163 100644
        --- a/Lib/guile/typemaps.i
        +++ b/Lib/guile/typemaps.i
        @@ -69,13 +69,13 @@
         %typemap(throws) SWIGTYPE {
           $<ype temp = new $ltype($1);
           scm_throw(scm_from_locale_symbol((char *) "swig-exception"),
        -	    scm_listify(SWIG_NewPointerObj(temp, $&descriptor, 1),
        +	    scm_list_n(SWIG_NewPointerObj(temp, $&descriptor, 1),
         		    SCM_UNDEFINED));
         }
         
         %typemap(throws) SWIGTYPE & {
           scm_throw(scm_from_locale_symbol((char *) "swig-exception"),
        -	    scm_listify(SWIG_NewPointerObj(&$1, $descriptor, 1),
        +	    scm_list_n(SWIG_NewPointerObj(&$1, $descriptor, 1),
         		    SCM_UNDEFINED));
         }
         
        @@ -87,13 +87,13 @@
         
         %typemap(throws) SWIGTYPE * {
           scm_throw(scm_from_locale_symbol((char *) "swig-exception"),
        -	    scm_listify(SWIG_NewPointerObj($1, $descriptor, 1),
        +	    scm_list_n(SWIG_NewPointerObj($1, $descriptor, 1),
         		    SCM_UNDEFINED));
         }
         
         %typemap(throws) SWIGTYPE [] {
           scm_throw(scm_from_locale_symbol((char *) "swig-exception"),
        -	    scm_listify(SWIG_NewPointerObj($1, $descriptor, 1),
        +	    scm_list_n(SWIG_NewPointerObj($1, $descriptor, 1),
         		    SCM_UNDEFINED));
         }
         
        @@ -176,7 +176,7 @@
         %typemap(varout) enum SWIGTYPE  { $result = scm_from_long((int)$1); }
         %typemap(throws) enum SWIGTYPE {
           scm_throw(scm_from_locale_symbol((char *) "swig-exception"),
        -     scm_listify(scm_from_long((int)$1), SCM_UNDEFINED));
        +     scm_list_n(scm_from_long((int)$1), SCM_UNDEFINED));
         }
         
         /* The SIMPLE_MAP_WITH_EXPR macro below defines the whole set of
        @@ -225,7 +225,7 @@
          %typemap(throws) C_NAME {
            C_NAME swig_c_value = $1;
            scm_throw(scm_from_locale_symbol((char *) "swig-exception"),
        -	     scm_listify(C_TO_SCM_EXPR, SCM_UNDEFINED));
        +	     scm_list_n(C_TO_SCM_EXPR, SCM_UNDEFINED));
          }
         %enddef
         
        @@ -269,7 +269,7 @@
          /* Throw typemap */
          %typemap(throws) C_NAME {
            scm_throw(scm_from_locale_symbol((char *) "swig-exception"),
        -	     scm_listify(C_TO_SCM($1), SCM_UNDEFINED));
        +	     scm_list_n(C_TO_SCM($1), SCM_UNDEFINED));
          }
         %enddef
         
        @@ -344,7 +344,7 @@ SIMPLE_MAP(unsigned long long, scm_to_ulong_long, scm_from_ulong_long, integer);
         
         %typemap(throws) char * {
           scm_throw(scm_from_locale_symbol((char *) "swig-exception"),
        -	    scm_listify(SWIG_str02scm($1), SCM_UNDEFINED));
        +	    scm_list_n(SWIG_str02scm($1), SCM_UNDEFINED));
         }
         
         /* Void */
        
        From a95ceabb70e9a28686440f0cc0dcb64eae281356 Mon Sep 17 00:00:00 2001
        From: Geert Janssens 
        Date: Wed, 18 Apr 2018 11:52:54 +0200
        Subject: [PATCH 450/455] guile - drop GDB_INTERFACE related stuff
        
        Guile itself has removed it a long time ago:
        http://git.savannah.gnu.org/gitweb/?p=guile.git;a=commit;h=8510e39278161d3cbf8ec4ba87b123fe28763ed4
        There's no need for it. I suspect it's just there because the
        interface file was created based on the then real main source file of guile.
        ---
         Lib/guile/guilemain.i | 5 -----
         1 file changed, 5 deletions(-)
        
        diff --git a/Lib/guile/guilemain.i b/Lib/guile/guilemain.i
        index 925b81fee..809154e99 100644
        --- a/Lib/guile/guilemain.i
        +++ b/Lib/guile/guilemain.i
        @@ -12,11 +12,6 @@
         extern "C" {
         #endif
         
        -/* Debugger interface (don't change the order of the following lines) */
        -#define GDB_TYPE SCM
        -#include 
        -GDB_INTERFACE;
        -
         static void
         inner_main(void *closure, int argc, char **argv)
         {
        
        From b02cb7e0bcf0ae747355b988b45900ed81538823 Mon Sep 17 00:00:00 2001
        From: Geert Janssens 
        Date: Thu, 19 Apr 2018 15:29:07 +0200
        Subject: [PATCH 451/455] Fix guile executable detection on early 2.0.x guile
         versions
        
        Querying guile-config for the executable name was only introduced in guile 2.0.12.
        If it works it's the most reliable method in environments with more than one guile
        executable. If it doesn't work fall back to path detection, assuming the executable
        name is just 'guile'. If that's incorrect it's up to the caller to explicitly
        specify the path to the right guile executable.
        ---
         configure.ac | 15 ++++++++-------
         1 file changed, 8 insertions(+), 7 deletions(-)
        
        diff --git a/configure.ac b/configure.ac
        index 664c0fa1a..0720ad66f 100644
        --- a/configure.ac
        +++ b/configure.ac
        @@ -1705,19 +1705,20 @@ else
           if test -n "$GUILE_CONFIG" ; then
             if test x"$GUILE" = xyes; then
               AC_MSG_CHECKING([for guile executable])
        -      if $GUILE_CONFIG info guile > /dev/null 2>&1; then
        -        GUILE="`$GUILE_CONFIG info guile`"
        +      # Try extracting it via guile-config first. If it's defined there it's the most reliable result
        +      GUILE="`$GUILE_CONFIG info guile 2>/dev/null`"
        +      if test -n "$GUILE";  then
                 AC_MSG_RESULT([$GUILE])
               else
                 AC_MSG_RESULT([not in guile-config, constructing path])
                 AC_MSG_CHECKING([for guile bindir])
                 guile_bindir="`$GUILE_CONFIG info bindir`"
                 AC_MSG_RESULT([$guile_bindir])
        -        GUILE=$guile_bindir/guile
        -        if ! test -f "$GUILE" ; then
        -          GUILE=
        -          AC_PATH_PROG(GUILE, guile)
        -        fi
        +        GUILE="$guile_bindir/guile"
        +      fi
        +      if ! test -f "$GUILE" ; then
        +        GUILE=
        +        AC_PATH_PROG(GUILE, guile)
               fi
             fi
         
        
        From 7e798c18621d1b1b8291a6c8080692e1a3852e4b Mon Sep 17 00:00:00 2001
        From: Geert Janssens 
        Date: Thu, 19 Apr 2018 16:22:56 +0200
        Subject: [PATCH 452/455] Disable guile configuration if guile-config and guile
         report a different version
        
        In addition
        - inform the user when guile gets disabled while it was requested
        - skip unecessary configuration work if guile gets disabled
        ---
         configure.ac | 35 +++++++++++++++++++++++++----------
         1 file changed, 25 insertions(+), 10 deletions(-)
        
        diff --git a/configure.ac b/configure.ac
        index 0720ad66f..789311d53 100644
        --- a/configure.ac
        +++ b/configure.ac
        @@ -1710,7 +1710,7 @@ else
               if test -n "$GUILE";  then
                 AC_MSG_RESULT([$GUILE])
               else
        -        AC_MSG_RESULT([not in guile-config, constructing path])
        +        AC_MSG_RESULT([not found via guile-config - constructing path])
                 AC_MSG_CHECKING([for guile bindir])
                 guile_bindir="`$GUILE_CONFIG info bindir`"
                 AC_MSG_RESULT([$guile_bindir])
        @@ -1722,7 +1722,9 @@ else
               fi
             fi
         
        -    if test -f "$GUILE" ; then
        +    if ! test -f "$GUILE" ; then
        +      AC_MSG_WARN([no suitable guile executable found. Disabling Guile])
        +    else
               AC_MSG_CHECKING([for guile version])
               guile_version=`$GUILE -c '(display (effective-version))'`
               AC_MSG_RESULT([$guile_version])
        @@ -1730,20 +1732,33 @@ else
               guile_good_version=`$GUILE -c '(if (>= (string->number (effective-version)) 1.8) (display "yes") (display "no"))'`
               AC_MSG_RESULT([$guile_good_version])
               if test x"$guile_good_version" != xyes ; then
        +        AC_MSG_WARN([at least guile version 1.8 is required. Disabling Guile])
                 GUILE=
               fi
             fi
         
        -    if test -z "$GUILE_CFLAGS" ; then
        -      AC_MSG_CHECKING([for guile compile flags])
        -      GUILE_CFLAGS="`$GUILE_CONFIG compile`" # Note that this can sometimes be empty
        -      AC_MSG_RESULT([$GUILE_CFLAGS])
        +    if test -f "$GUILE" ; then
        +      # Test if guile-config and guile versions match. They should.
        +      gc_version="`$GUILE_CONFIG --version 2>&1 | sed '1 s/.* //;q'`"
        +      g_version="`$GUILE --version | sed '1 s/.* //;q'`"
        +      if test "$gc_version" != "$g_version"; then
        +        AC_MSG_WARN([different versions reported by $GUILE_CONFIG ($gc_version) and $GUILE ($g_version). Disabling Guile])
        +        GUILE=
        +      fi
             fi
         
        -    if test -z "$GUILE_LIBS" ; then
        -      AC_MSG_CHECKING([for guile link flags])
        -      GUILE_LIBS="`$GUILE_CONFIG link`"
        -      AC_MSG_RESULT([$GUILE_LIBS])
        +    if test -f "$GUILE" ; then
        +      if test -z "$GUILE_CFLAGS" ; then
        +        AC_MSG_CHECKING([for guile compile flags])
        +        GUILE_CFLAGS="`$GUILE_CONFIG compile`" # Note that this can sometimes be empty
        +        AC_MSG_RESULT([$GUILE_CFLAGS])
        +      fi
        +
        +      if test -z "$GUILE_LIBS" ; then
        +        AC_MSG_CHECKING([for guile link flags])
        +        GUILE_LIBS="`$GUILE_CONFIG link`"
        +        AC_MSG_RESULT([$GUILE_LIBS])
        +      fi
             fi
           fi
         fi
        
        From f8adc3e6139d80b758c162aea2725c810f35484b Mon Sep 17 00:00:00 2001
        From: Geert Janssens 
        Date: Fri, 20 Apr 2018 08:54:37 +0200
        Subject: [PATCH 453/455] guile - resstructure some configure tests
        
        1. move the 'no executable found' message up to be with the executable tests
        2. test for an (non-)empty GUILE variable for all other conditions after that
        
        An empty GUILE variable means guile is disabled and consistently using the
        same test makes the code more readable.
        ---
         configure.ac | 11 ++++++-----
         1 file changed, 6 insertions(+), 5 deletions(-)
        
        diff --git a/configure.ac b/configure.ac
        index 789311d53..5ee050c64 100644
        --- a/configure.ac
        +++ b/configure.ac
        @@ -1720,11 +1720,12 @@ else
                 GUILE=
                 AC_PATH_PROG(GUILE, guile)
               fi
        +      if test -z "$GUILE" ; then
        +        AC_MSG_WARN([no suitable guile executable found. Disabling Guile])
        +      fi
             fi
         
        -    if ! test -f "$GUILE" ; then
        -      AC_MSG_WARN([no suitable guile executable found. Disabling Guile])
        -    else
        +    if test -n "$GUILE" ; then
               AC_MSG_CHECKING([for guile version])
               guile_version=`$GUILE -c '(display (effective-version))'`
               AC_MSG_RESULT([$guile_version])
        @@ -1737,7 +1738,7 @@ else
               fi
             fi
         
        -    if test -f "$GUILE" ; then
        +    if test -n "$GUILE" ; then
               # Test if guile-config and guile versions match. They should.
               gc_version="`$GUILE_CONFIG --version 2>&1 | sed '1 s/.* //;q'`"
               g_version="`$GUILE --version | sed '1 s/.* //;q'`"
        @@ -1747,7 +1748,7 @@ else
               fi
             fi
         
        -    if test -f "$GUILE" ; then
        +    if test -n "$GUILE" ; then
               if test -z "$GUILE_CFLAGS" ; then
                 AC_MSG_CHECKING([for guile compile flags])
                 GUILE_CFLAGS="`$GUILE_CONFIG compile`" # Note that this can sometimes be empty
        
        From d612c6a8353c0e535f5d664bdefed1d07a81030a Mon Sep 17 00:00:00 2001
        From: Olly Betts 
        Date: Sat, 21 Apr 2018 14:59:44 +1200
        Subject: [PATCH 454/455] [ci] guile 2.2 build no longer expected to fail
        
        ---
         .travis.yml | 4 ----
         1 file changed, 4 deletions(-)
        
        diff --git a/.travis.yml b/.travis.yml
        index 53b9226ac..527658709 100644
        --- a/.travis.yml
        +++ b/.travis.yml
        @@ -338,10 +338,6 @@ matrix:
               env: SWIGLANG=tcl
         
           allow_failures:
        -    # Started failing after upgrade from Guile 2.0.14 to Guile 2.2.0
        -    - compiler: clang
        -      os: osx
        -      env: SWIGLANG=guile
             # Lots of failing tests currently
             - compiler: gcc
               os: linux
        
        From 6fb6636ce2b2085384c3ffd656a966a25a599f96 Mon Sep 17 00:00:00 2001
        From: Ben Elliston 
        Date: Sat, 28 Apr 2018 12:28:11 +1000
        Subject: [PATCH 455/455] Remove superfluous parens in generated Python
         scripts.
        
        ---
         Source/Modules/python.cxx | 12 ++++++------
         1 file changed, 6 insertions(+), 6 deletions(-)
        
        diff --git a/Source/Modules/python.cxx b/Source/Modules/python.cxx
        index 4a1b4750d..57a5347cb 100644
        --- a/Source/Modules/python.cxx
        +++ b/Source/Modules/python.cxx
        @@ -927,16 +927,16 @@ public:
         	// Python-2.2 object hack
         	Printv(f_shadow,
         	       "\n", "def _swig_setattr_nondynamic(self, class_type, name, value, static=1):\n",
        -	       tab4, "if (name == \"thisown\"):\n", tab8, "return self.this.own(value)\n",
        -	       tab4, "if (name == \"this\"):\n", tab8, "if type(value).__name__ == 'SwigPyObject':\n", tab4, tab8, "self.__dict__[name] = value\n",
        +	       tab4, "if name == \"thisown\":\n", tab8, "return self.this.own(value)\n",
        +	       tab4, "if name == \"this\":\n", tab8, "if type(value).__name__ == 'SwigPyObject':\n", tab4, tab8, "self.__dict__[name] = value\n",
         #ifdef USE_THISOWN
         	       tab4, tab8, "if hasattr(value,\"thisown\"):\n", tab8, tab8, "self.__dict__[\"thisown\"] = value.thisown\n", tab4, tab8, "del value.thisown\n",
         #endif
         	       tab4, tab8, "return\n", tab4, "method = class_type.__swig_setmethods__.get(name, None)\n", tab4, "if method:\n", tab4, tab4, "return method(self, value)\n",
         #ifdef USE_THISOWN
        -	       tab4, "if (not static) or (name == \"thisown\"):\n",
        +	       tab4, "if not static or name == \"thisown\":\n",
         #else
        -	       tab4, "if (not static):\n",
        +	       tab4, "if not static:\n",
         #endif
         	       NIL);
         	if (!classic) {
        @@ -955,7 +955,7 @@ public:
         
         	Printv(f_shadow,
         	       "\n", "def _swig_getattr(self, class_type, name):\n",
        -	       tab4, "if (name == \"thisown\"):\n", tab8, "return self.this.own()\n",
        +	       tab4, "if name == \"thisown\":\n", tab8, "return self.this.own()\n",
         	       tab4, "method = class_type.__swig_getmethods__.get(name, None)\n",
         	       tab4, "if method:\n", tab8, "return method(self)\n",
         	       tab4, "raise AttributeError(\"'%s' object has no attribute '%s'\" % (class_type.__name__, name))\n\n", NIL);
        @@ -978,7 +978,7 @@ public:
         #ifdef USE_THISOWN
         	       tab4, tab4, "if hasattr(self, name) or (name in (\"this\", \"thisown\")):\n",
         #else
        -	       tab4, tab4, "if (name == \"thisown\"):\n", tab8, tab4, "return self.this.own(value)\n", tab4, tab4, "if hasattr(self, name) or (name == \"this\"):\n",
        +	       tab4, tab4, "if name == \"thisown\":\n", tab8, tab4, "return self.this.own(value)\n", tab4, tab4, "if hasattr(self, name) or (name == \"this\"):\n",
         #endif
         	       tab4, tab4, tab4, "set(self, name, value)\n",
         	       tab4, tab4, "else:\n",