mirror of https://github.com/swig/swig
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:
parent
777fd2c280
commit
4729cf2b1f
|
@ -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.
|
||||
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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<Integer> *x);
|
|||
In this case, <tt>List<Integer></tt> is exactly the same type as
|
||||
<tt>List<int></tt>. Any use of <tt>List<Integer></tt> is mapped back to the
|
||||
instantiation of <tt>List<int></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<int>;
|
||||
%template(IntegerList) List<Integer>; // 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< Integer >' with name 'IntegerList' ignored,
|
||||
example.i:47: Warning 404: previous instantiation of 'List< int >' 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<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
|
||||
</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<int>;
|
||||
%template(Listint) List<int>; // Error. Template already wrapped.
|
||||
%template(vec) vector<double>; // OK
|
||||
%template(vec100) vector<double, 100>; // 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< double,100 >' with name 'vec100' ignored,
|
||||
example.i:58: Warning 404: previous instantiation of 'vector< double >' 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<double, double>, but don't wrap it.
|
||||
%template() traits<double, double>;
|
||||
</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<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.
|
||||
</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<typename T> struct Traits {
|
||||
typedef T type;
|
||||
};
|
||||
%}
|
||||
|
||||
%template() Traits<int>; // instantiate Traits<int>, but don't wrap it
|
||||
|
||||
void traitor(Traits<int>::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<class T> T tfunc(T x) { };
|
||||
%template() tfunc<double>;
|
||||
</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< double >(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<int>;
|
|||
</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>
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
|
@ -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'.
|
|
@ -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'.
|
||||
|
|
|
@ -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 *>;
|
||||
|
|
|
@ -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 *)
|
|
@ -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(){}; };
|
||||
|
|
|
@ -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>;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
;
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue