summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWilliam S Fulton <wsf@fultondesigns.co.uk>2022-03-08 22:13:03 +0000
committerWilliam S Fulton <wsf@fultondesigns.co.uk>2022-03-10 22:18:23 +0000
commit8a8532d823d97b68a96da02f6c754a5ce5afb48f (patch)
tree7e838b206da2739da8fa3d1c7831479e26b2e68e
parentfe27e3d2ba1fc872f91053b38ec768d1916dc18a (diff)
downloadswig-8a8532d823d97b68a96da02f6c754a5ce5afb48f.tar.gz
Refactor code out of Language::unrollVirtualMethods
Move code in main loop into new function to handle one method at a time. In preparation for next commit for using declaration fix. Remove unused default_director variable.
-rw-r--r--Source/Modules/lang.cxx147
-rw-r--r--Source/Modules/swigmod.h4
2 files changed, 81 insertions, 70 deletions
diff --git a/Source/Modules/lang.cxx b/Source/Modules/lang.cxx
index 1d3513599..c9ab2e225 100644
--- a/Source/Modules/lang.cxx
+++ b/Source/Modules/lang.cxx
@@ -1845,16 +1845,82 @@ static String *vtable_method_id(Node *n) {
String *tmp = SwigType_pop_function(local_decl);
Delete(local_decl);
local_decl = tmp;
- Node *method_id = NewStringf("%s|%s", name, local_decl);
+ String *method_id = NewStringf("%s|%s", name, local_decl);
Delete(local_decl);
return method_id;
}
+/* ----------------------------------------------------------------------
+ * Language::unrollOneVirtualMethod()
+ * ---------------------------------------------------------------------- */
+
+void Language::unrollOneVirtualMethod(String *classname, Node *n, Node *parent, List *vm, int &virtual_destructor, int protectedbase) {
+ if (!checkAttribute(n, "storage", "virtual"))
+ return;
+ if (GetFlag(n, "final"))
+ return;
+
+ String *nodeType = Getattr(n, "nodeType");
+
+ /* we need to add methods(cdecl) and destructor (to check for throw decl) */
+ int is_destructor = (Cmp(nodeType, "destructor") == 0);
+ if ((Cmp(nodeType, "cdecl") == 0) || is_destructor) {
+ String *decl = Getattr(n, "decl");
+ /* extra check for function type and proper access */
+ if (SwigType_isfunction(decl) && (((!protectedbase || dirprot_mode()) && is_public(n)) || need_nonpublic_member(n))) {
+ String *name = Getattr(n, "name");
+ String *method_id = is_destructor ? NewStringf("~destructor") : vtable_method_id(n);
+ /* Make sure that the new method overwrites the existing: */
+ int len = Len(vm);
+ const int DO_NOT_REPLACE = -1;
+ int replace = DO_NOT_REPLACE;
+ for (int i = 0; i < len; i++) {
+ Node *item = Getitem(vm, i);
+ String *check_vmid = Getattr(item, "vmid");
+
+ if (Strcmp(method_id, check_vmid) == 0) {
+ replace = i;
+ break;
+ }
+ }
+ /* filling a new method item */
+ String *fqdname = NewStringf("%s::%s", classname, name);
+ Hash *item = NewHash();
+ Setattr(item, "fqdname", fqdname);
+ Node *m = Copy(n);
+
+ /* Store the complete return type - needed for non-simple return types (pointers, references etc.) */
+ SwigType *ty = NewString(Getattr(m, "type"));
+ SwigType_push(ty, decl);
+ if (SwigType_isqualifier(ty)) {
+ Delete(SwigType_pop(ty));
+ }
+ Delete(SwigType_pop_function(ty));
+ Setattr(m, "returntype", ty);
+
+ String *mname = NewStringf("%s::%s", Getattr(parent, "name"), name);
+ /* apply the features of the original method found in the base class */
+ Swig_features_get(Swig_cparse_features(), 0, mname, Getattr(m, "decl"), m);
+ Setattr(item, "methodNode", m);
+ Setattr(item, "vmid", method_id);
+ if (replace == DO_NOT_REPLACE)
+ Append(vm, item);
+ else
+ Setitem(vm, replace, item);
+ Setattr(n, "directorNode", m);
+
+ Delete(mname);
+ }
+ if (is_destructor) {
+ virtual_destructor = 1;
+ }
+ }
+}
/* ----------------------------------------------------------------------
* Language::unrollVirtualMethods()
* ---------------------------------------------------------------------- */
-int Language::unrollVirtualMethods(Node *n, Node *parent, List *vm, int default_director, int &virtual_destructor, int protectedbase) {
+int Language::unrollVirtualMethods(Node *n, Node *parent, List *vm, int &virtual_destructor, int protectedbase) {
bool first_base = false;
// recurse through all base classes to build the vtable
List *bl = Getattr(n, "bases");
@@ -1863,10 +1929,11 @@ int Language::unrollVirtualMethods(Node *n, Node *parent, List *vm, int default_
for (bi = First(bl); bi.item; bi = Next(bi)) {
if (first_base && !director_multiple_inheritance)
break;
- unrollVirtualMethods(bi.item, parent, vm, default_director, virtual_destructor);
+ unrollVirtualMethods(bi.item, parent, vm, virtual_destructor);
first_base = true;
}
}
+
// recurse through all protected base classes to build the vtable, as needed
bl = Getattr(n, "protectedbases");
if (bl) {
@@ -1874,10 +1941,11 @@ int Language::unrollVirtualMethods(Node *n, Node *parent, List *vm, int default_
for (bi = First(bl); bi.item; bi = Next(bi)) {
if (first_base && !director_multiple_inheritance)
break;
- unrollVirtualMethods(bi.item, parent, vm, default_director, virtual_destructor, 1);
+ unrollVirtualMethods(bi.item, parent, vm, virtual_destructor, 1);
first_base = true;
}
}
+
// find the methods that need directors
String *classname = Getattr(n, "name");
for (Node *ni = Getattr(n, "firstChild"); ni; ni = nextSibling(ni)) {
@@ -1886,76 +1954,17 @@ int Language::unrollVirtualMethods(Node *n, Node *parent, List *vm, int default_
int is_using = (Cmp(nodeType, "using") == 0);
Node *nn = is_using ? firstChild(ni) : ni; /* assume there is only one child node for "using" nodes */
if (is_using) {
- if (nn)
- nodeType = Getattr(nn, "nodeType");
- else
- continue; // A private "using" node
- }
- if (!checkAttribute(nn, "storage", "virtual"))
- continue;
- if (GetFlag(nn, "final"))
- continue;
- /* we need to add methods(cdecl) and destructor (to check for throw decl) */
- int is_destructor = (Cmp(nodeType, "destructor") == 0);
- if ((Cmp(nodeType, "cdecl") == 0) || is_destructor) {
- String *decl = Getattr(nn, "decl");
- /* extra check for function type and proper access */
- if (SwigType_isfunction(decl) && (((!protectedbase || dirprot_mode()) && is_public(nn)) || need_nonpublic_member(nn))) {
- String *name = Getattr(nn, "name");
- Node *method_id = is_destructor ? NewStringf("~destructor") : vtable_method_id(nn);
- /* Make sure that the new method overwrites the existing: */
- int len = Len(vm);
- const int DO_NOT_REPLACE = -1;
- int replace = DO_NOT_REPLACE;
- for (int i = 0; i < len; i++) {
- Node *item = Getitem(vm, i);
- String *check_vmid = Getattr(item, "vmid");
-
- if (Strcmp(method_id, check_vmid) == 0) {
- replace = i;
- break;
- }
- }
- /* filling a new method item */
- String *fqdname = NewStringf("%s::%s", classname, name);
- Hash *item = NewHash();
- Setattr(item, "fqdname", fqdname);
- Node *m = Copy(nn);
-
- /* Store the complete return type - needed for non-simple return types (pointers, references etc.) */
- SwigType *ty = NewString(Getattr(m, "type"));
- SwigType_push(ty, decl);
- if (SwigType_isqualifier(ty)) {
- Delete(SwigType_pop(ty));
- }
- Delete(SwigType_pop_function(ty));
- Setattr(m, "returntype", ty);
-
- String *mname = NewStringf("%s::%s", Getattr(parent, "name"), name);
- /* apply the features of the original method found in the base class */
- Swig_features_get(Swig_cparse_features(), 0, mname, Getattr(m, "decl"), m);
- Setattr(item, "methodNode", m);
- Setattr(item, "vmid", method_id);
- if (replace == DO_NOT_REPLACE)
- Append(vm, item);
- else
- Setitem(vm, replace, item);
- Setattr(nn, "directorNode", m);
-
- Delete(mname);
- }
- if (is_destructor) {
- virtual_destructor = 1;
- }
+ if (!nn)
+ continue; // A using node with no added functions, or a using node with private access
}
+ unrollOneVirtualMethod(classname, nn, parent, vm, virtual_destructor, protectedbase);
}
/*
We delete all the nodirector methods. This prevents the
generation of 'empty' director classes.
- But this has to be done outside the previous 'for'
- and the recursive loop!.
+ Done once we've collated all the virtual methods into vm.
*/
if (n == parent) {
int len = Len(vm);
@@ -2192,7 +2201,7 @@ int Language::classDirector(Node *n) {
}
List *vtable = NewList();
int virtual_destructor = 0;
- unrollVirtualMethods(n, n, vtable, 0, virtual_destructor);
+ unrollVirtualMethods(n, n, vtable, virtual_destructor);
// Emit all the using base::member statements for non virtual members (allprotected mode)
Node *ni;
@@ -3784,7 +3793,7 @@ int Language::abstractClassTest(Node *n) {
#endif
for (int i = 0; i < labs; i++) {
Node *ni = Getitem(abstracts, i);
- Node *method_id = vtable_method_id(ni);
+ String *method_id = vtable_method_id(ni);
if (!method_id)
continue;
bool exists_item = false;
diff --git a/Source/Modules/swigmod.h b/Source/Modules/swigmod.h
index bfb93d1a7..3661a2b61 100644
--- a/Source/Modules/swigmod.h
+++ b/Source/Modules/swigmod.h
@@ -196,7 +196,7 @@ public:
virtual int classDirector(Node *n);
virtual int classDirectorInit(Node *n);
virtual int classDirectorEnd(Node *n);
- virtual int unrollVirtualMethods(Node *n, Node *parent, List *vm, int default_director, int &virtual_destructor, int protectedbase = 0);
+ virtual int unrollVirtualMethods(Node *n, Node *parent, List *vm, int &virtual_destructor, int protectedbase = 0);
virtual int classDirectorConstructor(Node *n);
virtual int classDirectorDefaultConstructor(Node *n);
virtual int classDirectorMethod(Node *n, Node *parent, String *super);
@@ -346,6 +346,8 @@ protected:
class DoxygenTranslator *doxygenTranslator;
private:
+ void unrollOneVirtualMethod(String *classname, Node *n, Node *parent, List *vm, int &virtual_destructor, int protectedbase);
+
Hash *symtabs; /* symbol tables */
int overloading;
int multiinput;