From 3be670e8db5b45195b670c91eac3fb413cf8427b Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Mon, 29 Jan 2024 08:53:55 +0000 Subject: [PATCH] Fix assertion handling upcasting when using %shared_ptr on some templates. A different approach is taken for supporting casting smart pointers up the inheritance hierarchy. We no longer try to replace the underlying pointer type, provided in the 'feature:smartptr', with the base class type. Such as morphing 'std::shared_ptr<(Derived)>' into 'std::shared_ptr<(Base)>'. Instead, we simply use 'feature:smartptr' from the base class. This is more reliable than trying to pattern match the pointer type in the feature. The base class must of course also have the 'feature:smartptr' set, and this is still checked for as before. The feature is now parsed in one place and stored in the parse tree in the new 'smart' attribute for handling by the target languages. Fix also improves the handling of the type parsed in 'feature:smartptr' in that the type is now normalized and resolved in the scope of the class it is attached to. Closes #2768 --- CHANGES.current | 4 + .../test-suite/cpp11_shared_ptr_crtp_upcast.i | 92 +++++++++++++++++++ Examples/test-suite/csharp/Makefile.in | 1 + Examples/test-suite/d/Makefile.in | 1 + .../test-suite/errors/cpp_smartptr_feature.i | 14 +++ .../errors/cpp_smartptr_feature.stderr | 5 + Examples/test-suite/java/Makefile.in | 1 + Examples/test-suite/octave/Makefile.in | 1 + Examples/test-suite/python/Makefile.in | 1 + Examples/test-suite/ruby/Makefile.in | 1 + Source/CParse/parser.y | 9 +- Source/Modules/csharp.cxx | 36 ++++---- Source/Modules/d.cxx | 33 +++---- Source/Modules/java.cxx | 50 +++++----- Source/Modules/octave.cxx | 10 +- Source/Modules/python.cxx | 12 +-- Source/Modules/ruby.cxx | 39 ++++---- Source/Modules/swigmod.h | 1 - Source/Modules/typepass.cxx | 38 ++++---- Source/Modules/utils.cxx | 61 ------------ Source/Swig/typemap.c | 2 - 21 files changed, 244 insertions(+), 168 deletions(-) create mode 100644 Examples/test-suite/cpp11_shared_ptr_crtp_upcast.i create mode 100644 Examples/test-suite/errors/cpp_smartptr_feature.i create mode 100644 Examples/test-suite/errors/cpp_smartptr_feature.stderr diff --git a/CHANGES.current b/CHANGES.current index 3c662f6a8..c545169d4 100644 --- a/CHANGES.current +++ b/CHANGES.current @@ -7,6 +7,10 @@ the issue number to the end of the URL: https://github.com/swig/swig/issues/ Version 4.2.1 (in progress) =========================== +2024-01-31: wsfulton + #2768 Fix seg fault handling upcasting when using %shared_ptr on some + templates. + 2024-01-31: olly #2783 Fix incorrectly deduced type for function call. Regression introduced in 4.2.0. diff --git a/Examples/test-suite/cpp11_shared_ptr_crtp_upcast.i b/Examples/test-suite/cpp11_shared_ptr_crtp_upcast.i new file mode 100644 index 000000000..f00dc1ff4 --- /dev/null +++ b/Examples/test-suite/cpp11_shared_ptr_crtp_upcast.i @@ -0,0 +1,92 @@ +%module cpp11_shared_ptr_crtp_upcast + +// Cutdown testcase for assert reported in https://github.com/swig/swig/issues/2768 +// Note that this test has CRTP and %template instantiations for DiscretisedDensity template parameters not fully resolved + +%warnfilter(SWIGWARN_JAVA_MULTIPLE_INHERITANCE, + SWIGWARN_CSHARP_MULTIPLE_INHERITANCE, + SWIGWARN_D_MULTIPLE_INHERITANCE, + SWIGWARN_RUBY_MULTIPLE_INHERITANCE, + SWIGWARN_PHP_MULTIPLE_INHERITANCE) stir::DiscretisedDensity<3,float>; + +%include + +%{ +#include +namespace stir {} +using namespace stir; +%} + +%inline %{ +namespace stir { + // Note: CRTP + template + class RegisteredParsingObject : public Parent { + }; +} +%} + +%shared_ptr(stir::Array<3,float>) +%inline %{ +namespace stir { + template + class Array { + }; +} +%} +%template(FloatArray3D) stir::Array<3,float>; + +%shared_ptr(stir::ExamData); +%inline %{ +namespace stir { + class ExamData { + }; +} +%} + +%shared_ptr(stir::DiscretisedDensity<3,float>) +%inline %{ +namespace stir { + template + class DiscretisedDensity : public ExamData, public Array { + }; +} +%} + +%shared_ptr(stir::DataProcessor >) +%shared_ptr(stir::RegisteredParsingObject< + stir::ChainedDataProcessor >, + stir::DataProcessor >, + stir::DataProcessor > >) +%shared_ptr(stir::ChainedDataProcessor >) + +%inline %{ +namespace stir { + template + class DataProcessor { + }; + + template + class ChainedDataProcessor : public RegisteredParsingObject< ChainedDataProcessor, DataProcessor, DataProcessor > { + }; +} +%} + +// SWIG will qualify Discretised in the %template() declaration even though Discretised +// is not in scope with the 'using namespace stir' below commented out. +//using namespace stir; +%template(Float3DDiscretisedDensity) stir::DiscretisedDensity<3,float>; +%template(DataProcessor3DFloat) stir::DataProcessor >; +%template(RPChainedDataProcessor3DFloat) stir::RegisteredParsingObject< + stir::ChainedDataProcessor >, + stir::DataProcessor >, + stir::DataProcessor > >; +%template(ChainedDataProcessor3DFloat) stir::ChainedDataProcessor >; + +%inline %{ +void useobject(stir::RegisteredParsingObject< + stir::ChainedDataProcessor >, + stir::DataProcessor >, + stir::DataProcessor > >) { +} +%} diff --git a/Examples/test-suite/csharp/Makefile.in b/Examples/test-suite/csharp/Makefile.in index ca5a59160..6bda2ab56 100644 --- a/Examples/test-suite/csharp/Makefile.in +++ b/Examples/test-suite/csharp/Makefile.in @@ -41,6 +41,7 @@ CPP_TEST_CASES = \ CPP11_TEST_CASES = \ cpp11_shared_ptr_const \ + cpp11_shared_ptr_crtp_upcast \ cpp11_shared_ptr_nullptr_in_containers \ cpp11_shared_ptr_overload \ cpp11_shared_ptr_template_upcast \ diff --git a/Examples/test-suite/d/Makefile.in b/Examples/test-suite/d/Makefile.in index c9ece6140..10eddf17a 100644 --- a/Examples/test-suite/d/Makefile.in +++ b/Examples/test-suite/d/Makefile.in @@ -18,6 +18,7 @@ CPP_TEST_CASES = \ CPP11_TEST_CASES = \ cpp11_shared_ptr_const \ + cpp11_shared_ptr_crtp_upcast \ cpp11_shared_ptr_nullptr_in_containers \ cpp11_shared_ptr_overload \ cpp11_shared_ptr_upcast \ diff --git a/Examples/test-suite/errors/cpp_smartptr_feature.i b/Examples/test-suite/errors/cpp_smartptr_feature.i new file mode 100644 index 000000000..4a0d510cd --- /dev/null +++ b/Examples/test-suite/errors/cpp_smartptr_feature.i @@ -0,0 +1,14 @@ +%module xxx + +%feature("smartptr", noblock=1) AA { std::shared_ptr< AA > } +%feature("smartptr", noblock=1) DD { std::shared_ptr< } + + +struct AA {}; +struct BB : AA {}; +struct CC : AA {}; +struct DD : AA {}; + +%feature("smartptr", noblock=1) YY { std::shared_ptr< YY > } +struct XX {}; +struct YY : XX {}; diff --git a/Examples/test-suite/errors/cpp_smartptr_feature.stderr b/Examples/test-suite/errors/cpp_smartptr_feature.stderr new file mode 100644 index 000000000..442f795ac --- /dev/null +++ b/Examples/test-suite/errors/cpp_smartptr_feature.stderr @@ -0,0 +1,5 @@ +cpp_smartptr_feature.i:8: Warning 520: Derived class 'BB' of 'AA' is not similarly marked as a smart pointer. +cpp_smartptr_feature.i:9: Warning 520: Derived class 'CC' of 'AA' is not similarly marked as a smart pointer. +cpp_smartptr_feature.i:10: Error: Invalid type (std::shared_ptr<) in 'smartptr' feature for class DD. +cpp_smartptr_feature.i:10: Warning 520: Derived class 'DD' of 'AA' is not similarly marked as a smart pointer. +cpp_smartptr_feature.i:14: Warning 520: Base class 'XX' of 'YY' is not similarly marked as a smart pointer. diff --git a/Examples/test-suite/java/Makefile.in b/Examples/test-suite/java/Makefile.in index 00ebb100b..83335d4d4 100644 --- a/Examples/test-suite/java/Makefile.in +++ b/Examples/test-suite/java/Makefile.in @@ -55,6 +55,7 @@ CPP_TEST_CASES = \ CPP11_TEST_CASES = \ cpp11_shared_ptr_const \ + cpp11_shared_ptr_crtp_upcast \ cpp11_shared_ptr_nullptr_in_containers \ cpp11_shared_ptr_overload \ cpp11_shared_ptr_template_upcast \ diff --git a/Examples/test-suite/octave/Makefile.in b/Examples/test-suite/octave/Makefile.in index 3de1f72fc..78d4dec92 100644 --- a/Examples/test-suite/octave/Makefile.in +++ b/Examples/test-suite/octave/Makefile.in @@ -26,6 +26,7 @@ CPP_TEST_CASES += \ CPP11_TEST_CASES += \ cpp11_shared_ptr_const \ + cpp11_shared_ptr_crtp_upcast \ cpp11_shared_ptr_nullptr_in_containers \ cpp11_shared_ptr_overload \ cpp11_shared_ptr_upcast \ diff --git a/Examples/test-suite/python/Makefile.in b/Examples/test-suite/python/Makefile.in index 5e7e8b3ec..fca2d3ff5 100644 --- a/Examples/test-suite/python/Makefile.in +++ b/Examples/test-suite/python/Makefile.in @@ -90,6 +90,7 @@ CPP_TEST_CASES += \ CPP11_TEST_CASES = \ cpp11_hash_tables \ cpp11_shared_ptr_const \ + cpp11_shared_ptr_crtp_upcast \ cpp11_shared_ptr_nullptr_in_containers \ cpp11_shared_ptr_overload \ cpp11_shared_ptr_template_upcast \ diff --git a/Examples/test-suite/ruby/Makefile.in b/Examples/test-suite/ruby/Makefile.in index c831f1940..9171b84ce 100644 --- a/Examples/test-suite/ruby/Makefile.in +++ b/Examples/test-suite/ruby/Makefile.in @@ -44,6 +44,7 @@ CPP_TEST_CASES = \ CPP11_TEST_CASES = \ cpp11_hash_tables \ cpp11_shared_ptr_const \ + cpp11_shared_ptr_crtp_upcast \ cpp11_shared_ptr_nullptr_in_containers \ cpp11_shared_ptr_overload \ cpp11_shared_ptr_upcast \ diff --git a/Source/CParse/parser.y b/Source/CParse/parser.y index 39b9a8e27..3afdb2b8b 100644 --- a/Source/CParse/parser.y +++ b/Source/CParse/parser.y @@ -321,7 +321,14 @@ Hash *Swig_cparse_features(void) { return features_hash; } -/* Fully qualify any template parameters */ +/* ----------------------------------------------------------------------------- + * feature_identifier_fix() + * + * If a template, return template with all template parameters fully resolved. + * + * This is a copy and modification of typemap_identifier_fix. + * ----------------------------------------------------------------------------- */ + static String *feature_identifier_fix(String *s) { String *tp = SwigType_istemplate_templateprefix(s); if (tp) { diff --git a/Source/Modules/csharp.cxx b/Source/Modules/csharp.cxx index 45a396f5a..d217b5fd0 100644 --- a/Source/Modules/csharp.cxx +++ b/Source/Modules/csharp.cxx @@ -1729,6 +1729,7 @@ public: Node *base = it.item; SwigType *c_baseclassname = Getattr(base, "name"); String *interface_name = Getattr(base, "interface:name"); + SwigType *bsmart = Getattr(base, "smart"); if (Len(interface_list)) Append(interface_list, ", "); Append(interface_list, interface_name); @@ -1747,7 +1748,7 @@ public: Replaceall(cptr_method_name, "$interfacename", interface_name); String *upcast_method_name = Swig_name_member(getNSpace(), getClassPrefix(), cptr_method_name); - upcastsCode(smart, upcast_method_name, c_classname, c_baseclassname); + upcastsCode(smart, bsmart, upcast_method_name, c_classname, c_baseclassname); Delete(upcast_method_name); Delete(cptr_method_name); @@ -1761,7 +1762,7 @@ public: * Add code for C++ casting to base class * ----------------------------------------------------------------------------- */ - void upcastsCode(SwigType *smart, String *upcast_method_name, SwigType *c_classname, SwigType *c_baseclassname) { + void upcastsCode(SwigType *smart, SwigType *bsmart, String *upcast_method_name, SwigType *c_classname, SwigType *c_baseclassname) { String *wname = Swig_name_wrapper(upcast_method_name); Printv(imclass_cppcasts_code, "\n [global::System.Runtime.InteropServices.DllImport(\"", dllimport, "\", EntryPoint=\"", wname, "\")]\n", NIL); @@ -1770,18 +1771,18 @@ public: Replaceall(imclass_cppcasts_code, "$csclassname", proxy_class_name); if (smart) { - SwigType *bsmart = Swig_smartptr_upcast(smart, c_classname, c_baseclassname); - String *smartnamestr = SwigType_namestr(smart); - String *bsmartnamestr = SwigType_namestr(bsmart); + if (bsmart) { + String *smartnamestr = SwigType_namestr(smart); + String *bsmartnamestr = SwigType_namestr(bsmart); - Printv(upcasts_code, - "SWIGEXPORT ", bsmartnamestr, " * SWIGSTDCALL ", wname, "(", smartnamestr, " *jarg1) {\n", - " return jarg1 ? new ", bsmartnamestr, "(*jarg1) : 0;\n" - "}\n", "\n", NIL); + Printv(upcasts_code, + "SWIGEXPORT ", bsmartnamestr, " * SWIGSTDCALL ", wname, "(", smartnamestr, " *jarg1) {\n", + " return jarg1 ? new ", bsmartnamestr, "(*jarg1) : 0;\n" + "}\n", "\n", NIL); - Delete(bsmartnamestr); - Delete(smartnamestr); - Delete(bsmart); + Delete(bsmartnamestr); + Delete(smartnamestr); + } } else { String *classname = SwigType_namestr(c_classname); String *baseclassname = SwigType_namestr(c_baseclassname); @@ -1811,7 +1812,8 @@ public: SwigType *typemap_lookup_type = Getattr(n, "classtypeobj"); bool feature_director = Swig_directorclass(n) ? true : false; bool has_outerclass = Getattr(n, "nested:outer") != 0 && !GetFlag(n, "feature:flatnested"); - SwigType *smart = Swig_cparse_smartptr(n); + SwigType *smart = Getattr(n, "smart"); + SwigType *bsmart = 0; // Inheritance from pure C# classes Node *attributes = NewHash(); @@ -1833,6 +1835,7 @@ public: if (name) { c_baseclassname = baseclassname; baseclass = name; + bsmart = Getattr(base.item, "smart"); } } else { /* Warn about multiple inheritance for additional base class(es) */ @@ -2070,11 +2073,9 @@ public: if (derived) { String *upcast_method_name = Swig_name_member(getNSpace(), getClassPrefix(), smart != 0 ? "SWIGSmartPtrUpcast" : "SWIGUpcast"); - upcastsCode(smart, upcast_method_name, c_classname, c_baseclassname); + upcastsCode(smart, bsmart, upcast_method_name, c_classname, c_baseclassname); Delete(upcast_method_name); } - - Delete(smart); } /* ---------------------------------------------------------------------- @@ -3809,7 +3810,8 @@ public: String *qualified_classname = Copy(sym_name); String *nspace = getNSpace(); String *dirClassName = directorClassName(n); - String *smartptr = Getattr(n, "feature:smartptr"); + SwigType *smart = Getattr(n, "smart"); + String *smartptr = smart ? SwigType_namestr(smart) : 0; if (!GetFlag(n, "feature:flatnested")) { for (Node *outer_class = Getattr(n, "nested:outer"); outer_class; outer_class = Getattr(outer_class, "nested:outer")) { diff --git a/Source/Modules/d.cxx b/Source/Modules/d.cxx index 6fed3af4b..3bcee6b39 100644 --- a/Source/Modules/d.cxx +++ b/Source/Modules/d.cxx @@ -3183,6 +3183,7 @@ private: String *c_baseclassname = NULL; Node *basenode = NULL; String *baseclass = NULL; + SwigType *bsmart = 0; // Inheritance from pure D classes. Node *attributes = NewHash(); @@ -3206,6 +3207,7 @@ private: if (name) { c_baseclassname = baseclassname; baseclass = name; + bsmart = Getattr(base.item, "smart"); } } else { /* Warn about multiple inheritance for additional base class(es) */ @@ -3244,7 +3246,7 @@ private: // Add code to do C++ casting to base class (only for classes in an inheritance hierarchy) if (derived) { - writeClassUpcast(n, proxy_class_name, c_classname, c_baseclassname); + writeClassUpcast(n, bsmart, proxy_class_name, c_classname, c_baseclassname); } /* @@ -3405,9 +3407,9 @@ private: /* --------------------------------------------------------------------------- * D::writeClassUpcast() * --------------------------------------------------------------------------- */ - void writeClassUpcast(Node *n, const String* d_class_name, SwigType* c_classname, SwigType* c_baseclassname) { + void writeClassUpcast(Node *n, SwigType *bsmart, const String *d_class_name, SwigType *c_classname, SwigType *c_baseclassname) { - SwigType *smart = Swig_cparse_smartptr(n); + SwigType *smart = Getattr(n, "smart"); String *upcast_name = Swig_name_member(getNSpace(), d_class_name, (smart != 0 ? "SmartPtrUpcast" : "Upcast")); String *upcast_wrapper_name = Swig_name_wrapper(upcast_name); @@ -3417,20 +3419,20 @@ private: String *baseclassname = SwigType_namestr(c_baseclassname); if (smart) { - SwigType *bsmart = Swig_smartptr_upcast(smart, c_classname, c_baseclassname); - String *smartnamestr = SwigType_namestr(smart); - String *bsmartnamestr = SwigType_namestr(bsmart); + if (bsmart) { + String *smartnamestr = SwigType_namestr(smart); + String *bsmartnamestr = SwigType_namestr(bsmart); - Printv(upcasts_code, - "SWIGEXPORT ", bsmartnamestr, " * ", upcast_wrapper_name, - "(", smartnamestr, " *objectRef) {\n", - " return objectRef ? new ", bsmartnamestr, "(*objectRef) : 0;\n" - "}\n", - "\n", NIL); + Printv(upcasts_code, + "SWIGEXPORT ", bsmartnamestr, " * ", upcast_wrapper_name, + "(", smartnamestr, " *objectRef) {\n", + " return objectRef ? new ", bsmartnamestr, "(*objectRef) : 0;\n" + "}\n", + "\n", NIL); - Delete(bsmartnamestr); - Delete(smartnamestr); - Delete(bsmart); + Delete(bsmartnamestr); + Delete(smartnamestr); + } } else { Printv(upcasts_code, "SWIGEXPORT ", baseclassname, " * ", upcast_wrapper_name, @@ -3447,7 +3449,6 @@ private: Delete(classname); Delete(upcast_wrapper_name); Delete(upcast_name); - Delete(smart); } /* --------------------------------------------------------------------------- diff --git a/Source/Modules/java.cxx b/Source/Modules/java.cxx index 203485831..e35dbcb3b 100644 --- a/Source/Modules/java.cxx +++ b/Source/Modules/java.cxx @@ -1808,6 +1808,7 @@ public: Node *base = it.item; SwigType *c_baseclassname = Getattr(base, "name"); String *interface_name = Getattr(base, "interface:name"); + SwigType *bsmart = Getattr(base, "smart"); if (Len(interface_list)) Append(interface_list, ", "); Append(interface_list, interface_name); @@ -1826,7 +1827,7 @@ public: Replaceall(cptr_method_name, "$interfacename", interface_name); String *upcast_method_name = Swig_name_member(getNSpace(), getClassPrefix(), cptr_method_name); - upcastsCode(smart, upcast_method_name, c_classname, c_baseclassname); + upcastsCode(smart, bsmart, upcast_method_name, c_classname, c_baseclassname); Delete(upcast_method_name); Delete(cptr_method_name); @@ -1840,31 +1841,31 @@ public: * Add code for C++ casting to base class * ----------------------------------------------------------------------------- */ - void upcastsCode(SwigType *smart, String *upcast_method_name, SwigType *c_classname, SwigType *c_baseclassname) { + void upcastsCode(SwigType *smart, SwigType *bsmart, String *upcast_method_name, SwigType *c_classname, SwigType *c_baseclassname) { String *jniname = makeValidJniName(upcast_method_name); String *wname = Swig_name_wrapper(jniname); Printf(imclass_cppcasts_code, " public final static native long %s(long jarg1);\n", upcast_method_name); if (smart) { - SwigType *bsmart = Swig_smartptr_upcast(smart, c_classname, c_baseclassname); - String *smartnamestr = SwigType_namestr(smart); - String *bsmartnamestr = SwigType_namestr(bsmart); + if (bsmart) { + String *smartnamestr = SwigType_namestr(smart); + String *bsmartnamestr = SwigType_namestr(bsmart); - Printv(upcasts_code, - "SWIGEXPORT jlong JNICALL ", wname, "(JNIEnv *jenv, jclass jcls, jlong jarg1) {\n", - " jlong baseptr = 0;\n" - " ", smartnamestr, " *argp1;\n" - " (void)jenv;\n" - " (void)jcls;\n" - " argp1 = *(", smartnamestr, " **)&jarg1;\n" - " *(", bsmartnamestr, " **)&baseptr = argp1 ? new ", bsmartnamestr, "(*argp1) : 0;\n" - " return baseptr;\n" - "}\n", "\n", NIL); + Printv(upcasts_code, + "SWIGEXPORT jlong JNICALL ", wname, "(JNIEnv *jenv, jclass jcls, jlong jarg1) {\n", + " jlong baseptr = 0;\n" + " ", smartnamestr, " *argp1;\n" + " (void)jenv;\n" + " (void)jcls;\n" + " argp1 = *(", smartnamestr, " **)&jarg1;\n" + " *(", bsmartnamestr, " **)&baseptr = argp1 ? new ", bsmartnamestr, "(*argp1) : 0;\n" + " return baseptr;\n" + "}\n", "\n", NIL); - Delete(bsmartnamestr); - Delete(smartnamestr); - Delete(bsmart); + Delete(bsmartnamestr); + Delete(smartnamestr); + } } else { String *classname = SwigType_namestr(c_classname); String *baseclassname = SwigType_namestr(c_baseclassname); @@ -1899,7 +1900,8 @@ public: SwigType *typemap_lookup_type = Getattr(n, "classtypeobj"); bool feature_director = Swig_directorclass(n) ? true : false; bool has_outerclass = Getattr(n, "nested:outer") != 0 && !GetFlag(n, "feature:flatnested"); - SwigType *smart = Swig_cparse_smartptr(n); + SwigType *smart = Getattr(n, "smart"); + SwigType *bsmart = 0; // Inheritance from pure Java classes Node *attributes = NewHash(); @@ -1921,6 +1923,7 @@ public: if (name) { c_baseclassname = baseclassname; baseclass = name; + bsmart = Getattr(base.item, "smart"); } } else { /* Warn about multiple inheritance for additional base class(es) */ @@ -2068,11 +2071,9 @@ public: if (derived) { String *upcast_method_name = Swig_name_member(getNSpace(), getClassPrefix(), smart != 0 ? "SWIGSmartPtrUpcast" : "SWIGUpcast"); - upcastsCode(smart, upcast_method_name, c_classname, c_baseclassname); + upcastsCode(smart, bsmart, upcast_method_name, c_classname, c_baseclassname); Delete(upcast_method_name); } - - Delete(smart); } /* ---------------------------------------------------------------------- @@ -3790,7 +3791,8 @@ public: String *norm_name = SwigType_namestr(Getattr(n, "name")); String *swig_director_connect = Swig_name_member(getNSpace(), getClassPrefix(), "director_connect"); String *swig_director_connect_jni = makeValidJniName(swig_director_connect); - String *smartptr = Getattr(n, "feature:smartptr"); + SwigType *smart = Getattr(n, "smart"); + String *smartptr = smart ? SwigType_namestr(smart) : 0; String *dirClassName = directorClassName(n); Wrapper *code_wrap; @@ -3836,7 +3838,7 @@ public: "SWIGEXPORT void JNICALL Java_%s%s_%s(JNIEnv *jenv, jclass jcls, jobject jself, jlong objarg, jboolean jtake_or_release) {\n", jnipackage, jni_imclass_name, changeown_jnimethod_name); - if (Len(smartptr)) { + if (smartptr) { Printf(code_wrap->code, " %s *obj = *((%s **)&objarg);\n", smartptr, smartptr); Printf(code_wrap->code, " // Keep a local instance of the smart pointer around while we are using the raw pointer\n"); Printf(code_wrap->code, " // Avoids using smart pointer specific API.\n"); diff --git a/Source/Modules/octave.cxx b/Source/Modules/octave.cxx index a16858d2a..a85320b92 100644 --- a/Source/Modules/octave.cxx +++ b/Source/Modules/octave.cxx @@ -964,13 +964,14 @@ public: SwigType_add_pointer(t); // Replace storing a pointer to underlying class with a smart pointer (intended for use with non-intrusive smart pointers) - SwigType *smart = Swig_cparse_smartptr(n); + SwigType *smart = Getattr(n, "smart"); String *wrap_class = NewStringf("&_wrap_class_%s", class_name); if (smart) { - SwigType_add_pointer(smart); - SwigType_remember_clientdata(smart, wrap_class); + SwigType *psmart = Copy(smart); + SwigType_add_pointer(psmart); + SwigType_remember_clientdata(psmart, wrap_class); + Delete(psmart); } - //String *wrap_class = NewStringf("&_wrap_class_%s", class_name); SwigType_remember_clientdata(t, wrap_class); int use_director = Swig_directorclass(n); @@ -1047,7 +1048,6 @@ public: Delete(base_class); Delete(base_class_names); - Delete(smart); Delete(t); Delete(s_members_tab); s_members_tab = 0; diff --git a/Source/Modules/python.cxx b/Source/Modules/python.cxx index 56e888f8a..905a0263a 100644 --- a/Source/Modules/python.cxx +++ b/Source/Modules/python.cxx @@ -4365,12 +4365,14 @@ public: Printf(clientdata, "&%s_clientdata", templ); SwigType_remember_mangleddata(pmname, clientdata); - SwigType *smart = Swig_cparse_smartptr(n); + SwigType *smart = Getattr(n, "smart"); if (smart) { - SwigType_add_pointer(smart); - String *smart_pmname = SwigType_manglestr(smart); + SwigType *psmart = Copy(smart); + SwigType_add_pointer(psmart); + String *smart_pmname = SwigType_manglestr(psmart); SwigType_remember_mangleddata(smart_pmname, clientdata); Delete(smart_pmname); + Delete(psmart); } String *clientdata_klass = NewString("0"); @@ -4395,7 +4397,6 @@ public: Printv(f_init, " d = md;\n", NIL); Delete(clientdata); - Delete(smart); Delete(sname); Delete(rname); Delete(mname); @@ -4573,7 +4574,7 @@ public: if (shadow) { /* Generate a class registration function */ // Replace storing a pointer to underlying class with a smart pointer (intended for use with non-intrusive smart pointers) - SwigType *smart = Swig_cparse_smartptr(n); + SwigType *smart = Getattr(n, "smart"); SwigType *ct = Copy(smart ? smart : real_classname); SwigType_add_pointer(ct); SwigType *realct = Copy(real_classname); @@ -4595,7 +4596,6 @@ public: add_method(cname, cname, 0, 0, 1, 1, 1); Delete(cname); } - Delete(smart); Delete(ct); Delete(realct); if (!have_constructor) { diff --git a/Source/Modules/ruby.cxx b/Source/Modules/ruby.cxx index cb7d79fc9..f6facbb55 100644 --- a/Source/Modules/ruby.cxx +++ b/Source/Modules/ruby.cxx @@ -1809,7 +1809,7 @@ public: Wrapper_add_local(f, "classname", classname); } if (action) { - SwigType *smart = Swig_cparse_smartptr(pn); + SwigType *smart = Getattr(pn, "smart"); String *result_name = NewStringf("%s%s", smart ? "smart" : "", Swig_cresult_name()); if (smart) { String *result_var = NewStringf("%s *%s = 0", SwigType_namestr(smart), result_name); @@ -1821,7 +1821,6 @@ public: Printf(action, "\nSWIG_RubyAddTracking(%s, self);", result_name); } Delete(result_name); - Delete(smart); } } @@ -1888,16 +1887,17 @@ public: /* Extra code needed for new and initialize methods */ if (current == CONSTRUCTOR_ALLOCATE) { Node *pn = Swig_methodclass(n); - SwigType *smart = Swig_cparse_smartptr(pn); - if (smart) - SwigType_add_pointer(smart); - String *classtype = smart ? smart : t; + SwigType *smart = Getattr(pn, "smart"); + SwigType *psmart = smart ? Copy(smart) : 0; + if (psmart) + SwigType_add_pointer(psmart); + String *classtype = psmart ? psmart : t; need_result = 1; Printf(f->code, "VALUE vresult = SWIG_NewClassInstance(self, SWIGTYPE%s);\n", Char(SwigType_manglestr(classtype))); Printf(f->code, "#ifndef HAVE_RB_DEFINE_ALLOC_FUNC\n"); Printf(f->code, "rb_obj_call_init(vresult, argc, argv);\n"); Printf(f->code, "#endif\n"); - Delete(smart); + Delete(psmart); } else if (current == CONSTRUCTOR_INITIALIZE) { need_result = 1; } @@ -2399,12 +2399,13 @@ public: SwigType *btype = NewString(basename); SwigType_add_pointer(btype); SwigType_remember(btype); - SwigType *smart = Swig_cparse_smartptr(base.item); - if (smart) { - SwigType_add_pointer(smart); - SwigType_remember(smart); + SwigType *smart = Getattr(base.item, "smart"); + SwigType *psmart = smart ? Copy(psmart) : 0; + if (psmart) { + SwigType_add_pointer(psmart); + SwigType_remember(psmart); } - String *bmangle = SwigType_manglestr(smart ? smart : btype); + String *bmangle = SwigType_manglestr(psmart ? psmart : btype); if (multipleInheritance) { Insert(bmangle, 0, "((swig_class *) SWIGTYPE"); Append(bmangle, "->clientdata)->mImpl"); @@ -2415,7 +2416,7 @@ public: Replaceall(klass->init, "$super", bmangle); } Delete(bmangle); - Delete(smart); + Delete(psmart); Delete(btype); } base = Next(base); @@ -2516,15 +2517,15 @@ public: SwigType *tt = NewString(name); SwigType_add_pointer(tt); SwigType_remember(tt); - SwigType *smart = Swig_cparse_smartptr(n); - if (smart) { - SwigType_add_pointer(smart); - SwigType_remember(smart); + SwigType *psmart = Getattr(n, "smart"); + if (psmart) { + SwigType_add_pointer(psmart); + SwigType_remember(psmart); } - String *tm = SwigType_manglestr(smart ? smart : tt); + String *tm = SwigType_manglestr(psmart ? psmart : tt); Printf(klass->init, "SWIG_TypeClientData(SWIGTYPE%s, (void *) &SwigClass%s);\n", tm, valid_name); Delete(tm); - Delete(smart); + Delete(psmart); Delete(tt); Delete(valid_name); diff --git a/Source/Modules/swigmod.h b/Source/Modules/swigmod.h index fa89a6363..a053f36f0 100644 --- a/Source/Modules/swigmod.h +++ b/Source/Modules/swigmod.h @@ -421,7 +421,6 @@ void Wrapper_cast_dispatch_mode_set(int); void Wrapper_naturalvar_mode_set(int); void clean_overloaded(Node *n); -SwigType *Swig_smartptr_upcast(SwigType *smart, SwigType *c_classname, SwigType *c_baseclassname); extern "C" { const char *Swig_to_string(DOH *object, int count = -1); diff --git a/Source/Modules/typepass.cxx b/Source/Modules/typepass.cxx index 74171f355..c28226044 100644 --- a/Source/Modules/typepass.cxx +++ b/Source/Modules/typepass.cxx @@ -253,20 +253,18 @@ class TypePass:private Dispatcher { int len = Len(ilist); int i; for (i = 0; i < len; i++) { - Node *n = Getitem(ilist, i); - SwigType *bname = Getattr(n, "name"); - Node *bclass = n; /* Getattr(n,"class"); */ + Node *bclass = Getitem(ilist, i); + SwigType *bname = Getattr(bclass, "name"); Hash *scopes = Getattr(bclass, "typescope"); SwigType_inherit(clsname, bname, cast, 0); if (ispublic && !GetFlag(bclass, "feature:ignore")) { - String *smartptr = Getattr(first, "feature:smartptr"); - if (smartptr) { - SwigType *smart = Swig_cparse_smartptr(first); - if (smart) { - /* Record a (fake) inheritance relationship between smart pointer - and smart pointer to base class, so that smart pointer upcasts - are automatically generated. */ - SwigType *bsmart = Swig_smartptr_upcast(smart, clsname, bname); + String *smart = Getattr(first, "smart"); + if (smart) { + /* Record a (fake) inheritance relationship between smart pointer + and smart pointer to base class, so that smart pointer upcasts + are automatically generated. */ + SwigType *bsmart = Getattr(bclass, "smart"); + if (bsmart) { String *smartnamestr = SwigType_namestr(smart); String *bsmartnamestr = SwigType_namestr(bsmart); @@ -275,17 +273,15 @@ class TypePass:private Dispatcher { /* setup inheritance relationship between smart pointer templates */ SwigType_inherit(smart, bsmart, 0, convcode); - if (!GetFlag(bclass, "feature:smartptr")) - Swig_warning(WARN_LANG_SMARTPTR_MISSING, Getfile(first), Getline(first), "Base class '%s' of '%s' is not similarly marked as a smart pointer.\n", SwigType_namestr(Getattr(bclass, "name")), SwigType_namestr(Getattr(first, "name"))); Delete(bsmartnamestr); Delete(smartnamestr); Delete(convcode); - Delete(bsmart); + } else { + Swig_warning(WARN_LANG_SMARTPTR_MISSING, Getfile(first), Getline(first), "Base class '%s' of '%s' is not similarly marked as a smart pointer.\n", SwigType_namestr(Getattr(bclass, "name")), SwigType_namestr(Getattr(first, "name"))); } - Delete(smart); } else { - if (GetFlag(bclass, "feature:smartptr")) + if (GetFlag(bclass, "smart")) Swig_warning(WARN_LANG_SMARTPTR_MISSING, Getfile(first), Getline(first), "Derived class '%s' of '%s' is not similarly marked as a smart pointer.\n", SwigType_namestr(Getattr(first, "name")), SwigType_namestr(Getattr(bclass, "name"))); } } @@ -503,6 +499,16 @@ class TypePass:private Dispatcher { SwigType_new_scope(scopename); SwigType_attach_symtab(Getattr(n, "symtab")); + if (!GetFlag(n, "feature:ignore")) { + SwigType *smart = Swig_cparse_smartptr(n); + if (smart) { + // Resolve the type in 'feature:smartptr' in the scope of the class it is attached to + normalize_type(smart); + Setattr(n, "smart", smart); + Delete(smart); + } + } + /* Inherit type definitions into the class */ if (name && !(GetFlag(n, "nested") && !checkAttribute(n, "access", "public") && (GetFlag(n, "feature:flatnested") || Language::instance()->nestedClassesSupport() == Language::NCS_None))) { diff --git a/Source/Modules/utils.cxx b/Source/Modules/utils.cxx index 2ae1afa61..2d956c4c8 100644 --- a/Source/Modules/utils.cxx +++ b/Source/Modules/utils.cxx @@ -122,67 +122,6 @@ void Swig_set_max_hash_expand(int count) { SetMaxHashExpand(count); } -/* ----------------------------------------------------------------------------- - * misc_identifier_fix() - * - * If a template, return template with all template parameters fully resolved. - * - * This is a copy and modification of feature_identifier_fix and typemap_identifier_fix. - * ----------------------------------------------------------------------------- */ - -static SwigType *misc_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; -} - -/* ----------------------------------------------------------------------------- - * Swig_smartptr_upcast() - * - * Replace classname with baseclassname in smart (smart pointer) to morph smart into a - * smart pointer containing the base class instead of the given classname. - * All parameters should be fully qualified types. - * ----------------------------------------------------------------------------- */ - -SwigType *Swig_smartptr_upcast(SwigType *smart, SwigType *classname, SwigType *baseclassname) { - SwigType *bsmart = Copy(smart); - - SwigType *rclassname = SwigType_typedef_resolve_all(classname); - SwigType *rbaseclassname = SwigType_typedef_resolve_all(baseclassname); - - int replace_count = Replaceall(bsmart, rclassname, rbaseclassname); - if (replace_count == 0) { - // If no replacement made, it will be because rclassname is fully resolved, but the - // type in the smartptr feature used a typedef or is not a fully resolved name. - replace_count = Replaceall(bsmart, classname, rbaseclassname); - if (replace_count == 0) { - // Next try with all the template parameters in the smartptr resolved - Delete(bsmart); - SwigType *bsmart = misc_identifier_fix(smart); - if (bsmart) { - replace_count = Replaceall(bsmart, rclassname, rbaseclassname); - } - assert(replace_count); // failed to substitute - } - } - - Delete(rbaseclassname); - Delete(rclassname); - return bsmart; -} - extern "C" { diff --git a/Source/Swig/typemap.c b/Source/Swig/typemap.c index b76203454..3294bdf77 100644 --- a/Source/Swig/typemap.c +++ b/Source/Swig/typemap.c @@ -69,8 +69,6 @@ static Hash *typemaps; * resolving the template parameters. * * This is a copy and modification of feature_identifier_fix in parser.y. - * Also, Swig_smartptr_upcast() could be removed if SwigType_typedef_resolve_all - * is fixed to resolve all template parameters like below. * ----------------------------------------------------------------------------- */ static SwigType *typemap_identifier_fix(const SwigType *s) {