diff --git a/CHANGES.current b/CHANGES.current index c152184f3..14f4a5f4c 100644 --- a/CHANGES.current +++ b/CHANGES.current @@ -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 struct Foo { + typedef XX X; + typedef TT T; + }; + template struct UsesFoo { + void x(typename Foo::T, typename Foo::X); + }; + + Also fixes use of std::vector::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. diff --git a/Examples/test-suite/common.mk b/Examples/test-suite/common.mk index 10bc24309..0f80230ea 100644 --- a/Examples/test-suite/common.mk +++ b/Examples/test-suite/common.mk @@ -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 \ diff --git a/Examples/test-suite/java/template_default_class_parms_typedef_runme.java b/Examples/test-suite/java/template_default_class_parms_typedef_runme.java new file mode 100644 index 000000000..2b57875b7 --- /dev/null +++ b/Examples/test-suite/java/template_default_class_parms_typedef_runme.java @@ -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); + } + } +} + diff --git a/Examples/test-suite/li_std_vector.i b/Examples/test-suite/li_std_vector.i index a58f97ff1..55e0f4f6d 100644 --- a/Examples/test-suite/li_std_vector.i +++ b/Examples/test-suite/li_std_vector.i @@ -27,6 +27,7 @@ namespace std { %inline %{ typedef float Real; +size_t typedef_test(std::vector::size_type s) { return s; } %} namespace std { diff --git a/Examples/test-suite/python/li_std_vector_runme.py b/Examples/test-suite/python/li_std_vector_runme.py new file mode 100644 index 000000000..68a6d0348 --- /dev/null +++ b/Examples/test-suite/python/li_std_vector_runme.py @@ -0,0 +1,4 @@ +from li_std_vector import * + +if typedef_test(101) != 101: + raise RuntimeError diff --git a/Examples/test-suite/template_default_class_parms_typedef.i b/Examples/test-suite/template_default_class_parms_typedef.i new file mode 100644 index 000000000..fb64659ba --- /dev/null +++ b/Examples/test-suite/template_default_class_parms_typedef.i @@ -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 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::C c, Bar::D d, Bar::E e) {} + Bar::C method_2(Bar::C c, Bar::D d, Bar::E e) { return c; } + + // Use typedef with namespace and classname and full template parameter qualifiers + Bar(bool, bool, bool, Space::Bar::C c, Space::Bar::D d, Space::Bar::E e) {} + Space::Bar::C method_3(Space::Bar::C c, Space::Bar::D d, Space::Bar::E e) { return c; } + }; + template 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::T &, const Foo::T &, Foo::T t) {} + Foo::T method_B(Foo::T t) { return t; } + + // Use typedef with namespace and classname and full template parameter qualifiers + Foo(const Foo::T &, const Foo::T &, const Foo::T &, Foo::T t) {} + Foo::T method_C(Foo::T t) { return t; } + }; + template class ATemplate {}; + + template struct UsesBar { + void use_A(typename Bar::C, typename Bar::D, typename Bar::E) {} + void use_B(const typename Bar::C &, const typename Bar::D &, const typename Bar::E &) {} + void use_C(typename Space::Bar::C, typename Space::Bar::D, typename Space::Bar::E) {} + void use_D(const typename Space::Bar::C &, const typename Space::Bar::D &, const typename Space::Bar::E &) {} + }; +} +%} + +// Use defaults +%template(DefaultBar) Space::Bar; +%template(DefaultFoo) Space::Foo<>; + +// Don't use all defaults +%template(BarAnotherTypeBool) Space::Bar; +%template(FooAnotherType) Space::Foo; + +%template() Space::ATemplate<>; + +%template(UsesBarDouble) Space::UsesBar; diff --git a/Source/Modules/typepass.cxx b/Source/Modules/typepass.cxx index 74996207f..9baca9258 100644 --- a/Source/Modules/typepass.cxx +++ b/Source/Modules/typepass.cxx @@ -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; }