Add warning for ineffective %template instantiations

on forward template class declarations. A full template class definition is
required in order to wrap a template class as a proxy class.

Also tidyup handling of classforward code (no observable changes in
test-suite).
This commit is contained in:
William S Fulton 2024-06-29 17:20:07 +01:00
parent 3556c41b98
commit 8c8e27d246
9 changed files with 50 additions and 8 deletions

View File

@ -415,6 +415,7 @@ example.i(4) : Syntax error in input(1).
<li>327. Extern template ignored. <li>327. Extern template ignored.
<li>328. Value assigned to <em>name</em> not used due to limited parsing implementation. <li>328. Value assigned to <em>name</em> not used due to limited parsing implementation.
<li>329. Using declaration '<em>name</em>' for inheriting constructors uses base '<em>name</em>' which is not an immediate base of '<em>name</em>'. <li>329. Using declaration '<em>name</em>' for inheriting constructors uses base '<em>name</em>' which is not an immediate base of '<em>name</em>'.
<li>330. Template forward class instantiation '<em>templ</em>' with name '<em>name</em>' is ineffective.
<li>340. Lambda expressions and closures are not fully supported yet. <li>340. Lambda expressions and closures are not fully supported yet.
<li>344. Unable to deduce decltype for '<em>expr</em>'. <li>344. Unable to deduce decltype for '<em>expr</em>'.
<li>345. Unable to deduce auto return type for '<em>name</em>' (ignored). <li>345. Unable to deduce auto return type for '<em>name</em>' (ignored).

View File

@ -7,3 +7,8 @@ namespace UUU {
} }
%template(xxx) UUU::JJJ<int>; %template(xxx) UUU::JJJ<int>;
%template(TTT_int) VVV::TTT<int>; // needs to be after template is parsed
namespace VVV {
template<typename T> struct TTT {};
}

View File

@ -1,2 +1,3 @@
cpp_invalid_template.i:3: Error: Template 'SSS::AAA' undefined. cpp_invalid_template.i:3: Error: Template 'SSS::AAA' undefined.
cpp_invalid_template.i:9: Error: 'JJJ' is not defined as a template. (classforward) cpp_invalid_template.i:9: Error: 'JJJ' is not defined as a template. (classforward)
cpp_invalid_template.i:11: Error: Template 'VVV::TTT' undefined.

View File

@ -0,0 +1,20 @@
%module xxx
namespace Space {
template <typename T> struct ForwardDeclaredTemplate;
%template(ForwardDeclaredTemplate_double) ForwardDeclaredTemplate<double>;
template <typename T> struct ForwardDeclaredSpecialized;
%template(ForwardDeclaredTemplate_int) ForwardDeclaredSpecialized<int>; // no primary defined
%template(ForwardDeclaredTemplate_double) ForwardDeclaredSpecialized<double>; // needs to be after the specialized template definition.
template <> struct ForwardDeclaredSpecialized<double> {
void specialized(const ForwardDeclaredSpecialized& other) { }
};
template <typename T> struct ForwardDeclaredMisplacedPrimary;
%template(ForwardDeclaredTemplate_double) ForwardDeclaredMisplacedPrimary<double>; // needs to be after the primary template definition.
template <typename T> struct ForwardDeclaredMisplacedPrimary {
void primary(const ForwardDeclaredMisplacedPrimary& other) { }
};
}

View File

@ -0,0 +1,4 @@
cpp_template_forward.i:6: Warning 330: Template instantiation of forward class declaration 'Space::ForwardDeclaredTemplate< double >' with name 'ForwardDeclaredTemplate_double' is ineffective.
cpp_template_forward.i:9: Warning 330: Template instantiation of forward class declaration 'Space::ForwardDeclaredSpecialized< int >' with name 'ForwardDeclaredTemplate_int' is ineffective.
cpp_template_forward.i:10: Warning 330: Template instantiation of forward class declaration 'Space::ForwardDeclaredSpecialized< double >' with name 'ForwardDeclaredTemplate_double' is ineffective.
cpp_template_forward.i:16: Warning 330: Template instantiation of forward class declaration 'Space::ForwardDeclaredMisplacedPrimary< double >' with name 'ForwardDeclaredTemplate_double' is ineffective.

View File

@ -3,6 +3,8 @@
%rename(not1) *::operator!() const; %rename(not1) *::operator!() const;
%rename(negate) *::operator-() const; %rename(negate) *::operator-() const;
%warnfilter(SWIGWARN_PARSE_TEMPLATE_FORWARD) vfncs::OnlySpecialized<double>;
%inline %{ %inline %{
namespace vfncs { namespace vfncs {
@ -45,7 +47,7 @@ namespace vfncs {
%template(OnlySpecialized_int) OnlySpecialized<int>; %template(OnlySpecialized_int) OnlySpecialized<int>;
// Primary instantiation with only primary template forward declaration // Primary instantiation with only primary template forward declaration
%template(OnlySpecialized_double) OnlySpecialized<double>; // silently ignored - probably should warn %template(OnlySpecialized_double) OnlySpecialized<double>; // ignored with a warning
} }
%{ %{

View File

@ -2905,7 +2905,7 @@ template_directive: SWIGTEMPLATE LPAREN idstringopt RPAREN idcolonnt LESSTHAN va
if (GetFlag(nn, "instantiate")) { if (GetFlag(nn, "instantiate")) {
Delattr(nn, "instantiate"); Delattr(nn, "instantiate");
{ {
int nnisclass = (Strcmp(Getattr(nn, "templatetype"), "class") == 0); /* if not a class template it is a function template */ int nnisclass = (Strcmp(Getattr(nn, "templatetype"), "class") == 0); /* class template not a classforward nor function template */
Parm *tparms = Getattr(nn, "templateparms"); Parm *tparms = Getattr(nn, "templateparms");
int specialized = !tparms; /* fully specialized (an explicit specialization) */ int specialized = !tparms; /* fully specialized (an explicit specialization) */
String *tname = Copy(idcolonnt); String *tname = Copy(idcolonnt);
@ -2960,6 +2960,13 @@ template_directive: SWIGTEMPLATE LPAREN idstringopt RPAREN idcolonnt LESSTHAN va
} }
add_symbols_copy(templnode); add_symbols_copy(templnode);
if (Equal(nodeType(templnode), "classforward")) {
SWIG_WARN_NODE_BEGIN(templnode);
/* A full template class definition is required in order to wrap a template class as a proxy class so this %template is ineffective. */
Swig_warning(WARN_PARSE_TEMPLATE_FORWARD, cparse_file, cparse_line, "Template forward class instantiation '%s' with name '%s' is ineffective.\n", Swig_name_decl(templnode), Getattr(templnode, "sym:name"));
SWIG_WARN_NODE_END(templnode);
}
if (Strcmp(nodeType(templnode),"class") == 0) { if (Strcmp(nodeType(templnode),"class") == 0) {
/* Identify pure abstract methods */ /* Identify pure abstract methods */

View File

@ -223,6 +223,8 @@ static void cparse_template_expand(Node *templnode, Node *n, String *tname, Stri
cn = nextSibling(cn); cn = nextSibling(cn);
} }
} }
} else if (Equal(nodeType, "classforward")) {
/* Nothing to expand */
} else if (Equal(nodeType, "constructor")) { } else if (Equal(nodeType, "constructor")) {
if (!(Getattr(n, "templatetype"))) { if (!(Getattr(n, "templatetype"))) {
String *symname = Getattr(n, "sym:name"); String *symname = Getattr(n, "sym:name");
@ -1172,12 +1174,10 @@ Node *Swig_cparse_template_locate(String *name, Parm *instantiated_parms, String
if (n) { if (n) {
String *nodeType = nodeType(n); String *nodeType = nodeType(n);
int isclass = 0;
assert(Equal(nodeType, "template")); assert(Equal(nodeType, "template"));
(void)nodeType; String *templatetype = Getattr(n, "templatetype");
isclass = (Equal(Getattr(n, "templatetype"), "class"));
if (isclass) { if (Equal(templatetype, "class") || Equal(templatetype, "classforward")) {
Node *primary = Getattr(n, "primarytemplate"); Node *primary = Getattr(n, "primarytemplate");
Parm *tparmsfound = Getattr(primary ? primary : n, "templateparms"); Parm *tparmsfound = Getattr(primary ? primary : n, "templateparms");
int specialized = !tparmsfound; /* fully specialized (an explicit specialization) */ int specialized = !tparmsfound; /* fully specialized (an explicit specialization) */
@ -1361,8 +1361,8 @@ static void expand_defaults(ParmList *expanded_templateparms) {
ParmList *Swig_cparse_template_parms_expand(ParmList *instantiated_parms, Node *primary, Node *templ) { ParmList *Swig_cparse_template_parms_expand(ParmList *instantiated_parms, Node *primary, Node *templ) {
ParmList *expanded_templateparms = CopyParmList(instantiated_parms); ParmList *expanded_templateparms = CopyParmList(instantiated_parms);
String *templatetype = Getattr(primary, "templatetype"); String *templatetype = Getattr(primary, "templatetype");
if (Equal(templatetype, "class") || Equal(templatetype, "classforward")) { if (Equal(templatetype, "class") || Equal(templatetype, "classforward")) {
/* Class template */ /* Class template */
ParmList *templateparms = Getattr(primary, "templateparms"); ParmList *templateparms = Getattr(primary, "templateparms");
@ -1400,8 +1400,9 @@ ParmList *Swig_cparse_template_parms_expand(ParmList *instantiated_parms, Node *
ParmList *Swig_cparse_template_partialargs_expand(ParmList *partially_specialized_parms, Node *primary, ParmList *templateparms) { ParmList *Swig_cparse_template_partialargs_expand(ParmList *partially_specialized_parms, Node *primary, ParmList *templateparms) {
ParmList *expanded_templateparms = CopyParmList(partially_specialized_parms); ParmList *expanded_templateparms = CopyParmList(partially_specialized_parms);
String *templatetype = Getattr(primary, "templatetype");
if (Equal(Getattr(primary, "templatetype"), "class")) { if (Equal(templatetype, "class") || Equal(templatetype, "classforward")) {
/* Class template */ /* Class template */
int variadic = ParmList_variadic_parm(templateparms) ? 1 : 0; int variadic = ParmList_variadic_parm(templateparms) ? 1 : 0;
/* Add default arguments from primary template */ /* Add default arguments from primary template */

View File

@ -96,6 +96,7 @@
#define WARN_PARSE_EXTERN_TEMPLATE 327 #define WARN_PARSE_EXTERN_TEMPLATE 327
#define WARN_PARSE_ASSIGNED_VALUE 328 #define WARN_PARSE_ASSIGNED_VALUE 328
#define WARN_PARSE_USING_CONSTRUCTOR 329 #define WARN_PARSE_USING_CONSTRUCTOR 329
#define WARN_PARSE_TEMPLATE_FORWARD 330
#define WARN_CPP11_LAMBDA 340 #define WARN_CPP11_LAMBDA 340
/* Unused since 3.0.11: #define WARN_CPP11_ALIAS_DECLARATION 341 */ /* Unused since 3.0.11: #define WARN_CPP11_ALIAS_DECLARATION 341 */