Fix %copyctor used on class hierarchies with non-const copy constructor

Previously SWIG always attempted to call a copy constructor
taking a const reference parameter instead of a non-const
reference parameter.
This commit is contained in:
William S Fulton 2023-07-29 18:16:40 +01:00
parent b87c9fb4d7
commit 74e1deef6b
6 changed files with 143 additions and 1 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-07-29: wsfulton
https://sourceforge.net/p/swig/bugs/678/
Fix %copyctor used on class hierarchies with non-const copy
constructors. Previously SWIG always attempted to call a copy
constructor taking a const reference parameter instead of a
non-const reference parameter.
2023-07-28: wsfulton
[#2541] Fix overloading of templated constructors and %copyctor.

View File

@ -150,6 +150,7 @@ CPP_TEST_CASES += \
constant_pointers \
constover \
constructor_copy \
constructor_copy_non_const \
constructor_exception \
constructor_explicit \
constructor_ignore \

View File

@ -0,0 +1,71 @@
%module(ruby_minherit="1") constructor_copy_non_const
// Tests %copyctor and non-const copy constructors in inheritance chain
%warnfilter(SWIGWARN_JAVA_MULTIPLE_INHERITANCE,
SWIGWARN_CSHARP_MULTIPLE_INHERITANCE,
SWIGWARN_D_MULTIPLE_INHERITANCE,
SWIGWARN_PHP_MULTIPLE_INHERITANCE) CCDerived; /* C#, D, Java, PHP multiple inheritance */
%warnfilter(SWIGWARN_JAVA_MULTIPLE_INHERITANCE,
SWIGWARN_CSHARP_MULTIPLE_INHERITANCE,
SWIGWARN_D_MULTIPLE_INHERITANCE,
SWIGWARN_PHP_MULTIPLE_INHERITANCE) CCProtectedDerived; /* C#, D, Java, PHP multiple inheritance */
%inline %{
struct CCBase1 {
CCBase1() {}
};
%}
%copyctor;
%inline %{
struct CCBase2 {
CCBase2() {}
CCBase2(CCBase2& other) {} // non-const copyctor
};
struct CCDerived : CCBase1, CCBase2 {
CCDerived() {}
// implicitly declared non-const copyctor
};
struct CCMoreDerived : CCDerived {
// implicitly declared default ctor
// implicitly declared non-const copyctor
};
struct CCMoreDerived2 : CCDerived {
CCMoreDerived2() {}
CCMoreDerived2(const CCMoreDerived2& other) {} // const copyctor
};
struct CCMoreMoreDerived2 : CCMoreDerived2 {
// implicitly declared default ctor
// implicitly declared const copyctor
};
%}
// Repeat but with protected non-const copyctor
%inline %{
struct CCProtectedBase2 {
CCProtectedBase2() {}
protected:
CCProtectedBase2(CCProtectedBase2& other) {} // non-const copyctor
};
struct CCProtectedDerived : CCBase1, CCProtectedBase2 {
CCProtectedDerived() {}
// implicitly declared non-const copyctor
};
struct CCProtectedMoreDerived : CCProtectedDerived {
// implicitly declared default ctor
// implicitly declared non-const copyctor
};
struct CCProtectedMoreDerived2 : CCProtectedDerived {
CCProtectedMoreDerived2() {}
CCProtectedMoreDerived2(const CCProtectedMoreDerived2& other) {} // const copyctor
};
struct CCProtectedMoreMoreDerived2 : CCProtectedMoreDerived2 {
// implicitly declared default ctor
// implicitly declared const copyctor
};
%}

View File

@ -0,0 +1,30 @@
import constructor_copy_non_const.*;
public class constructor_copy_non_const_runme {
static {
try {
System.loadLibrary("constructor_copy_non_const");
} 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[]) {
{
CCBase2 ccb2 = new CCBase2(new CCBase2());
CCDerived ccd = new CCDerived(new CCDerived());
CCMoreDerived ccmd = new CCMoreDerived(new CCMoreDerived());
CCMoreDerived2 ccmd2 = new CCMoreDerived2(new CCMoreDerived2());
CCMoreMoreDerived2 ccmmd2 = new CCMoreMoreDerived2(new CCMoreMoreDerived2());
}
{
// no copy ctor CCProtectedBase2
CCProtectedDerived ccd = new CCProtectedDerived(new CCProtectedDerived());
CCProtectedMoreDerived ccmd = new CCProtectedMoreDerived(new CCProtectedMoreDerived());
CCProtectedMoreDerived2 ccmd2 = new CCProtectedMoreDerived2(new CCProtectedMoreDerived2());
CCProtectedMoreMoreDerived2 ccmmd2 = new CCProtectedMoreMoreDerived2(new CCProtectedMoreMoreDerived2());
}
}
}

View File

@ -0,0 +1,13 @@
from constructor_copy_non_const import *
ccb2 = CCBase2(CCBase2())
ccd = CCDerived(CCDerived())
ccmd = CCMoreDerived(CCMoreDerived())
ccmd2 = CCMoreDerived2(CCMoreDerived2())
ccmmd2 = CCMoreMoreDerived2(CCMoreMoreDerived2())
# no copy ctor CCProtectedBase2
ccd = CCProtectedDerived(CCProtectedDerived())
ccmd = CCProtectedMoreDerived(CCProtectedMoreDerived())
ccmd2 = CCProtectedMoreDerived2(CCProtectedMoreDerived2())
ccmmd2 = CCProtectedMoreMoreDerived2(CCProtectedMoreMoreDerived2())

View File

@ -651,11 +651,13 @@ Allocate():
if (!Getattr(n, "allocate:has_copy_constructor")) {
if (Getattr(n, "abstracts")) {
Delattr(n, "allocate:copy_constructor");
Delattr(n, "allocate:copy_constructor_non_const");
}
if (!Getattr(n, "allocate:copy_constructor")) {
/* Check base classes */
List *bases = Getattr(n, "allbases");
int allows_copy = 1;
int must_be_copy_non_const = 0;
for (int i = 0; i < Len(bases); i++) {
Node *n = Getitem(bases, i);
@ -663,10 +665,16 @@ Allocate():
if (!Getattr(n, "allocate:copy_constructor") && (!Getattr(n, "allocate:copy_base_constructor"))) {
allows_copy = 0;
}
if (Getattr(n, "allocate:copy_constructor_non_const") || (Getattr(n, "allocate:copy_base_constructor_non_const"))) {
must_be_copy_non_const = 1;
}
}
if (allows_copy) {
Setattr(n, "allocate:copy_constructor", "1");
}
if (must_be_copy_non_const) {
Setattr(n, "allocate:copy_constructor_non_const", "1");
}
}
}
@ -1164,6 +1172,7 @@ Allocate():
if (parms && (ParmList_numrequired(parms) == 1)) {
/* Look for a few cases. X(const X &), X(X &), X(X *) */
int copy_constructor = 0;
int copy_constructor_non_const = 0;
SwigType *type = Getattr(inclass, "name");
String *tn = NewStringf("r.q(const).%s", type);
String *cc = SwigType_typedef_resolve_all(tn);
@ -1183,6 +1192,7 @@ Allocate():
cc = NewStringf("r.%s", Getattr(inclass, "name"));
if (Strcmp(cc, Getattr(parms, "type")) == 0) {
copy_constructor = 1;
copy_constructor_non_const = 1;
} else {
Delete(cc);
cc = NewStringf("p.%s", Getattr(inclass, "name"));
@ -1205,6 +1215,15 @@ Allocate():
} else if (access_mode == PROTECTED) {
Setattr(inclass, "allocate:copy_base_constructor", "1");
}
if (copy_constructor_non_const) {
Setattr(n, "copy_constructor_non_const", "1");
Setattr(inclass, "allocate:has_copy_constructor_non_const", "1");
if (access_mode == PUBLIC) {
Setattr(inclass, "allocate:copy_constructor_non_const", "1");
} else if (access_mode == PROTECTED) {
Setattr(inclass, "allocate:copy_base_constructor_non_const", "1");
}
}
}
}
return SWIG_OK;
@ -1237,11 +1256,12 @@ static void addCopyConstructor(Node *n) {
Setfile(cn, Getfile(n));
Setline(cn, Getline(n));
int copy_constructor_non_const = GetFlag(n, "allocate:copy_constructor_non_const");
String *cname = Getattr(n, "name");
SwigType *type = Copy(cname);
String *lastname = Swig_scopename_last(cname);
String *name = SwigType_templateprefix(lastname);
String *cc = NewStringf("r.q(const).%s", type);
String *cc = NewStringf(copy_constructor_non_const ? "r.%s" : "r.q(const).%s", type);
String *decl = NewStringf("f(%s).", cc);
String *oldname = Getattr(n, "sym:name");