process protected/private bases, support/ignore multi-inheritance directors

git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/trunk/SWIG@6734 626c5289-ae23-0410-ae9c-e8d60b6d4f22
This commit is contained in:
Marcelo Matus 2004-11-15 22:51:48 +00:00
commit acb5bc3e48

View file

@ -277,6 +277,8 @@ Language::Language() :
default. Each language that need it, has to define it. default. Each language that need it, has to define it.
*/ */
director_prot_ctor_code = 0; director_prot_ctor_code = 0;
director_multiple_inheritance = 1;
director_language = 0;
} }
Language::~Language() { Language::~Language() {
@ -729,7 +731,7 @@ int Language::cDeclaration(Node *n) {
if (!isfriend ) { if (!isfriend ) {
/* we check what director needs. If the method is pure virtual, /* we check what director needs. If the method is pure virtual,
it is always needed. */ it is always needed. */
if (!(is_member_director(CurrentClass,n) && need_nonpublic_member(n))) if (!(directorsEnabled() && is_member_director(CurrentClass,n) && need_nonpublic_member(n)))
return SWIG_NOWRAP; return SWIG_NOWRAP;
} }
} }
@ -1515,22 +1517,50 @@ int Language::classDirectorDefaultConstructor(Node *n) {
/* ---------------------------------------------------------------------- /* ----------------------------------------------------------------------
* Language::unrollVirtualMethods() * Language::unrollVirtualMethods()
* ---------------------------------------------------------------------- */ * ---------------------------------------------------------------------- */
static
String *vtable_method_id(Node *n)
{
String *nodeType = Getattr(n, "nodeType");
int is_destructor = (Cmp(nodeType, "destructor") == 0);
if (is_destructor) return 0;
String *name = Getattr(n, "name");
String *decl = Getattr(n, "decl");
String *local_decl = SwigType_typedef_resolve_all(decl);
Node *method_id = NewStringf("%s|%s", name, local_decl);
Delete(local_decl);
return method_id;
}
int Language::unrollVirtualMethods(Node *n, int Language::unrollVirtualMethods(Node *n,
Node *parent, Node *parent,
Hash *vm, Hash *vm,
int default_director, int default_director,
int &virtual_destructor) { int &virtual_destructor,
int protectedbase) {
Node *ni; Node *ni;
String *nodeType; String *nodeType;
String *classname; String *classname;
String *decl; String *decl;
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");
if (bl) { if (bl) {
Iterator bi; Iterator bi;
for (bi = First(bl); bi.item; bi = Next(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); 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 // find the methods that need directors
@ -1545,11 +1575,11 @@ int Language::unrollVirtualMethods(Node *n,
decl = Getattr(ni, "decl"); decl = Getattr(ni, "decl");
/* extra check for function type and proper access */ /* extra check for function type and proper access */
if (SwigType_isfunction(decl) if (SwigType_isfunction(decl)
&& (is_public(n) || need_nonpublic_member(n)) && (((!protectedbase || dirprot_mode()) && is_public(ni))
&& (is_public(ni) || need_nonpublic_member(ni))) { || need_nonpublic_member(ni))) {
String *name = Getattr(ni, "name"); String *name = Getattr(ni, "name");
String *local_decl = SwigType_typedef_resolve_all(decl); Node *method_id = is_destructor ?
Node *method_id = is_destructor ? NewStringf("~destructor") : NewStringf("%s|%s", name, local_decl); NewStringf("~destructor") : vtable_method_id(ni);
/* Make sure that the new method overwrites the existing: */ /* Make sure that the new method overwrites the existing: */
Hash *exists_item = Getattr(vm, method_id); Hash *exists_item = Getattr(vm, method_id);
if (exists_item) { if (exists_item) {
@ -1564,7 +1594,8 @@ int Language::unrollVirtualMethods(Node *n,
Hash *item = NewHash(); Hash *item = NewHash();
Setattr(item, "fqName", fqname); Setattr(item, "fqName", fqname);
Node *m = Copy(ni); Node *m = Copy(ni);
String *mname = NewStringf("%s::%s", Getattr(parent,"name"), name); 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); Swig_features_get(Swig_cparse_features(), 0, mname, Getattr(m,"decl"), m);
Setattr(item, "methodNode", m); Setattr(item, "methodNode", m);
Setattr(vm, method_id, item); Setattr(vm, method_id, item);
@ -1572,7 +1603,6 @@ int Language::unrollVirtualMethods(Node *n,
Delete(fqname); Delete(fqname);
Delete(item); Delete(item);
Delete(method_id); Delete(method_id);
Delete(local_decl);
} }
if (is_destructor) { if (is_destructor) {
virtual_destructor = 1; virtual_destructor = 1;
@ -1592,39 +1622,16 @@ int Language::unrollVirtualMethods(Node *n,
for (k = First(vm); k.key; k = Next(k)) { for (k = First(vm); k.key; k = Next(k)) {
Node *m = Getattr(k.item, "methodNode"); Node *m = Getattr(k.item, "methodNode");
/* retrieve the director features */ /* retrieve the director features */
int mdir = checkAttribute(m, "feature:director", "1") || director_mode; int mdir = checkAttribute(m, "feature:director", "1");
int mndir = checkAttribute(m, "feature:nodirector", "1"); int mndir = checkAttribute(m, "feature:nodirector", "1");
/* 'nodirector' has precedence over 'director' */ /* 'nodirector' has precedence over 'director' */
int dir = (mdir || mndir) ? (mdir && !mndir) : 1; int dir = (mdir || mndir) ? (mdir && !mndir) : 1;
/* check if the method was found only in a base class */ /* check if the method was found only in a base class */
Node *p = Getattr(m, "parentNode"); Node *p = Getattr(m, "parentNode");
if (p != n) { if (p != n) {
/* check for my own features to take precedence, ie, if I only
found Base::method(), look for MySelf::method() features.
The problem is that MySelf::method() is not declared in the
MySelf class, and appears here through derivation:
%feature("nodirector") Base::method();
%feature("director") MySelf::method();
struct Base {
virtual ~Base();
virtual int method();
};
struct MySelf : Base {
};
*** Ask David, this is not working now!!! *****
This is now just giving back the Base::method() features,
maybe we need to look directly in the feature hash
table?...
*/
Node *c = Copy(m); Node *c = Copy(m);
Setattr(c, "parentNode", n); Setattr(c, "parentNode", n);
int cdir = checkAttribute(c, "feature:director", "1") || director_mode; int cdir = checkAttribute(c, "feature:director", "1");
int cndir = checkAttribute(c, "feature:nodirector", "1"); int cndir = checkAttribute(c, "feature:nodirector", "1");
dir = (cdir || cndir) ? (cdir && !cndir) : dir; dir = (cdir || cndir) ? (cdir && !cndir) : dir;
Delete(c); Delete(c);
@ -1637,7 +1644,7 @@ int Language::unrollVirtualMethods(Node *n,
Delattr(vm, k.key); Delattr(vm, k.key);
} }
} }
} }
return SWIG_OK; return SWIG_OK;
} }
@ -1696,16 +1703,21 @@ int Language::classDirectorConstructors(Node *n) {
for (ni = Getattr(n, "firstChild"); ni; ni = nextSibling(ni)) { for (ni = Getattr(n, "firstChild"); ni; ni = nextSibling(ni)) {
nodeType = Getattr(ni, "nodeType"); nodeType = Getattr(ni, "nodeType");
if (!Cmp(nodeType, "constructor")) { if (!Cmp(nodeType, "constructor")) {
Parm *parms = Getattr(ni,"parms");
if (is_public(ni)) { if (is_public(ni)) {
/* emit public constructor */ /* emit public constructor */
classDirectorConstructor(ni); classDirectorConstructor(ni);
constructor = 1; constructor = 1;
if (default_ctor)
default_ctor = !ParmList_numrequired(parms);
} else { } else {
/* emit protected constructor if needed */ /* emit protected constructor if needed */
if (need_nonpublic_ctor(ni)) { if (need_nonpublic_ctor(ni)) {
classDirectorConstructor(ni); classDirectorConstructor(ni);
constructor = 1; constructor = 1;
protected_ctor = 1; protected_ctor = 1;
if (default_ctor)
default_ctor = !ParmList_numrequired(parms);
} }
} }
} }
@ -1840,6 +1852,11 @@ int Language::classDirector(Node *n) {
"Director base class %s has no virtual destructor.\n", "Director base class %s has no virtual destructor.\n",
classtype); classtype);
} }
/*
since now %feature("nodirector") is working, we check
that the director is really not abstract.
*/
Setattr(n, "vtable", vtable); Setattr(n, "vtable", vtable);
classDirectorInit(n); classDirectorInit(n);
classDirectorConstructors(n); classDirectorConstructors(n);
@ -1913,19 +1930,21 @@ int Language::classDeclaration(Node *n) {
InClass = 1; InClass = 1;
CurrentClass = n; CurrentClass = n;
Abstract = abstractClassTest(n);
/* Call classHandler() here */ /* Call classHandler() here */
if (!ImportMode) { if (!ImportMode) {
int ndir = checkAttribute(n, "feature:director", "1") || director_mode; int ndir = checkAttribute(n, "feature:director", "1");
int nndir = checkAttribute(n, "feature:nodirector", "1"); int nndir = checkAttribute(n, "feature:nodirector", "1");
/* 'nodirector' has precedence over 'director' */ /* 'nodirector' has precedence over 'director' */
int dir = (ndir || nndir) ? (ndir && !nndir) : 0; int dir = (ndir || nndir) ? (ndir && !nndir) : 0;
if (directorsEnabled() && dir) { if (directorsEnabled() && dir) {
classDirector(n); classDirector(n);
} }
/* check for abstract after resolving directors */
Abstract = abstractClassTest(n);
classHandler(n); classHandler(n);
} else { } else {
Abstract = abstractClassTest(n);
Language::classHandler(n); Language::classHandler(n);
} }
@ -1992,6 +2011,7 @@ int Language::classHandler(Node *n) {
bool hasDirector = Swig_directorclass(n) ? true : false; bool hasDirector = Swig_directorclass(n) ? true : false;
/* Emit all of the class members */ /* Emit all of the class members */
emit_children(n); emit_children(n);
@ -2011,7 +2031,7 @@ int Language::classHandler(Node *n) {
if (!ImportMode && (GenerateDefault && !Getattr(n,"feature:nodefault"))) { if (!ImportMode && (GenerateDefault && !Getattr(n,"feature:nodefault"))) {
if (!Getattr(n,"has_constructor") && !Getattr(n,"allocate:has_constructor") && (Getattr(n,"allocate:default_constructor"))) { if (!Getattr(n,"has_constructor") && !Getattr(n,"allocate:has_constructor") && (Getattr(n,"allocate:default_constructor"))) {
/* Note: will need to change this to support different kinds of classes */ /* Note: will need to change this to support different kinds of classes */
if (!Abstract || hasDirector) { if (!Abstract) {
Node *cn = makeConstructor(CurrentClass); Node *cn = makeConstructor(CurrentClass);
constructorHandler(cn); constructorHandler(cn);
Delete(cn); Delete(cn);
@ -2098,6 +2118,7 @@ int Language::constructorDeclaration(Node *n) {
} }
/* Only create a constructor if the class is not abstract */ /* Only create a constructor if the class is not abstract */
if (!Abstract) { if (!Abstract) {
Node *over; Node *over;
over = Swig_symbol_isoverloaded(n); over = Swig_symbol_isoverloaded(n);
@ -2143,22 +2164,51 @@ int Language::constructorDeclaration(Node *n) {
* Language::constructorHandler() * Language::constructorHandler()
* ---------------------------------------------------------------------- */ * ---------------------------------------------------------------------- */
static String*
get_director_ctor_code(Node *n, String *director_ctor_code,
String *director_prot_ctor_code,
List*& abstract )
{
String *director_ctor = director_ctor_code;
int use_director = Swig_directorclass(n);
if (use_director) {
Node *pn = Swig_methodclass(n);
abstract = Getattr(pn,"abstract");
if (director_prot_ctor_code) {
int is_notabstract = Getattr(pn,"feature:notabstract") ? 1 : 0;
int is_abstract = abstract && !is_notabstract;
if (is_protected(n) || is_abstract) {
director_ctor = director_prot_ctor_code;
Delattr(pn,"abstract");
} else {
if (is_notabstract) {
Delattr(pn,"abstract");
} else {
abstract = 0;
}
}
}
}
return director_ctor;
}
int int
Language::constructorHandler(Node *n) { Language::constructorHandler(Node *n) {
Swig_require("constructorHandler",n,"?name","*sym:name","?type","?parms",NIL); Swig_require("constructorHandler",n,"?name","*sym:name","?type","?parms",NIL);
String *symname = Getattr(n,"sym:name"); String *symname = Getattr(n,"sym:name");
String *mrename = Swig_name_construct(symname); String *mrename = Swig_name_construct(symname);
String *director_ctor = director_ctor_code; List *abstract = 0;
if (director_prot_ctor_code) { String *director_ctor = get_director_ctor_code(n, director_ctor_code,
if (is_protected(n) || Getattr(Swig_methodclass(n),"abstract")) { director_prot_ctor_code,
director_ctor = director_prot_ctor_code; abstract);
} Swig_ConstructorToFunction(n, ClassType, none_comparison, director_ctor,
} CPlusPlus, Getattr(n, "template") ? 0 :Extend);
Swig_ConstructorToFunction(n, ClassType, none_comparison, director_ctor, CPlusPlus, Getattr(n, "template") ? 0 :Extend);
Setattr(n,"sym:name", mrename); Setattr(n,"sym:name", mrename);
functionWrapper(n); functionWrapper(n);
Delete(mrename); Delete(mrename);
Swig_restore(n); Swig_restore(n);
if (abstract) Setattr(Swig_methodclass(n),"abstract",abstract);
return SWIG_OK; return SWIG_OK;
} }
@ -2171,18 +2221,17 @@ Language::copyconstructorHandler(Node *n) {
Swig_require("copyconstructorHandler",n,"?name","*sym:name","?type","?parms", NIL); Swig_require("copyconstructorHandler",n,"?name","*sym:name","?type","?parms", NIL);
String *symname = Getattr(n,"sym:name"); String *symname = Getattr(n,"sym:name");
String *mrename = Swig_name_copyconstructor(symname); String *mrename = Swig_name_copyconstructor(symname);
String *director_ctor = director_ctor_code; List *abstract = 0;
if (director_prot_ctor_code) { String *director_ctor = get_director_ctor_code(n, director_ctor_code,
if (is_protected(n) || Getattr(Swig_methodclass(n),"abstract")) { director_prot_ctor_code,
director_ctor = director_prot_ctor_code; abstract);
}
}
Swig_ConstructorToFunction(n,ClassType, none_comparison, director_ctor, Swig_ConstructorToFunction(n,ClassType, none_comparison, director_ctor,
CPlusPlus, Getattr(n,"template") ? 0 : Extend); CPlusPlus, Getattr(n,"template") ? 0 : Extend);
Setattr(n,"sym:name", mrename); Setattr(n,"sym:name", mrename);
functionWrapper(n); functionWrapper(n);
Delete(mrename); Delete(mrename);
Swig_restore(n); Swig_restore(n);
if (abstract) Setattr(Swig_methodclass(n),"abstract",abstract);
return SWIG_OK; return SWIG_OK;
} }
@ -2576,7 +2625,7 @@ void Language::allow_directors(int val) {
* ----------------------------------------------------------------------------- */ * ----------------------------------------------------------------------------- */
int Language::directorsEnabled() const { int Language::directorsEnabled() const {
return (directors || director_mode) && CPlusPlus; return director_language && CPlusPlus && (directors || director_mode);
} }
/* ----------------------------------------------------------------------------- /* -----------------------------------------------------------------------------
@ -2731,33 +2780,61 @@ String * Language::getClassType() const {
/* ----------------------------------------------------------------------------- /* -----------------------------------------------------------------------------
* Language::abstractClassTest() * Language::abstractClassTest()
* ----------------------------------------------------------------------------- */ * ----------------------------------------------------------------------------- */
//#define SWIG_DEBUG
int Language::abstractClassTest(Node *n) { int Language::abstractClassTest(Node *n) {
/* check for non public operator new */ /* check for non public operator new */
if (Getattr(n,"feature:notabstract")) return 0;
if (Getattr(n,"allocate:nonew")) return 1; if (Getattr(n,"allocate:nonew")) return 1;
/* now check for the rest */ /* now check for the rest */
List *abstract = Getattr(n,"abstract"); List *abstract = Getattr(n,"abstract");
if (!abstract) return 0; if (!abstract) return 0;
int labs = Len(abstract);
#ifdef SWIG_DEBUG
List *bases = Getattr(n,"allbases");
Printf(stderr,"testing %s %d %d\n",Getattr(n,"name"),labs,Len(bases));
#endif
if (!labs) return 0; /*strange, but need to be fixed */
if (abstract && !directorsEnabled()) return 1; if (abstract && !directorsEnabled()) return 1;
if (Cmp(Getattr(n, "feature:director"), "1")) return 1; if (!Getattr(n,"feature:director")) return 1;
/*
since now %feature("noabstract") is working, we check Node *dirabstract = 0;
that the director is really not abstract. Node *vtable = Getattr(n, "vtable");
*/ if (vtable) {
int dirabstract = 0; #ifdef SWIG_DEBUG
for (int i = 0; i < Len(abstract); i++) { Printf(stderr,"vtable %s %d %d\n",Getattr(n,"name"),Len(vtable),labs);
Node *nn = Getitem(abstract,i); #endif
if (!is_member_director(n,nn)) { for (int i = 0; i < labs; i++) {
dirabstract = 1; Node *ni = Getitem(abstract,i);
Node *method_id = vtable_method_id(ni);
if (!method_id) continue;
Hash *exists_item = Getattr(vtable, method_id);
#ifdef SWIG_DEBUG
Printf(stderr,"method %s %d\n",method_id,exists_item ? 1 : 0);
#endif
Delete(method_id);
if (!exists_item) {
dirabstract = ni;
break;
}
} }
if (dirabstract) {
if (is_public(dirabstract)) {
Swig_warning(WARN_LANG_DIRECTOR_ABSTRACT,Getfile(n),Getline(n),
"Director class '%s' is abstract, abstract method '%s' is not accesible, maybe due to multiple inheritance or 'nodirector' feature\n",
SwigType_namestr(Getattr(n,"name")),
Getattr(dirabstract,"name"));
} else {
Swig_warning(WARN_LANG_DIRECTOR_ABSTRACT,Getfile(n),Getline(n),
"Director class '%s' is abstract, abstract method '%s' is private\n",
SwigType_namestr(Getattr(n,"name")),
Getattr(dirabstract,"name"));
}
return 1;
}
} else {
return 1;
} }
if (dirabstract) { return dirabstract ? 1 : 0;
Swig_warning(WARN_LANG_DIRECTOR_ABSTRACT,Getfile(n),Getline(n),
"Director class '%s' is abstract\n",
SwigType_namestr(Getattr(n,"name")));
}
return dirabstract;
} }
void Language::setSubclassInstanceCheck(String *nc) { void Language::setSubclassInstanceCheck(String *nc) {