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