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