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.
This commit is contained in:
William S Fulton 2022-03-08 22:13:03 +00:00
commit 8a8532d823
2 changed files with 81 additions and 70 deletions

View file

@ -1845,64 +1845,31 @@ static String *vtable_method_id(Node *n) {
String *tmp = SwigType_pop_function(local_decl); String *tmp = SwigType_pop_function(local_decl);
Delete(local_decl); Delete(local_decl);
local_decl = tmp; local_decl = tmp;
Node *method_id = NewStringf("%s|%s", name, local_decl); String *method_id = NewStringf("%s|%s", name, local_decl);
Delete(local_decl); Delete(local_decl);
return method_id; return method_id;
} }
/* ---------------------------------------------------------------------- /* ----------------------------------------------------------------------
* Language::unrollVirtualMethods() * Language::unrollOneVirtualMethod()
* ---------------------------------------------------------------------- */ * ---------------------------------------------------------------------- */
int Language::unrollVirtualMethods(Node *n, Node *parent, List *vm, int default_director, int &virtual_destructor, int protectedbase) {
bool first_base = false; void Language::unrollOneVirtualMethod(String *classname, Node *n, Node *parent, List *vm, int &virtual_destructor, int protectedbase) {
// recurse through all base classes to build the vtable if (!checkAttribute(n, "storage", "virtual"))
List *bl = Getattr(n, "bases"); return;
if (bl) { if (GetFlag(n, "final"))
Iterator bi; return;
for (bi = First(bl); bi.item; bi = Next(bi)) {
if (first_base && !director_multiple_inheritance) String *nodeType = Getattr(n, "nodeType");
break;
unrollVirtualMethods(bi.item, parent, vm, default_director, virtual_destructor);
first_base = true;
}
}
// recurse through all protected base classes to build the vtable, as needed
bl = Getattr(n, "protectedbases");
if (bl) {
Iterator bi;
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);
first_base = true;
}
}
// find the methods that need directors
String *classname = Getattr(n, "name");
for (Node *ni = Getattr(n, "firstChild"); ni; ni = nextSibling(ni)) {
/* we only need to check the virtual members */
String *nodeType = Getattr(ni, "nodeType");
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) */ /* we need to add methods(cdecl) and destructor (to check for throw decl) */
int is_destructor = (Cmp(nodeType, "destructor") == 0); int is_destructor = (Cmp(nodeType, "destructor") == 0);
if ((Cmp(nodeType, "cdecl") == 0) || is_destructor) { if ((Cmp(nodeType, "cdecl") == 0) || is_destructor) {
String *decl = Getattr(nn, "decl"); String *decl = Getattr(n, "decl");
/* extra check for function type and proper access */ /* extra check for function type and proper access */
if (SwigType_isfunction(decl) && (((!protectedbase || dirprot_mode()) && is_public(nn)) || need_nonpublic_member(nn))) { if (SwigType_isfunction(decl) && (((!protectedbase || dirprot_mode()) && is_public(n)) || need_nonpublic_member(n))) {
String *name = Getattr(nn, "name"); String *name = Getattr(n, "name");
Node *method_id = is_destructor ? NewStringf("~destructor") : vtable_method_id(nn); String *method_id = is_destructor ? NewStringf("~destructor") : vtable_method_id(n);
/* Make sure that the new method overwrites the existing: */ /* Make sure that the new method overwrites the existing: */
int len = Len(vm); int len = Len(vm);
const int DO_NOT_REPLACE = -1; const int DO_NOT_REPLACE = -1;
@ -1920,7 +1887,7 @@ int Language::unrollVirtualMethods(Node *n, Node *parent, List *vm, int default_
String *fqdname = NewStringf("%s::%s", classname, name); String *fqdname = NewStringf("%s::%s", classname, name);
Hash *item = NewHash(); Hash *item = NewHash();
Setattr(item, "fqdname", fqdname); Setattr(item, "fqdname", fqdname);
Node *m = Copy(nn); Node *m = Copy(n);
/* Store the complete return type - needed for non-simple return types (pointers, references etc.) */ /* Store the complete return type - needed for non-simple return types (pointers, references etc.) */
SwigType *ty = NewString(Getattr(m, "type")); SwigType *ty = NewString(Getattr(m, "type"));
@ -1940,7 +1907,7 @@ int Language::unrollVirtualMethods(Node *n, Node *parent, List *vm, int default_
Append(vm, item); Append(vm, item);
else else
Setitem(vm, replace, item); Setitem(vm, replace, item);
Setattr(nn, "directorNode", m); Setattr(n, "directorNode", m);
Delete(mname); Delete(mname);
} }
@ -1950,12 +1917,54 @@ int Language::unrollVirtualMethods(Node *n, Node *parent, List *vm, int default_
} }
} }
/* ----------------------------------------------------------------------
* Language::unrollVirtualMethods()
* ---------------------------------------------------------------------- */
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");
if (bl) {
Iterator bi;
for (bi = First(bl); bi.item; bi = Next(bi)) {
if (first_base && !director_multiple_inheritance)
break;
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) {
Iterator bi;
for (bi = First(bl); bi.item; bi = Next(bi)) {
if (first_base && !director_multiple_inheritance)
break;
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)) {
/* we only need to check the virtual members */
String *nodeType = Getattr(ni, "nodeType");
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)
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 We delete all the nodirector methods. This prevents the
generation of 'empty' director classes. generation of 'empty' director classes.
But this has to be done outside the previous 'for' Done once we've collated all the virtual methods into vm.
and the recursive loop!.
*/ */
if (n == parent) { if (n == parent) {
int len = Len(vm); int len = Len(vm);
@ -2192,7 +2201,7 @@ int Language::classDirector(Node *n) {
} }
List *vtable = NewList(); List *vtable = NewList();
int virtual_destructor = 0; 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) // Emit all the using base::member statements for non virtual members (allprotected mode)
Node *ni; Node *ni;
@ -3784,7 +3793,7 @@ int Language::abstractClassTest(Node *n) {
#endif #endif
for (int i = 0; i < labs; i++) { for (int i = 0; i < labs; i++) {
Node *ni = Getitem(abstracts, i); Node *ni = Getitem(abstracts, i);
Node *method_id = vtable_method_id(ni); String *method_id = vtable_method_id(ni);
if (!method_id) if (!method_id)
continue; continue;
bool exists_item = false; bool exists_item = false;

View file

@ -196,7 +196,7 @@ public:
virtual int classDirector(Node *n); virtual int classDirector(Node *n);
virtual int classDirectorInit(Node *n); virtual int classDirectorInit(Node *n);
virtual int classDirectorEnd(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 classDirectorConstructor(Node *n);
virtual int classDirectorDefaultConstructor(Node *n); virtual int classDirectorDefaultConstructor(Node *n);
virtual int classDirectorMethod(Node *n, Node *parent, String *super); virtual int classDirectorMethod(Node *n, Node *parent, String *super);
@ -346,6 +346,8 @@ protected:
class DoxygenTranslator *doxygenTranslator; class DoxygenTranslator *doxygenTranslator;
private: private:
void unrollOneVirtualMethod(String *classname, Node *n, Node *parent, List *vm, int &virtual_destructor, int protectedbase);
Hash *symtabs; /* symbol tables */ Hash *symtabs; /* symbol tables */
int overloading; int overloading;
int multiinput; int multiinput;