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