From 2acdfd77e9e498d604e1dc0636cf675f9ce10244 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Wed, 9 Nov 2022 22:11:27 +0000 Subject: [PATCH] SwigType * handling corrections Further corrections to pass SwigType * to methods expecting types instead of passing readable type strings. Required reworking code that adds a fake inheritance for smart pointers using the smartptr feature. Swig_smartptr_upcast() added as a support function for this. --- Source/Modules/csharp.cxx | 21 ++++++------- Source/Modules/d.cxx | 19 +++++------- Source/Modules/java.cxx | 21 ++++++------- Source/Modules/swigmod.h | 1 + Source/Modules/typepass.cxx | 30 +++++------------- Source/Modules/utils.cxx | 62 +++++++++++++++++++++++++++++++++++++ Source/Swig/typemap.c | 3 ++ 7 files changed, 98 insertions(+), 59 deletions(-) diff --git a/Source/Modules/csharp.cxx b/Source/Modules/csharp.cxx index 240a002b4..8d4b03151 100644 --- a/Source/Modules/csharp.cxx +++ b/Source/Modules/csharp.cxx @@ -1744,35 +1744,32 @@ public: Replaceall(imclass_cppcasts_code, "$csclassname", proxy_class_name); - String *classname = SwigType_namestr(c_classname); - 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(smart); - - // TODO: SwigType_typedef_resolve_all on a String instead of SwigType is incorrect for templates - SwigType *rclassname = SwigType_typedef_resolve_all(classname); - SwigType *rbaseclassname = SwigType_typedef_resolve_all(baseclassname); - Replaceall(bsmartnamestr, rclassname, rbaseclassname); + 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); - Delete(rbaseclassname); - Delete(rclassname); Delete(bsmartnamestr); Delete(smartnamestr); + Delete(bsmart); } else { + String *classname = SwigType_namestr(c_classname); + String *baseclassname = SwigType_namestr(c_baseclassname); + Printv(upcasts_code, "SWIGEXPORT ", baseclassname, " * SWIGSTDCALL ", wname, "(", classname, " *jarg1) {\n", " return (", baseclassname, " *)jarg1;\n" "}\n", "\n", NIL); + + Delete(baseclassname); + Delete(classname); } - Delete(baseclassname); - Delete(classname); Delete(wname); } diff --git a/Source/Modules/d.cxx b/Source/Modules/d.cxx index 31f300f2e..ecf931633 100644 --- a/Source/Modules/d.cxx +++ b/Source/Modules/d.cxx @@ -3374,19 +3374,15 @@ private: String *upcast_name = Swig_name_member(getNSpace(), d_class_name, (smart != 0 ? "SmartPtrUpcast" : "Upcast")); String *upcast_wrapper_name = Swig_name_wrapper(upcast_name); - writeImDModuleFunction(upcast_name, "void*", "(void* objectRef)", - upcast_wrapper_name); + writeImDModuleFunction(upcast_name, "void*", "(void* objectRef)", upcast_wrapper_name); String *classname = SwigType_namestr(c_classname); String *baseclassname = SwigType_namestr(c_baseclassname); - if (smart) { - String *smartnamestr = SwigType_namestr(smart); - String *bsmartnamestr = SwigType_namestr(smart); - // TODO: SwigType_typedef_resolve_all on a String instead of SwigType is incorrect for templates - SwigType *rclassname = SwigType_typedef_resolve_all(classname); - SwigType *rbaseclassname = SwigType_typedef_resolve_all(baseclassname); - Replaceall(bsmartnamestr, rclassname, rbaseclassname); + if (smart) { + SwigType *bsmart = Swig_smartptr_upcast(smart, c_classname, c_baseclassname); + String *smartnamestr = SwigType_namestr(smart); + String *bsmartnamestr = SwigType_namestr(bsmart); Printv(upcasts_code, "SWIGEXPORT ", bsmartnamestr, " * ", upcast_wrapper_name, @@ -3395,10 +3391,9 @@ private: "}\n", "\n", NIL); - Delete(rbaseclassname); - Delete(rclassname); Delete(bsmartnamestr); Delete(smartnamestr); + Delete(bsmart); } else { Printv(upcasts_code, "SWIGEXPORT ", baseclassname, " * ", upcast_wrapper_name, @@ -3413,8 +3408,8 @@ private: Delete(baseclassname); Delete(classname); - Delete(upcast_name); Delete(upcast_wrapper_name); + Delete(upcast_name); Delete(smart); } diff --git a/Source/Modules/java.cxx b/Source/Modules/java.cxx index 773945af2..d625d0476 100644 --- a/Source/Modules/java.cxx +++ b/Source/Modules/java.cxx @@ -1883,16 +1883,10 @@ public: Printf(imclass_cppcasts_code, " public final static native long %s(long jarg1);\n", upcast_method_name); - String *classname = SwigType_namestr(c_classname); - 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(smart); - - // TODO: SwigType_typedef_resolve_all on a String instead of SwigType is incorrect for templates - SwigType *rclassname = SwigType_typedef_resolve_all(classname); - SwigType *rbaseclassname = SwigType_typedef_resolve_all(baseclassname); - Replaceall(bsmartnamestr, rclassname, rbaseclassname); + String *bsmartnamestr = SwigType_namestr(bsmart); Printv(upcasts_code, "SWIGEXPORT jlong JNICALL ", wname, "(JNIEnv *jenv, jclass jcls, jlong jarg1) {\n", @@ -1905,11 +1899,13 @@ public: " return baseptr;\n" "}\n", "\n", NIL); - Delete(rbaseclassname); - Delete(rclassname); Delete(bsmartnamestr); Delete(smartnamestr); + Delete(bsmart); } else { + String *classname = SwigType_namestr(c_classname); + String *baseclassname = SwigType_namestr(c_baseclassname); + Printv(upcasts_code, "SWIGEXPORT jlong JNICALL ", wname, "(JNIEnv *jenv, jclass jcls, jlong jarg1) {\n", " jlong baseptr = 0;\n" @@ -1918,10 +1914,11 @@ public: " *(", baseclassname, " **)&baseptr = *(", classname, " **)&jarg1;\n" " return baseptr;\n" "}\n", "\n", NIL); + + Delete(baseclassname); + Delete(classname); } - Delete(baseclassname); - Delete(classname); Delete(wname); Delete(jniname); } diff --git a/Source/Modules/swigmod.h b/Source/Modules/swigmod.h index c605edf9d..dfeb2bace 100644 --- a/Source/Modules/swigmod.h +++ b/Source/Modules/swigmod.h @@ -423,6 +423,7 @@ 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 2a1dadf73..4a2a9df90 100644 --- a/Source/Modules/typepass.cxx +++ b/Source/Modules/typepass.cxx @@ -254,7 +254,7 @@ class TypePass:private Dispatcher { int i; for (i = 0; i < len; i++) { Node *n = Getitem(ilist, i); - String *bname = Getattr(n, "name"); + SwigType *bname = Getattr(n, "name"); Node *bclass = n; /* Getattr(n,"class"); */ Hash *scopes = Getattr(bclass, "typescope"); SwigType_inherit(clsname, bname, cast, 0); @@ -266,36 +266,20 @@ class TypePass:private Dispatcher { /* Record a (fake) inheritance relationship between smart pointer and smart pointer to base class, so that smart pointer upcasts are automatically generated. */ - SwigType *bsmart = Copy(smart); - - // TODO: SwigType_typedef_resolve_all on a String instead of SwigType is incorrect for templates - SwigType *rclsname = SwigType_typedef_resolve_all(clsname); - SwigType *rbname = SwigType_typedef_resolve_all(bname); - 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); - } - // The code above currently creates a smartptr of the base class by substitution, replacing Derived - // with Base resulting in something like: 'smartptr< Derived >' from 'smartptr< Base >'. Instead - // the feature:smartptr should be used as it also contains 'smartptr< Base >' as specified by the user. - // A similar fix should also be done in upcastsCode in java.cxx, csharp.cxx and writeClassUpcast in d.cxx. - // Printf(stdout, "smartcomparison %s <=> %s\n", SwigType_namestr(bsmart), Getattr(bclass, "feature:smartptr")); - - Delete(rclsname); - Delete(rbname); + SwigType *bsmart = Swig_smartptr_upcast(smart, clsname, bname); String *smartnamestr = SwigType_namestr(smart); String *bsmartnamestr = SwigType_namestr(bsmart); + /* construct casting code */ String *convcode = NewStringf("\n *newmemory = SWIG_CAST_NEW_MEMORY;\n return (void *) new %s(*(%s *)$from);\n", bsmartnamestr, smartnamestr); - Delete(bsmartnamestr); - Delete(smartnamestr); + /* 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); } diff --git a/Source/Modules/utils.cxx b/Source/Modules/utils.cxx index de6f87d8c..2072b73fa 100644 --- a/Source/Modules/utils.cxx +++ b/Source/Modules/utils.cxx @@ -115,6 +115,68 @@ 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 f0dee59d9..28e87702c 100644 --- a/Source/Swig/typemap.c +++ b/Source/Swig/typemap.c @@ -69,6 +69,8 @@ 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) { @@ -102,6 +104,7 @@ static Hash *get_typemap(const SwigType *type) { dtype = Swig_symbol_type_qualify(ty, 0); type = dtype; Delete(ty); + Delete(rty); } /* remove unary scope operator (::) prefix indicating global scope for looking up in the hashmap */