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