summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWilliam S Fulton <wsf@fultondesigns.co.uk>2013-08-28 20:24:54 +0100
committerWilliam S Fulton <wsf@fultondesigns.co.uk>2013-08-28 20:30:46 +0100
commitb58dabced9e7424e6107bfd40963806f3b831a19 (patch)
tree52f4467affe3859d0d61b9ad4214a28286e7b475
parent1cc735df5e087edc2ac189b39a1ccb12ed304a13 (diff)
downloadswig-b58dabced9e7424e6107bfd40963806f3b831a19.tar.gz
%implicitconv is improved for overloaded functions.
Like in C++, the methods with the actual types are considered before trying implicit conversions.
-rw-r--r--CHANGES.current20
-rw-r--r--Examples/test-suite/implicittest.i30
-rw-r--r--Examples/test-suite/python/implicittest_runme.py9
-rw-r--r--Source/Modules/overload.cxx63
4 files changed, 117 insertions, 5 deletions
diff --git a/CHANGES.current b/CHANGES.current
index f87f7ef70..07a57c42a 100644
--- a/CHANGES.current
+++ b/CHANGES.current
@@ -5,6 +5,26 @@ See the RELEASENOTES file for a summary of changes in each release.
Version 2.0.11 (in progress)
============================
+2013-08-28: wsfulton
+ [Python] %implicitconv is improved for overloaded functions. Like in C++, the methods
+ with the actual types are considered before trying implicit conversions. Example:
+
+ %implicitconv A;
+ struct A {
+ A(int i);
+ };
+ class CCC {
+ public:
+ int xx(int i) { return 11; }
+ int xx(const A& i) { return 22; }
+ };
+
+ The following python code:
+
+ CCC().xx(-1)
+
+ will now return 11 instead of 22 - the implicit conversion is not done.
+
2013-08-23: olly
[Python] Fix clang++ warning in generated wrapper code.
diff --git a/Examples/test-suite/implicittest.i b/Examples/test-suite/implicittest.i
index 10f901710..171c6055c 100644
--- a/Examples/test-suite/implicittest.i
+++ b/Examples/test-suite/implicittest.i
@@ -84,3 +84,33 @@
int get_AA_val(AA a) { return a.ii; }
int get_AA_ref(const AA& a) { return a.ii; }
}
+
+
+/****************** Overloading priority *********************/
+
+%inline %{
+class BBB {
+ public:
+ BBB(const B &) {}
+};
+
+class CCC {
+ public:
+ CCC(const BBB &) : checkvalue(0) {}
+ int xx(int i) { return 11; }
+ int xx(const A& i) { return 22; }
+ int yy(int i, int j) { return 111; }
+ int yy(const A& i, const A& j) { return 222; }
+ int checkvalue;
+};
+%}
+
+// CCC(const BBB &) was being called instead of this constructor (independent of being added via %extend)
+%extend CCC {
+ CCC(const B& b) {
+ CCC* ccc = new CCC(b);
+ ccc->checkvalue = 10;
+ return ccc;
+ }
+};
+
diff --git a/Examples/test-suite/python/implicittest_runme.py b/Examples/test-suite/python/implicittest_runme.py
index 5644555df..a9957bc7e 100644
--- a/Examples/test-suite/python/implicittest_runme.py
+++ b/Examples/test-suite/python/implicittest_runme.py
@@ -114,3 +114,12 @@ try:
raise RuntimeError
except TypeError:
pass
+
+
+### overloading priority test ###
+
+ccc = CCC(B())
+check(ccc.checkvalue, 10)
+check(ccc.xx(123), 11)
+check(ccc.yy(123, 123), 111)
+
diff --git a/Source/Modules/overload.cxx b/Source/Modules/overload.cxx
index 0112d2d9e..e95ef557f 100644
--- a/Source/Modules/overload.cxx
+++ b/Source/Modules/overload.cxx
@@ -26,6 +26,7 @@ struct Overloaded {
int argc; /* Argument count */
ParmList *parms; /* Parameters used for overload check */
int error; /* Ambiguity error */
+ bool implicitconv_function; /* For ordering implicitconv functions*/
};
static int fast_dispatch_mode = 0;
@@ -41,6 +42,32 @@ void Wrapper_cast_dispatch_mode_set(int flag) {
}
/* -----------------------------------------------------------------------------
+ * mark_implicitconv_function()
+ *
+ * Mark function if it contains an implicitconv type in the parameter list
+ * ----------------------------------------------------------------------------- */
+static void mark_implicitconv_function(Overloaded& onode) {
+ Parm *parms = onode.parms;
+ if (parms) {
+ bool is_implicitconv_function = false;
+ Parm *p = parms;
+ while (p) {
+ if (checkAttribute(p, "tmap:in:numinputs", "0")) {
+ p = Getattr(p, "tmap:in:next");
+ continue;
+ }
+ if (GetFlag(p, "implicitconv")) {
+ is_implicitconv_function = true;
+ break;
+ }
+ p = nextSibling(p);
+ }
+ if (is_implicitconv_function)
+ onode.implicitconv_function = true;
+ }
+}
+
+/* -----------------------------------------------------------------------------
* Swig_overload_rank()
*
* This function takes an overloaded declaration and creates a list that ranks
@@ -85,6 +112,9 @@ List *Swig_overload_rank(Node *n, bool script_lang_wrapping) {
nodes[nnodes].parms = Getattr(c, "wrap:parms");
nodes[nnodes].argc = emit_num_required(nodes[nnodes].parms);
nodes[nnodes].error = 0;
+ nodes[nnodes].implicitconv_function = false;
+
+ mark_implicitconv_function(nodes[nnodes]);
nnodes++;
}
c = Getattr(c, "sym:nextSibling");
@@ -287,12 +317,30 @@ List *Swig_overload_rank(Node *n, bool script_lang_wrapping) {
List *result = NewList();
{
int i;
+ int argc_changed_index = -1;
for (i = 0; i < nnodes; i++) {
if (nodes[i].error)
Setattr(nodes[i].n, "overload:ignore", "1");
Append(result, nodes[i].n);
- // Printf(stdout,"[ %d ] %s\n", i, ParmList_errorstr(nodes[i].parms));
- // Swig_print_node(nodes[i].n);
+ // Printf(stdout,"[ %d ] %d %s\n", i, nodes[i].implicitconv_function, ParmList_errorstr(nodes[i].parms));
+ // Swig_print_node(nodes[i].n);
+ if (i == nnodes-1 || nodes[i].argc != nodes[i+1].argc) {
+ if (argc_changed_index+2 < nnodes && (nodes[argc_changed_index+1].argc == nodes[argc_changed_index+2].argc)) {
+ // Add additional implicitconv functions in same order as already ranked.
+ // Consider overloaded functions by argument count... only add additional implicitconv functions if
+ // the number of functions with the same arg count > 1, ie, only if overloaded by same argument count.
+ int j;
+ for (j = argc_changed_index + 1; j <= i; j++) {
+ if (nodes[j].implicitconv_function) {
+ SetFlag(nodes[j].n, "implicitconvtypecheckoff");
+ Append(result, nodes[j].n);
+ // Printf(stdout,"[ %d ] %d + %s\n", j, nodes[j].implicitconv_function, ParmList_errorstr(nodes[j].parms));
+ // Swig_print_node(nodes[j].n);
+ }
+ }
+ }
+ argc_changed_index = i;
+ }
}
}
return result;
@@ -302,20 +350,22 @@ List *Swig_overload_rank(Node *n, bool script_lang_wrapping) {
// * print_typecheck()
// * ----------------------------------------------------------------------------- */
-static bool print_typecheck(String *f, int j, Parm *pj) {
+static bool print_typecheck(String *f, int j, Parm *pj, bool implicitconvtypecheckoff) {
char tmp[256];
sprintf(tmp, Char(argv_template_string), j);
String *tm = Getattr(pj, "tmap:typecheck");
if (tm) {
+ tm = Copy(tm);
Replaceid(tm, Getattr(pj, "lname"), "_v");
String *conv = Getattr(pj, "implicitconv");
- if (conv) {
+ if (conv && !implicitconvtypecheckoff) {
Replaceall(tm, "$implicitconv", conv);
} else {
Replaceall(tm, "$implicitconv", "0");
}
Replaceall(tm, "$input", tmp);
Printv(f, tm, "\n", NIL);
+ Delete(tm);
return true;
} else
return false;
@@ -715,6 +765,7 @@ String *Swig_overload_dispatch(Node *n, const_String_or_char_ptr fmt, int *maxar
for (i = 0; i < nfunc; i++) {
Node *ni = Getitem(dispatch, i);
Parm *pi = Getattr(ni, "wrap:parms");
+ bool implicitconvtypecheckoff = GetFlag(ni, "implicitconvtypecheckoff") != 0;
int num_required = emit_num_required(pi);
int num_arguments = emit_num_arguments(pi);
if (GetFlag(n, "wrap:this")) {
@@ -749,7 +800,7 @@ String *Swig_overload_dispatch(Node *n, const_String_or_char_ptr fmt, int *maxar
Printf(f, "}\n");
Delete(lfmt);
}
- if (print_typecheck(f, (GetFlag(n, "wrap:this") ? j + 1 : j), pj)) {
+ if (print_typecheck(f, (GetFlag(n, "wrap:this") ? j + 1 : j), pj, implicitconvtypecheckoff)) {
Printf(f, "if (_v) {\n");
num_braces++;
}
@@ -773,6 +824,8 @@ String *Swig_overload_dispatch(Node *n, const_String_or_char_ptr fmt, int *maxar
for ( /* empty */ ; num_braces > 0; num_braces--)
Printf(f, "}\n");
Printf(f, "}\n"); /* braces closes "if" for this method */
+ if (implicitconvtypecheckoff)
+ Delattr(ni, "implicitconvtypecheckoff");
}
Delete(dispatch);
return f;