diff --git a/CHANGES.current b/CHANGES.current index fd180c31c..6df9d6c5f 100644 --- a/CHANGES.current +++ b/CHANGES.current @@ -7,6 +7,13 @@ the issue number to the end of the URL: https://github.com/swig/swig/issues/ Version 4.1.0 (in progress) =========================== +2022-09-19: wsfulton + #1484 Fixes for class inheritance with the same name in different namespaces + such as: + + namespace A { class Bar {}; } + namespace B { template class Bar : public A::Bar {}; } + 2022-09-19: wsfulton #2316 Remove swig.spec file and srcrpm makefile target. These are very out of date and don't seem to be used by RPM based Linux distributions which have their diff --git a/Examples/test-suite/common.mk b/Examples/test-suite/common.mk index 64057fbcb..da90dd9fd 100644 --- a/Examples/test-suite/common.mk +++ b/Examples/test-suite/common.mk @@ -223,6 +223,7 @@ CPP_TEST_CASES += \ director_void \ director_wombat \ disown \ + duplicate_class_name_in_ns \ dynamic_cast \ empty \ enum_ignore \ diff --git a/Examples/test-suite/duplicate_class_name_in_ns.i b/Examples/test-suite/duplicate_class_name_in_ns.i new file mode 100644 index 000000000..8071f08b7 --- /dev/null +++ b/Examples/test-suite/duplicate_class_name_in_ns.i @@ -0,0 +1,88 @@ +%module duplicate_class_name_in_ns + +%rename(XA) A::X; +%rename(XB) B::X; + +%inline %{ + +namespace A +{ + class X + { + public: + X(){}; + }; + + template + class Foo + { + public: + Foo(){}; + }; + + class Bar + { + public: + Bar(){}; + }; + + template + class Baz + { + public: + Baz(){}; + }; +} + +namespace B +{ + // non-template derived from non-template + class X : public A::X + { + public: + X(){}; + A::X do_x(){return A::X();} + }; + + // template derived from template with different template args + template + class Foo : public A::Foo + { + public: + Foo(){}; + A::Foo do_foo(){return A::Foo();} + }; + + // template derived from non-template + template + class Bar : public A::Bar + { + public: + Bar(){}; + A::Bar do_bar(){return A::Bar();} + }; + + // template derived from template with same template args + template + class Baz : public A::Baz + { + public: + Baz(){}; + A::Baz do_baz(){return A::Baz();} + }; +} + +%} + +%template(AFoo) A::Foo; +%template(ABaz) A::Baz; +%template(BFoo) B::Foo; +%template(BBar) B::Bar; +%template(BBaz) B::Baz; + +%inline %{ + A::X get_a_x() {B::X x; return x.do_x();} + A::Foo get_a_foo() {B::Foo x; return x.do_foo();} + A::Bar get_a_bar() {B::Bar x; return x.do_bar();} + A::Baz get_a_baz() {B::Baz x; return x.do_baz();} +%} diff --git a/Source/CParse/templ.c b/Source/CParse/templ.c index 44a606299..8dc6a7315 100644 --- a/Source/CParse/templ.c +++ b/Source/CParse/templ.c @@ -335,6 +335,7 @@ int Swig_cparse_template_expand(Node *n, String *rname, ParmList *tparms, Symtab if (tp) { Symtab *tsdecl = Getattr(n, "sym:symtab"); + String *tsname = Getattr(n, "sym:name"); while (p && tp) { String *name, *value, *valuestr, *tmp, *tmpr; int sz, i; @@ -376,11 +377,18 @@ int Swig_cparse_template_expand(Node *n, String *rname, ParmList *tparms, Symtab sz = Len(typelist); for (i = 0; i < sz; i++) { String *s = Getitem(typelist, i); - /* Replace(s,name,value, DOH_REPLACE_ID); */ - /* Printf(stdout,"name = '%s', value = '%s', tbase = '%s', iname='%s' s = '%s' --> ", name, dvalue, tbase, iname, s); */ - SwigType_typename_replace(s, name, dvalue); - SwigType_typename_replace(s, tbase, iname); - /* Printf(stdout,"'%s'\n", s); */ + /* + The approach of 'trivially' replacing template arguments is kind of fragile. + In particular if types with similar name in different namespaces appear. + We will not replace template args if a type/class exists with the same + name which is not a template. + */ + Node * tynode = Swig_symbol_clookup(s, 0); + String *tyname = tynode ? Getattr(tynode, "sym:name") : 0; + if (!tyname || !tsname || !Equal(tyname, tsname) || Getattr(tynode, "templatetype")) { + SwigType_typename_replace(s, name, dvalue); + SwigType_typename_replace(s, tbase, iname); + } } tmp = NewStringf("#%s", name);