From 74345c92e47938a75817eff5ba48dc9d3ce2a281 Mon Sep 17 00:00:00 2001 From: Mike Romberg Date: Sat, 1 Jul 2017 17:38:48 -0600 Subject: [PATCH 01/41] 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 02/41] 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 03/41] 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 04/41] 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 05/41] 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 06/41] 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 a2e3cc0709364630dfde7fe65ca13752aa35ce70 Mon Sep 17 00:00:00 2001 From: Mike Romberg Date: Thu, 20 Jul 2017 13:07:59 -0600 Subject: [PATCH 07/41] 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 08/41] 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 09/41] 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 10/41] 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 11/41] [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 12/41] 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 13/41] [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 14/41] 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 15/41] 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 16/41] 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 17/41] 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 18/41] 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 19/41] 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 20/41] 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 21/41] 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 22/41] 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 23/41] 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 24/41] 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 25/41] 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 26/41] 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 27/41] 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 28/41] 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 29/41] 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 30/41] %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 31/41] 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 32/41] 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 33/41] 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 34/41] 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 35/41] 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 36/41] 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 37/41] 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 38/41] 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 39/41] 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 40/41] 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 41/41] 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 {