1 /** 2 * Compiler implementation of the 3 * $(LINK2 http://www.dlang.org, D programming language). 4 * 5 * Copyright: Copyright (c) 1999-2016 by Digital Mars, 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: $(DMDSRC _declaration.d) 9 */ 10 11 module ddmd.declaration; 12 13 import core.stdc.stdio; 14 import ddmd.aggregate; 15 import ddmd.arraytypes; 16 import ddmd.dcast; 17 import ddmd.dclass; 18 import ddmd.delegatize; 19 import ddmd.dscope; 20 import ddmd.dstruct; 21 import ddmd.dsymbol; 22 import ddmd.dtemplate; 23 import ddmd.errors; 24 import ddmd.expression; 25 import ddmd.func; 26 import ddmd.globals; 27 import ddmd.hdrgen; 28 import ddmd.id; 29 import ddmd.identifier; 30 import ddmd.init; 31 import ddmd.intrange; 32 import ddmd.mtype; 33 import ddmd.root.outbuffer; 34 import ddmd.root.rootobject; 35 import ddmd.sideeffect; 36 import ddmd.target; 37 import ddmd.tokens; 38 import ddmd.visitor; 39 40 /************************************ 41 * Check to see the aggregate type is nested and its context pointer is 42 * accessible from the current scope. 43 * Returns true if error occurs. 44 */ 45 extern (C++) bool checkFrameAccess(Loc loc, Scope* sc, AggregateDeclaration ad, size_t iStart = 0) 46 { 47 Dsymbol sparent = ad.toParent2(); 48 Dsymbol s = sc.func; 49 if (ad.isNested() && s) 50 { 51 //printf("ad = %p %s [%s], parent:%p\n", ad, ad.toChars(), ad.loc.toChars(), ad.parent); 52 //printf("sparent = %p %s [%s], parent: %s\n", sparent, sparent.toChars(), sparent.loc.toChars(), sparent.parent,toChars()); 53 if (checkNestedRef(s, sparent)) 54 { 55 error(loc, "cannot access frame pointer of %s", ad.toPrettyChars()); 56 return true; 57 } 58 } 59 60 bool result = false; 61 for (size_t i = iStart; i < ad.fields.dim; i++) 62 { 63 VarDeclaration vd = ad.fields[i]; 64 Type tb = vd.type.baseElemOf(); 65 if (tb.ty == Tstruct) 66 { 67 result |= checkFrameAccess(loc, sc, (cast(TypeStruct)tb).sym); 68 } 69 } 70 return result; 71 } 72 73 /****************************************** 74 */ 75 extern (C++) void ObjectNotFound(Identifier id) 76 { 77 Type.error(Loc(), "%s not found. object.d may be incorrectly installed or corrupt.", id.toChars()); 78 fatal(); 79 } 80 81 enum STCundefined = 0L; 82 enum STCstatic = (1L << 0); 83 enum STCextern = (1L << 1); 84 enum STCconst = (1L << 2); 85 enum STCfinal = (1L << 3); 86 enum STCabstract = (1L << 4); 87 enum STCparameter = (1L << 5); 88 enum STCfield = (1L << 6); 89 enum STCoverride = (1L << 7); 90 enum STCauto = (1L << 8); 91 enum STCsynchronized = (1L << 9); 92 enum STCdeprecated = (1L << 10); 93 enum STCin = (1L << 11); // in parameter 94 enum STCout = (1L << 12); // out parameter 95 enum STClazy = (1L << 13); // lazy parameter 96 enum STCforeach = (1L << 14); // variable for foreach loop 97 // (1L << 15) 98 enum STCvariadic = (1L << 16); // variadic function argument 99 enum STCctorinit = (1L << 17); // can only be set inside constructor 100 enum STCtemplateparameter = (1L << 18); // template parameter 101 enum STCscope = (1L << 19); 102 enum STCimmutable = (1L << 20); 103 enum STCref = (1L << 21); 104 enum STCinit = (1L << 22); // has explicit initializer 105 enum STCmanifest = (1L << 23); // manifest constant 106 enum STCnodtor = (1L << 24); // don't run destructor 107 enum STCnothrow = (1L << 25); // never throws exceptions 108 enum STCpure = (1L << 26); // pure function 109 enum STCtls = (1L << 27); // thread local 110 enum STCalias = (1L << 28); // alias parameter 111 enum STCshared = (1L << 29); // accessible from multiple threads 112 enum STCgshared = (1L << 30); // accessible from multiple threads, but not typed as "shared" 113 enum STCwild = (1L << 31); // for "wild" type constructor 114 enum STCproperty = (1L << 32); 115 enum STCsafe = (1L << 33); 116 enum STCtrusted = (1L << 34); 117 enum STCsystem = (1L << 35); 118 enum STCctfe = (1L << 36); // can be used in CTFE, even if it is static 119 enum STCdisable = (1L << 37); // for functions that are not callable 120 enum STCresult = (1L << 38); // for result variables passed to out contracts 121 enum STCnodefaultctor = (1L << 39); // must be set inside constructor 122 enum STCtemp = (1L << 40); // temporary variable 123 enum STCrvalue = (1L << 41); // force rvalue for variables 124 enum STCnogc = (1L << 42); // @nogc 125 enum STCvolatile = (1L << 43); // destined for volatile in the back end 126 enum STCreturn = (1L << 44); // 'return ref' for function parameters 127 enum STCautoref = (1L << 45); // Mark for the already deduced 'auto ref' parameter 128 enum STCinference = (1L << 46); // do attribute inference 129 enum STCexptemp = (1L << 47); // temporary variable that has lifetime restricted to an expression 130 131 enum STC_TYPECTOR = (STCconst | STCimmutable | STCshared | STCwild); 132 enum STC_FUNCATTR = (STCref | STCnothrow | STCnogc | STCpure | STCproperty | STCsafe | STCtrusted | STCsystem); 133 134 extern (C++) __gshared const(StorageClass) STCStorageClass = 135 (STCauto | STCscope | STCstatic | STCextern | STCconst | STCfinal | STCabstract | STCsynchronized | STCdeprecated | STCoverride | STClazy | STCalias | STCout | STCin | STCmanifest | STCimmutable | STCshared | STCwild | STCnothrow | STCnogc | STCpure | STCref | STCtls | STCgshared | STCproperty | STCsafe | STCtrusted | STCsystem | STCdisable); 136 137 struct Match 138 { 139 int count; // number of matches found 140 MATCH last; // match level of lastf 141 FuncDeclaration lastf; // last matching function we found 142 FuncDeclaration nextf; // current matching function 143 FuncDeclaration anyf; // pick a func, any func, to use for error recovery 144 } 145 146 /*********************************************************** 147 */ 148 extern (C++) abstract class Declaration : Dsymbol 149 { 150 Type type; 151 Type originalType; // before semantic analysis 152 StorageClass storage_class; 153 Prot protection; 154 LINK linkage; 155 int inuse; // used to detect cycles 156 157 // overridden symbol with pragma(mangle, "...") 158 const(char)* mangleOverride; 159 160 final extern (D) this(Identifier id) 161 { 162 super(id); 163 storage_class = STCundefined; 164 protection = Prot(PROTundefined); 165 linkage = LINKdefault; 166 } 167 168 override void semantic(Scope* sc) 169 { 170 } 171 172 override const(char)* kind() const 173 { 174 return "declaration"; 175 } 176 177 override final d_uns64 size(Loc loc) 178 { 179 assert(type); 180 return type.size(); 181 } 182 183 /************************************* 184 * Check to see if declaration can be modified in this context (sc). 185 * Issue error if not. 186 */ 187 final int checkModify(Loc loc, Scope* sc, Type t, Expression e1, int flag) 188 { 189 VarDeclaration v = isVarDeclaration(); 190 if (v && v.canassign) 191 return 2; 192 193 if (isParameter() || isResult()) 194 { 195 for (Scope* scx = sc; scx; scx = scx.enclosing) 196 { 197 if (scx.func == parent && (scx.flags & SCOPEcontract)) 198 { 199 const(char)* s = isParameter() && parent.ident != Id.ensure ? "parameter" : "result"; 200 if (!flag) 201 error(loc, "cannot modify %s '%s' in contract", s, toChars()); 202 return 2; // do not report type related errors 203 } 204 } 205 } 206 207 if (v && (isCtorinit() || isField())) 208 { 209 // It's only modifiable if inside the right constructor 210 if ((storage_class & (STCforeach | STCref)) == (STCforeach | STCref)) 211 return 2; 212 return modifyFieldVar(loc, sc, v, e1) ? 2 : 1; 213 } 214 return 1; 215 } 216 217 override final Dsymbol search(Loc loc, Identifier ident, int flags = SearchLocalsOnly) 218 { 219 Dsymbol s = Dsymbol.search(loc, ident, flags); 220 if (!s && type) 221 { 222 s = type.toDsymbol(_scope); 223 if (s) 224 s = s.search(loc, ident, flags); 225 } 226 return s; 227 } 228 229 final bool isStatic() 230 { 231 return (storage_class & STCstatic) != 0; 232 } 233 234 bool isDelete() 235 { 236 return false; 237 } 238 239 bool isDataseg() 240 { 241 return false; 242 } 243 244 bool isThreadlocal() 245 { 246 return false; 247 } 248 249 bool isCodeseg() 250 { 251 return false; 252 } 253 254 final bool isCtorinit() 255 { 256 return (storage_class & STCctorinit) != 0; 257 } 258 259 final bool isFinal() 260 { 261 return (storage_class & STCfinal) != 0; 262 } 263 264 final bool isAbstract() 265 { 266 return (storage_class & STCabstract) != 0; 267 } 268 269 final bool isConst() 270 { 271 return (storage_class & STCconst) != 0; 272 } 273 274 final bool isImmutable() 275 { 276 return (storage_class & STCimmutable) != 0; 277 } 278 279 final bool isWild() 280 { 281 return (storage_class & STCwild) != 0; 282 } 283 284 final bool isAuto() 285 { 286 return (storage_class & STCauto) != 0; 287 } 288 289 final bool isScope() 290 { 291 return (storage_class & STCscope) != 0; 292 } 293 294 final bool isSynchronized() 295 { 296 return (storage_class & STCsynchronized) != 0; 297 } 298 299 final bool isParameter() 300 { 301 return (storage_class & STCparameter) != 0; 302 } 303 304 override final bool isDeprecated() 305 { 306 return (storage_class & STCdeprecated) != 0; 307 } 308 309 final bool isOverride() 310 { 311 return (storage_class & STCoverride) != 0; 312 } 313 314 final bool isResult() 315 { 316 return (storage_class & STCresult) != 0; 317 } 318 319 final bool isField() 320 { 321 return (storage_class & STCfield) != 0; 322 } 323 324 final bool isIn() 325 { 326 return (storage_class & STCin) != 0; 327 } 328 329 final bool isOut() 330 { 331 return (storage_class & STCout) != 0; 332 } 333 334 final bool isRef() 335 { 336 return (storage_class & STCref) != 0; 337 } 338 339 override final Prot prot() 340 { 341 return protection; 342 } 343 344 override final inout(Declaration) isDeclaration() inout 345 { 346 return this; 347 } 348 349 override void accept(Visitor v) 350 { 351 v.visit(this); 352 } 353 } 354 355 /*********************************************************** 356 */ 357 extern (C++) final class TupleDeclaration : Declaration 358 { 359 Objects* objects; 360 bool isexp; // true: expression tuple 361 TypeTuple tupletype; // !=null if this is a type tuple 362 363 extern (D) this(Loc loc, Identifier id, Objects* objects) 364 { 365 super(id); 366 this.loc = loc; 367 this.objects = objects; 368 } 369 370 override Dsymbol syntaxCopy(Dsymbol s) 371 { 372 assert(0); 373 } 374 375 override const(char)* kind() const 376 { 377 return "tuple"; 378 } 379 380 override Type getType() 381 { 382 /* If this tuple represents a type, return that type 383 */ 384 385 //printf("TupleDeclaration::getType() %s\n", toChars()); 386 if (isexp) 387 return null; 388 if (!tupletype) 389 { 390 /* It's only a type tuple if all the Object's are types 391 */ 392 for (size_t i = 0; i < objects.dim; i++) 393 { 394 RootObject o = (*objects)[i]; 395 if (o.dyncast() != DYNCAST_TYPE) 396 { 397 //printf("\tnot[%d], %p, %d\n", i, o, o->dyncast()); 398 return null; 399 } 400 } 401 402 /* We know it's a type tuple, so build the TypeTuple 403 */ 404 Types* types = cast(Types*)objects; 405 auto args = new Parameters(); 406 args.setDim(objects.dim); 407 OutBuffer buf; 408 int hasdeco = 1; 409 for (size_t i = 0; i < types.dim; i++) 410 { 411 Type t = (*types)[i]; 412 //printf("type = %s\n", t->toChars()); 413 version (none) 414 { 415 buf.printf("_%s_%d", ident.toChars(), i); 416 const len = buf.offset; 417 const name = cast(const(char)*)buf.extractData(); 418 auto id = Identifier.idPool(name, len); 419 auto arg = new Parameter(STCin, t, id, null); 420 } 421 else 422 { 423 auto arg = new Parameter(0, t, null, null); 424 } 425 (*args)[i] = arg; 426 if (!t.deco) 427 hasdeco = 0; 428 } 429 430 tupletype = new TypeTuple(args); 431 if (hasdeco) 432 return tupletype.semantic(Loc(), null); 433 } 434 return tupletype; 435 } 436 437 override Dsymbol toAlias2() 438 { 439 //printf("TupleDeclaration::toAlias2() '%s' objects = %s\n", toChars(), objects->toChars()); 440 for (size_t i = 0; i < objects.dim; i++) 441 { 442 RootObject o = (*objects)[i]; 443 if (Dsymbol s = isDsymbol(o)) 444 { 445 s = s.toAlias2(); 446 (*objects)[i] = s; 447 } 448 } 449 return this; 450 } 451 452 override bool needThis() 453 { 454 //printf("TupleDeclaration::needThis(%s)\n", toChars()); 455 for (size_t i = 0; i < objects.dim; i++) 456 { 457 RootObject o = (*objects)[i]; 458 if (o.dyncast() == DYNCAST_EXPRESSION) 459 { 460 Expression e = cast(Expression)o; 461 if (e.op == TOKdsymbol) 462 { 463 DsymbolExp ve = cast(DsymbolExp)e; 464 Declaration d = ve.s.isDeclaration(); 465 if (d && d.needThis()) 466 { 467 return true; 468 } 469 } 470 } 471 } 472 return false; 473 } 474 475 override inout(TupleDeclaration) isTupleDeclaration() inout 476 { 477 return this; 478 } 479 480 override void accept(Visitor v) 481 { 482 v.visit(this); 483 } 484 } 485 486 /*********************************************************** 487 */ 488 extern (C++) final class AliasDeclaration : Declaration 489 { 490 Dsymbol aliassym; 491 Dsymbol overnext; // next in overload list 492 Dsymbol _import; // !=null if unresolved internal alias for selective import 493 494 extern (D) this(Loc loc, Identifier id, Type type) 495 { 496 super(id); 497 //printf("AliasDeclaration(id = '%s', type = %p)\n", id->toChars(), type); 498 //printf("type = '%s'\n", type->toChars()); 499 this.loc = loc; 500 this.type = type; 501 assert(type); 502 } 503 504 extern (D) this(Loc loc, Identifier id, Dsymbol s) 505 { 506 super(id); 507 //printf("AliasDeclaration(id = '%s', s = %p)\n", id->toChars(), s); 508 assert(s != this); 509 this.loc = loc; 510 this.aliassym = s; 511 assert(s); 512 } 513 514 override Dsymbol syntaxCopy(Dsymbol s) 515 { 516 //printf("AliasDeclaration::syntaxCopy()\n"); 517 assert(!s); 518 AliasDeclaration sa = type ? new AliasDeclaration(loc, ident, type.syntaxCopy()) : new AliasDeclaration(loc, ident, aliassym.syntaxCopy(null)); 519 sa.storage_class = storage_class; 520 return sa; 521 } 522 523 override void semantic(Scope* sc) 524 { 525 if (semanticRun >= PASSsemanticdone) 526 return; 527 assert(semanticRun <= PASSsemantic); 528 529 storage_class |= sc.stc & STCdeprecated; 530 protection = sc.protection; 531 userAttribDecl = sc.userAttribDecl; 532 533 if (!sc.func && inNonRoot()) 534 return; 535 536 aliasSemantic(sc); 537 } 538 539 final void aliasSemantic(Scope* sc) 540 { 541 //printf("AliasDeclaration::semantic() %s\n", toChars()); 542 if (aliassym) 543 { 544 auto fd = aliassym.isFuncLiteralDeclaration(); 545 auto td = aliassym.isTemplateDeclaration(); 546 if (fd || td && td.literal) 547 { 548 if (fd && fd.semanticRun >= PASSsemanticdone) 549 return; 550 551 Expression e = new FuncExp(loc, aliassym); 552 e = e.semantic(sc); 553 if (e.op == TOKfunction) 554 { 555 FuncExp fe = cast(FuncExp)e; 556 aliassym = fe.td ? cast(Dsymbol)fe.td : fe.fd; 557 } 558 else 559 { 560 aliassym = null; 561 type = Type.terror; 562 } 563 return; 564 } 565 566 if (aliassym.isTemplateInstance()) 567 aliassym.semantic(sc); 568 return; 569 } 570 inuse = 1; 571 572 // Given: 573 // alias foo.bar.abc def; 574 // it is not knowable from the syntax whether this is an alias 575 // for a type or an alias for a symbol. It is up to the semantic() 576 // pass to distinguish. 577 // If it is a type, then type is set and getType() will return that 578 // type. If it is a symbol, then aliassym is set and type is NULL - 579 // toAlias() will return aliasssym. 580 581 uint errors = global.errors; 582 Type oldtype = type; 583 584 // Ungag errors when not instantiated DeclDefs scope alias 585 auto ungag = Ungag(global.gag); 586 //printf("%s parent = %s, gag = %d, instantiated = %d\n", toChars(), parent, global.gag, isInstantiated()); 587 if (parent && global.gag && !isInstantiated() && !toParent2().isFuncDeclaration()) 588 { 589 //printf("%s type = %s\n", toPrettyChars(), type->toChars()); 590 global.gag = 0; 591 } 592 593 /* This section is needed because Type.resolve() will: 594 * const x = 3; 595 * alias y = x; 596 * try to convert identifier x to 3. 597 */ 598 auto s = type.toDsymbol(sc); 599 if (errors != global.errors) 600 { 601 s = null; 602 type = Type.terror; 603 } 604 if (s && s == this) 605 { 606 error("cannot resolve"); 607 s = null; 608 type = Type.terror; 609 } 610 if (!s || !s.isEnumMember()) 611 { 612 Type t; 613 Expression e; 614 Scope* sc2 = sc; 615 if (storage_class & (STCref | STCnothrow | STCnogc | STCpure | STCdisable)) 616 { 617 // For 'ref' to be attached to function types, and picked 618 // up by Type.resolve(), it has to go into sc. 619 sc2 = sc.push(); 620 sc2.stc |= storage_class & (STCref | STCnothrow | STCnogc | STCpure | STCshared | STCdisable); 621 } 622 type = type.addSTC(storage_class); 623 type.resolve(loc, sc2, &e, &t, &s); 624 if (sc2 != sc) 625 sc2.pop(); 626 627 if (e) // Try to convert Expression to Dsymbol 628 { 629 s = getDsymbol(e); 630 if (!s) 631 { 632 if (e.op != TOKerror) 633 error("cannot alias an expression %s", e.toChars()); 634 t = Type.terror; 635 } 636 } 637 type = t; 638 } 639 if (s == this) 640 { 641 assert(global.errors); 642 type = Type.terror; 643 s = null; 644 } 645 if (!s) // it's a type alias 646 { 647 //printf("alias %s resolved to type %s\n", toChars(), type.toChars()); 648 type = type.semantic(loc, sc); 649 aliassym = null; 650 } 651 else // it's a symbolic alias 652 { 653 //printf("alias %s resolved to %s %s\n", toChars(), s.kind(), s.toChars()); 654 type = null; 655 aliassym = s; 656 } 657 if (global.gag && errors != global.errors) 658 { 659 type = oldtype; 660 aliassym = null; 661 } 662 inuse = 0; 663 semanticRun = PASSsemanticdone; 664 665 if (auto sx = overnext) 666 { 667 overnext = null; 668 if (!overloadInsert(sx)) 669 ScopeDsymbol.multiplyDefined(Loc(), sx, this); 670 } 671 } 672 673 override bool overloadInsert(Dsymbol s) 674 { 675 //printf("[%s] AliasDeclaration::overloadInsert('%s') s = %s %s @ [%s]\n", 676 // loc.toChars(), toChars(), s->kind(), s->toChars(), s->loc.toChars()); 677 678 /* semantic analysis is already finished, and the aliased entity 679 * is not overloadable. 680 */ 681 if (semanticRun >= PASSsemanticdone) 682 { 683 if (type) 684 return false; 685 686 /* When s is added in member scope by static if, mixin("code") or others, 687 * aliassym is determined already. See the case in: test/compilable/test61.d 688 */ 689 auto sa = aliassym.toAlias(); 690 if (auto fd = sa.isFuncDeclaration()) 691 { 692 aliassym = new FuncAliasDeclaration(ident, fd); 693 aliassym.parent = parent; 694 return aliassym.overloadInsert(s); 695 } 696 if (auto td = sa.isTemplateDeclaration()) 697 { 698 aliassym = new OverDeclaration(ident, td); 699 aliassym.parent = parent; 700 return aliassym.overloadInsert(s); 701 } 702 if (auto od = sa.isOverDeclaration()) 703 { 704 if (sa.ident != ident || sa.parent != parent) 705 { 706 od = new OverDeclaration(ident, od); 707 od.parent = parent; 708 aliassym = od; 709 } 710 return od.overloadInsert(s); 711 } 712 if (auto os = sa.isOverloadSet()) 713 { 714 if (sa.ident != ident || sa.parent != parent) 715 { 716 os = new OverloadSet(ident, os); 717 os.parent = parent; 718 aliassym = os; 719 } 720 os.push(s); 721 return true; 722 } 723 return false; 724 } 725 726 /* Don't know yet what the aliased symbol is, so assume it can 727 * be overloaded and check later for correctness. 728 */ 729 if (overnext) 730 return overnext.overloadInsert(s); 731 if (s is this) 732 return true; 733 overnext = s; 734 return true; 735 } 736 737 override const(char)* kind() const 738 { 739 return "alias"; 740 } 741 742 override Type getType() 743 { 744 if (type) 745 return type; 746 return toAlias().getType(); 747 } 748 749 override Dsymbol toAlias() 750 { 751 //printf("[%s] AliasDeclaration::toAlias('%s', this = %p, aliassym = %p, kind = '%s', inuse = %d)\n", 752 // loc.toChars(), toChars(), this, aliassym, aliassym ? aliassym.kind() : "", inuse); 753 assert(this != aliassym); 754 //static int count; if (++count == 10) *(char*)0=0; 755 if (inuse == 1 && type && _scope) 756 { 757 inuse = 2; 758 uint olderrors = global.errors; 759 Dsymbol s = type.toDsymbol(_scope); 760 //printf("[%s] type = %s, s = %p, this = %p\n", loc.toChars(), type->toChars(), s, this); 761 if (global.errors != olderrors) 762 goto Lerr; 763 if (s) 764 { 765 s = s.toAlias(); 766 if (global.errors != olderrors) 767 goto Lerr; 768 aliassym = s; 769 inuse = 0; 770 } 771 else 772 { 773 Type t = type.semantic(loc, _scope); 774 if (t.ty == Terror) 775 goto Lerr; 776 if (global.errors != olderrors) 777 goto Lerr; 778 //printf("t = %s\n", t->toChars()); 779 inuse = 0; 780 } 781 } 782 if (inuse) 783 { 784 error("recursive alias declaration"); 785 786 Lerr: 787 // Avoid breaking "recursive alias" state during errors gagged 788 if (global.gag) 789 return this; 790 aliassym = new AliasDeclaration(loc, ident, Type.terror); 791 type = Type.terror; 792 return aliassym; 793 } 794 795 if (semanticRun >= PASSsemanticdone) 796 { 797 // semantic is already done. 798 799 // Do not see aliassym !is null, because of lambda aliases. 800 801 // Do not see type.deco !is null, even so "alias T = const int;` needs 802 // semantic analysis to take the storage class `const` as type qualifier. 803 } 804 else 805 { 806 if (_import && _import._scope) 807 { 808 /* If this is an internal alias for selective/renamed import, 809 * load the module first. 810 */ 811 _import.semantic(null); 812 } 813 if (_scope) 814 { 815 aliasSemantic(_scope); 816 } 817 } 818 819 inuse = 1; 820 Dsymbol s = aliassym ? aliassym.toAlias() : this; 821 inuse = 0; 822 return s; 823 } 824 825 override Dsymbol toAlias2() 826 { 827 if (inuse) 828 { 829 error("recursive alias declaration"); 830 return this; 831 } 832 inuse = 1; 833 Dsymbol s = aliassym ? aliassym.toAlias2() : this; 834 inuse = 0; 835 return s; 836 } 837 838 override inout(AliasDeclaration) isAliasDeclaration() inout 839 { 840 return this; 841 } 842 843 override void accept(Visitor v) 844 { 845 v.visit(this); 846 } 847 } 848 849 /*********************************************************** 850 */ 851 extern (C++) final class OverDeclaration : Declaration 852 { 853 Dsymbol overnext; // next in overload list 854 Dsymbol aliassym; 855 bool hasOverloads; 856 857 extern (D) this(Identifier ident, Dsymbol s, bool hasOverloads = true) 858 { 859 super(ident); 860 this.aliassym = s; 861 this.hasOverloads = hasOverloads; 862 if (hasOverloads) 863 { 864 if (OverDeclaration od = aliassym.isOverDeclaration()) 865 this.hasOverloads = od.hasOverloads; 866 } 867 else 868 { 869 // for internal use 870 assert(!aliassym.isOverDeclaration()); 871 } 872 } 873 874 override const(char)* kind() const 875 { 876 return "overload alias"; // todo 877 } 878 879 override void semantic(Scope* sc) 880 { 881 } 882 883 override bool equals(RootObject o) 884 { 885 if (this == o) 886 return true; 887 888 Dsymbol s = isDsymbol(o); 889 if (!s) 890 return false; 891 892 OverDeclaration od1 = this; 893 if (OverDeclaration od2 = s.isOverDeclaration()) 894 { 895 return od1.aliassym.equals(od2.aliassym) && od1.hasOverloads == od2.hasOverloads; 896 } 897 if (aliassym == s) 898 { 899 if (hasOverloads) 900 return true; 901 if (FuncDeclaration fd = s.isFuncDeclaration()) 902 { 903 return fd.isUnique() !is null; 904 } 905 if (TemplateDeclaration td = s.isTemplateDeclaration()) 906 { 907 return td.overnext is null; 908 } 909 } 910 return false; 911 } 912 913 override bool overloadInsert(Dsymbol s) 914 { 915 //printf("OverDeclaration::overloadInsert('%s') aliassym = %p, overnext = %p\n", s->toChars(), aliassym, overnext); 916 if (overnext) 917 return overnext.overloadInsert(s); 918 if (s == this) 919 return true; 920 overnext = s; 921 return true; 922 } 923 924 Dsymbol isUnique() 925 { 926 if (!hasOverloads) 927 { 928 if (aliassym.isFuncDeclaration() || 929 aliassym.isTemplateDeclaration()) 930 { 931 return aliassym; 932 } 933 } 934 935 Dsymbol result = null; 936 overloadApply(aliassym, (Dsymbol s) 937 { 938 if (result) 939 { 940 result = null; 941 return 1; // ambiguous, done 942 } 943 else 944 { 945 result = s; 946 return 0; 947 } 948 }); 949 return result; 950 } 951 952 override inout(OverDeclaration) isOverDeclaration() 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++) class VarDeclaration : Declaration 966 { 967 Initializer _init; 968 uint offset; 969 FuncDeclarations nestedrefs; // referenced by these lexically nested functions 970 bool isargptr; // if parameter that _argptr points to 971 structalign_t alignment; 972 bool ctorinit; // it has been initialized in a ctor 973 974 // Both these mean the var is not rebindable once assigned, 975 // and the destructor gets run when it goes out of scope 976 bool onstack; // it is a class that was allocated on the stack 977 bool mynew; // it is a class new'd with custom operator new 978 979 int canassign; // it can be assigned to 980 bool overlapped; // if it is a field and has overlapping 981 bool overlapUnsafe; // if it is an overlapping field and the overlaps are unsafe 982 ubyte isdataseg; // private data for isDataseg 0 unset, 1 true, 2 false 983 Dsymbol aliassym; // if redone as alias to another symbol 984 VarDeclaration lastVar; // Linked list of variables for goto-skips-init detection 985 uint endlinnum; // line number of end of scope that this var lives in 986 987 // When interpreting, these point to the value (NULL if value not determinable) 988 // The index of this variable on the CTFE stack, -1 if not allocated 989 int ctfeAdrOnStack; 990 991 // if !=NULL, rundtor is tested at runtime to see 992 // if the destructor should be run. Used to prevent 993 // dtor calls on postblitted vars 994 VarDeclaration rundtor; 995 Expression edtor; // if !=null, does the destruction of the variable 996 IntRange* range; // if !=null, the variable is known to be within the range 997 998 final extern (D) this(Loc loc, Type type, Identifier id, Initializer _init, StorageClass storage_class = STCundefined) 999 { 1000 super(id); 1001 //printf("VarDeclaration('%s')\n", id->toChars()); 1002 assert(id); 1003 debug 1004 { 1005 if (!type && !_init) 1006 { 1007 printf("VarDeclaration('%s')\n", id.toChars()); 1008 //*(char*)0=0; 1009 } 1010 } 1011 assert(type || _init); 1012 this.type = type; 1013 this._init = _init; 1014 this.loc = loc; 1015 ctfeAdrOnStack = -1; 1016 this.storage_class = storage_class; 1017 } 1018 1019 override Dsymbol syntaxCopy(Dsymbol s) 1020 { 1021 //printf("VarDeclaration::syntaxCopy(%s)\n", toChars()); 1022 assert(!s); 1023 auto v = new VarDeclaration(loc, type ? type.syntaxCopy() : null, ident, _init ? _init.syntaxCopy() : null, storage_class); 1024 return v; 1025 } 1026 1027 override void semantic(Scope* sc) 1028 { 1029 version (none) 1030 { 1031 printf("VarDeclaration::semantic('%s', parent = '%s') sem = %d\n", toChars(), sc.parent ? sc.parent.toChars() : null, sem); 1032 printf(" type = %s\n", type ? type.toChars() : "null"); 1033 printf(" stc = x%x\n", sc.stc); 1034 printf(" storage_class = x%llx\n", storage_class); 1035 printf("linkage = %d\n", sc.linkage); 1036 //if (strcmp(toChars(), "mul") == 0) assert(0); 1037 } 1038 //if (semanticRun > PASSinit) 1039 // return; 1040 //semanticRun = PSSsemantic; 1041 1042 if (semanticRun >= PASSsemanticdone) 1043 return; 1044 1045 Scope* scx = null; 1046 if (_scope) 1047 { 1048 sc = _scope; 1049 scx = sc; 1050 _scope = null; 1051 } 1052 1053 /* Pick up storage classes from context, but except synchronized, 1054 * override, abstract, and final. 1055 */ 1056 storage_class |= (sc.stc & ~(STCsynchronized | STCoverride | STCabstract | STCfinal)); 1057 if (storage_class & STCextern && _init) 1058 error("extern symbols cannot have initializers"); 1059 1060 userAttribDecl = sc.userAttribDecl; 1061 1062 AggregateDeclaration ad = isThis(); 1063 if (ad) 1064 storage_class |= ad.storage_class & STC_TYPECTOR; 1065 1066 /* If auto type inference, do the inference 1067 */ 1068 int inferred = 0; 1069 if (!type) 1070 { 1071 inuse++; 1072 1073 // Infering the type requires running semantic, 1074 // so mark the scope as ctfe if required 1075 bool needctfe = (storage_class & (STCmanifest | STCstatic)) != 0; 1076 if (needctfe) 1077 sc = sc.startCTFE(); 1078 1079 //printf("inferring type for %s with init %s\n", toChars(), init->toChars()); 1080 _init = _init.inferType(sc); 1081 type = _init.toExpression().type; 1082 if (needctfe) 1083 sc = sc.endCTFE(); 1084 1085 inuse--; 1086 inferred = 1; 1087 1088 /* This is a kludge to support the existing syntax for RAII 1089 * declarations. 1090 */ 1091 storage_class &= ~STCauto; 1092 originalType = type.syntaxCopy(); 1093 } 1094 else 1095 { 1096 if (!originalType) 1097 originalType = type.syntaxCopy(); 1098 1099 /* Prefix function attributes of variable declaration can affect 1100 * its type: 1101 * pure nothrow void function() fp; 1102 * static assert(is(typeof(fp) == void function() pure nothrow)); 1103 */ 1104 Scope* sc2 = sc.push(); 1105 sc2.stc |= (storage_class & STC_FUNCATTR); 1106 inuse++; 1107 type = type.semantic(loc, sc2); 1108 inuse--; 1109 sc2.pop(); 1110 } 1111 //printf(" semantic type = %s\n", type ? type->toChars() : "null"); 1112 if (type.ty == Terror) 1113 errors = true; 1114 1115 type.checkDeprecated(loc, sc); 1116 linkage = sc.linkage; 1117 this.parent = sc.parent; 1118 //printf("this = %p, parent = %p, '%s'\n", this, parent, parent->toChars()); 1119 protection = sc.protection; 1120 1121 /* If scope's alignment is the default, use the type's alignment, 1122 * otherwise the scope overrrides. 1123 */ 1124 alignment = sc.alignment(); 1125 if (alignment == STRUCTALIGN_DEFAULT) 1126 alignment = type.alignment(); // use type's alignment 1127 1128 //printf("sc->stc = %x\n", sc->stc); 1129 //printf("storage_class = x%x\n", storage_class); 1130 1131 if (global.params.vcomplex) 1132 type.checkComplexTransition(loc); 1133 1134 // Calculate type size + safety checks 1135 if (sc.func && !sc.intypeof) 1136 { 1137 if (storage_class & STCgshared && !isMember()) 1138 { 1139 if (sc.func.setUnsafe()) 1140 error("__gshared not allowed in safe functions; use shared"); 1141 } 1142 } 1143 1144 Dsymbol parent = toParent(); 1145 1146 Type tb = type.toBasetype(); 1147 Type tbn = tb.baseElemOf(); 1148 if (tb.ty == Tvoid && !(storage_class & STClazy)) 1149 { 1150 if (inferred) 1151 { 1152 error("type %s is inferred from initializer %s, and variables cannot be of type void", type.toChars(), _init.toChars()); 1153 } 1154 else 1155 error("variables cannot be of type void"); 1156 type = Type.terror; 1157 tb = type; 1158 } 1159 if (tb.ty == Tfunction) 1160 { 1161 error("cannot be declared to be a function"); 1162 type = Type.terror; 1163 tb = type; 1164 } 1165 if (tb.ty == Tstruct) 1166 { 1167 TypeStruct ts = cast(TypeStruct)tb; 1168 if (!ts.sym.members) 1169 { 1170 error("no definition of struct %s", ts.toChars()); 1171 } 1172 } 1173 if ((storage_class & STCauto) && !inferred) 1174 error("storage class 'auto' has no effect if type is not inferred, did you mean 'scope'?"); 1175 1176 if (tb.ty == Ttuple) 1177 { 1178 /* Instead, declare variables for each of the tuple elements 1179 * and add those. 1180 */ 1181 TypeTuple tt = cast(TypeTuple)tb; 1182 size_t nelems = Parameter.dim(tt.arguments); 1183 Expression ie = (_init && !_init.isVoidInitializer()) ? _init.toExpression() : null; 1184 if (ie) 1185 ie = ie.semantic(sc); 1186 if (nelems > 0 && ie) 1187 { 1188 auto iexps = new Expressions(); 1189 iexps.push(ie); 1190 auto exps = new Expressions(); 1191 for (size_t pos = 0; pos < iexps.dim; pos++) 1192 { 1193 Lexpand1: 1194 Expression e = (*iexps)[pos]; 1195 Parameter arg = Parameter.getNth(tt.arguments, pos); 1196 arg.type = arg.type.semantic(loc, sc); 1197 //printf("[%d] iexps->dim = %d, ", pos, iexps->dim); 1198 //printf("e = (%s %s, %s), ", Token::tochars[e->op], e->toChars(), e->type->toChars()); 1199 //printf("arg = (%s, %s)\n", arg->toChars(), arg->type->toChars()); 1200 1201 if (e != ie) 1202 { 1203 if (iexps.dim > nelems) 1204 goto Lnomatch; 1205 if (e.type.implicitConvTo(arg.type)) 1206 continue; 1207 } 1208 1209 if (e.op == TOKtuple) 1210 { 1211 TupleExp te = cast(TupleExp)e; 1212 if (iexps.dim - 1 + te.exps.dim > nelems) 1213 goto Lnomatch; 1214 1215 iexps.remove(pos); 1216 iexps.insert(pos, te.exps); 1217 (*iexps)[pos] = Expression.combine(te.e0, (*iexps)[pos]); 1218 goto Lexpand1; 1219 } 1220 else if (isAliasThisTuple(e)) 1221 { 1222 auto v = copyToTemp(0, "__tup", e); 1223 auto ve = new VarExp(loc, v); 1224 ve.type = e.type; 1225 1226 exps.setDim(1); 1227 (*exps)[0] = ve; 1228 expandAliasThisTuples(exps, 0); 1229 1230 for (size_t u = 0; u < exps.dim; u++) 1231 { 1232 Lexpand2: 1233 Expression ee = (*exps)[u]; 1234 arg = Parameter.getNth(tt.arguments, pos + u); 1235 arg.type = arg.type.semantic(loc, sc); 1236 //printf("[%d+%d] exps->dim = %d, ", pos, u, exps->dim); 1237 //printf("ee = (%s %s, %s), ", Token::tochars[ee->op], ee->toChars(), ee->type->toChars()); 1238 //printf("arg = (%s, %s)\n", arg->toChars(), arg->type->toChars()); 1239 1240 size_t iexps_dim = iexps.dim - 1 + exps.dim; 1241 if (iexps_dim > nelems) 1242 goto Lnomatch; 1243 if (ee.type.implicitConvTo(arg.type)) 1244 continue; 1245 1246 if (expandAliasThisTuples(exps, u) != -1) 1247 goto Lexpand2; 1248 } 1249 1250 if ((*exps)[0] != ve) 1251 { 1252 Expression e0 = (*exps)[0]; 1253 (*exps)[0] = new CommaExp(loc, new DeclarationExp(loc, v), e0); 1254 (*exps)[0].type = e0.type; 1255 1256 iexps.remove(pos); 1257 iexps.insert(pos, exps); 1258 goto Lexpand1; 1259 } 1260 } 1261 } 1262 if (iexps.dim < nelems) 1263 goto Lnomatch; 1264 1265 ie = new TupleExp(_init.loc, iexps); 1266 } 1267 Lnomatch: 1268 1269 if (ie && ie.op == TOKtuple) 1270 { 1271 TupleExp te = cast(TupleExp)ie; 1272 size_t tedim = te.exps.dim; 1273 if (tedim != nelems) 1274 { 1275 .error(loc, "tuple of %d elements cannot be assigned to tuple of %d elements", cast(int)tedim, cast(int)nelems); 1276 for (size_t u = tedim; u < nelems; u++) // fill dummy expression 1277 te.exps.push(new ErrorExp()); 1278 } 1279 } 1280 1281 auto exps = new Objects(); 1282 exps.setDim(nelems); 1283 for (size_t i = 0; i < nelems; i++) 1284 { 1285 Parameter arg = Parameter.getNth(tt.arguments, i); 1286 1287 OutBuffer buf; 1288 buf.printf("__%s_field_%llu", ident.toChars(), cast(ulong)i); 1289 auto id = Identifier.idPool(buf.peekSlice()); 1290 1291 Initializer ti; 1292 if (ie) 1293 { 1294 Expression einit = ie; 1295 if (ie.op == TOKtuple) 1296 { 1297 TupleExp te = cast(TupleExp)ie; 1298 einit = (*te.exps)[i]; 1299 if (i == 0) 1300 einit = Expression.combine(te.e0, einit); 1301 } 1302 ti = new ExpInitializer(einit.loc, einit); 1303 } 1304 else 1305 ti = _init ? _init.syntaxCopy() : null; 1306 1307 StorageClass storage_class = STCtemp | storage_class; 1308 if (arg.storageClass & STCparameter) 1309 storage_class |= arg.storageClass; 1310 auto v = new VarDeclaration(loc, arg.type, id, ti, storage_class); 1311 //printf("declaring field %s of type %s\n", v->toChars(), v->type->toChars()); 1312 v.semantic(sc); 1313 1314 if (sc.scopesym) 1315 { 1316 //printf("adding %s to %s\n", v->toChars(), sc->scopesym->toChars()); 1317 if (sc.scopesym.members) 1318 // Note this prevents using foreach() over members, because the limits can change 1319 sc.scopesym.members.push(v); 1320 } 1321 1322 Expression e = new DsymbolExp(loc, v); 1323 (*exps)[i] = e; 1324 } 1325 auto v2 = new TupleDeclaration(loc, ident, exps); 1326 v2.parent = this.parent; 1327 v2.isexp = true; 1328 aliassym = v2; 1329 semanticRun = PASSsemanticdone; 1330 return; 1331 } 1332 1333 /* Storage class can modify the type 1334 */ 1335 type = type.addStorageClass(storage_class); 1336 1337 /* Adjust storage class to reflect type 1338 */ 1339 if (type.isConst()) 1340 { 1341 storage_class |= STCconst; 1342 if (type.isShared()) 1343 storage_class |= STCshared; 1344 } 1345 else if (type.isImmutable()) 1346 storage_class |= STCimmutable; 1347 else if (type.isShared()) 1348 storage_class |= STCshared; 1349 else if (type.isWild()) 1350 storage_class |= STCwild; 1351 1352 if (StorageClass stc = storage_class & (STCsynchronized | STCoverride | STCabstract | STCfinal)) 1353 { 1354 if (stc == STCfinal) 1355 error("cannot be final, perhaps you meant const?"); 1356 else 1357 { 1358 OutBuffer buf; 1359 stcToBuffer(&buf, stc); 1360 error("cannot be %s", buf.peekString()); 1361 } 1362 storage_class &= ~stc; // strip off 1363 } 1364 1365 if (storage_class & STCscope) 1366 { 1367 StorageClass stc = storage_class & (STCstatic | STCextern | STCmanifest | STCtls | STCgshared); 1368 if (stc) 1369 { 1370 OutBuffer buf; 1371 stcToBuffer(&buf, stc); 1372 error("cannot be 'scope' and '%s'", buf.peekString()); 1373 } 1374 else if (isMember()) 1375 { 1376 error("field cannot be 'scope'"); 1377 } 1378 else if (!type.hasPointers()) 1379 { 1380 storage_class &= ~STCscope; // silently ignore; may occur in generic code 1381 } 1382 } 1383 1384 if (storage_class & (STCstatic | STCextern | STCmanifest | STCtemplateparameter | STCtls | STCgshared | STCctfe)) 1385 { 1386 } 1387 else 1388 { 1389 AggregateDeclaration aad = parent.isAggregateDeclaration(); 1390 if (aad) 1391 { 1392 if (global.params.vfield && storage_class & (STCconst | STCimmutable) && _init && !_init.isVoidInitializer()) 1393 { 1394 const(char)* p = loc.toChars(); 1395 const(char)* s = (storage_class & STCimmutable) ? "immutable" : "const"; 1396 fprintf(global.stdmsg, "%s: %s.%s is %s field\n", p ? p : "", ad.toPrettyChars(), toChars(), s); 1397 } 1398 storage_class |= STCfield; 1399 if (tbn.ty == Tstruct && (cast(TypeStruct)tbn).sym.noDefaultCtor) 1400 { 1401 if (!isThisDeclaration() && !_init) 1402 aad.noDefaultCtor = true; 1403 } 1404 } 1405 1406 InterfaceDeclaration id = parent.isInterfaceDeclaration(); 1407 if (id) 1408 { 1409 error("field not allowed in interface"); 1410 } 1411 else if (aad && aad.sizeok == SIZEOKdone) 1412 { 1413 error("cannot be further field because it will change the determined %s size", aad.toChars()); 1414 } 1415 1416 /* Templates cannot add fields to aggregates 1417 */ 1418 TemplateInstance ti = parent.isTemplateInstance(); 1419 if (ti) 1420 { 1421 // Take care of nested templates 1422 while (1) 1423 { 1424 TemplateInstance ti2 = ti.tempdecl.parent.isTemplateInstance(); 1425 if (!ti2) 1426 break; 1427 ti = ti2; 1428 } 1429 // If it's a member template 1430 AggregateDeclaration ad2 = ti.tempdecl.isMember(); 1431 if (ad2 && storage_class != STCundefined) 1432 { 1433 error("cannot use template to add field to aggregate '%s'", ad2.toChars()); 1434 } 1435 } 1436 } 1437 1438 if ((storage_class & (STCref | STCparameter | STCforeach | STCtemp | STCresult)) == STCref && ident != Id.This) 1439 { 1440 error("only parameters or foreach declarations can be ref"); 1441 } 1442 1443 if (type.hasWild()) 1444 { 1445 if (storage_class & (STCstatic | STCextern | STCtls | STCgshared | STCmanifest | STCfield) || isDataseg()) 1446 { 1447 error("only parameters or stack based variables can be inout"); 1448 } 1449 FuncDeclaration func = sc.func; 1450 if (func) 1451 { 1452 if (func.fes) 1453 func = func.fes.func; 1454 bool isWild = false; 1455 for (FuncDeclaration fd = func; fd; fd = fd.toParent2().isFuncDeclaration()) 1456 { 1457 if ((cast(TypeFunction)fd.type).iswild) 1458 { 1459 isWild = true; 1460 break; 1461 } 1462 } 1463 if (!isWild) 1464 { 1465 error("inout variables can only be declared inside inout functions"); 1466 } 1467 } 1468 } 1469 1470 if (!(storage_class & (STCctfe | STCref | STCresult)) && tbn.ty == Tstruct && (cast(TypeStruct)tbn).sym.noDefaultCtor) 1471 { 1472 if (!_init) 1473 { 1474 if (isField()) 1475 { 1476 /* For fields, we'll check the constructor later to make sure it is initialized 1477 */ 1478 storage_class |= STCnodefaultctor; 1479 } 1480 else if (storage_class & STCparameter) 1481 { 1482 } 1483 else 1484 error("default construction is disabled for type %s", type.toChars()); 1485 } 1486 } 1487 1488 FuncDeclaration fd = parent.isFuncDeclaration(); 1489 if (type.isscope() && !(storage_class & STCnodtor)) 1490 { 1491 if (storage_class & (STCfield | STCout | STCref | STCstatic | STCmanifest | STCtls | STCgshared) || !fd) 1492 { 1493 error("globals, statics, fields, manifest constants, ref and out parameters cannot be scope"); 1494 } 1495 if (!(storage_class & STCscope)) 1496 { 1497 if (!(storage_class & STCparameter) && ident != Id.withSym) 1498 error("reference to scope class must be scope"); 1499 } 1500 } 1501 1502 // Calculate type size + safety checks 1503 if (sc.func && !sc.intypeof) 1504 { 1505 if (_init && _init.isVoidInitializer() && type.hasPointers()) // get type size 1506 { 1507 if (sc.func.setUnsafe()) 1508 error("void initializers for pointers not allowed in safe functions"); 1509 } 1510 else if (!_init && 1511 !(storage_class & (STCstatic | STCextern | STCtls | STCgshared | STCmanifest | STCfield | STCparameter)) && 1512 type.hasVoidInitPointers()) 1513 { 1514 if (sc.func.setUnsafe()) 1515 error("void initializers for pointers not allowed in safe functions"); 1516 } 1517 } 1518 1519 if (!_init && !fd) 1520 { 1521 // If not mutable, initializable by constructor only 1522 storage_class |= STCctorinit; 1523 } 1524 1525 if (_init) 1526 storage_class |= STCinit; // remember we had an explicit initializer 1527 else if (storage_class & STCmanifest) 1528 error("manifest constants must have initializers"); 1529 1530 bool isBlit = false; 1531 d_uns64 sz; 1532 if (!_init && 1533 !sc.inunion && 1534 !(storage_class & (STCstatic | STCgshared | STCextern)) && 1535 fd && 1536 (!(storage_class & (STCfield | STCin | STCforeach | STCparameter | STCresult)) || 1537 (storage_class & STCout)) && 1538 (sz = type.size()) != 0) 1539 { 1540 // Provide a default initializer 1541 1542 //printf("Providing default initializer for '%s'\n", toChars()); 1543 if (sz == SIZE_INVALID && type.ty != Terror) 1544 error("size of type %s is invalid", type.toChars()); 1545 1546 Type tv = type; 1547 while (tv.ty == Tsarray) // Don't skip Tenum 1548 tv = tv.nextOf(); 1549 if (tv.needsNested()) 1550 { 1551 /* Nested struct requires valid enclosing frame pointer. 1552 * In StructLiteralExp::toElem(), it's calculated. 1553 */ 1554 assert(tbn.ty == Tstruct); 1555 checkFrameAccess(loc, sc, (cast(TypeStruct)tbn).sym); 1556 1557 Expression e = tv.defaultInitLiteral(loc); 1558 e = new BlitExp(loc, new VarExp(loc, this), e); 1559 e = e.semantic(sc); 1560 _init = new ExpInitializer(loc, e); 1561 goto Ldtor; 1562 } 1563 if (tv.ty == Tstruct && (cast(TypeStruct)tv).sym.zeroInit == 1) 1564 { 1565 /* If a struct is all zeros, as a special case 1566 * set it's initializer to the integer 0. 1567 * In AssignExp::toElem(), we check for this and issue 1568 * a memset() to initialize the struct. 1569 * Must do same check in interpreter. 1570 */ 1571 Expression e = new IntegerExp(loc, 0, Type.tint32); 1572 e = new BlitExp(loc, new VarExp(loc, this), e); 1573 e.type = type; // don't type check this, it would fail 1574 _init = new ExpInitializer(loc, e); 1575 goto Ldtor; 1576 } 1577 if (type.baseElemOf().ty == Tvoid) 1578 { 1579 error("%s does not have a default initializer", type.toChars()); 1580 } 1581 else if (auto e = type.defaultInit(loc)) 1582 { 1583 _init = new ExpInitializer(loc, e); 1584 } 1585 1586 // Default initializer is always a blit 1587 isBlit = true; 1588 } 1589 if (_init) 1590 { 1591 sc = sc.push(); 1592 sc.stc &= ~(STC_TYPECTOR | STCpure | STCnothrow | STCnogc | STCref | STCdisable); 1593 1594 ExpInitializer ei = _init.isExpInitializer(); 1595 if (ei) // Bugzilla 13424: Preset the required type to fail in FuncLiteralDeclaration::semantic3 1596 ei.exp = inferType(ei.exp, type); 1597 1598 // If inside function, there is no semantic3() call 1599 if (sc.func || sc.intypeof == 1) 1600 { 1601 // If local variable, use AssignExp to handle all the various 1602 // possibilities. 1603 if (fd && !(storage_class & (STCmanifest | STCstatic | STCtls | STCgshared | STCextern)) && !_init.isVoidInitializer()) 1604 { 1605 //printf("fd = '%s', var = '%s'\n", fd->toChars(), toChars()); 1606 if (!ei) 1607 { 1608 ArrayInitializer ai = _init.isArrayInitializer(); 1609 Expression e; 1610 if (ai && tb.ty == Taarray) 1611 e = ai.toAssocArrayLiteral(); 1612 else 1613 e = _init.toExpression(); 1614 if (!e) 1615 { 1616 // Run semantic, but don't need to interpret 1617 _init = _init.semantic(sc, type, INITnointerpret); 1618 e = _init.toExpression(); 1619 if (!e) 1620 { 1621 error("is not a static and cannot have static initializer"); 1622 return; 1623 } 1624 } 1625 ei = new ExpInitializer(_init.loc, e); 1626 _init = ei; 1627 } 1628 1629 Expression exp = ei.exp; 1630 Expression e1 = new VarExp(loc, this); 1631 if (isBlit) 1632 exp = new BlitExp(loc, e1, exp); 1633 else 1634 exp = new ConstructExp(loc, e1, exp); 1635 canassign++; 1636 exp = exp.semantic(sc); 1637 canassign--; 1638 exp = exp.optimize(WANTvalue); 1639 if (exp.op == TOKerror) 1640 { 1641 _init = new ErrorInitializer(); 1642 ei = null; 1643 } 1644 else 1645 ei.exp = exp; 1646 1647 if (ei && isScope()) 1648 { 1649 Expression ex = ei.exp; 1650 while (ex.op == TOKcomma) 1651 ex = (cast(CommaExp)ex).e2; 1652 if (ex.op == TOKblit || ex.op == TOKconstruct) 1653 ex = (cast(AssignExp)ex).e2; 1654 if (ex.op == TOKnew) 1655 { 1656 // See if initializer is a NewExp that can be allocated on the stack 1657 NewExp ne = cast(NewExp)ex; 1658 if (type.toBasetype().ty == Tclass) 1659 { 1660 if (ne.newargs && ne.newargs.dim > 1) 1661 { 1662 mynew = true; 1663 } 1664 else 1665 { 1666 ne.onstack = 1; 1667 onstack = true; 1668 } 1669 } 1670 } 1671 else if (ex.op == TOKfunction) 1672 { 1673 // or a delegate that doesn't escape a reference to the function 1674 FuncDeclaration f = (cast(FuncExp)ex).fd; 1675 f.tookAddressOf--; 1676 } 1677 } 1678 } 1679 else 1680 { 1681 // Bugzilla 14166: Don't run CTFE for the temporary variables inside typeof 1682 _init = _init.semantic(sc, type, sc.intypeof == 1 ? INITnointerpret : INITinterpret); 1683 } 1684 } 1685 else if (parent.isAggregateDeclaration()) 1686 { 1687 _scope = scx ? scx : sc.copy(); 1688 _scope.setNoFree(); 1689 } 1690 else if (storage_class & (STCconst | STCimmutable | STCmanifest) || type.isConst() || type.isImmutable()) 1691 { 1692 /* Because we may need the results of a const declaration in a 1693 * subsequent type, such as an array dimension, before semantic2() 1694 * gets ordinarily run, try to run semantic2() now. 1695 * Ignore failure. 1696 */ 1697 if (!inferred) 1698 { 1699 uint errors = global.errors; 1700 inuse++; 1701 if (ei) 1702 { 1703 Expression exp = ei.exp.syntaxCopy(); 1704 1705 bool needctfe = isDataseg() || (storage_class & STCmanifest); 1706 if (needctfe) 1707 sc = sc.startCTFE(); 1708 exp = exp.semantic(sc); 1709 exp = resolveProperties(sc, exp); 1710 if (needctfe) 1711 sc = sc.endCTFE(); 1712 1713 Type tb2 = type.toBasetype(); 1714 Type ti = exp.type.toBasetype(); 1715 1716 /* The problem is the following code: 1717 * struct CopyTest { 1718 * double x; 1719 * this(double a) { x = a * 10.0;} 1720 * this(this) { x += 2.0; } 1721 * } 1722 * const CopyTest z = CopyTest(5.3); // ok 1723 * const CopyTest w = z; // not ok, postblit not run 1724 * static assert(w.x == 55.0); 1725 * because the postblit doesn't get run on the initialization of w. 1726 */ 1727 if (ti.ty == Tstruct) 1728 { 1729 StructDeclaration sd = (cast(TypeStruct)ti).sym; 1730 /* Look to see if initializer involves a copy constructor 1731 * (which implies a postblit) 1732 */ 1733 // there is a copy constructor 1734 // and exp is the same struct 1735 if (sd.postblit && tb2.toDsymbol(null) == sd) 1736 { 1737 // The only allowable initializer is a (non-copy) constructor 1738 if (exp.isLvalue()) 1739 error("of type struct %s uses this(this), which is not allowed in static initialization", tb2.toChars()); 1740 } 1741 } 1742 ei.exp = exp; 1743 } 1744 _init = _init.semantic(sc, type, INITinterpret); 1745 inuse--; 1746 if (global.errors > errors) 1747 { 1748 _init = new ErrorInitializer(); 1749 type = Type.terror; 1750 } 1751 } 1752 else 1753 { 1754 _scope = scx ? scx : sc.copy(); 1755 _scope.setNoFree(); 1756 } 1757 } 1758 sc = sc.pop(); 1759 } 1760 1761 Ldtor: 1762 /* Build code to execute destruction, if necessary 1763 */ 1764 edtor = callScopeDtor(sc); 1765 if (edtor) 1766 { 1767 if (sc.func && storage_class & (STCstatic | STCgshared)) 1768 edtor = edtor.semantic(sc._module._scope); 1769 else 1770 edtor = edtor.semantic(sc); 1771 1772 version (none) 1773 { 1774 // currently disabled because of std.stdio.stdin, stdout and stderr 1775 if (isDataseg() && !(storage_class & STCextern)) 1776 error("static storage variables cannot have destructors"); 1777 } 1778 } 1779 1780 semanticRun = PASSsemanticdone; 1781 1782 if (type.toBasetype().ty == Terror) 1783 errors = true; 1784 1785 if(sc.scopesym && !sc.scopesym.isAggregateDeclaration()) 1786 { 1787 for (ScopeDsymbol sym = sc.scopesym; sym && endlinnum == 0; 1788 sym = sym.parent ? sym.parent.isScopeDsymbol() : null) 1789 endlinnum = sym.endlinnum; 1790 } 1791 } 1792 1793 override final void setFieldOffset(AggregateDeclaration ad, uint* poffset, bool isunion) 1794 { 1795 //printf("VarDeclaration::setFieldOffset(ad = %s) %s\n", ad.toChars(), toChars()); 1796 1797 if (aliassym) 1798 { 1799 // If this variable was really a tuple, set the offsets for the tuple fields 1800 TupleDeclaration v2 = aliassym.isTupleDeclaration(); 1801 assert(v2); 1802 for (size_t i = 0; i < v2.objects.dim; i++) 1803 { 1804 RootObject o = (*v2.objects)[i]; 1805 assert(o.dyncast() == DYNCAST_EXPRESSION); 1806 Expression e = cast(Expression)o; 1807 assert(e.op == TOKdsymbol); 1808 DsymbolExp se = cast(DsymbolExp)e; 1809 se.s.setFieldOffset(ad, poffset, isunion); 1810 } 1811 return; 1812 } 1813 1814 if (!isField()) 1815 return; 1816 assert(!(storage_class & (STCstatic | STCextern | STCparameter | STCtls))); 1817 1818 //printf("+VarDeclaration::setFieldOffset(ad = %s) %s\n", ad.toChars(), toChars()); 1819 1820 /* Fields that are tuples appear both as part of TupleDeclarations and 1821 * as members. That means ignore them if they are already a field. 1822 */ 1823 if (offset) 1824 { 1825 // already a field 1826 *poffset = ad.structsize; // Bugzilla 13613 1827 return; 1828 } 1829 for (size_t i = 0; i < ad.fields.dim; i++) 1830 { 1831 if (ad.fields[i] == this) 1832 { 1833 // already a field 1834 *poffset = ad.structsize; // Bugzilla 13613 1835 return; 1836 } 1837 } 1838 1839 // Check for forward referenced types which will fail the size() call 1840 Type t = type.toBasetype(); 1841 if (storage_class & STCref) 1842 { 1843 // References are the size of a pointer 1844 t = Type.tvoidptr; 1845 } 1846 Type tv = t.baseElemOf(); 1847 if (tv.ty == Tstruct) 1848 { 1849 auto ts = cast(TypeStruct)tv; 1850 assert(ts.sym != ad); // already checked in ad.determineFields() 1851 if (!ts.sym.determineSize(loc)) 1852 { 1853 type = Type.terror; 1854 errors = true; 1855 return; 1856 } 1857 } 1858 1859 // List in ad.fields. Even if the type is error, it's necessary to avoid 1860 // pointless error diagnostic "more initializers than fields" on struct literal. 1861 ad.fields.push(this); 1862 1863 if (t.ty == Terror) 1864 return; 1865 1866 const sz = t.size(loc); 1867 assert(sz != SIZE_INVALID && sz < uint.max); 1868 uint memsize = cast(uint)sz; // size of member 1869 uint memalignsize = Target.fieldalign(t); // size of member for alignment purposes 1870 offset = AggregateDeclaration.placeField( 1871 poffset, 1872 memsize, memalignsize, alignment, 1873 &ad.structsize, &ad.alignsize, 1874 isunion); 1875 1876 //printf("\t%s: memalignsize = %d\n", toChars(), memalignsize); 1877 //printf(" addField '%s' to '%s' at offset %d, size = %d\n", toChars(), ad.toChars(), offset, memsize); 1878 } 1879 1880 override final void semantic2(Scope* sc) 1881 { 1882 if (semanticRun < PASSsemanticdone && inuse) 1883 return; 1884 1885 //printf("VarDeclaration::semantic2('%s')\n", toChars()); 1886 1887 if (_init && !toParent().isFuncDeclaration()) 1888 { 1889 inuse++; 1890 version (none) 1891 { 1892 ExpInitializer ei = _init.isExpInitializer(); 1893 if (ei) 1894 { 1895 ei.exp.print(); 1896 printf("type = %p\n", ei.exp.type); 1897 } 1898 } 1899 // Bugzilla 14166: Don't run CTFE for the temporary variables inside typeof 1900 _init = _init.semantic(sc, type, sc.intypeof == 1 ? INITnointerpret : INITinterpret); 1901 inuse--; 1902 } 1903 if (storage_class & STCmanifest) 1904 { 1905 version (none) 1906 { 1907 if ((type.ty == Tclass) && type.isMutable()) 1908 { 1909 error("is mutable. Only const and immutable class enum are allowed, not %s", type.toChars()); 1910 } 1911 else if (type.ty == Tpointer && type.nextOf().ty == Tstruct && type.nextOf().isMutable()) 1912 { 1913 ExpInitializer ei = _init.isExpInitializer(); 1914 if (ei.exp.op == TOKaddress && (cast(AddrExp)ei.exp).e1.op == TOKstructliteral) 1915 { 1916 error("is a pointer to mutable struct. Only pointers to const or immutable struct enum are allowed, not %s", type.toChars()); 1917 } 1918 } 1919 } 1920 else 1921 { 1922 if (type.ty == Tclass && _init) 1923 { 1924 ExpInitializer ei = _init.isExpInitializer(); 1925 if (ei.exp.op == TOKclassreference) 1926 error(": Unable to initialize enum with class or pointer to struct. Use static const variable instead."); 1927 } 1928 else if (type.ty == Tpointer && type.nextOf().ty == Tstruct) 1929 { 1930 ExpInitializer ei = _init.isExpInitializer(); 1931 if (ei && ei.exp.op == TOKaddress && (cast(AddrExp)ei.exp).e1.op == TOKstructliteral) 1932 { 1933 error(": Unable to initialize enum with class or pointer to struct. Use static const variable instead."); 1934 } 1935 } 1936 } 1937 } 1938 else if (_init && isThreadlocal()) 1939 { 1940 if ((type.ty == Tclass) && type.isMutable() && !type.isShared()) 1941 { 1942 ExpInitializer ei = _init.isExpInitializer(); 1943 if (ei && ei.exp.op == TOKclassreference) 1944 error("is mutable. Only const or immutable class thread local variable are allowed, not %s", type.toChars()); 1945 } 1946 else if (type.ty == Tpointer && type.nextOf().ty == Tstruct && type.nextOf().isMutable() && !type.nextOf().isShared()) 1947 { 1948 ExpInitializer ei = _init.isExpInitializer(); 1949 if (ei && ei.exp.op == TOKaddress && (cast(AddrExp)ei.exp).e1.op == TOKstructliteral) 1950 { 1951 error("is a pointer to mutable struct. Only pointers to const, immutable or shared struct thread local variable are allowed, not %s", type.toChars()); 1952 } 1953 } 1954 } 1955 semanticRun = PASSsemantic2done; 1956 } 1957 1958 override const(char)* kind() const 1959 { 1960 return "variable"; 1961 } 1962 1963 override final AggregateDeclaration isThis() 1964 { 1965 AggregateDeclaration ad = null; 1966 if (!(storage_class & (STCstatic | STCextern | STCmanifest | STCtemplateparameter | STCtls | STCgshared | STCctfe))) 1967 { 1968 for (Dsymbol s = this; s; s = s.parent) 1969 { 1970 ad = s.isMember(); 1971 if (ad) 1972 break; 1973 if (!s.parent || !s.parent.isTemplateMixin()) 1974 break; 1975 } 1976 } 1977 return ad; 1978 } 1979 1980 override final bool needThis() 1981 { 1982 //printf("VarDeclaration::needThis(%s, x%x)\n", toChars(), storage_class); 1983 return isField(); 1984 } 1985 1986 override final bool isExport() 1987 { 1988 return protection.kind == PROTexport; 1989 } 1990 1991 override final bool isImportedSymbol() 1992 { 1993 if (protection.kind == PROTexport && !_init && (storage_class & STCstatic || parent.isModule())) 1994 return true; 1995 return false; 1996 } 1997 1998 /******************************* 1999 * Does symbol go into data segment? 2000 * Includes extern variables. 2001 */ 2002 override final bool isDataseg() 2003 { 2004 version (none) 2005 { 2006 printf("VarDeclaration::isDataseg(%p, '%s')\n", this, toChars()); 2007 printf("%llx, isModule: %p, isTemplateInstance: %p\n", storage_class & (STCstatic | STCconst), parent.isModule(), parent.isTemplateInstance()); 2008 printf("parent = '%s'\n", parent.toChars()); 2009 } 2010 2011 if (isdataseg == 0) // the value is not cached 2012 { 2013 isdataseg = 2; // The Variables does not go into the datasegment 2014 2015 if (!canTakeAddressOf()) 2016 { 2017 return false; 2018 } 2019 2020 Dsymbol parent = toParent(); 2021 if (!parent && !(storage_class & STCstatic)) 2022 { 2023 error("forward referenced"); 2024 type = Type.terror; 2025 } 2026 else if (storage_class & (STCstatic | STCextern | STCtls | STCgshared) || 2027 parent.isModule() || parent.isTemplateInstance()) 2028 { 2029 isdataseg = 1; // It is in the DataSegment 2030 } 2031 } 2032 2033 return (isdataseg == 1); 2034 } 2035 /************************************ 2036 * Does symbol go into thread local storage? 2037 */ 2038 override final bool isThreadlocal() 2039 { 2040 //printf("VarDeclaration::isThreadlocal(%p, '%s')\n", this, toChars()); 2041 /* Data defaults to being thread-local. It is not thread-local 2042 * if it is immutable, const or shared. 2043 */ 2044 bool i = isDataseg() && !(storage_class & (STCimmutable | STCconst | STCshared | STCgshared)); 2045 //printf("\treturn %d\n", i); 2046 return i; 2047 } 2048 2049 /******************************************** 2050 * Can variable be read and written by CTFE? 2051 */ 2052 final bool isCTFE() 2053 { 2054 return (storage_class & STCctfe) != 0; // || !isDataseg(); 2055 } 2056 2057 final bool isOverlappedWith(VarDeclaration v) 2058 { 2059 const vsz = v.type.size(); 2060 const tsz = type.size(); 2061 assert(vsz != SIZE_INVALID && tsz != SIZE_INVALID); 2062 return offset < v.offset + vsz && 2063 v.offset < offset + tsz; 2064 } 2065 2066 override final bool hasPointers() 2067 { 2068 //printf("VarDeclaration::hasPointers() %s, ty = %d\n", toChars(), type->ty); 2069 return (!isDataseg() && type.hasPointers()); 2070 } 2071 2072 /************************************* 2073 * Return true if we can take the address of this variable. 2074 */ 2075 final bool canTakeAddressOf() 2076 { 2077 return !(storage_class & STCmanifest); 2078 } 2079 2080 /****************************************** 2081 * Return true if variable needs to call the destructor. 2082 */ 2083 final bool needsScopeDtor() 2084 { 2085 //printf("VarDeclaration::needsScopeDtor() %s\n", toChars()); 2086 return edtor && !(storage_class & STCnodtor); 2087 } 2088 2089 /****************************************** 2090 * If a variable has a scope destructor call, return call for it. 2091 * Otherwise, return NULL. 2092 */ 2093 final Expression callScopeDtor(Scope* sc) 2094 { 2095 //printf("VarDeclaration::callScopeDtor() %s\n", toChars()); 2096 2097 // Destruction of STCfield's is handled by buildDtor() 2098 if (storage_class & (STCnodtor | STCref | STCout | STCfield)) 2099 { 2100 return null; 2101 } 2102 2103 Expression e = null; 2104 // Destructors for structs and arrays of structs 2105 Type tv = type.baseElemOf(); 2106 if (tv.ty == Tstruct) 2107 { 2108 StructDeclaration sd = (cast(TypeStruct)tv).sym; 2109 if (!sd.dtor) 2110 return null; 2111 2112 const sz = type.size(); 2113 assert(sz != SIZE_INVALID); 2114 if (!sz) 2115 return null; 2116 2117 if (type.toBasetype().ty == Tstruct) 2118 { 2119 // v.__xdtor() 2120 e = new VarExp(loc, this); 2121 2122 /* This is a hack so we can call destructors on const/immutable objects. 2123 * Need to add things like "const ~this()" and "immutable ~this()" to 2124 * fix properly. 2125 */ 2126 e.type = e.type.mutableOf(); 2127 2128 e = new DotVarExp(loc, e, sd.dtor, false); 2129 e = new CallExp(loc, e); 2130 } 2131 else 2132 { 2133 // _ArrayDtor(v[0 .. n]) 2134 e = new VarExp(loc, this); 2135 2136 const sdsz = sd.type.size(); 2137 assert(sdsz != SIZE_INVALID && sdsz != 0); 2138 const n = sz / sdsz; 2139 e = new SliceExp(loc, e, new IntegerExp(loc, 0, Type.tsize_t), new IntegerExp(loc, n, Type.tsize_t)); 2140 2141 // Prevent redundant bounds check 2142 (cast(SliceExp)e).upperIsInBounds = true; 2143 (cast(SliceExp)e).lowerIsLessThanUpper = true; 2144 2145 // This is a hack so we can call destructors on const/immutable objects. 2146 e.type = sd.type.arrayOf(); 2147 2148 e = new CallExp(loc, new IdentifierExp(loc, Id._ArrayDtor), e); 2149 } 2150 return e; 2151 } 2152 // Destructors for classes 2153 if (storage_class & (STCauto | STCscope) && !(storage_class & STCparameter)) 2154 { 2155 for (ClassDeclaration cd = type.isClassHandle(); cd; cd = cd.baseClass) 2156 { 2157 /* We can do better if there's a way with onstack 2158 * classes to determine if there's no way the monitor 2159 * could be set. 2160 */ 2161 //if (cd->isInterfaceDeclaration()) 2162 // error("interface %s cannot be scope", cd->toChars()); 2163 2164 if (cd.cpp) 2165 { 2166 // Destructors are not supported on extern(C++) classes 2167 break; 2168 } 2169 if (mynew || onstack || cd.dtors.dim) // if any destructors 2170 { 2171 // delete this; 2172 Expression ec; 2173 ec = new VarExp(loc, this); 2174 e = new DeleteExp(loc, ec); 2175 e.type = Type.tvoid; 2176 break; 2177 } 2178 } 2179 } 2180 return e; 2181 } 2182 2183 /******************************************* 2184 * If variable has a constant expression initializer, get it. 2185 * Otherwise, return null. 2186 */ 2187 final Expression getConstInitializer(bool needFullType = true) 2188 { 2189 assert(type && _init); 2190 2191 // Ungag errors when not speculative 2192 uint oldgag = global.gag; 2193 if (global.gag) 2194 { 2195 Dsymbol sym = toParent().isAggregateDeclaration(); 2196 if (sym && !sym.isSpeculative()) 2197 global.gag = 0; 2198 } 2199 2200 if (_scope) 2201 { 2202 inuse++; 2203 _init = _init.semantic(_scope, type, INITinterpret); 2204 _scope = null; 2205 inuse--; 2206 } 2207 2208 Expression e = _init.toExpression(needFullType ? type : null); 2209 global.gag = oldgag; 2210 return e; 2211 } 2212 2213 /******************************************* 2214 * Helper function for the expansion of manifest constant. 2215 */ 2216 final Expression expandInitializer(Loc loc) 2217 { 2218 assert((storage_class & STCmanifest) && _init); 2219 2220 auto e = getConstInitializer(); 2221 if (!e) 2222 { 2223 .error(loc, "cannot make expression out of initializer for %s", toChars()); 2224 return new ErrorExp(); 2225 } 2226 2227 e = e.copy(); 2228 e.loc = loc; // for better error message 2229 return e; 2230 } 2231 2232 override final void checkCtorConstInit() 2233 { 2234 version (none) 2235 { 2236 /* doesn't work if more than one static ctor */ 2237 if (ctorinit == 0 && isCtorinit() && !isField()) 2238 error("missing initializer in static constructor for const variable"); 2239 } 2240 } 2241 2242 /************************************ 2243 * Check to see if this variable is actually in an enclosing function 2244 * rather than the current one. 2245 * Returns true if error occurs. 2246 */ 2247 final bool checkNestedReference(Scope* sc, Loc loc) 2248 { 2249 //printf("VarDeclaration::checkNestedReference() %s\n", toChars()); 2250 if (sc.intypeof == 1 || (sc.flags & SCOPEctfe)) 2251 return false; 2252 if (!parent || parent == sc.parent) 2253 return false; 2254 if (isDataseg() || (storage_class & STCmanifest)) 2255 return false; 2256 2257 // The current function 2258 FuncDeclaration fdthis = sc.parent.isFuncDeclaration(); 2259 if (!fdthis) 2260 return false; // out of function scope 2261 2262 Dsymbol p = toParent2(); 2263 2264 // Function literals from fdthis to p must be delegates 2265 checkNestedRef(fdthis, p); 2266 2267 // The function that this variable is in 2268 FuncDeclaration fdv = p.isFuncDeclaration(); 2269 if (!fdv || fdv == fdthis) 2270 return false; 2271 2272 // Add fdthis to nestedrefs[] if not already there 2273 for (size_t i = 0; 1; i++) 2274 { 2275 if (i == nestedrefs.dim) 2276 { 2277 nestedrefs.push(fdthis); 2278 break; 2279 } 2280 if (nestedrefs[i] == fdthis) 2281 break; 2282 } 2283 2284 /* __require and __ensure will always get called directly, 2285 * so they never make outer functions closure. 2286 */ 2287 if (fdthis.ident == Id.require || fdthis.ident == Id.ensure) 2288 return false; 2289 2290 //printf("\tfdv = %s\n", fdv.toChars()); 2291 //printf("\tfdthis = %s\n", fdthis.toChars()); 2292 if (loc.filename) 2293 { 2294 int lv = fdthis.getLevel(loc, sc, fdv); 2295 if (lv == -2) // error 2296 return true; 2297 } 2298 2299 // Add this to fdv.closureVars[] if not already there 2300 for (size_t i = 0; 1; i++) 2301 { 2302 if (i == fdv.closureVars.dim) 2303 { 2304 if (!sc.intypeof && !(sc.flags & SCOPEcompile)) 2305 fdv.closureVars.push(this); 2306 break; 2307 } 2308 if (fdv.closureVars[i] == this) 2309 break; 2310 } 2311 2312 //printf("fdthis is %s\n", fdthis.toChars()); 2313 //printf("var %s in function %s is nested ref\n", toChars(), fdv.toChars()); 2314 // __dollar creates problems because it isn't a real variable Bugzilla 3326 2315 if (ident == Id.dollar) 2316 { 2317 .error(loc, "cannnot use $ inside a function literal"); 2318 return true; 2319 } 2320 if (ident == Id.withSym) // Bugzilla 1759 2321 { 2322 ExpInitializer ez = _init.isExpInitializer(); 2323 assert(ez); 2324 Expression e = ez.exp; 2325 if (e.op == TOKconstruct || e.op == TOKblit) 2326 e = (cast(AssignExp)e).e2; 2327 return lambdaCheckForNestedRef(e, sc); 2328 } 2329 2330 return false; 2331 } 2332 2333 override final Dsymbol toAlias() 2334 { 2335 //printf("VarDeclaration::toAlias('%s', this = %p, aliassym = %p)\n", toChars(), this, aliassym); 2336 if ((!type || !type.deco) && _scope) 2337 semantic(_scope); 2338 2339 assert(this != aliassym); 2340 Dsymbol s = aliassym ? aliassym.toAlias() : this; 2341 return s; 2342 } 2343 2344 // Eliminate need for dynamic_cast 2345 override final inout(VarDeclaration) isVarDeclaration() inout 2346 { 2347 return this; 2348 } 2349 2350 override void accept(Visitor v) 2351 { 2352 v.visit(this); 2353 } 2354 } 2355 2356 /*********************************************************** 2357 * This is a shell around a back end symbol 2358 */ 2359 extern (C++) final class SymbolDeclaration : Declaration 2360 { 2361 StructDeclaration dsym; 2362 2363 extern (D) this(Loc loc, StructDeclaration dsym) 2364 { 2365 super(dsym.ident); 2366 this.loc = loc; 2367 this.dsym = dsym; 2368 storage_class |= STCconst; 2369 } 2370 2371 // Eliminate need for dynamic_cast 2372 override inout(SymbolDeclaration) isSymbolDeclaration() inout 2373 { 2374 return this; 2375 } 2376 2377 override void accept(Visitor v) 2378 { 2379 v.visit(this); 2380 } 2381 } 2382 2383 /*********************************************************** 2384 */ 2385 extern (C++) class TypeInfoDeclaration : VarDeclaration 2386 { 2387 Type tinfo; 2388 2389 final extern (D) this(Type tinfo) 2390 { 2391 super(Loc(), Type.dtypeinfo.type, tinfo.getTypeInfoIdent(), null); 2392 this.tinfo = tinfo; 2393 storage_class = STCstatic | STCgshared; 2394 protection = Prot(PROTpublic); 2395 linkage = LINKc; 2396 } 2397 2398 static TypeInfoDeclaration create(Type tinfo) 2399 { 2400 return new TypeInfoDeclaration(tinfo); 2401 } 2402 2403 override final Dsymbol syntaxCopy(Dsymbol s) 2404 { 2405 assert(0); // should never be produced by syntax 2406 } 2407 2408 override final void semantic(Scope* sc) 2409 { 2410 assert(linkage == LINKc); 2411 } 2412 2413 override final const(char)* toChars() 2414 { 2415 //printf("TypeInfoDeclaration::toChars() tinfo = %s\n", tinfo->toChars()); 2416 OutBuffer buf; 2417 buf.writestring("typeid("); 2418 buf.writestring(tinfo.toChars()); 2419 buf.writeByte(')'); 2420 return buf.extractString(); 2421 } 2422 2423 override final inout(TypeInfoDeclaration) isTypeInfoDeclaration() inout 2424 { 2425 return this; 2426 } 2427 2428 override void accept(Visitor v) 2429 { 2430 v.visit(this); 2431 } 2432 } 2433 2434 /*********************************************************** 2435 */ 2436 extern (C++) final class TypeInfoStructDeclaration : TypeInfoDeclaration 2437 { 2438 extern (D) this(Type tinfo) 2439 { 2440 super(tinfo); 2441 if (!Type.typeinfostruct) 2442 { 2443 ObjectNotFound(Id.TypeInfo_Struct); 2444 } 2445 type = Type.typeinfostruct.type; 2446 } 2447 2448 static TypeInfoStructDeclaration create(Type tinfo) 2449 { 2450 return new TypeInfoStructDeclaration(tinfo); 2451 } 2452 2453 override void accept(Visitor v) 2454 { 2455 v.visit(this); 2456 } 2457 } 2458 2459 /*********************************************************** 2460 */ 2461 extern (C++) final class TypeInfoClassDeclaration : TypeInfoDeclaration 2462 { 2463 extern (D) this(Type tinfo) 2464 { 2465 super(tinfo); 2466 if (!Type.typeinfoclass) 2467 { 2468 ObjectNotFound(Id.TypeInfo_Class); 2469 } 2470 type = Type.typeinfoclass.type; 2471 } 2472 2473 static TypeInfoClassDeclaration create(Type tinfo) 2474 { 2475 return new TypeInfoClassDeclaration(tinfo); 2476 } 2477 2478 override void accept(Visitor v) 2479 { 2480 v.visit(this); 2481 } 2482 } 2483 2484 /*********************************************************** 2485 */ 2486 extern (C++) final class TypeInfoInterfaceDeclaration : TypeInfoDeclaration 2487 { 2488 extern (D) this(Type tinfo) 2489 { 2490 super(tinfo); 2491 if (!Type.typeinfointerface) 2492 { 2493 ObjectNotFound(Id.TypeInfo_Interface); 2494 } 2495 type = Type.typeinfointerface.type; 2496 } 2497 2498 static TypeInfoInterfaceDeclaration create(Type tinfo) 2499 { 2500 return new TypeInfoInterfaceDeclaration(tinfo); 2501 } 2502 2503 override void accept(Visitor v) 2504 { 2505 v.visit(this); 2506 } 2507 } 2508 2509 /*********************************************************** 2510 */ 2511 extern (C++) final class TypeInfoPointerDeclaration : TypeInfoDeclaration 2512 { 2513 extern (D) this(Type tinfo) 2514 { 2515 super(tinfo); 2516 if (!Type.typeinfopointer) 2517 { 2518 ObjectNotFound(Id.TypeInfo_Pointer); 2519 } 2520 type = Type.typeinfopointer.type; 2521 } 2522 2523 static TypeInfoPointerDeclaration create(Type tinfo) 2524 { 2525 return new TypeInfoPointerDeclaration(tinfo); 2526 } 2527 2528 override void accept(Visitor v) 2529 { 2530 v.visit(this); 2531 } 2532 } 2533 2534 /*********************************************************** 2535 */ 2536 extern (C++) final class TypeInfoArrayDeclaration : TypeInfoDeclaration 2537 { 2538 extern (D) this(Type tinfo) 2539 { 2540 super(tinfo); 2541 if (!Type.typeinfoarray) 2542 { 2543 ObjectNotFound(Id.TypeInfo_Array); 2544 } 2545 type = Type.typeinfoarray.type; 2546 } 2547 2548 static TypeInfoArrayDeclaration create(Type tinfo) 2549 { 2550 return new TypeInfoArrayDeclaration(tinfo); 2551 } 2552 2553 override void accept(Visitor v) 2554 { 2555 v.visit(this); 2556 } 2557 } 2558 2559 /*********************************************************** 2560 */ 2561 extern (C++) final class TypeInfoStaticArrayDeclaration : TypeInfoDeclaration 2562 { 2563 extern (D) this(Type tinfo) 2564 { 2565 super(tinfo); 2566 if (!Type.typeinfostaticarray) 2567 { 2568 ObjectNotFound(Id.TypeInfo_StaticArray); 2569 } 2570 type = Type.typeinfostaticarray.type; 2571 } 2572 2573 static TypeInfoStaticArrayDeclaration create(Type tinfo) 2574 { 2575 return new TypeInfoStaticArrayDeclaration(tinfo); 2576 } 2577 2578 override void accept(Visitor v) 2579 { 2580 v.visit(this); 2581 } 2582 } 2583 2584 /*********************************************************** 2585 */ 2586 extern (C++) final class TypeInfoAssociativeArrayDeclaration : TypeInfoDeclaration 2587 { 2588 extern (D) this(Type tinfo) 2589 { 2590 super(tinfo); 2591 if (!Type.typeinfoassociativearray) 2592 { 2593 ObjectNotFound(Id.TypeInfo_AssociativeArray); 2594 } 2595 type = Type.typeinfoassociativearray.type; 2596 } 2597 2598 static TypeInfoAssociativeArrayDeclaration create(Type tinfo) 2599 { 2600 return new TypeInfoAssociativeArrayDeclaration(tinfo); 2601 } 2602 2603 override void accept(Visitor v) 2604 { 2605 v.visit(this); 2606 } 2607 } 2608 2609 /*********************************************************** 2610 */ 2611 extern (C++) final class TypeInfoEnumDeclaration : TypeInfoDeclaration 2612 { 2613 extern (D) this(Type tinfo) 2614 { 2615 super(tinfo); 2616 if (!Type.typeinfoenum) 2617 { 2618 ObjectNotFound(Id.TypeInfo_Enum); 2619 } 2620 type = Type.typeinfoenum.type; 2621 } 2622 2623 static TypeInfoEnumDeclaration create(Type tinfo) 2624 { 2625 return new TypeInfoEnumDeclaration(tinfo); 2626 } 2627 2628 override void accept(Visitor v) 2629 { 2630 v.visit(this); 2631 } 2632 } 2633 2634 /*********************************************************** 2635 */ 2636 extern (C++) final class TypeInfoFunctionDeclaration : TypeInfoDeclaration 2637 { 2638 extern (D) this(Type tinfo) 2639 { 2640 super(tinfo); 2641 if (!Type.typeinfofunction) 2642 { 2643 ObjectNotFound(Id.TypeInfo_Function); 2644 } 2645 type = Type.typeinfofunction.type; 2646 } 2647 2648 static TypeInfoFunctionDeclaration create(Type tinfo) 2649 { 2650 return new TypeInfoFunctionDeclaration(tinfo); 2651 } 2652 2653 override void accept(Visitor v) 2654 { 2655 v.visit(this); 2656 } 2657 } 2658 2659 /*********************************************************** 2660 */ 2661 extern (C++) final class TypeInfoDelegateDeclaration : TypeInfoDeclaration 2662 { 2663 extern (D) this(Type tinfo) 2664 { 2665 super(tinfo); 2666 if (!Type.typeinfodelegate) 2667 { 2668 ObjectNotFound(Id.TypeInfo_Delegate); 2669 } 2670 type = Type.typeinfodelegate.type; 2671 } 2672 2673 static TypeInfoDelegateDeclaration create(Type tinfo) 2674 { 2675 return new TypeInfoDelegateDeclaration(tinfo); 2676 } 2677 2678 override void accept(Visitor v) 2679 { 2680 v.visit(this); 2681 } 2682 } 2683 2684 /*********************************************************** 2685 */ 2686 extern (C++) final class TypeInfoTupleDeclaration : TypeInfoDeclaration 2687 { 2688 extern (D) this(Type tinfo) 2689 { 2690 super(tinfo); 2691 if (!Type.typeinfotypelist) 2692 { 2693 ObjectNotFound(Id.TypeInfo_Tuple); 2694 } 2695 type = Type.typeinfotypelist.type; 2696 } 2697 2698 static TypeInfoTupleDeclaration create(Type tinfo) 2699 { 2700 return new TypeInfoTupleDeclaration(tinfo); 2701 } 2702 2703 override void accept(Visitor v) 2704 { 2705 v.visit(this); 2706 } 2707 } 2708 2709 /*********************************************************** 2710 */ 2711 extern (C++) final class TypeInfoConstDeclaration : TypeInfoDeclaration 2712 { 2713 extern (D) this(Type tinfo) 2714 { 2715 super(tinfo); 2716 if (!Type.typeinfoconst) 2717 { 2718 ObjectNotFound(Id.TypeInfo_Const); 2719 } 2720 type = Type.typeinfoconst.type; 2721 } 2722 2723 static TypeInfoConstDeclaration create(Type tinfo) 2724 { 2725 return new TypeInfoConstDeclaration(tinfo); 2726 } 2727 2728 override void accept(Visitor v) 2729 { 2730 v.visit(this); 2731 } 2732 } 2733 2734 /*********************************************************** 2735 */ 2736 extern (C++) final class TypeInfoInvariantDeclaration : TypeInfoDeclaration 2737 { 2738 extern (D) this(Type tinfo) 2739 { 2740 super(tinfo); 2741 if (!Type.typeinfoinvariant) 2742 { 2743 ObjectNotFound(Id.TypeInfo_Invariant); 2744 } 2745 type = Type.typeinfoinvariant.type; 2746 } 2747 2748 static TypeInfoInvariantDeclaration create(Type tinfo) 2749 { 2750 return new TypeInfoInvariantDeclaration(tinfo); 2751 } 2752 2753 override void accept(Visitor v) 2754 { 2755 v.visit(this); 2756 } 2757 } 2758 2759 /*********************************************************** 2760 */ 2761 extern (C++) final class TypeInfoSharedDeclaration : TypeInfoDeclaration 2762 { 2763 extern (D) this(Type tinfo) 2764 { 2765 super(tinfo); 2766 if (!Type.typeinfoshared) 2767 { 2768 ObjectNotFound(Id.TypeInfo_Shared); 2769 } 2770 type = Type.typeinfoshared.type; 2771 } 2772 2773 static TypeInfoSharedDeclaration create(Type tinfo) 2774 { 2775 return new TypeInfoSharedDeclaration(tinfo); 2776 } 2777 2778 override void accept(Visitor v) 2779 { 2780 v.visit(this); 2781 } 2782 } 2783 2784 /*********************************************************** 2785 */ 2786 extern (C++) final class TypeInfoWildDeclaration : TypeInfoDeclaration 2787 { 2788 extern (D) this(Type tinfo) 2789 { 2790 super(tinfo); 2791 if (!Type.typeinfowild) 2792 { 2793 ObjectNotFound(Id.TypeInfo_Wild); 2794 } 2795 type = Type.typeinfowild.type; 2796 } 2797 2798 static TypeInfoWildDeclaration create(Type tinfo) 2799 { 2800 return new TypeInfoWildDeclaration(tinfo); 2801 } 2802 2803 override void accept(Visitor v) 2804 { 2805 v.visit(this); 2806 } 2807 } 2808 2809 /*********************************************************** 2810 */ 2811 extern (C++) final class TypeInfoVectorDeclaration : TypeInfoDeclaration 2812 { 2813 extern (D) this(Type tinfo) 2814 { 2815 super(tinfo); 2816 if (!Type.typeinfovector) 2817 { 2818 ObjectNotFound(Id.TypeInfo_Vector); 2819 } 2820 type = Type.typeinfovector.type; 2821 } 2822 2823 static TypeInfoVectorDeclaration create(Type tinfo) 2824 { 2825 return new TypeInfoVectorDeclaration(tinfo); 2826 } 2827 2828 override void accept(Visitor v) 2829 { 2830 v.visit(this); 2831 } 2832 } 2833 2834 /*********************************************************** 2835 * For the "this" parameter to member functions 2836 */ 2837 extern (C++) final class ThisDeclaration : VarDeclaration 2838 { 2839 extern (D) this(Loc loc, Type t) 2840 { 2841 super(loc, t, Id.This, null); 2842 storage_class |= STCnodtor; 2843 } 2844 2845 override Dsymbol syntaxCopy(Dsymbol s) 2846 { 2847 assert(0); // should never be produced by syntax 2848 } 2849 2850 override inout(ThisDeclaration) isThisDeclaration() inout 2851 { 2852 return this; 2853 } 2854 2855 override void accept(Visitor v) 2856 { 2857 v.visit(this); 2858 } 2859 }