diff options
author | William S Fulton <wsf@fultondesigns.co.uk> | 2022-11-02 19:57:02 +0000 |
---|---|---|
committer | William S Fulton <wsf@fultondesigns.co.uk> | 2022-11-05 17:27:23 +0000 |
commit | ab6cc6da4929545baa00eb8a07aa3949d9dcd38c (patch) | |
tree | f8b70c116aa6384b5faae8aacb535712dd838524 | |
parent | cac363270325768283c4a75d90f948cef00f6fb3 (diff) | |
download | swig-ab6cc6da4929545baa00eb8a07aa3949d9dcd38c.tar.gz |
Fix infinite loop handling non-type template parameters
Fixes infinite loop due to () brackets in a non-type template
parameter containing an expression
Fixes #2418
Non-trivial expressions are still not qualified properly though.
-rw-r--r-- | CHANGES.current | 6 | ||||
-rw-r--r-- | Examples/test-suite/common.mk | 1 | ||||
-rw-r--r-- | Examples/test-suite/cpp14_enable_if_t.i | 34 | ||||
-rw-r--r-- | Examples/test-suite/java/cpp14_enable_if_t_runme.java | 19 | ||||
-rw-r--r-- | Source/Swig/symbol.c | 11 | ||||
-rw-r--r-- | Source/Swig/typesys.c | 1 |
6 files changed, 69 insertions, 3 deletions
diff --git a/CHANGES.current b/CHANGES.current index 83a1e20a9..8678b86c1 100644 --- a/CHANGES.current +++ b/CHANGES.current @@ -50,3 +50,9 @@ Version 4.1.1 (in progress) shown into the user interface file will provide the appropriate fix and the warning will disappear. This is important to do as swig-4.2 will not be able to provide this helpful warning. + +2022-11-02: wsfulton + #2418 Fix infinite loop handling non-type template parameters. + + Fixes infinite loop due to () brackets in a non-type template + parameter containing an expression. diff --git a/Examples/test-suite/common.mk b/Examples/test-suite/common.mk index 4681571e2..c52a74dd3 100644 --- a/Examples/test-suite/common.mk +++ b/Examples/test-suite/common.mk @@ -639,6 +639,7 @@ CPP11_TEST_BROKEN = \ # C++14 test cases. CPP14_TEST_CASES += \ cpp14_binary_integer_literals \ + cpp14_enable_if_t \ # Broken C++14 test cases. CPP14_TEST_BROKEN = \ diff --git a/Examples/test-suite/cpp14_enable_if_t.i b/Examples/test-suite/cpp14_enable_if_t.i new file mode 100644 index 000000000..a2e483380 --- /dev/null +++ b/Examples/test-suite/cpp14_enable_if_t.i @@ -0,0 +1,34 @@ +%module cpp14_enable_if_t + +// test use of enable_if_t but without full %template instantiation, that is no enable_if_t definition is parsed + +%inline %{ +#include <type_traits> +typedef int node_t; +typedef int position_t; + +template <typename A, typename B, std::enable_if_t<std::is_integral_v<A>, bool> = true> + void enableif1(const A a, const B b) {} + +// tests non-type template parameters within () brackets - was causing an infinite loop, issue #2418 +template <typename A, typename B, std::enable_if_t<(std::is_integral_v<A>), bool> = true> + void enableif2(const A a, const B b) {} + +template <typename A, typename B, std::enable_if_t<(std::is_integral_v<A> || std::is_same_v<A, node_t>), bool> = true> + void enableif3(const A a, const B b) {} + +template <typename A, typename B, std::enable_if_t<(std::is_integral_v<A> or std::is_same_v<A, node_t>) and (std::is_integral_v<B> or std::is_same_v<B, position_t>), bool> = true> + void enableif4(const A a, const B b) {} + +template <typename A, typename B, std::enable_if_t<(std::is_integral_v<A> and std::is_integral_v<B>), bool> = true> + int enableif5(const A a, const B b) { + return a + b; + } + +void tester() { + enableif5<int, int>(10, 20); +} +%} + +// non-type template parameters working well in SWIG, below is a simple workaround as the 3rd parameter is defaulted for enable_if_t (which is just SFINAE to give a nice C++ compiler error) +%template(enableif5) enableif5<int, int, true>; // workaround diff --git a/Examples/test-suite/java/cpp14_enable_if_t_runme.java b/Examples/test-suite/java/cpp14_enable_if_t_runme.java new file mode 100644 index 000000000..ade061be3 --- /dev/null +++ b/Examples/test-suite/java/cpp14_enable_if_t_runme.java @@ -0,0 +1,19 @@ +import cpp14_enable_if_t.*; + +public class cpp14_enable_if_t_runme { + + static { + try { + System.loadLibrary("cpp14_enable_if_t"); + } catch (UnsatisfiedLinkError e) { + System.err.println("Native code library failed to load. See the chapter on Dynamic Linking Problems in the SWIG Java documentation for help.\n" + e); + System.exit(1); + } + } + + public static void main(String argv[]) + { + if (cpp14_enable_if_t.enableif5(10, 20) != 30) + throw new RuntimeException("enableif5 not working"); + } +} diff --git a/Source/Swig/symbol.c b/Source/Swig/symbol.c index d39696f5b..107b1caef 100644 --- a/Source/Swig/symbol.c +++ b/Source/Swig/symbol.c @@ -1518,7 +1518,8 @@ Node *Swig_symbol_isoverloaded(Node *n) { static SwigType *symbol_template_qualify(const SwigType *e, Symtab *st) { String *tprefix, *tsuffix; SwigType *qprefix; - List *targs; + String *targs; + List *targslist; Node *tempn; Symtab *tscope; Iterator ti; @@ -1541,12 +1542,15 @@ static SwigType *symbol_template_qualify(const SwigType *e, Symtab *st) { tprefix = SwigType_templateprefix(e); tsuffix = SwigType_templatesuffix(e); qprefix = Swig_symbol_type_qualify(tprefix, st); - targs = SwigType_parmlist(e); + targs = SwigType_templateargs(e); + targslist = SwigType_parmlist(targs); tempn = Swig_symbol_clookup_local(tprefix, st); tscope = tempn ? Getattr(tempn, "sym:symtab") : 0; Append(qprefix, "<("); - for (ti = First(targs); ti.item;) { + for (ti = First(targslist); ti.item;) { String *vparm; + /* TODO: the logic here should be synchronised with that in SwigType_typedef_qualified() */ + /* TODO: ti.item might be a non-type parameter possibly within (), eg: (std::is_integral_v<(A)>||std::is_same_v<(A,node_t)>) */ String *qparm = Swig_symbol_type_qualify(ti.item, st); if (tscope && (tscope != st)) { String *ty = Swig_symbol_type_qualify(qparm, tscope); @@ -1568,6 +1572,7 @@ static SwigType *symbol_template_qualify(const SwigType *e, Symtab *st) { Delete(tprefix); Delete(tsuffix); Delete(targs); + Delete(targslist); #ifdef SWIG_DEBUG Printf(stderr, "symbol_temp_qual %s %s\n", e, qprefix); #endif diff --git a/Source/Swig/typesys.c b/Source/Swig/typesys.c index 74384f860..4a11790c7 100644 --- a/Source/Swig/typesys.c +++ b/Source/Swig/typesys.c @@ -1148,6 +1148,7 @@ SwigType *SwigType_typedef_qualified(const SwigType *t) { Append(qprefix, "<("); pi = First(parms); while ((p = pi.item)) { + /* TODO: the logic here should be synchronised with that in symbol_template_qualify() in symbol.c */ String *qt = SwigType_typedef_qualified(p); if (Equal(qt, p)) { /* && (!Swig_scopename_check(qt))) */ /* No change in value. It is entirely possible that the parameter is an integer value. |