From 4729cf2b1f44e57f46d13758009b10cec5af47b6 Mon Sep 17 00:00:00 2001
From: William S Fulton
Date: Fri, 18 Nov 2022 18:49:48 +0000
Subject: [PATCH] Duplicate class template instantiations via %template changes
Named duplicate class template instantiations now issue a warning and are ignored.
Duplicate empty class template instantiations are quietly ignored.
The test cases are fixed for this new behaviour.
This commit is a pre-requisite for the near future so that the Python
builtin wrappers can correctly use the SwigType_namestr function without
generating duplicate symbol names.
---
CHANGES.current | 44 ++++++
Doc/Manual/Contents.html | 1 +
Doc/Manual/SWIGPlus.html | 139 ++++++++++++++----
Doc/Manual/Warnings.html | 1 +
.../errors/cpp_template_class_repeat.i | 34 +++++
.../errors/cpp_template_class_repeat.stderr | 6 +
.../cpp_template_duplicate_names.stderr | 12 +-
.../test-suite/errors/cpp_template_repeat.i | 13 +-
.../errors/cpp_template_repeat.stderr | 6 +
.../test-suite/template_class_reuse_name.i | 3 +
Examples/test-suite/template_default2.i | 14 +-
.../template_specialization_defarg.i | 2 +
Source/CParse/cparse.h | 2 +-
Source/CParse/parser.y | 15 +-
Source/CParse/templ.c | 45 +++++-
Source/Modules/typepass.cxx | 1 +
16 files changed, 283 insertions(+), 55 deletions(-)
create mode 100644 Examples/test-suite/errors/cpp_template_class_repeat.i
create mode 100644 Examples/test-suite/errors/cpp_template_class_repeat.stderr
diff --git a/CHANGES.current b/CHANGES.current
index 3cc2c6066..e184cc6d8 100644
--- a/CHANGES.current
+++ b/CHANGES.current
@@ -7,6 +7,50 @@ the issue number to the end of the URL: https://github.com/swig/swig/issues/
Version 4.2.0 (in progress)
===========================
+2022-11-18: wsfulton
+ Duplicate class template instantiations via %template now issue a warning and are ignored.
+
+ %template(Aint) A;
+ %template(Aint2) A; // Now ignored and issues a warning
+
+ example.i:7: Warning 404: Duplicate template instantiation of 'A< int >' with name 'Aint2' ignored,
+ example.i:6: Warning 404: previous instantiation of 'A< int >' with name 'Aint'.
+
+ A single empty template instantiation before a named instantiation is the one exception
+ for allowing duplicate template instantiations as the empty template instantation does not
+ create a wrapper for the template, it merely adds the instantiation into SWIG's internal
+ type system.
+ Duplicate empty template instantiations are quietly ignored.
+
+ %template() B;
+ %template(Bint) B; // OK
+
+ %template() C;
+ %template() C; // Quietly ignored now
+ %template(Cint) C; // OK
+
+ Note that default template parameters are considered when looking for duplicates such as:
+
+ template struct D {};
+ %template(Dint) D;
+ %template(Dintshort) D;
+
+ example.i:7: Warning 404: Duplicate template instantiation of 'D< int,short >' with name 'Dintshort' ignored,
+ example.i:6: Warning 404: previous instantiation of 'D< int >' with name 'Dint'.
+
+ Note that the following always was ignored, but that was because the chosen name was a
+ duplicate rather than the template being a duplicate:
+
+ %template(Eint) E;
+ %template(Eint) E; // Always has been ignored as a redefined identifier
+
+ The old warning was:
+
+ example.i:7: Warning 302: Identifier 'Eint' redefined (ignored) (Renamed from 'E< int >'),
+ example.i:6: Warning 302: previous definition of 'Eint' (Renamed from 'E< int >').
+
+ *** POTENTIAL INCOMPATIBILITY ***
+
2022-11-05: wsfulton
#2417 Fix -swiglib for Windows when building with CMake.
diff --git a/Doc/Manual/Contents.html b/Doc/Manual/Contents.html
index fd74ab299..cecd54958 100644
--- a/Doc/Manual/Contents.html
+++ b/Doc/Manual/Contents.html
@@ -260,6 +260,7 @@
Function templates
Default template arguments
Template base classes
+Empty template instantiation
Template specialization
Member templates
Scoping and templates
diff --git a/Doc/Manual/SWIGPlus.html b/Doc/Manual/SWIGPlus.html
index b4b9acb17..cc33d6152 100644
--- a/Doc/Manual/SWIGPlus.html
+++ b/Doc/Manual/SWIGPlus.html
@@ -57,6 +57,7 @@
Function templates
Default template arguments
Template base classes
+Empty template instantiation
Template specialization
Member templates
Scoping and templates
@@ -3261,10 +3262,28 @@ void foo(List<Integer> *x);
In this case, List<Integer> is exactly the same type as
List<int>. Any use of List<Integer> is mapped back to the
instantiation of List<int> created earlier. Therefore, it is
-not necessary to instantiate a new class for the type Integer (doing so is
-redundant and will simply result in code bloat).
+not correct to instantiate a new class for the type Integer.
+An attempt to do so such as:
+
+
+%template(intList) List<int>;
+%template(IntegerList) List<Integer>; // Ignored
+
+
+
+
+will result in the duplicate instantiation being ignored with a warning:
+
+
+
+
+example.i:48: Warning 404: Duplicate template instantiation of 'List< Integer >' with name 'IntegerList' ignored,
+example.i:47: Warning 404: previous instantiation of 'List< int >' with name 'intList'.
+
+
+
The template provided to %template for instantiation must be the actual template and not a typedef to a template.
@@ -3333,36 +3352,49 @@ original template definition. Template default arguments are supported. For ex
-template vector<typename T, int max=100> class vector {
+template <typename T, int max=100> class vector {
...
};
-%template(intvec) vector<int>; // OK
+%template(intvec) vector<int>; // OK
%template(vec1000) vector<int, 1000>; // OK
The %template directive should not be used to wrap the same
-template instantiation more than once in the same scope. This will
-generate an error. For example:
+template instantiation more than once. This also applies to default parameters
+where a template parameter specified in the instantiation is the same as the default parameter.
+For example:
-%template(intList) List<int>;
-%template(Listint) List<int>; // Error. Template already wrapped.
+%template(vec) vector<double>; // OK
+%template(vec100) vector<double, 100>; // Ignored
-This error is caused because the template expansion results in two
-identical classes with the same name. This generates a symbol table
-conflict. Besides, it probably more efficient to only wrap a specific
-instantiation only once in order to reduce the potential for code
-bloat.
+will warn:
+
+
+example.i:59: Warning 404: Duplicate template instantiation of 'vector< double,100 >' with name 'vec100' ignored,
+example.i:58: Warning 404: previous instantiation of 'vector< double >' with name 'vec'.
+
+
+
+
+If this was not ignored, the template expansion would result in two identical classes.
+An identical instantiation is only wrapped once in order to reduce code bloat.
+
+
+
+Compatibility Note: Versions prior to SWIG-4.2.0 would sometimes not detect and prevent duplicate
+instantiations, such as when the wrapped name was different.
+
@@ -3429,20 +3461,6 @@ code (and base classes need to be wrapped before derived classes).
Don't worry--if you get the order wrong, SWIG should generate a warning message.
-
-Occasionally, you may need to tell SWIG about base classes that are defined by templates,
-but which aren't supposed to be wrapped. Since SWIG is not able to automatically
-instantiate templates for this purpose, you must do it manually. To do this, simply
-use the empty template instantiation, that is, %template with no name. For example:
-
-
-
-
-// Instantiate traits<double, double>, but don't wrap it.
-%template() traits<double, double>;
-
-
-
If you have to instantiate a lot of different classes for many different types,
you might consider writing a SWIG macro. For example:
@@ -3468,7 +3486,66 @@ TEMPLATE_WRAP(PairStringInt, std::pair<string, int>)
Note the use of a vararg macro for the type T. If this wasn't used, the comma in the templated type in the last example would not be possible.
-
+
+
+
+
+Occasionally, you may need to tell SWIG about classes that are defined by templates,
+but which aren't supposed to be wrapped. Since SWIG is not able to automatically
+instantiate templates for this purpose, you must do it manually. To do this, simply
+use %template(), that is the empty template instantiation that omits providing a name. For example:
+
+
+
+
+template<typename T> struct Traits {
+ typedef T type;
+};
+%}
+
+%template() Traits<int>; // instantiate Traits<int>, but don't wrap it
+
+void traitor(Traits<int>::type val);
+
+
+
+
+Without a template instantiation, SWIG does not know that the first parameter to the traitor
+function is type int and passing an integer to this function from any target language won't work.
+The empty template instantiation adds the appropriate type information into SWIG's type system, without
+forcing one to wrap the Traits class.
+
+
+
+Duplicate template instantiation are not allowed, as described in the
+Default template arguments section above.
+There is one exception where a named template instantiation can be followed by an empty template instantiation.
+Duplicate empty template instantiations are silently ignored, unlike duplicate named template instantiations.
+
+
+
+Unlike template class instantiations, template function instantiations must have a name.
+Consider the following:
+
+
+
+
+template<class T> T tfunc(T x) { };
+%template() tfunc<double>;
+
+
+
+
+The empty template instantiation will be ignored with:
+
+
+
+
+example.i:9: Warning 519: %template() contains no name. Template method ignored: tfunc< double >(double)
+
+
+
+
@@ -3558,7 +3635,7 @@ SWIG implements template argument deduction so that the following partial specia
-
+
@@ -3770,7 +3847,7 @@ constructor, that will dispatch the proper call depending on the argument
type.
-
+
@@ -3871,7 +3948,7 @@ template class C<int>;
-
+
diff --git a/Doc/Manual/Warnings.html b/Doc/Manual/Warnings.html
index b20b69cef..9d5361dae 100644
--- a/Doc/Manual/Warnings.html
+++ b/Doc/Manual/Warnings.html
@@ -493,6 +493,7 @@ example.i(4) : Syntax error in input(1).
401. Nothing known about class 'name'. Ignored.
402. Base class 'name' is incomplete.
403. Class 'name' might be abstract.
+404. Duplicate template instantiation of 'type' with name 'name' ignored, previous instantiation of 'type' with name 'name'.
450. Reserved
451. Setting const char * variable may leak memory.
452. Reserved
diff --git a/Examples/test-suite/errors/cpp_template_class_repeat.i b/Examples/test-suite/errors/cpp_template_class_repeat.i
new file mode 100644
index 000000000..c8bffd47a
--- /dev/null
+++ b/Examples/test-suite/errors/cpp_template_class_repeat.i
@@ -0,0 +1,34 @@
+%module xxx
+
+template struct A {};
+%template(Aint) A;
+%template(Aint2) A; // Now ignored and issues a warning
+
+template struct B {};
+%template() B;
+%template(Bint) B; // OK
+
+template struct C {};
+%template() C;
+%template() C; // Quietly ignored now
+%template(Cint) C; // OK
+
+template struct D {};
+%template(Dint) D;
+%template(Dintshort) D;
+
+template struct E {};
+%template(Eint) E;
+%template(Eint) E; // Always has been ignored as a redefined identifier
+
+
+template struct F {};
+%template(Fint) F;
+%template() F; // Quietly ignored
+%template() F; // Quietly ignored
+
+template struct G {};
+%template() G;
+%template() G; // Quietly ignored
+%template(Gint) G;
+%template() G; // Quietly ignored
diff --git a/Examples/test-suite/errors/cpp_template_class_repeat.stderr b/Examples/test-suite/errors/cpp_template_class_repeat.stderr
new file mode 100644
index 000000000..db283dc26
--- /dev/null
+++ b/Examples/test-suite/errors/cpp_template_class_repeat.stderr
@@ -0,0 +1,6 @@
+cpp_template_class_repeat.i:5: Warning 404: Duplicate template instantiation of 'A< int >' with name 'Aint2' ignored,
+cpp_template_class_repeat.i:4: Warning 404: previous instantiation of 'A< int >' with name 'Aint'.
+cpp_template_class_repeat.i:18: Warning 404: Duplicate template instantiation of 'D< int,short >' with name 'Dintshort' ignored,
+cpp_template_class_repeat.i:17: Warning 404: previous instantiation of 'D< int >' with name 'Dint'.
+cpp_template_class_repeat.i:22: Warning 404: Duplicate template instantiation of 'E< int >' with name 'Eint' ignored,
+cpp_template_class_repeat.i:21: Warning 404: previous instantiation of 'E< int >' with name 'Eint'.
diff --git a/Examples/test-suite/errors/cpp_template_duplicate_names.stderr b/Examples/test-suite/errors/cpp_template_duplicate_names.stderr
index 9856ff563..9e70963a8 100644
--- a/Examples/test-suite/errors/cpp_template_duplicate_names.stderr
+++ b/Examples/test-suite/errors/cpp_template_duplicate_names.stderr
@@ -2,13 +2,13 @@ cpp_template_duplicate_names.i:14: Warning 302: Identifier 'Duplicate1' redefine
cpp_template_duplicate_names.i:13: Warning 302: previous definition of 'Duplicate1'.
cpp_template_duplicate_names.i:14: Warning 302: Identifier 'Duplicate1' redefined (ignored),
cpp_template_duplicate_names.i:13: Warning 302: previous definition of 'Duplicate1'.
-cpp_template_duplicate_names.i:25: Warning 302: Identifier 'Duplicate2_0' redefined (ignored) (Renamed from 'Duplicate2< 0 >'),
-cpp_template_duplicate_names.i:24: Warning 302: previous definition of 'Duplicate2_0' (Renamed from 'Duplicate2< 0 >').
-cpp_template_duplicate_names.i:35: Warning 302: Identifier 'Duplicate3' redefined (ignored) (Renamed from 'Duplicate3< 0 >'),
-cpp_template_duplicate_names.i:31: Warning 302: previous definition of 'Duplicate3'.
+cpp_template_duplicate_names.i:25: Warning 404: Duplicate template instantiation of 'Duplicate2< 0 >' with name 'Duplicate2_0' ignored,
+cpp_template_duplicate_names.i:24: Warning 404: previous instantiation of 'Duplicate2< 0 >' with name 'Duplicate2_0'.
+cpp_template_duplicate_names.i:35: Warning 404: Duplicate template instantiation of 'Duplicate3< 0 >' with name 'Duplicate3' ignored,
+cpp_template_duplicate_names.i:34: Warning 404: previous instantiation of 'Duplicate3< 0 >' with name 'Duplicate3'.
cpp_template_duplicate_names.i:47: Warning 302: Identifier 'Duplicate4' redefined (ignored),
cpp_template_duplicate_names.i:46: Warning 302: previous definition of 'Duplicate4'.
cpp_template_duplicate_names.i:47: Warning 302: Identifier 'Duplicate4' redefined (ignored),
cpp_template_duplicate_names.i:46: Warning 302: previous definition of 'Duplicate4'.
-cpp_template_duplicate_names.i:50: Warning 302: Identifier 'Duplicate4' redefined (ignored) (Renamed from 'Duplicate4< 0 >'),
-cpp_template_duplicate_names.i:46: Warning 302: previous definition of 'Duplicate4'.
+cpp_template_duplicate_names.i:50: Warning 404: Duplicate template instantiation of 'Duplicate4< 0 >' with name 'Duplicate4' ignored,
+cpp_template_duplicate_names.i:49: Warning 404: previous instantiation of 'Duplicate4< 0 >' with name 'Duplicate4'.
diff --git a/Examples/test-suite/errors/cpp_template_repeat.i b/Examples/test-suite/errors/cpp_template_repeat.i
index f170080b7..08d378223 100644
--- a/Examples/test-suite/errors/cpp_template_repeat.i
+++ b/Examples/test-suite/errors/cpp_template_repeat.i
@@ -4,4 +4,15 @@ template T blah(T x) { };
%template(iblah) blah;
%template(iiblah) blah;
-// The second %template instantiation above should surely be ignored with a warning, but doesn't atm
+
+// empty template instantiations for template functions warn (unlike for template classes)
+%template() blah;
+%template() blah;
+%template() blah;
+
+%template(sblah) blah;
+%template(sblah) blah;
+
+%template() blah;
+%template() blah;
+%template(sblah) blah;
diff --git a/Examples/test-suite/errors/cpp_template_repeat.stderr b/Examples/test-suite/errors/cpp_template_repeat.stderr
index e69de29bb..7ab04f2a3 100644
--- a/Examples/test-suite/errors/cpp_template_repeat.stderr
+++ b/Examples/test-suite/errors/cpp_template_repeat.stderr
@@ -0,0 +1,6 @@
+cpp_template_repeat.i:6: Warning 404: Duplicate template instantiation of 'blah< int >' with name 'iiblah' ignored,
+cpp_template_repeat.i:5: Warning 404: previous instantiation of 'blah< int >' with name 'iblah'.
+cpp_template_repeat.i:14: Warning 404: Duplicate template instantiation of 'blah< short >' with name 'sblah' ignored,
+cpp_template_repeat.i:13: Warning 404: previous instantiation of 'blah< short >' with name 'sblah'.
+cpp_template_repeat.i:9: Warning 519: %template() contains no name. Template method ignored: blah< double >(double)
+cpp_template_repeat.i:16: Warning 519: %template() contains no name. Template method ignored: blah< char const * >(char const *)
diff --git a/Examples/test-suite/template_class_reuse_name.i b/Examples/test-suite/template_class_reuse_name.i
index 818816d0e..03c5c8d1f 100644
--- a/Examples/test-suite/template_class_reuse_name.i
+++ b/Examples/test-suite/template_class_reuse_name.i
@@ -97,6 +97,7 @@ namespace Space {
%warnfilter(SWIGWARN_PARSE_REDEFINED) Space::Duplicate2;
+%warnfilter(SWIGWARN_TYPE_REDEFINED) Space::Duplicate2;
%inline %{
namespace Space {
template struct Duplicate2 { void n(){}; };
@@ -107,6 +108,7 @@ namespace Space {
%warnfilter(SWIGWARN_PARSE_REDEFINED) Space::Duplicate3;
+%warnfilter(SWIGWARN_TYPE_REDEFINED) Space::Duplicate3;
%inline %{
namespace Space {
template struct Duplicate3 { void n(){}; };
@@ -123,6 +125,7 @@ namespace Space {
%}
%warnfilter(SWIGWARN_PARSE_REDEFINED) Space::Duplicate4;
+%warnfilter(SWIGWARN_TYPE_REDEFINED) Space::Duplicate4<0>;
namespace Space {
template struct Duplicate4 { void ff(){}; };
template struct Duplicate4 { void ff(){}; };
diff --git a/Examples/test-suite/template_default2.i b/Examples/test-suite/template_default2.i
index 9ba0455f1..1a22410d2 100644
--- a/Examples/test-suite/template_default2.i
+++ b/Examples/test-suite/template_default2.i
@@ -17,6 +17,16 @@
static const Polarization pmode = UnaryPolarization;
};
+ struct traits2
+ {
+ static const Polarization pmode = UnaryPolarization;
+ };
+
+ struct traits3
+ {
+ static const Polarization pmode = UnaryPolarization;
+ };
+
template > // **** problem here *****
@@ -37,8 +47,8 @@ namespace oss
Interface_tpl >;
// These don't
- %template(Module_UP2) Module;
- %template(Module_UP3) Module;
+ %template(Module_UP2) Module;
+ %template(Module_UP3) Module;
}
diff --git a/Examples/test-suite/template_specialization_defarg.i b/Examples/test-suite/template_specialization_defarg.i
index 2f664c6f2..1216ab09c 100644
--- a/Examples/test-suite/template_specialization_defarg.i
+++ b/Examples/test-suite/template_specialization_defarg.i
@@ -1,5 +1,7 @@
%module template_specialization_defarg
+%warnfilter(SWIGWARN_TYPE_REDEFINED) C; // note that warning is actually for the equivalent C
diff --git a/Source/CParse/cparse.h b/Source/CParse/cparse.h
index 2b63f034d..42ce87cef 100644
--- a/Source/CParse/cparse.h
+++ b/Source/CParse/cparse.h
@@ -66,7 +66,7 @@ extern "C" {
/* templ.c */
extern int Swig_cparse_template_expand(Node *n, String *rname, ParmList *tparms, Symtab *tscope);
- extern Node *Swig_cparse_template_locate(String *name, ParmList *tparms, Symtab *tscope);
+ extern Node *Swig_cparse_template_locate(String *name, ParmList *tparms, String *symname, Symtab *tscope);
extern void Swig_cparse_debug_templates(int);
#ifdef __cplusplus
diff --git a/Source/CParse/parser.y b/Source/CParse/parser.y
index 7f685e84e..61fac2b2e 100644
--- a/Source/CParse/parser.y
+++ b/Source/CParse/parser.y
@@ -2822,6 +2822,7 @@ template_directive: SWIGTEMPLATE LPAREN idstringopt RPAREN idcolonnt LESSTHAN va
Symtab *tscope = 0;
int specialized = 0;
int variadic = 0;
+ String *symname = $3 ? NewString($3) : 0;
$$ = 0;
@@ -2841,7 +2842,7 @@ template_directive: SWIGTEMPLATE LPAREN idstringopt RPAREN idcolonnt LESSTHAN va
This is closer to the C++ (typedef) behavior.
*/
- n = Swig_cparse_template_locate($5,$7,tscope);
+ n = Swig_cparse_template_locate($5, $7, symname, tscope);
/* Patch the argument types to respect namespaces */
p = $7;
@@ -2966,7 +2967,7 @@ template_directive: SWIGTEMPLATE LPAREN idstringopt RPAREN idcolonnt LESSTHAN va
Setattr(templnode,"sym:typename","1");
}
/* for now, nested %template is allowed only in the same scope as the template declaration */
- if ($3 && !(nnisclass && ((outer_class && (outer_class != Getattr(nn, "nested:outer")))
+ if (symname && !(nnisclass && ((outer_class && (outer_class != Getattr(nn, "nested:outer")))
||(extendmode && current_class && (current_class != Getattr(nn, "nested:outer")))))) {
/*
Comment this out for 1.3.28. We need to
@@ -2974,11 +2975,10 @@ template_directive: SWIGTEMPLATE LPAREN idstringopt RPAREN idcolonnt LESSTHAN va
move %ignore from using %rename to use
%feature(ignore).
- String *symname = Swig_name_make(templnode,0,$3,0,0);
+ String *symname = Swig_name_make(templnode, 0, symname, 0, 0);
*/
- String *symname = NewString($3);
- Swig_cparse_template_expand(templnode,symname,temparms,tscope);
- Setattr(templnode,"sym:name",symname);
+ Swig_cparse_template_expand(templnode, symname, temparms, tscope);
+ Setattr(templnode, "sym:name", symname);
} else {
static int cnt = 0;
String *nname = NewStringf("__dummy_%d__", cnt++);
@@ -2987,7 +2987,7 @@ template_directive: SWIGTEMPLATE LPAREN idstringopt RPAREN idcolonnt LESSTHAN va
SetFlag(templnode,"hidden");
Delete(nname);
Setattr(templnode,"feature:onlychildren", "typemap,typemapitem,typemapcopy,typedef,types,fragment,apply");
- if ($3) {
+ if (symname) {
Swig_warning(WARN_PARSE_NESTED_TEMPLATE, cparse_file, cparse_line, "Named nested template instantiations not supported. Processing as if no name was given to %%template().\n");
}
}
@@ -3106,6 +3106,7 @@ template_directive: SWIGTEMPLATE LPAREN idstringopt RPAREN idcolonnt LESSTHAN va
Swig_symbol_setscope(tscope);
Delete(Namespaceprefix);
Namespaceprefix = Swig_symbol_qualifiedscopename(0);
+ Delete(symname);
}
;
diff --git a/Source/CParse/templ.c b/Source/CParse/templ.c
index 0dec21586..b02df8d05 100644
--- a/Source/CParse/templ.c
+++ b/Source/CParse/templ.c
@@ -605,7 +605,7 @@ static EMatch does_parm_match(SwigType *type, SwigType *partial_parm_type, const
* Search for a template that matches name with given parameters.
* ----------------------------------------------------------------------------- */
-static Node *template_locate(String *name, Parm *tparms, Symtab *tscope) {
+static Node *template_locate(String *name, Parm *tparms, String *symname, Symtab *tscope) {
Node *n = 0;
String *tname = 0;
Node *templ;
@@ -626,7 +626,10 @@ static Node *template_locate(String *name, Parm *tparms, Symtab *tscope) {
tname = Copy(name);
SwigType_add_template(tname, tparms);
Printf(stdout, "\n");
- Swig_diagnostic(cparse_file, cparse_line, "template_debug: Searching for match to: '%s'\n", tname);
+ if (symname)
+ Swig_diagnostic(cparse_file, cparse_line, "Template debug: Searching for match to: '%s' for instantiation of template named '%s'\n", tname, symname);
+ else
+ Swig_diagnostic(cparse_file, cparse_line, "Template debug: Searching for match to: '%s' for instantiation of empty template\n", tname);
Delete(tname);
tname = 0;
}
@@ -682,11 +685,39 @@ static Node *template_locate(String *name, Parm *tparms, Symtab *tscope) {
}
tn = Getattr(n, "template");
if (tn) {
- if (template_debug) {
- Printf(stdout, " previous instantiation found: '%s'\n", Getattr(n, "name"));
+ /* Previously wrapped by a template instantiation */
+ Node *previous_named_instantiation = GetFlag(n, "hidden") ? Getattr(n, "csym:nextSibling") : n; /* "hidden" is set when "sym:name" is a __dummy_ name */
+ if (!symname) {
+ /* Quietly ignore empty template instantiations if there is a previous (empty or non-empty) template instantiation */
+ if (template_debug) {
+ if (previous_named_instantiation)
+ Printf(stdout, " previous instantiation with name '%s' found: '%s' - duplicate empty template instantiation ignored\n", Getattr(previous_named_instantiation, "sym:name"), Getattr(n, "name"));
+ else
+ Printf(stdout, " previous empty template instantiation found: '%s' - duplicate empty template instantiation ignored\n", Getattr(n, "name"));
+ }
+ return 0;
}
+ /* Accept a second instantiation only if previous template instantiation is empty */
+ if (previous_named_instantiation) {
+ String *previous_name = Getattr(previous_named_instantiation, "name");
+ String *previous_symname = Getattr(previous_named_instantiation, "sym:name");
+ String *unprocessed_tname = Copy(name);
+ SwigType_add_template(unprocessed_tname, tparms);
+
+ if (template_debug)
+ Printf(stdout, " previous instantiation with name '%s' found: '%s' - duplicate instantiation ignored\n", previous_symname, Getattr(n, "name"));
+ SWIG_WARN_NODE_BEGIN(n);
+ Swig_warning(WARN_TYPE_REDEFINED, cparse_file, cparse_line, "Duplicate template instantiation of '%s' with name '%s' ignored,\n", SwigType_namestr(unprocessed_tname), symname);
+ Swig_warning(WARN_TYPE_REDEFINED, Getfile(n), Getline(n), "previous instantiation of '%s' with name '%s'.\n", SwigType_namestr(previous_name), previous_symname);
+ SWIG_WARN_NODE_END(n);
+
+ Delete(unprocessed_tname);
+ return 0;
+ }
+ if (template_debug)
+ Printf(stdout, " previous empty template instantiation found: '%s' - using as duplicate instantiation overrides empty template instantiation\n", Getattr(n, "name"));
n = tn;
- goto success; /* Previously wrapped by a template instantiation */
+ goto success;
}
Swig_error(cparse_file, cparse_line, "'%s' is not defined as a template. (%s)\n", name, nodeType(n));
Delete(tname);
@@ -929,8 +960,8 @@ success:
* template exists.
* ----------------------------------------------------------------------------- */
-Node *Swig_cparse_template_locate(String *name, Parm *tparms, Symtab *tscope) {
- Node *n = template_locate(name, tparms, tscope); /* this function does what we want for templated classes */
+Node *Swig_cparse_template_locate(String *name, Parm *tparms, String *symname, Symtab *tscope) {
+ Node *n = template_locate(name, tparms, symname, tscope); /* this function does what we want for templated classes */
if (n) {
String *nodeType = nodeType(n);
diff --git a/Source/Modules/typepass.cxx b/Source/Modules/typepass.cxx
index 4a2a9df90..83ec8ad72 100644
--- a/Source/Modules/typepass.cxx
+++ b/Source/Modules/typepass.cxx
@@ -446,6 +446,7 @@ class TypePass:private Dispatcher {
SwigType_typedef_class(fname);
scopename = Copy(fname);
} else {
+ // Does this code ever get executed ??
Swig_warning(WARN_TYPE_REDEFINED, Getfile(n), Getline(n), "Template '%s' was already wrapped,\n", SwigType_namestr(name));
Swig_warning(WARN_TYPE_REDEFINED, Getfile(cn), Getline(cn), "previous wrap of '%s'.\n", SwigType_namestr(Getattr(cn, "name")));
scopename = 0;