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: