import source from 1.3.40
[external/swig.git] / Source / Modules / allocate.cxx
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.
4  *
5  * allocate.cxx
6  *
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  * ----------------------------------------------------------------------------- */
13
14 char cvsroot_allocate_cxx[] = "$Id: allocate.cxx 11583 2009-08-15 23:22:20Z wsfulton $";
15
16 #include "swigmod.h"
17 #include "cparse.h"
18
19 static int virtual_elimination_mode = 0;        /* set to 0 on default */
20
21 /* Set virtual_elimination_mode */
22 void Wrapper_virtual_elimination_mode_set(int flag) {
23   virtual_elimination_mode = flag;
24 }
25
26 /* Helper function to assist with abstract class checking.  
27    This is a major hack. Sorry.  */
28
29 extern "C" {
30   static String *search_decl = 0;       /* Declarator being searched */
31   static int check_implemented(Node *n) {
32     String *decl;
33     if (!n)
34        return 0;
35     while (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")) {
43               Delete(decl1);
44               Delete(decl2);
45               return 1;
46             }
47           }
48           Delete(decl1);
49           Delete(decl2);
50         }
51       }
52       n = Getattr(n, "csym:nextSibling");
53     }
54     return 0;
55   }
56 }
57
58 class Allocate:public Dispatcher {
59   Node *inclass;
60   int extendmode;
61
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) {
66
67     if (!bases)
68       return 0;
69
70     String *this_decl = Getattr(n, "decl");
71     if (!this_decl)
72        return 0;
73
74     String *name = Getattr(n, "name");
75     String *this_type = Getattr(n, "type");
76     String *resolved_decl = SwigType_typedef_resolve_all(this_decl);
77
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);
82       while (base) {
83         if (Strcmp(nodeType(base), "extend") == 0) {
84           // Loop through all the %extend methods
85           Node *extend = firstChild(base);
86           while (extend) {
87             if (function_is_defined_in_bases_seek(n, b, extend, this_decl, name, this_type, resolved_decl)) {
88               Delete(resolved_decl);
89               return 1;
90             }
91             extend = nextSibling(extend);
92           }
93         } else if (Strcmp(nodeType(base), "using") == 0) {
94           // Loop through all the using declaration methods
95           Node *usingdecl = firstChild(base);
96           while (usingdecl) {
97             if (function_is_defined_in_bases_seek(n, b, usingdecl, this_decl, name, this_type, resolved_decl)) {
98               Delete(resolved_decl);
99               return 1;
100             }
101             usingdecl = nextSibling(usingdecl);
102           }
103         } else {
104           // normal methods
105           if (function_is_defined_in_bases_seek(n, b, base, this_decl, name, this_type, resolved_decl)) {
106             Delete(resolved_decl);
107             return 1;
108           }
109         }
110         base = nextSibling(base);
111       }
112     }
113     Delete(resolved_decl);
114     resolved_decl = 0;
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")))
118         return 1;
119     }
120     return 0;
121   }
122
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) {
125
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
138           } else {
139             // Either we have:
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
144
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;
154               }
155               Delete(this_returntype);
156               Delete(base_returntype);
157             }
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) {
177                     decl_match = true;
178                   }
179                 }
180                 Delete(base_fn);
181                 Delete(this_fn);
182               }
183             }
184           }
185           //Printf(stderr,"look %s %s %d %d\n",base_decl, this_decl, returntype_match, decl_match);
186
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");
198
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) {
203                 // Different 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
207               }
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);
212
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");
222                       }
223               } else {
224                 // Some languages need to know about covariant return types
225                 Setattr(n, "covariant", most_base_covariant_type);
226               }
227
228             } else {
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);
233             }
234             if (both_have_public_access || both_have_protected_access)
235               return 1;
236           }
237         }
238       }
239     }
240     return 0;
241   }
242
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");
248     if (bases) {
249       for (int i = 0; i < Len(bases); i++) {
250         Node *base = Getitem(bases, i);
251         if (base == b)
252           non_public_base = true;
253       }
254     }
255     bases = Getattr(n, "protectedbases");
256     if (bases) {
257       for (int i = 0; i < Len(bases); i++) {
258         Node *base = Getitem(bases, i);
259         if (base == b)
260           non_public_base = true;
261       }
262     }
263     return non_public_base;
264   }
265
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));
277     if (resolve) {
278       String *unresolved = ty;
279       ty = SwigType_typedef_resolve_all(unresolved);
280       Delete(unresolved);
281     }
282     return ty;
283   }
284
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 */
288     int defined = 0;
289
290     bases = Getattr(classnode, "allbases");
291     if (!bases)
292       return 0;
293
294     {
295       int old_mode = virtual_elimination_mode;
296       if (is_member_director(classnode, member))
297         virtual_elimination_mode = 0;
298
299       if (function_is_defined_in_bases(member, bases)) {
300         defined = 1;
301       }
302
303       virtual_elimination_mode = old_mode;
304     }
305
306     if (defined)
307       return 1;
308     else
309       return 0;
310   }
311
312   /* Checks to see if a class is abstract through inheritance,
313      and saves the first node that seems to be abstract.
314    */
315   int is_abstract_inherit(Node *n, Node *base = 0, int first = 0) {
316     if (!first && (base == n))
317       return 0;
318     if (!base) {
319       /* Root node */
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);
324       return ret;
325     }
326     List *abstract = Getattr(base, "abstract");
327     if (abstract) {
328       int dabstract = 0;
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");
333         if (!name)
334           continue;
335         String *base_decl = Getattr(nn, "decl");
336         if (base_decl)
337           base_decl = SwigType_typedef_resolve_all(base_decl);
338         if (Strchr(name, '~'))
339           continue;             /* Don't care about destructors */
340
341         if (SwigType_isfunction(base_decl)) {
342           search_decl = SwigType_pop_function(base_decl);
343         }
344         Node *dn = Swig_symbol_clookup_local_check(name, 0, check_implemented);
345         Delete(search_decl);
346         Delete(base_decl);
347
348         if (!dn) {
349           List *nabstract = Getattr(n, "abstract");
350           if (!nabstract) {
351             nabstract = NewList();
352             Setattr(n, "abstract", nabstract);
353             Delete(nabstract);
354           }
355           Append(nabstract, nn);
356           if (!Getattr(n, "abstract:firstnode")) {
357             Setattr(n, "abstract:firstnode", nn);
358           }
359           dabstract = base != n;
360         }
361       }
362       if (dabstract)
363         return 1;
364     }
365     List *bases = Getattr(base, "allbases");
366     if (!bases)
367       return 0;
368     for (int i = 0; i < Len(bases); i++) {
369       if (is_abstract_inherit(n, Getitem(bases, i))) {
370         return 1;
371       }
372     }
373     return 0;
374   }
375
376
377   /* Grab methods used by smart pointers */
378
379   List *smart_pointer_methods(Node *cls, List *methods, int isconst, String *classname = 0) {
380     if (!methods) {
381       methods = NewList();
382     }
383
384     Node *c = firstChild(cls);
385     String *kind = Getattr(cls, "kind");
386     int mode = PUBLIC;
387     if (kind && (Strcmp(kind, "class") == 0))
388       mode = PRIVATE;
389
390     while (c) {
391       if (Getattr(c, "error") || GetFlag(c, "feature:ignore")) {
392         c = nextSibling(c);
393         continue;
394       }
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);
408             } else {
409               /* Make sure node with same name doesn't already exist */
410               int k;
411               int match = 0;
412               for (k = 0; k < Len(methods); k++) {
413                 e = Getitem(methods, k);
414                 if (Cmp(symname, Getattr(e, "sym:name")) == 0) {
415                   match = 1;
416                   break;
417                 }
418                 if ((!symname || (!Getattr(e, "sym:name"))) && (Cmp(name, Getattr(e, "name")) == 0)) {
419                   match = 1;
420                   break;
421                 }
422               }
423               if (!match) {
424                 Node *cc = c;
425                 while (cc) {
426                   Node *cp = cc;
427                   if (classname) {
428                     Setattr(cp, "classname", classname);
429                   }
430                   Setattr(cp, "allocate:smartpointeraccess", "1");
431                   /* If constant, we have to be careful */
432                   if (isconst) {
433                     SwigType *decl = Getattr(cp, "decl");
434                     if (decl) {
435                       if (SwigType_isfunction(decl)) {  /* If method, we only add if it's a const method */
436                         if (SwigType_isconst(decl)) {
437                           Append(methods, cp);
438                         }
439                       } else {
440                         Append(methods, cp);
441                       }
442                     } else {
443                       Append(methods, cp);
444                     }
445                   } else {
446                     Append(methods, cp);
447                   }
448                   cc = Getattr(cc, "sym:nextSibling");
449                 }
450               }
451             }
452           }
453         }
454       }
455
456       if (Strcmp(nodeType(c), "access") == 0) {
457         kind = Getattr(c, "kind");
458         if (Strcmp(kind, "public") == 0)
459           mode = PUBLIC;
460         else
461           mode = PRIVATE;
462       }
463       c = nextSibling(c);
464     }
465     /* Look for methods in base classes */
466     {
467       Node *bases = Getattr(cls, "bases");
468       int k;
469       for (k = 0; k < Len(bases); k++) {
470         smart_pointer_methods(Getitem(bases, k), methods, isconst);
471       }
472     }
473     /* Remove protected/private members */
474     {
475       for (int i = 0; i < Len(methods);) {
476         Node *n = Getitem(methods, i);
477         if (!is_public(n)) {
478           Delitem(methods, i);
479           continue;
480         }
481         i++;
482       }
483     }
484     return methods;
485   }
486
487   void mark_exception_classes(ParmList *p) {
488     while (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));
493       }
494       Node *c = Swig_symbol_clookup(t, 0);
495       if (c) {
496         if (!GetFlag(c, "feature:exceptionclass")) {
497           SetFlag(c, "feature:exceptionclass");
498         }
499       }
500       p = nextSibling(p);
501       Delete(t);
502     }
503   }
504
505
506   void process_exceptions(Node *n) {
507     ParmList *catchlist = 0;
508     /* 
509        the "catchlist" attribute is used to emit the block
510
511        try {$action;} 
512        catch <list of catches>;
513
514        in emit.cxx
515
516        and is either constructued from the "feature:catches" feature
517        or copied from the node "throws" list.
518      */
519     String *scatchlist = Getattr(n, "feature:catches");
520     if (scatchlist) {
521       catchlist = Swig_cparse_parms(scatchlist);
522       if (catchlist) {
523         Setattr(n, "catchlist", catchlist);
524         mark_exception_classes(catchlist);
525         Delete(catchlist);
526       }
527     }
528     ParmList *throws = Getattr(n, "throws");
529     if (throws) {
530       /* if there is no explicit catchlist, we catch everything in the throws list */
531       if (!catchlist) {
532         Setattr(n, "catchlist", throws);
533       }
534       mark_exception_classes(throws);
535     }
536   }
537
538 public:
539 Allocate():
540   inclass(NULL), extendmode(0) {
541   }
542
543   virtual int top(Node *n) {
544     cplus_mode = PUBLIC;
545     inclass = 0;
546     extendmode = 0;
547     emit_children(n);
548     return SWIG_OK;
549   }
550
551   virtual int importDirective(Node *n) {
552     return emit_children(n);
553   }
554   virtual int includeDirective(Node *n) {
555     return emit_children(n);
556   }
557   virtual int externDeclaration(Node *n) {
558     return emit_children(n);
559   }
560   virtual int namespaceDeclaration(Node *n) {
561     return emit_children(n);
562   }
563   virtual int extendDirective(Node *n) {
564     extendmode = 1;
565     emit_children(n);
566     extendmode = 0;
567     return SWIG_OK;
568   }
569
570   virtual int classDeclaration(Node *n) {
571     Symtab *symtab = Swig_symbol_current();
572     Swig_symbol_setscope(Getattr(n, "symtab"));
573
574     if (!CPlusPlus) {
575       /* Always have default constructors/destructors in C */
576       Setattr(n, "allocate:default_constructor", "1");
577       Setattr(n, "allocate:default_destructor", "1");
578     }
579
580     if (Getattr(n, "allocate:visit"))
581       return SWIG_OK;
582     Setattr(n, "allocate:visit", "1");
583
584     /* Always visit base classes first */
585     {
586       List *bases = Getattr(n, "bases");
587       if (bases) {
588         for (int i = 0; i < Len(bases); i++) {
589           Node *b = Getitem(bases, i);
590           classDeclaration(b);
591         }
592       }
593     }
594
595     inclass = n;
596     String *kind = Getattr(n, "kind");
597     if (Strcmp(kind, "class") == 0) {
598       cplus_mode = PRIVATE;
599     } else {
600       cplus_mode = PUBLIC;
601     }
602
603     emit_children(n);
604
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
607        a base class */
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");
612           if (na) {
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);
620               Delete(abstract);
621             }
622           }
623         }
624       }
625     }
626
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");
632       }
633       if (!Getattr(n, "allocate:default_constructor")) {
634         /* Check base classes */
635         List *bases = Getattr(n, "allbases");
636         int allows_default = 1;
637
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"))) {
642             allows_default = 0;
643           }
644         }
645         if (allows_default) {
646           Setattr(n, "allocate:default_constructor", "1");
647         }
648       }
649     }
650     if (!Getattr(n, "allocate:has_copy_constructor")) {
651       if (Getattr(n, "abstract")) {
652         Delattr(n, "allocate:copy_constructor");
653       }
654       if (!Getattr(n, "allocate:copy_constructor")) {
655         /* Check base classes */
656         List *bases = Getattr(n, "allbases");
657         int allows_copy = 1;
658
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"))) {
663             allows_copy = 0;
664           }
665         }
666         if (allows_copy) {
667           Setattr(n, "allocate:copy_constructor", "1");
668         }
669       }
670     }
671
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;
676
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"))) {
681           allows_destruct = 0;
682         }
683       }
684       if (allows_destruct) {
685         Setattr(n, "allocate:default_destructor", "1");
686       }
687     }
688
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;
693
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");
699         }
700       }
701       if (!allows_assign) {
702         Setattr(n, "allocate:noassign", "1");
703       }
704     }
705
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");
709       int allows_new = 1;
710
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");
716         }
717       }
718       if (!allows_new) {
719         Setattr(n, "allocate:nonew", "1");
720       }
721     }
722
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);
726       if (sp) {
727         /* Look for parent */
728         Node *p = parentNode(sp);
729         if (Strcmp(nodeType(p), "extend") == 0) {
730           p = parentNode(p);
731         }
732         if (Strcmp(nodeType(p), "class") == 0) {
733           if (GetFlag(p, "feature:ignore")) {
734             Setattr(n, "allocate:smartpointer", Getattr(p, "allocate:smartpointer"));
735           }
736         }
737       }
738     }
739
740     /* Only care about default behavior.  Remove temporary values */
741     Setattr(n, "allocate:visit", "1");
742     inclass = 0;
743     Swig_symbol_setscope(symtab);
744     return SWIG_OK;
745   }
746
747   virtual int accessDeclaration(Node *n) {
748     String *kind = Getattr(n, "kind");
749     if (Cmp(kind, "public") == 0) {
750       cplus_mode = PUBLIC;
751     } else if (Cmp(kind, "private") == 0) {
752       cplus_mode = PRIVATE;
753     } else if (Cmp(kind, "protected") == 0) {
754       cplus_mode = PROTECTED;
755     }
756     return SWIG_OK;
757   }
758
759   virtual int usingDeclaration(Node *n) {
760
761     Node *c = 0;
762     for (c = firstChild(n); c; c = nextSibling(c)) {
763       if (Strcmp(nodeType(c), "cdecl") == 0) {
764         process_exceptions(c);
765
766         if (inclass)
767           class_member_is_defined_in_bases(c, inclass);
768       }
769     }
770
771     return SWIG_OK;
772   }
773
774   virtual int cDeclaration(Node *n) {
775
776     process_exceptions(n);
777
778     if (inclass) {
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);
781
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 */
784
785       if (checkAttribute(n, "storage", "static")) {
786         Setattr(n, "cplus:staticbase", inclass);
787       }
788
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");
799         }
800       } else {
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");
805         }
806         /* Look for smart pointer operator */
807         if ((Strcmp(name, "operator ->") == 0) && (!GetFlag(n, "feature:ignore"))) {
808           /* Look for version with no parameters */
809           Node *sn = n;
810           while (sn) {
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 */
820                   int isconst = 0;
821                   Delete(SwigType_pop(type));
822                   if (SwigType_isconst(type)) {
823                     isconst = 1;
824                     Setattr(inclass, "allocate:smartpointerconst", "1");
825                   }
826                   List *methods = smart_pointer_methods(sc, 0, isconst);
827                   Setattr(inclass, "allocate:smartpointer", methods);
828                   Setattr(inclass, "allocate:smartpointerbase", base);
829                 } else {
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->()
832                      can be found */
833
834                   if ((SwigType_check_decl(type, "")) || (SwigType_check_decl(type, "r."))) {
835                     Node *nn = Swig_symbol_clookup((char *) "operator ->", Getattr(sc, "symtab"));
836                     if (nn) {
837                       Delete(base);
838                       Delete(type);
839                       sn = nn;
840                       continue;
841                     }
842                   }
843                 }
844               }
845               Delete(base);
846               Delete(type);
847               break;
848             }
849           }
850         }
851       }
852     }
853     return SWIG_OK;
854   }
855
856   virtual int constructorDeclaration(Node *n) {
857     if (!inclass)
858       return SWIG_OK;
859     Parm *parms = Getattr(n, "parms");
860
861     process_exceptions(n);
862     if (!extendmode) {
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");
870         }
871       }
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");
876       }
877     } else {
878       Setattr(inclass, "allocate:has_constructor", "1");
879       Setattr(inclass, "allocate:public_constructor", "1");
880     }
881
882
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);
893         Delete(cc);
894         cc = tmp;
895         tmp = Swig_symbol_template_deftype(rt, 0);
896         Delete(rt);
897         rt = tmp;
898       }
899       if (Strcmp(cc, rt) == 0) {
900         copy_constructor = 1;
901       } else {
902         Delete(cc);
903         cc = NewStringf("r.%s", Getattr(inclass, "name"));
904         if (Strcmp(cc, Getattr(parms, "type")) == 0) {
905           copy_constructor = 1;
906         } else {
907           Delete(cc);
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;
912           }
913           Delete(ty);
914         }
915       }
916       Delete(cc);
917       Delete(rt);
918       Delete(tn);
919
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");
927         }
928       }
929     }
930     return SWIG_OK;
931   }
932
933   virtual int destructorDeclaration(Node *n) {
934     (void) n;
935     if (!inclass)
936       return SWIG_OK;
937     if (!extendmode) {
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");
943       }
944     }
945     return SWIG_OK;
946   }
947 };
948
949 void Swig_default_allocators(Node *n) {
950   if (!n)
951     return;
952   Allocate *a = new Allocate;
953   a->top(n);
954   delete a;
955 }