mirror of https://github.com/swig/swig
Fix some scope and symbol lookup problems when template default parameters are being used with typedef - add the fully expanded template into the c symbol table and scope table.
git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/trunk@12754 626c5289-ae23-0410-ae9c-e8d60b6d4f22
This commit is contained in:
parent
6f67280044
commit
6c100423b8
|
@ -5,6 +5,20 @@ See the RELEASENOTES file for a summary of changes in each release.
|
|||
Version 2.0.5 (in progress)
|
||||
===========================
|
||||
|
||||
2011-07-01: wsfulton
|
||||
Fix some scope and symbol lookup problems when template default parameters are being
|
||||
used with typedef. For example:
|
||||
|
||||
template<typename XX, typename TT = SomeType> struct Foo {
|
||||
typedef XX X;
|
||||
typedef TT T;
|
||||
};
|
||||
template<typename TT> struct UsesFoo {
|
||||
void x(typename Foo<TT>::T, typename Foo<TT>::X);
|
||||
};
|
||||
|
||||
Also fixes use of std::vector<int>::size_type for Python as reported by Aubrey Barnard.
|
||||
|
||||
2011-06-23: olly
|
||||
[PHP] Fix director code to work when PHP is built with ZTS enabled,
|
||||
which is the standard configuration on Microsoft Windows.
|
||||
|
|
|
@ -341,6 +341,7 @@ CPP_TEST_CASES += \
|
|||
template_default2 \
|
||||
template_default_arg \
|
||||
template_default_class_parms \
|
||||
template_default_class_parms_typedef \
|
||||
template_default_inherit \
|
||||
template_default_qualify \
|
||||
template_default_vw \
|
||||
|
|
|
@ -0,0 +1,86 @@
|
|||
|
||||
|
||||
import template_default_class_parms_typedef.*;
|
||||
|
||||
public class template_default_class_parms_typedef_runme {
|
||||
|
||||
static {
|
||||
try {
|
||||
System.loadLibrary("template_default_class_parms_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[]) {
|
||||
{
|
||||
DefaultBar bar = new DefaultBar(20.0, new SomeType(), 10);
|
||||
double d = bar.getCType();
|
||||
bar.setCType(d);
|
||||
SomeType s = bar.getDType();
|
||||
bar.setDType(s);
|
||||
int i = bar.getEType();
|
||||
bar.setEType(i);
|
||||
d = bar.method(d, s, i);
|
||||
d = bar.method_1(d, s, i);
|
||||
d = bar.method_2(d, s, i);
|
||||
d = bar.method_3(d, s, i);
|
||||
|
||||
bar = new DefaultBar(true, 20.0, new SomeType(), 10);
|
||||
bar = new DefaultBar(true, true, 20.0, new SomeType(), 10);
|
||||
bar = new DefaultBar(true, true, true, 20.0, new SomeType(), 10);
|
||||
}
|
||||
{
|
||||
DefaultFoo foo = new DefaultFoo(new SomeType());
|
||||
SomeType s = foo.getTType();
|
||||
s = foo.method(s);
|
||||
s = foo.method_A(s);
|
||||
s = foo.method_B(s);
|
||||
s = foo.method_C(s);
|
||||
|
||||
foo = new DefaultFoo(new SomeType(), new SomeType());
|
||||
foo = new DefaultFoo(new SomeType(), new SomeType(), new SomeType());
|
||||
foo = new DefaultFoo(new SomeType(), new SomeType(), new SomeType(), new SomeType());
|
||||
}
|
||||
{
|
||||
BarAnotherTypeBool bar = new BarAnotherTypeBool(new AnotherType(), true, 10);
|
||||
AnotherType a = bar.getCType();
|
||||
bar.setCType(a);
|
||||
boolean b = bar.getDType();
|
||||
bar.setDType(b);
|
||||
int i = bar.getEType();
|
||||
bar.setEType(i);
|
||||
|
||||
a = bar.method(a, b, i);
|
||||
a = bar.method_1(a, b, i);
|
||||
a = bar.method_2(a, b, i);
|
||||
a = bar.method_3(a, b, i);
|
||||
|
||||
bar = new BarAnotherTypeBool(true, new AnotherType(), true, 10);
|
||||
bar = new BarAnotherTypeBool(true, true, new AnotherType(), true, 10);
|
||||
bar = new BarAnotherTypeBool(true, true, true, new AnotherType(), true, 10);
|
||||
}
|
||||
{
|
||||
FooAnotherType foo = new FooAnotherType(new AnotherType());
|
||||
AnotherType a = foo.getTType();
|
||||
foo.setTType(a);
|
||||
a = foo.method(a);
|
||||
a = foo.method_A(a);
|
||||
a = foo.method_B(a);
|
||||
a = foo.method_C(a);
|
||||
|
||||
foo = new FooAnotherType(new AnotherType(), new AnotherType());
|
||||
foo = new FooAnotherType(new AnotherType(), new AnotherType(), new AnotherType());
|
||||
foo = new FooAnotherType(new AnotherType(), new AnotherType(), new AnotherType(), new AnotherType());
|
||||
}
|
||||
{
|
||||
UsesBarDouble u = new UsesBarDouble();
|
||||
u.use_A(10.1, new SomeType(), 10);
|
||||
u.use_B(10.1, new SomeType(), 10);
|
||||
u.use_C(10.1, new SomeType(), 10);
|
||||
u.use_D(10.1, new SomeType(), 10);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -27,6 +27,7 @@ namespace std {
|
|||
|
||||
%inline %{
|
||||
typedef float Real;
|
||||
size_t typedef_test(std::vector<int>::size_type s) { return s; }
|
||||
%}
|
||||
|
||||
namespace std {
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
from li_std_vector import *
|
||||
|
||||
if typedef_test(101) != 101:
|
||||
raise RuntimeError
|
|
@ -0,0 +1,77 @@
|
|||
%module template_default_class_parms_typedef
|
||||
|
||||
// Based on template_default_class_parms testcase but using typedefs in template
|
||||
|
||||
%feature("python:nondynamic");
|
||||
|
||||
%inline %{
|
||||
namespace Space {
|
||||
struct SomeType {};
|
||||
struct AnotherType {};
|
||||
template<typename CC, typename DD = SomeType, typename EE = int> class Bar {
|
||||
public:
|
||||
typedef CC C;
|
||||
typedef DD D;
|
||||
typedef EE E;
|
||||
C CType;
|
||||
D DType;
|
||||
E EType;
|
||||
// Use typedef with no qualifiers
|
||||
Bar(C c, D d, E e) {}
|
||||
C method(C c, D d, E e) { return c; }
|
||||
|
||||
// Use typedef with classname qualifiers
|
||||
Bar(bool, Bar::C c, Bar::D d, Bar::E e) {}
|
||||
Bar::C method_1(Bar::C c, Bar::D d, Bar::E e) { return c; }
|
||||
|
||||
// Use typedef with classname and full template parameter qualifiers
|
||||
Bar(bool, bool, Bar<CC, DD, EE>::C c, Bar<CC, DD, EE>::D d, Bar<CC, DD, EE>::E e) {}
|
||||
Bar<CC, DD, EE>::C method_2(Bar<CC, DD, EE>::C c, Bar<CC, DD, EE>::D d, Bar<CC, DD, EE>::E e) { return c; }
|
||||
|
||||
// Use typedef with namespace and classname and full template parameter qualifiers
|
||||
Bar(bool, bool, bool, Space::Bar<CC, DD, EE>::C c, Space::Bar<CC, DD, EE>::D d, Space::Bar<CC, DD, EE>::E e) {}
|
||||
Space::Bar<CC, DD, EE>::C method_3(Space::Bar<CC, DD, EE>::C c, Space::Bar<CC, DD, EE>::D d, Space::Bar<CC, DD, EE>::E e) { return c; }
|
||||
};
|
||||
template<typename TT = SomeType> class Foo {
|
||||
public:
|
||||
typedef TT T;
|
||||
T TType;
|
||||
|
||||
// Use typedef with no qualifiers
|
||||
Foo(T t) {}
|
||||
T method(T t) { return t; }
|
||||
|
||||
// Use typedef with classname qualifiers
|
||||
Foo(const T &, T t) {}
|
||||
Foo::T method_A(Foo::T t) { return t; }
|
||||
|
||||
// Use typedef with classname and full template parameter qualifiers
|
||||
Foo(const Foo<TT>::T &, const Foo<TT>::T &, Foo<TT>::T t) {}
|
||||
Foo<TT>::T method_B(Foo<TT>::T t) { return t; }
|
||||
|
||||
// Use typedef with namespace and classname and full template parameter qualifiers
|
||||
Foo(const Foo<TT>::T &, const Foo<TT>::T &, const Foo<TT>::T &, Foo<TT>::T t) {}
|
||||
Foo<TT>::T method_C(Foo<TT>::T t) { return t; }
|
||||
};
|
||||
template<typename T = int> class ATemplate {};
|
||||
|
||||
template<typename T> struct UsesBar {
|
||||
void use_A(typename Bar<T>::C, typename Bar<T>::D, typename Bar<T>::E) {}
|
||||
void use_B(const typename Bar<T>::C &, const typename Bar<T>::D &, const typename Bar<T>::E &) {}
|
||||
void use_C(typename Space::Bar<T>::C, typename Space::Bar<T>::D, typename Space::Bar<T>::E) {}
|
||||
void use_D(const typename Space::Bar<T>::C &, const typename Space::Bar<T>::D &, const typename Space::Bar<T>::E &) {}
|
||||
};
|
||||
}
|
||||
%}
|
||||
|
||||
// Use defaults
|
||||
%template(DefaultBar) Space::Bar<double>;
|
||||
%template(DefaultFoo) Space::Foo<>;
|
||||
|
||||
// Don't use all defaults
|
||||
%template(BarAnotherTypeBool) Space::Bar<Space::AnotherType, bool>;
|
||||
%template(FooAnotherType) Space::Foo<Space::AnotherType>;
|
||||
|
||||
%template() Space::ATemplate<>;
|
||||
|
||||
%template(UsesBarDouble) Space::UsesBar<double>;
|
|
@ -399,20 +399,27 @@ class TypePass:private Dispatcher {
|
|||
String *nname = 0;
|
||||
String *fname = 0;
|
||||
String *scopename = 0;
|
||||
String *template_default_expanded = 0;
|
||||
|
||||
normalize = NewList();
|
||||
|
||||
if (name) {
|
||||
if (SwigType_istemplate(name)) {
|
||||
// We need to fully resolve the name to make templates work correctly */
|
||||
// We need to fully resolve the name and expand default template parameters to make templates work correctly */
|
||||
Node *cn;
|
||||
fname = SwigType_typedef_resolve_all(name);
|
||||
if (Strcmp(fname, name) != 0 && (cn = Swig_symbol_clookup_local(fname, 0))) {
|
||||
SwigType *resolved_name = SwigType_typedef_resolve_all(name);
|
||||
SwigType *deftype_name = Swig_symbol_template_deftype(resolved_name, 0);
|
||||
fname = Copy(resolved_name);
|
||||
if (!Equal(resolved_name, deftype_name))
|
||||
template_default_expanded = Copy(deftype_name);
|
||||
if (!Equal(fname, name) && (cn = Swig_symbol_clookup_local(fname, 0))) {
|
||||
if ((n == cn)
|
||||
|| (Strcmp(nodeType(cn), "template") == 0)
|
||||
|| (Getattr(cn, "feature:onlychildren") != 0)
|
||||
|| (Getattr(n, "feature:onlychildren") != 0)) {
|
||||
Swig_symbol_cadd(fname, n);
|
||||
if (template_default_expanded)
|
||||
Swig_symbol_cadd(template_default_expanded, n);
|
||||
SwigType_typedef_class(fname);
|
||||
scopename = Copy(fname);
|
||||
} else {
|
||||
|
@ -425,6 +432,8 @@ class TypePass:private Dispatcher {
|
|||
SwigType_typedef_class(fname);
|
||||
scopename = Copy(fname);
|
||||
}
|
||||
Delete(deftype_name);
|
||||
Delete(resolved_name);
|
||||
} else {
|
||||
if ((CPlusPlus) || (unnamed)) {
|
||||
SwigType_typedef_class(name);
|
||||
|
@ -444,7 +453,7 @@ class TypePass:private Dispatcher {
|
|||
SwigType_typedef(unnamed, tdname);
|
||||
}
|
||||
|
||||
if (nsname) {
|
||||
if (nsname && name) {
|
||||
nname = NewStringf("%s::%s", nsname, name);
|
||||
String *tdname = Getattr(n, "tdname");
|
||||
if (tdname) {
|
||||
|
@ -474,6 +483,13 @@ class TypePass:private Dispatcher {
|
|||
Delete(ts);
|
||||
Setattr(n, "module", module);
|
||||
|
||||
// When a fully qualified templated type with default parameters is used in the parsed code,
|
||||
// the following additional symbols and scopes are needed for successful lookups
|
||||
if (template_default_expanded) {
|
||||
Swig_symbol_alias(template_default_expanded, Getattr(n, "symtab"));
|
||||
SwigType_scope_alias(template_default_expanded, Getattr(n, "typescope"));
|
||||
}
|
||||
|
||||
/* Normalize deferred types */
|
||||
{
|
||||
normal_node *nn = new normal_node();
|
||||
|
@ -493,6 +509,7 @@ class TypePass:private Dispatcher {
|
|||
Setattr(n, "name", nname);
|
||||
Delete(nname);
|
||||
}
|
||||
Delete(fname);
|
||||
return SWIG_OK;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue