summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.github/workflows/ci.yml1
-rw-r--r--CHANGES.current46
-rw-r--r--Doc/Manual/CPlusPlus11.html55
-rw-r--r--Doc/Manual/Warnings.html1
-rw-r--r--Examples/test-suite/common.mk2
-rw-r--r--Examples/test-suite/cpp11_variadic_templates.i204
-rw-r--r--Examples/test-suite/python/cpp11_variadic_templates_runme.py152
-rw-r--r--Lib/lua/luarun.swg4
-rw-r--r--Source/CParse/cparse.h1
-rw-r--r--Source/CParse/parser.y169
-rw-r--r--Source/CParse/templ.c265
-rw-r--r--Source/Include/swigwarn.h2
-rw-r--r--Source/Swig/parms.c85
-rw-r--r--Source/Swig/stype.c73
-rw-r--r--Source/Swig/swig.h5
-rw-r--r--Source/Swig/swigparm.h11
-rw-r--r--Source/Swig/tree.c4
-rw-r--r--Source/Swig/typeobj.c84
18 files changed, 978 insertions, 186 deletions
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 35c6d31cb..4bdf04a48 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -187,6 +187,7 @@ jobs:
CPPSTD: c++11
- SWIGLANG: scilab
VER: '5.5.2'
+ continue-on-error: true # downloads have moved, awaiting URL redirect
- SWIGLANG: scilab
os: ubuntu-18.04 # scilab 6.0
- SWIGLANG: scilab
diff --git a/CHANGES.current b/CHANGES.current
index 6581c4073..4cdfee90c 100644
--- a/CHANGES.current
+++ b/CHANGES.current
@@ -7,6 +7,52 @@ the issue number to the end of the URL: https://github.com/swig/swig/issues/
Version 4.2.0 (in progress)
===========================
+2022-12-29: wsfulton
+ #1863 Syntax error fixes parsing more elaborate parameter pack arguments that are
+ used in function pointers, member function pointers:
+
+ template <typename... V> struct VariadicParms {
+ void ParmsFuncPtrPtr(int (*)(V*...)) {}
+ void ParmsFuncPtrPtrRef(int (*)(V*&...)) {}
+ void ParmsFuncPtrPtrRValueRef(int (*)(V*&&...)) {}
+ void ParmsFuncPtrRef(int (*)(V&...)) {}
+ void ParmsFuncPtrRValueRef(int (*)(V&&...)) {}
+
+ void ParmsMemFuncPtrPtr(int (KlassMemFuncs::*)(V*...)) {}
+ void ParmsMemFuncPtrPtrRef(int (KlassMemFuncs::*)(V*&...)) {}
+ void ParmsMemFuncPtrPtrRValueRef(int (KlassMemFuncs::*)(V*&&...)) {}
+ void ParmsMemFuncPtrRef(int (KlassMemFuncs::*)(V&...)) {}
+ void ParmsMemFuncPtrRValueRef(int (KlassMemFuncs::*)(V&&...)) {}
+ };
+
+ %template(VariadicParms0) VariadicParms<>;
+ %template(VariadicParms1) VariadicParms<A>;
+
+ Also in various other places such as within noexcept specifiers:
+
+ template<typename T, typename... Args>
+ void emplace(Args &&... args) noexcept(
+ std::is_nothrow_constructible<T, Args &&...>::value);
+
+2022-12-27: wsfulton
+ 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>;
+
+2022-12-23: wsfulton
+ #1863 Fix syntax error parsing variadic templates containing parameter pack arguments that
+ are function pointers.
+
+2022-12-22: wsfulton
+ Complete support for C++11 variadic templates. Support was previously limited
+ to just one template parameter. Now zero or more template parameters are supported.
+
2022-12-06: wsfulton
#1636 Fix syntax error for misplaced Doxygen comment after struct/class member.
Fix syntax error using Doxygen member groups syntax, "///*}", when used after
diff --git a/Doc/Manual/CPlusPlus11.html b/Doc/Manual/CPlusPlus11.html
index 50402cefd..6fdc1512a 100644
--- a/Doc/Manual/CPlusPlus11.html
+++ b/Doc/Manual/CPlusPlus11.html
@@ -1125,38 +1125,71 @@ union P {
<H3><a name="CPlusPlus11_variadic_templates">7.2.18 Variadic templates</a></H3>
-<p>SWIG supports the variadic templates syntax (inside the &lt;&gt;
-block, variadic class inheritance and variadic constructor and
-initializers) with some limitations. The following code is correctly parsed:</p>
+<p>SWIG supports the variadic templates including the &lt;&gt;
+variadic class inheritance, variadic methods, variadic constructors and
+initializers. Example:</p>
<div class="code"><pre>
template &lt;typename... BaseClasses&gt; class ClassName : public BaseClasses... {
public:
- ClassName (BaseClasses &amp;&amp;... baseClasses) : BaseClasses(baseClasses)... {}
+ ClassName(BaseClasses &amp;&amp;... baseClasses) : BaseClasses(baseClasses)... {}
+ void InstanceMethod(const BaseClasses&amp;... baseClasses) {}
};
</pre></div>
<p>
-For now however, the <tt>%template</tt> directive only accepts one parameter substitution
-for the variable template parameters.
+The <tt>%template</tt> directive works as expected for variable template parameters.
</p>
<div class="code"><pre>
-%template(MyVariant1) ClassName&lt;&gt; // zero argument not supported yet
-%template(MyVariant2) ClassName&lt;int&gt; // ok
-%template(MyVariant3) ClassName&lt;int, int&gt; // too many arguments not supported yet
+struct A {
+ virtual void amethod();
+ virtual ~A();
+};
+struct B {
+ virtual void bmethod();
+ virtual ~B();
+};
+%template(ClassName0) ClassName&lt;&gt;
+%template(ClassName1) ClassName&lt;A&gt;
+%template(ClassName2) ClassName&lt;A, B&gt;
+</pre></div>
+
+<p>
+Example usage from say Python:
+</p>
+
+<div class="targetlang"><pre>
+cn0 = ClassName0()
+cn0.InstanceMethod()
+
+a = A()
+cn1 = ClassName1(a)
+cn1.amethod()
+cn1.InstanceMethod(a)
+
+b = B()
+cn2 = ClassName2(a, b)
+cn2.InstanceMethod(a, b)
+cn2.amethod()
+cn2.bmethod()
</pre></div>
-<p>Support for the variadic <tt>sizeof()</tt> function is correctly parsed:</p>
+<p>Support for the variadic <tt>sizeof()</tt> function also works:</p>
<div class="code"><pre>
-const int SIZE = sizeof...(ClassName&lt;int, int&gt;);
+const int SIZE = sizeof...(ClassName&lt;A, B&gt;);
</pre></div>
<p>
In the above example <tt>SIZE</tt> is of course wrapped as a constant.
</p>
+<p>
+<b>Compatibility note:</b> SWIG-4.2.0 was the first version to fully support variadic templates.
+SWIG-3.0.0 provided initial support and was limited to only one variadic parameter.
+</p>
+
<H3><a name="CPlusPlus11_new_char_literals">7.2.19 New character literals</a></H3>
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..008539393 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,190 @@ 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>;
+
+%inline %{
+struct KlassMemFuncs {
+ int memfunc0() { return 0; }
+ int memfunc1() { return 1; }
+ int memfunc2() { return 2; }
+ int memfunc3() { return 3; }
+};
+template <typename... V> struct VariadicParms {
+ void ParmsVal(V... vparms_v) {}
+ void ParmsPtr(V*... vparms_p) {}
+ void ParmsPtrRef(V*&... vparms_pr) {}
+ void ParmsPtrRValueRef(V*&&... vparms_rvr) {}
+ void ParmsRef(V&... vparms_r) {}
+ void ParmsRValueRef(V&&... vparms_r) {}
+ void ParmsConstRef(const V&... vparms_cr) {}
+
+ // Conventional unnamed parameter function ptr
+ void ParmsFuncPtrVal(int (*)(V...)) {}
+ void ParmsFuncPtrPtr(int (*)(V*...)) {}
+ void ParmsFuncPtrPtrRef(int (*)(V*&...)) {}
+ void ParmsFuncPtrPtrRValueRef(int (*)(V*&&...)) {}
+ void ParmsFuncPtrRef(int (*)(V&...)) {}
+ void ParmsFuncPtrRValueRef(int (*)(V&&...)) {}
+ void ParmsFuncPtrConstRef(int (*)(const V&...)) {}
+
+ // Unconventional unnamed parameter function ptr
+ void ParmsFuncUnnamedVal(int (V...)) {}
+ void ParmsFuncUnnamedPtr(int (V*...)) {}
+ void ParmsFuncUnnamedPtrRef(int (V*&...)) {}
+ void ParmsFuncUnnamedPtrRValueRef(int (V*&&...)) {}
+ void ParmsFuncUnnamedRef(int (V&...)) {}
+ void ParmsFuncUnnamedRValueRef(int (V&&...)) {}
+ void ParmsFuncUnnamedConstRef(int (const V&...)) {}
+
+ // Unconventional named parameter function ptr
+ void ParmsFuncNamedVal(int fn(V...)) {}
+ void ParmsFuncNamedPtr(int fn(V*...)) {}
+ void ParmsFuncNamedPtrRef(int fn(V*&...)) {}
+ void ParmsFuncNamedPtrRValueRef(int fn(V*&&...)) {}
+ void ParmsFuncNamedRef(int fn(V&...)) {}
+ void ParmsFuncNamedRValueRef(int fn(V&&...)) {}
+ void ParmsFuncNamedConstRef(int fn(const V&...)) {}
+
+ // Conventional unnamed parameter member function ptr
+ void ParmsMemFuncPtrVal(int (KlassMemFuncs::*)(V...)) {}
+ void ParmsMemFuncPtrPtr(int (KlassMemFuncs::*)(V*...)) {}
+ void ParmsMemFuncPtrPtrRef(int (KlassMemFuncs::*)(V*&...)) {}
+ void ParmsMemFuncPtrPtrRValueRef(int (KlassMemFuncs::*)(V*&&...)) {}
+ void ParmsMemFuncPtrRef(int (KlassMemFuncs::*)(V&...)) {}
+ void ParmsMemFuncPtrRValueRef(int (KlassMemFuncs::*)(V&&...)) {}
+ void ParmsMemFuncPtrConstRef(int (KlassMemFuncs::*)(const V&...)) {}
+};
+%}
+
+%template(VariadicParms0) VariadicParms<>;
+%template(VariadicParms1) VariadicParms<A>;
+%template(VariadicParms2) VariadicParms<A,B>;
+%template(VariadicParms3) VariadicParms<A,B,C>;
+
+%inline %{
+template <typename... V> struct FixedAndVariadicParms {
+public:
+ void ParmsVal(short shortvar, V... vparms_v) {}
+ void ParmsPtr(short shortvar, V*... vparms_p) {}
+ void ParmsPtrRef(short shortvar, V*&... vparms_pr) {}
+ void ParmsPtrRValueRef(short shortvar, V*&&... vparms_rvr) {}
+ void ParmsRef(short shortvar, V&... vparms_r) {}
+ void ParmsRValueRef(short shortvar, V&&... vparms_r) {}
+ void ParmsConstRef(short shortvar, const V&... vparms_cr) {}
+
+ void ParmsFuncPtrVal(short shortvar, int (*)(short, V...)) {}
+ void ParmsMemFuncPtrVal(int (KlassMemFuncs::*)(V...)) {}
+};
+%}
+
+%template(FixedAndVariadicParms0) FixedAndVariadicParms<>;
+%template(FixedAndVariadicParms1) FixedAndVariadicParms<A>;
+%template(FixedAndVariadicParms2) FixedAndVariadicParms<A,B>;
+%template(FixedAndVariadicParms3) FixedAndVariadicParms<A,B,C>;
+
+// #1863
+%inline %{
+class Container {
+public:
+template<typename... Args>
+ static void notifyMyTypes(void (fn)(Args...)); // unconventional function (ptr)
+template<typename... Args>
+ static void notifyMyTypesA(void (*fn)(Args...)) {} // conventional function ptr
+template<typename... Args>
+ static void notifyMyTypesB(void fn(Args...)) {}; // unconventional function (ptr)
+};
+%}
+%{
+template<typename... Args>
+ void Container::notifyMyTypes(void (fn)(Args...)) {}
+
+// Explicit template instantiations
+template void Container::notifyMyTypes<>(void (tt)());
+template void Container::notifyMyTypes<int>(void (tt)(int));
+template void Container::notifyMyTypes<int, double>(void (tt)(int, double));
+%}
+
+// Not supported (most vexing parse), see Extending.html#Extending_nn7
+//%template(ContainerNotifyMyTypes1) Container::notifyMyTypes<int>;
+%template(ContainerNotifyMyTypesA1) Container::notifyMyTypesA<int>;
+%template(ContainerNotifyMyTypesB1) Container::notifyMyTypesB<int>;
+
+// #1863
+%inline %{
+#include <type_traits>
+class EmplaceContainer {
+public:
+template<typename T, typename... Args>
+void emplace(Args &&... args) noexcept(
+ std::is_nothrow_constructible<T, Args &&...>::value) {}
+};
+%}
+
+%template(emplace) EmplaceContainer::emplace<int,A>;
+// TODO
+//%template(emplace) EmplaceContainer::emplace<int,A,B,C>;
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/Lib/lua/luarun.swg b/Lib/lua/luarun.swg
index f47fd4fac..057361b59 100644
--- a/Lib/lua/luarun.swg
+++ b/Lib/lua/luarun.swg
@@ -87,7 +87,7 @@ typedef struct swig_elua_entry {
#endif
#if (SWIG_LUA_TARGET == SWIG_LUA_FLAVOR_ELUA) || (SWIG_LUA_TARGET == SWIG_LUA_FLAVOR_ELUAC)
-# define SWIG_LUA_CONSTTAB_INT(B, C) LSTRKEY(B), LNUMVAL(C)
+# define SWIG_LUA_CONSTTAB_INT(B, C...) LSTRKEY(B), LNUMVAL(C)
# define SWIG_LUA_CONSTTAB_FLOAT(B, C) LSTRKEY(B), LNUMVAL(C)
# define SWIG_LUA_CONSTTAB_STRING(B, C) LSTRKEY(B), LSTRVAL(C)
# define SWIG_LUA_CONSTTAB_CHAR(B, C) LSTRKEY(B), LNUMVAL(C)
@@ -103,7 +103,7 @@ typedef struct swig_elua_entry {
#define SWIG_LUA_CONSTTAB_BINARY(B, S, C, D) LSTRKEY(B), LNILVAL
#endif
#else /* SWIG_LUA_FLAVOR_LUA */
-# define SWIG_LUA_CONSTTAB_INT(B, C) SWIG_LUA_INT, (char *)B, (long)C, 0, 0, 0
+# define SWIG_LUA_CONSTTAB_INT(B, C...) SWIG_LUA_INT, (char *)B, (long)C, 0, 0, 0
# define SWIG_LUA_CONSTTAB_FLOAT(B, C) SWIG_LUA_FLOAT, (char *)B, 0, (double)C, 0, 0
# define SWIG_LUA_CONSTTAB_STRING(B, C) SWIG_LUA_STRING, (char *)B, 0, 0, (void *)C, 0
# define SWIG_LUA_CONSTTAB_CHAR(B, C) SWIG_LUA_CHAR, (char *)B, (long)C, 0, 0, 0
diff --git a/Source/CParse/cparse.h b/Source/CParse/cparse.h
index 42ce87cef..039e97de7 100644
--- a/Source/CParse/cparse.h
+++ b/Source/CParse/cparse.h
@@ -68,6 +68,7 @@ extern "C" {
extern int Swig_cparse_template_expand(Node *n, String *rname, ParmList *tparms, Symtab *tscope);
extern Node *Swig_cparse_template_locate(String *name, ParmList *tparms, String *symname, Symtab *tscope);
extern void Swig_cparse_debug_templates(int);
+ extern ParmList *Swig_cparse_template_parms_expand(ParmList *instantiated_parameters, Node *primary);
#ifdef __cplusplus
}
diff --git a/Source/CParse/parser.y b/Source/CParse/parser.y
index d723616e7..734e53a34 100644
--- a/Source/CParse/parser.y
+++ b/Source/CParse/parser.y
@@ -66,7 +66,7 @@ static String *Classprefix = 0;
static String *Namespaceprefix = 0;
static int inclass = 0;
static Node *currentOuterClass = 0; /* for nested classes */
-static const char *last_cpptype = 0;
+static String *last_cpptype = 0;
static int inherit_list = 0;
static Parm *template_parameters = 0;
static int parsing_template_declaration = 0;
@@ -1178,7 +1178,7 @@ static void update_nested_classes(Node *n)
* Create the nested class/struct/union as a forward declaration.
* ----------------------------------------------------------------------------- */
-static Node *nested_forward_declaration(const char *storage, const char *kind, String *sname, String *name, Node *cpp_opt_declarators) {
+static Node *nested_forward_declaration(const char *storage, const String *kind, String *sname, String *name, Node *cpp_opt_declarators) {
Node *nn = 0;
if (sname) {
@@ -1681,9 +1681,10 @@ static String *add_qualifier_to_declarator(SwigType *type, SwigType *qualifier)
%type <p> parm_no_dox parm valparm rawvalparms valparms valptail ;
%type <p> typemap_parm tm_list tm_tail ;
%type <p> templateparameter ;
-%type <id> templcpptype cpptype classkey classkeyopt access_specifier;
+%type <type> templcpptype cpptype classkey classkeyopt;
+%type <id> access_specifier;
%type <node> base_specifier;
-%type <str> variadic;
+%type <str> variadic_opt;
%type <type> type rawtype type_right anon_bitfield_type decltype ;
%type <bases> base_list inherit raw_inherit;
%type <dtype> definetype def_args etype default_delete deleted_definition explicit_default;
@@ -2812,11 +2813,11 @@ types_directive : TYPES LPAREN parms RPAREN stringbracesemi {
------------------------------------------------------------ */
template_directive: SWIGTEMPLATE LPAREN idstringopt RPAREN idcolonnt LESSTHAN valparms GREATERTHAN SEMI {
- Parm *p, *tp;
+ Parm *p;
Node *n;
Node *outer_class = currentOuterClass;
Symtab *tscope = 0;
- int specialized = 0;
+ int specialized = 0; /* fully specialized (an explicit specialization) */
int variadic = 0;
String *symname = $3 ? NewString($3) : 0;
@@ -2879,7 +2880,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))) {
@@ -2892,65 +2893,10 @@ template_directive: SWIGTEMPLATE LPAREN idstringopt RPAREN idcolonnt LESSTHAN va
continue;
} else {
String *tname = Copy($5);
- int def_supplied = 0;
- /* Expand the template */
- Node *templ = Swig_symbol_clookup($5,0);
- Parm *targs = templ ? Getattr(templ,"templateparms") : 0;
-
- ParmList *temparms;
- if (specialized) temparms = CopyParmList($7);
- else temparms = CopyParmList(tparms);
-
- /* Create typedef's and arguments */
- p = $7;
- tp = temparms;
- if (!p && ParmList_len(p) != ParmList_len(temparms)) {
- /* we have no template parameters supplied in %template for a template that has default args*/
- p = tp;
- def_supplied = 1;
- }
+ Node *primary_template = Swig_symbol_clookup(tname, 0);
- while (p) {
- String *value = Getattr(p,"value");
- if (def_supplied) {
- Setattr(p,"default","1");
- }
- if (value) {
- Setattr(tp,"value",value);
- } else {
- SwigType *ty = Getattr(p,"type");
- if (ty) {
- Setattr(tp,"type",ty);
- }
- Delattr(tp,"value");
- }
- /* fix default arg values */
- if (targs) {
- Parm *pi = temparms;
- Parm *ti = targs;
- String *tv = Getattr(tp,"value");
- if (!tv) tv = Getattr(tp,"type");
- while(pi != tp && ti && pi) {
- String *name = Getattr(ti,"name");
- String *value = Getattr(pi,"value");
- if (!value) value = Getattr(pi,"type");
- Replaceid(tv, name, value);
- pi = nextSibling(pi);
- ti = nextSibling(ti);
- }
- }
- p = nextSibling(p);
- tp = nextSibling(tp);
- if (!p && tp) {
- p = tp;
- def_supplied = 1;
- } else if (p && !tp) { /* Variadic template - tp < p */
- 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);
- break;
- }
- }
+ /* Expand the template */
+ ParmList *temparms = Swig_cparse_template_parms_expand($7, primary_template);
templnode = copy_node(nn);
update_nested_classes(templnode); /* update classes nested within template */
@@ -3765,7 +3711,7 @@ cpp_class_decl: storage_class cpptype idcolon class_virt_specifier_opt inherit L
Delete(fbase);
Delete(tbase);
}
- if (strcmp($2,"class") == 0) {
+ if (Strcmp($2, "class") == 0) {
cplus_mode = CPLUS_PRIVATE;
} else {
cplus_mode = CPLUS_PUBLIC;
@@ -3982,7 +3928,7 @@ cpp_class_decl: storage_class cpptype idcolon class_virt_specifier_opt inherit L
Swig_features_get(Swig_cparse_features(), Namespaceprefix, 0, 0, $<node>$);
/* save yyrename to the class attribute, to be used later in add_symbols()*/
Setattr($<node>$, "class_rename", make_name($<node>$,0,0));
- if (strcmp($2,"class") == 0) {
+ if (Strcmp($2, "class") == 0) {
cplus_mode = CPLUS_PRIVATE;
} else {
cplus_mode = CPLUS_PUBLIC;
@@ -4450,7 +4396,7 @@ template_parms : templateparameter templateparameterstail {
;
templateparameter : templcpptype def_args {
- $$ = NewParmWithoutFileLineInfo(NewString($1), 0);
+ $$ = NewParmWithoutFileLineInfo($1, 0);
Setfile($$, cparse_file);
Setline($$, cparse_line);
Setattr($$, "value", $2.rawval ? $2.rawval : $2.val);
@@ -4484,12 +4430,11 @@ 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");
}
}
}
@@ -5568,6 +5513,7 @@ declarator : pointer notso_direct_declarator {
Delete($$.type);
}
$$.type = $1;
+ SwigType_add_variadic($$.type);
}
| pointer AND ELLIPSIS notso_direct_declarator {
$$ = $4;
@@ -5577,6 +5523,7 @@ declarator : pointer notso_direct_declarator {
Delete($$.type);
}
$$.type = $1;
+ SwigType_add_variadic($$.type);
}
| pointer LAND ELLIPSIS notso_direct_declarator {
$$ = $4;
@@ -5586,15 +5533,13 @@ declarator : pointer notso_direct_declarator {
Delete($$.type);
}
$$.type = $1;
- }
- | ELLIPSIS direct_declarator {
- $$ = $2;
- if (!$$.type) $$.type = NewStringEmpty();
+ SwigType_add_variadic($$.type);
}
| AND ELLIPSIS notso_direct_declarator {
$$ = $3;
$$.type = NewStringEmpty();
SwigType_add_reference($$.type);
+ SwigType_add_variadic($$.type);
if ($3.type) {
SwigType_push($$.type,$3.type);
Delete($3.type);
@@ -5606,6 +5551,7 @@ declarator : pointer notso_direct_declarator {
$$ = $3;
$$.type = NewStringEmpty();
SwigType_add_rvalue_reference($$.type);
+ SwigType_add_variadic($$.type);
if ($3.type) {
SwigType_push($$.type,$3.type);
Delete($3.type);
@@ -5616,6 +5562,7 @@ declarator : pointer notso_direct_declarator {
$$ = $4;
SwigType_add_memberpointer(t,$1);
+ SwigType_add_variadic(t);
if ($$.type) {
SwigType_push(t,$$.type);
Delete($$.type);
@@ -5626,6 +5573,7 @@ declarator : pointer notso_direct_declarator {
SwigType *t = NewStringEmpty();
$$ = $5;
SwigType_add_memberpointer(t,$2);
+ SwigType_add_variadic(t);
SwigType_push($1,t);
if ($$.type) {
SwigType_push($1,$$.type);
@@ -5638,6 +5586,7 @@ declarator : pointer notso_direct_declarator {
$$ = $6;
SwigType_add_memberpointer($1,$2);
SwigType_add_reference($1);
+ SwigType_add_variadic($1);
if ($$.type) {
SwigType_push($1,$$.type);
Delete($$.type);
@@ -5648,6 +5597,7 @@ declarator : pointer notso_direct_declarator {
$$ = $6;
SwigType_add_memberpointer($1,$2);
SwigType_add_rvalue_reference($1);
+ SwigType_add_variadic($1);
if ($$.type) {
SwigType_push($1,$$.type);
Delete($$.type);
@@ -5659,6 +5609,7 @@ declarator : pointer notso_direct_declarator {
$$ = $5;
SwigType_add_memberpointer(t,$1);
SwigType_add_reference(t);
+ SwigType_add_variadic(t);
if ($$.type) {
SwigType_push(t,$$.type);
Delete($$.type);
@@ -5670,6 +5621,7 @@ declarator : pointer notso_direct_declarator {
$$ = $5;
SwigType_add_memberpointer(t,$1);
SwigType_add_rvalue_reference(t);
+ SwigType_add_variadic(t);
if ($$.type) {
SwigType_push(t,$$.type);
Delete($$.type);
@@ -5925,11 +5877,12 @@ direct_declarator : idcolon {
}
;
-abstract_declarator : pointer {
+abstract_declarator : pointer variadic_opt {
$$.type = $1;
$$.id = 0;
$$.parms = 0;
$$.have_parms = 0;
+ if ($2) SwigType_add_variadic($$.type);
}
| pointer direct_abstract_declarator {
$$ = $2;
@@ -5937,19 +5890,21 @@ abstract_declarator : pointer {
$$.type = $1;
Delete($2.type);
}
- | pointer AND {
+ | pointer AND variadic_opt {
$$.type = $1;
SwigType_add_reference($$.type);
$$.id = 0;
$$.parms = 0;
$$.have_parms = 0;
+ if ($3) SwigType_add_variadic($$.type);
}
- | pointer LAND {
+ | pointer LAND variadic_opt {
$$.type = $1;
SwigType_add_rvalue_reference($$.type);
$$.id = 0;
$$.parms = 0;
$$.have_parms = 0;
+ if ($3) SwigType_add_variadic($$.type);
}
| pointer AND direct_abstract_declarator {
$$ = $3;
@@ -5990,19 +5945,21 @@ abstract_declarator : pointer {
Delete($2.type);
}
}
- | AND {
+ | AND variadic_opt {
$$.id = 0;
$$.parms = 0;
$$.have_parms = 0;
$$.type = NewStringEmpty();
SwigType_add_reference($$.type);
+ if ($2) SwigType_add_variadic($$.type);
}
- | LAND {
+ | LAND variadic_opt {
$$.id = 0;
$$.parms = 0;
$$.have_parms = 0;
$$.type = NewStringEmpty();
SwigType_add_rvalue_reference($$.type);
+ if ($2) SwigType_add_variadic($$.type);
}
| idcolon DSTAR {
$$.type = NewStringEmpty();
@@ -6203,7 +6160,9 @@ rawtype : type_qualifier type_right {
$$ = $2;
SwigType_push($$,$1);
}
- | type_right { $$ = $1; }
+ | type_right {
+ $$ = $1;
+ }
| type_right type_qualifier {
$$ = $1;
SwigType_push($$,$2);
@@ -6213,6 +6172,10 @@ rawtype : type_qualifier type_right {
SwigType_push($$,$3);
SwigType_push($$,$1);
}
+ | rawtype ELLIPSIS {
+ $$ = $1;
+ SwigType_add_variadic($$);
+ }
;
type_right : primitive_type { $$ = $1;
@@ -6920,7 +6883,7 @@ exprcompound : expr PLUS expr {
}
;
-variadic : ELLIPSIS {
+variadic_opt : ELLIPSIS {
$$ = NewString("...");
}
| empty {
@@ -6965,7 +6928,7 @@ base_list : base_specifier {
base_specifier : opt_virtual {
$<intvalue>$ = cparse_line;
- } idcolon variadic {
+ } idcolon variadic_opt {
$$ = NewHash();
Setfile($$,cparse_file);
Setline($$,$<intvalue>2);
@@ -6978,12 +6941,13 @@ base_specifier : opt_virtual {
} else {
Setattr($$,"access","public");
}
- if ($4)
- SetFlag($$, "variadic");
+ if ($4) {
+ SwigType_add_variadic(Getattr($$, "name"));
+ }
}
| opt_virtual access_specifier {
$<intvalue>$ = cparse_line;
- } opt_virtual idcolon variadic {
+ } opt_virtual idcolon variadic_opt {
$$ = NewHash();
Setfile($$,cparse_file);
Setline($$,$<intvalue>3);
@@ -6994,8 +6958,9 @@ 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)
- SetFlag($$, "variadic");
+ if ($6) {
+ SwigType_add_variadic(Getattr($$, "name"));
+ }
}
;
@@ -7004,47 +6969,41 @@ access_specifier : PUBLIC { $$ = (char*)"public"; }
| PROTECTED { $$ = (char*)"protected"; }
;
-templcpptype : CLASS {
- $$ = (char*)"class";
+templcpptype : CLASS variadic_opt {
+ $$ = NewString("class");
if (!inherit_list) last_cpptype = $$;
+ if ($2) SwigType_add_variadic($$);
}
- | TYPENAME {
- $$ = (char *)"typename";
- if (!inherit_list) last_cpptype = $$;
- }
- | CLASS ELLIPSIS {
- $$ = (char *)"class...";
- if (!inherit_list) last_cpptype = $$;
- }
- | TYPENAME ELLIPSIS {
- $$ = (char *)"typename...";
+ | TYPENAME variadic_opt {
+ $$ = NewString("typename");
if (!inherit_list) last_cpptype = $$;
+ if ($2) SwigType_add_variadic($$);
}
;
cpptype : templcpptype {
$$ = $1;
}
- | STRUCT {
- $$ = (char*)"struct";
+ | STRUCT {
+ $$ = NewString("struct");
if (!inherit_list) last_cpptype = $$;
}
| UNION {
- $$ = (char*)"union";
+ $$ = NewString("union");
if (!inherit_list) last_cpptype = $$;
}
;
classkey : CLASS {
- $$ = (char*)"class";
+ $$ = NewString("class");
if (!inherit_list) last_cpptype = $$;
}
| STRUCT {
- $$ = (char*)"struct";
+ $$ = NewString("struct");
if (!inherit_list) last_cpptype = $$;
}
| UNION {
- $$ = (char*)"union";
+ $$ = NewString("union");
if (!inherit_list) last_cpptype = $$;
}
;
diff --git a/Source/CParse/templ.c b/Source/CParse/templ.c
index b02df8d05..1eeb91774 100644
--- a/Source/CParse/templ.c
+++ b/Source/CParse/templ.c
@@ -25,6 +25,16 @@ void SwigType_template_init(void) {
baselists[2] = "privatebaselist";
}
+void Swig_cparse_debug_templates(int x) {
+ template_debug = x;
+}
+
+/* -----------------------------------------------------------------------------
+ * 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) {
@@ -44,8 +54,57 @@ static void add_parms(ParmList *p, List *patchlist, List *typelist, int is_patte
}
}
-void Swig_cparse_debug_templates(int x) {
- template_debug = x;
+/* -----------------------------------------------------------------------------
+ * 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);
+ 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);
+ 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);
}
/* -----------------------------------------------------------------------------
@@ -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);
}
}
@@ -176,12 +254,11 @@ 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"));
- 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. */
@@ -204,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")) {
@@ -222,13 +298,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);
}
}
@@ -322,8 +398,7 @@ static void cparse_postprocess_expanded_template(Node *n) {
* partial_arg()
* ----------------------------------------------------------------------------- */
-static
-String *partial_arg(String *s, String *p) {
+static String *partial_arg(String *s, String *p) {
char *c;
char *cp = Char(p);
String *prefix;
@@ -352,18 +427,14 @@ int Swig_cparse_template_expand(Node *n, String *rname, ParmList *tparms, Symtab
String *tname;
String *iname;
String *tbase;
- patchlist = NewList();
- cpatchlist = NewList();
- typelist = NewList();
+ Parm *unexpanded_variadic_parm = 0;
+ ParmList *expanded_variadic_parms = 0;
+ patchlist = NewList(); /* List of String * ("name" and "value" attributes) */
+ cpatchlist = NewList(); /* List of String * (code) */
+ typelist = NewList(); /* List of SwigType * types */
- {
- 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);
@@ -401,10 +472,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 */
{
@@ -421,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) {
@@ -464,15 +540,23 @@ 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);
SwigType_typename_replace(s, tbase, iname);
@@ -505,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);
}
}
@@ -1005,3 +1091,110 @@ Node *Swig_cparse_template_locate(String *name, Parm *tparms, String *symname, S
return n;
}
+
+/* -----------------------------------------------------------------------------
+ * merge_parameters()
+ *
+ * expanded_templateparms are the template parameters passed to %template.
+ * This function adds missing parameter name and type attributes from the chosen
+ * template (templateparms).
+ *
+ * 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 int merge_parameters(ParmList *expanded_templateparms, ParmList *templateparms) {
+ Parm *p = expanded_templateparms;
+ Parm *tp = templateparms;
+ while (p && tp) {
+ Setattr(p, "name", Getattr(tp, "name"));
+ if (!Getattr(p, "type"))
+ Setattr(p, "type", Getattr(tp, "type"));
+ p = nextSibling(p);
+ tp = nextSibling(tp);
+ }
+ return ParmList_variadic_parm(templateparms) ? 1 : 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * mark_defaults()
+ *
+ * Mark all the template parameters that are expanded from a default value
+ * ----------------------------------------------------------------------------- */
+
+static void mark_defaults(ParmList *defaults) {
+ Parm *tp = defaults;
+ while (tp) {
+ Setattr(tp, "default", "1");
+ tp = nextSibling(tp);
+ }
+}
+
+/* -----------------------------------------------------------------------------
+ * expand_defaults()
+ *
+ * Replace parameter types in default argument values, example:
+ * input: int K,int T,class C=Less<(K)>
+ * output: int K,int T,class C=Less<(int)>
+ * ----------------------------------------------------------------------------- */
+
+static void expand_defaults(ParmList *expanded_templateparms) {
+ Parm *tp = expanded_templateparms;
+ while (tp) {
+ Parm *p = expanded_templateparms;
+ String *tv = Getattr(tp, "value");
+ if (!tv)
+ tv = Getattr(tp, "type");
+ while(p) {
+ String *name = Getattr(p, "name");
+ String *value = Getattr(p, "value");
+ if (!value)
+ value = Getattr(p, "type");
+ if (name)
+ Replaceid(tv, name, value);
+ p = nextSibling(p);
+ }
+ tp = nextSibling(tp);
+ }
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_cparse_template_parms_expand()
+ *
+ * instantiated_parameters: template parameters passed to %template
+ * primary: primary template node
+ *
+ * Expand the instantiated_parameters and return a parameter list with default
+ * arguments filled in where necessary.
+ * ----------------------------------------------------------------------------- */
+
+ParmList *Swig_cparse_template_parms_expand(ParmList *instantiated_parameters, Node *primary) {
+ ParmList *expanded_templateparms = 0;
+ ParmList *templateparms = Getattr(primary, "templateparms");
+
+ if (Equal(Getattr(primary, "templatetype"), "class")) {
+ /* Templated class */
+ expanded_templateparms = CopyParmList(instantiated_parameters);
+ 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 */
+ /* TODO: Default template parameters support was only added in C++11 */
+ expanded_templateparms = CopyParmList(instantiated_parameters);
+ merge_parameters(expanded_templateparms, templateparms);
+ }
+
+ 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 11071ce0c..3e052ca0c 100644
--- a/Source/Swig/parms.c
+++ b/Source/Swig/parms.c
@@ -113,7 +113,84 @@ ParmList *CopyParmList(ParmList *p) {
}
/* -----------------------------------------------------------------------------
- * int ParmList_numrequired(). Return number of required arguments
+ * ParmList_join()
+ *
+ * Join two parameter lists. Appends p2 to the end of p.
+ * No copies are made.
+ * Returns start of joined parameter list.
+ * ----------------------------------------------------------------------------- */
+
+ParmList *ParmList_join(ParmList *p, ParmList *p2) {
+ Parm *firstparm = p ? p : p2;
+ Parm *lastparm = 0;
+ while (p) {
+ lastparm = p;
+ p = nextSibling(p);
+ }
+ if (lastparm)
+ set_nextSibling(lastparm, p2);
+
+ return firstparm;
+}
+
+/* -----------------------------------------------------------------------------
+ * 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) {
+ break;
+ }
+ n--;
+ p = nextSibling(p);
+ }
+ return p;
+}
+
+/* -----------------------------------------------------------------------------
+ * 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
* ----------------------------------------------------------------------------- */
int ParmList_numrequired(ParmList *p) {
@@ -263,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..c925774e5 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, "[");
@@ -1386,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 b392d179d..4b02a8101 100644
--- a/Source/Swig/swig.h
+++ b/Source/Swig/swig.h
@@ -129,12 +129,15 @@ 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);
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);
@@ -155,6 +158,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);
@@ -184,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/swigparm.h b/Source/Swig/swigparm.h
index 7b63546ec..2d4cfb89d 100644
--- a/Source/Swig/swigparm.h
+++ b/Source/Swig/swigparm.h
@@ -19,10 +19,15 @@ extern Parm *NewParmNode(SwigType *type, Node *from_node);
extern Parm *CopyParm(Parm *p);
/* Parameter lists */
-extern ParmList *CopyParmList(ParmList *);
-extern ParmList *CopyParmListMax(ParmList *, int count);
-extern int ParmList_len(ParmList *);
+extern ParmList *CopyParmList(ParmList *p);
+extern ParmList *CopyParmListMax(ParmList *p, int count);
+extern ParmList *ParmList_join(ParmList *p, ParmList *p2);
+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);
extern int ParmList_has_varargs(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..d07de6e3d 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
@@ -283,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) {
@@ -308,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
@@ -316,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;
@@ -500,6 +505,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()
@@ -823,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;
}