From 6988b00aba4967f3e01352fbac3eb7f84090d87e Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Mon, 27 Apr 2015 23:14:34 +0200 Subject: [PATCH] Fix handling of default arguments after ignored ones in Python. Don't skip checking subsequent arguments just because one of them has "in" typemap with numinputs=0 attribute. Add a unit test showing the problem which is relatively rare as it doesn't happen for the class methods and is hidden unless autodoc feature is used for the global functions. Closes #377. --- CHANGES.current | 3 +++ Examples/test-suite/default_args.i | 14 ++++++++++++++ Examples/test-suite/python/default_args_runme.py | 7 +++++++ Source/Modules/python.cxx | 9 ++++----- 4 files changed, 28 insertions(+), 5 deletions(-) diff --git a/CHANGES.current b/CHANGES.current index 60023a0c6..16637426a 100644 --- a/CHANGES.current +++ b/CHANGES.current @@ -5,6 +5,9 @@ See the RELEASENOTES file for a summary of changes in each release. Version 3.0.6 (in progress) =========================== +2015-04-27: vadz + [Python] Fix "default" typemap used after an argument with "numinputs=0" (#377). + 2015-04-24: wsfulton [Python] Fix #256. Code generated with '-builtin -modernargs' segfaults for any method taking zero arguments. diff --git a/Examples/test-suite/default_args.i b/Examples/test-suite/default_args.i index 4ab24d335..719681f95 100644 --- a/Examples/test-suite/default_args.i +++ b/Examples/test-suite/default_args.i @@ -278,3 +278,17 @@ struct ConstMethods { } Pointf; } %} + +// Default arguments after ignored ones. +%typemap(in, numinputs=0) int square_error { $1 = 2; }; +%typemap(default, noblock=1) int def17 { $1 = 17; }; + +// Enabling autodoc feature has a side effect of disabling the generation of +// aliases for functions that can hide problems with default arguments at +// Python level. +%feature("autodoc","0") slightly_off_square; + +%inline %{ + inline int slightly_off_square(int square_error, int def17) { return def17*def17 + square_error; } +%} + diff --git a/Examples/test-suite/python/default_args_runme.py b/Examples/test-suite/python/default_args_runme.py index 18cc2c27a..0931bfd3d 100644 --- a/Examples/test-suite/python/default_args_runme.py +++ b/Examples/test-suite/python/default_args_runme.py @@ -110,6 +110,13 @@ def run(module_name): default_args.trickyvalue3(10); default_args.trickyvalue3(10, 10) default_args.seek(); default_args.seek(10) + if default_args.slightly_off_square(10) != 102: + raise RuntimeError + + if default_args.slightly_off_square() != 291: + raise RuntimeError + + if __name__=="__main__": run('default_args') diff --git a/Source/Modules/python.cxx b/Source/Modules/python.cxx index 532b15f4f..6ee39ac34 100644 --- a/Source/Modules/python.cxx +++ b/Source/Modules/python.cxx @@ -2003,17 +2003,16 @@ public: Parm *pnext; for (p = plist; p; p = pnext) { - pnext = NIL; + pnext = nextSibling(p); String *tm = Getattr(p, "tmap:in"); if (tm) { - pnext = Getattr(p, "tmap:in:next"); + Parm *in_next = Getattr(p, "tmap:in:next"); + if (in_next) + pnext = in_next; if (checkAttribute(p, "tmap:in:numinputs", "0")) { continue; } } - if (!pnext) { - pnext = nextSibling(p); - } // "default" typemap can contain arbitrary C++ code, so while it could, in // principle, be possible to examine it and check if it's just something