comparison dmd2/template.c @ 758:f04dde6e882c

Added initial D2 support, D2 frontend and changes to codegen to make things compile.
author Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
date Tue, 11 Nov 2008 01:38:48 +0100
parents
children 356e65836fb5
comparison
equal deleted inserted replaced
757:2c730d530c98 758:f04dde6e882c
1
2 // Compiler implementation of the D programming language
3 // Copyright (c) 1999-2008 by Digital Mars
4 // All Rights Reserved
5 // written by Walter Bright
6 // http://www.digitalmars.com
7 // License for redistribution is by either the Artistic License
8 // in artistic.txt, or the GNU General Public License in gnu.txt.
9 // See the included readme.txt for details.
10
11 // Handle template implementation
12
13 #include <stdio.h>
14 #include <assert.h>
15
16 #if !IN_LLVM
17 #if _WIN32
18 #include <windows.h>
19 long __cdecl __ehfilter(LPEXCEPTION_POINTERS ep);
20 #endif
21 #endif
22
23 #include "root.h"
24 #include "mem.h"
25 #include "stringtable.h"
26 #include "mars.h"
27 #include "identifier.h"
28 #include "mtype.h"
29 #include "template.h"
30 #include "init.h"
31 #include "expression.h"
32 #include "scope.h"
33 #include "module.h"
34 #include "aggregate.h"
35 #include "declaration.h"
36 #include "dsymbol.h"
37 #include "hdrgen.h"
38
39 #define LOG 0
40
41 /********************************************
42 * These functions substitute for dynamic_cast. dynamic_cast does not work
43 * on earlier versions of gcc.
44 */
45
46 Expression *isExpression(Object *o)
47 {
48 //return dynamic_cast<Expression *>(o);
49 if (!o || o->dyncast() != DYNCAST_EXPRESSION)
50 return NULL;
51 return (Expression *)o;
52 }
53
54 Dsymbol *isDsymbol(Object *o)
55 {
56 //return dynamic_cast<Dsymbol *>(o);
57 if (!o || o->dyncast() != DYNCAST_DSYMBOL)
58 return NULL;
59 return (Dsymbol *)o;
60 }
61
62 Type *isType(Object *o)
63 {
64 //return dynamic_cast<Type *>(o);
65 if (!o || o->dyncast() != DYNCAST_TYPE)
66 return NULL;
67 return (Type *)o;
68 }
69
70 Tuple *isTuple(Object *o)
71 {
72 //return dynamic_cast<Tuple *>(o);
73 if (!o || o->dyncast() != DYNCAST_TUPLE)
74 return NULL;
75 return (Tuple *)o;
76 }
77
78
79 /***********************
80 * Try to get arg as a type.
81 */
82
83 Type *getType(Object *o)
84 {
85 Type *t = isType(o);
86 if (!t)
87 { Expression *e = isExpression(o);
88 if (e)
89 t = e->type;
90 }
91 return t;
92 }
93
94 Dsymbol *getDsymbol(Object *oarg)
95 {
96 Dsymbol *sa;
97 Expression *ea = isExpression(oarg);
98 if (ea)
99 { // Try to convert Expression to symbol
100 if (ea->op == TOKvar)
101 sa = ((VarExp *)ea)->var;
102 else if (ea->op == TOKfunction)
103 sa = ((FuncExp *)ea)->fd;
104 else
105 sa = NULL;
106 }
107 else
108 { // Try to convert Type to symbol
109 Type *ta = isType(oarg);
110 if (ta)
111 sa = ta->toDsymbol(NULL);
112 else
113 sa = isDsymbol(oarg); // if already a symbol
114 }
115 return sa;
116 }
117
118 /******************************
119 * If o1 matches o2, return 1.
120 * Else, return 0.
121 */
122
123 int match(Object *o1, Object *o2, TemplateDeclaration *tempdecl, Scope *sc)
124 {
125 Type *t1 = isType(o1);
126 Type *t2 = isType(o2);
127 Expression *e1 = isExpression(o1);
128 Expression *e2 = isExpression(o2);
129 Dsymbol *s1 = isDsymbol(o1);
130 Dsymbol *s2 = isDsymbol(o2);
131 Tuple *v1 = isTuple(o1);
132 Tuple *v2 = isTuple(o2);
133
134 //printf("\t match t1 %p t2 %p, e1 %p e2 %p, s1 %p s2 %p, v1 %p v2 %p\n", t1,t2,e1,e2,s1,s2,v1,v2);
135
136 /* A proper implementation of the various equals() overrides
137 * should make it possible to just do o1->equals(o2), but
138 * we'll do that another day.
139 */
140
141 if (t1)
142 {
143 /* if t1 is an instance of ti, then give error
144 * about recursive expansions.
145 */
146 Dsymbol *s = t1->toDsymbol(sc);
147 if (s && s->parent)
148 { TemplateInstance *ti1 = s->parent->isTemplateInstance();
149 if (ti1 && ti1->tempdecl == tempdecl)
150 {
151 for (Scope *sc1 = sc; sc1; sc1 = sc1->enclosing)
152 {
153 if (sc1->scopesym == ti1)
154 {
155 error("recursive template expansion for template argument %s", t1->toChars());
156 return 1; // fake a match
157 }
158 }
159 }
160 }
161
162 if (!t2 || !t1->equals(t2))
163 goto Lnomatch;
164 }
165 else if (e1)
166 {
167 #if 0
168 if (e1 && e2)
169 {
170 printf("match %d\n", e1->equals(e2));
171 e1->print();
172 e2->print();
173 e1->type->print();
174 e2->type->print();
175 }
176 #endif
177 if (!e2)
178 goto Lnomatch;
179 if (!e1->equals(e2))
180 goto Lnomatch;
181 }
182 else if (s1)
183 {
184 //printf("%p %s, %p %s\n", s1, s1->toChars(), s2, s2->toChars());
185 if (!s2 || !s1->equals(s2) || s1->parent != s2->parent)
186 {
187 goto Lnomatch;
188 }
189 VarDeclaration *v1 = s1->isVarDeclaration();
190 VarDeclaration *v2 = s2->isVarDeclaration();
191 if (v1 && v2 && v1->storage_class & v2->storage_class & STCmanifest)
192 { ExpInitializer *ei1 = v1->init->isExpInitializer();
193 ExpInitializer *ei2 = v2->init->isExpInitializer();
194 if (ei1 && ei2 && !ei1->exp->equals(ei2->exp))
195 goto Lnomatch;
196 }
197 }
198 else if (v1)
199 {
200 if (!v2)
201 goto Lnomatch;
202 if (v1->objects.dim != v2->objects.dim)
203 goto Lnomatch;
204 for (size_t i = 0; i < v1->objects.dim; i++)
205 {
206 if (!match((Object *)v1->objects.data[i],
207 (Object *)v2->objects.data[i],
208 tempdecl, sc))
209 goto Lnomatch;
210 }
211 }
212 //printf("match\n");
213 return 1; // match
214 Lnomatch:
215 //printf("nomatch\n");
216 return 0; // nomatch;
217 }
218
219 /****************************************
220 */
221
222 void ObjectToCBuffer(OutBuffer *buf, HdrGenState *hgs, Object *oarg)
223 {
224 //printf("ObjectToCBuffer()\n");
225 Type *t = isType(oarg);
226 Expression *e = isExpression(oarg);
227 Dsymbol *s = isDsymbol(oarg);
228 Tuple *v = isTuple(oarg);
229 if (t)
230 { //printf("\tt: %s ty = %d\n", t->toChars(), t->ty);
231 t->toCBuffer(buf, NULL, hgs);
232 }
233 else if (e)
234 e->toCBuffer(buf, hgs);
235 else if (s)
236 {
237 char *p = s->ident ? s->ident->toChars() : s->toChars();
238 buf->writestring(p);
239 }
240 else if (v)
241 {
242 Objects *args = &v->objects;
243 for (size_t i = 0; i < args->dim; i++)
244 {
245 if (i)
246 buf->writeByte(',');
247 Object *o = (Object *)args->data[i];
248 ObjectToCBuffer(buf, hgs, o);
249 }
250 }
251 else if (!oarg)
252 {
253 buf->writestring("NULL");
254 }
255 else
256 {
257 #ifdef DEBUG
258 printf("bad Object = %p\n", oarg);
259 #endif
260 assert(0);
261 }
262 }
263
264 Object *objectSyntaxCopy(Object *o)
265 {
266 if (!o)
267 return NULL;
268 Type *t = isType(o);
269 if (t)
270 return t->syntaxCopy();
271 Expression *e = isExpression(o);
272 if (e)
273 return e->syntaxCopy();
274 return o;
275 }
276
277
278 /* ======================== TemplateDeclaration ============================= */
279
280 TemplateDeclaration::TemplateDeclaration(Loc loc, Identifier *id,
281 TemplateParameters *parameters, Expression *constraint, Array *decldefs)
282 : ScopeDsymbol(id)
283 {
284 #if LOG
285 printf("TemplateDeclaration(this = %p, id = '%s')\n", this, id->toChars());
286 #endif
287 #if 0
288 if (parameters)
289 for (int i = 0; i < parameters->dim; i++)
290 { TemplateParameter *tp = (TemplateParameter *)parameters->data[i];
291 //printf("\tparameter[%d] = %p\n", i, tp);
292 TemplateTypeParameter *ttp = tp->isTemplateTypeParameter();
293
294 if (ttp)
295 {
296 printf("\tparameter[%d] = %s : %s\n", i, tp->ident->toChars(), ttp->specType ? ttp->specType->toChars() : "");
297 }
298 }
299 #endif
300 this->loc = loc;
301 this->parameters = parameters;
302 this->origParameters = parameters;
303 this->constraint = constraint;
304 this->members = decldefs;
305 this->overnext = NULL;
306 this->overroot = NULL;
307 this->scope = NULL;
308 this->onemember = NULL;
309 }
310
311 Dsymbol *TemplateDeclaration::syntaxCopy(Dsymbol *)
312 {
313 //printf("TemplateDeclaration::syntaxCopy()\n");
314 TemplateDeclaration *td;
315 TemplateParameters *p;
316 Array *d;
317
318 p = NULL;
319 if (parameters)
320 {
321 p = new TemplateParameters();
322 p->setDim(parameters->dim);
323 for (int i = 0; i < p->dim; i++)
324 { TemplateParameter *tp = (TemplateParameter *)parameters->data[i];
325 p->data[i] = (void *)tp->syntaxCopy();
326 }
327 }
328 Expression *e = NULL;
329 if (constraint)
330 e = constraint->syntaxCopy();
331 d = Dsymbol::arraySyntaxCopy(members);
332 td = new TemplateDeclaration(loc, ident, p, e, d);
333
334 // LDC
335 td->intrinsicName = intrinsicName;
336
337 return td;
338 }
339
340 void TemplateDeclaration::semantic(Scope *sc)
341 {
342 #if LOG
343 printf("TemplateDeclaration::semantic(this = %p, id = '%s')\n", this, ident->toChars());
344 #endif
345 if (scope)
346 return; // semantic() already run
347
348 if (sc->func)
349 {
350 // error("cannot declare template at function scope %s", sc->func->toChars());
351 }
352
353 if (/*global.params.useArrayBounds &&*/ sc->module)
354 {
355 // Generate this function as it may be used
356 // when template is instantiated in other modules
357 sc->module->toModuleArray();
358 }
359
360 if (/*global.params.useAssert &&*/ sc->module)
361 {
362 // Generate this function as it may be used
363 // when template is instantiated in other modules
364 sc->module->toModuleAssert();
365 }
366
367 /* Remember Scope for later instantiations, but make
368 * a copy since attributes can change.
369 */
370 this->scope = new Scope(*sc);
371 this->scope->setNoFree();
372
373 // Set up scope for parameters
374 ScopeDsymbol *paramsym = new ScopeDsymbol();
375 paramsym->parent = sc->parent;
376 Scope *paramscope = sc->push(paramsym);
377 paramscope->parameterSpecialization = 1;
378
379 if (global.params.doDocComments)
380 {
381 origParameters = new TemplateParameters();
382 origParameters->setDim(parameters->dim);
383 for (int i = 0; i < parameters->dim; i++)
384 {
385 TemplateParameter *tp = (TemplateParameter *)parameters->data[i];
386 origParameters->data[i] = (void *)tp->syntaxCopy();
387 }
388 }
389
390 for (int i = 0; i < parameters->dim; i++)
391 {
392 TemplateParameter *tp = (TemplateParameter *)parameters->data[i];
393
394 tp->declareParameter(paramscope);
395 }
396
397 for (int i = 0; i < parameters->dim; i++)
398 {
399 TemplateParameter *tp = (TemplateParameter *)parameters->data[i];
400
401 tp->semantic(paramscope);
402 if (i + 1 != parameters->dim && tp->isTemplateTupleParameter())
403 error("template tuple parameter must be last one");
404 }
405
406 paramscope->pop();
407
408 if (members)
409 {
410 Dsymbol *s;
411 if (Dsymbol::oneMembers(members, &s))
412 {
413 if (s && s->ident && s->ident->equals(ident))
414 {
415 onemember = s;
416 s->parent = this;
417 }
418 }
419 }
420
421 /* BUG: should check:
422 * o no virtual functions or non-static data members of classes
423 */
424 }
425
426 const char *TemplateDeclaration::kind()
427 {
428 return (onemember && onemember->isAggregateDeclaration())
429 ? onemember->kind()
430 : (char *)"template";
431 }
432
433 /**********************************
434 * Overload existing TemplateDeclaration 'this' with the new one 's'.
435 * Return !=0 if successful; i.e. no conflict.
436 */
437
438 int TemplateDeclaration::overloadInsert(Dsymbol *s)
439 {
440 TemplateDeclaration **pf;
441 TemplateDeclaration *f;
442
443 #if LOG
444 printf("TemplateDeclaration::overloadInsert('%s')\n", s->toChars());
445 #endif
446 f = s->isTemplateDeclaration();
447 if (!f)
448 return FALSE;
449 TemplateDeclaration *pthis = this;
450 for (pf = &pthis; *pf; pf = &(*pf)->overnext)
451 {
452 #if 0
453 // Conflict if TemplateParameter's match
454 // Will get caught anyway later with TemplateInstance, but
455 // should check it now.
456 TemplateDeclaration *f2 = *pf;
457
458 if (f->parameters->dim != f2->parameters->dim)
459 goto Lcontinue;
460
461 for (int i = 0; i < f->parameters->dim; i++)
462 { TemplateParameter *p1 = (TemplateParameter *)f->parameters->data[i];
463 TemplateParameter *p2 = (TemplateParameter *)f2->parameters->data[i];
464
465 if (!p1->overloadMatch(p2))
466 goto Lcontinue;
467 }
468
469 #if LOG
470 printf("\tfalse: conflict\n");
471 #endif
472 return FALSE;
473
474 Lcontinue:
475 ;
476 #endif
477 }
478
479 f->overroot = this;
480 *pf = f;
481 #if LOG
482 printf("\ttrue: no conflict\n");
483 #endif
484 return TRUE;
485 }
486
487 /***************************************
488 * Given that ti is an instance of this TemplateDeclaration,
489 * deduce the types of the parameters to this, and store
490 * those deduced types in dedtypes[].
491 * Input:
492 * flag 1: don't do semantic() because of dummy types
493 * 2: don't change types in matchArg()
494 * Output:
495 * dedtypes deduced arguments
496 * Return match level.
497 */
498
499 MATCH TemplateDeclaration::matchWithInstance(TemplateInstance *ti,
500 Objects *dedtypes, int flag)
501 { MATCH m;
502 int dedtypes_dim = dedtypes->dim;
503
504 #define LOGM 0
505 #if LOGM
506 printf("\n+TemplateDeclaration::matchWithInstance(this = %s, ti = %s, flag = %d)\n", toChars(), ti->toChars(), flag);
507 #endif
508
509 #if 0
510 printf("dedtypes->dim = %d, parameters->dim = %d\n", dedtypes_dim, parameters->dim);
511 if (ti->tiargs->dim)
512 printf("ti->tiargs->dim = %d, [0] = %p\n",
513 ti->tiargs->dim,
514 ti->tiargs->data[0]);
515 #endif
516 dedtypes->zero();
517
518 int parameters_dim = parameters->dim;
519 int variadic = isVariadic() != NULL;
520
521 // If more arguments than parameters, no match
522 if (ti->tiargs->dim > parameters_dim && !variadic)
523 {
524 #if LOGM
525 printf(" no match: more arguments than parameters\n");
526 #endif
527 return MATCHnomatch;
528 }
529
530 assert(dedtypes_dim == parameters_dim);
531 assert(dedtypes_dim >= ti->tiargs->dim || variadic);
532
533 // Set up scope for parameters
534 assert((size_t)scope > 0x10000);
535 ScopeDsymbol *paramsym = new ScopeDsymbol();
536 paramsym->parent = scope->parent;
537 Scope *paramscope = scope->push(paramsym);
538
539 // Attempt type deduction
540 m = MATCHexact;
541 for (int i = 0; i < dedtypes_dim; i++)
542 { MATCH m2;
543 TemplateParameter *tp = (TemplateParameter *)parameters->data[i];
544 Declaration *sparam;
545
546 //printf("\targument [%d]\n", i);
547 #if LOGM
548 //printf("\targument [%d] is %s\n", i, oarg ? oarg->toChars() : "null");
549 TemplateTypeParameter *ttp = tp->isTemplateTypeParameter();
550 if (ttp)
551 printf("\tparameter[%d] is %s : %s\n", i, tp->ident->toChars(), ttp->specType ? ttp->specType->toChars() : "");
552 #endif
553
554 #if DMDV1
555 m2 = tp->matchArg(paramscope, ti->tiargs, i, parameters, dedtypes, &sparam);
556 #else
557 m2 = tp->matchArg(paramscope, ti->tiargs, i, parameters, dedtypes, &sparam, (flag & 2) ? 1 : 0);
558
559 #endif
560 //printf("\tm2 = %d\n", m2);
561
562 if (m2 == MATCHnomatch)
563 {
564 #if 0
565 printf("\tmatchArg() for parameter %i failed\n", i);
566 #endif
567 goto Lnomatch;
568 }
569
570 if (m2 < m)
571 m = m2;
572
573 if (!flag)
574 sparam->semantic(paramscope);
575 if (!paramscope->insert(sparam))
576 goto Lnomatch;
577 }
578
579 if (!flag)
580 {
581 /* Any parameter left without a type gets the type of
582 * its corresponding arg
583 */
584 for (int i = 0; i < dedtypes_dim; i++)
585 {
586 if (!dedtypes->data[i])
587 { assert(i < ti->tiargs->dim);
588 dedtypes->data[i] = ti->tiargs->data[i];
589 }
590 }
591 }
592
593 if (m && constraint && !(flag & 1))
594 { /* Check to see if constraint is satisfied.
595 */
596 Expression *e = constraint->syntaxCopy();
597 paramscope->flags |= SCOPEstaticif;
598 e = e->semantic(paramscope);
599 e = e->optimize(WANTvalue | WANTinterpret);
600 if (e->isBool(TRUE))
601 ;
602 else if (e->isBool(FALSE))
603 goto Lnomatch;
604 else
605 {
606 e->error("constraint %s is not constant or does not evaluate to a bool", e->toChars());
607 }
608 }
609
610 #if LOGM
611 // Print out the results
612 printf("--------------------------\n");
613 printf("template %s\n", toChars());
614 printf("instance %s\n", ti->toChars());
615 if (m)
616 {
617 for (int i = 0; i < dedtypes_dim; i++)
618 {
619 TemplateParameter *tp = (TemplateParameter *)parameters->data[i];
620 Object *oarg;
621
622 printf(" [%d]", i);
623
624 if (i < ti->tiargs->dim)
625 oarg = (Object *)ti->tiargs->data[i];
626 else
627 oarg = NULL;
628 tp->print(oarg, (Object *)dedtypes->data[i]);
629 }
630 }
631 else
632 goto Lnomatch;
633 #endif
634
635 #if LOGM
636 printf(" match = %d\n", m);
637 #endif
638 goto Lret;
639
640 Lnomatch:
641 #if LOGM
642 printf(" no match\n");
643 #endif
644 m = MATCHnomatch;
645
646 Lret:
647 paramscope->pop();
648 #if LOGM
649 printf("-TemplateDeclaration::matchWithInstance(this = %p, ti = %p) = %d\n", this, ti, m);
650 #endif
651 return m;
652 }
653
654 /********************************************
655 * Determine partial specialization order of 'this' vs td2.
656 * Returns:
657 * match this is at least as specialized as td2
658 * 0 td2 is more specialized than this
659 */
660
661 MATCH TemplateDeclaration::leastAsSpecialized(TemplateDeclaration *td2)
662 {
663 /* This works by taking the template parameters to this template
664 * declaration and feeding them to td2 as if it were a template
665 * instance.
666 * If it works, then this template is at least as specialized
667 * as td2.
668 */
669
670 TemplateInstance ti(0, ident); // create dummy template instance
671 Objects dedtypes;
672
673 #define LOG_LEASTAS 0
674
675 #if LOG_LEASTAS
676 printf("%s.leastAsSpecialized(%s)\n", toChars(), td2->toChars());
677 #endif
678
679 // Set type arguments to dummy template instance to be types
680 // generated from the parameters to this template declaration
681 ti.tiargs = new Objects();
682 ti.tiargs->setDim(parameters->dim);
683 for (int i = 0; i < ti.tiargs->dim; i++)
684 {
685 TemplateParameter *tp = (TemplateParameter *)parameters->data[i];
686
687 void *p = tp->dummyArg();
688 if (p)
689 ti.tiargs->data[i] = p;
690 else
691 ti.tiargs->setDim(i);
692 }
693
694 // Temporary Array to hold deduced types
695 //dedtypes.setDim(parameters->dim);
696 dedtypes.setDim(td2->parameters->dim);
697
698 // Attempt a type deduction
699 MATCH m = td2->matchWithInstance(&ti, &dedtypes, 1);
700 if (m)
701 {
702 /* A non-variadic template is more specialized than a
703 * variadic one.
704 */
705 if (isVariadic() && !td2->isVariadic())
706 goto L1;
707
708 #if LOG_LEASTAS
709 printf(" matches %d, so is least as specialized\n", m);
710 #endif
711 return m;
712 }
713 L1:
714 #if LOG_LEASTAS
715 printf(" doesn't match, so is not as specialized\n");
716 #endif
717 return MATCHnomatch;
718 }
719
720
721 /*************************************************
722 * Match function arguments against a specific template function.
723 * Input:
724 * loc instantiation location
725 * targsi Expression/Type initial list of template arguments
726 * ethis 'this' argument if !NULL
727 * fargs arguments to function
728 * Output:
729 * dedargs Expression/Type deduced template arguments
730 * Returns:
731 * match level
732 */
733
734 MATCH TemplateDeclaration::deduceFunctionTemplateMatch(Loc loc, Objects *targsi,
735 Expression *ethis, Expressions *fargs,
736 Objects *dedargs)
737 {
738 size_t i;
739 size_t nfparams;
740 size_t nfargs;
741 size_t nargsi; // array size of targsi
742 int fptupindex = -1;
743 int tuple_dim = 0;
744 MATCH match = MATCHexact;
745 FuncDeclaration *fd = onemember->toAlias()->isFuncDeclaration();
746 TypeFunction *fdtype; // type of fd
747 TemplateTupleParameter *tp;
748 Objects dedtypes; // for T:T*, the dedargs is the T*, dedtypes is the T
749
750 #if 0
751 printf("\nTemplateDeclaration::deduceFunctionTemplateMatch() %s\n", toChars());
752 for (i = 0; i < fargs->dim; i++)
753 { Expression *e = (Expression *)fargs->data[i];
754 printf("\tfarg[%d] is %s, type is %s\n", i, e->toChars(), e->type->toChars());
755 }
756 #endif
757
758 assert((size_t)scope > 0x10000);
759
760 dedargs->setDim(parameters->dim);
761 dedargs->zero();
762
763 dedtypes.setDim(parameters->dim);
764 dedtypes.zero();
765
766 // Set up scope for parameters
767 ScopeDsymbol *paramsym = new ScopeDsymbol();
768 paramsym->parent = scope->parent;
769 Scope *paramscope = scope->push(paramsym);
770
771 tp = isVariadic();
772
773 nargsi = 0;
774 if (targsi)
775 { // Set initial template arguments
776
777 nargsi = targsi->dim;
778 if (nargsi > parameters->dim)
779 { if (!tp)
780 goto Lnomatch;
781 dedargs->setDim(nargsi);
782 dedargs->zero();
783 }
784
785 memcpy(dedargs->data, targsi->data, nargsi * sizeof(*dedargs->data));
786
787 for (i = 0; i < nargsi; i++)
788 { assert(i < parameters->dim);
789 TemplateParameter *tp = (TemplateParameter *)parameters->data[i];
790 MATCH m;
791 Declaration *sparam;
792
793 m = tp->matchArg(paramscope, dedargs, i, parameters, &dedtypes, &sparam);
794 //printf("\tdeduceType m = %d\n", m);
795 if (m == MATCHnomatch)
796 goto Lnomatch;
797 if (m < match)
798 match = m;
799
800 sparam->semantic(paramscope);
801 if (!paramscope->insert(sparam))
802 goto Lnomatch;
803 }
804 }
805
806 assert(fd->type->ty == Tfunction);
807 fdtype = (TypeFunction *)fd->type;
808
809 nfparams = Argument::dim(fdtype->parameters); // number of function parameters
810 nfargs = fargs->dim; // number of function arguments
811
812 /* Check for match of function arguments with variadic template
813 * parameter, such as:
814 *
815 * template Foo(T, A...) { void Foo(T t, A a); }
816 * void main() { Foo(1,2,3); }
817 */
818 if (tp) // if variadic
819 {
820 if (nfparams == 0) // if no function parameters
821 {
822 Tuple *t = new Tuple();
823 //printf("t = %p\n", t);
824 dedargs->data[parameters->dim - 1] = (void *)t;
825 goto L2;
826 }
827 else if (nfargs < nfparams - 1)
828 goto L1;
829 else
830 {
831 /* Figure out which of the function parameters matches
832 * the tuple template parameter. Do this by matching
833 * type identifiers.
834 * Set the index of this function parameter to fptupindex.
835 */
836 for (fptupindex = 0; fptupindex < nfparams; fptupindex++)
837 {
838 Argument *fparam = (Argument *)fdtype->parameters->data[fptupindex];
839 if (fparam->type->ty != Tident)
840 continue;
841 TypeIdentifier *tid = (TypeIdentifier *)fparam->type;
842 if (!tp->ident->equals(tid->ident) || tid->idents.dim)
843 continue;
844
845 if (fdtype->varargs) // variadic function doesn't
846 goto Lnomatch; // go with variadic template
847
848 /* The types of the function arguments
849 * now form the tuple argument.
850 */
851 Tuple *t = new Tuple();
852 dedargs->data[parameters->dim - 1] = (void *)t;
853
854 tuple_dim = nfargs - (nfparams - 1);
855 t->objects.setDim(tuple_dim);
856 for (i = 0; i < tuple_dim; i++)
857 { Expression *farg = (Expression *)fargs->data[fptupindex + i];
858 t->objects.data[i] = (void *)farg->type;
859 }
860 goto L2;
861 }
862 fptupindex = -1;
863 }
864 }
865
866 L1:
867 if (nfparams == nfargs)
868 ;
869 else if (nfargs > nfparams)
870 {
871 if (fdtype->varargs == 0)
872 goto Lnomatch; // too many args, no match
873 match = MATCHconvert; // match ... with a conversion
874 }
875
876 L2:
877 // Match 'ethis' to any TemplateThisParameter's
878 if (ethis)
879 {
880 for (size_t i = 0; i < parameters->dim; i++)
881 { TemplateParameter *tp = (TemplateParameter *)parameters->data[i];
882 TemplateThisParameter *ttp = tp->isTemplateThisParameter();
883 if (ttp)
884 { MATCH m;
885
886 Type *t = new TypeIdentifier(0, ttp->ident);
887 m = ethis->type->deduceType(scope, t, parameters, &dedtypes);
888 if (!m)
889 goto Lnomatch;
890 if (m < match)
891 match = m; // pick worst match
892 }
893 }
894 }
895
896 // Loop through the function parameters
897 for (i = 0; i < nfparams; i++)
898 {
899 /* Skip over function parameters which wound up
900 * as part of a template tuple parameter.
901 */
902 if (i == fptupindex)
903 { if (fptupindex == nfparams - 1)
904 break;
905 i += tuple_dim - 1;
906 continue;
907 }
908
909 Argument *fparam = Argument::getNth(fdtype->parameters, i);
910
911 if (i >= nfargs) // if not enough arguments
912 {
913 if (fparam->defaultArg)
914 { /* Default arguments do not participate in template argument
915 * deduction.
916 */
917 goto Lmatch;
918 }
919 }
920 else
921 { Expression *farg = (Expression *)fargs->data[i];
922 #if 0
923 printf("\tfarg->type = %s\n", farg->type->toChars());
924 printf("\tfparam->type = %s\n", fparam->type->toChars());
925 #endif
926 MATCH m;
927 //m = farg->type->toHeadMutable()->deduceType(scope, fparam->type, parameters, &dedtypes);
928 m = farg->type->deduceType(scope, fparam->type, parameters, &dedtypes);
929 //printf("\tdeduceType m = %d\n", m);
930
931 /* If no match, see if there's a conversion to a delegate
932 */
933 if (!m && fparam->type->toBasetype()->ty == Tdelegate)
934 {
935 TypeDelegate *td = (TypeDelegate *)fparam->type->toBasetype();
936 TypeFunction *tf = (TypeFunction *)td->next;
937
938 if (!tf->varargs && Argument::dim(tf->parameters) == 0)
939 {
940 m = farg->type->deduceType(scope, tf->next, parameters, &dedtypes);
941 if (!m && tf->next->toBasetype()->ty == Tvoid)
942 m = MATCHconvert;
943 }
944 //printf("\tm2 = %d\n", m);
945 }
946
947 if (m)
948 { if (m < match)
949 match = m; // pick worst match
950 continue;
951 }
952 }
953
954 /* The following code for variadic arguments closely
955 * matches TypeFunction::callMatch()
956 */
957 if (!(fdtype->varargs == 2 && i + 1 == nfparams))
958 goto Lnomatch;
959
960 /* Check for match with function parameter T...
961 */
962 Type *tb = fparam->type->toBasetype();
963 switch (tb->ty)
964 {
965 // Perhaps we can do better with this, see TypeFunction::callMatch()
966 case Tsarray:
967 { TypeSArray *tsa = (TypeSArray *)tb;
968 integer_t sz = tsa->dim->toInteger();
969 if (sz != nfargs - i)
970 goto Lnomatch;
971 }
972 case Tarray:
973 { TypeArray *ta = (TypeArray *)tb;
974 for (; i < nfargs; i++)
975 {
976 Expression *arg = (Expression *)fargs->data[i];
977 assert(arg);
978 MATCH m;
979 /* If lazy array of delegates,
980 * convert arg(s) to delegate(s)
981 */
982 Type *tret = fparam->isLazyArray();
983 if (tret)
984 {
985 if (ta->next->equals(arg->type))
986 { m = MATCHexact;
987 }
988 else
989 {
990 m = arg->implicitConvTo(tret);
991 if (m == MATCHnomatch)
992 {
993 if (tret->toBasetype()->ty == Tvoid)
994 m = MATCHconvert;
995 }
996 }
997 }
998 else
999 {
1000 m = arg->type->deduceType(scope, ta->next, parameters, &dedtypes);
1001 //m = arg->implicitConvTo(ta->next);
1002 }
1003 if (m == MATCHnomatch)
1004 goto Lnomatch;
1005 if (m < match)
1006 match = m;
1007 }
1008 goto Lmatch;
1009 }
1010 case Tclass:
1011 case Tident:
1012 goto Lmatch;
1013
1014 default:
1015 goto Lnomatch;
1016 }
1017 }
1018
1019 Lmatch:
1020
1021 /* Fill in any missing arguments with their defaults.
1022 */
1023 for (i = nargsi; i < dedargs->dim; i++)
1024 {
1025 TemplateParameter *tp = (TemplateParameter *)parameters->data[i];
1026 //printf("tp[%d] = %s\n", i, tp->ident->toChars());
1027 /* For T:T*, the dedargs is the T*, dedtypes is the T
1028 * But for function templates, we really need them to match
1029 */
1030 Object *oarg = (Object *)dedargs->data[i];
1031 Object *oded = (Object *)dedtypes.data[i];
1032 //printf("1dedargs[%d] = %p, dedtypes[%d] = %p\n", i, oarg, i, oded);
1033 if (!oarg)
1034 {
1035 if (oded)
1036 {
1037 if (tp->specialization())
1038 { /* The specialization can work as long as afterwards
1039 * the oded == oarg
1040 */
1041 Declaration *sparam;
1042 dedargs->data[i] = (void *)oded;
1043 MATCH m2 = tp->matchArg(paramscope, dedargs, i, parameters, &dedtypes, &sparam, 0);
1044 //printf("m2 = %d\n", m2);
1045 if (!m2)
1046 goto Lnomatch;
1047 if (m2 < match)
1048 match = m2; // pick worst match
1049 if (dedtypes.data[i] != oded)
1050 error("specialization not allowed for deduced parameter %s", tp->ident->toChars());
1051 }
1052 }
1053 else
1054 { oded = tp->defaultArg(loc, paramscope);
1055 if (!oded)
1056 goto Lnomatch;
1057 }
1058 declareParameter(paramscope, tp, oded);
1059 dedargs->data[i] = (void *)oded;
1060 }
1061 }
1062
1063 if (constraint)
1064 { /* Check to see if constraint is satisfied.
1065 */
1066 Expression *e = constraint->syntaxCopy();
1067 paramscope->flags |= SCOPEstaticif;
1068 e = e->semantic(paramscope);
1069 e = e->optimize(WANTvalue | WANTinterpret);
1070 if (e->isBool(TRUE))
1071 ;
1072 else if (e->isBool(FALSE))
1073 goto Lnomatch;
1074 else
1075 {
1076 e->error("constraint %s is not constant or does not evaluate to a bool", e->toChars());
1077 }
1078 }
1079
1080
1081 #if 0
1082 for (i = 0; i < dedargs->dim; i++)
1083 { Type *t = (Type *)dedargs->data[i];
1084 printf("\tdedargs[%d] = %d, %s\n", i, t->dyncast(), t->toChars());
1085 }
1086 #endif
1087
1088 paramscope->pop();
1089 //printf("\tmatch %d\n", match);
1090 return match;
1091
1092 Lnomatch:
1093 paramscope->pop();
1094 //printf("\tnomatch\n");
1095 return MATCHnomatch;
1096 }
1097
1098 /**************************************************
1099 * Declare template parameter tp with value o, and install it in the scope sc.
1100 */
1101
1102 void TemplateDeclaration::declareParameter(Scope *sc, TemplateParameter *tp, Object *o)
1103 {
1104 //printf("TemplateDeclaration::declareParameter('%s', o = %p)\n", tp->ident->toChars(), o);
1105
1106 Type *targ = isType(o);
1107 Expression *ea = isExpression(o);
1108 Dsymbol *sa = isDsymbol(o);
1109 Tuple *va = isTuple(o);
1110
1111 Dsymbol *s;
1112
1113 if (targ)
1114 {
1115 //printf("type %s\n", targ->toChars());
1116 s = new AliasDeclaration(0, tp->ident, targ);
1117 }
1118 else if (sa)
1119 {
1120 //printf("Alias %s %s;\n", sa->ident->toChars(), tp->ident->toChars());
1121 s = new AliasDeclaration(0, tp->ident, sa);
1122 }
1123 else if (ea)
1124 {
1125 // tdtypes.data[i] always matches ea here
1126 Initializer *init = new ExpInitializer(loc, ea);
1127 TemplateValueParameter *tvp = tp->isTemplateValueParameter();
1128
1129 Type *t = tvp ? tvp->valType : NULL;
1130
1131 VarDeclaration *v = new VarDeclaration(loc, t, tp->ident, init);
1132 v->storage_class = STCmanifest;
1133 s = v;
1134 }
1135 else if (va)
1136 {
1137 //printf("\ttuple\n");
1138 s = new TupleDeclaration(loc, tp->ident, &va->objects);
1139 }
1140 else
1141 {
1142 #ifdef DEBUG
1143 o->print();
1144 #endif
1145 assert(0);
1146 }
1147 if (!sc->insert(s))
1148 error("declaration %s is already defined", tp->ident->toChars());
1149 s->semantic(sc);
1150 }
1151
1152 /**************************************
1153 * Determine if TemplateDeclaration is variadic.
1154 */
1155
1156 TemplateTupleParameter *isVariadic(TemplateParameters *parameters)
1157 { size_t dim = parameters->dim;
1158 TemplateTupleParameter *tp = NULL;
1159
1160 if (dim)
1161 tp = ((TemplateParameter *)parameters->data[dim - 1])->isTemplateTupleParameter();
1162 return tp;
1163 }
1164
1165 TemplateTupleParameter *TemplateDeclaration::isVariadic()
1166 {
1167 return ::isVariadic(parameters);
1168 }
1169
1170 /***********************************
1171 * We can overload templates.
1172 */
1173
1174 int TemplateDeclaration::isOverloadable()
1175 {
1176 return 1;
1177 }
1178
1179 /*************************************************
1180 * Given function arguments, figure out which template function
1181 * to expand, and return that function.
1182 * If no match, give error message and return NULL.
1183 * Input:
1184 * sc instantiation scope
1185 * loc instantiation location
1186 * targsi initial list of template arguments
1187 * ethis if !NULL, the 'this' pointer argument
1188 * fargs arguments to function
1189 * flags 1: do not issue error message on no match, just return NULL
1190 */
1191
1192 FuncDeclaration *TemplateDeclaration::deduceFunctionTemplate(Scope *sc, Loc loc,
1193 Objects *targsi, Expression *ethis, Expressions *fargs, int flags)
1194 {
1195 MATCH m_best = MATCHnomatch;
1196 TemplateDeclaration *td_ambig = NULL;
1197 TemplateDeclaration *td_best = NULL;
1198 Objects *tdargs = new Objects();
1199 TemplateInstance *ti;
1200 FuncDeclaration *fd;
1201
1202 #if 0
1203 printf("TemplateDeclaration::deduceFunctionTemplate() %s\n", toChars());
1204 printf(" targsi:\n");
1205 if (targsi)
1206 { for (int i = 0; i < targsi->dim; i++)
1207 { Object *arg = (Object *)targsi->data[i];
1208 printf("\t%s\n", arg->toChars());
1209 }
1210 }
1211 printf(" fargs:\n");
1212 for (int i = 0; i < fargs->dim; i++)
1213 { Expression *arg = (Expression *)fargs->data[i];
1214 printf("\t%s %s\n", arg->type->toChars(), arg->toChars());
1215 //printf("\tty = %d\n", arg->type->ty);
1216 }
1217 #endif
1218
1219 for (TemplateDeclaration *td = this; td; td = td->overnext)
1220 {
1221 if (!td->scope)
1222 {
1223 error("forward reference to template %s", td->toChars());
1224 goto Lerror;
1225 }
1226 if (!td->onemember || !td->onemember->toAlias()->isFuncDeclaration())
1227 {
1228 error("is not a function template");
1229 goto Lerror;
1230 }
1231
1232 MATCH m;
1233 Objects dedargs;
1234
1235 m = td->deduceFunctionTemplateMatch(loc, targsi, ethis, fargs, &dedargs);
1236 //printf("deduceFunctionTemplateMatch = %d\n", m);
1237 if (!m) // if no match
1238 continue;
1239
1240 if (m < m_best)
1241 goto Ltd_best;
1242 if (m > m_best)
1243 goto Ltd;
1244
1245 {
1246 // Disambiguate by picking the most specialized TemplateDeclaration
1247 MATCH c1 = td->leastAsSpecialized(td_best);
1248 MATCH c2 = td_best->leastAsSpecialized(td);
1249 //printf("c1 = %d, c2 = %d\n", c1, c2);
1250
1251 if (c1 > c2)
1252 goto Ltd;
1253 else if (c1 < c2)
1254 goto Ltd_best;
1255 else
1256 goto Lambig;
1257 }
1258
1259 Lambig: // td_best and td are ambiguous
1260 td_ambig = td;
1261 continue;
1262
1263 Ltd_best: // td_best is the best match so far
1264 td_ambig = NULL;
1265 continue;
1266
1267 Ltd: // td is the new best match
1268 td_ambig = NULL;
1269 assert((size_t)td->scope > 0x10000);
1270 td_best = td;
1271 m_best = m;
1272 tdargs->setDim(dedargs.dim);
1273 memcpy(tdargs->data, dedargs.data, tdargs->dim * sizeof(void *));
1274 continue;
1275 }
1276 if (!td_best)
1277 {
1278 if (!(flags & 1))
1279 error(loc, "does not match any function template declaration");
1280 goto Lerror;
1281 }
1282 if (td_ambig)
1283 {
1284 error(loc, "matches more than one function template declaration:\n %s\nand:\n %s",
1285 td_best->toChars(), td_ambig->toChars());
1286 }
1287
1288 /* The best match is td_best with arguments tdargs.
1289 * Now instantiate the template.
1290 */
1291 assert((size_t)td_best->scope > 0x10000);
1292 ti = new TemplateInstance(loc, td_best, tdargs);
1293 ti->semantic(sc);
1294 fd = ti->toAlias()->isFuncDeclaration();
1295 if (!fd)
1296 goto Lerror;
1297 return fd;
1298
1299 Lerror:
1300 if (!(flags & 1))
1301 {
1302 HdrGenState hgs;
1303
1304 OutBuffer bufa;
1305 Objects *args = targsi;
1306 if (args)
1307 { for (int i = 0; i < args->dim; i++)
1308 {
1309 if (i)
1310 bufa.writeByte(',');
1311 Object *oarg = (Object *)args->data[i];
1312 ObjectToCBuffer(&bufa, &hgs, oarg);
1313 }
1314 }
1315
1316 OutBuffer buf;
1317 argExpTypesToCBuffer(&buf, fargs, &hgs);
1318
1319 error(loc, "cannot deduce template function from argument types !(%s)(%s)",
1320 bufa.toChars(), buf.toChars());
1321 }
1322 return NULL;
1323 }
1324
1325 void TemplateDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
1326 {
1327 #if 0 // Should handle template functions
1328 if (onemember && onemember->isFuncDeclaration())
1329 buf->writestring("foo ");
1330 #endif
1331 buf->writestring(kind());
1332 buf->writeByte(' ');
1333 buf->writestring(ident->toChars());
1334 buf->writeByte('(');
1335 for (int i = 0; i < parameters->dim; i++)
1336 {
1337 TemplateParameter *tp = (TemplateParameter *)parameters->data[i];
1338 if (hgs->ddoc)
1339 tp = (TemplateParameter *)origParameters->data[i];
1340 if (i)
1341 buf->writeByte(',');
1342 tp->toCBuffer(buf, hgs);
1343 }
1344 buf->writeByte(')');
1345
1346 if (constraint)
1347 { buf->writestring(" if (");
1348 constraint->toCBuffer(buf, hgs);
1349 buf->writeByte(')');
1350 }
1351
1352 if (hgs->hdrgen)
1353 {
1354 hgs->tpltMember++;
1355 buf->writenl();
1356 buf->writebyte('{');
1357 buf->writenl();
1358 for (int i = 0; i < members->dim; i++)
1359 {
1360 Dsymbol *s = (Dsymbol *)members->data[i];
1361 s->toCBuffer(buf, hgs);
1362 }
1363 buf->writebyte('}');
1364 buf->writenl();
1365 hgs->tpltMember--;
1366 }
1367 }
1368
1369
1370 char *TemplateDeclaration::toChars()
1371 { OutBuffer buf;
1372 HdrGenState hgs;
1373
1374 memset(&hgs, 0, sizeof(hgs));
1375 buf.writestring(ident->toChars());
1376 buf.writeByte('(');
1377 for (int i = 0; i < parameters->dim; i++)
1378 {
1379 TemplateParameter *tp = (TemplateParameter *)parameters->data[i];
1380 if (i)
1381 buf.writeByte(',');
1382 tp->toCBuffer(&buf, &hgs);
1383 }
1384 buf.writeByte(')');
1385
1386 if (constraint)
1387 { buf.writestring(" if (");
1388 constraint->toCBuffer(&buf, &hgs);
1389 buf.writeByte(')');
1390 }
1391
1392 buf.writeByte(0);
1393 return (char *)buf.extractData();
1394 }
1395
1396 /* ======================== Type ============================================ */
1397
1398 /****
1399 * Given an identifier, figure out which TemplateParameter it is.
1400 * Return -1 if not found.
1401 */
1402
1403 int templateIdentifierLookup(Identifier *id, TemplateParameters *parameters)
1404 {
1405 for (size_t i = 0; i < parameters->dim; i++)
1406 { TemplateParameter *tp = (TemplateParameter *)parameters->data[i];
1407
1408 if (tp->ident->equals(id))
1409 return i;
1410 }
1411 return -1;
1412 }
1413
1414 int templateParameterLookup(Type *tparam, TemplateParameters *parameters)
1415 {
1416 assert(tparam->ty == Tident);
1417 TypeIdentifier *tident = (TypeIdentifier *)tparam;
1418 //printf("\ttident = '%s'\n", tident->toChars());
1419 if (tident->idents.dim == 0)
1420 {
1421 return templateIdentifierLookup(tident->ident, parameters);
1422 }
1423 return -1;
1424 }
1425
1426 /* These form the heart of template argument deduction.
1427 * Given 'this' being the type argument to the template instance,
1428 * it is matched against the template declaration parameter specialization
1429 * 'tparam' to determine the type to be used for the parameter.
1430 * Example:
1431 * template Foo(T:T*) // template declaration
1432 * Foo!(int*) // template instantiation
1433 * Input:
1434 * this = int*
1435 * tparam = T
1436 * parameters = [ T:T* ] // Array of TemplateParameter's
1437 * Output:
1438 * dedtypes = [ int ] // Array of Expression/Type's
1439 */
1440
1441 MATCH Type::deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters,
1442 Objects *dedtypes)
1443 {
1444 #if 0
1445 printf("Type::deduceType()\n");
1446 printf("\tthis = %d, ", ty); print();
1447 printf("\ttparam = %d, ", tparam->ty); tparam->print();
1448 #endif
1449 if (!tparam)
1450 goto Lnomatch;
1451
1452 if (this == tparam)
1453 goto Lexact;
1454
1455 if (tparam->ty == Tident)
1456 {
1457 // Determine which parameter tparam is
1458 int i = templateParameterLookup(tparam, parameters);
1459 if (i == -1)
1460 {
1461 if (!sc)
1462 goto Lnomatch;
1463
1464 /* Need a loc to go with the semantic routine.
1465 */
1466 Loc loc;
1467 if (parameters->dim)
1468 {
1469 TemplateParameter *tp = (TemplateParameter *)parameters->data[0];
1470 loc = tp->loc;
1471 }
1472
1473 /* BUG: what if tparam is a template instance, that
1474 * has as an argument another Tident?
1475 */
1476 tparam = tparam->semantic(loc, sc);
1477 assert(tparam->ty != Tident);
1478 return deduceType(sc, tparam, parameters, dedtypes);
1479 }
1480
1481 TemplateParameter *tp = (TemplateParameter *)parameters->data[i];
1482
1483 // Found the corresponding parameter tp
1484 if (!tp->isTemplateTypeParameter())
1485 goto Lnomatch;
1486 Type *tt = this;
1487 Type *at = (Type *)dedtypes->data[i];
1488
1489 // 3*3 == 9 cases
1490 if (tparam->isMutable())
1491 { // foo(U:U) T => T
1492 // foo(U:U) const(T) => const(T)
1493 // foo(U:U) invariant(T) => invariant(T)
1494 if (!at)
1495 { dedtypes->data[i] = (void *)this;
1496 goto Lexact;
1497 }
1498 }
1499 else if (mod == tparam->mod)
1500 { // foo(U:const(U)) const(T) => T
1501 // foo(U:invariant(U)) invariant(T) => T
1502 tt = mutableOf();
1503 if (!at)
1504 { dedtypes->data[i] = (void *)tt;
1505 goto Lexact;
1506 }
1507 }
1508 else if (tparam->isConst())
1509 { // foo(U:const(U)) T => T
1510 // foo(U:const(U)) invariant(T) => T
1511 tt = mutableOf();
1512 if (!at)
1513 { dedtypes->data[i] = (void *)tt;
1514 goto Lconst;
1515 }
1516 }
1517 else
1518 { // foo(U:invariant(U)) T => nomatch
1519 // foo(U:invariant(U)) const(T) => nomatch
1520 if (!at)
1521 goto Lnomatch;
1522 }
1523
1524 if (tt->equals(at))
1525 goto Lexact;
1526 else if (tt->ty == Tclass && at->ty == Tclass)
1527 {
1528 return tt->implicitConvTo(at);
1529 }
1530 else if (tt->ty == Tsarray && at->ty == Tarray &&
1531 tt->nextOf()->implicitConvTo(at->nextOf()) >= MATCHconst)
1532 {
1533 goto Lexact;
1534 }
1535 else
1536 goto Lnomatch;
1537 }
1538
1539 if (ty != tparam->ty)
1540 return implicitConvTo(tparam);
1541 // goto Lnomatch;
1542
1543 if (nextOf())
1544 return nextOf()->deduceType(sc, tparam->nextOf(), parameters, dedtypes);
1545
1546 Lexact:
1547 return MATCHexact;
1548
1549 Lnomatch:
1550 return MATCHnomatch;
1551
1552 Lconst:
1553 return MATCHconst;
1554 }
1555
1556 MATCH TypeSArray::deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters,
1557 Objects *dedtypes)
1558 {
1559 #if 0
1560 printf("TypeSArray::deduceType()\n");
1561 printf("\tthis = %d, ", ty); print();
1562 printf("\ttparam = %d, ", tparam->ty); tparam->print();
1563 #endif
1564
1565 // Extra check that array dimensions must match
1566 if (tparam)
1567 {
1568 if (tparam->ty == Tsarray)
1569 {
1570 TypeSArray *tp = (TypeSArray *)tparam;
1571
1572 if (tp->dim->op == TOKvar &&
1573 ((VarExp *)tp->dim)->var->storage_class & STCtemplateparameter)
1574 { int i = templateIdentifierLookup(((VarExp *)tp->dim)->var->ident, parameters);
1575 // This code matches code in TypeInstance::deduceType()
1576 if (i == -1)
1577 goto Lnomatch;
1578 TemplateParameter *tp = (TemplateParameter *)parameters->data[i];
1579 TemplateValueParameter *tvp = tp->isTemplateValueParameter();
1580 if (!tvp)
1581 goto Lnomatch;
1582 Expression *e = (Expression *)dedtypes->data[i];
1583 if (e)
1584 {
1585 if (!dim->equals(e))
1586 goto Lnomatch;
1587 }
1588 else
1589 { Type *vt = tvp->valType->semantic(0, sc);
1590 MATCH m = (MATCH)dim->implicitConvTo(vt);
1591 if (!m)
1592 goto Lnomatch;
1593 dedtypes->data[i] = dim;
1594 }
1595 }
1596 else if (dim->toInteger() != tp->dim->toInteger())
1597 return MATCHnomatch;
1598 }
1599 else if (tparam->ty == Taarray)
1600 {
1601 TypeAArray *tp = (TypeAArray *)tparam;
1602 if (tp->index->ty == Tident)
1603 { TypeIdentifier *tident = (TypeIdentifier *)tp->index;
1604
1605 if (tident->idents.dim == 0)
1606 { Identifier *id = tident->ident;
1607
1608 for (size_t i = 0; i < parameters->dim; i++)
1609 {
1610 TemplateParameter *tp = (TemplateParameter *)parameters->data[i];
1611
1612 if (tp->ident->equals(id))
1613 { // Found the corresponding template parameter
1614 TemplateValueParameter *tvp = tp->isTemplateValueParameter();
1615 if (!tvp || !tvp->valType->isintegral())
1616 goto Lnomatch;
1617
1618 if (dedtypes->data[i])
1619 {
1620 if (!dim->equals((Object *)dedtypes->data[i]))
1621 goto Lnomatch;
1622 }
1623 else
1624 { dedtypes->data[i] = (void *)dim;
1625 }
1626 return next->deduceType(sc, tparam->nextOf(), parameters, dedtypes);
1627 }
1628 }
1629 }
1630 }
1631 }
1632 else if (tparam->ty == Tarray)
1633 { MATCH m;
1634
1635 m = next->deduceType(sc, tparam->nextOf(), parameters, dedtypes);
1636 if (m == MATCHexact)
1637 m = MATCHconvert;
1638 return m;
1639 }
1640 }
1641 return Type::deduceType(sc, tparam, parameters, dedtypes);
1642
1643 Lnomatch:
1644 return MATCHnomatch;
1645 }
1646
1647 MATCH TypeAArray::deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes)
1648 {
1649 #if 0
1650 printf("TypeAArray::deduceType()\n");
1651 printf("\tthis = %d, ", ty); print();
1652 printf("\ttparam = %d, ", tparam->ty); tparam->print();
1653 #endif
1654
1655 // Extra check that index type must match
1656 if (tparam && tparam->ty == Taarray)
1657 {
1658 TypeAArray *tp = (TypeAArray *)tparam;
1659 if (!index->deduceType(sc, tp->index, parameters, dedtypes))
1660 {
1661 return MATCHnomatch;
1662 }
1663 }
1664 return Type::deduceType(sc, tparam, parameters, dedtypes);
1665 }
1666
1667 MATCH TypeFunction::deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes)
1668 {
1669 //printf("TypeFunction::deduceType()\n");
1670 //printf("\tthis = %d, ", ty); print();
1671 //printf("\ttparam = %d, ", tparam->ty); tparam->print();
1672
1673 // Extra check that function characteristics must match
1674 if (tparam && tparam->ty == Tfunction)
1675 {
1676 TypeFunction *tp = (TypeFunction *)tparam;
1677 if (varargs != tp->varargs ||
1678 linkage != tp->linkage)
1679 return MATCHnomatch;
1680
1681 size_t nfargs = Argument::dim(this->parameters);
1682 size_t nfparams = Argument::dim(tp->parameters);
1683
1684 /* See if tuple match
1685 */
1686 if (nfparams > 0 && nfargs >= nfparams - 1)
1687 {
1688 /* See if 'A' of the template parameter matches 'A'
1689 * of the type of the last function parameter.
1690 */
1691 Argument *fparam = (Argument *)tp->parameters->data[nfparams - 1];
1692 if (fparam->type->ty != Tident)
1693 goto L1;
1694 TypeIdentifier *tid = (TypeIdentifier *)fparam->type;
1695 if (tid->idents.dim)
1696 goto L1;
1697
1698 /* Look through parameters to find tuple matching tid->ident
1699 */
1700 size_t tupi = 0;
1701 for (; 1; tupi++)
1702 { if (tupi == parameters->dim)
1703 goto L1;
1704 TemplateParameter *t = (TemplateParameter *)parameters->data[tupi];
1705 TemplateTupleParameter *tup = t->isTemplateTupleParameter();
1706 if (tup && tup->ident->equals(tid->ident))
1707 break;
1708 }
1709
1710 /* The types of the function arguments [nfparams - 1 .. nfargs]
1711 * now form the tuple argument.
1712 */
1713 int tuple_dim = nfargs - (nfparams - 1);
1714
1715 /* See if existing tuple, and whether it matches or not
1716 */
1717 Object *o = (Object *)dedtypes->data[tupi];
1718 if (o)
1719 { // Existing deduced argument must be a tuple, and must match
1720 Tuple *t = isTuple(o);
1721 if (!t || t->objects.dim != tuple_dim)
1722 return MATCHnomatch;
1723 for (size_t i = 0; i < tuple_dim; i++)
1724 { Argument *arg = Argument::getNth(this->parameters, nfparams - 1 + i);
1725 if (!arg->type->equals((Object *)t->objects.data[i]))
1726 return MATCHnomatch;
1727 }
1728 }
1729 else
1730 { // Create new tuple
1731 Tuple *t = new Tuple();
1732 t->objects.setDim(tuple_dim);
1733 for (size_t i = 0; i < tuple_dim; i++)
1734 { Argument *arg = Argument::getNth(this->parameters, nfparams - 1 + i);
1735 t->objects.data[i] = (void *)arg->type;
1736 }
1737 dedtypes->data[tupi] = (void *)t;
1738 }
1739 nfparams--; // don't consider the last parameter for type deduction
1740 goto L2;
1741 }
1742
1743 L1:
1744 if (nfargs != nfparams)
1745 return MATCHnomatch;
1746 L2:
1747 for (size_t i = 0; i < nfparams; i++)
1748 {
1749 Argument *a = Argument::getNth(this->parameters, i);
1750 Argument *ap = Argument::getNth(tp->parameters, i);
1751 if (a->storageClass != ap->storageClass ||
1752 !a->type->deduceType(sc, ap->type, parameters, dedtypes))
1753 return MATCHnomatch;
1754 }
1755 }
1756 return Type::deduceType(sc, tparam, parameters, dedtypes);
1757 }
1758
1759 MATCH TypeIdentifier::deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes)
1760 {
1761 // Extra check
1762 if (tparam && tparam->ty == Tident)
1763 {
1764 TypeIdentifier *tp = (TypeIdentifier *)tparam;
1765
1766 for (int i = 0; i < idents.dim; i++)
1767 {
1768 Identifier *id1 = (Identifier *)idents.data[i];
1769 Identifier *id2 = (Identifier *)tp->idents.data[i];
1770
1771 if (!id1->equals(id2))
1772 return MATCHnomatch;
1773 }
1774 }
1775 return Type::deduceType(sc, tparam, parameters, dedtypes);
1776 }
1777
1778 MATCH TypeInstance::deduceType(Scope *sc,
1779 Type *tparam, TemplateParameters *parameters,
1780 Objects *dedtypes)
1781 {
1782 //printf("TypeInstance::deduceType(tparam = %s) %s\n", tparam->toChars(), toChars());
1783 //printf("\ttparam = %d, ", tparam->ty); tparam->print();
1784
1785 // Extra check
1786 if (tparam && tparam->ty == Tinstance)
1787 {
1788 TypeInstance *tp = (TypeInstance *)tparam;
1789
1790 //printf("tempinst->tempdecl = %p\n", tempinst->tempdecl);
1791 //printf("tp->tempinst->tempdecl = %p\n", tp->tempinst->tempdecl);
1792 if (!tp->tempinst->tempdecl)
1793 { //printf("tp->tempinst->name = '%s'\n", tp->tempinst->name->toChars());
1794 if (!tp->tempinst->name->equals(tempinst->name))
1795 {
1796 /* Handle case of:
1797 * template Foo(T : sa!(T), alias sa)
1798 */
1799 int i = templateIdentifierLookup(tp->tempinst->name, parameters);
1800 if (i == -1)
1801 { /* Didn't find it as a parameter identifier. Try looking
1802 * it up and seeing if is an alias. See Bugzilla 1454
1803 */
1804 Dsymbol *s = tempinst->tempdecl->scope->search(0, tp->tempinst->name, NULL);
1805 if (s)
1806 {
1807 s = s->toAlias();
1808 TemplateDeclaration *td = s->isTemplateDeclaration();
1809 if (td && td == tempinst->tempdecl)
1810 goto L2;
1811 }
1812 goto Lnomatch;
1813 }
1814 TemplateParameter *tpx = (TemplateParameter *)parameters->data[i];
1815 // This logic duplicates tpx->matchArg()
1816 TemplateAliasParameter *ta = tpx->isTemplateAliasParameter();
1817 if (!ta)
1818 goto Lnomatch;
1819 Object *sa = tempinst->tempdecl;
1820 if (!sa)
1821 goto Lnomatch;
1822 if (ta->specAlias && sa != ta->specAlias)
1823 goto Lnomatch;
1824 if (dedtypes->data[i])
1825 { // Must match already deduced symbol
1826 Object *s = (Object *)dedtypes->data[i];
1827
1828 if (s != sa)
1829 goto Lnomatch;
1830 }
1831 dedtypes->data[i] = sa;
1832 }
1833 }
1834 else if (tempinst->tempdecl != tp->tempinst->tempdecl)
1835 goto Lnomatch;
1836
1837 L2:
1838 if (tempinst->tiargs->dim != tp->tempinst->tiargs->dim)
1839 goto Lnomatch;
1840
1841 for (int i = 0; i < tempinst->tiargs->dim; i++)
1842 {
1843 //printf("\ttest: tempinst->tiargs[%d]\n", i);
1844 int j;
1845 Object *o1 = (Object *)tempinst->tiargs->data[i];
1846 Object *o2 = (Object *)tp->tempinst->tiargs->data[i];
1847
1848 Type *t1 = isType(o1);
1849 Type *t2 = isType(o2);
1850
1851 Expression *e1 = isExpression(o1);
1852 Expression *e2 = isExpression(o2);
1853
1854 #if 0
1855 if (t1) printf("t1 = %s\n", t1->toChars());
1856 if (t2) printf("t2 = %s\n", t2->toChars());
1857 if (e1) printf("e1 = %s\n", e1->toChars());
1858 if (e2) printf("e2 = %s\n", e2->toChars());
1859 #endif
1860
1861 if (t1 && t2)
1862 {
1863 if (!t1->deduceType(sc, t2, parameters, dedtypes))
1864 goto Lnomatch;
1865 }
1866 else if (e1 && e2)
1867 {
1868 if (!e1->equals(e2))
1869 { if (e2->op == TOKvar)
1870 {
1871 /*
1872 * (T:Number!(e2), int e2)
1873 */
1874 j = templateIdentifierLookup(((VarExp *)e2)->var->ident, parameters);
1875 goto L1;
1876 }
1877 goto Lnomatch;
1878 }
1879 }
1880 else if (e1 && t2 && t2->ty == Tident)
1881 {
1882 j = templateParameterLookup(t2, parameters);
1883 L1:
1884 if (j == -1)
1885 goto Lnomatch;
1886 TemplateParameter *tp = (TemplateParameter *)parameters->data[j];
1887 // BUG: use tp->matchArg() instead of the following
1888 TemplateValueParameter *tv = tp->isTemplateValueParameter();
1889 if (!tv)
1890 goto Lnomatch;
1891 Expression *e = (Expression *)dedtypes->data[j];
1892 if (e)
1893 {
1894 if (!e1->equals(e))
1895 goto Lnomatch;
1896 }
1897 else
1898 { Type *vt = tv->valType->semantic(0, sc);
1899 MATCH m = (MATCH)e1->implicitConvTo(vt);
1900 if (!m)
1901 goto Lnomatch;
1902 dedtypes->data[j] = e1;
1903 }
1904 }
1905 // BUG: Need to handle alias and tuple parameters
1906 else
1907 goto Lnomatch;
1908 }
1909 }
1910 return Type::deduceType(sc, tparam, parameters, dedtypes);
1911
1912 Lnomatch:
1913 return MATCHnomatch;
1914 }
1915
1916 MATCH TypeStruct::deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes)
1917 {
1918 //printf("TypeStruct::deduceType()\n");
1919 //printf("\tthis->parent = %s, ", sym->parent->toChars()); print();
1920 //printf("\ttparam = %d, ", tparam->ty); tparam->print();
1921
1922 /* If this struct is a template struct, and we're matching
1923 * it against a template instance, convert the struct type
1924 * to a template instance, too, and try again.
1925 */
1926 TemplateInstance *ti = sym->parent->isTemplateInstance();
1927
1928 if (tparam && tparam->ty == Tinstance)
1929 {
1930 if (ti && ti->toAlias() == sym)
1931 {
1932 TypeInstance *t = new TypeInstance(0, ti);
1933 return t->deduceType(sc, tparam, parameters, dedtypes);
1934 }
1935
1936 /* Match things like:
1937 * S!(T).foo
1938 */
1939 TypeInstance *tpi = (TypeInstance *)tparam;
1940 if (tpi->idents.dim)
1941 { Identifier *id = (Identifier *)tpi->idents.data[tpi->idents.dim - 1];
1942 if (id->dyncast() == DYNCAST_IDENTIFIER && sym->ident->equals(id))
1943 {
1944 Type *tparent = sym->parent->getType();
1945 if (tparent)
1946 {
1947 /* Slice off the .foo in S!(T).foo
1948 */
1949 tpi->idents.dim--;
1950 MATCH m = tparent->deduceType(sc, tpi, parameters, dedtypes);
1951 tpi->idents.dim++;
1952 return m;
1953 }
1954 }
1955 }
1956 }
1957
1958 // Extra check
1959 if (tparam && tparam->ty == Tstruct)
1960 {
1961 TypeStruct *tp = (TypeStruct *)tparam;
1962
1963 if (sym != tp->sym)
1964 return MATCHnomatch;
1965 }
1966 return Type::deduceType(sc, tparam, parameters, dedtypes);
1967 }
1968
1969 MATCH TypeEnum::deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes)
1970 {
1971 // Extra check
1972 if (tparam && tparam->ty == Tenum)
1973 {
1974 TypeEnum *tp = (TypeEnum *)tparam;
1975
1976 if (sym != tp->sym)
1977 return MATCHnomatch;
1978 }
1979 return Type::deduceType(sc, tparam, parameters, dedtypes);
1980 }
1981
1982 MATCH TypeTypedef::deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes)
1983 {
1984 // Extra check
1985 if (tparam && tparam->ty == Ttypedef)
1986 {
1987 TypeTypedef *tp = (TypeTypedef *)tparam;
1988
1989 if (sym != tp->sym)
1990 return MATCHnomatch;
1991 }
1992 return Type::deduceType(sc, tparam, parameters, dedtypes);
1993 }
1994
1995 MATCH TypeClass::deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes)
1996 {
1997 //printf("TypeClass::deduceType(this = %s)\n", toChars());
1998
1999 /* If this class is a template class, and we're matching
2000 * it against a template instance, convert the class type
2001 * to a template instance, too, and try again.
2002 */
2003 TemplateInstance *ti = sym->parent->isTemplateInstance();
2004
2005 if (tparam && tparam->ty == Tinstance)
2006 {
2007 if (ti && ti->toAlias() == sym)
2008 {
2009 TypeInstance *t = new TypeInstance(0, ti);
2010 return t->deduceType(sc, tparam, parameters, dedtypes);
2011 }
2012
2013 /* Match things like:
2014 * S!(T).foo
2015 */
2016 TypeInstance *tpi = (TypeInstance *)tparam;
2017 if (tpi->idents.dim)
2018 { Identifier *id = (Identifier *)tpi->idents.data[tpi->idents.dim - 1];
2019 if (id->dyncast() == DYNCAST_IDENTIFIER && sym->ident->equals(id))
2020 {
2021 Type *tparent = sym->parent->getType();
2022 if (tparent)
2023 {
2024 /* Slice off the .foo in S!(T).foo
2025 */
2026 tpi->idents.dim--;
2027 MATCH m = tparent->deduceType(sc, tpi, parameters, dedtypes);
2028 tpi->idents.dim++;
2029 return m;
2030 }
2031 }
2032 }
2033 }
2034
2035 // Extra check
2036 if (tparam && tparam->ty == Tclass)
2037 {
2038 TypeClass *tp = (TypeClass *)tparam;
2039
2040 //printf("\t%d\n", (MATCH) implicitConvTo(tp));
2041 return implicitConvTo(tp);
2042 }
2043 return Type::deduceType(sc, tparam, parameters, dedtypes);
2044 }
2045
2046 /* ======================== TemplateParameter =============================== */
2047
2048 TemplateParameter::TemplateParameter(Loc loc, Identifier *ident)
2049 {
2050 this->loc = loc;
2051 this->ident = ident;
2052 this->sparam = NULL;
2053 }
2054
2055 TemplateTypeParameter *TemplateParameter::isTemplateTypeParameter()
2056 {
2057 return NULL;
2058 }
2059
2060 TemplateValueParameter *TemplateParameter::isTemplateValueParameter()
2061 {
2062 return NULL;
2063 }
2064
2065 TemplateAliasParameter *TemplateParameter::isTemplateAliasParameter()
2066 {
2067 return NULL;
2068 }
2069
2070 TemplateTupleParameter *TemplateParameter::isTemplateTupleParameter()
2071 {
2072 return NULL;
2073 }
2074
2075 #if DMDV2
2076 TemplateThisParameter *TemplateParameter::isTemplateThisParameter()
2077 {
2078 return NULL;
2079 }
2080 #endif
2081
2082 /* ======================== TemplateTypeParameter =========================== */
2083
2084 // type-parameter
2085
2086 TemplateTypeParameter::TemplateTypeParameter(Loc loc, Identifier *ident, Type *specType,
2087 Type *defaultType)
2088 : TemplateParameter(loc, ident)
2089 {
2090 this->ident = ident;
2091 this->specType = specType;
2092 this->defaultType = defaultType;
2093 }
2094
2095 TemplateTypeParameter *TemplateTypeParameter::isTemplateTypeParameter()
2096 {
2097 return this;
2098 }
2099
2100 TemplateParameter *TemplateTypeParameter::syntaxCopy()
2101 {
2102 TemplateTypeParameter *tp = new TemplateTypeParameter(loc, ident, specType, defaultType);
2103 if (tp->specType)
2104 tp->specType = specType->syntaxCopy();
2105 if (defaultType)
2106 tp->defaultType = defaultType->syntaxCopy();
2107 return tp;
2108 }
2109
2110 void TemplateTypeParameter::declareParameter(Scope *sc)
2111 {
2112 //printf("TemplateTypeParameter::declareParameter('%s')\n", ident->toChars());
2113 TypeIdentifier *ti = new TypeIdentifier(loc, ident);
2114 sparam = new AliasDeclaration(loc, ident, ti);
2115 if (!sc->insert(sparam))
2116 error(loc, "parameter '%s' multiply defined", ident->toChars());
2117 }
2118
2119 void TemplateTypeParameter::semantic(Scope *sc)
2120 {
2121 //printf("TemplateTypeParameter::semantic('%s')\n", ident->toChars());
2122 if (specType)
2123 {
2124 specType = specType->semantic(loc, sc);
2125 }
2126 #if 0 // Don't do semantic() until instantiation
2127 if (defaultType)
2128 {
2129 defaultType = defaultType->semantic(loc, sc);
2130 }
2131 #endif
2132 }
2133
2134 /****************************************
2135 * Determine if two TemplateParameters are the same
2136 * as far as TemplateDeclaration overloading goes.
2137 * Returns:
2138 * 1 match
2139 * 0 no match
2140 */
2141
2142 int TemplateTypeParameter::overloadMatch(TemplateParameter *tp)
2143 {
2144 TemplateTypeParameter *ttp = tp->isTemplateTypeParameter();
2145
2146 if (ttp)
2147 {
2148 if (specType != ttp->specType)
2149 goto Lnomatch;
2150
2151 if (specType && !specType->equals(ttp->specType))
2152 goto Lnomatch;
2153
2154 return 1; // match
2155 }
2156
2157 Lnomatch:
2158 return 0;
2159 }
2160
2161 /*******************************************
2162 * Match to a particular TemplateParameter.
2163 * Input:
2164 * i i'th argument
2165 * tiargs[] actual arguments to template instance
2166 * parameters[] template parameters
2167 * dedtypes[] deduced arguments to template instance
2168 * *psparam set to symbol declared and initialized to dedtypes[i]
2169 * flags 1: don't do 'toHeadMutable()'
2170 */
2171
2172 MATCH TemplateTypeParameter::matchArg(Scope *sc, Objects *tiargs,
2173 int i, TemplateParameters *parameters, Objects *dedtypes,
2174 Declaration **psparam, int flags)
2175 {
2176 //printf("TemplateTypeParameter::matchArg()\n");
2177 Type *t;
2178 Object *oarg;
2179 MATCH m = MATCHexact;
2180 Type *ta;
2181
2182 if (i < tiargs->dim)
2183 oarg = (Object *)tiargs->data[i];
2184 else
2185 { // Get default argument instead
2186 oarg = defaultArg(loc, sc);
2187 if (!oarg)
2188 { assert(i < dedtypes->dim);
2189 // It might have already been deduced
2190 oarg = (Object *)dedtypes->data[i];
2191 if (!oarg)
2192 {
2193 goto Lnomatch;
2194 }
2195 flags |= 1; // already deduced, so don't to toHeadMutable()
2196 }
2197 }
2198
2199 ta = isType(oarg);
2200 if (!ta)
2201 {
2202 //printf("%s %p %p %p\n", oarg->toChars(), isExpression(oarg), isDsymbol(oarg), isTuple(oarg));
2203 goto Lnomatch;
2204 }
2205 //printf("ta is %s\n", ta->toChars());
2206
2207 t = (Type *)dedtypes->data[i];
2208
2209 if (specType)
2210 {
2211 //printf("\tcalling deduceType(): ta is %s, specType is %s\n", ta->toChars(), specType->toChars());
2212 MATCH m2 = ta->deduceType(sc, specType, parameters, dedtypes);
2213 if (m2 == MATCHnomatch)
2214 { //printf("\tfailed deduceType\n");
2215 goto Lnomatch;
2216 }
2217
2218 if (m2 < m)
2219 m = m2;
2220 t = (Type *)dedtypes->data[i];
2221 }
2222 else
2223 {
2224 // So that matches with specializations are better
2225 m = MATCHconvert;
2226
2227 /* This is so that:
2228 * template Foo(T), Foo!(const int), => ta == int
2229 */
2230 // if (!(flags & 1))
2231 // ta = ta->toHeadMutable();
2232
2233 if (t)
2234 { // Must match already deduced type
2235
2236 m = MATCHexact;
2237 if (!t->equals(ta))
2238 { //printf("t = %s ta = %s\n", t->toChars(), ta->toChars());
2239 goto Lnomatch;
2240 }
2241 }
2242 }
2243
2244 if (!t)
2245 {
2246 dedtypes->data[i] = ta;
2247 t = ta;
2248 }
2249 *psparam = new AliasDeclaration(loc, ident, t);
2250 //printf("\tm = %d\n", m);
2251 return m;
2252
2253 Lnomatch:
2254 *psparam = NULL;
2255 //printf("\tm = %d\n", MATCHnomatch);
2256 return MATCHnomatch;
2257 }
2258
2259
2260 void TemplateTypeParameter::print(Object *oarg, Object *oded)
2261 {
2262 printf(" %s\n", ident->toChars());
2263
2264 Type *t = isType(oarg);
2265 Type *ta = isType(oded);
2266
2267 assert(ta);
2268
2269 if (specType)
2270 printf("\tSpecialization: %s\n", specType->toChars());
2271 if (defaultType)
2272 printf("\tDefault: %s\n", defaultType->toChars());
2273 printf("\tArgument: %s\n", t ? t->toChars() : "NULL");
2274 printf("\tDeduced Type: %s\n", ta->toChars());
2275 }
2276
2277
2278 void TemplateTypeParameter::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
2279 {
2280 buf->writestring(ident->toChars());
2281 if (specType)
2282 {
2283 buf->writestring(" : ");
2284 specType->toCBuffer(buf, NULL, hgs);
2285 }
2286 if (defaultType)
2287 {
2288 buf->writestring(" = ");
2289 defaultType->toCBuffer(buf, NULL, hgs);
2290 }
2291 }
2292
2293
2294 void *TemplateTypeParameter::dummyArg()
2295 { Type *t;
2296
2297 if (specType)
2298 t = specType;
2299 else
2300 { // Use this for alias-parameter's too (?)
2301 t = new TypeIdentifier(loc, ident);
2302 }
2303 return (void *)t;
2304 }
2305
2306
2307 Object *TemplateTypeParameter::specialization()
2308 {
2309 return specType;
2310 }
2311
2312
2313 Object *TemplateTypeParameter::defaultArg(Loc loc, Scope *sc)
2314 {
2315 Type *t;
2316
2317 t = defaultType;
2318 if (t)
2319 {
2320 t = t->syntaxCopy();
2321 t = t->semantic(loc, sc);
2322 }
2323 return t;
2324 }
2325
2326 /* ======================== TemplateThisParameter =========================== */
2327
2328 #if DMDV2
2329 // this-parameter
2330
2331 TemplateThisParameter::TemplateThisParameter(Loc loc, Identifier *ident,
2332 Type *specType,
2333 Type *defaultType)
2334 : TemplateTypeParameter(loc, ident, specType, defaultType)
2335 {
2336 }
2337
2338 TemplateThisParameter *TemplateThisParameter::isTemplateThisParameter()
2339 {
2340 return this;
2341 }
2342
2343 TemplateParameter *TemplateThisParameter::syntaxCopy()
2344 {
2345 TemplateThisParameter *tp = new TemplateThisParameter(loc, ident, specType, defaultType);
2346 if (tp->specType)
2347 tp->specType = specType->syntaxCopy();
2348 if (defaultType)
2349 tp->defaultType = defaultType->syntaxCopy();
2350 return tp;
2351 }
2352
2353 void TemplateThisParameter::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
2354 {
2355 buf->writestring("this ");
2356 TemplateTypeParameter::toCBuffer(buf, hgs);
2357 }
2358 #endif
2359
2360 /* ======================== TemplateAliasParameter ========================== */
2361
2362 // alias-parameter
2363
2364 Dsymbol *TemplateAliasParameter::sdummy = NULL;
2365
2366 TemplateAliasParameter::TemplateAliasParameter(Loc loc, Identifier *ident,
2367 Type *specType, Object *specAlias, Object *defaultAlias)
2368 : TemplateParameter(loc, ident)
2369 {
2370 this->ident = ident;
2371 this->specType = specType;
2372 this->specAlias = specAlias;
2373 this->defaultAlias = defaultAlias;
2374 }
2375
2376 TemplateAliasParameter *TemplateAliasParameter::isTemplateAliasParameter()
2377 {
2378 return this;
2379 }
2380
2381 TemplateParameter *TemplateAliasParameter::syntaxCopy()
2382 {
2383 TemplateAliasParameter *tp = new TemplateAliasParameter(loc, ident, specType, specAlias, defaultAlias);
2384 if (tp->specType)
2385 tp->specType = specType->syntaxCopy();
2386 tp->specAlias = objectSyntaxCopy(specAlias);
2387 tp->defaultAlias = objectSyntaxCopy(defaultAlias);
2388 return tp;
2389 }
2390
2391 void TemplateAliasParameter::declareParameter(Scope *sc)
2392 {
2393 TypeIdentifier *ti = new TypeIdentifier(loc, ident);
2394 sparam = new AliasDeclaration(loc, ident, ti);
2395 if (!sc->insert(sparam))
2396 error(loc, "parameter '%s' multiply defined", ident->toChars());
2397 }
2398
2399 Object *aliasParameterSemantic(Loc loc, Scope *sc, Object *o)
2400 {
2401 if (o)
2402 {
2403 Expression *ea = isExpression(o);
2404 Type *ta = isType(o);
2405 if (ta)
2406 { Dsymbol *s = ta->toDsymbol(sc);
2407 if (s)
2408 o = s;
2409 else
2410 o = ta->semantic(loc, sc);
2411 }
2412 else if (ea)
2413 {
2414 ea = ea->semantic(sc);
2415 o = ea->optimize(WANTvalue | WANTinterpret);
2416 }
2417 }
2418 return o;
2419 }
2420
2421 void TemplateAliasParameter::semantic(Scope *sc)
2422 {
2423 if (specType)
2424 {
2425 specType = specType->semantic(loc, sc);
2426 }
2427 specAlias = aliasParameterSemantic(loc, sc, specAlias);
2428 #if 0 // Don't do semantic() until instantiation
2429 if (defaultAlias)
2430 defaultAlias = defaultAlias->semantic(loc, sc);
2431 #endif
2432 }
2433
2434 int TemplateAliasParameter::overloadMatch(TemplateParameter *tp)
2435 {
2436 TemplateAliasParameter *tap = tp->isTemplateAliasParameter();
2437
2438 if (tap)
2439 {
2440 if (specAlias != tap->specAlias)
2441 goto Lnomatch;
2442
2443 return 1; // match
2444 }
2445
2446 Lnomatch:
2447 return 0;
2448 }
2449
2450 MATCH TemplateAliasParameter::matchArg(Scope *sc,
2451 Objects *tiargs, int i, TemplateParameters *parameters,
2452 Objects *dedtypes,
2453 Declaration **psparam, int flags)
2454 {
2455 Object *sa;
2456 Object *oarg;
2457 Expression *ea;
2458 Dsymbol *s;
2459
2460 //printf("TemplateAliasParameter::matchArg()\n");
2461
2462 if (i < tiargs->dim)
2463 oarg = (Object *)tiargs->data[i];
2464 else
2465 { // Get default argument instead
2466 oarg = defaultArg(loc, sc);
2467 if (!oarg)
2468 { assert(i < dedtypes->dim);
2469 // It might have already been deduced
2470 oarg = (Object *)dedtypes->data[i];
2471 if (!oarg)
2472 goto Lnomatch;
2473 }
2474 }
2475
2476 sa = getDsymbol(oarg);
2477 if (sa)
2478 {
2479 /* specType means the alias must be a declaration with a type
2480 * that matches specType.
2481 */
2482 if (specType)
2483 { Declaration *d = ((Dsymbol *)sa)->isDeclaration();
2484 if (!d)
2485 goto Lnomatch;
2486 if (!d->type->equals(specType))
2487 goto Lnomatch;
2488 }
2489 }
2490 else
2491 {
2492 sa = oarg;
2493 ea = isExpression(oarg);
2494 if (ea)
2495 { if (specType)
2496 {
2497 if (!ea->type->equals(specType))
2498 goto Lnomatch;
2499 }
2500 }
2501 else
2502 goto Lnomatch;
2503 }
2504
2505 if (specAlias)
2506 {
2507 if (sa == sdummy)
2508 goto Lnomatch;
2509 if (sa != specAlias)
2510 goto Lnomatch;
2511 }
2512 else if (dedtypes->data[i])
2513 { // Must match already deduced symbol
2514 Object *s = (Object *)dedtypes->data[i];
2515
2516 if (!sa || s != sa)
2517 goto Lnomatch;
2518 }
2519 dedtypes->data[i] = sa;
2520
2521 s = isDsymbol(sa);
2522 if (s)
2523 *psparam = new AliasDeclaration(loc, ident, s);
2524 else
2525 {
2526 assert(ea);
2527
2528 // Declare manifest constant
2529 Initializer *init = new ExpInitializer(loc, ea);
2530 VarDeclaration *v = new VarDeclaration(loc, NULL, ident, init);
2531 v->storage_class = STCmanifest;
2532 v->semantic(sc);
2533 *psparam = v;
2534 }
2535 return MATCHexact;
2536
2537 Lnomatch:
2538 *psparam = NULL;
2539 return MATCHnomatch;
2540 }
2541
2542
2543 void TemplateAliasParameter::print(Object *oarg, Object *oded)
2544 {
2545 printf(" %s\n", ident->toChars());
2546
2547 Dsymbol *sa = isDsymbol(oded);
2548 assert(sa);
2549
2550 printf("\tArgument alias: %s\n", sa->toChars());
2551 }
2552
2553 void TemplateAliasParameter::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
2554 {
2555 buf->writestring("alias ");
2556 if (specType)
2557 { HdrGenState hgs;
2558 specType->toCBuffer(buf, ident, &hgs);
2559 }
2560 else
2561 buf->writestring(ident->toChars());
2562 if (specAlias)
2563 {
2564 buf->writestring(" : ");
2565 ObjectToCBuffer(buf, hgs, specAlias);
2566 }
2567 if (defaultAlias)
2568 {
2569 buf->writestring(" = ");
2570 ObjectToCBuffer(buf, hgs, defaultAlias);
2571 }
2572 }
2573
2574
2575 void *TemplateAliasParameter::dummyArg()
2576 { Object *s;
2577
2578 s = specAlias;
2579 if (!s)
2580 {
2581 if (!sdummy)
2582 sdummy = new Dsymbol();
2583 s = sdummy;
2584 }
2585 return (void*)s;
2586 }
2587
2588
2589 Object *TemplateAliasParameter::specialization()
2590 {
2591 return specAlias;
2592 }
2593
2594
2595 Object *TemplateAliasParameter::defaultArg(Loc loc, Scope *sc)
2596 {
2597 Object *o = aliasParameterSemantic(loc, sc, defaultAlias);
2598 return o;
2599 }
2600
2601 /* ======================== TemplateValueParameter ========================== */
2602
2603 // value-parameter
2604
2605 Expression *TemplateValueParameter::edummy = NULL;
2606
2607 TemplateValueParameter::TemplateValueParameter(Loc loc, Identifier *ident, Type *valType,
2608 Expression *specValue, Expression *defaultValue)
2609 : TemplateParameter(loc, ident)
2610 {
2611 this->ident = ident;
2612 this->valType = valType;
2613 this->specValue = specValue;
2614 this->defaultValue = defaultValue;
2615 }
2616
2617 TemplateValueParameter *TemplateValueParameter::isTemplateValueParameter()
2618 {
2619 return this;
2620 }
2621
2622 TemplateParameter *TemplateValueParameter::syntaxCopy()
2623 {
2624 TemplateValueParameter *tp =
2625 new TemplateValueParameter(loc, ident, valType, specValue, defaultValue);
2626 tp->valType = valType->syntaxCopy();
2627 if (specValue)
2628 tp->specValue = specValue->syntaxCopy();
2629 if (defaultValue)
2630 tp->defaultValue = defaultValue->syntaxCopy();
2631 return tp;
2632 }
2633
2634 void TemplateValueParameter::declareParameter(Scope *sc)
2635 {
2636 VarDeclaration *v = new VarDeclaration(loc, valType, ident, NULL);
2637 v->storage_class = STCtemplateparameter;
2638 if (!sc->insert(v))
2639 error(loc, "parameter '%s' multiply defined", ident->toChars());
2640 sparam = v;
2641 }
2642
2643 void TemplateValueParameter::semantic(Scope *sc)
2644 {
2645 sparam->semantic(sc);
2646 valType = valType->semantic(loc, sc);
2647 if (!(valType->isintegral() || valType->isfloating() || valType->isString()) &&
2648 valType->ty != Tident)
2649 error(loc, "arithmetic/string type expected for value-parameter, not %s", valType->toChars());
2650
2651 if (specValue)
2652 { Expression *e = specValue;
2653
2654 e = e->semantic(sc);
2655 e = e->implicitCastTo(sc, valType);
2656 e = e->optimize(WANTvalue | WANTinterpret);
2657 if (e->op == TOKint64 || e->op == TOKfloat64 ||
2658 e->op == TOKcomplex80 || e->op == TOKnull || e->op == TOKstring)
2659 specValue = e;
2660 //e->toInteger();
2661 }
2662
2663 #if 0 // defer semantic analysis to arg match
2664 if (defaultValue)
2665 { Expression *e = defaultValue;
2666
2667 e = e->semantic(sc);
2668 e = e->implicitCastTo(sc, valType);
2669 e = e->optimize(WANTvalue | WANTinterpret);
2670 if (e->op == TOKint64)
2671 defaultValue = e;
2672 //e->toInteger();
2673 }
2674 #endif
2675 }
2676
2677 int TemplateValueParameter::overloadMatch(TemplateParameter *tp)
2678 {
2679 TemplateValueParameter *tvp = tp->isTemplateValueParameter();
2680
2681 if (tvp)
2682 {
2683 if (valType != tvp->valType)
2684 goto Lnomatch;
2685
2686 if (valType && !valType->equals(tvp->valType))
2687 goto Lnomatch;
2688
2689 if (specValue != tvp->specValue)
2690 goto Lnomatch;
2691
2692 return 1; // match
2693 }
2694
2695 Lnomatch:
2696 return 0;
2697 }
2698
2699
2700 MATCH TemplateValueParameter::matchArg(Scope *sc,
2701 Objects *tiargs, int i, TemplateParameters *parameters, Objects *dedtypes,
2702 Declaration **psparam, int flags)
2703 {
2704 //printf("TemplateValueParameter::matchArg()\n");
2705
2706 Initializer *init;
2707 Declaration *sparam;
2708 MATCH m = MATCHexact;
2709 Expression *ei;
2710 Object *oarg;
2711
2712 if (i < tiargs->dim)
2713 oarg = (Object *)tiargs->data[i];
2714 else
2715 { // Get default argument instead
2716 oarg = defaultArg(loc, sc);
2717 if (!oarg)
2718 { assert(i < dedtypes->dim);
2719 // It might have already been deduced
2720 oarg = (Object *)dedtypes->data[i];
2721 if (!oarg)
2722 goto Lnomatch;
2723 }
2724 }
2725
2726 ei = isExpression(oarg);
2727 Type *vt;
2728
2729 if (!ei && oarg)
2730 goto Lnomatch;
2731
2732 if (ei && ei->op == TOKvar)
2733 { // Resolve const variables that we had skipped earlier
2734 ei = ei->optimize(WANTvalue | WANTinterpret);
2735 }
2736
2737 if (specValue)
2738 {
2739 if (!ei || ei == edummy)
2740 goto Lnomatch;
2741
2742 Expression *e = specValue;
2743
2744 e = e->semantic(sc);
2745 e = e->implicitCastTo(sc, valType);
2746 e = e->optimize(WANTvalue | WANTinterpret);
2747 //e->type = e->type->toHeadMutable();
2748
2749 ei = ei->syntaxCopy();
2750 ei = ei->semantic(sc);
2751 ei = ei->optimize(WANTvalue | WANTinterpret);
2752 //ei->type = ei->type->toHeadMutable();
2753 //printf("\tei: %s, %s\n", ei->toChars(), ei->type->toChars());
2754 //printf("\te : %s, %s\n", e->toChars(), e->type->toChars());
2755 if (!ei->equals(e))
2756 goto Lnomatch;
2757 }
2758 else if (dedtypes->data[i])
2759 { // Must match already deduced value
2760 Expression *e = (Expression *)dedtypes->data[i];
2761
2762 if (!ei || !ei->equals(e))
2763 goto Lnomatch;
2764 }
2765 Lmatch:
2766 //printf("\tvalType: %s, ty = %d\n", valType->toChars(), valType->ty);
2767 vt = valType->semantic(0, sc);
2768 //printf("ei: %s, ei->type: %s\n", ei->toChars(), ei->type->toChars());
2769 //printf("vt = %s\n", vt->toChars());
2770 if (ei->type)
2771 {
2772 //ei->type = ei->type->toHeadMutable();
2773 m = (MATCH)ei->implicitConvTo(vt);
2774 //printf("m: %d\n", m);
2775 if (!m)
2776 goto Lnomatch;
2777 }
2778 dedtypes->data[i] = ei;
2779
2780 init = new ExpInitializer(loc, ei);
2781 sparam = new VarDeclaration(loc, vt, ident, init);
2782 sparam->storage_class = STCmanifest;
2783 *psparam = sparam;
2784 return m;
2785
2786 Lnomatch:
2787 //printf("\tno match\n");
2788 *psparam = NULL;
2789 return MATCHnomatch;
2790 }
2791
2792
2793 void TemplateValueParameter::print(Object *oarg, Object *oded)
2794 {
2795 printf(" %s\n", ident->toChars());
2796
2797 Expression *ea = isExpression(oded);
2798
2799 if (specValue)
2800 printf("\tSpecialization: %s\n", specValue->toChars());
2801 printf("\tArgument Value: %s\n", ea ? ea->toChars() : "NULL");
2802 }
2803
2804
2805 void TemplateValueParameter::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
2806 {
2807 valType->toCBuffer(buf, ident, hgs);
2808 if (specValue)
2809 {
2810 buf->writestring(" : ");
2811 specValue->toCBuffer(buf, hgs);
2812 }
2813 if (defaultValue)
2814 {
2815 buf->writestring(" = ");
2816 defaultValue->toCBuffer(buf, hgs);
2817 }
2818 }
2819
2820
2821 void *TemplateValueParameter::dummyArg()
2822 { Expression *e;
2823
2824 e = specValue;
2825 if (!e)
2826 {
2827 // Create a dummy value
2828 if (!edummy)
2829 edummy = valType->defaultInit();
2830 e = edummy;
2831 }
2832 return (void *)e;
2833 }
2834
2835
2836 Object *TemplateValueParameter::specialization()
2837 {
2838 return specValue;
2839 }
2840
2841
2842 Object *TemplateValueParameter::defaultArg(Loc loc, Scope *sc)
2843 {
2844 Expression *e = defaultValue;
2845 if (e)
2846 {
2847 e = e->syntaxCopy();
2848 e = e->semantic(sc);
2849 #if DMDV2
2850 if (e->op == TOKdefault)
2851 { DefaultInitExp *de = (DefaultInitExp *)e;
2852 e = de->resolve(loc, sc);
2853 }
2854 #endif
2855 }
2856 return e;
2857 }
2858
2859 /* ======================== TemplateTupleParameter ========================== */
2860
2861 // variadic-parameter
2862
2863 TemplateTupleParameter::TemplateTupleParameter(Loc loc, Identifier *ident)
2864 : TemplateParameter(loc, ident)
2865 {
2866 this->ident = ident;
2867 }
2868
2869 TemplateTupleParameter *TemplateTupleParameter::isTemplateTupleParameter()
2870 {
2871 return this;
2872 }
2873
2874 TemplateParameter *TemplateTupleParameter::syntaxCopy()
2875 {
2876 TemplateTupleParameter *tp = new TemplateTupleParameter(loc, ident);
2877 return tp;
2878 }
2879
2880 void TemplateTupleParameter::declareParameter(Scope *sc)
2881 {
2882 TypeIdentifier *ti = new TypeIdentifier(loc, ident);
2883 sparam = new AliasDeclaration(loc, ident, ti);
2884 if (!sc->insert(sparam))
2885 error(loc, "parameter '%s' multiply defined", ident->toChars());
2886 }
2887
2888 void TemplateTupleParameter::semantic(Scope *sc)
2889 {
2890 }
2891
2892 int TemplateTupleParameter::overloadMatch(TemplateParameter *tp)
2893 {
2894 TemplateTupleParameter *tvp = tp->isTemplateTupleParameter();
2895
2896 if (tvp)
2897 {
2898 return 1; // match
2899 }
2900
2901 Lnomatch:
2902 return 0;
2903 }
2904
2905 MATCH TemplateTupleParameter::matchArg(Scope *sc,
2906 Objects *tiargs, int i, TemplateParameters *parameters,
2907 Objects *dedtypes,
2908 Declaration **psparam, int flags)
2909 {
2910 //printf("TemplateTupleParameter::matchArg()\n");
2911
2912 /* The rest of the actual arguments (tiargs[]) form the match
2913 * for the variadic parameter.
2914 */
2915 assert(i + 1 == dedtypes->dim); // must be the last one
2916 Tuple *ovar;
2917 if (i + 1 == tiargs->dim && isTuple((Object *)tiargs->data[i]))
2918 ovar = isTuple((Object *)tiargs->data[i]);
2919 else
2920 {
2921 ovar = new Tuple();
2922 //printf("ovar = %p\n", ovar);
2923 if (i < tiargs->dim)
2924 {
2925 //printf("i = %d, tiargs->dim = %d\n", i, tiargs->dim);
2926 ovar->objects.setDim(tiargs->dim - i);
2927 for (size_t j = 0; j < ovar->objects.dim; j++)
2928 ovar->objects.data[j] = tiargs->data[i + j];
2929 }
2930 }
2931 *psparam = new TupleDeclaration(loc, ident, &ovar->objects);
2932 dedtypes->data[i] = (void *)ovar;
2933 return MATCHexact;
2934 }
2935
2936
2937 void TemplateTupleParameter::print(Object *oarg, Object *oded)
2938 {
2939 printf(" %s... [", ident->toChars());
2940 Tuple *v = isTuple(oded);
2941 assert(v);
2942
2943 //printf("|%d| ", v->objects.dim);
2944 for (int i = 0; i < v->objects.dim; i++)
2945 {
2946 if (i)
2947 printf(", ");
2948
2949 Object *o = (Object *)v->objects.data[i];
2950
2951 Dsymbol *sa = isDsymbol(o);
2952 if (sa)
2953 printf("alias: %s", sa->toChars());
2954
2955 Type *ta = isType(o);
2956 if (ta)
2957 printf("type: %s", ta->toChars());
2958
2959 Expression *ea = isExpression(o);
2960 if (ea)
2961 printf("exp: %s", ea->toChars());
2962
2963 assert(!isTuple(o)); // no nested Tuple arguments
2964 }
2965
2966 printf("]\n");
2967 }
2968
2969 void TemplateTupleParameter::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
2970 {
2971 buf->writestring(ident->toChars());
2972 buf->writestring("...");
2973 }
2974
2975
2976 void *TemplateTupleParameter::dummyArg()
2977 {
2978 return NULL;
2979 }
2980
2981
2982 Object *TemplateTupleParameter::specialization()
2983 {
2984 return NULL;
2985 }
2986
2987
2988 Object *TemplateTupleParameter::defaultArg(Loc loc, Scope *sc)
2989 {
2990 return NULL;
2991 }
2992
2993 /* ======================== TemplateInstance ================================ */
2994
2995 TemplateInstance::TemplateInstance(Loc loc, Identifier *ident)
2996 : ScopeDsymbol(NULL)
2997 {
2998 #if LOG
2999 printf("TemplateInstance(this = %p, ident = '%s')\n", this, ident ? ident->toChars() : "null");
3000 #endif
3001 this->loc = loc;
3002 this->name = ident;
3003 this->tiargs = NULL;
3004 this->tempdecl = NULL;
3005 this->inst = NULL;
3006 this->argsym = NULL;
3007 this->aliasdecl = NULL;
3008 this->semanticdone = 0;
3009 this->semantictiargsdone = 0;
3010 this->withsym = NULL;
3011 this->nest = 0;
3012 this->havetempdecl = 0;
3013 this->isnested = NULL;
3014 this->errors = 0;
3015 this->tinst = NULL;
3016 }
3017
3018 /*****************
3019 * This constructor is only called when we figured out which function
3020 * template to instantiate.
3021 */
3022
3023 TemplateInstance::TemplateInstance(Loc loc, TemplateDeclaration *td, Objects *tiargs)
3024 : ScopeDsymbol(NULL)
3025 {
3026 #if LOG
3027 printf("TemplateInstance(this = %p, tempdecl = '%s')\n", this, td->toChars());
3028 #endif
3029 this->loc = loc;
3030 this->name = td->ident;
3031 this->tiargs = tiargs;
3032 this->tempdecl = td;
3033 this->inst = NULL;
3034 this->argsym = NULL;
3035 this->aliasdecl = NULL;
3036 this->semanticdone = 0;
3037 this->semantictiargsdone = 1;
3038 this->withsym = NULL;
3039 this->nest = 0;
3040 this->havetempdecl = 1;
3041 this->isnested = NULL;
3042 this->errors = 0;
3043 this->tinst = NULL;
3044
3045 assert((size_t)tempdecl->scope > 0x10000);
3046 }
3047
3048
3049 Objects *TemplateInstance::arraySyntaxCopy(Objects *objs)
3050 {
3051 Objects *a = NULL;
3052 if (objs)
3053 { a = new Objects();
3054 a->setDim(objs->dim);
3055 for (size_t i = 0; i < objs->dim; i++)
3056 {
3057 a->data[i] = objectSyntaxCopy((Object *)objs->data[i]);
3058 }
3059 }
3060 return a;
3061 }
3062
3063 Dsymbol *TemplateInstance::syntaxCopy(Dsymbol *s)
3064 {
3065 TemplateInstance *ti;
3066
3067 if (s)
3068 ti = (TemplateInstance *)s;
3069 else
3070 ti = new TemplateInstance(loc, name);
3071
3072 ti->tiargs = arraySyntaxCopy(tiargs);
3073
3074 ScopeDsymbol::syntaxCopy(ti);
3075 return ti;
3076 }
3077
3078
3079 void TemplateInstance::semantic(Scope *sc)
3080 {
3081 if (global.errors)
3082 {
3083 if (!global.gag)
3084 {
3085 /* Trying to soldier on rarely generates useful messages
3086 * at this point.
3087 */
3088 fatal();
3089 }
3090 return;
3091 }
3092 #if LOG
3093 printf("\n+TemplateInstance::semantic('%s', this=%p)\n", toChars(), this);
3094 #endif
3095 if (inst) // if semantic() was already run
3096 {
3097 #if LOG
3098 printf("-TemplateInstance::semantic('%s', this=%p) already run\n", inst->toChars(), inst);
3099 #endif
3100 return;
3101 }
3102
3103 if (semanticdone != 0)
3104 {
3105 error(loc, "recursive template expansion");
3106 // inst = this;
3107 return;
3108 }
3109 semanticdone = 1;
3110
3111 // get the enclosing template instance from the scope tinst
3112 tinst = sc->tinst;
3113
3114 #if LOG
3115 printf("\tdo semantic\n");
3116 #endif
3117 if (havetempdecl)
3118 {
3119 assert((size_t)tempdecl->scope > 0x10000);
3120 // Deduce tdtypes
3121 tdtypes.setDim(tempdecl->parameters->dim);
3122 if (!tempdecl->matchWithInstance(this, &tdtypes, 2))
3123 {
3124 error("incompatible arguments for template instantiation");
3125 inst = this;
3126 return;
3127 }
3128 }
3129 else
3130 {
3131 /* Run semantic on each argument, place results in tiargs[]
3132 * (if we havetempdecl, then tiargs is already evaluated)
3133 */
3134 semanticTiargs(sc);
3135
3136 tempdecl = findTemplateDeclaration(sc);
3137 if (tempdecl)
3138 tempdecl = findBestMatch(sc);
3139 if (!tempdecl || global.errors)
3140 { inst = this;
3141 //printf("error return %p, %d\n", tempdecl, global.errors);
3142 return; // error recovery
3143 }
3144 }
3145
3146 isNested(tiargs);
3147
3148 /* See if there is an existing TemplateInstantiation that already
3149 * implements the typeargs. If so, just refer to that one instead.
3150 */
3151
3152 for (size_t i = 0; i < tempdecl->instances.dim; i++)
3153 {
3154 TemplateInstance *ti = (TemplateInstance *)tempdecl->instances.data[i];
3155 #if LOG
3156 printf("\t%s: checking for match with instance %d (%p): '%s'\n", toChars(), i, ti, ti->toChars());
3157 #endif
3158 assert(tdtypes.dim == ti->tdtypes.dim);
3159
3160 // Nesting must match
3161 if (isnested != ti->isnested)
3162 continue;
3163 #if 0
3164 if (isnested && sc->parent != ti->parent)
3165 continue;
3166 #endif
3167 for (size_t j = 0; j < tdtypes.dim; j++)
3168 { Object *o1 = (Object *)tdtypes.data[j];
3169 Object *o2 = (Object *)ti->tdtypes.data[j];
3170 if (!match(o1, o2, tempdecl, sc))
3171 goto L1;
3172 }
3173
3174 // It's a match
3175 inst = ti;
3176 parent = ti->parent;
3177 #if LOG
3178 printf("\tit's a match with instance %p\n", inst);
3179 #endif
3180 return;
3181
3182 L1:
3183 ;
3184 }
3185
3186 /* So, we need to implement 'this' instance.
3187 */
3188 #if LOG
3189 printf("\timplement template instance '%s'\n", toChars());
3190 #endif
3191 unsigned errorsave = global.errors;
3192 inst = this;
3193 int tempdecl_instance_idx = tempdecl->instances.dim;
3194 tempdecl->instances.push(this);
3195 parent = tempdecl->parent;
3196 //printf("parent = '%s'\n", parent->kind());
3197
3198 ident = genIdent(); // need an identifier for name mangling purposes.
3199
3200 #if 1
3201 if (isnested)
3202 parent = isnested;
3203 #endif
3204 //printf("parent = '%s'\n", parent->kind());
3205
3206 // Add 'this' to the enclosing scope's members[] so the semantic routines
3207 // will get called on the instance members
3208 #if 1
3209 int dosemantic3 = 0;
3210 { Array *a;
3211
3212 Scope *scx = sc;
3213 #if 0
3214 for (scx = sc; scx; scx = scx->enclosing)
3215 if (scx->scopesym)
3216 break;
3217 #endif
3218
3219 //if (scx && scx->scopesym) printf("3: scx is %s %s\n", scx->scopesym->kind(), scx->scopesym->toChars());
3220 if (scx && scx->scopesym && scx->scopesym->members && !scx->scopesym->isTemplateMixin())
3221 {
3222 //printf("\t1: adding to %s %s\n", scx->scopesym->kind(), scx->scopesym->toChars());
3223 a = scx->scopesym->members;
3224 }
3225 else
3226 { Module *m = sc->module->importedFrom;
3227 //printf("\t2: adding to module %s instead of module %s\n", m->toChars(), sc->module->toChars());
3228 a = m->members;
3229 if (m->semanticdone >= 3)
3230 dosemantic3 = 1;
3231 }
3232 for (int i = 0; 1; i++)
3233 {
3234 if (i == a->dim)
3235 {
3236 a->push(this);
3237 break;
3238 }
3239 if (this == (Dsymbol *)a->data[i]) // if already in Array
3240 break;
3241 }
3242 }
3243 #endif
3244
3245 // Copy the syntax trees from the TemplateDeclaration
3246 members = Dsymbol::arraySyntaxCopy(tempdecl->members);
3247
3248 // Create our own scope for the template parameters
3249 Scope *scope = tempdecl->scope;
3250 if (!scope)
3251 {
3252 error("forward reference to template declaration %s\n", tempdecl->toChars());
3253 return;
3254 }
3255
3256 #if LOG
3257 printf("\tcreate scope for template parameters '%s'\n", toChars());
3258 #endif
3259 argsym = new ScopeDsymbol();
3260 argsym->parent = scope->parent;
3261 scope = scope->push(argsym);
3262
3263 // Declare each template parameter as an alias for the argument type
3264 declareParameters(scope);
3265
3266 // Add members of template instance to template instance symbol table
3267 // parent = scope->scopesym;
3268 symtab = new DsymbolTable();
3269 int memnum = 0;
3270 for (int i = 0; i < members->dim; i++)
3271 {
3272 Dsymbol *s = (Dsymbol *)members->data[i];
3273 #if LOG
3274 printf("\t[%d] adding member '%s' %p kind %s to '%s', memnum = %d\n", i, s->toChars(), s, s->kind(), this->toChars(), memnum);
3275 #endif
3276 memnum |= s->addMember(scope, this, memnum);
3277 }
3278 #if LOG
3279 printf("adding members done\n");
3280 #endif
3281
3282 /* See if there is only one member of template instance, and that
3283 * member has the same name as the template instance.
3284 * If so, this template instance becomes an alias for that member.
3285 */
3286 //printf("members->dim = %d\n", members->dim);
3287 if (members->dim)
3288 {
3289 Dsymbol *s;
3290 if (Dsymbol::oneMembers(members, &s) && s)
3291 {
3292 //printf("s->kind = '%s'\n", s->kind());
3293 //s->print();
3294 //printf("'%s', '%s'\n", s->ident->toChars(), tempdecl->ident->toChars());
3295 if (s->ident && s->ident->equals(tempdecl->ident))
3296 {
3297 //printf("setting aliasdecl\n");
3298 aliasdecl = new AliasDeclaration(loc, s->ident, s);
3299 }
3300 }
3301 }
3302
3303 // Do semantic() analysis on template instance members
3304 #if LOG
3305 printf("\tdo semantic() on template instance members '%s'\n", toChars());
3306 #endif
3307 Scope *sc2;
3308 sc2 = scope->push(this);
3309 //printf("isnested = %d, sc->parent = %s\n", isnested, sc->parent->toChars());
3310 sc2->parent = /*isnested ? sc->parent :*/ this;
3311 sc2->tinst = this;
3312
3313 #if !IN_LLVM
3314 #if _WIN32
3315 __try
3316 {
3317 #endif
3318 #endif
3319 for (int i = 0; i < members->dim; i++)
3320 {
3321 Dsymbol *s = (Dsymbol *)members->data[i];
3322 //printf("\t[%d] semantic on '%s' %p kind %s in '%s'\n", i, s->toChars(), s, s->kind(), this->toChars());
3323 //printf("test: isnested = %d, sc2->parent = %s\n", isnested, sc2->parent->toChars());
3324 // if (isnested)
3325 // s->parent = sc->parent;
3326 //printf("test3: isnested = %d, s->parent = %s\n", isnested, s->parent->toChars());
3327 s->semantic(sc2);
3328 //printf("test4: isnested = %d, s->parent = %s\n", isnested, s->parent->toChars());
3329 sc2->module->runDeferredSemantic();
3330 }
3331 #if !IN_LLVM
3332 #if _WIN32
3333 }
3334 __except (__ehfilter(GetExceptionInformation()))
3335 {
3336 global.gag = 0; // ensure error message gets printed
3337 error("recursive expansion");
3338 fatal();
3339 }
3340 #endif
3341 #endif
3342
3343 /* If any of the instantiation members didn't get semantic() run
3344 * on them due to forward references, we cannot run semantic2()
3345 * or semantic3() yet.
3346 */
3347 for (size_t i = 0; i < Module::deferred.dim; i++)
3348 { Dsymbol *sd = (Dsymbol *)Module::deferred.data[i];
3349
3350 if (sd->parent == this)
3351 goto Laftersemantic;
3352 }
3353
3354 /* The problem is when to parse the initializer for a variable.
3355 * Perhaps VarDeclaration::semantic() should do it like it does
3356 * for initializers inside a function.
3357 */
3358 // if (sc->parent->isFuncDeclaration())
3359
3360 /* BUG 782: this has problems if the classes this depends on
3361 * are forward referenced. Find a way to defer semantic()
3362 * on this template.
3363 */
3364 semantic2(sc2);
3365
3366 if (sc->func || dosemantic3)
3367 {
3368 semantic3(sc2);
3369 }
3370
3371 Laftersemantic:
3372 sc2->pop();
3373
3374 scope->pop();
3375
3376 // Give additional context info if error occurred during instantiation
3377 if (global.errors != errorsave)
3378 {
3379 error("error instantiating");
3380 if(tinst)
3381 tinst->printInstantiationTrace();
3382 errors = 1;
3383 if (global.gag)
3384 tempdecl->instances.remove(tempdecl_instance_idx);
3385 }
3386
3387 #if LOG
3388 printf("-TemplateInstance::semantic('%s', this=%p)\n", toChars(), this);
3389 #endif
3390 }
3391
3392
3393 void TemplateInstance::semanticTiargs(Scope *sc)
3394 {
3395 //printf("+TemplateInstance::semanticTiargs() %s\n", toChars());
3396 if (semantictiargsdone)
3397 return;
3398 semantictiargsdone = 1;
3399 semanticTiargs(loc, sc, tiargs, 0);
3400 }
3401
3402 /**********************************
3403 * Input:
3404 * flags 1: replace const variables with their initializers
3405 */
3406
3407 void TemplateInstance::semanticTiargs(Loc loc, Scope *sc, Objects *tiargs, int flags)
3408 {
3409 // Run semantic on each argument, place results in tiargs[]
3410 //printf("+TemplateInstance::semanticTiargs()\n");
3411 if (!tiargs)
3412 return;
3413 for (size_t j = 0; j < tiargs->dim; j++)
3414 {
3415 Object *o = (Object *)tiargs->data[j];
3416 Type *ta = isType(o);
3417 Expression *ea = isExpression(o);
3418 Dsymbol *sa = isDsymbol(o);
3419
3420 //printf("1: tiargs->data[%d] = %p, %p, %p, ea=%p, ta=%p\n", j, o, isDsymbol(o), isTuple(o), ea, ta);
3421 if (ta)
3422 {
3423 //printf("type %s\n", ta->toChars());
3424 // It might really be an Expression or an Alias
3425 ta->resolve(loc, sc, &ea, &ta, &sa);
3426 if (ea)
3427 {
3428 ea = ea->semantic(sc);
3429 /* This test is to skip substituting a const var with
3430 * its initializer. The problem is the initializer won't
3431 * match with an 'alias' parameter. Instead, do the
3432 * const substitution in TemplateValueParameter::matchArg().
3433 */
3434 if (ea->op != TOKvar || flags & 1)
3435 ea = ea->optimize(WANTvalue | WANTinterpret);
3436 tiargs->data[j] = ea;
3437 }
3438 else if (sa)
3439 { tiargs->data[j] = sa;
3440 TupleDeclaration *d = sa->toAlias()->isTupleDeclaration();
3441 if (d)
3442 {
3443 size_t dim = d->objects->dim;
3444 tiargs->remove(j);
3445 tiargs->insert(j, d->objects);
3446 j--;
3447 }
3448 }
3449 else if (ta)
3450 {
3451 if (ta->ty == Ttuple)
3452 { // Expand tuple
3453 TypeTuple *tt = (TypeTuple *)ta;
3454 size_t dim = tt->arguments->dim;
3455 tiargs->remove(j);
3456 if (dim)
3457 { tiargs->reserve(dim);
3458 for (size_t i = 0; i < dim; i++)
3459 { Argument *arg = (Argument *)tt->arguments->data[i];
3460 tiargs->insert(j + i, arg->type);
3461 }
3462 }
3463 j--;
3464 }
3465 else
3466 tiargs->data[j] = ta;
3467 }
3468 else
3469 {
3470 assert(global.errors);
3471 tiargs->data[j] = Type::terror;
3472 }
3473 }
3474 else if (ea)
3475 {
3476 if (!ea)
3477 { assert(global.errors);
3478 ea = new IntegerExp(0);
3479 }
3480 assert(ea);
3481 ea = ea->semantic(sc);
3482 if (ea->op != TOKvar || flags & 1)
3483 ea = ea->optimize(WANTvalue | WANTinterpret);
3484 tiargs->data[j] = ea;
3485 if (ea->op == TOKtype)
3486 tiargs->data[j] = ea->type;
3487 }
3488 else if (sa)
3489 {
3490 }
3491 else
3492 {
3493 assert(0);
3494 }
3495 //printf("1: tiargs->data[%d] = %p\n", j, tiargs->data[j]);
3496 }
3497 #if 0
3498 printf("-TemplateInstance::semanticTiargs('%s', this=%p)\n", toChars(), this);
3499 for (size_t j = 0; j < tiargs->dim; j++)
3500 {
3501 Object *o = (Object *)tiargs->data[j];
3502 Type *ta = isType(o);
3503 Expression *ea = isExpression(o);
3504 Dsymbol *sa = isDsymbol(o);
3505 Tuple *va = isTuple(o);
3506
3507 printf("\ttiargs[%d] = ta %p, ea %p, sa %p, va %p\n", j, ta, ea, sa, va);
3508 }
3509 #endif
3510 }
3511
3512 /**********************************************
3513 * Find template declaration corresponding to template instance.
3514 */
3515
3516 TemplateDeclaration *TemplateInstance::findTemplateDeclaration(Scope *sc)
3517 {
3518 //printf("TemplateInstance::findTemplateDeclaration() %s\n", toChars());
3519 if (!tempdecl)
3520 {
3521 /* Given:
3522 * foo!( ... )
3523 * figure out which TemplateDeclaration foo refers to.
3524 */
3525 Dsymbol *s;
3526 Dsymbol *scopesym;
3527 Identifier *id;
3528 int i;
3529
3530 id = name;
3531 s = sc->search(loc, id, &scopesym);
3532 if (!s)
3533 { error("identifier '%s' is not defined", id->toChars());
3534 return NULL;
3535 }
3536 #if LOG
3537 printf("It's an instance of '%s' kind '%s'\n", s->toChars(), s->kind());
3538 if (s->parent)
3539 printf("s->parent = '%s'\n", s->parent->toChars());
3540 #endif
3541 withsym = scopesym->isWithScopeSymbol();
3542
3543 /* We might have found an alias within a template when
3544 * we really want the template.
3545 */
3546 TemplateInstance *ti;
3547 if (s->parent &&
3548 (ti = s->parent->isTemplateInstance()) != NULL)
3549 {
3550 if (
3551 (ti->name == id ||
3552 ti->toAlias()->ident == id)
3553 &&
3554 ti->tempdecl)
3555 {
3556 /* This is so that one can refer to the enclosing
3557 * template, even if it has the same name as a member
3558 * of the template, if it has a !(arguments)
3559 */
3560 tempdecl = ti->tempdecl;
3561 if (tempdecl->overroot) // if not start of overloaded list of TemplateDeclaration's
3562 tempdecl = tempdecl->overroot; // then get the start
3563 s = tempdecl;
3564 }
3565 }
3566
3567 s = s->toAlias();
3568
3569 /* It should be a TemplateDeclaration, not some other symbol
3570 */
3571 tempdecl = s->isTemplateDeclaration();
3572 if (!tempdecl)
3573 {
3574 if (!s->parent && global.errors)
3575 return NULL;
3576 if (!s->parent && s->getType())
3577 { Dsymbol *s2 = s->getType()->toDsymbol(sc);
3578 if (!s2)
3579 {
3580 error("%s is not a template declaration, it is a %s", id->toChars(), s->kind());
3581 return NULL;
3582 }
3583 s = s2;
3584 }
3585 #ifdef DEBUG
3586 //if (!s->parent) printf("s = %s %s\n", s->kind(), s->toChars());
3587 #endif
3588 //assert(s->parent);
3589 TemplateInstance *ti = s->parent ? s->parent->isTemplateInstance() : NULL;
3590 if (ti &&
3591 (ti->name == id ||
3592 ti->toAlias()->ident == id)
3593 &&
3594 ti->tempdecl)
3595 {
3596 /* This is so that one can refer to the enclosing
3597 * template, even if it has the same name as a member
3598 * of the template, if it has a !(arguments)
3599 */
3600 tempdecl = ti->tempdecl;
3601 if (tempdecl->overroot) // if not start of overloaded list of TemplateDeclaration's
3602 tempdecl = tempdecl->overroot; // then get the start
3603 }
3604 else
3605 {
3606 error("%s is not a template declaration, it is a %s", id->toChars(), s->kind());
3607 return NULL;
3608 }
3609 }
3610 }
3611 else
3612 assert(tempdecl->isTemplateDeclaration());
3613 return tempdecl;
3614 }
3615
3616 TemplateDeclaration *TemplateInstance::findBestMatch(Scope *sc)
3617 {
3618 /* Since there can be multiple TemplateDeclaration's with the same
3619 * name, look for the best match.
3620 */
3621 TemplateDeclaration *td_ambig = NULL;
3622 TemplateDeclaration *td_best = NULL;
3623 MATCH m_best = MATCHnomatch;
3624 Objects dedtypes;
3625
3626 #if LOG
3627 printf("TemplateInstance::findBestMatch()\n");
3628 #endif
3629 for (TemplateDeclaration *td = tempdecl; td; td = td->overnext)
3630 {
3631 MATCH m;
3632
3633 //if (tiargs->dim) printf("2: tiargs->dim = %d, data[0] = %p\n", tiargs->dim, tiargs->data[0]);
3634
3635 // If more arguments than parameters,
3636 // then this is no match.
3637 if (td->parameters->dim < tiargs->dim)
3638 {
3639 if (!td->isVariadic())
3640 continue;
3641 }
3642
3643 dedtypes.setDim(td->parameters->dim);
3644 dedtypes.zero();
3645 if (!td->scope)
3646 {
3647 error("forward reference to template declaration %s", td->toChars());
3648 return NULL;
3649 }
3650 m = td->matchWithInstance(this, &dedtypes, 0);
3651 //printf("matchWithInstance = %d\n", m);
3652 if (!m) // no match at all
3653 continue;
3654
3655 if (m < m_best)
3656 goto Ltd_best;
3657 if (m > m_best)
3658 goto Ltd;
3659
3660 {
3661 // Disambiguate by picking the most specialized TemplateDeclaration
3662 MATCH c1 = td->leastAsSpecialized(td_best);
3663 MATCH c2 = td_best->leastAsSpecialized(td);
3664 //printf("c1 = %d, c2 = %d\n", c1, c2);
3665
3666 if (c1 > c2)
3667 goto Ltd;
3668 else if (c1 < c2)
3669 goto Ltd_best;
3670 else
3671 goto Lambig;
3672 }
3673
3674 Lambig: // td_best and td are ambiguous
3675 td_ambig = td;
3676 continue;
3677
3678 Ltd_best: // td_best is the best match so far
3679 td_ambig = NULL;
3680 continue;
3681
3682 Ltd: // td is the new best match
3683 td_ambig = NULL;
3684 td_best = td;
3685 m_best = m;
3686 tdtypes.setDim(dedtypes.dim);
3687 memcpy(tdtypes.data, dedtypes.data, tdtypes.dim * sizeof(void *));
3688 continue;
3689 }
3690
3691 if (!td_best)
3692 {
3693 if (tempdecl && !tempdecl->overnext)
3694 // Only one template, so we can give better error message
3695 error("%s does not match template declaration %s", toChars(), tempdecl->toChars());
3696 else
3697 error("%s does not match any template declaration", toChars());
3698 return NULL;
3699 }
3700 if (td_ambig)
3701 {
3702 error("%s matches more than one template declaration, %s and %s",
3703 toChars(), td_best->toChars(), td_ambig->toChars());
3704 }
3705
3706 /* The best match is td_best
3707 */
3708 tempdecl = td_best;
3709
3710 #if 0
3711 /* Cast any value arguments to be same type as value parameter
3712 */
3713 for (size_t i = 0; i < tiargs->dim; i++)
3714 { Object *o = (Object *)tiargs->data[i];
3715 Expression *ea = isExpression(o); // value argument
3716 TemplateParameter *tp = (TemplateParameter *)tempdecl->parameters->data[i];
3717 assert(tp);
3718 TemplateValueParameter *tvp = tp->isTemplateValueParameter();
3719 if (tvp)
3720 {
3721 assert(ea);
3722 ea = ea->castTo(tvp->valType);
3723 ea = ea->optimize(WANTvalue | WANTinterpret);
3724 tiargs->data[i] = (Object *)ea;
3725 }
3726 }
3727 #endif
3728
3729 #if LOG
3730 printf("\tIt's a match with template declaration '%s'\n", tempdecl->toChars());
3731 #endif
3732 return tempdecl;
3733 }
3734
3735
3736 /*****************************************
3737 * Determines if a TemplateInstance will need a nested
3738 * generation of the TemplateDeclaration.
3739 */
3740
3741 int TemplateInstance::isNested(Objects *args)
3742 { int nested = 0;
3743 //printf("TemplateInstance::isNested('%s')\n", tempdecl->ident->toChars());
3744
3745 /* A nested instance happens when an argument references a local
3746 * symbol that is on the stack.
3747 */
3748 for (size_t i = 0; i < args->dim; i++)
3749 { Object *o = (Object *)args->data[i];
3750 Expression *ea = isExpression(o);
3751 Dsymbol *sa = isDsymbol(o);
3752 Tuple *va = isTuple(o);
3753 if (ea)
3754 {
3755 if (ea->op == TOKvar)
3756 {
3757 sa = ((VarExp *)ea)->var;
3758 goto Lsa;
3759 }
3760 if (ea->op == TOKfunction)
3761 {
3762 sa = ((FuncExp *)ea)->fd;
3763 goto Lsa;
3764 }
3765 }
3766 else if (sa)
3767 {
3768 Lsa:
3769 Declaration *d = sa->isDeclaration();
3770 if (d && !d->isDataseg() &&
3771 #if DMDV2
3772 !(d->storage_class & STCmanifest) &&
3773 #endif
3774 (!d->isFuncDeclaration() || d->isFuncDeclaration()->isNested()) &&
3775 !isTemplateMixin())
3776 {
3777 // if module level template
3778 if (tempdecl->toParent()->isModule())
3779 { Dsymbol *dparent = d->toParent();
3780 if (!isnested)
3781 isnested = dparent;
3782 else if (isnested != dparent)
3783 {
3784 /* Select the more deeply nested of the two.
3785 * Error if one is not nested inside the other.
3786 */
3787 for (Dsymbol *p = isnested; p; p = p->parent)
3788 {
3789 if (p == dparent)
3790 goto L1; // isnested is most nested
3791 }
3792 for (Dsymbol *p = dparent; 1; p = p->parent)
3793 {
3794 if (p == isnested)
3795 { isnested = dparent;
3796 goto L1; // dparent is most nested
3797 }
3798 }
3799 error("is nested in both %s and %s", isnested->toChars(), dparent->toChars());
3800 }
3801 L1:
3802 //printf("\tnested inside %s\n", isnested->toChars());
3803 nested |= 1;
3804 }
3805 else
3806 error("cannot use local '%s' as parameter to non-global template %s", d->toChars(), tempdecl->toChars());
3807 }
3808 }
3809 else if (va)
3810 {
3811 nested |= isNested(&va->objects);
3812 }
3813 }
3814 return nested;
3815 }
3816
3817 /****************************************
3818 * This instance needs an identifier for name mangling purposes.
3819 * Create one by taking the template declaration name and adding
3820 * the type signature for it.
3821 */
3822
3823 Identifier *TemplateInstance::genIdent()
3824 { OutBuffer buf;
3825 char *id;
3826 Objects *args;
3827
3828 //printf("TemplateInstance::genIdent('%s')\n", tempdecl->ident->toChars());
3829 id = tempdecl->ident->toChars();
3830 buf.printf("__T%"PRIuSIZE"%s", strlen(id), id);
3831 args = tiargs;
3832 for (int i = 0; i < args->dim; i++)
3833 { Object *o = (Object *)args->data[i];
3834 Type *ta = isType(o);
3835 Expression *ea = isExpression(o);
3836 Dsymbol *sa = isDsymbol(o);
3837 Tuple *va = isTuple(o);
3838 //printf("\to %p ta %p ea %p sa %p va %p\n", o, ta, ea, sa, va);
3839 if (ta)
3840 {
3841 buf.writeByte('T');
3842 if (ta->deco)
3843 buf.writestring(ta->deco);
3844 else
3845 {
3846 #ifdef DEBUG
3847 printf("ta = %d, %s\n", ta->ty, ta->toChars());
3848 #endif
3849 assert(global.errors);
3850 }
3851 }
3852 else if (ea)
3853 {
3854 Lea:
3855 sinteger_t v;
3856 real_t r;
3857
3858 ea = ea->optimize(WANTvalue | WANTinterpret);
3859 if (ea->op == TOKvar)
3860 {
3861 sa = ((VarExp *)ea)->var;
3862 ea = NULL;
3863 goto Lsa;
3864 }
3865 if (ea->op == TOKfunction)
3866 {
3867 sa = ((FuncExp *)ea)->fd;
3868 ea = NULL;
3869 goto Lsa;
3870 }
3871 buf.writeByte('V');
3872 if (ea->op == TOKtuple)
3873 { ea->error("tuple is not a valid template value argument");
3874 continue;
3875 }
3876 #if 1
3877 /* Use deco that matches what it would be for a function parameter
3878 */
3879 //buf.writestring(ea->type->toHeadMutable()->deco);
3880 buf.writestring(ea->type->deco);
3881 #else
3882 // Use type of parameter, not type of argument
3883 TemplateParameter *tp = (TemplateParameter *)tempdecl->parameters->data[i];
3884 assert(tp);
3885 TemplateValueParameter *tvp = tp->isTemplateValueParameter();
3886 assert(tvp);
3887 buf.writestring(tvp->valType->deco);
3888 #endif
3889 ea->toMangleBuffer(&buf);
3890 }
3891 else if (sa)
3892 {
3893 Lsa:
3894 buf.writeByte('S');
3895 Declaration *d = sa->isDeclaration();
3896 if (d && !d->type->deco)
3897 { error("forward reference of %s", d->toChars());
3898 continue;
3899 }
3900 #if 0
3901 VarDeclaration *v = sa->isVarDeclaration();
3902 if (v && v->storage_class & STCmanifest)
3903 { ExpInitializer *ei = v->init->isExpInitializer();
3904 if (ei)
3905 {
3906 ea = ei->exp;
3907 goto Lea;
3908 }
3909 }
3910 #endif
3911 const char *p = sa->mangle();
3912 buf.printf("%zu%s", strlen(p), p);
3913 }
3914 else if (va)
3915 {
3916 assert(i + 1 == args->dim); // must be last one
3917 args = &va->objects;
3918 i = -1;
3919 }
3920 else
3921 assert(0);
3922 }
3923 buf.writeByte('Z');
3924 id = buf.toChars();
3925 buf.data = NULL;
3926 //printf("\tgenIdent = %s\n", id);
3927 return new Identifier(id, TOKidentifier);
3928 }
3929
3930
3931 /****************************************************
3932 * Declare parameters of template instance, initialize them with the
3933 * template instance arguments.
3934 */
3935
3936 void TemplateInstance::declareParameters(Scope *scope)
3937 {
3938 //printf("TemplateInstance::declareParameters()\n");
3939 for (int i = 0; i < tdtypes.dim; i++)
3940 {
3941 TemplateParameter *tp = (TemplateParameter *)tempdecl->parameters->data[i];
3942 //Object *o = (Object *)tiargs->data[i];
3943 Object *o = (Object *)tdtypes.data[i]; // initializer for tp
3944
3945 //printf("\ttdtypes[%d] = %p\n", i, o);
3946 tempdecl->declareParameter(scope, tp, o);
3947 }
3948 }
3949
3950
3951 void TemplateInstance::semantic2(Scope *sc)
3952 { int i;
3953
3954 if (semanticdone >= 2)
3955 return;
3956 semanticdone = 2;
3957 #if LOG
3958 printf("+TemplateInstance::semantic2('%s')\n", toChars());
3959 #endif
3960 if (!errors && members)
3961 {
3962 sc = tempdecl->scope;
3963 assert(sc);
3964 sc = sc->push(argsym);
3965 sc = sc->push(this);
3966 sc->tinst = this;
3967 for (i = 0; i < members->dim; i++)
3968 {
3969 Dsymbol *s = (Dsymbol *)members->data[i];
3970 #if LOG
3971 printf("\tmember '%s', kind = '%s'\n", s->toChars(), s->kind());
3972 #endif
3973 s->semantic2(sc);
3974 }
3975 sc = sc->pop();
3976 sc->pop();
3977 }
3978 #if LOG
3979 printf("-TemplateInstance::semantic2('%s')\n", toChars());
3980 #endif
3981 }
3982
3983 void TemplateInstance::semantic3(Scope *sc)
3984 {
3985 #if LOG
3986 printf("TemplateInstance::semantic3('%s'), semanticdone = %d\n", toChars(), semanticdone);
3987 #endif
3988 //if (toChars()[0] == 'D') *(char*)0=0;
3989 if (semanticdone >= 3)
3990 return;
3991 semanticdone = 3;
3992 if (!errors && members)
3993 {
3994 sc = tempdecl->scope;
3995 sc = sc->push(argsym);
3996 sc = sc->push(this);
3997 sc->tinst = this;
3998 for (int i = 0; i < members->dim; i++)
3999 {
4000 Dsymbol *s = (Dsymbol *)members->data[i];
4001 s->semantic3(sc);
4002 }
4003 sc = sc->pop();
4004 sc->pop();
4005 }
4006 }
4007
4008 void TemplateInstance::toObjFile(int multiobj)
4009 {
4010 #if LOG
4011 printf("TemplateInstance::toObjFile('%s', this = %p)\n", toChars(), this);
4012 #endif
4013 if (!errors && members)
4014 {
4015 if (multiobj)
4016 // Append to list of object files to be written later
4017 //obj_append(this);
4018 assert(0 && "multiobj");
4019 else
4020 {
4021 for (int i = 0; i < members->dim; i++)
4022 {
4023 Dsymbol *s = (Dsymbol *)members->data[i];
4024 s->toObjFile(multiobj);
4025 }
4026 }
4027 }
4028 }
4029
4030 void TemplateInstance::inlineScan()
4031 {
4032 #if LOG
4033 printf("TemplateInstance::inlineScan('%s')\n", toChars());
4034 #endif
4035 if (!errors && members)
4036 {
4037 for (int i = 0; i < members->dim; i++)
4038 {
4039 Dsymbol *s = (Dsymbol *)members->data[i];
4040 s->inlineScan();
4041 }
4042 }
4043 }
4044
4045 void TemplateInstance::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
4046 {
4047 int i;
4048
4049 Identifier *id = name;
4050 buf->writestring(id->toChars());
4051 buf->writestring("!(");
4052 if (nest)
4053 buf->writestring("...");
4054 else
4055 {
4056 nest++;
4057 Objects *args = tiargs;
4058 for (i = 0; i < args->dim; i++)
4059 {
4060 if (i)
4061 buf->writeByte(',');
4062 Object *oarg = (Object *)args->data[i];
4063 ObjectToCBuffer(buf, hgs, oarg);
4064 }
4065 nest--;
4066 }
4067 buf->writeByte(')');
4068 }
4069
4070
4071 Dsymbol *TemplateInstance::toAlias()
4072 {
4073 #if LOG
4074 printf("TemplateInstance::toAlias()\n");
4075 #endif
4076 if (!inst)
4077 { error("cannot resolve forward reference");
4078 return this;
4079 }
4080
4081 if (inst != this)
4082 return inst->toAlias();
4083
4084 if (aliasdecl)
4085 return aliasdecl->toAlias();
4086
4087 return inst;
4088 }
4089
4090 AliasDeclaration *TemplateInstance::isAliasDeclaration()
4091 {
4092 return aliasdecl;
4093 }
4094
4095 const char *TemplateInstance::kind()
4096 {
4097 return "template instance";
4098 }
4099
4100 int TemplateInstance::oneMember(Dsymbol **ps)
4101 {
4102 *ps = NULL;
4103 return TRUE;
4104 }
4105
4106 char *TemplateInstance::toChars()
4107 {
4108 OutBuffer buf;
4109 HdrGenState hgs;
4110 char *s;
4111
4112 toCBuffer(&buf, &hgs);
4113 s = buf.toChars();
4114 buf.data = NULL;
4115 return s;
4116 }
4117
4118 void TemplateInstance::printInstantiationTrace()
4119 {
4120 if(global.gag)
4121 return;
4122
4123 const int max_shown = 6;
4124
4125 // determine instantiation depth
4126 int n_instantiations = 1;
4127 TemplateInstance* cur = this;
4128 while(cur = cur->tinst)
4129 ++n_instantiations;
4130
4131 // show full trace only if it's short or verbose is on
4132 if(n_instantiations <= max_shown || global.params.verbose)
4133 {
4134 cur = this;
4135 while(cur)
4136 {
4137 fprintf(stdmsg," instantiatied in %s: %s\n", cur->loc.toChars(), cur->toChars());
4138 cur = cur->tinst;
4139 }
4140 }
4141 else
4142 {
4143 cur = this;
4144 size_t i = 0;
4145 for(; i < max_shown/2; ++i, cur = cur->tinst)
4146 fprintf(stdmsg," instantiatied in %s: %s\n", cur->loc.toChars(), cur->toChars());
4147 fprintf(stdmsg," ... (%d instantiations, -v to show) ...\n", n_instantiations - max_shown);
4148 for(; i < n_instantiations - max_shown + max_shown/2; ++i, cur = cur->tinst)
4149 {}
4150 for(; i < n_instantiations; ++i, cur = cur->tinst)
4151 fprintf(stdmsg," instantiatied in %s: %s\n", cur->loc.toChars(), cur->toChars());
4152 }
4153 }
4154
4155 /* ======================== TemplateMixin ================================ */
4156
4157 TemplateMixin::TemplateMixin(Loc loc, Identifier *ident, Type *tqual,
4158 Array *idents, Objects *tiargs)
4159 : TemplateInstance(loc, (Identifier *)idents->data[idents->dim - 1])
4160 {
4161 //printf("TemplateMixin(ident = '%s')\n", ident ? ident->toChars() : "");
4162 this->ident = ident;
4163 this->tqual = tqual;
4164 this->idents = idents;
4165 this->tiargs = tiargs ? tiargs : new Objects();
4166 this->scope = NULL;
4167 }
4168
4169 Dsymbol *TemplateMixin::syntaxCopy(Dsymbol *s)
4170 { TemplateMixin *tm;
4171
4172 Array *ids = new Array();
4173 ids->setDim(idents->dim);
4174 for (int i = 0; i < idents->dim; i++)
4175 { // Matches TypeQualified::syntaxCopyHelper()
4176 Identifier *id = (Identifier *)idents->data[i];
4177 if (id->dyncast() == DYNCAST_DSYMBOL)
4178 {
4179 TemplateInstance *ti = (TemplateInstance *)id;
4180
4181 ti = (TemplateInstance *)ti->syntaxCopy(NULL);
4182 id = (Identifier *)ti;
4183 }
4184 ids->data[i] = id;
4185 }
4186
4187 tm = new TemplateMixin(loc, ident,
4188 (Type *)(tqual ? tqual->syntaxCopy() : NULL),
4189 ids, tiargs);
4190 TemplateInstance::syntaxCopy(tm);
4191 return tm;
4192 }
4193
4194 void TemplateMixin::semantic(Scope *sc)
4195 {
4196 #if LOG
4197 printf("+TemplateMixin::semantic('%s', this=%p)\n", toChars(), this);
4198 fflush(stdout);
4199 #endif
4200 if (semanticdone &&
4201 // This for when a class/struct contains mixin members, and
4202 // is done over because of forward references
4203 (!parent || !toParent()->isAggregateDeclaration()))
4204 {
4205 #if LOG
4206 printf("\tsemantic done\n");
4207 #endif
4208 return;
4209 }
4210 if (!semanticdone)
4211 semanticdone = 1;
4212 #if LOG
4213 printf("\tdo semantic\n");
4214 #endif
4215
4216 #if !IN_LLVM
4217 // dont know what this is
4218 util_progress();
4219 #endif
4220
4221 Scope *scx = NULL;
4222 if (scope)
4223 { sc = scope;
4224 scx = scope; // save so we don't make redundant copies
4225 scope = NULL;
4226 }
4227
4228 // Follow qualifications to find the TemplateDeclaration
4229 if (!tempdecl)
4230 { Dsymbol *s;
4231 int i;
4232 Identifier *id;
4233
4234 if (tqual)
4235 { s = tqual->toDsymbol(sc);
4236 i = 0;
4237 }
4238 else
4239 {
4240 i = 1;
4241 id = (Identifier *)idents->data[0];
4242 switch (id->dyncast())
4243 {
4244 case DYNCAST_IDENTIFIER:
4245 s = sc->search(loc, id, NULL);
4246 break;
4247
4248 case DYNCAST_DSYMBOL:
4249 {
4250 TemplateInstance *ti = (TemplateInstance *)id;
4251 ti->semantic(sc);
4252 s = ti;
4253 break;
4254 }
4255 default:
4256 assert(0);
4257 }
4258 }
4259
4260 for (; i < idents->dim; i++)
4261 {
4262 if (!s)
4263 break;
4264 id = (Identifier *)idents->data[i];
4265 s = s->searchX(loc, sc, id);
4266 }
4267 if (!s)
4268 {
4269 error("is not defined");
4270 inst = this;
4271 return;
4272 }
4273 tempdecl = s->toAlias()->isTemplateDeclaration();
4274 if (!tempdecl)
4275 {
4276 error("%s isn't a template", s->toChars());
4277 inst = this;
4278 return;
4279 }
4280 }
4281
4282 // Look for forward reference
4283 assert(tempdecl);
4284 for (TemplateDeclaration *td = tempdecl; td; td = td->overnext)
4285 {
4286 if (!td->scope)
4287 {
4288 /* Cannot handle forward references if mixin is a struct member,
4289 * because addField must happen during struct's semantic, not
4290 * during the mixin semantic.
4291 * runDeferred will re-run mixin's semantic outside of the struct's
4292 * semantic.
4293 */
4294 semanticdone = 0;
4295 AggregateDeclaration *ad = toParent()->isAggregateDeclaration();
4296 if (ad)
4297 ad->sizeok = 2;
4298 else
4299 {
4300 // Forward reference
4301 //printf("forward reference - deferring\n");
4302 scope = scx ? scx : new Scope(*sc);
4303 scope->setNoFree();
4304 scope->module->addDeferredSemantic(this);
4305 }
4306 return;
4307 }
4308 }
4309
4310 // Run semantic on each argument, place results in tiargs[]
4311 semanticTiargs(sc);
4312
4313 tempdecl = findBestMatch(sc);
4314 if (!tempdecl)
4315 { inst = this;
4316 return; // error recovery
4317 }
4318
4319 if (!ident)
4320 ident = genIdent();
4321
4322 inst = this;
4323 parent = sc->parent;
4324
4325 /* Detect recursive mixin instantiations.
4326 */
4327 for (Dsymbol *s = parent; s; s = s->parent)
4328 {
4329 //printf("\ts = '%s'\n", s->toChars());
4330 TemplateMixin *tm = s->isTemplateMixin();
4331 if (!tm || tempdecl != tm->tempdecl)
4332 continue;
4333
4334 /* Different argument list lengths happen with variadic args
4335 */
4336 if (tiargs->dim != tm->tiargs->dim)
4337 continue;
4338
4339 for (int i = 0; i < tiargs->dim; i++)
4340 { Object *o = (Object *)tiargs->data[i];
4341 Type *ta = isType(o);
4342 Expression *ea = isExpression(o);
4343 Dsymbol *sa = isDsymbol(o);
4344 Object *tmo = (Object *)tm->tiargs->data[i];
4345 if (ta)
4346 {
4347 Type *tmta = isType(tmo);
4348 if (!tmta)
4349 goto Lcontinue;
4350 if (!ta->equals(tmta))
4351 goto Lcontinue;
4352 }
4353 else if (ea)
4354 { Expression *tme = isExpression(tmo);
4355 if (!tme || !ea->equals(tme))
4356 goto Lcontinue;
4357 }
4358 else if (sa)
4359 {
4360 Dsymbol *tmsa = isDsymbol(tmo);
4361 if (sa != tmsa)
4362 goto Lcontinue;
4363 }
4364 else
4365 assert(0);
4366 }
4367 error("recursive mixin instantiation");
4368 return;
4369
4370 Lcontinue:
4371 continue;
4372 }
4373
4374 // Copy the syntax trees from the TemplateDeclaration
4375 members = Dsymbol::arraySyntaxCopy(tempdecl->members);
4376 if (!members)
4377 return;
4378
4379 symtab = new DsymbolTable();
4380
4381 for (Scope *sce = sc; 1; sce = sce->enclosing)
4382 {
4383 ScopeDsymbol *sds = (ScopeDsymbol *)sce->scopesym;
4384 if (sds)
4385 {
4386 sds->importScope(this, PROTpublic);
4387 break;
4388 }
4389 }
4390
4391 #if LOG
4392 printf("\tcreate scope for template parameters '%s'\n", toChars());
4393 #endif
4394 Scope *scy = sc;
4395 scy = sc->push(this);
4396 scy->parent = this;
4397
4398 argsym = new ScopeDsymbol();
4399 argsym->parent = scy->parent;
4400 Scope *scope = scy->push(argsym);
4401
4402 unsigned errorsave = global.errors;
4403
4404 // Declare each template parameter as an alias for the argument type
4405 declareParameters(scope);
4406
4407 // Add members to enclosing scope, as well as this scope
4408 for (unsigned i = 0; i < members->dim; i++)
4409 { Dsymbol *s;
4410
4411 s = (Dsymbol *)members->data[i];
4412 s->addMember(scope, this, i);
4413 //sc->insert(s);
4414 //printf("sc->parent = %p, sc->scopesym = %p\n", sc->parent, sc->scopesym);
4415 //printf("s->parent = %s\n", s->parent->toChars());
4416 }
4417
4418 // Do semantic() analysis on template instance members
4419 #if LOG
4420 printf("\tdo semantic() on template instance members '%s'\n", toChars());
4421 #endif
4422 Scope *sc2;
4423 sc2 = scope->push(this);
4424 sc2->offset = sc->offset;
4425 for (int i = 0; i < members->dim; i++)
4426 {
4427 Dsymbol *s = (Dsymbol *)members->data[i];
4428 s->semantic(sc2);
4429 }
4430 sc->offset = sc2->offset;
4431
4432 /* The problem is when to parse the initializer for a variable.
4433 * Perhaps VarDeclaration::semantic() should do it like it does
4434 * for initializers inside a function.
4435 */
4436 // if (sc->parent->isFuncDeclaration())
4437
4438 semantic2(sc2);
4439
4440 if (sc->func)
4441 {
4442 semantic3(sc2);
4443 }
4444
4445 // Give additional context info if error occurred during instantiation
4446 if (global.errors != errorsave)
4447 {
4448 error("error instantiating");
4449 }
4450
4451 sc2->pop();
4452
4453 scope->pop();
4454
4455 // if (!isAnonymous())
4456 {
4457 scy->pop();
4458 }
4459 #if LOG
4460 printf("-TemplateMixin::semantic('%s', this=%p)\n", toChars(), this);
4461 #endif
4462 }
4463
4464 void TemplateMixin::semantic2(Scope *sc)
4465 { int i;
4466
4467 if (semanticdone >= 2)
4468 return;
4469 semanticdone = 2;
4470 #if LOG
4471 printf("+TemplateMixin::semantic2('%s')\n", toChars());
4472 #endif
4473 if (members)
4474 {
4475 assert(sc);
4476 sc = sc->push(argsym);
4477 sc = sc->push(this);
4478 for (i = 0; i < members->dim; i++)
4479 {
4480 Dsymbol *s = (Dsymbol *)members->data[i];
4481 #if LOG
4482 printf("\tmember '%s', kind = '%s'\n", s->toChars(), s->kind());
4483 #endif
4484 s->semantic2(sc);
4485 }
4486 sc = sc->pop();
4487 sc->pop();
4488 }
4489 #if LOG
4490 printf("-TemplateMixin::semantic2('%s')\n", toChars());
4491 #endif
4492 }
4493
4494 void TemplateMixin::semantic3(Scope *sc)
4495 { int i;
4496
4497 if (semanticdone >= 3)
4498 return;
4499 semanticdone = 3;
4500 #if LOG
4501 printf("TemplateMixin::semantic3('%s')\n", toChars());
4502 #endif
4503 if (members)
4504 {
4505 sc = sc->push(argsym);
4506 sc = sc->push(this);
4507 for (i = 0; i < members->dim; i++)
4508 {
4509 Dsymbol *s = (Dsymbol *)members->data[i];
4510 s->semantic3(sc);
4511 }
4512 sc = sc->pop();
4513 sc->pop();
4514 }
4515 }
4516
4517 void TemplateMixin::inlineScan()
4518 {
4519 TemplateInstance::inlineScan();
4520 }
4521
4522 const char *TemplateMixin::kind()
4523 {
4524 return "mixin";
4525 }
4526
4527 int TemplateMixin::oneMember(Dsymbol **ps)
4528 {
4529 return Dsymbol::oneMember(ps);
4530 }
4531
4532 int TemplateMixin::hasPointers()
4533 {
4534 //printf("TemplateMixin::hasPointers() %s\n", toChars());
4535 for (size_t i = 0; i < members->dim; i++)
4536 {
4537 Dsymbol *s = (Dsymbol *)members->data[i];
4538 //printf(" s = %s %s\n", s->kind(), s->toChars());
4539 if (s->hasPointers())
4540 {
4541 return 1;
4542 }
4543 }
4544 return 0;
4545 }
4546
4547 char *TemplateMixin::toChars()
4548 {
4549 OutBuffer buf;
4550 HdrGenState hgs;
4551 char *s;
4552
4553 TemplateInstance::toCBuffer(&buf, &hgs);
4554 s = buf.toChars();
4555 buf.data = NULL;
4556 return s;
4557 }
4558
4559 void TemplateMixin::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
4560 {
4561 buf->writestring("mixin ");
4562
4563 for (int i = 0; i < idents->dim; i++)
4564 { Identifier *id = (Identifier *)idents->data[i];
4565
4566 if (i)
4567 buf->writeByte('.');
4568 buf->writestring(id->toChars());
4569 }
4570 buf->writestring("!(");
4571 if (tiargs)
4572 {
4573 for (int i = 0; i < tiargs->dim; i++)
4574 { if (i)
4575 buf->writebyte(',');
4576 Object *oarg = (Object *)tiargs->data[i];
4577 Type *t = isType(oarg);
4578 Expression *e = isExpression(oarg);
4579 Dsymbol *s = isDsymbol(oarg);
4580 if (t)
4581 t->toCBuffer(buf, NULL, hgs);
4582 else if (e)
4583 e->toCBuffer(buf, hgs);
4584 else if (s)
4585 {
4586 char *p = s->ident ? s->ident->toChars() : s->toChars();
4587 buf->writestring(p);
4588 }
4589 else if (!oarg)
4590 {
4591 buf->writestring("NULL");
4592 }
4593 else
4594 {
4595 assert(0);
4596 }
4597 }
4598 }
4599 buf->writebyte(')');
4600 if (ident)
4601 {
4602 buf->writebyte(' ');
4603 buf->writestring(ident->toChars());
4604 }
4605 buf->writebyte(';');
4606 buf->writenl();
4607 }
4608
4609
4610 void TemplateMixin::toObjFile(int multiobj)
4611 {
4612 //printf("TemplateMixin::toObjFile('%s')\n", toChars());
4613 TemplateInstance::toObjFile(multiobj);
4614 }
4615