Constructors and destructors declared with template parameters

Recent commits for internal constructor and destructor names resulted
in destructors declared with template parameters being ignored
with warnings like:
  Illegal destructor name TemplPublicBase6< int >::~TemplPublicBase6(). Ignored.

Although declaring constructors and destructors with template parameters
are rejected by modern compilers and C++20, SWIG continues to support it.

Make sure the name stored in the parse tree is the C++20 compliant name
name, that is, without the template parameters.

Fixes using declarations for templated constructors declared with
template parameters, was warning with:
  Nothing known about 'TemplPublicBase6< int >::TemplPublicBase6'.
This commit is contained in:
William S Fulton 2023-07-18 18:47:21 +01:00
parent 0830c96e1b
commit 2ff9da0ce6
7 changed files with 88 additions and 11 deletions

View File

@ -1,5 +1,7 @@
%module cpp11_using_constructor
// Note: this testcase is also used by cpp11_director_using_constructor.i
%inline %{
// Public base constructors
struct PublicBase1 {
@ -406,6 +408,22 @@ struct TemplPublicBase5 {
// implicit constructor
virtual void meth() {}
};
template<typename T>
struct TemplPublicBase6 {
#ifdef SWIG
// Destructor and constructor declared with template parameters (not allowed in C++20 and later though)
virtual ~TemplPublicBase6<T>() {}
TemplPublicBase6<T>(T i, const char* s) {}
TemplPublicBase6<T>() = default;
#else
virtual ~TemplPublicBase6() {}
TemplPublicBase6(T i, const char* s) {}
TemplPublicBase6() = default;
#endif
virtual void meth() {}
};
%}
%template(TemplPublicBase1Int) TemplPublicBase1<int>;
@ -413,6 +431,7 @@ struct TemplPublicBase5 {
%template(TemplPublicBase3Int) TemplPublicBase3<int>;
%template(TemplPublicBase4Int) TemplPublicBase4<int>;
%template(TemplPublicBase5Int) TemplPublicBase5<int>;
%template(TemplPublicBase6Int) TemplPublicBase6<int>;
%inline %{
template<typename T>
@ -440,6 +459,11 @@ struct TemplPublicDerived5 : TemplPublicBase5<T> {
using TemplPublicBase5<T>::TemplPublicBase5;
using TemplPublicBase5<T>::meth;
};
template<typename T>
struct TemplPublicDerived6 : TemplPublicBase6<T> {
using TemplPublicBase6<T>::TemplPublicBase6;
using TemplPublicBase6<T>::meth;
};
%}
%template(TemplPublicDerived1Int) TemplPublicDerived1<int>;
@ -447,3 +471,4 @@ struct TemplPublicDerived5 : TemplPublicBase5<T> {
%template(TemplPublicDerived3Int) TemplPublicDerived3<int>;
%template(TemplPublicDerived4Int) TemplPublicDerived4<int>;
%template(TemplPublicDerived5Int) TemplPublicDerived5<int>;
%template(TemplPublicDerived6Int) TemplPublicDerived6<int>;

View File

@ -127,6 +127,8 @@ public class cpp11_director_using_constructor_runme {
new TemplPublicDerived3Int(0, "hi").meth();
new TemplPublicDerived4Int().meth();
new TemplPublicDerived5Int().meth();
new TemplPublicDerived6Int(0, "hi").meth();
new TemplPublicDerived6Int().meth();
}
//

View File

@ -125,5 +125,7 @@ public class cpp11_using_constructor_runme {
new TemplPublicDerived3Int(0, "hi").meth();
new TemplPublicDerived4Int().meth();
new TemplPublicDerived5Int().meth();
new TemplPublicDerived6Int(0, "hi").meth();
new TemplPublicDerived6Int().meth();
}
}

View File

@ -0,0 +1,24 @@
import template_construct.*;
public class template_construct_runme {
static {
try {
System.loadLibrary("template_construct");
} 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[]) {
Foo_int fi = new Foo_int(0);
fi.delete();
Foo_short fs = new Foo_short();
fs.delete();
fs = new Foo_short();
fs.delete();
}
}

View File

@ -113,3 +113,5 @@ TemplPublicDerived3Int().meth()
TemplPublicDerived3Int(0, "hi").meth()
TemplPublicDerived4Int().meth()
TemplPublicDerived5Int().meth()
TemplPublicDerived6Int(0, "hi").meth()
TemplPublicDerived6Int().meth()

View File

@ -1,21 +1,43 @@
%module template_construct
// Tests templates to make sure an extra <> in a constructor is ok.
// Tests templates to make sure an extra <> in a constructor and destructor is ok.
%inline %{
template<class T>
template<class T>
class Foo {
T y;
public:
#ifdef SWIG
Foo<T>(T x) : y(x) { }
~Foo<T>() {}
#else
// Modern compilers reject this, so feed the compiler the corrected
// version.
// Modern compilers (C++20) reject this, so feed the compiler the corrected version
Foo(T x) : y(x) { }
~Foo() {}
#endif
};
%}
%template(Foo_int) Foo<int>;
%inline %{
template<>
class Foo<short> {
short y;
public:
#ifdef SWIG
Foo<short>(short x) : y(x) { }
Foo<short>() : y(0) { }
virtual ~Foo<short>() {}
#else
// Modern compilers (C++20) reject this, so feed the compiler the corrected version
// version.
Foo(short x) : y(x) { }
Foo() : y(0) { }
virtual ~Foo() {}
#endif
};
%}
%template(Foo_short) Foo<short>;

View File

@ -4769,10 +4769,11 @@ cpp_member : cpp_member_no_dox
cpp_constructor_decl : storage_class type LPAREN parms RPAREN ctor_end {
if (inclass || extendmode) {
String *name = SwigType_templateprefix($2); /* A constructor can optionally be declared with template parameters before C++20, strip these off */
SwigType *decl = NewStringEmpty();
$$ = new_node("constructor");
Setattr($$,"storage",$1);
Setattr($$,"name",$2);
Setattr($$, "name", name);
Setattr($$,"parms",$4);
SwigType_add_function(decl,$4);
Setattr($$,"decl",decl);
@ -4798,9 +4799,9 @@ cpp_constructor_decl : storage_class type LPAREN parms RPAREN ctor_end {
/* A destructor (hopefully) */
cpp_destructor_decl : NOT idtemplate LPAREN parms RPAREN cpp_end {
String *name = NewStringf("%s",$2);
if (*(Char(name)) != '~') Insert(name,0,"~");
$$ = new_node("destructor");
String *name = SwigType_templateprefix($2); /* A destructor can optionally be declared with template parameters before C++20, strip these off */
Insert(name, 0, "~");
$$ = new_node("destructor");
Setattr($$,"name",name);
Delete(name);
if (Len(scanner_ccode)) {
@ -4828,11 +4829,10 @@ cpp_destructor_decl : NOT idtemplate LPAREN parms RPAREN cpp_end {
/* A virtual destructor */
| VIRTUAL NOT idtemplate LPAREN parms RPAREN cpp_vend {
String *name;
String *name = SwigType_templateprefix($3); /* A destructor can optionally be declared with template parameters before C++20, strip these off */
Insert(name, 0, "~");
$$ = new_node("destructor");
Setattr($$,"storage","virtual");
name = NewStringf("%s",$3);
if (*(Char(name)) != '~') Insert(name,0,"~");
Setattr($$,"name",name);
Delete(name);
Setattr($$,"throws",$7.throws);