%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 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'.
This commit is contained in:
William S Fulton 2017-08-09 00:06:24 +01:00
commit 959e627208
21 changed files with 689 additions and 114 deletions

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