From 307b4747697e8a5670db713f3c5eaa8a2338a223 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Fri, 16 May 2025 18:37:27 +0100 Subject: [PATCH] Fix regression expanding templates in function parameter values Only using the parameter value in the generated code, such as when using kwargs. This is known to be fundamentally flawed as sometimes the generated value is not accessible outside of the class it is defined in. Fixes regression due to a037e2f2e21884eb282b15da1478508d1cce5f86. The new fix now attempts to treat all value and name attributes as a SwigType instead of an unparsed type in a String. However, it does it more consistently instead of just for the "value" attribute in add_parms. Also subtle problem fix where cpatchlist was incorrectly being used instead of patchlist. Closes #3179 --- CHANGES.current | 4 ++++ Examples/test-suite/kwargs_feature.i | 3 +++ Source/CParse/templ.c | 21 +++++++++++++-------- 3 files changed, 20 insertions(+), 8 deletions(-) diff --git a/CHANGES.current b/CHANGES.current index 73bdabe04..79b4d0326 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.4.0 (in progress) =========================== +2025-05-16: wsfulton + #3179 Fix a regression using -kwargs since swig-4.1 in template expansion of + function parameter values. + 2025-05-13: wsfulton Fix undefined behaviour in directorout typemaps for void * and const char *& if the same wrapped function is called more than once. Note that using returning diff --git a/Examples/test-suite/kwargs_feature.i b/Examples/test-suite/kwargs_feature.i index b4e7c4d47..f04c4ab1d 100644 --- a/Examples/test-suite/kwargs_feature.i +++ b/Examples/test-suite/kwargs_feature.i @@ -54,6 +54,9 @@ T bar(T a = 1, T b = 0) {return a + b; } static T statbar(T a = 1, T b = 0) {return a + b; } + + enum AnEnum {ENUMVAL1, ENUMVAL2}; + void enumIn(AnEnum a = ENUMVAL1) {} }; %} diff --git a/Source/CParse/templ.c b/Source/CParse/templ.c index 253797b7f..6c6936077 100644 --- a/Source/CParse/templ.c +++ b/Source/CParse/templ.c @@ -176,8 +176,8 @@ static void cparse_template_expand(Node *templnode, Node *n, String *tname, Stri Append(typelist, Getattr(n, "name")); } - expand_parms(n, "parms", unexpanded_variadic_parm, expanded_variadic_parms, cpatchlist, typelist, 0); - expand_parms(n, "throws", unexpanded_variadic_parm, expanded_variadic_parms, cpatchlist, typelist, 0); + expand_parms(n, "parms", unexpanded_variadic_parm, expanded_variadic_parms, patchlist, typelist, 0); + expand_parms(n, "throws", unexpanded_variadic_parm, expanded_variadic_parms, patchlist, typelist, 0); } else if (Equal(nodeType, "class")) { /* Patch base classes */ @@ -252,8 +252,8 @@ static void cparse_template_expand(Node *templnode, Node *n, String *tname, Stri } Append(cpatchlist, Getattr(n, "code")); Append(typelist, Getattr(n, "decl")); - expand_parms(n, "parms", unexpanded_variadic_parm, expanded_variadic_parms, cpatchlist, typelist, 0); - expand_parms(n, "throws", unexpanded_variadic_parm, expanded_variadic_parms, cpatchlist, typelist, 0); + expand_parms(n, "parms", unexpanded_variadic_parm, expanded_variadic_parms, patchlist, typelist, 0); + expand_parms(n, "throws", unexpanded_variadic_parm, expanded_variadic_parms, patchlist, typelist, 0); } else if (Equal(nodeType, "destructor")) { /* We only need to patch the dtor of the template itself, not the destructors of any nested classes, so check that the parent of this node is the root * template node, with the special exception for %extend which adds its methods under an intermediate node. */ @@ -314,10 +314,10 @@ static void cparse_template_expand(Node *templnode, Node *n, String *tname, Stri Append(cpatchlist, Getattr(n, "code")); Append(typelist, Getattr(n, "type")); Append(typelist, Getattr(n, "decl")); - expand_parms(n, "parms", unexpanded_variadic_parm, expanded_variadic_parms, cpatchlist, typelist, 0); - expand_parms(n, "kwargs", unexpanded_variadic_parm, expanded_variadic_parms, cpatchlist, typelist, 0); - expand_parms(n, "pattern", unexpanded_variadic_parm, expanded_variadic_parms, cpatchlist, typelist, 1); - expand_parms(n, "throws", unexpanded_variadic_parm, expanded_variadic_parms, cpatchlist, typelist, 0); + expand_parms(n, "parms", unexpanded_variadic_parm, expanded_variadic_parms, patchlist, typelist, 0); + expand_parms(n, "kwargs", unexpanded_variadic_parm, expanded_variadic_parms, patchlist, typelist, 0); + expand_parms(n, "pattern", unexpanded_variadic_parm, expanded_variadic_parms, patchlist, typelist, 1); + expand_parms(n, "throws", unexpanded_variadic_parm, expanded_variadic_parms, patchlist, typelist, 0); cn = firstChild(n); while (cn) { cparse_template_expand(templnode, cn, tname, rname, templateargs, patchlist, typelist, cpatchlist, unexpanded_variadic_parm, expanded_variadic_parms); @@ -576,6 +576,11 @@ int Swig_cparse_template_expand(Node *n, String *rname, ParmList *tparms, Symtab /* Patch String or SwigType with SwigType, eg T => int in Foo<(T)>, or TT => Hello<(int)> in X<(TT)>::meth */ String *s = Getitem(patchlist, i); Replace(s, name, dvalue, DOH_REPLACE_ID); + /* Try treat the string as a proper SwigType thought it's usually a string containing an unparsed + * C type. The proper fix would be to parse the String to convert it to a SwigType say using + * Swig_cparse_type, but we'd need a re-entrant parser for that. This hack usually works for simple types. + */ + SwigType_typename_replace(s, tbase, name_with_templateargs); } sz = Len(typelist);