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.
This commit is contained in:
parent
973590ff91
commit
52edda64c1
6 changed files with 69 additions and 3 deletions
|
|
@ -50,3 +50,9 @@ Version 4.2.0 (in progress)
|
||||||
shown into the user interface file will provide the appropriate fix and
|
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
|
the warning will disappear. This is important to do as swig-4.2 will
|
||||||
not be able to provide this helpful warning.
|
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.
|
||||||
|
|
|
||||||
|
|
@ -639,6 +639,7 @@ CPP11_TEST_BROKEN = \
|
||||||
# C++14 test cases.
|
# C++14 test cases.
|
||||||
CPP14_TEST_CASES += \
|
CPP14_TEST_CASES += \
|
||||||
cpp14_binary_integer_literals \
|
cpp14_binary_integer_literals \
|
||||||
|
cpp14_enable_if_t \
|
||||||
|
|
||||||
# Broken C++14 test cases.
|
# Broken C++14 test cases.
|
||||||
CPP14_TEST_BROKEN = \
|
CPP14_TEST_BROKEN = \
|
||||||
|
|
|
||||||
34
Examples/test-suite/cpp14_enable_if_t.i
Normal file
34
Examples/test-suite/cpp14_enable_if_t.i
Normal file
|
|
@ -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
|
||||||
19
Examples/test-suite/java/cpp14_enable_if_t_runme.java
Normal file
19
Examples/test-suite/java/cpp14_enable_if_t_runme.java
Normal file
|
|
@ -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");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1518,7 +1518,8 @@ Node *Swig_symbol_isoverloaded(Node *n) {
|
||||||
static SwigType *symbol_template_qualify(const SwigType *e, Symtab *st) {
|
static SwigType *symbol_template_qualify(const SwigType *e, Symtab *st) {
|
||||||
String *tprefix, *tsuffix;
|
String *tprefix, *tsuffix;
|
||||||
SwigType *qprefix;
|
SwigType *qprefix;
|
||||||
List *targs;
|
String *targs;
|
||||||
|
List *targslist;
|
||||||
Node *tempn;
|
Node *tempn;
|
||||||
Symtab *tscope;
|
Symtab *tscope;
|
||||||
Iterator ti;
|
Iterator ti;
|
||||||
|
|
@ -1541,12 +1542,15 @@ static SwigType *symbol_template_qualify(const SwigType *e, Symtab *st) {
|
||||||
tprefix = SwigType_templateprefix(e);
|
tprefix = SwigType_templateprefix(e);
|
||||||
tsuffix = SwigType_templatesuffix(e);
|
tsuffix = SwigType_templatesuffix(e);
|
||||||
qprefix = Swig_symbol_type_qualify(tprefix, st);
|
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);
|
tempn = Swig_symbol_clookup_local(tprefix, st);
|
||||||
tscope = tempn ? Getattr(tempn, "sym:symtab") : 0;
|
tscope = tempn ? Getattr(tempn, "sym:symtab") : 0;
|
||||||
Append(qprefix, "<(");
|
Append(qprefix, "<(");
|
||||||
for (ti = First(targs); ti.item;) {
|
for (ti = First(targslist); ti.item;) {
|
||||||
String *vparm;
|
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);
|
String *qparm = Swig_symbol_type_qualify(ti.item, st);
|
||||||
if (tscope && (tscope != st)) {
|
if (tscope && (tscope != st)) {
|
||||||
String *ty = Swig_symbol_type_qualify(qparm, tscope);
|
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(tprefix);
|
||||||
Delete(tsuffix);
|
Delete(tsuffix);
|
||||||
Delete(targs);
|
Delete(targs);
|
||||||
|
Delete(targslist);
|
||||||
#ifdef SWIG_DEBUG
|
#ifdef SWIG_DEBUG
|
||||||
Printf(stderr, "symbol_temp_qual %s %s\n", e, qprefix);
|
Printf(stderr, "symbol_temp_qual %s %s\n", e, qprefix);
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -1148,6 +1148,7 @@ SwigType *SwigType_typedef_qualified(const SwigType *t) {
|
||||||
Append(qprefix, "<(");
|
Append(qprefix, "<(");
|
||||||
pi = First(parms);
|
pi = First(parms);
|
||||||
while ((p = pi.item)) {
|
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);
|
String *qt = SwigType_typedef_qualified(p);
|
||||||
if (Equal(qt, p)) { /* && (!Swig_scopename_check(qt))) */
|
if (Equal(qt, p)) { /* && (!Swig_scopename_check(qt))) */
|
||||||
/* No change in value. It is entirely possible that the parameter is an integer value.
|
/* No change in value. It is entirely possible that the parameter is an integer value.
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue