diff options
author | William S Fulton <wsf@fultondesigns.co.uk> | 2022-03-08 22:13:03 +0000 |
---|---|---|
committer | William S Fulton <wsf@fultondesigns.co.uk> | 2022-03-10 22:18:23 +0000 |
commit | 8a8532d823d97b68a96da02f6c754a5ce5afb48f (patch) | |
tree | 7e838b206da2739da8fa3d1c7831479e26b2e68e | |
parent | fe27e3d2ba1fc872f91053b38ec768d1916dc18a (diff) | |
download | swig-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.cxx | 147 | ||||
-rw-r--r-- | Source/Modules/swigmod.h | 4 |
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; |