Fix %import and %fragment forced inclusion to not generate code.

This commit is contained in:
William S Fulton 2017-06-03 16:18:41 +01:00
parent 857a62425c
commit 57a89f987d
8 changed files with 186 additions and 7 deletions

View File

@ -7,6 +7,28 @@ the issue number to the end of the URL: https://github.com/swig/swig/issues/
Version 4.0.0 (in progress)
===========================
2017-06-03: wsfulton
Fix %import on a file containing a file scope %fragment forced inclusion to not
generate the fragment contents as %import should not result in code being generated.
The behaviour is now the same as importing code insertion blocks.
Wrapping FileC.i in the following example will result in no generated code, whereas
previously "#include <limits.h>" was generated:
// FileA.i
%fragment("<limits.h>", "header") %{
#include <limits.h>
%}
%{
#include <stdio.h>
%}
%fragment("<limits.h>");
// FileC.i
%import "FileA.i"
*** POTENTIAL INCOMPATIBILITY ***
2017-05-26: Volker Diels-Grabsch, vadz
[Java] Implement java.util.List<> for std::vector. This notably allows to
iterate over wrapped vectors in a natural way.

View File

@ -3904,9 +3904,9 @@ A fragment can use one or more additional fragments, for example:
<div class="code">
<pre>
%fragment("&lt;limits.h&gt;", "header") {
%#include &lt;limits.h&gt;
}
%fragment("&lt;limits.h&gt;", "header") %{
#include &lt;limits.h&gt;
%}
%fragment("AsMyClass", "header", fragment="&lt;limits.h&gt;") {
@ -3989,8 +3989,91 @@ Finally, you can force the inclusion of a fragment at any point in the generated
</div>
<p>
which is very useful inside a template class, for example.
which, for example, is very useful inside a template class.
Another useful case is when using <tt>%extend</tt> inside a class
where the additional code in the <tt>%extend</tt> block depends on the contents of the fragment.
</p>
<div class="code">
<pre>
%fragment("&lt;limits.h&gt;", "header") %{
#include &lt;limits.h&gt;
%}
struct X {
...
%extend {
%fragment("&lt;limits.h&gt;");
bool check(short val) {
if (val &lt; SHRT_MIN /*defined in &lt;limits.h&gt;*/) {
return true;
} else {
return false;
}
}
}
};
</pre>
</div>
<p>
Forced inclusion of fragments can be used as a replacement for <a href="SWIG.html#SWIG_nn42">code insertion block</a>, ensuring the
code block is only generated once.
Consider the contents of FileA.i below which first uses a code insertion block and then a forced fragment inclusion to generate code:
<p>
<div class="code">
<pre>
// FileA.i
%{
#include &lt;stdio.h&gt;
%}
%fragment("&lt;limits.h&gt;");
</pre>
</div>
<p>
and another file including the above:
</p>
<div class="code">
<pre>
// FileB.i
%include "FileA.i"
</pre>
</div>
<p>
The resulting code in the wrappers for FileB.i is:
</p>
<div class="code">
<pre>
#include &lt;stdio.h&gt;
#include &lt;limits.h&gt;
</pre>
</div>
<p>
A note of caution must be mentioned when using <tt>%fragment</tt> forced inclusion or code insertion blocks with <tt>%import</tt>.
If <tt>%import</tt> is used instead:
<p>
<div class="code">
<pre>
// FileC.i
%import "FileA.i"
</pre>
</div>
<p>
then nothing is generated in the resulting code in the wrappers for FileC.i.
This is because <tt>%import</tt> is for collecting type information and does not result in any code
being generated, see <a href="Preprocessor.html#Preprocessor_nn3">File Imports</a>.
</p>
</ol>
<p>

View File

@ -246,6 +246,7 @@ CPP_TEST_CASES += \
global_vars \
grouping \
ignore_parameter \
import_fragments \
import_nomodule \
inherit \
inherit_member \

View File

@ -0,0 +1,18 @@
%module import_fragments
// Check %fragments forced inclusion does not result in code generation when using %import
%import "import_fragments_a.i"
%{
template<typename T>
struct TemplateA4 {};
%}
%template(TemplateA4Int) TemplateA4<int>;
%inline %{
int getImport4() {
// Requires the ImportA4 fragment to be generated in order to compile
return ImportA4;
}
%}

View File

@ -0,0 +1,45 @@
%module import_fragments_a
%fragment("ImportA1", "header") %{
ImportA1_this_will_not_compile;
%}
%fragment("ImportA2", "header") %{
ImportA2_this_will_not_compile;
%}
%fragment("ImportA3", "header") %{
ImportA3_this_will_not_compile;
%}
%fragment("ImportA4", "header") %{
static int ImportA4 = 99;
%}
%fragment("ImportA5", "header") %{
ImportA5_this_will_not_compile;
%}
%fragment("ImportA1");
%{
Import_will_not_compile;
%}
struct StructA {
%fragment("ImportA2");
};
template<typename T>
struct TemplateA3 {
%fragment("ImportA3");
};
template<typename T>
struct TemplateA4 {
%fragment("ImportA4");
};
template<typename T>
struct TemplateA5 {
%fragment("ImportA5");
};
%template(TemplateA5Double) TemplateA5<double>;
%include "import_fragments_b.i"

View File

@ -0,0 +1,9 @@
%module import_fragments_b
%fragment("ImportB", "header") %{
ImportB_this_will_not_compile;
%}
%fragment("ImportB");

View File

@ -462,10 +462,10 @@ int JAVASCRIPT::fragmentDirective(Node *n) {
// and register them at the emitter.
String *section = Getattr(n, "section");
if (Equal(section, "templates")) {
if (Equal(section, "templates") && !ImportMode) {
emitter->registerTemplate(Getattr(n, "value"), Getattr(n, "code"));
} else {
Swig_fragment_register(n);
return Language::fragmentDirective(n);
}
return SWIG_OK;

View File

@ -624,7 +624,8 @@ int Language::constantDirective(Node *n) {
* ---------------------------------------------------------------------- */
int Language::fragmentDirective(Node *n) {
Swig_fragment_register(n);
if (!(Getattr(n, "emitonly") && ImportMode))
Swig_fragment_register(n);
return SWIG_OK;
}