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