diff options
author | William S Fulton <wsf@fultondesigns.co.uk> | 2013-08-28 20:24:54 +0100 |
---|---|---|
committer | William S Fulton <wsf@fultondesigns.co.uk> | 2013-08-28 20:30:46 +0100 |
commit | b58dabced9e7424e6107bfd40963806f3b831a19 (patch) | |
tree | 52f4467affe3859d0d61b9ad4214a28286e7b475 | |
parent | 1cc735df5e087edc2ac189b39a1ccb12ed304a13 (diff) | |
download | swig-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.current | 20 | ||||
-rw-r--r-- | Examples/test-suite/implicittest.i | 30 | ||||
-rw-r--r-- | Examples/test-suite/python/implicittest_runme.py | 9 | ||||
-rw-r--r-- | Source/Modules/overload.cxx | 63 |
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; |