Add more information to these warning messages, including the
declaration for easier identification of the conflicting symbols.
Provides more consistent identifier names for constructors and methods.
Previously constructors did not display the template parameters, whereas
methods did. Incorrect 'renamed from' was also been shown for templated
methods (mmm in new testcase cpp_template_redefine.i).
1. When a template is instantiated via %template and uses the unary scope
operator ::, an error occurs if the instantiation is attempted within a
namespace that does not enclose the instantiated template.
For example, the following will now error as ::test::max is not enclosed within test1:
Error: '::test::max' resolves to 'test::max' and was incorrectly instantiated in
scope 'test1' instead of within scope 'test'.
namespace test1 {
%template(maxchar) ::test::max<char>;
}
2. SWIG previously failed to always detect a template did not exist when using
%template. In particular when instantiating a global template incorrectly within
namespace. The code below now correctly emits an error:
Error: Template 'test5::GlobalVector' undefined.
namespace test5 {
}
template<typename T> struct GlobalVector {};
%template(GVI) test5::GlobalVector<int>;
3. Also error out if an attempt is made to define a class using the unary scope
operator ::. The following is not legal C++ and now results in an error:
Error: Using the unary scope operator :: in class definition '::Space2::B' is invalid.
namespace Space2 {
struct B;
}
struct ::Space2::B {};
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'.