1 /** 2 * Semantic analysis for D types. 3 * 4 * Copyright: Copyright (C) 1999-2020 by The D Language Foundation, All Rights Reserved 5 * Authors: $(LINK2 http://www.digitalmars.com, Walter Bright) 6 * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) 7 * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/typesem.d, _typesem.d) 8 * Documentation: https://dlang.org/phobos/dmd_typesem.html 9 * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/typesem.d 10 */ 11 12 module dmd.typesem; 13 14 import core.checkedint; 15 import core.stdc..string; 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.astcodegen; 24 import dmd.complex; 25 import dmd.dcast; 26 import dmd.dclass; 27 import dmd.declaration; 28 import dmd.denum; 29 import dmd.dimport; 30 import dmd.dmangle; 31 import dmd.dmodule : Module; 32 import dmd.dscope; 33 import dmd.dstruct; 34 import dmd.dsymbol; 35 import dmd.dsymbolsem; 36 import dmd.dtemplate; 37 import dmd.errors; 38 import dmd.expression; 39 import dmd.expressionsem; 40 import dmd.func; 41 import dmd.globals; 42 import dmd.hdrgen; 43 import dmd.id; 44 import dmd.identifier; 45 import dmd.imphint; 46 import dmd.init; 47 import dmd.initsem; 48 import dmd.visitor; 49 import dmd.mtype; 50 import dmd.objc; 51 import dmd.opover; 52 import dmd.parse; 53 import dmd.root.ctfloat; 54 import dmd.root.rmem; 55 import dmd.root.outbuffer; 56 import dmd.root.rootobject; 57 import dmd.root..string; 58 import dmd.root.stringtable; 59 import dmd.semantic3; 60 import dmd.sideeffect; 61 import dmd.target; 62 import dmd.tokens; 63 import dmd.typesem; 64 65 /************************** 66 * This evaluates exp while setting length to be the number 67 * of elements in the tuple t. 68 */ 69 private Expression semanticLength(Scope* sc, Type t, Expression exp) 70 { 71 if (auto tt = t.isTypeTuple()) 72 { 73 ScopeDsymbol sym = new ArrayScopeSymbol(sc, tt); 74 sym.parent = sc.scopesym; 75 sc = sc.push(sym); 76 sc = sc.startCTFE(); 77 exp = exp.expressionSemantic(sc); 78 sc = sc.endCTFE(); 79 sc.pop(); 80 } 81 else 82 { 83 sc = sc.startCTFE(); 84 exp = exp.expressionSemantic(sc); 85 sc = sc.endCTFE(); 86 } 87 return exp; 88 } 89 90 private Expression semanticLength(Scope* sc, TupleDeclaration tup, Expression exp) 91 { 92 ScopeDsymbol sym = new ArrayScopeSymbol(sc, tup); 93 sym.parent = sc.scopesym; 94 95 sc = sc.push(sym); 96 sc = sc.startCTFE(); 97 exp = exp.expressionSemantic(sc); 98 sc = sc.endCTFE(); 99 sc.pop(); 100 101 return exp; 102 } 103 104 /************************************* 105 * Resolve a tuple index. 106 */ 107 private void resolveTupleIndex(const ref Loc loc, Scope* sc, Dsymbol s, Expression* pe, Type* pt, Dsymbol* ps, RootObject oindex) 108 { 109 *pt = null; 110 *ps = null; 111 *pe = null; 112 113 auto tup = s.isTupleDeclaration(); 114 115 auto eindex = isExpression(oindex); 116 auto tindex = isType(oindex); 117 auto sindex = isDsymbol(oindex); 118 119 if (!tup) 120 { 121 // It's really an index expression 122 if (tindex) 123 eindex = new TypeExp(loc, tindex); 124 else if (sindex) 125 eindex = symbolToExp(sindex, loc, sc, false); 126 Expression e = new IndexExp(loc, symbolToExp(s, loc, sc, false), eindex); 127 e = e.expressionSemantic(sc); 128 resolveExp(e, pt, pe, ps); 129 return; 130 } 131 132 // Convert oindex to Expression, then try to resolve to constant. 133 if (tindex) 134 tindex.resolve(loc, sc, &eindex, &tindex, &sindex); 135 if (sindex) 136 eindex = symbolToExp(sindex, loc, sc, false); 137 if (!eindex) 138 { 139 .error(loc, "index `%s` is not an expression", oindex.toChars()); 140 *pt = Type.terror; 141 return; 142 } 143 144 eindex = semanticLength(sc, tup, eindex); 145 eindex = eindex.ctfeInterpret(); 146 if (eindex.op == TOK.error) 147 { 148 *pt = Type.terror; 149 return; 150 } 151 const(uinteger_t) d = eindex.toUInteger(); 152 if (d >= tup.objects.dim) 153 { 154 .error(loc, "tuple index `%llu` exceeds length %u", d, tup.objects.dim); 155 *pt = Type.terror; 156 return; 157 } 158 159 RootObject o = (*tup.objects)[cast(size_t)d]; 160 *pt = isType(o); 161 *ps = isDsymbol(o); 162 *pe = isExpression(o); 163 if (*pt) 164 *pt = (*pt).typeSemantic(loc, sc); 165 if (*pe) 166 resolveExp(*pe, pt, pe, ps); 167 } 168 169 /************************************* 170 * Takes an array of Identifiers and figures out if 171 * it represents a Type, Expression, or Dsymbol. 172 * Params: 173 * mt = array of identifiers 174 * loc = location for error messages 175 * sc = context 176 * s = symbol to start search at 177 * scopesym = unused 178 * pe = set if expression 179 * pt = set if type 180 * ps = set if symbol 181 * typeid = set if in TypeidExpression https://dlang.org/spec/expression.html#TypeidExpression 182 */ 183 private void resolveHelper(TypeQualified mt, const ref Loc loc, Scope* sc, Dsymbol s, Dsymbol scopesym, 184 Expression* pe, Type* pt, Dsymbol* ps, bool intypeid = false) 185 { 186 version (none) 187 { 188 printf("TypeQualified::resolveHelper(sc = %p, idents = '%s')\n", sc, mt.toChars()); 189 if (scopesym) 190 printf("\tscopesym = '%s'\n", scopesym.toChars()); 191 } 192 *pe = null; 193 *pt = null; 194 *ps = null; 195 196 if (!s) 197 { 198 /* Look for what user might have intended 199 */ 200 const p = mt.mutableOf().unSharedOf().toChars(); 201 auto id = Identifier.idPool(p, cast(uint)strlen(p)); 202 if (const n = importHint(id.toString())) 203 error(loc, "`%s` is not defined, perhaps `import %.*s;` ?", p, cast(int)n.length, n.ptr); 204 else if (auto s2 = sc.search_correct(id)) 205 error(loc, "undefined identifier `%s`, did you mean %s `%s`?", p, s2.kind(), s2.toChars()); 206 else if (const q = Scope.search_correct_C(id)) 207 error(loc, "undefined identifier `%s`, did you mean `%s`?", p, q); 208 else 209 error(loc, "undefined identifier `%s`", p); 210 211 *pt = Type.terror; 212 return; 213 } 214 215 //printf("\t1: s = '%s' %p, kind = '%s'\n",s.toChars(), s, s.kind()); 216 Declaration d = s.isDeclaration(); 217 if (d && (d.storage_class & STC.templateparameter)) 218 s = s.toAlias(); 219 else 220 { 221 // check for deprecated or disabled aliases 222 s.checkDeprecated(loc, sc); 223 if (d) 224 d.checkDisabled(loc, sc, true); 225 } 226 s = s.toAlias(); 227 //printf("\t2: s = '%s' %p, kind = '%s'\n",s.toChars(), s, s.kind()); 228 for (size_t i = 0; i < mt.idents.dim; i++) 229 { 230 RootObject id = mt.idents[i]; 231 if (id.dyncast() == DYNCAST.expression || 232 id.dyncast() == DYNCAST.type) 233 { 234 Type tx; 235 Expression ex; 236 Dsymbol sx; 237 resolveTupleIndex(loc, sc, s, &ex, &tx, &sx, id); 238 if (sx) 239 { 240 s = sx.toAlias(); 241 continue; 242 } 243 if (tx) 244 ex = new TypeExp(loc, tx); 245 assert(ex); 246 247 ex = typeToExpressionHelper(mt, ex, i + 1); 248 ex = ex.expressionSemantic(sc); 249 resolveExp(ex, pt, pe, ps); 250 return; 251 } 252 253 Type t = s.getType(); // type symbol, type alias, or type tuple? 254 uint errorsave = global.errors; 255 int flags = t is null ? SearchLocalsOnly : IgnorePrivateImports; 256 257 Dsymbol sm = s.searchX(loc, sc, id, flags); 258 if (sm && !(sc.flags & SCOPE.ignoresymbolvisibility) && !symbolIsVisible(sc, sm)) 259 { 260 .error(loc, "`%s` is not visible from module `%s`", sm.toPrettyChars(), sc._module.toChars()); 261 sm = null; 262 } 263 if (global.errors != errorsave) 264 { 265 *pt = Type.terror; 266 return; 267 } 268 269 void helper3() 270 { 271 Expression e; 272 VarDeclaration v = s.isVarDeclaration(); 273 FuncDeclaration f = s.isFuncDeclaration(); 274 if (intypeid || !v && !f) 275 e = symbolToExp(s, loc, sc, true); 276 else 277 e = new VarExp(loc, s.isDeclaration(), true); 278 279 e = typeToExpressionHelper(mt, e, i); 280 e = e.expressionSemantic(sc); 281 resolveExp(e, pt, pe, ps); 282 } 283 284 //printf("\t3: s = %p %s %s, sm = %p\n", s, s.kind(), s.toChars(), sm); 285 if (intypeid && !t && sm && sm.needThis()) 286 return helper3(); 287 288 if (VarDeclaration v = s.isVarDeclaration()) 289 { 290 // https://issues.dlang.org/show_bug.cgi?id=19913 291 // v.type would be null if it is a forward referenced member. 292 if (v.type is null) 293 v.dsymbolSemantic(sc); 294 if (v.storage_class & (STC.const_ | STC.immutable_ | STC.manifest) || 295 v.type.isConst() || v.type.isImmutable()) 296 { 297 // https://issues.dlang.org/show_bug.cgi?id=13087 298 // this.field is not constant always 299 if (!v.isThisDeclaration()) 300 return helper3(); 301 } 302 } 303 if (!sm) 304 { 305 if (!t) 306 { 307 if (s.isDeclaration()) // var, func, or tuple declaration? 308 { 309 t = s.isDeclaration().type; 310 if (!t && s.isTupleDeclaration()) // expression tuple? 311 return helper3(); 312 } 313 else if (s.isTemplateInstance() || 314 s.isImport() || s.isPackage() || s.isModule()) 315 { 316 return helper3(); 317 } 318 } 319 if (t) 320 { 321 sm = t.toDsymbol(sc); 322 if (sm && id.dyncast() == DYNCAST.identifier) 323 { 324 sm = sm.search(loc, cast(Identifier)id, IgnorePrivateImports); 325 if (!sm) 326 return helper3(); 327 } 328 else 329 return helper3(); 330 } 331 else 332 { 333 if (id.dyncast() == DYNCAST.dsymbol) 334 { 335 // searchX already handles errors for template instances 336 assert(global.errors); 337 } 338 else 339 { 340 assert(id.dyncast() == DYNCAST.identifier); 341 sm = s.search_correct(cast(Identifier)id); 342 if (sm) 343 error(loc, "identifier `%s` of `%s` is not defined, did you mean %s `%s`?", id.toChars(), mt.toChars(), sm.kind(), sm.toChars()); 344 else 345 error(loc, "identifier `%s` of `%s` is not defined", id.toChars(), mt.toChars()); 346 } 347 *pe = new ErrorExp(); 348 return; 349 } 350 } 351 s = sm.toAlias(); 352 } 353 354 if (auto em = s.isEnumMember()) 355 { 356 // It's not a type, it's an expression 357 *pe = em.getVarExp(loc, sc); 358 return; 359 } 360 if (auto v = s.isVarDeclaration()) 361 { 362 /* This is mostly same with DsymbolExp::semantic(), but we cannot use it 363 * because some variables used in type context need to prevent lowering 364 * to a literal or contextful expression. For example: 365 * 366 * enum a = 1; alias b = a; 367 * template X(alias e){ alias v = e; } alias x = X!(1); 368 * struct S { int v; alias w = v; } 369 * // TypeIdentifier 'a', 'e', and 'v' should be TOK.variable, 370 * // because getDsymbol() need to work in AliasDeclaration::semantic(). 371 */ 372 if (!v.type || 373 !v.type.deco && v.inuse) 374 { 375 if (v.inuse) // https://issues.dlang.org/show_bug.cgi?id=9494 376 error(loc, "circular reference to %s `%s`", v.kind(), v.toPrettyChars()); 377 else 378 error(loc, "forward reference to %s `%s`", v.kind(), v.toPrettyChars()); 379 *pt = Type.terror; 380 return; 381 } 382 if (v.type.ty == Terror) 383 *pt = Type.terror; 384 else 385 *pe = new VarExp(loc, v); 386 return; 387 } 388 if (auto fld = s.isFuncLiteralDeclaration()) 389 { 390 //printf("'%s' is a function literal\n", fld.toChars()); 391 *pe = new FuncExp(loc, fld); 392 *pe = (*pe).expressionSemantic(sc); 393 return; 394 } 395 version (none) 396 { 397 if (FuncDeclaration fd = s.isFuncDeclaration()) 398 { 399 *pe = new DsymbolExp(loc, fd); 400 return; 401 } 402 } 403 404 Type t; 405 while (1) 406 { 407 t = s.getType(); 408 if (t) 409 break; 410 // If the symbol is an import, try looking inside the import 411 if (Import si = s.isImport()) 412 { 413 s = si.search(loc, s.ident); 414 if (s && s != si) 415 continue; 416 s = si; 417 } 418 *ps = s; 419 return; 420 } 421 422 if (auto ti = t.isTypeInstance()) 423 if (ti != mt && !ti.deco) 424 { 425 if (!ti.tempinst.errors) 426 error(loc, "forward reference to `%s`", ti.toChars()); 427 *pt = Type.terror; 428 return; 429 } 430 431 if (t.ty == Ttuple) 432 *pt = t; 433 else 434 *pt = t.merge(); 435 } 436 437 /************************************ 438 * Transitively search a type for all function types. 439 * If any function types with parameters are found that have parameter identifiers 440 * or default arguments, remove those and create a new type stripped of those. 441 * This is used to determine the "canonical" version of a type which is useful for 442 * comparisons. 443 * Params: 444 * t = type to scan 445 * Returns: 446 * `t` if no parameter identifiers or default arguments found, otherwise a new type that is 447 * the same as t but with no parameter identifiers or default arguments. 448 */ 449 private Type stripDefaultArgs(Type t) 450 { 451 static Parameters* stripParams(Parameters* parameters) 452 { 453 static Parameter stripParameter(Parameter p) 454 { 455 Type t = stripDefaultArgs(p.type); 456 return (t != p.type || p.defaultArg || p.ident || p.userAttribDecl) 457 ? new Parameter(p.storageClass, t, null, null, null) 458 : null; 459 } 460 461 if (parameters) 462 { 463 foreach (i, p; *parameters) 464 { 465 Parameter ps = stripParameter(p); 466 if (ps) 467 { 468 // Replace params with a copy we can modify 469 Parameters* nparams = new Parameters(parameters.dim); 470 471 foreach (j, ref np; *nparams) 472 { 473 Parameter pj = (*parameters)[j]; 474 if (j < i) 475 np = pj; 476 else if (j == i) 477 np = ps; 478 else 479 { 480 Parameter nps = stripParameter(pj); 481 np = nps ? nps : pj; 482 } 483 } 484 return nparams; 485 } 486 } 487 } 488 return parameters; 489 } 490 491 if (t is null) 492 return t; 493 494 if (auto tf = t.isTypeFunction()) 495 { 496 Type tret = stripDefaultArgs(tf.next); 497 Parameters* params = stripParams(tf.parameterList.parameters); 498 if (tret == tf.next && params == tf.parameterList.parameters) 499 return t; 500 TypeFunction tr = cast(TypeFunction)tf.copy(); 501 tr.parameterList.parameters = params; 502 tr.next = tret; 503 //printf("strip %s\n <- %s\n", tr.toChars(), t.toChars()); 504 return tr; 505 } 506 else if (auto tt = t.isTypeTuple()) 507 { 508 Parameters* args = stripParams(tt.arguments); 509 if (args == tt.arguments) 510 return t; 511 TypeTuple tr = cast(TypeTuple)t.copy(); 512 tr.arguments = args; 513 return tr; 514 } 515 else if (t.ty == Tenum) 516 { 517 // TypeEnum::nextOf() may be != NULL, but it's not necessary here. 518 return t; 519 } 520 else 521 { 522 Type tn = t.nextOf(); 523 Type n = stripDefaultArgs(tn); 524 if (n == tn) 525 return t; 526 TypeNext tr = cast(TypeNext)t.copy(); 527 tr.next = n; 528 return tr; 529 } 530 } 531 532 /****************************************** 533 * We've mistakenly parsed `t` as a type. 534 * Redo `t` as an Expression. 535 * Params: 536 * t = mistaken type 537 * Returns: 538 * t redone as Expression, null if cannot 539 */ 540 Expression typeToExpression(Type t) 541 { 542 static Expression visitSArray(TypeSArray t) 543 { 544 if (auto e = t.next.typeToExpression()) 545 return new ArrayExp(t.dim.loc, e, t.dim); 546 return null; 547 } 548 549 static Expression visitAArray(TypeAArray t) 550 { 551 if (auto e = t.next.typeToExpression()) 552 { 553 if (auto ei = t.index.typeToExpression()) 554 return new ArrayExp(t.loc, e, ei); 555 } 556 return null; 557 } 558 559 static Expression visitIdentifier(TypeIdentifier t) 560 { 561 return typeToExpressionHelper(t, new IdentifierExp(t.loc, t.ident)); 562 } 563 564 static Expression visitInstance(TypeInstance t) 565 { 566 return typeToExpressionHelper(t, new ScopeExp(t.loc, t.tempinst)); 567 } 568 569 // easy way to enable 'auto v = new int[mixin("exp")];' in 2.088+ 570 static Expression visitMixin(TypeMixin t) 571 { 572 return new TypeExp(t.loc, t); 573 } 574 575 switch (t.ty) 576 { 577 case Tsarray: return visitSArray(cast(TypeSArray) t); 578 case Taarray: return visitAArray(cast(TypeAArray) t); 579 case Tident: return visitIdentifier(cast(TypeIdentifier) t); 580 case Tinstance: return visitInstance(cast(TypeInstance) t); 581 case Tmixin: return visitMixin(cast(TypeMixin) t); 582 default: return null; 583 } 584 } 585 586 /* Helper function for `typeToExpression`. Contains common code 587 * for TypeQualified derived classes. 588 */ 589 Expression typeToExpressionHelper(TypeQualified t, Expression e, size_t i = 0) 590 { 591 //printf("toExpressionHelper(e = %s %s)\n", Token.toChars(e.op), e.toChars()); 592 foreach (id; t.idents[i .. t.idents.dim]) 593 { 594 //printf("\t[%d] e: '%s', id: '%s'\n", i, e.toChars(), id.toChars()); 595 596 final switch (id.dyncast()) 597 { 598 // ... '. ident' 599 case DYNCAST.identifier: 600 e = new DotIdExp(e.loc, e, cast(Identifier)id); 601 break; 602 603 // ... '. name!(tiargs)' 604 case DYNCAST.dsymbol: 605 auto ti = (cast(Dsymbol)id).isTemplateInstance(); 606 assert(ti); 607 e = new DotTemplateInstanceExp(e.loc, e, ti.name, ti.tiargs); 608 break; 609 610 // ... '[type]' 611 case DYNCAST.type: // https://issues.dlang.org/show_bug.cgi?id=1215 612 e = new ArrayExp(t.loc, e, new TypeExp(t.loc, cast(Type)id)); 613 break; 614 615 // ... '[expr]' 616 case DYNCAST.expression: // https://issues.dlang.org/show_bug.cgi?id=1215 617 e = new ArrayExp(t.loc, e, cast(Expression)id); 618 break; 619 620 case DYNCAST.object: 621 case DYNCAST.tuple: 622 case DYNCAST.parameter: 623 case DYNCAST.statement: 624 case DYNCAST.condition: 625 case DYNCAST.templateparameter: 626 assert(0); 627 } 628 } 629 return e; 630 } 631 632 /****************************************** 633 * Perform semantic analysis on a type. 634 * Params: 635 * t = Type AST node 636 * loc = the location of the type 637 * sc = context 638 * Returns: 639 * `Type` with completed semantic analysis, `Terror` if errors 640 * were encountered 641 */ 642 extern(C++) Type typeSemantic(Type t, const ref Loc loc, Scope* sc) 643 { 644 static Type error() 645 { 646 return Type.terror; 647 } 648 649 Type visitType(Type t) 650 { 651 if (t.ty == Tint128 || t.ty == Tuns128) 652 { 653 .error(loc, "`cent` and `ucent` types not implemented"); 654 return error(); 655 } 656 657 return t.merge(); 658 } 659 660 Type visitVector(TypeVector mtype) 661 { 662 const errors = global.errors; 663 mtype.basetype = mtype.basetype.typeSemantic(loc, sc); 664 if (errors != global.errors) 665 return error(); 666 mtype.basetype = mtype.basetype.toBasetype().mutableOf(); 667 if (mtype.basetype.ty != Tsarray) 668 { 669 .error(loc, "T in __vector(T) must be a static array, not `%s`", mtype.basetype.toChars()); 670 return error(); 671 } 672 TypeSArray t = cast(TypeSArray)mtype.basetype; 673 const sz = cast(int)t.size(loc); 674 final switch (target.isVectorTypeSupported(sz, t.nextOf())) 675 { 676 case 0: 677 // valid 678 break; 679 680 case 1: 681 // no support at all 682 .error(loc, "SIMD vector types not supported on this platform"); 683 return error(); 684 685 case 2: 686 // invalid base type 687 .error(loc, "vector type `%s` is not supported on this platform", mtype.toChars()); 688 return error(); 689 690 case 3: 691 // invalid size 692 .error(loc, "%d byte vector type `%s` is not supported on this platform", sz, mtype.toChars()); 693 return error(); 694 } 695 return merge(mtype); 696 } 697 698 Type visitSArray(TypeSArray mtype) 699 { 700 //printf("TypeSArray::semantic() %s\n", toChars()); 701 Type t; 702 Expression e; 703 Dsymbol s; 704 mtype.next.resolve(loc, sc, &e, &t, &s); 705 706 if (auto tup = s ? s.isTupleDeclaration() : null) 707 { 708 mtype.dim = semanticLength(sc, tup, mtype.dim); 709 mtype.dim = mtype.dim.ctfeInterpret(); 710 if (mtype.dim.op == TOK.error) 711 return error(); 712 713 uinteger_t d = mtype.dim.toUInteger(); 714 if (d >= tup.objects.dim) 715 { 716 .error(loc, "tuple index %llu exceeds %llu", cast(ulong)d, cast(ulong)tup.objects.dim); 717 return error(); 718 } 719 720 RootObject o = (*tup.objects)[cast(size_t)d]; 721 if (o.dyncast() != DYNCAST.type) 722 { 723 .error(loc, "`%s` is not a type", mtype.toChars()); 724 return error(); 725 } 726 return (cast(Type)o).addMod(mtype.mod); 727 } 728 729 Type tn = mtype.next.typeSemantic(loc, sc); 730 if (tn.ty == Terror) 731 return error(); 732 733 Type tbn = tn.toBasetype(); 734 if (mtype.dim) 735 { 736 //https://issues.dlang.org/show_bug.cgi?id=15478 737 if (mtype.dim.isDotVarExp()) 738 { 739 if (Declaration vd = mtype.dim.isDotVarExp().var) 740 { 741 FuncDeclaration fd = vd.toAlias().isFuncDeclaration(); 742 if (fd) 743 mtype.dim = new CallExp(loc, fd, null); 744 } 745 } 746 747 auto errors = global.errors; 748 mtype.dim = semanticLength(sc, tbn, mtype.dim); 749 if (errors != global.errors) 750 return error(); 751 752 mtype.dim = mtype.dim.optimize(WANTvalue); 753 mtype.dim = mtype.dim.ctfeInterpret(); 754 if (mtype.dim.op == TOK.error) 755 return error(); 756 757 errors = global.errors; 758 dinteger_t d1 = mtype.dim.toInteger(); 759 if (errors != global.errors) 760 return error(); 761 762 mtype.dim = mtype.dim.implicitCastTo(sc, Type.tsize_t); 763 mtype.dim = mtype.dim.optimize(WANTvalue); 764 if (mtype.dim.op == TOK.error) 765 return error(); 766 767 errors = global.errors; 768 dinteger_t d2 = mtype.dim.toInteger(); 769 if (errors != global.errors) 770 return error(); 771 772 if (mtype.dim.op == TOK.error) 773 return error(); 774 775 Type overflowError() 776 { 777 .error(loc, "`%s` size %llu * %llu exceeds 0x%llx size limit for static array", 778 mtype.toChars(), cast(ulong)tbn.size(loc), cast(ulong)d1, target.maxStaticDataSize); 779 return error(); 780 } 781 782 if (d1 != d2) 783 return overflowError(); 784 785 Type tbx = tbn.baseElemOf(); 786 if (tbx.ty == Tstruct && !(cast(TypeStruct)tbx).sym.members || 787 tbx.ty == Tenum && !(cast(TypeEnum)tbx).sym.members) 788 { 789 /* To avoid meaningless error message, skip the total size limit check 790 * when the bottom of element type is opaque. 791 */ 792 } 793 else if (tbn.isTypeBasic() || 794 tbn.ty == Tpointer || 795 tbn.ty == Tarray || 796 tbn.ty == Tsarray || 797 tbn.ty == Taarray || 798 (tbn.ty == Tstruct && ((cast(TypeStruct)tbn).sym.sizeok == Sizeok.done)) || 799 tbn.ty == Tclass) 800 { 801 /* Only do this for types that don't need to have semantic() 802 * run on them for the size, since they may be forward referenced. 803 */ 804 bool overflow = false; 805 if (mulu(tbn.size(loc), d2, overflow) >= target.maxStaticDataSize || overflow) 806 return overflowError(); 807 } 808 } 809 switch (tbn.ty) 810 { 811 case Ttuple: 812 { 813 // Index the tuple to get the type 814 assert(mtype.dim); 815 TypeTuple tt = cast(TypeTuple)tbn; 816 uinteger_t d = mtype.dim.toUInteger(); 817 if (d >= tt.arguments.dim) 818 { 819 .error(loc, "tuple index %llu exceeds %llu", cast(ulong)d, cast(ulong)tt.arguments.dim); 820 return error(); 821 } 822 Type telem = (*tt.arguments)[cast(size_t)d].type; 823 return telem.addMod(mtype.mod); 824 } 825 826 case Tfunction: 827 case Tnone: 828 .error(loc, "cannot have array of `%s`", tbn.toChars()); 829 return error(); 830 831 default: 832 break; 833 } 834 if (tbn.isscope()) 835 { 836 .error(loc, "cannot have array of scope `%s`", tbn.toChars()); 837 return error(); 838 } 839 840 /* Ensure things like const(immutable(T)[3]) become immutable(T[3]) 841 * and const(T)[3] become const(T[3]) 842 */ 843 mtype.next = tn; 844 mtype.transitive(); 845 return mtype.addMod(tn.mod).merge(); 846 } 847 848 Type visitDArray(TypeDArray mtype) 849 { 850 Type tn = mtype.next.typeSemantic(loc, sc); 851 Type tbn = tn.toBasetype(); 852 switch (tbn.ty) 853 { 854 case Ttuple: 855 return tbn; 856 857 case Tfunction: 858 case Tnone: 859 .error(loc, "cannot have array of `%s`", tbn.toChars()); 860 return error(); 861 862 case Terror: 863 return error(); 864 865 default: 866 break; 867 } 868 if (tn.isscope()) 869 { 870 .error(loc, "cannot have array of scope `%s`", tn.toChars()); 871 return error(); 872 } 873 mtype.next = tn; 874 mtype.transitive(); 875 return merge(mtype); 876 } 877 878 Type visitAArray(TypeAArray mtype) 879 { 880 //printf("TypeAArray::semantic() %s index.ty = %d\n", mtype.toChars(), mtype.index.ty); 881 if (mtype.deco) 882 { 883 return mtype; 884 } 885 886 mtype.loc = loc; 887 mtype.sc = sc; 888 if (sc) 889 sc.setNoFree(); 890 891 // Deal with the case where we thought the index was a type, but 892 // in reality it was an expression. 893 if (mtype.index.ty == Tident || mtype.index.ty == Tinstance || mtype.index.ty == Tsarray || mtype.index.ty == Ttypeof || mtype.index.ty == Treturn || mtype.index.ty == Tmixin) 894 { 895 Expression e; 896 Type t; 897 Dsymbol s; 898 mtype.index.resolve(loc, sc, &e, &t, &s); 899 900 //https://issues.dlang.org/show_bug.cgi?id=15478 901 if (s) 902 { 903 if (FuncDeclaration fd = s.toAlias().isFuncDeclaration()) 904 e = new CallExp(loc, fd, null); 905 } 906 907 if (e) 908 { 909 // It was an expression - 910 // Rewrite as a static array 911 auto tsa = new TypeSArray(mtype.next, e); 912 return tsa.typeSemantic(loc, sc); 913 } 914 else if (t) 915 mtype.index = t.typeSemantic(loc, sc); 916 else 917 { 918 .error(loc, "index is not a type or an expression"); 919 return error(); 920 } 921 } 922 else 923 mtype.index = mtype.index.typeSemantic(loc, sc); 924 mtype.index = mtype.index.merge2(); 925 926 if (mtype.index.nextOf() && !mtype.index.nextOf().isImmutable()) 927 { 928 mtype.index = mtype.index.constOf().mutableOf(); 929 version (none) 930 { 931 printf("index is %p %s\n", mtype.index, mtype.index.toChars()); 932 mtype.index.check(); 933 printf("index.mod = x%x\n", mtype.index.mod); 934 printf("index.ito = x%x\n", mtype.index.ito); 935 if (mtype.index.ito) 936 { 937 printf("index.ito.mod = x%x\n", mtype.index.ito.mod); 938 printf("index.ito.ito = x%x\n", mtype.index.ito.ito); 939 } 940 } 941 } 942 943 switch (mtype.index.toBasetype().ty) 944 { 945 case Tfunction: 946 case Tvoid: 947 case Tnone: 948 case Ttuple: 949 .error(loc, "cannot have associative array key of `%s`", mtype.index.toBasetype().toChars()); 950 goto case Terror; 951 case Terror: 952 return error(); 953 954 default: 955 break; 956 } 957 Type tbase = mtype.index.baseElemOf(); 958 while (tbase.ty == Tarray) 959 tbase = tbase.nextOf().baseElemOf(); 960 if (auto ts = tbase.isTypeStruct()) 961 { 962 /* AA's need typeid(index).equals() and getHash(). Issue error if not correctly set up. 963 */ 964 StructDeclaration sd = ts.sym; 965 if (sd.semanticRun < PASS.semanticdone) 966 sd.dsymbolSemantic(null); 967 968 // duplicate a part of StructDeclaration::semanticTypeInfoMembers 969 //printf("AA = %s, key: xeq = %p, xerreq = %p xhash = %p\n", toChars(), sd.xeq, sd.xerreq, sd.xhash); 970 if (sd.xeq && sd.xeq._scope && sd.xeq.semanticRun < PASS.semantic3done) 971 { 972 uint errors = global.startGagging(); 973 sd.xeq.semantic3(sd.xeq._scope); 974 if (global.endGagging(errors)) 975 sd.xeq = sd.xerreq; 976 } 977 978 //printf("AA = %s, key: xeq = %p, xhash = %p\n", toChars(), sd.xeq, sd.xhash); 979 const(char)* s = (mtype.index.toBasetype().ty != Tstruct) ? "bottom of " : ""; 980 if (!sd.xeq) 981 { 982 // If sd.xhash != NULL: 983 // sd or its fields have user-defined toHash. 984 // AA assumes that its result is consistent with bitwise equality. 985 // else: 986 // bitwise equality & hashing 987 } 988 else if (sd.xeq == sd.xerreq) 989 { 990 if (search_function(sd, Id.eq)) 991 { 992 .error(loc, "%sAA key type `%s` does not have `bool opEquals(ref const %s) const`", s, sd.toChars(), sd.toChars()); 993 } 994 else 995 { 996 .error(loc, "%sAA key type `%s` does not support const equality", s, sd.toChars()); 997 } 998 return error(); 999 } 1000 else if (!sd.xhash) 1001 { 1002 if (search_function(sd, Id.eq)) 1003 { 1004 .error(loc, "%sAA key type `%s` should have `extern (D) size_t toHash() const nothrow @safe` if `opEquals` defined", s, sd.toChars()); 1005 } 1006 else 1007 { 1008 .error(loc, "%sAA key type `%s` supports const equality but doesn't support const hashing", s, sd.toChars()); 1009 } 1010 return error(); 1011 } 1012 else 1013 { 1014 // defined equality & hashing 1015 assert(sd.xeq && sd.xhash); 1016 1017 /* xeq and xhash may be implicitly defined by compiler. For example: 1018 * struct S { int[] arr; } 1019 * With 'arr' field equality and hashing, compiler will implicitly 1020 * generate functions for xopEquals and xtoHash in TypeInfo_Struct. 1021 */ 1022 } 1023 } 1024 else if (tbase.ty == Tclass && !(cast(TypeClass)tbase).sym.isInterfaceDeclaration()) 1025 { 1026 ClassDeclaration cd = (cast(TypeClass)tbase).sym; 1027 if (cd.semanticRun < PASS.semanticdone) 1028 cd.dsymbolSemantic(null); 1029 1030 if (!ClassDeclaration.object) 1031 { 1032 .error(Loc.initial, "missing or corrupt object.d"); 1033 fatal(); 1034 } 1035 1036 __gshared FuncDeclaration feq = null; 1037 __gshared FuncDeclaration fcmp = null; 1038 __gshared FuncDeclaration fhash = null; 1039 if (!feq) 1040 feq = search_function(ClassDeclaration.object, Id.eq).isFuncDeclaration(); 1041 if (!fcmp) 1042 fcmp = search_function(ClassDeclaration.object, Id.cmp).isFuncDeclaration(); 1043 if (!fhash) 1044 fhash = search_function(ClassDeclaration.object, Id.tohash).isFuncDeclaration(); 1045 assert(fcmp && feq && fhash); 1046 1047 if (feq.vtblIndex < cd.vtbl.dim && cd.vtbl[feq.vtblIndex] == feq) 1048 { 1049 version (all) 1050 { 1051 if (fcmp.vtblIndex < cd.vtbl.dim && cd.vtbl[fcmp.vtblIndex] != fcmp) 1052 { 1053 const(char)* s = (mtype.index.toBasetype().ty != Tclass) ? "bottom of " : ""; 1054 .error(loc, "%sAA key type `%s` now requires equality rather than comparison", s, cd.toChars()); 1055 errorSupplemental(loc, "Please override `Object.opEquals` and `Object.toHash`."); 1056 } 1057 } 1058 } 1059 } 1060 mtype.next = mtype.next.typeSemantic(loc, sc).merge2(); 1061 mtype.transitive(); 1062 1063 switch (mtype.next.toBasetype().ty) 1064 { 1065 case Tfunction: 1066 case Tvoid: 1067 case Tnone: 1068 case Ttuple: 1069 .error(loc, "cannot have associative array of `%s`", mtype.next.toChars()); 1070 goto case Terror; 1071 case Terror: 1072 return error(); 1073 default: 1074 break; 1075 } 1076 if (mtype.next.isscope()) 1077 { 1078 .error(loc, "cannot have array of scope `%s`", mtype.next.toChars()); 1079 return error(); 1080 } 1081 return merge(mtype); 1082 } 1083 1084 Type visitPointer(TypePointer mtype) 1085 { 1086 //printf("TypePointer::semantic() %s\n", toChars()); 1087 if (mtype.deco) 1088 { 1089 return mtype; 1090 } 1091 Type n = mtype.next.typeSemantic(loc, sc); 1092 switch (n.toBasetype().ty) 1093 { 1094 case Ttuple: 1095 .error(loc, "cannot have pointer to `%s`", n.toChars()); 1096 goto case Terror; 1097 case Terror: 1098 return error(); 1099 default: 1100 break; 1101 } 1102 if (n != mtype.next) 1103 { 1104 mtype.deco = null; 1105 } 1106 mtype.next = n; 1107 if (mtype.next.ty != Tfunction) 1108 { 1109 mtype.transitive(); 1110 return merge(mtype); 1111 } 1112 version (none) 1113 { 1114 return merge(mtype); 1115 } 1116 else 1117 { 1118 mtype.deco = merge(mtype).deco; 1119 /* Don't return merge(), because arg identifiers and default args 1120 * can be different 1121 * even though the types match 1122 */ 1123 return mtype; 1124 } 1125 } 1126 1127 Type visitReference(TypeReference mtype) 1128 { 1129 //printf("TypeReference::semantic()\n"); 1130 Type n = mtype.next.typeSemantic(loc, sc); 1131 if (n != mtype.next) 1132 mtype.deco = null; 1133 mtype.next = n; 1134 mtype.transitive(); 1135 return merge(mtype); 1136 } 1137 1138 Type visitFunction(TypeFunction mtype) 1139 { 1140 if (mtype.deco) // if semantic() already run 1141 { 1142 //printf("already done\n"); 1143 return mtype; 1144 } 1145 //printf("TypeFunction::semantic() this = %p\n", this); 1146 //printf("TypeFunction::semantic() %s, sc.stc = %llx, fargs = %p\n", toChars(), sc.stc, fargs); 1147 1148 bool errors = false; 1149 1150 if (mtype.inuse > global.recursionLimit) 1151 { 1152 mtype.inuse = 0; 1153 .error(loc, "recursive type"); 1154 return error(); 1155 } 1156 1157 /* Copy in order to not mess up original. 1158 * This can produce redundant copies if inferring return type, 1159 * as semantic() will get called again on this. 1160 */ 1161 TypeFunction tf = mtype.copy().toTypeFunction(); 1162 if (mtype.parameterList.parameters) 1163 { 1164 tf.parameterList.parameters = mtype.parameterList.parameters.copy(); 1165 for (size_t i = 0; i < mtype.parameterList.parameters.dim; i++) 1166 { 1167 Parameter p = cast(Parameter)mem.xmalloc(__traits(classInstanceSize, Parameter)); 1168 memcpy(cast(void*)p, cast(void*)(*mtype.parameterList.parameters)[i], __traits(classInstanceSize, Parameter)); 1169 (*tf.parameterList.parameters)[i] = p; 1170 } 1171 } 1172 1173 if (sc.stc & STC.pure_) 1174 tf.purity = PURE.fwdref; 1175 if (sc.stc & STC.nothrow_) 1176 tf.isnothrow = true; 1177 if (sc.stc & STC.nogc) 1178 tf.isnogc = true; 1179 if (sc.stc & STC.ref_) 1180 tf.isref = true; 1181 if (sc.stc & STC.return_) 1182 tf.isreturn = true; 1183 if (sc.stc & STC.returninferred) 1184 tf.isreturninferred = true; 1185 if (sc.stc & STC.scope_) 1186 tf.isscope = true; 1187 if (sc.stc & STC.scopeinferred) 1188 tf.isscopeinferred = true; 1189 1190 // if (tf.isreturn && !tf.isref) 1191 // tf.isscope = true; // return by itself means 'return scope' 1192 1193 if (tf.trust == TRUST.default_) 1194 { 1195 if (sc.stc & STC.safe) 1196 tf.trust = TRUST.safe; 1197 else if (sc.stc & STC.system) 1198 tf.trust = TRUST.system; 1199 else if (sc.stc & STC.trusted) 1200 tf.trust = TRUST.trusted; 1201 } 1202 1203 if (sc.stc & STC.property) 1204 tf.isproperty = true; 1205 if (sc.stc & STC.live) 1206 tf.islive = true; 1207 1208 tf.linkage = sc.linkage; 1209 version (none) 1210 { 1211 /* If the parent is @safe, then this function defaults to safe 1212 * too. 1213 * If the parent's @safe-ty is inferred, then this function's @safe-ty needs 1214 * to be inferred first. 1215 */ 1216 if (tf.trust == TRUST.default_) 1217 for (Dsymbol p = sc.func; p; p = p.toParent2()) 1218 { 1219 FuncDeclaration fd = p.isFuncDeclaration(); 1220 if (fd) 1221 { 1222 if (fd.isSafeBypassingInference()) 1223 tf.trust = TRUST.safe; // default to @safe 1224 break; 1225 } 1226 } 1227 } 1228 1229 bool wildreturn = false; 1230 if (tf.next) 1231 { 1232 sc = sc.push(); 1233 sc.stc &= ~(STC.TYPECTOR | STC.FUNCATTR); 1234 tf.next = tf.next.typeSemantic(loc, sc); 1235 sc = sc.pop(); 1236 errors |= tf.checkRetType(loc); 1237 if (tf.next.isscope() && !(sc.flags & SCOPE.ctor)) 1238 { 1239 .error(loc, "functions cannot return `scope %s`", tf.next.toChars()); 1240 errors = true; 1241 } 1242 if (tf.next.hasWild()) 1243 wildreturn = true; 1244 1245 if (tf.isreturn && !tf.isref && !tf.next.hasPointers()) 1246 { 1247 tf.isreturn = false; 1248 } 1249 } 1250 1251 ubyte wildparams = 0; 1252 if (tf.parameterList.parameters) 1253 { 1254 /* Create a scope for evaluating the default arguments for the parameters 1255 */ 1256 Scope* argsc = sc.push(); 1257 argsc.stc = 0; // don't inherit storage class 1258 argsc.protection = Prot(Prot.Kind.public_); 1259 argsc.func = null; 1260 1261 size_t dim = tf.parameterList.length; 1262 for (size_t i = 0; i < dim; i++) 1263 { 1264 Parameter fparam = tf.parameterList[i]; 1265 mtype.inuse++; 1266 fparam.type = fparam.type.typeSemantic(loc, argsc); 1267 mtype.inuse--; 1268 if (fparam.type.ty == Terror) 1269 { 1270 errors = true; 1271 continue; 1272 } 1273 1274 fparam.type = fparam.type.addStorageClass(fparam.storageClass); 1275 1276 if (fparam.storageClass & (STC.auto_ | STC.alias_ | STC.static_)) 1277 { 1278 if (!fparam.type) 1279 continue; 1280 } 1281 1282 Type t = fparam.type.toBasetype(); 1283 1284 if (t.ty == Tfunction) 1285 { 1286 .error(loc, "cannot have parameter of function type `%s`", fparam.type.toChars()); 1287 errors = true; 1288 } 1289 else if (!(fparam.storageClass & (STC.ref_ | STC.out_)) && 1290 (t.ty == Tstruct || t.ty == Tsarray || t.ty == Tenum)) 1291 { 1292 Type tb2 = t.baseElemOf(); 1293 if (tb2.ty == Tstruct && !(cast(TypeStruct)tb2).sym.members || 1294 tb2.ty == Tenum && !(cast(TypeEnum)tb2).sym.memtype) 1295 { 1296 .error(loc, "cannot have parameter of opaque type `%s` by value", fparam.type.toChars()); 1297 errors = true; 1298 } 1299 } 1300 else if (!(fparam.storageClass & STC.lazy_) && t.ty == Tvoid) 1301 { 1302 .error(loc, "cannot have parameter of type `%s`", fparam.type.toChars()); 1303 errors = true; 1304 } 1305 1306 if ((fparam.storageClass & (STC.ref_ | STC.wild)) == (STC.ref_ | STC.wild)) 1307 { 1308 // 'ref inout' implies 'return' 1309 fparam.storageClass |= STC.return_; 1310 } 1311 1312 if (fparam.storageClass & STC.return_) 1313 { 1314 if (fparam.storageClass & (STC.ref_ | STC.out_)) 1315 { 1316 // Disabled for the moment awaiting improvement to allow return by ref 1317 // to be transformed into return by scope. 1318 if (0 && !tf.isref) 1319 { 1320 auto stc = fparam.storageClass & (STC.ref_ | STC.out_); 1321 .error(loc, "parameter `%s` is `return %s` but function does not return by `ref`", 1322 fparam.ident ? fparam.ident.toChars() : "", 1323 stcToChars(stc)); 1324 errors = true; 1325 } 1326 } 1327 else 1328 { 1329 if (!(fparam.storageClass & STC.scope_)) 1330 fparam.storageClass |= STC.scope_ | STC.scopeinferred; // 'return' implies 'scope' 1331 if (tf.isref) 1332 { 1333 } 1334 else if (tf.next && !tf.next.hasPointers() && tf.next.toBasetype().ty != Tvoid) 1335 { 1336 fparam.storageClass &= ~STC.return_; // https://issues.dlang.org/show_bug.cgi?id=18963 1337 } 1338 } 1339 } 1340 1341 if (fparam.storageClass & (STC.ref_ | STC.lazy_)) 1342 { 1343 } 1344 else if (fparam.storageClass & STC.out_) 1345 { 1346 if (ubyte m = fparam.type.mod & (MODFlags.immutable_ | MODFlags.const_ | MODFlags.wild)) 1347 { 1348 .error(loc, "cannot have `%s out` parameter of type `%s`", MODtoChars(m), t.toChars()); 1349 errors = true; 1350 } 1351 else 1352 { 1353 Type tv = t.baseElemOf(); 1354 if (tv.ty == Tstruct && (cast(TypeStruct)tv).sym.noDefaultCtor) 1355 { 1356 .error(loc, "cannot have `out` parameter of type `%s` because the default construction is disabled", fparam.type.toChars()); 1357 errors = true; 1358 } 1359 } 1360 } 1361 1362 if (fparam.storageClass & STC.scope_ && !fparam.type.hasPointers() && fparam.type.ty != Ttuple) 1363 { 1364 /* X foo(ref return scope X) => Ref-ReturnScope 1365 * ref X foo(ref return scope X) => ReturnRef-Scope 1366 * But X has no pointers, we don't need the scope part, so: 1367 * X foo(ref return scope X) => Ref 1368 * ref X foo(ref return scope X) => ReturnRef 1369 * Constructors are treated as if they are being returned through the hidden parameter, 1370 * which is by ref, and the ref there is ignored. 1371 */ 1372 fparam.storageClass &= ~STC.scope_; 1373 if (!tf.isref || (sc.flags & SCOPE.ctor)) 1374 fparam.storageClass &= ~STC.return_; 1375 } 1376 1377 if (t.hasWild()) 1378 { 1379 wildparams |= 1; 1380 //if (tf.next && !wildreturn) 1381 // error(loc, "inout on parameter means inout must be on return type as well (if from D1 code, replace with `ref`)"); 1382 } 1383 1384 if (fparam.defaultArg) 1385 { 1386 Expression e = fparam.defaultArg; 1387 const isRefOrOut = fparam.storageClass & (STC.ref_ | STC.out_); 1388 const isAuto = fparam.storageClass & (STC.auto_ | STC.autoref); 1389 if (isRefOrOut && !isAuto) 1390 { 1391 e = e.expressionSemantic(argsc); 1392 e = resolveProperties(argsc, e); 1393 } 1394 else 1395 { 1396 e = inferType(e, fparam.type); 1397 Initializer iz = new ExpInitializer(e.loc, e); 1398 iz = iz.initializerSemantic(argsc, fparam.type, INITnointerpret); 1399 e = iz.initializerToExpression(); 1400 } 1401 if (e.op == TOK.function_) // https://issues.dlang.org/show_bug.cgi?id=4820 1402 { 1403 FuncExp fe = cast(FuncExp)e; 1404 // Replace function literal with a function symbol, 1405 // since default arg expression must be copied when used 1406 // and copying the literal itself is wrong. 1407 e = new VarExp(e.loc, fe.fd, false); 1408 e = new AddrExp(e.loc, e); 1409 e = e.expressionSemantic(argsc); 1410 } 1411 e = e.implicitCastTo(argsc, fparam.type); 1412 1413 // default arg must be an lvalue 1414 if (isRefOrOut && !isAuto) 1415 e = e.toLvalue(argsc, e); 1416 1417 fparam.defaultArg = e; 1418 if (e.op == TOK.error) 1419 errors = true; 1420 } 1421 1422 /* If fparam after semantic() turns out to be a tuple, the number of parameters may 1423 * change. 1424 */ 1425 if (auto tt = t.isTypeTuple()) 1426 { 1427 /* TypeFunction::parameter also is used as the storage of 1428 * Parameter objects for FuncDeclaration. So we should copy 1429 * the elements of TypeTuple::arguments to avoid unintended 1430 * sharing of Parameter object among other functions. 1431 */ 1432 if (tt.arguments && tt.arguments.dim) 1433 { 1434 /* Propagate additional storage class from tuple parameters to their 1435 * element-parameters. 1436 * Make a copy, as original may be referenced elsewhere. 1437 */ 1438 size_t tdim = tt.arguments.dim; 1439 auto newparams = new Parameters(tdim); 1440 for (size_t j = 0; j < tdim; j++) 1441 { 1442 Parameter narg = (*tt.arguments)[j]; 1443 1444 // https://issues.dlang.org/show_bug.cgi?id=12744 1445 // If the storage classes of narg 1446 // conflict with the ones in fparam, it's ignored. 1447 StorageClass stc = fparam.storageClass | narg.storageClass; 1448 StorageClass stc1 = fparam.storageClass & (STC.ref_ | STC.out_ | STC.lazy_); 1449 StorageClass stc2 = narg.storageClass & (STC.ref_ | STC.out_ | STC.lazy_); 1450 if (stc1 && stc2 && stc1 != stc2) 1451 { 1452 OutBuffer buf1; stcToBuffer(&buf1, stc1 | ((stc1 & STC.ref_) ? (fparam.storageClass & STC.auto_) : 0)); 1453 OutBuffer buf2; stcToBuffer(&buf2, stc2); 1454 1455 .error(loc, "incompatible parameter storage classes `%s` and `%s`", 1456 buf1.peekChars(), buf2.peekChars()); 1457 errors = true; 1458 stc = stc1 | (stc & ~(STC.ref_ | STC.out_ | STC.lazy_)); 1459 } 1460 1461 /* https://issues.dlang.org/show_bug.cgi?id=18572 1462 * 1463 * If a tuple parameter has a default argument, when expanding the parameter 1464 * tuple the default argument tuple must also be expanded. 1465 */ 1466 Expression paramDefaultArg = narg.defaultArg; 1467 TupleExp te = fparam.defaultArg ? fparam.defaultArg.isTupleExp() : null; 1468 if (te && te.exps && te.exps.length) 1469 paramDefaultArg = (*te.exps)[j]; 1470 1471 (*newparams)[j] = new Parameter( 1472 stc, narg.type, narg.ident, paramDefaultArg, narg.userAttribDecl); 1473 } 1474 fparam.type = new TypeTuple(newparams); 1475 } 1476 fparam.storageClass = 0; 1477 1478 /* Reset number of parameters, and back up one to do this fparam again, 1479 * now that it is a tuple 1480 */ 1481 dim = tf.parameterList.length; 1482 i--; 1483 continue; 1484 } 1485 1486 /* Resolve "auto ref" storage class to be either ref or value, 1487 * based on the argument matching the parameter 1488 */ 1489 if (fparam.storageClass & STC.auto_) 1490 { 1491 Expression farg = mtype.fargs && i < mtype.fargs.dim ? (*mtype.fargs)[i] : fparam.defaultArg; 1492 if (farg && (fparam.storageClass & STC.ref_)) 1493 { 1494 if (farg.isLvalue()) 1495 { 1496 // ref parameter 1497 } 1498 else 1499 fparam.storageClass &= ~STC.ref_; // value parameter 1500 fparam.storageClass &= ~STC.auto_; // https://issues.dlang.org/show_bug.cgi?id=14656 1501 fparam.storageClass |= STC.autoref; 1502 } 1503 else if (mtype.incomplete && (fparam.storageClass & STC.ref_)) 1504 { 1505 // the default argument may have been temporarily removed, 1506 // see usage of `TypeFunction.incomplete`. 1507 // https://issues.dlang.org/show_bug.cgi?id=19891 1508 fparam.storageClass &= ~STC.auto_; 1509 fparam.storageClass |= STC.autoref; 1510 } 1511 else 1512 { 1513 .error(loc, "`auto` can only be used as part of `auto ref` for template function parameters"); 1514 errors = true; 1515 } 1516 } 1517 1518 // Remove redundant storage classes for type, they are already applied 1519 fparam.storageClass &= ~(STC.TYPECTOR | STC.in_); 1520 } 1521 argsc.pop(); 1522 } 1523 if (tf.isWild()) 1524 wildparams |= 2; 1525 1526 if (wildreturn && !wildparams) 1527 { 1528 .error(loc, "`inout` on `return` means `inout` must be on a parameter as well for `%s`", mtype.toChars()); 1529 errors = true; 1530 } 1531 tf.iswild = wildparams; 1532 1533 if (tf.isproperty && (tf.parameterList.varargs != VarArg.none || tf.parameterList.length > 2)) 1534 { 1535 .error(loc, "properties can only have zero, one, or two parameter"); 1536 errors = true; 1537 } 1538 1539 if (tf.parameterList.varargs == VarArg.variadic && tf.linkage != LINK.d && tf.parameterList.length == 0) 1540 { 1541 .error(loc, "variadic functions with non-D linkage must have at least one parameter"); 1542 errors = true; 1543 } 1544 1545 if (errors) 1546 return error(); 1547 1548 if (tf.next) 1549 tf.deco = tf.merge().deco; 1550 1551 /* Don't return merge(), because arg identifiers and default args 1552 * can be different 1553 * even though the types match 1554 */ 1555 return tf; 1556 } 1557 1558 Type visitDelegate(TypeDelegate mtype) 1559 { 1560 //printf("TypeDelegate::semantic() %s\n", toChars()); 1561 if (mtype.deco) // if semantic() already run 1562 { 1563 //printf("already done\n"); 1564 return mtype; 1565 } 1566 mtype.next = mtype.next.typeSemantic(loc, sc); 1567 if (mtype.next.ty != Tfunction) 1568 return error(); 1569 1570 /* In order to deal with https://issues.dlang.org/show_bug.cgi?id=4028 1571 * perhaps default arguments should 1572 * be removed from next before the merge. 1573 */ 1574 version (none) 1575 { 1576 return mtype.merge(); 1577 } 1578 else 1579 { 1580 /* Don't return merge(), because arg identifiers and default args 1581 * can be different 1582 * even though the types match 1583 */ 1584 mtype.deco = mtype.merge().deco; 1585 return mtype; 1586 } 1587 } 1588 1589 Type visitIdentifier(TypeIdentifier mtype) 1590 { 1591 Type t; 1592 Expression e; 1593 Dsymbol s; 1594 //printf("TypeIdentifier::semantic(%s)\n", mtype.toChars()); 1595 mtype.resolve(loc, sc, &e, &t, &s); 1596 if (t) 1597 { 1598 //printf("\tit's a type %d, %s, %s\n", t.ty, t.toChars(), t.deco); 1599 return t.addMod(mtype.mod); 1600 } 1601 else 1602 { 1603 if (s) 1604 { 1605 auto td = s.isTemplateDeclaration; 1606 if (td && td.onemember && td.onemember.isAggregateDeclaration) 1607 .error(loc, "template %s `%s` is used as a type without instantiation" 1608 ~ "; to instantiate it use `%s!(arguments)`", 1609 s.kind, s.toPrettyChars, s.ident.toChars); 1610 else 1611 .error(loc, "%s `%s` is used as a type", s.kind, s.toPrettyChars); 1612 //assert(0); 1613 } 1614 else if (e.op == TOK.variable) // special case: variable is used as a type 1615 { 1616 Dsymbol varDecl = mtype.toDsymbol(sc); 1617 const(Loc) varDeclLoc = varDecl.getLoc(); 1618 Module varDeclModule = varDecl.getModule(); 1619 1620 .error(loc, "variable `%s` is used as a type", mtype.toChars()); 1621 1622 if (varDeclModule != sc._module) // variable is imported 1623 { 1624 const(Loc) varDeclModuleImportLoc = varDeclModule.getLoc(); 1625 .errorSupplemental( 1626 varDeclModuleImportLoc, 1627 "variable `%s` is imported here from: `%s`", 1628 varDecl.toChars, 1629 varDeclModule.toPrettyChars, 1630 ); 1631 } 1632 1633 .errorSupplemental(varDeclLoc, "variable `%s` is declared here", varDecl.toChars); 1634 } 1635 else 1636 .error(loc, "`%s` is used as a type", mtype.toChars()); 1637 return error(); 1638 } 1639 } 1640 1641 Type visitInstance(TypeInstance mtype) 1642 { 1643 Type t; 1644 Expression e; 1645 Dsymbol s; 1646 1647 //printf("TypeInstance::semantic(%p, %s)\n", this, toChars()); 1648 { 1649 const errors = global.errors; 1650 mtype.resolve(loc, sc, &e, &t, &s); 1651 // if we had an error evaluating the symbol, suppress further errors 1652 if (!t && errors != global.errors) 1653 return error(); 1654 } 1655 1656 if (!t) 1657 { 1658 if (!e && s && s.errors) 1659 { 1660 // if there was an error evaluating the symbol, it might actually 1661 // be a type. Avoid misleading error messages. 1662 .error(loc, "`%s` had previous errors", mtype.toChars()); 1663 } 1664 else 1665 .error(loc, "`%s` is used as a type", mtype.toChars()); 1666 return error(); 1667 } 1668 return t; 1669 } 1670 1671 Type visitTypeof(TypeTypeof mtype) 1672 { 1673 //printf("TypeTypeof::semantic() %s\n", mtype.toChars()); 1674 Expression e; 1675 Type t; 1676 Dsymbol s; 1677 mtype.resolve(loc, sc, &e, &t, &s); 1678 if (s && (t = s.getType()) !is null) 1679 t = t.addMod(mtype.mod); 1680 if (!t) 1681 { 1682 .error(loc, "`%s` is used as a type", mtype.toChars()); 1683 return error(); 1684 } 1685 return t; 1686 } 1687 1688 Type visitTraits(TypeTraits mtype) 1689 { 1690 if (mtype.ty == Terror) 1691 return mtype; 1692 1693 const inAlias = (sc.flags & SCOPE.alias_) != 0; 1694 if (mtype.exp.ident != Id.allMembers && 1695 mtype.exp.ident != Id.derivedMembers && 1696 mtype.exp.ident != Id.getMember && 1697 mtype.exp.ident != Id.parent && 1698 mtype.exp.ident != Id.getOverloads && 1699 mtype.exp.ident != Id.getVirtualFunctions && 1700 mtype.exp.ident != Id.getVirtualMethods && 1701 mtype.exp.ident != Id.getAttributes && 1702 mtype.exp.ident != Id.getUnitTests && 1703 mtype.exp.ident != Id.getAliasThis) 1704 { 1705 static immutable (const(char)*)[2] ctxt = ["as type", "in alias"]; 1706 .error(mtype.loc, "trait `%s` is either invalid or not supported %s", 1707 mtype.exp.ident.toChars, ctxt[inAlias]); 1708 mtype.ty = Terror; 1709 return mtype; 1710 } 1711 1712 import dmd.traits : semanticTraits; 1713 Type result; 1714 1715 if (Expression e = semanticTraits(mtype.exp, sc)) 1716 { 1717 switch (e.op) 1718 { 1719 case TOK.dotVariable: 1720 mtype.sym = (cast(DotVarExp)e).var; 1721 break; 1722 case TOK.variable: 1723 mtype.sym = (cast(VarExp)e).var; 1724 break; 1725 case TOK.function_: 1726 auto fe = cast(FuncExp)e; 1727 mtype.sym = fe.td ? fe.td : fe.fd; 1728 break; 1729 case TOK.dotTemplateDeclaration: 1730 mtype.sym = (cast(DotTemplateExp)e).td; 1731 break; 1732 case TOK.dSymbol: 1733 mtype.sym = (cast(DsymbolExp)e).s; 1734 break; 1735 case TOK.template_: 1736 mtype.sym = (cast(TemplateExp)e).td; 1737 break; 1738 case TOK.scope_: 1739 mtype.sym = (cast(ScopeExp)e).sds; 1740 break; 1741 case TOK.tuple: 1742 TupleExp te = e.toTupleExp(); 1743 Objects* elems = new Objects(te.exps.dim); 1744 foreach (i; 0 .. elems.dim) 1745 { 1746 auto src = (*te.exps)[i]; 1747 switch (src.op) 1748 { 1749 case TOK.type: 1750 (*elems)[i] = (cast(TypeExp)src).type; 1751 break; 1752 case TOK.dotType: 1753 (*elems)[i] = (cast(DotTypeExp)src).sym.isType(); 1754 break; 1755 case TOK.overloadSet: 1756 (*elems)[i] = (cast(OverExp)src).type; 1757 break; 1758 default: 1759 if (auto sym = isDsymbol(src)) 1760 (*elems)[i] = sym; 1761 else 1762 (*elems)[i] = src; 1763 } 1764 } 1765 TupleDeclaration td = new TupleDeclaration(e.loc, Identifier.generateId("__aliastup"), elems); 1766 mtype.sym = td; 1767 break; 1768 case TOK.dotType: 1769 result = (cast(DotTypeExp)e).sym.isType(); 1770 break; 1771 case TOK.type: 1772 result = (cast(TypeExp)e).type; 1773 break; 1774 case TOK.overloadSet: 1775 result = (cast(OverExp)e).type; 1776 break; 1777 default: 1778 break; 1779 } 1780 } 1781 1782 if (result) 1783 result = result.addMod(mtype.mod); 1784 if (!inAlias && !result) 1785 { 1786 if (!global.errors) 1787 .error(mtype.loc, "`%s` does not give a valid type", mtype.toChars); 1788 return error(); 1789 } 1790 1791 return result; 1792 } 1793 1794 Type visitReturn(TypeReturn mtype) 1795 { 1796 //printf("TypeReturn::semantic() %s\n", toChars()); 1797 Expression e; 1798 Type t; 1799 Dsymbol s; 1800 mtype.resolve(loc, sc, &e, &t, &s); 1801 if (s && (t = s.getType()) !is null) 1802 t = t.addMod(mtype.mod); 1803 if (!t) 1804 { 1805 .error(loc, "`%s` is used as a type", mtype.toChars()); 1806 return error(); 1807 } 1808 return t; 1809 } 1810 1811 Type visitStruct(TypeStruct mtype) 1812 { 1813 //printf("TypeStruct::semantic('%s')\n", mtype.toChars()); 1814 if (mtype.deco) 1815 return mtype; 1816 1817 /* Don't semantic for sym because it should be deferred until 1818 * sizeof needed or its members accessed. 1819 */ 1820 // instead, parent should be set correctly 1821 assert(mtype.sym.parent); 1822 1823 if (mtype.sym.type.ty == Terror) 1824 return error(); 1825 1826 return merge(mtype); 1827 } 1828 1829 Type visitEnum(TypeEnum mtype) 1830 { 1831 //printf("TypeEnum::semantic() %s\n", toChars()); 1832 return mtype.deco ? mtype : merge(mtype); 1833 } 1834 1835 Type visitClass(TypeClass mtype) 1836 { 1837 //printf("TypeClass::semantic(%s)\n", mtype.toChars()); 1838 if (mtype.deco) 1839 return mtype; 1840 1841 /* Don't semantic for sym because it should be deferred until 1842 * sizeof needed or its members accessed. 1843 */ 1844 // instead, parent should be set correctly 1845 assert(mtype.sym.parent); 1846 1847 if (mtype.sym.type.ty == Terror) 1848 return error(); 1849 1850 return merge(mtype); 1851 } 1852 1853 Type visitTuple(TypeTuple mtype) 1854 { 1855 //printf("TypeTuple::semantic(this = %p)\n", this); 1856 //printf("TypeTuple::semantic() %p, %s\n", this, toChars()); 1857 if (!mtype.deco) 1858 mtype.deco = merge(mtype).deco; 1859 1860 /* Don't return merge(), because a tuple with one type has the 1861 * same deco as that type. 1862 */ 1863 return mtype; 1864 } 1865 1866 Type visitSlice(TypeSlice mtype) 1867 { 1868 //printf("TypeSlice::semantic() %s\n", toChars()); 1869 Type tn = mtype.next.typeSemantic(loc, sc); 1870 //printf("next: %s\n", tn.toChars()); 1871 1872 Type tbn = tn.toBasetype(); 1873 if (tbn.ty != Ttuple) 1874 { 1875 .error(loc, "can only slice tuple types, not `%s`", tbn.toChars()); 1876 return error(); 1877 } 1878 TypeTuple tt = cast(TypeTuple)tbn; 1879 1880 mtype.lwr = semanticLength(sc, tbn, mtype.lwr); 1881 mtype.upr = semanticLength(sc, tbn, mtype.upr); 1882 mtype.lwr = mtype.lwr.ctfeInterpret(); 1883 mtype.upr = mtype.upr.ctfeInterpret(); 1884 if (mtype.lwr.op == TOK.error || mtype.upr.op == TOK.error) 1885 return error(); 1886 1887 uinteger_t i1 = mtype.lwr.toUInteger(); 1888 uinteger_t i2 = mtype.upr.toUInteger(); 1889 if (!(i1 <= i2 && i2 <= tt.arguments.dim)) 1890 { 1891 .error(loc, "slice `[%llu..%llu]` is out of range of `[0..%llu]`", 1892 cast(ulong)i1, cast(ulong)i2, cast(ulong)tt.arguments.dim); 1893 return error(); 1894 } 1895 1896 mtype.next = tn; 1897 mtype.transitive(); 1898 1899 auto args = new Parameters(); 1900 args.reserve(cast(size_t)(i2 - i1)); 1901 foreach (arg; (*tt.arguments)[cast(size_t)i1 .. cast(size_t)i2]) 1902 { 1903 args.push(arg); 1904 } 1905 Type t = new TypeTuple(args); 1906 return t.typeSemantic(loc, sc); 1907 } 1908 1909 Type visitMixin(TypeMixin mtype) 1910 { 1911 //printf("TypeMixin::semantic() %s\n", toChars()); 1912 auto o = mtype.compileTypeMixin(loc, sc); 1913 if (auto t = o.isType()) 1914 { 1915 return t.typeSemantic(loc, sc); 1916 } 1917 else if (auto e = o.isExpression()) 1918 { 1919 e = e.expressionSemantic(sc); 1920 if (auto et = e.isTypeExp()) 1921 return et.type; 1922 else 1923 { 1924 if (!global.errors) 1925 .error(e.loc, "`%s` does not give a valid type", o.toChars); 1926 } 1927 } 1928 return error(); 1929 } 1930 1931 switch (t.ty) 1932 { 1933 default: return visitType(t); 1934 case Tvector: return visitVector(cast(TypeVector)t); 1935 case Tsarray: return visitSArray(cast(TypeSArray)t); 1936 case Tarray: return visitDArray(cast(TypeDArray)t); 1937 case Taarray: return visitAArray(cast(TypeAArray)t); 1938 case Tpointer: return visitPointer(cast(TypePointer)t); 1939 case Treference: return visitReference(cast(TypeReference)t); 1940 case Tfunction: return visitFunction(cast(TypeFunction)t); 1941 case Tdelegate: return visitDelegate(cast(TypeDelegate)t); 1942 case Tident: return visitIdentifier(cast(TypeIdentifier)t); 1943 case Tinstance: return visitInstance(cast(TypeInstance)t); 1944 case Ttypeof: return visitTypeof(cast(TypeTypeof)t); 1945 case Ttraits: return visitTraits(cast(TypeTraits)t); 1946 case Treturn: return visitReturn(cast(TypeReturn)t); 1947 case Tstruct: return visitStruct(cast(TypeStruct)t); 1948 case Tenum: return visitEnum(cast(TypeEnum)t); 1949 case Tclass: return visitClass(cast(TypeClass)t); 1950 case Ttuple: return visitTuple (cast(TypeTuple)t); 1951 case Tslice: return visitSlice(cast(TypeSlice)t); 1952 case Tmixin: return visitMixin(cast(TypeMixin)t); 1953 } 1954 } 1955 1956 /****************************************** 1957 * Compile the MixinType, returning the type or expression AST. 1958 * 1959 * Doesn't run semantic() on the returned object. 1960 * Params: 1961 * tm = mixin to compile as a type or expression 1962 * loc = location for error messages 1963 * sc = context 1964 * Return: 1965 * null if error, else RootObject AST as parsed 1966 */ 1967 RootObject compileTypeMixin(TypeMixin tm, Loc loc, Scope* sc) 1968 { 1969 OutBuffer buf; 1970 if (expressionsToString(buf, sc, tm.exps)) 1971 return null; 1972 1973 const errors = global.errors; 1974 const len = buf.length; 1975 buf.writeByte(0); 1976 const str = buf.extractSlice()[0 .. len]; 1977 scope p = new Parser!ASTCodegen(loc, sc._module, str, false); 1978 p.nextToken(); 1979 //printf("p.loc.linnum = %d\n", p.loc.linnum); 1980 1981 auto o = p.parseTypeOrAssignExp(TOK.endOfFile); 1982 p.reportDiagnostics(); 1983 if (errors != global.errors) 1984 { 1985 assert(global.errors != errors); // should have caught all these cases 1986 return null; 1987 } 1988 if (p.token.value != TOK.endOfFile) 1989 { 1990 .error(loc, "incomplete mixin type `%s`", str.ptr); 1991 return null; 1992 } 1993 1994 Type t = o.isType(); 1995 Expression e = t ? t.typeToExpression() : o.isExpression(); 1996 1997 return (!e && t) ? t : e; 1998 } 1999 2000 2001 /************************************ 2002 * If an identical type to `type` is in `type.stringtable`, return 2003 * the latter one. Otherwise, add it to `type.stringtable`. 2004 * Some types don't get merged and are returned as-is. 2005 * Params: 2006 * type = Type to check against existing types 2007 * Returns: 2008 * the type that was merged 2009 */ 2010 Type merge(Type type) 2011 { 2012 switch (type.ty) 2013 { 2014 case Terror: 2015 case Ttypeof: 2016 case Tident: 2017 case Tinstance: 2018 case Tmixin: 2019 return type; 2020 2021 case Tsarray: 2022 // prevents generating the mangle if the array dim is not yet known 2023 if (!(cast(TypeSArray) type).dim.isIntegerExp()) 2024 return type; 2025 goto default; 2026 2027 case Tenum: 2028 break; 2029 2030 case Taarray: 2031 if (!(cast(TypeAArray)type).index.merge().deco) 2032 return type; 2033 goto default; 2034 2035 default: 2036 if (type.nextOf() && !type.nextOf().deco) 2037 return type; 2038 break; 2039 } 2040 2041 //printf("merge(%s)\n", toChars()); 2042 if (!type.deco) 2043 { 2044 OutBuffer buf; 2045 buf.reserve(32); 2046 2047 mangleToBuffer(type, &buf); 2048 2049 auto sv = type.stringtable.update(buf[]); 2050 if (sv.value) 2051 { 2052 Type t = sv.value; 2053 debug 2054 { 2055 import core.stdc.stdio; 2056 if (!t.deco) 2057 printf("t = %s\n", t.toChars()); 2058 } 2059 assert(t.deco); 2060 //printf("old value, deco = '%s' %p\n", t.deco, t.deco); 2061 return t; 2062 } 2063 else 2064 { 2065 Type t = stripDefaultArgs(type); 2066 sv.value = t; 2067 type.deco = t.deco = cast(char*)sv.toDchars(); 2068 //printf("new value, deco = '%s' %p\n", t.deco, t.deco); 2069 return t; 2070 } 2071 } 2072 return type; 2073 } 2074 2075 /*************************************** 2076 * Calculate built-in properties which just the type is necessary. 2077 * 2078 * Params: 2079 * t = the type for which the property is calculated 2080 * scope_ = the scope from which the property is being accessed. Used for visibility checks only. 2081 * loc = the location where the property is encountered 2082 * ident = the identifier of the property 2083 * flag = if flag & 1, don't report "not a property" error and just return NULL. 2084 * Returns: 2085 * expression representing the property, or null if not a property and (flag & 1) 2086 */ 2087 Expression getProperty(Type t, Scope* scope_, const ref Loc loc, Identifier ident, int flag) 2088 { 2089 Expression visitType(Type mt) 2090 { 2091 Expression e; 2092 static if (LOGDOTEXP) 2093 { 2094 printf("Type::getProperty(type = '%s', ident = '%s')\n", mt.toChars(), ident.toChars()); 2095 } 2096 if (ident == Id.__sizeof) 2097 { 2098 d_uns64 sz = mt.size(loc); 2099 if (sz == SIZE_INVALID) 2100 return new ErrorExp(); 2101 e = new IntegerExp(loc, sz, Type.tsize_t); 2102 } 2103 else if (ident == Id.__xalignof) 2104 { 2105 const explicitAlignment = mt.alignment(); 2106 const naturalAlignment = mt.alignsize(); 2107 const actualAlignment = (explicitAlignment == STRUCTALIGN_DEFAULT ? naturalAlignment : explicitAlignment); 2108 e = new IntegerExp(loc, actualAlignment, Type.tsize_t); 2109 } 2110 else if (ident == Id._init) 2111 { 2112 Type tb = mt.toBasetype(); 2113 e = mt.defaultInitLiteral(loc); 2114 if (tb.ty == Tstruct && tb.needsNested()) 2115 { 2116 e.isStructLiteralExp().useStaticInit = true; 2117 } 2118 } 2119 else if (ident == Id._mangleof) 2120 { 2121 if (!mt.deco) 2122 { 2123 error(loc, "forward reference of type `%s.mangleof`", mt.toChars()); 2124 e = new ErrorExp(); 2125 } 2126 else 2127 { 2128 e = new StringExp(loc, mt.deco.toDString()); 2129 Scope sc; 2130 e = e.expressionSemantic(&sc); 2131 } 2132 } 2133 else if (ident == Id.stringof) 2134 { 2135 const s = mt.toChars(); 2136 e = new StringExp(loc, s.toDString()); 2137 Scope sc; 2138 e = e.expressionSemantic(&sc); 2139 } 2140 else if (flag && mt != Type.terror) 2141 { 2142 return null; 2143 } 2144 else 2145 { 2146 Dsymbol s = null; 2147 if (mt.ty == Tstruct || mt.ty == Tclass || mt.ty == Tenum) 2148 s = mt.toDsymbol(null); 2149 if (s) 2150 s = s.search_correct(ident); 2151 if (s && !symbolIsVisible(scope_, s)) 2152 s = null; 2153 if (mt != Type.terror) 2154 { 2155 if (s) 2156 error(loc, "no property `%s` for type `%s`, did you mean `%s`?", ident.toChars(), mt.toChars(), s.toPrettyChars()); 2157 else 2158 { 2159 if (ident == Id.call && mt.ty == Tclass) 2160 error(loc, "no property `%s` for type `%s`, did you mean `new %s`?", ident.toChars(), mt.toChars(), mt.toPrettyChars()); 2161 else 2162 { 2163 if (const n = importHint(ident.toString())) 2164 error(loc, "no property `%s` for type `%s`, perhaps `import %.*s;` is needed?", ident.toChars(), mt.toChars(), cast(int)n.length, n.ptr); 2165 else 2166 error(loc, "no property `%s` for type `%s`", ident.toChars(), mt.toPrettyChars(true)); 2167 } 2168 } 2169 } 2170 e = new ErrorExp(); 2171 } 2172 return e; 2173 } 2174 2175 Expression visitError(TypeError) 2176 { 2177 return new ErrorExp(); 2178 } 2179 2180 Expression visitBasic(TypeBasic mt) 2181 { 2182 Expression integerValue(dinteger_t i) 2183 { 2184 return new IntegerExp(loc, i, mt); 2185 } 2186 2187 Expression intValue(dinteger_t i) 2188 { 2189 return new IntegerExp(loc, i, Type.tint32); 2190 } 2191 2192 Expression floatValue(real_t r) 2193 { 2194 if (mt.isreal() || mt.isimaginary()) 2195 return new RealExp(loc, r, mt); 2196 else 2197 { 2198 return new ComplexExp(loc, complex_t(r, r), mt); 2199 } 2200 } 2201 2202 //printf("TypeBasic::getProperty('%s')\n", ident.toChars()); 2203 if (ident == Id.max) 2204 { 2205 switch (mt.ty) 2206 { 2207 case Tint8: return integerValue(byte.max); 2208 case Tuns8: return integerValue(ubyte.max); 2209 case Tint16: return integerValue(short.max); 2210 case Tuns16: return integerValue(ushort.max); 2211 case Tint32: return integerValue(int.max); 2212 case Tuns32: return integerValue(uint.max); 2213 case Tint64: return integerValue(long.max); 2214 case Tuns64: return integerValue(ulong.max); 2215 case Tbool: return integerValue(bool.max); 2216 case Tchar: return integerValue(char.max); 2217 case Twchar: return integerValue(wchar.max); 2218 case Tdchar: return integerValue(dchar.max); 2219 case Tcomplex32: 2220 case Timaginary32: 2221 case Tfloat32: return floatValue(target.FloatProperties.max); 2222 case Tcomplex64: 2223 case Timaginary64: 2224 case Tfloat64: return floatValue(target.DoubleProperties.max); 2225 case Tcomplex80: 2226 case Timaginary80: 2227 case Tfloat80: return floatValue(target.RealProperties.max); 2228 default: break; 2229 } 2230 } 2231 else if (ident == Id.min) 2232 { 2233 switch (mt.ty) 2234 { 2235 case Tint8: return integerValue(byte.min); 2236 case Tuns8: 2237 case Tuns16: 2238 case Tuns32: 2239 case Tuns64: 2240 case Tbool: 2241 case Tchar: 2242 case Twchar: 2243 case Tdchar: return integerValue(0); 2244 case Tint16: return integerValue(short.min); 2245 case Tint32: return integerValue(int.min); 2246 case Tint64: return integerValue(long.min); 2247 default: break; 2248 } 2249 } 2250 else if (ident == Id.min_normal) 2251 { 2252 switch (mt.ty) 2253 { 2254 case Tcomplex32: 2255 case Timaginary32: 2256 case Tfloat32: return floatValue(target.FloatProperties.min_normal); 2257 case Tcomplex64: 2258 case Timaginary64: 2259 case Tfloat64: return floatValue(target.DoubleProperties.min_normal); 2260 case Tcomplex80: 2261 case Timaginary80: 2262 case Tfloat80: return floatValue(target.RealProperties.min_normal); 2263 default: break; 2264 } 2265 } 2266 else if (ident == Id.nan) 2267 { 2268 switch (mt.ty) 2269 { 2270 case Tcomplex32: 2271 case Tcomplex64: 2272 case Tcomplex80: 2273 case Timaginary32: 2274 case Timaginary64: 2275 case Timaginary80: 2276 case Tfloat32: 2277 case Tfloat64: 2278 case Tfloat80: return floatValue(target.RealProperties.nan); 2279 default: break; 2280 } 2281 } 2282 else if (ident == Id.infinity) 2283 { 2284 switch (mt.ty) 2285 { 2286 case Tcomplex32: 2287 case Tcomplex64: 2288 case Tcomplex80: 2289 case Timaginary32: 2290 case Timaginary64: 2291 case Timaginary80: 2292 case Tfloat32: 2293 case Tfloat64: 2294 case Tfloat80: return floatValue(target.RealProperties.infinity); 2295 default: break; 2296 } 2297 } 2298 else if (ident == Id.dig) 2299 { 2300 switch (mt.ty) 2301 { 2302 case Tcomplex32: 2303 case Timaginary32: 2304 case Tfloat32: return intValue(target.FloatProperties.dig); 2305 case Tcomplex64: 2306 case Timaginary64: 2307 case Tfloat64: return intValue(target.DoubleProperties.dig); 2308 case Tcomplex80: 2309 case Timaginary80: 2310 case Tfloat80: return intValue(target.RealProperties.dig); 2311 default: break; 2312 } 2313 } 2314 else if (ident == Id.epsilon) 2315 { 2316 switch (mt.ty) 2317 { 2318 case Tcomplex32: 2319 case Timaginary32: 2320 case Tfloat32: return floatValue(target.FloatProperties.epsilon); 2321 case Tcomplex64: 2322 case Timaginary64: 2323 case Tfloat64: return floatValue(target.DoubleProperties.epsilon); 2324 case Tcomplex80: 2325 case Timaginary80: 2326 case Tfloat80: return floatValue(target.RealProperties.epsilon); 2327 default: break; 2328 } 2329 } 2330 else if (ident == Id.mant_dig) 2331 { 2332 switch (mt.ty) 2333 { 2334 case Tcomplex32: 2335 case Timaginary32: 2336 case Tfloat32: return intValue(target.FloatProperties.mant_dig); 2337 case Tcomplex64: 2338 case Timaginary64: 2339 case Tfloat64: return intValue(target.DoubleProperties.mant_dig); 2340 case Tcomplex80: 2341 case Timaginary80: 2342 case Tfloat80: return intValue(target.RealProperties.mant_dig); 2343 default: break; 2344 } 2345 } 2346 else if (ident == Id.max_10_exp) 2347 { 2348 switch (mt.ty) 2349 { 2350 case Tcomplex32: 2351 case Timaginary32: 2352 case Tfloat32: return intValue(target.FloatProperties.max_10_exp); 2353 case Tcomplex64: 2354 case Timaginary64: 2355 case Tfloat64: return intValue(target.DoubleProperties.max_10_exp); 2356 case Tcomplex80: 2357 case Timaginary80: 2358 case Tfloat80: return intValue(target.RealProperties.max_10_exp); 2359 default: break; 2360 } 2361 } 2362 else if (ident == Id.max_exp) 2363 { 2364 switch (mt.ty) 2365 { 2366 case Tcomplex32: 2367 case Timaginary32: 2368 case Tfloat32: return intValue(target.FloatProperties.max_exp); 2369 case Tcomplex64: 2370 case Timaginary64: 2371 case Tfloat64: return intValue(target.DoubleProperties.max_exp); 2372 case Tcomplex80: 2373 case Timaginary80: 2374 case Tfloat80: return intValue(target.RealProperties.max_exp); 2375 default: break; 2376 } 2377 } 2378 else if (ident == Id.min_10_exp) 2379 { 2380 switch (mt.ty) 2381 { 2382 case Tcomplex32: 2383 case Timaginary32: 2384 case Tfloat32: return intValue(target.FloatProperties.min_10_exp); 2385 case Tcomplex64: 2386 case Timaginary64: 2387 case Tfloat64: return intValue(target.DoubleProperties.min_10_exp); 2388 case Tcomplex80: 2389 case Timaginary80: 2390 case Tfloat80: return intValue(target.RealProperties.min_10_exp); 2391 default: break; 2392 } 2393 } 2394 else if (ident == Id.min_exp) 2395 { 2396 switch (mt.ty) 2397 { 2398 case Tcomplex32: 2399 case Timaginary32: 2400 case Tfloat32: return intValue(target.FloatProperties.min_exp); 2401 case Tcomplex64: 2402 case Timaginary64: 2403 case Tfloat64: return intValue(target.DoubleProperties.min_exp); 2404 case Tcomplex80: 2405 case Timaginary80: 2406 case Tfloat80: return intValue(target.RealProperties.min_exp); 2407 default: break; 2408 } 2409 } 2410 return visitType(mt); 2411 } 2412 2413 Expression visitVector(TypeVector mt) 2414 { 2415 return visitType(mt); 2416 } 2417 2418 Expression visitEnum(TypeEnum mt) 2419 { 2420 Expression e; 2421 if (ident == Id.max || ident == Id.min) 2422 { 2423 return mt.sym.getMaxMinValue(loc, ident); 2424 } 2425 else if (ident == Id._init) 2426 { 2427 e = mt.defaultInitLiteral(loc); 2428 } 2429 else if (ident == Id.stringof) 2430 { 2431 e = new StringExp(loc, mt.toString()); 2432 Scope sc; 2433 e = e.expressionSemantic(&sc); 2434 } 2435 else if (ident == Id._mangleof) 2436 { 2437 e = visitType(mt); 2438 } 2439 else 2440 { 2441 e = mt.toBasetype().getProperty(scope_, loc, ident, flag); 2442 } 2443 return e; 2444 } 2445 2446 Expression visitTuple(TypeTuple mt) 2447 { 2448 Expression e; 2449 static if (LOGDOTEXP) 2450 { 2451 printf("TypeTuple::getProperty(type = '%s', ident = '%s')\n", mt.toChars(), ident.toChars()); 2452 } 2453 if (ident == Id.length) 2454 { 2455 e = new IntegerExp(loc, mt.arguments.dim, Type.tsize_t); 2456 } 2457 else if (ident == Id._init) 2458 { 2459 e = mt.defaultInitLiteral(loc); 2460 } 2461 else if (flag) 2462 { 2463 e = null; 2464 } 2465 else 2466 { 2467 error(loc, "no property `%s` for tuple `%s`", ident.toChars(), mt.toChars()); 2468 e = new ErrorExp(); 2469 } 2470 return e; 2471 } 2472 2473 switch (t.ty) 2474 { 2475 default: return t.isTypeBasic() ? 2476 visitBasic(cast(TypeBasic)t) : 2477 visitType(t); 2478 2479 case Terror: return visitError (cast(TypeError)t); 2480 case Tvector: return visitVector(cast(TypeVector)t); 2481 case Tenum: return visitEnum (cast(TypeEnum)t); 2482 case Ttuple: return visitTuple (cast(TypeTuple)t); 2483 } 2484 } 2485 2486 /*************************************** 2487 * Normalize `e` as the result of resolve() process. 2488 */ 2489 private void resolveExp(Expression e, Type *pt, Expression *pe, Dsymbol* ps) 2490 { 2491 *pt = null; 2492 *pe = null; 2493 *ps = null; 2494 2495 Dsymbol s; 2496 switch (e.op) 2497 { 2498 case TOK.error: 2499 *pt = Type.terror; 2500 return; 2501 2502 case TOK.type: 2503 *pt = e.type; 2504 return; 2505 2506 case TOK.variable: 2507 s = (cast(VarExp)e).var; 2508 if (s.isVarDeclaration()) 2509 goto default; 2510 //if (s.isOverDeclaration()) 2511 // todo; 2512 break; 2513 2514 case TOK.template_: 2515 // TemplateDeclaration 2516 s = (cast(TemplateExp)e).td; 2517 break; 2518 2519 case TOK.scope_: 2520 s = (cast(ScopeExp)e).sds; 2521 // TemplateDeclaration, TemplateInstance, Import, Package, Module 2522 break; 2523 2524 case TOK.function_: 2525 s = getDsymbol(e); 2526 break; 2527 2528 case TOK.dotTemplateDeclaration: 2529 s = (cast(DotTemplateExp)e).td; 2530 break; 2531 2532 //case TOK.this_: 2533 //case TOK.super_: 2534 2535 //case TOK.tuple: 2536 2537 //case TOK.overloadSet: 2538 2539 //case TOK.dotVariable: 2540 //case TOK.dotTemplateInstance: 2541 //case TOK.dotType: 2542 //case TOK.dotIdentifier: 2543 2544 default: 2545 *pe = e; 2546 return; 2547 } 2548 2549 *ps = s; 2550 } 2551 2552 /************************************ 2553 * Resolve type 'mt' to either type, symbol, or expression. 2554 * If errors happened, resolved to Type.terror. 2555 * 2556 * Params: 2557 * mt = type to be resolved 2558 * loc = the location where the type is encountered 2559 * sc = the scope of the type 2560 * pe = is set if t is an expression 2561 * pt = is set if t is a type 2562 * ps = is set if t is a symbol 2563 * intypeid = true if in type id 2564 */ 2565 void resolve(Type mt, const ref Loc loc, Scope* sc, Expression* pe, Type* pt, Dsymbol* ps, bool intypeid = false) 2566 { 2567 void returnExp(Expression e) 2568 { 2569 *pt = null; 2570 *pe = e; 2571 *ps = null; 2572 } 2573 2574 void returnType(Type t) 2575 { 2576 *pt = t; 2577 *pe = null; 2578 *ps = null; 2579 } 2580 2581 void returnSymbol(Dsymbol s) 2582 { 2583 *pt = null; 2584 *pe = null; 2585 *ps = s; 2586 } 2587 2588 void returnError() 2589 { 2590 returnType(Type.terror); 2591 } 2592 2593 void visitType(Type mt) 2594 { 2595 //printf("Type::resolve() %s, %d\n", mt.toChars(), mt.ty); 2596 Type t = typeSemantic(mt, loc, sc); 2597 assert(t); 2598 returnType(t); 2599 } 2600 2601 void visitSArray(TypeSArray mt) 2602 { 2603 //printf("TypeSArray::resolve() %s\n", mt.toChars()); 2604 mt.next.resolve(loc, sc, pe, pt, ps, intypeid); 2605 //printf("s = %p, e = %p, t = %p\n", *ps, *pe, *pt); 2606 if (*pe) 2607 { 2608 // It's really an index expression 2609 if (Dsymbol s = getDsymbol(*pe)) 2610 *pe = new DsymbolExp(loc, s); 2611 returnExp(new ArrayExp(loc, *pe, mt.dim)); 2612 } 2613 else if (*ps) 2614 { 2615 Dsymbol s = *ps; 2616 if (auto tup = s.isTupleDeclaration()) 2617 { 2618 mt.dim = semanticLength(sc, tup, mt.dim); 2619 mt.dim = mt.dim.ctfeInterpret(); 2620 if (mt.dim.op == TOK.error) 2621 return returnError(); 2622 2623 const d = mt.dim.toUInteger(); 2624 if (d >= tup.objects.dim) 2625 { 2626 error(loc, "tuple index `%llu` exceeds length %u", d, tup.objects.dim); 2627 return returnError(); 2628 } 2629 2630 RootObject o = (*tup.objects)[cast(size_t)d]; 2631 if (o.dyncast() == DYNCAST.dsymbol) 2632 { 2633 return returnSymbol(cast(Dsymbol)o); 2634 } 2635 if (o.dyncast() == DYNCAST.expression) 2636 { 2637 Expression e = cast(Expression)o; 2638 if (e.op == TOK.dSymbol) 2639 return returnSymbol((cast(DsymbolExp)e).s); 2640 else 2641 return returnExp(e); 2642 } 2643 if (o.dyncast() == DYNCAST.type) 2644 { 2645 return returnType((cast(Type)o).addMod(mt.mod)); 2646 } 2647 2648 /* Create a new TupleDeclaration which 2649 * is a slice [d..d+1] out of the old one. 2650 * Do it this way because TemplateInstance::semanticTiargs() 2651 * can handle unresolved Objects this way. 2652 */ 2653 auto objects = new Objects(1); 2654 (*objects)[0] = o; 2655 return returnSymbol(new TupleDeclaration(loc, tup.ident, objects)); 2656 } 2657 else 2658 return visitType(mt); 2659 } 2660 else 2661 { 2662 if ((*pt).ty != Terror) 2663 mt.next = *pt; // prevent re-running semantic() on 'next' 2664 visitType(mt); 2665 } 2666 2667 } 2668 2669 void visitDArray(TypeDArray mt) 2670 { 2671 //printf("TypeDArray::resolve() %s\n", mt.toChars()); 2672 mt.next.resolve(loc, sc, pe, pt, ps, intypeid); 2673 //printf("s = %p, e = %p, t = %p\n", *ps, *pe, *pt); 2674 if (*pe) 2675 { 2676 // It's really a slice expression 2677 if (Dsymbol s = getDsymbol(*pe)) 2678 *pe = new DsymbolExp(loc, s); 2679 returnExp(new ArrayExp(loc, *pe)); 2680 } 2681 else if (*ps) 2682 { 2683 if (auto tup = (*ps).isTupleDeclaration()) 2684 { 2685 // keep *ps 2686 } 2687 else 2688 visitType(mt); 2689 } 2690 else 2691 { 2692 if ((*pt).ty != Terror) 2693 mt.next = *pt; // prevent re-running semantic() on 'next' 2694 visitType(mt); 2695 } 2696 } 2697 2698 void visitAArray(TypeAArray mt) 2699 { 2700 //printf("TypeAArray::resolve() %s\n", mt.toChars()); 2701 // Deal with the case where we thought the index was a type, but 2702 // in reality it was an expression. 2703 if (mt.index.ty == Tident || mt.index.ty == Tinstance || mt.index.ty == Tsarray) 2704 { 2705 Expression e; 2706 Type t; 2707 Dsymbol s; 2708 mt.index.resolve(loc, sc, &e, &t, &s, intypeid); 2709 if (e) 2710 { 2711 // It was an expression - 2712 // Rewrite as a static array 2713 auto tsa = new TypeSArray(mt.next, e); 2714 tsa.mod = mt.mod; // just copy mod field so tsa's semantic is not yet done 2715 return tsa.resolve(loc, sc, pe, pt, ps, intypeid); 2716 } 2717 else if (t) 2718 mt.index = t; 2719 else 2720 .error(loc, "index is not a type or an expression"); 2721 } 2722 visitType(mt); 2723 } 2724 2725 /************************************* 2726 * Takes an array of Identifiers and figures out if 2727 * it represents a Type or an Expression. 2728 * Output: 2729 * if expression, *pe is set 2730 * if type, *pt is set 2731 */ 2732 void visitIdentifier(TypeIdentifier mt) 2733 { 2734 //printf("TypeIdentifier::resolve(sc = %p, idents = '%s')\n", sc, mt.toChars()); 2735 if ((mt.ident.equals(Id._super) || mt.ident.equals(Id.This)) && !hasThis(sc)) 2736 { 2737 // @@@DEPRECATED_v2.091@@@. 2738 // Made an error in 2.086. 2739 // Eligible for removal in 2.091. 2740 if (mt.ident.equals(Id._super)) 2741 { 2742 error(mt.loc, "Using `super` as a type is obsolete. Use `typeof(super)` instead"); 2743 } 2744 // @@@DEPRECATED_v2.091@@@. 2745 // Made an error in 2.086. 2746 // Eligible for removal in 2.091. 2747 if (mt.ident.equals(Id.This)) 2748 { 2749 error(mt.loc, "Using `this` as a type is obsolete. Use `typeof(this)` instead"); 2750 } 2751 if (AggregateDeclaration ad = sc.getStructClassScope()) 2752 { 2753 if (ClassDeclaration cd = ad.isClassDeclaration()) 2754 { 2755 if (mt.ident.equals(Id.This)) 2756 mt.ident = cd.ident; 2757 else if (cd.baseClass && mt.ident.equals(Id._super)) 2758 mt.ident = cd.baseClass.ident; 2759 } 2760 else 2761 { 2762 StructDeclaration sd = ad.isStructDeclaration(); 2763 if (sd && mt.ident.equals(Id.This)) 2764 mt.ident = sd.ident; 2765 } 2766 } 2767 } 2768 if (mt.ident == Id.ctfe) 2769 { 2770 error(loc, "variable `__ctfe` cannot be read at compile time"); 2771 return returnError(); 2772 } 2773 2774 Dsymbol scopesym; 2775 Dsymbol s = sc.search(loc, mt.ident, &scopesym); 2776 /* 2777 * https://issues.dlang.org/show_bug.cgi?id=1170 2778 * https://issues.dlang.org/show_bug.cgi?id=10739 2779 * 2780 * If a symbol is not found, it might be declared in 2781 * a mixin-ed string or a mixin-ed template, so before 2782 * issuing an error semantically analyze all string/template 2783 * mixins that are members of the current ScopeDsymbol. 2784 */ 2785 if (!s && sc.enclosing) 2786 { 2787 ScopeDsymbol sds = sc.enclosing.scopesym; 2788 if (sds && sds.members) 2789 { 2790 void semanticOnMixin(Dsymbol member) 2791 { 2792 if (auto compileDecl = member.isCompileDeclaration()) 2793 compileDecl.dsymbolSemantic(sc); 2794 else if (auto mixinTempl = member.isTemplateMixin()) 2795 mixinTempl.dsymbolSemantic(sc); 2796 } 2797 sds.members.foreachDsymbol( s => semanticOnMixin(s) ); 2798 s = sc.search(loc, mt.ident, &scopesym); 2799 } 2800 } 2801 2802 if (s) 2803 { 2804 // https://issues.dlang.org/show_bug.cgi?id=16042 2805 // If `f` is really a function template, then replace `f` 2806 // with the function template declaration. 2807 if (auto f = s.isFuncDeclaration()) 2808 { 2809 if (auto td = getFuncTemplateDecl(f)) 2810 { 2811 // If not at the beginning of the overloaded list of 2812 // `TemplateDeclaration`s, then get the beginning 2813 if (td.overroot) 2814 td = td.overroot; 2815 s = td; 2816 } 2817 } 2818 } 2819 2820 mt.resolveHelper(loc, sc, s, scopesym, pe, pt, ps, intypeid); 2821 if (*pt) 2822 (*pt) = (*pt).addMod(mt.mod); 2823 } 2824 2825 void visitInstance(TypeInstance mt) 2826 { 2827 // Note close similarity to TypeIdentifier::resolve() 2828 2829 //printf("TypeInstance::resolve(sc = %p, tempinst = '%s')\n", sc, mt.tempinst.toChars()); 2830 mt.tempinst.dsymbolSemantic(sc); 2831 if (!global.gag && mt.tempinst.errors) 2832 return returnError(); 2833 2834 mt.resolveHelper(loc, sc, mt.tempinst, null, pe, pt, ps, intypeid); 2835 if (*pt) 2836 *pt = (*pt).addMod(mt.mod); 2837 //if (*pt) printf("*pt = %d '%s'\n", (*pt).ty, (*pt).toChars()); 2838 } 2839 2840 void visitTypeof(TypeTypeof mt) 2841 { 2842 //printf("TypeTypeof::resolve(this = %p, sc = %p, idents = '%s')\n", mt, sc, mt.toChars()); 2843 //static int nest; if (++nest == 50) *(char*)0=0; 2844 if (sc is null) 2845 { 2846 error(loc, "Invalid scope."); 2847 return returnError(); 2848 } 2849 if (mt.inuse) 2850 { 2851 mt.inuse = 2; 2852 error(loc, "circular `typeof` definition"); 2853 Lerr: 2854 mt.inuse--; 2855 return returnError(); 2856 } 2857 mt.inuse++; 2858 2859 /* Currently we cannot evaluate 'exp' in speculative context, because 2860 * the type implementation may leak to the final execution. Consider: 2861 * 2862 * struct S(T) { 2863 * string toString() const { return "x"; } 2864 * } 2865 * void main() { 2866 * alias X = typeof(S!int()); 2867 * assert(typeid(X).toString() == "x"); 2868 * } 2869 */ 2870 Scope* sc2 = sc.push(); 2871 sc2.intypeof = 1; 2872 auto exp2 = mt.exp.expressionSemantic(sc2); 2873 exp2 = resolvePropertiesOnly(sc2, exp2); 2874 sc2.pop(); 2875 2876 if (exp2.op == TOK.error) 2877 { 2878 if (!global.gag) 2879 mt.exp = exp2; 2880 goto Lerr; 2881 } 2882 mt.exp = exp2; 2883 2884 if (mt.exp.op == TOK.type || 2885 mt.exp.op == TOK.scope_) 2886 { 2887 if (mt.exp.checkType()) 2888 goto Lerr; 2889 2890 /* Today, 'typeof(func)' returns void if func is a 2891 * function template (TemplateExp), or 2892 * template lambda (FuncExp). 2893 * It's actually used in Phobos as an idiom, to branch code for 2894 * template functions. 2895 */ 2896 } 2897 if (auto f = mt.exp.op == TOK.variable ? (cast( VarExp)mt.exp).var.isFuncDeclaration() 2898 : mt.exp.op == TOK.dotVariable ? (cast(DotVarExp)mt.exp).var.isFuncDeclaration() : null) 2899 { 2900 if (f.checkForwardRef(loc)) 2901 goto Lerr; 2902 } 2903 if (auto f = isFuncAddress(mt.exp)) 2904 { 2905 if (f.checkForwardRef(loc)) 2906 goto Lerr; 2907 } 2908 2909 Type t = mt.exp.type; 2910 if (!t) 2911 { 2912 error(loc, "expression `%s` has no type", mt.exp.toChars()); 2913 goto Lerr; 2914 } 2915 if (t.ty == Ttypeof) 2916 { 2917 error(loc, "forward reference to `%s`", mt.toChars()); 2918 goto Lerr; 2919 } 2920 if (mt.idents.dim == 0) 2921 { 2922 returnType(t.addMod(mt.mod)); 2923 } 2924 else 2925 { 2926 if (Dsymbol s = t.toDsymbol(sc)) 2927 mt.resolveHelper(loc, sc, s, null, pe, pt, ps, intypeid); 2928 else 2929 { 2930 auto e = typeToExpressionHelper(mt, new TypeExp(loc, t)); 2931 e = e.expressionSemantic(sc); 2932 resolveExp(e, pt, pe, ps); 2933 } 2934 if (*pt) 2935 (*pt) = (*pt).addMod(mt.mod); 2936 } 2937 mt.inuse--; 2938 } 2939 2940 void visitReturn(TypeReturn mt) 2941 { 2942 //printf("TypeReturn::resolve(sc = %p, idents = '%s')\n", sc, mt.toChars()); 2943 Type t; 2944 { 2945 FuncDeclaration func = sc.func; 2946 if (!func) 2947 { 2948 error(loc, "`typeof(return)` must be inside function"); 2949 return returnError(); 2950 } 2951 if (func.fes) 2952 func = func.fes.func; 2953 t = func.type.nextOf(); 2954 if (!t) 2955 { 2956 error(loc, "cannot use `typeof(return)` inside function `%s` with inferred return type", sc.func.toChars()); 2957 return returnError(); 2958 } 2959 } 2960 if (mt.idents.dim == 0) 2961 { 2962 return returnType(t.addMod(mt.mod)); 2963 } 2964 else 2965 { 2966 if (Dsymbol s = t.toDsymbol(sc)) 2967 mt.resolveHelper(loc, sc, s, null, pe, pt, ps, intypeid); 2968 else 2969 { 2970 auto e = typeToExpressionHelper(mt, new TypeExp(loc, t)); 2971 e = e.expressionSemantic(sc); 2972 resolveExp(e, pt, pe, ps); 2973 } 2974 if (*pt) 2975 (*pt) = (*pt).addMod(mt.mod); 2976 } 2977 } 2978 2979 void visitSlice(TypeSlice mt) 2980 { 2981 mt.next.resolve(loc, sc, pe, pt, ps, intypeid); 2982 if (*pe) 2983 { 2984 // It's really a slice expression 2985 if (Dsymbol s = getDsymbol(*pe)) 2986 *pe = new DsymbolExp(loc, s); 2987 return returnExp(new ArrayExp(loc, *pe, new IntervalExp(loc, mt.lwr, mt.upr))); 2988 } 2989 else if (*ps) 2990 { 2991 Dsymbol s = *ps; 2992 TupleDeclaration td = s.isTupleDeclaration(); 2993 if (td) 2994 { 2995 /* It's a slice of a TupleDeclaration 2996 */ 2997 ScopeDsymbol sym = new ArrayScopeSymbol(sc, td); 2998 sym.parent = sc.scopesym; 2999 sc = sc.push(sym); 3000 sc = sc.startCTFE(); 3001 mt.lwr = mt.lwr.expressionSemantic(sc); 3002 mt.upr = mt.upr.expressionSemantic(sc); 3003 sc = sc.endCTFE(); 3004 sc = sc.pop(); 3005 3006 mt.lwr = mt.lwr.ctfeInterpret(); 3007 mt.upr = mt.upr.ctfeInterpret(); 3008 const i1 = mt.lwr.toUInteger(); 3009 const i2 = mt.upr.toUInteger(); 3010 if (!(i1 <= i2 && i2 <= td.objects.dim)) 3011 { 3012 error(loc, "slice `[%llu..%llu]` is out of range of [0..%u]", i1, i2, td.objects.dim); 3013 return returnError(); 3014 } 3015 3016 if (i1 == 0 && i2 == td.objects.dim) 3017 { 3018 return returnSymbol(td); 3019 } 3020 3021 /* Create a new TupleDeclaration which 3022 * is a slice [i1..i2] out of the old one. 3023 */ 3024 auto objects = new Objects(cast(size_t)(i2 - i1)); 3025 for (size_t i = 0; i < objects.dim; i++) 3026 { 3027 (*objects)[i] = (*td.objects)[cast(size_t)i1 + i]; 3028 } 3029 3030 return returnSymbol(new TupleDeclaration(loc, td.ident, objects)); 3031 } 3032 else 3033 visitType(mt); 3034 } 3035 else 3036 { 3037 if ((*pt).ty != Terror) 3038 mt.next = *pt; // prevent re-running semantic() on 'next' 3039 visitType(mt); 3040 } 3041 } 3042 3043 void visitMixin(TypeMixin mt) 3044 { 3045 auto o = mt.compileTypeMixin(loc, sc); 3046 3047 if (auto t = o.isType()) 3048 { 3049 resolve(t, loc, sc, pe, pt, ps, intypeid); 3050 } 3051 else if (auto e = o.isExpression()) 3052 { 3053 e = e.expressionSemantic(sc); 3054 if (auto et = e.isTypeExp()) 3055 return returnType(et.type); 3056 else 3057 returnExp(e); 3058 } 3059 else 3060 returnError(); 3061 } 3062 3063 void visitTraits(TypeTraits tt) 3064 { 3065 if (Type t = typeSemantic(tt, loc, sc)) 3066 returnType(t); 3067 else if (tt.sym) 3068 returnSymbol(tt.sym); 3069 else 3070 return returnError(); 3071 } 3072 3073 switch (mt.ty) 3074 { 3075 default: visitType (mt); break; 3076 case Tsarray: visitSArray (cast(TypeSArray)mt); break; 3077 case Tarray: visitDArray (cast(TypeDArray)mt); break; 3078 case Taarray: visitAArray (cast(TypeAArray)mt); break; 3079 case Tident: visitIdentifier(cast(TypeIdentifier)mt); break; 3080 case Tinstance: visitInstance (cast(TypeInstance)mt); break; 3081 case Ttypeof: visitTypeof (cast(TypeTypeof)mt); break; 3082 case Treturn: visitReturn (cast(TypeReturn)mt); break; 3083 case Tslice: visitSlice (cast(TypeSlice)mt); break; 3084 case Tmixin: visitMixin (cast(TypeMixin)mt); break; 3085 case Ttraits: visitTraits (cast(TypeTraits)mt); break; 3086 } 3087 } 3088 3089 /************************ 3090 * Access the members of the object e. This type is same as e.type. 3091 * Params: 3092 * mt = type for which the dot expression is used 3093 * sc = instantiating scope 3094 * e = expression to convert 3095 * ident = identifier being used 3096 * flag = DotExpFlag bit flags 3097 * 3098 * Returns: 3099 * resulting expression with e.ident resolved 3100 */ 3101 Expression dotExp(Type mt, Scope* sc, Expression e, Identifier ident, int flag) 3102 { 3103 Expression visitType(Type mt) 3104 { 3105 VarDeclaration v = null; 3106 static if (LOGDOTEXP) 3107 { 3108 printf("Type::dotExp(e = '%s', ident = '%s')\n", e.toChars(), ident.toChars()); 3109 } 3110 Expression ex = e.lastComma(); 3111 if (ex.op == TOK.dotVariable) 3112 { 3113 DotVarExp dv = cast(DotVarExp)ex; 3114 v = dv.var.isVarDeclaration(); 3115 } 3116 else if (ex.op == TOK.variable) 3117 { 3118 VarExp ve = cast(VarExp)ex; 3119 v = ve.var.isVarDeclaration(); 3120 } 3121 if (v) 3122 { 3123 if (ident == Id.offsetof) 3124 { 3125 if (v.isField()) 3126 { 3127 auto ad = v.toParent().isAggregateDeclaration(); 3128 objc.checkOffsetof(e, ad); 3129 ad.size(e.loc); 3130 if (ad.sizeok != Sizeok.done) 3131 return new ErrorExp(); 3132 return new IntegerExp(e.loc, v.offset, Type.tsize_t); 3133 } 3134 } 3135 else if (ident == Id._init) 3136 { 3137 Type tb = mt.toBasetype(); 3138 e = mt.defaultInitLiteral(e.loc); 3139 if (tb.ty == Tstruct && tb.needsNested()) 3140 { 3141 e.isStructLiteralExp().useStaticInit = true; 3142 } 3143 goto Lreturn; 3144 } 3145 } 3146 if (ident == Id.stringof) 3147 { 3148 /* https://issues.dlang.org/show_bug.cgi?id=3796 3149 * this should demangle e.type.deco rather than 3150 * pretty-printing the type. 3151 */ 3152 e = new StringExp(e.loc, e.toString()); 3153 } 3154 else 3155 e = mt.getProperty(sc, e.loc, ident, flag & DotExpFlag.gag); 3156 3157 Lreturn: 3158 if (e) 3159 e = e.expressionSemantic(sc); 3160 return e; 3161 } 3162 3163 Expression visitError(TypeError) 3164 { 3165 return new ErrorExp(); 3166 } 3167 3168 Expression visitBasic(TypeBasic mt) 3169 { 3170 static if (LOGDOTEXP) 3171 { 3172 printf("TypeBasic::dotExp(e = '%s', ident = '%s')\n", e.toChars(), ident.toChars()); 3173 } 3174 Type t; 3175 if (ident == Id.re) 3176 { 3177 switch (mt.ty) 3178 { 3179 case Tcomplex32: 3180 t = mt.tfloat32; 3181 goto L1; 3182 3183 case Tcomplex64: 3184 t = mt.tfloat64; 3185 goto L1; 3186 3187 case Tcomplex80: 3188 t = mt.tfloat80; 3189 goto L1; 3190 L1: 3191 e = e.castTo(sc, t); 3192 break; 3193 3194 case Tfloat32: 3195 case Tfloat64: 3196 case Tfloat80: 3197 break; 3198 3199 case Timaginary32: 3200 t = mt.tfloat32; 3201 goto L2; 3202 3203 case Timaginary64: 3204 t = mt.tfloat64; 3205 goto L2; 3206 3207 case Timaginary80: 3208 t = mt.tfloat80; 3209 goto L2; 3210 L2: 3211 e = new RealExp(e.loc, CTFloat.zero, t); 3212 break; 3213 3214 default: 3215 e = mt.Type.getProperty(sc, e.loc, ident, flag); 3216 break; 3217 } 3218 } 3219 else if (ident == Id.im) 3220 { 3221 Type t2; 3222 switch (mt.ty) 3223 { 3224 case Tcomplex32: 3225 t = mt.timaginary32; 3226 t2 = mt.tfloat32; 3227 goto L3; 3228 3229 case Tcomplex64: 3230 t = mt.timaginary64; 3231 t2 = mt.tfloat64; 3232 goto L3; 3233 3234 case Tcomplex80: 3235 t = mt.timaginary80; 3236 t2 = mt.tfloat80; 3237 goto L3; 3238 L3: 3239 e = e.castTo(sc, t); 3240 e.type = t2; 3241 break; 3242 3243 case Timaginary32: 3244 t = mt.tfloat32; 3245 goto L4; 3246 3247 case Timaginary64: 3248 t = mt.tfloat64; 3249 goto L4; 3250 3251 case Timaginary80: 3252 t = mt.tfloat80; 3253 goto L4; 3254 L4: 3255 e = e.copy(); 3256 e.type = t; 3257 break; 3258 3259 case Tfloat32: 3260 case Tfloat64: 3261 case Tfloat80: 3262 e = new RealExp(e.loc, CTFloat.zero, mt); 3263 break; 3264 3265 default: 3266 e = mt.Type.getProperty(sc, e.loc, ident, flag); 3267 break; 3268 } 3269 } 3270 else 3271 { 3272 return visitType(mt); 3273 } 3274 if (!(flag & 1) || e) 3275 e = e.expressionSemantic(sc); 3276 return e; 3277 } 3278 3279 Expression visitVector(TypeVector mt) 3280 { 3281 static if (LOGDOTEXP) 3282 { 3283 printf("TypeVector::dotExp(e = '%s', ident = '%s')\n", e.toChars(), ident.toChars()); 3284 } 3285 if (ident == Id.ptr && e.op == TOK.call) 3286 { 3287 /* The trouble with TOK.call is the return ABI for float[4] is different from 3288 * __vector(float[4]), and a type paint won't do. 3289 */ 3290 e = new AddrExp(e.loc, e); 3291 e = e.expressionSemantic(sc); 3292 return e.castTo(sc, mt.basetype.nextOf().pointerTo()); 3293 } 3294 if (ident == Id.array) 3295 { 3296 //e = e.castTo(sc, basetype); 3297 // Keep lvalue-ness 3298 e = new VectorArrayExp(e.loc, e); 3299 e = e.expressionSemantic(sc); 3300 return e; 3301 } 3302 if (ident == Id._init || ident == Id.offsetof || ident == Id.stringof || ident == Id.__xalignof) 3303 { 3304 // init should return a new VectorExp 3305 // https://issues.dlang.org/show_bug.cgi?id=12776 3306 // offsetof does not work on a cast expression, so use e directly 3307 // stringof should not add a cast to the output 3308 return visitType(mt); 3309 } 3310 return mt.basetype.dotExp(sc, e.castTo(sc, mt.basetype), ident, flag); 3311 } 3312 3313 Expression visitArray(TypeArray mt) 3314 { 3315 static if (LOGDOTEXP) 3316 { 3317 printf("TypeArray::dotExp(e = '%s', ident = '%s')\n", e.toChars(), ident.toChars()); 3318 } 3319 3320 e = visitType(mt); 3321 3322 if (!(flag & 1) || e) 3323 e = e.expressionSemantic(sc); 3324 return e; 3325 } 3326 3327 Expression visitSArray(TypeSArray mt) 3328 { 3329 static if (LOGDOTEXP) 3330 { 3331 printf("TypeSArray::dotExp(e = '%s', ident = '%s')\n", e.toChars(), ident.toChars()); 3332 } 3333 if (ident == Id.length) 3334 { 3335 Loc oldLoc = e.loc; 3336 e = mt.dim.copy(); 3337 e.loc = oldLoc; 3338 } 3339 else if (ident == Id.ptr) 3340 { 3341 if (e.op == TOK.type) 3342 { 3343 e.error("`%s` is not an expression", e.toChars()); 3344 return new ErrorExp(); 3345 } 3346 else if (!(flag & DotExpFlag.noDeref) && sc.func && !sc.intypeof && !(sc.flags & SCOPE.debug_) && sc.func.setUnsafe()) 3347 { 3348 e.error("`%s.ptr` cannot be used in `@safe` code, use `&%s[0]` instead", e.toChars(), e.toChars()); 3349 return new ErrorExp(); 3350 } 3351 e = e.castTo(sc, e.type.nextOf().pointerTo()); 3352 } 3353 else 3354 { 3355 e = visitArray(mt); 3356 } 3357 if (!(flag & 1) || e) 3358 e = e.expressionSemantic(sc); 3359 return e; 3360 } 3361 3362 Expression visitDArray(TypeDArray mt) 3363 { 3364 static if (LOGDOTEXP) 3365 { 3366 printf("TypeDArray::dotExp(e = '%s', ident = '%s')\n", e.toChars(), ident.toChars()); 3367 } 3368 if (e.op == TOK.type && (ident == Id.length || ident == Id.ptr)) 3369 { 3370 e.error("`%s` is not an expression", e.toChars()); 3371 return new ErrorExp(); 3372 } 3373 if (ident == Id.length) 3374 { 3375 if (e.op == TOK.string_) 3376 { 3377 StringExp se = cast(StringExp)e; 3378 return new IntegerExp(se.loc, se.len, Type.tsize_t); 3379 } 3380 if (e.op == TOK.null_) 3381 { 3382 return new IntegerExp(e.loc, 0, Type.tsize_t); 3383 } 3384 if (checkNonAssignmentArrayOp(e)) 3385 { 3386 return new ErrorExp(); 3387 } 3388 e = new ArrayLengthExp(e.loc, e); 3389 e.type = Type.tsize_t; 3390 return e; 3391 } 3392 else if (ident == Id.ptr) 3393 { 3394 if (!(flag & DotExpFlag.noDeref) && sc.func && !sc.intypeof && !(sc.flags & SCOPE.debug_) && sc.func.setUnsafe()) 3395 { 3396 e.error("`%s.ptr` cannot be used in `@safe` code, use `&%s[0]` instead", e.toChars(), e.toChars()); 3397 return new ErrorExp(); 3398 } 3399 return e.castTo(sc, mt.next.pointerTo()); 3400 } 3401 else 3402 { 3403 return visitArray(mt); 3404 } 3405 } 3406 3407 Expression visitAArray(TypeAArray mt) 3408 { 3409 static if (LOGDOTEXP) 3410 { 3411 printf("TypeAArray::dotExp(e = '%s', ident = '%s')\n", e.toChars(), ident.toChars()); 3412 } 3413 if (ident == Id.length) 3414 { 3415 __gshared FuncDeclaration fd_aaLen = null; 3416 if (fd_aaLen is null) 3417 { 3418 auto fparams = new Parameters(); 3419 fparams.push(new Parameter(STC.in_, mt, null, null, null)); 3420 fd_aaLen = FuncDeclaration.genCfunc(fparams, Type.tsize_t, Id.aaLen); 3421 TypeFunction tf = fd_aaLen.type.toTypeFunction(); 3422 tf.purity = PURE.const_; 3423 tf.isnothrow = true; 3424 tf.isnogc = false; 3425 } 3426 Expression ev = new VarExp(e.loc, fd_aaLen, false); 3427 e = new CallExp(e.loc, ev, e); 3428 e.type = fd_aaLen.type.toTypeFunction().next; 3429 return e; 3430 } 3431 else 3432 { 3433 return visitType(mt); 3434 } 3435 } 3436 3437 Expression visitReference(TypeReference mt) 3438 { 3439 static if (LOGDOTEXP) 3440 { 3441 printf("TypeReference::dotExp(e = '%s', ident = '%s')\n", e.toChars(), ident.toChars()); 3442 } 3443 // References just forward things along 3444 return mt.next.dotExp(sc, e, ident, flag); 3445 } 3446 3447 Expression visitDelegate(TypeDelegate mt) 3448 { 3449 static if (LOGDOTEXP) 3450 { 3451 printf("TypeDelegate::dotExp(e = '%s', ident = '%s')\n", e.toChars(), ident.toChars()); 3452 } 3453 if (ident == Id.ptr) 3454 { 3455 e = new DelegatePtrExp(e.loc, e); 3456 e = e.expressionSemantic(sc); 3457 } 3458 else if (ident == Id.funcptr) 3459 { 3460 if (!(flag & DotExpFlag.noDeref) && sc.func && !sc.intypeof && !(sc.flags & SCOPE.debug_) && sc.func.setUnsafe()) 3461 { 3462 e.error("`%s.funcptr` cannot be used in `@safe` code", e.toChars()); 3463 return new ErrorExp(); 3464 } 3465 e = new DelegateFuncptrExp(e.loc, e); 3466 e = e.expressionSemantic(sc); 3467 } 3468 else 3469 { 3470 return visitType(mt); 3471 } 3472 return e; 3473 } 3474 3475 /*************************************** 3476 * Figures out what to do with an undefined member reference 3477 * for classes and structs. 3478 * 3479 * If flag & 1, don't report "not a property" error and just return NULL. 3480 */ 3481 Expression noMember(Type mt, Scope* sc, Expression e, Identifier ident, int flag) 3482 { 3483 //printf("Type.noMember(e: %s ident: %s flag: %d)\n", e.toChars(), ident.toChars(), flag); 3484 3485 bool gagError = flag & 1; 3486 3487 __gshared int nest; // https://issues.dlang.org/show_bug.cgi?id=17380 3488 3489 static Expression returnExp(Expression e) 3490 { 3491 --nest; 3492 return e; 3493 } 3494 3495 if (++nest > global.recursionLimit) 3496 { 3497 .error(e.loc, "cannot resolve identifier `%s`", ident.toChars()); 3498 return returnExp(gagError ? null : new ErrorExp()); 3499 } 3500 3501 3502 assert(mt.ty == Tstruct || mt.ty == Tclass); 3503 auto sym = mt.toDsymbol(sc).isAggregateDeclaration(); 3504 assert(sym); 3505 if (ident != Id.__sizeof && 3506 ident != Id.__xalignof && 3507 ident != Id._init && 3508 ident != Id._mangleof && 3509 ident != Id.stringof && 3510 ident != Id.offsetof && 3511 // https://issues.dlang.org/show_bug.cgi?id=15045 3512 // Don't forward special built-in member functions. 3513 ident != Id.ctor && 3514 ident != Id.dtor && 3515 ident != Id.__xdtor && 3516 ident != Id.postblit && 3517 ident != Id.__xpostblit) 3518 { 3519 /* Look for overloaded opDot() to see if we should forward request 3520 * to it. 3521 */ 3522 if (auto fd = search_function(sym, Id.opDot)) 3523 { 3524 /* Rewrite e.ident as: 3525 * e.opDot().ident 3526 */ 3527 e = build_overload(e.loc, sc, e, null, fd); 3528 // @@@DEPRECATED_2.087@@@. 3529 e.deprecation("`opDot` is deprecated. Use `alias this`"); 3530 e = new DotIdExp(e.loc, e, ident); 3531 return returnExp(e.expressionSemantic(sc)); 3532 } 3533 3534 /* Look for overloaded opDispatch to see if we should forward request 3535 * to it. 3536 */ 3537 if (auto fd = search_function(sym, Id.opDispatch)) 3538 { 3539 /* Rewrite e.ident as: 3540 * e.opDispatch!("ident") 3541 */ 3542 TemplateDeclaration td = fd.isTemplateDeclaration(); 3543 if (!td) 3544 { 3545 fd.error("must be a template `opDispatch(string s)`, not a %s", fd.kind()); 3546 return returnExp(new ErrorExp()); 3547 } 3548 auto se = new StringExp(e.loc, ident.toString()); 3549 auto tiargs = new Objects(); 3550 tiargs.push(se); 3551 auto dti = new DotTemplateInstanceExp(e.loc, e, Id.opDispatch, tiargs); 3552 dti.ti.tempdecl = td; 3553 /* opDispatch, which doesn't need IFTI, may occur instantiate error. 3554 * e.g. 3555 * template opDispatch(name) if (isValid!name) { ... } 3556 */ 3557 uint errors = gagError ? global.startGagging() : 0; 3558 e = dti.semanticY(sc, 0); 3559 if (gagError && global.endGagging(errors)) 3560 e = null; 3561 return returnExp(e); 3562 } 3563 3564 /* See if we should forward to the alias this. 3565 */ 3566 auto alias_e = resolveAliasThis(sc, e, gagError); 3567 if (alias_e && alias_e != e) 3568 { 3569 /* Rewrite e.ident as: 3570 * e.aliasthis.ident 3571 */ 3572 auto die = new DotIdExp(e.loc, alias_e, ident); 3573 3574 auto errors = gagError ? 0 : global.startGagging(); 3575 auto exp = die.semanticY(sc, gagError); 3576 if (!gagError) 3577 { 3578 global.endGagging(errors); 3579 if (exp && exp.op == TOK.error) 3580 exp = null; 3581 } 3582 3583 if (exp && gagError) 3584 // now that we know that the alias this leads somewhere useful, 3585 // go back and print deprecations/warnings that we skipped earlier due to the gag 3586 resolveAliasThis(sc, e, false); 3587 3588 return returnExp(exp); 3589 } 3590 } 3591 return returnExp(visitType(mt)); 3592 } 3593 3594 Expression visitStruct(TypeStruct mt) 3595 { 3596 Dsymbol s; 3597 static if (LOGDOTEXP) 3598 { 3599 printf("TypeStruct::dotExp(e = '%s', ident = '%s')\n", e.toChars(), ident.toChars()); 3600 } 3601 assert(e.op != TOK.dot); 3602 3603 // https://issues.dlang.org/show_bug.cgi?id=14010 3604 if (ident == Id._mangleof) 3605 { 3606 return mt.getProperty(sc, e.loc, ident, flag & 1); 3607 } 3608 3609 /* If e.tupleof 3610 */ 3611 if (ident == Id._tupleof) 3612 { 3613 /* Create a TupleExp out of the fields of the struct e: 3614 * (e.field0, e.field1, e.field2, ...) 3615 */ 3616 e = e.expressionSemantic(sc); // do this before turning on noaccesscheck 3617 3618 if (!mt.sym.determineFields()) 3619 { 3620 error(e.loc, "unable to determine fields of `%s` because of forward references", mt.toChars()); 3621 } 3622 3623 Expression e0; 3624 Expression ev = e.op == TOK.type ? null : e; 3625 if (ev) 3626 ev = extractSideEffect(sc, "__tup", e0, ev); 3627 3628 auto exps = new Expressions(); 3629 exps.reserve(mt.sym.fields.dim); 3630 for (size_t i = 0; i < mt.sym.fields.dim; i++) 3631 { 3632 VarDeclaration v = mt.sym.fields[i]; 3633 Expression ex; 3634 if (ev) 3635 ex = new DotVarExp(e.loc, ev, v); 3636 else 3637 { 3638 ex = new VarExp(e.loc, v); 3639 ex.type = ex.type.addMod(e.type.mod); 3640 } 3641 exps.push(ex); 3642 } 3643 3644 e = new TupleExp(e.loc, e0, exps); 3645 Scope* sc2 = sc.push(); 3646 sc2.flags |= global.params.vsafe ? SCOPE.onlysafeaccess : SCOPE.noaccesscheck; 3647 e = e.expressionSemantic(sc2); 3648 sc2.pop(); 3649 return e; 3650 } 3651 3652 immutable flags = sc.flags & SCOPE.ignoresymbolvisibility ? IgnoreSymbolVisibility : 0; 3653 s = mt.sym.search(e.loc, ident, flags | IgnorePrivateImports); 3654 L1: 3655 if (!s) 3656 { 3657 return noMember(mt, sc, e, ident, flag); 3658 } 3659 if (!(sc.flags & SCOPE.ignoresymbolvisibility) && !symbolIsVisible(sc, s)) 3660 { 3661 return noMember(mt, sc, e, ident, flag); 3662 } 3663 if (!s.isFuncDeclaration()) // because of overloading 3664 { 3665 s.checkDeprecated(e.loc, sc); 3666 if (auto d = s.isDeclaration()) 3667 d.checkDisabled(e.loc, sc); 3668 } 3669 s = s.toAlias(); 3670 3671 if (auto em = s.isEnumMember()) 3672 { 3673 return em.getVarExp(e.loc, sc); 3674 } 3675 if (auto v = s.isVarDeclaration()) 3676 { 3677 if (!v.type || 3678 !v.type.deco && v.inuse) 3679 { 3680 if (v.inuse) // https://issues.dlang.org/show_bug.cgi?id=9494 3681 e.error("circular reference to %s `%s`", v.kind(), v.toPrettyChars()); 3682 else 3683 e.error("forward reference to %s `%s`", v.kind(), v.toPrettyChars()); 3684 return new ErrorExp(); 3685 } 3686 if (v.type.ty == Terror) 3687 { 3688 return new ErrorExp(); 3689 } 3690 3691 if ((v.storage_class & STC.manifest) && v._init) 3692 { 3693 if (v.inuse) 3694 { 3695 e.error("circular initialization of %s `%s`", v.kind(), v.toPrettyChars()); 3696 return new ErrorExp(); 3697 } 3698 checkAccess(e.loc, sc, null, v); 3699 Expression ve = new VarExp(e.loc, v); 3700 if (!isTrivialExp(e)) 3701 { 3702 ve = new CommaExp(e.loc, e, ve); 3703 } 3704 return ve.expressionSemantic(sc); 3705 } 3706 } 3707 3708 if (auto t = s.getType()) 3709 { 3710 return (new TypeExp(e.loc, t)).expressionSemantic(sc); 3711 } 3712 3713 TemplateMixin tm = s.isTemplateMixin(); 3714 if (tm) 3715 { 3716 Expression de = new DotExp(e.loc, e, new ScopeExp(e.loc, tm)); 3717 de.type = e.type; 3718 return de; 3719 } 3720 3721 TemplateDeclaration td = s.isTemplateDeclaration(); 3722 if (td) 3723 { 3724 if (e.op == TOK.type) 3725 e = new TemplateExp(e.loc, td); 3726 else 3727 e = new DotTemplateExp(e.loc, e, td); 3728 return e.expressionSemantic(sc); 3729 } 3730 3731 TemplateInstance ti = s.isTemplateInstance(); 3732 if (ti) 3733 { 3734 if (!ti.semanticRun) 3735 { 3736 ti.dsymbolSemantic(sc); 3737 if (!ti.inst || ti.errors) // if template failed to expand 3738 { 3739 return new ErrorExp(); 3740 } 3741 } 3742 s = ti.inst.toAlias(); 3743 if (!s.isTemplateInstance()) 3744 goto L1; 3745 if (e.op == TOK.type) 3746 e = new ScopeExp(e.loc, ti); 3747 else 3748 e = new DotExp(e.loc, e, new ScopeExp(e.loc, ti)); 3749 return e.expressionSemantic(sc); 3750 } 3751 3752 if (s.isImport() || s.isModule() || s.isPackage()) 3753 { 3754 return symbolToExp(s, e.loc, sc, false); 3755 } 3756 3757 OverloadSet o = s.isOverloadSet(); 3758 if (o) 3759 { 3760 auto oe = new OverExp(e.loc, o); 3761 if (e.op == TOK.type) 3762 { 3763 return oe; 3764 } 3765 return new DotExp(e.loc, e, oe); 3766 } 3767 3768 Declaration d = s.isDeclaration(); 3769 if (!d) 3770 { 3771 e.error("`%s.%s` is not a declaration", e.toChars(), ident.toChars()); 3772 return new ErrorExp(); 3773 } 3774 3775 if (e.op == TOK.type) 3776 { 3777 /* It's: 3778 * Struct.d 3779 */ 3780 if (TupleDeclaration tup = d.isTupleDeclaration()) 3781 { 3782 e = new TupleExp(e.loc, tup); 3783 return e.expressionSemantic(sc); 3784 } 3785 if (d.needThis() && sc.intypeof != 1) 3786 { 3787 /* Rewrite as: 3788 * this.d 3789 */ 3790 if (hasThis(sc)) 3791 { 3792 e = new DotVarExp(e.loc, new ThisExp(e.loc), d); 3793 return e.expressionSemantic(sc); 3794 } 3795 } 3796 if (d.semanticRun == PASS.init) 3797 d.dsymbolSemantic(null); 3798 checkAccess(e.loc, sc, e, d); 3799 auto ve = new VarExp(e.loc, d); 3800 if (d.isVarDeclaration() && d.needThis()) 3801 ve.type = d.type.addMod(e.type.mod); 3802 return ve; 3803 } 3804 3805 bool unreal = e.op == TOK.variable && (cast(VarExp)e).var.isField(); 3806 if (d.isDataseg() || unreal && d.isField()) 3807 { 3808 // (e, d) 3809 checkAccess(e.loc, sc, e, d); 3810 Expression ve = new VarExp(e.loc, d); 3811 e = unreal ? ve : new CommaExp(e.loc, e, ve); 3812 return e.expressionSemantic(sc); 3813 } 3814 3815 e = new DotVarExp(e.loc, e, d); 3816 return e.expressionSemantic(sc); 3817 } 3818 3819 Expression visitEnum(TypeEnum mt) 3820 { 3821 static if (LOGDOTEXP) 3822 { 3823 printf("TypeEnum::dotExp(e = '%s', ident = '%s') '%s'\n", e.toChars(), ident.toChars(), mt.toChars()); 3824 } 3825 // https://issues.dlang.org/show_bug.cgi?id=14010 3826 if (ident == Id._mangleof) 3827 { 3828 return mt.getProperty(sc, e.loc, ident, flag & 1); 3829 } 3830 3831 if (mt.sym.semanticRun < PASS.semanticdone) 3832 mt.sym.dsymbolSemantic(null); 3833 if (!mt.sym.members) 3834 { 3835 if (mt.sym.isSpecial()) 3836 { 3837 /* Special enums forward to the base type 3838 */ 3839 e = mt.sym.memtype.dotExp(sc, e, ident, flag); 3840 } 3841 else if (!(flag & 1)) 3842 { 3843 mt.sym.error("is forward referenced when looking for `%s`", ident.toChars()); 3844 e = new ErrorExp(); 3845 } 3846 else 3847 e = null; 3848 return e; 3849 } 3850 3851 Dsymbol s = mt.sym.search(e.loc, ident); 3852 if (!s) 3853 { 3854 if (ident == Id.max || ident == Id.min || ident == Id._init) 3855 { 3856 return mt.getProperty(sc, e.loc, ident, flag & 1); 3857 } 3858 3859 Expression res = mt.sym.getMemtype(Loc.initial).dotExp(sc, e, ident, 1); 3860 if (!(flag & 1) && !res) 3861 { 3862 if (auto ns = mt.sym.search_correct(ident)) 3863 e.error("no property `%s` for type `%s`. Did you mean `%s.%s` ?", ident.toChars(), mt.toChars(), mt.toChars(), 3864 ns.toChars()); 3865 else 3866 e.error("no property `%s` for type `%s`", ident.toChars(), 3867 mt.toChars()); 3868 3869 return new ErrorExp(); 3870 } 3871 return res; 3872 } 3873 EnumMember m = s.isEnumMember(); 3874 return m.getVarExp(e.loc, sc); 3875 } 3876 3877 Expression visitClass(TypeClass mt) 3878 { 3879 Dsymbol s; 3880 static if (LOGDOTEXP) 3881 { 3882 printf("TypeClass::dotExp(e = '%s', ident = '%s')\n", e.toChars(), ident.toChars()); 3883 } 3884 assert(e.op != TOK.dot); 3885 3886 // https://issues.dlang.org/show_bug.cgi?id=12543 3887 if (ident == Id.__sizeof || ident == Id.__xalignof || ident == Id._mangleof) 3888 { 3889 return mt.Type.getProperty(sc, e.loc, ident, 0); 3890 } 3891 3892 /* If e.tupleof 3893 */ 3894 if (ident == Id._tupleof) 3895 { 3896 objc.checkTupleof(e, mt); 3897 3898 /* Create a TupleExp 3899 */ 3900 e = e.expressionSemantic(sc); // do this before turning on noaccesscheck 3901 3902 mt.sym.size(e.loc); // do semantic of type 3903 3904 Expression e0; 3905 Expression ev = e.op == TOK.type ? null : e; 3906 if (ev) 3907 ev = extractSideEffect(sc, "__tup", e0, ev); 3908 3909 auto exps = new Expressions(); 3910 exps.reserve(mt.sym.fields.dim); 3911 for (size_t i = 0; i < mt.sym.fields.dim; i++) 3912 { 3913 VarDeclaration v = mt.sym.fields[i]; 3914 // Don't include hidden 'this' pointer 3915 if (v.isThisDeclaration()) 3916 continue; 3917 Expression ex; 3918 if (ev) 3919 ex = new DotVarExp(e.loc, ev, v); 3920 else 3921 { 3922 ex = new VarExp(e.loc, v); 3923 ex.type = ex.type.addMod(e.type.mod); 3924 } 3925 exps.push(ex); 3926 } 3927 3928 e = new TupleExp(e.loc, e0, exps); 3929 Scope* sc2 = sc.push(); 3930 sc2.flags |= global.params.vsafe ? SCOPE.onlysafeaccess : SCOPE.noaccesscheck; 3931 e = e.expressionSemantic(sc2); 3932 sc2.pop(); 3933 return e; 3934 } 3935 3936 int flags = sc.flags & SCOPE.ignoresymbolvisibility ? IgnoreSymbolVisibility : 0; 3937 s = mt.sym.search(e.loc, ident, flags | IgnorePrivateImports); 3938 3939 L1: 3940 if (!s) 3941 { 3942 // See if it's 'this' class or a base class 3943 if (mt.sym.ident == ident) 3944 { 3945 if (e.op == TOK.type) 3946 { 3947 return mt.Type.getProperty(sc, e.loc, ident, 0); 3948 } 3949 e = new DotTypeExp(e.loc, e, mt.sym); 3950 e = e.expressionSemantic(sc); 3951 return e; 3952 } 3953 if (auto cbase = mt.sym.searchBase(ident)) 3954 { 3955 if (e.op == TOK.type) 3956 { 3957 return mt.Type.getProperty(sc, e.loc, ident, 0); 3958 } 3959 if (auto ifbase = cbase.isInterfaceDeclaration()) 3960 e = new CastExp(e.loc, e, ifbase.type); 3961 else 3962 e = new DotTypeExp(e.loc, e, cbase); 3963 e = e.expressionSemantic(sc); 3964 return e; 3965 } 3966 3967 if (ident == Id.classinfo) 3968 { 3969 if (!Type.typeinfoclass) 3970 { 3971 error(e.loc, "`object.TypeInfo_Class` could not be found, but is implicitly used"); 3972 return new ErrorExp(); 3973 } 3974 3975 Type t = Type.typeinfoclass.type; 3976 if (e.op == TOK.type || e.op == TOK.dotType) 3977 { 3978 /* For type.classinfo, we know the classinfo 3979 * at compile time. 3980 */ 3981 if (!mt.sym.vclassinfo) 3982 mt.sym.vclassinfo = new TypeInfoClassDeclaration(mt.sym.type); 3983 e = new VarExp(e.loc, mt.sym.vclassinfo); 3984 e = e.addressOf(); 3985 e.type = t; // do this so we don't get redundant dereference 3986 } 3987 else 3988 { 3989 /* For class objects, the classinfo reference is the first 3990 * entry in the vtbl[] 3991 */ 3992 e = new PtrExp(e.loc, e); 3993 e.type = t.pointerTo(); 3994 if (mt.sym.isInterfaceDeclaration()) 3995 { 3996 if (mt.sym.isCPPinterface()) 3997 { 3998 /* C++ interface vtbl[]s are different in that the 3999 * first entry is always pointer to the first virtual 4000 * function, not classinfo. 4001 * We can't get a .classinfo for it. 4002 */ 4003 error(e.loc, "no `.classinfo` for C++ interface objects"); 4004 } 4005 /* For an interface, the first entry in the vtbl[] 4006 * is actually a pointer to an instance of struct Interface. 4007 * The first member of Interface is the .classinfo, 4008 * so add an extra pointer indirection. 4009 */ 4010 e.type = e.type.pointerTo(); 4011 e = new PtrExp(e.loc, e); 4012 e.type = t.pointerTo(); 4013 } 4014 e = new PtrExp(e.loc, e, t); 4015 } 4016 return e; 4017 } 4018 4019 if (ident == Id.__vptr) 4020 { 4021 /* The pointer to the vtbl[] 4022 * *cast(immutable(void*)**)e 4023 */ 4024 e = e.castTo(sc, mt.tvoidptr.immutableOf().pointerTo().pointerTo()); 4025 e = new PtrExp(e.loc, e); 4026 e = e.expressionSemantic(sc); 4027 return e; 4028 } 4029 4030 if (ident == Id.__monitor && mt.sym.hasMonitor()) 4031 { 4032 /* The handle to the monitor (call it a void*) 4033 * *(cast(void**)e + 1) 4034 */ 4035 e = e.castTo(sc, mt.tvoidptr.pointerTo()); 4036 e = new AddExp(e.loc, e, IntegerExp.literal!1); 4037 e = new PtrExp(e.loc, e); 4038 e = e.expressionSemantic(sc); 4039 return e; 4040 } 4041 4042 if (ident == Id.outer && mt.sym.vthis) 4043 { 4044 if (mt.sym.vthis.semanticRun == PASS.init) 4045 mt.sym.vthis.dsymbolSemantic(null); 4046 4047 if (auto cdp = mt.sym.toParentLocal().isClassDeclaration()) 4048 { 4049 auto dve = new DotVarExp(e.loc, e, mt.sym.vthis); 4050 dve.type = cdp.type.addMod(e.type.mod); 4051 return dve; 4052 } 4053 4054 /* https://issues.dlang.org/show_bug.cgi?id=15839 4055 * Find closest parent class through nested functions. 4056 */ 4057 for (auto p = mt.sym.toParentLocal(); p; p = p.toParentLocal()) 4058 { 4059 auto fd = p.isFuncDeclaration(); 4060 if (!fd) 4061 break; 4062 auto ad = fd.isThis(); 4063 if (!ad && fd.isNested()) 4064 continue; 4065 if (!ad) 4066 break; 4067 if (auto cdp = ad.isClassDeclaration()) 4068 { 4069 auto ve = new ThisExp(e.loc); 4070 4071 ve.var = fd.vthis; 4072 const nestedError = fd.vthis.checkNestedReference(sc, e.loc); 4073 assert(!nestedError); 4074 4075 ve.type = cdp.type.addMod(fd.vthis.type.mod).addMod(e.type.mod); 4076 return ve; 4077 } 4078 break; 4079 } 4080 4081 // Continue to show enclosing function's frame (stack or closure). 4082 auto dve = new DotVarExp(e.loc, e, mt.sym.vthis); 4083 dve.type = mt.sym.vthis.type.addMod(e.type.mod); 4084 return dve; 4085 } 4086 4087 return noMember(mt, sc, e, ident, flag & 1); 4088 } 4089 if (!(sc.flags & SCOPE.ignoresymbolvisibility) && !symbolIsVisible(sc, s)) 4090 { 4091 return noMember(mt, sc, e, ident, flag); 4092 } 4093 if (!s.isFuncDeclaration()) // because of overloading 4094 { 4095 s.checkDeprecated(e.loc, sc); 4096 if (auto d = s.isDeclaration()) 4097 d.checkDisabled(e.loc, sc); 4098 } 4099 s = s.toAlias(); 4100 4101 if (auto em = s.isEnumMember()) 4102 { 4103 return em.getVarExp(e.loc, sc); 4104 } 4105 if (auto v = s.isVarDeclaration()) 4106 { 4107 if (!v.type || 4108 !v.type.deco && v.inuse) 4109 { 4110 if (v.inuse) // https://issues.dlang.org/show_bug.cgi?id=9494 4111 e.error("circular reference to %s `%s`", v.kind(), v.toPrettyChars()); 4112 else 4113 e.error("forward reference to %s `%s`", v.kind(), v.toPrettyChars()); 4114 return new ErrorExp(); 4115 } 4116 if (v.type.ty == Terror) 4117 { 4118 return new ErrorExp(); 4119 } 4120 4121 if ((v.storage_class & STC.manifest) && v._init) 4122 { 4123 if (v.inuse) 4124 { 4125 e.error("circular initialization of %s `%s`", v.kind(), v.toPrettyChars()); 4126 return new ErrorExp(); 4127 } 4128 checkAccess(e.loc, sc, null, v); 4129 Expression ve = new VarExp(e.loc, v); 4130 ve = ve.expressionSemantic(sc); 4131 return ve; 4132 } 4133 } 4134 4135 if (auto t = s.getType()) 4136 { 4137 return (new TypeExp(e.loc, t)).expressionSemantic(sc); 4138 } 4139 4140 TemplateMixin tm = s.isTemplateMixin(); 4141 if (tm) 4142 { 4143 Expression de = new DotExp(e.loc, e, new ScopeExp(e.loc, tm)); 4144 de.type = e.type; 4145 return de; 4146 } 4147 4148 TemplateDeclaration td = s.isTemplateDeclaration(); 4149 if (td) 4150 { 4151 if (e.op == TOK.type) 4152 e = new TemplateExp(e.loc, td); 4153 else 4154 e = new DotTemplateExp(e.loc, e, td); 4155 e = e.expressionSemantic(sc); 4156 return e; 4157 } 4158 4159 TemplateInstance ti = s.isTemplateInstance(); 4160 if (ti) 4161 { 4162 if (!ti.semanticRun) 4163 { 4164 ti.dsymbolSemantic(sc); 4165 if (!ti.inst || ti.errors) // if template failed to expand 4166 { 4167 return new ErrorExp(); 4168 } 4169 } 4170 s = ti.inst.toAlias(); 4171 if (!s.isTemplateInstance()) 4172 goto L1; 4173 if (e.op == TOK.type) 4174 e = new ScopeExp(e.loc, ti); 4175 else 4176 e = new DotExp(e.loc, e, new ScopeExp(e.loc, ti)); 4177 return e.expressionSemantic(sc); 4178 } 4179 4180 if (s.isImport() || s.isModule() || s.isPackage()) 4181 { 4182 e = symbolToExp(s, e.loc, sc, false); 4183 return e; 4184 } 4185 4186 OverloadSet o = s.isOverloadSet(); 4187 if (o) 4188 { 4189 auto oe = new OverExp(e.loc, o); 4190 if (e.op == TOK.type) 4191 { 4192 return oe; 4193 } 4194 return new DotExp(e.loc, e, oe); 4195 } 4196 4197 Declaration d = s.isDeclaration(); 4198 if (!d) 4199 { 4200 e.error("`%s.%s` is not a declaration", e.toChars(), ident.toChars()); 4201 return new ErrorExp(); 4202 } 4203 4204 if (e.op == TOK.type) 4205 { 4206 /* It's: 4207 * Class.d 4208 */ 4209 if (TupleDeclaration tup = d.isTupleDeclaration()) 4210 { 4211 e = new TupleExp(e.loc, tup); 4212 e = e.expressionSemantic(sc); 4213 return e; 4214 } 4215 4216 if (mt.sym.classKind == ClassKind.objc 4217 && d.isFuncDeclaration() 4218 && d.isFuncDeclaration().isStatic 4219 && d.isFuncDeclaration().selector) 4220 { 4221 auto classRef = new ObjcClassReferenceExp(e.loc, mt.sym); 4222 return new DotVarExp(e.loc, classRef, d).expressionSemantic(sc); 4223 } 4224 else if (d.needThis() && sc.intypeof != 1) 4225 { 4226 /* Rewrite as: 4227 * this.d 4228 */ 4229 AggregateDeclaration ad = d.isMemberLocal(); 4230 if (auto f = hasThis(sc)) 4231 { 4232 // This is almost same as getRightThis() in expressionsem.d 4233 Expression e1; 4234 Type t; 4235 /* returns: true to continue, false to return */ 4236 if (f.isThis2) 4237 { 4238 if (f.followInstantiationContext(ad)) 4239 { 4240 e1 = new VarExp(e.loc, f.vthis); 4241 e1 = new PtrExp(e1.loc, e1); 4242 e1 = new IndexExp(e1.loc, e1, IntegerExp.literal!1); 4243 auto pd = f.toParent2().isDeclaration(); 4244 assert(pd); 4245 t = pd.type.toBasetype(); 4246 e1 = getThisSkipNestedFuncs(e1.loc, sc, f.toParent2(), ad, e1, t, d, true); 4247 if (!e1) 4248 { 4249 e = new VarExp(e.loc, d); 4250 return e; 4251 } 4252 goto L2; 4253 } 4254 } 4255 e1 = new ThisExp(e.loc); 4256 e1 = e1.expressionSemantic(sc); 4257 L2: 4258 t = e1.type.toBasetype(); 4259 ClassDeclaration cd = e.type.isClassHandle(); 4260 ClassDeclaration tcd = t.isClassHandle(); 4261 if (cd && tcd && (tcd == cd || cd.isBaseOf(tcd, null))) 4262 { 4263 e = new DotTypeExp(e1.loc, e1, cd); 4264 e = new DotVarExp(e.loc, e, d); 4265 e = e.expressionSemantic(sc); 4266 return e; 4267 } 4268 if (tcd && tcd.isNested()) 4269 { 4270 /* e1 is the 'this' pointer for an inner class: tcd. 4271 * Rewrite it as the 'this' pointer for the outer class. 4272 */ 4273 auto vthis = tcd.followInstantiationContext(ad) ? tcd.vthis2 : tcd.vthis; 4274 e1 = new DotVarExp(e.loc, e1, vthis); 4275 e1.type = vthis.type; 4276 e1.type = e1.type.addMod(t.mod); 4277 // Do not call ensureStaticLinkTo() 4278 //e1 = e1.expressionSemantic(sc); 4279 4280 // Skip up over nested functions, and get the enclosing 4281 // class type. 4282 e1 = getThisSkipNestedFuncs(e1.loc, sc, tcd.toParentP(ad), ad, e1, t, d, true); 4283 if (!e1) 4284 { 4285 e = new VarExp(e.loc, d); 4286 return e; 4287 } 4288 goto L2; 4289 } 4290 } 4291 } 4292 //printf("e = %s, d = %s\n", e.toChars(), d.toChars()); 4293 if (d.semanticRun == PASS.init) 4294 d.dsymbolSemantic(null); 4295 4296 // If static function, get the most visible overload. 4297 // Later on the call is checked for correctness. 4298 // https://issues.dlang.org/show_bug.cgi?id=12511 4299 if (auto fd = d.isFuncDeclaration()) 4300 { 4301 import dmd.access : mostVisibleOverload; 4302 d = cast(Declaration)mostVisibleOverload(fd, sc._module); 4303 } 4304 4305 checkAccess(e.loc, sc, e, d); 4306 auto ve = new VarExp(e.loc, d); 4307 if (d.isVarDeclaration() && d.needThis()) 4308 ve.type = d.type.addMod(e.type.mod); 4309 return ve; 4310 } 4311 4312 bool unreal = e.op == TOK.variable && (cast(VarExp)e).var.isField(); 4313 if (d.isDataseg() || unreal && d.isField()) 4314 { 4315 // (e, d) 4316 checkAccess(e.loc, sc, e, d); 4317 Expression ve = new VarExp(e.loc, d); 4318 e = unreal ? ve : new CommaExp(e.loc, e, ve); 4319 e = e.expressionSemantic(sc); 4320 return e; 4321 } 4322 4323 e = new DotVarExp(e.loc, e, d); 4324 e = e.expressionSemantic(sc); 4325 return e; 4326 } 4327 4328 switch (mt.ty) 4329 { 4330 case Tvector: return visitVector (cast(TypeVector)mt); 4331 case Tsarray: return visitSArray (cast(TypeSArray)mt); 4332 case Tstruct: return visitStruct (cast(TypeStruct)mt); 4333 case Tenum: return visitEnum (cast(TypeEnum)mt); 4334 case Terror: return visitError (cast(TypeError)mt); 4335 case Tarray: return visitDArray (cast(TypeDArray)mt); 4336 case Taarray: return visitAArray (cast(TypeAArray)mt); 4337 case Treference: return visitReference(cast(TypeReference)mt); 4338 case Tdelegate: return visitDelegate (cast(TypeDelegate)mt); 4339 case Tclass: return visitClass (cast(TypeClass)mt); 4340 4341 default: return mt.isTypeBasic() 4342 ? visitBasic(cast(TypeBasic)mt) 4343 : visitType(mt); 4344 } 4345 } 4346 4347 4348 /************************ 4349 * Get the the default initialization expression for a type. 4350 * Params: 4351 * mt = the type for which the init expression is returned 4352 * loc = the location where the expression needs to be evaluated 4353 * 4354 * Returns: 4355 * The initialization expression for the type. 4356 */ 4357 Expression defaultInit(Type mt, const ref Loc loc) 4358 { 4359 Expression visitBasic(TypeBasic mt) 4360 { 4361 static if (LOGDEFAULTINIT) 4362 { 4363 printf("TypeBasic::defaultInit() '%s'\n", mt.toChars()); 4364 } 4365 dinteger_t value = 0; 4366 4367 switch (mt.ty) 4368 { 4369 case Tchar: 4370 value = 0xFF; 4371 break; 4372 4373 case Twchar: 4374 case Tdchar: 4375 value = 0xFFFF; 4376 break; 4377 4378 case Timaginary32: 4379 case Timaginary64: 4380 case Timaginary80: 4381 case Tfloat32: 4382 case Tfloat64: 4383 case Tfloat80: 4384 return new RealExp(loc, target.RealProperties.nan, mt); 4385 4386 case Tcomplex32: 4387 case Tcomplex64: 4388 case Tcomplex80: 4389 { 4390 // Can't use fvalue + I*fvalue (the im part becomes a quiet NaN). 4391 const cvalue = complex_t(target.RealProperties.nan, target.RealProperties.nan); 4392 return new ComplexExp(loc, cvalue, mt); 4393 } 4394 4395 case Tvoid: 4396 error(loc, "`void` does not have a default initializer"); 4397 return new ErrorExp(); 4398 4399 default: 4400 break; 4401 } 4402 return new IntegerExp(loc, value, mt); 4403 } 4404 4405 Expression visitVector(TypeVector mt) 4406 { 4407 //printf("TypeVector::defaultInit()\n"); 4408 assert(mt.basetype.ty == Tsarray); 4409 Expression e = mt.basetype.defaultInit(loc); 4410 auto ve = new VectorExp(loc, e, mt); 4411 ve.type = mt; 4412 ve.dim = cast(int)(mt.basetype.size(loc) / mt.elementType().size(loc)); 4413 return ve; 4414 } 4415 4416 Expression visitSArray(TypeSArray mt) 4417 { 4418 static if (LOGDEFAULTINIT) 4419 { 4420 printf("TypeSArray::defaultInit() '%s'\n", mt.toChars()); 4421 } 4422 if (mt.next.ty == Tvoid) 4423 return mt.tuns8.defaultInit(loc); 4424 else 4425 return mt.next.defaultInit(loc); 4426 } 4427 4428 Expression visitFunction(TypeFunction mt) 4429 { 4430 error(loc, "`function` does not have a default initializer"); 4431 return new ErrorExp(); 4432 } 4433 4434 Expression visitStruct(TypeStruct mt) 4435 { 4436 static if (LOGDEFAULTINIT) 4437 { 4438 printf("TypeStruct::defaultInit() '%s'\n", mt.toChars()); 4439 } 4440 Declaration d = new SymbolDeclaration(mt.sym.loc, mt.sym); 4441 assert(d); 4442 d.type = mt; 4443 d.storage_class |= STC.rvalue; // https://issues.dlang.org/show_bug.cgi?id=14398 4444 return new VarExp(mt.sym.loc, d); 4445 } 4446 4447 Expression visitEnum(TypeEnum mt) 4448 { 4449 static if (LOGDEFAULTINIT) 4450 { 4451 printf("TypeEnum::defaultInit() '%s'\n", mt.toChars()); 4452 } 4453 // Initialize to first member of enum 4454 Expression e = mt.sym.getDefaultValue(loc); 4455 e = e.copy(); 4456 e.loc = loc; 4457 e.type = mt; // to deal with const, immutable, etc., variants 4458 return e; 4459 } 4460 4461 Expression visitTuple(TypeTuple mt) 4462 { 4463 static if (LOGDEFAULTINIT) 4464 { 4465 printf("TypeTuple::defaultInit() '%s'\n", mt.toChars()); 4466 } 4467 auto exps = new Expressions(mt.arguments.dim); 4468 for (size_t i = 0; i < mt.arguments.dim; i++) 4469 { 4470 Parameter p = (*mt.arguments)[i]; 4471 assert(p.type); 4472 Expression e = p.type.defaultInitLiteral(loc); 4473 if (e.op == TOK.error) 4474 { 4475 return e; 4476 } 4477 (*exps)[i] = e; 4478 } 4479 return new TupleExp(loc, exps); 4480 } 4481 4482 switch (mt.ty) 4483 { 4484 case Tvector: return visitVector (cast(TypeVector)mt); 4485 case Tsarray: return visitSArray (cast(TypeSArray)mt); 4486 case Tfunction: return visitFunction(cast(TypeFunction)mt); 4487 case Tstruct: return visitStruct (cast(TypeStruct)mt); 4488 case Tenum: return visitEnum (cast(TypeEnum)mt); 4489 case Ttuple: return visitTuple (cast(TypeTuple)mt); 4490 4491 case Tnull: return new NullExp(Loc.initial, Type.tnull); 4492 4493 case Terror: return new ErrorExp(); 4494 4495 case Tarray: 4496 case Taarray: 4497 case Tpointer: 4498 case Treference: 4499 case Tdelegate: 4500 case Tclass: return new NullExp(loc, mt); 4501 4502 default: return mt.isTypeBasic() ? 4503 visitBasic(cast(TypeBasic)mt) : 4504 null; 4505 } 4506 }