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