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 14char cvsroot_allocate_cxx[] = "$Id: allocate.cxx 11583 2009-08-15 23:22:20Z wsfulton $"; 15 16#include "swigmod.h" 17#include "cparse.h" 18 19static int virtual_elimination_mode = 0; /* set to 0 on default */ 20 21/* Set virtual_elimination_mode */ 22void 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 29extern "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 58class 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 538public: 539Allocate(): 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 949void Swig_default_allocators(Node *n) { 950 if (!n) 951 return; 952 Allocate *a = new Allocate; 953 a->top(n); 954 delete a; 955} 956