diff --git a/CHANGES.current b/CHANGES.current index 3de7275ec..23455b289 100644 --- a/CHANGES.current +++ b/CHANGES.current @@ -7,6 +7,10 @@ the issue number to the end of the URL: https://github.com/swig/swig/issues/ Version 4.0.0 (in progress) =========================== +2019-02-25: wsfulton + [Python] Fix compile errors wrapping overloaded functions/constructors where a vararg + function is declared after a non-vararg function. + 2019-02-23: zphensley42 Use fully qualified name 'java.lang.Object' instead of 'Object' in generated code to avoid clashes with wrapped C++ classes called 'Object'. diff --git a/Examples/test-suite/go/varargs_overload_runme.go b/Examples/test-suite/go/varargs_overload_runme.go index 52fc1b0e9..5978be005 100644 --- a/Examples/test-suite/go/varargs_overload_runme.go +++ b/Examples/test-suite/go/varargs_overload_runme.go @@ -35,4 +35,40 @@ func main() { if varargs_overload.Vararg_over4("Hello", 123) != "Hello" { panic(8) } + + + // Same as above but non-vararg function declared first + + if varargs_overload.Vararg_over6("Hello") != "Hello" { + panic(0) + } + if varargs_overload.Vararg_over6(2) != "2" { + panic(1) + } + + if varargs_overload.Vararg_over7("Hello") != "Hello" { + panic(2) + } + if varargs_overload.Vararg_over7(2, 2.2) != "2 2.2" { + panic(3) + } + + if varargs_overload.Vararg_over8("Hello") != "Hello" { + panic(4) + } + if varargs_overload.Vararg_over8(2, 2.2, "hey") != "2 2.2 hey" { + panic(5) + } + + if varargs_overload.Vararg_over9("Hello") != "Hello" { + panic(6) + } + + if varargs_overload.Vararg_over9(123) != "123" { + panic(7) + } + + if varargs_overload.Vararg_over9("Hello", 123) != "Hello" { + panic(8) + } } diff --git a/Examples/test-suite/ocaml/varargs_overload_runme.ml b/Examples/test-suite/ocaml/varargs_overload_runme.ml index 3085e6258..418f881e3 100644 --- a/Examples/test-suite/ocaml/varargs_overload_runme.ml +++ b/Examples/test-suite/ocaml/varargs_overload_runme.ml @@ -11,5 +11,19 @@ let _ = assert (_vararg_over3 '(2, 2.2, "hey") as string = "2 2.2 hey"); assert (_vararg_over4 '("Hello") as string = "Hello"); assert (_vararg_over4 '(123) as string = "123"); - assert (_vararg_over4 '("Hello", 123) as string = "Hello") + assert (_vararg_over4 '("Hello", 123) as string = "Hello"); + + + (* Same as above but non-vararg function declared first *) + + assert (_vararg_over6 '("Hello") as string = "Hello"); + assert (_vararg_over6 '(2) as string = "2"); + assert (_vararg_over7 '("Hello") as string = "Hello"); + assert (_vararg_over7 '(2, 2.2) as string = "2 2.2"); + + assert (_vararg_over8 '("Hello") as string = "Hello"); + assert (_vararg_over8 '(2, 2.2, "hey") as string = "2 2.2 hey"); + assert (_vararg_over9 '("Hello") as string = "Hello"); + assert (_vararg_over9 '(123) as string = "123"); + assert (_vararg_over9 '("Hello", 123) as string = "Hello"); ;; diff --git a/Examples/test-suite/python/varargs_overload_runme.py b/Examples/test-suite/python/varargs_overload_runme.py index 37958620c..6f5a70222 100644 --- a/Examples/test-suite/python/varargs_overload_runme.py +++ b/Examples/test-suite/python/varargs_overload_runme.py @@ -28,3 +28,35 @@ if varargs_overload.vararg_over4(123) != "123": if varargs_overload.vararg_over4("Hello", 123) != "Hello": raise RuntimeError, "Failed" + + +# Same as above but non-vararg function declared first + +if varargs_overload.vararg_over6("Hello") != "Hello": + raise RuntimeError, "Failed" + +if varargs_overload.vararg_over6(2) != "2": + raise RuntimeError, "Failed" + + +if varargs_overload.vararg_over7("Hello") != "Hello": + raise RuntimeError, "Failed" + +if varargs_overload.vararg_over7(2, 2.2) != "2 2.2": + raise RuntimeError, "Failed" + + +if varargs_overload.vararg_over8("Hello") != "Hello": + raise RuntimeError, "Failed" + +if varargs_overload.vararg_over8(2, 2.2, "hey") != "2 2.2 hey": + raise RuntimeError, "Failed" + +if varargs_overload.vararg_over9("Hello") != "Hello": + raise RuntimeError, "Failed" + +if varargs_overload.vararg_over9(123) != "123": + raise RuntimeError, "Failed" + +if varargs_overload.vararg_over9("Hello", 123) != "Hello": + raise RuntimeError, "Failed" diff --git a/Examples/test-suite/scilab/varargs_overload_runme.sci b/Examples/test-suite/scilab/varargs_overload_runme.sci index 7603b667c..7426e8165 100644 --- a/Examples/test-suite/scilab/varargs_overload_runme.sci +++ b/Examples/test-suite/scilab/varargs_overload_runme.sci @@ -4,7 +4,7 @@ checkequal(vararg_over1("Hello"), "Hello", "vararg_over1(""Hello"")"); checkequal(vararg_over1(2), "2", "vararg_over1(2)"); -checkequal(vararg_over2("Hello"), "Hello", "vararg_over1(""Hello"")"); +checkequal(vararg_over2("Hello"), "Hello", "vararg_over2(""Hello"")"); checkequal(vararg_over2(2, 2.2), "2 2.2", "vararg_over2(2, 2.2)") @@ -18,4 +18,24 @@ checkequal(vararg_over4(123), "123", "vararg_over4(123)"); checkequal(vararg_over4("Hello", 123), "Hello", "vararg_over4(""Hello"", 123)"); + +// Same as above but non-vararg function declared first + +checkequal(vararg_over6("Hello"), "Hello", "vararg_over6(""Hello"")"); + +checkequal(vararg_over6(2), "2", "vararg_over6(2)"); + +checkequal(vararg_over7("Hello"), "Hello", "vararg_over7(""Hello"")"); + +checkequal(vararg_over7(2, 2.2), "2 2.2", "vararg_over7(2, 2.2)") + +checkequal(vararg_over8("Hello"), "Hello", "vararg_over8(""Hello"")"); + +checkequal(vararg_over8(2, 2.2, "hey"), "2 2.2 hey", "vararg_over8(2, 2.2, ""hey"")"); + +checkequal(vararg_over9("Hello"), "Hello", "vararg_over9(""Hello"")"); + +checkequal(vararg_over9(123), "123", "vararg_over9(123)"); + +checkequal(vararg_over9("Hello", 123), "Hello", "vararg_over9(""Hello"", 123)"); exec("swigtest.quit", -1); diff --git a/Examples/test-suite/varargs_overload.i b/Examples/test-suite/varargs_overload.i index 9a24e15a8..eb9dcaab9 100644 --- a/Examples/test-suite/varargs_overload.i +++ b/Examples/test-suite/varargs_overload.i @@ -44,3 +44,47 @@ const char *vararg_over4(int i) { return buffer; } %} + + +// Same as above but non-vararg function declared first + +%inline %{ +const char *vararg_over6(int i) { + static char buffer[256]; + sprintf(buffer, "%d", i); + return buffer; +} +const char *vararg_over6(const char *fmt, ...) { + return fmt; +} + +const char *vararg_over7(int i, double j) { + static char buffer[256]; + sprintf(buffer, "%d %g", i, j); + return buffer; +} +const char *vararg_over7(const char *fmt, ...) { + return fmt; +} + +const char *vararg_over8(int i, double j, const char *s) { + static char buffer[256]; + sprintf(buffer, "%d %g %s", i, j, s); + return buffer; +} +const char *vararg_over8(const char *fmt, ...) { + return fmt; +} +%} + +%varargs(int mode = 0) vararg_over9; +%inline %{ +const char *vararg_over9(int i) { + static char buffer[256]; + sprintf(buffer, "%d", i); + return buffer; +} +const char *vararg_over9(const char *fmt, ...) { + return fmt; +} +%} diff --git a/Source/Modules/emit.cxx b/Source/Modules/emit.cxx index 43f87db6f..7a4c2dcfb 100644 --- a/Source/Modules/emit.cxx +++ b/Source/Modules/emit.cxx @@ -188,7 +188,9 @@ void emit_attach_parmmaps(ParmList *l, Wrapper *f) { p = lp; while (p) { if (SwigType_isvarargs(Getattr(p, "type"))) { + // Mark the head of the ParmList that it has varargs Setattr(l, "emit:varargs", lp); +//Printf(stdout, "setting emit:varargs %s ... %s +++ %s\n", Getattr(l, "emit:varargs"), Getattr(l, "type"), Getattr(p, "type")); break; } p = nextSibling(p); @@ -329,7 +331,8 @@ int emit_num_required(ParmList *parms) { /* ----------------------------------------------------------------------------- * emit_isvarargs() * - * Checks if a function is a varargs function + * Checks if a ParmList is a parameter list containing varargs. + * This function requires emit_attach_parmmaps to have been called beforehand. * ----------------------------------------------------------------------------- */ int emit_isvarargs(ParmList *p) { @@ -340,6 +343,28 @@ int emit_isvarargs(ParmList *p) { return 0; } +/* ----------------------------------------------------------------------------- + * emit_isvarargs_function() + * + * Checks for varargs in a function/constructor (can be overloaded) + * ----------------------------------------------------------------------------- */ + +bool emit_isvarargs_function(Node *n) { + bool has_varargs = false; + Node *over = Getattr(n, "sym:overloaded"); + if (over) { + for (Node *sibling = over; sibling; sibling = Getattr(sibling, "sym:nextSibling")) { + if (ParmList_has_varargs(Getattr(sibling, "parms"))) { + has_varargs = true; + break; + } + } + } else { + has_varargs = ParmList_has_varargs(Getattr(n, "parms")) ? true : false; + } + return has_varargs; +} + /* ----------------------------------------------------------------------------- * void emit_mark_vararg_parms() * diff --git a/Source/Modules/python.cxx b/Source/Modules/python.cxx index 3c1767d6f..9ffc00592 100755 --- a/Source/Modules/python.cxx +++ b/Source/Modules/python.cxx @@ -2187,7 +2187,7 @@ public: * is_real_overloaded() * * Check if the function is overloaded, but not just have some - * siblings generated due to the original function have + * siblings generated due to the original function having * default arguments. * ------------------------------------------------------------ */ bool is_real_overloaded(Node *n) { @@ -2689,7 +2689,6 @@ public: bool add_self = builtin_self && (!builtin_ctor || director_class); bool builtin_getter = (builtin && GetFlag(n, "memberget")); bool builtin_setter = (builtin && GetFlag(n, "memberset") && !builtin_getter); - bool over_varargs = false; char const *self_param = builtin ? "self" : "SWIGUNUSEDPARM(self)"; char const *wrap_return = builtin_ctor ? "int " : "PyObject *"; String *linkage = NewString("SWIGINTERN "); @@ -2765,22 +2764,7 @@ public: } } - if (overname) { - String *over_varargs_attr = Getattr(n, "python:overvarargs"); - if (!over_varargs_attr) { - for (Node *sibling = n; sibling; sibling = Getattr(sibling, "sym:nextSibling")) { - if (emit_isvarargs(Getattr(sibling, "parms"))) { - over_varargs = true; - break; - } - } - over_varargs_attr = NewString(over_varargs ? "1" : "0"); - for (Node *sibling = n; sibling; sibling = Getattr(sibling, "sym:nextSibling")) - Setattr(sibling, "python:overvarargs", over_varargs_attr); - } - if (Strcmp(over_varargs_attr, "0") != 0) - over_varargs = true; - } + bool over_varargs = emit_isvarargs_function(n); int funpack = fastunpack && !varargs && !over_varargs && !allow_kwargs; int noargs = funpack && (tuple_required == 0 && tuple_arguments == 0); diff --git a/Source/Modules/swigmod.h b/Source/Modules/swigmod.h index ef49c5684..583cb13fe 100644 --- a/Source/Modules/swigmod.h +++ b/Source/Modules/swigmod.h @@ -383,7 +383,8 @@ List *SWIG_output_files(); void SWIG_library_directory(const char *); int emit_num_arguments(ParmList *); int emit_num_required(ParmList *); -int emit_isvarargs(ParmList *); +int emit_isvarargs(ParmList *p); +bool emit_isvarargs_function(Node *n); void emit_attach_parmmaps(ParmList *, Wrapper *f); void emit_mark_varargs(ParmList *l); String *emit_action(Node *n); diff --git a/Source/Swig/parms.c b/Source/Swig/parms.c index bec1e63fa..3e832c361 100644 --- a/Source/Swig/parms.c +++ b/Source/Swig/parms.c @@ -254,3 +254,19 @@ int ParmList_has_defaultargs(ParmList *p) { } return 0; } + +/* --------------------------------------------------------------------- + * ParmList_has_varargs() + * + * Returns 1 if the parameter list passed in has varargs. + * Otherwise returns 0. + * ---------------------------------------------------------------------- */ + +int ParmList_has_varargs(ParmList *p) { + Parm *lp = 0; + while (p) { + lp = p; + p = nextSibling(p); + } + return lp ? SwigType_isvarargs(Getattr(lp, "type")) : 0; +} diff --git a/Source/Swig/swigparm.h b/Source/Swig/swigparm.h index 368b4d26b..7b27df5f6 100644 --- a/Source/Swig/swigparm.h +++ b/Source/Swig/swigparm.h @@ -24,6 +24,7 @@ extern ParmList *CopyParmListMax(ParmList *, int count); extern int ParmList_len(ParmList *); extern int ParmList_numrequired(ParmList *); extern int ParmList_has_defaultargs(ParmList *p); +extern int ParmList_has_varargs(ParmList *p); /* Output functions */ extern String *ParmList_str(ParmList *);