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