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