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.rootobject; 65 import dmd.root..string; 66 import dmd.semantic2; 67 import dmd.semantic3; 68 import dmd.sideeffect; 69 import dmd.safe; 70 import dmd.target; 71 import dmd.tokens; 72 import dmd.traits; 73 import dmd.typesem; 74 import dmd.typinf; 75 import dmd.utf; 76 import dmd.utils; 77 import dmd.visitor; 78 79 enum LOGSEMANTIC = false; 80 81 /******************************************************** 82 * Perform semantic analysis and CTFE on expressions to produce 83 * a string. 84 * Params: 85 * buf = append generated string to buffer 86 * sc = context 87 * exps = array of Expressions 88 * Returns: 89 * true on error 90 */ 91 bool expressionsToString(ref OutBuffer buf, Scope* sc, Expressions* exps) 92 { 93 if (!exps) 94 return false; 95 96 foreach (ex; *exps) 97 { 98 if (!ex) 99 continue; 100 auto sc2 = sc.startCTFE(); 101 auto e2 = ex.expressionSemantic(sc2); 102 auto e3 = resolveProperties(sc2, e2); 103 sc2.endCTFE(); 104 105 // allowed to contain types as well as expressions 106 auto e4 = ctfeInterpretForPragmaMsg(e3); 107 if (!e4 || e4.op == TOK.error) 108 return true; 109 110 // expand tuple 111 if (auto te = e4.isTupleExp()) 112 { 113 if (expressionsToString(buf, sc, te.exps)) 114 return true; 115 continue; 116 } 117 // char literals exp `.toStringExp` return `null` but we cant override it 118 // because in most contexts we don't want the conversion to succeed. 119 IntegerExp ie = e4.isIntegerExp(); 120 const ty = (ie && ie.type) ? ie.type.ty : Terror; 121 if (ty.isSomeChar) 122 { 123 auto tsa = new TypeSArray(ie.type, new IntegerExp(1)); 124 e4 = new ArrayLiteralExp(ex.loc, tsa, ie); 125 } 126 127 if (StringExp se = e4.toStringExp()) 128 buf.writestring(se.toUTF8(sc).peekString()); 129 else 130 buf.writestring(e4.toString()); 131 } 132 return false; 133 } 134 135 136 /*********************************************************** 137 * Resolve `exp` as a compile-time known string. 138 * Params: 139 * sc = scope 140 * exp = Expression which expected as a string 141 * s = What the string is expected for, will be used in error diagnostic. 142 * Returns: 143 * String literal, or `null` if error happens. 144 */ 145 StringExp semanticString(Scope *sc, Expression exp, const char* s) 146 { 147 sc = sc.startCTFE(); 148 exp = exp.expressionSemantic(sc); 149 exp = resolveProperties(sc, exp); 150 sc = sc.endCTFE(); 151 152 if (exp.op == TOK.error) 153 return null; 154 155 auto e = exp; 156 if (exp.type.isString()) 157 { 158 e = e.ctfeInterpret(); 159 if (e.op == TOK.error) 160 return null; 161 } 162 163 auto se = e.toStringExp(); 164 if (!se) 165 { 166 exp.error("`string` expected for %s, not `(%s)` of type `%s`", 167 s, exp.toChars(), exp.type.toChars()); 168 return null; 169 } 170 return se; 171 } 172 173 private Expression extractOpDollarSideEffect(Scope* sc, UnaExp ue) 174 { 175 Expression e0; 176 Expression e1 = Expression.extractLast(ue.e1, e0); 177 // https://issues.dlang.org/show_bug.cgi?id=12585 178 // Extract the side effect part if ue.e1 is comma. 179 180 if ((sc.flags & SCOPE.ctfe) ? hasSideEffect(e1) : !isTrivialExp(e1)) // match logic in extractSideEffect() 181 { 182 /* Even if opDollar is needed, 'e1' should be evaluate only once. So 183 * Rewrite: 184 * e1.opIndex( ... use of $ ... ) 185 * e1.opSlice( ... use of $ ... ) 186 * as: 187 * (ref __dop = e1, __dop).opIndex( ... __dop.opDollar ...) 188 * (ref __dop = e1, __dop).opSlice( ... __dop.opDollar ...) 189 */ 190 e1 = extractSideEffect(sc, "__dop", e0, e1, false); 191 assert(e1.op == TOK.variable); 192 VarExp ve = cast(VarExp)e1; 193 ve.var.storage_class |= STC.exptemp; // lifetime limited to expression 194 } 195 ue.e1 = e1; 196 return e0; 197 } 198 199 /************************************** 200 * Runs semantic on ae.arguments. Declares temporary variables 201 * if '$' was used. 202 */ 203 Expression resolveOpDollar(Scope* sc, ArrayExp ae, Expression* pe0) 204 { 205 assert(!ae.lengthVar); 206 *pe0 = null; 207 AggregateDeclaration ad = isAggregate(ae.e1.type); 208 Dsymbol slice = search_function(ad, Id.slice); 209 //printf("slice = %s %s\n", slice.kind(), slice.toChars()); 210 foreach (i, e; *ae.arguments) 211 { 212 if (i == 0) 213 *pe0 = extractOpDollarSideEffect(sc, ae); 214 215 if (e.op == TOK.interval && !(slice && slice.isTemplateDeclaration())) 216 { 217 Lfallback: 218 if (ae.arguments.dim == 1) 219 return null; 220 ae.error("multi-dimensional slicing requires template `opSlice`"); 221 return new ErrorExp(); 222 } 223 //printf("[%d] e = %s\n", i, e.toChars()); 224 225 // Create scope for '$' variable for this dimension 226 auto sym = new ArrayScopeSymbol(sc, ae); 227 sym.parent = sc.scopesym; 228 sc = sc.push(sym); 229 ae.lengthVar = null; // Create it only if required 230 ae.currentDimension = i; // Dimension for $, if required 231 232 e = e.expressionSemantic(sc); 233 e = resolveProperties(sc, e); 234 235 if (ae.lengthVar && sc.func) 236 { 237 // If $ was used, declare it now 238 Expression de = new DeclarationExp(ae.loc, ae.lengthVar); 239 de = de.expressionSemantic(sc); 240 *pe0 = Expression.combine(*pe0, de); 241 } 242 sc = sc.pop(); 243 244 if (e.op == TOK.interval) 245 { 246 IntervalExp ie = cast(IntervalExp)e; 247 248 auto tiargs = new Objects(); 249 Expression edim = new IntegerExp(ae.loc, i, Type.tsize_t); 250 edim = edim.expressionSemantic(sc); 251 tiargs.push(edim); 252 253 auto fargs = new Expressions(2); 254 (*fargs)[0] = ie.lwr; 255 (*fargs)[1] = ie.upr; 256 257 uint xerrors = global.startGagging(); 258 sc = sc.push(); 259 FuncDeclaration fslice = resolveFuncCall(ae.loc, sc, slice, tiargs, ae.e1.type, fargs, FuncResolveFlag.quiet); 260 sc = sc.pop(); 261 global.endGagging(xerrors); 262 if (!fslice) 263 goto Lfallback; 264 265 e = new DotTemplateInstanceExp(ae.loc, ae.e1, slice.ident, tiargs); 266 e = new CallExp(ae.loc, e, fargs); 267 e = e.expressionSemantic(sc); 268 } 269 270 if (!e.type) 271 { 272 ae.error("`%s` has no value", e.toChars()); 273 e = new ErrorExp(); 274 } 275 if (e.op == TOK.error) 276 return e; 277 278 (*ae.arguments)[i] = e; 279 } 280 return ae; 281 } 282 283 /************************************** 284 * Runs semantic on se.lwr and se.upr. Declares a temporary variable 285 * if '$' was used. 286 * Returns: 287 * ae, or ErrorExp if errors occurred 288 */ 289 Expression resolveOpDollar(Scope* sc, ArrayExp ae, IntervalExp ie, Expression* pe0) 290 { 291 //assert(!ae.lengthVar); 292 if (!ie) 293 return ae; 294 295 VarDeclaration lengthVar = ae.lengthVar; 296 bool errors = false; 297 298 // create scope for '$' 299 auto sym = new ArrayScopeSymbol(sc, ae); 300 sym.parent = sc.scopesym; 301 sc = sc.push(sym); 302 303 Expression sem(Expression e) 304 { 305 e = e.expressionSemantic(sc); 306 e = resolveProperties(sc, e); 307 if (!e.type) 308 { 309 ae.error("`%s` has no value", e.toChars()); 310 errors = true; 311 } 312 return e; 313 } 314 315 ie.lwr = sem(ie.lwr); 316 ie.upr = sem(ie.upr); 317 318 if (lengthVar != ae.lengthVar && sc.func) 319 { 320 // If $ was used, declare it now 321 Expression de = new DeclarationExp(ae.loc, ae.lengthVar); 322 de = de.expressionSemantic(sc); 323 *pe0 = Expression.combine(*pe0, de); 324 } 325 326 sc = sc.pop(); 327 328 return errors ? new ErrorExp() : ae; 329 } 330 331 /****************************** 332 * Perform semantic() on an array of Expressions. 333 */ 334 bool arrayExpressionSemantic(Expressions* exps, Scope* sc, bool preserveErrors = false) 335 { 336 bool err = false; 337 if (exps) 338 { 339 foreach (ref e; *exps) 340 { 341 if (e) 342 { 343 auto e2 = e.expressionSemantic(sc); 344 if (e2.op == TOK.error) 345 err = true; 346 if (preserveErrors || e2.op != TOK.error) 347 e = e2; 348 } 349 } 350 } 351 return err; 352 } 353 354 /****************************** 355 * Check the tail CallExp is really property function call. 356 * Bugs: 357 * This doesn't appear to do anything. 358 */ 359 private bool checkPropertyCall(Expression e) 360 { 361 e = lastComma(e); 362 363 if (e.op == TOK.call) 364 { 365 CallExp ce = cast(CallExp)e; 366 TypeFunction tf; 367 if (ce.f) 368 { 369 tf = cast(TypeFunction)ce.f.type; 370 /* If a forward reference to ce.f, try to resolve it 371 */ 372 if (!tf.deco && ce.f.semanticRun < PASS.semanticdone) 373 { 374 ce.f.dsymbolSemantic(null); 375 tf = cast(TypeFunction)ce.f.type; 376 } 377 } 378 else if (ce.e1.type.ty == Tfunction) 379 tf = cast(TypeFunction)ce.e1.type; 380 else if (ce.e1.type.ty == Tdelegate) 381 tf = cast(TypeFunction)ce.e1.type.nextOf(); 382 else if (ce.e1.type.ty == Tpointer && ce.e1.type.nextOf().ty == Tfunction) 383 tf = cast(TypeFunction)ce.e1.type.nextOf(); 384 else 385 assert(0); 386 } 387 return false; 388 } 389 390 /****************************** 391 * Find symbol in accordance with the UFCS name look up rule 392 */ 393 private Expression searchUFCS(Scope* sc, UnaExp ue, Identifier ident) 394 { 395 //printf("searchUFCS(ident = %s)\n", ident.toChars()); 396 Loc loc = ue.loc; 397 398 // TODO: merge with Scope.search.searchScopes() 399 Dsymbol searchScopes(int flags) 400 { 401 Dsymbol s = null; 402 for (Scope* scx = sc; scx; scx = scx.enclosing) 403 { 404 if (!scx.scopesym) 405 continue; 406 if (scx.scopesym.isModule()) 407 flags |= SearchUnqualifiedModule; // tell Module.search() that SearchLocalsOnly is to be obeyed 408 s = scx.scopesym.search(loc, ident, flags); 409 if (s) 410 { 411 // overload set contains only module scope symbols. 412 if (s.isOverloadSet()) 413 break; 414 // selective/renamed imports also be picked up 415 if (AliasDeclaration ad = s.isAliasDeclaration()) 416 { 417 if (ad._import) 418 break; 419 } 420 // See only module scope symbols for UFCS target. 421 Dsymbol p = s.toParent2(); 422 if (p && p.isModule()) 423 break; 424 } 425 s = null; 426 427 // Stop when we hit a module, but keep going if that is not just under the global scope 428 if (scx.scopesym.isModule() && !(scx.enclosing && !scx.enclosing.enclosing)) 429 break; 430 } 431 return s; 432 } 433 434 int flags = 0; 435 Dsymbol s; 436 437 if (sc.flags & SCOPE.ignoresymbolvisibility) 438 flags |= IgnoreSymbolVisibility; 439 440 // First look in local scopes 441 s = searchScopes(flags | SearchLocalsOnly); 442 if (!s) 443 { 444 // Second look in imported modules 445 s = searchScopes(flags | SearchImportsOnly); 446 } 447 448 if (!s) 449 return ue.e1.type.Type.getProperty(sc, loc, ident, 0); 450 451 FuncDeclaration f = s.isFuncDeclaration(); 452 if (f) 453 { 454 TemplateDeclaration td = getFuncTemplateDecl(f); 455 if (td) 456 { 457 if (td.overroot) 458 td = td.overroot; 459 s = td; 460 } 461 } 462 463 if (ue.op == TOK.dotTemplateInstance) 464 { 465 DotTemplateInstanceExp dti = cast(DotTemplateInstanceExp)ue; 466 auto ti = new TemplateInstance(loc, s.ident, dti.ti.tiargs); 467 if (!ti.updateTempDecl(sc, s)) 468 return new ErrorExp(); 469 return new ScopeExp(loc, ti); 470 } 471 else 472 { 473 //printf("-searchUFCS() %s\n", s.toChars()); 474 return new DsymbolExp(loc, s); 475 } 476 } 477 478 /****************************** 479 * Pull out callable entity with UFCS. 480 */ 481 private Expression resolveUFCS(Scope* sc, CallExp ce) 482 { 483 Loc loc = ce.loc; 484 Expression eleft; 485 Expression e; 486 487 if (ce.e1.op == TOK.dotIdentifier) 488 { 489 DotIdExp die = cast(DotIdExp)ce.e1; 490 Identifier ident = die.ident; 491 492 Expression ex = die.semanticX(sc); 493 if (ex != die) 494 { 495 ce.e1 = ex; 496 return null; 497 } 498 eleft = die.e1; 499 500 Type t = eleft.type.toBasetype(); 501 if (t.ty == Tarray || t.ty == Tsarray || t.ty == Tnull || (t.isTypeBasic() && t.ty != Tvoid)) 502 { 503 /* Built-in types and arrays have no callable properties, so do shortcut. 504 * It is necessary in: e.init() 505 */ 506 } 507 else if (t.ty == Taarray) 508 { 509 if (ident == Id.remove) 510 { 511 /* Transform: 512 * aa.remove(arg) into delete aa[arg] 513 */ 514 if (!ce.arguments || ce.arguments.dim != 1) 515 { 516 ce.error("expected key as argument to `aa.remove()`"); 517 return new ErrorExp(); 518 } 519 if (!eleft.type.isMutable()) 520 { 521 ce.error("cannot remove key from `%s` associative array `%s`", MODtoChars(t.mod), eleft.toChars()); 522 return new ErrorExp(); 523 } 524 Expression key = (*ce.arguments)[0]; 525 key = key.expressionSemantic(sc); 526 key = resolveProperties(sc, key); 527 528 TypeAArray taa = cast(TypeAArray)t; 529 key = key.implicitCastTo(sc, taa.index); 530 531 if (key.checkValue() || key.checkSharedAccess(sc)) 532 return new ErrorExp(); 533 534 semanticTypeInfo(sc, taa.index); 535 536 return new RemoveExp(loc, eleft, key); 537 } 538 } 539 else 540 { 541 if (Expression ey = die.semanticY(sc, 1)) 542 { 543 if (ey.op == TOK.error) 544 return ey; 545 ce.e1 = ey; 546 if (isDotOpDispatch(ey)) 547 { 548 uint errors = global.startGagging(); 549 e = ce.syntaxCopy().expressionSemantic(sc); 550 if (!global.endGagging(errors)) 551 return e; 552 553 // even opDispatch and UFCS must have valid arguments, 554 // so now that we've seen indication of a problem, 555 // check them for issues. 556 Expressions* originalArguments = Expression.arraySyntaxCopy(ce.arguments); 557 558 if (arrayExpressionSemantic(originalArguments, sc)) 559 return new ErrorExp(); 560 561 /* fall down to UFCS */ 562 } 563 else 564 return null; 565 } 566 } 567 568 /* https://issues.dlang.org/show_bug.cgi?id=13953 569 * 570 * If a struct has an alias this to an associative array 571 * and remove is used on a struct instance, we have to 572 * check first if there is a remove function that can be called 573 * on the struct. If not we must check the alias this. 574 * 575 * struct A 576 * { 577 * string[string] a; 578 * alias a this; 579 * } 580 * 581 * void fun() 582 * { 583 * A s; 584 * s.remove("foo"); 585 * } 586 */ 587 const errors = global.startGagging(); 588 e = searchUFCS(sc, die, ident); 589 // if there were any errors and the identifier was remove 590 if (global.endGagging(errors)) 591 { 592 if (ident == Id.remove) 593 { 594 // check alias this 595 Expression alias_e = resolveAliasThis(sc, die.e1, 1); 596 if (alias_e && alias_e != die.e1) 597 { 598 die.e1 = alias_e; 599 CallExp ce2 = cast(CallExp)ce.syntaxCopy(); 600 ce2.e1 = die; 601 e = cast(CallExp)ce2.trySemantic(sc); 602 if (e) 603 return e; 604 } 605 } 606 // if alias this did not work out, print the initial errors 607 searchUFCS(sc, die, ident); 608 } 609 } 610 else if (ce.e1.op == TOK.dotTemplateInstance) 611 { 612 DotTemplateInstanceExp dti = cast(DotTemplateInstanceExp)ce.e1; 613 if (Expression ey = dti.semanticY(sc, 1)) 614 { 615 ce.e1 = ey; 616 return null; 617 } 618 eleft = dti.e1; 619 e = searchUFCS(sc, dti, dti.ti.name); 620 } 621 else 622 return null; 623 624 // Rewrite 625 ce.e1 = e; 626 if (!ce.arguments) 627 ce.arguments = new Expressions(); 628 ce.arguments.shift(eleft); 629 630 return null; 631 } 632 633 /****************************** 634 * Pull out property with UFCS. 635 */ 636 private Expression resolveUFCSProperties(Scope* sc, Expression e1, Expression e2 = null) 637 { 638 Loc loc = e1.loc; 639 Expression eleft; 640 Expression e; 641 642 if (e1.op == TOK.dotIdentifier) 643 { 644 DotIdExp die = cast(DotIdExp)e1; 645 eleft = die.e1; 646 e = searchUFCS(sc, die, die.ident); 647 } 648 else if (e1.op == TOK.dotTemplateInstance) 649 { 650 DotTemplateInstanceExp dti; 651 dti = cast(DotTemplateInstanceExp)e1; 652 eleft = dti.e1; 653 e = searchUFCS(sc, dti, dti.ti.name); 654 } 655 else 656 return null; 657 658 if (e is null) 659 return null; 660 661 // Rewrite 662 if (e2) 663 { 664 // run semantic without gagging 665 e2 = e2.expressionSemantic(sc); 666 667 /* f(e1) = e2 668 */ 669 Expression ex = e.copy(); 670 auto a1 = new Expressions(1); 671 (*a1)[0] = eleft; 672 ex = new CallExp(loc, ex, a1); 673 auto e1PassSemantic = ex.trySemantic(sc); 674 675 /* f(e1, e2) 676 */ 677 auto a2 = new Expressions(2); 678 (*a2)[0] = eleft; 679 (*a2)[1] = e2; 680 e = new CallExp(loc, e, a2); 681 e = e.trySemantic(sc); 682 if (!e1PassSemantic && !e) 683 { 684 /* https://issues.dlang.org/show_bug.cgi?id=20448 685 * 686 * If both versions have failed to pass semantic, 687 * f(e1) = e2 gets priority in error printing 688 * because f might be a templated function that 689 * failed to instantiate and we have to print 690 * the instantiation errors. 691 */ 692 return e1.expressionSemantic(sc); 693 } 694 else if (ex && !e) 695 { 696 checkPropertyCall(ex); 697 ex = new AssignExp(loc, ex, e2); 698 return ex.expressionSemantic(sc); 699 } 700 else 701 { 702 // strict setter prints errors if fails 703 e = e.expressionSemantic(sc); 704 } 705 checkPropertyCall(e); 706 return e; 707 } 708 else 709 { 710 /* f(e1) 711 */ 712 auto arguments = new Expressions(1); 713 (*arguments)[0] = eleft; 714 e = new CallExp(loc, e, arguments); 715 e = e.expressionSemantic(sc); 716 checkPropertyCall(e); 717 return e.expressionSemantic(sc); 718 } 719 } 720 721 /****************************** 722 * If e1 is a property function (template), resolve it. 723 */ 724 Expression resolvePropertiesOnly(Scope* sc, Expression e1) 725 { 726 //printf("e1 = %s %s\n", Token::toChars(e1.op), e1.toChars()); 727 728 Expression handleOverloadSet(OverloadSet os) 729 { 730 assert(os); 731 foreach (s; os.a) 732 { 733 auto fd = s.isFuncDeclaration(); 734 auto td = s.isTemplateDeclaration(); 735 if (fd) 736 { 737 if ((cast(TypeFunction)fd.type).isproperty) 738 return resolveProperties(sc, e1); 739 } 740 else if (td && td.onemember && (fd = td.onemember.isFuncDeclaration()) !is null) 741 { 742 if ((cast(TypeFunction)fd.type).isproperty || 743 (fd.storage_class2 & STC.property) || 744 (td._scope.stc & STC.property)) 745 return resolveProperties(sc, e1); 746 } 747 } 748 return e1; 749 } 750 751 Expression handleTemplateDecl(TemplateDeclaration td) 752 { 753 assert(td); 754 if (td.onemember) 755 { 756 if (auto fd = td.onemember.isFuncDeclaration()) 757 { 758 if ((cast(TypeFunction)fd.type).isproperty || 759 (fd.storage_class2 & STC.property) || 760 (td._scope.stc & STC.property)) 761 return resolveProperties(sc, e1); 762 } 763 } 764 return e1; 765 } 766 767 Expression handleFuncDecl(FuncDeclaration fd) 768 { 769 assert(fd); 770 if ((cast(TypeFunction)fd.type).isproperty) 771 return resolveProperties(sc, e1); 772 return e1; 773 } 774 775 if (auto de = e1.isDotExp()) 776 { 777 if (auto os = de.e2.isOverExp()) 778 return handleOverloadSet(os.vars); 779 } 780 else if (auto oe = e1.isOverExp()) 781 return handleOverloadSet(oe.vars); 782 else if (auto dti = e1.isDotTemplateInstanceExp()) 783 { 784 if (dti.ti.tempdecl) 785 if (auto td = dti.ti.tempdecl.isTemplateDeclaration()) 786 return handleTemplateDecl(td); 787 } 788 else if (auto dte = e1.isDotTemplateExp()) 789 return handleTemplateDecl(dte.td); 790 else if (e1.op == TOK.scope_) 791 { 792 Dsymbol s = (cast(ScopeExp)e1).sds; 793 TemplateInstance ti = s.isTemplateInstance(); 794 if (ti && !ti.semanticRun && ti.tempdecl) 795 if (auto td = ti.tempdecl.isTemplateDeclaration()) 796 return handleTemplateDecl(td); 797 } 798 else if (e1.op == TOK.template_) 799 return handleTemplateDecl((cast(TemplateExp)e1).td); 800 else if (e1.op == TOK.dotVariable && e1.type.ty == Tfunction) 801 { 802 DotVarExp dve = cast(DotVarExp)e1; 803 return handleFuncDecl(dve.var.isFuncDeclaration()); 804 } 805 else if (e1.op == TOK.variable && e1.type && e1.type.ty == Tfunction && (sc.intypeof || !(cast(VarExp)e1).var.needThis())) 806 return handleFuncDecl((cast(VarExp)e1).var.isFuncDeclaration()); 807 return e1; 808 } 809 810 /**************************************** 811 * Turn symbol `s` into the expression it represents. 812 * 813 * Params: 814 * s = symbol to resolve 815 * loc = location of use of `s` 816 * sc = context 817 * hasOverloads = applies if `s` represents a function. 818 * true means it's overloaded and will be resolved later, 819 * false means it's the exact function symbol. 820 * Returns: 821 * `s` turned into an expression, `ErrorExp` if an error occurred 822 */ 823 Expression symbolToExp(Dsymbol s, const ref Loc loc, Scope *sc, bool hasOverloads) 824 { 825 static if (LOGSEMANTIC) 826 { 827 printf("DsymbolExp::resolve(%s %s)\n", s.kind(), s.toChars()); 828 } 829 830 Lagain: 831 Expression e; 832 833 //printf("DsymbolExp:: %p '%s' is a symbol\n", this, toChars()); 834 //printf("s = '%s', s.kind = '%s'\n", s.toChars(), s.kind()); 835 Dsymbol olds = s; 836 Declaration d = s.isDeclaration(); 837 if (d && (d.storage_class & STC.templateparameter)) 838 { 839 s = s.toAlias(); 840 } 841 else 842 { 843 if (!s.isFuncDeclaration()) // functions are checked after overloading 844 { 845 s.checkDeprecated(loc, sc); 846 if (d) 847 d.checkDisabled(loc, sc); 848 } 849 850 // https://issues.dlang.org/show_bug.cgi?id=12023 851 // if 's' is a tuple variable, the tuple is returned. 852 s = s.toAlias(); 853 854 //printf("s = '%s', s.kind = '%s', s.needThis() = %p\n", s.toChars(), s.kind(), s.needThis()); 855 if (s != olds && !s.isFuncDeclaration()) 856 { 857 s.checkDeprecated(loc, sc); 858 if (d) 859 d.checkDisabled(loc, sc); 860 } 861 } 862 863 if (auto em = s.isEnumMember()) 864 { 865 return em.getVarExp(loc, sc); 866 } 867 if (auto v = s.isVarDeclaration()) 868 { 869 //printf("Identifier '%s' is a variable, type '%s'\n", s.toChars(), v.type.toChars()); 870 if (sc.intypeof == 1 && !v.inuse) 871 v.dsymbolSemantic(sc); 872 if (!v.type || // during variable type inference 873 !v.type.deco && v.inuse) // during variable type semantic 874 { 875 if (v.inuse) // variable type depends on the variable itself 876 error(loc, "circular reference to %s `%s`", v.kind(), v.toPrettyChars()); 877 else // variable type cannot be determined 878 error(loc, "forward reference to %s `%s`", v.kind(), v.toPrettyChars()); 879 return new ErrorExp(); 880 } 881 if (v.type.ty == Terror) 882 return new ErrorExp(); 883 884 if ((v.storage_class & STC.manifest) && v._init) 885 { 886 if (v.inuse) 887 { 888 error(loc, "circular initialization of %s `%s`", v.kind(), v.toPrettyChars()); 889 return new ErrorExp(); 890 } 891 e = v.expandInitializer(loc); 892 v.inuse++; 893 e = e.expressionSemantic(sc); 894 v.inuse--; 895 return e; 896 } 897 898 // Change the ancestor lambdas to delegate before hasThis(sc) call. 899 if (v.checkNestedReference(sc, loc)) 900 return new ErrorExp(); 901 902 if (v.needThis() && hasThis(sc)) 903 e = new DotVarExp(loc, new ThisExp(loc), v); 904 else 905 e = new VarExp(loc, v); 906 e = e.expressionSemantic(sc); 907 return e; 908 } 909 if (auto fld = s.isFuncLiteralDeclaration()) 910 { 911 //printf("'%s' is a function literal\n", fld.toChars()); 912 e = new FuncExp(loc, fld); 913 return e.expressionSemantic(sc); 914 } 915 if (auto f = s.isFuncDeclaration()) 916 { 917 f = f.toAliasFunc(); 918 if (!f.functionSemantic()) 919 return new ErrorExp(); 920 921 if (!hasOverloads && f.checkForwardRef(loc)) 922 return new ErrorExp(); 923 924 auto fd = s.isFuncDeclaration(); 925 fd.type = f.type; 926 return new VarExp(loc, fd, hasOverloads); 927 } 928 if (OverDeclaration od = s.isOverDeclaration()) 929 { 930 e = new VarExp(loc, od, true); 931 e.type = Type.tvoid; 932 return e; 933 } 934 if (OverloadSet o = s.isOverloadSet()) 935 { 936 //printf("'%s' is an overload set\n", o.toChars()); 937 return new OverExp(loc, o); 938 } 939 940 if (Import imp = s.isImport()) 941 { 942 if (!imp.pkg) 943 { 944 .error(loc, "forward reference of import `%s`", imp.toChars()); 945 return new ErrorExp(); 946 } 947 auto ie = new ScopeExp(loc, imp.pkg); 948 return ie.expressionSemantic(sc); 949 } 950 if (Package pkg = s.isPackage()) 951 { 952 auto ie = new ScopeExp(loc, pkg); 953 return ie.expressionSemantic(sc); 954 } 955 if (Module mod = s.isModule()) 956 { 957 auto ie = new ScopeExp(loc, mod); 958 return ie.expressionSemantic(sc); 959 } 960 if (Nspace ns = s.isNspace()) 961 { 962 auto ie = new ScopeExp(loc, ns); 963 return ie.expressionSemantic(sc); 964 } 965 966 if (Type t = s.getType()) 967 { 968 return (new TypeExp(loc, t)).expressionSemantic(sc); 969 } 970 971 if (TupleDeclaration tup = s.isTupleDeclaration()) 972 { 973 if (tup.needThis() && hasThis(sc)) 974 e = new DotVarExp(loc, new ThisExp(loc), tup); 975 else 976 e = new TupleExp(loc, tup); 977 e = e.expressionSemantic(sc); 978 return e; 979 } 980 981 if (TemplateInstance ti = s.isTemplateInstance()) 982 { 983 ti.dsymbolSemantic(sc); 984 if (!ti.inst || ti.errors) 985 return new ErrorExp(); 986 s = ti.toAlias(); 987 if (!s.isTemplateInstance()) 988 goto Lagain; 989 e = new ScopeExp(loc, ti); 990 e = e.expressionSemantic(sc); 991 return e; 992 } 993 if (TemplateDeclaration td = s.isTemplateDeclaration()) 994 { 995 Dsymbol p = td.toParentLocal(); 996 FuncDeclaration fdthis = hasThis(sc); 997 AggregateDeclaration ad = p ? p.isAggregateDeclaration() : null; 998 if (fdthis && ad && fdthis.isMemberLocal() == ad && (td._scope.stc & STC.static_) == 0) 999 { 1000 e = new DotTemplateExp(loc, new ThisExp(loc), td); 1001 } 1002 else 1003 e = new TemplateExp(loc, td); 1004 e = e.expressionSemantic(sc); 1005 return e; 1006 } 1007 1008 .error(loc, "%s `%s` is not a variable", s.kind(), s.toChars()); 1009 return new ErrorExp(); 1010 } 1011 1012 /************************************************************* 1013 * Given var, get the 1014 * right `this` pointer if var is in an outer class, but our 1015 * existing `this` pointer is in an inner class. 1016 * Params: 1017 * loc = location to use for error messages 1018 * sc = context 1019 * ad = struct or class we need the correct `this` for 1020 * e1 = existing `this` 1021 * var = the specific member of ad we're accessing 1022 * flag = if true, return `null` instead of throwing an error 1023 * Returns: 1024 * Expression representing the `this` for the var 1025 */ 1026 private Expression getRightThis(const ref Loc loc, Scope* sc, AggregateDeclaration ad, Expression e1, Dsymbol var, int flag = 0) 1027 { 1028 //printf("\ngetRightThis(e1 = %s, ad = %s, var = %s)\n", e1.toChars(), ad.toChars(), var.toChars()); 1029 L1: 1030 Type t = e1.type.toBasetype(); 1031 //printf("e1.type = %s, var.type = %s\n", e1.type.toChars(), var.type.toChars()); 1032 1033 if (e1.op == TOK.objcClassReference) 1034 { 1035 // We already have an Objective-C class reference, just use that as 'this'. 1036 return e1; 1037 } 1038 else if (ad && ad.isClassDeclaration && ad.isClassDeclaration.classKind == ClassKind.objc && 1039 var.isFuncDeclaration && var.isFuncDeclaration.isStatic && 1040 var.isFuncDeclaration.selector) 1041 { 1042 return new ObjcClassReferenceExp(e1.loc, cast(ClassDeclaration) ad); 1043 } 1044 1045 /* Access of a member which is a template parameter in dual-scope scenario 1046 * class A { inc(alias m)() { ++m; } } // `m` needs `this` of `B` 1047 * class B {int m; inc() { new A().inc!m(); } } 1048 */ 1049 if (e1.op == TOK.this_) 1050 { 1051 FuncDeclaration f = hasThis(sc); 1052 if (f && f.isThis2) 1053 { 1054 if (f.followInstantiationContext(ad)) 1055 { 1056 e1 = new VarExp(loc, f.vthis); 1057 e1 = new PtrExp(loc, e1); 1058 e1 = new IndexExp(loc, e1, IntegerExp.literal!1); 1059 e1 = getThisSkipNestedFuncs(loc, sc, f.toParent2(), ad, e1, t, var); 1060 if (e1.op == TOK.error) 1061 return e1; 1062 goto L1; 1063 } 1064 } 1065 } 1066 1067 /* If e1 is not the 'this' pointer for ad 1068 */ 1069 if (ad && 1070 !(t.ty == Tpointer && t.nextOf().ty == Tstruct && (cast(TypeStruct)t.nextOf()).sym == ad) && 1071 !(t.ty == Tstruct && (cast(TypeStruct)t).sym == ad)) 1072 { 1073 ClassDeclaration cd = ad.isClassDeclaration(); 1074 ClassDeclaration tcd = t.isClassHandle(); 1075 1076 /* e1 is the right this if ad is a base class of e1 1077 */ 1078 if (!cd || !tcd || !(tcd == cd || cd.isBaseOf(tcd, null))) 1079 { 1080 /* Only classes can be inner classes with an 'outer' 1081 * member pointing to the enclosing class instance 1082 */ 1083 if (tcd && tcd.isNested()) 1084 { 1085 /* e1 is the 'this' pointer for an inner class: tcd. 1086 * Rewrite it as the 'this' pointer for the outer class. 1087 */ 1088 auto vthis = tcd.followInstantiationContext(ad) ? tcd.vthis2 : tcd.vthis; 1089 e1 = new DotVarExp(loc, e1, vthis); 1090 e1.type = vthis.type; 1091 e1.type = e1.type.addMod(t.mod); 1092 // Do not call ensureStaticLinkTo() 1093 //e1 = e1.semantic(sc); 1094 1095 // Skip up over nested functions, and get the enclosing 1096 // class type. 1097 e1 = getThisSkipNestedFuncs(loc, sc, tcd.toParentP(ad), ad, e1, t, var); 1098 if (e1.op == TOK.error) 1099 return e1; 1100 goto L1; 1101 } 1102 1103 /* Can't find a path from e1 to ad 1104 */ 1105 if (flag) 1106 return null; 1107 e1.error("`this` for `%s` needs to be type `%s` not type `%s`", var.toChars(), ad.toChars(), t.toChars()); 1108 return new ErrorExp(); 1109 } 1110 } 1111 return e1; 1112 } 1113 1114 /*************************************** 1115 * Pull out any properties. 1116 */ 1117 private Expression resolvePropertiesX(Scope* sc, Expression e1, Expression e2 = null) 1118 { 1119 //printf("resolvePropertiesX, e1 = %s %s, e2 = %s\n", Token.toChars(e1.op), e1.toChars(), e2 ? e2.toChars() : null); 1120 Loc loc = e1.loc; 1121 1122 OverloadSet os; 1123 Dsymbol s; 1124 Objects* tiargs; 1125 Type tthis; 1126 if (e1.op == TOK.dot) 1127 { 1128 DotExp de = cast(DotExp)e1; 1129 if (de.e2.op == TOK.overloadSet) 1130 { 1131 tiargs = null; 1132 tthis = de.e1.type; 1133 os = (cast(OverExp)de.e2).vars; 1134 goto Los; 1135 } 1136 } 1137 else if (e1.op == TOK.overloadSet) 1138 { 1139 tiargs = null; 1140 tthis = null; 1141 os = (cast(OverExp)e1).vars; 1142 Los: 1143 assert(os); 1144 FuncDeclaration fd = null; 1145 if (e2) 1146 { 1147 e2 = e2.expressionSemantic(sc); 1148 if (e2.op == TOK.error) 1149 return new ErrorExp(); 1150 e2 = resolveProperties(sc, e2); 1151 1152 Expressions a; 1153 a.push(e2); 1154 1155 for (size_t i = 0; i < os.a.dim; i++) 1156 { 1157 if (FuncDeclaration f = resolveFuncCall(loc, sc, os.a[i], tiargs, tthis, &a, FuncResolveFlag.quiet)) 1158 { 1159 if (f.errors) 1160 return new ErrorExp(); 1161 fd = f; 1162 assert(fd.type.ty == Tfunction); 1163 } 1164 } 1165 if (fd) 1166 { 1167 Expression e = new CallExp(loc, e1, e2); 1168 return e.expressionSemantic(sc); 1169 } 1170 } 1171 { 1172 for (size_t i = 0; i < os.a.dim; i++) 1173 { 1174 if (FuncDeclaration f = resolveFuncCall(loc, sc, os.a[i], tiargs, tthis, null, FuncResolveFlag.quiet)) 1175 { 1176 if (f.errors) 1177 return new ErrorExp(); 1178 fd = f; 1179 assert(fd.type.ty == Tfunction); 1180 TypeFunction tf = cast(TypeFunction)fd.type; 1181 if (!tf.isref && e2) 1182 { 1183 error(loc, "%s is not an lvalue", e1.toChars()); 1184 return new ErrorExp(); 1185 } 1186 } 1187 } 1188 if (fd) 1189 { 1190 Expression e = new CallExp(loc, e1); 1191 if (e2) 1192 e = new AssignExp(loc, e, e2); 1193 return e.expressionSemantic(sc); 1194 } 1195 } 1196 if (e2) 1197 goto Leprop; 1198 } 1199 else if (e1.op == TOK.dotTemplateInstance) 1200 { 1201 DotTemplateInstanceExp dti = cast(DotTemplateInstanceExp)e1; 1202 if (!dti.findTempDecl(sc)) 1203 goto Leprop; 1204 if (!dti.ti.semanticTiargs(sc)) 1205 goto Leprop; 1206 tiargs = dti.ti.tiargs; 1207 tthis = dti.e1.type; 1208 if ((os = dti.ti.tempdecl.isOverloadSet()) !is null) 1209 goto Los; 1210 if ((s = dti.ti.tempdecl) !is null) 1211 goto Lfd; 1212 } 1213 else if (e1.op == TOK.dotTemplateDeclaration) 1214 { 1215 DotTemplateExp dte = cast(DotTemplateExp)e1; 1216 s = dte.td; 1217 tiargs = null; 1218 tthis = dte.e1.type; 1219 goto Lfd; 1220 } 1221 else if (e1.op == TOK.scope_) 1222 { 1223 s = (cast(ScopeExp)e1).sds; 1224 TemplateInstance ti = s.isTemplateInstance(); 1225 if (ti && !ti.semanticRun && ti.tempdecl) 1226 { 1227 //assert(ti.needsTypeInference(sc)); 1228 if (!ti.semanticTiargs(sc)) 1229 goto Leprop; 1230 tiargs = ti.tiargs; 1231 tthis = null; 1232 if ((os = ti.tempdecl.isOverloadSet()) !is null) 1233 goto Los; 1234 if ((s = ti.tempdecl) !is null) 1235 goto Lfd; 1236 } 1237 } 1238 else if (e1.op == TOK.template_) 1239 { 1240 s = (cast(TemplateExp)e1).td; 1241 tiargs = null; 1242 tthis = null; 1243 goto Lfd; 1244 } 1245 else if (e1.op == TOK.dotVariable && e1.type && e1.type.toBasetype().ty == Tfunction) 1246 { 1247 DotVarExp dve = cast(DotVarExp)e1; 1248 s = dve.var.isFuncDeclaration(); 1249 tiargs = null; 1250 tthis = dve.e1.type; 1251 goto Lfd; 1252 } 1253 else if (e1.op == TOK.variable && e1.type && e1.type.toBasetype().ty == Tfunction) 1254 { 1255 s = (cast(VarExp)e1).var.isFuncDeclaration(); 1256 tiargs = null; 1257 tthis = null; 1258 Lfd: 1259 assert(s); 1260 if (e2) 1261 { 1262 e2 = e2.expressionSemantic(sc); 1263 if (e2.op == TOK.error) 1264 return new ErrorExp(); 1265 e2 = resolveProperties(sc, e2); 1266 1267 Expressions a; 1268 a.push(e2); 1269 1270 FuncDeclaration fd = resolveFuncCall(loc, sc, s, tiargs, tthis, &a, FuncResolveFlag.quiet); 1271 if (fd && fd.type) 1272 { 1273 if (fd.errors) 1274 return new ErrorExp(); 1275 assert(fd.type.ty == Tfunction); 1276 Expression e = new CallExp(loc, e1, e2); 1277 return e.expressionSemantic(sc); 1278 } 1279 } 1280 { 1281 FuncDeclaration fd = resolveFuncCall(loc, sc, s, tiargs, tthis, null, FuncResolveFlag.quiet); 1282 if (fd && fd.type) 1283 { 1284 if (fd.errors) 1285 return new ErrorExp(); 1286 assert(fd.type.ty == Tfunction); 1287 TypeFunction tf = cast(TypeFunction)fd.type; 1288 if (!e2 || tf.isref) 1289 { 1290 Expression e = new CallExp(loc, e1); 1291 if (e2) 1292 e = new AssignExp(loc, e, e2); 1293 return e.expressionSemantic(sc); 1294 } 1295 } 1296 } 1297 if (FuncDeclaration fd = s.isFuncDeclaration()) 1298 { 1299 // Keep better diagnostic message for invalid property usage of functions 1300 assert(fd.type.ty == Tfunction); 1301 Expression e = new CallExp(loc, e1, e2); 1302 return e.expressionSemantic(sc); 1303 } 1304 if (e2) 1305 goto Leprop; 1306 } 1307 if (e1.op == TOK.variable) 1308 { 1309 VarExp ve = cast(VarExp)e1; 1310 VarDeclaration v = ve.var.isVarDeclaration(); 1311 if (v && ve.checkPurity(sc, v)) 1312 return new ErrorExp(); 1313 } 1314 if (e2) 1315 return null; 1316 1317 if (e1.type && e1.op != TOK.type) // function type is not a property 1318 { 1319 /* Look for e1 being a lazy parameter; rewrite as delegate call 1320 * only if the symbol wasn't already treated as a delegate 1321 */ 1322 auto ve = e1.isVarExp(); 1323 if (ve && ve.var.storage_class & STC.lazy_ && !ve.delegateWasExtracted) 1324 { 1325 Expression e = new CallExp(loc, e1); 1326 return e.expressionSemantic(sc); 1327 } 1328 else if (e1.op == TOK.dotVariable) 1329 { 1330 // Check for reading overlapped pointer field in @safe code. 1331 if (checkUnsafeAccess(sc, e1, true, true)) 1332 return new ErrorExp(); 1333 } 1334 else if (e1.op == TOK.dot) 1335 { 1336 e1.error("expression has no value"); 1337 return new ErrorExp(); 1338 } 1339 else if (e1.op == TOK.call) 1340 { 1341 CallExp ce = cast(CallExp)e1; 1342 // Check for reading overlapped pointer field in @safe code. 1343 if (checkUnsafeAccess(sc, ce.e1, true, true)) 1344 return new ErrorExp(); 1345 } 1346 } 1347 1348 if (!e1.type) 1349 { 1350 error(loc, "cannot resolve type for %s", e1.toChars()); 1351 e1 = new ErrorExp(); 1352 } 1353 return e1; 1354 1355 Leprop: 1356 error(loc, "not a property %s", e1.toChars()); 1357 return new ErrorExp(); 1358 } 1359 1360 extern (C++) Expression resolveProperties(Scope* sc, Expression e) 1361 { 1362 //printf("resolveProperties(%s)\n", e.toChars()); 1363 e = resolvePropertiesX(sc, e); 1364 if (e.checkRightThis(sc)) 1365 return new ErrorExp(); 1366 return e; 1367 } 1368 1369 /**************************************** 1370 * The common type is determined by applying ?: to each pair. 1371 * Output: 1372 * exps[] properties resolved, implicitly cast to common type, rewritten in place 1373 * *pt if pt is not NULL, set to the common type 1374 * Returns: 1375 * true a semantic error was detected 1376 */ 1377 private bool arrayExpressionToCommonType(Scope* sc, Expressions* exps, Type* pt) 1378 { 1379 /* Still have a problem with: 1380 * ubyte[][] = [ cast(ubyte[])"hello", [1]]; 1381 * which works if the array literal is initialized top down with the ubyte[][] 1382 * type, but fails with this function doing bottom up typing. 1383 */ 1384 1385 //printf("arrayExpressionToCommonType()\n"); 1386 scope IntegerExp integerexp = IntegerExp.literal!0; 1387 scope CondExp condexp = new CondExp(Loc.initial, integerexp, null, null); 1388 1389 Type t0 = null; 1390 Expression e0 = null; 1391 size_t j0 = ~0; 1392 bool foundType; 1393 1394 for (size_t i = 0; i < exps.dim; i++) 1395 { 1396 Expression e = (*exps)[i]; 1397 if (!e) 1398 continue; 1399 1400 e = resolveProperties(sc, e); 1401 if (!e.type) 1402 { 1403 e.error("`%s` has no value", e.toChars()); 1404 t0 = Type.terror; 1405 continue; 1406 } 1407 if (e.op == TOK.type) 1408 { 1409 foundType = true; // do not break immediately, there might be more errors 1410 e.checkValue(); // report an error "type T has no value" 1411 t0 = Type.terror; 1412 continue; 1413 } 1414 if (e.type.ty == Tvoid) 1415 { 1416 // void expressions do not concur to the determination of the common 1417 // type. 1418 continue; 1419 } 1420 if (checkNonAssignmentArrayOp(e)) 1421 { 1422 t0 = Type.terror; 1423 continue; 1424 } 1425 1426 e = doCopyOrMove(sc, e); 1427 1428 if (!foundType && t0 && !t0.equals(e.type)) 1429 { 1430 /* This applies ?: to merge the types. It's backwards; 1431 * ?: should call this function to merge types. 1432 */ 1433 condexp.type = null; 1434 condexp.e1 = e0; 1435 condexp.e2 = e; 1436 condexp.loc = e.loc; 1437 Expression ex = condexp.expressionSemantic(sc); 1438 if (ex.op == TOK.error) 1439 e = ex; 1440 else 1441 { 1442 (*exps)[j0] = condexp.e1; 1443 e = condexp.e2; 1444 } 1445 } 1446 j0 = i; 1447 e0 = e; 1448 t0 = e.type; 1449 if (e.op != TOK.error) 1450 (*exps)[i] = e; 1451 } 1452 1453 if (!t0) 1454 t0 = Type.tvoid; // [] is typed as void[] 1455 else if (t0.ty != Terror) 1456 { 1457 for (size_t i = 0; i < exps.dim; i++) 1458 { 1459 Expression e = (*exps)[i]; 1460 if (!e) 1461 continue; 1462 1463 e = e.implicitCastTo(sc, t0); 1464 //assert(e.op != TOK.error); 1465 if (e.op == TOK.error) 1466 { 1467 /* https://issues.dlang.org/show_bug.cgi?id=13024 1468 * a workaround for the bug in typeMerge - 1469 * it should paint e1 and e2 by deduced common type, 1470 * but doesn't in this particular case. 1471 */ 1472 t0 = Type.terror; 1473 break; 1474 } 1475 (*exps)[i] = e; 1476 } 1477 } 1478 if (pt) 1479 *pt = t0; 1480 1481 return (t0 == Type.terror); 1482 } 1483 1484 private Expression opAssignToOp(const ref Loc loc, TOK op, Expression e1, Expression e2) 1485 { 1486 Expression e; 1487 switch (op) 1488 { 1489 case TOK.addAssign: 1490 e = new AddExp(loc, e1, e2); 1491 break; 1492 1493 case TOK.minAssign: 1494 e = new MinExp(loc, e1, e2); 1495 break; 1496 1497 case TOK.mulAssign: 1498 e = new MulExp(loc, e1, e2); 1499 break; 1500 1501 case TOK.divAssign: 1502 e = new DivExp(loc, e1, e2); 1503 break; 1504 1505 case TOK.modAssign: 1506 e = new ModExp(loc, e1, e2); 1507 break; 1508 1509 case TOK.andAssign: 1510 e = new AndExp(loc, e1, e2); 1511 break; 1512 1513 case TOK.orAssign: 1514 e = new OrExp(loc, e1, e2); 1515 break; 1516 1517 case TOK.xorAssign: 1518 e = new XorExp(loc, e1, e2); 1519 break; 1520 1521 case TOK.leftShiftAssign: 1522 e = new ShlExp(loc, e1, e2); 1523 break; 1524 1525 case TOK.rightShiftAssign: 1526 e = new ShrExp(loc, e1, e2); 1527 break; 1528 1529 case TOK.unsignedRightShiftAssign: 1530 e = new UshrExp(loc, e1, e2); 1531 break; 1532 1533 default: 1534 assert(0); 1535 } 1536 return e; 1537 } 1538 1539 /********************* 1540 * Rewrite: 1541 * array.length op= e2 1542 * as: 1543 * array.length = array.length op e2 1544 * or: 1545 * auto tmp = &array; 1546 * (*tmp).length = (*tmp).length op e2 1547 */ 1548 private Expression rewriteOpAssign(BinExp exp) 1549 { 1550 Expression e; 1551 1552 assert(exp.e1.op == TOK.arrayLength); 1553 ArrayLengthExp ale = cast(ArrayLengthExp)exp.e1; 1554 if (ale.e1.op == TOK.variable) 1555 { 1556 e = opAssignToOp(exp.loc, exp.op, ale, exp.e2); 1557 e = new AssignExp(exp.loc, ale.syntaxCopy(), e); 1558 } 1559 else 1560 { 1561 /* auto tmp = &array; 1562 * (*tmp).length = (*tmp).length op e2 1563 */ 1564 auto tmp = copyToTemp(0, "__arraylength", new AddrExp(ale.loc, ale.e1)); 1565 1566 Expression e1 = new ArrayLengthExp(ale.loc, new PtrExp(ale.loc, new VarExp(ale.loc, tmp))); 1567 Expression elvalue = e1.syntaxCopy(); 1568 e = opAssignToOp(exp.loc, exp.op, e1, exp.e2); 1569 e = new AssignExp(exp.loc, elvalue, e); 1570 e = new CommaExp(exp.loc, new DeclarationExp(ale.loc, tmp), e); 1571 } 1572 return e; 1573 } 1574 1575 /**************************************** 1576 * Preprocess arguments to function. 1577 * Input: 1578 * reportErrors whether or not to report errors here. Some callers are not 1579 * checking actual function params, so they'll do their own error reporting 1580 * Output: 1581 * exps[] tuples expanded, properties resolved, rewritten in place 1582 * Returns: 1583 * true a semantic error occurred 1584 */ 1585 private bool preFunctionParameters(Scope* sc, Expressions* exps, const bool reportErrors = true) 1586 { 1587 bool err = false; 1588 if (exps) 1589 { 1590 expandTuples(exps); 1591 1592 for (size_t i = 0; i < exps.dim; i++) 1593 { 1594 Expression arg = (*exps)[i]; 1595 arg = resolveProperties(sc, arg); 1596 if (arg.op == TOK.type) 1597 { 1598 // for static alias this: https://issues.dlang.org/show_bug.cgi?id=17684 1599 arg = resolveAliasThis(sc, arg); 1600 1601 if (arg.op == TOK.type) 1602 { 1603 if (reportErrors) 1604 { 1605 arg.error("cannot pass type `%s` as a function argument", arg.toChars()); 1606 arg = new ErrorExp(); 1607 } 1608 err = true; 1609 } 1610 } 1611 else if (arg.type.toBasetype().ty == Tfunction) 1612 { 1613 if (reportErrors) 1614 { 1615 arg.error("cannot pass function `%s` as a function argument", arg.toChars()); 1616 arg = new ErrorExp(); 1617 } 1618 err = true; 1619 } 1620 else if (checkNonAssignmentArrayOp(arg)) 1621 { 1622 arg = new ErrorExp(); 1623 err = true; 1624 } 1625 (*exps)[i] = arg; 1626 } 1627 } 1628 return err; 1629 } 1630 1631 /******************************************** 1632 * Issue an error if default construction is disabled for type t. 1633 * Default construction is required for arrays and 'out' parameters. 1634 * Returns: 1635 * true an error was issued 1636 */ 1637 private bool checkDefCtor(Loc loc, Type t) 1638 { 1639 t = t.baseElemOf(); 1640 if (t.ty == Tstruct) 1641 { 1642 StructDeclaration sd = (cast(TypeStruct)t).sym; 1643 if (sd.noDefaultCtor) 1644 { 1645 sd.error(loc, "default construction is disabled"); 1646 return true; 1647 } 1648 } 1649 return false; 1650 } 1651 1652 /**************************************** 1653 * Now that we know the exact type of the function we're calling, 1654 * the arguments[] need to be adjusted: 1655 * 1. implicitly convert argument to the corresponding parameter type 1656 * 2. add default arguments for any missing arguments 1657 * 3. do default promotions on arguments corresponding to ... 1658 * 4. add hidden _arguments[] argument 1659 * 5. call copy constructor for struct value arguments 1660 * Params: 1661 * loc = location of function call 1662 * sc = context 1663 * tf = type of the function 1664 * ethis = `this` argument, `null` if none or not known 1665 * tthis = type of `this` argument, `null` if no `this` argument 1666 * arguments = array of actual arguments to function call 1667 * fd = the function being called, `null` if called indirectly 1668 * prettype = set to return type of function 1669 * peprefix = set to expression to execute before `arguments[]` are evaluated, `null` if none 1670 * Returns: 1671 * true errors happened 1672 */ 1673 private bool functionParameters(const ref Loc loc, Scope* sc, 1674 TypeFunction tf, Expression ethis, Type tthis, Expressions* arguments, FuncDeclaration fd, 1675 Type* prettype, Expression* peprefix) 1676 { 1677 //printf("functionParameters() %s\n", fd ? fd.toChars() : ""); 1678 assert(arguments); 1679 assert(fd || tf.next); 1680 size_t nargs = arguments ? arguments.dim : 0; 1681 const size_t nparams = tf.parameterList.length; 1682 const olderrors = global.errors; 1683 bool err = false; 1684 *prettype = Type.terror; 1685 Expression eprefix = null; 1686 *peprefix = null; 1687 1688 if (nargs > nparams && tf.parameterList.varargs == VarArg.none) 1689 { 1690 error(loc, "expected %llu arguments, not %llu for non-variadic function type `%s`", cast(ulong)nparams, cast(ulong)nargs, tf.toChars()); 1691 return true; 1692 } 1693 1694 // If inferring return type, and semantic3() needs to be run if not already run 1695 if (!tf.next && fd.inferRetType) 1696 { 1697 fd.functionSemantic(); 1698 } 1699 else if (fd && fd.parent) 1700 { 1701 TemplateInstance ti = fd.parent.isTemplateInstance(); 1702 if (ti && ti.tempdecl) 1703 { 1704 fd.functionSemantic3(); 1705 } 1706 } 1707 const isCtorCall = fd && fd.needThis() && fd.isCtorDeclaration(); 1708 1709 const size_t n = (nargs > nparams) ? nargs : nparams; // n = max(nargs, nparams) 1710 1711 /* If the function return type has wildcards in it, we'll need to figure out the actual type 1712 * based on the actual argument types. 1713 * Start with the `this` argument, later on merge into wildmatch the mod bits of the rest 1714 * of the arguments. 1715 */ 1716 MOD wildmatch = (tthis && !isCtorCall) ? tthis.Type.deduceWild(tf, false) : 0; 1717 1718 bool done = false; 1719 foreach (const i; 0 .. n) 1720 { 1721 Expression arg = (i < nargs) ? (*arguments)[i] : null; 1722 1723 if (i < nparams) 1724 { 1725 bool errorArgs() 1726 { 1727 error(loc, "expected %llu function arguments, not %llu", cast(ulong)nparams, cast(ulong)nargs); 1728 return true; 1729 } 1730 1731 Parameter p = tf.parameterList[i]; 1732 const bool isRef = (p.storageClass & (STC.ref_ | STC.out_)) != 0; 1733 1734 if (!arg) 1735 { 1736 if (!p.defaultArg) 1737 { 1738 if (tf.parameterList.varargs == VarArg.typesafe && i + 1 == nparams) 1739 goto L2; 1740 return errorArgs(); 1741 } 1742 arg = p.defaultArg; 1743 arg = inlineCopy(arg, sc); 1744 // __FILE__, __LINE__, __MODULE__, __FUNCTION__, and __PRETTY_FUNCTION__ 1745 arg = arg.resolveLoc(loc, sc); 1746 arguments.push(arg); 1747 nargs++; 1748 } 1749 else 1750 { 1751 if (arg.op == TOK.default_) 1752 { 1753 arg = arg.resolveLoc(loc, sc); 1754 (*arguments)[i] = arg; 1755 } 1756 } 1757 1758 1759 if (isRef && !p.type.isConst && !p.type.isImmutable 1760 && (p.storageClass & STC.const_) != STC.const_ 1761 && (p.storageClass & STC.immutable_) != STC.immutable_ 1762 && checkIfIsStructLiteralDotExpr(arg)) 1763 break; 1764 1765 if (tf.parameterList.varargs == VarArg.typesafe && i + 1 == nparams) // https://dlang.org/spec/function.html#variadic 1766 { 1767 //printf("\t\tvarargs == 2, p.type = '%s'\n", p.type.toChars()); 1768 { 1769 MATCH m; 1770 if ((m = arg.implicitConvTo(p.type)) > MATCH.nomatch) 1771 { 1772 if (p.type.nextOf() && arg.implicitConvTo(p.type.nextOf()) >= m) 1773 goto L2; 1774 else if (nargs != nparams) 1775 return errorArgs(); 1776 goto L1; 1777 } 1778 } 1779 L2: 1780 Type tb = p.type.toBasetype(); 1781 switch (tb.ty) 1782 { 1783 case Tsarray: 1784 case Tarray: 1785 { 1786 /* Create a static array variable v of type arg.type: 1787 * T[dim] __arrayArg = [ arguments[i], ..., arguments[nargs-1] ]; 1788 * 1789 * The array literal in the initializer of the hidden variable 1790 * is now optimized. 1791 * https://issues.dlang.org/show_bug.cgi?id=2356 1792 */ 1793 Type tbn = (cast(TypeArray)tb).next; // array element type 1794 Type tret = p.isLazyArray(); 1795 1796 auto elements = new Expressions(nargs - i); 1797 foreach (u; 0 .. elements.dim) 1798 { 1799 Expression a = (*arguments)[i + u]; 1800 if (tret && a.implicitConvTo(tret)) 1801 { 1802 // p is a lazy array of delegates, tret is return type of the delegates 1803 a = a.implicitCastTo(sc, tret) 1804 .optimize(WANTvalue) 1805 .toDelegate(tret, sc); 1806 } 1807 else 1808 a = a.implicitCastTo(sc, tbn); 1809 a = a.addDtorHook(sc); 1810 (*elements)[u] = a; 1811 } 1812 // https://issues.dlang.org/show_bug.cgi?id=14395 1813 // Convert to a static array literal, or its slice. 1814 arg = new ArrayLiteralExp(loc, tbn.sarrayOf(nargs - i), elements); 1815 if (tb.ty == Tarray) 1816 { 1817 arg = new SliceExp(loc, arg, null, null); 1818 arg.type = p.type; 1819 } 1820 break; 1821 } 1822 case Tclass: 1823 { 1824 /* Set arg to be: 1825 * new Tclass(arg0, arg1, ..., argn) 1826 */ 1827 auto args = new Expressions(nargs - i); 1828 foreach (u; i .. nargs) 1829 (*args)[u - i] = (*arguments)[u]; 1830 arg = new NewExp(loc, null, null, p.type, args); 1831 break; 1832 } 1833 default: 1834 if (!arg) 1835 { 1836 error(loc, "not enough arguments"); 1837 return true; 1838 } 1839 break; 1840 } 1841 arg = arg.expressionSemantic(sc); 1842 //printf("\targ = '%s'\n", arg.toChars()); 1843 arguments.setDim(i + 1); 1844 (*arguments)[i] = arg; 1845 nargs = i + 1; 1846 done = true; 1847 } 1848 1849 L1: 1850 if (!(p.storageClass & STC.lazy_ && p.type.ty == Tvoid)) 1851 { 1852 1853 if (ubyte wm = arg.type.deduceWild(p.type, isRef)) 1854 { 1855 wildmatch = wildmatch ? MODmerge(wildmatch, wm) : wm; 1856 //printf("[%d] p = %s, a = %s, wm = %d, wildmatch = %d\n", i, p.type.toChars(), arg.type.toChars(), wm, wildmatch); 1857 } 1858 } 1859 } 1860 if (done) 1861 break; 1862 } 1863 if ((wildmatch == MODFlags.mutable || wildmatch == MODFlags.immutable_) && 1864 tf.next && tf.next.hasWild() && 1865 (tf.isref || !tf.next.implicitConvTo(tf.next.immutableOf()))) 1866 { 1867 bool errorInout(MOD wildmatch) 1868 { 1869 const(char)* s = wildmatch == MODFlags.mutable ? "mutable" : MODtoChars(wildmatch); 1870 error(loc, "modify `inout` to `%s` is not allowed inside `inout` function", s); 1871 return true; 1872 } 1873 1874 if (fd) 1875 { 1876 /* If the called function may return the reference to 1877 * outer inout data, it should be rejected. 1878 * 1879 * void foo(ref inout(int) x) { 1880 * ref inout(int) bar(inout(int)) { return x; } 1881 * struct S { 1882 * ref inout(int) bar() inout { return x; } 1883 * ref inout(int) baz(alias a)() inout { return x; } 1884 * } 1885 * bar(int.init) = 1; // bad! 1886 * S().bar() = 1; // bad! 1887 * } 1888 * void test() { 1889 * int a; 1890 * auto s = foo(a); 1891 * s.baz!a() = 1; // bad! 1892 * } 1893 * 1894 */ 1895 bool checkEnclosingWild(Dsymbol s) 1896 { 1897 bool checkWild(Dsymbol s) 1898 { 1899 if (!s) 1900 return false; 1901 if (auto ad = s.isAggregateDeclaration()) 1902 { 1903 if (ad.isNested()) 1904 return checkEnclosingWild(s); 1905 } 1906 else if (auto ff = s.isFuncDeclaration()) 1907 { 1908 if ((cast(TypeFunction)ff.type).iswild) 1909 return errorInout(wildmatch); 1910 1911 if (ff.isNested() || ff.isThis()) 1912 return checkEnclosingWild(s); 1913 } 1914 return false; 1915 } 1916 1917 Dsymbol ctx0 = s.toParent2(); 1918 Dsymbol ctx1 = s.toParentLocal(); 1919 if (checkWild(ctx0)) 1920 return true; 1921 if (ctx0 != ctx1) 1922 return checkWild(ctx1); 1923 return false; 1924 } 1925 if ((fd.isThis() || fd.isNested()) && checkEnclosingWild(fd)) 1926 return true; 1927 } 1928 else if (tf.isWild()) 1929 return errorInout(wildmatch); 1930 } 1931 1932 Expression firstArg = ((tf.next && tf.next.ty == Tvoid || isCtorCall) && 1933 tthis && 1934 tthis.isMutable() && tthis.toBasetype().ty == Tstruct && 1935 tthis.hasPointers()) 1936 ? ethis : null; 1937 1938 assert(nargs >= nparams); 1939 foreach (const i, arg; (*arguments)[0 .. nargs]) 1940 { 1941 assert(arg); 1942 if (i < nparams) 1943 { 1944 Parameter p = tf.parameterList[i]; 1945 Type targ = arg.type; // keep original type for isCopyable() because alias this 1946 // resolution may hide an uncopyable type 1947 1948 if (!(p.storageClass & STC.lazy_ && p.type.ty == Tvoid)) 1949 { 1950 Type tprm = p.type.hasWild() 1951 ? p.type.substWildTo(wildmatch) 1952 : p.type; 1953 1954 const hasCopyCtor = (arg.type.ty == Tstruct) && (cast(TypeStruct)arg.type).sym.hasCopyCtor; 1955 const typesMatch = arg.type.mutableOf().unSharedOf().equals(tprm.mutableOf().unSharedOf()); 1956 if (!((hasCopyCtor && typesMatch) || tprm.equals(arg.type))) 1957 { 1958 //printf("arg.type = %s, p.type = %s\n", arg.type.toChars(), p.type.toChars()); 1959 arg = arg.implicitCastTo(sc, tprm); 1960 arg = arg.optimize(WANTvalue, (p.storageClass & (STC.ref_ | STC.out_)) != 0); 1961 } 1962 } 1963 if (p.storageClass & STC.ref_) 1964 { 1965 if (global.params.rvalueRefParam && 1966 !arg.isLvalue() && 1967 targ.isCopyable()) 1968 { /* allow rvalues to be passed to ref parameters by copying 1969 * them to a temp, then pass the temp as the argument 1970 */ 1971 auto v = copyToTemp(0, "__rvalue", arg); 1972 Expression ev = new DeclarationExp(arg.loc, v); 1973 ev = new CommaExp(arg.loc, ev, new VarExp(arg.loc, v)); 1974 arg = ev.expressionSemantic(sc); 1975 } 1976 arg = arg.toLvalue(sc, arg); 1977 1978 // Look for mutable misaligned pointer, etc., in @safe mode 1979 err |= checkUnsafeAccess(sc, arg, false, true); 1980 } 1981 else if (p.storageClass & STC.out_) 1982 { 1983 Type t = arg.type; 1984 if (!t.isMutable() || !t.isAssignable()) // check blit assignable 1985 { 1986 arg.error("cannot modify struct `%s` with immutable members", arg.toChars()); 1987 err = true; 1988 } 1989 else 1990 { 1991 // Look for misaligned pointer, etc., in @safe mode 1992 err |= checkUnsafeAccess(sc, arg, false, true); 1993 err |= checkDefCtor(arg.loc, t); // t must be default constructible 1994 } 1995 arg = arg.toLvalue(sc, arg); 1996 } 1997 else if (p.storageClass & STC.lazy_) 1998 { 1999 // Convert lazy argument to a delegate 2000 auto t = (p.type.ty == Tvoid) ? p.type : arg.type; 2001 arg = toDelegate(arg, t, sc); 2002 } 2003 //printf("arg: %s\n", arg.toChars()); 2004 //printf("type: %s\n", arg.type.toChars()); 2005 //printf("param: %s\n", p.toChars()); 2006 2007 if (firstArg && p.storageClass & STC.return_) 2008 { 2009 /* Argument value can be assigned to firstArg. 2010 * Check arg to see if it matters. 2011 */ 2012 if (global.params.vsafe) 2013 err |= checkParamArgumentReturn(sc, firstArg, arg, false); 2014 } 2015 else if (tf.parameterEscapes(tthis, p)) 2016 { 2017 /* Argument value can escape from the called function. 2018 * Check arg to see if it matters. 2019 */ 2020 if (global.params.vsafe) 2021 err |= checkParamArgumentEscape(sc, fd, p, arg, false, false); 2022 } 2023 else 2024 { 2025 /* Argument value cannot escape from the called function. 2026 */ 2027 Expression a = arg; 2028 if (a.op == TOK.cast_) 2029 a = (cast(CastExp)a).e1; 2030 2031 ArrayLiteralExp ale; 2032 if (p.type.toBasetype().ty == Tarray && !(p.storageClass & STC.return_) && 2033 (ale = a.isArrayLiteralExp()) !is null) 2034 { 2035 // allocate the array literal as temporary static array on the stack 2036 ale.type = ale.type.nextOf().sarrayOf(ale.elements.length); 2037 auto tmp = copyToTemp(0, "__arrayliteral_on_stack", ale); 2038 auto declareTmp = new DeclarationExp(ale.loc, tmp); 2039 auto castToSlice = new CastExp(ale.loc, new VarExp(ale.loc, tmp), p.type); 2040 arg = CommaExp.combine(declareTmp, castToSlice); 2041 arg = arg.expressionSemantic(sc); 2042 } 2043 else if (a.op == TOK.function_) 2044 { 2045 /* Function literals can only appear once, so if this 2046 * appearance was scoped, there cannot be any others. 2047 */ 2048 FuncExp fe = cast(FuncExp)a; 2049 fe.fd.tookAddressOf = 0; 2050 } 2051 else if (a.op == TOK.delegate_) 2052 { 2053 /* For passing a delegate to a scoped parameter, 2054 * this doesn't count as taking the address of it. 2055 * We only worry about 'escaping' references to the function. 2056 */ 2057 DelegateExp de = cast(DelegateExp)a; 2058 if (de.e1.op == TOK.variable) 2059 { 2060 VarExp ve = cast(VarExp)de.e1; 2061 FuncDeclaration f = ve.var.isFuncDeclaration(); 2062 if (f) 2063 { 2064 if (f.tookAddressOf) 2065 --f.tookAddressOf; 2066 //printf("--tookAddressOf = %d\n", f.tookAddressOf); 2067 } 2068 } 2069 } 2070 } 2071 if (!(p.storageClass & (STC.ref_ | STC.out_))) 2072 err |= arg.checkSharedAccess(sc); 2073 2074 arg = arg.optimize(WANTvalue, (p.storageClass & (STC.ref_ | STC.out_)) != 0); 2075 2076 /* Determine if this parameter is the "first reference" parameter through which 2077 * later "return" arguments can be stored. 2078 */ 2079 if (i == 0 && !tthis && p.storageClass & (STC.ref_ | STC.out_) && p.type && 2080 (tf.next && tf.next.ty == Tvoid || isCtorCall)) 2081 { 2082 Type tb = p.type.baseElemOf(); 2083 if (tb.isMutable() && tb.hasPointers()) 2084 { 2085 firstArg = arg; 2086 } 2087 } 2088 } 2089 else 2090 { 2091 // These will be the trailing ... arguments 2092 // If not D linkage, do promotions 2093 if (tf.linkage != LINK.d) 2094 { 2095 // Promote bytes, words, etc., to ints 2096 arg = integralPromotions(arg, sc); 2097 2098 // Promote floats to doubles 2099 switch (arg.type.ty) 2100 { 2101 case Tfloat32: 2102 arg = arg.castTo(sc, Type.tfloat64); 2103 break; 2104 2105 case Timaginary32: 2106 arg = arg.castTo(sc, Type.timaginary64); 2107 break; 2108 2109 default: 2110 break; 2111 } 2112 if (tf.parameterList.varargs == VarArg.variadic) 2113 { 2114 const(char)* p = tf.linkage == LINK.c ? "extern(C)" : "extern(C++)"; 2115 if (arg.type.ty == Tarray) 2116 { 2117 arg.error("cannot pass dynamic arrays to `%s` vararg functions", p); 2118 err = true; 2119 } 2120 if (arg.type.ty == Tsarray) 2121 { 2122 arg.error("cannot pass static arrays to `%s` vararg functions", p); 2123 err = true; 2124 } 2125 } 2126 } 2127 2128 // Do not allow types that need destructors or copy constructors. 2129 if (arg.type.needsDestruction()) 2130 { 2131 arg.error("cannot pass types that need destruction as variadic arguments"); 2132 err = true; 2133 } 2134 if (arg.type.needsCopyOrPostblit()) 2135 { 2136 arg.error("cannot pass types with postblits or copy constructors as variadic arguments"); 2137 err = true; 2138 } 2139 2140 // Convert static arrays to dynamic arrays 2141 // BUG: I don't think this is right for D2 2142 Type tb = arg.type.toBasetype(); 2143 if (tb.ty == Tsarray) 2144 { 2145 TypeSArray ts = cast(TypeSArray)tb; 2146 Type ta = ts.next.arrayOf(); 2147 if (ts.size(arg.loc) == 0) 2148 arg = new NullExp(arg.loc, ta); 2149 else 2150 arg = arg.castTo(sc, ta); 2151 } 2152 if (tb.ty == Tstruct) 2153 { 2154 //arg = callCpCtor(sc, arg); 2155 } 2156 // Give error for overloaded function addresses 2157 if (arg.op == TOK.symbolOffset) 2158 { 2159 SymOffExp se = cast(SymOffExp)arg; 2160 if (se.hasOverloads && !se.var.isFuncDeclaration().isUnique()) 2161 { 2162 arg.error("function `%s` is overloaded", arg.toChars()); 2163 err = true; 2164 } 2165 } 2166 err |= arg.checkValue(); 2167 err |= arg.checkSharedAccess(sc); 2168 arg = arg.optimize(WANTvalue); 2169 } 2170 (*arguments)[i] = arg; 2171 } 2172 2173 /* If calling C scanf(), printf(), or any variants, check the format string against the arguments 2174 */ 2175 const isVa_list = tf.parameterList.varargs == VarArg.none; 2176 if (fd && fd.flags & FUNCFLAG.printf) 2177 { 2178 if (auto se = (*arguments)[nparams - 1 - isVa_list].isStringExp()) 2179 { 2180 checkPrintfFormat(se.loc, se.peekString(), (*arguments)[nparams .. nargs], isVa_list); 2181 } 2182 } 2183 else if (fd && fd.flags & FUNCFLAG.scanf) 2184 { 2185 if (auto se = (*arguments)[nparams - 1 - isVa_list].isStringExp()) 2186 { 2187 checkScanfFormat(se.loc, se.peekString(), (*arguments)[nparams .. nargs], isVa_list); 2188 } 2189 } 2190 else 2191 { 2192 // TODO: not checking the "v" functions yet (for those, check format string only, not args) 2193 } 2194 2195 /* Remaining problems: 2196 * 1. order of evaluation - some function push L-to-R, others R-to-L. Until we resolve what array assignment does (which is 2197 * implemented by calling a function) we'll defer this for now. 2198 * 2. value structs (or static arrays of them) that need to be copy constructed 2199 * 3. value structs (or static arrays of them) that have destructors, and subsequent arguments that may throw before the 2200 * function gets called (functions normally destroy their parameters) 2201 * 2 and 3 are handled by doing the argument construction in 'eprefix' so that if a later argument throws, they are cleaned 2202 * up properly. Pushing arguments on the stack then cannot fail. 2203 */ 2204 { 2205 /* TODO: tackle problem 1) 2206 */ 2207 const bool leftToRight = true; // TODO: something like !fd.isArrayOp 2208 if (!leftToRight) 2209 assert(nargs == nparams); // no variadics for RTL order, as they would probably be evaluated LTR and so add complexity 2210 2211 const ptrdiff_t start = (leftToRight ? 0 : cast(ptrdiff_t)nargs - 1); 2212 const ptrdiff_t end = (leftToRight ? cast(ptrdiff_t)nargs : -1); 2213 const ptrdiff_t step = (leftToRight ? 1 : -1); 2214 2215 /* Compute indices of last throwing argument and first arg needing destruction. 2216 * Used to not set up destructors unless an arg needs destruction on a throw 2217 * in a later argument. 2218 */ 2219 ptrdiff_t lastthrow = -1; 2220 ptrdiff_t firstdtor = -1; 2221 for (ptrdiff_t i = start; i != end; i += step) 2222 { 2223 Expression arg = (*arguments)[i]; 2224 if (canThrow(arg, sc.func, false)) 2225 lastthrow = i; 2226 if (firstdtor == -1 && arg.type.needsDestruction()) 2227 { 2228 Parameter p = (i >= nparams ? null : tf.parameterList[i]); 2229 if (!(p && (p.storageClass & (STC.lazy_ | STC.ref_ | STC.out_)))) 2230 firstdtor = i; 2231 } 2232 } 2233 2234 /* Does problem 3) apply to this call? 2235 */ 2236 const bool needsPrefix = (firstdtor >= 0 && lastthrow >= 0 2237 && (lastthrow - firstdtor) * step > 0); 2238 2239 /* If so, initialize 'eprefix' by declaring the gate 2240 */ 2241 VarDeclaration gate = null; 2242 if (needsPrefix) 2243 { 2244 // eprefix => bool __gate [= false] 2245 Identifier idtmp = Identifier.generateId("__gate"); 2246 gate = new VarDeclaration(loc, Type.tbool, idtmp, null); 2247 gate.storage_class |= STC.temp | STC.ctfe | STC.volatile_; 2248 gate.dsymbolSemantic(sc); 2249 2250 auto ae = new DeclarationExp(loc, gate); 2251 eprefix = ae.expressionSemantic(sc); 2252 } 2253 2254 for (ptrdiff_t i = start; i != end; i += step) 2255 { 2256 Expression arg = (*arguments)[i]; 2257 2258 Parameter parameter = (i >= nparams ? null : tf.parameterList[i]); 2259 const bool isRef = (parameter && (parameter.storageClass & (STC.ref_ | STC.out_))); 2260 const bool isLazy = (parameter && (parameter.storageClass & STC.lazy_)); 2261 2262 /* Skip lazy parameters 2263 */ 2264 if (isLazy) 2265 continue; 2266 2267 /* Do we have a gate? Then we have a prefix and we're not yet past the last throwing arg. 2268 * Declare a temporary variable for this arg and append that declaration to 'eprefix', 2269 * which will implicitly take care of potential problem 2) for this arg. 2270 * 'eprefix' will therefore finally contain all args up to and including the last 2271 * potentially throwing arg, excluding all lazy parameters. 2272 */ 2273 if (gate) 2274 { 2275 const bool needsDtor = (!isRef && arg.type.needsDestruction() && i != lastthrow); 2276 2277 /* Declare temporary 'auto __pfx = arg' (needsDtor) or 'auto __pfy = arg' (!needsDtor) 2278 */ 2279 auto tmp = copyToTemp(0, 2280 needsDtor ? "__pfx" : "__pfy", 2281 !isRef ? arg : arg.addressOf()); 2282 tmp.dsymbolSemantic(sc); 2283 2284 /* Modify the destructor so it only runs if gate==false, i.e., 2285 * only if there was a throw while constructing the args 2286 */ 2287 if (!needsDtor) 2288 { 2289 if (tmp.edtor) 2290 { 2291 assert(i == lastthrow); 2292 tmp.edtor = null; 2293 } 2294 } 2295 else 2296 { 2297 // edtor => (__gate || edtor) 2298 assert(tmp.edtor); 2299 Expression e = tmp.edtor; 2300 e = new LogicalExp(e.loc, TOK.orOr, new VarExp(e.loc, gate), e); 2301 tmp.edtor = e.expressionSemantic(sc); 2302 //printf("edtor: %s\n", tmp.edtor.toChars()); 2303 } 2304 2305 // eprefix => (eprefix, auto __pfx/y = arg) 2306 auto ae = new DeclarationExp(loc, tmp); 2307 eprefix = Expression.combine(eprefix, ae.expressionSemantic(sc)); 2308 2309 // arg => __pfx/y 2310 arg = new VarExp(loc, tmp); 2311 arg = arg.expressionSemantic(sc); 2312 if (isRef) 2313 { 2314 arg = new PtrExp(loc, arg); 2315 arg = arg.expressionSemantic(sc); 2316 } 2317 2318 /* Last throwing arg? Then finalize eprefix => (eprefix, gate = true), 2319 * i.e., disable the dtors right after constructing the last throwing arg. 2320 * From now on, the callee will take care of destructing the args because 2321 * the args are implicitly moved into function parameters. 2322 * 2323 * Set gate to null to let the next iterations know they don't need to 2324 * append to eprefix anymore. 2325 */ 2326 if (i == lastthrow) 2327 { 2328 auto e = new AssignExp(gate.loc, new VarExp(gate.loc, gate), IntegerExp.createBool(true)); 2329 eprefix = Expression.combine(eprefix, e.expressionSemantic(sc)); 2330 gate = null; 2331 } 2332 } 2333 else 2334 { 2335 /* No gate, no prefix to append to. 2336 * Handle problem 2) by calling the copy constructor for value structs 2337 * (or static arrays of them) if appropriate. 2338 */ 2339 Type tv = arg.type.baseElemOf(); 2340 if (!isRef && tv.ty == Tstruct) 2341 arg = doCopyOrMove(sc, arg, parameter ? parameter.type : null); 2342 } 2343 2344 (*arguments)[i] = arg; 2345 } 2346 } 2347 //if (eprefix) printf("eprefix: %s\n", eprefix.toChars()); 2348 2349 /* Test compliance with DIP1021 2350 */ 2351 if (global.params.useDIP1021 && 2352 tf.trust != TRUST.system && tf.trust != TRUST.trusted) 2353 err |= checkMutableArguments(sc, fd, tf, ethis, arguments, false); 2354 2355 // If D linkage and variadic, add _arguments[] as first argument 2356 if (tf.isDstyleVariadic()) 2357 { 2358 assert(arguments.dim >= nparams); 2359 2360 auto args = new Parameters(arguments.dim - nparams); 2361 for (size_t i = 0; i < arguments.dim - nparams; i++) 2362 { 2363 auto arg = new Parameter(STC.in_, (*arguments)[nparams + i].type, null, null, null); 2364 (*args)[i] = arg; 2365 } 2366 auto tup = new TypeTuple(args); 2367 Expression e = (new TypeidExp(loc, tup)).expressionSemantic(sc); 2368 arguments.insert(0, e); 2369 } 2370 2371 /* Determine function return type: tret 2372 */ 2373 Type tret = tf.next; 2374 if (isCtorCall) 2375 { 2376 //printf("[%s] fd = %s %s, %d %d %d\n", loc.toChars(), fd.toChars(), fd.type.toChars(), 2377 // wildmatch, tf.isWild(), fd.isReturnIsolated()); 2378 if (!tthis) 2379 { 2380 assert(sc.intypeof || global.errors); 2381 tthis = fd.isThis().type.addMod(fd.type.mod); 2382 } 2383 if (tf.isWild() && !fd.isReturnIsolated()) 2384 { 2385 if (wildmatch) 2386 tret = tret.substWildTo(wildmatch); 2387 int offset; 2388 if (!tret.implicitConvTo(tthis) && !(MODimplicitConv(tret.mod, tthis.mod) && tret.isBaseOf(tthis, &offset) && offset == 0)) 2389 { 2390 const(char)* s1 = tret.isNaked() ? " mutable" : tret.modToChars(); 2391 const(char)* s2 = tthis.isNaked() ? " mutable" : tthis.modToChars(); 2392 .error(loc, "`inout` constructor `%s` creates%s object, not%s", fd.toPrettyChars(), s1, s2); 2393 err = true; 2394 } 2395 } 2396 tret = tthis; 2397 } 2398 else if (wildmatch && tret) 2399 { 2400 /* Adjust function return type based on wildmatch 2401 */ 2402 //printf("wildmatch = x%x, tret = %s\n", wildmatch, tret.toChars()); 2403 tret = tret.substWildTo(wildmatch); 2404 } 2405 2406 *prettype = tret; 2407 *peprefix = eprefix; 2408 return (err || olderrors != global.errors); 2409 } 2410 2411 /** 2412 * Determines whether a symbol represents a module or package 2413 * (Used as a helper for is(type == module) and is(type == package)) 2414 * 2415 * Params: 2416 * sym = the symbol to be checked 2417 * 2418 * Returns: 2419 * the symbol which `sym` represents (or `null` if it doesn't represent a `Package`) 2420 */ 2421 Package resolveIsPackage(Dsymbol sym) 2422 { 2423 Package pkg; 2424 if (Import imp = sym.isImport()) 2425 { 2426 if (imp.pkg is null) 2427 { 2428 .error(sym.loc, "Internal Compiler Error: unable to process forward-referenced import `%s`", 2429 imp.toChars()); 2430 assert(0); 2431 } 2432 pkg = imp.pkg; 2433 } 2434 else if (auto mod = sym.isModule()) 2435 pkg = mod.isPackageFile ? mod.pkg : sym.isPackage(); 2436 else 2437 pkg = sym.isPackage(); 2438 if (pkg) 2439 pkg.resolvePKGunknown(); 2440 return pkg; 2441 } 2442 2443 private Module loadStdMath() 2444 { 2445 __gshared Import impStdMath = null; 2446 if (!impStdMath) 2447 { 2448 auto a = new Identifiers(); 2449 a.push(Id.std); 2450 auto s = new Import(Loc.initial, a, Id.math, null, false); 2451 // Module.load will call fatal() if there's no std.math available. 2452 // Gag the error here, pushing the error handling to the caller. 2453 uint errors = global.startGagging(); 2454 s.load(null); 2455 if (s.mod) 2456 { 2457 s.mod.importAll(null); 2458 s.mod.dsymbolSemantic(null); 2459 } 2460 global.endGagging(errors); 2461 impStdMath = s; 2462 } 2463 return impStdMath.mod; 2464 } 2465 2466 private extern (C++) final class ExpressionSemanticVisitor : Visitor 2467 { 2468 alias visit = Visitor.visit; 2469 2470 Scope* sc; 2471 Expression result; 2472 2473 this(Scope* sc) 2474 { 2475 this.sc = sc; 2476 } 2477 2478 private void setError() 2479 { 2480 result = new ErrorExp(); 2481 } 2482 2483 /************************** 2484 * Semantically analyze Expression. 2485 * Determine types, fold constants, etc. 2486 */ 2487 override void visit(Expression e) 2488 { 2489 static if (LOGSEMANTIC) 2490 { 2491 printf("Expression::semantic() %s\n", e.toChars()); 2492 } 2493 if (e.type) 2494 e.type = e.type.typeSemantic(e.loc, sc); 2495 else 2496 e.type = Type.tvoid; 2497 result = e; 2498 } 2499 2500 override void visit(IntegerExp e) 2501 { 2502 assert(e.type); 2503 if (e.type.ty == Terror) 2504 return setError(); 2505 2506 assert(e.type.deco); 2507 e.setInteger(e.getInteger()); 2508 result = e; 2509 } 2510 2511 override void visit(RealExp e) 2512 { 2513 if (!e.type) 2514 e.type = Type.tfloat64; 2515 else 2516 e.type = e.type.typeSemantic(e.loc, sc); 2517 result = e; 2518 } 2519 2520 override void visit(ComplexExp e) 2521 { 2522 if (!e.type) 2523 e.type = Type.tcomplex80; 2524 else 2525 e.type = e.type.typeSemantic(e.loc, sc); 2526 result = e; 2527 } 2528 2529 override void visit(IdentifierExp exp) 2530 { 2531 static if (LOGSEMANTIC) 2532 { 2533 printf("IdentifierExp::semantic('%s')\n", exp.ident.toChars()); 2534 } 2535 if (exp.type) // This is used as the dummy expression 2536 { 2537 result = exp; 2538 return; 2539 } 2540 2541 Dsymbol scopesym; 2542 Dsymbol s = sc.search(exp.loc, exp.ident, &scopesym); 2543 if (s) 2544 { 2545 if (s.errors) 2546 return setError(); 2547 2548 Expression e; 2549 2550 /* See if the symbol was a member of an enclosing 'with' 2551 */ 2552 WithScopeSymbol withsym = scopesym.isWithScopeSymbol(); 2553 if (withsym && withsym.withstate.wthis) 2554 { 2555 /* Disallow shadowing 2556 */ 2557 // First find the scope of the with 2558 Scope* scwith = sc; 2559 while (scwith.scopesym != scopesym) 2560 { 2561 scwith = scwith.enclosing; 2562 assert(scwith); 2563 } 2564 // Look at enclosing scopes for symbols with the same name, 2565 // in the same function 2566 for (Scope* scx = scwith; scx && scx.func == scwith.func; scx = scx.enclosing) 2567 { 2568 Dsymbol s2; 2569 if (scx.scopesym && scx.scopesym.symtab && (s2 = scx.scopesym.symtab.lookup(s.ident)) !is null && s != s2) 2570 { 2571 exp.error("with symbol `%s` is shadowing local symbol `%s`", s.toPrettyChars(), s2.toPrettyChars()); 2572 return setError(); 2573 } 2574 } 2575 s = s.toAlias(); 2576 2577 // Same as wthis.ident 2578 // TODO: DotIdExp.semantic will find 'ident' from 'wthis' again. 2579 // The redudancy should be removed. 2580 e = new VarExp(exp.loc, withsym.withstate.wthis); 2581 e = new DotIdExp(exp.loc, e, exp.ident); 2582 e = e.expressionSemantic(sc); 2583 } 2584 else 2585 { 2586 if (withsym) 2587 { 2588 if (auto t = withsym.withstate.exp.isTypeExp()) 2589 { 2590 e = new TypeExp(exp.loc, t.type); 2591 e = new DotIdExp(exp.loc, e, exp.ident); 2592 result = e.expressionSemantic(sc); 2593 return; 2594 } 2595 } 2596 2597 /* If f is really a function template, 2598 * then replace f with the function template declaration. 2599 */ 2600 FuncDeclaration f = s.isFuncDeclaration(); 2601 if (f) 2602 { 2603 TemplateDeclaration td = getFuncTemplateDecl(f); 2604 if (td) 2605 { 2606 if (td.overroot) // if not start of overloaded list of TemplateDeclaration's 2607 td = td.overroot; // then get the start 2608 e = new TemplateExp(exp.loc, td, f); 2609 e = e.expressionSemantic(sc); 2610 result = e; 2611 return; 2612 } 2613 } 2614 2615 if (global.params.fixAliasThis) 2616 { 2617 ExpressionDsymbol expDsym = scopesym.isExpressionDsymbol(); 2618 if (expDsym) 2619 { 2620 //printf("expDsym = %s\n", expDsym.exp.toChars()); 2621 result = expDsym.exp.expressionSemantic(sc); 2622 return; 2623 } 2624 } 2625 // Haven't done overload resolution yet, so pass 1 2626 e = symbolToExp(s, exp.loc, sc, true); 2627 } 2628 result = e; 2629 return; 2630 } 2631 2632 if (!global.params.fixAliasThis && hasThis(sc)) 2633 { 2634 for (AggregateDeclaration ad = sc.getStructClassScope(); ad;) 2635 { 2636 if (ad.aliasthis) 2637 { 2638 Expression e; 2639 e = new ThisExp(exp.loc); 2640 e = new DotIdExp(exp.loc, e, ad.aliasthis.ident); 2641 e = new DotIdExp(exp.loc, e, exp.ident); 2642 e = e.trySemantic(sc); 2643 if (e) 2644 { 2645 result = e; 2646 return; 2647 } 2648 } 2649 2650 auto cd = ad.isClassDeclaration(); 2651 if (cd && cd.baseClass && cd.baseClass != ClassDeclaration.object) 2652 { 2653 ad = cd.baseClass; 2654 continue; 2655 } 2656 break; 2657 } 2658 } 2659 2660 if (exp.ident == Id.ctfe) 2661 { 2662 if (sc.flags & SCOPE.ctfe) 2663 { 2664 exp.error("variable `__ctfe` cannot be read at compile time"); 2665 return setError(); 2666 } 2667 2668 // Create the magic __ctfe bool variable 2669 auto vd = new VarDeclaration(exp.loc, Type.tbool, Id.ctfe, null); 2670 vd.storage_class |= STC.temp; 2671 vd.semanticRun = PASS.semanticdone; 2672 Expression e = new VarExp(exp.loc, vd); 2673 e = e.expressionSemantic(sc); 2674 result = e; 2675 return; 2676 } 2677 2678 // If we've reached this point and are inside a with() scope then we may 2679 // try one last attempt by checking whether the 'wthis' object supports 2680 // dynamic dispatching via opDispatch. 2681 // This is done by rewriting this expression as wthis.ident. 2682 // The innermost with() scope of the hierarchy to satisfy the condition 2683 // above wins. 2684 // https://issues.dlang.org/show_bug.cgi?id=6400 2685 for (Scope* sc2 = sc; sc2; sc2 = sc2.enclosing) 2686 { 2687 if (!sc2.scopesym) 2688 continue; 2689 2690 if (auto ss = sc2.scopesym.isWithScopeSymbol()) 2691 { 2692 if (ss.withstate.wthis) 2693 { 2694 Expression e; 2695 e = new VarExp(exp.loc, ss.withstate.wthis); 2696 e = new DotIdExp(exp.loc, e, exp.ident); 2697 e = e.trySemantic(sc); 2698 if (e) 2699 { 2700 result = e; 2701 return; 2702 } 2703 } 2704 // Try Type.opDispatch (so the static version) 2705 else if (ss.withstate.exp && ss.withstate.exp.op == TOK.type) 2706 { 2707 if (Type t = ss.withstate.exp.isTypeExp().type) 2708 { 2709 Expression e; 2710 e = new TypeExp(exp.loc, t); 2711 e = new DotIdExp(exp.loc, e, exp.ident); 2712 e = e.trySemantic(sc); 2713 if (e) 2714 { 2715 result = e; 2716 return; 2717 } 2718 } 2719 } 2720 } 2721 } 2722 2723 /* Look for what user might have meant 2724 */ 2725 if (const n = importHint(exp.ident.toString())) 2726 exp.error("`%s` is not defined, perhaps `import %.*s;` is needed?", exp.ident.toChars(), cast(int)n.length, n.ptr); 2727 else if (auto s2 = sc.search_correct(exp.ident)) 2728 exp.error("undefined identifier `%s`, did you mean %s `%s`?", exp.ident.toChars(), s2.kind(), s2.toChars()); 2729 else if (const p = Scope.search_correct_C(exp.ident)) 2730 exp.error("undefined identifier `%s`, did you mean `%s`?", exp.ident.toChars(), p); 2731 else 2732 exp.error("undefined identifier `%s`", exp.ident.toChars()); 2733 2734 result = new ErrorExp(); 2735 } 2736 2737 override void visit(DsymbolExp e) 2738 { 2739 result = symbolToExp(e.s, e.loc, sc, e.hasOverloads); 2740 } 2741 2742 override void visit(ThisExp e) 2743 { 2744 static if (LOGSEMANTIC) 2745 { 2746 printf("ThisExp::semantic()\n"); 2747 } 2748 if (e.type) 2749 { 2750 result = e; 2751 return; 2752 } 2753 2754 FuncDeclaration fd = hasThis(sc); // fd is the uplevel function with the 'this' variable 2755 AggregateDeclaration ad; 2756 2757 /* Special case for typeof(this) and typeof(super) since both 2758 * should work even if they are not inside a non-static member function 2759 */ 2760 if (!fd && sc.intypeof == 1) 2761 { 2762 // Find enclosing struct or class 2763 for (Dsymbol s = sc.getStructClassScope(); 1; s = s.parent) 2764 { 2765 if (!s) 2766 { 2767 e.error("`%s` is not in a class or struct scope", e.toChars()); 2768 goto Lerr; 2769 } 2770 ClassDeclaration cd = s.isClassDeclaration(); 2771 if (cd) 2772 { 2773 e.type = cd.type; 2774 result = e; 2775 return; 2776 } 2777 StructDeclaration sd = s.isStructDeclaration(); 2778 if (sd) 2779 { 2780 e.type = sd.type; 2781 result = e; 2782 return; 2783 } 2784 } 2785 } 2786 if (!fd) 2787 goto Lerr; 2788 2789 assert(fd.vthis); 2790 e.var = fd.vthis; 2791 assert(e.var.parent); 2792 ad = fd.isMemberLocal(); 2793 if (!ad) 2794 ad = fd.isMember2(); 2795 assert(ad); 2796 e.type = ad.type.addMod(e.var.type.mod); 2797 2798 if (e.var.checkNestedReference(sc, e.loc)) 2799 return setError(); 2800 2801 result = e; 2802 return; 2803 2804 Lerr: 2805 e.error("`this` is only defined in non-static member functions, not `%s`", sc.parent.toChars()); 2806 result = new ErrorExp(); 2807 } 2808 2809 override void visit(SuperExp e) 2810 { 2811 static if (LOGSEMANTIC) 2812 { 2813 printf("SuperExp::semantic('%s')\n", e.toChars()); 2814 } 2815 if (e.type) 2816 { 2817 result = e; 2818 return; 2819 } 2820 2821 FuncDeclaration fd = hasThis(sc); 2822 ClassDeclaration cd; 2823 Dsymbol s; 2824 2825 /* Special case for typeof(this) and typeof(super) since both 2826 * should work even if they are not inside a non-static member function 2827 */ 2828 if (!fd && sc.intypeof == 1) 2829 { 2830 // Find enclosing class 2831 for (s = sc.getStructClassScope(); 1; s = s.parent) 2832 { 2833 if (!s) 2834 { 2835 e.error("`%s` is not in a class scope", e.toChars()); 2836 goto Lerr; 2837 } 2838 cd = s.isClassDeclaration(); 2839 if (cd) 2840 { 2841 cd = cd.baseClass; 2842 if (!cd) 2843 { 2844 e.error("class `%s` has no `super`", s.toChars()); 2845 goto Lerr; 2846 } 2847 e.type = cd.type; 2848 result = e; 2849 return; 2850 } 2851 } 2852 } 2853 if (!fd) 2854 goto Lerr; 2855 2856 e.var = fd.vthis; 2857 assert(e.var && e.var.parent); 2858 2859 s = fd.toParentDecl(); 2860 if (s.isTemplateDeclaration()) // allow inside template constraint 2861 s = s.toParent(); 2862 assert(s); 2863 cd = s.isClassDeclaration(); 2864 //printf("parent is %s %s\n", fd.toParent().kind(), fd.toParent().toChars()); 2865 if (!cd) 2866 goto Lerr; 2867 if (!cd.baseClass) 2868 { 2869 e.error("no base class for `%s`", cd.toChars()); 2870 e.type = cd.type.addMod(e.var.type.mod); 2871 } 2872 else 2873 { 2874 e.type = cd.baseClass.type; 2875 e.type = e.type.castMod(e.var.type.mod); 2876 } 2877 2878 if (e.var.checkNestedReference(sc, e.loc)) 2879 return setError(); 2880 2881 result = e; 2882 return; 2883 2884 Lerr: 2885 e.error("`super` is only allowed in non-static class member functions"); 2886 result = new ErrorExp(); 2887 } 2888 2889 override void visit(NullExp e) 2890 { 2891 static if (LOGSEMANTIC) 2892 { 2893 printf("NullExp::semantic('%s')\n", e.toChars()); 2894 } 2895 // NULL is the same as (void *)0 2896 if (e.type) 2897 { 2898 result = e; 2899 return; 2900 } 2901 e.type = Type.tnull; 2902 result = e; 2903 } 2904 2905 override void visit(StringExp e) 2906 { 2907 static if (LOGSEMANTIC) 2908 { 2909 printf("StringExp::semantic() %s\n", e.toChars()); 2910 } 2911 if (e.type) 2912 { 2913 result = e; 2914 return; 2915 } 2916 2917 OutBuffer buffer; 2918 size_t newlen = 0; 2919 size_t u; 2920 dchar c; 2921 2922 switch (e.postfix) 2923 { 2924 case 'd': 2925 for (u = 0; u < e.len;) 2926 { 2927 if (const p = utf_decodeChar(e.peekString(), u, c)) 2928 { 2929 e.error("%.*s", cast(int)p.length, p.ptr); 2930 return setError(); 2931 } 2932 else 2933 { 2934 buffer.write4(c); 2935 newlen++; 2936 } 2937 } 2938 buffer.write4(0); 2939 e.setData(buffer.extractData(), newlen, 4); 2940 e.type = new TypeDArray(Type.tdchar.immutableOf()); 2941 e.committed = 1; 2942 break; 2943 2944 case 'w': 2945 for (u = 0; u < e.len;) 2946 { 2947 if (const p = utf_decodeChar(e.peekString(), u, c)) 2948 { 2949 e.error("%.*s", cast(int)p.length, p.ptr); 2950 return setError(); 2951 } 2952 else 2953 { 2954 buffer.writeUTF16(c); 2955 newlen++; 2956 if (c >= 0x10000) 2957 newlen++; 2958 } 2959 } 2960 buffer.writeUTF16(0); 2961 e.setData(buffer.extractData(), newlen, 2); 2962 e.type = new TypeDArray(Type.twchar.immutableOf()); 2963 e.committed = 1; 2964 break; 2965 2966 case 'c': 2967 e.committed = 1; 2968 goto default; 2969 2970 default: 2971 e.type = new TypeDArray(Type.tchar.immutableOf()); 2972 break; 2973 } 2974 e.type = e.type.typeSemantic(e.loc, sc); 2975 //type = type.immutableOf(); 2976 //printf("type = %s\n", type.toChars()); 2977 2978 result = e; 2979 } 2980 2981 override void visit(TupleExp exp) 2982 { 2983 static if (LOGSEMANTIC) 2984 { 2985 printf("+TupleExp::semantic(%s)\n", exp.toChars()); 2986 } 2987 if (exp.type) 2988 { 2989 result = exp; 2990 return; 2991 } 2992 2993 if (exp.e0) 2994 exp.e0 = exp.e0.expressionSemantic(sc); 2995 2996 // Run semantic() on each argument 2997 bool err = false; 2998 for (size_t i = 0; i < exp.exps.dim; i++) 2999 { 3000 Expression e = (*exp.exps)[i]; 3001 e = e.expressionSemantic(sc); 3002 if (!e.type) 3003 { 3004 exp.error("`%s` has no value", e.toChars()); 3005 err = true; 3006 } 3007 else if (e.op == TOK.error) 3008 err = true; 3009 else 3010 (*exp.exps)[i] = e; 3011 } 3012 if (err) 3013 return setError(); 3014 3015 expandTuples(exp.exps); 3016 3017 exp.type = new TypeTuple(exp.exps); 3018 exp.type = exp.type.typeSemantic(exp.loc, sc); 3019 //printf("-TupleExp::semantic(%s)\n", toChars()); 3020 result = exp; 3021 } 3022 3023 override void visit(ArrayLiteralExp e) 3024 { 3025 static if (LOGSEMANTIC) 3026 { 3027 printf("ArrayLiteralExp::semantic('%s')\n", e.toChars()); 3028 } 3029 if (e.type) 3030 { 3031 result = e; 3032 return; 3033 } 3034 3035 /* Perhaps an empty array literal [ ] should be rewritten as null? 3036 */ 3037 3038 if (e.basis) 3039 e.basis = e.basis.expressionSemantic(sc); 3040 if (arrayExpressionSemantic(e.elements, sc) || (e.basis && e.basis.op == TOK.error)) 3041 return setError(); 3042 3043 expandTuples(e.elements); 3044 3045 Type t0; 3046 if (e.basis) 3047 e.elements.push(e.basis); 3048 bool err = arrayExpressionToCommonType(sc, e.elements, &t0); 3049 if (e.basis) 3050 e.basis = e.elements.pop(); 3051 if (err) 3052 return setError(); 3053 3054 e.type = t0.arrayOf(); 3055 e.type = e.type.typeSemantic(e.loc, sc); 3056 3057 /* Disallow array literals of type void being used. 3058 */ 3059 if (e.elements.dim > 0 && t0.ty == Tvoid) 3060 { 3061 e.error("`%s` of type `%s` has no value", e.toChars(), e.type.toChars()); 3062 return setError(); 3063 } 3064 3065 if (global.params.useTypeInfo && Type.dtypeinfo) 3066 semanticTypeInfo(sc, e.type); 3067 3068 result = e; 3069 } 3070 3071 override void visit(AssocArrayLiteralExp e) 3072 { 3073 static if (LOGSEMANTIC) 3074 { 3075 printf("AssocArrayLiteralExp::semantic('%s')\n", e.toChars()); 3076 } 3077 if (e.type) 3078 { 3079 result = e; 3080 return; 3081 } 3082 3083 // Run semantic() on each element 3084 bool err_keys = arrayExpressionSemantic(e.keys, sc); 3085 bool err_vals = arrayExpressionSemantic(e.values, sc); 3086 if (err_keys || err_vals) 3087 return setError(); 3088 3089 expandTuples(e.keys); 3090 expandTuples(e.values); 3091 if (e.keys.dim != e.values.dim) 3092 { 3093 e.error("number of keys is %u, must match number of values %u", e.keys.dim, e.values.dim); 3094 return setError(); 3095 } 3096 3097 Type tkey = null; 3098 Type tvalue = null; 3099 err_keys = arrayExpressionToCommonType(sc, e.keys, &tkey); 3100 err_vals = arrayExpressionToCommonType(sc, e.values, &tvalue); 3101 if (err_keys || err_vals) 3102 return setError(); 3103 3104 if (tkey == Type.terror || tvalue == Type.terror) 3105 return setError(); 3106 3107 e.type = new TypeAArray(tvalue, tkey); 3108 e.type = e.type.typeSemantic(e.loc, sc); 3109 3110 semanticTypeInfo(sc, e.type); 3111 3112 if (global.params.vsafe) 3113 { 3114 if (checkAssocArrayLiteralEscape(sc, e, false)) 3115 return setError(); 3116 } 3117 3118 result = e; 3119 } 3120 3121 override void visit(StructLiteralExp e) 3122 { 3123 static if (LOGSEMANTIC) 3124 { 3125 printf("StructLiteralExp::semantic('%s')\n", e.toChars()); 3126 } 3127 if (e.type) 3128 { 3129 result = e; 3130 return; 3131 } 3132 3133 e.sd.size(e.loc); 3134 if (e.sd.sizeok != Sizeok.done) 3135 return setError(); 3136 3137 // run semantic() on each element 3138 if (arrayExpressionSemantic(e.elements, sc)) 3139 return setError(); 3140 3141 expandTuples(e.elements); 3142 3143 /* Fit elements[] to the corresponding type of field[]. 3144 */ 3145 if (!e.sd.fit(e.loc, sc, e.elements, e.stype)) 3146 return setError(); 3147 3148 /* Fill out remainder of elements[] with default initializers for fields[] 3149 */ 3150 if (!e.sd.fill(e.loc, e.elements, false)) 3151 { 3152 /* An error in the initializer needs to be recorded as an error 3153 * in the enclosing function or template, since the initializer 3154 * will be part of the stuct declaration. 3155 */ 3156 global.increaseErrorCount(); 3157 return setError(); 3158 } 3159 3160 if (checkFrameAccess(e.loc, sc, e.sd, e.elements.dim)) 3161 return setError(); 3162 3163 e.type = e.stype ? e.stype : e.sd.type; 3164 result = e; 3165 } 3166 3167 override void visit(TypeExp exp) 3168 { 3169 if (exp.type.ty == Terror) 3170 return setError(); 3171 3172 //printf("TypeExp::semantic(%s)\n", exp.type.toChars()); 3173 Expression e; 3174 Type t; 3175 Dsymbol s; 3176 3177 dmd.typesem.resolve(exp.type, exp.loc, sc, &e, &t, &s, true); 3178 if (e) 3179 { 3180 // `(Type)` is actually `(var)` so if `(var)` is a member requiring `this` 3181 // then rewrite as `(this.var)` in case it would be followed by a DotVar 3182 // to fix https://issues.dlang.org/show_bug.cgi?id=9490 3183 VarExp ve = e.isVarExp(); 3184 if (ve && ve.var && exp.parens && !ve.var.isStatic() && !(sc.stc & STC.static_) && 3185 sc.func && sc.func.needThis && ve.var.toParent2().isAggregateDeclaration()) 3186 { 3187 // printf("apply fix for issue 9490: add `this.` to `%s`...\n", e.toChars()); 3188 e = new DotVarExp(exp.loc, new ThisExp(exp.loc), ve.var, false); 3189 } 3190 //printf("e = %s %s\n", Token::toChars(e.op), e.toChars()); 3191 e = e.expressionSemantic(sc); 3192 } 3193 else if (t) 3194 { 3195 //printf("t = %d %s\n", t.ty, t.toChars()); 3196 exp.type = t.typeSemantic(exp.loc, sc); 3197 e = exp; 3198 } 3199 else if (s) 3200 { 3201 //printf("s = %s %s\n", s.kind(), s.toChars()); 3202 e = symbolToExp(s, exp.loc, sc, true); 3203 } 3204 else 3205 assert(0); 3206 3207 if (global.params.vcomplex) 3208 exp.type.checkComplexTransition(exp.loc, sc); 3209 3210 result = e; 3211 } 3212 3213 override void visit(ScopeExp exp) 3214 { 3215 static if (LOGSEMANTIC) 3216 { 3217 printf("+ScopeExp::semantic(%p '%s')\n", exp, exp.toChars()); 3218 } 3219 if (exp.type) 3220 { 3221 result = exp; 3222 return; 3223 } 3224 3225 ScopeDsymbol sds2 = exp.sds; 3226 TemplateInstance ti = sds2.isTemplateInstance(); 3227 while (ti) 3228 { 3229 WithScopeSymbol withsym; 3230 if (!ti.findTempDecl(sc, &withsym) || !ti.semanticTiargs(sc)) 3231 return setError(); 3232 if (withsym && withsym.withstate.wthis) 3233 { 3234 Expression e = new VarExp(exp.loc, withsym.withstate.wthis); 3235 e = new DotTemplateInstanceExp(exp.loc, e, ti); 3236 result = e.expressionSemantic(sc); 3237 return; 3238 } 3239 if (ti.needsTypeInference(sc)) 3240 { 3241 if (TemplateDeclaration td = ti.tempdecl.isTemplateDeclaration()) 3242 { 3243 Dsymbol p = td.toParentLocal(); 3244 FuncDeclaration fdthis = hasThis(sc); 3245 AggregateDeclaration ad = p ? p.isAggregateDeclaration() : null; 3246 if (fdthis && ad && fdthis.isMemberLocal() == ad && (td._scope.stc & STC.static_) == 0) 3247 { 3248 Expression e = new DotTemplateInstanceExp(exp.loc, new ThisExp(exp.loc), ti.name, ti.tiargs); 3249 result = e.expressionSemantic(sc); 3250 return; 3251 } 3252 } 3253 else if (OverloadSet os = ti.tempdecl.isOverloadSet()) 3254 { 3255 FuncDeclaration fdthis = hasThis(sc); 3256 AggregateDeclaration ad = os.parent.isAggregateDeclaration(); 3257 if (fdthis && ad && fdthis.isMemberLocal() == ad) 3258 { 3259 Expression e = new DotTemplateInstanceExp(exp.loc, new ThisExp(exp.loc), ti.name, ti.tiargs); 3260 result = e.expressionSemantic(sc); 3261 return; 3262 } 3263 } 3264 // ti is an instance which requires IFTI. 3265 exp.sds = ti; 3266 exp.type = Type.tvoid; 3267 result = exp; 3268 return; 3269 } 3270 ti.dsymbolSemantic(sc); 3271 if (!ti.inst || ti.errors) 3272 return setError(); 3273 3274 Dsymbol s = ti.toAlias(); 3275 if (s == ti) 3276 { 3277 exp.sds = ti; 3278 exp.type = Type.tvoid; 3279 result = exp; 3280 return; 3281 } 3282 sds2 = s.isScopeDsymbol(); 3283 if (sds2) 3284 { 3285 ti = sds2.isTemplateInstance(); 3286 //printf("+ sds2 = %s, '%s'\n", sds2.kind(), sds2.toChars()); 3287 continue; 3288 } 3289 3290 if (auto v = s.isVarDeclaration()) 3291 { 3292 if (!v.type) 3293 { 3294 exp.error("forward reference of %s `%s`", v.kind(), v.toChars()); 3295 return setError(); 3296 } 3297 if ((v.storage_class & STC.manifest) && v._init) 3298 { 3299 /* When an instance that will be converted to a constant exists, 3300 * the instance representation "foo!tiargs" is treated like a 3301 * variable name, and its recursive appearance check (note that 3302 * it's equivalent with a recursive instantiation of foo) is done 3303 * separately from the circular initialization check for the 3304 * eponymous enum variable declaration. 3305 * 3306 * template foo(T) { 3307 * enum bool foo = foo; // recursive definition check (v.inuse) 3308 * } 3309 * template bar(T) { 3310 * enum bool bar = bar!T; // recursive instantiation check (ti.inuse) 3311 * } 3312 */ 3313 if (ti.inuse) 3314 { 3315 exp.error("recursive expansion of %s `%s`", ti.kind(), ti.toPrettyChars()); 3316 return setError(); 3317 } 3318 v.checkDeprecated(exp.loc, sc); 3319 auto e = v.expandInitializer(exp.loc); 3320 ti.inuse++; 3321 e = e.expressionSemantic(sc); 3322 ti.inuse--; 3323 result = e; 3324 return; 3325 } 3326 } 3327 3328 //printf("s = %s, '%s'\n", s.kind(), s.toChars()); 3329 auto e = symbolToExp(s, exp.loc, sc, true); 3330 //printf("-1ScopeExp::semantic()\n"); 3331 result = e; 3332 return; 3333 } 3334 3335 //printf("sds2 = %s, '%s'\n", sds2.kind(), sds2.toChars()); 3336 //printf("\tparent = '%s'\n", sds2.parent.toChars()); 3337 sds2.dsymbolSemantic(sc); 3338 3339 // (Aggregate|Enum)Declaration 3340 if (auto t = sds2.getType()) 3341 { 3342 result = (new TypeExp(exp.loc, t)).expressionSemantic(sc); 3343 return; 3344 } 3345 3346 if (auto td = sds2.isTemplateDeclaration()) 3347 { 3348 result = (new TemplateExp(exp.loc, td)).expressionSemantic(sc); 3349 return; 3350 } 3351 3352 exp.sds = sds2; 3353 exp.type = Type.tvoid; 3354 //printf("-2ScopeExp::semantic() %s\n", toChars()); 3355 result = exp; 3356 } 3357 3358 override void visit(NewExp exp) 3359 { 3360 static if (LOGSEMANTIC) 3361 { 3362 printf("NewExp::semantic() %s\n", exp.toChars()); 3363 if (exp.thisexp) 3364 printf("\tthisexp = %s\n", exp.thisexp.toChars()); 3365 printf("\tnewtype: %s\n", exp.newtype.toChars()); 3366 } 3367 if (exp.type) // if semantic() already run 3368 { 3369 result = exp; 3370 return; 3371 } 3372 3373 //for error messages if the argument in [] is not convertible to size_t 3374 const originalNewtype = exp.newtype; 3375 3376 // https://issues.dlang.org/show_bug.cgi?id=11581 3377 // With the syntax `new T[edim]` or `thisexp.new T[edim]`, 3378 // T should be analyzed first and edim should go into arguments iff it's 3379 // not a tuple. 3380 Expression edim = null; 3381 if (!exp.arguments && exp.newtype.ty == Tsarray) 3382 { 3383 edim = (cast(TypeSArray)exp.newtype).dim; 3384 exp.newtype = (cast(TypeNext)exp.newtype).next; 3385 } 3386 3387 ClassDeclaration cdthis = null; 3388 if (exp.thisexp) 3389 { 3390 exp.thisexp = exp.thisexp.expressionSemantic(sc); 3391 if (exp.thisexp.op == TOK.error) 3392 return setError(); 3393 3394 cdthis = exp.thisexp.type.isClassHandle(); 3395 if (!cdthis) 3396 { 3397 exp.error("`this` for nested class must be a class type, not `%s`", exp.thisexp.type.toChars()); 3398 return setError(); 3399 } 3400 3401 sc = sc.push(cdthis); 3402 exp.type = exp.newtype.typeSemantic(exp.loc, sc); 3403 sc = sc.pop(); 3404 } 3405 else 3406 { 3407 exp.type = exp.newtype.typeSemantic(exp.loc, sc); 3408 } 3409 if (exp.type.ty == Terror) 3410 return setError(); 3411 3412 if (edim) 3413 { 3414 if (exp.type.toBasetype().ty == Ttuple) 3415 { 3416 // --> new T[edim] 3417 exp.type = new TypeSArray(exp.type, edim); 3418 exp.type = exp.type.typeSemantic(exp.loc, sc); 3419 if (exp.type.ty == Terror) 3420 return setError(); 3421 } 3422 else 3423 { 3424 // --> new T[](edim) 3425 exp.arguments = new Expressions(); 3426 exp.arguments.push(edim); 3427 exp.type = exp.type.arrayOf(); 3428 } 3429 } 3430 3431 exp.newtype = exp.type; // in case type gets cast to something else 3432 Type tb = exp.type.toBasetype(); 3433 //printf("tb: %s, deco = %s\n", tb.toChars(), tb.deco); 3434 if (arrayExpressionSemantic(exp.newargs, sc) || 3435 preFunctionParameters(sc, exp.newargs)) 3436 { 3437 return setError(); 3438 } 3439 if (arrayExpressionSemantic(exp.arguments, sc)) 3440 { 3441 return setError(); 3442 } 3443 //https://issues.dlang.org/show_bug.cgi?id=20547 3444 //exp.arguments are the "parameters" to [], not to a real function 3445 //so the errors that come from preFunctionParameters are misleading 3446 if (originalNewtype.ty == Tsarray) 3447 { 3448 if (preFunctionParameters(sc, exp.arguments, false)) 3449 { 3450 exp.error("cannot create a `%s` with `new`", originalNewtype.toChars()); 3451 return setError(); 3452 } 3453 } 3454 else if (preFunctionParameters(sc, exp.arguments)) 3455 { 3456 return setError(); 3457 } 3458 3459 if (exp.thisexp && tb.ty != Tclass) 3460 { 3461 exp.error("`.new` is only for allocating nested classes, not `%s`", tb.toChars()); 3462 return setError(); 3463 } 3464 3465 const size_t nargs = exp.arguments ? exp.arguments.dim : 0; 3466 Expression newprefix = null; 3467 3468 if (tb.ty == Tclass) 3469 { 3470 auto cd = (cast(TypeClass)tb).sym; 3471 cd.size(exp.loc); 3472 if (cd.sizeok != Sizeok.done) 3473 return setError(); 3474 if (!cd.ctor) 3475 cd.ctor = cd.searchCtor(); 3476 if (cd.noDefaultCtor && !nargs && !cd.defaultCtor) 3477 { 3478 exp.error("default construction is disabled for type `%s`", cd.type.toChars()); 3479 return setError(); 3480 } 3481 3482 if (cd.isInterfaceDeclaration()) 3483 { 3484 exp.error("cannot create instance of interface `%s`", cd.toChars()); 3485 return setError(); 3486 } 3487 3488 if (cd.isAbstract()) 3489 { 3490 exp.error("cannot create instance of abstract class `%s`", cd.toChars()); 3491 for (size_t i = 0; i < cd.vtbl.dim; i++) 3492 { 3493 FuncDeclaration fd = cd.vtbl[i].isFuncDeclaration(); 3494 if (fd && fd.isAbstract()) 3495 { 3496 errorSupplemental(exp.loc, "function `%s` is not implemented", 3497 fd.toFullSignature()); 3498 } 3499 } 3500 return setError(); 3501 } 3502 // checkDeprecated() is already done in newtype.typeSemantic(). 3503 3504 if (cd.isNested()) 3505 { 3506 /* We need a 'this' pointer for the nested class. 3507 * Ensure we have the right one. 3508 */ 3509 Dsymbol s = cd.toParentLocal(); 3510 3511 //printf("cd isNested, parent = %s '%s'\n", s.kind(), s.toPrettyChars()); 3512 if (auto cdn = s.isClassDeclaration()) 3513 { 3514 if (!cdthis) 3515 { 3516 // Supply an implicit 'this' and try again 3517 exp.thisexp = new ThisExp(exp.loc); 3518 for (Dsymbol sp = sc.parent; 1; sp = sp.toParentLocal()) 3519 { 3520 if (!sp) 3521 { 3522 exp.error("outer class `%s` `this` needed to `new` nested class `%s`", 3523 cdn.toChars(), cd.toChars()); 3524 return setError(); 3525 } 3526 ClassDeclaration cdp = sp.isClassDeclaration(); 3527 if (!cdp) 3528 continue; 3529 if (cdp == cdn || cdn.isBaseOf(cdp, null)) 3530 break; 3531 // Add a '.outer' and try again 3532 exp.thisexp = new DotIdExp(exp.loc, exp.thisexp, Id.outer); 3533 } 3534 3535 exp.thisexp = exp.thisexp.expressionSemantic(sc); 3536 if (exp.thisexp.op == TOK.error) 3537 return setError(); 3538 cdthis = exp.thisexp.type.isClassHandle(); 3539 } 3540 if (cdthis != cdn && !cdn.isBaseOf(cdthis, null)) 3541 { 3542 //printf("cdthis = %s\n", cdthis.toChars()); 3543 exp.error("`this` for nested class must be of type `%s`, not `%s`", 3544 cdn.toChars(), exp.thisexp.type.toChars()); 3545 return setError(); 3546 } 3547 if (!MODimplicitConv(exp.thisexp.type.mod, exp.newtype.mod)) 3548 { 3549 exp.error("nested type `%s` should have the same or weaker constancy as enclosing type `%s`", 3550 exp.newtype.toChars(), exp.thisexp.type.toChars()); 3551 return setError(); 3552 } 3553 } 3554 else if (exp.thisexp) 3555 { 3556 exp.error("`.new` is only for allocating nested classes"); 3557 return setError(); 3558 } 3559 else if (auto fdn = s.isFuncDeclaration()) 3560 { 3561 // make sure the parent context fdn of cd is reachable from sc 3562 if (!ensureStaticLinkTo(sc.parent, fdn)) 3563 { 3564 exp.error("outer function context of `%s` is needed to `new` nested class `%s`", 3565 fdn.toPrettyChars(), cd.toPrettyChars()); 3566 return setError(); 3567 } 3568 } 3569 else 3570 assert(0); 3571 } 3572 else if (exp.thisexp) 3573 { 3574 exp.error("`.new` is only for allocating nested classes"); 3575 return setError(); 3576 } 3577 3578 if (cd.vthis2) 3579 { 3580 if (AggregateDeclaration ad2 = cd.isMember2()) 3581 { 3582 Expression te = new ThisExp(exp.loc).expressionSemantic(sc); 3583 if (te.op != TOK.error) 3584 te = getRightThis(exp.loc, sc, ad2, te, cd); 3585 if (te.op == TOK.error) 3586 { 3587 exp.error("need `this` of type `%s` needed to `new` nested class `%s`", ad2.toChars(), cd.toChars()); 3588 return setError(); 3589 } 3590 } 3591 } 3592 3593 if (cd.aggNew) 3594 { 3595 // Prepend the size argument to newargs[] 3596 Expression e = new IntegerExp(exp.loc, cd.size(exp.loc), Type.tsize_t); 3597 if (!exp.newargs) 3598 exp.newargs = new Expressions(); 3599 exp.newargs.shift(e); 3600 3601 FuncDeclaration f = resolveFuncCall(exp.loc, sc, cd.aggNew, null, tb, exp.newargs, FuncResolveFlag.standard); 3602 if (!f || f.errors) 3603 return setError(); 3604 3605 checkFunctionAttributes(exp, sc, f); 3606 checkAccess(cd, exp.loc, sc, f); 3607 3608 TypeFunction tf = cast(TypeFunction)f.type; 3609 Type rettype; 3610 if (functionParameters(exp.loc, sc, tf, null, null, exp.newargs, f, &rettype, &newprefix)) 3611 return setError(); 3612 3613 exp.allocator = f.isNewDeclaration(); 3614 assert(exp.allocator); 3615 } 3616 else 3617 { 3618 if (exp.newargs && exp.newargs.dim) 3619 { 3620 exp.error("no allocator for `%s`", cd.toChars()); 3621 return setError(); 3622 } 3623 } 3624 3625 if (cd.ctor) 3626 { 3627 FuncDeclaration f = resolveFuncCall(exp.loc, sc, cd.ctor, null, tb, exp.arguments, FuncResolveFlag.standard); 3628 if (!f || f.errors) 3629 return setError(); 3630 3631 checkFunctionAttributes(exp, sc, f); 3632 checkAccess(cd, exp.loc, sc, f); 3633 3634 TypeFunction tf = cast(TypeFunction)f.type; 3635 if (!exp.arguments) 3636 exp.arguments = new Expressions(); 3637 if (functionParameters(exp.loc, sc, tf, null, exp.type, exp.arguments, f, &exp.type, &exp.argprefix)) 3638 return setError(); 3639 3640 exp.member = f.isCtorDeclaration(); 3641 assert(exp.member); 3642 } 3643 else 3644 { 3645 if (nargs) 3646 { 3647 exp.error("no constructor for `%s`", cd.toChars()); 3648 return setError(); 3649 } 3650 3651 // https://issues.dlang.org/show_bug.cgi?id=19941 3652 // Run semantic on all field initializers to resolve any forward 3653 // references. This is the same as done for structs in sd.fill(). 3654 for (ClassDeclaration c = cd; c; c = c.baseClass) 3655 { 3656 foreach (v; c.fields) 3657 { 3658 if (v.inuse || v._scope is null || v._init is null || 3659 v._init.isVoidInitializer()) 3660 continue; 3661 v.inuse++; 3662 v._init = v._init.initializerSemantic(v._scope, v.type, INITinterpret); 3663 v.inuse--; 3664 } 3665 } 3666 } 3667 } 3668 else if (tb.ty == Tstruct) 3669 { 3670 auto sd = (cast(TypeStruct)tb).sym; 3671 sd.size(exp.loc); 3672 if (sd.sizeok != Sizeok.done) 3673 return setError(); 3674 if (!sd.ctor) 3675 sd.ctor = sd.searchCtor(); 3676 if (sd.noDefaultCtor && !nargs) 3677 { 3678 exp.error("default construction is disabled for type `%s`", sd.type.toChars()); 3679 return setError(); 3680 } 3681 // checkDeprecated() is already done in newtype.typeSemantic(). 3682 3683 if (sd.aggNew) 3684 { 3685 // Prepend the uint size argument to newargs[] 3686 Expression e = new IntegerExp(exp.loc, sd.size(exp.loc), Type.tsize_t); 3687 if (!exp.newargs) 3688 exp.newargs = new Expressions(); 3689 exp.newargs.shift(e); 3690 3691 FuncDeclaration f = resolveFuncCall(exp.loc, sc, sd.aggNew, null, tb, exp.newargs, FuncResolveFlag.standard); 3692 if (!f || f.errors) 3693 return setError(); 3694 3695 checkFunctionAttributes(exp, sc, f); 3696 checkAccess(sd, exp.loc, sc, f); 3697 3698 TypeFunction tf = cast(TypeFunction)f.type; 3699 Type rettype; 3700 if (functionParameters(exp.loc, sc, tf, null, null, exp.newargs, f, &rettype, &newprefix)) 3701 return setError(); 3702 3703 exp.allocator = f.isNewDeclaration(); 3704 assert(exp.allocator); 3705 } 3706 else 3707 { 3708 if (exp.newargs && exp.newargs.dim) 3709 { 3710 exp.error("no allocator for `%s`", sd.toChars()); 3711 return setError(); 3712 } 3713 } 3714 3715 if (sd.ctor && nargs) 3716 { 3717 FuncDeclaration f = resolveFuncCall(exp.loc, sc, sd.ctor, null, tb, exp.arguments, FuncResolveFlag.standard); 3718 if (!f || f.errors) 3719 return setError(); 3720 3721 checkFunctionAttributes(exp, sc, f); 3722 checkAccess(sd, exp.loc, sc, f); 3723 3724 TypeFunction tf = cast(TypeFunction)f.type; 3725 if (!exp.arguments) 3726 exp.arguments = new Expressions(); 3727 if (functionParameters(exp.loc, sc, tf, null, exp.type, exp.arguments, f, &exp.type, &exp.argprefix)) 3728 return setError(); 3729 3730 exp.member = f.isCtorDeclaration(); 3731 assert(exp.member); 3732 3733 if (checkFrameAccess(exp.loc, sc, sd, sd.fields.dim)) 3734 return setError(); 3735 } 3736 else 3737 { 3738 if (!exp.arguments) 3739 exp.arguments = new Expressions(); 3740 3741 if (!sd.fit(exp.loc, sc, exp.arguments, tb)) 3742 return setError(); 3743 3744 if (!sd.fill(exp.loc, exp.arguments, false)) 3745 return setError(); 3746 3747 if (checkFrameAccess(exp.loc, sc, sd, exp.arguments ? exp.arguments.dim : 0)) 3748 return setError(); 3749 3750 /* Since a `new` allocation may escape, check each of the arguments for escaping 3751 */ 3752 if (global.params.vsafe) 3753 { 3754 foreach (arg; *exp.arguments) 3755 { 3756 if (arg && checkNewEscape(sc, arg, false)) 3757 return setError(); 3758 } 3759 } 3760 } 3761 3762 exp.type = exp.type.pointerTo(); 3763 } 3764 else if (tb.ty == Tarray && nargs) 3765 { 3766 Type tn = tb.nextOf().baseElemOf(); 3767 Dsymbol s = tn.toDsymbol(sc); 3768 AggregateDeclaration ad = s ? s.isAggregateDeclaration() : null; 3769 if (ad && ad.noDefaultCtor) 3770 { 3771 exp.error("default construction is disabled for type `%s`", tb.nextOf().toChars()); 3772 return setError(); 3773 } 3774 for (size_t i = 0; i < nargs; i++) 3775 { 3776 if (tb.ty != Tarray) 3777 { 3778 exp.error("too many arguments for array"); 3779 return setError(); 3780 } 3781 3782 Expression arg = (*exp.arguments)[i]; 3783 arg = resolveProperties(sc, arg); 3784 arg = arg.implicitCastTo(sc, Type.tsize_t); 3785 if (arg.op == TOK.error) 3786 return setError(); 3787 arg = arg.optimize(WANTvalue); 3788 if (arg.op == TOK.int64 && cast(sinteger_t)arg.toInteger() < 0) 3789 { 3790 exp.error("negative array index `%s`", arg.toChars()); 3791 return setError(); 3792 } 3793 (*exp.arguments)[i] = arg; 3794 tb = (cast(TypeDArray)tb).next.toBasetype(); 3795 } 3796 } 3797 else if (tb.isscalar()) 3798 { 3799 if (!nargs) 3800 { 3801 } 3802 else if (nargs == 1) 3803 { 3804 Expression e = (*exp.arguments)[0]; 3805 e = e.implicitCastTo(sc, tb); 3806 (*exp.arguments)[0] = e; 3807 } 3808 else 3809 { 3810 exp.error("more than one argument for construction of `%s`", exp.type.toChars()); 3811 return setError(); 3812 } 3813 3814 exp.type = exp.type.pointerTo(); 3815 } 3816 else 3817 { 3818 exp.error("cannot create a `%s` with `new`", exp.type.toChars()); 3819 return setError(); 3820 } 3821 3822 //printf("NewExp: '%s'\n", toChars()); 3823 //printf("NewExp:type '%s'\n", type.toChars()); 3824 semanticTypeInfo(sc, exp.type); 3825 3826 if (newprefix) 3827 { 3828 result = Expression.combine(newprefix, exp); 3829 return; 3830 } 3831 result = exp; 3832 } 3833 3834 override void visit(NewAnonClassExp e) 3835 { 3836 static if (LOGSEMANTIC) 3837 { 3838 printf("NewAnonClassExp::semantic() %s\n", e.toChars()); 3839 //printf("thisexp = %p\n", thisexp); 3840 //printf("type: %s\n", type.toChars()); 3841 } 3842 3843 Expression d = new DeclarationExp(e.loc, e.cd); 3844 sc = sc.push(); // just create new scope 3845 sc.flags &= ~SCOPE.ctfe; // temporary stop CTFE 3846 d = d.expressionSemantic(sc); 3847 sc = sc.pop(); 3848 3849 if (!e.cd.errors && sc.intypeof && !sc.parent.inNonRoot()) 3850 { 3851 ScopeDsymbol sds = sc.tinst ? cast(ScopeDsymbol)sc.tinst : sc._module; 3852 if (!sds.members) 3853 sds.members = new Dsymbols(); 3854 sds.members.push(e.cd); 3855 } 3856 3857 Expression n = new NewExp(e.loc, e.thisexp, e.newargs, e.cd.type, e.arguments); 3858 3859 Expression c = new CommaExp(e.loc, d, n); 3860 result = c.expressionSemantic(sc); 3861 } 3862 3863 override void visit(SymOffExp e) 3864 { 3865 static if (LOGSEMANTIC) 3866 { 3867 printf("SymOffExp::semantic('%s')\n", e.toChars()); 3868 } 3869 //var.dsymbolSemantic(sc); 3870 if (!e.type) 3871 e.type = e.var.type.pointerTo(); 3872 3873 if (auto v = e.var.isVarDeclaration()) 3874 { 3875 if (v.checkNestedReference(sc, e.loc)) 3876 return setError(); 3877 } 3878 else if (auto f = e.var.isFuncDeclaration()) 3879 { 3880 if (f.checkNestedReference(sc, e.loc)) 3881 return setError(); 3882 } 3883 3884 result = e; 3885 } 3886 3887 override void visit(VarExp e) 3888 { 3889 static if (LOGSEMANTIC) 3890 { 3891 printf("VarExp::semantic(%s)\n", e.toChars()); 3892 } 3893 3894 auto vd = e.var.isVarDeclaration(); 3895 auto fd = e.var.isFuncDeclaration(); 3896 3897 if (fd) 3898 { 3899 //printf("L%d fd = %s\n", __LINE__, f.toChars()); 3900 if (!fd.functionSemantic()) 3901 return setError(); 3902 } 3903 3904 if (!e.type) 3905 e.type = e.var.type; 3906 if (e.type && !e.type.deco) 3907 { 3908 auto decl = e.var.isDeclaration(); 3909 if (decl) 3910 decl.inuse++; 3911 e.type = e.type.typeSemantic(e.loc, sc); 3912 if (decl) 3913 decl.inuse--; 3914 } 3915 3916 /* Fix for 1161 doesn't work because it causes protection 3917 * problems when instantiating imported templates passing private 3918 * variables as alias template parameters. 3919 */ 3920 //checkAccess(loc, sc, NULL, var); 3921 3922 if (vd) 3923 { 3924 if (vd.checkNestedReference(sc, e.loc)) 3925 return setError(); 3926 3927 // https://issues.dlang.org/show_bug.cgi?id=12025 3928 // If the variable is not actually used in runtime code, 3929 // the purity violation error is redundant. 3930 //checkPurity(sc, vd); 3931 } 3932 else if (fd) 3933 { 3934 // TODO: If fd isn't yet resolved its overload, the checkNestedReference 3935 // call would cause incorrect validation. 3936 // Maybe here should be moved in CallExp, or AddrExp for functions. 3937 if (fd.checkNestedReference(sc, e.loc)) 3938 return setError(); 3939 } 3940 else if (auto od = e.var.isOverDeclaration()) 3941 { 3942 e.type = Type.tvoid; // ambiguous type? 3943 } 3944 3945 result = e; 3946 } 3947 3948 override void visit(FuncExp exp) 3949 { 3950 static if (LOGSEMANTIC) 3951 { 3952 printf("FuncExp::semantic(%s)\n", exp.toChars()); 3953 if (exp.fd.treq) 3954 printf(" treq = %s\n", exp.fd.treq.toChars()); 3955 } 3956 3957 if (exp.type) 3958 { 3959 result = exp; 3960 return; 3961 } 3962 3963 Expression e = exp; 3964 uint olderrors; 3965 3966 sc = sc.push(); // just create new scope 3967 sc.flags &= ~SCOPE.ctfe; // temporary stop CTFE 3968 sc.protection = Prot(Prot.Kind.public_); // https://issues.dlang.org/show_bug.cgi?id=12506 3969 3970 /* fd.treq might be incomplete type, 3971 * so should not semantic it. 3972 * void foo(T)(T delegate(int) dg){} 3973 * foo(a=>a); // in IFTI, treq == T delegate(int) 3974 */ 3975 //if (fd.treq) 3976 // fd.treq = fd.treq.dsymbolSemantic(loc, sc); 3977 3978 exp.genIdent(sc); 3979 3980 // Set target of return type inference 3981 if (exp.fd.treq && !exp.fd.type.nextOf()) 3982 { 3983 TypeFunction tfv = null; 3984 if (exp.fd.treq.ty == Tdelegate || (exp.fd.treq.ty == Tpointer && exp.fd.treq.nextOf().ty == Tfunction)) 3985 tfv = cast(TypeFunction)exp.fd.treq.nextOf(); 3986 if (tfv) 3987 { 3988 TypeFunction tfl = cast(TypeFunction)exp.fd.type; 3989 tfl.next = tfv.nextOf(); 3990 } 3991 } 3992 3993 //printf("td = %p, treq = %p\n", td, fd.treq); 3994 if (exp.td) 3995 { 3996 assert(exp.td.parameters && exp.td.parameters.dim); 3997 exp.td.dsymbolSemantic(sc); 3998 exp.type = Type.tvoid; // temporary type 3999 4000 if (exp.fd.treq) // defer type determination 4001 { 4002 FuncExp fe; 4003 if (exp.matchType(exp.fd.treq, sc, &fe) > MATCH.nomatch) 4004 e = fe; 4005 else 4006 e = new ErrorExp(); 4007 } 4008 goto Ldone; 4009 } 4010 4011 olderrors = global.errors; 4012 exp.fd.dsymbolSemantic(sc); 4013 if (olderrors == global.errors) 4014 { 4015 exp.fd.semantic2(sc); 4016 if (olderrors == global.errors) 4017 exp.fd.semantic3(sc); 4018 } 4019 if (olderrors != global.errors) 4020 { 4021 if (exp.fd.type && exp.fd.type.ty == Tfunction && !exp.fd.type.nextOf()) 4022 (cast(TypeFunction)exp.fd.type).next = Type.terror; 4023 e = new ErrorExp(); 4024 goto Ldone; 4025 } 4026 4027 // Type is a "delegate to" or "pointer to" the function literal 4028 if ((exp.fd.isNested() && exp.fd.tok == TOK.delegate_) || (exp.tok == TOK.reserved && exp.fd.treq && exp.fd.treq.ty == Tdelegate)) 4029 { 4030 exp.type = new TypeDelegate(exp.fd.type); 4031 exp.type = exp.type.typeSemantic(exp.loc, sc); 4032 4033 exp.fd.tok = TOK.delegate_; 4034 } 4035 else 4036 { 4037 exp.type = new TypePointer(exp.fd.type); 4038 exp.type = exp.type.typeSemantic(exp.loc, sc); 4039 //type = fd.type.pointerTo(); 4040 4041 /* A lambda expression deduced to function pointer might become 4042 * to a delegate literal implicitly. 4043 * 4044 * auto foo(void function() fp) { return 1; } 4045 * assert(foo({}) == 1); 4046 * 4047 * So, should keep fd.tok == TOKreserve if fd.treq == NULL. 4048 */ 4049 if (exp.fd.treq && exp.fd.treq.ty == Tpointer) 4050 { 4051 // change to non-nested 4052 exp.fd.tok = TOK.function_; 4053 exp.fd.vthis = null; 4054 } 4055 } 4056 exp.fd.tookAddressOf++; 4057 4058 Ldone: 4059 sc = sc.pop(); 4060 result = e; 4061 } 4062 4063 /** 4064 * Perform semantic analysis on function literals 4065 * 4066 * Test the following construct: 4067 * --- 4068 * (x, y, z) { return x + y + z; }(42, 84, 1992); 4069 * --- 4070 */ 4071 Expression callExpSemantic(FuncExp exp, Scope* sc, Expressions* arguments) 4072 { 4073 if ((!exp.type || exp.type == Type.tvoid) && exp.td && arguments && arguments.dim) 4074 { 4075 for (size_t k = 0; k < arguments.dim; k++) 4076 { 4077 Expression checkarg = (*arguments)[k]; 4078 if (checkarg.op == TOK.error) 4079 return checkarg; 4080 } 4081 4082 exp.genIdent(sc); 4083 4084 assert(exp.td.parameters && exp.td.parameters.dim); 4085 exp.td.dsymbolSemantic(sc); 4086 4087 TypeFunction tfl = cast(TypeFunction)exp.fd.type; 4088 size_t dim = tfl.parameterList.length; 4089 if (arguments.dim < dim) 4090 { 4091 // Default arguments are always typed, so they don't need inference. 4092 Parameter p = tfl.parameterList[arguments.dim]; 4093 if (p.defaultArg) 4094 dim = arguments.dim; 4095 } 4096 4097 if ((tfl.parameterList.varargs == VarArg.none && arguments.dim > dim) || 4098 arguments.dim < dim) 4099 { 4100 OutBuffer buf; 4101 foreach (idx, ref arg; *arguments) 4102 buf.printf("%s%s", (idx ? ", ".ptr : "".ptr), arg.type.toChars()); 4103 exp.error("function literal `%s%s` is not callable using argument types `(%s)`", 4104 exp.fd.toChars(), parametersTypeToChars(tfl.parameterList), 4105 buf.peekChars()); 4106 exp.errorSupplemental("too %s arguments, expected `%d`, got `%d`", 4107 arguments.dim < dim ? "few".ptr : "many".ptr, 4108 cast(int)dim, cast(int)arguments.dim); 4109 return new ErrorExp(); 4110 } 4111 4112 auto tiargs = new Objects(); 4113 tiargs.reserve(exp.td.parameters.dim); 4114 4115 for (size_t i = 0; i < exp.td.parameters.dim; i++) 4116 { 4117 TemplateParameter tp = (*exp.td.parameters)[i]; 4118 for (size_t u = 0; u < dim; u++) 4119 { 4120 Parameter p = tfl.parameterList[u]; 4121 if (p.type.ty == Tident && (cast(TypeIdentifier)p.type).ident == tp.ident) 4122 { 4123 Expression e = (*arguments)[u]; 4124 tiargs.push(e.type); 4125 u = dim; // break inner loop 4126 } 4127 } 4128 } 4129 4130 auto ti = new TemplateInstance(exp.loc, exp.td, tiargs); 4131 return (new ScopeExp(exp.loc, ti)).expressionSemantic(sc); 4132 } 4133 return exp.expressionSemantic(sc); 4134 } 4135 4136 override void visit(CallExp exp) 4137 { 4138 static if (LOGSEMANTIC) 4139 { 4140 printf("CallExp::semantic() %s\n", exp.toChars()); 4141 } 4142 if (exp.type) 4143 { 4144 result = exp; 4145 return; // semantic() already run 4146 } 4147 4148 Objects* tiargs = null; // initial list of template arguments 4149 Expression ethis = null; 4150 Type tthis = null; 4151 Expression e1org = exp.e1; 4152 4153 if (exp.e1.op == TOK.comma) 4154 { 4155 /* Rewrite (a,b)(args) as (a,(b(args))) 4156 */ 4157 auto ce = cast(CommaExp)exp.e1; 4158 exp.e1 = ce.e2; 4159 ce.e2 = exp; 4160 result = ce.expressionSemantic(sc); 4161 return; 4162 } 4163 if (exp.e1.op == TOK.delegate_) 4164 { 4165 DelegateExp de = cast(DelegateExp)exp.e1; 4166 exp.e1 = new DotVarExp(de.loc, de.e1, de.func, de.hasOverloads); 4167 visit(exp); 4168 return; 4169 } 4170 if (exp.e1.op == TOK.function_) 4171 { 4172 if (arrayExpressionSemantic(exp.arguments, sc) || preFunctionParameters(sc, exp.arguments)) 4173 return setError(); 4174 4175 // Run e1 semantic even if arguments have any errors 4176 FuncExp fe = cast(FuncExp)exp.e1; 4177 exp.e1 = callExpSemantic(fe, sc, exp.arguments); 4178 if (exp.e1.op == TOK.error) 4179 { 4180 result = exp.e1; 4181 return; 4182 } 4183 } 4184 4185 if (Expression ex = resolveUFCS(sc, exp)) 4186 { 4187 result = ex; 4188 return; 4189 } 4190 4191 /* This recognizes: 4192 * foo!(tiargs)(funcargs) 4193 */ 4194 if (exp.e1.op == TOK.scope_) 4195 { 4196 ScopeExp se = cast(ScopeExp)exp.e1; 4197 TemplateInstance ti = se.sds.isTemplateInstance(); 4198 if (ti) 4199 { 4200 /* Attempt to instantiate ti. If that works, go with it. 4201 * If not, go with partial explicit specialization. 4202 */ 4203 WithScopeSymbol withsym; 4204 if (!ti.findTempDecl(sc, &withsym) || !ti.semanticTiargs(sc)) 4205 return setError(); 4206 if (withsym && withsym.withstate.wthis) 4207 { 4208 exp.e1 = new VarExp(exp.e1.loc, withsym.withstate.wthis); 4209 exp.e1 = new DotTemplateInstanceExp(exp.e1.loc, exp.e1, ti); 4210 goto Ldotti; 4211 } 4212 if (ti.needsTypeInference(sc, 1)) 4213 { 4214 /* Go with partial explicit specialization 4215 */ 4216 tiargs = ti.tiargs; 4217 assert(ti.tempdecl); 4218 if (TemplateDeclaration td = ti.tempdecl.isTemplateDeclaration()) 4219 exp.e1 = new TemplateExp(exp.loc, td); 4220 else if (OverDeclaration od = ti.tempdecl.isOverDeclaration()) 4221 exp.e1 = new VarExp(exp.loc, od); 4222 else 4223 exp.e1 = new OverExp(exp.loc, ti.tempdecl.isOverloadSet()); 4224 } 4225 else 4226 { 4227 Expression e1x = exp.e1.expressionSemantic(sc); 4228 if (e1x.op == TOK.error) 4229 { 4230 result = e1x; 4231 return; 4232 } 4233 exp.e1 = e1x; 4234 } 4235 } 4236 } 4237 4238 /* This recognizes: 4239 * expr.foo!(tiargs)(funcargs) 4240 */ 4241 Ldotti: 4242 if (exp.e1.op == TOK.dotTemplateInstance && !exp.e1.type) 4243 { 4244 DotTemplateInstanceExp se = cast(DotTemplateInstanceExp)exp.e1; 4245 TemplateInstance ti = se.ti; 4246 { 4247 /* Attempt to instantiate ti. If that works, go with it. 4248 * If not, go with partial explicit specialization. 4249 */ 4250 if (!se.findTempDecl(sc) || !ti.semanticTiargs(sc)) 4251 return setError(); 4252 if (ti.needsTypeInference(sc, 1)) 4253 { 4254 /* Go with partial explicit specialization 4255 */ 4256 tiargs = ti.tiargs; 4257 assert(ti.tempdecl); 4258 if (TemplateDeclaration td = ti.tempdecl.isTemplateDeclaration()) 4259 exp.e1 = new DotTemplateExp(exp.loc, se.e1, td); 4260 else if (OverDeclaration od = ti.tempdecl.isOverDeclaration()) 4261 { 4262 exp.e1 = new DotVarExp(exp.loc, se.e1, od, true); 4263 } 4264 else 4265 exp.e1 = new DotExp(exp.loc, se.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 Lagain: 4281 //printf("Lagain: %s\n", toChars()); 4282 exp.f = null; 4283 if (exp.e1.op == TOK.this_ || exp.e1.op == TOK.super_) 4284 { 4285 // semantic() run later for these 4286 } 4287 else 4288 { 4289 if (exp.e1.op == TOK.dotIdentifier) 4290 { 4291 DotIdExp die = cast(DotIdExp)exp.e1; 4292 exp.e1 = die.expressionSemantic(sc); 4293 /* Look for e1 having been rewritten to expr.opDispatch!(string) 4294 * We handle such earlier, so go back. 4295 * Note that in the rewrite, we carefully did not run semantic() on e1 4296 */ 4297 if (exp.e1.op == TOK.dotTemplateInstance && !exp.e1.type) 4298 { 4299 goto Ldotti; 4300 } 4301 } 4302 else 4303 { 4304 __gshared int nest; 4305 if (++nest > global.recursionLimit) 4306 { 4307 exp.error("recursive evaluation of `%s`", exp.toChars()); 4308 --nest; 4309 return setError(); 4310 } 4311 Expression ex = unaSemantic(exp, sc); 4312 --nest; 4313 if (ex) 4314 { 4315 result = ex; 4316 return; 4317 } 4318 } 4319 4320 /* Look for e1 being a lazy parameter 4321 */ 4322 if (exp.e1.op == TOK.variable) 4323 { 4324 VarExp ve = cast(VarExp)exp.e1; 4325 if (ve.var.storage_class & STC.lazy_) 4326 { 4327 // lazy parameters can be called without violating purity and safety 4328 Type tw = ve.var.type; 4329 Type tc = ve.var.type.substWildTo(MODFlags.const_); 4330 auto tf = new TypeFunction(ParameterList(), tc, LINK.d, STC.safe | STC.pure_); 4331 (tf = cast(TypeFunction)tf.typeSemantic(exp.loc, sc)).next = tw; // hack for bug7757 4332 auto t = new TypeDelegate(tf); 4333 ve.type = t.typeSemantic(exp.loc, sc); 4334 } 4335 VarDeclaration v = ve.var.isVarDeclaration(); 4336 if (v && ve.checkPurity(sc, v)) 4337 return setError(); 4338 } 4339 4340 if (exp.e1.op == TOK.symbolOffset && (cast(SymOffExp)exp.e1).hasOverloads) 4341 { 4342 SymOffExp se = cast(SymOffExp)exp.e1; 4343 exp.e1 = new VarExp(se.loc, se.var, true); 4344 exp.e1 = exp.e1.expressionSemantic(sc); 4345 } 4346 else if (exp.e1.op == TOK.dot) 4347 { 4348 DotExp de = cast(DotExp)exp.e1; 4349 4350 if (de.e2.op == TOK.overloadSet) 4351 { 4352 ethis = de.e1; 4353 tthis = de.e1.type; 4354 exp.e1 = de.e2; 4355 } 4356 } 4357 else if (exp.e1.op == TOK.star && exp.e1.type.ty == Tfunction) 4358 { 4359 // Rewrite (*fp)(arguments) to fp(arguments) 4360 exp.e1 = (cast(PtrExp)exp.e1).e1; 4361 } 4362 } 4363 4364 Type t1 = exp.e1.type ? exp.e1.type.toBasetype() : null; 4365 4366 if (exp.e1.op == TOK.error) 4367 { 4368 result = exp.e1; 4369 return; 4370 } 4371 if (arrayExpressionSemantic(exp.arguments, sc) || preFunctionParameters(sc, exp.arguments)) 4372 return setError(); 4373 4374 // Check for call operator overload 4375 if (t1) 4376 { 4377 if (t1.ty == Tstruct) 4378 { 4379 auto sd = (cast(TypeStruct)t1).sym; 4380 sd.size(exp.loc); // Resolve forward references to construct object 4381 if (sd.sizeok != Sizeok.done) 4382 return setError(); 4383 if (!sd.ctor) 4384 sd.ctor = sd.searchCtor(); 4385 /* If `sd.ctor` is a generated copy constructor, this means that it 4386 is the single constructor that this struct has. In order to not 4387 disable default construction, the ctor is nullified. The side effect 4388 of this is that the generated copy constructor cannot be called 4389 explicitly, but that is ok, because when calling a constructor the 4390 default constructor should have priority over the generated copy 4391 constructor. 4392 */ 4393 if (sd.ctor) 4394 { 4395 auto ctor = sd.ctor.isCtorDeclaration(); 4396 if (ctor && ctor.isCpCtor && ctor.generated) 4397 sd.ctor = null; 4398 } 4399 4400 // First look for constructor 4401 if (exp.e1.op == TOK.type && sd.ctor) 4402 { 4403 if (!sd.noDefaultCtor && !(exp.arguments && exp.arguments.dim)) 4404 goto Lx; 4405 4406 auto sle = new StructLiteralExp(exp.loc, sd, null, exp.e1.type); 4407 if (!sd.fill(exp.loc, sle.elements, true)) 4408 return setError(); 4409 if (checkFrameAccess(exp.loc, sc, sd, sle.elements.dim)) 4410 return setError(); 4411 4412 // https://issues.dlang.org/show_bug.cgi?id=14556 4413 // Set concrete type to avoid further redundant semantic(). 4414 sle.type = exp.e1.type; 4415 4416 /* Constructor takes a mutable object, so don't use 4417 * the immutable initializer symbol. 4418 */ 4419 sle.useStaticInit = false; 4420 4421 Expression e = sle; 4422 if (auto cf = sd.ctor.isCtorDeclaration()) 4423 { 4424 e = new DotVarExp(exp.loc, e, cf, true); 4425 } 4426 else if (auto td = sd.ctor.isTemplateDeclaration()) 4427 { 4428 e = new DotIdExp(exp.loc, e, td.ident); 4429 } 4430 else if (auto os = sd.ctor.isOverloadSet()) 4431 { 4432 e = new DotExp(exp.loc, e, new OverExp(exp.loc, os)); 4433 } 4434 else 4435 assert(0); 4436 e = new CallExp(exp.loc, e, exp.arguments); 4437 e = e.expressionSemantic(sc); 4438 result = e; 4439 return; 4440 } 4441 // No constructor, look for overload of opCall 4442 if (search_function(sd, Id.call)) 4443 goto L1; 4444 // overload of opCall, therefore it's a call 4445 if (exp.e1.op != TOK.type) 4446 { 4447 if (sd.aliasthis && exp.e1.type != exp.att1) 4448 { 4449 if (!exp.att1 && exp.e1.type.checkAliasThisRec()) 4450 exp.att1 = exp.e1.type; 4451 exp.e1 = resolveAliasThis(sc, exp.e1); 4452 goto Lagain; 4453 } 4454 exp.error("%s `%s` does not overload ()", sd.kind(), sd.toChars()); 4455 return setError(); 4456 } 4457 4458 /* It's a struct literal 4459 */ 4460 Lx: 4461 Expression e = new StructLiteralExp(exp.loc, sd, exp.arguments, exp.e1.type); 4462 e = e.expressionSemantic(sc); 4463 result = e; 4464 return; 4465 } 4466 else if (t1.ty == Tclass) 4467 { 4468 L1: 4469 // Rewrite as e1.call(arguments) 4470 Expression e = new DotIdExp(exp.loc, exp.e1, Id.call); 4471 e = new CallExp(exp.loc, e, exp.arguments); 4472 e = e.expressionSemantic(sc); 4473 result = e; 4474 return; 4475 } 4476 else if (exp.e1.op == TOK.type && t1.isscalar()) 4477 { 4478 Expression e; 4479 4480 // Make sure to use the the enum type itself rather than its 4481 // base type 4482 // https://issues.dlang.org/show_bug.cgi?id=16346 4483 if (exp.e1.type.ty == Tenum) 4484 { 4485 t1 = exp.e1.type; 4486 } 4487 4488 if (!exp.arguments || exp.arguments.dim == 0) 4489 { 4490 e = t1.defaultInitLiteral(exp.loc); 4491 } 4492 else if (exp.arguments.dim == 1) 4493 { 4494 e = (*exp.arguments)[0]; 4495 e = e.implicitCastTo(sc, t1); 4496 e = new CastExp(exp.loc, e, t1); 4497 } 4498 else 4499 { 4500 exp.error("more than one argument for construction of `%s`", t1.toChars()); 4501 return setError(); 4502 } 4503 e = e.expressionSemantic(sc); 4504 result = e; 4505 return; 4506 } 4507 } 4508 4509 static FuncDeclaration resolveOverloadSet(Loc loc, Scope* sc, 4510 OverloadSet os, Objects* tiargs, Type tthis, Expressions* arguments) 4511 { 4512 FuncDeclaration f = null; 4513 foreach (s; os.a) 4514 { 4515 if (tiargs && s.isFuncDeclaration()) 4516 continue; 4517 if (auto f2 = resolveFuncCall(loc, sc, s, tiargs, tthis, arguments, FuncResolveFlag.quiet)) 4518 { 4519 if (f2.errors) 4520 return null; 4521 if (f) 4522 { 4523 /* Error if match in more than one overload set, 4524 * even if one is a 'better' match than the other. 4525 */ 4526 ScopeDsymbol.multiplyDefined(loc, f, f2); 4527 } 4528 else 4529 f = f2; 4530 } 4531 } 4532 if (!f) 4533 .error(loc, "no overload matches for `%s`", os.toChars()); 4534 else if (f.errors) 4535 f = null; 4536 return f; 4537 } 4538 4539 bool isSuper = false; 4540 if (exp.e1.op == TOK.dotVariable && t1.ty == Tfunction || exp.e1.op == TOK.dotTemplateDeclaration) 4541 { 4542 UnaExp ue = cast(UnaExp)exp.e1; 4543 4544 Expression ue1 = ue.e1; 4545 Expression ue1old = ue1; // need for 'right this' check 4546 VarDeclaration v; 4547 if (ue1.op == TOK.variable && (v = (cast(VarExp)ue1).var.isVarDeclaration()) !is null && v.needThis()) 4548 { 4549 ue.e1 = new TypeExp(ue1.loc, ue1.type); 4550 ue1 = null; 4551 } 4552 4553 DotVarExp dve; 4554 DotTemplateExp dte; 4555 Dsymbol s; 4556 if (exp.e1.op == TOK.dotVariable) 4557 { 4558 dve = cast(DotVarExp)exp.e1; 4559 dte = null; 4560 s = dve.var; 4561 tiargs = null; 4562 } 4563 else 4564 { 4565 dve = null; 4566 dte = cast(DotTemplateExp)exp.e1; 4567 s = dte.td; 4568 } 4569 4570 // Do overload resolution 4571 exp.f = resolveFuncCall(exp.loc, sc, s, tiargs, ue1 ? ue1.type : null, exp.arguments, FuncResolveFlag.standard); 4572 if (!exp.f || exp.f.errors || exp.f.type.ty == Terror) 4573 return setError(); 4574 4575 if (exp.f.interfaceVirtual) 4576 { 4577 /* Cast 'this' to the type of the interface, and replace f with the interface's equivalent 4578 */ 4579 auto b = exp.f.interfaceVirtual; 4580 auto ad2 = b.sym; 4581 ue.e1 = ue.e1.castTo(sc, ad2.type.addMod(ue.e1.type.mod)); 4582 ue.e1 = ue.e1.expressionSemantic(sc); 4583 ue1 = ue.e1; 4584 auto vi = exp.f.findVtblIndex(&ad2.vtbl, cast(int)ad2.vtbl.dim); 4585 assert(vi >= 0); 4586 exp.f = ad2.vtbl[vi].isFuncDeclaration(); 4587 assert(exp.f); 4588 } 4589 if (exp.f.needThis()) 4590 { 4591 AggregateDeclaration ad = exp.f.toParentLocal().isAggregateDeclaration(); 4592 ue.e1 = getRightThis(exp.loc, sc, ad, ue.e1, exp.f); 4593 if (ue.e1.op == TOK.error) 4594 { 4595 result = ue.e1; 4596 return; 4597 } 4598 ethis = ue.e1; 4599 tthis = ue.e1.type; 4600 if (!(exp.f.type.ty == Tfunction && (cast(TypeFunction)exp.f.type).isscope)) 4601 { 4602 if (global.params.vsafe && checkParamArgumentEscape(sc, exp.f, null, ethis, false, false)) 4603 return setError(); 4604 } 4605 } 4606 4607 /* Cannot call public functions from inside invariant 4608 * (because then the invariant would have infinite recursion) 4609 */ 4610 if (sc.func && sc.func.isInvariantDeclaration() && ue.e1.op == TOK.this_ && exp.f.addPostInvariant()) 4611 { 4612 exp.error("cannot call `public`/`export` function `%s` from invariant", exp.f.toChars()); 4613 return setError(); 4614 } 4615 4616 checkFunctionAttributes(exp, sc, exp.f); 4617 checkAccess(exp.loc, sc, ue.e1, exp.f); 4618 if (!exp.f.needThis()) 4619 { 4620 exp.e1 = Expression.combine(ue.e1, new VarExp(exp.loc, exp.f, false)); 4621 } 4622 else 4623 { 4624 if (ue1old.checkRightThis(sc)) 4625 return setError(); 4626 if (exp.e1.op == TOK.dotVariable) 4627 { 4628 dve.var = exp.f; 4629 exp.e1.type = exp.f.type; 4630 } 4631 else 4632 { 4633 exp.e1 = new DotVarExp(exp.loc, dte.e1, exp.f, false); 4634 exp.e1 = exp.e1.expressionSemantic(sc); 4635 if (exp.e1.op == TOK.error) 4636 return setError(); 4637 ue = cast(UnaExp)exp.e1; 4638 } 4639 version (none) 4640 { 4641 printf("ue.e1 = %s\n", ue.e1.toChars()); 4642 printf("f = %s\n", exp.f.toChars()); 4643 printf("t = %s\n", t.toChars()); 4644 printf("e1 = %s\n", exp.e1.toChars()); 4645 printf("e1.type = %s\n", exp.e1.type.toChars()); 4646 } 4647 4648 // See if we need to adjust the 'this' pointer 4649 AggregateDeclaration ad = exp.f.isThis(); 4650 ClassDeclaration cd = ue.e1.type.isClassHandle(); 4651 if (ad && cd && ad.isClassDeclaration()) 4652 { 4653 if (ue.e1.op == TOK.dotType) 4654 { 4655 ue.e1 = (cast(DotTypeExp)ue.e1).e1; 4656 exp.directcall = true; 4657 } 4658 else if (ue.e1.op == TOK.super_) 4659 exp.directcall = true; 4660 else if ((cd.storage_class & STC.final_) != 0) // https://issues.dlang.org/show_bug.cgi?id=14211 4661 exp.directcall = true; 4662 4663 if (ad != cd) 4664 { 4665 ue.e1 = ue.e1.castTo(sc, ad.type.addMod(ue.e1.type.mod)); 4666 ue.e1 = ue.e1.expressionSemantic(sc); 4667 } 4668 } 4669 } 4670 // If we've got a pointer to a function then deference it 4671 // https://issues.dlang.org/show_bug.cgi?id=16483 4672 if (exp.e1.type.ty == Tpointer && exp.e1.type.nextOf().ty == Tfunction) 4673 { 4674 Expression e = new PtrExp(exp.loc, exp.e1); 4675 e.type = exp.e1.type.nextOf(); 4676 exp.e1 = e; 4677 } 4678 t1 = exp.e1.type; 4679 } 4680 else if (exp.e1.op == TOK.super_ || exp.e1.op == TOK.this_) 4681 { 4682 auto ad = sc.func ? sc.func.isThis() : null; 4683 auto cd = ad ? ad.isClassDeclaration() : null; 4684 4685 isSuper = exp.e1.op == TOK.super_; 4686 if (isSuper) 4687 { 4688 // Base class constructor call 4689 if (!cd || !cd.baseClass || !sc.func.isCtorDeclaration()) 4690 { 4691 exp.error("super class constructor call must be in a constructor"); 4692 return setError(); 4693 } 4694 if (!cd.baseClass.ctor) 4695 { 4696 exp.error("no super class constructor for `%s`", cd.baseClass.toChars()); 4697 return setError(); 4698 } 4699 } 4700 else 4701 { 4702 // `this` call expression must be inside a 4703 // constructor 4704 if (!ad || !sc.func.isCtorDeclaration()) 4705 { 4706 exp.error("constructor call must be in a constructor"); 4707 return setError(); 4708 } 4709 4710 // https://issues.dlang.org/show_bug.cgi?id=18719 4711 // If `exp` is a call expression to another constructor 4712 // then it means that all struct/class fields will be 4713 // initialized after this call. 4714 foreach (ref field; sc.ctorflow.fieldinit) 4715 { 4716 field.csx |= CSX.this_ctor; 4717 } 4718 } 4719 4720 if (!sc.intypeof && !(sc.ctorflow.callSuper & CSX.halt)) 4721 { 4722 if (sc.inLoop || sc.ctorflow.callSuper & CSX.label) 4723 exp.error("constructor calls not allowed in loops or after labels"); 4724 if (sc.ctorflow.callSuper & (CSX.super_ctor | CSX.this_ctor)) 4725 exp.error("multiple constructor calls"); 4726 if ((sc.ctorflow.callSuper & CSX.return_) && !(sc.ctorflow.callSuper & CSX.any_ctor)) 4727 exp.error("an earlier `return` statement skips constructor"); 4728 sc.ctorflow.callSuper |= CSX.any_ctor | (isSuper ? CSX.super_ctor : CSX.this_ctor); 4729 } 4730 4731 tthis = ad.type.addMod(sc.func.type.mod); 4732 auto ctor = isSuper ? cd.baseClass.ctor : ad.ctor; 4733 if (auto os = ctor.isOverloadSet()) 4734 exp.f = resolveOverloadSet(exp.loc, sc, os, null, tthis, exp.arguments); 4735 else 4736 exp.f = resolveFuncCall(exp.loc, sc, ctor, null, tthis, exp.arguments, FuncResolveFlag.standard); 4737 4738 if (!exp.f || exp.f.errors) 4739 return setError(); 4740 4741 checkFunctionAttributes(exp, sc, exp.f); 4742 checkAccess(exp.loc, sc, null, exp.f); 4743 4744 exp.e1 = new DotVarExp(exp.e1.loc, exp.e1, exp.f, false); 4745 exp.e1 = exp.e1.expressionSemantic(sc); 4746 t1 = exp.e1.type; 4747 4748 // BUG: this should really be done by checking the static 4749 // call graph 4750 if (exp.f == sc.func) 4751 { 4752 exp.error("cyclic constructor call"); 4753 return setError(); 4754 } 4755 } 4756 else if (exp.e1.op == TOK.overloadSet) 4757 { 4758 auto os = (cast(OverExp)exp.e1).vars; 4759 exp.f = resolveOverloadSet(exp.loc, sc, os, tiargs, tthis, exp.arguments); 4760 if (!exp.f) 4761 return setError(); 4762 if (ethis) 4763 exp.e1 = new DotVarExp(exp.loc, ethis, exp.f, false); 4764 else 4765 exp.e1 = new VarExp(exp.loc, exp.f, false); 4766 goto Lagain; 4767 } 4768 else if (!t1) 4769 { 4770 exp.error("function expected before `()`, not `%s`", exp.e1.toChars()); 4771 return setError(); 4772 } 4773 else if (t1.ty == Terror) 4774 { 4775 return setError(); 4776 } 4777 else if (t1.ty != Tfunction) 4778 { 4779 TypeFunction tf; 4780 const(char)* p; 4781 Dsymbol s; 4782 exp.f = null; 4783 if (exp.e1.op == TOK.function_) 4784 { 4785 // function literal that direct called is always inferred. 4786 assert((cast(FuncExp)exp.e1).fd); 4787 exp.f = (cast(FuncExp)exp.e1).fd; 4788 tf = cast(TypeFunction)exp.f.type; 4789 p = "function literal"; 4790 } 4791 else if (t1.ty == Tdelegate) 4792 { 4793 TypeDelegate td = cast(TypeDelegate)t1; 4794 assert(td.next.ty == Tfunction); 4795 tf = cast(TypeFunction)td.next; 4796 p = "delegate"; 4797 } 4798 else if (t1.ty == Tpointer && (cast(TypePointer)t1).next.ty == Tfunction) 4799 { 4800 tf = cast(TypeFunction)(cast(TypePointer)t1).next; 4801 p = "function pointer"; 4802 } 4803 else if (exp.e1.op == TOK.dotVariable && (cast(DotVarExp)exp.e1).var.isOverDeclaration()) 4804 { 4805 DotVarExp dve = cast(DotVarExp)exp.e1; 4806 exp.f = resolveFuncCall(exp.loc, sc, dve.var, tiargs, dve.e1.type, exp.arguments, FuncResolveFlag.overloadOnly); 4807 if (!exp.f) 4808 return setError(); 4809 if (exp.f.needThis()) 4810 { 4811 dve.var = exp.f; 4812 dve.type = exp.f.type; 4813 dve.hasOverloads = false; 4814 goto Lagain; 4815 } 4816 exp.e1 = new VarExp(dve.loc, exp.f, false); 4817 Expression e = new CommaExp(exp.loc, dve.e1, exp); 4818 result = e.expressionSemantic(sc); 4819 return; 4820 } 4821 else if (exp.e1.op == TOK.variable && (cast(VarExp)exp.e1).var.isOverDeclaration()) 4822 { 4823 s = (cast(VarExp)exp.e1).var; 4824 goto L2; 4825 } 4826 else if (exp.e1.op == TOK.template_) 4827 { 4828 s = (cast(TemplateExp)exp.e1).td; 4829 L2: 4830 exp.f = resolveFuncCall(exp.loc, sc, s, tiargs, null, exp.arguments, FuncResolveFlag.standard); 4831 if (!exp.f || exp.f.errors) 4832 return setError(); 4833 if (exp.f.needThis()) 4834 { 4835 if (hasThis(sc)) 4836 { 4837 // Supply an implicit 'this', as in 4838 // this.ident 4839 exp.e1 = new DotVarExp(exp.loc, (new ThisExp(exp.loc)).expressionSemantic(sc), exp.f, false); 4840 goto Lagain; 4841 } 4842 else if (isNeedThisScope(sc, exp.f)) 4843 { 4844 exp.error("need `this` for `%s` of type `%s`", exp.f.toChars(), exp.f.type.toChars()); 4845 return setError(); 4846 } 4847 } 4848 exp.e1 = new VarExp(exp.e1.loc, exp.f, false); 4849 goto Lagain; 4850 } 4851 else 4852 { 4853 exp.error("function expected before `()`, not `%s` of type `%s`", exp.e1.toChars(), exp.e1.type.toChars()); 4854 return setError(); 4855 } 4856 4857 const(char)* failMessage; 4858 Expression[] fargs = exp.arguments ? (*exp.arguments)[] : null; 4859 if (!tf.callMatch(null, fargs, 0, &failMessage, sc)) 4860 { 4861 OutBuffer buf; 4862 buf.writeByte('('); 4863 argExpTypesToCBuffer(&buf, exp.arguments); 4864 buf.writeByte(')'); 4865 if (tthis) 4866 tthis.modToBuffer(&buf); 4867 4868 //printf("tf = %s, args = %s\n", tf.deco, (*arguments)[0].type.deco); 4869 .error(exp.loc, "%s `%s%s` is not callable using argument types `%s`", 4870 p, exp.e1.toChars(), parametersTypeToChars(tf.parameterList), buf.peekChars()); 4871 if (failMessage) 4872 errorSupplemental(exp.loc, "%s", failMessage); 4873 return setError(); 4874 } 4875 // Purity and safety check should run after testing arguments matching 4876 if (exp.f) 4877 { 4878 exp.checkPurity(sc, exp.f); 4879 exp.checkSafety(sc, exp.f); 4880 exp.checkNogc(sc, exp.f); 4881 if (exp.f.checkNestedReference(sc, exp.loc)) 4882 return setError(); 4883 } 4884 else if (sc.func && sc.intypeof != 1 && !(sc.flags & (SCOPE.ctfe | SCOPE.debug_))) 4885 { 4886 bool err = false; 4887 if (!tf.purity && sc.func.setImpure()) 4888 { 4889 exp.error("`pure` %s `%s` cannot call impure %s `%s`", 4890 sc.func.kind(), sc.func.toPrettyChars(), p, exp.e1.toChars()); 4891 err = true; 4892 } 4893 if (!tf.isnogc && sc.func.setGC()) 4894 { 4895 exp.error("`@nogc` %s `%s` cannot call non-@nogc %s `%s`", 4896 sc.func.kind(), sc.func.toPrettyChars(), p, exp.e1.toChars()); 4897 err = true; 4898 } 4899 if (tf.trust <= TRUST.system && sc.func.setUnsafe()) 4900 { 4901 exp.error("`@safe` %s `%s` cannot call `@system` %s `%s`", 4902 sc.func.kind(), sc.func.toPrettyChars(), p, exp.e1.toChars()); 4903 err = true; 4904 } 4905 if (err) 4906 return setError(); 4907 } 4908 4909 if (t1.ty == Tpointer) 4910 { 4911 Expression e = new PtrExp(exp.loc, exp.e1); 4912 e.type = tf; 4913 exp.e1 = e; 4914 } 4915 t1 = tf; 4916 } 4917 else if (exp.e1.op == TOK.variable) 4918 { 4919 // Do overload resolution 4920 VarExp ve = cast(VarExp)exp.e1; 4921 4922 exp.f = ve.var.isFuncDeclaration(); 4923 assert(exp.f); 4924 tiargs = null; 4925 4926 if (exp.f.overnext) 4927 exp.f = resolveFuncCall(exp.loc, sc, exp.f, tiargs, null, exp.arguments, FuncResolveFlag.overloadOnly); 4928 else 4929 { 4930 exp.f = exp.f.toAliasFunc(); 4931 TypeFunction tf = cast(TypeFunction)exp.f.type; 4932 const(char)* failMessage; 4933 Expression[] fargs = exp.arguments ? (*exp.arguments)[] : null; 4934 if (!tf.callMatch(null, fargs, 0, &failMessage, sc)) 4935 { 4936 OutBuffer buf; 4937 buf.writeByte('('); 4938 argExpTypesToCBuffer(&buf, exp.arguments); 4939 buf.writeByte(')'); 4940 4941 //printf("tf = %s, args = %s\n", tf.deco, (*arguments)[0].type.deco); 4942 .error(exp.loc, "%s `%s%s` is not callable using argument types `%s`", 4943 exp.f.kind(), exp.f.toPrettyChars(), parametersTypeToChars(tf.parameterList), buf.peekChars()); 4944 if (failMessage) 4945 errorSupplemental(exp.loc, "%s", failMessage); 4946 exp.f = null; 4947 } 4948 } 4949 if (!exp.f || exp.f.errors) 4950 return setError(); 4951 4952 if (exp.f.needThis()) 4953 { 4954 // Change the ancestor lambdas to delegate before hasThis(sc) call. 4955 if (exp.f.checkNestedReference(sc, exp.loc)) 4956 return setError(); 4957 4958 if (hasThis(sc)) 4959 { 4960 // Supply an implicit 'this', as in 4961 // this.ident 4962 exp.e1 = new DotVarExp(exp.loc, (new ThisExp(exp.loc)).expressionSemantic(sc), ve.var); 4963 // Note: we cannot use f directly, because further overload resolution 4964 // through the supplied 'this' may cause different result. 4965 goto Lagain; 4966 } 4967 else if (isNeedThisScope(sc, exp.f)) 4968 { 4969 exp.error("need `this` for `%s` of type `%s`", exp.f.toChars(), exp.f.type.toChars()); 4970 return setError(); 4971 } 4972 } 4973 4974 checkFunctionAttributes(exp, sc, exp.f); 4975 checkAccess(exp.loc, sc, null, exp.f); 4976 if (exp.f.checkNestedReference(sc, exp.loc)) 4977 return setError(); 4978 4979 ethis = null; 4980 tthis = null; 4981 4982 if (ve.hasOverloads) 4983 { 4984 exp.e1 = new VarExp(ve.loc, exp.f, false); 4985 exp.e1.type = exp.f.type; 4986 } 4987 t1 = exp.f.type; 4988 } 4989 assert(t1.ty == Tfunction); 4990 4991 Expression argprefix; 4992 if (!exp.arguments) 4993 exp.arguments = new Expressions(); 4994 if (functionParameters(exp.loc, sc, cast(TypeFunction)t1, ethis, tthis, exp.arguments, exp.f, &exp.type, &argprefix)) 4995 return setError(); 4996 4997 if (!exp.type) 4998 { 4999 exp.e1 = e1org; // https://issues.dlang.org/show_bug.cgi?id=10922 5000 // avoid recursive expression printing 5001 exp.error("forward reference to inferred return type of function call `%s`", exp.toChars()); 5002 return setError(); 5003 } 5004 5005 if (exp.f && exp.f.tintro) 5006 { 5007 Type t = exp.type; 5008 int offset = 0; 5009 TypeFunction tf = cast(TypeFunction)exp.f.tintro; 5010 if (tf.next.isBaseOf(t, &offset) && offset) 5011 { 5012 exp.type = tf.next; 5013 result = Expression.combine(argprefix, exp.castTo(sc, t)); 5014 return; 5015 } 5016 } 5017 5018 // Handle the case of a direct lambda call 5019 if (exp.f && exp.f.isFuncLiteralDeclaration() && sc.func && !sc.intypeof) 5020 { 5021 exp.f.tookAddressOf = 0; 5022 } 5023 5024 result = Expression.combine(argprefix, exp); 5025 5026 if (isSuper) 5027 { 5028 auto ad = sc.func ? sc.func.isThis() : null; 5029 auto cd = ad ? ad.isClassDeclaration() : null; 5030 if (cd && cd.classKind == ClassKind.cpp && exp.f && !exp.f.fbody) 5031 { 5032 // if super is defined in C++, it sets the vtable pointer to the base class 5033 // so we have to restore it, but still return 'this' from super() call: 5034 // (auto __vptrTmp = this.__vptr, auto __superTmp = super()), (this.__vptr = __vptrTmp, __superTmp) 5035 Loc loc = exp.loc; 5036 5037 auto vptr = new DotIdExp(loc, new ThisExp(loc), Id.__vptr); 5038 auto vptrTmpDecl = copyToTemp(0, "__vptrTmp", vptr); 5039 auto declareVptrTmp = new DeclarationExp(loc, vptrTmpDecl); 5040 5041 auto superTmpDecl = copyToTemp(0, "__superTmp", result); 5042 auto declareSuperTmp = new DeclarationExp(loc, superTmpDecl); 5043 5044 auto declareTmps = new CommaExp(loc, declareVptrTmp, declareSuperTmp); 5045 5046 auto restoreVptr = new AssignExp(loc, vptr.syntaxCopy(), new VarExp(loc, vptrTmpDecl)); 5047 5048 Expression e = new CommaExp(loc, declareTmps, new CommaExp(loc, restoreVptr, new VarExp(loc, superTmpDecl))); 5049 result = e.expressionSemantic(sc); 5050 } 5051 } 5052 5053 // declare dual-context container 5054 if (exp.f && exp.f.isThis2 && !sc.intypeof && sc.func) 5055 { 5056 // check access to second `this` 5057 if (AggregateDeclaration ad2 = exp.f.isMember2()) 5058 { 5059 Expression te = new ThisExp(exp.loc).expressionSemantic(sc); 5060 if (te.op != TOK.error) 5061 te = getRightThis(exp.loc, sc, ad2, te, exp.f); 5062 if (te.op == TOK.error) 5063 { 5064 exp.error("need `this` of type `%s` to call function `%s`", ad2.toChars(), exp.f.toChars()); 5065 return setError(); 5066 } 5067 } 5068 VarDeclaration vthis2 = makeThis2Argument(exp.loc, sc, exp.f); exp.vthis2 = vthis2; 5069 Expression de = new DeclarationExp(exp.loc, vthis2); 5070 result = Expression.combine(de, result); 5071 result = result.expressionSemantic(sc); 5072 } 5073 } 5074 5075 override void visit(DeclarationExp e) 5076 { 5077 if (e.type) 5078 { 5079 result = e; 5080 return; 5081 } 5082 static if (LOGSEMANTIC) 5083 { 5084 printf("DeclarationExp::semantic() %s\n", e.toChars()); 5085 } 5086 5087 uint olderrors = global.errors; 5088 5089 /* This is here to support extern(linkage) declaration, 5090 * where the extern(linkage) winds up being an AttribDeclaration 5091 * wrapper. 5092 */ 5093 Dsymbol s = e.declaration; 5094 5095 while (1) 5096 { 5097 AttribDeclaration ad = s.isAttribDeclaration(); 5098 if (ad) 5099 { 5100 if (ad.decl && ad.decl.dim == 1) 5101 { 5102 s = (*ad.decl)[0]; 5103 continue; 5104 } 5105 } 5106 break; 5107 } 5108 5109 VarDeclaration v = s.isVarDeclaration(); 5110 if (v) 5111 { 5112 // Do semantic() on initializer first, so: 5113 // int a = a; 5114 // will be illegal. 5115 e.declaration.dsymbolSemantic(sc); 5116 s.parent = sc.parent; 5117 } 5118 5119 //printf("inserting '%s' %p into sc = %p\n", s.toChars(), s, sc); 5120 // Insert into both local scope and function scope. 5121 // Must be unique in both. 5122 if (s.ident) 5123 { 5124 if (!sc.insert(s)) 5125 { 5126 e.error("declaration `%s` is already defined", s.toPrettyChars()); 5127 return setError(); 5128 } 5129 else if (sc.func) 5130 { 5131 // https://issues.dlang.org/show_bug.cgi?id=11720 5132 // include Dataseg variables 5133 if ((s.isFuncDeclaration() || 5134 s.isAggregateDeclaration() || 5135 s.isEnumDeclaration() || 5136 v && v.isDataseg()) && !sc.func.localsymtab.insert(s)) 5137 { 5138 // https://issues.dlang.org/show_bug.cgi?id=18266 5139 // set parent so that type semantic does not assert 5140 s.parent = sc.parent; 5141 Dsymbol originalSymbol = sc.func.localsymtab.lookup(s.ident); 5142 assert(originalSymbol); 5143 e.error("declaration `%s` is already defined in another scope in `%s` at line `%d`", s.toPrettyChars(), sc.func.toChars(), originalSymbol.loc.linnum); 5144 return setError(); 5145 } 5146 else 5147 { 5148 // Disallow shadowing 5149 for (Scope* scx = sc.enclosing; scx && (scx.func == sc.func || (scx.func && sc.func.fes)); scx = scx.enclosing) 5150 { 5151 Dsymbol s2; 5152 if (scx.scopesym && scx.scopesym.symtab && (s2 = scx.scopesym.symtab.lookup(s.ident)) !is null && s != s2) 5153 { 5154 // allow STC.local symbols to be shadowed 5155 // TODO: not really an optimal design 5156 auto decl = s2.isDeclaration(); 5157 if (!decl || !(decl.storage_class & STC.local)) 5158 { 5159 if (sc.func.fes) 5160 { 5161 e.deprecation("%s `%s` is shadowing %s `%s`. Rename the `foreach` variable.", s.kind(), s.ident.toChars(), s2.kind(), s2.toPrettyChars()); 5162 } 5163 else 5164 { 5165 e.error("%s `%s` is shadowing %s `%s`", s.kind(), s.ident.toChars(), s2.kind(), s2.toPrettyChars()); 5166 return setError(); 5167 } 5168 } 5169 } 5170 } 5171 } 5172 } 5173 } 5174 if (!s.isVarDeclaration()) 5175 { 5176 Scope* sc2 = sc; 5177 if (sc2.stc & (STC.pure_ | STC.nothrow_ | STC.nogc)) 5178 sc2 = sc.push(); 5179 sc2.stc &= ~(STC.pure_ | STC.nothrow_ | STC.nogc); 5180 e.declaration.dsymbolSemantic(sc2); 5181 if (sc2 != sc) 5182 sc2.pop(); 5183 s.parent = sc.parent; 5184 } 5185 if (global.errors == olderrors) 5186 { 5187 e.declaration.semantic2(sc); 5188 if (global.errors == olderrors) 5189 { 5190 e.declaration.semantic3(sc); 5191 } 5192 } 5193 // todo: error in declaration should be propagated. 5194 5195 e.type = Type.tvoid; 5196 result = e; 5197 } 5198 5199 override void visit(TypeidExp exp) 5200 { 5201 static if (LOGSEMANTIC) 5202 { 5203 printf("TypeidExp::semantic() %s\n", exp.toChars()); 5204 } 5205 Type ta = isType(exp.obj); 5206 Expression ea = isExpression(exp.obj); 5207 Dsymbol sa = isDsymbol(exp.obj); 5208 //printf("ta %p ea %p sa %p\n", ta, ea, sa); 5209 5210 if (ta) 5211 { 5212 dmd.typesem.resolve(ta, exp.loc, sc, &ea, &ta, &sa, true); 5213 } 5214 5215 if (ea) 5216 { 5217 if (auto sym = getDsymbol(ea)) 5218 ea = symbolToExp(sym, exp.loc, sc, false); 5219 else 5220 ea = ea.expressionSemantic(sc); 5221 ea = resolveProperties(sc, ea); 5222 ta = ea.type; 5223 if (ea.op == TOK.type) 5224 ea = null; 5225 } 5226 5227 if (!ta) 5228 { 5229 //printf("ta %p ea %p sa %p\n", ta, ea, sa); 5230 exp.error("no type for `typeid(%s)`", ea ? ea.toChars() : (sa ? sa.toChars() : "")); 5231 return setError(); 5232 } 5233 5234 if (global.params.vcomplex) 5235 ta.checkComplexTransition(exp.loc, sc); 5236 5237 Expression e; 5238 auto tb = ta.toBasetype(); 5239 if (ea && tb.ty == Tclass) 5240 { 5241 if (tb.toDsymbol(sc).isClassDeclaration().classKind == ClassKind.cpp) 5242 { 5243 error(exp.loc, "Runtime type information is not supported for `extern(C++)` classes"); 5244 e = new ErrorExp(); 5245 } 5246 else if (!Type.typeinfoclass) 5247 { 5248 error(exp.loc, "`object.TypeInfo_Class` could not be found, but is implicitly used"); 5249 e = new ErrorExp(); 5250 } 5251 else 5252 { 5253 /* Get the dynamic type, which is .classinfo 5254 */ 5255 ea = ea.expressionSemantic(sc); 5256 e = new TypeidExp(ea.loc, ea); 5257 e.type = Type.typeinfoclass.type; 5258 } 5259 } 5260 else if (ta.ty == Terror) 5261 { 5262 e = new ErrorExp(); 5263 } 5264 else 5265 { 5266 // Handle this in the glue layer 5267 e = new TypeidExp(exp.loc, ta); 5268 e.type = getTypeInfoType(exp.loc, ta, sc); 5269 5270 semanticTypeInfo(sc, ta); 5271 5272 if (ea) 5273 { 5274 e = new CommaExp(exp.loc, ea, e); // execute ea 5275 e = e.expressionSemantic(sc); 5276 } 5277 } 5278 result = e; 5279 } 5280 5281 override void visit(TraitsExp e) 5282 { 5283 result = semanticTraits(e, sc); 5284 } 5285 5286 override void visit(HaltExp e) 5287 { 5288 static if (LOGSEMANTIC) 5289 { 5290 printf("HaltExp::semantic()\n"); 5291 } 5292 e.type = Type.tvoid; 5293 result = e; 5294 } 5295 5296 override void visit(IsExp e) 5297 { 5298 /* is(targ id tok tspec) 5299 * is(targ id : tok2) 5300 * is(targ id == tok2) 5301 */ 5302 static if (LOGSEMANTIC) 5303 { 5304 printf("IsExp::semantic(%s)\n", e.toChars()); 5305 } 5306 if (e.id && !(sc.flags & SCOPE.condition)) 5307 { 5308 e.error("can only declare type aliases within `static if` conditionals or `static assert`s"); 5309 return setError(); 5310 } 5311 5312 Type tded = null; 5313 if (e.tok2 == TOK.package_ || e.tok2 == TOK.module_) // These is() expressions are special because they can work on modules, not just types. 5314 { 5315 const oldErrors = global.startGagging(); 5316 Dsymbol sym = e.targ.toDsymbol(sc); 5317 global.endGagging(oldErrors); 5318 5319 if (sym is null) 5320 goto Lno; 5321 Package p = resolveIsPackage(sym); 5322 if (p is null) 5323 goto Lno; 5324 if (e.tok2 == TOK.package_ && p.isModule()) // Note that isModule() will return null for package modules because they're not actually instances of Module. 5325 goto Lno; 5326 else if(e.tok2 == TOK.module_ && !(p.isModule() || p.isPackageMod())) 5327 goto Lno; 5328 tded = e.targ; 5329 goto Lyes; 5330 } 5331 5332 { 5333 Scope* sc2 = sc.copy(); // keep sc.flags 5334 sc2.tinst = null; 5335 sc2.minst = null; 5336 sc2.flags |= SCOPE.fullinst; 5337 Type t = e.targ.trySemantic(e.loc, sc2); 5338 sc2.pop(); 5339 if (!t) // errors, so condition is false 5340 goto Lno; 5341 e.targ = t; 5342 } 5343 5344 if (e.tok2 != TOK.reserved) 5345 { 5346 switch (e.tok2) 5347 { 5348 case TOK.struct_: 5349 if (e.targ.ty != Tstruct) 5350 goto Lno; 5351 if ((cast(TypeStruct)e.targ).sym.isUnionDeclaration()) 5352 goto Lno; 5353 tded = e.targ; 5354 break; 5355 5356 case TOK.union_: 5357 if (e.targ.ty != Tstruct) 5358 goto Lno; 5359 if (!(cast(TypeStruct)e.targ).sym.isUnionDeclaration()) 5360 goto Lno; 5361 tded = e.targ; 5362 break; 5363 5364 case TOK.class_: 5365 if (e.targ.ty != Tclass) 5366 goto Lno; 5367 if ((cast(TypeClass)e.targ).sym.isInterfaceDeclaration()) 5368 goto Lno; 5369 tded = e.targ; 5370 break; 5371 5372 case TOK.interface_: 5373 if (e.targ.ty != Tclass) 5374 goto Lno; 5375 if (!(cast(TypeClass)e.targ).sym.isInterfaceDeclaration()) 5376 goto Lno; 5377 tded = e.targ; 5378 break; 5379 5380 case TOK.const_: 5381 if (!e.targ.isConst()) 5382 goto Lno; 5383 tded = e.targ; 5384 break; 5385 5386 case TOK.immutable_: 5387 if (!e.targ.isImmutable()) 5388 goto Lno; 5389 tded = e.targ; 5390 break; 5391 5392 case TOK.shared_: 5393 if (!e.targ.isShared()) 5394 goto Lno; 5395 tded = e.targ; 5396 break; 5397 5398 case TOK.inout_: 5399 if (!e.targ.isWild()) 5400 goto Lno; 5401 tded = e.targ; 5402 break; 5403 5404 case TOK.super_: 5405 // If class or interface, get the base class and interfaces 5406 if (e.targ.ty != Tclass) 5407 goto Lno; 5408 else 5409 { 5410 ClassDeclaration cd = (cast(TypeClass)e.targ).sym; 5411 auto args = new Parameters(); 5412 args.reserve(cd.baseclasses.dim); 5413 if (cd.semanticRun < PASS.semanticdone) 5414 cd.dsymbolSemantic(null); 5415 for (size_t i = 0; i < cd.baseclasses.dim; i++) 5416 { 5417 BaseClass* b = (*cd.baseclasses)[i]; 5418 args.push(new Parameter(STC.in_, b.type, null, null, null)); 5419 } 5420 tded = new TypeTuple(args); 5421 } 5422 break; 5423 5424 case TOK.enum_: 5425 if (e.targ.ty != Tenum) 5426 goto Lno; 5427 if (e.id) 5428 tded = (cast(TypeEnum)e.targ).sym.getMemtype(e.loc); 5429 else 5430 tded = e.targ; 5431 5432 if (tded.ty == Terror) 5433 return setError(); 5434 break; 5435 5436 case TOK.delegate_: 5437 if (e.targ.ty != Tdelegate) 5438 goto Lno; 5439 tded = (cast(TypeDelegate)e.targ).next; // the underlying function type 5440 break; 5441 5442 case TOK.function_: 5443 case TOK.parameters: 5444 { 5445 if (e.targ.ty != Tfunction) 5446 goto Lno; 5447 tded = e.targ; 5448 5449 /* Generate tuple from function parameter types. 5450 */ 5451 assert(tded.ty == Tfunction); 5452 auto tdedf = tded.isTypeFunction(); 5453 size_t dim = tdedf.parameterList.length; 5454 auto args = new Parameters(); 5455 args.reserve(dim); 5456 for (size_t i = 0; i < dim; i++) 5457 { 5458 Parameter arg = tdedf.parameterList[i]; 5459 assert(arg && arg.type); 5460 /* If one of the default arguments was an error, 5461 don't return an invalid tuple 5462 */ 5463 if (e.tok2 == TOK.parameters && arg.defaultArg && arg.defaultArg.op == TOK.error) 5464 return setError(); 5465 args.push(new Parameter(arg.storageClass, arg.type, (e.tok2 == TOK.parameters) ? arg.ident : null, (e.tok2 == TOK.parameters) ? arg.defaultArg : null, arg.userAttribDecl)); 5466 } 5467 tded = new TypeTuple(args); 5468 break; 5469 } 5470 case TOK.return_: 5471 /* Get the 'return type' for the function, 5472 * delegate, or pointer to function. 5473 */ 5474 if (e.targ.ty == Tfunction) 5475 tded = (cast(TypeFunction)e.targ).next; 5476 else if (e.targ.ty == Tdelegate) 5477 { 5478 tded = (cast(TypeDelegate)e.targ).next; 5479 tded = (cast(TypeFunction)tded).next; 5480 } 5481 else if (e.targ.ty == Tpointer && (cast(TypePointer)e.targ).next.ty == Tfunction) 5482 { 5483 tded = (cast(TypePointer)e.targ).next; 5484 tded = (cast(TypeFunction)tded).next; 5485 } 5486 else 5487 goto Lno; 5488 break; 5489 5490 case TOK.argumentTypes: 5491 /* Generate a type tuple of the equivalent types used to determine if a 5492 * function argument of this type can be passed in registers. 5493 * The results of this are highly platform dependent, and intended 5494 * primarly for use in implementing va_arg(). 5495 */ 5496 tded = target.toArgTypes(e.targ); 5497 if (!tded) 5498 goto Lno; 5499 // not valid for a parameter 5500 break; 5501 5502 case TOK.vector: 5503 if (e.targ.ty != Tvector) 5504 goto Lno; 5505 tded = (cast(TypeVector)e.targ).basetype; 5506 break; 5507 5508 default: 5509 assert(0); 5510 } 5511 5512 // https://issues.dlang.org/show_bug.cgi?id=18753 5513 if (tded) 5514 goto Lyes; 5515 goto Lno; 5516 } 5517 else if (e.tspec && !e.id && !(e.parameters && e.parameters.dim)) 5518 { 5519 /* Evaluate to true if targ matches tspec 5520 * is(targ == tspec) 5521 * is(targ : tspec) 5522 */ 5523 e.tspec = e.tspec.typeSemantic(e.loc, sc); 5524 //printf("targ = %s, %s\n", targ.toChars(), targ.deco); 5525 //printf("tspec = %s, %s\n", tspec.toChars(), tspec.deco); 5526 5527 if (e.tok == TOK.colon) 5528 { 5529 if (e.targ.implicitConvTo(e.tspec)) 5530 goto Lyes; 5531 else 5532 goto Lno; 5533 } 5534 else /* == */ 5535 { 5536 if (e.targ.equals(e.tspec)) 5537 goto Lyes; 5538 else 5539 goto Lno; 5540 } 5541 } 5542 else if (e.tspec) 5543 { 5544 /* Evaluate to true if targ matches tspec. 5545 * If true, declare id as an alias for the specialized type. 5546 * is(targ == tspec, tpl) 5547 * is(targ : tspec, tpl) 5548 * is(targ id == tspec) 5549 * is(targ id : tspec) 5550 * is(targ id == tspec, tpl) 5551 * is(targ id : tspec, tpl) 5552 */ 5553 Identifier tid = e.id ? e.id : Identifier.generateId("__isexp_id"); 5554 e.parameters.insert(0, new TemplateTypeParameter(e.loc, tid, null, null)); 5555 5556 Objects dedtypes = Objects(e.parameters.dim); 5557 dedtypes.zero(); 5558 5559 MATCH m = deduceType(e.targ, sc, e.tspec, e.parameters, &dedtypes, null, 0, e.tok == TOK.equal); 5560 //printf("targ: %s\n", targ.toChars()); 5561 //printf("tspec: %s\n", tspec.toChars()); 5562 if (m <= MATCH.nomatch || (m != MATCH.exact && e.tok == TOK.equal)) 5563 { 5564 goto Lno; 5565 } 5566 else 5567 { 5568 tded = cast(Type)dedtypes[0]; 5569 if (!tded) 5570 tded = e.targ; 5571 Objects tiargs = Objects(1); 5572 tiargs[0] = e.targ; 5573 5574 /* Declare trailing parameters 5575 */ 5576 for (size_t i = 1; i < e.parameters.dim; i++) 5577 { 5578 TemplateParameter tp = (*e.parameters)[i]; 5579 Declaration s = null; 5580 5581 m = tp.matchArg(e.loc, sc, &tiargs, i, e.parameters, &dedtypes, &s); 5582 if (m <= MATCH.nomatch) 5583 goto Lno; 5584 s.dsymbolSemantic(sc); 5585 if (!sc.insert(s)) 5586 e.error("declaration `%s` is already defined", s.toChars()); 5587 5588 unSpeculative(sc, s); 5589 } 5590 goto Lyes; 5591 } 5592 } 5593 else if (e.id) 5594 { 5595 /* Declare id as an alias for type targ. Evaluate to true 5596 * is(targ id) 5597 */ 5598 tded = e.targ; 5599 goto Lyes; 5600 } 5601 5602 Lyes: 5603 if (e.id) 5604 { 5605 Dsymbol s; 5606 Tuple tup = isTuple(tded); 5607 if (tup) 5608 s = new TupleDeclaration(e.loc, e.id, &tup.objects); 5609 else 5610 s = new AliasDeclaration(e.loc, e.id, tded); 5611 s.dsymbolSemantic(sc); 5612 5613 /* The reason for the !tup is unclear. It fails Phobos unittests if it is not there. 5614 * More investigation is needed. 5615 */ 5616 if (!tup && !sc.insert(s)) 5617 e.error("declaration `%s` is already defined", s.toChars()); 5618 5619 unSpeculative(sc, s); 5620 } 5621 //printf("Lyes\n"); 5622 result = IntegerExp.createBool(true); 5623 return; 5624 5625 Lno: 5626 //printf("Lno\n"); 5627 result = IntegerExp.createBool(false); 5628 } 5629 5630 override void visit(BinAssignExp exp) 5631 { 5632 if (exp.type) 5633 { 5634 result = exp; 5635 return; 5636 } 5637 5638 Expression e = exp.op_overload(sc); 5639 if (e) 5640 { 5641 result = e; 5642 return; 5643 } 5644 5645 if (checkIfIsStructLiteralDotExpr(exp.e1)) 5646 return setError(); 5647 if (exp.e1.op == TOK.arrayLength) 5648 { 5649 // arr.length op= e2; 5650 e = rewriteOpAssign(exp); 5651 e = e.expressionSemantic(sc); 5652 result = e; 5653 return; 5654 } 5655 if (exp.e1.op == TOK.slice || exp.e1.type.ty == Tarray || exp.e1.type.ty == Tsarray) 5656 { 5657 if (checkNonAssignmentArrayOp(exp.e1)) 5658 return setError(); 5659 5660 if (exp.e1.op == TOK.slice) 5661 (cast(SliceExp)exp.e1).arrayop = true; 5662 5663 // T[] op= ... 5664 if (exp.e2.implicitConvTo(exp.e1.type.nextOf())) 5665 { 5666 // T[] op= T 5667 exp.e2 = exp.e2.castTo(sc, exp.e1.type.nextOf()); 5668 } 5669 else if (Expression ex = typeCombine(exp, sc)) 5670 { 5671 result = ex; 5672 return; 5673 } 5674 exp.type = exp.e1.type; 5675 result = arrayOp(exp, sc); 5676 return; 5677 } 5678 5679 exp.e1 = exp.e1.expressionSemantic(sc); 5680 exp.e1 = exp.e1.optimize(WANTvalue); 5681 exp.e1 = exp.e1.modifiableLvalue(sc, exp.e1); 5682 exp.type = exp.e1.type; 5683 5684 if (auto ad = isAggregate(exp.e1.type)) 5685 { 5686 if (const s = search_function(ad, Id.opOpAssign)) 5687 { 5688 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()); 5689 return setError(); 5690 } 5691 } 5692 if (exp.e1.checkScalar() || 5693 exp.e1.checkReadModifyWrite(exp.op, exp.e2) || 5694 exp.e1.checkSharedAccess(sc)) 5695 return setError(); 5696 5697 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); 5698 int bitwise = (exp.op == TOK.andAssign || exp.op == TOK.orAssign || exp.op == TOK.xorAssign); 5699 int shift = (exp.op == TOK.leftShiftAssign || exp.op == TOK.rightShiftAssign || exp.op == TOK.unsignedRightShiftAssign); 5700 5701 if (bitwise && exp.type.toBasetype().ty == Tbool) 5702 exp.e2 = exp.e2.implicitCastTo(sc, exp.type); 5703 else if (exp.checkNoBool()) 5704 return setError(); 5705 5706 if ((exp.op == TOK.addAssign || exp.op == TOK.minAssign) && exp.e1.type.toBasetype().ty == Tpointer && exp.e2.type.toBasetype().isintegral()) 5707 { 5708 result = scaleFactor(exp, sc); 5709 return; 5710 } 5711 5712 if (Expression ex = typeCombine(exp, sc)) 5713 { 5714 result = ex; 5715 return; 5716 } 5717 5718 if (arith && (exp.checkArithmeticBin() || exp.checkSharedAccessBin(sc))) 5719 return setError(); 5720 if ((bitwise || shift) && (exp.checkIntegralBin() || exp.checkSharedAccessBin(sc))) 5721 return setError(); 5722 5723 if (shift) 5724 { 5725 if (exp.e2.type.toBasetype().ty != Tvector) 5726 exp.e2 = exp.e2.castTo(sc, Type.tshiftcnt); 5727 } 5728 5729 if (!target.isVectorOpSupported(exp.type.toBasetype(), exp.op, exp.e2.type.toBasetype())) 5730 { 5731 result = exp.incompatibleTypes(); 5732 return; 5733 } 5734 5735 if (exp.e1.op == TOK.error || exp.e2.op == TOK.error) 5736 return setError(); 5737 5738 e = exp.checkOpAssignTypes(sc); 5739 if (e.op == TOK.error) 5740 { 5741 result = e; 5742 return; 5743 } 5744 5745 assert(e.op == TOK.assign || e == exp); 5746 result = (cast(BinExp)e).reorderSettingAAElem(sc); 5747 } 5748 5749 private Expression compileIt(CompileExp exp) 5750 { 5751 OutBuffer buf; 5752 if (expressionsToString(buf, sc, exp.exps)) 5753 return null; 5754 5755 uint errors = global.errors; 5756 const len = buf.length; 5757 const str = buf.extractChars()[0 .. len]; 5758 scope p = new Parser!ASTCodegen(exp.loc, sc._module, str, false); 5759 p.nextToken(); 5760 //printf("p.loc.linnum = %d\n", p.loc.linnum); 5761 5762 Expression e = p.parseExpression(); 5763 p.reportDiagnostics(); 5764 if (global.errors != errors) 5765 return null; 5766 5767 if (p.token.value != TOK.endOfFile) 5768 { 5769 exp.error("incomplete mixin expression `%s`", str.ptr); 5770 return null; 5771 } 5772 return e; 5773 } 5774 5775 override void visit(CompileExp exp) 5776 { 5777 /* https://dlang.org/spec/expression.html#mixin_expressions 5778 */ 5779 5780 static if (LOGSEMANTIC) 5781 { 5782 printf("CompileExp::semantic('%s')\n", exp.toChars()); 5783 } 5784 5785 auto e = compileIt(exp); 5786 if (!e) 5787 return setError(); 5788 result = e.expressionSemantic(sc); 5789 } 5790 5791 override void visit(ImportExp e) 5792 { 5793 static if (LOGSEMANTIC) 5794 { 5795 printf("ImportExp::semantic('%s')\n", e.toChars()); 5796 } 5797 5798 auto se = semanticString(sc, e.e1, "file name argument"); 5799 if (!se) 5800 return setError(); 5801 se = se.toUTF8(sc); 5802 5803 auto namez = se.toStringz().ptr; 5804 if (!global.filePath) 5805 { 5806 e.error("need `-J` switch to import text file `%s`", namez); 5807 return setError(); 5808 } 5809 5810 /* Be wary of CWE-22: Improper Limitation of a Pathname to a Restricted Directory 5811 * ('Path Traversal') attacks. 5812 * http://cwe.mitre.org/data/definitions/22.html 5813 */ 5814 5815 auto name = FileName.safeSearchPath(global.filePath, namez); 5816 if (!name) 5817 { 5818 e.error("file `%s` cannot be found or not in a path specified with `-J`", se.toChars()); 5819 return setError(); 5820 } 5821 5822 sc._module.contentImportedFiles.push(name); 5823 if (global.params.verbose) 5824 { 5825 const slice = se.peekString(); 5826 message("file %.*s\t(%s)", cast(int)slice.length, slice.ptr, name); 5827 } 5828 if (global.params.moduleDeps !is null) 5829 { 5830 OutBuffer* ob = global.params.moduleDeps; 5831 Module imod = sc.instantiatingModule(); 5832 5833 if (!global.params.moduleDepsFile) 5834 ob.writestring("depsFile "); 5835 ob.writestring(imod.toPrettyChars()); 5836 ob.writestring(" ("); 5837 escapePath(ob, imod.srcfile.toChars()); 5838 ob.writestring(") : "); 5839 if (global.params.moduleDepsFile) 5840 ob.writestring("string : "); 5841 ob.write(se.peekString()); 5842 ob.writestring(" ("); 5843 escapePath(ob, name); 5844 ob.writestring(")"); 5845 ob.writenl(); 5846 } 5847 5848 { 5849 auto readResult = File.read(name); 5850 if (!readResult.success) 5851 { 5852 e.error("cannot read file `%s`", name); 5853 return setError(); 5854 } 5855 else 5856 { 5857 // take ownership of buffer (probably leaking) 5858 auto data = readResult.extractSlice(); 5859 se = new StringExp(e.loc, data); 5860 } 5861 } 5862 result = se.expressionSemantic(sc); 5863 } 5864 5865 override void visit(AssertExp exp) 5866 { 5867 // https://dlang.org/spec/expression.html#assert_expressions 5868 static if (LOGSEMANTIC) 5869 { 5870 printf("AssertExp::semantic('%s')\n", exp.toChars()); 5871 } 5872 5873 const generateMsg = !exp.msg && global.params.checkAction == CHECKACTION.context; 5874 Expression temporariesPrefix; 5875 5876 if (generateMsg) 5877 // no message - use assert expression as msg 5878 { 5879 /* 5880 { 5881 auto a = e1, b = e2; 5882 assert(a == b, _d_assert_fail!"=="(a, b)); 5883 }() 5884 */ 5885 5886 /* 5887 Stores the result of an operand expression into a temporary 5888 if necessary, e.g. if it is an impure fuction call containing side 5889 effects as in https://issues.dlang.org/show_bug.cgi?id=20114 5890 5891 Params: 5892 op = an expression which may require a temporary (added to 5893 `temporariesPrefix`: `auto tmp = op`) and will be replaced 5894 by `tmp` if necessary 5895 5896 Returns: (possibly replaced) `op` 5897 */ 5898 Expression maybePromoteToTmp(ref Expression op) 5899 { 5900 op = op.expressionSemantic(sc); 5901 op = resolveProperties(sc, op); 5902 if (op.hasSideEffect) 5903 { 5904 const stc = op.isLvalue() ? STC.ref_ : 0; 5905 auto tmp = copyToTemp(stc, "__assertOp", op); 5906 tmp.dsymbolSemantic(sc); 5907 5908 auto decl = new DeclarationExp(op.loc, tmp); 5909 temporariesPrefix = Expression.combine(temporariesPrefix, decl); 5910 5911 op = new VarExp(op.loc, tmp); 5912 op = op.expressionSemantic(sc); 5913 } 5914 return op; 5915 } 5916 5917 // if the assert condition is a mixin expression, try to compile it 5918 if (auto ce = exp.e1.isCompileExp()) 5919 { 5920 if (auto e1 = compileIt(ce)) 5921 exp.e1 = e1; 5922 } 5923 5924 const tok = exp.e1.op; 5925 bool isEqualsCallExpression; 5926 if (tok == TOK.call) 5927 { 5928 const callExp = cast(CallExp) exp.e1; 5929 5930 // https://issues.dlang.org/show_bug.cgi?id=20331 5931 // callExp.f may be null if the assert contains a call to 5932 // a function pointer or literal 5933 if (const callExpFunc = callExp.f) 5934 { 5935 const callExpIdent = callExpFunc.ident; 5936 isEqualsCallExpression = callExpIdent == Id.__equals || 5937 callExpIdent == Id.eq; 5938 } 5939 } 5940 if (tok == TOK.equal || tok == TOK.notEqual || 5941 tok == TOK.lessThan || tok == TOK.greaterThan || 5942 tok == TOK.lessOrEqual || tok == TOK.greaterOrEqual || 5943 tok == TOK.identity || tok == TOK.notIdentity || 5944 tok == TOK.in_ || 5945 isEqualsCallExpression) 5946 { 5947 if (!verifyHookExist(exp.loc, *sc, Id._d_assert_fail, "generating assert messages")) 5948 return setError(); 5949 5950 auto es = new Expressions(2); 5951 auto tiargs = new Objects(3); 5952 Loc loc = exp.e1.loc; 5953 5954 if (isEqualsCallExpression) 5955 { 5956 auto callExp = cast(CallExp) exp.e1; 5957 auto args = callExp.arguments; 5958 5959 // structs with opEquals get rewritten to a DotVarExp: 5960 // a.opEquals(b) 5961 // https://issues.dlang.org/show_bug.cgi?id=20100 5962 if (args.length == 1) 5963 { 5964 auto dv = callExp.e1.isDotVarExp(); 5965 assert(dv); 5966 5967 // runtime args 5968 (*es)[0] = maybePromoteToTmp(dv.e1); 5969 (*es)[1] = maybePromoteToTmp((*args)[0]); 5970 } 5971 else 5972 { 5973 // runtime args 5974 (*es)[0] = maybePromoteToTmp((*args)[0]); 5975 (*es)[1] = maybePromoteToTmp((*args)[1]); 5976 } 5977 } 5978 else 5979 { 5980 auto binExp = cast(EqualExp) exp.e1; 5981 5982 // runtime args 5983 (*es)[0] = maybePromoteToTmp(binExp.e1); 5984 (*es)[1] = maybePromoteToTmp(binExp.e2); 5985 } 5986 5987 // template args 5988 Expression comp = new StringExp(loc, isEqualsCallExpression ? "==" : Token.toString(exp.e1.op)); 5989 comp = comp.expressionSemantic(sc); 5990 (*tiargs)[0] = comp; 5991 (*tiargs)[1] = (*es)[0].type; 5992 (*tiargs)[2] = (*es)[1].type; 5993 5994 Expression __assertFail = new IdentifierExp(exp.loc, Id.empty); 5995 auto assertFail = new DotIdExp(loc, __assertFail, Id.object); 5996 5997 auto dt = new DotTemplateInstanceExp(loc, assertFail, Id._d_assert_fail, tiargs); 5998 auto ec = CallExp.create(Loc.initial, dt, es); 5999 exp.msg = ec; 6000 } 6001 else 6002 { 6003 OutBuffer buf; 6004 buf.printf("%s failed", exp.toChars()); 6005 exp.msg = new StringExp(Loc.initial, buf.extractSlice()); 6006 } 6007 } 6008 6009 if (Expression ex = unaSemantic(exp, sc)) 6010 { 6011 result = ex; 6012 return; 6013 } 6014 6015 exp.e1 = resolveProperties(sc, exp.e1); 6016 // BUG: see if we can do compile time elimination of the Assert 6017 exp.e1 = exp.e1.optimize(WANTvalue); 6018 exp.e1 = exp.e1.toBoolean(sc); 6019 6020 if (exp.msg) 6021 { 6022 exp.msg = expressionSemantic(exp.msg, sc); 6023 exp.msg = resolveProperties(sc, exp.msg); 6024 exp.msg = exp.msg.implicitCastTo(sc, Type.tchar.constOf().arrayOf()); 6025 exp.msg = exp.msg.optimize(WANTvalue); 6026 checkParamArgumentEscape(sc, null, null, exp.msg, true, false); 6027 } 6028 6029 if (exp.e1.op == TOK.error) 6030 { 6031 result = exp.e1; 6032 return; 6033 } 6034 if (exp.msg && exp.msg.op == TOK.error) 6035 { 6036 result = exp.msg; 6037 return; 6038 } 6039 6040 auto f1 = checkNonAssignmentArrayOp(exp.e1); 6041 auto f2 = exp.msg && checkNonAssignmentArrayOp(exp.msg); 6042 if (f1 || f2) 6043 return setError(); 6044 6045 if (exp.e1.isBool(false)) 6046 { 6047 /* This is an `assert(0)` which means halt program execution 6048 */ 6049 FuncDeclaration fd = sc.parent.isFuncDeclaration(); 6050 if (fd) 6051 fd.hasReturnExp |= 4; 6052 sc.ctorflow.orCSX(CSX.halt); 6053 6054 if (global.params.useAssert == CHECKENABLE.off) 6055 { 6056 Expression e = new HaltExp(exp.loc); 6057 e = e.expressionSemantic(sc); 6058 result = e; 6059 return; 6060 } 6061 } 6062 6063 exp.type = Type.tvoid; 6064 6065 result = !temporariesPrefix 6066 ? exp 6067 : Expression.combine(temporariesPrefix, exp).expressionSemantic(sc); 6068 } 6069 6070 override void visit(DotIdExp exp) 6071 { 6072 static if (LOGSEMANTIC) 6073 { 6074 printf("DotIdExp::semantic(this = %p, '%s')\n", exp, exp.toChars()); 6075 //printf("e1.op = %d, '%s'\n", e1.op, Token::toChars(e1.op)); 6076 } 6077 Expression e = exp.semanticY(sc, 1); 6078 if (e && isDotOpDispatch(e)) 6079 { 6080 uint errors = global.startGagging(); 6081 e = resolvePropertiesX(sc, e); 6082 if (global.endGagging(errors)) 6083 e = null; /* fall down to UFCS */ 6084 else 6085 { 6086 result = e; 6087 return; 6088 } 6089 } 6090 if (!e) // if failed to find the property 6091 { 6092 /* If ident is not a valid property, rewrite: 6093 * e1.ident 6094 * as: 6095 * .ident(e1) 6096 */ 6097 e = resolveUFCSProperties(sc, exp); 6098 } 6099 result = e; 6100 } 6101 6102 override void visit(DotTemplateExp e) 6103 { 6104 if (Expression ex = unaSemantic(e, sc)) 6105 { 6106 result = ex; 6107 return; 6108 } 6109 result = e; 6110 } 6111 6112 override void visit(DotVarExp exp) 6113 { 6114 static if (LOGSEMANTIC) 6115 { 6116 printf("DotVarExp::semantic('%s')\n", exp.toChars()); 6117 } 6118 if (exp.type) 6119 { 6120 result = exp; 6121 return; 6122 } 6123 6124 exp.var = exp.var.toAlias().isDeclaration(); 6125 6126 exp.e1 = exp.e1.expressionSemantic(sc); 6127 6128 if (auto tup = exp.var.isTupleDeclaration()) 6129 { 6130 /* Replace: 6131 * e1.tuple(a, b, c) 6132 * with: 6133 * tuple(e1.a, e1.b, e1.c) 6134 */ 6135 Expression e0; 6136 Expression ev = sc.func ? extractSideEffect(sc, "__tup", e0, exp.e1) : exp.e1; 6137 6138 auto exps = new Expressions(); 6139 exps.reserve(tup.objects.dim); 6140 for (size_t i = 0; i < tup.objects.dim; i++) 6141 { 6142 RootObject o = (*tup.objects)[i]; 6143 Expression e; 6144 Declaration var; 6145 if (o.dyncast() == DYNCAST.expression) 6146 { 6147 e = cast(Expression)o; 6148 if (auto se = e.isDsymbolExp()) 6149 var = se.s.isDeclaration(); 6150 else if (auto ve = e.isVarExp()) 6151 if (!ve.var.isFuncDeclaration()) 6152 // Exempt functions for backwards compatibility reasons. 6153 // See: https://issues.dlang.org/show_bug.cgi?id=20470#c1 6154 var = ve.var; 6155 } 6156 else if (o.dyncast() == DYNCAST.dsymbol) 6157 { 6158 Dsymbol s = cast(Dsymbol) o; 6159 Declaration d = s.isDeclaration(); 6160 if (!d || d.isFuncDeclaration()) 6161 // Exempt functions for backwards compatibility reasons. 6162 // See: https://issues.dlang.org/show_bug.cgi?id=20470#c1 6163 e = new DsymbolExp(exp.loc, s); 6164 else 6165 var = d; 6166 } 6167 else if (o.dyncast() == DYNCAST.type) 6168 { 6169 e = new TypeExp(exp.loc, cast(Type)o); 6170 } 6171 else 6172 { 6173 exp.error("`%s` is not an expression", o.toChars()); 6174 return setError(); 6175 } 6176 if (var) 6177 e = new DotVarExp(exp.loc, ev, var); 6178 exps.push(e); 6179 } 6180 6181 Expression e = new TupleExp(exp.loc, e0, exps); 6182 e = e.expressionSemantic(sc); 6183 result = e; 6184 return; 6185 } 6186 6187 exp.e1 = exp.e1.addDtorHook(sc); 6188 6189 Type t1 = exp.e1.type; 6190 6191 if (FuncDeclaration fd = exp.var.isFuncDeclaration()) 6192 { 6193 // for functions, do checks after overload resolution 6194 if (!fd.functionSemantic()) 6195 return setError(); 6196 6197 /* https://issues.dlang.org/show_bug.cgi?id=13843 6198 * If fd obviously has no overloads, we should 6199 * normalize AST, and it will give a chance to wrap fd with FuncExp. 6200 */ 6201 if ((fd.isNested() && !fd.isThis()) || fd.isFuncLiteralDeclaration()) 6202 { 6203 // (e1, fd) 6204 auto e = symbolToExp(fd, exp.loc, sc, false); 6205 result = Expression.combine(exp.e1, e); 6206 return; 6207 } 6208 6209 exp.type = fd.type; 6210 assert(exp.type); 6211 } 6212 else if (OverDeclaration od = exp.var.isOverDeclaration()) 6213 { 6214 exp.type = Type.tvoid; // ambiguous type? 6215 } 6216 else 6217 { 6218 exp.type = exp.var.type; 6219 if (!exp.type && global.errors) // var is goofed up, just return error. 6220 return setError(); 6221 assert(exp.type); 6222 6223 if (t1.ty == Tpointer) 6224 t1 = t1.nextOf(); 6225 6226 exp.type = exp.type.addMod(t1.mod); 6227 6228 Dsymbol vparent = exp.var.toParent(); 6229 AggregateDeclaration ad = vparent ? vparent.isAggregateDeclaration() : null; 6230 if (Expression e1x = getRightThis(exp.loc, sc, ad, exp.e1, exp.var, 1)) 6231 exp.e1 = e1x; 6232 else 6233 { 6234 /* Later checkRightThis will report correct error for invalid field variable access. 6235 */ 6236 Expression e = new VarExp(exp.loc, exp.var); 6237 e = e.expressionSemantic(sc); 6238 result = e; 6239 return; 6240 } 6241 checkAccess(exp.loc, sc, exp.e1, exp.var); 6242 6243 VarDeclaration v = exp.var.isVarDeclaration(); 6244 if (v && (v.isDataseg() || (v.storage_class & STC.manifest))) 6245 { 6246 Expression e = expandVar(WANTvalue, v); 6247 if (e) 6248 { 6249 result = e; 6250 return; 6251 } 6252 } 6253 6254 if (v && (v.isDataseg() || // fix https://issues.dlang.org/show_bug.cgi?id=8238 6255 (!v.needThis() && v.semanticRun > PASS.init))) // fix https://issues.dlang.org/show_bug.cgi?id=17258 6256 { 6257 // (e1, v) 6258 checkAccess(exp.loc, sc, exp.e1, v); 6259 Expression e = new VarExp(exp.loc, v); 6260 e = new CommaExp(exp.loc, exp.e1, e); 6261 e = e.expressionSemantic(sc); 6262 result = e; 6263 return; 6264 } 6265 } 6266 //printf("-DotVarExp::semantic('%s')\n", toChars()); 6267 result = exp; 6268 } 6269 6270 override void visit(DotTemplateInstanceExp exp) 6271 { 6272 static if (LOGSEMANTIC) 6273 { 6274 printf("DotTemplateInstanceExp::semantic('%s')\n", exp.toChars()); 6275 } 6276 // Indicate we need to resolve by UFCS. 6277 Expression e = exp.semanticY(sc, 1); 6278 if (!e) 6279 e = resolveUFCSProperties(sc, exp); 6280 result = e; 6281 } 6282 6283 override void visit(DelegateExp e) 6284 { 6285 static if (LOGSEMANTIC) 6286 { 6287 printf("DelegateExp::semantic('%s')\n", e.toChars()); 6288 } 6289 if (e.type) 6290 { 6291 result = e; 6292 return; 6293 } 6294 6295 e.e1 = e.e1.expressionSemantic(sc); 6296 6297 e.type = new TypeDelegate(e.func.type); 6298 e.type = e.type.typeSemantic(e.loc, sc); 6299 6300 FuncDeclaration f = e.func.toAliasFunc(); 6301 AggregateDeclaration ad = f.toParentLocal().isAggregateDeclaration(); 6302 if (f.needThis()) 6303 e.e1 = getRightThis(e.loc, sc, ad, e.e1, f); 6304 if (e.e1.op == TOK.error) 6305 return setError(); 6306 6307 /* A delegate takes the address of e.e1 in order to set the .ptr field 6308 * https://issues.dlang.org/show_bug.cgi?id=18575 6309 */ 6310 if (global.params.vsafe && e.e1.type.toBasetype().ty == Tstruct) 6311 { 6312 if (auto v = expToVariable(e.e1)) 6313 { 6314 if (!checkAddressVar(sc, e, v)) 6315 return setError(); 6316 } 6317 } 6318 6319 if (f.type.ty == Tfunction) 6320 { 6321 TypeFunction tf = cast(TypeFunction)f.type; 6322 if (!MODmethodConv(e.e1.type.mod, f.type.mod)) 6323 { 6324 OutBuffer thisBuf, funcBuf; 6325 MODMatchToBuffer(&thisBuf, e.e1.type.mod, tf.mod); 6326 MODMatchToBuffer(&funcBuf, tf.mod, e.e1.type.mod); 6327 e.error("%smethod `%s` is not callable using a %s`%s`", 6328 funcBuf.peekChars(), f.toPrettyChars(), thisBuf.peekChars(), e.e1.toChars()); 6329 return setError(); 6330 } 6331 } 6332 if (ad && ad.isClassDeclaration() && ad.type != e.e1.type) 6333 { 6334 // A downcast is required for interfaces 6335 // https://issues.dlang.org/show_bug.cgi?id=3706 6336 e.e1 = new CastExp(e.loc, e.e1, ad.type); 6337 e.e1 = e.e1.expressionSemantic(sc); 6338 } 6339 result = e; 6340 // declare dual-context container 6341 if (f.isThis2 && !sc.intypeof && sc.func) 6342 { 6343 // check access to second `this` 6344 if (AggregateDeclaration ad2 = f.isMember2()) 6345 { 6346 Expression te = new ThisExp(e.loc).expressionSemantic(sc); 6347 if (te.op != TOK.error) 6348 te = getRightThis(e.loc, sc, ad2, te, f); 6349 if (te.op == TOK.error) 6350 { 6351 e.error("need `this` of type `%s` to make delegate from function `%s`", ad2.toChars(), f.toChars()); 6352 return setError(); 6353 } 6354 } 6355 VarDeclaration vthis2 = makeThis2Argument(e.loc, sc, f); 6356 e.vthis2 = vthis2; 6357 Expression de = new DeclarationExp(e.loc, vthis2); 6358 result = Expression.combine(de, result); 6359 result = result.expressionSemantic(sc); 6360 } 6361 } 6362 6363 override void visit(DotTypeExp exp) 6364 { 6365 static if (LOGSEMANTIC) 6366 { 6367 printf("DotTypeExp::semantic('%s')\n", exp.toChars()); 6368 } 6369 if (exp.type) 6370 { 6371 result = exp; 6372 return; 6373 } 6374 6375 if (auto e = unaSemantic(exp, sc)) 6376 { 6377 result = e; 6378 return; 6379 } 6380 6381 exp.type = exp.sym.getType().addMod(exp.e1.type.mod); 6382 result = exp; 6383 } 6384 6385 override void visit(AddrExp exp) 6386 { 6387 static if (LOGSEMANTIC) 6388 { 6389 printf("AddrExp::semantic('%s')\n", exp.toChars()); 6390 } 6391 if (exp.type) 6392 { 6393 result = exp; 6394 return; 6395 } 6396 6397 if (Expression ex = unaSemantic(exp, sc)) 6398 { 6399 result = ex; 6400 return; 6401 } 6402 6403 int wasCond = exp.e1.op == TOK.question; 6404 6405 if (exp.e1.op == TOK.dotTemplateInstance) 6406 { 6407 DotTemplateInstanceExp dti = cast(DotTemplateInstanceExp)exp.e1; 6408 TemplateInstance ti = dti.ti; 6409 { 6410 //assert(ti.needsTypeInference(sc)); 6411 ti.dsymbolSemantic(sc); 6412 if (!ti.inst || ti.errors) // if template failed to expand 6413 return setError(); 6414 6415 Dsymbol s = ti.toAlias(); 6416 FuncDeclaration f = s.isFuncDeclaration(); 6417 if (f) 6418 { 6419 exp.e1 = new DotVarExp(exp.e1.loc, dti.e1, f); 6420 exp.e1 = exp.e1.expressionSemantic(sc); 6421 } 6422 } 6423 } 6424 else if (exp.e1.op == TOK.scope_) 6425 { 6426 TemplateInstance ti = (cast(ScopeExp)exp.e1).sds.isTemplateInstance(); 6427 if (ti) 6428 { 6429 //assert(ti.needsTypeInference(sc)); 6430 ti.dsymbolSemantic(sc); 6431 if (!ti.inst || ti.errors) // if template failed to expand 6432 return setError(); 6433 6434 Dsymbol s = ti.toAlias(); 6435 FuncDeclaration f = s.isFuncDeclaration(); 6436 if (f) 6437 { 6438 exp.e1 = new VarExp(exp.e1.loc, f); 6439 exp.e1 = exp.e1.expressionSemantic(sc); 6440 } 6441 } 6442 } 6443 /* https://issues.dlang.org/show_bug.cgi?id=809 6444 * 6445 * If the address of a lazy variable is taken, 6446 * the expression is rewritten so that the type 6447 * of it is the delegate type. This means that 6448 * the symbol is not going to represent a call 6449 * to the delegate anymore, but rather, the 6450 * actual symbol. 6451 */ 6452 if (auto ve = exp.e1.isVarExp()) 6453 { 6454 if (ve.var.storage_class & STC.lazy_) 6455 { 6456 exp.e1 = exp.e1.expressionSemantic(sc); 6457 exp.e1 = resolveProperties(sc, exp.e1); 6458 if (auto callExp = exp.e1.isCallExp()) 6459 { 6460 if (callExp.e1.type.toBasetype().ty == Tdelegate) 6461 { 6462 /* https://issues.dlang.org/show_bug.cgi?id=20551 6463 * 6464 * Cannot take address of lazy parameter in @safe code 6465 * because it might end up being a pointer to undefined 6466 * memory. 6467 */ 6468 if (sc.func && !sc.intypeof && !(sc.flags & SCOPE.debug_) && sc.func.setUnsafe()) 6469 { 6470 exp.error("cannot take address of lazy parameter `%s` in `@safe` function `%s`", 6471 ve.toChars(), sc.func.toChars()); 6472 setError(); 6473 } 6474 else 6475 { 6476 VarExp ve2 = callExp.e1.isVarExp(); 6477 ve2.delegateWasExtracted = true; 6478 ve2.var.storage_class |= STC.scope_; 6479 result = ve2; 6480 } 6481 return; 6482 } 6483 } 6484 } 6485 } 6486 6487 exp.e1 = exp.e1.toLvalue(sc, null); 6488 if (exp.e1.op == TOK.error) 6489 { 6490 result = exp.e1; 6491 return; 6492 } 6493 if (checkNonAssignmentArrayOp(exp.e1)) 6494 return setError(); 6495 6496 if (!exp.e1.type) 6497 { 6498 exp.error("cannot take address of `%s`", exp.e1.toChars()); 6499 return setError(); 6500 } 6501 6502 bool hasOverloads; 6503 if (auto f = isFuncAddress(exp, &hasOverloads)) 6504 { 6505 if (!hasOverloads && f.checkForwardRef(exp.loc)) 6506 return setError(); 6507 } 6508 else if (!exp.e1.type.deco) 6509 { 6510 if (exp.e1.op == TOK.variable) 6511 { 6512 VarExp ve = cast(VarExp)exp.e1; 6513 Declaration d = ve.var; 6514 exp.error("forward reference to %s `%s`", d.kind(), d.toChars()); 6515 } 6516 else 6517 exp.error("forward reference to `%s`", exp.e1.toChars()); 6518 return setError(); 6519 } 6520 6521 exp.type = exp.e1.type.pointerTo(); 6522 6523 // See if this should really be a delegate 6524 if (exp.e1.op == TOK.dotVariable) 6525 { 6526 DotVarExp dve = cast(DotVarExp)exp.e1; 6527 FuncDeclaration f = dve.var.isFuncDeclaration(); 6528 if (f) 6529 { 6530 f = f.toAliasFunc(); // FIXME, should see overloads 6531 // https://issues.dlang.org/show_bug.cgi?id=1983 6532 if (!dve.hasOverloads) 6533 f.tookAddressOf++; 6534 6535 Expression e; 6536 if (f.needThis()) 6537 e = new DelegateExp(exp.loc, dve.e1, f, dve.hasOverloads); 6538 else // It is a function pointer. Convert &v.f() --> (v, &V.f()) 6539 e = new CommaExp(exp.loc, dve.e1, new AddrExp(exp.loc, new VarExp(exp.loc, f, dve.hasOverloads))); 6540 e = e.expressionSemantic(sc); 6541 result = e; 6542 return; 6543 } 6544 6545 // Look for misaligned pointer in @safe mode 6546 if (checkUnsafeAccess(sc, dve, !exp.type.isMutable(), true)) 6547 return setError(); 6548 6549 if (global.params.vsafe) 6550 { 6551 if (VarDeclaration v = expToVariable(dve.e1)) 6552 { 6553 if (!checkAddressVar(sc, exp, v)) 6554 return setError(); 6555 } 6556 } 6557 } 6558 else if (exp.e1.op == TOK.variable) 6559 { 6560 VarExp ve = cast(VarExp)exp.e1; 6561 VarDeclaration v = ve.var.isVarDeclaration(); 6562 if (v) 6563 { 6564 if (!checkAddressVar(sc, exp, v)) 6565 return setError(); 6566 6567 ve.checkPurity(sc, v); 6568 } 6569 FuncDeclaration f = ve.var.isFuncDeclaration(); 6570 if (f) 6571 { 6572 /* Because nested functions cannot be overloaded, 6573 * mark here that we took its address because castTo() 6574 * may not be called with an exact match. 6575 */ 6576 if (!ve.hasOverloads || (f.isNested() && !f.needThis())) 6577 f.tookAddressOf++; 6578 if (f.isNested() && !f.needThis()) 6579 { 6580 if (f.isFuncLiteralDeclaration()) 6581 { 6582 if (!f.FuncDeclaration.isNested()) 6583 { 6584 /* Supply a 'null' for a this pointer if no this is available 6585 */ 6586 Expression e = new DelegateExp(exp.loc, new NullExp(exp.loc, Type.tnull), f, ve.hasOverloads); 6587 e = e.expressionSemantic(sc); 6588 result = e; 6589 return; 6590 } 6591 } 6592 Expression e = new DelegateExp(exp.loc, exp.e1, f, ve.hasOverloads); 6593 e = e.expressionSemantic(sc); 6594 result = e; 6595 return; 6596 } 6597 if (f.needThis()) 6598 { 6599 if (hasThis(sc)) 6600 { 6601 /* Should probably supply 'this' after overload resolution, 6602 * not before. 6603 */ 6604 Expression ethis = new ThisExp(exp.loc); 6605 Expression e = new DelegateExp(exp.loc, ethis, f, ve.hasOverloads); 6606 e = e.expressionSemantic(sc); 6607 result = e; 6608 return; 6609 } 6610 if (sc.func && !sc.intypeof) 6611 { 6612 if (!(sc.flags & SCOPE.debug_) && sc.func.setUnsafe()) 6613 { 6614 exp.error("`this` reference necessary to take address of member `%s` in `@safe` function `%s`", f.toChars(), sc.func.toChars()); 6615 } 6616 } 6617 } 6618 } 6619 } 6620 else if ((exp.e1.op == TOK.this_ || exp.e1.op == TOK.super_) && global.params.vsafe) 6621 { 6622 if (VarDeclaration v = expToVariable(exp.e1)) 6623 { 6624 if (!checkAddressVar(sc, exp, v)) 6625 return setError(); 6626 } 6627 } 6628 else if (exp.e1.op == TOK.call) 6629 { 6630 CallExp ce = cast(CallExp)exp.e1; 6631 if (ce.e1.type.ty == Tfunction) 6632 { 6633 TypeFunction tf = cast(TypeFunction)ce.e1.type; 6634 if (tf.isref && sc.func && !sc.intypeof && !(sc.flags & SCOPE.debug_) && sc.func.setUnsafe()) 6635 { 6636 exp.error("cannot take address of `ref return` of `%s()` in `@safe` function `%s`", 6637 ce.e1.toChars(), sc.func.toChars()); 6638 } 6639 } 6640 } 6641 else if (exp.e1.op == TOK.index) 6642 { 6643 /* For: 6644 * int[3] a; 6645 * &a[i] 6646 * check 'a' the same as for a regular variable 6647 */ 6648 if (VarDeclaration v = expToVariable(exp.e1)) 6649 { 6650 if (global.params.vsafe && !checkAddressVar(sc, exp, v)) 6651 return setError(); 6652 6653 exp.e1.checkPurity(sc, v); 6654 } 6655 } 6656 else if (wasCond) 6657 { 6658 /* a ? b : c was transformed to *(a ? &b : &c), but we still 6659 * need to do safety checks 6660 */ 6661 assert(exp.e1.op == TOK.star); 6662 PtrExp pe = cast(PtrExp)exp.e1; 6663 assert(pe.e1.op == TOK.question); 6664 CondExp ce = cast(CondExp)pe.e1; 6665 assert(ce.e1.op == TOK.address); 6666 assert(ce.e2.op == TOK.address); 6667 6668 // Re-run semantic on the address expressions only 6669 ce.e1.type = null; 6670 ce.e1 = ce.e1.expressionSemantic(sc); 6671 ce.e2.type = null; 6672 ce.e2 = ce.e2.expressionSemantic(sc); 6673 } 6674 result = exp.optimize(WANTvalue); 6675 } 6676 6677 override void visit(PtrExp exp) 6678 { 6679 static if (LOGSEMANTIC) 6680 { 6681 printf("PtrExp::semantic('%s')\n", exp.toChars()); 6682 } 6683 if (exp.type) 6684 { 6685 result = exp; 6686 return; 6687 } 6688 6689 Expression e = exp.op_overload(sc); 6690 if (e) 6691 { 6692 result = e; 6693 return; 6694 } 6695 6696 Type tb = exp.e1.type.toBasetype(); 6697 switch (tb.ty) 6698 { 6699 case Tpointer: 6700 exp.type = (cast(TypePointer)tb).next; 6701 break; 6702 6703 case Tsarray: 6704 case Tarray: 6705 if (isNonAssignmentArrayOp(exp.e1)) 6706 goto default; 6707 exp.error("using `*` on an array is no longer supported; use `*(%s).ptr` instead", exp.e1.toChars()); 6708 exp.type = (cast(TypeArray)tb).next; 6709 exp.e1 = exp.e1.castTo(sc, exp.type.pointerTo()); 6710 break; 6711 6712 case Terror: 6713 return setError(); 6714 6715 default: 6716 exp.error("can only `*` a pointer, not a `%s`", exp.e1.type.toChars()); 6717 goto case Terror; 6718 } 6719 6720 if (exp.checkValue() || exp.checkSharedAccess(sc)) 6721 return setError(); 6722 6723 result = exp; 6724 } 6725 6726 override void visit(NegExp exp) 6727 { 6728 static if (LOGSEMANTIC) 6729 { 6730 printf("NegExp::semantic('%s')\n", exp.toChars()); 6731 } 6732 if (exp.type) 6733 { 6734 result = exp; 6735 return; 6736 } 6737 6738 Expression e = exp.op_overload(sc); 6739 if (e) 6740 { 6741 result = e; 6742 return; 6743 } 6744 6745 fix16997(sc, exp); 6746 exp.type = exp.e1.type; 6747 Type tb = exp.type.toBasetype(); 6748 if (tb.ty == Tarray || tb.ty == Tsarray) 6749 { 6750 if (!isArrayOpValid(exp.e1)) 6751 { 6752 result = arrayOpInvalidError(exp); 6753 return; 6754 } 6755 result = exp; 6756 return; 6757 } 6758 if (!target.isVectorOpSupported(tb, exp.op)) 6759 { 6760 result = exp.incompatibleTypes(); 6761 return; 6762 } 6763 if (exp.e1.checkNoBool()) 6764 return setError(); 6765 if (exp.e1.checkArithmetic() || 6766 exp.e1.checkSharedAccess(sc)) 6767 return setError(); 6768 6769 result = exp; 6770 } 6771 6772 override void visit(UAddExp exp) 6773 { 6774 static if (LOGSEMANTIC) 6775 { 6776 printf("UAddExp::semantic('%s')\n", exp.toChars()); 6777 } 6778 assert(!exp.type); 6779 6780 Expression e = exp.op_overload(sc); 6781 if (e) 6782 { 6783 result = e; 6784 return; 6785 } 6786 6787 fix16997(sc, exp); 6788 if (!target.isVectorOpSupported(exp.e1.type.toBasetype(), exp.op)) 6789 { 6790 result = exp.incompatibleTypes(); 6791 return; 6792 } 6793 if (exp.e1.checkNoBool()) 6794 return setError(); 6795 if (exp.e1.checkArithmetic()) 6796 return setError(); 6797 if (exp.e1.checkSharedAccess(sc)) 6798 return setError(); 6799 6800 result = exp.e1; 6801 } 6802 6803 override void visit(ComExp exp) 6804 { 6805 if (exp.type) 6806 { 6807 result = exp; 6808 return; 6809 } 6810 6811 Expression e = exp.op_overload(sc); 6812 if (e) 6813 { 6814 result = e; 6815 return; 6816 } 6817 6818 fix16997(sc, exp); 6819 exp.type = exp.e1.type; 6820 Type tb = exp.type.toBasetype(); 6821 if (tb.ty == Tarray || tb.ty == Tsarray) 6822 { 6823 if (!isArrayOpValid(exp.e1)) 6824 { 6825 result = arrayOpInvalidError(exp); 6826 return; 6827 } 6828 result = exp; 6829 return; 6830 } 6831 if (!target.isVectorOpSupported(tb, exp.op)) 6832 { 6833 result = exp.incompatibleTypes(); 6834 return; 6835 } 6836 if (exp.e1.checkNoBool()) 6837 return setError(); 6838 if (exp.e1.checkIntegral() || 6839 exp.e1.checkSharedAccess(sc)) 6840 return setError(); 6841 6842 result = exp; 6843 } 6844 6845 override void visit(NotExp e) 6846 { 6847 if (e.type) 6848 { 6849 result = e; 6850 return; 6851 } 6852 6853 e.setNoderefOperand(); 6854 6855 // Note there is no operator overload 6856 if (Expression ex = unaSemantic(e, sc)) 6857 { 6858 result = ex; 6859 return; 6860 } 6861 6862 // for static alias this: https://issues.dlang.org/show_bug.cgi?id=17684 6863 if (e.e1.op == TOK.type) 6864 e.e1 = resolveAliasThis(sc, e.e1); 6865 6866 e.e1 = resolveProperties(sc, e.e1); 6867 e.e1 = e.e1.toBoolean(sc); 6868 if (e.e1.type == Type.terror) 6869 { 6870 result = e.e1; 6871 return; 6872 } 6873 6874 if (!target.isVectorOpSupported(e.e1.type.toBasetype(), e.op)) 6875 { 6876 result = e.incompatibleTypes(); 6877 } 6878 // https://issues.dlang.org/show_bug.cgi?id=13910 6879 // Today NotExp can take an array as its operand. 6880 if (checkNonAssignmentArrayOp(e.e1)) 6881 return setError(); 6882 6883 e.type = Type.tbool; 6884 result = e; 6885 } 6886 6887 override void visit(DeleteExp exp) 6888 { 6889 if (!sc.isDeprecated) 6890 { 6891 // @@@DEPRECATED_2019-02@@@ 6892 // 1. Deprecation for 1 year 6893 // 2. Error for 1 year 6894 // 3. Removal of keyword, "delete" can be used for other identities 6895 if (!exp.isRAII) 6896 deprecation(exp.loc, "The `delete` keyword has been deprecated. Use `object.destroy()` (and `core.memory.GC.free()` if applicable) instead."); 6897 } 6898 6899 if (Expression ex = unaSemantic(exp, sc)) 6900 { 6901 result = ex; 6902 return; 6903 } 6904 exp.e1 = resolveProperties(sc, exp.e1); 6905 exp.e1 = exp.e1.modifiableLvalue(sc, null); 6906 if (exp.e1.op == TOK.error) 6907 { 6908 result = exp.e1; 6909 return; 6910 } 6911 exp.type = Type.tvoid; 6912 6913 AggregateDeclaration ad = null; 6914 Type tb = exp.e1.type.toBasetype(); 6915 switch (tb.ty) 6916 { 6917 case Tclass: 6918 { 6919 auto cd = (cast(TypeClass)tb).sym; 6920 if (cd.isCOMinterface()) 6921 { 6922 /* Because COM classes are deleted by IUnknown.Release() 6923 */ 6924 exp.error("cannot `delete` instance of COM interface `%s`", cd.toChars()); 6925 return setError(); 6926 } 6927 ad = cd; 6928 break; 6929 } 6930 case Tpointer: 6931 tb = (cast(TypePointer)tb).next.toBasetype(); 6932 if (tb.ty == Tstruct) 6933 { 6934 ad = (cast(TypeStruct)tb).sym; 6935 semanticTypeInfo(sc, tb); 6936 } 6937 break; 6938 6939 case Tarray: 6940 { 6941 Type tv = tb.nextOf().baseElemOf(); 6942 if (tv.ty == Tstruct) 6943 { 6944 ad = (cast(TypeStruct)tv).sym; 6945 if (ad.dtor) 6946 semanticTypeInfo(sc, ad.type); 6947 } 6948 break; 6949 } 6950 default: 6951 exp.error("cannot delete type `%s`", exp.e1.type.toChars()); 6952 return setError(); 6953 } 6954 6955 bool err = false; 6956 if (ad) 6957 { 6958 if (ad.dtor) 6959 { 6960 err |= exp.checkPurity(sc, ad.dtor); 6961 err |= exp.checkSafety(sc, ad.dtor); 6962 err |= exp.checkNogc(sc, ad.dtor); 6963 } 6964 if (err) 6965 return setError(); 6966 } 6967 6968 if (!sc.intypeof && sc.func && 6969 !exp.isRAII && 6970 !(sc.flags & SCOPE.debug_) && 6971 sc.func.setUnsafe()) 6972 { 6973 exp.error("`%s` is not `@safe` but is used in `@safe` function `%s`", exp.toChars(), sc.func.toChars()); 6974 err = true; 6975 } 6976 if (err) 6977 return setError(); 6978 6979 result = exp; 6980 } 6981 6982 override void visit(CastExp exp) 6983 { 6984 static if (LOGSEMANTIC) 6985 { 6986 printf("CastExp::semantic('%s')\n", exp.toChars()); 6987 } 6988 //static int x; assert(++x < 10); 6989 if (exp.type) 6990 { 6991 result = exp; 6992 return; 6993 } 6994 6995 if (exp.to) 6996 { 6997 exp.to = exp.to.typeSemantic(exp.loc, sc); 6998 if (exp.to == Type.terror) 6999 return setError(); 7000 7001 if (!exp.to.hasPointers()) 7002 exp.setNoderefOperand(); 7003 7004 // When e1 is a template lambda, this cast may instantiate it with 7005 // the type 'to'. 7006 exp.e1 = inferType(exp.e1, exp.to); 7007 } 7008 7009 if (auto e = unaSemantic(exp, sc)) 7010 { 7011 result = e; 7012 return; 7013 } 7014 7015 // for static alias this: https://issues.dlang.org/show_bug.cgi?id=17684 7016 if (exp.e1.op == TOK.type) 7017 exp.e1 = resolveAliasThis(sc, exp.e1); 7018 7019 auto e1x = resolveProperties(sc, exp.e1); 7020 if (e1x.op == TOK.error) 7021 { 7022 result = e1x; 7023 return; 7024 } 7025 if (e1x.checkType()) 7026 return setError(); 7027 exp.e1 = e1x; 7028 7029 if (!exp.e1.type) 7030 { 7031 exp.error("cannot cast `%s`", exp.e1.toChars()); 7032 return setError(); 7033 } 7034 7035 // https://issues.dlang.org/show_bug.cgi?id=19954 7036 if (exp.e1.type.ty == Ttuple) 7037 { 7038 TupleExp te = exp.e1.isTupleExp(); 7039 if (te.exps.dim == 1) 7040 exp.e1 = (*te.exps)[0]; 7041 } 7042 7043 // only allow S(x) rewrite if cast specified S explicitly. 7044 // See https://issues.dlang.org/show_bug.cgi?id=18545 7045 const bool allowImplicitConstruction = exp.to !is null; 7046 7047 if (!exp.to) // Handle cast(const) and cast(immutable), etc. 7048 { 7049 exp.to = exp.e1.type.castMod(exp.mod); 7050 exp.to = exp.to.typeSemantic(exp.loc, sc); 7051 7052 if (exp.to == Type.terror) 7053 return setError(); 7054 } 7055 7056 if (exp.to.ty == Ttuple) 7057 { 7058 exp.error("cannot cast `%s` to tuple type `%s`", exp.e1.toChars(), exp.to.toChars()); 7059 return setError(); 7060 } 7061 7062 // cast(void) is used to mark e1 as unused, so it is safe 7063 if (exp.to.ty == Tvoid) 7064 { 7065 exp.type = exp.to; 7066 result = exp; 7067 return; 7068 } 7069 7070 if (!exp.to.equals(exp.e1.type) && exp.mod == cast(ubyte)~0) 7071 { 7072 if (Expression e = exp.op_overload(sc)) 7073 { 7074 result = e.implicitCastTo(sc, exp.to); 7075 return; 7076 } 7077 } 7078 7079 Type t1b = exp.e1.type.toBasetype(); 7080 Type tob = exp.to.toBasetype(); 7081 7082 if (allowImplicitConstruction && tob.ty == Tstruct && !tob.equals(t1b)) 7083 { 7084 /* Look to replace: 7085 * cast(S)t 7086 * with: 7087 * S(t) 7088 */ 7089 7090 // Rewrite as to.call(e1) 7091 Expression e = new TypeExp(exp.loc, exp.to); 7092 e = new CallExp(exp.loc, e, exp.e1); 7093 e = e.trySemantic(sc); 7094 if (e) 7095 { 7096 result = e; 7097 return; 7098 } 7099 } 7100 7101 if (!t1b.equals(tob) && (t1b.ty == Tarray || t1b.ty == Tsarray)) 7102 { 7103 if (checkNonAssignmentArrayOp(exp.e1)) 7104 return setError(); 7105 } 7106 7107 // Look for casting to a vector type 7108 if (tob.ty == Tvector && t1b.ty != Tvector) 7109 { 7110 result = new VectorExp(exp.loc, exp.e1, exp.to); 7111 result = result.expressionSemantic(sc); 7112 return; 7113 } 7114 7115 Expression ex = exp.e1.castTo(sc, exp.to); 7116 if (ex.op == TOK.error) 7117 { 7118 result = ex; 7119 return; 7120 } 7121 7122 // Check for unsafe casts 7123 if (!sc.intypeof && 7124 !(sc.flags & SCOPE.debug_) && 7125 !isSafeCast(ex, t1b, tob) && 7126 (!sc.func && sc.stc & STC.safe || sc.func && sc.func.setUnsafe())) 7127 { 7128 exp.error("cast from `%s` to `%s` not allowed in safe code", exp.e1.type.toChars(), exp.to.toChars()); 7129 return setError(); 7130 } 7131 7132 // `object.__ArrayCast` is a rewrite of an old runtime hook `_d_arraycast`. `_d_arraycast` was not built 7133 // to handle certain casts. Those casts which `object.__ArrayCast` does not support are filtered out. 7134 // See `e2ir.toElemCast` for other types of casts. If `object.__ArrayCast` is improved to support more 7135 // casts these conditions and potentially some logic in `e2ir.toElemCast` can be removed. 7136 if (tob.ty == Tarray) 7137 { 7138 // https://issues.dlang.org/show_bug.cgi?id=19840 7139 if (auto ad = isAggregate(t1b)) 7140 { 7141 if (ad.aliasthis) 7142 { 7143 Expression e = resolveAliasThis(sc, exp.e1); 7144 e = new CastExp(exp.loc, e, exp.to); 7145 result = e.expressionSemantic(sc); 7146 return; 7147 } 7148 } 7149 7150 if(t1b.ty == Tarray && exp.e1.op != TOK.arrayLiteral && (sc.flags & SCOPE.ctfe) == 0) 7151 { 7152 auto tFrom = t1b.nextOf(); 7153 auto tTo = tob.nextOf(); 7154 7155 // https://issues.dlang.org/show_bug.cgi?id=20130 7156 if (exp.e1.op != TOK.string_ || !ex.isStringExp) 7157 { 7158 const uint fromSize = cast(uint)tFrom.size(); 7159 const uint toSize = cast(uint)tTo.size(); 7160 7161 // If array element sizes do not match, we must adjust the dimensions 7162 if (fromSize != toSize) 7163 { 7164 if (!verifyHookExist(exp.loc, *sc, Id.__ArrayCast, "casting array of structs")) 7165 return setError(); 7166 7167 // A runtime check is needed in case arrays don't line up. That check should 7168 // be done in the implementation of `object.__ArrayCast` 7169 if (toSize == 0 || (fromSize % toSize) != 0) 7170 { 7171 // lower to `object.__ArrayCast!(TFrom, TTo)(from)` 7172 7173 // fully qualify as `object.__ArrayCast` 7174 Expression id = new IdentifierExp(exp.loc, Id.empty); 7175 auto dotid = new DotIdExp(exp.loc, id, Id.object); 7176 7177 auto tiargs = new Objects(); 7178 tiargs.push(tFrom); 7179 tiargs.push(tTo); 7180 auto dt = new DotTemplateInstanceExp(exp.loc, dotid, Id.__ArrayCast, tiargs); 7181 7182 auto arguments = new Expressions(); 7183 arguments.push(exp.e1); 7184 Expression ce = new CallExp(exp.loc, dt, arguments); 7185 7186 result = expressionSemantic(ce, sc); 7187 return; 7188 } 7189 } 7190 } 7191 } 7192 } 7193 7194 result = ex; 7195 } 7196 7197 override void visit(VectorExp exp) 7198 { 7199 static if (LOGSEMANTIC) 7200 { 7201 printf("VectorExp::semantic('%s')\n", exp.toChars()); 7202 } 7203 if (exp.type) 7204 { 7205 result = exp; 7206 return; 7207 } 7208 7209 exp.e1 = exp.e1.expressionSemantic(sc); 7210 exp.type = exp.to.typeSemantic(exp.loc, sc); 7211 if (exp.e1.op == TOK.error || exp.type.ty == Terror) 7212 { 7213 result = exp.e1; 7214 return; 7215 } 7216 7217 Type tb = exp.type.toBasetype(); 7218 assert(tb.ty == Tvector); 7219 TypeVector tv = cast(TypeVector)tb; 7220 Type te = tv.elementType(); 7221 exp.dim = cast(int)(tv.size(exp.loc) / te.size(exp.loc)); 7222 7223 bool checkElem(Expression elem) 7224 { 7225 if (elem.isConst() == 1) 7226 return false; 7227 7228 exp.error("constant expression expected, not `%s`", elem.toChars()); 7229 return true; 7230 } 7231 7232 exp.e1 = exp.e1.optimize(WANTvalue); 7233 bool res; 7234 if (exp.e1.op == TOK.arrayLiteral) 7235 { 7236 foreach (i; 0 .. exp.dim) 7237 { 7238 // Do not stop on first error - check all AST nodes even if error found 7239 res |= checkElem(exp.e1.isArrayLiteralExp()[i]); 7240 } 7241 } 7242 else if (exp.e1.type.ty == Tvoid) 7243 checkElem(exp.e1); 7244 7245 result = res ? new ErrorExp() : exp; 7246 } 7247 7248 override void visit(VectorArrayExp e) 7249 { 7250 static if (LOGSEMANTIC) 7251 { 7252 printf("VectorArrayExp::semantic('%s')\n", e.toChars()); 7253 } 7254 if (!e.type) 7255 { 7256 unaSemantic(e, sc); 7257 e.e1 = resolveProperties(sc, e.e1); 7258 7259 if (e.e1.op == TOK.error) 7260 { 7261 result = e.e1; 7262 return; 7263 } 7264 assert(e.e1.type.ty == Tvector); 7265 e.type = e.e1.type.isTypeVector().basetype; 7266 } 7267 result = e; 7268 } 7269 7270 override void visit(SliceExp exp) 7271 { 7272 static if (LOGSEMANTIC) 7273 { 7274 printf("SliceExp::semantic('%s')\n", exp.toChars()); 7275 } 7276 if (exp.type) 7277 { 7278 result = exp; 7279 return; 7280 } 7281 7282 // operator overloading should be handled in ArrayExp already. 7283 if (Expression ex = unaSemantic(exp, sc)) 7284 { 7285 result = ex; 7286 return; 7287 } 7288 exp.e1 = resolveProperties(sc, exp.e1); 7289 if (exp.e1.op == TOK.type && exp.e1.type.ty != Ttuple) 7290 { 7291 if (exp.lwr || exp.upr) 7292 { 7293 exp.error("cannot slice type `%s`", exp.e1.toChars()); 7294 return setError(); 7295 } 7296 Expression e = new TypeExp(exp.loc, exp.e1.type.arrayOf()); 7297 result = e.expressionSemantic(sc); 7298 return; 7299 } 7300 if (!exp.lwr && !exp.upr) 7301 { 7302 if (exp.e1.op == TOK.arrayLiteral) 7303 { 7304 // Convert [a,b,c][] to [a,b,c] 7305 Type t1b = exp.e1.type.toBasetype(); 7306 Expression e = exp.e1; 7307 if (t1b.ty == Tsarray) 7308 { 7309 e = e.copy(); 7310 e.type = t1b.nextOf().arrayOf(); 7311 } 7312 result = e; 7313 return; 7314 } 7315 if (exp.e1.op == TOK.slice) 7316 { 7317 // Convert e[][] to e[] 7318 SliceExp se = cast(SliceExp)exp.e1; 7319 if (!se.lwr && !se.upr) 7320 { 7321 result = se; 7322 return; 7323 } 7324 } 7325 if (isArrayOpOperand(exp.e1)) 7326 { 7327 // Convert (a[]+b[])[] to a[]+b[] 7328 result = exp.e1; 7329 return; 7330 } 7331 } 7332 if (exp.e1.op == TOK.error) 7333 { 7334 result = exp.e1; 7335 return; 7336 } 7337 if (exp.e1.type.ty == Terror) 7338 return setError(); 7339 7340 Type t1b = exp.e1.type.toBasetype(); 7341 if (t1b.ty == Tpointer) 7342 { 7343 if ((cast(TypePointer)t1b).next.ty == Tfunction) 7344 { 7345 exp.error("cannot slice function pointer `%s`", exp.e1.toChars()); 7346 return setError(); 7347 } 7348 if (!exp.lwr || !exp.upr) 7349 { 7350 exp.error("need upper and lower bound to slice pointer"); 7351 return setError(); 7352 } 7353 if (sc.func && !sc.intypeof && !(sc.flags & SCOPE.debug_) && sc.func.setUnsafe()) 7354 { 7355 exp.error("pointer slicing not allowed in safe functions"); 7356 return setError(); 7357 } 7358 } 7359 else if (t1b.ty == Tarray) 7360 { 7361 } 7362 else if (t1b.ty == Tsarray) 7363 { 7364 if (!exp.arrayop && global.params.vsafe) 7365 { 7366 /* Slicing a static array is like taking the address of it. 7367 * Perform checks as if e[] was &e 7368 */ 7369 if (VarDeclaration v = expToVariable(exp.e1)) 7370 { 7371 if (exp.e1.op == TOK.dotVariable) 7372 { 7373 DotVarExp dve = cast(DotVarExp)exp.e1; 7374 if ((dve.e1.op == TOK.this_ || dve.e1.op == TOK.super_) && 7375 !(v.storage_class & STC.ref_)) 7376 { 7377 // because it's a class 7378 v = null; 7379 } 7380 } 7381 7382 if (v && !checkAddressVar(sc, exp, v)) 7383 return setError(); 7384 } 7385 } 7386 } 7387 else if (t1b.ty == Ttuple) 7388 { 7389 if (!exp.lwr && !exp.upr) 7390 { 7391 result = exp.e1; 7392 return; 7393 } 7394 if (!exp.lwr || !exp.upr) 7395 { 7396 exp.error("need upper and lower bound to slice tuple"); 7397 return setError(); 7398 } 7399 } 7400 else if (t1b.ty == Tvector) 7401 { 7402 // Convert e1 to corresponding static array 7403 TypeVector tv1 = cast(TypeVector)t1b; 7404 t1b = tv1.basetype; 7405 t1b = t1b.castMod(tv1.mod); 7406 exp.e1.type = t1b; 7407 } 7408 else 7409 { 7410 exp.error("`%s` cannot be sliced with `[]`", t1b.ty == Tvoid ? exp.e1.toChars() : t1b.toChars()); 7411 return setError(); 7412 } 7413 7414 /* Run semantic on lwr and upr. 7415 */ 7416 Scope* scx = sc; 7417 if (t1b.ty == Tsarray || t1b.ty == Tarray || t1b.ty == Ttuple) 7418 { 7419 // Create scope for 'length' variable 7420 ScopeDsymbol sym = new ArrayScopeSymbol(sc, exp); 7421 sym.parent = sc.scopesym; 7422 sc = sc.push(sym); 7423 } 7424 if (exp.lwr) 7425 { 7426 if (t1b.ty == Ttuple) 7427 sc = sc.startCTFE(); 7428 exp.lwr = exp.lwr.expressionSemantic(sc); 7429 exp.lwr = resolveProperties(sc, exp.lwr); 7430 if (t1b.ty == Ttuple) 7431 sc = sc.endCTFE(); 7432 exp.lwr = exp.lwr.implicitCastTo(sc, Type.tsize_t); 7433 } 7434 if (exp.upr) 7435 { 7436 if (t1b.ty == Ttuple) 7437 sc = sc.startCTFE(); 7438 exp.upr = exp.upr.expressionSemantic(sc); 7439 exp.upr = resolveProperties(sc, exp.upr); 7440 if (t1b.ty == Ttuple) 7441 sc = sc.endCTFE(); 7442 exp.upr = exp.upr.implicitCastTo(sc, Type.tsize_t); 7443 } 7444 if (sc != scx) 7445 sc = sc.pop(); 7446 if (exp.lwr && exp.lwr.type == Type.terror || exp.upr && exp.upr.type == Type.terror) 7447 return setError(); 7448 7449 if (t1b.ty == Ttuple) 7450 { 7451 exp.lwr = exp.lwr.ctfeInterpret(); 7452 exp.upr = exp.upr.ctfeInterpret(); 7453 uinteger_t i1 = exp.lwr.toUInteger(); 7454 uinteger_t i2 = exp.upr.toUInteger(); 7455 7456 TupleExp te; 7457 TypeTuple tup; 7458 size_t length; 7459 if (exp.e1.op == TOK.tuple) // slicing an expression tuple 7460 { 7461 te = cast(TupleExp)exp.e1; 7462 tup = null; 7463 length = te.exps.dim; 7464 } 7465 else if (exp.e1.op == TOK.type) // slicing a type tuple 7466 { 7467 te = null; 7468 tup = cast(TypeTuple)t1b; 7469 length = Parameter.dim(tup.arguments); 7470 } 7471 else 7472 assert(0); 7473 7474 if (i2 < i1 || length < i2) 7475 { 7476 exp.error("string slice `[%llu .. %llu]` is out of bounds", i1, i2); 7477 return setError(); 7478 } 7479 7480 size_t j1 = cast(size_t)i1; 7481 size_t j2 = cast(size_t)i2; 7482 Expression e; 7483 if (exp.e1.op == TOK.tuple) 7484 { 7485 auto exps = new Expressions(j2 - j1); 7486 for (size_t i = 0; i < j2 - j1; i++) 7487 { 7488 (*exps)[i] = (*te.exps)[j1 + i]; 7489 } 7490 e = new TupleExp(exp.loc, te.e0, exps); 7491 } 7492 else 7493 { 7494 auto args = new Parameters(); 7495 args.reserve(j2 - j1); 7496 for (size_t i = j1; i < j2; i++) 7497 { 7498 Parameter arg = Parameter.getNth(tup.arguments, i); 7499 args.push(arg); 7500 } 7501 e = new TypeExp(exp.e1.loc, new TypeTuple(args)); 7502 } 7503 e = e.expressionSemantic(sc); 7504 result = e; 7505 return; 7506 } 7507 7508 exp.type = t1b.nextOf().arrayOf(); 7509 // Allow typedef[] -> typedef[] 7510 if (exp.type.equals(t1b)) 7511 exp.type = exp.e1.type; 7512 7513 // We might know $ now 7514 setLengthVarIfKnown(exp.lengthVar, t1b); 7515 7516 if (exp.lwr && exp.upr) 7517 { 7518 exp.lwr = exp.lwr.optimize(WANTvalue); 7519 exp.upr = exp.upr.optimize(WANTvalue); 7520 7521 IntRange lwrRange = getIntRange(exp.lwr); 7522 IntRange uprRange = getIntRange(exp.upr); 7523 7524 if (t1b.ty == Tsarray || t1b.ty == Tarray) 7525 { 7526 Expression el = new ArrayLengthExp(exp.loc, exp.e1); 7527 el = el.expressionSemantic(sc); 7528 el = el.optimize(WANTvalue); 7529 if (el.op == TOK.int64) 7530 { 7531 // Array length is known at compile-time. Upper is in bounds if it fits length. 7532 dinteger_t length = el.toInteger(); 7533 auto bounds = IntRange(SignExtendedNumber(0), SignExtendedNumber(length)); 7534 exp.upperIsInBounds = bounds.contains(uprRange); 7535 } 7536 else if (exp.upr.op == TOK.int64 && exp.upr.toInteger() == 0) 7537 { 7538 // Upper slice expression is '0'. Value is always in bounds. 7539 exp.upperIsInBounds = true; 7540 } 7541 else if (exp.upr.op == TOK.variable && (cast(VarExp)exp.upr).var.ident == Id.dollar) 7542 { 7543 // Upper slice expression is '$'. Value is always in bounds. 7544 exp.upperIsInBounds = true; 7545 } 7546 } 7547 else if (t1b.ty == Tpointer) 7548 { 7549 exp.upperIsInBounds = true; 7550 } 7551 else 7552 assert(0); 7553 7554 exp.lowerIsLessThanUpper = (lwrRange.imax <= uprRange.imin); 7555 7556 //printf("upperIsInBounds = %d lowerIsLessThanUpper = %d\n", exp.upperIsInBounds, exp.lowerIsLessThanUpper); 7557 } 7558 7559 result = exp; 7560 } 7561 7562 override void visit(ArrayLengthExp e) 7563 { 7564 static if (LOGSEMANTIC) 7565 { 7566 printf("ArrayLengthExp::semantic('%s')\n", e.toChars()); 7567 } 7568 if (e.type) 7569 { 7570 result = e; 7571 return; 7572 } 7573 7574 if (Expression ex = unaSemantic(e, sc)) 7575 { 7576 result = ex; 7577 return; 7578 } 7579 e.e1 = resolveProperties(sc, e.e1); 7580 7581 e.type = Type.tsize_t; 7582 result = e; 7583 } 7584 7585 override void visit(ArrayExp exp) 7586 { 7587 static if (LOGSEMANTIC) 7588 { 7589 printf("ArrayExp::semantic('%s')\n", exp.toChars()); 7590 } 7591 assert(!exp.type); 7592 Expression e = exp.op_overload(sc); 7593 if (e) 7594 { 7595 result = e; 7596 return; 7597 } 7598 7599 if (isAggregate(exp.e1.type)) 7600 exp.error("no `[]` operator overload for type `%s`", exp.e1.type.toChars()); 7601 else if (exp.e1.op == TOK.type && exp.e1.type.ty != Ttuple) 7602 exp.error("static array of `%s` with multiple lengths not allowed", exp.e1.type.toChars()); 7603 else if (isIndexableNonAggregate(exp.e1.type)) 7604 exp.error("only one index allowed to index `%s`", exp.e1.type.toChars()); 7605 else 7606 exp.error("cannot use `[]` operator on expression of type `%s`", exp.e1.type.toChars()); 7607 7608 result = new ErrorExp(); 7609 } 7610 7611 override void visit(DotExp exp) 7612 { 7613 static if (LOGSEMANTIC) 7614 { 7615 printf("DotExp::semantic('%s')\n", exp.toChars()); 7616 if (exp.type) 7617 printf("\ttype = %s\n", exp.type.toChars()); 7618 } 7619 exp.e1 = exp.e1.expressionSemantic(sc); 7620 exp.e2 = exp.e2.expressionSemantic(sc); 7621 7622 if (exp.e1.op == TOK.type) 7623 { 7624 result = exp.e2; 7625 return; 7626 } 7627 if (exp.e2.op == TOK.type) 7628 { 7629 result = exp.e2; 7630 return; 7631 } 7632 if (exp.e2.op == TOK.template_) 7633 { 7634 auto td = (cast(TemplateExp)exp.e2).td; 7635 Expression e = new DotTemplateExp(exp.loc, exp.e1, td); 7636 result = e.expressionSemantic(sc); 7637 return; 7638 } 7639 if (!exp.type || exp.e1.op == TOK.this_) 7640 exp.type = exp.e2.type; 7641 result = exp; 7642 } 7643 7644 override void visit(CommaExp e) 7645 { 7646 if (e.type) 7647 { 7648 result = e; 7649 return; 7650 } 7651 7652 // Allow `((a,b),(x,y))` 7653 if (e.allowCommaExp) 7654 { 7655 CommaExp.allow(e.e1); 7656 CommaExp.allow(e.e2); 7657 } 7658 7659 if (Expression ex = binSemanticProp(e, sc)) 7660 { 7661 result = ex; 7662 return; 7663 } 7664 e.e1 = e.e1.addDtorHook(sc); 7665 7666 if (checkNonAssignmentArrayOp(e.e1)) 7667 return setError(); 7668 7669 e.type = e.e2.type; 7670 if (e.type !is Type.tvoid && !e.allowCommaExp && !e.isGenerated) 7671 e.error("Using the result of a comma expression is not allowed"); 7672 result = e; 7673 } 7674 7675 override void visit(IntervalExp e) 7676 { 7677 static if (LOGSEMANTIC) 7678 { 7679 printf("IntervalExp::semantic('%s')\n", e.toChars()); 7680 } 7681 if (e.type) 7682 { 7683 result = e; 7684 return; 7685 } 7686 7687 Expression le = e.lwr; 7688 le = le.expressionSemantic(sc); 7689 le = resolveProperties(sc, le); 7690 7691 Expression ue = e.upr; 7692 ue = ue.expressionSemantic(sc); 7693 ue = resolveProperties(sc, ue); 7694 7695 if (le.op == TOK.error) 7696 { 7697 result = le; 7698 return; 7699 } 7700 if (ue.op == TOK.error) 7701 { 7702 result = ue; 7703 return; 7704 } 7705 7706 e.lwr = le; 7707 e.upr = ue; 7708 7709 e.type = Type.tvoid; 7710 result = e; 7711 } 7712 7713 override void visit(DelegatePtrExp e) 7714 { 7715 static if (LOGSEMANTIC) 7716 { 7717 printf("DelegatePtrExp::semantic('%s')\n", e.toChars()); 7718 } 7719 if (!e.type) 7720 { 7721 unaSemantic(e, sc); 7722 e.e1 = resolveProperties(sc, e.e1); 7723 7724 if (e.e1.op == TOK.error) 7725 { 7726 result = e.e1; 7727 return; 7728 } 7729 e.type = Type.tvoidptr; 7730 } 7731 result = e; 7732 } 7733 7734 override void visit(DelegateFuncptrExp e) 7735 { 7736 static if (LOGSEMANTIC) 7737 { 7738 printf("DelegateFuncptrExp::semantic('%s')\n", e.toChars()); 7739 } 7740 if (!e.type) 7741 { 7742 unaSemantic(e, sc); 7743 e.e1 = resolveProperties(sc, e.e1); 7744 if (e.e1.op == TOK.error) 7745 { 7746 result = e.e1; 7747 return; 7748 } 7749 e.type = e.e1.type.nextOf().pointerTo(); 7750 } 7751 result = e; 7752 } 7753 7754 override void visit(IndexExp exp) 7755 { 7756 static if (LOGSEMANTIC) 7757 { 7758 printf("IndexExp::semantic('%s')\n", exp.toChars()); 7759 } 7760 if (exp.type) 7761 { 7762 result = exp; 7763 return; 7764 } 7765 7766 // operator overloading should be handled in ArrayExp already. 7767 if (!exp.e1.type) 7768 exp.e1 = exp.e1.expressionSemantic(sc); 7769 assert(exp.e1.type); // semantic() should already be run on it 7770 if (exp.e1.op == TOK.type && exp.e1.type.ty != Ttuple) 7771 { 7772 exp.e2 = exp.e2.expressionSemantic(sc); 7773 exp.e2 = resolveProperties(sc, exp.e2); 7774 Type nt; 7775 if (exp.e2.op == TOK.type) 7776 nt = new TypeAArray(exp.e1.type, exp.e2.type); 7777 else 7778 nt = new TypeSArray(exp.e1.type, exp.e2); 7779 Expression e = new TypeExp(exp.loc, nt); 7780 result = e.expressionSemantic(sc); 7781 return; 7782 } 7783 if (exp.e1.op == TOK.error) 7784 { 7785 result = exp.e1; 7786 return; 7787 } 7788 if (exp.e1.type.ty == Terror) 7789 return setError(); 7790 7791 // Note that unlike C we do not implement the int[ptr] 7792 7793 Type t1b = exp.e1.type.toBasetype(); 7794 7795 if (t1b.ty == Tvector) 7796 { 7797 // Convert e1 to corresponding static array 7798 TypeVector tv1 = cast(TypeVector)t1b; 7799 t1b = tv1.basetype; 7800 t1b = t1b.castMod(tv1.mod); 7801 exp.e1.type = t1b; 7802 } 7803 7804 /* Run semantic on e2 7805 */ 7806 Scope* scx = sc; 7807 if (t1b.ty == Tsarray || t1b.ty == Tarray || t1b.ty == Ttuple) 7808 { 7809 // Create scope for 'length' variable 7810 ScopeDsymbol sym = new ArrayScopeSymbol(sc, exp); 7811 sym.parent = sc.scopesym; 7812 sc = sc.push(sym); 7813 } 7814 if (t1b.ty == Ttuple) 7815 sc = sc.startCTFE(); 7816 exp.e2 = exp.e2.expressionSemantic(sc); 7817 exp.e2 = resolveProperties(sc, exp.e2); 7818 if (t1b.ty == Ttuple) 7819 sc = sc.endCTFE(); 7820 if (exp.e2.op == TOK.tuple) 7821 { 7822 TupleExp te = cast(TupleExp)exp.e2; 7823 if (te.exps && te.exps.dim == 1) 7824 exp.e2 = Expression.combine(te.e0, (*te.exps)[0]); // bug 4444 fix 7825 } 7826 if (sc != scx) 7827 sc = sc.pop(); 7828 if (exp.e2.type == Type.terror) 7829 return setError(); 7830 7831 if (checkNonAssignmentArrayOp(exp.e1)) 7832 return setError(); 7833 7834 switch (t1b.ty) 7835 { 7836 case Tpointer: 7837 if ((cast(TypePointer)t1b).next.ty == Tfunction) 7838 { 7839 exp.error("cannot index function pointer `%s`", exp.e1.toChars()); 7840 return setError(); 7841 } 7842 exp.e2 = exp.e2.implicitCastTo(sc, Type.tsize_t); 7843 if (exp.e2.type == Type.terror) 7844 return setError(); 7845 exp.e2 = exp.e2.optimize(WANTvalue); 7846 if (exp.e2.op == TOK.int64 && exp.e2.toInteger() == 0) 7847 { 7848 } 7849 else if (sc.func && !(sc.flags & SCOPE.debug_) && sc.func.setUnsafe()) 7850 { 7851 exp.error("safe function `%s` cannot index pointer `%s`", sc.func.toPrettyChars(), exp.e1.toChars()); 7852 return setError(); 7853 } 7854 exp.type = (cast(TypeNext)t1b).next; 7855 break; 7856 7857 case Tarray: 7858 exp.e2 = exp.e2.implicitCastTo(sc, Type.tsize_t); 7859 if (exp.e2.type == Type.terror) 7860 return setError(); 7861 exp.type = (cast(TypeNext)t1b).next; 7862 break; 7863 7864 case Tsarray: 7865 { 7866 exp.e2 = exp.e2.implicitCastTo(sc, Type.tsize_t); 7867 if (exp.e2.type == Type.terror) 7868 return setError(); 7869 exp.type = t1b.nextOf(); 7870 break; 7871 } 7872 case Taarray: 7873 { 7874 TypeAArray taa = cast(TypeAArray)t1b; 7875 /* We can skip the implicit conversion if they differ only by 7876 * constness 7877 * https://issues.dlang.org/show_bug.cgi?id=2684 7878 * see also bug https://issues.dlang.org/show_bug.cgi?id=2954 b 7879 */ 7880 if (!arrayTypeCompatibleWithoutCasting(exp.e2.type, taa.index)) 7881 { 7882 exp.e2 = exp.e2.implicitCastTo(sc, taa.index); // type checking 7883 if (exp.e2.type == Type.terror) 7884 return setError(); 7885 } 7886 7887 semanticTypeInfo(sc, taa); 7888 7889 exp.type = taa.next; 7890 break; 7891 } 7892 case Ttuple: 7893 { 7894 exp.e2 = exp.e2.implicitCastTo(sc, Type.tsize_t); 7895 if (exp.e2.type == Type.terror) 7896 return setError(); 7897 7898 exp.e2 = exp.e2.ctfeInterpret(); 7899 uinteger_t index = exp.e2.toUInteger(); 7900 7901 TupleExp te; 7902 TypeTuple tup; 7903 size_t length; 7904 if (exp.e1.op == TOK.tuple) 7905 { 7906 te = cast(TupleExp)exp.e1; 7907 tup = null; 7908 length = te.exps.dim; 7909 } 7910 else if (exp.e1.op == TOK.type) 7911 { 7912 te = null; 7913 tup = cast(TypeTuple)t1b; 7914 length = Parameter.dim(tup.arguments); 7915 } 7916 else 7917 assert(0); 7918 7919 if (length <= index) 7920 { 7921 exp.error("array index `[%llu]` is outside array bounds `[0 .. %llu]`", index, cast(ulong)length); 7922 return setError(); 7923 } 7924 Expression e; 7925 if (exp.e1.op == TOK.tuple) 7926 { 7927 e = (*te.exps)[cast(size_t)index]; 7928 e = Expression.combine(te.e0, e); 7929 } 7930 else 7931 e = new TypeExp(exp.e1.loc, Parameter.getNth(tup.arguments, cast(size_t)index).type); 7932 result = e; 7933 return; 7934 } 7935 default: 7936 exp.error("`%s` must be an array or pointer type, not `%s`", exp.e1.toChars(), exp.e1.type.toChars()); 7937 return setError(); 7938 } 7939 7940 // We might know $ now 7941 setLengthVarIfKnown(exp.lengthVar, t1b); 7942 7943 if (t1b.ty == Tsarray || t1b.ty == Tarray) 7944 { 7945 Expression el = new ArrayLengthExp(exp.loc, exp.e1); 7946 el = el.expressionSemantic(sc); 7947 el = el.optimize(WANTvalue); 7948 if (el.op == TOK.int64) 7949 { 7950 exp.e2 = exp.e2.optimize(WANTvalue); 7951 dinteger_t length = el.toInteger(); 7952 if (length) 7953 { 7954 auto bounds = IntRange(SignExtendedNumber(0), SignExtendedNumber(length - 1)); 7955 exp.indexIsInBounds = bounds.contains(getIntRange(exp.e2)); 7956 } 7957 } 7958 } 7959 7960 result = exp; 7961 } 7962 7963 override void visit(PostExp exp) 7964 { 7965 static if (LOGSEMANTIC) 7966 { 7967 printf("PostExp::semantic('%s')\n", exp.toChars()); 7968 } 7969 if (exp.type) 7970 { 7971 result = exp; 7972 return; 7973 } 7974 7975 if (Expression ex = binSemantic(exp, sc)) 7976 { 7977 result = ex; 7978 return; 7979 } 7980 Expression e1x = resolveProperties(sc, exp.e1); 7981 if (e1x.op == TOK.error) 7982 { 7983 result = e1x; 7984 return; 7985 } 7986 exp.e1 = e1x; 7987 7988 Expression e = exp.op_overload(sc); 7989 if (e) 7990 { 7991 result = e; 7992 return; 7993 } 7994 7995 if (exp.e1.checkReadModifyWrite(exp.op)) 7996 return setError(); 7997 7998 if (exp.e1.op == TOK.slice) 7999 { 8000 const(char)* s = exp.op == TOK.plusPlus ? "increment" : "decrement"; 8001 exp.error("cannot post-%s array slice `%s`, use pre-%s instead", s, exp.e1.toChars(), s); 8002 return setError(); 8003 } 8004 8005 exp.e1 = exp.e1.optimize(WANTvalue); 8006 8007 Type t1 = exp.e1.type.toBasetype(); 8008 if (t1.ty == Tclass || t1.ty == Tstruct || exp.e1.op == TOK.arrayLength) 8009 { 8010 /* Check for operator overloading, 8011 * but rewrite in terms of ++e instead of e++ 8012 */ 8013 8014 /* If e1 is not trivial, take a reference to it 8015 */ 8016 Expression de = null; 8017 if (exp.e1.op != TOK.variable && exp.e1.op != TOK.arrayLength) 8018 { 8019 // ref v = e1; 8020 auto v = copyToTemp(STC.ref_, "__postref", exp.e1); 8021 de = new DeclarationExp(exp.loc, v); 8022 exp.e1 = new VarExp(exp.e1.loc, v); 8023 } 8024 8025 /* Rewrite as: 8026 * auto tmp = e1; ++e1; tmp 8027 */ 8028 auto tmp = copyToTemp(0, "__pitmp", exp.e1); 8029 Expression ea = new DeclarationExp(exp.loc, tmp); 8030 8031 Expression eb = exp.e1.syntaxCopy(); 8032 eb = new PreExp(exp.op == TOK.plusPlus ? TOK.prePlusPlus : TOK.preMinusMinus, exp.loc, eb); 8033 8034 Expression ec = new VarExp(exp.loc, tmp); 8035 8036 // Combine de,ea,eb,ec 8037 if (de) 8038 ea = new CommaExp(exp.loc, de, ea); 8039 e = new CommaExp(exp.loc, ea, eb); 8040 e = new CommaExp(exp.loc, e, ec); 8041 e = e.expressionSemantic(sc); 8042 result = e; 8043 return; 8044 } 8045 8046 exp.e1 = exp.e1.modifiableLvalue(sc, exp.e1); 8047 8048 e = exp; 8049 if (exp.e1.checkScalar() || 8050 exp.e1.checkSharedAccess(sc)) 8051 return setError(); 8052 if (exp.e1.checkNoBool()) 8053 return setError(); 8054 8055 if (exp.e1.type.ty == Tpointer) 8056 e = scaleFactor(exp, sc); 8057 else 8058 exp.e2 = exp.e2.castTo(sc, exp.e1.type); 8059 e.type = exp.e1.type; 8060 result = e; 8061 } 8062 8063 override void visit(PreExp exp) 8064 { 8065 Expression e = exp.op_overload(sc); 8066 // printf("PreExp::semantic('%s')\n", toChars()); 8067 if (e) 8068 { 8069 result = e; 8070 return; 8071 } 8072 8073 // Rewrite as e1+=1 or e1-=1 8074 if (exp.op == TOK.prePlusPlus) 8075 e = new AddAssignExp(exp.loc, exp.e1, new IntegerExp(exp.loc, 1, Type.tint32)); 8076 else 8077 e = new MinAssignExp(exp.loc, exp.e1, new IntegerExp(exp.loc, 1, Type.tint32)); 8078 result = e.expressionSemantic(sc); 8079 } 8080 8081 /* 8082 * Get the expression initializer for a specific struct 8083 * 8084 * Params: 8085 * sd = the struct for which the expression initializer is needed 8086 * loc = the location of the initializer 8087 * sc = the scope where the expression is located 8088 * t = the type of the expression 8089 * 8090 * Returns: 8091 * The expression initializer or error expression if any errors occured 8092 */ 8093 private Expression getInitExp(StructDeclaration sd, Loc loc, Scope* sc, Type t) 8094 { 8095 if (sd.zeroInit && !sd.isNested()) 8096 { 8097 // https://issues.dlang.org/show_bug.cgi?id=14606 8098 // Always use BlitExp for the special expression: (struct = 0) 8099 return new IntegerExp(loc, 0, Type.tint32); 8100 } 8101 8102 if (sd.isNested()) 8103 { 8104 auto sle = new StructLiteralExp(loc, sd, null, t); 8105 if (!sd.fill(loc, sle.elements, true)) 8106 return new ErrorExp(); 8107 if (checkFrameAccess(loc, sc, sd, sle.elements.dim)) 8108 return new ErrorExp(); 8109 8110 sle.type = t; 8111 return sle; 8112 } 8113 8114 return t.defaultInit(loc); 8115 } 8116 8117 override void visit(AssignExp exp) 8118 { 8119 static if (LOGSEMANTIC) 8120 { 8121 printf("AssignExp::semantic('%s')\n", exp.toChars()); 8122 } 8123 //printf("exp.e1.op = %d, '%s'\n", exp.e1.op, Token.toChars(exp.e1.op)); 8124 //printf("exp.e2.op = %d, '%s'\n", exp.e2.op, Token.toChars(exp.e2.op)); 8125 8126 void setResult(Expression e, int line = __LINE__) 8127 { 8128 //printf("line %d\n", line); 8129 result = e; 8130 } 8131 8132 if (exp.type) 8133 { 8134 return setResult(exp); 8135 } 8136 8137 Expression e1old = exp.e1; 8138 8139 if (auto e2comma = exp.e2.isCommaExp()) 8140 { 8141 if (!e2comma.isGenerated) 8142 exp.error("Using the result of a comma expression is not allowed"); 8143 8144 /* Rewrite to get rid of the comma from rvalue 8145 * e1=(e0,e2) => e0,(e1=e2) 8146 */ 8147 Expression e0; 8148 exp.e2 = Expression.extractLast(e2comma, e0); 8149 Expression e = Expression.combine(e0, exp); 8150 return setResult(e.expressionSemantic(sc)); 8151 } 8152 8153 /* Look for operator overloading of a[arguments] = e2. 8154 * Do it before e1.expressionSemantic() otherwise the ArrayExp will have been 8155 * converted to unary operator overloading already. 8156 */ 8157 if (auto ae = exp.e1.isArrayExp()) 8158 { 8159 Expression res; 8160 8161 ae.e1 = ae.e1.expressionSemantic(sc); 8162 ae.e1 = resolveProperties(sc, ae.e1); 8163 Expression ae1old = ae.e1; 8164 8165 const(bool) maybeSlice = 8166 (ae.arguments.dim == 0 || 8167 ae.arguments.dim == 1 && (*ae.arguments)[0].op == TOK.interval); 8168 8169 IntervalExp ie = null; 8170 if (maybeSlice && ae.arguments.dim) 8171 { 8172 assert((*ae.arguments)[0].op == TOK.interval); 8173 ie = cast(IntervalExp)(*ae.arguments)[0]; 8174 } 8175 while (true) 8176 { 8177 if (ae.e1.op == TOK.error) 8178 return setResult(ae.e1); 8179 8180 Expression e0 = null; 8181 Expression ae1save = ae.e1; 8182 ae.lengthVar = null; 8183 8184 Type t1b = ae.e1.type.toBasetype(); 8185 AggregateDeclaration ad = isAggregate(t1b); 8186 if (!ad) 8187 break; 8188 if (search_function(ad, Id.indexass)) 8189 { 8190 // Deal with $ 8191 res = resolveOpDollar(sc, ae, &e0); 8192 if (!res) // a[i..j] = e2 might be: a.opSliceAssign(e2, i, j) 8193 goto Lfallback; 8194 if (res.op == TOK.error) 8195 return setResult(res); 8196 8197 res = exp.e2.expressionSemantic(sc); 8198 if (res.op == TOK.error) 8199 return setResult(res); 8200 exp.e2 = res; 8201 8202 /* Rewrite (a[arguments] = e2) as: 8203 * a.opIndexAssign(e2, arguments) 8204 */ 8205 Expressions* a = ae.arguments.copy(); 8206 a.insert(0, exp.e2); 8207 res = new DotIdExp(exp.loc, ae.e1, Id.indexass); 8208 res = new CallExp(exp.loc, res, a); 8209 if (maybeSlice) // a[] = e2 might be: a.opSliceAssign(e2) 8210 res = res.trySemantic(sc); 8211 else 8212 res = res.expressionSemantic(sc); 8213 if (res) 8214 return setResult(Expression.combine(e0, res)); 8215 } 8216 8217 Lfallback: 8218 if (maybeSlice && search_function(ad, Id.sliceass)) 8219 { 8220 // Deal with $ 8221 res = resolveOpDollar(sc, ae, ie, &e0); 8222 if (res.op == TOK.error) 8223 return setResult(res); 8224 8225 res = exp.e2.expressionSemantic(sc); 8226 if (res.op == TOK.error) 8227 return setResult(res); 8228 8229 exp.e2 = res; 8230 8231 /* Rewrite (a[i..j] = e2) as: 8232 * a.opSliceAssign(e2, i, j) 8233 */ 8234 auto a = new Expressions(); 8235 a.push(exp.e2); 8236 if (ie) 8237 { 8238 a.push(ie.lwr); 8239 a.push(ie.upr); 8240 } 8241 res = new DotIdExp(exp.loc, ae.e1, Id.sliceass); 8242 res = new CallExp(exp.loc, res, a); 8243 res = res.expressionSemantic(sc); 8244 return setResult(Expression.combine(e0, res)); 8245 } 8246 8247 // No operator overloading member function found yet, but 8248 // there might be an alias this to try. 8249 if (ad.aliasthis && t1b != ae.att1) 8250 { 8251 if (!ae.att1 && t1b.checkAliasThisRec()) 8252 ae.att1 = t1b; 8253 8254 /* Rewrite (a[arguments] op e2) as: 8255 * a.aliasthis[arguments] op e2 8256 */ 8257 ae.e1 = resolveAliasThis(sc, ae1save, true); 8258 if (ae.e1) 8259 continue; 8260 } 8261 break; 8262 } 8263 ae.e1 = ae1old; // recovery 8264 ae.lengthVar = null; 8265 } 8266 8267 /* Run this.e1 semantic. 8268 */ 8269 { 8270 Expression e1x = exp.e1; 8271 8272 /* With UFCS, e.f = value 8273 * Could mean: 8274 * .f(e, value) 8275 * or: 8276 * .f(e) = value 8277 */ 8278 if (auto dti = e1x.isDotTemplateInstanceExp()) 8279 { 8280 Expression e = dti.semanticY(sc, 1); 8281 if (!e) 8282 { 8283 return setResult(resolveUFCSProperties(sc, e1x, exp.e2)); 8284 } 8285 8286 e1x = e; 8287 } 8288 else if (auto die = e1x.isDotIdExp()) 8289 { 8290 Expression e = die.semanticY(sc, 1); 8291 if (e && isDotOpDispatch(e)) 8292 { 8293 /* https://issues.dlang.org/show_bug.cgi?id=19687 8294 * 8295 * On this branch, e2 is semantically analyzed in resolvePropertiesX, 8296 * but that call is done with gagged errors. That is the only time when 8297 * semantic gets ran on e2, that is why the error never gets to be printed. 8298 * In order to make sure that UFCS is tried with correct parameters, e2 8299 * needs to have semantic ran on it. 8300 */ 8301 exp.e2 = exp.e2.expressionSemantic(sc); 8302 uint errors = global.startGagging(); 8303 e = resolvePropertiesX(sc, e, exp.e2); 8304 if (global.endGagging(errors)) 8305 e = null; /* fall down to UFCS */ 8306 else 8307 return setResult(e); 8308 } 8309 if (!e) 8310 return setResult(resolveUFCSProperties(sc, e1x, exp.e2)); 8311 e1x = e; 8312 } 8313 else 8314 { 8315 if (auto se = e1x.isSliceExp()) 8316 se.arrayop = true; 8317 8318 e1x = e1x.expressionSemantic(sc); 8319 } 8320 8321 /* We have f = value. 8322 * Could mean: 8323 * f(value) 8324 * or: 8325 * f() = value 8326 */ 8327 if (Expression e = resolvePropertiesX(sc, e1x, exp.e2)) 8328 return setResult(e); 8329 8330 if (e1x.checkRightThis(sc)) 8331 { 8332 return setError(); 8333 } 8334 exp.e1 = e1x; 8335 assert(exp.e1.type); 8336 } 8337 Type t1 = exp.e1.type.toBasetype(); 8338 8339 /* Run this.e2 semantic. 8340 * Different from other binary expressions, the analysis of e2 8341 * depends on the result of e1 in assignments. 8342 */ 8343 { 8344 Expression e2x = inferType(exp.e2, t1.baseElemOf()); 8345 e2x = e2x.expressionSemantic(sc); 8346 e2x = resolveProperties(sc, e2x); 8347 if (e2x.op == TOK.type) 8348 e2x = resolveAliasThis(sc, e2x); //https://issues.dlang.org/show_bug.cgi?id=17684 8349 if (e2x.op == TOK.error) 8350 return setResult(e2x); 8351 if (e2x.checkValue() || e2x.checkSharedAccess(sc)) 8352 return setError(); 8353 exp.e2 = e2x; 8354 } 8355 8356 /* Rewrite tuple assignment as a tuple of assignments. 8357 */ 8358 { 8359 Expression e2x = exp.e2; 8360 8361 Ltupleassign: 8362 if (exp.e1.op == TOK.tuple && e2x.op == TOK.tuple) 8363 { 8364 TupleExp tup1 = cast(TupleExp)exp.e1; 8365 TupleExp tup2 = cast(TupleExp)e2x; 8366 size_t dim = tup1.exps.dim; 8367 Expression e = null; 8368 if (dim != tup2.exps.dim) 8369 { 8370 exp.error("mismatched tuple lengths, %d and %d", cast(int)dim, cast(int)tup2.exps.dim); 8371 return setError(); 8372 } 8373 if (dim == 0) 8374 { 8375 e = new IntegerExp(exp.loc, 0, Type.tint32); 8376 e = new CastExp(exp.loc, e, Type.tvoid); // avoid "has no effect" error 8377 e = Expression.combine(tup1.e0, tup2.e0, e); 8378 } 8379 else 8380 { 8381 auto exps = new Expressions(dim); 8382 for (size_t i = 0; i < dim; i++) 8383 { 8384 Expression ex1 = (*tup1.exps)[i]; 8385 Expression ex2 = (*tup2.exps)[i]; 8386 (*exps)[i] = new AssignExp(exp.loc, ex1, ex2); 8387 } 8388 e = new TupleExp(exp.loc, Expression.combine(tup1.e0, tup2.e0), exps); 8389 } 8390 return setResult(e.expressionSemantic(sc)); 8391 } 8392 8393 /* Look for form: e1 = e2.aliasthis. 8394 */ 8395 if (exp.e1.op == TOK.tuple) 8396 { 8397 TupleDeclaration td = isAliasThisTuple(e2x); 8398 if (!td) 8399 goto Lnomatch; 8400 8401 assert(exp.e1.type.ty == Ttuple); 8402 TypeTuple tt = cast(TypeTuple)exp.e1.type; 8403 8404 Expression e0; 8405 Expression ev = extractSideEffect(sc, "__tup", e0, e2x); 8406 8407 auto iexps = new Expressions(); 8408 iexps.push(ev); 8409 for (size_t u = 0; u < iexps.dim; u++) 8410 { 8411 Lexpand: 8412 Expression e = (*iexps)[u]; 8413 8414 Parameter arg = Parameter.getNth(tt.arguments, u); 8415 //printf("[%d] iexps.dim = %d, ", u, iexps.dim); 8416 //printf("e = (%s %s, %s), ", Token::tochars[e.op], e.toChars(), e.type.toChars()); 8417 //printf("arg = (%s, %s)\n", arg.toChars(), arg.type.toChars()); 8418 8419 if (!arg || !e.type.implicitConvTo(arg.type)) 8420 { 8421 // expand initializer to tuple 8422 if (expandAliasThisTuples(iexps, u) != -1) 8423 { 8424 if (iexps.dim <= u) 8425 break; 8426 goto Lexpand; 8427 } 8428 goto Lnomatch; 8429 } 8430 } 8431 e2x = new TupleExp(e2x.loc, e0, iexps); 8432 e2x = e2x.expressionSemantic(sc); 8433 if (e2x.op == TOK.error) 8434 { 8435 result = e2x; 8436 return; 8437 } 8438 // Do not need to overwrite this.e2 8439 goto Ltupleassign; 8440 } 8441 Lnomatch: 8442 } 8443 8444 exp.e1.checkSharedAccess(sc); 8445 8446 /* Inside constructor, if this is the first assignment of object field, 8447 * rewrite this to initializing the field. 8448 */ 8449 if (exp.op == TOK.assign 8450 && exp.e1.checkModifiable(sc) == Modifiable.initialization) 8451 { 8452 //printf("[%s] change to init - %s\n", exp.loc.toChars(), exp.toChars()); 8453 auto t = exp.type; 8454 exp = new ConstructExp(exp.loc, exp.e1, exp.e2); 8455 exp.type = t; 8456 8457 // @@@DEPRECATED_2020-06@@@ 8458 // When removing, alter `checkModifiable` to return the correct value. 8459 if (sc.func.isStaticCtorDeclaration() && !sc.func.isSharedStaticCtorDeclaration() && 8460 exp.e1.type.isImmutable()) 8461 { 8462 deprecation(exp.loc, "initialization of `immutable` variable from `static this` is deprecated."); 8463 deprecationSupplemental(exp.loc, "Use `shared static this` instead."); 8464 } 8465 8466 // https://issues.dlang.org/show_bug.cgi?id=13515 8467 // set Index::modifiable flag for complex AA element initialization 8468 if (auto ie1 = exp.e1.isIndexExp()) 8469 { 8470 Expression e1x = ie1.markSettingAAElem(); 8471 if (e1x.op == TOK.error) 8472 { 8473 result = e1x; 8474 return; 8475 } 8476 } 8477 } 8478 else if (exp.op == TOK.construct && exp.e1.op == TOK.variable && 8479 (cast(VarExp)exp.e1).var.storage_class & (STC.out_ | STC.ref_)) 8480 { 8481 exp.memset |= MemorySet.referenceInit; 8482 } 8483 8484 /* If it is an assignment from a 'foreign' type, 8485 * check for operator overloading. 8486 */ 8487 if (exp.memset & MemorySet.referenceInit) 8488 { 8489 // If this is an initialization of a reference, 8490 // do nothing 8491 } 8492 else if (t1.ty == Tstruct) 8493 { 8494 auto e1x = exp.e1; 8495 auto e2x = exp.e2; 8496 auto sd = (cast(TypeStruct)t1).sym; 8497 8498 if (exp.op == TOK.construct) 8499 { 8500 Type t2 = e2x.type.toBasetype(); 8501 if (t2.ty == Tstruct && sd == (cast(TypeStruct)t2).sym) 8502 { 8503 sd.size(exp.loc); 8504 if (sd.sizeok != Sizeok.done) 8505 return setError(); 8506 if (!sd.ctor) 8507 sd.ctor = sd.searchCtor(); 8508 8509 // https://issues.dlang.org/show_bug.cgi?id=15661 8510 // Look for the form from last of comma chain. 8511 auto e2y = lastComma(e2x); 8512 8513 CallExp ce = (e2y.op == TOK.call) ? cast(CallExp)e2y : null; 8514 DotVarExp dve = (ce && ce.e1.op == TOK.dotVariable) 8515 ? cast(DotVarExp)ce.e1 : null; 8516 if (sd.ctor && ce && dve && dve.var.isCtorDeclaration() && 8517 // https://issues.dlang.org/show_bug.cgi?id=19389 8518 dve.e1.op != TOK.dotVariable && 8519 e2y.type.implicitConvTo(t1)) 8520 { 8521 /* Look for form of constructor call which is: 8522 * __ctmp.ctor(arguments...) 8523 */ 8524 8525 /* Before calling the constructor, initialize 8526 * variable with a bit copy of the default 8527 * initializer 8528 */ 8529 Expression einit = getInitExp(sd, exp.loc, sc, t1); 8530 if (einit.op == TOK.error) 8531 { 8532 result = einit; 8533 return; 8534 } 8535 8536 auto ae = new BlitExp(exp.loc, exp.e1, einit); 8537 ae.type = e1x.type; 8538 8539 /* Replace __ctmp being constructed with e1. 8540 * We need to copy constructor call expression, 8541 * because it may be used in other place. 8542 */ 8543 auto dvx = cast(DotVarExp)dve.copy(); 8544 dvx.e1 = e1x; 8545 auto cx = cast(CallExp)ce.copy(); 8546 cx.e1 = dvx; 8547 if (checkConstructorEscape(sc, cx, false)) 8548 return setError(); 8549 8550 Expression e0; 8551 Expression.extractLast(e2x, e0); 8552 8553 auto e = Expression.combine(e0, ae, cx); 8554 e = e.expressionSemantic(sc); 8555 result = e; 8556 return; 8557 } 8558 if (sd.postblit || sd.hasCopyCtor) 8559 { 8560 /* We have a copy constructor for this 8561 */ 8562 if (e2x.op == TOK.question) 8563 { 8564 /* Rewrite as: 8565 * a ? e1 = b : e1 = c; 8566 */ 8567 CondExp econd = cast(CondExp)e2x; 8568 Expression ea1 = new ConstructExp(econd.e1.loc, e1x, econd.e1); 8569 Expression ea2 = new ConstructExp(econd.e1.loc, e1x, econd.e2); 8570 Expression e = new CondExp(exp.loc, econd.econd, ea1, ea2); 8571 result = e.expressionSemantic(sc); 8572 return; 8573 } 8574 8575 if (e2x.isLvalue()) 8576 { 8577 if (sd.hasCopyCtor) 8578 { 8579 /* Rewrite as: 8580 * e1 = init, e1.copyCtor(e2); 8581 */ 8582 Expression einit = new BlitExp(exp.loc, exp.e1, getInitExp(sd, exp.loc, sc, t1)); 8583 einit.type = e1x.type; 8584 8585 Expression e; 8586 e = new DotIdExp(exp.loc, e1x, Id.ctor); 8587 e = new CallExp(exp.loc, e, e2x); 8588 e = new CommaExp(exp.loc, einit, e); 8589 8590 //printf("e: %s\n", e.toChars()); 8591 8592 result = e.expressionSemantic(sc); 8593 return; 8594 } 8595 else 8596 { 8597 if (!e2x.type.implicitConvTo(e1x.type)) 8598 { 8599 exp.error("conversion error from `%s` to `%s`", 8600 e2x.type.toChars(), e1x.type.toChars()); 8601 return setError(); 8602 } 8603 8604 /* Rewrite as: 8605 * (e1 = e2).postblit(); 8606 * 8607 * Blit assignment e1 = e2 returns a reference to the original e1, 8608 * then call the postblit on it. 8609 */ 8610 Expression e = e1x.copy(); 8611 e.type = e.type.mutableOf(); 8612 if (e.type.isShared && !sd.type.isShared) 8613 e.type = e.type.unSharedOf(); 8614 e = new BlitExp(exp.loc, e, e2x); 8615 e = new DotVarExp(exp.loc, e, sd.postblit, false); 8616 e = new CallExp(exp.loc, e); 8617 result = e.expressionSemantic(sc); 8618 return; 8619 } 8620 } 8621 else 8622 { 8623 /* The struct value returned from the function is transferred 8624 * so should not call the destructor on it. 8625 */ 8626 e2x = valueNoDtor(e2x); 8627 } 8628 } 8629 8630 // https://issues.dlang.org/show_bug.cgi?id=19251 8631 // if e2 cannot be converted to e1.type, maybe there is an alias this 8632 if (!e2x.implicitConvTo(t1)) 8633 { 8634 AggregateDeclaration ad2 = isAggregate(e2x.type); 8635 if (ad2 && ad2.aliasthis && !(exp.att2 && e2x.type == exp.att2)) 8636 { 8637 if (!exp.att2 && exp.e2.type.checkAliasThisRec()) 8638 exp.att2 = exp.e2.type; 8639 /* Rewrite (e1 op e2) as: 8640 * (e1 op e2.aliasthis) 8641 */ 8642 exp.e2 = new DotIdExp(exp.e2.loc, exp.e2, ad2.aliasthis.ident); 8643 result = exp.expressionSemantic(sc); 8644 return; 8645 } 8646 } 8647 } 8648 else if (!e2x.implicitConvTo(t1)) 8649 { 8650 sd.size(exp.loc); 8651 if (sd.sizeok != Sizeok.done) 8652 return setError(); 8653 if (!sd.ctor) 8654 sd.ctor = sd.searchCtor(); 8655 8656 if (sd.ctor) 8657 { 8658 /* Look for implicit constructor call 8659 * Rewrite as: 8660 * e1 = init, e1.ctor(e2) 8661 */ 8662 8663 /* Fix Issue 5153 : https://issues.dlang.org/show_bug.cgi?id=5153 8664 * Using `new` to initialize a struct object is a common mistake, but 8665 * the error message from the compiler is not very helpful in that 8666 * case. If exp.e2 is a NewExp and the type of new is the same as 8667 * the type as exp.e1 (struct in this case), then we know for sure 8668 * that the user wants to instantiate a struct. This is done to avoid 8669 * issuing an error when the user actually wants to call a constructor 8670 * which receives a class object. 8671 * 8672 * Foo f = new Foo2(0); is a valid expression if Foo has a constructor 8673 * which receives an instance of a Foo2 class 8674 */ 8675 if (exp.e2.op == TOK.new_) 8676 { 8677 auto newExp = cast(NewExp)(exp.e2); 8678 if (newExp.newtype && newExp.newtype == t1) 8679 { 8680 error(exp.loc, "cannot implicitly convert expression `%s` of type `%s` to `%s`", 8681 newExp.toChars(), newExp.type.toChars(), t1.toChars()); 8682 errorSupplemental(exp.loc, "Perhaps remove the `new` keyword?"); 8683 return setError(); 8684 } 8685 } 8686 8687 Expression einit = new BlitExp(exp.loc, e1x, getInitExp(sd, exp.loc, sc, t1)); 8688 einit.type = e1x.type; 8689 8690 Expression e; 8691 e = new DotIdExp(exp.loc, e1x, Id.ctor); 8692 e = new CallExp(exp.loc, e, e2x); 8693 e = new CommaExp(exp.loc, einit, e); 8694 e = e.expressionSemantic(sc); 8695 result = e; 8696 return; 8697 } 8698 if (search_function(sd, Id.call)) 8699 { 8700 /* Look for static opCall 8701 * https://issues.dlang.org/show_bug.cgi?id=2702 8702 * Rewrite as: 8703 * e1 = typeof(e1).opCall(arguments) 8704 */ 8705 e2x = typeDotIdExp(e2x.loc, e1x.type, Id.call); 8706 e2x = new CallExp(exp.loc, e2x, exp.e2); 8707 8708 e2x = e2x.expressionSemantic(sc); 8709 e2x = resolveProperties(sc, e2x); 8710 if (e2x.op == TOK.error) 8711 { 8712 result = e2x; 8713 return; 8714 } 8715 if (e2x.checkValue() || e2x.checkSharedAccess(sc)) 8716 return setError(); 8717 } 8718 } 8719 else // https://issues.dlang.org/show_bug.cgi?id=11355 8720 { 8721 AggregateDeclaration ad2 = isAggregate(e2x.type); 8722 if (ad2 && ad2.aliasthis && !(exp.att2 && e2x.type == exp.att2)) 8723 { 8724 if (!exp.att2 && exp.e2.type.checkAliasThisRec()) 8725 exp.att2 = exp.e2.type; 8726 /* Rewrite (e1 op e2) as: 8727 * (e1 op e2.aliasthis) 8728 */ 8729 exp.e2 = new DotIdExp(exp.e2.loc, exp.e2, ad2.aliasthis.ident); 8730 result = exp.expressionSemantic(sc); 8731 return; 8732 } 8733 } 8734 } 8735 else if (exp.op == TOK.assign) 8736 { 8737 if (e1x.op == TOK.index && (cast(IndexExp)e1x).e1.type.toBasetype().ty == Taarray) 8738 { 8739 /* 8740 * Rewrite: 8741 * aa[key] = e2; 8742 * as: 8743 * ref __aatmp = aa; 8744 * ref __aakey = key; 8745 * ref __aaval = e2; 8746 * (__aakey in __aatmp 8747 * ? __aatmp[__aakey].opAssign(__aaval) 8748 * : ConstructExp(__aatmp[__aakey], __aaval)); 8749 */ 8750 // ensure we keep the expr modifiable 8751 Expression esetting = (cast(IndexExp)e1x).markSettingAAElem(); 8752 if (esetting.op == TOK.error) 8753 { 8754 result = esetting; 8755 return; 8756 } 8757 assert(esetting.op == TOK.index); 8758 IndexExp ie = cast(IndexExp) esetting; 8759 Type t2 = e2x.type.toBasetype(); 8760 8761 Expression e0 = null; 8762 Expression ea = extractSideEffect(sc, "__aatmp", e0, ie.e1); 8763 Expression ek = extractSideEffect(sc, "__aakey", e0, ie.e2); 8764 Expression ev = extractSideEffect(sc, "__aaval", e0, e2x); 8765 8766 AssignExp ae = cast(AssignExp)exp.copy(); 8767 ae.e1 = new IndexExp(exp.loc, ea, ek); 8768 ae.e1 = ae.e1.expressionSemantic(sc); 8769 ae.e1 = ae.e1.optimize(WANTvalue); 8770 ae.e2 = ev; 8771 Expression e = ae.op_overload(sc); 8772 if (e) 8773 { 8774 Expression ey = null; 8775 if (t2.ty == Tstruct && sd == t2.toDsymbol(sc)) 8776 { 8777 ey = ev; 8778 } 8779 else if (!ev.implicitConvTo(ie.type) && sd.ctor) 8780 { 8781 // Look for implicit constructor call 8782 // Rewrite as S().ctor(e2) 8783 ey = new StructLiteralExp(exp.loc, sd, null); 8784 ey = new DotIdExp(exp.loc, ey, Id.ctor); 8785 ey = new CallExp(exp.loc, ey, ev); 8786 ey = ey.trySemantic(sc); 8787 } 8788 if (ey) 8789 { 8790 Expression ex; 8791 ex = new IndexExp(exp.loc, ea, ek); 8792 ex = ex.expressionSemantic(sc); 8793 ex = ex.optimize(WANTvalue); 8794 ex = ex.modifiableLvalue(sc, ex); // allocate new slot 8795 8796 ey = new ConstructExp(exp.loc, ex, ey); 8797 ey = ey.expressionSemantic(sc); 8798 if (ey.op == TOK.error) 8799 { 8800 result = ey; 8801 return; 8802 } 8803 ex = e; 8804 8805 // https://issues.dlang.org/show_bug.cgi?id=14144 8806 // The whole expression should have the common type 8807 // of opAssign() return and assigned AA entry. 8808 // Even if there's no common type, expression should be typed as void. 8809 Type t = null; 8810 if (!typeMerge(sc, TOK.question, &t, &ex, &ey)) 8811 { 8812 ex = new CastExp(ex.loc, ex, Type.tvoid); 8813 ey = new CastExp(ey.loc, ey, Type.tvoid); 8814 } 8815 e = new CondExp(exp.loc, new InExp(exp.loc, ek, ea), ex, ey); 8816 } 8817 e = Expression.combine(e0, e); 8818 e = e.expressionSemantic(sc); 8819 result = e; 8820 return; 8821 } 8822 } 8823 else 8824 { 8825 Expression e = exp.op_overload(sc); 8826 if (e) 8827 { 8828 result = e; 8829 return; 8830 } 8831 } 8832 } 8833 else 8834 assert(exp.op == TOK.blit); 8835 8836 exp.e1 = e1x; 8837 exp.e2 = e2x; 8838 } 8839 else if (t1.ty == Tclass) 8840 { 8841 // Disallow assignment operator overloads for same type 8842 if (exp.op == TOK.assign && !exp.e2.implicitConvTo(exp.e1.type)) 8843 { 8844 Expression e = exp.op_overload(sc); 8845 if (e) 8846 { 8847 result = e; 8848 return; 8849 } 8850 } 8851 } 8852 else if (t1.ty == Tsarray) 8853 { 8854 // SliceExp cannot have static array type without context inference. 8855 assert(exp.e1.op != TOK.slice); 8856 Expression e1x = exp.e1; 8857 Expression e2x = exp.e2; 8858 8859 if (e2x.implicitConvTo(e1x.type)) 8860 { 8861 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())) 8862 { 8863 if (e1x.checkPostblit(sc, t1)) 8864 return setError(); 8865 } 8866 8867 // e2 matches to t1 because of the implicit length match, so 8868 if (isUnaArrayOp(e2x.op) || isBinArrayOp(e2x.op)) 8869 { 8870 // convert e1 to e1[] 8871 // e.g. e1[] = a[] + b[]; 8872 auto sle = new SliceExp(e1x.loc, e1x, null, null); 8873 sle.arrayop = true; 8874 e1x = sle.expressionSemantic(sc); 8875 } 8876 else 8877 { 8878 // convert e2 to t1 later 8879 // e.g. e1 = [1, 2, 3]; 8880 } 8881 } 8882 else 8883 { 8884 if (e2x.implicitConvTo(t1.nextOf().arrayOf()) > MATCH.nomatch) 8885 { 8886 uinteger_t dim1 = (cast(TypeSArray)t1).dim.toInteger(); 8887 uinteger_t dim2 = dim1; 8888 if (auto ale = e2x.isArrayLiteralExp()) 8889 { 8890 dim2 = ale.elements ? ale.elements.dim : 0; 8891 } 8892 else if (auto se = e2x.isSliceExp()) 8893 { 8894 Type tx = toStaticArrayType(se); 8895 if (tx) 8896 dim2 = (cast(TypeSArray)tx).dim.toInteger(); 8897 } 8898 if (dim1 != dim2) 8899 { 8900 exp.error("mismatched array lengths, %d and %d", cast(int)dim1, cast(int)dim2); 8901 return setError(); 8902 } 8903 } 8904 8905 // May be block or element-wise assignment, so 8906 // convert e1 to e1[] 8907 if (exp.op != TOK.assign) 8908 { 8909 // If multidimensional static array, treat as one large array 8910 // 8911 // Find the appropriate array type depending on the assignment, e.g. 8912 // int[3] = int => int[3] 8913 // int[3][2] = int => int[6] 8914 // int[3][2] = int[] => int[3][2] 8915 // int[3][2][4] + int => int[24] 8916 // int[3][2][4] + int[] => int[3][8] 8917 ulong dim = t1.isTypeSArray().dim.toUInteger(); 8918 auto type = t1.nextOf(); 8919 8920 for (TypeSArray tsa; (tsa = type.isTypeSArray()) !is null; ) 8921 { 8922 import core.checkedint : mulu; 8923 8924 // Accumulate skipped dimensions 8925 bool overflow = false; 8926 dim = mulu(dim, tsa.dim.toUInteger(), overflow); 8927 if (overflow || dim >= uint.max) 8928 { 8929 // dym exceeds maximum array size 8930 exp.error("static array `%s` size overflowed to %llu", 8931 e1x.type.toChars(), cast(ulong) dim); 8932 return setError(); 8933 } 8934 8935 // Move to the element type 8936 type = tsa.nextOf().toBasetype(); 8937 8938 // Rewrite ex1 as a static array if a matching type was found 8939 if (e2x.implicitConvTo(type) > MATCH.nomatch) 8940 { 8941 e1x.type = type.sarrayOf(dim); 8942 break; 8943 } 8944 } 8945 } 8946 auto sle = new SliceExp(e1x.loc, e1x, null, null); 8947 sle.arrayop = true; 8948 e1x = sle.expressionSemantic(sc); 8949 } 8950 if (e1x.op == TOK.error) 8951 return setResult(e1x); 8952 if (e2x.op == TOK.error) 8953 return setResult(e2x); 8954 8955 exp.e1 = e1x; 8956 exp.e2 = e2x; 8957 t1 = e1x.type.toBasetype(); 8958 } 8959 /* Check the mutability of e1. 8960 */ 8961 if (auto ale = exp.e1.isArrayLengthExp()) 8962 { 8963 // e1 is not an lvalue, but we let code generator handle it 8964 8965 auto ale1x = ale.e1.modifiableLvalue(sc, exp.e1); 8966 if (ale1x.op == TOK.error) 8967 return setResult(ale1x); 8968 ale.e1 = ale1x; 8969 8970 Type tn = ale.e1.type.toBasetype().nextOf(); 8971 checkDefCtor(ale.loc, tn); 8972 8973 Identifier hook = global.params.tracegc ? Id._d_arraysetlengthTTrace : Id._d_arraysetlengthT; 8974 if (!verifyHookExist(exp.loc, *sc, Id._d_arraysetlengthTImpl, "resizing arrays")) 8975 return setError(); 8976 8977 // Lower to object._d_arraysetlengthTImpl!(typeof(e1))._d_arraysetlengthT{,Trace}(e1, e2) 8978 Expression id = new IdentifierExp(ale.loc, Id.empty); 8979 id = new DotIdExp(ale.loc, id, Id.object); 8980 auto tiargs = new Objects(); 8981 tiargs.push(ale.e1.type); 8982 id = new DotTemplateInstanceExp(ale.loc, id, Id._d_arraysetlengthTImpl, tiargs); 8983 id = new DotIdExp(ale.loc, id, hook); 8984 id = id.expressionSemantic(sc); 8985 8986 auto arguments = new Expressions(); 8987 arguments.reserve(5); 8988 if (global.params.tracegc) 8989 { 8990 auto funcname = (sc.callsc && sc.callsc.func) ? sc.callsc.func.toPrettyChars() : sc.func.toPrettyChars(); 8991 arguments.push(new StringExp(exp.loc, exp.loc.filename.toDString())); 8992 arguments.push(new IntegerExp(exp.loc, exp.loc.linnum, Type.tint32)); 8993 arguments.push(new StringExp(exp.loc, funcname.toDString())); 8994 } 8995 arguments.push(ale.e1); 8996 arguments.push(exp.e2); 8997 8998 Expression ce = new CallExp(ale.loc, id, arguments); 8999 auto res = ce.expressionSemantic(sc); 9000 // if (global.params.verbose) 9001 // message("lowered %s =>\n %s", exp.toChars(), res.toChars()); 9002 return setResult(res); 9003 } 9004 else if (auto se = exp.e1.isSliceExp()) 9005 { 9006 Type tn = se.type.nextOf(); 9007 const fun = sc.func; 9008 if (exp.op == TOK.assign && !tn.isMutable() && 9009 // allow modifiation in module ctor, see 9010 // https://issues.dlang.org/show_bug.cgi?id=9884 9011 (!fun || (fun && !fun.isStaticCtorDeclaration()))) 9012 { 9013 exp.error("slice `%s` is not mutable", se.toChars()); 9014 return setError(); 9015 } 9016 9017 if (exp.op == TOK.assign && !tn.baseElemOf().isAssignable()) 9018 { 9019 exp.error("slice `%s` is not mutable, struct `%s` has immutable members", 9020 exp.e1.toChars(), tn.baseElemOf().toChars()); 9021 result = new ErrorExp(); 9022 return; 9023 } 9024 9025 // For conditional operator, both branches need conversion. 9026 while (se.e1.op == TOK.slice) 9027 se = cast(SliceExp)se.e1; 9028 if (se.e1.op == TOK.question && se.e1.type.toBasetype().ty == Tsarray) 9029 { 9030 se.e1 = se.e1.modifiableLvalue(sc, exp.e1); 9031 if (se.e1.op == TOK.error) 9032 return setResult(se.e1); 9033 } 9034 } 9035 else 9036 { 9037 if (t1.ty == Tsarray && exp.op == TOK.assign) 9038 { 9039 Type tn = exp.e1.type.nextOf(); 9040 if (tn && !tn.baseElemOf().isAssignable()) 9041 { 9042 exp.error("array `%s` is not mutable, struct `%s` has immutable members", 9043 exp.e1.toChars(), tn.baseElemOf().toChars()); 9044 result = new ErrorExp(); 9045 return; 9046 } 9047 } 9048 9049 Expression e1x = exp.e1; 9050 9051 // Try to do a decent error message with the expression 9052 // before it got constant folded 9053 9054 if (e1x.op != TOK.variable) 9055 e1x = e1x.optimize(WANTvalue); 9056 9057 if (exp.op == TOK.assign) 9058 e1x = e1x.modifiableLvalue(sc, e1old); 9059 9060 if (checkIfIsStructLiteralDotExpr(e1x)) 9061 return setError(); 9062 9063 if (e1x.op == TOK.error) 9064 { 9065 result = e1x; 9066 return; 9067 } 9068 exp.e1 = e1x; 9069 } 9070 9071 /* Tweak e2 based on the type of e1. 9072 */ 9073 Expression e2x = exp.e2; 9074 Type t2 = e2x.type.toBasetype(); 9075 9076 // If it is a array, get the element type. Note that it may be 9077 // multi-dimensional. 9078 Type telem = t1; 9079 while (telem.ty == Tarray) 9080 telem = telem.nextOf(); 9081 9082 if (exp.e1.op == TOK.slice && t1.nextOf() && 9083 (telem.ty != Tvoid || e2x.op == TOK.null_) && 9084 e2x.implicitConvTo(t1.nextOf())) 9085 { 9086 // Check for block assignment. If it is of type void[], void[][], etc, 9087 // '= null' is the only allowable block assignment (Bug 7493) 9088 exp.memset |= MemorySet.blockAssign; // make it easy for back end to tell what this is 9089 e2x = e2x.implicitCastTo(sc, t1.nextOf()); 9090 if (exp.op != TOK.blit && e2x.isLvalue() && exp.e1.checkPostblit(sc, t1.nextOf())) 9091 return setError(); 9092 } 9093 else if (exp.e1.op == TOK.slice && 9094 (t2.ty == Tarray || t2.ty == Tsarray) && 9095 t2.nextOf().implicitConvTo(t1.nextOf())) 9096 { 9097 // Check element-wise assignment. 9098 9099 /* If assigned elements number is known at compile time, 9100 * check the mismatch. 9101 */ 9102 SliceExp se1 = cast(SliceExp)exp.e1; 9103 TypeSArray tsa1 = cast(TypeSArray)toStaticArrayType(se1); 9104 TypeSArray tsa2 = null; 9105 if (auto ale = e2x.isArrayLiteralExp()) 9106 tsa2 = cast(TypeSArray)t2.nextOf().sarrayOf(ale.elements.dim); 9107 else if (auto se = e2x.isSliceExp()) 9108 tsa2 = cast(TypeSArray)toStaticArrayType(se); 9109 else 9110 tsa2 = t2.isTypeSArray(); 9111 if (tsa1 && tsa2) 9112 { 9113 uinteger_t dim1 = tsa1.dim.toInteger(); 9114 uinteger_t dim2 = tsa2.dim.toInteger(); 9115 if (dim1 != dim2) 9116 { 9117 exp.error("mismatched array lengths, %d and %d", cast(int)dim1, cast(int)dim2); 9118 return setError(); 9119 } 9120 } 9121 9122 if (exp.op != TOK.blit && 9123 (e2x.op == TOK.slice && (cast(UnaExp)e2x).e1.isLvalue() || 9124 e2x.op == TOK.cast_ && (cast(UnaExp)e2x).e1.isLvalue() || 9125 e2x.op != TOK.slice && e2x.isLvalue())) 9126 { 9127 if (exp.e1.checkPostblit(sc, t1.nextOf())) 9128 return setError(); 9129 } 9130 9131 if (0 && global.params.warnings != DiagnosticReporting.off && !global.gag && exp.op == TOK.assign && 9132 e2x.op != TOK.slice && e2x.op != TOK.assign && 9133 e2x.op != TOK.arrayLiteral && e2x.op != TOK.string_ && 9134 !(e2x.op == TOK.add || e2x.op == TOK.min || 9135 e2x.op == TOK.mul || e2x.op == TOK.div || 9136 e2x.op == TOK.mod || e2x.op == TOK.xor || 9137 e2x.op == TOK.and || e2x.op == TOK.or || 9138 e2x.op == TOK.pow || 9139 e2x.op == TOK.tilde || e2x.op == TOK.negate)) 9140 { 9141 const(char)* e1str = exp.e1.toChars(); 9142 const(char)* e2str = e2x.toChars(); 9143 exp.warning("explicit element-wise assignment `%s = (%s)[]` is better than `%s = %s`", e1str, e2str, e1str, e2str); 9144 } 9145 9146 Type t2n = t2.nextOf(); 9147 Type t1n = t1.nextOf(); 9148 int offset; 9149 if (t2n.equivalent(t1n) || 9150 t1n.isBaseOf(t2n, &offset) && offset == 0) 9151 { 9152 /* Allow copy of distinct qualifier elements. 9153 * eg. 9154 * char[] dst; const(char)[] src; 9155 * dst[] = src; 9156 * 9157 * class C {} class D : C {} 9158 * C[2] ca; D[] da; 9159 * ca[] = da; 9160 */ 9161 if (isArrayOpValid(e2x)) 9162 { 9163 // Don't add CastExp to keep AST for array operations 9164 e2x = e2x.copy(); 9165 e2x.type = exp.e1.type.constOf(); 9166 } 9167 else 9168 e2x = e2x.castTo(sc, exp.e1.type.constOf()); 9169 } 9170 else 9171 { 9172 /* https://issues.dlang.org/show_bug.cgi?id=15778 9173 * A string literal has an array type of immutable 9174 * elements by default, and normally it cannot be convertible to 9175 * array type of mutable elements. But for element-wise assignment, 9176 * elements need to be const at best. So we should give a chance 9177 * to change code unit size for polysemous string literal. 9178 */ 9179 if (e2x.op == TOK.string_) 9180 e2x = e2x.implicitCastTo(sc, exp.e1.type.constOf()); 9181 else 9182 e2x = e2x.implicitCastTo(sc, exp.e1.type); 9183 } 9184 if (t1n.toBasetype.ty == Tvoid && t2n.toBasetype.ty == Tvoid) 9185 { 9186 if (!sc.intypeof && sc.func && !(sc.flags & SCOPE.debug_) && sc.func.setUnsafe()) 9187 { 9188 exp.error("cannot copy `void[]` to `void[]` in `@safe` code"); 9189 return setError(); 9190 } 9191 } 9192 } 9193 else 9194 { 9195 if (0 && global.params.warnings != DiagnosticReporting.off && !global.gag && exp.op == TOK.assign && 9196 t1.ty == Tarray && t2.ty == Tsarray && 9197 e2x.op != TOK.slice && 9198 t2.implicitConvTo(t1)) 9199 { 9200 // Disallow ar[] = sa (Converted to ar[] = sa[]) 9201 // Disallow da = sa (Converted to da = sa[]) 9202 const(char)* e1str = exp.e1.toChars(); 9203 const(char)* e2str = e2x.toChars(); 9204 const(char)* atypestr = exp.e1.op == TOK.slice ? "element-wise" : "slice"; 9205 exp.warning("explicit %s assignment `%s = (%s)[]` is better than `%s = %s`", atypestr, e1str, e2str, e1str, e2str); 9206 } 9207 if (exp.op == TOK.blit) 9208 e2x = e2x.castTo(sc, exp.e1.type); 9209 else 9210 { 9211 e2x = e2x.implicitCastTo(sc, exp.e1.type); 9212 9213 // Fix Issue 13435: https://issues.dlang.org/show_bug.cgi?id=13435 9214 9215 // If the implicit cast has failed and the assign expression is 9216 // the initialization of a struct member field 9217 if (e2x.op == TOK.error && exp.op == TOK.construct && t1.ty == Tstruct) 9218 { 9219 scope sd = (cast(TypeStruct)t1).sym; 9220 Dsymbol opAssign = search_function(sd, Id.assign); 9221 9222 // and the struct defines an opAssign 9223 if (opAssign) 9224 { 9225 // offer more information about the cause of the problem 9226 errorSupplemental(exp.loc, 9227 "`%s` is the first assignment of `%s` therefore it represents its initialization", 9228 exp.toChars(), exp.e1.toChars()); 9229 errorSupplemental(exp.loc, 9230 "`opAssign` methods are not used for initialization, but for subsequent assignments"); 9231 } 9232 } 9233 } 9234 } 9235 if (e2x.op == TOK.error) 9236 { 9237 result = e2x; 9238 return; 9239 } 9240 exp.e2 = e2x; 9241 t2 = exp.e2.type.toBasetype(); 9242 9243 /* Look for array operations 9244 */ 9245 if ((t2.ty == Tarray || t2.ty == Tsarray) && isArrayOpValid(exp.e2)) 9246 { 9247 // Look for valid array operations 9248 if (!(exp.memset & MemorySet.blockAssign) && 9249 exp.e1.op == TOK.slice && 9250 (isUnaArrayOp(exp.e2.op) || isBinArrayOp(exp.e2.op))) 9251 { 9252 exp.type = exp.e1.type; 9253 if (exp.op == TOK.construct) // https://issues.dlang.org/show_bug.cgi?id=10282 9254 // tweak mutability of e1 element 9255 exp.e1.type = exp.e1.type.nextOf().mutableOf().arrayOf(); 9256 result = arrayOp(exp, sc); 9257 return; 9258 } 9259 9260 // Drop invalid array operations in e2 9261 // d = a[] + b[], d = (a[] + b[])[0..2], etc 9262 if (checkNonAssignmentArrayOp(exp.e2, !(exp.memset & MemorySet.blockAssign) && exp.op == TOK.assign)) 9263 return setError(); 9264 9265 // Remains valid array assignments 9266 // d = d[], d = [1,2,3], etc 9267 } 9268 9269 /* Don't allow assignment to classes that were allocated on the stack with: 9270 * scope Class c = new Class(); 9271 */ 9272 if (exp.e1.op == TOK.variable && exp.op == TOK.assign) 9273 { 9274 VarExp ve = cast(VarExp)exp.e1; 9275 VarDeclaration vd = ve.var.isVarDeclaration(); 9276 if (vd && (vd.onstack || vd.mynew)) 9277 { 9278 assert(t1.ty == Tclass); 9279 exp.error("cannot rebind scope variables"); 9280 } 9281 } 9282 9283 if (exp.e1.op == TOK.variable && (cast(VarExp)exp.e1).var.ident == Id.ctfe) 9284 { 9285 exp.error("cannot modify compiler-generated variable `__ctfe`"); 9286 } 9287 9288 exp.type = exp.e1.type; 9289 assert(exp.type); 9290 auto res = exp.op == TOK.assign ? exp.reorderSettingAAElem(sc) : exp; 9291 checkAssignEscape(sc, res, false); 9292 return setResult(res); 9293 } 9294 9295 override void visit(PowAssignExp exp) 9296 { 9297 if (exp.type) 9298 { 9299 result = exp; 9300 return; 9301 } 9302 9303 Expression e = exp.op_overload(sc); 9304 if (e) 9305 { 9306 result = e; 9307 return; 9308 } 9309 9310 if (exp.e1.checkReadModifyWrite(exp.op, exp.e2)) 9311 return setError(); 9312 9313 assert(exp.e1.type && exp.e2.type); 9314 if (exp.e1.op == TOK.slice || exp.e1.type.ty == Tarray || exp.e1.type.ty == Tsarray) 9315 { 9316 if (checkNonAssignmentArrayOp(exp.e1)) 9317 return setError(); 9318 9319 // T[] ^^= ... 9320 if (exp.e2.implicitConvTo(exp.e1.type.nextOf())) 9321 { 9322 // T[] ^^= T 9323 exp.e2 = exp.e2.castTo(sc, exp.e1.type.nextOf()); 9324 } 9325 else if (Expression ex = typeCombine(exp, sc)) 9326 { 9327 result = ex; 9328 return; 9329 } 9330 9331 // Check element types are arithmetic 9332 Type tb1 = exp.e1.type.nextOf().toBasetype(); 9333 Type tb2 = exp.e2.type.toBasetype(); 9334 if (tb2.ty == Tarray || tb2.ty == Tsarray) 9335 tb2 = tb2.nextOf().toBasetype(); 9336 if ((tb1.isintegral() || tb1.isfloating()) && (tb2.isintegral() || tb2.isfloating())) 9337 { 9338 exp.type = exp.e1.type; 9339 result = arrayOp(exp, sc); 9340 return; 9341 } 9342 } 9343 else 9344 { 9345 exp.e1 = exp.e1.modifiableLvalue(sc, exp.e1); 9346 } 9347 9348 if ((exp.e1.type.isintegral() || exp.e1.type.isfloating()) && (exp.e2.type.isintegral() || exp.e2.type.isfloating())) 9349 { 9350 Expression e0 = null; 9351 e = exp.reorderSettingAAElem(sc); 9352 e = Expression.extractLast(e, e0); 9353 assert(e == exp); 9354 9355 if (exp.e1.op == TOK.variable) 9356 { 9357 // Rewrite: e1 = e1 ^^ e2 9358 e = new PowExp(exp.loc, exp.e1.syntaxCopy(), exp.e2); 9359 e = new AssignExp(exp.loc, exp.e1, e); 9360 } 9361 else 9362 { 9363 // Rewrite: ref tmp = e1; tmp = tmp ^^ e2 9364 auto v = copyToTemp(STC.ref_, "__powtmp", exp.e1); 9365 auto de = new DeclarationExp(exp.e1.loc, v); 9366 auto ve = new VarExp(exp.e1.loc, v); 9367 e = new PowExp(exp.loc, ve, exp.e2); 9368 e = new AssignExp(exp.loc, new VarExp(exp.e1.loc, v), e); 9369 e = new CommaExp(exp.loc, de, e); 9370 } 9371 e = Expression.combine(e0, e); 9372 e = e.expressionSemantic(sc); 9373 result = e; 9374 return; 9375 } 9376 result = exp.incompatibleTypes(); 9377 } 9378 9379 override void visit(CatAssignExp exp) 9380 { 9381 if (exp.type) 9382 { 9383 result = exp; 9384 return; 9385 } 9386 9387 //printf("CatAssignExp::semantic() %s\n", exp.toChars()); 9388 Expression e = exp.op_overload(sc); 9389 if (e) 9390 { 9391 result = e; 9392 return; 9393 } 9394 9395 if (exp.e1.op == TOK.slice) 9396 { 9397 SliceExp se = cast(SliceExp)exp.e1; 9398 if (se.e1.type.toBasetype().ty == Tsarray) 9399 { 9400 exp.error("cannot append to static array `%s`", se.e1.type.toChars()); 9401 return setError(); 9402 } 9403 } 9404 9405 if (checkIfIsStructLiteralDotExpr(exp.e1)) 9406 return setError(); 9407 9408 exp.e1 = exp.e1.modifiableLvalue(sc, exp.e1); 9409 if (exp.e1.op == TOK.error) 9410 { 9411 result = exp.e1; 9412 return; 9413 } 9414 if (exp.e2.op == TOK.error) 9415 { 9416 result = exp.e2; 9417 return; 9418 } 9419 9420 if (checkNonAssignmentArrayOp(exp.e2)) 9421 return setError(); 9422 9423 Type tb1 = exp.e1.type.toBasetype(); 9424 Type tb1next = tb1.nextOf(); 9425 Type tb2 = exp.e2.type.toBasetype(); 9426 9427 /* Possibilities: 9428 * TOK.concatenateAssign: appending T[] to T[] 9429 * TOK.concatenateElemAssign: appending T to T[] 9430 * TOK.concatenateDcharAssign: appending dchar to T[] 9431 */ 9432 if ((tb1.ty == Tarray) && 9433 (tb2.ty == Tarray || tb2.ty == Tsarray) && 9434 (exp.e2.implicitConvTo(exp.e1.type) || 9435 (tb2.nextOf().implicitConvTo(tb1next) && 9436 (tb2.nextOf().size(Loc.initial) == tb1next.size(Loc.initial))))) 9437 { 9438 // TOK.concatenateAssign 9439 assert(exp.op == TOK.concatenateAssign); 9440 if (exp.e1.checkPostblit(sc, tb1next)) 9441 return setError(); 9442 9443 exp.e2 = exp.e2.castTo(sc, exp.e1.type); 9444 } 9445 else if ((tb1.ty == Tarray) && exp.e2.implicitConvTo(tb1next)) 9446 { 9447 /* https://issues.dlang.org/show_bug.cgi?id=19782 9448 * 9449 * If e2 is implicitly convertible to tb1next, the conversion 9450 * might be done through alias this, in which case, e2 needs to 9451 * be modified accordingly (e2 => e2.aliasthis). 9452 */ 9453 if (tb2.ty == Tstruct && (cast(TypeStruct)tb2).implicitConvToThroughAliasThis(tb1next)) 9454 goto Laliasthis; 9455 if (tb2.ty == Tclass && (cast(TypeClass)tb2).implicitConvToThroughAliasThis(tb1next)) 9456 goto Laliasthis; 9457 // Append element 9458 if (exp.e2.checkPostblit(sc, tb2)) 9459 return setError(); 9460 9461 if (checkNewEscape(sc, exp.e2, false)) 9462 return setError(); 9463 9464 exp = new CatElemAssignExp(exp.loc, exp.type, exp.e1, exp.e2.castTo(sc, tb1next)); 9465 exp.e2 = doCopyOrMove(sc, exp.e2); 9466 } 9467 else if (tb1.ty == Tarray && 9468 (tb1next.ty == Tchar || tb1next.ty == Twchar) && 9469 exp.e2.type.ty != tb1next.ty && 9470 exp.e2.implicitConvTo(Type.tdchar)) 9471 { 9472 // Append dchar to char[] or wchar[] 9473 exp = new CatDcharAssignExp(exp.loc, exp.type, exp.e1, exp.e2.castTo(sc, Type.tdchar)); 9474 9475 /* Do not allow appending wchar to char[] because if wchar happens 9476 * to be a surrogate pair, nothing good can result. 9477 */ 9478 } 9479 else 9480 { 9481 // Try alias this on first operand 9482 static Expression tryAliasThisForLhs(BinAssignExp exp, Scope* sc) 9483 { 9484 AggregateDeclaration ad1 = isAggregate(exp.e1.type); 9485 if (!ad1 || !ad1.aliasthis) 9486 return null; 9487 9488 /* Rewrite (e1 op e2) as: 9489 * (e1.aliasthis op e2) 9490 */ 9491 if (exp.att1 && exp.e1.type == exp.att1) 9492 return null; 9493 //printf("att %s e1 = %s\n", Token::toChars(e.op), e.e1.type.toChars()); 9494 Expression e1 = new DotIdExp(exp.loc, exp.e1, ad1.aliasthis.ident); 9495 BinExp be = cast(BinExp)exp.copy(); 9496 if (!be.att1 && exp.e1.type.checkAliasThisRec()) 9497 be.att1 = exp.e1.type; 9498 be.e1 = e1; 9499 return be.trySemantic(sc); 9500 } 9501 9502 // Try alias this on second operand 9503 static Expression tryAliasThisForRhs(BinAssignExp exp, Scope* sc) 9504 { 9505 AggregateDeclaration ad2 = isAggregate(exp.e2.type); 9506 if (!ad2 || !ad2.aliasthis) 9507 return null; 9508 /* Rewrite (e1 op e2) as: 9509 * (e1 op e2.aliasthis) 9510 */ 9511 if (exp.att2 && exp.e2.type == exp.att2) 9512 return null; 9513 //printf("att %s e2 = %s\n", Token::toChars(e.op), e.e2.type.toChars()); 9514 Expression e2 = new DotIdExp(exp.loc, exp.e2, ad2.aliasthis.ident); 9515 BinExp be = cast(BinExp)exp.copy(); 9516 if (!be.att2 && exp.e2.type.checkAliasThisRec()) 9517 be.att2 = exp.e2.type; 9518 be.e2 = e2; 9519 return be.trySemantic(sc); 9520 } 9521 9522 Laliasthis: 9523 result = tryAliasThisForLhs(exp, sc); 9524 if (result) 9525 return; 9526 9527 result = tryAliasThisForRhs(exp, sc); 9528 if (result) 9529 return; 9530 9531 exp.error("cannot append type `%s` to type `%s`", tb2.toChars(), tb1.toChars()); 9532 return setError(); 9533 } 9534 9535 if (exp.e2.checkValue() || exp.e2.checkSharedAccess(sc)) 9536 return setError(); 9537 9538 exp.type = exp.e1.type; 9539 auto res = exp.reorderSettingAAElem(sc); 9540 if ((exp.op == TOK.concatenateElemAssign || exp.op == TOK.concatenateDcharAssign) && global.params.vsafe) 9541 checkAssignEscape(sc, res, false); 9542 result = res; 9543 } 9544 9545 override void visit(AddExp exp) 9546 { 9547 static if (LOGSEMANTIC) 9548 { 9549 printf("AddExp::semantic('%s')\n", exp.toChars()); 9550 } 9551 if (exp.type) 9552 { 9553 result = exp; 9554 return; 9555 } 9556 9557 if (Expression ex = binSemanticProp(exp, sc)) 9558 { 9559 result = ex; 9560 return; 9561 } 9562 Expression e = exp.op_overload(sc); 9563 if (e) 9564 { 9565 result = e; 9566 return; 9567 } 9568 9569 Type tb1 = exp.e1.type.toBasetype(); 9570 Type tb2 = exp.e2.type.toBasetype(); 9571 9572 bool err = false; 9573 if (tb1.ty == Tdelegate || tb1.ty == Tpointer && tb1.nextOf().ty == Tfunction) 9574 { 9575 err |= exp.e1.checkArithmetic() || exp.e1.checkSharedAccess(sc); 9576 } 9577 if (tb2.ty == Tdelegate || tb2.ty == Tpointer && tb2.nextOf().ty == Tfunction) 9578 { 9579 err |= exp.e2.checkArithmetic() || exp.e2.checkSharedAccess(sc); 9580 } 9581 if (err) 9582 return setError(); 9583 9584 if (tb1.ty == Tpointer && exp.e2.type.isintegral() || tb2.ty == Tpointer && exp.e1.type.isintegral()) 9585 { 9586 result = scaleFactor(exp, sc); 9587 return; 9588 } 9589 9590 if (tb1.ty == Tpointer && tb2.ty == Tpointer) 9591 { 9592 result = exp.incompatibleTypes(); 9593 return; 9594 } 9595 9596 if (Expression ex = typeCombine(exp, sc)) 9597 { 9598 result = ex; 9599 return; 9600 } 9601 9602 Type tb = exp.type.toBasetype(); 9603 if (tb.ty == Tarray || tb.ty == Tsarray) 9604 { 9605 if (!isArrayOpValid(exp)) 9606 { 9607 result = arrayOpInvalidError(exp); 9608 return; 9609 } 9610 result = exp; 9611 return; 9612 } 9613 9614 tb1 = exp.e1.type.toBasetype(); 9615 if (!target.isVectorOpSupported(tb1, exp.op, tb2)) 9616 { 9617 result = exp.incompatibleTypes(); 9618 return; 9619 } 9620 if ((tb1.isreal() && exp.e2.type.isimaginary()) || (tb1.isimaginary() && exp.e2.type.isreal())) 9621 { 9622 switch (exp.type.toBasetype().ty) 9623 { 9624 case Tfloat32: 9625 case Timaginary32: 9626 exp.type = Type.tcomplex32; 9627 break; 9628 9629 case Tfloat64: 9630 case Timaginary64: 9631 exp.type = Type.tcomplex64; 9632 break; 9633 9634 case Tfloat80: 9635 case Timaginary80: 9636 exp.type = Type.tcomplex80; 9637 break; 9638 9639 default: 9640 assert(0); 9641 } 9642 } 9643 result = exp; 9644 } 9645 9646 override void visit(MinExp exp) 9647 { 9648 static if (LOGSEMANTIC) 9649 { 9650 printf("MinExp::semantic('%s')\n", exp.toChars()); 9651 } 9652 if (exp.type) 9653 { 9654 result = exp; 9655 return; 9656 } 9657 9658 if (Expression ex = binSemanticProp(exp, sc)) 9659 { 9660 result = ex; 9661 return; 9662 } 9663 Expression e = exp.op_overload(sc); 9664 if (e) 9665 { 9666 result = e; 9667 return; 9668 } 9669 9670 Type t1 = exp.e1.type.toBasetype(); 9671 Type t2 = exp.e2.type.toBasetype(); 9672 9673 bool err = false; 9674 if (t1.ty == Tdelegate || t1.ty == Tpointer && t1.nextOf().ty == Tfunction) 9675 { 9676 err |= exp.e1.checkArithmetic() || exp.e1.checkSharedAccess(sc); 9677 } 9678 if (t2.ty == Tdelegate || t2.ty == Tpointer && t2.nextOf().ty == Tfunction) 9679 { 9680 err |= exp.e2.checkArithmetic() || exp.e2.checkSharedAccess(sc); 9681 } 9682 if (err) 9683 return setError(); 9684 9685 if (t1.ty == Tpointer) 9686 { 9687 if (t2.ty == Tpointer) 9688 { 9689 // https://dlang.org/spec/expression.html#add_expressions 9690 // "If both operands are pointers, and the operator is -, the pointers are 9691 // subtracted and the result is divided by the size of the type pointed to 9692 // by the operands. It is an error if the pointers point to different types." 9693 Type p1 = t1.nextOf(); 9694 Type p2 = t2.nextOf(); 9695 9696 if (!p1.equivalent(p2)) 9697 { 9698 // Deprecation to remain for at least a year, after which this should be 9699 // changed to an error 9700 // See https://github.com/dlang/dmd/pull/7332 9701 deprecation(exp.loc, 9702 "cannot subtract pointers to different types: `%s` and `%s`.", 9703 t1.toChars(), t2.toChars()); 9704 } 9705 9706 // Need to divide the result by the stride 9707 // Replace (ptr - ptr) with (ptr - ptr) / stride 9708 d_int64 stride; 9709 9710 // make sure pointer types are compatible 9711 if (Expression ex = typeCombine(exp, sc)) 9712 { 9713 result = ex; 9714 return; 9715 } 9716 9717 exp.type = Type.tptrdiff_t; 9718 stride = t2.nextOf().size(); 9719 if (stride == 0) 9720 { 9721 e = new IntegerExp(exp.loc, 0, Type.tptrdiff_t); 9722 } 9723 else 9724 { 9725 e = new DivExp(exp.loc, exp, new IntegerExp(Loc.initial, stride, Type.tptrdiff_t)); 9726 e.type = Type.tptrdiff_t; 9727 } 9728 } 9729 else if (t2.isintegral()) 9730 e = scaleFactor(exp, sc); 9731 else 9732 { 9733 exp.error("can't subtract `%s` from pointer", t2.toChars()); 9734 e = new ErrorExp(); 9735 } 9736 result = e; 9737 return; 9738 } 9739 if (t2.ty == Tpointer) 9740 { 9741 exp.type = exp.e2.type; 9742 exp.error("can't subtract pointer from `%s`", exp.e1.type.toChars()); 9743 return setError(); 9744 } 9745 9746 if (Expression ex = typeCombine(exp, sc)) 9747 { 9748 result = ex; 9749 return; 9750 } 9751 9752 Type tb = exp.type.toBasetype(); 9753 if (tb.ty == Tarray || tb.ty == Tsarray) 9754 { 9755 if (!isArrayOpValid(exp)) 9756 { 9757 result = arrayOpInvalidError(exp); 9758 return; 9759 } 9760 result = exp; 9761 return; 9762 } 9763 9764 t1 = exp.e1.type.toBasetype(); 9765 t2 = exp.e2.type.toBasetype(); 9766 if (!target.isVectorOpSupported(t1, exp.op, t2)) 9767 { 9768 result = exp.incompatibleTypes(); 9769 return; 9770 } 9771 if ((t1.isreal() && t2.isimaginary()) || (t1.isimaginary() && t2.isreal())) 9772 { 9773 switch (exp.type.ty) 9774 { 9775 case Tfloat32: 9776 case Timaginary32: 9777 exp.type = Type.tcomplex32; 9778 break; 9779 9780 case Tfloat64: 9781 case Timaginary64: 9782 exp.type = Type.tcomplex64; 9783 break; 9784 9785 case Tfloat80: 9786 case Timaginary80: 9787 exp.type = Type.tcomplex80; 9788 break; 9789 9790 default: 9791 assert(0); 9792 } 9793 } 9794 result = exp; 9795 return; 9796 } 9797 9798 override void visit(CatExp exp) 9799 { 9800 // https://dlang.org/spec/expression.html#cat_expressions 9801 //printf("CatExp.semantic() %s\n", toChars()); 9802 if (exp.type) 9803 { 9804 result = exp; 9805 return; 9806 } 9807 9808 if (Expression ex = binSemanticProp(exp, sc)) 9809 { 9810 result = ex; 9811 return; 9812 } 9813 Expression e = exp.op_overload(sc); 9814 if (e) 9815 { 9816 result = e; 9817 return; 9818 } 9819 9820 Type tb1 = exp.e1.type.toBasetype(); 9821 Type tb2 = exp.e2.type.toBasetype(); 9822 9823 auto f1 = checkNonAssignmentArrayOp(exp.e1); 9824 auto f2 = checkNonAssignmentArrayOp(exp.e2); 9825 if (f1 || f2) 9826 return setError(); 9827 9828 /* BUG: Should handle things like: 9829 * char c; 9830 * c ~ ' ' 9831 * ' ' ~ c; 9832 */ 9833 9834 Type tb1next = tb1.nextOf(); 9835 Type tb2next = tb2.nextOf(); 9836 9837 // Check for: array ~ array 9838 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))) 9839 { 9840 /* https://issues.dlang.org/show_bug.cgi?id=9248 9841 * Here to avoid the case of: 9842 * void*[] a = [cast(void*)1]; 9843 * void*[] b = [cast(void*)2]; 9844 * a ~ b; 9845 * becoming: 9846 * a ~ [cast(void*)b]; 9847 */ 9848 9849 /* https://issues.dlang.org/show_bug.cgi?id=14682 9850 * Also to avoid the case of: 9851 * int[][] a; 9852 * a ~ []; 9853 * becoming: 9854 * a ~ cast(int[])[]; 9855 */ 9856 goto Lpeer; 9857 } 9858 9859 // Check for: array ~ element 9860 if ((tb1.ty == Tsarray || tb1.ty == Tarray) && tb2.ty != Tvoid) 9861 { 9862 if (exp.e1.op == TOK.arrayLiteral) 9863 { 9864 exp.e2 = doCopyOrMove(sc, exp.e2); 9865 // https://issues.dlang.org/show_bug.cgi?id=14686 9866 // Postblit call appears in AST, and this is 9867 // finally translated to an ArrayLiteralExp in below optimize(). 9868 } 9869 else if (exp.e1.op == TOK.string_) 9870 { 9871 // No postblit call exists on character (integer) value. 9872 } 9873 else 9874 { 9875 if (exp.e2.checkPostblit(sc, tb2)) 9876 return setError(); 9877 // Postblit call will be done in runtime helper function 9878 } 9879 9880 if (exp.e1.op == TOK.arrayLiteral && exp.e1.implicitConvTo(tb2.arrayOf())) 9881 { 9882 exp.e1 = exp.e1.implicitCastTo(sc, tb2.arrayOf()); 9883 exp.type = tb2.arrayOf(); 9884 goto L2elem; 9885 } 9886 if (exp.e2.implicitConvTo(tb1next) >= MATCH.convert) 9887 { 9888 exp.e2 = exp.e2.implicitCastTo(sc, tb1next); 9889 exp.type = tb1next.arrayOf(); 9890 L2elem: 9891 if (tb2.ty == Tarray || tb2.ty == Tsarray) 9892 { 9893 // Make e2 into [e2] 9894 exp.e2 = new ArrayLiteralExp(exp.e2.loc, exp.type, exp.e2); 9895 } 9896 else if (checkNewEscape(sc, exp.e2, false)) 9897 return setError(); 9898 result = exp.optimize(WANTvalue); 9899 return; 9900 } 9901 } 9902 // Check for: element ~ array 9903 if ((tb2.ty == Tsarray || tb2.ty == Tarray) && tb1.ty != Tvoid) 9904 { 9905 if (exp.e2.op == TOK.arrayLiteral) 9906 { 9907 exp.e1 = doCopyOrMove(sc, exp.e1); 9908 } 9909 else if (exp.e2.op == TOK.string_) 9910 { 9911 } 9912 else 9913 { 9914 if (exp.e1.checkPostblit(sc, tb1)) 9915 return setError(); 9916 } 9917 9918 if (exp.e2.op == TOK.arrayLiteral && exp.e2.implicitConvTo(tb1.arrayOf())) 9919 { 9920 exp.e2 = exp.e2.implicitCastTo(sc, tb1.arrayOf()); 9921 exp.type = tb1.arrayOf(); 9922 goto L1elem; 9923 } 9924 if (exp.e1.implicitConvTo(tb2next) >= MATCH.convert) 9925 { 9926 exp.e1 = exp.e1.implicitCastTo(sc, tb2next); 9927 exp.type = tb2next.arrayOf(); 9928 L1elem: 9929 if (tb1.ty == Tarray || tb1.ty == Tsarray) 9930 { 9931 // Make e1 into [e1] 9932 exp.e1 = new ArrayLiteralExp(exp.e1.loc, exp.type, exp.e1); 9933 } 9934 else if (checkNewEscape(sc, exp.e1, false)) 9935 return setError(); 9936 result = exp.optimize(WANTvalue); 9937 return; 9938 } 9939 } 9940 9941 Lpeer: 9942 if ((tb1.ty == Tsarray || tb1.ty == Tarray) && (tb2.ty == Tsarray || tb2.ty == Tarray) && (tb1next.mod || tb2next.mod) && (tb1next.mod != tb2next.mod)) 9943 { 9944 Type t1 = tb1next.mutableOf().constOf().arrayOf(); 9945 Type t2 = tb2next.mutableOf().constOf().arrayOf(); 9946 if (exp.e1.op == TOK.string_ && !(cast(StringExp)exp.e1).committed) 9947 exp.e1.type = t1; 9948 else 9949 exp.e1 = exp.e1.castTo(sc, t1); 9950 if (exp.e2.op == TOK.string_ && !(cast(StringExp)exp.e2).committed) 9951 exp.e2.type = t2; 9952 else 9953 exp.e2 = exp.e2.castTo(sc, t2); 9954 } 9955 9956 if (Expression ex = typeCombine(exp, sc)) 9957 { 9958 result = ex; 9959 return; 9960 } 9961 exp.type = exp.type.toHeadMutable(); 9962 9963 Type tb = exp.type.toBasetype(); 9964 if (tb.ty == Tsarray) 9965 exp.type = tb.nextOf().arrayOf(); 9966 if (exp.type.ty == Tarray && tb1next && tb2next && tb1next.mod != tb2next.mod) 9967 { 9968 exp.type = exp.type.nextOf().toHeadMutable().arrayOf(); 9969 } 9970 if (Type tbn = tb.nextOf()) 9971 { 9972 if (exp.checkPostblit(sc, tbn)) 9973 return setError(); 9974 } 9975 Type t1 = exp.e1.type.toBasetype(); 9976 Type t2 = exp.e2.type.toBasetype(); 9977 if ((t1.ty == Tarray || t1.ty == Tsarray) && 9978 (t2.ty == Tarray || t2.ty == Tsarray)) 9979 { 9980 // Normalize to ArrayLiteralExp or StringExp as far as possible 9981 e = exp.optimize(WANTvalue); 9982 } 9983 else 9984 { 9985 //printf("(%s) ~ (%s)\n", e1.toChars(), e2.toChars()); 9986 result = exp.incompatibleTypes(); 9987 return; 9988 } 9989 9990 result = e; 9991 } 9992 9993 override void visit(MulExp exp) 9994 { 9995 version (none) 9996 { 9997 printf("MulExp::semantic() %s\n", exp.toChars()); 9998 } 9999 if (exp.type) 10000 { 10001 result = exp; 10002 return; 10003 } 10004 10005 if (Expression ex = binSemanticProp(exp, sc)) 10006 { 10007 result = ex; 10008 return; 10009 } 10010 Expression e = exp.op_overload(sc); 10011 if (e) 10012 { 10013 result = e; 10014 return; 10015 } 10016 10017 if (Expression ex = typeCombine(exp, sc)) 10018 { 10019 result = ex; 10020 return; 10021 } 10022 10023 Type tb = exp.type.toBasetype(); 10024 if (tb.ty == Tarray || tb.ty == Tsarray) 10025 { 10026 if (!isArrayOpValid(exp)) 10027 { 10028 result = arrayOpInvalidError(exp); 10029 return; 10030 } 10031 result = exp; 10032 return; 10033 } 10034 10035 if (exp.checkArithmeticBin() || exp.checkSharedAccessBin(sc)) 10036 return setError(); 10037 10038 if (exp.type.isfloating()) 10039 { 10040 Type t1 = exp.e1.type; 10041 Type t2 = exp.e2.type; 10042 10043 if (t1.isreal()) 10044 { 10045 exp.type = t2; 10046 } 10047 else if (t2.isreal()) 10048 { 10049 exp.type = t1; 10050 } 10051 else if (t1.isimaginary()) 10052 { 10053 if (t2.isimaginary()) 10054 { 10055 switch (t1.toBasetype().ty) 10056 { 10057 case Timaginary32: 10058 exp.type = Type.tfloat32; 10059 break; 10060 10061 case Timaginary64: 10062 exp.type = Type.tfloat64; 10063 break; 10064 10065 case Timaginary80: 10066 exp.type = Type.tfloat80; 10067 break; 10068 10069 default: 10070 assert(0); 10071 } 10072 10073 // iy * iv = -yv 10074 exp.e1.type = exp.type; 10075 exp.e2.type = exp.type; 10076 e = new NegExp(exp.loc, exp); 10077 e = e.expressionSemantic(sc); 10078 result = e; 10079 return; 10080 } 10081 else 10082 exp.type = t2; // t2 is complex 10083 } 10084 else if (t2.isimaginary()) 10085 { 10086 exp.type = t1; // t1 is complex 10087 } 10088 } 10089 else if (!target.isVectorOpSupported(tb, exp.op, exp.e2.type.toBasetype())) 10090 { 10091 result = exp.incompatibleTypes(); 10092 return; 10093 } 10094 result = exp; 10095 } 10096 10097 override void visit(DivExp exp) 10098 { 10099 if (exp.type) 10100 { 10101 result = exp; 10102 return; 10103 } 10104 10105 if (Expression ex = binSemanticProp(exp, sc)) 10106 { 10107 result = ex; 10108 return; 10109 } 10110 Expression e = exp.op_overload(sc); 10111 if (e) 10112 { 10113 result = e; 10114 return; 10115 } 10116 10117 if (Expression ex = typeCombine(exp, sc)) 10118 { 10119 result = ex; 10120 return; 10121 } 10122 10123 Type tb = exp.type.toBasetype(); 10124 if (tb.ty == Tarray || tb.ty == Tsarray) 10125 { 10126 if (!isArrayOpValid(exp)) 10127 { 10128 result = arrayOpInvalidError(exp); 10129 return; 10130 } 10131 result = exp; 10132 return; 10133 } 10134 10135 if (exp.checkArithmeticBin() || exp.checkSharedAccessBin(sc)) 10136 return setError(); 10137 10138 if (exp.type.isfloating()) 10139 { 10140 Type t1 = exp.e1.type; 10141 Type t2 = exp.e2.type; 10142 10143 if (t1.isreal()) 10144 { 10145 exp.type = t2; 10146 if (t2.isimaginary()) 10147 { 10148 // x/iv = i(-x/v) 10149 exp.e2.type = t1; 10150 e = new NegExp(exp.loc, exp); 10151 e = e.expressionSemantic(sc); 10152 result = e; 10153 return; 10154 } 10155 } 10156 else if (t2.isreal()) 10157 { 10158 exp.type = t1; 10159 } 10160 else if (t1.isimaginary()) 10161 { 10162 if (t2.isimaginary()) 10163 { 10164 switch (t1.toBasetype().ty) 10165 { 10166 case Timaginary32: 10167 exp.type = Type.tfloat32; 10168 break; 10169 10170 case Timaginary64: 10171 exp.type = Type.tfloat64; 10172 break; 10173 10174 case Timaginary80: 10175 exp.type = Type.tfloat80; 10176 break; 10177 10178 default: 10179 assert(0); 10180 } 10181 } 10182 else 10183 exp.type = t2; // t2 is complex 10184 } 10185 else if (t2.isimaginary()) 10186 { 10187 exp.type = t1; // t1 is complex 10188 } 10189 } 10190 else if (!target.isVectorOpSupported(tb, exp.op, exp.e2.type.toBasetype())) 10191 { 10192 result = exp.incompatibleTypes(); 10193 return; 10194 } 10195 result = exp; 10196 } 10197 10198 override void visit(ModExp exp) 10199 { 10200 if (exp.type) 10201 { 10202 result = exp; 10203 return; 10204 } 10205 10206 if (Expression ex = binSemanticProp(exp, sc)) 10207 { 10208 result = ex; 10209 return; 10210 } 10211 Expression e = exp.op_overload(sc); 10212 if (e) 10213 { 10214 result = e; 10215 return; 10216 } 10217 10218 if (Expression ex = typeCombine(exp, sc)) 10219 { 10220 result = ex; 10221 return; 10222 } 10223 10224 Type tb = exp.type.toBasetype(); 10225 if (tb.ty == Tarray || tb.ty == Tsarray) 10226 { 10227 if (!isArrayOpValid(exp)) 10228 { 10229 result = arrayOpInvalidError(exp); 10230 return; 10231 } 10232 result = exp; 10233 return; 10234 } 10235 if (!target.isVectorOpSupported(tb, exp.op, exp.e2.type.toBasetype())) 10236 { 10237 result = exp.incompatibleTypes(); 10238 return; 10239 } 10240 10241 if (exp.checkArithmeticBin() || exp.checkSharedAccessBin(sc)) 10242 return setError(); 10243 10244 if (exp.type.isfloating()) 10245 { 10246 exp.type = exp.e1.type; 10247 if (exp.e2.type.iscomplex()) 10248 { 10249 exp.error("cannot perform modulo complex arithmetic"); 10250 return setError(); 10251 } 10252 } 10253 result = exp; 10254 } 10255 10256 override void visit(PowExp exp) 10257 { 10258 if (exp.type) 10259 { 10260 result = exp; 10261 return; 10262 } 10263 10264 //printf("PowExp::semantic() %s\n", toChars()); 10265 if (Expression ex = binSemanticProp(exp, sc)) 10266 { 10267 result = ex; 10268 return; 10269 } 10270 Expression e = exp.op_overload(sc); 10271 if (e) 10272 { 10273 result = e; 10274 return; 10275 } 10276 10277 if (Expression ex = typeCombine(exp, sc)) 10278 { 10279 result = ex; 10280 return; 10281 } 10282 10283 Type tb = exp.type.toBasetype(); 10284 if (tb.ty == Tarray || tb.ty == Tsarray) 10285 { 10286 if (!isArrayOpValid(exp)) 10287 { 10288 result = arrayOpInvalidError(exp); 10289 return; 10290 } 10291 result = exp; 10292 return; 10293 } 10294 10295 if (exp.checkArithmeticBin() || exp.checkSharedAccessBin(sc)) 10296 return setError(); 10297 10298 if (!target.isVectorOpSupported(tb, exp.op, exp.e2.type.toBasetype())) 10299 { 10300 result = exp.incompatibleTypes(); 10301 return; 10302 } 10303 10304 // First, attempt to fold the expression. 10305 e = exp.optimize(WANTvalue); 10306 if (e.op != TOK.pow) 10307 { 10308 e = e.expressionSemantic(sc); 10309 result = e; 10310 return; 10311 } 10312 10313 Module mmath = loadStdMath(); 10314 if (!mmath) 10315 { 10316 e.error("`%s` requires `std.math` for `^^` operators", e.toChars()); 10317 return setError(); 10318 } 10319 e = new ScopeExp(exp.loc, mmath); 10320 10321 if (exp.e2.op == TOK.float64 && exp.e2.toReal() == CTFloat.half) 10322 { 10323 // Replace e1 ^^ 0.5 with .std.math.sqrt(e1) 10324 e = new CallExp(exp.loc, new DotIdExp(exp.loc, e, Id._sqrt), exp.e1); 10325 } 10326 else 10327 { 10328 // Replace e1 ^^ e2 with .std.math.pow(e1, e2) 10329 e = new CallExp(exp.loc, new DotIdExp(exp.loc, e, Id._pow), exp.e1, exp.e2); 10330 } 10331 e = e.expressionSemantic(sc); 10332 result = e; 10333 return; 10334 } 10335 10336 override void visit(ShlExp exp) 10337 { 10338 //printf("ShlExp::semantic(), type = %p\n", type); 10339 if (exp.type) 10340 { 10341 result = exp; 10342 return; 10343 } 10344 10345 if (Expression ex = binSemanticProp(exp, sc)) 10346 { 10347 result = ex; 10348 return; 10349 } 10350 Expression e = exp.op_overload(sc); 10351 if (e) 10352 { 10353 result = e; 10354 return; 10355 } 10356 10357 if (exp.checkIntegralBin() || exp.checkSharedAccessBin(sc)) 10358 return setError(); 10359 10360 if (!target.isVectorOpSupported(exp.e1.type.toBasetype(), exp.op, exp.e2.type.toBasetype())) 10361 { 10362 result = exp.incompatibleTypes(); 10363 return; 10364 } 10365 exp.e1 = integralPromotions(exp.e1, sc); 10366 if (exp.e2.type.toBasetype().ty != Tvector) 10367 exp.e2 = exp.e2.castTo(sc, Type.tshiftcnt); 10368 10369 exp.type = exp.e1.type; 10370 result = exp; 10371 } 10372 10373 override void visit(ShrExp exp) 10374 { 10375 if (exp.type) 10376 { 10377 result = exp; 10378 return; 10379 } 10380 10381 if (Expression ex = binSemanticProp(exp, sc)) 10382 { 10383 result = ex; 10384 return; 10385 } 10386 Expression e = exp.op_overload(sc); 10387 if (e) 10388 { 10389 result = e; 10390 return; 10391 } 10392 10393 if (exp.checkIntegralBin() || exp.checkSharedAccessBin(sc)) 10394 return setError(); 10395 10396 if (!target.isVectorOpSupported(exp.e1.type.toBasetype(), exp.op, exp.e2.type.toBasetype())) 10397 { 10398 result = exp.incompatibleTypes(); 10399 return; 10400 } 10401 exp.e1 = integralPromotions(exp.e1, sc); 10402 if (exp.e2.type.toBasetype().ty != Tvector) 10403 exp.e2 = exp.e2.castTo(sc, Type.tshiftcnt); 10404 10405 exp.type = exp.e1.type; 10406 result = exp; 10407 } 10408 10409 override void visit(UshrExp exp) 10410 { 10411 if (exp.type) 10412 { 10413 result = exp; 10414 return; 10415 } 10416 10417 if (Expression ex = binSemanticProp(exp, sc)) 10418 { 10419 result = ex; 10420 return; 10421 } 10422 Expression e = exp.op_overload(sc); 10423 if (e) 10424 { 10425 result = e; 10426 return; 10427 } 10428 10429 if (exp.checkIntegralBin() || exp.checkSharedAccessBin(sc)) 10430 return setError(); 10431 10432 if (!target.isVectorOpSupported(exp.e1.type.toBasetype(), exp.op, exp.e2.type.toBasetype())) 10433 { 10434 result = exp.incompatibleTypes(); 10435 return; 10436 } 10437 exp.e1 = integralPromotions(exp.e1, sc); 10438 if (exp.e2.type.toBasetype().ty != Tvector) 10439 exp.e2 = exp.e2.castTo(sc, Type.tshiftcnt); 10440 10441 exp.type = exp.e1.type; 10442 result = exp; 10443 } 10444 10445 override void visit(AndExp exp) 10446 { 10447 if (exp.type) 10448 { 10449 result = exp; 10450 return; 10451 } 10452 10453 if (Expression ex = binSemanticProp(exp, sc)) 10454 { 10455 result = ex; 10456 return; 10457 } 10458 Expression e = exp.op_overload(sc); 10459 if (e) 10460 { 10461 result = e; 10462 return; 10463 } 10464 10465 if (exp.e1.type.toBasetype().ty == Tbool && exp.e2.type.toBasetype().ty == Tbool) 10466 { 10467 exp.type = exp.e1.type; 10468 result = exp; 10469 return; 10470 } 10471 10472 if (Expression ex = typeCombine(exp, sc)) 10473 { 10474 result = ex; 10475 return; 10476 } 10477 10478 Type tb = exp.type.toBasetype(); 10479 if (tb.ty == Tarray || tb.ty == Tsarray) 10480 { 10481 if (!isArrayOpValid(exp)) 10482 { 10483 result = arrayOpInvalidError(exp); 10484 return; 10485 } 10486 result = exp; 10487 return; 10488 } 10489 if (!target.isVectorOpSupported(tb, exp.op, exp.e2.type.toBasetype())) 10490 { 10491 result = exp.incompatibleTypes(); 10492 return; 10493 } 10494 if (exp.checkIntegralBin() || exp.checkSharedAccessBin(sc)) 10495 return setError(); 10496 10497 result = exp; 10498 } 10499 10500 override void visit(OrExp exp) 10501 { 10502 if (exp.type) 10503 { 10504 result = exp; 10505 return; 10506 } 10507 10508 if (Expression ex = binSemanticProp(exp, sc)) 10509 { 10510 result = ex; 10511 return; 10512 } 10513 Expression e = exp.op_overload(sc); 10514 if (e) 10515 { 10516 result = e; 10517 return; 10518 } 10519 10520 if (exp.e1.type.toBasetype().ty == Tbool && exp.e2.type.toBasetype().ty == Tbool) 10521 { 10522 exp.type = exp.e1.type; 10523 result = exp; 10524 return; 10525 } 10526 10527 if (Expression ex = typeCombine(exp, sc)) 10528 { 10529 result = ex; 10530 return; 10531 } 10532 10533 Type tb = exp.type.toBasetype(); 10534 if (tb.ty == Tarray || tb.ty == Tsarray) 10535 { 10536 if (!isArrayOpValid(exp)) 10537 { 10538 result = arrayOpInvalidError(exp); 10539 return; 10540 } 10541 result = exp; 10542 return; 10543 } 10544 if (!target.isVectorOpSupported(tb, exp.op, exp.e2.type.toBasetype())) 10545 { 10546 result = exp.incompatibleTypes(); 10547 return; 10548 } 10549 if (exp.checkIntegralBin() || exp.checkSharedAccessBin(sc)) 10550 return setError(); 10551 10552 result = exp; 10553 } 10554 10555 override void visit(XorExp exp) 10556 { 10557 if (exp.type) 10558 { 10559 result = exp; 10560 return; 10561 } 10562 10563 if (Expression ex = binSemanticProp(exp, sc)) 10564 { 10565 result = ex; 10566 return; 10567 } 10568 Expression e = exp.op_overload(sc); 10569 if (e) 10570 { 10571 result = e; 10572 return; 10573 } 10574 10575 if (exp.e1.type.toBasetype().ty == Tbool && exp.e2.type.toBasetype().ty == Tbool) 10576 { 10577 exp.type = exp.e1.type; 10578 result = exp; 10579 return; 10580 } 10581 10582 if (Expression ex = typeCombine(exp, sc)) 10583 { 10584 result = ex; 10585 return; 10586 } 10587 10588 Type tb = exp.type.toBasetype(); 10589 if (tb.ty == Tarray || tb.ty == Tsarray) 10590 { 10591 if (!isArrayOpValid(exp)) 10592 { 10593 result = arrayOpInvalidError(exp); 10594 return; 10595 } 10596 result = exp; 10597 return; 10598 } 10599 if (!target.isVectorOpSupported(tb, exp.op, exp.e2.type.toBasetype())) 10600 { 10601 result = exp.incompatibleTypes(); 10602 return; 10603 } 10604 if (exp.checkIntegralBin() || exp.checkSharedAccessBin(sc)) 10605 return setError(); 10606 10607 result = exp; 10608 } 10609 10610 override void visit(LogicalExp exp) 10611 { 10612 static if (LOGSEMANTIC) 10613 { 10614 printf("LogicalExp::semantic() %s\n", exp.toChars()); 10615 } 10616 10617 if (exp.type) 10618 { 10619 result = exp; 10620 return; 10621 } 10622 10623 exp.setNoderefOperands(); 10624 10625 Expression e1x = exp.e1.expressionSemantic(sc); 10626 10627 // for static alias this: https://issues.dlang.org/show_bug.cgi?id=17684 10628 if (e1x.op == TOK.type) 10629 e1x = resolveAliasThis(sc, e1x); 10630 10631 e1x = resolveProperties(sc, e1x); 10632 e1x = e1x.toBoolean(sc); 10633 10634 if (sc.flags & SCOPE.condition) 10635 { 10636 /* If in static if, don't evaluate e2 if we don't have to. 10637 */ 10638 e1x = e1x.optimize(WANTvalue); 10639 if (e1x.isBool(exp.op == TOK.orOr)) 10640 { 10641 result = IntegerExp.createBool(exp.op == TOK.orOr); 10642 return; 10643 } 10644 } 10645 10646 CtorFlow ctorflow = sc.ctorflow.clone(); 10647 Expression e2x = exp.e2.expressionSemantic(sc); 10648 sc.merge(exp.loc, ctorflow); 10649 ctorflow.freeFieldinit(); 10650 10651 // for static alias this: https://issues.dlang.org/show_bug.cgi?id=17684 10652 if (e2x.op == TOK.type) 10653 e2x = resolveAliasThis(sc, e2x); 10654 10655 e2x = resolveProperties(sc, e2x); 10656 10657 auto f1 = checkNonAssignmentArrayOp(e1x); 10658 auto f2 = checkNonAssignmentArrayOp(e2x); 10659 if (f1 || f2) 10660 return setError(); 10661 10662 // Unless the right operand is 'void', the expression is converted to 'bool'. 10663 if (e2x.type.ty != Tvoid) 10664 e2x = e2x.toBoolean(sc); 10665 10666 if (e2x.op == TOK.type || e2x.op == TOK.scope_) 10667 { 10668 exp.error("`%s` is not an expression", exp.e2.toChars()); 10669 return setError(); 10670 } 10671 if (e1x.op == TOK.error) 10672 { 10673 result = e1x; 10674 return; 10675 } 10676 if (e2x.op == TOK.error) 10677 { 10678 result = e2x; 10679 return; 10680 } 10681 10682 // The result type is 'bool', unless the right operand has type 'void'. 10683 if (e2x.type.ty == Tvoid) 10684 exp.type = Type.tvoid; 10685 else 10686 exp.type = Type.tbool; 10687 10688 exp.e1 = e1x; 10689 exp.e2 = e2x; 10690 result = exp; 10691 } 10692 10693 10694 override void visit(CmpExp exp) 10695 { 10696 static if (LOGSEMANTIC) 10697 { 10698 printf("CmpExp::semantic('%s')\n", exp.toChars()); 10699 } 10700 if (exp.type) 10701 { 10702 result = exp; 10703 return; 10704 } 10705 10706 exp.setNoderefOperands(); 10707 10708 if (Expression ex = binSemanticProp(exp, sc)) 10709 { 10710 result = ex; 10711 return; 10712 } 10713 Type t1 = exp.e1.type.toBasetype(); 10714 Type t2 = exp.e2.type.toBasetype(); 10715 if (t1.ty == Tclass && exp.e2.op == TOK.null_ || t2.ty == Tclass && exp.e1.op == TOK.null_) 10716 { 10717 exp.error("do not use `null` when comparing class types"); 10718 return setError(); 10719 } 10720 10721 TOK cmpop; 10722 if (auto e = exp.op_overload(sc, &cmpop)) 10723 { 10724 if (!e.type.isscalar() && e.type.equals(exp.e1.type)) 10725 { 10726 exp.error("recursive `opCmp` expansion"); 10727 return setError(); 10728 } 10729 if (e.op == TOK.call) 10730 { 10731 e = new CmpExp(cmpop, exp.loc, e, new IntegerExp(exp.loc, 0, Type.tint32)); 10732 e = e.expressionSemantic(sc); 10733 } 10734 result = e; 10735 return; 10736 } 10737 10738 if (Expression ex = typeCombine(exp, sc)) 10739 { 10740 result = ex; 10741 return; 10742 } 10743 10744 auto f1 = checkNonAssignmentArrayOp(exp.e1); 10745 auto f2 = checkNonAssignmentArrayOp(exp.e2); 10746 if (f1 || f2) 10747 return setError(); 10748 10749 exp.type = Type.tbool; 10750 10751 // Special handling for array comparisons 10752 Expression arrayLowering = null; 10753 t1 = exp.e1.type.toBasetype(); 10754 t2 = exp.e2.type.toBasetype(); 10755 if ((t1.ty == Tarray || t1.ty == Tsarray || t1.ty == Tpointer) && (t2.ty == Tarray || t2.ty == Tsarray || t2.ty == Tpointer)) 10756 { 10757 Type t1next = t1.nextOf(); 10758 Type t2next = t2.nextOf(); 10759 if (t1next.implicitConvTo(t2next) < MATCH.constant && t2next.implicitConvTo(t1next) < MATCH.constant && (t1next.ty != Tvoid && t2next.ty != Tvoid)) 10760 { 10761 exp.error("array comparison type mismatch, `%s` vs `%s`", t1next.toChars(), t2next.toChars()); 10762 return setError(); 10763 } 10764 if ((t1.ty == Tarray || t1.ty == Tsarray) && (t2.ty == Tarray || t2.ty == Tsarray)) 10765 { 10766 if (!verifyHookExist(exp.loc, *sc, Id.__cmp, "comparing arrays")) 10767 return setError(); 10768 10769 // Lower to object.__cmp(e1, e2) 10770 Expression al = new IdentifierExp(exp.loc, Id.empty); 10771 al = new DotIdExp(exp.loc, al, Id.object); 10772 al = new DotIdExp(exp.loc, al, Id.__cmp); 10773 al = al.expressionSemantic(sc); 10774 10775 auto arguments = new Expressions(2); 10776 (*arguments)[0] = exp.e1; 10777 (*arguments)[1] = exp.e2; 10778 10779 al = new CallExp(exp.loc, al, arguments); 10780 al = new CmpExp(exp.op, exp.loc, al, IntegerExp.literal!0); 10781 10782 arrayLowering = al; 10783 } 10784 } 10785 else if (t1.ty == Tstruct || t2.ty == Tstruct || (t1.ty == Tclass && t2.ty == Tclass)) 10786 { 10787 if (t2.ty == Tstruct) 10788 exp.error("need member function `opCmp()` for %s `%s` to compare", t2.toDsymbol(sc).kind(), t2.toChars()); 10789 else 10790 exp.error("need member function `opCmp()` for %s `%s` to compare", t1.toDsymbol(sc).kind(), t1.toChars()); 10791 return setError(); 10792 } 10793 else if (t1.iscomplex() || t2.iscomplex()) 10794 { 10795 exp.error("compare not defined for complex operands"); 10796 return setError(); 10797 } 10798 else if (t1.ty == Taarray || t2.ty == Taarray) 10799 { 10800 exp.error("`%s` is not defined for associative arrays", Token.toChars(exp.op)); 10801 return setError(); 10802 } 10803 else if (!target.isVectorOpSupported(t1, exp.op, t2)) 10804 { 10805 result = exp.incompatibleTypes(); 10806 return; 10807 } 10808 else 10809 { 10810 bool r1 = exp.e1.checkValue() || exp.e1.checkSharedAccess(sc); 10811 bool r2 = exp.e2.checkValue() || exp.e2.checkSharedAccess(sc); 10812 if (r1 || r2) 10813 return setError(); 10814 } 10815 10816 //printf("CmpExp: %s, type = %s\n", e.toChars(), e.type.toChars()); 10817 if (arrayLowering) 10818 { 10819 arrayLowering = arrayLowering.expressionSemantic(sc); 10820 result = arrayLowering; 10821 return; 10822 } 10823 result = exp; 10824 return; 10825 } 10826 10827 override void visit(InExp exp) 10828 { 10829 if (exp.type) 10830 { 10831 result = exp; 10832 return; 10833 } 10834 10835 if (Expression ex = binSemanticProp(exp, sc)) 10836 { 10837 result = ex; 10838 return; 10839 } 10840 Expression e = exp.op_overload(sc); 10841 if (e) 10842 { 10843 result = e; 10844 return; 10845 } 10846 10847 Type t2b = exp.e2.type.toBasetype(); 10848 switch (t2b.ty) 10849 { 10850 case Taarray: 10851 { 10852 TypeAArray ta = cast(TypeAArray)t2b; 10853 10854 // Special handling for array keys 10855 if (!arrayTypeCompatibleWithoutCasting(exp.e1.type, ta.index)) 10856 { 10857 // Convert key to type of key 10858 exp.e1 = exp.e1.implicitCastTo(sc, ta.index); 10859 } 10860 10861 semanticTypeInfo(sc, ta.index); 10862 10863 // Return type is pointer to value 10864 exp.type = ta.nextOf().pointerTo(); 10865 break; 10866 } 10867 10868 case Terror: 10869 return setError(); 10870 10871 default: 10872 result = exp.incompatibleTypes(); 10873 return; 10874 } 10875 result = exp; 10876 } 10877 10878 override void visit(RemoveExp e) 10879 { 10880 if (Expression ex = binSemantic(e, sc)) 10881 { 10882 result = ex; 10883 return; 10884 } 10885 result = e; 10886 } 10887 10888 override void visit(EqualExp exp) 10889 { 10890 //printf("EqualExp::semantic('%s')\n", exp.toChars()); 10891 if (exp.type) 10892 { 10893 result = exp; 10894 return; 10895 } 10896 10897 exp.setNoderefOperands(); 10898 10899 if (auto e = binSemanticProp(exp, sc)) 10900 { 10901 result = e; 10902 return; 10903 } 10904 if (exp.e1.op == TOK.type || exp.e2.op == TOK.type) 10905 { 10906 result = exp.incompatibleTypes(); 10907 return; 10908 } 10909 10910 { 10911 auto t1 = exp.e1.type; 10912 auto t2 = exp.e2.type; 10913 if (t1.ty == Tenum && t2.ty == Tenum && !t1.equivalent(t2)) 10914 exp.error("Comparison between different enumeration types `%s` and `%s`; If this behavior is intended consider using `std.conv.asOriginalType`", 10915 t1.toChars(), t2.toChars()); 10916 } 10917 10918 /* Before checking for operator overloading, check to see if we're 10919 * comparing the addresses of two statics. If so, we can just see 10920 * if they are the same symbol. 10921 */ 10922 if (exp.e1.op == TOK.address && exp.e2.op == TOK.address) 10923 { 10924 AddrExp ae1 = cast(AddrExp)exp.e1; 10925 AddrExp ae2 = cast(AddrExp)exp.e2; 10926 if (ae1.e1.op == TOK.variable && ae2.e1.op == TOK.variable) 10927 { 10928 VarExp ve1 = cast(VarExp)ae1.e1; 10929 VarExp ve2 = cast(VarExp)ae2.e1; 10930 if (ve1.var == ve2.var) 10931 { 10932 // They are the same, result is 'true' for ==, 'false' for != 10933 result = IntegerExp.createBool(exp.op == TOK.equal); 10934 return; 10935 } 10936 } 10937 } 10938 10939 Type t1 = exp.e1.type.toBasetype(); 10940 Type t2 = exp.e2.type.toBasetype(); 10941 10942 bool needsDirectEq(Type t1, Type t2) 10943 { 10944 Type t1n = t1.nextOf().toBasetype(); 10945 Type t2n = t2.nextOf().toBasetype(); 10946 if ((t1n.ty.isSomeChar && t2n.ty.isSomeChar) || 10947 (t1n.ty == Tvoid || t2n.ty == Tvoid)) 10948 { 10949 return false; 10950 } 10951 if (t1n.constOf() != t2n.constOf()) 10952 return true; 10953 10954 Type t = t1n; 10955 while (t.toBasetype().nextOf()) 10956 t = t.nextOf().toBasetype(); 10957 if (t.ty != Tstruct) 10958 return false; 10959 10960 if (global.params.useTypeInfo && Type.dtypeinfo) 10961 semanticTypeInfo(sc, t); 10962 10963 return (cast(TypeStruct)t).sym.hasIdentityEquals; 10964 } 10965 10966 if (auto e = exp.op_overload(sc)) 10967 { 10968 result = e; 10969 return; 10970 } 10971 10972 10973 if (!(t1.ty == Tarray && t2.ty == Tarray && needsDirectEq(t1, t2))) 10974 { 10975 if (auto e = typeCombine(exp, sc)) 10976 { 10977 result = e; 10978 return; 10979 } 10980 } 10981 10982 auto f1 = checkNonAssignmentArrayOp(exp.e1); 10983 auto f2 = checkNonAssignmentArrayOp(exp.e2); 10984 if (f1 || f2) 10985 return setError(); 10986 10987 exp.type = Type.tbool; 10988 10989 // Special handling for array comparisons 10990 if (!(t1.ty == Tarray && t2.ty == Tarray && needsDirectEq(t1, t2))) 10991 { 10992 if (!arrayTypeCompatible(exp.loc, exp.e1.type, exp.e2.type)) 10993 { 10994 if (exp.e1.type != exp.e2.type && exp.e1.type.isfloating() && exp.e2.type.isfloating()) 10995 { 10996 // Cast both to complex 10997 exp.e1 = exp.e1.castTo(sc, Type.tcomplex80); 10998 exp.e2 = exp.e2.castTo(sc, Type.tcomplex80); 10999 } 11000 } 11001 } 11002 11003 if (t1.ty == Tarray && t2.ty == Tarray) 11004 { 11005 //printf("Lowering to __equals %s %s\n", e1.toChars(), e2.toChars()); 11006 11007 // For e1 and e2 of struct type, lowers e1 == e2 to object.__equals(e1, e2) 11008 // and e1 != e2 to !(object.__equals(e1, e2)). 11009 11010 if (!verifyHookExist(exp.loc, *sc, Id.__equals, "equal checks on arrays")) 11011 return setError(); 11012 11013 Expression __equals = new IdentifierExp(exp.loc, Id.empty); 11014 Identifier id = Identifier.idPool("__equals"); 11015 __equals = new DotIdExp(exp.loc, __equals, Id.object); 11016 __equals = new DotIdExp(exp.loc, __equals, id); 11017 11018 auto arguments = new Expressions(2); 11019 (*arguments)[0] = exp.e1; 11020 (*arguments)[1] = exp.e2; 11021 11022 __equals = new CallExp(exp.loc, __equals, arguments); 11023 if (exp.op == TOK.notEqual) 11024 { 11025 __equals = new NotExp(exp.loc, __equals); 11026 } 11027 __equals = __equals.expressionSemantic(sc); 11028 11029 result = __equals; 11030 return; 11031 } 11032 11033 if (exp.e1.type.toBasetype().ty == Taarray) 11034 semanticTypeInfo(sc, exp.e1.type.toBasetype()); 11035 11036 11037 if (!target.isVectorOpSupported(t1, exp.op, t2)) 11038 { 11039 result = exp.incompatibleTypes(); 11040 return; 11041 } 11042 11043 result = exp; 11044 } 11045 11046 override void visit(IdentityExp exp) 11047 { 11048 if (exp.type) 11049 { 11050 result = exp; 11051 return; 11052 } 11053 11054 exp.setNoderefOperands(); 11055 11056 if (auto e = binSemanticProp(exp, sc)) 11057 { 11058 result = e; 11059 return; 11060 } 11061 11062 if (auto e = typeCombine(exp, sc)) 11063 { 11064 result = e; 11065 return; 11066 } 11067 11068 auto f1 = checkNonAssignmentArrayOp(exp.e1); 11069 auto f2 = checkNonAssignmentArrayOp(exp.e2); 11070 if (f1 || f2) 11071 return setError(); 11072 11073 if (exp.e1.op == TOK.type || exp.e2.op == TOK.type) 11074 { 11075 result = exp.incompatibleTypes(); 11076 return; 11077 } 11078 11079 exp.type = Type.tbool; 11080 11081 if (exp.e1.type != exp.e2.type && exp.e1.type.isfloating() && exp.e2.type.isfloating()) 11082 { 11083 // Cast both to complex 11084 exp.e1 = exp.e1.castTo(sc, Type.tcomplex80); 11085 exp.e2 = exp.e2.castTo(sc, Type.tcomplex80); 11086 } 11087 11088 auto tb1 = exp.e1.type.toBasetype(); 11089 auto tb2 = exp.e2.type.toBasetype(); 11090 if (!target.isVectorOpSupported(tb1, exp.op, tb2)) 11091 { 11092 result = exp.incompatibleTypes(); 11093 return; 11094 } 11095 11096 if (exp.e1.op == TOK.call) 11097 exp.e1 = (cast(CallExp)exp.e1).addDtorHook(sc); 11098 if (exp.e2.op == TOK.call) 11099 exp.e2 = (cast(CallExp)exp.e2).addDtorHook(sc); 11100 11101 if (exp.e1.type.toBasetype().ty == Tsarray || 11102 exp.e2.type.toBasetype().ty == Tsarray) 11103 exp.deprecation("identity comparison of static arrays " 11104 ~ "implicitly coerces them to slices, " 11105 ~ "which are compared by reference"); 11106 11107 result = exp; 11108 } 11109 11110 override void visit(CondExp exp) 11111 { 11112 static if (LOGSEMANTIC) 11113 { 11114 printf("CondExp::semantic('%s')\n", exp.toChars()); 11115 } 11116 if (exp.type) 11117 { 11118 result = exp; 11119 return; 11120 } 11121 11122 if (exp.econd.op == TOK.dotIdentifier) 11123 (cast(DotIdExp)exp.econd).noderef = true; 11124 11125 Expression ec = exp.econd.expressionSemantic(sc); 11126 ec = resolveProperties(sc, ec); 11127 ec = ec.toBoolean(sc); 11128 11129 CtorFlow ctorflow_root = sc.ctorflow.clone(); 11130 Expression e1x = exp.e1.expressionSemantic(sc); 11131 e1x = resolveProperties(sc, e1x); 11132 11133 CtorFlow ctorflow1 = sc.ctorflow; 11134 sc.ctorflow = ctorflow_root; 11135 Expression e2x = exp.e2.expressionSemantic(sc); 11136 e2x = resolveProperties(sc, e2x); 11137 11138 sc.merge(exp.loc, ctorflow1); 11139 ctorflow1.freeFieldinit(); 11140 11141 if (ec.op == TOK.error) 11142 { 11143 result = ec; 11144 return; 11145 } 11146 if (ec.type == Type.terror) 11147 return setError(); 11148 exp.econd = ec; 11149 11150 if (e1x.op == TOK.error) 11151 { 11152 result = e1x; 11153 return; 11154 } 11155 if (e1x.type == Type.terror) 11156 return setError(); 11157 exp.e1 = e1x; 11158 11159 if (e2x.op == TOK.error) 11160 { 11161 result = e2x; 11162 return; 11163 } 11164 if (e2x.type == Type.terror) 11165 return setError(); 11166 exp.e2 = e2x; 11167 11168 auto f0 = checkNonAssignmentArrayOp(exp.econd); 11169 auto f1 = checkNonAssignmentArrayOp(exp.e1); 11170 auto f2 = checkNonAssignmentArrayOp(exp.e2); 11171 if (f0 || f1 || f2) 11172 return setError(); 11173 11174 Type t1 = exp.e1.type; 11175 Type t2 = exp.e2.type; 11176 // If either operand is void the result is void, we have to cast both 11177 // the expression to void so that we explicitly discard the expression 11178 // value if any 11179 // https://issues.dlang.org/show_bug.cgi?id=16598 11180 if (t1.ty == Tvoid || t2.ty == Tvoid) 11181 { 11182 exp.type = Type.tvoid; 11183 exp.e1 = exp.e1.castTo(sc, exp.type); 11184 exp.e2 = exp.e2.castTo(sc, exp.type); 11185 } 11186 else if (t1 == t2) 11187 exp.type = t1; 11188 else 11189 { 11190 if (Expression ex = typeCombine(exp, sc)) 11191 { 11192 result = ex; 11193 return; 11194 } 11195 11196 switch (exp.e1.type.toBasetype().ty) 11197 { 11198 case Tcomplex32: 11199 case Tcomplex64: 11200 case Tcomplex80: 11201 exp.e2 = exp.e2.castTo(sc, exp.e1.type); 11202 break; 11203 default: 11204 break; 11205 } 11206 switch (exp.e2.type.toBasetype().ty) 11207 { 11208 case Tcomplex32: 11209 case Tcomplex64: 11210 case Tcomplex80: 11211 exp.e1 = exp.e1.castTo(sc, exp.e2.type); 11212 break; 11213 default: 11214 break; 11215 } 11216 if (exp.type.toBasetype().ty == Tarray) 11217 { 11218 exp.e1 = exp.e1.castTo(sc, exp.type); 11219 exp.e2 = exp.e2.castTo(sc, exp.type); 11220 } 11221 } 11222 exp.type = exp.type.merge2(); 11223 version (none) 11224 { 11225 printf("res: %s\n", exp.type.toChars()); 11226 printf("e1 : %s\n", exp.e1.type.toChars()); 11227 printf("e2 : %s\n", exp.e2.type.toChars()); 11228 } 11229 11230 /* https://issues.dlang.org/show_bug.cgi?id=14696 11231 * If either e1 or e2 contain temporaries which need dtor, 11232 * make them conditional. 11233 * Rewrite: 11234 * cond ? (__tmp1 = ..., __tmp1) : (__tmp2 = ..., __tmp2) 11235 * to: 11236 * (auto __cond = cond) ? (... __tmp1) : (... __tmp2) 11237 * and replace edtors of __tmp1 and __tmp2 with: 11238 * __tmp1.edtor --> __cond && __tmp1.dtor() 11239 * __tmp2.edtor --> __cond || __tmp2.dtor() 11240 */ 11241 exp.hookDtors(sc); 11242 11243 result = exp; 11244 } 11245 11246 override void visit(FileInitExp e) 11247 { 11248 //printf("FileInitExp::semantic()\n"); 11249 e.type = Type.tstring; 11250 result = e; 11251 } 11252 11253 override void visit(LineInitExp e) 11254 { 11255 e.type = Type.tint32; 11256 result = e; 11257 } 11258 11259 override void visit(ModuleInitExp e) 11260 { 11261 //printf("ModuleInitExp::semantic()\n"); 11262 e.type = Type.tstring; 11263 result = e; 11264 } 11265 11266 override void visit(FuncInitExp e) 11267 { 11268 //printf("FuncInitExp::semantic()\n"); 11269 e.type = Type.tstring; 11270 if (sc.func) 11271 { 11272 result = e.resolveLoc(Loc.initial, sc); 11273 return; 11274 } 11275 result = e; 11276 } 11277 11278 override void visit(PrettyFuncInitExp e) 11279 { 11280 //printf("PrettyFuncInitExp::semantic()\n"); 11281 e.type = Type.tstring; 11282 if (sc.func) 11283 { 11284 result = e.resolveLoc(Loc.initial, sc); 11285 return; 11286 } 11287 11288 result = e; 11289 } 11290 } 11291 11292 /********************************** 11293 * Try to run semantic routines. 11294 * If they fail, return NULL. 11295 */ 11296 Expression trySemantic(Expression exp, Scope* sc) 11297 { 11298 //printf("+trySemantic(%s)\n", exp.toChars()); 11299 uint errors = global.startGagging(); 11300 Expression e = expressionSemantic(exp, sc); 11301 if (global.endGagging(errors)) 11302 { 11303 e = null; 11304 } 11305 //printf("-trySemantic(%s)\n", exp.toChars()); 11306 return e; 11307 } 11308 11309 /************************** 11310 * Helper function for easy error propagation. 11311 * If error occurs, returns ErrorExp. Otherwise returns NULL. 11312 */ 11313 Expression unaSemantic(UnaExp e, Scope* sc) 11314 { 11315 static if (LOGSEMANTIC) 11316 { 11317 printf("UnaExp::semantic('%s')\n", e.toChars()); 11318 } 11319 Expression e1x = e.e1.expressionSemantic(sc); 11320 if (e1x.op == TOK.error) 11321 return e1x; 11322 e.e1 = e1x; 11323 return null; 11324 } 11325 11326 /************************** 11327 * Helper function for easy error propagation. 11328 * If error occurs, returns ErrorExp. Otherwise returns NULL. 11329 */ 11330 Expression binSemantic(BinExp e, Scope* sc) 11331 { 11332 static if (LOGSEMANTIC) 11333 { 11334 printf("BinExp::semantic('%s')\n", e.toChars()); 11335 } 11336 Expression e1x = e.e1.expressionSemantic(sc); 11337 Expression e2x = e.e2.expressionSemantic(sc); 11338 11339 // for static alias this: https://issues.dlang.org/show_bug.cgi?id=17684 11340 if (e1x.op == TOK.type) 11341 e1x = resolveAliasThis(sc, e1x); 11342 if (e2x.op == TOK.type) 11343 e2x = resolveAliasThis(sc, e2x); 11344 11345 if (e1x.op == TOK.error) 11346 return e1x; 11347 if (e2x.op == TOK.error) 11348 return e2x; 11349 e.e1 = e1x; 11350 e.e2 = e2x; 11351 return null; 11352 } 11353 11354 Expression binSemanticProp(BinExp e, Scope* sc) 11355 { 11356 if (Expression ex = binSemantic(e, sc)) 11357 return ex; 11358 Expression e1x = resolveProperties(sc, e.e1); 11359 Expression e2x = resolveProperties(sc, e.e2); 11360 if (e1x.op == TOK.error) 11361 return e1x; 11362 if (e2x.op == TOK.error) 11363 return e2x; 11364 e.e1 = e1x; 11365 e.e2 = e2x; 11366 return null; 11367 } 11368 11369 // entrypoint for semantic ExpressionSemanticVisitor 11370 extern (C++) Expression expressionSemantic(Expression e, Scope* sc) 11371 { 11372 scope v = new ExpressionSemanticVisitor(sc); 11373 e.accept(v); 11374 return v.result; 11375 } 11376 11377 Expression semanticX(DotIdExp exp, Scope* sc) 11378 { 11379 //printf("DotIdExp::semanticX(this = %p, '%s')\n", this, toChars()); 11380 if (Expression ex = unaSemantic(exp, sc)) 11381 return ex; 11382 11383 if (exp.ident == Id._mangleof) 11384 { 11385 // symbol.mangleof 11386 Dsymbol ds; 11387 switch (exp.e1.op) 11388 { 11389 case TOK.scope_: 11390 ds = (cast(ScopeExp)exp.e1).sds; 11391 goto L1; 11392 case TOK.variable: 11393 ds = (cast(VarExp)exp.e1).var; 11394 goto L1; 11395 case TOK.dotVariable: 11396 ds = (cast(DotVarExp)exp.e1).var; 11397 goto L1; 11398 case TOK.overloadSet: 11399 ds = (cast(OverExp)exp.e1).vars; 11400 goto L1; 11401 case TOK.template_: 11402 { 11403 TemplateExp te = cast(TemplateExp)exp.e1; 11404 ds = te.fd ? cast(Dsymbol)te.fd : te.td; 11405 } 11406 L1: 11407 { 11408 assert(ds); 11409 if (auto f = ds.isFuncDeclaration()) 11410 { 11411 if (f.checkForwardRef(exp.loc)) 11412 { 11413 return new ErrorExp(); 11414 } 11415 if (f.flags & (FUNCFLAG.purityInprocess | FUNCFLAG.safetyInprocess | 11416 FUNCFLAG.nothrowInprocess | FUNCFLAG.nogcInprocess)) 11417 { 11418 f.error(exp.loc, "cannot retrieve its `.mangleof` while inferring attributes"); 11419 return new ErrorExp(); 11420 } 11421 } 11422 OutBuffer buf; 11423 mangleToBuffer(ds, &buf); 11424 Expression e = new StringExp(exp.loc, buf.extractSlice()); 11425 e = e.expressionSemantic(sc); 11426 return e; 11427 } 11428 default: 11429 break; 11430 } 11431 } 11432 11433 if (exp.e1.op == TOK.variable && exp.e1.type.toBasetype().ty == Tsarray && exp.ident == Id.length) 11434 { 11435 // bypass checkPurity 11436 return exp.e1.type.dotExp(sc, exp.e1, exp.ident, exp.noderef ? DotExpFlag.noDeref : 0); 11437 } 11438 11439 if (exp.e1.op == TOK.dot) 11440 { 11441 } 11442 else 11443 { 11444 exp.e1 = resolvePropertiesX(sc, exp.e1); 11445 } 11446 if (exp.e1.op == TOK.tuple && exp.ident == Id.offsetof) 11447 { 11448 /* 'distribute' the .offsetof to each of the tuple elements. 11449 */ 11450 TupleExp te = cast(TupleExp)exp.e1; 11451 auto exps = new Expressions(te.exps.dim); 11452 for (size_t i = 0; i < exps.dim; i++) 11453 { 11454 Expression e = (*te.exps)[i]; 11455 e = e.expressionSemantic(sc); 11456 e = new DotIdExp(e.loc, e, Id.offsetof); 11457 (*exps)[i] = e; 11458 } 11459 // Don't evaluate te.e0 in runtime 11460 Expression e = new TupleExp(exp.loc, null, exps); 11461 e = e.expressionSemantic(sc); 11462 return e; 11463 } 11464 if (exp.e1.op == TOK.tuple && exp.ident == Id.length) 11465 { 11466 TupleExp te = cast(TupleExp)exp.e1; 11467 // Don't evaluate te.e0 in runtime 11468 Expression e = new IntegerExp(exp.loc, te.exps.dim, Type.tsize_t); 11469 return e; 11470 } 11471 11472 // https://issues.dlang.org/show_bug.cgi?id=14416 11473 // Template has no built-in properties except for 'stringof'. 11474 if ((exp.e1.op == TOK.dotTemplateDeclaration || exp.e1.op == TOK.template_) && exp.ident != Id.stringof) 11475 { 11476 exp.error("template `%s` does not have property `%s`", exp.e1.toChars(), exp.ident.toChars()); 11477 return new ErrorExp(); 11478 } 11479 if (!exp.e1.type) 11480 { 11481 exp.error("expression `%s` does not have property `%s`", exp.e1.toChars(), exp.ident.toChars()); 11482 return new ErrorExp(); 11483 } 11484 11485 return exp; 11486 } 11487 11488 // Resolve e1.ident without seeing UFCS. 11489 // If flag == 1, stop "not a property" error and return NULL. 11490 Expression semanticY(DotIdExp exp, Scope* sc, int flag) 11491 { 11492 //printf("DotIdExp::semanticY(this = %p, '%s')\n", exp, exp.toChars()); 11493 11494 //{ static int z; fflush(stdout); if (++z == 10) *(char*)0=0; } 11495 11496 /* Special case: rewrite this.id and super.id 11497 * to be classtype.id and baseclasstype.id 11498 * if we have no this pointer. 11499 */ 11500 if ((exp.e1.op == TOK.this_ || exp.e1.op == TOK.super_) && !hasThis(sc)) 11501 { 11502 if (AggregateDeclaration ad = sc.getStructClassScope()) 11503 { 11504 if (exp.e1.op == TOK.this_) 11505 { 11506 exp.e1 = new TypeExp(exp.e1.loc, ad.type); 11507 } 11508 else 11509 { 11510 ClassDeclaration cd = ad.isClassDeclaration(); 11511 if (cd && cd.baseClass) 11512 exp.e1 = new TypeExp(exp.e1.loc, cd.baseClass.type); 11513 } 11514 } 11515 } 11516 11517 Expression e = semanticX(exp, sc); 11518 if (e != exp) 11519 return e; 11520 11521 Expression eleft; 11522 Expression eright; 11523 if (exp.e1.op == TOK.dot) 11524 { 11525 DotExp de = cast(DotExp)exp.e1; 11526 eleft = de.e1; 11527 eright = de.e2; 11528 } 11529 else 11530 { 11531 eleft = null; 11532 eright = exp.e1; 11533 } 11534 11535 Type t1b = exp.e1.type.toBasetype(); 11536 11537 if (eright.op == TOK.scope_) // also used for template alias's 11538 { 11539 ScopeExp ie = cast(ScopeExp)eright; 11540 11541 int flags = SearchLocalsOnly; 11542 /* Disable access to another module's private imports. 11543 * The check for 'is sds our current module' is because 11544 * the current module should have access to its own imports. 11545 */ 11546 if (ie.sds.isModule() && ie.sds != sc._module) 11547 flags |= IgnorePrivateImports; 11548 if (sc.flags & SCOPE.ignoresymbolvisibility) 11549 flags |= IgnoreSymbolVisibility; 11550 Dsymbol s = ie.sds.search(exp.loc, exp.ident, flags); 11551 /* Check for visibility before resolving aliases because public 11552 * aliases to private symbols are public. 11553 */ 11554 if (s && !(sc.flags & SCOPE.ignoresymbolvisibility) && !symbolIsVisible(sc._module, s)) 11555 { 11556 s = null; 11557 } 11558 if (s) 11559 { 11560 auto p = s.isPackage(); 11561 if (p && checkAccess(sc, p)) 11562 { 11563 s = null; 11564 } 11565 } 11566 if (s) 11567 { 11568 // if 's' is a tuple variable, the tuple is returned. 11569 s = s.toAlias(); 11570 11571 exp.checkDeprecated(sc, s); 11572 exp.checkDisabled(sc, s); 11573 11574 EnumMember em = s.isEnumMember(); 11575 if (em) 11576 { 11577 return em.getVarExp(exp.loc, sc); 11578 } 11579 VarDeclaration v = s.isVarDeclaration(); 11580 if (v) 11581 { 11582 //printf("DotIdExp:: Identifier '%s' is a variable, type '%s'\n", toChars(), v.type.toChars()); 11583 if (!v.type || 11584 !v.type.deco && v.inuse) 11585 { 11586 if (v.inuse) 11587 exp.error("circular reference to %s `%s`", v.kind(), v.toPrettyChars()); 11588 else 11589 exp.error("forward reference to %s `%s`", v.kind(), v.toPrettyChars()); 11590 return new ErrorExp(); 11591 } 11592 if (v.type.ty == Terror) 11593 return new ErrorExp(); 11594 11595 if ((v.storage_class & STC.manifest) && v._init && !exp.wantsym) 11596 { 11597 /* Normally, the replacement of a symbol with its initializer is supposed to be in semantic2(). 11598 * Introduced by https://github.com/dlang/dmd/pull/5588 which should probably 11599 * be reverted. `wantsym` is the hack to work around the problem. 11600 */ 11601 if (v.inuse) 11602 { 11603 error(exp.loc, "circular initialization of %s `%s`", v.kind(), v.toPrettyChars()); 11604 return new ErrorExp(); 11605 } 11606 e = v.expandInitializer(exp.loc); 11607 v.inuse++; 11608 e = e.expressionSemantic(sc); 11609 v.inuse--; 11610 return e; 11611 } 11612 11613 if (v.needThis()) 11614 { 11615 if (!eleft) 11616 eleft = new ThisExp(exp.loc); 11617 e = new DotVarExp(exp.loc, eleft, v); 11618 e = e.expressionSemantic(sc); 11619 } 11620 else 11621 { 11622 e = new VarExp(exp.loc, v); 11623 if (eleft) 11624 { 11625 e = new CommaExp(exp.loc, eleft, e); 11626 e.type = v.type; 11627 } 11628 } 11629 e = e.deref(); 11630 return e.expressionSemantic(sc); 11631 } 11632 11633 FuncDeclaration f = s.isFuncDeclaration(); 11634 if (f) 11635 { 11636 //printf("it's a function\n"); 11637 if (!f.functionSemantic()) 11638 return new ErrorExp(); 11639 if (f.needThis()) 11640 { 11641 if (!eleft) 11642 eleft = new ThisExp(exp.loc); 11643 e = new DotVarExp(exp.loc, eleft, f, true); 11644 e = e.expressionSemantic(sc); 11645 } 11646 else 11647 { 11648 e = new VarExp(exp.loc, f, true); 11649 if (eleft) 11650 { 11651 e = new CommaExp(exp.loc, eleft, e); 11652 e.type = f.type; 11653 } 11654 } 11655 return e; 11656 } 11657 if (auto td = s.isTemplateDeclaration()) 11658 { 11659 if (eleft) 11660 e = new DotTemplateExp(exp.loc, eleft, td); 11661 else 11662 e = new TemplateExp(exp.loc, td); 11663 e = e.expressionSemantic(sc); 11664 return e; 11665 } 11666 if (OverDeclaration od = s.isOverDeclaration()) 11667 { 11668 e = new VarExp(exp.loc, od, true); 11669 if (eleft) 11670 { 11671 e = new CommaExp(exp.loc, eleft, e); 11672 e.type = Type.tvoid; // ambiguous type? 11673 } 11674 return e; 11675 } 11676 OverloadSet o = s.isOverloadSet(); 11677 if (o) 11678 { 11679 //printf("'%s' is an overload set\n", o.toChars()); 11680 return new OverExp(exp.loc, o); 11681 } 11682 11683 if (auto t = s.getType()) 11684 { 11685 return (new TypeExp(exp.loc, t)).expressionSemantic(sc); 11686 } 11687 11688 TupleDeclaration tup = s.isTupleDeclaration(); 11689 if (tup) 11690 { 11691 if (eleft) 11692 { 11693 e = new DotVarExp(exp.loc, eleft, tup); 11694 e = e.expressionSemantic(sc); 11695 return e; 11696 } 11697 e = new TupleExp(exp.loc, tup); 11698 e = e.expressionSemantic(sc); 11699 return e; 11700 } 11701 11702 ScopeDsymbol sds = s.isScopeDsymbol(); 11703 if (sds) 11704 { 11705 //printf("it's a ScopeDsymbol %s\n", ident.toChars()); 11706 e = new ScopeExp(exp.loc, sds); 11707 e = e.expressionSemantic(sc); 11708 if (eleft) 11709 e = new DotExp(exp.loc, eleft, e); 11710 return e; 11711 } 11712 11713 Import imp = s.isImport(); 11714 if (imp) 11715 { 11716 ie = new ScopeExp(exp.loc, imp.pkg); 11717 return ie.expressionSemantic(sc); 11718 } 11719 // BUG: handle other cases like in IdentifierExp::semantic() 11720 debug 11721 { 11722 printf("s = '%s', kind = '%s'\n", s.toChars(), s.kind()); 11723 } 11724 assert(0); 11725 } 11726 else if (exp.ident == Id.stringof) 11727 { 11728 e = new StringExp(exp.loc, ie.toString()); 11729 e = e.expressionSemantic(sc); 11730 return e; 11731 } 11732 if (ie.sds.isPackage() || ie.sds.isImport() || ie.sds.isModule()) 11733 { 11734 flag = 0; 11735 } 11736 if (flag) 11737 return null; 11738 s = ie.sds.search_correct(exp.ident); 11739 if (s && symbolIsVisible(sc, s)) 11740 { 11741 if (s.isPackage()) 11742 exp.error("undefined identifier `%s` in %s `%s`, perhaps add `static import %s;`", exp.ident.toChars(), ie.sds.kind(), ie.sds.toPrettyChars(), s.toPrettyChars()); 11743 else 11744 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()); 11745 } 11746 else 11747 exp.error("undefined identifier `%s` in %s `%s`", exp.ident.toChars(), ie.sds.kind(), ie.sds.toPrettyChars()); 11748 return new ErrorExp(); 11749 } 11750 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) 11751 { 11752 Type t1bn = t1b.nextOf(); 11753 if (flag) 11754 { 11755 AggregateDeclaration ad = isAggregate(t1bn); 11756 if (ad && !ad.members) // https://issues.dlang.org/show_bug.cgi?id=11312 11757 return null; 11758 } 11759 11760 /* Rewrite: 11761 * p.ident 11762 * as: 11763 * (*p).ident 11764 */ 11765 if (flag && t1bn.ty == Tvoid) 11766 return null; 11767 e = new PtrExp(exp.loc, exp.e1); 11768 e = e.expressionSemantic(sc); 11769 return e.type.dotExp(sc, e, exp.ident, flag | (exp.noderef ? DotExpFlag.noDeref : 0)); 11770 } 11771 else 11772 { 11773 if (exp.e1.op == TOK.type || exp.e1.op == TOK.template_) 11774 flag = 0; 11775 e = exp.e1.type.dotExp(sc, exp.e1, exp.ident, flag | (exp.noderef ? DotExpFlag.noDeref : 0)); 11776 if (e) 11777 e = e.expressionSemantic(sc); 11778 return e; 11779 } 11780 } 11781 11782 // Resolve e1.ident!tiargs without seeing UFCS. 11783 // If flag == 1, stop "not a property" error and return NULL. 11784 Expression semanticY(DotTemplateInstanceExp exp, Scope* sc, int flag) 11785 { 11786 static if (LOGSEMANTIC) 11787 { 11788 printf("DotTemplateInstanceExpY::semantic('%s')\n", exp.toChars()); 11789 } 11790 11791 static Expression errorExp() 11792 { 11793 return new ErrorExp(); 11794 } 11795 11796 auto die = new DotIdExp(exp.loc, exp.e1, exp.ti.name); 11797 11798 Expression e = die.semanticX(sc); 11799 if (e == die) 11800 { 11801 exp.e1 = die.e1; // take back 11802 Type t1b = exp.e1.type.toBasetype(); 11803 if (t1b.ty == Tarray || t1b.ty == Tsarray || t1b.ty == Taarray || t1b.ty == Tnull || (t1b.isTypeBasic() && t1b.ty != Tvoid)) 11804 { 11805 /* No built-in type has templatized properties, so do shortcut. 11806 * It is necessary in: 1024.max!"a < b" 11807 */ 11808 if (flag) 11809 return null; 11810 } 11811 e = die.semanticY(sc, flag); 11812 if (flag) 11813 { 11814 if (!e || 11815 isDotOpDispatch(e)) 11816 { 11817 /* opDispatch!tiargs would be a function template that needs IFTI, 11818 * so it's not a template 11819 */ 11820 return null; 11821 } 11822 } 11823 } 11824 assert(e); 11825 11826 if (e.op == TOK.error) 11827 return e; 11828 if (e.op == TOK.dotVariable) 11829 { 11830 DotVarExp dve = cast(DotVarExp)e; 11831 if (FuncDeclaration fd = dve.var.isFuncDeclaration()) 11832 { 11833 if (TemplateDeclaration td = fd.findTemplateDeclRoot()) 11834 { 11835 e = new DotTemplateExp(dve.loc, dve.e1, td); 11836 e = e.expressionSemantic(sc); 11837 } 11838 } 11839 else if (OverDeclaration od = dve.var.isOverDeclaration()) 11840 { 11841 exp.e1 = dve.e1; // pull semantic() result 11842 11843 if (!exp.findTempDecl(sc)) 11844 goto Lerr; 11845 if (exp.ti.needsTypeInference(sc)) 11846 return exp; 11847 exp.ti.dsymbolSemantic(sc); 11848 if (!exp.ti.inst || exp.ti.errors) // if template failed to expand 11849 return errorExp(); 11850 11851 if (Declaration v = exp.ti.toAlias().isDeclaration()) 11852 { 11853 if (v.type && !v.type.deco) 11854 v.type = v.type.typeSemantic(v.loc, sc); 11855 return new DotVarExp(exp.loc, exp.e1, v) 11856 .expressionSemantic(sc); 11857 } 11858 return new DotExp(exp.loc, exp.e1, new ScopeExp(exp.loc, exp.ti)) 11859 .expressionSemantic(sc); 11860 } 11861 } 11862 else if (e.op == TOK.variable) 11863 { 11864 VarExp ve = cast(VarExp)e; 11865 if (FuncDeclaration fd = ve.var.isFuncDeclaration()) 11866 { 11867 if (TemplateDeclaration td = fd.findTemplateDeclRoot()) 11868 { 11869 e = new TemplateExp(ve.loc, td) 11870 .expressionSemantic(sc); 11871 } 11872 } 11873 else if (OverDeclaration od = ve.var.isOverDeclaration()) 11874 { 11875 exp.ti.tempdecl = od; 11876 return new ScopeExp(exp.loc, exp.ti) 11877 .expressionSemantic(sc); 11878 } 11879 } 11880 11881 if (e.op == TOK.dotTemplateDeclaration) 11882 { 11883 DotTemplateExp dte = cast(DotTemplateExp)e; 11884 exp.e1 = dte.e1; // pull semantic() result 11885 11886 exp.ti.tempdecl = dte.td; 11887 if (!exp.ti.semanticTiargs(sc)) 11888 return errorExp(); 11889 if (exp.ti.needsTypeInference(sc)) 11890 return exp; 11891 exp.ti.dsymbolSemantic(sc); 11892 if (!exp.ti.inst || exp.ti.errors) // if template failed to expand 11893 return errorExp(); 11894 11895 if (Declaration v = exp.ti.toAlias().isDeclaration()) 11896 { 11897 if (v.isFuncDeclaration() || v.isVarDeclaration()) 11898 { 11899 return new DotVarExp(exp.loc, exp.e1, v) 11900 .expressionSemantic(sc); 11901 } 11902 } 11903 return new DotExp(exp.loc, exp.e1, new ScopeExp(exp.loc, exp.ti)) 11904 .expressionSemantic(sc); 11905 } 11906 else if (e.op == TOK.template_) 11907 { 11908 exp.ti.tempdecl = (cast(TemplateExp)e).td; 11909 return new ScopeExp(exp.loc, exp.ti) 11910 .expressionSemantic(sc); 11911 } 11912 else if (e.op == TOK.dot) 11913 { 11914 DotExp de = cast(DotExp)e; 11915 11916 if (de.e2.op == TOK.overloadSet) 11917 { 11918 if (!exp.findTempDecl(sc) || !exp.ti.semanticTiargs(sc)) 11919 { 11920 return errorExp(); 11921 } 11922 if (exp.ti.needsTypeInference(sc)) 11923 return exp; 11924 exp.ti.dsymbolSemantic(sc); 11925 if (!exp.ti.inst || exp.ti.errors) // if template failed to expand 11926 return errorExp(); 11927 11928 if (Declaration v = exp.ti.toAlias().isDeclaration()) 11929 { 11930 if (v.type && !v.type.deco) 11931 v.type = v.type.typeSemantic(v.loc, sc); 11932 return new DotVarExp(exp.loc, exp.e1, v) 11933 .expressionSemantic(sc); 11934 } 11935 return new DotExp(exp.loc, exp.e1, new ScopeExp(exp.loc, exp.ti)) 11936 .expressionSemantic(sc); 11937 } 11938 } 11939 else if (e.op == TOK.overloadSet) 11940 { 11941 OverExp oe = cast(OverExp)e; 11942 exp.ti.tempdecl = oe.vars; 11943 return new ScopeExp(exp.loc, exp.ti) 11944 .expressionSemantic(sc); 11945 } 11946 11947 Lerr: 11948 exp.error("`%s` isn't a template", e.toChars()); 11949 return errorExp(); 11950 } 11951 11952 /*************************************** 11953 * If expression is shared, check that we can access it. 11954 * Give error message if not. 11955 * Params: 11956 * e = expression to check 11957 * sc = context 11958 * Returns: 11959 * true on error 11960 */ 11961 bool checkSharedAccess(Expression e, Scope* sc) 11962 { 11963 if (!global.params.noSharedAccess || 11964 sc.intypeof || 11965 sc.flags & SCOPE.ctfe) 11966 { 11967 return false; 11968 } 11969 11970 //printf("checkSharedAccess() %s\n", e.toChars()); 11971 11972 static bool check(Expression e) 11973 { 11974 static bool sharedError(Expression e) 11975 { 11976 // https://dlang.org/phobos/core_atomic.html 11977 e.error("direct access to shared `%s` is not allowed, see `core.atomic`", e.toChars()); 11978 return true; 11979 } 11980 11981 bool visitVar(VarExp ve) 11982 { 11983 return ve.var.type.isShared() ? sharedError(ve) : false; 11984 } 11985 11986 bool visitPtr(PtrExp pe) 11987 { 11988 return pe.e1.type.nextOf().isShared() ? sharedError(pe) : false; 11989 } 11990 11991 bool visitDotVar(DotVarExp dve) 11992 { 11993 return dve.var.type.isShared() || check(dve.e1) ? sharedError(dve) : false; 11994 } 11995 11996 bool visitIndex(IndexExp ie) 11997 { 11998 return ie.e1.type.nextOf().isShared() ? sharedError(ie) : false; 11999 } 12000 12001 bool visitComma(CommaExp ce) 12002 { 12003 return check(ce.e2); 12004 } 12005 12006 switch (e.op) 12007 { 12008 case TOK.variable: return visitVar(e.isVarExp()); 12009 case TOK.star: return visitPtr(e.isPtrExp()); 12010 case TOK.dotVariable: return visitDotVar(e.isDotVarExp()); 12011 case TOK.index: return visitIndex(e.isIndexExp()); 12012 case TOK.comma: return visitComma(e.isCommaExp()); 12013 default: 12014 return false; 12015 } 12016 } 12017 12018 return check(e); 12019 } 12020 12021 12022 12023 /**************************************************** 12024 * Determine if `exp`, which takes the address of `v`, can do so safely. 12025 * Params: 12026 * sc = context 12027 * exp = expression that takes the address of `v` 12028 * v = the variable getting its address taken 12029 * Returns: 12030 * `true` if ok, `false` for error 12031 */ 12032 private bool checkAddressVar(Scope* sc, UnaExp exp, VarDeclaration v) 12033 { 12034 //printf("checkAddressVar(exp: %s, v: %s)\n", exp.toChars(), v.toChars()); 12035 if (v) 12036 { 12037 if (!v.canTakeAddressOf()) 12038 { 12039 exp.error("cannot take address of `%s`", exp.e1.toChars()); 12040 return false; 12041 } 12042 if (sc.func && !sc.intypeof && !v.isDataseg()) 12043 { 12044 const(char)* p = v.isParameter() ? "parameter" : "local"; 12045 if (global.params.vsafe) 12046 { 12047 // Taking the address of v means it cannot be set to 'scope' later 12048 v.storage_class &= ~STC.maybescope; 12049 v.doNotInferScope = true; 12050 if (exp.e1.type.hasPointers() && v.storage_class & STC.scope_ && 12051 !(sc.flags & SCOPE.debug_) && sc.func.setUnsafe()) 12052 { 12053 exp.error("cannot take address of `scope` %s `%s` in `@safe` function `%s`", p, v.toChars(), sc.func.toChars()); 12054 return false; 12055 } 12056 } 12057 else if (!(sc.flags & SCOPE.debug_) && sc.func.setUnsafe()) 12058 { 12059 exp.error("cannot take address of %s `%s` in `@safe` function `%s`", p, v.toChars(), sc.func.toChars()); 12060 return false; 12061 } 12062 } 12063 } 12064 return true; 12065 } 12066 12067 /******************************* 12068 * Checks the attributes of a function. 12069 * Purity (`pure`), safety (`@safe`), no GC allocations(`@nogc`) 12070 * and usage of `deprecated` and `@disabled`-ed symbols are checked. 12071 * 12072 * Params: 12073 * exp = expression to check attributes for 12074 * sc = scope of the function 12075 * f = function to be checked 12076 * Returns: `true` if error occur. 12077 */ 12078 private bool checkFunctionAttributes(Expression exp, Scope* sc, FuncDeclaration f) 12079 { 12080 with(exp) 12081 { 12082 bool error = checkDisabled(sc, f); 12083 error |= checkDeprecated(sc, f); 12084 error |= checkPurity(sc, f); 12085 error |= checkSafety(sc, f); 12086 error |= checkNogc(sc, f); 12087 return error; 12088 } 12089 } 12090 12091 /******************************* 12092 * Helper function for `getRightThis()`. 12093 * Gets `this` of the next outer aggregate. 12094 * Params: 12095 * loc = location to use for error messages 12096 * sc = context 12097 * s = the parent symbol of the existing `this` 12098 * ad = struct or class we need the correct `this` for 12099 * e1 = existing `this` 12100 * t = type of the existing `this` 12101 * var = the specific member of ad we're accessing 12102 * flag = if true, return `null` instead of throwing an error 12103 * Returns: 12104 * Expression representing the `this` for the var 12105 */ 12106 Expression getThisSkipNestedFuncs(const ref Loc loc, Scope* sc, Dsymbol s, AggregateDeclaration ad, Expression e1, Type t, Dsymbol var, bool flag = false) 12107 { 12108 int n = 0; 12109 while (s && s.isFuncDeclaration()) 12110 { 12111 FuncDeclaration f = s.isFuncDeclaration(); 12112 if (f.vthis) 12113 { 12114 n++; 12115 e1 = new VarExp(loc, f.vthis); 12116 if (f.isThis2) 12117 { 12118 // (*__this)[i] 12119 if (n > 1) 12120 e1 = e1.expressionSemantic(sc); 12121 e1 = new PtrExp(loc, e1); 12122 uint i = f.followInstantiationContext(ad); 12123 e1 = new IndexExp(loc, e1, new IntegerExp(i)); 12124 s = f.toParentP(ad); 12125 continue; 12126 } 12127 } 12128 else 12129 { 12130 if (flag) 12131 return null; 12132 e1.error("need `this` of type `%s` to access member `%s` from static function `%s`", ad.toChars(), var.toChars(), f.toChars()); 12133 e1 = new ErrorExp(); 12134 return e1; 12135 } 12136 s = s.toParent2(); 12137 } 12138 if (n > 1 || e1.op == TOK.index) 12139 e1 = e1.expressionSemantic(sc); 12140 if (s && e1.type.equivalent(Type.tvoidptr)) 12141 { 12142 if (auto sad = s.isAggregateDeclaration()) 12143 { 12144 Type ta = sad.handleType(); 12145 if (ta.ty == Tstruct) 12146 ta = ta.pointerTo(); 12147 e1.type = ta; 12148 } 12149 } 12150 e1.type = e1.type.addMod(t.mod); 12151 return e1; 12152 } 12153 12154 /******************************* 12155 * Make a dual-context container for use as a `this` argument. 12156 * Params: 12157 * loc = location to use for error messages 12158 * sc = current scope 12159 * fd = target function that will take the `this` argument 12160 * Returns: 12161 * Temporary closure variable. 12162 * Note: 12163 * The function `fd` is added to the nested references of the 12164 * newly created variable such that a closure is made for the variable when 12165 * the address of `fd` is taken. 12166 */ 12167 VarDeclaration makeThis2Argument(const ref Loc loc, Scope* sc, FuncDeclaration fd) 12168 { 12169 Type tthis2 = Type.tvoidptr.sarrayOf(2); 12170 VarDeclaration vthis2 = new VarDeclaration(loc, tthis2, Identifier.generateId("__this"), null); 12171 vthis2.storage_class |= STC.temp; 12172 vthis2.dsymbolSemantic(sc); 12173 vthis2.parent = sc.parent; 12174 // make it a closure var 12175 assert(sc.func); 12176 sc.func.closureVars.push(vthis2); 12177 // add `fd` to the nested refs 12178 vthis2.nestedrefs.push(fd); 12179 return vthis2; 12180 } 12181 12182 /******************************* 12183 * Make sure that the runtime hook `id` exists. 12184 * Params: 12185 * loc = location to use for error messages 12186 * sc = current scope 12187 * id = the hook identifier 12188 * description = what the hook does 12189 * module_ = what module the hook is located in 12190 * Returns: 12191 * a `bool` indicating if the hook is present. 12192 */ 12193 bool verifyHookExist(const ref Loc loc, ref Scope sc, Identifier id, string description, Identifier module_ = Id.object) 12194 { 12195 auto rootSymbol = sc.search(loc, Id.empty, null); 12196 if (auto moduleSymbol = rootSymbol.search(loc, module_)) 12197 if (moduleSymbol.search(loc, id)) 12198 return true; 12199 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); 12200 return false; 12201 } 12202 12203 /** 12204 * Check if an expression is an access to a struct member with the struct 12205 * defined from a literal. 12206 * 12207 * This happens with manifest constants since the initializer is reused as is, 12208 * each time the declaration is part of an expression, which means that the 12209 * literal used as initializer can become a Lvalue. This Lvalue must not be modifiable. 12210 * 12211 * Params: 12212 * exp = An expression that's attempted to be written. 12213 * Must be the LHS of an `AssignExp`, `BinAssignExp`, `CatAssignExp`, 12214 * or the expression passed to a modifiable function parameter. 12215 * Returns: 12216 * `true` if `expr` is a dot var or a dot identifier touching to a struct literal, 12217 * in which case an error message is issued, and `false` otherwise. 12218 */ 12219 private bool checkIfIsStructLiteralDotExpr(Expression exp) 12220 { 12221 // e1.var = ... 12222 // e1.ident = ... 12223 Expression e1; 12224 if (exp.op == TOK.dotVariable) 12225 e1 = exp.isDotVarExp().e1; 12226 else if (exp.op == TOK.dotIdentifier) 12227 e1 = exp.isDotIdExp().e1; 12228 else 12229 return false; 12230 12231 // enum SomeStruct ss = { ... } 12232 // also true for access from a .init: SomeStruct.init.member = ... 12233 if (e1.op != TOK.structLiteral) 12234 return false; 12235 12236 error(exp.loc, "cannot modify constant expression `%s`", exp.toChars()); 12237 return true; 12238 }