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.
This commit is contained in:
William S Fulton 2022-11-18 18:49:48 +00:00
parent 777fd2c280
commit 4729cf2b1f
16 changed files with 283 additions and 55 deletions

View File

@ -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<int>;
%template(Aint2) A<int>; // 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<int>;
%template(Bint) B<int>; // OK
%template() C<int>;
%template() C<int>; // Quietly ignored now
%template(Cint) C<int>; // OK
Note that default template parameters are considered when looking for duplicates such as:
template <typename T, typename U = short> struct D {};
%template(Dint) D<int>;
%template(Dintshort) D<int, short>;
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<int>;
%template(Eint) E<int>; // 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.

View File

@ -260,6 +260,7 @@
<li><a href="SWIGPlus.html#SWIGPlus_template_functions">Function templates</a>
<li><a href="SWIGPlus.html#SWIGPlus_template_classes">Default template arguments</a>
<li><a href="SWIGPlus.html#SWIGPlus_template_class_inheritance">Template base classes</a>
<li><a href="SWIGPlus.html#SWIGPlus_template_empty">Empty template instantiation</a>
<li><a href="SWIGPlus.html#SWIGPlus_template_specialization">Template specialization</a>
<li><a href="SWIGPlus.html#SWIGPlus_template_member">Member templates</a>
<li><a href="SWIGPlus.html#SWIGPlus_template_scoping">Scoping and templates</a>

View File

@ -57,6 +57,7 @@
<li><a href="#SWIGPlus_template_functions">Function templates</a>
<li><a href="#SWIGPlus_template_classes">Default template arguments</a>
<li><a href="#SWIGPlus_template_class_inheritance">Template base classes</a>
<li><a href="#SWIGPlus_template_empty">Empty template instantiation</a>
<li><a href="#SWIGPlus_template_specialization">Template specialization</a>
<li><a href="#SWIGPlus_template_member">Member templates</a>
<li><a href="#SWIGPlus_template_scoping">Scoping and templates</a>
@ -3261,10 +3262,28 @@ void foo(List&lt;Integer&gt; *x);
In this case, <tt>List&lt;Integer&gt;</tt> is exactly the same type as
<tt>List&lt;int&gt;</tt>. Any use of <tt>List&lt;Integer&gt;</tt> is mapped back to the
instantiation of <tt>List&lt;int&gt;</tt> created earlier. Therefore, it is
not necessary to instantiate a new class for the type <tt>Integer</tt> (doing so is
redundant and will simply result in code bloat).
not correct to instantiate a new class for the type <tt>Integer</tt>.
An attempt to do so such as:
</p>
<div class="code">
<pre>
%template(intList) List&lt;int&gt;;
%template(IntegerList) List&lt;Integer&gt;; // Ignored
</pre>
</div>
<p>
will result in the duplicate instantiation being ignored with a warning:
</p>
<div class="shell">
<pre>
example.i:48: Warning 404: Duplicate template instantiation of 'List&lt; Integer &gt;' with name 'IntegerList' ignored,
example.i:47: Warning 404: previous instantiation of 'List&lt; int &gt;' with name 'intList'.
</pre>
</div>
<p>
The template provided to <tt>%template</tt> for instantiation must be the actual template and not a typedef to a template.
</p>
@ -3333,36 +3352,49 @@ original template definition. Template default arguments are supported. For ex
<div class="code">
<pre>
template vector&lt;typename T, int max=100&gt; class vector {
template &lt;typename T, int max=100&gt; class vector {
...
};
%template(intvec) vector&lt;int&gt;; // OK
%template(intvec) vector&lt;int&gt;; // OK
%template(vec1000) vector&lt;int, 1000&gt;; // OK
</pre>
</div>
<p>
The <tt>%template</tt> 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:
</p>
<div class="code">
<pre>
%template(intList) List&lt;int&gt;;
%template(Listint) List&lt;int&gt;; // Error. Template already wrapped.
%template(vec) vector&lt;double&gt;; // OK
%template(vec100) vector&lt;double, 100&gt;; // Ignored
</pre>
</div>
<p>
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:
</p>
<div class="shell">
<pre>
example.i:59: Warning 404: Duplicate template instantiation of 'vector&lt; double,100 &gt;' with name 'vec100' ignored,
example.i:58: Warning 404: previous instantiation of 'vector&lt; double &gt;' with name 'vec'.
</pre>
</div>
<p>
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.
</p>
<p>
<b>Compatibility Note</b>: Versions prior to SWIG-4.2.0 would sometimes not detect and prevent duplicate
instantiations, such as when the wrapped name was different.
</p>
<H3><a name="SWIGPlus_template_class_inheritance">6.18.4 Template base classes</a></H3>
@ -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.
</p>
<p>
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, <tt>%template</tt> with no name. For example:
</p>
<div class="code">
<pre>
// Instantiate traits&lt;double, double&gt;, but don't wrap it.
%template() traits&lt;double, double&gt;;
</pre>
</div>
<p>
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&lt;string, int&gt;)
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.
</p>
<H3><a name="SWIGPlus_template_specialization">6.18.5 Template specialization</a></H3>
<H3><a name="SWIGPlus_template_empty">6.18.5 Empty template instantiation</a></H3>
<p>
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 <tt>%template()</tt>, that is the empty template instantiation that omits providing a name. For example:
</p>
<div class="code">
<pre>
template&lt;typename T&gt; struct Traits {
typedef T type;
};
%}
%template() Traits&lt;int&gt;; // instantiate Traits&lt;int&gt;, but don't wrap it
void traitor(Traits&lt;int&gt;::type val);
</pre>
</div>
<p>
Without a template instantiation, SWIG does not know that the first parameter to the <tt>traitor</tt>
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 <tt>Traits</tt> class.
</p>
<p>
Duplicate template instantiation are not allowed, as described in the
<a href="#SWIGPlus_template_classes">Default template arguments</a> 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.
</p>
<p>
Unlike template class instantiations, template function instantiations must have a name.
Consider the following:
</p>
<div class="code">
<pre>
template&lt;class T&gt; T tfunc(T x) { };
%template() tfunc&lt;double&gt;;
</pre>
</div>
<p>
The empty template instantiation will be ignored with:
</p>
<div class="shell">
<pre>
example.i:9: Warning 519: %template() contains no name. Template method ignored: tfunc&lt; double &gt;(double)
</pre>
</div>
<H3><a name="SWIGPlus_template_specialization">6.18.6 Template specialization</a></H3>
<p>
@ -3558,7 +3635,7 @@ SWIG implements template argument deduction so that the following partial specia
</pre>
</div>
<H3><a name="SWIGPlus_template_member">6.18.6 Member templates</a></H3>
<H3><a name="SWIGPlus_template_member">6.18.7 Member templates</a></H3>
<p>
@ -3770,7 +3847,7 @@ constructor, that will dispatch the proper call depending on the argument
type.
</p>
<H3><a name="SWIGPlus_template_scoping">6.18.7 Scoping and templates</a></H3>
<H3><a name="SWIGPlus_template_scoping">6.18.8 Scoping and templates</a></H3>
<p>
@ -3871,7 +3948,7 @@ template class C&lt;int&gt;;
</p>
<H3><a name="SWIGPlus_template_more">6.18.8 More on templates</a></H3>
<H3><a name="SWIGPlus_template_more">6.18.9 More on templates</a></H3>
<p>

View File

@ -493,6 +493,7 @@ example.i(4) : Syntax error in input(1).
<li>401. Nothing known about class 'name'. Ignored.
<li>402. Base class 'name' is incomplete.
<li>403. Class 'name' might be abstract.
<li>404. Duplicate template instantiation of '<em>type</em>' with name '<em>name</em>' ignored, previous instantiation of '<em>type</em>' with name '<em>name</em>'.
<li>450. Reserved
<li>451. Setting const char * variable may leak memory.
<li>452. Reserved

View File

@ -0,0 +1,34 @@
%module xxx
template<typename T> struct A {};
%template(Aint) A<int>;
%template(Aint2) A<int>; // Now ignored and issues a warning
template<typename T> struct B {};
%template() B<int>;
%template(Bint) B<int>; // OK
template<typename T> struct C {};
%template() C<int>;
%template() C<int>; // Quietly ignored now
%template(Cint) C<int>; // OK
template <typename T, typename U = short> struct D {};
%template(Dint) D<int>;
%template(Dintshort) D<int, short>;
template<typename T> struct E {};
%template(Eint) E<int>;
%template(Eint) E<int>; // Always has been ignored as a redefined identifier
template<typename T> struct F {};
%template(Fint) F<int>;
%template() F<int>; // Quietly ignored
%template() F<int>; // Quietly ignored
template<typename T> struct G {};
%template() G<int>;
%template() G<int>; // Quietly ignored
%template(Gint) G<int>;
%template() G<int>; // Quietly ignored

View File

@ -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'.

View File

@ -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'.

View File

@ -4,4 +4,15 @@ template<class T> T blah(T x) { };
%template(iblah) blah<int>;
%template(iiblah) blah<int>;
// 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<double>;
%template() blah<double>;
%template() blah<double>;
%template(sblah) blah<short>;
%template(sblah) blah<short>;
%template() blah<const char *>;
%template() blah<const char *>;
%template(sblah) blah<const char *>;

View File

@ -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 *)

View File

@ -97,6 +97,7 @@ namespace Space {
%warnfilter(SWIGWARN_PARSE_REDEFINED) Space::Duplicate2;
%warnfilter(SWIGWARN_TYPE_REDEFINED) Space::Duplicate2;
%inline %{
namespace Space {
template <int I> 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 <int I> 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 <bool B> struct Duplicate4 { void ff(){}; };
template <bool B> struct Duplicate4 { void ff(){}; };

View File

@ -17,6 +17,16 @@
static const Polarization pmode = UnaryPolarization;
};
struct traits2
{
static const Polarization pmode = UnaryPolarization;
};
struct traits3
{
static const Polarization pmode = UnaryPolarization;
};
template <class C,
Polarization P = C::pmode,
class Base = Interface_tpl<P> > // **** problem here *****
@ -37,8 +47,8 @@ namespace oss
Interface_tpl<UnaryPolarization> >;
// These don't
%template(Module_UP2) Module<traits, UnaryPolarization>;
%template(Module_UP3) Module<traits>;
%template(Module_UP2) Module<traits2, UnaryPolarization>;
%template(Module_UP3) Module<traits3>;
}

View File

@ -1,5 +1,7 @@
%module template_specialization_defarg
%warnfilter(SWIGWARN_TYPE_REDEFINED) C<double, double>; // note that warning is actually for the equivalent C<double.
%inline %{
template <class A, class B = double>

View File

@ -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

View File

@ -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);
}
;

View File

@ -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);

View File

@ -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;