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);
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::unrollVirtualMethods()
* Language::unrollOneVirtualMethod()
* ---------------------------------------------------------------------- */
int Language::unrollVirtualMethods(Node *n, Node *parent, List *vm, int default_director, 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, 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;
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(nn, "decl");
String *decl = Getattr(n, "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);
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;
@ -1920,7 +1887,7 @@ int Language::unrollVirtualMethods(Node *n, Node *parent, List *vm, int default_
String *fqdname = NewStringf("%s::%s", classname, name);
Hash *item = NewHash();
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.) */
SwigType *ty = NewString(Getattr(m, "type"));
@ -1940,7 +1907,7 @@ int Language::unrollVirtualMethods(Node *n, Node *parent, List *vm, int default_
Append(vm, item);
else
Setitem(vm, replace, item);
Setattr(nn, "directorNode", m);
Setattr(n, "directorNode", m);
Delete(mname);
}
@ -1948,14 +1915,56 @@ int Language::unrollVirtualMethods(Node *n, Node *parent, List *vm, int default_
virtual_destructor = 1;
}
}
}
/* ----------------------------------------------------------------------
* 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
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;

View file

@ -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;