diff options
author | William S Fulton <wsf@fultondesigns.co.uk> | 2022-12-27 19:36:40 +0000 |
---|---|---|
committer | William S Fulton <wsf@fultondesigns.co.uk> | 2022-12-29 23:38:17 +0000 |
commit | 674abaddbf854e2374f115ef08e59fa79702e19a (patch) | |
tree | 73a7d41d03b31258284996f0239a295394ddb209 /Source | |
parent | 70837bbc2638ec18bd07d333c6e474c89f4ce695 (diff) | |
download | swig-674abaddbf854e2374f115ef08e59fa79702e19a.tar.gz |
Fix instantiation of variadic class templates
containing parameter pack arguments that are function pointers.
template <typename... V> struct VariadicParms {
void ParmsFuncPtrVal(int (*)(V...)) {}
};
%template(VariadicParms0) VariadicParms<>;
%template(VariadicParms1) VariadicParms<A>;
Diffstat (limited to 'Source')
-rw-r--r-- | Source/CParse/templ.c | 33 | ||||
-rw-r--r-- | Source/Swig/stype.c | 66 | ||||
-rw-r--r-- | Source/Swig/swig.h | 2 | ||||
-rw-r--r-- | Source/Swig/typeobj.c | 43 |
4 files changed, 117 insertions, 27 deletions
diff --git a/Source/CParse/templ.c b/Source/CParse/templ.c index 1d9a590a5..1eeb91774 100644 --- a/Source/CParse/templ.c +++ b/Source/CParse/templ.c @@ -25,6 +25,9 @@ void SwigType_template_init(void) { baselists[2] = "privatebaselist"; } +void Swig_cparse_debug_templates(int x) { + template_debug = x; +} /* ----------------------------------------------------------------------------- * add_parms() @@ -70,9 +73,9 @@ static void add_parms(ParmList *p, List *patchlist, List *typelist, int is_patte static void expand_variadic_parms(Node *n, const char *attribute, Parm *unexpanded_variadic_parm, ParmList *expanded_variadic_parms) { ParmList *p = Getattr(n, attribute); - Parm *variadic = ParmList_variadic_parm(p); - if (variadic) { - if (unexpanded_variadic_parm) { + if (unexpanded_variadic_parm) { + Parm *variadic = ParmList_variadic_parm(p); + if (variadic) { SwigType *type = Getattr(variadic, "type"); String *unexpanded_name = Getattr(unexpanded_variadic_parm, "name"); ParmList *expanded = CopyParmList(expanded_variadic_parms); @@ -103,9 +106,6 @@ static void expand_parms(Node *n, const char *attribute, Parm *unexpanded_variad p = Getattr(n, attribute); add_parms(p, patchlist, typelist, is_pattern); } -void Swig_cparse_debug_templates(int x) { - template_debug = x; -} /* ----------------------------------------------------------------------------- * cparse_template_expand() @@ -254,7 +254,6 @@ static void cparse_template_expand(Node *templnode, Node *n, String *tname, Stri Delete(tmp); } } - /* Setattr(n,"sym:name",name); */ } Append(cpatchlist, Getattr(n, "code")); Append(typelist, Getattr(n, "decl")); @@ -282,7 +281,6 @@ static void cparse_template_expand(Node *templnode, Node *n, String *tname, Stri Replace(name, tname, rname, DOH_REPLACE_ANY); } } - /* Setattr(n,"sym:name",name); */ Append(cpatchlist, Getattr(n, "code")); } } else if (Equal(nodeType, "using")) { @@ -431,9 +429,9 @@ int Swig_cparse_template_expand(Node *n, String *rname, ParmList *tparms, Symtab String *tbase; Parm *unexpanded_variadic_parm = 0; ParmList *expanded_variadic_parms = 0; - patchlist = NewList(); - cpatchlist = NewList(); - typelist = NewList(); + patchlist = NewList(); /* List of String * ("name" and "value" attributes) */ + cpatchlist = NewList(); /* List of String * (code) */ + typelist = NewList(); /* List of SwigType * types */ templateargs = NewStringEmpty(); SwigType_add_template(templateargs, tparms); @@ -499,7 +497,7 @@ int Swig_cparse_template_expand(Node *n, String *rname, ParmList *tparms, Symtab Parm *p = tparms; /* Printf(stdout,"%s\n", ParmList_str_defaultargs(tp)); */ - if (tp) { + if (p && tp) { Symtab *tsdecl = Getattr(n, "sym:symtab"); String *tsname = Getattr(n, "sym:name"); while (p && tp) { @@ -542,17 +540,22 @@ int Swig_cparse_template_expand(Node *n, String *rname, ParmList *tparms, Symtab } sz = Len(typelist); for (i = 0; i < sz; i++) { - String *s = Getitem(typelist, i); + SwigType *s = Getitem(typelist, i); + + assert(!SwigType_isvariadic(s)); /* All parameters should have already been expanded, this is for function that contain variadic parameters only, such as f(v.p.V) */ + SwigType_variadic_replace(s, unexpanded_variadic_parm, expanded_variadic_parms); + /* The approach of 'trivially' replacing template arguments is kind of fragile. In particular if types with similar name in different namespaces appear. We will not replace template args if a type/class exists with the same name which is not a template. */ - Node * tynode = Swig_symbol_clookup(s, 0); + Node *tynode = Swig_symbol_clookup(s, 0); String *tyname = tynode ? Getattr(tynode, "sym:name") : 0; /* Printf(stdout, " replacing %s with %s to %s or %s to %s\n", s, name, dvalue, tbase, iname); + Printf(stdout, " %d %s to %s\n", tp == unexpanded_variadic_parm, name, ParmList_str_defaultargs(expanded_variadic_parms)); */ if (!tyname || !tsname || !Equal(tyname, tsname) || Getattr(tynode, "templatetype")) { SwigType_typename_replace(s, name, dvalue); @@ -586,6 +589,8 @@ int Swig_cparse_template_expand(Node *n, String *rname, ParmList *tparms, Symtab sz = Len(typelist); for (i = 0; i < sz; i++) { String *s = Getitem(typelist, i); + assert(!SwigType_isvariadic(s)); /* All parameters should have already been expanded, this is for function that contain variadic parameters only, such as f(v.p.V) */ + SwigType_variadic_replace(s, unexpanded_variadic_parm, expanded_variadic_parms); SwigType_typename_replace(s, tbase, iname); } } diff --git a/Source/Swig/stype.c b/Source/Swig/stype.c index 6ffae7288..c925774e5 100644 --- a/Source/Swig/stype.c +++ b/Source/Swig/stype.c @@ -1393,6 +1393,72 @@ void SwigType_typename_replace(SwigType *t, String *pat, String *rep) { } /* ----------------------------------------------------------------------------- + * SwigType_variadic_replace() + * + * Replaces variadic parameter with a list of (zero or more) parameters. + * Needed for variadic templates. + * ----------------------------------------------------------------------------- */ + +void SwigType_variadic_replace(SwigType *t, Parm *unexpanded_variadic_parm, ParmList *expanded_variadic_parms) { + String *nt; + int i, ilen; + List *elem; + if (!unexpanded_variadic_parm) + return; + + if (SwigType_isvariadic(t)) { + /* Based on expand_variadic_parms() but input is single SwigType (t) instead of ParmList */ + String *unexpanded_name = Getattr(unexpanded_variadic_parm, "name"); + ParmList *expanded = CopyParmList(expanded_variadic_parms); + Parm *ep = expanded; + while (ep) { + SwigType *newtype = Copy(t); + SwigType_del_variadic(newtype); + Replaceid(newtype, unexpanded_name, Getattr(ep, "type")); + Setattr(ep, "type", newtype); + ep = nextSibling(ep); + } + Clear(t); + SwigType *fparms = SwigType_function_parms_only(expanded); + Append(t, fparms); + Delete(expanded); + + return; + } + nt = NewStringEmpty(); + elem = SwigType_split(t); + ilen = Len(elem); + for (i = 0; i < ilen; i++) { + String *e = Getitem(elem, i); + if (SwigType_isfunction(e)) { + int j, jlen; + List *fparms = SwigType_parmlist(e); + Clear(e); + Append(e, "f("); + jlen = Len(fparms); + for (j = 0; j < jlen; j++) { + SwigType *type = Getitem(fparms, j); + SwigType_variadic_replace(type, unexpanded_variadic_parm, expanded_variadic_parms); + if (Len(type) > 0) { + if (j != 0) + Putc(',', e); + Append(e, type); + } else { + assert(j == jlen - 1); /* A variadic parm was replaced with zero parms, variadic parms are only changed at the end of the list */ + } + } + Append(e, ")."); + Delete(fparms); + } + Append(nt, e); + } + Clear(t); + Append(t, nt); + Delete(nt); + Delete(elem); +} + +/* ----------------------------------------------------------------------------- * SwigType_remove_global_scope_prefix() * * Removes the unary scope operator (::) prefix indicating global scope in all diff --git a/Source/Swig/swig.h b/Source/Swig/swig.h index 1f406a3e6..4b02a8101 100644 --- a/Source/Swig/swig.h +++ b/Source/Swig/swig.h @@ -137,6 +137,7 @@ extern "C" { extern SwigType *SwigType_add_template(SwigType *t, ParmList *parms); extern SwigType *SwigType_pop_function(SwigType *t); extern SwigType *SwigType_pop_function_qualifiers(SwigType *t); + extern SwigType *SwigType_function_parms_only(ParmList *parms); extern ParmList *SwigType_function_parms(const SwigType *t, Node *file_line_node); extern List *SwigType_split(const SwigType *t); extern String *SwigType_pop(SwigType *t); @@ -187,6 +188,7 @@ extern "C" { extern SwigType *SwigType_default_create(const SwigType *ty); extern SwigType *SwigType_default_deduce(const SwigType *t); extern void SwigType_typename_replace(SwigType *t, String *pat, String *rep); + extern void SwigType_variadic_replace(SwigType *t, Parm *unexpanded_variadic_parm, ParmList *expanded_variadic_parms); extern SwigType *SwigType_remove_global_scope_prefix(const SwigType *t); extern SwigType *SwigType_alttype(const SwigType *t, int ltmap); diff --git a/Source/Swig/typeobj.c b/Source/Swig/typeobj.c index 3981418c5..d07de6e3d 100644 --- a/Source/Swig/typeobj.c +++ b/Source/Swig/typeobj.c @@ -287,6 +287,7 @@ String *SwigType_parm(const SwigType *t) { * SwigType_split() * * Splits a type into its component parts and returns a list of string. + * The component parts of SwigType are split by '.'. * ----------------------------------------------------------------------------- */ List *SwigType_split(const SwigType *t) { @@ -312,7 +313,7 @@ List *SwigType_split(const SwigType *t) { /* ----------------------------------------------------------------------------- * SwigType_parmlist() * - * Splits a comma separated list of parameters into its component parts + * Splits a comma separated list of SwigType * parameters into its component parts * The input is expected to contain the parameter list within () brackets * Returns 0 if no argument list in the input, ie there are no round brackets () * Returns an empty List if there are no parameters in the () brackets @@ -320,12 +321,12 @@ List *SwigType_split(const SwigType *t) { * * Foo(std::string,p.f().Bar<(int,double)>) * - * returns 2 elements in the list: + * returns 2 SwigType * elements in the list: * std::string * p.f().Bar<(int,double)> * ----------------------------------------------------------------------------- */ -List *SwigType_parmlist(const String *p) { +List *SwigType_parmlist(const SwigType *p) { String *item = 0; List *list; char *c; @@ -864,26 +865,42 @@ SwigType *SwigType_array_type(const SwigType *ty) { * Functions * * SwigType_add_function() + * SwigType_function_parms_only() * SwigType_isfunction() * SwigType_pop_function() * * Add, remove, and test for function types. * ----------------------------------------------------------------------------- */ -/* Returns the function type, t, constructed from the parameters, parms */ -SwigType *SwigType_add_function(SwigType *t, ParmList *parms) { - String *pstr; - Parm *p; +/* ----------------------------------------------------------------------------- + * SwigType_function_parms_only() + * + * Creates a comma separated list of SwigType strings from parms + * ----------------------------------------------------------------------------- */ - Insert(t, 0, ")."); - pstr = NewString("f("); +SwigType *SwigType_function_parms_only(ParmList *parms) { + Parm *p; + SwigType *t = NewString(""); for (p = parms; p; p = nextSibling(p)) { if (p != parms) - Putc(',', pstr); - Append(pstr, Getattr(p, "type")); + Putc(',', t); + Append(t, Getattr(p, "type")); } - Insert(t, 0, pstr); - Delete(pstr); + return t; +} + +/* ----------------------------------------------------------------------------- + * SwigType_add_function() + * + * Returns the function type, t, constructed from the parameters, parms + * ----------------------------------------------------------------------------- */ + +SwigType *SwigType_add_function(SwigType *t, ParmList *parms) { + SwigType *fparms = SwigType_function_parms_only(parms); + Insert(fparms, 0, "f("); + Append(fparms, ")."); + Insert(t, 0, fparms); + Delete(fparms); return t; } |