summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWilliam S Fulton <wsf@fultondesigns.co.uk>2022-11-02 19:57:02 +0000
committerWilliam S Fulton <wsf@fultondesigns.co.uk>2022-11-05 17:27:23 +0000
commitab6cc6da4929545baa00eb8a07aa3949d9dcd38c (patch)
treef8b70c116aa6384b5faae8aacb535712dd838524
parentcac363270325768283c4a75d90f948cef00f6fb3 (diff)
downloadswig-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.current6
-rw-r--r--Examples/test-suite/common.mk1
-rw-r--r--Examples/test-suite/cpp14_enable_if_t.i34
-rw-r--r--Examples/test-suite/java/cpp14_enable_if_t_runme.java19
-rw-r--r--Source/Swig/symbol.c11
-rw-r--r--Source/Swig/typesys.c1
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.