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