diff options
-rw-r--r-- | Doc/Manual/Warnings.html | 1 | ||||
-rw-r--r-- | Examples/test-suite/common.mk | 2 | ||||
-rw-r--r-- | Examples/test-suite/cpp11_variadic_templates.i | 81 | ||||
-rw-r--r-- | Examples/test-suite/python/cpp11_variadic_templates_runme.py | 152 | ||||
-rw-r--r-- | Source/CParse/parser.y | 23 | ||||
-rw-r--r-- | Source/CParse/templ.c | 159 | ||||
-rw-r--r-- | Source/Include/swigwarn.h | 2 | ||||
-rw-r--r-- | Source/Swig/parms.c | 51 | ||||
-rw-r--r-- | Source/Swig/stype.c | 7 | ||||
-rw-r--r-- | Source/Swig/swig.h | 3 | ||||
-rw-r--r-- | Source/Swig/swigparm.h | 5 | ||||
-rw-r--r-- | Source/Swig/tree.c | 4 | ||||
-rw-r--r-- | Source/Swig/typeobj.c | 41 |
13 files changed, 465 insertions, 66 deletions
diff --git a/Doc/Manual/Warnings.html b/Doc/Manual/Warnings.html index 1cdf37ec2..1ed629cc6 100644 --- a/Doc/Manual/Warnings.html +++ b/Doc/Manual/Warnings.html @@ -439,7 +439,6 @@ example.i(4) : Syntax error in input(1). <li>326. Deprecated %extend name used - the <em>kind</em> name '<em>name</em>' should be used instead of the typedef name '<em>name</em>'. <li>327. Extern template ignored. <li>340. Lambda expressions and closures are not fully supported yet. -<li>343. Only the first variadic template argument is currently supported. <li>344. Unable to deduce decltype for '<em>expr</em>'. <li>350. operator new ignored. <li>351. operator delete ignored. diff --git a/Examples/test-suite/common.mk b/Examples/test-suite/common.mk index 3a5e7f678..cb71aab1b 100644 --- a/Examples/test-suite/common.mk +++ b/Examples/test-suite/common.mk @@ -632,10 +632,10 @@ CPP11_TEST_CASES += \ cpp11_uniform_initialization \ cpp11_unrestricted_unions \ cpp11_userdefined_literals \ + cpp11_variadic_templates \ # Broken C++11 test cases. CPP11_TEST_BROKEN = \ -# cpp11_variadic_templates \ # Broken for some languages (such as Java) # cpp11_reference_wrapper \ # No typemaps # C++14 test cases. diff --git a/Examples/test-suite/cpp11_variadic_templates.i b/Examples/test-suite/cpp11_variadic_templates.i index 15ab4eece..e561ad805 100644 --- a/Examples/test-suite/cpp11_variadic_templates.i +++ b/Examples/test-suite/cpp11_variadic_templates.i @@ -4,9 +4,21 @@ using variadic number of classes. */ %module cpp11_variadic_templates -%warnfilter(SWIGWARN_CPP11_VARIADIC_TEMPLATE) MultiArgs; -%warnfilter(SWIGWARN_CPP11_VARIADIC_TEMPLATE) SizeOf; -%warnfilter(SWIGWARN_CPP11_VARIADIC_TEMPLATE) MultiInherit; +%warnfilter(SWIGWARN_JAVA_MULTIPLE_INHERITANCE, + SWIGWARN_CSHARP_MULTIPLE_INHERITANCE, + SWIGWARN_D_MULTIPLE_INHERITANCE, + SWIGWARN_PHP_MULTIPLE_INHERITANCE, + SWIGWARN_RUBY_MULTIPLE_INHERITANCE) MultiInherit; +%warnfilter(SWIGWARN_JAVA_MULTIPLE_INHERITANCE, + SWIGWARN_CSHARP_MULTIPLE_INHERITANCE, + SWIGWARN_D_MULTIPLE_INHERITANCE, + SWIGWARN_PHP_MULTIPLE_INHERITANCE, + SWIGWARN_RUBY_MULTIPLE_INHERITANCE) NumerousInherit; +%warnfilter(SWIGWARN_JAVA_MULTIPLE_INHERITANCE, + SWIGWARN_CSHARP_MULTIPLE_INHERITANCE, + SWIGWARN_D_MULTIPLE_INHERITANCE, + SWIGWARN_PHP_MULTIPLE_INHERITANCE, + SWIGWARN_RUBY_MULTIPLE_INHERITANCE) LotsInherit; //////////////////////// // Variadic templates // @@ -24,7 +36,6 @@ class MultiArgs<int, std::vector<int>, std::map<std::string, std::vector<int>>> %} -// TODO %template (MultiArgs1) MultiArgs<int, std::vector<int>, std::map<std::string, std::vector<int>>>; //////////////////////// @@ -36,7 +47,10 @@ template<typename... Args> struct SizeOf { }; %} -%template (SizeOf1) SizeOf<int, int>; +%template (SizeOf0) SizeOf<>; +%template (SizeOf1) SizeOf<int>; +%template (SizeOf2) SizeOf<int, int>; +%template (SizeOf3) SizeOf<int, int, int>; ////////////////////////// // Variadic inheritance // @@ -60,18 +74,67 @@ public: int b; }; +class C { +public: + C() { + c = 300; + } + virtual ~C() {} + int c; +}; + +class D { +public: + D() { + d = 400; + } + virtual ~D() {} + int d; +}; + template <typename... BaseClasses> class MultiInherit : public BaseClasses... { public: MultiInherit(BaseClasses&... baseClasses) : BaseClasses(baseClasses)... {} + void MultiInstanceMethod(BaseClasses&... baseClasses) {} + static void MultiStaticMethod(BaseClasses&... baseClasses) {} int InstanceMethod() { return 123; } static int StaticMethod() { return 456; } }; %} - -// TODO -//%template (MultiInherit0) MultiInherit<>; +%template (MultiInherit0) MultiInherit<>; %template (MultiInherit1) MultiInherit<A>; -// TODO %template (MultiInherit2) MultiInherit<A,B>; +%template (MultiInherit3) MultiInherit<A,B,C>; + +%inline %{ +template <typename... BaseClasses> class NumerousInherit : public BaseClasses... { +public: + NumerousInherit(int i, BaseClasses&... baseClasses) : BaseClasses(baseClasses)... {} + void NumerousInstanceMethod(int i, BaseClasses&... baseClasses) {} + static void NumerousStaticMethod(int i, BaseClasses&... baseClasses) {} + int InstanceMethod() { return 123; } + static int StaticMethod() { return 456; } +}; +%} + +%template (NumerousInherit0) NumerousInherit<>; +%template (NumerousInherit1) NumerousInherit<A>; +%template (NumerousInherit2) NumerousInherit<A,B>; +%template (NumerousInherit3) NumerousInherit<A,B,C>; + +%inline %{ +template <typename T, typename... BaseClasses> class LotsInherit : public T, public BaseClasses... { +public: + LotsInherit(T t, BaseClasses&... baseClasses) : BaseClasses(baseClasses)... {} + void LotsInstanceMethod(T t, BaseClasses&... baseClasses) {} + static void LotsStaticMethod(T t, BaseClasses&... baseClasses) {} + int InstanceMethod() { return 123; } + static int StaticMethod() { return 456; } +}; +%} +%template (LotsInherit1) LotsInherit<A>; +%template (LotsInherit2) LotsInherit<A,B>; +%template (LotsInherit3) LotsInherit<A,B,C>; +%template (LotsInherit4) LotsInherit<A,B,C,D>; diff --git a/Examples/test-suite/python/cpp11_variadic_templates_runme.py b/Examples/test-suite/python/cpp11_variadic_templates_runme.py new file mode 100644 index 000000000..b27e53910 --- /dev/null +++ b/Examples/test-suite/python/cpp11_variadic_templates_runme.py @@ -0,0 +1,152 @@ +from cpp11_variadic_templates import * + +ma = MultiArgs1() + +# SizeOf testing +so0 = SizeOf0() +if so0.size != 0: + raise RuntimeError("so0.size") +so1 = SizeOf1() +if so1.size != 1: + raise RuntimeError("so1.size") +so2 = SizeOf2() +if so2.size != 2: + raise RuntimeError("so2.size") +so3 = SizeOf3() +if so3.size != 3: + raise RuntimeError("so3.size") + +a = A() +b = B() +c = C() +d = D() + +# MultiInherit0 +mi0 = MultiInherit0() +mi0.MultiInstanceMethod() +MultiInherit0.MultiStaticMethod() +mi0.InstanceMethod() +MultiInherit0.StaticMethod() + +# MultiInherit1 +mi1 = MultiInherit1(a) +if mi1.a != 100: + raise RuntimeError("fail mi1.a") +mi1.MultiInstanceMethod(a) +MultiInherit1.MultiStaticMethod(a) +mi1.InstanceMethod() +MultiInherit1.StaticMethod() + +# MultiInherit2 +mi2 = MultiInherit2(a, b) +if mi2.a != 100: + raise RuntimeError("fail mi2.a") +if mi2.b != 200: + raise RuntimeError("fail mi2.b") +mi2.MultiInstanceMethod(a, b) +MultiInherit2.MultiStaticMethod(a, b) +mi2.InstanceMethod() +MultiInherit2.StaticMethod() + +# MultiInherit3 +mi3 = MultiInherit3(a, b, c) +if mi3.a != 100: + raise RuntimeError("fail mi3.a") +if mi3.b != 200: + raise RuntimeError("fail mi3.b") +if mi3.c != 300: + raise RuntimeError("fail mi3.c") +mi3.MultiInstanceMethod(a, b, c) +MultiInherit3.MultiStaticMethod(a, b, c) +mi3.InstanceMethod() +MultiInherit3.StaticMethod() + +# NumerousInherit0 +num = 123 +ni0 = NumerousInherit0(num) +ni0.NumerousInstanceMethod(num) +NumerousInherit0.NumerousStaticMethod(num) +ni0.InstanceMethod() +NumerousInherit0.StaticMethod() + +# NumerousInherit1 +ni1 = NumerousInherit1(num, a) +if ni1.a != 100: + raise RuntimeError("fail ni1.a") +ni1.NumerousInstanceMethod(num, a) +NumerousInherit1.NumerousStaticMethod(num, a) +ni1.InstanceMethod() +NumerousInherit1.StaticMethod() + +# NumerousInherit2 +ni2 = NumerousInherit2(num, a, b) +if ni2.a != 100: + raise RuntimeError("fail ni2.a") +if ni2.b != 200: + raise RuntimeError("fail ni2.b") +ni2.NumerousInstanceMethod(num, a, b) +NumerousInherit2.NumerousStaticMethod(num, a, b) +ni2.InstanceMethod() +NumerousInherit2.StaticMethod() + +# NumerousInherit3 +ni3 = NumerousInherit3(num, a, b, c) +if ni3.a != 100: + raise RuntimeError("fail ni3.a") +if ni3.b != 200: + raise RuntimeError("fail ni3.b") +if ni3.c != 300: + raise RuntimeError("fail ni3.c") +ni3.NumerousInstanceMethod(num, a, b, c) +NumerousInherit3.NumerousStaticMethod(num, a, b, c) +ni3.InstanceMethod() +NumerousInherit3.StaticMethod() + +LotsInherit1 +lots1 = LotsInherit1(a) +if lots1.a != 100: + raise RuntimeError("fail lots1.a") +lots1.LotsInstanceMethod(a) +LotsInherit1.LotsStaticMethod(a) +lots1.InstanceMethod() +LotsInherit1.StaticMethod() + +# LotsInherit2 +lots2 = LotsInherit2(a, b) +if lots2.a != 100: + raise RuntimeError("fail lots2.a") +if lots2.b != 200: + raise RuntimeError("fail lots2.b") +lots2.LotsInstanceMethod(a, b) +LotsInherit2.LotsStaticMethod(a, b) +lots2.InstanceMethod() +LotsInherit2.StaticMethod() + +# LotsInherit3 +lots3 = LotsInherit3(a, b, c) +if lots3.a != 100: + raise RuntimeError("fail lots3.a") +if lots3.b != 200: + raise RuntimeError("fail lots3.b") +if lots3.c != 300: + raise RuntimeError("fail lots3.c") +lots3.LotsInstanceMethod(a, b, c) +LotsInherit3.LotsStaticMethod(a, b, c) +lots3.InstanceMethod() +LotsInherit3.StaticMethod() + +# LotsInherit4 +lots4 = LotsInherit4(a, b, c, d) +if lots4.a != 100: + raise RuntimeError("fail lots4.a") +if lots4.b != 200: + raise RuntimeError("fail lots4.b") +if lots4.c != 300: + raise RuntimeError("fail lots4.c") +if lots4.d != 400: + raise RuntimeError("fail lots4.c") +lots4.LotsInstanceMethod(a, b, c, d) +LotsInherit4.LotsStaticMethod(a, b, c, d) +lots4.InstanceMethod() +LotsInherit4.StaticMethod() + diff --git a/Source/CParse/parser.y b/Source/CParse/parser.y index 9cdd2d0f6..31b1f92ea 100644 --- a/Source/CParse/parser.y +++ b/Source/CParse/parser.y @@ -2879,7 +2879,7 @@ template_directive: SWIGTEMPLATE LPAREN idstringopt RPAREN idcolonnt LESSTHAN va Parm *tparms = Getattr(nn,"templateparms"); if (!tparms) { specialized = 1; - } else if (Getattr(tparms,"variadic") && strncmp(Char(Getattr(tparms,"variadic")), "1", 1)==0) { + } else if (ParmList_variadic_parm(tparms)) { variadic = 1; } if (nnisclass && !variadic && !specialized && (ParmList_len($7) > ParmList_len(tparms))) { @@ -4429,12 +4429,12 @@ templateparameter : templcpptype def_args { const char *t = Strchr(type, ' '); Setattr(p, "name", t + 1); Setattr(p, "type", NewStringWithSize(type, t - Char(type))); - } else if ((Strncmp(type, "class... ", 9) == 0) || (Strncmp(type, "typename... ", 12) == 0)) { + } else if ((Strncmp(type, "v.class ", 8) == 0) || (Strncmp(type, "v.typename ", 11) == 0)) { /* Variadic template args */ const char *t = Strchr(type, ' '); Setattr(p, "name", t + 1); Setattr(p, "type", NewStringWithSize(type, t - Char(type))); - Setattr(p, "variadic", "1"); + SetFlag(p, "variadic"); } } } @@ -5540,6 +5540,8 @@ declarator : pointer notso_direct_declarator { $$ = $3; $$.type = NewStringEmpty(); SwigType_add_reference($$.type); + SwigType_add_variadic($$.type); +/* TODO: add other SwigType_add_variadic */ if ($3.type) { SwigType_push($$.type,$3.type); Delete($3.type); @@ -6923,8 +6925,11 @@ base_specifier : opt_virtual { } else { Setattr($$,"access","public"); } - if ($4) + if ($4) { +/*TODO: remove "variadic" flag */ SetFlag($$, "variadic"); + SwigType_add_variadic(Getattr($$, "name")); + } } | opt_virtual access_specifier { $<intvalue>$ = cparse_line; @@ -6939,8 +6944,10 @@ base_specifier : opt_virtual { if (Strcmp($2,"public") != 0) { Swig_warning(WARN_PARSE_PRIVATE_INHERIT, Getfile($$), Getline($$), "%s inheritance from base '%s' (ignored).\n", $2, SwigType_namestr($5)); } - if ($6) + if ($6) { SetFlag($$, "variadic"); + SwigType_add_variadic(Getattr($$, "name")); + } } ; @@ -6958,11 +6965,13 @@ templcpptype : CLASS { if (!inherit_list) last_cpptype = $$; } | CLASS ELLIPSIS { - $$ = (char *)"class..."; + /* TODO: call SwigType_add_variadic() instead */ + $$ = (char *)"v.class"; if (!inherit_list) last_cpptype = $$; } | TYPENAME ELLIPSIS { - $$ = (char *)"typename..."; + /* TODO: call SwigType_add_variadic() instead */ + $$ = (char *)"v.typename"; if (!inherit_list) last_cpptype = $$; } ; diff --git a/Source/CParse/templ.c b/Source/CParse/templ.c index 2317b892f..1d9a590a5 100644 --- a/Source/CParse/templ.c +++ b/Source/CParse/templ.c @@ -26,6 +26,13 @@ void SwigType_template_init(void) { } +/* ----------------------------------------------------------------------------- + * add_parms() + * + * Add the value and type of each parameter into patchlist and typelist + * (List of String/SwigType) for later template parameter substitutions. + * ----------------------------------------------------------------------------- */ + static void add_parms(ParmList *p, List *patchlist, List *typelist, int is_pattern) { while (p) { SwigType *ty = Getattr(p, "type"); @@ -44,6 +51,58 @@ static void add_parms(ParmList *p, List *patchlist, List *typelist, int is_patte } } +/* ----------------------------------------------------------------------------- + * expand_variadic_parms() + * + * Expand variadic parameter in the parameter list stored as attribute in n. For example: + * template <typename... T> struct X : { X(T&... tt); } + * %template(XABC) X<A,B,C>; + * inputs for the constructor parameter list will be for attribute = "parms": + * Getattr(n, attribute) : v.r.T tt + * unexpanded_variadic_parm: v.typename T + * expanded_variadic_parms : A,B,C + * results in: + * Getattr(n, attribute) : r.A,r.B,r.C + * that is, template is expanded as: struct XABC : { X(A&,B&,C&); } + * Note that there are no parameter names are in the expanded parameter list. + * Nothing happens if the parameter list has no variadic parameters. + * ----------------------------------------------------------------------------- */ + +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) { + SwigType *type = Getattr(variadic, "type"); + String *unexpanded_name = Getattr(unexpanded_variadic_parm, "name"); + ParmList *expanded = CopyParmList(expanded_variadic_parms); + Parm *ep = expanded; + while (ep) { + SwigType *newtype = Copy(type); + SwigType_del_variadic(newtype); + Replaceid(newtype, unexpanded_name, Getattr(ep, "type")); + Setattr(ep, "type", newtype); + ep = nextSibling(ep); + } + expanded = ParmList_replace_last(p, expanded); + Setattr(n, attribute, expanded); + } + } +} + +/* ----------------------------------------------------------------------------- + * expand_parms() + * + * Expand variadic parameters in parameter lists and add parameters to patchlist + * and typelist for later template parameter substitutions. + * ----------------------------------------------------------------------------- */ + +static void expand_parms(Node *n, const char *attribute, Parm *unexpanded_variadic_parm, ParmList *expanded_variadic_parms, List *patchlist, List *typelist, int is_pattern) { + ParmList *p; + expand_variadic_parms(n, attribute, unexpanded_variadic_parm, expanded_variadic_parms); + p = Getattr(n, attribute); + add_parms(p, patchlist, typelist, is_pattern); +} void Swig_cparse_debug_templates(int x) { template_debug = x; } @@ -56,7 +115,7 @@ void Swig_cparse_debug_templates(int x) { * template parameters * ----------------------------------------------------------------------------- */ -static void cparse_template_expand(Node *templnode, Node *n, String *tname, String *rname, String *templateargs, List *patchlist, List *typelist, List *cpatchlist) { +static void cparse_template_expand(Node *templnode, Node *n, String *tname, String *rname, String *templateargs, List *patchlist, List *typelist, List *cpatchlist, Parm *unexpanded_variadic_parm, ParmList *expanded_variadic_parms) { static int expanded = 0; String *nodeType; if (!n) @@ -70,7 +129,7 @@ static void cparse_template_expand(Node *templnode, Node *n, String *tname, Stri if (!expanded) { expanded = 1; set_nodeType(n, Getattr(n, "templatetype")); - cparse_template_expand(templnode, n, tname, rname, templateargs, patchlist, typelist, cpatchlist); + cparse_template_expand(templnode, n, tname, rname, templateargs, patchlist, typelist, cpatchlist, unexpanded_variadic_parm, expanded_variadic_parms); expanded = 0; return; } else { @@ -78,7 +137,7 @@ static void cparse_template_expand(Node *templnode, Node *n, String *tname, Stri /* Member templates */ set_nodeType(n, Getattr(n, "templatetype")); - cparse_template_expand(templnode, n, tname, rname, templateargs, patchlist, typelist, cpatchlist); + cparse_template_expand(templnode, n, tname, rname, templateargs, patchlist, typelist, cpatchlist, unexpanded_variadic_parm, expanded_variadic_parms); set_nodeType(n, "template"); return; } @@ -113,8 +172,8 @@ static void cparse_template_expand(Node *templnode, Node *n, String *tname, Stri Append(typelist, Getattr(n, "name")); } - add_parms(Getattr(n, "parms"), cpatchlist, typelist, 0); - add_parms(Getattr(n, "throws"), cpatchlist, typelist, 0); + 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); } else if (Equal(nodeType, "class")) { /* Patch base classes */ @@ -127,8 +186,27 @@ static void cparse_template_expand(Node *templnode, Node *n, String *tname, Stri int ilen = Len(bases); for (i = 0; i < ilen; i++) { String *name = Copy(Getitem(bases, i)); - Setitem(bases, i, name); - Append(typelist, name); + if (SwigType_isvariadic(name)) { + Parm *parm = NewParmWithoutFileLineInfo(name, 0); + Node *temp_parm_node = NewHash(); + Setattr(temp_parm_node, "variadicbaseparms", parm); + assert(i == ilen - 1); + Delitem(bases, i); + expand_variadic_parms(temp_parm_node, "variadicbaseparms", unexpanded_variadic_parm, expanded_variadic_parms); + { + Parm *vp = Getattr(temp_parm_node, "variadicbaseparms"); + while (vp) { + String *name = Copy(Getattr(vp, "type")); + Append(bases, name); + Append(typelist, name); + vp = nextSibling(vp); + } + } + Delete(temp_parm_node); + } else { + Setitem(bases, i, name); + Append(typelist, name); + } } } } @@ -137,7 +215,7 @@ static void cparse_template_expand(Node *templnode, Node *n, String *tname, Stri { Node *cn = firstChild(n); while (cn) { - cparse_template_expand(templnode, cn, tname, rname, templateargs, patchlist, typelist, cpatchlist); + cparse_template_expand(templnode, cn, tname, rname, templateargs, patchlist, typelist, cpatchlist, unexpanded_variadic_parm, expanded_variadic_parms); cn = nextSibling(cn); } } @@ -180,8 +258,8 @@ static void cparse_template_expand(Node *templnode, Node *n, String *tname, Stri } Append(cpatchlist, Getattr(n, "code")); Append(typelist, Getattr(n, "decl")); - add_parms(Getattr(n, "parms"), cpatchlist, typelist, 0); - add_parms(Getattr(n, "throws"), cpatchlist, typelist, 0); + 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); } 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. */ @@ -222,13 +300,13 @@ 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")); - add_parms(Getattr(n, "parms"), cpatchlist, typelist, 0); - add_parms(Getattr(n, "kwargs"), cpatchlist, typelist, 0); - add_parms(Getattr(n, "pattern"), cpatchlist, typelist, 1); - add_parms(Getattr(n, "throws"), cpatchlist, typelist, 0); + 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); cn = firstChild(n); while (cn) { - cparse_template_expand(templnode, cn, tname, rname, templateargs, patchlist, typelist, cpatchlist); + cparse_template_expand(templnode, cn, tname, rname, templateargs, patchlist, typelist, cpatchlist, unexpanded_variadic_parm, expanded_variadic_parms); cn = nextSibling(cn); } } @@ -351,18 +429,14 @@ int Swig_cparse_template_expand(Node *n, String *rname, ParmList *tparms, Symtab String *tname; String *iname; String *tbase; + Parm *unexpanded_variadic_parm = 0; + ParmList *expanded_variadic_parms = 0; patchlist = NewList(); cpatchlist = NewList(); typelist = NewList(); - { - String *tmp = NewStringEmpty(); - if (tparms) { - SwigType_add_template(tmp, tparms); - } - templateargs = Copy(tmp); - Delete(tmp); - } + templateargs = NewStringEmpty(); + SwigType_add_template(templateargs, tparms); tname = Copy(Getattr(n, "name")); tbase = Swig_scopename_last(tname); @@ -400,10 +474,15 @@ int Swig_cparse_template_expand(Node *n, String *rname, ParmList *tparms, Symtab } */ + ParmList *templateparms = Getattr(n, "templateparms"); + unexpanded_variadic_parm = ParmList_variadic_parm(templateparms); + if (unexpanded_variadic_parm) + expanded_variadic_parms = ParmList_nth_parm(tparms, ParmList_len(templateparms) - 1); + /* Printf(stdout,"targs = '%s'\n", templateargs); Printf(stdout,"rname = '%s'\n", rname); Printf(stdout,"tname = '%s'\n", tname); */ - cparse_template_expand(n, n, tname, rname, templateargs, patchlist, typelist, cpatchlist); + cparse_template_expand(n, n, tname, rname, templateargs, patchlist, typelist, cpatchlist, unexpanded_variadic_parm, expanded_variadic_parms); /* Set the name */ { @@ -472,6 +551,9 @@ int Swig_cparse_template_expand(Node *n, String *rname, ParmList *tparms, Symtab */ 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); + */ if (!tyname || !tsname || !Equal(tyname, tsname) || Getattr(tynode, "templatetype")) { SwigType_typename_replace(s, name, dvalue); SwigType_typename_replace(s, tbase, iname); @@ -1015,9 +1097,11 @@ Node *Swig_cparse_template_locate(String *name, Parm *tparms, String *symname, S * Grab the parameter names from templateparms. * Non-type template parameters have no type information in expanded_templateparms. * Grab them from templateparms. + * + * Return 1 if there are variadic template parameters, 0 otherwise. * ----------------------------------------------------------------------------- */ -static void merge_parameters(ParmList *expanded_templateparms, ParmList *templateparms) { +static int merge_parameters(ParmList *expanded_templateparms, ParmList *templateparms) { Parm *p = expanded_templateparms; Parm *tp = templateparms; while (p && tp) { @@ -1027,6 +1111,7 @@ static void merge_parameters(ParmList *expanded_templateparms, ParmList *templat p = nextSibling(p); tp = nextSibling(tp); } + return ParmList_variadic_parm(templateparms) ? 1 : 0; } /* ----------------------------------------------------------------------------- @@ -1088,14 +1173,16 @@ ParmList *Swig_cparse_template_parms_expand(ParmList *instantiated_parameters, N if (Equal(Getattr(primary, "templatetype"), "class")) { /* Templated class */ expanded_templateparms = CopyParmList(instantiated_parameters); - merge_parameters(expanded_templateparms, templateparms); - /* Add default arguments from chosen template */ - ParmList *defaults_start = ParmList_nth_parm(templateparms, ParmList_len(instantiated_parameters)); - if (defaults_start) { - ParmList *defaults = CopyParmList(defaults_start); - mark_defaults(defaults); - expanded_templateparms = ParmList_join(expanded_templateparms, defaults); - expand_defaults(expanded_templateparms); + int variadic = merge_parameters(expanded_templateparms, templateparms); + /* Add default arguments from primary template */ + if (!variadic) { + ParmList *defaults_start = ParmList_nth_parm(templateparms, ParmList_len(instantiated_parameters)); + if (defaults_start) { + ParmList *defaults = CopyParmList(defaults_start); + mark_defaults(defaults); + expanded_templateparms = ParmList_join(expanded_templateparms, defaults); + expand_defaults(expanded_templateparms); + } } } else { /* Templated function */ @@ -1104,11 +1191,5 @@ ParmList *Swig_cparse_template_parms_expand(ParmList *instantiated_parameters, N merge_parameters(expanded_templateparms, templateparms); } - if (templateparms && (ParmList_len(templateparms) < ParmList_len(expanded_templateparms))) { - SWIG_WARN_NODE_BEGIN(nn); - Swig_warning(WARN_CPP11_VARIADIC_TEMPLATE, cparse_file, cparse_line, "Only the first variadic template argument is currently supported.\n"); - SWIG_WARN_NODE_END(nn); - } - return expanded_templateparms; } diff --git a/Source/Include/swigwarn.h b/Source/Include/swigwarn.h index cc8192d29..f9be0b669 100644 --- a/Source/Include/swigwarn.h +++ b/Source/Include/swigwarn.h @@ -98,7 +98,7 @@ #define WARN_CPP11_LAMBDA 340 #define WARN_CPP11_ALIAS_DECLARATION 341 /* redundant now */ #define WARN_CPP11_ALIAS_TEMPLATE 342 /* redundant now */ -#define WARN_CPP11_VARIADIC_TEMPLATE 343 +#define WARN_CPP11_VARIADIC_TEMPLATE 343 /* redundant now */ #define WARN_CPP11_DECLTYPE 344 #define WARN_IGNORE_OPERATOR_NEW 350 /* new */ diff --git a/Source/Swig/parms.c b/Source/Swig/parms.c index ab767bd76..3e052ca0c 100644 --- a/Source/Swig/parms.c +++ b/Source/Swig/parms.c @@ -122,11 +122,10 @@ ParmList *CopyParmList(ParmList *p) { ParmList *ParmList_join(ParmList *p, ParmList *p2) { Parm *firstparm = p ? p : p2; - Parm *lastparm = p; + Parm *lastparm = 0; while (p) { + lastparm = p; p = nextSibling(p); - if (p) - lastparm = p; } if (lastparm) set_nextSibling(lastparm, p2); @@ -135,15 +134,38 @@ ParmList *ParmList_join(ParmList *p, ParmList *p2) { } /* ----------------------------------------------------------------------------- + * ParmList_replace_last() + * + * Delete last parameter in p and replace it with parameter list p2. + * p must have at least one element, that is, must not be NULL. + * Return beginning of modified parameter list. + * ----------------------------------------------------------------------------- */ + +ParmList *ParmList_replace_last(ParmList *p, ParmList *p2) { + ParmList *start = p; + int len = ParmList_len(p); + assert(p); + if (len == 1) { + start = p2; + } else if (len > 1) { + Parm *secondlastparm = ParmList_nth_parm(p, len - 2); + set_nextSibling(secondlastparm, p2); + } + return start; +} + +/* ----------------------------------------------------------------------------- * ParmList_nth_parm() * * return the nth parameter (0 based) in the parameter list + * return NULL if there are not enough parameters in the list * ----------------------------------------------------------------------------- */ Parm *ParmList_nth_parm(ParmList *p, unsigned int n) { while (p) { - if (n == 0) + if (n == 0) { break; + } n--; p = nextSibling(p); } @@ -151,6 +173,21 @@ Parm *ParmList_nth_parm(ParmList *p, unsigned int n) { } /* ----------------------------------------------------------------------------- + * ParmList_variadic_parm() + * + * Return the variadic parm (last in list if it is variadic), NULL otherwise + * ----------------------------------------------------------------------------- */ + +Parm *ParmList_variadic_parm(ParmList *p) { + Parm *lastparm = 0; + while (p) { + lastparm = p; + p = nextSibling(p); + } + return lastparm && SwigType_isvariadic(Getattr(lastparm, "type")) ? lastparm : 0; +} + +/* ----------------------------------------------------------------------------- * ParmList_numrequired() * * Return number of required arguments @@ -303,10 +340,10 @@ int ParmList_has_defaultargs(ParmList *p) { * ---------------------------------------------------------------------- */ int ParmList_has_varargs(ParmList *p) { - Parm *lp = 0; + Parm *lastparm = 0; while (p) { - lp = p; + lastparm = p; p = nextSibling(p); } - return lp ? SwigType_isvarargs(Getattr(lp, "type")) : 0; + return lastparm ? SwigType_isvarargs(Getattr(lastparm, "type")) : 0; } diff --git a/Source/Swig/stype.c b/Source/Swig/stype.c index 79e011c77..6ffae7288 100644 --- a/Source/Swig/stype.c +++ b/Source/Swig/stype.c @@ -42,6 +42,7 @@ * 'p.' = Pointer (*) * 'r.' = Reference (&) * 'z.' = Rvalue reference (&&) + * 'v.' = Variadic (...) * 'a(n).' = Array of size n [n] * 'f(..,..).' = Function with arguments (args) * 'q(str).' = Qualifier, such as const or volatile (cv-qualifier) @@ -624,6 +625,12 @@ String *SwigType_str(const SwigType *s, const_String_or_char_ptr id) { Insert(result, 0, "("); Append(result, ")"); } + } else if (SwigType_isvariadic(element)) { + Insert(result, 0, "..."); + if ((forwardelement) && ((SwigType_isfunction(forwardelement) || (SwigType_isarray(forwardelement))))) { + Insert(result, 0, "("); + Append(result, ")"); + } } else if (SwigType_isarray(element)) { DOH *size; Append(result, "["); diff --git a/Source/Swig/swig.h b/Source/Swig/swig.h index b392d179d..1f406a3e6 100644 --- a/Source/Swig/swig.h +++ b/Source/Swig/swig.h @@ -129,6 +129,8 @@ extern "C" { extern SwigType *SwigType_del_reference(SwigType *t); extern SwigType *SwigType_add_rvalue_reference(SwigType *t); extern SwigType *SwigType_del_rvalue_reference(SwigType *t); + extern SwigType *SwigType_add_variadic(SwigType *t); + extern SwigType *SwigType_del_variadic(SwigType *t); extern SwigType *SwigType_add_qualifier(SwigType *t, const_String_or_char_ptr qual); extern SwigType *SwigType_del_qualifier(SwigType *t); extern SwigType *SwigType_add_function(SwigType *t, ParmList *parms); @@ -155,6 +157,7 @@ extern "C" { extern int SwigType_isreference(const SwigType *t); extern int SwigType_isreference_return(const SwigType *t); extern int SwigType_isrvalue_reference(const SwigType *t); + extern int SwigType_isvariadic(const SwigType *t); extern int SwigType_isarray(const SwigType *t); extern int SwigType_prefix_is_simple_1D_array(const SwigType *t); extern int SwigType_isfunction(const SwigType *t); diff --git a/Source/Swig/swigparm.h b/Source/Swig/swigparm.h index 77d96aef6..2d4cfb89d 100644 --- a/Source/Swig/swigparm.h +++ b/Source/Swig/swigparm.h @@ -22,7 +22,10 @@ extern Parm *CopyParm(Parm *p); extern ParmList *CopyParmList(ParmList *p); extern ParmList *CopyParmListMax(ParmList *p, int count); extern ParmList *ParmList_join(ParmList *p, ParmList *p2); -extern Parm *ParmList_nth_parm(ParmList *p, unsigned int n); +extern ParmList *ParmList_replace_last(ParmList *p, ParmList *p2); +extern Parm *ParmList_nth_parm(ParmList *p, unsigned int n); +extern Parm *ParmList_variadic_parm(ParmList *p); +extern Parm *ParmList_add_parm(ParmList *p, Parm *newparm); extern int ParmList_numrequired(ParmList *); extern int ParmList_len(ParmList *); extern int ParmList_has_defaultargs(ParmList *p); diff --git a/Source/Swig/tree.c b/Source/Swig/tree.c index 438e8b73d..1b9e83289 100644 --- a/Source/Swig/tree.c +++ b/Source/Swig/tree.c @@ -114,6 +114,10 @@ void Swig_print_node(Node *obj) { } Printf(stdout, "%-12s - \"%(escape)-0.80s%s\"\n", k, o, trunc); Delete(o); +/* + } else if (DohIsSequence(value)) { + Printf(stdout, "%-12s - %s\n", k, value); +*/ } else { Printf(stdout, "%-12s - %p\n", k, value); } diff --git a/Source/Swig/typeobj.c b/Source/Swig/typeobj.c index 088497fa5..3981418c5 100644 --- a/Source/Swig/typeobj.c +++ b/Source/Swig/typeobj.c @@ -45,6 +45,7 @@ * 'p.' = Pointer (*) * 'r.' = Reference or ref-qualifier (&) * 'z.' = Rvalue reference or ref-qualifier (&&) + * 'v.' = Variadic (...) * 'a(n).' = Array of size n [n] * 'f(..,..).' = Function with arguments (args) * 'q(str).' = Qualifier, such as const or volatile (cv-qualifier) @@ -79,6 +80,7 @@ * SwigType_add_pointer() * SwigType_add_reference() * SwigType_add_rvalue_reference() + * SwigType_add_variadic() * SwigType_add_array() * * These are used to build new types. There are also functions to undo these @@ -87,6 +89,7 @@ * SwigType_del_pointer() * SwigType_del_reference() * SwigType_del_rvalue_reference() + * SwigType_del_variadic() * SwigType_del_array() * * In addition, there are query functions @@ -94,6 +97,7 @@ * SwigType_ispointer() * SwigType_isreference() * SwigType_isrvalue_reference() + * SwigType_isvariadic() * SwigType_isarray() * * Finally, there are some data extraction functions that can be used to @@ -500,6 +504,43 @@ int SwigType_isrvalue_reference(const SwigType *t) { } /* ----------------------------------------------------------------------------- + * Variadic + * + * SwigType_add_variadic() + * SwigType_del_variadic() + * SwigType_isvariadic() + * + * Add, remove, and test if a type is a variadic. The deletion and query + * functions take into account qualifiers (if any). + * ----------------------------------------------------------------------------- */ + +SwigType *SwigType_add_variadic(SwigType *t) { + Insert(t, 0, "v."); + return t; +} + +SwigType *SwigType_del_variadic(SwigType *t) { + char *c = Char(t); + if (strncmp(c, "v.", 2)) { + printf("Fatal error: SwigType_del_variadic applied to non-variadic.\n"); + Exit(EXIT_FAILURE); + } + Delslice(t, 0, 2); + return t; +} + +int SwigType_isvariadic(const SwigType *t) { + char *c; + if (!t) + return 0; + c = Char(t); + if (strncmp(c, "v.", 2) == 0) { + return 1; + } + return 0; +} + +/* ----------------------------------------------------------------------------- * Qualifiers * * SwigType_add_qualifier() |