1 /** 2 * Miscellaneous declarations, including typedef, alias, variable declarations including the 3 * implicit this declaration, type tuples, ClassInfo, ModuleInfo and various TypeInfos. 4 * 5 * Copyright: Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved 6 * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) 7 * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) 8 * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/declaration.d, _declaration.d) 9 * Documentation: https://dlang.org/phobos/dmd_declaration.html 10 * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/declaration.d 11 */ 12 13 module dmd.declaration; 14 15 import core.stdc.stdio; 16 import dmd.aggregate; 17 import dmd.arraytypes; 18 import dmd.astenums; 19 import dmd.attrib; 20 import dmd.ctorflow; 21 import dmd.dclass; 22 import dmd.delegatize; 23 import dmd.dscope; 24 import dmd.dstruct; 25 import dmd.dsymbol; 26 import dmd.dsymbolsem; 27 import dmd.dtemplate; 28 import dmd.errors; 29 import dmd.expression; 30 import dmd.func; 31 import dmd.globals; 32 import dmd.gluelayer; 33 import dmd.id; 34 import dmd.identifier; 35 import dmd.init; 36 import dmd.initsem; 37 import dmd.intrange; 38 import dmd.mtype; 39 import dmd.common.outbuffer; 40 import dmd.root.rootobject; 41 import dmd.target; 42 import dmd.tokens; 43 import dmd.typesem; 44 import dmd.visitor; 45 46 /************************************ 47 * Check to see the aggregate type is nested and its context pointer is 48 * accessible from the current scope. 49 * Returns true if error occurs. 50 */ 51 bool checkFrameAccess(Loc loc, Scope* sc, AggregateDeclaration ad, size_t iStart = 0) 52 { 53 Dsymbol sparent = ad.toParentLocal(); 54 Dsymbol sparent2 = ad.toParent2(); 55 Dsymbol s = sc.func; 56 if (ad.isNested() && s) 57 { 58 //printf("ad = %p %s [%s], parent:%p\n", ad, ad.toChars(), ad.loc.toChars(), ad.parent); 59 //printf("sparent = %p %s [%s], parent: %s\n", sparent, sparent.toChars(), sparent.loc.toChars(), sparent.parent,toChars()); 60 //printf("sparent2 = %p %s [%s], parent: %s\n", sparent2, sparent2.toChars(), sparent2.loc.toChars(), sparent2.parent,toChars()); 61 if (!ensureStaticLinkTo(s, sparent) || sparent != sparent2 && !ensureStaticLinkTo(s, sparent2)) 62 { 63 error(loc, "cannot access frame pointer of `%s`", ad.toPrettyChars()); 64 return true; 65 } 66 } 67 68 bool result = false; 69 for (size_t i = iStart; i < ad.fields.dim; i++) 70 { 71 VarDeclaration vd = ad.fields[i]; 72 Type tb = vd.type.baseElemOf(); 73 if (tb.ty == Tstruct) 74 { 75 result |= checkFrameAccess(loc, sc, (cast(TypeStruct)tb).sym); 76 } 77 } 78 return result; 79 } 80 81 /*********************************************** 82 * Mark variable v as modified if it is inside a constructor that var 83 * is a field in. 84 */ 85 bool modifyFieldVar(Loc loc, Scope* sc, VarDeclaration var, Expression e1) 86 { 87 //printf("modifyFieldVar(var = %s)\n", var.toChars()); 88 Dsymbol s = sc.func; 89 while (1) 90 { 91 FuncDeclaration fd = null; 92 if (s) 93 fd = s.isFuncDeclaration(); 94 if (fd && 95 ((fd.isCtorDeclaration() && var.isField()) || 96 (fd.isStaticCtorDeclaration() && !var.isField())) && 97 fd.toParentDecl() == var.toParent2() && 98 (!e1 || e1.op == EXP.this_)) 99 { 100 bool result = true; 101 102 var.ctorinit = true; 103 //printf("setting ctorinit\n"); 104 105 if (var.isField() && sc.ctorflow.fieldinit.length && !sc.intypeof) 106 { 107 assert(e1); 108 auto mustInit = ((var.storage_class & STC.nodefaultctor) != 0 || 109 var.type.needsNested()); 110 111 const dim = sc.ctorflow.fieldinit.length; 112 auto ad = fd.isMemberDecl(); 113 assert(ad); 114 size_t i; 115 for (i = 0; i < dim; i++) // same as findFieldIndexByName in ctfeexp.c ? 116 { 117 if (ad.fields[i] == var) 118 break; 119 } 120 assert(i < dim); 121 auto fieldInit = &sc.ctorflow.fieldinit[i]; 122 const fi = fieldInit.csx; 123 124 if (fi & CSX.this_ctor) 125 { 126 if (var.type.isMutable() && e1.type.isMutable()) 127 result = false; 128 else 129 { 130 const(char)* modStr = !var.type.isMutable() ? MODtoChars(var.type.mod) : MODtoChars(e1.type.mod); 131 .error(loc, "%s field `%s` initialized multiple times", modStr, var.toChars()); 132 .errorSupplemental(fieldInit.loc, "Previous initialization is here."); 133 } 134 } 135 else if (sc.inLoop || (fi & CSX.label)) 136 { 137 if (!mustInit && var.type.isMutable() && e1.type.isMutable()) 138 result = false; 139 else 140 { 141 const(char)* modStr = !var.type.isMutable() ? MODtoChars(var.type.mod) : MODtoChars(e1.type.mod); 142 .error(loc, "%s field `%s` initialization is not allowed in loops or after labels", modStr, var.toChars()); 143 } 144 } 145 146 fieldInit.csx |= CSX.this_ctor; 147 fieldInit.loc = e1.loc; 148 if (var.overlapped) // https://issues.dlang.org/show_bug.cgi?id=15258 149 { 150 foreach (j, v; ad.fields) 151 { 152 if (v is var || !var.isOverlappedWith(v)) 153 continue; 154 v.ctorinit = true; 155 sc.ctorflow.fieldinit[j].csx = CSX.this_ctor; 156 } 157 } 158 } 159 else if (fd != sc.func) 160 { 161 if (var.type.isMutable()) 162 result = false; 163 else if (sc.func.fes) 164 { 165 const(char)* p = var.isField() ? "field" : var.kind(); 166 .error(loc, "%s %s `%s` initialization is not allowed in foreach loop", 167 MODtoChars(var.type.mod), p, var.toChars()); 168 } 169 else 170 { 171 const(char)* p = var.isField() ? "field" : var.kind(); 172 .error(loc, "%s %s `%s` initialization is not allowed in nested function `%s`", 173 MODtoChars(var.type.mod), p, var.toChars(), sc.func.toChars()); 174 } 175 } 176 else if (fd.isStaticCtorDeclaration() && !fd.isSharedStaticCtorDeclaration() && 177 var.type.isImmutable()) 178 { 179 .error(loc, "%s %s `%s` initialization is not allowed in `static this`", 180 MODtoChars(var.type.mod), var.kind(), var.toChars()); 181 errorSupplemental(loc, "Use `shared static this` instead."); 182 } 183 return result; 184 } 185 else 186 { 187 if (s) 188 { 189 s = s.toParentP(var.toParent2()); 190 continue; 191 } 192 } 193 break; 194 } 195 return false; 196 } 197 198 /****************************************** 199 */ 200 extern (C++) void ObjectNotFound(Identifier id) 201 { 202 error(Loc.initial, "`%s` not found. object.d may be incorrectly installed or corrupt.", id.toChars()); 203 fatal(); 204 } 205 206 /* Accumulator for successive matches. 207 */ 208 struct MatchAccumulator 209 { 210 int count; // number of matches found so far 211 MATCH last = MATCH.nomatch; // match level of lastf 212 FuncDeclaration lastf; // last matching function we found 213 FuncDeclaration nextf; // if ambiguous match, this is the "other" function 214 } 215 216 /*********************************************************** 217 */ 218 extern (C++) abstract class Declaration : Dsymbol 219 { 220 Type type; 221 Type originalType; // before semantic analysis 222 StorageClass storage_class = STC.undefined_; 223 Visibility visibility; 224 LINK _linkage = LINK.default_; // may be `LINK.system`; use `resolvedLinkage()` to resolve it 225 short inuse; // used to detect cycles 226 227 ubyte adFlags; // control re-assignment of AliasDeclaration (put here for packing reasons) 228 enum wasRead = 1; // set if AliasDeclaration was read 229 enum ignoreRead = 2; // ignore any reads of AliasDeclaration 230 231 Symbol* isym; // import version of csym 232 233 // overridden symbol with pragma(mangle, "...") 234 const(char)[] mangleOverride; 235 236 final extern (D) this(Identifier ident) 237 { 238 super(ident); 239 visibility = Visibility(Visibility.Kind.undefined); 240 } 241 242 final extern (D) this(const ref Loc loc, Identifier ident) 243 { 244 super(loc, ident); 245 visibility = Visibility(Visibility.Kind.undefined); 246 } 247 248 override const(char)* kind() const 249 { 250 return "declaration"; 251 } 252 253 override final uinteger_t size(const ref Loc loc) 254 { 255 assert(type); 256 const sz = type.size(); 257 if (sz == SIZE_INVALID) 258 errors = true; 259 return sz; 260 } 261 262 /** 263 * Issue an error if an attempt to call a disabled method is made 264 * 265 * If the declaration is disabled but inside a disabled function, 266 * returns `true` but do not issue an error message. 267 * 268 * Params: 269 * loc = Location information of the call 270 * sc = Scope in which the call occurs 271 * isAliasedDeclaration = if `true` searches overload set 272 * 273 * Returns: 274 * `true` if this `Declaration` is `@disable`d, `false` otherwise. 275 */ 276 extern (D) final bool checkDisabled(Loc loc, Scope* sc, bool isAliasedDeclaration = false) 277 { 278 if (!(storage_class & STC.disable)) 279 return false; 280 281 if (sc.func && sc.func.storage_class & STC.disable) 282 return true; 283 284 if (auto p = toParent()) 285 { 286 if (auto postblit = isPostBlitDeclaration()) 287 { 288 /* https://issues.dlang.org/show_bug.cgi?id=21885 289 * 290 * If the generated postblit is disabled, it 291 * means that one of the fields has a disabled 292 * postblit. Print the first field that has 293 * a disabled postblit. 294 */ 295 if (postblit.isGenerated()) 296 { 297 auto sd = p.isStructDeclaration(); 298 assert(sd); 299 for (size_t i = 0; i < sd.fields.dim; i++) 300 { 301 auto structField = sd.fields[i]; 302 if (structField.overlapped) 303 continue; 304 Type tv = structField.type.baseElemOf(); 305 if (tv.ty != Tstruct) 306 continue; 307 auto sdv = (cast(TypeStruct)tv).sym; 308 if (!sdv.postblit) 309 continue; 310 if (sdv.postblit.isDisabled()) 311 { 312 p.error(loc, "is not copyable because field `%s` is not copyable", structField.toChars()); 313 return true; 314 } 315 } 316 } 317 p.error(loc, "is not copyable because it has a disabled postblit"); 318 return true; 319 } 320 } 321 322 // if the function is @disabled, maybe there 323 // is an overload in the overload set that isn't 324 if (isAliasedDeclaration) 325 { 326 FuncDeclaration fd = isFuncDeclaration(); 327 if (fd) 328 { 329 for (FuncDeclaration ovl = fd; ovl; ovl = cast(FuncDeclaration)ovl.overnext) 330 if (!(ovl.storage_class & STC.disable)) 331 return false; 332 } 333 } 334 335 if (auto ctor = isCtorDeclaration()) 336 { 337 if (ctor.isCpCtor && ctor.isGenerated()) 338 { 339 .error(loc, "Generating an `inout` copy constructor for `struct %s` failed, therefore instances of it are uncopyable", parent.toPrettyChars()); 340 return true; 341 } 342 } 343 error(loc, "cannot be used because it is annotated with `@disable`"); 344 return true; 345 } 346 347 /************************************* 348 * Check to see if declaration can be modified in this context (sc). 349 * Issue error if not. 350 * Params: 351 * loc = location for error messages 352 * e1 = `null` or `this` expression when this declaration is a field 353 * sc = context 354 * flag = if the first bit is set it means do not issue error message for 355 * invalid modification; if the second bit is set, it means that 356 this declaration is a field and a subfield of it is modified. 357 * Returns: 358 * Modifiable.yes or Modifiable.initialization 359 */ 360 extern (D) final Modifiable checkModify(Loc loc, Scope* sc, Expression e1, ModifyFlags flag) 361 { 362 VarDeclaration v = isVarDeclaration(); 363 if (v && v.canassign) 364 return Modifiable.initialization; 365 366 if (isParameter() || isResult()) 367 { 368 for (Scope* scx = sc; scx; scx = scx.enclosing) 369 { 370 if (scx.func == parent && (scx.flags & SCOPE.contract)) 371 { 372 const(char)* s = isParameter() && parent.ident != Id.ensure ? "parameter" : "result"; 373 if (!(flag & ModifyFlags.noError)) 374 error(loc, "cannot modify %s `%s` in contract", s, toChars()); 375 return Modifiable.initialization; // do not report type related errors 376 } 377 } 378 } 379 380 if (e1 && e1.op == EXP.this_ && isField()) 381 { 382 VarDeclaration vthis = e1.isThisExp().var; 383 for (Scope* scx = sc; scx; scx = scx.enclosing) 384 { 385 if (scx.func == vthis.parent && (scx.flags & SCOPE.contract)) 386 { 387 if (!(flag & ModifyFlags.noError)) 388 error(loc, "cannot modify parameter `this` in contract"); 389 return Modifiable.initialization; // do not report type related errors 390 } 391 } 392 } 393 394 if (v && (v.isCtorinit() || isField())) 395 { 396 // It's only modifiable if inside the right constructor 397 if ((storage_class & (STC.foreach_ | STC.ref_)) == (STC.foreach_ | STC.ref_)) 398 return Modifiable.initialization; 399 if (flag & ModifyFlags.fieldAssign) 400 return Modifiable.yes; 401 return modifyFieldVar(loc, sc, v, e1) ? Modifiable.initialization : Modifiable.yes; 402 } 403 return Modifiable.yes; 404 } 405 406 override final Dsymbol search(const ref Loc loc, Identifier ident, int flags = SearchLocalsOnly) 407 { 408 Dsymbol s = Dsymbol.search(loc, ident, flags); 409 if (!s && type) 410 { 411 s = type.toDsymbol(_scope); 412 if (s) 413 s = s.search(loc, ident, flags); 414 } 415 return s; 416 } 417 418 final bool isStatic() const pure nothrow @nogc @safe 419 { 420 return (storage_class & STC.static_) != 0; 421 } 422 423 /// Returns the linkage, resolving the target-specific `System` one. 424 final LINK resolvedLinkage() const 425 { 426 return _linkage == LINK.system ? target.systemLinkage() : _linkage; 427 } 428 429 bool isDelete() 430 { 431 return false; 432 } 433 434 bool isDataseg() 435 { 436 return false; 437 } 438 439 bool isThreadlocal() 440 { 441 return false; 442 } 443 444 bool isCodeseg() const pure nothrow @nogc @safe 445 { 446 return false; 447 } 448 449 final bool isFinal() const pure nothrow @nogc @safe 450 { 451 return (storage_class & STC.final_) != 0; 452 } 453 454 bool isAbstract() 455 { 456 return (storage_class & STC.abstract_) != 0; 457 } 458 459 final bool isConst() const pure nothrow @nogc @safe 460 { 461 return (storage_class & STC.const_) != 0; 462 } 463 464 final bool isImmutable() const pure nothrow @nogc @safe 465 { 466 return (storage_class & STC.immutable_) != 0; 467 } 468 469 final bool isWild() const pure nothrow @nogc @safe 470 { 471 return (storage_class & STC.wild) != 0; 472 } 473 474 final bool isAuto() const pure nothrow @nogc @safe 475 { 476 return (storage_class & STC.auto_) != 0; 477 } 478 479 final bool isScope() const pure nothrow @nogc @safe 480 { 481 return (storage_class & STC.scope_) != 0; 482 } 483 484 final bool isSynchronized() const pure nothrow @nogc @safe 485 { 486 return (storage_class & STC.synchronized_) != 0; 487 } 488 489 final bool isParameter() const pure nothrow @nogc @safe 490 { 491 return (storage_class & STC.parameter) != 0; 492 } 493 494 override final bool isDeprecated() const pure nothrow @nogc @safe 495 { 496 return (storage_class & STC.deprecated_) != 0; 497 } 498 499 final bool isDisabled() const pure nothrow @nogc @safe 500 { 501 return (storage_class & STC.disable) != 0; 502 } 503 504 final bool isOverride() const pure nothrow @nogc @safe 505 { 506 return (storage_class & STC.override_) != 0; 507 } 508 509 final bool isResult() const pure nothrow @nogc @safe 510 { 511 return (storage_class & STC.result) != 0; 512 } 513 514 final bool isField() const pure nothrow @nogc @safe 515 { 516 return (storage_class & STC.field) != 0; 517 } 518 519 final bool isIn() const pure nothrow @nogc @safe 520 { 521 return (storage_class & STC.in_) != 0; 522 } 523 524 final bool isOut() const pure nothrow @nogc @safe 525 { 526 return (storage_class & STC.out_) != 0; 527 } 528 529 final bool isRef() const pure nothrow @nogc @safe 530 { 531 return (storage_class & STC.ref_) != 0; 532 } 533 534 /// Returns: Whether the variable is a reference, annotated with `out` or `ref` 535 final bool isReference() const pure nothrow @nogc @safe 536 { 537 return (storage_class & (STC.ref_ | STC.out_)) != 0; 538 } 539 540 final bool isFuture() const pure nothrow @nogc @safe 541 { 542 return (storage_class & STC.future) != 0; 543 } 544 545 override final Visibility visible() pure nothrow @nogc @safe 546 { 547 return visibility; 548 } 549 550 override final inout(Declaration) isDeclaration() inout pure nothrow @nogc @safe 551 { 552 return this; 553 } 554 555 override void accept(Visitor v) 556 { 557 v.visit(this); 558 } 559 } 560 561 /*********************************************************** 562 */ 563 extern (C++) final class TupleDeclaration : Declaration 564 { 565 Objects* objects; 566 bool isexp; // true: expression tuple 567 TypeTuple tupletype; // !=null if this is a type tuple 568 569 extern (D) this(const ref Loc loc, Identifier ident, Objects* objects) 570 { 571 super(loc, ident); 572 this.objects = objects; 573 } 574 575 override TupleDeclaration syntaxCopy(Dsymbol s) 576 { 577 assert(0); 578 } 579 580 override const(char)* kind() const 581 { 582 return "tuple"; 583 } 584 585 override Type getType() 586 { 587 /* If this tuple represents a type, return that type 588 */ 589 590 //printf("TupleDeclaration::getType() %s\n", toChars()); 591 if (isexp) 592 return null; 593 if (!tupletype) 594 { 595 /* It's only a type tuple if all the Object's are types 596 */ 597 for (size_t i = 0; i < objects.dim; i++) 598 { 599 RootObject o = (*objects)[i]; 600 if (o.dyncast() != DYNCAST.type) 601 { 602 //printf("\tnot[%d], %p, %d\n", i, o, o.dyncast()); 603 return null; 604 } 605 } 606 607 /* We know it's a type tuple, so build the TypeTuple 608 */ 609 Types* types = cast(Types*)objects; 610 auto args = new Parameters(objects.dim); 611 OutBuffer buf; 612 int hasdeco = 1; 613 for (size_t i = 0; i < types.dim; i++) 614 { 615 Type t = (*types)[i]; 616 //printf("type = %s\n", t.toChars()); 617 version (none) 618 { 619 buf.printf("_%s_%d", ident.toChars(), i); 620 const len = buf.offset; 621 const name = buf.extractSlice().ptr; 622 auto id = Identifier.idPool(name, len); 623 auto arg = new Parameter(STC.in_, t, id, null); 624 } 625 else 626 { 627 auto arg = new Parameter(0, t, null, null, null); 628 } 629 (*args)[i] = arg; 630 if (!t.deco) 631 hasdeco = 0; 632 } 633 634 tupletype = new TypeTuple(args); 635 if (hasdeco) 636 return tupletype.typeSemantic(Loc.initial, null); 637 } 638 return tupletype; 639 } 640 641 override Dsymbol toAlias2() 642 { 643 //printf("TupleDeclaration::toAlias2() '%s' objects = %s\n", toChars(), objects.toChars()); 644 for (size_t i = 0; i < objects.dim; i++) 645 { 646 RootObject o = (*objects)[i]; 647 if (Dsymbol s = isDsymbol(o)) 648 { 649 s = s.toAlias2(); 650 (*objects)[i] = s; 651 } 652 } 653 return this; 654 } 655 656 override bool needThis() 657 { 658 //printf("TupleDeclaration::needThis(%s)\n", toChars()); 659 return isexp ? foreachVar((s) { return s.needThis(); }) != 0 : false; 660 } 661 662 /*********************************************************** 663 * Calls dg(Dsymbol) for each Dsymbol, which should be a VarDeclaration 664 * inside DsymbolExp (isexp == true). 665 * Params: 666 * dg = delegate to call for each Dsymbol 667 */ 668 extern (D) void foreachVar(scope void delegate(Dsymbol) dg) 669 { 670 assert(isexp); 671 foreach (o; *objects) 672 { 673 if (auto e = o.isExpression()) 674 if (auto se = e.isDsymbolExp()) 675 dg(se.s); 676 } 677 } 678 679 /*********************************************************** 680 * Calls dg(Dsymbol) for each Dsymbol, which should be a VarDeclaration 681 * inside DsymbolExp (isexp == true). 682 * If dg returns !=0, stops and returns that value else returns 0. 683 * Params: 684 * dg = delegate to call for each Dsymbol 685 * Returns: 686 * last value returned by dg() 687 */ 688 extern (D) int foreachVar(scope int delegate(Dsymbol) dg) 689 { 690 assert(isexp); 691 foreach (o; *objects) 692 { 693 if (auto e = o.isExpression()) 694 if (auto se = e.isDsymbolExp()) 695 if(auto ret = dg(se.s)) 696 return ret; 697 } 698 return 0; 699 } 700 701 override inout(TupleDeclaration) isTupleDeclaration() inout 702 { 703 return this; 704 } 705 706 override void accept(Visitor v) 707 { 708 v.visit(this); 709 } 710 } 711 712 /*********************************************************** 713 * https://dlang.org/spec/declaration.html#AliasDeclaration 714 */ 715 extern (C++) final class AliasDeclaration : Declaration 716 { 717 Dsymbol aliassym; // alias ident = aliassym; 718 719 Dsymbol overnext; // next in overload list 720 Dsymbol _import; // !=null if unresolved internal alias for selective import 721 722 extern (D) this(const ref Loc loc, Identifier ident, Type type) 723 { 724 super(loc, ident); 725 //printf("AliasDeclaration(id = '%s', type = %p)\n", id.toChars(), type); 726 //printf("type = '%s'\n", type.toChars()); 727 this.type = type; 728 assert(type); 729 } 730 731 extern (D) this(const ref Loc loc, Identifier ident, Dsymbol s) 732 { 733 super(loc, ident); 734 //printf("AliasDeclaration(id = '%s', s = %p)\n", id.toChars(), s); 735 assert(s != this); 736 this.aliassym = s; 737 assert(s); 738 } 739 740 static AliasDeclaration create(const ref Loc loc, Identifier id, Type type) 741 { 742 return new AliasDeclaration(loc, id, type); 743 } 744 745 override AliasDeclaration syntaxCopy(Dsymbol s) 746 { 747 //printf("AliasDeclaration::syntaxCopy()\n"); 748 assert(!s); 749 AliasDeclaration sa = type ? new AliasDeclaration(loc, ident, type.syntaxCopy()) : new AliasDeclaration(loc, ident, aliassym.syntaxCopy(null)); 750 sa.comment = comment; 751 sa.storage_class = storage_class; 752 return sa; 753 } 754 755 override bool overloadInsert(Dsymbol s) 756 { 757 //printf("[%s] AliasDeclaration::overloadInsert('%s') s = %s %s @ [%s]\n", 758 // loc.toChars(), toChars(), s.kind(), s.toChars(), s.loc.toChars()); 759 760 /** Aliases aren't overloadable themselves, but if their Aliasee is 761 * overloadable they are converted to an overloadable Alias (either 762 * FuncAliasDeclaration or OverDeclaration). 763 * 764 * This is done by moving the Aliasee into such an overloadable alias 765 * which is then used to replace the existing Aliasee. The original 766 * Alias (_this_) remains a useless shell. 767 * 768 * This is a horrible mess. It was probably done to avoid replacing 769 * existing AST nodes and references, but it needs a major 770 * simplification b/c it's too complex to maintain. 771 * 772 * A simpler approach might be to merge any colliding symbols into a 773 * simple Overload class (an array) and then later have that resolve 774 * all collisions. 775 */ 776 if (semanticRun >= PASS.semanticdone) 777 { 778 /* Semantic analysis is already finished, and the aliased entity 779 * is not overloadable. 780 */ 781 if (type) 782 return false; 783 784 /* When s is added in member scope by static if, mixin("code") or others, 785 * aliassym is determined already. See the case in: test/compilable/test61.d 786 */ 787 auto sa = aliassym.toAlias(); 788 789 if (auto td = s.toAlias().isTemplateDeclaration()) 790 s = td.funcroot ? td.funcroot : td; 791 792 if (auto fd = sa.isFuncDeclaration()) 793 { 794 auto fa = new FuncAliasDeclaration(ident, fd); 795 fa.visibility = visibility; 796 fa.parent = parent; 797 aliassym = fa; 798 return aliassym.overloadInsert(s); 799 } 800 if (auto td = sa.isTemplateDeclaration()) 801 { 802 auto od = new OverDeclaration(ident, td.funcroot ? td.funcroot : td); 803 od.visibility = visibility; 804 od.parent = parent; 805 aliassym = od; 806 return aliassym.overloadInsert(s); 807 } 808 if (auto od = sa.isOverDeclaration()) 809 { 810 if (sa.ident != ident || sa.parent != parent) 811 { 812 od = new OverDeclaration(ident, od); 813 od.visibility = visibility; 814 od.parent = parent; 815 aliassym = od; 816 } 817 return od.overloadInsert(s); 818 } 819 if (auto os = sa.isOverloadSet()) 820 { 821 if (sa.ident != ident || sa.parent != parent) 822 { 823 os = new OverloadSet(ident, os); 824 // TODO: visibility is lost here b/c OverloadSets have no visibility attribute 825 // Might no be a practical issue, b/c the code below fails to resolve the overload anyhow. 826 // ---- 827 // module os1; 828 // import a, b; 829 // private alias merged = foo; // private alias to overload set of a.foo and b.foo 830 // ---- 831 // module os2; 832 // import a, b; 833 // public alias merged = bar; // public alias to overload set of a.bar and b.bar 834 // ---- 835 // module bug; 836 // import os1, os2; 837 // void test() { merged(123); } // should only look at os2.merged 838 // 839 // os.visibility = visibility; 840 os.parent = parent; 841 aliassym = os; 842 } 843 os.push(s); 844 return true; 845 } 846 return false; 847 } 848 849 /* Don't know yet what the aliased symbol is, so assume it can 850 * be overloaded and check later for correctness. 851 */ 852 if (overnext) 853 return overnext.overloadInsert(s); 854 if (s is this) 855 return true; 856 overnext = s; 857 return true; 858 } 859 860 override const(char)* kind() const 861 { 862 return "alias"; 863 } 864 865 override Type getType() 866 { 867 if (type) 868 return type; 869 return toAlias().getType(); 870 } 871 872 override Dsymbol toAlias() 873 { 874 //printf("[%s] AliasDeclaration::toAlias('%s', this = %p, aliassym = %p, kind = '%s', inuse = %d)\n", 875 // loc.toChars(), toChars(), this, aliassym, aliassym ? aliassym.kind() : "", inuse); 876 assert(this != aliassym); 877 //static int count; if (++count == 10) *(char*)0=0; 878 879 // Reading the AliasDeclaration 880 if (!(adFlags & ignoreRead)) 881 adFlags |= wasRead; // can never assign to this AliasDeclaration again 882 883 if (inuse == 1 && type && _scope) 884 { 885 inuse = 2; 886 uint olderrors = global.errors; 887 Dsymbol s = type.toDsymbol(_scope); 888 //printf("[%s] type = %s, s = %p, this = %p\n", loc.toChars(), type.toChars(), s, this); 889 if (global.errors != olderrors) 890 goto Lerr; 891 if (s) 892 { 893 s = s.toAlias(); 894 if (global.errors != olderrors) 895 goto Lerr; 896 aliassym = s; 897 inuse = 0; 898 } 899 else 900 { 901 Type t = type.typeSemantic(loc, _scope); 902 if (t.ty == Terror) 903 goto Lerr; 904 if (global.errors != olderrors) 905 goto Lerr; 906 //printf("t = %s\n", t.toChars()); 907 inuse = 0; 908 } 909 } 910 if (inuse) 911 { 912 error("recursive alias declaration"); 913 914 Lerr: 915 // Avoid breaking "recursive alias" state during errors gagged 916 if (global.gag) 917 return this; 918 aliassym = new AliasDeclaration(loc, ident, Type.terror); 919 type = Type.terror; 920 return aliassym; 921 } 922 923 if (semanticRun >= PASS.semanticdone) 924 { 925 // semantic is already done. 926 927 // Do not see aliassym !is null, because of lambda aliases. 928 929 // Do not see type.deco !is null, even so "alias T = const int;` needs 930 // semantic analysis to take the storage class `const` as type qualifier. 931 } 932 else 933 { 934 if (_import && _import._scope) 935 { 936 /* If this is an internal alias for selective/renamed import, 937 * load the module first. 938 */ 939 _import.dsymbolSemantic(null); 940 } 941 if (_scope) 942 { 943 aliasSemantic(this, _scope); 944 } 945 } 946 947 inuse = 1; 948 Dsymbol s = aliassym ? aliassym.toAlias() : this; 949 inuse = 0; 950 return s; 951 } 952 953 override Dsymbol toAlias2() 954 { 955 if (inuse) 956 { 957 error("recursive alias declaration"); 958 return this; 959 } 960 inuse = 1; 961 Dsymbol s = aliassym ? aliassym.toAlias2() : this; 962 inuse = 0; 963 return s; 964 } 965 966 override bool isOverloadable() const 967 { 968 // assume overloadable until alias is resolved 969 return semanticRun < PASS.semanticdone || 970 aliassym && aliassym.isOverloadable(); 971 } 972 973 override inout(AliasDeclaration) isAliasDeclaration() inout 974 { 975 return this; 976 } 977 978 /** Returns: `true` if this instance was created to make a template parameter 979 visible in the scope of a template body, `false` otherwise */ 980 extern (D) bool isAliasedTemplateParameter() const 981 { 982 return !!(storage_class & STC.templateparameter); 983 } 984 985 override void accept(Visitor v) 986 { 987 v.visit(this); 988 } 989 } 990 991 /*********************************************************** 992 */ 993 extern (C++) final class OverDeclaration : Declaration 994 { 995 Dsymbol overnext; // next in overload list 996 Dsymbol aliassym; 997 998 extern (D) this(Identifier ident, Dsymbol s) 999 { 1000 super(ident); 1001 this.aliassym = s; 1002 } 1003 1004 override const(char)* kind() const 1005 { 1006 return "overload alias"; // todo 1007 } 1008 1009 override bool equals(const RootObject o) const 1010 { 1011 if (this == o) 1012 return true; 1013 1014 auto s = isDsymbol(o); 1015 if (!s) 1016 return false; 1017 1018 if (auto od2 = s.isOverDeclaration()) 1019 return this.aliassym.equals(od2.aliassym); 1020 return this.aliassym == s; 1021 } 1022 1023 override bool overloadInsert(Dsymbol s) 1024 { 1025 //printf("OverDeclaration::overloadInsert('%s') aliassym = %p, overnext = %p\n", s.toChars(), aliassym, overnext); 1026 if (overnext) 1027 return overnext.overloadInsert(s); 1028 if (s == this) 1029 return true; 1030 overnext = s; 1031 return true; 1032 } 1033 1034 override bool isOverloadable() const 1035 { 1036 return true; 1037 } 1038 1039 Dsymbol isUnique() 1040 { 1041 Dsymbol result = null; 1042 overloadApply(aliassym, (Dsymbol s) 1043 { 1044 if (result) 1045 { 1046 result = null; 1047 return 1; // ambiguous, done 1048 } 1049 else 1050 { 1051 result = s; 1052 return 0; 1053 } 1054 }); 1055 return result; 1056 } 1057 1058 override inout(OverDeclaration) isOverDeclaration() inout 1059 { 1060 return this; 1061 } 1062 1063 override void accept(Visitor v) 1064 { 1065 v.visit(this); 1066 } 1067 } 1068 1069 /*********************************************************** 1070 */ 1071 extern (C++) class VarDeclaration : Declaration 1072 { 1073 Initializer _init; 1074 FuncDeclarations nestedrefs; // referenced by these lexically nested functions 1075 Dsymbol aliassym; // if redone as alias to another symbol 1076 VarDeclaration lastVar; // Linked list of variables for goto-skips-init detection 1077 Expression edtor; // if !=null, does the destruction of the variable 1078 IntRange* range; // if !=null, the variable is known to be within the range 1079 VarDeclarations* maybes; // STC.maybescope variables that are assigned to this STC.maybescope variable 1080 1081 uint endlinnum; // line number of end of scope that this var lives in 1082 uint offset; 1083 uint sequenceNumber; // order the variables are declared 1084 structalign_t alignment; 1085 1086 // When interpreting, these point to the value (NULL if value not determinable) 1087 // The index of this variable on the CTFE stack, AdrOnStackNone if not allocated 1088 enum AdrOnStackNone = ~0u; 1089 uint ctfeAdrOnStack; 1090 1091 // `bool` fields that are compacted into bit fields in a string mixin 1092 private extern (D) static struct BitFields 1093 { 1094 bool isargptr; /// if parameter that _argptr points to 1095 bool ctorinit; /// it has been initialized in a ctor 1096 bool iscatchvar; /// this is the exception object variable in catch() clause 1097 bool isowner; /// this is an Owner, despite it being `scope` 1098 bool setInCtorOnly; /// field can only be set in a constructor, as it is const or immutable 1099 1100 /// It is a class that was allocated on the stack 1101 /// 1102 /// This means the var is not rebindable once assigned, 1103 /// and the destructor gets run when it goes out of scope 1104 bool onstack; 1105 1106 bool overlapped; /// if it is a field and has overlapping 1107 bool overlapUnsafe; /// if it is an overlapping field and the overlaps are unsafe 1108 bool doNotInferScope; /// do not infer 'scope' for this variable 1109 bool doNotInferReturn; /// do not infer 'return' for this variable 1110 1111 bool isArgDtorVar; /// temporary created to handle scope destruction of a function argument 1112 } 1113 1114 import dmd.common.bitfields : generateBitFields; 1115 mixin(generateBitFields!(BitFields, ushort)); 1116 1117 byte canassign; // it can be assigned to 1118 ubyte isdataseg; // private data for isDataseg 0 unset, 1 true, 2 false 1119 1120 final extern (D) this(const ref Loc loc, Type type, Identifier ident, Initializer _init, StorageClass storage_class = STC.undefined_) 1121 in 1122 { 1123 assert(ident); 1124 } 1125 do 1126 { 1127 //printf("VarDeclaration('%s')\n", ident.toChars()); 1128 super(loc, ident); 1129 debug 1130 { 1131 if (!type && !_init) 1132 { 1133 //printf("VarDeclaration('%s')\n", ident.toChars()); 1134 //*(char*)0=0; 1135 } 1136 } 1137 1138 assert(type || _init); 1139 this.type = type; 1140 this._init = _init; 1141 ctfeAdrOnStack = AdrOnStackNone; 1142 this.storage_class = storage_class; 1143 } 1144 1145 static VarDeclaration create(const ref Loc loc, Type type, Identifier ident, Initializer _init, StorageClass storage_class = STC.undefined_) 1146 { 1147 return new VarDeclaration(loc, type, ident, _init, storage_class); 1148 } 1149 1150 override VarDeclaration syntaxCopy(Dsymbol s) 1151 { 1152 //printf("VarDeclaration::syntaxCopy(%s)\n", toChars()); 1153 assert(!s); 1154 auto v = new VarDeclaration(loc, type ? type.syntaxCopy() : null, ident, _init ? _init.syntaxCopy() : null, storage_class); 1155 v.comment = comment; 1156 return v; 1157 } 1158 1159 override void setFieldOffset(AggregateDeclaration ad, ref FieldState fieldState, bool isunion) 1160 { 1161 //printf("VarDeclaration::setFieldOffset(ad = %s) %s\n", ad.toChars(), toChars()); 1162 1163 if (aliassym) 1164 { 1165 // If this variable was really a tuple, set the offsets for the tuple fields 1166 TupleDeclaration v2 = aliassym.isTupleDeclaration(); 1167 assert(v2); 1168 v2.foreachVar((s) { s.setFieldOffset(ad, fieldState, isunion); }); 1169 return; 1170 } 1171 1172 if (!isField()) 1173 return; 1174 assert(!(storage_class & (STC.static_ | STC.extern_ | STC.parameter))); 1175 1176 //printf("+VarDeclaration::setFieldOffset(ad = %s) %s\n", ad.toChars(), toChars()); 1177 1178 /* Fields that are tuples appear both as part of TupleDeclarations and 1179 * as members. That means ignore them if they are already a field. 1180 */ 1181 if (offset) 1182 { 1183 // already a field 1184 fieldState.offset = ad.structsize; // https://issues.dlang.org/show_bug.cgi?id=13613 1185 return; 1186 } 1187 for (size_t i = 0; i < ad.fields.dim; i++) 1188 { 1189 if (ad.fields[i] == this) 1190 { 1191 // already a field 1192 fieldState.offset = ad.structsize; // https://issues.dlang.org/show_bug.cgi?id=13613 1193 return; 1194 } 1195 } 1196 1197 // Check for forward referenced types which will fail the size() call 1198 Type t = type.toBasetype(); 1199 if (storage_class & STC.ref_) 1200 { 1201 // References are the size of a pointer 1202 t = Type.tvoidptr; 1203 } 1204 Type tv = t.baseElemOf(); 1205 if (tv.ty == Tstruct) 1206 { 1207 auto ts = cast(TypeStruct)tv; 1208 assert(ts.sym != ad); // already checked in ad.determineFields() 1209 if (!ts.sym.determineSize(loc)) 1210 { 1211 type = Type.terror; 1212 errors = true; 1213 return; 1214 } 1215 } 1216 1217 // List in ad.fields. Even if the type is error, it's necessary to avoid 1218 // pointless error diagnostic "more initializers than fields" on struct literal. 1219 ad.fields.push(this); 1220 1221 if (t.ty == Terror) 1222 return; 1223 1224 /* If coming after a bit field in progress, 1225 * advance past the field 1226 */ 1227 fieldState.inFlight = false; 1228 1229 const sz = t.size(loc); 1230 assert(sz != SIZE_INVALID && sz < uint.max); 1231 uint memsize = cast(uint)sz; // size of member 1232 uint memalignsize = target.fieldalign(t); // size of member for alignment purposes 1233 offset = AggregateDeclaration.placeField( 1234 &fieldState.offset, 1235 memsize, memalignsize, alignment, 1236 &ad.structsize, &ad.alignsize, 1237 isunion); 1238 1239 //printf("\t%s: memalignsize = %d\n", toChars(), memalignsize); 1240 //printf(" addField '%s' to '%s' at offset %d, size = %d\n", toChars(), ad.toChars(), offset, memsize); 1241 } 1242 1243 override const(char)* kind() const 1244 { 1245 return "variable"; 1246 } 1247 1248 override final inout(AggregateDeclaration) isThis() inout 1249 { 1250 if (!(storage_class & (STC.static_ | STC.extern_ | STC.manifest | STC.templateparameter | STC.gshared | STC.ctfe))) 1251 { 1252 /* The casting is necessary because `s = s.parent` is otherwise rejected 1253 */ 1254 for (auto s = cast(Dsymbol)this; s; s = s.parent) 1255 { 1256 auto ad = (cast(inout)s).isMember(); 1257 if (ad) 1258 return ad; 1259 if (!s.parent || !s.parent.isTemplateMixin()) 1260 break; 1261 } 1262 } 1263 return null; 1264 } 1265 1266 override final bool needThis() 1267 { 1268 //printf("VarDeclaration::needThis(%s, x%x)\n", toChars(), storage_class); 1269 return isField(); 1270 } 1271 1272 override final bool isExport() const 1273 { 1274 return visibility.kind == Visibility.Kind.export_; 1275 } 1276 1277 override final bool isImportedSymbol() const 1278 { 1279 if (visibility.kind == Visibility.Kind.export_ && !_init && (storage_class & STC.static_ || parent.isModule())) 1280 return true; 1281 return false; 1282 } 1283 1284 final bool isCtorinit() const pure nothrow @nogc @safe 1285 { 1286 return setInCtorOnly; 1287 } 1288 1289 /******************************* 1290 * Does symbol go into data segment? 1291 * Includes extern variables. 1292 */ 1293 override final bool isDataseg() 1294 { 1295 version (none) 1296 { 1297 printf("VarDeclaration::isDataseg(%p, '%s')\n", this, toChars()); 1298 printf("%llx, isModule: %p, isTemplateInstance: %p, isNspace: %p\n", 1299 storage_class & (STC.static_ | STC.const_), parent.isModule(), parent.isTemplateInstance(), parent.isNspace()); 1300 printf("parent = '%s'\n", parent.toChars()); 1301 } 1302 1303 if (isdataseg == 0) // the value is not cached 1304 { 1305 isdataseg = 2; // The Variables does not go into the datasegment 1306 1307 if (!canTakeAddressOf()) 1308 { 1309 return false; 1310 } 1311 1312 Dsymbol parent = toParent(); 1313 if (!parent && !(storage_class & STC.static_)) 1314 { 1315 error("forward referenced"); 1316 type = Type.terror; 1317 } 1318 else if (storage_class & (STC.static_ | STC.extern_ | STC.gshared) || 1319 parent.isModule() || parent.isTemplateInstance() || parent.isNspace()) 1320 { 1321 assert(!isParameter() && !isResult()); 1322 isdataseg = 1; // It is in the DataSegment 1323 } 1324 } 1325 1326 return (isdataseg == 1); 1327 } 1328 /************************************ 1329 * Does symbol go into thread local storage? 1330 */ 1331 override final bool isThreadlocal() 1332 { 1333 //printf("VarDeclaration::isThreadlocal(%p, '%s')\n", this, toChars()); 1334 /* Data defaults to being thread-local. It is not thread-local 1335 * if it is immutable, const or shared. 1336 */ 1337 bool i = isDataseg() && !(storage_class & (STC.immutable_ | STC.const_ | STC.shared_ | STC.gshared)); 1338 //printf("\treturn %d\n", i); 1339 return i; 1340 } 1341 1342 /******************************************** 1343 * Can variable be read and written by CTFE? 1344 */ 1345 final bool isCTFE() 1346 { 1347 return (storage_class & STC.ctfe) != 0; // || !isDataseg(); 1348 } 1349 1350 final bool isOverlappedWith(VarDeclaration v) 1351 { 1352 const vsz = v.type.size(); 1353 const tsz = type.size(); 1354 assert(vsz != SIZE_INVALID && tsz != SIZE_INVALID); 1355 1356 // Overlap is checked by comparing bit offsets 1357 auto bitoffset = offset * 8; 1358 auto vbitoffset = v.offset * 8; 1359 1360 // Bitsize of types are overridden by any bit-field widths. 1361 ulong tbitsize = void; 1362 if (auto bf = isBitFieldDeclaration()) 1363 { 1364 bitoffset += bf.bitOffset; 1365 tbitsize = bf.fieldWidth; 1366 } 1367 else 1368 tbitsize = tsz * 8; 1369 1370 ulong vbitsize = void; 1371 if (auto vbf = v.isBitFieldDeclaration()) 1372 { 1373 vbitoffset += vbf.bitOffset; 1374 vbitsize = vbf.fieldWidth; 1375 } 1376 else 1377 vbitsize = vsz * 8; 1378 1379 return bitoffset < vbitoffset + vbitsize && 1380 vbitoffset < bitoffset + tbitsize; 1381 } 1382 1383 override final bool hasPointers() 1384 { 1385 //printf("VarDeclaration::hasPointers() %s, ty = %d\n", toChars(), type.ty); 1386 return (!isDataseg() && type.hasPointers()); 1387 } 1388 1389 /************************************* 1390 * Return true if we can take the address of this variable. 1391 */ 1392 final bool canTakeAddressOf() 1393 { 1394 return !(storage_class & STC.manifest); 1395 } 1396 1397 /****************************************** 1398 * Return true if variable needs to call the destructor. 1399 */ 1400 final bool needsScopeDtor() 1401 { 1402 //printf("VarDeclaration::needsScopeDtor() %s\n", toChars()); 1403 return edtor && !(storage_class & STC.nodtor); 1404 } 1405 1406 /****************************************** 1407 * If a variable has a scope destructor call, return call for it. 1408 * Otherwise, return NULL. 1409 */ 1410 extern (D) final Expression callScopeDtor(Scope* sc) 1411 { 1412 //printf("VarDeclaration::callScopeDtor() %s\n", toChars()); 1413 1414 // Destruction of STC.field's is handled by buildDtor() 1415 if (storage_class & (STC.nodtor | STC.ref_ | STC.out_ | STC.field)) 1416 { 1417 return null; 1418 } 1419 1420 if (iscatchvar) 1421 return null; // destructor is built by `void semantic(Catch c, Scope* sc)`, not here 1422 1423 Expression e = null; 1424 // Destructors for structs and arrays of structs 1425 Type tv = type.baseElemOf(); 1426 if (tv.ty == Tstruct) 1427 { 1428 StructDeclaration sd = (cast(TypeStruct)tv).sym; 1429 if (!sd.dtor || sd.errors) 1430 return null; 1431 1432 const sz = type.size(); 1433 assert(sz != SIZE_INVALID); 1434 if (!sz) 1435 return null; 1436 1437 if (type.toBasetype().ty == Tstruct) 1438 { 1439 // v.__xdtor() 1440 e = new VarExp(loc, this); 1441 1442 /* This is a hack so we can call destructors on const/immutable objects. 1443 * Need to add things like "const ~this()" and "immutable ~this()" to 1444 * fix properly. 1445 */ 1446 e.type = e.type.mutableOf(); 1447 1448 // Enable calling destructors on shared objects. 1449 // The destructor is always a single, non-overloaded function, 1450 // and must serve both shared and non-shared objects. 1451 e.type = e.type.unSharedOf; 1452 1453 e = new DotVarExp(loc, e, sd.dtor, false); 1454 e = new CallExp(loc, e); 1455 } 1456 else 1457 { 1458 // __ArrayDtor(v[0 .. n]) 1459 e = new VarExp(loc, this); 1460 1461 const sdsz = sd.type.size(); 1462 assert(sdsz != SIZE_INVALID && sdsz != 0); 1463 const n = sz / sdsz; 1464 SliceExp se = new SliceExp(loc, e, new IntegerExp(loc, 0, Type.tsize_t), 1465 new IntegerExp(loc, n, Type.tsize_t)); 1466 1467 // Prevent redundant bounds check 1468 se.upperIsInBounds = true; 1469 se.lowerIsLessThanUpper = true; 1470 1471 // This is a hack so we can call destructors on const/immutable objects. 1472 se.type = sd.type.arrayOf(); 1473 1474 e = new CallExp(loc, new IdentifierExp(loc, Id.__ArrayDtor), se); 1475 } 1476 return e; 1477 } 1478 // Destructors for classes 1479 if (storage_class & (STC.auto_ | STC.scope_) && !(storage_class & STC.parameter)) 1480 { 1481 for (ClassDeclaration cd = type.isClassHandle(); cd; cd = cd.baseClass) 1482 { 1483 /* We can do better if there's a way with onstack 1484 * classes to determine if there's no way the monitor 1485 * could be set. 1486 */ 1487 //if (cd.isInterfaceDeclaration()) 1488 // error("interface `%s` cannot be scope", cd.toChars()); 1489 1490 if (onstack) // if any destructors 1491 { 1492 // delete'ing C++ classes crashes (and delete is deprecated anyway) 1493 if (cd.classKind == ClassKind.cpp) 1494 { 1495 // Don't call non-existant dtor 1496 if (!cd.dtor) 1497 break; 1498 1499 e = new VarExp(loc, this); 1500 e.type = e.type.mutableOf().unSharedOf(); // Hack for mutable ctor on immutable instances 1501 e = new DotVarExp(loc, e, cd.dtor, false); 1502 e = new CallExp(loc, e); 1503 break; 1504 } 1505 1506 // delete this; 1507 Expression ec; 1508 ec = new VarExp(loc, this); 1509 e = new DeleteExp(loc, ec, true); 1510 e.type = Type.tvoid; 1511 break; 1512 } 1513 } 1514 } 1515 return e; 1516 } 1517 1518 /******************************************* 1519 * If variable has a constant expression initializer, get it. 1520 * Otherwise, return null. 1521 */ 1522 extern (D) final Expression getConstInitializer(bool needFullType = true) 1523 { 1524 assert(type && _init); 1525 1526 // Ungag errors when not speculative 1527 uint oldgag = global.gag; 1528 if (global.gag) 1529 { 1530 Dsymbol sym = toParent().isAggregateDeclaration(); 1531 if (sym && !sym.isSpeculative()) 1532 global.gag = 0; 1533 } 1534 1535 if (_scope) 1536 { 1537 inuse++; 1538 _init = _init.initializerSemantic(_scope, type, INITinterpret); 1539 _scope = null; 1540 inuse--; 1541 } 1542 1543 Expression e = _init.initializerToExpression(needFullType ? type : null); 1544 global.gag = oldgag; 1545 return e; 1546 } 1547 1548 /******************************************* 1549 * Helper function for the expansion of manifest constant. 1550 */ 1551 extern (D) final Expression expandInitializer(Loc loc) 1552 { 1553 assert((storage_class & STC.manifest) && _init); 1554 1555 auto e = getConstInitializer(); 1556 if (!e) 1557 { 1558 .error(loc, "cannot make expression out of initializer for `%s`", toChars()); 1559 return ErrorExp.get(); 1560 } 1561 1562 e = e.copy(); 1563 e.loc = loc; // for better error message 1564 return e; 1565 } 1566 1567 override final void checkCtorConstInit() 1568 { 1569 version (none) 1570 { 1571 /* doesn't work if more than one static ctor */ 1572 if (ctorinit == 0 && isCtorinit() && !isField()) 1573 error("missing initializer in static constructor for const variable"); 1574 } 1575 } 1576 1577 /************************************ 1578 * Check to see if this variable is actually in an enclosing function 1579 * rather than the current one. 1580 * Update nestedrefs[], closureVars[] and outerVars[]. 1581 * Returns: true if error occurs. 1582 */ 1583 extern (D) final bool checkNestedReference(Scope* sc, Loc loc) 1584 { 1585 //printf("VarDeclaration::checkNestedReference() %s\n", toChars()); 1586 if (sc.intypeof == 1 || (sc.flags & SCOPE.ctfe)) 1587 return false; 1588 if (!parent || parent == sc.parent) 1589 return false; 1590 if (isDataseg() || (storage_class & STC.manifest)) 1591 return false; 1592 1593 // The current function 1594 FuncDeclaration fdthis = sc.parent.isFuncDeclaration(); 1595 if (!fdthis) 1596 return false; // out of function scope 1597 1598 Dsymbol p = toParent2(); 1599 1600 // Function literals from fdthis to p must be delegates 1601 ensureStaticLinkTo(fdthis, p); 1602 1603 // The function that this variable is in 1604 FuncDeclaration fdv = p.isFuncDeclaration(); 1605 if (!fdv || fdv == fdthis) 1606 return false; 1607 1608 // Add fdthis to nestedrefs[] if not already there 1609 if (!nestedrefs.contains(fdthis)) 1610 nestedrefs.push(fdthis); 1611 1612 //printf("\tfdv = %s\n", fdv.toChars()); 1613 //printf("\tfdthis = %s\n", fdthis.toChars()); 1614 if (loc.isValid()) 1615 { 1616 if (fdthis.getLevelAndCheck(loc, sc, fdv, this) == fdthis.LevelError) 1617 return true; 1618 } 1619 1620 // Add this VarDeclaration to fdv.closureVars[] if not already there 1621 if (!sc.intypeof && !(sc.flags & SCOPE.compile) && 1622 // https://issues.dlang.org/show_bug.cgi?id=17605 1623 (fdv.flags & FUNCFLAG.compileTimeOnly || !(fdthis.flags & FUNCFLAG.compileTimeOnly)) 1624 ) 1625 { 1626 if (!fdv.closureVars.contains(this)) 1627 fdv.closureVars.push(this); 1628 } 1629 1630 if (!fdthis.outerVars.contains(this)) 1631 fdthis.outerVars.push(this); 1632 1633 //printf("fdthis is %s\n", fdthis.toChars()); 1634 //printf("var %s in function %s is nested ref\n", toChars(), fdv.toChars()); 1635 // __dollar creates problems because it isn't a real variable 1636 // https://issues.dlang.org/show_bug.cgi?id=3326 1637 if (ident == Id.dollar) 1638 { 1639 .error(loc, "cannnot use `$` inside a function literal"); 1640 return true; 1641 } 1642 if (ident == Id.withSym) // https://issues.dlang.org/show_bug.cgi?id=1759 1643 { 1644 ExpInitializer ez = _init.isExpInitializer(); 1645 assert(ez); 1646 Expression e = ez.exp; 1647 if (e.op == EXP.construct || e.op == EXP.blit) 1648 e = (cast(AssignExp)e).e2; 1649 return lambdaCheckForNestedRef(e, sc); 1650 } 1651 1652 return false; 1653 } 1654 1655 override final Dsymbol toAlias() 1656 { 1657 //printf("VarDeclaration::toAlias('%s', this = %p, aliassym = %p)\n", toChars(), this, aliassym); 1658 if ((!type || !type.deco) && _scope) 1659 dsymbolSemantic(this, _scope); 1660 1661 assert(this != aliassym); 1662 Dsymbol s = aliassym ? aliassym.toAlias() : this; 1663 return s; 1664 } 1665 1666 // Eliminate need for dynamic_cast 1667 override final inout(VarDeclaration) isVarDeclaration() inout 1668 { 1669 return this; 1670 } 1671 1672 override void accept(Visitor v) 1673 { 1674 v.visit(this); 1675 } 1676 } 1677 1678 /******************************************************* 1679 * C11 6.7.2.1-4 bit fields 1680 */ 1681 extern (C++) class BitFieldDeclaration : VarDeclaration 1682 { 1683 Expression width; 1684 1685 uint fieldWidth; 1686 uint bitOffset; 1687 1688 final extern (D) this(const ref Loc loc, Type type, Identifier ident, Expression width) 1689 { 1690 super(loc, type, ident, null); 1691 1692 this.width = width; 1693 this.storage_class |= STC.field; 1694 } 1695 1696 override BitFieldDeclaration syntaxCopy(Dsymbol s) 1697 { 1698 //printf("BitFieldDeclaration::syntaxCopy(%s)\n", toChars()); 1699 assert(!s); 1700 auto bf = new BitFieldDeclaration(loc, type ? type.syntaxCopy() : null, ident, width.syntaxCopy()); 1701 bf.comment = comment; 1702 return bf; 1703 } 1704 1705 override final inout(BitFieldDeclaration) isBitFieldDeclaration() inout 1706 { 1707 return this; 1708 } 1709 1710 override void accept(Visitor v) 1711 { 1712 v.visit(this); 1713 } 1714 1715 override final void setFieldOffset(AggregateDeclaration ad, ref FieldState fieldState, bool isunion) 1716 { 1717 //printf("BitFieldDeclaration::setFieldOffset(ad: %s, field: %s)\n", ad.toChars(), toChars()); 1718 static void print(const ref FieldState fieldState) 1719 { 1720 printf("FieldState.offset = %d bytes\n", fieldState.offset); 1721 printf(" .fieldOffset = %d bytes\n", fieldState.fieldOffset); 1722 printf(" .bitOffset = %d bits\n", fieldState.bitOffset); 1723 printf(" .fieldSize = %d bytes\n", fieldState.fieldSize); 1724 printf(" .inFlight = %d\n\n", fieldState.inFlight); 1725 } 1726 //print(fieldState); 1727 1728 Type t = type.toBasetype(); 1729 const bool anon = isAnonymous(); 1730 1731 // List in ad.fields. Even if the type is error, it's necessary to avoid 1732 // pointless error diagnostic "more initializers than fields" on struct literal. 1733 if (!anon) 1734 ad.fields.push(this); 1735 1736 if (t.ty == Terror) 1737 return; 1738 1739 const sz = t.size(loc); 1740 assert(sz != SIZE_INVALID && sz < uint.max); 1741 uint memsize = cast(uint)sz; // size of member 1742 uint memalignsize = target.fieldalign(t); // size of member for alignment purposes 1743 1744 if (fieldWidth == 0 && !anon) 1745 error(loc, "named bit fields cannot have 0 width"); 1746 if (fieldWidth > memsize * 8) 1747 error(loc, "bit field width %d is larger than type", fieldWidth); 1748 1749 const style = target.c.bitFieldStyle; 1750 1751 void startNewField() 1752 { 1753 uint alignsize; 1754 if (style == TargetC.BitFieldStyle.Gcc_Clang) 1755 { 1756 if (fieldWidth > 32) 1757 alignsize = memalignsize; 1758 else if (fieldWidth > 16) 1759 alignsize = 4; 1760 else if (fieldWidth > 8) 1761 alignsize = 2; 1762 else 1763 alignsize = 1; 1764 } 1765 else 1766 alignsize = memsize; // not memalignsize 1767 1768 uint dummy; 1769 offset = AggregateDeclaration.placeField( 1770 &fieldState.offset, 1771 memsize, alignsize, alignment, 1772 &ad.structsize, 1773 (anon && style == TargetC.BitFieldStyle.Gcc_Clang) ? &dummy : &ad.alignsize, 1774 isunion); 1775 1776 fieldState.inFlight = true; 1777 fieldState.fieldOffset = offset; 1778 fieldState.bitOffset = 0; 1779 fieldState.fieldSize = memsize; 1780 } 1781 1782 if (style == TargetC.BitFieldStyle.Gcc_Clang) 1783 { 1784 if (fieldWidth == 0) 1785 { 1786 if (!isunion) 1787 { 1788 // Use type of zero width field to align to next field 1789 fieldState.offset = (fieldState.offset + memalignsize - 1) & ~(memalignsize - 1); 1790 ad.structsize = fieldState.offset; 1791 } 1792 1793 fieldState.inFlight = false; 1794 return; 1795 } 1796 1797 if (ad.alignsize == 0) 1798 ad.alignsize = 1; 1799 if (!anon && 1800 ad.alignsize < memalignsize) 1801 ad.alignsize = memalignsize; 1802 } 1803 else if (style == TargetC.BitFieldStyle.MS) 1804 { 1805 if (ad.alignsize == 0) 1806 ad.alignsize = 1; 1807 if (fieldWidth == 0) 1808 { 1809 if (fieldState.inFlight && !isunion) 1810 { 1811 // documentation says align to next int 1812 //const alsz = cast(uint)Type.tint32.size(); 1813 const alsz = memsize; // but it really does this 1814 fieldState.offset = (fieldState.offset + alsz - 1) & ~(alsz - 1); 1815 ad.structsize = fieldState.offset; 1816 } 1817 1818 fieldState.inFlight = false; 1819 return; 1820 } 1821 } 1822 else if (style == TargetC.BitFieldStyle.DM) 1823 { 1824 if (anon && fieldWidth && (!fieldState.inFlight || fieldState.bitOffset == 0)) 1825 return; // this probably should be a bug in DMC 1826 if (ad.alignsize == 0) 1827 ad.alignsize = 1; 1828 if (fieldWidth == 0) 1829 { 1830 if (fieldState.inFlight && !isunion) 1831 { 1832 const alsz = memsize; 1833 fieldState.offset = (fieldState.offset + alsz - 1) & ~(alsz - 1); 1834 ad.structsize = fieldState.offset; 1835 } 1836 1837 fieldState.inFlight = false; 1838 return; 1839 } 1840 } 1841 1842 if (!fieldState.inFlight) 1843 { 1844 startNewField(); 1845 } 1846 else if (style == TargetC.BitFieldStyle.Gcc_Clang) 1847 { 1848 if (fieldState.bitOffset + fieldWidth > memsize * 8) 1849 { 1850 //printf("start1 fieldState.bitOffset:%u fieldWidth:%u memsize:%u\n", fieldState.bitOffset, fieldWidth, memsize); 1851 startNewField(); 1852 } 1853 else 1854 { 1855 // if alignment boundary is crossed 1856 uint start = fieldState.fieldOffset * 8 + fieldState.bitOffset; 1857 uint end = start + fieldWidth; 1858 //printf("%s start: %d end: %d memalignsize: %d\n", ad.toChars(), start, end, memalignsize); 1859 if (start / (memalignsize * 8) != (end - 1) / (memalignsize * 8)) 1860 { 1861 //printf("alignment is crossed\n"); 1862 startNewField(); 1863 } 1864 } 1865 } 1866 else if (style == TargetC.BitFieldStyle.DM || 1867 style == TargetC.BitFieldStyle.MS) 1868 { 1869 if (memsize != fieldState.fieldSize || 1870 fieldState.bitOffset + fieldWidth > fieldState.fieldSize * 8) 1871 { 1872 startNewField(); 1873 } 1874 } 1875 else 1876 assert(0); 1877 1878 offset = fieldState.fieldOffset; 1879 bitOffset = fieldState.bitOffset; 1880 1881 const pastField = bitOffset + fieldWidth; 1882 if (style == TargetC.BitFieldStyle.Gcc_Clang) 1883 { 1884 auto size = (pastField + 7) / 8; 1885 fieldState.fieldSize = size; 1886 //printf(" offset: %d, size: %d\n", offset, size); 1887 ad.structsize = offset + size; 1888 } 1889 else 1890 fieldState.fieldSize = memsize; 1891 //printf("at end: ad.structsize = %d\n", cast(int)ad.structsize); 1892 //print(fieldState); 1893 1894 if (!isunion) 1895 { 1896 fieldState.offset = offset + fieldState.fieldSize; 1897 fieldState.bitOffset = pastField; 1898 } 1899 1900 //printf("\t%s: memalignsize = %d\n", toChars(), memalignsize); 1901 //printf(" addField '%s' to '%s' at offset %d, size = %d\n", toChars(), ad.toChars(), offset, memsize); 1902 } 1903 } 1904 1905 /*********************************************************** 1906 * This is a shell around a back end symbol 1907 */ 1908 extern (C++) final class SymbolDeclaration : Declaration 1909 { 1910 AggregateDeclaration dsym; 1911 1912 extern (D) this(const ref Loc loc, AggregateDeclaration dsym) 1913 { 1914 super(loc, dsym.ident); 1915 this.dsym = dsym; 1916 storage_class |= STC.const_; 1917 } 1918 1919 // Eliminate need for dynamic_cast 1920 override inout(SymbolDeclaration) isSymbolDeclaration() inout 1921 { 1922 return this; 1923 } 1924 1925 override void accept(Visitor v) 1926 { 1927 v.visit(this); 1928 } 1929 } 1930 1931 /*********************************************************** 1932 */ 1933 extern (C++) class TypeInfoDeclaration : VarDeclaration 1934 { 1935 Type tinfo; 1936 1937 final extern (D) this(Type tinfo) 1938 { 1939 super(Loc.initial, Type.dtypeinfo.type, tinfo.getTypeInfoIdent(), null); 1940 this.tinfo = tinfo; 1941 storage_class = STC.static_ | STC.gshared; 1942 visibility = Visibility(Visibility.Kind.public_); 1943 _linkage = LINK.c; 1944 alignment.set(target.ptrsize); 1945 } 1946 1947 static TypeInfoDeclaration create(Type tinfo) 1948 { 1949 return new TypeInfoDeclaration(tinfo); 1950 } 1951 1952 override final TypeInfoDeclaration syntaxCopy(Dsymbol s) 1953 { 1954 assert(0); // should never be produced by syntax 1955 } 1956 1957 override final const(char)* toChars() const 1958 { 1959 //printf("TypeInfoDeclaration::toChars() tinfo = %s\n", tinfo.toChars()); 1960 OutBuffer buf; 1961 buf.writestring("typeid("); 1962 buf.writestring(tinfo.toChars()); 1963 buf.writeByte(')'); 1964 return buf.extractChars(); 1965 } 1966 1967 override final inout(TypeInfoDeclaration) isTypeInfoDeclaration() inout @nogc nothrow pure @safe 1968 { 1969 return this; 1970 } 1971 1972 override void accept(Visitor v) 1973 { 1974 v.visit(this); 1975 } 1976 } 1977 1978 /*********************************************************** 1979 */ 1980 extern (C++) final class TypeInfoStructDeclaration : TypeInfoDeclaration 1981 { 1982 extern (D) this(Type tinfo) 1983 { 1984 super(tinfo); 1985 if (!Type.typeinfostruct) 1986 { 1987 ObjectNotFound(Id.TypeInfo_Struct); 1988 } 1989 type = Type.typeinfostruct.type; 1990 } 1991 1992 static TypeInfoStructDeclaration create(Type tinfo) 1993 { 1994 return new TypeInfoStructDeclaration(tinfo); 1995 } 1996 1997 override void accept(Visitor v) 1998 { 1999 v.visit(this); 2000 } 2001 } 2002 2003 /*********************************************************** 2004 */ 2005 extern (C++) final class TypeInfoClassDeclaration : TypeInfoDeclaration 2006 { 2007 extern (D) this(Type tinfo) 2008 { 2009 super(tinfo); 2010 if (!Type.typeinfoclass) 2011 { 2012 ObjectNotFound(Id.TypeInfo_Class); 2013 } 2014 type = Type.typeinfoclass.type; 2015 } 2016 2017 static TypeInfoClassDeclaration create(Type tinfo) 2018 { 2019 return new TypeInfoClassDeclaration(tinfo); 2020 } 2021 2022 override void accept(Visitor v) 2023 { 2024 v.visit(this); 2025 } 2026 } 2027 2028 /*********************************************************** 2029 */ 2030 extern (C++) final class TypeInfoInterfaceDeclaration : TypeInfoDeclaration 2031 { 2032 extern (D) this(Type tinfo) 2033 { 2034 super(tinfo); 2035 if (!Type.typeinfointerface) 2036 { 2037 ObjectNotFound(Id.TypeInfo_Interface); 2038 } 2039 type = Type.typeinfointerface.type; 2040 } 2041 2042 static TypeInfoInterfaceDeclaration create(Type tinfo) 2043 { 2044 return new TypeInfoInterfaceDeclaration(tinfo); 2045 } 2046 2047 override void accept(Visitor v) 2048 { 2049 v.visit(this); 2050 } 2051 } 2052 2053 /*********************************************************** 2054 */ 2055 extern (C++) final class TypeInfoPointerDeclaration : TypeInfoDeclaration 2056 { 2057 extern (D) this(Type tinfo) 2058 { 2059 super(tinfo); 2060 if (!Type.typeinfopointer) 2061 { 2062 ObjectNotFound(Id.TypeInfo_Pointer); 2063 } 2064 type = Type.typeinfopointer.type; 2065 } 2066 2067 static TypeInfoPointerDeclaration create(Type tinfo) 2068 { 2069 return new TypeInfoPointerDeclaration(tinfo); 2070 } 2071 2072 override void accept(Visitor v) 2073 { 2074 v.visit(this); 2075 } 2076 } 2077 2078 /*********************************************************** 2079 */ 2080 extern (C++) final class TypeInfoArrayDeclaration : TypeInfoDeclaration 2081 { 2082 extern (D) this(Type tinfo) 2083 { 2084 super(tinfo); 2085 if (!Type.typeinfoarray) 2086 { 2087 ObjectNotFound(Id.TypeInfo_Array); 2088 } 2089 type = Type.typeinfoarray.type; 2090 } 2091 2092 static TypeInfoArrayDeclaration create(Type tinfo) 2093 { 2094 return new TypeInfoArrayDeclaration(tinfo); 2095 } 2096 2097 override void accept(Visitor v) 2098 { 2099 v.visit(this); 2100 } 2101 } 2102 2103 /*********************************************************** 2104 */ 2105 extern (C++) final class TypeInfoStaticArrayDeclaration : TypeInfoDeclaration 2106 { 2107 extern (D) this(Type tinfo) 2108 { 2109 super(tinfo); 2110 if (!Type.typeinfostaticarray) 2111 { 2112 ObjectNotFound(Id.TypeInfo_StaticArray); 2113 } 2114 type = Type.typeinfostaticarray.type; 2115 } 2116 2117 static TypeInfoStaticArrayDeclaration create(Type tinfo) 2118 { 2119 return new TypeInfoStaticArrayDeclaration(tinfo); 2120 } 2121 2122 override void accept(Visitor v) 2123 { 2124 v.visit(this); 2125 } 2126 } 2127 2128 /*********************************************************** 2129 */ 2130 extern (C++) final class TypeInfoAssociativeArrayDeclaration : TypeInfoDeclaration 2131 { 2132 extern (D) this(Type tinfo) 2133 { 2134 super(tinfo); 2135 if (!Type.typeinfoassociativearray) 2136 { 2137 ObjectNotFound(Id.TypeInfo_AssociativeArray); 2138 } 2139 type = Type.typeinfoassociativearray.type; 2140 } 2141 2142 static TypeInfoAssociativeArrayDeclaration create(Type tinfo) 2143 { 2144 return new TypeInfoAssociativeArrayDeclaration(tinfo); 2145 } 2146 2147 override void accept(Visitor v) 2148 { 2149 v.visit(this); 2150 } 2151 } 2152 2153 /*********************************************************** 2154 */ 2155 extern (C++) final class TypeInfoEnumDeclaration : TypeInfoDeclaration 2156 { 2157 extern (D) this(Type tinfo) 2158 { 2159 super(tinfo); 2160 if (!Type.typeinfoenum) 2161 { 2162 ObjectNotFound(Id.TypeInfo_Enum); 2163 } 2164 type = Type.typeinfoenum.type; 2165 } 2166 2167 static TypeInfoEnumDeclaration create(Type tinfo) 2168 { 2169 return new TypeInfoEnumDeclaration(tinfo); 2170 } 2171 2172 override void accept(Visitor v) 2173 { 2174 v.visit(this); 2175 } 2176 } 2177 2178 /*********************************************************** 2179 */ 2180 extern (C++) final class TypeInfoFunctionDeclaration : TypeInfoDeclaration 2181 { 2182 extern (D) this(Type tinfo) 2183 { 2184 super(tinfo); 2185 if (!Type.typeinfofunction) 2186 { 2187 ObjectNotFound(Id.TypeInfo_Function); 2188 } 2189 type = Type.typeinfofunction.type; 2190 } 2191 2192 static TypeInfoFunctionDeclaration create(Type tinfo) 2193 { 2194 return new TypeInfoFunctionDeclaration(tinfo); 2195 } 2196 2197 override void accept(Visitor v) 2198 { 2199 v.visit(this); 2200 } 2201 } 2202 2203 /*********************************************************** 2204 */ 2205 extern (C++) final class TypeInfoDelegateDeclaration : TypeInfoDeclaration 2206 { 2207 extern (D) this(Type tinfo) 2208 { 2209 super(tinfo); 2210 if (!Type.typeinfodelegate) 2211 { 2212 ObjectNotFound(Id.TypeInfo_Delegate); 2213 } 2214 type = Type.typeinfodelegate.type; 2215 } 2216 2217 static TypeInfoDelegateDeclaration create(Type tinfo) 2218 { 2219 return new TypeInfoDelegateDeclaration(tinfo); 2220 } 2221 2222 override void accept(Visitor v) 2223 { 2224 v.visit(this); 2225 } 2226 } 2227 2228 /*********************************************************** 2229 */ 2230 extern (C++) final class TypeInfoTupleDeclaration : TypeInfoDeclaration 2231 { 2232 extern (D) this(Type tinfo) 2233 { 2234 super(tinfo); 2235 if (!Type.typeinfotypelist) 2236 { 2237 ObjectNotFound(Id.TypeInfo_Tuple); 2238 } 2239 type = Type.typeinfotypelist.type; 2240 } 2241 2242 static TypeInfoTupleDeclaration create(Type tinfo) 2243 { 2244 return new TypeInfoTupleDeclaration(tinfo); 2245 } 2246 2247 override void accept(Visitor v) 2248 { 2249 v.visit(this); 2250 } 2251 } 2252 2253 /*********************************************************** 2254 */ 2255 extern (C++) final class TypeInfoConstDeclaration : TypeInfoDeclaration 2256 { 2257 extern (D) this(Type tinfo) 2258 { 2259 super(tinfo); 2260 if (!Type.typeinfoconst) 2261 { 2262 ObjectNotFound(Id.TypeInfo_Const); 2263 } 2264 type = Type.typeinfoconst.type; 2265 } 2266 2267 static TypeInfoConstDeclaration create(Type tinfo) 2268 { 2269 return new TypeInfoConstDeclaration(tinfo); 2270 } 2271 2272 override void accept(Visitor v) 2273 { 2274 v.visit(this); 2275 } 2276 } 2277 2278 /*********************************************************** 2279 */ 2280 extern (C++) final class TypeInfoInvariantDeclaration : TypeInfoDeclaration 2281 { 2282 extern (D) this(Type tinfo) 2283 { 2284 super(tinfo); 2285 if (!Type.typeinfoinvariant) 2286 { 2287 ObjectNotFound(Id.TypeInfo_Invariant); 2288 } 2289 type = Type.typeinfoinvariant.type; 2290 } 2291 2292 static TypeInfoInvariantDeclaration create(Type tinfo) 2293 { 2294 return new TypeInfoInvariantDeclaration(tinfo); 2295 } 2296 2297 override void accept(Visitor v) 2298 { 2299 v.visit(this); 2300 } 2301 } 2302 2303 /*********************************************************** 2304 */ 2305 extern (C++) final class TypeInfoSharedDeclaration : TypeInfoDeclaration 2306 { 2307 extern (D) this(Type tinfo) 2308 { 2309 super(tinfo); 2310 if (!Type.typeinfoshared) 2311 { 2312 ObjectNotFound(Id.TypeInfo_Shared); 2313 } 2314 type = Type.typeinfoshared.type; 2315 } 2316 2317 static TypeInfoSharedDeclaration create(Type tinfo) 2318 { 2319 return new TypeInfoSharedDeclaration(tinfo); 2320 } 2321 2322 override void accept(Visitor v) 2323 { 2324 v.visit(this); 2325 } 2326 } 2327 2328 /*********************************************************** 2329 */ 2330 extern (C++) final class TypeInfoWildDeclaration : TypeInfoDeclaration 2331 { 2332 extern (D) this(Type tinfo) 2333 { 2334 super(tinfo); 2335 if (!Type.typeinfowild) 2336 { 2337 ObjectNotFound(Id.TypeInfo_Wild); 2338 } 2339 type = Type.typeinfowild.type; 2340 } 2341 2342 static TypeInfoWildDeclaration create(Type tinfo) 2343 { 2344 return new TypeInfoWildDeclaration(tinfo); 2345 } 2346 2347 override void accept(Visitor v) 2348 { 2349 v.visit(this); 2350 } 2351 } 2352 2353 /*********************************************************** 2354 */ 2355 extern (C++) final class TypeInfoVectorDeclaration : TypeInfoDeclaration 2356 { 2357 extern (D) this(Type tinfo) 2358 { 2359 super(tinfo); 2360 if (!Type.typeinfovector) 2361 { 2362 ObjectNotFound(Id.TypeInfo_Vector); 2363 } 2364 type = Type.typeinfovector.type; 2365 } 2366 2367 static TypeInfoVectorDeclaration create(Type tinfo) 2368 { 2369 return new TypeInfoVectorDeclaration(tinfo); 2370 } 2371 2372 override void accept(Visitor v) 2373 { 2374 v.visit(this); 2375 } 2376 } 2377 2378 /*********************************************************** 2379 * For the "this" parameter to member functions 2380 */ 2381 extern (C++) final class ThisDeclaration : VarDeclaration 2382 { 2383 extern (D) this(const ref Loc loc, Type t) 2384 { 2385 super(loc, t, Id.This, null); 2386 storage_class |= STC.nodtor; 2387 } 2388 2389 override ThisDeclaration syntaxCopy(Dsymbol s) 2390 { 2391 assert(0); // should never be produced by syntax 2392 } 2393 2394 override inout(ThisDeclaration) isThisDeclaration() inout 2395 { 2396 return this; 2397 } 2398 2399 override void accept(Visitor v) 2400 { 2401 v.visit(this); 2402 } 2403 } 2404