diff --git a/Doc/Manual/Warnings.html b/Doc/Manual/Warnings.html index 58350ea63..879d5ffb7 100644 --- a/Doc/Manual/Warnings.html +++ b/Doc/Manual/Warnings.html @@ -415,6 +415,7 @@ example.i(4) : Syntax error in input(1).
  • 327. Extern template ignored.
  • 328. Value assigned to name not used due to limited parsing implementation.
  • 329. Using declaration 'name' for inheriting constructors uses base 'name' which is not an immediate base of 'name'. +
  • 330. Template forward class instantiation 'templ' with name 'name' is ineffective.
  • 340. Lambda expressions and closures are not fully supported yet.
  • 344. Unable to deduce decltype for 'expr'.
  • 345. Unable to deduce auto return type for 'name' (ignored). diff --git a/Examples/test-suite/errors/cpp_invalid_template.i b/Examples/test-suite/errors/cpp_invalid_template.i index 45ad73908..dfeca133f 100644 --- a/Examples/test-suite/errors/cpp_invalid_template.i +++ b/Examples/test-suite/errors/cpp_invalid_template.i @@ -7,3 +7,8 @@ namespace UUU { } %template(xxx) UUU::JJJ; + +%template(TTT_int) VVV::TTT; // needs to be after template is parsed +namespace VVV { + template struct TTT {}; +} diff --git a/Examples/test-suite/errors/cpp_invalid_template.stderr b/Examples/test-suite/errors/cpp_invalid_template.stderr index f39464942..08119043d 100644 --- a/Examples/test-suite/errors/cpp_invalid_template.stderr +++ b/Examples/test-suite/errors/cpp_invalid_template.stderr @@ -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. diff --git a/Examples/test-suite/errors/cpp_template_forward.i b/Examples/test-suite/errors/cpp_template_forward.i new file mode 100644 index 000000000..5b5e3f198 --- /dev/null +++ b/Examples/test-suite/errors/cpp_template_forward.i @@ -0,0 +1,20 @@ +%module xxx + + +namespace Space { + template struct ForwardDeclaredTemplate; + %template(ForwardDeclaredTemplate_double) ForwardDeclaredTemplate; + + template struct ForwardDeclaredSpecialized; + %template(ForwardDeclaredTemplate_int) ForwardDeclaredSpecialized; // no primary defined + %template(ForwardDeclaredTemplate_double) ForwardDeclaredSpecialized; // needs to be after the specialized template definition. + template <> struct ForwardDeclaredSpecialized { + void specialized(const ForwardDeclaredSpecialized& other) { } + }; + + template struct ForwardDeclaredMisplacedPrimary; + %template(ForwardDeclaredTemplate_double) ForwardDeclaredMisplacedPrimary; // needs to be after the primary template definition. + template struct ForwardDeclaredMisplacedPrimary { + void primary(const ForwardDeclaredMisplacedPrimary& other) { } + }; +} diff --git a/Examples/test-suite/errors/cpp_template_forward.stderr b/Examples/test-suite/errors/cpp_template_forward.stderr new file mode 100644 index 000000000..5919d5ea3 --- /dev/null +++ b/Examples/test-suite/errors/cpp_template_forward.stderr @@ -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. diff --git a/Examples/test-suite/template_specialization.i b/Examples/test-suite/template_specialization.i index b79fee4dd..a6050a192 100644 --- a/Examples/test-suite/template_specialization.i +++ b/Examples/test-suite/template_specialization.i @@ -3,6 +3,8 @@ %rename(not1) *::operator!() const; %rename(negate) *::operator-() const; +%warnfilter(SWIGWARN_PARSE_TEMPLATE_FORWARD) vfncs::OnlySpecialized; + %inline %{ namespace vfncs { @@ -45,7 +47,7 @@ namespace vfncs { %template(OnlySpecialized_int) OnlySpecialized; // Primary instantiation with only primary template forward declaration - %template(OnlySpecialized_double) OnlySpecialized; // silently ignored - probably should warn + %template(OnlySpecialized_double) OnlySpecialized; // ignored with a warning } %{ diff --git a/Source/CParse/parser.y b/Source/CParse/parser.y index c1e3faa36..9a8e3e3e3 100644 --- a/Source/CParse/parser.y +++ b/Source/CParse/parser.y @@ -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 */ diff --git a/Source/CParse/templ.c b/Source/CParse/templ.c index 4289e5c70..253797b7f 100644 --- a/Source/CParse/templ.c +++ b/Source/CParse/templ.c @@ -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 */ diff --git a/Source/Include/swigwarn.h b/Source/Include/swigwarn.h index 6e0c083e0..38dc75c45 100644 --- a/Source/Include/swigwarn.h +++ b/Source/Include/swigwarn.h @@ -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 */