diff --git a/CHANGES.current b/CHANGES.current index dd9c87135..37c7f57c4 100644 --- a/CHANGES.current +++ b/CHANGES.current @@ -7,6 +7,36 @@ the issue number to the end of the URL: https://github.com/swig/swig/issues/ Version 4.0.0 (in progress) =========================== +2017-09-23: wsfulton + Issue #1098. Fix overloading of shared_ptr with underlying pointer types, eg: + + void m(std::shared_ptr p); + void m(T &p); + void m(T *p); + + Only the first method is wrapped and the others are ignored/shadowed. + The implementation is done via a new attribute in the 'typecheck' typemap called + 'equivalent'. If specified, it must contain the equivalent pointer type for overloading + and can only be used for the special SWIG_TYPECHECK_POINTER precedence level. + The shared_ptr 'typecheck' typemaps have been modified accordingly. + Here is a simplified version: + + %typemap(typecheck, precedence=SWIG_TYPECHECK_POINTER, equivalent="T *") + T, + T CONST &, + T CONST *, + T *CONST&, + std::shared_ptr< T >, + std::shared_ptr< T > &, + std::shared_ptr< T > *, + std::shared_ptr< T > *& + { ... } + + Overloading with any of these types will result in SWIG ignoring all but the first + overloaded method by default. Without the 'equivalent' attribute, wrapping the overloaded + methods resulted in types being shadowed (scripting languages) or code that did not + compile (statically typed languages). + 2017-09-19: futatuki [Python] #1003 Add --with-2to3=/path/to/2to3 option to configure. diff --git a/Doc/Manual/Contents.html b/Doc/Manual/Contents.html index f3beb2298..25f633cab 100644 --- a/Doc/Manual/Contents.html +++ b/Doc/Manual/Contents.html @@ -381,6 +381,7 @@ @@ -500,6 +501,9 @@
  • Usage
  • Typemaps and overloading +
  • More about %apply and %clear
  • Passing data between typemaps
  • C++ "this" pointer diff --git a/Doc/Manual/Library.html b/Doc/Manual/Library.html index 8939c8df0..d4fedd036 100644 --- a/Doc/Manual/Library.html +++ b/Doc/Manual/Library.html @@ -35,6 +35,7 @@ @@ -1921,7 +1922,30 @@ Adding the missing %shared_ptr macros will fix this: -

    9.4.4.3 shared_ptr and templates

    +

    9.4.4.3 shared_ptr and method overloading

    + + +

    +A C++ compiler can disambiguate a method overloaded by a shared_ptr and one using the raw underlying type. +For example, either one of these methods can be called in C++: +

    + +
    +
    +int age(std::shared_ptr<GrandParent> num);
    +int age(GrandParent& num);
    +
    +
    + +

    +When wrapped by SWIG, disambiguation is not possible using the overloaded names as there is just one equivalent type (GrandParent) in the target language. +SWIG will choose to wrap just the first method by default. +Ambiguity in overloading discusses ways to control which method(s) gets wrapped using %ignore or %rename. +For the interested reader, SWIG detects that they are equivalent types via the typecheck typemaps in the shared_ptr library. +

    + +

    9.4.4.4 shared_ptr and templates

    +

    The %shared_ptr macro should be used for all the required instantiations @@ -1962,7 +1986,7 @@ The SWIG code below shows the required ordering: -

    9.4.4.4 shared_ptr and directors

    +

    9.4.4.5 shared_ptr and directors

    diff --git a/Doc/Manual/Typemaps.html b/Doc/Manual/Typemaps.html index eeabdd89a..ee807d118 100644 --- a/Doc/Manual/Typemaps.html +++ b/Doc/Manual/Typemaps.html @@ -89,6 +89,9 @@

  • Usage
  • Typemaps and overloading +
  • More about %apply and %clear
  • Passing data between typemaps
  • C++ "this" pointer @@ -4754,7 +4757,8 @@ then the type is given a precedence higher than any other known precedence level
    -example.i:18: Warning 467: Overloaded method foo(int) not supported (incomplete type checking rule - no precedence level in typecheck typemap for 'int').
    +example.i:18: Warning 467: Overloaded method foo(int) not supported (incomplete type
    +checking rule - no precedence level in typecheck typemap for 'int').
     
    @@ -4779,10 +4783,112 @@ simply check the type of the first array element and use that to dispatch to the Subsequent "in" typemaps would then perform more extensive type-checking.
  • -
  • Make sure you read the section on overloading in the "SWIG and C++" chapter. +
  • Make sure you read the section on overloading in the SWIG and C++ chapter.
  • +

    11.13.1 SWIG_TYPECHECK_POINTER precedence level and the typecheck typemap

    + + +

    +When it comes to overloading of a particular type passed by value, pointer or reference (const and non-const), +a C++ compiler can disambiguate which overloaded function to call. +However, SWIG effectively treats these as pointers in the target language and thus as equivalent types. +For example, consider: +

    + +
    +
    +class X { ... };
    +void m(X const &c); // equivalent: void m(X *c);
    +void m(X &r);       // equivalent: void m(X *r);
    +void m(X *p);       // equivalent: void m(X *p);
    +
    +
    + +

    +These cannot be disambiguated in the target languages and so SWIG will choose the first method and ignore the subsequent two methods. +The scripting languages do this by using the overload dispatch mechanism described earlier and warnings indicate this: +

    + +
    +
    +example.i:6: Warning 509: Overloaded method m(X &) effectively ignored,
    +example.i:5: Warning 509: as it is shadowed by m(X const &).
    +example.i:7: Warning 509: Overloaded method m(X *) effectively ignored,
    +example.i:5: Warning 509: as it is shadowed by m(X const &).
    +
    +
    + +

    +The statically typed languages like Java and C# automatically ignore all but the first equivalent overloaded methods with warnings: +

    + +
    +
    +example.i:6: Warning 516: Overloaded method m(X &) ignored,
    +example.i:5: Warning 516: using m(X const &) instead.
    +example.i:7: Warning 516: Overloaded method m(X *) ignored,
    +example.i:5: Warning 516: using m(X const &) instead.
    +
    +
    + +

    +You can select the overloaded method you would like to wrap by ignoring the other two with %ignore or rename two of them with %rename +and this will of course remove the warnings too. +The problem of ambiguity is also discussed in the C++ chapter on overloading. +

    + +

    +So how does this work with respect to typemaps? +The typemaps SWIG provides to handle overloading for these three methods are from the SWIGTYPE family. +As discussed earlier, in Default typemap matching rules, +the SWIGTYPE & typemaps are used for references and SWIGTYPE * typemaps are used for pointers. +SWIG uses the special SWIG_TYPECHECK_POINTER (0) precedence level to handle these types in the "typecheck" typemap: +

    + +
    +
    +%typemap(typecheck, precedence=SWIG_TYPECHECK_POINTER) SWIGTYPE & "..."
    +%typemap(typecheck, precedence=SWIG_TYPECHECK_POINTER) SWIGTYPE * "..."
    +
    +
    + +

    +When the SWIGTYPE "typecheck" typemaps use the SWIG_TYPECHECK_POINTER precedence level, +SWIG converts the type to a pointer equivalent type and then uses the equivalent type to detect if it can be disambiguated in an overloaded method in the target language. +In our example above, the equivalent types for X const &, X & and X * are all X *. +As they are the same, they cannot be disambiguated and so just the first overloaded method is chosen. +

    + +

    +The automatic conversion to equivalent types and subsequent type comparison is triggered via the use of the special SWIG_TYPECHECK_POINTER precedence level +and works for types passed by value, pointer and reference. +Alas, there are more ways to overload a method that also need handling. +C++ smart pointers are such a type which can be disambiguated by a C++ compiler but not automatically by SWIG. +SWIG does not automatically know that a smart pointer has an equivalent type, but it can be told manually. +Just specify the 'equivalent' attribute in the "typecheck" typemap with a pointer to the underlying type. +

    + +
    +
    +%typemap(typecheck, precedence=SWIG_TYPECHECK_POINTER, equivalent="X *") MySmartPtr<X> " ... "
    +
    +void m(X &r);            // equivalent: void m(X *r);
    +void m(MySmartPtr<X> s); // equivalent: void m(X *s);
    +
    +
    + +

    +Now SWIG will detect the two types are equivalent and generate valid code by wrapping just the first overloaded method. +You can of course choose which method to wrap by ignoring one of them with %ignore. +Otherwise both can be wrapped by removing the overloading name ambiguity by renaming one of them with %rename. +

    + +

    +The 'equivalent' attribute is used in the implementation for the shared_ptr smart pointer library. +

    +

    11.14 More about %apply and %clear

    diff --git a/Examples/test-suite/csharp/Makefile.in b/Examples/test-suite/csharp/Makefile.in index a59399af3..a4ae7131d 100644 --- a/Examples/test-suite/csharp/Makefile.in +++ b/Examples/test-suite/csharp/Makefile.in @@ -31,6 +31,7 @@ CPP_TEST_CASES = \ CPP11_TEST_CASES = \ cpp11_shared_ptr_const \ cpp11_shared_ptr_nullptr_in_containers \ + cpp11_shared_ptr_overload \ cpp11_shared_ptr_upcast \ cpp11_strongly_typed_enumerations_simple \ diff --git a/Examples/test-suite/d/Makefile.in b/Examples/test-suite/d/Makefile.in index 75c93ed7a..a20cfb4e3 100644 --- a/Examples/test-suite/d/Makefile.in +++ b/Examples/test-suite/d/Makefile.in @@ -27,6 +27,7 @@ CPP_TEST_CASES = \ CPP11_TEST_CASES = \ cpp11_shared_ptr_const \ cpp11_shared_ptr_nullptr_in_containers \ + cpp11_shared_ptr_overload \ cpp11_shared_ptr_upcast \ include $(srcdir)/../common.mk diff --git a/Examples/test-suite/java/Makefile.in b/Examples/test-suite/java/Makefile.in index 0f8fd9767..5f1dc375b 100644 --- a/Examples/test-suite/java/Makefile.in +++ b/Examples/test-suite/java/Makefile.in @@ -46,6 +46,7 @@ CPP_TEST_CASES = \ CPP11_TEST_CASES = \ cpp11_shared_ptr_const \ cpp11_shared_ptr_nullptr_in_containers \ + cpp11_shared_ptr_overload \ cpp11_shared_ptr_upcast \ cpp11_strongly_typed_enumerations_simple \ diff --git a/Examples/test-suite/java/cpp11_shared_ptr_overload_runme.java b/Examples/test-suite/java/cpp11_shared_ptr_overload_runme.java new file mode 100644 index 000000000..27dfe1830 --- /dev/null +++ b/Examples/test-suite/java/cpp11_shared_ptr_overload_runme.java @@ -0,0 +1,60 @@ +import cpp11_shared_ptr_overload.*; + +public class cpp11_shared_ptr_overload_runme { + static { + try { + System.loadLibrary("cpp11_shared_ptr_overload"); + } 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[]) + { + String ret = null; + + // ref + ret = cpp11_shared_ptr_overload.UseA(new MyType("123")); + if (!ret.equals("123 ref")) throw new RuntimeException("UseA fail:" + ret); + + ret = cpp11_shared_ptr_overload.UseB(0, new MyType("123")); + if (!ret.equals("123 ref")) throw new RuntimeException("UseB fail:" + ret); + + ret = cpp11_shared_ptr_overload.UseC(0, new MyType("123"), new MyType("456")); + if (!ret.equals("123 ref")) throw new RuntimeException("UseC fail:" + ret); + + // sharedptr + ret = cpp11_shared_ptr_overload.UseX(new MyType("123")); + if (!ret.equals("123 sharedptr")) throw new RuntimeException("UseX fail:" + ret); + + ret = cpp11_shared_ptr_overload.UseY(0, new MyType("123")); + if (!ret.equals("123 sharedptr")) throw new RuntimeException("UseY fail:" + ret); + + ret = cpp11_shared_ptr_overload.UseZ(0, new MyType("123"), new MyType("456")); + if (!ret.equals("123 sharedptr")) throw new RuntimeException("UseZ fail:" + ret); + + // Combo1-4 + ret = cpp11_shared_ptr_overload.Combo1(new MyType("XXX")); + if (!ret.equals("XXXCombo1")) throw new RuntimeException("Combo1 fail:" + ret); + + ret = cpp11_shared_ptr_overload.Combo2(new MyType("XXX")); + if (!ret.equals("XXXCombo2")) throw new RuntimeException("Combo2 fail:" + ret); + + ret = cpp11_shared_ptr_overload.Combo3(new MyType("XXX")); + if (!ret.equals("XXXCombo3")) throw new RuntimeException("Combo3 fail:" + ret); + + ret = cpp11_shared_ptr_overload.Combo4(new MyType("XXX")); + if (!ret.equals("XXXCombo4")) throw new RuntimeException("Combo4 fail:" + ret); + + // Combo5-7 + ret = cpp11_shared_ptr_overload.Combo5(new MyType("XXX")); + if (!ret.equals("XXXCombo5")) throw new RuntimeException("Combo5 fail:" + ret); + + ret = cpp11_shared_ptr_overload.Combo6(new MyType("XXX")); + if (!ret.equals("XXXCombo6")) throw new RuntimeException("Combo6 fail:" + ret); + + ret = cpp11_shared_ptr_overload.Combo7(new MyType("XXX")); + if (!ret.equals("XXXCombo7")) throw new RuntimeException("Combo7 fail:" + ret); + } +} diff --git a/Examples/test-suite/python/Makefile.in b/Examples/test-suite/python/Makefile.in index ce9dbad13..aa8bcbe60 100644 --- a/Examples/test-suite/python/Makefile.in +++ b/Examples/test-suite/python/Makefile.in @@ -83,6 +83,7 @@ CPP11_TEST_CASES = \ cpp11_hash_tables \ cpp11_shared_ptr_const \ cpp11_shared_ptr_nullptr_in_containers \ + cpp11_shared_ptr_overload \ cpp11_shared_ptr_upcast \ C_TEST_CASES += \ diff --git a/Examples/test-suite/python/cpp11_shared_ptr_overload_runme.py b/Examples/test-suite/python/cpp11_shared_ptr_overload_runme.py new file mode 100644 index 000000000..6b179cb6d --- /dev/null +++ b/Examples/test-suite/python/cpp11_shared_ptr_overload_runme.py @@ -0,0 +1,45 @@ +import cpp11_shared_ptr_overload +from cpp11_shared_ptr_overload import MyType + +# ref +ret = cpp11_shared_ptr_overload.UseA(MyType("123")) +if ret != "123 ref": raise RuntimeError("UseA fail:" + ret) + +ret = cpp11_shared_ptr_overload.UseB(0, MyType("123")) +if ret != "123 ref": raise RuntimeError("UseB fail:" + ret) + +ret = cpp11_shared_ptr_overload.UseC(0, MyType("123"), MyType("456")) +if ret != "123 ref": raise RuntimeError("UseC fail:" + ret) + +# sharedptr +ret = cpp11_shared_ptr_overload.UseX(MyType("123")) +if ret != "123 sharedptr": raise RuntimeError("UseX fail:" + ret) + +ret = cpp11_shared_ptr_overload.UseY(0, MyType("123")) +if ret != "123 sharedptr": raise RuntimeError("UseY fail:" + ret) + +ret = cpp11_shared_ptr_overload.UseZ(0, MyType("123"), MyType("456")) +if ret != "123 sharedptr": raise RuntimeError("UseZ fail:" + ret) + +# Combo1-4 +ret = cpp11_shared_ptr_overload.Combo1(MyType("XXX")) +if ret != "XXXCombo1": raise RuntimeError("Combo1 fail:" + ret) + +ret = cpp11_shared_ptr_overload.Combo2(MyType("XXX")) +if ret != "XXXCombo2": raise RuntimeError("Combo2 fail:" + ret) + +ret = cpp11_shared_ptr_overload.Combo3(MyType("XXX")) +if ret != "XXXCombo3": raise RuntimeError("Combo3 fail:" + ret) + +ret = cpp11_shared_ptr_overload.Combo4(MyType("XXX")) +if ret != "XXXCombo4": raise RuntimeError("Combo4 fail:" + ret) + +# Combo5-7 +ret = cpp11_shared_ptr_overload.Combo5(MyType("XXX")) +if ret != "XXXCombo5": raise RuntimeError("Combo5 fail:" + ret) + +ret = cpp11_shared_ptr_overload.Combo6(MyType("XXX")) +if ret != "XXXCombo6": raise RuntimeError("Combo6 fail:" + ret) + +ret = cpp11_shared_ptr_overload.Combo7(MyType("XXX")) +if ret != "XXXCombo7": raise RuntimeError("Combo7 fail:" + ret) diff --git a/Examples/test-suite/ruby/Makefile.in b/Examples/test-suite/ruby/Makefile.in index ee9d390fe..03eb239c9 100644 --- a/Examples/test-suite/ruby/Makefile.in +++ b/Examples/test-suite/ruby/Makefile.in @@ -36,6 +36,7 @@ CPP11_TEST_CASES = \ cpp11_hash_tables \ cpp11_shared_ptr_const \ cpp11_shared_ptr_nullptr_in_containers \ + cpp11_shared_ptr_overload \ cpp11_shared_ptr_upcast \ cpp11_std_unordered_map \ cpp11_std_unordered_multimap \ diff --git a/Lib/csharp/boost_intrusive_ptr.i b/Lib/csharp/boost_intrusive_ptr.i index d0a048d16..6b0392d3d 100644 --- a/Lib/csharp/boost_intrusive_ptr.i +++ b/Lib/csharp/boost_intrusive_ptr.i @@ -505,6 +505,17 @@ %typemap(imtype, nopgcpp="1") SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > swigSharedPtrUpcast "global::System.Runtime.InteropServices.HandleRef" %typemap(imtype, nopgcpp="1") SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > swigSharedPtrUpcast "global::System.Runtime.InteropServices.HandleRef" +// Typecheck typemaps +%typemap(typecheck, precedence=SWIG_TYPECHECK_POINTER, equivalent="TYPE *") + TYPE CONST, + TYPE CONST &, + TYPE CONST *, + TYPE *CONST&, + SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >, + SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > &, + SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *, + SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *& + "" %template() SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >; %enddef diff --git a/Lib/csharp/boost_shared_ptr.i b/Lib/csharp/boost_shared_ptr.i index 8d65d7953..699d05885 100644 --- a/Lib/csharp/boost_shared_ptr.i +++ b/Lib/csharp/boost_shared_ptr.i @@ -233,6 +233,18 @@ } } +// Typecheck typemaps +%typemap(typecheck, precedence=SWIG_TYPECHECK_POINTER, equivalent="TYPE *") + TYPE CONST, + TYPE CONST &, + TYPE CONST *, + TYPE *CONST&, + SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >, + SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > &, + SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *, + SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *& + "" + %template() SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >; %enddef diff --git a/Lib/d/boost_shared_ptr.i b/Lib/d/boost_shared_ptr.i index 5c171555e..5ee928465 100644 --- a/Lib/d/boost_shared_ptr.i +++ b/Lib/d/boost_shared_ptr.i @@ -197,5 +197,17 @@ public static void* swigGetCPtr(typeof(this) obj) { } } +// Typecheck typemaps +%typemap(typecheck, precedence=SWIG_TYPECHECK_POINTER, equivalent="TYPE *") + TYPE CONST, + TYPE CONST &, + TYPE CONST *, + TYPE *CONST&, + SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >, + SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > &, + SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *, + SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *& + "" + %template() SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >; %enddef diff --git a/Lib/java/boost_intrusive_ptr.i b/Lib/java/boost_intrusive_ptr.i index 48e530c63..3bc80b467 100644 --- a/Lib/java/boost_intrusive_ptr.i +++ b/Lib/java/boost_intrusive_ptr.i @@ -467,6 +467,17 @@ %typemap(jtype, nopgcpp="1") SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > swigSharedPtrUpcast "long" %typemap(jtype, nopgcpp="1") SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > swigSharedPtrUpcast "long" +// Typecheck typemaps +%typemap(typecheck, precedence=SWIG_TYPECHECK_POINTER, equivalent="TYPE *") + TYPE CONST, + TYPE CONST &, + TYPE CONST *, + TYPE *CONST&, + SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >, + SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > &, + SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *, + SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *& + "" %template() SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >; %enddef diff --git a/Lib/java/boost_shared_ptr.i b/Lib/java/boost_shared_ptr.i index 699a8a0a0..6a5e0b2ed 100644 --- a/Lib/java/boost_shared_ptr.i +++ b/Lib/java/boost_shared_ptr.i @@ -225,6 +225,18 @@ } %} +// Typecheck typemaps +%typemap(typecheck, precedence=SWIG_TYPECHECK_POINTER, equivalent="TYPE *") + TYPE CONST, + TYPE CONST &, + TYPE CONST *, + TYPE *CONST&, + SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >, + SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > &, + SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *, + SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *& + "" + %template() SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >; %enddef diff --git a/Lib/octave/boost_shared_ptr.i b/Lib/octave/boost_shared_ptr.i index 4ef646831..68bd9506f 100644 --- a/Lib/octave/boost_shared_ptr.i +++ b/Lib/octave/boost_shared_ptr.i @@ -283,7 +283,7 @@ // Typecheck typemaps // Note: SWIG_ConvertPtr with void ** parameter set to 0 instead of using SWIG_ConvertPtrAndOwn, so that the casting // function is not called thereby avoiding a possible smart pointer copy constructor call when casting up the inheritance chain. -%typemap(typecheck,precedence=SWIG_TYPECHECK_POINTER,noblock=1) +%typemap(typecheck, precedence=SWIG_TYPECHECK_POINTER, equivalent="TYPE *", noblock=1) TYPE CONST, TYPE CONST &, TYPE CONST *, diff --git a/Lib/python/boost_shared_ptr.i b/Lib/python/boost_shared_ptr.i index be5604cbe..83a263505 100644 --- a/Lib/python/boost_shared_ptr.i +++ b/Lib/python/boost_shared_ptr.i @@ -294,7 +294,7 @@ // Typecheck typemaps // Note: SWIG_ConvertPtr with void ** parameter set to 0 instead of using SWIG_ConvertPtrAndOwn, so that the casting // function is not called thereby avoiding a possible smart pointer copy constructor call when casting up the inheritance chain. -%typemap(typecheck,precedence=SWIG_TYPECHECK_POINTER,noblock=1) +%typemap(typecheck, precedence=SWIG_TYPECHECK_POINTER, equivalent="TYPE *", noblock=1) TYPE CONST, TYPE CONST &, TYPE CONST *, diff --git a/Lib/r/boost_shared_ptr.i b/Lib/r/boost_shared_ptr.i index 4a56d7cba..a7b0df1f2 100644 --- a/Lib/r/boost_shared_ptr.i +++ b/Lib/r/boost_shared_ptr.i @@ -281,7 +281,7 @@ // Typecheck typemaps // Note: SWIG_ConvertPtr with void ** parameter set to 0 instead of using SWIG_ConvertPtrAndOwn, so that the casting // function is not called thereby avoiding a possible smart pointer copy constructor call when casting up the inheritance chain. -%typemap(typecheck,precedence=SWIG_TYPECHECK_POINTER,noblock=1) +%typemap(typecheck, precedence=SWIG_TYPECHECK_POINTER, equivalent="TYPE *", noblock=1) TYPE CONST, TYPE CONST &, TYPE CONST *, diff --git a/Lib/ruby/boost_shared_ptr.i b/Lib/ruby/boost_shared_ptr.i index 02e2f999f..9c4766c78 100644 --- a/Lib/ruby/boost_shared_ptr.i +++ b/Lib/ruby/boost_shared_ptr.i @@ -369,7 +369,7 @@ // Typecheck typemaps // Note: SWIG_ConvertPtr with void ** parameter set to 0 instead of using SWIG_ConvertPtrAndOwn, so that the casting // function is not called thereby avoiding a possible smart pointer copy constructor call when casting up the inheritance chain. -%typemap(typecheck,precedence=SWIG_TYPECHECK_POINTER,noblock=1) +%typemap(typecheck, precedence=SWIG_TYPECHECK_POINTER, equivalent="TYPE *", noblock=1) TYPE CONST, TYPE CONST &, TYPE CONST *, diff --git a/Lib/ruby/std_shared_ptr.i b/Lib/ruby/std_shared_ptr.i index 9742230cc..dee35ec03 100644 --- a/Lib/ruby/std_shared_ptr.i +++ b/Lib/ruby/std_shared_ptr.i @@ -3,7 +3,7 @@ %include -%fragment("StdSharedPtrTraits","header",fragment="StdTraitsForwardDeclaration") +%fragment("StdSharedPtrTraits","header",fragment="StdTraitsForwardDeclaration",fragment="") { namespace swig { /* diff --git a/Lib/scilab/boost_shared_ptr.i b/Lib/scilab/boost_shared_ptr.i index d595b4861..b7bbb0d4a 100644 --- a/Lib/scilab/boost_shared_ptr.i +++ b/Lib/scilab/boost_shared_ptr.i @@ -290,7 +290,7 @@ // Typecheck typemaps // Note: SWIG_ConvertPtr with void ** parameter set to 0 instead of using SWIG_ConvertPtrAndOwn, so that the casting // function is not called thereby avoiding a possible smart pointer copy constructor call when casting up the inheritance chain. -%typemap(typecheck,precedence=SWIG_TYPECHECK_POINTER,noblock=1) +%typemap(typecheck, precedence=SWIG_TYPECHECK_POINTER, equivalent="TYPE *", noblock=1) TYPE CONST, TYPE CONST &, TYPE CONST *, diff --git a/Source/Modules/emit.cxx b/Source/Modules/emit.cxx index 813a30924..c1ba0758a 100644 --- a/Source/Modules/emit.cxx +++ b/Source/Modules/emit.cxx @@ -12,6 +12,7 @@ * ----------------------------------------------------------------------------- */ #include "swigmod.h" +#include "cparse.h" /* ----------------------------------------------------------------------------- * emit_return_variable() @@ -112,9 +113,8 @@ void emit_attach_parmmaps(ParmList *l, Wrapper *f) { /* This is compatibility code to deal with the deprecated "ignore" typemap */ Parm *p = l; Parm *np; - String *tm; while (p) { - tm = Getattr(p, "tmap:in"); + String *tm = Getattr(p, "tmap:in"); if (tm && checkAttribute(p, "tmap:in:numinputs", "0")) { Replaceall(tm, "$target", Getattr(p, "lname")); Printv(f->code, tm, "\n", NIL); @@ -134,7 +134,6 @@ void emit_attach_parmmaps(ParmList *l, Wrapper *f) { /* Perform a sanity check on "in" and "freearg" typemaps. These must exactly match to avoid chaos. If a mismatch occurs, we nuke the freearg typemap */ - { Parm *p = l; Parm *npin, *npfreearg; @@ -196,6 +195,36 @@ void emit_attach_parmmaps(ParmList *l, Wrapper *f) { } } } + + /* + * An equivalent type can be used in the typecheck typemap for SWIG to detect the overloading of equivalent + * target language types. This is primarily for the smartptr feature, where a pointer and a smart pointer + * are seen as equivalent types in the target language. + */ + { + Parm *p = l; + while (p) { + String *tm = Getattr(p, "tmap:typecheck"); + if (tm) { + String *equivalent = Getattr(p, "tmap:typecheck:equivalent"); + if (equivalent) { + String *precedence = Getattr(p, "tmap:typecheck:precedence"); + if (precedence && Strcmp(precedence, "0") != 0) + Swig_error(Getfile(tm), Getline(tm), "The 'typecheck' typemap for %s contains an 'equivalent' attribute for a 'precedence' that is not set to SWIG_TYPECHECK_POINTER or 0.\n", SwigType_str(Getattr(p, "type"), 0)); + SwigType *cpt = Swig_cparse_type(equivalent); + if (cpt) { + Setattr(p, "equivtype", cpt); + Delete(cpt); + } else { + Swig_error(Getfile(tm), Getline(tm), "Invalid type (%s) in 'equivalent' attribute in 'typecheck' typemap for type %s.\n", equivalent, SwigType_str(Getattr(p, "type"), 0)); + } + } + p = Getattr(p, "tmap:typecheck:next"); + } else { + p = nextSibling(p); + } + } + } } /* ----------------------------------------------------------------------------- diff --git a/Source/Modules/overload.cxx b/Source/Modules/overload.cxx index 81d1bb000..3945d598f 100644 --- a/Source/Modules/overload.cxx +++ b/Source/Modules/overload.cxx @@ -185,7 +185,8 @@ List *Swig_overload_rank(Node *n, bool script_lang_wrapping) { nodes[j] = t; break; } else if ((differ == 0) && (Strcmp(t1, "0") == 0)) { - t1 = Getattr(p1, "ltype"); + t1 = Getattr(p1, "equivtype"); + t1 = t1 ? t1 : Getattr(p1, "ltype"); if (!t1) { t1 = SwigType_ltype(Getattr(p1, "type")); if (Getattr(p1, "tmap:typecheck:SWIGTYPE")) { @@ -193,7 +194,8 @@ List *Swig_overload_rank(Node *n, bool script_lang_wrapping) { } Setattr(p1, "ltype", t1); } - t2 = Getattr(p2, "ltype"); + t2 = Getattr(p2, "equivtype"); + t2 = t2 ? t2 : Getattr(p2, "ltype"); if (!t2) { t2 = SwigType_ltype(Getattr(p2, "type")); if (Getattr(p2, "tmap:typecheck:SWIGTYPE")) {