diff options
author | vitalyisaev <vitalyisaev@ydb.tech> | 2023-11-30 13:26:22 +0300 |
---|---|---|
committer | vitalyisaev <vitalyisaev@ydb.tech> | 2023-11-30 15:44:45 +0300 |
commit | 0a98fece5a9b54f16afeb3a94b3eb3105e9c3962 (patch) | |
tree | 291d72dbd7e9865399f668c84d11ed86fb190bbf /contrib/tools/swig/Source/Modules/allocate.cxx | |
parent | cb2c8d75065e5b3c47094067cb4aa407d4813298 (diff) | |
download | ydb-0a98fece5a9b54f16afeb3a94b3eb3105e9c3962.tar.gz |
YQ Connector:Use docker-compose in integrational tests
Diffstat (limited to 'contrib/tools/swig/Source/Modules/allocate.cxx')
-rw-r--r-- | contrib/tools/swig/Source/Modules/allocate.cxx | 971 |
1 files changed, 971 insertions, 0 deletions
diff --git a/contrib/tools/swig/Source/Modules/allocate.cxx b/contrib/tools/swig/Source/Modules/allocate.cxx new file mode 100644 index 0000000000..0e1262f839 --- /dev/null +++ b/contrib/tools/swig/Source/Modules/allocate.cxx @@ -0,0 +1,971 @@ +/* ----------------------------------------------------------------------------- + * This file is part of SWIG, which is licensed as a whole under version 3 + * (or any later version) of the GNU General Public License. Some additional + * terms also apply to certain portions of SWIG. The full details of the SWIG + * license and copyrights can be found in the LICENSE and COPYRIGHT files + * included with the SWIG source code as distributed by the SWIG developers + * and at https://www.swig.org/legal.html. + * + * allocate.cxx + * + * This module tries to figure out which classes and structures support + * default constructors and destructors in C++. There are several rules that + * define this behavior including pure abstract methods, private sections, + * and non-default constructors in base classes. See the ARM or + * Doc/Manual/SWIGPlus.html for details. + * ----------------------------------------------------------------------------- */ + +#include "swigmod.h" +#include "cparse.h" + +static int virtual_elimination_mode = 0; /* set to 0 on default */ + +/* Set virtual_elimination_mode */ +void Wrapper_virtual_elimination_mode_set(int flag) { + virtual_elimination_mode = flag; +} + +/* Helper function to assist with abstract class checking. + This is a major hack. Sorry. */ + +extern "C" { + static String *search_decl = 0; /* Declarator being searched */ + static int check_implemented(Node *n) { + String *decl; + if (!n) + return 0; + while (n) { + if (Strcmp(nodeType(n), "cdecl") == 0) { + decl = Getattr(n, "decl"); + if (SwigType_isfunction(decl)) { + SwigType *decl1 = SwigType_typedef_resolve_all(decl); + SwigType *decl2 = SwigType_pop_function(decl1); + if (Strcmp(decl2, search_decl) == 0) { + if (!GetFlag(n, "abstract")) { + Delete(decl1); + Delete(decl2); + return 1; + } + } + Delete(decl1); + Delete(decl2); + } + } + n = Getattr(n, "csym:nextSibling"); + } + return 0; + } +} + +class Allocate:public Dispatcher { + Node *inclass; + int extendmode; + + /* Checks if a function, n, is the same as any in the base class, ie if the method is polymorphic. + * Also checks for methods which will be hidden (ie a base has an identical non-virtual method). + * Both methods must have public access for a match to occur. */ + int function_is_defined_in_bases(Node *n, Node *bases) { + + if (!bases) + return 0; + + String *this_decl = Getattr(n, "decl"); + if (!this_decl) + return 0; + + String *name = Getattr(n, "name"); + String *this_type = Getattr(n, "type"); + String *resolved_decl = SwigType_typedef_resolve_all(this_decl); + + // Search all base classes for methods with same signature + for (int i = 0; i < Len(bases); i++) { + Node *b = Getitem(bases, i); + Node *base = firstChild(b); + while (base) { + if (Strcmp(nodeType(base), "extend") == 0) { + // Loop through all the %extend methods + Node *extend = firstChild(base); + while (extend) { + if (function_is_defined_in_bases_seek(n, b, extend, this_decl, name, this_type, resolved_decl)) { + Delete(resolved_decl); + return 1; + } + extend = nextSibling(extend); + } + } else if (Strcmp(nodeType(base), "using") == 0) { + // Loop through all the using declaration methods + Node *usingdecl = firstChild(base); + while (usingdecl) { + if (function_is_defined_in_bases_seek(n, b, usingdecl, this_decl, name, this_type, resolved_decl)) { + Delete(resolved_decl); + return 1; + } + usingdecl = nextSibling(usingdecl); + } + } else { + // normal methods + if (function_is_defined_in_bases_seek(n, b, base, this_decl, name, this_type, resolved_decl)) { + Delete(resolved_decl); + return 1; + } + } + base = nextSibling(base); + } + } + Delete(resolved_decl); + resolved_decl = 0; + for (int j = 0; j < Len(bases); j++) { + Node *b = Getitem(bases, j); + if (function_is_defined_in_bases(n, Getattr(b, "allbases"))) + return 1; + } + return 0; + } + + /* Helper function for function_is_defined_in_bases */ + int function_is_defined_in_bases_seek(Node *n, Node *b, Node *base, String *this_decl, String *name, String *this_type, String *resolved_decl) { + + String *base_decl = Getattr(base, "decl"); + SwigType *base_type = Getattr(base, "type"); + if (base_decl && base_type) { + if (checkAttribute(base, "name", name) && !GetFlag(b, "feature:ignore") /* whole class is ignored */ ) { + if (SwigType_isfunction(resolved_decl) && SwigType_isfunction(base_decl)) { + // We have found a method that has the same name as one in a base class + bool covariant_returntype = false; + bool returntype_match = Strcmp(base_type, this_type) == 0 ? true : false; + bool decl_match = Strcmp(base_decl, this_decl) == 0 ? true : false; + if (returntype_match && decl_match) { + // Exact match - we have found a method with identical signature + // No typedef resolution was done, but skipping it speeds things up slightly + } else { + // Either we have: + // 1) matching methods but are one of them uses a different typedef (return type or parameter) to the one in base class' method + // 2) matching polymorphic methods with covariant return type + // 3) a non-matching method (ie an overloaded method of some sort) + // 4) a matching method which is not polymorphic, ie it hides the base class' method + + // Check if fully resolved return types match (including + // covariant return types) + if (!returntype_match) { + String *this_returntype = function_return_type(n); + String *base_returntype = function_return_type(base); + returntype_match = Strcmp(this_returntype, base_returntype) == 0 ? true : false; + if (!returntype_match) { + covariant_returntype = SwigType_issubtype(this_returntype, base_returntype) ? true : false; + returntype_match = covariant_returntype; + } + Delete(this_returntype); + Delete(base_returntype); + } + // The return types must match at this point, for the whole method to match + if (returntype_match && !decl_match) { + // Now need to check the parameter list + // First do an inexpensive parameter count + ParmList *this_parms = Getattr(n, "parms"); + ParmList *base_parms = Getattr(base, "parms"); + if (ParmList_len(this_parms) == ParmList_len(base_parms)) { + // Number of parameters are the same, now check that all the parameters match + SwigType *base_fn = NewString(""); + SwigType *this_fn = NewString(""); + SwigType_add_function(base_fn, base_parms); + SwigType_add_function(this_fn, this_parms); + base_fn = SwigType_typedef_resolve_all(base_fn); + this_fn = SwigType_typedef_resolve_all(this_fn); + if (Strcmp(base_fn, this_fn) == 0) { + // Finally check that the qualifiers match + int base_qualifier = SwigType_isqualifier(resolved_decl); + int this_qualifier = SwigType_isqualifier(base_decl); + if (base_qualifier == this_qualifier) { + decl_match = true; + } + } + Delete(base_fn); + Delete(this_fn); + } + } + } + //Printf(stderr,"look %s %s %d %d\n",base_decl, this_decl, returntype_match, decl_match); + + if (decl_match && returntype_match) { + // Found an identical method in the base class + bool this_wrapping_protected_members = is_member_director(n) ? true : false; // This should really check for dirprot rather than just being a director method + bool base_wrapping_protected_members = is_member_director(base) ? true : false; // This should really check for dirprot rather than just being a director method + bool both_have_public_access = is_public(n) && is_public(base); + bool both_have_protected_access = (is_protected(n) && this_wrapping_protected_members) && (is_protected(base) && base_wrapping_protected_members); + bool both_have_private_access = is_private(n) && is_private(base); + if (checkAttribute(base, "storage", "virtual")) { + // Found a polymorphic method. + // Mark the polymorphic method, in case the virtual keyword was not used. + Setattr(n, "storage", "virtual"); + if (!GetFlag(b, "feature:interface")) { // interface implementation neither hides nor overrides + if (both_have_public_access || both_have_protected_access) { + if (!is_non_public_base(inclass, b)) + Setattr(n, "override", base); // Note C# definition of override, ie access must be the same + } + else if (!both_have_private_access) { + // Different access + if (this_wrapping_protected_members || base_wrapping_protected_members) + if (!is_non_public_base(inclass, b)) + Setattr(n, "hides", base); // Note C# definition of hiding, ie hidden if access is different + } + } + // Try and find the most base's covariant return type + SwigType *most_base_covariant_type = Getattr(base, "covariant"); + if (!most_base_covariant_type && covariant_returntype) + most_base_covariant_type = function_return_type(base, false); + + if (!most_base_covariant_type) { + // Eliminate the derived virtual method. + if (virtual_elimination_mode && !is_member_director(n)) + if (both_have_public_access) + if (!is_non_public_base(inclass, b)) + if (!Swig_symbol_isoverloaded(n)) { + // Don't eliminate if an overloaded method as this hides the method + // in the scripting languages: the dispatch function will hide the base method if ignored. + SetFlag(n, "feature:ignore"); + } + } else { + // Some languages need to know about covariant return types + Setattr(n, "covariant", most_base_covariant_type); + } + + } else { + // Found an identical method in the base class, but it is not polymorphic. + if (both_have_public_access || both_have_protected_access) + if (!is_non_public_base(inclass, b)) + Setattr(n, "hides", base); + } + if (both_have_public_access || both_have_protected_access) + return 1; + } + } + } + } + return 0; + } + + /* Determines whether the base class, b, is in the list of private + * or protected base classes for class n. */ + bool is_non_public_base(Node *n, Node *b) { + bool non_public_base = false; + Node *bases = Getattr(n, "privatebases"); + if (bases) { + for (int i = 0; i < Len(bases); i++) { + Node *base = Getitem(bases, i); + if (base == b) + non_public_base = true; + } + } + bases = Getattr(n, "protectedbases"); + if (bases) { + for (int i = 0; i < Len(bases); i++) { + Node *base = Getitem(bases, i); + if (base == b) + non_public_base = true; + } + } + return non_public_base; + } + + /* Returns the return type for a function. The node n should be a function. + If resolve is true the fully returned type is fully resolved. + Caller is responsible for deleting returned string. */ + String *function_return_type(Node *n, bool resolve = true) { + String *decl = Getattr(n, "decl"); + SwigType *type = Getattr(n, "type"); + String *ty = NewString(type); + SwigType_push(ty, decl); + if (SwigType_isqualifier(ty)) + Delete(SwigType_pop(ty)); + Delete(SwigType_pop_function(ty)); + if (resolve) { + String *unresolved = ty; + ty = SwigType_typedef_resolve_all(unresolved); + Delete(unresolved); + } + return ty; + } + + /* Checks if a class member is the same as inherited from the class bases */ + int class_member_is_defined_in_bases(Node *member, Node *classnode) { + Node *bases; /* bases is the closest ancestors of classnode */ + int defined = 0; + + bases = Getattr(classnode, "allbases"); + if (!bases) + return 0; + + { + int old_mode = virtual_elimination_mode; + if (is_member_director(classnode, member)) + virtual_elimination_mode = 0; + + if (function_is_defined_in_bases(member, bases)) { + defined = 1; + } + + virtual_elimination_mode = old_mode; + } + + if (defined) + return 1; + else + return 0; + } + + /* Checks to see if a class is abstract through inheritance, + and saves the first node that seems to be abstract. + */ + int is_abstract_inherit(Node *n, Node *base = 0, int first = 0) { + if (!first && (base == n)) + return 0; + if (!base) { + /* Root node */ + Symtab *stab = Getattr(n, "symtab"); /* Get symbol table for node */ + Symtab *oldtab = Swig_symbol_setscope(stab); + int ret = is_abstract_inherit(n, n, 1); + Swig_symbol_setscope(oldtab); + return ret; + } + List *abstracts = Getattr(base, "abstracts"); + if (abstracts) { + int dabstract = 0; + int len = Len(abstracts); + for (int i = 0; i < len; i++) { + Node *nn = Getitem(abstracts, i); + String *name = Getattr(nn, "name"); + if (!name) + continue; + if (Strchr(name, '~')) + continue; /* Don't care about destructors */ + String *base_decl = Getattr(nn, "decl"); + if (base_decl) + base_decl = SwigType_typedef_resolve_all(base_decl); + if (SwigType_isfunction(base_decl)) + search_decl = SwigType_pop_function(base_decl); + Node *dn = Swig_symbol_clookup_local_check(name, 0, check_implemented); + Delete(search_decl); + Delete(base_decl); + + if (!dn) { + List *nabstracts = Getattr(n, "abstracts"); + if (!nabstracts) { + nabstracts = NewList(); + Setattr(n, "abstracts", nabstracts); + Delete(nabstracts); + } + Append(nabstracts, nn); + if (!Getattr(n, "abstracts:firstnode")) { + Setattr(n, "abstracts:firstnode", nn); + } + dabstract = base != n; + } + } + if (dabstract) + return 1; + } + List *bases = Getattr(base, "allbases"); + if (!bases) + return 0; + for (int i = 0; i < Len(bases); i++) { + if (is_abstract_inherit(n, Getitem(bases, i))) { + return 1; + } + } + return 0; + } + + + /* Grab methods used by smart pointers */ + + List *smart_pointer_methods(Node *cls, List *methods, int isconst, String *classname = 0) { + if (!methods) { + methods = NewList(); + } + + Node *c = firstChild(cls); + + while (c) { + if (Getattr(c, "error") || GetFlag(c, "feature:ignore")) { + c = nextSibling(c); + continue; + } + if (!isconst && (Strcmp(nodeType(c), "extend") == 0)) { + methods = smart_pointer_methods(c, methods, isconst, Getattr(cls, "name")); + } else if (Strcmp(nodeType(c), "cdecl") == 0) { + if (!GetFlag(c, "feature:ignore")) { + String *storage = Getattr(c, "storage"); + if (!((Cmp(storage, "typedef") == 0)) + && !((Cmp(storage, "friend") == 0))) { + String *name = Getattr(c, "name"); + String *symname = Getattr(c, "sym:name"); + Node *e = Swig_symbol_clookup_local(name, 0); + if (e && is_public(e) && !GetFlag(e, "feature:ignore") && (Cmp(symname, Getattr(e, "sym:name")) == 0)) { + Swig_warning(WARN_LANG_DEREF_SHADOW, Getfile(e), Getline(e), "Declaration of '%s' shadows declaration accessible via operator->(),\n", name); + Swig_warning(WARN_LANG_DEREF_SHADOW, Getfile(c), Getline(c), "previous declaration of '%s'.\n", name); + } else { + /* Make sure node with same name doesn't already exist */ + int k; + int match = 0; + for (k = 0; k < Len(methods); k++) { + e = Getitem(methods, k); + if (Cmp(symname, Getattr(e, "sym:name")) == 0) { + match = 1; + break; + } + if (!Getattr(e, "sym:name") && (Cmp(name, Getattr(e, "name")) == 0)) { + match = 1; + break; + } + } + if (!match) { + Node *cc = c; + while (cc) { + Node *cp = cc; + if (classname) { + Setattr(cp, "extendsmartclassname", classname); + } + Setattr(cp, "allocate:smartpointeraccess", "1"); + /* If constant, we have to be careful */ + if (isconst) { + SwigType *decl = Getattr(cp, "decl"); + if (decl) { + if (SwigType_isfunction(decl)) { /* If method, we only add if it's a const method */ + if (SwigType_isconst(decl)) { + Append(methods, cp); + } + } else { + Append(methods, cp); + } + } else { + Append(methods, cp); + } + } else { + Append(methods, cp); + } + cc = Getattr(cc, "sym:nextSibling"); + } + } + } + } + } + } + + c = nextSibling(c); + } + /* Look for methods in base classes */ + { + Node *bases = Getattr(cls, "bases"); + int k; + for (k = 0; k < Len(bases); k++) { + smart_pointer_methods(Getitem(bases, k), methods, isconst); + } + } + /* Remove protected/private members */ + { + for (int i = 0; i < Len(methods);) { + Node *n = Getitem(methods, i); + if (!is_public(n)) { + Delitem(methods, i); + continue; + } + i++; + } + } + return methods; + } + + void mark_exception_classes(ParmList *p) { + while (p) { + SwigType *ty = Getattr(p, "type"); + SwigType *t = SwigType_typedef_resolve_all(ty); + if (SwigType_isreference(t) || SwigType_ispointer(t) || SwigType_isarray(t)) { + Delete(SwigType_pop(t)); + } + Node *c = Swig_symbol_clookup(t, 0); + if (c) { + if (!GetFlag(c, "feature:exceptionclass")) { + SetFlag(c, "feature:exceptionclass"); + } + } + p = nextSibling(p); + Delete(t); + } + } + + + void process_exceptions(Node *n) { + ParmList *catchlist = 0; + /* + the "catchlist" attribute is used to emit the block + + try {$action;} + catch <list of catches>; + + in emit.cxx + + and is either constructed from the "feature:catches" feature + or copied from the node "throws" list. + */ + String *scatchlist = Getattr(n, "feature:catches"); + if (scatchlist) { + catchlist = Swig_cparse_parms(scatchlist, n); + if (catchlist) { + Setattr(n, "catchlist", catchlist); + mark_exception_classes(catchlist); + Delete(catchlist); + } + } + ParmList *throws = Getattr(n, "throws"); + if (throws) { + /* if there is no explicit catchlist, we catch everything in the throws list */ + if (!catchlist) { + Setattr(n, "catchlist", throws); + } + mark_exception_classes(throws); + } + } + +public: +Allocate(): + inclass(NULL), extendmode(0) { + } + + virtual int top(Node *n) { + cplus_mode = PUBLIC; + inclass = 0; + extendmode = 0; + emit_children(n); + return SWIG_OK; + } + + virtual int importDirective(Node *n) { + return emit_children(n); + } + virtual int includeDirective(Node *n) { + return emit_children(n); + } + virtual int externDeclaration(Node *n) { + return emit_children(n); + } + virtual int namespaceDeclaration(Node *n) { + return emit_children(n); + } + virtual int extendDirective(Node *n) { + extendmode = 1; + emit_children(n); + extendmode = 0; + return SWIG_OK; + } + + virtual int classDeclaration(Node *n) { + Symtab *symtab = Swig_symbol_current(); + Swig_symbol_setscope(Getattr(n, "symtab")); + save_value<Node*> oldInclass(inclass); + save_value<AccessMode> oldAcessMode(cplus_mode); + save_value<int> oldExtendMode(extendmode); + if (Getattr(n, "template")) + extendmode = 0; + if (!CPlusPlus) { + /* Always have default constructors/destructors in C */ + Setattr(n, "allocate:default_constructor", "1"); + Setattr(n, "allocate:default_destructor", "1"); + } + + if (Getattr(n, "allocate:visit")) + return SWIG_OK; + Setattr(n, "allocate:visit", "1"); + + /* Always visit base classes first */ + { + List *bases = Getattr(n, "bases"); + if (bases) { + for (int i = 0; i < Len(bases); i++) { + Node *b = Getitem(bases, i); + classDeclaration(b); + } + } + } + inclass = n; + String *kind = Getattr(n, "kind"); + if (Strcmp(kind, "class") == 0) { + cplus_mode = PRIVATE; + } else { + cplus_mode = PUBLIC; + } + + emit_children(n); + + /* Check if the class is abstract via inheritance. This might occur if a class didn't have + any pure virtual methods of its own, but it didn't implement all of the pure methods in + a base class */ + if (!Getattr(n, "abstracts") && is_abstract_inherit(n)) { + if (((Getattr(n, "allocate:public_constructor") || (!GetFlag(n, "feature:nodefault") && !Getattr(n, "allocate:has_constructor"))))) { + if (!GetFlag(n, "feature:notabstract")) { + Node *na = Getattr(n, "abstracts:firstnode"); + if (na) { + Swig_warning(WARN_TYPE_ABSTRACT, Getfile(n), Getline(n), + "Class '%s' might be abstract, " "no constructors generated,\n", SwigType_namestr(Getattr(n, "name"))); + Swig_warning(WARN_TYPE_ABSTRACT, Getfile(na), Getline(na), "Method %s might not be implemented.\n", Swig_name_decl(na)); + if (!Getattr(n, "abstracts")) { + List *abstracts = NewList(); + Append(abstracts, na); + Setattr(n, "abstracts", abstracts); + Delete(abstracts); + } + } + } + } + } + + if (!Getattr(n, "allocate:has_constructor")) { + /* No constructor is defined. We need to check a few things */ + /* If class is abstract. No default constructor. Sorry */ + if (Getattr(n, "abstracts")) { + Delattr(n, "allocate:default_constructor"); + } + if (!Getattr(n, "allocate:default_constructor")) { + /* Check base classes */ + List *bases = Getattr(n, "allbases"); + int allows_default = 1; + + for (int i = 0; i < Len(bases); i++) { + Node *n = Getitem(bases, i); + /* If base class does not allow default constructor, we don't allow it either */ + if (!Getattr(n, "allocate:default_constructor") && (!Getattr(n, "allocate:default_base_constructor"))) { + allows_default = 0; + } + } + if (allows_default) { + Setattr(n, "allocate:default_constructor", "1"); + } + } + } + if (!Getattr(n, "allocate:has_copy_constructor")) { + if (Getattr(n, "abstracts")) { + Delattr(n, "allocate:copy_constructor"); + } + if (!Getattr(n, "allocate:copy_constructor")) { + /* Check base classes */ + List *bases = Getattr(n, "allbases"); + int allows_copy = 1; + + for (int i = 0; i < Len(bases); i++) { + Node *n = Getitem(bases, i); + /* If base class does not allow copy constructor, we don't allow it either */ + if (!Getattr(n, "allocate:copy_constructor") && (!Getattr(n, "allocate:copy_base_constructor"))) { + allows_copy = 0; + } + } + if (allows_copy) { + Setattr(n, "allocate:copy_constructor", "1"); + } + } + } + + if (!Getattr(n, "allocate:has_destructor")) { + /* No destructor was defined */ + List *bases = Getattr(n, "allbases"); + int allows_destruct = 1; + + for (int i = 0; i < Len(bases); i++) { + Node *n = Getitem(bases, i); + /* If base class does not allow default destructor, we don't allow it either */ + if (!Getattr(n, "allocate:default_destructor") && (!Getattr(n, "allocate:default_base_destructor"))) { + allows_destruct = 0; + } + } + if (allows_destruct) { + Setattr(n, "allocate:default_destructor", "1"); + } + } + + if (!Getattr(n, "allocate:has_assign")) { + /* No assignment operator was defined */ + List *bases = Getattr(n, "allbases"); + int allows_assign = 1; + + for (int i = 0; i < Len(bases); i++) { + Node *n = Getitem(bases, i); + /* If base class does not allow assignment, we don't allow it either */ + if (Getattr(n, "allocate:has_assign")) { + allows_assign = !Getattr(n, "allocate:noassign"); + } + } + if (!allows_assign) { + Setattr(n, "allocate:noassign", "1"); + } + } + + if (!Getattr(n, "allocate:has_new")) { + /* No new operator was defined */ + List *bases = Getattr(n, "allbases"); + int allows_new = 1; + + for (int i = 0; i < Len(bases); i++) { + Node *n = Getitem(bases, i); + /* If base class does not allow new operator, we don't allow it either */ + if (Getattr(n, "allocate:has_new")) { + allows_new = !Getattr(n, "allocate:nonew"); + } + } + if (!allows_new) { + Setattr(n, "allocate:nonew", "1"); + } + } + + /* Check if base classes allow smart pointers, but might be hidden */ + if (!Getattr(n, "allocate:smartpointer")) { + Node *sp = Swig_symbol_clookup("operator ->", 0); + if (sp) { + /* Look for parent */ + Node *p = parentNode(sp); + if (Strcmp(nodeType(p), "extend") == 0) { + p = parentNode(p); + } + if (Strcmp(nodeType(p), "class") == 0) { + if (GetFlag(p, "feature:ignore")) { + Setattr(n, "allocate:smartpointer", Getattr(p, "allocate:smartpointer")); + } + } + } + } + + Swig_interface_propagate_methods(n); + + /* Only care about default behavior. Remove temporary values */ + Setattr(n, "allocate:visit", "1"); + Swig_symbol_setscope(symtab); + return SWIG_OK; + } + + virtual int accessDeclaration(Node *n) { + String *kind = Getattr(n, "kind"); + if (Cmp(kind, "public") == 0) { + cplus_mode = PUBLIC; + } else if (Cmp(kind, "private") == 0) { + cplus_mode = PRIVATE; + } else if (Cmp(kind, "protected") == 0) { + cplus_mode = PROTECTED; + } + return SWIG_OK; + } + + virtual int usingDeclaration(Node *n) { + + Node *c = 0; + for (c = firstChild(n); c; c = nextSibling(c)) { + if (Strcmp(nodeType(c), "cdecl") == 0) { + process_exceptions(c); + + if (inclass) + class_member_is_defined_in_bases(c, inclass); + } + } + + return SWIG_OK; + } + + virtual int cDeclaration(Node *n) { + + process_exceptions(n); + + if (inclass) { + /* check whether the member node n is defined in class node in class's bases */ + class_member_is_defined_in_bases(n, inclass); + + /* Check to see if this is a static member or not. If so, we add an attribute + cplus:staticbase that saves the current class */ + + if (Swig_storage_isstatic(n)) { + Setattr(n, "cplus:staticbase", inclass); + } else if (Cmp(Getattr(n, "kind"), "variable") == 0) { + /* Check member variable to determine whether assignment is valid */ + if (SwigType_isreference(Getattr(n, "type"))) { + /* Can't assign a class with reference member data */ + Setattr(inclass, "allocate:noassign", "1"); + } + } + + String *name = Getattr(n, "name"); + if (cplus_mode != PUBLIC) { + if (Strcmp(name, "operator =") == 0) { + /* Look for a private assignment operator */ + if (!GetFlag(n, "deleted")) + Setattr(inclass, "allocate:has_assign", "1"); + Setattr(inclass, "allocate:noassign", "1"); + } else if (Strcmp(name, "operator new") == 0) { + /* Look for a private new operator */ + if (!GetFlag(n, "deleted")) + Setattr(inclass, "allocate:has_new", "1"); + Setattr(inclass, "allocate:nonew", "1"); + } + } else { + if (Strcmp(name, "operator =") == 0) { + if (!GetFlag(n, "deleted")) + Setattr(inclass, "allocate:has_assign", "1"); + else + Setattr(inclass, "allocate:noassign", "1"); + } else if (Strcmp(name, "operator new") == 0) { + if (!GetFlag(n, "deleted")) + Setattr(inclass, "allocate:has_new", "1"); + else + Setattr(inclass, "allocate:nonew", "1"); + } + /* Look for smart pointer operator */ + if ((Strcmp(name, "operator ->") == 0) && (!GetFlag(n, "feature:ignore"))) { + /* Look for version with no parameters */ + Node *sn = n; + while (sn) { + if (!Getattr(sn, "parms")) { + SwigType *type = SwigType_typedef_resolve_all(Getattr(sn, "type")); + SwigType_push(type, Getattr(sn, "decl")); + Delete(SwigType_pop_function(type)); + SwigType *base = SwigType_base(type); + Node *sc = Swig_symbol_clookup(base, 0); + if ((sc) && (Strcmp(nodeType(sc), "class") == 0)) { + if (SwigType_check_decl(type, "p.")) { + /* Need to check if type is a const pointer */ + int isconst = 0; + Delete(SwigType_pop(type)); + if (SwigType_isconst(type)) { + isconst = !Getattr(inclass, "allocate:smartpointermutable"); + Setattr(inclass, "allocate:smartpointerconst", "1"); + } + else { + Setattr(inclass, "allocate:smartpointermutable", "1"); + } + List *methods = smart_pointer_methods(sc, 0, isconst); + Setattr(inclass, "allocate:smartpointer", methods); + Setattr(inclass, "allocate:smartpointerpointeeclassname", Getattr(sc, "name")); + } else { + /* Hmmm. The return value is not a pointer. If the type is a value + or reference. We're going to chase it to see if another operator->() + can be found */ + if ((SwigType_check_decl(type, "")) || (SwigType_check_decl(type, "r."))) { + Node *nn = Swig_symbol_clookup("operator ->", Getattr(sc, "symtab")); + if (nn) { + Delete(base); + Delete(type); + sn = nn; + continue; + } + } + } + } + Delete(base); + Delete(type); + break; + } + } + } + } + } + return SWIG_OK; + } + + virtual int constructorDeclaration(Node *n) { + if (!inclass) + return SWIG_OK; + Parm *parms = Getattr(n, "parms"); + + process_exceptions(n); + if (!extendmode) { + if (!ParmList_numrequired(parms)) { + /* Class does define a default constructor */ + /* However, we had better see where it is defined */ + if (cplus_mode == PUBLIC) { + Setattr(inclass, "allocate:default_constructor", "1"); + } else if (cplus_mode == PROTECTED) { + Setattr(inclass, "allocate:default_base_constructor", "1"); + } + } + /* Class defines some kind of constructor. May or may not be public */ + Setattr(inclass, "allocate:has_constructor", "1"); + if (cplus_mode == PUBLIC) { + Setattr(inclass, "allocate:public_constructor", "1"); + } + } else { + Setattr(inclass, "allocate:has_constructor", "1"); + Setattr(inclass, "allocate:public_constructor", "1"); + } + + + /* See if this is a copy constructor */ + if (parms && (ParmList_numrequired(parms) == 1)) { + /* Look for a few cases. X(const X &), X(X &), X(X *) */ + int copy_constructor = 0; + SwigType *type = Getattr(inclass, "name"); + String *tn = NewStringf("r.q(const).%s", type); + String *cc = SwigType_typedef_resolve_all(tn); + SwigType *rt = SwigType_typedef_resolve_all(Getattr(parms, "type")); + if (SwigType_istemplate(type)) { + String *tmp = Swig_symbol_template_deftype(cc, 0); + Delete(cc); + cc = tmp; + tmp = Swig_symbol_template_deftype(rt, 0); + Delete(rt); + rt = tmp; + } + if (Strcmp(cc, rt) == 0) { + copy_constructor = 1; + } else { + Delete(cc); + cc = NewStringf("r.%s", Getattr(inclass, "name")); + if (Strcmp(cc, Getattr(parms, "type")) == 0) { + copy_constructor = 1; + } else { + Delete(cc); + cc = NewStringf("p.%s", Getattr(inclass, "name")); + String *ty = SwigType_strip_qualifiers(Getattr(parms, "type")); + if (Strcmp(cc, ty) == 0) { + copy_constructor = 1; + } + Delete(ty); + } + } + Delete(cc); + Delete(rt); + Delete(tn); + + if (copy_constructor) { + Setattr(n, "copy_constructor", "1"); + Setattr(inclass, "allocate:has_copy_constructor", "1"); + if (cplus_mode == PUBLIC) { + Setattr(inclass, "allocate:copy_constructor", "1"); + } else if (cplus_mode == PROTECTED) { + Setattr(inclass, "allocate:copy_base_constructor", "1"); + } + } + } + return SWIG_OK; + } + + virtual int destructorDeclaration(Node *n) { + (void) n; + if (!inclass) + return SWIG_OK; + if (!extendmode) { + Setattr(inclass, "allocate:has_destructor", "1"); + if (cplus_mode == PUBLIC) { + Setattr(inclass, "allocate:default_destructor", "1"); + } else if (cplus_mode == PROTECTED) { + Setattr(inclass, "allocate:default_base_destructor", "1"); + } else if (cplus_mode == PRIVATE) { + Setattr(inclass, "allocate:private_destructor", "1"); + } + } else { + Setattr(inclass, "allocate:has_destructor", "1"); + Setattr(inclass, "allocate:default_destructor", "1"); + } + return SWIG_OK; + } +}; + +void Swig_default_allocators(Node *n) { + if (!n) + return; + Allocate *a = new Allocate; + a->top(n); + delete a; +} |