Apply patch #3066958 from Mikael Johansson to fix default smart pointer handling when the smart pointer contains both a const and non-const operator->.

git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/trunk@12240 626c5289-ae23-0410-ae9c-e8d60b6d4f22
This commit is contained in:
William S Fulton 2010-10-03 13:12:00 +00:00
commit 3219746776
9 changed files with 343 additions and 12 deletions

View file

@ -5,6 +5,10 @@ See the RELEASENOTES file for a summary of changes in each release.
Version 2.0.1 (in progress)
===========================
2010-10-03: wsfulton
Apply patch #3066958 from Mikael Johansson to fix default smart pointer
handling when the smart pointer contains both a const and non-const operator->.
2010-10-01: wsfulton
Add -pcreversion option to display PCRE version information.

View file

@ -294,6 +294,7 @@ CPP_TEST_CASES += \
sizet \
smart_pointer_const \
smart_pointer_const2 \
smart_pointer_const_overload \
smart_pointer_extend \
smart_pointer_member \
smart_pointer_multi \

View file

@ -0,0 +1,99 @@
import smart_pointer_const_overload.*;
public class smart_pointer_const_overload_runme {
static int CONST_ACCESS = 1;
static int MUTABLE_ACCESS = 2;
static {
System.loadLibrary("smart_pointer_const_overload");
}
public static void test(Bar b, Foo f) {
Assert(f.getX() == 0);
// Test member variable get
Assert(b.getX() == 0);
Assert(f.getAccess() == CONST_ACCESS);
// Test member variable set
b.setX(1);
Assert(f.getX() == 1);
Assert(f.getAccess() == MUTABLE_ACCESS);
// Test const method
Assert(b.getx() == 1);
Assert(f.getAccess() == CONST_ACCESS);
// Test mutable method
b.setx(2);
Assert(f.getX() == 2);
Assert(f.getAccess() == MUTABLE_ACCESS);
// Test extended const method
Assert(b.getx2() == 2);
Assert(f.getAccess() == CONST_ACCESS);
// Test extended mutable method
b.setx2(3);
Assert(f.getX() == 3);
Assert(f.getAccess() == MUTABLE_ACCESS);
// Test static method
b.stat();
Assert(f.getAccess() == CONST_ACCESS);
// Test const member
f.setAccess(MUTABLE_ACCESS);
Assert(b.getY() == 0);
Assert(f.getAccess() == CONST_ACCESS);
// Test get through mutable pointer to const member
f.setAccess(MUTABLE_ACCESS);
Assert(smart_pointer_const_overload.get_int(b.getYp()) == 0);
Assert(f.getAccess() == CONST_ACCESS);
// Test get through const pointer to mutable member
f.setX(4);
f.setAccess(MUTABLE_ACCESS);
Assert(smart_pointer_const_overload.get_int(b.getXp()) == 4);
Assert(f.getAccess() == CONST_ACCESS);
// Test set through const pointer to mutable member
f.setAccess(MUTABLE_ACCESS);
smart_pointer_const_overload.set_int(b.getXp(), 5);
Assert(f.getX() == 5);
Assert(f.getAccess() == CONST_ACCESS);
// Test set pointer to const member
b.setYp(smart_pointer_const_overload.new_int(6));
Assert(f.getY() == 0);
Assert(smart_pointer_const_overload.get_int(f.getYp()) == 6);
Assert(f.getAccess() == MUTABLE_ACCESS);
smart_pointer_const_overload.delete_int(f.getYp());
}
public static void main(String argv[]) {
Foo f = new Foo();
Bar b = new Bar(f);
//Foo f2 = new Foo();
//Bar b2 = new Bar2(f2);
test(b, f);
//test(b2, f2);
}
public static void Assert(boolean b) {
if (!b)
throw new RuntimeException("Assertion failed");
}
}

View file

@ -0,0 +1,123 @@
from smart_pointer_const_overload import *
CONST_ACCESS = 1
MUTABLE_ACCESS = 2
def test(b, f):
if f.x != 0:
raise RuntimeError
# Test member variable get
if b.x != 0:
raise RuntimeError
if f.access != CONST_ACCESS:
raise RuntimeError
# Test member variable set
b.x = 1
if f.x != 1:
raise RuntimeError
if f.access != MUTABLE_ACCESS:
raise RuntimeError
# Test const method
if b.getx() != 1:
raise RuntimeError
if f.access != CONST_ACCESS:
raise RuntimeError
# Test mutable method
b.setx(2)
if f.x != 2:
raise RuntimeError
if f.access != MUTABLE_ACCESS:
raise RuntimeError
# Test extended const method
if b.getx2() != 2:
raise RuntimeError
if f.access != CONST_ACCESS:
raise RuntimeError
# Test extended mutable method
b.setx2(3)
if f.x != 3:
raise RuntimeError
if f.access != MUTABLE_ACCESS:
raise RuntimeError
# Test static method
b.stat()
if f.access != CONST_ACCESS:
raise RuntimeError
# Test const member
f.access = MUTABLE_ACCESS
if b.y != 0:
raise RuntimeError
if f.access != CONST_ACCESS:
raise RuntimeError
# Test get through mutable pointer to const member
f.access = MUTABLE_ACCESS
if get_int(b.yp) != 0:
raise RuntimeError
if f.access != CONST_ACCESS:
raise RuntimeError
# Test get through const pointer to mutable member
f.x = 4
f.access = MUTABLE_ACCESS
if get_int(b.xp) != 4:
raise RuntimeError
if f.access != CONST_ACCESS:
raise RuntimeError
# Test set through const pointer to mutable member
f.access = MUTABLE_ACCESS
set_int(b.xp, 5)
if f.x != 5:
raise RuntimeError
if f.access != CONST_ACCESS:
raise RuntimeError
# Test set pointer to const member
b.yp = new_int(6)
if f.y != 0:
raise RuntimeError
if get_int(f.yp) != 6:
raise RuntimeError
if f.access != MUTABLE_ACCESS:
raise RuntimeError
delete_int(f.yp);
f = Foo()
b = Bar(f)
f2 = Foo()
b2 = Bar2(f2)
test(b, f)
test(b2, f2)

View file

@ -0,0 +1,74 @@
%module smart_pointer_const_overload
%warnfilter(SWIGWARN_LANG_OVERLOAD_IGNORED) Bar::operator->; // Overloaded method Bar::operator ->() ignored
%warnfilter(SWIGWARN_LANG_OVERLOAD_IGNORED) Bar2::operator->; // Overloaded method Bar2::operator ->() ignored
%inline %{
int CONST_ACCESS = 1;
int MUTABLE_ACCESS = 2;
int *new_int(int ivalue) {
int *i = (int *) malloc(sizeof(ivalue));
*i = ivalue;
return i;
}
int get_int(int *i) {
return *i;
}
void set_int(int *i, int ivalue) {
*i = ivalue;
}
void delete_int(int *i) {
free(i);
}
struct Foo {
int x;
int * const xp;
const int y;
const int *yp;
int access;
Foo() : x(0), xp(&x), y(0), yp(&y), access(0) { }
int getx() const { return x; }
void setx(int x_) { x = x_; }
static void stat() {}
};
%}
%extend Foo {
int getx2() const { return self->x; }
void setx2(int x_) { self->x = x_; }
};
%inline %{
class Bar {
Foo *f;
public:
Bar(Foo *f) : f(f) { }
const Foo *operator->() const {
f->access = CONST_ACCESS;
return f;
}
Foo *operator->() {
f->access = MUTABLE_ACCESS;
return f;
}
};
class Bar2 {
Foo *f;
public:
Bar2(Foo *f) : f(f) { }
Foo *operator->() {
f->access = MUTABLE_ACCESS;
return f;
}
const Foo *operator->() const {
f->access = CONST_ACCESS;
return f;
}
};
%}

View file

@ -824,9 +824,12 @@ Allocate():
int isconst = 0;
Delete(SwigType_pop(type));
if (SwigType_isconst(type)) {
isconst = 1;
isconst = !Getattr(inclass, "allocate:smartpointermutable");
Setattr(inclass, "allocate:smartpointerconst", "1");
}
else {
Setattr(inclass, "allocate:smartpointermutable", "1");
}
List *methods = smart_pointer_methods(sc, 0, isconst);
Setattr(inclass, "allocate:smartpointer", methods);
Setattr(inclass, "allocate:smartpointerbase", base);
@ -834,7 +837,6 @@ Allocate():
/* Hmmm. The return value is not a pointer. If the type is a value
or reference. We're going to chase it to see if another operator->()
can be found */
if ((SwigType_check_decl(type, "")) || (SwigType_check_decl(type, "r."))) {
Node *nn = Swig_symbol_clookup((char *) "operator ->", Getattr(sc, "symtab"));
if (nn) {

View file

@ -1344,7 +1344,7 @@ int Language::variableHandler(Node *n) {
Swig_save("variableHandler", n, "feature:immutable", NIL);
if (SmartPointer) {
/* If a smart-pointer and it's a constant access, we have to set immutable */
if (Getattr(CurrentClass, "allocate:smartpointerconst")) {
if (!Getattr(CurrentClass, "allocate:smartpointermutable")) {
SetFlag(n, "feature:immutable");
}
}
@ -1391,7 +1391,7 @@ int Language::membervariableHandler(Node *n) {
int assignable = is_assignable(n);
if (SmartPointer) {
if (Getattr(CurrentClass, "allocate:smartpointerconst")) {
if (!Getattr(CurrentClass, "allocate:smartpointermutable")) {
assignable = 0;
}
}
@ -2443,6 +2443,9 @@ int Language::classHandler(Node *n) {
List *methods = Getattr(n, "allocate:smartpointer");
cplus_mode = PUBLIC;
SmartPointer = CWRAP_SMART_POINTER;
if (Getattr(n, "allocate:smartpointerconst") && Getattr(n, "allocate:smartpointermutable")) {
SmartPointer |= CWRAP_SMART_POINTER_OVERLOAD;
}
Iterator c;
for (c = First(methods); c.item; c = Next(c)) {
emit_one(c.item);

View file

@ -783,15 +783,32 @@ int Swig_add_extension_code(Node *n, const String *function_name, ParmList *parm
* ----------------------------------------------------------------------------- */
int Swig_MethodToFunction(Node *n, const_String_or_char_ptr nspace, String *classname, int flags, SwigType *director_type, int is_director) {
String *name, *qualifier;
String *name;
ParmList *parms;
SwigType *type;
Parm *p;
String *self = 0;
/* If smart pointer, change self dereferencing */
int is_smart_pointer_overload = 0;
String *qualifier = Getattr(n, "qualifier");
/* If smart pointer without const overload or mutable method, change self dereferencing */
if (flags & CWRAP_SMART_POINTER) {
self = NewString("(*this)->");
if (flags & CWRAP_SMART_POINTER_OVERLOAD) {
String *cname = Getattr(n, "classname") ? Getattr(n, "classname") : classname;
if (qualifier && strncmp(Char(qualifier), "q(const)", 8) == 0) {
self = NewString("(*(this))->");
is_smart_pointer_overload = 1;
}
else if (Cmp(Getattr(n, "storage"), "static") == 0) {
self = NewStringf("(*(%s const *)this)->", cname);
is_smart_pointer_overload = 1;
}
else {
self = NewString("(*this)->");
}
} else {
self = NewString("(*this)->");
}
}
/* If node is a member template expansion, we don't allow added code */
@ -799,7 +816,6 @@ int Swig_MethodToFunction(Node *n, const_String_or_char_ptr nspace, String *clas
flags &= ~(CWRAP_EXTEND);
name = Getattr(n, "name");
qualifier = Getattr(n, "qualifier");
parms = CopyParmList(nonvoid_parms(Getattr(n, "parms")));
type = NewString(classname);
@ -921,10 +937,16 @@ int Swig_MethodToFunction(Node *n, const_String_or_char_ptr nspace, String *clas
if (Cmp(Getattr(n, "storage"), "static") != 0) {
String *pname = Swig_cparm_name(pp, i);
String *ctname = SwigType_namestr(cname);
String *fadd = NewStringf("(%s*)(%s)->operator ->()", ctname, pname);
String *ctname = SwigType_namestr(cname);
String *fadd = 0;
if (is_smart_pointer_overload) {
fadd = NewStringf("(%s const *)((%s const *)%s)->operator ->()", ctname, classname, pname);
}
else {
fadd = NewStringf("(%s*)(%s)->operator ->()", ctname, pname);
}
Append(func, fadd);
Delete(ctname);
Delete(ctname);
Delete(fadd);
Delete(pname);
pp = nextSibling(pp);
@ -1310,6 +1332,8 @@ int Swig_MembergetToFunction(Node *n, String *classname, int flags) {
Node *sn = Getattr(n, "cplus:staticbase");
String *base = Getattr(sn, "name");
self = NewStringf("%s::", base);
} else if (flags & CWRAP_SMART_POINTER_OVERLOAD) {
self = NewStringf("(*(%s const *)this)->", classname);
} else {
self = NewString("(*this)->");
}

View file

@ -370,6 +370,7 @@ extern int ParmList_is_compactdefargs(ParmList *p);
#define CWRAP_DIRECTOR_ONE_CALL 0x08
#define CWRAP_DIRECTOR_TWO_CALLS 0x10
#define CWRAP_ALL_PROTECTED_ACCESS 0x20
#define CWRAP_SMART_POINTER_OVERLOAD 0x40
/* --- Director Helpers --- */
extern Node *Swig_methodclass(Node *n);