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 = &pr; // 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: