/* ----------------------------------------------------------------------------- * 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)) && !Strstr(storage, "friend")) { 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 ; 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 oldInclass(inclass); save_value oldAcessMode(cplus_mode); save_value 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; }