diff --git a/CHANGES.current b/CHANGES.current index b97d7709d..eb96dc093 100644 --- a/CHANGES.current +++ b/CHANGES.current @@ -7,6 +7,14 @@ the issue number to the end of the URL: https://github.com/swig/swig/issues/ Version 4.1.0 (in progress) =========================== +2021-03-26: olly + [PHP] Add PHP keywords 'fn' (added in 7.4) and 'match' (added in + 8.0) to the list SWIG knows to automatically rename. + +2021-03-23: wsfulton + #1942 [Python] Fix compilation error in wrappers when using -builtin + and wrapping varargs in constructors. + 2021-03-22: goto40 #1977 Fix handling of template template parameters. diff --git a/Examples/test-suite/kwargs_feature.i b/Examples/test-suite/kwargs_feature.i index 2b662caeb..dd5b2638d 100644 --- a/Examples/test-suite/kwargs_feature.i +++ b/Examples/test-suite/kwargs_feature.i @@ -126,3 +126,21 @@ struct Extending2 {}; struct ExtendingOptArgs1 {}; struct ExtendingOptArgs2 {}; %} + +// Varargs +%warnfilter(SWIGWARN_LANG_VARARGS_KEYWORD) VarargConstructor::VarargConstructor; // Can't wrap varargs with keyword arguments enabled +%warnfilter(SWIGWARN_LANG_VARARGS_KEYWORD) VarargConstructor::vararg_method; // Can't wrap varargs with keyword arguments enabled +%inline %{ +struct VarargConstructor { + char *str; + VarargConstructor(const char *fmt, ...) { + str = new char[strlen(fmt) + 1]; + strcpy(str, fmt); + } + void vararg_method(const char *fmt, ...) { + delete [] str; + str = new char[strlen(fmt) + 1]; + strcpy(str, fmt); + } +}; +%} diff --git a/Examples/test-suite/python/kwargs_feature_runme.py b/Examples/test-suite/python/kwargs_feature_runme.py index 31d49d221..387658ec3 100644 --- a/Examples/test-suite/python/kwargs_feature_runme.py +++ b/Examples/test-suite/python/kwargs_feature_runme.py @@ -122,3 +122,18 @@ try: raise RuntimeError("missed exception") except TypeError as e: pass + +# Varargs +f = VarargConstructor(fmt="Ciao") +f.vararg_method(fmt="Bonjour") +try: + f = VarargConstructor(nonexistent="Ciao") + raise RuntimeError("missed exception") +except TypeError as e: + pass + +try: + f.vararg_method(nonexistent="Bonjour") + raise RuntimeError("missed exception") +except TypeError as e: + pass diff --git a/Examples/test-suite/python/varargs_runme.py b/Examples/test-suite/python/varargs_runme.py index 8f90d5cde..13f85a75f 100644 --- a/Examples/test-suite/python/varargs_runme.py +++ b/Examples/test-suite/python/varargs_runme.py @@ -3,6 +3,10 @@ import varargs if varargs.test("Hello") != "Hello": raise RuntimeError("Failed") +vc = varargs.VarargConstructor("Hey there") +if vc.str != "Hey there": + raise RuntimeError("Failed") + f = varargs.Foo("Greetings") if f.str != "Greetings": raise RuntimeError("Failed") diff --git a/Examples/test-suite/varargs.i b/Examples/test-suite/varargs.i index dd56cb073..68c7a1714 100644 --- a/Examples/test-suite/varargs.i +++ b/Examples/test-suite/varargs.i @@ -1,17 +1,31 @@ -// Tests SWIG's *default* handling of varargs (function varargs, not preprocessor varargs). +// Tests SWIG's handling of varargs (function varargs, not preprocessor varargs). // The default behavior is to simply ignore the varargs. %module varargs +// Default handling of varargs + +%inline %{ +char *test(const char *fmt, ...) { + return (char *) fmt; +} + +struct VarargConstructor { + char *str; + VarargConstructor(const char *fmt, ...) { + str = new char[strlen(fmt) + 1]; + strcpy(str, fmt); + } +}; +%} + +// %varargs support + %varargs(int mode = 0) test_def; %varargs(int mode = 0) Foo::Foo; %varargs(int mode = 0) Foo::statictest(const char*fmt, ...); %varargs(2, int mode = 0) test_plenty(const char*fmt, ...); %inline %{ -char *test(const char *fmt, ...) { - return (char *) fmt; -} - const char *test_def(const char *fmt, ...) { return fmt; } @@ -40,5 +54,4 @@ public: const char *test_plenty(const char *fmt, ...) { return fmt; } - %} diff --git a/Lib/php/factory.i b/Lib/php/factory.i index 399ef8c1b..2f641fe40 100644 --- a/Lib/php/factory.i +++ b/Lib/php/factory.i @@ -3,41 +3,41 @@ you have: ---- geometry.h -------- - struct Geometry { - enum GeomType{ - POINT, - CIRCLE - }; - - virtual ~Geometry() {} + struct Geometry { + enum GeomType{ + POINT, + CIRCLE + }; + + virtual ~Geometry() {} virtual int draw() = 0; - + // // Factory method for all the Geometry objects // - static Geometry *create(GeomType i); - }; - - struct Point : Geometry { - int draw() { return 1; } - double width() { return 1.0; } - }; - - struct Circle : Geometry { - int draw() { return 2; } - double radius() { return 1.5; } - }; - + static Geometry *create(GeomType i); + }; + + struct Point : Geometry { + int draw() { return 1; } + double width() { return 1.0; } + }; + + struct Circle : Geometry { + int draw() { return 2; } + double radius() { return 1.5; } + }; + // // Factory method for all the Geometry objects // Geometry *Geometry::create(GeomType type) { - switch (type) { - case POINT: return new Point(); - case CIRCLE: return new Circle(); - default: return 0; - } - } + switch (type) { + case POINT: return new Point(); + case CIRCLE: return new Circle(); + default: return 0; + } + } ---- geometry.h -------- @@ -57,16 +57,16 @@ NOTES: remember to fully qualify all the type names and don't use %factory inside a namespace declaration, ie, instead of - + namespace Foo { %factory(Geometry *Geometry::create, Point, Circle); } use - %factory(Foo::Geometry *Foo::Geometry::create, Foo::Point, Foo::Circle); + %factory(Foo::Geometry *Foo::Geometry::create, Foo::Point, Foo::Circle); + - */ /* for loop for macro with one argument */ @@ -90,14 +90,14 @@ /* for loop for macro with two arguments */ %define %formacro_2(macro,...)%_formacro_2(macro, __VA_ARGS__, __fordone__)%enddef -%define %_factory_dispatch(Type) +%define %_factory_dispatch(Type) if (!dcast) { Type *dobj = dynamic_cast($1); if (dobj) { dcast = 1; zend_object *std = $descriptor(Type)##_ce->create_object($descriptor(Type)##_ce); SWIG_SetZval(return_value, $needNewFlow, $owner, SWIG_as_voidptr(dobj), $descriptor(Type *), std); - } + } }%enddef %define %factory(Method,Types...) diff --git a/Lib/php/php.swg b/Lib/php/php.swg index 3c36236d9..b285d897a 100644 --- a/Lib/php/php.swg +++ b/Lib/php/php.swg @@ -176,7 +176,8 @@ %{ if (SWIG_ConvertPtr(&$input, (void **) &$1, 0, 0) < 0) { /* Allow NULL from php for void* */ - if (Z_ISNULL($input)) $1=0; + if (Z_ISNULL($input)) + $1=0; else SWIG_PHP_Error(E_ERROR, "Type error in argument $argnum of $symname. Expected $1_descriptor"); } diff --git a/Lib/php/phpkw.swg b/Lib/php/phpkw.swg index 5c5296a1f..58c108968 100644 --- a/Lib/php/phpkw.swg +++ b/Lib/php/phpkw.swg @@ -55,6 +55,7 @@ PHPKW(endwhile); PHPKW(extends); PHPKW(final); PHPKW(finally); +PHPKW(fn); // as of PHP 7.4 PHPKW(for); PHPKW(foreach); PHPKW(function); @@ -65,6 +66,7 @@ PHPKW(implements); PHPKW(instanceof); PHPKW(insteadof); PHPKW(interface); +PHPKW(match); // as of PHP 8.0 PHPKW(namespace); PHPKW(new); PHPKW(or); diff --git a/Lib/php/phprun.swg b/Lib/php/phprun.swg index 4d395cbf4..76eee87da 100644 --- a/Lib/php/phprun.swg +++ b/Lib/php/phprun.swg @@ -154,7 +154,7 @@ SWIG_ConvertResourceData(void * p, const char *type_name, swig_type_info *ty) { return p; } - if (! type_name) { + if (! type_name) { /* can't convert p to ptr type ty if we don't know what type p is */ return NULL; } diff --git a/Lib/php/std_common.i b/Lib/php/std_common.i index 092bf012b..1b69fc779 100644 --- a/Lib/php/std_common.i +++ b/Lib/php/std_common.i @@ -7,4 +7,3 @@ %include %apply size_t { std::size_t }; - diff --git a/Lib/php/std_map.i b/Lib/php/std_map.i index 7c0157353..fed3cf0b3 100644 --- a/Lib/php/std_map.i +++ b/Lib/php/std_map.i @@ -35,7 +35,7 @@ namespace std { map(); map(const map& other); - + unsigned int size() const; void clear(); %extend { diff --git a/Lib/php/std_vector.i b/Lib/php/std_vector.i index e633bc3ad..382b37ca0 100644 --- a/Lib/php/std_vector.i +++ b/Lib/php/std_vector.i @@ -112,5 +112,3 @@ namespace std { %define specialize_std_vector(T) #warning "specialize_std_vector - specialization for type T no longer needed" %enddef - - diff --git a/Lib/php/stl.i b/Lib/php/stl.i index 04f86014f..38aba67b8 100644 --- a/Lib/php/stl.i +++ b/Lib/php/stl.i @@ -7,4 +7,3 @@ %include %include %include - diff --git a/Source/Modules/php.cxx b/Source/Modules/php.cxx index d96b13097..51ff6b76f 100644 --- a/Source/Modules/php.cxx +++ b/Source/Modules/php.cxx @@ -24,17 +24,6 @@ * value which is a compound C++ expression (i.e. as if we had a * method with two overloaded forms instead of a single method with * a default parameter value). - * - * Long term: - * - * Sort out locale-dependent behaviour of strtod() - it's harmless unless - * SWIG ever sets the locale and DOH/base.c calls atof, so we're probably - * OK currently at least. - */ - -/* - * TODO: Replace remaining stderr messages with Swig_error or Swig_warning - * (may need to add more WARN_PHP_xxx codes...) */ #include "swigmod.h" @@ -1933,8 +1922,6 @@ public: arg_names = (String **) malloc(max_num_of_arguments * sizeof(String *)); if (!arg_names) { - /* FIXME: How should this be handled? The rest of SWIG just seems - * to not bother checking for malloc failing! */ fprintf(stderr, "Malloc failed!\n"); SWIG_exit(EXIT_FAILURE); } @@ -1945,8 +1932,6 @@ public: arg_values = (String **) malloc(max_num_of_arguments * sizeof(String *)); byref = (unsigned char *) malloc(max_num_of_arguments); if (!arg_values || !byref) { - /* FIXME: How should this be handled? The rest of SWIG just seems - * to not bother checking for malloc failing! */ fprintf(stderr, "Malloc failed!\n"); SWIG_exit(EXIT_FAILURE); } @@ -2064,7 +2049,6 @@ public: case T_LONGDOUBLE: { char *p; errno = 0; - /* FIXME: strtod is locale dependent... */ double val = strtod(Char(value), &p); if (errno || *p) { Clear(value); diff --git a/Source/Modules/python.cxx b/Source/Modules/python.cxx index c9bc21742..4ef0eb929 100644 --- a/Source/Modules/python.cxx +++ b/Source/Modules/python.cxx @@ -2753,7 +2753,7 @@ public: if (!varargs) { Printv(f->def, linkage, wrap_return, wname, "(PyObject *", self_param, ", PyObject *args", builtin_kwargs, ") {", NIL); } else { - Printv(f->def, linkage, wrap_return, wname, "__varargs__", "(PyObject *", self_param, ", PyObject *args, PyObject *varargs) {", NIL); + Printv(f->def, linkage, wrap_return, wname, "__varargs__", "(PyObject *", self_param, ", PyObject *args, PyObject *varargs", builtin_kwargs, ") {", NIL); } if (allow_kwargs) { Swig_warning(WARN_LANG_OVERLOAD_KEYWORD, input_file, line_number, "Can't use keyword arguments with overloaded functions (%s).\n", Swig_name_decl(n)); @@ -3253,10 +3253,10 @@ public: Printf(f->code, " Py_XINCREF(swig_obj[i + %d]);\n", num_fixed_arguments); Printf(f->code, "}\n"); } else { - Printf(f->code, "newargs = PyTuple_GetSlice(args,0,%d);\n", num_fixed_arguments); - Printf(f->code, "varargs = PyTuple_GetSlice(args,%d,PyTuple_Size(args));\n", num_fixed_arguments); + Printf(f->code, "newargs = PyTuple_GetSlice(args, 0, %d);\n", num_fixed_arguments); + Printf(f->code, "varargs = PyTuple_GetSlice(args, %d, PyTuple_Size(args));\n", num_fixed_arguments); } - Printf(f->code, "resultobj = %s__varargs__(%s,newargs,varargs);\n", wname, builtin ? "self" : "NULL"); + Printf(f->code, "resultobj = %s__varargs__(%s, newargs, varargs%s);\n", wname, builtin ? "self" : "NULL", strlen(builtin_kwargs) == 0 ? "" : ", kwargs"); Append(f->code, "Py_XDECREF(newargs);\n"); Append(f->code, "Py_XDECREF(varargs);\n"); Append(f->code, "return resultobj;\n"); diff --git a/configure.ac b/configure.ac index 31f8c2cfa..e8cdfb043 100644 --- a/configure.ac +++ b/configure.ac @@ -26,6 +26,11 @@ AM_PROG_CC_C_O # Needed for subdir-objects in AUTOMAKE_OPTIONS AC_COMPILE_WARNINGS # Increase warning levels +AC_MSG_CHECKING([CFLAGS to compile SWIG executable]) +AC_MSG_RESULT([$CFLAGS]) +AC_MSG_CHECKING([CXXFLAGS to compile SWIG executable]) +AC_MSG_RESULT([$CXXFLAGS]) + AC_DEFINE_UNQUOTED(SWIG_CXX, ["$CXX"], [Compiler that built SWIG]) AC_DEFINE_UNQUOTED(SWIG_PLATFORM, ["$host"], [Platform that SWIG is built for])