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
This commit is contained in:
William S Fulton 2024-01-29 08:53:55 +00:00
parent d6850a60fa
commit 3be670e8db
21 changed files with 244 additions and 168 deletions

View File

@ -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.

View File

@ -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 <std_shared_ptr.i>
%{
#include <memory>
namespace stir {}
using namespace stir;
%}
%inline %{
namespace stir {
// Note: CRTP
template <typename Derived, typename Base, typename Parent = Base>
class RegisteredParsingObject : public Parent {
};
}
%}
%shared_ptr(stir::Array<3,float>)
%inline %{
namespace stir {
template <int num_dimensions, typename elemT>
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<int num_dimensions, typename elemT>
class DiscretisedDensity : public ExamData, public Array<num_dimensions,elemT> {
};
}
%}
%shared_ptr(stir::DataProcessor<stir::DiscretisedDensity<3,float> >)
%shared_ptr(stir::RegisteredParsingObject<
stir::ChainedDataProcessor<stir::DiscretisedDensity<3,float> >,
stir::DataProcessor<DiscretisedDensity<3,float> >,
stir::DataProcessor<DiscretisedDensity<3,float> > >)
%shared_ptr(stir::ChainedDataProcessor<stir::DiscretisedDensity<3,float> >)
%inline %{
namespace stir {
template <typename DataT>
class DataProcessor {
};
template <typename DataT>
class ChainedDataProcessor : public RegisteredParsingObject< ChainedDataProcessor<DataT>, DataProcessor<DataT>, DataProcessor<DataT> > {
};
}
%}
// 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<stir::DiscretisedDensity<3,float> >;
%template(RPChainedDataProcessor3DFloat) stir::RegisteredParsingObject<
stir::ChainedDataProcessor<stir::DiscretisedDensity<3,float> >,
stir::DataProcessor<DiscretisedDensity<3,float> >,
stir::DataProcessor<DiscretisedDensity<3,float> > >;
%template(ChainedDataProcessor3DFloat) stir::ChainedDataProcessor<stir::DiscretisedDensity<3,float> >;
%inline %{
void useobject(stir::RegisteredParsingObject<
stir::ChainedDataProcessor<stir::DiscretisedDensity<3,float> >,
stir::DataProcessor<DiscretisedDensity<3,float> >,
stir::DataProcessor<DiscretisedDensity<3,float> > >) {
}
%}

View File

@ -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 \

View File

@ -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 \

View File

@ -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 {};

View File

@ -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.

View File

@ -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 \

View File

@ -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 \

View File

@ -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 \

View File

@ -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 \

View File

@ -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) {

View File

@ -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")) {

View File

@ -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);
}
/* ---------------------------------------------------------------------------

View File

@ -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");

View File

@ -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;

View File

@ -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) {

View File

@ -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);

View File

@ -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);

View File

@ -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))) {

View File

@ -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" {

View File

@ -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) {