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