summaryrefslogtreecommitdiff
path: root/Source
diff options
context:
space:
mode:
authorWilliam S Fulton <wsf@fultondesigns.co.uk>2022-12-27 19:36:40 +0000
committerWilliam S Fulton <wsf@fultondesigns.co.uk>2022-12-29 23:38:17 +0000
commit674abaddbf854e2374f115ef08e59fa79702e19a (patch)
tree73a7d41d03b31258284996f0239a295394ddb209 /Source
parent70837bbc2638ec18bd07d333c6e474c89f4ce695 (diff)
downloadswig-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.c33
-rw-r--r--Source/Swig/stype.c66
-rw-r--r--Source/Swig/swig.h2
-rw-r--r--Source/Swig/typeobj.c43
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;
}