/trunk/Source/Modules/allocate.cxx
C++ | 953 lines | 759 code | 78 blank | 116 comment | 290 complexity | eb9a40820f1b19711dd0468f92ab6e3d MD5 | raw file
1/* ----------------------------------------------------------------------------- 2 * This file is part of SWIG, which is licensed as a whole under version 3 3 * (or any later version) of the GNU General Public License. Some additional 4 * terms also apply to certain portions of SWIG. The full details of the SWIG 5 * license and copyrights can be found in the LICENSE and COPYRIGHT files 6 * included with the SWIG source code as distributed by the SWIG developers 7 * and at http://www.swig.org/legal.html. 8 * 9 * allocate.cxx 10 * 11 * This module tries to figure out which classes and structures support 12 * default constructors and destructors in C++. There are several rules that 13 * define this behavior including pure abstract methods, private sections, 14 * and non-default constructors in base classes. See the ARM or 15 * Doc/Manual/SWIGPlus.html for details. 16 * ----------------------------------------------------------------------------- */ 17 18char cvsroot_allocate_cxx[] = "$Id: allocate.cxx 12804 2011-09-13 06:15:29Z wsfulton $"; 19 20#include "swigmod.h" 21#include "cparse.h" 22 23static int virtual_elimination_mode = 0; /* set to 0 on default */ 24 25/* Set virtual_elimination_mode */ 26void Wrapper_virtual_elimination_mode_set(int flag) { 27 virtual_elimination_mode = flag; 28} 29 30/* Helper function to assist with abstract class checking. 31 This is a major hack. Sorry. */ 32 33extern "C" { 34 static String *search_decl = 0; /* Declarator being searched */ 35 static int check_implemented(Node *n) { 36 String *decl; 37 if (!n) 38 return 0; 39 while (n) { 40 if (Strcmp(nodeType(n), "cdecl") == 0) { 41 decl = Getattr(n, "decl"); 42 if (SwigType_isfunction(decl)) { 43 SwigType *decl1 = SwigType_typedef_resolve_all(decl); 44 SwigType *decl2 = SwigType_pop_function(decl1); 45 if (Strcmp(decl2, search_decl) == 0) { 46 if (!Getattr(n, "abstract")) { 47 Delete(decl1); 48 Delete(decl2); 49 return 1; 50 } 51 } 52 Delete(decl1); 53 Delete(decl2); 54 } 55 } 56 n = Getattr(n, "csym:nextSibling"); 57 } 58 return 0; 59 } 60} 61 62class Allocate:public Dispatcher { 63 Node *inclass; 64 int extendmode; 65 66 /* Checks if a function, n, is the same as any in the base class, ie if the method is polymorphic. 67 * Also checks for methods which will be hidden (ie a base has an identical non-virtual method). 68 * Both methods must have public access for a match to occur. */ 69 int function_is_defined_in_bases(Node *n, Node *bases) { 70 71 if (!bases) 72 return 0; 73 74 String *this_decl = Getattr(n, "decl"); 75 if (!this_decl) 76 return 0; 77 78 String *name = Getattr(n, "name"); 79 String *this_type = Getattr(n, "type"); 80 String *resolved_decl = SwigType_typedef_resolve_all(this_decl); 81 82 // Search all base classes for methods with same signature 83 for (int i = 0; i < Len(bases); i++) { 84 Node *b = Getitem(bases, i); 85 Node *base = firstChild(b); 86 while (base) { 87 if (Strcmp(nodeType(base), "extend") == 0) { 88 // Loop through all the %extend methods 89 Node *extend = firstChild(base); 90 while (extend) { 91 if (function_is_defined_in_bases_seek(n, b, extend, this_decl, name, this_type, resolved_decl)) { 92 Delete(resolved_decl); 93 return 1; 94 } 95 extend = nextSibling(extend); 96 } 97 } else if (Strcmp(nodeType(base), "using") == 0) { 98 // Loop through all the using declaration methods 99 Node *usingdecl = firstChild(base); 100 while (usingdecl) { 101 if (function_is_defined_in_bases_seek(n, b, usingdecl, this_decl, name, this_type, resolved_decl)) { 102 Delete(resolved_decl); 103 return 1; 104 } 105 usingdecl = nextSibling(usingdecl); 106 } 107 } else { 108 // normal methods 109 if (function_is_defined_in_bases_seek(n, b, base, this_decl, name, this_type, resolved_decl)) { 110 Delete(resolved_decl); 111 return 1; 112 } 113 } 114 base = nextSibling(base); 115 } 116 } 117 Delete(resolved_decl); 118 resolved_decl = 0; 119 for (int j = 0; j < Len(bases); j++) { 120 Node *b = Getitem(bases, j); 121 if (function_is_defined_in_bases(n, Getattr(b, "allbases"))) 122 return 1; 123 } 124 return 0; 125 } 126 127 /* Helper function for function_is_defined_in_bases */ 128 int function_is_defined_in_bases_seek(Node *n, Node *b, Node *base, String *this_decl, String *name, String *this_type, String *resolved_decl) { 129 130 String *base_decl = Getattr(base, "decl"); 131 SwigType *base_type = Getattr(base, "type"); 132 if (base_decl && base_type) { 133 if (checkAttribute(base, "name", name) && !GetFlag(b, "feature:ignore") /* whole class is ignored */ ) { 134 if (SwigType_isfunction(resolved_decl) && SwigType_isfunction(base_decl)) { 135 // We have found a method that has the same name as one in a base class 136 bool covariant_returntype = false; 137 bool returntype_match = Strcmp(base_type, this_type) == 0 ? true : false; 138 bool decl_match = Strcmp(base_decl, this_decl) == 0 ? true : false; 139 if (returntype_match && decl_match) { 140 // Exact match - we have found a method with identical signature 141 // No typedef resolution was done, but skipping it speeds things up slightly 142 } else { 143 // Either we have: 144 // 1) matching methods but are one of them uses a different typedef (return type or parameter) to the one in base class' method 145 // 2) matching polymorphic methods with covariant return type 146 // 3) a non-matching method (ie an overloaded method of some sort) 147 // 4) a matching method which is not polymorphic, ie it hides the base class' method 148 149 // Check if fully resolved return types match (including 150 // covariant return types) 151 if (!returntype_match) { 152 String *this_returntype = function_return_type(n); 153 String *base_returntype = function_return_type(base); 154 returntype_match = Strcmp(this_returntype, base_returntype) == 0 ? true : false; 155 if (!returntype_match) { 156 covariant_returntype = SwigType_issubtype(this_returntype, base_returntype) ? true : false; 157 returntype_match = covariant_returntype; 158 } 159 Delete(this_returntype); 160 Delete(base_returntype); 161 } 162 // The return types must match at this point, for the whole method to match 163 if (returntype_match && !decl_match) { 164 // Now need to check the parameter list 165 // First do an inexpensive parameter count 166 ParmList *this_parms = Getattr(n, "parms"); 167 ParmList *base_parms = Getattr(base, "parms"); 168 if (ParmList_len(this_parms) == ParmList_len(base_parms)) { 169 // Number of parameters are the same, now check that all the parameters match 170 SwigType *base_fn = NewString(""); 171 SwigType *this_fn = NewString(""); 172 SwigType_add_function(base_fn, base_parms); 173 SwigType_add_function(this_fn, this_parms); 174 base_fn = SwigType_typedef_resolve_all(base_fn); 175 this_fn = SwigType_typedef_resolve_all(this_fn); 176 if (Strcmp(base_fn, this_fn) == 0) { 177 // Finally check that the qualifiers match 178 int base_qualifier = SwigType_isqualifier(resolved_decl); 179 int this_qualifier = SwigType_isqualifier(base_decl); 180 if (base_qualifier == this_qualifier) { 181 decl_match = true; 182 } 183 } 184 Delete(base_fn); 185 Delete(this_fn); 186 } 187 } 188 } 189 //Printf(stderr,"look %s %s %d %d\n",base_decl, this_decl, returntype_match, decl_match); 190 191 if (decl_match && returntype_match) { 192 // Found an identical method in the base class 193 bool this_wrapping_protected_members = is_member_director(n) ? true : false; // This should really check for dirprot rather than just being a director method 194 bool base_wrapping_protected_members = is_member_director(base) ? true : false; // This should really check for dirprot rather than just being a director method 195 bool both_have_public_access = is_public(n) && is_public(base); 196 bool both_have_protected_access = (is_protected(n) && this_wrapping_protected_members) && (is_protected(base) && base_wrapping_protected_members); 197 bool both_have_private_access = is_private(n) && is_private(base); 198 if (checkAttribute(base, "storage", "virtual")) { 199 // Found a polymorphic method. 200 // Mark the polymorphic method, in case the virtual keyword was not used. 201 Setattr(n, "storage", "virtual"); 202 203 if (both_have_public_access || both_have_protected_access) { 204 if (!is_non_public_base(inclass, b)) 205 Setattr(n, "override", base); // Note C# definition of override, ie access must be the same 206 } else if (!both_have_private_access) { 207 // Different access 208 if (this_wrapping_protected_members || base_wrapping_protected_members) 209 if (!is_non_public_base(inclass, b)) 210 Setattr(n, "hides", base); // Note C# definition of hiding, ie hidden if access is different 211 } 212 // Try and find the most base's covariant return type 213 SwigType *most_base_covariant_type = Getattr(base, "covariant"); 214 if (!most_base_covariant_type && covariant_returntype) 215 most_base_covariant_type = function_return_type(base, false); 216 217 if (!most_base_covariant_type) { 218 // Eliminate the derived virtual method. 219 if (virtual_elimination_mode && !is_member_director(n)) 220 if (both_have_public_access) 221 if (!is_non_public_base(inclass, b)) 222 if (!Swig_symbol_isoverloaded(n)) { 223 // Don't eliminate if an overloaded method as this hides the method 224 // in the scripting languages: the dispatch function will hide the base method if ignored. 225 SetFlag(n, "feature:ignore"); 226 } 227 } else { 228 // Some languages need to know about covariant return types 229 Setattr(n, "covariant", most_base_covariant_type); 230 } 231 232 } else { 233 // Found an identical method in the base class, but it is not polymorphic. 234 if (both_have_public_access || both_have_protected_access) 235 if (!is_non_public_base(inclass, b)) 236 Setattr(n, "hides", base); 237 } 238 if (both_have_public_access || both_have_protected_access) 239 return 1; 240 } 241 } 242 } 243 } 244 return 0; 245 } 246 247 /* Determines whether the base class, b, is in the list of private 248 * or protected base classes for class n. */ 249 bool is_non_public_base(Node *n, Node *b) { 250 bool non_public_base = false; 251 Node *bases = Getattr(n, "privatebases"); 252 if (bases) { 253 for (int i = 0; i < Len(bases); i++) { 254 Node *base = Getitem(bases, i); 255 if (base == b) 256 non_public_base = true; 257 } 258 } 259 bases = Getattr(n, "protectedbases"); 260 if (bases) { 261 for (int i = 0; i < Len(bases); i++) { 262 Node *base = Getitem(bases, i); 263 if (base == b) 264 non_public_base = true; 265 } 266 } 267 return non_public_base; 268 } 269 270 /* Returns the return type for a function. The node n should be a function. 271 If resolve is true the fully returned type is fully resolved. 272 Caller is responsible for deleting returned string. */ 273 String *function_return_type(Node *n, bool resolve = true) { 274 String *decl = Getattr(n, "decl"); 275 SwigType *type = Getattr(n, "type"); 276 String *ty = NewString(type); 277 SwigType_push(ty, decl); 278 if (SwigType_isqualifier(ty)) 279 Delete(SwigType_pop(ty)); 280 Delete(SwigType_pop_function(ty)); 281 if (resolve) { 282 String *unresolved = ty; 283 ty = SwigType_typedef_resolve_all(unresolved); 284 Delete(unresolved); 285 } 286 return ty; 287 } 288 289 /* Checks if a class member is the same as inherited from the class bases */ 290 int class_member_is_defined_in_bases(Node *member, Node *classnode) { 291 Node *bases; /* bases is the closest ancestors of classnode */ 292 int defined = 0; 293 294 bases = Getattr(classnode, "allbases"); 295 if (!bases) 296 return 0; 297 298 { 299 int old_mode = virtual_elimination_mode; 300 if (is_member_director(classnode, member)) 301 virtual_elimination_mode = 0; 302 303 if (function_is_defined_in_bases(member, bases)) { 304 defined = 1; 305 } 306 307 virtual_elimination_mode = old_mode; 308 } 309 310 if (defined) 311 return 1; 312 else 313 return 0; 314 } 315 316 /* Checks to see if a class is abstract through inheritance, 317 and saves the first node that seems to be abstract. 318 */ 319 int is_abstract_inherit(Node *n, Node *base = 0, int first = 0) { 320 if (!first && (base == n)) 321 return 0; 322 if (!base) { 323 /* Root node */ 324 Symtab *stab = Getattr(n, "symtab"); /* Get symbol table for node */ 325 Symtab *oldtab = Swig_symbol_setscope(stab); 326 int ret = is_abstract_inherit(n, n, 1); 327 Swig_symbol_setscope(oldtab); 328 return ret; 329 } 330 List *abstract = Getattr(base, "abstract"); 331 if (abstract) { 332 int dabstract = 0; 333 int len = Len(abstract); 334 for (int i = 0; i < len; i++) { 335 Node *nn = Getitem(abstract, i); 336 String *name = Getattr(nn, "name"); 337 if (!name) 338 continue; 339 String *base_decl = Getattr(nn, "decl"); 340 if (base_decl) 341 base_decl = SwigType_typedef_resolve_all(base_decl); 342 if (Strchr(name, '~')) 343 continue; /* Don't care about destructors */ 344 345 if (SwigType_isfunction(base_decl)) { 346 search_decl = SwigType_pop_function(base_decl); 347 } 348 Node *dn = Swig_symbol_clookup_local_check(name, 0, check_implemented); 349 Delete(search_decl); 350 Delete(base_decl); 351 352 if (!dn) { 353 List *nabstract = Getattr(n, "abstract"); 354 if (!nabstract) { 355 nabstract = NewList(); 356 Setattr(n, "abstract", nabstract); 357 Delete(nabstract); 358 } 359 Append(nabstract, nn); 360 if (!Getattr(n, "abstract:firstnode")) { 361 Setattr(n, "abstract:firstnode", nn); 362 } 363 dabstract = base != n; 364 } 365 } 366 if (dabstract) 367 return 1; 368 } 369 List *bases = Getattr(base, "allbases"); 370 if (!bases) 371 return 0; 372 for (int i = 0; i < Len(bases); i++) { 373 if (is_abstract_inherit(n, Getitem(bases, i))) { 374 return 1; 375 } 376 } 377 return 0; 378 } 379 380 381 /* Grab methods used by smart pointers */ 382 383 List *smart_pointer_methods(Node *cls, List *methods, int isconst, String *classname = 0) { 384 if (!methods) { 385 methods = NewList(); 386 } 387 388 Node *c = firstChild(cls); 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 c = nextSibling(c); 457 } 458 /* Look for methods in base classes */ 459 { 460 Node *bases = Getattr(cls, "bases"); 461 int k; 462 for (k = 0; k < Len(bases); k++) { 463 smart_pointer_methods(Getitem(bases, k), methods, isconst); 464 } 465 } 466 /* Remove protected/private members */ 467 { 468 for (int i = 0; i < Len(methods);) { 469 Node *n = Getitem(methods, i); 470 if (!is_public(n)) { 471 Delitem(methods, i); 472 continue; 473 } 474 i++; 475 } 476 } 477 return methods; 478 } 479 480 void mark_exception_classes(ParmList *p) { 481 while (p) { 482 SwigType *ty = Getattr(p, "type"); 483 SwigType *t = SwigType_typedef_resolve_all(ty); 484 if (SwigType_isreference(t) || SwigType_ispointer(t) || SwigType_isarray(t)) { 485 Delete(SwigType_pop(t)); 486 } 487 Node *c = Swig_symbol_clookup(t, 0); 488 if (c) { 489 if (!GetFlag(c, "feature:exceptionclass")) { 490 SetFlag(c, "feature:exceptionclass"); 491 } 492 } 493 p = nextSibling(p); 494 Delete(t); 495 } 496 } 497 498 499 void process_exceptions(Node *n) { 500 ParmList *catchlist = 0; 501 /* 502 the "catchlist" attribute is used to emit the block 503 504 try {$action;} 505 catch <list of catches>; 506 507 in emit.cxx 508 509 and is either constructued from the "feature:catches" feature 510 or copied from the node "throws" list. 511 */ 512 String *scatchlist = Getattr(n, "feature:catches"); 513 if (scatchlist) { 514 catchlist = Swig_cparse_parms(scatchlist, n); 515 if (catchlist) { 516 Setattr(n, "catchlist", catchlist); 517 mark_exception_classes(catchlist); 518 Delete(catchlist); 519 } 520 } 521 ParmList *throws = Getattr(n, "throws"); 522 if (throws) { 523 /* if there is no explicit catchlist, we catch everything in the throws list */ 524 if (!catchlist) { 525 Setattr(n, "catchlist", throws); 526 } 527 mark_exception_classes(throws); 528 } 529 } 530 531public: 532Allocate(): 533 inclass(NULL), extendmode(0) { 534 } 535 536 virtual int top(Node *n) { 537 cplus_mode = PUBLIC; 538 inclass = 0; 539 extendmode = 0; 540 emit_children(n); 541 return SWIG_OK; 542 } 543 544 virtual int importDirective(Node *n) { 545 return emit_children(n); 546 } 547 virtual int includeDirective(Node *n) { 548 return emit_children(n); 549 } 550 virtual int externDeclaration(Node *n) { 551 return emit_children(n); 552 } 553 virtual int namespaceDeclaration(Node *n) { 554 return emit_children(n); 555 } 556 virtual int extendDirective(Node *n) { 557 extendmode = 1; 558 emit_children(n); 559 extendmode = 0; 560 return SWIG_OK; 561 } 562 563 virtual int classDeclaration(Node *n) { 564 Symtab *symtab = Swig_symbol_current(); 565 Swig_symbol_setscope(Getattr(n, "symtab")); 566 567 if (!CPlusPlus) { 568 /* Always have default constructors/destructors in C */ 569 Setattr(n, "allocate:default_constructor", "1"); 570 Setattr(n, "allocate:default_destructor", "1"); 571 } 572 573 if (Getattr(n, "allocate:visit")) 574 return SWIG_OK; 575 Setattr(n, "allocate:visit", "1"); 576 577 /* Always visit base classes first */ 578 { 579 List *bases = Getattr(n, "bases"); 580 if (bases) { 581 for (int i = 0; i < Len(bases); i++) { 582 Node *b = Getitem(bases, i); 583 classDeclaration(b); 584 } 585 } 586 } 587 588 inclass = n; 589 String *kind = Getattr(n, "kind"); 590 if (Strcmp(kind, "class") == 0) { 591 cplus_mode = PRIVATE; 592 } else { 593 cplus_mode = PUBLIC; 594 } 595 596 emit_children(n); 597 598 /* Check if the class is abstract via inheritance. This might occur if a class didn't have 599 any pure virtual methods of its own, but it didn't implement all of the pure methods in 600 a base class */ 601 if (!Getattr(n, "abstract") && is_abstract_inherit(n)) { 602 if (((Getattr(n, "allocate:public_constructor") || (!GetFlag(n, "feature:nodefault") && !Getattr(n, "allocate:has_constructor"))))) { 603 if (!GetFlag(n, "feature:notabstract")) { 604 Node *na = Getattr(n, "abstract:firstnode"); 605 if (na) { 606 Swig_warning(WARN_TYPE_ABSTRACT, Getfile(n), Getline(n), 607 "Class '%s' might be abstract, " "no constructors generated,\n", SwigType_namestr(Getattr(n, "name"))); 608 Swig_warning(WARN_TYPE_ABSTRACT, Getfile(na), Getline(na), "Method %s might not be implemented.\n", Swig_name_decl(na)); 609 if (!Getattr(n, "abstract")) { 610 List *abstract = NewList(); 611 Append(abstract, na); 612 Setattr(n, "abstract", abstract); 613 Delete(abstract); 614 } 615 } 616 } 617 } 618 } 619 620 if (!Getattr(n, "allocate:has_constructor")) { 621 /* No constructor is defined. We need to check a few things */ 622 /* If class is abstract. No default constructor. Sorry */ 623 if (Getattr(n, "abstract")) { 624 Delattr(n, "allocate:default_constructor"); 625 } 626 if (!Getattr(n, "allocate:default_constructor")) { 627 /* Check base classes */ 628 List *bases = Getattr(n, "allbases"); 629 int allows_default = 1; 630 631 for (int i = 0; i < Len(bases); i++) { 632 Node *n = Getitem(bases, i); 633 /* If base class does not allow default constructor, we don't allow it either */ 634 if (!Getattr(n, "allocate:default_constructor") && (!Getattr(n, "allocate:default_base_constructor"))) { 635 allows_default = 0; 636 } 637 } 638 if (allows_default) { 639 Setattr(n, "allocate:default_constructor", "1"); 640 } 641 } 642 } 643 if (!Getattr(n, "allocate:has_copy_constructor")) { 644 if (Getattr(n, "abstract")) { 645 Delattr(n, "allocate:copy_constructor"); 646 } 647 if (!Getattr(n, "allocate:copy_constructor")) { 648 /* Check base classes */ 649 List *bases = Getattr(n, "allbases"); 650 int allows_copy = 1; 651 652 for (int i = 0; i < Len(bases); i++) { 653 Node *n = Getitem(bases, i); 654 /* If base class does not allow copy constructor, we don't allow it either */ 655 if (!Getattr(n, "allocate:copy_constructor") && (!Getattr(n, "allocate:copy_base_constructor"))) { 656 allows_copy = 0; 657 } 658 } 659 if (allows_copy) { 660 Setattr(n, "allocate:copy_constructor", "1"); 661 } 662 } 663 } 664 665 if (!Getattr(n, "allocate:has_destructor")) { 666 /* No destructor was defined. We need to check a few things here too */ 667 List *bases = Getattr(n, "allbases"); 668 int allows_destruct = 1; 669 670 for (int i = 0; i < Len(bases); i++) { 671 Node *n = Getitem(bases, i); 672 /* If base class does not allow default destructor, we don't allow it either */ 673 if (!Getattr(n, "allocate:default_destructor") && (!Getattr(n, "allocate:default_base_destructor"))) { 674 allows_destruct = 0; 675 } 676 } 677 if (allows_destruct) { 678 Setattr(n, "allocate:default_destructor", "1"); 679 } 680 } 681 682 if (!Getattr(n, "allocate:has_assign")) { 683 /* No destructor was defined. We need to check a few things here too */ 684 List *bases = Getattr(n, "allbases"); 685 int allows_assign = 1; 686 687 for (int i = 0; i < Len(bases); i++) { 688 Node *n = Getitem(bases, i); 689 /* If base class does not allow default destructor, we don't allow it either */ 690 if (Getattr(n, "allocate:has_assign")) { 691 allows_assign = !Getattr(n, "allocate:noassign"); 692 } 693 } 694 if (!allows_assign) { 695 Setattr(n, "allocate:noassign", "1"); 696 } 697 } 698 699 if (!Getattr(n, "allocate:has_new")) { 700 /* No destructor was defined. We need to check a few things here too */ 701 List *bases = Getattr(n, "allbases"); 702 int allows_new = 1; 703 704 for (int i = 0; i < Len(bases); i++) { 705 Node *n = Getitem(bases, i); 706 /* If base class does not allow default destructor, we don't allow it either */ 707 if (Getattr(n, "allocate:has_new")) { 708 allows_new = !Getattr(n, "allocate:nonew"); 709 } 710 } 711 if (!allows_new) { 712 Setattr(n, "allocate:nonew", "1"); 713 } 714 } 715 716 /* Check if base classes allow smart pointers, but might be hidden */ 717 if (!Getattr(n, "allocate:smartpointer")) { 718 Node *sp = Swig_symbol_clookup((char *) "operator ->", 0); 719 if (sp) { 720 /* Look for parent */ 721 Node *p = parentNode(sp); 722 if (Strcmp(nodeType(p), "extend") == 0) { 723 p = parentNode(p); 724 } 725 if (Strcmp(nodeType(p), "class") == 0) { 726 if (GetFlag(p, "feature:ignore")) { 727 Setattr(n, "allocate:smartpointer", Getattr(p, "allocate:smartpointer")); 728 } 729 } 730 } 731 } 732 733 /* Only care about default behavior. Remove temporary values */ 734 Setattr(n, "allocate:visit", "1"); 735 inclass = 0; 736 Swig_symbol_setscope(symtab); 737 return SWIG_OK; 738 } 739 740 virtual int accessDeclaration(Node *n) { 741 String *kind = Getattr(n, "kind"); 742 if (Cmp(kind, "public") == 0) { 743 cplus_mode = PUBLIC; 744 } else if (Cmp(kind, "private") == 0) { 745 cplus_mode = PRIVATE; 746 } else if (Cmp(kind, "protected") == 0) { 747 cplus_mode = PROTECTED; 748 } 749 return SWIG_OK; 750 } 751 752 virtual int usingDeclaration(Node *n) { 753 754 Node *c = 0; 755 for (c = firstChild(n); c; c = nextSibling(c)) { 756 if (Strcmp(nodeType(c), "cdecl") == 0) { 757 process_exceptions(c); 758 759 if (inclass) 760 class_member_is_defined_in_bases(c, inclass); 761 } 762 } 763 764 return SWIG_OK; 765 } 766 767 virtual int cDeclaration(Node *n) { 768 769 process_exceptions(n); 770 771 if (inclass) { 772 /* check whether the member node n is defined in class node in class's bases */ 773 class_member_is_defined_in_bases(n, inclass); 774 775 /* Check to see if this is a static member or not. If so, we add an attribute 776 cplus:staticbase that saves the current class */ 777 778 if (checkAttribute(n, "storage", "static")) { 779 Setattr(n, "cplus:staticbase", inclass); 780 } 781 782 String *name = Getattr(n, "name"); 783 if (cplus_mode != PUBLIC) { 784 if (Strcmp(name, "operator =") == 0) { 785 /* Look for a private assignment operator */ 786 Setattr(inclass, "allocate:has_assign", "1"); 787 Setattr(inclass, "allocate:noassign", "1"); 788 } else if (Strcmp(name, "operator new") == 0) { 789 /* Look for a private new operator */ 790 Setattr(inclass, "allocate:has_new", "1"); 791 Setattr(inclass, "allocate:nonew", "1"); 792 } 793 } else { 794 if (Strcmp(name, "operator =") == 0) { 795 Setattr(inclass, "allocate:has_assign", "1"); 796 } else if (Strcmp(name, "operator new") == 0) { 797 Setattr(inclass, "allocate:has_new", "1"); 798 } 799 /* Look for smart pointer operator */ 800 if ((Strcmp(name, "operator ->") == 0) && (!GetFlag(n, "feature:ignore"))) { 801 /* Look for version with no parameters */ 802 Node *sn = n; 803 while (sn) { 804 if (!Getattr(sn, "parms")) { 805 SwigType *type = SwigType_typedef_resolve_all(Getattr(sn, "type")); 806 SwigType_push(type, Getattr(sn, "decl")); 807 Delete(SwigType_pop_function(type)); 808 SwigType *base = SwigType_base(type); 809 Node *sc = Swig_symbol_clookup(base, 0); 810 if ((sc) && (Strcmp(nodeType(sc), "class") == 0)) { 811 if (SwigType_check_decl(type, "p.")) { 812 /* Need to check if type is a const pointer */ 813 int isconst = 0; 814 Delete(SwigType_pop(type)); 815 if (SwigType_isconst(type)) { 816 isconst = !Getattr(inclass, "allocate:smartpointermutable"); 817 Setattr(inclass, "allocate:smartpointerconst", "1"); 818 } 819 else { 820 Setattr(inclass, "allocate:smartpointermutable", "1"); 821 } 822 List *methods = smart_pointer_methods(sc, 0, isconst); 823 Setattr(inclass, "allocate:smartpointer", methods); 824 Setattr(inclass, "allocate:smartpointerbase", base); 825 } else { 826 /* Hmmm. The return value is not a pointer. If the type is a value 827 or reference. We're going to chase it to see if another operator->() 828 can be found */ 829 if ((SwigType_check_decl(type, "")) || (SwigType_check_decl(type, "r."))) { 830 Node *nn = Swig_symbol_clookup((char *) "operator ->", Getattr(sc, "symtab")); 831 if (nn) { 832 Delete(base); 833 Delete(type); 834 sn = nn; 835 continue; 836 } 837 } 838 } 839 } 840 Delete(base); 841 Delete(type); 842 break; 843 } 844 } 845 } 846 } 847 } 848 return SWIG_OK; 849 } 850 851 virtual int constructorDeclaration(Node *n) { 852 if (!inclass) 853 return SWIG_OK; 854 Parm *parms = Getattr(n, "parms"); 855 856 process_exceptions(n); 857 if (!extendmode) { 858 if (!ParmList_numrequired(parms)) { 859 /* Class does define a default constructor */ 860 /* However, we had better see where it is defined */ 861 if (cplus_mode == PUBLIC) { 862 Setattr(inclass, "allocate:default_constructor", "1"); 863 } else if (cplus_mode == PROTECTED) { 864 Setattr(inclass, "allocate:default_base_constructor", "1"); 865 } 866 } 867 /* Class defines some kind of constructor. May or may not be public */ 868 Setattr(inclass, "allocate:has_constructor", "1"); 869 if (cplus_mode == PUBLIC) { 870 Setattr(inclass, "allocate:public_constructor", "1"); 871 } 872 } else { 873 Setattr(inclass, "allocate:has_constructor", "1"); 874 Setattr(inclass, "allocate:public_constructor", "1"); 875 } 876 877 878 /* See if this is a copy constructor */ 879 if (parms && (ParmList_numrequired(parms) == 1)) { 880 /* Look for a few cases. X(const X &), X(X &), X(X *) */ 881 int copy_constructor = 0; 882 SwigType *type = Getattr(inclass, "name"); 883 String *tn = NewStringf("r.q(const).%s", type); 884 String *cc = SwigType_typedef_resolve_all(tn); 885 SwigType *rt = SwigType_typedef_resolve_all(Getattr(parms, "type")); 886 if (SwigType_istemplate(type)) { 887 String *tmp = Swig_symbol_template_deftype(cc, 0); 888 Delete(cc); 889 cc = tmp; 890 tmp = Swig_symbol_template_deftype(rt, 0); 891 Delete(rt); 892 rt = tmp; 893 } 894 if (Strcmp(cc, rt) == 0) { 895 copy_constructor = 1; 896 } else { 897 Delete(cc); 898 cc = NewStringf("r.%s", Getattr(inclass, "name")); 899 if (Strcmp(cc, Getattr(parms, "type")) == 0) { 900 copy_constructor = 1; 901 } else { 902 Delete(cc); 903 cc = NewStringf("p.%s", Getattr(inclass, "name")); 904 String *ty = SwigType_strip_qualifiers(Getattr(parms, "type")); 905 if (Strcmp(cc, ty) == 0) { 906 copy_constructor = 1; 907 } 908 Delete(ty); 909 } 910 } 911 Delete(cc); 912 Delete(rt); 913 Delete(tn); 914 915 if (copy_constructor) { 916 Setattr(n, "copy_constructor", "1"); 917 Setattr(inclass, "allocate:has_copy_constructor", "1"); 918 if (cplus_mode == PUBLIC) { 919 Setattr(inclass, "allocate:copy_constructor", "1"); 920 } else if (cplus_mode == PROTECTED) { 921 Setattr(inclass, "allocate:copy_base_constructor", "1"); 922 } 923 } 924 } 925 return SWIG_OK; 926 } 927 928 virtual int destructorDeclaration(Node *n) { 929 (void) n; 930 if (!inclass) 931 return SWIG_OK; 932 if (!extendmode) { 933 Setattr(inclass, "allocate:has_destructor", "1"); 934 if (cplus_mode == PUBLIC) { 935 Setattr(inclass, "allocate:default_destructor", "1"); 936 } else if (cplus_mode == PROTECTED) { 937 Setattr(inclass, "allocate:default_base_destructor", "1"); 938 } 939 } else { 940 Setattr(inclass, "allocate:has_destructor", "1"); 941 Setattr(inclass, "allocate:default_destructor", "1"); 942 } 943 return SWIG_OK; 944 } 945}; 946 947void Swig_default_allocators(Node *n) { 948 if (!n) 949 return; 950 Allocate *a = new Allocate; 951 a->top(n); 952 delete a; 953}