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