PageRenderTime 61ms CodeModel.GetById 5ms RepoModel.GetById 0ms app.codeStats 0ms

/trunk/Source/Modules/allocate.cxx

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