diff options
-rw-r--r-- | .github/workflows/ci.yml | 1 | ||||
-rw-r--r-- | CHANGES.current | 46 | ||||
-rw-r--r-- | Doc/Manual/CPlusPlus11.html | 55 | ||||
-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 | 204 | ||||
-rw-r--r-- | Examples/test-suite/python/cpp11_variadic_templates_runme.py | 152 | ||||
-rw-r--r-- | Lib/lua/luarun.swg | 4 | ||||
-rw-r--r-- | Source/CParse/cparse.h | 1 | ||||
-rw-r--r-- | Source/CParse/parser.y | 169 | ||||
-rw-r--r-- | Source/CParse/templ.c | 265 | ||||
-rw-r--r-- | Source/Include/swigwarn.h | 2 | ||||
-rw-r--r-- | Source/Swig/parms.c | 85 | ||||
-rw-r--r-- | Source/Swig/stype.c | 73 | ||||
-rw-r--r-- | Source/Swig/swig.h | 5 | ||||
-rw-r--r-- | Source/Swig/swigparm.h | 11 | ||||
-rw-r--r-- | Source/Swig/tree.c | 4 | ||||
-rw-r--r-- | Source/Swig/typeobj.c | 84 |
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 <> -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 <> +variadic class inheritance, variadic methods, variadic constructors and +initializers. Example:</p> <div class="code"><pre> template <typename... BaseClasses> class ClassName : public BaseClasses... { public: - ClassName (BaseClasses &&... baseClasses) : BaseClasses(baseClasses)... {} + ClassName(BaseClasses &&... baseClasses) : BaseClasses(baseClasses)... {} + void InstanceMethod(const BaseClasses&... 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<> // zero argument not supported yet -%template(MyVariant2) ClassName<int> // ok -%template(MyVariant3) ClassName<int, int> // too many arguments not supported yet +struct A { + virtual void amethod(); + virtual ~A(); +}; +struct B { + virtual void bmethod(); + virtual ~B(); +}; +%template(ClassName0) ClassName<> +%template(ClassName1) ClassName<A> +%template(ClassName2) ClassName<A, B> +</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<int, int>); +const int SIZE = sizeof...(ClassName<A, B>); </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; } |