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,16 +1845,82 @@ 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::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() * 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; bool first_base = false;
// recurse through all base classes to build the vtable // recurse through all base classes to build the vtable
List *bl = Getattr(n, "bases"); 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)) { for (bi = First(bl); bi.item; bi = Next(bi)) {
if (first_base && !director_multiple_inheritance) if (first_base && !director_multiple_inheritance)
break; break;
unrollVirtualMethods(bi.item, parent, vm, default_director, virtual_destructor); unrollVirtualMethods(bi.item, parent, vm, virtual_destructor);
first_base = true; first_base = true;
} }
} }
// recurse through all protected base classes to build the vtable, as needed // recurse through all protected base classes to build the vtable, as needed
bl = Getattr(n, "protectedbases"); bl = Getattr(n, "protectedbases");
if (bl) { 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)) { for (bi = First(bl); bi.item; bi = Next(bi)) {
if (first_base && !director_multiple_inheritance) if (first_base && !director_multiple_inheritance)
break; break;
unrollVirtualMethods(bi.item, parent, vm, default_director, virtual_destructor, 1); unrollVirtualMethods(bi.item, parent, vm, virtual_destructor, 1);
first_base = true; first_base = true;
} }
} }
// find the methods that need directors // find the methods that need directors
String *classname = Getattr(n, "name"); String *classname = Getattr(n, "name");
for (Node *ni = Getattr(n, "firstChild"); ni; ni = nextSibling(ni)) { 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); int is_using = (Cmp(nodeType, "using") == 0);
Node *nn = is_using ? firstChild(ni) : ni; /* assume there is only one child node for "using" nodes */ Node *nn = is_using ? firstChild(ni) : ni; /* assume there is only one child node for "using" nodes */
if (is_using) { if (is_using) {
if (nn) if (!nn)
nodeType = Getattr(nn, "nodeType"); continue; // A using node with no added functions, or a using node with private access
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;
}
} }
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;