1 /** 2 * Compiler implementation of the 3 * $(LINK2 http://www.dlang.org, D programming language). 4 * 5 * Copyright: Copyright (c) 1999-2016 by Digital Mars, All Rights Reserved 6 * Authors: $(LINK2 http://www.digitalmars.com, Walter Bright) 7 * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) 8 * Source: $(DMDSRC _dcast.d) 9 */ 10 11 module ddmd.dcast; 12 13 import core.stdc.stdio; 14 import core.stdc..string; 15 import ddmd.aggregate; 16 import ddmd.aliasthis; 17 import ddmd.arrayop; 18 import ddmd.arraytypes; 19 import ddmd.dclass; 20 import ddmd.declaration; 21 import ddmd.dscope; 22 import ddmd.dstruct; 23 import ddmd.dsymbol; 24 import ddmd.errors; 25 import ddmd.expression; 26 import ddmd.func; 27 import ddmd.globals; 28 import ddmd.impcnvtab; 29 import ddmd.init; 30 import ddmd.intrange; 31 import ddmd.mtype; 32 import ddmd.opover; 33 import ddmd.root.ctfloat; 34 import ddmd.root.outbuffer; 35 import ddmd.root.rmem; 36 import ddmd.tokens; 37 import ddmd.utf; 38 import ddmd.visitor; 39 40 enum LOG = false; 41 42 /************************************** 43 * Do an implicit cast. 44 * Issue error if it can't be done. 45 */ 46 extern (C++) Expression implicitCastTo(Expression e, Scope* sc, Type t) 47 { 48 extern (C++) final class ImplicitCastTo : Visitor 49 { 50 alias visit = super.visit; 51 public: 52 Type t; 53 Scope* sc; 54 Expression result; 55 56 extern (D) this(Scope* sc, Type t) 57 { 58 this.sc = sc; 59 this.t = t; 60 } 61 62 override void visit(Expression e) 63 { 64 //printf("Expression.implicitCastTo(%s of type %s) => %s\n", e.toChars(), e.type.toChars(), t.toChars()); 65 66 MATCH match = e.implicitConvTo(t); 67 if (match) 68 { 69 if (match == MATCHconst && (e.type.constConv(t) || !e.isLvalue() && e.type.equivalent(t))) 70 { 71 /* Do not emit CastExp for const conversions and 72 * unique conversions on rvalue. 73 */ 74 result = e.copy(); 75 result.type = t; 76 return; 77 } 78 result = e.castTo(sc, t); 79 return; 80 } 81 82 result = e.optimize(WANTvalue); 83 if (result != e) 84 { 85 result.accept(this); 86 return; 87 } 88 89 if (t.ty != Terror && e.type.ty != Terror) 90 { 91 if (!t.deco) 92 { 93 e.error("forward reference to type %s", t.toChars()); 94 } 95 else 96 { 97 //printf("type %p ty %d deco %p\n", type, type.ty, type.deco); 98 //type = type.semantic(loc, sc); 99 //printf("type %s t %s\n", type.deco, t.deco); 100 e.error("cannot implicitly convert expression (%s) of type %s to %s", 101 e.toChars(), e.type.toChars(), t.toChars()); 102 } 103 } 104 result = new ErrorExp(); 105 } 106 107 override void visit(StringExp e) 108 { 109 //printf("StringExp::implicitCastTo(%s of type %s) => %s\n", e->toChars(), e->type->toChars(), t->toChars()); 110 visit(cast(Expression)e); 111 if (result.op == TOKstring) 112 { 113 // Retain polysemous nature if it started out that way 114 (cast(StringExp)result).committed = e.committed; 115 } 116 } 117 118 override void visit(ErrorExp e) 119 { 120 result = e; 121 } 122 123 override void visit(FuncExp e) 124 { 125 //printf("FuncExp::implicitCastTo type = %p %s, t = %s\n", e->type, e->type ? e->type->toChars() : NULL, t->toChars()); 126 FuncExp fe; 127 if (e.matchType(t, sc, &fe) > MATCHnomatch) 128 { 129 result = fe; 130 return; 131 } 132 visit(cast(Expression)e); 133 } 134 135 override void visit(ArrayLiteralExp e) 136 { 137 visit(cast(Expression)e); 138 139 Type tb = result.type.toBasetype(); 140 if (tb.ty == Tarray) 141 semanticTypeInfo(sc, (cast(TypeDArray)tb).next); 142 } 143 144 override void visit(SliceExp e) 145 { 146 visit(cast(Expression)e); 147 if (result.op != TOKslice) 148 return; 149 150 e = cast(SliceExp)result; 151 if (e.e1.op == TOKarrayliteral) 152 { 153 ArrayLiteralExp ale = cast(ArrayLiteralExp)e.e1; 154 Type tb = t.toBasetype(); 155 Type tx; 156 if (tb.ty == Tsarray) 157 tx = tb.nextOf().sarrayOf(ale.elements ? ale.elements.dim : 0); 158 else 159 tx = tb.nextOf().arrayOf(); 160 e.e1 = ale.implicitCastTo(sc, tx); 161 } 162 } 163 } 164 165 scope ImplicitCastTo v = new ImplicitCastTo(sc, t); 166 e.accept(v); 167 return v.result; 168 } 169 170 /******************************************* 171 * Return MATCH level of implicitly converting e to type t. 172 * Don't do the actual cast; don't change e. 173 */ 174 extern (C++) MATCH implicitConvTo(Expression e, Type t) 175 { 176 extern (C++) final class ImplicitConvTo : Visitor 177 { 178 alias visit = super.visit; 179 public: 180 Type t; 181 MATCH result; 182 183 extern (D) this(Type t) 184 { 185 this.t = t; 186 result = MATCHnomatch; 187 } 188 189 override void visit(Expression e) 190 { 191 version (none) 192 { 193 printf("Expression::implicitConvTo(this=%s, type=%s, t=%s)\n", e.toChars(), e.type.toChars(), t.toChars()); 194 } 195 //static int nest; if (++nest == 10) assert(0); 196 if (t == Type.terror) 197 return; 198 if (!e.type) 199 { 200 e.error("%s is not an expression", e.toChars()); 201 e.type = Type.terror; 202 } 203 204 Expression ex = e.optimize(WANTvalue); 205 if (ex.type.equals(t)) 206 { 207 result = MATCHexact; 208 return; 209 } 210 if (ex != e) 211 { 212 //printf("\toptimized to %s of type %s\n", e->toChars(), e->type->toChars()); 213 result = ex.implicitConvTo(t); 214 return; 215 } 216 217 MATCH match = e.type.implicitConvTo(t); 218 if (match != MATCHnomatch) 219 { 220 result = match; 221 return; 222 } 223 224 /* See if we can do integral narrowing conversions 225 */ 226 if (e.type.isintegral() && t.isintegral() && e.type.isTypeBasic() && t.isTypeBasic()) 227 { 228 IntRange src = getIntRange(e); 229 IntRange target = IntRange.fromType(t); 230 if (target.contains(src)) 231 { 232 result = MATCHconvert; 233 return; 234 } 235 } 236 } 237 238 /****** 239 * Given expression e of type t, see if we can implicitly convert e 240 * to type tprime, where tprime is type t with mod bits added. 241 * Returns: 242 * match level 243 */ 244 static MATCH implicitMod(Expression e, Type t, MOD mod) 245 { 246 Type tprime; 247 if (t.ty == Tpointer) 248 tprime = t.nextOf().castMod(mod).pointerTo(); 249 else if (t.ty == Tarray) 250 tprime = t.nextOf().castMod(mod).arrayOf(); 251 else if (t.ty == Tsarray) 252 tprime = t.nextOf().castMod(mod).sarrayOf(t.size() / t.nextOf().size()); 253 else 254 tprime = t.castMod(mod); 255 256 return e.implicitConvTo(tprime); 257 } 258 259 static MATCH implicitConvToAddMin(BinExp e, Type t) 260 { 261 /* Is this (ptr +- offset)? If so, then ask ptr 262 * if the conversion can be done. 263 * This is to support doing things like implicitly converting a mutable unique 264 * pointer to an immutable pointer. 265 */ 266 267 Type tb = t.toBasetype(); 268 Type typeb = e.type.toBasetype(); 269 270 if (typeb.ty != Tpointer || tb.ty != Tpointer) 271 return MATCHnomatch; 272 273 Type t1b = e.e1.type.toBasetype(); 274 Type t2b = e.e2.type.toBasetype(); 275 if (t1b.ty == Tpointer && t2b.isintegral() && t1b.equivalent(tb)) 276 { 277 // ptr + offset 278 // ptr - offset 279 MATCH m = e.e1.implicitConvTo(t); 280 return (m > MATCHconst) ? MATCHconst : m; 281 } 282 if (t2b.ty == Tpointer && t1b.isintegral() && t2b.equivalent(tb)) 283 { 284 // offset + ptr 285 MATCH m = e.e2.implicitConvTo(t); 286 return (m > MATCHconst) ? MATCHconst : m; 287 } 288 289 return MATCHnomatch; 290 } 291 292 override void visit(AddExp e) 293 { 294 version (none) 295 { 296 printf("AddExp::implicitConvTo(this=%s, type=%s, t=%s)\n", e.toChars(), e.type.toChars(), t.toChars()); 297 } 298 visit(cast(Expression)e); 299 if (result == MATCHnomatch) 300 result = implicitConvToAddMin(e, t); 301 } 302 303 override void visit(MinExp e) 304 { 305 version (none) 306 { 307 printf("MinExp::implicitConvTo(this=%s, type=%s, t=%s)\n", e.toChars(), e.type.toChars(), t.toChars()); 308 } 309 visit(cast(Expression)e); 310 if (result == MATCHnomatch) 311 result = implicitConvToAddMin(e, t); 312 } 313 314 override void visit(IntegerExp e) 315 { 316 version (none) 317 { 318 printf("IntegerExp::implicitConvTo(this=%s, type=%s, t=%s)\n", e.toChars(), e.type.toChars(), t.toChars()); 319 } 320 MATCH m = e.type.implicitConvTo(t); 321 if (m >= MATCHconst) 322 { 323 result = m; 324 return; 325 } 326 327 TY ty = e.type.toBasetype().ty; 328 TY toty = t.toBasetype().ty; 329 TY oldty = ty; 330 331 if (m == MATCHnomatch && t.ty == Tenum) 332 return; 333 334 if (t.ty == Tvector) 335 { 336 TypeVector tv = cast(TypeVector)t; 337 TypeBasic tb = tv.elementType(); 338 if (tb.ty == Tvoid) 339 return; 340 toty = tb.ty; 341 } 342 343 switch (ty) 344 { 345 case Tbool: 346 case Tint8: 347 case Tchar: 348 case Tuns8: 349 case Tint16: 350 case Tuns16: 351 case Twchar: 352 ty = Tint32; 353 break; 354 355 case Tdchar: 356 ty = Tuns32; 357 break; 358 359 default: 360 break; 361 } 362 363 // Only allow conversion if no change in value 364 dinteger_t value = e.toInteger(); 365 switch (toty) 366 { 367 case Tbool: 368 if ((value & 1) != value) 369 return; 370 break; 371 372 case Tint8: 373 if (ty == Tuns64 && value & ~0x7FU) 374 return; 375 else if (cast(byte)value != value) 376 return; 377 break; 378 379 case Tchar: 380 if ((oldty == Twchar || oldty == Tdchar) && value > 0x7F) 381 return; 382 goto case Tuns8; 383 case Tuns8: 384 //printf("value = %llu %llu\n", (dinteger_t)(unsigned char)value, value); 385 if (cast(ubyte)value != value) 386 return; 387 break; 388 389 case Tint16: 390 if (ty == Tuns64 && value & ~0x7FFFU) 391 return; 392 else if (cast(short)value != value) 393 return; 394 break; 395 396 case Twchar: 397 if (oldty == Tdchar && value > 0xD7FF && value < 0xE000) 398 return; 399 goto case Tuns16; 400 case Tuns16: 401 if (cast(ushort)value != value) 402 return; 403 break; 404 405 case Tint32: 406 if (ty == Tuns32) 407 { 408 } 409 else if (ty == Tuns64 && value & ~0x7FFFFFFFU) 410 return; 411 else if (cast(int)value != value) 412 return; 413 break; 414 415 case Tuns32: 416 if (ty == Tint32) 417 { 418 } 419 else if (cast(uint)value != value) 420 return; 421 break; 422 423 case Tdchar: 424 if (value > 0x10FFFFU) 425 return; 426 break; 427 428 case Tfloat32: 429 { 430 float f; 431 if (e.type.isunsigned()) 432 { 433 f = cast(float)value; 434 if (f != value) 435 return; 436 } 437 else 438 { 439 f = cast(float)cast(sinteger_t)value; 440 if (f != cast(sinteger_t)value) 441 return; 442 } 443 break; 444 } 445 446 case Tfloat64: 447 { 448 double f; 449 if (e.type.isunsigned()) 450 { 451 f = cast(double)value; 452 if (f != value) 453 return; 454 } 455 else 456 { 457 f = cast(double)cast(sinteger_t)value; 458 if (f != cast(sinteger_t)value) 459 return; 460 } 461 break; 462 } 463 464 case Tfloat80: 465 { 466 if (e.type.isunsigned()) 467 { 468 const f = real_t(value); 469 if (cast(dinteger_t)f != value) // isn't this a noop, because the compiler prefers ld 470 return; 471 } 472 else 473 { 474 const f = real_t(cast(sinteger_t)value); 475 if (cast(sinteger_t)f != cast(sinteger_t)value) 476 return; 477 } 478 break; 479 } 480 481 case Tpointer: 482 //printf("type = %s\n", type->toBasetype()->toChars()); 483 //printf("t = %s\n", t->toBasetype()->toChars()); 484 if (ty == Tpointer && e.type.toBasetype().nextOf().ty == t.toBasetype().nextOf().ty) 485 { 486 /* Allow things like: 487 * const char* P = cast(char *)3; 488 * char* q = P; 489 */ 490 break; 491 } 492 goto default; 493 494 default: 495 visit(cast(Expression)e); 496 return; 497 } 498 499 //printf("MATCHconvert\n"); 500 result = MATCHconvert; 501 } 502 503 override void visit(ErrorExp e) 504 { 505 // no match 506 } 507 508 override void visit(NullExp e) 509 { 510 version (none) 511 { 512 printf("NullExp::implicitConvTo(this=%s, type=%s, t=%s, committed = %d)\n", e.toChars(), e.type.toChars(), t.toChars(), e.committed); 513 } 514 if (e.type.equals(t)) 515 { 516 result = MATCHexact; 517 return; 518 } 519 520 /* Allow implicit conversions from immutable to mutable|const, 521 * and mutable to immutable. It works because, after all, a null 522 * doesn't actually point to anything. 523 */ 524 if (t.equivalent(e.type)) 525 { 526 result = MATCHconst; 527 return; 528 } 529 530 visit(cast(Expression)e); 531 } 532 533 override void visit(StructLiteralExp e) 534 { 535 version (none) 536 { 537 printf("StructLiteralExp::implicitConvTo(this=%s, type=%s, t=%s)\n", e.toChars(), e.type.toChars(), t.toChars()); 538 } 539 visit(cast(Expression)e); 540 if (result != MATCHnomatch) 541 return; 542 if (e.type.ty == t.ty && e.type.ty == Tstruct && (cast(TypeStruct)e.type).sym == (cast(TypeStruct)t).sym) 543 { 544 result = MATCHconst; 545 for (size_t i = 0; i < e.elements.dim; i++) 546 { 547 Expression el = (*e.elements)[i]; 548 if (!el) 549 continue; 550 Type te = el.type; 551 te = e.sd.fields[i].type.addMod(t.mod); 552 MATCH m2 = el.implicitConvTo(te); 553 //printf("\t%s => %s, match = %d\n", el->toChars(), te->toChars(), m2); 554 if (m2 < result) 555 result = m2; 556 } 557 } 558 } 559 560 override void visit(StringExp e) 561 { 562 version (none) 563 { 564 printf("StringExp::implicitConvTo(this=%s, committed=%d, type=%s, t=%s)\n", e.toChars(), e.committed, e.type.toChars(), t.toChars()); 565 } 566 if (!e.committed && t.ty == Tpointer && t.nextOf().ty == Tvoid) 567 return; 568 569 if (e.type.ty == Tsarray || e.type.ty == Tarray || e.type.ty == Tpointer) 570 { 571 TY tyn = e.type.nextOf().ty; 572 if (tyn == Tchar || tyn == Twchar || tyn == Tdchar) 573 { 574 switch (t.ty) 575 { 576 case Tsarray: 577 if (e.type.ty == Tsarray) 578 { 579 TY tynto = t.nextOf().ty; 580 if (tynto == tyn) 581 { 582 if ((cast(TypeSArray)e.type).dim.toInteger() == (cast(TypeSArray)t).dim.toInteger()) 583 { 584 result = MATCHexact; 585 } 586 return; 587 } 588 if (tynto == Tchar || tynto == Twchar || tynto == Tdchar) 589 { 590 if (e.committed && tynto != tyn) 591 return; 592 size_t fromlen = e.numberOfCodeUnits(tynto); 593 size_t tolen = cast(size_t)(cast(TypeSArray)t).dim.toInteger(); 594 if (tolen < fromlen) 595 return; 596 if (tolen != fromlen) 597 { 598 // implicit length extending 599 result = MATCHconvert; 600 return; 601 } 602 } 603 if (!e.committed && (tynto == Tchar || tynto == Twchar || tynto == Tdchar)) 604 { 605 result = MATCHexact; 606 return; 607 } 608 } 609 else if (e.type.ty == Tarray) 610 { 611 TY tynto = t.nextOf().ty; 612 if (tynto == Tchar || tynto == Twchar || tynto == Tdchar) 613 { 614 if (e.committed && tynto != tyn) 615 return; 616 size_t fromlen = e.numberOfCodeUnits(tynto); 617 size_t tolen = cast(size_t)(cast(TypeSArray)t).dim.toInteger(); 618 if (tolen < fromlen) 619 return; 620 if (tolen != fromlen) 621 { 622 // implicit length extending 623 result = MATCHconvert; 624 return; 625 } 626 } 627 if (tynto == tyn) 628 { 629 result = MATCHexact; 630 return; 631 } 632 if (!e.committed && (tynto == Tchar || tynto == Twchar || tynto == Tdchar)) 633 { 634 result = MATCHexact; 635 return; 636 } 637 } 638 goto case; /+ fall through +/ 639 case Tarray: 640 case Tpointer: 641 Type tn = t.nextOf(); 642 MATCH m = MATCHexact; 643 if (e.type.nextOf().mod != tn.mod) 644 { 645 if (!tn.isConst()) 646 return; 647 m = MATCHconst; 648 } 649 if (!e.committed) 650 { 651 switch (tn.ty) 652 { 653 case Tchar: 654 if (e.postfix == 'w' || e.postfix == 'd') 655 m = MATCHconvert; 656 result = m; 657 return; 658 case Twchar: 659 if (e.postfix != 'w') 660 m = MATCHconvert; 661 result = m; 662 return; 663 case Tdchar: 664 if (e.postfix != 'd') 665 m = MATCHconvert; 666 result = m; 667 return; 668 default: 669 break; 670 } 671 } 672 break; 673 674 default: 675 break; 676 } 677 } 678 } 679 680 visit(cast(Expression)e); 681 } 682 683 override void visit(ArrayLiteralExp e) 684 { 685 version (none) 686 { 687 printf("ArrayLiteralExp::implicitConvTo(this=%s, type=%s, t=%s)\n", e.toChars(), e.type.toChars(), t.toChars()); 688 } 689 Type tb = t.toBasetype(); 690 Type typeb = e.type.toBasetype(); 691 692 if ((tb.ty == Tarray || tb.ty == Tsarray) && 693 (typeb.ty == Tarray || typeb.ty == Tsarray)) 694 { 695 result = MATCHexact; 696 Type typen = typeb.nextOf().toBasetype(); 697 698 if (tb.ty == Tsarray) 699 { 700 TypeSArray tsa = cast(TypeSArray)tb; 701 if (e.elements.dim != tsa.dim.toInteger()) 702 result = MATCHnomatch; 703 } 704 705 Type telement = tb.nextOf(); 706 if (!e.elements.dim) 707 { 708 if (typen.ty != Tvoid) 709 result = typen.implicitConvTo(telement); 710 } 711 else 712 { 713 if (e.basis) 714 { 715 MATCH m = e.basis.implicitConvTo(telement); 716 if (m < result) 717 result = m; 718 } 719 for (size_t i = 0; i < e.elements.dim; i++) 720 { 721 Expression el = (*e.elements)[i]; 722 if (result == MATCHnomatch) 723 break; 724 if (!el) 725 continue; 726 MATCH m = el.implicitConvTo(telement); 727 if (m < result) 728 result = m; // remember worst match 729 } 730 } 731 732 if (!result) 733 result = e.type.implicitConvTo(t); 734 735 return; 736 } 737 else if (tb.ty == Tvector && (typeb.ty == Tarray || typeb.ty == Tsarray)) 738 { 739 result = MATCHexact; 740 // Convert array literal to vector type 741 TypeVector tv = cast(TypeVector)tb; 742 TypeSArray tbase = cast(TypeSArray)tv.basetype; 743 assert(tbase.ty == Tsarray); 744 const edim = e.elements.dim; 745 const tbasedim = tbase.dim.toInteger(); 746 if (edim > tbasedim) 747 { 748 result = MATCHnomatch; 749 return; 750 } 751 752 Type telement = tv.elementType(); 753 if (edim < tbasedim) 754 { 755 Expression el = typeb.nextOf.defaultInitLiteral(e.loc); 756 MATCH m = el.implicitConvTo(telement); 757 if (m < result) 758 result = m; // remember worst match 759 } 760 foreach (i; 0 .. edim) 761 { 762 Expression el = (*e.elements)[i]; 763 MATCH m = el.implicitConvTo(telement); 764 if (m < result) 765 result = m; // remember worst match 766 if (result == MATCHnomatch) 767 break; // no need to check for worse 768 } 769 return; 770 } 771 772 visit(cast(Expression)e); 773 } 774 775 override void visit(AssocArrayLiteralExp e) 776 { 777 Type tb = t.toBasetype(); 778 Type typeb = e.type.toBasetype(); 779 780 if (tb.ty == Taarray && typeb.ty == Taarray) 781 { 782 result = MATCHexact; 783 for (size_t i = 0; i < e.keys.dim; i++) 784 { 785 Expression el = (*e.keys)[i]; 786 MATCH m = el.implicitConvTo((cast(TypeAArray)tb).index); 787 if (m < result) 788 result = m; // remember worst match 789 if (result == MATCHnomatch) 790 break; // no need to check for worse 791 el = (*e.values)[i]; 792 m = el.implicitConvTo(tb.nextOf()); 793 if (m < result) 794 result = m; // remember worst match 795 if (result == MATCHnomatch) 796 break; // no need to check for worse 797 } 798 return; 799 } 800 else 801 visit(cast(Expression)e); 802 } 803 804 override void visit(CallExp e) 805 { 806 enum LOG = 0; 807 static if (LOG) 808 { 809 printf("CallExp::implicitConvTo(this=%s, type=%s, t=%s)\n", e.toChars(), e.type.toChars(), t.toChars()); 810 } 811 812 visit(cast(Expression)e); 813 if (result != MATCHnomatch) 814 return; 815 816 /* Allow the result of strongly pure functions to 817 * convert to immutable 818 */ 819 if (e.f && e.f.isolateReturn()) 820 { 821 result = e.type.immutableOf().implicitConvTo(t); 822 if (result > MATCHconst) // Match level is MATCHconst at best. 823 result = MATCHconst; 824 return; 825 } 826 827 /* Conversion is 'const' conversion if: 828 * 1. function is pure (weakly pure is ok) 829 * 2. implicit conversion only fails because of mod bits 830 * 3. each function parameter can be implicitly converted to the mod bits 831 */ 832 Type tx = e.f ? e.f.type : e.e1.type; 833 tx = tx.toBasetype(); 834 if (tx.ty != Tfunction) 835 return; 836 TypeFunction tf = cast(TypeFunction)tx; 837 838 if (tf.purity == PUREimpure) 839 return; 840 if (e.f && e.f.isNested()) 841 return; 842 843 /* See if fail only because of mod bits. 844 * 845 * Bugzilla 14155: All pure functions can access global immutable data. 846 * So the returned pointer may refer an immutable global data, 847 * and then the returned pointer that points non-mutable object 848 * cannot be unique pointer. 849 * 850 * Example: 851 * immutable g; 852 * static this() { g = 1; } 853 * const(int*) foo() pure { return &g; } 854 * void test() { 855 * immutable(int*) ip = foo(); // OK 856 * int* mp = foo(); // should be disallowed 857 * } 858 */ 859 if (e.type.immutableOf().implicitConvTo(t) < MATCHconst && e.type.addMod(MODshared).implicitConvTo(t) < MATCHconst && e.type.implicitConvTo(t.addMod(MODshared)) < MATCHconst) 860 { 861 return; 862 } 863 // Allow a conversion to immutable type, or 864 // conversions of mutable types between thread-local and shared. 865 866 /* Get mod bits of what we're converting to 867 */ 868 Type tb = t.toBasetype(); 869 MOD mod = tb.mod; 870 if (tf.isref) 871 { 872 } 873 else 874 { 875 Type ti = getIndirection(t); 876 if (ti) 877 mod = ti.mod; 878 } 879 static if (LOG) 880 { 881 printf("mod = x%x\n", mod); 882 } 883 if (mod & MODwild) 884 return; // not sure what to do with this 885 886 /* Apply mod bits to each function parameter, 887 * and see if we can convert the function argument to the modded type 888 */ 889 890 size_t nparams = Parameter.dim(tf.parameters); 891 size_t j = (tf.linkage == LINKd && tf.varargs == 1); // if TypeInfoArray was prepended 892 if (e.e1.op == TOKdotvar) 893 { 894 /* Treat 'this' as just another function argument 895 */ 896 DotVarExp dve = cast(DotVarExp)e.e1; 897 Type targ = dve.e1.type; 898 if (targ.constConv(targ.castMod(mod)) == MATCHnomatch) 899 return; 900 } 901 for (size_t i = j; i < e.arguments.dim; ++i) 902 { 903 Expression earg = (*e.arguments)[i]; 904 Type targ = earg.type.toBasetype(); 905 static if (LOG) 906 { 907 printf("[%d] earg: %s, targ: %s\n", cast(int)i, earg.toChars(), targ.toChars()); 908 } 909 if (i - j < nparams) 910 { 911 Parameter fparam = Parameter.getNth(tf.parameters, i - j); 912 if (fparam.storageClass & STClazy) 913 return; // not sure what to do with this 914 Type tparam = fparam.type; 915 if (!tparam) 916 continue; 917 if (fparam.storageClass & (STCout | STCref)) 918 { 919 if (targ.constConv(tparam.castMod(mod)) == MATCHnomatch) 920 return; 921 continue; 922 } 923 } 924 static if (LOG) 925 { 926 printf("[%d] earg: %s, targm: %s\n", cast(int)i, earg.toChars(), targ.addMod(mod).toChars()); 927 } 928 if (implicitMod(earg, targ, mod) == MATCHnomatch) 929 return; 930 } 931 932 /* Success 933 */ 934 result = MATCHconst; 935 } 936 937 override void visit(AddrExp e) 938 { 939 version (none) 940 { 941 printf("AddrExp::implicitConvTo(this=%s, type=%s, t=%s)\n", e.toChars(), e.type.toChars(), t.toChars()); 942 } 943 result = e.type.implicitConvTo(t); 944 //printf("\tresult = %d\n", result); 945 946 if (result != MATCHnomatch) 947 return; 948 949 Type tb = t.toBasetype(); 950 Type typeb = e.type.toBasetype(); 951 952 // Look for pointers to functions where the functions are overloaded. 953 if (e.e1.op == TOKoverloadset && 954 (tb.ty == Tpointer || tb.ty == Tdelegate) && tb.nextOf().ty == Tfunction) 955 { 956 OverExp eo = cast(OverExp)e.e1; 957 FuncDeclaration f = null; 958 for (size_t i = 0; i < eo.vars.a.dim; i++) 959 { 960 Dsymbol s = eo.vars.a[i]; 961 FuncDeclaration f2 = s.isFuncDeclaration(); 962 assert(f2); 963 if (f2.overloadExactMatch(tb.nextOf())) 964 { 965 if (f) 966 { 967 /* Error if match in more than one overload set, 968 * even if one is a 'better' match than the other. 969 */ 970 ScopeDsymbol.multiplyDefined(e.loc, f, f2); 971 } 972 else 973 f = f2; 974 result = MATCHexact; 975 } 976 } 977 } 978 979 if (e.e1.op == TOKvar && 980 typeb.ty == Tpointer && typeb.nextOf().ty == Tfunction && 981 tb.ty == Tpointer && tb.nextOf().ty == Tfunction) 982 { 983 /* I don't think this can ever happen - 984 * it should have been 985 * converted to a SymOffExp. 986 */ 987 assert(0); 988 } 989 990 //printf("\tresult = %d\n", result); 991 } 992 993 override void visit(SymOffExp e) 994 { 995 version (none) 996 { 997 printf("SymOffExp::implicitConvTo(this=%s, type=%s, t=%s)\n", e.toChars(), e.type.toChars(), t.toChars()); 998 } 999 result = e.type.implicitConvTo(t); 1000 //printf("\tresult = %d\n", result); 1001 if (result != MATCHnomatch) 1002 return; 1003 1004 Type tb = t.toBasetype(); 1005 Type typeb = e.type.toBasetype(); 1006 1007 // Look for pointers to functions where the functions are overloaded. 1008 if (typeb.ty == Tpointer && typeb.nextOf().ty == Tfunction && 1009 (tb.ty == Tpointer || tb.ty == Tdelegate) && tb.nextOf().ty == Tfunction) 1010 { 1011 if (FuncDeclaration f = e.var.isFuncDeclaration()) 1012 { 1013 f = f.overloadExactMatch(tb.nextOf()); 1014 if (f) 1015 { 1016 if ((tb.ty == Tdelegate && (f.needThis() || f.isNested())) || 1017 (tb.ty == Tpointer && !(f.needThis() || f.isNested()))) 1018 { 1019 result = MATCHexact; 1020 } 1021 } 1022 } 1023 } 1024 //printf("\tresult = %d\n", result); 1025 } 1026 1027 override void visit(DelegateExp e) 1028 { 1029 version (none) 1030 { 1031 printf("DelegateExp::implicitConvTo(this=%s, type=%s, t=%s)\n", e.toChars(), e.type.toChars(), t.toChars()); 1032 } 1033 result = e.type.implicitConvTo(t); 1034 if (result != MATCHnomatch) 1035 return; 1036 1037 Type tb = t.toBasetype(); 1038 Type typeb = e.type.toBasetype(); 1039 1040 // Look for pointers to functions where the functions are overloaded. 1041 if (typeb.ty == Tdelegate && tb.ty == Tdelegate) 1042 { 1043 if (e.func && e.func.overloadExactMatch(tb.nextOf())) 1044 result = MATCHexact; 1045 } 1046 } 1047 1048 override void visit(FuncExp e) 1049 { 1050 //printf("FuncExp::implicitConvTo type = %p %s, t = %s\n", e->type, e->type ? e->type->toChars() : NULL, t->toChars()); 1051 MATCH m = e.matchType(t, null, null, 1); 1052 if (m > MATCHnomatch) 1053 { 1054 result = m; 1055 return; 1056 } 1057 visit(cast(Expression)e); 1058 } 1059 1060 override void visit(OrExp e) 1061 { 1062 visit(cast(Expression)e); 1063 if (result != MATCHnomatch) 1064 return; 1065 1066 MATCH m1 = e.e1.implicitConvTo(t); 1067 MATCH m2 = e.e2.implicitConvTo(t); 1068 1069 // Pick the worst match 1070 result = (m1 < m2) ? m1 : m2; 1071 } 1072 1073 override void visit(XorExp e) 1074 { 1075 visit(cast(Expression)e); 1076 if (result != MATCHnomatch) 1077 return; 1078 1079 MATCH m1 = e.e1.implicitConvTo(t); 1080 MATCH m2 = e.e2.implicitConvTo(t); 1081 1082 // Pick the worst match 1083 result = (m1 < m2) ? m1 : m2; 1084 } 1085 1086 override void visit(CondExp e) 1087 { 1088 MATCH m1 = e.e1.implicitConvTo(t); 1089 MATCH m2 = e.e2.implicitConvTo(t); 1090 //printf("CondExp: m1 %d m2 %d\n", m1, m2); 1091 1092 // Pick the worst match 1093 result = (m1 < m2) ? m1 : m2; 1094 } 1095 1096 override void visit(CommaExp e) 1097 { 1098 e.e2.accept(this); 1099 } 1100 1101 override void visit(CastExp e) 1102 { 1103 version (none) 1104 { 1105 printf("CastExp::implicitConvTo(this=%s, type=%s, t=%s)\n", e.toChars(), e.type.toChars(), t.toChars()); 1106 } 1107 result = e.type.implicitConvTo(t); 1108 if (result != MATCHnomatch) 1109 return; 1110 1111 if (t.isintegral() && e.e1.type.isintegral() && e.e1.implicitConvTo(t) != MATCHnomatch) 1112 result = MATCHconvert; 1113 else 1114 visit(cast(Expression)e); 1115 } 1116 1117 override void visit(NewExp e) 1118 { 1119 version (none) 1120 { 1121 printf("NewExp::implicitConvTo(this=%s, type=%s, t=%s)\n", e.toChars(), e.type.toChars(), t.toChars()); 1122 } 1123 visit(cast(Expression)e); 1124 if (result != MATCHnomatch) 1125 return; 1126 1127 /* Calling new() is like calling a pure function. We can implicitly convert the 1128 * return from new() to t using the same algorithm as in CallExp, with the function 1129 * 'arguments' being: 1130 * thisexp 1131 * newargs 1132 * arguments 1133 * .init 1134 * 'member' and 'allocator' need to be pure. 1135 */ 1136 1137 /* See if fail only because of mod bits 1138 */ 1139 if (e.type.immutableOf().implicitConvTo(t.immutableOf()) == MATCHnomatch) 1140 return; 1141 1142 /* Get mod bits of what we're converting to 1143 */ 1144 Type tb = t.toBasetype(); 1145 MOD mod = tb.mod; 1146 if (Type ti = getIndirection(t)) 1147 mod = ti.mod; 1148 static if (LOG) 1149 { 1150 printf("mod = x%x\n", mod); 1151 } 1152 if (mod & MODwild) 1153 return; // not sure what to do with this 1154 1155 /* Apply mod bits to each argument, 1156 * and see if we can convert the argument to the modded type 1157 */ 1158 1159 if (e.thisexp) 1160 { 1161 /* Treat 'this' as just another function argument 1162 */ 1163 Type targ = e.thisexp.type; 1164 if (targ.constConv(targ.castMod(mod)) == MATCHnomatch) 1165 return; 1166 } 1167 1168 /* Check call to 'allocator', then 'member' 1169 */ 1170 FuncDeclaration fd = e.allocator; 1171 for (int count = 0; count < 2; ++count, (fd = e.member)) 1172 { 1173 if (!fd) 1174 continue; 1175 if (fd.errors || fd.type.ty != Tfunction) 1176 return; // error 1177 TypeFunction tf = cast(TypeFunction)fd.type; 1178 if (tf.purity == PUREimpure) 1179 return; // impure 1180 1181 if (fd == e.member) 1182 { 1183 if (e.type.immutableOf().implicitConvTo(t) < MATCHconst && e.type.addMod(MODshared).implicitConvTo(t) < MATCHconst && e.type.implicitConvTo(t.addMod(MODshared)) < MATCHconst) 1184 { 1185 return; 1186 } 1187 // Allow a conversion to immutable type, or 1188 // conversions of mutable types between thread-local and shared. 1189 } 1190 1191 Expressions* args = (fd == e.allocator) ? e.newargs : e.arguments; 1192 1193 size_t nparams = Parameter.dim(tf.parameters); 1194 size_t j = (tf.linkage == LINKd && tf.varargs == 1); // if TypeInfoArray was prepended 1195 for (size_t i = j; i < e.arguments.dim; ++i) 1196 { 1197 Expression earg = (*args)[i]; 1198 Type targ = earg.type.toBasetype(); 1199 static if (LOG) 1200 { 1201 printf("[%d] earg: %s, targ: %s\n", cast(int)i, earg.toChars(), targ.toChars()); 1202 } 1203 if (i - j < nparams) 1204 { 1205 Parameter fparam = Parameter.getNth(tf.parameters, i - j); 1206 if (fparam.storageClass & STClazy) 1207 return; // not sure what to do with this 1208 Type tparam = fparam.type; 1209 if (!tparam) 1210 continue; 1211 if (fparam.storageClass & (STCout | STCref)) 1212 { 1213 if (targ.constConv(tparam.castMod(mod)) == MATCHnomatch) 1214 return; 1215 continue; 1216 } 1217 } 1218 static if (LOG) 1219 { 1220 printf("[%d] earg: %s, targm: %s\n", cast(int)i, earg.toChars(), targ.addMod(mod).toChars()); 1221 } 1222 if (implicitMod(earg, targ, mod) == MATCHnomatch) 1223 return; 1224 } 1225 } 1226 1227 /* If no 'member', then construction is by simple assignment, 1228 * and just straight check 'arguments' 1229 */ 1230 if (!e.member && e.arguments) 1231 { 1232 for (size_t i = 0; i < e.arguments.dim; ++i) 1233 { 1234 Expression earg = (*e.arguments)[i]; 1235 if (!earg) // Bugzilla 14853: if it's on overlapped field 1236 continue; 1237 Type targ = earg.type.toBasetype(); 1238 static if (LOG) 1239 { 1240 printf("[%d] earg: %s, targ: %s\n", cast(int)i, earg.toChars(), targ.toChars()); 1241 printf("[%d] earg: %s, targm: %s\n", cast(int)i, earg.toChars(), targ.addMod(mod).toChars()); 1242 } 1243 if (implicitMod(earg, targ, mod) == MATCHnomatch) 1244 return; 1245 } 1246 } 1247 1248 /* Consider the .init expression as an argument 1249 */ 1250 Type ntb = e.newtype.toBasetype(); 1251 if (ntb.ty == Tarray) 1252 ntb = ntb.nextOf().toBasetype(); 1253 if (ntb.ty == Tstruct) 1254 { 1255 // Don't allow nested structs - uplevel reference may not be convertible 1256 StructDeclaration sd = (cast(TypeStruct)ntb).sym; 1257 sd.size(e.loc); // resolve any forward references 1258 if (sd.isNested()) 1259 return; 1260 } 1261 if (ntb.isZeroInit(e.loc)) 1262 { 1263 /* Zeros are implicitly convertible, except for special cases. 1264 */ 1265 if (ntb.ty == Tclass) 1266 { 1267 /* With new() must look at the class instance initializer. 1268 */ 1269 ClassDeclaration cd = (cast(TypeClass)ntb).sym; 1270 1271 cd.size(e.loc); // resolve any forward references 1272 1273 if (cd.isNested()) 1274 return; // uplevel reference may not be convertible 1275 1276 assert(!cd.isInterfaceDeclaration()); 1277 1278 struct ClassCheck 1279 { 1280 extern (C++) static bool convertible(Loc loc, ClassDeclaration cd, MOD mod) 1281 { 1282 for (size_t i = 0; i < cd.fields.dim; i++) 1283 { 1284 VarDeclaration v = cd.fields[i]; 1285 Initializer _init = v._init; 1286 if (_init) 1287 { 1288 if (_init.isVoidInitializer()) 1289 { 1290 } 1291 else if (ExpInitializer ei = _init.isExpInitializer()) 1292 { 1293 Type tb = v.type.toBasetype(); 1294 if (implicitMod(ei.exp, tb, mod) == MATCHnomatch) 1295 return false; 1296 } 1297 else 1298 { 1299 /* Enhancement: handle StructInitializer and ArrayInitializer 1300 */ 1301 return false; 1302 } 1303 } 1304 else if (!v.type.isZeroInit(loc)) 1305 return false; 1306 } 1307 return cd.baseClass ? convertible(loc, cd.baseClass, mod) : true; 1308 } 1309 } 1310 1311 if (!ClassCheck.convertible(e.loc, cd, mod)) 1312 return; 1313 } 1314 } 1315 else 1316 { 1317 Expression earg = e.newtype.defaultInitLiteral(e.loc); 1318 Type targ = e.newtype.toBasetype(); 1319 1320 if (implicitMod(earg, targ, mod) == MATCHnomatch) 1321 return; 1322 } 1323 1324 /* Success 1325 */ 1326 result = MATCHconst; 1327 } 1328 1329 override void visit(SliceExp e) 1330 { 1331 //printf("SliceExp::implicitConvTo e = %s, type = %s\n", e->toChars(), e->type->toChars()); 1332 visit(cast(Expression)e); 1333 if (result != MATCHnomatch) 1334 return; 1335 1336 Type tb = t.toBasetype(); 1337 Type typeb = e.type.toBasetype(); 1338 1339 if (tb.ty == Tsarray && typeb.ty == Tarray) 1340 { 1341 typeb = toStaticArrayType(e); 1342 if (typeb) 1343 result = typeb.implicitConvTo(t); 1344 return; 1345 } 1346 1347 /* If the only reason it won't convert is because of the mod bits, 1348 * then test for conversion by seeing if e1 can be converted with those 1349 * same mod bits. 1350 */ 1351 Type t1b = e.e1.type.toBasetype(); 1352 if (tb.ty == Tarray && typeb.equivalent(tb)) 1353 { 1354 Type tbn = tb.nextOf(); 1355 Type tx = null; 1356 1357 /* If e->e1 is dynamic array or pointer, the uniqueness of e->e1 1358 * is equivalent with the uniqueness of the referred data. And in here 1359 * we can have arbitrary typed reference for that. 1360 */ 1361 if (t1b.ty == Tarray) 1362 tx = tbn.arrayOf(); 1363 if (t1b.ty == Tpointer) 1364 tx = tbn.pointerTo(); 1365 1366 /* If e->e1 is static array, at least it should be an rvalue. 1367 * If not, e->e1 is a reference, and its uniqueness does not link 1368 * to the uniqueness of the referred data. 1369 */ 1370 if (t1b.ty == Tsarray && !e.e1.isLvalue()) 1371 tx = tbn.sarrayOf(t1b.size() / tbn.size()); 1372 1373 if (tx) 1374 { 1375 result = e.e1.implicitConvTo(tx); 1376 if (result > MATCHconst) // Match level is MATCHconst at best. 1377 result = MATCHconst; 1378 } 1379 } 1380 1381 // Enhancement 10724 1382 if (tb.ty == Tpointer && e.e1.op == TOKstring) 1383 e.e1.accept(this); 1384 } 1385 } 1386 1387 scope ImplicitConvTo v = new ImplicitConvTo(t); 1388 e.accept(v); 1389 return v.result; 1390 } 1391 1392 extern (C++) Type toStaticArrayType(SliceExp e) 1393 { 1394 if (e.lwr && e.upr) 1395 { 1396 // For the following code to work, e should be optimized beforehand. 1397 // (eg. $ in lwr and upr should be already resolved, if possible) 1398 Expression lwr = e.lwr.optimize(WANTvalue); 1399 Expression upr = e.upr.optimize(WANTvalue); 1400 if (lwr.isConst() && upr.isConst()) 1401 { 1402 size_t len = cast(size_t)(upr.toUInteger() - lwr.toUInteger()); 1403 return e.type.toBasetype().nextOf().sarrayOf(len); 1404 } 1405 } 1406 else 1407 { 1408 Type t1b = e.e1.type.toBasetype(); 1409 if (t1b.ty == Tsarray) 1410 return t1b; 1411 } 1412 return null; 1413 } 1414 1415 /************************************** 1416 * Do an explicit cast. 1417 * Assume that the 'this' expression does not have any indirections. 1418 */ 1419 extern (C++) Expression castTo(Expression e, Scope* sc, Type t) 1420 { 1421 extern (C++) final class CastTo : Visitor 1422 { 1423 alias visit = super.visit; 1424 public: 1425 Type t; 1426 Scope* sc; 1427 Expression result; 1428 1429 extern (D) this(Scope* sc, Type t) 1430 { 1431 this.sc = sc; 1432 this.t = t; 1433 } 1434 1435 override void visit(Expression e) 1436 { 1437 //printf("Expression::castTo(this=%s, t=%s)\n", e->toChars(), t->toChars()); 1438 version (none) 1439 { 1440 printf("Expression::castTo(this=%s, type=%s, t=%s)\n", e.toChars(), e.type.toChars(), t.toChars()); 1441 } 1442 if (e.type.equals(t)) 1443 { 1444 result = e; 1445 return; 1446 } 1447 if (e.op == TOKvar) 1448 { 1449 VarDeclaration v = (cast(VarExp)e).var.isVarDeclaration(); 1450 if (v && v.storage_class & STCmanifest) 1451 { 1452 result = e.ctfeInterpret(); 1453 result = result.castTo(sc, t); 1454 return; 1455 } 1456 } 1457 1458 Type tob = t.toBasetype(); 1459 Type t1b = e.type.toBasetype(); 1460 if (tob.equals(t1b)) 1461 { 1462 result = e.copy(); // because of COW for assignment to e->type 1463 result.type = t; 1464 return; 1465 } 1466 1467 /* Make semantic error against invalid cast between concrete types. 1468 * Assume that 'e' is never be any placeholder expressions. 1469 * The result of these checks should be consistent with CastExp::toElem(). 1470 */ 1471 1472 // Fat Value types 1473 const(bool) tob_isFV = (tob.ty == Tstruct || tob.ty == Tsarray); 1474 const(bool) t1b_isFV = (t1b.ty == Tstruct || t1b.ty == Tsarray); 1475 1476 // Fat Reference types 1477 const(bool) tob_isFR = (tob.ty == Tarray || tob.ty == Tdelegate); 1478 const(bool) t1b_isFR = (t1b.ty == Tarray || t1b.ty == Tdelegate); 1479 1480 // Reference types 1481 const(bool) tob_isR = (tob_isFR || tob.ty == Tpointer || tob.ty == Taarray || tob.ty == Tclass); 1482 const(bool) t1b_isR = (t1b_isFR || t1b.ty == Tpointer || t1b.ty == Taarray || t1b.ty == Tclass); 1483 1484 // Arithmetic types (== valueable basic types) 1485 const(bool) tob_isA = (tob.isintegral() || tob.isfloating()); 1486 const(bool) t1b_isA = (t1b.isintegral() || t1b.isfloating()); 1487 1488 if (AggregateDeclaration t1ad = isAggregate(t1b)) 1489 { 1490 AggregateDeclaration toad = isAggregate(tob); 1491 if (t1ad != toad && t1ad.aliasthis) 1492 { 1493 if (t1b.ty == Tclass && tob.ty == Tclass) 1494 { 1495 ClassDeclaration t1cd = t1b.isClassHandle(); 1496 ClassDeclaration tocd = tob.isClassHandle(); 1497 int offset; 1498 if (tocd.isBaseOf(t1cd, &offset)) 1499 goto Lok; 1500 } 1501 1502 /* Forward the cast to our alias this member, rewrite to: 1503 * cast(to)e1.aliasthis 1504 */ 1505 result = resolveAliasThis(sc, e); 1506 result = result.castTo(sc, t); 1507 return; 1508 } 1509 } 1510 else if (tob.ty == Tvector && t1b.ty != Tvector) 1511 { 1512 //printf("test1 e = %s, e->type = %s, tob = %s\n", e->toChars(), e->type->toChars(), tob->toChars()); 1513 TypeVector tv = cast(TypeVector)tob; 1514 result = new CastExp(e.loc, e, tv.elementType()); 1515 result = new VectorExp(e.loc, result, tob); 1516 result = result.semantic(sc); 1517 return; 1518 } 1519 else if (tob.ty != Tvector && t1b.ty == Tvector) 1520 { 1521 // T[n] <-- __vector(U[m]) 1522 if (tob.ty == Tsarray) 1523 { 1524 if (t1b.size(e.loc) == tob.size(e.loc)) 1525 goto Lok; 1526 } 1527 goto Lfail; 1528 } 1529 else if (t1b.implicitConvTo(tob) == MATCHconst && t.equals(e.type.constOf())) 1530 { 1531 result = e.copy(); 1532 result.type = t; 1533 return; 1534 } 1535 1536 // arithmetic values vs. other arithmetic values 1537 // arithmetic values vs. T* 1538 if (tob_isA && (t1b_isA || t1b.ty == Tpointer) || t1b_isA && (tob_isA || tob.ty == Tpointer)) 1539 { 1540 goto Lok; 1541 } 1542 1543 // arithmetic values vs. references or fat values 1544 if (tob_isA && (t1b_isR || t1b_isFV) || t1b_isA && (tob_isR || tob_isFV)) 1545 { 1546 goto Lfail; 1547 } 1548 1549 // Bugzlla 3133: A cast between fat values is possible only when the sizes match. 1550 if (tob_isFV && t1b_isFV) 1551 { 1552 if (t1b.size(e.loc) == tob.size(e.loc)) 1553 goto Lok; 1554 e.error("cannot cast expression %s of type %s to %s because of different sizes", e.toChars(), e.type.toChars(), t.toChars()); 1555 result = new ErrorExp(); 1556 return; 1557 } 1558 1559 // Fat values vs. null or references 1560 if (tob_isFV && (t1b.ty == Tnull || t1b_isR) || t1b_isFV && (tob.ty == Tnull || tob_isR)) 1561 { 1562 if (tob.ty == Tpointer && t1b.ty == Tsarray) 1563 { 1564 // T[n] sa; 1565 // cast(U*)sa; // ==> cast(U*)sa.ptr; 1566 result = new AddrExp(e.loc, e); 1567 result.type = t; 1568 return; 1569 } 1570 if (tob.ty == Tarray && t1b.ty == Tsarray) 1571 { 1572 // T[n] sa; 1573 // cast(U[])sa; // ==> cast(U[])sa[]; 1574 d_uns64 fsize = t1b.nextOf().size(); 1575 d_uns64 tsize = tob.nextOf().size(); 1576 if (((cast(TypeSArray)t1b).dim.toInteger() * fsize) % tsize != 0) 1577 { 1578 // copied from sarray_toDarray() in e2ir.c 1579 e.error("cannot cast expression %s of type %s to %s since sizes don't line up", e.toChars(), e.type.toChars(), t.toChars()); 1580 result = new ErrorExp(); 1581 return; 1582 } 1583 goto Lok; 1584 } 1585 goto Lfail; 1586 } 1587 1588 /* For references, any reinterpret casts are allowed to same 'ty' type. 1589 * T* to U* 1590 * R1 function(P1) to R2 function(P2) 1591 * R1 delegate(P1) to R2 delegate(P2) 1592 * T[] to U[] 1593 * V1[K1] to V2[K2] 1594 * class/interface A to B (will be a dynamic cast if possible) 1595 */ 1596 if (tob.ty == t1b.ty && tob_isR && t1b_isR) 1597 goto Lok; 1598 1599 // typeof(null) <-- non-null references or values 1600 if (tob.ty == Tnull && t1b.ty != Tnull) 1601 goto Lfail; // Bugzilla 14629 1602 // typeof(null) --> non-null references or arithmetic values 1603 if (t1b.ty == Tnull && tob.ty != Tnull) 1604 goto Lok; 1605 1606 // Check size mismatch of references. 1607 // Tarray and Tdelegate are (void*).sizeof*2, but others have (void*).sizeof. 1608 if (tob_isFR && t1b_isR || t1b_isFR && tob_isR) 1609 { 1610 if (tob.ty == Tpointer && t1b.ty == Tarray) 1611 { 1612 // T[] da; 1613 // cast(U*)da; // ==> cast(U*)da.ptr; 1614 goto Lok; 1615 } 1616 if (tob.ty == Tpointer && t1b.ty == Tdelegate) 1617 { 1618 // void delegate() dg; 1619 // cast(U*)dg; // ==> cast(U*)dg.ptr; 1620 // Note that it happens even when U is a Tfunction! 1621 e.deprecation("casting from %s to %s is deprecated", e.type.toChars(), t.toChars()); 1622 goto Lok; 1623 } 1624 goto Lfail; 1625 } 1626 1627 if (t1b.ty == Tvoid && tob.ty != Tvoid) 1628 { 1629 Lfail: 1630 e.error("cannot cast expression %s of type %s to %s", e.toChars(), e.type.toChars(), t.toChars()); 1631 result = new ErrorExp(); 1632 return; 1633 } 1634 1635 Lok: 1636 result = new CastExp(e.loc, e, tob); 1637 result.type = t; // Don't call semantic() 1638 //printf("Returning: %s\n", result->toChars()); 1639 } 1640 1641 override void visit(ErrorExp e) 1642 { 1643 result = e; 1644 } 1645 1646 override void visit(RealExp e) 1647 { 1648 if (!e.type.equals(t)) 1649 { 1650 if ((e.type.isreal() && t.isreal()) || (e.type.isimaginary() && t.isimaginary())) 1651 { 1652 result = e.copy(); 1653 result.type = t; 1654 } 1655 else 1656 visit(cast(Expression)e); 1657 return; 1658 } 1659 result = e; 1660 } 1661 1662 override void visit(ComplexExp e) 1663 { 1664 if (!e.type.equals(t)) 1665 { 1666 if (e.type.iscomplex() && t.iscomplex()) 1667 { 1668 result = e.copy(); 1669 result.type = t; 1670 } 1671 else 1672 visit(cast(Expression)e); 1673 return; 1674 } 1675 result = e; 1676 } 1677 1678 override void visit(NullExp e) 1679 { 1680 //printf("NullExp::castTo(t = %s) %s\n", t->toChars(), toChars()); 1681 visit(cast(Expression)e); 1682 if (result.op == TOKnull) 1683 { 1684 NullExp ex = cast(NullExp)result; 1685 ex.committed = 1; 1686 return; 1687 } 1688 } 1689 1690 override void visit(StructLiteralExp e) 1691 { 1692 visit(cast(Expression)e); 1693 if (result.op == TOKstructliteral) 1694 (cast(StructLiteralExp)result).stype = t; // commit type 1695 } 1696 1697 override void visit(StringExp e) 1698 { 1699 /* This follows copy-on-write; any changes to 'this' 1700 * will result in a copy. 1701 * The this->string member is considered immutable. 1702 */ 1703 int copied = 0; 1704 1705 //printf("StringExp::castTo(t = %s), '%s' committed = %d\n", t->toChars(), e->toChars(), e->committed); 1706 1707 if (!e.committed && t.ty == Tpointer && t.nextOf().ty == Tvoid) 1708 { 1709 e.error("cannot convert string literal to void*"); 1710 result = new ErrorExp(); 1711 return; 1712 } 1713 1714 StringExp se = e; 1715 if (!e.committed) 1716 { 1717 se = cast(StringExp)e.copy(); 1718 se.committed = 1; 1719 copied = 1; 1720 } 1721 1722 if (e.type.equals(t)) 1723 { 1724 result = se; 1725 return; 1726 } 1727 1728 Type tb = t.toBasetype(); 1729 Type typeb = e.type.toBasetype(); 1730 1731 //printf("\ttype = %s\n", e->type->toChars()); 1732 if (tb.ty == Tdelegate && typeb.ty != Tdelegate) 1733 { 1734 visit(cast(Expression)e); 1735 return; 1736 } 1737 1738 if (typeb.equals(tb)) 1739 { 1740 if (!copied) 1741 { 1742 se = cast(StringExp)e.copy(); 1743 copied = 1; 1744 } 1745 se.type = t; 1746 result = se; 1747 return; 1748 } 1749 1750 /* Handle reinterpret casts: 1751 * cast(wchar[3])"abcd"c --> [\u6261, \u6463, \u0000] 1752 * cast(wchar[2])"abcd"c --> [\u6261, \u6463] 1753 * cast(wchar[1])"abcd"c --> [\u6261] 1754 */ 1755 if (e.committed && tb.ty == Tsarray && typeb.ty == Tarray) 1756 { 1757 se = cast(StringExp)e.copy(); 1758 d_uns64 szx = tb.nextOf().size(); 1759 assert(szx <= 255); 1760 se.sz = cast(ubyte)szx; 1761 se.len = cast(size_t)(cast(TypeSArray)tb).dim.toInteger(); 1762 se.committed = 1; 1763 se.type = t; 1764 1765 /* Assure space for terminating 0 1766 */ 1767 if ((se.len + 1) * se.sz > (e.len + 1) * e.sz) 1768 { 1769 void* s = mem.xmalloc((se.len + 1) * se.sz); 1770 memcpy(s, se..string, se.len * se.sz); 1771 memset(s + se.len * se.sz, 0, se.sz); 1772 se..string = cast(char*)s; 1773 } 1774 result = se; 1775 return; 1776 } 1777 1778 if (tb.ty != Tsarray && tb.ty != Tarray && tb.ty != Tpointer) 1779 { 1780 if (!copied) 1781 { 1782 se = cast(StringExp)e.copy(); 1783 copied = 1; 1784 } 1785 goto Lcast; 1786 } 1787 if (typeb.ty != Tsarray && typeb.ty != Tarray && typeb.ty != Tpointer) 1788 { 1789 if (!copied) 1790 { 1791 se = cast(StringExp)e.copy(); 1792 copied = 1; 1793 } 1794 goto Lcast; 1795 } 1796 1797 if (typeb.nextOf().size() == tb.nextOf().size()) 1798 { 1799 if (!copied) 1800 { 1801 se = cast(StringExp)e.copy(); 1802 copied = 1; 1803 } 1804 if (tb.ty == Tsarray) 1805 goto L2; // handle possible change in static array dimension 1806 se.type = t; 1807 result = se; 1808 return; 1809 } 1810 1811 if (e.committed) 1812 goto Lcast; 1813 1814 auto X(T, U)(T tf, U tt) 1815 { 1816 return (cast(int)tf * 256 + cast(int)tt); 1817 } 1818 1819 { 1820 OutBuffer buffer; 1821 size_t newlen = 0; 1822 int tfty = typeb.nextOf().toBasetype().ty; 1823 int ttty = tb.nextOf().toBasetype().ty; 1824 switch (X(tfty, ttty)) 1825 { 1826 case X(Tchar, Tchar): 1827 case X(Twchar, Twchar): 1828 case X(Tdchar, Tdchar): 1829 break; 1830 1831 case X(Tchar, Twchar): 1832 for (size_t u = 0; u < e.len;) 1833 { 1834 dchar c; 1835 const p = utf_decodeChar(se..string, e.len, u, c); 1836 if (p) 1837 e.error("%s", p); 1838 else 1839 buffer.writeUTF16(c); 1840 } 1841 newlen = buffer.offset / 2; 1842 buffer.writeUTF16(0); 1843 goto L1; 1844 1845 case X(Tchar, Tdchar): 1846 for (size_t u = 0; u < e.len;) 1847 { 1848 dchar c; 1849 const p = utf_decodeChar(se..string, e.len, u, c); 1850 if (p) 1851 e.error("%s", p); 1852 buffer.write4(c); 1853 newlen++; 1854 } 1855 buffer.write4(0); 1856 goto L1; 1857 1858 case X(Twchar, Tchar): 1859 for (size_t u = 0; u < e.len;) 1860 { 1861 dchar c; 1862 const p = utf_decodeWchar(se.wstring, e.len, u, c); 1863 if (p) 1864 e.error("%s", p); 1865 else 1866 buffer.writeUTF8(c); 1867 } 1868 newlen = buffer.offset; 1869 buffer.writeUTF8(0); 1870 goto L1; 1871 1872 case X(Twchar, Tdchar): 1873 for (size_t u = 0; u < e.len;) 1874 { 1875 dchar c; 1876 const p = utf_decodeWchar(se.wstring, e.len, u, c); 1877 if (p) 1878 e.error("%s", p); 1879 buffer.write4(c); 1880 newlen++; 1881 } 1882 buffer.write4(0); 1883 goto L1; 1884 1885 case X(Tdchar, Tchar): 1886 for (size_t u = 0; u < e.len; u++) 1887 { 1888 uint c = se.dstring[u]; 1889 if (!utf_isValidDchar(c)) 1890 e.error("invalid UCS-32 char \\U%08x", c); 1891 else 1892 buffer.writeUTF8(c); 1893 newlen++; 1894 } 1895 newlen = buffer.offset; 1896 buffer.writeUTF8(0); 1897 goto L1; 1898 1899 case X(Tdchar, Twchar): 1900 for (size_t u = 0; u < e.len; u++) 1901 { 1902 uint c = se.dstring[u]; 1903 if (!utf_isValidDchar(c)) 1904 e.error("invalid UCS-32 char \\U%08x", c); 1905 else 1906 buffer.writeUTF16(c); 1907 newlen++; 1908 } 1909 newlen = buffer.offset / 2; 1910 buffer.writeUTF16(0); 1911 goto L1; 1912 1913 L1: 1914 if (!copied) 1915 { 1916 se = cast(StringExp)e.copy(); 1917 copied = 1; 1918 } 1919 se..string = buffer.extractData(); 1920 se.len = newlen; 1921 1922 { 1923 d_uns64 szx = tb.nextOf().size(); 1924 assert(szx <= 255); 1925 se.sz = cast(ubyte)szx; 1926 } 1927 break; 1928 1929 default: 1930 assert(typeb.nextOf().size() != tb.nextOf().size()); 1931 goto Lcast; 1932 } 1933 } 1934 L2: 1935 assert(copied); 1936 1937 // See if need to truncate or extend the literal 1938 if (tb.ty == Tsarray) 1939 { 1940 size_t dim2 = cast(size_t)(cast(TypeSArray)tb).dim.toInteger(); 1941 //printf("dim from = %d, to = %d\n", (int)se->len, (int)dim2); 1942 1943 // Changing dimensions 1944 if (dim2 != se.len) 1945 { 1946 // Copy when changing the string literal 1947 size_t newsz = se.sz; 1948 size_t d = (dim2 < se.len) ? dim2 : se.len; 1949 void* s = mem.xmalloc((dim2 + 1) * newsz); 1950 memcpy(s, se..string, d * newsz); 1951 // Extend with 0, add terminating 0 1952 memset(s + d * newsz, 0, (dim2 + 1 - d) * newsz); 1953 se..string = cast(char*)s; 1954 se.len = dim2; 1955 } 1956 } 1957 se.type = t; 1958 result = se; 1959 return; 1960 1961 Lcast: 1962 result = new CastExp(e.loc, se, t); 1963 result.type = t; // so semantic() won't be run on e 1964 } 1965 1966 override void visit(AddrExp e) 1967 { 1968 version (none) 1969 { 1970 printf("AddrExp::castTo(this=%s, type=%s, t=%s)\n", e.toChars(), e.type.toChars(), t.toChars()); 1971 } 1972 result = e; 1973 1974 Type tb = t.toBasetype(); 1975 Type typeb = e.type.toBasetype(); 1976 1977 if (tb.equals(typeb)) 1978 { 1979 result = e.copy(); 1980 result.type = t; 1981 return; 1982 } 1983 1984 // Look for pointers to functions where the functions are overloaded. 1985 if (e.e1.op == TOKoverloadset && 1986 (tb.ty == Tpointer || tb.ty == Tdelegate) && tb.nextOf().ty == Tfunction) 1987 { 1988 OverExp eo = cast(OverExp)e.e1; 1989 FuncDeclaration f = null; 1990 for (size_t i = 0; i < eo.vars.a.dim; i++) 1991 { 1992 auto s = eo.vars.a[i]; 1993 auto f2 = s.isFuncDeclaration(); 1994 assert(f2); 1995 if (f2.overloadExactMatch(tb.nextOf())) 1996 { 1997 if (f) 1998 { 1999 /* Error if match in more than one overload set, 2000 * even if one is a 'better' match than the other. 2001 */ 2002 ScopeDsymbol.multiplyDefined(e.loc, f, f2); 2003 } 2004 else 2005 f = f2; 2006 } 2007 } 2008 if (f) 2009 { 2010 f.tookAddressOf++; 2011 auto se = new SymOffExp(e.loc, f, 0, false); 2012 se.semantic(sc); 2013 // Let SymOffExp::castTo() do the heavy lifting 2014 visit(se); 2015 return; 2016 } 2017 } 2018 2019 if (e.e1.op == TOKvar && 2020 typeb.ty == Tpointer && typeb.nextOf().ty == Tfunction && 2021 tb.ty == Tpointer && tb.nextOf().ty == Tfunction) 2022 { 2023 auto ve = cast(VarExp)e.e1; 2024 auto f = ve.var.isFuncDeclaration(); 2025 if (f) 2026 { 2027 assert(f.isImportedSymbol()); 2028 f = f.overloadExactMatch(tb.nextOf()); 2029 if (f) 2030 { 2031 result = new VarExp(e.loc, f, false); 2032 result.type = f.type; 2033 result = new AddrExp(e.loc, result); 2034 result.type = t; 2035 return; 2036 } 2037 } 2038 } 2039 2040 if (auto f = isFuncAddress(e)) 2041 { 2042 if (f.checkForwardRef(e.loc)) 2043 { 2044 result = new ErrorExp(); 2045 return; 2046 } 2047 } 2048 2049 visit(cast(Expression)e); 2050 } 2051 2052 override void visit(TupleExp e) 2053 { 2054 if (e.type.equals(t)) 2055 { 2056 result = e; 2057 return; 2058 } 2059 2060 TupleExp te = cast(TupleExp)e.copy(); 2061 te.e0 = e.e0 ? e.e0.copy() : null; 2062 te.exps = e.exps.copy(); 2063 for (size_t i = 0; i < te.exps.dim; i++) 2064 { 2065 Expression ex = (*te.exps)[i]; 2066 ex = ex.castTo(sc, t); 2067 (*te.exps)[i] = ex; 2068 } 2069 result = te; 2070 2071 /* Questionable behavior: In here, result->type is not set to t. 2072 * Therefoe: 2073 * TypeTuple!(int, int) values; 2074 * auto values2 = cast(long)values; 2075 * // typeof(values2) == TypeTuple!(int, int) !! 2076 * 2077 * Only when the casted tuple is immediately expanded, it would work. 2078 * auto arr = [cast(long)values]; 2079 * // typeof(arr) == long[] 2080 */ 2081 } 2082 2083 override void visit(ArrayLiteralExp e) 2084 { 2085 version (none) 2086 { 2087 printf("ArrayLiteralExp::castTo(this=%s, type=%s, => %s)\n", e.toChars(), e.type.toChars(), t.toChars()); 2088 } 2089 if (e.type == t) 2090 { 2091 result = e; 2092 return; 2093 } 2094 ArrayLiteralExp ae = e; 2095 2096 Type tb = t.toBasetype(); 2097 Type typeb = e.type.toBasetype(); 2098 2099 if ((tb.ty == Tarray || tb.ty == Tsarray) && 2100 (typeb.ty == Tarray || typeb.ty == Tsarray)) 2101 { 2102 if (tb.nextOf().toBasetype().ty == Tvoid && typeb.nextOf().toBasetype().ty != Tvoid) 2103 { 2104 // Don't do anything to cast non-void[] to void[] 2105 } 2106 else if (typeb.ty == Tsarray && typeb.nextOf().toBasetype().ty == Tvoid) 2107 { 2108 // Don't do anything for casting void[n] to others 2109 } 2110 else 2111 { 2112 if (tb.ty == Tsarray) 2113 { 2114 TypeSArray tsa = cast(TypeSArray)tb; 2115 if (e.elements.dim != tsa.dim.toInteger()) 2116 goto L1; 2117 } 2118 2119 ae = cast(ArrayLiteralExp)e.copy(); 2120 if (e.basis) 2121 ae.basis = e.basis.castTo(sc, tb.nextOf()); 2122 ae.elements = e.elements.copy(); 2123 for (size_t i = 0; i < e.elements.dim; i++) 2124 { 2125 Expression ex = (*e.elements)[i]; 2126 if (!ex) 2127 continue; 2128 ex = ex.castTo(sc, tb.nextOf()); 2129 (*ae.elements)[i] = ex; 2130 } 2131 ae.type = t; 2132 result = ae; 2133 return; 2134 } 2135 } 2136 else if (tb.ty == Tpointer && typeb.ty == Tsarray) 2137 { 2138 Type tp = typeb.nextOf().pointerTo(); 2139 if (!tp.equals(ae.type)) 2140 { 2141 ae = cast(ArrayLiteralExp)e.copy(); 2142 ae.type = tp; 2143 } 2144 } 2145 else if (tb.ty == Tvector && (typeb.ty == Tarray || typeb.ty == Tsarray)) 2146 { 2147 // Convert array literal to vector type 2148 TypeVector tv = cast(TypeVector)tb; 2149 TypeSArray tbase = cast(TypeSArray)tv.basetype; 2150 assert(tbase.ty == Tsarray); 2151 const edim = e.elements.dim; 2152 const tbasedim = tbase.dim.toInteger(); 2153 if (edim > tbasedim) 2154 goto L1; 2155 2156 ae = cast(ArrayLiteralExp)e.copy(); 2157 ae.type = tbase; // Bugzilla 12642 2158 ae.elements = e.elements.copy(); 2159 Type telement = tv.elementType(); 2160 foreach (i; 0 .. edim) 2161 { 2162 Expression ex = (*e.elements)[i]; 2163 ex = ex.castTo(sc, telement); 2164 (*ae.elements)[i] = ex; 2165 } 2166 // Fill in the rest with the default initializer 2167 ae.elements.setDim(cast(size_t)tbasedim); 2168 foreach (i; edim .. cast(size_t)tbasedim) 2169 { 2170 Expression ex = typeb.nextOf.defaultInitLiteral(e.loc); 2171 ex = ex.castTo(sc, telement); 2172 (*ae.elements)[i] = ex; 2173 } 2174 Expression ev = new VectorExp(e.loc, ae, tb); 2175 ev = ev.semantic(sc); 2176 result = ev; 2177 return; 2178 } 2179 L1: 2180 visit(cast(Expression)ae); 2181 } 2182 2183 override void visit(AssocArrayLiteralExp e) 2184 { 2185 if (e.type == t) 2186 { 2187 result = e; 2188 return; 2189 } 2190 2191 Type tb = t.toBasetype(); 2192 Type typeb = e.type.toBasetype(); 2193 2194 if (tb.ty == Taarray && typeb.ty == Taarray && 2195 tb.nextOf().toBasetype().ty != Tvoid) 2196 { 2197 AssocArrayLiteralExp ae = cast(AssocArrayLiteralExp)e.copy(); 2198 ae.keys = e.keys.copy(); 2199 ae.values = e.values.copy(); 2200 assert(e.keys.dim == e.values.dim); 2201 for (size_t i = 0; i < e.keys.dim; i++) 2202 { 2203 Expression ex = (*e.values)[i]; 2204 ex = ex.castTo(sc, tb.nextOf()); 2205 (*ae.values)[i] = ex; 2206 2207 ex = (*e.keys)[i]; 2208 ex = ex.castTo(sc, (cast(TypeAArray)tb).index); 2209 (*ae.keys)[i] = ex; 2210 } 2211 ae.type = t; 2212 result = ae; 2213 return; 2214 } 2215 visit(cast(Expression)e); 2216 } 2217 2218 override void visit(SymOffExp e) 2219 { 2220 version (none) 2221 { 2222 printf("SymOffExp::castTo(this=%s, type=%s, t=%s)\n", e.toChars(), e.type.toChars(), t.toChars()); 2223 } 2224 if (e.type == t && !e.hasOverloads) 2225 { 2226 result = e; 2227 return; 2228 } 2229 2230 Type tb = t.toBasetype(); 2231 Type typeb = e.type.toBasetype(); 2232 2233 if (tb.equals(typeb)) 2234 { 2235 result = e.copy(); 2236 result.type = t; 2237 (cast(SymOffExp)result).hasOverloads = false; 2238 return; 2239 } 2240 2241 // Look for pointers to functions where the functions are overloaded. 2242 if (e.hasOverloads && 2243 typeb.ty == Tpointer && typeb.nextOf().ty == Tfunction && 2244 (tb.ty == Tpointer || tb.ty == Tdelegate) && tb.nextOf().ty == Tfunction) 2245 { 2246 FuncDeclaration f = e.var.isFuncDeclaration(); 2247 f = f ? f.overloadExactMatch(tb.nextOf()) : null; 2248 if (f) 2249 { 2250 if (tb.ty == Tdelegate) 2251 { 2252 if (f.needThis() && hasThis(sc)) 2253 { 2254 result = new DelegateExp(e.loc, new ThisExp(e.loc), f, false); 2255 result = result.semantic(sc); 2256 } 2257 else if (f.isNested()) 2258 { 2259 result = new DelegateExp(e.loc, new IntegerExp(0), f, false); 2260 result = result.semantic(sc); 2261 } 2262 else if (f.needThis()) 2263 { 2264 e.error("no 'this' to create delegate for %s", f.toChars()); 2265 result = new ErrorExp(); 2266 return; 2267 } 2268 else 2269 { 2270 e.error("cannot cast from function pointer to delegate"); 2271 result = new ErrorExp(); 2272 return; 2273 } 2274 } 2275 else 2276 { 2277 result = new SymOffExp(e.loc, f, 0, false); 2278 result.type = t; 2279 } 2280 f.tookAddressOf++; 2281 return; 2282 } 2283 } 2284 2285 if (auto f = isFuncAddress(e)) 2286 { 2287 if (f.checkForwardRef(e.loc)) 2288 { 2289 result = new ErrorExp(); 2290 return; 2291 } 2292 } 2293 2294 visit(cast(Expression)e); 2295 } 2296 2297 override void visit(DelegateExp e) 2298 { 2299 version (none) 2300 { 2301 printf("DelegateExp::castTo(this=%s, type=%s, t=%s)\n", e.toChars(), e.type.toChars(), t.toChars()); 2302 } 2303 static __gshared const(char)* msg = "cannot form delegate due to covariant return type"; 2304 2305 Type tb = t.toBasetype(); 2306 Type typeb = e.type.toBasetype(); 2307 2308 if (tb.equals(typeb) && !e.hasOverloads) 2309 { 2310 int offset; 2311 e.func.tookAddressOf++; 2312 if (e.func.tintro && e.func.tintro.nextOf().isBaseOf(e.func.type.nextOf(), &offset) && offset) 2313 e.error("%s", msg); 2314 result = e.copy(); 2315 result.type = t; 2316 return; 2317 } 2318 2319 // Look for delegates to functions where the functions are overloaded. 2320 if (typeb.ty == Tdelegate && tb.ty == Tdelegate) 2321 { 2322 if (e.func) 2323 { 2324 auto f = e.func.overloadExactMatch(tb.nextOf()); 2325 if (f) 2326 { 2327 int offset; 2328 if (f.tintro && f.tintro.nextOf().isBaseOf(f.type.nextOf(), &offset) && offset) 2329 e.error("%s", msg); 2330 if (f != e.func) // if address not already marked as taken 2331 f.tookAddressOf++; 2332 result = new DelegateExp(e.loc, e.e1, f, false); 2333 result.type = t; 2334 return; 2335 } 2336 if (e.func.tintro) 2337 e.error("%s", msg); 2338 } 2339 } 2340 2341 if (auto f = isFuncAddress(e)) 2342 { 2343 if (f.checkForwardRef(e.loc)) 2344 { 2345 result = new ErrorExp(); 2346 return; 2347 } 2348 } 2349 2350 visit(cast(Expression)e); 2351 } 2352 2353 override void visit(FuncExp e) 2354 { 2355 //printf("FuncExp::castTo type = %s, t = %s\n", e->type->toChars(), t->toChars()); 2356 FuncExp fe; 2357 if (e.matchType(t, sc, &fe, 1) > MATCHnomatch) 2358 { 2359 result = fe; 2360 return; 2361 } 2362 visit(cast(Expression)e); 2363 } 2364 2365 override void visit(CondExp e) 2366 { 2367 if (!e.type.equals(t)) 2368 { 2369 result = new CondExp(e.loc, e.econd, e.e1.castTo(sc, t), e.e2.castTo(sc, t)); 2370 result.type = t; 2371 return; 2372 } 2373 result = e; 2374 } 2375 2376 override void visit(CommaExp e) 2377 { 2378 Expression e2c = e.e2.castTo(sc, t); 2379 2380 if (e2c != e.e2) 2381 { 2382 result = new CommaExp(e.loc, e.e1, e2c); 2383 result.type = e2c.type; 2384 } 2385 else 2386 { 2387 result = e; 2388 result.type = e.e2.type; 2389 } 2390 } 2391 2392 override void visit(SliceExp e) 2393 { 2394 //printf("SliceExp::castTo e = %s, type = %s, t = %s\n", e->toChars(), e->type->toChars(), t->toChars()); 2395 2396 Type tb = t.toBasetype(); 2397 Type typeb = e.type.toBasetype(); 2398 2399 if (e.type.equals(t) || typeb.ty != Tarray || 2400 (tb.ty != Tarray && tb.ty != Tsarray)) 2401 { 2402 visit(cast(Expression)e); 2403 return; 2404 } 2405 2406 if (tb.ty == Tarray) 2407 { 2408 if (typeb.nextOf().equivalent(tb.nextOf())) 2409 { 2410 // T[] to const(T)[] 2411 result = e.copy(); 2412 result.type = t; 2413 } 2414 else 2415 { 2416 visit(cast(Expression)e); 2417 } 2418 return; 2419 } 2420 2421 // Handle the cast from Tarray to Tsarray with CT-known slicing 2422 2423 TypeSArray tsa = cast(TypeSArray)toStaticArrayType(e); 2424 if (tsa && tsa.size(e.loc) == tb.size(e.loc)) 2425 { 2426 /* Match if the sarray sizes are equal: 2427 * T[a .. b] to const(T)[b-a] 2428 * T[a .. b] to U[dim] if (T.sizeof*(b-a) == U.sizeof*dim) 2429 * 2430 * If a SliceExp has Tsarray, it will become lvalue. 2431 * That's handled in SliceExp::isLvalue and toLvalue 2432 */ 2433 result = e.copy(); 2434 result.type = t; 2435 return; 2436 } 2437 if (tsa && tsa.dim.equals((cast(TypeSArray)tb).dim)) 2438 { 2439 /* Match if the dimensions are equal 2440 * with the implicit conversion of e->e1: 2441 * cast(float[2]) [2.0, 1.0, 0.0][0..2]; 2442 */ 2443 Type t1b = e.e1.type.toBasetype(); 2444 if (t1b.ty == Tsarray) 2445 t1b = tb.nextOf().sarrayOf((cast(TypeSArray)t1b).dim.toInteger()); 2446 else if (t1b.ty == Tarray) 2447 t1b = tb.nextOf().arrayOf(); 2448 else if (t1b.ty == Tpointer) 2449 t1b = tb.nextOf().pointerTo(); 2450 else 2451 assert(0); 2452 if (e.e1.implicitConvTo(t1b) > MATCHnomatch) 2453 { 2454 Expression e1x = e.e1.implicitCastTo(sc, t1b); 2455 assert(e1x.op != TOKerror); 2456 e = cast(SliceExp)e.copy(); 2457 e.e1 = e1x; 2458 e.type = t; 2459 result = e; 2460 return; 2461 } 2462 } 2463 e.error("cannot cast expression %s of type %s to %s", e.toChars(), tsa ? tsa.toChars() : e.type.toChars(), t.toChars()); 2464 result = new ErrorExp(); 2465 } 2466 } 2467 2468 scope CastTo v = new CastTo(sc, t); 2469 e.accept(v); 2470 return v.result; 2471 } 2472 2473 /**************************************** 2474 * Set type inference target 2475 * t Target type 2476 * flag 1: don't put an error when inference fails 2477 */ 2478 extern (C++) Expression inferType(Expression e, Type t, int flag = 0) 2479 { 2480 extern (C++) final class InferType : Visitor 2481 { 2482 alias visit = super.visit; 2483 public: 2484 Type t; 2485 int flag; 2486 Expression result; 2487 2488 extern (D) this(Type t, int flag) 2489 { 2490 this.t = t; 2491 this.flag = flag; 2492 } 2493 2494 override void visit(Expression e) 2495 { 2496 result = e; 2497 } 2498 2499 override void visit(ArrayLiteralExp ale) 2500 { 2501 Type tb = t.toBasetype(); 2502 if (tb.ty == Tarray || tb.ty == Tsarray) 2503 { 2504 Type tn = tb.nextOf(); 2505 if (ale.basis) 2506 ale.basis = inferType(ale.basis, tn, flag); 2507 for (size_t i = 0; i < ale.elements.dim; i++) 2508 { 2509 Expression e = (*ale.elements)[i]; 2510 if (e) 2511 { 2512 e = inferType(e, tn, flag); 2513 (*ale.elements)[i] = e; 2514 } 2515 } 2516 } 2517 result = ale; 2518 } 2519 2520 override void visit(AssocArrayLiteralExp aale) 2521 { 2522 Type tb = t.toBasetype(); 2523 if (tb.ty == Taarray) 2524 { 2525 TypeAArray taa = cast(TypeAArray)tb; 2526 Type ti = taa.index; 2527 Type tv = taa.nextOf(); 2528 for (size_t i = 0; i < aale.keys.dim; i++) 2529 { 2530 Expression e = (*aale.keys)[i]; 2531 if (e) 2532 { 2533 e = inferType(e, ti, flag); 2534 (*aale.keys)[i] = e; 2535 } 2536 } 2537 for (size_t i = 0; i < aale.values.dim; i++) 2538 { 2539 Expression e = (*aale.values)[i]; 2540 if (e) 2541 { 2542 e = inferType(e, tv, flag); 2543 (*aale.values)[i] = e; 2544 } 2545 } 2546 } 2547 result = aale; 2548 } 2549 2550 override void visit(FuncExp fe) 2551 { 2552 //printf("FuncExp::inferType('%s'), to=%s\n", fe->type ? fe->type->toChars() : "null", t->toChars()); 2553 if (t.ty == Tdelegate || t.ty == Tpointer && t.nextOf().ty == Tfunction) 2554 { 2555 fe.fd.treq = t; 2556 } 2557 result = fe; 2558 } 2559 2560 override void visit(CondExp ce) 2561 { 2562 Type tb = t.toBasetype(); 2563 ce.e1 = inferType(ce.e1, tb, flag); 2564 ce.e2 = inferType(ce.e2, tb, flag); 2565 result = ce; 2566 } 2567 } 2568 2569 if (!t) 2570 return e; 2571 2572 scope InferType v = new InferType(t, flag); 2573 e.accept(v); 2574 return v.result; 2575 } 2576 2577 /**************************************** 2578 * Scale addition/subtraction to/from pointer. 2579 */ 2580 extern (C++) Expression scaleFactor(BinExp be, Scope* sc) 2581 { 2582 Type t1b = be.e1.type.toBasetype(); 2583 Type t2b = be.e2.type.toBasetype(); 2584 Expression eoff; 2585 2586 if (t1b.ty == Tpointer && t2b.isintegral()) 2587 { 2588 // Need to adjust operator by the stride 2589 // Replace (ptr + int) with (ptr + (int * stride)) 2590 Type t = Type.tptrdiff_t; 2591 2592 d_uns64 stride = t1b.nextOf().size(be.loc); 2593 if (!t.equals(t2b)) 2594 be.e2 = be.e2.castTo(sc, t); 2595 eoff = be.e2; 2596 be.e2 = new MulExp(be.loc, be.e2, new IntegerExp(Loc(), stride, t)); 2597 be.e2.type = t; 2598 be.type = be.e1.type; 2599 } 2600 else if (t2b.ty == Tpointer && t1b.isintegral()) 2601 { 2602 // Need to adjust operator by the stride 2603 // Replace (int + ptr) with (ptr + (int * stride)) 2604 Type t = Type.tptrdiff_t; 2605 Expression e; 2606 2607 d_uns64 stride = t2b.nextOf().size(be.loc); 2608 if (!t.equals(t1b)) 2609 e = be.e1.castTo(sc, t); 2610 else 2611 e = be.e1; 2612 eoff = e; 2613 e = new MulExp(be.loc, e, new IntegerExp(Loc(), stride, t)); 2614 e.type = t; 2615 be.type = be.e2.type; 2616 be.e1 = be.e2; 2617 be.e2 = e; 2618 } 2619 else 2620 assert(0); 2621 2622 if (sc.func && !sc.intypeof) 2623 { 2624 eoff = eoff.optimize(WANTvalue); 2625 if (eoff.op == TOKint64 && eoff.toInteger() == 0) 2626 { 2627 } 2628 else if (sc.func.setUnsafe()) 2629 { 2630 be.error("pointer arithmetic not allowed in @safe functions"); 2631 return new ErrorExp(); 2632 } 2633 } 2634 2635 return be; 2636 } 2637 2638 /************************************** 2639 * Return true if e is an empty array literal with dimensionality 2640 * equal to or less than type of other array. 2641 * [], [[]], [[[]]], etc. 2642 * I.e., make sure that [1,2] is compatible with [], 2643 * [[1,2]] is compatible with [[]], etc. 2644 */ 2645 extern (C++) bool isVoidArrayLiteral(Expression e, Type other) 2646 { 2647 while (e.op == TOKarrayliteral && e.type.ty == Tarray && ((cast(ArrayLiteralExp)e).elements.dim == 1)) 2648 { 2649 auto ale = cast(ArrayLiteralExp)e; 2650 e = ale.getElement(0); 2651 if (other.ty == Tsarray || other.ty == Tarray) 2652 other = other.nextOf(); 2653 else 2654 return false; 2655 } 2656 if (other.ty != Tsarray && other.ty != Tarray) 2657 return false; 2658 Type t = e.type; 2659 return (e.op == TOKarrayliteral && t.ty == Tarray && t.nextOf().ty == Tvoid && (cast(ArrayLiteralExp)e).elements.dim == 0); 2660 } 2661 2662 // used by deduceType() 2663 extern (C++) Type rawTypeMerge(Type t1, Type t2) 2664 { 2665 if (t1.equals(t2)) 2666 return t1; 2667 if (t1.equivalent(t2)) 2668 return t1.castMod(MODmerge(t1.mod, t2.mod)); 2669 2670 auto t1b = t1.toBasetype(); 2671 auto t2b = t2.toBasetype(); 2672 if (t1b.equals(t2b)) 2673 return t1b; 2674 if (t1b.equivalent(t2b)) 2675 return t1b.castMod(MODmerge(t1b.mod, t2b.mod)); 2676 2677 auto ty = cast(TY)impcnvResult[t1b.ty][t2b.ty]; 2678 if (ty != Terror) 2679 return Type.basic[ty]; 2680 2681 return null; 2682 } 2683 2684 /************************************** 2685 * Combine types. 2686 * Output: 2687 * *pt merged type, if *pt is not NULL 2688 * *pe1 rewritten e1 2689 * *pe2 rewritten e2 2690 * Returns: 2691 * true success 2692 * false failed 2693 */ 2694 extern (C++) bool typeMerge(Scope* sc, TOK op, Type* pt, Expression* pe1, Expression* pe2) 2695 { 2696 //printf("typeMerge() %s op %s\n", pe1.toChars(), pe2.toChars()); 2697 2698 MATCH m; 2699 Expression e1 = *pe1; 2700 Expression e2 = *pe2; 2701 Type t1b = e1.type.toBasetype(); 2702 Type t2b = e2.type.toBasetype(); 2703 2704 if (op != TOKquestion || t1b.ty != t2b.ty && (t1b.isTypeBasic() && t2b.isTypeBasic())) 2705 { 2706 e1 = integralPromotions(e1, sc); 2707 e2 = integralPromotions(e2, sc); 2708 } 2709 2710 Type t1 = e1.type; 2711 Type t2 = e2.type; 2712 assert(t1); 2713 Type t = t1; 2714 2715 /* The start type of alias this type recursion. 2716 * In following case, we should save A, and stop recursion 2717 * if it appears again. 2718 * X -> Y -> [A] -> B -> A -> B -> ... 2719 */ 2720 Type att1 = null; 2721 Type att2 = null; 2722 2723 //if (t1) printf("\tt1 = %s\n", t1->toChars()); 2724 //if (t2) printf("\tt2 = %s\n", t2->toChars()); 2725 debug 2726 { 2727 if (!t2) 2728 printf("\te2 = '%s'\n", e2.toChars()); 2729 } 2730 assert(t2); 2731 2732 if (t1.mod != t2.mod && 2733 t1.ty == Tenum && t2.ty == Tenum && 2734 (cast(TypeEnum)t1).sym == (cast(TypeEnum)t2).sym) 2735 { 2736 ubyte mod = MODmerge(t1.mod, t2.mod); 2737 t1 = t1.castMod(mod); 2738 t2 = t2.castMod(mod); 2739 } 2740 2741 Lagain: 2742 t1b = t1.toBasetype(); 2743 t2b = t2.toBasetype(); 2744 2745 TY ty = cast(TY)impcnvResult[t1b.ty][t2b.ty]; 2746 if (ty != Terror) 2747 { 2748 TY ty1 = cast(TY)impcnvType1[t1b.ty][t2b.ty]; 2749 TY ty2 = cast(TY)impcnvType2[t1b.ty][t2b.ty]; 2750 2751 if (t1b.ty == ty1) // if no promotions 2752 { 2753 if (t1.equals(t2)) 2754 { 2755 t = t1; 2756 goto Lret; 2757 } 2758 2759 if (t1b.equals(t2b)) 2760 { 2761 t = t1b; 2762 goto Lret; 2763 } 2764 } 2765 2766 t = Type.basic[ty]; 2767 2768 t1 = Type.basic[ty1]; 2769 t2 = Type.basic[ty2]; 2770 e1 = e1.castTo(sc, t1); 2771 e2 = e2.castTo(sc, t2); 2772 //printf("after typeCombine():\n"); 2773 //print(); 2774 //printf("ty = %d, ty1 = %d, ty2 = %d\n", ty, ty1, ty2); 2775 goto Lret; 2776 } 2777 2778 t1 = t1b; 2779 t2 = t2b; 2780 2781 if (t1.ty == Ttuple || t2.ty == Ttuple) 2782 goto Lincompatible; 2783 2784 if (t1.equals(t2)) 2785 { 2786 // merging can not result in new enum type 2787 if (t.ty == Tenum) 2788 t = t1b; 2789 } 2790 else if ((t1.ty == Tpointer && t2.ty == Tpointer) || (t1.ty == Tdelegate && t2.ty == Tdelegate)) 2791 { 2792 // Bring pointers to compatible type 2793 Type t1n = t1.nextOf(); 2794 Type t2n = t2.nextOf(); 2795 2796 if (t1n.equals(t2n)) 2797 { 2798 } 2799 else if (t1n.ty == Tvoid) // pointers to void are always compatible 2800 t = t2; 2801 else if (t2n.ty == Tvoid) 2802 { 2803 } 2804 else if (t1.implicitConvTo(t2)) 2805 { 2806 goto Lt2; 2807 } 2808 else if (t2.implicitConvTo(t1)) 2809 { 2810 goto Lt1; 2811 } 2812 else if (t1n.ty == Tfunction && t2n.ty == Tfunction) 2813 { 2814 TypeFunction tf1 = cast(TypeFunction)t1n; 2815 TypeFunction tf2 = cast(TypeFunction)t2n; 2816 tf1.purityLevel(); 2817 tf2.purityLevel(); 2818 2819 TypeFunction d = cast(TypeFunction)tf1.syntaxCopy(); 2820 2821 if (tf1.purity != tf2.purity) 2822 d.purity = PUREimpure; 2823 assert(d.purity != PUREfwdref); 2824 2825 d.isnothrow = (tf1.isnothrow && tf2.isnothrow); 2826 d.isnogc = (tf1.isnogc && tf2.isnogc); 2827 2828 if (tf1.trust == tf2.trust) 2829 d.trust = tf1.trust; 2830 else if (tf1.trust <= TRUSTsystem || tf2.trust <= TRUSTsystem) 2831 d.trust = TRUSTsystem; 2832 else 2833 d.trust = TRUSTtrusted; 2834 2835 Type tx = null; 2836 if (t1.ty == Tdelegate) 2837 { 2838 tx = new TypeDelegate(d); 2839 } 2840 else 2841 tx = d.pointerTo(); 2842 2843 tx = tx.semantic(e1.loc, sc); 2844 2845 if (t1.implicitConvTo(tx) && t2.implicitConvTo(tx)) 2846 { 2847 t = tx; 2848 e1 = e1.castTo(sc, t); 2849 e2 = e2.castTo(sc, t); 2850 goto Lret; 2851 } 2852 goto Lincompatible; 2853 } 2854 else if (t1n.mod != t2n.mod) 2855 { 2856 if (!t1n.isImmutable() && !t2n.isImmutable() && t1n.isShared() != t2n.isShared()) 2857 goto Lincompatible; 2858 ubyte mod = MODmerge(t1n.mod, t2n.mod); 2859 t1 = t1n.castMod(mod).pointerTo(); 2860 t2 = t2n.castMod(mod).pointerTo(); 2861 t = t1; 2862 goto Lagain; 2863 } 2864 else if (t1n.ty == Tclass && t2n.ty == Tclass) 2865 { 2866 ClassDeclaration cd1 = t1n.isClassHandle(); 2867 ClassDeclaration cd2 = t2n.isClassHandle(); 2868 int offset; 2869 if (cd1.isBaseOf(cd2, &offset)) 2870 { 2871 if (offset) 2872 e2 = e2.castTo(sc, t); 2873 } 2874 else if (cd2.isBaseOf(cd1, &offset)) 2875 { 2876 t = t2; 2877 if (offset) 2878 e1 = e1.castTo(sc, t); 2879 } 2880 else 2881 goto Lincompatible; 2882 } 2883 else 2884 { 2885 t1 = t1n.constOf().pointerTo(); 2886 t2 = t2n.constOf().pointerTo(); 2887 if (t1.implicitConvTo(t2)) 2888 { 2889 goto Lt2; 2890 } 2891 else if (t2.implicitConvTo(t1)) 2892 { 2893 goto Lt1; 2894 } 2895 goto Lincompatible; 2896 } 2897 } 2898 else if ((t1.ty == Tsarray || t1.ty == Tarray) && (e2.op == TOKnull && t2.ty == Tpointer && t2.nextOf().ty == Tvoid || e2.op == TOKarrayliteral && t2.ty == Tsarray && t2.nextOf().ty == Tvoid && (cast(TypeSArray)t2).dim.toInteger() == 0 || isVoidArrayLiteral(e2, t1))) 2899 { 2900 /* (T[n] op void*) => T[] 2901 * (T[] op void*) => T[] 2902 * (T[n] op void[0]) => T[] 2903 * (T[] op void[0]) => T[] 2904 * (T[n] op void[]) => T[] 2905 * (T[] op void[]) => T[] 2906 */ 2907 goto Lx1; 2908 } 2909 else if ((t2.ty == Tsarray || t2.ty == Tarray) && (e1.op == TOKnull && t1.ty == Tpointer && t1.nextOf().ty == Tvoid || e1.op == TOKarrayliteral && t1.ty == Tsarray && t1.nextOf().ty == Tvoid && (cast(TypeSArray)t1).dim.toInteger() == 0 || isVoidArrayLiteral(e1, t2))) 2910 { 2911 /* (void* op T[n]) => T[] 2912 * (void* op T[]) => T[] 2913 * (void[0] op T[n]) => T[] 2914 * (void[0] op T[]) => T[] 2915 * (void[] op T[n]) => T[] 2916 * (void[] op T[]) => T[] 2917 */ 2918 goto Lx2; 2919 } 2920 else if ((t1.ty == Tsarray || t1.ty == Tarray) && (m = t1.implicitConvTo(t2)) != MATCHnomatch) 2921 { 2922 // Bugzilla 7285: Tsarray op [x, y, ...] should to be Tsarray 2923 // Bugzilla 14737: Tsarray ~ [x, y, ...] should to be Tarray 2924 if (t1.ty == Tsarray && e2.op == TOKarrayliteral && op != TOKcat) 2925 goto Lt1; 2926 if (m == MATCHconst && (op == TOKaddass || op == TOKminass || op == TOKmulass || op == TOKdivass || op == TOKmodass || op == TOKpowass || op == TOKandass || op == TOKorass || op == TOKxorass)) 2927 { 2928 // Don't make the lvalue const 2929 t = t2; 2930 goto Lret; 2931 } 2932 goto Lt2; 2933 } 2934 else if ((t2.ty == Tsarray || t2.ty == Tarray) && t2.implicitConvTo(t1)) 2935 { 2936 // Bugzilla 7285 & 14737 2937 if (t2.ty == Tsarray && e1.op == TOKarrayliteral && op != TOKcat) 2938 goto Lt2; 2939 goto Lt1; 2940 } 2941 else if ((t1.ty == Tsarray || t1.ty == Tarray || t1.ty == Tpointer) && (t2.ty == Tsarray || t2.ty == Tarray || t2.ty == Tpointer) && t1.nextOf().mod != t2.nextOf().mod) 2942 { 2943 /* If one is mutable and the other invariant, then retry 2944 * with both of them as const 2945 */ 2946 Type t1n = t1.nextOf(); 2947 Type t2n = t2.nextOf(); 2948 ubyte mod; 2949 if (e1.op == TOKnull && e2.op != TOKnull) 2950 mod = t2n.mod; 2951 else if (e1.op != TOKnull && e2.op == TOKnull) 2952 mod = t1n.mod; 2953 else if (!t1n.isImmutable() && !t2n.isImmutable() && t1n.isShared() != t2n.isShared()) 2954 goto Lincompatible; 2955 else 2956 mod = MODmerge(t1n.mod, t2n.mod); 2957 2958 if (t1.ty == Tpointer) 2959 t1 = t1n.castMod(mod).pointerTo(); 2960 else 2961 t1 = t1n.castMod(mod).arrayOf(); 2962 2963 if (t2.ty == Tpointer) 2964 t2 = t2n.castMod(mod).pointerTo(); 2965 else 2966 t2 = t2n.castMod(mod).arrayOf(); 2967 t = t1; 2968 goto Lagain; 2969 } 2970 else if (t1.ty == Tclass && t2.ty == Tclass) 2971 { 2972 if (t1.mod != t2.mod) 2973 { 2974 ubyte mod; 2975 if (e1.op == TOKnull && e2.op != TOKnull) 2976 mod = t2.mod; 2977 else if (e1.op != TOKnull && e2.op == TOKnull) 2978 mod = t1.mod; 2979 else if (!t1.isImmutable() && !t2.isImmutable() && t1.isShared() != t2.isShared()) 2980 goto Lincompatible; 2981 else 2982 mod = MODmerge(t1.mod, t2.mod); 2983 t1 = t1.castMod(mod); 2984 t2 = t2.castMod(mod); 2985 t = t1; 2986 goto Lagain; 2987 } 2988 goto Lcc; 2989 } 2990 else if (t1.ty == Tclass || t2.ty == Tclass) 2991 { 2992 Lcc: 2993 while (1) 2994 { 2995 MATCH i1 = e2.implicitConvTo(t1); 2996 MATCH i2 = e1.implicitConvTo(t2); 2997 2998 if (i1 && i2) 2999 { 3000 // We have the case of class vs. void*, so pick class 3001 if (t1.ty == Tpointer) 3002 i1 = MATCHnomatch; 3003 else if (t2.ty == Tpointer) 3004 i2 = MATCHnomatch; 3005 } 3006 3007 if (i2) 3008 { 3009 e2 = e2.castTo(sc, t2); 3010 goto Lt2; 3011 } 3012 else if (i1) 3013 { 3014 e1 = e1.castTo(sc, t1); 3015 goto Lt1; 3016 } 3017 else if (t1.ty == Tclass && t2.ty == Tclass) 3018 { 3019 TypeClass tc1 = cast(TypeClass)t1; 3020 TypeClass tc2 = cast(TypeClass)t2; 3021 3022 /* Pick 'tightest' type 3023 */ 3024 ClassDeclaration cd1 = tc1.sym.baseClass; 3025 ClassDeclaration cd2 = tc2.sym.baseClass; 3026 if (cd1 && cd2) 3027 { 3028 t1 = cd1.type.castMod(t1.mod); 3029 t2 = cd2.type.castMod(t2.mod); 3030 } 3031 else if (cd1) 3032 t1 = cd1.type; 3033 else if (cd2) 3034 t2 = cd2.type; 3035 else 3036 goto Lincompatible; 3037 } 3038 else if (t1.ty == Tstruct && (cast(TypeStruct)t1).sym.aliasthis) 3039 { 3040 if (att1 && e1.type == att1) 3041 goto Lincompatible; 3042 if (!att1 && e1.type.checkAliasThisRec()) 3043 att1 = e1.type; 3044 //printf("att tmerge(c || c) e1 = %s\n", e1->type->toChars()); 3045 e1 = resolveAliasThis(sc, e1); 3046 t1 = e1.type; 3047 continue; 3048 } 3049 else if (t2.ty == Tstruct && (cast(TypeStruct)t2).sym.aliasthis) 3050 { 3051 if (att2 && e2.type == att2) 3052 goto Lincompatible; 3053 if (!att2 && e2.type.checkAliasThisRec()) 3054 att2 = e2.type; 3055 //printf("att tmerge(c || c) e2 = %s\n", e2->type->toChars()); 3056 e2 = resolveAliasThis(sc, e2); 3057 t2 = e2.type; 3058 continue; 3059 } 3060 else 3061 goto Lincompatible; 3062 } 3063 } 3064 else if (t1.ty == Tstruct && t2.ty == Tstruct) 3065 { 3066 if (t1.mod != t2.mod) 3067 { 3068 if (!t1.isImmutable() && !t2.isImmutable() && t1.isShared() != t2.isShared()) 3069 goto Lincompatible; 3070 ubyte mod = MODmerge(t1.mod, t2.mod); 3071 t1 = t1.castMod(mod); 3072 t2 = t2.castMod(mod); 3073 t = t1; 3074 goto Lagain; 3075 } 3076 3077 TypeStruct ts1 = cast(TypeStruct)t1; 3078 TypeStruct ts2 = cast(TypeStruct)t2; 3079 if (ts1.sym != ts2.sym) 3080 { 3081 if (!ts1.sym.aliasthis && !ts2.sym.aliasthis) 3082 goto Lincompatible; 3083 3084 MATCH i1 = MATCHnomatch; 3085 MATCH i2 = MATCHnomatch; 3086 3087 Expression e1b = null; 3088 Expression e2b = null; 3089 if (ts2.sym.aliasthis) 3090 { 3091 if (att2 && e2.type == att2) 3092 goto Lincompatible; 3093 if (!att2 && e2.type.checkAliasThisRec()) 3094 att2 = e2.type; 3095 //printf("att tmerge(s && s) e2 = %s\n", e2->type->toChars()); 3096 e2b = resolveAliasThis(sc, e2); 3097 i1 = e2b.implicitConvTo(t1); 3098 } 3099 if (ts1.sym.aliasthis) 3100 { 3101 if (att1 && e1.type == att1) 3102 goto Lincompatible; 3103 if (!att1 && e1.type.checkAliasThisRec()) 3104 att1 = e1.type; 3105 //printf("att tmerge(s && s) e1 = %s\n", e1->type->toChars()); 3106 e1b = resolveAliasThis(sc, e1); 3107 i2 = e1b.implicitConvTo(t2); 3108 } 3109 if (i1 && i2) 3110 goto Lincompatible; 3111 3112 if (i1) 3113 goto Lt1; 3114 else if (i2) 3115 goto Lt2; 3116 3117 if (e1b) 3118 { 3119 e1 = e1b; 3120 t1 = e1b.type.toBasetype(); 3121 } 3122 if (e2b) 3123 { 3124 e2 = e2b; 3125 t2 = e2b.type.toBasetype(); 3126 } 3127 t = t1; 3128 goto Lagain; 3129 } 3130 } 3131 else if (t1.ty == Tstruct || t2.ty == Tstruct) 3132 { 3133 if (t1.ty == Tstruct && (cast(TypeStruct)t1).sym.aliasthis) 3134 { 3135 if (att1 && e1.type == att1) 3136 goto Lincompatible; 3137 if (!att1 && e1.type.checkAliasThisRec()) 3138 att1 = e1.type; 3139 //printf("att tmerge(s || s) e1 = %s\n", e1->type->toChars()); 3140 e1 = resolveAliasThis(sc, e1); 3141 t1 = e1.type; 3142 t = t1; 3143 goto Lagain; 3144 } 3145 if (t2.ty == Tstruct && (cast(TypeStruct)t2).sym.aliasthis) 3146 { 3147 if (att2 && e2.type == att2) 3148 goto Lincompatible; 3149 if (!att2 && e2.type.checkAliasThisRec()) 3150 att2 = e2.type; 3151 //printf("att tmerge(s || s) e2 = %s\n", e2->type->toChars()); 3152 e2 = resolveAliasThis(sc, e2); 3153 t2 = e2.type; 3154 t = t2; 3155 goto Lagain; 3156 } 3157 goto Lincompatible; 3158 } 3159 else if ((e1.op == TOKstring || e1.op == TOKnull) && e1.implicitConvTo(t2)) 3160 { 3161 goto Lt2; 3162 } 3163 else if ((e2.op == TOKstring || e2.op == TOKnull) && e2.implicitConvTo(t1)) 3164 { 3165 goto Lt1; 3166 } 3167 else if (t1.ty == Tsarray && t2.ty == Tsarray && e2.implicitConvTo(t1.nextOf().arrayOf())) 3168 { 3169 Lx1: 3170 t = t1.nextOf().arrayOf(); // T[] 3171 e1 = e1.castTo(sc, t); 3172 e2 = e2.castTo(sc, t); 3173 } 3174 else if (t1.ty == Tsarray && t2.ty == Tsarray && e1.implicitConvTo(t2.nextOf().arrayOf())) 3175 { 3176 Lx2: 3177 t = t2.nextOf().arrayOf(); 3178 e1 = e1.castTo(sc, t); 3179 e2 = e2.castTo(sc, t); 3180 } 3181 else if (t1.ty == Tvector && t2.ty == Tvector) 3182 { 3183 // Bugzilla 13841, all vector types should have no common types between 3184 // different vectors, even though their sizes are same. 3185 goto Lincompatible; 3186 } 3187 else if (t1.ty == Tvector && t2.ty != Tvector && e2.implicitConvTo(t1)) 3188 { 3189 e2 = e2.castTo(sc, t1); 3190 t2 = t1; 3191 t = t1; 3192 goto Lagain; 3193 } 3194 else if (t2.ty == Tvector && t1.ty != Tvector && e1.implicitConvTo(t2)) 3195 { 3196 e1 = e1.castTo(sc, t2); 3197 t1 = t2; 3198 t = t1; 3199 goto Lagain; 3200 } 3201 else if (t1.isintegral() && t2.isintegral()) 3202 { 3203 if (t1.ty != t2.ty) 3204 { 3205 e1 = integralPromotions(e1, sc); 3206 e2 = integralPromotions(e2, sc); 3207 t1 = e1.type; 3208 t2 = e2.type; 3209 goto Lagain; 3210 } 3211 assert(t1.ty == t2.ty); 3212 if (!t1.isImmutable() && !t2.isImmutable() && t1.isShared() != t2.isShared()) 3213 goto Lincompatible; 3214 ubyte mod = MODmerge(t1.mod, t2.mod); 3215 3216 t1 = t1.castMod(mod); 3217 t2 = t2.castMod(mod); 3218 t = t1; 3219 e1 = e1.castTo(sc, t); 3220 e2 = e2.castTo(sc, t); 3221 goto Lagain; 3222 } 3223 else if (t1.ty == Tnull && t2.ty == Tnull) 3224 { 3225 ubyte mod = MODmerge(t1.mod, t2.mod); 3226 3227 t = t1.castMod(mod); 3228 e1 = e1.castTo(sc, t); 3229 e2 = e2.castTo(sc, t); 3230 goto Lret; 3231 } 3232 else if (t2.ty == Tnull && (t1.ty == Tpointer || t1.ty == Taarray || t1.ty == Tarray)) 3233 { 3234 goto Lt1; 3235 } 3236 else if (t1.ty == Tnull && (t2.ty == Tpointer || t2.ty == Taarray || t2.ty == Tarray)) 3237 { 3238 goto Lt2; 3239 } 3240 else if (t1.ty == Tarray && isBinArrayOp(op) && isArrayOpOperand(e1)) 3241 { 3242 if (e2.implicitConvTo(t1.nextOf())) 3243 { 3244 // T[] op T 3245 // T[] op cast(T)U 3246 e2 = e2.castTo(sc, t1.nextOf()); 3247 t = t1.nextOf().arrayOf(); 3248 } 3249 else if (t1.nextOf().implicitConvTo(e2.type)) 3250 { 3251 // (cast(T)U)[] op T (Bugzilla 12780) 3252 // e1 is left as U[], it will be handled in arrayOp() later. 3253 t = e2.type.arrayOf(); 3254 } 3255 else if (t2.ty == Tarray && isArrayOpOperand(e2)) 3256 { 3257 if (t1.nextOf().implicitConvTo(t2.nextOf())) 3258 { 3259 // (cast(T)U)[] op T[] (Bugzilla 12780) 3260 // e1 is left as U[], it will be handled in arrayOp() later. 3261 t = t2.nextOf().arrayOf(); 3262 } 3263 else if (t2.nextOf().implicitConvTo(t1.nextOf())) 3264 { 3265 // T[] op (cast(T)U)[] (Bugzilla 12780) 3266 // e2 is left as U[], it will be handled in arrayOp() later. 3267 t = t1.nextOf().arrayOf(); 3268 } 3269 else 3270 goto Lincompatible; 3271 } 3272 else 3273 goto Lincompatible; 3274 } 3275 else if (t2.ty == Tarray && isBinArrayOp(op) && isArrayOpOperand(e2)) 3276 { 3277 if (e1.implicitConvTo(t2.nextOf())) 3278 { 3279 // T op T[] 3280 // cast(T)U op T[] 3281 e1 = e1.castTo(sc, t2.nextOf()); 3282 t = t2.nextOf().arrayOf(); 3283 } 3284 else if (t2.nextOf().implicitConvTo(e1.type)) 3285 { 3286 // T op (cast(T)U)[] (Bugzilla 12780) 3287 // e2 is left as U[], it will be handled in arrayOp() later. 3288 t = e1.type.arrayOf(); 3289 } 3290 else 3291 goto Lincompatible; 3292 3293 //printf("test %s\n", Token::toChars(op)); 3294 e1 = e1.optimize(WANTvalue); 3295 if (isCommutative(op) && e1.isConst()) 3296 { 3297 /* Swap operands to minimize number of functions generated 3298 */ 3299 //printf("swap %s\n", Token::toChars(op)); 3300 Expression tmp = e1; 3301 e1 = e2; 3302 e2 = tmp; 3303 } 3304 } 3305 else 3306 { 3307 Lincompatible: 3308 return false; 3309 } 3310 Lret: 3311 if (!*pt) 3312 *pt = t; 3313 *pe1 = e1; 3314 *pe2 = e2; 3315 3316 version (none) 3317 { 3318 printf("-typeMerge() %s op %s\n", e1.toChars(), e2.toChars()); 3319 if (e1.type) 3320 printf("\tt1 = %s\n", e1.type.toChars()); 3321 if (e2.type) 3322 printf("\tt2 = %s\n", e2.type.toChars()); 3323 printf("\ttype = %s\n", t.toChars()); 3324 } 3325 //print(); 3326 return true; 3327 3328 Lt1: 3329 e2 = e2.castTo(sc, t1); 3330 t = t1; 3331 goto Lret; 3332 3333 Lt2: 3334 e1 = e1.castTo(sc, t2); 3335 t = t2; 3336 goto Lret; 3337 } 3338 3339 /************************************ 3340 * Bring leaves to common type. 3341 * Returns ErrorExp if error occurs. otherwise returns NULL. 3342 */ 3343 extern (C++) Expression typeCombine(BinExp be, Scope* sc) 3344 { 3345 Type t1 = be.e1.type.toBasetype(); 3346 Type t2 = be.e2.type.toBasetype(); 3347 3348 if (be.op == TOKmin || be.op == TOKadd) 3349 { 3350 // struct+struct, and class+class are errors 3351 if (t1.ty == Tstruct && t2.ty == Tstruct) 3352 goto Lerror; 3353 else if (t1.ty == Tclass && t2.ty == Tclass) 3354 goto Lerror; 3355 else if (t1.ty == Taarray && t2.ty == Taarray) 3356 goto Lerror; 3357 } 3358 3359 if (!typeMerge(sc, be.op, &be.type, &be.e1, &be.e2)) 3360 goto Lerror; 3361 3362 // If the types have no value, return an error 3363 if (be.e1.op == TOKerror) 3364 return be.e1; 3365 if (be.e2.op == TOKerror) 3366 return be.e2; 3367 return null; 3368 3369 Lerror: 3370 Expression ex = be.incompatibleTypes(); 3371 if (ex.op == TOKerror) 3372 return ex; 3373 return new ErrorExp(); 3374 } 3375 3376 /*********************************** 3377 * Do integral promotions (convertchk). 3378 * Don't convert <array of> to <pointer to> 3379 */ 3380 extern (C++) Expression integralPromotions(Expression e, Scope* sc) 3381 { 3382 //printf("integralPromotions %s %s\n", e->toChars(), e->type->toChars()); 3383 switch (e.type.toBasetype().ty) 3384 { 3385 case Tvoid: 3386 e.error("void has no value"); 3387 return new ErrorExp(); 3388 3389 case Tint8: 3390 case Tuns8: 3391 case Tint16: 3392 case Tuns16: 3393 case Tbool: 3394 case Tchar: 3395 case Twchar: 3396 e = e.castTo(sc, Type.tint32); 3397 break; 3398 3399 case Tdchar: 3400 e = e.castTo(sc, Type.tuns32); 3401 break; 3402 3403 default: 3404 break; 3405 } 3406 return e; 3407 } 3408 3409 /*********************************** 3410 * See if both types are arrays that can be compared 3411 * for equality. Return true if so. 3412 * If they are arrays, but incompatible, issue error. 3413 * This is to enable comparing things like an immutable 3414 * array with a mutable one. 3415 */ 3416 extern (C++) bool arrayTypeCompatible(Loc loc, Type t1, Type t2) 3417 { 3418 t1 = t1.toBasetype().merge2(); 3419 t2 = t2.toBasetype().merge2(); 3420 3421 if ((t1.ty == Tarray || t1.ty == Tsarray || t1.ty == Tpointer) && (t2.ty == Tarray || t2.ty == Tsarray || t2.ty == Tpointer)) 3422 { 3423 if (t1.nextOf().implicitConvTo(t2.nextOf()) < MATCHconst && t2.nextOf().implicitConvTo(t1.nextOf()) < MATCHconst && (t1.nextOf().ty != Tvoid && t2.nextOf().ty != Tvoid)) 3424 { 3425 error(loc, "array equality comparison type mismatch, %s vs %s", t1.toChars(), t2.toChars()); 3426 } 3427 return true; 3428 } 3429 return false; 3430 } 3431 3432 /*********************************** 3433 * See if both types are arrays that can be compared 3434 * for equality without any casting. Return true if so. 3435 * This is to enable comparing things like an immutable 3436 * array with a mutable one. 3437 */ 3438 extern (C++) bool arrayTypeCompatibleWithoutCasting(Loc loc, Type t1, Type t2) 3439 { 3440 t1 = t1.toBasetype(); 3441 t2 = t2.toBasetype(); 3442 3443 if ((t1.ty == Tarray || t1.ty == Tsarray || t1.ty == Tpointer) && t2.ty == t1.ty) 3444 { 3445 if (t1.nextOf().implicitConvTo(t2.nextOf()) >= MATCHconst || t2.nextOf().implicitConvTo(t1.nextOf()) >= MATCHconst) 3446 return true; 3447 } 3448 return false; 3449 } 3450 3451 /******************************************************************/ 3452 /* Determine the integral ranges of an expression. 3453 * This is used to determine if implicit narrowing conversions will 3454 * be allowed. 3455 */ 3456 extern (C++) IntRange getIntRange(Expression e) 3457 { 3458 extern (C++) final class IntRangeVisitor : Visitor 3459 { 3460 alias visit = super.visit; 3461 private: 3462 static uinteger_t getMask(uinteger_t v) 3463 { 3464 // Ref: http://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2 3465 v |= v >> 1; 3466 v |= v >> 2; 3467 v |= v >> 4; 3468 v |= v >> 8; 3469 v |= v >> 16; 3470 v |= v >> 32; 3471 return v; 3472 } 3473 3474 // The algorithms for &, |, ^ are not yet the best! Sometimes they will produce 3475 // not the tightest bound. See 3476 // https://github.com/dlang/dmd/pull/116 3477 // for detail. 3478 static IntRange unsignedBitwiseAnd(ref const(IntRange) a, ref const(IntRange) b) 3479 { 3480 // the DiffMasks stores the mask of bits which are variable in the range. 3481 uinteger_t aDiffMask = getMask(a.imin.value ^ a.imax.value); 3482 uinteger_t bDiffMask = getMask(b.imin.value ^ b.imax.value); 3483 3484 // Since '&' computes the digitwise-minimum, the we could set all varying 3485 // digits to 0 to get a lower bound, and set all varying digits to 1 to get 3486 // an upper bound. 3487 IntRange result; 3488 result.imin.value = (a.imin.value & ~aDiffMask) & (b.imin.value & ~bDiffMask); 3489 result.imax.value = (a.imax.value | aDiffMask) & (b.imax.value | bDiffMask); 3490 3491 // Sometimes the upper bound is overestimated. The upper bound will never 3492 // exceed the input. 3493 if (result.imax.value > a.imax.value) 3494 result.imax.value = a.imax.value; 3495 if (result.imax.value > b.imax.value) 3496 result.imax.value = b.imax.value; 3497 3498 result.imin.negative = result.imax.negative = a.imin.negative && b.imin.negative; 3499 return result; 3500 } 3501 3502 static IntRange unsignedBitwiseOr(ref const(IntRange) a, ref const(IntRange) b) 3503 { 3504 // the DiffMasks stores the mask of bits which are variable in the range. 3505 uinteger_t aDiffMask = getMask(a.imin.value ^ a.imax.value); 3506 uinteger_t bDiffMask = getMask(b.imin.value ^ b.imax.value); 3507 3508 // The imax algorithm by Adam D. Ruppe. 3509 // http://www.digitalmars.com/pnews/read.php?server=news.digitalmars.com&group=digitalmars.D&artnum=108796 3510 IntRange result; 3511 result.imin.value = (a.imin.value & ~aDiffMask) | (b.imin.value & ~bDiffMask); 3512 result.imax.value = a.imax.value | b.imax.value | getMask(a.imax.value & b.imax.value); 3513 3514 // Sometimes the lower bound is underestimated. The lower bound will never 3515 // less than the input. 3516 if (result.imin.value < a.imin.value) 3517 result.imin.value = a.imin.value; 3518 if (result.imin.value < b.imin.value) 3519 result.imin.value = b.imin.value; 3520 3521 result.imin.negative = result.imax.negative = a.imin.negative || b.imin.negative; 3522 return result; 3523 } 3524 3525 static IntRange unsignedBitwiseXor(ref const(IntRange) a, ref const(IntRange) b) 3526 { 3527 // the DiffMasks stores the mask of bits which are variable in the range. 3528 uinteger_t aDiffMask = getMask(a.imin.value ^ a.imax.value); 3529 uinteger_t bDiffMask = getMask(b.imin.value ^ b.imax.value); 3530 IntRange result; 3531 result.imin.value = (a.imin.value ^ b.imin.value) & ~(aDiffMask | bDiffMask); 3532 result.imax.value = (a.imax.value ^ b.imax.value) | (aDiffMask | bDiffMask); 3533 result.imin.negative = result.imax.negative = a.imin.negative != b.imin.negative; 3534 return result; 3535 } 3536 3537 public: 3538 IntRange range; 3539 3540 override void visit(Expression e) 3541 { 3542 range = IntRange.fromType(e.type); 3543 } 3544 3545 override void visit(IntegerExp e) 3546 { 3547 range = IntRange(SignExtendedNumber(e.getInteger()))._cast(e.type); 3548 } 3549 3550 override void visit(CastExp e) 3551 { 3552 range = getIntRange(e.e1)._cast(e.type); 3553 } 3554 3555 override void visit(AddExp e) 3556 { 3557 IntRange ir1 = getIntRange(e.e1); 3558 IntRange ir2 = getIntRange(e.e2); 3559 range = IntRange(ir1.imin + ir2.imin, ir1.imax + ir2.imax)._cast(e.type); 3560 } 3561 3562 override void visit(MinExp e) 3563 { 3564 IntRange ir1 = getIntRange(e.e1); 3565 IntRange ir2 = getIntRange(e.e2); 3566 range = IntRange(ir1.imin - ir2.imax, ir1.imax - ir2.imin)._cast(e.type); 3567 } 3568 3569 override void visit(DivExp e) 3570 { 3571 IntRange ir1 = getIntRange(e.e1); 3572 IntRange ir2 = getIntRange(e.e2); 3573 3574 // Should we ignore the possibility of div-by-0??? 3575 if (ir2.containsZero()) 3576 { 3577 visit(cast(Expression)e); 3578 return; 3579 } 3580 3581 // [a,b] / [c,d] = [min (a/c, a/d, b/c, b/d), max (a/c, a/d, b/c, b/d)] 3582 SignExtendedNumber[4] bdy; 3583 bdy[0] = ir1.imin / ir2.imin; 3584 bdy[1] = ir1.imin / ir2.imax; 3585 bdy[2] = ir1.imax / ir2.imin; 3586 bdy[3] = ir1.imax / ir2.imax; 3587 range = IntRange.fromNumbers4(bdy.ptr)._cast(e.type); 3588 } 3589 3590 override void visit(MulExp e) 3591 { 3592 IntRange ir1 = getIntRange(e.e1); 3593 IntRange ir2 = getIntRange(e.e2); 3594 3595 // [a,b] * [c,d] = [min (ac, ad, bc, bd), max (ac, ad, bc, bd)] 3596 SignExtendedNumber[4] bdy; 3597 bdy[0] = ir1.imin * ir2.imin; 3598 bdy[1] = ir1.imin * ir2.imax; 3599 bdy[2] = ir1.imax * ir2.imin; 3600 bdy[3] = ir1.imax * ir2.imax; 3601 range = IntRange.fromNumbers4(bdy.ptr)._cast(e.type); 3602 } 3603 3604 override void visit(ModExp e) 3605 { 3606 IntRange irNum = getIntRange(e.e1); 3607 IntRange irDen = getIntRange(e.e2).absNeg(); 3608 3609 /* 3610 due to the rules of D (C)'s % operator, we need to consider the cases 3611 separately in different range of signs. 3612 3613 case 1. [500, 1700] % [7, 23] (numerator is always positive) 3614 = [0, 22] 3615 case 2. [-500, 1700] % [7, 23] (numerator can be negative) 3616 = [-22, 22] 3617 case 3. [-1700, -500] % [7, 23] (numerator is always negative) 3618 = [-22, 0] 3619 3620 the number 22 is the maximum absolute value in the denomator's range. We 3621 don't care about divide by zero. 3622 */ 3623 3624 // Modding on 0 is invalid anyway. 3625 if (!irDen.imin.negative) 3626 { 3627 visit(cast(Expression)e); 3628 return; 3629 } 3630 3631 ++irDen.imin; 3632 irDen.imax = -irDen.imin; 3633 3634 if (!irNum.imin.negative) 3635 irNum.imin.value = 0; 3636 else if (irNum.imin < irDen.imin) 3637 irNum.imin = irDen.imin; 3638 3639 if (irNum.imax.negative) 3640 { 3641 irNum.imax.negative = false; 3642 irNum.imax.value = 0; 3643 } 3644 else if (irNum.imax > irDen.imax) 3645 irNum.imax = irDen.imax; 3646 3647 range = irNum._cast(e.type); 3648 } 3649 3650 override void visit(AndExp e) 3651 { 3652 IntRange ir1 = getIntRange(e.e1); 3653 IntRange ir2 = getIntRange(e.e2); 3654 3655 IntRange ir1neg, ir1pos, ir2neg, ir2pos; 3656 bool has1neg, has1pos, has2neg, has2pos; 3657 3658 ir1.splitBySign(ir1neg, has1neg, ir1pos, has1pos); 3659 ir2.splitBySign(ir2neg, has2neg, ir2pos, has2pos); 3660 3661 IntRange result; 3662 bool hasResult = false; 3663 if (has1pos && has2pos) 3664 result.unionOrAssign(unsignedBitwiseAnd(ir1pos, ir2pos), hasResult); 3665 if (has1pos && has2neg) 3666 result.unionOrAssign(unsignedBitwiseAnd(ir1pos, ir2neg), hasResult); 3667 if (has1neg && has2pos) 3668 result.unionOrAssign(unsignedBitwiseAnd(ir1neg, ir2pos), hasResult); 3669 if (has1neg && has2neg) 3670 result.unionOrAssign(unsignedBitwiseAnd(ir1neg, ir2neg), hasResult); 3671 3672 assert(hasResult); 3673 range = result._cast(e.type); 3674 } 3675 3676 override void visit(OrExp e) 3677 { 3678 IntRange ir1 = getIntRange(e.e1); 3679 IntRange ir2 = getIntRange(e.e2); 3680 3681 IntRange ir1neg, ir1pos, ir2neg, ir2pos; 3682 bool has1neg, has1pos, has2neg, has2pos; 3683 3684 ir1.splitBySign(ir1neg, has1neg, ir1pos, has1pos); 3685 ir2.splitBySign(ir2neg, has2neg, ir2pos, has2pos); 3686 3687 IntRange result; 3688 bool hasResult = false; 3689 if (has1pos && has2pos) 3690 result.unionOrAssign(unsignedBitwiseOr(ir1pos, ir2pos), hasResult); 3691 if (has1pos && has2neg) 3692 result.unionOrAssign(unsignedBitwiseOr(ir1pos, ir2neg), hasResult); 3693 if (has1neg && has2pos) 3694 result.unionOrAssign(unsignedBitwiseOr(ir1neg, ir2pos), hasResult); 3695 if (has1neg && has2neg) 3696 result.unionOrAssign(unsignedBitwiseOr(ir1neg, ir2neg), hasResult); 3697 3698 assert(hasResult); 3699 range = result._cast(e.type); 3700 } 3701 3702 override void visit(XorExp e) 3703 { 3704 IntRange ir1 = getIntRange(e.e1); 3705 IntRange ir2 = getIntRange(e.e2); 3706 3707 IntRange ir1neg, ir1pos, ir2neg, ir2pos; 3708 bool has1neg, has1pos, has2neg, has2pos; 3709 3710 ir1.splitBySign(ir1neg, has1neg, ir1pos, has1pos); 3711 ir2.splitBySign(ir2neg, has2neg, ir2pos, has2pos); 3712 3713 IntRange result; 3714 bool hasResult = false; 3715 if (has1pos && has2pos) 3716 result.unionOrAssign(unsignedBitwiseXor(ir1pos, ir2pos), hasResult); 3717 if (has1pos && has2neg) 3718 result.unionOrAssign(unsignedBitwiseXor(ir1pos, ir2neg), hasResult); 3719 if (has1neg && has2pos) 3720 result.unionOrAssign(unsignedBitwiseXor(ir1neg, ir2pos), hasResult); 3721 if (has1neg && has2neg) 3722 result.unionOrAssign(unsignedBitwiseXor(ir1neg, ir2neg), hasResult); 3723 3724 assert(hasResult); 3725 range = result._cast(e.type); 3726 } 3727 3728 override void visit(ShlExp e) 3729 { 3730 IntRange ir1 = getIntRange(e.e1); 3731 IntRange ir2 = getIntRange(e.e2); 3732 3733 if (ir2.imin.negative) 3734 ir2 = IntRange(SignExtendedNumber(0), SignExtendedNumber(64)); 3735 3736 SignExtendedNumber lower = ir1.imin << (ir1.imin.negative ? ir2.imax : ir2.imin); 3737 SignExtendedNumber upper = ir1.imax << (ir1.imax.negative ? ir2.imin : ir2.imax); 3738 3739 range = IntRange(lower, upper)._cast(e.type); 3740 } 3741 3742 override void visit(ShrExp e) 3743 { 3744 IntRange ir1 = getIntRange(e.e1); 3745 IntRange ir2 = getIntRange(e.e2); 3746 3747 if (ir2.imin.negative) 3748 ir2 = IntRange(SignExtendedNumber(0), SignExtendedNumber(64)); 3749 3750 SignExtendedNumber lower = ir1.imin >> (ir1.imin.negative ? ir2.imin : ir2.imax); 3751 SignExtendedNumber upper = ir1.imax >> (ir1.imax.negative ? ir2.imax : ir2.imin); 3752 3753 range = IntRange(lower, upper)._cast(e.type); 3754 } 3755 3756 override void visit(UshrExp e) 3757 { 3758 IntRange ir1 = getIntRange(e.e1).castUnsigned(e.e1.type); 3759 IntRange ir2 = getIntRange(e.e2); 3760 3761 if (ir2.imin.negative) 3762 ir2 = IntRange(SignExtendedNumber(0), SignExtendedNumber(64)); 3763 3764 range = IntRange(ir1.imin >> ir2.imax, ir1.imax >> ir2.imin)._cast(e.type); 3765 } 3766 3767 override void visit(AssignExp e) 3768 { 3769 range = getIntRange(e.e2)._cast(e.type); 3770 } 3771 3772 override void visit(CondExp e) 3773 { 3774 // No need to check e->econd; assume caller has called optimize() 3775 IntRange ir1 = getIntRange(e.e1); 3776 IntRange ir2 = getIntRange(e.e2); 3777 range = ir1.unionWith(ir2)._cast(e.type); 3778 } 3779 3780 override void visit(VarExp e) 3781 { 3782 Expression ie; 3783 VarDeclaration vd = e.var.isVarDeclaration(); 3784 if (vd && vd.range) 3785 range = vd.range._cast(e.type); 3786 else if (vd && vd._init && !vd.type.isMutable() && (ie = vd.getConstInitializer()) !is null) 3787 ie.accept(this); 3788 else 3789 visit(cast(Expression)e); 3790 } 3791 3792 override void visit(CommaExp e) 3793 { 3794 e.e2.accept(this); 3795 } 3796 3797 override void visit(ComExp e) 3798 { 3799 IntRange ir = getIntRange(e.e1); 3800 range = IntRange(SignExtendedNumber(~ir.imax.value, !ir.imax.negative), SignExtendedNumber(~ir.imin.value, !ir.imin.negative))._cast(e.type); 3801 } 3802 3803 override void visit(NegExp e) 3804 { 3805 IntRange ir = getIntRange(e.e1); 3806 range = IntRange(-ir.imax, -ir.imin)._cast(e.type); 3807 } 3808 } 3809 3810 scope IntRangeVisitor v = new IntRangeVisitor(); 3811 e.accept(v); 3812 return v.range; 3813 }