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>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>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>344. Unable to deduce decltype for '<em>expr</em>'.
<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(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: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(negate) *::operator-() const;
%warnfilter(SWIGWARN_PARSE_TEMPLATE_FORWARD) vfncs::OnlySpecialized<double>;
%inline %{
namespace vfncs {
@ -45,7 +47,7 @@ namespace vfncs {
%template(OnlySpecialized_int) OnlySpecialized<int>;
// 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")) {
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");
int specialized = !tparms; /* fully specialized (an explicit specialization) */
String *tname = Copy(idcolonnt);
@ -2960,6 +2960,13 @@ template_directive: SWIGTEMPLATE LPAREN idstringopt RPAREN idcolonnt LESSTHAN va
}
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) {
/* 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);
}
}
} else if (Equal(nodeType, "classforward")) {
/* Nothing to expand */
} else if (Equal(nodeType, "constructor")) {
if (!(Getattr(n, "templatetype"))) {
String *symname = Getattr(n, "sym:name");
@ -1172,12 +1174,10 @@ Node *Swig_cparse_template_locate(String *name, Parm *instantiated_parms, String
if (n) {
String *nodeType = nodeType(n);
int isclass = 0;
assert(Equal(nodeType, "template"));
(void)nodeType;
isclass = (Equal(Getattr(n, "templatetype"), "class"));
String *templatetype = Getattr(n, "templatetype");
if (isclass) {
if (Equal(templatetype, "class") || Equal(templatetype, "classforward")) {
Node *primary = Getattr(n, "primarytemplate");
Parm *tparmsfound = Getattr(primary ? primary : n, "templateparms");
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 *expanded_templateparms = CopyParmList(instantiated_parms);
String *templatetype = Getattr(primary, "templatetype");
if (Equal(templatetype, "class") || Equal(templatetype, "classforward")) {
/* Class template */
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 *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 */
int variadic = ParmList_variadic_parm(templateparms) ? 1 : 0;
/* Add default arguments from primary template */

View File

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