1: 
   2: // Compiler implementation of the D programming language
   3: // Copyright (c) 1999-2010 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: #include <stdio.h>
  12: #include <stdlib.h>
  13: #include <ctype.h>
  14: static char __file__[] = __FILE__;      /* for tassert.h                */
  15: #include        "tassert.h"
  16: #if _MSC_VER
  17: #include <complex>
  18: #else
  19: #include <complex.h>
  20: #endif
  21: 
  22: #ifdef __APPLE__
  23: #define integer_t dmd_integer_t
  24: #endif
  25: 
  26: #include "rmem.h"
  27: 
  28: //#include "port.h"
  29: #include "mtype.h"
  30: #include "init.h"
  31: #include "expression.h"
  32: #include "id.h"
  33: #include "declaration.h"
  34: #include "aggregate.h"
  35: #include "template.h"
  36: 
  37: static void inferApplyArgTypesX(FuncDeclaration *fstart, Parameters *arguments);
  38: static void inferApplyArgTypesZ(TemplateDeclaration *tstart, Parameters *arguments);
  39: static int inferApplyArgTypesY(TypeFunction *tf, Parameters *arguments);
  40: static void templateResolve(Match *m, TemplateDeclaration *td, Scope *sc, Loc loc, Objects *targsi, Expression *ethis, Expressions *arguments);
  41: 
  42: /******************************** Expression **************************/
  43: 
  44: 
  45: /***********************************
  46:  * Determine if operands of binary op can be reversed
  47:  * to fit operator overload.
  48:  */
  49: 
  50: int Expression::isCommutative()
  51: {
  52:     return FALSE;       // default is no reverse
  53: }
  54: 
  55: /***********************************
  56:  * Get Identifier for operator overload.
  57:  */
  58: 
  59: Identifier *Expression::opId()
  60: {
  61:     assert(0);
  62:     return NULL;
  63: }
  64: 
  65: /***********************************
  66:  * Get Identifier for reverse operator overload,
  67:  * NULL if not supported for this operator.
  68:  */
  69: 
  70: Identifier *Expression::opId_r()
  71: {
  72:     return NULL;
  73: }
  74: 
  75: /************************* Operators *****************************/
  76: 
  77: Identifier *UAddExp::opId()   { return Id::uadd; }
  78: 
  79: Identifier *NegExp::opId()   { return Id::neg; }
  80: 
  81: Identifier *ComExp::opId()   { return Id::com; }
  82: 
  83: Identifier *CastExp::opId()   { return Id::cast; }
  84: 
  85: Identifier *InExp::opId()     { return Id::opIn; }
  86: Identifier *InExp::opId_r()     { return Id::opIn_r; }
  87: 
  88: Identifier *PostExp::opId() { return (op == TOKplusplus)
  89:                                 ? Id::postinc
  90:                                 : Id::postdec; }
  91: 
  92: int AddExp::isCommutative()  { return TRUE; }
  93: Identifier *AddExp::opId()   { return Id::add; }
  94: Identifier *AddExp::opId_r() { return Id::add_r; }
  95: 
  96: Identifier *MinExp::opId()   { return Id::sub; }
  97: Identifier *MinExp::opId_r() { return Id::sub_r; }
  98: 
  99: int MulExp::isCommutative()  { return TRUE; }
 100: Identifier *MulExp::opId()   { return Id::mul; }
 101: Identifier *MulExp::opId_r() { return Id::mul_r; }
 102: 
 103: Identifier *DivExp::opId()   { return Id::div; }
 104: Identifier *DivExp::opId_r() { return Id::div_r; }
 105: 
 106: Identifier *ModExp::opId()   { return Id::mod; }
 107: Identifier *ModExp::opId_r() { return Id::mod_r; }
 108: 
 109: #if DMDV2
 110: Identifier *PowExp::opId()   { return Id::pow; }
 111: Identifier *PowExp::opId_r() { return Id::pow_r; }
 112: #endif
 113: 
 114: Identifier *ShlExp::opId()   { return Id::shl; }
 115: Identifier *ShlExp::opId_r() { return Id::shl_r; }
 116: 
 117: Identifier *ShrExp::opId()   { return Id::shr; }
 118: Identifier *ShrExp::opId_r() { return Id::shr_r; }
 119: 
 120: Identifier *UshrExp::opId()   { return Id::ushr; }
 121: Identifier *UshrExp::opId_r() { return Id::ushr_r; }
 122: 
 123: int AndExp::isCommutative()  { return TRUE; }
 124: Identifier *AndExp::opId()   { return Id::iand; }
 125: Identifier *AndExp::opId_r() { return Id::iand_r; }
 126: 
 127: int OrExp::isCommutative()  { return TRUE; }
 128: Identifier *OrExp::opId()   { return Id::ior; }
 129: Identifier *OrExp::opId_r() { return Id::ior_r; }
 130: 
 131: int XorExp::isCommutative()  { return TRUE; }
 132: Identifier *XorExp::opId()   { return Id::ixor; }
 133: Identifier *XorExp::opId_r() { return Id::ixor_r; }
 134: 
 135: Identifier *CatExp::opId()   { return Id::cat; }
 136: Identifier *CatExp::opId_r() { return Id::cat_r; }
 137: 
 138: Identifier *    AssignExp::opId()  { return Id::assign;  }
 139: Identifier * AddAssignExp::opId()  { return Id::addass;  }
 140: Identifier * MinAssignExp::opId()  { return Id::subass;  }
 141: Identifier * MulAssignExp::opId()  { return Id::mulass;  }
 142: Identifier * DivAssignExp::opId()  { return Id::divass;  }
 143: Identifier * ModAssignExp::opId()  { return Id::modass;  }
 144: Identifier * AndAssignExp::opId()  { return Id::andass;  }
 145: Identifier *  OrAssignExp::opId()  { return Id::orass;   }
 146: Identifier * XorAssignExp::opId()  { return Id::xorass;  }
 147: Identifier * ShlAssignExp::opId()  { return Id::shlass;  }
 148: Identifier * ShrAssignExp::opId()  { return Id::shrass;  }
 149: Identifier *UshrAssignExp::opId()  { return Id::ushrass; }
 150: Identifier * CatAssignExp::opId()  { return Id::catass;  }
 151: Identifier * PowAssignExp::opId()  { return Id::powass;  }
 152: 
 153: int EqualExp::isCommutative()  { return TRUE; }
 154: Identifier *EqualExp::opId()   { return Id::eq; }
 155: 
 156: int CmpExp::isCommutative()  { return TRUE; }
 157: Identifier *CmpExp::opId()   { return Id::cmp; }
 158: 
 159: Identifier *ArrayExp::opId()    { return Id::index; }
 160: Identifier *PtrExp::opId()      { return Id::opStar; }
 161: 
 162: /************************************
 163:  * If type is a class or struct, return the symbol for it,
 164:  * else NULL
 165:  */
 166: AggregateDeclaration *isAggregate(Type *t)
 167: {
 168:     t = t->toBasetype();
 169:     if (t->ty == Tclass)
 170:     {
 171:         return ((TypeClass *)t)->sym;
 172:     }
 173:     else if (t->ty == Tstruct)
 174:     {
 175:         return ((TypeStruct *)t)->sym;
 176:     }
 177:     return NULL;
 178: }
 179: 
 180: /*******************************************
 181:  * Helper function to turn operator into template argument list
 182:  */
 183: Objects *opToArg(Scope *sc, enum TOK op)
 184: {
 185:     /* Remove the = from op=
 186:      */
 187:     switch (op)
 188:     {
 189:         case TOKaddass: op = TOKadd; break;
 190:         case TOKminass: op = TOKmin; break;
 191:         case TOKmulass: op = TOKmul; break;
 192:         case TOKdivass: op = TOKdiv; break;
 193:         case TOKmodass: op = TOKmod; break;
 194:         case TOKandass: op = TOKand; break;
 195:         case TOKorass:  op = TOKor;  break;
 196:         case TOKxorass: op = TOKxor; break;
 197:         case TOKshlass: op = TOKshl; break;
 198:         case TOKshrass: op = TOKshr; break;
 199:         case TOKushrass: op = TOKushr; break;
 200:         case TOKcatass: op = TOKcat; break;
 201:         case TOKpowass: op = TOKpow; break;
 202:     }
 203:     Expression *e = new StringExp(0, (char *)Token::toChars(op));
warning C6211: Leaking memory 'e' due to an exception. Consider using a local catch block to clean up memory: Lines: 187, 189, 203, 204, 205
204: e = e->semantic(sc); 205: Objects *targsi = new Objects(); 206: targsi->push(e); 207: return targsi; 208: } 209: 210: /************************************ 211: * Operator overload. 212: * Check for operator overload, if so, replace 213: * with function call. 214: * Return NULL if not an operator overload. 215: */ 216: 217: Expression *UnaExp::op_overload(Scope *sc) 218: { 219: //printf("UnaExp::op_overload() (%s)\n", toChars()); 220: 221: #if DMDV2 222: if (e1->op == TOKarray) 223: { 224: ArrayExp *ae = (ArrayExp *)e1; 225: ae->e1 = ae->e1->semantic(sc); 226: ae->e1 = resolveProperties(sc, ae->e1); 227: 228: AggregateDeclaration *ad = isAggregate(ae->e1->type); 229: if (ad) 230: { 231: /* Rewrite as: 232: * a.opIndexUnary!("+")(args); 233: */ 234: Dsymbol *fd = search_function(ad, Id::opIndexUnary); 235: if (fd) 236: { 237: Objects *targsi = opToArg(sc, op); 238: Expression *e = new DotTemplateInstanceExp(loc, ae->e1, fd->ident, targsi); 239: e = new CallExp(loc, e, ae->arguments); 240: e = e->semantic(sc); 241: return e; 242: } 243: 244: // Didn't find it. Forward to aliasthis 245: if (ad->aliasthis) 246: { 247: /* Rewrite op(a[arguments]) as: 248: * op(a.aliasthis[arguments]) 249: */ 250: Expression *e1 = ae->copy(); 251: ((ArrayExp *)e1)->e1 = new DotIdExp(loc, ae->e1, ad->aliasthis->ident); 252: Expression *e = copy(); 253: ((UnaExp *)e)->e1 = e1; 254: e = e->trySemantic(sc); 255: return e; 256: } 257: } 258: } 259: else if (e1->op == TOKslice) 260: { 261: SliceExp *se = (SliceExp *)e1; 262: se->e1 = se->e1->semantic(sc); 263: se->e1 = resolveProperties(sc, se->e1); 264: 265: AggregateDeclaration *ad = isAggregate(se->e1->type); 266: if (ad) 267: { 268: /* Rewrite as: 269: * a.opSliceUnary!("+")(lwr, upr); 270: */ 271: Dsymbol *fd = search_function(ad, Id::opSliceUnary); 272: if (fd) 273: { 274: Expressions *a = new Expressions(); 275: if (se->lwr) 276: { a->push(se->lwr); 277: a->push(se->upr); 278: } 279: 280: Objects *targsi = opToArg(sc, op); 281: Expression *e = new DotTemplateInstanceExp(loc, se->e1, fd->ident, targsi); 282: e = new CallExp(loc, e, a); 283: e = e->semantic(sc); 284: return e; 285: } 286: 287: // Didn't find it. Forward to aliasthis 288: if (ad->aliasthis) 289: { 290: /* Rewrite op(a[lwr..upr]) as: 291: * op(a.aliasthis[lwr..upr]) 292: */ 293: Expression *e1 = se->copy(); 294: ((SliceExp *)e1)->e1 = new DotIdExp(loc, se->e1, ad->aliasthis->ident); 295: Expression *e = copy(); 296: ((UnaExp *)e)->e1 = e1; 297: e = e->trySemantic(sc); 298: return e; 299: } 300: } 301: } 302: #endif 303: 304: e1 = e1->semantic(sc); 305: e1 = resolveProperties(sc, e1); 306: 307: AggregateDeclaration *ad = isAggregate(e1->type); 308: if (ad) 309: { 310: Dsymbol *fd = NULL; 311: #if 1 // Old way, kept for compatibility with D1 312: if (op != TOKpreplusplus && op != TOKpreminusminus) 313: { fd = search_function(ad, opId()); 314: if (fd) 315: { 316: if (op == TOKarray) 317: { 318: /* Rewrite op e1[arguments] as: 319: * e1.fd(arguments) 320: */ 321: Expression *e = new DotIdExp(loc, e1, fd->ident); 322: ArrayExp *ae = (ArrayExp *)this; 323: e = new CallExp(loc, e, ae->arguments); 324: e = e->semantic(sc); 325: return e; 326: } 327: else 328: { 329: // Rewrite +e1 as e1.add() 330: return build_overload(loc, sc, e1, NULL, fd); 331: } 332: } 333: } 334: #endif 335: 336: #if DMDV2 337: /* Rewrite as: 338: * e1.opUnary!("+")(); 339: */ 340: fd = search_function(ad, Id::opUnary); 341: if (fd) 342: { 343: Objects *targsi = opToArg(sc, op); 344: Expression *e = new DotTemplateInstanceExp(loc, e1, fd->ident, targsi); 345: e = new CallExp(loc, e); 346: e = e->semantic(sc); 347: return e; 348: } 349: 350: // Didn't find it. Forward to aliasthis 351: if (ad->aliasthis) 352: { 353: /* Rewrite op(e1) as: 354: * op(e1.aliasthis) 355: */ 356: Expression *e1 = new DotIdExp(loc, this->e1, ad->aliasthis->ident); 357: Expression *e = copy(); 358: ((UnaExp *)e)->e1 = e1; 359: e = e->trySemantic(sc); 360: return e; 361: } 362: #endif 363: } 364: return NULL; 365: } 366: 367: Expression *ArrayExp::op_overload(Scope *sc) 368: { 369: //printf("ArrayExp::op_overload() (%s)\n", toChars()); 370: AggregateDeclaration *ad = isAggregate(e1->type); 371: if (ad) 372: { 373: Dsymbol *fd = search_function(ad, opId()); 374: if (fd) 375: { 376: /* Rewrite op e1[arguments] as: 377: * e1.opIndex(arguments) 378: */ 379: Expression *e = new DotIdExp(loc, e1, fd->ident); 380: e = new CallExp(loc, e, arguments); 381: e = e->semantic(sc); 382: return e; 383: } 384: 385: // Didn't find it. Forward to aliasthis 386: if (ad->aliasthis) 387: { 388: /* Rewrite op(e1) as: 389: * op(e1.aliasthis) 390: */ 391: Expression *e1 = new DotIdExp(loc, this->e1, ad->aliasthis->ident); 392: Expression *e = copy(); 393: ((UnaExp *)e)->e1 = e1; 394: e = e->trySemantic(sc); 395: return e; 396: } 397: } 398: return NULL; 399: } 400: 401: /*********************************************** 402: * This is mostly the same as UnaryExp::op_overload(), but has 403: * a different rewrite. 404: */ 405: Expression *CastExp::op_overload(Scope *sc) 406: { 407: //printf("CastExp::op_overload() (%s)\n", toChars()); 408: AggregateDeclaration *ad = isAggregate(e1->type); 409: if (ad) 410: { 411: Dsymbol *fd = NULL; 412: /* Rewrite as: 413: * e1.opCast!(T)(); 414: */ 415: fd = search_function(ad, Id::cast); 416: if (fd) 417: { 418: #if 1 // Backwards compatibility with D1 if opCast is a function, not a template 419: if (fd->isFuncDeclaration()) 420: { // Rewrite as: e1.opCast() 421: return build_overload(loc, sc, e1, NULL, fd); 422: } 423: #endif 424: Objects *targsi = new Objects(); 425: targsi->push(to); 426: Expression *e = new DotTemplateInstanceExp(loc, e1, fd->ident, targsi); 427: e = new CallExp(loc, e); 428: e = e->semantic(sc); 429: return e; 430: } 431: 432: // Didn't find it. Forward to aliasthis 433: if (ad->aliasthis) 434: { 435: /* Rewrite op(e1) as: 436: * op(e1.aliasthis) 437: */ 438: Expression *e1 = new DotIdExp(loc, this->e1, ad->aliasthis->ident); 439: Expression *e = copy(); 440: ((UnaExp *)e)->e1 = e1; 441: e = e->trySemantic(sc); 442: return e; 443: } 444: } 445: return NULL; 446: } 447: 448: Expression *BinExp::op_overload(Scope *sc) 449: { 450: //printf("BinExp::op_overload() (%s)\n", toChars()); 451: 452: Identifier *id = opId(); 453: Identifier *id_r = opId_r(); 454: 455: Expressions args1; 456: Expressions args2; 457: int argsset = 0; 458: 459: AggregateDeclaration *ad1 = isAggregate(e1->type); 460: AggregateDeclaration *ad2 = isAggregate(e2->type); 461: 462: Dsymbol *s = NULL; 463: Dsymbol *s_r = NULL; 464: 465: #if 1 // the old D1 scheme 466: if (ad1 && id) 467: { 468: s = search_function(ad1, id); 469: } 470: if (ad2 && id_r) 471: { 472: s_r = search_function(ad2, id_r); 473: } 474: #endif 475: 476: Objects *targsi = NULL; 477: #if DMDV2 478: if (!s && !s_r && op != TOKequal && op != TOKnotequal && op != TOKassign && 479: op != TOKplusplus && op != TOKminusminus) 480: { 481: /* Try the new D2 scheme, opBinary and opBinaryRight 482: */ 483: if (ad1) 484: s = search_function(ad1, Id::opBinary); 485: if (ad2) 486: s_r = search_function(ad2, Id::opBinaryRight); 487: 488: // Set targsi, the template argument list, which will be the operator string 489: if (s || s_r) 490: { 491: id = Id::opBinary; 492: id_r = Id::opBinaryRight; 493: targsi = opToArg(sc, op); 494: } 495: } 496: #endif 497: 498: if (s || s_r) 499: { 500: /* Try: 501: * a.opfunc(b) 502: * b.opfunc_r(a) 503: * and see which is better. 504: */ 505: 506: args1.setDim(1); 507: args1.tdata()[0] = e1; 508: args2.setDim(1); 509: args2.tdata()[0] = e2; 510: argsset = 1; 511: 512: Match m; 513: memset(&m, 0, sizeof(m)); 514: m.last = MATCHnomatch; 515: 516: if (s) 517: { 518: FuncDeclaration *fd = s->isFuncDeclaration(); 519: if (fd) 520: { 521: overloadResolveX(&m, fd, NULL, &args2); 522: } 523: else 524: { TemplateDeclaration *td = s->isTemplateDeclaration(); 525: templateResolve(&m, td, sc, loc, targsi, e1, &args2); 526: } 527: } 528: 529: FuncDeclaration *lastf = m.lastf; 530: 531: if (s_r) 532: { 533: FuncDeclaration *fd = s_r->isFuncDeclaration(); 534: if (fd) 535: { 536: overloadResolveX(&m, fd, NULL, &args1); 537: } 538: else 539: { TemplateDeclaration *td = s_r->isTemplateDeclaration(); 540: templateResolve(&m, td, sc, loc, targsi, e2, &args1); 541: } 542: } 543: 544: if (m.count > 1) 545: { 546: // Error, ambiguous 547: error("overloads %s and %s both match argument list for %s", 548: m.lastf->type->toChars(), 549: m.nextf->type->toChars(), 550: m.lastf->toChars()); 551: } 552: else if (m.last == MATCHnomatch) 553: { 554: m.lastf = m.anyf; 555: if (targsi) 556: goto L1; 557: } 558: 559: Expression *e; 560: if (op == TOKplusplus || op == TOKminusminus) 561: // Kludge because operator overloading regards e++ and e-- 562: // as unary, but it's implemented as a binary. 563: // Rewrite (e1 ++ e2) as e1.postinc() 564: // Rewrite (e1 -- e2) as e1.postdec() 565: e = build_overload(loc, sc, e1, NULL, m.lastf ? m.lastf : s); 566: else if (lastf && m.lastf == lastf || !s_r && m.last == MATCHnomatch) 567: // Rewrite (e1 op e2) as e1.opfunc(e2) 568: e = build_overload(loc, sc, e1, e2, m.lastf ? m.lastf : s); 569: else 570: // Rewrite (e1 op e2) as e2.opfunc_r(e1) 571: e = build_overload(loc, sc, e2, e1, m.lastf ? m.lastf : s_r); 572: return e; 573: } 574: 575: L1: 576: #if 1 // Retained for D1 compatibility 577: if (isCommutative() && !targsi) 578: { 579: s = NULL; 580: s_r = NULL; 581: if (ad1 && id_r) 582: { 583: s_r = search_function(ad1, id_r); 584: } 585: if (ad2 && id) 586: { 587: s = search_function(ad2, id); 588: } 589: 590: if (s || s_r) 591: { 592: /* Try: 593: * a.opfunc_r(b) 594: * b.opfunc(a) 595: * and see which is better. 596: */ 597: 598: if (!argsset) 599: { args1.setDim(1); 600: args1.tdata()[0] = e1; 601: args2.setDim(1); 602: args2.tdata()[0] = e2; 603: } 604: 605: Match m; 606: memset(&m, 0, sizeof(m)); 607: m.last = MATCHnomatch; 608: 609: if (s_r) 610: { 611: FuncDeclaration *fd = s_r->isFuncDeclaration(); 612: if (fd) 613: { 614: overloadResolveX(&m, fd, NULL, &args2); 615: } 616: else 617: { TemplateDeclaration *td = s_r->isTemplateDeclaration(); 618: templateResolve(&m, td, sc, loc, targsi, e1, &args2); 619: } 620: } 621: FuncDeclaration *lastf = m.lastf; 622: 623: if (s) 624: { 625: FuncDeclaration *fd = s->isFuncDeclaration(); 626: if (fd) 627: { 628: overloadResolveX(&m, fd, NULL, &args1); 629: } 630: else 631: { TemplateDeclaration *td = s->isTemplateDeclaration(); 632: templateResolve(&m, td, sc, loc, targsi, e2, &args1); 633: } 634: } 635: 636: if (m.count > 1) 637: { 638: // Error, ambiguous 639: error("overloads %s and %s both match argument list for %s", 640: m.lastf->type->toChars(), 641: m.nextf->type->toChars(), 642: m.lastf->toChars()); 643: } 644: else if (m.last == MATCHnomatch) 645: { 646: m.lastf = m.anyf; 647: } 648: 649: Expression *e; 650: if (lastf && m.lastf == lastf || !s && m.last == MATCHnomatch) 651: // Rewrite (e1 op e2) as e1.opfunc_r(e2) 652: e = build_overload(loc, sc, e1, e2, m.lastf ? m.lastf : s_r); 653: else 654: // Rewrite (e1 op e2) as e2.opfunc(e1) 655: e = build_overload(loc, sc, e2, e1, m.lastf ? m.lastf : s); 656: 657: // When reversing operands of comparison operators, 658: // need to reverse the sense of the op 659: switch (op) 660: { 661: case TOKlt: op = TOKgt; break; 662: case TOKgt: op = TOKlt; break; 663: case TOKle: op = TOKge; break; 664: case TOKge: op = TOKle; break; 665: 666: // Floating point compares 667: case TOKule: op = TOKuge; break; 668: case TOKul: op = TOKug; break; 669: case TOKuge: op = TOKule; break; 670: case TOKug: op = TOKul; break; 671: 672: // These are symmetric 673: case TOKunord: 674: case TOKlg: 675: case TOKleg: 676: case TOKue: 677: break; 678: } 679: 680: return e; 681: } 682: } 683: #endif 684: 685: #if DMDV2 686: // Try alias this on first operand 687: if (ad1 && ad1->aliasthis && 688: !(op == TOKassign && ad2 && ad1 == ad2)) // See Bugzilla 2943 689: { 690: /* Rewrite (e1 op e2) as: 691: * (e1.aliasthis op e2) 692: */ 693: Expression *e1 = new DotIdExp(loc, this->e1, ad1->aliasthis->ident); 694: Expression *e = copy(); 695: ((BinExp *)e)->e1 = e1; 696: e = e->trySemantic(sc); 697: return e; 698: } 699: 700: // Try alias this on second operand 701: if (ad2 && ad2->aliasthis && 702: /* Bugzilla 2943: make sure that when we're copying the struct, we don't 703: * just copy the alias this member 704: */ 705: !(op == TOKassign && ad1 && ad1 == ad2)) 706: { 707: /* Rewrite (e1 op e2) as: 708: * (e1 op e2.aliasthis) 709: */ 710: Expression *e2 = new DotIdExp(loc, this->e2, ad2->aliasthis->ident); 711: Expression *e = copy(); 712: ((BinExp *)e)->e2 = e2; 713: e = e->trySemantic(sc); 714: return e; 715: } 716: #endif 717: return NULL; 718: } 719: 720: /****************************************** 721: * Common code for overloading of EqualExp and CmpExp 722: */ 723: Expression *BinExp::compare_overload(Scope *sc, Identifier *id) 724: { 725: //printf("BinExp::compare_overload(id = %s) %s\n", id->toChars(), toChars()); 726: 727: AggregateDeclaration *ad1 = isAggregate(e1->type); 728: AggregateDeclaration *ad2 = isAggregate(e2->type); 729: 730: Dsymbol *s = NULL; 731: Dsymbol *s_r = NULL; 732: 733: if (ad1) 734: { 735: s = search_function(ad1, id); 736: } 737: if (ad2) 738: { 739: s_r = search_function(ad2, id); 740: if (s == s_r) 741: s_r = NULL; 742: } 743: 744: Objects *targsi = NULL; 745: 746: if (s || s_r) 747: { 748: /* Try: 749: * a.opEquals(b) 750: * b.opEquals(a) 751: * and see which is better. 752: */ 753: 754: Expressions args1; 755: Expressions args2; 756: 757: args1.setDim(1); 758: args1.tdata()[0] = e1; 759: args2.setDim(1); 760: args2.tdata()[0] = e2; 761: 762: Match m; 763: memset(&m, 0, sizeof(m)); 764: m.last = MATCHnomatch; 765: 766: if (0 && s && s_r) 767: { 768: printf("s : %s\n", s->toPrettyChars()); 769: printf("s_r: %s\n", s_r->toPrettyChars()); 770: } 771: 772: if (s) 773: { 774: FuncDeclaration *fd = s->isFuncDeclaration(); 775: if (fd) 776: { 777: overloadResolveX(&m, fd, NULL, &args2); 778: } 779: else 780: { TemplateDeclaration *td = s->isTemplateDeclaration(); 781: templateResolve(&m, td, sc, loc, targsi, NULL, &args2); 782: } 783: } 784: 785: FuncDeclaration *lastf = m.lastf; 786: int count = m.count; 787: 788: if (s_r) 789: { 790: FuncDeclaration *fd = s_r->isFuncDeclaration(); 791: if (fd) 792: { 793: overloadResolveX(&m, fd, NULL, &args1); 794: } 795: else 796: { TemplateDeclaration *td = s_r->isTemplateDeclaration(); 797: templateResolve(&m, td, sc, loc, targsi, NULL, &args1); 798: } 799: } 800: 801: if (m.count > 1) 802: { 803: /* The following if says "not ambiguous" if there's one match 804: * from s and one from s_r, in which case we pick s. 805: * This doesn't follow the spec, but is a workaround for the case 806: * where opEquals was generated from templates and we cannot figure 807: * out if both s and s_r came from the same declaration or not. 808: * The test case is: 809: * import std.typecons; 810: * void main() { 811: * assert(tuple("has a", 2u) == tuple("has a", 1)); 812: * } 813: */ 814: if (!(m.lastf == lastf && m.count == 2 && count == 1)) 815: { 816: // Error, ambiguous 817: error("overloads %s and %s both match argument list for %s", 818: m.lastf->type->toChars(), 819: m.nextf->type->toChars(), 820: m.lastf->toChars()); 821: } 822: } 823: else if (m.last == MATCHnomatch) 824: { 825: m.lastf = m.anyf; 826: } 827: 828: Expression *e; 829: if (lastf && m.lastf == lastf || !s_r && m.last == MATCHnomatch) 830: // Rewrite (e1 op e2) as e1.opfunc(e2) 831: e = build_overload(loc, sc, e1, e2, m.lastf ? m.lastf : s); 832: else 833: { // Rewrite (e1 op e2) as e2.opfunc_r(e1) 834: e = build_overload(loc, sc, e2, e1, m.lastf ? m.lastf : s_r); 835: 836: // When reversing operands of comparison operators, 837: // need to reverse the sense of the op 838: switch (op) 839: { 840: case TOKlt: op = TOKgt; break; 841: case TOKgt: op = TOKlt; break; 842: case TOKle: op = TOKge; break; 843: case TOKge: op = TOKle; break; 844: 845: // Floating point compares 846: case TOKule: op = TOKuge; break; 847: case TOKul: op = TOKug; break; 848: case TOKuge: op = TOKule; break; 849: case TOKug: op = TOKul; break; 850: 851: // The rest are symmetric 852: default: 853: break; 854: } 855: } 856: 857: return e; 858: } 859: 860: // Try alias this on first operand 861: if (ad1 && ad1->aliasthis) 862: { 863: /* Rewrite (e1 op e2) as: 864: * (e1.aliasthis op e2) 865: */ 866: Expression *e1 = new DotIdExp(loc, this->e1, ad1->aliasthis->ident); 867: Expression *e = copy(); 868: ((BinExp *)e)->e1 = e1; 869: e = e->trySemantic(sc); 870: return e; 871: } 872: 873: // Try alias this on second operand 874: if (ad2 && ad2->aliasthis) 875: { 876: /* Rewrite (e1 op e2) as: 877: * (e1 op e2.aliasthis) 878: */ 879: Expression *e2 = new DotIdExp(loc, this->e2, ad2->aliasthis->ident); 880: Expression *e = copy(); 881: ((BinExp *)e)->e2 = e2; 882: e = e->trySemantic(sc); 883: return e; 884: } 885: 886: return NULL; 887: } 888: 889: Expression *EqualExp::op_overload(Scope *sc) 890: { 891: //printf("EqualExp::op_overload() (%s)\n", toChars()); 892: 893: Type *t1 = e1->type->toBasetype(); 894: Type *t2 = e2->type->toBasetype(); 895: if (t1->ty == Tclass && t2->ty == Tclass) 896: { 897: /* Rewrite as: 898: * .object.opEquals(e1, e2) 899: */ 900: Expression *e = new IdentifierExp(loc, Id::empty); 901: e = new DotIdExp(loc, e, Id::object); 902: e = new DotIdExp(loc, e, Id::eq); 903: e = new CallExp(loc, e, e1, e2); 904: e = e->semantic(sc); 905: return e; 906: } 907: 908: return compare_overload(sc, Id::eq); 909: } 910: 911: Expression *CmpExp::op_overload(Scope *sc) 912: { 913: //printf("CmpExp::op_overload() (%s)\n", toChars()); 914: 915: return compare_overload(sc, Id::cmp); 916: } 917: 918: /********************************* 919: * Operator overloading for op= 920: */ 921: Expression *BinAssignExp::op_overload(Scope *sc) 922: { 923: //printf("BinAssignExp::op_overload() (%s)\n", toChars()); 924: 925: #if DMDV2 926: if (e1->op == TOKarray) 927: { 928: ArrayExp *ae = (ArrayExp *)e1; 929: ae->e1 = ae->e1->semantic(sc); 930: ae->e1 = resolveProperties(sc, ae->e1); 931: 932: AggregateDeclaration *ad = isAggregate(ae->e1->type); 933: if (ad) 934: { 935: /* Rewrite a[args]+=e2 as: 936: * a.opIndexOpAssign!("+")(e2, args); 937: */ 938: Dsymbol *fd = search_function(ad, Id::opIndexOpAssign); 939: if (fd) 940: { 941: Expressions *a = new Expressions();
warning C6211: Leaking memory 'a' due to an exception. Consider using a local catch block to clean up memory: Lines: 926, 928, 929, 930, 932, 933, 938, 939, 941, 942, 943, 946, 947
942: a->push(e2); 943: for (int i = 0; i < ae->arguments->dim; i++)
warning C4018: '<' : signed/unsigned mismatch
944: a->push(ae->arguments->tdata()[i]); 945: 946: Objects *targsi = opToArg(sc, op); 947: Expression *e = new DotTemplateInstanceExp(loc, ae->e1, fd->ident, targsi); 948: e = new CallExp(loc, e, a); 949: e = e->semantic(sc); 950: return e; 951: } 952: 953: // Didn't find it. Forward to aliasthis 954: if (ad->aliasthis) 955: { 956: /* Rewrite a[arguments] op= e2 as: 957: * a.aliasthis[arguments] op= e2 958: */ 959: Expression *e1 = ae->copy(); 960: ((ArrayExp *)e1)->e1 = new DotIdExp(loc, ae->e1, ad->aliasthis->ident); 961: Expression *e = copy(); 962: ((UnaExp *)e)->e1 = e1; 963: e = e->trySemantic(sc); 964: return e; 965: } 966: } 967: } 968: else if (e1->op == TOKslice) 969: { 970: SliceExp *se = (SliceExp *)e1; 971: se->e1 = se->e1->semantic(sc); 972: se->e1 = resolveProperties(sc, se->e1); 973: 974: AggregateDeclaration *ad = isAggregate(se->e1->type); 975: if (ad) 976: { 977: /* Rewrite a[lwr..upr]+=e2 as: 978: * a.opSliceOpAssign!("+")(e2, lwr, upr); 979: */ 980: Dsymbol *fd = search_function(ad, Id::opSliceOpAssign); 981: if (fd) 982: { 983: Expressions *a = new Expressions(); 984: a->push(e2); 985: if (se->lwr) 986: { a->push(se->lwr); 987: a->push(se->upr); 988: } 989: 990: Objects *targsi = opToArg(sc, op); 991: Expression *e = new DotTemplateInstanceExp(loc, se->e1, fd->ident, targsi); 992: e = new CallExp(loc, e, a); 993: e = e->semantic(sc); 994: return e; 995: } 996: 997: // Didn't find it. Forward to aliasthis 998: if (ad->aliasthis) 999: { 1000: /* Rewrite a[lwr..upr] op= e2 as: 1001: * a.aliasthis[lwr..upr] op= e2 1002: */ 1003: Expression *e1 = se->copy(); 1004: ((SliceExp *)e1)->e1 = new DotIdExp(loc, se->e1, ad->aliasthis->ident); 1005: Expression *e = copy(); 1006: ((UnaExp *)e)->e1 = e1; 1007: e = e->trySemantic(sc); 1008: return e; 1009: } 1010: } 1011: } 1012: #endif 1013: 1014: BinExp::semantic(sc); 1015: e1 = resolveProperties(sc, e1); 1016: e2 = resolveProperties(sc, e2); 1017: 1018: Identifier *id = opId(); 1019: 1020: Expressions args2; 1021: 1022: AggregateDeclaration *ad1 = isAggregate(e1->type); 1023: 1024: Dsymbol *s = NULL; 1025: 1026: #if 1 // the old D1 scheme 1027: if (ad1 && id) 1028: { 1029: s = search_function(ad1, id); 1030: } 1031: #endif 1032: 1033: Objects *targsi = NULL; 1034: #if DMDV2 1035: if (!s) 1036: { /* Try the new D2 scheme, opOpAssign 1037: */ 1038: if (ad1) 1039: s = search_function(ad1, Id::opOpAssign); 1040: 1041: // Set targsi, the template argument list, which will be the operator string 1042: if (s) 1043: { 1044: id = Id::opOpAssign; 1045: targsi = opToArg(sc, op); 1046: } 1047: } 1048: #endif 1049: 1050: if (s) 1051: { 1052: /* Try: 1053: * a.opOpAssign(b) 1054: */ 1055: 1056: args2.setDim(1); 1057: args2.tdata()[0] = e2; 1058: 1059: Match m; 1060: memset(&m, 0, sizeof(m)); 1061: m.last = MATCHnomatch; 1062: 1063: if (s) 1064: { 1065: FuncDeclaration *fd = s->isFuncDeclaration(); 1066: if (fd) 1067: { 1068: overloadResolveX(&m, fd, NULL, &args2); 1069: } 1070: else 1071: { TemplateDeclaration *td = s->isTemplateDeclaration(); 1072: templateResolve(&m, td, sc, loc, targsi, e1, &args2); 1073: } 1074: } 1075: 1076: if (m.count > 1) 1077: { 1078: // Error, ambiguous 1079: error("overloads %s and %s both match argument list for %s", 1080: m.lastf->type->toChars(), 1081: m.nextf->type->toChars(), 1082: m.lastf->toChars()); 1083: } 1084: else if (m.last == MATCHnomatch) 1085: { 1086: m.lastf = m.anyf; 1087: if (targsi) 1088: goto L1; 1089: } 1090: 1091: // Rewrite (e1 op e2) as e1.opOpAssign(e2) 1092: return build_overload(loc, sc, e1, e2, m.lastf ? m.lastf : s); 1093: } 1094: 1095: L1: 1096: 1097: #if DMDV2 1098: // Try alias this on first operand 1099: if (ad1 && ad1->aliasthis) 1100: { 1101: /* Rewrite (e1 op e2) as: 1102: * (e1.aliasthis op e2) 1103: */ 1104: Expression *e1 = new DotIdExp(loc, this->e1, ad1->aliasthis->ident); 1105: Expression *e = copy(); 1106: ((BinExp *)e)->e1 = e1; 1107: e = e->trySemantic(sc); 1108: return e; 1109: } 1110: 1111: // Try alias this on second operand 1112: AggregateDeclaration *ad2 = isAggregate(e2->type); 1113: if (ad2 && ad2->aliasthis) 1114: { 1115: /* Rewrite (e1 op e2) as: 1116: * (e1 op e2.aliasthis) 1117: */ 1118: Expression *e2 = new DotIdExp(loc, this->e2, ad2->aliasthis->ident); 1119: Expression *e = copy(); 1120: ((BinExp *)e)->e2 = e2; 1121: e = e->trySemantic(sc); 1122: return e; 1123: } 1124: #endif 1125: return NULL; 1126: } 1127: 1128: /*********************************** 1129: * Utility to build a function call out of this reference and argument. 1130: */ 1131: 1132: Expression *build_overload(Loc loc, Scope *sc, Expression *ethis, Expression *earg, 1133: Dsymbol *d) 1134: { 1135: assert(d); 1136: Expression *e; 1137: 1138: //printf("build_overload(id = '%s')\n", id->toChars()); 1139: //earg->print(); 1140: //earg->type->print(); 1141: Declaration *decl = d->isDeclaration(); 1142: if (decl) 1143: e = new DotVarExp(loc, ethis, decl, 0); 1144: else 1145: e = new DotIdExp(loc, ethis, d->ident); 1146: e = new CallExp(loc, e, earg); 1147: 1148: e = e->semantic(sc); 1149: return e; 1150: } 1151: 1152: /*************************************** 1153: * Search for function funcid in aggregate ad. 1154: */ 1155: 1156: Dsymbol *search_function(ScopeDsymbol *ad, Identifier *funcid) 1157: { 1158: Dsymbol *s; 1159: FuncDeclaration *fd; 1160: TemplateDeclaration *td; 1161: 1162: s = ad->search(0, funcid, 0); 1163: if (s) 1164: { Dsymbol *s2; 1165: 1166: //printf("search_function: s = '%s'\n", s->kind()); 1167: s2 = s->toAlias(); 1168: //printf("search_function: s2 = '%s'\n", s2->kind()); 1169: fd = s2->isFuncDeclaration(); 1170: if (fd && fd->type->ty == Tfunction) 1171: return fd; 1172: 1173: td = s2->isTemplateDeclaration(); 1174: if (td) 1175: return td; 1176: } 1177: return NULL; 1178: } 1179: 1180: 1181: /***************************************** 1182: * Given array of arguments and an aggregate type, 1183: * if any of the argument types are missing, attempt to infer 1184: * them from the aggregate type. 1185: */ 1186: 1187: void inferApplyArgTypes(enum TOK op, Parameters *arguments, Expression *aggr) 1188: { 1189: if (!arguments || !arguments->dim) 1190: return; 1191: 1192: /* Return if no arguments need types. 1193: */ 1194: for (size_t u = 0; 1; u++) 1195: { if (u == arguments->dim) 1196: return; 1197: Parameter *arg = arguments->tdata()[u]; 1198: if (!arg->type) 1199: break; 1200: } 1201: 1202: Dsymbol *s; 1203: AggregateDeclaration *ad; 1204: 1205: Parameter *arg = arguments->tdata()[0]; 1206: Type *taggr = aggr->type; 1207: if (!taggr) 1208: return; 1209: Type *tab = taggr->toBasetype(); 1210: switch (tab->ty) 1211: { 1212: case Tarray: 1213: case Tsarray: 1214: case Ttuple: 1215: if (arguments->dim == 2) 1216: { 1217: if (!arg->type) 1218: arg->type = Type::tsize_t; // key type 1219: arg = arguments->tdata()[1]; 1220: } 1221: if (!arg->type && tab->ty != Ttuple) 1222: arg->type = tab->nextOf(); // value type 1223: break; 1224: 1225: case Taarray: 1226: { TypeAArray *taa = (TypeAArray *)tab; 1227: 1228: if (arguments->dim == 2) 1229: { 1230: if (!arg->type) 1231: arg->type = taa->index; // key type 1232: arg = arguments->tdata()[1]; 1233: } 1234: if (!arg->type) 1235: arg->type = taa->next; // value type 1236: break; 1237: } 1238: 1239: case Tclass: 1240: ad = ((TypeClass *)tab)->sym; 1241: goto Laggr; 1242: 1243: case Tstruct: 1244: ad = ((TypeStruct *)tab)->sym; 1245: goto Laggr; 1246: 1247: Laggr: 1248: s = search_function(ad, 1249: (op == TOKforeach_reverse) ? Id::applyReverse 1250: : Id::apply); 1251: if (s) 1252: goto Lapply; // prefer opApply 1253: 1254: if (arguments->dim == 1) 1255: { 1256: if (!arg->type) 1257: { 1258: /* Look for a head() or rear() overload 1259: */ 1260: Identifier *id = (op == TOKforeach) ? Id::Fhead : Id::Ftoe; 1261: Dsymbol *s = search_function(ad, id);
warning C6246: Local declaration of 's' hides declaration of the same name in outer scope. For additional information, see previous declaration at line '1202' of 'c:\projects\extern\d\dmd\src\opover.c': Lines: 1202
1262: FuncDeclaration *fd = s ? s->isFuncDeclaration() : NULL; 1263: if (!fd) 1264: { if (s && s->isTemplateDeclaration()) 1265: break; 1266: goto Lapply; 1267: } 1268: arg->type = fd->type->nextOf(); 1269: } 1270: break; 1271: } 1272: 1273: Lapply: 1274: { /* Look for an 1275: * int opApply(int delegate(ref Type [, ...]) dg); 1276: * overload 1277: */ 1278: if (s) 1279: { 1280: FuncDeclaration *fd = s->isFuncDeclaration(); 1281: if (fd) 1282: { inferApplyArgTypesX(fd, arguments); 1283: break; 1284: } 1285: #if 0 1286: TemplateDeclaration *td = s->isTemplateDeclaration(); 1287: if (td) 1288: { inferApplyArgTypesZ(td, arguments); 1289: break; 1290: } 1291: #endif 1292: } 1293: break; 1294: } 1295: 1296: case Tdelegate: 1297: { 1298: if (0 && aggr->op == TOKdelegate) 1299: { DelegateExp *de = (DelegateExp *)aggr; 1300: 1301: FuncDeclaration *fd = de->func->isFuncDeclaration(); 1302: if (fd) 1303: inferApplyArgTypesX(fd, arguments); 1304: } 1305: else 1306: { 1307: inferApplyArgTypesY((TypeFunction *)tab->nextOf(), arguments); 1308: } 1309: break; 1310: } 1311: 1312: default: 1313: break; // ignore error, caught later 1314: } 1315: } 1316: 1317: /******************************** 1318: * Recursive helper function, 1319: * analogous to func.overloadResolveX(). 1320: */ 1321: 1322: int fp3(void *param, FuncDeclaration *f) 1323: { 1324: Parameters *arguments = (Parameters *)param; 1325: TypeFunction *tf = (TypeFunction *)f->type; 1326: if (inferApplyArgTypesY(tf, arguments) == 1) 1327: return 0; 1328: if (arguments->dim == 0) 1329: return 1; 1330: return 0; 1331: } 1332: 1333: static void inferApplyArgTypesX(FuncDeclaration *fstart, Parameters *arguments) 1334: { 1335: overloadApply(fstart, &fp3, arguments); 1336: } 1337: 1338: /****************************** 1339: * Infer arguments from type of function. 1340: * Returns: 1341: * 0 match for this function 1342: * 1 no match for this function 1343: */ 1344: 1345: static int inferApplyArgTypesY(TypeFunction *tf, Parameters *arguments) 1346: { size_t nparams; 1347: Parameter *p; 1348: 1349: if (Parameter::dim(tf->parameters) != 1) 1350: goto Lnomatch; 1351: p = Parameter::getNth(tf->parameters, 0); 1352: if (p->type->ty != Tdelegate) 1353: goto Lnomatch; 1354: tf = (TypeFunction *)p->type->nextOf(); 1355: assert(tf->ty == Tfunction); 1356: 1357: /* We now have tf, the type of the delegate. Match it against 1358: * the arguments, filling in missing argument types. 1359: */ 1360: nparams = Parameter::dim(tf->parameters); 1361: if (nparams == 0 || tf->varargs) 1362: goto Lnomatch; // not enough parameters 1363: if (arguments->dim != nparams) 1364: goto Lnomatch; // not enough parameters 1365: 1366: for (size_t u = 0; u < nparams; u++) 1367: { 1368: Parameter *arg = arguments->tdata()[u]; 1369: Parameter *param = Parameter::getNth(tf->parameters, u); 1370: if (arg->type) 1371: { if (!arg->type->equals(param->type)) 1372: { 1373: /* Cannot resolve argument types. Indicate an 1374: * error by setting the number of arguments to 0. 1375: */ 1376: arguments->dim = 0; 1377: goto Lmatch; 1378: } 1379: continue; 1380: } 1381: arg->type = param->type; 1382: } 1383: Lmatch: 1384: return 0; 1385: 1386: Lnomatch: 1387: return 1; 1388: } 1389: 1390: /******************************************* 1391: * Infer foreach arg types from a template function opApply which looks like: 1392: * int opApply(alias int func(ref uint))() { ... } 1393: */ 1394: 1395: #if 0 1396: void inferApplyArgTypesZ(TemplateDeclaration *tstart, Parameters *arguments) 1397: { 1398: for (TemplateDeclaration *td = tstart; td; td = td->overnext) 1399: { 1400: if (!td->scope) 1401: { 1402: error("forward reference to template %s", td->toChars()); 1403: return; 1404: } 1405: if (!td->onemember || !td->onemember->toAlias()->isFuncDeclaration()) 1406: { 1407: error("is not a function template"); 1408: return; 1409: } 1410: if (!td->parameters || td->parameters->dim != 1) 1411: continue; 1412: TemplateParameter *tp = td->parameters->tdata()[0]; 1413: TemplateAliasParameter *tap = tp->isTemplateAliasParameter(); 1414: if (!tap || !tap->specType || tap->specType->ty != Tfunction) 1415: continue; 1416: TypeFunction *tf = (TypeFunction *)tap->specType; 1417: if (inferApplyArgTypesY(tf, arguments) == 0) // found it 1418: return; 1419: } 1420: } 1421: #endif 1422: 1423: /************************************** 1424: */ 1425: 1426: static void templateResolve(Match *m, TemplateDeclaration *td, Scope *sc, Loc loc, Objects *targsi, Expression *ethis, Expressions *arguments) 1427: { 1428: FuncDeclaration *fd; 1429: 1430: assert(td); 1431: fd = td->deduceFunctionTemplate(sc, loc, targsi, ethis, arguments, 1); 1432: if (!fd) 1433: return; 1434: m->anyf = fd; 1435: if (m->last >= MATCHexact) 1436: { 1437: m->nextf = fd; 1438: m->count++; 1439: } 1440: else 1441: { 1442: m->last = MATCHexact; 1443: m->lastf = fd; 1444: m->count = 1; 1445: } 1446: } 1447: 1448: