Variable setters for non-assignable types

Fix incorrect variable setters being generated when the type of the
variable is not assignable, due to variable type inheriting a private
assignment operator further up the inheritance chain (further up than
the immediate base).
This commit is contained in:
William S Fulton 2023-09-04 07:18:47 +01:00
parent abd299c6f4
commit f11bffcb19
5 changed files with 55 additions and 6 deletions

View File

@ -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-03: wsfulton
https://sourceforge.net/p/swig/bugs/1006/
Fix incorrect variable setters being generated when the type of the
variable is not assignable, due to variable type inheriting a private
assignment operator further up the inheritance chain (further up than
the immediate base).
2023-09-03: wsfulton
[Guile, Ocaml, Perl] Don't attempt to generate a setter when wrapping
variables which have a private assignment operator as assignment is not

View File

@ -0,0 +1,20 @@
import private_assign.*;
public class private_assign_runme {
static {
try {
System.loadLibrary("private_assign");
} catch (UnsatisfiedLinkError e) {
System.err.println("Native code library failed to load. See the chapter on Dynamic Linking Problems in the SWIG Java documentation for help.\n" + e);
System.exit(1);
}
}
public static void main(String argv[]) {
Three three = new Three();
TwoNotAssignableCopyable tn = three.getTwoNot();
TwoIsAssignableCopyable ti = three.getTwoIs();
three.setTwoIs(new TwoIsAssignableCopyable());
}
}

View File

@ -63,3 +63,26 @@
FooBar bar;
%}
// https://sourceforge.net/p/swig/bugs/1006/
%rename(Assign) TwoIsAssignableCopyable::operator=;
%inline %{
struct nocopy {
nocopy() {}
private:
nocopy(const nocopy&);
nocopy& operator=(const nocopy&);
};
struct One: public nocopy {};
struct TwoNotAssignableCopyable: public One {};
struct TwoIsAssignableCopyable: public One {
TwoIsAssignableCopyable() {}
TwoIsAssignableCopyable(const TwoIsAssignableCopyable&) {}
TwoIsAssignableCopyable& operator=(const TwoIsAssignableCopyable&) { return *this; }
};
struct Three {
TwoNotAssignableCopyable TwoNot; // getter only should be generated
TwoIsAssignableCopyable TwoIs; // setter and getter should be generated
};
%}

View File

@ -855,8 +855,8 @@ Allocate():
for (int i = 0; i < Len(bases); i++) {
Node *n = Getitem(bases, i);
/* If base class does not allow assignment, we don't allow it either */
if (Getattr(n, "allocate:has_assign")) {
allows_assign = !Getattr(n, "allocate:noassign");
if (Getattr(n, "allocate:noassign")) {
allows_assign = 0;
}
}
if (!allows_assign) {

View File

@ -3738,6 +3738,7 @@ void Language::setOverloadResolutionTemplates(String *argc, String *argv) {
int Language::is_assignable(Node *n) {
if (GetFlag(n, "feature:immutable"))
return 0;
int assignable = 1;
SwigType *type = Getattr(n, "type");
Node *cn = 0;
SwigType *ftd = SwigType_typedef_resolve_all(type);
@ -3748,16 +3749,14 @@ int Language::is_assignable(Node *n) {
if ((Strcmp(nodeType(cn), "class") == 0)) {
if (Getattr(cn, "allocate:noassign")) {
SetFlag(n, "feature:immutable");
Delete(ftd);
Delete(td);
return 0;
assignable = 0;
}
}
}
}
Delete(ftd);
Delete(td);
return 1;
return assignable;
}
String *Language::runtimeCode() {