1 /** 2 * Semantic analysis of expressions. 3 * 4 * Specification: ($LINK2 https://dlang.org/spec/expression.html, Expressions) 5 * 6 * Copyright: Copyright (C) 1999-2020 by The D Language Foundation, All Rights Reserved 7 * Authors: $(LINK2 http://www.digitalmars.com, Walter Bright) 8 * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) 9 * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/expressionsem.d, _expressionsem.d) 10 * Documentation: https://dlang.org/phobos/dmd_expressionsem.html 11 * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/expressionsem.d 12 */ 13 14 module dmd.expressionsem; 15 16 import core.stdc.stdio; 17 18 import dmd.access; 19 import dmd.aggregate; 20 import dmd.aliasthis; 21 import dmd.arrayop; 22 import dmd.arraytypes; 23 import dmd.attrib; 24 import dmd.astcodegen; 25 import dmd.canthrow; 26 import dmd.chkformat; 27 import dmd.ctorflow; 28 import dmd.dscope; 29 import dmd.dsymbol; 30 import dmd.declaration; 31 import dmd.dclass; 32 import dmd.dcast; 33 import dmd.delegatize; 34 import dmd.denum; 35 import dmd.dimport; 36 import dmd.dinterpret; 37 import dmd.dmangle; 38 import dmd.dmodule; 39 import dmd.dstruct; 40 import dmd.dsymbolsem; 41 import dmd.dtemplate; 42 import dmd.errors; 43 import dmd.escape; 44 import dmd.expression; 45 import dmd.func; 46 import dmd.globals; 47 import dmd.hdrgen; 48 import dmd.id; 49 import dmd.identifier; 50 import dmd.imphint; 51 import dmd.init; 52 import dmd.initsem; 53 import dmd.inline; 54 import dmd.intrange; 55 import dmd.mtype; 56 import dmd.nspace; 57 import dmd.opover; 58 import dmd.optimize; 59 import dmd.parse; 60 import dmd.root.ctfloat; 61 import dmd.root.file; 62 import dmd.root.filename; 63 import dmd.root.outbuffer; 64 import dmd.root.rmem; 65 import dmd.root.rootobject; 66 import dmd.root.string; 67 import dmd.semantic2; 68 import dmd.semantic3; 69 import dmd.sideeffect; 70 import dmd.safe; 71 import dmd.target; 72 import dmd.tokens; 73 import dmd.traits; 74 import dmd.typesem; 75 import dmd.typinf; 76 import dmd.utf; 77 import dmd.utils; 78 import dmd.visitor; 79 80 enum LOGSEMANTIC = false; 81 82 /******************************************************** 83 * Perform semantic analysis and CTFE on expressions to produce 84 * a string. 85 * Params: 86 * buf = append generated string to buffer 87 * sc = context 88 * exps = array of Expressions 89 * Returns: 90 * true on error 91 */ 92 bool expressionsToString(ref OutBuffer buf, Scope* sc, Expressions* exps) 93 { 94 if (!exps) 95 return false; 96 97 foreach (ex; *exps) 98 { 99 if (!ex) 100 continue; 101 auto sc2 = sc.startCTFE(); 102 auto e2 = ex.expressionSemantic(sc2); 103 auto e3 = resolveProperties(sc2, e2); 104 sc2.endCTFE(); 105 106 // allowed to contain types as well as expressions 107 auto e4 = ctfeInterpretForPragmaMsg(e3); 108 if (!e4 || e4.op == TOK.error) 109 return true; 110 111 // expand tuple 112 if (auto te = e4.isTupleExp()) 113 { 114 if (expressionsToString(buf, sc, te.exps)) 115 return true; 116 continue; 117 } 118 // char literals exp `.toStringExp` return `null` but we cant override it 119 // because in most contexts we don't want the conversion to succeed. 120 IntegerExp ie = e4.isIntegerExp(); 121 const ty = (ie && ie.type) ? ie.type.ty : Terror; 122 if (ty.isSomeChar) 123 { 124 auto tsa = new TypeSArray(ie.type, IntegerExp.literal!1); 125 e4 = new ArrayLiteralExp(ex.loc, tsa, ie); 126 } 127 128 if (StringExp se = e4.toStringExp()) 129 buf.writestring(se.toUTF8(sc).peekString()); 130 else 131 buf.writestring(e4.toString()); 132 } 133 return false; 134 } 135 136 137 /*********************************************************** 138 * Resolve `exp` as a compile-time known string. 139 * Params: 140 * sc = scope 141 * exp = Expression which expected as a string 142 * s = What the string is expected for, will be used in error diagnostic. 143 * Returns: 144 * String literal, or `null` if error happens. 145 */ 146 StringExp semanticString(Scope *sc, Expression exp, const char* s) 147 { 148 sc = sc.startCTFE(); 149 exp = exp.expressionSemantic(sc); 150 exp = resolveProperties(sc, exp); 151 sc = sc.endCTFE(); 152 153 if (exp.op == TOK.error) 154 return null; 155 156 auto e = exp; 157 if (exp.type.isString()) 158 { 159 e = e.ctfeInterpret(); 160 if (e.op == TOK.error) 161 return null; 162 } 163 164 auto se = e.toStringExp(); 165 if (!se) 166 { 167 exp.error("`string` expected for %s, not `(%s)` of type `%s`", 168 s, exp.toChars(), exp.type.toChars()); 169 return null; 170 } 171 return se; 172 } 173 174 private Expression extractOpDollarSideEffect(Scope* sc, UnaExp ue) 175 { 176 Expression e0; 177 Expression e1 = Expression.extractLast(ue.e1, e0); 178 // https://issues.dlang.org/show_bug.cgi?id=12585 179 // Extract the side effect part if ue.e1 is comma. 180 181 if ((sc.flags & SCOPE.ctfe) ? hasSideEffect(e1) : !isTrivialExp(e1)) // match logic in extractSideEffect() 182 { 183 /* Even if opDollar is needed, 'e1' should be evaluate only once. So 184 * Rewrite: 185 * e1.opIndex( ... use of $ ... ) 186 * e1.opSlice( ... use of $ ... ) 187 * as: 188 * (ref __dop = e1, __dop).opIndex( ... __dop.opDollar ...) 189 * (ref __dop = e1, __dop).opSlice( ... __dop.opDollar ...) 190 */ 191 e1 = extractSideEffect(sc, "__dop", e0, e1, false); 192 assert(e1.op == TOK.variable); 193 VarExp ve = cast(VarExp)e1; 194 ve.var.storage_class |= STC.exptemp; // lifetime limited to expression 195 } 196 ue.e1 = e1; 197 return e0; 198 } 199 200 /************************************** 201 * Runs semantic on ae.arguments. Declares temporary variables 202 * if '$' was used. 203 */ 204 Expression resolveOpDollar(Scope* sc, ArrayExp ae, Expression* pe0) 205 { 206 assert(!ae.lengthVar); 207 *pe0 = null; 208 AggregateDeclaration ad = isAggregate(ae.e1.type); 209 Dsymbol slice = search_function(ad, Id.slice); 210 //printf("slice = %s %s\n", slice.kind(), slice.toChars()); 211 foreach (i, e; *ae.arguments) 212 { 213 if (i == 0) 214 *pe0 = extractOpDollarSideEffect(sc, ae); 215 216 if (e.op == TOK.interval && !(slice && slice.isTemplateDeclaration())) 217 { 218 Lfallback: 219 if (ae.arguments.dim == 1) 220 return null; 221 ae.error("multi-dimensional slicing requires template `opSlice`"); 222 return ErrorExp.get(); 223 } 224 //printf("[%d] e = %s\n", i, e.toChars()); 225 226 // Create scope for '$' variable for this dimension 227 auto sym = new ArrayScopeSymbol(sc, ae); 228 sym.parent = sc.scopesym; 229 sc = sc.push(sym); 230 ae.lengthVar = null; // Create it only if required 231 ae.currentDimension = i; // Dimension for $, if required 232 233 e = e.expressionSemantic(sc); 234 e = resolveProperties(sc, e); 235 236 if (ae.lengthVar && sc.func) 237 { 238 // If $ was used, declare it now 239 Expression de = new DeclarationExp(ae.loc, ae.lengthVar); 240 de = de.expressionSemantic(sc); 241 *pe0 = Expression.combine(*pe0, de); 242 } 243 sc = sc.pop(); 244 245 if (e.op == TOK.interval) 246 { 247 IntervalExp ie = cast(IntervalExp)e; 248 249 auto tiargs = new Objects(); 250 Expression edim = new IntegerExp(ae.loc, i, Type.tsize_t); 251 edim = edim.expressionSemantic(sc); 252 tiargs.push(edim); 253 254 auto fargs = new Expressions(2); 255 (*fargs)[0] = ie.lwr; 256 (*fargs)[1] = ie.upr; 257 258 uint xerrors = global.startGagging(); 259 sc = sc.push(); 260 FuncDeclaration fslice = resolveFuncCall(ae.loc, sc, slice, tiargs, ae.e1.type, fargs, FuncResolveFlag.quiet); 261 sc = sc.pop(); 262 global.endGagging(xerrors); 263 if (!fslice) 264 goto Lfallback; 265 266 e = new DotTemplateInstanceExp(ae.loc, ae.e1, slice.ident, tiargs); 267 e = new CallExp(ae.loc, e, fargs); 268 e = e.expressionSemantic(sc); 269 } 270 271 if (!e.type) 272 { 273 ae.error("`%s` has no value", e.toChars()); 274 e = ErrorExp.get(); 275 } 276 if (e.op == TOK.error) 277 return e; 278 279 (*ae.arguments)[i] = e; 280 } 281 return ae; 282 } 283 284 /************************************** 285 * Runs semantic on se.lwr and se.upr. Declares a temporary variable 286 * if '$' was used. 287 * Returns: 288 * ae, or ErrorExp if errors occurred 289 */ 290 Expression resolveOpDollar(Scope* sc, ArrayExp ae, IntervalExp ie, Expression* pe0) 291 { 292 //assert(!ae.lengthVar); 293 if (!ie) 294 return ae; 295 296 VarDeclaration lengthVar = ae.lengthVar; 297 bool errors = false; 298 299 // create scope for '$' 300 auto sym = new ArrayScopeSymbol(sc, ae); 301 sym.parent = sc.scopesym; 302 sc = sc.push(sym); 303 304 Expression sem(Expression e) 305 { 306 e = e.expressionSemantic(sc); 307 e = resolveProperties(sc, e); 308 if (!e.type) 309 { 310 ae.error("`%s` has no value", e.toChars()); 311 errors = true; 312 } 313 return e; 314 } 315 316 ie.lwr = sem(ie.lwr); 317 ie.upr = sem(ie.upr); 318 319 if (lengthVar != ae.lengthVar && sc.func) 320 { 321 // If $ was used, declare it now 322 Expression de = new DeclarationExp(ae.loc, ae.lengthVar); 323 de = de.expressionSemantic(sc); 324 *pe0 = Expression.combine(*pe0, de); 325 } 326 327 sc = sc.pop(); 328 329 return errors ? ErrorExp.get() : ae; 330 } 331 332 /****************************** 333 * Perform semantic() on an array of Expressions. 334 */ 335 bool arrayExpressionSemantic(Expressions* exps, Scope* sc, bool preserveErrors = false) 336 { 337 bool err = false; 338 if (exps) 339 { 340 foreach (ref e; *exps) 341 { 342 if (e) 343 { 344 auto e2 = e.expressionSemantic(sc); 345 if (e2.op == TOK.error) 346 err = true; 347 if (preserveErrors || e2.op != TOK.error) 348 e = e2; 349 } 350 } 351 } 352 return err; 353 } 354 355 /****************************** 356 * Check the tail CallExp is really property function call. 357 * Bugs: 358 * This doesn't appear to do anything. 359 */ 360 private bool checkPropertyCall(Expression e) 361 { 362 e = lastComma(e); 363 364 if (e.op == TOK.call) 365 { 366 CallExp ce = cast(CallExp)e; 367 TypeFunction tf; 368 if (ce.f) 369 { 370 tf = cast(TypeFunction)ce.f.type; 371 /* If a forward reference to ce.f, try to resolve it 372 */ 373 if (!tf.deco && ce.f.semanticRun < PASS.semanticdone) 374 { 375 ce.f.dsymbolSemantic(null); 376 tf = cast(TypeFunction)ce.f.type; 377 } 378 } 379 else if (ce.e1.type.ty == Tfunction) 380 tf = cast(TypeFunction)ce.e1.type; 381 else if (ce.e1.type.ty == Tdelegate) 382 tf = cast(TypeFunction)ce.e1.type.nextOf(); 383 else if (ce.e1.type.ty == Tpointer && ce.e1.type.nextOf().ty == Tfunction) 384 tf = cast(TypeFunction)ce.e1.type.nextOf(); 385 else 386 assert(0); 387 } 388 return false; 389 } 390 391 /****************************** 392 * Find symbol in accordance with the UFCS name look up rule 393 */ 394 private Expression searchUFCS(Scope* sc, UnaExp ue, Identifier ident) 395 { 396 //printf("searchUFCS(ident = %s)\n", ident.toChars()); 397 Loc loc = ue.loc; 398 399 // TODO: merge with Scope.search.searchScopes() 400 Dsymbol searchScopes(int flags) 401 { 402 Dsymbol s = null; 403 for (Scope* scx = sc; scx; scx = scx.enclosing) 404 { 405 if (!scx.scopesym) 406 continue; 407 if (scx.scopesym.isModule()) 408 flags |= SearchUnqualifiedModule; // tell Module.search() that SearchLocalsOnly is to be obeyed 409 s = scx.scopesym.search(loc, ident, flags); 410 if (s) 411 { 412 // overload set contains only module scope symbols. 413 if (s.isOverloadSet()) 414 break; 415 // selective/renamed imports also be picked up 416 if (AliasDeclaration ad = s.isAliasDeclaration()) 417 { 418 if (ad._import) 419 break; 420 } 421 // See only module scope symbols for UFCS target. 422 Dsymbol p = s.toParent2(); 423 if (p && p.isModule()) 424 break; 425 } 426 s = null; 427 428 // Stop when we hit a module, but keep going if that is not just under the global scope 429 if (scx.scopesym.isModule() && !(scx.enclosing && !scx.enclosing.enclosing)) 430 break; 431 } 432 return s; 433 } 434 435 int flags = 0; 436 Dsymbol s; 437 438 if (sc.flags & SCOPE.ignoresymbolvisibility) 439 flags |= IgnoreSymbolVisibility; 440 441 // First look in local scopes 442 s = searchScopes(flags | SearchLocalsOnly); 443 if (!s) 444 { 445 // Second look in imported modules 446 s = searchScopes(flags | SearchImportsOnly); 447 } 448 449 if (!s) 450 return ue.e1.type.Type.getProperty(sc, loc, ident, 0); 451 452 FuncDeclaration f = s.isFuncDeclaration(); 453 if (f) 454 { 455 TemplateDeclaration td = getFuncTemplateDecl(f); 456 if (td) 457 { 458 if (td.overroot) 459 td = td.overroot; 460 s = td; 461 } 462 } 463 464 if (ue.op == TOK.dotTemplateInstance) 465 { 466 DotTemplateInstanceExp dti = cast(DotTemplateInstanceExp)ue; 467 auto ti = Pool!TemplateInstance.make(loc, s.ident, dti.ti.tiargs); 468 if (!ti.updateTempDecl(sc, s)) 469 return ErrorExp.get(); 470 return new ScopeExp(loc, ti); 471 } 472 else 473 { 474 //printf("-searchUFCS() %s\n", s.toChars()); 475 return new DsymbolExp(loc, s); 476 } 477 } 478 479 /****************************** 480 * Pull out callable entity with UFCS. 481 */ 482 private Expression resolveUFCS(Scope* sc, CallExp ce) 483 { 484 Loc loc = ce.loc; 485 Expression eleft; 486 Expression e; 487 488 if (ce.e1.op == TOK.dotIdentifier) 489 { 490 DotIdExp die = cast(DotIdExp)ce.e1; 491 Identifier ident = die.ident; 492 493 Expression ex = die.semanticX(sc); 494 if (ex != die) 495 { 496 ce.e1 = ex; 497 return null; 498 } 499 eleft = die.e1; 500 501 Type t = eleft.type.toBasetype(); 502 if (t.ty == Tarray || t.ty == Tsarray || t.ty == Tnull || (t.isTypeBasic() && t.ty != Tvoid)) 503 { 504 /* Built-in types and arrays have no callable properties, so do shortcut. 505 * It is necessary in: e.init() 506 */ 507 } 508 else if (t.ty == Taarray) 509 { 510 if (ident == Id.remove) 511 { 512 /* Transform: 513 * aa.remove(arg) into delete aa[arg] 514 */ 515 if (!ce.arguments || ce.arguments.dim != 1) 516 { 517 ce.error("expected key as argument to `aa.remove()`"); 518 return ErrorExp.get(); 519 } 520 if (!eleft.type.isMutable()) 521 { 522 ce.error("cannot remove key from `%s` associative array `%s`", MODtoChars(t.mod), eleft.toChars()); 523 return ErrorExp.get(); 524 } 525 Expression key = (*ce.arguments)[0]; 526 key = key.expressionSemantic(sc); 527 key = resolveProperties(sc, key); 528 529 TypeAArray taa = cast(TypeAArray)t; 530 key = key.implicitCastTo(sc, taa.index); 531 532 if (key.checkValue() || key.checkSharedAccess(sc)) 533 return ErrorExp.get(); 534 535 semanticTypeInfo(sc, taa.index); 536 537 return new RemoveExp(loc, eleft, key); 538 } 539 } 540 else 541 { 542 if (Expression ey = die.semanticY(sc, 1)) 543 { 544 if (ey.op == TOK.error) 545 return ey; 546 ce.e1 = ey; 547 if (isDotOpDispatch(ey)) 548 { 549 uint errors = global.startGagging(); 550 e = ce.syntaxCopy().expressionSemantic(sc); 551 if (!global.endGagging(errors)) 552 return e; 553 554 // even opDispatch and UFCS must have valid arguments, 555 // so now that we've seen indication of a problem, 556 // check them for issues. 557 Expressions* originalArguments = Expression.arraySyntaxCopy(ce.arguments); 558 559 if (arrayExpressionSemantic(originalArguments, sc)) 560 return ErrorExp.get(); 561 562 /* fall down to UFCS */ 563 } 564 else 565 return null; 566 } 567 } 568 569 /* https://issues.dlang.org/show_bug.cgi?id=13953 570 * 571 * If a struct has an alias this to an associative array 572 * and remove is used on a struct instance, we have to 573 * check first if there is a remove function that can be called 574 * on the struct. If not we must check the alias this. 575 * 576 * struct A 577 * { 578 * string[string] a; 579 * alias a this; 580 * } 581 * 582 * void fun() 583 * { 584 * A s; 585 * s.remove("foo"); 586 * } 587 */ 588 const errors = global.startGagging(); 589 e = searchUFCS(sc, die, ident); 590 // if there were any errors and the identifier was remove 591 if (global.endGagging(errors)) 592 { 593 if (ident == Id.remove) 594 { 595 // check alias this 596 Expression alias_e = resolveAliasThis(sc, die.e1, 1); 597 if (alias_e && alias_e != die.e1) 598 { 599 die.e1 = alias_e; 600 CallExp ce2 = cast(CallExp)ce.syntaxCopy(); 601 ce2.e1 = die; 602 e = cast(CallExp)ce2.trySemantic(sc); 603 if (e) 604 return e; 605 } 606 } 607 // if alias this did not work out, print the initial errors 608 searchUFCS(sc, die, ident); 609 } 610 } 611 else if (ce.e1.op == TOK.dotTemplateInstance) 612 { 613 DotTemplateInstanceExp dti = cast(DotTemplateInstanceExp)ce.e1; 614 if (Expression ey = dti.semanticY(sc, 1)) 615 { 616 ce.e1 = ey; 617 return null; 618 } 619 eleft = dti.e1; 620 e = searchUFCS(sc, dti, dti.ti.name); 621 } 622 else 623 return null; 624 625 // Rewrite 626 ce.e1 = e; 627 if (!ce.arguments) 628 ce.arguments = new Expressions(); 629 ce.arguments.shift(eleft); 630 631 return null; 632 } 633 634 /****************************** 635 * Pull out property with UFCS. 636 */ 637 private Expression resolveUFCSProperties(Scope* sc, Expression e1, Expression e2 = null) 638 { 639 Loc loc = e1.loc; 640 Expression eleft; 641 Expression e; 642 643 if (e1.op == TOK.dotIdentifier) 644 { 645 DotIdExp die = cast(DotIdExp)e1; 646 eleft = die.e1; 647 e = searchUFCS(sc, die, die.ident); 648 } 649 else if (e1.op == TOK.dotTemplateInstance) 650 { 651 DotTemplateInstanceExp dti; 652 dti = cast(DotTemplateInstanceExp)e1; 653 eleft = dti.e1; 654 e = searchUFCS(sc, dti, dti.ti.name); 655 } 656 else 657 return null; 658 659 if (e is null) 660 return null; 661 662 // Rewrite 663 if (e2) 664 { 665 // run semantic without gagging 666 e2 = e2.expressionSemantic(sc); 667 668 /* f(e1) = e2 669 */ 670 Expression ex = e.copy(); 671 auto a1 = new Expressions(1); 672 (*a1)[0] = eleft; 673 ex = new CallExp(loc, ex, a1); 674 auto e1PassSemantic = ex.trySemantic(sc); 675 676 /* f(e1, e2) 677 */ 678 auto a2 = new Expressions(2); 679 (*a2)[0] = eleft; 680 (*a2)[1] = e2; 681 e = new CallExp(loc, e, a2); 682 e = e.trySemantic(sc); 683 if (!e1PassSemantic && !e) 684 { 685 /* https://issues.dlang.org/show_bug.cgi?id=20448 686 * 687 * If both versions have failed to pass semantic, 688 * f(e1) = e2 gets priority in error printing 689 * because f might be a templated function that 690 * failed to instantiate and we have to print 691 * the instantiation errors. 692 */ 693 return e1.expressionSemantic(sc); 694 } 695 else if (ex && !e) 696 { 697 checkPropertyCall(ex); 698 ex = new AssignExp(loc, ex, e2); 699 return ex.expressionSemantic(sc); 700 } 701 else 702 { 703 // strict setter prints errors if fails 704 e = e.expressionSemantic(sc); 705 } 706 checkPropertyCall(e); 707 return e; 708 } 709 else 710 { 711 /* f(e1) 712 */ 713 auto arguments = new Expressions(1); 714 (*arguments)[0] = eleft; 715 e = new CallExp(loc, e, arguments); 716 e = e.expressionSemantic(sc); 717 checkPropertyCall(e); 718 return e.expressionSemantic(sc); 719 } 720 } 721 722 /****************************** 723 * If e1 is a property function (template), resolve it. 724 */ 725 Expression resolvePropertiesOnly(Scope* sc, Expression e1) 726 { 727 //printf("e1 = %s %s\n", Token::toChars(e1.op), e1.toChars()); 728 729 Expression handleOverloadSet(OverloadSet os) 730 { 731 assert(os); 732 foreach (s; os.a) 733 { 734 auto fd = s.isFuncDeclaration(); 735 auto td = s.isTemplateDeclaration(); 736 if (fd) 737 { 738 if ((cast(TypeFunction)fd.type).isproperty) 739 return resolveProperties(sc, e1); 740 } 741 else if (td && td.onemember && (fd = td.onemember.isFuncDeclaration()) !is null) 742 { 743 if ((cast(TypeFunction)fd.type).isproperty || 744 (fd.storage_class2 & STC.property) || 745 (td._scope.stc & STC.property)) 746 return resolveProperties(sc, e1); 747 } 748 } 749 return e1; 750 } 751 752 Expression handleTemplateDecl(TemplateDeclaration td) 753 { 754 assert(td); 755 if (td.onemember) 756 { 757 if (auto fd = td.onemember.isFuncDeclaration()) 758 { 759 if ((cast(TypeFunction)fd.type).isproperty || 760 (fd.storage_class2 & STC.property) || 761 (td._scope.stc & STC.property)) 762 return resolveProperties(sc, e1); 763 } 764 } 765 return e1; 766 } 767 768 Expression handleFuncDecl(FuncDeclaration fd) 769 { 770 assert(fd); 771 if ((cast(TypeFunction)fd.type).isproperty) 772 return resolveProperties(sc, e1); 773 return e1; 774 } 775 776 if (auto de = e1.isDotExp()) 777 { 778 if (auto os = de.e2.isOverExp()) 779 return handleOverloadSet(os.vars); 780 } 781 else if (auto oe = e1.isOverExp()) 782 return handleOverloadSet(oe.vars); 783 else if (auto dti = e1.isDotTemplateInstanceExp()) 784 { 785 if (dti.ti.tempdecl) 786 if (auto td = dti.ti.tempdecl.isTemplateDeclaration()) 787 return handleTemplateDecl(td); 788 } 789 else if (auto dte = e1.isDotTemplateExp()) 790 return handleTemplateDecl(dte.td); 791 else if (e1.op == TOK.scope_) 792 { 793 Dsymbol s = (cast(ScopeExp)e1).sds; 794 TemplateInstance ti = s.isTemplateInstance(); 795 if (ti && !ti.semanticRun && ti.tempdecl) 796 if (auto td = ti.tempdecl.isTemplateDeclaration()) 797 return handleTemplateDecl(td); 798 } 799 else if (e1.op == TOK.template_) 800 return handleTemplateDecl((cast(TemplateExp)e1).td); 801 else if (e1.op == TOK.dotVariable && e1.type.ty == Tfunction) 802 { 803 DotVarExp dve = cast(DotVarExp)e1; 804 return handleFuncDecl(dve.var.isFuncDeclaration()); 805 } 806 else if (e1.op == TOK.variable && e1.type && e1.type.ty == Tfunction && (sc.intypeof || !(cast(VarExp)e1).var.needThis())) 807 return handleFuncDecl((cast(VarExp)e1).var.isFuncDeclaration()); 808 return e1; 809 } 810 811 /**************************************** 812 * Turn symbol `s` into the expression it represents. 813 * 814 * Params: 815 * s = symbol to resolve 816 * loc = location of use of `s` 817 * sc = context 818 * hasOverloads = applies if `s` represents a function. 819 * true means it's overloaded and will be resolved later, 820 * false means it's the exact function symbol. 821 * Returns: 822 * `s` turned into an expression, `ErrorExp` if an error occurred 823 */ 824 Expression symbolToExp(Dsymbol s, const ref Loc loc, Scope *sc, bool hasOverloads) 825 { 826 static if (LOGSEMANTIC) 827 { 828 printf("DsymbolExp::resolve(%s %s)\n", s.kind(), s.toChars()); 829 } 830 831 Lagain: 832 Expression e; 833 834 //printf("DsymbolExp:: %p '%s' is a symbol\n", this, toChars()); 835 //printf("s = '%s', s.kind = '%s'\n", s.toChars(), s.kind()); 836 Dsymbol olds = s; 837 Declaration d = s.isDeclaration(); 838 if (d && (d.storage_class & STC.templateparameter)) 839 { 840 s = s.toAlias(); 841 } 842 else 843 { 844 if (!s.isFuncDeclaration()) // functions are checked after overloading 845 { 846 s.checkDeprecated(loc, sc); 847 if (d) 848 d.checkDisabled(loc, sc); 849 } 850 851 // https://issues.dlang.org/show_bug.cgi?id=12023 852 // if 's' is a tuple variable, the tuple is returned. 853 s = s.toAlias(); 854 855 //printf("s = '%s', s.kind = '%s', s.needThis() = %p\n", s.toChars(), s.kind(), s.needThis()); 856 if (s != olds && !s.isFuncDeclaration()) 857 { 858 s.checkDeprecated(loc, sc); 859 if (d) 860 d.checkDisabled(loc, sc); 861 } 862 } 863 864 if (auto em = s.isEnumMember()) 865 { 866 return em.getVarExp(loc, sc); 867 } 868 if (auto v = s.isVarDeclaration()) 869 { 870 //printf("Identifier '%s' is a variable, type '%s'\n", s.toChars(), v.type.toChars()); 871 if (sc.intypeof == 1 && !v.inuse) 872 v.dsymbolSemantic(sc); 873 if (!v.type || // during variable type inference 874 !v.type.deco && v.inuse) // during variable type semantic 875 { 876 if (v.inuse) // variable type depends on the variable itself 877 error(loc, "circular reference to %s `%s`", v.kind(), v.toPrettyChars()); 878 else // variable type cannot be determined 879 error(loc, "forward reference to %s `%s`", v.kind(), v.toPrettyChars()); 880 return ErrorExp.get(); 881 } 882 if (v.type.ty == Terror) 883 return ErrorExp.get(); 884 885 if ((v.storage_class & STC.manifest) && v._init) 886 { 887 if (v.inuse) 888 { 889 error(loc, "circular initialization of %s `%s`", v.kind(), v.toPrettyChars()); 890 return ErrorExp.get(); 891 } 892 e = v.expandInitializer(loc); 893 v.inuse++; 894 e = e.expressionSemantic(sc); 895 v.inuse--; 896 return e; 897 } 898 899 // Change the ancestor lambdas to delegate before hasThis(sc) call. 900 if (v.checkNestedReference(sc, loc)) 901 return ErrorExp.get(); 902 903 if (v.needThis() && hasThis(sc)) 904 e = new DotVarExp(loc, new ThisExp(loc), v); 905 else 906 e = new VarExp(loc, v); 907 e = e.expressionSemantic(sc); 908 return e; 909 } 910 if (auto fld = s.isFuncLiteralDeclaration()) 911 { 912 //printf("'%s' is a function literal\n", fld.toChars()); 913 e = new FuncExp(loc, fld); 914 return e.expressionSemantic(sc); 915 } 916 if (auto f = s.isFuncDeclaration()) 917 { 918 f = f.toAliasFunc(); 919 if (!f.functionSemantic()) 920 return ErrorExp.get(); 921 922 if (!hasOverloads && f.checkForwardRef(loc)) 923 return ErrorExp.get(); 924 925 auto fd = s.isFuncDeclaration(); 926 fd.type = f.type; 927 return new VarExp(loc, fd, hasOverloads); 928 } 929 if (OverDeclaration od = s.isOverDeclaration()) 930 { 931 e = new VarExp(loc, od, true); 932 e.type = Type.tvoid; 933 return e; 934 } 935 if (OverloadSet o = s.isOverloadSet()) 936 { 937 //printf("'%s' is an overload set\n", o.toChars()); 938 return new OverExp(loc, o); 939 } 940 941 if (Import imp = s.isImport()) 942 { 943 if (!imp.pkg) 944 { 945 .error(loc, "forward reference of import `%s`", imp.toChars()); 946 return ErrorExp.get(); 947 } 948 auto ie = new ScopeExp(loc, imp.pkg); 949 return ie.expressionSemantic(sc); 950 } 951 if (Package pkg = s.isPackage()) 952 { 953 auto ie = new ScopeExp(loc, pkg); 954 return ie.expressionSemantic(sc); 955 } 956 if (Module mod = s.isModule()) 957 { 958 auto ie = new ScopeExp(loc, mod); 959 return ie.expressionSemantic(sc); 960 } 961 if (Nspace ns = s.isNspace()) 962 { 963 auto ie = new ScopeExp(loc, ns); 964 return ie.expressionSemantic(sc); 965 } 966 967 if (Type t = s.getType()) 968 { 969 return (new TypeExp(loc, t)).expressionSemantic(sc); 970 } 971 972 if (TupleDeclaration tup = s.isTupleDeclaration()) 973 { 974 if (tup.needThis() && hasThis(sc)) 975 e = new DotVarExp(loc, new ThisExp(loc), tup); 976 else 977 e = new TupleExp(loc, tup); 978 e = e.expressionSemantic(sc); 979 return e; 980 } 981 982 if (TemplateInstance ti = s.isTemplateInstance()) 983 { 984 ti.dsymbolSemantic(sc); 985 if (!ti.inst || ti.errors) 986 return ErrorExp.get(); 987 s = ti.toAlias(); 988 if (!s.isTemplateInstance()) 989 goto Lagain; 990 e = new ScopeExp(loc, ti); 991 e = e.expressionSemantic(sc); 992 return e; 993 } 994 if (TemplateDeclaration td = s.isTemplateDeclaration()) 995 { 996 Dsymbol p = td.toParentLocal(); 997 FuncDeclaration fdthis = hasThis(sc); 998 AggregateDeclaration ad = p ? p.isAggregateDeclaration() : null; 999 if (fdthis && ad && fdthis.isMemberLocal() == ad && (td._scope.stc & STC.static_) == 0) 1000 { 1001 e = new DotTemplateExp(loc, new ThisExp(loc), td); 1002 } 1003 else 1004 e = new TemplateExp(loc, td); 1005 e = e.expressionSemantic(sc); 1006 return e; 1007 } 1008 1009 .error(loc, "%s `%s` is not a variable", s.kind(), s.toChars()); 1010 return ErrorExp.get(); 1011 } 1012 1013 /************************************************************* 1014 * Given var, get the 1015 * right `this` pointer if var is in an outer class, but our 1016 * existing `this` pointer is in an inner class. 1017 * Params: 1018 * loc = location to use for error messages 1019 * sc = context 1020 * ad = struct or class we need the correct `this` for 1021 * e1 = existing `this` 1022 * var = the specific member of ad we're accessing 1023 * flag = if true, return `null` instead of throwing an error 1024 * Returns: 1025 * Expression representing the `this` for the var 1026 */ 1027 private Expression getRightThis(const ref Loc loc, Scope* sc, AggregateDeclaration ad, Expression e1, Dsymbol var, int flag = 0) 1028 { 1029 //printf("\ngetRightThis(e1 = %s, ad = %s, var = %s)\n", e1.toChars(), ad.toChars(), var.toChars()); 1030 L1: 1031 Type t = e1.type.toBasetype(); 1032 //printf("e1.type = %s, var.type = %s\n", e1.type.toChars(), var.type.toChars()); 1033 1034 if (e1.op == TOK.objcClassReference) 1035 { 1036 // We already have an Objective-C class reference, just use that as 'this'. 1037 return e1; 1038 } 1039 else if (ad && ad.isClassDeclaration && ad.isClassDeclaration.classKind == ClassKind.objc && 1040 var.isFuncDeclaration && var.isFuncDeclaration.isStatic && 1041 var.isFuncDeclaration.objc.selector) 1042 { 1043 return new ObjcClassReferenceExp(e1.loc, cast(ClassDeclaration) ad); 1044 } 1045 1046 /* Access of a member which is a template parameter in dual-scope scenario 1047 * class A { inc(alias m)() { ++m; } } // `m` needs `this` of `B` 1048 * class B {int m; inc() { new A().inc!m(); } } 1049 */ 1050 if (e1.op == TOK.this_) 1051 { 1052 FuncDeclaration f = hasThis(sc); 1053 if (f && f.isThis2) 1054 { 1055 if (f.followInstantiationContext(ad)) 1056 { 1057 e1 = new VarExp(loc, f.vthis); 1058 e1 = new PtrExp(loc, e1); 1059 e1 = new IndexExp(loc, e1, IntegerExp.literal!1); 1060 e1 = getThisSkipNestedFuncs(loc, sc, f.toParent2(), ad, e1, t, var); 1061 if (e1.op == TOK.error) 1062 return e1; 1063 goto L1; 1064 } 1065 } 1066 } 1067 1068 /* If e1 is not the 'this' pointer for ad 1069 */ 1070 if (ad && 1071 !(t.ty == Tpointer && t.nextOf().ty == Tstruct && (cast(TypeStruct)t.nextOf()).sym == ad) && 1072 !(t.ty == Tstruct && (cast(TypeStruct)t).sym == ad)) 1073 { 1074 ClassDeclaration cd = ad.isClassDeclaration(); 1075 ClassDeclaration tcd = t.isClassHandle(); 1076 1077 /* e1 is the right this if ad is a base class of e1 1078 */ 1079 if (!cd || !tcd || !(tcd == cd || cd.isBaseOf(tcd, null))) 1080 { 1081 /* Only classes can be inner classes with an 'outer' 1082 * member pointing to the enclosing class instance 1083 */ 1084 if (tcd && tcd.isNested()) 1085 { 1086 /* e1 is the 'this' pointer for an inner class: tcd. 1087 * Rewrite it as the 'this' pointer for the outer class. 1088 */ 1089 auto vthis = tcd.followInstantiationContext(ad) ? tcd.vthis2 : tcd.vthis; 1090 e1 = new DotVarExp(loc, e1, vthis); 1091 e1.type = vthis.type; 1092 e1.type = e1.type.addMod(t.mod); 1093 // Do not call ensureStaticLinkTo() 1094 //e1 = e1.semantic(sc); 1095 1096 // Skip up over nested functions, and get the enclosing 1097 // class type. 1098 e1 = getThisSkipNestedFuncs(loc, sc, tcd.toParentP(ad), ad, e1, t, var); 1099 if (e1.op == TOK.error) 1100 return e1; 1101 goto L1; 1102 } 1103 1104 /* Can't find a path from e1 to ad 1105 */ 1106 if (flag) 1107 return null; 1108 e1.error("`this` for `%s` needs to be type `%s` not type `%s`", var.toChars(), ad.toChars(), t.toChars()); 1109 return ErrorExp.get(); 1110 } 1111 } 1112 return e1; 1113 } 1114 1115 /*************************************** 1116 * Pull out any properties. 1117 */ 1118 private Expression resolvePropertiesX(Scope* sc, Expression e1, Expression e2 = null) 1119 { 1120 //printf("resolvePropertiesX, e1 = %s %s, e2 = %s\n", Token.toChars(e1.op), e1.toChars(), e2 ? e2.toChars() : null); 1121 Loc loc = e1.loc; 1122 1123 OverloadSet os; 1124 Dsymbol s; 1125 Objects* tiargs; 1126 Type tthis; 1127 if (e1.op == TOK.dot) 1128 { 1129 DotExp de = cast(DotExp)e1; 1130 if (de.e2.op == TOK.overloadSet) 1131 { 1132 tiargs = null; 1133 tthis = de.e1.type; 1134 os = (cast(OverExp)de.e2).vars; 1135 goto Los; 1136 } 1137 } 1138 else if (e1.op == TOK.overloadSet) 1139 { 1140 tiargs = null; 1141 tthis = null; 1142 os = (cast(OverExp)e1).vars; 1143 Los: 1144 assert(os); 1145 FuncDeclaration fd = null; 1146 if (e2) 1147 { 1148 e2 = e2.expressionSemantic(sc); 1149 if (e2.op == TOK.error) 1150 return ErrorExp.get(); 1151 e2 = resolveProperties(sc, e2); 1152 1153 Expressions a; 1154 a.push(e2); 1155 1156 for (size_t i = 0; i < os.a.dim; i++) 1157 { 1158 if (FuncDeclaration f = resolveFuncCall(loc, sc, os.a[i], tiargs, tthis, &a, FuncResolveFlag.quiet)) 1159 { 1160 if (f.errors) 1161 return ErrorExp.get(); 1162 fd = f; 1163 assert(fd.type.ty == Tfunction); 1164 } 1165 } 1166 if (fd) 1167 { 1168 Expression e = new CallExp(loc, e1, e2); 1169 return e.expressionSemantic(sc); 1170 } 1171 } 1172 { 1173 for (size_t i = 0; i < os.a.dim; i++) 1174 { 1175 if (FuncDeclaration f = resolveFuncCall(loc, sc, os.a[i], tiargs, tthis, null, FuncResolveFlag.quiet)) 1176 { 1177 if (f.errors) 1178 return ErrorExp.get(); 1179 fd = f; 1180 assert(fd.type.ty == Tfunction); 1181 TypeFunction tf = cast(TypeFunction)fd.type; 1182 if (!tf.isref && e2) 1183 { 1184 error(loc, "%s is not an lvalue", e1.toChars()); 1185 return ErrorExp.get(); 1186 } 1187 } 1188 } 1189 if (fd) 1190 { 1191 Expression e = new CallExp(loc, e1); 1192 if (e2) 1193 e = new AssignExp(loc, e, e2); 1194 return e.expressionSemantic(sc); 1195 } 1196 } 1197 if (e2) 1198 goto Leprop; 1199 } 1200 else if (e1.op == TOK.dotTemplateInstance) 1201 { 1202 DotTemplateInstanceExp dti = cast(DotTemplateInstanceExp)e1; 1203 if (!dti.findTempDecl(sc)) 1204 goto Leprop; 1205 if (!dti.ti.semanticTiargs(sc)) 1206 goto Leprop; 1207 tiargs = dti.ti.tiargs; 1208 tthis = dti.e1.type; 1209 if ((os = dti.ti.tempdecl.isOverloadSet()) !is null) 1210 goto Los; 1211 if ((s = dti.ti.tempdecl) !is null) 1212 goto Lfd; 1213 } 1214 else if (e1.op == TOK.dotTemplateDeclaration) 1215 { 1216 DotTemplateExp dte = cast(DotTemplateExp)e1; 1217 s = dte.td; 1218 tiargs = null; 1219 tthis = dte.e1.type; 1220 goto Lfd; 1221 } 1222 else if (e1.op == TOK.scope_) 1223 { 1224 s = (cast(ScopeExp)e1).sds; 1225 TemplateInstance ti = s.isTemplateInstance(); 1226 if (ti && !ti.semanticRun && ti.tempdecl) 1227 { 1228 //assert(ti.needsTypeInference(sc)); 1229 if (!ti.semanticTiargs(sc)) 1230 goto Leprop; 1231 tiargs = ti.tiargs; 1232 tthis = null; 1233 if ((os = ti.tempdecl.isOverloadSet()) !is null) 1234 goto Los; 1235 if ((s = ti.tempdecl) !is null) 1236 goto Lfd; 1237 } 1238 } 1239 else if (e1.op == TOK.template_) 1240 { 1241 s = (cast(TemplateExp)e1).td; 1242 tiargs = null; 1243 tthis = null; 1244 goto Lfd; 1245 } 1246 else if (e1.op == TOK.dotVariable && e1.type && e1.type.toBasetype().ty == Tfunction) 1247 { 1248 DotVarExp dve = cast(DotVarExp)e1; 1249 s = dve.var.isFuncDeclaration(); 1250 tiargs = null; 1251 tthis = dve.e1.type; 1252 goto Lfd; 1253 } 1254 else if (e1.op == TOK.variable && e1.type && e1.type.toBasetype().ty == Tfunction) 1255 { 1256 s = (cast(VarExp)e1).var.isFuncDeclaration(); 1257 tiargs = null; 1258 tthis = null; 1259 Lfd: 1260 assert(s); 1261 if (e2) 1262 { 1263 e2 = e2.expressionSemantic(sc); 1264 if (e2.op == TOK.error) 1265 return ErrorExp.get(); 1266 e2 = resolveProperties(sc, e2); 1267 1268 Expressions a; 1269 a.push(e2); 1270 1271 FuncDeclaration fd = resolveFuncCall(loc, sc, s, tiargs, tthis, &a, FuncResolveFlag.quiet); 1272 if (fd && fd.type) 1273 { 1274 if (fd.errors) 1275 return ErrorExp.get(); 1276 assert(fd.type.ty == Tfunction); 1277 Expression e = new CallExp(loc, e1, e2); 1278 return e.expressionSemantic(sc); 1279 } 1280 } 1281 { 1282 FuncDeclaration fd = resolveFuncCall(loc, sc, s, tiargs, tthis, null, FuncResolveFlag.quiet); 1283 if (fd && fd.type) 1284 { 1285 if (fd.errors) 1286 return ErrorExp.get(); 1287 assert(fd.type.ty == Tfunction); 1288 TypeFunction tf = cast(TypeFunction)fd.type; 1289 if (!e2 || tf.isref) 1290 { 1291 Expression e = new CallExp(loc, e1); 1292 if (e2) 1293 e = new AssignExp(loc, e, e2); 1294 return e.expressionSemantic(sc); 1295 } 1296 } 1297 } 1298 if (FuncDeclaration fd = s.isFuncDeclaration()) 1299 { 1300 // Keep better diagnostic message for invalid property usage of functions 1301 assert(fd.type.ty == Tfunction); 1302 Expression e = new CallExp(loc, e1, e2); 1303 return e.expressionSemantic(sc); 1304 } 1305 if (e2) 1306 goto Leprop; 1307 } 1308 if (e1.op == TOK.variable) 1309 { 1310 VarExp ve = cast(VarExp)e1; 1311 VarDeclaration v = ve.var.isVarDeclaration(); 1312 if (v && ve.checkPurity(sc, v)) 1313 return ErrorExp.get(); 1314 } 1315 if (e2) 1316 return null; 1317 1318 if (e1.type && e1.op != TOK.type) // function type is not a property 1319 { 1320 /* Look for e1 being a lazy parameter; rewrite as delegate call 1321 * only if the symbol wasn't already treated as a delegate 1322 */ 1323 auto ve = e1.isVarExp(); 1324 if (ve && ve.var.storage_class & STC.lazy_ && !ve.delegateWasExtracted) 1325 { 1326 Expression e = new CallExp(loc, e1); 1327 return e.expressionSemantic(sc); 1328 } 1329 else if (e1.op == TOK.dotVariable) 1330 { 1331 // Check for reading overlapped pointer field in @safe code. 1332 if (checkUnsafeAccess(sc, e1, true, true)) 1333 return ErrorExp.get(); 1334 } 1335 else if (e1.op == TOK.dot) 1336 { 1337 e1.error("expression has no value"); 1338 return ErrorExp.get(); 1339 } 1340 else if (e1.op == TOK.call) 1341 { 1342 CallExp ce = cast(CallExp)e1; 1343 // Check for reading overlapped pointer field in @safe code. 1344 if (checkUnsafeAccess(sc, ce.e1, true, true)) 1345 return ErrorExp.get(); 1346 } 1347 } 1348 1349 if (!e1.type) 1350 { 1351 error(loc, "cannot resolve type for %s", e1.toChars()); 1352 e1 = ErrorExp.get(); 1353 } 1354 return e1; 1355 1356 Leprop: 1357 error(loc, "not a property %s", e1.toChars()); 1358 return ErrorExp.get(); 1359 } 1360 1361 extern (C++) Expression resolveProperties(Scope* sc, Expression e) 1362 { 1363 //printf("resolveProperties(%s)\n", e.toChars()); 1364 e = resolvePropertiesX(sc, e); 1365 if (e.checkRightThis(sc)) 1366 return ErrorExp.get(); 1367 return e; 1368 } 1369 1370 /**************************************** 1371 * The common type is determined by applying ?: to each pair. 1372 * Output: 1373 * exps[] properties resolved, implicitly cast to common type, rewritten in place 1374 * *pt if pt is not NULL, set to the common type 1375 * Returns: 1376 * true a semantic error was detected 1377 */ 1378 private bool arrayExpressionToCommonType(Scope* sc, Expressions* exps, Type* pt) 1379 { 1380 /* Still have a problem with: 1381 * ubyte[][] = [ cast(ubyte[])"hello", [1]]; 1382 * which works if the array literal is initialized top down with the ubyte[][] 1383 * type, but fails with this function doing bottom up typing. 1384 */ 1385 1386 //printf("arrayExpressionToCommonType()\n"); 1387 scope IntegerExp integerexp = IntegerExp.literal!0; 1388 scope CondExp condexp = new CondExp(Loc.initial, integerexp, null, null); 1389 1390 Type t0 = null; 1391 Expression e0 = null; 1392 size_t j0 = ~0; 1393 bool foundType; 1394 1395 for (size_t i = 0; i < exps.dim; i++) 1396 { 1397 Expression e = (*exps)[i]; 1398 if (!e) 1399 continue; 1400 1401 e = resolveProperties(sc, e); 1402 if (!e.type) 1403 { 1404 e.error("`%s` has no value", e.toChars()); 1405 t0 = Type.terror; 1406 continue; 1407 } 1408 if (e.op == TOK.type) 1409 { 1410 foundType = true; // do not break immediately, there might be more errors 1411 e.checkValue(); // report an error "type T has no value" 1412 t0 = Type.terror; 1413 continue; 1414 } 1415 if (e.type.ty == Tvoid) 1416 { 1417 // void expressions do not concur to the determination of the common 1418 // type. 1419 continue; 1420 } 1421 if (checkNonAssignmentArrayOp(e)) 1422 { 1423 t0 = Type.terror; 1424 continue; 1425 } 1426 1427 e = doCopyOrMove(sc, e); 1428 1429 if (!foundType && t0 && !t0.equals(e.type)) 1430 { 1431 /* This applies ?: to merge the types. It's backwards; 1432 * ?: should call this function to merge types. 1433 */ 1434 condexp.type = null; 1435 condexp.e1 = e0; 1436 condexp.e2 = e; 1437 condexp.loc = e.loc; 1438 Expression ex = condexp.expressionSemantic(sc); 1439 if (ex.op == TOK.error) 1440 e = ex; 1441 else 1442 { 1443 // Convert to common type 1444 (*exps)[j0] = condexp.e1.castTo(sc, condexp.type); 1445 e = condexp.e2.castTo(sc, condexp.type); 1446 } 1447 } 1448 j0 = i; 1449 e0 = e; 1450 t0 = e.type; 1451 if (e.op != TOK.error) 1452 (*exps)[i] = e; 1453 } 1454 1455 if (!t0) 1456 t0 = Type.tvoid; // [] is typed as void[] 1457 else if (t0.ty != Terror) 1458 { 1459 for (size_t i = 0; i < exps.dim; i++) 1460 { 1461 Expression e = (*exps)[i]; 1462 if (!e) 1463 continue; 1464 1465 e = e.implicitCastTo(sc, t0); 1466 //assert(e.op != TOK.error); 1467 if (e.op == TOK.error) 1468 { 1469 /* https://issues.dlang.org/show_bug.cgi?id=13024 1470 * a workaround for the bug in typeMerge - 1471 * it should paint e1 and e2 by deduced common type, 1472 * but doesn't in this particular case. 1473 */ 1474 t0 = Type.terror; 1475 break; 1476 } 1477 (*exps)[i] = e; 1478 } 1479 } 1480 if (pt) 1481 *pt = t0; 1482 1483 return (t0 == Type.terror); 1484 } 1485 1486 private Expression opAssignToOp(const ref Loc loc, TOK op, Expression e1, Expression e2) 1487 { 1488 Expression e; 1489 switch (op) 1490 { 1491 case TOK.addAssign: 1492 e = new AddExp(loc, e1, e2); 1493 break; 1494 1495 case TOK.minAssign: 1496 e = new MinExp(loc, e1, e2); 1497 break; 1498 1499 case TOK.mulAssign: 1500 e = new MulExp(loc, e1, e2); 1501 break; 1502 1503 case TOK.divAssign: 1504 e = new DivExp(loc, e1, e2); 1505 break; 1506 1507 case TOK.modAssign: 1508 e = new ModExp(loc, e1, e2); 1509 break; 1510 1511 case TOK.andAssign: 1512 e = new AndExp(loc, e1, e2); 1513 break; 1514 1515 case TOK.orAssign: 1516 e = new OrExp(loc, e1, e2); 1517 break; 1518 1519 case TOK.xorAssign: 1520 e = new XorExp(loc, e1, e2); 1521 break; 1522 1523 case TOK.leftShiftAssign: 1524 e = new ShlExp(loc, e1, e2); 1525 break; 1526 1527 case TOK.rightShiftAssign: 1528 e = new ShrExp(loc, e1, e2); 1529 break; 1530 1531 case TOK.unsignedRightShiftAssign: 1532 e = new UshrExp(loc, e1, e2); 1533 break; 1534 1535 default: 1536 assert(0); 1537 } 1538 return e; 1539 } 1540 1541 /********************* 1542 * Rewrite: 1543 * array.length op= e2 1544 * as: 1545 * array.length = array.length op e2 1546 * or: 1547 * auto tmp = &array; 1548 * (*tmp).length = (*tmp).length op e2 1549 */ 1550 private Expression rewriteOpAssign(BinExp exp) 1551 { 1552 Expression e; 1553 1554 assert(exp.e1.op == TOK.arrayLength); 1555 ArrayLengthExp ale = cast(ArrayLengthExp)exp.e1; 1556 if (ale.e1.op == TOK.variable) 1557 { 1558 e = opAssignToOp(exp.loc, exp.op, ale, exp.e2); 1559 e = new AssignExp(exp.loc, ale.syntaxCopy(), e); 1560 } 1561 else 1562 { 1563 /* auto tmp = &array; 1564 * (*tmp).length = (*tmp).length op e2 1565 */ 1566 auto tmp = copyToTemp(0, "__arraylength", new AddrExp(ale.loc, ale.e1)); 1567 1568 Expression e1 = new ArrayLengthExp(ale.loc, new PtrExp(ale.loc, new VarExp(ale.loc, tmp))); 1569 Expression elvalue = e1.syntaxCopy(); 1570 e = opAssignToOp(exp.loc, exp.op, e1, exp.e2); 1571 e = new AssignExp(exp.loc, elvalue, e); 1572 e = new CommaExp(exp.loc, new DeclarationExp(ale.loc, tmp), e); 1573 } 1574 return e; 1575 } 1576 1577 /**************************************** 1578 * Preprocess arguments to function. 1579 * Input: 1580 * reportErrors whether or not to report errors here. Some callers are not 1581 * checking actual function params, so they'll do their own error reporting 1582 * Output: 1583 * exps[] tuples expanded, properties resolved, rewritten in place 1584 * Returns: 1585 * true a semantic error occurred 1586 */ 1587 private bool preFunctionParameters(Scope* sc, Expressions* exps, const bool reportErrors = true) 1588 { 1589 bool err = false; 1590 if (exps) 1591 { 1592 expandTuples(exps); 1593 1594 for (size_t i = 0; i < exps.dim; i++) 1595 { 1596 Expression arg = (*exps)[i]; 1597 arg = resolveProperties(sc, arg); 1598 if (arg.op == TOK.type) 1599 { 1600 // for static alias this: https://issues.dlang.org/show_bug.cgi?id=17684 1601 arg = resolveAliasThis(sc, arg); 1602 1603 if (arg.op == TOK.type) 1604 { 1605 if (reportErrors) 1606 { 1607 arg.error("cannot pass type `%s` as a function argument", arg.toChars()); 1608 arg = ErrorExp.get(); 1609 } 1610 err = true; 1611 } 1612 } 1613 else if (arg.type.toBasetype().ty == Tfunction) 1614 { 1615 if (reportErrors) 1616 { 1617 arg.error("cannot pass function `%s` as a function argument", arg.toChars()); 1618 arg = ErrorExp.get(); 1619 } 1620 err = true; 1621 } 1622 else if (checkNonAssignmentArrayOp(arg)) 1623 { 1624 arg = ErrorExp.get(); 1625 err = true; 1626 } 1627 (*exps)[i] = arg; 1628 } 1629 } 1630 return err; 1631 } 1632 1633 /******************************************** 1634 * Issue an error if default construction is disabled for type t. 1635 * Default construction is required for arrays and 'out' parameters. 1636 * Returns: 1637 * true an error was issued 1638 */ 1639 private bool checkDefCtor(Loc loc, Type t) 1640 { 1641 t = t.baseElemOf(); 1642 if (t.ty == Tstruct) 1643 { 1644 StructDeclaration sd = (cast(TypeStruct)t).sym; 1645 if (sd.noDefaultCtor) 1646 { 1647 sd.error(loc, "default construction is disabled"); 1648 return true; 1649 } 1650 } 1651 return false; 1652 } 1653 1654 /**************************************** 1655 * Now that we know the exact type of the function we're calling, 1656 * the arguments[] need to be adjusted: 1657 * 1. implicitly convert argument to the corresponding parameter type 1658 * 2. add default arguments for any missing arguments 1659 * 3. do default promotions on arguments corresponding to ... 1660 * 4. add hidden _arguments[] argument 1661 * 5. call copy constructor for struct value arguments 1662 * Params: 1663 * loc = location of function call 1664 * sc = context 1665 * tf = type of the function 1666 * ethis = `this` argument, `null` if none or not known 1667 * tthis = type of `this` argument, `null` if no `this` argument 1668 * arguments = array of actual arguments to function call 1669 * fd = the function being called, `null` if called indirectly 1670 * prettype = set to return type of function 1671 * peprefix = set to expression to execute before `arguments[]` are evaluated, `null` if none 1672 * Returns: 1673 * true errors happened 1674 */ 1675 private bool functionParameters(const ref Loc loc, Scope* sc, 1676 TypeFunction tf, Expression ethis, Type tthis, Expressions* arguments, FuncDeclaration fd, 1677 Type* prettype, Expression* peprefix) 1678 { 1679 //printf("functionParameters() %s\n", fd ? fd.toChars() : ""); 1680 assert(arguments); 1681 assert(fd || tf.next); 1682 size_t nargs = arguments ? arguments.dim : 0; 1683 const size_t nparams = tf.parameterList.length; 1684 const olderrors = global.errors; 1685 bool err = false; 1686 *prettype = Type.terror; 1687 Expression eprefix = null; 1688 *peprefix = null; 1689 1690 if (nargs > nparams && tf.parameterList.varargs == VarArg.none) 1691 { 1692 error(loc, "expected %llu arguments, not %llu for non-variadic function type `%s`", cast(ulong)nparams, cast(ulong)nargs, tf.toChars()); 1693 return true; 1694 } 1695 1696 // If inferring return type, and semantic3() needs to be run if not already run 1697 if (!tf.next && fd.inferRetType) 1698 { 1699 fd.functionSemantic(); 1700 } 1701 else if (fd && fd.parent) 1702 { 1703 TemplateInstance ti = fd.parent.isTemplateInstance(); 1704 if (ti && ti.tempdecl) 1705 { 1706 fd.functionSemantic3(); 1707 } 1708 } 1709 1710 /* If calling a pragma(inline, true) function, 1711 * set flag to later scan for inlines. 1712 */ 1713 if (fd && fd.inlining == PINLINE.always) 1714 { 1715 if (sc._module) 1716 sc._module.hasAlwaysInlines = true; 1717 if (sc.func) 1718 sc.func.hasAlwaysInlines = true; 1719 } 1720 1721 const isCtorCall = fd && fd.needThis() && fd.isCtorDeclaration(); 1722 1723 const size_t n = (nargs > nparams) ? nargs : nparams; // n = max(nargs, nparams) 1724 1725 /* If the function return type has wildcards in it, we'll need to figure out the actual type 1726 * based on the actual argument types. 1727 * Start with the `this` argument, later on merge into wildmatch the mod bits of the rest 1728 * of the arguments. 1729 */ 1730 MOD wildmatch = (tthis && !isCtorCall) ? tthis.Type.deduceWild(tf, false) : 0; 1731 1732 bool done = false; 1733 foreach (const i; 0 .. n) 1734 { 1735 Expression arg = (i < nargs) ? (*arguments)[i] : null; 1736 1737 if (i < nparams) 1738 { 1739 bool errorArgs() 1740 { 1741 error(loc, "expected %llu function arguments, not %llu", cast(ulong)nparams, cast(ulong)nargs); 1742 return true; 1743 } 1744 1745 Parameter p = tf.parameterList[i]; 1746 const bool isRef = p.isReference(); 1747 1748 if (!arg) 1749 { 1750 if (!p.defaultArg) 1751 { 1752 if (tf.parameterList.varargs == VarArg.typesafe && i + 1 == nparams) 1753 goto L2; 1754 return errorArgs(); 1755 } 1756 arg = p.defaultArg; 1757 arg = inlineCopy(arg, sc); 1758 // __FILE__, __LINE__, __MODULE__, __FUNCTION__, and __PRETTY_FUNCTION__ 1759 arg = arg.resolveLoc(loc, sc); 1760 arguments.push(arg); 1761 nargs++; 1762 } 1763 else 1764 { 1765 if (isDefaultInitOp(arg.op)) 1766 { 1767 arg = arg.resolveLoc(loc, sc); 1768 (*arguments)[i] = arg; 1769 } 1770 } 1771 1772 1773 if (isRef && !p.type.isConst && !p.type.isImmutable 1774 && (p.storageClass & STC.const_) != STC.const_ 1775 && (p.storageClass & STC.immutable_) != STC.immutable_ 1776 && checkIfIsStructLiteralDotExpr(arg)) 1777 break; 1778 1779 if (tf.parameterList.varargs == VarArg.typesafe && i + 1 == nparams) // https://dlang.org/spec/function.html#variadic 1780 { 1781 //printf("\t\tvarargs == 2, p.type = '%s'\n", p.type.toChars()); 1782 { 1783 MATCH m; 1784 if ((m = arg.implicitConvTo(p.type)) > MATCH.nomatch) 1785 { 1786 if (p.type.nextOf() && arg.implicitConvTo(p.type.nextOf()) >= m) 1787 goto L2; 1788 else if (nargs != nparams) 1789 return errorArgs(); 1790 goto L1; 1791 } 1792 } 1793 L2: 1794 Type tb = p.type.toBasetype(); 1795 switch (tb.ty) 1796 { 1797 case Tsarray: 1798 case Tarray: 1799 { 1800 /* Create a static array variable v of type arg.type: 1801 * T[dim] __arrayArg = [ arguments[i], ..., arguments[nargs-1] ]; 1802 * 1803 * The array literal in the initializer of the hidden variable 1804 * is now optimized. 1805 * https://issues.dlang.org/show_bug.cgi?id=2356 1806 */ 1807 Type tbn = (cast(TypeArray)tb).next; // array element type 1808 Type tret = p.isLazyArray(); 1809 1810 auto elements = new Expressions(nargs - i); 1811 foreach (u; 0 .. elements.dim) 1812 { 1813 Expression a = (*arguments)[i + u]; 1814 if (tret && a.implicitConvTo(tret)) 1815 { 1816 // p is a lazy array of delegates, tret is return type of the delegates 1817 a = a.implicitCastTo(sc, tret) 1818 .optimize(WANTvalue) 1819 .toDelegate(tret, sc); 1820 } 1821 else 1822 a = a.implicitCastTo(sc, tbn); 1823 a = a.addDtorHook(sc); 1824 (*elements)[u] = a; 1825 } 1826 // https://issues.dlang.org/show_bug.cgi?id=14395 1827 // Convert to a static array literal, or its slice. 1828 arg = new ArrayLiteralExp(loc, tbn.sarrayOf(nargs - i), elements); 1829 if (tb.ty == Tarray) 1830 { 1831 arg = new SliceExp(loc, arg, null, null); 1832 arg.type = p.type; 1833 } 1834 break; 1835 } 1836 case Tclass: 1837 { 1838 /* Set arg to be: 1839 * new Tclass(arg0, arg1, ..., argn) 1840 */ 1841 auto args = new Expressions(nargs - i); 1842 foreach (u; i .. nargs) 1843 (*args)[u - i] = (*arguments)[u]; 1844 arg = new NewExp(loc, null, null, p.type, args); 1845 break; 1846 } 1847 default: 1848 if (!arg) 1849 { 1850 error(loc, "not enough arguments"); 1851 return true; 1852 } 1853 break; 1854 } 1855 arg = arg.expressionSemantic(sc); 1856 //printf("\targ = '%s'\n", arg.toChars()); 1857 arguments.setDim(i + 1); 1858 (*arguments)[i] = arg; 1859 nargs = i + 1; 1860 done = true; 1861 } 1862 1863 L1: 1864 if (!(p.storageClass & STC.lazy_ && p.type.ty == Tvoid)) 1865 { 1866 1867 if (ubyte wm = arg.type.deduceWild(p.type, isRef)) 1868 { 1869 wildmatch = wildmatch ? MODmerge(wildmatch, wm) : wm; 1870 //printf("[%d] p = %s, a = %s, wm = %d, wildmatch = %d\n", i, p.type.toChars(), arg.type.toChars(), wm, wildmatch); 1871 } 1872 } 1873 } 1874 if (done) 1875 break; 1876 } 1877 if ((wildmatch == MODFlags.mutable || wildmatch == MODFlags.immutable_) && 1878 tf.next && tf.next.hasWild() && 1879 (tf.isref || !tf.next.implicitConvTo(tf.next.immutableOf()))) 1880 { 1881 bool errorInout(MOD wildmatch) 1882 { 1883 const(char)* s = wildmatch == MODFlags.mutable ? "mutable" : MODtoChars(wildmatch); 1884 error(loc, "modify `inout` to `%s` is not allowed inside `inout` function", s); 1885 return true; 1886 } 1887 1888 if (fd) 1889 { 1890 /* If the called function may return the reference to 1891 * outer inout data, it should be rejected. 1892 * 1893 * void foo(ref inout(int) x) { 1894 * ref inout(int) bar(inout(int)) { return x; } 1895 * struct S { 1896 * ref inout(int) bar() inout { return x; } 1897 * ref inout(int) baz(alias a)() inout { return x; } 1898 * } 1899 * bar(int.init) = 1; // bad! 1900 * S().bar() = 1; // bad! 1901 * } 1902 * void test() { 1903 * int a; 1904 * auto s = foo(a); 1905 * s.baz!a() = 1; // bad! 1906 * } 1907 * 1908 */ 1909 bool checkEnclosingWild(Dsymbol s) 1910 { 1911 bool checkWild(Dsymbol s) 1912 { 1913 if (!s) 1914 return false; 1915 if (auto ad = s.isAggregateDeclaration()) 1916 { 1917 if (ad.isNested()) 1918 return checkEnclosingWild(s); 1919 } 1920 else if (auto ff = s.isFuncDeclaration()) 1921 { 1922 if ((cast(TypeFunction)ff.type).iswild) 1923 return errorInout(wildmatch); 1924 1925 if (ff.isNested() || ff.isThis()) 1926 return checkEnclosingWild(s); 1927 } 1928 return false; 1929 } 1930 1931 Dsymbol ctx0 = s.toParent2(); 1932 Dsymbol ctx1 = s.toParentLocal(); 1933 if (checkWild(ctx0)) 1934 return true; 1935 if (ctx0 != ctx1) 1936 return checkWild(ctx1); 1937 return false; 1938 } 1939 if ((fd.isThis() || fd.isNested()) && checkEnclosingWild(fd)) 1940 return true; 1941 } 1942 else if (tf.isWild()) 1943 return errorInout(wildmatch); 1944 } 1945 1946 Expression firstArg = ((tf.next && tf.next.ty == Tvoid || isCtorCall) && 1947 tthis && 1948 tthis.isMutable() && tthis.toBasetype().ty == Tstruct && 1949 tthis.hasPointers()) 1950 ? ethis : null; 1951 1952 assert(nargs >= nparams); 1953 foreach (const i, arg; (*arguments)[0 .. nargs]) 1954 { 1955 assert(arg); 1956 if (i < nparams) 1957 { 1958 Parameter p = tf.parameterList[i]; 1959 Type targ = arg.type; // keep original type for isCopyable() because alias this 1960 // resolution may hide an uncopyable type 1961 1962 if (!(p.storageClass & STC.lazy_ && p.type.ty == Tvoid)) 1963 { 1964 Type tprm = p.type.hasWild() 1965 ? p.type.substWildTo(wildmatch) 1966 : p.type; 1967 1968 const hasCopyCtor = (arg.type.ty == Tstruct) && (cast(TypeStruct)arg.type).sym.hasCopyCtor; 1969 const typesMatch = arg.type.mutableOf().unSharedOf().equals(tprm.mutableOf().unSharedOf()); 1970 if (!((hasCopyCtor && typesMatch) || tprm.equals(arg.type))) 1971 { 1972 //printf("arg.type = %s, p.type = %s\n", arg.type.toChars(), p.type.toChars()); 1973 arg = arg.implicitCastTo(sc, tprm); 1974 arg = arg.optimize(WANTvalue, p.isReference()); 1975 } 1976 } 1977 1978 // Support passing rvalue to `in` parameters 1979 if ((p.storageClass & (STC.in_ | STC.ref_)) == (STC.in_ | STC.ref_)) 1980 { 1981 if (!arg.isLvalue()) 1982 { 1983 auto v = copyToTemp(STC.exptemp, "__rvalue", arg); 1984 Expression ev = new DeclarationExp(arg.loc, v); 1985 ev = new CommaExp(arg.loc, ev, new VarExp(arg.loc, v)); 1986 arg = ev.expressionSemantic(sc); 1987 } 1988 arg = arg.toLvalue(sc, arg); 1989 1990 // Look for mutable misaligned pointer, etc., in @safe mode 1991 err |= checkUnsafeAccess(sc, arg, false, true); 1992 } 1993 else if (p.storageClass & STC.ref_) 1994 { 1995 if (global.params.rvalueRefParam && 1996 !arg.isLvalue() && 1997 targ.isCopyable()) 1998 { /* allow rvalues to be passed to ref parameters by copying 1999 * them to a temp, then pass the temp as the argument 2000 */ 2001 auto v = copyToTemp(0, "__rvalue", arg); 2002 Expression ev = new DeclarationExp(arg.loc, v); 2003 ev = new CommaExp(arg.loc, ev, new VarExp(arg.loc, v)); 2004 arg = ev.expressionSemantic(sc); 2005 } 2006 arg = arg.toLvalue(sc, arg); 2007 2008 // Look for mutable misaligned pointer, etc., in @safe mode 2009 err |= checkUnsafeAccess(sc, arg, false, true); 2010 } 2011 else if (p.storageClass & STC.out_) 2012 { 2013 Type t = arg.type; 2014 if (!t.isMutable() || !t.isAssignable()) // check blit assignable 2015 { 2016 arg.error("cannot modify struct `%s` with immutable members", arg.toChars()); 2017 err = true; 2018 } 2019 else 2020 { 2021 // Look for misaligned pointer, etc., in @safe mode 2022 err |= checkUnsafeAccess(sc, arg, false, true); 2023 err |= checkDefCtor(arg.loc, t); // t must be default constructible 2024 } 2025 arg = arg.toLvalue(sc, arg); 2026 } 2027 else if (p.storageClass & STC.lazy_) 2028 { 2029 // Convert lazy argument to a delegate 2030 auto t = (p.type.ty == Tvoid) ? p.type : arg.type; 2031 arg = toDelegate(arg, t, sc); 2032 } 2033 //printf("arg: %s\n", arg.toChars()); 2034 //printf("type: %s\n", arg.type.toChars()); 2035 //printf("param: %s\n", p.toChars()); 2036 2037 if (firstArg && p.storageClass & STC.return_) 2038 { 2039 /* Argument value can be assigned to firstArg. 2040 * Check arg to see if it matters. 2041 */ 2042 if (global.params.vsafe) 2043 err |= checkParamArgumentReturn(sc, firstArg, arg, false); 2044 } 2045 else if (tf.parameterEscapes(tthis, p)) 2046 { 2047 /* Argument value can escape from the called function. 2048 * Check arg to see if it matters. 2049 */ 2050 if (global.params.vsafe) 2051 err |= checkParamArgumentEscape(sc, fd, p, arg, false, false); 2052 } 2053 else 2054 { 2055 /* Argument value cannot escape from the called function. 2056 */ 2057 Expression a = arg; 2058 if (a.op == TOK.cast_) 2059 a = (cast(CastExp)a).e1; 2060 2061 ArrayLiteralExp ale; 2062 if (p.type.toBasetype().ty == Tarray && !(p.storageClass & STC.return_) && 2063 (ale = a.isArrayLiteralExp()) !is null) 2064 { 2065 // allocate the array literal as temporary static array on the stack 2066 ale.type = ale.type.nextOf().sarrayOf(ale.elements ? ale.elements.length : 0); 2067 auto tmp = copyToTemp(0, "__arrayliteral_on_stack", ale); 2068 auto declareTmp = new DeclarationExp(ale.loc, tmp); 2069 auto castToSlice = new CastExp(ale.loc, new VarExp(ale.loc, tmp), p.type); 2070 arg = CommaExp.combine(declareTmp, castToSlice); 2071 arg = arg.expressionSemantic(sc); 2072 } 2073 else if (a.op == TOK.function_) 2074 { 2075 /* Function literals can only appear once, so if this 2076 * appearance was scoped, there cannot be any others. 2077 */ 2078 FuncExp fe = cast(FuncExp)a; 2079 fe.fd.tookAddressOf = 0; 2080 } 2081 else if (a.op == TOK.delegate_) 2082 { 2083 /* For passing a delegate to a scoped parameter, 2084 * this doesn't count as taking the address of it. 2085 * We only worry about 'escaping' references to the function. 2086 */ 2087 DelegateExp de = cast(DelegateExp)a; 2088 if (de.e1.op == TOK.variable) 2089 { 2090 VarExp ve = cast(VarExp)de.e1; 2091 FuncDeclaration f = ve.var.isFuncDeclaration(); 2092 if (f) 2093 { 2094 if (f.tookAddressOf) 2095 --f.tookAddressOf; 2096 //printf("--tookAddressOf = %d\n", f.tookAddressOf); 2097 } 2098 } 2099 } 2100 } 2101 if (!p.isReference()) 2102 err |= arg.checkSharedAccess(sc); 2103 2104 arg = arg.optimize(WANTvalue, p.isReference()); 2105 2106 /* Determine if this parameter is the "first reference" parameter through which 2107 * later "return" arguments can be stored. 2108 */ 2109 if (i == 0 && !tthis && p.isReference() && p.type && 2110 (tf.next && tf.next.ty == Tvoid || isCtorCall)) 2111 { 2112 Type tb = p.type.baseElemOf(); 2113 if (tb.isMutable() && tb.hasPointers()) 2114 { 2115 firstArg = arg; 2116 } 2117 } 2118 } 2119 else 2120 { 2121 // These will be the trailing ... arguments 2122 // If not D linkage, do promotions 2123 if (tf.linkage != LINK.d) 2124 { 2125 // Promote bytes, words, etc., to ints 2126 arg = integralPromotions(arg, sc); 2127 2128 // Promote floats to doubles 2129 switch (arg.type.ty) 2130 { 2131 case Tfloat32: 2132 arg = arg.castTo(sc, Type.tfloat64); 2133 break; 2134 2135 case Timaginary32: 2136 arg = arg.castTo(sc, Type.timaginary64); 2137 break; 2138 2139 default: 2140 break; 2141 } 2142 if (tf.parameterList.varargs == VarArg.variadic) 2143 { 2144 const(char)* p = tf.linkage == LINK.c ? "extern(C)" : "extern(C++)"; 2145 if (arg.type.ty == Tarray) 2146 { 2147 arg.error("cannot pass dynamic arrays to `%s` vararg functions", p); 2148 err = true; 2149 } 2150 if (arg.type.ty == Tsarray) 2151 { 2152 arg.error("cannot pass static arrays to `%s` vararg functions", p); 2153 err = true; 2154 } 2155 } 2156 } 2157 2158 // Do not allow types that need destructors or copy constructors. 2159 if (arg.type.needsDestruction()) 2160 { 2161 arg.error("cannot pass types that need destruction as variadic arguments"); 2162 err = true; 2163 } 2164 if (arg.type.needsCopyOrPostblit()) 2165 { 2166 arg.error("cannot pass types with postblits or copy constructors as variadic arguments"); 2167 err = true; 2168 } 2169 2170 // Convert static arrays to dynamic arrays 2171 // BUG: I don't think this is right for D2 2172 Type tb = arg.type.toBasetype(); 2173 if (tb.ty == Tsarray) 2174 { 2175 TypeSArray ts = cast(TypeSArray)tb; 2176 Type ta = ts.next.arrayOf(); 2177 if (ts.size(arg.loc) == 0) 2178 arg = new NullExp(arg.loc, ta); 2179 else 2180 arg = arg.castTo(sc, ta); 2181 } 2182 if (tb.ty == Tstruct) 2183 { 2184 //arg = callCpCtor(sc, arg); 2185 } 2186 // Give error for overloaded function addresses 2187 if (arg.op == TOK.symbolOffset) 2188 { 2189 SymOffExp se = cast(SymOffExp)arg; 2190 if (se.hasOverloads && !se.var.isFuncDeclaration().isUnique()) 2191 { 2192 arg.error("function `%s` is overloaded", arg.toChars()); 2193 err = true; 2194 } 2195 } 2196 err |= arg.checkValue(); 2197 err |= arg.checkSharedAccess(sc); 2198 arg = arg.optimize(WANTvalue); 2199 } 2200 (*arguments)[i] = arg; 2201 } 2202 2203 /* If calling C scanf(), printf(), or any variants, check the format string against the arguments 2204 */ 2205 const isVa_list = tf.parameterList.varargs == VarArg.none; 2206 if (fd && fd.flags & FUNCFLAG.printf) 2207 { 2208 if (auto se = (*arguments)[nparams - 1 - isVa_list].isStringExp()) 2209 { 2210 checkPrintfFormat(se.loc, se.peekString(), (*arguments)[nparams .. nargs], isVa_list); 2211 } 2212 } 2213 else if (fd && fd.flags & FUNCFLAG.scanf) 2214 { 2215 if (auto se = (*arguments)[nparams - 1 - isVa_list].isStringExp()) 2216 { 2217 checkScanfFormat(se.loc, se.peekString(), (*arguments)[nparams .. nargs], isVa_list); 2218 } 2219 } 2220 else 2221 { 2222 // TODO: not checking the "v" functions yet (for those, check format string only, not args) 2223 } 2224 2225 /* Remaining problems: 2226 * 1. order of evaluation - some function push L-to-R, others R-to-L. Until we resolve what array assignment does (which is 2227 * implemented by calling a function) we'll defer this for now. 2228 * 2. value structs (or static arrays of them) that need to be copy constructed 2229 * 3. value structs (or static arrays of them) that have destructors, and subsequent arguments that may throw before the 2230 * function gets called (functions normally destroy their parameters) 2231 * 2 and 3 are handled by doing the argument construction in 'eprefix' so that if a later argument throws, they are cleaned 2232 * up properly. Pushing arguments on the stack then cannot fail. 2233 */ 2234 { 2235 /* TODO: tackle problem 1) 2236 */ 2237 const bool leftToRight = true; // TODO: Any cases that need rightToLeft? 2238 if (!leftToRight) 2239 assert(nargs == nparams); // no variadics for RTL order, as they would probably be evaluated LTR and so add complexity 2240 2241 const ptrdiff_t start = (leftToRight ? 0 : cast(ptrdiff_t)nargs - 1); 2242 const ptrdiff_t end = (leftToRight ? cast(ptrdiff_t)nargs : -1); 2243 const ptrdiff_t step = (leftToRight ? 1 : -1); 2244 2245 /* Compute indices of last throwing argument and first arg needing destruction. 2246 * Used to not set up destructors unless an arg needs destruction on a throw 2247 * in a later argument. 2248 */ 2249 ptrdiff_t lastthrow = -1; 2250 ptrdiff_t firstdtor = -1; 2251 for (ptrdiff_t i = start; i != end; i += step) 2252 { 2253 Expression arg = (*arguments)[i]; 2254 if (canThrow(arg, sc.func, false)) 2255 lastthrow = i; 2256 if (firstdtor == -1 && arg.type.needsDestruction()) 2257 { 2258 Parameter p = (i >= nparams ? null : tf.parameterList[i]); 2259 if (!(p && (p.storageClass & (STC.lazy_ | STC.ref_ | STC.out_)))) 2260 firstdtor = i; 2261 } 2262 } 2263 2264 /* Does problem 3) apply to this call? 2265 */ 2266 const bool needsPrefix = (firstdtor >= 0 && lastthrow >= 0 2267 && (lastthrow - firstdtor) * step > 0); 2268 2269 /* If so, initialize 'eprefix' by declaring the gate 2270 */ 2271 VarDeclaration gate = null; 2272 if (needsPrefix) 2273 { 2274 // eprefix => bool __gate [= false] 2275 Identifier idtmp = Identifier.generateId("__gate"); 2276 gate = new VarDeclaration(loc, Type.tbool, idtmp, null); 2277 gate.storage_class |= STC.temp | STC.ctfe | STC.volatile_; 2278 gate.dsymbolSemantic(sc); 2279 2280 auto ae = new DeclarationExp(loc, gate); 2281 eprefix = ae.expressionSemantic(sc); 2282 } 2283 2284 for (ptrdiff_t i = start; i != end; i += step) 2285 { 2286 Expression arg = (*arguments)[i]; 2287 2288 Parameter parameter = (i >= nparams ? null : tf.parameterList[i]); 2289 const bool isRef = parameter && parameter.isReference(); 2290 const bool isLazy = (parameter && (parameter.storageClass & STC.lazy_)); 2291 2292 /* Skip lazy parameters 2293 */ 2294 if (isLazy) 2295 continue; 2296 2297 /* Do we have a gate? Then we have a prefix and we're not yet past the last throwing arg. 2298 * Declare a temporary variable for this arg and append that declaration to 'eprefix', 2299 * which will implicitly take care of potential problem 2) for this arg. 2300 * 'eprefix' will therefore finally contain all args up to and including the last 2301 * potentially throwing arg, excluding all lazy parameters. 2302 */ 2303 if (gate) 2304 { 2305 const bool needsDtor = (!isRef && arg.type.needsDestruction() && i != lastthrow); 2306 2307 /* Declare temporary 'auto __pfx = arg' (needsDtor) or 'auto __pfy = arg' (!needsDtor) 2308 */ 2309 auto tmp = copyToTemp(0, 2310 needsDtor ? "__pfx" : "__pfy", 2311 !isRef ? arg : arg.addressOf()); 2312 tmp.dsymbolSemantic(sc); 2313 2314 /* Modify the destructor so it only runs if gate==false, i.e., 2315 * only if there was a throw while constructing the args 2316 */ 2317 if (!needsDtor) 2318 { 2319 if (tmp.edtor) 2320 { 2321 assert(i == lastthrow); 2322 tmp.edtor = null; 2323 } 2324 } 2325 else 2326 { 2327 // edtor => (__gate || edtor) 2328 assert(tmp.edtor); 2329 Expression e = tmp.edtor; 2330 e = new LogicalExp(e.loc, TOK.orOr, new VarExp(e.loc, gate), e); 2331 tmp.edtor = e.expressionSemantic(sc); 2332 //printf("edtor: %s\n", tmp.edtor.toChars()); 2333 } 2334 2335 // eprefix => (eprefix, auto __pfx/y = arg) 2336 auto ae = new DeclarationExp(loc, tmp); 2337 eprefix = Expression.combine(eprefix, ae.expressionSemantic(sc)); 2338 2339 // arg => __pfx/y 2340 arg = new VarExp(loc, tmp); 2341 arg = arg.expressionSemantic(sc); 2342 if (isRef) 2343 { 2344 arg = new PtrExp(loc, arg); 2345 arg = arg.expressionSemantic(sc); 2346 } 2347 2348 /* Last throwing arg? Then finalize eprefix => (eprefix, gate = true), 2349 * i.e., disable the dtors right after constructing the last throwing arg. 2350 * From now on, the callee will take care of destructing the args because 2351 * the args are implicitly moved into function parameters. 2352 * 2353 * Set gate to null to let the next iterations know they don't need to 2354 * append to eprefix anymore. 2355 */ 2356 if (i == lastthrow) 2357 { 2358 auto e = new AssignExp(gate.loc, new VarExp(gate.loc, gate), IntegerExp.createBool(true)); 2359 eprefix = Expression.combine(eprefix, e.expressionSemantic(sc)); 2360 gate = null; 2361 } 2362 } 2363 else 2364 { 2365 /* No gate, no prefix to append to. 2366 * Handle problem 2) by calling the copy constructor for value structs 2367 * (or static arrays of them) if appropriate. 2368 */ 2369 Type tv = arg.type.baseElemOf(); 2370 if (!isRef && tv.ty == Tstruct) 2371 arg = doCopyOrMove(sc, arg, parameter ? parameter.type : null); 2372 } 2373 2374 (*arguments)[i] = arg; 2375 } 2376 } 2377 //if (eprefix) printf("eprefix: %s\n", eprefix.toChars()); 2378 2379 /* Test compliance with DIP1021 2380 */ 2381 if (global.params.useDIP1021 && 2382 tf.trust != TRUST.system && tf.trust != TRUST.trusted) 2383 err |= checkMutableArguments(sc, fd, tf, ethis, arguments, false); 2384 2385 // If D linkage and variadic, add _arguments[] as first argument 2386 if (tf.isDstyleVariadic()) 2387 { 2388 assert(arguments.dim >= nparams); 2389 2390 auto args = new Parameters(arguments.dim - nparams); 2391 for (size_t i = 0; i < arguments.dim - nparams; i++) 2392 { 2393 auto arg = new Parameter(STC.in_, (*arguments)[nparams + i].type, null, null, null); 2394 (*args)[i] = arg; 2395 } 2396 auto tup = new TypeTuple(args); 2397 Expression e = (new TypeidExp(loc, tup)).expressionSemantic(sc); 2398 arguments.insert(0, e); 2399 } 2400 2401 /* Determine function return type: tret 2402 */ 2403 Type tret = tf.next; 2404 if (isCtorCall) 2405 { 2406 //printf("[%s] fd = %s %s, %d %d %d\n", loc.toChars(), fd.toChars(), fd.type.toChars(), 2407 // wildmatch, tf.isWild(), fd.isReturnIsolated()); 2408 if (!tthis) 2409 { 2410 assert(sc.intypeof || global.errors); 2411 tthis = fd.isThis().type.addMod(fd.type.mod); 2412 } 2413 if (tf.isWild() && !fd.isReturnIsolated()) 2414 { 2415 if (wildmatch) 2416 tret = tret.substWildTo(wildmatch); 2417 int offset; 2418 if (!tret.implicitConvTo(tthis) && !(MODimplicitConv(tret.mod, tthis.mod) && tret.isBaseOf(tthis, &offset) && offset == 0)) 2419 { 2420 const(char)* s1 = tret.isNaked() ? " mutable" : tret.modToChars(); 2421 const(char)* s2 = tthis.isNaked() ? " mutable" : tthis.modToChars(); 2422 .error(loc, "`inout` constructor `%s` creates%s object, not%s", fd.toPrettyChars(), s1, s2); 2423 err = true; 2424 } 2425 } 2426 tret = tthis; 2427 } 2428 else if (wildmatch && tret) 2429 { 2430 /* Adjust function return type based on wildmatch 2431 */ 2432 //printf("wildmatch = x%x, tret = %s\n", wildmatch, tret.toChars()); 2433 tret = tret.substWildTo(wildmatch); 2434 } 2435 2436 *prettype = tret; 2437 *peprefix = eprefix; 2438 return (err || olderrors != global.errors); 2439 } 2440 2441 /** 2442 * Determines whether a symbol represents a module or package 2443 * (Used as a helper for is(type == module) and is(type == package)) 2444 * 2445 * Params: 2446 * sym = the symbol to be checked 2447 * 2448 * Returns: 2449 * the symbol which `sym` represents (or `null` if it doesn't represent a `Package`) 2450 */ 2451 Package resolveIsPackage(Dsymbol sym) 2452 { 2453 Package pkg; 2454 if (Import imp = sym.isImport()) 2455 { 2456 if (imp.pkg is null) 2457 { 2458 .error(sym.loc, "Internal Compiler Error: unable to process forward-referenced import `%s`", 2459 imp.toChars()); 2460 assert(0); 2461 } 2462 pkg = imp.pkg; 2463 } 2464 else if (auto mod = sym.isModule()) 2465 pkg = mod.isPackageFile ? mod.pkg : sym.isPackage(); 2466 else 2467 pkg = sym.isPackage(); 2468 if (pkg) 2469 pkg.resolvePKGunknown(); 2470 return pkg; 2471 } 2472 2473 private Module loadStdMath() 2474 { 2475 __gshared Import impStdMath = null; 2476 if (!impStdMath) 2477 { 2478 auto a = new Identifiers(); 2479 a.push(Id.std); 2480 auto s = new Import(Loc.initial, a, Id.math, null, false); 2481 // Module.load will call fatal() if there's no std.math available. 2482 // Gag the error here, pushing the error handling to the caller. 2483 uint errors = global.startGagging(); 2484 s.load(null); 2485 if (s.mod) 2486 { 2487 s.mod.importAll(null); 2488 s.mod.dsymbolSemantic(null); 2489 } 2490 global.endGagging(errors); 2491 impStdMath = s; 2492 } 2493 return impStdMath.mod; 2494 } 2495 2496 private extern (C++) final class ExpressionSemanticVisitor : Visitor 2497 { 2498 alias visit = Visitor.visit; 2499 2500 Scope* sc; 2501 Expression result; 2502 2503 this(Scope* sc) 2504 { 2505 this.sc = sc; 2506 } 2507 2508 private void setError() 2509 { 2510 result = ErrorExp.get(); 2511 } 2512 2513 /************************** 2514 * Semantically analyze Expression. 2515 * Determine types, fold constants, etc. 2516 */ 2517 override void visit(Expression e) 2518 { 2519 static if (LOGSEMANTIC) 2520 { 2521 printf("Expression::semantic() %s\n", e.toChars()); 2522 } 2523 if (e.type) 2524 e.type = e.type.typeSemantic(e.loc, sc); 2525 else 2526 e.type = Type.tvoid; 2527 result = e; 2528 } 2529 2530 override void visit(IntegerExp e) 2531 { 2532 assert(e.type); 2533 if (e.type.ty == Terror) 2534 return setError(); 2535 2536 assert(e.type.deco); 2537 e.setInteger(e.getInteger()); 2538 result = e; 2539 } 2540 2541 override void visit(RealExp e) 2542 { 2543 if (!e.type) 2544 e.type = Type.tfloat64; 2545 else 2546 e.type = e.type.typeSemantic(e.loc, sc); 2547 result = e; 2548 } 2549 2550 override void visit(ComplexExp e) 2551 { 2552 if (!e.type) 2553 e.type = Type.tcomplex80; 2554 else 2555 e.type = e.type.typeSemantic(e.loc, sc); 2556 result = e; 2557 } 2558 2559 override void visit(IdentifierExp exp) 2560 { 2561 static if (LOGSEMANTIC) 2562 { 2563 printf("IdentifierExp::semantic('%s')\n", exp.ident.toChars()); 2564 } 2565 if (exp.type) // This is used as the dummy expression 2566 { 2567 result = exp; 2568 return; 2569 } 2570 2571 Dsymbol scopesym; 2572 Dsymbol s = sc.search(exp.loc, exp.ident, &scopesym); 2573 if (s) 2574 { 2575 if (s.errors) 2576 return setError(); 2577 2578 Expression e; 2579 2580 /* See if the symbol was a member of an enclosing 'with' 2581 */ 2582 WithScopeSymbol withsym = scopesym.isWithScopeSymbol(); 2583 if (withsym && withsym.withstate.wthis) 2584 { 2585 /* Disallow shadowing 2586 */ 2587 // First find the scope of the with 2588 Scope* scwith = sc; 2589 while (scwith.scopesym != scopesym) 2590 { 2591 scwith = scwith.enclosing; 2592 assert(scwith); 2593 } 2594 // Look at enclosing scopes for symbols with the same name, 2595 // in the same function 2596 for (Scope* scx = scwith; scx && scx.func == scwith.func; scx = scx.enclosing) 2597 { 2598 Dsymbol s2; 2599 if (scx.scopesym && scx.scopesym.symtab && (s2 = scx.scopesym.symtab.lookup(s.ident)) !is null && s != s2) 2600 { 2601 exp.error("with symbol `%s` is shadowing local symbol `%s`", s.toPrettyChars(), s2.toPrettyChars()); 2602 return setError(); 2603 } 2604 } 2605 s = s.toAlias(); 2606 2607 // Same as wthis.ident 2608 // TODO: DotIdExp.semantic will find 'ident' from 'wthis' again. 2609 // The redudancy should be removed. 2610 e = new VarExp(exp.loc, withsym.withstate.wthis); 2611 e = new DotIdExp(exp.loc, e, exp.ident); 2612 e = e.expressionSemantic(sc); 2613 } 2614 else 2615 { 2616 if (withsym) 2617 { 2618 if (auto t = withsym.withstate.exp.isTypeExp()) 2619 { 2620 e = new TypeExp(exp.loc, t.type); 2621 e = new DotIdExp(exp.loc, e, exp.ident); 2622 result = e.expressionSemantic(sc); 2623 return; 2624 } 2625 } 2626 2627 /* If f is really a function template, 2628 * then replace f with the function template declaration. 2629 */ 2630 FuncDeclaration f = s.isFuncDeclaration(); 2631 if (f) 2632 { 2633 TemplateDeclaration td = getFuncTemplateDecl(f); 2634 if (td) 2635 { 2636 if (td.overroot) // if not start of overloaded list of TemplateDeclaration's 2637 td = td.overroot; // then get the start 2638 e = new TemplateExp(exp.loc, td, f); 2639 e = e.expressionSemantic(sc); 2640 result = e; 2641 return; 2642 } 2643 } 2644 2645 if (global.params.fixAliasThis) 2646 { 2647 ExpressionDsymbol expDsym = scopesym.isExpressionDsymbol(); 2648 if (expDsym) 2649 { 2650 //printf("expDsym = %s\n", expDsym.exp.toChars()); 2651 result = expDsym.exp.expressionSemantic(sc); 2652 return; 2653 } 2654 } 2655 // Haven't done overload resolution yet, so pass 1 2656 e = symbolToExp(s, exp.loc, sc, true); 2657 } 2658 result = e; 2659 return; 2660 } 2661 2662 if (!global.params.fixAliasThis && hasThis(sc)) 2663 { 2664 for (AggregateDeclaration ad = sc.getStructClassScope(); ad;) 2665 { 2666 if (ad.aliasthis) 2667 { 2668 Expression e; 2669 e = new ThisExp(exp.loc); 2670 e = new DotIdExp(exp.loc, e, ad.aliasthis.ident); 2671 e = new DotIdExp(exp.loc, e, exp.ident); 2672 e = e.trySemantic(sc); 2673 if (e) 2674 { 2675 result = e; 2676 return; 2677 } 2678 } 2679 2680 auto cd = ad.isClassDeclaration(); 2681 if (cd && cd.baseClass && cd.baseClass != ClassDeclaration.object) 2682 { 2683 ad = cd.baseClass; 2684 continue; 2685 } 2686 break; 2687 } 2688 } 2689 2690 if (exp.ident == Id.ctfe) 2691 { 2692 if (sc.flags & SCOPE.ctfe) 2693 { 2694 exp.error("variable `__ctfe` cannot be read at compile time"); 2695 return setError(); 2696 } 2697 2698 // Create the magic __ctfe bool variable 2699 auto vd = new VarDeclaration(exp.loc, Type.tbool, Id.ctfe, null); 2700 vd.storage_class |= STC.temp; 2701 vd.semanticRun = PASS.semanticdone; 2702 Expression e = new VarExp(exp.loc, vd); 2703 e = e.expressionSemantic(sc); 2704 result = e; 2705 return; 2706 } 2707 2708 // If we've reached this point and are inside a with() scope then we may 2709 // try one last attempt by checking whether the 'wthis' object supports 2710 // dynamic dispatching via opDispatch. 2711 // This is done by rewriting this expression as wthis.ident. 2712 // The innermost with() scope of the hierarchy to satisfy the condition 2713 // above wins. 2714 // https://issues.dlang.org/show_bug.cgi?id=6400 2715 for (Scope* sc2 = sc; sc2; sc2 = sc2.enclosing) 2716 { 2717 if (!sc2.scopesym) 2718 continue; 2719 2720 if (auto ss = sc2.scopesym.isWithScopeSymbol()) 2721 { 2722 if (ss.withstate.wthis) 2723 { 2724 Expression e; 2725 e = new VarExp(exp.loc, ss.withstate.wthis); 2726 e = new DotIdExp(exp.loc, e, exp.ident); 2727 e = e.trySemantic(sc); 2728 if (e) 2729 { 2730 result = e; 2731 return; 2732 } 2733 } 2734 // Try Type.opDispatch (so the static version) 2735 else if (ss.withstate.exp && ss.withstate.exp.op == TOK.type) 2736 { 2737 if (Type t = ss.withstate.exp.isTypeExp().type) 2738 { 2739 Expression e; 2740 e = new TypeExp(exp.loc, t); 2741 e = new DotIdExp(exp.loc, e, exp.ident); 2742 e = e.trySemantic(sc); 2743 if (e) 2744 { 2745 result = e; 2746 return; 2747 } 2748 } 2749 } 2750 } 2751 } 2752 2753 /* Look for what user might have meant 2754 */ 2755 if (const n = importHint(exp.ident.toString())) 2756 exp.error("`%s` is not defined, perhaps `import %.*s;` is needed?", exp.ident.toChars(), cast(int)n.length, n.ptr); 2757 else if (auto s2 = sc.search_correct(exp.ident)) 2758 exp.error("undefined identifier `%s`, did you mean %s `%s`?", exp.ident.toChars(), s2.kind(), s2.toChars()); 2759 else if (const p = Scope.search_correct_C(exp.ident)) 2760 exp.error("undefined identifier `%s`, did you mean `%s`?", exp.ident.toChars(), p); 2761 else 2762 exp.error("undefined identifier `%s`", exp.ident.toChars()); 2763 2764 result = ErrorExp.get(); 2765 } 2766 2767 override void visit(DsymbolExp e) 2768 { 2769 result = symbolToExp(e.s, e.loc, sc, e.hasOverloads); 2770 } 2771 2772 override void visit(ThisExp e) 2773 { 2774 static if (LOGSEMANTIC) 2775 { 2776 printf("ThisExp::semantic()\n"); 2777 } 2778 if (e.type) 2779 { 2780 result = e; 2781 return; 2782 } 2783 2784 FuncDeclaration fd = hasThis(sc); // fd is the uplevel function with the 'this' variable 2785 AggregateDeclaration ad; 2786 2787 /* Special case for typeof(this) and typeof(super) since both 2788 * should work even if they are not inside a non-static member function 2789 */ 2790 if (!fd && sc.intypeof == 1) 2791 { 2792 // Find enclosing struct or class 2793 for (Dsymbol s = sc.getStructClassScope(); 1; s = s.parent) 2794 { 2795 if (!s) 2796 { 2797 e.error("`%s` is not in a class or struct scope", e.toChars()); 2798 goto Lerr; 2799 } 2800 ClassDeclaration cd = s.isClassDeclaration(); 2801 if (cd) 2802 { 2803 e.type = cd.type; 2804 result = e; 2805 return; 2806 } 2807 StructDeclaration sd = s.isStructDeclaration(); 2808 if (sd) 2809 { 2810 e.type = sd.type; 2811 result = e; 2812 return; 2813 } 2814 } 2815 } 2816 if (!fd) 2817 goto Lerr; 2818 2819 assert(fd.vthis); 2820 e.var = fd.vthis; 2821 assert(e.var.parent); 2822 ad = fd.isMemberLocal(); 2823 if (!ad) 2824 ad = fd.isMember2(); 2825 assert(ad); 2826 e.type = ad.type.addMod(e.var.type.mod); 2827 2828 if (e.var.checkNestedReference(sc, e.loc)) 2829 return setError(); 2830 2831 result = e; 2832 return; 2833 2834 Lerr: 2835 e.error("`this` is only defined in non-static member functions, not `%s`", sc.parent.toChars()); 2836 result = ErrorExp.get(); 2837 } 2838 2839 override void visit(SuperExp e) 2840 { 2841 static if (LOGSEMANTIC) 2842 { 2843 printf("SuperExp::semantic('%s')\n", e.toChars()); 2844 } 2845 if (e.type) 2846 { 2847 result = e; 2848 return; 2849 } 2850 2851 FuncDeclaration fd = hasThis(sc); 2852 ClassDeclaration cd; 2853 Dsymbol s; 2854 2855 /* Special case for typeof(this) and typeof(super) since both 2856 * should work even if they are not inside a non-static member function 2857 */ 2858 if (!fd && sc.intypeof == 1) 2859 { 2860 // Find enclosing class 2861 for (s = sc.getStructClassScope(); 1; s = s.parent) 2862 { 2863 if (!s) 2864 { 2865 e.error("`%s` is not in a class scope", e.toChars()); 2866 goto Lerr; 2867 } 2868 cd = s.isClassDeclaration(); 2869 if (cd) 2870 { 2871 cd = cd.baseClass; 2872 if (!cd) 2873 { 2874 e.error("class `%s` has no `super`", s.toChars()); 2875 goto Lerr; 2876 } 2877 e.type = cd.type; 2878 result = e; 2879 return; 2880 } 2881 } 2882 } 2883 if (!fd) 2884 goto Lerr; 2885 2886 e.var = fd.vthis; 2887 assert(e.var && e.var.parent); 2888 2889 s = fd.toParentDecl(); 2890 if (s.isTemplateDeclaration()) // allow inside template constraint 2891 s = s.toParent(); 2892 assert(s); 2893 cd = s.isClassDeclaration(); 2894 //printf("parent is %s %s\n", fd.toParent().kind(), fd.toParent().toChars()); 2895 if (!cd) 2896 goto Lerr; 2897 if (!cd.baseClass) 2898 { 2899 e.error("no base class for `%s`", cd.toChars()); 2900 e.type = cd.type.addMod(e.var.type.mod); 2901 } 2902 else 2903 { 2904 e.type = cd.baseClass.type; 2905 e.type = e.type.castMod(e.var.type.mod); 2906 } 2907 2908 if (e.var.checkNestedReference(sc, e.loc)) 2909 return setError(); 2910 2911 result = e; 2912 return; 2913 2914 Lerr: 2915 e.error("`super` is only allowed in non-static class member functions"); 2916 result = ErrorExp.get(); 2917 } 2918 2919 override void visit(NullExp e) 2920 { 2921 static if (LOGSEMANTIC) 2922 { 2923 printf("NullExp::semantic('%s')\n", e.toChars()); 2924 } 2925 // NULL is the same as (void *)0 2926 if (e.type) 2927 { 2928 result = e; 2929 return; 2930 } 2931 e.type = Type.tnull; 2932 result = e; 2933 } 2934 2935 override void visit(StringExp e) 2936 { 2937 static if (LOGSEMANTIC) 2938 { 2939 printf("StringExp::semantic() %s\n", e.toChars()); 2940 } 2941 if (e.type) 2942 { 2943 result = e; 2944 return; 2945 } 2946 2947 OutBuffer buffer; 2948 size_t newlen = 0; 2949 size_t u; 2950 dchar c; 2951 2952 switch (e.postfix) 2953 { 2954 case 'd': 2955 for (u = 0; u < e.len;) 2956 { 2957 if (const p = utf_decodeChar(e.peekString(), u, c)) 2958 { 2959 e.error("%.*s", cast(int)p.length, p.ptr); 2960 return setError(); 2961 } 2962 else 2963 { 2964 buffer.write4(c); 2965 newlen++; 2966 } 2967 } 2968 buffer.write4(0); 2969 e.setData(buffer.extractData(), newlen, 4); 2970 e.type = new TypeDArray(Type.tdchar.immutableOf()); 2971 e.committed = 1; 2972 break; 2973 2974 case 'w': 2975 for (u = 0; u < e.len;) 2976 { 2977 if (const p = utf_decodeChar(e.peekString(), u, c)) 2978 { 2979 e.error("%.*s", cast(int)p.length, p.ptr); 2980 return setError(); 2981 } 2982 else 2983 { 2984 buffer.writeUTF16(c); 2985 newlen++; 2986 if (c >= 0x10000) 2987 newlen++; 2988 } 2989 } 2990 buffer.writeUTF16(0); 2991 e.setData(buffer.extractData(), newlen, 2); 2992 e.type = new TypeDArray(Type.twchar.immutableOf()); 2993 e.committed = 1; 2994 break; 2995 2996 case 'c': 2997 e.committed = 1; 2998 goto default; 2999 3000 default: 3001 e.type = new TypeDArray(Type.tchar.immutableOf()); 3002 break; 3003 } 3004 e.type = e.type.typeSemantic(e.loc, sc); 3005 //type = type.immutableOf(); 3006 //printf("type = %s\n", type.toChars()); 3007 3008 result = e; 3009 } 3010 3011 override void visit(TupleExp exp) 3012 { 3013 static if (LOGSEMANTIC) 3014 { 3015 printf("+TupleExp::semantic(%s)\n", exp.toChars()); 3016 } 3017 if (exp.type) 3018 { 3019 result = exp; 3020 return; 3021 } 3022 3023 if (exp.e0) 3024 exp.e0 = exp.e0.expressionSemantic(sc); 3025 3026 // Run semantic() on each argument 3027 bool err = false; 3028 for (size_t i = 0; i < exp.exps.dim; i++) 3029 { 3030 Expression e = (*exp.exps)[i]; 3031 e = e.expressionSemantic(sc); 3032 if (!e.type) 3033 { 3034 exp.error("`%s` has no value", e.toChars()); 3035 err = true; 3036 } 3037 else if (e.op == TOK.error) 3038 err = true; 3039 else 3040 (*exp.exps)[i] = e; 3041 } 3042 if (err) 3043 return setError(); 3044 3045 expandTuples(exp.exps); 3046 3047 exp.type = new TypeTuple(exp.exps); 3048 exp.type = exp.type.typeSemantic(exp.loc, sc); 3049 //printf("-TupleExp::semantic(%s)\n", toChars()); 3050 result = exp; 3051 } 3052 3053 override void visit(ArrayLiteralExp e) 3054 { 3055 static if (LOGSEMANTIC) 3056 { 3057 printf("ArrayLiteralExp::semantic('%s')\n", e.toChars()); 3058 } 3059 if (e.type) 3060 { 3061 result = e; 3062 return; 3063 } 3064 3065 /* Perhaps an empty array literal [ ] should be rewritten as null? 3066 */ 3067 3068 if (e.basis) 3069 e.basis = e.basis.expressionSemantic(sc); 3070 if (arrayExpressionSemantic(e.elements, sc) || (e.basis && e.basis.op == TOK.error)) 3071 return setError(); 3072 3073 expandTuples(e.elements); 3074 3075 Type t0; 3076 if (e.basis) 3077 e.elements.push(e.basis); 3078 bool err = arrayExpressionToCommonType(sc, e.elements, &t0); 3079 if (e.basis) 3080 e.basis = e.elements.pop(); 3081 if (err) 3082 return setError(); 3083 3084 e.type = t0.arrayOf(); 3085 e.type = e.type.typeSemantic(e.loc, sc); 3086 3087 /* Disallow array literals of type void being used. 3088 */ 3089 if (e.elements.dim > 0 && t0.ty == Tvoid) 3090 { 3091 e.error("`%s` of type `%s` has no value", e.toChars(), e.type.toChars()); 3092 return setError(); 3093 } 3094 3095 if (global.params.useTypeInfo && Type.dtypeinfo) 3096 semanticTypeInfo(sc, e.type); 3097 3098 result = e; 3099 } 3100 3101 override void visit(AssocArrayLiteralExp e) 3102 { 3103 static if (LOGSEMANTIC) 3104 { 3105 printf("AssocArrayLiteralExp::semantic('%s')\n", e.toChars()); 3106 } 3107 if (e.type) 3108 { 3109 result = e; 3110 return; 3111 } 3112 3113 // Run semantic() on each element 3114 bool err_keys = arrayExpressionSemantic(e.keys, sc); 3115 bool err_vals = arrayExpressionSemantic(e.values, sc); 3116 if (err_keys || err_vals) 3117 return setError(); 3118 3119 expandTuples(e.keys); 3120 expandTuples(e.values); 3121 if (e.keys.dim != e.values.dim) 3122 { 3123 e.error("number of keys is %llu, must match number of values %llu", 3124 cast(ulong) e.keys.dim, cast(ulong) e.values.dim); 3125 return setError(); 3126 } 3127 3128 Type tkey = null; 3129 Type tvalue = null; 3130 err_keys = arrayExpressionToCommonType(sc, e.keys, &tkey); 3131 err_vals = arrayExpressionToCommonType(sc, e.values, &tvalue); 3132 if (err_keys || err_vals) 3133 return setError(); 3134 3135 if (tkey == Type.terror || tvalue == Type.terror) 3136 return setError(); 3137 3138 e.type = new TypeAArray(tvalue, tkey); 3139 e.type = e.type.typeSemantic(e.loc, sc); 3140 3141 semanticTypeInfo(sc, e.type); 3142 3143 if (global.params.vsafe) 3144 { 3145 if (checkAssocArrayLiteralEscape(sc, e, false)) 3146 return setError(); 3147 } 3148 3149 result = e; 3150 } 3151 3152 override void visit(StructLiteralExp e) 3153 { 3154 static if (LOGSEMANTIC) 3155 { 3156 printf("StructLiteralExp::semantic('%s')\n", e.toChars()); 3157 } 3158 if (e.type) 3159 { 3160 result = e; 3161 return; 3162 } 3163 3164 e.sd.size(e.loc); 3165 if (e.sd.sizeok != Sizeok.done) 3166 return setError(); 3167 3168 // run semantic() on each element 3169 if (arrayExpressionSemantic(e.elements, sc)) 3170 return setError(); 3171 3172 expandTuples(e.elements); 3173 3174 /* Fit elements[] to the corresponding type of field[]. 3175 */ 3176 if (!e.sd.fit(e.loc, sc, e.elements, e.stype)) 3177 return setError(); 3178 3179 /* Fill out remainder of elements[] with default initializers for fields[] 3180 */ 3181 if (!e.sd.fill(e.loc, e.elements, false)) 3182 { 3183 /* An error in the initializer needs to be recorded as an error 3184 * in the enclosing function or template, since the initializer 3185 * will be part of the stuct declaration. 3186 */ 3187 global.increaseErrorCount(); 3188 return setError(); 3189 } 3190 3191 if (checkFrameAccess(e.loc, sc, e.sd, e.elements.dim)) 3192 return setError(); 3193 3194 e.type = e.stype ? e.stype : e.sd.type; 3195 result = e; 3196 } 3197 3198 override void visit(TypeExp exp) 3199 { 3200 if (exp.type.ty == Terror) 3201 return setError(); 3202 3203 //printf("TypeExp::semantic(%s)\n", exp.type.toChars()); 3204 Expression e; 3205 Type t; 3206 Dsymbol s; 3207 3208 dmd.typesem.resolve(exp.type, exp.loc, sc, &e, &t, &s, true); 3209 if (e) 3210 { 3211 // `(Type)` is actually `(var)` so if `(var)` is a member requiring `this` 3212 // then rewrite as `(this.var)` in case it would be followed by a DotVar 3213 // to fix https://issues.dlang.org/show_bug.cgi?id=9490 3214 VarExp ve = e.isVarExp(); 3215 if (ve && ve.var && exp.parens && !ve.var.isStatic() && !(sc.stc & STC.static_) && 3216 sc.func && sc.func.needThis && ve.var.toParent2().isAggregateDeclaration()) 3217 { 3218 // printf("apply fix for issue 9490: add `this.` to `%s`...\n", e.toChars()); 3219 e = new DotVarExp(exp.loc, new ThisExp(exp.loc), ve.var, false); 3220 } 3221 //printf("e = %s %s\n", Token::toChars(e.op), e.toChars()); 3222 e = e.expressionSemantic(sc); 3223 } 3224 else if (t) 3225 { 3226 //printf("t = %d %s\n", t.ty, t.toChars()); 3227 exp.type = t.typeSemantic(exp.loc, sc); 3228 e = exp; 3229 } 3230 else if (s) 3231 { 3232 //printf("s = %s %s\n", s.kind(), s.toChars()); 3233 e = symbolToExp(s, exp.loc, sc, true); 3234 } 3235 else 3236 assert(0); 3237 3238 if (global.params.vcomplex) 3239 exp.type.checkComplexTransition(exp.loc, sc); 3240 3241 result = e; 3242 } 3243 3244 override void visit(ScopeExp exp) 3245 { 3246 static if (LOGSEMANTIC) 3247 { 3248 printf("+ScopeExp::semantic(%p '%s')\n", exp, exp.toChars()); 3249 } 3250 if (exp.type) 3251 { 3252 result = exp; 3253 return; 3254 } 3255 3256 ScopeDsymbol sds2 = exp.sds; 3257 TemplateInstance ti = sds2.isTemplateInstance(); 3258 while (ti) 3259 { 3260 WithScopeSymbol withsym; 3261 if (!ti.findTempDecl(sc, &withsym) || !ti.semanticTiargs(sc)) 3262 return setError(); 3263 if (withsym && withsym.withstate.wthis) 3264 { 3265 Expression e = new VarExp(exp.loc, withsym.withstate.wthis); 3266 e = new DotTemplateInstanceExp(exp.loc, e, ti); 3267 result = e.expressionSemantic(sc); 3268 return; 3269 } 3270 if (ti.needsTypeInference(sc)) 3271 { 3272 if (TemplateDeclaration td = ti.tempdecl.isTemplateDeclaration()) 3273 { 3274 Dsymbol p = td.toParentLocal(); 3275 FuncDeclaration fdthis = hasThis(sc); 3276 AggregateDeclaration ad = p ? p.isAggregateDeclaration() : null; 3277 if (fdthis && ad && fdthis.isMemberLocal() == ad && (td._scope.stc & STC.static_) == 0) 3278 { 3279 Expression e = new DotTemplateInstanceExp(exp.loc, new ThisExp(exp.loc), ti); 3280 result = e.expressionSemantic(sc); 3281 return; 3282 } 3283 } 3284 else if (OverloadSet os = ti.tempdecl.isOverloadSet()) 3285 { 3286 FuncDeclaration fdthis = hasThis(sc); 3287 AggregateDeclaration ad = os.parent.isAggregateDeclaration(); 3288 if (fdthis && ad && fdthis.isMemberLocal() == ad) 3289 { 3290 Expression e = new DotTemplateInstanceExp(exp.loc, new ThisExp(exp.loc), ti); 3291 result = e.expressionSemantic(sc); 3292 return; 3293 } 3294 } 3295 // ti is an instance which requires IFTI. 3296 exp.sds = ti; 3297 exp.type = Type.tvoid; 3298 result = exp; 3299 return; 3300 } 3301 ti.dsymbolSemantic(sc); 3302 if (!ti.inst || ti.errors) 3303 return setError(); 3304 3305 Dsymbol s = ti.toAlias(); 3306 if (s == ti) 3307 { 3308 exp.sds = ti; 3309 exp.type = Type.tvoid; 3310 result = exp; 3311 return; 3312 } 3313 sds2 = s.isScopeDsymbol(); 3314 if (sds2) 3315 { 3316 ti = sds2.isTemplateInstance(); 3317 //printf("+ sds2 = %s, '%s'\n", sds2.kind(), sds2.toChars()); 3318 continue; 3319 } 3320 3321 if (auto v = s.isVarDeclaration()) 3322 { 3323 if (!v.type) 3324 { 3325 exp.error("forward reference of %s `%s`", v.kind(), v.toChars()); 3326 return setError(); 3327 } 3328 if ((v.storage_class & STC.manifest) && v._init) 3329 { 3330 /* When an instance that will be converted to a constant exists, 3331 * the instance representation "foo!tiargs" is treated like a 3332 * variable name, and its recursive appearance check (note that 3333 * it's equivalent with a recursive instantiation of foo) is done 3334 * separately from the circular initialization check for the 3335 * eponymous enum variable declaration. 3336 * 3337 * template foo(T) { 3338 * enum bool foo = foo; // recursive definition check (v.inuse) 3339 * } 3340 * template bar(T) { 3341 * enum bool bar = bar!T; // recursive instantiation check (ti.inuse) 3342 * } 3343 */ 3344 if (ti.inuse) 3345 { 3346 exp.error("recursive expansion of %s `%s`", ti.kind(), ti.toPrettyChars()); 3347 return setError(); 3348 } 3349 v.checkDeprecated(exp.loc, sc); 3350 auto e = v.expandInitializer(exp.loc); 3351 ti.inuse++; 3352 e = e.expressionSemantic(sc); 3353 ti.inuse--; 3354 result = e; 3355 return; 3356 } 3357 } 3358 3359 //printf("s = %s, '%s'\n", s.kind(), s.toChars()); 3360 auto e = symbolToExp(s, exp.loc, sc, true); 3361 //printf("-1ScopeExp::semantic()\n"); 3362 result = e; 3363 return; 3364 } 3365 3366 //printf("sds2 = %s, '%s'\n", sds2.kind(), sds2.toChars()); 3367 //printf("\tparent = '%s'\n", sds2.parent.toChars()); 3368 sds2.dsymbolSemantic(sc); 3369 3370 // (Aggregate|Enum)Declaration 3371 if (auto t = sds2.getType()) 3372 { 3373 result = (new TypeExp(exp.loc, t)).expressionSemantic(sc); 3374 return; 3375 } 3376 3377 if (auto td = sds2.isTemplateDeclaration()) 3378 { 3379 result = (new TemplateExp(exp.loc, td)).expressionSemantic(sc); 3380 return; 3381 } 3382 3383 exp.sds = sds2; 3384 exp.type = Type.tvoid; 3385 //printf("-2ScopeExp::semantic() %s\n", toChars()); 3386 result = exp; 3387 } 3388 3389 override void visit(NewExp exp) 3390 { 3391 static if (LOGSEMANTIC) 3392 { 3393 printf("NewExp::semantic() %s\n", exp.toChars()); 3394 if (exp.thisexp) 3395 printf("\tthisexp = %s\n", exp.thisexp.toChars()); 3396 printf("\tnewtype: %s\n", exp.newtype.toChars()); 3397 } 3398 if (exp.type) // if semantic() already run 3399 { 3400 result = exp; 3401 return; 3402 } 3403 3404 //for error messages if the argument in [] is not convertible to size_t 3405 const originalNewtype = exp.newtype; 3406 3407 // https://issues.dlang.org/show_bug.cgi?id=11581 3408 // With the syntax `new T[edim]` or `thisexp.new T[edim]`, 3409 // T should be analyzed first and edim should go into arguments iff it's 3410 // not a tuple. 3411 Expression edim = null; 3412 if (!exp.arguments && exp.newtype.ty == Tsarray) 3413 { 3414 edim = (cast(TypeSArray)exp.newtype).dim; 3415 exp.newtype = (cast(TypeNext)exp.newtype).next; 3416 } 3417 3418 ClassDeclaration cdthis = null; 3419 if (exp.thisexp) 3420 { 3421 exp.thisexp = exp.thisexp.expressionSemantic(sc); 3422 if (exp.thisexp.op == TOK.error) 3423 return setError(); 3424 3425 cdthis = exp.thisexp.type.isClassHandle(); 3426 if (!cdthis) 3427 { 3428 exp.error("`this` for nested class must be a class type, not `%s`", exp.thisexp.type.toChars()); 3429 return setError(); 3430 } 3431 3432 sc = sc.push(cdthis); 3433 exp.type = exp.newtype.typeSemantic(exp.loc, sc); 3434 sc = sc.pop(); 3435 } 3436 else 3437 { 3438 exp.type = exp.newtype.typeSemantic(exp.loc, sc); 3439 } 3440 if (exp.type.ty == Terror) 3441 return setError(); 3442 3443 if (edim) 3444 { 3445 if (exp.type.toBasetype().ty == Ttuple) 3446 { 3447 // --> new T[edim] 3448 exp.type = new TypeSArray(exp.type, edim); 3449 exp.type = exp.type.typeSemantic(exp.loc, sc); 3450 if (exp.type.ty == Terror) 3451 return setError(); 3452 } 3453 else 3454 { 3455 // --> new T[](edim) 3456 exp.arguments = new Expressions(); 3457 exp.arguments.push(edim); 3458 exp.type = exp.type.arrayOf(); 3459 } 3460 } 3461 3462 exp.newtype = exp.type; // in case type gets cast to something else 3463 Type tb = exp.type.toBasetype(); 3464 //printf("tb: %s, deco = %s\n", tb.toChars(), tb.deco); 3465 if (arrayExpressionSemantic(exp.newargs, sc) || 3466 preFunctionParameters(sc, exp.newargs)) 3467 { 3468 return setError(); 3469 } 3470 if (arrayExpressionSemantic(exp.arguments, sc)) 3471 { 3472 return setError(); 3473 } 3474 //https://issues.dlang.org/show_bug.cgi?id=20547 3475 //exp.arguments are the "parameters" to [], not to a real function 3476 //so the errors that come from preFunctionParameters are misleading 3477 if (originalNewtype.ty == Tsarray) 3478 { 3479 if (preFunctionParameters(sc, exp.arguments, false)) 3480 { 3481 exp.error("cannot create a `%s` with `new`", originalNewtype.toChars()); 3482 return setError(); 3483 } 3484 } 3485 else if (preFunctionParameters(sc, exp.arguments)) 3486 { 3487 return setError(); 3488 } 3489 3490 if (exp.thisexp && tb.ty != Tclass) 3491 { 3492 exp.error("`.new` is only for allocating nested classes, not `%s`", tb.toChars()); 3493 return setError(); 3494 } 3495 3496 const size_t nargs = exp.arguments ? exp.arguments.dim : 0; 3497 Expression newprefix = null; 3498 3499 if (tb.ty == Tclass) 3500 { 3501 auto cd = (cast(TypeClass)tb).sym; 3502 cd.size(exp.loc); 3503 if (cd.sizeok != Sizeok.done) 3504 return setError(); 3505 if (!cd.ctor) 3506 cd.ctor = cd.searchCtor(); 3507 if (cd.noDefaultCtor && !nargs && !cd.defaultCtor) 3508 { 3509 exp.error("default construction is disabled for type `%s`", cd.type.toChars()); 3510 return setError(); 3511 } 3512 3513 if (cd.isInterfaceDeclaration()) 3514 { 3515 exp.error("cannot create instance of interface `%s`", cd.toChars()); 3516 return setError(); 3517 } 3518 3519 if (cd.isAbstract()) 3520 { 3521 exp.error("cannot create instance of abstract class `%s`", cd.toChars()); 3522 for (size_t i = 0; i < cd.vtbl.dim; i++) 3523 { 3524 FuncDeclaration fd = cd.vtbl[i].isFuncDeclaration(); 3525 if (fd && fd.isAbstract()) 3526 { 3527 errorSupplemental(exp.loc, "function `%s` is not implemented", 3528 fd.toFullSignature()); 3529 } 3530 } 3531 return setError(); 3532 } 3533 // checkDeprecated() is already done in newtype.typeSemantic(). 3534 3535 if (cd.isNested()) 3536 { 3537 /* We need a 'this' pointer for the nested class. 3538 * Ensure we have the right one. 3539 */ 3540 Dsymbol s = cd.toParentLocal(); 3541 3542 //printf("cd isNested, parent = %s '%s'\n", s.kind(), s.toPrettyChars()); 3543 if (auto cdn = s.isClassDeclaration()) 3544 { 3545 if (!cdthis) 3546 { 3547 // Supply an implicit 'this' and try again 3548 exp.thisexp = new ThisExp(exp.loc); 3549 for (Dsymbol sp = sc.parent; 1; sp = sp.toParentLocal()) 3550 { 3551 if (!sp) 3552 { 3553 exp.error("outer class `%s` `this` needed to `new` nested class `%s`", 3554 cdn.toChars(), cd.toChars()); 3555 return setError(); 3556 } 3557 ClassDeclaration cdp = sp.isClassDeclaration(); 3558 if (!cdp) 3559 continue; 3560 if (cdp == cdn || cdn.isBaseOf(cdp, null)) 3561 break; 3562 // Add a '.outer' and try again 3563 exp.thisexp = new DotIdExp(exp.loc, exp.thisexp, Id.outer); 3564 } 3565 3566 exp.thisexp = exp.thisexp.expressionSemantic(sc); 3567 if (exp.thisexp.op == TOK.error) 3568 return setError(); 3569 cdthis = exp.thisexp.type.isClassHandle(); 3570 } 3571 if (cdthis != cdn && !cdn.isBaseOf(cdthis, null)) 3572 { 3573 //printf("cdthis = %s\n", cdthis.toChars()); 3574 exp.error("`this` for nested class must be of type `%s`, not `%s`", 3575 cdn.toChars(), exp.thisexp.type.toChars()); 3576 return setError(); 3577 } 3578 if (!MODimplicitConv(exp.thisexp.type.mod, exp.newtype.mod)) 3579 { 3580 exp.error("nested type `%s` should have the same or weaker constancy as enclosing type `%s`", 3581 exp.newtype.toChars(), exp.thisexp.type.toChars()); 3582 return setError(); 3583 } 3584 } 3585 else if (exp.thisexp) 3586 { 3587 exp.error("`.new` is only for allocating nested classes"); 3588 return setError(); 3589 } 3590 else if (auto fdn = s.isFuncDeclaration()) 3591 { 3592 // make sure the parent context fdn of cd is reachable from sc 3593 if (!ensureStaticLinkTo(sc.parent, fdn)) 3594 { 3595 exp.error("outer function context of `%s` is needed to `new` nested class `%s`", 3596 fdn.toPrettyChars(), cd.toPrettyChars()); 3597 return setError(); 3598 } 3599 } 3600 else 3601 assert(0); 3602 } 3603 else if (exp.thisexp) 3604 { 3605 exp.error("`.new` is only for allocating nested classes"); 3606 return setError(); 3607 } 3608 3609 if (cd.vthis2) 3610 { 3611 if (AggregateDeclaration ad2 = cd.isMember2()) 3612 { 3613 Expression te = new ThisExp(exp.loc).expressionSemantic(sc); 3614 if (te.op != TOK.error) 3615 te = getRightThis(exp.loc, sc, ad2, te, cd); 3616 if (te.op == TOK.error) 3617 { 3618 exp.error("need `this` of type `%s` needed to `new` nested class `%s`", ad2.toChars(), cd.toChars()); 3619 return setError(); 3620 } 3621 } 3622 } 3623 3624 if (cd.aggNew) 3625 { 3626 // Prepend the size argument to newargs[] 3627 Expression e = new IntegerExp(exp.loc, cd.size(exp.loc), Type.tsize_t); 3628 if (!exp.newargs) 3629 exp.newargs = new Expressions(); 3630 exp.newargs.shift(e); 3631 3632 FuncDeclaration f = resolveFuncCall(exp.loc, sc, cd.aggNew, null, tb, exp.newargs, FuncResolveFlag.standard); 3633 if (!f || f.errors) 3634 return setError(); 3635 3636 checkFunctionAttributes(exp, sc, f); 3637 checkAccess(cd, exp.loc, sc, f); 3638 3639 TypeFunction tf = cast(TypeFunction)f.type; 3640 Type rettype; 3641 if (functionParameters(exp.loc, sc, tf, null, null, exp.newargs, f, &rettype, &newprefix)) 3642 return setError(); 3643 3644 exp.allocator = f.isNewDeclaration(); 3645 assert(exp.allocator); 3646 } 3647 else 3648 { 3649 if (exp.newargs && exp.newargs.dim) 3650 { 3651 exp.error("no allocator for `%s`", cd.toChars()); 3652 return setError(); 3653 } 3654 } 3655 3656 if (cd.ctor) 3657 { 3658 FuncDeclaration f = resolveFuncCall(exp.loc, sc, cd.ctor, null, tb, exp.arguments, FuncResolveFlag.standard); 3659 if (!f || f.errors) 3660 return setError(); 3661 3662 checkFunctionAttributes(exp, sc, f); 3663 checkAccess(cd, exp.loc, sc, f); 3664 3665 TypeFunction tf = cast(TypeFunction)f.type; 3666 if (!exp.arguments) 3667 exp.arguments = new Expressions(); 3668 if (functionParameters(exp.loc, sc, tf, null, exp.type, exp.arguments, f, &exp.type, &exp.argprefix)) 3669 return setError(); 3670 3671 exp.member = f.isCtorDeclaration(); 3672 assert(exp.member); 3673 } 3674 else 3675 { 3676 if (nargs) 3677 { 3678 exp.error("no constructor for `%s`", cd.toChars()); 3679 return setError(); 3680 } 3681 3682 // https://issues.dlang.org/show_bug.cgi?id=19941 3683 // Run semantic on all field initializers to resolve any forward 3684 // references. This is the same as done for structs in sd.fill(). 3685 for (ClassDeclaration c = cd; c; c = c.baseClass) 3686 { 3687 foreach (v; c.fields) 3688 { 3689 if (v.inuse || v._scope is null || v._init is null || 3690 v._init.isVoidInitializer()) 3691 continue; 3692 v.inuse++; 3693 v._init = v._init.initializerSemantic(v._scope, v.type, INITinterpret); 3694 v.inuse--; 3695 } 3696 } 3697 } 3698 } 3699 else if (tb.ty == Tstruct) 3700 { 3701 auto sd = (cast(TypeStruct)tb).sym; 3702 sd.size(exp.loc); 3703 if (sd.sizeok != Sizeok.done) 3704 return setError(); 3705 if (!sd.ctor) 3706 sd.ctor = sd.searchCtor(); 3707 if (sd.noDefaultCtor && !nargs) 3708 { 3709 exp.error("default construction is disabled for type `%s`", sd.type.toChars()); 3710 return setError(); 3711 } 3712 // checkDeprecated() is already done in newtype.typeSemantic(). 3713 3714 if (sd.aggNew) 3715 { 3716 // Prepend the uint size argument to newargs[] 3717 Expression e = new IntegerExp(exp.loc, sd.size(exp.loc), Type.tsize_t); 3718 if (!exp.newargs) 3719 exp.newargs = new Expressions(); 3720 exp.newargs.shift(e); 3721 3722 FuncDeclaration f = resolveFuncCall(exp.loc, sc, sd.aggNew, null, tb, exp.newargs, FuncResolveFlag.standard); 3723 if (!f || f.errors) 3724 return setError(); 3725 3726 checkFunctionAttributes(exp, sc, f); 3727 checkAccess(sd, exp.loc, sc, f); 3728 3729 TypeFunction tf = cast(TypeFunction)f.type; 3730 Type rettype; 3731 if (functionParameters(exp.loc, sc, tf, null, null, exp.newargs, f, &rettype, &newprefix)) 3732 return setError(); 3733 3734 exp.allocator = f.isNewDeclaration(); 3735 assert(exp.allocator); 3736 } 3737 else 3738 { 3739 if (exp.newargs && exp.newargs.dim) 3740 { 3741 exp.error("no allocator for `%s`", sd.toChars()); 3742 return setError(); 3743 } 3744 } 3745 3746 if (sd.ctor && nargs) 3747 { 3748 FuncDeclaration f = resolveFuncCall(exp.loc, sc, sd.ctor, null, tb, exp.arguments, FuncResolveFlag.standard); 3749 if (!f || f.errors) 3750 return setError(); 3751 3752 checkFunctionAttributes(exp, sc, f); 3753 checkAccess(sd, exp.loc, sc, f); 3754 3755 TypeFunction tf = cast(TypeFunction)f.type; 3756 if (!exp.arguments) 3757 exp.arguments = new Expressions(); 3758 if (functionParameters(exp.loc, sc, tf, null, exp.type, exp.arguments, f, &exp.type, &exp.argprefix)) 3759 return setError(); 3760 3761 exp.member = f.isCtorDeclaration(); 3762 assert(exp.member); 3763 3764 if (checkFrameAccess(exp.loc, sc, sd, sd.fields.dim)) 3765 return setError(); 3766 } 3767 else 3768 { 3769 if (!exp.arguments) 3770 exp.arguments = new Expressions(); 3771 3772 if (!sd.fit(exp.loc, sc, exp.arguments, tb)) 3773 return setError(); 3774 3775 if (!sd.fill(exp.loc, exp.arguments, false)) 3776 return setError(); 3777 3778 if (checkFrameAccess(exp.loc, sc, sd, exp.arguments ? exp.arguments.dim : 0)) 3779 return setError(); 3780 3781 /* Since a `new` allocation may escape, check each of the arguments for escaping 3782 */ 3783 if (global.params.vsafe) 3784 { 3785 foreach (arg; *exp.arguments) 3786 { 3787 if (arg && checkNewEscape(sc, arg, false)) 3788 return setError(); 3789 } 3790 } 3791 } 3792 3793 exp.type = exp.type.pointerTo(); 3794 } 3795 else if (tb.ty == Tarray) 3796 { 3797 if (!nargs) 3798 { 3799 // https://issues.dlang.org/show_bug.cgi?id=20422 3800 // Without this check the compiler would give a misleading error 3801 exp.error("missing length argument for array"); 3802 return setError(); 3803 } 3804 3805 Type tn = tb.nextOf().baseElemOf(); 3806 Dsymbol s = tn.toDsymbol(sc); 3807 AggregateDeclaration ad = s ? s.isAggregateDeclaration() : null; 3808 if (ad && ad.noDefaultCtor) 3809 { 3810 exp.error("default construction is disabled for type `%s`", tb.nextOf().toChars()); 3811 return setError(); 3812 } 3813 for (size_t i = 0; i < nargs; i++) 3814 { 3815 if (tb.ty != Tarray) 3816 { 3817 exp.error("too many arguments for array"); 3818 return setError(); 3819 } 3820 3821 Expression arg = (*exp.arguments)[i]; 3822 arg = resolveProperties(sc, arg); 3823 arg = arg.implicitCastTo(sc, Type.tsize_t); 3824 if (arg.op == TOK.error) 3825 return setError(); 3826 arg = arg.optimize(WANTvalue); 3827 if (arg.op == TOK.int64 && cast(sinteger_t)arg.toInteger() < 0) 3828 { 3829 exp.error("negative array index `%s`", arg.toChars()); 3830 return setError(); 3831 } 3832 (*exp.arguments)[i] = arg; 3833 tb = (cast(TypeDArray)tb).next.toBasetype(); 3834 } 3835 } 3836 else if (tb.isscalar()) 3837 { 3838 if (!nargs) 3839 { 3840 } 3841 else if (nargs == 1) 3842 { 3843 Expression e = (*exp.arguments)[0]; 3844 e = e.implicitCastTo(sc, tb); 3845 (*exp.arguments)[0] = e; 3846 } 3847 else 3848 { 3849 exp.error("more than one argument for construction of `%s`", exp.type.toChars()); 3850 return setError(); 3851 } 3852 3853 exp.type = exp.type.pointerTo(); 3854 } 3855 else 3856 { 3857 exp.error("cannot create a `%s` with `new`", exp.type.toChars()); 3858 return setError(); 3859 } 3860 3861 //printf("NewExp: '%s'\n", toChars()); 3862 //printf("NewExp:type '%s'\n", type.toChars()); 3863 semanticTypeInfo(sc, exp.type); 3864 3865 if (newprefix) 3866 { 3867 result = Expression.combine(newprefix, exp); 3868 return; 3869 } 3870 result = exp; 3871 } 3872 3873 override void visit(NewAnonClassExp e) 3874 { 3875 static if (LOGSEMANTIC) 3876 { 3877 printf("NewAnonClassExp::semantic() %s\n", e.toChars()); 3878 //printf("thisexp = %p\n", thisexp); 3879 //printf("type: %s\n", type.toChars()); 3880 } 3881 3882 Expression d = new DeclarationExp(e.loc, e.cd); 3883 sc = sc.push(); // just create new scope 3884 sc.flags &= ~SCOPE.ctfe; // temporary stop CTFE 3885 d = d.expressionSemantic(sc); 3886 sc = sc.pop(); 3887 3888 if (!e.cd.errors && sc.intypeof && !sc.parent.inNonRoot()) 3889 { 3890 ScopeDsymbol sds = sc.tinst ? cast(ScopeDsymbol)sc.tinst : sc._module; 3891 if (!sds.members) 3892 sds.members = new Dsymbols(); 3893 sds.members.push(e.cd); 3894 } 3895 3896 Expression n = new NewExp(e.loc, e.thisexp, e.newargs, e.cd.type, e.arguments); 3897 3898 Expression c = new CommaExp(e.loc, d, n); 3899 result = c.expressionSemantic(sc); 3900 } 3901 3902 override void visit(SymOffExp e) 3903 { 3904 static if (LOGSEMANTIC) 3905 { 3906 printf("SymOffExp::semantic('%s')\n", e.toChars()); 3907 } 3908 //var.dsymbolSemantic(sc); 3909 if (!e.type) 3910 e.type = e.var.type.pointerTo(); 3911 3912 if (auto v = e.var.isVarDeclaration()) 3913 { 3914 if (v.checkNestedReference(sc, e.loc)) 3915 return setError(); 3916 } 3917 else if (auto f = e.var.isFuncDeclaration()) 3918 { 3919 if (f.checkNestedReference(sc, e.loc)) 3920 return setError(); 3921 } 3922 3923 result = e; 3924 } 3925 3926 override void visit(VarExp e) 3927 { 3928 static if (LOGSEMANTIC) 3929 { 3930 printf("VarExp::semantic(%s)\n", e.toChars()); 3931 } 3932 3933 auto vd = e.var.isVarDeclaration(); 3934 auto fd = e.var.isFuncDeclaration(); 3935 3936 if (fd) 3937 { 3938 //printf("L%d fd = %s\n", __LINE__, f.toChars()); 3939 if (!fd.functionSemantic()) 3940 return setError(); 3941 } 3942 3943 if (!e.type) 3944 e.type = e.var.type; 3945 if (e.type && !e.type.deco) 3946 { 3947 auto decl = e.var.isDeclaration(); 3948 if (decl) 3949 decl.inuse++; 3950 e.type = e.type.typeSemantic(e.loc, sc); 3951 if (decl) 3952 decl.inuse--; 3953 } 3954 3955 /* Fix for 1161 doesn't work because it causes protection 3956 * problems when instantiating imported templates passing private 3957 * variables as alias template parameters. 3958 */ 3959 //checkAccess(loc, sc, NULL, var); 3960 3961 if (vd) 3962 { 3963 if (vd.checkNestedReference(sc, e.loc)) 3964 return setError(); 3965 3966 // https://issues.dlang.org/show_bug.cgi?id=12025 3967 // If the variable is not actually used in runtime code, 3968 // the purity violation error is redundant. 3969 //checkPurity(sc, vd); 3970 } 3971 else if (fd) 3972 { 3973 // TODO: If fd isn't yet resolved its overload, the checkNestedReference 3974 // call would cause incorrect validation. 3975 // Maybe here should be moved in CallExp, or AddrExp for functions. 3976 if (fd.checkNestedReference(sc, e.loc)) 3977 return setError(); 3978 } 3979 else if (auto od = e.var.isOverDeclaration()) 3980 { 3981 e.type = Type.tvoid; // ambiguous type? 3982 } 3983 3984 result = e; 3985 } 3986 3987 override void visit(FuncExp exp) 3988 { 3989 static if (LOGSEMANTIC) 3990 { 3991 printf("FuncExp::semantic(%s)\n", exp.toChars()); 3992 if (exp.fd.treq) 3993 printf(" treq = %s\n", exp.fd.treq.toChars()); 3994 } 3995 3996 if (exp.type) 3997 { 3998 result = exp; 3999 return; 4000 } 4001 4002 Expression e = exp; 4003 uint olderrors; 4004 4005 sc = sc.push(); // just create new scope 4006 sc.flags &= ~SCOPE.ctfe; // temporary stop CTFE 4007 sc.protection = Prot(Prot.Kind.public_); // https://issues.dlang.org/show_bug.cgi?id=12506 4008 4009 /* fd.treq might be incomplete type, 4010 * so should not semantic it. 4011 * void foo(T)(T delegate(int) dg){} 4012 * foo(a=>a); // in IFTI, treq == T delegate(int) 4013 */ 4014 //if (fd.treq) 4015 // fd.treq = fd.treq.dsymbolSemantic(loc, sc); 4016 4017 exp.genIdent(sc); 4018 4019 // Set target of return type inference 4020 if (exp.fd.treq && !exp.fd.type.nextOf()) 4021 { 4022 TypeFunction tfv = null; 4023 if (exp.fd.treq.ty == Tdelegate || (exp.fd.treq.ty == Tpointer && exp.fd.treq.nextOf().ty == Tfunction)) 4024 tfv = cast(TypeFunction)exp.fd.treq.nextOf(); 4025 if (tfv) 4026 { 4027 TypeFunction tfl = cast(TypeFunction)exp.fd.type; 4028 tfl.next = tfv.nextOf(); 4029 } 4030 } 4031 4032 //printf("td = %p, treq = %p\n", td, fd.treq); 4033 if (exp.td) 4034 { 4035 assert(exp.td.parameters && exp.td.parameters.dim); 4036 exp.td.dsymbolSemantic(sc); 4037 exp.type = Type.tvoid; // temporary type 4038 4039 if (exp.fd.treq) // defer type determination 4040 { 4041 FuncExp fe; 4042 if (exp.matchType(exp.fd.treq, sc, &fe) > MATCH.nomatch) 4043 e = fe; 4044 else 4045 e = ErrorExp.get(); 4046 } 4047 goto Ldone; 4048 } 4049 4050 olderrors = global.errors; 4051 exp.fd.dsymbolSemantic(sc); 4052 if (olderrors == global.errors) 4053 { 4054 exp.fd.semantic2(sc); 4055 if (olderrors == global.errors) 4056 exp.fd.semantic3(sc); 4057 } 4058 if (olderrors != global.errors) 4059 { 4060 if (exp.fd.type && exp.fd.type.ty == Tfunction && !exp.fd.type.nextOf()) 4061 (cast(TypeFunction)exp.fd.type).next = Type.terror; 4062 e = ErrorExp.get(); 4063 goto Ldone; 4064 } 4065 4066 // Type is a "delegate to" or "pointer to" the function literal 4067 if ((exp.fd.isNested() && exp.fd.tok == TOK.delegate_) || (exp.tok == TOK.reserved && exp.fd.treq && exp.fd.treq.ty == Tdelegate)) 4068 { 4069 exp.type = new TypeDelegate(exp.fd.type); 4070 exp.type = exp.type.typeSemantic(exp.loc, sc); 4071 4072 exp.fd.tok = TOK.delegate_; 4073 } 4074 else 4075 { 4076 exp.type = new TypePointer(exp.fd.type); 4077 exp.type = exp.type.typeSemantic(exp.loc, sc); 4078 //type = fd.type.pointerTo(); 4079 4080 /* A lambda expression deduced to function pointer might become 4081 * to a delegate literal implicitly. 4082 * 4083 * auto foo(void function() fp) { return 1; } 4084 * assert(foo({}) == 1); 4085 * 4086 * So, should keep fd.tok == TOKreserve if fd.treq == NULL. 4087 */ 4088 if (exp.fd.treq && exp.fd.treq.ty == Tpointer) 4089 { 4090 // change to non-nested 4091 exp.fd.tok = TOK.function_; 4092 exp.fd.vthis = null; 4093 } 4094 } 4095 exp.fd.tookAddressOf++; 4096 4097 Ldone: 4098 sc = sc.pop(); 4099 result = e; 4100 } 4101 4102 /** 4103 * Perform semantic analysis on function literals 4104 * 4105 * Test the following construct: 4106 * --- 4107 * (x, y, z) { return x + y + z; }(42, 84, 1992); 4108 * --- 4109 */ 4110 Expression callExpSemantic(FuncExp exp, Scope* sc, Expressions* arguments) 4111 { 4112 if ((!exp.type || exp.type == Type.tvoid) && exp.td && arguments && arguments.dim) 4113 { 4114 for (size_t k = 0; k < arguments.dim; k++) 4115 { 4116 Expression checkarg = (*arguments)[k]; 4117 if (checkarg.op == TOK.error) 4118 return checkarg; 4119 } 4120 4121 exp.genIdent(sc); 4122 4123 assert(exp.td.parameters && exp.td.parameters.dim); 4124 exp.td.dsymbolSemantic(sc); 4125 4126 TypeFunction tfl = cast(TypeFunction)exp.fd.type; 4127 size_t dim = tfl.parameterList.length; 4128 if (arguments.dim < dim) 4129 { 4130 // Default arguments are always typed, so they don't need inference. 4131 Parameter p = tfl.parameterList[arguments.dim]; 4132 if (p.defaultArg) 4133 dim = arguments.dim; 4134 } 4135 4136 if ((tfl.parameterList.varargs == VarArg.none && arguments.dim > dim) || 4137 arguments.dim < dim) 4138 { 4139 OutBuffer buf; 4140 foreach (idx, ref arg; *arguments) 4141 buf.printf("%s%s", (idx ? ", ".ptr : "".ptr), arg.type.toChars()); 4142 exp.error("function literal `%s%s` is not callable using argument types `(%s)`", 4143 exp.fd.toChars(), parametersTypeToChars(tfl.parameterList), 4144 buf.peekChars()); 4145 exp.errorSupplemental("too %s arguments, expected `%d`, got `%d`", 4146 arguments.dim < dim ? "few".ptr : "many".ptr, 4147 cast(int)dim, cast(int)arguments.dim); 4148 return ErrorExp.get(); 4149 } 4150 4151 auto tiargs = new Objects(); 4152 tiargs.reserve(exp.td.parameters.dim); 4153 4154 for (size_t i = 0; i < exp.td.parameters.dim; i++) 4155 { 4156 TemplateParameter tp = (*exp.td.parameters)[i]; 4157 assert(dim <= tfl.parameterList.length); 4158 foreach (u, p; tfl.parameterList) 4159 { 4160 if (u == dim) 4161 break; 4162 4163 if (p.type.ty == Tident && (cast(TypeIdentifier)p.type).ident == tp.ident) 4164 { 4165 Expression e = (*arguments)[u]; 4166 tiargs.push(e.type); 4167 break; 4168 } 4169 } 4170 } 4171 4172 auto ti = Pool!TemplateInstance.make(exp.loc, exp.td, tiargs); 4173 return (new ScopeExp(exp.loc, ti)).expressionSemantic(sc); 4174 } 4175 return exp.expressionSemantic(sc); 4176 } 4177 4178 override void visit(CallExp exp) 4179 { 4180 static if (LOGSEMANTIC) 4181 { 4182 printf("CallExp::semantic() %s\n", exp.toChars()); 4183 } 4184 if (exp.type) 4185 { 4186 result = exp; 4187 return; // semantic() already run 4188 } 4189 4190 Objects* tiargs = null; // initial list of template arguments 4191 Expression ethis = null; 4192 Type tthis = null; 4193 Expression e1org = exp.e1; 4194 4195 if (exp.e1.op == TOK.comma) 4196 { 4197 /* Rewrite (a,b)(args) as (a,(b(args))) 4198 */ 4199 auto ce = cast(CommaExp)exp.e1; 4200 exp.e1 = ce.e2; 4201 ce.e2 = exp; 4202 result = ce.expressionSemantic(sc); 4203 return; 4204 } 4205 if (exp.e1.op == TOK.delegate_) 4206 { 4207 DelegateExp de = cast(DelegateExp)exp.e1; 4208 exp.e1 = new DotVarExp(de.loc, de.e1, de.func, de.hasOverloads); 4209 visit(exp); 4210 return; 4211 } 4212 if (exp.e1.op == TOK.function_) 4213 { 4214 if (arrayExpressionSemantic(exp.arguments, sc) || preFunctionParameters(sc, exp.arguments)) 4215 return setError(); 4216 4217 // Run e1 semantic even if arguments have any errors 4218 FuncExp fe = cast(FuncExp)exp.e1; 4219 exp.e1 = callExpSemantic(fe, sc, exp.arguments); 4220 if (exp.e1.op == TOK.error) 4221 { 4222 result = exp.e1; 4223 return; 4224 } 4225 } 4226 4227 if (Expression ex = resolveUFCS(sc, exp)) 4228 { 4229 result = ex; 4230 return; 4231 } 4232 4233 /* This recognizes: 4234 * foo!(tiargs)(funcargs) 4235 */ 4236 if (exp.e1.op == TOK.scope_) 4237 { 4238 ScopeExp se = cast(ScopeExp)exp.e1; 4239 TemplateInstance ti = se.sds.isTemplateInstance(); 4240 if (ti) 4241 { 4242 /* Attempt to instantiate ti. If that works, go with it. 4243 * If not, go with partial explicit specialization. 4244 */ 4245 WithScopeSymbol withsym; 4246 if (!ti.findTempDecl(sc, &withsym) || !ti.semanticTiargs(sc)) 4247 return setError(); 4248 if (withsym && withsym.withstate.wthis) 4249 { 4250 exp.e1 = new VarExp(exp.e1.loc, withsym.withstate.wthis); 4251 exp.e1 = new DotTemplateInstanceExp(exp.e1.loc, exp.e1, ti); 4252 goto Ldotti; 4253 } 4254 if (ti.needsTypeInference(sc, 1)) 4255 { 4256 /* Go with partial explicit specialization 4257 */ 4258 tiargs = ti.tiargs; 4259 assert(ti.tempdecl); 4260 if (TemplateDeclaration td = ti.tempdecl.isTemplateDeclaration()) 4261 exp.e1 = new TemplateExp(exp.loc, td); 4262 else if (OverDeclaration od = ti.tempdecl.isOverDeclaration()) 4263 exp.e1 = new VarExp(exp.loc, od); 4264 else 4265 exp.e1 = new OverExp(exp.loc, ti.tempdecl.isOverloadSet()); 4266 } 4267 else 4268 { 4269 Expression e1x = exp.e1.expressionSemantic(sc); 4270 if (e1x.op == TOK.error) 4271 { 4272 result = e1x; 4273 return; 4274 } 4275 exp.e1 = e1x; 4276 } 4277 } 4278 } 4279 4280 /* This recognizes: 4281 * expr.foo!(tiargs)(funcargs) 4282 */ 4283 Ldotti: 4284 if (exp.e1.op == TOK.dotTemplateInstance && !exp.e1.type) 4285 { 4286 DotTemplateInstanceExp se = cast(DotTemplateInstanceExp)exp.e1; 4287 TemplateInstance ti = se.ti; 4288 { 4289 /* Attempt to instantiate ti. If that works, go with it. 4290 * If not, go with partial explicit specialization. 4291 */ 4292 if (!se.findTempDecl(sc) || !ti.semanticTiargs(sc)) 4293 return setError(); 4294 if (ti.needsTypeInference(sc, 1)) 4295 { 4296 /* Go with partial explicit specialization 4297 */ 4298 tiargs = ti.tiargs; 4299 assert(ti.tempdecl); 4300 if (TemplateDeclaration td = ti.tempdecl.isTemplateDeclaration()) 4301 exp.e1 = new DotTemplateExp(exp.loc, se.e1, td); 4302 else if (OverDeclaration od = ti.tempdecl.isOverDeclaration()) 4303 { 4304 exp.e1 = new DotVarExp(exp.loc, se.e1, od, true); 4305 } 4306 else 4307 exp.e1 = new DotExp(exp.loc, se.e1, new OverExp(exp.loc, ti.tempdecl.isOverloadSet())); 4308 } 4309 else 4310 { 4311 Expression e1x = exp.e1.expressionSemantic(sc); 4312 if (e1x.op == TOK.error) 4313 { 4314 result = e1x; 4315 return; 4316 } 4317 exp.e1 = e1x; 4318 } 4319 } 4320 } 4321 4322 Lagain: 4323 //printf("Lagain: %s\n", toChars()); 4324 exp.f = null; 4325 if (exp.e1.op == TOK.this_ || exp.e1.op == TOK.super_) 4326 { 4327 // semantic() run later for these 4328 } 4329 else 4330 { 4331 if (exp.e1.op == TOK.dotIdentifier) 4332 { 4333 DotIdExp die = cast(DotIdExp)exp.e1; 4334 exp.e1 = die.expressionSemantic(sc); 4335 /* Look for e1 having been rewritten to expr.opDispatch!(string) 4336 * We handle such earlier, so go back. 4337 * Note that in the rewrite, we carefully did not run semantic() on e1 4338 */ 4339 if (exp.e1.op == TOK.dotTemplateInstance && !exp.e1.type) 4340 { 4341 goto Ldotti; 4342 } 4343 } 4344 else 4345 { 4346 __gshared int nest; 4347 if (++nest > global.recursionLimit) 4348 { 4349 exp.error("recursive evaluation of `%s`", exp.toChars()); 4350 --nest; 4351 return setError(); 4352 } 4353 Expression ex = unaSemantic(exp, sc); 4354 --nest; 4355 if (ex) 4356 { 4357 result = ex; 4358 return; 4359 } 4360 } 4361 4362 /* Look for e1 being a lazy parameter 4363 */ 4364 if (exp.e1.op == TOK.variable) 4365 { 4366 VarExp ve = cast(VarExp)exp.e1; 4367 if (ve.var.storage_class & STC.lazy_) 4368 { 4369 // lazy parameters can be called without violating purity and safety 4370 Type tw = ve.var.type; 4371 Type tc = ve.var.type.substWildTo(MODFlags.const_); 4372 auto tf = new TypeFunction(ParameterList(), tc, LINK.d, STC.safe | STC.pure_); 4373 (tf = cast(TypeFunction)tf.typeSemantic(exp.loc, sc)).next = tw; // hack for bug7757 4374 auto t = new TypeDelegate(tf); 4375 ve.type = t.typeSemantic(exp.loc, sc); 4376 } 4377 VarDeclaration v = ve.var.isVarDeclaration(); 4378 if (v && ve.checkPurity(sc, v)) 4379 return setError(); 4380 } 4381 4382 if (exp.e1.op == TOK.symbolOffset && (cast(SymOffExp)exp.e1).hasOverloads) 4383 { 4384 SymOffExp se = cast(SymOffExp)exp.e1; 4385 exp.e1 = new VarExp(se.loc, se.var, true); 4386 exp.e1 = exp.e1.expressionSemantic(sc); 4387 } 4388 else if (exp.e1.op == TOK.dot) 4389 { 4390 DotExp de = cast(DotExp)exp.e1; 4391 4392 if (de.e2.op == TOK.overloadSet) 4393 { 4394 ethis = de.e1; 4395 tthis = de.e1.type; 4396 exp.e1 = de.e2; 4397 } 4398 } 4399 else if (exp.e1.op == TOK.star && exp.e1.type.ty == Tfunction) 4400 { 4401 // Rewrite (*fp)(arguments) to fp(arguments) 4402 exp.e1 = (cast(PtrExp)exp.e1).e1; 4403 } 4404 } 4405 4406 Type t1 = exp.e1.type ? exp.e1.type.toBasetype() : null; 4407 4408 if (exp.e1.op == TOK.error) 4409 { 4410 result = exp.e1; 4411 return; 4412 } 4413 if (arrayExpressionSemantic(exp.arguments, sc) || preFunctionParameters(sc, exp.arguments)) 4414 return setError(); 4415 4416 // Check for call operator overload 4417 if (t1) 4418 { 4419 if (t1.ty == Tstruct) 4420 { 4421 auto sd = (cast(TypeStruct)t1).sym; 4422 sd.size(exp.loc); // Resolve forward references to construct object 4423 if (sd.sizeok != Sizeok.done) 4424 return setError(); 4425 if (!sd.ctor) 4426 sd.ctor = sd.searchCtor(); 4427 /* If `sd.ctor` is a generated copy constructor, this means that it 4428 is the single constructor that this struct has. In order to not 4429 disable default construction, the ctor is nullified. The side effect 4430 of this is that the generated copy constructor cannot be called 4431 explicitly, but that is ok, because when calling a constructor the 4432 default constructor should have priority over the generated copy 4433 constructor. 4434 */ 4435 if (sd.ctor) 4436 { 4437 auto ctor = sd.ctor.isCtorDeclaration(); 4438 if (ctor && ctor.isCpCtor && ctor.generated) 4439 sd.ctor = null; 4440 } 4441 4442 // First look for constructor 4443 if (exp.e1.op == TOK.type && sd.ctor) 4444 { 4445 if (!sd.noDefaultCtor && !(exp.arguments && exp.arguments.dim)) 4446 goto Lx; 4447 4448 auto sle = new StructLiteralExp(exp.loc, sd, null, exp.e1.type); 4449 if (!sd.fill(exp.loc, sle.elements, true)) 4450 return setError(); 4451 if (checkFrameAccess(exp.loc, sc, sd, sle.elements.dim)) 4452 return setError(); 4453 4454 // https://issues.dlang.org/show_bug.cgi?id=14556 4455 // Set concrete type to avoid further redundant semantic(). 4456 sle.type = exp.e1.type; 4457 4458 /* Constructor takes a mutable object, so don't use 4459 * the immutable initializer symbol. 4460 */ 4461 sle.useStaticInit = false; 4462 4463 Expression e = sle; 4464 if (auto cf = sd.ctor.isCtorDeclaration()) 4465 { 4466 e = new DotVarExp(exp.loc, e, cf, true); 4467 } 4468 else if (auto td = sd.ctor.isTemplateDeclaration()) 4469 { 4470 e = new DotIdExp(exp.loc, e, td.ident); 4471 } 4472 else if (auto os = sd.ctor.isOverloadSet()) 4473 { 4474 e = new DotExp(exp.loc, e, new OverExp(exp.loc, os)); 4475 } 4476 else 4477 assert(0); 4478 e = new CallExp(exp.loc, e, exp.arguments); 4479 e = e.expressionSemantic(sc); 4480 result = e; 4481 return; 4482 } 4483 // No constructor, look for overload of opCall 4484 if (search_function(sd, Id.call)) 4485 goto L1; 4486 // overload of opCall, therefore it's a call 4487 if (exp.e1.op != TOK.type) 4488 { 4489 if (sd.aliasthis && exp.e1.type != exp.att1) 4490 { 4491 if (!exp.att1 && exp.e1.type.checkAliasThisRec()) 4492 exp.att1 = exp.e1.type; 4493 exp.e1 = resolveAliasThis(sc, exp.e1); 4494 goto Lagain; 4495 } 4496 exp.error("%s `%s` does not overload ()", sd.kind(), sd.toChars()); 4497 return setError(); 4498 } 4499 4500 /* It's a struct literal 4501 */ 4502 Lx: 4503 Expression e = new StructLiteralExp(exp.loc, sd, exp.arguments, exp.e1.type); 4504 e = e.expressionSemantic(sc); 4505 result = e; 4506 return; 4507 } 4508 else if (t1.ty == Tclass) 4509 { 4510 L1: 4511 // Rewrite as e1.call(arguments) 4512 Expression e = new DotIdExp(exp.loc, exp.e1, Id.call); 4513 e = new CallExp(exp.loc, e, exp.arguments); 4514 e = e.expressionSemantic(sc); 4515 result = e; 4516 return; 4517 } 4518 else if (exp.e1.op == TOK.type && t1.isscalar()) 4519 { 4520 Expression e; 4521 4522 // Make sure to use the the enum type itself rather than its 4523 // base type 4524 // https://issues.dlang.org/show_bug.cgi?id=16346 4525 if (exp.e1.type.ty == Tenum) 4526 { 4527 t1 = exp.e1.type; 4528 } 4529 4530 if (!exp.arguments || exp.arguments.dim == 0) 4531 { 4532 e = t1.defaultInitLiteral(exp.loc); 4533 } 4534 else if (exp.arguments.dim == 1) 4535 { 4536 e = (*exp.arguments)[0]; 4537 e = e.implicitCastTo(sc, t1); 4538 e = new CastExp(exp.loc, e, t1); 4539 } 4540 else 4541 { 4542 exp.error("more than one argument for construction of `%s`", t1.toChars()); 4543 return setError(); 4544 } 4545 e = e.expressionSemantic(sc); 4546 result = e; 4547 return; 4548 } 4549 } 4550 4551 static FuncDeclaration resolveOverloadSet(Loc loc, Scope* sc, 4552 OverloadSet os, Objects* tiargs, Type tthis, Expressions* arguments) 4553 { 4554 FuncDeclaration f = null; 4555 foreach (s; os.a) 4556 { 4557 if (tiargs && s.isFuncDeclaration()) 4558 continue; 4559 if (auto f2 = resolveFuncCall(loc, sc, s, tiargs, tthis, arguments, FuncResolveFlag.quiet)) 4560 { 4561 if (f2.errors) 4562 return null; 4563 if (f) 4564 { 4565 /* Error if match in more than one overload set, 4566 * even if one is a 'better' match than the other. 4567 */ 4568 ScopeDsymbol.multiplyDefined(loc, f, f2); 4569 } 4570 else 4571 f = f2; 4572 } 4573 } 4574 if (!f) 4575 .error(loc, "no overload matches for `%s`", os.toChars()); 4576 else if (f.errors) 4577 f = null; 4578 return f; 4579 } 4580 4581 bool isSuper = false; 4582 if (exp.e1.op == TOK.dotVariable && t1.ty == Tfunction || exp.e1.op == TOK.dotTemplateDeclaration) 4583 { 4584 UnaExp ue = cast(UnaExp)exp.e1; 4585 4586 Expression ue1 = ue.e1; 4587 Expression ue1old = ue1; // need for 'right this' check 4588 VarDeclaration v; 4589 if (ue1.op == TOK.variable && (v = (cast(VarExp)ue1).var.isVarDeclaration()) !is null && v.needThis()) 4590 { 4591 ue.e1 = new TypeExp(ue1.loc, ue1.type); 4592 ue1 = null; 4593 } 4594 4595 DotVarExp dve; 4596 DotTemplateExp dte; 4597 Dsymbol s; 4598 if (exp.e1.op == TOK.dotVariable) 4599 { 4600 dve = cast(DotVarExp)exp.e1; 4601 dte = null; 4602 s = dve.var; 4603 tiargs = null; 4604 } 4605 else 4606 { 4607 dve = null; 4608 dte = cast(DotTemplateExp)exp.e1; 4609 s = dte.td; 4610 } 4611 4612 // Do overload resolution 4613 exp.f = resolveFuncCall(exp.loc, sc, s, tiargs, ue1 ? ue1.type : null, exp.arguments, FuncResolveFlag.standard); 4614 if (!exp.f || exp.f.errors || exp.f.type.ty == Terror) 4615 return setError(); 4616 4617 if (exp.f.interfaceVirtual) 4618 { 4619 /* Cast 'this' to the type of the interface, and replace f with the interface's equivalent 4620 */ 4621 auto b = exp.f.interfaceVirtual; 4622 auto ad2 = b.sym; 4623 ue.e1 = ue.e1.castTo(sc, ad2.type.addMod(ue.e1.type.mod)); 4624 ue.e1 = ue.e1.expressionSemantic(sc); 4625 ue1 = ue.e1; 4626 auto vi = exp.f.findVtblIndex(&ad2.vtbl, cast(int)ad2.vtbl.dim); 4627 assert(vi >= 0); 4628 exp.f = ad2.vtbl[vi].isFuncDeclaration(); 4629 assert(exp.f); 4630 } 4631 if (exp.f.needThis()) 4632 { 4633 AggregateDeclaration ad = exp.f.toParentLocal().isAggregateDeclaration(); 4634 ue.e1 = getRightThis(exp.loc, sc, ad, ue.e1, exp.f); 4635 if (ue.e1.op == TOK.error) 4636 { 4637 result = ue.e1; 4638 return; 4639 } 4640 ethis = ue.e1; 4641 tthis = ue.e1.type; 4642 if (!(exp.f.type.ty == Tfunction && (cast(TypeFunction)exp.f.type).isScopeQual)) 4643 { 4644 if (global.params.vsafe && checkParamArgumentEscape(sc, exp.f, null, ethis, false, false)) 4645 return setError(); 4646 } 4647 } 4648 4649 /* Cannot call public functions from inside invariant 4650 * (because then the invariant would have infinite recursion) 4651 */ 4652 if (sc.func && sc.func.isInvariantDeclaration() && ue.e1.op == TOK.this_ && exp.f.addPostInvariant()) 4653 { 4654 exp.error("cannot call `public`/`export` function `%s` from invariant", exp.f.toChars()); 4655 return setError(); 4656 } 4657 4658 checkFunctionAttributes(exp, sc, exp.f); 4659 checkAccess(exp.loc, sc, ue.e1, exp.f); 4660 if (!exp.f.needThis()) 4661 { 4662 exp.e1 = Expression.combine(ue.e1, new VarExp(exp.loc, exp.f, false)); 4663 } 4664 else 4665 { 4666 if (ue1old.checkRightThis(sc)) 4667 return setError(); 4668 if (exp.e1.op == TOK.dotVariable) 4669 { 4670 dve.var = exp.f; 4671 exp.e1.type = exp.f.type; 4672 } 4673 else 4674 { 4675 exp.e1 = new DotVarExp(exp.loc, dte.e1, exp.f, false); 4676 exp.e1 = exp.e1.expressionSemantic(sc); 4677 if (exp.e1.op == TOK.error) 4678 return setError(); 4679 ue = cast(UnaExp)exp.e1; 4680 } 4681 version (none) 4682 { 4683 printf("ue.e1 = %s\n", ue.e1.toChars()); 4684 printf("f = %s\n", exp.f.toChars()); 4685 printf("t1 = %s\n", t1.toChars()); 4686 printf("e1 = %s\n", exp.e1.toChars()); 4687 printf("e1.type = %s\n", exp.e1.type.toChars()); 4688 } 4689 4690 // See if we need to adjust the 'this' pointer 4691 AggregateDeclaration ad = exp.f.isThis(); 4692 ClassDeclaration cd = ue.e1.type.isClassHandle(); 4693 if (ad && cd && ad.isClassDeclaration()) 4694 { 4695 if (ue.e1.op == TOK.dotType) 4696 { 4697 ue.e1 = (cast(DotTypeExp)ue.e1).e1; 4698 exp.directcall = true; 4699 } 4700 else if (ue.e1.op == TOK.super_) 4701 exp.directcall = true; 4702 else if ((cd.storage_class & STC.final_) != 0) // https://issues.dlang.org/show_bug.cgi?id=14211 4703 exp.directcall = true; 4704 4705 if (ad != cd) 4706 { 4707 ue.e1 = ue.e1.castTo(sc, ad.type.addMod(ue.e1.type.mod)); 4708 ue.e1 = ue.e1.expressionSemantic(sc); 4709 } 4710 } 4711 } 4712 // If we've got a pointer to a function then deference it 4713 // https://issues.dlang.org/show_bug.cgi?id=16483 4714 if (exp.e1.type.ty == Tpointer && exp.e1.type.nextOf().ty == Tfunction) 4715 { 4716 Expression e = new PtrExp(exp.loc, exp.e1); 4717 e.type = exp.e1.type.nextOf(); 4718 exp.e1 = e; 4719 } 4720 t1 = exp.e1.type; 4721 } 4722 else if (exp.e1.op == TOK.super_ || exp.e1.op == TOK.this_) 4723 { 4724 auto ad = sc.func ? sc.func.isThis() : null; 4725 auto cd = ad ? ad.isClassDeclaration() : null; 4726 4727 isSuper = exp.e1.op == TOK.super_; 4728 if (isSuper) 4729 { 4730 // Base class constructor call 4731 if (!cd || !cd.baseClass || !sc.func.isCtorDeclaration()) 4732 { 4733 exp.error("super class constructor call must be in a constructor"); 4734 return setError(); 4735 } 4736 if (!cd.baseClass.ctor) 4737 { 4738 exp.error("no super class constructor for `%s`", cd.baseClass.toChars()); 4739 return setError(); 4740 } 4741 } 4742 else 4743 { 4744 // `this` call expression must be inside a 4745 // constructor 4746 if (!ad || !sc.func.isCtorDeclaration()) 4747 { 4748 exp.error("constructor call must be in a constructor"); 4749 return setError(); 4750 } 4751 4752 // https://issues.dlang.org/show_bug.cgi?id=18719 4753 // If `exp` is a call expression to another constructor 4754 // then it means that all struct/class fields will be 4755 // initialized after this call. 4756 foreach (ref field; sc.ctorflow.fieldinit) 4757 { 4758 field.csx |= CSX.this_ctor; 4759 } 4760 } 4761 4762 if (!sc.intypeof && !(sc.ctorflow.callSuper & CSX.halt)) 4763 { 4764 if (sc.inLoop || sc.ctorflow.callSuper & CSX.label) 4765 exp.error("constructor calls not allowed in loops or after labels"); 4766 if (sc.ctorflow.callSuper & (CSX.super_ctor | CSX.this_ctor)) 4767 exp.error("multiple constructor calls"); 4768 if ((sc.ctorflow.callSuper & CSX.return_) && !(sc.ctorflow.callSuper & CSX.any_ctor)) 4769 exp.error("an earlier `return` statement skips constructor"); 4770 sc.ctorflow.callSuper |= CSX.any_ctor | (isSuper ? CSX.super_ctor : CSX.this_ctor); 4771 } 4772 4773 tthis = ad.type.addMod(sc.func.type.mod); 4774 auto ctor = isSuper ? cd.baseClass.ctor : ad.ctor; 4775 if (auto os = ctor.isOverloadSet()) 4776 exp.f = resolveOverloadSet(exp.loc, sc, os, null, tthis, exp.arguments); 4777 else 4778 exp.f = resolveFuncCall(exp.loc, sc, ctor, null, tthis, exp.arguments, FuncResolveFlag.standard); 4779 4780 if (!exp.f || exp.f.errors) 4781 return setError(); 4782 4783 checkFunctionAttributes(exp, sc, exp.f); 4784 checkAccess(exp.loc, sc, null, exp.f); 4785 4786 exp.e1 = new DotVarExp(exp.e1.loc, exp.e1, exp.f, false); 4787 exp.e1 = exp.e1.expressionSemantic(sc); 4788 // https://issues.dlang.org/show_bug.cgi?id=21095 4789 if (exp.e1.op == TOK.error) 4790 return setError(); 4791 t1 = exp.e1.type; 4792 4793 // BUG: this should really be done by checking the static 4794 // call graph 4795 if (exp.f == sc.func) 4796 { 4797 exp.error("cyclic constructor call"); 4798 return setError(); 4799 } 4800 } 4801 else if (exp.e1.op == TOK.overloadSet) 4802 { 4803 auto os = (cast(OverExp)exp.e1).vars; 4804 exp.f = resolveOverloadSet(exp.loc, sc, os, tiargs, tthis, exp.arguments); 4805 if (!exp.f) 4806 return setError(); 4807 if (ethis) 4808 exp.e1 = new DotVarExp(exp.loc, ethis, exp.f, false); 4809 else 4810 exp.e1 = new VarExp(exp.loc, exp.f, false); 4811 goto Lagain; 4812 } 4813 else if (!t1) 4814 { 4815 exp.error("function expected before `()`, not `%s`", exp.e1.toChars()); 4816 return setError(); 4817 } 4818 else if (t1.ty == Terror) 4819 { 4820 return setError(); 4821 } 4822 else if (t1.ty != Tfunction) 4823 { 4824 TypeFunction tf; 4825 const(char)* p; 4826 Dsymbol s; 4827 exp.f = null; 4828 if (exp.e1.op == TOK.function_) 4829 { 4830 // function literal that direct called is always inferred. 4831 assert((cast(FuncExp)exp.e1).fd); 4832 exp.f = (cast(FuncExp)exp.e1).fd; 4833 tf = cast(TypeFunction)exp.f.type; 4834 p = "function literal"; 4835 } 4836 else if (t1.ty == Tdelegate) 4837 { 4838 TypeDelegate td = cast(TypeDelegate)t1; 4839 assert(td.next.ty == Tfunction); 4840 tf = cast(TypeFunction)td.next; 4841 p = "delegate"; 4842 } 4843 else if (t1.ty == Tpointer && (cast(TypePointer)t1).next.ty == Tfunction) 4844 { 4845 tf = cast(TypeFunction)(cast(TypePointer)t1).next; 4846 p = "function pointer"; 4847 } 4848 else if (exp.e1.op == TOK.dotVariable && (cast(DotVarExp)exp.e1).var.isOverDeclaration()) 4849 { 4850 DotVarExp dve = cast(DotVarExp)exp.e1; 4851 exp.f = resolveFuncCall(exp.loc, sc, dve.var, tiargs, dve.e1.type, exp.arguments, FuncResolveFlag.overloadOnly); 4852 if (!exp.f) 4853 return setError(); 4854 if (exp.f.needThis()) 4855 { 4856 dve.var = exp.f; 4857 dve.type = exp.f.type; 4858 dve.hasOverloads = false; 4859 goto Lagain; 4860 } 4861 exp.e1 = new VarExp(dve.loc, exp.f, false); 4862 Expression e = new CommaExp(exp.loc, dve.e1, exp); 4863 result = e.expressionSemantic(sc); 4864 return; 4865 } 4866 else if (exp.e1.op == TOK.variable && (cast(VarExp)exp.e1).var.isOverDeclaration()) 4867 { 4868 s = (cast(VarExp)exp.e1).var; 4869 goto L2; 4870 } 4871 else if (exp.e1.op == TOK.template_) 4872 { 4873 s = (cast(TemplateExp)exp.e1).td; 4874 L2: 4875 exp.f = resolveFuncCall(exp.loc, sc, s, tiargs, null, exp.arguments, FuncResolveFlag.standard); 4876 if (!exp.f || exp.f.errors) 4877 return setError(); 4878 if (exp.f.needThis()) 4879 { 4880 if (hasThis(sc)) 4881 { 4882 // Supply an implicit 'this', as in 4883 // this.ident 4884 exp.e1 = new DotVarExp(exp.loc, (new ThisExp(exp.loc)).expressionSemantic(sc), exp.f, false); 4885 goto Lagain; 4886 } 4887 else if (isNeedThisScope(sc, exp.f)) 4888 { 4889 exp.error("need `this` for `%s` of type `%s`", exp.f.toChars(), exp.f.type.toChars()); 4890 return setError(); 4891 } 4892 } 4893 exp.e1 = new VarExp(exp.e1.loc, exp.f, false); 4894 goto Lagain; 4895 } 4896 else 4897 { 4898 exp.error("function expected before `()`, not `%s` of type `%s`", exp.e1.toChars(), exp.e1.type.toChars()); 4899 return setError(); 4900 } 4901 4902 const(char)* failMessage; 4903 Expression[] fargs = exp.arguments ? (*exp.arguments)[] : null; 4904 if (!tf.callMatch(null, fargs, 0, &failMessage, sc)) 4905 { 4906 OutBuffer buf; 4907 buf.writeByte('('); 4908 argExpTypesToCBuffer(&buf, exp.arguments); 4909 buf.writeByte(')'); 4910 if (tthis) 4911 tthis.modToBuffer(&buf); 4912 4913 //printf("tf = %s, args = %s\n", tf.deco, (*arguments)[0].type.deco); 4914 .error(exp.loc, "%s `%s%s` is not callable using argument types `%s`", 4915 p, exp.e1.toChars(), parametersTypeToChars(tf.parameterList), buf.peekChars()); 4916 if (failMessage) 4917 errorSupplemental(exp.loc, "%s", failMessage); 4918 return setError(); 4919 } 4920 // Purity and safety check should run after testing arguments matching 4921 if (exp.f) 4922 { 4923 exp.checkPurity(sc, exp.f); 4924 exp.checkSafety(sc, exp.f); 4925 exp.checkNogc(sc, exp.f); 4926 if (exp.f.checkNestedReference(sc, exp.loc)) 4927 return setError(); 4928 } 4929 else if (sc.func && sc.intypeof != 1 && !(sc.flags & (SCOPE.ctfe | SCOPE.debug_))) 4930 { 4931 bool err = false; 4932 if (!tf.purity && sc.func.setImpure()) 4933 { 4934 exp.error("`pure` %s `%s` cannot call impure %s `%s`", 4935 sc.func.kind(), sc.func.toPrettyChars(), p, exp.e1.toChars()); 4936 err = true; 4937 } 4938 if (!tf.isnogc && sc.func.setGC()) 4939 { 4940 exp.error("`@nogc` %s `%s` cannot call non-@nogc %s `%s`", 4941 sc.func.kind(), sc.func.toPrettyChars(), p, exp.e1.toChars()); 4942 err = true; 4943 } 4944 if (tf.trust <= TRUST.system && sc.func.setUnsafe()) 4945 { 4946 exp.error("`@safe` %s `%s` cannot call `@system` %s `%s`", 4947 sc.func.kind(), sc.func.toPrettyChars(), p, exp.e1.toChars()); 4948 err = true; 4949 } 4950 if (err) 4951 return setError(); 4952 } 4953 4954 if (t1.ty == Tpointer) 4955 { 4956 Expression e = new PtrExp(exp.loc, exp.e1); 4957 e.type = tf; 4958 exp.e1 = e; 4959 } 4960 t1 = tf; 4961 } 4962 else if (exp.e1.op == TOK.variable) 4963 { 4964 // Do overload resolution 4965 VarExp ve = cast(VarExp)exp.e1; 4966 4967 exp.f = ve.var.isFuncDeclaration(); 4968 assert(exp.f); 4969 tiargs = null; 4970 4971 if (exp.f.overnext) 4972 exp.f = resolveFuncCall(exp.loc, sc, exp.f, tiargs, null, exp.arguments, FuncResolveFlag.overloadOnly); 4973 else 4974 { 4975 exp.f = exp.f.toAliasFunc(); 4976 TypeFunction tf = cast(TypeFunction)exp.f.type; 4977 const(char)* failMessage; 4978 Expression[] fargs = exp.arguments ? (*exp.arguments)[] : null; 4979 if (!tf.callMatch(null, fargs, 0, &failMessage, sc)) 4980 { 4981 OutBuffer buf; 4982 buf.writeByte('('); 4983 argExpTypesToCBuffer(&buf, exp.arguments); 4984 buf.writeByte(')'); 4985 4986 //printf("tf = %s, args = %s\n", tf.deco, (*arguments)[0].type.deco); 4987 .error(exp.loc, "%s `%s%s` is not callable using argument types `%s`", 4988 exp.f.kind(), exp.f.toPrettyChars(), parametersTypeToChars(tf.parameterList), buf.peekChars()); 4989 if (failMessage) 4990 errorSupplemental(exp.loc, "%s", failMessage); 4991 exp.f = null; 4992 } 4993 } 4994 if (!exp.f || exp.f.errors) 4995 return setError(); 4996 4997 if (exp.f.needThis()) 4998 { 4999 // Change the ancestor lambdas to delegate before hasThis(sc) call. 5000 if (exp.f.checkNestedReference(sc, exp.loc)) 5001 return setError(); 5002 5003 if (hasThis(sc)) 5004 { 5005 // Supply an implicit 'this', as in 5006 // this.ident 5007 exp.e1 = new DotVarExp(exp.loc, (new ThisExp(exp.loc)).expressionSemantic(sc), ve.var); 5008 // Note: we cannot use f directly, because further overload resolution 5009 // through the supplied 'this' may cause different result. 5010 goto Lagain; 5011 } 5012 else if (isNeedThisScope(sc, exp.f)) 5013 { 5014 exp.error("need `this` for `%s` of type `%s`", exp.f.toChars(), exp.f.type.toChars()); 5015 return setError(); 5016 } 5017 } 5018 5019 checkFunctionAttributes(exp, sc, exp.f); 5020 checkAccess(exp.loc, sc, null, exp.f); 5021 if (exp.f.checkNestedReference(sc, exp.loc)) 5022 return setError(); 5023 5024 ethis = null; 5025 tthis = null; 5026 5027 if (ve.hasOverloads) 5028 { 5029 exp.e1 = new VarExp(ve.loc, exp.f, false); 5030 exp.e1.type = exp.f.type; 5031 } 5032 t1 = exp.f.type; 5033 } 5034 assert(t1.ty == Tfunction); 5035 5036 Expression argprefix; 5037 if (!exp.arguments) 5038 exp.arguments = new Expressions(); 5039 if (functionParameters(exp.loc, sc, cast(TypeFunction)t1, ethis, tthis, exp.arguments, exp.f, &exp.type, &argprefix)) 5040 return setError(); 5041 5042 if (!exp.type) 5043 { 5044 exp.e1 = e1org; // https://issues.dlang.org/show_bug.cgi?id=10922 5045 // avoid recursive expression printing 5046 exp.error("forward reference to inferred return type of function call `%s`", exp.toChars()); 5047 return setError(); 5048 } 5049 5050 if (exp.f && exp.f.tintro) 5051 { 5052 Type t = exp.type; 5053 int offset = 0; 5054 TypeFunction tf = cast(TypeFunction)exp.f.tintro; 5055 if (tf.next.isBaseOf(t, &offset) && offset) 5056 { 5057 exp.type = tf.next; 5058 result = Expression.combine(argprefix, exp.castTo(sc, t)); 5059 return; 5060 } 5061 } 5062 5063 // Handle the case of a direct lambda call 5064 if (exp.f && exp.f.isFuncLiteralDeclaration() && sc.func && !sc.intypeof) 5065 { 5066 exp.f.tookAddressOf = 0; 5067 } 5068 5069 result = Expression.combine(argprefix, exp); 5070 5071 if (isSuper) 5072 { 5073 auto ad = sc.func ? sc.func.isThis() : null; 5074 auto cd = ad ? ad.isClassDeclaration() : null; 5075 if (cd && cd.classKind == ClassKind.cpp && exp.f && !exp.f.fbody) 5076 { 5077 // if super is defined in C++, it sets the vtable pointer to the base class 5078 // so we have to restore it, but still return 'this' from super() call: 5079 // (auto __vptrTmp = this.__vptr, auto __superTmp = super()), (this.__vptr = __vptrTmp, __superTmp) 5080 Loc loc = exp.loc; 5081 5082 auto vptr = new DotIdExp(loc, new ThisExp(loc), Id.__vptr); 5083 auto vptrTmpDecl = copyToTemp(0, "__vptrTmp", vptr); 5084 auto declareVptrTmp = new DeclarationExp(loc, vptrTmpDecl); 5085 5086 auto superTmpDecl = copyToTemp(0, "__superTmp", result); 5087 auto declareSuperTmp = new DeclarationExp(loc, superTmpDecl); 5088 5089 auto declareTmps = new CommaExp(loc, declareVptrTmp, declareSuperTmp); 5090 5091 auto restoreVptr = new AssignExp(loc, vptr.syntaxCopy(), new VarExp(loc, vptrTmpDecl)); 5092 5093 Expression e = new CommaExp(loc, declareTmps, new CommaExp(loc, restoreVptr, new VarExp(loc, superTmpDecl))); 5094 result = e.expressionSemantic(sc); 5095 } 5096 } 5097 5098 // declare dual-context container 5099 if (exp.f && exp.f.isThis2 && !sc.intypeof && sc.func) 5100 { 5101 // check access to second `this` 5102 if (AggregateDeclaration ad2 = exp.f.isMember2()) 5103 { 5104 Expression te = new ThisExp(exp.loc).expressionSemantic(sc); 5105 if (te.op != TOK.error) 5106 te = getRightThis(exp.loc, sc, ad2, te, exp.f); 5107 if (te.op == TOK.error) 5108 { 5109 exp.error("need `this` of type `%s` to call function `%s`", ad2.toChars(), exp.f.toChars()); 5110 return setError(); 5111 } 5112 } 5113 VarDeclaration vthis2 = makeThis2Argument(exp.loc, sc, exp.f); exp.vthis2 = vthis2; 5114 Expression de = new DeclarationExp(exp.loc, vthis2); 5115 result = Expression.combine(de, result); 5116 result = result.expressionSemantic(sc); 5117 } 5118 } 5119 5120 override void visit(DeclarationExp e) 5121 { 5122 if (e.type) 5123 { 5124 result = e; 5125 return; 5126 } 5127 static if (LOGSEMANTIC) 5128 { 5129 printf("DeclarationExp::semantic() %s\n", e.toChars()); 5130 } 5131 5132 uint olderrors = global.errors; 5133 5134 /* This is here to support extern(linkage) declaration, 5135 * where the extern(linkage) winds up being an AttribDeclaration 5136 * wrapper. 5137 */ 5138 Dsymbol s = e.declaration; 5139 5140 while (1) 5141 { 5142 AttribDeclaration ad = s.isAttribDeclaration(); 5143 if (ad) 5144 { 5145 if (ad.decl && ad.decl.dim == 1) 5146 { 5147 s = (*ad.decl)[0]; 5148 continue; 5149 } 5150 } 5151 break; 5152 } 5153 5154 VarDeclaration v = s.isVarDeclaration(); 5155 if (v) 5156 { 5157 // Do semantic() on initializer first, so: 5158 // int a = a; 5159 // will be illegal. 5160 e.declaration.dsymbolSemantic(sc); 5161 s.parent = sc.parent; 5162 } 5163 5164 //printf("inserting '%s' %p into sc = %p\n", s.toChars(), s, sc); 5165 // Insert into both local scope and function scope. 5166 // Must be unique in both. 5167 if (s.ident) 5168 { 5169 if (!sc.insert(s)) 5170 { 5171 auto conflict = sc.search(Loc.initial, s.ident, null); 5172 e.error("declaration `%s` is already defined", s.toPrettyChars()); 5173 errorSupplemental(conflict.loc, "`%s` `%s` is defined here", 5174 conflict.kind(), conflict.toChars()); 5175 return setError(); 5176 } 5177 else if (sc.func) 5178 { 5179 // https://issues.dlang.org/show_bug.cgi?id=11720 5180 // include Dataseg variables 5181 if ((s.isFuncDeclaration() || 5182 s.isAggregateDeclaration() || 5183 s.isEnumDeclaration() || 5184 v && v.isDataseg()) && !sc.func.localsymtab.insert(s)) 5185 { 5186 // https://issues.dlang.org/show_bug.cgi?id=18266 5187 // set parent so that type semantic does not assert 5188 s.parent = sc.parent; 5189 Dsymbol originalSymbol = sc.func.localsymtab.lookup(s.ident); 5190 assert(originalSymbol); 5191 e.error("declaration `%s` is already defined in another scope in `%s` at line `%d`", s.toPrettyChars(), sc.func.toChars(), originalSymbol.loc.linnum); 5192 return setError(); 5193 } 5194 else 5195 { 5196 /* https://issues.dlang.org/show_bug.cgi?id=21272 5197 * If we are in a foreach body we need to extract the 5198 * function containing the foreach 5199 */ 5200 FuncDeclaration fes_enclosing_func; 5201 if (sc.func && sc.func.fes) 5202 fes_enclosing_func = sc.enclosing.enclosing.func; 5203 5204 // Disallow shadowing 5205 for (Scope* scx = sc.enclosing; scx && (scx.func == sc.func || (fes_enclosing_func && scx.func == fes_enclosing_func)); scx = scx.enclosing) 5206 { 5207 Dsymbol s2; 5208 if (scx.scopesym && scx.scopesym.symtab && (s2 = scx.scopesym.symtab.lookup(s.ident)) !is null && s != s2) 5209 { 5210 // allow STC.local symbols to be shadowed 5211 // TODO: not really an optimal design 5212 auto decl = s2.isDeclaration(); 5213 if (!decl || !(decl.storage_class & STC.local)) 5214 { 5215 if (sc.func.fes) 5216 { 5217 e.deprecation("%s `%s` is shadowing %s `%s`. Rename the `foreach` variable.", s.kind(), s.ident.toChars(), s2.kind(), s2.toPrettyChars()); 5218 } 5219 else 5220 { 5221 e.error("%s `%s` is shadowing %s `%s`", s.kind(), s.ident.toChars(), s2.kind(), s2.toPrettyChars()); 5222 return setError(); 5223 } 5224 } 5225 } 5226 } 5227 } 5228 } 5229 } 5230 if (!s.isVarDeclaration()) 5231 { 5232 Scope* sc2 = sc; 5233 if (sc2.stc & (STC.pure_ | STC.nothrow_ | STC.nogc)) 5234 sc2 = sc.push(); 5235 sc2.stc &= ~(STC.pure_ | STC.nothrow_ | STC.nogc); 5236 e.declaration.dsymbolSemantic(sc2); 5237 if (sc2 != sc) 5238 sc2.pop(); 5239 s.parent = sc.parent; 5240 } 5241 if (global.errors == olderrors) 5242 { 5243 e.declaration.semantic2(sc); 5244 if (global.errors == olderrors) 5245 { 5246 e.declaration.semantic3(sc); 5247 } 5248 } 5249 // todo: error in declaration should be propagated. 5250 5251 e.type = Type.tvoid; 5252 result = e; 5253 } 5254 5255 override void visit(TypeidExp exp) 5256 { 5257 static if (LOGSEMANTIC) 5258 { 5259 printf("TypeidExp::semantic() %s\n", exp.toChars()); 5260 } 5261 Type ta = isType(exp.obj); 5262 Expression ea = isExpression(exp.obj); 5263 Dsymbol sa = isDsymbol(exp.obj); 5264 //printf("ta %p ea %p sa %p\n", ta, ea, sa); 5265 5266 if (ta) 5267 { 5268 dmd.typesem.resolve(ta, exp.loc, sc, &ea, &ta, &sa, true); 5269 } 5270 5271 if (ea) 5272 { 5273 if (auto sym = getDsymbol(ea)) 5274 ea = symbolToExp(sym, exp.loc, sc, false); 5275 else 5276 ea = ea.expressionSemantic(sc); 5277 ea = resolveProperties(sc, ea); 5278 ta = ea.type; 5279 if (ea.op == TOK.type) 5280 ea = null; 5281 } 5282 5283 if (!ta) 5284 { 5285 //printf("ta %p ea %p sa %p\n", ta, ea, sa); 5286 exp.error("no type for `typeid(%s)`", ea ? ea.toChars() : (sa ? sa.toChars() : "")); 5287 return setError(); 5288 } 5289 5290 if (global.params.vcomplex) 5291 ta.checkComplexTransition(exp.loc, sc); 5292 5293 Expression e; 5294 auto tb = ta.toBasetype(); 5295 if (ea && tb.ty == Tclass) 5296 { 5297 if (tb.toDsymbol(sc).isClassDeclaration().classKind == ClassKind.cpp) 5298 { 5299 error(exp.loc, "Runtime type information is not supported for `extern(C++)` classes"); 5300 e = ErrorExp.get(); 5301 } 5302 else if (!Type.typeinfoclass) 5303 { 5304 error(exp.loc, "`object.TypeInfo_Class` could not be found, but is implicitly used"); 5305 e = ErrorExp.get(); 5306 } 5307 else 5308 { 5309 /* Get the dynamic type, which is .classinfo 5310 */ 5311 ea = ea.expressionSemantic(sc); 5312 e = new TypeidExp(ea.loc, ea); 5313 e.type = Type.typeinfoclass.type; 5314 } 5315 } 5316 else if (ta.ty == Terror) 5317 { 5318 e = ErrorExp.get(); 5319 } 5320 else 5321 { 5322 // Handle this in the glue layer 5323 e = new TypeidExp(exp.loc, ta); 5324 e.type = getTypeInfoType(exp.loc, ta, sc); 5325 5326 semanticTypeInfo(sc, ta); 5327 5328 if (ea) 5329 { 5330 e = new CommaExp(exp.loc, ea, e); // execute ea 5331 e = e.expressionSemantic(sc); 5332 } 5333 } 5334 result = e; 5335 } 5336 5337 override void visit(TraitsExp e) 5338 { 5339 result = semanticTraits(e, sc); 5340 } 5341 5342 override void visit(HaltExp e) 5343 { 5344 static if (LOGSEMANTIC) 5345 { 5346 printf("HaltExp::semantic()\n"); 5347 } 5348 e.type = Type.tvoid; 5349 result = e; 5350 } 5351 5352 override void visit(IsExp e) 5353 { 5354 /* is(targ id tok tspec) 5355 * is(targ id : tok2) 5356 * is(targ id == tok2) 5357 */ 5358 Type tded = null; 5359 5360 void yes() 5361 { 5362 //printf("yes\n"); 5363 if (!e.id) 5364 { 5365 result = IntegerExp.createBool(true); 5366 return; 5367 } 5368 5369 Dsymbol s; 5370 Tuple tup = isTuple(tded); 5371 if (tup) 5372 s = new TupleDeclaration(e.loc, e.id, &tup.objects); 5373 else 5374 s = new AliasDeclaration(e.loc, e.id, tded); 5375 s.dsymbolSemantic(sc); 5376 5377 /* The reason for the !tup is unclear. It fails Phobos unittests if it is not there. 5378 * More investigation is needed. 5379 */ 5380 if (!tup && !sc.insert(s)) 5381 { 5382 auto conflict = sc.search(Loc.initial, s.ident, null); 5383 e.error("declaration `%s` is already defined", s.toPrettyChars()); 5384 errorSupplemental(conflict.loc, "`%s` `%s` is defined here", 5385 conflict.kind(), conflict.toChars()); 5386 } 5387 5388 unSpeculative(sc, s); 5389 5390 result = IntegerExp.createBool(true); 5391 } 5392 void no() 5393 { 5394 result = IntegerExp.createBool(false); 5395 //printf("no\n"); 5396 } 5397 5398 static if (LOGSEMANTIC) 5399 { 5400 printf("IsExp::semantic(%s)\n", e.toChars()); 5401 } 5402 if (e.id && !(sc.flags & SCOPE.condition)) 5403 { 5404 e.error("can only declare type aliases within `static if` conditionals or `static assert`s"); 5405 return setError(); 5406 } 5407 5408 if (e.tok2 == TOK.package_ || e.tok2 == TOK.module_) // These is() expressions are special because they can work on modules, not just types. 5409 { 5410 const oldErrors = global.startGagging(); 5411 Dsymbol sym = e.targ.toDsymbol(sc); 5412 global.endGagging(oldErrors); 5413 5414 if (sym is null) 5415 return no(); 5416 Package p = resolveIsPackage(sym); 5417 if (p is null) 5418 return no(); 5419 if (e.tok2 == TOK.package_ && p.isModule()) // Note that isModule() will return null for package modules because they're not actually instances of Module. 5420 return no(); 5421 else if(e.tok2 == TOK.module_ && !(p.isModule() || p.isPackageMod())) 5422 return no(); 5423 tded = e.targ; 5424 return yes(); 5425 } 5426 5427 { 5428 Scope* sc2 = sc.copy(); // keep sc.flags 5429 sc2.tinst = null; 5430 sc2.minst = null; 5431 sc2.flags |= SCOPE.fullinst; 5432 Type t = e.targ.trySemantic(e.loc, sc2); 5433 sc2.pop(); 5434 if (!t) // errors, so condition is false 5435 return no(); 5436 e.targ = t; 5437 } 5438 5439 if (e.tok2 != TOK.reserved) 5440 { 5441 switch (e.tok2) 5442 { 5443 case TOK.struct_: 5444 if (e.targ.ty != Tstruct) 5445 return no(); 5446 if ((cast(TypeStruct)e.targ).sym.isUnionDeclaration()) 5447 return no(); 5448 tded = e.targ; 5449 break; 5450 5451 case TOK.union_: 5452 if (e.targ.ty != Tstruct) 5453 return no(); 5454 if (!(cast(TypeStruct)e.targ).sym.isUnionDeclaration()) 5455 return no(); 5456 tded = e.targ; 5457 break; 5458 5459 case TOK.class_: 5460 if (e.targ.ty != Tclass) 5461 return no(); 5462 if ((cast(TypeClass)e.targ).sym.isInterfaceDeclaration()) 5463 return no(); 5464 tded = e.targ; 5465 break; 5466 5467 case TOK.interface_: 5468 if (e.targ.ty != Tclass) 5469 return no(); 5470 if (!(cast(TypeClass)e.targ).sym.isInterfaceDeclaration()) 5471 return no(); 5472 tded = e.targ; 5473 break; 5474 5475 case TOK.const_: 5476 if (!e.targ.isConst()) 5477 return no(); 5478 tded = e.targ; 5479 break; 5480 5481 case TOK.immutable_: 5482 if (!e.targ.isImmutable()) 5483 return no(); 5484 tded = e.targ; 5485 break; 5486 5487 case TOK.shared_: 5488 if (!e.targ.isShared()) 5489 return no(); 5490 tded = e.targ; 5491 break; 5492 5493 case TOK.inout_: 5494 if (!e.targ.isWild()) 5495 return no(); 5496 tded = e.targ; 5497 break; 5498 5499 case TOK.super_: 5500 // If class or interface, get the base class and interfaces 5501 if (e.targ.ty != Tclass) 5502 return no(); 5503 else 5504 { 5505 ClassDeclaration cd = (cast(TypeClass)e.targ).sym; 5506 auto args = new Parameters(); 5507 args.reserve(cd.baseclasses.dim); 5508 if (cd.semanticRun < PASS.semanticdone) 5509 cd.dsymbolSemantic(null); 5510 for (size_t i = 0; i < cd.baseclasses.dim; i++) 5511 { 5512 BaseClass* b = (*cd.baseclasses)[i]; 5513 args.push(new Parameter(STC.in_, b.type, null, null, null)); 5514 } 5515 tded = new TypeTuple(args); 5516 } 5517 break; 5518 5519 case TOK.enum_: 5520 if (e.targ.ty != Tenum) 5521 return no(); 5522 if (e.id) 5523 tded = (cast(TypeEnum)e.targ).sym.getMemtype(e.loc); 5524 else 5525 tded = e.targ; 5526 5527 if (tded.ty == Terror) 5528 return setError(); 5529 break; 5530 5531 case TOK.delegate_: 5532 if (e.targ.ty != Tdelegate) 5533 return no(); 5534 tded = (cast(TypeDelegate)e.targ).next; // the underlying function type 5535 break; 5536 5537 case TOK.function_: 5538 case TOK.parameters: 5539 { 5540 if (e.targ.ty != Tfunction) 5541 return no(); 5542 tded = e.targ; 5543 5544 /* Generate tuple from function parameter types. 5545 */ 5546 assert(tded.ty == Tfunction); 5547 auto tdedf = tded.isTypeFunction(); 5548 auto args = new Parameters(); 5549 foreach (i, arg; tdedf.parameterList) 5550 { 5551 assert(arg && arg.type); 5552 /* If one of the default arguments was an error, 5553 don't return an invalid tuple 5554 */ 5555 if (e.tok2 == TOK.parameters && arg.defaultArg && arg.defaultArg.op == TOK.error) 5556 return setError(); 5557 args.push(new Parameter(arg.storageClass, arg.type, (e.tok2 == TOK.parameters) ? arg.ident : null, (e.tok2 == TOK.parameters) ? arg.defaultArg : null, arg.userAttribDecl)); 5558 } 5559 tded = new TypeTuple(args); 5560 break; 5561 } 5562 case TOK.return_: 5563 /* Get the 'return type' for the function, 5564 * delegate, or pointer to function. 5565 */ 5566 if (e.targ.ty == Tfunction) 5567 tded = (cast(TypeFunction)e.targ).next; 5568 else if (e.targ.ty == Tdelegate) 5569 { 5570 tded = (cast(TypeDelegate)e.targ).next; 5571 tded = (cast(TypeFunction)tded).next; 5572 } 5573 else if (e.targ.ty == Tpointer && (cast(TypePointer)e.targ).next.ty == Tfunction) 5574 { 5575 tded = (cast(TypePointer)e.targ).next; 5576 tded = (cast(TypeFunction)tded).next; 5577 } 5578 else 5579 return no(); 5580 break; 5581 5582 case TOK.argumentTypes: 5583 /* Generate a type tuple of the equivalent types used to determine if a 5584 * function argument of this type can be passed in registers. 5585 * The results of this are highly platform dependent, and intended 5586 * primarly for use in implementing va_arg(). 5587 */ 5588 tded = target.toArgTypes(e.targ); 5589 if (!tded) 5590 return no(); 5591 // not valid for a parameter 5592 break; 5593 5594 case TOK.vector: 5595 if (e.targ.ty != Tvector) 5596 return no(); 5597 tded = (cast(TypeVector)e.targ).basetype; 5598 break; 5599 5600 default: 5601 assert(0); 5602 } 5603 5604 // https://issues.dlang.org/show_bug.cgi?id=18753 5605 if (tded) 5606 return yes(); 5607 return no(); 5608 } 5609 else if (e.tspec && !e.id && !(e.parameters && e.parameters.dim)) 5610 { 5611 /* Evaluate to true if targ matches tspec 5612 * is(targ == tspec) 5613 * is(targ : tspec) 5614 */ 5615 e.tspec = e.tspec.typeSemantic(e.loc, sc); 5616 //printf("targ = %s, %s\n", e.targ.toChars(), e.targ.deco); 5617 //printf("tspec = %s, %s\n", e.tspec.toChars(), e.tspec.deco); 5618 5619 if (e.tok == TOK.colon) 5620 { 5621 // current scope is itself deprecated, or deprecations are not errors 5622 const bool deprecationAllowed = sc.isDeprecated 5623 || global.params.useDeprecated != DiagnosticReporting.error; 5624 const bool preventAliasThis = e.targ.hasDeprecatedAliasThis && !deprecationAllowed; 5625 5626 if (preventAliasThis && e.targ.ty == Tstruct) 5627 { 5628 if ((cast(TypeStruct) e.targ).implicitConvToWithoutAliasThis(e.tspec)) 5629 return yes(); 5630 else 5631 return no(); 5632 } 5633 else if (preventAliasThis && e.targ.ty == Tclass) 5634 { 5635 if ((cast(TypeClass) e.targ).implicitConvToWithoutAliasThis(e.tspec)) 5636 return yes(); 5637 else 5638 return no(); 5639 } 5640 else if (e.targ.implicitConvTo(e.tspec)) 5641 return yes(); 5642 else 5643 return no(); 5644 } 5645 else /* == */ 5646 { 5647 if (e.targ.equals(e.tspec)) 5648 return yes(); 5649 else 5650 return no(); 5651 } 5652 } 5653 else if (e.tspec) 5654 { 5655 /* Evaluate to true if targ matches tspec. 5656 * If true, declare id as an alias for the specialized type. 5657 * is(targ == tspec, tpl) 5658 * is(targ : tspec, tpl) 5659 * is(targ id == tspec) 5660 * is(targ id : tspec) 5661 * is(targ id == tspec, tpl) 5662 * is(targ id : tspec, tpl) 5663 */ 5664 Identifier tid = e.id ? e.id : Identifier.generateId("__isexp_id"); 5665 e.parameters.insert(0, new TemplateTypeParameter(e.loc, tid, null, null)); 5666 5667 Objects dedtypes = Objects(e.parameters.dim); 5668 dedtypes.zero(); 5669 5670 MATCH m = deduceType(e.targ, sc, e.tspec, e.parameters, &dedtypes, null, 0, e.tok == TOK.equal); 5671 //printf("targ: %s\n", targ.toChars()); 5672 //printf("tspec: %s\n", tspec.toChars()); 5673 if (m <= MATCH.nomatch || (m != MATCH.exact && e.tok == TOK.equal)) 5674 { 5675 return no(); 5676 } 5677 else 5678 { 5679 tded = cast(Type)dedtypes[0]; 5680 if (!tded) 5681 tded = e.targ; 5682 Objects tiargs = Objects(1); 5683 tiargs[0] = e.targ; 5684 5685 /* Declare trailing parameters 5686 */ 5687 for (size_t i = 1; i < e.parameters.dim; i++) 5688 { 5689 TemplateParameter tp = (*e.parameters)[i]; 5690 Declaration s = null; 5691 5692 m = tp.matchArg(e.loc, sc, &tiargs, i, e.parameters, &dedtypes, &s); 5693 if (m <= MATCH.nomatch) 5694 return no(); 5695 s.dsymbolSemantic(sc); 5696 if (!sc.insert(s)) 5697 { 5698 auto conflict = sc.search(Loc.initial, s.ident, null); 5699 e.error("declaration `%s` is already defined", s.toPrettyChars()); 5700 errorSupplemental(conflict.loc, "`%s` `%s` is defined here", 5701 conflict.kind(), conflict.toChars()); 5702 } 5703 5704 unSpeculative(sc, s); 5705 } 5706 return yes(); 5707 } 5708 } 5709 else if (e.id) 5710 { 5711 /* Declare id as an alias for type targ. Evaluate to true 5712 * is(targ id) 5713 */ 5714 tded = e.targ; 5715 } 5716 return yes(); 5717 } 5718 5719 override void visit(BinAssignExp exp) 5720 { 5721 if (exp.type) 5722 { 5723 result = exp; 5724 return; 5725 } 5726 5727 Expression e = exp.op_overload(sc); 5728 if (e) 5729 { 5730 result = e; 5731 return; 5732 } 5733 5734 if (checkIfIsStructLiteralDotExpr(exp.e1)) 5735 return setError(); 5736 if (exp.e1.op == TOK.arrayLength) 5737 { 5738 // arr.length op= e2; 5739 e = rewriteOpAssign(exp); 5740 e = e.expressionSemantic(sc); 5741 result = e; 5742 return; 5743 } 5744 if (exp.e1.op == TOK.slice || exp.e1.type.ty == Tarray || exp.e1.type.ty == Tsarray) 5745 { 5746 if (checkNonAssignmentArrayOp(exp.e1)) 5747 return setError(); 5748 5749 if (exp.e1.op == TOK.slice) 5750 (cast(SliceExp)exp.e1).arrayop = true; 5751 5752 // T[] op= ... 5753 if (exp.e2.implicitConvTo(exp.e1.type.nextOf())) 5754 { 5755 // T[] op= T 5756 exp.e2 = exp.e2.castTo(sc, exp.e1.type.nextOf()); 5757 } 5758 else if (Expression ex = typeCombine(exp, sc)) 5759 { 5760 result = ex; 5761 return; 5762 } 5763 exp.type = exp.e1.type; 5764 result = arrayOp(exp, sc); 5765 return; 5766 } 5767 5768 exp.e1 = exp.e1.expressionSemantic(sc); 5769 exp.e1 = exp.e1.optimize(WANTvalue); 5770 exp.e1 = exp.e1.modifiableLvalue(sc, exp.e1); 5771 exp.type = exp.e1.type; 5772 5773 if (auto ad = isAggregate(exp.e1.type)) 5774 { 5775 if (const s = search_function(ad, Id.opOpAssign)) 5776 { 5777 error(exp.loc, "none of the `opOpAssign` overloads of `%s` are callable for `%s` of type `%s`", ad.toChars(), exp.e1.toChars(), exp.e1.type.toChars()); 5778 return setError(); 5779 } 5780 } 5781 if (exp.e1.checkScalar() || 5782 exp.e1.checkReadModifyWrite(exp.op, exp.e2) || 5783 exp.e1.checkSharedAccess(sc)) 5784 return setError(); 5785 5786 int arith = (exp.op == TOK.addAssign || exp.op == TOK.minAssign || exp.op == TOK.mulAssign || exp.op == TOK.divAssign || exp.op == TOK.modAssign || exp.op == TOK.powAssign); 5787 int bitwise = (exp.op == TOK.andAssign || exp.op == TOK.orAssign || exp.op == TOK.xorAssign); 5788 int shift = (exp.op == TOK.leftShiftAssign || exp.op == TOK.rightShiftAssign || exp.op == TOK.unsignedRightShiftAssign); 5789 5790 if (bitwise && exp.type.toBasetype().ty == Tbool) 5791 exp.e2 = exp.e2.implicitCastTo(sc, exp.type); 5792 else if (exp.checkNoBool()) 5793 return setError(); 5794 5795 if ((exp.op == TOK.addAssign || exp.op == TOK.minAssign) && exp.e1.type.toBasetype().ty == Tpointer && exp.e2.type.toBasetype().isintegral()) 5796 { 5797 result = scaleFactor(exp, sc); 5798 return; 5799 } 5800 5801 if (Expression ex = typeCombine(exp, sc)) 5802 { 5803 result = ex; 5804 return; 5805 } 5806 5807 if (arith && (exp.checkArithmeticBin() || exp.checkSharedAccessBin(sc))) 5808 return setError(); 5809 if ((bitwise || shift) && (exp.checkIntegralBin() || exp.checkSharedAccessBin(sc))) 5810 return setError(); 5811 5812 if (shift) 5813 { 5814 if (exp.e2.type.toBasetype().ty != Tvector) 5815 exp.e2 = exp.e2.castTo(sc, Type.tshiftcnt); 5816 } 5817 5818 if (!target.isVectorOpSupported(exp.type.toBasetype(), exp.op, exp.e2.type.toBasetype())) 5819 { 5820 result = exp.incompatibleTypes(); 5821 return; 5822 } 5823 5824 if (exp.e1.op == TOK.error || exp.e2.op == TOK.error) 5825 return setError(); 5826 5827 e = exp.checkOpAssignTypes(sc); 5828 if (e.op == TOK.error) 5829 { 5830 result = e; 5831 return; 5832 } 5833 5834 assert(e.op == TOK.assign || e == exp); 5835 result = (cast(BinExp)e).reorderSettingAAElem(sc); 5836 } 5837 5838 private Expression compileIt(CompileExp exp) 5839 { 5840 OutBuffer buf; 5841 if (expressionsToString(buf, sc, exp.exps)) 5842 return null; 5843 5844 uint errors = global.errors; 5845 const len = buf.length; 5846 const str = buf.extractChars()[0 .. len]; 5847 scope p = new Parser!ASTCodegen(exp.loc, sc._module, str, false); 5848 p.nextToken(); 5849 //printf("p.loc.linnum = %d\n", p.loc.linnum); 5850 5851 Expression e = p.parseExpression(); 5852 p.reportDiagnostics(); 5853 if (global.errors != errors) 5854 return null; 5855 5856 if (p.token.value != TOK.endOfFile) 5857 { 5858 exp.error("incomplete mixin expression `%s`", str.ptr); 5859 return null; 5860 } 5861 return e; 5862 } 5863 5864 override void visit(CompileExp exp) 5865 { 5866 /* https://dlang.org/spec/expression.html#mixin_expressions 5867 */ 5868 5869 static if (LOGSEMANTIC) 5870 { 5871 printf("CompileExp::semantic('%s')\n", exp.toChars()); 5872 } 5873 5874 auto e = compileIt(exp); 5875 if (!e) 5876 return setError(); 5877 result = e.expressionSemantic(sc); 5878 } 5879 5880 override void visit(ImportExp e) 5881 { 5882 static if (LOGSEMANTIC) 5883 { 5884 printf("ImportExp::semantic('%s')\n", e.toChars()); 5885 } 5886 5887 auto se = semanticString(sc, e.e1, "file name argument"); 5888 if (!se) 5889 return setError(); 5890 se = se.toUTF8(sc); 5891 5892 auto namez = se.toStringz().ptr; 5893 if (!global.filePath) 5894 { 5895 e.error("need `-J` switch to import text file `%s`", namez); 5896 return setError(); 5897 } 5898 5899 /* Be wary of CWE-22: Improper Limitation of a Pathname to a Restricted Directory 5900 * ('Path Traversal') attacks. 5901 * http://cwe.mitre.org/data/definitions/22.html 5902 */ 5903 5904 auto name = FileName.safeSearchPath(global.filePath, namez); 5905 if (!name) 5906 { 5907 e.error("file `%s` cannot be found or not in a path specified with `-J`", se.toChars()); 5908 e.errorSupplemental("Path(s) searched (as provided by `-J`):"); 5909 foreach (idx, path; *global.filePath) 5910 { 5911 const attr = FileName.exists(path); 5912 const(char)* err = attr == 2 ? "" : 5913 (attr == 1 ? " (not a directory)" : " (path not found)"); 5914 e.errorSupplemental("[%zu]: `%s`%s", idx, path, err); 5915 } 5916 return setError(); 5917 } 5918 5919 sc._module.contentImportedFiles.push(name); 5920 if (global.params.verbose) 5921 { 5922 const slice = se.peekString(); 5923 message("file %.*s\t(%s)", cast(int)slice.length, slice.ptr, name); 5924 } 5925 if (global.params.moduleDeps !is null) 5926 { 5927 OutBuffer* ob = global.params.moduleDeps; 5928 Module imod = sc.instantiatingModule(); 5929 5930 if (!global.params.moduleDepsFile) 5931 ob.writestring("depsFile "); 5932 ob.writestring(imod.toPrettyChars()); 5933 ob.writestring(" ("); 5934 escapePath(ob, imod.srcfile.toChars()); 5935 ob.writestring(") : "); 5936 if (global.params.moduleDepsFile) 5937 ob.writestring("string : "); 5938 ob.write(se.peekString()); 5939 ob.writestring(" ("); 5940 escapePath(ob, name); 5941 ob.writestring(")"); 5942 ob.writenl(); 5943 } 5944 5945 { 5946 auto readResult = File.read(name); 5947 if (!readResult.success) 5948 { 5949 e.error("cannot read file `%s`", name); 5950 return setError(); 5951 } 5952 else 5953 { 5954 // take ownership of buffer (probably leaking) 5955 auto data = readResult.extractSlice(); 5956 se = new StringExp(e.loc, data); 5957 } 5958 } 5959 result = se.expressionSemantic(sc); 5960 } 5961 5962 override void visit(AssertExp exp) 5963 { 5964 // https://dlang.org/spec/expression.html#assert_expressions 5965 static if (LOGSEMANTIC) 5966 { 5967 printf("AssertExp::semantic('%s')\n", exp.toChars()); 5968 } 5969 5970 const generateMsg = !exp.msg && global.params.checkAction == CHECKACTION.context; 5971 Expression temporariesPrefix; 5972 5973 if (generateMsg) 5974 // no message - use assert expression as msg 5975 { 5976 if (!verifyHookExist(exp.loc, *sc, Id._d_assert_fail, "generating assert messages")) 5977 return setError(); 5978 5979 /* 5980 { 5981 auto a = e1, b = e2; 5982 assert(a == b, _d_assert_fail!"=="(a, b)); 5983 }() 5984 */ 5985 5986 /* 5987 Stores the result of an operand expression into a temporary 5988 if necessary, e.g. if it is an impure fuction call containing side 5989 effects as in https://issues.dlang.org/show_bug.cgi?id=20114 5990 5991 Params: 5992 op = an expression which may require a temporary (added to 5993 `temporariesPrefix`: `auto tmp = op`) and will be replaced 5994 by `tmp` if necessary 5995 5996 Returns: (possibly replaced) `op` 5997 */ 5998 Expression maybePromoteToTmp(ref Expression op) 5999 { 6000 // https://issues.dlang.org/show_bug.cgi?id=20989 6001 // Flag that _d_assert_fail will never dereference `array.ptr` to avoid safety 6002 // errors for `assert(!array.ptr)` => `_d_assert_fail!"!"(array.ptr)` 6003 { 6004 auto die = op.isDotIdExp(); 6005 if (die && die.ident == Id.ptr) 6006 die.noderef = true; 6007 } 6008 6009 op = op.expressionSemantic(sc); 6010 op = resolveProperties(sc, op); 6011 if (op.hasSideEffect) 6012 { 6013 const stc = op.isLvalue() ? STC.ref_ : 0; 6014 auto tmp = copyToTemp(stc, "__assertOp", op); 6015 tmp.dsymbolSemantic(sc); 6016 6017 auto decl = new DeclarationExp(op.loc, tmp); 6018 temporariesPrefix = Expression.combine(temporariesPrefix, decl); 6019 6020 op = new VarExp(op.loc, tmp); 6021 op = op.expressionSemantic(sc); 6022 } 6023 return op; 6024 } 6025 6026 // if the assert condition is a mixin expression, try to compile it 6027 if (auto ce = exp.e1.isCompileExp()) 6028 { 6029 if (auto e1 = compileIt(ce)) 6030 exp.e1 = e1; 6031 } 6032 6033 Expressions* es; 6034 Objects* tiargs; 6035 Loc loc = exp.e1.loc; 6036 6037 const tok = exp.e1.op; 6038 bool isEqualsCallExpression; 6039 if (tok == TOK.call) 6040 { 6041 const callExp = cast(CallExp) exp.e1; 6042 6043 // https://issues.dlang.org/show_bug.cgi?id=20331 6044 // callExp.f may be null if the assert contains a call to 6045 // a function pointer or literal 6046 if (const callExpFunc = callExp.f) 6047 { 6048 const callExpIdent = callExpFunc.ident; 6049 isEqualsCallExpression = callExpIdent == Id.__equals || 6050 callExpIdent == Id.eq; 6051 } 6052 } 6053 if (tok == TOK.equal || tok == TOK.notEqual || 6054 tok == TOK.lessThan || tok == TOK.greaterThan || 6055 tok == TOK.lessOrEqual || tok == TOK.greaterOrEqual || 6056 tok == TOK.identity || tok == TOK.notIdentity || 6057 tok == TOK.in_ || 6058 isEqualsCallExpression) 6059 { 6060 es = new Expressions(2); 6061 tiargs = new Objects(3); 6062 6063 if (isEqualsCallExpression) 6064 { 6065 auto callExp = cast(CallExp) exp.e1; 6066 auto args = callExp.arguments; 6067 6068 // structs with opEquals get rewritten to a DotVarExp: 6069 // a.opEquals(b) 6070 // https://issues.dlang.org/show_bug.cgi?id=20100 6071 if (args.length == 1) 6072 { 6073 auto dv = callExp.e1.isDotVarExp(); 6074 assert(dv); 6075 6076 // runtime args 6077 (*es)[0] = maybePromoteToTmp(dv.e1); 6078 (*es)[1] = maybePromoteToTmp((*args)[0]); 6079 } 6080 else 6081 { 6082 // runtime args 6083 (*es)[0] = maybePromoteToTmp((*args)[0]); 6084 (*es)[1] = maybePromoteToTmp((*args)[1]); 6085 } 6086 } 6087 else 6088 { 6089 auto binExp = cast(EqualExp) exp.e1; 6090 6091 // runtime args 6092 (*es)[0] = maybePromoteToTmp(binExp.e1); 6093 (*es)[1] = maybePromoteToTmp(binExp.e2); 6094 } 6095 6096 // template args 6097 Expression comp = new StringExp(loc, isEqualsCallExpression ? "==" : Token.toString(exp.e1.op)); 6098 comp = comp.expressionSemantic(sc); 6099 (*tiargs)[0] = comp; 6100 (*tiargs)[1] = (*es)[0].type; 6101 (*tiargs)[2] = (*es)[1].type; 6102 } 6103 6104 // Format exp.e1 before any additional boolean conversion 6105 // Ignore &&/|| because "assert(...) failed" is more informative than "false != true" 6106 else if (tok != TOK.andAnd && tok != TOK.orOr) 6107 { 6108 es = new Expressions(1); 6109 tiargs = new Objects(2); 6110 6111 if (auto ne = exp.e1.isNotExp()) 6112 { 6113 // Fetch the (potential non-bool) expression and fold 6114 // (n) negations into (n % 2) negations, e.g. !!a => a 6115 for (bool neg = true; ; neg = !neg) 6116 { 6117 if (auto ne2 = ne.e1.isNotExp()) 6118 ne = ne2; 6119 else 6120 { 6121 (*es)[0] = maybePromoteToTmp(ne.e1); 6122 (*tiargs)[0] = new StringExp(loc, neg ? "!" : ""); 6123 break; 6124 } 6125 } 6126 } 6127 else 6128 { // Simply format exp.e1 6129 (*es)[0] = maybePromoteToTmp(exp.e1); 6130 // No special treatment for other operators to avoid redundant template instantions 6131 (*tiargs)[0] = new StringExp(loc, ""); 6132 } 6133 6134 (*tiargs)[1] = (*es)[0].type; 6135 6136 // Passing __ctfe to auto ref infers ref and aborts compilation: 6137 // "cannot modify compiler-generated variable __ctfe" 6138 auto ve = (*es)[0].isVarExp(); 6139 if (ve && ve.var.ident == Id.ctfe) 6140 { 6141 exp.msg = new StringExp(loc, "assert(__ctfe) failed!"); 6142 goto LSkip; 6143 } 6144 } 6145 else 6146 { 6147 OutBuffer buf; 6148 buf.printf("%s failed", exp.toChars()); 6149 exp.msg = new StringExp(Loc.initial, buf.extractSlice()); 6150 goto LSkip; 6151 } 6152 6153 Expression __assertFail = new IdentifierExp(exp.loc, Id.empty); 6154 auto assertFail = new DotIdExp(loc, __assertFail, Id.object); 6155 6156 auto dt = new DotTemplateInstanceExp(loc, assertFail, Id._d_assert_fail, tiargs); 6157 auto ec = CallExp.create(Loc.initial, dt, es); 6158 exp.msg = ec; 6159 } 6160 6161 LSkip: 6162 if (Expression ex = unaSemantic(exp, sc)) 6163 { 6164 result = ex; 6165 return; 6166 } 6167 6168 exp.e1 = resolveProperties(sc, exp.e1); 6169 // BUG: see if we can do compile time elimination of the Assert 6170 exp.e1 = exp.e1.optimize(WANTvalue); 6171 exp.e1 = exp.e1.toBoolean(sc); 6172 6173 if (exp.msg) 6174 { 6175 exp.msg = expressionSemantic(exp.msg, sc); 6176 exp.msg = resolveProperties(sc, exp.msg); 6177 exp.msg = exp.msg.implicitCastTo(sc, Type.tchar.constOf().arrayOf()); 6178 exp.msg = exp.msg.optimize(WANTvalue); 6179 checkParamArgumentEscape(sc, null, null, exp.msg, true, false); 6180 } 6181 6182 if (exp.e1.op == TOK.error) 6183 { 6184 result = exp.e1; 6185 return; 6186 } 6187 if (exp.msg && exp.msg.op == TOK.error) 6188 { 6189 result = exp.msg; 6190 return; 6191 } 6192 6193 auto f1 = checkNonAssignmentArrayOp(exp.e1); 6194 auto f2 = exp.msg && checkNonAssignmentArrayOp(exp.msg); 6195 if (f1 || f2) 6196 return setError(); 6197 6198 if (exp.e1.isBool(false)) 6199 { 6200 /* This is an `assert(0)` which means halt program execution 6201 */ 6202 FuncDeclaration fd = sc.parent.isFuncDeclaration(); 6203 if (fd) 6204 fd.hasReturnExp |= 4; 6205 sc.ctorflow.orCSX(CSX.halt); 6206 6207 if (global.params.useAssert == CHECKENABLE.off) 6208 { 6209 Expression e = new HaltExp(exp.loc); 6210 e = e.expressionSemantic(sc); 6211 result = e; 6212 return; 6213 } 6214 } 6215 6216 exp.type = Type.tvoid; 6217 6218 result = !temporariesPrefix 6219 ? exp 6220 : Expression.combine(temporariesPrefix, exp).expressionSemantic(sc); 6221 } 6222 6223 override void visit(DotIdExp exp) 6224 { 6225 static if (LOGSEMANTIC) 6226 { 6227 printf("DotIdExp::semantic(this = %p, '%s')\n", exp, exp.toChars()); 6228 //printf("e1.op = %d, '%s'\n", e1.op, Token::toChars(e1.op)); 6229 } 6230 Expression e = exp.semanticY(sc, 1); 6231 if (e && isDotOpDispatch(e)) 6232 { 6233 uint errors = global.startGagging(); 6234 e = resolvePropertiesX(sc, e); 6235 if (global.endGagging(errors)) 6236 e = null; /* fall down to UFCS */ 6237 else 6238 { 6239 result = e; 6240 return; 6241 } 6242 } 6243 if (!e) // if failed to find the property 6244 { 6245 /* If ident is not a valid property, rewrite: 6246 * e1.ident 6247 * as: 6248 * .ident(e1) 6249 */ 6250 e = resolveUFCSProperties(sc, exp); 6251 } 6252 result = e; 6253 } 6254 6255 override void visit(DotTemplateExp e) 6256 { 6257 if (Expression ex = unaSemantic(e, sc)) 6258 { 6259 result = ex; 6260 return; 6261 } 6262 result = e; 6263 } 6264 6265 override void visit(DotVarExp exp) 6266 { 6267 static if (LOGSEMANTIC) 6268 { 6269 printf("DotVarExp::semantic('%s')\n", exp.toChars()); 6270 } 6271 if (exp.type) 6272 { 6273 result = exp; 6274 return; 6275 } 6276 6277 exp.var = exp.var.toAlias().isDeclaration(); 6278 6279 exp.e1 = exp.e1.expressionSemantic(sc); 6280 6281 if (auto tup = exp.var.isTupleDeclaration()) 6282 { 6283 /* Replace: 6284 * e1.tuple(a, b, c) 6285 * with: 6286 * tuple(e1.a, e1.b, e1.c) 6287 */ 6288 Expression e0; 6289 Expression ev = sc.func ? extractSideEffect(sc, "__tup", e0, exp.e1) : exp.e1; 6290 6291 auto exps = new Expressions(); 6292 exps.reserve(tup.objects.dim); 6293 for (size_t i = 0; i < tup.objects.dim; i++) 6294 { 6295 RootObject o = (*tup.objects)[i]; 6296 Expression e; 6297 Declaration var; 6298 if (o.dyncast() == DYNCAST.expression) 6299 { 6300 e = cast(Expression)o; 6301 if (auto se = e.isDsymbolExp()) 6302 var = se.s.isDeclaration(); 6303 else if (auto ve = e.isVarExp()) 6304 if (!ve.var.isFuncDeclaration()) 6305 // Exempt functions for backwards compatibility reasons. 6306 // See: https://issues.dlang.org/show_bug.cgi?id=20470#c1 6307 var = ve.var; 6308 } 6309 else if (o.dyncast() == DYNCAST.dsymbol) 6310 { 6311 Dsymbol s = cast(Dsymbol) o; 6312 Declaration d = s.isDeclaration(); 6313 if (!d || d.isFuncDeclaration()) 6314 // Exempt functions for backwards compatibility reasons. 6315 // See: https://issues.dlang.org/show_bug.cgi?id=20470#c1 6316 e = new DsymbolExp(exp.loc, s); 6317 else 6318 var = d; 6319 } 6320 else if (o.dyncast() == DYNCAST.type) 6321 { 6322 e = new TypeExp(exp.loc, cast(Type)o); 6323 } 6324 else 6325 { 6326 exp.error("`%s` is not an expression", o.toChars()); 6327 return setError(); 6328 } 6329 if (var) 6330 e = new DotVarExp(exp.loc, ev, var); 6331 exps.push(e); 6332 } 6333 6334 Expression e = new TupleExp(exp.loc, e0, exps); 6335 e = e.expressionSemantic(sc); 6336 result = e; 6337 return; 6338 } 6339 6340 exp.e1 = exp.e1.addDtorHook(sc); 6341 6342 Type t1 = exp.e1.type; 6343 6344 if (FuncDeclaration fd = exp.var.isFuncDeclaration()) 6345 { 6346 // for functions, do checks after overload resolution 6347 if (!fd.functionSemantic()) 6348 return setError(); 6349 6350 /* https://issues.dlang.org/show_bug.cgi?id=13843 6351 * If fd obviously has no overloads, we should 6352 * normalize AST, and it will give a chance to wrap fd with FuncExp. 6353 */ 6354 if ((fd.isNested() && !fd.isThis()) || fd.isFuncLiteralDeclaration()) 6355 { 6356 // (e1, fd) 6357 auto e = symbolToExp(fd, exp.loc, sc, false); 6358 result = Expression.combine(exp.e1, e); 6359 return; 6360 } 6361 6362 exp.type = fd.type; 6363 assert(exp.type); 6364 } 6365 else if (OverDeclaration od = exp.var.isOverDeclaration()) 6366 { 6367 exp.type = Type.tvoid; // ambiguous type? 6368 } 6369 else 6370 { 6371 exp.type = exp.var.type; 6372 if (!exp.type && global.errors) // var is goofed up, just return error. 6373 return setError(); 6374 assert(exp.type); 6375 6376 if (t1.ty == Tpointer) 6377 t1 = t1.nextOf(); 6378 6379 exp.type = exp.type.addMod(t1.mod); 6380 6381 Dsymbol vparent = exp.var.toParent(); 6382 AggregateDeclaration ad = vparent ? vparent.isAggregateDeclaration() : null; 6383 if (Expression e1x = getRightThis(exp.loc, sc, ad, exp.e1, exp.var, 1)) 6384 exp.e1 = e1x; 6385 else 6386 { 6387 /* Later checkRightThis will report correct error for invalid field variable access. 6388 */ 6389 Expression e = new VarExp(exp.loc, exp.var); 6390 e = e.expressionSemantic(sc); 6391 result = e; 6392 return; 6393 } 6394 checkAccess(exp.loc, sc, exp.e1, exp.var); 6395 6396 VarDeclaration v = exp.var.isVarDeclaration(); 6397 if (v && (v.isDataseg() || (v.storage_class & STC.manifest))) 6398 { 6399 Expression e = expandVar(WANTvalue, v); 6400 if (e) 6401 { 6402 result = e; 6403 return; 6404 } 6405 } 6406 6407 if (v && (v.isDataseg() || // fix https://issues.dlang.org/show_bug.cgi?id=8238 6408 (!v.needThis() && v.semanticRun > PASS.init))) // fix https://issues.dlang.org/show_bug.cgi?id=17258 6409 { 6410 // (e1, v) 6411 checkAccess(exp.loc, sc, exp.e1, v); 6412 Expression e = new VarExp(exp.loc, v); 6413 e = new CommaExp(exp.loc, exp.e1, e); 6414 e = e.expressionSemantic(sc); 6415 result = e; 6416 return; 6417 } 6418 } 6419 //printf("-DotVarExp::semantic('%s')\n", toChars()); 6420 result = exp; 6421 } 6422 6423 override void visit(DotTemplateInstanceExp exp) 6424 { 6425 static if (LOGSEMANTIC) 6426 { 6427 printf("DotTemplateInstanceExp::semantic('%s')\n", exp.toChars()); 6428 } 6429 // Indicate we need to resolve by UFCS. 6430 Expression e = exp.semanticY(sc, 1); 6431 if (!e) 6432 e = resolveUFCSProperties(sc, exp); 6433 result = e; 6434 } 6435 6436 override void visit(DelegateExp e) 6437 { 6438 static if (LOGSEMANTIC) 6439 { 6440 printf("DelegateExp::semantic('%s')\n", e.toChars()); 6441 } 6442 if (e.type) 6443 { 6444 result = e; 6445 return; 6446 } 6447 6448 e.e1 = e.e1.expressionSemantic(sc); 6449 6450 e.type = new TypeDelegate(e.func.type); 6451 e.type = e.type.typeSemantic(e.loc, sc); 6452 6453 FuncDeclaration f = e.func.toAliasFunc(); 6454 AggregateDeclaration ad = f.toParentLocal().isAggregateDeclaration(); 6455 if (f.needThis()) 6456 e.e1 = getRightThis(e.loc, sc, ad, e.e1, f); 6457 if (e.e1.op == TOK.error) 6458 return setError(); 6459 6460 /* A delegate takes the address of e.e1 in order to set the .ptr field 6461 * https://issues.dlang.org/show_bug.cgi?id=18575 6462 */ 6463 if (global.params.vsafe && e.e1.type.toBasetype().ty == Tstruct) 6464 { 6465 if (auto v = expToVariable(e.e1)) 6466 { 6467 if (!checkAddressVar(sc, e.e1, v)) 6468 return setError(); 6469 } 6470 } 6471 6472 if (f.type.ty == Tfunction) 6473 { 6474 TypeFunction tf = cast(TypeFunction)f.type; 6475 if (!MODmethodConv(e.e1.type.mod, f.type.mod)) 6476 { 6477 OutBuffer thisBuf, funcBuf; 6478 MODMatchToBuffer(&thisBuf, e.e1.type.mod, tf.mod); 6479 MODMatchToBuffer(&funcBuf, tf.mod, e.e1.type.mod); 6480 e.error("%smethod `%s` is not callable using a %s`%s`", 6481 funcBuf.peekChars(), f.toPrettyChars(), thisBuf.peekChars(), e.e1.toChars()); 6482 return setError(); 6483 } 6484 } 6485 if (ad && ad.isClassDeclaration() && ad.type != e.e1.type) 6486 { 6487 // A downcast is required for interfaces 6488 // https://issues.dlang.org/show_bug.cgi?id=3706 6489 e.e1 = new CastExp(e.loc, e.e1, ad.type); 6490 e.e1 = e.e1.expressionSemantic(sc); 6491 } 6492 result = e; 6493 // declare dual-context container 6494 if (f.isThis2 && !sc.intypeof && sc.func) 6495 { 6496 // check access to second `this` 6497 if (AggregateDeclaration ad2 = f.isMember2()) 6498 { 6499 Expression te = new ThisExp(e.loc).expressionSemantic(sc); 6500 if (te.op != TOK.error) 6501 te = getRightThis(e.loc, sc, ad2, te, f); 6502 if (te.op == TOK.error) 6503 { 6504 e.error("need `this` of type `%s` to make delegate from function `%s`", ad2.toChars(), f.toChars()); 6505 return setError(); 6506 } 6507 } 6508 VarDeclaration vthis2 = makeThis2Argument(e.loc, sc, f); 6509 e.vthis2 = vthis2; 6510 Expression de = new DeclarationExp(e.loc, vthis2); 6511 result = Expression.combine(de, result); 6512 result = result.expressionSemantic(sc); 6513 } 6514 } 6515 6516 override void visit(DotTypeExp exp) 6517 { 6518 static if (LOGSEMANTIC) 6519 { 6520 printf("DotTypeExp::semantic('%s')\n", exp.toChars()); 6521 } 6522 if (exp.type) 6523 { 6524 result = exp; 6525 return; 6526 } 6527 6528 if (auto e = unaSemantic(exp, sc)) 6529 { 6530 result = e; 6531 return; 6532 } 6533 6534 exp.type = exp.sym.getType().addMod(exp.e1.type.mod); 6535 result = exp; 6536 } 6537 6538 override void visit(AddrExp exp) 6539 { 6540 static if (LOGSEMANTIC) 6541 { 6542 printf("AddrExp::semantic('%s')\n", exp.toChars()); 6543 } 6544 if (exp.type) 6545 { 6546 result = exp; 6547 return; 6548 } 6549 6550 if (Expression ex = unaSemantic(exp, sc)) 6551 { 6552 result = ex; 6553 return; 6554 } 6555 6556 int wasCond = exp.e1.op == TOK.question; 6557 6558 if (exp.e1.op == TOK.dotTemplateInstance) 6559 { 6560 DotTemplateInstanceExp dti = cast(DotTemplateInstanceExp)exp.e1; 6561 TemplateInstance ti = dti.ti; 6562 { 6563 //assert(ti.needsTypeInference(sc)); 6564 ti.dsymbolSemantic(sc); 6565 if (!ti.inst || ti.errors) // if template failed to expand 6566 return setError(); 6567 6568 Dsymbol s = ti.toAlias(); 6569 FuncDeclaration f = s.isFuncDeclaration(); 6570 if (f) 6571 { 6572 exp.e1 = new DotVarExp(exp.e1.loc, dti.e1, f); 6573 exp.e1 = exp.e1.expressionSemantic(sc); 6574 } 6575 } 6576 } 6577 else if (exp.e1.op == TOK.scope_) 6578 { 6579 TemplateInstance ti = (cast(ScopeExp)exp.e1).sds.isTemplateInstance(); 6580 if (ti) 6581 { 6582 //assert(ti.needsTypeInference(sc)); 6583 ti.dsymbolSemantic(sc); 6584 if (!ti.inst || ti.errors) // if template failed to expand 6585 return setError(); 6586 6587 Dsymbol s = ti.toAlias(); 6588 FuncDeclaration f = s.isFuncDeclaration(); 6589 if (f) 6590 { 6591 exp.e1 = new VarExp(exp.e1.loc, f); 6592 exp.e1 = exp.e1.expressionSemantic(sc); 6593 } 6594 } 6595 } 6596 /* https://issues.dlang.org/show_bug.cgi?id=809 6597 * 6598 * If the address of a lazy variable is taken, 6599 * the expression is rewritten so that the type 6600 * of it is the delegate type. This means that 6601 * the symbol is not going to represent a call 6602 * to the delegate anymore, but rather, the 6603 * actual symbol. 6604 */ 6605 if (auto ve = exp.e1.isVarExp()) 6606 { 6607 if (ve.var.storage_class & STC.lazy_) 6608 { 6609 exp.e1 = exp.e1.expressionSemantic(sc); 6610 exp.e1 = resolveProperties(sc, exp.e1); 6611 if (auto callExp = exp.e1.isCallExp()) 6612 { 6613 if (callExp.e1.type.toBasetype().ty == Tdelegate) 6614 { 6615 /* https://issues.dlang.org/show_bug.cgi?id=20551 6616 * 6617 * Cannot take address of lazy parameter in @safe code 6618 * because it might end up being a pointer to undefined 6619 * memory. 6620 */ 6621 if (sc.func && !sc.intypeof && !(sc.flags & SCOPE.debug_) && sc.func.setUnsafe()) 6622 { 6623 exp.error("cannot take address of lazy parameter `%s` in `@safe` function `%s`", 6624 ve.toChars(), sc.func.toChars()); 6625 setError(); 6626 } 6627 else 6628 { 6629 VarExp ve2 = callExp.e1.isVarExp(); 6630 ve2.delegateWasExtracted = true; 6631 ve2.var.storage_class |= STC.scope_; 6632 result = ve2; 6633 } 6634 return; 6635 } 6636 } 6637 } 6638 } 6639 6640 exp.e1 = exp.e1.toLvalue(sc, null); 6641 if (exp.e1.op == TOK.error) 6642 { 6643 result = exp.e1; 6644 return; 6645 } 6646 if (checkNonAssignmentArrayOp(exp.e1)) 6647 return setError(); 6648 6649 if (!exp.e1.type) 6650 { 6651 exp.error("cannot take address of `%s`", exp.e1.toChars()); 6652 return setError(); 6653 } 6654 6655 bool hasOverloads; 6656 if (auto f = isFuncAddress(exp, &hasOverloads)) 6657 { 6658 if (!hasOverloads && f.checkForwardRef(exp.loc)) 6659 return setError(); 6660 } 6661 else if (!exp.e1.type.deco) 6662 { 6663 if (exp.e1.op == TOK.variable) 6664 { 6665 VarExp ve = cast(VarExp)exp.e1; 6666 Declaration d = ve.var; 6667 exp.error("forward reference to %s `%s`", d.kind(), d.toChars()); 6668 } 6669 else 6670 exp.error("forward reference to `%s`", exp.e1.toChars()); 6671 return setError(); 6672 } 6673 6674 exp.type = exp.e1.type.pointerTo(); 6675 6676 // See if this should really be a delegate 6677 if (exp.e1.op == TOK.dotVariable) 6678 { 6679 DotVarExp dve = cast(DotVarExp)exp.e1; 6680 FuncDeclaration f = dve.var.isFuncDeclaration(); 6681 if (f) 6682 { 6683 f = f.toAliasFunc(); // FIXME, should see overloads 6684 // https://issues.dlang.org/show_bug.cgi?id=1983 6685 if (!dve.hasOverloads) 6686 f.tookAddressOf++; 6687 6688 Expression e; 6689 if (f.needThis()) 6690 e = new DelegateExp(exp.loc, dve.e1, f, dve.hasOverloads); 6691 else // It is a function pointer. Convert &v.f() --> (v, &V.f()) 6692 e = new CommaExp(exp.loc, dve.e1, new AddrExp(exp.loc, new VarExp(exp.loc, f, dve.hasOverloads))); 6693 e = e.expressionSemantic(sc); 6694 result = e; 6695 return; 6696 } 6697 6698 // Look for misaligned pointer in @safe mode 6699 if (checkUnsafeAccess(sc, dve, !exp.type.isMutable(), true)) 6700 return setError(); 6701 6702 if (global.params.vsafe) 6703 { 6704 if (VarDeclaration v = expToVariable(dve.e1)) 6705 { 6706 if (!checkAddressVar(sc, exp.e1, v)) 6707 return setError(); 6708 } 6709 } 6710 } 6711 else if (exp.e1.op == TOK.variable) 6712 { 6713 VarExp ve = cast(VarExp)exp.e1; 6714 VarDeclaration v = ve.var.isVarDeclaration(); 6715 if (v) 6716 { 6717 if (!checkAddressVar(sc, exp.e1, v)) 6718 return setError(); 6719 6720 ve.checkPurity(sc, v); 6721 } 6722 FuncDeclaration f = ve.var.isFuncDeclaration(); 6723 if (f) 6724 { 6725 /* Because nested functions cannot be overloaded, 6726 * mark here that we took its address because castTo() 6727 * may not be called with an exact match. 6728 */ 6729 if (!ve.hasOverloads || (f.isNested() && !f.needThis())) 6730 f.tookAddressOf++; 6731 if (f.isNested() && !f.needThis()) 6732 { 6733 if (f.isFuncLiteralDeclaration()) 6734 { 6735 if (!f.FuncDeclaration.isNested()) 6736 { 6737 /* Supply a 'null' for a this pointer if no this is available 6738 */ 6739 Expression e = new DelegateExp(exp.loc, new NullExp(exp.loc, Type.tnull), f, ve.hasOverloads); 6740 e = e.expressionSemantic(sc); 6741 result = e; 6742 return; 6743 } 6744 } 6745 Expression e = new DelegateExp(exp.loc, exp.e1, f, ve.hasOverloads); 6746 e = e.expressionSemantic(sc); 6747 result = e; 6748 return; 6749 } 6750 if (f.needThis()) 6751 { 6752 if (hasThis(sc)) 6753 { 6754 /* Should probably supply 'this' after overload resolution, 6755 * not before. 6756 */ 6757 Expression ethis = new ThisExp(exp.loc); 6758 Expression e = new DelegateExp(exp.loc, ethis, f, ve.hasOverloads); 6759 e = e.expressionSemantic(sc); 6760 result = e; 6761 return; 6762 } 6763 if (sc.func && !sc.intypeof) 6764 { 6765 if (!(sc.flags & SCOPE.debug_) && sc.func.setUnsafe()) 6766 { 6767 exp.error("`this` reference necessary to take address of member `%s` in `@safe` function `%s`", f.toChars(), sc.func.toChars()); 6768 } 6769 } 6770 } 6771 } 6772 } 6773 else if ((exp.e1.op == TOK.this_ || exp.e1.op == TOK.super_) && global.params.vsafe) 6774 { 6775 if (VarDeclaration v = expToVariable(exp.e1)) 6776 { 6777 if (!checkAddressVar(sc, exp.e1, v)) 6778 return setError(); 6779 } 6780 } 6781 else if (exp.e1.op == TOK.call) 6782 { 6783 CallExp ce = cast(CallExp)exp.e1; 6784 if (ce.e1.type.ty == Tfunction) 6785 { 6786 TypeFunction tf = cast(TypeFunction)ce.e1.type; 6787 if (tf.isref && sc.func && !sc.intypeof && !(sc.flags & SCOPE.debug_) && sc.func.setUnsafe()) 6788 { 6789 exp.error("cannot take address of `ref return` of `%s()` in `@safe` function `%s`", 6790 ce.e1.toChars(), sc.func.toChars()); 6791 } 6792 } 6793 } 6794 else if (exp.e1.op == TOK.index) 6795 { 6796 /* For: 6797 * int[3] a; 6798 * &a[i] 6799 * check 'a' the same as for a regular variable 6800 */ 6801 if (VarDeclaration v = expToVariable(exp.e1)) 6802 { 6803 if (global.params.vsafe && !checkAddressVar(sc, exp.e1, v)) 6804 return setError(); 6805 6806 exp.e1.checkPurity(sc, v); 6807 } 6808 } 6809 else if (wasCond) 6810 { 6811 /* a ? b : c was transformed to *(a ? &b : &c), but we still 6812 * need to do safety checks 6813 */ 6814 assert(exp.e1.op == TOK.star); 6815 PtrExp pe = cast(PtrExp)exp.e1; 6816 assert(pe.e1.op == TOK.question); 6817 CondExp ce = cast(CondExp)pe.e1; 6818 assert(ce.e1.op == TOK.address); 6819 assert(ce.e2.op == TOK.address); 6820 6821 // Re-run semantic on the address expressions only 6822 ce.e1.type = null; 6823 ce.e1 = ce.e1.expressionSemantic(sc); 6824 ce.e2.type = null; 6825 ce.e2 = ce.e2.expressionSemantic(sc); 6826 } 6827 result = exp.optimize(WANTvalue); 6828 } 6829 6830 override void visit(PtrExp exp) 6831 { 6832 static if (LOGSEMANTIC) 6833 { 6834 printf("PtrExp::semantic('%s')\n", exp.toChars()); 6835 } 6836 if (exp.type) 6837 { 6838 result = exp; 6839 return; 6840 } 6841 6842 Expression e = exp.op_overload(sc); 6843 if (e) 6844 { 6845 result = e; 6846 return; 6847 } 6848 6849 Type tb = exp.e1.type.toBasetype(); 6850 switch (tb.ty) 6851 { 6852 case Tpointer: 6853 exp.type = (cast(TypePointer)tb).next; 6854 break; 6855 6856 case Tsarray: 6857 case Tarray: 6858 if (isNonAssignmentArrayOp(exp.e1)) 6859 goto default; 6860 exp.error("using `*` on an array is no longer supported; use `*(%s).ptr` instead", exp.e1.toChars()); 6861 exp.type = (cast(TypeArray)tb).next; 6862 exp.e1 = exp.e1.castTo(sc, exp.type.pointerTo()); 6863 break; 6864 6865 case Terror: 6866 return setError(); 6867 6868 default: 6869 exp.error("can only `*` a pointer, not a `%s`", exp.e1.type.toChars()); 6870 goto case Terror; 6871 } 6872 6873 if (exp.checkValue()) 6874 return setError(); 6875 6876 result = exp; 6877 } 6878 6879 override void visit(NegExp exp) 6880 { 6881 static if (LOGSEMANTIC) 6882 { 6883 printf("NegExp::semantic('%s')\n", exp.toChars()); 6884 } 6885 if (exp.type) 6886 { 6887 result = exp; 6888 return; 6889 } 6890 6891 Expression e = exp.op_overload(sc); 6892 if (e) 6893 { 6894 result = e; 6895 return; 6896 } 6897 6898 fix16997(sc, exp); 6899 exp.type = exp.e1.type; 6900 Type tb = exp.type.toBasetype(); 6901 if (tb.ty == Tarray || tb.ty == Tsarray) 6902 { 6903 if (!isArrayOpValid(exp.e1)) 6904 { 6905 result = arrayOpInvalidError(exp); 6906 return; 6907 } 6908 result = exp; 6909 return; 6910 } 6911 if (!target.isVectorOpSupported(tb, exp.op)) 6912 { 6913 result = exp.incompatibleTypes(); 6914 return; 6915 } 6916 if (exp.e1.checkNoBool()) 6917 return setError(); 6918 if (exp.e1.checkArithmetic() || 6919 exp.e1.checkSharedAccess(sc)) 6920 return setError(); 6921 6922 result = exp; 6923 } 6924 6925 override void visit(UAddExp exp) 6926 { 6927 static if (LOGSEMANTIC) 6928 { 6929 printf("UAddExp::semantic('%s')\n", exp.toChars()); 6930 } 6931 assert(!exp.type); 6932 6933 Expression e = exp.op_overload(sc); 6934 if (e) 6935 { 6936 result = e; 6937 return; 6938 } 6939 6940 fix16997(sc, exp); 6941 if (!target.isVectorOpSupported(exp.e1.type.toBasetype(), exp.op)) 6942 { 6943 result = exp.incompatibleTypes(); 6944 return; 6945 } 6946 if (exp.e1.checkNoBool()) 6947 return setError(); 6948 if (exp.e1.checkArithmetic()) 6949 return setError(); 6950 if (exp.e1.checkSharedAccess(sc)) 6951 return setError(); 6952 6953 result = exp.e1; 6954 } 6955 6956 override void visit(ComExp exp) 6957 { 6958 if (exp.type) 6959 { 6960 result = exp; 6961 return; 6962 } 6963 6964 Expression e = exp.op_overload(sc); 6965 if (e) 6966 { 6967 result = e; 6968 return; 6969 } 6970 6971 fix16997(sc, exp); 6972 exp.type = exp.e1.type; 6973 Type tb = exp.type.toBasetype(); 6974 if (tb.ty == Tarray || tb.ty == Tsarray) 6975 { 6976 if (!isArrayOpValid(exp.e1)) 6977 { 6978 result = arrayOpInvalidError(exp); 6979 return; 6980 } 6981 result = exp; 6982 return; 6983 } 6984 if (!target.isVectorOpSupported(tb, exp.op)) 6985 { 6986 result = exp.incompatibleTypes(); 6987 return; 6988 } 6989 if (exp.e1.checkNoBool()) 6990 return setError(); 6991 if (exp.e1.checkIntegral() || 6992 exp.e1.checkSharedAccess(sc)) 6993 return setError(); 6994 6995 result = exp; 6996 } 6997 6998 override void visit(NotExp e) 6999 { 7000 if (e.type) 7001 { 7002 result = e; 7003 return; 7004 } 7005 7006 e.setNoderefOperand(); 7007 7008 // Note there is no operator overload 7009 if (Expression ex = unaSemantic(e, sc)) 7010 { 7011 result = ex; 7012 return; 7013 } 7014 7015 // for static alias this: https://issues.dlang.org/show_bug.cgi?id=17684 7016 if (e.e1.op == TOK.type) 7017 e.e1 = resolveAliasThis(sc, e.e1); 7018 7019 e.e1 = resolveProperties(sc, e.e1); 7020 e.e1 = e.e1.toBoolean(sc); 7021 if (e.e1.type == Type.terror) 7022 { 7023 result = e.e1; 7024 return; 7025 } 7026 7027 if (!target.isVectorOpSupported(e.e1.type.toBasetype(), e.op)) 7028 { 7029 result = e.incompatibleTypes(); 7030 } 7031 // https://issues.dlang.org/show_bug.cgi?id=13910 7032 // Today NotExp can take an array as its operand. 7033 if (checkNonAssignmentArrayOp(e.e1)) 7034 return setError(); 7035 7036 e.type = Type.tbool; 7037 result = e; 7038 } 7039 7040 override void visit(DeleteExp exp) 7041 { 7042 if (!sc.isDeprecated) 7043 { 7044 // @@@DEPRECATED_2019-02@@@ 7045 // 1. Deprecation for 1 year 7046 // 2. Error for 1 year 7047 // 3. Removal of keyword, "delete" can be used for other identities 7048 if (!exp.isRAII) 7049 deprecation(exp.loc, "The `delete` keyword has been deprecated. Use `object.destroy()` (and `core.memory.GC.free()` if applicable) instead."); 7050 } 7051 7052 if (Expression ex = unaSemantic(exp, sc)) 7053 { 7054 result = ex; 7055 return; 7056 } 7057 exp.e1 = resolveProperties(sc, exp.e1); 7058 exp.e1 = exp.e1.modifiableLvalue(sc, null); 7059 if (exp.e1.op == TOK.error) 7060 { 7061 result = exp.e1; 7062 return; 7063 } 7064 exp.type = Type.tvoid; 7065 7066 AggregateDeclaration ad = null; 7067 Type tb = exp.e1.type.toBasetype(); 7068 switch (tb.ty) 7069 { 7070 case Tclass: 7071 { 7072 auto cd = (cast(TypeClass)tb).sym; 7073 if (cd.isCOMinterface()) 7074 { 7075 /* Because COM classes are deleted by IUnknown.Release() 7076 */ 7077 exp.error("cannot `delete` instance of COM interface `%s`", cd.toChars()); 7078 return setError(); 7079 } 7080 ad = cd; 7081 break; 7082 } 7083 case Tpointer: 7084 tb = (cast(TypePointer)tb).next.toBasetype(); 7085 if (tb.ty == Tstruct) 7086 { 7087 ad = (cast(TypeStruct)tb).sym; 7088 semanticTypeInfo(sc, tb); 7089 } 7090 break; 7091 7092 case Tarray: 7093 { 7094 Type tv = tb.nextOf().baseElemOf(); 7095 if (tv.ty == Tstruct) 7096 { 7097 ad = (cast(TypeStruct)tv).sym; 7098 if (ad.dtor) 7099 semanticTypeInfo(sc, ad.type); 7100 } 7101 break; 7102 } 7103 default: 7104 exp.error("cannot delete type `%s`", exp.e1.type.toChars()); 7105 return setError(); 7106 } 7107 7108 bool err = false; 7109 if (ad) 7110 { 7111 if (ad.dtor) 7112 { 7113 err |= exp.checkPurity(sc, ad.dtor); 7114 err |= exp.checkSafety(sc, ad.dtor); 7115 err |= exp.checkNogc(sc, ad.dtor); 7116 } 7117 if (err) 7118 return setError(); 7119 } 7120 7121 if (!sc.intypeof && sc.func && 7122 !exp.isRAII && 7123 !(sc.flags & SCOPE.debug_) && 7124 sc.func.setUnsafe()) 7125 { 7126 exp.error("`%s` is not `@safe` but is used in `@safe` function `%s`", exp.toChars(), sc.func.toChars()); 7127 err = true; 7128 } 7129 if (err) 7130 return setError(); 7131 7132 result = exp; 7133 } 7134 7135 override void visit(CastExp exp) 7136 { 7137 static if (LOGSEMANTIC) 7138 { 7139 printf("CastExp::semantic('%s')\n", exp.toChars()); 7140 } 7141 //static int x; assert(++x < 10); 7142 if (exp.type) 7143 { 7144 result = exp; 7145 return; 7146 } 7147 7148 if (exp.to) 7149 { 7150 exp.to = exp.to.typeSemantic(exp.loc, sc); 7151 if (exp.to == Type.terror) 7152 return setError(); 7153 7154 if (!exp.to.hasPointers()) 7155 exp.setNoderefOperand(); 7156 7157 // When e1 is a template lambda, this cast may instantiate it with 7158 // the type 'to'. 7159 exp.e1 = inferType(exp.e1, exp.to); 7160 } 7161 7162 if (auto e = unaSemantic(exp, sc)) 7163 { 7164 result = e; 7165 return; 7166 } 7167 7168 // for static alias this: https://issues.dlang.org/show_bug.cgi?id=17684 7169 if (exp.e1.op == TOK.type) 7170 exp.e1 = resolveAliasThis(sc, exp.e1); 7171 7172 auto e1x = resolveProperties(sc, exp.e1); 7173 if (e1x.op == TOK.error) 7174 { 7175 result = e1x; 7176 return; 7177 } 7178 if (e1x.checkType()) 7179 return setError(); 7180 exp.e1 = e1x; 7181 7182 if (!exp.e1.type) 7183 { 7184 exp.error("cannot cast `%s`", exp.e1.toChars()); 7185 return setError(); 7186 } 7187 7188 // https://issues.dlang.org/show_bug.cgi?id=19954 7189 if (exp.e1.type.ty == Ttuple) 7190 { 7191 TupleExp te = exp.e1.isTupleExp(); 7192 if (te.exps.dim == 1) 7193 exp.e1 = (*te.exps)[0]; 7194 } 7195 7196 // only allow S(x) rewrite if cast specified S explicitly. 7197 // See https://issues.dlang.org/show_bug.cgi?id=18545 7198 const bool allowImplicitConstruction = exp.to !is null; 7199 7200 if (!exp.to) // Handle cast(const) and cast(immutable), etc. 7201 { 7202 exp.to = exp.e1.type.castMod(exp.mod); 7203 exp.to = exp.to.typeSemantic(exp.loc, sc); 7204 7205 if (exp.to == Type.terror) 7206 return setError(); 7207 } 7208 7209 if (exp.to.ty == Ttuple) 7210 { 7211 exp.error("cannot cast `%s` to tuple type `%s`", exp.e1.toChars(), exp.to.toChars()); 7212 return setError(); 7213 } 7214 7215 // cast(void) is used to mark e1 as unused, so it is safe 7216 if (exp.to.ty == Tvoid) 7217 { 7218 exp.type = exp.to; 7219 result = exp; 7220 return; 7221 } 7222 7223 if (!exp.to.equals(exp.e1.type) && exp.mod == cast(ubyte)~0) 7224 { 7225 if (Expression e = exp.op_overload(sc)) 7226 { 7227 result = e.implicitCastTo(sc, exp.to); 7228 return; 7229 } 7230 } 7231 7232 Type t1b = exp.e1.type.toBasetype(); 7233 Type tob = exp.to.toBasetype(); 7234 7235 if (allowImplicitConstruction && tob.ty == Tstruct && !tob.equals(t1b)) 7236 { 7237 /* Look to replace: 7238 * cast(S)t 7239 * with: 7240 * S(t) 7241 */ 7242 7243 // Rewrite as to.call(e1) 7244 Expression e = new TypeExp(exp.loc, exp.to); 7245 e = new CallExp(exp.loc, e, exp.e1); 7246 e = e.trySemantic(sc); 7247 if (e) 7248 { 7249 result = e; 7250 return; 7251 } 7252 } 7253 7254 if (!t1b.equals(tob) && (t1b.ty == Tarray || t1b.ty == Tsarray)) 7255 { 7256 if (checkNonAssignmentArrayOp(exp.e1)) 7257 return setError(); 7258 } 7259 7260 // Look for casting to a vector type 7261 if (tob.ty == Tvector && t1b.ty != Tvector) 7262 { 7263 result = new VectorExp(exp.loc, exp.e1, exp.to); 7264 result = result.expressionSemantic(sc); 7265 return; 7266 } 7267 7268 Expression ex = exp.e1.castTo(sc, exp.to); 7269 if (ex.op == TOK.error) 7270 { 7271 result = ex; 7272 return; 7273 } 7274 7275 // Check for unsafe casts 7276 if (!sc.intypeof && 7277 !(sc.flags & SCOPE.debug_) && 7278 !isSafeCast(ex, t1b, tob) && 7279 (!sc.func && sc.stc & STC.safe || sc.func && sc.func.setUnsafe())) 7280 { 7281 exp.error("cast from `%s` to `%s` not allowed in safe code", exp.e1.type.toChars(), exp.to.toChars()); 7282 return setError(); 7283 } 7284 7285 // `object.__ArrayCast` is a rewrite of an old runtime hook `_d_arraycast`. `_d_arraycast` was not built 7286 // to handle certain casts. Those casts which `object.__ArrayCast` does not support are filtered out. 7287 // See `e2ir.toElemCast` for other types of casts. If `object.__ArrayCast` is improved to support more 7288 // casts these conditions and potentially some logic in `e2ir.toElemCast` can be removed. 7289 if (tob.ty == Tarray) 7290 { 7291 // https://issues.dlang.org/show_bug.cgi?id=19840 7292 if (auto ad = isAggregate(t1b)) 7293 { 7294 if (ad.aliasthis) 7295 { 7296 Expression e = resolveAliasThis(sc, exp.e1); 7297 e = new CastExp(exp.loc, e, exp.to); 7298 result = e.expressionSemantic(sc); 7299 return; 7300 } 7301 } 7302 7303 if(t1b.ty == Tarray && exp.e1.op != TOK.arrayLiteral && (sc.flags & SCOPE.ctfe) == 0) 7304 { 7305 auto tFrom = t1b.nextOf(); 7306 auto tTo = tob.nextOf(); 7307 7308 // https://issues.dlang.org/show_bug.cgi?id=20130 7309 if (exp.e1.op != TOK.string_ || !ex.isStringExp) 7310 { 7311 const uint fromSize = cast(uint)tFrom.size(); 7312 const uint toSize = cast(uint)tTo.size(); 7313 7314 // If array element sizes do not match, we must adjust the dimensions 7315 if (fromSize != toSize) 7316 { 7317 if (!verifyHookExist(exp.loc, *sc, Id.__ArrayCast, "casting array of structs")) 7318 return setError(); 7319 7320 // A runtime check is needed in case arrays don't line up. That check should 7321 // be done in the implementation of `object.__ArrayCast` 7322 if (toSize == 0 || (fromSize % toSize) != 0) 7323 { 7324 // lower to `object.__ArrayCast!(TFrom, TTo)(from)` 7325 7326 // fully qualify as `object.__ArrayCast` 7327 Expression id = new IdentifierExp(exp.loc, Id.empty); 7328 auto dotid = new DotIdExp(exp.loc, id, Id.object); 7329 7330 auto tiargs = new Objects(); 7331 tiargs.push(tFrom); 7332 tiargs.push(tTo); 7333 auto dt = new DotTemplateInstanceExp(exp.loc, dotid, Id.__ArrayCast, tiargs); 7334 7335 auto arguments = new Expressions(); 7336 arguments.push(exp.e1); 7337 Expression ce = new CallExp(exp.loc, dt, arguments); 7338 7339 result = expressionSemantic(ce, sc); 7340 return; 7341 } 7342 } 7343 } 7344 } 7345 } 7346 7347 result = ex; 7348 } 7349 7350 override void visit(VectorExp exp) 7351 { 7352 static if (LOGSEMANTIC) 7353 { 7354 printf("VectorExp::semantic('%s')\n", exp.toChars()); 7355 } 7356 if (exp.type) 7357 { 7358 result = exp; 7359 return; 7360 } 7361 7362 exp.e1 = exp.e1.expressionSemantic(sc); 7363 exp.type = exp.to.typeSemantic(exp.loc, sc); 7364 if (exp.e1.op == TOK.error || exp.type.ty == Terror) 7365 { 7366 result = exp.e1; 7367 return; 7368 } 7369 7370 Type tb = exp.type.toBasetype(); 7371 assert(tb.ty == Tvector); 7372 TypeVector tv = cast(TypeVector)tb; 7373 Type te = tv.elementType(); 7374 exp.dim = cast(int)(tv.size(exp.loc) / te.size(exp.loc)); 7375 7376 bool checkElem(Expression elem) 7377 { 7378 if (elem.isConst() == 1) 7379 return false; 7380 7381 exp.error("constant expression expected, not `%s`", elem.toChars()); 7382 return true; 7383 } 7384 7385 exp.e1 = exp.e1.optimize(WANTvalue); 7386 bool res; 7387 if (exp.e1.op == TOK.arrayLiteral) 7388 { 7389 foreach (i; 0 .. exp.dim) 7390 { 7391 // Do not stop on first error - check all AST nodes even if error found 7392 res |= checkElem(exp.e1.isArrayLiteralExp()[i]); 7393 } 7394 } 7395 else if (exp.e1.type.ty == Tvoid) 7396 checkElem(exp.e1); 7397 7398 result = res ? ErrorExp.get() : exp; 7399 } 7400 7401 override void visit(VectorArrayExp e) 7402 { 7403 static if (LOGSEMANTIC) 7404 { 7405 printf("VectorArrayExp::semantic('%s')\n", e.toChars()); 7406 } 7407 if (!e.type) 7408 { 7409 unaSemantic(e, sc); 7410 e.e1 = resolveProperties(sc, e.e1); 7411 7412 if (e.e1.op == TOK.error) 7413 { 7414 result = e.e1; 7415 return; 7416 } 7417 assert(e.e1.type.ty == Tvector); 7418 e.type = e.e1.type.isTypeVector().basetype; 7419 } 7420 result = e; 7421 } 7422 7423 override void visit(SliceExp exp) 7424 { 7425 static if (LOGSEMANTIC) 7426 { 7427 printf("SliceExp::semantic('%s')\n", exp.toChars()); 7428 } 7429 if (exp.type) 7430 { 7431 result = exp; 7432 return; 7433 } 7434 7435 // operator overloading should be handled in ArrayExp already. 7436 if (Expression ex = unaSemantic(exp, sc)) 7437 { 7438 result = ex; 7439 return; 7440 } 7441 exp.e1 = resolveProperties(sc, exp.e1); 7442 if (exp.e1.op == TOK.type && exp.e1.type.ty != Ttuple) 7443 { 7444 if (exp.lwr || exp.upr) 7445 { 7446 exp.error("cannot slice type `%s`", exp.e1.toChars()); 7447 return setError(); 7448 } 7449 Expression e = new TypeExp(exp.loc, exp.e1.type.arrayOf()); 7450 result = e.expressionSemantic(sc); 7451 return; 7452 } 7453 if (!exp.lwr && !exp.upr) 7454 { 7455 if (exp.e1.op == TOK.arrayLiteral) 7456 { 7457 // Convert [a,b,c][] to [a,b,c] 7458 Type t1b = exp.e1.type.toBasetype(); 7459 Expression e = exp.e1; 7460 if (t1b.ty == Tsarray) 7461 { 7462 e = e.copy(); 7463 e.type = t1b.nextOf().arrayOf(); 7464 } 7465 result = e; 7466 return; 7467 } 7468 if (exp.e1.op == TOK.slice) 7469 { 7470 // Convert e[][] to e[] 7471 SliceExp se = cast(SliceExp)exp.e1; 7472 if (!se.lwr && !se.upr) 7473 { 7474 result = se; 7475 return; 7476 } 7477 } 7478 if (isArrayOpOperand(exp.e1)) 7479 { 7480 // Convert (a[]+b[])[] to a[]+b[] 7481 result = exp.e1; 7482 return; 7483 } 7484 } 7485 if (exp.e1.op == TOK.error) 7486 { 7487 result = exp.e1; 7488 return; 7489 } 7490 if (exp.e1.type.ty == Terror) 7491 return setError(); 7492 7493 Type t1b = exp.e1.type.toBasetype(); 7494 if (t1b.ty == Tpointer) 7495 { 7496 if ((cast(TypePointer)t1b).next.ty == Tfunction) 7497 { 7498 exp.error("cannot slice function pointer `%s`", exp.e1.toChars()); 7499 return setError(); 7500 } 7501 if (!exp.lwr || !exp.upr) 7502 { 7503 exp.error("need upper and lower bound to slice pointer"); 7504 return setError(); 7505 } 7506 if (sc.func && !sc.intypeof && !(sc.flags & SCOPE.debug_) && sc.func.setUnsafe()) 7507 { 7508 exp.error("pointer slicing not allowed in safe functions"); 7509 return setError(); 7510 } 7511 } 7512 else if (t1b.ty == Tarray) 7513 { 7514 } 7515 else if (t1b.ty == Tsarray) 7516 { 7517 if (!exp.arrayop && global.params.vsafe) 7518 { 7519 /* Slicing a static array is like taking the address of it. 7520 * Perform checks as if e[] was &e 7521 */ 7522 if (VarDeclaration v = expToVariable(exp.e1)) 7523 { 7524 if (exp.e1.op == TOK.dotVariable) 7525 { 7526 DotVarExp dve = cast(DotVarExp)exp.e1; 7527 if ((dve.e1.op == TOK.this_ || dve.e1.op == TOK.super_) && 7528 !(v.storage_class & STC.ref_)) 7529 { 7530 // because it's a class 7531 v = null; 7532 } 7533 } 7534 7535 if (v && !checkAddressVar(sc, exp.e1, v)) 7536 return setError(); 7537 } 7538 } 7539 } 7540 else if (t1b.ty == Ttuple) 7541 { 7542 if (!exp.lwr && !exp.upr) 7543 { 7544 result = exp.e1; 7545 return; 7546 } 7547 if (!exp.lwr || !exp.upr) 7548 { 7549 exp.error("need upper and lower bound to slice tuple"); 7550 return setError(); 7551 } 7552 } 7553 else if (t1b.ty == Tvector) 7554 { 7555 // Convert e1 to corresponding static array 7556 TypeVector tv1 = cast(TypeVector)t1b; 7557 t1b = tv1.basetype; 7558 t1b = t1b.castMod(tv1.mod); 7559 exp.e1.type = t1b; 7560 } 7561 else 7562 { 7563 exp.error("`%s` cannot be sliced with `[]`", t1b.ty == Tvoid ? exp.e1.toChars() : t1b.toChars()); 7564 return setError(); 7565 } 7566 7567 /* Run semantic on lwr and upr. 7568 */ 7569 Scope* scx = sc; 7570 if (t1b.ty == Tsarray || t1b.ty == Tarray || t1b.ty == Ttuple) 7571 { 7572 // Create scope for 'length' variable 7573 ScopeDsymbol sym = new ArrayScopeSymbol(sc, exp); 7574 sym.parent = sc.scopesym; 7575 sc = sc.push(sym); 7576 } 7577 if (exp.lwr) 7578 { 7579 if (t1b.ty == Ttuple) 7580 sc = sc.startCTFE(); 7581 exp.lwr = exp.lwr.expressionSemantic(sc); 7582 exp.lwr = resolveProperties(sc, exp.lwr); 7583 if (t1b.ty == Ttuple) 7584 sc = sc.endCTFE(); 7585 exp.lwr = exp.lwr.implicitCastTo(sc, Type.tsize_t); 7586 } 7587 if (exp.upr) 7588 { 7589 if (t1b.ty == Ttuple) 7590 sc = sc.startCTFE(); 7591 exp.upr = exp.upr.expressionSemantic(sc); 7592 exp.upr = resolveProperties(sc, exp.upr); 7593 if (t1b.ty == Ttuple) 7594 sc = sc.endCTFE(); 7595 exp.upr = exp.upr.implicitCastTo(sc, Type.tsize_t); 7596 } 7597 if (sc != scx) 7598 sc = sc.pop(); 7599 if (exp.lwr && exp.lwr.type == Type.terror || exp.upr && exp.upr.type == Type.terror) 7600 return setError(); 7601 7602 if (t1b.ty == Ttuple) 7603 { 7604 exp.lwr = exp.lwr.ctfeInterpret(); 7605 exp.upr = exp.upr.ctfeInterpret(); 7606 uinteger_t i1 = exp.lwr.toUInteger(); 7607 uinteger_t i2 = exp.upr.toUInteger(); 7608 7609 TupleExp te; 7610 TypeTuple tup; 7611 size_t length; 7612 if (exp.e1.op == TOK.tuple) // slicing an expression tuple 7613 { 7614 te = cast(TupleExp)exp.e1; 7615 tup = null; 7616 length = te.exps.dim; 7617 } 7618 else if (exp.e1.op == TOK.type) // slicing a type tuple 7619 { 7620 te = null; 7621 tup = cast(TypeTuple)t1b; 7622 length = Parameter.dim(tup.arguments); 7623 } 7624 else 7625 assert(0); 7626 7627 if (i2 < i1 || length < i2) 7628 { 7629 exp.error("string slice `[%llu .. %llu]` is out of bounds", i1, i2); 7630 return setError(); 7631 } 7632 7633 size_t j1 = cast(size_t)i1; 7634 size_t j2 = cast(size_t)i2; 7635 Expression e; 7636 if (exp.e1.op == TOK.tuple) 7637 { 7638 auto exps = new Expressions(j2 - j1); 7639 for (size_t i = 0; i < j2 - j1; i++) 7640 { 7641 (*exps)[i] = (*te.exps)[j1 + i]; 7642 } 7643 e = new TupleExp(exp.loc, te.e0, exps); 7644 } 7645 else 7646 { 7647 auto args = new Parameters(); 7648 args.reserve(j2 - j1); 7649 for (size_t i = j1; i < j2; i++) 7650 { 7651 Parameter arg = Parameter.getNth(tup.arguments, i); 7652 args.push(arg); 7653 } 7654 e = new TypeExp(exp.e1.loc, new TypeTuple(args)); 7655 } 7656 e = e.expressionSemantic(sc); 7657 result = e; 7658 return; 7659 } 7660 7661 exp.type = t1b.nextOf().arrayOf(); 7662 // Allow typedef[] -> typedef[] 7663 if (exp.type.equals(t1b)) 7664 exp.type = exp.e1.type; 7665 7666 // We might know $ now 7667 setLengthVarIfKnown(exp.lengthVar, t1b); 7668 7669 if (exp.lwr && exp.upr) 7670 { 7671 exp.lwr = exp.lwr.optimize(WANTvalue); 7672 exp.upr = exp.upr.optimize(WANTvalue); 7673 7674 IntRange lwrRange = getIntRange(exp.lwr); 7675 IntRange uprRange = getIntRange(exp.upr); 7676 7677 if (t1b.ty == Tsarray || t1b.ty == Tarray) 7678 { 7679 Expression el = new ArrayLengthExp(exp.loc, exp.e1); 7680 el = el.expressionSemantic(sc); 7681 el = el.optimize(WANTvalue); 7682 if (el.op == TOK.int64) 7683 { 7684 // Array length is known at compile-time. Upper is in bounds if it fits length. 7685 dinteger_t length = el.toInteger(); 7686 auto bounds = IntRange(SignExtendedNumber(0), SignExtendedNumber(length)); 7687 exp.upperIsInBounds = bounds.contains(uprRange); 7688 } 7689 else if (exp.upr.op == TOK.int64 && exp.upr.toInteger() == 0) 7690 { 7691 // Upper slice expression is '0'. Value is always in bounds. 7692 exp.upperIsInBounds = true; 7693 } 7694 else if (exp.upr.op == TOK.variable && (cast(VarExp)exp.upr).var.ident == Id.dollar) 7695 { 7696 // Upper slice expression is '$'. Value is always in bounds. 7697 exp.upperIsInBounds = true; 7698 } 7699 } 7700 else if (t1b.ty == Tpointer) 7701 { 7702 exp.upperIsInBounds = true; 7703 } 7704 else 7705 assert(0); 7706 7707 exp.lowerIsLessThanUpper = (lwrRange.imax <= uprRange.imin); 7708 7709 //printf("upperIsInBounds = %d lowerIsLessThanUpper = %d\n", exp.upperIsInBounds, exp.lowerIsLessThanUpper); 7710 } 7711 7712 result = exp; 7713 } 7714 7715 override void visit(ArrayLengthExp e) 7716 { 7717 static if (LOGSEMANTIC) 7718 { 7719 printf("ArrayLengthExp::semantic('%s')\n", e.toChars()); 7720 } 7721 if (e.type) 7722 { 7723 result = e; 7724 return; 7725 } 7726 7727 if (Expression ex = unaSemantic(e, sc)) 7728 { 7729 result = ex; 7730 return; 7731 } 7732 e.e1 = resolveProperties(sc, e.e1); 7733 7734 e.type = Type.tsize_t; 7735 result = e; 7736 } 7737 7738 override void visit(ArrayExp exp) 7739 { 7740 static if (LOGSEMANTIC) 7741 { 7742 printf("ArrayExp::semantic('%s')\n", exp.toChars()); 7743 } 7744 assert(!exp.type); 7745 Expression e = exp.op_overload(sc); 7746 if (e) 7747 { 7748 result = e; 7749 return; 7750 } 7751 7752 if (isAggregate(exp.e1.type)) 7753 exp.error("no `[]` operator overload for type `%s`", exp.e1.type.toChars()); 7754 else if (exp.e1.op == TOK.type && exp.e1.type.ty != Ttuple) 7755 exp.error("static array of `%s` with multiple lengths not allowed", exp.e1.type.toChars()); 7756 else if (isIndexableNonAggregate(exp.e1.type)) 7757 exp.error("only one index allowed to index `%s`", exp.e1.type.toChars()); 7758 else 7759 exp.error("cannot use `[]` operator on expression of type `%s`", exp.e1.type.toChars()); 7760 7761 result = ErrorExp.get(); 7762 } 7763 7764 override void visit(DotExp exp) 7765 { 7766 static if (LOGSEMANTIC) 7767 { 7768 printf("DotExp::semantic('%s')\n", exp.toChars()); 7769 if (exp.type) 7770 printf("\ttype = %s\n", exp.type.toChars()); 7771 } 7772 exp.e1 = exp.e1.expressionSemantic(sc); 7773 exp.e2 = exp.e2.expressionSemantic(sc); 7774 7775 if (exp.e1.op == TOK.type) 7776 { 7777 result = exp.e2; 7778 return; 7779 } 7780 if (exp.e2.op == TOK.type) 7781 { 7782 result = exp.e2; 7783 return; 7784 } 7785 if (exp.e2.op == TOK.template_) 7786 { 7787 auto td = (cast(TemplateExp)exp.e2).td; 7788 Expression e = new DotTemplateExp(exp.loc, exp.e1, td); 7789 result = e.expressionSemantic(sc); 7790 return; 7791 } 7792 if (!exp.type || exp.e1.op == TOK.this_) 7793 exp.type = exp.e2.type; 7794 result = exp; 7795 } 7796 7797 override void visit(CommaExp e) 7798 { 7799 if (e.type) 7800 { 7801 result = e; 7802 return; 7803 } 7804 7805 // Allow `((a,b),(x,y))` 7806 if (e.allowCommaExp) 7807 { 7808 CommaExp.allow(e.e1); 7809 CommaExp.allow(e.e2); 7810 } 7811 7812 if (Expression ex = binSemanticProp(e, sc)) 7813 { 7814 result = ex; 7815 return; 7816 } 7817 e.e1 = e.e1.addDtorHook(sc); 7818 7819 if (checkNonAssignmentArrayOp(e.e1)) 7820 return setError(); 7821 7822 e.type = e.e2.type; 7823 if (e.type is Type.tvoid) 7824 discardValue(e.e1); 7825 else if (!e.allowCommaExp && !e.isGenerated) 7826 e.error("Using the result of a comma expression is not allowed"); 7827 result = e; 7828 } 7829 7830 override void visit(IntervalExp e) 7831 { 7832 static if (LOGSEMANTIC) 7833 { 7834 printf("IntervalExp::semantic('%s')\n", e.toChars()); 7835 } 7836 if (e.type) 7837 { 7838 result = e; 7839 return; 7840 } 7841 7842 Expression le = e.lwr; 7843 le = le.expressionSemantic(sc); 7844 le = resolveProperties(sc, le); 7845 7846 Expression ue = e.upr; 7847 ue = ue.expressionSemantic(sc); 7848 ue = resolveProperties(sc, ue); 7849 7850 if (le.op == TOK.error) 7851 { 7852 result = le; 7853 return; 7854 } 7855 if (ue.op == TOK.error) 7856 { 7857 result = ue; 7858 return; 7859 } 7860 7861 e.lwr = le; 7862 e.upr = ue; 7863 7864 e.type = Type.tvoid; 7865 result = e; 7866 } 7867 7868 override void visit(DelegatePtrExp e) 7869 { 7870 static if (LOGSEMANTIC) 7871 { 7872 printf("DelegatePtrExp::semantic('%s')\n", e.toChars()); 7873 } 7874 if (!e.type) 7875 { 7876 unaSemantic(e, sc); 7877 e.e1 = resolveProperties(sc, e.e1); 7878 7879 if (e.e1.op == TOK.error) 7880 { 7881 result = e.e1; 7882 return; 7883 } 7884 e.type = Type.tvoidptr; 7885 } 7886 result = e; 7887 } 7888 7889 override void visit(DelegateFuncptrExp e) 7890 { 7891 static if (LOGSEMANTIC) 7892 { 7893 printf("DelegateFuncptrExp::semantic('%s')\n", e.toChars()); 7894 } 7895 if (!e.type) 7896 { 7897 unaSemantic(e, sc); 7898 e.e1 = resolveProperties(sc, e.e1); 7899 if (e.e1.op == TOK.error) 7900 { 7901 result = e.e1; 7902 return; 7903 } 7904 e.type = e.e1.type.nextOf().pointerTo(); 7905 } 7906 result = e; 7907 } 7908 7909 override void visit(IndexExp exp) 7910 { 7911 static if (LOGSEMANTIC) 7912 { 7913 printf("IndexExp::semantic('%s')\n", exp.toChars()); 7914 } 7915 if (exp.type) 7916 { 7917 result = exp; 7918 return; 7919 } 7920 7921 // operator overloading should be handled in ArrayExp already. 7922 if (!exp.e1.type) 7923 exp.e1 = exp.e1.expressionSemantic(sc); 7924 assert(exp.e1.type); // semantic() should already be run on it 7925 if (exp.e1.op == TOK.type && exp.e1.type.ty != Ttuple) 7926 { 7927 exp.e2 = exp.e2.expressionSemantic(sc); 7928 exp.e2 = resolveProperties(sc, exp.e2); 7929 Type nt; 7930 if (exp.e2.op == TOK.type) 7931 nt = new TypeAArray(exp.e1.type, exp.e2.type); 7932 else 7933 nt = new TypeSArray(exp.e1.type, exp.e2); 7934 Expression e = new TypeExp(exp.loc, nt); 7935 result = e.expressionSemantic(sc); 7936 return; 7937 } 7938 if (exp.e1.op == TOK.error) 7939 { 7940 result = exp.e1; 7941 return; 7942 } 7943 if (exp.e1.type.ty == Terror) 7944 return setError(); 7945 7946 // Note that unlike C we do not implement the int[ptr] 7947 7948 Type t1b = exp.e1.type.toBasetype(); 7949 7950 if (t1b.ty == Tvector) 7951 { 7952 // Convert e1 to corresponding static array 7953 TypeVector tv1 = cast(TypeVector)t1b; 7954 t1b = tv1.basetype; 7955 t1b = t1b.castMod(tv1.mod); 7956 exp.e1.type = t1b; 7957 } 7958 7959 /* Run semantic on e2 7960 */ 7961 Scope* scx = sc; 7962 if (t1b.ty == Tsarray || t1b.ty == Tarray || t1b.ty == Ttuple) 7963 { 7964 // Create scope for 'length' variable 7965 ScopeDsymbol sym = new ArrayScopeSymbol(sc, exp); 7966 sym.parent = sc.scopesym; 7967 sc = sc.push(sym); 7968 } 7969 if (t1b.ty == Ttuple) 7970 sc = sc.startCTFE(); 7971 exp.e2 = exp.e2.expressionSemantic(sc); 7972 exp.e2 = resolveProperties(sc, exp.e2); 7973 if (t1b.ty == Ttuple) 7974 sc = sc.endCTFE(); 7975 if (exp.e2.op == TOK.tuple) 7976 { 7977 TupleExp te = cast(TupleExp)exp.e2; 7978 if (te.exps && te.exps.dim == 1) 7979 exp.e2 = Expression.combine(te.e0, (*te.exps)[0]); // bug 4444 fix 7980 } 7981 if (sc != scx) 7982 sc = sc.pop(); 7983 if (exp.e2.type == Type.terror) 7984 return setError(); 7985 7986 if (checkNonAssignmentArrayOp(exp.e1)) 7987 return setError(); 7988 7989 switch (t1b.ty) 7990 { 7991 case Tpointer: 7992 if ((cast(TypePointer)t1b).next.ty == Tfunction) 7993 { 7994 exp.error("cannot index function pointer `%s`", exp.e1.toChars()); 7995 return setError(); 7996 } 7997 exp.e2 = exp.e2.implicitCastTo(sc, Type.tsize_t); 7998 if (exp.e2.type == Type.terror) 7999 return setError(); 8000 exp.e2 = exp.e2.optimize(WANTvalue); 8001 if (exp.e2.op == TOK.int64 && exp.e2.toInteger() == 0) 8002 { 8003 } 8004 else if (sc.func && !(sc.flags & SCOPE.debug_) && sc.func.setUnsafe()) 8005 { 8006 exp.error("safe function `%s` cannot index pointer `%s`", sc.func.toPrettyChars(), exp.e1.toChars()); 8007 return setError(); 8008 } 8009 exp.type = (cast(TypeNext)t1b).next; 8010 break; 8011 8012 case Tarray: 8013 exp.e2 = exp.e2.implicitCastTo(sc, Type.tsize_t); 8014 if (exp.e2.type == Type.terror) 8015 return setError(); 8016 exp.type = (cast(TypeNext)t1b).next; 8017 break; 8018 8019 case Tsarray: 8020 { 8021 exp.e2 = exp.e2.implicitCastTo(sc, Type.tsize_t); 8022 if (exp.e2.type == Type.terror) 8023 return setError(); 8024 exp.type = t1b.nextOf(); 8025 break; 8026 } 8027 case Taarray: 8028 { 8029 TypeAArray taa = cast(TypeAArray)t1b; 8030 /* We can skip the implicit conversion if they differ only by 8031 * constness 8032 * https://issues.dlang.org/show_bug.cgi?id=2684 8033 * see also bug https://issues.dlang.org/show_bug.cgi?id=2954 b 8034 */ 8035 if (!arrayTypeCompatibleWithoutCasting(exp.e2.type, taa.index)) 8036 { 8037 exp.e2 = exp.e2.implicitCastTo(sc, taa.index); // type checking 8038 if (exp.e2.type == Type.terror) 8039 return setError(); 8040 } 8041 8042 semanticTypeInfo(sc, taa); 8043 8044 exp.type = taa.next; 8045 break; 8046 } 8047 case Ttuple: 8048 { 8049 exp.e2 = exp.e2.implicitCastTo(sc, Type.tsize_t); 8050 if (exp.e2.type == Type.terror) 8051 return setError(); 8052 8053 exp.e2 = exp.e2.ctfeInterpret(); 8054 uinteger_t index = exp.e2.toUInteger(); 8055 8056 TupleExp te; 8057 TypeTuple tup; 8058 size_t length; 8059 if (exp.e1.op == TOK.tuple) 8060 { 8061 te = cast(TupleExp)exp.e1; 8062 tup = null; 8063 length = te.exps.dim; 8064 } 8065 else if (exp.e1.op == TOK.type) 8066 { 8067 te = null; 8068 tup = cast(TypeTuple)t1b; 8069 length = Parameter.dim(tup.arguments); 8070 } 8071 else 8072 assert(0); 8073 8074 if (length <= index) 8075 { 8076 exp.error("array index `[%llu]` is outside array bounds `[0 .. %llu]`", index, cast(ulong)length); 8077 return setError(); 8078 } 8079 Expression e; 8080 if (exp.e1.op == TOK.tuple) 8081 { 8082 e = (*te.exps)[cast(size_t)index]; 8083 e = Expression.combine(te.e0, e); 8084 } 8085 else 8086 e = new TypeExp(exp.e1.loc, Parameter.getNth(tup.arguments, cast(size_t)index).type); 8087 result = e; 8088 return; 8089 } 8090 default: 8091 exp.error("`%s` must be an array or pointer type, not `%s`", exp.e1.toChars(), exp.e1.type.toChars()); 8092 return setError(); 8093 } 8094 8095 // We might know $ now 8096 setLengthVarIfKnown(exp.lengthVar, t1b); 8097 8098 if (t1b.ty == Tsarray || t1b.ty == Tarray) 8099 { 8100 Expression el = new ArrayLengthExp(exp.loc, exp.e1); 8101 el = el.expressionSemantic(sc); 8102 el = el.optimize(WANTvalue); 8103 if (el.op == TOK.int64) 8104 { 8105 exp.e2 = exp.e2.optimize(WANTvalue); 8106 dinteger_t length = el.toInteger(); 8107 if (length) 8108 { 8109 auto bounds = IntRange(SignExtendedNumber(0), SignExtendedNumber(length - 1)); 8110 exp.indexIsInBounds = bounds.contains(getIntRange(exp.e2)); 8111 } 8112 } 8113 } 8114 8115 result = exp; 8116 } 8117 8118 override void visit(PostExp exp) 8119 { 8120 static if (LOGSEMANTIC) 8121 { 8122 printf("PostExp::semantic('%s')\n", exp.toChars()); 8123 } 8124 if (exp.type) 8125 { 8126 result = exp; 8127 return; 8128 } 8129 8130 if (Expression ex = binSemantic(exp, sc)) 8131 { 8132 result = ex; 8133 return; 8134 } 8135 Expression e1x = resolveProperties(sc, exp.e1); 8136 if (e1x.op == TOK.error) 8137 { 8138 result = e1x; 8139 return; 8140 } 8141 exp.e1 = e1x; 8142 8143 Expression e = exp.op_overload(sc); 8144 if (e) 8145 { 8146 result = e; 8147 return; 8148 } 8149 8150 if (exp.e1.checkReadModifyWrite(exp.op)) 8151 return setError(); 8152 8153 if (exp.e1.op == TOK.slice) 8154 { 8155 const(char)* s = exp.op == TOK.plusPlus ? "increment" : "decrement"; 8156 exp.error("cannot post-%s array slice `%s`, use pre-%s instead", s, exp.e1.toChars(), s); 8157 return setError(); 8158 } 8159 8160 exp.e1 = exp.e1.optimize(WANTvalue); 8161 8162 Type t1 = exp.e1.type.toBasetype(); 8163 if (t1.ty == Tclass || t1.ty == Tstruct || exp.e1.op == TOK.arrayLength) 8164 { 8165 /* Check for operator overloading, 8166 * but rewrite in terms of ++e instead of e++ 8167 */ 8168 8169 /* If e1 is not trivial, take a reference to it 8170 */ 8171 Expression de = null; 8172 if (exp.e1.op != TOK.variable && exp.e1.op != TOK.arrayLength) 8173 { 8174 // ref v = e1; 8175 auto v = copyToTemp(STC.ref_, "__postref", exp.e1); 8176 de = new DeclarationExp(exp.loc, v); 8177 exp.e1 = new VarExp(exp.e1.loc, v); 8178 } 8179 8180 /* Rewrite as: 8181 * auto tmp = e1; ++e1; tmp 8182 */ 8183 auto tmp = copyToTemp(0, "__pitmp", exp.e1); 8184 Expression ea = new DeclarationExp(exp.loc, tmp); 8185 8186 Expression eb = exp.e1.syntaxCopy(); 8187 eb = new PreExp(exp.op == TOK.plusPlus ? TOK.prePlusPlus : TOK.preMinusMinus, exp.loc, eb); 8188 8189 Expression ec = new VarExp(exp.loc, tmp); 8190 8191 // Combine de,ea,eb,ec 8192 if (de) 8193 ea = new CommaExp(exp.loc, de, ea); 8194 e = new CommaExp(exp.loc, ea, eb); 8195 e = new CommaExp(exp.loc, e, ec); 8196 e = e.expressionSemantic(sc); 8197 result = e; 8198 return; 8199 } 8200 8201 exp.e1 = exp.e1.modifiableLvalue(sc, exp.e1); 8202 8203 e = exp; 8204 if (exp.e1.checkScalar() || 8205 exp.e1.checkSharedAccess(sc)) 8206 return setError(); 8207 if (exp.e1.checkNoBool()) 8208 return setError(); 8209 8210 if (exp.e1.type.ty == Tpointer) 8211 e = scaleFactor(exp, sc); 8212 else 8213 exp.e2 = exp.e2.castTo(sc, exp.e1.type); 8214 e.type = exp.e1.type; 8215 result = e; 8216 } 8217 8218 override void visit(PreExp exp) 8219 { 8220 Expression e = exp.op_overload(sc); 8221 // printf("PreExp::semantic('%s')\n", toChars()); 8222 if (e) 8223 { 8224 result = e; 8225 return; 8226 } 8227 8228 // Rewrite as e1+=1 or e1-=1 8229 if (exp.op == TOK.prePlusPlus) 8230 e = new AddAssignExp(exp.loc, exp.e1, IntegerExp.literal!1); 8231 else 8232 e = new MinAssignExp(exp.loc, exp.e1, IntegerExp.literal!1); 8233 result = e.expressionSemantic(sc); 8234 } 8235 8236 /* 8237 * Get the expression initializer for a specific struct 8238 * 8239 * Params: 8240 * sd = the struct for which the expression initializer is needed 8241 * loc = the location of the initializer 8242 * sc = the scope where the expression is located 8243 * t = the type of the expression 8244 * 8245 * Returns: 8246 * The expression initializer or error expression if any errors occured 8247 */ 8248 private Expression getInitExp(StructDeclaration sd, Loc loc, Scope* sc, Type t) 8249 { 8250 if (sd.zeroInit && !sd.isNested()) 8251 { 8252 // https://issues.dlang.org/show_bug.cgi?id=14606 8253 // Always use BlitExp for the special expression: (struct = 0) 8254 return IntegerExp.literal!0; 8255 } 8256 8257 if (sd.isNested()) 8258 { 8259 auto sle = new StructLiteralExp(loc, sd, null, t); 8260 if (!sd.fill(loc, sle.elements, true)) 8261 return ErrorExp.get(); 8262 if (checkFrameAccess(loc, sc, sd, sle.elements.dim)) 8263 return ErrorExp.get(); 8264 8265 sle.type = t; 8266 return sle; 8267 } 8268 8269 return t.defaultInit(loc); 8270 } 8271 8272 override void visit(AssignExp exp) 8273 { 8274 static if (LOGSEMANTIC) 8275 { 8276 printf("AssignExp::semantic('%s')\n", exp.toChars()); 8277 } 8278 //printf("exp.e1.op = %d, '%s'\n", exp.e1.op, Token.toChars(exp.e1.op)); 8279 //printf("exp.e2.op = %d, '%s'\n", exp.e2.op, Token.toChars(exp.e2.op)); 8280 8281 void setResult(Expression e, int line = __LINE__) 8282 { 8283 //printf("line %d\n", line); 8284 result = e; 8285 } 8286 8287 if (exp.type) 8288 { 8289 return setResult(exp); 8290 } 8291 8292 Expression e1old = exp.e1; 8293 8294 if (auto e2comma = exp.e2.isCommaExp()) 8295 { 8296 if (!e2comma.isGenerated) 8297 exp.error("Using the result of a comma expression is not allowed"); 8298 8299 /* Rewrite to get rid of the comma from rvalue 8300 * e1=(e0,e2) => e0,(e1=e2) 8301 */ 8302 Expression e0; 8303 exp.e2 = Expression.extractLast(e2comma, e0); 8304 Expression e = Expression.combine(e0, exp); 8305 return setResult(e.expressionSemantic(sc)); 8306 } 8307 8308 /* Look for operator overloading of a[arguments] = e2. 8309 * Do it before e1.expressionSemantic() otherwise the ArrayExp will have been 8310 * converted to unary operator overloading already. 8311 */ 8312 if (auto ae = exp.e1.isArrayExp()) 8313 { 8314 Expression res; 8315 8316 ae.e1 = ae.e1.expressionSemantic(sc); 8317 ae.e1 = resolveProperties(sc, ae.e1); 8318 Expression ae1old = ae.e1; 8319 8320 const(bool) maybeSlice = 8321 (ae.arguments.dim == 0 || 8322 ae.arguments.dim == 1 && (*ae.arguments)[0].op == TOK.interval); 8323 8324 IntervalExp ie = null; 8325 if (maybeSlice && ae.arguments.dim) 8326 { 8327 assert((*ae.arguments)[0].op == TOK.interval); 8328 ie = cast(IntervalExp)(*ae.arguments)[0]; 8329 } 8330 while (true) 8331 { 8332 if (ae.e1.op == TOK.error) 8333 return setResult(ae.e1); 8334 8335 Expression e0 = null; 8336 Expression ae1save = ae.e1; 8337 ae.lengthVar = null; 8338 8339 Type t1b = ae.e1.type.toBasetype(); 8340 AggregateDeclaration ad = isAggregate(t1b); 8341 if (!ad) 8342 break; 8343 if (search_function(ad, Id.indexass)) 8344 { 8345 // Deal with $ 8346 res = resolveOpDollar(sc, ae, &e0); 8347 if (!res) // a[i..j] = e2 might be: a.opSliceAssign(e2, i, j) 8348 goto Lfallback; 8349 if (res.op == TOK.error) 8350 return setResult(res); 8351 8352 res = exp.e2.expressionSemantic(sc); 8353 if (res.op == TOK.error) 8354 return setResult(res); 8355 exp.e2 = res; 8356 8357 /* Rewrite (a[arguments] = e2) as: 8358 * a.opIndexAssign(e2, arguments) 8359 */ 8360 Expressions* a = ae.arguments.copy(); 8361 a.insert(0, exp.e2); 8362 res = new DotIdExp(exp.loc, ae.e1, Id.indexass); 8363 res = new CallExp(exp.loc, res, a); 8364 if (maybeSlice) // a[] = e2 might be: a.opSliceAssign(e2) 8365 res = res.trySemantic(sc); 8366 else 8367 res = res.expressionSemantic(sc); 8368 if (res) 8369 return setResult(Expression.combine(e0, res)); 8370 } 8371 8372 Lfallback: 8373 if (maybeSlice && search_function(ad, Id.sliceass)) 8374 { 8375 // Deal with $ 8376 res = resolveOpDollar(sc, ae, ie, &e0); 8377 if (res.op == TOK.error) 8378 return setResult(res); 8379 8380 res = exp.e2.expressionSemantic(sc); 8381 if (res.op == TOK.error) 8382 return setResult(res); 8383 8384 exp.e2 = res; 8385 8386 /* Rewrite (a[i..j] = e2) as: 8387 * a.opSliceAssign(e2, i, j) 8388 */ 8389 auto a = new Expressions(); 8390 a.push(exp.e2); 8391 if (ie) 8392 { 8393 a.push(ie.lwr); 8394 a.push(ie.upr); 8395 } 8396 res = new DotIdExp(exp.loc, ae.e1, Id.sliceass); 8397 res = new CallExp(exp.loc, res, a); 8398 res = res.expressionSemantic(sc); 8399 return setResult(Expression.combine(e0, res)); 8400 } 8401 8402 // No operator overloading member function found yet, but 8403 // there might be an alias this to try. 8404 if (ad.aliasthis && t1b != ae.att1) 8405 { 8406 if (!ae.att1 && t1b.checkAliasThisRec()) 8407 ae.att1 = t1b; 8408 8409 /* Rewrite (a[arguments] op e2) as: 8410 * a.aliasthis[arguments] op e2 8411 */ 8412 ae.e1 = resolveAliasThis(sc, ae1save, true); 8413 if (ae.e1) 8414 continue; 8415 } 8416 break; 8417 } 8418 ae.e1 = ae1old; // recovery 8419 ae.lengthVar = null; 8420 } 8421 8422 /* Run this.e1 semantic. 8423 */ 8424 { 8425 Expression e1x = exp.e1; 8426 8427 /* With UFCS, e.f = value 8428 * Could mean: 8429 * .f(e, value) 8430 * or: 8431 * .f(e) = value 8432 */ 8433 if (auto dti = e1x.isDotTemplateInstanceExp()) 8434 { 8435 Expression e = dti.semanticY(sc, 1); 8436 if (!e) 8437 { 8438 return setResult(resolveUFCSProperties(sc, e1x, exp.e2)); 8439 } 8440 8441 e1x = e; 8442 } 8443 else if (auto die = e1x.isDotIdExp()) 8444 { 8445 Expression e = die.semanticY(sc, 1); 8446 if (e && isDotOpDispatch(e)) 8447 { 8448 /* https://issues.dlang.org/show_bug.cgi?id=19687 8449 * 8450 * On this branch, e2 is semantically analyzed in resolvePropertiesX, 8451 * but that call is done with gagged errors. That is the only time when 8452 * semantic gets ran on e2, that is why the error never gets to be printed. 8453 * In order to make sure that UFCS is tried with correct parameters, e2 8454 * needs to have semantic ran on it. 8455 */ 8456 exp.e2 = exp.e2.expressionSemantic(sc); 8457 uint errors = global.startGagging(); 8458 e = resolvePropertiesX(sc, e, exp.e2); 8459 if (global.endGagging(errors)) 8460 e = null; /* fall down to UFCS */ 8461 else 8462 return setResult(e); 8463 } 8464 if (!e) 8465 return setResult(resolveUFCSProperties(sc, e1x, exp.e2)); 8466 e1x = e; 8467 } 8468 else 8469 { 8470 if (auto se = e1x.isSliceExp()) 8471 se.arrayop = true; 8472 8473 e1x = e1x.expressionSemantic(sc); 8474 } 8475 8476 /* We have f = value. 8477 * Could mean: 8478 * f(value) 8479 * or: 8480 * f() = value 8481 */ 8482 if (Expression e = resolvePropertiesX(sc, e1x, exp.e2)) 8483 return setResult(e); 8484 8485 if (e1x.checkRightThis(sc)) 8486 { 8487 return setError(); 8488 } 8489 exp.e1 = e1x; 8490 assert(exp.e1.type); 8491 } 8492 Type t1 = exp.e1.type.toBasetype(); 8493 8494 /* Run this.e2 semantic. 8495 * Different from other binary expressions, the analysis of e2 8496 * depends on the result of e1 in assignments. 8497 */ 8498 { 8499 Expression e2x = inferType(exp.e2, t1.baseElemOf()); 8500 e2x = e2x.expressionSemantic(sc); 8501 e2x = resolveProperties(sc, e2x); 8502 if (e2x.op == TOK.type) 8503 e2x = resolveAliasThis(sc, e2x); //https://issues.dlang.org/show_bug.cgi?id=17684 8504 if (e2x.op == TOK.error) 8505 return setResult(e2x); 8506 if (e2x.checkValue() || e2x.checkSharedAccess(sc)) 8507 return setError(); 8508 exp.e2 = e2x; 8509 } 8510 8511 /* Rewrite tuple assignment as a tuple of assignments. 8512 */ 8513 { 8514 Expression e2x = exp.e2; 8515 8516 Ltupleassign: 8517 if (exp.e1.op == TOK.tuple && e2x.op == TOK.tuple) 8518 { 8519 TupleExp tup1 = cast(TupleExp)exp.e1; 8520 TupleExp tup2 = cast(TupleExp)e2x; 8521 size_t dim = tup1.exps.dim; 8522 Expression e = null; 8523 if (dim != tup2.exps.dim) 8524 { 8525 exp.error("mismatched tuple lengths, %d and %d", cast(int)dim, cast(int)tup2.exps.dim); 8526 return setError(); 8527 } 8528 if (dim == 0) 8529 { 8530 e = IntegerExp.literal!0; 8531 e = new CastExp(exp.loc, e, Type.tvoid); // avoid "has no effect" error 8532 e = Expression.combine(tup1.e0, tup2.e0, e); 8533 } 8534 else 8535 { 8536 auto exps = new Expressions(dim); 8537 for (size_t i = 0; i < dim; i++) 8538 { 8539 Expression ex1 = (*tup1.exps)[i]; 8540 Expression ex2 = (*tup2.exps)[i]; 8541 (*exps)[i] = new AssignExp(exp.loc, ex1, ex2); 8542 } 8543 e = new TupleExp(exp.loc, Expression.combine(tup1.e0, tup2.e0), exps); 8544 } 8545 return setResult(e.expressionSemantic(sc)); 8546 } 8547 8548 /* Look for form: e1 = e2.aliasthis. 8549 */ 8550 if (exp.e1.op == TOK.tuple) 8551 { 8552 TupleDeclaration td = isAliasThisTuple(e2x); 8553 if (!td) 8554 goto Lnomatch; 8555 8556 assert(exp.e1.type.ty == Ttuple); 8557 TypeTuple tt = cast(TypeTuple)exp.e1.type; 8558 8559 Expression e0; 8560 Expression ev = extractSideEffect(sc, "__tup", e0, e2x); 8561 8562 auto iexps = new Expressions(); 8563 iexps.push(ev); 8564 for (size_t u = 0; u < iexps.dim; u++) 8565 { 8566 Lexpand: 8567 Expression e = (*iexps)[u]; 8568 8569 Parameter arg = Parameter.getNth(tt.arguments, u); 8570 //printf("[%d] iexps.dim = %d, ", u, iexps.dim); 8571 //printf("e = (%s %s, %s), ", Token::tochars[e.op], e.toChars(), e.type.toChars()); 8572 //printf("arg = (%s, %s)\n", arg.toChars(), arg.type.toChars()); 8573 8574 if (!arg || !e.type.implicitConvTo(arg.type)) 8575 { 8576 // expand initializer to tuple 8577 if (expandAliasThisTuples(iexps, u) != -1) 8578 { 8579 if (iexps.dim <= u) 8580 break; 8581 goto Lexpand; 8582 } 8583 goto Lnomatch; 8584 } 8585 } 8586 e2x = new TupleExp(e2x.loc, e0, iexps); 8587 e2x = e2x.expressionSemantic(sc); 8588 if (e2x.op == TOK.error) 8589 { 8590 result = e2x; 8591 return; 8592 } 8593 // Do not need to overwrite this.e2 8594 goto Ltupleassign; 8595 } 8596 Lnomatch: 8597 } 8598 8599 if (exp.op == TOK.assign) // skip TOK.blit and TOK.construct, which are initializations 8600 exp.e1.checkSharedAccess(sc); 8601 8602 /* Inside constructor, if this is the first assignment of object field, 8603 * rewrite this to initializing the field. 8604 */ 8605 if (exp.op == TOK.assign 8606 && exp.e1.checkModifiable(sc) == Modifiable.initialization) 8607 { 8608 //printf("[%s] change to init - %s\n", exp.loc.toChars(), exp.toChars()); 8609 auto t = exp.type; 8610 exp = new ConstructExp(exp.loc, exp.e1, exp.e2); 8611 exp.type = t; 8612 8613 // @@@DEPRECATED_2020-06@@@ 8614 // When removing, alter `checkModifiable` to return the correct value. 8615 if (sc.func.isStaticCtorDeclaration() && !sc.func.isSharedStaticCtorDeclaration() && 8616 exp.e1.type.isImmutable()) 8617 { 8618 deprecation(exp.loc, "initialization of `immutable` variable from `static this` is deprecated."); 8619 deprecationSupplemental(exp.loc, "Use `shared static this` instead."); 8620 } 8621 8622 // https://issues.dlang.org/show_bug.cgi?id=13515 8623 // set Index::modifiable flag for complex AA element initialization 8624 if (auto ie1 = exp.e1.isIndexExp()) 8625 { 8626 Expression e1x = ie1.markSettingAAElem(); 8627 if (e1x.op == TOK.error) 8628 { 8629 result = e1x; 8630 return; 8631 } 8632 } 8633 } 8634 else if (exp.op == TOK.construct && exp.e1.op == TOK.variable && 8635 (cast(VarExp)exp.e1).var.storage_class & (STC.out_ | STC.ref_)) 8636 { 8637 exp.memset = MemorySet.referenceInit; 8638 } 8639 8640 /* If it is an assignment from a 'foreign' type, 8641 * check for operator overloading. 8642 */ 8643 if (exp.memset == MemorySet.referenceInit) 8644 { 8645 // If this is an initialization of a reference, 8646 // do nothing 8647 } 8648 else if (t1.ty == Tstruct) 8649 { 8650 auto e1x = exp.e1; 8651 auto e2x = exp.e2; 8652 auto sd = (cast(TypeStruct)t1).sym; 8653 8654 if (exp.op == TOK.construct) 8655 { 8656 Type t2 = e2x.type.toBasetype(); 8657 if (t2.ty == Tstruct && sd == (cast(TypeStruct)t2).sym) 8658 { 8659 sd.size(exp.loc); 8660 if (sd.sizeok != Sizeok.done) 8661 return setError(); 8662 if (!sd.ctor) 8663 sd.ctor = sd.searchCtor(); 8664 8665 // https://issues.dlang.org/show_bug.cgi?id=15661 8666 // Look for the form from last of comma chain. 8667 auto e2y = lastComma(e2x); 8668 8669 CallExp ce = (e2y.op == TOK.call) ? cast(CallExp)e2y : null; 8670 DotVarExp dve = (ce && ce.e1.op == TOK.dotVariable) 8671 ? cast(DotVarExp)ce.e1 : null; 8672 if (sd.ctor && ce && dve && dve.var.isCtorDeclaration() && 8673 // https://issues.dlang.org/show_bug.cgi?id=19389 8674 dve.e1.op != TOK.dotVariable && 8675 e2y.type.implicitConvTo(t1)) 8676 { 8677 /* Look for form of constructor call which is: 8678 * __ctmp.ctor(arguments...) 8679 */ 8680 8681 /* Before calling the constructor, initialize 8682 * variable with a bit copy of the default 8683 * initializer 8684 */ 8685 Expression einit = getInitExp(sd, exp.loc, sc, t1); 8686 if (einit.op == TOK.error) 8687 { 8688 result = einit; 8689 return; 8690 } 8691 8692 auto ae = new BlitExp(exp.loc, exp.e1, einit); 8693 ae.type = e1x.type; 8694 8695 /* Replace __ctmp being constructed with e1. 8696 * We need to copy constructor call expression, 8697 * because it may be used in other place. 8698 */ 8699 auto dvx = cast(DotVarExp)dve.copy(); 8700 dvx.e1 = e1x; 8701 auto cx = cast(CallExp)ce.copy(); 8702 cx.e1 = dvx; 8703 if (checkConstructorEscape(sc, cx, false)) 8704 return setError(); 8705 8706 Expression e0; 8707 Expression.extractLast(e2x, e0); 8708 8709 auto e = Expression.combine(e0, ae, cx); 8710 e = e.expressionSemantic(sc); 8711 result = e; 8712 return; 8713 } 8714 if (sd.postblit || sd.hasCopyCtor) 8715 { 8716 /* We have a copy constructor for this 8717 */ 8718 if (e2x.op == TOK.question) 8719 { 8720 /* Rewrite as: 8721 * a ? e1 = b : e1 = c; 8722 */ 8723 CondExp econd = cast(CondExp)e2x; 8724 Expression ea1 = new ConstructExp(econd.e1.loc, e1x, econd.e1); 8725 Expression ea2 = new ConstructExp(econd.e1.loc, e1x, econd.e2); 8726 Expression e = new CondExp(exp.loc, econd.econd, ea1, ea2); 8727 result = e.expressionSemantic(sc); 8728 return; 8729 } 8730 8731 if (e2x.isLvalue()) 8732 { 8733 if (sd.hasCopyCtor) 8734 { 8735 /* Rewrite as: 8736 * e1 = init, e1.copyCtor(e2); 8737 */ 8738 Expression einit = new BlitExp(exp.loc, exp.e1, getInitExp(sd, exp.loc, sc, t1)); 8739 einit.type = e1x.type; 8740 8741 Expression e; 8742 e = new DotIdExp(exp.loc, e1x, Id.ctor); 8743 e = new CallExp(exp.loc, e, e2x); 8744 e = new CommaExp(exp.loc, einit, e); 8745 8746 //printf("e: %s\n", e.toChars()); 8747 8748 result = e.expressionSemantic(sc); 8749 return; 8750 } 8751 else 8752 { 8753 if (!e2x.type.implicitConvTo(e1x.type)) 8754 { 8755 exp.error("conversion error from `%s` to `%s`", 8756 e2x.type.toChars(), e1x.type.toChars()); 8757 return setError(); 8758 } 8759 8760 /* Rewrite as: 8761 * (e1 = e2).postblit(); 8762 * 8763 * Blit assignment e1 = e2 returns a reference to the original e1, 8764 * then call the postblit on it. 8765 */ 8766 Expression e = e1x.copy(); 8767 e.type = e.type.mutableOf(); 8768 if (e.type.isShared && !sd.type.isShared) 8769 e.type = e.type.unSharedOf(); 8770 e = new BlitExp(exp.loc, e, e2x); 8771 e = new DotVarExp(exp.loc, e, sd.postblit, false); 8772 e = new CallExp(exp.loc, e); 8773 result = e.expressionSemantic(sc); 8774 return; 8775 } 8776 } 8777 else 8778 { 8779 /* The struct value returned from the function is transferred 8780 * so should not call the destructor on it. 8781 */ 8782 e2x = valueNoDtor(e2x); 8783 } 8784 } 8785 8786 // https://issues.dlang.org/show_bug.cgi?id=19251 8787 // if e2 cannot be converted to e1.type, maybe there is an alias this 8788 if (!e2x.implicitConvTo(t1)) 8789 { 8790 AggregateDeclaration ad2 = isAggregate(e2x.type); 8791 if (ad2 && ad2.aliasthis && !(exp.att2 && e2x.type == exp.att2)) 8792 { 8793 if (!exp.att2 && exp.e2.type.checkAliasThisRec()) 8794 exp.att2 = exp.e2.type; 8795 /* Rewrite (e1 op e2) as: 8796 * (e1 op e2.aliasthis) 8797 */ 8798 exp.e2 = new DotIdExp(exp.e2.loc, exp.e2, ad2.aliasthis.ident); 8799 result = exp.expressionSemantic(sc); 8800 return; 8801 } 8802 } 8803 } 8804 else if (!e2x.implicitConvTo(t1)) 8805 { 8806 sd.size(exp.loc); 8807 if (sd.sizeok != Sizeok.done) 8808 return setError(); 8809 if (!sd.ctor) 8810 sd.ctor = sd.searchCtor(); 8811 8812 if (sd.ctor) 8813 { 8814 /* Look for implicit constructor call 8815 * Rewrite as: 8816 * e1 = init, e1.ctor(e2) 8817 */ 8818 8819 /* Fix Issue 5153 : https://issues.dlang.org/show_bug.cgi?id=5153 8820 * Using `new` to initialize a struct object is a common mistake, but 8821 * the error message from the compiler is not very helpful in that 8822 * case. If exp.e2 is a NewExp and the type of new is the same as 8823 * the type as exp.e1 (struct in this case), then we know for sure 8824 * that the user wants to instantiate a struct. This is done to avoid 8825 * issuing an error when the user actually wants to call a constructor 8826 * which receives a class object. 8827 * 8828 * Foo f = new Foo2(0); is a valid expression if Foo has a constructor 8829 * which receives an instance of a Foo2 class 8830 */ 8831 if (exp.e2.op == TOK.new_) 8832 { 8833 auto newExp = cast(NewExp)(exp.e2); 8834 if (newExp.newtype && newExp.newtype == t1) 8835 { 8836 error(exp.loc, "cannot implicitly convert expression `%s` of type `%s` to `%s`", 8837 newExp.toChars(), newExp.type.toChars(), t1.toChars()); 8838 errorSupplemental(exp.loc, "Perhaps remove the `new` keyword?"); 8839 return setError(); 8840 } 8841 } 8842 8843 Expression einit = new BlitExp(exp.loc, e1x, getInitExp(sd, exp.loc, sc, t1)); 8844 einit.type = e1x.type; 8845 8846 Expression e; 8847 e = new DotIdExp(exp.loc, e1x, Id.ctor); 8848 e = new CallExp(exp.loc, e, e2x); 8849 e = new CommaExp(exp.loc, einit, e); 8850 e = e.expressionSemantic(sc); 8851 result = e; 8852 return; 8853 } 8854 if (search_function(sd, Id.call)) 8855 { 8856 /* Look for static opCall 8857 * https://issues.dlang.org/show_bug.cgi?id=2702 8858 * Rewrite as: 8859 * e1 = typeof(e1).opCall(arguments) 8860 */ 8861 e2x = typeDotIdExp(e2x.loc, e1x.type, Id.call); 8862 e2x = new CallExp(exp.loc, e2x, exp.e2); 8863 8864 e2x = e2x.expressionSemantic(sc); 8865 e2x = resolveProperties(sc, e2x); 8866 if (e2x.op == TOK.error) 8867 { 8868 result = e2x; 8869 return; 8870 } 8871 if (e2x.checkValue() || e2x.checkSharedAccess(sc)) 8872 return setError(); 8873 } 8874 } 8875 else // https://issues.dlang.org/show_bug.cgi?id=11355 8876 { 8877 AggregateDeclaration ad2 = isAggregate(e2x.type); 8878 if (ad2 && ad2.aliasthis && !(exp.att2 && e2x.type == exp.att2)) 8879 { 8880 if (!exp.att2 && exp.e2.type.checkAliasThisRec()) 8881 exp.att2 = exp.e2.type; 8882 /* Rewrite (e1 op e2) as: 8883 * (e1 op e2.aliasthis) 8884 */ 8885 exp.e2 = new DotIdExp(exp.e2.loc, exp.e2, ad2.aliasthis.ident); 8886 result = exp.expressionSemantic(sc); 8887 return; 8888 } 8889 } 8890 } 8891 else if (exp.op == TOK.assign) 8892 { 8893 if (e1x.op == TOK.index && (cast(IndexExp)e1x).e1.type.toBasetype().ty == Taarray) 8894 { 8895 /* 8896 * Rewrite: 8897 * aa[key] = e2; 8898 * as: 8899 * ref __aatmp = aa; 8900 * ref __aakey = key; 8901 * ref __aaval = e2; 8902 * (__aakey in __aatmp 8903 * ? __aatmp[__aakey].opAssign(__aaval) 8904 * : ConstructExp(__aatmp[__aakey], __aaval)); 8905 */ 8906 // ensure we keep the expr modifiable 8907 Expression esetting = (cast(IndexExp)e1x).markSettingAAElem(); 8908 if (esetting.op == TOK.error) 8909 { 8910 result = esetting; 8911 return; 8912 } 8913 assert(esetting.op == TOK.index); 8914 IndexExp ie = cast(IndexExp) esetting; 8915 Type t2 = e2x.type.toBasetype(); 8916 8917 Expression e0 = null; 8918 Expression ea = extractSideEffect(sc, "__aatmp", e0, ie.e1); 8919 Expression ek = extractSideEffect(sc, "__aakey", e0, ie.e2); 8920 Expression ev = extractSideEffect(sc, "__aaval", e0, e2x); 8921 8922 AssignExp ae = cast(AssignExp)exp.copy(); 8923 ae.e1 = new IndexExp(exp.loc, ea, ek); 8924 ae.e1 = ae.e1.expressionSemantic(sc); 8925 ae.e1 = ae.e1.optimize(WANTvalue); 8926 ae.e2 = ev; 8927 Expression e = ae.op_overload(sc); 8928 if (e) 8929 { 8930 Expression ey = null; 8931 if (t2.ty == Tstruct && sd == t2.toDsymbol(sc)) 8932 { 8933 ey = ev; 8934 } 8935 else if (!ev.implicitConvTo(ie.type) && sd.ctor) 8936 { 8937 // Look for implicit constructor call 8938 // Rewrite as S().ctor(e2) 8939 ey = new StructLiteralExp(exp.loc, sd, null); 8940 ey = new DotIdExp(exp.loc, ey, Id.ctor); 8941 ey = new CallExp(exp.loc, ey, ev); 8942 ey = ey.trySemantic(sc); 8943 } 8944 if (ey) 8945 { 8946 Expression ex; 8947 ex = new IndexExp(exp.loc, ea, ek); 8948 ex = ex.expressionSemantic(sc); 8949 ex = ex.optimize(WANTvalue); 8950 ex = ex.modifiableLvalue(sc, ex); // allocate new slot 8951 8952 ey = new ConstructExp(exp.loc, ex, ey); 8953 ey = ey.expressionSemantic(sc); 8954 if (ey.op == TOK.error) 8955 { 8956 result = ey; 8957 return; 8958 } 8959 ex = e; 8960 8961 // https://issues.dlang.org/show_bug.cgi?id=14144 8962 // The whole expression should have the common type 8963 // of opAssign() return and assigned AA entry. 8964 // Even if there's no common type, expression should be typed as void. 8965 Type t = null; 8966 if (!typeMerge(sc, TOK.question, &t, &ex, &ey)) 8967 { 8968 ex = new CastExp(ex.loc, ex, Type.tvoid); 8969 ey = new CastExp(ey.loc, ey, Type.tvoid); 8970 } 8971 e = new CondExp(exp.loc, new InExp(exp.loc, ek, ea), ex, ey); 8972 } 8973 e = Expression.combine(e0, e); 8974 e = e.expressionSemantic(sc); 8975 result = e; 8976 return; 8977 } 8978 } 8979 else 8980 { 8981 Expression e = exp.op_overload(sc); 8982 if (e) 8983 { 8984 result = e; 8985 return; 8986 } 8987 } 8988 } 8989 else 8990 assert(exp.op == TOK.blit); 8991 8992 exp.e1 = e1x; 8993 exp.e2 = e2x; 8994 } 8995 else if (t1.ty == Tclass) 8996 { 8997 // Disallow assignment operator overloads for same type 8998 if (exp.op == TOK.assign && !exp.e2.implicitConvTo(exp.e1.type)) 8999 { 9000 Expression e = exp.op_overload(sc); 9001 if (e) 9002 { 9003 result = e; 9004 return; 9005 } 9006 } 9007 } 9008 else if (t1.ty == Tsarray) 9009 { 9010 // SliceExp cannot have static array type without context inference. 9011 assert(exp.e1.op != TOK.slice); 9012 Expression e1x = exp.e1; 9013 Expression e2x = exp.e2; 9014 9015 if (e2x.implicitConvTo(e1x.type)) 9016 { 9017 if (exp.op != TOK.blit && (e2x.op == TOK.slice && (cast(UnaExp)e2x).e1.isLvalue() || e2x.op == TOK.cast_ && (cast(UnaExp)e2x).e1.isLvalue() || e2x.op != TOK.slice && e2x.isLvalue())) 9018 { 9019 if (e1x.checkPostblit(sc, t1)) 9020 return setError(); 9021 } 9022 9023 // e2 matches to t1 because of the implicit length match, so 9024 if (isUnaArrayOp(e2x.op) || isBinArrayOp(e2x.op)) 9025 { 9026 // convert e1 to e1[] 9027 // e.g. e1[] = a[] + b[]; 9028 auto sle = new SliceExp(e1x.loc, e1x, null, null); 9029 sle.arrayop = true; 9030 e1x = sle.expressionSemantic(sc); 9031 } 9032 else 9033 { 9034 // convert e2 to t1 later 9035 // e.g. e1 = [1, 2, 3]; 9036 } 9037 } 9038 else 9039 { 9040 if (e2x.implicitConvTo(t1.nextOf().arrayOf()) > MATCH.nomatch) 9041 { 9042 uinteger_t dim1 = (cast(TypeSArray)t1).dim.toInteger(); 9043 uinteger_t dim2 = dim1; 9044 if (auto ale = e2x.isArrayLiteralExp()) 9045 { 9046 dim2 = ale.elements ? ale.elements.dim : 0; 9047 } 9048 else if (auto se = e2x.isSliceExp()) 9049 { 9050 Type tx = toStaticArrayType(se); 9051 if (tx) 9052 dim2 = (cast(TypeSArray)tx).dim.toInteger(); 9053 } 9054 if (dim1 != dim2) 9055 { 9056 exp.error("mismatched array lengths, %d and %d", cast(int)dim1, cast(int)dim2); 9057 return setError(); 9058 } 9059 } 9060 9061 // May be block or element-wise assignment, so 9062 // convert e1 to e1[] 9063 if (exp.op != TOK.assign) 9064 { 9065 // If multidimensional static array, treat as one large array 9066 // 9067 // Find the appropriate array type depending on the assignment, e.g. 9068 // int[3] = int => int[3] 9069 // int[3][2] = int => int[6] 9070 // int[3][2] = int[] => int[3][2] 9071 // int[3][2][4] + int => int[24] 9072 // int[3][2][4] + int[] => int[3][8] 9073 ulong dim = t1.isTypeSArray().dim.toUInteger(); 9074 auto type = t1.nextOf(); 9075 9076 for (TypeSArray tsa; (tsa = type.isTypeSArray()) !is null; ) 9077 { 9078 import core.checkedint : mulu; 9079 9080 // Accumulate skipped dimensions 9081 bool overflow = false; 9082 dim = mulu(dim, tsa.dim.toUInteger(), overflow); 9083 if (overflow || dim >= uint.max) 9084 { 9085 // dym exceeds maximum array size 9086 exp.error("static array `%s` size overflowed to %llu", 9087 e1x.type.toChars(), cast(ulong) dim); 9088 return setError(); 9089 } 9090 9091 // Move to the element type 9092 type = tsa.nextOf().toBasetype(); 9093 9094 // Rewrite ex1 as a static array if a matching type was found 9095 if (e2x.implicitConvTo(type) > MATCH.nomatch) 9096 { 9097 e1x.type = type.sarrayOf(dim); 9098 break; 9099 } 9100 } 9101 } 9102 auto sle = new SliceExp(e1x.loc, e1x, null, null); 9103 sle.arrayop = true; 9104 e1x = sle.expressionSemantic(sc); 9105 } 9106 if (e1x.op == TOK.error) 9107 return setResult(e1x); 9108 if (e2x.op == TOK.error) 9109 return setResult(e2x); 9110 9111 exp.e1 = e1x; 9112 exp.e2 = e2x; 9113 t1 = e1x.type.toBasetype(); 9114 } 9115 /* Check the mutability of e1. 9116 */ 9117 if (auto ale = exp.e1.isArrayLengthExp()) 9118 { 9119 // e1 is not an lvalue, but we let code generator handle it 9120 9121 auto ale1x = ale.e1.modifiableLvalue(sc, exp.e1); 9122 if (ale1x.op == TOK.error) 9123 return setResult(ale1x); 9124 ale.e1 = ale1x; 9125 9126 Type tn = ale.e1.type.toBasetype().nextOf(); 9127 checkDefCtor(ale.loc, tn); 9128 9129 Identifier hook = global.params.tracegc ? Id._d_arraysetlengthTTrace : Id._d_arraysetlengthT; 9130 if (!verifyHookExist(exp.loc, *sc, Id._d_arraysetlengthTImpl, "resizing arrays")) 9131 return setError(); 9132 9133 // Lower to object._d_arraysetlengthTImpl!(typeof(e1))._d_arraysetlengthT{,Trace}(e1, e2) 9134 Expression id = new IdentifierExp(ale.loc, Id.empty); 9135 id = new DotIdExp(ale.loc, id, Id.object); 9136 auto tiargs = new Objects(); 9137 tiargs.push(ale.e1.type); 9138 id = new DotTemplateInstanceExp(ale.loc, id, Id._d_arraysetlengthTImpl, tiargs); 9139 id = new DotIdExp(ale.loc, id, hook); 9140 id = id.expressionSemantic(sc); 9141 9142 auto arguments = new Expressions(); 9143 arguments.reserve(5); 9144 if (global.params.tracegc) 9145 { 9146 auto funcname = (sc.callsc && sc.callsc.func) ? sc.callsc.func.toPrettyChars() : sc.func.toPrettyChars(); 9147 arguments.push(new StringExp(exp.loc, exp.loc.filename.toDString())); 9148 arguments.push(new IntegerExp(exp.loc, exp.loc.linnum, Type.tint32)); 9149 arguments.push(new StringExp(exp.loc, funcname.toDString())); 9150 } 9151 arguments.push(ale.e1); 9152 arguments.push(exp.e2); 9153 9154 Expression ce = new CallExp(ale.loc, id, arguments); 9155 auto res = ce.expressionSemantic(sc); 9156 // if (global.params.verbose) 9157 // message("lowered %s =>\n %s", exp.toChars(), res.toChars()); 9158 return setResult(res); 9159 } 9160 else if (auto se = exp.e1.isSliceExp()) 9161 { 9162 Type tn = se.type.nextOf(); 9163 const fun = sc.func; 9164 if (exp.op == TOK.assign && !tn.isMutable() && 9165 // allow modifiation in module ctor, see 9166 // https://issues.dlang.org/show_bug.cgi?id=9884 9167 (!fun || (fun && !fun.isStaticCtorDeclaration()))) 9168 { 9169 exp.error("slice `%s` is not mutable", se.toChars()); 9170 return setError(); 9171 } 9172 9173 if (exp.op == TOK.assign && !tn.baseElemOf().isAssignable()) 9174 { 9175 exp.error("slice `%s` is not mutable, struct `%s` has immutable members", 9176 exp.e1.toChars(), tn.baseElemOf().toChars()); 9177 result = ErrorExp.get(); 9178 return; 9179 } 9180 9181 // For conditional operator, both branches need conversion. 9182 while (se.e1.op == TOK.slice) 9183 se = cast(SliceExp)se.e1; 9184 if (se.e1.op == TOK.question && se.e1.type.toBasetype().ty == Tsarray) 9185 { 9186 se.e1 = se.e1.modifiableLvalue(sc, exp.e1); 9187 if (se.e1.op == TOK.error) 9188 return setResult(se.e1); 9189 } 9190 } 9191 else 9192 { 9193 if (t1.ty == Tsarray && exp.op == TOK.assign) 9194 { 9195 Type tn = exp.e1.type.nextOf(); 9196 if (tn && !tn.baseElemOf().isAssignable()) 9197 { 9198 exp.error("array `%s` is not mutable, struct `%s` has immutable members", 9199 exp.e1.toChars(), tn.baseElemOf().toChars()); 9200 result = ErrorExp.get(); 9201 return; 9202 } 9203 } 9204 9205 Expression e1x = exp.e1; 9206 9207 // Try to do a decent error message with the expression 9208 // before it got constant folded 9209 9210 if (e1x.op != TOK.variable) 9211 e1x = e1x.optimize(WANTvalue); 9212 9213 if (exp.op == TOK.assign) 9214 e1x = e1x.modifiableLvalue(sc, e1old); 9215 9216 if (checkIfIsStructLiteralDotExpr(e1x)) 9217 return setError(); 9218 9219 if (e1x.op == TOK.error) 9220 { 9221 result = e1x; 9222 return; 9223 } 9224 exp.e1 = e1x; 9225 } 9226 9227 /* Tweak e2 based on the type of e1. 9228 */ 9229 Expression e2x = exp.e2; 9230 Type t2 = e2x.type.toBasetype(); 9231 9232 // If it is a array, get the element type. Note that it may be 9233 // multi-dimensional. 9234 Type telem = t1; 9235 while (telem.ty == Tarray) 9236 telem = telem.nextOf(); 9237 9238 if (exp.e1.op == TOK.slice && t1.nextOf() && 9239 (telem.ty != Tvoid || e2x.op == TOK.null_) && 9240 e2x.implicitConvTo(t1.nextOf())) 9241 { 9242 // Check for block assignment. If it is of type void[], void[][], etc, 9243 // '= null' is the only allowable block assignment (Bug 7493) 9244 exp.memset = MemorySet.blockAssign; // make it easy for back end to tell what this is 9245 e2x = e2x.implicitCastTo(sc, t1.nextOf()); 9246 if (exp.op != TOK.blit && e2x.isLvalue() && exp.e1.checkPostblit(sc, t1.nextOf())) 9247 return setError(); 9248 } 9249 else if (exp.e1.op == TOK.slice && 9250 (t2.ty == Tarray || t2.ty == Tsarray) && 9251 t2.nextOf().implicitConvTo(t1.nextOf())) 9252 { 9253 // Check element-wise assignment. 9254 9255 /* If assigned elements number is known at compile time, 9256 * check the mismatch. 9257 */ 9258 SliceExp se1 = cast(SliceExp)exp.e1; 9259 TypeSArray tsa1 = cast(TypeSArray)toStaticArrayType(se1); 9260 TypeSArray tsa2 = null; 9261 if (auto ale = e2x.isArrayLiteralExp()) 9262 tsa2 = cast(TypeSArray)t2.nextOf().sarrayOf(ale.elements.dim); 9263 else if (auto se = e2x.isSliceExp()) 9264 tsa2 = cast(TypeSArray)toStaticArrayType(se); 9265 else 9266 tsa2 = t2.isTypeSArray(); 9267 if (tsa1 && tsa2) 9268 { 9269 uinteger_t dim1 = tsa1.dim.toInteger(); 9270 uinteger_t dim2 = tsa2.dim.toInteger(); 9271 if (dim1 != dim2) 9272 { 9273 exp.error("mismatched array lengths, %d and %d", cast(int)dim1, cast(int)dim2); 9274 return setError(); 9275 } 9276 } 9277 9278 if (exp.op != TOK.blit && 9279 (e2x.op == TOK.slice && (cast(UnaExp)e2x).e1.isLvalue() || 9280 e2x.op == TOK.cast_ && (cast(UnaExp)e2x).e1.isLvalue() || 9281 e2x.op != TOK.slice && e2x.isLvalue())) 9282 { 9283 if (exp.e1.checkPostblit(sc, t1.nextOf())) 9284 return setError(); 9285 } 9286 9287 if (0 && global.params.warnings != DiagnosticReporting.off && !global.gag && exp.op == TOK.assign && 9288 e2x.op != TOK.slice && e2x.op != TOK.assign && 9289 e2x.op != TOK.arrayLiteral && e2x.op != TOK.string_ && 9290 !(e2x.op == TOK.add || e2x.op == TOK.min || 9291 e2x.op == TOK.mul || e2x.op == TOK.div || 9292 e2x.op == TOK.mod || e2x.op == TOK.xor || 9293 e2x.op == TOK.and || e2x.op == TOK.or || 9294 e2x.op == TOK.pow || 9295 e2x.op == TOK.tilde || e2x.op == TOK.negate)) 9296 { 9297 const(char)* e1str = exp.e1.toChars(); 9298 const(char)* e2str = e2x.toChars(); 9299 exp.warning("explicit element-wise assignment `%s = (%s)[]` is better than `%s = %s`", e1str, e2str, e1str, e2str); 9300 } 9301 9302 Type t2n = t2.nextOf(); 9303 Type t1n = t1.nextOf(); 9304 int offset; 9305 if (t2n.equivalent(t1n) || 9306 t1n.isBaseOf(t2n, &offset) && offset == 0) 9307 { 9308 /* Allow copy of distinct qualifier elements. 9309 * eg. 9310 * char[] dst; const(char)[] src; 9311 * dst[] = src; 9312 * 9313 * class C {} class D : C {} 9314 * C[2] ca; D[] da; 9315 * ca[] = da; 9316 */ 9317 if (isArrayOpValid(e2x)) 9318 { 9319 // Don't add CastExp to keep AST for array operations 9320 e2x = e2x.copy(); 9321 e2x.type = exp.e1.type.constOf(); 9322 } 9323 else 9324 e2x = e2x.castTo(sc, exp.e1.type.constOf()); 9325 } 9326 else 9327 { 9328 /* https://issues.dlang.org/show_bug.cgi?id=15778 9329 * A string literal has an array type of immutable 9330 * elements by default, and normally it cannot be convertible to 9331 * array type of mutable elements. But for element-wise assignment, 9332 * elements need to be const at best. So we should give a chance 9333 * to change code unit size for polysemous string literal. 9334 */ 9335 if (e2x.op == TOK.string_) 9336 e2x = e2x.implicitCastTo(sc, exp.e1.type.constOf()); 9337 else 9338 e2x = e2x.implicitCastTo(sc, exp.e1.type); 9339 } 9340 if (t1n.toBasetype.ty == Tvoid && t2n.toBasetype.ty == Tvoid) 9341 { 9342 if (!sc.intypeof && sc.func && !(sc.flags & SCOPE.debug_) && sc.func.setUnsafe()) 9343 { 9344 exp.error("cannot copy `void[]` to `void[]` in `@safe` code"); 9345 return setError(); 9346 } 9347 } 9348 } 9349 else 9350 { 9351 if (0 && global.params.warnings != DiagnosticReporting.off && !global.gag && exp.op == TOK.assign && 9352 t1.ty == Tarray && t2.ty == Tsarray && 9353 e2x.op != TOK.slice && 9354 t2.implicitConvTo(t1)) 9355 { 9356 // Disallow ar[] = sa (Converted to ar[] = sa[]) 9357 // Disallow da = sa (Converted to da = sa[]) 9358 const(char)* e1str = exp.e1.toChars(); 9359 const(char)* e2str = e2x.toChars(); 9360 const(char)* atypestr = exp.e1.op == TOK.slice ? "element-wise" : "slice"; 9361 exp.warning("explicit %s assignment `%s = (%s)[]` is better than `%s = %s`", atypestr, e1str, e2str, e1str, e2str); 9362 } 9363 if (exp.op == TOK.blit) 9364 e2x = e2x.castTo(sc, exp.e1.type); 9365 else 9366 { 9367 e2x = e2x.implicitCastTo(sc, exp.e1.type); 9368 9369 // Fix Issue 13435: https://issues.dlang.org/show_bug.cgi?id=13435 9370 9371 // If the implicit cast has failed and the assign expression is 9372 // the initialization of a struct member field 9373 if (e2x.op == TOK.error && exp.op == TOK.construct && t1.ty == Tstruct) 9374 { 9375 scope sd = (cast(TypeStruct)t1).sym; 9376 Dsymbol opAssign = search_function(sd, Id.assign); 9377 9378 // and the struct defines an opAssign 9379 if (opAssign) 9380 { 9381 // offer more information about the cause of the problem 9382 errorSupplemental(exp.loc, 9383 "`%s` is the first assignment of `%s` therefore it represents its initialization", 9384 exp.toChars(), exp.e1.toChars()); 9385 errorSupplemental(exp.loc, 9386 "`opAssign` methods are not used for initialization, but for subsequent assignments"); 9387 } 9388 } 9389 } 9390 } 9391 if (e2x.op == TOK.error) 9392 { 9393 result = e2x; 9394 return; 9395 } 9396 exp.e2 = e2x; 9397 t2 = exp.e2.type.toBasetype(); 9398 9399 /* Look for array operations 9400 */ 9401 if ((t2.ty == Tarray || t2.ty == Tsarray) && isArrayOpValid(exp.e2)) 9402 { 9403 // Look for valid array operations 9404 if (exp.memset != MemorySet.blockAssign && 9405 exp.e1.op == TOK.slice && 9406 (isUnaArrayOp(exp.e2.op) || isBinArrayOp(exp.e2.op))) 9407 { 9408 exp.type = exp.e1.type; 9409 if (exp.op == TOK.construct) // https://issues.dlang.org/show_bug.cgi?id=10282 9410 // tweak mutability of e1 element 9411 exp.e1.type = exp.e1.type.nextOf().mutableOf().arrayOf(); 9412 result = arrayOp(exp, sc); 9413 return; 9414 } 9415 9416 // Drop invalid array operations in e2 9417 // d = a[] + b[], d = (a[] + b[])[0..2], etc 9418 if (checkNonAssignmentArrayOp(exp.e2, exp.memset != MemorySet.blockAssign && exp.op == TOK.assign)) 9419 return setError(); 9420 9421 // Remains valid array assignments 9422 // d = d[], d = [1,2,3], etc 9423 } 9424 9425 /* Don't allow assignment to classes that were allocated on the stack with: 9426 * scope Class c = new Class(); 9427 */ 9428 if (exp.e1.op == TOK.variable && exp.op == TOK.assign) 9429 { 9430 VarExp ve = cast(VarExp)exp.e1; 9431 VarDeclaration vd = ve.var.isVarDeclaration(); 9432 if (vd && (vd.onstack || vd.mynew)) 9433 { 9434 assert(t1.ty == Tclass); 9435 exp.error("cannot rebind scope variables"); 9436 } 9437 } 9438 9439 if (exp.e1.op == TOK.variable && (cast(VarExp)exp.e1).var.ident == Id.ctfe) 9440 { 9441 exp.error("cannot modify compiler-generated variable `__ctfe`"); 9442 } 9443 9444 exp.type = exp.e1.type; 9445 assert(exp.type); 9446 auto res = exp.op == TOK.assign ? exp.reorderSettingAAElem(sc) : exp; 9447 checkAssignEscape(sc, res, false); 9448 return setResult(res); 9449 } 9450 9451 override void visit(PowAssignExp exp) 9452 { 9453 if (exp.type) 9454 { 9455 result = exp; 9456 return; 9457 } 9458 9459 Expression e = exp.op_overload(sc); 9460 if (e) 9461 { 9462 result = e; 9463 return; 9464 } 9465 9466 if (exp.e1.checkReadModifyWrite(exp.op, exp.e2)) 9467 return setError(); 9468 9469 assert(exp.e1.type && exp.e2.type); 9470 if (exp.e1.op == TOK.slice || exp.e1.type.ty == Tarray || exp.e1.type.ty == Tsarray) 9471 { 9472 if (checkNonAssignmentArrayOp(exp.e1)) 9473 return setError(); 9474 9475 // T[] ^^= ... 9476 if (exp.e2.implicitConvTo(exp.e1.type.nextOf())) 9477 { 9478 // T[] ^^= T 9479 exp.e2 = exp.e2.castTo(sc, exp.e1.type.nextOf()); 9480 } 9481 else if (Expression ex = typeCombine(exp, sc)) 9482 { 9483 result = ex; 9484 return; 9485 } 9486 9487 // Check element types are arithmetic 9488 Type tb1 = exp.e1.type.nextOf().toBasetype(); 9489 Type tb2 = exp.e2.type.toBasetype(); 9490 if (tb2.ty == Tarray || tb2.ty == Tsarray) 9491 tb2 = tb2.nextOf().toBasetype(); 9492 if ((tb1.isintegral() || tb1.isfloating()) && (tb2.isintegral() || tb2.isfloating())) 9493 { 9494 exp.type = exp.e1.type; 9495 result = arrayOp(exp, sc); 9496 return; 9497 } 9498 } 9499 else 9500 { 9501 exp.e1 = exp.e1.modifiableLvalue(sc, exp.e1); 9502 } 9503 9504 if ((exp.e1.type.isintegral() || exp.e1.type.isfloating()) && (exp.e2.type.isintegral() || exp.e2.type.isfloating())) 9505 { 9506 Expression e0 = null; 9507 e = exp.reorderSettingAAElem(sc); 9508 e = Expression.extractLast(e, e0); 9509 assert(e == exp); 9510 9511 if (exp.e1.op == TOK.variable) 9512 { 9513 // Rewrite: e1 = e1 ^^ e2 9514 e = new PowExp(exp.loc, exp.e1.syntaxCopy(), exp.e2); 9515 e = new AssignExp(exp.loc, exp.e1, e); 9516 } 9517 else 9518 { 9519 // Rewrite: ref tmp = e1; tmp = tmp ^^ e2 9520 auto v = copyToTemp(STC.ref_, "__powtmp", exp.e1); 9521 auto de = new DeclarationExp(exp.e1.loc, v); 9522 auto ve = new VarExp(exp.e1.loc, v); 9523 e = new PowExp(exp.loc, ve, exp.e2); 9524 e = new AssignExp(exp.loc, new VarExp(exp.e1.loc, v), e); 9525 e = new CommaExp(exp.loc, de, e); 9526 } 9527 e = Expression.combine(e0, e); 9528 e = e.expressionSemantic(sc); 9529 result = e; 9530 return; 9531 } 9532 result = exp.incompatibleTypes(); 9533 } 9534 9535 override void visit(CatAssignExp exp) 9536 { 9537 if (exp.type) 9538 { 9539 result = exp; 9540 return; 9541 } 9542 9543 //printf("CatAssignExp::semantic() %s\n", exp.toChars()); 9544 Expression e = exp.op_overload(sc); 9545 if (e) 9546 { 9547 result = e; 9548 return; 9549 } 9550 9551 if (exp.e1.op == TOK.slice) 9552 { 9553 SliceExp se = cast(SliceExp)exp.e1; 9554 if (se.e1.type.toBasetype().ty == Tsarray) 9555 { 9556 exp.error("cannot append to static array `%s`", se.e1.type.toChars()); 9557 return setError(); 9558 } 9559 } 9560 9561 if (checkIfIsStructLiteralDotExpr(exp.e1)) 9562 return setError(); 9563 9564 exp.e1 = exp.e1.modifiableLvalue(sc, exp.e1); 9565 if (exp.e1.op == TOK.error) 9566 { 9567 result = exp.e1; 9568 return; 9569 } 9570 if (exp.e2.op == TOK.error) 9571 { 9572 result = exp.e2; 9573 return; 9574 } 9575 9576 if (checkNonAssignmentArrayOp(exp.e2)) 9577 return setError(); 9578 9579 Type tb1 = exp.e1.type.toBasetype(); 9580 Type tb1next = tb1.nextOf(); 9581 Type tb2 = exp.e2.type.toBasetype(); 9582 9583 /* Possibilities: 9584 * TOK.concatenateAssign: appending T[] to T[] 9585 * TOK.concatenateElemAssign: appending T to T[] 9586 * TOK.concatenateDcharAssign: appending dchar to T[] 9587 */ 9588 if ((tb1.ty == Tarray) && 9589 (tb2.ty == Tarray || tb2.ty == Tsarray) && 9590 (exp.e2.implicitConvTo(exp.e1.type) || 9591 (tb2.nextOf().implicitConvTo(tb1next) && 9592 (tb2.nextOf().size(Loc.initial) == tb1next.size(Loc.initial))))) 9593 { 9594 // TOK.concatenateAssign 9595 assert(exp.op == TOK.concatenateAssign); 9596 if (exp.e1.checkPostblit(sc, tb1next)) 9597 return setError(); 9598 9599 exp.e2 = exp.e2.castTo(sc, exp.e1.type); 9600 } 9601 else if ((tb1.ty == Tarray) && exp.e2.implicitConvTo(tb1next)) 9602 { 9603 /* https://issues.dlang.org/show_bug.cgi?id=19782 9604 * 9605 * If e2 is implicitly convertible to tb1next, the conversion 9606 * might be done through alias this, in which case, e2 needs to 9607 * be modified accordingly (e2 => e2.aliasthis). 9608 */ 9609 if (tb2.ty == Tstruct && (cast(TypeStruct)tb2).implicitConvToThroughAliasThis(tb1next)) 9610 goto Laliasthis; 9611 if (tb2.ty == Tclass && (cast(TypeClass)tb2).implicitConvToThroughAliasThis(tb1next)) 9612 goto Laliasthis; 9613 // Append element 9614 if (exp.e2.checkPostblit(sc, tb2)) 9615 return setError(); 9616 9617 if (checkNewEscape(sc, exp.e2, false)) 9618 return setError(); 9619 9620 exp = new CatElemAssignExp(exp.loc, exp.type, exp.e1, exp.e2.castTo(sc, tb1next)); 9621 exp.e2 = doCopyOrMove(sc, exp.e2); 9622 } 9623 else if (tb1.ty == Tarray && 9624 (tb1next.ty == Tchar || tb1next.ty == Twchar) && 9625 exp.e2.type.ty != tb1next.ty && 9626 exp.e2.implicitConvTo(Type.tdchar)) 9627 { 9628 // Append dchar to char[] or wchar[] 9629 exp = new CatDcharAssignExp(exp.loc, exp.type, exp.e1, exp.e2.castTo(sc, Type.tdchar)); 9630 9631 /* Do not allow appending wchar to char[] because if wchar happens 9632 * to be a surrogate pair, nothing good can result. 9633 */ 9634 } 9635 else 9636 { 9637 // Try alias this on first operand 9638 static Expression tryAliasThisForLhs(BinAssignExp exp, Scope* sc) 9639 { 9640 AggregateDeclaration ad1 = isAggregate(exp.e1.type); 9641 if (!ad1 || !ad1.aliasthis) 9642 return null; 9643 9644 /* Rewrite (e1 op e2) as: 9645 * (e1.aliasthis op e2) 9646 */ 9647 if (exp.att1 && exp.e1.type == exp.att1) 9648 return null; 9649 //printf("att %s e1 = %s\n", Token::toChars(e.op), e.e1.type.toChars()); 9650 Expression e1 = new DotIdExp(exp.loc, exp.e1, ad1.aliasthis.ident); 9651 BinExp be = cast(BinExp)exp.copy(); 9652 if (!be.att1 && exp.e1.type.checkAliasThisRec()) 9653 be.att1 = exp.e1.type; 9654 be.e1 = e1; 9655 return be.trySemantic(sc); 9656 } 9657 9658 // Try alias this on second operand 9659 static Expression tryAliasThisForRhs(BinAssignExp exp, Scope* sc) 9660 { 9661 AggregateDeclaration ad2 = isAggregate(exp.e2.type); 9662 if (!ad2 || !ad2.aliasthis) 9663 return null; 9664 /* Rewrite (e1 op e2) as: 9665 * (e1 op e2.aliasthis) 9666 */ 9667 if (exp.att2 && exp.e2.type == exp.att2) 9668 return null; 9669 //printf("att %s e2 = %s\n", Token::toChars(e.op), e.e2.type.toChars()); 9670 Expression e2 = new DotIdExp(exp.loc, exp.e2, ad2.aliasthis.ident); 9671 BinExp be = cast(BinExp)exp.copy(); 9672 if (!be.att2 && exp.e2.type.checkAliasThisRec()) 9673 be.att2 = exp.e2.type; 9674 be.e2 = e2; 9675 return be.trySemantic(sc); 9676 } 9677 9678 Laliasthis: 9679 result = tryAliasThisForLhs(exp, sc); 9680 if (result) 9681 return; 9682 9683 result = tryAliasThisForRhs(exp, sc); 9684 if (result) 9685 return; 9686 9687 exp.error("cannot append type `%s` to type `%s`", tb2.toChars(), tb1.toChars()); 9688 return setError(); 9689 } 9690 9691 if (exp.e2.checkValue() || exp.e2.checkSharedAccess(sc)) 9692 return setError(); 9693 9694 exp.type = exp.e1.type; 9695 auto res = exp.reorderSettingAAElem(sc); 9696 if ((exp.op == TOK.concatenateElemAssign || exp.op == TOK.concatenateDcharAssign) && global.params.vsafe) 9697 checkAssignEscape(sc, res, false); 9698 result = res; 9699 } 9700 9701 override void visit(AddExp exp) 9702 { 9703 static if (LOGSEMANTIC) 9704 { 9705 printf("AddExp::semantic('%s')\n", exp.toChars()); 9706 } 9707 if (exp.type) 9708 { 9709 result = exp; 9710 return; 9711 } 9712 9713 if (Expression ex = binSemanticProp(exp, sc)) 9714 { 9715 result = ex; 9716 return; 9717 } 9718 Expression e = exp.op_overload(sc); 9719 if (e) 9720 { 9721 result = e; 9722 return; 9723 } 9724 9725 Type tb1 = exp.e1.type.toBasetype(); 9726 Type tb2 = exp.e2.type.toBasetype(); 9727 9728 bool err = false; 9729 if (tb1.ty == Tdelegate || tb1.ty == Tpointer && tb1.nextOf().ty == Tfunction) 9730 { 9731 err |= exp.e1.checkArithmetic() || exp.e1.checkSharedAccess(sc); 9732 } 9733 if (tb2.ty == Tdelegate || tb2.ty == Tpointer && tb2.nextOf().ty == Tfunction) 9734 { 9735 err |= exp.e2.checkArithmetic() || exp.e2.checkSharedAccess(sc); 9736 } 9737 if (err) 9738 return setError(); 9739 9740 if (tb1.ty == Tpointer && exp.e2.type.isintegral() || tb2.ty == Tpointer && exp.e1.type.isintegral()) 9741 { 9742 result = scaleFactor(exp, sc); 9743 return; 9744 } 9745 9746 if (tb1.ty == Tpointer && tb2.ty == Tpointer) 9747 { 9748 result = exp.incompatibleTypes(); 9749 return; 9750 } 9751 9752 if (Expression ex = typeCombine(exp, sc)) 9753 { 9754 result = ex; 9755 return; 9756 } 9757 9758 Type tb = exp.type.toBasetype(); 9759 if (tb.ty == Tarray || tb.ty == Tsarray) 9760 { 9761 if (!isArrayOpValid(exp)) 9762 { 9763 result = arrayOpInvalidError(exp); 9764 return; 9765 } 9766 result = exp; 9767 return; 9768 } 9769 9770 tb1 = exp.e1.type.toBasetype(); 9771 if (!target.isVectorOpSupported(tb1, exp.op, tb2)) 9772 { 9773 result = exp.incompatibleTypes(); 9774 return; 9775 } 9776 if ((tb1.isreal() && exp.e2.type.isimaginary()) || (tb1.isimaginary() && exp.e2.type.isreal())) 9777 { 9778 switch (exp.type.toBasetype().ty) 9779 { 9780 case Tfloat32: 9781 case Timaginary32: 9782 exp.type = Type.tcomplex32; 9783 break; 9784 9785 case Tfloat64: 9786 case Timaginary64: 9787 exp.type = Type.tcomplex64; 9788 break; 9789 9790 case Tfloat80: 9791 case Timaginary80: 9792 exp.type = Type.tcomplex80; 9793 break; 9794 9795 default: 9796 assert(0); 9797 } 9798 } 9799 result = exp; 9800 } 9801 9802 override void visit(MinExp exp) 9803 { 9804 static if (LOGSEMANTIC) 9805 { 9806 printf("MinExp::semantic('%s')\n", exp.toChars()); 9807 } 9808 if (exp.type) 9809 { 9810 result = exp; 9811 return; 9812 } 9813 9814 if (Expression ex = binSemanticProp(exp, sc)) 9815 { 9816 result = ex; 9817 return; 9818 } 9819 Expression e = exp.op_overload(sc); 9820 if (e) 9821 { 9822 result = e; 9823 return; 9824 } 9825 9826 Type t1 = exp.e1.type.toBasetype(); 9827 Type t2 = exp.e2.type.toBasetype(); 9828 9829 bool err = false; 9830 if (t1.ty == Tdelegate || t1.ty == Tpointer && t1.nextOf().ty == Tfunction) 9831 { 9832 err |= exp.e1.checkArithmetic() || exp.e1.checkSharedAccess(sc); 9833 } 9834 if (t2.ty == Tdelegate || t2.ty == Tpointer && t2.nextOf().ty == Tfunction) 9835 { 9836 err |= exp.e2.checkArithmetic() || exp.e2.checkSharedAccess(sc); 9837 } 9838 if (err) 9839 return setError(); 9840 9841 if (t1.ty == Tpointer) 9842 { 9843 if (t2.ty == Tpointer) 9844 { 9845 // https://dlang.org/spec/expression.html#add_expressions 9846 // "If both operands are pointers, and the operator is -, the pointers are 9847 // subtracted and the result is divided by the size of the type pointed to 9848 // by the operands. It is an error if the pointers point to different types." 9849 Type p1 = t1.nextOf(); 9850 Type p2 = t2.nextOf(); 9851 9852 if (!p1.equivalent(p2)) 9853 { 9854 // Deprecation to remain for at least a year, after which this should be 9855 // changed to an error 9856 // See https://github.com/dlang/dmd/pull/7332 9857 deprecation(exp.loc, 9858 "cannot subtract pointers to different types: `%s` and `%s`.", 9859 t1.toChars(), t2.toChars()); 9860 } 9861 9862 // Need to divide the result by the stride 9863 // Replace (ptr - ptr) with (ptr - ptr) / stride 9864 d_int64 stride; 9865 9866 // make sure pointer types are compatible 9867 if (Expression ex = typeCombine(exp, sc)) 9868 { 9869 result = ex; 9870 return; 9871 } 9872 9873 exp.type = Type.tptrdiff_t; 9874 stride = t2.nextOf().size(); 9875 if (stride == 0) 9876 { 9877 e = new IntegerExp(exp.loc, 0, Type.tptrdiff_t); 9878 } 9879 else 9880 { 9881 e = new DivExp(exp.loc, exp, new IntegerExp(Loc.initial, stride, Type.tptrdiff_t)); 9882 e.type = Type.tptrdiff_t; 9883 } 9884 } 9885 else if (t2.isintegral()) 9886 e = scaleFactor(exp, sc); 9887 else 9888 { 9889 exp.error("can't subtract `%s` from pointer", t2.toChars()); 9890 e = ErrorExp.get(); 9891 } 9892 result = e; 9893 return; 9894 } 9895 if (t2.ty == Tpointer) 9896 { 9897 exp.type = exp.e2.type; 9898 exp.error("can't subtract pointer from `%s`", exp.e1.type.toChars()); 9899 return setError(); 9900 } 9901 9902 if (Expression ex = typeCombine(exp, sc)) 9903 { 9904 result = ex; 9905 return; 9906 } 9907 9908 Type tb = exp.type.toBasetype(); 9909 if (tb.ty == Tarray || tb.ty == Tsarray) 9910 { 9911 if (!isArrayOpValid(exp)) 9912 { 9913 result = arrayOpInvalidError(exp); 9914 return; 9915 } 9916 result = exp; 9917 return; 9918 } 9919 9920 t1 = exp.e1.type.toBasetype(); 9921 t2 = exp.e2.type.toBasetype(); 9922 if (!target.isVectorOpSupported(t1, exp.op, t2)) 9923 { 9924 result = exp.incompatibleTypes(); 9925 return; 9926 } 9927 if ((t1.isreal() && t2.isimaginary()) || (t1.isimaginary() && t2.isreal())) 9928 { 9929 switch (exp.type.ty) 9930 { 9931 case Tfloat32: 9932 case Timaginary32: 9933 exp.type = Type.tcomplex32; 9934 break; 9935 9936 case Tfloat64: 9937 case Timaginary64: 9938 exp.type = Type.tcomplex64; 9939 break; 9940 9941 case Tfloat80: 9942 case Timaginary80: 9943 exp.type = Type.tcomplex80; 9944 break; 9945 9946 default: 9947 assert(0); 9948 } 9949 } 9950 result = exp; 9951 return; 9952 } 9953 9954 override void visit(CatExp exp) 9955 { 9956 // https://dlang.org/spec/expression.html#cat_expressions 9957 //printf("CatExp.semantic() %s\n", toChars()); 9958 if (exp.type) 9959 { 9960 result = exp; 9961 return; 9962 } 9963 9964 if (Expression ex = binSemanticProp(exp, sc)) 9965 { 9966 result = ex; 9967 return; 9968 } 9969 Expression e = exp.op_overload(sc); 9970 if (e) 9971 { 9972 result = e; 9973 return; 9974 } 9975 9976 Type tb1 = exp.e1.type.toBasetype(); 9977 Type tb2 = exp.e2.type.toBasetype(); 9978 9979 auto f1 = checkNonAssignmentArrayOp(exp.e1); 9980 auto f2 = checkNonAssignmentArrayOp(exp.e2); 9981 if (f1 || f2) 9982 return setError(); 9983 9984 /* BUG: Should handle things like: 9985 * char c; 9986 * c ~ ' ' 9987 * ' ' ~ c; 9988 */ 9989 9990 Type tb1next = tb1.nextOf(); 9991 Type tb2next = tb2.nextOf(); 9992 9993 // Check for: array ~ array 9994 if (tb1next && tb2next && (tb1next.implicitConvTo(tb2next) >= MATCH.constant || tb2next.implicitConvTo(tb1next) >= MATCH.constant || exp.e1.op == TOK.arrayLiteral && exp.e1.implicitConvTo(tb2) || exp.e2.op == TOK.arrayLiteral && exp.e2.implicitConvTo(tb1))) 9995 { 9996 /* https://issues.dlang.org/show_bug.cgi?id=9248 9997 * Here to avoid the case of: 9998 * void*[] a = [cast(void*)1]; 9999 * void*[] b = [cast(void*)2]; 10000 * a ~ b; 10001 * becoming: 10002 * a ~ [cast(void*)b]; 10003 */ 10004 10005 /* https://issues.dlang.org/show_bug.cgi?id=14682 10006 * Also to avoid the case of: 10007 * int[][] a; 10008 * a ~ []; 10009 * becoming: 10010 * a ~ cast(int[])[]; 10011 */ 10012 goto Lpeer; 10013 } 10014 10015 // Check for: array ~ element 10016 if ((tb1.ty == Tsarray || tb1.ty == Tarray) && tb2.ty != Tvoid) 10017 { 10018 if (exp.e1.op == TOK.arrayLiteral) 10019 { 10020 exp.e2 = doCopyOrMove(sc, exp.e2); 10021 // https://issues.dlang.org/show_bug.cgi?id=14686 10022 // Postblit call appears in AST, and this is 10023 // finally translated to an ArrayLiteralExp in below optimize(). 10024 } 10025 else if (exp.e1.op == TOK.string_) 10026 { 10027 // No postblit call exists on character (integer) value. 10028 } 10029 else 10030 { 10031 if (exp.e2.checkPostblit(sc, tb2)) 10032 return setError(); 10033 // Postblit call will be done in runtime helper function 10034 } 10035 10036 if (exp.e1.op == TOK.arrayLiteral && exp.e1.implicitConvTo(tb2.arrayOf())) 10037 { 10038 exp.e1 = exp.e1.implicitCastTo(sc, tb2.arrayOf()); 10039 exp.type = tb2.arrayOf(); 10040 goto L2elem; 10041 } 10042 if (exp.e2.implicitConvTo(tb1next) >= MATCH.convert) 10043 { 10044 exp.e2 = exp.e2.implicitCastTo(sc, tb1next); 10045 exp.type = tb1next.arrayOf(); 10046 L2elem: 10047 if (tb2.ty == Tarray || tb2.ty == Tsarray) 10048 { 10049 // Make e2 into [e2] 10050 exp.e2 = new ArrayLiteralExp(exp.e2.loc, exp.type, exp.e2); 10051 } 10052 else if (checkNewEscape(sc, exp.e2, false)) 10053 return setError(); 10054 result = exp.optimize(WANTvalue); 10055 return; 10056 } 10057 } 10058 // Check for: element ~ array 10059 if ((tb2.ty == Tsarray || tb2.ty == Tarray) && tb1.ty != Tvoid) 10060 { 10061 if (exp.e2.op == TOK.arrayLiteral) 10062 { 10063 exp.e1 = doCopyOrMove(sc, exp.e1); 10064 } 10065 else if (exp.e2.op == TOK.string_) 10066 { 10067 } 10068 else 10069 { 10070 if (exp.e1.checkPostblit(sc, tb1)) 10071 return setError(); 10072 } 10073 10074 if (exp.e2.op == TOK.arrayLiteral && exp.e2.implicitConvTo(tb1.arrayOf())) 10075 { 10076 exp.e2 = exp.e2.implicitCastTo(sc, tb1.arrayOf()); 10077 exp.type = tb1.arrayOf(); 10078 goto L1elem; 10079 } 10080 if (exp.e1.implicitConvTo(tb2next) >= MATCH.convert) 10081 { 10082 exp.e1 = exp.e1.implicitCastTo(sc, tb2next); 10083 exp.type = tb2next.arrayOf(); 10084 L1elem: 10085 if (tb1.ty == Tarray || tb1.ty == Tsarray) 10086 { 10087 // Make e1 into [e1] 10088 exp.e1 = new ArrayLiteralExp(exp.e1.loc, exp.type, exp.e1); 10089 } 10090 else if (checkNewEscape(sc, exp.e1, false)) 10091 return setError(); 10092 result = exp.optimize(WANTvalue); 10093 return; 10094 } 10095 } 10096 10097 Lpeer: 10098 if ((tb1.ty == Tsarray || tb1.ty == Tarray) && (tb2.ty == Tsarray || tb2.ty == Tarray) && (tb1next.mod || tb2next.mod) && (tb1next.mod != tb2next.mod)) 10099 { 10100 Type t1 = tb1next.mutableOf().constOf().arrayOf(); 10101 Type t2 = tb2next.mutableOf().constOf().arrayOf(); 10102 if (exp.e1.op == TOK.string_ && !(cast(StringExp)exp.e1).committed) 10103 exp.e1.type = t1; 10104 else 10105 exp.e1 = exp.e1.castTo(sc, t1); 10106 if (exp.e2.op == TOK.string_ && !(cast(StringExp)exp.e2).committed) 10107 exp.e2.type = t2; 10108 else 10109 exp.e2 = exp.e2.castTo(sc, t2); 10110 } 10111 10112 if (Expression ex = typeCombine(exp, sc)) 10113 { 10114 result = ex; 10115 return; 10116 } 10117 exp.type = exp.type.toHeadMutable(); 10118 10119 Type tb = exp.type.toBasetype(); 10120 if (tb.ty == Tsarray) 10121 exp.type = tb.nextOf().arrayOf(); 10122 if (exp.type.ty == Tarray && tb1next && tb2next && tb1next.mod != tb2next.mod) 10123 { 10124 exp.type = exp.type.nextOf().toHeadMutable().arrayOf(); 10125 } 10126 if (Type tbn = tb.nextOf()) 10127 { 10128 if (exp.checkPostblit(sc, tbn)) 10129 return setError(); 10130 } 10131 Type t1 = exp.e1.type.toBasetype(); 10132 Type t2 = exp.e2.type.toBasetype(); 10133 if ((t1.ty == Tarray || t1.ty == Tsarray) && 10134 (t2.ty == Tarray || t2.ty == Tsarray)) 10135 { 10136 // Normalize to ArrayLiteralExp or StringExp as far as possible 10137 e = exp.optimize(WANTvalue); 10138 } 10139 else 10140 { 10141 //printf("(%s) ~ (%s)\n", e1.toChars(), e2.toChars()); 10142 result = exp.incompatibleTypes(); 10143 return; 10144 } 10145 10146 result = e; 10147 } 10148 10149 override void visit(MulExp exp) 10150 { 10151 version (none) 10152 { 10153 printf("MulExp::semantic() %s\n", exp.toChars()); 10154 } 10155 if (exp.type) 10156 { 10157 result = exp; 10158 return; 10159 } 10160 10161 if (Expression ex = binSemanticProp(exp, sc)) 10162 { 10163 result = ex; 10164 return; 10165 } 10166 Expression e = exp.op_overload(sc); 10167 if (e) 10168 { 10169 result = e; 10170 return; 10171 } 10172 10173 if (Expression ex = typeCombine(exp, sc)) 10174 { 10175 result = ex; 10176 return; 10177 } 10178 10179 Type tb = exp.type.toBasetype(); 10180 if (tb.ty == Tarray || tb.ty == Tsarray) 10181 { 10182 if (!isArrayOpValid(exp)) 10183 { 10184 result = arrayOpInvalidError(exp); 10185 return; 10186 } 10187 result = exp; 10188 return; 10189 } 10190 10191 if (exp.checkArithmeticBin() || exp.checkSharedAccessBin(sc)) 10192 return setError(); 10193 10194 if (exp.type.isfloating()) 10195 { 10196 Type t1 = exp.e1.type; 10197 Type t2 = exp.e2.type; 10198 10199 if (t1.isreal()) 10200 { 10201 exp.type = t2; 10202 } 10203 else if (t2.isreal()) 10204 { 10205 exp.type = t1; 10206 } 10207 else if (t1.isimaginary()) 10208 { 10209 if (t2.isimaginary()) 10210 { 10211 switch (t1.toBasetype().ty) 10212 { 10213 case Timaginary32: 10214 exp.type = Type.tfloat32; 10215 break; 10216 10217 case Timaginary64: 10218 exp.type = Type.tfloat64; 10219 break; 10220 10221 case Timaginary80: 10222 exp.type = Type.tfloat80; 10223 break; 10224 10225 default: 10226 assert(0); 10227 } 10228 10229 // iy * iv = -yv 10230 exp.e1.type = exp.type; 10231 exp.e2.type = exp.type; 10232 e = new NegExp(exp.loc, exp); 10233 e = e.expressionSemantic(sc); 10234 result = e; 10235 return; 10236 } 10237 else 10238 exp.type = t2; // t2 is complex 10239 } 10240 else if (t2.isimaginary()) 10241 { 10242 exp.type = t1; // t1 is complex 10243 } 10244 } 10245 else if (!target.isVectorOpSupported(tb, exp.op, exp.e2.type.toBasetype())) 10246 { 10247 result = exp.incompatibleTypes(); 10248 return; 10249 } 10250 result = exp; 10251 } 10252 10253 override void visit(DivExp exp) 10254 { 10255 if (exp.type) 10256 { 10257 result = exp; 10258 return; 10259 } 10260 10261 if (Expression ex = binSemanticProp(exp, sc)) 10262 { 10263 result = ex; 10264 return; 10265 } 10266 Expression e = exp.op_overload(sc); 10267 if (e) 10268 { 10269 result = e; 10270 return; 10271 } 10272 10273 if (Expression ex = typeCombine(exp, sc)) 10274 { 10275 result = ex; 10276 return; 10277 } 10278 10279 Type tb = exp.type.toBasetype(); 10280 if (tb.ty == Tarray || tb.ty == Tsarray) 10281 { 10282 if (!isArrayOpValid(exp)) 10283 { 10284 result = arrayOpInvalidError(exp); 10285 return; 10286 } 10287 result = exp; 10288 return; 10289 } 10290 10291 if (exp.checkArithmeticBin() || exp.checkSharedAccessBin(sc)) 10292 return setError(); 10293 10294 if (exp.type.isfloating()) 10295 { 10296 Type t1 = exp.e1.type; 10297 Type t2 = exp.e2.type; 10298 10299 if (t1.isreal()) 10300 { 10301 exp.type = t2; 10302 if (t2.isimaginary()) 10303 { 10304 // x/iv = i(-x/v) 10305 exp.e2.type = t1; 10306 e = new NegExp(exp.loc, exp); 10307 e = e.expressionSemantic(sc); 10308 result = e; 10309 return; 10310 } 10311 } 10312 else if (t2.isreal()) 10313 { 10314 exp.type = t1; 10315 } 10316 else if (t1.isimaginary()) 10317 { 10318 if (t2.isimaginary()) 10319 { 10320 switch (t1.toBasetype().ty) 10321 { 10322 case Timaginary32: 10323 exp.type = Type.tfloat32; 10324 break; 10325 10326 case Timaginary64: 10327 exp.type = Type.tfloat64; 10328 break; 10329 10330 case Timaginary80: 10331 exp.type = Type.tfloat80; 10332 break; 10333 10334 default: 10335 assert(0); 10336 } 10337 } 10338 else 10339 exp.type = t2; // t2 is complex 10340 } 10341 else if (t2.isimaginary()) 10342 { 10343 exp.type = t1; // t1 is complex 10344 } 10345 } 10346 else if (!target.isVectorOpSupported(tb, exp.op, exp.e2.type.toBasetype())) 10347 { 10348 result = exp.incompatibleTypes(); 10349 return; 10350 } 10351 result = exp; 10352 } 10353 10354 override void visit(ModExp exp) 10355 { 10356 if (exp.type) 10357 { 10358 result = exp; 10359 return; 10360 } 10361 10362 if (Expression ex = binSemanticProp(exp, sc)) 10363 { 10364 result = ex; 10365 return; 10366 } 10367 Expression e = exp.op_overload(sc); 10368 if (e) 10369 { 10370 result = e; 10371 return; 10372 } 10373 10374 if (Expression ex = typeCombine(exp, sc)) 10375 { 10376 result = ex; 10377 return; 10378 } 10379 10380 Type tb = exp.type.toBasetype(); 10381 if (tb.ty == Tarray || tb.ty == Tsarray) 10382 { 10383 if (!isArrayOpValid(exp)) 10384 { 10385 result = arrayOpInvalidError(exp); 10386 return; 10387 } 10388 result = exp; 10389 return; 10390 } 10391 if (!target.isVectorOpSupported(tb, exp.op, exp.e2.type.toBasetype())) 10392 { 10393 result = exp.incompatibleTypes(); 10394 return; 10395 } 10396 10397 if (exp.checkArithmeticBin() || exp.checkSharedAccessBin(sc)) 10398 return setError(); 10399 10400 if (exp.type.isfloating()) 10401 { 10402 exp.type = exp.e1.type; 10403 if (exp.e2.type.iscomplex()) 10404 { 10405 exp.error("cannot perform modulo complex arithmetic"); 10406 return setError(); 10407 } 10408 } 10409 result = exp; 10410 } 10411 10412 override void visit(PowExp exp) 10413 { 10414 if (exp.type) 10415 { 10416 result = exp; 10417 return; 10418 } 10419 10420 //printf("PowExp::semantic() %s\n", toChars()); 10421 if (Expression ex = binSemanticProp(exp, sc)) 10422 { 10423 result = ex; 10424 return; 10425 } 10426 Expression e = exp.op_overload(sc); 10427 if (e) 10428 { 10429 result = e; 10430 return; 10431 } 10432 10433 if (Expression ex = typeCombine(exp, sc)) 10434 { 10435 result = ex; 10436 return; 10437 } 10438 10439 Type tb = exp.type.toBasetype(); 10440 if (tb.ty == Tarray || tb.ty == Tsarray) 10441 { 10442 if (!isArrayOpValid(exp)) 10443 { 10444 result = arrayOpInvalidError(exp); 10445 return; 10446 } 10447 result = exp; 10448 return; 10449 } 10450 10451 if (exp.checkArithmeticBin() || exp.checkSharedAccessBin(sc)) 10452 return setError(); 10453 10454 if (!target.isVectorOpSupported(tb, exp.op, exp.e2.type.toBasetype())) 10455 { 10456 result = exp.incompatibleTypes(); 10457 return; 10458 } 10459 10460 // First, attempt to fold the expression. 10461 e = exp.optimize(WANTvalue); 10462 if (e.op != TOK.pow) 10463 { 10464 e = e.expressionSemantic(sc); 10465 result = e; 10466 return; 10467 } 10468 10469 Module mmath = loadStdMath(); 10470 if (!mmath) 10471 { 10472 e.error("`%s` requires `std.math` for `^^` operators", e.toChars()); 10473 return setError(); 10474 } 10475 e = new ScopeExp(exp.loc, mmath); 10476 10477 if (exp.e2.op == TOK.float64 && exp.e2.toReal() == CTFloat.half) 10478 { 10479 // Replace e1 ^^ 0.5 with .std.math.sqrt(e1) 10480 e = new CallExp(exp.loc, new DotIdExp(exp.loc, e, Id._sqrt), exp.e1); 10481 } 10482 else 10483 { 10484 // Replace e1 ^^ e2 with .std.math.pow(e1, e2) 10485 e = new CallExp(exp.loc, new DotIdExp(exp.loc, e, Id._pow), exp.e1, exp.e2); 10486 } 10487 e = e.expressionSemantic(sc); 10488 result = e; 10489 return; 10490 } 10491 10492 override void visit(ShlExp exp) 10493 { 10494 //printf("ShlExp::semantic(), type = %p\n", type); 10495 if (exp.type) 10496 { 10497 result = exp; 10498 return; 10499 } 10500 10501 if (Expression ex = binSemanticProp(exp, sc)) 10502 { 10503 result = ex; 10504 return; 10505 } 10506 Expression e = exp.op_overload(sc); 10507 if (e) 10508 { 10509 result = e; 10510 return; 10511 } 10512 10513 if (exp.checkIntegralBin() || exp.checkSharedAccessBin(sc)) 10514 return setError(); 10515 10516 if (!target.isVectorOpSupported(exp.e1.type.toBasetype(), exp.op, exp.e2.type.toBasetype())) 10517 { 10518 result = exp.incompatibleTypes(); 10519 return; 10520 } 10521 exp.e1 = integralPromotions(exp.e1, sc); 10522 if (exp.e2.type.toBasetype().ty != Tvector) 10523 exp.e2 = exp.e2.castTo(sc, Type.tshiftcnt); 10524 10525 exp.type = exp.e1.type; 10526 result = exp; 10527 } 10528 10529 override void visit(ShrExp exp) 10530 { 10531 if (exp.type) 10532 { 10533 result = exp; 10534 return; 10535 } 10536 10537 if (Expression ex = binSemanticProp(exp, sc)) 10538 { 10539 result = ex; 10540 return; 10541 } 10542 Expression e = exp.op_overload(sc); 10543 if (e) 10544 { 10545 result = e; 10546 return; 10547 } 10548 10549 if (exp.checkIntegralBin() || exp.checkSharedAccessBin(sc)) 10550 return setError(); 10551 10552 if (!target.isVectorOpSupported(exp.e1.type.toBasetype(), exp.op, exp.e2.type.toBasetype())) 10553 { 10554 result = exp.incompatibleTypes(); 10555 return; 10556 } 10557 exp.e1 = integralPromotions(exp.e1, sc); 10558 if (exp.e2.type.toBasetype().ty != Tvector) 10559 exp.e2 = exp.e2.castTo(sc, Type.tshiftcnt); 10560 10561 exp.type = exp.e1.type; 10562 result = exp; 10563 } 10564 10565 override void visit(UshrExp exp) 10566 { 10567 if (exp.type) 10568 { 10569 result = exp; 10570 return; 10571 } 10572 10573 if (Expression ex = binSemanticProp(exp, sc)) 10574 { 10575 result = ex; 10576 return; 10577 } 10578 Expression e = exp.op_overload(sc); 10579 if (e) 10580 { 10581 result = e; 10582 return; 10583 } 10584 10585 if (exp.checkIntegralBin() || exp.checkSharedAccessBin(sc)) 10586 return setError(); 10587 10588 if (!target.isVectorOpSupported(exp.e1.type.toBasetype(), exp.op, exp.e2.type.toBasetype())) 10589 { 10590 result = exp.incompatibleTypes(); 10591 return; 10592 } 10593 exp.e1 = integralPromotions(exp.e1, sc); 10594 if (exp.e2.type.toBasetype().ty != Tvector) 10595 exp.e2 = exp.e2.castTo(sc, Type.tshiftcnt); 10596 10597 exp.type = exp.e1.type; 10598 result = exp; 10599 } 10600 10601 override void visit(AndExp exp) 10602 { 10603 if (exp.type) 10604 { 10605 result = exp; 10606 return; 10607 } 10608 10609 if (Expression ex = binSemanticProp(exp, sc)) 10610 { 10611 result = ex; 10612 return; 10613 } 10614 Expression e = exp.op_overload(sc); 10615 if (e) 10616 { 10617 result = e; 10618 return; 10619 } 10620 10621 if (exp.e1.type.toBasetype().ty == Tbool && exp.e2.type.toBasetype().ty == Tbool) 10622 { 10623 exp.type = exp.e1.type; 10624 result = exp; 10625 return; 10626 } 10627 10628 if (Expression ex = typeCombine(exp, sc)) 10629 { 10630 result = ex; 10631 return; 10632 } 10633 10634 Type tb = exp.type.toBasetype(); 10635 if (tb.ty == Tarray || tb.ty == Tsarray) 10636 { 10637 if (!isArrayOpValid(exp)) 10638 { 10639 result = arrayOpInvalidError(exp); 10640 return; 10641 } 10642 result = exp; 10643 return; 10644 } 10645 if (!target.isVectorOpSupported(tb, exp.op, exp.e2.type.toBasetype())) 10646 { 10647 result = exp.incompatibleTypes(); 10648 return; 10649 } 10650 if (exp.checkIntegralBin() || exp.checkSharedAccessBin(sc)) 10651 return setError(); 10652 10653 result = exp; 10654 } 10655 10656 override void visit(OrExp exp) 10657 { 10658 if (exp.type) 10659 { 10660 result = exp; 10661 return; 10662 } 10663 10664 if (Expression ex = binSemanticProp(exp, sc)) 10665 { 10666 result = ex; 10667 return; 10668 } 10669 Expression e = exp.op_overload(sc); 10670 if (e) 10671 { 10672 result = e; 10673 return; 10674 } 10675 10676 if (exp.e1.type.toBasetype().ty == Tbool && exp.e2.type.toBasetype().ty == Tbool) 10677 { 10678 exp.type = exp.e1.type; 10679 result = exp; 10680 return; 10681 } 10682 10683 if (Expression ex = typeCombine(exp, sc)) 10684 { 10685 result = ex; 10686 return; 10687 } 10688 10689 Type tb = exp.type.toBasetype(); 10690 if (tb.ty == Tarray || tb.ty == Tsarray) 10691 { 10692 if (!isArrayOpValid(exp)) 10693 { 10694 result = arrayOpInvalidError(exp); 10695 return; 10696 } 10697 result = exp; 10698 return; 10699 } 10700 if (!target.isVectorOpSupported(tb, exp.op, exp.e2.type.toBasetype())) 10701 { 10702 result = exp.incompatibleTypes(); 10703 return; 10704 } 10705 if (exp.checkIntegralBin() || exp.checkSharedAccessBin(sc)) 10706 return setError(); 10707 10708 result = exp; 10709 } 10710 10711 override void visit(XorExp exp) 10712 { 10713 if (exp.type) 10714 { 10715 result = exp; 10716 return; 10717 } 10718 10719 if (Expression ex = binSemanticProp(exp, sc)) 10720 { 10721 result = ex; 10722 return; 10723 } 10724 Expression e = exp.op_overload(sc); 10725 if (e) 10726 { 10727 result = e; 10728 return; 10729 } 10730 10731 if (exp.e1.type.toBasetype().ty == Tbool && exp.e2.type.toBasetype().ty == Tbool) 10732 { 10733 exp.type = exp.e1.type; 10734 result = exp; 10735 return; 10736 } 10737 10738 if (Expression ex = typeCombine(exp, sc)) 10739 { 10740 result = ex; 10741 return; 10742 } 10743 10744 Type tb = exp.type.toBasetype(); 10745 if (tb.ty == Tarray || tb.ty == Tsarray) 10746 { 10747 if (!isArrayOpValid(exp)) 10748 { 10749 result = arrayOpInvalidError(exp); 10750 return; 10751 } 10752 result = exp; 10753 return; 10754 } 10755 if (!target.isVectorOpSupported(tb, exp.op, exp.e2.type.toBasetype())) 10756 { 10757 result = exp.incompatibleTypes(); 10758 return; 10759 } 10760 if (exp.checkIntegralBin() || exp.checkSharedAccessBin(sc)) 10761 return setError(); 10762 10763 result = exp; 10764 } 10765 10766 override void visit(LogicalExp exp) 10767 { 10768 static if (LOGSEMANTIC) 10769 { 10770 printf("LogicalExp::semantic() %s\n", exp.toChars()); 10771 } 10772 10773 if (exp.type) 10774 { 10775 result = exp; 10776 return; 10777 } 10778 10779 exp.setNoderefOperands(); 10780 10781 Expression e1x = exp.e1.expressionSemantic(sc); 10782 10783 // for static alias this: https://issues.dlang.org/show_bug.cgi?id=17684 10784 if (e1x.op == TOK.type) 10785 e1x = resolveAliasThis(sc, e1x); 10786 10787 e1x = resolveProperties(sc, e1x); 10788 e1x = e1x.toBoolean(sc); 10789 10790 if (sc.flags & SCOPE.condition) 10791 { 10792 /* If in static if, don't evaluate e2 if we don't have to. 10793 */ 10794 e1x = e1x.optimize(WANTvalue); 10795 if (e1x.isBool(exp.op == TOK.orOr)) 10796 { 10797 result = IntegerExp.createBool(exp.op == TOK.orOr); 10798 return; 10799 } 10800 } 10801 10802 CtorFlow ctorflow = sc.ctorflow.clone(); 10803 Expression e2x = exp.e2.expressionSemantic(sc); 10804 sc.merge(exp.loc, ctorflow); 10805 ctorflow.freeFieldinit(); 10806 10807 // for static alias this: https://issues.dlang.org/show_bug.cgi?id=17684 10808 if (e2x.op == TOK.type) 10809 e2x = resolveAliasThis(sc, e2x); 10810 10811 e2x = resolveProperties(sc, e2x); 10812 10813 auto f1 = checkNonAssignmentArrayOp(e1x); 10814 auto f2 = checkNonAssignmentArrayOp(e2x); 10815 if (f1 || f2) 10816 return setError(); 10817 10818 // Unless the right operand is 'void', the expression is converted to 'bool'. 10819 if (e2x.type.ty != Tvoid) 10820 e2x = e2x.toBoolean(sc); 10821 10822 if (e2x.op == TOK.type || e2x.op == TOK.scope_) 10823 { 10824 exp.error("`%s` is not an expression", exp.e2.toChars()); 10825 return setError(); 10826 } 10827 if (e1x.op == TOK.error) 10828 { 10829 result = e1x; 10830 return; 10831 } 10832 if (e2x.op == TOK.error) 10833 { 10834 result = e2x; 10835 return; 10836 } 10837 10838 // The result type is 'bool', unless the right operand has type 'void'. 10839 if (e2x.type.ty == Tvoid) 10840 exp.type = Type.tvoid; 10841 else 10842 exp.type = Type.tbool; 10843 10844 exp.e1 = e1x; 10845 exp.e2 = e2x; 10846 result = exp; 10847 } 10848 10849 10850 override void visit(CmpExp exp) 10851 { 10852 static if (LOGSEMANTIC) 10853 { 10854 printf("CmpExp::semantic('%s')\n", exp.toChars()); 10855 } 10856 if (exp.type) 10857 { 10858 result = exp; 10859 return; 10860 } 10861 10862 exp.setNoderefOperands(); 10863 10864 if (Expression ex = binSemanticProp(exp, sc)) 10865 { 10866 result = ex; 10867 return; 10868 } 10869 Type t1 = exp.e1.type.toBasetype(); 10870 Type t2 = exp.e2.type.toBasetype(); 10871 if (t1.ty == Tclass && exp.e2.op == TOK.null_ || t2.ty == Tclass && exp.e1.op == TOK.null_) 10872 { 10873 exp.error("do not use `null` when comparing class types"); 10874 return setError(); 10875 } 10876 10877 TOK cmpop; 10878 if (auto e = exp.op_overload(sc, &cmpop)) 10879 { 10880 if (!e.type.isscalar() && e.type.equals(exp.e1.type)) 10881 { 10882 exp.error("recursive `opCmp` expansion"); 10883 return setError(); 10884 } 10885 if (e.op == TOK.call) 10886 { 10887 e = new CmpExp(cmpop, exp.loc, e, IntegerExp.literal!0); 10888 e = e.expressionSemantic(sc); 10889 } 10890 result = e; 10891 return; 10892 } 10893 10894 if (Expression ex = typeCombine(exp, sc)) 10895 { 10896 result = ex; 10897 return; 10898 } 10899 10900 auto f1 = checkNonAssignmentArrayOp(exp.e1); 10901 auto f2 = checkNonAssignmentArrayOp(exp.e2); 10902 if (f1 || f2) 10903 return setError(); 10904 10905 exp.type = Type.tbool; 10906 10907 // Special handling for array comparisons 10908 Expression arrayLowering = null; 10909 t1 = exp.e1.type.toBasetype(); 10910 t2 = exp.e2.type.toBasetype(); 10911 if ((t1.ty == Tarray || t1.ty == Tsarray || t1.ty == Tpointer) && (t2.ty == Tarray || t2.ty == Tsarray || t2.ty == Tpointer)) 10912 { 10913 Type t1next = t1.nextOf(); 10914 Type t2next = t2.nextOf(); 10915 if (t1next.implicitConvTo(t2next) < MATCH.constant && t2next.implicitConvTo(t1next) < MATCH.constant && (t1next.ty != Tvoid && t2next.ty != Tvoid)) 10916 { 10917 exp.error("array comparison type mismatch, `%s` vs `%s`", t1next.toChars(), t2next.toChars()); 10918 return setError(); 10919 } 10920 if ((t1.ty == Tarray || t1.ty == Tsarray) && (t2.ty == Tarray || t2.ty == Tsarray)) 10921 { 10922 if (!verifyHookExist(exp.loc, *sc, Id.__cmp, "comparing arrays")) 10923 return setError(); 10924 10925 // Lower to object.__cmp(e1, e2) 10926 Expression al = new IdentifierExp(exp.loc, Id.empty); 10927 al = new DotIdExp(exp.loc, al, Id.object); 10928 al = new DotIdExp(exp.loc, al, Id.__cmp); 10929 al = al.expressionSemantic(sc); 10930 10931 auto arguments = new Expressions(2); 10932 (*arguments)[0] = exp.e1; 10933 (*arguments)[1] = exp.e2; 10934 10935 al = new CallExp(exp.loc, al, arguments); 10936 al = new CmpExp(exp.op, exp.loc, al, IntegerExp.literal!0); 10937 10938 arrayLowering = al; 10939 } 10940 } 10941 else if (t1.ty == Tstruct || t2.ty == Tstruct || (t1.ty == Tclass && t2.ty == Tclass)) 10942 { 10943 if (t2.ty == Tstruct) 10944 exp.error("need member function `opCmp()` for %s `%s` to compare", t2.toDsymbol(sc).kind(), t2.toChars()); 10945 else 10946 exp.error("need member function `opCmp()` for %s `%s` to compare", t1.toDsymbol(sc).kind(), t1.toChars()); 10947 return setError(); 10948 } 10949 else if (t1.iscomplex() || t2.iscomplex()) 10950 { 10951 exp.error("compare not defined for complex operands"); 10952 return setError(); 10953 } 10954 else if (t1.ty == Taarray || t2.ty == Taarray) 10955 { 10956 exp.error("`%s` is not defined for associative arrays", Token.toChars(exp.op)); 10957 return setError(); 10958 } 10959 else if (!target.isVectorOpSupported(t1, exp.op, t2)) 10960 { 10961 result = exp.incompatibleTypes(); 10962 return; 10963 } 10964 else 10965 { 10966 bool r1 = exp.e1.checkValue() || exp.e1.checkSharedAccess(sc); 10967 bool r2 = exp.e2.checkValue() || exp.e2.checkSharedAccess(sc); 10968 if (r1 || r2) 10969 return setError(); 10970 } 10971 10972 //printf("CmpExp: %s, type = %s\n", e.toChars(), e.type.toChars()); 10973 if (arrayLowering) 10974 { 10975 arrayLowering = arrayLowering.expressionSemantic(sc); 10976 result = arrayLowering; 10977 return; 10978 } 10979 result = exp; 10980 return; 10981 } 10982 10983 override void visit(InExp exp) 10984 { 10985 if (exp.type) 10986 { 10987 result = exp; 10988 return; 10989 } 10990 10991 if (Expression ex = binSemanticProp(exp, sc)) 10992 { 10993 result = ex; 10994 return; 10995 } 10996 Expression e = exp.op_overload(sc); 10997 if (e) 10998 { 10999 result = e; 11000 return; 11001 } 11002 11003 Type t2b = exp.e2.type.toBasetype(); 11004 switch (t2b.ty) 11005 { 11006 case Taarray: 11007 { 11008 TypeAArray ta = cast(TypeAArray)t2b; 11009 11010 // Special handling for array keys 11011 if (!arrayTypeCompatibleWithoutCasting(exp.e1.type, ta.index)) 11012 { 11013 // Convert key to type of key 11014 exp.e1 = exp.e1.implicitCastTo(sc, ta.index); 11015 } 11016 11017 semanticTypeInfo(sc, ta.index); 11018 11019 // Return type is pointer to value 11020 exp.type = ta.nextOf().pointerTo(); 11021 break; 11022 } 11023 11024 case Terror: 11025 return setError(); 11026 11027 default: 11028 result = exp.incompatibleTypes(); 11029 return; 11030 } 11031 result = exp; 11032 } 11033 11034 override void visit(RemoveExp e) 11035 { 11036 if (Expression ex = binSemantic(e, sc)) 11037 { 11038 result = ex; 11039 return; 11040 } 11041 result = e; 11042 } 11043 11044 override void visit(EqualExp exp) 11045 { 11046 //printf("EqualExp::semantic('%s')\n", exp.toChars()); 11047 if (exp.type) 11048 { 11049 result = exp; 11050 return; 11051 } 11052 11053 exp.setNoderefOperands(); 11054 11055 if (auto e = binSemanticProp(exp, sc)) 11056 { 11057 result = e; 11058 return; 11059 } 11060 if (exp.e1.op == TOK.type || exp.e2.op == TOK.type) 11061 { 11062 /* https://issues.dlang.org/show_bug.cgi?id=12520 11063 * empty tuples are represented as types so special cases are added 11064 * so that they can be compared for equality with tuples of values. 11065 */ 11066 static auto extractTypeTupAndExpTup(Expression e) 11067 { 11068 static struct Result { bool ttEmpty; bool te; } 11069 auto tt = e.op == TOK.type ? e.isTypeExp().type.isTypeTuple() : null; 11070 return Result(tt && (!tt.arguments || !tt.arguments.dim), e.isTupleExp() !is null); 11071 } 11072 auto tups1 = extractTypeTupAndExpTup(exp.e1); 11073 auto tups2 = extractTypeTupAndExpTup(exp.e2); 11074 // AliasSeq!() == AliasSeq!(<at least a value>) 11075 if (tups1.ttEmpty && tups2.te) 11076 { 11077 result = IntegerExp.createBool(exp.op != TOK.equal); 11078 return; 11079 } 11080 // AliasSeq!(<at least a value>) == AliasSeq!() 11081 else if (tups1.te && tups2.ttEmpty) 11082 { 11083 result = IntegerExp.createBool(exp.op != TOK.equal); 11084 return; 11085 } 11086 // AliasSeq!() == AliasSeq!() 11087 else if (tups1.ttEmpty && tups2.ttEmpty) 11088 { 11089 result = IntegerExp.createBool(exp.op == TOK.equal); 11090 return; 11091 } 11092 // otherwise, two types are really not comparable 11093 result = exp.incompatibleTypes(); 11094 return; 11095 } 11096 11097 { 11098 auto t1 = exp.e1.type; 11099 auto t2 = exp.e2.type; 11100 if (t1.ty == Tenum && t2.ty == Tenum && !t1.equivalent(t2)) 11101 exp.error("Comparison between different enumeration types `%s` and `%s`; If this behavior is intended consider using `std.conv.asOriginalType`", 11102 t1.toChars(), t2.toChars()); 11103 } 11104 11105 /* Before checking for operator overloading, check to see if we're 11106 * comparing the addresses of two statics. If so, we can just see 11107 * if they are the same symbol. 11108 */ 11109 if (exp.e1.op == TOK.address && exp.e2.op == TOK.address) 11110 { 11111 AddrExp ae1 = cast(AddrExp)exp.e1; 11112 AddrExp ae2 = cast(AddrExp)exp.e2; 11113 if (ae1.e1.op == TOK.variable && ae2.e1.op == TOK.variable) 11114 { 11115 VarExp ve1 = cast(VarExp)ae1.e1; 11116 VarExp ve2 = cast(VarExp)ae2.e1; 11117 if (ve1.var == ve2.var) 11118 { 11119 // They are the same, result is 'true' for ==, 'false' for != 11120 result = IntegerExp.createBool(exp.op == TOK.equal); 11121 return; 11122 } 11123 } 11124 } 11125 11126 Type t1 = exp.e1.type.toBasetype(); 11127 Type t2 = exp.e2.type.toBasetype(); 11128 11129 // Indicates whether the comparison of the 2 specified array types 11130 // requires an object.__equals() lowering. 11131 static bool needsDirectEq(Type t1, Type t2, Scope* sc) 11132 { 11133 Type t1n = t1.nextOf().toBasetype(); 11134 Type t2n = t2.nextOf().toBasetype(); 11135 if ((t1n.ty.isSomeChar && t2n.ty.isSomeChar) || 11136 (t1n.ty == Tvoid || t2n.ty == Tvoid)) 11137 { 11138 return false; 11139 } 11140 if (t1n.constOf() != t2n.constOf()) 11141 return true; 11142 11143 Type t = t1n; 11144 while (t.toBasetype().nextOf()) 11145 t = t.nextOf().toBasetype(); 11146 if (auto ts = t.isTypeStruct()) 11147 { 11148 // semanticTypeInfo() makes sure hasIdentityEquals has been computed 11149 if (global.params.useTypeInfo && Type.dtypeinfo) 11150 semanticTypeInfo(sc, ts); 11151 11152 return ts.sym.hasIdentityEquals; // has custom opEquals 11153 } 11154 11155 return false; 11156 } 11157 11158 if (auto e = exp.op_overload(sc)) 11159 { 11160 result = e; 11161 return; 11162 } 11163 11164 11165 const isArrayComparison = (t1.ty == Tarray || t1.ty == Tsarray) && 11166 (t2.ty == Tarray || t2.ty == Tsarray); 11167 const needsArrayLowering = isArrayComparison && needsDirectEq(t1, t2, sc); 11168 11169 if (!needsArrayLowering) 11170 { 11171 if (auto e = typeCombine(exp, sc)) 11172 { 11173 result = e; 11174 return; 11175 } 11176 } 11177 11178 auto f1 = checkNonAssignmentArrayOp(exp.e1); 11179 auto f2 = checkNonAssignmentArrayOp(exp.e2); 11180 if (f1 || f2) 11181 return setError(); 11182 11183 exp.type = Type.tbool; 11184 11185 if (!isArrayComparison) 11186 { 11187 if (exp.e1.type != exp.e2.type && exp.e1.type.isfloating() && exp.e2.type.isfloating()) 11188 { 11189 // Cast both to complex 11190 exp.e1 = exp.e1.castTo(sc, Type.tcomplex80); 11191 exp.e2 = exp.e2.castTo(sc, Type.tcomplex80); 11192 } 11193 } 11194 11195 // lower some array comparisons to object.__equals(e1, e2) 11196 if (needsArrayLowering || (t1.ty == Tarray && t2.ty == Tarray)) 11197 { 11198 //printf("Lowering to __equals %s %s\n", exp.e1.toChars(), exp.e2.toChars()); 11199 11200 if (!verifyHookExist(exp.loc, *sc, Id.__equals, "equal checks on arrays")) 11201 return setError(); 11202 11203 Expression __equals = new IdentifierExp(exp.loc, Id.empty); 11204 Identifier id = Identifier.idPool("__equals"); 11205 __equals = new DotIdExp(exp.loc, __equals, Id.object); 11206 __equals = new DotIdExp(exp.loc, __equals, id); 11207 11208 auto arguments = new Expressions(2); 11209 (*arguments)[0] = exp.e1; 11210 (*arguments)[1] = exp.e2; 11211 11212 __equals = new CallExp(exp.loc, __equals, arguments); 11213 if (exp.op == TOK.notEqual) 11214 { 11215 __equals = new NotExp(exp.loc, __equals); 11216 } 11217 __equals = __equals.trySemantic(sc); // for better error message 11218 if (!__equals) 11219 { 11220 exp.error("incompatible types for array comparison: `%s` and `%s`", 11221 exp.e1.type.toChars(), exp.e2.type.toChars()); 11222 __equals = ErrorExp.get(); 11223 } 11224 11225 result = __equals; 11226 return; 11227 } 11228 11229 if (exp.e1.type.toBasetype().ty == Taarray) 11230 semanticTypeInfo(sc, exp.e1.type.toBasetype()); 11231 11232 11233 if (!target.isVectorOpSupported(t1, exp.op, t2)) 11234 { 11235 result = exp.incompatibleTypes(); 11236 return; 11237 } 11238 11239 result = exp; 11240 } 11241 11242 override void visit(IdentityExp exp) 11243 { 11244 if (exp.type) 11245 { 11246 result = exp; 11247 return; 11248 } 11249 11250 exp.setNoderefOperands(); 11251 11252 if (auto e = binSemanticProp(exp, sc)) 11253 { 11254 result = e; 11255 return; 11256 } 11257 11258 if (auto e = typeCombine(exp, sc)) 11259 { 11260 result = e; 11261 return; 11262 } 11263 11264 auto f1 = checkNonAssignmentArrayOp(exp.e1); 11265 auto f2 = checkNonAssignmentArrayOp(exp.e2); 11266 if (f1 || f2) 11267 return setError(); 11268 11269 if (exp.e1.op == TOK.type || exp.e2.op == TOK.type) 11270 { 11271 result = exp.incompatibleTypes(); 11272 return; 11273 } 11274 11275 exp.type = Type.tbool; 11276 11277 if (exp.e1.type != exp.e2.type && exp.e1.type.isfloating() && exp.e2.type.isfloating()) 11278 { 11279 // Cast both to complex 11280 exp.e1 = exp.e1.castTo(sc, Type.tcomplex80); 11281 exp.e2 = exp.e2.castTo(sc, Type.tcomplex80); 11282 } 11283 11284 auto tb1 = exp.e1.type.toBasetype(); 11285 auto tb2 = exp.e2.type.toBasetype(); 11286 if (!target.isVectorOpSupported(tb1, exp.op, tb2)) 11287 { 11288 result = exp.incompatibleTypes(); 11289 return; 11290 } 11291 11292 if (exp.e1.op == TOK.call) 11293 exp.e1 = (cast(CallExp)exp.e1).addDtorHook(sc); 11294 if (exp.e2.op == TOK.call) 11295 exp.e2 = (cast(CallExp)exp.e2).addDtorHook(sc); 11296 11297 if (exp.e1.type.toBasetype().ty == Tsarray || 11298 exp.e2.type.toBasetype().ty == Tsarray) 11299 exp.deprecation("identity comparison of static arrays " 11300 ~ "implicitly coerces them to slices, " 11301 ~ "which are compared by reference"); 11302 11303 result = exp; 11304 } 11305 11306 override void visit(CondExp exp) 11307 { 11308 static if (LOGSEMANTIC) 11309 { 11310 printf("CondExp::semantic('%s')\n", exp.toChars()); 11311 } 11312 if (exp.type) 11313 { 11314 result = exp; 11315 return; 11316 } 11317 11318 if (exp.econd.op == TOK.dotIdentifier) 11319 (cast(DotIdExp)exp.econd).noderef = true; 11320 11321 Expression ec = exp.econd.expressionSemantic(sc); 11322 ec = resolveProperties(sc, ec); 11323 ec = ec.toBoolean(sc); 11324 11325 CtorFlow ctorflow_root = sc.ctorflow.clone(); 11326 Expression e1x = exp.e1.expressionSemantic(sc); 11327 e1x = resolveProperties(sc, e1x); 11328 11329 CtorFlow ctorflow1 = sc.ctorflow; 11330 sc.ctorflow = ctorflow_root; 11331 Expression e2x = exp.e2.expressionSemantic(sc); 11332 e2x = resolveProperties(sc, e2x); 11333 11334 sc.merge(exp.loc, ctorflow1); 11335 ctorflow1.freeFieldinit(); 11336 11337 if (ec.op == TOK.error) 11338 { 11339 result = ec; 11340 return; 11341 } 11342 if (ec.type == Type.terror) 11343 return setError(); 11344 exp.econd = ec; 11345 11346 if (e1x.op == TOK.error) 11347 { 11348 result = e1x; 11349 return; 11350 } 11351 if (e1x.type == Type.terror) 11352 return setError(); 11353 exp.e1 = e1x; 11354 11355 if (e2x.op == TOK.error) 11356 { 11357 result = e2x; 11358 return; 11359 } 11360 if (e2x.type == Type.terror) 11361 return setError(); 11362 exp.e2 = e2x; 11363 11364 auto f0 = checkNonAssignmentArrayOp(exp.econd); 11365 auto f1 = checkNonAssignmentArrayOp(exp.e1); 11366 auto f2 = checkNonAssignmentArrayOp(exp.e2); 11367 if (f0 || f1 || f2) 11368 return setError(); 11369 11370 Type t1 = exp.e1.type; 11371 Type t2 = exp.e2.type; 11372 // If either operand is void the result is void, we have to cast both 11373 // the expression to void so that we explicitly discard the expression 11374 // value if any 11375 // https://issues.dlang.org/show_bug.cgi?id=16598 11376 if (t1.ty == Tvoid || t2.ty == Tvoid) 11377 { 11378 exp.type = Type.tvoid; 11379 exp.e1 = exp.e1.castTo(sc, exp.type); 11380 exp.e2 = exp.e2.castTo(sc, exp.type); 11381 } 11382 else if (t1 == t2) 11383 exp.type = t1; 11384 else 11385 { 11386 if (Expression ex = typeCombine(exp, sc)) 11387 { 11388 result = ex; 11389 return; 11390 } 11391 11392 switch (exp.e1.type.toBasetype().ty) 11393 { 11394 case Tcomplex32: 11395 case Tcomplex64: 11396 case Tcomplex80: 11397 exp.e2 = exp.e2.castTo(sc, exp.e1.type); 11398 break; 11399 default: 11400 break; 11401 } 11402 switch (exp.e2.type.toBasetype().ty) 11403 { 11404 case Tcomplex32: 11405 case Tcomplex64: 11406 case Tcomplex80: 11407 exp.e1 = exp.e1.castTo(sc, exp.e2.type); 11408 break; 11409 default: 11410 break; 11411 } 11412 if (exp.type.toBasetype().ty == Tarray) 11413 { 11414 exp.e1 = exp.e1.castTo(sc, exp.type); 11415 exp.e2 = exp.e2.castTo(sc, exp.type); 11416 } 11417 } 11418 exp.type = exp.type.merge2(); 11419 version (none) 11420 { 11421 printf("res: %s\n", exp.type.toChars()); 11422 printf("e1 : %s\n", exp.e1.type.toChars()); 11423 printf("e2 : %s\n", exp.e2.type.toChars()); 11424 } 11425 11426 /* https://issues.dlang.org/show_bug.cgi?id=14696 11427 * If either e1 or e2 contain temporaries which need dtor, 11428 * make them conditional. 11429 * Rewrite: 11430 * cond ? (__tmp1 = ..., __tmp1) : (__tmp2 = ..., __tmp2) 11431 * to: 11432 * (auto __cond = cond) ? (... __tmp1) : (... __tmp2) 11433 * and replace edtors of __tmp1 and __tmp2 with: 11434 * __tmp1.edtor --> __cond && __tmp1.dtor() 11435 * __tmp2.edtor --> __cond || __tmp2.dtor() 11436 */ 11437 exp.hookDtors(sc); 11438 11439 result = exp; 11440 } 11441 11442 override void visit(FileInitExp e) 11443 { 11444 //printf("FileInitExp::semantic()\n"); 11445 e.type = Type.tstring; 11446 result = e; 11447 } 11448 11449 override void visit(LineInitExp e) 11450 { 11451 e.type = Type.tint32; 11452 result = e; 11453 } 11454 11455 override void visit(ModuleInitExp e) 11456 { 11457 //printf("ModuleInitExp::semantic()\n"); 11458 e.type = Type.tstring; 11459 result = e; 11460 } 11461 11462 override void visit(FuncInitExp e) 11463 { 11464 //printf("FuncInitExp::semantic()\n"); 11465 e.type = Type.tstring; 11466 if (sc.func) 11467 { 11468 result = e.resolveLoc(Loc.initial, sc); 11469 return; 11470 } 11471 result = e; 11472 } 11473 11474 override void visit(PrettyFuncInitExp e) 11475 { 11476 //printf("PrettyFuncInitExp::semantic()\n"); 11477 e.type = Type.tstring; 11478 if (sc.func) 11479 { 11480 result = e.resolveLoc(Loc.initial, sc); 11481 return; 11482 } 11483 11484 result = e; 11485 } 11486 } 11487 11488 /********************************** 11489 * Try to run semantic routines. 11490 * If they fail, return NULL. 11491 */ 11492 Expression trySemantic(Expression exp, Scope* sc) 11493 { 11494 //printf("+trySemantic(%s)\n", exp.toChars()); 11495 uint errors = global.startGagging(); 11496 Expression e = expressionSemantic(exp, sc); 11497 if (global.endGagging(errors)) 11498 { 11499 e = null; 11500 } 11501 //printf("-trySemantic(%s)\n", exp.toChars()); 11502 return e; 11503 } 11504 11505 /************************** 11506 * Helper function for easy error propagation. 11507 * If error occurs, returns ErrorExp. Otherwise returns NULL. 11508 */ 11509 Expression unaSemantic(UnaExp e, Scope* sc) 11510 { 11511 static if (LOGSEMANTIC) 11512 { 11513 printf("UnaExp::semantic('%s')\n", e.toChars()); 11514 } 11515 Expression e1x = e.e1.expressionSemantic(sc); 11516 if (e1x.op == TOK.error) 11517 return e1x; 11518 e.e1 = e1x; 11519 return null; 11520 } 11521 11522 /************************** 11523 * Helper function for easy error propagation. 11524 * If error occurs, returns ErrorExp. Otherwise returns NULL. 11525 */ 11526 Expression binSemantic(BinExp e, Scope* sc) 11527 { 11528 static if (LOGSEMANTIC) 11529 { 11530 printf("BinExp::semantic('%s')\n", e.toChars()); 11531 } 11532 Expression e1x = e.e1.expressionSemantic(sc); 11533 Expression e2x = e.e2.expressionSemantic(sc); 11534 11535 // for static alias this: https://issues.dlang.org/show_bug.cgi?id=17684 11536 if (e1x.op == TOK.type) 11537 e1x = resolveAliasThis(sc, e1x); 11538 if (e2x.op == TOK.type) 11539 e2x = resolveAliasThis(sc, e2x); 11540 11541 if (e1x.op == TOK.error) 11542 return e1x; 11543 if (e2x.op == TOK.error) 11544 return e2x; 11545 e.e1 = e1x; 11546 e.e2 = e2x; 11547 return null; 11548 } 11549 11550 Expression binSemanticProp(BinExp e, Scope* sc) 11551 { 11552 if (Expression ex = binSemantic(e, sc)) 11553 return ex; 11554 Expression e1x = resolveProperties(sc, e.e1); 11555 Expression e2x = resolveProperties(sc, e.e2); 11556 if (e1x.op == TOK.error) 11557 return e1x; 11558 if (e2x.op == TOK.error) 11559 return e2x; 11560 e.e1 = e1x; 11561 e.e2 = e2x; 11562 return null; 11563 } 11564 11565 // entrypoint for semantic ExpressionSemanticVisitor 11566 extern (C++) Expression expressionSemantic(Expression e, Scope* sc) 11567 { 11568 scope v = new ExpressionSemanticVisitor(sc); 11569 e.accept(v); 11570 return v.result; 11571 } 11572 11573 Expression semanticX(DotIdExp exp, Scope* sc) 11574 { 11575 //printf("DotIdExp::semanticX(this = %p, '%s')\n", this, toChars()); 11576 if (Expression ex = unaSemantic(exp, sc)) 11577 return ex; 11578 11579 if (exp.ident == Id._mangleof) 11580 { 11581 // symbol.mangleof 11582 Dsymbol ds; 11583 switch (exp.e1.op) 11584 { 11585 case TOK.scope_: 11586 ds = (cast(ScopeExp)exp.e1).sds; 11587 goto L1; 11588 case TOK.variable: 11589 ds = (cast(VarExp)exp.e1).var; 11590 goto L1; 11591 case TOK.dotVariable: 11592 ds = (cast(DotVarExp)exp.e1).var; 11593 goto L1; 11594 case TOK.overloadSet: 11595 ds = (cast(OverExp)exp.e1).vars; 11596 goto L1; 11597 case TOK.template_: 11598 { 11599 TemplateExp te = cast(TemplateExp)exp.e1; 11600 ds = te.fd ? cast(Dsymbol)te.fd : te.td; 11601 } 11602 L1: 11603 { 11604 assert(ds); 11605 if (auto f = ds.isFuncDeclaration()) 11606 { 11607 if (f.checkForwardRef(exp.loc)) 11608 { 11609 return ErrorExp.get(); 11610 } 11611 if (f.flags & (FUNCFLAG.purityInprocess | FUNCFLAG.safetyInprocess | 11612 FUNCFLAG.nothrowInprocess | FUNCFLAG.nogcInprocess)) 11613 { 11614 f.error(exp.loc, "cannot retrieve its `.mangleof` while inferring attributes"); 11615 return ErrorExp.get(); 11616 } 11617 } 11618 OutBuffer buf; 11619 mangleToBuffer(ds, &buf); 11620 Expression e = new StringExp(exp.loc, buf.extractSlice()); 11621 e = e.expressionSemantic(sc); 11622 return e; 11623 } 11624 default: 11625 break; 11626 } 11627 } 11628 11629 if (exp.e1.op == TOK.variable && exp.e1.type.toBasetype().ty == Tsarray && exp.ident == Id.length) 11630 { 11631 // bypass checkPurity 11632 return exp.e1.type.dotExp(sc, exp.e1, exp.ident, exp.noderef ? DotExpFlag.noDeref : 0); 11633 } 11634 11635 if (exp.e1.op == TOK.dot) 11636 { 11637 } 11638 else 11639 { 11640 exp.e1 = resolvePropertiesX(sc, exp.e1); 11641 } 11642 if (exp.e1.op == TOK.tuple && exp.ident == Id.offsetof) 11643 { 11644 /* 'distribute' the .offsetof to each of the tuple elements. 11645 */ 11646 TupleExp te = cast(TupleExp)exp.e1; 11647 auto exps = new Expressions(te.exps.dim); 11648 for (size_t i = 0; i < exps.dim; i++) 11649 { 11650 Expression e = (*te.exps)[i]; 11651 e = e.expressionSemantic(sc); 11652 e = new DotIdExp(e.loc, e, Id.offsetof); 11653 (*exps)[i] = e; 11654 } 11655 // Don't evaluate te.e0 in runtime 11656 Expression e = new TupleExp(exp.loc, null, exps); 11657 e = e.expressionSemantic(sc); 11658 return e; 11659 } 11660 if (exp.e1.op == TOK.tuple && exp.ident == Id.length) 11661 { 11662 TupleExp te = cast(TupleExp)exp.e1; 11663 // Don't evaluate te.e0 in runtime 11664 Expression e = new IntegerExp(exp.loc, te.exps.dim, Type.tsize_t); 11665 return e; 11666 } 11667 11668 // https://issues.dlang.org/show_bug.cgi?id=14416 11669 // Template has no built-in properties except for 'stringof'. 11670 if ((exp.e1.op == TOK.dotTemplateDeclaration || exp.e1.op == TOK.template_) && exp.ident != Id.stringof) 11671 { 11672 exp.error("template `%s` does not have property `%s`", exp.e1.toChars(), exp.ident.toChars()); 11673 return ErrorExp.get(); 11674 } 11675 if (!exp.e1.type) 11676 { 11677 exp.error("expression `%s` does not have property `%s`", exp.e1.toChars(), exp.ident.toChars()); 11678 return ErrorExp.get(); 11679 } 11680 11681 return exp; 11682 } 11683 11684 // Resolve e1.ident without seeing UFCS. 11685 // If flag == 1, stop "not a property" error and return NULL. 11686 Expression semanticY(DotIdExp exp, Scope* sc, int flag) 11687 { 11688 //printf("DotIdExp::semanticY(this = %p, '%s')\n", exp, exp.toChars()); 11689 11690 //{ static int z; fflush(stdout); if (++z == 10) *(char*)0=0; } 11691 11692 /* Special case: rewrite this.id and super.id 11693 * to be classtype.id and baseclasstype.id 11694 * if we have no this pointer. 11695 */ 11696 if ((exp.e1.op == TOK.this_ || exp.e1.op == TOK.super_) && !hasThis(sc)) 11697 { 11698 if (AggregateDeclaration ad = sc.getStructClassScope()) 11699 { 11700 if (exp.e1.op == TOK.this_) 11701 { 11702 exp.e1 = new TypeExp(exp.e1.loc, ad.type); 11703 } 11704 else 11705 { 11706 ClassDeclaration cd = ad.isClassDeclaration(); 11707 if (cd && cd.baseClass) 11708 exp.e1 = new TypeExp(exp.e1.loc, cd.baseClass.type); 11709 } 11710 } 11711 } 11712 11713 Expression e = semanticX(exp, sc); 11714 if (e != exp) 11715 return e; 11716 11717 Expression eleft; 11718 Expression eright; 11719 if (exp.e1.op == TOK.dot) 11720 { 11721 DotExp de = cast(DotExp)exp.e1; 11722 eleft = de.e1; 11723 eright = de.e2; 11724 } 11725 else 11726 { 11727 eleft = null; 11728 eright = exp.e1; 11729 } 11730 11731 Type t1b = exp.e1.type.toBasetype(); 11732 11733 if (eright.op == TOK.scope_) // also used for template alias's 11734 { 11735 ScopeExp ie = cast(ScopeExp)eright; 11736 11737 int flags = SearchLocalsOnly; 11738 /* Disable access to another module's private imports. 11739 * The check for 'is sds our current module' is because 11740 * the current module should have access to its own imports. 11741 */ 11742 if (ie.sds.isModule() && ie.sds != sc._module) 11743 flags |= IgnorePrivateImports; 11744 if (sc.flags & SCOPE.ignoresymbolvisibility) 11745 flags |= IgnoreSymbolVisibility; 11746 Dsymbol s = ie.sds.search(exp.loc, exp.ident, flags); 11747 /* Check for visibility before resolving aliases because public 11748 * aliases to private symbols are public. 11749 */ 11750 if (s && !(sc.flags & SCOPE.ignoresymbolvisibility) && !symbolIsVisible(sc._module, s)) 11751 { 11752 s = null; 11753 } 11754 if (s) 11755 { 11756 auto p = s.isPackage(); 11757 if (p && checkAccess(sc, p)) 11758 { 11759 s = null; 11760 } 11761 } 11762 if (s) 11763 { 11764 // if 's' is a tuple variable, the tuple is returned. 11765 s = s.toAlias(); 11766 11767 exp.checkDeprecated(sc, s); 11768 exp.checkDisabled(sc, s); 11769 11770 EnumMember em = s.isEnumMember(); 11771 if (em) 11772 { 11773 return em.getVarExp(exp.loc, sc); 11774 } 11775 VarDeclaration v = s.isVarDeclaration(); 11776 if (v) 11777 { 11778 //printf("DotIdExp:: Identifier '%s' is a variable, type '%s'\n", toChars(), v.type.toChars()); 11779 if (!v.type || 11780 !v.type.deco && v.inuse) 11781 { 11782 if (v.inuse) 11783 exp.error("circular reference to %s `%s`", v.kind(), v.toPrettyChars()); 11784 else 11785 exp.error("forward reference to %s `%s`", v.kind(), v.toPrettyChars()); 11786 return ErrorExp.get(); 11787 } 11788 if (v.type.ty == Terror) 11789 return ErrorExp.get(); 11790 11791 if ((v.storage_class & STC.manifest) && v._init && !exp.wantsym) 11792 { 11793 /* Normally, the replacement of a symbol with its initializer is supposed to be in semantic2(). 11794 * Introduced by https://github.com/dlang/dmd/pull/5588 which should probably 11795 * be reverted. `wantsym` is the hack to work around the problem. 11796 */ 11797 if (v.inuse) 11798 { 11799 error(exp.loc, "circular initialization of %s `%s`", v.kind(), v.toPrettyChars()); 11800 return ErrorExp.get(); 11801 } 11802 e = v.expandInitializer(exp.loc); 11803 v.inuse++; 11804 e = e.expressionSemantic(sc); 11805 v.inuse--; 11806 return e; 11807 } 11808 11809 if (v.needThis()) 11810 { 11811 if (!eleft) 11812 eleft = new ThisExp(exp.loc); 11813 e = new DotVarExp(exp.loc, eleft, v); 11814 e = e.expressionSemantic(sc); 11815 } 11816 else 11817 { 11818 e = new VarExp(exp.loc, v); 11819 if (eleft) 11820 { 11821 e = new CommaExp(exp.loc, eleft, e); 11822 e.type = v.type; 11823 } 11824 } 11825 e = e.deref(); 11826 return e.expressionSemantic(sc); 11827 } 11828 11829 FuncDeclaration f = s.isFuncDeclaration(); 11830 if (f) 11831 { 11832 //printf("it's a function\n"); 11833 if (!f.functionSemantic()) 11834 return ErrorExp.get(); 11835 if (f.needThis()) 11836 { 11837 if (!eleft) 11838 eleft = new ThisExp(exp.loc); 11839 e = new DotVarExp(exp.loc, eleft, f, true); 11840 e = e.expressionSemantic(sc); 11841 } 11842 else 11843 { 11844 e = new VarExp(exp.loc, f, true); 11845 if (eleft) 11846 { 11847 e = new CommaExp(exp.loc, eleft, e); 11848 e.type = f.type; 11849 } 11850 } 11851 return e; 11852 } 11853 if (auto td = s.isTemplateDeclaration()) 11854 { 11855 if (eleft) 11856 e = new DotTemplateExp(exp.loc, eleft, td); 11857 else 11858 e = new TemplateExp(exp.loc, td); 11859 e = e.expressionSemantic(sc); 11860 return e; 11861 } 11862 if (OverDeclaration od = s.isOverDeclaration()) 11863 { 11864 e = new VarExp(exp.loc, od, true); 11865 if (eleft) 11866 { 11867 e = new CommaExp(exp.loc, eleft, e); 11868 e.type = Type.tvoid; // ambiguous type? 11869 } 11870 return e; 11871 } 11872 OverloadSet o = s.isOverloadSet(); 11873 if (o) 11874 { 11875 //printf("'%s' is an overload set\n", o.toChars()); 11876 return new OverExp(exp.loc, o); 11877 } 11878 11879 if (auto t = s.getType()) 11880 { 11881 return (new TypeExp(exp.loc, t)).expressionSemantic(sc); 11882 } 11883 11884 TupleDeclaration tup = s.isTupleDeclaration(); 11885 if (tup) 11886 { 11887 if (eleft) 11888 { 11889 e = new DotVarExp(exp.loc, eleft, tup); 11890 e = e.expressionSemantic(sc); 11891 return e; 11892 } 11893 e = new TupleExp(exp.loc, tup); 11894 e = e.expressionSemantic(sc); 11895 return e; 11896 } 11897 11898 ScopeDsymbol sds = s.isScopeDsymbol(); 11899 if (sds) 11900 { 11901 //printf("it's a ScopeDsymbol %s\n", ident.toChars()); 11902 e = new ScopeExp(exp.loc, sds); 11903 e = e.expressionSemantic(sc); 11904 if (eleft) 11905 e = new DotExp(exp.loc, eleft, e); 11906 return e; 11907 } 11908 11909 Import imp = s.isImport(); 11910 if (imp) 11911 { 11912 ie = new ScopeExp(exp.loc, imp.pkg); 11913 return ie.expressionSemantic(sc); 11914 } 11915 // BUG: handle other cases like in IdentifierExp::semantic() 11916 debug 11917 { 11918 printf("s = '%s', kind = '%s'\n", s.toChars(), s.kind()); 11919 } 11920 assert(0); 11921 } 11922 else if (exp.ident == Id.stringof) 11923 { 11924 e = new StringExp(exp.loc, ie.toString()); 11925 e = e.expressionSemantic(sc); 11926 return e; 11927 } 11928 if (ie.sds.isPackage() || ie.sds.isImport() || ie.sds.isModule()) 11929 { 11930 flag = 0; 11931 } 11932 if (flag) 11933 return null; 11934 s = ie.sds.search_correct(exp.ident); 11935 if (s && symbolIsVisible(sc, s)) 11936 { 11937 if (s.isPackage()) 11938 exp.error("undefined identifier `%s` in %s `%s`, perhaps add `static import %s;`", exp.ident.toChars(), ie.sds.kind(), ie.sds.toPrettyChars(), s.toPrettyChars()); 11939 else 11940 exp.error("undefined identifier `%s` in %s `%s`, did you mean %s `%s`?", exp.ident.toChars(), ie.sds.kind(), ie.sds.toPrettyChars(), s.kind(), s.toChars()); 11941 } 11942 else 11943 exp.error("undefined identifier `%s` in %s `%s`", exp.ident.toChars(), ie.sds.kind(), ie.sds.toPrettyChars()); 11944 return ErrorExp.get(); 11945 } 11946 else if (t1b.ty == Tpointer && exp.e1.type.ty != Tenum && exp.ident != Id._init && exp.ident != Id.__sizeof && exp.ident != Id.__xalignof && exp.ident != Id.offsetof && exp.ident != Id._mangleof && exp.ident != Id.stringof) 11947 { 11948 Type t1bn = t1b.nextOf(); 11949 if (flag) 11950 { 11951 AggregateDeclaration ad = isAggregate(t1bn); 11952 if (ad && !ad.members) // https://issues.dlang.org/show_bug.cgi?id=11312 11953 return null; 11954 } 11955 11956 /* Rewrite: 11957 * p.ident 11958 * as: 11959 * (*p).ident 11960 */ 11961 if (flag && t1bn.ty == Tvoid) 11962 return null; 11963 e = new PtrExp(exp.loc, exp.e1); 11964 e = e.expressionSemantic(sc); 11965 return e.type.dotExp(sc, e, exp.ident, flag | (exp.noderef ? DotExpFlag.noDeref : 0)); 11966 } 11967 else 11968 { 11969 if (exp.e1.op == TOK.type || exp.e1.op == TOK.template_) 11970 flag = 0; 11971 e = exp.e1.type.dotExp(sc, exp.e1, exp.ident, flag | (exp.noderef ? DotExpFlag.noDeref : 0)); 11972 if (e) 11973 e = e.expressionSemantic(sc); 11974 return e; 11975 } 11976 } 11977 11978 // Resolve e1.ident!tiargs without seeing UFCS. 11979 // If flag == 1, stop "not a property" error and return NULL. 11980 Expression semanticY(DotTemplateInstanceExp exp, Scope* sc, int flag) 11981 { 11982 static if (LOGSEMANTIC) 11983 { 11984 printf("DotTemplateInstanceExpY::semantic('%s')\n", exp.toChars()); 11985 } 11986 11987 static Expression errorExp() 11988 { 11989 return ErrorExp.get(); 11990 } 11991 11992 Expression e1 = exp.e1; 11993 11994 if (exp.ti.tempdecl && exp.ti.tempdecl.parent && exp.ti.tempdecl.parent.isTemplateMixin()) 11995 { 11996 // if 'ti.tempdecl' happens to be found in a mixin template don't lose that info 11997 // and do the symbol search in that context (Issue: 19476) 11998 auto tm = cast(TemplateMixin)exp.ti.tempdecl.parent; 11999 e1 = new DotExp(exp.e1.loc, exp.e1, new ScopeExp(tm.loc, tm)); 12000 } 12001 12002 auto die = new DotIdExp(exp.loc, e1, exp.ti.name); 12003 12004 Expression e = die.semanticX(sc); 12005 if (e == die) 12006 { 12007 exp.e1 = die.e1; // take back 12008 Type t1b = exp.e1.type.toBasetype(); 12009 if (t1b.ty == Tarray || t1b.ty == Tsarray || t1b.ty == Taarray || t1b.ty == Tnull || (t1b.isTypeBasic() && t1b.ty != Tvoid)) 12010 { 12011 /* No built-in type has templatized properties, so do shortcut. 12012 * It is necessary in: 1024.max!"a < b" 12013 */ 12014 if (flag) 12015 return null; 12016 } 12017 e = die.semanticY(sc, flag); 12018 if (flag) 12019 { 12020 if (!e || 12021 isDotOpDispatch(e)) 12022 { 12023 /* opDispatch!tiargs would be a function template that needs IFTI, 12024 * so it's not a template 12025 */ 12026 return null; 12027 } 12028 } 12029 } 12030 assert(e); 12031 12032 if (e.op == TOK.error) 12033 return e; 12034 if (e.op == TOK.dotVariable) 12035 { 12036 DotVarExp dve = cast(DotVarExp)e; 12037 if (FuncDeclaration fd = dve.var.isFuncDeclaration()) 12038 { 12039 if (TemplateDeclaration td = fd.findTemplateDeclRoot()) 12040 { 12041 e = new DotTemplateExp(dve.loc, dve.e1, td); 12042 e = e.expressionSemantic(sc); 12043 } 12044 } 12045 else if (OverDeclaration od = dve.var.isOverDeclaration()) 12046 { 12047 exp.e1 = dve.e1; // pull semantic() result 12048 12049 if (!exp.findTempDecl(sc)) 12050 goto Lerr; 12051 if (exp.ti.needsTypeInference(sc)) 12052 return exp; 12053 exp.ti.dsymbolSemantic(sc); 12054 if (!exp.ti.inst || exp.ti.errors) // if template failed to expand 12055 return errorExp(); 12056 12057 if (Declaration v = exp.ti.toAlias().isDeclaration()) 12058 { 12059 if (v.type && !v.type.deco) 12060 v.type = v.type.typeSemantic(v.loc, sc); 12061 return new DotVarExp(exp.loc, exp.e1, v) 12062 .expressionSemantic(sc); 12063 } 12064 return new DotExp(exp.loc, exp.e1, new ScopeExp(exp.loc, exp.ti)) 12065 .expressionSemantic(sc); 12066 } 12067 } 12068 else if (e.op == TOK.variable) 12069 { 12070 VarExp ve = cast(VarExp)e; 12071 if (FuncDeclaration fd = ve.var.isFuncDeclaration()) 12072 { 12073 if (TemplateDeclaration td = fd.findTemplateDeclRoot()) 12074 { 12075 e = new TemplateExp(ve.loc, td) 12076 .expressionSemantic(sc); 12077 } 12078 } 12079 else if (OverDeclaration od = ve.var.isOverDeclaration()) 12080 { 12081 exp.ti.tempdecl = od; 12082 return new ScopeExp(exp.loc, exp.ti) 12083 .expressionSemantic(sc); 12084 } 12085 } 12086 12087 if (e.op == TOK.dotTemplateDeclaration) 12088 { 12089 DotTemplateExp dte = cast(DotTemplateExp)e; 12090 exp.e1 = dte.e1; // pull semantic() result 12091 12092 exp.ti.tempdecl = dte.td; 12093 if (!exp.ti.semanticTiargs(sc)) 12094 return errorExp(); 12095 if (exp.ti.needsTypeInference(sc)) 12096 return exp; 12097 exp.ti.dsymbolSemantic(sc); 12098 if (!exp.ti.inst || exp.ti.errors) // if template failed to expand 12099 return errorExp(); 12100 12101 if (Declaration v = exp.ti.toAlias().isDeclaration()) 12102 { 12103 if (v.isFuncDeclaration() || v.isVarDeclaration()) 12104 { 12105 return new DotVarExp(exp.loc, exp.e1, v) 12106 .expressionSemantic(sc); 12107 } 12108 } 12109 return new DotExp(exp.loc, exp.e1, new ScopeExp(exp.loc, exp.ti)) 12110 .expressionSemantic(sc); 12111 } 12112 else if (e.op == TOK.template_) 12113 { 12114 exp.ti.tempdecl = (cast(TemplateExp)e).td; 12115 return new ScopeExp(exp.loc, exp.ti) 12116 .expressionSemantic(sc); 12117 } 12118 else if (e.op == TOK.dot) 12119 { 12120 DotExp de = cast(DotExp)e; 12121 12122 if (de.e2.op == TOK.overloadSet) 12123 { 12124 if (!exp.findTempDecl(sc) || !exp.ti.semanticTiargs(sc)) 12125 { 12126 return errorExp(); 12127 } 12128 if (exp.ti.needsTypeInference(sc)) 12129 return exp; 12130 exp.ti.dsymbolSemantic(sc); 12131 if (!exp.ti.inst || exp.ti.errors) // if template failed to expand 12132 return errorExp(); 12133 12134 if (Declaration v = exp.ti.toAlias().isDeclaration()) 12135 { 12136 if (v.type && !v.type.deco) 12137 v.type = v.type.typeSemantic(v.loc, sc); 12138 return new DotVarExp(exp.loc, exp.e1, v) 12139 .expressionSemantic(sc); 12140 } 12141 return new DotExp(exp.loc, exp.e1, new ScopeExp(exp.loc, exp.ti)) 12142 .expressionSemantic(sc); 12143 } 12144 } 12145 else if (e.op == TOK.overloadSet) 12146 { 12147 OverExp oe = cast(OverExp)e; 12148 exp.ti.tempdecl = oe.vars; 12149 return new ScopeExp(exp.loc, exp.ti) 12150 .expressionSemantic(sc); 12151 } 12152 12153 Lerr: 12154 exp.error("`%s` isn't a template", e.toChars()); 12155 return errorExp(); 12156 } 12157 12158 /*************************************** 12159 * If expression is shared, check that we can access it. 12160 * Give error message if not. 12161 * 12162 * Params: 12163 * e = expression to check 12164 * sc = context 12165 * returnRef = Whether this expression is for a `return` statement 12166 * off a `ref` function, in which case a single level 12167 * of dereference is allowed (e.g. `shared(int)*`). 12168 * Returns: 12169 * true on error 12170 */ 12171 bool checkSharedAccess(Expression e, Scope* sc, bool returnRef = false) 12172 { 12173 if (!global.params.noSharedAccess || 12174 sc.intypeof || 12175 sc.flags & SCOPE.ctfe) 12176 { 12177 return false; 12178 } 12179 12180 //printf("checkSharedAccess() %s\n", e.toChars()); 12181 12182 static extern(C++) final class SharedCheckVisitor : SemanticTimeTransitiveVisitor 12183 { 12184 /// In case we don't know which expression triggered it, 12185 /// e.g. for `visit(Type)` overload 12186 Expression original; 12187 /// Where the result is stored (`true` == error) 12188 bool result; 12189 /// Whether we should allow one level of dereferencing 12190 bool allowRef; 12191 12192 /// Ctor 12193 this(Expression oe, bool allowRef_) 12194 { 12195 this.original = oe; 12196 this.allowRef = allowRef_; 12197 } 12198 12199 void sharedError(Expression e) 12200 { 12201 // https://dlang.org/phobos/core_atomic.html 12202 e.error("direct access to shared `%s` is not allowed, see `core.atomic`", e.toChars()); 12203 this.result = true; 12204 } 12205 12206 /// Introduce base class overrides 12207 alias visit = SemanticTimeTransitiveVisitor.visit; 12208 12209 // Error by default 12210 override void visit(Expression e) 12211 { 12212 if (e.type.isShared()) 12213 this.sharedError(e); 12214 } 12215 12216 /// Ditto 12217 override void visit(Type t) 12218 { 12219 // Note: This handles things like `new shared(Throwable).msg`, 12220 // where accessing `msg` would violate `shared`. 12221 if (t.isShared()) 12222 this.sharedError(this.original); 12223 } 12224 12225 // Those have no indirections / can be ignored 12226 override void visit(ErrorExp e) {} 12227 override void visit(ComplexExp e) {} 12228 override void visit(IntegerExp e) {} 12229 override void visit(NullExp e) {} 12230 12231 override void visit(VarExp e) 12232 { 12233 if (!this.allowRef && e.var.type.isShared()) 12234 this.sharedError(e); 12235 } 12236 12237 override void visit(AddrExp e) 12238 { 12239 this.allowRef = true; 12240 e.e1.accept(this); 12241 } 12242 12243 override void visit(PtrExp e) 12244 { 12245 if (!this.allowRef && e.type.isShared()) 12246 return this.sharedError(e); 12247 12248 if (e.e1.type.isShared()) 12249 return this.sharedError(e); 12250 12251 this.allowRef = false; 12252 e.e1.accept(this); 12253 } 12254 12255 override void visit(DotVarExp e) 12256 { 12257 if (!this.allowRef && e.type.isShared()) 12258 return this.sharedError(e); 12259 12260 // Allow to use `DotVarExp` within value types 12261 if (e.e1.type.ty == Tsarray || e.e1.type.ty == Tstruct) 12262 return e.e1.accept(this); 12263 12264 // If we end up with a single `VarExp`, it might be a `ref` param 12265 // `shared ref T` param == `shared(T)*`. 12266 if (auto ve = e.e1.isVarExp()) 12267 { 12268 this.allowRef = this.allowRef && (ve.var.storage_class & STC.ref_); 12269 return e.e1.accept(this); 12270 } 12271 12272 this.allowRef = false; 12273 return e.e1.accept(this); 12274 } 12275 12276 override void visit(IndexExp e) 12277 { 12278 if (!this.allowRef && e.type.isShared()) 12279 return this.sharedError(e); 12280 12281 if (e.e1.type.isShared()) 12282 return this.sharedError(e); 12283 12284 this.allowRef = false; 12285 e.e1.accept(this); 12286 } 12287 12288 override void visit(CommaExp e) 12289 { 12290 // Cannot be `return ref` since we can't use the return, 12291 // but it's better to show that error than an unrelated `shared` one 12292 this.allowRef = true; 12293 e.e2.accept(this); 12294 } 12295 } 12296 12297 scope visitor = new SharedCheckVisitor(e, returnRef); 12298 e.accept(visitor); 12299 return visitor.result; 12300 } 12301 12302 12303 12304 /**************************************************** 12305 * Determine if `exp`, which gets its address taken, can do so safely. 12306 * Params: 12307 * sc = context 12308 * exp = expression having its address taken 12309 * v = the variable getting its address taken 12310 * Returns: 12311 * `true` if ok, `false` for error 12312 */ 12313 bool checkAddressVar(Scope* sc, Expression exp, VarDeclaration v) 12314 { 12315 //printf("checkAddressVar(exp: %s, v: %s)\n", exp.toChars(), v.toChars()); 12316 if (v) 12317 { 12318 if (!v.canTakeAddressOf()) 12319 { 12320 exp.error("cannot take address of `%s`", exp.toChars()); 12321 return false; 12322 } 12323 if (sc.func && !sc.intypeof && !v.isDataseg()) 12324 { 12325 const(char)* p = v.isParameter() ? "parameter" : "local"; 12326 if (global.params.vsafe) 12327 { 12328 // Taking the address of v means it cannot be set to 'scope' later 12329 v.storage_class &= ~STC.maybescope; 12330 v.doNotInferScope = true; 12331 if (exp.type.hasPointers() && v.storage_class & STC.scope_ && 12332 !(sc.flags & SCOPE.debug_) && sc.func.setUnsafe()) 12333 { 12334 exp.error("cannot take address of `scope` %s `%s` in `@safe` function `%s`", p, v.toChars(), sc.func.toChars()); 12335 return false; 12336 } 12337 } 12338 else if (!(sc.flags & SCOPE.debug_) && 12339 sc.func.setUnsafe()) 12340 { 12341 exp.error("cannot take address of %s `%s` in `@safe` function `%s`", p, v.toChars(), sc.func.toChars()); 12342 return false; 12343 } 12344 } 12345 } 12346 return true; 12347 } 12348 12349 /******************************* 12350 * Checks the attributes of a function. 12351 * Purity (`pure`), safety (`@safe`), no GC allocations(`@nogc`) 12352 * and usage of `deprecated` and `@disabled`-ed symbols are checked. 12353 * 12354 * Params: 12355 * exp = expression to check attributes for 12356 * sc = scope of the function 12357 * f = function to be checked 12358 * Returns: `true` if error occur. 12359 */ 12360 private bool checkFunctionAttributes(Expression exp, Scope* sc, FuncDeclaration f) 12361 { 12362 with(exp) 12363 { 12364 bool error = checkDisabled(sc, f); 12365 error |= checkDeprecated(sc, f); 12366 error |= checkPurity(sc, f); 12367 error |= checkSafety(sc, f); 12368 error |= checkNogc(sc, f); 12369 return error; 12370 } 12371 } 12372 12373 /******************************* 12374 * Helper function for `getRightThis()`. 12375 * Gets `this` of the next outer aggregate. 12376 * Params: 12377 * loc = location to use for error messages 12378 * sc = context 12379 * s = the parent symbol of the existing `this` 12380 * ad = struct or class we need the correct `this` for 12381 * e1 = existing `this` 12382 * t = type of the existing `this` 12383 * var = the specific member of ad we're accessing 12384 * flag = if true, return `null` instead of throwing an error 12385 * Returns: 12386 * Expression representing the `this` for the var 12387 */ 12388 Expression getThisSkipNestedFuncs(const ref Loc loc, Scope* sc, Dsymbol s, AggregateDeclaration ad, Expression e1, Type t, Dsymbol var, bool flag = false) 12389 { 12390 int n = 0; 12391 while (s && s.isFuncDeclaration()) 12392 { 12393 FuncDeclaration f = s.isFuncDeclaration(); 12394 if (f.vthis) 12395 { 12396 n++; 12397 e1 = new VarExp(loc, f.vthis); 12398 if (f.isThis2) 12399 { 12400 // (*__this)[i] 12401 if (n > 1) 12402 e1 = e1.expressionSemantic(sc); 12403 e1 = new PtrExp(loc, e1); 12404 uint i = f.followInstantiationContext(ad); 12405 e1 = new IndexExp(loc, e1, new IntegerExp(i)); 12406 s = f.toParentP(ad); 12407 continue; 12408 } 12409 } 12410 else 12411 { 12412 if (flag) 12413 return null; 12414 e1.error("need `this` of type `%s` to access member `%s` from static function `%s`", ad.toChars(), var.toChars(), f.toChars()); 12415 e1 = ErrorExp.get(); 12416 return e1; 12417 } 12418 s = s.toParent2(); 12419 } 12420 if (n > 1 || e1.op == TOK.index) 12421 e1 = e1.expressionSemantic(sc); 12422 if (s && e1.type.equivalent(Type.tvoidptr)) 12423 { 12424 if (auto sad = s.isAggregateDeclaration()) 12425 { 12426 Type ta = sad.handleType(); 12427 if (ta.ty == Tstruct) 12428 ta = ta.pointerTo(); 12429 e1.type = ta; 12430 } 12431 } 12432 e1.type = e1.type.addMod(t.mod); 12433 return e1; 12434 } 12435 12436 /******************************* 12437 * Make a dual-context container for use as a `this` argument. 12438 * Params: 12439 * loc = location to use for error messages 12440 * sc = current scope 12441 * fd = target function that will take the `this` argument 12442 * Returns: 12443 * Temporary closure variable. 12444 * Note: 12445 * The function `fd` is added to the nested references of the 12446 * newly created variable such that a closure is made for the variable when 12447 * the address of `fd` is taken. 12448 */ 12449 VarDeclaration makeThis2Argument(const ref Loc loc, Scope* sc, FuncDeclaration fd) 12450 { 12451 Type tthis2 = Type.tvoidptr.sarrayOf(2); 12452 VarDeclaration vthis2 = new VarDeclaration(loc, tthis2, Identifier.generateId("__this"), null); 12453 vthis2.storage_class |= STC.temp; 12454 vthis2.dsymbolSemantic(sc); 12455 vthis2.parent = sc.parent; 12456 // make it a closure var 12457 assert(sc.func); 12458 sc.func.closureVars.push(vthis2); 12459 // add `fd` to the nested refs 12460 vthis2.nestedrefs.push(fd); 12461 return vthis2; 12462 } 12463 12464 /******************************* 12465 * Make sure that the runtime hook `id` exists. 12466 * Params: 12467 * loc = location to use for error messages 12468 * sc = current scope 12469 * id = the hook identifier 12470 * description = what the hook does 12471 * module_ = what module the hook is located in 12472 * Returns: 12473 * a `bool` indicating if the hook is present. 12474 */ 12475 bool verifyHookExist(const ref Loc loc, ref Scope sc, Identifier id, string description, Identifier module_ = Id.object) 12476 { 12477 auto rootSymbol = sc.search(loc, Id.empty, null); 12478 if (auto moduleSymbol = rootSymbol.search(loc, module_)) 12479 if (moduleSymbol.search(loc, id)) 12480 return true; 12481 error(loc, "`%s.%s` not found. The current runtime does not support %.*s, or the runtime is corrupt.", module_.toChars(), id.toChars(), cast(int)description.length, description.ptr); 12482 return false; 12483 } 12484 12485 /** 12486 * Check if an expression is an access to a struct member with the struct 12487 * defined from a literal. 12488 * 12489 * This happens with manifest constants since the initializer is reused as is, 12490 * each time the declaration is part of an expression, which means that the 12491 * literal used as initializer can become a Lvalue. This Lvalue must not be modifiable. 12492 * 12493 * Params: 12494 * exp = An expression that's attempted to be written. 12495 * Must be the LHS of an `AssignExp`, `BinAssignExp`, `CatAssignExp`, 12496 * or the expression passed to a modifiable function parameter. 12497 * Returns: 12498 * `true` if `expr` is a dot var or a dot identifier touching to a struct literal, 12499 * in which case an error message is issued, and `false` otherwise. 12500 */ 12501 private bool checkIfIsStructLiteralDotExpr(Expression exp) 12502 { 12503 // e1.var = ... 12504 // e1.ident = ... 12505 Expression e1; 12506 if (exp.op == TOK.dotVariable) 12507 e1 = exp.isDotVarExp().e1; 12508 else if (exp.op == TOK.dotIdentifier) 12509 e1 = exp.isDotIdExp().e1; 12510 else 12511 return false; 12512 12513 // enum SomeStruct ss = { ... } 12514 // also true for access from a .init: SomeStruct.init.member = ... 12515 if (e1.op != TOK.structLiteral) 12516 return false; 12517 12518 error(exp.loc, "cannot modify constant expression `%s`", exp.toChars()); 12519 return true; 12520 }