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 a037e2f2e2.
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
This commit is contained in:
William S Fulton 2025-05-16 18:37:27 +01:00
parent c39c1401cc
commit 307b474769
3 changed files with 20 additions and 8 deletions

View File

@ -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) 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 2025-05-13: wsfulton
Fix undefined behaviour in directorout typemaps for void * and const char *& if 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 the same wrapped function is called more than once. Note that using returning

View File

@ -54,6 +54,9 @@
T bar(T a = 1, T b = 0) {return a + b; } T bar(T a = 1, T b = 0) {return a + b; }
static T statbar(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) {}
}; };
%} %}

View File

@ -176,8 +176,8 @@ static void cparse_template_expand(Node *templnode, Node *n, String *tname, Stri
Append(typelist, Getattr(n, "name")); Append(typelist, Getattr(n, "name"));
} }
expand_parms(n, "parms", 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, cpatchlist, typelist, 0); expand_parms(n, "throws", unexpanded_variadic_parm, expanded_variadic_parms, patchlist, typelist, 0);
} else if (Equal(nodeType, "class")) { } else if (Equal(nodeType, "class")) {
/* Patch base classes */ /* 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(cpatchlist, Getattr(n, "code"));
Append(typelist, Getattr(n, "decl")); Append(typelist, Getattr(n, "decl"));
expand_parms(n, "parms", 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, cpatchlist, typelist, 0); expand_parms(n, "throws", unexpanded_variadic_parm, expanded_variadic_parms, patchlist, typelist, 0);
} else if (Equal(nodeType, "destructor")) { } 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 /* 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. */ * 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(cpatchlist, Getattr(n, "code"));
Append(typelist, Getattr(n, "type")); Append(typelist, Getattr(n, "type"));
Append(typelist, Getattr(n, "decl")); Append(typelist, Getattr(n, "decl"));
expand_parms(n, "parms", 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, cpatchlist, 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, cpatchlist, typelist, 1); expand_parms(n, "pattern", unexpanded_variadic_parm, expanded_variadic_parms, patchlist, typelist, 1);
expand_parms(n, "throws", unexpanded_variadic_parm, expanded_variadic_parms, cpatchlist, typelist, 0); expand_parms(n, "throws", unexpanded_variadic_parm, expanded_variadic_parms, patchlist, typelist, 0);
cn = firstChild(n); cn = firstChild(n);
while (cn) { while (cn) {
cparse_template_expand(templnode, cn, tname, rname, templateargs, patchlist, typelist, cpatchlist, unexpanded_variadic_parm, expanded_variadic_parms); 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 */ /* 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); String *s = Getitem(patchlist, i);
Replace(s, name, dvalue, DOH_REPLACE_ID); 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); sz = Len(typelist);