Merge branch 'master' into gsoc2017-php7-classes-via-c-api

This commit is contained in:
Olly Betts 2017-09-14 09:01:37 +12:00
commit f72d9c1f21
103 changed files with 2332 additions and 853 deletions

View file

@ -21116,7 +21116,7 @@ Version 1.3.7 (September 3, 2001)
typedef __name vector<T>; typedef __name vector<T>;
%enddef %enddef
An a specific instantiation is created in exactly the same way: A specific instantiation is created in exactly the same way:
%template(intvec) vector<int>; %template(intvec) vector<int>;

View file

@ -7,6 +7,174 @@ the issue number to the end of the URL: https://github.com/swig/swig/issues/
Version 4.0.0 (in progress) Version 4.0.0 (in progress)
=========================== ===========================
2017-08-16: wsfulton
Fix #1063. Add using declarations to templates into typedef table.
Using declarations to templates were missing in SWIG's internal typedef tables.
This led to a few problems, such as, templates that did not instantiate and generated
C++ code that did not compile as SWIG did not know what scope the template was
in. This happened mostly when a using declaration was used on a template type in a
completely unrelated namespace.
2017-08-16: wsfulton
Fix type lookup in the presence of using directives and using declarations.
Fix some cases of type lookup failure via a combination of both using directives and
using declarations resulting in C++ code that did not compile as the generated type was
not fully qualified for use in the global namespace. Example below:
namespace Space5 {
namespace SubSpace5 {
namespace SubSubSpace5 {
struct F {};
}
}
using namespace SubSpace5;
using SubSubSpace5::F;
void func(SubSubSpace5::F f);
}
2017-08-16: wsfulton
Issue #1051. %template scope enforcement and class definition fixes.
The scoping rules around %template have been specified and enforced.
The %template directive for a class template is the equivalent to an
explicit instantiation of a C++ class template. The scope for a valid
%template instantiation is now the same as the scope required for a
valid explicit instantiation of a C++ template. A definition of the
template for the explicit instantiation must be in scope where the
instantiation is declared and must not be enclosed within a different
namespace.
For example, a few %template and C++ explicit instantiations of std::vector
are shown below:
// valid
namespace std {
%template(vin) vector<int>;
template class vector<int>;
}
// valid
using namespace std;
%template(vin) vector<int>;
template class vector<int>;
// valid
using std::vector;
%template(vin) vector<int>;
template class vector<int>;
// ill-formed
namespace unrelated {
using std::vector;
%template(vin) vector<int>;
template class vector<int>;
}
// ill-formed
namespace unrelated {
using namespace std;
%template(vin) vector<int>;
template class vector<int>;
}
// ill-formed
namespace unrelated {
namespace std {
%template(vin) vector<int>;
template class vector<int>;
}
}
// ill-formed
namespace unrelated {
%template(vin) std::vector<int>;
template class std::vector<int>;
}
When the scope is incorrect, an error now occurs such as:
cpp_template_scope.i:34: Error: 'vector' resolves to 'std::vector' and
was incorrectly instantiated in scope 'unrelated' instead of within scope 'std'.
Previously SWIG accepted the ill-formed examples above but this led to
numerous subtle template scope problems especially in the presence of
using declarations and using directives as well as with %feature and %typemap.
Actually, a valid instantiation is one which conforms to the C++03
standard as C++11 made a change to disallow using declarations and
using directives to find a template.
// valid C++03, ill-formed C++11
using std::vector;
template class vector<int>;
Similar fixes for defining classes using forward class references have
also been put in place. For example:
namespace Space1 {
struct A;
}
namespace Space2 {
struct Space1::A {
void x();
}
}
will now error out with:
cpp_class_definition.i:5: Error: 'Space1::A' resolves to 'Space1::A' and
was incorrectly instantiated in scope 'Space2' instead of within scope 'Space1'.
2017-08-16: wsfulton
Fix scope lookup for template parameters containing unary scope operators.
Fixes cases like:
namespace Alloc {
template<typename T> struct Rebind {
typedef int Integer;
};
}
%template(RebindBucket) Alloc::Rebind< Bucket >;
OR
%template(RebindBucket) Alloc::Rebind< ::Bucket >;
Alloc::Rebind< Bucket >::Integer Bucket1();
Alloc::Rebind< ::Bucket >::Integer Bucket2();
Alloc::Rebind<::template TemplateBucket<double>>::Integer Bucket3();
2017-08-16: wsfulton
For templates only, the template parameters are fully resolved when
handling typemaps. Without this, it is too hard to have decent rules
to apply typemaps when parameter types are typedef'd and template
parameters have default values.
Fixes %clear for typedefs in templates, eg:
%typemap("in") XXX<int>::Long "..."
template typename<T> struct XXX {
typedef long Long;
};
%clear XXX<int>::Long;
as the typemap was previously incorrectly stored as a typemap for long
instead of XXX<int>::Long.
2017-08-05: olly
[C++11] Allow static_assert at the top level (and disallow it right
after template<T>). Fixes https://github.com/swig/swig/issues/1031
reported by Artem V L.
2017-08-02: wsfulton
Fix incorrectly shown warning when an empty template instantiation was used on a
class used as a base class and that base class was explicitly ignored with %ignore.
Example of the warning which will no longer appear:
Warning 401: Base class 'Functor< int,int >' has no name as it is an empty
template instantiated with '%template()'. Ignored.
2017-07-17: fflexo 2017-07-17: fflexo
[Java] #674 Add std_list.i to add support for std::list containers. The Java proxy [Java] #674 Add std_list.i to add support for std::list containers. The Java proxy
extends java.util.AbstractSequentialList and makes the C++ std::list container look extends java.util.AbstractSequentialList and makes the C++ std::list container look

View file

@ -155,7 +155,7 @@ SWIG directives. SWIG can be furnished with a header file, but an
interface can also be generated without library headers by supplying a interface can also be generated without library headers by supplying a
simple text file--called the interface file, which is typically named simple text file--called the interface file, which is typically named
with a <tt>.i</tt> extension--containing any foreign declarations of with a <tt>.i</tt> extension--containing any foreign declarations of
identifiers you wish to use. The most common approach is to use a an identifiers you wish to use. The most common approach is to use an
interface file with directives to parse the needed headers. A straight interface file with directives to parse the needed headers. A straight
parse of library headers will result in usable code, but SWIG parse of library headers will result in usable code, but SWIG
directives provides much freedom in how a user might tailor the directives provides much freedom in how a user might tailor the

View file

@ -409,7 +409,7 @@ All the steps required to compile and use a simple hierarchy of classes for shap
<p> <p>
First create an Android project called <tt>SwigClass</tt> in a subdirectory called <tt>class</tt>. First create an Android project called <tt>SwigClass</tt> in a subdirectory called <tt>class</tt>.
The steps below create and build a the JNI C++ app. The steps below create and build the JNI C++ app.
Adjust the <tt>--target</tt> id as mentioned earlier in the <a href="Android.html#Android_examples_intro">Examples introduction</a>. Adjust the <tt>--target</tt> id as mentioned earlier in the <a href="Android.html#Android_examples_intro">Examples introduction</a>.
</p> </p>

View file

@ -411,7 +411,7 @@ following conditions need to be met:
<p> <p>
ccache was inspired by the compilercache shell script script written ccache was inspired by the compilercache shell script written
by Erik Thiele and I would like to thank him for an excellent piece of by Erik Thiele and I would like to thank him for an excellent piece of
work. See work. See
<a href="http://www.erikyyy.de/compilercache/">http://www.erikyyy.de/compilercache/</a> <a href="http://www.erikyyy.de/compilercache/">http://www.erikyyy.de/compilercache/</a>

View file

@ -877,7 +877,8 @@ so in this case it is entirely possible to pass an int instead of a double to <t
<p> <p>
SWIG correctly parses the new <tt>static_assert</tt> declarations. SWIG correctly parses the new <tt>static_assert</tt> declarations (though 3.0.12 and earlier
had a bug which meant this wasn't accepted at file scope).
This is a C++ compile time directive so there isn't anything useful that SWIG can do with it. This is a C++ compile time directive so there isn't anything useful that SWIG can do with it.
</p> </p>

View file

@ -1772,7 +1772,7 @@ should pass the call on to <tt>CSharpDefaults.DefaultMethod(int)</tt>using the C
<p> <p>
When using <a href="Modules.html#Modules">multiple modules</a> it is is possible to compile each SWIG generated wrapper When using <a href="Modules.html#Modules">multiple modules</a> it is possible to compile each SWIG generated wrapper
into a different assembly. into a different assembly.
However, by default the generated code may not compile if However, by default the generated code may not compile if
generated classes in one assembly use generated classes in another assembly. generated classes in one assembly use generated classes in another assembly.

View file

@ -246,6 +246,16 @@
<li><a href="SWIGPlus.html#SWIGPlus_nn28">Wrapping overloaded operators</a> <li><a href="SWIGPlus.html#SWIGPlus_nn28">Wrapping overloaded operators</a>
<li><a href="SWIGPlus.html#SWIGPlus_class_extension">Class extension</a> <li><a href="SWIGPlus.html#SWIGPlus_class_extension">Class extension</a>
<li><a href="SWIGPlus.html#SWIGPlus_nn30">Templates</a> <li><a href="SWIGPlus.html#SWIGPlus_nn30">Templates</a>
<ul>
<li><a href="SWIGPlus.html#SWIGPlus_template_directive">The %template directive</a>
<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_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>
<li><a href="SWIGPlus.html#SWIGPlus_template_more">More on templates</a>
</ul>
<li><a href="SWIGPlus.html#SWIGPlus_namespaces">Namespaces</a> <li><a href="SWIGPlus.html#SWIGPlus_namespaces">Namespaces</a>
<ul> <ul>
<li><a href="SWIGPlus.html#SWIGPlus_nspace">The nspace feature for namespaces</a> <li><a href="SWIGPlus.html#SWIGPlus_nspace">The nspace feature for namespaces</a>

View file

@ -280,7 +280,7 @@ class SomeClass : AnInterface, AnotherInterface {
... ...
} }
</pre></div> </pre></div>
<p>For this to work, <tt>AnInterface</tt> and <tt>AnotherInterface</tt> have to be in scope. If SWIG is not in split proxy mode, this is already the case, but it it is, they have to be added to the import list via the <tt>dimports</tt> typemap. Additionally, the import statement depends on the package SWIG is configured to emit the modules to.</p> <p>For this to work, <tt>AnInterface</tt> and <tt>AnotherInterface</tt> have to be in scope. If SWIG is not in split proxy mode, this is already the case, but if it is, they have to be added to the import list via the <tt>dimports</tt> typemap. Additionally, the import statement depends on the package SWIG is configured to emit the modules to.</p>
<p>The <tt>$importtype</tt> macro helps you to elegantly solve this problem:</p> <p>The <tt>$importtype</tt> macro helps you to elegantly solve this problem:</p>
<div class="code"><pre> <div class="code"><pre>
%typemap(dimports) RemoteMpe %{ %typemap(dimports) RemoteMpe %{

View file

@ -1576,7 +1576,7 @@ return the node for the first class member.
<div class="indent"> <div class="indent">
Returns the last child node. You might use this if you wanted to append a new Returns the last child node. You might use this if you wanted to append a new
node to the of a class. node to the children of a class.
</div> </div>
<p> <p>
@ -3164,7 +3164,7 @@ these kinds of problems.
</p> </p>
<dt> <b>Examples/Makefile.in</b> <dt> <b>Examples/Makefile.in</b>
<dd> Nothing special here; see comments at top the of this file <dd> Nothing special here; see comments at the top of this file
and look to the existing languages for examples. and look to the existing languages for examples.
<dt> <b>Examples/qux99/check.list</b> <dt> <b>Examples/qux99/check.list</b>

View file

@ -639,7 +639,7 @@ public:
virtual ~FooBarAbstract() {}; virtual ~FooBarAbstract() {};
std::string FooBar() { std::string FooBar() {
return this->Foo() + ", " + this->Bar(); return this-&gt;Foo() + ", " + this-&gt;Bar();
}; };
protected: protected:

View file

@ -4105,7 +4105,7 @@ the exception specification or <code>%catches</code> feature.
</p> </p>
<p>Note that the "directorthrows" typemaps are important <p>Note that the "directorthrows" typemaps are important
only if it is important for the the exceptions passed through the C++ only if it is important for the exceptions passed through the C++
layer to be mapped to distinct C++ exceptions. If director methods layer to be mapped to distinct C++ exceptions. If director methods
are being called by C++ code that is itself wrapped in a are being called by C++ code that is itself wrapped in a
SWIG generated Java wrapper and access is always through this wrapper, SWIG generated Java wrapper and access is always through this wrapper,

View file

@ -411,7 +411,7 @@ void print_array(double x[10]);
Now, in a scripting language, you might write this: Now, in a scripting language, you might write this:
</p> </p>
<div class="code"> <div class="targetlang">
<pre> <pre>
a = new_doubleArray(10) # Create an array a = new_doubleArray(10) # Create an array
for i in range(0, 10): for i in range(0, 10):
@ -475,7 +475,7 @@ void print_array(double x[10]);
Allows you to do this: Allows you to do this:
</p> </p>
<div class="code"> <div class="targetlang">
<pre> <pre>
import example import example
c = example.doubleArray(10) # Create double[10] c = example.doubleArray(10) # Create double[10]
@ -801,7 +801,7 @@ target language. In other words, if you were using a language like Tcl,
and you wrote this, and you wrote this,
</p> </p>
<div class="code"> <div class="targetlang">
<pre> <pre>
% foo Hello % foo Hello
</pre> </pre>
@ -852,7 +852,7 @@ size_t parity(char *str, size_t len, size_t initial);
Now, in the target language, you can use binary string data like this: Now, in the target language, you can use binary string data like this:
</p> </p>
<div class="code"> <div class="targetlang">
<pre> <pre>
&gt;&gt;&gt; s = "H\x00\x15eg\x09\x20" &gt;&gt;&gt; s = "H\x00\x15eg\x09\x20"
&gt;&gt;&gt; parity(s, 0) &gt;&gt;&gt; parity(s, 0)

View file

@ -1008,8 +1008,7 @@ The following operators cannot be overloaded (mainly because they are not suppor
<p> <p>
SWIG also accepts the <tt>__str__()</tt> member function which converts an object to a string. This function should return a const char*, preferably to static memory. This will be used for the <tt>print()</tt> and <tt>tostring()</tt> functions in Lua. Assuming the complex class has a function SWIG also accepts the <tt>__str__()</tt> member function which converts an object to a string. This function should return a const char*, preferably to static memory. This will be used for the <tt>print()</tt> and <tt>tostring()</tt> functions in Lua. Assuming the complex class has a function
</p> </p>
<div class="code"><pre>const char* __str__() <div class="code"><pre>const char* __str__() {
{
static char buffer[255]; static char buffer[255];
sprintf(buffer, "Complex(%g, %g)", this-&gt;re(), this-&gt;im()); sprintf(buffer, "Complex(%g, %g)", this-&gt;re(), this-&gt;im());
return buffer; return buffer;
@ -1031,8 +1030,7 @@ Complex(10, 12)
<p> <p>
It is also possible to overload the operator<tt>[]</tt>, but currently this cannot be automatically performed. To overload the operator<tt>[]</tt> you need to provide two functions, <tt>__getitem__()</tt> and <tt>__setitem__()</tt> It is also possible to overload the operator<tt>[]</tt>, but currently this cannot be automatically performed. To overload the operator<tt>[]</tt> you need to provide two functions, <tt>__getitem__()</tt> and <tt>__setitem__()</tt>
</p> </p>
<div class="code"><pre>class Complex <div class="code"><pre>class Complex {
{
//.... //....
double __getitem__(int i)const; // i is the index, returns the data double __getitem__(int i)const; // i is the index, returns the data
void __setitem__(int i, double d); // i is the index, d is the data void __setitem__(int i, double d); // i is the index, d is the data

View file

@ -1633,10 +1633,9 @@ class DoubleArray {
void setitem(int i, double val) { void setitem(int i, double val) {
if ((i &gt;= 0) &amp;&amp; (i &lt; n)) if ((i &gt;= 0) &amp;&amp; (i &lt; n))
ptr[i] = val; ptr[i] = val;
else { else
throw RangeError(); throw RangeError();
} }
}
}; };
</pre></div> </pre></div>

View file

@ -163,7 +163,7 @@ If the module is in PHP's default extension directory, you can omit the path.
<p> <p>
For some SAPIs (for example, the CLI SAPI) you can instead use the For some SAPIs (for example, the CLI SAPI) you can instead use the
<a href="http://php.net/manual/en/function.dl.php">dl() function</a> to load <a href="http://php.net/manual/en/function.dl.php">dl() function</a> to load
an extension at run time, by adding a like like this to the start of each an extension at run time, by adding a line like this to the start of each
PHP script which uses your extension: PHP script which uses your extension:
</p> </p>

View file

@ -226,13 +226,12 @@ resulting C file should be built as a python extension, inserting the module
#include "example.h" #include "example.h"
int fact(int n) { int fact(int n) {
if (n &lt; 0){ /* This should probably return an error, but this is simpler */ if (n &lt; 0) { /* This should probably return an error, but this is simpler */
return 0; return 0;
} }
if (n == 0) { if (n == 0) {
return 1; return 1;
} } else {
else {
/* testing for overflow would be a good idea here */ /* testing for overflow would be a good idea here */
return n * fact(n-1); return n * fact(n-1);
} }
@ -2476,8 +2475,9 @@ public:
Twit operator+ (const Twit&amp; twit) const; Twit operator+ (const Twit&amp; twit) const;
// Forward to operator+ // Forward to operator+
Twit add (const Twit&amp; twit) const Twit add (const Twit&amp; twit) const {
{ return *this + twit; } return *this + twit;
}
}; };
</pre> </pre>
</div> </div>
@ -6046,7 +6046,7 @@ zipimporter requires python-3.5.1 or newer to work with subpackages.
<p> <p>
When SWIG creates wrappers from an interface file, say foo.i, two Python modules are When SWIG creates wrappers from an interface file, say foo.i, two Python modules are
created. There is a pure Python module module (foo.py) and C/C++ code which is created. There is a pure Python module (foo.py) and C/C++ code which is
built and linked into a dynamically (or statically) loaded low-level module _foo built and linked into a dynamically (or statically) loaded low-level module _foo
(see the <a href="Python.html#Python_nn3">Preliminaries section</a> for details). So, the interface (see the <a href="Python.html#Python_nn3">Preliminaries section</a> for details). So, the interface
file really defines two Python modules. How these two modules are loaded is file really defines two Python modules. How these two modules are loaded is

View file

@ -49,6 +49,16 @@
<li><a href="#SWIGPlus_nn28">Wrapping overloaded operators</a> <li><a href="#SWIGPlus_nn28">Wrapping overloaded operators</a>
<li><a href="#SWIGPlus_class_extension">Class extension</a> <li><a href="#SWIGPlus_class_extension">Class extension</a>
<li><a href="#SWIGPlus_nn30">Templates</a> <li><a href="#SWIGPlus_nn30">Templates</a>
<ul>
<li><a href="#SWIGPlus_template_directive">The %template directive</a>
<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_specialization">Template specialization</a>
<li><a href="#SWIGPlus_template_member">Member templates</a>
<li><a href="#SWIGPlus_template_scoping">Scoping and templates</a>
<li><a href="#SWIGPlus_template_more">More on templates</a>
</ul>
<li><a href="#SWIGPlus_namespaces">Namespaces</a> <li><a href="#SWIGPlus_namespaces">Namespaces</a>
<ul> <ul>
<li><a href="#SWIGPlus_nspace">The nspace feature for namespaces</a> <li><a href="#SWIGPlus_nspace">The nspace feature for namespaces</a>
@ -2779,7 +2789,7 @@ into two methods such that additional logic can be packed into the operations; C
<tt>this[type key] { get { ... } set { ... }}</tt>, Python uses <tt>this[type key] { get { ... } set { ... }}</tt>, Python uses
<tt>__getitem__</tt> and <tt>__setitem__</tt>, etc. In C++ if the return <tt>__getitem__</tt> and <tt>__setitem__</tt>, etc. In C++ if the return
type of <tt>operator[]</tt> is a reference and the method is const, it is often indicative of the <i>setter</i>, type of <tt>operator[]</tt> is a reference and the method is const, it is often indicative of the <i>setter</i>,
and and the <i>getter</i> is usually a const function return an object by value. and the <i>getter</i> is usually a const function return an object by value.
In the absence of any hard and fast rules and the fact that there may be multiple index operators, In the absence of any hard and fast rules and the fact that there may be multiple index operators,
it is up to the user to choose the getter and setter to use by using %rename as shown earlier. it is up to the user to choose the getter and setter to use by using %rename as shown earlier.
</p> </p>
@ -2936,10 +2946,12 @@ as <tt>vector&lt;int&gt;</tt>. The wrapper for <tt>foo()</tt> will
accept either variant. accept either variant.
</p> </p>
<H3><a name="SWIGPlus_template_directive">6.18.1 The %template directive</a></H3>
<p> <p>
Starting with SWIG-1.3.7, simple C++ template declarations can also be There are a couple of important points about template wrapping.
wrapped. SWIG-1.3.12 greatly expands upon the earlier implementation. Before discussing this any further, there are a few things First, a bare C++ template
you need to know about template wrapping. First, a bare C++ template
does not define any sort of runnable object-code for which SWIG can does not define any sort of runnable object-code for which SWIG can
normally create a wrapper. Therefore, in order to wrap a template, normally create a wrapper. Therefore, in order to wrap a template,
you need to give SWIG information about a particular template you need to give SWIG information about a particular template
@ -2947,12 +2959,11 @@ instantiation (e.g., <tt>vector&lt;int&gt;</tt>,
<tt>array&lt;double&gt;</tt>, etc.). Second, an instantiation name <tt>array&lt;double&gt;</tt>, etc.). Second, an instantiation name
such as <tt>vector&lt;int&gt;</tt> is generally not a valid identifier such as <tt>vector&lt;int&gt;</tt> is generally not a valid identifier
name in most target languages. Thus, you will need to give the name in most target languages. Thus, you will need to give the
template instantiation a more suitable name such as <tt>intvector</tt> template instantiation a more suitable name such as <tt>intvector</tt>.
when creating a wrapper.
</p> </p>
<p> <p>
To illustrate, consider the following template definition: To illustrate, consider the following class template definition:
</p> </p>
<div class="code"><pre> <div class="code"><pre>
@ -2985,14 +2996,26 @@ public:
</pre></div> </pre></div>
<p> <p>
By itself, this template declaration is useless--SWIG simply ignores it By itself, this class template is useless--SWIG simply ignores it
because it doesn't know how to generate any code until unless a definition of because it doesn't know how to generate any code unless a definition of
<tt>T</tt> is provided. <tt>T</tt> is provided.
The <tt>%template</tt> directive is required to instantiate the template for use in a target language.
The directive requires an identifier name for use in the target language plus the template for instantiation.
The example below instantiates <tt>List&lt;int&gt;</tt> for use as a class named <tt>intList</tt>:
</p> </p>
<div class="code">
<pre>
%template(intList) List&lt;int&gt;;
</pre>
</div>
<p> <p>
One way to create wrappers for a specific template instantiation is to simply The instantiation expands the template code as a C++ compiler would do and then makes it available
provide an expanded version of the class directly like this: under the given identifier name.
Essentially it is the same as wrapping the following concept code where
the class template definition has <tt>T</TT> expanded to <tt>int</tt>
(note that this is not entirely valid syntax):
</p> </p>
<div class="code"> <div class="code">
@ -3014,28 +3037,6 @@ public:
</div> </div>
<p>
The <tt>%rename</tt> directive is needed to give the template class an appropriate identifier
name in the target language (most languages would not recognize C++ template syntax as a valid
class name). The rest of the code is the same as what would appear in a normal
class definition.
</p>
<p>
Since manual expansion of templates gets old in a hurry, the <tt>%template</tt> directive can
be used to create instantiations of a template class. Semantically, <tt>%template</tt> is
simply a shortcut---it expands template code in exactly the same way as shown above. Here
are some examples:
</p>
<div class="code">
<pre>
/* Instantiate a few different versions of the template */
%template(intList) List&lt;int&gt;;
%template(doubleList) List&lt;double&gt;;
</pre>
</div>
<p> <p>
The argument to <tt>%template()</tt> is the name of the instantiation The argument to <tt>%template()</tt> is the name of the instantiation
in the target language. The name you choose should not conflict with in the target language. The name you choose should not conflict with
@ -3053,7 +3054,81 @@ typedef List&lt;int&gt; intList; // OK
</div> </div>
<p> <p>
SWIG can also generate wrappers for function templates using a similar technique. The <tt>%template</tt> directive
must always appear <em>after</em> the definition of the template to be expanded, so the following will work:
</p>
<div class="code">
<pre>
template&lt;class T&gt; class List { ... };
%template(intList) List&lt;int&gt;;
</pre>
</div>
<p>
but if %template is used before the template definition, such as:
</p>
<div class="code">
<pre>
%template(intList) List&lt;int&gt;;
template&lt;class T&gt; class List { ... };
</pre>
</div>
<p>
SWIG will generate an error:
</p>
<div class="shell">
<pre>
example.i:3: Error: Template 'List' undefined.
</pre>
</div>
<p>
Since the type system knows how to handle <tt>typedef</tt>, it is
generally not necessary to instantiate different versions of a template
for typenames that are equivalent. For instance, consider this code:
</p>
<div class="code">
<pre>
%template(intList) List&lt;int&gt;;
typedef int Integer;
...
void foo(List&lt;Integer&gt; *x);
</pre>
</div>
<p>
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).
</p>
<p>
The template provide to <tt>%template</tt> for instantiation must be the actual template and not a typedef to a template.
</p>
<div class="code">
<pre>
typedef List&lt;int&gt; ListOfInt;
%template(intList) List&lt;int&gt;; // ok
%template(intList) ListOfInt; // illegal - Syntax error
</pre>
</div>
<H3><a name="SWIGPlus_template_functions">6.18.2 Function templates</a></H3>
<p>
SWIG can also generate wrappers for function templates using a similar technique
to that shown above for class templates.
For example: For example:
</p> </p>
@ -3073,6 +3148,28 @@ In this case, <tt>maxint</tt> and <tt>maxdouble</tt> become unique names for spe
instantiations of the function. instantiations of the function.
</p> </p>
<p>
SWIG even supports overloaded templated functions. As usual the <tt>%template</tt> directive
is used to wrap templated functions. For example:
</p>
<div class="code">
<pre>
template&lt;class T&gt; void foo(T x) { };
template&lt;class T&gt; void foo(T x, T y) { };
%template(foo) foo&lt;int&gt;;
</pre>
</div>
<p>
This will generate two overloaded wrapper methods, the first will take a single integer as an argument
and the second will take two integer arguments.
</p>
<H3><a name="SWIGPlus_template_classes">6.18.3 Default template arguments</a></H3>
<p> <p>
The number of arguments supplied to <tt>%template</tt> should match that in the The number of arguments supplied to <tt>%template</tt> should match that in the
original template definition. Template default arguments are supported. For example: original template definition. Template default arguments are supported. For example:
@ -3110,28 +3207,8 @@ instantiation only once in order to reduce the potential for code
bloat. bloat.
</p> </p>
<p> <H3><a name="SWIGPlus_template_class_inheritance">6.18.4 Template base classes</a></H3>
Since the type system knows how to handle <tt>typedef</tt>, it is
generally not necessary to instantiate different versions of a template
for typenames that are equivalent. For instance, consider this code:
</p>
<div class="code">
<pre>
%template(intList) vector&lt;int&gt;;
typedef int Integer;
...
void foo(vector&lt;Integer&gt; *x);
</pre>
</div>
<p>
In this case, <tt>vector&lt;Integer&gt;</tt> is exactly the same type as
<tt>vector&lt;int&gt;</tt>. Any use of <tt>Vector&lt;Integer&gt;</tt> is mapped back to the
instantiation of <tt>vector&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).
</p>
<p> <p>
When a template is instantiated using <tt>%template</tt>, information When a template is instantiated using <tt>%template</tt>, information
@ -3158,13 +3235,13 @@ nothing is known about <tt>List&lt;int&gt;</tt>, you will get a warning message
<div class="shell"> <div class="shell">
<pre> <pre>
example.h:42: Warning 401. Nothing known about class 'List&lt;int &gt;'. Ignored. example.h:42: Warning 401. Nothing known about class 'List&lt; int &gt;'. Ignored.
example.h:42: Warning 401. Maybe you forgot to instantiate 'List&lt;int &gt;' using %template. example.h:42: Warning 401. Maybe you forgot to instantiate 'List&lt; int &gt;' using %template.
</pre> </pre>
</div> </div>
<p> <p>
If a template class inherits from another template class, you need to If a class template inherits from another class template, you need to
make sure that base classes are instantiated before derived classes. make sure that base classes are instantiated before derived classes.
For example: For example:
</p> </p>
@ -3235,6 +3312,9 @@ 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. 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> </p>
<H3><a name="SWIGPlus_template_specialization">6.18.5 Template specialization</a></H3>
<p> <p>
The SWIG template mechanism <em>does</em> support specialization. For instance, if you define The SWIG template mechanism <em>does</em> support specialization. For instance, if you define
a class like this, a class like this,
@ -3281,7 +3361,7 @@ private:
public: public:
List(int max); List(int max);
~List(); ~List();
void append(int obj); void append(T obj);
int length(); int length();
T get(int n); T get(int n);
}; };
@ -3322,10 +3402,13 @@ SWIG implements template argument deduction so that the following partial specia
</pre> </pre>
</div> </div>
<H3><a name="SWIGPlus_template_member">6.18.6 Member templates</a></H3>
<p> <p>
Member function templates are supported. The underlying principle is the same Member templates are supported. The underlying principle is the same
as for normal templates--SWIG can't create a wrapper unless you provide as for normal templates--SWIG can't create a wrapper unless you provide
more information about types. For example, a class with a member template might more information about types. For example, a class with a member function template might
look like this: look like this:
</p> </p>
@ -3399,11 +3482,6 @@ methods to the Foo class.
</p> </p>
<p>
Note: because of the way that templates are handled, the <tt>%template</tt> directive
must always appear <em>after</em> the definition of the template to be expanded.
</p>
<p> <p>
Now, if your target language supports overloading, you can even try Now, if your target language supports overloading, you can even try
</p> </p>
@ -3424,7 +3502,7 @@ depending on the argument type.
<p> <p>
When used with members, the <tt>%template</tt> directive may be placed in another When used with members, the <tt>%template</tt> directive may be placed in another
template class. Here is a slightly perverse example: class template. Here is a slightly perverse example:
</p> </p>
<div class="code"> <div class="code">
@ -3475,7 +3553,7 @@ template&lt;class T1, class T2&gt; struct pair {
<p> <p>
This declaration is perfectly acceptable to SWIG, but the constructor template will be ignored This declaration is perfectly acceptable to SWIG, but the constructor template will be ignored
unless you explicitly expand it. To do that, you could expand a few versions of the constructor unless you explicitly expand it. To do that, you could expand a few versions of the constructor
in the template class itself. For example: in the class template itself. For example:
</p> </p>
<div class="code"> <div class="code">
@ -3536,6 +3614,110 @@ constructor, that will dispatch the proper call depending on the argument
type. type.
</p> </p>
<H3><a name="SWIGPlus_template_scoping">6.18.7 Scoping and templates</a></H3>
<p>
The <tt>%template</tt> directive for a class template is the equivalent to an explicit instantiation
of a C++ class template. The scope for a valid <tt>%template</tt> instantiation is the same
as the scope required for a valid explicit instantiation of a C++ template.
A definition of the template for the explicit instantiation must be in scope
where the instantiation is declared and must not be enclosed within a different namespace.
</p>
<p>
For example, a few <tt>%template</tt> instantiations and C++ explicit instantiations are shown below:
</p>
<div class="code">
<pre>
namespace N {
template&lt;typename T&gt; class C {};
}
// valid
%template(cin) N::C&lt;int&gt;;
template class N::C&lt;int&gt;;
// valid
namespace N {
%template(cin) C&lt;int&gt;;
template class C&lt;int&gt;;
}
// valid
using namespace N;
%template(cin) C&lt;int&gt;;
template class C&lt;int&gt;;
// valid
using N::C;
%template(cin) C&lt;int&gt;;
template class C&lt;int&gt;;
// ill-formed
namespace unrelated {
using N::C;
%template(cin) C&lt;int&gt;;
template class C&lt;int&gt;;
}
// ill-formed
namespace unrelated {
using namespace N;
%template(cin) C&lt;int&gt;;
template class C&lt;int&gt;;
}
// ill-formed
namespace unrelated {
namespace N {
%template(cin) C&lt;int&gt;;
template class C&lt;int&gt;;
}
}
// ill-formed
namespace unrelated {
%template(cin) N::C&lt;int&gt;;
template class N::C&lt;int&gt;;
}
</pre>
</div>
<p>
When the scope is incorrect, such as for the ill-formed examples above, an error occurs:
</p>
<div class="shell">
<pre>
cpp_template_scope.i:34: Error: 'C' resolves to 'N::C' and was incorrectly instantiated
in scope 'unrelated' instead of within scope 'N'.
</pre>
</div>
<p>
A note for the C++ standard geeks out there; a valid instantiation is one which conforms to
the C++03 standard as C++11 made a change to disallow using declarations and using directives to find a template.
</p>
<div class="code">
<pre>
// valid C++03, ill-formed C++11
using N::C;
template class C&lt;int&gt;;
</pre>
</div>
<p>
<b>Compatibility Note</b>: Versions prior to SWIG-4.0.0 did not error out with incorrectly scoped
<tt>%template</tt> declarations, but this led to numerous subtle template scope problems.
</p>
<H3><a name="SWIGPlus_template_more">6.18.8 More on templates</a></H3>
<p> <p>
If all of this isn't quite enough and you really want to make If all of this isn't quite enough and you really want to make
someone's head explode, SWIG directives such as someone's head explode, SWIG directives such as
@ -3568,7 +3750,7 @@ instantiation.
</p> </p>
<p> <p>
It is also possible to separate these declarations from the template class. For example: It is also possible to separate these declarations from the class template. For example:
</p> </p>
<div class="code"> <div class="code">
@ -3616,25 +3798,6 @@ additional methods to a specific instantiation. For example:
</pre> </pre>
</div> </div>
<p>
SWIG even supports overloaded templated functions. As usual the <tt>%template</tt> directive
is used to wrap templated functions. For example:
</p>
<div class="code">
<pre>
template&lt;class T&gt; void foo(T x) { };
template&lt;class T&gt; void foo(T x, T y) { };
%template(foo) foo&lt;int&gt;;
</pre>
</div>
<p>
This will generate two overloaded wrapper methods, the first will take a single integer as an argument
and the second will take two integer arguments.
</p>
<p> <p>
It is even possible to extend a class via <tt>%extend</tt> with template methods, for example: It is even possible to extend a class via <tt>%extend</tt> with template methods, for example:
</p> </p>
@ -3694,7 +3857,7 @@ For example:
<pre> <pre>
template &lt;class T&gt; class OuterTemplateClass {}; template &lt;class T&gt; class OuterTemplateClass {};
// The nested class OuterClass::InnerClass inherits from the template class // The nested class OuterClass::InnerClass inherits from the class template
// OuterTemplateClass&lt;OuterClass::InnerStruct&gt; and thus the template needs // OuterTemplateClass&lt;OuterClass::InnerStruct&gt; and thus the template needs
// to be expanded with %template before the OuterClass declaration. // to be expanded with %template before the OuterClass declaration.
%template(OuterTemplateClass_OuterClass__InnerStruct) %template(OuterTemplateClass_OuterClass__InnerStruct)
@ -3915,6 +4078,8 @@ then SWIG simply creates three wrapper functions <tt>bar()</tt>,
<tt>spam()</tt>, and <tt>blah()</tt> in the target language. SWIG <tt>spam()</tt>, and <tt>blah()</tt> in the target language. SWIG
does not prepend the names with a namespace prefix nor are the does not prepend the names with a namespace prefix nor are the
functions packaged in any kind of nested scope. functions packaged in any kind of nested scope.
Note that the default handling of flattening all the namespace scopes in the target language
can be changed via the <a href="#SWIGPlus_nspace">nspace feature</a>.
</p> </p>
<p> <p>
@ -4203,9 +4368,7 @@ namespace foo {
<p> <p>
<b>Note:</b> The flattening of namespaces is only intended to serve as <b>Note:</b> The flattening of namespaces is only intended to serve as
a basic namespace implementation. a basic namespace implementation.
None of the target language modules are currently programmed More advanced handling of namespaces is discussed next.
with any namespace awareness. In the future, language modules may or may not provide
more advanced namespace support.
</p> </p>
<H3><a name="SWIGPlus_nspace">6.19.1 The nspace feature for namespaces</a></H3> <H3><a name="SWIGPlus_nspace">6.19.1 The nspace feature for namespaces</a></H3>
@ -4524,7 +4687,7 @@ for member pointers.
<p> <p>
In some C++ programs, objects are often encapsulated by smart-pointers In some C++ programs, objects are often encapsulated by smart-pointers
or proxy classes. This is sometimes done to implement automatic memory management (reference counting) or or proxy classes. This is sometimes done to implement automatic memory management (reference counting) or
persistence. Typically a smart-pointer is defined by a template class where persistence. Typically a smart-pointer is defined by a class template where
the <tt>-&gt;</tt> operator has been overloaded. This class is then wrapped the <tt>-&gt;</tt> operator has been overloaded. This class is then wrapped
around some other class. For example: around some other class. For example:
</p> </p>

View file

@ -1136,7 +1136,7 @@ But we can use either use the <tt>get_perimeter()</tt> function of the parent cl
As explained in <a href="SWIGPlus.html#SWIGPlus_overloaded_methods">6.15</a> SWIG provides support for overloaded functions and constructors. As explained in <a href="SWIGPlus.html#SWIGPlus_overloaded_methods">6.15</a> SWIG provides support for overloaded functions and constructors.
</p> </p>
<p>As SWIG knows pointer types, the overloading works also with pointer types, here is is an example with a function <tt>magnify</tt> overloaded for the previous classes <tt>Shape</tt> and <tt>Circle</tt>: <p>As SWIG knows pointer types, the overloading works also with pointer types, here is an example with a function <tt>magnify</tt> overloaded for the previous classes <tt>Shape</tt> and <tt>Circle</tt>:
</p> </p>
<div class="code"><pre> <div class="code"><pre>
@ -1620,11 +1620,11 @@ void printArray(int values[], int len) {
<p> <p>
There are no specific typemaps for pointer-to-pointers, they are are mapped as pointers in Scilab. There are no specific typemaps for pointer-to-pointers, they are mapped as pointers in Scilab.
</p> </p>
<p> <p>
Pointer-to-pointers are sometimes used to implement matrices in C. The following is a an example of this: Pointer-to-pointers are sometimes used to implement matrices in C. The following is an example of this:
</p> </p>
@ -2062,7 +2062,7 @@ In this mode, the following SWIG options may be used to setup the build:
Let's give an example how to build a module <tt>example</tt>, composed of two sources, and using a library dependency: Let's give an example how to build a module <tt>example</tt>, composed of two sources, and using a library dependency:
</p> </p>
<ul> <ul>
<li>the sources are <tt>baa1.c</tt> and <tt>baa2.c</tt> (and are stored in in the current directory)</li> <li>the sources are <tt>baa1.c</tt> and <tt>baa2.c</tt> (and are stored in the current directory)</li>
<li>the library is <tt>libfoo</tt> in <tt>/opt/foo</tt> (headers stored in <tt>/opt/foo/include</tt>, and shared library in <tt>/opt/foo/lib</tt>)</li> <li>the library is <tt>libfoo</tt> in <tt>/opt/foo</tt> (headers stored in <tt>/opt/foo/include</tt>, and shared library in <tt>/opt/foo/lib</tt>)</li>
</ul> </ul>

View file

@ -30,5 +30,5 @@ f.enum_test(example.Foo.LUDICROUS);
// enum value BLUE of enum color is accessed as property of cconst // enum value BLUE of enum color is accessed as property of cconst
console.log("example.BLUE= " + example.BLUE); console.log("example.BLUE= " + example.BLUE);
// enum value LUDICROUS of enum Foo::speed is accessed as as property of cconst // enum value LUDICROUS of enum Foo::speed is accessed as property of cconst
console.log("example.speed.LUDICROUS= " + example.Foo.LUDICROUS); console.log("example.speed.LUDICROUS= " + example.Foo.LUDICROUS);

View file

@ -14,7 +14,7 @@ CEO=@(name) subclass(swigexample.Manager(name),'getPosition',@(self) "CEO");
# Create an instance of our employee extension class, CEO. The calls to # Create an instance of our employee extension class, CEO. The calls to
# getName() and getPosition() are standard, the call to getTitle() uses # getName() and getPosition() are standard, the call to getTitle() uses
# the director wrappers to call CEO.getPosition. e = CEO("Alice") # the director wrappers to call CEO.getPosition.
e = CEO("Alice"); e = CEO("Alice");
printf("%s is a %s\n",e.getName(),e.getPosition()); printf("%s is a %s\n",e.getName(),e.getPosition());

View file

@ -18,7 +18,7 @@ class CEO(example.Manager):
# Create an instance of our employee extension class, CEO. The calls to # Create an instance of our employee extension class, CEO. The calls to
# getName() and getPosition() are standard, the call to getTitle() uses # getName() and getPosition() are standard, the call to getTitle() uses
# the director wrappers to call CEO.getPosition. e = CEO("Alice") # the director wrappers to call CEO.getPosition.
e = CEO("Alice") e = CEO("Alice")
print e.getName(), "is a", e.getPosition() print e.getName(), "is a", e.getPosition()

View file

@ -2,4 +2,5 @@
import robin import robin
assert(robin.run() == "AWAY!") if not(robin.run() == "AWAY!"):
raise RuntimeError("test failed")

View file

@ -4,4 +4,5 @@ sys.path.insert(0, 'path1')
from brave import robin from brave import robin
assert(robin.run() == "AWAY!") if not(robin.run() == "AWAY!"):
raise RuntimeError("test failed")

View file

@ -6,4 +6,5 @@ sys.path.insert(0, 'path3')
from brave import robin from brave import robin
assert(robin.run() == "AWAY!") if not(robin.run() == "AWAY!"):
raise RuntimeError("test failed")

View file

@ -6,4 +6,5 @@ sys.path.insert(0, 'path3')
from brave import robin from brave import robin
assert(robin.run() == "AWAY!") if not(robin.run() == "AWAY!"):
raise RuntimeError("test failed")

View file

@ -7,4 +7,5 @@ import pkg1.foo
print " Finished importing pkg1.foo" print " Finished importing pkg1.foo"
assert(pkg1.foo.count() == 3) if not(pkg1.foo.count() == 3):
raise RuntimeError("test failed")

View file

@ -7,4 +7,5 @@ import pkg1.foo
print " Finished importing pkg1.foo" print " Finished importing pkg1.foo"
assert(pkg1.foo.count() == 3) if not(pkg1.foo.count() == 3):
raise RuntimeError("test failed")

View file

@ -47,6 +47,6 @@ testdir/README file.
Further Documentation Further Documentation
--------------------- ---------------------
There is documentation about the test-suite and how to use use it in There is documentation about the test-suite and how to use it in
the SWIG documentation - Doc/Manual/Extending.html#Extending_test_suite. the SWIG documentation - Doc/Manual/Extending.html#Extending_test_suite.

View file

@ -0,0 +1,160 @@
// Test a mix of forward class declarations, class definitions, using declarations and using directives.
%module class_scope_namespace
%warnfilter(SWIGWARN_PARSE_NAMED_NESTED_CLASS) H::HH;
%warnfilter(SWIGWARN_PARSE_NAMED_NESTED_CLASS) Space8::I::II;
%inline %{
struct A;
namespace Space1 {
namespace SubSpace1 {
struct A {
void aa(Space1::SubSpace1::A, SubSpace1::A, A) {}
};
void aaa(Space1::SubSpace1::A, SubSpace1::A, A) {}
}
}
namespace Space2 {
struct B;
}
using Space2::B;
#ifdef __clang__
namespace Space2 {
struct B {
void bb(Space2::B, B) {}
};
}
#else
struct B {
void bb(Space2::B, B) {}
};
#endif
void bbb(Space2::B, B) {}
namespace Space3 {
namespace SubSpace3 {
struct C;
struct D;
}
}
struct C;
struct D;
namespace Space3 {
struct C;
struct SubSpace3::C {
void cc(Space3::SubSpace3::C, SubSpace3::C) {}
};
using SubSpace3::D;
struct SubSpace3::D {
void dd(Space3::SubSpace3::D, SubSpace3::D, D) {}
};
void ccc(Space3::SubSpace3::C, SubSpace3::C) {}
void ddd(Space3::SubSpace3::D, SubSpace3::D, D) {}
}
namespace Space4 {
namespace SubSpace4 {
struct E;
}
}
using namespace Space4;
using SubSpace4::E;
// Was added to incorrect namespace in swig-3.0.12
struct SubSpace4::E {
void ee(Space4::SubSpace4::E, SubSpace4::E, E) {}
};
void eee(Space4::SubSpace4::E, SubSpace4::E, E) {}
namespace Space5 {
namespace SubSpace5 {
namespace SubSubSpace5 {
struct F;
}
}
}
namespace Space5 {
using namespace SubSpace5;
using SubSubSpace5::F;
// Was added to incorrect namespace in swig-3.0.12
struct SubSubSpace5::F {
void ff(Space5::SubSpace5::SubSubSpace5::F, SubSpace5::SubSubSpace5::F, SubSubSpace5::F, F) {}
};
void fff(Space5::SubSpace5::SubSubSpace5::F, SubSpace5::SubSubSpace5::F, SubSubSpace5::F, F) {}
}
namespace Space6 {
struct G;
namespace SubSpace6 {
struct G;
}
}
namespace Space6 {
struct SubSpace6::G {
void gg(Space6::SubSpace6::G, SubSpace6::G) {}
};
void ggg(Space6::SubSpace6::G, SubSpace6::G) {}
}
struct HH;
struct H {
struct HH {
void hh(H::HH) {}
};
};
void hhh(H::HH) {}
namespace Space8 {
struct II;
struct I {
struct II {
void ii(Space8::I::II, I::II) {}
};
};
void iii(Space8::I::II, I::II) {}
}
struct J;
namespace Space9 {
namespace SubSpace9 {
struct J {
void jj(Space9::SubSpace9::J, SubSpace9::J, J) {}
};
void jjj(Space9::SubSpace9::J, SubSpace9::J, J) {}
}
}
namespace Space10 {
struct K;
}
namespace Space10 {
namespace SubSpace10 {
struct K {
void kk(Space10::SubSpace10::K, SubSpace10::K, K) {}
};
void kkk(Space10::SubSpace10::K, SubSpace10::K, K) {}
}
}
namespace OtherSpace {
struct L;
struct M;
}
using OtherSpace::L;
namespace Space11 {
using OtherSpace::M;
namespace SubSpace11 {
struct L {
void ll(Space11::SubSpace11::L, SubSpace11::L, L) {}
};
void lll(Space11::SubSpace11::L, SubSpace11::L, L) {}
struct M {
void mm(Space11::SubSpace11::M, SubSpace11::M, M) {}
};
void mmm(Space11::SubSpace11::M, SubSpace11::M, M) {}
}
}
%}

View file

@ -136,6 +136,7 @@ CPP_TEST_CASES += \
char_binary \ char_binary \
char_strings \ char_strings \
chartest \ chartest \
class_scope_namespace \
class_forward \ class_forward \
class_ignore \ class_ignore \
class_scope_weird \ class_scope_weird \
@ -291,6 +292,7 @@ CPP_TEST_CASES += \
multiple_inheritance_shared_ptr \ multiple_inheritance_shared_ptr \
name_cxx \ name_cxx \
name_warnings \ name_warnings \
namespace_chase \
namespace_class \ namespace_class \
namespace_enum \ namespace_enum \
namespace_extend \ namespace_extend \
@ -418,6 +420,7 @@ CPP_TEST_CASES += \
template_default_inherit \ template_default_inherit \
template_default_qualify \ template_default_qualify \
template_default_vw \ template_default_vw \
template_empty_inherit \
template_enum \ template_enum \
template_enum_ns_inherit \ template_enum_ns_inherit \
template_enum_typedef \ template_enum_typedef \
@ -434,6 +437,7 @@ CPP_TEST_CASES += \
template_methods \ template_methods \
template_namespace_forward_declaration \ template_namespace_forward_declaration \
template_using_directive_and_declaration_forward \ template_using_directive_and_declaration_forward \
template_using_directive_typedef \
template_nested \ template_nested \
template_nested_typemaps \ template_nested_typemaps \
template_ns \ template_ns \
@ -444,6 +448,7 @@ CPP_TEST_CASES += \
template_ns_enum2 \ template_ns_enum2 \
template_ns_inherit \ template_ns_inherit \
template_ns_scope \ template_ns_scope \
template_parameters_global_scope \
template_partial_arg \ template_partial_arg \
template_partial_specialization \ template_partial_specialization \
template_partial_specialization_typedef \ template_partial_specialization_typedef \

View file

@ -1,12 +1,32 @@
/* This test case checks whether SWIG correctly parses and ignores the /* This test case checks whether SWIG correctly parses and ignores
keywords "static_assert()" inside the class or struct. "static_assert()" in various places.
*/ */
%module cpp11_static_assert %module cpp11_static_assert
%inline %{ %inline %{
static_assert(sizeof(int) >= 2, "What? int size is invalid!");
namespace dummy {
// C++17 allows the message to be omitted, so check that works too.
// But only show the C++17 version to SWIG, as the compiler may
// lack C++17 support.
#ifdef SWIG
static_assert(sizeof(int) >= sizeof(short));
#else
static_assert(sizeof(int) >= sizeof(short), "blah");
#endif
}
template <typename T> template <typename T>
struct Check1 { struct Check1 {
static_assert(sizeof(int) <= sizeof(T), "not big enough"); static_assert(sizeof(int) <= sizeof(T), "not big enough");
Check1() {
#ifdef SWIG
static_assert(true);
#else
static_assert(true, "true");
#endif
}
}; };
template <typename T> template <typename T>

View file

@ -18,7 +18,7 @@ public class li_std_map_runme {
public static void Main() public static void Main()
{ {
// Set up an int int map // Set up an string to int map
StringIntMap simap = new StringIntMap(); StringIntMap simap = new StringIntMap();
for (int i = 0; i < collectionSize; i++) for (int i = 0; i < collectionSize; i++)
{ {

View file

@ -25,7 +25,7 @@ namespace Swig {
size_t ExceptionMethod() size_t ExceptionMethod()
{ {
// Check positioning of director code in wrapper file // Check positioning of director code in wrapper file
// Below is what we really want to test, but director exceptions vary too much across across all languages // Below is what we really want to test, but director exceptions vary too much across all languages
// throw Swig::DirectorException("DirectorException was not in scope!!"); // throw Swig::DirectorException("DirectorException was not in scope!!");
// Instead check definition of Director class as that is defined in the same place as DirectorException (director.swg) // Instead check definition of Director class as that is defined in the same place as DirectorException (director.swg)
size_t size = sizeof(Swig::Director); size_t size = sizeof(Swig::Director);

View file

@ -0,0 +1,26 @@
%module xxx
// This should error but doesn't
#if 0
namespace OtherSpace {
struct L;
}
namespace Space11 {
namespace SubSpace11 {
using OtherSpace::L;
struct L {
void ll();
};
}
}
#endif
namespace Space1 {
struct A;
}
namespace Space2 {
struct Space1::A {
void x();
};
}

View file

@ -0,0 +1 @@
cpp_class_definition.i:22: Error: 'Space1::A' resolves to 'Space1::A' and was incorrectly instantiated in scope 'Space2' instead of within scope 'Space1'.

View file

@ -0,0 +1,9 @@
%module cpp_invalid_scope
%template(abc) SSS::AAA<int>;
namespace UUU {
struct JJJ;
}
%template(xxx) UUU::JJJ<int>;

View file

@ -0,0 +1,3 @@
cpp_invalid_template.i:3: Error: Undefined scope 'SSS'
cpp_invalid_template.i:3: Error: Template 'SSS::AAA' undefined.
cpp_invalid_template.i:9: Error: 'JJJ' is not defined as a template. (classforward)

View file

@ -0,0 +1,40 @@
%module namespace_template
namespace test {
template<typename T> T max(T a, T b) { return (a > b) ? a : b; }
template<typename T> class vector {
public:
vector() { }
~vector() { }
};
}
namespace test2 {
using namespace test;
%template(maxshort) max<short>;
%template(vectorshort) vector<short>;
}
namespace test3 {
using test::max;
using test::vector;
%template(maxlong) max<long>;
%template(vectorlong) vector<long>;
}
namespace test4 {
using namespace test;
typedef int Integer;
}
namespace test4 {
%template(maxInteger) max<Integer>;
%template(vectorInteger) vector<Integer>;
}
using namespace test;
namespace test5 {
%template(maxdouble) max<double>;
%template(vectordouble) vector<double>;
}

View file

@ -0,0 +1,9 @@
cpp_namespace_template_bad.i:14: Error: 'max' resolves to 'test::max' and was incorrectly instantiated in scope 'test2' instead of within scope 'test'.
cpp_namespace_template_bad.i:15: Error: 'vector' resolves to 'test::vector' and was incorrectly instantiated in scope 'test2' instead of within scope 'test'.
cpp_namespace_template_bad.i:21: Error: 'max' resolves to 'test::max' and was incorrectly instantiated in scope 'test3' instead of within scope 'test'.
cpp_namespace_template_bad.i:22: Error: 'vector' resolves to 'test::vector' and was incorrectly instantiated in scope 'test3' instead of within scope 'test'.
cpp_namespace_template_bad.i:31: Error: 'max' resolves to 'test::max' and was incorrectly instantiated in scope 'test4' instead of within scope 'test'.
cpp_namespace_template_bad.i:32: Error: 'vector' resolves to 'test::vector' and was incorrectly instantiated in scope 'test4' instead of within scope 'test'.
cpp_namespace_template_bad.i:37: Error: 'max' resolves to 'test::max' and was incorrectly instantiated in scope 'test5' instead of within scope 'test'.
cpp_namespace_template_bad.i:37: Error: Template 'max' undefined.
cpp_namespace_template_bad.i:38: Error: 'vector' resolves to 'test::vector' and was incorrectly instantiated in scope 'test5' instead of within scope 'test'.

View file

@ -1,2 +1,4 @@
cpp_nested_template.i:9: Error: 'Temply' resolves to '::Temply' and was incorrectly instantiated in scope 'A' instead of within scope ''.
cpp_nested_template.i:9: Warning 324: Named nested template instantiations not supported. Processing as if no name was given to %template(). cpp_nested_template.i:9: Warning 324: Named nested template instantiations not supported. Processing as if no name was given to %template().
cpp_nested_template.i:18: Error: 'Temply' resolves to '::Temply' and was incorrectly instantiated in scope 'B' instead of within scope ''.
cpp_nested_template.i:18: Warning 324: Named nested template instantiations not supported. Processing as if no name was given to %template(). cpp_nested_template.i:18: Warning 324: Named nested template instantiations not supported. Processing as if no name was given to %template().

View file

@ -0,0 +1,57 @@
%module xxx
namespace std {
template<typename T> class vector {};
}
struct S1 {};
struct S2 {};
struct S3 {};
struct S4 {};
struct S5 {};
struct S6 {};
struct S7 {};
// valid
namespace std {
%template(vi1) vector<S1>;
template class vector<S1>;
}
// valid
using namespace std;
%template(vi2) vector<S2>;
template class vector<S2>;
// valid
using std::vector;
%template(vi3) vector<S3>;
template class vector<S3>;
// ill-formed
namespace unrelated {
using std::vector;
%template(vi4) vector<S4>;
template class vector<S4>;
}
// ill-formed
namespace unrelated {
using namespace std;
%template(vi5) vector<S5>;
template class vector<S5>;
}
// ill-formed
namespace unrelated {
namespace std {
%template(vi6) vector<S6>;
template class vector<S6>;
}
}
// ill-formed
namespace unrelated {
%template(vi7) std::vector<S7>;
template class std::vector<S7>;
}

View file

@ -0,0 +1,11 @@
cpp_template_scope.i:18: Warning 320: Explicit template instantiation ignored.
cpp_template_scope.i:24: Warning 320: Explicit template instantiation ignored.
cpp_template_scope.i:29: Warning 320: Explicit template instantiation ignored.
cpp_template_scope.i:34: Error: 'vector' resolves to 'std::vector' and was incorrectly instantiated in scope 'unrelated' instead of within scope 'std'.
cpp_template_scope.i:35: Warning 320: Explicit template instantiation ignored.
cpp_template_scope.i:41: Error: 'vector' resolves to 'std::vector' and was incorrectly instantiated in scope 'unrelated' instead of within scope 'std'.
cpp_template_scope.i:42: Warning 320: Explicit template instantiation ignored.
cpp_template_scope.i:48: Error: 'vector' resolves to 'std::vector' and was incorrectly instantiated in scope 'unrelated::std' instead of within scope 'std'.
cpp_template_scope.i:49: Warning 320: Explicit template instantiation ignored.
cpp_template_scope.i:55: Error: 'std::vector' resolves to 'std::vector' and was incorrectly instantiated in scope 'unrelated' instead of within scope 'std'.
cpp_template_scope.i:56: Warning 320: Explicit template instantiation ignored.

View file

@ -0,0 +1,59 @@
import class_scope_namespace.*;
public class class_scope_namespace_runme {
static {
try {
System.loadLibrary("class_scope_namespace");
} catch (UnsatisfiedLinkError e) {
System.err.println("Native code library failed to load. See the chapter on Dynamic Linking Problems in the SWIG Java documentation for help.\n" + e);
System.exit(1);
}
}
public static void main(String argv[])
{
A a = new A();
B b = new B();
C c = new C();
D d = new D();
E e = new E();
F f = new F();
G g = new G();
H.HH h = new H.HH();
I.II i = new I.II();
J j = new J();
K k = new K();
L l = new L();
M m = new M();
a.aa(a, a, a);
b.bb(b, b);
c.cc(c, c);
d.dd(d, d, d);
e.ee(e, e, e);
f.ff(f, f, f, f);
g.gg(g, g);
h.hh(h);
i.ii(i, i);
j.jj(j, j, j);
k.kk(k, k, k);
l.ll(l, l, l);
m.mm(m, m, m);
class_scope_namespace.aaa(a, a, a);
class_scope_namespace.bbb(b, b);
class_scope_namespace.ccc(c, c);
class_scope_namespace.ddd(d, d, d);
class_scope_namespace.eee(e, e, e);
class_scope_namespace.fff(f, f, f, f);
class_scope_namespace.ggg(g, g);
class_scope_namespace.hhh(h);
class_scope_namespace.iii(i, i);
class_scope_namespace.jjj(j, j, j);
class_scope_namespace.kkk(k, k, k);
class_scope_namespace.lll(l, l, l);
class_scope_namespace.mmm(m, m, m);
}
}

View file

@ -0,0 +1,19 @@
import cpp11_template_typedefs.*;
public class cpp11_template_typedefs_runme {
static {
try {
System.loadLibrary("cpp11_template_typedefs");
} catch (UnsatisfiedLinkError e) {
System.err.println("Native code library failed to load. See the chapter on Dynamic Linking Problems in the SWIG Java documentation for help.\n" + e);
System.exit(1);
}
}
public static void main(String argv[]) {
int alloc1 = cpp11_template_typedefs.get_bucket_allocator1();
int alloc2 = cpp11_template_typedefs.get_bucket_allocator2();
}
}

View file

@ -0,0 +1,26 @@
import namespace_chase.*;
public class namespace_chase_runme {
static {
try {
System.loadLibrary("namespace_chase");
} catch (UnsatisfiedLinkError e) {
System.err.println("Native code library failed to load. See the chapter on Dynamic Linking Problems in the SWIG Java documentation for help.\n" + e);
System.exit(1);
}
}
public static void main(String argv[])
{
Struct1A s1a = new Struct1A();
Struct1B s1b = new Struct1B();
Struct1C s1c = new Struct1C();
namespace_chase.sss3a(s1a, s1b, s1c);
namespace_chase.sss3b(s1a, s1b, s1c);
// needs fixing
// namespace_chase.sss3c(s1a, s1b, s1c);
}
}

View file

@ -0,0 +1,32 @@
import namespace_template.*;
public class namespace_template_runme {
static {
try {
System.loadLibrary("namespace_template");
} catch (UnsatisfiedLinkError e) {
System.err.println("Native code library failed to load. See the chapter on Dynamic Linking Problems in the SWIG Java documentation for help.\n" + e);
System.exit(1);
}
}
public static void main(String argv[]) {
vectorchar vc = new vectorchar();
vectorshort vs = new vectorshort();
vectorint vi = new vectorint();
vectorlong vl = new vectorlong();
vc.blah((char)10);
vs.blah((short)10);
vi.blah(10);
vl.blah(10);
vc.vectoruse(vc, vc);
vs.vectoruse(vs, vs);
vi.vectoruse(vi, vi);
vl.vectoruse(vl, vl);
}
}

View file

@ -0,0 +1,75 @@
import template_parameters_global_scope.*;
public class template_parameters_global_scope_runme {
static {
try {
System.loadLibrary("template_parameters_global_scope");
} catch (UnsatisfiedLinkError e) {
System.err.println("Native code library failed to load. See the chapter on Dynamic Linking Problems in the SWIG Java documentation for help.\n" + e);
System.exit(1);
}
}
public static void main(String argv[]) {
int alloc = 0;
// Check 1
alloc = template_parameters_global_scope.Bucket1();
alloc = template_parameters_global_scope.Bucket2();
alloc = template_parameters_global_scope.Bucket3();
alloc = template_parameters_global_scope.Bucket4();
alloc = template_parameters_global_scope.Bucket5();
alloc = template_parameters_global_scope.Bucket6();
// Check 2
alloc = template_parameters_global_scope.Spade1();
alloc = template_parameters_global_scope.Spade2();
alloc = template_parameters_global_scope.Spade3();
alloc = template_parameters_global_scope.Spade4();
alloc = template_parameters_global_scope.Spade5();
alloc = template_parameters_global_scope.Spade6();
// Check 3
alloc = template_parameters_global_scope.Ball1();
alloc = template_parameters_global_scope.Ball2();
alloc = template_parameters_global_scope.Ball3();
alloc = template_parameters_global_scope.Ball4();
alloc = template_parameters_global_scope.Ball5();
alloc = template_parameters_global_scope.Ball6();
// Check 4
alloc = template_parameters_global_scope.Bat1();
alloc = template_parameters_global_scope.Bat2();
alloc = template_parameters_global_scope.Bat3();
alloc = template_parameters_global_scope.Bat4();
alloc = template_parameters_global_scope.Bat5();
alloc = template_parameters_global_scope.Bat6();
// Check 5
alloc = template_parameters_global_scope.Chair1();
alloc = template_parameters_global_scope.Chair2();
alloc = template_parameters_global_scope.Chair3();
alloc = template_parameters_global_scope.Chair4();
alloc = template_parameters_global_scope.Chair5();
alloc = template_parameters_global_scope.Chair6();
// Check 6
alloc = template_parameters_global_scope.Table1();
alloc = template_parameters_global_scope.Table2();
alloc = template_parameters_global_scope.Table3();
alloc = template_parameters_global_scope.Table4();
alloc = template_parameters_global_scope.Table5();
alloc = template_parameters_global_scope.Table6();
/*
alloc = template_parameters_global_scope.rejig1();
alloc = template_parameters_global_scope.rejig2();
alloc = template_parameters_global_scope.rejig3();
alloc = template_parameters_global_scope.rejig4();
alloc = template_parameters_global_scope.rejig5();
alloc = template_parameters_global_scope.rejig6();
*/
}
}

View file

@ -19,32 +19,32 @@ public class template_using_directive_and_declaration_forward_runme {
template_using_directive_and_declaration_forward.useit1b(new Thing1Int()); template_using_directive_and_declaration_forward.useit1b(new Thing1Int());
template_using_directive_and_declaration_forward.useit1c(new Thing1Int()); template_using_directive_and_declaration_forward.useit1c(new Thing1Int());
//BROKEN template_using_directive_and_declaration_forward.useit2(new Thing2Int()); template_using_directive_and_declaration_forward.useit2(new Thing2Int());
template_using_directive_and_declaration_forward.useit2a(new Thing2Int()); template_using_directive_and_declaration_forward.useit2a(new Thing2Int());
template_using_directive_and_declaration_forward.useit2b(new Thing2Int()); template_using_directive_and_declaration_forward.useit2b(new Thing2Int());
template_using_directive_and_declaration_forward.useit2c(new Thing2Int()); template_using_directive_and_declaration_forward.useit2c(new Thing2Int());
template_using_directive_and_declaration_forward.useit2d(new Thing2Int()); template_using_directive_and_declaration_forward.useit2d(new Thing2Int());
//BROKEN template_using_directive_and_declaration_forward.useit3(new Thing3Int()); template_using_directive_and_declaration_forward.useit3(new Thing3Int());
template_using_directive_and_declaration_forward.useit3a(new Thing3Int()); template_using_directive_and_declaration_forward.useit3a(new Thing3Int());
template_using_directive_and_declaration_forward.useit3b(new Thing3Int()); template_using_directive_and_declaration_forward.useit3b(new Thing3Int());
template_using_directive_and_declaration_forward.useit3c(new Thing3Int()); template_using_directive_and_declaration_forward.useit3c(new Thing3Int());
template_using_directive_and_declaration_forward.useit3d(new Thing3Int()); template_using_directive_and_declaration_forward.useit3d(new Thing3Int());
//BROKEN template_using_directive_and_declaration_forward.useit4(new Thing4Int()); template_using_directive_and_declaration_forward.useit4(new Thing4Int());
template_using_directive_and_declaration_forward.useit4a(new Thing4Int()); template_using_directive_and_declaration_forward.useit4a(new Thing4Int());
template_using_directive_and_declaration_forward.useit4b(new Thing4Int()); template_using_directive_and_declaration_forward.useit4b(new Thing4Int());
template_using_directive_and_declaration_forward.useit4c(new Thing4Int()); template_using_directive_and_declaration_forward.useit4c(new Thing4Int());
template_using_directive_and_declaration_forward.useit4d(new Thing4Int()); template_using_directive_and_declaration_forward.useit4d(new Thing4Int());
//BROKEN template_using_directive_and_declaration_forward.useit5(new Thing5Int()); template_using_directive_and_declaration_forward.useit5(new Thing5Int());
template_using_directive_and_declaration_forward.useit5a(new Thing5Int()); template_using_directive_and_declaration_forward.useit5a(new Thing5Int());
template_using_directive_and_declaration_forward.useit5b(new Thing5Int()); template_using_directive_and_declaration_forward.useit5b(new Thing5Int());
template_using_directive_and_declaration_forward.useit5c(new Thing5Int()); template_using_directive_and_declaration_forward.useit5c(new Thing5Int());
template_using_directive_and_declaration_forward.useit5d(new Thing5Int()); template_using_directive_and_declaration_forward.useit5d(new Thing5Int());
//BROKEN template_using_directive_and_declaration_forward.useit7(new Thing7Int()); template_using_directive_and_declaration_forward.useit7(new Thing7Int());
template_using_directive_and_declaration_forward.useit7a(new Thing7Int()); template_using_directive_and_declaration_forward.useit7a(new Thing7Int());
template_using_directive_and_declaration_forward.useit7b(new Thing7Int()); template_using_directive_and_declaration_forward.useit7b(new Thing7Int());
template_using_directive_and_declaration_forward.useit7c(new Thing7Int()); template_using_directive_and_declaration_forward.useit7c(new Thing7Int());

View file

@ -0,0 +1,31 @@
import template_using_directive_typedef.*;
public class template_using_directive_typedef_runme {
static {
try {
System.loadLibrary("template_using_directive_typedef");
} catch (UnsatisfiedLinkError e) {
System.err.println("Native code library failed to load. See the chapter on Dynamic Linking Problems in the SWIG Java documentation for help.\n" + e);
System.exit(1);
}
}
public static void main(String argv[]) {
Vector_Obj vo = new Vector_Obj();
Holder h = new Holder();
h.holder_use1(vo, vo, vo);
h.holder_use2(vo, vo, vo);
h.holder_use3(vo, vo, vo);
template_using_directive_typedef.tns_holder_use(vo, vo);
template_using_directive_typedef.tns_use(vo, vo, vo);
template_using_directive_typedef.global_holder_use(vo);
template_using_directive_typedef.global_use(vo, vo, vo);
template_using_directive_typedef.ns1_holder_use(vo);
template_using_directive_typedef.ns2_holder_use(vo, vo, vo, vo);
}
}

View file

@ -0,0 +1,36 @@
%module namespace_chase
%inline %{
namespace Space1A {
struct Struct1A {};
namespace Space1B {
struct Struct1B {};
namespace Space1C {
struct Struct1C {};
}
}
}
namespace Space2A {
using namespace Space1A;
namespace Space2B {
using namespace Space1B;
namespace Space2C {
using namespace Space1C;
}
}
}
namespace Space3 {
using namespace Space2A;
void sss3a(Space1A::Struct1A, Space1A::Space1B::Struct1B, Space1A::Space1B::Space1C::Struct1C) {}
void sss3b(Struct1A, Space1B::Struct1B, Space1B::Space1C::Struct1C) {}
// To fix: the last two parameters below fail and result in SWIGTYPE_ types instead of proxy classes
void sss3c(Space2A::Struct1A, Space2A::Space1B::Struct1B, Space2A::Space1B::Space1C::Struct1C) {}
}
namespace Space4 {
using namespace Space2A;
using namespace Space2A::Space2B;
using namespace Space2A::Space2B::Space2C;
void sss4a(Struct1A, Struct1B, Space2C::Struct1C) {}
void sss4b(Struct1A, Struct1B, Struct1C) {}
}
%}

View file

@ -2,10 +2,10 @@
%module namespace_template %module namespace_template
%warnfilter(SWIGWARN_RUBY_WRONG_NAME) vector<int>; /* Ruby, wrong class name */ %warnfilter(SWIGWARN_RUBY_WRONG_NAME) test::vector<int>; /* Ruby, wrong class name */
%warnfilter(SWIGWARN_RUBY_WRONG_NAME) test2::vector<short>; /* Ruby, wrong class name */ %warnfilter(SWIGWARN_RUBY_WRONG_NAME) test::vector<short>; /* Ruby, wrong class name */
%warnfilter(SWIGWARN_RUBY_WRONG_NAME) test3::vector<long>; /* Ruby, wrong class name */ %warnfilter(SWIGWARN_RUBY_WRONG_NAME) test::vector<long>; /* Ruby, wrong class name */
%warnfilter(SWIGWARN_RUBY_WRONG_NAME) vector<test4::Integer>; /* Ruby, wrong class name */ %warnfilter(SWIGWARN_RUBY_WRONG_NAME) test::vector<test::Char>; /* Ruby, wrong class name */
%{ %{
#ifdef max #ifdef max
@ -23,20 +23,9 @@ namespace test {
char * blah(T x) { char * blah(T x) {
return (char *) "vector::blah"; return (char *) "vector::blah";
} }
void vectoruse(vector<T> a, test::vector<T> b) {}
}; };
} }
namespace test2 {
using namespace test;
}
namespace test3 {
using test::max;
using test::vector;
}
using namespace test2;
namespace T4 = test;
%} %}
namespace test { namespace test {
@ -48,6 +37,7 @@ namespace test {
char * blah(T x) { char * blah(T x) {
return (char *) "vector::blah"; return (char *) "vector::blah";
} }
void vectoruse(vector<T> a, test::vector<T> b) {}
}; };
} }
@ -55,30 +45,26 @@ using namespace test;
%template(maxint) max<int>; %template(maxint) max<int>;
%template(vectorint) vector<int>; %template(vectorint) vector<int>;
namespace test2 { namespace test {
using namespace test;
%template(maxshort) max<short>; %template(maxshort) max<short>;
%template(vectorshort) vector<short>; %template(vectorshort) vector<short>;
} }
namespace test3 { namespace test {
using test::max;
using test::vector;
%template(maxlong) max<long>; %template(maxlong) max<long>;
%template(vectorlong) vector<long>; %template(vectorlong) vector<long>;
} }
%inline %{ %inline %{
namespace test4 { namespace test {
using namespace test; typedef char Char;
typedef int Integer;
} }
%} %}
namespace test4 { namespace test {
%template(maxInteger) max<Integer>; %template(maxchar) max<Char>;
%template(vectorInteger) vector<Integer>; %template(vectorchar) vector<Char>;
} }

View file

@ -6,7 +6,7 @@ Test::More Support
== ==
Test::More is a standard perl test harness tool. Test::More is a standard perl test harness tool.
Support was added for for using Test::More in 1.3.28. Support was added for using Test::More in 1.3.28.
If adding a new test to this suite, please use Test::More. If adding a new test to this suite, please use Test::More.
There are a few legacy test cases which do not use Test::More and these ought to be converted: There are a few legacy test cases which do not use Test::More and these ought to be converted:

View file

@ -9,4 +9,3 @@ check::equal('1.5',(new ReflectionExtension('php_pragma'))->getVersion(),"1.5==v
check::done(); check::done();
?> ?>

View file

@ -372,8 +372,9 @@ int methodX(int x) { return x+100; }
// Comma in macro - Github issue #974 // Comma in macro - Github issue #974
%inline %{ %inline %{
#define __attribute__(x) #define swig__attribute__(x)
#define TCX_PACKED(d) d __attribute__ ((__packed__)) #define TCX_PACKED(d) d swig__attribute__ ((__packed__))
TCX_PACKED (typedef struct tcxMessageTestImpl TCX_PACKED (typedef struct tcxMessageTestImpl
{ {

View file

@ -0,0 +1,15 @@
import template_using_directive_typedef
vo = template_using_directive_typedef.Vector_Obj();
h = template_using_directive_typedef.Holder();
h.holder_use1(vo, vo, vo);
h.holder_use2(vo, vo, vo);
h.holder_use3(vo, vo, vo);
template_using_directive_typedef.tns_holder_use(vo, vo);
template_using_directive_typedef.tns_use(vo, vo, vo);
template_using_directive_typedef.global_holder_use(vo);
template_using_directive_typedef.global_use(vo, vo, vo);
template_using_directive_typedef.ns1_holder_use(vo);
template_using_directive_typedef.ns2_holder_use(vo, vo, vo, vo);

View file

@ -0,0 +1,32 @@
from typemap_template_typedef import *
def check(got, expected):
if got != expected:
raise RuntimeError("got: " + str(got) + " expected: " + str(expected))
x = XXXInt()
check(x.aa1(0), 0)
check(x.aa2(0), 55)
check(x.aa3(0), 0)
check(aa1(0), 0)
check(aa2(0), 0)
check(x.bb1(0), 0)
check(x.bb2(0), 66)
check(x.bb3(0), 0)
check(bb1(0), 0)
check(bb2(0), 0)
check(x.cc1(0), 0)
check(x.cc2(0), 77)
check(x.cc3(0), 77)
check(cc1(0), 0)
check(cc2(0), 0)
check(x.dd1(0), 0)
check(x.dd2(0), 88)
check(x.dd3(0), 0)
check(dd1(0), 0)
check(dd2(0), 0)

View file

@ -49,11 +49,6 @@ namespace one
}; };
} }
%define PTR_DEF(o)
typedef one::Ptr<o> o ## _ptr;
%template(o ## _ptr) one::Ptr<o>;
%enddef
namespace one namespace one
{ {
class Obj1 class Obj1
@ -63,7 +58,8 @@ namespace one
void donothing() {} void donothing() {}
}; };
PTR_DEF(Obj1) typedef one::Ptr<Obj1> Obj1_ptr;
%template(Obj1_ptr) one::Ptr<Obj1>;
} }
namespace two namespace two
@ -75,6 +71,9 @@ namespace two
void donothing() {} void donothing() {}
}; };
PTR_DEF(Obj2) typedef one::Ptr<Obj2> Obj2_ptr;
} }
using two::Obj2;
%template(Obj2_ptr) one::Ptr<Obj2>;

View file

@ -0,0 +1,33 @@
%module template_empty_inherit
%rename(FunctorOperator) operator();
%inline %{
template<class Arg, typename Result> struct Functor {
virtual Result operator()(Arg x) const = 0;
};
%}
// Bug fix - %ignore was resulting in this warning:
// Warning 401: Base class 'Functor< int,int >' has no name as it is an empty template instantiated with '%template()'. Ignored.
%ignore Functor<int, int>;
%template() Functor<int, int>;
%inline %{
#include <algorithm>
#include <iterator>
struct SquareFunctor : Functor<int, int> {
int operator()(int v) const { return v*v; }
};
%}
%include <std_vector.i>
%template(VectorInt) std::vector<int>;
%inline %{
std::vector<int> squares(const std::vector<int>& vi) {
std::vector<int> result;
std::transform(vi.begin(), vi.end(), std::back_inserter(result), SquareFunctor());
return result;
}
%}

View file

@ -1,25 +1,30 @@
#pragma SWIG nowarn=SWIGWARN_PARSE_NESTED_TEMPLATE
%module template_nested_typemaps %module template_nested_typemaps
// Testing that the typemaps invoked within a class via %template are picked up by appropriate methods #pragma SWIG nowarn=SWIGWARN_PARSE_NAMED_NESTED_CLASS
template <typename T> struct Typemap { // Testing that the typemaps invoked within a class via %template are picked up by appropriate methods
%typemap(in) T { // Only for languages that support nested classes
$1 = -99;
}
};
template <> struct Typemap<short> { // Note explicit specialization
%typemap(in) short {
$1 = -77;
}
};
%inline %{ %inline %{
int globalInt1(int s) { return s; } int globalInt1(int s) { return s; }
short globalShort1(short s) { return s; } short globalShort1(short s) { return s; }
template <typename T> struct Breeze { template <typename T> struct Breeze {
template <typename TMT> struct Typemap {
#ifdef SWIG
%typemap(in) TMT {
$1 = -99;
}
#endif
};
template <typename TMT> struct TypemapShort {
#ifdef SWIG
%typemap(in) short {
$1 = -77;
}
#endif
};
int methodInt1(int s) { return s; } int methodInt1(int s) { return s; }
#if defined(SWIG) #if defined(SWIG)
%template() Typemap<int>; %template() Typemap<int>;
@ -29,7 +34,7 @@ template <typename T> struct Breeze {
short methodShort1(short s) { return s; } short methodShort1(short s) { return s; }
#if defined(SWIG) #if defined(SWIG)
%template(TypemapShort) Typemap<short>; // should issue warning SWIGWARN_PARSE_NESTED_TEMPLATE %template() TypemapShort<short>;
#endif #endif
short methodShort2(short s) { return s; } // should pick up the typemap within Typemap<short> short methodShort2(short s) { return s; } // should pick up the typemap within Typemap<short>
}; };

View file

@ -0,0 +1,133 @@
%module template_parameters_global_scope
%inline %{
namespace Alloc {
template<typename T> struct Rebind {
typedef int Integer;
};
}
%}
%inline %{
struct Bucket_ {};
typedef Bucket_ TDBucket;
typedef ::Bucket_ TDGlobalBucket;
%}
// Check 1: %template no unary scope operator
%template(RebindBucket) Alloc::Rebind< Bucket_ >;
%inline %{
Alloc::Rebind< Bucket_ >::Integer Bucket1() { return 1; }
Alloc::Rebind< ::Bucket_ >::Integer Bucket2() { return 2; }
Alloc::Rebind< TDBucket >::Integer Bucket3() { return 3; }
Alloc::Rebind< ::TDBucket >::Integer Bucket4() { return 4; }
Alloc::Rebind< TDGlobalBucket >::Integer Bucket5() { return 5; }
Alloc::Rebind< ::TDGlobalBucket >::Integer Bucket6() { return 6; }
%}
// Check 2: %template with unary scope operator
%inline %{
struct Spade {};
typedef Spade TDSpade;
typedef ::Spade TDGlobalSpade;
%}
%template(RebindSpade) Alloc::Rebind< ::Spade >;
%inline %{
Alloc::Rebind< Spade >::Integer Spade1() { return 1; }
Alloc::Rebind< ::Spade >::Integer Spade2() { return 2; }
Alloc::Rebind< TDSpade >::Integer Spade3() { return 3; }
Alloc::Rebind< ::TDSpade >::Integer Spade4() { return 4; }
Alloc::Rebind< TDGlobalSpade >::Integer Spade5() { return 5; }
Alloc::Rebind< ::TDGlobalSpade >::Integer Spade6() { return 6; }
%}
// Check 3: %template typedef no unary scope operator
%inline %{
struct Ball {};
typedef Ball TDBall;
typedef ::Ball TDGlobalBall;
%}
%template(RebindBall) Alloc::Rebind< TDBall >;
%inline %{
Alloc::Rebind< Ball >::Integer Ball1() { return 1; }
Alloc::Rebind< ::Ball >::Integer Ball2() { return 2; }
Alloc::Rebind< TDBall >::Integer Ball3() { return 3; }
Alloc::Rebind< ::TDBall >::Integer Ball4() { return 4; }
Alloc::Rebind< TDGlobalBall >::Integer Ball5() { return 5; }
Alloc::Rebind< ::TDGlobalBall >::Integer Ball6() { return 6; }
%}
// Check 4: %template typedef with unary scope operator
%inline %{
struct Bat {};
typedef Bat TDBat;
typedef ::Bat TDGlobalBat;
%}
%template(RebindBat) Alloc::Rebind< ::TDBat >;
%inline %{
Alloc::Rebind< Bat >::Integer Bat1() { return 1; }
Alloc::Rebind< ::Bat >::Integer Bat2() { return 2; }
Alloc::Rebind< TDBat >::Integer Bat3() { return 3; }
Alloc::Rebind< ::TDBat >::Integer Bat4() { return 4; }
Alloc::Rebind< TDGlobalBat >::Integer Bat5() { return 5; }
Alloc::Rebind< ::TDGlobalBat >::Integer Bat6() { return 6; }
%}
// Check 5: %template double typedef no unary scope operator
%inline %{
struct Chair {};
typedef Chair TDChair;
typedef ::Chair TDGlobalChair;
%}
%template(RebindChair) Alloc::Rebind< TDGlobalChair >;
%inline %{
Alloc::Rebind< Chair >::Integer Chair1() { return 1; }
Alloc::Rebind< ::Chair >::Integer Chair2() { return 2; }
Alloc::Rebind< TDChair >::Integer Chair3() { return 3; }
Alloc::Rebind< ::TDChair >::Integer Chair4() { return 4; }
Alloc::Rebind< TDGlobalChair >::Integer Chair5() { return 5; }
Alloc::Rebind< ::TDGlobalChair >::Integer Chair6() { return 6; }
%}
// Check 6: %template double typedef with unary scope operator
%inline %{
struct Table {};
typedef Table TDTable;
typedef ::Table TDGlobalTable;
%}
%template(RebindTable) Alloc::Rebind< ::TDGlobalTable >;
%inline %{
Alloc::Rebind< Table >::Integer Table1() { return 1; }
Alloc::Rebind< ::Table >::Integer Table2() { return 2; }
Alloc::Rebind< TDTable >::Integer Table3() { return 3; }
Alloc::Rebind< ::TDTable >::Integer Table4() { return 4; }
Alloc::Rebind< TDGlobalTable >::Integer Table5() { return 5; }
Alloc::Rebind< ::TDGlobalTable >::Integer Table6() { return 6; }
%}
#if 0
%inline %{
namespace Alloc {
template<typename T=::Spade/*, typename T2=TDSpade, typename T3=::TDSpade, typename T4=TDGlobalSpade, typename T5=::TDGlobalSpade*/> struct Rejig {
typedef int Integer;
};
}
%}
%template(RejigSpade) Alloc::Rejig<::Spade>;
%inline %{
Alloc::Rejig<>::Integer rejig1() { return 1; }
Alloc::Rejig< ::Spade >::Integer rejig2() { return 2; }
Alloc::Rejig< ::TDSpade >::Integer rejig3() { return 3; }
Alloc::Rejig< ::TDSpade >::Integer rejig4() { return 4; }
Alloc::Rejig< TDGlobalSpade >::Integer rejig5() { return 5; }
Alloc::Rejig< ::TDGlobalSpade >::Integer rejig6() { return 6; }
%}
#endif

View file

@ -32,7 +32,7 @@ namespace One {
%template(H) One::OneParm<int **>; %template(H) One::OneParm<int **>;
// %template scope explicit specializations // %template scope explicit specializations
namespace ONE { namespace One {
%template(I) One::OneParm<float>; %template(I) One::OneParm<float>;
%template(J) ::One::OneParm<float *>; %template(J) ::One::OneParm<float *>;
} }
@ -42,7 +42,7 @@ namespace One {
} }
// %template scope partial specializations // %template scope partial specializations
namespace ONE { namespace One {
%template(BB) One::OneParm<bool *>; %template(BB) One::OneParm<bool *>;
%template(BBB) ::One::OneParm<char *>; %template(BBB) ::One::OneParm<char *>;
} }

View file

@ -59,7 +59,7 @@ namespace One {
%template(H) One::OneParm<TypeDef::IntPtrPtr>; %template(H) One::OneParm<TypeDef::IntPtrPtr>;
// %template scope explicit specializations // %template scope explicit specializations
namespace ONE { namespace One {
%template(I) One::OneParm<TypeDef::Float>; %template(I) One::OneParm<TypeDef::Float>;
%template(J) ::One::OneParm<TypeDef::FloatPtr>; %template(J) ::One::OneParm<TypeDef::FloatPtr>;
} }
@ -69,7 +69,7 @@ namespace One {
} }
// %template scope partial specializations // %template scope partial specializations
namespace ONE { namespace One {
%template(BB) One::OneParm<TypeDef::BoolPtr>; %template(BB) One::OneParm<TypeDef::BoolPtr>;
%template(BBB) ::One::OneParm<TypeDef::CharPtr>; %template(BBB) ::One::OneParm<TypeDef::CharPtr>;
} }

View file

@ -0,0 +1,44 @@
%module template_using_directive_typedef
%inline %{
namespace space {
template<typename T> class Vector {};
class VectorClass {};
}
struct Obj {};
%}
%template(Vector_Obj) space::Vector<Obj>;
%inline %{
namespace tns {
using space::Vector; // template using directives were not being added into the typedef table
using space::VectorClass;
typedef Vector<Obj> NSVec;
}
%}
%inline %{
namespace tns {
struct Holder {
// using Vec = Vector<Obj>;
typedef Vector<Obj> Vec;
typedef VectorClass VecClass;
Vec items;
void holder_use1(space::Vector<Obj>, tns::NSVec, tns::Vector<Obj>) {}
void holder_use2(space::Vector<Obj>, NSVec, Vector<Obj>) {}
void holder_use3(tns::Holder::Vec, Holder::Vec, Vec) {}
};
void tns_holder_use(tns::Holder::Vec, Holder::Vec) {}
void tns_use(space::Vector<Obj>, NSVec, tns::NSVec) {}
}
void global_holder_use(tns::Holder::Vec) {}
void global_use(space::Vector<Obj>, tns::NSVec, tns::Vector<Obj>) {}
namespace ns1 {
void ns1_holder_use(tns::Holder::Vec) {}
}
namespace ns2 {
using namespace tns;
void ns2_holder_use(tns::Holder::Vec, Holder::Vec, NSVec, Vector<Obj>) {}
}
%}

View file

@ -0,0 +1,66 @@
%module typemap_template_typedef
//%module("templatereduce") typemap_template_typedef
%typemap(in) int TMAP55 %{ $1 = 55; /* int TMAP55 typemap */ %}
%typemap(in) int TMAP66 %{ $1 = 66; /* int TMAP66 typemap */ %}
%typemap(in) int TMAP77 %{ $1 = 77; /* int TMAP77 typemap */ %}
%typemap(in) int TMAP88 %{ $1 = 88; /* int TMAP88 typemap */ %}
%apply int TMAP77 { XXX<int>::Long cc }
%inline %{
typedef int Integer;
template<typename T> struct XXX {
#ifdef SWIG
// In swig-3.0.12 'Long aa' was actually stored as 'long aa' in typemap table instead of 'XXX<int>::Long aa'
%apply int TMAP55 { Long aa }
%apply int TMAP66 { XXX<int>::Long bb }
%apply int TMAP88 { XXX<Integer>::Long dd }
#endif
typedef long Long;
long aa1(long aa) { return aa; }
long aa2(Long aa) { return aa; }
long bb1(long bb) { return bb; }
long bb2(Long bb) { return bb; }
long cc1(long cc) { return cc; }
long cc2(Long cc) { return cc; }
long dd1(long dd) { return dd; }
long dd2(Long dd) { return dd; }
#ifdef SWIG
%clear Long aa;
%clear XXX<int>::Long bb;
%clear XXX<Integer>::Long dd;
#endif
long aa3(Long aa) { return aa; }
long bb3(Long bb) { return bb; }
long cc3(Long cc) { return cc; }
long dd3(Long dd) { return dd; }
};
%}
%template(XXXInt) XXX<Integer>;
%clear XXX<int>::Long cc;
%inline %{
long aa1(XXX<int>::Long aa) { return aa; }
long aa2(long aa) { return aa; }
long bb1(XXX<int>::Long bb) { return bb; }
long bb2(long bb) { return bb; }
long cc1(XXX<int>::Long cc) { return cc; }
long cc2(long cc) { return cc; }
long dd1(XXX<Integer>::Long dd) { return dd; }
long dd2(long dd) { return dd; }
%}
%inline %{
typedef Integer INTEGER;
template<typename T1, typename T2 = INTEGER> struct YYY {
void meff(T1 t1, T2 t2) {}
};
%}
%template(YYYIntInt) YYY<INTEGER>;
%inline %{
void whyohwhy(YYY<INTEGER> yy) {}
%}

View file

@ -162,7 +162,7 @@
return ret; return ret;
} }
// Treat references to arrays like like references to a single element. // Treat references to arrays like references to a single element.
%apply SWIGTYPE & { SWIGTYPE ((&)[ANY]) } %apply SWIGTYPE & { SWIGTYPE ((&)[ANY]) }

View file

@ -180,7 +180,7 @@ typedef struct swig_elua_entry {
* -------------------------------------------------------------------------- */ * -------------------------------------------------------------------------- */
/* Push the string STR on the Lua stack, like lua_pushstring, but /* Push the string STR on the Lua stack, like lua_pushstring, but
prefixed with the the location of the innermost Lua call-point prefixed with the location of the innermost Lua call-point
(as formated by luaL_where). */ (as formated by luaL_where). */
SWIGRUNTIME void SWIGRUNTIME void
SWIG_Lua_pusherrstring (lua_State *L, const char *str) SWIG_Lua_pusherrstring (lua_State *L, const char *str)
@ -191,7 +191,7 @@ SWIG_Lua_pusherrstring (lua_State *L, const char *str)
} }
/* Push a formatted string generated from FMT and following args on /* Push a formatted string generated from FMT and following args on
the Lua stack, like lua_pushfstring, but prefixed with the the the Lua stack, like lua_pushfstring, but prefixed with the
location of the innermost Lua call-point (as formated by luaL_where). */ location of the innermost Lua call-point (as formated by luaL_where). */
SWIGRUNTIME void SWIGRUNTIME void
SWIG_Lua_pushferrstring (lua_State *L, const char *fmt, ...) SWIG_Lua_pushferrstring (lua_State *L, const char *fmt, ...)

View file

@ -202,8 +202,8 @@ namespace swig
// swig::SwigVar_PyObject item = OctSequence_GetItem(_seq, _index); // swig::SwigVar_PyObject item = OctSequence_GetItem(_seq, _index);
octave_value item; // * todo octave_value item; // * todo
try { try {
return swig::as<T>(item, true); return swig::as<T>(item);
} catch (std::exception& e) { } catch (const std::exception& e) {
char msg[1024]; char msg[1024];
sprintf(msg, "in sequence element %d ", _index); sprintf(msg, "in sequence element %d ", _index);
if (!Octave_Error_Occurred()) { if (!Octave_Error_Occurred()) {

View file

@ -103,14 +103,14 @@ namespace swig {
template <class Type> template <class Type>
struct traits_as<Type, value_category> { struct traits_as<Type, value_category> {
static Type as(const octave_value& obj, bool throw_error) { static Type as(const octave_value& obj) {
Type v; Type v;
int res = asval(obj, &v); int res = asval(obj, &v);
if (!obj.is_defined() || !SWIG_IsOK(res)) { if (!obj.is_defined() || !SWIG_IsOK(res)) {
if (!Octave_Error_Occurred()) { if (!Octave_Error_Occurred()) {
%type_error(swig::type_name<Type>()); %type_error(swig::type_name<Type>());
} }
if (throw_error) throw std::invalid_argument("bad type"); throw std::invalid_argument("bad type");
} }
return v; return v;
} }
@ -118,7 +118,7 @@ namespace swig {
template <class Type> template <class Type>
struct traits_as<Type, pointer_category> { struct traits_as<Type, pointer_category> {
static Type as(const octave_value& obj, bool throw_error) { static Type as(const octave_value& obj) {
Type *v = 0; Type *v = 0;
int res = traits_asptr<Type>::asptr(obj, &v); int res = traits_asptr<Type>::asptr(obj, &v);
if (SWIG_IsOK(res) && v) { if (SWIG_IsOK(res) && v) {
@ -130,21 +130,17 @@ namespace swig {
return *v; return *v;
} }
} else { } else {
// Uninitialized return value, no Type() constructor required.
static Type *v_def = (Type*) malloc(sizeof(Type));
if (!Octave_Error_Occurred()) { if (!Octave_Error_Occurred()) {
%type_error(swig::type_name<Type>()); %type_error(swig::type_name<Type>());
} }
if (throw_error) throw std::invalid_argument("bad type"); throw std::invalid_argument("bad type");
memset(v_def,0,sizeof(Type));
return *v_def;
} }
} }
}; };
template <class Type> template <class Type>
struct traits_as<Type*, pointer_category> { struct traits_as<Type*, pointer_category> {
static Type* as(const octave_value& obj, bool throw_error) { static Type* as(const octave_value& obj) {
Type *v = 0; Type *v = 0;
int res = traits_asptr<Type>::asptr(obj, &v); int res = traits_asptr<Type>::asptr(obj, &v);
if (SWIG_IsOK(res)) { if (SWIG_IsOK(res)) {
@ -153,15 +149,14 @@ namespace swig {
if (!Octave_Error_Occurred()) { if (!Octave_Error_Occurred()) {
%type_error(swig::type_name<Type>()); %type_error(swig::type_name<Type>());
} }
if (throw_error) throw std::invalid_argument("bad type"); throw std::invalid_argument("bad type");
return 0;
} }
} }
}; };
template <class Type> template <class Type>
inline Type as(const octave_value& obj, bool te = false) { inline Type as(const octave_value& obj) {
return traits_as<Type, typename traits<Type>::category>::as(obj, te); return traits_as<Type, typename traits<Type>::category>::as(obj);
} }
template <class Type> template <class Type>

View file

@ -392,7 +392,7 @@ SWIG_Perl_NewPackedObj(SWIG_MAYBE_PERL_OBJECT void *ptr, int sz, swig_type_info
return result; return result;
} }
/* Convert a packed value value */ /* Convert a packed pointer value */
SWIGRUNTIME int SWIGRUNTIME int
SWIG_Perl_ConvertPacked(SWIG_MAYBE_PERL_OBJECT SV *obj, void *ptr, int sz, swig_type_info *ty) { SWIG_Perl_ConvertPacked(SWIG_MAYBE_PERL_OBJECT SV *obj, void *ptr, int sz, swig_type_info *ty) {
swig_cast_info *tc; swig_cast_info *tc;

View file

@ -134,7 +134,7 @@
%typemap(in) SWIGTYPE *DISOWN %typemap(in) SWIGTYPE *DISOWN
{ {
if(SWIG_ConvertPtr(*$input, (void **) &$1, $1_descriptor, SWIG_POINTER_DISOWN ) < 0) { if(SWIG_ConvertPtr(*$input, (void **) &$1, $1_descriptor, SWIG_POINTER_DISOWN ) < 0) {
SWIG_PHP_Error(E_ERROR, "Type error in argument $argnum of $symname. Expected $&1_descriptor"); SWIG_PHP_Error(E_ERROR, "Type error in argument $argnum of $symname. Expected $1_descriptor");
} }
} }

View file

@ -434,8 +434,8 @@ namespace swig
{ {
swig::SwigVar_PyObject item = PySequence_GetItem(_seq, _index); swig::SwigVar_PyObject item = PySequence_GetItem(_seq, _index);
try { try {
return swig::as<T>(item, true); return swig::as<T>(item);
} catch (std::exception& e) { } catch (const std::invalid_argument& e) {
char msg[1024]; char msg[1024];
sprintf(msg, "in sequence element %d ", (int)_index); sprintf(msg, "in sequence element %d ", (int)_index);
if (!PyErr_Occurred()) { if (!PyErr_Occurred()) {

View file

@ -538,7 +538,7 @@ SwigPyObject_dealloc(PyObject *v)
PyObject *res; PyObject *res;
/* PyObject_CallFunction() has the potential to silently drop /* PyObject_CallFunction() has the potential to silently drop
the active active exception. In cases of unnamed temporary the active exception. In cases of unnamed temporary
variable or where we just finished iterating over a generator variable or where we just finished iterating over a generator
StopIteration will be active right now, and this needs to StopIteration will be active right now, and this needs to
remain true upon return from SwigPyObject_dealloc. So save remain true upon return from SwigPyObject_dealloc. So save
@ -1308,7 +1308,7 @@ SWIG_Python_ConvertFunctionPtr(PyObject *obj, void **ptr, swig_type_info *ty) {
} }
} }
/* Convert a packed value value */ /* Convert a packed pointer value */
SWIGRUNTIME int SWIGRUNTIME int
SWIG_Python_ConvertPacked(PyObject *obj, void *ptr, size_t sz, swig_type_info *ty) { SWIG_Python_ConvertPacked(PyObject *obj, void *ptr, size_t sz, swig_type_info *ty) {

View file

@ -107,14 +107,14 @@ namespace swig {
template <class Type> template <class Type>
struct traits_as<Type, value_category> { struct traits_as<Type, value_category> {
static Type as(PyObject *obj, bool throw_error) { static Type as(PyObject *obj) {
Type v; Type v;
int res = asval(obj, &v); int res = asval(obj, &v);
if (!obj || !SWIG_IsOK(res)) { if (!obj || !SWIG_IsOK(res)) {
if (!PyErr_Occurred()) { if (!PyErr_Occurred()) {
::%type_error(swig::type_name<Type>()); ::%type_error(swig::type_name<Type>());
} }
if (throw_error) throw std::invalid_argument("bad type"); throw std::invalid_argument("bad type");
} }
return v; return v;
} }
@ -122,7 +122,7 @@ namespace swig {
template <class Type> template <class Type>
struct traits_as<Type, pointer_category> { struct traits_as<Type, pointer_category> {
static Type as(PyObject *obj, bool throw_error) { static Type as(PyObject *obj) {
Type *v = 0; Type *v = 0;
int res = (obj ? traits_asptr<Type>::asptr(obj, &v) : SWIG_ERROR); int res = (obj ? traits_asptr<Type>::asptr(obj, &v) : SWIG_ERROR);
if (SWIG_IsOK(res) && v) { if (SWIG_IsOK(res) && v) {
@ -134,21 +134,17 @@ namespace swig {
return *v; return *v;
} }
} else { } else {
// Uninitialized return value, no Type() constructor required.
static Type *v_def = (Type*) malloc(sizeof(Type));
if (!PyErr_Occurred()) { if (!PyErr_Occurred()) {
%type_error(swig::type_name<Type>()); %type_error(swig::type_name<Type>());
} }
if (throw_error) throw std::invalid_argument("bad type"); throw std::invalid_argument("bad type");
memset(v_def,0,sizeof(Type));
return *v_def;
} }
} }
}; };
template <class Type> template <class Type>
struct traits_as<Type*, pointer_category> { struct traits_as<Type*, pointer_category> {
static Type* as(PyObject *obj, bool throw_error) { static Type* as(PyObject *obj) {
Type *v = 0; Type *v = 0;
int res = (obj ? traits_asptr<Type>::asptr(obj, &v) : SWIG_ERROR); int res = (obj ? traits_asptr<Type>::asptr(obj, &v) : SWIG_ERROR);
if (SWIG_IsOK(res)) { if (SWIG_IsOK(res)) {
@ -157,15 +153,14 @@ namespace swig {
if (!PyErr_Occurred()) { if (!PyErr_Occurred()) {
%type_error(swig::type_name<Type>()); %type_error(swig::type_name<Type>());
} }
if (throw_error) throw std::invalid_argument("bad type"); throw std::invalid_argument("bad type");
return 0;
} }
} }
}; };
template <class Type> template <class Type>
inline Type as(PyObject *obj, bool te = false) { inline Type as(PyObject *obj) {
return traits_as<Type, typename traits<Type>::category>::as(obj, te); return traits_as<Type, typename traits<Type>::category>::as(obj);
} }
template <class Type> template <class Type>

View file

@ -350,7 +350,7 @@ SWIG_R_NewPackedObj(void *ptr, size_t sz, swig_type_info *type) {
return ptr ? RSwigPacked_New((void *) ptr, sz, type) : R_NilValue; return ptr ? RSwigPacked_New((void *) ptr, sz, type) : R_NilValue;
} }
/* Convert a packed value value */ /* Convert a packed pointer value */
SWIGRUNTIME int SWIGRUNTIME int
SWIG_R_ConvertPacked(SEXP obj, void *ptr, size_t sz, swig_type_info *ty) { SWIG_R_ConvertPacked(SEXP obj, void *ptr, size_t sz, swig_type_info *ty) {

View file

@ -101,11 +101,10 @@ namespace swig {
template <class Type> template <class Type>
struct traits_as<Type, value_category> { struct traits_as<Type, value_category> {
static Type as(SWIG_Object obj, bool throw_error) { static Type as(SWIG_Object obj) {
Type v; Type v;
int res = asval(obj, &v); int res = asval(obj, &v);
if (!obj || !SWIG_IsOK(res)) { if (!obj || !SWIG_IsOK(res)) {
if (throw_error)
throw std::invalid_argument("bad type"); throw std::invalid_argument("bad type");
} }
return v; return v;
@ -114,7 +113,7 @@ namespace swig {
template <class Type> template <class Type>
struct traits_as<Type, pointer_category> { struct traits_as<Type, pointer_category> {
static Type as(SWIG_Object obj, bool throw_error) { static Type as(SWIG_Object obj) {
Type *v = 0; Type *v = 0;
int res = (obj ? traits_asptr<Type>::asptr(obj, &v) : SWIG_ERROR); int res = (obj ? traits_asptr<Type>::asptr(obj, &v) : SWIG_ERROR);
if (SWIG_IsOK(res) && v) { if (SWIG_IsOK(res) && v) {
@ -126,12 +125,7 @@ namespace swig {
return *v; return *v;
} }
} else { } else {
// Uninitialized return value, no Type() constructor required.
static Type *v_def = (Type*) malloc(sizeof(Type));
if (throw_error)
throw std::invalid_argument("bad type"); throw std::invalid_argument("bad type");
memset(v_def,0,sizeof(Type));
return *v_def;
} }
} }
}; };
@ -152,8 +146,8 @@ namespace swig {
}; };
template <class Type> template <class Type>
inline Type as(SWIG_Object obj, bool te = false) { inline Type as(SWIG_Object obj) {
return traits_as<Type, typename traits<Type>::category>::as(obj, te); return traits_as<Type, typename traits<Type>::category>::as(obj);
} }
template <class Type> template <class Type>

View file

@ -7,7 +7,7 @@
# This could be provided as a separate run-time library but this # This could be provided as a separate run-time library but this
# approach allows the code to to be included directly into the # approach allows the code to be included directly into the
# generated bindings and so removes the need to have and install an # generated bindings and so removes the need to have and install an
# additional library. We may however end up with multiple copies of # additional library. We may however end up with multiple copies of
# this and some confusion at run-time as to which class to use. This # this and some confusion at run-time as to which class to use. This

View file

@ -183,8 +183,8 @@ namespace swig
{ {
VALUE item = rb_ary_entry(_seq, _index ); VALUE item = rb_ary_entry(_seq, _index );
try { try {
return swig::as<T>(item, true); return swig::as<T>(item);
} catch (std::exception& e) { } catch (const std::invalid_argument& e) {
char msg[1024]; char msg[1024];
sprintf(msg, "in sequence element %d ", _index); sprintf(msg, "in sequence element %d ", _index);
VALUE lastErr = rb_gv_get("$!"); VALUE lastErr = rb_gv_get("$!");
@ -926,7 +926,7 @@ namespace swig
VALUE elem = argv[0]; VALUE elem = argv[0];
int idx = 0; int idx = 0;
try { try {
Sequence::value_type val = swig::as<Sequence::value_type>( elem, true ); Sequence::value_type val = swig::as<Sequence::value_type>( elem );
if ( i >= len ) { if ( i >= len ) {
$self->resize(i-1, val); $self->resize(i-1, val);
return $self; return $self;
@ -943,7 +943,7 @@ namespace swig
} }
} }
catch( std::invalid_argument ) catch( const std::invalid_argument & )
{ {
rb_raise( rb_eArgError, "%s", rb_raise( rb_eArgError, "%s",
Ruby_Format_TypeError( "", Ruby_Format_TypeError( "",
@ -967,10 +967,10 @@ namespace swig
Sequence::iterator start = $self->begin(); Sequence::iterator start = $self->begin();
VALUE elem = argv[idx]; VALUE elem = argv[idx];
try { try {
Sequence::value_type val = swig::as<Sequence::value_type>( elem, true ); Sequence::value_type val = swig::as<Sequence::value_type>( elem );
$self->insert( start, val ); $self->insert( start, val );
} }
catch( std::invalid_argument ) catch( const std::invalid_argument & )
{ {
rb_raise( rb_eArgError, "%s", rb_raise( rb_eArgError, "%s",
Ruby_Format_TypeError( "", Ruby_Format_TypeError( "",

View file

@ -363,7 +363,7 @@ SWIG_Ruby_NewPackedObj(void *ptr, int sz, swig_type_info *type) {
return rb_str_new2(result); return rb_str_new2(result);
} }
/* Convert a packed value value */ /* Convert a packed pointer value */
SWIGRUNTIME int SWIGRUNTIME int
SWIG_Ruby_ConvertPacked(VALUE obj, void *ptr, int sz, swig_type_info *ty) { SWIG_Ruby_ConvertPacked(VALUE obj, void *ptr, int sz, swig_type_info *ty) {
swig_cast_info *tc; swig_cast_info *tc;

View file

@ -115,15 +115,15 @@ namespace swig {
template <class Type> template <class Type>
struct traits_as<Type, value_category> { struct traits_as<Type, value_category> {
static Type as(VALUE obj, bool throw_error) { static Type as(VALUE obj) {
Type v; Type v;
int res = asval(obj, &v); int res = asval(obj, &v);
if (!SWIG_IsOK(res)) { if (!SWIG_IsOK(res)) {
if (throw_error) throw std::invalid_argument("bad type");
VALUE lastErr = rb_gv_get("$!"); VALUE lastErr = rb_gv_get("$!");
if (lastErr == Qnil) { if (lastErr == Qnil) {
%type_error(swig::type_name<Type>()); %type_error(swig::type_name<Type>());
} }
throw std::invalid_argument("bad type");
} }
return v; return v;
} }
@ -131,7 +131,7 @@ namespace swig {
template <class Type> template <class Type>
struct traits_as<Type, pointer_category> { struct traits_as<Type, pointer_category> {
static Type as(VALUE obj, bool throw_error) { static Type as(VALUE obj) {
Type *v = 0; Type *v = 0;
int res = traits_asptr<Type>::asptr(obj, &v); int res = traits_asptr<Type>::asptr(obj, &v);
if (SWIG_IsOK(res) && v) { if (SWIG_IsOK(res) && v) {
@ -143,40 +143,35 @@ namespace swig {
return *v; return *v;
} }
} else { } else {
// Uninitialized return value, no Type() constructor required.
if (throw_error) throw std::invalid_argument("bad type");
VALUE lastErr = rb_gv_get("$!"); VALUE lastErr = rb_gv_get("$!");
if (lastErr == Qnil) { if (lastErr == Qnil) {
%type_error(swig::type_name<Type>()); %type_error(swig::type_name<Type>());
} }
static Type *v_def = (Type*) malloc(sizeof(Type)); throw std::invalid_argument("bad type");
memset(v_def,0,sizeof(Type));
return *v_def;
} }
} }
}; };
template <class Type> template <class Type>
struct traits_as<Type*, pointer_category> { struct traits_as<Type*, pointer_category> {
static Type* as(VALUE obj, bool throw_error) { static Type* as(VALUE obj) {
Type *v = 0; Type *v = 0;
int res = traits_asptr<Type>::asptr(obj, &v); int res = traits_asptr<Type>::asptr(obj, &v);
if (SWIG_IsOK(res)) { if (SWIG_IsOK(res)) {
return v; return v;
} else { } else {
if (throw_error) throw std::invalid_argument("bad type");
VALUE lastErr = rb_gv_get("$!"); VALUE lastErr = rb_gv_get("$!");
if (lastErr == Qnil) { if (lastErr == Qnil) {
%type_error(swig::type_name<Type>()); %type_error(swig::type_name<Type>());
} }
return 0; throw std::invalid_argument("bad type");
} }
} }
}; };
template <class Type> template <class Type>
inline Type as(VALUE obj, bool te = false) { inline Type as(VALUE obj) {
return traits_as< Type, typename traits< Type >::category >::as(obj, te); return traits_as< Type, typename traits< Type >::category >::as(obj);
} }
template <class Type> template <class Type>

View file

@ -80,35 +80,35 @@ namespace swig {
template <class Type> template <class Type>
struct traits_as<std::shared_ptr<Type>, pointer_category> { struct traits_as<std::shared_ptr<Type>, pointer_category> {
static std::shared_ptr<Type> as(VALUE obj, bool throw_error) { static std::shared_ptr<Type> as(VALUE obj) {
std::shared_ptr<Type> ret; std::shared_ptr<Type> ret;
std::shared_ptr<Type> *v = &ret; std::shared_ptr<Type> *v = &ret;
int res = traits_asptr<std::shared_ptr<Type> >::asptr(obj, &v); int res = traits_asptr<std::shared_ptr<Type> >::asptr(obj, &v);
if (SWIG_IsOK(res)) { if (SWIG_IsOK(res)) {
return ret; return ret;
} else { } else {
if (throw_error) throw std::invalid_argument("bad type");
VALUE lastErr = rb_gv_get("$!"); VALUE lastErr = rb_gv_get("$!");
if (lastErr == Qnil) if (lastErr == Qnil)
SWIG_Error(SWIG_TypeError, swig::type_name<std::shared_ptr<Type> >()); SWIG_Error(SWIG_TypeError, swig::type_name<std::shared_ptr<Type> >());
return std::shared_ptr<Type>(); throw std::invalid_argument("bad type");
} }
} }
}; };
template <class Type> template <class Type>
struct traits_as<std::shared_ptr<Type> *, pointer_category> { struct traits_as<std::shared_ptr<Type> *, pointer_category> {
static std::shared_ptr<Type> * as(VALUE obj, bool throw_error) { static std::shared_ptr<Type> * as(VALUE obj) {
std::shared_ptr<Type> *p = 0; std::shared_ptr<Type> *p = 0;
int res = traits_asptr<std::shared_ptr<Type> >::asptr(obj, &p); int res = traits_asptr<std::shared_ptr<Type> >::asptr(obj, &p);
if (SWIG_IsOK(res)) { if (SWIG_IsOK(res)) {
return p; return p;
} else { } else {
if (throw_error) throw std::invalid_argument("bad type");
VALUE lastErr = rb_gv_get("$!"); VALUE lastErr = rb_gv_get("$!");
if (lastErr == Qnil) if (lastErr == Qnil)
SWIG_Error(SWIG_TypeError, swig::type_name<std::shared_ptr<Type> *>()); SWIG_Error(SWIG_TypeError, swig::type_name<std::shared_ptr<Type> *>());
return 0; throw std::invalid_argument("bad type");
} }
} }
}; };

View file

@ -104,23 +104,21 @@ namespace swig {
template <class Type> template <class Type>
struct traits_as<Type, value_category> { struct traits_as<Type, value_category> {
static Type as(const SwigSciObject& obj, bool throw_error) { static Type as(const SwigSciObject& obj) {
Type v; Type v;
int res = asval(obj, &v); int res = asval(obj, &v);
if (SWIG_IsOK(res)) { if (SWIG_IsOK(res)) {
return v; return v;
} else { } else {
%type_error(swig::type_name<Type>()); %type_error(swig::type_name<Type>());
if (throw_error)
throw std::invalid_argument("bad type"); throw std::invalid_argument("bad type");
return res;
} }
} }
}; };
template <class Type> template <class Type>
struct traits_as<Type, pointer_category> { struct traits_as<Type, pointer_category> {
static Type as(const SwigSciObject& obj, bool throw_error) { static Type as(const SwigSciObject& obj) {
Type *v = 0; Type *v = 0;
int res = traits_asptr<Type>::asptr(obj, &v); int res = traits_asptr<Type>::asptr(obj, &v);
if (SWIG_IsOK(res) && v) { if (SWIG_IsOK(res) && v) {
@ -132,36 +130,29 @@ namespace swig {
return *v; return *v;
} }
} else { } else {
// Uninitialized return value, no Type() constructor required.
static Type *v_def = (Type*) malloc(sizeof(Type));
%type_error(swig::type_name<Type>()); %type_error(swig::type_name<Type>());
if (throw_error)
throw std::invalid_argument("bad type"); throw std::invalid_argument("bad type");
memset(v_def,0,sizeof(Type));
return *v_def;
} }
} }
}; };
template <class Type> template <class Type>
struct traits_as<Type*, pointer_category> { struct traits_as<Type*, pointer_category> {
static Type* as(const SwigSciObject& obj, bool throw_error) { static Type* as(const SwigSciObject& obj) {
Type *v = 0; Type *v = 0;
int res = traits_asptr<Type>::asptr(obj, &v); int res = traits_asptr<Type>::asptr(obj, &v);
if (SWIG_IsOK(res)) { if (SWIG_IsOK(res)) {
return v; return v;
} else { } else {
%type_error(swig::type_name<Type>()); %type_error(swig::type_name<Type>());
if (throw_error)
throw std::invalid_argument("bad type"); throw std::invalid_argument("bad type");
return SWIG_OK;
} }
} }
}; };
template <class Type> template <class Type>
inline Type as(const SwigSciObject& obj, bool te = false) { inline Type as(const SwigSciObject& obj) {
return traits_as<Type, typename traits<Type>::category>::as(obj, te); return traits_as<Type, typename traits<Type>::category>::as(obj);
} }
template <class Type> template <class Type>

View file

@ -7,7 +7,7 @@
#define SWIG_Object int #define SWIG_Object int
#define %append_output(obj) if (!SWIG_IsOK(SWIG_Scilab_SetOutput(pvApiCtx, obj))) return SWIG_ERROR #define %append_output(obj) if (!SWIG_IsOK(SWIG_Scilab_SetOutput(pvApiCtx, obj))) return SWIG_ERROR
#define %set_constant(name, obj) if (!SWIG_IsOK(SWIG_Scilab_SetOutput(pvApiCtx, obj))) return SWIG_ERROR // Name is managed by the the function name #define %set_constant(name, obj) if (!SWIG_IsOK(SWIG_Scilab_SetOutput(pvApiCtx, obj))) return SWIG_ERROR // Name is managed by the function name
#define %raise(obj, type, desc) SWIG_Scilab_Raise(obj, type, desc) #define %raise(obj, type, desc) SWIG_Scilab_Raise(obj, type, desc)
#define %set_output(obj) if (!SWIG_IsOK(SWIG_Scilab_SetOutput(pvApiCtx, obj))) return SWIG_ERROR #define %set_output(obj) if (!SWIG_IsOK(SWIG_Scilab_SetOutput(pvApiCtx, obj))) return SWIG_ERROR
#define %set_varoutput(obj) if (!SWIG_IsOK(SWIG_Scilab_SetOutput(pvApiCtx, obj))) return SWIG_ERROR #define %set_varoutput(obj) if (!SWIG_IsOK(SWIG_Scilab_SetOutput(pvApiCtx, obj))) return SWIG_ERROR

View file

@ -199,7 +199,7 @@ SWIG_Tcl_PointerTypeFromString(char *c) {
return c; return c;
} }
/* Convert a packed value value */ /* Convert a packed pointer value */
SWIGRUNTIME int SWIGRUNTIME int
SWIG_Tcl_ConvertPacked(Tcl_Interp *SWIGUNUSEDPARM(interp) , Tcl_Obj *obj, void *ptr, int sz, swig_type_info *ty) { SWIG_Tcl_ConvertPacked(Tcl_Interp *SWIGUNUSEDPARM(interp) , Tcl_Obj *obj, void *ptr, int sz, swig_type_info *ty) {
swig_cast_info *tc; swig_cast_info *tc;

View file

@ -209,7 +209,7 @@ static String *yyrename = 0;
/* Forward renaming operator */ /* Forward renaming operator */
static String *resolve_create_node_scope(String *cname); static String *resolve_create_node_scope(String *cname, int is_class_definition);
Hash *Swig_cparse_features(void) { Hash *Swig_cparse_features(void) {
@ -815,32 +815,53 @@ static String *remove_block(Node *kw, const String *inputcode) {
return modified_code; return modified_code;
} }
/*
#define RESOLVE_DEBUG 1
*/
static Node *nscope = 0; static Node *nscope = 0;
static Node *nscope_inner = 0; static Node *nscope_inner = 0;
/* Remove the scope prefix from cname and return the base name without the prefix. /* Remove the scope prefix from cname and return the base name without the prefix.
* The scopes required for the symbol name are resolved and/or created, if required. * The scopes required for the symbol name are resolved and/or created, if required.
* For example AA::BB::CC as input returns CC and creates the namespace AA then inner * For example AA::BB::CC as input returns CC and creates the namespace AA then inner
* namespace BB in the current scope. If cname is found to already exist as a weak symbol * namespace BB in the current scope. */
* (forward reference) then the scope might be changed to match, such as when a symbol match static String *resolve_create_node_scope(String *cname, int is_class_definition) {
* is made via a using reference. */
static String *resolve_create_node_scope(String *cname) {
Symtab *gscope = 0; Symtab *gscope = 0;
Node *cname_node = 0; Node *cname_node = 0;
int skip_lookup = 0; String *last = Swig_scopename_last(cname);
nscope = 0; nscope = 0;
nscope_inner = 0; nscope_inner = 0;
if (Strncmp(cname,"::",2) == 0) if (Strncmp(cname,"::" ,2) != 0) {
skip_lookup = 1; if (is_class_definition) {
/* Only lookup symbols which are in scope via a using declaration but not via a using directive.
cname_node = skip_lookup ? 0 : Swig_symbol_clookup_no_inherit(cname, 0); For example find y via 'using x::y' but not y via a 'using namespace x'. */
cname_node = Swig_symbol_clookup_no_inherit(cname, 0);
if (!cname_node) {
Node *full_lookup_node = Swig_symbol_clookup(cname, 0);
if (full_lookup_node) {
/* This finds a symbol brought into scope via both a using directive and a using declaration. */
Node *last_node = Swig_symbol_clookup_no_inherit(last, 0);
if (last_node == full_lookup_node)
cname_node = last_node;
}
}
} else {
/* For %template, the template needs to be in scope via any means. */
cname_node = Swig_symbol_clookup(cname, 0);
}
}
#if RESOLVE_DEBUG
if (!cname_node)
Printf(stdout, "symbol does not yet exist (%d): [%s]\n", is_class_definition, cname);
else
Printf(stdout, "symbol does exist (%d): [%s]\n", is_class_definition, cname);
#endif
if (cname_node) { if (cname_node) {
/* The symbol has been defined already or is in another scope. /* The symbol has been defined already or is in another scope.
If it is a weak symbol, it needs replacing and if it was brought into the current scope If it is a weak symbol, it needs replacing and if it was brought into the current scope,
via a using declaration, the scope needs adjusting appropriately for the new symbol. the scope needs adjusting appropriately for the new symbol.
Similarly for defined templates. */ Similarly for defined templates. */
Symtab *symtab = Getattr(cname_node, "sym:symtab"); Symtab *symtab = Getattr(cname_node, "sym:symtab");
Node *sym_weak = Getattr(cname_node, "sym:weak"); Node *sym_weak = Getattr(cname_node, "sym:weak");
@ -848,48 +869,92 @@ static String *resolve_create_node_scope(String *cname) {
/* Check if the scope is the current scope */ /* Check if the scope is the current scope */
String *current_scopename = Swig_symbol_qualifiedscopename(0); String *current_scopename = Swig_symbol_qualifiedscopename(0);
String *found_scopename = Swig_symbol_qualifiedscopename(symtab); String *found_scopename = Swig_symbol_qualifiedscopename(symtab);
int len;
if (!current_scopename) if (!current_scopename)
current_scopename = NewString(""); current_scopename = NewString("");
if (!found_scopename) if (!found_scopename)
found_scopename = NewString(""); found_scopename = NewString("");
len = Len(current_scopename);
if ((len > 0) && (Strncmp(current_scopename, found_scopename, len) == 0)) { {
if (Len(found_scopename) > len + 2) { int fail = 1;
/* A matching weak symbol was found in non-global scope, some scope adjustment may be required */ List *current_scopes = Swig_scopename_tolist(current_scopename);
String *new_cname = NewString(Char(found_scopename) + len + 2); /* skip over "::" prefix */ List *found_scopes = Swig_scopename_tolist(found_scopename);
String *base = Swig_scopename_last(cname); Iterator cit = First(current_scopes);
Printf(new_cname, "::%s", base); Iterator fit = First(found_scopes);
cname = new_cname; #if RESOLVE_DEBUG
Delete(base); Printf(stdout, "comparing current: [%s] found: [%s]\n", current_scopename, found_scopename);
} else { #endif
/* A matching weak symbol was found in the same non-global local scope, no scope adjustment required */ for (; fit.item && cit.item; fit = Next(fit), cit = Next(cit)) {
assert(len == Len(found_scopename)); String *current = cit.item;
String *found = fit.item;
#if RESOLVE_DEBUG
Printf(stdout, " looping %s %s\n", current, found);
#endif
if (Strcmp(current, found) != 0)
break;
} }
} else {
String *base = Swig_scopename_last(cname); if (!cit.item) {
if (Len(found_scopename) > 0) { String *subscope = NewString("");
/* A matching weak symbol was found in a different scope to the local scope - probably via a using declaration */ for (; fit.item; fit = Next(fit)) {
cname = NewStringf("%s::%s", found_scopename, base); if (Len(subscope) > 0)
} else { Append(subscope, "::");
/* Either: Append(subscope, fit.item);
1) A matching weak symbol was found in a different scope to the local scope - this is actually a
symbol with the same name in a different scope which we don't want, so no adjustment required.
2) A matching weak symbol was found in the global scope - no adjustment required.
*/
cname = Copy(base);
} }
Delete(base); if (Len(subscope) > 0)
cname = NewStringf("%s::%s", subscope, last);
else
cname = Copy(last);
#if RESOLVE_DEBUG
Printf(stdout, "subscope to create: [%s] cname: [%s]\n", subscope, cname);
#endif
fail = 0;
Delete(subscope);
} else {
if (is_class_definition) {
if (!fit.item) {
/* It is valid to define a new class with the same name as one forward declared in a parent scope */
fail = 0;
} else if (Swig_scopename_check(cname)) {
/* Classes defined with scope qualifiers must have a matching forward declaration in matching scope */
fail = 1;
} else {
/* This may let through some invalid cases */
fail = 0;
} }
#if RESOLVE_DEBUG
Printf(stdout, "scope for class definition, fail: %d\n", fail);
#endif
} else {
#if RESOLVE_DEBUG
Printf(stdout, "no matching base scope for template\n");
#endif
fail = 1;
}
}
Delete(found_scopes);
Delete(current_scopes);
if (fail) {
String *cname_resolved = NewStringf("%s::%s", found_scopename, last);
Swig_error(cparse_file, cparse_line, "'%s' resolves to '%s' and was incorrectly instantiated in scope '%s' instead of within scope '%s'.\n", cname, cname_resolved, current_scopename, found_scopename);
cname = Copy(last);
Delete(cname_resolved);
}
}
Delete(current_scopename); Delete(current_scopename);
Delete(found_scopename); Delete(found_scopename);
} }
} else if (!is_class_definition) {
/* A template instantiation requires a template to be found in scope... fail here too?
Swig_error(cparse_file, cparse_line, "No template found to instantiate '%s' with %%template.\n", cname);
*/
} }
if (Swig_scopename_check(cname)) { if (Swig_scopename_check(cname)) {
Node *ns; Node *ns;
String *prefix = Swig_scopename_prefix(cname); String *prefix = Swig_scopename_prefix(cname);
String *base = Swig_scopename_last(cname);
if (prefix && (Strncmp(prefix,"::",2) == 0)) { if (prefix && (Strncmp(prefix,"::",2) == 0)) {
/* I don't think we can use :: global scope to declare classes and hence neither %template. - consider reporting error instead - wsfulton. */ /* I don't think we can use :: global scope to declare classes and hence neither %template. - consider reporting error instead - wsfulton. */
/* Use the global scope */ /* Use the global scope */
@ -899,6 +964,7 @@ static String *resolve_create_node_scope(String *cname) {
gscope = set_scope_to_global(); gscope = set_scope_to_global();
} }
if (Len(prefix) == 0) { if (Len(prefix) == 0) {
String *base = Copy(last);
/* Use the global scope, but we need to add a 'global' namespace. */ /* Use the global scope, but we need to add a 'global' namespace. */
if (!gscope) gscope = set_scope_to_global(); if (!gscope) gscope = set_scope_to_global();
/* note that this namespace is not the "unnamed" one, /* note that this namespace is not the "unnamed" one,
@ -907,6 +973,7 @@ static String *resolve_create_node_scope(String *cname) {
nscope = new_node("namespace"); nscope = new_node("namespace");
Setattr(nscope,"symtab", gscope);; Setattr(nscope,"symtab", gscope);;
nscope_inner = nscope; nscope_inner = nscope;
Delete(last);
return base; return base;
} }
/* Try to locate the scope */ /* Try to locate the scope */
@ -924,7 +991,7 @@ static String *resolve_create_node_scope(String *cname) {
String *nname = Swig_symbol_qualifiedscopename(nstab); String *nname = Swig_symbol_qualifiedscopename(nstab);
if (tname && (Strcmp(tname,nname) == 0)) { if (tname && (Strcmp(tname,nname) == 0)) {
ns = 0; ns = 0;
cname = base; cname = Copy(last);
} }
Delete(tname); Delete(tname);
Delete(nname); Delete(nname);
@ -932,19 +999,10 @@ static String *resolve_create_node_scope(String *cname) {
if (ns) { if (ns) {
/* we will try to create a new node using the namespaces we /* we will try to create a new node using the namespaces we
can find in the scope name */ can find in the scope name */
List *scopes; List *scopes = Swig_scopename_tolist(prefix);
String *sname; String *sname;
Iterator si; Iterator si;
String *name = NewString(prefix);
scopes = NewList();
while (name) {
String *base = Swig_scopename_last(name);
String *tprefix = Swig_scopename_prefix(name);
Insert(scopes,0,base);
Delete(base);
Delete(name);
name = tprefix;
}
for (si = First(scopes); si.item; si = Next(si)) { for (si = First(scopes); si.item; si = Next(si)) {
Node *ns1,*ns2; Node *ns1,*ns2;
sname = si.item; sname = si.item;
@ -990,12 +1048,13 @@ static String *resolve_create_node_scope(String *cname) {
nscope_inner = ns2; nscope_inner = ns2;
if (!nscope) nscope = ns2; if (!nscope) nscope = ns2;
} }
cname = base; cname = Copy(last);
Delete(scopes); Delete(scopes);
} }
} }
Delete(prefix); Delete(prefix);
} }
Delete(last);
return cname; return cname;
} }
@ -2631,9 +2690,8 @@ template_directive: SWIGTEMPLATE LPAREN idstringopt RPAREN idcolonnt LESSTHAN va
tscope = Swig_symbol_current(); /* Get the current scope */ tscope = Swig_symbol_current(); /* Get the current scope */
/* If the class name is qualified, we need to create or lookup namespace entries */ /* If the class name is qualified, we need to create or lookup namespace entries */
if (!inclass) { $5 = resolve_create_node_scope($5, 0);
$5 = resolve_create_node_scope($5);
}
if (nscope_inner && Strcmp(nodeType(nscope_inner), "class") == 0) { if (nscope_inner && Strcmp(nodeType(nscope_inner), "class") == 0) {
outer_class = nscope_inner; outer_class = nscope_inner;
} }
@ -2991,6 +3049,9 @@ c_declaration : c_decl {
SetFlag($$,"aliastemplate"); SetFlag($$,"aliastemplate");
add_symbols($$); add_symbols($$);
} }
| cpp_static_assert {
$$ = $1;
}
; ;
/* ------------------------------------------------------------ /* ------------------------------------------------------------
@ -3520,7 +3581,7 @@ cpp_class_decl : storage_class cpptype idcolon inherit LBRACE {
Setattr($<node>$,"prev_symtab",Swig_symbol_current()); Setattr($<node>$,"prev_symtab",Swig_symbol_current());
/* If the class name is qualified. We need to create or lookup namespace/scope entries */ /* If the class name is qualified. We need to create or lookup namespace/scope entries */
scope = resolve_create_node_scope($3); scope = resolve_create_node_scope($3, 1);
/* save nscope_inner to the class - it may be overwritten in nested classes*/ /* save nscope_inner to the class - it may be overwritten in nested classes*/
Setattr($<node>$, "nested:innerscope", nscope_inner); Setattr($<node>$, "nested:innerscope", nscope_inner);
Setattr($<node>$, "nested:nscope", nscope); Setattr($<node>$, "nested:nscope", nscope);
@ -4209,9 +4270,6 @@ cpp_temp_possible: c_decl {
| cpp_constructor_decl { | cpp_constructor_decl {
$$ = $1; $$ = $1;
} }
| cpp_static_assert {
$$ = $1;
}
| cpp_template_decl { | cpp_template_decl {
$$ = 0; $$ = 0;
} }
@ -4469,7 +4527,6 @@ cpp_member : c_declaration { $$ = $1; }
default_arguments($$); default_arguments($$);
} }
| cpp_destructor_decl { $$ = $1; } | cpp_destructor_decl { $$ = $1; }
| cpp_static_assert { $$ = $1; }
| cpp_protection_decl { $$ = $1; } | cpp_protection_decl { $$ = $1; }
| cpp_swig_directive { $$ = $1; } | cpp_swig_directive { $$ = $1; }
| cpp_conversion_operator { $$ = $1; } | cpp_conversion_operator { $$ = $1; }
@ -4673,7 +4730,8 @@ cpp_catch_decl : CATCH LPAREN parms RPAREN LBRACE {
} }
; ;
/* static_assert(bool, const char*); */ /* static_assert(bool, const char*); (C++11)
* static_assert(bool); (C++17) */
cpp_static_assert : STATIC_ASSERT LPAREN { cpp_static_assert : STATIC_ASSERT LPAREN {
skip_balanced('(',')'); skip_balanced('(',')');
$$ = 0; $$ = 0;

View file

@ -990,7 +990,7 @@ private:
* overname: The overload string for overloaded function. * overname: The overload string for overloaded function.
* wname: The SWIG wrapped name--the name of the C function. * wname: The SWIG wrapped name--the name of the C function.
* base: A list of the names of base classes, in the case where this * base: A list of the names of base classes, in the case where this
* is is a vritual method not defined in the current class. * is a virtual method not defined in the current class.
* parms: The parameters. * parms: The parameters.
* result: The result type. * result: The result type.
* is_static: Whether this is a static method or member. * is_static: Whether this is a static method or member.

View file

@ -1949,7 +1949,7 @@ int Language::unrollVirtualMethods(Node *n, Node *parent, List *vm, int default_
generation of 'empty' director classes. generation of 'empty' director classes.
But this has to be done outside the previous 'for' But this has to be done outside the previous 'for'
an the recursive loop!. and the recursive loop!.
*/ */
if (n == parent) { if (n == parent) {
int len = Len(vm); int len = Len(vm);
@ -2078,7 +2078,7 @@ int Language::classDirectorConstructors(Node *n) {
needed, since there is a public constructor already defined. needed, since there is a public constructor already defined.
(scottm) This code is needed here to make the director_abstract + (scottm) This code is needed here to make the director_abstract +
test generate compilable code (Example2 in director_abastract.i). test generate compilable code (Example2 in director_abstract.i).
(mmatus) This is very strange, since swig compiled with gcc3.2.3 (mmatus) This is very strange, since swig compiled with gcc3.2.3
doesn't need it here.... doesn't need it here....
@ -3308,7 +3308,7 @@ Node *Language::classLookup(const SwigType *s) const {
} }
if (n) { if (n) {
/* Found a match. Look at the prefix. We only allow /* Found a match. Look at the prefix. We only allow
the cases where where we want a proxy class for the particular type */ the cases where we want a proxy class for the particular type */
bool acceptable_prefix = bool acceptable_prefix =
(Len(prefix) == 0) || // simple type (pass by value) (Len(prefix) == 0) || // simple type (pass by value)
(Strcmp(prefix, "p.") == 0) || // pointer (Strcmp(prefix, "p.") == 0) || // pointer

View file

@ -1755,7 +1755,7 @@ public:
* *
* This is to convert the string of Lua code into a proper string, which can then be * This is to convert the string of Lua code into a proper string, which can then be
* emitted into the C/C++ code. * emitted into the C/C++ code.
* Basically is is a lot of search & replacing of odd sequences * Basically it is a lot of search & replacing of odd sequences
* ---------------------------------------------------------------------------- */ * ---------------------------------------------------------------------------- */
void escapeCode(String *str) { void escapeCode(String *str) {
@ -1770,7 +1770,7 @@ public:
/* ----------------------------------------------------------------------------- /* -----------------------------------------------------------------------------
* rawGetCArraysHash(String *name) * rawGetCArraysHash(String *name)
* *
* A small helper to hide impelementation of how CArrays hashes are stored * A small helper to hide implementation of how CArrays hashes are stored
* ---------------------------------------------------------------------------- */ * ---------------------------------------------------------------------------- */
Hash *rawGetCArraysHash(const_String_or_char_ptr name) { Hash *rawGetCArraysHash(const_String_or_char_ptr name) {

View file

@ -718,7 +718,7 @@ String * R::createFunctionPointerHandler(SwigType *t, Node *n, int *numArgs) {
function that handles the scoerceout. function that handles the scoerceout.
We need to check if any of the argument types have an entry in We need to check if any of the argument types have an entry in
that map. If none do, the ignore and call the function straight. that map. If none do, the ignore and call the function straight.
Otherwise, generate the a marshalling function. Otherwise, generate a marshalling function.
Need to be able to find it in S. Or use an entirely generic one Need to be able to find it in S. Or use an entirely generic one
that evaluates the expressions. that evaluates the expressions.
Handle errors in the evaluation of the function by restoring Handle errors in the evaluation of the function by restoring

View file

@ -187,10 +187,12 @@ class TypePass:private Dispatcher {
ilist = alist = NewList(); ilist = alist = NewList();
Append(ilist, bcls); Append(ilist, bcls);
} else { } else {
if (!GetFlag(bcls, "feature:ignore")) {
Swig_warning(WARN_TYPE_UNDEFINED_CLASS, Getfile(bname), Getline(bname), "Base class '%s' has no name as it is an empty template instantiated with '%%template()'. Ignored.\n", SwigType_namestr(bname)); Swig_warning(WARN_TYPE_UNDEFINED_CLASS, Getfile(bname), Getline(bname), "Base class '%s' has no name as it is an empty template instantiated with '%%template()'. Ignored.\n", SwigType_namestr(bname));
Swig_warning(WARN_TYPE_UNDEFINED_CLASS, Getfile(bcls), Getline(bcls), "The %%template directive must be written before '%s' is used as a base class and be declared with a name.\n", SwigType_namestr(bname)); Swig_warning(WARN_TYPE_UNDEFINED_CLASS, Getfile(bcls), Getline(bcls), "The %%template directive must be written before '%s' is used as a base class and be declared with a name.\n", SwigType_namestr(bname));
} }
} }
}
break; break;
} }
if (Strcmp(nodeType(bcls), "classforward") != 0) { if (Strcmp(nodeType(bcls), "classforward") != 0) {
@ -209,9 +211,11 @@ class TypePass:private Dispatcher {
ilist = alist = NewList(); ilist = alist = NewList();
Append(ilist, bcls); Append(ilist, bcls);
} else { } else {
if (!GetFlag(bcls, "feature:ignore")) {
Swig_warning(WARN_TYPE_UNDEFINED_CLASS, Getfile(bname), Getline(bname), "Base class '%s' has no name as it is an empty template instantiated with '%%template()'. Ignored.\n", SwigType_namestr(bname)); Swig_warning(WARN_TYPE_UNDEFINED_CLASS, Getfile(bname), Getline(bname), "Base class '%s' has no name as it is an empty template instantiated with '%%template()'. Ignored.\n", SwigType_namestr(bname));
Swig_warning(WARN_TYPE_UNDEFINED_CLASS, Getfile(bcls), Getline(bcls), "The %%template directive must be written before '%s' is used as a base class and be declared with a name.\n", SwigType_namestr(bname)); Swig_warning(WARN_TYPE_UNDEFINED_CLASS, Getfile(bcls), Getline(bcls), "The %%template directive must be written before '%s' is used as a base class and be declared with a name.\n", SwigType_namestr(bname));
} }
}
} else { } else {
Swig_warning(WARN_TYPE_UNDEFINED_CLASS, Getfile(bname), Getline(bname), "Base class '%s' undefined.\n", SwigType_namestr(bname)); Swig_warning(WARN_TYPE_UNDEFINED_CLASS, Getfile(bname), Getline(bname), "Base class '%s' undefined.\n", SwigType_namestr(bname));
Swig_warning(WARN_TYPE_UNDEFINED_CLASS, Getfile(bcls), Getline(bcls), "'%s' must be defined before it is used as a base class.\n", SwigType_namestr(bname)); Swig_warning(WARN_TYPE_UNDEFINED_CLASS, Getfile(bcls), Getline(bcls), "'%s' must be defined before it is used as a base class.\n", SwigType_namestr(bname));
@ -1199,10 +1203,7 @@ class TypePass:private Dispatcher {
} else if (Strcmp(ntype, "enum") == 0) { } else if (Strcmp(ntype, "enum") == 0) {
SwigType_typedef_using(Getattr(n, "uname")); SwigType_typedef_using(Getattr(n, "uname"));
} else if (Strcmp(ntype, "template") == 0) { } else if (Strcmp(ntype, "template") == 0) {
/*
Printf(stdout, "usingDeclaration template %s --- %s\n", Getattr(n, "name"), Getattr(n, "uname"));
SwigType_typedef_using(Getattr(n, "uname")); SwigType_typedef_using(Getattr(n, "uname"));
*/
} }
} }
} }

View file

@ -59,7 +59,7 @@ int is_non_virtual_protected_access(Node *n) {
// When vtable is empty, the director class does not get emitted, so a check for an empty vtable should be done. // When vtable is empty, the director class does not get emitted, so a check for an empty vtable should be done.
// However, vtable is set in Language and so is not yet set when methods in Typepass call clean_overloaded() // However, vtable is set in Language and so is not yet set when methods in Typepass call clean_overloaded()
// which calls is_non_virtual_protected_access. So commented out below. // which calls is_non_virtual_protected_access. So commented out below.
// Moving the director vtable creation into into Typepass should solve this problem. // Moving the director vtable creation into Typepass should solve this problem.
if (is_member_director_helper(parentNode, n) /* && Getattr(parentNode, "vtable")*/) if (is_member_director_helper(parentNode, n) /* && Getattr(parentNode, "vtable")*/)
result = 1; result = 1;
} }

View file

@ -277,7 +277,7 @@ int Swig_cargs(Wrapper *w, ParmList *p) {
SwigType_del_rvalue_reference(tvalue); SwigType_del_rvalue_reference(tvalue);
tycode = SwigType_type(tvalue); tycode = SwigType_type(tvalue);
if (tycode != T_USER) { if (tycode != T_USER) {
/* plain primitive type, we copy the the def value */ /* plain primitive type, we copy the def value */
String *lstr = SwigType_lstr(tvalue, defname); String *lstr = SwigType_lstr(tvalue, defname);
defvalue = NewStringf("%s = %s", lstr, qvalue); defvalue = NewStringf("%s = %s", lstr, qvalue);
Delete(lstr); Delete(lstr);

View file

@ -823,10 +823,11 @@ String *Swig_string_emangle(String *s) {
/* ----------------------------------------------------------------------------- /* -----------------------------------------------------------------------------
* Swig_scopename_prefix() * Swig_scopename_split()
* *
* Take a qualified name like "A::B::C" and return the scope name. * Take a qualified name like "A::B::C" and splits off the last name.
* In this case, "A::B". Returns NULL if there is no base. * In this case, returns "C" as last and "A::B" as prefix.
* Always returns non NULL for last, but prefix may be NULL if there is no prefix.
* ----------------------------------------------------------------------------- */ * ----------------------------------------------------------------------------- */
void Swig_scopename_split(const String *s, String **rprefix, String **rlast) { void Swig_scopename_split(const String *s, String **rprefix, String **rlast) {
@ -882,6 +883,12 @@ void Swig_scopename_split(const String *s, String **rprefix, String **rlast) {
} }
} }
/* -----------------------------------------------------------------------------
* Swig_scopename_prefix()
*
* Take a qualified name like "A::B::C" and return the scope name.
* In this case, "A::B". Returns NULL if there is no base.
* ----------------------------------------------------------------------------- */
String *Swig_scopename_prefix(const String *s) { String *Swig_scopename_prefix(const String *s) {
char *tmp = Char(s); char *tmp = Char(s);
@ -1067,6 +1074,31 @@ String *Swig_scopename_suffix(const String *s) {
} }
} }
/* -----------------------------------------------------------------------------
* Swig_scopename_tolist()
*
* Take a qualified scope name like "A::B::C" and convert it to a list.
* In this case, return a list of 3 elements "A", "B", "C".
* Returns an empty list if the input is empty.
* ----------------------------------------------------------------------------- */
List *Swig_scopename_tolist(const String *s) {
List *scopes = NewList();
String *name = Len(s) == 0 ? 0 : NewString(s);
while (name) {
String *last = 0;
String *prefix = 0;
Swig_scopename_split(name, &prefix, &last);
Insert(scopes, 0, last);
Delete(last);
Delete(name);
name = prefix;
}
Delete(name);
return scopes;
}
/* ----------------------------------------------------------------------------- /* -----------------------------------------------------------------------------
* Swig_scopename_check() * Swig_scopename_check()
* *

View file

@ -326,6 +326,7 @@ extern int ParmList_is_compactdefargs(ParmList *p);
extern String *Swig_scopename_last(const String *s); extern String *Swig_scopename_last(const String *s);
extern String *Swig_scopename_first(const String *s); extern String *Swig_scopename_first(const String *s);
extern String *Swig_scopename_suffix(const String *s); extern String *Swig_scopename_suffix(const String *s);
extern List *Swig_scopename_tolist(const String *s);
extern int Swig_scopename_check(const String *s); extern int Swig_scopename_check(const String *s);
extern String *Swig_string_lower(String *s); extern String *Swig_string_lower(String *s);
extern String *Swig_string_upper(String *s); extern String *Swig_string_upper(String *s);

View file

@ -599,7 +599,7 @@ void Swig_symbol_cadd(const_String_or_char_ptr name, Node *n) {
Setattr(ccurrent, name, n); Setattr(ccurrent, name, n);
} }
/* Multiple entries in the C symbol table. We append to to the symbol table */ /* Multiple entries in the C symbol table. We append to the symbol table */
if (append) { if (append) {
Node *fn, *pn = 0; Node *fn, *pn = 0;
cn = Getattr(ccurrent, name); cn = Getattr(ccurrent, name);

View file

@ -61,13 +61,44 @@ static void replace_embedded_typemap(String *s, ParmList *parm_sublist, Wrapper
static Hash *typemaps; static Hash *typemaps;
/* -----------------------------------------------------------------------------
* typemap_identifier_fix()
*
* Create a type that can be used as a hash key lookup independent of the various
* ways a template parameter list can be defined. This is achieved by fully
* resolving the template parameters.
*
* This is a copy and modification of feature_identifier_fix in parser.y.
* ----------------------------------------------------------------------------- */
static SwigType *typemap_identifier_fix(const SwigType *s) {
String *tp = SwigType_istemplate_templateprefix(s);
if (tp) {
String *ts, *ta, *tq, *tr;
ts = SwigType_templatesuffix(s);
ta = SwigType_templateargs(s);
tq = Swig_symbol_type_qualify(ta, 0);
tr = SwigType_typedef_resolve_all(ta);
Append(tp,tr);
Append(tp,ts);
Delete(ts);
Delete(ta);
Delete(tq);
Delete(tr);
return tp;
} else {
return NewString(s);
}
}
static Hash *get_typemap(const SwigType *type) { static Hash *get_typemap(const SwigType *type) {
Hash *tm = 0; Hash *tm = 0;
SwigType *dtype = 0; SwigType *dtype = 0;
SwigType *hashtype; SwigType *hashtype;
if (SwigType_istemplate(type)) { if (SwigType_istemplate(type)) {
String *ty = Swig_symbol_template_deftype(type, 0); SwigType *rty = typemap_identifier_fix(type);
String *ty = Swig_symbol_template_deftype(rty, 0);
dtype = Swig_symbol_type_qualify(ty, 0); dtype = Swig_symbol_type_qualify(ty, 0);
type = dtype; type = dtype;
Delete(ty); Delete(ty);
@ -88,7 +119,7 @@ static void set_typemap(const SwigType *type, Hash **tmhash) {
Hash *new_tm = 0; Hash *new_tm = 0;
assert(*tmhash == 0); assert(*tmhash == 0);
if (SwigType_istemplate(type)) { if (SwigType_istemplate(type)) {
SwigType *rty = SwigType_typedef_resolve_all(type); SwigType *rty = typemap_identifier_fix(type);
String *ty = Swig_symbol_template_deftype(rty, 0); String *ty = Swig_symbol_template_deftype(rty, 0);
String *tyq = Swig_symbol_type_qualify(ty, 0); String *tyq = Swig_symbol_type_qualify(ty, 0);
hashtype = SwigType_remove_global_scope_prefix(tyq); hashtype = SwigType_remove_global_scope_prefix(tyq);
@ -733,6 +764,7 @@ static Hash *typemap_search(const_String_or_char_ptr tmap_method, SwigType *type
SwigType *oldctype = ctype; SwigType *oldctype = ctype;
ctype = SwigType_typedef_resolve(ctype_unstripped); ctype = SwigType_typedef_resolve(ctype_unstripped);
Delete(oldctype); Delete(oldctype);
Delete(ctype_unstripped);
ctype_unstripped = Copy(ctype); ctype_unstripped = Copy(ctype);
} }
} }

View file

@ -42,10 +42,15 @@
* "name" - Scope name * "name" - Scope name
* "qname" - Fully qualified typename * "qname" - Fully qualified typename
* "typetab" - Type table containing typenames and typedef information * "typetab" - Type table containing typenames and typedef information
* For a given key in the typetab table, the value is a fully
* qualified name if not pointing to itself.
* "symtab" - Hash table of symbols defined in a scope * "symtab" - Hash table of symbols defined in a scope
* "inherit" - List of inherited scopes * "inherit" - List of inherited scopes
* "parent" - Parent scope * "parent" - Parent scope
* *
* The contents of these tables can be viewed for debugging using the -debug-typedef
* option which calls SwigType_print_scope().
*
* Typedef information is stored in the "typetab" hash table. For example, * Typedef information is stored in the "typetab" hash table. For example,
* if you have these declarations: * if you have these declarations:
* *
@ -53,8 +58,7 @@
* typedef A B; * typedef A B;
* typedef B *C; * typedef B *C;
* *
* typetab is built as follows: * typetab in scope '' contains:
*
* "A" : "int" * "A" : "int"
* "B" : "A" * "B" : "A"
* "C" : "p.B" * "C" : "p.B"
@ -67,6 +71,26 @@
* ---> a(40).p.p.A (B --> A) * ---> a(40).p.p.A (B --> A)
* ---> a(40).p.p.int (A --> int) * ---> a(40).p.p.int (A --> int)
* *
*
* Using declarations are stored in the "typetab" hash table. For example,
*
* namespace NN {
* struct SS {};
* }
* namespace N {
* struct S {};
* using NN::SS;
* }
* using N::S;
*
* typetab in scope '' contains:
* "S" : "N::S"
*
* and typetab in scope 'N' contains:
* "SS" : "NN::SS"
* "S" : "S"
*
*
* For inheritance, SWIG tries to resolve types back to the base class. For instance, if * For inheritance, SWIG tries to resolve types back to the base class. For instance, if
* you have this: * you have this:
* *
@ -74,13 +98,38 @@
* public: * public:
* typedef int Integer; * typedef int Integer;
* }; * };
* * struct Bar : public Foo {
* class Bar : public Foo {
* void blah(Integer x); * void blah(Integer x);
* }; * };
* *
* In this case typetab in scope '' contains:
* "Foo" : "Foo"
* "Bar" : "Bar"
* and scope 'Foo' contains:
* "Integer" : "int"
* and scope 'Bar' inherits from 'Foo' but is empty (observe that blah is not a scope or typedef)
*
* The argument type of Bar::blah will be set to Foo::Integer. * The argument type of Bar::blah will be set to Foo::Integer.
* *
*
* The scope-inheritance mechanism is used to manage C++ using directives.
*
* namespace XX {
* class CC {};
* }
* namespace X {
* class C {};
* using namespace XX;
* }
* using namespace X;
*
* typetab in scope '' inherits from 'X'
* typetab in scope 'X' inherits from 'XX' and contains:
* "C" : "C"
* typetab in scope 'XX' contains:
* "CC" : "CC"
*
*
* The scope-inheritance mechanism is used to manage C++ namespace aliases. * The scope-inheritance mechanism is used to manage C++ namespace aliases.
* For example, if you have this: * For example, if you have this:
* *
@ -90,8 +139,8 @@
* *
* namespace F = Foo; * namespace F = Foo;
* *
* In this case, "F::" is defined as a scope that "inherits" from Foo. Internally, * In this case, F is defined as a scope that "inherits" from Foo. Internally,
* "F::" will merely be an empty scope that refers to Foo. SWIG will never * F will merely be an empty scope that points to Foo. SWIG will never
* place new type information into a namespace alias---attempts to do so * place new type information into a namespace alias---attempts to do so
* will generate a warning message (in the parser) and will place information into * will generate a warning message (in the parser) and will place information into
* Foo instead. * Foo instead.
@ -166,6 +215,7 @@ void SwigType_typesystem_init() {
* ----------------------------------------------------------------------------- */ * ----------------------------------------------------------------------------- */
int SwigType_typedef(const SwigType *type, const_String_or_char_ptr name) { int SwigType_typedef(const SwigType *type, const_String_or_char_ptr name) {
/* Printf(stdout, "typedef %s %s\n", type, name); */
if (Getattr(current_typetab, name)) if (Getattr(current_typetab, name))
return -1; /* Already defined */ return -1; /* Already defined */
if (Strcmp(type, name) == 0) { /* Can't typedef a name to itself */ if (Strcmp(type, name) == 0) { /* Can't typedef a name to itself */
@ -248,10 +298,26 @@ void SwigType_new_scope(const_String_or_char_ptr name) {
ttab = NewHash(); ttab = NewHash();
Setattr(s, "typetab", ttab); Setattr(s, "typetab", ttab);
/* Build fully qualified name and */ /* Build fully qualified name */
qname = SwigType_scope_name(s); qname = SwigType_scope_name(s);
#if 1
{
/* TODO: only do with templates? What happens with non-templates with code below? */
String *stripped_qname;
stripped_qname = SwigType_remove_global_scope_prefix(qname);
/* Use fully qualified name for hash key without unary scope prefix, qname may contain unary scope */
Setattr(scopes, stripped_qname, s);
Setattr(s, "qname", qname);
/*
Printf(stdout, "SwigType_new_scope stripped %s %s\n", qname, stripped_qname);
*/
Delete(stripped_qname);
}
#else
Printf(stdout, "SwigType_new_scope %s\n", qname);
Setattr(scopes, qname, s); Setattr(scopes, qname, s);
Setattr(s, "qname", qname); Setattr(s, "qname", qname);
#endif
Delete(qname); Delete(qname);
current_scope = s; current_scope = s;
@ -418,12 +484,14 @@ static Typetab *SwigType_find_scope(Typetab *s, const SwigType *nameprefix) {
Typetab *s_orig = s; Typetab *s_orig = s;
String *nnameprefix = 0; String *nnameprefix = 0;
static int check_parent = 1; static int check_parent = 1;
int is_template = 0;
if (Getmark(s)) if (Getmark(s))
return 0; return 0;
Setmark(s, 1); Setmark(s, 1);
if (SwigType_istemplate(nameprefix)) { is_template = SwigType_istemplate(nameprefix);
if (is_template) {
nnameprefix = SwigType_typedef_resolve_all(nameprefix); nnameprefix = SwigType_typedef_resolve_all(nameprefix);
nameprefix = nnameprefix; nameprefix = nnameprefix;
} }
@ -437,10 +505,12 @@ static Typetab *SwigType_find_scope(Typetab *s, const SwigType *nameprefix) {
} else { } else {
full = NewString(nameprefix); full = NewString(nameprefix);
} }
if (Getattr(scopes, full)) {
s = Getattr(scopes, full); s = Getattr(scopes, full);
} else { if (!s && is_template) {
s = 0; /* try look up scope with all the unary scope operators within the template parameter list removed */
SwigType *full_stripped = SwigType_remove_global_scope_prefix(full);
s = Getattr(scopes, full_stripped);
Delete(full_stripped);
} }
Delete(full); Delete(full);
if (s) { if (s) {
@ -541,8 +611,11 @@ static SwigType *_typedef_resolve(Typetab *s, String *base, int look_parent) {
/* ----------------------------------------------------------------------------- /* -----------------------------------------------------------------------------
* template_parameters_resolve() * template_parameters_resolve()
* *
* For use with templates only. The template parameters are resolved. If none * For use with templates only. Attempts to resolve one template parameter.
* of the parameters can be resolved, zero is returned. *
* If one of the template parameters can be resolved, the type is returned with
* just the one parameter resolved and the remaining parameters left as is.
* If none of the template parameters can be resolved, zero is returned.
* ----------------------------------------------------------------------------- */ * ----------------------------------------------------------------------------- */
static String *template_parameters_resolve(const String *base) { static String *template_parameters_resolve(const String *base) {
@ -574,14 +647,15 @@ static String *template_parameters_resolve(const String *base) {
if ((i + 1) < sz) if ((i + 1) < sz)
Append(type, ","); Append(type, ",");
} }
if (rep) {
Append(type, ")>"); Append(type, ")>");
Append(type, suffix); Append(type, suffix);
Delete(suffix); } else {
Delete(tparms);
if (!rep) {
Delete(type); Delete(type);
type = 0; type = 0;
} }
Delete(suffix);
Delete(tparms);
return type; return type;
} }
@ -592,6 +666,17 @@ static SwigType *typedef_resolve(Typetab *s, String *base) {
/* ----------------------------------------------------------------------------- /* -----------------------------------------------------------------------------
* SwigType_typedef_resolve() * SwigType_typedef_resolve()
*
* Given a type declaration, this function looks to reduce/resolve the type via a
* typedef (including via C++ using declarations).
*
* If it is able to find a typedef, the resolved type is returned. If no typedef
* is found NULL is returned. The type name is resolved in the current scope.
* The type returned is not always fully qualified for the global scope, it is
* valid for use in the current scope. If the current scope is global scope, a
* fully qualified type should be returned.
*
* Some additional notes are in Doc/Manual/Extending.html.
* ----------------------------------------------------------------------------- */ * ----------------------------------------------------------------------------- */
/* #define SWIG_DEBUG */ /* #define SWIG_DEBUG */
@ -718,6 +803,25 @@ SwigType *SwigType_typedef_resolve(const SwigType *t) {
} }
} }
if (!type && SwigType_istemplate(base)) {
String *tprefix = SwigType_templateprefix(base);
String *rtprefix = SwigType_typedef_resolve(tprefix);
/* We're looking for a using declaration on the template prefix to resolve the template prefix
* in another scope. Using declaration do not have template parameters. */
if (rtprefix && !SwigType_istemplate(rtprefix)) {
String *tsuffix = SwigType_templatesuffix(base);
String *targs = SwigType_templateargs(base);
type = NewString(rtprefix);
newtype = 1;
Append(type, targs);
Append(type, tsuffix);
Delete(targs);
Delete(tsuffix);
Delete(rtprefix);
}
Delete(tprefix);
}
if (type && (Equal(base, type))) { if (type && (Equal(base, type))) {
if (newtype) if (newtype)
Delete(type); Delete(type);
@ -911,6 +1015,9 @@ SwigType *SwigType_typedef_resolve_all(const SwigType *t) {
return Copy(r); return Copy(r);
} }
#ifdef SWIG_DEBUG
Printf(stdout, "SwigType_typedef_resolve_all start ... %s\n", t);
#endif
/* Recursively resolve the typedef */ /* Recursively resolve the typedef */
r = NewString(t); r = NewString(t);
while ((n = SwigType_typedef_resolve(r))) { while ((n = SwigType_typedef_resolve(r))) {
@ -931,6 +1038,9 @@ SwigType *SwigType_typedef_resolve_all(const SwigType *t) {
Delete(key); Delete(key);
Delete(rr); Delete(rr);
} }
#ifdef SWIG_DEBUG
Printf(stdout, "SwigType_typedef_resolve_all end === %s => %s\n", t, r);
#endif
return r; return r;
} }
@ -938,8 +1048,17 @@ SwigType *SwigType_typedef_resolve_all(const SwigType *t) {
/* ----------------------------------------------------------------------------- /* -----------------------------------------------------------------------------
* SwigType_typedef_qualified() * SwigType_typedef_qualified()
* *
* Given a type declaration, this function tries to fully qualify it according to * Given a type declaration, this function tries to fully qualify it so that the
* typedef scope rules. * resulting type can be used in the global scope. The type name is resolved in
* the current scope.
*
* It provides a fully qualified name, not necessarily a fully expanded name.
* When a using declaration or using directive is found the type may not be fully
* expanded, but it will be resolved and fully qualified for use in the global scope.
*
* This function is for looking up scopes to qualify a type. It does not resolve
* C typedefs, it just qualifies them. See SwigType_typedef_resolve for resolving.
*
* If the unary scope operator (::) is used as a prefix to the type to denote global * If the unary scope operator (::) is used as a prefix to the type to denote global
* scope, it is left in place. * scope, it is left in place.
* ----------------------------------------------------------------------------- */ * ----------------------------------------------------------------------------- */
@ -1000,20 +1119,14 @@ SwigType *SwigType_typedef_qualified(const SwigType *t) {
out of the current scope */ out of the current scope */
Typetab *cs = current_scope; Typetab *cs = current_scope;
while (cs) { if (cs) {
String *qs = SwigType_scope_name(cs); Typetab *found_scope = SwigType_find_scope(cs, e);
if (Len(qs)) { if (found_scope) {
Append(qs, "::"); String *qs = SwigType_scope_name(found_scope);
}
Append(qs, e);
if (Getattr(scopes, qs)) {
Clear(e); Clear(e);
Append(e, qs); Append(e, qs);
Delete(qs); Delete(qs);
break;
} }
Delete(qs);
cs = Getattr(cs, "parent");
} }
} }
} }
@ -1029,10 +1142,6 @@ SwigType *SwigType_typedef_qualified(const SwigType *t) {
Parm *p; Parm *p;
List *parms; List *parms;
ty = Swig_symbol_template_deftype(e, current_symtab); ty = Swig_symbol_template_deftype(e, current_symtab);
/*
String *dt = Swig_symbol_template_deftype(e, current_symtab);
ty = Swig_symbol_type_qualify(dt, 0);
*/
e = ty; e = ty;
parms = SwigType_parmlist(e); parms = SwigType_parmlist(e);
tprefix = SwigType_templateprefix(e); tprefix = SwigType_templateprefix(e);
@ -1099,9 +1208,6 @@ SwigType *SwigType_typedef_qualified(const SwigType *t) {
Delete(tprefix); Delete(tprefix);
Delete(qprefix); Delete(qprefix);
Delete(parms); Delete(parms);
/*
Delete(dt);
*/
} }
Append(result, e); Append(result, e);
Delete(ty); Delete(ty);
@ -1181,7 +1287,7 @@ int SwigType_typedef_using(const_String_or_char_ptr name) {
String *defined_name = 0; String *defined_name = 0;
/* Printf(stdout,"using %s\n", name); */ /* Printf(stdout, "using %s\n", name); */
if (!Swig_scopename_check(name)) if (!Swig_scopename_check(name))
return -1; /* Not properly qualified */ return -1; /* Not properly qualified */

View file

@ -280,7 +280,7 @@ fi
AC_MSG_RESULT($RPATH) AC_MSG_RESULT($RPATH)
# LINKFORSHARED are the flags passed to the $(CC) command that links # LINKFORSHARED are the flags passed to the $(CC) command that links
# the a few executables -- this is only needed for a few systems # a few executables -- this is only needed for a few systems
AC_MSG_CHECKING(LINKFORSHARED) AC_MSG_CHECKING(LINKFORSHARED)
if test -z "$LINKFORSHARED" if test -z "$LINKFORSHARED"