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:
parent
fe27e3d2ba
commit
8a8532d823
2 changed files with 81 additions and 70 deletions
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue