diff options
-rw-r--r-- | CHANGES.current | 20 | ||||
-rw-r--r-- | Doc/Manual/CPlusPlus11.html | 49 | ||||
-rw-r--r-- | Doc/Manual/Contents.html | 2 | ||||
-rw-r--r-- | Examples/test-suite/cpp11_type_aliasing.i | 76 | ||||
-rw-r--r-- | Examples/test-suite/errors/cpp_using_type_aliasing.stderr | 3 | ||||
-rw-r--r-- | Examples/test-suite/li_boost_shared_ptr_template.i | 2 | ||||
-rw-r--r-- | Examples/test-suite/python/autodoc_runme.py | 8 | ||||
-rw-r--r-- | Examples/test-suite/python/cpp11_type_aliasing_runme.py | 32 | ||||
-rw-r--r-- | Examples/test-suite/python/cpp_static_runme.py | 3 | ||||
-rw-r--r-- | Examples/test-suite/python/exception_classname_runme.py | 3 | ||||
-rw-r--r-- | Examples/test-suite/python/li_boost_shared_ptr_template_runme.py | 18 | ||||
-rw-r--r-- | Examples/test-suite/python/operbool_runme.py | 3 | ||||
-rw-r--r-- | Examples/test-suite/python/python_destructor_exception_runme.py | 6 | ||||
-rw-r--r-- | Examples/test-suite/python/unicode_strings_runme.py | 12 | ||||
-rw-r--r-- | Lib/python/pyprimtypes.swg | 4 | ||||
-rw-r--r-- | Source/CParse/parser.y | 15 | ||||
-rw-r--r-- | Source/Modules/overload.cxx | 16 | ||||
-rw-r--r-- | Source/Modules/typepass.cxx | 8 |
18 files changed, 205 insertions, 75 deletions
diff --git a/CHANGES.current b/CHANGES.current index 312343f56..b3bb600dc 100644 --- a/CHANGES.current +++ b/CHANGES.current @@ -4,3 +4,23 @@ See the RELEASENOTES file for a summary of changes in each release. Version 3.0.11 (in progress) ============================ + +2016-06-25: mromberg + [Python] #711 Fix -castmode and conversion of signed and unsigned integer types. + See 2015-12-23 CHANGES entry for details of these improvements when they were + implemented for the default options (ie not using -castmode). + +2016-06-25: ahnolds + Patch #730 - Fix %implicitconv for overloaded functions when using + -castmode or -fastdispatch options. + + The result is that in all overload cases where there are multiple possibilities + with the same number of arguments, the dispatch function will first check for + exact (aka non implicit) matches, and then subsequently check for implicit + casting matches. This was already happening in the normal dispatch situation, + and in the -fastdispatch case two passes through the candidates were happening, + just with SWIG_POINTER_IMPLICIT_CONV always set. After this patch, it is not set + on the first pass, and then set on the second pass. + +2016-06-25: liorgold + Patch #727 - Add support for C++11 type aliasing. diff --git a/Doc/Manual/CPlusPlus11.html b/Doc/Manual/CPlusPlus11.html index 714845bba..a4845832e 100644 --- a/Doc/Manual/CPlusPlus11.html +++ b/Doc/Manual/CPlusPlus11.html @@ -29,7 +29,7 @@ <li><a href="#CPlusPlus11_strongly_typed_enumerations">Strongly typed enumerations</a> <li><a href="#CPlusPlus11_double_angle_brackets">Double angle brackets</a> <li><a href="#CPlusPlus11_explicit_conversion_operators">Explicit conversion operators</a> -<li><a href="#CPlusPlus11_alias_templates">Alias templates</a> +<li><a href="#CPlusPlus11_alias_templates">Type alias and alias templates</a> <li><a href="#CPlusPlus11_unrestricted_unions">Unrestricted unions</a> <li><a href="#CPlusPlus11_variadic_templates">Variadic templates</a> <li><a href="#CPlusPlus11_new_string_literals">New string literals</a> @@ -603,10 +603,30 @@ Conversion operators either with or without <tt>explicit</tt> need renaming to a them available as a normal proxy method. </p> -<H3><a name="CPlusPlus11_alias_templates">7.2.16 Alias templates</a></H3> +<H3><a name="CPlusPlus11_alias_templates">7.2.16 Type alias and alias templates</a></H3> <p> +A type alias is a statement of the form: +</p> + +<div class="code"><pre> +using PFD = void (*)(double); // New introduced syntax +</pre></div> + +<p> +which is equivalent to the old style typedef: +</p> + +<div class="code"><pre> +typedef void (*PFD)(double); // The old style +</pre></div> + +<p> +SWIG supports type aliasing. +</p> + +<p> The following is an example of an alias template: <div class="code"><pre> @@ -632,31 +652,6 @@ example.i:13: Warning 342: The 'using' keyword in template aliasing is not fully </pre> </div> -<p> -Similarly for non-template type aliasing: -</p> - -<div class="code"><pre> -using PFD = void (*)(double); // New introduced syntax -</pre></div> - -<p> -A warning will be issued: -</p> - -<div class="shell"> -<pre> -example.i:17: Warning 341: The 'using' keyword in type aliasing is not fully supported yet. -</pre> -</div> - - -<p>The equivalent old style typedefs can be used as a workaround:</p> - -<div class="code"><pre> -typedef void (*PFD)(double); // The old style -</pre></div> - <H3><a name="CPlusPlus11_unrestricted_unions">7.2.17 Unrestricted unions</a></H3> diff --git a/Doc/Manual/Contents.html b/Doc/Manual/Contents.html index 7107384c8..0b456fca7 100644 --- a/Doc/Manual/Contents.html +++ b/Doc/Manual/Contents.html @@ -287,7 +287,7 @@ <li><a href="CPlusPlus11.html#CPlusPlus11_strongly_typed_enumerations">Strongly typed enumerations</a> <li><a href="CPlusPlus11.html#CPlusPlus11_double_angle_brackets">Double angle brackets</a> <li><a href="CPlusPlus11.html#CPlusPlus11_explicit_conversion_operators">Explicit conversion operators</a> -<li><a href="CPlusPlus11.html#CPlusPlus11_alias_templates">Alias templates</a> +<li><a href="CPlusPlus11.html#CPlusPlus11_alias_templates">Type alias and alias templates</a> <li><a href="CPlusPlus11.html#CPlusPlus11_unrestricted_unions">Unrestricted unions</a> <li><a href="CPlusPlus11.html#CPlusPlus11_variadic_templates">Variadic templates</a> <li><a href="CPlusPlus11.html#CPlusPlus11_new_string_literals">New string literals</a> diff --git a/Examples/test-suite/cpp11_type_aliasing.i b/Examples/test-suite/cpp11_type_aliasing.i index 87443633a..2f6ea3aa7 100644 --- a/Examples/test-suite/cpp11_type_aliasing.i +++ b/Examples/test-suite/cpp11_type_aliasing.i @@ -2,15 +2,6 @@ // Type aliasing seg fault : Github issue #424 -%warnfilter(SWIGWARN_CPP11_ALIAS_DECLARATION) Target; -%warnfilter(SWIGWARN_CPP11_ALIAS_DECLARATION) Int; -%warnfilter(SWIGWARN_CPP11_ALIAS_DECLARATION) IntRef; -%warnfilter(SWIGWARN_CPP11_ALIAS_DECLARATION) IntPtrRef; -%warnfilter(SWIGWARN_CPP11_ALIAS_DECLARATION) IntRValueRef; -%warnfilter(SWIGWARN_CPP11_ALIAS_DECLARATION) IntArray; -%warnfilter(SWIGWARN_CPP11_ALIAS_DECLARATION) HalideTargetPtr1; -%warnfilter(SWIGWARN_CPP11_ALIAS_DECLARATION) HalideTargetPtr2; - %inline %{ namespace Halide { @@ -53,14 +44,69 @@ public: %inline %{ -using Int = int; -using IntRef = int&; -using IntPtrRef = int*&; -using IntRValueRef = int&&; -using IntArray = int[]; - using HalideTargetPtr1 = Halide::Target*; namespace Halide { using HalideTargetPtr2 = Target*; } %} + +// Define some types + +%inline %{ +using Int = int; +using IntPtr = Int*; +using IntRef = Int&; +using IntPtrRef = Int*&; +using IntRValueRef = Int&&; +using IntArray = Int[]; +%} + +// Test that SWIG understands these new types + +%callback("%s_cb"); +Int mult2(Int x); +%nocallback; + +%inline %{ +Int mult2(Int x) { return x * 2; } +IntPtr allocate_int() { return new Int(12); } +void free_int(int* ptr) { delete ptr; } +void inplace_mult2(IntRef x) { x *= 2; } +Int read_int(IntPtr ptr) { return *ptr; } + +template <typename T> class Pair { +public: + using data_t = T; + + data_t a, b; + + Pair() : a(), b() { } + Pair(data_t a, data_t b) : a(a), b(b) { } + data_t first() { return a; } + data_t second() { return b; } +}; +%} + +%template(int_pair) Pair<Int>; + +%inline %{ +using PairInt = Pair<Int>; + +class PairSubclass : public PairInt { +public: + PairSubclass(data_t a, data_t b) : PairInt(a, b) { } + + using const_ref_data_t = const data_t&; +}; + +PairSubclass::data_t plus1(PairSubclass::const_ref_data_t x) { return x + 1; } +%} + +// Test function pointers + +%inline %{ +using callback_t = int(*)(int); + +callback_t get_callback() { return mult2; } +int call(callback_t func, int param) { return func(param); } +%} diff --git a/Examples/test-suite/errors/cpp_using_type_aliasing.stderr b/Examples/test-suite/errors/cpp_using_type_aliasing.stderr index 3f256652f..e69de29bb 100644 --- a/Examples/test-suite/errors/cpp_using_type_aliasing.stderr +++ b/Examples/test-suite/errors/cpp_using_type_aliasing.stderr @@ -1,3 +0,0 @@ -cpp_using_type_aliasing.i:8: Warning 341: The 'using' keyword in type aliasing is not fully supported yet. -cpp_using_type_aliasing.i:8: Warning 315: Nothing known about 'Okay< int >'. -cpp_using_type_aliasing.i:8: Warning 315: Nothing known about 'Okay< int >'. diff --git a/Examples/test-suite/li_boost_shared_ptr_template.i b/Examples/test-suite/li_boost_shared_ptr_template.i index e3b735c24..3965a976e 100644 --- a/Examples/test-suite/li_boost_shared_ptr_template.i +++ b/Examples/test-suite/li_boost_shared_ptr_template.i @@ -67,7 +67,7 @@ INTEGER bar_getter(Base<INTEGER>& foo) { // 2nd test - templates with default template parameters #if defined(SHARED_PTR_WRAPPERS_IMPLEMENTED) -%shared_ptr(Space::BaseDefault<short>) +%shared_ptr(Space::BaseDefault<short, int>) %shared_ptr(Space::DerivedDefault<short>) %shared_ptr(Space::DerivedDefault2<short>) diff --git a/Examples/test-suite/python/autodoc_runme.py b/Examples/test-suite/python/autodoc_runme.py index ce0aae0eb..af04c8c0e 100644 --- a/Examples/test-suite/python/autodoc_runme.py +++ b/Examples/test-suite/python/autodoc_runme.py @@ -15,11 +15,19 @@ def check(got, expected, expected_builtin=None, skip=False): def is_new_style_class(cls): return hasattr(cls, "__class__") +def is_fastproxy(module): + return "new_instancemethod" in module + if not is_new_style_class(A): # Missing static methods make this hard to test... skip if -classic is # used! sys.exit(0) +if is_fastproxy(dir()): + # Detect when -fastproxy is specified and skip test as it changes the function names making it + # hard to test... skip until the number of options are reduced in SWIG-3.1 and autodoc is improved + sys.exit(0) + # skip builtin check - the autodoc is missing, but it probably should not be skip = True diff --git a/Examples/test-suite/python/cpp11_type_aliasing_runme.py b/Examples/test-suite/python/cpp11_type_aliasing_runme.py new file mode 100644 index 000000000..52cc81d1c --- /dev/null +++ b/Examples/test-suite/python/cpp11_type_aliasing_runme.py @@ -0,0 +1,32 @@ +from cpp11_type_aliasing import * + +if get_host_target().bits != 32: + raise RuntimeError("get_host_target().bits should return 32") + +if mult2(10) != 20: + raise RuntimeError("mult2(10) should return 20") + +int_ptr = allocate_int() +inplace_mult2(int_ptr) +if read_int(int_ptr) != 24: + raise RuntimeError("read_int should return 24") +free_int(int_ptr) + +pair = PairSubclass(3, 4) +if pair.first() != 3: + raise RuntimeError("pair.first() should return 3") + +if pair.second() != 4: + raise RuntimeError("pair.second() should return 4") + +if pair.a != 3: + raise RuntimeError("pair.a should be 3") + +if plus1(5) != 6: + raise RuntimeError("plus1(5) should return 6") + +if call(mult2_cb, 7) != 14: + raise RuntimeError("call(mult2_cb, 7) should return 14") + +if call(get_callback(), 7) != 14: + raise RuntimeError("call(get_callback(), 7) should return 14") diff --git a/Examples/test-suite/python/cpp_static_runme.py b/Examples/test-suite/python/cpp_static_runme.py index b742de285..1c7705f3e 100644 --- a/Examples/test-suite/python/cpp_static_runme.py +++ b/Examples/test-suite/python/cpp_static_runme.py @@ -14,4 +14,5 @@ else: StaticFunctionTest().static_func_2(1) StaticFunctionTest().static_func_3(1, 2) StaticMemberTest.static_int = 10 -assert StaticMemberTest.static_int == 10 +if not StaticMemberTest.static_int == 10: + raise RuntimeError("static_int not 10") diff --git a/Examples/test-suite/python/exception_classname_runme.py b/Examples/test-suite/python/exception_classname_runme.py index c78f4e68b..9a82c9105 100644 --- a/Examples/test-suite/python/exception_classname_runme.py +++ b/Examples/test-suite/python/exception_classname_runme.py @@ -1,4 +1,5 @@ import exception_classname a = exception_classname.Exception() -assert a.testfunc() == 42 +if a.testfunc() != 42: + raise RuntimeError("Not 42!") diff --git a/Examples/test-suite/python/li_boost_shared_ptr_template_runme.py b/Examples/test-suite/python/li_boost_shared_ptr_template_runme.py index 6b56ec479..eab7e282a 100644 --- a/Examples/test-suite/python/li_boost_shared_ptr_template_runme.py +++ b/Examples/test-suite/python/li_boost_shared_ptr_template_runme.py @@ -8,9 +8,8 @@ if d.bar() != 2: raise RuntimeError if bar_getter(b) != 1: raise RuntimeError -# Fix reverted in rev 12953 -# if bar_getter(d) != 2: -# raise RuntimeError +if bar_getter(d) != 2: + raise RuntimeError b = BaseDefaultInt() d = DerivedDefaultInt() @@ -23,8 +22,11 @@ if d2.bar2() != 4: raise RuntimeError if bar2_getter(b) != 3: raise RuntimeError -# Fix reverted in rev 12953 -# if bar2_getter(d) != 4: -# raise RuntimeError -# if bar2_getter(d2) != 4: -# raise RuntimeError +# SWIG fix reverted in Subversion rev 12953 +# Testcase has now been modified to mask the problem by providing the default parameter 'int' in: +# %shared_ptr(Space::BaseDefault<short, int>) +# If this is not done then d fails to convert to BaseDefault<short>& +if bar2_getter(d) != 4: + raise RuntimeError +if bar2_getter(d2) != 4: + raise RuntimeError diff --git a/Examples/test-suite/python/operbool_runme.py b/Examples/test-suite/python/operbool_runme.py index 708dea786..cdef85abc 100644 --- a/Examples/test-suite/python/operbool_runme.py +++ b/Examples/test-suite/python/operbool_runme.py @@ -1,3 +1,4 @@ #!/usr/bin/env python import operbool -assert not operbool.Test() +if operbool.Test(): + raise RuntimeError("operbool failed") diff --git a/Examples/test-suite/python/python_destructor_exception_runme.py b/Examples/test-suite/python/python_destructor_exception_runme.py index 671eff3cc..ee71ab33b 100644 --- a/Examples/test-suite/python/python_destructor_exception_runme.py +++ b/Examples/test-suite/python/python_destructor_exception_runme.py @@ -26,8 +26,10 @@ def test1(): sys.stderr.flush() sys.stderr = stderr_saved - assert attributeErrorOccurred - assert buffer.getvalue().count("I am the ClassWithThrowingDestructor dtor doing bad things") >= 1 + if not attributeErrorOccurred: + raise RuntimeError("attributeErrorOccurred failed") + if not buffer.getvalue().count("I am the ClassWithThrowingDestructor dtor doing bad things") >= 1: + raise RuntimeError("ClassWithThrowingDestructor dtor doing bad things failed") class VectorHolder(object): def __init__(self, v): diff --git a/Examples/test-suite/python/unicode_strings_runme.py b/Examples/test-suite/python/unicode_strings_runme.py index 3ce98bcdb..fa9c51437 100644 --- a/Examples/test-suite/python/unicode_strings_runme.py +++ b/Examples/test-suite/python/unicode_strings_runme.py @@ -13,11 +13,15 @@ if sys.version_info[0:2] >= (3, 1): if unicode_strings.non_utf8_std_string() != test_string: raise ValueError('Test comparison mismatch') +def check(s1, s2): + if s1 != s2: + raise RuntimeError("{} != {}".format(s1, s2)) + # Testing SWIG_PYTHON_2_UNICODE flag which allows unicode strings to be passed to C if sys.version_info[0:2] < (3, 0): - assert unicode_strings.charstring("hello1") == "hello1" - assert unicode_strings.charstring(str(u"hello2")) == "hello2" - assert unicode_strings.charstring(u"hello3") == "hello3" - assert unicode_strings.charstring(unicode("hello4")) == "hello4" + check(unicode_strings.charstring("hello1"), "hello1") + check(unicode_strings.charstring(str(u"hello2")), "hello2") + check(unicode_strings.charstring(u"hello3"), "hello3") + check(unicode_strings.charstring(unicode("hello4")), "hello4") unicode_strings.charstring(u"hell\xb05") unicode_strings.charstring(u"hell\u00f66") diff --git a/Lib/python/pyprimtypes.swg b/Lib/python/pyprimtypes.swg index fb5bbf6df..575b6db88 100644 --- a/Lib/python/pyprimtypes.swg +++ b/Lib/python/pyprimtypes.swg @@ -223,6 +223,8 @@ SWIG_AsVal_dec(long long)(PyObject *obj, long long *val) const double mant_min = -mant_max; double d; res = SWIG_AsVal(double)(obj,&d); + if (SWIG_IsOK(res) && !SWIG_CanCastAsInteger(&d, mant_min, mant_max)) + return SWIG_OverflowError; if (SWIG_IsOK(res) && SWIG_CanCastAsInteger(&d, mant_min, mant_max)) { if (val) *val = (long long)(d); return SWIG_AddCast(res); @@ -280,6 +282,8 @@ SWIG_AsVal_dec(unsigned long long)(PyObject *obj, unsigned long long *val) const double mant_max = 1LL << DBL_MANT_DIG; double d; res = SWIG_AsVal(double)(obj,&d); + if (SWIG_IsOK(res) && !SWIG_CanCastAsInteger(&d, 0, mant_max)) + return SWIG_OverflowError; if (SWIG_IsOK(res) && SWIG_CanCastAsInteger(&d, 0, mant_max)) { if (val) *val = (unsigned long long)(d); return SWIG_AddCast(res); diff --git a/Source/CParse/parser.y b/Source/CParse/parser.y index 51cd5b553..784187c28 100644 --- a/Source/CParse/parser.y +++ b/Source/CParse/parser.y @@ -2899,16 +2899,15 @@ c_declaration : c_decl { SWIG_WARN_NODE_END($$); } | USING idcolon EQUAL type plain_declarator SEMI { - $$ = new_node("using"); - Setattr($$,"name",$2); + /* Convert using statement to a typedef statement */ + $$ = new_node("cdecl"); SwigType_push($4,$5.type); - Setattr($$,"uname",$4); + Setattr($$,"type",$4); + Setattr($$,"storage","typedef"); + Setattr($$,"name",$2); + Setattr($$,"decl",""); + SetFlag($$,"typealias"); add_symbols($$); - SWIG_WARN_NODE_BEGIN($$); - Swig_warning(WARN_CPP11_ALIAS_DECLARATION, cparse_file, cparse_line, "The 'using' keyword in type aliasing is not fully supported yet.\n"); - SWIG_WARN_NODE_END($$); - - $$ = 0; /* TODO - ignored for now */ } | TEMPLATE LESSTHAN template_parms GREATERTHAN USING idcolon EQUAL type plain_declarator SEMI { $$ = new_node("using"); diff --git a/Source/Modules/overload.cxx b/Source/Modules/overload.cxx index dd3ca4972..330294efd 100644 --- a/Source/Modules/overload.cxx +++ b/Source/Modules/overload.cxx @@ -433,6 +433,7 @@ String *Swig_overload_dispatch_cast(Node *n, const_String_or_char_ptr fmt, int * int fn = 0; Node *ni = Getitem(dispatch, i); Parm *pi = Getattr(ni, "wrap:parms"); + bool implicitconvtypecheckoff = GetFlag(ni, "implicitconvtypecheckoff") != 0; int num_required = emit_num_required(pi); int num_arguments = emit_num_arguments(pi); if (num_arguments > *maxargs) @@ -476,6 +477,7 @@ String *Swig_overload_dispatch_cast(Node *n, const_String_or_char_ptr fmt, int * String *tm = Getattr(pj, "tmap:typecheck"); if (tm) { + tm = Copy(tm); /* normalise for comparison later */ Replaceid(tm, Getattr(pj, "lname"), "_v"); @@ -528,13 +530,14 @@ String *Swig_overload_dispatch_cast(Node *n, const_String_or_char_ptr fmt, int * String *tmp = NewStringf(argv_template_string, j); String *conv = Getattr(pj, "implicitconv"); - if (conv) { + if (conv && !implicitconvtypecheckoff) { Replaceall(tm, "$implicitconv", conv); } else { Replaceall(tm, "$implicitconv", "0"); } Replaceall(tm, "$input", tmp); Printv(f, "{\n", tm, "}\n", NIL); + Delete(tm); fn = i + 1; Printf(f, "if (!_v) goto check_%d;\n", fn); Printf(f, "_ranki += _v*_pi;\n"); @@ -574,6 +577,9 @@ String *Swig_overload_dispatch_cast(Node *n, const_String_or_char_ptr fmt, int * if (fn) Printf(f, "check_%d:\n\n", fn); + if (implicitconvtypecheckoff) + Delattr(ni, "implicitconvtypecheckoff"); + Delete(lfmt); Delete(coll); } @@ -607,6 +613,7 @@ String *Swig_overload_dispatch_fast(Node *n, const_String_or_char_ptr fmt, int * int fn = 0; Node *ni = Getitem(dispatch, i); Parm *pi = Getattr(ni, "wrap:parms"); + bool implicitconvtypecheckoff = GetFlag(ni, "implicitconvtypecheckoff") != 0; int num_required = emit_num_required(pi); int num_arguments = emit_num_arguments(pi); if (num_arguments > *maxargs) @@ -646,6 +653,7 @@ String *Swig_overload_dispatch_fast(Node *n, const_String_or_char_ptr fmt, int * String *tm = Getattr(pj, "tmap:typecheck"); if (tm) { + tm = Copy(tm); /* normalise for comparison later */ Replaceid(tm, Getattr(pj, "lname"), "_v"); @@ -699,13 +707,14 @@ String *Swig_overload_dispatch_fast(Node *n, const_String_or_char_ptr fmt, int * String *tmp = NewStringf(argv_template_string, j); String *conv = Getattr(pj, "implicitconv"); - if (conv) { + if (conv && !implicitconvtypecheckoff) { Replaceall(tm, "$implicitconv", conv); } else { Replaceall(tm, "$implicitconv", "0"); } Replaceall(tm, "$input", tmp); Printv(f, "{\n", tm, "}\n", NIL); + Delete(tm); fn = i + 1; Printf(f, "if (!_v) goto check_%d;\n", fn); } @@ -737,6 +746,9 @@ String *Swig_overload_dispatch_fast(Node *n, const_String_or_char_ptr fmt, int * if (fn) Printf(f, "check_%d:\n\n", fn); + if (implicitconvtypecheckoff) + Delattr(ni, "implicitconvtypecheckoff"); + Delete(lfmt); Delete(coll); } diff --git a/Source/Modules/typepass.cxx b/Source/Modules/typepass.cxx index 847f5b4f9..dc4d02bdd 100644 --- a/Source/Modules/typepass.cxx +++ b/Source/Modules/typepass.cxx @@ -265,7 +265,13 @@ class TypePass:private Dispatcher { SwigType *bsmart = Copy(smart); SwigType *rclsname = SwigType_typedef_resolve_all(clsname); SwigType *rbname = SwigType_typedef_resolve_all(bname); - Replaceall(bsmart, rclsname, rbname); + int replace_count = Replaceall(bsmart, rclsname, rbname); + if (replace_count == 0) { + // If no replacement made, it will be because rclsname is fully resolved, but the + // type in the smartptr feature used a typedef or not fully resolved name. + String *firstname = Getattr(first, "name"); + Replaceall(bsmart, firstname, rbname); + } Delete(rclsname); Delete(rbname); String *smartnamestr = SwigType_namestr(smart); |