PageRenderTime 45ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

/trunk/Source/CParse/templ.c

#
C | 865 lines | 649 code | 68 blank | 148 comment | 146 complexity | 86f72c3f86031ebed291b36349b3aaa5 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. * templ.c
  10. *
  11. * Expands a template into a specialized version.
  12. * ----------------------------------------------------------------------------- */
  13. char cvsroot_templ_c[] = "$Id: templ.c 11982 2010-04-09 21:40:23Z wsfulton $";
  14. #include "swig.h"
  15. #include "cparse.h"
  16. static int template_debug = 0;
  17. const char *baselists[3];
  18. void SwigType_template_init() {
  19. baselists[0] = "baselist";
  20. baselists[1] = "protectedbaselist";
  21. baselists[2] = "privatebaselist";
  22. }
  23. static void add_parms(ParmList *p, List *patchlist, List *typelist) {
  24. while (p) {
  25. SwigType *ty = Getattr(p, "type");
  26. SwigType *val = Getattr(p, "value");
  27. Append(typelist, ty);
  28. Append(typelist, val);
  29. Append(patchlist, val);
  30. p = nextSibling(p);
  31. }
  32. }
  33. void Swig_cparse_debug_templates(int x) {
  34. template_debug = x;
  35. }
  36. /* -----------------------------------------------------------------------------
  37. * cparse_template_expand()
  38. *
  39. * Expands a template node into a specialized version. This is done by
  40. * patching typenames and other aspects of the node according to a list of
  41. * template parameters
  42. * ----------------------------------------------------------------------------- */
  43. static int cparse_template_expand(Node *n, String *tname, String *rname, String *templateargs, List *patchlist, List *typelist, List *cpatchlist) {
  44. static int expanded = 0;
  45. int ret;
  46. String *nodeType;
  47. if (!n)
  48. return 0;
  49. nodeType = nodeType(n);
  50. if (Getattr(n, "error"))
  51. return 0;
  52. if (Equal(nodeType, "template")) {
  53. /* Change the node type back to normal */
  54. if (!expanded) {
  55. expanded = 1;
  56. set_nodeType(n, Getattr(n, "templatetype"));
  57. ret = cparse_template_expand(n, tname, rname, templateargs, patchlist, typelist, cpatchlist);
  58. expanded = 0;
  59. return ret;
  60. } else {
  61. /* Called when template appears inside another template */
  62. /* Member templates */
  63. set_nodeType(n, Getattr(n, "templatetype"));
  64. ret = cparse_template_expand(n, tname, rname, templateargs, patchlist, typelist, cpatchlist);
  65. set_nodeType(n, "template");
  66. return ret;
  67. }
  68. } else if (Equal(nodeType, "cdecl")) {
  69. /* A simple C declaration */
  70. SwigType *t, *v, *d;
  71. String *code;
  72. t = Getattr(n, "type");
  73. v = Getattr(n, "value");
  74. d = Getattr(n, "decl");
  75. code = Getattr(n, "code");
  76. Append(typelist, t);
  77. Append(typelist, d);
  78. Append(patchlist, v);
  79. Append(cpatchlist, code);
  80. if (Getattr(n, "conversion_operator")) {
  81. Append(cpatchlist, Getattr(n, "name"));
  82. if (Getattr(n, "sym:name")) {
  83. Append(cpatchlist, Getattr(n, "sym:name"));
  84. }
  85. }
  86. add_parms(Getattr(n, "parms"), cpatchlist, typelist);
  87. add_parms(Getattr(n, "throws"), cpatchlist, typelist);
  88. } else if (Equal(nodeType, "class")) {
  89. /* Patch base classes */
  90. {
  91. int b = 0;
  92. for (b = 0; b < 3; ++b) {
  93. List *bases = Getattr(n, baselists[b]);
  94. if (bases) {
  95. int i;
  96. int ilen = Len(bases);
  97. for (i = 0; i < ilen; i++) {
  98. String *name = Copy(Getitem(bases, i));
  99. Setitem(bases, i, name);
  100. Append(typelist, name);
  101. }
  102. }
  103. }
  104. }
  105. /* Patch children */
  106. {
  107. Node *cn = firstChild(n);
  108. while (cn) {
  109. cparse_template_expand(cn, tname, rname, templateargs, patchlist, typelist, cpatchlist);
  110. cn = nextSibling(cn);
  111. }
  112. }
  113. } else if (Equal(nodeType, "constructor")) {
  114. String *name = Getattr(n, "name");
  115. if (!(Getattr(n, "templatetype"))) {
  116. String *symname;
  117. String *stripped_name = SwigType_templateprefix(name);
  118. if (Strstr(tname, stripped_name)) {
  119. Replaceid(name, stripped_name, tname);
  120. }
  121. Delete(stripped_name);
  122. symname = Getattr(n, "sym:name");
  123. if (symname) {
  124. stripped_name = SwigType_templateprefix(symname);
  125. if (Strstr(tname, stripped_name)) {
  126. Replaceid(symname, stripped_name, tname);
  127. }
  128. Delete(stripped_name);
  129. }
  130. if (strchr(Char(name), '<')) {
  131. Append(patchlist, Getattr(n, "name"));
  132. } else {
  133. Append(name, templateargs);
  134. }
  135. name = Getattr(n, "sym:name");
  136. if (name) {
  137. if (strchr(Char(name), '<')) {
  138. Clear(name);
  139. Append(name, rname);
  140. } else {
  141. String *tmp = Copy(name);
  142. Replace(tmp, tname, rname, DOH_REPLACE_ANY);
  143. Clear(name);
  144. Append(name, tmp);
  145. Delete(tmp);
  146. }
  147. }
  148. /* Setattr(n,"sym:name",name); */
  149. }
  150. Append(cpatchlist, Getattr(n, "code"));
  151. Append(typelist, Getattr(n, "decl"));
  152. add_parms(Getattr(n, "parms"), cpatchlist, typelist);
  153. add_parms(Getattr(n, "throws"), cpatchlist, typelist);
  154. } else if (Equal(nodeType, "destructor")) {
  155. String *name = Getattr(n, "name");
  156. if (name) {
  157. if (strchr(Char(name), '<'))
  158. Append(patchlist, Getattr(n, "name"));
  159. else
  160. Append(name, templateargs);
  161. }
  162. name = Getattr(n, "sym:name");
  163. if (name) {
  164. if (strchr(Char(name), '<')) {
  165. String *sn = Copy(tname);
  166. Setattr(n, "sym:name", sn);
  167. Delete(sn);
  168. } else {
  169. Replace(name, tname, rname, DOH_REPLACE_ANY);
  170. }
  171. }
  172. /* Setattr(n,"sym:name",name); */
  173. Append(cpatchlist, Getattr(n, "code"));
  174. } else if (Equal(nodeType, "using")) {
  175. String *uname = Getattr(n, "uname");
  176. if (uname && strchr(Char(uname), '<')) {
  177. Append(patchlist, uname);
  178. }
  179. if (Getattr(n, "namespace")) {
  180. /* Namespace link. This is nasty. Is other namespace defined? */
  181. }
  182. } else {
  183. /* Look for obvious parameters */
  184. Node *cn;
  185. Append(cpatchlist, Getattr(n, "code"));
  186. Append(typelist, Getattr(n, "type"));
  187. Append(typelist, Getattr(n, "decl"));
  188. add_parms(Getattr(n, "parms"), cpatchlist, typelist);
  189. add_parms(Getattr(n, "kwargs"), cpatchlist, typelist);
  190. add_parms(Getattr(n, "pattern"), cpatchlist, typelist);
  191. add_parms(Getattr(n, "throws"), cpatchlist, typelist);
  192. cn = firstChild(n);
  193. while (cn) {
  194. cparse_template_expand(cn, tname, rname, templateargs, patchlist, typelist, cpatchlist);
  195. cn = nextSibling(cn);
  196. }
  197. }
  198. return 0;
  199. }
  200. static
  201. String *partial_arg(String *s, String *p) {
  202. char *c;
  203. char *cp = Char(p);
  204. String *prefix;
  205. String *newarg;
  206. /* Find the prefix on the partial argument */
  207. c = strchr(cp, '$');
  208. if (!c) {
  209. return Copy(s);
  210. }
  211. prefix = NewStringWithSize(cp, c - cp);
  212. newarg = Copy(s);
  213. Replace(newarg, prefix, "", DOH_REPLACE_ANY | DOH_REPLACE_FIRST);
  214. Delete(prefix);
  215. return newarg;
  216. }
  217. /* -----------------------------------------------------------------------------
  218. * Swig_cparse_template_expand()
  219. * ----------------------------------------------------------------------------- */
  220. int Swig_cparse_template_expand(Node *n, String *rname, ParmList *tparms, Symtab *tscope) {
  221. List *patchlist, *cpatchlist, *typelist;
  222. String *templateargs;
  223. String *tname;
  224. String *iname;
  225. String *tbase;
  226. patchlist = NewList();
  227. cpatchlist = NewList();
  228. typelist = NewList();
  229. {
  230. String *tmp = NewStringEmpty();
  231. if (tparms) {
  232. SwigType_add_template(tmp, tparms);
  233. }
  234. templateargs = Copy(tmp);
  235. Delete(tmp);
  236. }
  237. tname = Copy(Getattr(n, "name"));
  238. tbase = Swig_scopename_last(tname);
  239. /* Look for partial specialization matching */
  240. if (Getattr(n, "partialargs")) {
  241. Parm *p, *tp;
  242. ParmList *ptargs = SwigType_function_parms(Getattr(n, "partialargs"), n);
  243. p = ptargs;
  244. tp = tparms;
  245. while (p && tp) {
  246. SwigType *ptype;
  247. SwigType *tptype;
  248. SwigType *partial_type;
  249. ptype = Getattr(p, "type");
  250. tptype = Getattr(tp, "type");
  251. if (ptype && tptype) {
  252. partial_type = partial_arg(tptype, ptype);
  253. /* Printf(stdout,"partial '%s' '%s' ---> '%s'\n", tptype, ptype, partial_type); */
  254. Setattr(tp, "type", partial_type);
  255. Delete(partial_type);
  256. }
  257. p = nextSibling(p);
  258. tp = nextSibling(tp);
  259. }
  260. assert(ParmList_len(ptargs) == ParmList_len(tparms));
  261. Delete(ptargs);
  262. }
  263. /*
  264. Parm *p = tparms;
  265. while (p) {
  266. Printf(stdout, "tparm: '%s' '%s' '%s'\n", Getattr(p, "name"), Getattr(p, "type"), Getattr(p, "value"));
  267. p = nextSibling(p);
  268. }
  269. */
  270. /* Printf(stdout,"targs = '%s'\n", templateargs);
  271. Printf(stdout,"rname = '%s'\n", rname);
  272. Printf(stdout,"tname = '%s'\n", tname); */
  273. cparse_template_expand(n, tname, rname, templateargs, patchlist, typelist, cpatchlist);
  274. /* Set the name */
  275. {
  276. String *name = Getattr(n, "name");
  277. if (name) {
  278. Append(name, templateargs);
  279. }
  280. iname = name;
  281. }
  282. /* Patch all of the types */
  283. {
  284. Parm *tp = Getattr(n, "templateparms");
  285. Parm *p = tparms;
  286. /* Printf(stdout,"%s\n", ParmList_str_defaultargs(tp)); */
  287. if (tp) {
  288. Symtab *tsdecl = Getattr(n, "sym:symtab");
  289. while (p && tp) {
  290. String *name, *value, *valuestr, *tydef, *tmp, *tmpr;
  291. int sz, i;
  292. String *dvalue = 0;
  293. String *qvalue = 0;
  294. name = Getattr(tp, "name");
  295. value = Getattr(p, "value");
  296. tydef = Getattr(p, "typedef");
  297. if (name) {
  298. if (!value)
  299. value = Getattr(p, "type");
  300. qvalue = Swig_symbol_typedef_reduce(value, tsdecl);
  301. dvalue = Swig_symbol_type_qualify(qvalue, tsdecl);
  302. if (SwigType_istemplate(dvalue)) {
  303. String *ty = Swig_symbol_template_deftype(dvalue, tscope);
  304. Delete(dvalue);
  305. dvalue = ty;
  306. }
  307. assert(dvalue);
  308. valuestr = SwigType_str(dvalue, 0);
  309. /* Need to patch default arguments */
  310. {
  311. Parm *rp = nextSibling(p);
  312. while (rp) {
  313. String *rvalue = Getattr(rp, "value");
  314. if (rvalue) {
  315. Replace(rvalue, name, dvalue, DOH_REPLACE_ID);
  316. }
  317. rp = nextSibling(rp);
  318. }
  319. }
  320. sz = Len(patchlist);
  321. for (i = 0; i < sz; i++) {
  322. String *s = Getitem(patchlist, i);
  323. Replace(s, name, dvalue, DOH_REPLACE_ID);
  324. }
  325. sz = Len(typelist);
  326. for (i = 0; i < sz; i++) {
  327. String *s = Getitem(typelist, i);
  328. /* Replace(s,name,value, DOH_REPLACE_ID); */
  329. /* Printf(stdout,"name = '%s', value = '%s', tbase = '%s', iname='%s' s = '%s' --> ", name, dvalue, tbase, iname, s); */
  330. SwigType_typename_replace(s, name, dvalue);
  331. SwigType_typename_replace(s, tbase, iname);
  332. /* Printf(stdout,"'%s'\n", s); */
  333. }
  334. if (!tydef) {
  335. tydef = dvalue;
  336. }
  337. tmp = NewStringf("#%s", name);
  338. tmpr = NewStringf("\"%s\"", valuestr);
  339. sz = Len(cpatchlist);
  340. for (i = 0; i < sz; i++) {
  341. String *s = Getitem(cpatchlist, i);
  342. Replace(s, tmp, tmpr, DOH_REPLACE_ID);
  343. /* Replace(s,name,tydef, DOH_REPLACE_ID); */
  344. Replace(s, name, valuestr, DOH_REPLACE_ID);
  345. }
  346. Delete(tmp);
  347. Delete(tmpr);
  348. Delete(valuestr);
  349. Delete(dvalue);
  350. Delete(qvalue);
  351. }
  352. p = nextSibling(p);
  353. tp = nextSibling(tp);
  354. if (!p)
  355. p = tp;
  356. }
  357. } else {
  358. /* No template parameters at all. This could be a specialization */
  359. int i, sz;
  360. sz = Len(typelist);
  361. for (i = 0; i < sz; i++) {
  362. String *s = Getitem(typelist, i);
  363. SwigType_typename_replace(s, tbase, iname);
  364. }
  365. }
  366. }
  367. /* Patch bases */
  368. {
  369. List *bases = Getattr(n, "baselist");
  370. if (bases) {
  371. Iterator b;
  372. for (b = First(bases); b.item; b = Next(b)) {
  373. String *qn = Swig_symbol_type_qualify(b.item, tscope);
  374. Clear(b.item);
  375. Append(b.item, qn);
  376. Delete(qn);
  377. }
  378. }
  379. }
  380. Delete(patchlist);
  381. Delete(cpatchlist);
  382. Delete(typelist);
  383. Delete(tbase);
  384. Delete(tname);
  385. Delete(templateargs);
  386. /* set_nodeType(n,"template"); */
  387. return 0;
  388. }
  389. typedef enum { ExactNoMatch = -2, PartiallySpecializedNoMatch = -1, PartiallySpecializedMatch = 1, ExactMatch = 2 } EMatch;
  390. /* -----------------------------------------------------------------------------
  391. * does_parm_match()
  392. *
  393. * Template argument deduction - check if a template type matches a partially specialized
  394. * template parameter type. Typedef reduce 'partial_parm_type' to see if it matches 'type'.
  395. *
  396. * type - template parameter type to match against
  397. * partial_parm_type - partially specialized template type - a possible match
  398. * partial_parm_type_base - base type of partial_parm_type
  399. * tscope - template scope
  400. * specialization_priority - (output) contains a value indicating how good the match is
  401. * (higher is better) only set if return is set to PartiallySpecializedMatch or ExactMatch.
  402. * ----------------------------------------------------------------------------- */
  403. static EMatch does_parm_match(SwigType *type, SwigType *partial_parm_type, const char *partial_parm_type_base, Symtab *tscope, int *specialization_priority) {
  404. static const int EXACT_MATCH_PRIORITY = 99999; /* a number bigger than the length of any conceivable type */
  405. int matches;
  406. int substitutions;
  407. EMatch match;
  408. SwigType *ty = Swig_symbol_typedef_reduce(type, tscope);
  409. String *base = SwigType_base(ty);
  410. SwigType *t = Copy(partial_parm_type);
  411. substitutions = Replaceid(t, partial_parm_type_base, base); /* eg: Replaceid("p.$1", "$1", "int") returns t="p.int" */
  412. matches = Equal(ty, t);
  413. *specialization_priority = -1;
  414. if (substitutions == 1) {
  415. /* we have a non-explicit specialized parameter (in partial_parm_type) because a substitution for $1, $2... etc has taken place */
  416. SwigType *tt = Copy(partial_parm_type);
  417. int len;
  418. /*
  419. check for match to partial specialization type, for example, all of the following could match the type in the %template:
  420. template <typename T> struct XX {};
  421. template <typename T> struct XX<T &> {}; // r.$1
  422. template <typename T> struct XX<T const&> {}; // r.q(const).$1
  423. template <typename T> struct XX<T *const&> {}; // r.q(const).p.$1
  424. %template(XXX) XX<int *const&>; // r.q(const).p.int
  425. where type="r.q(const).p.int" will match either of tt="r.", tt="r.q(const)" tt="r.q(const).p"
  426. */
  427. Replaceid(tt, partial_parm_type_base, ""); /* remove the $1, $2 etc, eg tt="p.$1" => "p." */
  428. len = Len(tt);
  429. if (Strncmp(tt, ty, len) == 0) {
  430. match = PartiallySpecializedMatch;
  431. *specialization_priority = len;
  432. } else {
  433. match = PartiallySpecializedNoMatch;
  434. }
  435. Delete(tt);
  436. } else {
  437. match = matches ? ExactMatch : ExactNoMatch;
  438. if (matches)
  439. *specialization_priority = EXACT_MATCH_PRIORITY; /* exact matches always take precedence */
  440. }
  441. /*
  442. Printf(stdout, " does_parm_match %2d %5d [%s] [%s]\n", match, *specialization_priority, type, partial_parm_type);
  443. */
  444. Delete(t);
  445. Delete(base);
  446. Delete(ty);
  447. return match;
  448. }
  449. /* -----------------------------------------------------------------------------
  450. * template_locate()
  451. *
  452. * Search for a template that matches name with given parameters.
  453. * ----------------------------------------------------------------------------- */
  454. static Node *template_locate(String *name, Parm *tparms, Symtab *tscope) {
  455. Node *n = 0;
  456. String *tname = 0;
  457. Node *templ;
  458. Symtab *primary_scope = 0;
  459. List *possiblepartials = 0;
  460. Parm *p;
  461. Parm *parms = 0;
  462. Parm *targs;
  463. ParmList *expandedparms;
  464. int *priorities_matrix = 0;
  465. int max_possible_partials = 0;
  466. int posslen = 0;
  467. /* Search for primary (unspecialized) template */
  468. templ = Swig_symbol_clookup(name, 0);
  469. if (template_debug) {
  470. tname = Copy(name);
  471. SwigType_add_template(tname, tparms);
  472. Printf(stdout, "\n");
  473. Swig_diagnostic(cparse_file, cparse_line, "template_debug: Searching for match to: '%s'\n", tname);
  474. Delete(tname);
  475. tname = 0;
  476. }
  477. if (templ) {
  478. tname = Copy(name);
  479. parms = CopyParmList(tparms);
  480. /* All template specializations must be in the primary template's scope, store the symbol table for this scope for specialization lookups */
  481. primary_scope = Getattr(templ, "sym:symtab");
  482. /* Add default values from primary template */
  483. targs = Getattr(templ, "templateparms");
  484. expandedparms = Swig_symbol_template_defargs(parms, targs, tscope, primary_scope);
  485. /* reduce the typedef */
  486. p = expandedparms;
  487. while (p) {
  488. SwigType *ty = Getattr(p, "type");
  489. if (ty) {
  490. SwigType *nt = Swig_symbol_type_qualify(ty, tscope);
  491. Setattr(p, "type", nt);
  492. Delete(nt);
  493. }
  494. p = nextSibling(p);
  495. }
  496. SwigType_add_template(tname, expandedparms);
  497. /* Search for an explicit (exact) specialization. Example: template<> class name<int> { ... } */
  498. {
  499. if (template_debug) {
  500. Printf(stdout, " searching for : '%s' (explicit specialization)\n", tname);
  501. }
  502. n = Swig_symbol_clookup_local(tname, primary_scope);
  503. if (!n) {
  504. SwigType *rname = Swig_symbol_typedef_reduce(tname, tscope);
  505. if (!Equal(rname, tname)) {
  506. if (template_debug) {
  507. Printf(stdout, " searching for : '%s' (explicit specialization with typedef reduction)\n", rname);
  508. }
  509. n = Swig_symbol_clookup_local(rname, primary_scope);
  510. }
  511. Delete(rname);
  512. }
  513. if (n) {
  514. Node *tn;
  515. String *nodeType = nodeType(n);
  516. if (Equal(nodeType, "template")) {
  517. if (template_debug) {
  518. Printf(stdout, " explicit specialization found: '%s'\n", Getattr(n, "name"));
  519. }
  520. goto success;
  521. }
  522. tn = Getattr(n, "template");
  523. if (tn) {
  524. if (template_debug) {
  525. Printf(stdout, " previous instantiation found: '%s'\n", Getattr(n, "name"));
  526. }
  527. n = tn;
  528. goto success; /* Previously wrapped by a template instantiation */
  529. }
  530. Swig_error(cparse_file, cparse_line, "'%s' is not defined as a template. (%s)\n", name, nodeType(n));
  531. Delete(tname);
  532. Delete(parms);
  533. return 0; /* Found a match, but it's not a template of any kind. */
  534. }
  535. }
  536. /* Search for partial specializations.
  537. * Example: template<typename T> class name<T *> { ... }
  538. * There are 3 types of template arguments:
  539. * (1) Template type arguments
  540. * (2) Template non type arguments
  541. * (3) Template template arguments
  542. * only (1) is really supported for partial specializations
  543. */
  544. /* Rank each template parameter against the desired template parameters then build a matrix of best matches */
  545. possiblepartials = NewList();
  546. {
  547. char tmp[32];
  548. List *partials;
  549. partials = Getattr(templ, "partials"); /* note that these partial specializations do not include explicit specializations */
  550. if (partials) {
  551. Iterator pi;
  552. int parms_len = ParmList_len(parms);
  553. int *priorities_row;
  554. max_possible_partials = Len(partials);
  555. priorities_matrix = (int *)malloc(sizeof(int) * max_possible_partials * parms_len); /* slightly wasteful allocation for max possible matches */
  556. priorities_row = priorities_matrix;
  557. for (pi = First(partials); pi.item; pi = Next(pi)) {
  558. Parm *p = parms;
  559. int all_parameters_match = 1;
  560. int i = 1;
  561. Parm *partialparms = Getattr(pi.item, "partialparms");
  562. Parm *pp = partialparms;
  563. String *templcsymname = Getattr(pi.item, "templcsymname");
  564. if (template_debug) {
  565. Printf(stdout, " checking match: '%s' (partial specialization)\n", templcsymname);
  566. }
  567. if (ParmList_len(partialparms) == parms_len) {
  568. while (p && pp) {
  569. SwigType *t;
  570. sprintf(tmp, "$%d", i);
  571. t = Getattr(p, "type");
  572. if (!t)
  573. t = Getattr(p, "value");
  574. if (t) {
  575. EMatch match = does_parm_match(t, Getattr(pp, "type"), tmp, tscope, priorities_row + i - 1);
  576. if (match < (int)PartiallySpecializedMatch) {
  577. all_parameters_match = 0;
  578. break;
  579. }
  580. }
  581. i++;
  582. p = nextSibling(p);
  583. pp = nextSibling(pp);
  584. }
  585. if (all_parameters_match) {
  586. Append(possiblepartials, pi.item);
  587. priorities_row += parms_len;
  588. }
  589. }
  590. }
  591. }
  592. }
  593. posslen = Len(possiblepartials);
  594. if (template_debug) {
  595. int i;
  596. if (posslen == 0)
  597. Printf(stdout, " matched partials: NONE\n");
  598. else if (posslen == 1)
  599. Printf(stdout, " chosen partial: '%s'\n", Getattr(Getitem(possiblepartials, 0), "templcsymname"));
  600. else {
  601. Printf(stdout, " possibly matched partials:\n");
  602. for (i = 0; i < posslen; i++) {
  603. Printf(stdout, " '%s'\n", Getattr(Getitem(possiblepartials, i), "templcsymname"));
  604. }
  605. }
  606. }
  607. if (posslen > 1) {
  608. /* Now go through all the possibly matched partial specialization templates and look for a non-ambiguous match.
  609. * Exact matches rank the highest and deduced parameters are ranked by how specialized they are, eg looking for
  610. * a match to const int *, the following rank (highest to lowest):
  611. * const int * (exact match)
  612. * const T *
  613. * T *
  614. * T
  615. *
  616. * An ambiguous example when attempting to match as either specialization could match: %template() X<int *, double *>;
  617. * template<typename T1, typename T2> X class {}; // primary template
  618. * template<typename T1> X<T1, double *> class {}; // specialization (1)
  619. * template<typename T2> X<int *, T2> class {}; // specialization (2)
  620. */
  621. if (template_debug) {
  622. int row, col;
  623. int parms_len = ParmList_len(parms);
  624. Printf(stdout, " parameter priorities matrix (%d parms):\n", parms_len);
  625. for (row = 0; row < posslen; row++) {
  626. int *priorities_row = priorities_matrix + row*parms_len;
  627. Printf(stdout, " ");
  628. for (col = 0; col < parms_len; col++) {
  629. Printf(stdout, "%5d ", priorities_row[col]);
  630. }
  631. Printf(stdout, "\n");
  632. }
  633. }
  634. {
  635. int row, col;
  636. int parms_len = ParmList_len(parms);
  637. /* Printf(stdout, " parameter priorities inverse matrix (%d parms):\n", parms_len); */
  638. for (col = 0; col < parms_len; col++) {
  639. int *priorities_col = priorities_matrix + col;
  640. int maxpriority = -1;
  641. /*
  642. Printf(stdout, "max_possible_partials: %d col:%d\n", max_possible_partials, col);
  643. Printf(stdout, " ");
  644. */
  645. /* determine the highest rank for this nth parameter */
  646. for (row = 0; row < posslen; row++) {
  647. int *element_ptr = priorities_col + row*parms_len;
  648. int priority = *element_ptr;
  649. if (priority > maxpriority)
  650. maxpriority = priority;
  651. /* Printf(stdout, "%5d ", priority); */
  652. }
  653. /* Printf(stdout, "\n"); */
  654. /* flag all the parameters which equal the highest rank */
  655. for (row = 0; row < posslen; row++) {
  656. int *element_ptr = priorities_col + row*parms_len;
  657. int priority = *element_ptr;
  658. *element_ptr = (priority >= maxpriority) ? 1 : 0;
  659. }
  660. }
  661. }
  662. {
  663. int row, col;
  664. int parms_len = ParmList_len(parms);
  665. Iterator pi = First(possiblepartials);
  666. Node *chosenpartials = NewList();
  667. if (template_debug)
  668. Printf(stdout, " priority flags matrix:\n");
  669. for (row = 0; row < posslen; row++) {
  670. int *priorities_row = priorities_matrix + row*parms_len;
  671. int highest_count = 0; /* count of highest priority parameters */
  672. for (col = 0; col < parms_len; col++) {
  673. highest_count += priorities_row[col];
  674. }
  675. if (template_debug) {
  676. Printf(stdout, " ");
  677. for (col = 0; col < parms_len; col++) {
  678. Printf(stdout, "%5d ", priorities_row[col]);
  679. }
  680. Printf(stdout, "\n");
  681. }
  682. if (highest_count == parms_len) {
  683. Append(chosenpartials, pi.item);
  684. }
  685. pi = Next(pi);
  686. }
  687. if (Len(chosenpartials) > 0) {
  688. /* one or more best match found */
  689. Delete(possiblepartials);
  690. possiblepartials = chosenpartials;
  691. posslen = Len(possiblepartials);
  692. } else {
  693. /* no best match found */
  694. Delete(chosenpartials);
  695. }
  696. }
  697. }
  698. if (posslen > 0) {
  699. String *s = Getattr(Getitem(possiblepartials, 0), "templcsymname");
  700. n = Swig_symbol_clookup_local(s, primary_scope);
  701. if (posslen > 1) {
  702. int i;
  703. if (n) {
  704. Swig_warning(WARN_PARSE_TEMPLATE_AMBIG, cparse_file, cparse_line, "Instantiation of template '%s' is ambiguous,\n", SwigType_namestr(tname));
  705. Swig_warning(WARN_PARSE_TEMPLATE_AMBIG, Getfile(n), Getline(n), " instantiation '%s' used,\n", SwigType_namestr(Getattr(n, "name")));
  706. }
  707. for (i = 1; i < posslen; i++) {
  708. String *templcsymname = Getattr(Getitem(possiblepartials, i), "templcsymname");
  709. Node *ignored_node = Swig_symbol_clookup_local(templcsymname, primary_scope);
  710. Swig_warning(WARN_PARSE_TEMPLATE_AMBIG, Getfile(ignored_node), Getline(ignored_node), " instantiation '%s' ignored.\n", SwigType_namestr(Getattr(ignored_node, "name")));
  711. }
  712. }
  713. }
  714. if (!n) {
  715. if (template_debug) {
  716. Printf(stdout, " chosen primary template: '%s'\n", Getattr(templ, "name"));
  717. }
  718. n = templ;
  719. }
  720. } else {
  721. if (template_debug) {
  722. Printf(stdout, " primary template not found\n");
  723. }
  724. /* Give up if primary (unspecialized) template not found as specializations will only exist if there is a primary template */
  725. n = 0;
  726. }
  727. if (!n) {
  728. Swig_error(cparse_file, cparse_line, "Template '%s' undefined.\n", name);
  729. } else if (n) {
  730. String *nodeType = nodeType(n);
  731. if (!Equal(nodeType, "template")) {
  732. Swig_error(cparse_file, cparse_line, "'%s' is not defined as a template. (%s)\n", name, nodeType);
  733. n = 0;
  734. }
  735. }
  736. success:
  737. Delete(tname);
  738. Delete(possiblepartials);
  739. if ((template_debug) && (n)) {
  740. /*
  741. Printf(stdout, "Node: %p\n", n);
  742. Swig_print_node(n);
  743. */
  744. Printf(stdout, " chosen template:'%s'\n", Getattr(n, "name"));
  745. }
  746. Delete(parms);
  747. free(priorities_matrix);
  748. return n;
  749. }
  750. /* -----------------------------------------------------------------------------
  751. * Swig_cparse_template_locate()
  752. *
  753. * Search for a template that matches name with given parameters.
  754. * For templated classes finds the specialized template should there be one.
  755. * For templated functions finds the unspecialized template even if a specialized
  756. * template exists.
  757. * ----------------------------------------------------------------------------- */
  758. Node *Swig_cparse_template_locate(String *name, Parm *tparms, Symtab *tscope) {
  759. Node *n = template_locate(name, tparms, tscope); /* this function does what we want for templated classes */
  760. if (n) {
  761. String *nodeType = nodeType(n);
  762. int isclass = 0;
  763. assert(Equal(nodeType, "template"));
  764. isclass = (Equal(Getattr(n, "templatetype"), "class"));
  765. if (!isclass) {
  766. /* If not a templated class we must have a templated function.
  767. The template found is not necessarily the one we want when dealing with templated
  768. functions. We don't want any specialized templated functions as they won't have
  769. the default parameters. Lets look for the unspecialized template. Also make sure
  770. the number of template parameters is correct as it is possible to overload a
  771. templated function with different numbers of template parameters. */
  772. if (template_debug) {
  773. Printf(stdout, " Not a templated class, seeking most appropriate templated function\n");
  774. }
  775. n = Swig_symbol_clookup_local(name, 0);
  776. while (n) {
  777. Parm *tparmsfound = Getattr(n, "templateparms");
  778. if (ParmList_len(tparms) == ParmList_len(tparmsfound)) {
  779. /* successful match */
  780. break;
  781. }
  782. /* repeat until we find a match with correct number of templated parameters */
  783. n = Getattr(n, "sym:nextSibling");
  784. }
  785. if (!n) {
  786. Swig_error(cparse_file, cparse_line, "Template '%s' undefined.\n", name);
  787. }
  788. if ((template_debug) && (n)) {
  789. Printf(stdout, "Templated function found: %p\n", n);
  790. Swig_print_node(n);
  791. }
  792. }
  793. }
  794. return n;
  795. }