1:
2: // Compiler implementation of the D programming language
3: // Copyright (c) 1999-2011 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: static char __file__[] = __FILE__; /* for tassert.h */
15: #include "tassert.h"
16:
17: #include "cdef.h"
18: #include "root.h"
19: #include "rmem.h"
20: #include "stringtable.h"
21:
22: #include "mtype.h"
23: #include "template.h"
24: #include "init.h"
25: #include "expression.h"
26: #include "scope.h"
27: #include "module.h"
28: #include "aggregate.h"
29: #include "declaration.h"
30: #include "dsymbol.h"
31: #include "mars.h"
32: #include "dsymbol.h"
33: #include "identifier.h"
34: #include "hdrgen.h"
35: #include "id.h"
36:
37: #if WINDOWS_SEH
38: #include <windows.h>
39: long __cdecl __ehfilter(LPEXCEPTION_POINTERS ep);
40: #endif
41:
42: #define LOG 0
43:
44: /********************************************
45: * These functions substitute for dynamic_cast. dynamic_cast does not work
46: * on earlier versions of gcc.
47: */
48:
49: Expression *isExpression(Object *o)
50: {
51: //return dynamic_cast<Expression *>(o);
52: if (!o || o->dyncast() != DYNCAST_EXPRESSION)
53: return NULL;
54: return (Expression *)o;
55: }
56:
57: Dsymbol *isDsymbol(Object *o)
58: {
59: //return dynamic_cast<Dsymbol *>(o);
60: if (!o || o->dyncast() != DYNCAST_DSYMBOL)
61: return NULL;
62: return (Dsymbol *)o;
63: }
64:
65: Type *isType(Object *o)
66: {
67: //return dynamic_cast<Type *>(o);
68: if (!o || o->dyncast() != DYNCAST_TYPE)
69: return NULL;
70: return (Type *)o;
71: }
72:
73: Tuple *isTuple(Object *o)
74: {
75: //return dynamic_cast<Tuple *>(o);
76: if (!o || o->dyncast() != DYNCAST_TUPLE)
77: return NULL;
78: return (Tuple *)o;
79: }
80:
81: /**************************************
82: * Is this Object an error?
83: */
84: int isError(Object *o)
85: {
86: Type *t = isType(o);
87: if (t)
88: return (t->ty == Terror);
89: Expression *e = isExpression(o);
90: if (e)
91: return (e->op == TOKerror);
92: Tuple *v = isTuple(o);
93: if (v)
94: return arrayObjectIsError(&v->objects);
95: return 0;
96: }
97:
98: /**************************************
99: * Are any of the Objects an error?
100: */
101: int arrayObjectIsError(Objects *args)
102: {
103: for (size_t i = 0; i < args->dim; i++)
104: {
105: Object *o = args->tdata()[i];
106: if (isError(o))
107: return 1;
108: }
109: return 0;
110: }
111:
112: /***********************
113: * Try to get arg as a type.
114: */
115:
116: Type *getType(Object *o)
117: {
118: Type *t = isType(o);
119: if (!t)
120: { Expression *e = isExpression(o);
121: if (e)
122: t = e->type;
123: }
124: return t;
125: }
126:
127: Dsymbol *getDsymbol(Object *oarg)
128: {
129: Dsymbol *sa;
130: Expression *ea = isExpression(oarg);
131: if (ea)
132: { // Try to convert Expression to symbol
133: if (ea->op == TOKvar)
134: sa = ((VarExp *)ea)->var;
135: else if (ea->op == TOKfunction)
136: sa = ((FuncExp *)ea)->fd;
137: else
138: sa = NULL;
139: }
140: else
141: { // Try to convert Type to symbol
142: Type *ta = isType(oarg);
143: if (ta)
144: sa = ta->toDsymbol(NULL);
145: else
146: sa = isDsymbol(oarg); // if already a symbol
147: }
148: return sa;
149: }
150:
151: /******************************
152: * If o1 matches o2, return 1.
153: * Else, return 0.
154: */
155:
156: int match(Object *o1, Object *o2, TemplateDeclaration *tempdecl, Scope *sc)
157: {
158: Type *t1 = isType(o1);
159: Type *t2 = isType(o2);
160: Expression *e1 = isExpression(o1);
161: Expression *e2 = isExpression(o2);
162: Dsymbol *s1 = isDsymbol(o1);
163: Dsymbol *s2 = isDsymbol(o2);
164: Tuple *v1 = isTuple(o1);
165: Tuple *v2 = isTuple(o2);
166:
167: //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);
168:
169: /* A proper implementation of the various equals() overrides
170: * should make it possible to just do o1->equals(o2), but
171: * we'll do that another day.
172: */
173:
174: if (s1)
175: {
176: VarDeclaration *v1 = s1->isVarDeclaration();
warning C6246: Local declaration of 'v1' hides declaration of the same name in outer scope. For additional information, see previous declaration at line '164' of 'c:\projects\extern\d\dmd\src\template.c': Lines: 164
177: if (v1 && v1->storage_class & STCmanifest)
178: { ExpInitializer *ei1 = v1->init->isExpInitializer();
179: if (ei1)
180: e1 = ei1->exp, s1 = NULL;
181: }
182: }
183: if (s2)
184: {
185: VarDeclaration *v2 = s2->isVarDeclaration();
warning C6246: Local declaration of 'v2' hides declaration of the same name in outer scope. For additional information, see previous declaration at line '165' of 'c:\projects\extern\d\dmd\src\template.c': Lines: 165
186: if (v2 && v2->storage_class & STCmanifest)
187: { ExpInitializer *ei2 = v2->init->isExpInitializer();
188: if (ei2)
189: e2 = ei2->exp, s2 = NULL;
190: }
191: }
192:
193: if (t1)
194: {
195: /* if t1 is an instance of ti, then give error
196: * about recursive expansions.
197: */
198: Dsymbol *s = t1->toDsymbol(sc);
199: if (s && s->parent)
200: { TemplateInstance *ti1 = s->parent->isTemplateInstance();
201: if (ti1 && ti1->tempdecl == tempdecl)
202: {
203: for (Scope *sc1 = sc; sc1; sc1 = sc1->enclosing)
204: {
205: if (sc1->scopesym == ti1)
206: {
207: error("recursive template expansion for template argument %s", t1->toChars());
208: return 1; // fake a match
209: }
210: }
211: }
212: }
213:
214: //printf("t1 = %s\n", t1->toChars());
215: //printf("t2 = %s\n", t2->toChars());
216: if (!t2 || !t1->equals(t2))
217: goto Lnomatch;
218: }
219: else if (e1)
220: {
221: #if 0
222: if (e1 && e2)
223: {
224: printf("match %d\n", e1->equals(e2));
225: e1->print();
226: e2->print();
227: e1->type->print();
228: e2->type->print();
229: }
230: #endif
231: if (!e2)
232: goto Lnomatch;
233: if (!e1->equals(e2))
234: goto Lnomatch;
235: }
236: else if (s1)
237: {
238: if (!s2 || !s1->equals(s2) || s1->parent != s2->parent)
239: goto Lnomatch;
240: }
241: else if (v1)
242: {
243: if (!v2)
244: goto Lnomatch;
245: if (v1->objects.dim != v2->objects.dim)
246: goto Lnomatch;
247: for (size_t i = 0; i < v1->objects.dim; i++)
248: {
249: if (!match(v1->objects.tdata()[i],
250: v2->objects.tdata()[i],
251: tempdecl, sc))
252: goto Lnomatch;
253: }
254: }
255: Lmatch:
warning C4102: 'Lmatch' : unreferenced label
256: //printf("match\n");
257: return 1; // match
258: Lnomatch:
259: //printf("nomatch\n");
260: return 0; // nomatch;
261: }
262:
263:
264: /************************************
265: * Match an array of them.
266: */
267: int arrayObjectMatch(Objects *oa1, Objects *oa2, TemplateDeclaration *tempdecl, Scope *sc)
268: {
269: if (oa1 == oa2)
270: return 1;
271: if (oa1->dim != oa2->dim)
272: return 0;
273: for (size_t j = 0; j < oa1->dim; j++)
274: { Object *o1 = oa1->tdata()[j];
275: Object *o2 = oa2->tdata()[j];
276: if (!match(o1, o2, tempdecl, sc))
277: {
278: return 0;
279: }
280: }
281: return 1;
282: }
283:
284: /****************************************
285: */
286:
287: void ObjectToCBuffer(OutBuffer *buf, HdrGenState *hgs, Object *oarg)
288: {
289: //printf("ObjectToCBuffer()\n");
290: Type *t = isType(oarg);
291: Expression *e = isExpression(oarg);
292: Dsymbol *s = isDsymbol(oarg);
293: Tuple *v = isTuple(oarg);
294: if (t)
295: { //printf("\tt: %s ty = %d\n", t->toChars(), t->ty);
296: t->toCBuffer(buf, NULL, hgs);
297: }
298: else if (e)
299: e->toCBuffer(buf, hgs);
300: else if (s)
301: {
302: char *p = s->ident ? s->ident->toChars() : s->toChars();
303: buf->writestring(p);
304: }
305: else if (v)
306: {
307: Objects *args = &v->objects;
308: for (size_t i = 0; i < args->dim; i++)
309: {
310: if (i)
311: buf->writeByte(',');
312: Object *o = args->tdata()[i];
313: ObjectToCBuffer(buf, hgs, o);
314: }
315: }
316: else if (!oarg)
317: {
318: buf->writestring("NULL");
319: }
320: else
321: {
322: #ifdef DEBUG
323: printf("bad Object = %p\n", oarg);
324: #endif
325: assert(0);
326: }
327: }
328:
329: #if DMDV2
330: Object *objectSyntaxCopy(Object *o)
331: {
332: if (!o)
333: return NULL;
334: Type *t = isType(o);
335: if (t)
336: return t->syntaxCopy();
337: Expression *e = isExpression(o);
338: if (e)
339: return e->syntaxCopy();
340: return o;
341: }
342: #endif
343:
344:
345: /* ======================== TemplateDeclaration ============================= */
346:
347: TemplateDeclaration::TemplateDeclaration(Loc loc, Identifier *id,
348: TemplateParameters *parameters, Expression *constraint, Dsymbols *decldefs, int ismixin)
349: : ScopeDsymbol(id)
350: {
351: #if LOG
352: printf("TemplateDeclaration(this = %p, id = '%s')\n", this, id->toChars());
353: #endif
354: #if 0
355: if (parameters)
356: for (int i = 0; i < parameters->dim; i++)
357: { TemplateParameter *tp = parameters->tdata()[i];
358: //printf("\tparameter[%d] = %p\n", i, tp);
359: TemplateTypeParameter *ttp = tp->isTemplateTypeParameter();
360:
361: if (ttp)
362: {
363: printf("\tparameter[%d] = %s : %s\n", i, tp->ident->toChars(), ttp->specType ? ttp->specType->toChars() : "");
364: }
365: }
366: #endif
367: this->loc = loc;
368: this->parameters = parameters;
369: this->origParameters = parameters;
370: this->constraint = constraint;
371: this->members = decldefs;
372: this->overnext = NULL;
373: this->overroot = NULL;
374: this->semanticRun = 0;
375: this->onemember = NULL;
376: this->literal = 0;
377: this->ismixin = ismixin;
378: this->previous = NULL;
379:
380: // Compute in advance for Ddoc's use
381: if (members)
382: {
383: Dsymbol *s;
384: if (Dsymbol::oneMembers(members, &s))
385: {
386: if (s && s->ident && s->ident->equals(ident))
387: {
388: onemember = s;
389: s->parent = this;
390: }
391: }
392: }
393: }
394:
395: Dsymbol *TemplateDeclaration::syntaxCopy(Dsymbol *)
396: {
397: //printf("TemplateDeclaration::syntaxCopy()\n");
398: TemplateDeclaration *td;
399: TemplateParameters *p;
400:
401: p = NULL;
402: if (parameters)
403: {
404: p = new TemplateParameters();
405: p->setDim(parameters->dim);
406: for (int i = 0; i < p->dim; i++)
warning C4018: '<' : signed/unsigned mismatch
407: { TemplateParameter *tp = parameters->tdata()[i];
408: p->tdata()[i] = tp->syntaxCopy();
409: }
410: }
411: Expression *e = NULL;
412: if (constraint)
413: e = constraint->syntaxCopy();
414: Dsymbols *d = Dsymbol::arraySyntaxCopy(members);
415: td = new TemplateDeclaration(loc, ident, p, e, d, ismixin);
416: return td;
417: }
418:
419: void TemplateDeclaration::semantic(Scope *sc)
420: {
421: #if LOG
422: printf("TemplateDeclaration::semantic(this = %p, id = '%s')\n", this, ident->toChars());
423: printf("sc->stc = %llx\n", sc->stc);
424: printf("sc->module = %s\n", sc->module->toChars());
425: #endif
426: if (semanticRun)
427: return; // semantic() already run
428: semanticRun = 1;
429:
430: if (sc->module && sc->module->ident == Id::object && ident == Id::AssociativeArray)
431: { Type::associativearray = this;
432: }
433:
434: if (sc->func)
435: {
436: #if DMDV1
437: error("cannot declare template at function scope %s", sc->func->toChars());
438: #endif
439: }
440:
441: if (/*global.params.useArrayBounds &&*/ sc->module)
442: {
443: // Generate this function as it may be used
444: // when template is instantiated in other modules
445: sc->module->toModuleArray();
446: }
447:
448: if (/*global.params.useAssert &&*/ sc->module)
449: {
450: // Generate this function as it may be used
451: // when template is instantiated in other modules
452: sc->module->toModuleAssert();
453: }
454:
455: #if DMDV2
456: if (/*global.params.useUnitTests &&*/ sc->module)
457: {
458: // Generate this function as it may be used
459: // when template is instantiated in other modules
460: sc->module->toModuleUnittest();
461: }
462: #endif
463:
464: /* Remember Scope for later instantiations, but make
465: * a copy since attributes can change.
466: */
467: this->scope = new Scope(*sc);
468: this->scope->setNoFree();
469:
470: // Set up scope for parameters
471: ScopeDsymbol *paramsym = new ScopeDsymbol();
472: paramsym->parent = sc->parent;
473: Scope *paramscope = sc->push(paramsym);
474: paramscope->parameterSpecialization = 1;
475: paramscope->stc = 0;
476:
477: if (!parent)
478: parent = sc->parent;
479:
480: if (global.params.doDocComments)
481: {
482: origParameters = new TemplateParameters();
483: origParameters->setDim(parameters->dim);
484: for (int i = 0; i < parameters->dim; i++)
warning C4018: '<' : signed/unsigned mismatch
485: {
486: TemplateParameter *tp = parameters->tdata()[i];
487: origParameters->tdata()[i] = tp->syntaxCopy();
488: }
489: }
490:
491: for (int i = 0; i < parameters->dim; i++)
warning C4018: '<' : signed/unsigned mismatch
492: {
493: TemplateParameter *tp = parameters->tdata()[i];
494:
495: tp->declareParameter(paramscope);
496: }
497:
498: for (int i = 0; i < parameters->dim; i++)
warning C4018: '<' : signed/unsigned mismatch
499: {
500: TemplateParameter *tp = parameters->tdata()[i];
501:
502: tp->semantic(paramscope);
503: if (i + 1 != parameters->dim && tp->isTemplateTupleParameter())
504: error("template tuple parameter must be last one");
505: }
506:
507: paramscope->pop();
508:
509: // Compute again
510: onemember = NULL;
511: if (members)
512: {
513: Dsymbol *s;
514: if (Dsymbol::oneMembers(members, &s))
515: {
516: if (s && s->ident && s->ident->equals(ident))
517: {
518: onemember = s;
519: s->parent = this;
520: }
521: }
522: }
523:
524: /* BUG: should check:
525: * o no virtual functions or non-static data members of classes
526: */
527: }
528:
529: const char *TemplateDeclaration::kind()
530: {
531: return (onemember && onemember->isAggregateDeclaration())
532: ? onemember->kind()
533: : (char *)"template";
534: }
535:
536: /**********************************
537: * Overload existing TemplateDeclaration 'this' with the new one 's'.
538: * Return !=0 if successful; i.e. no conflict.
539: */
540:
541: int TemplateDeclaration::overloadInsert(Dsymbol *s)
542: {
543: TemplateDeclaration **pf;
544: TemplateDeclaration *f;
545:
546: #if LOG
547: printf("TemplateDeclaration::overloadInsert('%s')\n", s->toChars());
548: #endif
549: f = s->isTemplateDeclaration();
550: if (!f)
551: return FALSE;
552: TemplateDeclaration *pthis = this;
553: for (pf = &pthis; *pf; pf = &(*pf)->overnext)
554: {
555: #if 0
556: // Conflict if TemplateParameter's match
557: // Will get caught anyway later with TemplateInstance, but
558: // should check it now.
559: TemplateDeclaration *f2 = *pf;
560:
561: if (f->parameters->dim != f2->parameters->dim)
562: goto Lcontinue;
563:
564: for (int i = 0; i < f->parameters->dim; i++)
565: { TemplateParameter *p1 = f->parameters->tdata()[i];
566: TemplateParameter *p2 = f2->parameters->tdata()[i];
567:
568: if (!p1->overloadMatch(p2))
569: goto Lcontinue;
570: }
571:
572: #if LOG
573: printf("\tfalse: conflict\n");
574: #endif
575: return FALSE;
576:
577: Lcontinue:
578: ;
579: #endif
580: }
581:
582: f->overroot = this;
583: *pf = f;
584: #if LOG
585: printf("\ttrue: no conflict\n");
586: #endif
587: return TRUE;
588: }
589:
590: /****************************
591: * Declare all the function parameters as variables
592: * and add them to the scope
593: */
594: void TemplateDeclaration::makeParamNamesVisibleInConstraint(Scope *paramscope, Expressions *fargs)
595: {
596: /* We do this ONLY if there is only one function in the template.
597: */
598: FuncDeclaration *fd = onemember && onemember->toAlias() ?
599: onemember->toAlias()->isFuncDeclaration() : NULL;
600: if (fd)
601: {
602: paramscope->parent = fd;
603: int fvarargs; // function varargs
604: Parameters *fparameters = fd->getParameters(&fvarargs);
605: size_t nfparams = Parameter::dim(fparameters); // Num function parameters
606: for (int i = 0; i < nfparams; i++)
warning C4018: '<' : signed/unsigned mismatch
607: {
608: Parameter *fparam = Parameter::getNth(fparameters, i)->syntaxCopy();
609: if (!fparam->ident)
610: continue; // don't add it, if it has no name
611: Type *vtype = fparam->type->syntaxCopy();
612: // isPure will segfault if called on a ctor, because fd->type is null.
613: if (fd->type && fd->isPure())
614: vtype = vtype->addMod(MODconst);
615: VarDeclaration *v = new VarDeclaration(loc, vtype, fparam->ident, NULL);
616: v->storage_class |= STCparameter;
617: // Not sure if this condition is correct/necessary.
618: // It's from func.c
619: if (//fd->type && fd->type->ty == Tfunction &&
620: fvarargs == 2 && i + 1 == nfparams)
621: v->storage_class |= STCvariadic;
622:
623: v->storage_class |= fparam->storageClass & (STCin | STCout | STCref | STClazy | STCfinal | STC_TYPECTOR | STCnodtor);
624: if (fparam->storageClass & STCauto)
625: {
626: if (fargs && i < fargs->dim)
warning C4018: '<' : signed/unsigned mismatch
627: { Expression *farg = fargs->tdata()[i];
628: if (farg->isLvalue())
629: ; // ref parameter
630: else
631: v->storage_class &= ~STCref; // value parameter
632: }
633: }
634:
635: v->semantic(paramscope);
636: if (!paramscope->insert(v))
637: error("parameter %s.%s is already defined", toChars(), v->toChars());
638: else
639: v->parent = this;
640: }
641: }
642: }
643:
644: /***************************************
645: * Given that ti is an instance of this TemplateDeclaration,
646: * deduce the types of the parameters to this, and store
647: * those deduced types in dedtypes[].
648: * Input:
649: * flag 1: don't do semantic() because of dummy types
650: * 2: don't change types in matchArg()
651: * Output:
652: * dedtypes deduced arguments
653: * Return match level.
654: */
655:
656: MATCH TemplateDeclaration::matchWithInstance(TemplateInstance *ti,
657: Objects *dedtypes, Expressions *fargs, int flag)
658: { MATCH m;
659: int dedtypes_dim = dedtypes->dim;
660:
661: #define LOGM 0
662: #if LOGM
663: printf("\n+TemplateDeclaration::matchWithInstance(this = %s, ti = %s, flag = %d)\n", toChars(), ti->toChars(), flag);
664: #endif
665:
666: #if 0
667: printf("dedtypes->dim = %d, parameters->dim = %d\n", dedtypes_dim, parameters->dim);
668: if (ti->tiargs->dim)
669: printf("ti->tiargs->dim = %d, [0] = %p\n",
670: ti->tiargs->dim,
671: ti->tiargs->tdata()[0]);
672: #endif
673: dedtypes->zero();
674:
675: int parameters_dim = parameters->dim;
676: int variadic = isVariadic() != NULL;
677:
678: // If more arguments than parameters, no match
679: if (ti->tiargs->dim > parameters_dim && !variadic)
warning C4018: '>' : signed/unsigned mismatch
680: {
681: #if LOGM
682: printf(" no match: more arguments than parameters\n");
683: #endif
684: return MATCHnomatch;
685: }
686:
687: assert(dedtypes_dim == parameters_dim);
688: assert(dedtypes_dim >= ti->tiargs->dim || variadic);
warning C4018: '>=' : signed/unsigned mismatch
689:
690: // Set up scope for parameters
691: assert((size_t)scope > 0x10000);
692: ScopeDsymbol *paramsym = new ScopeDsymbol();
693: paramsym->parent = scope->parent;
694: Scope *paramscope = scope->push(paramsym);
695: paramscope->stc = 0;
696:
697: // Attempt type deduction
698: m = MATCHexact;
699: for (int i = 0; i < dedtypes_dim; i++)
700: { MATCH m2;
701: TemplateParameter *tp = parameters->tdata()[i];
702: Declaration *sparam;
703:
704: //printf("\targument [%d]\n", i);
705: #if LOGM
706: //printf("\targument [%d] is %s\n", i, oarg ? oarg->toChars() : "null");
707: TemplateTypeParameter *ttp = tp->isTemplateTypeParameter();
708: if (ttp)
709: printf("\tparameter[%d] is %s : %s\n", i, tp->ident->toChars(), ttp->specType ? ttp->specType->toChars() : "");
710: #endif
711:
712: #if DMDV1
713: m2 = tp->matchArg(paramscope, ti->tiargs, i, parameters, dedtypes, &sparam);
714: #else
715: m2 = tp->matchArg(paramscope, ti->tiargs, i, parameters, dedtypes, &sparam, (flag & 2) ? 1 : 0);
716:
717: #endif
718: //printf("\tm2 = %d\n", m2);
719:
720: if (m2 == MATCHnomatch)
721: {
722: #if 0
723: printf("\tmatchArg() for parameter %i failed\n", i);
724: #endif
725: goto Lnomatch;
726: }
727:
728: if (m2 < m)
729: m = m2;
730:
731: if (!flag)
732: sparam->semantic(paramscope);
733: if (!paramscope->insert(sparam))
734: goto Lnomatch;
735: }
736:
737: if (!flag)
738: {
739: /* Any parameter left without a type gets the type of
740: * its corresponding arg
741: */
742: for (int i = 0; i < dedtypes_dim; i++)
743: {
744: if (!dedtypes->tdata()[i])
745: { assert(i < ti->tiargs->dim);
warning C4018: '<' : signed/unsigned mismatch
746: dedtypes->tdata()[i] = (Type *)ti->tiargs->tdata()[i];
747: }
748: }
749: }
750:
751: #if DMDV2
752: if (m && constraint && !(flag & 1))
753: { /* Check to see if constraint is satisfied.
754: */
755: makeParamNamesVisibleInConstraint(paramscope, fargs);
756: Expression *e = constraint->syntaxCopy();
757: Scope *sc = paramscope->push();
758: sc->flags |= SCOPEstaticif;
759: e = e->semantic(sc);
760: sc->pop();
761: e = e->optimize(WANTvalue | WANTinterpret);
762: if (e->isBool(TRUE))
763: ;
764: else if (e->isBool(FALSE))
765: goto Lnomatch;
766: else
767: {
768: e->error("constraint %s is not constant or does not evaluate to a bool", e->toChars());
769: }
770: }
771: #endif
772:
773: #if LOGM
774: // Print out the results
775: printf("--------------------------\n");
776: printf("template %s\n", toChars());
777: printf("instance %s\n", ti->toChars());
778: if (m)
779: {
780: for (int i = 0; i < dedtypes_dim; i++)
781: {
782: TemplateParameter *tp = parameters->tdata()[i];
783: Object *oarg;
784:
785: printf(" [%d]", i);
786:
787: if (i < ti->tiargs->dim)
788: oarg = ti->tiargs->tdata()[i];
789: else
790: oarg = NULL;
791: tp->print(oarg, dedtypes->tdata()[i]);
792: }
793: }
794: else
795: goto Lnomatch;
796: #endif
797:
798: #if LOGM
799: printf(" match = %d\n", m);
800: #endif
801: goto Lret;
802:
803: Lnomatch:
804: #if LOGM
805: printf(" no match\n");
806: #endif
807: m = MATCHnomatch;
808:
809: Lret:
810: paramscope->pop();
811: #if LOGM
812: printf("-TemplateDeclaration::matchWithInstance(this = %p, ti = %p) = %d\n", this, ti, m);
813: #endif
814: return m;
815: }
816:
817: /********************************************
818: * Determine partial specialization order of 'this' vs td2.
819: * Returns:
820: * match this is at least as specialized as td2
821: * 0 td2 is more specialized than this
822: */
823:
824: MATCH TemplateDeclaration::leastAsSpecialized(TemplateDeclaration *td2, Expressions *fargs)
825: {
826: /* This works by taking the template parameters to this template
827: * declaration and feeding them to td2 as if it were a template
828: * instance.
829: * If it works, then this template is at least as specialized
830: * as td2.
831: */
832:
833: TemplateInstance ti(0, ident); // create dummy template instance
834: Objects dedtypes;
835:
836: #define LOG_LEASTAS 0
837:
838: #if LOG_LEASTAS
839: printf("%s.leastAsSpecialized(%s)\n", toChars(), td2->toChars());
840: #endif
841:
842: // Set type arguments to dummy template instance to be types
843: // generated from the parameters to this template declaration
844: ti.tiargs = new Objects();
845: ti.tiargs->setDim(parameters->dim);
846: for (int i = 0; i < ti.tiargs->dim; i++)
warning C4018: '<' : signed/unsigned mismatch
847: {
848: TemplateParameter *tp = parameters->tdata()[i];
849:
850: Object *p = (Object *)tp->dummyArg();
851: if (p)
852: ti.tiargs->tdata()[i] = p;
853: else
854: ti.tiargs->setDim(i);
855: }
856:
857: // Temporary Array to hold deduced types
858: //dedtypes.setDim(parameters->dim);
859: dedtypes.setDim(td2->parameters->dim);
860:
861: // Attempt a type deduction
862: MATCH m = td2->matchWithInstance(&ti, &dedtypes, fargs, 1);
863: if (m)
864: {
865: /* A non-variadic template is more specialized than a
866: * variadic one.
867: */
868: if (isVariadic() && !td2->isVariadic())
869: goto L1;
870:
871: #if LOG_LEASTAS
872: printf(" matches %d, so is least as specialized\n", m);
873: #endif
874: return m;
875: }
876: L1:
877: #if LOG_LEASTAS
878: printf(" doesn't match, so is not as specialized\n");
879: #endif
880: return MATCHnomatch;
881: }
882:
883:
884: /*************************************************
885: * Match function arguments against a specific template function.
886: * Input:
887: * loc instantiation location
888: * targsi Expression/Type initial list of template arguments
889: * ethis 'this' argument if !NULL
890: * fargs arguments to function
891: * Output:
892: * dedargs Expression/Type deduced template arguments
893: * Returns:
894: * match level
895: */
896:
897: MATCH TemplateDeclaration::deduceFunctionTemplateMatch(Scope *sc, Loc loc, Objects *targsi,
898: Expression *ethis, Expressions *fargs,
899: Objects *dedargs)
900: {
901: size_t i;
902: size_t nfparams;
903: size_t nfargs;
904: size_t nargsi; // array size of targsi
905: int fptupindex = -1;
906: int tuple_dim = 0;
907: MATCH match = MATCHexact;
908: FuncDeclaration *fd = onemember->toAlias()->isFuncDeclaration();
909: Parameters *fparameters; // function parameter list
910: int fvarargs; // function varargs
911: Objects dedtypes; // for T:T*, the dedargs is the T*, dedtypes is the T
912:
913: #if 0
914: printf("\nTemplateDeclaration::deduceFunctionTemplateMatch() %s\n", toChars());
915: for (i = 0; i < fargs->dim; i++)
916: { Expression *e = fargs->tdata()[i];
917: printf("\tfarg[%d] is %s, type is %s\n", i, e->toChars(), e->type->toChars());
918: }
919: printf("fd = %s\n", fd->toChars());
920: printf("fd->type = %s\n", fd->type->toChars());
921: if (ethis)
922: printf("ethis->type = %s\n", ethis->type->toChars());
923: #endif
924:
925: assert((size_t)scope > 0x10000);
926:
927: dedargs->setDim(parameters->dim);
928: dedargs->zero();
929:
930: dedtypes.setDim(parameters->dim);
931: dedtypes.zero();
932:
933: // Set up scope for parameters
934: ScopeDsymbol *paramsym = new ScopeDsymbol();
935: paramsym->parent = scope->parent;
936: Scope *paramscope = scope->push(paramsym);
937: paramscope->stc = 0;
938:
939: TemplateTupleParameter *tp = isVariadic();
940: int tp_is_declared = 0;
941:
942: #if 0
943: for (i = 0; i < dedargs->dim; i++)
944: {
945: printf("\tdedarg[%d] = ", i);
946: Object *oarg = dedargs->tdata()[i];
947: if (oarg) printf("%s", oarg->toChars());
948: printf("\n");
949: }
950: #endif
951:
952:
953: nargsi = 0;
954: if (targsi)
955: { // Set initial template arguments
956:
957: nargsi = targsi->dim;
958: size_t n = parameters->dim;
959: if (tp)
960: n--;
961: if (nargsi > n)
962: { if (!tp)
963: goto Lnomatch;
964:
965: /* The extra initial template arguments
966: * now form the tuple argument.
967: */
968: Tuple *t = new Tuple();
969: assert(parameters->dim);
970: dedargs->tdata()[parameters->dim - 1] = t;
971:
972: tuple_dim = nargsi - n;
973: t->objects.setDim(tuple_dim);
974: for (size_t i = 0; i < tuple_dim; i++)
warning C4018: '<' : signed/unsigned mismatch
warning C6246: Local declaration of 'i' hides declaration of the same name in outer scope. For additional information, see previous declaration at line '901' of 'c:\projects\extern\d\dmd\src\template.c': Lines: 901
975: {
976: t->objects.tdata()[i] = targsi->tdata()[n + i];
977: }
978: declareParameter(paramscope, tp, t);
979: tp_is_declared = 1;
980: }
981: else
982: n = nargsi;
983:
984: memcpy(dedargs->tdata(), targsi->tdata(), n * sizeof(*dedargs->tdata()));
985:
986: for (size_t i = 0; i < n; i++)
warning C6246: Local declaration of 'i' hides declaration of the same name in outer scope. For additional information, see previous declaration at line '901' of 'c:\projects\extern\d\dmd\src\template.c': Lines: 901
987: { assert(i < parameters->dim);
988: TemplateParameter *tp = parameters->tdata()[i];
warning C6246: Local declaration of 'tp' hides declaration of the same name in outer scope. For additional information, see previous declaration at line '939' of 'c:\projects\extern\d\dmd\src\template.c': Lines: 939
989: MATCH m;
990: Declaration *sparam = NULL;
991:
992: m = tp->matchArg(paramscope, dedargs, i, parameters, &dedtypes, &sparam);
993: //printf("\tdeduceType m = %d\n", m);
994: if (m == MATCHnomatch)
995: goto Lnomatch;
996: if (m < match)
997: match = m;
998:
999: sparam->semantic(paramscope);
1000: if (!paramscope->insert(sparam))
1001: goto Lnomatch;
1002: }
1003: }
1004: #if 0
1005: for (i = 0; i < dedargs->dim; i++)
1006: {
1007: printf("\tdedarg[%d] = ", i);
1008: Object *oarg = dedargs->tdata()[i];
1009: if (oarg) printf("%s", oarg->toChars());
1010: printf("\n");
1011: }
1012: #endif
1013:
1014: fparameters = fd->getParameters(&fvarargs);
1015: nfparams = Parameter::dim(fparameters); // number of function parameters
1016: nfargs = fargs ? fargs->dim : 0; // number of function arguments
1017:
1018: /* Check for match of function arguments with variadic template
1019: * parameter, such as:
1020: *
1021: * template Foo(T, A...) { void Foo(T t, A a); }
1022: * void main() { Foo(1,2,3); }
1023: */
1024: if (tp) // if variadic
1025: {
1026: if (nfparams == 0 && nfargs != 0) // if no function parameters
1027: {
1028: if (tp_is_declared)
1029: goto L2;
1030: Tuple *t = new Tuple();
1031: //printf("t = %p\n", t);
1032: dedargs->tdata()[parameters->dim - 1] = t;
1033: declareParameter(paramscope, tp, t);
1034: goto L2;
1035: }
1036: else if (nfargs < nfparams - 1)
1037: goto L1;
1038: else
1039: {
1040: /* Figure out which of the function parameters matches
1041: * the tuple template parameter. Do this by matching
1042: * type identifiers.
1043: * Set the index of this function parameter to fptupindex.
1044: */
1045: for (fptupindex = 0; fptupindex < nfparams; fptupindex++)
warning C4018: '<' : signed/unsigned mismatch
1046: {
1047: Parameter *fparam = fparameters->tdata()[fptupindex];
1048: if (fparam->type->ty != Tident)
1049: continue;
1050: TypeIdentifier *tid = (TypeIdentifier *)fparam->type;
1051: if (!tp->ident->equals(tid->ident) || tid->idents.dim)
1052: continue;
1053:
1054: if (fvarargs) // variadic function doesn't
1055: goto Lnomatch; // go with variadic template
1056:
1057: if (tp_is_declared)
1058: goto L2;
1059:
1060: /* The types of the function arguments
1061: * now form the tuple argument.
1062: */
1063: Tuple *t = new Tuple();
1064: dedargs->tdata()[parameters->dim - 1] = t;
1065:
1066: tuple_dim = nfargs - (nfparams - 1);
1067: t->objects.setDim(tuple_dim);
1068: for (i = 0; i < tuple_dim; i++)
warning C4018: '<' : signed/unsigned mismatch
1069: { Expression *farg = fargs->tdata()[fptupindex + i];
1070: t->objects.tdata()[i] = farg->type;
1071: }
1072: declareParameter(paramscope, tp, t);
1073: goto L2;
1074: }
1075: fptupindex = -1;
1076: }
1077: }
1078:
1079: L1:
1080: if (nfparams == nfargs)
1081: ;
1082: else if (nfargs > nfparams)
1083: {
1084: if (fvarargs == 0)
1085: goto Lnomatch; // too many args, no match
1086: match = MATCHconvert; // match ... with a conversion
1087: }
1088:
1089: L2:
1090: #if DMDV2
1091: if (ethis)
1092: {
1093: // Match 'ethis' to any TemplateThisParameter's
1094: for (size_t i = 0; i < parameters->dim; i++)
warning C6246: Local declaration of 'i' hides declaration of the same name in outer scope. For additional information, see previous declaration at line '901' of 'c:\projects\extern\d\dmd\src\template.c': Lines: 901
1095: { TemplateParameter *tp = parameters->tdata()[i];
warning C6246: Local declaration of 'tp' hides declaration of the same name in outer scope. For additional information, see previous declaration at line '939' of 'c:\projects\extern\d\dmd\src\template.c': Lines: 939
1096: TemplateThisParameter *ttp = tp->isTemplateThisParameter();
1097: if (ttp)
1098: { MATCH m;
1099:
1100: Type *t = new TypeIdentifier(0, ttp->ident);
1101: m = ethis->type->deduceType(paramscope, t, parameters, &dedtypes);
1102: if (!m)
1103: goto Lnomatch;
1104: if (m < match)
1105: match = m; // pick worst match
1106: }
1107: }
1108:
1109: // Match attributes of ethis against attributes of fd
1110: if (fd->type)
1111: {
1112: Type *tthis = ethis->type;
1113: unsigned mod = fd->type->mod;
1114: StorageClass stc = scope->stc;
1115: // Propagate parent storage class (see bug 5504)
1116: Dsymbol *p = parent;
1117: while (p->isTemplateDeclaration() || p->isTemplateInstance())
1118: p = p->parent;
1119: AggregateDeclaration *ad = p->isAggregateDeclaration();
1120: if (ad)
1121: stc |= ad->storage_class;
1122:
1123: if (stc & (STCshared | STCsynchronized))
1124: mod |= MODshared;
1125: if (stc & STCimmutable)
1126: mod |= MODimmutable;
1127: if (stc & STCconst)
1128: mod |= MODconst;
1129: if (stc & STCwild)
1130: mod |= MODwild;
1131: // Fix mod
1132: if (mod & MODimmutable)
1133: mod = MODimmutable;
1134: if (mod & MODconst)
1135: mod &= ~STCwild;
1136: if (tthis->mod != mod)
1137: {
1138: if (!MODimplicitConv(tthis->mod, mod))
1139: goto Lnomatch;
1140: if (MATCHconst < match)
1141: match = MATCHconst;
1142: }
1143: }
1144: }
1145: #endif
1146:
1147: // Loop through the function parameters
1148: for (size_t parami = 0; parami < nfparams; parami++)
1149: {
1150: /* Skip over function parameters which wound up
1151: * as part of a template tuple parameter.
1152: */
1153: if (parami == fptupindex)
1154: continue;
1155: /* Set i = index into function arguments
1156: * Function parameters correspond to function arguments as follows.
1157: * Note that tuple_dim may be zero, and there may be default or
1158: * variadic arguments at the end.
1159: * arg [0..fptupindex] == param[0..fptupindex]
1160: * arg [fptupindex..fptupindex+tuple_dim] == param[fptupindex]
1161: * arg[fputupindex+dim.. ] == param[fptupindex+1.. ]
1162: */
1163: i = parami;
1164: if (fptupindex >= 0 && parami > fptupindex)
warning C4018: '>' : signed/unsigned mismatch
1165: i += tuple_dim - 1;
1166:
1167: Parameter *fparam = Parameter::getNth(fparameters, parami);
1168:
1169: if (i >= nfargs) // if not enough arguments
1170: {
1171: if (fparam->defaultArg)
1172: { /* Default arguments do not participate in template argument
1173: * deduction.
1174: */
1175: goto Lmatch;
1176: }
1177: }
1178: else
1179: { Expression *farg = fargs->tdata()[i];
1180: #if 0
1181: printf("\tfarg->type = %s\n", farg->type->toChars());
1182: printf("\tfparam->type = %s\n", fparam->type->toChars());
1183: #endif
1184: Type *argtype = farg->type;
1185:
1186: #if DMDV2
1187: /* Allow string literals which are type [] to match with [dim]
1188: */
1189: if (farg->op == TOKstring)
1190: { StringExp *se = (StringExp *)farg;
1191: if (!se->committed && argtype->ty == Tarray &&
1192: fparam->type->toBasetype()->ty == Tsarray)
1193: {
1194: argtype = new TypeSArray(argtype->nextOf(), new IntegerExp(se->loc, se->len, Type::tindex));
1195: argtype = argtype->semantic(se->loc, NULL);
1196: argtype = argtype->invariantOf();
1197: }
1198: }
1199: #endif
1200:
1201: MATCH m;
1202: m = argtype->deduceType(paramscope, fparam->type, parameters, &dedtypes);
1203: //printf("\tdeduceType m = %d\n", m);
1204:
1205: /* If no match, see if there's a conversion to a delegate
1206: */
1207: if (!m && fparam->type->toBasetype()->ty == Tdelegate)
1208: {
1209: TypeDelegate *td = (TypeDelegate *)fparam->type->toBasetype();
1210: TypeFunction *tf = (TypeFunction *)td->next;
1211:
1212: if (!tf->varargs && Parameter::dim(tf->parameters) == 0)
1213: {
1214: m = farg->type->deduceType(paramscope, tf->next, parameters, &dedtypes);
1215: if (!m && tf->next->toBasetype()->ty == Tvoid)
1216: m = MATCHconvert;
1217: }
1218: //printf("\tm2 = %d\n", m);
1219: }
1220:
1221: if (m)
1222: { if (m < match)
1223: match = m; // pick worst match
1224: continue;
1225: }
1226: }
1227:
1228: /* The following code for variadic arguments closely
1229: * matches TypeFunction::callMatch()
1230: */
1231: if (!(fvarargs == 2 && i + 1 == nfparams))
1232: goto Lnomatch;
1233:
1234: /* Check for match with function parameter T...
1235: */
1236: Type *tb = fparam->type->toBasetype();
1237: switch (tb->ty)
1238: {
1239: // Perhaps we can do better with this, see TypeFunction::callMatch()
1240: case Tsarray:
1241: { TypeSArray *tsa = (TypeSArray *)tb;
1242: dinteger_t sz = tsa->dim->toInteger();
1243: if (sz != nfargs - i)
1244: goto Lnomatch;
1245: }
1246: case Tarray:
1247: { TypeArray *ta = (TypeArray *)tb;
1248: for (; i < nfargs; i++)
1249: {
1250: Expression *arg = fargs->tdata()[i];
1251: assert(arg);
1252: MATCH m;
1253: /* If lazy array of delegates,
1254: * convert arg(s) to delegate(s)
1255: */
1256: Type *tret = fparam->isLazyArray();
1257: if (tret)
1258: {
1259: if (ta->next->equals(arg->type))
1260: { m = MATCHexact;
1261: }
1262: else
1263: {
1264: m = arg->implicitConvTo(tret);
1265: if (m == MATCHnomatch)
1266: {
1267: if (tret->toBasetype()->ty == Tvoid)
1268: m = MATCHconvert;
1269: }
1270: }
1271: }
1272: else
1273: {
1274: m = arg->type->deduceType(paramscope, ta->next, parameters, &dedtypes);
1275: //m = arg->implicitConvTo(ta->next);
1276: }
1277: if (m == MATCHnomatch)
1278: goto Lnomatch;
1279: if (m < match)
1280: match = m;
1281: }
1282: goto Lmatch;
1283: }
1284: case Tclass:
1285: case Tident:
1286: goto Lmatch;
1287:
1288: default:
1289: goto Lnomatch;
1290: }
1291: }
1292:
1293: Lmatch:
1294:
1295: for (i = nargsi; i < dedargs->dim; i++)
1296: {
1297: TemplateParameter *tparam = parameters->tdata()[i];
1298: //printf("tparam[%d] = %s\n", i, tparam->ident->toChars());
1299: /* For T:T*, the dedargs is the T*, dedtypes is the T
1300: * But for function templates, we really need them to match
1301: */
1302: Object *oarg = dedargs->tdata()[i];
1303: Object *oded = dedtypes.tdata()[i];
1304: //printf("1dedargs[%d] = %p, dedtypes[%d] = %p\n", i, oarg, i, oded);
1305: //if (oarg) printf("oarg: %s\n", oarg->toChars());
1306: //if (oded) printf("oded: %s\n", oded->toChars());
1307: if (!oarg)
1308: {
1309: if (oded)
1310: {
1311: if (tparam->specialization())
1312: { /* The specialization can work as long as afterwards
1313: * the oded == oarg
1314: */
1315: Declaration *sparam;
1316: dedargs->tdata()[i] = oded;
1317: MATCH m2 = tparam->matchArg(paramscope, dedargs, i, parameters, &dedtypes, &sparam, 0);
1318: //printf("m2 = %d\n", m2);
1319: if (!m2)
1320: goto Lnomatch;
1321: if (m2 < match)
1322: match = m2; // pick worst match
1323: if (dedtypes.tdata()[i] != oded)
1324: error("specialization not allowed for deduced parameter %s", tparam->ident->toChars());
1325: }
1326: }
1327: else
1328: { oded = tparam->defaultArg(loc, paramscope);
1329: if (!oded)
1330: {
1331: if (tp && // if tuple parameter and
1332: fptupindex < 0 && // tuple parameter was not in function parameter list and
1333: nargsi == dedargs->dim - 1) // we're one argument short (i.e. no tuple argument)
1334: { // make tuple argument an empty tuple
1335: oded = (Object *)new Tuple();
1336: }
1337: else
1338: goto Lnomatch;
1339: }
1340: }
1341: declareParameter(paramscope, tparam, oded);
1342: dedargs->tdata()[i] = oded;
1343: }
1344: }
1345:
1346: #if DMDV2
1347: if (constraint)
1348: { /* Check to see if constraint is satisfied.
1349: */
1350: makeParamNamesVisibleInConstraint(paramscope, fargs);
1351: Expression *e = constraint->syntaxCopy();
1352: paramscope->flags |= SCOPEstaticif;
1353:
1354: /* Detect recursive attempts to instantiate this template declaration,
1355: * Bugzilla 4072
1356: * void foo(T)(T x) if (is(typeof(foo(x)))) { }
1357: * static assert(!is(typeof(foo(7))));
1358: * Recursive attempts are regarded as a constraint failure.
1359: */
1360: int nmatches = 0;
1361: for (Previous *p = previous; p; p = p->prev)
1362: {
1363: if (arrayObjectMatch(p->dedargs, dedargs, this, sc))
1364: {
1365: //printf("recursive, no match p->sc=%p %p %s\n", p->sc, this, this->toChars());
1366: /* It must be a subscope of p->sc, other scope chains are not recursive
1367: * instantiations.
1368: */
1369: for (Scope *scx = sc; scx; scx = scx->enclosing)
1370: {
1371: if (scx == p->sc)
1372: goto Lnomatch;
1373: }
1374: }
1375: /* BUG: should also check for ref param differences
1376: */
1377: }
1378:
1379: Previous pr;
1380: pr.prev = previous;
1381: pr.sc = paramscope;
1382: pr.dedargs = dedargs;
1383: previous = ≺ // add this to threaded list
1384:
1385: int nerrors = global.errors;
1386:
1387: e = e->semantic(paramscope);
1388:
1389: previous = pr.prev; // unlink from threaded list
1390:
1391: if (nerrors != global.errors) // if any errors from evaluating the constraint, no match
1392: goto Lnomatch;
1393:
1394: e = e->optimize(WANTvalue | WANTinterpret);
1395: if (e->isBool(TRUE))
1396: ;
1397: else if (e->isBool(FALSE))
1398: goto Lnomatch;
1399: else
1400: {
1401: e->error("constraint %s is not constant or does not evaluate to a bool", e->toChars());
1402: }
1403: }
1404: #endif
1405:
1406: #if 0
1407: for (i = 0; i < dedargs->dim; i++)
1408: { Type *t = dedargs->tdata()[i];
1409: printf("\tdedargs[%d] = %d, %s\n", i, t->dyncast(), t->toChars());
1410: }
1411: #endif
1412:
1413: paramscope->pop();
1414: //printf("\tmatch %d\n", match);
1415: return match;
1416:
1417: Lnomatch:
1418: paramscope->pop();
1419: //printf("\tnomatch\n");
1420: return MATCHnomatch;
1421: }
1422:
1423: /**************************************************
1424: * Declare template parameter tp with value o, and install it in the scope sc.
1425: */
1426:
1427: void TemplateDeclaration::declareParameter(Scope *sc, TemplateParameter *tp, Object *o)
1428: {
1429: //printf("TemplateDeclaration::declareParameter('%s', o = %p)\n", tp->ident->toChars(), o);
1430:
1431: Type *targ = isType(o);
1432: Expression *ea = isExpression(o);
1433: Dsymbol *sa = isDsymbol(o);
1434: Tuple *va = isTuple(o);
1435:
1436: Dsymbol *s;
1437:
1438: // See if tp->ident already exists with a matching definition
1439: Dsymbol *scopesym;
1440: s = sc->search(loc, tp->ident, &scopesym);
1441: if (s && scopesym == sc->scopesym)
1442: {
1443: TupleDeclaration *td = s->isTupleDeclaration();
1444: if (va && td)
1445: { Tuple tup;
1446: tup.objects = *td->objects;
1447: if (match(va, &tup, this, sc))
1448: {
1449: return;
1450: }
1451: }
1452: }
1453:
1454: if (targ)
1455: {
1456: //printf("type %s\n", targ->toChars());
1457: s = new AliasDeclaration(0, tp->ident, targ);
1458: }
1459: else if (sa)
1460: {
1461: //printf("Alias %s %s;\n", sa->ident->toChars(), tp->ident->toChars());
1462: s = new AliasDeclaration(0, tp->ident, sa);
1463: }
1464: else if (ea)
1465: {
1466: // tdtypes.data[i] always matches ea here
1467: Initializer *init = new ExpInitializer(loc, ea);
1468: TemplateValueParameter *tvp = tp->isTemplateValueParameter();
1469:
1470: Type *t = tvp ? tvp->valType : NULL;
1471:
1472: VarDeclaration *v = new VarDeclaration(loc, t, tp->ident, init);
1473: v->storage_class = STCmanifest;
1474: s = v;
1475: }
1476: else if (va)
1477: {
1478: //printf("\ttuple\n");
1479: s = new TupleDeclaration(loc, tp->ident, &va->objects);
1480: }
1481: else
1482: {
1483: #ifdef DEBUG
1484: o->print();
1485: #endif
1486: assert(0);
1487: }
1488: if (!sc->insert(s))
1489: error("declaration %s is already defined", tp->ident->toChars());
1490: s->semantic(sc);
1491: }
1492:
1493: /**************************************
1494: * Determine if TemplateDeclaration is variadic.
1495: */
1496:
1497: TemplateTupleParameter *isVariadic(TemplateParameters *parameters)
1498: { size_t dim = parameters->dim;
1499: TemplateTupleParameter *tp = NULL;
1500:
1501: if (dim)
1502: tp = (parameters->tdata()[dim - 1])->isTemplateTupleParameter();
1503: return tp;
1504: }
1505:
1506: TemplateTupleParameter *TemplateDeclaration::isVariadic()
1507: {
1508: return ::isVariadic(parameters);
1509: }
1510:
1511: /***********************************
1512: * We can overload templates.
1513: */
1514:
1515: int TemplateDeclaration::isOverloadable()
1516: {
1517: return 1;
1518: }
1519:
1520: /*************************************************
1521: * Given function arguments, figure out which template function
1522: * to expand, and return that function.
1523: * If no match, give error message and return NULL.
1524: * Input:
1525: * sc instantiation scope
1526: * loc instantiation location
1527: * targsi initial list of template arguments
1528: * ethis if !NULL, the 'this' pointer argument
1529: * fargs arguments to function
1530: * flags 1: do not issue error message on no match, just return NULL
1531: */
1532:
1533: FuncDeclaration *TemplateDeclaration::deduceFunctionTemplate(Scope *sc, Loc loc,
1534: Objects *targsi, Expression *ethis, Expressions *fargs, int flags)
1535: {
1536: MATCH m_best = MATCHnomatch;
1537: TemplateDeclaration *td_ambig = NULL;
1538: TemplateDeclaration *td_best = NULL;
1539: Objects *tdargs = new Objects();
1540: TemplateInstance *ti;
1541: FuncDeclaration *fd;
1542:
1543: #if 0
1544: printf("TemplateDeclaration::deduceFunctionTemplate() %s\n", toChars());
1545: printf(" targsi:\n");
1546: if (targsi)
1547: { for (int i = 0; i < targsi->dim; i++)
1548: { Object *arg = targsi->tdata()[i];
1549: printf("\t%s\n", arg->toChars());
1550: }
1551: }
1552: printf(" fargs:\n");
1553: for (int i = 0; i < fargs->dim; i++)
1554: { Expression *arg = fargs->tdata()[i];
1555: printf("\t%s %s\n", arg->type->toChars(), arg->toChars());
1556: //printf("\tty = %d\n", arg->type->ty);
1557: }
1558: printf("stc = %llx\n", scope->stc);
1559: #endif
1560:
1561: for (TemplateDeclaration *td = this; td; td = td->overnext)
1562: {
1563: if (!td->semanticRun)
1564: {
1565: error("forward reference to template %s", td->toChars());
1566: goto Lerror;
1567: }
1568: if (!td->onemember || !td->onemember->toAlias()->isFuncDeclaration())
1569: {
1570: error("is not a function template");
1571: goto Lerror;
1572: }
1573:
1574: MATCH m;
1575: Objects dedargs;
1576:
1577: m = td->deduceFunctionTemplateMatch(sc, loc, targsi, ethis, fargs, &dedargs);
1578: //printf("deduceFunctionTemplateMatch = %d\n", m);
1579: if (!m) // if no match
1580: continue;
1581:
1582: if (m < m_best)
1583: goto Ltd_best;
1584: if (m > m_best)
1585: goto Ltd;
1586:
1587: {
1588: // Disambiguate by picking the most specialized TemplateDeclaration
1589: MATCH c1 = td->leastAsSpecialized(td_best, fargs);
1590: MATCH c2 = td_best->leastAsSpecialized(td, fargs);
1591: //printf("c1 = %d, c2 = %d\n", c1, c2);
1592:
1593: if (c1 > c2)
1594: goto Ltd;
1595: else if (c1 < c2)
1596: goto Ltd_best;
1597: else
1598: goto Lambig;
1599: }
1600:
1601: Lambig: // td_best and td are ambiguous
1602: td_ambig = td;
1603: continue;
1604:
1605: Ltd_best: // td_best is the best match so far
1606: td_ambig = NULL;
1607: continue;
1608:
1609: Ltd: // td is the new best match
1610: td_ambig = NULL;
1611: assert((size_t)td->scope > 0x10000);
1612: td_best = td;
1613: m_best = m;
1614: tdargs->setDim(dedargs.dim);
1615: memcpy(tdargs->tdata(), dedargs.tdata(), tdargs->dim * sizeof(void *));
1616: continue;
1617: }
1618: if (!td_best)
1619: {
1620: if (!(flags & 1))
1621: error(loc, "does not match any function template declaration");
1622: goto Lerror;
1623: }
1624: if (td_ambig)
1625: {
1626: error(loc, "%s matches more than one template declaration, %s(%d):%s and %s(%d):%s",
1627: toChars(),
1628: td_best->loc.filename, td_best->loc.linnum, td_best->toChars(),
1629: td_ambig->loc.filename, td_ambig->loc.linnum, td_ambig->toChars());
1630: }
1631:
1632: /* The best match is td_best with arguments tdargs.
1633: * Now instantiate the template.
1634: */
1635: assert((size_t)td_best->scope > 0x10000);
1636: ti = new TemplateInstance(loc, td_best, tdargs);
1637: ti->semantic(sc, fargs);
1638: fd = ti->toAlias()->isFuncDeclaration();
1639: if (!fd)
1640: goto Lerror;
1641: return fd;
1642:
1643: Lerror:
1644: #if DMDV2
1645: if (!(flags & 1))
1646: #endif
1647: {
1648: HdrGenState hgs;
1649:
1650: OutBuffer bufa;
1651: Objects *args = targsi;
1652: if (args)
1653: { for (int i = 0; i < args->dim; i++)
warning C4018: '<' : signed/unsigned mismatch
1654: {
1655: if (i)
1656: bufa.writeByte(',');
1657: Object *oarg = args->tdata()[i];
1658: ObjectToCBuffer(&bufa, &hgs, oarg);
1659: }
1660: }
1661:
1662: OutBuffer buf;
1663: argExpTypesToCBuffer(&buf, fargs, &hgs);
1664: error(loc, "cannot deduce template function from argument types !(%s)(%s)",
1665: bufa.toChars(), buf.toChars());
1666: }
1667: return NULL;
1668: }
1669:
1670: void TemplateDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
1671: {
1672: #if 0 // Should handle template functions for doc generation
1673: if (onemember && onemember->isFuncDeclaration())
1674: buf->writestring("foo ");
1675: #endif
1676: if (hgs->ddoc)
1677: buf->writestring(kind());
1678: else
1679: buf->writestring("template");
1680: buf->writeByte(' ');
1681: buf->writestring(ident->toChars());
1682: buf->writeByte('(');
1683: for (int i = 0; i < parameters->dim; i++)
warning C4018: '<' : signed/unsigned mismatch
1684: {
1685: TemplateParameter *tp = parameters->tdata()[i];
1686: if (hgs->ddoc)
1687: tp = origParameters->tdata()[i];
1688: if (i)
1689: buf->writeByte(',');
1690: tp->toCBuffer(buf, hgs);
1691: }
1692: buf->writeByte(')');
1693: #if DMDV2
1694: if (constraint)
1695: { buf->writestring(" if (");
1696: constraint->toCBuffer(buf, hgs);
1697: buf->writeByte(')');
1698: }
1699: #endif
1700:
1701: if (hgs->hdrgen)
1702: {
1703: hgs->tpltMember++;
1704: buf->writenl();
1705: buf->writebyte('{');
1706: buf->writenl();
1707: for (int i = 0; i < members->dim; i++)
warning C4018: '<' : signed/unsigned mismatch
1708: {
1709: Dsymbol *s = members->tdata()[i];
1710: s->toCBuffer(buf, hgs);
1711: }
1712: buf->writebyte('}');
1713: buf->writenl();
1714: hgs->tpltMember--;
1715: }
1716: }
1717:
1718:
1719: char *TemplateDeclaration::toChars()
1720: { OutBuffer buf;
1721: HdrGenState hgs;
1722:
1723: memset(&hgs, 0, sizeof(hgs));
1724: buf.writestring(ident->toChars());
1725: buf.writeByte('(');
1726: for (int i = 0; i < parameters->dim; i++)
warning C4018: '<' : signed/unsigned mismatch
1727: {
1728: TemplateParameter *tp = parameters->tdata()[i];
1729: if (i)
1730: buf.writeByte(',');
1731: tp->toCBuffer(&buf, &hgs);
1732: }
1733: buf.writeByte(')');
1734: #if DMDV2
1735: if (constraint)
1736: { buf.writestring(" if (");
1737: constraint->toCBuffer(&buf, &hgs);
1738: buf.writeByte(')');
1739: }
1740: #endif
1741: buf.writeByte(0);
1742: return (char *)buf.extractData();
1743: }
1744:
1745: /* ======================== Type ============================================ */
1746:
1747: /****
1748: * Given an identifier, figure out which TemplateParameter it is.
1749: * Return -1 if not found.
1750: */
1751:
1752: int templateIdentifierLookup(Identifier *id, TemplateParameters *parameters)
1753: {
1754: for (size_t i = 0; i < parameters->dim; i++)
1755: { TemplateParameter *tp = parameters->tdata()[i];
1756:
1757: if (tp->ident->equals(id))
1758: return i;
1759: }
1760: return -1;
1761: }
1762:
1763: int templateParameterLookup(Type *tparam, TemplateParameters *parameters)
1764: {
1765: assert(tparam->ty == Tident);
1766: TypeIdentifier *tident = (TypeIdentifier *)tparam;
1767: //printf("\ttident = '%s'\n", tident->toChars());
1768: if (tident->idents.dim == 0)
1769: {
1770: return templateIdentifierLookup(tident->ident, parameters);
1771: }
1772: return -1;
1773: }
1774:
1775: /* These form the heart of template argument deduction.
1776: * Given 'this' being the type argument to the template instance,
1777: * it is matched against the template declaration parameter specialization
1778: * 'tparam' to determine the type to be used for the parameter.
1779: * Example:
1780: * template Foo(T:T*) // template declaration
1781: * Foo!(int*) // template instantiation
1782: * Input:
1783: * this = int*
1784: * tparam = T
1785: * parameters = [ T:T* ] // Array of TemplateParameter's
1786: * Output:
1787: * dedtypes = [ int ] // Array of Expression/Type's
1788: */
1789:
1790: MATCH Type::deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters,
1791: Objects *dedtypes)
1792: {
1793: #if 0
1794: printf("Type::deduceType()\n");
1795: printf("\tthis = %d, ", ty); print();
1796: printf("\ttparam = %d, ", tparam->ty); tparam->print();
1797: #endif
1798: if (!tparam)
1799: goto Lnomatch;
1800:
1801: if (this == tparam)
1802: goto Lexact;
1803:
1804: if (tparam->ty == Tident)
1805: {
1806: // Determine which parameter tparam is
1807: int i = templateParameterLookup(tparam, parameters);
1808: if (i == -1)
1809: {
1810: if (!sc)
1811: goto Lnomatch;
1812:
1813: /* Need a loc to go with the semantic routine.
1814: */
1815: Loc loc;
1816: if (parameters->dim)
1817: {
1818: TemplateParameter *tp = parameters->tdata()[0];
1819: loc = tp->loc;
1820: }
1821:
1822: /* BUG: what if tparam is a template instance, that
1823: * has as an argument another Tident?
1824: */
1825: tparam = tparam->semantic(loc, sc);
1826: assert(tparam->ty != Tident);
1827: return deduceType(sc, tparam, parameters, dedtypes);
1828: }
1829:
1830: TemplateParameter *tp = parameters->tdata()[i];
1831:
1832: // Found the corresponding parameter tp
1833: if (!tp->isTemplateTypeParameter())
1834: goto Lnomatch;
1835: Type *tt = this;
1836: Type *at = (Type *)dedtypes->tdata()[i];
1837:
1838: // 7*7 == 49 cases
1839:
1840: #define X(U,T) ((U) << 4) | (T)
1841: switch (X(tparam->mod, mod))
1842: {
1843: case X(0, 0):
1844: case X(0, MODconst):
1845: case X(0, MODimmutable):
1846: case X(0, MODshared):
1847: case X(0, MODconst | MODshared):
1848: case X(0, MODwild):
1849: case X(0, MODwild | MODshared):
1850: // foo(U:U) T => T
1851: // foo(U:U) const(T) => const(T)
1852: // foo(U:U) immutable(T) => immutable(T)
1853: // foo(U:U) shared(T) => shared(T)
1854: // foo(U:U) const(shared(T)) => const(shared(T))
1855: // foo(U:U) wild(T) => wild(T)
1856: // foo(U:U) wild(shared(T)) => wild(shared(T))
1857: if (!at)
1858: { dedtypes->tdata()[i] = tt;
1859: goto Lexact;
1860: }
1861: break;
1862:
1863: case X(MODconst, MODconst):
1864: case X(MODimmutable, MODimmutable):
1865: case X(MODshared, MODshared):
1866: case X(MODconst | MODshared, MODconst | MODshared):
1867: case X(MODwild, MODwild):
1868: case X(MODwild | MODshared, MODwild | MODshared):
1869: // foo(U:const(U)) const(T) => T
1870: // foo(U:immutable(U)) immutable(T) => T
1871: // foo(U:shared(U)) shared(T) => T
1872: // foo(U:const(shared(U)) const(shared(T)) => T
1873: // foo(U:wild(U)) wild(T) => T
1874: // foo(U:wild(shared(U)) wild(shared(T)) => T
1875: tt = mutableOf()->unSharedOf();
1876: if (!at)
1877: { dedtypes->tdata()[i] = tt;
1878: goto Lexact;
1879: }
1880: break;
1881:
1882: case X(MODconst, 0):
1883: case X(MODconst, MODimmutable):
1884: case X(MODconst, MODconst | MODshared):
1885: case X(MODconst | MODshared, MODimmutable):
1886: case X(MODconst, MODwild):
1887: case X(MODconst, MODwild | MODshared):
1888: // foo(U:const(U)) T => T
1889: // foo(U:const(U)) immutable(T) => T
1890: // foo(U:const(U)) const(shared(T)) => shared(T)
1891: // foo(U:const(shared(U)) immutable(T) => T
1892: // foo(U:const(U)) wild(shared(T)) => shared(T)
1893: tt = mutableOf();
1894: if (!at)
1895: { dedtypes->tdata()[i] = tt;
1896: goto Lconst;
1897: }
1898: break;
1899:
1900: case X(MODshared, MODconst | MODshared):
1901: case X(MODconst | MODshared, MODshared):
1902: case X(MODshared, MODwild | MODshared):
1903: // foo(U:shared(U)) const(shared(T)) => const(T)
1904: // foo(U:const(shared(U)) shared(T) => T
1905: // foo(U:shared(U)) wild(shared(T)) => wild(T)
1906: tt = unSharedOf();
1907: if (!at)
1908: { dedtypes->tdata()[i] = tt;
1909: goto Lconst;
1910: }
1911: break;
1912:
1913: case X(MODimmutable, 0):
1914: case X(MODimmutable, MODconst):
1915: case X(MODimmutable, MODshared):
1916: case X(MODimmutable, MODconst | MODshared):
1917: case X(MODconst, MODshared):
1918: case X(MODshared, 0):
1919: case X(MODshared, MODconst):
1920: case X(MODshared, MODimmutable):
1921: case X(MODconst | MODshared, 0):
1922: case X(MODconst | MODshared, MODconst):
1923: case X(MODimmutable, MODwild):
1924: case X(MODshared, MODwild):
1925: case X(MODconst | MODshared, MODwild):
1926: case X(MODwild, 0):
1927: case X(MODwild, MODconst):
1928: case X(MODwild, MODimmutable):
1929: case X(MODwild, MODshared):
1930: case X(MODwild, MODconst | MODshared):
1931: case X(MODwild | MODshared, 0):
1932: case X(MODwild | MODshared, MODconst):
1933: case X(MODwild | MODshared, MODimmutable):
1934: case X(MODwild | MODshared, MODshared):
1935: case X(MODwild | MODshared, MODconst | MODshared):
1936: case X(MODwild | MODshared, MODwild):
1937: case X(MODimmutable, MODwild | MODshared):
1938: case X(MODconst | MODshared, MODwild | MODshared):
1939: case X(MODwild, MODwild | MODshared):
1940:
1941: // foo(U:immutable(U)) T => nomatch
1942: // foo(U:immutable(U)) const(T) => nomatch
1943: // foo(U:immutable(U)) shared(T) => nomatch
1944: // foo(U:immutable(U)) const(shared(T)) => nomatch
1945: // foo(U:const(U)) shared(T) => nomatch
1946: // foo(U:shared(U)) T => nomatch
1947: // foo(U:shared(U)) const(T) => nomatch
1948: // foo(U:shared(U)) immutable(T) => nomatch
1949: // foo(U:const(shared(U)) T => nomatch
1950: // foo(U:const(shared(U)) const(T) => nomatch
1951: // foo(U:immutable(U)) wild(T) => nomatch
1952: // foo(U:shared(U)) wild(T) => nomatch
1953: // foo(U:const(shared(U)) wild(T) => nomatch
1954: // foo(U:wild(U)) T => nomatch
1955: // foo(U:wild(U)) const(T) => nomatch
1956: // foo(U:wild(U)) immutable(T) => nomatch
1957: // foo(U:wild(U)) shared(T) => nomatch
1958: // foo(U:wild(U)) const(shared(T)) => nomatch
1959: // foo(U:wild(shared(U)) T => nomatch
1960: // foo(U:wild(shared(U)) const(T) => nomatch
1961: // foo(U:wild(shared(U)) immutable(T) => nomatch
1962: // foo(U:wild(shared(U)) shared(T) => nomatch
1963: // foo(U:wild(shared(U)) const(shared(T)) => nomatch
1964: // foo(U:wild(shared(U)) wild(T) => nomatch
1965: // foo(U:immutable(U)) wild(shared(T)) => nomatch
1966: // foo(U:const(shared(U))) wild(shared(T)) => nomatch
1967: // foo(U:wild(U)) wild(shared(T)) => nomatch
1968: //if (!at)
1969: goto Lnomatch;
1970: break;
1971:
1972: default:
1973: assert(0);
1974: }
1975: #undef X
1976:
1977: if (tt->equals(at))
1978: goto Lexact;
1979: else if (tt->ty == Tclass && at->ty == Tclass)
1980: {
1981: return tt->implicitConvTo(at);
1982: }
1983: else if (tt->ty == Tsarray && at->ty == Tarray &&
1984: tt->nextOf()->implicitConvTo(at->nextOf()) >= MATCHconst)
1985: {
1986: goto Lexact;
1987: }
1988: else
1989: goto Lnomatch;
1990: }
1991:
1992: if (ty != tparam->ty)
1993: {
1994: #if DMDV2
1995: // Can't instantiate AssociativeArray!() without a scope
1996: if (tparam->ty == Taarray && !((TypeAArray*)tparam)->sc)
1997: ((TypeAArray*)tparam)->sc = sc;
1998: #endif
1999: return implicitConvTo(tparam);
2000: }
2001:
2002: if (nextOf())
2003: return nextOf()->deduceType(sc, tparam->nextOf(), parameters, dedtypes);
2004:
2005: Lexact:
2006: return MATCHexact;
2007:
2008: Lnomatch:
2009: return MATCHnomatch;
2010:
2011: #if DMDV2
2012: Lconst:
2013: return MATCHconst;
2014: #endif
2015: }
2016:
2017: #if DMDV2
2018: MATCH TypeDArray::deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters,
2019: Objects *dedtypes)
2020: {
2021: #if 0
2022: printf("TypeDArray::deduceType()\n");
2023: printf("\tthis = %d, ", ty); print();
2024: printf("\ttparam = %d, ", tparam->ty); tparam->print();
2025: #endif
2026: return Type::deduceType(sc, tparam, parameters, dedtypes);
2027:
2028: Lnomatch:
warning C4102: 'Lnomatch' : unreferenced label
2029: return MATCHnomatch;
2030: }
2031: #endif
2032:
2033: MATCH TypeSArray::deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters,
2034: Objects *dedtypes)
2035: {
2036: #if 0
2037: printf("TypeSArray::deduceType()\n");
2038: printf("\tthis = %d, ", ty); print();
2039: printf("\ttparam = %d, ", tparam->ty); tparam->print();
2040: #endif
2041:
2042: // Extra check that array dimensions must match
2043: if (tparam)
2044: {
2045: if (tparam->ty == Tsarray)
2046: {
2047: TypeSArray *tp = (TypeSArray *)tparam;
2048:
2049: if (tp->dim->op == TOKvar &&
2050: ((VarExp *)tp->dim)->var->storage_class & STCtemplateparameter)
2051: { int i = templateIdentifierLookup(((VarExp *)tp->dim)->var->ident, parameters);
2052: // This code matches code in TypeInstance::deduceType()
2053: if (i == -1)
2054: goto Lnomatch;
2055: TemplateParameter *tp = parameters->tdata()[i];
warning C6246: Local declaration of 'tp' hides declaration of the same name in outer scope. For additional information, see previous declaration at line '2047' of 'c:\projects\extern\d\dmd\src\template.c': Lines: 2047
2056: TemplateValueParameter *tvp = tp->isTemplateValueParameter();
2057: if (!tvp)
2058: goto Lnomatch;
2059: Expression *e = (Expression *)dedtypes->tdata()[i];
2060: if (e)
2061: {
2062: if (!dim->equals(e))
2063: goto Lnomatch;
2064: }
2065: else
2066: { Type *vt = tvp->valType->semantic(0, sc);
2067: MATCH m = (MATCH)dim->implicitConvTo(vt);
2068: if (!m)
2069: goto Lnomatch;
2070: dedtypes->tdata()[i] = dim;
2071: }
2072: }
2073: else if (dim->toInteger() != tp->dim->toInteger())
2074: return MATCHnomatch;
2075: }
2076: else if (tparam->ty == Taarray)
2077: {
2078: TypeAArray *tp = (TypeAArray *)tparam;
2079: if (tp->index->ty == Tident)
2080: { TypeIdentifier *tident = (TypeIdentifier *)tp->index;
2081:
2082: if (tident->idents.dim == 0)
2083: { Identifier *id = tident->ident;
2084:
2085: for (size_t i = 0; i < parameters->dim; i++)
2086: {
2087: TemplateParameter *tp = parameters->tdata()[i];
warning C6246: Local declaration of 'tp' hides declaration of the same name in outer scope. For additional information, see previous declaration at line '2078' of 'c:\projects\extern\d\dmd\src\template.c': Lines: 2078
2088:
2089: if (tp->ident->equals(id))
2090: { // Found the corresponding template parameter
2091: TemplateValueParameter *tvp = tp->isTemplateValueParameter();
2092: if (!tvp || !tvp->valType->isintegral())
2093: goto Lnomatch;
2094:
2095: if (dedtypes->tdata()[i])
2096: {
2097: if (!dim->equals(dedtypes->tdata()[i]))
2098: goto Lnomatch;
2099: }
2100: else
2101: { dedtypes->tdata()[i] = dim;
2102: }
2103: return next->deduceType(sc, tparam->nextOf(), parameters, dedtypes);
2104: }
2105: }
2106: }
2107: }
2108: }
2109: else if (tparam->ty == Tarray)
2110: { MATCH m;
2111:
2112: m = next->deduceType(sc, tparam->nextOf(), parameters, dedtypes);
2113: if (m == MATCHexact)
2114: m = MATCHconvert;
2115: return m;
2116: }
2117: }
2118: return Type::deduceType(sc, tparam, parameters, dedtypes);
2119:
2120: Lnomatch:
2121: return MATCHnomatch;
2122: }
2123:
2124: MATCH TypeAArray::deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes)
2125: {
2126: #if 0
2127: printf("TypeAArray::deduceType()\n");
2128: printf("\tthis = %d, ", ty); print();
2129: printf("\ttparam = %d, ", tparam->ty); tparam->print();
2130: #endif
2131:
2132: // Extra check that index type must match
2133: if (tparam && tparam->ty == Taarray)
2134: {
2135: TypeAArray *tp = (TypeAArray *)tparam;
2136: if (!index->deduceType(sc, tp->index, parameters, dedtypes))
2137: {
2138: return MATCHnomatch;
2139: }
2140: }
2141: return Type::deduceType(sc, tparam, parameters, dedtypes);
2142: }
2143:
2144: MATCH TypeFunction::deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes)
2145: {
2146: //printf("TypeFunction::deduceType()\n");
2147: //printf("\tthis = %d, ", ty); print();
2148: //printf("\ttparam = %d, ", tparam->ty); tparam->print();
2149:
2150: // Extra check that function characteristics must match
2151: if (tparam && tparam->ty == Tfunction)
2152: {
2153: TypeFunction *tp = (TypeFunction *)tparam;
2154: if (varargs != tp->varargs ||
2155: linkage != tp->linkage)
2156: return MATCHnomatch;
2157:
2158: size_t nfargs = Parameter::dim(this->parameters);
2159: size_t nfparams = Parameter::dim(tp->parameters);
2160:
2161: /* See if tuple match
2162: */
2163: if (nfparams > 0 && nfargs >= nfparams - 1)
2164: {
2165: /* See if 'A' of the template parameter matches 'A'
2166: * of the type of the last function parameter.
2167: */
2168: Parameter *fparam = Parameter::getNth(tp->parameters, nfparams - 1);
2169: assert(fparam);
2170: assert(fparam->type);
2171: if (fparam->type->ty != Tident)
2172: goto L1;
2173: TypeIdentifier *tid = (TypeIdentifier *)fparam->type;
2174: if (tid->idents.dim)
2175: goto L1;
2176:
2177: /* Look through parameters to find tuple matching tid->ident
2178: */
2179: size_t tupi = 0;
2180: for (; 1; tupi++)
2181: { if (tupi == parameters->dim)
2182: goto L1;
2183: TemplateParameter *t = parameters->tdata()[tupi];
2184: TemplateTupleParameter *tup = t->isTemplateTupleParameter();
2185: if (tup && tup->ident->equals(tid->ident))
2186: break;
2187: }
2188:
2189: /* The types of the function arguments [nfparams - 1 .. nfargs]
2190: * now form the tuple argument.
2191: */
2192: int tuple_dim = nfargs - (nfparams - 1);
2193:
2194: /* See if existing tuple, and whether it matches or not
2195: */
2196: Object *o = dedtypes->tdata()[tupi];
2197: if (o)
2198: { // Existing deduced argument must be a tuple, and must match
2199: Tuple *t = isTuple(o);
2200: if (!t || t->objects.dim != tuple_dim)
2201: return MATCHnomatch;
2202: for (size_t i = 0; i < tuple_dim; i++)
warning C4018: '<' : signed/unsigned mismatch
2203: { Parameter *arg = Parameter::getNth(this->parameters, nfparams - 1 + i);
2204: if (!arg->type->equals(t->objects.tdata()[i]))
2205: return MATCHnomatch;
2206: }
2207: }
2208: else
2209: { // Create new tuple
2210: Tuple *t = new Tuple();
2211: t->objects.setDim(tuple_dim);
2212: for (size_t i = 0; i < tuple_dim; i++)
warning C4018: '<' : signed/unsigned mismatch
2213: { Parameter *arg = Parameter::getNth(this->parameters, nfparams - 1 + i);
2214: t->objects.tdata()[i] = arg->type;
2215: }
2216: dedtypes->tdata()[tupi] = t;
2217: }
2218: nfparams--; // don't consider the last parameter for type deduction
2219: goto L2;
2220: }
2221:
2222: L1:
2223: if (nfargs != nfparams)
2224: return MATCHnomatch;
2225: L2:
2226: for (size_t i = 0; i < nfparams; i++)
2227: {
2228: Parameter *a = Parameter::getNth(this->parameters, i);
2229: Parameter *ap = Parameter::getNth(tp->parameters, i);
2230: if (a->storageClass != ap->storageClass ||
2231: !a->type->deduceType(sc, ap->type, parameters, dedtypes))
2232: return MATCHnomatch;
2233: }
2234: }
2235: return Type::deduceType(sc, tparam, parameters, dedtypes);
2236: }
2237:
2238: MATCH TypeIdentifier::deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes)
2239: {
2240: // Extra check
2241: if (tparam && tparam->ty == Tident)
2242: {
2243: TypeIdentifier *tp = (TypeIdentifier *)tparam;
2244:
2245: for (int i = 0; i < idents.dim; i++)
warning C4018: '<' : signed/unsigned mismatch
2246: {
2247: Identifier *id1 = idents.tdata()[i];
2248: Identifier *id2 = tp->idents.tdata()[i];
2249:
2250: if (!id1->equals(id2))
2251: return MATCHnomatch;
2252: }
2253: }
2254: return Type::deduceType(sc, tparam, parameters, dedtypes);
2255: }
2256:
2257: MATCH TypeInstance::deduceType(Scope *sc,
2258: Type *tparam, TemplateParameters *parameters,
2259: Objects *dedtypes)
2260: {
2261: #if 0
2262: printf("TypeInstance::deduceType()\n");
2263: printf("\tthis = %d, ", ty); print();
2264: printf("\ttparam = %d, ", tparam->ty); tparam->print();
2265: #endif
2266:
2267: // Extra check
2268: if (tparam && tparam->ty == Tinstance)
2269: {
2270: TypeInstance *tp = (TypeInstance *)tparam;
2271:
2272: //printf("tempinst->tempdecl = %p\n", tempinst->tempdecl);
2273: //printf("tp->tempinst->tempdecl = %p\n", tp->tempinst->tempdecl);
2274: if (!tp->tempinst->tempdecl)
2275: { //printf("tp->tempinst->name = '%s'\n", tp->tempinst->name->toChars());
2276: if (!tp->tempinst->name->equals(tempinst->name))
2277: {
2278: /* Handle case of:
2279: * template Foo(T : sa!(T), alias sa)
2280: */
2281: int i = templateIdentifierLookup(tp->tempinst->name, parameters);
2282: if (i == -1)
2283: { /* Didn't find it as a parameter identifier. Try looking
2284: * it up and seeing if is an alias. See Bugzilla 1454
2285: */
2286: Dsymbol *s = tempinst->tempdecl->scope->search(0, tp->tempinst->name, NULL);
2287: if (s)
2288: {
2289: s = s->toAlias();
2290: TemplateDeclaration *td = s->isTemplateDeclaration();
2291: if (td && td == tempinst->tempdecl)
2292: goto L2;
2293: }
2294: goto Lnomatch;
2295: }
2296: TemplateParameter *tpx = parameters->tdata()[i];
2297: // This logic duplicates tpx->matchArg()
2298: TemplateAliasParameter *ta = tpx->isTemplateAliasParameter();
2299: if (!ta)
2300: goto Lnomatch;
2301: Object *sa = tempinst->tempdecl;
2302: if (!sa)
2303: goto Lnomatch;
2304: if (ta->specAlias && sa != ta->specAlias)
2305: goto Lnomatch;
2306: if (dedtypes->tdata()[i])
2307: { // Must match already deduced symbol
2308: Object *s = dedtypes->tdata()[i];
2309:
2310: if (s != sa)
2311: goto Lnomatch;
2312: }
2313: dedtypes->tdata()[i] = sa;
2314: }
2315: }
2316: else if (tempinst->tempdecl != tp->tempinst->tempdecl)
2317: goto Lnomatch;
2318:
2319: L2:
2320:
2321: for (int i = 0; 1; i++)
2322: {
2323: //printf("\ttest: tempinst->tiargs[%d]\n", i);
2324: Object *o1;
2325: if (i < tempinst->tiargs->dim)
warning C4018: '<' : signed/unsigned mismatch
2326: o1 = tempinst->tiargs->tdata()[i];
2327: else if (i < tempinst->tdtypes.dim && i < tp->tempinst->tiargs->dim)
warning C4018: '<' : signed/unsigned mismatch
warning C4018: '<' : signed/unsigned mismatch
2328: // Pick up default arg
2329: o1 = tempinst->tdtypes.tdata()[i];
2330: else
2331: break;
2332:
2333: if (i >= tp->tempinst->tiargs->dim)
warning C4018: '>=' : signed/unsigned mismatch
2334: goto Lnomatch;
2335:
2336: Object *o2 = tp->tempinst->tiargs->tdata()[i];
2337:
2338: Type *t1 = isType(o1);
2339: Type *t2 = isType(o2);
2340:
2341: Expression *e1 = isExpression(o1);
2342: Expression *e2 = isExpression(o2);
2343:
2344: Dsymbol *s1 = isDsymbol(o1);
2345: Dsymbol *s2 = isDsymbol(o2);
2346:
2347: Tuple *v1 = isTuple(o1);
2348: Tuple *v2 = isTuple(o2);
2349: #if 0
2350: if (t1) printf("t1 = %s\n", t1->toChars());
2351: if (t2) printf("t2 = %s\n", t2->toChars());
2352: if (e1) printf("e1 = %s\n", e1->toChars());
2353: if (e2) printf("e2 = %s\n", e2->toChars());
2354: if (s1) printf("s1 = %s\n", s1->toChars());
2355: if (s2) printf("s2 = %s\n", s2->toChars());
2356: if (v1) printf("v1 = %s\n", v1->toChars());
2357: if (v2) printf("v2 = %s\n", v2->toChars());
2358: #endif
2359:
2360: TemplateTupleParameter *ttp;
2361: int j;
2362: if (t2 &&
2363: t2->ty == Tident &&
2364: i == tp->tempinst->tiargs->dim - 1 &&
2365: i == tempinst->tempdecl->parameters->dim - 1 &&
2366: (ttp = tempinst->tempdecl->isVariadic()) != NULL)
2367: {
2368: /* Given:
2369: * struct A(B...) {}
2370: * alias A!(int, float) X;
2371: * static if (!is(X Y == A!(Z), Z))
2372: * deduce that Z is a tuple(int, float)
2373: */
2374:
2375: j = templateParameterLookup(t2, parameters);
2376: if (j == -1)
2377: goto Lnomatch;
2378:
2379: /* Create tuple from remaining args
2380: */
2381: Tuple *vt = new Tuple();
2382: int vtdim = tempinst->tiargs->dim - i;
2383: vt->objects.setDim(vtdim);
2384: for (size_t k = 0; k < vtdim; k++)
warning C4018: '<' : signed/unsigned mismatch
2385: vt->objects.tdata()[k] = tempinst->tiargs->tdata()[i + k];
2386:
2387: Tuple *v = (Tuple *)dedtypes->tdata()[j];
2388: if (v)
2389: {
2390: if (!match(v, vt, tempinst->tempdecl, sc))
2391: goto Lnomatch;
2392: }
2393: else
2394: dedtypes->tdata()[j] = vt;
2395: break; //return MATCHexact;
2396: }
2397:
2398: if (t1 && t2)
2399: {
2400: if (!t1->deduceType(sc, t2, parameters, dedtypes))
2401: goto Lnomatch;
2402: }
2403: else if (e1 && e2)
2404: {
2405: if (!e1->equals(e2))
2406: { if (e2->op == TOKvar)
2407: {
2408: /*
2409: * (T:Number!(e2), int e2)
2410: */
2411: j = templateIdentifierLookup(((VarExp *)e2)->var->ident, parameters);
2412: goto L1;
2413: }
2414: goto Lnomatch;
2415: }
2416: }
2417: else if (e1 && t2 && t2->ty == Tident)
2418: {
2419: j = templateParameterLookup(t2, parameters);
2420: L1:
2421: if (j == -1)
2422: goto Lnomatch;
2423: TemplateParameter *tp = parameters->tdata()[j];
warning C6246: Local declaration of 'tp' hides declaration of the same name in outer scope. For additional information, see previous declaration at line '2270' of 'c:\projects\extern\d\dmd\src\template.c': Lines: 2270
2424: // BUG: use tp->matchArg() instead of the following
2425: TemplateValueParameter *tv = tp->isTemplateValueParameter();
2426: if (!tv)
2427: goto Lnomatch;
2428: Expression *e = (Expression *)dedtypes->tdata()[j];
2429: if (e)
2430: {
2431: if (!e1->equals(e))
2432: goto Lnomatch;
2433: }
2434: else
2435: { Type *vt = tv->valType->semantic(0, sc);
2436: MATCH m = (MATCH)e1->implicitConvTo(vt);
2437: if (!m)
2438: goto Lnomatch;
2439: dedtypes->tdata()[j] = e1;
2440: }
2441: }
2442: else if (s1 && t2 && t2->ty == Tident)
2443: {
2444: j = templateParameterLookup(t2, parameters);
2445: if (j == -1)
2446: goto Lnomatch;
2447: TemplateParameter *tp = parameters->tdata()[j];
warning C6246: Local declaration of 'tp' hides declaration of the same name in outer scope. For additional information, see previous declaration at line '2270' of 'c:\projects\extern\d\dmd\src\template.c': Lines: 2270
2448: // BUG: use tp->matchArg() instead of the following
2449: TemplateAliasParameter *ta = tp->isTemplateAliasParameter();
2450: if (!ta)
2451: goto Lnomatch;
2452: Dsymbol *s = (Dsymbol *)dedtypes->tdata()[j];
2453: if (s)
2454: {
2455: if (!s1->equals(s))
2456: goto Lnomatch;
2457: }
2458: else
2459: {
2460: dedtypes->tdata()[j] = s1;
2461: }
2462: }
2463: else if (s1 && s2)
2464: {
2465: if (!s1->equals(s2))
2466: goto Lnomatch;
2467: }
2468: // BUG: Need to handle tuple parameters
2469: else
2470: goto Lnomatch;
2471: }
2472: }
2473: return Type::deduceType(sc, tparam, parameters, dedtypes);
2474:
2475: Lnomatch:
2476: //printf("no match\n");
2477: return MATCHnomatch;
2478: }
2479:
2480: MATCH TypeStruct::deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes)
2481: {
2482: //printf("TypeStruct::deduceType()\n");
2483: //printf("\tthis->parent = %s, ", sym->parent->toChars()); print();
2484: //printf("\ttparam = %d, ", tparam->ty); tparam->print();
2485:
2486: /* If this struct is a template struct, and we're matching
2487: * it against a template instance, convert the struct type
2488: * to a template instance, too, and try again.
2489: */
2490: TemplateInstance *ti = sym->parent->isTemplateInstance();
2491:
2492: if (tparam && tparam->ty == Tinstance)
2493: {
2494: if (ti && ti->toAlias() == sym)
2495: {
2496: TypeInstance *t = new TypeInstance(0, ti);
2497: return t->deduceType(sc, tparam, parameters, dedtypes);
2498: }
2499:
2500: /* Match things like:
2501: * S!(T).foo
2502: */
2503: TypeInstance *tpi = (TypeInstance *)tparam;
2504: if (tpi->idents.dim)
2505: { Identifier *id = tpi->idents.tdata()[tpi->idents.dim - 1];
2506: if (id->dyncast() == DYNCAST_IDENTIFIER && sym->ident->equals(id))
2507: {
2508: Type *tparent = sym->parent->getType();
2509: if (tparent)
2510: {
2511: /* Slice off the .foo in S!(T).foo
2512: */
2513: tpi->idents.dim--;
2514: MATCH m = tparent->deduceType(sc, tpi, parameters, dedtypes);
2515: tpi->idents.dim++;
2516: return m;
2517: }
2518: }
2519: }
2520: }
2521:
2522: // Extra check
2523: if (tparam && tparam->ty == Tstruct)
2524: {
2525: TypeStruct *tp = (TypeStruct *)tparam;
2526:
2527: if (sym != tp->sym)
2528: return MATCHnomatch;
2529: }
2530: return Type::deduceType(sc, tparam, parameters, dedtypes);
2531: }
2532:
2533: MATCH TypeEnum::deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes)
2534: {
2535: // Extra check
2536: if (tparam && tparam->ty == Tenum)
2537: {
2538: TypeEnum *tp = (TypeEnum *)tparam;
2539:
2540: if (sym != tp->sym)
2541: return MATCHnomatch;
2542: }
2543: return Type::deduceType(sc, tparam, parameters, dedtypes);
2544: }
2545:
2546: MATCH TypeTypedef::deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes)
2547: {
2548: // Extra check
2549: if (tparam && tparam->ty == Ttypedef)
2550: {
2551: TypeTypedef *tp = (TypeTypedef *)tparam;
2552:
2553: if (sym != tp->sym)
2554: return MATCHnomatch;
2555: }
2556: return Type::deduceType(sc, tparam, parameters, dedtypes);
2557: }
2558:
2559: /* Helper for TypeClass::deduceType().
2560: * Classes can match with implicit conversion to a base class or interface.
2561: * This is complicated, because there may be more than one base class which
2562: * matches. In such cases, one or more parameters remain ambiguous.
2563: * For example,
2564: *
2565: * interface I(X, Y) {}
2566: * class C : I(uint, double), I(char, double) {}
2567: * C x;
2568: * foo(T, U)( I!(T, U) x)
2569: *
2570: * deduces that U is double, but T remains ambiguous (could be char or uint).
2571: *
2572: * Given a baseclass b, and initial deduced types 'dedtypes', this function
2573: * tries to match tparam with b, and also tries all base interfaces of b.
2574: * If a match occurs, numBaseClassMatches is incremented, and the new deduced
2575: * types are ANDed with the current 'best' estimate for dedtypes.
2576: */
2577: void deduceBaseClassParameters(BaseClass *b,
2578: Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes,
2579: Objects *best, int &numBaseClassMatches)
2580: {
2581: TemplateInstance *parti = b->base ? b->base->parent->isTemplateInstance() : NULL;
2582: if (parti)
2583: {
2584: // Make a temporary copy of dedtypes so we don't destroy it
2585: Objects *tmpdedtypes = new Objects();
warning C6211: Leaking memory 'tmpdedtypes' due to an exception. Consider using a local catch block to clean up memory: Lines: 2581, 2582, 2585, 2586, 2587, 2589
2586: tmpdedtypes->setDim(dedtypes->dim);
2587: memcpy(tmpdedtypes->tdata(), dedtypes->tdata(), dedtypes->dim * sizeof(void *));
2588:
2589: TypeInstance *t = new TypeInstance(0, parti);
2590: MATCH m = t->deduceType(sc, tparam, parameters, tmpdedtypes);
2591: if (m != MATCHnomatch)
2592: {
2593: // If this is the first ever match, it becomes our best estimate
2594: if (numBaseClassMatches==0)
2595: memcpy(best->tdata(), tmpdedtypes->tdata(), tmpdedtypes->dim * sizeof(void *));
2596: else for (size_t k = 0; k < tmpdedtypes->dim; ++k)
2597: {
2598: // If we've found more than one possible type for a parameter,
2599: // mark it as unknown.
2600: if (tmpdedtypes->tdata()[k] != best->tdata()[k])
2601: best->tdata()[k] = dedtypes->tdata()[k];
2602: }
2603: ++numBaseClassMatches;
2604: }
2605: }
2606: // Now recursively test the inherited interfaces
2607: for (size_t j = 0; j < b->baseInterfaces_dim; ++j)
warning C4018: '<' : signed/unsigned mismatch
2608: {
2609: deduceBaseClassParameters( &(b->baseInterfaces)[j],
2610: sc, tparam, parameters, dedtypes,
2611: best, numBaseClassMatches);
2612: }
2613:
2614: }
2615:
2616: MATCH TypeClass::deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes)
2617: {
2618: //printf("TypeClass::deduceType(this = %s)\n", toChars());
2619:
2620: /* If this class is a template class, and we're matching
2621: * it against a template instance, convert the class type
2622: * to a template instance, too, and try again.
2623: */
2624: TemplateInstance *ti = sym->parent->isTemplateInstance();
2625:
2626: if (tparam && tparam->ty == Tinstance)
2627: {
2628: if (ti && ti->toAlias() == sym)
2629: {
2630: TypeInstance *t = new TypeInstance(0, ti);
2631: MATCH m = t->deduceType(sc, tparam, parameters, dedtypes);
2632: // Even if the match fails, there is still a chance it could match
2633: // a base class.
2634: if (m != MATCHnomatch)
2635: return m;
2636: }
2637:
2638: /* Match things like:
2639: * S!(T).foo
2640: */
2641: TypeInstance *tpi = (TypeInstance *)tparam;
2642: if (tpi->idents.dim)
2643: { Identifier *id = tpi->idents.tdata()[tpi->idents.dim - 1];
2644: if (id->dyncast() == DYNCAST_IDENTIFIER && sym->ident->equals(id))
2645: {
2646: Type *tparent = sym->parent->getType();
2647: if (tparent)
2648: {
2649: /* Slice off the .foo in S!(T).foo
2650: */
2651: tpi->idents.dim--;
2652: MATCH m = tparent->deduceType(sc, tpi, parameters, dedtypes);
2653: tpi->idents.dim++;
2654: return m;
2655: }
2656: }
2657: }
2658:
2659: // If it matches exactly or via implicit conversion, we're done
2660: MATCH m = Type::deduceType(sc, tparam, parameters, dedtypes);
2661: if (m != MATCHnomatch)
2662: return m;
2663:
2664: /* There is still a chance to match via implicit conversion to
2665: * a base class or interface. Because there could be more than one such
2666: * match, we need to check them all.
2667: */
2668:
2669: int numBaseClassMatches = 0; // Have we found an interface match?
2670:
2671: // Our best guess at dedtypes
2672: Objects *best = new Objects();
2673: best->setDim(dedtypes->dim);
2674:
2675: ClassDeclaration *s = sym;
2676: while(s && s->baseclasses->dim > 0)
2677: {
2678: // Test the base class
2679: deduceBaseClassParameters((s->baseclasses->tdata()[0]),
2680: sc, tparam, parameters, dedtypes,
2681: best, numBaseClassMatches);
2682:
2683: // Test the interfaces inherited by the base class
2684: for (size_t i = 0; i < s->interfaces_dim; ++i)
warning C4018: '<' : signed/unsigned mismatch
2685: {
2686: BaseClass *b = s->interfaces[i];
2687: deduceBaseClassParameters(b, sc, tparam, parameters, dedtypes,
2688: best, numBaseClassMatches);
2689: }
2690: s = ((s->baseclasses->tdata()[0]))->base;
2691: }
2692:
2693: if (numBaseClassMatches == 0)
2694: return MATCHnomatch;
2695:
2696: // If we got at least one match, copy the known types into dedtypes
2697: memcpy(dedtypes->tdata(), best->tdata(), best->dim * sizeof(void *));
2698: return MATCHconvert;
2699: }
2700:
2701: // Extra check
2702: if (tparam && tparam->ty == Tclass)
2703: {
2704: TypeClass *tp = (TypeClass *)tparam;
2705:
2706: //printf("\t%d\n", (MATCH) implicitConvTo(tp));
2707: return implicitConvTo(tp);
2708: }
2709: return Type::deduceType(sc, tparam, parameters, dedtypes);
2710: }
2711:
2712: /* ======================== TemplateParameter =============================== */
2713:
2714: TemplateParameter::TemplateParameter(Loc loc, Identifier *ident)
2715: {
2716: this->loc = loc;
2717: this->ident = ident;
2718: this->sparam = NULL;
2719: }
2720:
2721: TemplateTypeParameter *TemplateParameter::isTemplateTypeParameter()
2722: {
2723: return NULL;
2724: }
2725:
2726: TemplateValueParameter *TemplateParameter::isTemplateValueParameter()
2727: {
2728: return NULL;
2729: }
2730:
2731: TemplateAliasParameter *TemplateParameter::isTemplateAliasParameter()
2732: {
2733: return NULL;
2734: }
2735:
2736: TemplateTupleParameter *TemplateParameter::isTemplateTupleParameter()
2737: {
2738: return NULL;
2739: }
2740:
2741: #if DMDV2
2742: TemplateThisParameter *TemplateParameter::isTemplateThisParameter()
2743: {
2744: return NULL;
2745: }
2746: #endif
2747:
2748: /* ======================== TemplateTypeParameter =========================== */
2749:
2750: // type-parameter
2751:
2752: TemplateTypeParameter::TemplateTypeParameter(Loc loc, Identifier *ident, Type *specType,
2753: Type *defaultType)
2754: : TemplateParameter(loc, ident)
2755: {
2756: this->ident = ident;
2757: this->specType = specType;
2758: this->defaultType = defaultType;
2759: }
2760:
2761: TemplateTypeParameter *TemplateTypeParameter::isTemplateTypeParameter()
2762: {
2763: return this;
2764: }
2765:
2766: TemplateParameter *TemplateTypeParameter::syntaxCopy()
2767: {
2768: TemplateTypeParameter *tp = new TemplateTypeParameter(loc, ident, specType, defaultType);
2769: if (tp->specType)
2770: tp->specType = specType->syntaxCopy();
2771: if (defaultType)
2772: tp->defaultType = defaultType->syntaxCopy();
2773: return tp;
2774: }
2775:
2776: void TemplateTypeParameter::declareParameter(Scope *sc)
2777: {
2778: //printf("TemplateTypeParameter::declareParameter('%s')\n", ident->toChars());
2779: TypeIdentifier *ti = new TypeIdentifier(loc, ident);
2780: sparam = new AliasDeclaration(loc, ident, ti);
2781: if (!sc->insert(sparam))
2782: error(loc, "parameter '%s' multiply defined", ident->toChars());
2783: }
2784:
2785: void TemplateTypeParameter::semantic(Scope *sc)
2786: {
2787: //printf("TemplateTypeParameter::semantic('%s')\n", ident->toChars());
2788: if (specType)
2789: {
2790: specType = specType->semantic(loc, sc);
2791: }
2792: #if 0 // Don't do semantic() until instantiation
2793: if (defaultType)
2794: {
2795: defaultType = defaultType->semantic(loc, sc);
2796: }
2797: #endif
2798: }
2799:
2800: /****************************************
2801: * Determine if two TemplateParameters are the same
2802: * as far as TemplateDeclaration overloading goes.
2803: * Returns:
2804: * 1 match
2805: * 0 no match
2806: */
2807:
2808: int TemplateTypeParameter::overloadMatch(TemplateParameter *tp)
2809: {
2810: TemplateTypeParameter *ttp = tp->isTemplateTypeParameter();
2811:
2812: if (ttp)
2813: {
2814: if (specType != ttp->specType)
2815: goto Lnomatch;
2816:
2817: if (specType && !specType->equals(ttp->specType))
2818: goto Lnomatch;
2819:
2820: return 1; // match
2821: }
2822:
2823: Lnomatch:
2824: return 0;
2825: }
2826:
2827: /*******************************************
2828: * Match to a particular TemplateParameter.
2829: * Input:
2830: * i i'th argument
2831: * tiargs[] actual arguments to template instance
2832: * parameters[] template parameters
2833: * dedtypes[] deduced arguments to template instance
2834: * *psparam set to symbol declared and initialized to dedtypes[i]
2835: * flags 1: don't do 'toHeadMutable()'
2836: */
2837:
2838: MATCH TemplateTypeParameter::matchArg(Scope *sc, Objects *tiargs,
2839: int i, TemplateParameters *parameters, Objects *dedtypes,
2840: Declaration **psparam, int flags)
2841: {
2842: //printf("TemplateTypeParameter::matchArg()\n");
2843: Type *t;
2844: Object *oarg;
2845: MATCH m = MATCHexact;
2846: Type *ta;
2847:
2848: if (i < tiargs->dim)
warning C4018: '<' : signed/unsigned mismatch
2849: oarg = tiargs->tdata()[i];
2850: else
2851: { // Get default argument instead
2852: oarg = defaultArg(loc, sc);
2853: if (!oarg)
2854: { assert(i < dedtypes->dim);
warning C4018: '<' : signed/unsigned mismatch
2855: // It might have already been deduced
2856: oarg = dedtypes->tdata()[i];
2857: if (!oarg)
2858: {
2859: goto Lnomatch;
2860: }
2861: flags |= 1; // already deduced, so don't to toHeadMutable()
2862: }
2863: }
2864:
2865: ta = isType(oarg);
2866: if (!ta)
2867: {
2868: //printf("%s %p %p %p\n", oarg->toChars(), isExpression(oarg), isDsymbol(oarg), isTuple(oarg));
2869: goto Lnomatch;
2870: }
2871: //printf("ta is %s\n", ta->toChars());
2872:
2873: t = (Type *)dedtypes->tdata()[i];
2874:
2875: if (specType)
2876: {
2877: //printf("\tcalling deduceType(): ta is %s, specType is %s\n", ta->toChars(), specType->toChars());
2878: MATCH m2 = ta->deduceType(sc, specType, parameters, dedtypes);
2879: if (m2 == MATCHnomatch)
2880: { //printf("\tfailed deduceType\n");
2881: goto Lnomatch;
2882: }
2883:
2884: if (m2 < m)
2885: m = m2;
2886: t = (Type *)dedtypes->tdata()[i];
2887: }
2888: else
2889: {
2890: // So that matches with specializations are better
2891: m = MATCHconvert;
2892:
2893: /* This is so that:
2894: * template Foo(T), Foo!(const int), => ta == int
2895: */
2896: // if (!(flags & 1))
2897: // ta = ta->toHeadMutable();
2898:
2899: if (t)
2900: { // Must match already deduced type
2901:
2902: m = MATCHexact;
2903: if (!t->equals(ta))
2904: { //printf("t = %s ta = %s\n", t->toChars(), ta->toChars());
2905: goto Lnomatch;
2906: }
2907: }
2908: }
2909:
2910: if (!t)
2911: {
2912: dedtypes->tdata()[i] = ta;
2913: t = ta;
2914: }
2915: *psparam = new AliasDeclaration(loc, ident, t);
2916: //printf("\tm = %d\n", m);
2917: return m;
2918:
2919: Lnomatch:
2920: *psparam = NULL;
2921: //printf("\tm = %d\n", MATCHnomatch);
2922: return MATCHnomatch;
2923: }
2924:
2925:
2926: void TemplateTypeParameter::print(Object *oarg, Object *oded)
2927: {
2928: printf(" %s\n", ident->toChars());
2929:
2930: Type *t = isType(oarg);
2931: Type *ta = isType(oded);
2932:
2933: assert(ta);
2934:
2935: if (specType)
2936: printf("\tSpecialization: %s\n", specType->toChars());
2937: if (defaultType)
2938: printf("\tDefault: %s\n", defaultType->toChars());
2939: printf("\tParameter: %s\n", t ? t->toChars() : "NULL");
2940: printf("\tDeduced Type: %s\n", ta->toChars());
2941: }
2942:
2943:
2944: void TemplateTypeParameter::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
2945: {
2946: buf->writestring(ident->toChars());
2947: if (specType)
2948: {
2949: buf->writestring(" : ");
2950: specType->toCBuffer(buf, NULL, hgs);
2951: }
2952: if (defaultType)
2953: {
2954: buf->writestring(" = ");
2955: defaultType->toCBuffer(buf, NULL, hgs);
2956: }
2957: }
2958:
2959:
2960: void *TemplateTypeParameter::dummyArg()
2961: { Type *t;
2962:
2963: if (specType)
2964: t = specType;
2965: else
2966: { // Use this for alias-parameter's too (?)
2967: t = new TypeIdentifier(loc, ident);
2968: }
2969: return (void *)t;
2970: }
2971:
2972:
2973: Object *TemplateTypeParameter::specialization()
2974: {
2975: return specType;
2976: }
2977:
2978:
2979: Object *TemplateTypeParameter::defaultArg(Loc loc, Scope *sc)
2980: {
2981: Type *t;
2982:
2983: t = defaultType;
2984: if (t)
2985: {
2986: t = t->syntaxCopy();
2987: t = t->semantic(loc, sc);
2988: }
2989: return t;
2990: }
2991:
2992: /* ======================== TemplateThisParameter =========================== */
2993:
2994: #if DMDV2
2995: // this-parameter
2996:
2997: TemplateThisParameter::TemplateThisParameter(Loc loc, Identifier *ident,
2998: Type *specType,
2999: Type *defaultType)
3000: : TemplateTypeParameter(loc, ident, specType, defaultType)
3001: {
3002: }
3003:
3004: TemplateThisParameter *TemplateThisParameter::isTemplateThisParameter()
3005: {
3006: return this;
3007: }
3008:
3009: TemplateParameter *TemplateThisParameter::syntaxCopy()
3010: {
3011: TemplateThisParameter *tp = new TemplateThisParameter(loc, ident, specType, defaultType);
3012: if (tp->specType)
3013: tp->specType = specType->syntaxCopy();
3014: if (defaultType)
3015: tp->defaultType = defaultType->syntaxCopy();
3016: return tp;
3017: }
3018:
3019: void TemplateThisParameter::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
3020: {
3021: buf->writestring("this ");
3022: TemplateTypeParameter::toCBuffer(buf, hgs);
3023: }
3024: #endif
3025:
3026: /* ======================== TemplateAliasParameter ========================== */
3027:
3028: // alias-parameter
3029:
3030: Dsymbol *TemplateAliasParameter::sdummy = NULL;
3031:
3032: TemplateAliasParameter::TemplateAliasParameter(Loc loc, Identifier *ident,
3033: Type *specType, Object *specAlias, Object *defaultAlias)
3034: : TemplateParameter(loc, ident)
3035: {
3036: this->ident = ident;
3037: this->specType = specType;
3038: this->specAlias = specAlias;
3039: this->defaultAlias = defaultAlias;
3040: }
3041:
3042: TemplateAliasParameter *TemplateAliasParameter::isTemplateAliasParameter()
3043: {
3044: return this;
3045: }
3046:
3047: TemplateParameter *TemplateAliasParameter::syntaxCopy()
3048: {
3049: TemplateAliasParameter *tp = new TemplateAliasParameter(loc, ident, specType, specAlias, defaultAlias);
3050: if (tp->specType)
3051: tp->specType = specType->syntaxCopy();
3052: tp->specAlias = objectSyntaxCopy(specAlias);
3053: tp->defaultAlias = objectSyntaxCopy(defaultAlias);
3054: return tp;
3055: }
3056:
3057: void TemplateAliasParameter::declareParameter(Scope *sc)
3058: {
3059: TypeIdentifier *ti = new TypeIdentifier(loc, ident);
3060: sparam = new AliasDeclaration(loc, ident, ti);
3061: if (!sc->insert(sparam))
3062: error(loc, "parameter '%s' multiply defined", ident->toChars());
3063: }
3064:
3065: Object *aliasParameterSemantic(Loc loc, Scope *sc, Object *o)
3066: {
3067: if (o)
3068: {
3069: Expression *ea = isExpression(o);
3070: Type *ta = isType(o);
3071: if (ta)
3072: { Dsymbol *s = ta->toDsymbol(sc);
3073: if (s)
3074: o = s;
3075: else
3076: o = ta->semantic(loc, sc);
3077: }
3078: else if (ea)
3079: {
3080: ea = ea->semantic(sc);
3081: o = ea->optimize(WANTvalue | WANTinterpret);
3082: }
3083: }
3084: return o;
3085: }
3086:
3087: void TemplateAliasParameter::semantic(Scope *sc)
3088: {
3089: if (specType)
3090: {
3091: specType = specType->semantic(loc, sc);
3092: }
3093: specAlias = aliasParameterSemantic(loc, sc, specAlias);
3094: #if 0 // Don't do semantic() until instantiation
3095: if (defaultAlias)
3096: defaultAlias = defaultAlias->semantic(loc, sc);
3097: #endif
3098: }
3099:
3100: int TemplateAliasParameter::overloadMatch(TemplateParameter *tp)
3101: {
3102: TemplateAliasParameter *tap = tp->isTemplateAliasParameter();
3103:
3104: if (tap)
3105: {
3106: if (specAlias != tap->specAlias)
3107: goto Lnomatch;
3108:
3109: return 1; // match
3110: }
3111:
3112: Lnomatch:
3113: return 0;
3114: }
3115:
3116: MATCH TemplateAliasParameter::matchArg(Scope *sc,
3117: Objects *tiargs, int i, TemplateParameters *parameters,
3118: Objects *dedtypes,
3119: Declaration **psparam, int flags)
3120: {
3121: Object *sa;
3122: Object *oarg;
3123: Expression *ea;
3124: Dsymbol *s;
3125:
3126: //printf("TemplateAliasParameter::matchArg()\n");
3127:
3128: if (i < tiargs->dim)
warning C4018: '<' : signed/unsigned mismatch
3129: oarg = tiargs->tdata()[i];
3130: else
3131: { // Get default argument instead
3132: oarg = defaultArg(loc, sc);
3133: if (!oarg)
3134: { assert(i < dedtypes->dim);
warning C4018: '<' : signed/unsigned mismatch
3135: // It might have already been deduced
3136: oarg = dedtypes->tdata()[i];
3137: if (!oarg)
3138: goto Lnomatch;
3139: }
3140: }
3141:
3142: sa = getDsymbol(oarg);
3143: if (sa)
3144: {
3145: /* specType means the alias must be a declaration with a type
3146: * that matches specType.
3147: */
3148: if (specType)
3149: { Declaration *d = ((Dsymbol *)sa)->isDeclaration();
3150: if (!d)
3151: goto Lnomatch;
3152: if (!d->type->equals(specType))
3153: goto Lnomatch;
3154: }
3155: }
3156: else
3157: {
3158: sa = oarg;
3159: ea = isExpression(oarg);
3160: if (ea)
3161: { if (specType)
3162: {
3163: if (!ea->type->equals(specType))
3164: goto Lnomatch;
3165: }
3166: }
3167: else
3168: goto Lnomatch;
3169: }
3170:
3171: if (specAlias)
3172: {
3173: if (sa == sdummy)
3174: goto Lnomatch;
3175: if (sa != specAlias)
3176: goto Lnomatch;
3177: }
3178: else if (dedtypes->tdata()[i])
3179: { // Must match already deduced symbol
3180: Object *s = dedtypes->tdata()[i];
warning C6246: Local declaration of 's' hides declaration of the same name in outer scope. For additional information, see previous declaration at line '3124' of 'c:\projects\extern\d\dmd\src\template.c': Lines: 3124
3181:
3182: if (!sa || s != sa)
3183: goto Lnomatch;
3184: }
3185: dedtypes->tdata()[i] = sa;
3186:
3187: s = isDsymbol(sa);
3188: if (s)
3189: *psparam = new AliasDeclaration(loc, ident, s);
3190: else
3191: {
3192: assert(ea);
warning C6001: Using uninitialized memory 'ea': Lines: 3121, 3122, 3123, 3124, 3128, 3129, 3142, 3143, 3148, 3149, 3150, 3152, 3171, 3178, 3180, 3182, 3185, 3187, 3188, 3192
3193:
3194: // Declare manifest constant
3195: Initializer *init = new ExpInitializer(loc, ea);
3196: VarDeclaration *v = new VarDeclaration(loc, NULL, ident, init);
3197: v->storage_class = STCmanifest;
3198: v->semantic(sc);
3199: *psparam = v;
3200: }
3201: return MATCHexact;
3202:
3203: Lnomatch:
3204: *psparam = NULL;
3205: //printf("\tm = %d\n", MATCHnomatch);
3206: return MATCHnomatch;
3207: }
3208:
3209:
3210: void TemplateAliasParameter::print(Object *oarg, Object *oded)
3211: {
3212: printf(" %s\n", ident->toChars());
3213:
3214: Dsymbol *sa = isDsymbol(oded);
3215: assert(sa);
3216:
3217: printf("\tParameter alias: %s\n", sa->toChars());
3218: }
3219:
3220: void TemplateAliasParameter::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
3221: {
3222: buf->writestring("alias ");
3223: if (specType)
3224: { HdrGenState hgs;
warning C6246: Local declaration of 'hgs' hides declaration of the same name in outer scope. For additional information, see previous declaration at line '3220' of 'c:\projects\extern\d\dmd\src\template.c': Lines: 3220
3225: specType->toCBuffer(buf, ident, &hgs);
3226: }
3227: else
3228: buf->writestring(ident->toChars());
3229: if (specAlias)
3230: {
3231: buf->writestring(" : ");
3232: ObjectToCBuffer(buf, hgs, specAlias);
3233: }
3234: if (defaultAlias)
3235: {
3236: buf->writestring(" = ");
3237: ObjectToCBuffer(buf, hgs, defaultAlias);
3238: }
3239: }
3240:
3241:
3242: void *TemplateAliasParameter::dummyArg()
3243: { Object *s;
3244:
3245: s = specAlias;
3246: if (!s)
3247: {
3248: if (!sdummy)
3249: sdummy = new Dsymbol();
3250: s = sdummy;
3251: }
3252: return (void*)s;
3253: }
3254:
3255:
3256: Object *TemplateAliasParameter::specialization()
3257: {
3258: return specAlias;
3259: }
3260:
3261:
3262: Object *TemplateAliasParameter::defaultArg(Loc loc, Scope *sc)
3263: {
3264: Object *da = defaultAlias;
3265: Type *ta = isType(defaultAlias);
3266: if (ta)
3267: {
3268: if (ta->ty == Tinstance)
3269: {
3270: // If the default arg is a template, instantiate for each type
3271: da = ta->syntaxCopy();
3272: }
3273: }
3274:
3275: Object *o = aliasParameterSemantic(loc, sc, da);
3276: return o;
3277: }
3278:
3279: /* ======================== TemplateValueParameter ========================== */
3280:
3281: // value-parameter
3282:
3283: Expression *TemplateValueParameter::edummy = NULL;
3284:
3285: TemplateValueParameter::TemplateValueParameter(Loc loc, Identifier *ident, Type *valType,
3286: Expression *specValue, Expression *defaultValue)
3287: : TemplateParameter(loc, ident)
3288: {
3289: this->ident = ident;
3290: this->valType = valType;
3291: this->specValue = specValue;
3292: this->defaultValue = defaultValue;
3293: }
3294:
3295: TemplateValueParameter *TemplateValueParameter::isTemplateValueParameter()
3296: {
3297: return this;
3298: }
3299:
3300: TemplateParameter *TemplateValueParameter::syntaxCopy()
3301: {
3302: TemplateValueParameter *tp =
3303: new TemplateValueParameter(loc, ident, valType, specValue, defaultValue);
3304: tp->valType = valType->syntaxCopy();
3305: if (specValue)
3306: tp->specValue = specValue->syntaxCopy();
3307: if (defaultValue)
3308: tp->defaultValue = defaultValue->syntaxCopy();
3309: return tp;
3310: }
3311:
3312: void TemplateValueParameter::declareParameter(Scope *sc)
3313: {
3314: VarDeclaration *v = new VarDeclaration(loc, valType, ident, NULL);
3315: v->storage_class = STCtemplateparameter;
3316: if (!sc->insert(v))
3317: error(loc, "parameter '%s' multiply defined", ident->toChars());
3318: sparam = v;
3319: }
3320:
3321: void TemplateValueParameter::semantic(Scope *sc)
3322: {
3323: sparam->semantic(sc);
3324: valType = valType->semantic(loc, sc);
3325: if (!(valType->isintegral() || valType->isfloating() || valType->isString()) &&
3326: valType->ty != Tident)
3327: {
3328: if (valType != Type::terror)
3329: error(loc, "arithmetic/string type expected for value-parameter, not %s", valType->toChars());
3330: }
3331:
3332: if (specValue)
3333: { Expression *e = specValue;
3334:
3335: e = e->semantic(sc);
3336: e = e->implicitCastTo(sc, valType);
3337: e = e->optimize(WANTvalue | WANTinterpret);
3338: if (e->op == TOKint64 || e->op == TOKfloat64 ||
3339: e->op == TOKcomplex80 || e->op == TOKnull || e->op == TOKstring)
3340: specValue = e;
3341: //e->toInteger();
3342: }
3343:
3344: #if 0 // defer semantic analysis to arg match
3345: if (defaultValue)
3346: { Expression *e = defaultValue;
3347:
3348: e = e->semantic(sc);
3349: e = e->implicitCastTo(sc, valType);
3350: e = e->optimize(WANTvalue | WANTinterpret);
3351: if (e->op == TOKint64)
3352: defaultValue = e;
3353: //e->toInteger();
3354: }
3355: #endif
3356: }
3357:
3358: int TemplateValueParameter::overloadMatch(TemplateParameter *tp)
3359: {
3360: TemplateValueParameter *tvp = tp->isTemplateValueParameter();
3361:
3362: if (tvp)
3363: {
3364: if (valType != tvp->valType)
3365: goto Lnomatch;
3366:
3367: if (valType && !valType->equals(tvp->valType))
3368: goto Lnomatch;
3369:
3370: if (specValue != tvp->specValue)
3371: goto Lnomatch;
3372:
3373: return 1; // match
3374: }
3375:
3376: Lnomatch:
3377: return 0;
3378: }
3379:
3380:
3381: MATCH TemplateValueParameter::matchArg(Scope *sc,
3382: Objects *tiargs, int i, TemplateParameters *parameters, Objects *dedtypes,
3383: Declaration **psparam, int flags)
3384: {
3385: //printf("TemplateValueParameter::matchArg()\n");
3386:
3387: Initializer *init;
3388: Declaration *sparam;
3389: MATCH m = MATCHexact;
3390: Expression *ei;
3391: Object *oarg;
3392:
3393: if (i < tiargs->dim)
warning C4018: '<' : signed/unsigned mismatch
3394: oarg = tiargs->tdata()[i];
3395: else
3396: { // Get default argument instead
3397: oarg = defaultArg(loc, sc);
3398: if (!oarg)
3399: { assert(i < dedtypes->dim);
warning C4018: '<' : signed/unsigned mismatch
3400: // It might have already been deduced
3401: oarg = dedtypes->tdata()[i];
3402: if (!oarg)
3403: goto Lnomatch;
3404: }
3405: }
3406:
3407: ei = isExpression(oarg);
3408: Type *vt;
3409:
3410: if (!ei && oarg)
3411: goto Lnomatch;
3412:
3413: if (ei && ei->op == TOKvar)
3414: { // Resolve const variables that we had skipped earlier
3415: ei = ei->optimize(WANTvalue | WANTinterpret);
3416: }
3417:
3418: if (specValue)
3419: {
3420: if (!ei || ei == edummy)
3421: goto Lnomatch;
3422:
3423: Expression *e = specValue;
3424:
3425: e = e->semantic(sc);
3426: e = e->implicitCastTo(sc, valType);
3427: e = e->optimize(WANTvalue | WANTinterpret);
3428: //e->type = e->type->toHeadMutable();
3429:
3430: ei = ei->syntaxCopy();
3431: ei = ei->semantic(sc);
3432: ei = ei->optimize(WANTvalue | WANTinterpret);
3433: //ei->type = ei->type->toHeadMutable();
3434: //printf("\tei: %s, %s\n", ei->toChars(), ei->type->toChars());
3435: //printf("\te : %s, %s\n", e->toChars(), e->type->toChars());
3436: if (!ei->equals(e))
3437: goto Lnomatch;
3438: }
3439: else if (dedtypes->tdata()[i])
3440: { // Must match already deduced value
3441: Expression *e = (Expression *)dedtypes->tdata()[i];
3442:
3443: if (!ei || !ei->equals(e))
3444: goto Lnomatch;
3445: }
3446: Lmatch:
warning C4102: 'Lmatch' : unreferenced label
3447: //printf("\tvalType: %s, ty = %d\n", valType->toChars(), valType->ty);
3448: vt = valType->semantic(0, sc);
3449: //printf("ei: %s, ei->type: %s\n", ei->toChars(), ei->type->toChars());
3450: //printf("vt = %s\n", vt->toChars());
3451: if (ei->type)
3452: {
3453: m = (MATCH)ei->implicitConvTo(vt);
3454: //printf("m: %d\n", m);
3455: if (!m)
3456: goto Lnomatch;
3457: }
3458: dedtypes->tdata()[i] = ei;
3459:
3460: init = new ExpInitializer(loc, ei);
3461: sparam = new VarDeclaration(loc, vt, ident, init);
3462: sparam->storage_class = STCmanifest;
3463: *psparam = sparam;
3464: return m;
3465:
3466: Lnomatch:
3467: //printf("\tno match\n");
3468: *psparam = NULL;
3469: return MATCHnomatch;
3470: }
3471:
3472:
3473: void TemplateValueParameter::print(Object *oarg, Object *oded)
3474: {
3475: printf(" %s\n", ident->toChars());
3476:
3477: Expression *ea = isExpression(oded);
3478:
3479: if (specValue)
3480: printf("\tSpecialization: %s\n", specValue->toChars());
3481: printf("\tParameter Value: %s\n", ea ? ea->toChars() : "NULL");
3482: }
3483:
3484:
3485: void TemplateValueParameter::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
3486: {
3487: valType->toCBuffer(buf, ident, hgs);
3488: if (specValue)
3489: {
3490: buf->writestring(" : ");
3491: specValue->toCBuffer(buf, hgs);
3492: }
3493: if (defaultValue)
3494: {
3495: buf->writestring(" = ");
3496: defaultValue->toCBuffer(buf, hgs);
3497: }
3498: }
3499:
3500:
3501: void *TemplateValueParameter::dummyArg()
3502: { Expression *e;
3503:
3504: e = specValue;
3505: if (!e)
3506: {
3507: // Create a dummy value
3508: if (!edummy)
3509: edummy = valType->defaultInit();
3510: e = edummy;
3511: }
3512: return (void *)e;
3513: }
3514:
3515:
3516: Object *TemplateValueParameter::specialization()
3517: {
3518: return specValue;
3519: }
3520:
3521:
3522: Object *TemplateValueParameter::defaultArg(Loc loc, Scope *sc)
3523: {
3524: Expression *e = defaultValue;
3525: if (e)
3526: {
3527: e = e->syntaxCopy();
3528: e = e->semantic(sc);
3529: #if DMDV2
3530: e = e->resolveLoc(loc, sc);
3531: #endif
3532: }
3533: return e;
3534: }
3535:
3536: /* ======================== TemplateTupleParameter ========================== */
3537:
3538: // variadic-parameter
3539:
3540: TemplateTupleParameter::TemplateTupleParameter(Loc loc, Identifier *ident)
3541: : TemplateParameter(loc, ident)
3542: {
3543: this->ident = ident;
3544: }
3545:
3546: TemplateTupleParameter *TemplateTupleParameter::isTemplateTupleParameter()
3547: {
3548: return this;
3549: }
3550:
3551: TemplateParameter *TemplateTupleParameter::syntaxCopy()
3552: {
3553: TemplateTupleParameter *tp = new TemplateTupleParameter(loc, ident);
3554: return tp;
3555: }
3556:
3557: void TemplateTupleParameter::declareParameter(Scope *sc)
3558: {
3559: TypeIdentifier *ti = new TypeIdentifier(loc, ident);
3560: sparam = new AliasDeclaration(loc, ident, ti);
3561: if (!sc->insert(sparam))
3562: error(loc, "parameter '%s' multiply defined", ident->toChars());
3563: }
3564:
3565: void TemplateTupleParameter::semantic(Scope *sc)
3566: {
3567: }
3568:
3569: int TemplateTupleParameter::overloadMatch(TemplateParameter *tp)
3570: {
3571: TemplateTupleParameter *tvp = tp->isTemplateTupleParameter();
3572:
3573: if (tvp)
3574: {
3575: return 1; // match
3576: }
3577:
3578: Lnomatch:
warning C4102: 'Lnomatch' : unreferenced label
3579: return 0;
3580: }
3581:
3582: MATCH TemplateTupleParameter::matchArg(Scope *sc,
3583: Objects *tiargs, int i, TemplateParameters *parameters,
3584: Objects *dedtypes,
3585: Declaration **psparam, int flags)
3586: {
3587: //printf("TemplateTupleParameter::matchArg()\n");
3588:
3589: /* The rest of the actual arguments (tiargs[]) form the match
3590: * for the variadic parameter.
3591: */
3592: assert(i + 1 == dedtypes->dim); // must be the last one
3593: Tuple *ovar;
3594:
3595: if (dedtypes->tdata()[i] && isTuple(dedtypes->tdata()[i]))
3596: // It was already been deduced
3597: ovar = isTuple(dedtypes->tdata()[i]);
3598: else if (i + 1 == tiargs->dim && isTuple(tiargs->tdata()[i]))
3599: ovar = isTuple(tiargs->tdata()[i]);
3600: else
3601: {
3602: ovar = new Tuple();
warning C6211: Leaking memory 'ovar' due to an exception. Consider using a local catch block to clean up memory: Lines: 3592, 3593, 3595, 3598, 3602, 3604, 3612
warning C6211: Leaking memory 'dedtypes->public: struct Object * * __thiscall ArrayBase<struct Object>::tdata(void)()[868]' due to an exception. Consider using a local catch block to clean up memory: Lines: 3592, 3593, 3595, 3598, 3602, 3604, 3607, 3608, 3612
warning C6211: Leaking memory 'dedtypes->public: struct Object * * __thiscall ArrayBase<struct Object>::tdata(void)()[860]' due to an exception. Consider using a local catch block to clean up memory: Lines: 3592, 3593, 3595, 3598, 3602, 3604, 3607, 3608, 3609, 3608, 3609, 3608, 3612
warning C6211: Leaking memory 'dedtypes->public: struct Object * * __thiscall ArrayBase<struct Object>::tdata(void)()[6724]' due to an exception. Consider using a local catch block to clean up memory: Lines: 3592, 3593, 3595, 3598, 3602, 3604, 3607, 3608, 3612
warning C6211: Leaking memory 'dedtypes->public: struct Object * * __thiscall ArrayBase<struct Object>::tdata(void)()[6716]' due to an exception. Consider using a local catch block to clean up memory: Lines: 3592, 3593, 3595, 3598, 3602, 3604, 3607, 3608, 3609, 3608, 3609, 3608, 3612
warning C6211: Leaking memory 'dedtypes->public: struct Object * * __thiscall ArrayBase<struct Object>::tdata(void)()[13444]' due to an exception. Consider using a local catch block to clean up memory: Lines: 3592, 3593, 3595, 3598, 3602, 3604, 3607, 3608, 3612
warning C6211: Leaking memory 'dedtypes->public: struct Object * * __thiscall ArrayBase<struct Object>::tdata(void)()[13436]' due to an exception. Consider using a local catch block to clean up memory: Lines: 3592, 3593, 3595, 3598, 3602, 3604, 3607, 3608, 3609, 3608, 3609, 3608, 3612
warning C6211: Leaking memory 'dedtypes->public: struct Object * * __thiscall ArrayBase<struct Object>::tdata(void)()[19296]' due to an exception. Consider using a local catch block to clean up memory: Lines: 3592, 3593, 3595, 3598, 3602, 3604, 3607, 3608, 3612
warning C6211: Leaking memory 'dedtypes->public: struct Object * * __thiscall ArrayBase<struct Object>::tdata(void)()[19288]' due to an exception. Consider using a local catch block to clean up memory: Lines: 3592, 3593, 3595, 3598, 3602, 3604, 3607, 3608, 3609, 3608, 3609, 3608, 3612
3603: //printf("ovar = %p\n", ovar);
3604: if (i < tiargs->dim)
warning C4018: '<' : signed/unsigned mismatch
3605: {
3606: //printf("i = %d, tiargs->dim = %d\n", i, tiargs->dim);
3607: ovar->objects.setDim(tiargs->dim - i);
3608: for (size_t j = 0; j < ovar->objects.dim; j++)
3609: ovar->objects.tdata()[j] = tiargs->tdata()[i + j];
3610: }
3611: }
3612: *psparam = new TupleDeclaration(loc, ident, &ovar->objects);
3613: dedtypes->tdata()[i] = ovar;
3614: return MATCHexact;
3615: }
3616:
3617:
3618: void TemplateTupleParameter::print(Object *oarg, Object *oded)
3619: {
3620: printf(" %s... [", ident->toChars());
3621: Tuple *v = isTuple(oded);
3622: assert(v);
3623:
3624: //printf("|%d| ", v->objects.dim);
3625: for (int i = 0; i < v->objects.dim; i++)
warning C4018: '<' : signed/unsigned mismatch
3626: {
3627: if (i)
3628: printf(", ");
3629:
3630: Object *o = v->objects.tdata()[i];
3631:
3632: Dsymbol *sa = isDsymbol(o);
3633: if (sa)
3634: printf("alias: %s", sa->toChars());
3635:
3636: Type *ta = isType(o);
3637: if (ta)
3638: printf("type: %s", ta->toChars());
3639:
3640: Expression *ea = isExpression(o);
3641: if (ea)
3642: printf("exp: %s", ea->toChars());
3643:
3644: assert(!isTuple(o)); // no nested Tuple arguments
3645: }
3646:
3647: printf("]\n");
3648: }
3649:
3650: void TemplateTupleParameter::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
3651: {
3652: buf->writestring(ident->toChars());
3653: buf->writestring("...");
3654: }
3655:
3656:
3657: void *TemplateTupleParameter::dummyArg()
3658: {
3659: return NULL;
3660: }
3661:
3662:
3663: Object *TemplateTupleParameter::specialization()
3664: {
3665: return NULL;
3666: }
3667:
3668:
3669: Object *TemplateTupleParameter::defaultArg(Loc loc, Scope *sc)
3670: {
3671: return NULL;
3672: }
3673:
3674: /* ======================== TemplateInstance ================================ */
3675:
3676: TemplateInstance::TemplateInstance(Loc loc, Identifier *ident)
3677: : ScopeDsymbol(NULL)
3678: {
3679: #if LOG
3680: printf("TemplateInstance(this = %p, ident = '%s')\n", this, ident ? ident->toChars() : "null");
3681: #endif
3682: this->loc = loc;
3683: this->name = ident;
3684: this->tiargs = NULL;
3685: this->tempdecl = NULL;
3686: this->inst = NULL;
3687: this->tinst = NULL;
3688: this->argsym = NULL;
3689: this->aliasdecl = NULL;
3690: this->semanticRun = 0;
3691: this->semantictiargsdone = 0;
3692: this->withsym = NULL;
3693: this->nest = 0;
3694: this->havetempdecl = 0;
3695: this->isnested = NULL;
3696: this->errors = 0;
3697: }
3698:
3699: /*****************
3700: * This constructor is only called when we figured out which function
3701: * template to instantiate.
3702: */
3703:
3704: TemplateInstance::TemplateInstance(Loc loc, TemplateDeclaration *td, Objects *tiargs)
3705: : ScopeDsymbol(NULL)
3706: {
3707: #if LOG
3708: printf("TemplateInstance(this = %p, tempdecl = '%s')\n", this, td->toChars());
3709: #endif
3710: this->loc = loc;
3711: this->name = td->ident;
3712: this->tiargs = tiargs;
3713: this->tempdecl = td;
3714: this->inst = NULL;
3715: this->tinst = NULL;
3716: this->argsym = NULL;
3717: this->aliasdecl = NULL;
3718: this->semanticRun = 0;
3719: this->semantictiargsdone = 1;
3720: this->withsym = NULL;
3721: this->nest = 0;
3722: this->havetempdecl = 1;
3723: this->isnested = NULL;
3724: this->errors = 0;
3725:
3726: assert((size_t)tempdecl->scope > 0x10000);
3727: }
3728:
3729:
3730: Objects *TemplateInstance::arraySyntaxCopy(Objects *objs)
3731: {
3732: Objects *a = NULL;
3733: if (objs)
3734: { a = new Objects();
3735: a->setDim(objs->dim);
3736: for (size_t i = 0; i < objs->dim; i++)
3737: {
3738: a->tdata()[i] = objectSyntaxCopy(objs->tdata()[i]);
3739: }
3740: }
3741: return a;
3742: }
3743:
3744: Dsymbol *TemplateInstance::syntaxCopy(Dsymbol *s)
3745: {
3746: TemplateInstance *ti;
3747:
3748: if (s)
3749: ti = (TemplateInstance *)s;
3750: else
3751: ti = new TemplateInstance(loc, name);
3752:
3753: ti->tiargs = arraySyntaxCopy(tiargs);
3754:
3755: ScopeDsymbol::syntaxCopy(ti);
3756: return ti;
3757: }
3758:
3759:
3760: void TemplateInstance::semantic(Scope *sc)
3761: {
3762: semantic(sc, NULL);
3763: }
3764:
3765: void TemplateInstance::semantic(Scope *sc, Expressions *fargs)
3766: {
3767: //printf("TemplateInstance::semantic('%s', this=%p, gag = %d, sc = %p)\n", toChars(), this, global.gag, sc);
3768: if (global.errors && name != Id::AssociativeArray)
3769: {
3770: //printf("not instantiating %s due to %d errors\n", toChars(), global.errors);
3771: if (!global.gag)
3772: {
3773: /* Trying to soldier on rarely generates useful messages
3774: * at this point.
3775: */
3776: fatal();
3777: }
3778: // return;
3779: }
3780: #if LOG
3781: printf("\n+TemplateInstance::semantic('%s', this=%p)\n", toChars(), this);
3782: #endif
3783: if (inst) // if semantic() was already run
3784: {
3785: #if LOG
3786: printf("-TemplateInstance::semantic('%s', this=%p) already run\n", inst->toChars(), inst);
3787: #endif
3788: return;
3789: }
3790:
3791: // get the enclosing template instance from the scope tinst
3792: tinst = sc->tinst;
3793:
3794: if (semanticRun != 0)
3795: {
3796: #if LOG
3797: printf("Recursive template expansion\n");
3798: #endif
3799: error(loc, "recursive template expansion");
3800: // inst = this;
3801: return;
3802: }
3803: semanticRun = 1;
3804:
3805: #if LOG
3806: printf("\tdo semantic\n");
3807: #endif
3808: if (havetempdecl)
3809: {
3810: assert((size_t)tempdecl->scope > 0x10000);
3811: // Deduce tdtypes
3812: tdtypes.setDim(tempdecl->parameters->dim);
3813: if (!tempdecl->matchWithInstance(this, &tdtypes, fargs, 2))
3814: {
3815: error("incompatible arguments for template instantiation");
3816: inst = this;
3817: return;
3818: }
3819: }
3820: else
3821: {
3822: /* Run semantic on each argument, place results in tiargs[]
3823: * (if we havetempdecl, then tiargs is already evaluated)
3824: */
3825: semanticTiargs(sc);
3826: if (arrayObjectIsError(tiargs))
3827: { inst = this;
3828: //printf("error return %p, %d\n", tempdecl, global.errors);
3829: return; // error recovery
3830: }
3831:
3832: tempdecl = findTemplateDeclaration(sc);
3833: if (tempdecl)
3834: tempdecl = findBestMatch(sc, fargs);
3835: if (!tempdecl || global.errors)
3836: { inst = this;
3837: //printf("error return %p, %d\n", tempdecl, global.errors);
3838: return; // error recovery
3839: }
3840: }
3841:
3842: // If tempdecl is a mixin, disallow it
3843: if (tempdecl->ismixin)
3844: error("mixin templates are not regular templates");
3845:
3846: hasNestedArgs(tiargs);
3847:
3848: /* See if there is an existing TemplateInstantiation that already
3849: * implements the typeargs. If so, just refer to that one instead.
3850: */
3851:
3852: for (size_t i = 0; i < tempdecl->instances.dim; i++)
3853: {
3854: TemplateInstance *ti = tempdecl->instances.tdata()[i];
3855: #if LOG
3856: printf("\t%s: checking for match with instance %d (%p): '%s'\n", toChars(), i, ti, ti->toChars());
3857: #endif
3858: assert(tdtypes.dim == ti->tdtypes.dim);
3859:
3860: // Nesting must match
3861: if (isnested != ti->isnested)
3862: {
3863: //printf("test2 isnested %s ti->isnested %s\n", isnested ? isnested->toChars() : "", ti->isnested ? ti->isnested->toChars() : "");
3864: continue;
3865: }
3866: #if 0
3867: if (isnested && sc->parent != ti->parent)
3868: continue;
3869: #endif
3870: if (!arrayObjectMatch(&tdtypes, &ti->tdtypes, tempdecl, sc))
3871: goto L1;
3872:
3873: /* Template functions may have different instantiations based on
3874: * "auto ref" parameters.
3875: */
3876: if (fargs)
3877: {
3878: FuncDeclaration *fd = ti->toAlias()->isFuncDeclaration();
3879: if (fd)
3880: {
3881: Parameters *fparameters = fd->getParameters(NULL);
3882: size_t nfparams = Parameter::dim(fparameters); // Num function parameters
3883: for (int i = 0; i < nfparams && i < fargs->dim; i++)
warning C4018: '<' : signed/unsigned mismatch
warning C4018: '<' : signed/unsigned mismatch
warning C6246: Local declaration of 'i' hides declaration of the same name in outer scope. For additional information, see previous declaration at line '3852' of 'c:\projects\extern\d\dmd\src\template.c': Lines: 3852
3884: { Parameter *fparam = Parameter::getNth(fparameters, i);
3885: Expression *farg = fargs->tdata()[i];
3886: if (fparam->storageClass & STCauto) // if "auto ref"
3887: {
3888: if (farg->isLvalue())
3889: { if (!(fparam->storageClass & STCref))
3890: goto L1; // auto ref's don't match
3891: }
3892: else
3893: { if (fparam->storageClass & STCref)
3894: goto L1; // auto ref's don't match
3895: }
3896: }
3897: }
3898: }
3899: }
3900:
3901: // It's a match
3902: inst = ti;
3903: parent = ti->parent;
3904: #if LOG
3905: printf("\tit's a match with instance %p\n", inst);
3906: #endif
3907: return;
3908:
3909: L1:
3910: ;
3911: }
3912:
3913: /* So, we need to implement 'this' instance.
3914: */
3915: #if LOG
3916: printf("\timplement template instance %s '%s'\n", tempdecl->parent->toChars(), toChars());
3917: printf("\ttempdecl %s\n", tempdecl->toChars());
3918: #endif
3919: unsigned errorsave = global.errors;
3920: inst = this;
3921: int tempdecl_instance_idx = tempdecl->instances.dim;
3922: tempdecl->instances.push(this);
3923: parent = tempdecl->parent;
3924: //printf("parent = '%s'\n", parent->kind());
3925:
3926: ident = genIdent(tiargs); // need an identifier for name mangling purposes.
3927:
3928: #if 1
3929: if (isnested)
3930: parent = isnested;
3931: #endif
3932: //printf("parent = '%s'\n", parent->kind());
3933:
3934: // Add 'this' to the enclosing scope's members[] so the semantic routines
3935: // will get called on the instance members
3936: #if 1
3937: int dosemantic3 = 0;
3938: if (!sc->parameterSpecialization)
3939: { Dsymbols *a;
3940:
3941: Scope *scx = sc;
3942: #if 0
3943: for (scx = sc; scx; scx = scx->enclosing)
3944: if (scx->scopesym)
3945: break;
3946: #endif
3947:
3948: //if (scx && scx->scopesym) printf("3: scx is %s %s\n", scx->scopesym->kind(), scx->scopesym->toChars());
3949: if (scx && scx->scopesym &&
3950: scx->scopesym->members && !scx->scopesym->isTemplateMixin()
3951: #if 0 // removed because it bloated compile times
3952: /* The problem is if A imports B, and B imports A, and both A
3953: * and B instantiate the same template, does the compilation of A
3954: * or the compilation of B do the actual instantiation?
3955: *
3956: * see bugzilla 2500.
3957: */
3958: && !scx->module->selfImports()
3959: #endif
3960: )
3961: {
3962: //printf("\t1: adding to %s %s\n", scx->scopesym->kind(), scx->scopesym->toChars());
3963: a = scx->scopesym->members;
3964: }
3965: else
3966: { Module *m = sc->module->importedFrom;
3967: //printf("\t2: adding to module %s instead of module %s\n", m->toChars(), sc->module->toChars());
3968: a = m->members;
3969: if (m->semanticRun >= 3)
3970: {
3971: dosemantic3 = 1;
3972: }
3973: }
3974: for (int i = 0; 1; i++)
3975: {
3976: if (i == a->dim)
3977: {
3978: a->push(this);
3979: break;
3980: }
3981: if (this == a->tdata()[i]) // if already in Array
3982: break;
3983: }
3984: }
3985: #endif
3986:
3987: // Copy the syntax trees from the TemplateDeclaration
3988: members = Dsymbol::arraySyntaxCopy(tempdecl->members);
3989:
3990: // Create our own scope for the template parameters
3991: Scope *scope = tempdecl->scope;
3992: if (!tempdecl->semanticRun)
3993: {
3994: error("template instantiation %s forward references template declaration %s\n", toChars(), tempdecl->toChars());
3995: return;
3996: }
3997:
3998: #if LOG
3999: printf("\tcreate scope for template parameters '%s'\n", toChars());
4000: #endif
4001: argsym = new ScopeDsymbol();
4002: argsym->parent = scope->parent;
4003: scope = scope->push(argsym);
4004: // scope->stc = 0;
4005:
4006: // Declare each template parameter as an alias for the argument type
4007: Scope *paramscope = scope->push();
4008: paramscope->stc = 0;
4009: declareParameters(paramscope);
4010: paramscope->pop();
4011:
4012: // Add members of template instance to template instance symbol table
4013: // parent = scope->scopesym;
4014: symtab = new DsymbolTable();
4015: int memnum = 0;
4016: for (int i = 0; i < members->dim; i++)
warning C4018: '<' : signed/unsigned mismatch
4017: {
4018: Dsymbol *s = members->tdata()[i];
4019: #if LOG
4020: printf("\t[%d] adding member '%s' %p kind %s to '%s', memnum = %d\n", i, s->toChars(), s, s->kind(), this->toChars(), memnum);
4021: #endif
4022: memnum |= s->addMember(scope, this, memnum);
4023: }
4024: #if LOG
4025: printf("adding members done\n");
4026: #endif
4027:
4028: /* See if there is only one member of template instance, and that
4029: * member has the same name as the template instance.
4030: * If so, this template instance becomes an alias for that member.
4031: */
4032: //printf("members->dim = %d\n", members->dim);
4033: if (members->dim)
4034: {
4035: Dsymbol *s;
4036: if (Dsymbol::oneMembers(members, &s) && s)
4037: {
4038: //printf("s->kind = '%s'\n", s->kind());
4039: //s->print();
4040: //printf("'%s', '%s'\n", s->ident->toChars(), tempdecl->ident->toChars());
4041: if (s->ident && s->ident->equals(tempdecl->ident))
4042: {
4043: //printf("setting aliasdecl\n");
4044: aliasdecl = new AliasDeclaration(loc, s->ident, s);
4045: }
4046: }
4047: }
4048:
4049: /* If function template declaration
4050: */
4051: if (fargs && aliasdecl)
4052: {
4053: FuncDeclaration *fd = aliasdecl->toAlias()->isFuncDeclaration();
4054: if (fd)
4055: {
4056: /* Transmit fargs to type so that TypeFunction::semantic() can
4057: * resolve any "auto ref" storage classes.
4058: */
4059: TypeFunction *tf = (TypeFunction *)fd->type;
4060: if (tf && tf->ty == Tfunction)
4061: tf->fargs = fargs;
4062: }
4063: }
4064:
4065: // Do semantic() analysis on template instance members
4066: #if LOG
4067: printf("\tdo semantic() on template instance members '%s'\n", toChars());
4068: #endif
4069: Scope *sc2;
4070: sc2 = scope->push(this);
4071: //printf("isnested = %d, sc->parent = %s\n", isnested, sc->parent->toChars());
4072: sc2->parent = /*isnested ? sc->parent :*/ this;
4073: sc2->tinst = this;
4074:
4075: #if WINDOWS_SEH
4076: __try
4077: {
4078: #endif
4079: static int nest;
4080: //printf("%d\n", nest);
4081: if (++nest > 500)
4082: {
4083: global.gag = 0; // ensure error message gets printed
4084: error("recursive expansion");
4085: fatal();
4086: }
4087: for (int i = 0; i < members->dim; i++)
warning C4018: '<' : signed/unsigned mismatch
4088: {
4089: Dsymbol *s = members->tdata()[i];
4090: //printf("\t[%d] semantic on '%s' %p kind %s in '%s'\n", i, s->toChars(), s, s->kind(), this->toChars());
4091: //printf("test: isnested = %d, sc2->parent = %s\n", isnested, sc2->parent->toChars());
4092: // if (isnested)
4093: // s->parent = sc->parent;
4094: //printf("test3: isnested = %d, s->parent = %s\n", isnested, s->parent->toChars());
4095: s->semantic(sc2);
4096: //printf("test4: isnested = %d, s->parent = %s\n", isnested, s->parent->toChars());
4097: sc2->module->runDeferredSemantic();
4098: }
4099: --nest;
4100: #if WINDOWS_SEH
4101: }
4102: __except (__ehfilter(GetExceptionInformation()))
4103: {
4104: global.gag = 0; // ensure error message gets printed
4105: error("recursive expansion");
4106: fatal();
4107: }
4108: #endif
4109:
4110: /* If any of the instantiation members didn't get semantic() run
4111: * on them due to forward references, we cannot run semantic2()
4112: * or semantic3() yet.
4113: */
4114: for (size_t i = 0; i < Module::deferred.dim; i++)
4115: { Dsymbol *sd = Module::deferred.tdata()[i];
4116:
4117: if (sd->parent == this)
4118: {
4119: //printf("deferred %s %s\n", sd->parent->toChars(), sd->toChars());
4120: AggregateDeclaration *ad = sd->isAggregateDeclaration();
4121: if (ad)
4122: ad->deferred = this;
4123: goto Laftersemantic;
4124: }
4125: }
4126:
4127: /* The problem is when to parse the initializer for a variable.
4128: * Perhaps VarDeclaration::semantic() should do it like it does
4129: * for initializers inside a function.
4130: */
4131: // if (sc->parent->isFuncDeclaration())
4132:
4133: /* BUG 782: this has problems if the classes this depends on
4134: * are forward referenced. Find a way to defer semantic()
4135: * on this template.
4136: */
4137: semantic2(sc2);
4138:
4139: if (sc->func || dosemantic3)
4140: {
4141: #if WINDOWS_SEH
4142: __try
4143: {
4144: #endif
4145: static int nest;
warning C6246: Local declaration of 'nest' hides declaration of the same name in outer scope. For additional information, see previous declaration at line '4079' of 'c:\projects\extern\d\dmd\src\template.c': Lines: 4079
4146: if (++nest > 300)
4147: {
4148: global.gag = 0; // ensure error message gets printed
4149: error("recursive expansion");
4150: fatal();
4151: }
4152: semantic3(sc2);
4153: --nest;
4154: #if WINDOWS_SEH
4155: }
4156: __except (__ehfilter(GetExceptionInformation()))
4157: {
4158: global.gag = 0; // ensure error message gets printed
4159: error("recursive expansion");
4160: fatal();
4161: }
4162: #endif
4163: }
4164:
4165: Laftersemantic:
4166: sc2->pop();
4167:
4168: scope->pop();
4169:
4170: // Give additional context info if error occurred during instantiation
4171: if (global.errors != errorsave)
4172: {
4173: error(loc, "error instantiating");
4174: if (tinst)
4175: { tinst->printInstantiationTrace();
4176: }
4177: errors = 1;
4178: if (global.gag)
4179: { // Try to reset things so we can try again later to instantiate it
4180: //printf("remove %s\n", toChars());
4181: tempdecl->instances.remove(tempdecl_instance_idx);
4182: if (!(sc->flags & SCOPEstaticif))
4183: { // Bugzilla 4302 for discussion
4184: semanticRun = 0;
4185: inst = NULL;
4186: }
4187: }
4188: }
4189:
4190: #if LOG
4191: printf("-TemplateInstance::semantic('%s', this=%p)\n", toChars(), this);
4192: #endif
4193: }
4194:
4195:
4196: void TemplateInstance::semanticTiargs(Scope *sc)
4197: {
4198: //printf("+TemplateInstance::semanticTiargs() %s\n", toChars());
4199: if (semantictiargsdone)
4200: return;
4201: semantictiargsdone = 1;
4202: semanticTiargs(loc, sc, tiargs, 0);
4203: }
4204:
4205: /**********************************
4206: * Input:
4207: * flags 1: replace const variables with their initializers
4208: */
4209:
4210: void TemplateInstance::semanticTiargs(Loc loc, Scope *sc, Objects *tiargs, int flags)
4211: {
4212: // Run semantic on each argument, place results in tiargs[]
4213: //printf("+TemplateInstance::semanticTiargs()\n");
4214: if (!tiargs)
4215: return;
4216: for (size_t j = 0; j < tiargs->dim; j++)
4217: {
4218: Object *o = tiargs->tdata()[j];
4219: Type *ta = isType(o);
4220: Expression *ea = isExpression(o);
4221: Dsymbol *sa = isDsymbol(o);
4222:
4223: //printf("1: tiargs->tdata()[%d] = %p, %p, %p, ea=%p, ta=%p\n", j, o, isDsymbol(o), isTuple(o), ea, ta);
4224: if (ta)
4225: {
4226: //printf("type %s\n", ta->toChars());
4227: // It might really be an Expression or an Alias
4228: ta->resolve(loc, sc, &ea, &ta, &sa);
4229: if (ea)
4230: {
4231: ea = ea->semantic(sc);
4232: /* This test is to skip substituting a const var with
4233: * its initializer. The problem is the initializer won't
4234: * match with an 'alias' parameter. Instead, do the
4235: * const substitution in TemplateValueParameter::matchArg().
4236: */
4237: if (flags & 1) // only used by __traits, must not interpret the args
4238: ea = ea->optimize(WANTvalue);
4239: else if (ea->op != TOKvar)
4240: ea = ea->optimize(WANTvalue | WANTinterpret);
4241: tiargs->tdata()[j] = ea;
4242: }
4243: else if (sa)
4244: { tiargs->tdata()[j] = sa;
4245: TupleDeclaration *d = sa->toAlias()->isTupleDeclaration();
4246: if (d)
4247: {
4248: size_t dim = d->objects->dim;
4249: tiargs->remove(j);
4250: tiargs->insert(j, d->objects);
4251: j--;
4252: }
4253: }
4254: else if (ta)
4255: {
4256: Ltype:
4257: if (ta->ty == Ttuple)
4258: { // Expand tuple
4259: TypeTuple *tt = (TypeTuple *)ta;
4260: size_t dim = tt->arguments->dim;
4261: tiargs->remove(j);
4262: if (dim)
4263: { tiargs->reserve(dim);
4264: for (size_t i = 0; i < dim; i++)
4265: { Parameter *arg = tt->arguments->tdata()[i];
4266: tiargs->insert(j + i, arg->type);
4267: }
4268: }
4269: j--;
4270: }
4271: else
4272: tiargs->tdata()[j] = ta;
4273: }
4274: else
4275: {
4276: assert(global.errors);
4277: tiargs->tdata()[j] = Type::terror;
4278: }
4279: }
4280: else if (ea)
4281: {
4282: if (!ea)
4283: { assert(global.errors);
4284: ea = new ErrorExp();
4285: }
4286: assert(ea);
4287: ea = ea->semantic(sc);
4288: if (flags & 1) // only used by __traits, must not interpret the args
4289: ea = ea->optimize(WANTvalue);
4290: else if (ea->op != TOKvar)
4291: ea = ea->optimize(WANTvalue | WANTinterpret);
4292: tiargs->tdata()[j] = ea;
4293: if (ea->op == TOKtype)
4294: { ta = ea->type;
4295: goto Ltype;
4296: }
4297: if (ea->op == TOKtuple)
4298: { // Expand tuple
4299: TupleExp *te = (TupleExp *)ea;
4300: size_t dim = te->exps->dim;
4301: tiargs->remove(j);
4302: if (dim)
4303: { tiargs->reserve(dim);
4304: for (size_t i = 0; i < dim; i++)
4305: tiargs->insert(j + i, te->exps->tdata()[i]);
4306: }
4307: j--;
4308: }
4309: }
4310: else if (sa)
4311: {
4312: TemplateDeclaration *td = sa->isTemplateDeclaration();
4313: if (td && !td->semanticRun && td->literal)
4314: td->semantic(sc);
4315: }
4316: else
4317: {
4318: assert(0);
4319: }
4320: //printf("1: tiargs->tdata()[%d] = %p\n", j, tiargs->tdata()[j]);
4321: }
4322: #if 0
4323: printf("-TemplateInstance::semanticTiargs()\n");
4324: for (size_t j = 0; j < tiargs->dim; j++)
4325: {
4326: Object *o = tiargs->tdata()[j];
4327: Type *ta = isType(o);
4328: Expression *ea = isExpression(o);
4329: Dsymbol *sa = isDsymbol(o);
4330: Tuple *va = isTuple(o);
4331:
4332: printf("\ttiargs[%d] = ta %p, ea %p, sa %p, va %p\n", j, ta, ea, sa, va);
4333: }
4334: #endif
4335: }
4336:
4337: /**********************************************
4338: * Find template declaration corresponding to template instance.
4339: */
4340:
4341: TemplateDeclaration *TemplateInstance::findTemplateDeclaration(Scope *sc)
4342: {
4343: //printf("TemplateInstance::findTemplateDeclaration() %s\n", toChars());
4344: if (!tempdecl)
4345: {
4346: /* Given:
4347: * foo!( ... )
4348: * figure out which TemplateDeclaration foo refers to.
4349: */
4350: Dsymbol *s;
4351: Dsymbol *scopesym;
4352: Identifier *id;
4353: int i;
warning C4101: 'i' : unreferenced local variable
4354:
4355: id = name;
4356: s = sc->search(loc, id, &scopesym);
4357: if (!s)
4358: {
4359: s = sc->search_correct(id);
4360: if (s)
4361: error("template '%s' is not defined, did you mean %s?", id->toChars(), s->toChars());
4362: else
4363: error("template '%s' is not defined", id->toChars());
4364: return NULL;
4365: }
4366:
4367: /* If an OverloadSet, look for a unique member that is a template declaration
4368: */
4369: OverloadSet *os = s->isOverloadSet();
4370: if (os)
4371: { s = NULL;
4372: for (int i = 0; i < os->a.dim; i++)
warning C4018: '<' : signed/unsigned mismatch
warning C6246: Local declaration of 'i' hides declaration of the same name in outer scope. For additional information, see previous declaration at line '4353' of 'c:\projects\extern\d\dmd\src\template.c': Lines: 4353
4373: { Dsymbol *s2 = os->a.tdata()[i];
4374: if (s2->isTemplateDeclaration())
4375: {
4376: if (s)
4377: error("ambiguous template declaration %s and %s", s->toPrettyChars(), s2->toPrettyChars());
4378: s = s2;
4379: }
4380: }
4381: if (!s)
4382: { error("template '%s' is not defined", id->toChars());
4383: return NULL;
4384: }
4385: }
4386:
4387: #if LOG
4388: printf("It's an instance of '%s' kind '%s'\n", s->toChars(), s->kind());
4389: if (s->parent)
4390: printf("s->parent = '%s'\n", s->parent->toChars());
4391: #endif
4392: withsym = scopesym->isWithScopeSymbol();
4393:
4394: /* We might have found an alias within a template when
4395: * we really want the template.
4396: */
4397: TemplateInstance *ti;
4398: if (s->parent &&
4399: (ti = s->parent->isTemplateInstance()) != NULL)
4400: {
4401: if (ti->tempdecl && ti->tempdecl->ident == id)
4402: {
4403: /* This is so that one can refer to the enclosing
4404: * template, even if it has the same name as a member
4405: * of the template, if it has a !(arguments)
4406: */
4407: tempdecl = ti->tempdecl;
4408: if (tempdecl->overroot) // if not start of overloaded list of TemplateDeclaration's
4409: tempdecl = tempdecl->overroot; // then get the start
4410: s = tempdecl;
4411: }
4412: }
4413:
4414: s = s->toAlias();
4415:
4416: /* It should be a TemplateDeclaration, not some other symbol
4417: */
4418: tempdecl = s->isTemplateDeclaration();
4419: if (!tempdecl)
4420: {
4421: if (!s->parent && global.errors)
4422: return NULL;
4423: if (!s->parent && s->getType())
4424: { Dsymbol *s2 = s->getType()->toDsymbol(sc);
4425: if (!s2)
4426: {
4427: error("%s is not a template declaration, it is a %s", id->toChars(), s->kind());
4428: return NULL;
4429: }
4430: s = s2;
4431: }
4432: #ifdef DEBUG
4433: //if (!s->parent) printf("s = %s %s\n", s->kind(), s->toChars());
4434: #endif
4435: //assert(s->parent);
4436: TemplateInstance *ti = s->parent ? s->parent->isTemplateInstance() : NULL;
warning C6246: Local declaration of 'ti' hides declaration of the same name in outer scope. For additional information, see previous declaration at line '4397' of 'c:\projects\extern\d\dmd\src\template.c': Lines: 4397
4437: if (ti &&
4438: (ti->name == id ||
4439: ti->toAlias()->ident == id)
4440: &&
4441: ti->tempdecl)
4442: {
4443: /* This is so that one can refer to the enclosing
4444: * template, even if it has the same name as a member
4445: * of the template, if it has a !(arguments)
4446: */
4447: tempdecl = ti->tempdecl;
4448: if (tempdecl->overroot) // if not start of overloaded list of TemplateDeclaration's
4449: tempdecl = tempdecl->overroot; // then get the start
4450: }
4451: else
4452: {
4453: error("%s is not a template declaration, it is a %s", id->toChars(), s->kind());
4454: return NULL;
4455: }
4456: }
4457: }
4458: else
4459: assert(tempdecl->isTemplateDeclaration());
4460: return tempdecl;
4461: }
4462:
4463: TemplateDeclaration *TemplateInstance::findBestMatch(Scope *sc, Expressions *fargs)
4464: {
4465: /* Since there can be multiple TemplateDeclaration's with the same
4466: * name, look for the best match.
4467: */
4468: TemplateDeclaration *td_ambig = NULL;
4469: TemplateDeclaration *td_best = NULL;
4470: MATCH m_best = MATCHnomatch;
4471: Objects dedtypes;
4472:
4473: #if LOG
4474: printf("TemplateInstance::findBestMatch()\n");
4475: #endif
4476: // First look for forward references
4477: for (TemplateDeclaration *td = tempdecl; td; td = td->overnext)
4478: {
4479: if (!td->semanticRun)
4480: {
4481: if (td->scope)
4482: { // Try to fix forward reference
4483: td->semantic(td->scope);
4484: }
4485: if (!td->semanticRun)
4486: {
4487: error("%s forward references template declaration %s\n", toChars(), td->toChars());
4488: return NULL;
4489: }
4490: }
4491: }
4492:
4493: for (TemplateDeclaration *td = tempdecl; td; td = td->overnext)
4494: {
4495: MATCH m;
4496:
4497: //if (tiargs->dim) printf("2: tiargs->dim = %d, data[0] = %p\n", tiargs->dim, tiargs->tdata()[0]);
4498:
4499: // If more arguments than parameters,
4500: // then this is no match.
4501: if (td->parameters->dim < tiargs->dim)
4502: {
4503: if (!td->isVariadic())
4504: continue;
4505: }
4506:
4507: dedtypes.setDim(td->parameters->dim);
4508: dedtypes.zero();
4509: assert(td->semanticRun);
4510: m = td->matchWithInstance(this, &dedtypes, fargs, 0);
4511: //printf("matchWithInstance = %d\n", m);
4512: if (!m) // no match at all
4513: continue;
4514:
4515: if (m < m_best)
4516: goto Ltd_best;
4517: if (m > m_best)
4518: goto Ltd;
4519:
4520: {
4521: // Disambiguate by picking the most specialized TemplateDeclaration
4522: MATCH c1 = td->leastAsSpecialized(td_best, fargs);
4523: MATCH c2 = td_best->leastAsSpecialized(td, fargs);
4524: //printf("c1 = %d, c2 = %d\n", c1, c2);
4525:
4526: if (c1 > c2)
4527: goto Ltd;
4528: else if (c1 < c2)
4529: goto Ltd_best;
4530: else
4531: goto Lambig;
4532: }
4533:
4534: Lambig: // td_best and td are ambiguous
4535: td_ambig = td;
4536: continue;
4537:
4538: Ltd_best: // td_best is the best match so far
4539: td_ambig = NULL;
4540: continue;
4541:
4542: Ltd: // td is the new best match
4543: td_ambig = NULL;
4544: td_best = td;
4545: m_best = m;
4546: tdtypes.setDim(dedtypes.dim);
4547: memcpy(tdtypes.tdata(), dedtypes.tdata(), tdtypes.dim * sizeof(void *));
4548: continue;
4549: }
4550:
4551: if (!td_best)
4552: {
4553: if (tempdecl && !tempdecl->overnext)
4554: // Only one template, so we can give better error message
4555: error("%s does not match template declaration %s", toChars(), tempdecl->toChars());
4556: else
4557: error("%s does not match any template declaration", toChars());
4558: return NULL;
4559: }
4560: if (td_ambig)
4561: {
4562: error("%s matches more than one template declaration, %s(%d):%s and %s(%d):%s",
4563: toChars(),
4564: td_best->loc.filename, td_best->loc.linnum, td_best->toChars(),
4565: td_ambig->loc.filename, td_ambig->loc.linnum, td_ambig->toChars());
4566: }
4567:
4568: /* The best match is td_best
4569: */
4570: tempdecl = td_best;
4571:
4572: #if 0
4573: /* Cast any value arguments to be same type as value parameter
4574: */
4575: for (size_t i = 0; i < tiargs->dim; i++)
4576: { Object *o = tiargs->tdata()[i];
4577: Expression *ea = isExpression(o); // value argument
4578: TemplateParameter *tp = tempdecl->parameters->tdata()[i];
4579: assert(tp);
4580: TemplateValueParameter *tvp = tp->isTemplateValueParameter();
4581: if (tvp)
4582: {
4583: assert(ea);
4584: ea = ea->castTo(tvp->valType);
4585: ea = ea->optimize(WANTvalue | WANTinterpret);
4586: tiargs->tdata()[i] = (Object *)ea;
4587: }
4588: }
4589: #endif
4590:
4591: #if LOG
4592: printf("\tIt's a match with template declaration '%s'\n", tempdecl->toChars());
4593: #endif
4594: return tempdecl;
4595: }
4596:
4597:
4598: /*****************************************
4599: * Determines if a TemplateInstance will need a nested
4600: * generation of the TemplateDeclaration.
4601: */
4602:
4603: int TemplateInstance::hasNestedArgs(Objects *args)
4604: { int nested = 0;
4605: //printf("TemplateInstance::hasNestedArgs('%s')\n", tempdecl->ident->toChars());
4606:
4607: /* A nested instance happens when an argument references a local
4608: * symbol that is on the stack.
4609: */
4610: for (size_t i = 0; i < args->dim; i++)
4611: { Object *o = args->tdata()[i];
4612: Expression *ea = isExpression(o);
4613: Dsymbol *sa = isDsymbol(o);
4614: Tuple *va = isTuple(o);
4615: if (ea)
4616: {
4617: if (ea->op == TOKvar)
4618: {
4619: sa = ((VarExp *)ea)->var;
4620: goto Lsa;
4621: }
4622: if (ea->op == TOKfunction)
4623: {
4624: sa = ((FuncExp *)ea)->fd;
4625: goto Lsa;
4626: }
4627: }
4628: else if (sa)
4629: {
4630: Lsa:
4631: TemplateDeclaration *td = sa->isTemplateDeclaration();
4632: Declaration *d = sa->isDeclaration();
4633: if ((td && td->literal) ||
4634: (d && !d->isDataseg() &&
4635: #if DMDV2
4636: !(d->storage_class & STCmanifest) &&
4637: #endif
4638: (!d->isFuncDeclaration() || d->isFuncDeclaration()->isNested()) &&
4639: !isTemplateMixin()
4640: ))
4641: {
4642: // if module level template
4643: if (tempdecl->toParent()->isModule())
4644: { Dsymbol *dparent = sa->toParent();
4645: if (!isnested)
4646: isnested = dparent;
4647: else if (isnested != dparent)
4648: {
4649: /* Select the more deeply nested of the two.
4650: * Error if one is not nested inside the other.
4651: */
4652: for (Dsymbol *p = isnested; p; p = p->parent)
4653: {
4654: if (p == dparent)
4655: goto L1; // isnested is most nested
4656: }
4657: for (Dsymbol *p = dparent; p; p = p->parent)
4658: {
4659: if (p == isnested)
4660: { isnested = dparent;
4661: goto L1; // dparent is most nested
4662: }
4663: }
4664: error("%s is nested in both %s and %s",
4665: toChars(), isnested->toChars(), dparent->toChars());
4666: }
4667: L1:
4668: //printf("\tnested inside %s\n", isnested->toChars());
4669: nested |= 1;
4670: }
4671: else
4672: error("cannot use local '%s' as parameter to non-global template %s", sa->toChars(), tempdecl->toChars());
4673: }
4674: }
4675: else if (va)
4676: {
4677: nested |= hasNestedArgs(&va->objects);
4678: }
4679: }
4680: return nested;
4681: }
4682:
4683: /****************************************
4684: * This instance needs an identifier for name mangling purposes.
4685: * Create one by taking the template declaration name and adding
4686: * the type signature for it.
4687: */
4688:
4689: Identifier *TemplateInstance::genIdent(Objects *args)
4690: { OutBuffer buf;
4691:
4692: //printf("TemplateInstance::genIdent('%s')\n", tempdecl->ident->toChars());
4693: char *id = tempdecl->ident->toChars();
4694: buf.printf("__T%"SIZE_T_FORMAT"u%s", strlen(id), id);
4695: for (int i = 0; i < args->dim; i++)
warning C4018: '<' : signed/unsigned mismatch
4696: { Object *o = args->tdata()[i];
4697: Type *ta = isType(o);
4698: Expression *ea = isExpression(o);
4699: Dsymbol *sa = isDsymbol(o);
4700: Tuple *va = isTuple(o);
4701: //printf("\to [%d] %p ta %p ea %p sa %p va %p\n", i, o, ta, ea, sa, va);
4702: if (ta)
4703: {
4704: buf.writeByte('T');
4705: if (ta->deco)
4706: buf.writestring(ta->deco);
4707: else
4708: {
4709: #ifdef DEBUG
4710: printf("ta = %d, %s\n", ta->ty, ta->toChars());
4711: #endif
4712: assert(global.errors);
4713: }
4714: }
4715: else if (ea)
4716: {
4717: Lea:
warning C4102: 'Lea' : unreferenced label
4718: sinteger_t v;
warning C4101: 'v' : unreferenced local variable
4719: real_t r;
warning C4101: 'r' : unreferenced local variable
4720: // Don't interpret it yet, it might actually be an alias
4721: ea = ea->optimize(WANTvalue);
4722: if (ea->op == TOKvar)
4723: {
4724: sa = ((VarExp *)ea)->var;
4725: ea = NULL;
4726: goto Lsa;
4727: }
4728: if (ea->op == TOKthis)
4729: {
4730: sa = ((ThisExp *)ea)->var;
4731: ea = NULL;
4732: goto Lsa;
4733: }
4734: if (ea->op == TOKfunction)
4735: {
4736: sa = ((FuncExp *)ea)->fd;
4737: ea = NULL;
4738: goto Lsa;
4739: }
4740: buf.writeByte('V');
4741: if (ea->op == TOKtuple)
4742: { ea->error("tuple is not a valid template value argument");
4743: continue;
4744: }
4745: // Now that we know it is not an alias, we MUST obtain a value
4746: ea = ea->optimize(WANTvalue | WANTinterpret);
4747: #if 1
4748: /* Use deco that matches what it would be for a function parameter
4749: */
4750: buf.writestring(ea->type->deco);
4751: #else
4752: // Use type of parameter, not type of argument
4753: TemplateParameter *tp = tempdecl->parameters->tdata()[i];
4754: assert(tp);
4755: TemplateValueParameter *tvp = tp->isTemplateValueParameter();
4756: assert(tvp);
4757: buf.writestring(tvp->valType->deco);
4758: #endif
4759: ea->toMangleBuffer(&buf);
4760: }
4761: else if (sa)
4762: {
4763: Lsa:
4764: buf.writeByte('S');
4765: Declaration *d = sa->isDeclaration();
4766: if (d && (!d->type || !d->type->deco))
4767: { error("forward reference of %s", d->toChars());
4768: continue;
4769: }
4770: #if 0
4771: VarDeclaration *v = sa->isVarDeclaration();
4772: if (v && v->storage_class & STCmanifest)
4773: { ExpInitializer *ei = v->init->isExpInitializer();
4774: if (ei)
4775: {
4776: ea = ei->exp;
4777: goto Lea;
4778: }
4779: }
4780: #endif
4781: const char *p = sa->mangle();
4782:
4783: /* Bugzilla 3043: if the first character of p is a digit this
4784: * causes ambiguity issues because the digits of the two numbers are adjacent.
4785: * Current demanglers resolve this by trying various places to separate the
4786: * numbers until one gets a successful demangle.
4787: * Unfortunately, fixing this ambiguity will break existing binary
4788: * compatibility and the demanglers, so we'll leave it as is.
4789: */
4790: buf.printf("%"SIZE_T_FORMAT"u%s", strlen(p), p);
4791: }
4792: else if (va)
4793: {
4794: assert(i + 1 == args->dim); // must be last one
4795: args = &va->objects;
4796: i = -1;
4797: }
4798: else
4799: assert(0);
4800: }
4801: buf.writeByte('Z');
4802: id = buf.toChars();
4803: //buf.data = NULL; // we can free the string after call to idPool()
4804: //printf("\tgenIdent = %s\n", id);
4805: return Lexer::idPool(id);
4806: }
4807:
4808:
4809: /****************************************************
4810: * Declare parameters of template instance, initialize them with the
4811: * template instance arguments.
4812: */
4813:
4814: void TemplateInstance::declareParameters(Scope *sc)
4815: {
4816: //printf("TemplateInstance::declareParameters()\n");
4817: for (int i = 0; i < tdtypes.dim; i++)
warning C4018: '<' : signed/unsigned mismatch
4818: {
4819: TemplateParameter *tp = tempdecl->parameters->tdata()[i];
4820: //Object *o = tiargs->tdata()[i];
4821: Object *o = tdtypes.tdata()[i]; // initializer for tp
4822:
4823: //printf("\ttdtypes[%d] = %p\n", i, o);
4824: tempdecl->declareParameter(sc, tp, o);
4825: }
4826: }
4827:
4828: /*****************************************************
4829: * Determine if template instance is really a template function,
4830: * and that template function needs to infer types from the function
4831: * arguments.
4832: */
4833:
4834: int TemplateInstance::needsTypeInference(Scope *sc)
4835: {
4836: //printf("TemplateInstance::needsTypeInference() %s\n", toChars());
4837: if (!tempdecl)
4838: tempdecl = findTemplateDeclaration(sc);
4839: int multipleMatches = FALSE;
4840: for (TemplateDeclaration *td = tempdecl; td; td = td->overnext)
4841: {
4842: /* If any of the overloaded template declarations need inference,
4843: * then return TRUE
4844: */
4845: FuncDeclaration *fd;
4846: if (!td->onemember ||
4847: (fd = td->onemember->toAlias()->isFuncDeclaration()) == NULL ||
4848: fd->type->ty != Tfunction)
4849: {
4850: /* Not a template function, therefore type inference is not possible.
4851: */
4852: //printf("false\n");
4853: return FALSE;
4854: }
4855:
4856: /* Determine if the instance arguments, tiargs, are all that is necessary
4857: * to instantiate the template.
4858: */
4859: TemplateTupleParameter *tp = td->isVariadic();
4860: //printf("tp = %p, td->parameters->dim = %d, tiargs->dim = %d\n", tp, td->parameters->dim, tiargs->dim);
4861: TypeFunction *fdtype = (TypeFunction *)fd->type;
4862: if (Parameter::dim(fdtype->parameters) &&
4863: (tp || tiargs->dim < td->parameters->dim))
4864: return TRUE;
4865: /* If there is more than one function template which matches, we may
4866: * need type inference (see Bugzilla 4430)
4867: */
4868: if (td != tempdecl)
4869: multipleMatches = TRUE;
4870: }
4871: //printf("false\n");
4872: return multipleMatches;
4873: }
4874:
4875: void TemplateInstance::semantic2(Scope *sc)
4876: { int i;
4877:
4878: if (semanticRun >= 2)
4879: return;
4880: semanticRun = 2;
4881: #if LOG
4882: printf("+TemplateInstance::semantic2('%s')\n", toChars());
4883: #endif
4884: if (!errors && members)
4885: {
4886: sc = tempdecl->scope;
4887: assert(sc);
4888: sc = sc->push(argsym);
4889: sc = sc->push(this);
4890: sc->tinst = this;
4891: for (i = 0; i < members->dim; i++)
warning C4018: '<' : signed/unsigned mismatch
4892: {
4893: Dsymbol *s = members->tdata()[i];
4894: #if LOG
4895: printf("\tmember '%s', kind = '%s'\n", s->toChars(), s->kind());
4896: #endif
4897: s->semantic2(sc);
4898: }
4899: sc = sc->pop();
4900: sc->pop();
4901: }
4902: #if LOG
4903: printf("-TemplateInstance::semantic2('%s')\n", toChars());
4904: #endif
4905: }
4906:
4907: void TemplateInstance::semantic3(Scope *sc)
4908: {
4909: #if LOG
4910: printf("TemplateInstance::semantic3('%s'), semanticRun = %d\n", toChars(), semanticRun);
4911: #endif
4912: //if (toChars()[0] == 'D') *(char*)0=0;
4913: if (semanticRun >= 3)
4914: return;
4915: semanticRun = 3;
4916: if (!errors && members)
4917: {
4918: sc = tempdecl->scope;
4919: sc = sc->push(argsym);
4920: sc = sc->push(this);
4921: sc->tinst = this;
4922: for (int i = 0; i < members->dim; i++)
warning C4018: '<' : signed/unsigned mismatch
4923: {
4924: Dsymbol *s = members->tdata()[i];
4925: s->semantic3(sc);
4926: }
4927: sc = sc->pop();
4928: sc->pop();
4929: }
4930: }
4931:
4932: /**************************************
4933: * Given an error instantiating the TemplateInstance,
4934: * give the nested TemplateInstance instantiations that got
4935: * us here. Those are a list threaded into the nested scopes.
4936: */
4937: void TemplateInstance::printInstantiationTrace()
4938: {
4939: if (global.gag)
4940: return;
4941:
4942: const int max_shown = 6;
4943: const char format[] = "%s: instantiated from here: %s\n";
4944:
4945: // determine instantiation depth and number of recursive instantiations
4946: int n_instantiations = 1;
4947: int n_totalrecursions = 0;
4948: for (TemplateInstance *cur = this; cur; cur = cur->tinst)
4949: {
4950: ++n_instantiations;
4951: // If two instantiations use the same declaration, they are recursive.
4952: // (this works even if they are instantiated from different places in the
4953: // same template).
4954: // In principle, we could also check for multiple-template recursion, but it's
4955: // probably not worthwhile.
4956: if (cur->tinst && cur->tempdecl && cur->tinst->tempdecl
4957: && cur->tempdecl->loc.equals(cur->tinst->tempdecl->loc))
4958: ++n_totalrecursions;
4959: }
4960:
4961: // show full trace only if it's short or verbose is on
4962: if (n_instantiations <= max_shown || global.params.verbose)
4963: {
4964: for (TemplateInstance *cur = this; cur; cur = cur->tinst)
4965: {
4966: fprintf(stdmsg, format, cur->loc.toChars(), cur->toChars());
4967: }
4968: }
4969: else if (n_instantiations - n_totalrecursions <= max_shown)
4970: {
4971: // By collapsing recursive instantiations into a single line,
4972: // we can stay under the limit.
4973: int recursionDepth=0;
4974: for (TemplateInstance *cur = this; cur; cur = cur->tinst)
4975: {
4976: if (cur->tinst && cur->tempdecl && cur->tinst->tempdecl
4977: && cur->tempdecl->loc.equals(cur->tinst->tempdecl->loc))
4978: {
4979: ++recursionDepth;
4980: }
4981: else
4982: {
4983: if (recursionDepth)
4984: fprintf(stdmsg, "%s: %d recursive instantiations from here: %s\n", cur->loc.toChars(), recursionDepth+2, cur->toChars());
4985: else
4986: fprintf(stdmsg,format, cur->loc.toChars(), cur->toChars());
4987: recursionDepth = 0;
4988: }
4989: }
4990: }
4991: else
4992: {
4993: // Even after collapsing the recursions, the depth is too deep.
4994: // Just display the first few and last few instantiations.
4995: size_t i = 0;
4996: for (TemplateInstance *cur = this; cur; cur = cur->tinst)
4997: {
4998: if (i == max_shown / 2)
4999: fprintf(stdmsg," ... (%d instantiations, -v to show) ...\n", n_instantiations - max_shown);
5000:
5001: if (i < max_shown / 2 ||
5002: i >= n_instantiations - max_shown + max_shown / 2)
warning C4018: '>=' : signed/unsigned mismatch
5003: fprintf(stdmsg, format, cur->loc.toChars(), cur->toChars());
5004: ++i;
5005: }
5006: }
5007: }
5008:
5009: void TemplateInstance::toObjFile(int multiobj)
5010: {
5011: #if LOG
5012: printf("TemplateInstance::toObjFile('%s', this = %p)\n", toChars(), this);
5013: #endif
5014: if (!errors && members)
5015: {
5016: if (multiobj)
5017: // Append to list of object files to be written later
5018: obj_append(this);
5019: else
5020: {
5021: for (int i = 0; i < members->dim; i++)
warning C4018: '<' : signed/unsigned mismatch
5022: {
5023: Dsymbol *s = members->tdata()[i];
5024: s->toObjFile(multiobj);
5025: }
5026: }
5027: }
5028: }
5029:
5030: void TemplateInstance::inlineScan()
5031: {
5032: #if LOG
5033: printf("TemplateInstance::inlineScan('%s')\n", toChars());
5034: #endif
5035: if (!errors && members)
5036: {
5037: for (int i = 0; i < members->dim; i++)
warning C4018: '<' : signed/unsigned mismatch
5038: {
5039: Dsymbol *s = members->tdata()[i];
5040: s->inlineScan();
5041: }
5042: }
5043: }
5044:
5045: void TemplateInstance::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
5046: {
5047: int i;
5048:
5049: Identifier *id = name;
5050: buf->writestring(id->toChars());
5051: buf->writestring("!(");
5052: if (nest)
5053: buf->writestring("...");
5054: else
5055: {
5056: nest++;
5057: Objects *args = tiargs;
5058: for (i = 0; i < args->dim; i++)
warning C4018: '<' : signed/unsigned mismatch
5059: {
5060: if (i)
5061: buf->writeByte(',');
5062: Object *oarg = args->tdata()[i];
5063: ObjectToCBuffer(buf, hgs, oarg);
5064: }
5065: nest--;
5066: }
5067: buf->writeByte(')');
5068: }
5069:
5070:
5071: Dsymbol *TemplateInstance::toAlias()
5072: {
5073: #if LOG
5074: printf("TemplateInstance::toAlias()\n");
5075: #endif
5076: if (!inst)
5077: { error("cannot resolve forward reference");
5078: errors = 1;
5079: return this;
5080: }
5081:
5082: if (inst != this)
5083: return inst->toAlias();
5084:
5085: if (aliasdecl)
5086: {
5087: return aliasdecl->toAlias();
5088: }
5089:
5090: return inst;
5091: }
5092:
5093: AliasDeclaration *TemplateInstance::isAliasDeclaration()
5094: {
5095: return aliasdecl;
5096: }
5097:
5098: const char *TemplateInstance::kind()
5099: {
5100: return "template instance";
5101: }
5102:
5103: int TemplateInstance::oneMember(Dsymbol **ps)
5104: {
5105: *ps = NULL;
5106: return TRUE;
5107: }
5108:
5109: char *TemplateInstance::toChars()
5110: {
5111: OutBuffer buf;
5112: HdrGenState hgs;
5113: char *s;
5114:
5115: toCBuffer(&buf, &hgs);
5116: s = buf.toChars();
5117: buf.data = NULL;
5118: return s;
5119: }
5120:
5121: /* ======================== TemplateMixin ================================ */
5122:
5123: TemplateMixin::TemplateMixin(Loc loc, Identifier *ident, Type *tqual,
5124: Identifiers *idents, Objects *tiargs)
5125: : TemplateInstance(loc, idents->tdata()[idents->dim - 1])
5126: {
5127: //printf("TemplateMixin(ident = '%s')\n", ident ? ident->toChars() : "");
5128: this->ident = ident;
5129: this->tqual = tqual;
5130: this->idents = idents;
5131: this->tiargs = tiargs ? tiargs : new Objects();
5132: }
5133:
5134: Dsymbol *TemplateMixin::syntaxCopy(Dsymbol *s)
5135: { TemplateMixin *tm;
5136:
5137: Identifiers *ids = new Identifiers();
5138: ids->setDim(idents->dim);
5139: for (int i = 0; i < idents->dim; i++)
warning C4018: '<' : signed/unsigned mismatch
5140: { // Matches TypeQualified::syntaxCopyHelper()
5141: Identifier *id = idents->tdata()[i];
5142: if (id->dyncast() == DYNCAST_DSYMBOL)
5143: {
5144: TemplateInstance *ti = (TemplateInstance *)id;
5145:
5146: ti = (TemplateInstance *)ti->syntaxCopy(NULL);
5147: id = (Identifier *)ti;
5148: }
5149: ids->tdata()[i] = id;
5150: }
5151:
5152: tm = new TemplateMixin(loc, ident,
5153: (Type *)(tqual ? tqual->syntaxCopy() : NULL),
5154: ids, tiargs);
5155: TemplateInstance::syntaxCopy(tm);
5156: return tm;
5157: }
5158:
5159: void TemplateMixin::semantic(Scope *sc)
5160: {
5161: #if LOG
5162: printf("+TemplateMixin::semantic('%s', this=%p)\n", toChars(), this);
5163: fflush(stdout);
5164: #endif
5165: if (semanticRun)
5166: {
5167: // This for when a class/struct contains mixin members, and
5168: // is done over because of forward references
5169: if (parent && toParent()->isAggregateDeclaration())
5170: semanticRun = 1; // do over
5171: else
5172: {
5173: #if LOG
5174: printf("\tsemantic done\n");
5175: #endif
5176: return;
5177: }
5178: }
5179: if (!semanticRun)
5180: semanticRun = 1;
5181: #if LOG
5182: printf("\tdo semantic\n");
5183: #endif
5184: util_progress();
5185:
5186: Scope *scx = NULL;
5187: if (scope)
5188: { sc = scope;
5189: scx = scope; // save so we don't make redundant copies
5190: scope = NULL;
5191: }
5192:
5193: // Follow qualifications to find the TemplateDeclaration
5194: if (!tempdecl)
5195: { Dsymbol *s;
5196: int i;
5197: Identifier *id;
5198:
5199: if (tqual)
5200: { s = tqual->toDsymbol(sc);
5201: i = 0;
5202: }
5203: else
5204: {
5205: i = 1;
5206: id = idents->tdata()[0];
5207: switch (id->dyncast())
5208: {
5209: case DYNCAST_IDENTIFIER:
5210: s = sc->search(loc, id, NULL);
5211: break;
5212:
5213: case DYNCAST_DSYMBOL:
5214: {
5215: TemplateInstance *ti = (TemplateInstance *)id;
5216: ti->semantic(sc);
5217: s = ti;
5218: break;
5219: }
5220: default:
5221: assert(0);
5222: }
5223: }
5224:
5225: for (; i < idents->dim; i++)
warning C4018: '<' : signed/unsigned mismatch
5226: {
5227: if (!s)
5228: break;
5229: id = idents->tdata()[i];
5230: s = s->searchX(loc, sc, id);
5231: }
5232: if (!s)
5233: {
5234: error("is not defined");
5235: inst = this;
5236: return;
5237: }
5238: tempdecl = s->toAlias()->isTemplateDeclaration();
5239: if (!tempdecl)
5240: {
5241: error("%s isn't a template", s->toChars());
5242: inst = this;
5243: return;
5244: }
5245: }
5246:
5247: // Look for forward reference
5248: assert(tempdecl);
5249: for (TemplateDeclaration *td = tempdecl; td; td = td->overnext)
5250: {
5251: if (!td->semanticRun)
5252: {
5253: /* Cannot handle forward references if mixin is a struct member,
5254: * because addField must happen during struct's semantic, not
5255: * during the mixin semantic.
5256: * runDeferred will re-run mixin's semantic outside of the struct's
5257: * semantic.
5258: */
5259: semanticRun = 0;
5260: AggregateDeclaration *ad = toParent()->isAggregateDeclaration();
5261: if (ad)
5262: ad->sizeok = 2;
5263: else
5264: {
5265: // Forward reference
5266: //printf("forward reference - deferring\n");
5267: scope = scx ? scx : new Scope(*sc);
5268: scope->setNoFree();
5269: scope->module->addDeferredSemantic(this);
5270: }
5271: return;
5272: }
5273: }
5274:
5275: // Run semantic on each argument, place results in tiargs[]
5276: semanticTiargs(sc);
5277: if (errors)
5278: return;
5279:
5280: tempdecl = findBestMatch(sc, NULL);
5281: if (!tempdecl)
5282: { inst = this;
5283: return; // error recovery
5284: }
5285:
5286: if (!ident)
5287: ident = genIdent(tiargs);
5288:
5289: inst = this;
5290: parent = sc->parent;
5291:
5292: /* Detect recursive mixin instantiations.
5293: */
5294: for (Dsymbol *s = parent; s; s = s->parent)
5295: {
5296: //printf("\ts = '%s'\n", s->toChars());
5297: TemplateMixin *tm = s->isTemplateMixin();
5298: if (!tm || tempdecl != tm->tempdecl)
5299: continue;
5300:
5301: /* Different argument list lengths happen with variadic args
5302: */
5303: if (tiargs->dim != tm->tiargs->dim)
5304: continue;
5305:
5306: for (int i = 0; i < tiargs->dim; i++)
warning C4018: '<' : signed/unsigned mismatch
5307: { Object *o = tiargs->tdata()[i];
5308: Type *ta = isType(o);
5309: Expression *ea = isExpression(o);
5310: Dsymbol *sa = isDsymbol(o);
5311: Object *tmo = tm->tiargs->tdata()[i];
5312: if (ta)
5313: {
5314: Type *tmta = isType(tmo);
5315: if (!tmta)
5316: goto Lcontinue;
5317: if (!ta->equals(tmta))
5318: goto Lcontinue;
5319: }
5320: else if (ea)
5321: { Expression *tme = isExpression(tmo);
5322: if (!tme || !ea->equals(tme))
5323: goto Lcontinue;
5324: }
5325: else if (sa)
5326: {
5327: Dsymbol *tmsa = isDsymbol(tmo);
5328: if (sa != tmsa)
5329: goto Lcontinue;
5330: }
5331: else
5332: assert(0);
5333: }
5334: error("recursive mixin instantiation");
5335: return;
5336:
5337: Lcontinue:
5338: continue;
5339: }
5340:
5341: // Copy the syntax trees from the TemplateDeclaration
5342: members = Dsymbol::arraySyntaxCopy(tempdecl->members);
5343: if (!members)
5344: return;
5345:
5346: symtab = new DsymbolTable();
5347:
5348: for (Scope *sce = sc; 1; sce = sce->enclosing)
5349: {
5350: ScopeDsymbol *sds = (ScopeDsymbol *)sce->scopesym;
5351: if (sds)
5352: {
5353: sds->importScope(this, PROTpublic);
warning C6011: Dereferencing NULL pointer 'sds': Lines: 5165, 5169, 5170, 5179, 5184, 5186, 5187, 5188, 5189, 5190, 5194, 5248, 5249, 5251, 5249, 5276, 5277, 5280, 5281, 5286, 5289, 5290, 5294, 5297, 5298, 5294, 5342, 5343, 5346, 5348, 5350, 5351, 5348, 5350, 5351, 5348, 5350, 5351, 5348, 5350, 5351, 5353
5354: break;
5355: }
5356: }
5357:
5358: #if LOG
5359: printf("\tcreate scope for template parameters '%s'\n", toChars());
5360: #endif
5361: Scope *scy = sc;
5362: scy = sc->push(this);
5363: scy->parent = this;
5364:
5365: argsym = new ScopeDsymbol();
5366: argsym->parent = scy->parent;
5367: Scope *argscope = scy->push(argsym);
5368:
5369: unsigned errorsave = global.errors;
5370:
5371: // Declare each template parameter as an alias for the argument type
5372: declareParameters(argscope);
5373:
5374: // Add members to enclosing scope, as well as this scope
5375: for (unsigned i = 0; i < members->dim; i++)
5376: { Dsymbol *s;
5377:
5378: s = members->tdata()[i];
5379: s->addMember(argscope, this, i);
5380: //sc->insert(s);
5381: //printf("sc->parent = %p, sc->scopesym = %p\n", sc->parent, sc->scopesym);
5382: //printf("s->parent = %s\n", s->parent->toChars());
5383: }
5384:
5385: // Do semantic() analysis on template instance members
5386: #if LOG
5387: printf("\tdo semantic() on template instance members '%s'\n", toChars());
5388: #endif
5389: Scope *sc2;
5390: sc2 = argscope->push(this);
5391: sc2->offset = sc->offset;
5392:
5393: static int nest;
5394: //printf("%d\n", nest);
5395: if (++nest > 500)
5396: {
5397: global.gag = 0; // ensure error message gets printed
5398: error("recursive expansion");
5399: fatal();
5400: }
5401:
5402: for (int i = 0; i < members->dim; i++)
warning C4018: '<' : signed/unsigned mismatch
5403: {
5404: Dsymbol *s = members->tdata()[i];
5405: s->semantic(sc2);
5406: }
5407:
5408: nest--;
5409:
5410: sc->offset = sc2->offset;
5411:
5412: /* The problem is when to parse the initializer for a variable.
5413: * Perhaps VarDeclaration::semantic() should do it like it does
5414: * for initializers inside a function.
5415: */
5416: // if (sc->parent->isFuncDeclaration())
5417:
5418: semantic2(sc2);
5419:
5420: if (sc->func)
5421: {
5422: semantic3(sc2);
5423: }
5424:
5425: // Give additional context info if error occurred during instantiation
5426: if (global.errors != errorsave)
5427: {
5428: error("error instantiating");
5429: }
5430:
5431: sc2->pop();
5432:
5433: argscope->pop();
5434:
5435: // if (!isAnonymous())
5436: {
5437: scy->pop();
5438: }
5439: #if LOG
5440: printf("-TemplateMixin::semantic('%s', this=%p)\n", toChars(), this);
5441: #endif
5442: }
5443:
5444: void TemplateMixin::semantic2(Scope *sc)
5445: { int i;
5446:
5447: if (semanticRun >= 2)
5448: return;
5449: semanticRun = 2;
5450: #if LOG
5451: printf("+TemplateMixin::semantic2('%s')\n", toChars());
5452: #endif
5453: if (members)
5454: {
5455: assert(sc);
5456: sc = sc->push(argsym);
5457: sc = sc->push(this);
5458: for (i = 0; i < members->dim; i++)
warning C4018: '<' : signed/unsigned mismatch
5459: {
5460: Dsymbol *s = members->tdata()[i];
5461: #if LOG
5462: printf("\tmember '%s', kind = '%s'\n", s->toChars(), s->kind());
5463: #endif
5464: s->semantic2(sc);
5465: }
5466: sc = sc->pop();
5467: sc->pop();
5468: }
5469: #if LOG
5470: printf("-TemplateMixin::semantic2('%s')\n", toChars());
5471: #endif
5472: }
5473:
5474: void TemplateMixin::semantic3(Scope *sc)
5475: { int i;
5476:
5477: if (semanticRun >= 3)
5478: return;
5479: semanticRun = 3;
5480: #if LOG
5481: printf("TemplateMixin::semantic3('%s')\n", toChars());
5482: #endif
5483: if (members)
5484: {
5485: sc = sc->push(argsym);
5486: sc = sc->push(this);
5487: for (i = 0; i < members->dim; i++)
warning C4018: '<' : signed/unsigned mismatch
5488: {
5489: Dsymbol *s = members->tdata()[i];
5490: s->semantic3(sc);
5491: }
5492: sc = sc->pop();
5493: sc->pop();
5494: }
5495: }
5496:
5497: void TemplateMixin::inlineScan()
5498: {
5499: TemplateInstance::inlineScan();
5500: }
5501:
5502: const char *TemplateMixin::kind()
5503: {
5504: return "mixin";
5505: }
5506:
5507: int TemplateMixin::oneMember(Dsymbol **ps)
5508: {
5509: return Dsymbol::oneMember(ps);
5510: }
5511:
5512: int TemplateMixin::hasPointers()
5513: {
5514: //printf("TemplateMixin::hasPointers() %s\n", toChars());
5515: for (size_t i = 0; i < members->dim; i++)
5516: {
5517: Dsymbol *s = members->tdata()[i];
5518: //printf(" s = %s %s\n", s->kind(), s->toChars());
5519: if (s->hasPointers())
5520: {
5521: return 1;
5522: }
5523: }
5524: return 0;
5525: }
5526:
5527: char *TemplateMixin::toChars()
5528: {
5529: OutBuffer buf;
5530: HdrGenState hgs;
5531: char *s;
5532:
5533: TemplateInstance::toCBuffer(&buf, &hgs);
5534: s = buf.toChars();
5535: buf.data = NULL;
5536: return s;
5537: }
5538:
5539: void TemplateMixin::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
5540: {
5541: buf->writestring("mixin ");
5542:
5543: for (int i = 0; i < idents->dim; i++)
warning C4018: '<' : signed/unsigned mismatch
5544: { Identifier *id = idents->tdata()[i];
5545:
5546: if (i)
5547: buf->writeByte('.');
5548: buf->writestring(id->toChars());
5549: }
5550: buf->writestring("!(");
5551: if (tiargs)
5552: {
5553: for (int i = 0; i < tiargs->dim; i++)
warning C4018: '<' : signed/unsigned mismatch
5554: { if (i)
5555: buf->writebyte(',');
5556: Object *oarg = tiargs->tdata()[i];
5557: Type *t = isType(oarg);
5558: Expression *e = isExpression(oarg);
5559: Dsymbol *s = isDsymbol(oarg);
5560: if (t)
5561: t->toCBuffer(buf, NULL, hgs);
5562: else if (e)
5563: e->toCBuffer(buf, hgs);
5564: else if (s)
5565: {
5566: char *p = s->ident ? s->ident->toChars() : s->toChars();
5567: buf->writestring(p);
5568: }
5569: else if (!oarg)
5570: {
5571: buf->writestring("NULL");
5572: }
5573: else
5574: {
5575: assert(0);
5576: }
5577: }
5578: }
5579: buf->writebyte(')');
5580: if (ident)
5581: {
5582: buf->writebyte(' ');
5583: buf->writestring(ident->toChars());
5584: }
5585: buf->writebyte(';');
5586: buf->writenl();
5587: }
5588:
5589:
5590: void TemplateMixin::toObjFile(int multiobj)
5591: {
5592: //printf("TemplateMixin::toObjFile('%s')\n", toChars());
5593: TemplateInstance::toObjFile(multiobj);
5594: }
5595:
5596: