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