summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWilliam S Fulton <wsf@fultondesigns.co.uk>2022-03-06 11:37:27 +0000
committerWilliam S Fulton <wsf@fultondesigns.co.uk>2022-03-10 22:18:23 +0000
commitbd5ffe86e400855e8538da10d711a422f6c865ee (patch)
tree288f4a324a54df8f27ee066a99880217b3a035c3
parent2a9431ebfb81d2ebcb1ce489fdf43d0f751df72a (diff)
downloadswig-bd5ffe86e400855e8538da10d711a422f6c865ee.tar.gz
Using declarations in derived class parameters scoping fix
Fix using declaration in derived class incorrectly introducing a method from a base class when the using declaration is declared before the method declaration. Problem occurred when within a namespace and the parameter types in the method signatures were not fully qualified. Issue #1441
-rw-r--r--CHANGES.current6
-rw-r--r--Examples/test-suite/common.mk1
-rw-r--r--Examples/test-suite/using_member_scopes.i31
-rw-r--r--Source/Modules/typepass.cxx58
4 files changed, 74 insertions, 22 deletions
diff --git a/CHANGES.current b/CHANGES.current
index ce8efe1bf..aa3939567 100644
--- a/CHANGES.current
+++ b/CHANGES.current
@@ -38,6 +38,12 @@ Version 4.1.0 (in progress)
Also SWIG/Javascript tried to exit with status -1 in a few places
(which typically results in exit status 255).
+2022-03-05: wsfulton
+ #1441 Fix using declaration in derived class incorrectly introducing a method
+ from a base class when the using declaration is declared before the method
+ declaration. Problem occurred when within a namespace and the parameter types
+ in the method signatures were not fully qualified.
+
2022-03-03: olly
#1901 #2223 SWIG should now always exit cleanly if memory
allocation fails, including removing any output files created
diff --git a/Examples/test-suite/common.mk b/Examples/test-suite/common.mk
index 22816c552..685882f80 100644
--- a/Examples/test-suite/common.mk
+++ b/Examples/test-suite/common.mk
@@ -554,6 +554,7 @@ CPP_TEST_CASES += \
using_extend \
using_inherit \
using_member \
+ using_member_scopes \
using_namespace \
using_namespace_loop \
using_pointers \
diff --git a/Examples/test-suite/using_member_scopes.i b/Examples/test-suite/using_member_scopes.i
new file mode 100644
index 000000000..bfd09902c
--- /dev/null
+++ b/Examples/test-suite/using_member_scopes.i
@@ -0,0 +1,31 @@
+%module using_member_scopes
+
+// Fully qualifying parameter types in a method declared after the using declaration caused
+// a method being incorrectly added by the using declaration even though the declaration already existed
+
+%inline %{
+namespace OgreBites
+{
+ struct NativeWindowType {};
+ class ApplicationContextBase {
+ public:
+ virtual ~ApplicationContextBase() {}
+ virtual void setWindowGrab(NativeWindowType* win, bool grab = true) {}
+ void setWindowGrab(bool grab = true) {}
+ };
+ class ApplicationContextSDL : public ApplicationContextBase {
+ public:
+ using ApplicationContextBase::setWindowGrab;
+ void setWindowGrab(NativeWindowType* win, bool grab) {} // This should not be added again as it exists in base class
+ };
+/*
+typedef not working yet
+ class ApplicationContextSDL2 : public ApplicationContextBase {
+ public:
+ using ApplicationContextBase::setWindowGrab;
+ typedef NativeWindowType* pNWT;
+ void setWindowGrab(pNWT win, bool grab) {} // This should not be added again as it exists in base class
+ };
+*/
+}
+%}
diff --git a/Source/Modules/typepass.cxx b/Source/Modules/typepass.cxx
index d3f8dc196..658f2e79c 100644
--- a/Source/Modules/typepass.cxx
+++ b/Source/Modules/typepass.cxx
@@ -1039,6 +1039,21 @@ class TypePass:private Dispatcher {
Node *unodes = 0, *last_unodes = 0;
int ccount = 0;
String *symname = Getattr(n, "sym:name");
+
+ // The overloaded functions in scope may not yet have had their parameters normalized yet (in cDeclaration).
+ // Happens if the functions were declared after the using declaration. So use a normalized copy.
+ List *n_decl_list = NewList();
+ Node *over = Getattr(n, "sym:overloaded");
+ while (over) {
+ String *odecl = Copy(Getattr(over, "decl"));
+ if (odecl) {
+ normalize_type(odecl);
+ Append(n_decl_list, odecl);
+ Delete(odecl);
+ }
+ over = Getattr(over, "sym:nextSibling");
+ }
+
while (c) {
if (Strcmp(nodeType(c), "cdecl") == 0) {
if (!(Swig_storage_isstatic(c)
@@ -1049,30 +1064,28 @@ class TypePass:private Dispatcher {
String *csymname = Getattr(c, "sym:name");
if (!csymname || (Strcmp(csymname, symname) == 0)) {
- {
- String *decl = Getattr(c, "decl");
- Node *over = Getattr(n, "sym:overloaded");
- int match = 0;
- while (over) {
- String *odecl = Getattr(over, "decl");
- if (Cmp(decl, odecl) == 0) {
- match = 1;
- break;
- }
- over = Getattr(over, "sym:nextSibling");
- }
- if (match) {
- /* Don't generate a method if the method is overridden in this class,
- * for example don't generate another m(bool) should there be a Base::m(bool) :
- * struct Derived : Base {
- * void m(bool);
- * using Base::m;
- * };
- */
- c = Getattr(c, "csym:nextSibling");
- continue;
+ String *decl = Getattr(c, "decl");
+ int match = 0;
+
+ for (Iterator it = First(n_decl_list); it.item; it = Next(it)) {
+ String *odecl = it.item;
+ if (Cmp(decl, odecl) == 0) {
+ match = 1;
+ break;
}
}
+ if (match) {
+ /* Don't generate a method if the method is overridden in this class,
+ * for example don't generate another m(bool) should there be a Base::m(bool) :
+ * struct Derived : Base {
+ * void m(bool);
+ * using Base::m;
+ * };
+ */
+ c = Getattr(c, "csym:nextSibling");
+ continue;
+ }
+
Node *nn = copyNode(c);
Setfile(nn, Getfile(n));
Setline(nn, Getline(n));
@@ -1206,6 +1219,7 @@ class TypePass:private Dispatcher {
#endif
clean_overloaded(n); // Needed?
}
+ Delete(n_decl_list);
}
}
} else if ((Strcmp(ntype, "class") == 0) || ((Strcmp(ntype, "classforward") == 0))) {