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);
|
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;
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue