1 /* -----------------------------------------------------------------------------
2 * See the LICENSE file for information on copyright, usage and redistribution
3 * of SWIG, and the README file for authors - http://www.swig.org/release.html.
7 * This module tries to figure out which classes and structures support
8 * default constructors and destructors in C++. There are several rules that
9 * define this behavior including pure abstract methods, private sections,
10 * and non-default constructors in base classes. See the ARM or
11 * Doc/Manual/SWIGPlus.html for details.
12 * ----------------------------------------------------------------------------- */
14 char cvsroot_allocate_cxx[] = "$Id: allocate.cxx 11583 2009-08-15 23:22:20Z wsfulton $";
19 static int virtual_elimination_mode = 0; /* set to 0 on default */
21 /* Set virtual_elimination_mode */
22 void Wrapper_virtual_elimination_mode_set(int flag) {
23 virtual_elimination_mode = flag;
26 /* Helper function to assist with abstract class checking.
27 This is a major hack. Sorry. */
30 static String *search_decl = 0; /* Declarator being searched */
31 static int check_implemented(Node *n) {
36 if (Strcmp(nodeType(n), "cdecl") == 0) {
37 decl = Getattr(n, "decl");
38 if (SwigType_isfunction(decl)) {
39 SwigType *decl1 = SwigType_typedef_resolve_all(decl);
40 SwigType *decl2 = SwigType_pop_function(decl1);
41 if (Strcmp(decl2, search_decl) == 0) {
42 if (!Getattr(n, "abstract")) {
52 n = Getattr(n, "csym:nextSibling");
58 class Allocate:public Dispatcher {
62 /* Checks if a function, n, is the same as any in the base class, ie if the method is polymorphic.
63 * Also checks for methods which will be hidden (ie a base has an identical non-virtual method).
64 * Both methods must have public access for a match to occur. */
65 int function_is_defined_in_bases(Node *n, Node *bases) {
70 String *this_decl = Getattr(n, "decl");
74 String *name = Getattr(n, "name");
75 String *this_type = Getattr(n, "type");
76 String *resolved_decl = SwigType_typedef_resolve_all(this_decl);
78 // Search all base classes for methods with same signature
79 for (int i = 0; i < Len(bases); i++) {
80 Node *b = Getitem(bases, i);
81 Node *base = firstChild(b);
83 if (Strcmp(nodeType(base), "extend") == 0) {
84 // Loop through all the %extend methods
85 Node *extend = firstChild(base);
87 if (function_is_defined_in_bases_seek(n, b, extend, this_decl, name, this_type, resolved_decl)) {
88 Delete(resolved_decl);
91 extend = nextSibling(extend);
93 } else if (Strcmp(nodeType(base), "using") == 0) {
94 // Loop through all the using declaration methods
95 Node *usingdecl = firstChild(base);
97 if (function_is_defined_in_bases_seek(n, b, usingdecl, this_decl, name, this_type, resolved_decl)) {
98 Delete(resolved_decl);
101 usingdecl = nextSibling(usingdecl);
105 if (function_is_defined_in_bases_seek(n, b, base, this_decl, name, this_type, resolved_decl)) {
106 Delete(resolved_decl);
110 base = nextSibling(base);
113 Delete(resolved_decl);
115 for (int j = 0; j < Len(bases); j++) {
116 Node *b = Getitem(bases, j);
117 if (function_is_defined_in_bases(n, Getattr(b, "allbases")))
123 /* Helper function for function_is_defined_in_bases */
124 int function_is_defined_in_bases_seek(Node *n, Node *b, Node *base, String *this_decl, String *name, String *this_type, String *resolved_decl) {
126 String *base_decl = Getattr(base, "decl");
127 SwigType *base_type = Getattr(base, "type");
128 if (base_decl && base_type) {
129 if (checkAttribute(base, "name", name) && !GetFlag(b, "feature:ignore") /* whole class is ignored */ ) {
130 if (SwigType_isfunction(resolved_decl) && SwigType_isfunction(base_decl)) {
131 // We have found a method that has the same name as one in a base class
132 bool covariant_returntype = false;
133 bool returntype_match = Strcmp(base_type, this_type) == 0 ? true : false;
134 bool decl_match = Strcmp(base_decl, this_decl) == 0 ? true : false;
135 if (returntype_match && decl_match) {
136 // Exact match - we have found a method with identical signature
137 // No typedef resolution was done, but skipping it speeds things up slightly
140 // 1) matching methods but are one of them uses a different typedef (return type or parameter) to the one in base class' method
141 // 2) matching polymorphic methods with covariant return type
142 // 3) a non-matching method (ie an overloaded method of some sort)
143 // 4) a matching method which is not polymorphic, ie it hides the base class' method
145 // Check if fully resolved return types match (including
146 // covariant return types)
147 if (!returntype_match) {
148 String *this_returntype = function_return_type(n);
149 String *base_returntype = function_return_type(base);
150 returntype_match = Strcmp(this_returntype, base_returntype) == 0 ? true : false;
151 if (!returntype_match) {
152 covariant_returntype = SwigType_issubtype(this_returntype, base_returntype) ? true : false;
153 returntype_match = covariant_returntype;
155 Delete(this_returntype);
156 Delete(base_returntype);
158 // The return types must match at this point, for the whole method to match
159 if (returntype_match && !decl_match) {
160 // Now need to check the parameter list
161 // First do an inexpensive parameter count
162 ParmList *this_parms = Getattr(n, "parms");
163 ParmList *base_parms = Getattr(base, "parms");
164 if (ParmList_len(this_parms) == ParmList_len(base_parms)) {
165 // Number of parameters are the same, now check that all the parameters match
166 SwigType *base_fn = NewString("");
167 SwigType *this_fn = NewString("");
168 SwigType_add_function(base_fn, base_parms);
169 SwigType_add_function(this_fn, this_parms);
170 base_fn = SwigType_typedef_resolve_all(base_fn);
171 this_fn = SwigType_typedef_resolve_all(this_fn);
172 if (Strcmp(base_fn, this_fn) == 0) {
173 // Finally check that the qualifiers match
174 int base_qualifier = SwigType_isqualifier(resolved_decl);
175 int this_qualifier = SwigType_isqualifier(base_decl);
176 if (base_qualifier == this_qualifier) {
185 //Printf(stderr,"look %s %s %d %d\n",base_decl, this_decl, returntype_match, decl_match);
187 if (decl_match && returntype_match) {
188 // Found an identical method in the base class
189 bool this_wrapping_protected_members = is_member_director(n) ? true : false; // This should really check for dirprot rather than just being a director method
190 bool base_wrapping_protected_members = is_member_director(base) ? true : false; // This should really check for dirprot rather than just being a director method
191 bool both_have_public_access = is_public(n) && is_public(base);
192 bool both_have_protected_access = (is_protected(n) && this_wrapping_protected_members) && (is_protected(base) && base_wrapping_protected_members);
193 bool both_have_private_access = is_private(n) && is_private(base);
194 if (checkAttribute(base, "storage", "virtual")) {
195 // Found a polymorphic method.
196 // Mark the polymorphic method, in case the virtual keyword was not used.
197 Setattr(n, "storage", "virtual");
199 if (both_have_public_access || both_have_protected_access) {
200 if (!is_non_public_base(inclass, b))
201 Setattr(n, "override", base); // Note C# definition of override, ie access must be the same
202 } else if (!both_have_private_access) {
204 if (this_wrapping_protected_members || base_wrapping_protected_members)
205 if (!is_non_public_base(inclass, b))
206 Setattr(n, "hides", base); // Note C# definition of hiding, ie hidden if access is different
208 // Try and find the most base's covariant return type
209 SwigType *most_base_covariant_type = Getattr(base, "covariant");
210 if (!most_base_covariant_type && covariant_returntype)
211 most_base_covariant_type = function_return_type(base, false);
213 if (!most_base_covariant_type) {
214 // Eliminate the derived virtual method.
215 if (virtual_elimination_mode)
216 if (both_have_public_access)
217 if (!is_non_public_base(inclass, b))
218 if (!Swig_symbol_isoverloaded(n)) {
219 // Don't eliminate if an overloaded method as this hides the method
220 // in the scripting languages: the dispatch function will hide the base method if ignored.
221 SetFlag(n, "feature:ignore");
224 // Some languages need to know about covariant return types
225 Setattr(n, "covariant", most_base_covariant_type);
229 // Found an identical method in the base class, but it is not polymorphic.
230 if (both_have_public_access || both_have_protected_access)
231 if (!is_non_public_base(inclass, b))
232 Setattr(n, "hides", base);
234 if (both_have_public_access || both_have_protected_access)
243 /* Determines whether the base class, b, is in the list of private
244 * or protected base classes for class n. */
245 bool is_non_public_base(Node *n, Node *b) {
246 bool non_public_base = false;
247 Node *bases = Getattr(n, "privatebases");
249 for (int i = 0; i < Len(bases); i++) {
250 Node *base = Getitem(bases, i);
252 non_public_base = true;
255 bases = Getattr(n, "protectedbases");
257 for (int i = 0; i < Len(bases); i++) {
258 Node *base = Getitem(bases, i);
260 non_public_base = true;
263 return non_public_base;
266 /* Returns the return type for a function. The node n should be a function.
267 If resolve is true the fully returned type is fully resolved.
268 Caller is responsible for deleting returned string. */
269 String *function_return_type(Node *n, bool resolve = true) {
270 String *decl = Getattr(n, "decl");
271 SwigType *type = Getattr(n, "type");
272 String *ty = NewString(type);
273 SwigType_push(ty, decl);
274 if (SwigType_isqualifier(ty))
275 Delete(SwigType_pop(ty));
276 Delete(SwigType_pop_function(ty));
278 String *unresolved = ty;
279 ty = SwigType_typedef_resolve_all(unresolved);
285 /* Checks if a class member is the same as inherited from the class bases */
286 int class_member_is_defined_in_bases(Node *member, Node *classnode) {
287 Node *bases; /* bases is the closest ancestors of classnode */
290 bases = Getattr(classnode, "allbases");
295 int old_mode = virtual_elimination_mode;
296 if (is_member_director(classnode, member))
297 virtual_elimination_mode = 0;
299 if (function_is_defined_in_bases(member, bases)) {
303 virtual_elimination_mode = old_mode;
312 /* Checks to see if a class is abstract through inheritance,
313 and saves the first node that seems to be abstract.
315 int is_abstract_inherit(Node *n, Node *base = 0, int first = 0) {
316 if (!first && (base == n))
320 Symtab *stab = Getattr(n, "symtab"); /* Get symbol table for node */
321 Symtab *oldtab = Swig_symbol_setscope(stab);
322 int ret = is_abstract_inherit(n, n, 1);
323 Swig_symbol_setscope(oldtab);
326 List *abstract = Getattr(base, "abstract");
329 int len = Len(abstract);
330 for (int i = 0; i < len; i++) {
331 Node *nn = Getitem(abstract, i);
332 String *name = Getattr(nn, "name");
335 String *base_decl = Getattr(nn, "decl");
337 base_decl = SwigType_typedef_resolve_all(base_decl);
338 if (Strchr(name, '~'))
339 continue; /* Don't care about destructors */
341 if (SwigType_isfunction(base_decl)) {
342 search_decl = SwigType_pop_function(base_decl);
344 Node *dn = Swig_symbol_clookup_local_check(name, 0, check_implemented);
349 List *nabstract = Getattr(n, "abstract");
351 nabstract = NewList();
352 Setattr(n, "abstract", nabstract);
355 Append(nabstract, nn);
356 if (!Getattr(n, "abstract:firstnode")) {
357 Setattr(n, "abstract:firstnode", nn);
359 dabstract = base != n;
365 List *bases = Getattr(base, "allbases");
368 for (int i = 0; i < Len(bases); i++) {
369 if (is_abstract_inherit(n, Getitem(bases, i))) {
377 /* Grab methods used by smart pointers */
379 List *smart_pointer_methods(Node *cls, List *methods, int isconst, String *classname = 0) {
384 Node *c = firstChild(cls);
385 String *kind = Getattr(cls, "kind");
387 if (kind && (Strcmp(kind, "class") == 0))
391 if (Getattr(c, "error") || GetFlag(c, "feature:ignore")) {
395 if (!isconst && (Strcmp(nodeType(c), "extend") == 0)) {
396 methods = smart_pointer_methods(c, methods, isconst, Getattr(cls, "name"));
397 } else if (Strcmp(nodeType(c), "cdecl") == 0) {
398 if (!GetFlag(c, "feature:ignore")) {
399 String *storage = Getattr(c, "storage");
400 if (!((Cmp(storage, "typedef") == 0))
401 && !((Cmp(storage, "friend") == 0))) {
402 String *name = Getattr(c, "name");
403 String *symname = Getattr(c, "sym:name");
404 Node *e = Swig_symbol_clookup_local(name, 0);
405 if (e && is_public(e) && !GetFlag(e, "feature:ignore") && (Cmp(symname, Getattr(e, "sym:name")) == 0)) {
406 Swig_warning(WARN_LANG_DEREF_SHADOW, Getfile(e), Getline(e), "Declaration of '%s' shadows declaration accessible via operator->(),\n", name);
407 Swig_warning(WARN_LANG_DEREF_SHADOW, Getfile(c), Getline(c), "previous declaration of '%s'.\n", name);
409 /* Make sure node with same name doesn't already exist */
412 for (k = 0; k < Len(methods); k++) {
413 e = Getitem(methods, k);
414 if (Cmp(symname, Getattr(e, "sym:name")) == 0) {
418 if ((!symname || (!Getattr(e, "sym:name"))) && (Cmp(name, Getattr(e, "name")) == 0)) {
428 Setattr(cp, "classname", classname);
430 Setattr(cp, "allocate:smartpointeraccess", "1");
431 /* If constant, we have to be careful */
433 SwigType *decl = Getattr(cp, "decl");
435 if (SwigType_isfunction(decl)) { /* If method, we only add if it's a const method */
436 if (SwigType_isconst(decl)) {
448 cc = Getattr(cc, "sym:nextSibling");
456 if (Strcmp(nodeType(c), "access") == 0) {
457 kind = Getattr(c, "kind");
458 if (Strcmp(kind, "public") == 0)
465 /* Look for methods in base classes */
467 Node *bases = Getattr(cls, "bases");
469 for (k = 0; k < Len(bases); k++) {
470 smart_pointer_methods(Getitem(bases, k), methods, isconst);
473 /* Remove protected/private members */
475 for (int i = 0; i < Len(methods);) {
476 Node *n = Getitem(methods, i);
487 void mark_exception_classes(ParmList *p) {
489 SwigType *ty = Getattr(p, "type");
490 SwigType *t = SwigType_typedef_resolve_all(ty);
491 if (SwigType_isreference(t) || SwigType_ispointer(t) || SwigType_isarray(t)) {
492 Delete(SwigType_pop(t));
494 Node *c = Swig_symbol_clookup(t, 0);
496 if (!GetFlag(c, "feature:exceptionclass")) {
497 SetFlag(c, "feature:exceptionclass");
506 void process_exceptions(Node *n) {
507 ParmList *catchlist = 0;
509 the "catchlist" attribute is used to emit the block
512 catch <list of catches>;
516 and is either constructued from the "feature:catches" feature
517 or copied from the node "throws" list.
519 String *scatchlist = Getattr(n, "feature:catches");
521 catchlist = Swig_cparse_parms(scatchlist);
523 Setattr(n, "catchlist", catchlist);
524 mark_exception_classes(catchlist);
528 ParmList *throws = Getattr(n, "throws");
530 /* if there is no explicit catchlist, we catch everything in the throws list */
532 Setattr(n, "catchlist", throws);
534 mark_exception_classes(throws);
540 inclass(NULL), extendmode(0) {
543 virtual int top(Node *n) {
551 virtual int importDirective(Node *n) {
552 return emit_children(n);
554 virtual int includeDirective(Node *n) {
555 return emit_children(n);
557 virtual int externDeclaration(Node *n) {
558 return emit_children(n);
560 virtual int namespaceDeclaration(Node *n) {
561 return emit_children(n);
563 virtual int extendDirective(Node *n) {
570 virtual int classDeclaration(Node *n) {
571 Symtab *symtab = Swig_symbol_current();
572 Swig_symbol_setscope(Getattr(n, "symtab"));
575 /* Always have default constructors/destructors in C */
576 Setattr(n, "allocate:default_constructor", "1");
577 Setattr(n, "allocate:default_destructor", "1");
580 if (Getattr(n, "allocate:visit"))
582 Setattr(n, "allocate:visit", "1");
584 /* Always visit base classes first */
586 List *bases = Getattr(n, "bases");
588 for (int i = 0; i < Len(bases); i++) {
589 Node *b = Getitem(bases, i);
596 String *kind = Getattr(n, "kind");
597 if (Strcmp(kind, "class") == 0) {
598 cplus_mode = PRIVATE;
605 /* Check if the class is abstract via inheritance. This might occur if a class didn't have
606 any pure virtual methods of its own, but it didn't implement all of the pure methods in
608 if (!Getattr(n, "abstract") && is_abstract_inherit(n)) {
609 if (((Getattr(n, "allocate:public_constructor") || (!GetFlag(n, "feature:nodefault") && !Getattr(n, "allocate:has_constructor"))))) {
610 if (!GetFlag(n, "feature:notabstract")) {
611 Node *na = Getattr(n, "abstract:firstnode");
613 Swig_warning(WARN_TYPE_ABSTRACT, Getfile(n), Getline(n),
614 "Class '%s' might be abstract, " "no constructors generated,\n", SwigType_namestr(Getattr(n, "name")));
615 Swig_warning(WARN_TYPE_ABSTRACT, Getfile(na), Getline(na), "Method %s might not be implemented.\n", Swig_name_decl(na));
616 if (!Getattr(n, "abstract")) {
617 List *abstract = NewList();
618 Append(abstract, na);
619 Setattr(n, "abstract", abstract);
627 if (!Getattr(n, "allocate:has_constructor")) {
628 /* No constructor is defined. We need to check a few things */
629 /* If class is abstract. No default constructor. Sorry */
630 if (Getattr(n, "abstract")) {
631 Delattr(n, "allocate:default_constructor");
633 if (!Getattr(n, "allocate:default_constructor")) {
634 /* Check base classes */
635 List *bases = Getattr(n, "allbases");
636 int allows_default = 1;
638 for (int i = 0; i < Len(bases); i++) {
639 Node *n = Getitem(bases, i);
640 /* If base class does not allow default constructor, we don't allow it either */
641 if (!Getattr(n, "allocate:default_constructor") && (!Getattr(n, "allocate:default_base_constructor"))) {
645 if (allows_default) {
646 Setattr(n, "allocate:default_constructor", "1");
650 if (!Getattr(n, "allocate:has_copy_constructor")) {
651 if (Getattr(n, "abstract")) {
652 Delattr(n, "allocate:copy_constructor");
654 if (!Getattr(n, "allocate:copy_constructor")) {
655 /* Check base classes */
656 List *bases = Getattr(n, "allbases");
659 for (int i = 0; i < Len(bases); i++) {
660 Node *n = Getitem(bases, i);
661 /* If base class does not allow copy constructor, we don't allow it either */
662 if (!Getattr(n, "allocate:copy_constructor") && (!Getattr(n, "allocate:copy_base_constructor"))) {
667 Setattr(n, "allocate:copy_constructor", "1");
672 if (!Getattr(n, "allocate:has_destructor")) {
673 /* No destructor was defined. We need to check a few things here too */
674 List *bases = Getattr(n, "allbases");
675 int allows_destruct = 1;
677 for (int i = 0; i < Len(bases); i++) {
678 Node *n = Getitem(bases, i);
679 /* If base class does not allow default destructor, we don't allow it either */
680 if (!Getattr(n, "allocate:default_destructor") && (!Getattr(n, "allocate:default_base_destructor"))) {
684 if (allows_destruct) {
685 Setattr(n, "allocate:default_destructor", "1");
689 if (!Getattr(n, "allocate:has_assign")) {
690 /* No destructor was defined. We need to check a few things here too */
691 List *bases = Getattr(n, "allbases");
692 int allows_assign = 1;
694 for (int i = 0; i < Len(bases); i++) {
695 Node *n = Getitem(bases, i);
696 /* If base class does not allow default destructor, we don't allow it either */
697 if (Getattr(n, "allocate:has_assign")) {
698 allows_assign = !Getattr(n, "allocate:noassign");
701 if (!allows_assign) {
702 Setattr(n, "allocate:noassign", "1");
706 if (!Getattr(n, "allocate:has_new")) {
707 /* No destructor was defined. We need to check a few things here too */
708 List *bases = Getattr(n, "allbases");
711 for (int i = 0; i < Len(bases); i++) {
712 Node *n = Getitem(bases, i);
713 /* If base class does not allow default destructor, we don't allow it either */
714 if (Getattr(n, "allocate:has_new")) {
715 allows_new = !Getattr(n, "allocate:nonew");
719 Setattr(n, "allocate:nonew", "1");
723 /* Check if base classes allow smart pointers, but might be hidden */
724 if (!Getattr(n, "allocate:smartpointer")) {
725 Node *sp = Swig_symbol_clookup((char *) "operator ->", 0);
727 /* Look for parent */
728 Node *p = parentNode(sp);
729 if (Strcmp(nodeType(p), "extend") == 0) {
732 if (Strcmp(nodeType(p), "class") == 0) {
733 if (GetFlag(p, "feature:ignore")) {
734 Setattr(n, "allocate:smartpointer", Getattr(p, "allocate:smartpointer"));
740 /* Only care about default behavior. Remove temporary values */
741 Setattr(n, "allocate:visit", "1");
743 Swig_symbol_setscope(symtab);
747 virtual int accessDeclaration(Node *n) {
748 String *kind = Getattr(n, "kind");
749 if (Cmp(kind, "public") == 0) {
751 } else if (Cmp(kind, "private") == 0) {
752 cplus_mode = PRIVATE;
753 } else if (Cmp(kind, "protected") == 0) {
754 cplus_mode = PROTECTED;
759 virtual int usingDeclaration(Node *n) {
762 for (c = firstChild(n); c; c = nextSibling(c)) {
763 if (Strcmp(nodeType(c), "cdecl") == 0) {
764 process_exceptions(c);
767 class_member_is_defined_in_bases(c, inclass);
774 virtual int cDeclaration(Node *n) {
776 process_exceptions(n);
779 /* check whether the member node n is defined in class node in class's bases */
780 class_member_is_defined_in_bases(n, inclass);
782 /* Check to see if this is a static member or not. If so, we add an attribute
783 cplus:staticbase that saves the current class */
785 if (checkAttribute(n, "storage", "static")) {
786 Setattr(n, "cplus:staticbase", inclass);
789 String *name = Getattr(n, "name");
790 if (cplus_mode != PUBLIC) {
791 if (Strcmp(name, "operator =") == 0) {
792 /* Look for a private assignment operator */
793 Setattr(inclass, "allocate:has_assign", "1");
794 Setattr(inclass, "allocate:noassign", "1");
795 } else if (Strcmp(name, "operator new") == 0) {
796 /* Look for a private new operator */
797 Setattr(inclass, "allocate:has_new", "1");
798 Setattr(inclass, "allocate:nonew", "1");
801 if (Strcmp(name, "operator =") == 0) {
802 Setattr(inclass, "allocate:has_assign", "1");
803 } else if (Strcmp(name, "operator new") == 0) {
804 Setattr(inclass, "allocate:has_new", "1");
806 /* Look for smart pointer operator */
807 if ((Strcmp(name, "operator ->") == 0) && (!GetFlag(n, "feature:ignore"))) {
808 /* Look for version with no parameters */
811 if (!Getattr(sn, "parms")) {
812 SwigType *type = SwigType_typedef_resolve_all(Getattr(sn, "type"));
813 SwigType_push(type, Getattr(sn, "decl"));
814 Delete(SwigType_pop_function(type));
815 SwigType *base = SwigType_base(type);
816 Node *sc = Swig_symbol_clookup(base, 0);
817 if ((sc) && (Strcmp(nodeType(sc), "class") == 0)) {
818 if (SwigType_check_decl(type, "p.")) {
819 /* Need to check if type is a const pointer */
821 Delete(SwigType_pop(type));
822 if (SwigType_isconst(type)) {
824 Setattr(inclass, "allocate:smartpointerconst", "1");
826 List *methods = smart_pointer_methods(sc, 0, isconst);
827 Setattr(inclass, "allocate:smartpointer", methods);
828 Setattr(inclass, "allocate:smartpointerbase", base);
830 /* Hmmm. The return value is not a pointer. If the type is a value
831 or reference. We're going to chase it to see if another operator->()
834 if ((SwigType_check_decl(type, "")) || (SwigType_check_decl(type, "r."))) {
835 Node *nn = Swig_symbol_clookup((char *) "operator ->", Getattr(sc, "symtab"));
856 virtual int constructorDeclaration(Node *n) {
859 Parm *parms = Getattr(n, "parms");
861 process_exceptions(n);
863 if (!ParmList_numrequired(parms)) {
864 /* Class does define a default constructor */
865 /* However, we had better see where it is defined */
866 if (cplus_mode == PUBLIC) {
867 Setattr(inclass, "allocate:default_constructor", "1");
868 } else if (cplus_mode == PROTECTED) {
869 Setattr(inclass, "allocate:default_base_constructor", "1");
872 /* Class defines some kind of constructor. May or may not be public */
873 Setattr(inclass, "allocate:has_constructor", "1");
874 if (cplus_mode == PUBLIC) {
875 Setattr(inclass, "allocate:public_constructor", "1");
878 Setattr(inclass, "allocate:has_constructor", "1");
879 Setattr(inclass, "allocate:public_constructor", "1");
883 /* See if this is a copy constructor */
884 if (parms && (ParmList_numrequired(parms) == 1)) {
885 /* Look for a few cases. X(const X &), X(X &), X(X *) */
886 int copy_constructor = 0;
887 SwigType *type = Getattr(inclass, "name");
888 String *tn = NewStringf("r.q(const).%s", type);
889 String *cc = SwigType_typedef_resolve_all(tn);
890 SwigType *rt = SwigType_typedef_resolve_all(Getattr(parms, "type"));
891 if (SwigType_istemplate(type)) {
892 String *tmp = Swig_symbol_template_deftype(cc, 0);
895 tmp = Swig_symbol_template_deftype(rt, 0);
899 if (Strcmp(cc, rt) == 0) {
900 copy_constructor = 1;
903 cc = NewStringf("r.%s", Getattr(inclass, "name"));
904 if (Strcmp(cc, Getattr(parms, "type")) == 0) {
905 copy_constructor = 1;
908 cc = NewStringf("p.%s", Getattr(inclass, "name"));
909 String *ty = SwigType_strip_qualifiers(Getattr(parms, "type"));
910 if (Strcmp(cc, ty) == 0) {
911 copy_constructor = 1;
920 if (copy_constructor) {
921 Setattr(n, "copy_constructor", "1");
922 Setattr(inclass, "allocate:has_copy_constructor", "1");
923 if (cplus_mode == PUBLIC) {
924 Setattr(inclass, "allocate:copy_constructor", "1");
925 } else if (cplus_mode == PROTECTED) {
926 Setattr(inclass, "allocate:copy_base_constructor", "1");
933 virtual int destructorDeclaration(Node *n) {
938 Setattr(inclass, "allocate:has_destructor", "1");
939 if (cplus_mode == PUBLIC) {
940 Setattr(inclass, "allocate:default_destructor", "1");
941 } else if (cplus_mode == PROTECTED) {
942 Setattr(inclass, "allocate:default_base_destructor", "1");
949 void Swig_default_allocators(Node *n) {
952 Allocate *a = new Allocate;