From 650aad82ede59abe1a9355c274e213d33ae9d543 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Sat, 9 Sep 2023 19:15:15 +0100 Subject: [PATCH] Fix incorrect variable setters being generated when wrapping arrays A setter is no longer generated if the type of the array members are non-assignable. --- CHANGES.current | 7 +++ Examples/test-suite/cpp11_assign_delete.i | 50 +++++++++++++++++++ .../java/cpp11_assign_delete_runme.java | 33 ++++++++++++ Examples/test-suite/private_assign.i | 6 +++ Source/Modules/allocate.cxx | 24 ++++++--- 5 files changed, 112 insertions(+), 8 deletions(-) diff --git a/CHANGES.current b/CHANGES.current index 408ff7279..7638b91c9 100644 --- a/CHANGES.current +++ b/CHANGES.current @@ -7,6 +7,13 @@ the issue number to the end of the URL: https://github.com/swig/swig/issues/ Version 4.2.0 (in progress) =========================== +2023-09-09: wsfulton + https://sourceforge.net/p/swig/bugs/919/ + + Fix incorrect variable setters being generated when wrapping arrays. + A setter is no longer generated if the type of the array members + are non-assignable. + 2023-09-09: wsfulton Non-assignable detection fixes when wrapping const member variables. Const member variables such as the following are non-assignable by diff --git a/Examples/test-suite/cpp11_assign_delete.i b/Examples/test-suite/cpp11_assign_delete.i index 990def296..dd2b180e7 100644 --- a/Examples/test-suite/cpp11_assign_delete.i +++ b/Examples/test-suite/cpp11_assign_delete.i @@ -25,6 +25,13 @@ struct MemberVars { AssignPrivate MemberPrivate; }; +struct MemberArrayVars { + // These will only have getters + AssignPublic ArrayMemberPublic[1]; + AssignProtected ArrayMemberProtected[1]; + AssignPrivate ArrayMemberPrivate[1]; +}; + // (2) Test indirectly non-assignable member variables via inheritance struct AssignPublicDerived : AssignPublic {}; struct AssignProtectedDerived : AssignProtected {}; @@ -120,3 +127,46 @@ struct StaticMembersMemberVarsHolder { }; StaticMembersMemberVars GlobalStaticMembersMemberVars; %} + +// (4) Test indirectly non-assignable member variables via classes that themselves have non-assignable array member variables +%inline %{ +struct MemberPublicArrayVar { + AssignPublic MemberPublic[1]; +}; + +struct MemberProtectedArrayVar { +protected: + AssignProtected MemberProtected[1]; +}; + +struct MemberPrivateArrayVar { +private: + AssignPrivate MemberPrivate[1]; +}; + +struct MembersMemberArrayVars { + // These will only have getters + MemberPublicArrayVar MemberPublic; + MemberProtectedArrayVar MemberProtected; + MemberPrivateArrayVar MemberPrivate; +}; + +struct StaticMembersMemberArrayVars { + static MemberPublicArrayVar StaticMemberPublic; + static MemberProtectedArrayVar StaticMemberProtected; + static MemberPrivateArrayVar StaticMemberPrivate; +}; +MemberPublicArrayVar StaticMembersMemberArrayVars::StaticMemberPublic; +MemberProtectedArrayVar StaticMembersMemberArrayVars::StaticMemberProtected; +MemberPrivateArrayVar StaticMembersMemberArrayVars::StaticMemberPrivate; + +MemberPublicArrayVar GlobalArrayMemberPublic; +MemberProtectedArrayVar GlobalArrayMemberProtected; +MemberPrivateArrayVar GlobalArrayMemberPrivate; + +// Setters and getters available +struct StaticMembersMemberArrayVarsHolder { + StaticMembersMemberArrayVars Member; +}; +StaticMembersMemberArrayVars GlobalStaticMembersMemberArrayVars; +%} diff --git a/Examples/test-suite/java/cpp11_assign_delete_runme.java b/Examples/test-suite/java/cpp11_assign_delete_runme.java index 896a3cb96..c15632457 100644 --- a/Examples/test-suite/java/cpp11_assign_delete_runme.java +++ b/Examples/test-suite/java/cpp11_assign_delete_runme.java @@ -14,6 +14,7 @@ public class cpp11_assign_delete_runme { public static void main(String argv[]) { MemberVars mv = new MemberVars(); + MemberArrayVars mav = new MemberArrayVars(); // (1) Test directly non-assignable member variables // These will only have getters @@ -21,6 +22,10 @@ public class cpp11_assign_delete_runme { AssignProtected a2 = mv.getMemberProtected(); AssignPrivate a3 = mv.getMemberPrivate(); + AssignPublic ma1 = mav.getArrayMemberPublic(); + AssignProtected ma2 = mav.getArrayMemberProtected(); + AssignPrivate ma3 = mav.getArrayMemberPrivate(); + // (2) Test indirectly non-assignable member variables via inheritance InheritedMemberVars imv = new InheritedMemberVars(); // These will only have getters @@ -59,6 +64,7 @@ public class cpp11_assign_delete_runme { cpp11_assign_delete.setGlobalPrivateDerivedSettable(ga9); // (3) Test indirectly non-assignable member variables via classes that themselves have non-assignable member variables + { MembersMemberVars m = new MembersMemberVars(); // These will only have getters @@ -81,5 +87,32 @@ public class cpp11_assign_delete_runme { StaticMembersMemberVars smmv = cpp11_assign_delete.getGlobalStaticMembersMemberVars(); cpp11_assign_delete.setGlobalStaticMembersMemberVars(smmv); + } + + // (4) Test indirectly non-assignable member variables via classes that themselves have non-assignable array member variables + { + MembersMemberArrayVars m = new MembersMemberArrayVars(); + + // These will only have getters + MemberPublicArrayVar mpv1 = m.getMemberPublic(); + MemberProtectedArrayVar mpv2 = m.getMemberProtected(); + MemberPrivateArrayVar mpv3 = m.getMemberPrivate(); + + MemberPublicArrayVar smpv1 = StaticMembersMemberArrayVars.getStaticMemberPublic(); + MemberProtectedArrayVar smpv2 = StaticMembersMemberArrayVars.getStaticMemberProtected(); + MemberPrivateArrayVar smpv3 = StaticMembersMemberArrayVars.getStaticMemberPrivate(); + + MemberPublicArrayVar gmpv1 = cpp11_assign_delete.getGlobalArrayMemberPublic(); + MemberProtectedArrayVar gmpv2 = cpp11_assign_delete.getGlobalArrayMemberProtected(); + MemberPrivateArrayVar gmpv3 = cpp11_assign_delete.getGlobalArrayMemberPrivate(); + + // Setters and getters available + StaticMembersMemberArrayVarsHolder smmvh = new StaticMembersMemberArrayVarsHolder(); + StaticMembersMemberArrayVars member = smmvh.getMember(); + smmvh.setMember(member); + + StaticMembersMemberArrayVars smmv = cpp11_assign_delete.getGlobalStaticMembersMemberArrayVars(); + cpp11_assign_delete.setGlobalStaticMembersMemberArrayVars(smmv); + } } } diff --git a/Examples/test-suite/private_assign.i b/Examples/test-suite/private_assign.i index ae6d7589e..bcc21439e 100644 --- a/Examples/test-suite/private_assign.i +++ b/Examples/test-suite/private_assign.i @@ -57,11 +57,17 @@ %} %inline %{ + Foo foo_global; + Foo foo_global_array[1]; + Foo foo_global_array_2d[2][2]; + struct FooBar : Foo { }; FooBar bar; + FooBar bar_array[1]; + FooBar bar_array_2d[2][2]; %} // https://sourceforge.net/p/swig/bugs/1006/ diff --git a/Source/Modules/allocate.cxx b/Source/Modules/allocate.cxx index bb20e3562..3ad29d700 100644 --- a/Source/Modules/allocate.cxx +++ b/Source/Modules/allocate.cxx @@ -667,15 +667,10 @@ class Allocate:public Dispatcher { } } - bool is_assignable(Node *n, bool &is_reference, bool &is_const) { + bool is_assignable_type(const SwigType *type) { bool assignable = true; - SwigType *ty = Copy(Getattr(n, "type")); - SwigType_push(ty, Getattr(n, "decl")); - SwigType *ftd = SwigType_typedef_resolve_all(ty); - SwigType *td = SwigType_strip_qualifiers(ftd); - - if (SwigType_type(td) == T_USER) { - Node *cn = Swig_symbol_clookup(td, 0); + if (SwigType_type(type) == T_USER) { + Node *cn = Swig_symbol_clookup(type, 0); if (cn) { if ((Strcmp(nodeType(cn), "class") == 0)) { if (Getattr(cn, "allocate:noassign")) { @@ -683,7 +678,20 @@ class Allocate:public Dispatcher { } } } + } else if (SwigType_isarray(type)) { + SwigType *array_type = SwigType_array_type(type); + assignable = is_assignable_type(array_type); } + return assignable; + } + + bool is_assignable(Node *n, bool &is_reference, bool &is_const) { + SwigType *ty = Copy(Getattr(n, "type")); + SwigType_push(ty, Getattr(n, "decl")); + SwigType *ftd = SwigType_typedef_resolve_all(ty); + SwigType *td = SwigType_strip_qualifiers(ftd); + + bool assignable = is_assignable_type(td); is_reference = SwigType_isreference(td) || SwigType_isrvalue_reference(td); is_const = !SwigType_ismutable(ftd); if (GetFlag(n, "hasconsttype"))